Doxygen
Loading...
Searching...
No Matches
pre.l File Reference
#include <stdint.h>
#include "doxygen.h"
#include <stack>
#include <deque>
#include <algorithm>
#include <utility>
#include <mutex>
#include <thread>
#include <cstdio>
#include <cassert>
#include <cctype>
#include <cerrno>
#include "qcstring.h"
#include "containers.h"
#include "pre.h"
#include "constexp.h"
#include "define.h"
#include "message.h"
#include "util.h"
#include "defargs.h"
#include "debug.h"
#include "portable.h"
#include "arguments.h"
#include "entry.h"
#include "condparser.h"
#include "config.h"
#include "filedef.h"
#include "regex.h"
#include "fileinfo.h"
#include "trace.h"
#include "stringutil.h"
#include "doxygen_lex.h"
#include "pre.l.h"
Include dependency graph for pre.l:

Go to the source code of this file.

Classes

struct  preYY_CondCtx
struct  FileState
struct  PreIncludeInfo
class  DefineManager
 Class that manages the defines available while preprocessing files. More...
class  DefineManager::DefinesPerFile
 Local class used to hold the defines for a single file. More...
struct  preYY_state
struct  Preprocessor::Private

Macros

#define YY_TYPEDEF_YY_SCANNER_T
#define YY_NO_UNISTD_H   1
#define YY_INPUT(buf, result, max_size)
#define MAX_EXPANSION_DEPTH   50

Typedefs

typedef yyguts_t * yyscan_t
typedef std::map< std::string, DefineDefineMap
 A dictionary of managed Define objects.

Functions

static const char * stateToString (int state)
static QCString escapeAt (const QCString &text)
static QCString extractTrailingComment (const QCString &s)
static char resolveTrigraph (char c)
static void outputArray (yyscan_t yyscanner, const char *a, yy_size_t len)
static void outputString (yyscan_t yyscanner, const QCString &s)
static void outputChar (yyscan_t yyscanner, char c)
static void outputSpaces (yyscan_t yyscanner, char *s)
static void outputSpace (yyscan_t yyscanner, char c)
static void extraSpacing (yyscan_t yyscanner)
static QCString expandMacro (yyscan_t yyscanner, const QCString &name)
static void readIncludeFile (yyscan_t yyscanner, const QCString &inc)
static void incrLevel (yyscan_t yyscanner)
static void decrLevel (yyscan_t yyscanner)
static void setCaseDone (yyscan_t yyscanner, bool value)
static bool otherCaseDone (yyscan_t yyscanner)
static bool computeExpression (yyscan_t yyscanner, const QCString &expr)
static void startCondSection (yyscan_t yyscanner, const QCString &sectId)
static void endCondSection (yyscan_t yyscanner)
static void addMacroDefinition (yyscan_t yyscanner)
static void addDefine (yyscan_t yyscanner)
static void setFileName (yyscan_t yyscanner, const QCString &name)
static int yyread (yyscan_t yyscanner, char *buf, int max_size)
static DefineisDefined (yyscan_t yyscanner, const QCString &name)
 Returns a reference to a Define object given its name or 0 if the Define does not exist.
static void determineBlockName (yyscan_t yyscanner)
static yy_size_t getFenceSize (char *txt, yy_size_t leng)
static const char * getLexerFILE ()
int yylex (yyscan_t yyscanner)
static std::unique_ptr< FileStatecheckAndOpenFile (yyscan_t yyscanner, const QCString &fileName, bool &alreadyProcessed)
static std::unique_ptr< FileStatefindFile (yyscan_t yyscanner, const QCString &fileName, bool localInclude, bool &alreadyProcessed)
static int getNextChar (yyscan_t yyscanner, const QCString &expr, QCString *rest, uint32_t &pos)
static int getCurrentChar (yyscan_t yyscanner, const QCString &expr, QCString *rest, uint32_t pos)
static void unputChar (yyscan_t yyscanner, const QCString &expr, QCString *rest, uint32_t &pos, char c)
static bool expandExpression (yyscan_t yyscanner, QCString &expr, QCString *rest, int pos, int level)
static QCString stringize (const QCString &s)
static void processConcatOperators (QCString &expr)
static void returnCharToStream (yyscan_t yyscanner, char c)
static void addTillEndOfString (yyscan_t yyscanner, const QCString &expr, QCString *rest, uint32_t &pos, char term, QCString &arg)
static void skipCommentMacroName (yyscan_t yyscanner, const QCString &expr, QCString *rest, int &cc, uint32_t &j, int &len)
static QCString expandVAOpt (const QCString &vaStr, bool hasOptionalArgs)
static bool replaceFunctionMacro (yyscan_t yyscanner, const QCString &expr, QCString *rest, int pos, int &len, const Define *def, QCString &result, int level)
static int getNextId (const QCString &expr, int p, int *l)
static void addSeparatorsIfNeeded (yyscan_t yyscanner, const QCString &expr, QCString &resultExpr, QCString &restExpr, int pos)
static const char * processUntilMatchingTerminator (const char *inputStr, QCString &result)
 Process string or character literal.
static QCString removeIdsAndMarkers (const QCString &s)
static QCString removeMarkers (const QCString &s)
static void forceEndCondSection (yyscan_t yyscanner)
static void initPredefined (yyscan_t yyscanner, const QCString &fileName)

Variables

static std::mutex g_debugMutex
static std::mutex g_globalDefineMutex
static std::mutex g_updateGlobals
static DefineManager g_defineManager

Macro Definition Documentation

◆ MAX_EXPANSION_DEPTH

#define MAX_EXPANSION_DEPTH   50

Definition at line 3013 of file pre.l.

Referenced by expandExpression().

◆ YY_INPUT

#define YY_INPUT ( buf,
result,
max_size )
Value:
result=yyread(yyscanner,buf,max_size);
static int yyread(yyscan_t yyscanner, char *buf, int max_size)
Definition code.l:3971

Definition at line 349 of file pre.l.

◆ YY_NO_UNISTD_H

#define YY_NO_UNISTD_H   1

Definition at line 68 of file pre.l.

◆ YY_TYPEDEF_YY_SCANNER_T

#define YY_TYPEDEF_YY_SCANNER_T

Definition at line 22 of file pre.l.

Typedef Documentation

◆ DefineMap

typedef std::map< std::string, Define > DefineMap

A dictionary of managed Define objects.

Definition at line 109 of file pre.l.

◆ yyscan_t

typedef yyguts_t* yyscan_t

Definition at line 24 of file pre.l.

Function Documentation

◆ addDefine()

void addDefine ( yyscan_t yyscanner)
static

Definition at line 3526 of file pre.l.

