Doxygen
Loading...
Searching...
No Matches
pre.l File Reference
#include <stdint.h>
#include "pre.h"
#include <algorithm>
#include <deque>
#include <map>
#include <memory>
#include <mutex>
#include <stack>
#include <utility>
#include "arguments.h"
#include "condparser.h"
#include "config.h"
#include "constexp.h"
#include "containers.h"
#include "debug.h"
#include "defargs.h"
#include "define.h"
#include "doxygen.h"
#include "dstring.h"
#include "entry.h"
#include "filedef.h"
#include "fileinfo.h"
#include "filename.h"
#include "fortranscanner.h"
#include "message.h"
#include "portable.h"
#include "regex.h"
#include "stringutil.h"
#include "trace.h"
#include "util.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 DString escapeAt (const DString &text)
static DString extractTrailingComment (const DString &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 DString &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 DString expandMacro (yyscan_t yyscanner, const DString &name)
static DString expandStandardMacro (yyscan_t yyscanner, const DString &name)
static void readIncludeFile (yyscan_t yyscanner, const DString &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 DString &expr)
static void startCondSection (yyscan_t yyscanner, const DString &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 DString &name)
static int yyread (yyscan_t yyscanner, char *buf, int max_size)
static DefineisDefined (yyscan_t yyscanner, const DString &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 DString &fileName, bool &alreadyProcessed)
static std::unique_ptr< FileStatefindFile (yyscan_t yyscanner, const DString &fileName, bool localInclude, bool &alreadyProcessed)
static int getNextChar (yyscan_t yyscanner, const DString &expr, DString *rest, uint32_t &pos)
static int getCurrentChar (yyscan_t yyscanner, const DString &expr, DString *rest, uint32_t pos)
static void unputChar (yyscan_t yyscanner, const DString &expr, DString *rest, uint32_t &pos, char c)
static bool expandExpression (yyscan_t yyscanner, DString &expr, DString *rest, int pos, int level)
static DString stringize (const DString &s)
static void processConcatOperators (DString &expr)
static void returnCharToStream (yyscan_t yyscanner, char c)
static void addTillEndOfString (yyscan_t yyscanner, const DString &expr, DString *rest, uint32_t &pos, char term, DString &arg)
static void addTillEndOfComment (yyscan_t yyscanner, const DString &expr, DString *rest, uint32_t &pos, char term, DString &arg)
static void skipCommentMacroName (yyscan_t yyscanner, const DString &expr, DString *rest, int &cc, uint32_t &j, int &len)
static DString expandVAOpt (const DString &vaStr, bool hasOptionalArgs)
static bool replaceFunctionMacro (yyscan_t yyscanner, const DString &expr, DString *rest, int pos, int &len, const Define *def, DString &result, int level)
static int getNextId (const DString &expr, int p, int *l)
static void addSeparatorsIfNeeded (yyscan_t yyscanner, const DString &expr, DString &resultExpr, DString &restExpr, int pos)
static const char * processUntilMatchingTerminator (const char *inputStr, DString &result)
 Process string or character literal.
static DString removeIdsAndMarkers (const DString &s)
static DString removeMarkers (const DString &s)
static void forceEndCondSection (yyscan_t yyscanner)
static void initPredefined (yyscan_t yyscanner, const DString &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 3109 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:3981

Definition at line 356 of file pre.l.

◆ YY_NO_UNISTD_H

#define YY_NO_UNISTD_H   1

Definition at line 68 of file pre.l.

◆ YY_TYPEDEF_YY_SCANNER_T

#define YY_TYPEDEF_YY_SCANNER_T

Definition at line 22 of file pre.l.

Typedef Documentation

◆ DefineMap

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

A dictionary of managed Define objects.

Definition at line 110 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 3657 of file pre.l.

3658{
3659 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
3660 Define def;
3661 def.name = state->defName;
3662 def.definition = state->defText.stripWhiteSpace();
3663 def.nargs = state->defArgs;
3664 def.fileName = state->fileName;
3665 def.fileDef = state->yyFileDef;
3666 def.lineNr = state->yyLineNr-state->yyMLines;
3667 def.columnNr = state->yyColNr;
3668 def.varArgs = state->defVarArgs;
3669 //printf("newDefine: %s %s file: %s\n",qPrint(def.name),qPrint(def.definition),
3670 // def.fileDef ? qPrint(def.fileDef->name()) : qPrint(def.fileName));
3671 //printf("newDefine: '%s'->'%s'\n",qPrint(def.name),qPrint(def.definition));
3672 if (!def.name.empty() &&
3674 {
3675 def.isPredefined=true;
3676 def.expandAsDefined=true;
3677 }
3678 auto it = state->localDefines.find(def.name.str());
3679 if (it!=state->localDefines.end()) // redefine
3680 {
3681 state->localDefines.erase(it);
3682 }
3683 state->localDefines.emplace(def.name.str(),def);
bool empty() const
Returns true iff the string is empty (std::string compatible alias for isEmpty()).
Definition dstring.h:148
DString stripWhiteSpace() const
returns a copy of this string with leading and trailing whitespace removed
Definition dstring.h:337
const std::string & str() const
Definition dstring.h:645
A class representing a macro definition.
Definition define.h:31
int lineNr
Definition define.h:38
bool varArgs
Definition define.h:42
DString name
Definition define.h:33
FileDef * fileDef
Definition define.h:37
bool isPredefined
Definition define.h:43
DString fileName
Definition define.h:35
size_t columnNr
Definition define.h:39
int nargs
Definition define.h:40
bool expandAsDefined
Definition define.h:45
DString definition
Definition define.h:34
static StringUnorderedSet expandAsDefinedSet
Definition doxygen.h:112
3684}

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

◆ addMacroDefinition()

void addMacroDefinition ( yyscan_t yyscanner)
static

Definition at line 3686 of file pre.l.

3687{
3688 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
3689 if (state->skip) return; // do not add this define as it is inside a
3690 // conditional section (cond command) that is disabled.
3691
3692 Define define;
3693 define.fileName = state->fileName;
3694 define.lineNr = state->yyLineNr - state->yyMLines;
3695 define.columnNr = state->yyColNr;
3696 define.name = state->defName;
3697 define.args = state->defArgsStr;
3698 define.fileDef = state->inputFileDef;
DString args
Definition define.h:36
3699
3700 DString litText = state->defLitText;
3701 size_t l=litText.find('\n');
3702 if (l!=DString::npos && l>0 && litText.left(l).stripWhiteSpace()=="\\")
3703 {
3704 // strip first line if it only contains a slash
3705 litText = litText.mid(l+1);
3706 }
3707 else if (l!=DString::npos && l>0)
3708 {
3709 // align the items on the first line with the items on the second line
3710 size_t k=l+1;
3711 const char *p=litText.data()+k;
3712 char c = 0;
3713 while ((c=*p++) && (c==' ' || c=='\t')) k++;
3714 litText=litText.mid(l+1,k-l-1)+litText.stripWhiteSpace();
3715 }
3716 DString litTextStripped = state->defLitText.stripWhiteSpace();
3717 if (litTextStripped.contains('\n')>=1)
3718 {
3719 define.definition = litText;
3720 }
3721 else
3722 {
3723 define.definition = litTextStripped;
3724 }
3725 {
3726 state->macroDefinitions.push_back(define);
3727 }
A String class for use with Doxygen wrapping std::string and adding some additional functionality off...
Definition dstring.h:84
DString mid(size_t index, size_t len=npos) const
Definition dstring.h:318
static constexpr size_t npos
value used to indicate 'not found' or 'to the end of the string', matching std::string::npos
Definition dstring.h:178
int contains(char c, bool cs=true) const
Definition dstring.cpp:85
size_t find(char c, size_t pos=0) const
Definition dstring.h:239
DString left(size_t len) const
Definition dstring.h:306
const char * data() const
Returns a pointer to the contents of the string in the form of a 0-terminated C string.
Definition dstring.h:157
3728}

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

◆ addSeparatorsIfNeeded()

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

Definition at line 3111 of file pre.l.

3112{
3113 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
3114 if (!state->nospaces)
3115 {
3116 // peek back in the stream, for a colon character
3117 char ccPrev = pos==0 || (int)expr.length()<pos ? state->prevChar : expr.at(pos-1);
3118 DString leftSpace = ccPrev!=':' && ccPrev!=' ' ? " " : "";
3119 int ccNext = 0;
3120 restExpr=restExpr.stripWhiteSpace();
3121 if (restExpr.empty()) // peek ahead in the stream for non-whitespace
3122 {
3123 uint32_t j=(uint32_t)resultExpr.length();
3124 while ((ccNext=getNextChar(yyscanner,resultExpr,nullptr,j))!=EOF && ccNext==' ') { }
3125 if (ccNext != EOF) unputChar(yyscanner,resultExpr,nullptr,j,(char)ccNext);
3126 }
3127 else // take first char from remainder
3128 {
3129 ccNext=restExpr.at(0);
3130 }
3131 // don't add whitespace before a colon
3132 DString rightSpace = ccNext!=':' && ccNext!=' ' ? " " : "";
3133 //printf("ccPrev='%c' ccNext='%c' p=%d expr=%zu restExpr='%s' left='%s' right='%s'\n",
3134 // ccPrev,ccNext,pos,expr.length(),qPrint(restExpr),qPrint(leftSpace),qPrint(rightSpace));
3135 resultExpr=leftSpace+resultExpr+rightSpace;
3136 }
char & at(size_t i)
Returns a reference to the character at index i.
Definition dstring.h:686
size_t length() const
Returns the length of the string, not counting the 0-terminator.
Definition dstring.h:151
static void unputChar(yyscan_t yyscanner, const DString &expr, DString *rest, uint32_t &pos, char c)
Definition pre.l:4104
static int getNextChar(yyscan_t yyscanner, const DString &expr, DString *rest, uint32_t &pos)
Definition pre.l:4058
3137}

References DString::at(), DString::empty(), getNextChar(), DString::length(), DString::stripWhiteSpace(), and unputChar().

Referenced by expandExpression().

◆ addTillEndOfComment()

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

Definition at line 2686 of file pre.l.

2688{
2689 int cc;
2690 while ((cc=getNextChar(yyscanner,expr,rest,pos))!=EOF && cc!=0)
2691 {
2692 if (cc=='*' && getCurrentChar(yyscanner,expr,rest,pos)=='/')
2693 {
2694 arg+=(char)cc;
2695 cc = getNextChar(yyscanner,expr,rest,pos);
2696 return;
2697 }
2698 arg+=(char)cc;
2699 }
static int getCurrentChar(yyscan_t yyscanner, const DString &expr, DString *rest, uint32_t pos)
Definition pre.l:4081
2700}

References getCurrentChar(), getNextChar(), and term.

Referenced by replaceFunctionMacro().

◆ addTillEndOfString()

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

Definition at line 2667 of file pre.l.

2669{
2670 int cc;
2671 while ((cc=getNextChar(yyscanner,expr,rest,pos))!=EOF && cc!=0)
2672 {
2673 if (cc=='\\')
2674 {
2675 arg+=(char)cc;
2676 cc=getNextChar(yyscanner,expr,rest,pos);
2677 }
2678 else if (cc==term)
2679 {
2680 return;
2681 }
2682 arg+=(char)cc;
2683 }
#define term(fmt,...)
Definition message.h:137
2684}

References getNextChar(), and term.

Referenced by replaceFunctionMacro().

◆ checkAndOpenFile()

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

Definition at line 2355 of file pre.l.

2356{
2357 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
2358 alreadyProcessed = false;
2359 std::unique_ptr<FileState> fs;
2360 //printf("checkAndOpenFile(%s)\n",qPrint(fileName));
2361 FileInfo fi(fileName.str());
2362 if (fi.exists() && fi.isFile())
2363 {
2364 StringVector exclPatterns = Config_getList(EXCLUDE_PATTERNS);
2365 if (fi.match(exclPatterns,useCaseSenseNames())) return nullptr;
Minimal replacement for QFileInfo.
Definition fileinfo.h:26
#define Config_getList(name)
Definition config.h:38
std::vector< std::string > StringVector
Definition containers.h:33
bool useCaseSenseNames()
Returns true if the names of the symbols can be case sensitive.
Definition util.cpp:2679
2366
2367 DString absName = fi.absFilePath();
2368
2369 // global guard
2370 if (state->curlyCount==0) // not #include inside { ... }
2371 {
2372 std::lock_guard<std::mutex> lock(g_globalDefineMutex);
2373 if (g_defineManager.alreadyProcessed(absName.str()))
2374 {
2375 alreadyProcessed = true;
2376 //printf(" already included 1\n");
2377 return 0; // already done
2378 }
2379 }
2380 // check include stack for absName
bool alreadyProcessed(const std::string &fileName) const
Definition pre.l:208
static std::mutex g_globalDefineMutex
Definition pre.l:235
static DefineManager g_defineManager
Definition pre.l:237
2381
2382 alreadyProcessed = std::any_of(
2383 state->includeStack.begin(),
2384 state->includeStack.end(),
2385 [absName](const std::unique_ptr<FileState> &lfs)
2386 { return lfs->fileName==absName; }
2387 );
2388
2389 if (alreadyProcessed)
2390 {
2391 //printf(" already included 2\n");
2392 return nullptr;
2393 }
2394 //printf("#include %s\n",qPrint(absName));
2395
2396 fs = std::make_unique<FileState>();
2397 if (!readInputFile(absName,fs->fileBuf))
2398 { // error
2399 //printf(" error reading\n");
2400 fs.reset();
2401 }
2402 else
2403 {
2404 addTerminalCharIfMissing(fs->fileBuf,'\n');
2405 fs->oldFileBuf = state->inputBuf;
2406 fs->oldFileBufPos = state->inputBufPos;
2407 }
2408 }
2409 return fs;
void addTerminalCharIfMissing(std::string &s, char c)
Definition stringutil.h:87
bool readInputFile(const DString &fileName, std::string &contents, bool filter, bool isSourceCode)
read a file name fileName and optionally filter and transcode it
Definition util.cpp:4374
2410}

References FileInfo::absFilePath(), addTerminalCharIfMissing(), DefineManager::alreadyProcessed(), Config_getList, FileInfo::exists(), g_defineManager, g_globalDefineMutex, FileInfo::isFile(), FileInfo::match(), readInputFile(), DString::str(), and useCaseSenseNames().

Referenced by findFile().

◆ computeExpression()

bool computeExpression ( yyscan_t yyscanner,
const DString & 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 3595 of file pre.l.

3596{
3597 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
3598 DString e=expr;
3599 DString ee=expr;
3600 ee = removeMarkers(ee);
3601 state->expanded.clear();
3602 expandExpression(yyscanner,e,nullptr,0,0);
3603 //printf("after expansion '%s'\n",qPrint(e));
3604 e = removeIdsAndMarkers(e);
3605 if (e.empty()) return false;
3606 //printf("parsing '%s'\n",qPrint(e));
3607 return state->constExpParser.parse(state->fileName.data(),state->yyLineNr,e.str(),ee.str());
static DString removeMarkers(const DString &s)
Definition pre.l:3524
static DString removeIdsAndMarkers(const DString &s)
Definition pre.l:3329
static bool expandExpression(yyscan_t yyscanner, DString &expr, DString *rest, int pos, int level)
Definition pre.l:3143
3608}

References DString::empty(), expandExpression(), removeIdsAndMarkers(), removeMarkers(), and DString::str().

◆ decrLevel()

void decrLevel ( yyscan_t yyscanner)
static

Definition at line 2313 of file pre.l.

2314{
2315 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
2316 //printf("%s line %d: decrLevel %zu\n",qPrint(state->fileName),state->yyLineNr,state->levelGuard.size());
2317 if (!state->levelGuard.empty())
2318 {
2319 state->levelGuard.pop();
2320 }
2321 else
2322 {
2323 if (state->condGuardErrorLine!=0)
2324 {
2325 warn(state->condGuardErrorFileName,state->condGuardErrorLine,"{}",state->condGuardErrorMessage);
2326 }
2327 else
2328 {
2329 warn(state->fileName,state->yyLineNr,"More #endif's than #if's found.");
2330 }
2331 }
#define warn(file, line, fmt,...)
Definition message.h:97
2332}

References warn.

◆ determineBlockName()

void determineBlockName ( yyscan_t yyscanner)
static

Definition at line 3778 of file pre.l.

3779{
3780 struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
3781 yyextra->fenceSize=0;
3782 char c=0;
3783 if (yytext[1]=='f' && ((c=yytext[2])=='[' || c=='{' || c=='(' || c=='$'))
3784 {
3785 switch (c)
3786 {
3787 case '[': yyextra->blockName="]"; break;
3788 case '{': yyextra->blockName="}"; break;
3789 case '(': yyextra->blockName=")"; break;
3790 case '$': yyextra->blockName="$"; break;
3791 default: break;
3792 }
3793 yyextra->blockName=yyextra->blockName.stripWhiteSpace();
3794 }
3795 else
3796 {
3797 DString bn=DString(&yytext[1]).stripWhiteSpace();
3798 if (bn=="startuml")
3799 {
3800 yyextra->blockName="uml";
3801 }
3802 else
3803 {
3804 if (size_t i = bn.find('{'); // for \code{.c}
3805 i!=DString::npos) bn=bn.left(i).stripWhiteSpace();
3806 yyextra->blockName=bn;
3807 }
3808 }
3809}

References DString::find(), DString::left(), DString::npos, and DString::stripWhiteSpace().

◆ endCondSection()

void endCondSection ( yyscan_t yyscanner)
static

Definition at line 3980 of file pre.l.

3981{
3982 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
3983 if (state->condGuardCount>0 && state->condGuardErrorLine==0)
3984 {
3985 state->condGuardErrorLine = state->yyLineNr;
3986 state->condGuardErrorFileName = state->fileName;
3987 state->condGuardErrorMessage = "more #if's than #endif's in \\cond..\\endcond section";
3988 }
3989 else if (state->condGuardCount<0 && state->condGuardErrorLine==0)
3990 {
3991 state->condGuardErrorLine = state->yyLineNr;
3992 state->condGuardErrorFileName = state->fileName;
3993 state->condGuardErrorMessage = "more #endif's than #if's in \\cond..\\endcond section";
3994 }
3995 else // balanced again -> no error
3996 {
3997 state->condGuardErrorLine = 0;
3998 }
3999 if (state->condStack.empty())
4000 {
4001 warn(state->fileName,state->yyLineNr,"the \\endcond does not have a corresponding \\cond in this file");
4002 state->skip=false;
4003 }
4004 else
4005 {
4006 const std::unique_ptr<preYY_CondCtx> &ctx = state->condStack.top();
4007 state->skip=ctx->skip;
4008 state->condStack.pop();
4009 }
4010 //printf("endCondSection: skip=%d stack=%d\n",state->skip,state->condStack.count());
4011}

References warn.

◆ escapeAt()

DString escapeAt ( const DString & text)
static

Definition at line 4023 of file pre.l.

4024{
4025 DString result;
4026 if (!text.empty())
4027 {
4028 char c = 0;
4029 const char *p=text.data();
4030 while ((c=*p++))
4031 {
4032 if (c=='@') result+="@@"; else result+=c;
4033 }
4034 }
4035 return result;
4036}

References DString::data(), and DString::empty().

◆ expandExpression()

bool expandExpression ( yyscan_t yyscanner,
DString & expr,
DString * 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 3143 of file pre.l.

3144{
3145 struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
3146 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
3147 //printf(">expandExpression(expr='%s',rest='%s',pos=%d,level=%d)\n",qPrint(expr),rest ? qPrint(*rest) : "", pos, level);
3148 if (expr.empty())
3149 {
3150 //printf("<expandExpression: empty\n");
3151 return true;
3152 }
3153 if (state->expanded.find(expr.str())!=state->expanded.end() &&
3154 level>MAX_EXPANSION_DEPTH) // check for too deep recursive expansions
3155 {
3156 //printf("<expandExpression: already expanded expr='%s'\n",qPrint(expr));
3157 return false;
3158 }
3159 else
3160 {
3161 state->expanded.insert(expr.str());
3162 }
3163 DString macroName;
3164 DString expMacro;
3165 bool definedTest=false;
3166 int i=pos, l=0, p=0, len=0;
3167 int startPos = pos;
3168 int samePosCount=0;
3169 while ((p=getNextId(expr,i,&l))!=-1) // search for an macro name
3170 {
3171 bool replaced=false;
3172 DString resultExpr;
3173 macroName=expr.mid(p,l);
3174 //printf(" p=%d macroName=%s\n",p,qPrint(macroName));
3175 if (!(resultExpr = expandStandardMacro(yyscanner,macroName)).empty())
3176 {
3177 DString restExpr=expr.mid(p+8);
3178 expr=expr.left(p)+resultExpr+restExpr;
3179 }
3180 else if (p<2 || !(expr.at(p-2)=='@' && expr.at(p-1)=='-')) // no-rescan marker?
3181 {
3182 if (state->expandedDict.find(macroName.str())==state->expandedDict.end()) // expand macro
3183 {
3184 bool expanded=false;
3185 Define *def=isDefined(yyscanner,macroName);
3186 // In case EXPAND_ONLY_PREDEF is enabled prevent expansion unless the macro was explicitly
3187 // predefined
3188 if (yyextra->expandOnlyPredef && def && !def->isPredefined) def=nullptr;
3189 if (macroName=="defined")
3190 {
3191 //printf("found defined inside macro definition '%s'\n",qPrint(expr.mid(p)));
3192 definedTest=true;
3193 }
3194 else if (definedTest) // macro name was found after defined
3195 {
3196 if (def) expMacro = " 1 "; else expMacro = " 0 ";
3197 replaced=true;
3198 len=l;
3199 definedTest=false;
3200 }
3201 else if (def && def->nargs==-1) // simple macro
3202 {
3203 // substitute the definition of the macro
3204 expMacro=def->definition.stripWhiteSpace();
3205 //expMacro=def->definition.stripWhiteSpace();
3206 replaced=true;
3207 len=l;
3208 //printf("simple macro expansion='%s'->'%s'\n",qPrint(macroName),qPrint(expMacro));
3209 }
3210 else if (def && def->nargs>=0) // function macro
3211 {
3212 //printf(" >>>> call replaceFunctionMacro expr='%s'\n",qPrint(expr));
3213 replaced=replaceFunctionMacro(yyscanner,expr,rest,p+l,len,def,expMacro,level);
3214 //printf(" <<<< call replaceFunctionMacro: replaced=%d\n",replaced);
3215 len+=l;
3216 }
#define MAX_EXPANSION_DEPTH
Definition pre.l:3109
static DString expandStandardMacro(yyscan_t yyscanner, const DString &name)
Definition pre.l:3628
static int getNextId(const DString &expr, int p, int *l)
Definition pre.l:3055
static bool replaceFunctionMacro(yyscan_t yyscanner, const DString &expr, DString *rest, int pos, int &len, const Define *def, DString &result, int level)
Definition pre.l:2786
static Define * isDefined(yyscan_t yyscanner, const DString &name)
Returns a reference to a Define object given its name or 0 if the Define does not exist.
Definition pre.l:4128
3217
3218 if (replaced) // expand the macro and rescan the expression
3219 {
3220 //printf(" replacing '%s'->'%s'\n",qPrint(expr.mid(p,len)),qPrint(expMacro));
3221 resultExpr=expMacro;
3222 DString restExpr=expr.mid(p+len);
3223 addSeparatorsIfNeeded(yyscanner,expr,resultExpr,restExpr,p);
3224 processConcatOperators(resultExpr);
3225 //printf(" macroName=%s restExpr='%s' def->nonRecursive=%d\n",qPrint(macroName),qPrint(restExpr),def ? def->nonRecursive : false);
3226 if (def && !def->nonRecursive)
3227 {
3228 state->expandedDict.emplace(toStdString(macroName),def);
3229 expanded = expandExpression(yyscanner,resultExpr,&restExpr,0,level+1);
3230 state->expandedDict.erase(toStdString(macroName));
3231 }
3232 else if (def && def->nonRecursive)
3233 {
3234 expanded = true;
3235 }
3236 if (expanded)
3237 {
3238 //printf("expanded '%s' + '%s' + '%s'\n",qPrint(expr.left(p)),qPrint(resultExpr),qPrint(restExpr));
3239 expr=expr.left(p)+resultExpr+restExpr;
3240 i=p;
3241 }
3242 else
3243 {
3244 //printf("not expanded '%s' + @- '%s'\n",qPrint(expr.left(p)),qPrint(expr.mid(p)));
3245 expr=expr.left(p)+"@-"+expr.mid(p);
3246 i=p+l+2;
3247 }
3248 }
3249 else // move to the next macro name
3250 {
3251 //printf(" moving to the next macro old i=%d new i=%d\n",i,p+l);
3252 i=p+l;
3253 }
3254 }
3255 else // move to the next macro name
3256 {
3257 expr=expr.left(p)+"@-"+expr.mid(p);
3258 //printf("macro already expanded, moving to the next macro expr=%s\n",qPrint(expr));
3259 i=p+l+2;
3260 //i=p+l;
3261 }
3262 // check for too many inplace expansions without making progress
3263 if (i==startPos)
3264 {
3265 samePosCount++;
3266 }
3267 else
3268 {
3269 startPos=i;
3270 samePosCount=0;
3271 }
3272 if (samePosCount>MAX_EXPANSION_DEPTH)
3273 {
3274 break;
3275 }
3276 }
3277 else // no re-scan marker found, skip the macro name
3278 {
3279 //printf("skipping marked macro\n");
3280 i=p+l;
3281 }
3282 }
3283 //printf("<expandExpression(expr='%s',rest='%s',pos=%d,level=%d)\n",qPrint(expr),rest ? qPrint(*rest) : "", pos,level);
3284 return true;
bool nonRecursive
Definition define.h:44
std::string toStdString(const DString &s)
Definition dstring.h:798
static void addSeparatorsIfNeeded(yyscan_t yyscanner, const DString &expr, DString &resultExpr, DString &restExpr, int pos)
Definition pre.l:3111
static void processConcatOperators(DString &expr)
Definition pre.l:2614
3285}

References addSeparatorsIfNeeded(), DString::at(), Define::definition, DString::empty(), expandExpression(), expandStandardMacro(), getNextId(), isDefined(), Define::isPredefined, DString::left(), MAX_EXPANSION_DEPTH, DString::mid(), Define::nargs, Define::nonRecursive, processConcatOperators(), replaceFunctionMacro(), DString::str(), DString::stripWhiteSpace(), and toStdString().

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

◆ expandMacro()

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

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

Definition at line 3614 of file pre.l.

3615{
3616 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3617 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
3618 state->prevChar = yyscanner->yytext_r > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ? *(yyscanner->yytext_r-1) : 0;
3619 DString n=name;
3620 state->expanded.clear();
3621 expandExpression(yyscanner,n,nullptr,0,0);
3622 n=removeMarkers(n);
3623 state->prevChar=0;
3624 //printf("expandMacro '%s'->'%s'\n",qPrint(name),qPrint(n));
3625 return n;
void clear()
Definition dstring.h:214
3626}

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

◆ expandStandardMacro()

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

Definition at line 3628 of file pre.l.

3629{
3630 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3631 DString resultExpr;
3632 if (name == "__LINE__")
3633 {
3634 return DString().setNum(yyextra->yyLineNr);
3635 }
3636 else if (name == "__FILE__")
3637 {
3638 resultExpr = "\"";
3639 resultExpr += yyextra->fileName;
3640 resultExpr += "\"";
3641 }
3642 else if (name == "__DATE__")
3643 {
3644 resultExpr = "\"";
3645 resultExpr += __DATE__;
3646 resultExpr += "\"";
3647 }
3648 else if (name == "__TIME__")
3649 {
3650 resultExpr = "\"";
3651 resultExpr += __TIME__;
3652 resultExpr += "\"";
3653 }
3654 return resultExpr;
DString & setNum(short n)
Definition dstring.h:552
3655}

References DString::setNum().

Referenced by expandExpression().

◆ expandVAOpt()

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

Definition at line 2734 of file pre.l.

2735{
2736 //printf("expandVAOpt(vaStr=%s,hasOptionalArgs=%d)\n",qPrint(vaStr),hasOptionalArgs);
2737 DString result;
2738 size_t vo=0, vp=0;
2739 result.clear();
2740 size_t vl = vaStr.length();
2741 while ((vo = vaStr.find("__VA_OPT__(",vp))!=DString::npos)
2742 {
2743 bool hasHash = vo>0 && vaStr.at(vo-1)=='#';
2744 if (hasHash)
2745 {
2746 result+=vaStr.mid(vp,vo-vp-1); // don't copy #
2747 result+="\"";
2748 }
2749 else
2750 {
2751 result+=vaStr.mid(vp,vo-vp);
2752 }
2753 size_t ve=vo+11; // skip over '__VA_OPT__(' part
2754 int bc=1;
2755 while (bc>0 && ve<vl)
2756 {
2757 if (vaStr[ve]==')') bc--;
2758 else if (vaStr[ve]=='(') bc++;
2759 ve++;
2760 }
2761 // ve points to end of __VA_OPT__(....)
2762 if (bc==0 && hasOptionalArgs)
2763 {
2764 DString voStr = vaStr.mid(vo+11,ve-vo-12);
2765 //printf("vo=%d ve=%d voStr=%s\n",vo,ve,qPrint(voStr));
2766 result+=voStr; // take 'x' from __VA_OPT__(x)
2767 }
2768 if (hasHash)
2769 {
2770 result+="\"";
2771 }
2772 vp=ve;
2773 }
2774 result+=vaStr.mid(vp);
2775 //printf("vaStr='%s'\n -> '%s'\n",qPrint(vaStr),qPrint(result));
2776 return result;
2777}

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

Referenced by replaceFunctionMacro().

◆ extractTrailingComment()

DString extractTrailingComment ( const DString & s)
static

Definition at line 2486 of file pre.l.

2487{
2488 if (s.empty()) return "";
2489 int i=(int)s.length()-1;
2490 while (i>=0)
2491 {
2492 char c=s[i];
2493 switch (c)
2494 {
2495 case '/':
2496 {
2497 i--;
2498 if (i>=0 && s[i]=='*') // end of a comment block
2499 {
2500 i--;
2501 while (i>0 && !(s[i-1]=='/' && s[i]=='*')) i--;
2502 if (i==0)
2503 {
2504 i++;
2505 }
2506 // only /*!< ... */ or /**< ... */ are treated as a comment for the macro name,
2507 // otherwise the comment is treated as part of the macro definition
2508 return ((s[i+1]=='*' || s[i+1]=='!') && s[i+2]=='<') ? &s[i-1] : "";
2509 }
2510 else
2511 {
2512 return "";
2513 }
2514 }
2515 break;
2516 // whitespace or line-continuation
2517 case ' ':
2518 case '\t':
2519 case '\r':
2520 case '\n':
2521 case '\\':
2522 break;
2523 default:
2524 return "";
2525 }
2526 i--;
2527 }
2528 return "";
2529}

References DString::empty(), and DString::length().

◆ extraSpacing()

void extraSpacing ( yyscan_t yyscanner)
inlinestatic

Definition at line 3765 of file pre.l.

3766{
3767 struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
3768 if (!yyextra->defContinue) return;
3769 for (int i=0; i< (int)yyleng; i++)
3770 {
3771 if (yytext[i] == '\t')
3772 yyextra->defExtraSpacing+='\t';
3773 else
3774 yyextra->defExtraSpacing+=' ';
3775 }
3776}

◆ findFile()

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

Definition at line 2412 of file pre.l.

2413{
2414 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
2415 //printf("** findFile(%s,%d) state->fileName=%s\n",qPrint(fileName),localInclude,qPrint(state->fileName));
2416 if (Portable::isAbsolutePath(fileName))
2417 {
2418 auto fs = checkAndOpenFile(yyscanner,fileName,alreadyProcessed);
2419 if (fs)
2420 {
2421 setFileName(yyscanner,fileName);
2422 state->yyLineNr=1;
2423 return fs;
2424 }
2425 else if (alreadyProcessed)
2426 {
2427 return nullptr;
2428 }
2429 }
2430 if (localInclude && !state->fileName.empty())
2431 {
2432 FileInfo fi(state->fileName.str());
2433 if (fi.exists())
2434 {
2435 DString absName = DString(fi.dirPath(true))+"/"+fileName;
2436 auto fs = checkAndOpenFile(yyscanner,absName,alreadyProcessed);
2437 if (fs)
2438 {
2439 setFileName(yyscanner,absName);
2440 state->yyLineNr=1;
2441 return fs;
2442 }
2443 else if (alreadyProcessed)
2444 {
2445 return nullptr;
2446 }
2447 }
2448 }
2449 if (state->pathList.empty())
2450 {
2451 return nullptr;
2452 }
2453 for (auto path : state->pathList)
2454 {
2455 DString absName = path+"/"+fileName;
2456 //printf(" Looking for %s in %s\n",fileName,qPrint(path));
2457 auto fs = checkAndOpenFile(yyscanner,absName,alreadyProcessed);
2458 if (fs)
2459 {
2460 setFileName(yyscanner,absName);
2461 state->yyLineNr=1;
2462 //printf(" -> found it\n");
2463 return fs;
2464 }
2465 else if (alreadyProcessed)
2466 {
2467 return nullptr;
2468 }
2469 }
2470 bool ambig = false;
2471 FileDef *fd=Doxygen::inputNameLinkedMap->findFileDef(fileName,ambig);
2472 if (fd && !ambig) // fallback in case the file is uniquely named in the input, use that one
2473 {
2474 auto fs = checkAndOpenFile(yyscanner,fd->absFilePath(),alreadyProcessed);
2475 if (fs)
2476 {
2477 setFileName(yyscanner,fd->absFilePath());
2478 state->yyLineNr=1;
2479 //printf(" -> found it\n");
2480 return fs;
2481 }
2482 }
2483 return nullptr;
static FileNameLinkedMap * inputNameLinkedMap
Definition doxygen.h:97
A model of a file symbol.
Definition filedef.h:97
virtual DString absFilePath() const =0
FileDef * findFileDef(const DString &n, bool &ambig) const
Returns the file definition in fnMap that matches the file name n.
Definition filename.cpp:38
bool isAbsolutePath(const DString &fileName)
Definition portable.cpp:513
static std::unique_ptr< FileState > checkAndOpenFile(yyscan_t yyscanner, const DString &fileName, bool &alreadyProcessed)
Definition pre.l:2355
static void setFileName(yyscan_t yyscanner, const DString &name)
Definition pre.l:2279
2484}

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

Referenced by readIncludeFile().

◆ forceEndCondSection()

void forceEndCondSection ( yyscan_t yyscanner)
static

Definition at line 4013 of file pre.l.

4014{
4015 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
4016 while (!state->condStack.empty())
4017 {
4018 state->condStack.pop();
4019 }
4020 state->skip=false;
4021}

Referenced by Preprocessor::processFile().

◆ getCurrentChar()

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

Definition at line 4081 of file pre.l.

4082{
4083 //printf("getCurrentChar(%s,%s,%d)\n",qPrint(expr),rest ? rest->data() : 0,pos);
4084 if (pos<expr.length())
4085 {
4086 //printf("%c=expr()\n",expr.at(pos));
4087 return expr.at(pos);
4088 }
4089 else if (rest && !rest->empty())
4090 {
4091 int cc=rest->at(0);
4092 //printf("%c=rest\n",cc);
4093 return cc;
4094 }
4095 else
4096 {
4097 int cc=yyinput(yyscanner);
4098 returnCharToStream(yyscanner,(char)cc);
4099 //printf("%c=yyinput()\n",cc);
4100 return cc;
4101 }
static void returnCharToStream(yyscan_t yyscanner, char c)
Definition pre.l:2661
4102}

References DString::at(), DString::empty(), DString::length(), and returnCharToStream().

Referenced by addTillEndOfComment(), replaceFunctionMacro(), and skipCommentMacroName().

◆ getFenceSize()

yy_size_t getFenceSize ( char * txt,
yy_size_t leng )
static

Definition at line 2268 of file pre.l.

2269{
2270 yy_size_t fenceSize = 0;
2271 for (size_t i = 0; i < leng; i++)
2272 {
2273 if (txt[i] != ' ' && txt[i] != '*' && txt[i] != '\t') break;
2274 fenceSize++;
2275 }
2276 return leng-fenceSize;
2277}

◆ getLexerFILE()

const char * getLexerFILE ( )
inlinestatic

Definition at line 359 of file pre.l.

359{return __FILE__;}

◆ getNextChar()

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

Definition at line 4058 of file pre.l.

4059{
4060 //printf("getNextChar(%s,%s,%d)\n",qPrint(expr),rest ? rest->data() : 0,pos);
4061 if (pos<expr.length())
4062 {
4063 //printf(" expr()='%c'\n",expr.at(pos));
4064 return expr.at(pos++);
4065 }
4066 else if (rest && !rest->empty())
4067 {
4068 int cc=rest->at(0);
4069 *rest=rest->right(rest->length()-1);
4070 //printf(" rest='%c'\n",cc);
4071 return cc;
4072 }
4073 else
4074 {
4075 int cc=yyinput(yyscanner);
4076 //printf(" yyinput()='%c' %d\n",cc,EOF);
4077 return cc;
4078 }
DString right(size_t len) const
Definition dstring.h:311
4079}

References DString::at(), DString::empty(), DString::length(), and DString::right().

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

◆ getNextId()

int getNextId ( const DString & 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 3055 of file pre.l.

3056{
3057 int n;
3058 while (p<(int)expr.length())
3059 {
3060 char c=expr.at(p++);
3061 if (isdigit(c)) // skip number
3062 {
3063 while (p<(int)expr.length() && isId(expr.at(p))) p++;
3064 }
3065 else if (isalpha(c) || c=='_') // read id
3066 {
3067 n=p-1;
3068 while (p<(int)expr.length() && isId(expr.at(p))) p++;
3069 *l=p-n;
3070 return n;
3071 }
3072 else if (c=='"') // skip string
3073 {
3074 char ppc=0,pc=c;
3075 if (p<(int)expr.length()) c=expr.at(p);
3076 while (p<(int)expr.length() && (c!='"' || (pc=='\\' && ppc!='\\')))
3077 // continue as long as no " is found, but ignoring \", but not \\"
3078 {
3079 ppc=pc;
3080 pc=c;
3081 c=expr.at(p);
3082 p++;
3083 }
3084 if (p<(int)expr.length()) ++p; // skip closing quote
3085 }
3086 else if (c=='/') // skip C Comment
3087 {
3088 //printf("Found C comment at p=%d\n",p);
3089 char pc=c;
3090 if (p<(int)expr.length())
3091 {
3092 c=expr.at(p);
3093 if (c=='*') // Start of C comment
3094 {
3095 p++;
3096 while (p<(int)expr.length() && !(pc=='*' && c=='/'))
3097 {
3098 pc=c;
3099 c=expr.at(p++);
3100 }
3101 }
3102 }
3103 //printf("Found end of C comment at p=%d\n",p);
3104 }
3105 }
3106 return -1;
bool isId(char c)
Returns true if c is a valid character for an identifier.
Definition dstring.h:895
3107}

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

Referenced by expandExpression().

◆ incrLevel()

void incrLevel ( yyscan_t yyscanner)
static

Definition at line 2306 of file pre.l.

2307{
2308 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
2309 state->levelGuard.push(false);
2310 //printf("%s line %d: incrLevel %zu\n",qPrint(state->fileName),state->yyLineNr,state->levelGuard.size());
2311}

◆ initPredefined()

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

Definition at line 4157 of file pre.l.

4158{
4159 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
4160
4161 // add predefined macros
4162 StringVector predefList = Config_getList(PREDEFINED);
4163 for (const auto &ds : predefList)
4164 {
4165 size_t i_equals=ds.find('=');
4166 size_t i_obrace=ds.find('(');
4167 size_t i_cbrace=ds.find(')');
4168 bool nonRecursive = i_equals!=std::string::npos && i_equals>0 && ds[i_equals-1]==':';
4169
4170 if ((i_obrace==0) || (i_equals==0) || (i_equals==1 && ds[i_equals-1]==':'))
4171 {
4172 continue; // no define name
4173 }
4174
4175 if (i_obrace<i_equals && i_cbrace<i_equals &&
4176 i_obrace!=std::string::npos && i_cbrace!=std::string::npos &&
4177 i_obrace<i_cbrace
4178 ) // predefined function macro definition
4179 {
4180 static const reg::Ex reId(R"(\a\w*)");
4181 std::map<std::string,int> argMap;
4182 std::string args = ds.substr(i_obrace+1,i_cbrace-i_obrace-1); // part between ( and )
4183 bool hasVarArgs = args.find("...")!=std::string::npos;
4184 //printf("predefined function macro '%s'\n",qPrint(ds));
4185 int count = 0;
4186 reg::Iterator arg_it(args,reId,0);
4187 reg::Iterator arg_end;
4188 // gather the formal arguments in a dictionary
4189 for (; arg_it!=arg_end; ++arg_it)
4190 {
4191 argMap.emplace(arg_it->str(),count++);
4192 }
4193 if (hasVarArgs) // add the variable argument if present
4194 {
4195 argMap.emplace("__VA_ARGS__",count++);
4196 }
Class representing a regular expression.
Definition regex.h:39
Class to iterate through matches.
Definition regex.h:239
4197
4198 // strip definition part
4199 std::string definition;
4200 std::string in=ds.substr(i_equals+1);
4201 reg::Iterator re_it(in,reId);
4202 reg::Iterator re_end;
4203 size_t i=0;
4204 // substitute all occurrences of formal arguments by their
4205 // corresponding markers
4206 for (; re_it!=re_end; ++re_it)
4207 {
4208 const auto &match = *re_it;
4209 size_t pi = match.position();
4210 size_t l = match.length();
4211 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:861
4212
4213 auto it = argMap.find(match.str());
4214 if (it!=argMap.end())
4215 {
4216 int argIndex = it->second;
4217 DString marker;
4218 marker.sprintf(" @%d ",argIndex);
4219 definition+=marker.str();
4220 }
4221 else
4222 {
4223 definition+=match.str();
4224 }
4225 i=pi+l;
4226 }
4227 definition+=in.substr(i);
DString & sprintf(const char *format,...)
Definition dstring.cpp:34
4228
4229 // add define definition to the dictionary of defines for this file
4230 std::string dname = ds.substr(0,i_obrace);
4231 if (!dname.empty())
4232 {
4233 Define def;
4234 def.name = dname;
4235 def.definition = definition;
4236 def.nargs = count;
4237 def.isPredefined = true;
4238 def.nonRecursive = nonRecursive;
4239 def.fileDef = state->yyFileDef;
4240 def.fileName = fileName;
4241 def.varArgs = hasVarArgs;
4242 state->contextDefines.emplace(def.name.str(),def);
4243
4244 //printf("#define '%s' '%s' #nargs=%d hasVarArgs=%d\n",
4245 // qPrint(def.name),qPrint(def.definition),def.nargs,def.varArgs);
4246 }
4247 }
4248 else if (!ds.empty()) // predefined non-function macro definition
4249 {
4250 //printf("predefined normal macro '%s'\n",qPrint(ds));
4251 Define def;
4252 if (i_equals==std::string::npos) // simple define without argument
4253 {
4254 def.name = ds;
4255 def.definition = "1"; // substitute occurrences by 1 (true)
4256 }
4257 else // simple define with argument
4258 {
4259 int ine=static_cast<int>(i_equals) - (nonRecursive ? 1 : 0);
4260 def.name = ds.substr(0,ine);
4261 def.definition = ds.substr(i_equals+1);
4262 }
4263 if (!def.name.empty())
4264 {
4265 def.nargs = -1;
4266 def.isPredefined = true;
4267 def.nonRecursive = nonRecursive;
4268 def.fileDef = state->yyFileDef;
4269 def.fileName = fileName;
4270 state->contextDefines.emplace(def.name.str(),def);
4271 }
4272 }
4273 }
DString substr(size_t pos=0, size_t count=npos) const
Returns a substring of length count starting at pos.
Definition dstring.h:223
4274}

References Config_getList, Define::definition, DString::empty(), Define::fileDef, Define::fileName, Define::isPredefined, Define::name, Define::nargs, Define::nonRecursive, DString::sprintf(), DString::str(), reg::Match::str(), DString::substr(), and Define::varArgs.

Referenced by Preprocessor::processFile().

◆ isDefined()

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

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

Definition at line 4128 of file pre.l.

4129{
4130 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
4131
4132 bool undef = false;
4133 auto findDefine = [&undef,&name](DefineMap &map)
4134 {
4135 Define *d=nullptr;
4136 auto it = map.find(name.str());
4137 if (it!=map.end())
4138 {
4139 d = &it->second;
4140 if (d->undef)
4141 {
4142 undef=true;
4143 d=nullptr;
4144 }
4145 }
4146 return d;
4147 };
bool undef
Definition define.h:41
std::map< std::string, Define > DefineMap
A dictionary of managed Define objects.
Definition pre.l:110
4148
4149 Define *def = findDefine(state->localDefines);
4150 if (def==nullptr && !undef)
4151 {
4152 def = findDefine(state->contextDefines);
4153 }
4154 return def;
4155}

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

Referenced by expandExpression().

◆ otherCaseDone()

bool otherCaseDone ( yyscan_t yyscanner)
static

Definition at line 2334 of file pre.l.

2335{
2336 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
2337 if (state->levelGuard.empty())
2338 {
2339 warn(state->fileName,state->yyLineNr,"Found an #else without a preceding #if.");
2340 return true;
2341 }
2342 else
2343 {
2344 return state->levelGuard.top();
2345 }
2346}

References warn.

◆ outputArray()

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

Definition at line 3736 of file pre.l.

3737{
3738 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
3739 if (state->includeStack.empty() || state->curlyCount>0) (*state->outputBuf)+=std::string_view(a,len);
3740}

◆ outputChar()

void outputChar ( yyscan_t yyscanner,
char c )
inlinestatic

Definition at line 3730 of file pre.l.

3731{
3732 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
3733 if (state->includeStack.empty() || state->curlyCount>0) (*state->outputBuf)+=c;
3734}

Referenced by outputSpace(), and outputSpaces().

◆ outputSpace()

void outputSpace ( yyscan_t yyscanner,
char c )
inlinestatic

Definition at line 3748 of file pre.l.

3749{
3750 if (c=='\t') outputChar(yyscanner,'\t');
3751 else outputChar(yyscanner,' ');
static void outputChar(yyscan_t yyscanner, char c)
Definition pre.l:3730
3752}

References outputChar().

◆ outputSpaces()

void outputSpaces ( yyscan_t yyscanner,
char * s )
inlinestatic

Definition at line 3754 of file pre.l.

3755{
3756 const char *p=s;
3757 char c = 0;
3758 while ((c=*p++))
3759 {
3760 if (c=='\t') outputChar(yyscanner,'\t');
3761 else outputChar(yyscanner,' ');
3762 }
3763}

References outputChar().

◆ outputString()

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

Definition at line 3742 of file pre.l.

3743{
3744 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
3745 if (state->includeStack.empty() || state->curlyCount>0) (*state->outputBuf)+=a.str();
3746}

References DString::str().

Referenced by readIncludeFile().

◆ processConcatOperators()

void processConcatOperators ( DString & 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 2614 of file pre.l.

2615{
2616 if (expr.empty()) return;
2617 //printf("processConcatOperators: in='%s'\n",qPrint(expr));
2618 std::string e = expr.str();
2619 static const reg::Ex r(R"(\s*##\s*)");
DirIterator end(const DirIterator &) noexcept
Definition dir.cpp:181
2621
2622 size_t i=0;
2623 for (;;)
2624 {
2625 reg::Iterator it(e,r,i);
2626 if (it!=end)
2627 {
2628 const auto &match = *it;
2629 size_t n = match.position();
2630 size_t l = match.length();
2631 //printf("Match: '%s'\n",qPrint(expr.mid(i)));
2632 if (n+l+1<e.length() && e[static_cast<int>(n+l)]=='@' && expr[static_cast<int>(n+l+1)]=='-')
2633 {
2634 // remove no-rescan marker after ID
2635 l+=2;
2636 }
2637 //printf("found '%s'\n",qPrint(expr.mid(n,l)));
2638 // remove the ## operator and the surrounding whitespace
2639 e=e.substr(0,n)+e.substr(n+l);
2640 int k=static_cast<int>(n)-1;
2641 while (k>=0 && isId(e[k])) k--;
2642 if (k>0 && e[k]=='-' && e[k-1]=='@')
2643 {
2644 // remove no-rescan marker before ID
2645 e=e.substr(0,k-1)+e.substr(k+1);
2646 n-=2;
2647 }
2648 i=n;
2649 }
2650 else
2651 {
2652 break;
2653 }
2654 }
2655
2656 expr = e;
2657
2658 //printf("processConcatOperators: out='%s'\n",qPrint(expr));
2659}

References DString::empty(), end(), isId(), and DString::str().

Referenced by expandExpression().

◆ processUntilMatchingTerminator()

const char * processUntilMatchingTerminator ( const char * inputStr,
DString & 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 3293 of file pre.l.

3294{
3295 if (inputStr==nullptr) return inputStr;
3296 char term = *inputStr; // capture start character of the literal
3297 if (term!='\'' && term!='"') return inputStr; // not a valid literal
3298 char c=term;
3299 // output start character
3300 result+=c;
3301 inputStr++;
3302 while ((c=*inputStr)) // while inside the literal
3303 {
3304 if (c==term) // found end marker of the literal
3305 {
3306 // output end character and stop
3307 result+=c;
3308 inputStr++;
3309 break;
3310 }
3311 else if (c=='\\') // escaped character, process next character
3312 // as well without checking for end marker.
3313 {
3314 result+=c;
3315 inputStr++;
3316 c=*inputStr;
3317 if (c==0) break; // unexpected end of string after escape character
3318 }
3319 result+=c;
3320 inputStr++;
3321 }
3322 return inputStr;
3323}

References term.

Referenced by removeIdsAndMarkers(), and removeMarkers().

◆ readIncludeFile()

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

Definition at line 3811 of file pre.l.

3812{
3813 AUTO_TRACE("inc={}",inc);
3814 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
3815 uint32_t i=0;
#define AUTO_TRACE(...)
Definition docnode.cpp:53
3816
3817 // find the start of the include file name
3818 while (i<inc.length() &&
3819 (inc.at(i)==' ' || inc.at(i)=='"' || inc.at(i)=='<')
3820 ) i++;
3821 uint32_t s=i;
3822
3823 // was it a local include?
3824 bool localInclude = s>0 && inc.at(s-1)=='"';
3825
3826 // find the end of the include file name
3827 while (i<inc.length() && inc.at(i)!='"' && inc.at(i)!='>') i++;
3828
3829 if (s<inc.length() && i>s) // valid include file name found
3830 {
3831 // extract include path+name
3832 DString incFileName=inc.mid(s,i-s).stripWhiteSpace();
3833 if (incFileName.endsWith(".exe") || incFileName.endsWith(".dll") || incFileName.endsWith(".tlb"))
3834 {
3835 // skip imported binary files (e.g. M$ type libraries)
3836 return;
3837 }
bool endsWith(const char *s) const
Definition dstring.h:617
3838
3839 DString oldFileName = state->fileName;
3840 FileDef *oldFileDef = state->yyFileDef;
3841 int oldLineNr = state->yyLineNr;
3842 //printf("Searching for '%s'\n",qPrint(incFileName));
3843
3844 DString absIncFileName = determineAbsoluteIncludeName(state->fileName,incFileName);
DString determineAbsoluteIncludeName(const DString &curFile, const DString &incFileName)
Definition util.cpp:2929
3845
3846 // findFile will overwrite state->yyFileDef if found
3847 std::unique_ptr<FileState> fs;
3848 bool alreadyProcessed = false;
3849 //printf("calling findFile(%s)\n",qPrint(incFileName));
3850 fs=findFile(yyscanner,absIncFileName,localInclude,alreadyProcessed); // see if the absolute include file can be found
3851 if (fs)
3852 {
3853 {
3854 std::lock_guard<std::mutex> lock(g_globalDefineMutex);
3855 g_defineManager.addInclude(oldFileName.str(),absIncFileName.str());
3856 }
void addInclude(const std::string &fromFileName, const std::string &toFileName)
Definition pre.l:174
static std::unique_ptr< FileState > findFile(yyscan_t yyscanner, const DString &fileName, bool localInclude, bool &alreadyProcessed)
Definition pre.l:2412
3857
3858 //printf("Found include file!\n");
3860 {
3861 for (i=0;i<state->includeStack.size();i++)
3862 {
3864 }
3865 Debug::print(Debug::Preprocessor,0,"#include {}: parsing...\n",incFileName);
3866 }
@ Preprocessor
Definition debug.h:31
static bool isFlagSet(const DebugMask mask)
Definition debug.cpp:132
static void print(DebugMask mask, int prio, fmt::format_string< Args... > fmt, Args &&... args)
Definition debug.h:78
3867
3868 if (state->includeStack.empty() && oldFileDef)
3869 {
3870 PreIncludeInfo *ii = state->includeRelations.find(absIncFileName);
3871 if (ii==nullptr)
3872 {
3873 bool ambig = false;
3874 FileDef *incFd = Doxygen::inputNameLinkedMap->findFileDef(absIncFileName,ambig);
3875 state->includeRelations.add(
3876 absIncFileName,
3877 oldFileDef,
3878 ambig ? nullptr : incFd,
3879 incFileName,
3880 localInclude,
3881 state->isImported
3882 );
3883 }
3884 }
3885
3886 struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
3887 fs->bufState = YY_CURRENT_BUFFER;
3888 fs->lineNr = oldLineNr;
3889 fs->fileName = oldFileName;
3890 fs->curlyCount = state->curlyCount;
3891 //state->curlyCount = 0; // don't reset counter, see issue #10997
3892 fs->lexRulesPart = state->lexRulesPart;
3893 fs->levelGuard = state->levelGuard;
3894 while (!state->levelGuard.empty()) state->levelGuard.pop();
3895 state->lexRulesPart = false;
3896 // push the state on the stack
3897 FileState *fs_ptr = fs.get();
3898 state->includeStack.push_back(std::move(fs));
3899 // set the scanner to the include file
3900
3901 // Deal with file changes due to
3902 // #include's within { .. } blocks
3903 DString lineStr(state->fileName.length()+20, DString::ExplicitSize);
3904 lineStr.sprintf("# 1 \"%s\" 1\n",qPrint(state->fileName));
3905 outputString(yyscanner,lineStr);
@ ExplicitSize
Definition dstring.h:131
const char * qPrint(const char *s)
Definition dstring.h:783
static void outputString(yyscan_t yyscanner, const DString &s)
Definition pre.l:3742
3906
3907 AUTO_TRACE_ADD("Switching to include file {}",incFileName);
3908 state->expectGuard=true;
3909 state->inputBuf = &fs_ptr->fileBuf;
3910 state->inputBufPos=0;
3911 yy_switch_to_buffer(yy_create_buffer(0, YY_BUF_SIZE, yyscanner),yyscanner);
3912 }
3913 else
3914 {
3915 if (alreadyProcessed) // if this header was already process we can just copy the stored macros
3916 // in the local context
3917 {
3918 std::lock_guard<std::mutex> lock(g_globalDefineMutex);
3919 g_defineManager.addInclude(state->fileName.str(),absIncFileName.str());
3920 g_defineManager.retrieve(absIncFileName.str(),state->contextDefines);
3921 }
void retrieve(const std::string &fileName, DefineMap &toMap)
Definition pre.l:197
#define YY_BUF_SIZE
Definition commentcnv.l:19
#define AUTO_TRACE_ADD(...)
Definition docnode.cpp:54
std::string fileBuf
Definition pre.l:86
3922
3923 if (state->includeStack.empty() && oldFileDef)
3924 {
3925 PreIncludeInfo *ii = state->includeRelations.find(absIncFileName);
3926 if (ii==nullptr)
3927 {
3928 bool ambig = false;
3929 FileDef *incFd = Doxygen::inputNameLinkedMap->findFileDef(absIncFileName,ambig);
3930 ii = state->includeRelations.add(absIncFileName,
3931 oldFileDef,
3932 ambig ? nullptr : incFd,
3933 incFileName,
3934 localInclude,
3935 state->isImported
3936 );
3937 }
3938 }
3939
3941 {
3942 for (i=0;i<state->includeStack.size();i++)
3943 {
3945 }
3946 if (alreadyProcessed)
3947 {
3948 Debug::print(Debug::Preprocessor,0,"#include {}: already processed! skipping...\n",incFileName);
3949 }
3950 else
3951 {
3952 Debug::print(Debug::Preprocessor,0,"#include {}: not found! skipping...\n",incFileName);
3953 }
3954 //printf("error: include file %s not found\n",yytext);
3955 }
3956 if (localInclude && !state->includeStack.empty() && state->curlyCount>0 && !alreadyProcessed) // failed to find #include inside { ... }
3957 {
3958 warn(state->fileName,state->yyLineNr,"include file {} not found, perhaps you forgot to add its directory to INCLUDE_PATH?",incFileName);
3959 }
3960 }
3961 }
3962}

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

◆ removeIdsAndMarkers()

DString removeIdsAndMarkers ( const DString & 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 3329 of file pre.l.

3330{
3331 static const std::vector<std::string> signs = { "signed", "unsigned" };
3332 struct TypeInfo { std::string name; size_t size; };
3333 static const std::vector<TypeInfo> types = {
3334 { "short int", sizeof(short int) },
3335 { "long long int", sizeof(long long int) },
3336 { "long int", sizeof(long int) },
3337 { "long long", sizeof(long long) },
3338 { "long double", sizeof(long double) },
3339 { "int", sizeof(int) },
3340 { "short", sizeof(short) },
3341 { "bool", sizeof(bool) },
3342 { "long", sizeof(long) },
3343 { "char", sizeof(char) },
3344 { "float", sizeof(float) },
3345 { "double", sizeof(double) },
3346 };
3347
3348 // Check if string p starts with basic types ending with a ')', such as 'signed long)' or ' float )'
3349 // and return the pointer just past the ')' and the size of the type as a tuple.
3350 // If the pattern is not found the tuple (nullptr,0) is returned.
3351 auto process_cast_or_sizeof = [](const char *p) -> std::pair<const char *,size_t>
3352 {
3353 const char *q = p;
3354 while (*q==' ' || *q=='\t') q++;
3355 bool found=false;
3356 size_t size = sizeof(int); // '(signed)' or '(unsigned)' is an int type
3357 for (const auto &sgn : signs)
3358 {
3359 if (dstrncmp(q,sgn.c_str(),sgn.length())==0) { q+=sgn.length(); found=true; }
3360 }
3361 if (!found || *q==' ' || *q=='\t' || *q==')') // continue searching
3362 {
3363 while (*q==' ' || *q=='\t') q++;
3364 for (const auto &t : types)
3365 {
3366 if (dstrncmp(q,t.name.c_str(),t.name.length())==0)
3367 {
3368 q += t.name.length();
3369 size = t.size;
3370 break;
3371 }
3372 }
3373 while (*q==' ' || *q=='\t') q++;
3374 if (*q==')') return std::make_pair(++q,size);
3375 }
3376 return std::make_pair(nullptr,0);
3377 };
int dstrncmp(const char *str1, const char *str2, size_t len)
Definition dstring.h:56
3378
3379 //printf("removeIdsAndMarkers(%s)\n",qPrint(s));
3380 if (s.empty()) return s;
3381 const char *p=s.data();
3382 bool inNum=false;
3383 DString result;
3384 if (p)
3385 {
3386 char c = 0;
3387 while ((c=*p))
3388 {
3389 if (c=='(') // potential cast, ignore it
3390 {
3391 const char *q = process_cast_or_sizeof(p+1).first;
3392 //printf("potential cast:\nin: %s\nout: %s\n",p,q);
3393 if (q)
3394 {
3395 p=q;
3396 continue;
3397 }
3398 }
3399 else if (c=='s' && literal_at(p,"sizeof")) // sizeof(...)
3400 {
3401 const char *q = p+6;
3402 while (*q==' ' || *q=='\t') q++;
3403 if (*q=='(')
3404 {
3405 auto r = process_cast_or_sizeof(q+1);
3406 //printf("sizeof:\nin: %s\nout: %zu%s\n--> sizeof=%zu\n",p,r.second,r.first,r.second);
3407 if (r.first)
3408 {
3409 result+=DString().setNum(r.second);
3410 p=r.first;
3411 continue;
3412 }
3413 }
3414 }
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:101
3415
3416 if (c=='@') // replace @@ with @ and remove @E
3417 {
3418 if (*(p+1)=='@')
3419 {
3420 result+=c;
3421 }
3422 else if (*(p+1)=='E')
3423 {
3424 // skip
3425 }
3426 p+=2;
3427 }
3428 else if (isdigit(c)) // number
3429 {
3430 result+=c;
3431 p++;
3432 inNum=true;
3433 }
3434 else if (c=='\'') // quoted character
3435 {
3436 p = processUntilMatchingTerminator(p,result);
3437 }
3438 else if (c=='d' && !inNum) // identifier starting with a 'd'
3439 {
3440 if (literal_at(p,"defined ") || literal_at(p,"defined("))
3441 // defined keyword
3442 {
3443 p+=7; // skip defined
3444 }
3445 else
3446 {
3447 result+="0L";
3448 p++;
3449 while ((c=*p) && isId(c)) p++;
3450 }
3451 }
3452 else if ((isalpha(c) || c=='_') && !inNum) // replace identifier with 0L
3453 {
3454 result+="0L";
3455 p++;
3456 while ((c=*p) && isId(c)) p++;
3457 while ((c=*p) && isspace((uint8_t)c)) p++;
3458 if (*p=='(') // undefined function macro
3459 {
3460 p++;
3461 int count=1;
3462 while ((c=*p++))
3463 {
3464 if (c=='(') count++;
3465 else if (c==')')
3466 {
3467 count--;
3468 if (count==0) break;
3469 }
3470 else if (c=='/')
3471 {
3472 char pc=c;
3473 c=*++p;
3474 if (c=='*') // start of C comment
3475 {
3476 while (*p && !(pc=='*' && c=='/')) // search end of comment
3477 {
3478 pc=c;
3479 c=*++p;
3480 }
3481 p++;
3482 }
3483 }
3484 }
3485 }
3486 }
3487 else if (c=='/') // skip C comments
3488 {
3489 char pc=c;
3490 c=*++p;
3491 if (c=='*') // start of C comment
3492 {
3493 while (*p && !(pc=='*' && c=='/')) // search end of comment
3494 {
3495 pc=c;
3496 c=*++p;
3497 }
3498 p++;
3499 }
3500 else // oops, not comment but division
3501 {
3502 result+=pc;
3503 goto nextChar;
3504 }
3505 }
3506 else
3507 {
static const char * processUntilMatchingTerminator(const char *inputStr, DString &result)
Process string or character literal.
Definition pre.l:3293
3508nextChar:
3509 result+=c;
3510 char lc=(char)tolower(c);
3511 if (!isId(lc) && lc!='.' /*&& lc!='-' && lc!='+'*/) inNum=false;
3512 p++;
3513 }
3514 }
3515 }
3516 //printf("removeIdsAndMarkers(%s)=%s\n",s,qPrint(result));
3517 return result;
3518}

References DString::data(), dstrncmp(), DString::empty(), isId(), literal_at(), processUntilMatchingTerminator(), and DString::setNum().

Referenced by computeExpression().

◆ removeMarkers()

DString removeMarkers ( const DString & s)
static

replaces all occurrences of @ in s by @

assumption:
s only contains pairs of @'s

Definition at line 3524 of file pre.l.

3525{
3526 if (s.empty()) return s;
3527 const char *p=s.data();
3528 DString result;
3529 if (p)
3530 {
3531 char c = 0;
3532 while ((c=*p))
3533 {
3534 switch(c)
3535 {
3536 case '@': // replace @@ with @
3537 {
3538 if (*(p+1)=='@')
3539 {
3540 result+=c;
3541 }
3542 p+=2;
3543 }
3544 break;
3545 case '/': // skip C comments
3546 {
3547 result+=c;
3548 char pc=c;
3549 c=*++p;
3550 if (c=='*') // start of C comment
3551 {
3552 while (*p && !(pc=='*' && c=='/')) // search end of comment
3553 {
3554 if (*p=='@' && *(p+1)=='@')
3555 {
3556 result+=c;
3557 p++;
3558 }
3559 else
3560 {
3561 result+=c;
3562 }
3563 pc=c;
3564 c=*++p;
3565 }
3566 if (*p)
3567 {
3568 result+=c;
3569 p++;
3570 }
3571 }
3572 }
3573 break;
3574 case '"': // skip string literals
3575 case '\'': // skip char literals
3576 p = processUntilMatchingTerminator(p,result);
3577 break;
3578 default:
3579 {
3580 result+=c;
3581 p++;
3582 }
3583 break;
3584 }
3585 }
3586 }
3587 //printf("RemoveMarkers(%s)=%s\n",s,qPrint(result));
3588 return result;
3589}

References DString::data(), DString::empty(), and processUntilMatchingTerminator().

Referenced by computeExpression(), and expandMacro().

◆ replaceFunctionMacro()

bool replaceFunctionMacro ( yyscan_t yyscanner,
const DString & expr,
DString * rest,
int pos,
int & len,
const Define * def,
DString & 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 2786 of file pre.l.

2787{
2788 //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());
2789 uint32_t j=pos;
2790 len=0;
2791 result.clear();
2792 int cc;
2793
2794 skipCommentMacroName(yyscanner, expr, rest, cc, j, len);
static void skipCommentMacroName(yyscan_t yyscanner, const DString &expr, DString *rest, int &cc, uint32_t &j, int &len)
Definition pre.l:2702
2795
2796 if (cc!='(')
2797 {
2798 if (cc!=':') // don't add spaces for colons
2799 {
2800 unputChar(yyscanner,expr,rest,j,' ');
2801 }
2802 return false;
2803 }
2804 getNextChar(yyscanner,expr,rest,j); // eat the '(' character
2805
2806 std::map<std::string,std::string> argTable; // list of arguments
2807 DString arg;
2808 int argCount=0;
2809 int argCountNonEmpty=0;
2810 bool done=false;
2811
2812 // PHASE 1: read the macro arguments
2813 if (def->nargs==0)
2814 {
2815 while ((cc=getNextChar(yyscanner,expr,rest,j))!=EOF && cc!=0)
2816 {
2817 char c = (char)cc;
2818 if (c==')') break;
2819 }
2820 }
2821 else
2822 {
2823 while (!done && (argCount<def->nargs || def->varArgs) &&
2824 ((cc=getNextChar(yyscanner,expr,rest,j))!=EOF && cc!=0)
2825 )
2826 {
2827 char c=(char)cc;
2828 if (c=='(') // argument is a function => search for matching )
2829 {
2830 int lvl=1;
2831 arg+=c;
2832 //char term='\0';
2833 while ((cc=getNextChar(yyscanner,expr,rest,j))!=EOF && cc!=0)
2834 {
2835 c=(char)cc;
2836 //printf("processing %c: term=%c (%d)\n",c,term,term);
2837 if (c=='\'' || c=='\"') // skip ('s and )'s inside strings
2838 {
2839 arg+=c;
2840 addTillEndOfString(yyscanner,expr,rest,j,c,arg);
2841 }
2842 else if (c=='/')
2843 {
2844 int nxtChar = getCurrentChar(yyscanner,expr,rest,j);
2845 if (nxtChar == '*')
2846 {
2847 arg+=c;
2848 addTillEndOfComment(yyscanner,expr,rest,j,c,arg);
2849 }
2850 // We don't need to handle the // case as this has already been converted into a /* .. */ comment.
2851 }
static void addTillEndOfComment(yyscan_t yyscanner, const DString &expr, DString *rest, uint32_t &pos, char term, DString &arg)
Definition pre.l:2686
static void addTillEndOfString(yyscan_t yyscanner, const DString &expr, DString *rest, uint32_t &pos, char term, DString &arg)
Definition pre.l:2667
2852
2853 if (c==')')
2854 {
2855 lvl--;
2856 arg+=c;
2857 if (lvl==0) break;
2858 }
2859 else if (c=='(')
2860 {
2861 lvl++;
2862 arg+=c;
2863 }
2864 else
2865 {
2866 arg+=c;
2867 }
2868 }
2869 }
2870 else if (c==')' || c==',') // last or next argument found
2871 {
2872 if (c==',' && argCount==def->nargs-1 && def->varArgs)
2873 {
2874 expandExpression(yyscanner,arg,nullptr,0,level+1);
2875 arg=arg.stripWhiteSpace();
2876 arg+=',';
2877 }
2878 else
2879 {
2880 expandExpression(yyscanner,arg,nullptr,0,level+1);
2881 arg=arg.stripWhiteSpace();
2882 DString argKey;
2883 argKey.sprintf("@%d",argCount++); // key name
2884 if (c==',' || !arg.empty()) argCountNonEmpty++;
2885 // add argument to the lookup table
2886 argTable.emplace(toStdString(argKey), toStdString(arg));
2887 arg.clear();
2888 if (c==')') // end of the argument list
2889 {
2890 done=true;
2891 }
2892 }
2893 }
2894 else if (c=='\"') // append literal strings
2895 {
2896 arg+=c;
2897 bool found=false;
2898 while (!found && (cc=getNextChar(yyscanner,expr,rest,j))!=EOF && cc!=0)
2899 {
2900 found = cc=='"';
2901 if (cc=='\\')
2902 {
2903 c=(char)cc;
2904 arg+=c;
2905 if ((cc=getNextChar(yyscanner,expr,rest,j))==EOF || cc==0) break;
2906 }
2907 c=(char)cc;
2908 arg+=c;
2909 }
2910 }
2911 else if (c=='\'') // append literal characters
2912 {
2913 arg+=c;
2914 bool found=false;
2915 while (!found && (cc=getNextChar(yyscanner,expr,rest,j))!=EOF && cc!=0)
2916 {
2917 found = cc=='\'';
2918 if (cc=='\\')
2919 {
2920 c=(char)cc;
2921 arg+=c;
2922 if ((cc=getNextChar(yyscanner,expr,rest,j))==EOF || cc==0) break;
2923 }
2924 c=(char)cc;
2925 arg+=c;
2926 }
2927 }
2928 else if (c=='/') // possible start of a comment
2929 {
2930 char prevChar = '\0';
2931 arg+=c;
2932 if ((cc=getCurrentChar(yyscanner,expr,rest,j)) == '*') // we have a comment
2933 {
2934 while ((cc=getNextChar(yyscanner,expr,rest,j))!=EOF && cc!=0)
2935 {
2936 c=(char)cc;
2937 arg+=c;
2938 if (c == '/' && prevChar == '*') break; // we have an end of comment
2939 prevChar = c;
2940 }
2941 }
2942 }
2943 else // append other characters
2944 {
2945 arg+=c;
2946 }
2947 }
2948 }
2949
2950 // PHASE 2: apply the macro function
2951 if (argCount==def->nargs || // same number of arguments
2952 (argCount>=def->nargs-1 && def->varArgs)) // variadic macro with at least as many
2953 // params as the non-variadic part (see bug731985)
2954 {
2955 size_t k=0;
2956 // substitution of all formal arguments
2957 DString resExpr;
2959 //printf("varArgs=%d argCount=%d def->nargs=%d d=%s\n",def->varArgs,argCount,def->nargs,qPrint(d));
2960 if (def->varArgs) d = expandVAOpt(d,argCountNonEmpty!=def->nargs-1);
2961 //printf("Macro definition: '%s'\n",qPrint(d));
2962 bool inString=false;
2963 while (k<d.length())
2964 {
2965 if (d.at(k)=='@') // maybe a marker, otherwise an escaped @
2966 {
2967 if (d.at(k+1)=='@') // escaped @ => copy it (is unescaped later)
2968 {
2969 k+=2;
2970 resExpr+="@@"; // we unescape these later
2971 }
2972 else if (d.at(k+1)=='-') // no-rescan marker
2973 {
2974 k+=2;
2975 resExpr+="@-";
2976 }
2977 else // argument marker => read the argument number
2978 {
2979 DString key="@";
2980 bool hash=false;
2981 int l=static_cast<int>(k)-1;
2982 // search for ## backward
2983 if (l>=0 && d.at(l)=='"') l--;
2984 while (l>=0 && d.at(l)==' ') l--;
2985 if (l>0 && d.at(l)=='#' && d.at(l-1)=='#') hash=true;
2986 k++;
2987 // scan the number
2988 while (k<d.length() && d.at(k)>='0' && d.at(k)<='9') key+=d.at(k++);
2989 if (!hash)
2990 {
2991 // search for ## forward
2992 l=static_cast<int>(k);
2993 if (l<(int)d.length() && d.at(l)=='"') l++;
2994 while (l<(int)d.length() && d.at(l)==' ') l++;
2995 if (l<(int)d.length()-1 && d.at(l)=='#' && d.at(l+1)=='#') hash=true;
2996 }
2997 //printf("request key %s result %s\n",qPrint(key),argTable[key]->data());
2998 auto it = argTable.find(key.str());
2999 if (it!=argTable.end())
3000 {
3001 DString substArg = it->second;
3002 //printf("substArg='%s'\n",qPrint(substArg));
3003 // only if no ## operator is before or after the argument
3004 // marker we do macro expansion.
3005 if (!hash)
3006 {
3007 expandExpression(yyscanner,substArg,nullptr,0,level+1);
3008 }
3009 if (inString)
3010 {
3011 //printf("'%s'=stringize('%s')\n",qPrint(stringize(*subst)),subst->data());
static DString expandVAOpt(const DString &vaStr, bool hasOptionalArgs)
Definition pre.l:2734
3012
3013 // if the marker is inside a string (because a # was put
3014 // before the macro name) we must escape " and \ characters
3015 resExpr+=stringize(substArg);
3016 }
3017 else
3018 {
3019 if (hash && substArg.empty())
3020 {
3021 resExpr+="@E"; // empty argument will be remove later on
3022 }
3023 resExpr+=substArg;
3024 }
3025 }
3026 }
3027 }
3028 else // no marker, just copy
3029 {
3030 if (!inString && d.at(k)=='\"')
3031 {
3032 inString=true; // entering a literal string
3033 }
3034 else if (k>2 && inString && d.at(k)=='\"' && (d.at(k-1)!='\\' || d.at(k-2)=='\\'))
3035 {
3036 inString=false; // leaving a literal string
3037 }
3038 resExpr+=d.at(k++);
3039 }
3040 }
3041 len=j-pos;
3042 result=resExpr;
3043 //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());
3044 return true;
3045 }
3046 //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());
3047 return false;
static DString stringize(const DString &s)
Definition pre.l:2536
3048}

References addTillEndOfComment(), addTillEndOfString(), DString::at(), DString::clear(), Define::definition, DString::empty(), expandExpression(), expandVAOpt(), getCurrentChar(), getNextChar(), DString::length(), Define::nargs, skipCommentMacroName(), DString::sprintf(), DString::str(), stringize(), DString::stripWhiteSpace(), toStdString(), unputChar(), and Define::varArgs.

Referenced by expandExpression().

◆ resolveTrigraph()

char resolveTrigraph ( char c)
static

Definition at line 4038 of file pre.l.

4039{
4040 switch (c)
4041 {
4042 case '=': return '#';
4043 case '/': return '\\';
4044 case '\'': return '^';
4045 case '(': return '[';
4046 case ')': return ']';
4047 case '!': return '|';
4048 case '<': return '{';
4049 case '>': return '}';
4050 case '-': return '~';
4051 }
4052 return '?';
4053}

◆ returnCharToStream()

void returnCharToStream ( yyscan_t yyscanner,
char c )
static

Definition at line 2661 of file pre.l.

2662{
2663 struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
2664 unput(c);
2665}

Referenced by getCurrentChar(), and unputChar().

◆ setCaseDone()

void setCaseDone ( yyscan_t yyscanner,
bool value )
static

Definition at line 2348 of file pre.l.

2349{
2350 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
2351 state->levelGuard.top()=value;
2352}

◆ setFileName()

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

Definition at line 2279 of file pre.l.

2280{
2281 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
2282 bool ambig = false;
2283 FileInfo fi(name.str());
2284 state->fileName=fi.absFilePath();
2285 state->yyFileDef=Doxygen::inputNameLinkedMap->findFileDef(state->fileName,ambig);
2286 if (state->yyFileDef==nullptr) // if this is not an input file check if it is an include file
2287 {
2288 state->yyFileDef=Doxygen::includeNameLinkedMap->findFileDef(state->fileName,ambig);
2289 }
2290 //printf("setFileName(%s) state->fileName=%s state->yyFileDef=%p\n",
2291 // name,qPrint(state->fileName),state->yyFileDef);
2292 if (state->yyFileDef && state->yyFileDef->isReference()) state->yyFileDef=nullptr;
2293 state->insideIDL = getLanguageFromFileName(state->fileName)==SrcLangExt::IDL;
2294 state->insideCS = getLanguageFromFileName(state->fileName)==SrcLangExt::CSharp;
2295 state->insideFtn = getLanguageFromFileName(state->fileName)==SrcLangExt::Fortran;
2296 state->isFixedFormFtn = false;
2297 if (state->insideFtn)
2298 {
2300 state->isFixedFormFtn = recognizeFixedForm(DString(state->inputBuf->data()),fmt);
2301 }
2302 EntryType section = EntryType::guessSection(state->fileName);
2303 state->isSource = section.isHeader() || section.isSource();
static FileNameLinkedMap * includeNameLinkedMap
Definition doxygen.h:94
Wrapper class for the Entry type.
Definition types.h:856
static EntryType guessSection(const DString &name)
Definition types.cpp:22
bool recognizeFixedForm(const DString &contents, FortranFormat format)
FortranFormat convertFileNameFortranParserCode(const DString &fn)
Definition message.h:146
FortranFormat
Definition types.h:612
SrcLangExt getLanguageFromFileName(const DString &fileName, SrcLangExt defLang)
Definition util.cpp:4168
2304}

References FileInfo::absFilePath(), convertFileNameFortranParserCode(), FileNameLinkedMap::findFileDef(), getLanguageFromFileName(), EntryType::guessSection(), Doxygen::includeNameLinkedMap, Doxygen::inputNameLinkedMap, recognizeFixedForm(), and DString::str().

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

◆ skipCommentMacroName()

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

Definition at line 2702 of file pre.l.

2704{
2705 bool changed = false;
2706
2707 do
2708 {
2709 changed = false;
2710 while ((cc=getCurrentChar(yyscanner,expr,rest,j))!=EOF && cc!='\n' && isspace(cc))
2711 {
2712 len++;
2713 getNextChar(yyscanner,expr,rest,j);
2714 }
2715
2716 if (cc=='/') // possible start of a comment
2717 {
2718 int prevChar = '\0';
2719 getNextChar(yyscanner,expr,rest,j);
2720 if ((cc=getCurrentChar(yyscanner,expr,rest,j))!=EOF && cc == '*') // we have a comment
2721 {
2722 while ((cc=getNextChar(yyscanner,expr,rest,j))!=EOF && cc!=0)
2723 {
2724 if (cc == '/' && prevChar == '*') break; // we have an end of comment
2725 prevChar = cc;
2726 }
2727 if (cc != EOF) changed = true;
2728 }
2729 }
2730 } while (changed);
2731}

References getCurrentChar(), and getNextChar().

Referenced by replaceFunctionMacro().

◆ startCondSection()

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

Definition at line 3966 of file pre.l.

3967{
3968 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
3969 //printf("startCondSection: skip=%d stack=%d\n",state->skip,state->condStack.size());
3970 CondParser prs;
3971 bool expResult = prs.parse(state->fileName.data(),state->yyLineNr,sectId.data());
3972 state->condStack.emplace(std::make_unique<preYY_CondCtx>(state->fileName,state->yyLineNr,sectId,state->skip));
3973 if (!expResult)
3974 {
3975 state->skip=true;
3976 }
3977 //printf(" expResult=%d skip=%d\n",expResult,state->skip);
Copyright (C) 1997-2026 by Dimitri van Heesch.
Definition condparser.h:29
bool parse(const DString &fileName, int lineNr, const DString &expr)
parses and evaluates the given expression.
3978}

References DString::data(), and CondParser::parse().

◆ stateToString()

const char * stateToString ( int state)
static

◆ stringize()

DString stringize ( const DString & s)
static

Definition at line 2536 of file pre.l.

2537{
2538 DString result;
2539 uint32_t i=0;
2540 bool inString=false;
2541 bool inChar=false;
2542 char c,pc;
2543 while (i<s.length())
2544 {
2545 if (!inString && !inChar)
2546 {
2547 while (i<s.length() && !inString && !inChar)
2548 {
2549 c=s.at(i++);
2550 if (c=='"')
2551 {
2552 result+="\\\"";
2553 inString=true;
2554 }
2555 else if (c=='\'')
2556 {
2557 result+=c;
2558 inChar=true;
2559 }
2560 else
2561 {
2562 result+=c;
2563 }
2564 }
2565 }
2566 else if (inChar)
2567 {
2568 while (i<s.length() && inChar)
2569 {
2570 c=s.at(i++);
2571 if (c=='\'')
2572 {
2573 result+='\'';
2574 inChar=false;
2575 }
2576 else if (c=='\\')
2577 {
2578 result+="\\\\";
2579 }
2580 else
2581 {
2582 result+=c;
2583 }
2584 }
2585 }
2586 else
2587 {
2588 pc=0;
2589 while (i<s.length() && inString)
2590 {
2591 c=s.at(i++);
2592 if (c=='"')
2593 {
2594 result+="\\\"";
2595 inString= pc=='\\';
2596 }
2597 else if (c=='\\')
2598 result+="\\\\";
2599 else
2600 result+=c;
2601 pc=c;
2602 }
2603 }
2604 }
2605 //printf("stringize '%s'->'%s'\n",qPrint(s),qPrint(result));
2606 return result;
2607}

References DString::at(), and DString::length().

Referenced by replaceFunctionMacro().

◆ unputChar()

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

Definition at line 4104 of file pre.l.

4105{
4106 //printf("unputChar(%s,%s,%d,%c)\n",qPrint(expr),rest ? rest->data() : 0,pos,c);
4107 if (pos<expr.length())
4108 {
4109 pos++;
4110 }
4111 else if (rest)
4112 {
4113 //printf(" prepending '%c' to rest!\n",c);
4114 char cs[2];cs[0]=c;cs[1]='\0';
4115 rest->prepend(cs);
4116 }
4117 else
4118 {
4119 //printf(" yyunput()='%c'\n",c);
4120 returnCharToStream(yyscanner,c);
4121 }
4122 //printf("result: unputChar(%s,%s,%d,%c)\n",qPrint(expr),rest ? rest->data() : 0,pos,c);
DString & prepend(const char *s)
Definition dstring.h:515
4123}

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

Referenced by addSeparatorsIfNeeded(), and replaceFunctionMacro().

◆ yylex()

int yylex ( yyscan_t yyscanner)

Definition at line 493 of file pre.l.

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

◆ yyread()

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

Definition at line 2258 of file pre.l.

2259{
2260 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
2261 int bytesInBuf = static_cast<int>(state->inputBuf->size())-state->inputBufPos;
2262 int bytesToCopy = std::min(max_size,bytesInBuf);
2263 memcpy(buf,state->inputBuf->data()+state->inputBufPos,bytesToCopy);
2264 state->inputBufPos+=bytesToCopy;
2265 return bytesToCopy;
2266}

Variable Documentation

◆ g_debugMutex

std::mutex g_debugMutex
static

Definition at line 234 of file pre.l.

Referenced by Preprocessor::processFile().

◆ g_defineManager

DefineManager g_defineManager
static

Definition at line 237 of file pre.l.

Referenced by checkAndOpenFile(), and readIncludeFile().

◆ g_globalDefineMutex

std::mutex g_globalDefineMutex
static

Definition at line 235 of file pre.l.

Referenced by checkAndOpenFile(), and readIncludeFile().

◆ g_updateGlobals

std::mutex g_updateGlobals
static

Definition at line 236 of file pre.l.

Referenced by Preprocessor::processFile().