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

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

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

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

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

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

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

2635{
2636 int cc;
2637 while ((cc=getNextChar(yyscanner,expr,rest,pos))!=EOF && cc!=0)
2638 {
2639 if (cc=='\\')
2640 {
2641 arg+=(char)cc;
2642 cc=getNextChar(yyscanner,expr,rest,pos);
2643 }
2644 else if (cc==term)
2645 {
2646 return;
2647 }
2648 arg+=(char)cc;
2649 }
#define term(fmt,...)
Definition message.h:137
2650}

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

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

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

3535{
3536 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
3537 QCString e=expr;
3538 QCString ee=expr;
3539 ee = removeMarkers(ee);
3540 state->expanded.clear();
3541 expandExpression(yyscanner,e,nullptr,0,0);
3542 //printf("after expansion '%s'\n",qPrint(e));
3543 e = removeIdsAndMarkers(e);
3544 if (e.isEmpty()) return FALSE;
3545 //printf("parsing '%s'\n",qPrint(e));
3546 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:3082
static QCString removeIdsAndMarkers(const QCString &s)
Definition pre.l:3268
static QCString removeMarkers(const QCString &s)
Definition pre.l:3463
3547}

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

◆ decrLevel()

void decrLevel ( yyscan_t yyscanner)
static

Definition at line 2279 of file pre.l.

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

References warn.

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

◆ determineBlockName()

void determineBlockName ( yyscan_t yyscanner)
static

Definition at line 3717 of file pre.l.

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

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

◆ endCondSection()

void endCondSection ( yyscan_t yyscanner)
static

Definition at line 3919 of file pre.l.

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

References FALSE, and warn.

◆ escapeAt()

QCString escapeAt ( const QCString & text)
static

Definition at line 3962 of file pre.l.

3963{
3964 QCString result;
3965 if (!text.isEmpty())
3966 {
3967 char c = 0;
3968 const char *p=text.data();
3969 while ((c=*p++))
3970 {
3971 if (c=='@') result+="@@"; else result+=c;
3972 }
3973 }
3974 return result;
3975}

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

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

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

3554{
3555 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3556 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
3557 state->prevChar = yyscanner->yytext_r > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ? *(yyscanner->yytext_r-1) : 0;
3558 QCString n=name;
3559 state->expanded.clear();
3560 expandExpression(yyscanner,n,nullptr,0,0);
3561 n=removeMarkers(n);
3562 state->prevChar=0;
3563 //printf("expandMacro '%s'->'%s'\n",qPrint(name),qPrint(n));
3564 return n;
void clear()
Definition qcstring.h:182
3565}

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

◆ expandStandardMacro()

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

Definition at line 3567 of file pre.l.

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

References QCString::setNum().

Referenced by expandExpression().

◆ expandVAOpt()

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

Definition at line 2684 of file pre.l.

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

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

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

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

◆ extraSpacing()

void extraSpacing ( yyscan_t yyscanner)
inlinestatic

Definition at line 3704 of file pre.l.

3705{
3706 struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
3707 if (!yyextra->defContinue) return;
3708 for (int i=0; i< (int)yyleng; i++)
3709 {
3710 if (yytext[i] == '\t')
3711 yyextra->defExtraSpacing+='\t';
3712 else
3713 yyextra->defExtraSpacing+=' ';
3714 }
3715}

◆ findFile()

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

Definition at line 2378 of file pre.l.

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

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

3953{
3954 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
3955 while (!state->condStack.empty())
3956 {
3957 state->condStack.pop();
3958 }
3959 state->skip=FALSE;
3960}

References FALSE.

Referenced by Preprocessor::processFile().

◆ getCurrentChar()

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

Definition at line 4020 of file pre.l.

4021{
4022 //printf("getCurrentChar(%s,%s,%d)\n",qPrint(expr),rest ? rest->data() : 0,pos);
4023 if (pos<expr.length())
4024 {
4025 //printf("%c=expr()\n",expr.at(pos));
4026 return expr.at(pos);
4027 }
4028 else if (rest && !rest->isEmpty())
4029 {
4030 int cc=rest->at(0);
4031 //printf("%c=rest\n",cc);
4032 return cc;
4033 }
4034 else
4035 {
4036 int cc=yyinput(yyscanner);
4037 returnCharToStream(yyscanner,(char)cc);
4038 //printf("%c=yyinput()\n",cc);
4039 return cc;
4040 }
static void returnCharToStream(yyscan_t yyscanner, char c)
Definition pre.l:2627
4041}

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

2241{
2242 yy_size_t fenceSize = 0;
2243 for (size_t i = 0; i < leng; i++)
2244 {
2245 if (txt[i] != ' ' && txt[i] != '*' && txt[i] != '\t') break;
2246 fenceSize++;
2247 }
2248 return leng-fenceSize;
2249}

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

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

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

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

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

Referenced by expandExpression().

◆ incrLevel()

void incrLevel ( yyscan_t yyscanner)
static

Definition at line 2272 of file pre.l.

2273{
2274 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
2275 state->levelGuard.push(false);
2276 //printf("%s line %d: incrLevel %zu\n",qPrint(state->fileName),state->yyLineNr,state->levelGuard.size());
2277}

◆ initPredefined()

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

Definition at line 4096 of file pre.l.

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

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

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

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