3527{
3528 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
3529 Define def;
3530 def.name = state->defName;
3531 def.definition = state->defText.stripWhiteSpace();
3532 def.nargs = state->defArgs;
3533 def.fileName = state->fileName;
3534 def.fileDef = state->yyFileDef;
3535 def.lineNr = state->yyLineNr-state->yyMLines;
3536 def.columnNr = state->yyColNr;
3537 def.varArgs = state->defVarArgs;
3538 //printf("newDefine: %s %s file: %s\n",qPrint(def.name),qPrint(def.definition),
3539 // def.fileDef ? qPrint(def.fileDef->name()) : qPrint(def.fileName));
3540 //printf("newDefine: '%s'->'%s'\n",qPrint(def.name),qPrint(def.definition));
3541 if (!def.name.isEmpty() &&
3543 {
3544 def.isPredefined=TRUE;
3546 }
3547 auto it = state->localDefines.find(def.name.str());
3548 if (it!=state->localDefines.end()) // redefine
3549 {
3550 state->localDefines.erase(it);
3551 }
3552 state->localDefines.emplace(def.name.str(),def);
A class representing a macro definition.
Definition define.h:31
int lineNr
Definition define.h:38
bool varArgs
Definition define.h:42
QCString fileName
Definition define.h:35
QCString name
Definition define.h:33
FileDef * fileDef
Definition define.h:37
bool isPredefined
Definition define.h:43
int columnNr
Definition define.h:39
QCString definition
Definition define.h:34
int nargs
Definition define.h:40
bool expandAsDefined
Definition define.h:45
static StringUnorderedSet expandAsDefinedSet
Definition doxygen.h:118
bool isEmpty() const
Returns TRUE iff the string is empty.
Definition qcstring.h:163
QCString stripWhiteSpace() const
returns a copy of this string with leading and trailing whitespace removed
Definition qcstring.h:260
const std::string & str() const
Definition qcstring.h:552
#define TRUE
Definition qcstring.h:37
3553}

References Define::columnNr, Define::definition, Define::expandAsDefined, Doxygen::expandAsDefinedSet, Define::fileDef, Define::fileName, QCString::isEmpty(), Define::isPredefined, Define::lineNr, Define::name, Define::nargs, QCString::str(), QCString::stripWhiteSpace(), TRUE, and Define::varArgs.

◆ addMacroDefinition()

void addMacroDefinition ( yyscan_t yyscanner)
static

Definition at line 3555 of file pre.l.

3556{
3557 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
3558 if (state->skip) return; // do not add this define as it is inside a
3559 // conditional section (cond command) that is disabled.
3560
3561 Define define;
3562 define.fileName = state->fileName;
3563 define.lineNr = state->yyLineNr - state->yyMLines;
3564 define.columnNr = state->yyColNr;
3565 define.name = state->defName;
3566 define.args = state->defArgsStr;
3567 define.fileDef = state->inputFileDef;
QCString args
Definition define.h:36
3568
3569 QCString litText = state->defLitText;
3570 int l=litText.find('\n');
3571 if (l>0 && litText.left(l).stripWhiteSpace()=="\\")
3572 {
3573 // strip first line if it only contains a slash
3574 litText = litText.right(litText.length()-l-1);
3575 }
3576 else if (l>0)
3577 {
3578 // align the items on the first line with the items on the second line
3579 int k=l+1;
3580 const char *p=litText.data()+k;
3581 char c = 0;
3582 while ((c=*p++) && (c==' ' || c=='\t')) k++;
3583 litText=litText.mid(l+1,k-l-1)+litText.stripWhiteSpace();
3584 }
3585 QCString litTextStripped = state->defLitText.stripWhiteSpace();
3586 if (litTextStripped.contains('\n')>=1)
3587 {
3588 define.definition = litText;
3589 }
3590 else
3591 {
3592 define.definition = litTextStripped;
3593 }
3594 {
3595 state->macroDefinitions.push_back(define);
3596 }
This is an alternative implementation of QCString.
Definition qcstring.h:101
int find(char c, int index=0, bool cs=TRUE) const
Definition qcstring.cpp:43
size_t length() const
Returns the length of the string, not counting the 0-terminator.
Definition qcstring.h:166
QCString mid(size_t index, size_t len=static_cast< size_t >(-1)) const
Definition qcstring.h:241
QCString right(size_t len) const
Definition qcstring.h:234
const char * data() const
Returns a pointer to the contents of the string in the form of a 0-terminated C string.
Definition qcstring.h:172
QCString left(size_t len) const
Definition qcstring.h:229
int contains(char c, bool cs=TRUE) const
Definition qcstring.cpp:148
3597}

References Define::args, Define::columnNr, QCString::contains(), QCString::data(), Define::definition, Define::fileDef, Define::fileName, QCString::find(), QCString::left(), QCString::length(), Define::lineNr, QCString::mid(), Define::name, QCString::right(), and QCString::stripWhiteSpace().

◆ addSeparatorsIfNeeded()

void addSeparatorsIfNeeded ( yyscan_t yyscanner,
const QCString & expr,
QCString & resultExpr,
QCString & restExpr,
int pos )
static

Definition at line 3015 of file pre.l.

3016{
3017 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
3018 if (!state->nospaces)
3019 {
3020 // peek back in the stream, for a colon character
3021 char ccPrev = pos==0 || (int)expr.length()<pos ? state->prevChar : expr.at(pos-1);
3022 QCString leftSpace = ccPrev!=':' && ccPrev!=' ' ? " " : "";
3023 int ccNext = 0;
3024 restExpr=restExpr.stripWhiteSpace();
3025 if (restExpr.isEmpty()) // peek ahead in the stream for non-whitespace
3026 {
3027 uint32_t j=(uint32_t)resultExpr.length();
3028 while ((ccNext=getNextChar(yyscanner,resultExpr,nullptr,j))!=EOF && ccNext==' ') { }
3029 if (ccNext != EOF) unputChar(yyscanner,resultExpr,nullptr,j,(char)ccNext);
3030 }
3031 else // take first char from remainder
3032 {
3033 ccNext=restExpr.at(0);
3034 }
3035 // don't add whitespace before a colon
3036 QCString rightSpace = ccNext!=':' && ccNext!=' ' ? " " : "";
3037 //printf("ccPrev='%c' ccNext='%c' p=%d expr=%zu restExpr='%s' left='%s' right='%s'\n",
3038 // ccPrev,ccNext,pos,expr.length(),qPrint(restExpr),qPrint(leftSpace),qPrint(rightSpace));
3039 resultExpr=leftSpace+resultExpr+rightSpace;
3040 }
char & at(size_t i)
Returns a reference to the character at index i.
Definition qcstring.h:593
static int getNextChar(yyscan_t yyscanner, const QCString &expr, QCString *rest, uint32_t &pos)
Definition pre.l:3909
static void unputChar(yyscan_t yyscanner, const QCString &expr, QCString *rest, uint32_t &pos, char c)
Definition pre.l:3955
3041}

References QCString::at(), getNextChar(), QCString::isEmpty(), QCString::length(), QCString::stripWhiteSpace(), and unputChar().

Referenced by expandExpression().

◆ addTillEndOfString()

void addTillEndOfString ( yyscan_t yyscanner,
const QCString & expr,
QCString * rest,
uint32_t & pos,
char term,
QCString & arg )
inlinestatic

Definition at line 2598 of file pre.l.

2600{
2601 int cc;
2602 while ((cc=getNextChar(yyscanner,expr,rest,pos))!=EOF && cc!=0)
2603 {
2604 if (cc=='\\')
2605 {
2606 arg+=(char)cc;
2607 cc=getNextChar(yyscanner,expr,rest,pos);
2608 }
2609 else if (cc==term)
2610 {
2611 return;
2612 }
2613 arg+=(char)cc;
2614 }
#define term(fmt,...)
Definition message.h:137
2615}

References getNextChar(), and term.

Referenced by replaceFunctionMacro().

◆ checkAndOpenFile()

std::unique_ptr< FileState > checkAndOpenFile ( yyscan_t yyscanner,
const QCString & fileName,
bool & alreadyProcessed )
static

Definition at line 2286 of file pre.l.

2287{
2288 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
2289 alreadyProcessed = FALSE;
2290 std::unique_ptr<FileState> fs;
2291 //printf("checkAndOpenFile(%s)\n",qPrint(fileName));
2292 FileInfo fi(fileName.str());
2293 if (fi.exists() && fi.isFile())
2294 {
2295 const StringVector &exclPatterns = Config_getList(EXCLUDE_PATTERNS);
2296 if (patternMatch(fi,exclPatterns)) return nullptr;
Minimal replacement for QFileInfo.
Definition fileinfo.h:23
#define Config_getList(name)
Definition config.h:38
std::vector< std::string > StringVector
Definition containers.h:33
#define FALSE
Definition qcstring.h:34
bool patternMatch(const FileInfo &fi, const StringVector &patList)
Definition util.cpp:5640
2297
2298 QCString absName = fi.absFilePath();
2299
2300 // global guard
2301 if (state->curlyCount==0) // not #include inside { ... }
2302 {
2303 std::lock_guard<std::mutex> lock(g_globalDefineMutex);
2304 if (g_defineManager.alreadyProcessed(absName.str()))
2305 {
2306 alreadyProcessed = TRUE;
2307 //printf(" already included 1\n");
2308 return 0; // already done
2309 }
2310 }
2311 // check include stack for absName
static std::mutex g_globalDefineMutex
Definition pre.l:234
static DefineManager g_defineManager
Definition pre.l:236
2312
2313 alreadyProcessed = std::any_of(
2314 state->includeStack.begin(),
2315 state->includeStack.end(),
2316 [absName](const std::unique_ptr<FileState> &lfs)
2317 { return lfs->fileName==absName; }
2318 );
2319
2320 if (alreadyProcessed)
2321 {
2322 //printf(" already included 2\n");
2323 return nullptr;
2324 }
2325 //printf("#include %s\n",qPrint(absName));
2326
2327 fs = std::make_unique<FileState>();
2328 if (!readInputFile(absName,fs->fileBuf))
2329 { // error
2330 //printf(" error reading\n");
2331 fs.reset();
2332 }
2333 else
2334 {
2335 addTerminalCharIfMissing(fs->fileBuf,'\n');
2336 fs->oldFileBuf = state->inputBuf;
2337 fs->oldFileBufPos = state->inputBufPos;
2338 }
2339 }
2340 return fs;
void addTerminalCharIfMissing(std::string &s, char c)
Definition stringutil.h:84
bool readInputFile(const QCString &fileName, std::string &contents, bool filter, bool isSourceCode)
read a file name fileName and optionally filter and transcode it
Definition util.cpp:5486
2341}

References FileInfo::absFilePath(), addTerminalCharIfMissing(), Config_getList, FileInfo::exists(), FALSE, g_defineManager, g_globalDefineMutex, FileInfo::isFile(), patternMatch(), readInputFile(), QCString::str(), and TRUE.

Referenced by findFile().

◆ computeExpression()

bool computeExpression ( yyscan_t yyscanner,
const QCString & expr )
static

compute the value of the expression in string expr. If needed the function may read additional characters from the input.

Definition at line 3493 of file pre.l.

3494{
3495 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
3496 QCString e=expr;
3497 QCString ee=expr;
3498 ee = removeMarkers(ee);
3499 state->expanded.clear();
3500 expandExpression(yyscanner,e,nullptr,0,0);
3501 //printf("after expansion '%s'\n",qPrint(e));
3502 e = removeIdsAndMarkers(e);
3503 if (e.isEmpty()) return FALSE;
3504 //printf("parsing '%s'\n",qPrint(e));
3505 return state->constExpParser.parse(state->fileName.data(),state->yyLineNr,e.str(),ee.str());
static bool expandExpression(yyscan_t yyscanner, QCString &expr, QCString *rest, int pos, int level)
Definition pre.l:3047
static QCString removeIdsAndMarkers(const QCString &s)
Definition pre.l:3227
static QCString removeMarkers(const QCString &s)
Definition pre.l:3422
3506}

References expandExpression(), FALSE, QCString::isEmpty(), removeIdsAndMarkers(), removeMarkers(), and QCString::str().

◆ decrLevel()

void decrLevel ( yyscan_t yyscanner)
static

Definition at line 2251 of file pre.l.

2252{
2253 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
2254 //printf("%s line %d: decrLevel %d\n",qPrint(state->fileName),state->yyLineNr,state->levelGuard.size());
2255 if (!state->levelGuard.empty())
2256 {
2257 state->levelGuard.pop();
2258 }
2259 else
2260 {
2261 warn(state->fileName,state->yyLineNr,"More #endif's than #if's found.");
2262 }
#define warn(file, line, fmt,...)
Definition message.h:97
2263}

References warn.

Referenced by Markdown::Private::writeBlockQuote().

◆ determineBlockName()

void determineBlockName ( yyscan_t yyscanner)
static

Definition at line 3647 of file pre.l.

3648{
3649 struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
3650 yyextra->fenceSize=0;
3651 char c=0;
3652 if (yytext[1]=='f' && ((c=yytext[2])=='[' || c=='{' || c=='(' || c=='$'))
3653 {
3654 switch (c)
3655 {
3656 case '[': yyextra->blockName="]"; break;
3657 case '{': yyextra->blockName="}"; break;
3658 case '(': yyextra->blockName=")"; break;
3659 case '$': yyextra->blockName="$"; break;
3660 default: break;
3661 }
3662 yyextra->blockName=yyextra->blockName.stripWhiteSpace();
3663 }
3664 else
3665 {
3666 QCString bn=QCString(&yytext[1]).stripWhiteSpace();
3667 if (bn=="startuml")
3668 {
3669 yyextra->blockName="uml";
3670 }
3671 else
3672 {
3673 int i = bn.find('{'); // for \code{.c}
3674 if (i!=-1) bn=bn.left(i).stripWhiteSpace();
3675 yyextra->blockName=bn;
3676 }
3677 }
3678}

References QCString::find(), QCString::left(), and QCString::stripWhiteSpace().

◆ endCondSection()

void endCondSection ( yyscan_t yyscanner)
static

Definition at line 3847 of file pre.l.

3848{
3849 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
3850 if (state->condStack.empty())
3851 {
3852 warn(state->fileName,state->yyLineNr,"the \\endcond does not have a corresponding \\cond in this file");
3853 state->skip=FALSE;
3854 }
3855 else
3856 {
3857 const std::unique_ptr<preYY_CondCtx> &ctx = state->condStack.top();
3858 state->skip=ctx->skip;
3859 state->condStack.pop();
3860 }
3861 //printf("endCondSection: skip=%d stack=%d\n",state->skip,state->condStack.count());
3862}

References FALSE, and warn.

◆ escapeAt()

QCString escapeAt ( const QCString & text)
static

Definition at line 3874 of file pre.l.

3875{
3876 QCString result;
3877 if (!text.isEmpty())
3878 {
3879 char c = 0;
3880 const char *p=text.data();
3881 while ((c=*p++))
3882 {
3883 if (c=='@') result+="@@"; else result+=c;
3884 }
3885 }
3886 return result;
3887}

References QCString::data(), and QCString::isEmpty().

◆ expandExpression()

bool expandExpression ( yyscan_t yyscanner,
QCString & expr,
QCString * rest,
int pos,
int level )
static

performs recursive macro expansion on the string expr starting at position pos. May read additional characters from the input while re-scanning!

Definition at line 3047 of file pre.l.

3048{
3049 struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
3050 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
3051 //printf(">expandExpression(expr='%s',rest='%s',pos=%d,level=%d)\n",qPrint(expr),rest ? qPrint(*rest) : "", pos, level);
3052 if (expr.isEmpty())
3053 {
3054 //printf("<expandExpression: empty\n");
3055 return TRUE;
3056 }
3057 if (state->expanded.find(expr.str())!=state->expanded.end() &&
3058 level>MAX_EXPANSION_DEPTH) // check for too deep recursive expansions
3059 {
3060 //printf("<expandExpression: already expanded expr='%s'\n",qPrint(expr));
3061 return FALSE;
3062 }
3063 else
3064 {
3065 state->expanded.insert(expr.str());
3066 }
3067 QCString macroName;
3068 QCString expMacro;
3069 bool definedTest=FALSE;
3070 int i=pos, l=0, p=0, len=0;
3071 int startPos = pos;
3072 int samePosCount=0;
3073 while ((p=getNextId(expr,i,&l))!=-1) // search for an macro name
3074 {
3075 bool replaced=FALSE;
3076 macroName=expr.mid(p,l);
3077 //printf(" p=%d macroName=%s\n",p,qPrint(macroName));
3078 if (p<2 || !(expr.at(p-2)=='@' && expr.at(p-1)=='-')) // no-rescan marker?
3079 {
3080 if (state->expandedDict.find(macroName.str())==state->expandedDict.end()) // expand macro
3081 {
3082 bool expanded=false;
3083 Define *def=isDefined(yyscanner,macroName);
3084 // In case EXPAND_ONLY_PREDEF is enabled prevent expansion unless the macro was explicitly
3085 // predefined
3086 if (yyextra->expandOnlyPredef && def && !def->isPredefined) def=nullptr;
3087 if (macroName=="defined")
3088 {
3089 //printf("found defined inside macro definition '%s'\n",qPrint(expr.right(expr.length()-p)));
3090 definedTest=TRUE;
3091 }
3092 else if (definedTest) // macro name was found after defined
3093 {
3094 if (def) expMacro = " 1 "; else expMacro = " 0 ";
3095 replaced=TRUE;
3096 len=l;
3097 definedTest=FALSE;
3098 }
3099 else if (def && def->nargs==-1) // simple macro
3100 {
3101 // substitute the definition of the macro
3102 expMacro=def->definition.stripWhiteSpace();
3103 //expMacro=def->definition.stripWhiteSpace();
3104 replaced=TRUE;
3105 len=l;
3106 //printf("simple macro expansion='%s'->'%s'\n",qPrint(macroName),qPrint(expMacro));
3107 }
3108 else if (def && def->nargs>=0) // function macro
3109 {
3110 //printf(" >>>> call replaceFunctionMacro expr='%s'\n",qPrint(expr));
3111 replaced=replaceFunctionMacro(yyscanner,expr,rest,p+l,len,def,expMacro,level);
3112 //printf(" <<<< call replaceFunctionMacro: replaced=%d\n",replaced);
3113 len+=l;
3114 }
#define MAX_EXPANSION_DEPTH
Definition pre.l:3013
static Define * isDefined(yyscan_t yyscanner, const QCString &name)
Returns a reference to a Define object given its name or 0 if the Define does not exist.
Definition pre.l:3979
static int getNextId(const QCString &expr, int p, int *l)
Definition pre.l:2959
static bool replaceFunctionMacro(yyscan_t yyscanner, const QCString &expr, QCString *rest, int pos, int &len, const Define *def, QCString &result, int level)
Definition pre.l:2701
3115
3116 if (replaced) // expand the macro and rescan the expression
3117 {
3118 //printf(" replacing '%s'->'%s'\n",qPrint(expr.mid(p,len)),qPrint(expMacro));
3119 QCString resultExpr=expMacro;
3120 QCString restExpr=expr.right(expr.length()-len-p);
3121 addSeparatorsIfNeeded(yyscanner,expr,resultExpr,restExpr,p);
3122 processConcatOperators(resultExpr);
3123 //printf(" macroName=%s restExpr='%s' def->nonRecursive=%d\n",qPrint(macroName),qPrint(restExpr),def ? def->nonRecursive : false);
3124 if (def && !def->nonRecursive)
3125 {
3126 state->expandedDict.emplace(toStdString(macroName),def);
3127 expanded = expandExpression(yyscanner,resultExpr,&restExpr,0,level+1);
3128 state->expandedDict.erase(toStdString(macroName));
3129 }
3130 else if (def && def->nonRecursive)
3131 {
3132 expanded = true;
3133 }
3134 if (expanded)
3135 {
3136 //printf("expanded '%s' + '%s' + '%s'\n",qPrint(expr.left(p)),qPrint(resultExpr),qPrint(restExpr));
3137 expr=expr.left(p)+resultExpr+restExpr;
3138 i=p;
3139 }
3140 else
3141 {
3142 //printf("not expanded '%s' + @- '%s'\n",qPrint(expr.left(p)),qPrint(expr.right(expr.length()-p)));
3143 expr=expr.left(p)+"@-"+expr.right(expr.length()-p);
3144 i=p+l+2;
3145 }
3146 }
3147 else // move to the next macro name
3148 {
3149 //printf(" moving to the next macro old i=%d new i=%d\n",i,p+l);
3150 i=p+l;
3151 }
3152 }
3153 else // move to the next macro name
3154 {
3155 expr=expr.left(p)+"@-"+expr.right(expr.length()-p);
3156 //printf("macro already expanded, moving to the next macro expr=%s\n",qPrint(expr));
3157 i=p+l+2;
3158 //i=p+l;
3159 }
3160 // check for too many inplace expansions without making progress
3161 if (i==startPos)
3162 {
3163 samePosCount++;
3164 }
3165 else
3166 {
3167 startPos=i;
3168 samePosCount=0;
3169 }
3170 if (samePosCount>MAX_EXPANSION_DEPTH)
3171 {
3172 break;
3173 }
3174 }
3175 else // no re-scan marker found, skip the macro name
3176 {
3177 //printf("skipping marked macro\n");
3178 i=p+l;
3179 }
3180 }
3181 //printf("<expandExpression(expr='%s',rest='%s',pos=%d,level=%d)\n",qPrint(expr),rest ? qPrint(*rest) : "", pos,level);
3182 return TRUE;
bool nonRecursive
Definition define.h:44
static void addSeparatorsIfNeeded(yyscan_t yyscanner, const QCString &expr, QCString &resultExpr, QCString &restExpr, int pos)
Definition pre.l:3015
static void processConcatOperators(QCString &expr)
Definition pre.l:2545
std::string toStdString(const QCString &s)
Definition qcstring.h:702
3183}

References addSeparatorsIfNeeded(), QCString::at(), Define::definition, expandExpression(), FALSE, getNextId(), isDefined(), QCString::isEmpty(), Define::isPredefined, QCString::left(), QCString::length(), MAX_EXPANSION_DEPTH, QCString::mid(), Define::nargs, Define::nonRecursive, processConcatOperators(), replaceFunctionMacro(), QCString::right(), QCString::str(), QCString::stripWhiteSpace(), toStdString(), and TRUE.

Referenced by computeExpression(), expandExpression(), expandMacro(), and replaceFunctionMacro().

◆ expandMacro()

QCString expandMacro ( yyscan_t yyscanner,
const QCString & name )
static

expands the macro definition in name If needed the function may read additional characters from the input

Definition at line 3512 of file pre.l.

3513{
3514 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3515 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
3516 state->prevChar = yyscanner->yytext_r > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ? *(yyscanner->yytext_r-1) : 0;
3517 QCString n=name;
3518 state->expanded.clear();
3519 expandExpression(yyscanner,n,nullptr,0,0);
3520 n=removeMarkers(n);
3521 state->prevChar=0;
3522 //printf("expandMacro '%s'->'%s'\n",qPrint(name),qPrint(n));
3523 return n;
void clear()
Definition qcstring.h:182
3524}

References QCString::clear(), expandExpression(), and removeMarkers().

◆ expandVAOpt()

QCString expandVAOpt ( const QCString & vaStr,
bool hasOptionalArgs )
static

Definition at line 2649 of file pre.l.

2650{
2651 //printf("expandVAOpt(vaStr=%s,hasOptionalArgs=%d)\n",qPrint(vaStr),hasOptionalArgs);
2652 QCString result;
2653 int vo=0, vp=0;
2654 result.clear();
2655 int vl = static_cast<int>(vaStr.length());
2656 while ((vo = vaStr.find("__VA_OPT__(",vp))!=-1)
2657 {
2658 bool hasHash = vo>0 && vaStr.at(vo-1)=='#';
2659 if (hasHash)
2660 {
2661 result+=vaStr.mid(vp,vo-vp-1); // don't copy #
2662 result+="\"";
2663 }
2664 else
2665 {
2666 result+=vaStr.mid(vp,vo-vp);
2667 }
2668 int ve=vo+11; // skip over '__VA_OPT__(' part
2669 int bc=1;
2670 while (bc>0 && ve<vl)
2671 {
2672 if (vaStr[ve]==')') bc--;
2673 else if (vaStr[ve]=='(') bc++;
2674 ve++;
2675 }
2676 // ve points to end of __VA_OPT__(....)
2677 if (bc==0 && hasOptionalArgs)
2678 {
2679 QCString voStr = vaStr.mid(vo+11,ve-vo-12);
2680 //printf("vo=%d ve=%d voStr=%s\n",vo,ve,qPrint(voStr));
2681 result+=voStr; // take 'x' from __VA_OPT__(x)
2682 }
2683 if (hasHash)
2684 {
2685 result+="\"";
2686 }
2687 vp=ve;
2688 }
2689 result+=vaStr.mid(vp);
2690 //printf("vaStr='%s'\n -> '%s'\n",qPrint(vaStr),qPrint(result));
2691 return result;
2692}

References QCString::at(), QCString::clear(), QCString::find(), QCString::length(), and QCString::mid().

Referenced by replaceFunctionMacro().

◆ extractTrailingComment()

QCString extractTrailingComment ( const QCString & s)
static

Definition at line 2417 of file pre.l.

2418{
2419 if (s.isEmpty()) return "";
2420 int i=(int)s.length()-1;
2421 while (i>=0)
2422 {
2423 char c=s[i];
2424 switch (c)
2425 {
2426 case '/':
2427 {
2428 i--;
2429 if (i>=0 && s[i]=='*') // end of a comment block
2430 {
2431 i--;
2432 while (i>0 && !(s[i-1]=='/' && s[i]=='*')) i--;
2433 if (i==0)
2434 {
2435 i++;
2436 }
2437 // only /*!< ... */ or /**< ... */ are treated as a comment for the macro name,
2438 // otherwise the comment is treated as part of the macro definition
2439 return ((s[i+1]=='*' || s[i+1]=='!') && s[i+2]=='<') ? &s[i-1] : "";
2440 }
2441 else
2442 {
2443 return "";
2444 }
2445 }
2446 break;
2447 // whitespace or line-continuation
2448 case ' ':
2449 case '\t':
2450 case '\r':
2451 case '\n':
2452 case '\\':
2453 break;
2454 default:
2455 return "";
2456 }
2457 i--;
2458 }
2459 return "";
2460}

References QCString::isEmpty(), and QCString::length().

◆ extraSpacing()

void extraSpacing ( yyscan_t yyscanner)
inlinestatic

Definition at line 3634 of file pre.l.

3635{
3636 struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
3637 if (!yyextra->defContinue) return;
3638 for (int i=0; i< (int)yyleng; i++)
3639 {
3640 if (yytext[i] == '\t')
3641 yyextra->defExtraSpacing+='\t';
3642 else
3643 yyextra->defExtraSpacing+=' ';
3644 }
3645}

◆ findFile()

std::unique_ptr< FileState > findFile ( yyscan_t yyscanner,
const QCString & fileName,
bool localInclude,
bool & alreadyProcessed )
static

Definition at line 2343 of file pre.l.

2344{
2345 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
2346 //printf("** findFile(%s,%d) state->fileName=%s\n",qPrint(fileName),localInclude,qPrint(state->fileName));
2347 if (Portable::isAbsolutePath(fileName))
2348 {
2349 auto fs = checkAndOpenFile(yyscanner,fileName,alreadyProcessed);
2350 if (fs)
2351 {
2352 setFileName(yyscanner,fileName);
2353 state->yyLineNr=1;
2354 return fs;
2355 }
2356 else if (alreadyProcessed)
2357 {
2358 return nullptr;
2359 }
2360 }
2361 if (localInclude && !state->fileName.isEmpty())
2362 {
2363 FileInfo fi(state->fileName.str());
2364 if (fi.exists())
2365 {
2366 QCString absName = QCString(fi.dirPath(TRUE))+"/"+fileName;
2367 auto fs = checkAndOpenFile(yyscanner,absName,alreadyProcessed);
2368 if (fs)
2369 {
2370 setFileName(yyscanner,absName);
2371 state->yyLineNr=1;
2372 return fs;
2373 }
2374 else if (alreadyProcessed)
2375 {
2376 return nullptr;
2377 }
2378 }
2379 }
2380 if (state->pathList.empty())
2381 {
2382 return nullptr;
2383 }
2384 for (auto path : state->pathList)
2385 {
2386 QCString absName = path+"/"+fileName;
2387 //printf(" Looking for %s in %s\n",fileName,qPrint(path));
2388 auto fs = checkAndOpenFile(yyscanner,absName,alreadyProcessed);
2389 if (fs)
2390 {
2391 setFileName(yyscanner,absName);
2392 state->yyLineNr=1;
2393 //printf(" -> found it\n");
2394 return fs;
2395 }
2396 else if (alreadyProcessed)
2397 {
2398 return nullptr;
2399 }
2400 }
2401 bool ambig = false;
2403 if (fd && !ambig) // fallback in case the file is uniquely named in the input, use that one
2404 {
2405 auto fs = checkAndOpenFile(yyscanner,fd->absFilePath(),alreadyProcessed);
2406 if (fs)
2407 {
2408 setFileName(yyscanner,fd->absFilePath());
2409 state->yyLineNr=1;
2410 //printf(" -> found it\n");
2411 return fs;
2412 }
2413 }
2414 return nullptr;
static FileNameLinkedMap * inputNameLinkedMap
Definition doxygen.h:104
A model of a file symbol.
Definition filedef.h:99
virtual QCString absFilePath() const =0
bool isAbsolutePath(const QCString &fileName)
Definition portable.cpp:498
static void setFileName(yyscan_t yyscanner, const QCString &name)
Definition pre.l:2223
static std::unique_ptr< FileState > checkAndOpenFile(yyscan_t yyscanner, const QCString &fileName, bool &alreadyProcessed)
Definition pre.l:2286
FileDef * findFileDef(const FileNameLinkedMap *fnMap, const QCString &n, bool &ambig)
Definition util.cpp:2838
2415}

References FileDef::absFilePath(), checkAndOpenFile(), FileInfo::dirPath(), FileInfo::exists(), findFileDef(), Doxygen::inputNameLinkedMap, Portable::isAbsolutePath(), setFileName(), and TRUE.

◆ forceEndCondSection()

void forceEndCondSection ( yyscan_t yyscanner)
static

Definition at line 3864 of file pre.l.

3865{
3866 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
3867 while (!state->condStack.empty())
3868 {
3869 state->condStack.pop();
3870 }
3871 state->skip=FALSE;
3872}

References FALSE.

Referenced by Preprocessor::processFile().

◆ getCurrentChar()

int getCurrentChar ( yyscan_t yyscanner,
const QCString & expr,
QCString * rest,
uint32_t pos )
static

Definition at line 3932 of file pre.l.

3933{
3934 //printf("getCurrentChar(%s,%s,%d)\n",qPrint(expr),rest ? rest->data() : 0,pos);
3935 if (pos<expr.length())
3936 {
3937 //printf("%c=expr()\n",expr.at(pos));
3938 return expr.at(pos);
3939 }
3940 else if (rest && !rest->isEmpty())
3941 {
3942 int cc=rest->at(0);
3943 //printf("%c=rest\n",cc);
3944 return cc;
3945 }
3946 else
3947 {
3948 int cc=yyinput(yyscanner);
3949 returnCharToStream(yyscanner,(char)cc);
3950 //printf("%c=yyinput()\n",cc);
3951 return cc;
3952 }
static void returnCharToStream(yyscan_t yyscanner, char c)
Definition pre.l:2592
3953}

References QCString::at(), QCString::isEmpty(), QCString::length(), and returnCharToStream().

Referenced by replaceFunctionMacro(), and skipCommentMacroName().

◆ getFenceSize()

yy_size_t getFenceSize ( char * txt,
yy_size_t leng )
static

Definition at line 2212 of file pre.l.

2213{
2214 yy_size_t fenceSize = 0;
2215 for (size_t i = 0; i < leng; i++)
2216 {
2217 if (txt[i] != ' ' && txt[i] != '*' && txt[i] != '\t') break;
2218 fenceSize++;
2219 }
2220 return leng-fenceSize;
2221}

◆ getLexerFILE()

const char * getLexerFILE ( )
inlinestatic

Definition at line 352 of file pre.l.

352{return __FILE__;}

◆ getNextChar()

int getNextChar ( yyscan_t yyscanner,
const QCString & expr,
QCString * rest,
uint32_t & pos )
static

Definition at line 3909 of file pre.l.

3910{
3911 //printf("getNextChar(%s,%s,%d)\n",qPrint(expr),rest ? rest->data() : 0,pos);
3912 if (pos<expr.length())
3913 {
3914 //printf(" expr()='%c'\n",expr.at(pos));
3915 return expr.at(pos++);
3916 }
3917 else if (rest && !rest->isEmpty())
3918 {
3919 int cc=rest->at(0);
3920 *rest=rest->right(rest->length()-1);
3921 //printf(" rest='%c'\n",cc);
3922 return cc;
3923 }
3924 else
3925 {
3926 int cc=yyinput(yyscanner);
3927 //printf(" yyinput()='%c' %d\n",cc,EOF);
3928 return cc;
3929 }
3930}

References QCString::at(), QCString::isEmpty(), QCString::length(), and QCString::right().

Referenced by addSeparatorsIfNeeded(), addTillEndOfString(), replaceFunctionMacro(), and skipCommentMacroName().

◆ getNextId()

int getNextId ( const QCString & expr,
int p,
int * l )
static

returns the next identifier in string expr by starting at position p. The position of the identifier is returned (or -1 if nothing is found) and l is its length. Any quoted strings are skipping during the search.

Definition at line 2959 of file pre.l.

2960{
2961 int n;
2962 while (p<(int)expr.length())
2963 {
2964 char c=expr.at(p++);
2965 if (isdigit(c)) // skip number
2966 {
2967 while (p<(int)expr.length() && isId(expr.at(p))) p++;
2968 }
2969 else if (isalpha(c) || c=='_') // read id
2970 {
2971 n=p-1;
2972 while (p<(int)expr.length() && isId(expr.at(p))) p++;
2973 *l=p-n;
2974 return n;
2975 }
2976 else if (c=='"') // skip string
2977 {
2978 char ppc=0,pc=c;
2979 if (p<(int)expr.length()) c=expr.at(p);
2980 while (p<(int)expr.length() && (c!='"' || (pc=='\\' && ppc!='\\')))
2981 // continue as long as no " is found, but ignoring \", but not \\"
2982 {
2983 ppc=pc;
2984 pc=c;
2985 c=expr.at(p);
2986 p++;
2987 }
2988 if (p<(int)expr.length()) ++p; // skip closing quote
2989 }
2990 else if (c=='/') // skip C Comment
2991 {
2992 //printf("Found C comment at p=%d\n",p);
2993 char pc=c;
2994 if (p<(int)expr.length())
2995 {
2996 c=expr.at(p);
2997 if (c=='*') // Start of C comment
2998 {
2999 p++;
3000 while (p<(int)expr.length() && !(pc=='*' && c=='/'))
3001 {
3002 pc=c;
3003 c=expr.at(p++);
3004 }
3005 }
3006 }
3007 //printf("Found end of C comment at p=%d\n",p);
3008 }
3009 }
3010 return -1;
bool isId(int c)
Definition util.h:207
3011}

References QCString::at(), isId(), and QCString::length().

Referenced by expandExpression().

◆ incrLevel()

void incrLevel ( yyscan_t yyscanner)
static

Definition at line 2244 of file pre.l.

2245{
2246 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
2247 state->levelGuard.push(false);
2248 //printf("%s line %d: incrLevel %d\n",qPrint(yyextra->fileName),yyextra->yyLineNr,yyextra->levelGuard.size());
2249}

◆ initPredefined()

void initPredefined ( yyscan_t yyscanner,
const QCString & fileName )
static

Definition at line 4008 of file pre.l.

4009{
4010 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
4011
4012 // add predefined macros
4013 const StringVector &predefList = Config_getList(PREDEFINED);
4014 for (const auto &ds : predefList)
4015 {
4016 size_t i_equals=ds.find('=');
4017 size_t i_obrace=ds.find('(');
4018 size_t i_cbrace=ds.find(')');
4019 bool nonRecursive = i_equals!=std::string::npos && i_equals>0 && ds[i_equals-1]==':';
4020
4021 if ((i_obrace==0) || (i_equals==0) || (i_equals==1 && ds[i_equals-1]==':'))
4022 {
4023 continue; // no define name
4024 }
4025
4026 if (i_obrace<i_equals && i_cbrace<i_equals &&
4027 i_obrace!=std::string::npos && i_cbrace!=std::string::npos &&
4028 i_obrace<i_cbrace
4029 ) // predefined function macro definition
4030 {
4031 static const reg::Ex reId(R"(\a\w*)");
4032 std::map<std::string,int> argMap;
4033 std::string args = ds.substr(i_obrace+1,i_cbrace-i_obrace-1); // part between ( and )
4034 bool hasVarArgs = args.find("...")!=std::string::npos;
4035 //printf("predefined function macro '%s'\n",qPrint(ds));
4036 int count = 0;
4037 reg::Iterator arg_it(args,reId,0);
4038 reg::Iterator arg_end;
4039 // gather the formal arguments in a dictionary
4040 for (; arg_it!=arg_end; ++arg_it)
4041 {
4042 argMap.emplace(arg_it->str(),count++);
4043 }
4044 if (hasVarArgs) // add the variable argument if present
4045 {
4046 argMap.emplace("__VA_ARGS__",count++);
4047 }
Class representing a regular expression.
Definition regex.h:39
Class to iterate through matches.
Definition regex.h:230
4048
4049 // strip definition part
4050 std::string definition;
4051 std::string in=ds.substr(i_equals+1);
4052 reg::Iterator re_it(in,reId);
4053 reg::Iterator re_end;
4054 size_t i=0;
4055 // substitute all occurrences of formal arguments by their
4056 // corresponding markers
4057 for (; re_it!=re_end; ++re_it)
4058 {
4059 const auto &match = *re_it;
4060 size_t pi = match.position();
4061 size_t l = match.length();
4062 if (pi>i) definition+=in.substr(i,pi-i);
bool match(std::string_view str, Match &match, const Ex &re)
Matches a given string str for a match against regular expression re.
Definition regex.cpp:855
4063
4064 auto it = argMap.find(match.str());
4065 if (it!=argMap.end())
4066 {
4067 int argIndex = it->second;
4068 QCString marker;
4069 marker.sprintf(" @%d ",argIndex);
4070 definition+=marker.str();
4071 }
4072 else
4073 {
4074 definition+=match.str();
4075 }
4076 i=pi+l;
4077 }
4078 definition+=in.substr(i);
QCString & sprintf(const char *format,...)
Definition qcstring.cpp:29
4079
4080 // add define definition to the dictionary of defines for this file
4081 std::string dname = ds.substr(0,i_obrace);
4082 if (!dname.empty())
4083 {
4084 Define def;
4085 def.name = dname;
4086 def.definition = definition;
4087 def.nargs = count;
4088 def.isPredefined = TRUE;
4089 def.nonRecursive = nonRecursive;
4090 def.fileDef = state->yyFileDef;
4091 def.fileName = fileName;
4092 def.varArgs = hasVarArgs;
4093 state->contextDefines.emplace(def.name.str(),def);
4094
4095 //printf("#define '%s' '%s' #nargs=%d hasVarArgs=%d\n",
4096 // qPrint(def.name),qPrint(def.definition),def.nargs,def.varArgs);
4097 }
4098 }
4099 else if (!ds.empty()) // predefined non-function macro definition
4100 {
4101 //printf("predefined normal macro '%s'\n",qPrint(ds));
4102 Define def;
4103 if (i_equals==std::string::npos) // simple define without argument
4104 {
4105 def.name = ds;
4106 def.definition = "1"; // substitute occurrences by 1 (true)
4107 }
4108 else // simple define with argument
4109 {
4110 int ine=static_cast<int>(i_equals) - (nonRecursive ? 1 : 0);
4111 def.name = ds.substr(0,ine);
4112 def.definition = ds.substr(i_equals+1);
4113 }
4114 if (!def.name.isEmpty())
4115 {
4116 def.nargs = -1;
4117 def.isPredefined = TRUE;
4118 def.nonRecursive = nonRecursive;
4119 def.fileDef = state->yyFileDef;
4120 def.fileName = fileName;
4121 state->contextDefines.emplace(def.name.str(),def);
4122 }
4123 }
4124 }
4125}

References Config_getList, Define::definition, Define::fileDef, Define::fileName, QCString::isEmpty(), Define::isPredefined, Define::name, Define::nargs, Define::nonRecursive, QCString::sprintf(), QCString::str(), reg::Match::str(), TRUE, and Define::varArgs.

Referenced by Preprocessor::processFile().

◆ isDefined()

Define * isDefined ( yyscan_t yyscanner,
const QCString & name )
static

Returns a reference to a Define object given its name or 0 if the Define does not exist.

Definition at line 3979 of file pre.l.

3980{
3981 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
3982
3983 bool undef = false;
3984 auto findDefine = [&undef,&name](DefineMap &map)
3985 {
3986 Define *d=nullptr;
3987 auto it = map.find(name.str());
3988 if (it!=map.end())
3989 {
3990 d = &it->second;
3991 if (d->undef)
3992 {
3993 undef=true;
3994 d=nullptr;
3995 }
3996 }
3997 return d;
3998 };
bool undef
Definition define.h:41
std::map< std::string, Define > DefineMap
A dictionary of managed Define objects.
Definition pre.l:109
3999
4000 Define *def = findDefine(state->localDefines);
4001 if (def==nullptr && !undef)
4002 {
4003 def = findDefine(state->contextDefines);
4004 }
4005 return def;
4006}

References QCString::str(), and Define::undef.

Referenced by expandExpression().

◆ otherCaseDone()

bool otherCaseDone ( yyscan_t yyscanner)
static

Definition at line 2265 of file pre.l.

2266{
2267 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
2268 if (state->levelGuard.empty())
2269 {
2270 warn(state->fileName,state->yyLineNr,"Found an #else without a preceding #if.");
2271 return TRUE;
2272 }
2273 else
2274 {
2275 return state->levelGuard.top();
2276 }
2277}

References TRUE, and warn.

◆ outputArray()

void outputArray ( yyscan_t yyscanner,
const char * a,
yy_size_t len )
inlinestatic

Definition at line 3605 of file pre.l.

3606{
3607 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
3608 if (state->includeStack.empty() || state->curlyCount>0) (*state->outputBuf)+=std::string_view(a,len);
3609}

◆ outputChar()

void outputChar ( yyscan_t yyscanner,
char c )
inlinestatic

Definition at line 3599 of file pre.l.

3600{
3601 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
3602 if (state->includeStack.empty() || state->curlyCount>0) (*state->outputBuf)+=c;
3603}

Referenced by outputSpace(), and outputSpaces().

◆ outputSpace()

void outputSpace ( yyscan_t yyscanner,
char c )
inlinestatic

Definition at line 3617 of file pre.l.

3618{
3619 if (c=='\t') outputChar(yyscanner,'\t');
3620 else outputChar(yyscanner,' ');
static void outputChar(yyscan_t yyscanner, char c)
Definition pre.l:3599
3621}

References outputChar().

◆ outputSpaces()

void outputSpaces ( yyscan_t yyscanner,
char * s )
inlinestatic

Definition at line 3623 of file pre.l.

3624{
3625 const char *p=s;
3626 char c = 0;
3627 while ((c=*p++))
3628 {
3629 if (c=='\t') outputChar(yyscanner,'\t');
3630 else outputChar(yyscanner,' ');
3631 }
3632}

References outputChar().

◆ outputString()

void outputString ( yyscan_t yyscanner,
const QCString & s )
inlinestatic

Definition at line 3611 of file pre.l.

3612{
3613 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
3614 if (state->includeStack.empty() || state->curlyCount>0) (*state->outputBuf)+=a.str();
3615}

References QCString::str().

Referenced by readIncludeFile().

◆ processConcatOperators()

void processConcatOperators ( QCString & expr)
static

Execute all ## operators in expr. If the macro name before or after the operator contains a no-rescan marker (-) then this is removed (before the concatenated macro name may be expanded again.

Definition at line 2545 of file pre.l.

2546{
2547 if (expr.isEmpty()) return;
2548 //printf("processConcatOperators: in='%s'\n",qPrint(expr));
2549 std::string e = expr.str();
2550 static const reg::Ex r(R"(\s*##\s*)");
DirIterator end(const DirIterator &) noexcept
Definition dir.cpp:175
2552
2553 size_t i=0;
2554 for (;;)
2555 {
2556 reg::Iterator it(e,r,i);
2557 if (it!=end)
2558 {
2559 const auto &match = *it;
2560 size_t n = match.position();
2561 size_t l = match.length();
2562 //printf("Match: '%s'\n",qPrint(expr.mid(i)));
2563 if (n+l+1<e.length() && e[static_cast<int>(n+l)]=='@' && expr[static_cast<int>(n+l+1)]=='-')
2564 {
2565 // remove no-rescan marker after ID
2566 l+=2;
2567 }
2568 //printf("found '%s'\n",qPrint(expr.mid(n,l)));
2569 // remove the ## operator and the surrounding whitespace
2570 e=e.substr(0,n)+e.substr(n+l);
2571 int k=static_cast<int>(n)-1;
2572 while (k>=0 && isId(e[k])) k--;
2573 if (k>0 && e[k]=='-' && e[k-1]=='@')
2574 {
2575 // remove no-rescan marker before ID
2576 e=e.substr(0,k-1)+e.substr(k+1);
2577 n-=2;
2578 }
2579 i=n;
2580 }
2581 else
2582 {
2583 break;
2584 }
2585 }
2586
2587 expr = e;
2588
2589 //printf("processConcatOperators: out='%s'\n",qPrint(expr));
2590}

References end(), QCString::isEmpty(), isId(), and QCString::str().

Referenced by expandExpression().

◆ processUntilMatchingTerminator()

const char * processUntilMatchingTerminator ( const char * inputStr,
QCString & result )
static

Process string or character literal.

inputStr should point to the start of a string or character literal. the routine will return a pointer to just after the end of the literal the character making up the literal will be added to result.

Definition at line 3191 of file pre.l.

3192{
3193 if (inputStr==nullptr) return inputStr;
3194 char term = *inputStr; // capture start character of the literal
3195 if (term!='\'' && term!='"') return inputStr; // not a valid literal
3196 char c=term;
3197 // output start character
3198 result+=c;
3199 inputStr++;
3200 while ((c=*inputStr)) // while inside the literal
3201 {
3202 if (c==term) // found end marker of the literal
3203 {
3204 // output end character and stop
3205 result+=c;
3206 inputStr++;
3207 break;
3208 }
3209 else if (c=='\\') // escaped character, process next character
3210 // as well without checking for end marker.
3211 {
3212 result+=c;
3213 inputStr++;
3214 c=*inputStr;
3215 if (c==0) break; // unexpected end of string after escape character
3216 }
3217 result+=c;
3218 inputStr++;
3219 }
3220 return inputStr;
3221}

References term.

Referenced by removeIdsAndMarkers(), and removeMarkers().

◆ readIncludeFile()

void readIncludeFile ( yyscan_t yyscanner,
const QCString & inc )
static

Definition at line 3680 of file pre.l.

3681{
3682 AUTO_TRACE("inc={}",inc);
3683 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
3684 uint32_t i=0;
#define AUTO_TRACE(...)
Definition docnode.cpp:46
3685
3686 // find the start of the include file name
3687 while (i<inc.length() &&
3688 (inc.at(i)==' ' || inc.at(i)=='"' || inc.at(i)=='<')
3689 ) i++;
3690 uint32_t s=i;
3691
3692 // was it a local include?
3693 bool localInclude = s>0 && inc.at(s-1)=='"';
3694
3695 // find the end of the include file name
3696 while (i<inc.length() && inc.at(i)!='"' && inc.at(i)!='>') i++;
3697
3698 if (s<inc.length() && i>s) // valid include file name found
3699 {
3700 // extract include path+name
3701 QCString incFileName=inc.mid(s,i-s).stripWhiteSpace();
3702 if (incFileName.endsWith(".exe") || incFileName.endsWith(".dll") || incFileName.endsWith(".tlb"))
3703 {
3704 // skip imported binary files (e.g. M$ type libraries)
3705 return;
3706 }
bool endsWith(const char *s) const
Definition qcstring.h:524
3707
3708 QCString oldFileName = state->fileName;
3709 FileDef *oldFileDef = state->yyFileDef;
3710 int oldLineNr = state->yyLineNr;
3711 //printf("Searching for '%s'\n",qPrint(incFileName));
3712
3713 QCString absIncFileName = determineAbsoluteIncludeName(state->fileName,incFileName);
QCString determineAbsoluteIncludeName(const QCString &curFile, const QCString &incFileName)
Definition util.cpp:3542
3714
3715 // findFile will overwrite state->yyFileDef if found
3716 std::unique_ptr<FileState> fs;
3717 bool alreadyProcessed = FALSE;
3718 //printf("calling findFile(%s)\n",qPrint(incFileName));
3719 fs=findFile(yyscanner,absIncFileName,localInclude,alreadyProcessed); // see if the absolute include file can be found
3720 if (fs)
3721 {
3722 {
3723 std::lock_guard<std::mutex> lock(g_globalDefineMutex);
3724 g_defineManager.addInclude(oldFileName.str(),absIncFileName.str());
3725 }
static std::unique_ptr< FileState > findFile(yyscan_t yyscanner, const QCString &fileName, bool localInclude, bool &alreadyProcessed)
Definition pre.l:2343
3726
3727 //printf("Found include file!\n");
3729 {
3730 for (i=0;i<state->includeStack.size();i++)
3731 {
3733 }
3734 Debug::print(Debug::Preprocessor,0,"#include {}: parsing...\n",incFileName);
3735 }
@ Preprocessor
Definition debug.h:30
static bool isFlagSet(const DebugMask mask)
Definition debug.cpp:132
static void print(DebugMask mask, int prio, fmt::format_string< Args... > fmt, Args &&... args)
Definition debug.h:76
3736
3737 if (state->includeStack.empty() && oldFileDef)
3738 {
3739 PreIncludeInfo *ii = state->includeRelations.find(absIncFileName);
3740 if (ii==nullptr)
3741 {
3742 bool ambig = false;
3743 FileDef *incFd = findFileDef(Doxygen::inputNameLinkedMap,absIncFileName,ambig);
3744 state->includeRelations.add(
3745 absIncFileName,
3746 oldFileDef,
3747 ambig ? nullptr : incFd,
3748 incFileName,
3749 localInclude,
3750 state->isImported
3751 );
3752 }
3753 }
3754
3755 struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
3756 fs->bufState = YY_CURRENT_BUFFER;
3757 fs->lineNr = oldLineNr;
3758 fs->fileName = oldFileName;
3759 fs->curlyCount = state->curlyCount;
3760 //state->curlyCount = 0; // don't reset counter, see issue #10997
3761 fs->lexRulesPart = state->lexRulesPart;
3762 state->lexRulesPart = false;
3763 // push the state on the stack
3764 FileState *fs_ptr = fs.get();
3765 state->includeStack.push_back(std::move(fs));
3766 // set the scanner to the include file
3767
3768 // Deal with file changes due to
3769 // #include's within { .. } blocks
3770 QCString lineStr(state->fileName.length()+20, QCString::ExplicitSize);
3771 lineStr.sprintf("# 1 \"%s\" 1\n",qPrint(state->fileName));
3772 outputString(yyscanner,lineStr);
@ ExplicitSize
Definition qcstring.h:146
static void outputString(yyscan_t yyscanner, const QCString &s)
Definition pre.l:3611
const char * qPrint(const char *s)
Definition qcstring.h:687
3773
3774 AUTO_TRACE_ADD("Switching to include file {}",incFileName);
3775 state->expectGuard=TRUE;
3776 state->inputBuf = &fs_ptr->fileBuf;
3777 state->inputBufPos=0;
3778 yy_switch_to_buffer(yy_create_buffer(0, YY_BUF_SIZE, yyscanner),yyscanner);
3779 }
3780 else
3781 {
3782 if (alreadyProcessed) // if this header was already process we can just copy the stored macros
3783 // in the local context
3784 {
3785 std::lock_guard<std::mutex> lock(g_globalDefineMutex);
3786 g_defineManager.addInclude(state->fileName.str(),absIncFileName.str());
3787 g_defineManager.retrieve(absIncFileName.str(),state->contextDefines);
3788 }
#define YY_BUF_SIZE
Definition commentcnv.l:19
#define AUTO_TRACE_ADD(...)
Definition docnode.cpp:47
std::string fileBuf
Definition pre.l:86
3789
3790 if (state->includeStack.empty() && oldFileDef)
3791 {
3792 PreIncludeInfo *ii = state->includeRelations.find(absIncFileName);
3793 if (ii==nullptr)
3794 {
3795 bool ambig = false;
3796 FileDef *incFd = findFileDef(Doxygen::inputNameLinkedMap,absIncFileName,ambig);
3797 ii = state->includeRelations.add(absIncFileName,
3798 oldFileDef,
3799 ambig ? nullptr : incFd,
3800 incFileName,
3801 localInclude,
3802 state->isImported
3803 );
3804 }
3805 }
3806
3808 {
3809 for (i=0;i<state->includeStack.size();i++)
3810 {
3812 }
3813 if (alreadyProcessed)
3814 {
3815 Debug::print(Debug::Preprocessor,0,"#include {}: already processed! skipping...\n",incFileName);
3816 }
3817 else
3818 {
3819 Debug::print(Debug::Preprocessor,0,"#include {}: not found! skipping...\n",incFileName);
3820 }
3821 //printf("error: include file %s not found\n",yytext);
3822 }
3823 if (localInclude && !state->includeStack.empty() && state->curlyCount>0 && !alreadyProcessed) // failed to find #include inside { ... }
3824 {
3825 warn(state->fileName,state->yyLineNr,"include file {} not found, perhaps you forgot to add its directory to INCLUDE_PATH?",incFileName);
3826 }
3827 }
3828 }
3829}

References QCString::at(), AUTO_TRACE, AUTO_TRACE_ADD, determineAbsoluteIncludeName(), QCString::endsWith(), QCString::ExplicitSize, FALSE, FileState::fileBuf, findFile(), findFileDef(), g_defineManager, g_globalDefineMutex, Doxygen::inputNameLinkedMap, Debug::isFlagSet(), QCString::length(), QCString::mid(), outputString(), Debug::Preprocessor, Debug::print(), qPrint(), QCString::sprintf(), QCString::str(), QCString::stripWhiteSpace(), TRUE, warn, and YY_BUF_SIZE.

◆ removeIdsAndMarkers()

QCString removeIdsAndMarkers ( const QCString & s)
static

replaces all occurrences of @@ in s by @ and removes all occurrences of @E. All identifiers found are replaced by 0L

Definition at line 3227 of file pre.l.

3228{
3229 static const std::vector<std::string> signs = { "signed", "unsigned" };
3230 struct TypeInfo { std::string name; size_t size; };
3231 static const std::vector<TypeInfo> types = {
3232 { "short int", sizeof(short int) },
3233 { "long long int", sizeof(long long int) },
3234 { "long int", sizeof(long int) },
3235 { "long long", sizeof(long long) },
3236 { "long double", sizeof(long double) },
3237 { "int", sizeof(int) },
3238 { "short", sizeof(short) },
3239 { "bool", sizeof(bool) },
3240 { "long", sizeof(long) },
3241 { "char", sizeof(char) },
3242 { "float", sizeof(float) },
3243 { "double", sizeof(double) },
3244 };
3245
3246 // Check if string p starts with basic types ending with a ')', such as 'signed long)' or ' float )'
3247 // and return the pointer just past the ')' and the size of the type as a tuple.
3248 // If the pattern is not found the tuple (nullptr,0) is returned.
3249 auto process_cast_or_sizeof = [](const char *p) -> std::pair<const char *,size_t>
3250 {
3251 const char *q = p;
3252 while (*q==' ' || *q=='\t') q++;
3253 bool found=false;
3254 size_t size = sizeof(int); // '(signed)' or '(unsigned)' is an int type
3255 for (const auto &sgn : signs)
3256 {
3257 if (qstrncmp(q,sgn.c_str(),sgn.length())==0) { q+=sgn.length(); found=true; }
3258 }
3259 if (!found || *q==' ' || *q=='\t' || *q==')') // continue searching
3260 {
3261 while (*q==' ' || *q=='\t') q++;
3262 for (const auto &t : types)
3263 {
3264 if (qstrncmp(q,t.name.c_str(),t.name.length())==0)
3265 {
3266 q += t.name.length();
3267 size = t.size;
3268 break;
3269 }
3270 }
3271 while (*q==' ' || *q=='\t') q++;
3272 if (*q==')') return std::make_pair(++q,size);
3273 }
3274 return std::make_pair(nullptr,0);
3275 };
int qstrncmp(const char *str1, const char *str2, size_t len)
Definition qcstring.h:75
3276
3277 //printf("removeIdsAndMarkers(%s)\n",qPrint(s));
3278 if (s.isEmpty()) return s;
3279 const char *p=s.data();
3280 bool inNum=FALSE;
3281 QCString result;
3282 if (p)
3283 {
3284 char c = 0;
3285 while ((c=*p))
3286 {
3287 if (c=='(') // potential cast, ignore it
3288 {
3289 const char *q = process_cast_or_sizeof(p+1).first;
3290 //printf("potential cast:\nin: %s\nout: %s\n",p,q);
3291 if (q)
3292 {
3293 p=q;
3294 continue;
3295 }
3296 }
3297 else if (c=='s' && literal_at(p,"sizeof")) // sizeof(...)
3298 {
3299 const char *q = p+6;
3300 while (*q==' ' || *q=='\t') q++;
3301 if (*q=='(')
3302 {
3303 auto r = process_cast_or_sizeof(q+1);
3304 //printf("sizeof:\nin: %s\nout: %zu%s\n--> sizeof=%zu\n",p,r.second,r.first,r.second);
3305 if (r.first)
3306 {
3307 result+=QCString().setNum(r.second);
3308 p=r.first;
3309 continue;
3310 }
3311 }
3312 }
QCString & setNum(short n)
Definition qcstring.h:459
bool literal_at(const char *data, const char(&str)[N])
returns TRUE iff data points to a substring that matches string literal str
Definition stringutil.h:98
3313
3314 if (c=='@') // replace @@ with @ and remove @E
3315 {
3316 if (*(p+1)=='@')
3317 {
3318 result+=c;
3319 }
3320 else if (*(p+1)=='E')
3321 {
3322 // skip
3323 }
3324 p+=2;
3325 }
3326 else if (isdigit(c)) // number
3327 {
3328 result+=c;
3329 p++;
3330 inNum=TRUE;
3331 }
3332 else if (c=='\'') // quoted character
3333 {
3334 p = processUntilMatchingTerminator(p,result);
3335 }
3336 else if (c=='d' && !inNum) // identifier starting with a 'd'
3337 {
3338 if (literal_at(p,"defined ") || literal_at(p,"defined("))
3339 // defined keyword
3340 {
3341 p+=7; // skip defined
3342 }
3343 else
3344 {
3345 result+="0L";
3346 p++;
3347 while ((c=*p) && isId(c)) p++;
3348 }
3349 }
3350 else if ((isalpha(c) || c=='_') && !inNum) // replace identifier with 0L
3351 {
3352 result+="0L";
3353 p++;
3354 while ((c=*p) && isId(c)) p++;
3355 while ((c=*p) && isspace((uint8_t)c)) p++;
3356 if (*p=='(') // undefined function macro
3357 {
3358 p++;
3359 int count=1;
3360 while ((c=*p++))
3361 {
3362 if (c=='(') count++;
3363 else if (c==')')
3364 {
3365 count--;
3366 if (count==0) break;
3367 }
3368 else if (c=='/')
3369 {
3370 char pc=c;
3371 c=*++p;
3372 if (c=='*') // start of C comment
3373 {
3374 while (*p && !(pc=='*' && c=='/')) // search end of comment
3375 {
3376 pc=c;
3377 c=*++p;
3378 }
3379 p++;
3380 }
3381 }
3382 }
3383 }
3384 }
3385 else if (c=='/') // skip C comments
3386 {
3387 char pc=c;
3388 c=*++p;
3389 if (c=='*') // start of C comment
3390 {
3391 while (*p && !(pc=='*' && c=='/')) // search end of comment
3392 {
3393 pc=c;
3394 c=*++p;
3395 }
3396 p++;
3397 }
3398 else // oops, not comment but division
3399 {
3400 result+=pc;
3401 goto nextChar;
3402 }
3403 }
3404 else
3405 {
static const char * processUntilMatchingTerminator(const char *inputStr, QCString &result)
Process string or character literal.
Definition pre.l:3191
3406nextChar:
3407 result+=c;
3408 char lc=(char)tolower(c);
3409 if (!isId(lc) && lc!='.' /*&& lc!='-' && lc!='+'*/) inNum=FALSE;
3410 p++;
3411 }
3412 }
3413 }
3414 //printf("removeIdsAndMarkers(%s)=%s\n",s,qPrint(result));
3415 return result;
3416}

References QCString::data(), FALSE, QCString::isEmpty(), isId(), literal_at(), processUntilMatchingTerminator(), qstrncmp(), QCString::setNum(), and TRUE.

Referenced by computeExpression().

◆ removeMarkers()

QCString removeMarkers ( const QCString & s)
static

replaces all occurrences of @ in s by @

assumption:
s only contains pairs of @'s

Definition at line 3422 of file pre.l.

3423{
3424 if (s.isEmpty()) return s;
3425 const char *p=s.data();
3426 QCString result;
3427 if (p)
3428 {
3429 char c = 0;
3430 while ((c=*p))
3431 {
3432 switch(c)
3433 {
3434 case '@': // replace @@ with @
3435 {
3436 if (*(p+1)=='@')
3437 {
3438 result+=c;
3439 }
3440 p+=2;
3441 }
3442 break;
3443 case '/': // skip C comments
3444 {
3445 result+=c;
3446 char pc=c;
3447 c=*++p;
3448 if (c=='*') // start of C comment
3449 {
3450 while (*p && !(pc=='*' && c=='/')) // search end of comment
3451 {
3452 if (*p=='@' && *(p+1)=='@')
3453 {
3454 result+=c;
3455 p++;
3456 }
3457 else
3458 {
3459 result+=c;
3460 }
3461 pc=c;
3462 c=*++p;
3463 }
3464 if (*p)
3465 {
3466 result+=c;
3467 p++;
3468 }
3469 }
3470 }
3471 break;
3472 case '"': // skip string literals
3473 case '\'': // skip char literals
3474 p = processUntilMatchingTerminator(p,result);
3475 break;
3476 default:
3477 {
3478 result+=c;
3479 p++;
3480 }
3481 break;
3482 }
3483 }
3484 }
3485 //printf("RemoveMarkers(%s)=%s\n",s,qPrint(result));
3486 return result;
3487}

References QCString::data(), QCString::isEmpty(), and processUntilMatchingTerminator().

Referenced by computeExpression(), and expandMacro().

◆ replaceFunctionMacro()

bool replaceFunctionMacro ( yyscan_t yyscanner,
const QCString & expr,
QCString * rest,
int pos,
int & len,
const Define * def,
QCString & result,
int level )
static

replaces the function macro def whose argument list starts at pos in expression expr. Notice that this routine may scan beyond the expr string if needed. In that case the characters will be read from the input file. The replacement string will be returned in result and the length of the (unexpanded) argument list is stored in len.

Definition at line 2701 of file pre.l.

2702{
2703 //printf(">replaceFunctionMacro(expr='%s',rest='%s',pos=%d,def='%s') level=%zu\n",qPrint(expr),rest ? qPrint(*rest) : 0,pos,qPrint(def->name),preYYget_extra(yyscanner)->levelGuard.size());
2704 uint32_t j=pos;
2705 len=0;
2706 result.clear();
2707 int cc;
2708
2709 skipCommentMacroName(yyscanner, expr, rest, cc, j, len);
static void skipCommentMacroName(yyscan_t yyscanner, const QCString &expr, QCString *rest, int &cc, uint32_t &j, int &len)
Definition pre.l:2617
2710
2711 if (cc!='(')
2712 {
2713 if (cc!=':') // don't add spaces for colons
2714 {
2715 unputChar(yyscanner,expr,rest,j,' ');
2716 }
2717 return FALSE;
2718 }
2719 getNextChar(yyscanner,expr,rest,j); // eat the '(' character
2720
2721 std::map<std::string,std::string> argTable; // list of arguments
2722 QCString arg;
2723 int argCount=0;
2724 int argCountNonEmpty=0;
2725 bool done=FALSE;
2726
2727 // PHASE 1: read the macro arguments
2728 if (def->nargs==0)
2729 {
2730 while ((cc=getNextChar(yyscanner,expr,rest,j))!=EOF && cc!=0)
2731 {
2732 char c = (char)cc;
2733 if (c==')') break;
2734 }
2735 }
2736 else
2737 {
2738 while (!done && (argCount<def->nargs || def->varArgs) &&
2739 ((cc=getNextChar(yyscanner,expr,rest,j))!=EOF && cc!=0)
2740 )
2741 {
2742 char c=(char)cc;
2743 if (c=='(') // argument is a function => search for matching )
2744 {
2745 int lvl=1;
2746 arg+=c;
2747 //char term='\0';
2748 while ((cc=getNextChar(yyscanner,expr,rest,j))!=EOF && cc!=0)
2749 {
2750 c=(char)cc;
2751 //printf("processing %c: term=%c (%d)\n",c,term,term);
2752 if (c=='\'' || c=='\"') // skip ('s and )'s inside strings
2753 {
2754 arg+=c;
2755 addTillEndOfString(yyscanner,expr,rest,j,c,arg);
2756 }
2757 if (c==')')
2758 {
2759 lvl--;
2760 arg+=c;
2761 if (lvl==0) break;
2762 }
2763 else if (c=='(')
2764 {
2765 lvl++;
2766 arg+=c;
2767 }
2768 else
2769 {
2770 arg+=c;
2771 }
2772 }
2773 }
2774 else if (c==')' || c==',') // last or next argument found
2775 {
2776 if (c==',' && argCount==def->nargs-1 && def->varArgs)
2777 {
2778 expandExpression(yyscanner,arg,nullptr,0,level+1);
2779 arg=arg.stripWhiteSpace();
2780 arg+=',';
2781 }
2782 else
2783 {
2784 expandExpression(yyscanner,arg,nullptr,0,level+1);
2785 arg=arg.stripWhiteSpace();
2786 QCString argKey;
2787 argKey.sprintf("@%d",argCount++); // key name
2788 if (c==',' || !arg.isEmpty()) argCountNonEmpty++;
2789 // add argument to the lookup table
2790 argTable.emplace(toStdString(argKey), toStdString(arg));
2791 arg.clear();
2792 if (c==')') // end of the argument list
2793 {
2794 done=TRUE;
2795 }
2796 }
2797 }
2798 else if (c=='\"') // append literal strings
2799 {
2800 arg+=c;
2801 bool found=FALSE;
2802 while (!found && (cc=getNextChar(yyscanner,expr,rest,j))!=EOF && cc!=0)
2803 {
2804 found = cc=='"';
2805 if (cc=='\\')
2806 {
2807 c=(char)cc;
2808 arg+=c;
2809 if ((cc=getNextChar(yyscanner,expr,rest,j))==EOF || cc==0) break;
2810 }
2811 c=(char)cc;
2812 arg+=c;
2813 }
2814 }
2815 else if (c=='\'') // append literal characters
2816 {
2817 arg+=c;
2818 bool found=FALSE;
2819 while (!found && (cc=getNextChar(yyscanner,expr,rest,j))!=EOF && cc!=0)
2820 {
2821 found = cc=='\'';
2822 if (cc=='\\')
2823 {
2824 c=(char)cc;
2825 arg+=c;
2826 if ((cc=getNextChar(yyscanner,expr,rest,j))==EOF || cc==0) break;
2827 }
2828 c=(char)cc;
2829 arg+=c;
2830 }
2831 }
2832 else if (c=='/') // possible start of a comment
2833 {
2834 char prevChar = '\0';
2835 arg+=c;
2836 if ((cc=getCurrentChar(yyscanner,expr,rest,j)) == '*') // we have a comment
2837 {
2838 while ((cc=getNextChar(yyscanner,expr,rest,j))!=EOF && cc!=0)
2839 {
2840 c=(char)cc;
2841 arg+=c;
2842 if (c == '/' && prevChar == '*') break; // we have an end of comment
2843 prevChar = c;
2844 }
2845 }
2846 }
2847 else // append other characters
2848 {
2849 arg+=c;
2850 }
2851 }
2852 }
static int getCurrentChar(yyscan_t yyscanner, const QCString &expr, QCString *rest, uint32_t pos)
Definition pre.l:3932
static void addTillEndOfString(yyscan_t yyscanner, const QCString &expr, QCString *rest, uint32_t &pos, char term, QCString &arg)
Definition pre.l:2598
2853
2854 // PHASE 2: apply the macro function
2855 if (argCount==def->nargs || // same number of arguments
2856 (argCount>=def->nargs-1 && def->varArgs)) // variadic macro with at least as many
2857 // params as the non-variadic part (see bug731985)
2858 {
2859 uint32_t k=0;
2860 // substitution of all formal arguments
2861 QCString resExpr;
2863 //printf("varArgs=%d argCount=%d def->nargs=%d d=%s\n",def->varArgs,argCount,def->nargs,qPrint(d));
2864 if (def->varArgs) d = expandVAOpt(d,argCountNonEmpty!=def->nargs-1);
2865 //printf("Macro definition: '%s'\n",qPrint(d));
2866 bool inString=FALSE;
2867 while (k<d.length())
2868 {
2869 if (d.at(k)=='@') // maybe a marker, otherwise an escaped @
2870 {
2871 if (d.at(k+1)=='@') // escaped @ => copy it (is unescaped later)
2872 {
2873 k+=2;
2874 resExpr+="@@"; // we unescape these later
2875 }
2876 else if (d.at(k+1)=='-') // no-rescan marker
2877 {
2878 k+=2;
2879 resExpr+="@-";
2880 }
2881 else // argument marker => read the argument number
2882 {
2883 QCString key="@";
2884 bool hash=FALSE;
2885 int l=k-1;
2886 // search for ## backward
2887 if (l>=0 && d.at(l)=='"') l--;
2888 while (l>=0 && d.at(l)==' ') l--;
2889 if (l>0 && d.at(l)=='#' && d.at(l-1)=='#') hash=TRUE;
2890 k++;
2891 // scan the number
2892 while (k<d.length() && d.at(k)>='0' && d.at(k)<='9') key+=d.at(k++);
2893 if (!hash)
2894 {
2895 // search for ## forward
2896 l=k;
2897 if (l<(int)d.length() && d.at(l)=='"') l++;
2898 while (l<(int)d.length() && d.at(l)==' ') l++;
2899 if (l<(int)d.length()-1 && d.at(l)=='#' && d.at(l+1)=='#') hash=TRUE;
2900 }
2901 //printf("request key %s result %s\n",qPrint(key),argTable[key]->data());
2902 auto it = argTable.find(key.str());
2903 if (it!=argTable.end())
2904 {
2905 QCString substArg = it->second;
2906 //printf("substArg='%s'\n",qPrint(substArg));
2907 // only if no ## operator is before or after the argument
2908 // marker we do macro expansion.
2909 if (!hash)
2910 {
2911 expandExpression(yyscanner,substArg,nullptr,0,level+1);
2912 }
2913 if (inString)
2914 {
2915 //printf("'%s'=stringize('%s')\n",qPrint(stringize(*subst)),subst->data());
static QCString expandVAOpt(const QCString &vaStr, bool hasOptionalArgs)
Definition pre.l:2649
2916
2917 // if the marker is inside a string (because a # was put
2918 // before the macro name) we must escape " and \ characters
2919 resExpr+=stringize(substArg);
2920 }
2921 else
2922 {
2923 if (hash && substArg.isEmpty())
2924 {
2925 resExpr+="@E"; // empty argument will be remove later on
2926 }
2927 resExpr+=substArg;
2928 }
2929 }
2930 }
2931 }
2932 else // no marker, just copy
2933 {
2934 if (!inString && d.at(k)=='\"')
2935 {
2936 inString=TRUE; // entering a literal string
2937 }
2938 else if (k>2 && inString && d.at(k)=='\"' && (d.at(k-1)!='\\' || d.at(k-2)=='\\'))
2939 {
2940 inString=FALSE; // leaving a literal string
2941 }
2942 resExpr+=d.at(k++);
2943 }
2944 }
2945 len=j-pos;
2946 result=resExpr;
2947 //printf("<replaceFunctionMacro(expr='%s',rest='%s',pos=%d,def='%s',result='%s') level=%zu return=TRUE\n",qPrint(expr),rest ? qPrint(*rest) : 0,pos,qPrint(def->name),qPrint(result),preYYget_extra(yyscanner)->levelGuard.size());
2948 return TRUE;
2949 }
2950 //printf("<replaceFunctionMacro(expr='%s',rest='%s',pos=%d,def='%s',result='%s') level=%zu return=FALSE\n",qPrint(expr),rest ? qPrint(*rest) : 0,pos,qPrint(def->name),qPrint(result),preYYget_extra(yyscanner)->levelGuard.size());
2951 return FALSE;
static QCString stringize(const QCString &s)
Definition pre.l:2467
2952}

References addTillEndOfString(), QCString::at(), QCString::clear(), Define::definition, expandExpression(), expandVAOpt(), FALSE, getCurrentChar(), getNextChar(), QCString::isEmpty(), QCString::length(), Define::nargs, skipCommentMacroName(), QCString::sprintf(), QCString::str(), stringize(), QCString::stripWhiteSpace(), toStdString(), TRUE, unputChar(), and Define::varArgs.

Referenced by expandExpression().

◆ resolveTrigraph()

char resolveTrigraph ( char c)
static

Definition at line 3889 of file pre.l.

3890{
3891 switch (c)
3892 {
3893 case '=': return '#';
3894 case '/': return '\\';
3895 case '\'': return '^';
3896 case '(': return '[';
3897 case ')': return ']';
3898 case '!': return '|';
3899 case '<': return '{';
3900 case '>': return '}';
3901 case '-': return '~';
3902 }
3903 return '?';
3904}

◆ returnCharToStream()

void returnCharToStream ( yyscan_t yyscanner,
char c )
static

Definition at line 2592 of file pre.l.

2593{
2594 struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
2595 unput(c);
2596}

Referenced by getCurrentChar(), and unputChar().

◆ setCaseDone()

void setCaseDone ( yyscan_t yyscanner,
bool value )
static

Definition at line 2279 of file pre.l.

2280{
2281 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
2282 state->levelGuard.top()=value;
2283}

◆ setFileName()

void setFileName ( yyscan_t yyscanner,
const QCString & name )
static

Definition at line 2223 of file pre.l.

2224{
2225 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
2226 bool ambig = false;
2227 FileInfo fi(name.str());
2228 state->fileName=fi.absFilePath();
2229 state->yyFileDef=findFileDef(Doxygen::inputNameLinkedMap,state->fileName,ambig);
2230 if (state->yyFileDef==nullptr) // if this is not an input file check if it is an include file
2231 {
2232 state->yyFileDef=findFileDef(Doxygen::includeNameLinkedMap,state->fileName,ambig);
2233 }
2234 //printf("setFileName(%s) state->fileName=%s state->yyFileDef=%p\n",
2235 // name,qPrint(state->fileName),state->yyFileDef);
2236 if (state->yyFileDef && state->yyFileDef->isReference()) state->yyFileDef=nullptr;
2237 state->insideIDL = getLanguageFromFileName(state->fileName)==SrcLangExt::IDL;
2238 state->insideCS = getLanguageFromFileName(state->fileName)==SrcLangExt::CSharp;
2239 state->insideFtn = getLanguageFromFileName(state->fileName)==SrcLangExt::Fortran;
2240 EntryType section = guessSection(state->fileName);
2241 state->isSource = section.isHeader() || section.isSource();
static FileNameLinkedMap * includeNameLinkedMap
Definition doxygen.h:101
Wrapper class for the Entry type.
Definition types.h:813
SrcLangExt getLanguageFromFileName(const QCString &fileName, SrcLangExt defLang)
Definition util.cpp:5147
EntryType guessSection(const QCString &name)
Definition util.cpp:339
2242}

References FileInfo::absFilePath(), findFileDef(), getLanguageFromFileName(), guessSection(), Doxygen::includeNameLinkedMap, Doxygen::inputNameLinkedMap, and QCString::str().

Referenced by findFile(), and Preprocessor::processFile().

◆ skipCommentMacroName()

void skipCommentMacroName ( yyscan_t yyscanner,
const QCString & expr,
QCString * rest,
int & cc,
uint32_t & j,
int & len )
static

Definition at line 2617 of file pre.l.

2619{
2620 bool changed = false;
2621
2622 do
2623 {
2624 changed = false;
2625 while ((cc=getCurrentChar(yyscanner,expr,rest,j))!=EOF && cc!='\n' && isspace(cc))
2626 {
2627 len++;
2628 getNextChar(yyscanner,expr,rest,j);
2629 }
2630
2631 if (cc=='/') // possible start of a comment
2632 {
2633 int prevChar = '\0';
2634 getNextChar(yyscanner,expr,rest,j);
2635 if ((cc=getCurrentChar(yyscanner,expr,rest,j))!=EOF && cc == '*') // we have a comment
2636 {
2637 while ((cc=getNextChar(yyscanner,expr,rest,j))!=EOF && cc!=0)
2638 {
2639 if (cc == '/' && prevChar == '*') break; // we have an end of comment
2640 prevChar = cc;
2641 }
2642 if (cc != EOF) changed = true;
2643 }
2644 }
2645 } while (changed);
2646}

References getCurrentChar(), and getNextChar().

Referenced by replaceFunctionMacro().

◆ startCondSection()

void startCondSection ( yyscan_t yyscanner,
const QCString & sectId )
static

Definition at line 3833 of file pre.l.

3834{
3835 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
3836 //printf("startCondSection: skip=%d stack=%d\n",state->skip,state->condStack.size());
3837 CondParser prs;
3838 bool expResult = prs.parse(state->fileName.data(),state->yyLineNr,sectId.data());
3839 state->condStack.emplace(std::make_unique<preYY_CondCtx>(state->fileName,state->yyLineNr,sectId,state->skip));
3840 if (!expResult)
3841 {
3842 state->skip=TRUE;
3843 }
3844 //printf(" expResult=%d skip=%d\n",expResult,state->skip);
Copyright (C) 1997-2015 by Dimitri van Heesch.
Definition condparser.h:28
bool parse(const QCString &fileName, int lineNr, const QCString &expr)
Copyright (C) 1997-2015 by Dimitri van Heesch.
3845}

References QCString::data(), CondParser::parse(), and TRUE.

◆ stateToString()

const char * stateToString ( int state)
static

◆ stringize()

QCString stringize ( const QCString & s)
static

Definition at line 2467 of file pre.l.

2468{
2469 QCString result;
2470 uint32_t i=0;
2471 bool inString=FALSE;
2472 bool inChar=FALSE;
2473 char c,pc;
2474 while (i<s.length())
2475 {
2476 if (!inString && !inChar)
2477 {
2478 while (i<s.length() && !inString && !inChar)
2479 {
2480 c=s.at(i++);
2481 if (c=='"')
2482 {
2483 result+="\\\"";
2484 inString=TRUE;
2485 }
2486 else if (c=='\'')
2487 {
2488 result+=c;
2489 inChar=TRUE;
2490 }
2491 else
2492 {
2493 result+=c;
2494 }
2495 }
2496 }
2497 else if (inChar)
2498 {
2499 while (i<s.length() && inChar)
2500 {
2501 c=s.at(i++);
2502 if (c=='\'')
2503 {
2504 result+='\'';
2505 inChar=FALSE;
2506 }
2507 else if (c=='\\')
2508 {
2509 result+="\\\\";
2510 }
2511 else
2512 {
2513 result+=c;
2514 }
2515 }
2516 }
2517 else
2518 {
2519 pc=0;
2520 while (i<s.length() && inString)
2521 {
2522 c=s.at(i++);
2523 if (c=='"')
2524 {
2525 result+="\\\"";
2526 inString= pc=='\\';
2527 }
2528 else if (c=='\\')
2529 result+="\\\\";
2530 else
2531 result+=c;
2532 pc=c;
2533 }
2534 }
2535 }
2536 //printf("stringize '%s'->'%s'\n",qPrint(s),qPrint(result));
2537 return result;
2538}

References QCString::at(), FALSE, QCString::length(), and TRUE.

Referenced by replaceFunctionMacro().

◆ unputChar()

void unputChar ( yyscan_t yyscanner,
const QCString & expr,
QCString * rest,
uint32_t & pos,
char c )
static

Definition at line 3955 of file pre.l.

3956{
3957 //printf("unputChar(%s,%s,%d,%c)\n",qPrint(expr),rest ? rest->data() : 0,pos,c);
3958 if (pos<expr.length())
3959 {
3960 pos++;
3961 }
3962 else if (rest)
3963 {
3964 //printf(" prepending '%c' to rest!\n",c);
3965 char cs[2];cs[0]=c;cs[1]='\0';
3966 rest->prepend(cs);
3967 }
3968 else
3969 {
3970 //printf(" yyunput()='%c'\n",c);
3971 returnCharToStream(yyscanner,c);
3972 }
3973 //printf("result: unputChar(%s,%s,%d,%c)\n",qPrint(expr),rest ? rest->data() : 0,pos,c);
QCString & prepend(const char *s)
Definition qcstring.h:422
3974}

References QCString::length(), QCString::prepend(), and returnCharToStream().

Referenced by addSeparatorsIfNeeded(), and replaceFunctionMacro().

◆ yylex()

int yylex ( yyscan_t yyscanner)

Definition at line 485 of file pre.l.

490 { // Trigraph
491 unput(resolveTrigraph(yytext[2]));
492 }
static char resolveTrigraph(char c)
Definition pre.l:3889
493<Start>^{B}*"#" {
494 yyextra->yyColNr+=(int)yyleng;
495 yyextra->yyMLines=0;
496 yyextra->potentialDefine=yytext;
497 BEGIN(Command);
498 }
499<Start>^("%top{"|"%{") {
500 if (getLanguageFromFileName(yyextra->fileName)!=SrcLangExt::Lex) REJECT
501 outputArray(yyscanner,yytext,yyleng);
502 BEGIN(LexCopyLine);
503 }
static void outputArray(yyscan_t yyscanner, const char *a, yy_size_t len)
Definition pre.l:3605
504<Start>^{Bopt}"cpp_quote"{Bopt}"("{Bopt}\" {
505 if (yyextra->insideIDL)
506 {
507 BEGIN(IDLquote);
508 }
509 else
510 {
511 REJECT;
512 }
513 }
514<IDLquote>"\\\\" {
515 outputArray(yyscanner,"\\",1);
516 }
517<IDLquote>"\\\"" {
518 outputArray(yyscanner,"\"",1);
519 }
520<IDLquote>"\""{Bopt}")" {
521 BEGIN(Start);
522 }
523<IDLquote>\n {
524 outputChar(yyscanner,'\n');
525 yyextra->yyLineNr++;
526 }
527<IDLquote>. {
528 outputArray(yyscanner,yytext,yyleng);
529 }
530<Start>^{Bopt}/[^#] {
531 outputArray(yyscanner,yytext,yyleng);
532 BEGIN(CopyLine);
533 }
534<Start>^{B}*[a-z_A-Z\x80-\xFF][a-z_A-Z0-9\x80-\xFF]+{B}*"("[^\‍)\n]*")"/{BN}{1,10}*[:{] { // constructors?
535 int i;
536 for (i=(int)yyleng-1;i>=0;i--)
537 {
538 unput(yytext[i]);
539 }
540 BEGIN(CopyLine);
541 }
542<Start>^{B}*[_A-Z][_A-Z0-9]+{B}*"("[^\‍(\‍)\n]*"("[^\‍)\n]*")"[^\‍)\n]*")"{B}*\n | // function list macro with one (...) argument, e.g. for K_GLOBAL_STATIC_WITH_ARGS
543<Start>^{B}*[_A-Z][_A-Z0-9]+{B}*"("[^\‍)\n]*")"{B}*\n | // function like macro
544<Start>^{B}*[_A-Z][_A-Z0-9]+{B}*"("[^\‍(\‍)\n]*"("[^\‍)\n]*")"[^\‍)\n]*")"/{B}*("//"|"/\*") | // function list macro with one (...) argument followed by comment
545<Start>^{B}*[_A-Z][_A-Z0-9]+{B}*"("[^\‍)\n]*")"/{B}*("//"|"/\*") { // function like macro followed by comment
546 bool skipFuncMacros = Config_getBool(SKIP_FUNCTION_MACROS);
547 QCString name(yytext);
548 int pos = name.find('(');
549 if (pos<0) pos=0; // should never happen
550 name=name.left(pos).stripWhiteSpace();
#define Config_getBool(name)
Definition config.h:33
551
552 Define *def=nullptr;
553 if (skipFuncMacros && !yyextra->insideFtn &&
554 name!="Q_PROPERTY" &&
555 !(
556 (yyextra->includeStack.empty() || yyextra->curlyCount>0) &&
557 yyextra->macroExpansion &&
558 (def=isDefined(yyscanner,name)) &&
559 /*macroIsAccessible(def) &&*/
560 (!yyextra->expandOnlyPredef || def->isPredefined)
561 )
562 )
563 {
564 // Only when ends on \n
565 if (yytext[yyleng-1] == '\n')
566 {
567 outputChar(yyscanner,'\n');
568 yyextra->yyLineNr++;
569 }
570 }
571 else // don't skip
572 {
573 int i;
574 for (i=(int)yyleng-1;i>=0;i--)
575 {
576 unput(yytext[i]);
577 }
578 BEGIN(CopyLine);
579 }
580 }
581<CopyLine,LexCopyLine>"extern"{BN}*"\""[^\"]+"\""{BN}*("{")? {
582 QCString text=yytext;
583 yyextra->yyLineNr+=text.contains('\n');
584 outputArray(yyscanner,yytext,yyleng);
585 }
586<CopyLine,LexCopyLine>{RAWBEGIN} {
587 yyextra->delimiter = extractBeginRawStringDelimiter(yytext);
588 outputArray(yyscanner,yytext,yyleng);
589 BEGIN(CopyRawString);
590 }
QCString extractBeginRawStringDelimiter(const char *rawStart)
Definition util.cpp:6884
591<CopyLine,LexCopyLine>"{" { // count brackets inside the main file
592 if (yyextra->includeStack.empty())
593 {
594 yyextra->curlyCount++;
595 }
596 outputChar(yyscanner,*yytext);
597 }
598<LexCopyLine>^"%}" {
599 outputArray(yyscanner,yytext,yyleng);
600 }
601<CopyLine,LexCopyLine>"}" { // count brackets inside the main file
602 if (yyextra->includeStack.empty() && yyextra->curlyCount>0)
603 {
604 yyextra->curlyCount--;
605 }
606 outputChar(yyscanner,*yytext);
607 }
608<CopyLine,LexCopyLine>"'"\\‍[0-7]{1,3}"'" {
609 outputArray(yyscanner,yytext,yyleng);
610 }
611<CopyLine,LexCopyLine>"'"\\."'" {
612 outputArray(yyscanner,yytext,yyleng);
613 }
614<CopyLine,LexCopyLine>"'"."'" {
615 outputArray(yyscanner,yytext,yyleng);
616 }
617<CopyLine,LexCopyLine>[$]?@\" {
618 if (getLanguageFromFileName(yyextra->fileName)!=SrcLangExt::CSharp) REJECT;
619 outputArray(yyscanner,yytext,yyleng);
620 BEGIN( CopyStringCs );
621 }
622<CopyLine,LexCopyLine>\" {
623 outputChar(yyscanner,*yytext);
624 if (getLanguageFromFileName(yyextra->fileName)!=SrcLangExt::Fortran)
625 {
626 BEGIN( CopyString );
627 }
628 else
629 {
630 BEGIN( CopyStringFtnDouble );
631 }
632 }
633<CopyLine,LexCopyLine>\' {
634 if (getLanguageFromFileName(yyextra->fileName)!=SrcLangExt::Fortran) REJECT;
635 outputChar(yyscanner,*yytext);
636 BEGIN( CopyStringFtn );
637 }
638<CopyString>[^\"\\\r\n]{1,1000} {
639 outputArray(yyscanner,yytext,yyleng);
640 }
641<CopyStringCs>[^\"\r\n]{1,1000} {
642 outputArray(yyscanner,yytext,yyleng);
643 }
644<CopyStringCs>\"\" {
645 outputArray(yyscanner,yytext,yyleng);
646 }
647<CopyString>\\. {
648 outputArray(yyscanner,yytext,yyleng);
649 }
650<CopyString,CopyStringCs>\" {
651 outputChar(yyscanner,*yytext);
652 BEGIN( CopyLine );
653 }
654<CopyStringFtnDouble>[^\"\\\r\n]{1,1000} {
655 outputArray(yyscanner,yytext,yyleng);
656 }
657<CopyStringFtnDouble>\\. {
658 outputArray(yyscanner,yytext,yyleng);
659 }
660<CopyStringFtnDouble>\" {
661 outputChar(yyscanner,*yytext);
662 BEGIN( CopyLine );
663 }
664<CopyStringFtn>[^\'\\\r\n]{1,1000} {
665 outputArray(yyscanner,yytext,yyleng);
666 }
667<CopyStringFtn>\\. {
668 outputArray(yyscanner,yytext,yyleng);
669 }
670<CopyStringFtn>\' {
671 outputChar(yyscanner,*yytext);
672 BEGIN( CopyLine );
673 }
674<CopyRawString>{RAWEND} {
675 outputArray(yyscanner,yytext,yyleng);
676 if (extractEndRawStringDelimiter(yytext)==yyextra->delimiter)
677 {
678 BEGIN( CopyLine );
679 }
680 }
QCString extractEndRawStringDelimiter(const char *rawEnd)
Definition util.cpp:6892
681<CopyRawString>[^)]{1,1000} {
682 outputArray(yyscanner,yytext,yyleng);
683 }
684<CopyRawString>. {
685 outputChar(yyscanner,*yytext);
686 }
687<CopyLine,LexCopyLine>{ID}/{BN}{0,80}"(" {
688 yyextra->expectGuard = FALSE;
689 Define *def=nullptr;
690 //def=yyextra->globalDefineDict->find(yytext);
691 //def=isDefined(yyscanner,yytext);
692 //printf("Search for define %s found=%d yyextra->includeStack.empty()=%d "
693 // "yyextra->curlyCount=%d yyextra->macroExpansion=%d yyextra->expandOnlyPredef=%d "
694 // "isPreDefined=%d\n",yytext,def ? 1 : 0,
695 // yyextra->includeStack.empty(),yyextra->curlyCount,yyextra->macroExpansion,yyextra->expandOnlyPredef,
696 // def ? def->isPredefined : -1
697 // );
698 if ((yyextra->includeStack.empty() || yyextra->curlyCount>0) &&
699 yyextra->macroExpansion &&
700 (def=isDefined(yyscanner,yytext)) &&
701 (!yyextra->expandOnlyPredef || def->isPredefined)
702 )
703 {
704 //printf("Found it! #args=%d\n",def->nargs);
705 yyextra->roundCount=0;
706 yyextra->defArgsStr=yytext;
707 if (def->nargs==-1) // no function macro
708 {
709 QCString result = def->isPredefined && !def->expandAsDefined ?
710 def->definition :
711 expandMacro(yyscanner,yyextra->defArgsStr);
712 outputString(yyscanner,result);
713 }
714 else // zero or more arguments
715 {
716 yyextra->findDefArgContext = CopyLine;
717 BEGIN(FindDefineArgs);
718 }
719 }
720 else
721 {
722 outputArray(yyscanner,yytext,yyleng);
723 }
724 }
static QCString expandMacro(yyscan_t yyscanner, const QCString &name)
Definition pre.l:3512
725<CopyLine>{RulesDelim} {
726 if (getLanguageFromFileName(yyextra->fileName)!=SrcLangExt::Lex) REJECT;
727 yyextra->lexRulesPart = !yyextra->lexRulesPart;
728 outputArray(yyscanner,yytext,yyleng);
729 }
730 /* start lex rule handling */
731<CopyLine>{RulesSharp} {
732 if (!yyextra->lexRulesPart) REJECT;
733 if (yyextra->curlyCount) REJECT;
734 outputArray(yyscanner,yytext,yyleng);
735 BEGIN(RulesPattern);
736 }
737<RulesPattern>{EscapeRulesChar} {
738 outputArray(yyscanner,yytext,yyleng);
739 }
740<RulesPattern>{RulesCurly} {
741 outputArray(yyscanner,yytext,yyleng);
742 }
743<RulesPattern>{StartDouble} {
744 outputArray(yyscanner,yytext,yyleng);
745 yyextra->lastContext = YY_START;
746 BEGIN(RulesDouble);
747 }
748<RulesDouble,RulesRoundDouble>"\\\\" {
749 outputArray(yyscanner,yytext,yyleng);
750 }
751<RulesDouble,RulesRoundDouble>"\\\"" {
752 outputArray(yyscanner,yytext,yyleng);
753 }
754<RulesDouble>"\"" {
755 outputArray(yyscanner,yytext,yyleng);
756 BEGIN( yyextra->lastContext ) ;
757 }
758<RulesRoundDouble>"\"" {
759 outputArray(yyscanner,yytext,yyleng);
760 BEGIN(RulesRound) ;
761 }
762<RulesDouble,RulesRoundDouble>. {
763 outputArray(yyscanner,yytext,yyleng);
764 }
765<RulesPattern>{StartSquare} {
766 outputArray(yyscanner,yytext,yyleng);
767 yyextra->lastContext = YY_START;
768 BEGIN(RulesSquare);
769 }
770<RulesSquare,RulesRoundSquare>{CHARCE} {
771 outputArray(yyscanner,yytext,yyleng);
772 }
773<RulesSquare,RulesRoundSquare>"\\‍[" |
774<RulesSquare,RulesRoundSquare>"\\‍]" {
775 outputArray(yyscanner,yytext,yyleng);
776 }
777<RulesSquare>"]" {
778 outputArray(yyscanner,yytext,yyleng);
779 BEGIN(RulesPattern);
780 }
781<RulesRoundSquare>"]" {
782 outputArray(yyscanner,yytext,yyleng);
783 BEGIN(RulesRound) ;
784 }
785<RulesSquare,RulesRoundSquare>"\\\\" {
786 outputArray(yyscanner,yytext,yyleng);
787 }
788<RulesSquare,RulesRoundSquare>. {
789 outputArray(yyscanner,yytext,yyleng);
790 }
791<RulesPattern>{StartRoundQuest} {
792 outputArray(yyscanner,yytext,yyleng);
793 yyextra->lastContext = YY_START;
794 BEGIN(RulesRoundQuest);
795 }
796<RulesRoundQuest>{nl} {
797 outputArray(yyscanner,yytext,yyleng);
798 }
799<RulesRoundQuest>[^)] {
800 outputArray(yyscanner,yytext,yyleng);
801 }
802<RulesRoundQuest>")" {
803 outputArray(yyscanner,yytext,yyleng);
804 BEGIN(yyextra->lastContext);
805 }
806<RulesPattern>{StartRound} {
807 yyextra->roundCount++;
808 outputArray(yyscanner,yytext,yyleng);
809 yyextra->lastContext = YY_START;
810 BEGIN(RulesRound);
811 }
812<RulesRound>{RulesCurly} {
813 outputArray(yyscanner,yytext,yyleng);
814 }
815<RulesRound>{StartSquare} {
816 outputArray(yyscanner,yytext,yyleng);
817 BEGIN(RulesRoundSquare);
818 }
819<RulesRound>{StartDouble} {
820 outputArray(yyscanner,yytext,yyleng);
821 BEGIN(RulesRoundDouble);
822 }
823<RulesRound>{EscapeRulesChar} {
824 outputArray(yyscanner,yytext,yyleng);
825 }
826<RulesRound>"(" {
827 yyextra->roundCount++;
828 outputArray(yyscanner,yytext,yyleng);
829 }
830<RulesRound>")" {
831 yyextra->roundCount--;
832 outputArray(yyscanner,yytext,yyleng);
833 if (!yyextra->roundCount) BEGIN( yyextra->lastContext ) ;
834 }
835<RulesRound>{nl} {
836 outputArray(yyscanner,yytext,yyleng);
837 }
838<RulesRound>{B} {
839 outputArray(yyscanner,yytext,yyleng);
840 }
841<RulesRound>. {
842 outputArray(yyscanner,yytext,yyleng);
843 }
844<RulesPattern>{B} {
845 outputArray(yyscanner,yytext,yyleng);
846 BEGIN(CopyLine);
847 }
848<RulesPattern>. {
849 outputArray(yyscanner,yytext,yyleng);
850 }
851 /* end lex rule handling */
852<CopyLine,LexCopyLine>{ID} {
853 Define *def=nullptr;
854 if ((yyextra->includeStack.empty() || yyextra->curlyCount>0) &&
855 yyextra->macroExpansion &&
856 (def=isDefined(yyscanner,yytext)) &&
857 def->nargs==-1 &&
858 (!yyextra->expandOnlyPredef || def->isPredefined)
859 )
860 {
861 QCString result=def->isPredefined && !def->expandAsDefined ?
862 def->definition :
863 expandMacro(yyscanner,yytext);
864 outputString(yyscanner,result);
865 }
866 else
867 {
868 outputArray(yyscanner,yytext,yyleng);
869 }
870 }
871<CopyLine,LexCopyLine>"\\"\r?/\n { // strip line continuation characters
872 if (getLanguageFromFileName(yyextra->fileName)==SrcLangExt::Fortran) outputChar(yyscanner,*yytext);
873 }
874<CopyLine,LexCopyLine>\\. {
875 outputArray(yyscanner,yytext,(int)yyleng);
876 }
877<CopyLine,LexCopyLine>. {
878 outputChar(yyscanner,*yytext);
879 }
880<CopyLine,LexCopyLine>\n {
881 outputChar(yyscanner,'\n');
882 BEGIN(Start);
883 yyextra->yyLineNr++;
884 yyextra->yyColNr=1;
885 }
886<FindDefineArgs>"(" {
887 yyextra->defArgsStr+='(';
888 yyextra->roundCount++;
889 }
890<FindDefineArgs>")" {
891 yyextra->defArgsStr+=')';
892 yyextra->roundCount--;
893 if (yyextra->roundCount==0)
894 {
895 QCString result=expandMacro(yyscanner,yyextra->defArgsStr);
896 //printf("yyextra->defArgsStr='%s'->'%s'\n",qPrint(yyextra->defArgsStr),qPrint(result));
897 if (yyextra->findDefArgContext==CopyLine)
898 {
899 outputString(yyscanner,result);
900 BEGIN(yyextra->findDefArgContext);
901 }
902 else // yyextra->findDefArgContext==IncludeID
903 {
904 readIncludeFile(yyscanner,result);
905 yyextra->nospaces=FALSE;
906 BEGIN(Start);
907 }
908 }
909 }
910 /*
static void readIncludeFile(yyscan_t yyscanner, const QCString &inc)
Definition pre.l:3680
911<FindDefineArgs>")"{B}*"(" {
912 yyextra->defArgsStr+=yytext;
913 }
914 */
915<FindDefineArgs>{CHARLIT} {
916 yyextra->defArgsStr+=yytext;
917 }
918<FindDefineArgs>{CCS}[*!]? {
919 yyextra->defArgsStr+=yytext;
920 BEGIN(ArgCopyCComment);
921 }
922<FindDefineArgs>{CPPC}[/!].*\n/{B}*{CPPC}[/!] { // replace multi line C++ style comment by C style comment
923 if (Config_getBool(MULTILINE_CPP_IS_BRIEF) && !Config_getBool(QT_AUTOBRIEF))
924 {
925 if (yytext[3]=='<') // preserve < before @brief
926 {
927 yyextra->defArgsStr+=QCString("/**< @brief ")+&yytext[4];
928 }
929 else
930 {
931 yyextra->defArgsStr+=QCString("/** @brief ")+&yytext[3];
932 }
933 }
934 else
935 {
936 yyextra->defArgsStr+=QCString("/**")+&yytext[3];
937 }
938 BEGIN(ArgCopyCppComment);
939 }
940<FindDefineArgs>{CPPC}[/!].*\n { // replace C++ single line style comment by C style comment
941 if (Config_getBool(QT_AUTOBRIEF))
942 {
943 yyextra->defArgsStr+=QCString("/**")+&yytext[3]+" */";
944 }
945 else // add brief command explicitly when translating C++ to C comment style
946 {
947 if (yytext[3]=='<') // preserve < before @brief
948 {
949 yyextra->defArgsStr+=QCString("/**< @brief ")+&yytext[4]+" */";
950 }
951 else
952 {
953 yyextra->defArgsStr+=QCString("/** @brief ")+&yytext[3]+" */";
954 }
955 }
956 }
957<FindDefineArgs>{CPPC}.*\n { // replace C++ single line style comment by C style comment
958 yyextra->defArgsStr+=QCString("/*")+&yytext[2]+" */";
959 }
960<FindDefineArgs>\" {
961 yyextra->defArgsStr+=*yytext;
962 BEGIN(ReadString);
963 }
964<FindDefineArgs>' {
965 if (getLanguageFromFileName(yyextra->fileName)!=SrcLangExt::Fortran) REJECT;
966 yyextra->defArgsStr+=*yytext;
967 BEGIN(ReadString);
968 }
969<FindDefineArgs>\n {
970 yyextra->defArgsStr+=' ';
971 yyextra->yyLineNr++;
972 outputChar(yyscanner,'\n');
973 }
974<FindDefineArgs>"@" {
975 yyextra->defArgsStr+="@@";
976 }
977<FindDefineArgs>. {
978 yyextra->defArgsStr+=*yytext;
979 }
980<ArgCopyCComment>[^*\n]+ {
981 yyextra->defArgsStr+=yytext;
982 }
983<ArgCopyCComment>{CCE} {
984 yyextra->defArgsStr+=yytext;
985 BEGIN(FindDefineArgs);
986 }
987<ArgCopyCComment>\n {
988 yyextra->defArgsStr+=yytext;
989 yyextra->yyLineNr++;
990 }
991<ArgCopyCComment>. {
992 yyextra->defArgsStr+=yytext;
993 }
994<ArgCopyCppComment>^{B}*
995<ArgCopyCppComment>{CPPC}[/!].*\n/{B}*{CPPC}[/!] { // replace multi line C++ style comment by C style comment
996 const char *startContent = &yytext[3];
997 if (startContent[0]=='<') startContent++;
998 yyextra->defArgsStr+=startContent;
999 }
1000<ArgCopyCppComment>{CPPC}[/!].*\n { // replace C++ multie line style comment by C style comment
1001 const char *startContent = &yytext[3];
1002 if (startContent[0]=='<') startContent++;
1003 yyextra->defArgsStr+=QCString(startContent)+" */";
1004 BEGIN(FindDefineArgs);
1005 }
1006<ArgCopyCppComment>. { // unexpected character
1007 unput(*yytext);
1008 yyextra->defArgsStr+=" */";
1009 BEGIN(FindDefineArgs);
1010 }
1011<ReadString>"\"" {
1012 yyextra->defArgsStr+=*yytext;
1013 BEGIN(FindDefineArgs);
1014 }
1015<ReadString>"'" {
1016 if (getLanguageFromFileName(yyextra->fileName)!=SrcLangExt::Fortran) REJECT;
1017 yyextra->defArgsStr+=*yytext;
1018 BEGIN(FindDefineArgs);
1019 }
1020
1021<ReadString>{CPPC}|{CCS} {
1022 yyextra->defArgsStr+=yytext;
1023 }
1024<ReadString>\\/\r?\n { // line continuation
1025 }
1026<ReadString>\\. {
1027 yyextra->defArgsStr+=yytext;
1028 }
1029<ReadString>. {
1030 yyextra->defArgsStr+=*yytext;
1031 }
1032<Command>("include"|"import"){B}+/{ID} {
1033 yyextra->isImported = yytext[1]=='m';
1034 if (yyextra->macroExpansion)
1035 BEGIN(IncludeID);
1036 }
1037<Command>("include"|"import"){B}*[<"] {
1038 yyextra->isImported = yytext[1]=='m';
1039 char c[2];
1040 c[0]=yytext[yyleng-1];c[1]='\0';
1041 yyextra->incName=c;
1042 BEGIN(Include);
1043 }
1044<Command>("cmake")?"define"{B}+ {
1045 yyextra->potentialDefine += substitute(yytext,"cmake"," ");
1046 //printf("!!!DefName\n");
1047 yyextra->yyColNr+=(int)yyleng;
1048 BEGIN(DefName);
1049 }
QCString substitute(const QCString &s, const QCString &src, const QCString &dst)
substitute all occurrences of src in s by dst
Definition qcstring.cpp:571
1050<Command>"cmakedefine01"{B}+ {
1051 yyextra->potentialDefine += substitute(yytext,"cmakedefine01"," define ");
1052 //printf("!!!DefName\n");
1053 yyextra->yyColNr+=(int)yyleng;
1054 BEGIN(CmakeDefName01);
1055 }
1056<Command>"ifdef"/{B}*"(" {
1057 incrLevel(yyscanner);
1058 yyextra->guardExpr.clear();
1059 BEGIN(DefinedExpr2);
1060 }
static void incrLevel(yyscan_t yyscanner)
Definition pre.l:2244
1061<Command>"ifdef"/{B}+ {
1062 //printf("Pre.l: ifdef\n");
1063 incrLevel(yyscanner);
1064 yyextra->guardExpr.clear();
1065 BEGIN(DefinedExpr1);
1066 }
1067<Command>"ifndef"/{B}*"(" {
1068 incrLevel(yyscanner);
1069 yyextra->guardExpr="! ";
1070 BEGIN(DefinedExpr2);
1071 }
1072<Command>"ifndef"/{B}+ {
1073 incrLevel(yyscanner);
1074 yyextra->guardExpr="! ";
1075 BEGIN(DefinedExpr1);
1076 }
1077<Command>"if"/[ \t(!] {
1078 incrLevel(yyscanner);
1079 yyextra->guardExpr.clear();
1080 BEGIN(Guard);
1081 }
1082<Command>("elif"|"else"{B}*"if")/[ \t(!] {
1083 if (!otherCaseDone(yyscanner))
1084 {
1085 yyextra->guardExpr.clear();
1086 BEGIN(Guard);
1087 }
1088 else
1089 {
1090 yyextra->ifcount=0;
1091 BEGIN(SkipCPPBlock);
1092 }
1093 }
static bool otherCaseDone(yyscan_t yyscanner)
Definition pre.l:2265
1094<Command>"else"/[^a-z_A-Z0-9\x80-\xFF] {
1095 if (otherCaseDone(yyscanner))
1096 {
1097 yyextra->ifcount=0;
1098 BEGIN(SkipCPPBlock);
1099 }
1100 else
1101 {
1102 setCaseDone(yyscanner,TRUE);
1103 }
1104 }
static void setCaseDone(yyscan_t yyscanner, bool value)
Definition pre.l:2279
1105<Command>"undef"{B}+ {
1106 BEGIN(UndefName);
1107 }
1108<Command>("elif"|"else"{B}*"if")/[ \t(!] {
1109 if (!otherCaseDone(yyscanner))
1110 {
1111 yyextra->guardExpr.clear();
1112 BEGIN(Guard);
1113 }
1114 }
1115<Command>"endif"/[^a-z_A-Z0-9\x80-\xFF] {
1116 //printf("Pre.l: #endif\n");
1117 decrLevel(yyscanner);
1118 }
static void decrLevel(yyscan_t yyscanner)
Definition pre.l:2251
1119<Command,IgnoreLine>\n {
1120 outputChar(yyscanner,'\n');
1121 BEGIN(Start);
1122 yyextra->yyLineNr++;
1123 }
1124<Command>"pragma"{B}+"once" {
1125 yyextra->expectGuard = FALSE;
1126 if (yyextra->pragmaSet.find(yyextra->fileName.str())!=yyextra->pragmaSet.end())
1127 {
1128 outputChar(yyscanner,'\n');
1129 BEGIN(PragmaOnce);
1130 }
1131 else
1132 {
1133 yyextra->pragmaSet.insert(yyextra->fileName.data());
1134 }
1135 }
1136<PragmaOnce>. {}
1137<PragmaOnce>\n {}
1138<PragmaOnce><<EOF>> {
1139 yyextra->expectGuard = FALSE;
1140 BEGIN(Start);
1141 }
1142<Command>{ID} { // unknown directive
1143 BEGIN(IgnoreLine);
1144 }
1145<IgnoreLine>\\‍[\r]?\n {
1146 outputChar(yyscanner,'\n');
1147 yyextra->yyLineNr++;
1148 }
1149<IgnoreLine>.
1150<Command>. { yyextra->potentialDefine += yytext[0]=='\t' ? '\t' : ' ';
1151 yyextra->yyColNr+=(int)yyleng;
1152 }
1153<UndefName>{ID} {
1154 Define *def;
1155 if ((def=isDefined(yyscanner,yytext))
1156 /*&& !def->isPredefined*/
1157 && !def->nonRecursive
1158 )
1159 {
1160 //printf("undefining %s\n",yytext);
1161 def->undef=TRUE;
1162 }
1163 BEGIN(Start);
1164 }
1165<Guard>\\‍[\r]?\n {
1166 outputChar(yyscanner,'\n');
1167 yyextra->guardExpr+=' ';
1168 yyextra->yyLineNr++;
1169 }
1170<Guard>"defined"/{B}*"(" {
1171 BEGIN(DefinedExpr2);
1172 }
1173<Guard>"defined"/{B}+ {
1174 BEGIN(DefinedExpr1);
1175 }
1176<Guard>"true"/{B}|{B}*[\r]?\n { yyextra->guardExpr+="1L"; }
1177<Guard>"false"/{B}|{B}*[\r]?\n { yyextra->guardExpr+="0L"; }
1178<Guard>"not"/{B} { yyextra->guardExpr+='!'; }
1179<Guard>"not_eq"/{B} { yyextra->guardExpr+="!="; }
1180<Guard>"and"/{B} { yyextra->guardExpr+="&&"; }
1181<Guard>"or"/{B} { yyextra->guardExpr+="||"; }
1182<Guard>"bitand"/{B} { yyextra->guardExpr+="&"; }
1183<Guard>"bitor"/{B} { yyextra->guardExpr+="|"; }
1184<Guard>"xor"/{B} { yyextra->guardExpr+="^"; }
1185<Guard>"compl"/{B} { yyextra->guardExpr+="~"; }
1186<Guard>{ID} { yyextra->guardExpr+=yytext; }
1187<Guard>"@" { yyextra->guardExpr+="@@"; }
1188<Guard>. { yyextra->guardExpr+=*yytext; }
1189<Guard>\n {
1190 unput(*yytext);
1191 //printf("Guard: '%s'\n",
1192 // qPrint(yyextra->guardExpr));
1193 bool guard=computeExpression(yyscanner,yyextra->guardExpr);
1194 setCaseDone(yyscanner,guard);
1195 if (guard)
1196 {
1197 BEGIN(Start);
1198 }
1199 else
1200 {
1201 yyextra->ifcount=0;
1202 BEGIN(SkipCPPBlock);
1203 }
1204 }
static bool computeExpression(yyscan_t yyscanner, const QCString &expr)
Definition pre.l:3493
1205<DefinedExpr1,DefinedExpr2>\\\n { yyextra->yyLineNr++; outputChar(yyscanner,'\n'); }
1206<DefinedExpr1>{ID} {
1207 if (isDefined(yyscanner,yytext) || yyextra->guardName==yytext)
1208 yyextra->guardExpr+=" 1L ";
1209 else
1210 yyextra->guardExpr+=" 0L ";
1211 yyextra->lastGuardName=yytext;
1212 BEGIN(Guard);
1213 }
1214<DefinedExpr2>{ID} {
1215 if (isDefined(yyscanner,yytext) || yyextra->guardName==yytext)
1216 yyextra->guardExpr+=" 1L ";
1217 else
1218 yyextra->guardExpr+=" 0L ";
1219 yyextra->lastGuardName=yytext;
1220 }
1221<DefinedExpr1,DefinedExpr2>\n { // should not happen, handle anyway
1222 yyextra->yyLineNr++;
1223 yyextra->ifcount=0;
1224 BEGIN(SkipCPPBlock);
1225 }
1226<DefinedExpr2>")" {
1227 BEGIN(Guard);
1228 }
1229<DefinedExpr1,DefinedExpr2>.
1230<SkipCPPBlock>^{B}*"#" { BEGIN(SkipCommand); }
1231<SkipCPPBlock>^{Bopt}/[^#] { BEGIN(SkipLine); }
1232<SkipCPPBlock>\n { yyextra->yyLineNr++; outputChar(yyscanner,'\n'); }
1233<SkipCPPBlock>.
1234<SkipCommand>"if"(("n")?("def"))?/[ \t(!] {
1235 incrLevel(yyscanner);
1236 yyextra->ifcount++;
1237 //printf("#if... depth=%d\n",yyextra->ifcount);
1238 }
1239<SkipCommand>"else" {
1240 //printf("Else! yyextra->ifcount=%d otherCaseDone=%d\n",yyextra->ifcount,otherCaseDone());
1241 if (yyextra->ifcount==0 && !otherCaseDone(yyscanner))
1242 {
1243 setCaseDone(yyscanner,TRUE);
1244 //outputChar(yyscanner,'\n');
1245 BEGIN(Start);
1246 }
1247 }
1248<SkipCommand>("elif"|"else"{B}*"if")/[ \t(!] {
1249 if (yyextra->ifcount==0)
1250 {
1251 if (!otherCaseDone(yyscanner))
1252 {
1253 yyextra->guardExpr.clear();
1254 yyextra->lastGuardName.clear();
1255 BEGIN(Guard);
1256 }
1257 else
1258 {
1259 BEGIN(SkipCPPBlock);
1260 }
1261 }
1262 }
1263<SkipCommand>"endif" {
1264 yyextra->expectGuard = FALSE;
1265 decrLevel(yyscanner);
1266 if (--yyextra->ifcount<0)
1267 {
1268 //outputChar(yyscanner,'\n');
1269 BEGIN(Start);
1270 }
1271 }
1272<SkipCommand>\n {
1273 outputChar(yyscanner,'\n');
1274 yyextra->yyLineNr++;
1275 BEGIN(SkipCPPBlock);
1276 }
1277<SkipCommand>{ID} { // unknown directive
1278 BEGIN(SkipLine);
1279 }
1280<SkipCommand>.
1281<SkipLine>[^'"/\n]+
1282<SkipLine>{CHARLIT} { }
1283<SkipLine>\" {
1284 BEGIN(SkipString);
1285 }
1286<SkipLine>.
1287<SkipString>{CPPC}/[^\n]* {
1288 }
1289<SkipLine,SkipCommand,SkipCPPBlock>{CPPC}[^\n]* {
1290 yyextra->lastCPPContext=YY_START;
1291 BEGIN(RemoveCPPComment);
1292 }
1293<SkipString>{CCS}/[^\n]* {
1294 }
1295<SkipLine,SkipCommand,SkipCPPBlock>{CCS}/[^\n]* {
1296 yyextra->lastCContext=YY_START;
1297 BEGIN(RemoveCComment);
1298 }
1299<SkipLine>\n {
1300 outputChar(yyscanner,'\n');
1301 yyextra->yyLineNr++;
1302 BEGIN(SkipCPPBlock);
1303 }
1304<SkipString>[^"\\\n]+ { }
1305<SkipString>\\. { }
1306<SkipString>\" {
1307 BEGIN(SkipLine);
1308 }
1309<SkipString>. { }
1310<IncludeID>{ID}{Bopt}/"(" {
1311 yyextra->nospaces=TRUE;
1312 yyextra->roundCount=0;
1313 yyextra->defArgsStr=yytext;
1314 yyextra->findDefArgContext = IncludeID;
1315 BEGIN(FindDefineArgs);
1316 }
1317<IncludeID>{ID} {
1318 yyextra->nospaces=TRUE;
1319 readIncludeFile(yyscanner,expandMacro(yyscanner,yytext));
1320 BEGIN(Start);
1321 }
1322<Include>[^\">\n]+[\">] {
1323 yyextra->incName+=yytext;
1324 if (yyextra->isImported)
1325 {
1326 BEGIN(EndImport);
1327 }
1328 else
1329 {
1330 readIncludeFile(yyscanner,yyextra->incName);
1331 BEGIN(Start);
1332 }
1333 }
1334<EndImport>{ENDIMPORTopt}/\n {
1335 readIncludeFile(yyscanner,yyextra->incName);
1336 BEGIN(Start);
1337 }
1338<EndImport>\\‍[\r]?"\n" {
1339 outputChar(yyscanner,'\n');
1340 yyextra->yyLineNr++;
1341 }
1342<EndImport>. {
1343 }
1344<DefName>{ID}/("\\\n")*"(" { // define with argument
1345 //printf("Define() '%s'\n",yytext);
1346 yyextra->argMap.clear();
1347 yyextra->defArgs = 0;
1348 yyextra->defArgsStr.clear();
1349 yyextra->defText.clear();
1350 yyextra->defLitText.clear();
1351 yyextra->defName = yytext;
1352 yyextra->defVarArgs = FALSE;
1353 yyextra->defExtraSpacing.clear();
1354 yyextra->defContinue = false;
1355 BEGIN(DefineArg);
1356 }
1357<DefName>{ID}{B}+"1"/[ \r\t\n] { // special case: define with 1 -> can be "guard"
1358 //printf("Define '%s'\n",yytext);
1359 yyextra->argMap.clear();
1360 yyextra->defArgs = -1;
1361 yyextra->defArgsStr.clear();
1362 yyextra->defName = QCString(yytext).left(yyleng-1).stripWhiteSpace();
1363 yyextra->defVarArgs = FALSE;
1364 //printf("Guard check: %s!=%s || %d\n",
1365 // qPrint(yyextra->defName),qPrint(yyextra->lastGuardName),yyextra->expectGuard);
1366 if (yyextra->curlyCount>0 || yyextra->defName!=yyextra->lastGuardName || !yyextra->expectGuard)
1367 { // define may appear in the output
1368 QCString def = yyextra->potentialDefine +
1369 yyextra->defName ;
1370 outputString(yyscanner,def);
1371 outputSpaces(yyscanner,yytext+yyextra->defName.length());
1372 yyextra->quoteArg=FALSE;
1373 yyextra->insideComment=FALSE;
1374 yyextra->lastGuardName.clear();
1375 yyextra->defText="1";
1376 yyextra->defLitText="1";
1377 BEGIN(DefineText);
1378 }
1379 else // define is a guard => hide
1380 {
1381 //printf("Found a guard %s\n",yytext);
1382 yyextra->defText.clear();
1383 yyextra->defLitText.clear();
1384 BEGIN(Start);
1385 }
1386 yyextra->expectGuard=FALSE;
1387 }
static void outputSpaces(yyscan_t yyscanner, char *s)
Definition pre.l:3623
1388<DefName,CmakeDefName01>{ID}/{B}*"\n" { // empty define
1389 yyextra->argMap.clear();
1390 yyextra->defArgs = -1;
1391 yyextra->defName = yytext;
1392 yyextra->defArgsStr.clear();
1393 yyextra->defText.clear();
1394 yyextra->defLitText.clear();
1395 yyextra->defVarArgs = FALSE;
1396 //printf("Guard check: %s!=%s || %d\n",
1397 // qPrint(yyextra->defName),qPrint(yyextra->lastGuardName),yyextra->expectGuard);
1398 if (yyextra->curlyCount>0 || yyextra->defName!=yyextra->lastGuardName || !yyextra->expectGuard)
1399 { // define may appear in the output
1400 QCString def = yyextra->potentialDefine + yyextra->defName;
1401 outputString(yyscanner,def);
1402 yyextra->quoteArg=FALSE;
1403 yyextra->insideComment=FALSE;
1404 if (YY_START == CmakeDefName01) yyextra->defText = "0";
1405 else if (yyextra->insideCS) yyextra->defText="1"; // for C#, use "1" as define text
1406 BEGIN(DefineText);
1407 }
1408 else // define is a guard => hide
1409 {
1410 //printf("Found a guard %s\n",yytext);
1411 yyextra->guardName = yytext;
1412 yyextra->lastGuardName.clear();
1413 BEGIN(Start);
1414 }
1415 yyextra->expectGuard=FALSE;
1416 }
1417<DefName>{ID}/{B}* { // define with content
1418 //printf("Define '%s'\n",yytext);
1419 yyextra->argMap.clear();
1420 yyextra->defArgs = -1;
1421 yyextra->defArgsStr.clear();
1422 yyextra->defText.clear();
1423 yyextra->defLitText.clear();
1424 yyextra->defName = yytext;
1425 yyextra->defVarArgs = FALSE;
1426 QCString def = yyextra->potentialDefine +
1427 yyextra->defName +
1428 yyextra->defArgsStr ;
1429 outputString(yyscanner,def);
1430 yyextra->quoteArg=FALSE;
1431 yyextra->insideComment=FALSE;
1432 BEGIN(DefineText);
1433 }
1434<DefineArg>"\\\n" {
1435 yyextra->defExtraSpacing+="\n";
1436 yyextra->defContinue = true;
1437 yyextra->yyLineNr++;
1438 }
1439<DefineArg>{B}* { yyextra->defExtraSpacing+=yytext; }
1440<DefineArg>","{B}* { yyextra->defArgsStr+=yytext; }
1441<DefineArg>"("{B}* { yyextra->defArgsStr+=yytext; }
1442<DefineArg>{B}*")"{B}* {
1443 extraSpacing(yyscanner);
1444 yyextra->defArgsStr+=yytext;
1445 QCString def = yyextra->potentialDefine +
1446 yyextra->defName +
1447 yyextra->defArgsStr +
1448 yyextra->defExtraSpacing ;
1449 outputString(yyscanner,def);
1450 yyextra->quoteArg=FALSE;
1451 yyextra->insideComment=FALSE;
1452 BEGIN(DefineText);
1453 }
static void extraSpacing(yyscan_t yyscanner)
Definition pre.l:3634
1454<DefineArg>"..." { // Variadic macro
1455 yyextra->defVarArgs = TRUE;
1456 yyextra->defArgsStr+=yytext;
1457 yyextra->argMap.emplace(std::string("__VA_ARGS__"),yyextra->defArgs);
1458 yyextra->defArgs++;
1459 }
1460<DefineArg>{ID}{B}*("..."?) {
1461 //printf("Define addArg(%s)\n",yytext);
1462 QCString argName=yytext;
1463 yyextra->defVarArgs = yytext[yyleng-1]=='.';
1464 if (yyextra->defVarArgs) // strip ellipsis
1465 {
1466 argName=argName.left(argName.length()-3);
1467 }
1468 argName = argName.stripWhiteSpace();
1469 yyextra->defArgsStr+=yytext;
1470 yyextra->argMap.emplace(toStdString(argName),yyextra->defArgs);
1471 yyextra->defArgs++;
1472 extraSpacing(yyscanner);
1473 }
1474 /*
1475<DefineText>"/ **"|"/ *!" {
1476 yyextra->defText+=yytext;
1477 yyextra->defLitText+=yytext;
1478 yyextra->insideComment=TRUE;
1479 }
1480<DefineText>"* /" {
1481 yyextra->defText+=yytext;
1482 yyextra->defLitText+=yytext;
1483 yyextra->insideComment=FALSE;
1484 }
1485 */
1486<DefineText>{CCS}[!*]? {
1487 yyextra->defText+=yytext;
1488 yyextra->defLitText+=yytext;
1489 yyextra->lastCContext=YY_START;
1490 yyextra->commentCount=1;
1491 BEGIN(CopyCComment);
1492 }
1493<DefineText>{CPPC}[!/]? {
1494 outputArray(yyscanner,yytext,yyleng);
1495 yyextra->lastCPPContext=YY_START;
1496 yyextra->defLitText+=' ';
1497 BEGIN(SkipCPPComment);
1498 }
1499<SkipCComment>[/]?{CCE} {
1500 if (yytext[0]=='/') outputChar(yyscanner,'/');
1501 outputChar(yyscanner,'*');outputChar(yyscanner,'/');
1502 if (--yyextra->commentCount<=0)
1503 {
1504 if (yyextra->lastCContext==Start)
1505 // small hack to make sure that ^... rule will
1506 // match when going to Start... Example: "/*...*/ some stuff..."
1507 {
1508 YY_CURRENT_BUFFER->yy_at_bol=1;
1509 }
1510 BEGIN(yyextra->lastCContext);
1511 }
1512 }
1513<SkipCComment>{CPPC}("/")* {
1514 outputArray(yyscanner,yytext,yyleng);
1515 }
1516<SkipCComment>{CCS} {
1517 outputChar(yyscanner,'/');outputChar(yyscanner,'*');
1518 //yyextra->commentCount++;
1519 }
1520<SkipCond>{CMD}{CMD} { }
1521<SkipCond>^({B}*"*"+)?{B}{0,3}"~~~"[~]* {
1522 bool markdownSupport = Config_getBool(MARKDOWN_SUPPORT);
1523 if (!markdownSupport || !yyextra->isSpecialComment)
1524 {
1525 REJECT;
1526 }
1527 else
1528 {
1529 yyextra->fenceChar='~';
1530 yyextra->fenceSize=(int)getFenceSize(yytext,yyleng);
1531 BEGIN(SkipCondVerbatim);
1532 }
1533 }
static yy_size_t getFenceSize(char *txt, yy_size_t leng)
Definition pre.l:2212
1534<SkipCond>^({B}*"*"+)?{B}{0,3}"```"[`]* {
1535 bool markdownSupport = Config_getBool(MARKDOWN_SUPPORT);
1536 if (!markdownSupport || !yyextra->isSpecialComment)
1537 {
1538 REJECT;
1539 }
1540 else
1541 {
1542 yyextra->fenceChar='`';
1543 yyextra->fenceSize=(int)getFenceSize(yytext,yyleng);
1544 BEGIN(SkipCondVerbatim);
1545 }
1546 }
1547<SkipCComment>^({B}*"*"+)?{B}{0,3}"~~~"[~]* {
1548 bool markdownSupport = Config_getBool(MARKDOWN_SUPPORT);
1549 if (!markdownSupport || !yyextra->isSpecialComment)
1550 {
1551 REJECT;
1552 }
1553 else
1554 {
1555 outputArray(yyscanner,yytext,yyleng);
1556 yyextra->fenceChar='~';
1557 yyextra->fenceSize=(int)getFenceSize(yytext,yyleng);
1558 BEGIN(SkipVerbatim);
1559 }
1560 }
1561<SkipCComment>^({B}*"*"+)?{B}{0,3}"```"[`]* {
1562 bool markdownSupport = Config_getBool(MARKDOWN_SUPPORT);
1563 if (!markdownSupport || !yyextra->isSpecialComment)
1564 {
1565 REJECT;
1566 }
1567 else
1568 {
1569 outputArray(yyscanner,yytext,yyleng);
1570 yyextra->fenceChar='`';
1571 yyextra->fenceSize=(int)getFenceSize(yytext,yyleng);
1572 BEGIN(SkipVerbatim);
1573 }
1574 }
1575<SkipCComment>{CMD}{VERBATIM_LINE} |
1576<SkipCComment>{CMD}{LITERAL_BLOCK} { // escaped command
1577 outputArray(yyscanner,yytext,yyleng);
1578 yyextra->yyLineNr+=QCString(yytext).contains('\n');
1579 }
1580<SkipCComment>{VERBATIM_LINE}.*/\n { // normal command
1581 outputArray(yyscanner,yytext,yyleng);
1582 }
1583<SkipCComment>{LITERAL_BLOCK} { // normal block command
1584 outputArray(yyscanner,yytext,yyleng);
1585 yyextra->yyLineNr+=QCString(yytext).contains('\n');
1586 determineBlockName(yyscanner);
1587 BEGIN(SkipVerbatim);
1588 }
static void determineBlockName(yyscan_t yyscanner)
Definition pre.l:3647
1589<SkipCond>{CMD}{CMD}"cond"[ \t]+ {}// escaped cond command
1590<SkipCond>{CMD}"cond"/\n |
1591<SkipCond>{CMD}"cond"[ \t]+ { // cond command in a skipped cond section, this section has to be skipped as well
1592 // but has to be recorded to match the endcond command
1593 startCondSection(yyscanner," ");
1594 }
static void startCondSection(yyscan_t yyscanner, const QCString &sectId)
Definition pre.l:3833
1595<SkipCComment>"{"[ \t]*"@code"/[ \t\n] {
1596 outputArray(yyscanner,"@iliteral{code}",15);
1597 yyextra->javaBlock=1;
1598 BEGIN(JavaDocVerbatimCode);
1599 }
1600<SkipCComment>"{"[ \t]*"@literal"/[ \t\n] {
1601 outputArray(yyscanner,"@iliteral",9);
1602 yyextra->javaBlock=1;
1603 BEGIN(JavaDocVerbatimCode);
1604 }
1605<SkipCComment,SkipCPPComment>{CMD}{CMD}"cond"[ \t\n]+ { // escaped cond command
1606 outputArray(yyscanner,yytext,yyleng);
1607 }
1608<SkipCPPComment>{CMD}"cond"[ \t]+ { // conditional section
1609 yyextra->ccomment=TRUE;
1610 yyextra->condCtx=YY_START;
1611 BEGIN(CondLineCpp);
1612 }
1613<SkipCComment>{CMD}"cond"[ \t]+ { // conditional section
1614 yyextra->ccomment=FALSE;
1615 yyextra->condCtx=YY_START;
1616 BEGIN(CondLineC);
1617 }
1618<CondLineC,CondLineCpp>[!()&| \ta-z_A-Z0-9\x80-\xFF.\-]+ {
1619 startCondSection(yyscanner,yytext);
1620 if (yyextra->skip)
1621 {
1622 if (YY_START==CondLineC)
1623 {
1624 // end C comment
1625 outputArray(yyscanner,"*/",2);
1626 yyextra->ccomment=TRUE;
1627 }
1628 else
1629 {
1630 yyextra->ccomment=FALSE;
1631 }
1632 BEGIN(SkipCond);
1633 }
1634 else
1635 {
1636 BEGIN(yyextra->condCtx);
1637 }
1638 }
1639<CondLineC,CondLineCpp>. { // non-guard character
1640 unput(*yytext);
1641 startCondSection(yyscanner," ");
1642 if (yyextra->skip)
1643 {
1644 if (YY_START==CondLineC)
1645 {
1646 // end C comment
1647 outputArray(yyscanner,"*/",2);
1648 yyextra->ccomment=TRUE;
1649 }
1650 else
1651 {
1652 yyextra->ccomment=FALSE;
1653 }
1654 BEGIN(SkipCond);
1655 }
1656 else
1657 {
1658 BEGIN(yyextra->condCtx);
1659 }
1660 }
1661<SkipCComment,SkipCPPComment>{CMD}"cond"{WSopt}/\n { // no guard
1662 if (YY_START==SkipCComment)
1663 {
1664 yyextra->ccomment=TRUE;
1665 // end C comment
1666 outputArray(yyscanner,"*/",2);
1667 }
1668 else
1669 {
1670 yyextra->ccomment=FALSE;
1671 }
1672 yyextra->condCtx=YY_START;
1673 startCondSection(yyscanner," ");
1674 BEGIN(SkipCond);
1675 }
1676<SkipCond>\n { yyextra->yyLineNr++; outputChar(yyscanner,'\n'); }
1677<SkipCond>{VERBATIM_LINE}.*/\n { }
1678<SkipCond>{LITERAL_BLOCK} {
1679 auto numNLs = QCString(yytext).contains('\n');
1680 yyextra->yyLineNr+=numNLs;
1681 for (int i = 0; i < numNLs; i++) outputChar(yyscanner,'\n');
1682 determineBlockName(yyscanner);
1683 BEGIN(SkipCondVerbatim);
1684 }
1685
1686<SkipCond>. { }
1687<SkipCond>[^\/\!*\\@\n]+ { }
1688<SkipCond>{CPPC}[/!] { yyextra->ccomment=FALSE; }
1689<SkipCond>{CCS}[*!] { yyextra->ccomment=TRUE; }
1690<SkipCond,SkipCComment,SkipCPPComment>{CMD}{CMD}"endcond"/[^a-z_A-Z0-9\x80-\xFF] {
1691 if (!yyextra->skip)
1692 {
1693 outputArray(yyscanner,yytext,yyleng);
1694 }
1695 }
1696<SkipCond>{CMD}"endcond"/[^a-z_A-Z0-9\x80-\xFF] {
1697 bool oldSkip = yyextra->skip;
1698 endCondSection(yyscanner);
1699 if (oldSkip && !yyextra->skip)
1700 {
1701 if (yyextra->ccomment)
1702 {
1703 outputArray(yyscanner,"/** ",4); // */
1704 }
1705 BEGIN(yyextra->condCtx);
1706 }
1707 }
static void endCondSection(yyscan_t yyscanner)
Definition pre.l:3847
1708<SkipCComment,SkipCPPComment>{CMD}"endcond"/[^a-z_A-Z0-9\x80-\xFF] {
1709 bool oldSkip = yyextra->skip;
1710 endCondSection(yyscanner);
1711 if (oldSkip && !yyextra->skip)
1712 {
1713 BEGIN(yyextra->condCtx);
1714 }
1715 }
1716<SkipCondVerbatim>{LITERAL_BLOCK_END} { /* end of verbatim block */
1717 if (yytext[1]=='f' && yyextra->blockName==&yytext[2])
1718 {
1719 BEGIN(SkipCond);
1720 }
1721 else if (&yytext[4]==yyextra->blockName)
1722 {
1723 BEGIN(SkipCond);
1724 }
1725 }
1726<SkipVerbatim>{LITERAL_BLOCK_END} { /* end of verbatim block */
1727 outputArray(yyscanner,yytext,yyleng);
1728 if (yytext[1]=='f' && yyextra->blockName==&yytext[2])
1729 {
1730 BEGIN(SkipCComment);
1731 }
1732 else if (&yytext[4]==yyextra->blockName)
1733 {
1734 BEGIN(SkipCComment);
1735 }
1736 }
1737<SkipCondVerbatim>^({B}*"*"+)?{B}{0,3}"~~~"[~]* {
1738 if (yyextra->fenceSize==getFenceSize(yytext,yyleng) && yyextra->fenceChar=='~')
1739 {
1740 BEGIN(SkipCond);
1741 }
1742 }
1743<SkipCondVerbatim>^({B}*"*"+)?{B}{0,3}"```"[`]* {
1744 if (yyextra->fenceSize==getFenceSize(yytext,yyleng) && yyextra->fenceChar=='`')
1745 {
1746 BEGIN(SkipCond);
1747 }
1748 }
1749<SkipVerbatim>^({B}*"*"+)?{B}{0,3}"~~~"[~]* {
1750 outputArray(yyscanner,yytext,yyleng);
1751 if (yyextra->fenceSize==getFenceSize(yytext,yyleng) && yyextra->fenceChar=='~')
1752 {
1753 BEGIN(SkipCComment);
1754 }
1755 }
1756<SkipVerbatim>^({B}*"*"+)?{B}{0,3}"```"[`]* {
1757 outputArray(yyscanner,yytext,yyleng);
1758 if (yyextra->fenceSize==getFenceSize(yytext,yyleng) && yyextra->fenceChar=='`')
1759 {
1760 BEGIN(SkipCComment);
1761 }
1762 }
1763<SkipCondVerbatim>{CCE}|{CCS} { }
1764<SkipVerbatim>{CCE}|{CCS} {
1765 outputArray(yyscanner,yytext,yyleng);
1766 }
1767<JavaDocVerbatimCode>"{" {
1768 if (yyextra->javaBlock==0)
1769 {
1770 REJECT;
1771 }
1772 else
1773 {
1774 yyextra->javaBlock++;
1775 outputArray(yyscanner,yytext,(int)yyleng);
1776 }
1777 }
1778<JavaDocVerbatimCode>"}" {
1779 if (yyextra->javaBlock==0)
1780 {
1781 REJECT;
1782 }
1783 else
1784 {
1785 yyextra->javaBlock--;
1786 if (yyextra->javaBlock==0)
1787 {
1788 outputArray(yyscanner," @endiliteral ",14);
1789 BEGIN(SkipCComment);
1790 }
1791 else
1792 {
1793 outputArray(yyscanner,yytext,(int)yyleng);
1794 }
1795 }
1796 }
1797<JavaDocVerbatimCode>\n { /* new line in verbatim block */
1798 outputArray(yyscanner,yytext,(int)yyleng);
1799 }
1800<JavaDocVerbatimCode>. { /* any other character */
1801 outputArray(yyscanner,yytext,(int)yyleng);
1802 }
1803<SkipCondVerbatim>[^{*\\@\x06~`\n\/]+ { }
1804<SkipCComment,SkipVerbatim>[^{*\\@\x06~`\n\/]+ {
1805 outputArray(yyscanner,yytext,yyleng);
1806 }
1807<SkipCComment,SkipVerbatim,SkipCondVerbatim>\n {
1808 yyextra->yyLineNr++;
1809 outputChar(yyscanner,'\n');
1810 }
1811<SkipCondVerbatim>. { }
1812<SkipCComment,SkipVerbatim>. {
1813 outputChar(yyscanner,*yytext);
1814 }
1815<CopyCComment>[^*a-z_A-Z\x80-\xFF\n]*[^*a-z_A-Z\x80-\xFF\\\n] {
1816 yyextra->defLitText+=yytext;
1817 yyextra->defText+=escapeAt(yytext);
1818 }
static QCString escapeAt(const QCString &text)
Definition pre.l:3874
1819<CopyCComment>\\‍[\r]?\n {
1820 yyextra->defLitText+=yytext;
1821 yyextra->defText+=" ";
1822 yyextra->yyLineNr++;
1823 yyextra->yyMLines++;
1824 }
1825<CopyCComment>{CCE} {
1826 yyextra->defLitText+=yytext;
1827 yyextra->defText+=yytext;
1828 BEGIN(yyextra->lastCContext);
1829 }
1830<CopyCComment>\n {
1831 yyextra->yyLineNr++;
1832 yyextra->defLitText+=yytext;
1833 yyextra->defText+=' ';
1834 }
1835<RemoveCComment>{CCE}{B}*"#" { // see bug 594021 for a usecase for this rule
1836 if (yyextra->lastCContext==SkipCPPBlock)
1837 {
1838 BEGIN(SkipCommand);
1839 }
1840 else
1841 {
1842 REJECT;
1843 }
1844 }
1845<RemoveCComment>{CCE} { BEGIN(yyextra->lastCContext); }
1846<RemoveCComment>{CPPC}
1847<RemoveCComment>{CCS}
1848<RemoveCComment>[^*\x06\n]+
1849<RemoveCComment>\n { yyextra->yyLineNr++; outputChar(yyscanner,'\n'); }
1850<RemoveCComment>.
1851<SkipCPPComment>[^\n\/\\@]+ {
1852 outputArray(yyscanner,yytext,yyleng);
1853 }
1854<SkipCPPComment,RemoveCPPComment>\n {
1855 unput(*yytext);
1856 BEGIN(yyextra->lastCPPContext);
1857 }
1858<SkipCPPComment>{CCS} {
1859 outputChar(yyscanner,'/');outputChar(yyscanner,'*');
1860 }
1861<SkipCPPComment>{CPPC} {
1862 outputChar(yyscanner,'/');outputChar(yyscanner,'/');
1863 }
1864<SkipCPPComment>[^\x06\@\\\n]+ {
1865 outputArray(yyscanner,yytext,yyleng);
1866 }
1867<SkipCPPComment>. {
1868 outputChar(yyscanner,*yytext);
1869 }
1870<RemoveCPPComment>{CCS}
1871<RemoveCPPComment>{CPPC}
1872<RemoveCPPComment>[^\x06\n]+
1873<RemoveCPPComment>.
1874<DefineText>"__VA_OPT__("{B}*"##" {
1875 warn(yyextra->fileName,yyextra->yyLineNr,
1876 "'##' may not appear at the beginning of a __VA_OPT__()",
1877 yyextra->defName,yyextra->defLitText.stripWhiteSpace());
1878 yyextra->defText+="__VA_OPT__(";
1879 yyextra->defLitText+="__VA_OPT__(";
1880 }
1881<DefineText>"#"/"__VA_OPT__" {
1882 yyextra->defText+=yytext;
1883 yyextra->defLitText+=yytext;
1884 }
1885<DefineText>"#"/{IDSTART} {
1886 outputChar(yyscanner,' ');
1887 yyextra->quoteArg=TRUE;
1888 yyextra->idStart=true;
1889 yyextra->defLitText+=yytext;
1890 }
1891<DefineText,CopyCComment>{ID} {
1892 yyextra->defLitText+=yytext;
1893 if (YY_START == DefineText) outputSpaces(yyscanner,yytext);
1894 if (yyextra->quoteArg)
1895 {
1896 yyextra->defText+="\"";
1897 }
1898 if (yyextra->defArgs>0)
1899 {
1900 auto it = yyextra->argMap.find(yytext);
1901 if (it!=yyextra->argMap.end())
1902 {
1903 int n = it->second;
1904 yyextra->defText+='@';
1905 yyextra->defText+=QCString().setNum(n);
1906 }
1907 else
1908 {
1909 if (yyextra->idStart)
1910 {
1911 warn(yyextra->fileName,yyextra->yyLineNr,
1912 "'#' is not followed by a macro parameter '{}': '{}'",
1913 yyextra->defName,yyextra->defLitText.stripWhiteSpace());
1914 }
1915 yyextra->defText+=yytext;
1916 }
1917 }
1918 else
1919 {
1920 yyextra->defText+=yytext;
1921 }
1922 if (yyextra->quoteArg)
1923 {
1924 yyextra->defText+="\"";
1925 }
1926 yyextra->quoteArg=FALSE;
1927 yyextra->idStart=false;
1928 }
1929<CopyCComment>. {
1930 yyextra->defLitText+=yytext;
1931 yyextra->defText+=yytext;
1932 }
1933<DefineText>\\‍[\r]?\n {
1934 yyextra->defLitText+=yytext;
1935 outputChar(yyscanner,'\\');
1936 outputChar(yyscanner,'\n');
1937 yyextra->defText += ' ';
1938 yyextra->yyLineNr++;
1939 yyextra->yyMLines++;
1940 }
1941<DefineText>\n {
1942 QCString comment=extractTrailingComment(yyextra->defLitText);
1943 yyextra->defText = yyextra->defText.stripWhiteSpace();
1944 if (yyextra->defText.startsWith("##"))
1945 {
1946 warn(yyextra->fileName,yyextra->yyLineNr,
1947 "'##' cannot occur at the beginning of a macro definition '{}': '{}'",
1948 yyextra->defName,yyextra->defLitText.stripWhiteSpace());
1949 }
1950 else if (yyextra->defText.endsWith("##"))
1951 {
1952 warn(yyextra->fileName,yyextra->yyLineNr,
1953 "'##' cannot occur at the end of a macro definition '{}': '{}'",
1954 yyextra->defName,yyextra->defLitText.stripWhiteSpace());
1955 }
1956 else if (yyextra->defText.endsWith("#"))
1957 {
1958 warn(yyextra->fileName,yyextra->yyLineNr,
1959 "expected formal parameter after # in macro definition '{}': '{}'",
1960 yyextra->defName,yyextra->defLitText.stripWhiteSpace());
1961 }
1962 if (!comment.isEmpty())
1963 {
1964 outputString(yyscanner,comment);
1965 yyextra->defLitText=yyextra->defLitText.left(yyextra->defLitText.length()-comment.length()-1);
1966 }
1967 outputChar(yyscanner,'\n');
1968 yyextra->defLitText+=yytext;
1969 Define *def=nullptr;
1970 //printf("Define name='%s' text='%s' litTexti='%s'\n",qPrint(yyextra->defName),qPrint(yyextra->defText),qPrint(yyextra->defLitText));
1971 if (yyextra->includeStack.empty() || yyextra->curlyCount>0)
1972 {
1973 addMacroDefinition(yyscanner);
1974 }
1975 def=isDefined(yyscanner,yyextra->defName);
1976 if (def==0) // new define
1977 {
1978 //printf("new define '%s'!\n",qPrint(yyextra->defName));
1979 addDefine(yyscanner);
1980 }
1981 else if (def /*&& macroIsAccessible(def)*/)
1982 // name already exists
1983 {
1984 //printf("existing define!\n");
1985 //printf("define found\n");
1986 if (def->undef) // undefined name
1987 {
1988 def->undef = FALSE;
1989 def->name = yyextra->defName;
1990 def->definition = yyextra->defText.stripWhiteSpace();
1991 def->nargs = yyextra->defArgs;
1992 def->fileName = yyextra->fileName;
1993 def->lineNr = yyextra->yyLineNr-yyextra->yyMLines;
1994 def->columnNr = yyextra->yyColNr;
1995 }
1996 else
1997 {
1998 if (def->fileName != yyextra->fileName && !yyextra->expandOnlyPredef) addDefine(yyscanner);
1999 //printf("error: define %s is defined more than once!\n",qPrint(yyextra->defName));
2000 }
2001 }
2002 yyextra->argMap.clear();
2003 yyextra->yyLineNr++;
2004 yyextra->yyColNr=1;
2005 yyextra->lastGuardName.clear();
2006 BEGIN(Start);
2007 }
static void addMacroDefinition(yyscan_t yyscanner)
Definition pre.l:3555
static void addDefine(yyscan_t yyscanner)
Definition pre.l:3526
static QCString extractTrailingComment(const QCString &s)
Definition pre.l:2417
const char * comment
2008<DefineText>{B}* { outputString(yyscanner,yytext);
2009 yyextra->defText += ' ';
2010 yyextra->defLitText+=yytext;
2011 }
2012<DefineText>{B}*"##"{B}* { outputString(yyscanner,substitute(yytext,"##"," "));
2013 yyextra->defText += "##";
2014 yyextra->defLitText+=yytext;
2015 }
2016<DefineText>"@" { outputString(yyscanner,substitute(yytext,"@@"," "));
2017 yyextra->defText += "@@";
2018 yyextra->defLitText+=yytext;
2019 }
2020<DefineText>\" {
2021 outputChar(yyscanner,' ');
2022 yyextra->defText += *yytext;
2023 yyextra->defLitText+=yytext;
2024 if (!yyextra->insideComment)
2025 {
2026 BEGIN(SkipDoubleQuote);
2027 }
2028 }
2029<DefineText>{NUMBER} {
2030 outputSpaces(yyscanner,yytext);
2031 yyextra->defText += yytext;
2032 yyextra->defLitText+=yytext;
2033 }
2034<DefineText>\' {
2035 outputChar(yyscanner,' ');
2036 yyextra->defText += *yytext;
2037 yyextra->defLitText+=yytext;
2038 if (!yyextra->insideComment)
2039 {
2040 BEGIN(SkipSingleQuote);
2041 }
2042 }
2043<SkipDoubleQuote>{CPPC}[/]? { outputSpaces(yyscanner,yytext);
2044 yyextra->defText += yytext;
2045 yyextra->defLitText+=yytext;
2046 }
2047<SkipDoubleQuote>{CCS}[*]? { outputSpaces(yyscanner,yytext);
2048 yyextra->defText += yytext;
2049 yyextra->defLitText+=yytext;
2050 }
2051<SkipDoubleQuote>\" {
2052 outputChar(yyscanner,' ');
2053 yyextra->defText += *yytext;
2054 yyextra->defLitText+=yytext;
2055 BEGIN(DefineText);
2056 }
2057<SkipSingleQuote,SkipDoubleQuote>\\. {
2058 outputSpaces(yyscanner,yytext);
2059 yyextra->defText += yytext;
2060 yyextra->defLitText+=yytext;
2061 }
2062<SkipSingleQuote>\' {
2063 outputChar(yyscanner,' ');
2064 yyextra->defText += *yytext;
2065 yyextra->defLitText+=yytext;
2066 BEGIN(DefineText);
2067 }
2068<SkipDoubleQuote,SkipSingleQuote>. { outputSpace(yyscanner,yytext[0]);
2069 yyextra->defText += *yytext;
2070 yyextra->defLitText += *yytext;
2071 }
2072<DefineText>. { outputSpace(yyscanner,yytext[0]);
2073 yyextra->defText += *yytext;
2074 yyextra->defLitText += *yytext;
2075 }
2076<<EOF>> {
2077 TRACE("End of include file");
2078 //printf("Include stack depth=%d\n",yyextra->includeStack.size());
2079 if (yyextra->includeStack.empty())
2080 {
2081 TRACE("Terminating scanner");
2082 yyterminate();
2083 }
2084 else
2085 {
2086 QCString toFileName = yyextra->fileName;
2087 const std::unique_ptr<FileState> &fs=yyextra->includeStack.back();
2088 //fileDefineCache->merge(yyextra->fileName,fs->fileName);
2089 YY_BUFFER_STATE oldBuf = YY_CURRENT_BUFFER;
2090 yy_switch_to_buffer( fs->bufState, yyscanner );
2091 yy_delete_buffer( oldBuf, yyscanner );
2092 yyextra->yyLineNr = fs->lineNr;
2093 //preYYin = fs->oldYYin;
2094 yyextra->inputBuf = fs->oldFileBuf;
2095 yyextra->inputBufPos = fs->oldFileBufPos;
2096 yyextra->curlyCount = fs->curlyCount;
2097 setFileName(yyscanner,fs->fileName);
2098 TRACE("switching to {}",yyextra->fileName);
#define yyterminate()
#define TRACE(...)
Definition trace.h:77
2099
2100 // Deal with file changes due to
2101 // #include's within { .. } blocks
2102 QCString lineStr(15+yyextra->fileName.length(), QCString::ExplicitSize);
2103 lineStr.sprintf("# %d \"%s\" 2",yyextra->yyLineNr,qPrint(yyextra->fileName));
2104 outputString(yyscanner,lineStr);
2105
2106 yyextra->includeStack.pop_back();
2107
2108 {
2109 std::lock_guard<std::mutex> lock(g_globalDefineMutex);
2110 // to avoid deadlocks we allow multiple threads to process the same header file.
2111 // The first one to finish will store the results globally. After that the
2112 // next time the same file is encountered, the stored data is used and the file
2113 // is not processed again.
2114 if (!g_defineManager.alreadyProcessed(toFileName.str()))
2115 {
2116 // now that the file is completely processed, prevent it from processing it again
2117 g_defineManager.addInclude(yyextra->fileName.str(),toFileName.str());
2118 g_defineManager.store(toFileName.str(),yyextra->localDefines);
2119 }
2120 else
2121 {
2123 {
2124 Debug::print(Debug::Preprocessor,0,"#include {}: was already processed by another thread! not storing data...\n",toFileName);
2125 }
2126 }
2127 }
2128 // move the local macros definitions for in this file to the translation unit context
2129 for (const auto &kv : yyextra->localDefines)
2130 {
2131 auto pair = yyextra->contextDefines.insert(kv);
2132 if (!pair.second) // define already in context -> replace with local version
2133 {
2134 yyextra->contextDefines.erase(pair.first);
2135 yyextra->contextDefines.insert(kv);
2136 }
2137 }
2138 yyextra->localDefines.clear();
2139 }
2140 }
2141<*>{CCS}/{CCE} |
2142<*>{CCS}[*!]? {
2143 if (YY_START==SkipVerbatim || YY_START == SkipCondVerbatim || YY_START==SkipCond || YY_START==IDLquote || YY_START == PragmaOnce)
2144 {
2145 REJECT;
2146 }
2147 else
2148 {
2149 outputArray(yyscanner,yytext,yyleng);
2150 yyextra->lastCContext=YY_START;
2151 yyextra->commentCount=1;
2152 if (yyleng==3)
2153 {
2154 yyextra->isSpecialComment = true;
2155 yyextra->lastGuardName.clear(); // reset guard in case the #define is documented!
2156 }
2157 else
2158 {
2159 yyextra->isSpecialComment = false;
2160 }
2161 BEGIN(SkipCComment);
2162 }
2163 }
2164<*>{CPPC}[/!]? {
2165 if (YY_START==SkipVerbatim || YY_START == SkipCondVerbatim || YY_START==SkipCond || getLanguageFromFileName(yyextra->fileName)==SrcLangExt::Fortran || YY_START==IDLquote || YY_START == PragmaOnce)
2166 {
2167 REJECT;
2168 }
2169 else if (YY_START==RulesRoundDouble)
2170 {
2171 REJECT;
2172 }
2173 else
2174 {
2175 outputArray(yyscanner,yytext,yyleng);
2176 yyextra->lastCPPContext=YY_START;
2177 if (yyleng==3)
2178 {
2179 yyextra->isSpecialComment = true;
2180 yyextra->lastGuardName.clear(); // reset guard in case the #define is documented!
2181 }
2182 else
2183 {
2184 yyextra->isSpecialComment = false;
2185 }
2186 BEGIN(SkipCPPComment);
2187 }
2188 }
2189<*>\n {
2190 outputChar(yyscanner,'\n');
2191 yyextra->yyLineNr++;
2192 }
2193<*>. {
2194 yyextra->expectGuard = FALSE;
2195 outputChar(yyscanner,*yytext);
2196 }
2197
2198%%

◆ yyread()

int yyread ( yyscan_t yyscanner,
char * buf,
int max_size )
static

Definition at line 2202 of file pre.l.

2203{
2204 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
2205 int bytesInBuf = static_cast<int>(state->inputBuf->size())-state->inputBufPos;
2206 int bytesToCopy = std::min(max_size,bytesInBuf);
2207 memcpy(buf,state->inputBuf->data()+state->inputBufPos,bytesToCopy);
2208 state->inputBufPos+=bytesToCopy;
2209 return bytesToCopy;
2210}

Variable Documentation

◆ g_debugMutex

std::mutex g_debugMutex
static

Definition at line 233 of file pre.l.

Referenced by Preprocessor::processFile().

◆ g_defineManager

DefineManager g_defineManager
static

Definition at line 236 of file pre.l.

Referenced by checkAndOpenFile(), and readIncludeFile().

◆ g_globalDefineMutex

std::mutex g_globalDefineMutex
static

Definition at line 234 of file pre.l.

Referenced by checkAndOpenFile(), and readIncludeFile().

◆ g_updateGlobals

std::mutex g_updateGlobals
static

Definition at line 235 of file pre.l.

Referenced by Preprocessor::processFile().