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 QCString expandStandardMacro (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 3055 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:3982

Definition at line 353 of file pre.l.

◆ YY_NO_UNISTD_H

#define YY_NO_UNISTD_H   1

Definition at line 66 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 108 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 3603 of file pre.l.

3604{
3605 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
3606 Define def;
3607 def.name = state->defName;
3608 def.definition = state->defText.stripWhiteSpace();
3609 def.nargs = state->defArgs;
3610 def.fileName = state->fileName;
3611 def.fileDef = state->yyFileDef;
3612 def.lineNr = state->yyLineNr-state->yyMLines;
3613 def.columnNr = state->yyColNr;
3614 def.varArgs = state->defVarArgs;
3615 //printf("newDefine: %s %s file: %s\n",qPrint(def.name),qPrint(def.definition),
3616 // def.fileDef ? qPrint(def.fileDef->name()) : qPrint(def.fileName));
3617 //printf("newDefine: '%s'->'%s'\n",qPrint(def.name),qPrint(def.definition));
3618 if (!def.name.isEmpty() &&
3620 {
3621 def.isPredefined=TRUE;
3623 }
3624 auto it = state->localDefines.find(def.name.str());
3625 if (it!=state->localDefines.end()) // redefine
3626 {
3627 state->localDefines.erase(it);
3628 }
3629 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:119
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
3630}

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 3632 of file pre.l.

3633{
3634 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
3635 if (state->skip) return; // do not add this define as it is inside a
3636 // conditional section (cond command) that is disabled.
3637
3638 Define define;
3639 define.fileName = state->fileName;
3640 define.lineNr = state->yyLineNr - state->yyMLines;
3641 define.columnNr = state->yyColNr;
3642 define.name = state->defName;
3643 define.args = state->defArgsStr;
3644 define.fileDef = state->inputFileDef;
QCString args
Definition define.h:36
3645
3646 QCString litText = state->defLitText;
3647 int l=litText.find('\n');
3648 if (l>0 && litText.left(l).stripWhiteSpace()=="\\")
3649 {
3650 // strip first line if it only contains a slash
3651 litText = litText.right(litText.length()-l-1);
3652 }
3653 else if (l>0)
3654 {
3655 // align the items on the first line with the items on the second line
3656 int k=l+1;
3657 const char *p=litText.data()+k;
3658 char c = 0;
3659 while ((c=*p++) && (c==' ' || c=='\t')) k++;
3660 litText=litText.mid(l+1,k-l-1)+litText.stripWhiteSpace();
3661 }
3662 QCString litTextStripped = state->defLitText.stripWhiteSpace();
3663 if (litTextStripped.contains('\n')>=1)
3664 {
3665 define.definition = litText;
3666 }
3667 else
3668 {
3669 define.definition = litTextStripped;
3670 }
3671 {
3672 state->macroDefinitions.push_back(define);
3673 }
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
3674}

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 3057 of file pre.l.

3058{
3059 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
3060 if (!state->nospaces)
3061 {
3062 // peek back in the stream, for a colon character
3063 char ccPrev = pos==0 || (int)expr.length()<pos ? state->prevChar : expr.at(pos-1);
3064 QCString leftSpace = ccPrev!=':' && ccPrev!=' ' ? " " : "";
3065 int ccNext = 0;
3066 restExpr=restExpr.stripWhiteSpace();
3067 if (restExpr.isEmpty()) // peek ahead in the stream for non-whitespace
3068 {
3069 uint32_t j=(uint32_t)resultExpr.length();
3070 while ((ccNext=getNextChar(yyscanner,resultExpr,nullptr,j))!=EOF && ccNext==' ') { }
3071 if (ccNext != EOF) unputChar(yyscanner,resultExpr,nullptr,j,(char)ccNext);
3072 }
3073 else // take first char from remainder
3074 {
3075 ccNext=restExpr.at(0);
3076 }
3077 // don't add whitespace before a colon
3078 QCString rightSpace = ccNext!=':' && ccNext!=' ' ? " " : "";
3079 //printf("ccPrev='%c' ccNext='%c' p=%d expr=%zu restExpr='%s' left='%s' right='%s'\n",
3080 // ccPrev,ccNext,pos,expr.length(),qPrint(restExpr),qPrint(leftSpace),qPrint(rightSpace));
3081 resultExpr=leftSpace+resultExpr+rightSpace;
3082 }
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:4004
static void unputChar(yyscan_t yyscanner, const QCString &expr, QCString *rest, uint32_t &pos, char c)
Definition pre.l:4050
3083}

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 2640 of file pre.l.

2642{
2643 int cc;
2644 while ((cc=getNextChar(yyscanner,expr,rest,pos))!=EOF && cc!=0)
2645 {
2646 if (cc=='\\')
2647 {
2648 arg+=(char)cc;
2649 cc=getNextChar(yyscanner,expr,rest,pos);
2650 }
2651 else if (cc==term)
2652 {
2653 return;
2654 }
2655 arg+=(char)cc;
2656 }
#define term(fmt,...)
Definition message.h:137
2657}

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 2328 of file pre.l.

2329{
2330 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
2331 alreadyProcessed = FALSE;
2332 std::unique_ptr<FileState> fs;
2333 //printf("checkAndOpenFile(%s)\n",qPrint(fileName));
2334 FileInfo fi(fileName.str());
2335 if (fi.exists() && fi.isFile())
2336 {
2337 const StringVector &exclPatterns = Config_getList(EXCLUDE_PATTERNS);
2338 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:5724
2339
2340 QCString absName = fi.absFilePath();
2341
2342 // global guard
2343 if (state->curlyCount==0) // not #include inside { ... }
2344 {
2345 std::lock_guard<std::mutex> lock(g_globalDefineMutex);
2346 if (g_defineManager.alreadyProcessed(absName.str()))
2347 {
2348 alreadyProcessed = TRUE;
2349 //printf(" already included 1\n");
2350 return 0; // already done
2351 }
2352 }
2353 // check include stack for absName
static std::mutex g_globalDefineMutex
Definition pre.l:233
static DefineManager g_defineManager
Definition pre.l:235
2354
2355 alreadyProcessed = std::any_of(
2356 state->includeStack.begin(),
2357 state->includeStack.end(),
2358 [absName](const std::unique_ptr<FileState> &lfs)
2359 { return lfs->fileName==absName; }
2360 );
2361
2362 if (alreadyProcessed)
2363 {
2364 //printf(" already included 2\n");
2365 return nullptr;
2366 }
2367 //printf("#include %s\n",qPrint(absName));
2368
2369 fs = std::make_unique<FileState>();
2370 if (!readInputFile(absName,fs->fileBuf))
2371 { // error
2372 //printf(" error reading\n");
2373 fs.reset();
2374 }
2375 else
2376 {
2377 addTerminalCharIfMissing(fs->fileBuf,'\n');
2378 fs->oldFileBuf = state->inputBuf;
2379 fs->oldFileBufPos = state->inputBufPos;
2380 }
2381 }
2382 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:5570
2383}

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 3541 of file pre.l.

3542{
3543 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
3544 QCString e=expr;
3545 QCString ee=expr;
3546 ee = removeMarkers(ee);
3547 state->expanded.clear();
3548 expandExpression(yyscanner,e,nullptr,0,0);
3549 //printf("after expansion '%s'\n",qPrint(e));
3550 e = removeIdsAndMarkers(e);
3551 if (e.isEmpty()) return FALSE;
3552 //printf("parsing '%s'\n",qPrint(e));
3553 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:3089
static QCString removeIdsAndMarkers(const QCString &s)
Definition pre.l:3275
static QCString removeMarkers(const QCString &s)
Definition pre.l:3470
3554}

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

◆ decrLevel()

void decrLevel ( yyscan_t yyscanner)
static

Definition at line 2286 of file pre.l.

2287{
2288 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
2289 //printf("%s line %d: decrLevel %zu\n",qPrint(state->fileName),state->yyLineNr,state->levelGuard.size());
2290 if (!state->levelGuard.empty())
2291 {
2292 state->levelGuard.pop();
2293 }
2294 else
2295 {
2296 if (state->condGuardErrorLine!=0)
2297 {
2298 warn(state->condGuardErrorFileName,state->condGuardErrorLine,"{}",state->condGuardErrorMessage);
2299 }
2300 else
2301 {
2302 warn(state->fileName,state->yyLineNr,"More #endif's than #if's found.");
2303 }
2304 }
#define warn(file, line, fmt,...)
Definition message.h:97
2305}

References warn.

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

◆ determineBlockName()

void determineBlockName ( yyscan_t yyscanner)
static

Definition at line 3724 of file pre.l.

3725{
3726 struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
3727 yyextra->fenceSize=0;
3728 char c=0;
3729 if (yytext[1]=='f' && ((c=yytext[2])=='[' || c=='{' || c=='(' || c=='$'))
3730 {
3731 switch (c)
3732 {
3733 case '[': yyextra->blockName="]"; break;
3734 case '{': yyextra->blockName="}"; break;
3735 case '(': yyextra->blockName=")"; break;
3736 case '$': yyextra->blockName="$"; break;
3737 default: break;
3738 }
3739 yyextra->blockName=yyextra->blockName.stripWhiteSpace();
3740 }
3741 else
3742 {
3743 QCString bn=QCString(&yytext[1]).stripWhiteSpace();
3744 if (bn=="startuml")
3745 {
3746 yyextra->blockName="uml";
3747 }
3748 else
3749 {
3750 int i = bn.find('{'); // for \code{.c}
3751 if (i!=-1) bn=bn.left(i).stripWhiteSpace();
3752 yyextra->blockName=bn;
3753 }
3754 }
3755}

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

◆ endCondSection()

void endCondSection ( yyscan_t yyscanner)
static

Definition at line 3926 of file pre.l.

3927{
3928 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
3929 if (state->condGuardCount>0 && state->condGuardErrorLine==0)
3930 {
3931 state->condGuardErrorLine = state->yyLineNr;
3932 state->condGuardErrorFileName = state->fileName;
3933 state->condGuardErrorMessage = "more #if's than #endif's in \\cond..\\endcond section";
3934 }
3935 else if (state->condGuardCount<0 && state->condGuardErrorLine==0)
3936 {
3937 state->condGuardErrorLine = state->yyLineNr;
3938 state->condGuardErrorFileName = state->fileName;
3939 state->condGuardErrorMessage = "more #endif's than #if's in \\cond..\\endcond section";
3940 }
3941 else // balanced again -> no error
3942 {
3943 state->condGuardErrorLine = 0;
3944 }
3945 if (state->condStack.empty())
3946 {
3947 warn(state->fileName,state->yyLineNr,"the \\endcond does not have a corresponding \\cond in this file");
3948 state->skip=FALSE;
3949 }
3950 else
3951 {
3952 const std::unique_ptr<preYY_CondCtx> &ctx = state->condStack.top();
3953 state->skip=ctx->skip;
3954 state->condStack.pop();
3955 }
3956 //printf("endCondSection: skip=%d stack=%d\n",state->skip,state->condStack.count());
3957}

References FALSE, and warn.

◆ escapeAt()

QCString escapeAt ( const QCString & text)
static

Definition at line 3969 of file pre.l.

3970{
3971 QCString result;
3972 if (!text.isEmpty())
3973 {
3974 char c = 0;
3975 const char *p=text.data();
3976 while ((c=*p++))
3977 {
3978 if (c=='@') result+="@@"; else result+=c;
3979 }
3980 }
3981 return result;
3982}

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 3089 of file pre.l.

3090{
3091 struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
3092 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
3093 //printf(">expandExpression(expr='%s',rest='%s',pos=%d,level=%d)\n",qPrint(expr),rest ? qPrint(*rest) : "", pos, level);
3094 if (expr.isEmpty())
3095 {
3096 //printf("<expandExpression: empty\n");
3097 return TRUE;
3098 }
3099 if (state->expanded.find(expr.str())!=state->expanded.end() &&
3100 level>MAX_EXPANSION_DEPTH) // check for too deep recursive expansions
3101 {
3102 //printf("<expandExpression: already expanded expr='%s'\n",qPrint(expr));
3103 return FALSE;
3104 }
3105 else
3106 {
3107 state->expanded.insert(expr.str());
3108 }
3109 QCString macroName;
3110 QCString expMacro;
3111 bool definedTest=FALSE;
3112 int i=pos, l=0, p=0, len=0;
3113 int startPos = pos;
3114 int samePosCount=0;
3115 while ((p=getNextId(expr,i,&l))!=-1) // search for an macro name
3116 {
3117 bool replaced=FALSE;
3118 QCString resultExpr;
3119 macroName=expr.mid(p,l);
3120 //printf(" p=%d macroName=%s\n",p,qPrint(macroName));
3121 if (!(resultExpr = expandStandardMacro(yyscanner,macroName)).isEmpty())
3122 {
3123 QCString restExpr=expr.right(expr.length()-8-p);
3124 expr=expr.left(p)+resultExpr+restExpr;
3125 }
3126 else if (p<2 || !(expr.at(p-2)=='@' && expr.at(p-1)=='-')) // no-rescan marker?
3127 {
3128 if (state->expandedDict.find(macroName.str())==state->expandedDict.end()) // expand macro
3129 {
3130 bool expanded=false;
3131 Define *def=isDefined(yyscanner,macroName);
3132 // In case EXPAND_ONLY_PREDEF is enabled prevent expansion unless the macro was explicitly
3133 // predefined
3134 if (yyextra->expandOnlyPredef && def && !def->isPredefined) def=nullptr;
3135 if (macroName=="defined")
3136 {
3137 //printf("found defined inside macro definition '%s'\n",qPrint(expr.right(expr.length()-p)));
3138 definedTest=TRUE;
3139 }
3140 else if (definedTest) // macro name was found after defined
3141 {
3142 if (def) expMacro = " 1 "; else expMacro = " 0 ";
3143 replaced=TRUE;
3144 len=l;
3145 definedTest=FALSE;
3146 }
3147 else if (def && def->nargs==-1) // simple macro
3148 {
3149 // substitute the definition of the macro
3150 expMacro=def->definition.stripWhiteSpace();
3151 //expMacro=def->definition.stripWhiteSpace();
3152 replaced=TRUE;
3153 len=l;
3154 //printf("simple macro expansion='%s'->'%s'\n",qPrint(macroName),qPrint(expMacro));
3155 }
3156 else if (def && def->nargs>=0) // function macro
3157 {
3158 //printf(" >>>> call replaceFunctionMacro expr='%s'\n",qPrint(expr));
3159 replaced=replaceFunctionMacro(yyscanner,expr,rest,p+l,len,def,expMacro,level);
3160 //printf(" <<<< call replaceFunctionMacro: replaced=%d\n",replaced);
3161 len+=l;
3162 }
#define MAX_EXPANSION_DEPTH
Definition pre.l:3055
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:4074
static int getNextId(const QCString &expr, int p, int *l)
Definition pre.l:3001
static QCString expandStandardMacro(yyscan_t yyscanner, const QCString &name)
Definition pre.l:3574
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:2743
3163
3164 if (replaced) // expand the macro and rescan the expression
3165 {
3166 //printf(" replacing '%s'->'%s'\n",qPrint(expr.mid(p,len)),qPrint(expMacro));
3167 resultExpr=expMacro;
3168 QCString restExpr=expr.right(expr.length()-len-p);
3169 addSeparatorsIfNeeded(yyscanner,expr,resultExpr,restExpr,p);
3170 processConcatOperators(resultExpr);
3171 //printf(" macroName=%s restExpr='%s' def->nonRecursive=%d\n",qPrint(macroName),qPrint(restExpr),def ? def->nonRecursive : false);
3172 if (def && !def->nonRecursive)
3173 {
3174 state->expandedDict.emplace(toStdString(macroName),def);
3175 expanded = expandExpression(yyscanner,resultExpr,&restExpr,0,level+1);
3176 state->expandedDict.erase(toStdString(macroName));
3177 }
3178 else if (def && def->nonRecursive)
3179 {
3180 expanded = true;
3181 }
3182 if (expanded)
3183 {
3184 //printf("expanded '%s' + '%s' + '%s'\n",qPrint(expr.left(p)),qPrint(resultExpr),qPrint(restExpr));
3185 expr=expr.left(p)+resultExpr+restExpr;
3186 i=p;
3187 }
3188 else
3189 {
3190 //printf("not expanded '%s' + @- '%s'\n",qPrint(expr.left(p)),qPrint(expr.right(expr.length()-p)));
3191 expr=expr.left(p)+"@-"+expr.right(expr.length()-p);
3192 i=p+l+2;
3193 }
3194 }
3195 else // move to the next macro name
3196 {
3197 //printf(" moving to the next macro old i=%d new i=%d\n",i,p+l);
3198 i=p+l;
3199 }
3200 }
3201 else // move to the next macro name
3202 {
3203 expr=expr.left(p)+"@-"+expr.right(expr.length()-p);
3204 //printf("macro already expanded, moving to the next macro expr=%s\n",qPrint(expr));
3205 i=p+l+2;
3206 //i=p+l;
3207 }
3208 // check for too many inplace expansions without making progress
3209 if (i==startPos)
3210 {
3211 samePosCount++;
3212 }
3213 else
3214 {
3215 startPos=i;
3216 samePosCount=0;
3217 }
3218 if (samePosCount>MAX_EXPANSION_DEPTH)
3219 {
3220 break;
3221 }
3222 }
3223 else // no re-scan marker found, skip the macro name
3224 {
3225 //printf("skipping marked macro\n");
3226 i=p+l;
3227 }
3228 }
3229 //printf("<expandExpression(expr='%s',rest='%s',pos=%d,level=%d)\n",qPrint(expr),rest ? qPrint(*rest) : "", pos,level);
3230 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:3057
static void processConcatOperators(QCString &expr)
Definition pre.l:2587
std::string toStdString(const QCString &s)
Definition qcstring.h:702
3231}

References addSeparatorsIfNeeded(), QCString::at(), Define::definition, expandExpression(), expandStandardMacro(), 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 3560 of file pre.l.

3561{
3562 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3563 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
3564 state->prevChar = yyscanner->yytext_r > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ? *(yyscanner->yytext_r-1) : 0;
3565 QCString n=name;
3566 state->expanded.clear();
3567 expandExpression(yyscanner,n,nullptr,0,0);
3568 n=removeMarkers(n);
3569 state->prevChar=0;
3570 //printf("expandMacro '%s'->'%s'\n",qPrint(name),qPrint(n));
3571 return n;
void clear()
Definition qcstring.h:182
3572}

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

◆ expandStandardMacro()

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

Definition at line 3574 of file pre.l.

3575{
3576 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3577 QCString resultExpr;
3578 if (name == "__LINE__")
3579 {
3580 return QCString().setNum(yyextra->yyLineNr);
3581 }
3582 else if (name == "__FILE__")
3583 {
3584 resultExpr = "\"";
3585 resultExpr += yyextra->fileName;
3586 resultExpr += "\"";
3587 }
3588 else if (name == "__DATE__")
3589 {
3590 resultExpr = "\"";
3591 resultExpr += __DATE__;
3592 resultExpr += "\"";
3593 }
3594 else if (name == "__TIME__")
3595 {
3596 resultExpr = "\"";
3597 resultExpr += __TIME__;
3598 resultExpr += "\"";
3599 }
3600 return resultExpr;
QCString & setNum(short n)
Definition qcstring.h:459
3601}

References QCString::setNum().

Referenced by expandExpression().

◆ expandVAOpt()

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

Definition at line 2691 of file pre.l.

2692{
2693 //printf("expandVAOpt(vaStr=%s,hasOptionalArgs=%d)\n",qPrint(vaStr),hasOptionalArgs);
2694 QCString result;
2695 int vo=0, vp=0;
2696 result.clear();
2697 int vl = static_cast<int>(vaStr.length());
2698 while ((vo = vaStr.find("__VA_OPT__(",vp))!=-1)
2699 {
2700 bool hasHash = vo>0 && vaStr.at(vo-1)=='#';
2701 if (hasHash)
2702 {
2703 result+=vaStr.mid(vp,vo-vp-1); // don't copy #
2704 result+="\"";
2705 }
2706 else
2707 {
2708 result+=vaStr.mid(vp,vo-vp);
2709 }
2710 int ve=vo+11; // skip over '__VA_OPT__(' part
2711 int bc=1;
2712 while (bc>0 && ve<vl)
2713 {
2714 if (vaStr[ve]==')') bc--;
2715 else if (vaStr[ve]=='(') bc++;
2716 ve++;
2717 }
2718 // ve points to end of __VA_OPT__(....)
2719 if (bc==0 && hasOptionalArgs)
2720 {
2721 QCString voStr = vaStr.mid(vo+11,ve-vo-12);
2722 //printf("vo=%d ve=%d voStr=%s\n",vo,ve,qPrint(voStr));
2723 result+=voStr; // take 'x' from __VA_OPT__(x)
2724 }
2725 if (hasHash)
2726 {
2727 result+="\"";
2728 }
2729 vp=ve;
2730 }
2731 result+=vaStr.mid(vp);
2732 //printf("vaStr='%s'\n -> '%s'\n",qPrint(vaStr),qPrint(result));
2733 return result;
2734}

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 2459 of file pre.l.

2460{
2461 if (s.isEmpty()) return "";
2462 int i=(int)s.length()-1;
2463 while (i>=0)
2464 {
2465 char c=s[i];
2466 switch (c)
2467 {
2468 case '/':
2469 {
2470 i--;
2471 if (i>=0 && s[i]=='*') // end of a comment block
2472 {
2473 i--;
2474 while (i>0 && !(s[i-1]=='/' && s[i]=='*')) i--;
2475 if (i==0)
2476 {
2477 i++;
2478 }
2479 // only /*!< ... */ or /**< ... */ are treated as a comment for the macro name,
2480 // otherwise the comment is treated as part of the macro definition
2481 return ((s[i+1]=='*' || s[i+1]=='!') && s[i+2]=='<') ? &s[i-1] : "";
2482 }
2483 else
2484 {
2485 return "";
2486 }
2487 }
2488 break;
2489 // whitespace or line-continuation
2490 case ' ':
2491 case '\t':
2492 case '\r':
2493 case '\n':
2494 case '\\':
2495 break;
2496 default:
2497 return "";
2498 }
2499 i--;
2500 }
2501 return "";
2502}

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

◆ extraSpacing()

void extraSpacing ( yyscan_t yyscanner)
inlinestatic

Definition at line 3711 of file pre.l.

3712{
3713 struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
3714 if (!yyextra->defContinue) return;
3715 for (int i=0; i< (int)yyleng; i++)
3716 {
3717 if (yytext[i] == '\t')
3718 yyextra->defExtraSpacing+='\t';
3719 else
3720 yyextra->defExtraSpacing+=' ';
3721 }
3722}

◆ findFile()

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

Definition at line 2385 of file pre.l.

2386{
2387 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
2388 //printf("** findFile(%s,%d) state->fileName=%s\n",qPrint(fileName),localInclude,qPrint(state->fileName));
2389 if (Portable::isAbsolutePath(fileName))
2390 {
2391 auto fs = checkAndOpenFile(yyscanner,fileName,alreadyProcessed);
2392 if (fs)
2393 {
2394 setFileName(yyscanner,fileName);
2395 state->yyLineNr=1;
2396 return fs;
2397 }
2398 else if (alreadyProcessed)
2399 {
2400 return nullptr;
2401 }
2402 }
2403 if (localInclude && !state->fileName.isEmpty())
2404 {
2405 FileInfo fi(state->fileName.str());
2406 if (fi.exists())
2407 {
2408 QCString absName = QCString(fi.dirPath(TRUE))+"/"+fileName;
2409 auto fs = checkAndOpenFile(yyscanner,absName,alreadyProcessed);
2410 if (fs)
2411 {
2412 setFileName(yyscanner,absName);
2413 state->yyLineNr=1;
2414 return fs;
2415 }
2416 else if (alreadyProcessed)
2417 {
2418 return nullptr;
2419 }
2420 }
2421 }
2422 if (state->pathList.empty())
2423 {
2424 return nullptr;
2425 }
2426 for (auto path : state->pathList)
2427 {
2428 QCString absName = path+"/"+fileName;
2429 //printf(" Looking for %s in %s\n",fileName,qPrint(path));
2430 auto fs = checkAndOpenFile(yyscanner,absName,alreadyProcessed);
2431 if (fs)
2432 {
2433 setFileName(yyscanner,absName);
2434 state->yyLineNr=1;
2435 //printf(" -> found it\n");
2436 return fs;
2437 }
2438 else if (alreadyProcessed)
2439 {
2440 return nullptr;
2441 }
2442 }
2443 bool ambig = false;
2445 if (fd && !ambig) // fallback in case the file is uniquely named in the input, use that one
2446 {
2447 auto fs = checkAndOpenFile(yyscanner,fd->absFilePath(),alreadyProcessed);
2448 if (fs)
2449 {
2450 setFileName(yyscanner,fd->absFilePath());
2451 state->yyLineNr=1;
2452 //printf(" -> found it\n");
2453 return fs;
2454 }
2455 }
2456 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:497
static void setFileName(yyscan_t yyscanner, const QCString &name)
Definition pre.l:2258
static std::unique_ptr< FileState > checkAndOpenFile(yyscan_t yyscanner, const QCString &fileName, bool &alreadyProcessed)
Definition pre.l:2328
FileDef * findFileDef(const FileNameLinkedMap *fnMap, const QCString &n, bool &ambig)
Definition util.cpp:2904
2457}

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 3959 of file pre.l.

3960{
3961 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
3962 while (!state->condStack.empty())
3963 {
3964 state->condStack.pop();
3965 }
3966 state->skip=FALSE;
3967}

References FALSE.

Referenced by Preprocessor::processFile().

◆ getCurrentChar()

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

Definition at line 4027 of file pre.l.

4028{
4029 //printf("getCurrentChar(%s,%s,%d)\n",qPrint(expr),rest ? rest->data() : 0,pos);
4030 if (pos<expr.length())
4031 {
4032 //printf("%c=expr()\n",expr.at(pos));
4033 return expr.at(pos);
4034 }
4035 else if (rest && !rest->isEmpty())
4036 {
4037 int cc=rest->at(0);
4038 //printf("%c=rest\n",cc);
4039 return cc;
4040 }
4041 else
4042 {
4043 int cc=yyinput(yyscanner);
4044 returnCharToStream(yyscanner,(char)cc);
4045 //printf("%c=yyinput()\n",cc);
4046 return cc;
4047 }
static void returnCharToStream(yyscan_t yyscanner, char c)
Definition pre.l:2634
4048}

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 2247 of file pre.l.

2248{
2249 yy_size_t fenceSize = 0;
2250 for (size_t i = 0; i < leng; i++)
2251 {
2252 if (txt[i] != ' ' && txt[i] != '*' && txt[i] != '\t') break;
2253 fenceSize++;
2254 }
2255 return leng-fenceSize;
2256}

◆ getLexerFILE()

const char * getLexerFILE ( )
inlinestatic

Definition at line 356 of file pre.l.

356{return __FILE__;}

◆ getNextChar()

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

Definition at line 4004 of file pre.l.

4005{
4006 //printf("getNextChar(%s,%s,%d)\n",qPrint(expr),rest ? rest->data() : 0,pos);
4007 if (pos<expr.length())
4008 {
4009 //printf(" expr()='%c'\n",expr.at(pos));
4010 return expr.at(pos++);
4011 }
4012 else if (rest && !rest->isEmpty())
4013 {
4014 int cc=rest->at(0);
4015 *rest=rest->right(rest->length()-1);
4016 //printf(" rest='%c'\n",cc);
4017 return cc;
4018 }
4019 else
4020 {
4021 int cc=yyinput(yyscanner);
4022 //printf(" yyinput()='%c' %d\n",cc,EOF);
4023 return cc;
4024 }
4025}

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 3001 of file pre.l.

3002{
3003 int n;
3004 while (p<(int)expr.length())
3005 {
3006 char c=expr.at(p++);
3007 if (isdigit(c)) // skip number
3008 {
3009 while (p<(int)expr.length() && isId(expr.at(p))) p++;
3010 }
3011 else if (isalpha(c) || c=='_') // read id
3012 {
3013 n=p-1;
3014 while (p<(int)expr.length() && isId(expr.at(p))) p++;
3015 *l=p-n;
3016 return n;
3017 }
3018 else if (c=='"') // skip string
3019 {
3020 char ppc=0,pc=c;
3021 if (p<(int)expr.length()) c=expr.at(p);
3022 while (p<(int)expr.length() && (c!='"' || (pc=='\\' && ppc!='\\')))
3023 // continue as long as no " is found, but ignoring \", but not \\"
3024 {
3025 ppc=pc;
3026 pc=c;
3027 c=expr.at(p);
3028 p++;
3029 }
3030 if (p<(int)expr.length()) ++p; // skip closing quote
3031 }
3032 else if (c=='/') // skip C Comment
3033 {
3034 //printf("Found C comment at p=%d\n",p);
3035 char pc=c;
3036 if (p<(int)expr.length())
3037 {
3038 c=expr.at(p);
3039 if (c=='*') // Start of C comment
3040 {
3041 p++;
3042 while (p<(int)expr.length() && !(pc=='*' && c=='/'))
3043 {
3044 pc=c;
3045 c=expr.at(p++);
3046 }
3047 }
3048 }
3049 //printf("Found end of C comment at p=%d\n",p);
3050 }
3051 }
3052 return -1;
bool isId(int c)
Definition util.h:256
3053}

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

Referenced by expandExpression().

◆ incrLevel()

void incrLevel ( yyscan_t yyscanner)
static

Definition at line 2279 of file pre.l.

2280{
2281 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
2282 state->levelGuard.push(false);
2283 //printf("%s line %d: incrLevel %zu\n",qPrint(state->fileName),state->yyLineNr,state->levelGuard.size());
2284}

◆ initPredefined()

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

Definition at line 4103 of file pre.l.

4104{
4105 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
4106
4107 // add predefined macros
4108 const StringVector &predefList = Config_getList(PREDEFINED);
4109 for (const auto &ds : predefList)
4110 {
4111 size_t i_equals=ds.find('=');
4112 size_t i_obrace=ds.find('(');
4113 size_t i_cbrace=ds.find(')');
4114 bool nonRecursive = i_equals!=std::string::npos && i_equals>0 && ds[i_equals-1]==':';
4115
4116 if ((i_obrace==0) || (i_equals==0) || (i_equals==1 && ds[i_equals-1]==':'))
4117 {
4118 continue; // no define name
4119 }
4120
4121 if (i_obrace<i_equals && i_cbrace<i_equals &&
4122 i_obrace!=std::string::npos && i_cbrace!=std::string::npos &&
4123 i_obrace<i_cbrace
4124 ) // predefined function macro definition
4125 {
4126 static const reg::Ex reId(R"(\a\w*)");
4127 std::map<std::string,int> argMap;
4128 std::string args = ds.substr(i_obrace+1,i_cbrace-i_obrace-1); // part between ( and )
4129 bool hasVarArgs = args.find("...")!=std::string::npos;
4130 //printf("predefined function macro '%s'\n",qPrint(ds));
4131 int count = 0;
4132 reg::Iterator arg_it(args,reId,0);
4133 reg::Iterator arg_end;
4134 // gather the formal arguments in a dictionary
4135 for (; arg_it!=arg_end; ++arg_it)
4136 {
4137 argMap.emplace(arg_it->str(),count++);
4138 }
4139 if (hasVarArgs) // add the variable argument if present
4140 {
4141 argMap.emplace("__VA_ARGS__",count++);
4142 }
Class representing a regular expression.
Definition regex.h:39
Class to iterate through matches.
Definition regex.h:230
4143
4144 // strip definition part
4145 std::string definition;
4146 std::string in=ds.substr(i_equals+1);
4147 reg::Iterator re_it(in,reId);
4148 reg::Iterator re_end;
4149 size_t i=0;
4150 // substitute all occurrences of formal arguments by their
4151 // corresponding markers
4152 for (; re_it!=re_end; ++re_it)
4153 {
4154 const auto &match = *re_it;
4155 size_t pi = match.position();
4156 size_t l = match.length();
4157 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
4158
4159 auto it = argMap.find(match.str());
4160 if (it!=argMap.end())
4161 {
4162 int argIndex = it->second;
4163 QCString marker;
4164 marker.sprintf(" @%d ",argIndex);
4165 definition+=marker.str();
4166 }
4167 else
4168 {
4169 definition+=match.str();
4170 }
4171 i=pi+l;
4172 }
4173 definition+=in.substr(i);
QCString & sprintf(const char *format,...)
Definition qcstring.cpp:29
4174
4175 // add define definition to the dictionary of defines for this file
4176 std::string dname = ds.substr(0,i_obrace);
4177 if (!dname.empty())
4178 {
4179 Define def;
4180 def.name = dname;
4181 def.definition = definition;
4182 def.nargs = count;
4183 def.isPredefined = TRUE;
4184 def.nonRecursive = nonRecursive;
4185 def.fileDef = state->yyFileDef;
4186 def.fileName = fileName;
4187 def.varArgs = hasVarArgs;
4188 state->contextDefines.emplace(def.name.str(),def);
4189
4190 //printf("#define '%s' '%s' #nargs=%d hasVarArgs=%d\n",
4191 // qPrint(def.name),qPrint(def.definition),def.nargs,def.varArgs);
4192 }
4193 }
4194 else if (!ds.empty()) // predefined non-function macro definition
4195 {
4196 //printf("predefined normal macro '%s'\n",qPrint(ds));
4197 Define def;
4198 if (i_equals==std::string::npos) // simple define without argument
4199 {
4200 def.name = ds;
4201 def.definition = "1"; // substitute occurrences by 1 (true)
4202 }
4203 else // simple define with argument
4204 {
4205 int ine=static_cast<int>(i_equals) - (nonRecursive ? 1 : 0);
4206 def.name = ds.substr(0,ine);
4207 def.definition = ds.substr(i_equals+1);
4208 }
4209 if (!def.name.isEmpty())
4210 {
4211 def.nargs = -1;
4212 def.isPredefined = TRUE;
4213 def.nonRecursive = nonRecursive;
4214 def.fileDef = state->yyFileDef;
4215 def.fileName = fileName;
4216 state->contextDefines.emplace(def.name.str(),def);
4217 }
4218 }
4219 }
4220}

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 4074 of file pre.l.

4075{
4076 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
4077
4078 bool undef = false;
4079 auto findDefine = [&undef,&name](DefineMap &map)
4080 {
4081 Define *d=nullptr;
4082 auto it = map.find(name.str());
4083 if (it!=map.end())
4084 {
4085 d = &it->second;
4086 if (d->undef)
4087 {
4088 undef=true;
4089 d=nullptr;
4090 }
4091 }
4092 return d;
4093 };
bool undef
Definition define.h:41
std::map< std::string, Define > DefineMap
A dictionary of managed Define objects.
Definition pre.l:108
4094
4095 Define *def = findDefine(state->localDefines);
4096 if (def==nullptr && !undef)
4097 {
4098 def = findDefine(state->contextDefines);
4099 }
4100 return def;
4101}

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

Referenced by expandExpression().

◆ otherCaseDone()

bool otherCaseDone ( yyscan_t yyscanner)
static

Definition at line 2307 of file pre.l.

2308{
2309 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
2310 if (state->levelGuard.empty())
2311 {
2312 warn(state->fileName,state->yyLineNr,"Found an #else without a preceding #if.");
2313 return TRUE;
2314 }
2315 else
2316 {
2317 return state->levelGuard.top();
2318 }
2319}

References TRUE, and warn.

◆ outputArray()

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

Definition at line 3682 of file pre.l.

3683{
3684 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
3685 if (state->includeStack.empty() || state->curlyCount>0) (*state->outputBuf)+=std::string_view(a,len);
3686}

◆ outputChar()

void outputChar ( yyscan_t yyscanner,
char c )
inlinestatic

Definition at line 3676 of file pre.l.

3677{
3678 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
3679 if (state->includeStack.empty() || state->curlyCount>0) (*state->outputBuf)+=c;
3680}

Referenced by outputSpace(), and outputSpaces().

◆ outputSpace()

void outputSpace ( yyscan_t yyscanner,
char c )
inlinestatic

Definition at line 3694 of file pre.l.

3695{
3696 if (c=='\t') outputChar(yyscanner,'\t');
3697 else outputChar(yyscanner,' ');
static void outputChar(yyscan_t yyscanner, char c)
Definition pre.l:3676
3698}

References outputChar().

◆ outputSpaces()

void outputSpaces ( yyscan_t yyscanner,
char * s )
inlinestatic

Definition at line 3700 of file pre.l.

3701{
3702 const char *p=s;
3703 char c = 0;
3704 while ((c=*p++))
3705 {
3706 if (c=='\t') outputChar(yyscanner,'\t');
3707 else outputChar(yyscanner,' ');
3708 }
3709}

References outputChar().

◆ outputString()

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

Definition at line 3688 of file pre.l.

3689{
3690 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
3691 if (state->includeStack.empty() || state->curlyCount>0) (*state->outputBuf)+=a.str();
3692}

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 2587 of file pre.l.

2588{
2589 if (expr.isEmpty()) return;
2590 //printf("processConcatOperators: in='%s'\n",qPrint(expr));
2591 std::string e = expr.str();
2592 static const reg::Ex r(R"(\s*##\s*)");
DirIterator end(const DirIterator &) noexcept
Definition dir.cpp:175
2594
2595 size_t i=0;
2596 for (;;)
2597 {
2598 reg::Iterator it(e,r,i);
2599 if (it!=end)
2600 {
2601 const auto &match = *it;
2602 size_t n = match.position();
2603 size_t l = match.length();
2604 //printf("Match: '%s'\n",qPrint(expr.mid(i)));
2605 if (n+l+1<e.length() && e[static_cast<int>(n+l)]=='@' && expr[static_cast<int>(n+l+1)]=='-')
2606 {
2607 // remove no-rescan marker after ID
2608 l+=2;
2609 }
2610 //printf("found '%s'\n",qPrint(expr.mid(n,l)));
2611 // remove the ## operator and the surrounding whitespace
2612 e=e.substr(0,n)+e.substr(n+l);
2613 int k=static_cast<int>(n)-1;
2614 while (k>=0 && isId(e[k])) k--;
2615 if (k>0 && e[k]=='-' && e[k-1]=='@')
2616 {
2617 // remove no-rescan marker before ID
2618 e=e.substr(0,k-1)+e.substr(k+1);
2619 n-=2;
2620 }
2621 i=n;
2622 }
2623 else
2624 {
2625 break;
2626 }
2627 }
2628
2629 expr = e;
2630
2631 //printf("processConcatOperators: out='%s'\n",qPrint(expr));
2632}

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 3239 of file pre.l.

3240{
3241 if (inputStr==nullptr) return inputStr;
3242 char term = *inputStr; // capture start character of the literal
3243 if (term!='\'' && term!='"') return inputStr; // not a valid literal
3244 char c=term;
3245 // output start character
3246 result+=c;
3247 inputStr++;
3248 while ((c=*inputStr)) // while inside the literal
3249 {
3250 if (c==term) // found end marker of the literal
3251 {
3252 // output end character and stop
3253 result+=c;
3254 inputStr++;
3255 break;
3256 }
3257 else if (c=='\\') // escaped character, process next character
3258 // as well without checking for end marker.
3259 {
3260 result+=c;
3261 inputStr++;
3262 c=*inputStr;
3263 if (c==0) break; // unexpected end of string after escape character
3264 }
3265 result+=c;
3266 inputStr++;
3267 }
3268 return inputStr;
3269}

References term.

Referenced by removeIdsAndMarkers(), and removeMarkers().

◆ readIncludeFile()

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

Definition at line 3757 of file pre.l.

3758{
3759 AUTO_TRACE("inc={}",inc);
3760 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
3761 uint32_t i=0;
#define AUTO_TRACE(...)
Definition docnode.cpp:48
3762
3763 // find the start of the include file name
3764 while (i<inc.length() &&
3765 (inc.at(i)==' ' || inc.at(i)=='"' || inc.at(i)=='<')
3766 ) i++;
3767 uint32_t s=i;
3768
3769 // was it a local include?
3770 bool localInclude = s>0 && inc.at(s-1)=='"';
3771
3772 // find the end of the include file name
3773 while (i<inc.length() && inc.at(i)!='"' && inc.at(i)!='>') i++;
3774
3775 if (s<inc.length() && i>s) // valid include file name found
3776 {
3777 // extract include path+name
3778 QCString incFileName=inc.mid(s,i-s).stripWhiteSpace();
3779 if (incFileName.endsWith(".exe") || incFileName.endsWith(".dll") || incFileName.endsWith(".tlb"))
3780 {
3781 // skip imported binary files (e.g. M$ type libraries)
3782 return;
3783 }
bool endsWith(const char *s) const
Definition qcstring.h:524
3784
3785 QCString oldFileName = state->fileName;
3786 FileDef *oldFileDef = state->yyFileDef;
3787 int oldLineNr = state->yyLineNr;
3788 //printf("Searching for '%s'\n",qPrint(incFileName));
3789
3790 QCString absIncFileName = determineAbsoluteIncludeName(state->fileName,incFileName);
QCString determineAbsoluteIncludeName(const QCString &curFile, const QCString &incFileName)
Definition util.cpp:3621
3791
3792 // findFile will overwrite state->yyFileDef if found
3793 std::unique_ptr<FileState> fs;
3794 bool alreadyProcessed = FALSE;
3795 //printf("calling findFile(%s)\n",qPrint(incFileName));
3796 fs=findFile(yyscanner,absIncFileName,localInclude,alreadyProcessed); // see if the absolute include file can be found
3797 if (fs)
3798 {
3799 {
3800 std::lock_guard<std::mutex> lock(g_globalDefineMutex);
3801 g_defineManager.addInclude(oldFileName.str(),absIncFileName.str());
3802 }
static std::unique_ptr< FileState > findFile(yyscan_t yyscanner, const QCString &fileName, bool localInclude, bool &alreadyProcessed)
Definition pre.l:2385
3803
3804 //printf("Found include file!\n");
3806 {
3807 for (i=0;i<state->includeStack.size();i++)
3808 {
3810 }
3811 Debug::print(Debug::Preprocessor,0,"#include {}: parsing...\n",incFileName);
3812 }
@ Preprocessor
Definition debug.h:30
static bool isFlagSet(const DebugMask mask)
Definition debug.cpp:133
static void print(DebugMask mask, int prio, fmt::format_string< Args... > fmt, Args &&... args)
Definition debug.h:77
3813
3814 if (state->includeStack.empty() && oldFileDef)
3815 {
3816 PreIncludeInfo *ii = state->includeRelations.find(absIncFileName);
3817 if (ii==nullptr)
3818 {
3819 bool ambig = false;
3820 FileDef *incFd = findFileDef(Doxygen::inputNameLinkedMap,absIncFileName,ambig);
3821 state->includeRelations.add(
3822 absIncFileName,
3823 oldFileDef,
3824 ambig ? nullptr : incFd,
3825 incFileName,
3826 localInclude,
3827 state->isImported
3828 );
3829 }
3830 }
3831
3832 struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
3833 fs->bufState = YY_CURRENT_BUFFER;
3834 fs->lineNr = oldLineNr;
3835 fs->fileName = oldFileName;
3836 fs->curlyCount = state->curlyCount;
3837 //state->curlyCount = 0; // don't reset counter, see issue #10997
3838 fs->lexRulesPart = state->lexRulesPart;
3839 fs->levelGuard = state->levelGuard;
3840 while (!state->levelGuard.empty()) state->levelGuard.pop();
3841 state->lexRulesPart = false;
3842 // push the state on the stack
3843 FileState *fs_ptr = fs.get();
3844 state->includeStack.push_back(std::move(fs));
3845 // set the scanner to the include file
3846
3847 // Deal with file changes due to
3848 // #include's within { .. } blocks
3849 QCString lineStr(state->fileName.length()+20, QCString::ExplicitSize);
3850 lineStr.sprintf("# 1 \"%s\" 1\n",qPrint(state->fileName));
3851 outputString(yyscanner,lineStr);
@ ExplicitSize
Definition qcstring.h:146
static void outputString(yyscan_t yyscanner, const QCString &s)
Definition pre.l:3688
const char * qPrint(const char *s)
Definition qcstring.h:687
3852
3853 AUTO_TRACE_ADD("Switching to include file {}",incFileName);
3854 state->expectGuard=TRUE;
3855 state->inputBuf = &fs_ptr->fileBuf;
3856 state->inputBufPos=0;
3857 yy_switch_to_buffer(yy_create_buffer(0, YY_BUF_SIZE, yyscanner),yyscanner);
3858 }
3859 else
3860 {
3861 if (alreadyProcessed) // if this header was already process we can just copy the stored macros
3862 // in the local context
3863 {
3864 std::lock_guard<std::mutex> lock(g_globalDefineMutex);
3865 g_defineManager.addInclude(state->fileName.str(),absIncFileName.str());
3866 g_defineManager.retrieve(absIncFileName.str(),state->contextDefines);
3867 }
#define YY_BUF_SIZE
Definition commentcnv.l:19
#define AUTO_TRACE_ADD(...)
Definition docnode.cpp:49
std::string fileBuf
Definition pre.l:84
3868
3869 if (state->includeStack.empty() && oldFileDef)
3870 {
3871 PreIncludeInfo *ii = state->includeRelations.find(absIncFileName);
3872 if (ii==nullptr)
3873 {
3874 bool ambig = false;
3875 FileDef *incFd = findFileDef(Doxygen::inputNameLinkedMap,absIncFileName,ambig);
3876 ii = state->includeRelations.add(absIncFileName,
3877 oldFileDef,
3878 ambig ? nullptr : incFd,
3879 incFileName,
3880 localInclude,
3881 state->isImported
3882 );
3883 }
3884 }
3885
3887 {
3888 for (i=0;i<state->includeStack.size();i++)
3889 {
3891 }
3892 if (alreadyProcessed)
3893 {
3894 Debug::print(Debug::Preprocessor,0,"#include {}: already processed! skipping...\n",incFileName);
3895 }
3896 else
3897 {
3898 Debug::print(Debug::Preprocessor,0,"#include {}: not found! skipping...\n",incFileName);
3899 }
3900 //printf("error: include file %s not found\n",yytext);
3901 }
3902 if (localInclude && !state->includeStack.empty() && state->curlyCount>0 && !alreadyProcessed) // failed to find #include inside { ... }
3903 {
3904 warn(state->fileName,state->yyLineNr,"include file {} not found, perhaps you forgot to add its directory to INCLUDE_PATH?",incFileName);
3905 }
3906 }
3907 }
3908}

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 3275 of file pre.l.

3276{
3277 static const std::vector<std::string> signs = { "signed", "unsigned" };
3278 struct TypeInfo { std::string name; size_t size; };
3279 static const std::vector<TypeInfo> types = {
3280 { "short int", sizeof(short int) },
3281 { "long long int", sizeof(long long int) },
3282 { "long int", sizeof(long int) },
3283 { "long long", sizeof(long long) },
3284 { "long double", sizeof(long double) },
3285 { "int", sizeof(int) },
3286 { "short", sizeof(short) },
3287 { "bool", sizeof(bool) },
3288 { "long", sizeof(long) },
3289 { "char", sizeof(char) },
3290 { "float", sizeof(float) },
3291 { "double", sizeof(double) },
3292 };
3293
3294 // Check if string p starts with basic types ending with a ')', such as 'signed long)' or ' float )'
3295 // and return the pointer just past the ')' and the size of the type as a tuple.
3296 // If the pattern is not found the tuple (nullptr,0) is returned.
3297 auto process_cast_or_sizeof = [](const char *p) -> std::pair<const char *,size_t>
3298 {
3299 const char *q = p;
3300 while (*q==' ' || *q=='\t') q++;
3301 bool found=false;
3302 size_t size = sizeof(int); // '(signed)' or '(unsigned)' is an int type
3303 for (const auto &sgn : signs)
3304 {
3305 if (qstrncmp(q,sgn.c_str(),sgn.length())==0) { q+=sgn.length(); found=true; }
3306 }
3307 if (!found || *q==' ' || *q=='\t' || *q==')') // continue searching
3308 {
3309 while (*q==' ' || *q=='\t') q++;
3310 for (const auto &t : types)
3311 {
3312 if (qstrncmp(q,t.name.c_str(),t.name.length())==0)
3313 {
3314 q += t.name.length();
3315 size = t.size;
3316 break;
3317 }
3318 }
3319 while (*q==' ' || *q=='\t') q++;
3320 if (*q==')') return std::make_pair(++q,size);
3321 }
3322 return std::make_pair(nullptr,0);
3323 };
int qstrncmp(const char *str1, const char *str2, size_t len)
Definition qcstring.h:75
3324
3325 //printf("removeIdsAndMarkers(%s)\n",qPrint(s));
3326 if (s.isEmpty()) return s;
3327 const char *p=s.data();
3328 bool inNum=FALSE;
3329 QCString result;
3330 if (p)
3331 {
3332 char c = 0;
3333 while ((c=*p))
3334 {
3335 if (c=='(') // potential cast, ignore it
3336 {
3337 const char *q = process_cast_or_sizeof(p+1).first;
3338 //printf("potential cast:\nin: %s\nout: %s\n",p,q);
3339 if (q)
3340 {
3341 p=q;
3342 continue;
3343 }
3344 }
3345 else if (c=='s' && literal_at(p,"sizeof")) // sizeof(...)
3346 {
3347 const char *q = p+6;
3348 while (*q==' ' || *q=='\t') q++;
3349 if (*q=='(')
3350 {
3351 auto r = process_cast_or_sizeof(q+1);
3352 //printf("sizeof:\nin: %s\nout: %zu%s\n--> sizeof=%zu\n",p,r.second,r.first,r.second);
3353 if (r.first)
3354 {
3355 result+=QCString().setNum(r.second);
3356 p=r.first;
3357 continue;
3358 }
3359 }
3360 }
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
3361
3362 if (c=='@') // replace @@ with @ and remove @E
3363 {
3364 if (*(p+1)=='@')
3365 {
3366 result+=c;
3367 }
3368 else if (*(p+1)=='E')
3369 {
3370 // skip
3371 }
3372 p+=2;
3373 }
3374 else if (isdigit(c)) // number
3375 {
3376 result+=c;
3377 p++;
3378 inNum=TRUE;
3379 }
3380 else if (c=='\'') // quoted character
3381 {
3382 p = processUntilMatchingTerminator(p,result);
3383 }
3384 else if (c=='d' && !inNum) // identifier starting with a 'd'
3385 {
3386 if (literal_at(p,"defined ") || literal_at(p,"defined("))
3387 // defined keyword
3388 {
3389 p+=7; // skip defined
3390 }
3391 else
3392 {
3393 result+="0L";
3394 p++;
3395 while ((c=*p) && isId(c)) p++;
3396 }
3397 }
3398 else if ((isalpha(c) || c=='_') && !inNum) // replace identifier with 0L
3399 {
3400 result+="0L";
3401 p++;
3402 while ((c=*p) && isId(c)) p++;
3403 while ((c=*p) && isspace((uint8_t)c)) p++;
3404 if (*p=='(') // undefined function macro
3405 {
3406 p++;
3407 int count=1;
3408 while ((c=*p++))
3409 {
3410 if (c=='(') count++;
3411 else if (c==')')
3412 {
3413 count--;
3414 if (count==0) break;
3415 }
3416 else if (c=='/')
3417 {
3418 char pc=c;
3419 c=*++p;
3420 if (c=='*') // start of C comment
3421 {
3422 while (*p && !(pc=='*' && c=='/')) // search end of comment
3423 {
3424 pc=c;
3425 c=*++p;
3426 }
3427 p++;
3428 }
3429 }
3430 }
3431 }
3432 }
3433 else if (c=='/') // skip C comments
3434 {
3435 char pc=c;
3436 c=*++p;
3437 if (c=='*') // start of C comment
3438 {
3439 while (*p && !(pc=='*' && c=='/')) // search end of comment
3440 {
3441 pc=c;
3442 c=*++p;
3443 }
3444 p++;
3445 }
3446 else // oops, not comment but division
3447 {
3448 result+=pc;
3449 goto nextChar;
3450 }
3451 }
3452 else
3453 {
static const char * processUntilMatchingTerminator(const char *inputStr, QCString &result)
Process string or character literal.
Definition pre.l:3239
3454nextChar:
3455 result+=c;
3456 char lc=(char)tolower(c);
3457 if (!isId(lc) && lc!='.' /*&& lc!='-' && lc!='+'*/) inNum=FALSE;
3458 p++;
3459 }
3460 }
3461 }
3462 //printf("removeIdsAndMarkers(%s)=%s\n",s,qPrint(result));
3463 return result;
3464}

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 3470 of file pre.l.

3471{
3472 if (s.isEmpty()) return s;
3473 const char *p=s.data();
3474 QCString result;
3475 if (p)
3476 {
3477 char c = 0;
3478 while ((c=*p))
3479 {
3480 switch(c)
3481 {
3482 case '@': // replace @@ with @
3483 {
3484 if (*(p+1)=='@')
3485 {
3486 result+=c;
3487 }
3488 p+=2;
3489 }
3490 break;
3491 case '/': // skip C comments
3492 {
3493 result+=c;
3494 char pc=c;
3495 c=*++p;
3496 if (c=='*') // start of C comment
3497 {
3498 while (*p && !(pc=='*' && c=='/')) // search end of comment
3499 {
3500 if (*p=='@' && *(p+1)=='@')
3501 {
3502 result+=c;
3503 p++;
3504 }
3505 else
3506 {
3507 result+=c;
3508 }
3509 pc=c;
3510 c=*++p;
3511 }
3512 if (*p)
3513 {
3514 result+=c;
3515 p++;
3516 }
3517 }
3518 }
3519 break;
3520 case '"': // skip string literals
3521 case '\'': // skip char literals
3522 p = processUntilMatchingTerminator(p,result);
3523 break;
3524 default:
3525 {
3526 result+=c;
3527 p++;
3528 }
3529 break;
3530 }
3531 }
3532 }
3533 //printf("RemoveMarkers(%s)=%s\n",s,qPrint(result));
3534 return result;
3535}

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 2743 of file pre.l.

2744{
2745 //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());
2746 uint32_t j=pos;
2747 len=0;
2748 result.clear();
2749 int cc;
2750
2751 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:2659
2752
2753 if (cc!='(')
2754 {
2755 if (cc!=':') // don't add spaces for colons
2756 {
2757 unputChar(yyscanner,expr,rest,j,' ');
2758 }
2759 return FALSE;
2760 }
2761 getNextChar(yyscanner,expr,rest,j); // eat the '(' character
2762
2763 std::map<std::string,std::string> argTable; // list of arguments
2764 QCString arg;
2765 int argCount=0;
2766 int argCountNonEmpty=0;
2767 bool done=FALSE;
2768
2769 // PHASE 1: read the macro arguments
2770 if (def->nargs==0)
2771 {
2772 while ((cc=getNextChar(yyscanner,expr,rest,j))!=EOF && cc!=0)
2773 {
2774 char c = (char)cc;
2775 if (c==')') break;
2776 }
2777 }
2778 else
2779 {
2780 while (!done && (argCount<def->nargs || def->varArgs) &&
2781 ((cc=getNextChar(yyscanner,expr,rest,j))!=EOF && cc!=0)
2782 )
2783 {
2784 char c=(char)cc;
2785 if (c=='(') // argument is a function => search for matching )
2786 {
2787 int lvl=1;
2788 arg+=c;
2789 //char term='\0';
2790 while ((cc=getNextChar(yyscanner,expr,rest,j))!=EOF && cc!=0)
2791 {
2792 c=(char)cc;
2793 //printf("processing %c: term=%c (%d)\n",c,term,term);
2794 if (c=='\'' || c=='\"') // skip ('s and )'s inside strings
2795 {
2796 arg+=c;
2797 addTillEndOfString(yyscanner,expr,rest,j,c,arg);
2798 }
2799 if (c==')')
2800 {
2801 lvl--;
2802 arg+=c;
2803 if (lvl==0) break;
2804 }
2805 else if (c=='(')
2806 {
2807 lvl++;
2808 arg+=c;
2809 }
2810 else
2811 {
2812 arg+=c;
2813 }
2814 }
2815 }
2816 else if (c==')' || c==',') // last or next argument found
2817 {
2818 if (c==',' && argCount==def->nargs-1 && def->varArgs)
2819 {
2820 expandExpression(yyscanner,arg,nullptr,0,level+1);
2821 arg=arg.stripWhiteSpace();
2822 arg+=',';
2823 }
2824 else
2825 {
2826 expandExpression(yyscanner,arg,nullptr,0,level+1);
2827 arg=arg.stripWhiteSpace();
2828 QCString argKey;
2829 argKey.sprintf("@%d",argCount++); // key name
2830 if (c==',' || !arg.isEmpty()) argCountNonEmpty++;
2831 // add argument to the lookup table
2832 argTable.emplace(toStdString(argKey), toStdString(arg));
2833 arg.clear();
2834 if (c==')') // end of the argument list
2835 {
2836 done=TRUE;
2837 }
2838 }
2839 }
2840 else if (c=='\"') // append literal strings
2841 {
2842 arg+=c;
2843 bool found=FALSE;
2844 while (!found && (cc=getNextChar(yyscanner,expr,rest,j))!=EOF && cc!=0)
2845 {
2846 found = cc=='"';
2847 if (cc=='\\')
2848 {
2849 c=(char)cc;
2850 arg+=c;
2851 if ((cc=getNextChar(yyscanner,expr,rest,j))==EOF || cc==0) break;
2852 }
2853 c=(char)cc;
2854 arg+=c;
2855 }
2856 }
2857 else if (c=='\'') // append literal characters
2858 {
2859 arg+=c;
2860 bool found=FALSE;
2861 while (!found && (cc=getNextChar(yyscanner,expr,rest,j))!=EOF && cc!=0)
2862 {
2863 found = cc=='\'';
2864 if (cc=='\\')
2865 {
2866 c=(char)cc;
2867 arg+=c;
2868 if ((cc=getNextChar(yyscanner,expr,rest,j))==EOF || cc==0) break;
2869 }
2870 c=(char)cc;
2871 arg+=c;
2872 }
2873 }
2874 else if (c=='/') // possible start of a comment
2875 {
2876 char prevChar = '\0';
2877 arg+=c;
2878 if ((cc=getCurrentChar(yyscanner,expr,rest,j)) == '*') // we have a comment
2879 {
2880 while ((cc=getNextChar(yyscanner,expr,rest,j))!=EOF && cc!=0)
2881 {
2882 c=(char)cc;
2883 arg+=c;
2884 if (c == '/' && prevChar == '*') break; // we have an end of comment
2885 prevChar = c;
2886 }
2887 }
2888 }
2889 else // append other characters
2890 {
2891 arg+=c;
2892 }
2893 }
2894 }
static int getCurrentChar(yyscan_t yyscanner, const QCString &expr, QCString *rest, uint32_t pos)
Definition pre.l:4027
static void addTillEndOfString(yyscan_t yyscanner, const QCString &expr, QCString *rest, uint32_t &pos, char term, QCString &arg)
Definition pre.l:2640
2895
2896 // PHASE 2: apply the macro function
2897 if (argCount==def->nargs || // same number of arguments
2898 (argCount>=def->nargs-1 && def->varArgs)) // variadic macro with at least as many
2899 // params as the non-variadic part (see bug731985)
2900 {
2901 uint32_t k=0;
2902 // substitution of all formal arguments
2903 QCString resExpr;
2905 //printf("varArgs=%d argCount=%d def->nargs=%d d=%s\n",def->varArgs,argCount,def->nargs,qPrint(d));
2906 if (def->varArgs) d = expandVAOpt(d,argCountNonEmpty!=def->nargs-1);
2907 //printf("Macro definition: '%s'\n",qPrint(d));
2908 bool inString=FALSE;
2909 while (k<d.length())
2910 {
2911 if (d.at(k)=='@') // maybe a marker, otherwise an escaped @
2912 {
2913 if (d.at(k+1)=='@') // escaped @ => copy it (is unescaped later)
2914 {
2915 k+=2;
2916 resExpr+="@@"; // we unescape these later
2917 }
2918 else if (d.at(k+1)=='-') // no-rescan marker
2919 {
2920 k+=2;
2921 resExpr+="@-";
2922 }
2923 else // argument marker => read the argument number
2924 {
2925 QCString key="@";
2926 bool hash=FALSE;
2927 int l=k-1;
2928 // search for ## backward
2929 if (l>=0 && d.at(l)=='"') l--;
2930 while (l>=0 && d.at(l)==' ') l--;
2931 if (l>0 && d.at(l)=='#' && d.at(l-1)=='#') hash=TRUE;
2932 k++;
2933 // scan the number
2934 while (k<d.length() && d.at(k)>='0' && d.at(k)<='9') key+=d.at(k++);
2935 if (!hash)
2936 {
2937 // search for ## forward
2938 l=k;
2939 if (l<(int)d.length() && d.at(l)=='"') l++;
2940 while (l<(int)d.length() && d.at(l)==' ') l++;
2941 if (l<(int)d.length()-1 && d.at(l)=='#' && d.at(l+1)=='#') hash=TRUE;
2942 }
2943 //printf("request key %s result %s\n",qPrint(key),argTable[key]->data());
2944 auto it = argTable.find(key.str());
2945 if (it!=argTable.end())
2946 {
2947 QCString substArg = it->second;
2948 //printf("substArg='%s'\n",qPrint(substArg));
2949 // only if no ## operator is before or after the argument
2950 // marker we do macro expansion.
2951 if (!hash)
2952 {
2953 expandExpression(yyscanner,substArg,nullptr,0,level+1);
2954 }
2955 if (inString)
2956 {
2957 //printf("'%s'=stringize('%s')\n",qPrint(stringize(*subst)),subst->data());
static QCString expandVAOpt(const QCString &vaStr, bool hasOptionalArgs)
Definition pre.l:2691
2958
2959 // if the marker is inside a string (because a # was put
2960 // before the macro name) we must escape " and \ characters
2961 resExpr+=stringize(substArg);
2962 }
2963 else
2964 {
2965 if (hash && substArg.isEmpty())
2966 {
2967 resExpr+="@E"; // empty argument will be remove later on
2968 }
2969 resExpr+=substArg;
2970 }
2971 }
2972 }
2973 }
2974 else // no marker, just copy
2975 {
2976 if (!inString && d.at(k)=='\"')
2977 {
2978 inString=TRUE; // entering a literal string
2979 }
2980 else if (k>2 && inString && d.at(k)=='\"' && (d.at(k-1)!='\\' || d.at(k-2)=='\\'))
2981 {
2982 inString=FALSE; // leaving a literal string
2983 }
2984 resExpr+=d.at(k++);
2985 }
2986 }
2987 len=j-pos;
2988 result=resExpr;
2989 //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());
2990 return TRUE;
2991 }
2992 //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());
2993 return FALSE;
static QCString stringize(const QCString &s)
Definition pre.l:2509
2994}

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 3984 of file pre.l.

3985{
3986 switch (c)
3987 {
3988 case '=': return '#';
3989 case '/': return '\\';
3990 case '\'': return '^';
3991 case '(': return '[';
3992 case ')': return ']';
3993 case '!': return '|';
3994 case '<': return '{';
3995 case '>': return '}';
3996 case '-': return '~';
3997 }
3998 return '?';
3999}

◆ returnCharToStream()

void returnCharToStream ( yyscan_t yyscanner,
char c )
static

Definition at line 2634 of file pre.l.

2635{
2636 struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
2637 unput(c);
2638}

Referenced by getCurrentChar(), and unputChar().

◆ setCaseDone()

void setCaseDone ( yyscan_t yyscanner,
bool value )
static

Definition at line 2321 of file pre.l.

2322{
2323 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
2324 state->levelGuard.top()=value;
2325}

◆ setFileName()

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

Definition at line 2258 of file pre.l.

2259{
2260 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
2261 bool ambig = false;
2262 FileInfo fi(name.str());
2263 state->fileName=fi.absFilePath();
2264 state->yyFileDef=findFileDef(Doxygen::inputNameLinkedMap,state->fileName,ambig);
2265 if (state->yyFileDef==nullptr) // if this is not an input file check if it is an include file
2266 {
2267 state->yyFileDef=findFileDef(Doxygen::includeNameLinkedMap,state->fileName,ambig);
2268 }
2269 //printf("setFileName(%s) state->fileName=%s state->yyFileDef=%p\n",
2270 // name,qPrint(state->fileName),state->yyFileDef);
2271 if (state->yyFileDef && state->yyFileDef->isReference()) state->yyFileDef=nullptr;
2272 state->insideIDL = getLanguageFromFileName(state->fileName)==SrcLangExt::IDL;
2273 state->insideCS = getLanguageFromFileName(state->fileName)==SrcLangExt::CSharp;
2274 state->insideFtn = getLanguageFromFileName(state->fileName)==SrcLangExt::Fortran;
2275 EntryType section = guessSection(state->fileName);
2276 state->isSource = section.isHeader() || section.isSource();
static FileNameLinkedMap * includeNameLinkedMap
Definition doxygen.h:101
Wrapper class for the Entry type.
Definition types.h:816
SrcLangExt getLanguageFromFileName(const QCString &fileName, SrcLangExt defLang)
Definition util.cpp:5231
EntryType guessSection(const QCString &name)
Definition util.cpp:338
2277}

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 2659 of file pre.l.

2661{
2662 bool changed = false;
2663
2664 do
2665 {
2666 changed = false;
2667 while ((cc=getCurrentChar(yyscanner,expr,rest,j))!=EOF && cc!='\n' && isspace(cc))
2668 {
2669 len++;
2670 getNextChar(yyscanner,expr,rest,j);
2671 }
2672
2673 if (cc=='/') // possible start of a comment
2674 {
2675 int prevChar = '\0';
2676 getNextChar(yyscanner,expr,rest,j);
2677 if ((cc=getCurrentChar(yyscanner,expr,rest,j))!=EOF && cc == '*') // we have a comment
2678 {
2679 while ((cc=getNextChar(yyscanner,expr,rest,j))!=EOF && cc!=0)
2680 {
2681 if (cc == '/' && prevChar == '*') break; // we have an end of comment
2682 prevChar = cc;
2683 }
2684 if (cc != EOF) changed = true;
2685 }
2686 }
2687 } while (changed);
2688}

References getCurrentChar(), and getNextChar().

Referenced by replaceFunctionMacro().

◆ startCondSection()

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

Definition at line 3912 of file pre.l.

3913{
3914 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
3915 //printf("startCondSection: skip=%d stack=%d\n",state->skip,state->condStack.size());
3916 CondParser prs;
3917 bool expResult = prs.parse(state->fileName.data(),state->yyLineNr,sectId.data());
3918 state->condStack.emplace(std::make_unique<preYY_CondCtx>(state->fileName,state->yyLineNr,sectId,state->skip));
3919 if (!expResult)
3920 {
3921 state->skip=TRUE;
3922 }
3923 //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.
3924}

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

◆ stateToString()

const char * stateToString ( int state)
static

◆ stringize()

QCString stringize ( const QCString & s)
static

Definition at line 2509 of file pre.l.

2510{
2511 QCString result;
2512 uint32_t i=0;
2513 bool inString=FALSE;
2514 bool inChar=FALSE;
2515 char c,pc;
2516 while (i<s.length())
2517 {
2518 if (!inString && !inChar)
2519 {
2520 while (i<s.length() && !inString && !inChar)
2521 {
2522 c=s.at(i++);
2523 if (c=='"')
2524 {
2525 result+="\\\"";
2526 inString=TRUE;
2527 }
2528 else if (c=='\'')
2529 {
2530 result+=c;
2531 inChar=TRUE;
2532 }
2533 else
2534 {
2535 result+=c;
2536 }
2537 }
2538 }
2539 else if (inChar)
2540 {
2541 while (i<s.length() && inChar)
2542 {
2543 c=s.at(i++);
2544 if (c=='\'')
2545 {
2546 result+='\'';
2547 inChar=FALSE;
2548 }
2549 else if (c=='\\')
2550 {
2551 result+="\\\\";
2552 }
2553 else
2554 {
2555 result+=c;
2556 }
2557 }
2558 }
2559 else
2560 {
2561 pc=0;
2562 while (i<s.length() && inString)
2563 {
2564 c=s.at(i++);
2565 if (c=='"')
2566 {
2567 result+="\\\"";
2568 inString= pc=='\\';
2569 }
2570 else if (c=='\\')
2571 result+="\\\\";
2572 else
2573 result+=c;
2574 pc=c;
2575 }
2576 }
2577 }
2578 //printf("stringize '%s'->'%s'\n",qPrint(s),qPrint(result));
2579 return result;
2580}

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 4050 of file pre.l.

4051{
4052 //printf("unputChar(%s,%s,%d,%c)\n",qPrint(expr),rest ? rest->data() : 0,pos,c);
4053 if (pos<expr.length())
4054 {
4055 pos++;
4056 }
4057 else if (rest)
4058 {
4059 //printf(" prepending '%c' to rest!\n",c);
4060 char cs[2];cs[0]=c;cs[1]='\0';
4061 rest->prepend(cs);
4062 }
4063 else
4064 {
4065 //printf(" yyunput()='%c'\n",c);
4066 returnCharToStream(yyscanner,c);
4067 }
4068 //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
4069}

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

Referenced by addSeparatorsIfNeeded(), and replaceFunctionMacro().

◆ yylex()

int yylex ( yyscan_t yyscanner)

Definition at line 489 of file pre.l.

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

◆ yyread()

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

Definition at line 2237 of file pre.l.

2238{
2239 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
2240 int bytesInBuf = static_cast<int>(state->inputBuf->size())-state->inputBufPos;
2241 int bytesToCopy = std::min(max_size,bytesInBuf);
2242 memcpy(buf,state->inputBuf->data()+state->inputBufPos,bytesToCopy);
2243 state->inputBufPos+=bytesToCopy;
2244 return bytesToCopy;
2245}

Variable Documentation

◆ g_debugMutex

std::mutex g_debugMutex
static

Definition at line 232 of file pre.l.

Referenced by Preprocessor::processFile().

◆ g_defineManager

DefineManager g_defineManager
static

Definition at line 235 of file pre.l.

Referenced by checkAndOpenFile(), and readIncludeFile().

◆ g_globalDefineMutex

std::mutex g_globalDefineMutex
static

Definition at line 233 of file pre.l.

Referenced by checkAndOpenFile(), and readIncludeFile().

◆ g_updateGlobals

std::mutex g_updateGlobals
static

Definition at line 234 of file pre.l.

Referenced by Preprocessor::processFile().