Referenced by expandExpression().

◆ otherCaseDone()

bool otherCaseDone ( yyscan_t yyscanner)
static

Definition at line 2300 of file pre.l.

2301{
2302 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
2303 if (state->levelGuard.empty())
2304 {
2305 warn(state->fileName,state->yyLineNr,"Found an #else without a preceding #if.");
2306 return TRUE;
2307 }
2308 else
2309 {
2310 return state->levelGuard.top();
2311 }
2312}

References TRUE, and warn.

◆ outputArray()

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

Definition at line 3675 of file pre.l.

3676{
3677 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
3678 if (state->includeStack.empty() || state->curlyCount>0) (*state->outputBuf)+=std::string_view(a,len);
3679}

◆ outputChar()

void outputChar ( yyscan_t yyscanner,
char c )
inlinestatic

Definition at line 3669 of file pre.l.

3670{
3671 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
3672 if (state->includeStack.empty() || state->curlyCount>0) (*state->outputBuf)+=c;
3673}

Referenced by outputSpace(), and outputSpaces().

◆ outputSpace()

void outputSpace ( yyscan_t yyscanner,
char c )
inlinestatic

Definition at line 3687 of file pre.l.

3688{
3689 if (c=='\t') outputChar(yyscanner,'\t');
3690 else outputChar(yyscanner,' ');
static void outputChar(yyscan_t yyscanner, char c)
Definition pre.l:3669
3691}

References outputChar().

◆ outputSpaces()

void outputSpaces ( yyscan_t yyscanner,
char * s )
inlinestatic

Definition at line 3693 of file pre.l.

3694{
3695 const char *p=s;
3696 char c = 0;
3697 while ((c=*p++))
3698 {
3699 if (c=='\t') outputChar(yyscanner,'\t');
3700 else outputChar(yyscanner,' ');
3701 }
3702}

References outputChar().

◆ outputString()

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

Definition at line 3681 of file pre.l.

3682{
3683 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
3684 if (state->includeStack.empty() || state->curlyCount>0) (*state->outputBuf)+=a.str();
3685}

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

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

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

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

References term.

Referenced by removeIdsAndMarkers(), and removeMarkers().

◆ readIncludeFile()

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

Definition at line 3750 of file pre.l.

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

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

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

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

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

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

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

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

3978{
3979 switch (c)
3980 {
3981 case '=': return '#';
3982 case '/': return '\\';
3983 case '\'': return '^';
3984 case '(': return '[';
3985 case ')': return ']';
3986 case '!': return '|';
3987 case '<': return '{';
3988 case '>': return '}';
3989 case '-': return '~';
3990 }
3991 return '?';
3992}

◆ returnCharToStream()

void returnCharToStream ( yyscan_t yyscanner,
char c )
static

Definition at line 2627 of file pre.l.

2628{
2629 struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
2630 unput(c);
2631}

Referenced by getCurrentChar(), and unputChar().

◆ setCaseDone()

void setCaseDone ( yyscan_t yyscanner,
bool value )
static

Definition at line 2314 of file pre.l.

2315{
2316 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
2317 state->levelGuard.top()=value;
2318}

◆ setFileName()

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

Definition at line 2251 of file pre.l.

2252{
2253 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
2254 bool ambig = false;
2255 FileInfo fi(name.str());
2256 state->fileName=fi.absFilePath();
2257 state->yyFileDef=findFileDef(Doxygen::inputNameLinkedMap,state->fileName,ambig);
2258 if (state->yyFileDef==nullptr) // if this is not an input file check if it is an include file
2259 {
2260 state->yyFileDef=findFileDef(Doxygen::includeNameLinkedMap,state->fileName,ambig);
2261 }
2262 //printf("setFileName(%s) state->fileName=%s state->yyFileDef=%p\n",
2263 // name,qPrint(state->fileName),state->yyFileDef);
2264 if (state->yyFileDef && state->yyFileDef->isReference()) state->yyFileDef=nullptr;
2265 state->insideIDL = getLanguageFromFileName(state->fileName)==SrcLangExt::IDL;
2266 state->insideCS = getLanguageFromFileName(state->fileName)==SrcLangExt::CSharp;
2267 state->insideFtn = getLanguageFromFileName(state->fileName)==SrcLangExt::Fortran;
2268 EntryType section = guessSection(state->fileName);
2269 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
2270}

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

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

References getCurrentChar(), and getNextChar().

Referenced by replaceFunctionMacro().

◆ startCondSection()

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

Definition at line 3905 of file pre.l.

3906{
3907 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
3908 //printf("startCondSection: skip=%d stack=%d\n",state->skip,state->condStack.size());
3909 CondParser prs;
3910 bool expResult = prs.parse(state->fileName.data(),state->yyLineNr,sectId.data());
3911 state->condStack.emplace(std::make_unique<preYY_CondCtx>(state->fileName,state->yyLineNr,sectId,state->skip));
3912 if (!expResult)
3913 {
3914 state->skip=TRUE;
3915 }
3916 //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.
3917}

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

◆ stateToString()

const char * stateToString ( int state)
static

◆ stringize()

QCString stringize ( const QCString & s)
static

Definition at line 2502 of file pre.l.

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

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

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

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:3977
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:3675
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:3553
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:3750
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:2272
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:2300
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:2314
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:2279
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:3534
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:3693
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:3704
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->defText+=yytext;
1498 yyextra->defLitText+=yytext;
1499 yyextra->lastCContext=YY_START;
1500 yyextra->commentCount=1;
1501 BEGIN(CopyCComment);
1502 }
1503<DefineText>{CPPC}[!/]? {
1504 outputArray(yyscanner,yytext,yyleng);
1505 yyextra->lastCPPContext=YY_START;
1506 yyextra->defLitText+=' ';
1507 BEGIN(SkipCPPComment);
1508 }
1509<SkipCComment>[/]?{CCE} {
1510 if (yytext[0]=='/') outputChar(yyscanner,'/');
1511 outputChar(yyscanner,'*');outputChar(yyscanner,'/');
1512 if (--yyextra->commentCount<=0)
1513 {
1514 if (yyextra->lastCContext==Start)
1515 // small hack to make sure that ^... rule will
1516 // match when going to Start... Example: "/*...*/ some stuff..."
1517 {
1518 YY_CURRENT_BUFFER->yy_at_bol=1;
1519 }
1520 BEGIN(yyextra->lastCContext);
1521 }
1522 }
1523<SkipCComment>{CPPC}("/")* {
1524 outputArray(yyscanner,yytext,yyleng);
1525 }
1526<SkipCComment>{CCS} {
1527 outputChar(yyscanner,'/');outputChar(yyscanner,'*');
1528 //yyextra->commentCount++;
1529 }
1530<SkipCond>{CMD}{CMD} { }
1531<SkipCond>^({B}*"*"+)?{B}{0,3}"~~~"[~]* {
1532 bool markdownSupport = Config_getBool(MARKDOWN_SUPPORT);
1533 if (!markdownSupport || !yyextra->isSpecialComment)
1534 {
1535 REJECT;
1536 }
1537 else
1538 {
1539 yyextra->fenceChar='~';
1540 yyextra->fenceSize=(int)getFenceSize(yytext,yyleng);
1541 BEGIN(SkipCondVerbatim);
1542 }
1543 }
static yy_size_t getFenceSize(char *txt, yy_size_t leng)
Definition pre.l:2240
1544<SkipCond>^({B}*"*"+)?{B}{0,3}"```"[`]* {
1545 bool markdownSupport = Config_getBool(MARKDOWN_SUPPORT);
1546 if (!markdownSupport || !yyextra->isSpecialComment)
1547 {
1548 REJECT;
1549 }
1550 else
1551 {
1552 yyextra->fenceChar='`';
1553 yyextra->fenceSize=(int)getFenceSize(yytext,yyleng);
1554 BEGIN(SkipCondVerbatim);
1555 }
1556 }
1557<SkipCComment>^({B}*"*"+)?{B}{0,3}"~~~"[~]* {
1558 bool markdownSupport = Config_getBool(MARKDOWN_SUPPORT);
1559 if (!markdownSupport || !yyextra->isSpecialComment)
1560 {
1561 REJECT;
1562 }
1563 else
1564 {
1565 outputArray(yyscanner,yytext,yyleng);
1566 yyextra->fenceChar='~';
1567 yyextra->fenceSize=(int)getFenceSize(yytext,yyleng);
1568 BEGIN(SkipVerbatim);
1569 }
1570 }
1571<SkipCComment>^({B}*"*"+)?{B}{0,3}"```"[`]* {
1572 bool markdownSupport = Config_getBool(MARKDOWN_SUPPORT);
1573 if (!markdownSupport || !yyextra->isSpecialComment)
1574 {
1575 REJECT;
1576 }
1577 else
1578 {
1579 outputArray(yyscanner,yytext,yyleng);
1580 yyextra->fenceChar='`';
1581 yyextra->fenceSize=(int)getFenceSize(yytext,yyleng);
1582 BEGIN(SkipVerbatim);
1583 }
1584 }
1585<SkipCComment>{CMD}{VERBATIM_LINE} |
1586<SkipCComment>{CMD}{LITERAL_BLOCK} { // escaped command
1587 outputArray(yyscanner,yytext,yyleng);
1588 yyextra->yyLineNr+=QCString(yytext).contains('\n');
1589 }
1590<SkipCComment>{VERBATIM_LINE}.*/\n { // normal command
1591 outputArray(yyscanner,yytext,yyleng);
1592 }
1593<SkipCComment>{LITERAL_BLOCK} { // normal block command
1594 outputArray(yyscanner,yytext,yyleng);
1595 yyextra->yyLineNr+=QCString(yytext).contains('\n');
1596 if (yyextra->isSpecialComment)
1597 {
1598 determineBlockName(yyscanner);
1599 BEGIN(SkipVerbatim);
1600 }
1601 }
static void determineBlockName(yyscan_t yyscanner)
Definition pre.l:3717
1602<SkipCond>{CMD}{CMD}"cond"[ \t]+ {}// escaped cond command
1603<SkipCond>{CMD}"cond"/\n |
1604<SkipCond>{CMD}"cond"[ \t]+ { // cond command in a skipped cond section, this section has to be skipped as well
1605 // but has to be recorded to match the endcond command
1606 startCondSection(yyscanner," ");
1607 }
static void startCondSection(yyscan_t yyscanner, const QCString &sectId)
Definition pre.l:3905
1608<SkipCComment>"{"[ \t]*"@code"/[ \t\n] {
1609 outputArray(yyscanner,"@iliteral{code}",15);
1610 yyextra->javaBlock=1;
1611 BEGIN(JavaDocVerbatimCode);
1612 }
1613<SkipCComment>"{"[ \t]*"@literal"/[ \t\n] {
1614 outputArray(yyscanner,"@iliteral",9);
1615 yyextra->javaBlock=1;
1616 BEGIN(JavaDocVerbatimCode);
1617 }
1618<SkipCComment,SkipCPPComment>{CMD}{CMD}"cond"[ \t\n]+ { // escaped cond command
1619 outputArray(yyscanner,yytext,yyleng);
1620 }
1621<SkipCPPComment>{CMD}"cond"[ \t]+ { // conditional section
1622 yyextra->ccomment=TRUE;
1623 yyextra->condCtx=YY_START;
1624 BEGIN(CondLineCpp);
1625 }
1626<SkipCComment>{CMD}"cond"[ \t]+ { // conditional section
1627 yyextra->ccomment=FALSE;
1628 yyextra->condCtx=YY_START;
1629 BEGIN(CondLineC);
1630 }
1631<CondLineC,CondLineCpp>[!()&| \ta-z_A-Z0-9\x80-\xFF.\-]+ {
1632 startCondSection(yyscanner,yytext);
1633 if (yyextra->skip)
1634 {
1635 if (YY_START==CondLineC)
1636 {
1637 // end C comment
1638 outputArray(yyscanner,"*/",2);
1639 yyextra->ccomment=TRUE;
1640 }
1641 else
1642 {
1643 yyextra->ccomment=FALSE;
1644 }
1645 BEGIN(SkipCond);
1646 }
1647 else
1648 {
1649 BEGIN(yyextra->condCtx);
1650 }
1651 }
1652<CondLineC,CondLineCpp>. { // non-guard character
1653 unput(*yytext);
1654 startCondSection(yyscanner," ");
1655 if (yyextra->skip)
1656 {
1657 if (YY_START==CondLineC)
1658 {
1659 // end C comment
1660 outputArray(yyscanner,"*/",2);
1661 yyextra->ccomment=TRUE;
1662 }
1663 else
1664 {
1665 yyextra->ccomment=FALSE;
1666 }
1667 BEGIN(SkipCond);
1668 }
1669 else
1670 {
1671 BEGIN(yyextra->condCtx);
1672 }
1673 }
1674<SkipCComment,SkipCPPComment>{CMD}"cond"{WSopt}/\n { // no guard
1675 if (YY_START==SkipCComment)
1676 {
1677 yyextra->ccomment=TRUE;
1678 // end C comment
1679 outputArray(yyscanner,"*/",2);
1680 }
1681 else
1682 {
1683 yyextra->ccomment=FALSE;
1684 }
1685 yyextra->condCtx=YY_START;
1686 yyextra->condGuardCount=0;
1687 startCondSection(yyscanner," ");
1688 BEGIN(SkipCond);
1689 }
1690<SkipCond>\n { yyextra->yyLineNr++; outputChar(yyscanner,'\n'); }
1691<SkipCond>{VERBATIM_LINE}.*/\n { }
1692<SkipCond>{LITERAL_BLOCK} {
1693 auto numNLs = QCString(yytext).contains('\n');
1694 yyextra->yyLineNr+=numNLs;
1695 for (int i = 0; i < numNLs; i++) outputChar(yyscanner,'\n');
1696 determineBlockName(yyscanner);
1697 BEGIN(SkipCondVerbatim);
1698 }
1699
1700<SkipCond>. { }
1701<SkipCond>"#if"("def")? { yyextra->condGuardCount++; }
1702<SkipCond>"#endif" { yyextra->condGuardCount--; }
1703<SkipCond>[^\/\!*\\@\n#]+ { }
1704<SkipCond>{CPPC}[/!] { yyextra->ccomment=FALSE; }
1705<SkipCond>{CCS}[*!] { yyextra->ccomment=TRUE; }
1706<SkipCond,SkipCComment,SkipCPPComment>{CMD}{CMD}"endcond"/[^a-z_A-Z0-9\x80-\xFF] {
1707 if (!yyextra->skip)
1708 {
1709 outputArray(yyscanner,yytext,yyleng);
1710 }
1711 }
1712<SkipCond>{CMD}"endcond"/[^a-z_A-Z0-9\x80-\xFF] {
1713 bool oldSkip = yyextra->skip;
1714 endCondSection(yyscanner);
1715 if (oldSkip && !yyextra->skip)
1716 {
1717 if (yyextra->ccomment)
1718 {
1719 outputArray(yyscanner,"/** ",4); // */
1720 }
1721 BEGIN(yyextra->condCtx);
1722 }
1723 }
static void endCondSection(yyscan_t yyscanner)
Definition pre.l:3919
1724<SkipCComment,SkipCPPComment>{CMD}"endcond"/[^a-z_A-Z0-9\x80-\xFF] {
1725 bool oldSkip = yyextra->skip;
1726 endCondSection(yyscanner);
1727 if (oldSkip && !yyextra->skip)
1728 {
1729 BEGIN(yyextra->condCtx);
1730 }
1731 }
1732<SkipCondVerbatim>{LITERAL_BLOCK_END} { /* end of verbatim block */
1733 if (yytext[1]=='f' && yyextra->blockName==&yytext[2])
1734 {
1735 BEGIN(SkipCond);
1736 }
1737 else if (&yytext[4]==yyextra->blockName)
1738 {
1739 BEGIN(SkipCond);
1740 }
1741 }
1742<SkipVerbatim>{LITERAL_BLOCK_END} { /* end of verbatim block */
1743 outputArray(yyscanner,yytext,yyleng);
1744 if (yytext[1]=='f' && yyextra->blockName==&yytext[2])
1745 {
1746 BEGIN(SkipCComment);
1747 }
1748 else if (&yytext[4]==yyextra->blockName)
1749 {
1750 BEGIN(SkipCComment);
1751 }
1752 }
1753<SkipCondVerbatim>^({B}*"*"+)?{B}{0,3}"~~~"[~]* {
1754 if (yyextra->fenceSize==getFenceSize(yytext,yyleng) && yyextra->fenceChar=='~')
1755 {
1756 BEGIN(SkipCond);
1757 }
1758 }
1759<SkipCondVerbatim>^({B}*"*"+)?{B}{0,3}"```"[`]* {
1760 if (yyextra->fenceSize==getFenceSize(yytext,yyleng) && yyextra->fenceChar=='`')
1761 {
1762 BEGIN(SkipCond);
1763 }
1764 }
1765<SkipVerbatim>^({B}*"*"+)?{B}{0,3}"~~~"[~]* {
1766 outputArray(yyscanner,yytext,yyleng);
1767 if (yyextra->fenceSize==getFenceSize(yytext,yyleng) && yyextra->fenceChar=='~')
1768 {
1769 BEGIN(SkipCComment);
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<SkipCondVerbatim>{CCE}|{CCS} { }
1780<SkipVerbatim>{CCE}|{CCS} {
1781 outputArray(yyscanner,yytext,yyleng);
1782 }
1783<JavaDocVerbatimCode>"{" {
1784 if (yyextra->javaBlock==0)
1785 {
1786 REJECT;
1787 }
1788 else
1789 {
1790 yyextra->javaBlock++;
1791 outputArray(yyscanner,yytext,(int)yyleng);
1792 }
1793 }
1794<JavaDocVerbatimCode>"}" {
1795 if (yyextra->javaBlock==0)
1796 {
1797 REJECT;
1798 }
1799 else
1800 {
1801 yyextra->javaBlock--;
1802 if (yyextra->javaBlock==0)
1803 {
1804 outputArray(yyscanner," @endiliteral ",14);
1805 BEGIN(SkipCComment);
1806 }
1807 else
1808 {
1809 outputArray(yyscanner,yytext,(int)yyleng);
1810 }
1811 }
1812 }
1813<JavaDocVerbatimCode>\n { /* new line in verbatim block */
1814 outputArray(yyscanner,yytext,(int)yyleng);
1815 }
1816<JavaDocVerbatimCode>. { /* any other character */
1817 outputArray(yyscanner,yytext,(int)yyleng);
1818 }
1819<SkipCondVerbatim>[^{*\\@\x06~`\n\/]+ { }
1820<SkipCComment,SkipVerbatim>[^{*\\@\x06~`\n\/]+ {
1821 outputArray(yyscanner,yytext,yyleng);
1822 }
1823<SkipCComment,SkipVerbatim,SkipCondVerbatim>\n {
1824 yyextra->yyLineNr++;
1825 outputChar(yyscanner,'\n');
1826 }
1827<SkipCondVerbatim>. { }
1828<SkipCComment,SkipVerbatim>. {
1829 outputChar(yyscanner,*yytext);
1830 }
1831<CopyCComment>[^*a-z_A-Z\x80-\xFF\n]*[^*a-z_A-Z\x80-\xFF\\\n] {
1832 yyextra->defLitText+=yytext;
1833 yyextra->defText+=escapeAt(yytext);
1834 }
static QCString escapeAt(const QCString &text)
Definition pre.l:3962
1835<CopyCComment>\\‍[\r]?\n {
1836 yyextra->defLitText+=yytext;
1837 yyextra->defText+=" ";
1838 yyextra->yyLineNr++;
1839 yyextra->yyMLines++;
1840 }
1841<CopyCComment>{CCE} {
1842 yyextra->defLitText+=yytext;
1843 yyextra->defText+=yytext;
1844 BEGIN(yyextra->lastCContext);
1845 }
1846<CopyCComment>\n {
1847 yyextra->yyLineNr++;
1848 yyextra->defLitText+=yytext;
1849 yyextra->defText+=' ';
1850 }
1851<RemoveCComment>{CCE}{B}*"#" { // see bug 594021 for a usecase for this rule
1852 if (yyextra->lastCContext==SkipCPPBlock)
1853 {
1854 BEGIN(SkipCommand);
1855 }
1856 else
1857 {
1858 REJECT;
1859 }
1860 }
1861<RemoveCComment>{CCE} { BEGIN(yyextra->lastCContext); }
1862<RemoveCComment>{CPPC}
1863<RemoveCComment>{CCS}
1864<RemoveCComment>[^*\x06\n]+
1865<RemoveCComment>\n { yyextra->yyLineNr++; outputChar(yyscanner,'\n'); }
1866<RemoveCComment>.
1867<SkipCPPComment>[^\n\/\\@]+ {
1868 outputArray(yyscanner,yytext,yyleng);
1869 }
1870<SkipCPPComment,RemoveCPPComment>\n {
1871 unput(*yytext);
1872 BEGIN(yyextra->lastCPPContext);
1873 }
1874<SkipCPPComment>{CCS} {
1875 outputChar(yyscanner,'/');outputChar(yyscanner,'*');
1876 }
1877<SkipCPPComment>{CPPC} {
1878 outputChar(yyscanner,'/');outputChar(yyscanner,'/');
1879 }
1880<SkipCPPComment>[^\x06\@\\\n]+ {
1881 outputArray(yyscanner,yytext,yyleng);
1882 }
1883<SkipCPPComment>. {
1884 outputChar(yyscanner,*yytext);
1885 }
1886<RemoveCPPComment>{CCS}
1887<RemoveCPPComment>{CPPC}
1888<RemoveCPPComment>[^\x06\n]+
1889<RemoveCPPComment>.
1890<DefineText>"__VA_OPT__("{B}*"##" {
1891 warn(yyextra->fileName,yyextra->yyLineNr,
1892 "'##' may not appear at the beginning of a __VA_OPT__()",
1893 yyextra->defName,yyextra->defLitText.stripWhiteSpace());
1894 yyextra->defText+="__VA_OPT__(";
1895 yyextra->defLitText+="__VA_OPT__(";
1896 }
1897<DefineText>"#"/"__VA_OPT__" {
1898 yyextra->defText+=yytext;
1899 yyextra->defLitText+=yytext;
1900 }
1901<DefineText>"#"/{IDSTART} {
1902 outputChar(yyscanner,' ');
1903 yyextra->quoteArg=TRUE;
1904 yyextra->idStart=true;
1905 yyextra->defLitText+=yytext;
1906 }
1907<DefineText,CopyCComment>{ID} {
1908 yyextra->defLitText+=yytext;
1909 if (YY_START == DefineText) outputSpaces(yyscanner,yytext);
1910 if (yyextra->quoteArg)
1911 {
1912 yyextra->defText+="\"";
1913 }
1914 if (yyextra->defArgs>0)
1915 {
1916 auto it = yyextra->argMap.find(yytext);
1917 if (it!=yyextra->argMap.end())
1918 {
1919 int n = it->second;
1920 yyextra->defText+='@';
1921 yyextra->defText+=QCString().setNum(n);
1922 }
1923 else
1924 {
1925 if (yyextra->idStart)
1926 {
1927 warn(yyextra->fileName,yyextra->yyLineNr,
1928 "'#' is not followed by a macro parameter '{}': '{}'",
1929 yyextra->defName,yyextra->defLitText.stripWhiteSpace());
1930 }
1931 yyextra->defText+=yytext;
1932 }
1933 }
1934 else
1935 {
1936 yyextra->defText+=yytext;
1937 }
1938 if (yyextra->quoteArg)
1939 {
1940 yyextra->defText+="\"";
1941 }
1942 yyextra->quoteArg=FALSE;
1943 yyextra->idStart=false;
1944 }
1945<CopyCComment>. {
1946 yyextra->defLitText+=yytext;
1947 yyextra->defText+=yytext;
1948 }
1949<DefineText>\\‍[\r]?\n {
1950 yyextra->defLitText+=yytext;
1951 outputChar(yyscanner,'\\');
1952 outputChar(yyscanner,'\n');
1953 yyextra->defText += ' ';
1954 yyextra->yyLineNr++;
1955 yyextra->yyMLines++;
1956 }
1957<DefineText>\n {
1958 QCString comment=extractTrailingComment(yyextra->defLitText);
1959 yyextra->defText = yyextra->defText.stripWhiteSpace();
1960 if (yyextra->defText.startsWith("##"))
1961 {
1962 warn(yyextra->fileName,yyextra->yyLineNr,
1963 "'##' cannot occur at the beginning of a macro definition '{}': '{}'",
1964 yyextra->defName,yyextra->defLitText.stripWhiteSpace());
1965 }
1966 else if (yyextra->defText.endsWith("##"))
1967 {
1968 warn(yyextra->fileName,yyextra->yyLineNr,
1969 "'##' cannot occur at the end of a macro definition '{}': '{}'",
1970 yyextra->defName,yyextra->defLitText.stripWhiteSpace());
1971 }
1972 else if (yyextra->defText.endsWith("#"))
1973 {
1974 warn(yyextra->fileName,yyextra->yyLineNr,
1975 "expected formal parameter after # in macro definition '{}': '{}'",
1976 yyextra->defName,yyextra->defLitText.stripWhiteSpace());
1977 }
1978 if (!comment.isEmpty())
1979 {
1980 outputString(yyscanner,comment);
1981 yyextra->defLitText=yyextra->defLitText.left(yyextra->defLitText.length()-comment.length()-1);
1982 }
1983 outputChar(yyscanner,'\n');
1984 yyextra->defLitText+=yytext;
1985 Define *def=nullptr;
1986 //printf("Define name='%s' text='%s' litTexti='%s'\n",qPrint(yyextra->defName),qPrint(yyextra->defText),qPrint(yyextra->defLitText));
1987 if (yyextra->includeStack.empty() || yyextra->curlyCount>0)
1988 {
1989 addMacroDefinition(yyscanner);
1990 }
1991 def=isDefined(yyscanner,yyextra->defName);
1992 if (def==0) // new define
1993 {
1994 //printf("new define '%s'!\n",qPrint(yyextra->defName));
1995 addDefine(yyscanner);
1996 }
1997 else if (def /*&& macroIsAccessible(def)*/)
1998 // name already exists
1999 {
2000 //printf("existing define!\n");
2001 //printf("define found\n");
2002 if (def->undef) // undefined name
2003 {
2004 def->undef = FALSE;
2005 def->name = yyextra->defName;
2006 def->definition = yyextra->defText.stripWhiteSpace();
2007 def->nargs = yyextra->defArgs;
2008 def->fileName = yyextra->fileName;
2009 def->lineNr = yyextra->yyLineNr-yyextra->yyMLines;
2010 def->columnNr = yyextra->yyColNr;
2011 }
2012 else
2013 {
2014 if (def->fileName != yyextra->fileName && !yyextra->expandOnlyPredef) addDefine(yyscanner);
2015 //printf("error: define %s is defined more than once!\n",qPrint(yyextra->defName));
2016 }
2017 }
2018 yyextra->argMap.clear();
2019 yyextra->yyLineNr++;
2020 yyextra->yyColNr=1;
2021 yyextra->lastGuardName.clear();
2022 BEGIN(Start);
2023 }
static void addMacroDefinition(yyscan_t yyscanner)
Definition pre.l:3625
static void addDefine(yyscan_t yyscanner)
Definition pre.l:3596
static QCString extractTrailingComment(const QCString &s)
Definition pre.l:2452
const char * comment
2024<DefineText>{B}* { outputString(yyscanner,yytext);
2025 yyextra->defText += ' ';
2026 yyextra->defLitText+=yytext;
2027 }
2028<DefineText>{B}*"##"{B}* { outputString(yyscanner,substitute(yytext,"##"," "));
2029 yyextra->defText += "##";
2030 yyextra->defLitText+=yytext;
2031 }
2032<DefineText>"@" { outputString(yyscanner,substitute(yytext,"@@"," "));
2033 yyextra->defText += "@@";
2034 yyextra->defLitText+=yytext;
2035 }
2036<DefineText>\" {
2037 outputChar(yyscanner,' ');
2038 yyextra->defText += *yytext;
2039 yyextra->defLitText+=yytext;
2040 if (!yyextra->insideComment)
2041 {
2042 BEGIN(SkipDoubleQuote);
2043 }
2044 }
2045<DefineText>{NUMBER} {
2046 outputSpaces(yyscanner,yytext);
2047 yyextra->defText += yytext;
2048 yyextra->defLitText+=yytext;
2049 }
2050<DefineText>\' {
2051 outputChar(yyscanner,' ');
2052 yyextra->defText += *yytext;
2053 yyextra->defLitText+=yytext;
2054 if (!yyextra->insideComment)
2055 {
2056 BEGIN(SkipSingleQuote);
2057 }
2058 }
2059<SkipDoubleQuote>{CPPC}[/]? { outputSpaces(yyscanner,yytext);
2060 yyextra->defText += yytext;
2061 yyextra->defLitText+=yytext;
2062 }
2063<SkipDoubleQuote>{CCS}[*]? { outputSpaces(yyscanner,yytext);
2064 yyextra->defText += yytext;
2065 yyextra->defLitText+=yytext;
2066 }
2067<SkipDoubleQuote>\" {
2068 outputChar(yyscanner,' ');
2069 yyextra->defText += *yytext;
2070 yyextra->defLitText+=yytext;
2071 BEGIN(DefineText);
2072 }
2073<SkipSingleQuote,SkipDoubleQuote>\\. {
2074 outputSpaces(yyscanner,yytext);
2075 yyextra->defText += yytext;
2076 yyextra->defLitText+=yytext;
2077 }
2078<SkipSingleQuote>\' {
2079 outputChar(yyscanner,' ');
2080 yyextra->defText += *yytext;
2081 yyextra->defLitText+=yytext;
2082 BEGIN(DefineText);
2083 }
2084<SkipDoubleQuote,SkipSingleQuote>. { outputSpace(yyscanner,yytext[0]);
2085 yyextra->defText += *yytext;
2086 yyextra->defLitText += *yytext;
2087 }
2088<DefineText>. { outputSpace(yyscanner,yytext[0]);
2089 yyextra->defText += *yytext;
2090 yyextra->defLitText += *yytext;
2091 }
2092<<EOF>> {
2093 TRACE("End of include file");
2094 //printf("Include stack depth=%d\n",yyextra->includeStack.size());
2095 if (yyextra->includeStack.empty())
2096 {
2097 TRACE("Terminating scanner");
2098 yyterminate();
2099 }
2100 else
2101 {
2102 if (!yyextra->levelGuard.empty())
2103 {
2104 if (yyextra->condGuardErrorLine!=0)
2105 {
2106 warn(yyextra->condGuardErrorFileName,yyextra->condGuardErrorLine,"{}",yyextra->condGuardErrorMessage);
2107 }
2108 else
2109 {
2110 warn(yyextra->fileName,yyextra->yyLineNr,"More #endif's than #if's found.");
2111 }
2112 }
2113 QCString toFileName = yyextra->fileName;
2114 const std::unique_ptr<FileState> &fs=yyextra->includeStack.back();
2115 //fileDefineCache->merge(yyextra->fileName,fs->fileName);
2116 YY_BUFFER_STATE oldBuf = YY_CURRENT_BUFFER;
2117 yy_switch_to_buffer( fs->bufState, yyscanner );
2118 yy_delete_buffer( oldBuf, yyscanner );
2119 yyextra->yyLineNr = fs->lineNr;
2120 //preYYin = fs->oldYYin;
2121 yyextra->inputBuf = fs->oldFileBuf;
2122 yyextra->inputBufPos = fs->oldFileBufPos;
2123 yyextra->curlyCount = fs->curlyCount;
2124 yyextra->levelGuard = fs->levelGuard;
2125 setFileName(yyscanner,fs->fileName);
2126 TRACE("switching to {}",yyextra->fileName);
#define yyterminate()
#define TRACE(...)
Definition trace.h:77
2127
2128 // Deal with file changes due to
2129 // #include's within { .. } blocks
2130 QCString lineStr(15+yyextra->fileName.length(), QCString::ExplicitSize);
2131 lineStr.sprintf("# %d \"%s\" 2",yyextra->yyLineNr,qPrint(yyextra->fileName));
2132 outputString(yyscanner,lineStr);
2133
2134 yyextra->includeStack.pop_back();
2135
2136 {
2137 std::lock_guard<std::mutex> lock(g_globalDefineMutex);
2138 // to avoid deadlocks we allow multiple threads to process the same header file.
2139 // The first one to finish will store the results globally. After that the
2140 // next time the same file is encountered, the stored data is used and the file
2141 // is not processed again.
2142 if (!g_defineManager.alreadyProcessed(toFileName.str()))
2143 {
2144 // now that the file is completely processed, prevent it from processing it again
2145 g_defineManager.addInclude(yyextra->fileName.str(),toFileName.str());
2146 g_defineManager.store(toFileName.str(),yyextra->localDefines);
2147 }
2148 else
2149 {
2151 {
2152 Debug::print(Debug::Preprocessor,0,"#include {}: was already processed by another thread! not storing data...\n",toFileName);
2153 }
2154 }
2155 }
2156 // move the local macros definitions for in this file to the translation unit context
2157 for (const auto &kv : yyextra->localDefines)
2158 {
2159 auto pair = yyextra->contextDefines.insert(kv);
2160 if (!pair.second) // define already in context -> replace with local version
2161 {
2162 yyextra->contextDefines.erase(pair.first);
2163 yyextra->contextDefines.insert(kv);
2164 }
2165 }
2166 yyextra->localDefines.clear();
2167 }
2168 }
2169<*>{CCS}/{CCE} |
2170<*>{CCS}[*!]? {
2171 if (YY_START==SkipVerbatim || YY_START == SkipCondVerbatim || YY_START==SkipCond || YY_START==IDLquote || YY_START == PragmaOnce)
2172 {
2173 REJECT;
2174 }
2175 else
2176 {
2177 outputArray(yyscanner,yytext,yyleng);
2178 yyextra->lastCContext=YY_START;
2179 yyextra->commentCount=1;
2180 if (yyleng==3)
2181 {
2182 yyextra->isSpecialComment = true;
2183 yyextra->lastGuardName.clear(); // reset guard in case the #define is documented!
2184 }
2185 else
2186 {
2187 yyextra->isSpecialComment = false;
2188 }
2189 BEGIN(SkipCComment);
2190 }
2191 }
2192<*>{CPPC}[/!]? {
2193 if (YY_START==SkipVerbatim || YY_START == SkipCondVerbatim || YY_START==SkipCond || getLanguageFromFileName(yyextra->fileName)==SrcLangExt::Fortran || YY_START==IDLquote || YY_START == PragmaOnce)
2194 {
2195 REJECT;
2196 }
2197 else if (YY_START==RulesRoundDouble)
2198 {
2199 REJECT;
2200 }
2201 else
2202 {
2203 outputArray(yyscanner,yytext,yyleng);
2204 yyextra->lastCPPContext=YY_START;
2205 if (yyleng==3)
2206 {
2207 yyextra->isSpecialComment = true;
2208 yyextra->lastGuardName.clear(); // reset guard in case the #define is documented!
2209 }
2210 else
2211 {
2212 yyextra->isSpecialComment = false;
2213 }
2214 BEGIN(SkipCPPComment);
2215 }
2216 }
2217<*>\n {
2218 outputChar(yyscanner,'\n');
2219 yyextra->yyLineNr++;
2220 }
2221<*>. {
2222 yyextra->expectGuard = FALSE;
2223 outputChar(yyscanner,*yytext);
2224 }
2225
2226%%

◆ yyread()

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

Definition at line 2230 of file pre.l.

2231{
2232 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
2233 int bytesInBuf = static_cast<int>(state->inputBuf->size())-state->inputBufPos;
2234 int bytesToCopy = std::min(max_size,bytesInBuf);
2235 memcpy(buf,state->inputBuf->data()+state->inputBufPos,bytesToCopy);
2236 state->inputBufPos+=bytesToCopy;
2237 return bytesToCopy;
2238}

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().