Doxygen
Loading...
Searching...
No Matches
pre.l File Reference
#include <stdint.h>
#include "doxygen.h"
#include <stack>
#include <deque>
#include <algorithm>
#include <utility>
#include <mutex>
#include <thread>
#include <cstdio>
#include <cassert>
#include <cctype>
#include <cerrno>
#include "dstring.h"
#include "containers.h"
#include "pre.h"
#include "constexp.h"
#include "define.h"
#include "message.h"
#include "util.h"
#include "defargs.h"
#include "debug.h"
#include "portable.h"
#include "arguments.h"
#include "entry.h"
#include "condparser.h"
#include "config.h"
#include "filedef.h"
#include "regex.h"
#include "fileinfo.h"
#include "trace.h"
#include "stringutil.h"
#include "filename.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 3108 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 at line 355 of file pre.l.

◆ YY_NO_UNISTD_H

#define YY_NO_UNISTD_H   1

Definition at line 67 of file pre.l.

◆ YY_TYPEDEF_YY_SCANNER_T

#define YY_TYPEDEF_YY_SCANNER_T

Definition at line 22 of file pre.l.

Typedef Documentation

◆ DefineMap

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

A dictionary of managed Define objects.

Definition at line 109 of file pre.l.

◆ yyscan_t

typedef yyguts_t* yyscan_t

Definition at line 24 of file pre.l.

Function Documentation

◆ addDefine()

void addDefine ( yyscan_t yyscanner)
static

Definition at line 3656 of file pre.l.

3657{
3658 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
3659 Define def;
3660 def.name = state->defName;
3661 def.definition = state->defText.stripWhiteSpace();
3662 def.nargs = state->defArgs;
3663 def.fileName = state->fileName;
3664 def.fileDef = state->yyFileDef;
3665 def.lineNr = state->yyLineNr-state->yyMLines;
3666 def.columnNr = state->yyColNr;
3667 def.varArgs = state->defVarArgs;
3668 //printf("newDefine: %s %s file: %s\n",qPrint(def.name),qPrint(def.definition),
3669 // def.fileDef ? qPrint(def.fileDef->name()) : qPrint(def.fileName));
3670 //printf("newDefine: '%s'->'%s'\n",qPrint(def.name),qPrint(def.definition));
3671 if (!def.name.empty() &&
3673 {
3674 def.isPredefined=true;
3675 def.expandAsDefined=true;
3676 }
3677 auto it = state->localDefines.find(def.name.str());
3678 if (it!=state->localDefines.end()) // redefine
3679 {
3680 state->localDefines.erase(it);
3681 }
3682 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:153
DString stripWhiteSpace() const
returns a copy of this string with leading and trailing whitespace removed
Definition dstring.h:342
const std::string & str() const
Definition dstring.h:634
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:119
3683}

References addDefine(), 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.

Referenced by addDefine().

◆ addMacroDefinition()

void addMacroDefinition ( yyscan_t yyscanner)
static

Definition at line 3685 of file pre.l.

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

References addMacroDefinition(), 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().

Referenced by addMacroDefinition().

◆ addSeparatorsIfNeeded()

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

Definition at line 3110 of file pre.l.

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

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

Referenced by addSeparatorsIfNeeded(), and expandExpression().

◆ addTillEndOfComment()

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

Definition at line 2685 of file pre.l.

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

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

Referenced by addTillEndOfComment(), and replaceFunctionMacro().

◆ addTillEndOfString()

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

Definition at line 2666 of file pre.l.

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

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

Referenced by addTillEndOfString(), and replaceFunctionMacro().

◆ checkAndOpenFile()

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

Definition at line 2354 of file pre.l.

2355{
2356 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
2357 alreadyProcessed = false;
2358 std::unique_ptr<FileState> fs;
2359 //printf("checkAndOpenFile(%s)\n",qPrint(fileName));
2360 FileInfo fi(fileName.str());
2361 if (fi.exists() && fi.isFile())
2362 {
2363 StringVector exclPatterns = Config_getList(EXCLUDE_PATTERNS);
2364 if (patternMatch(fi,exclPatterns)) return nullptr;
Minimal replacement for QFileInfo.
Definition fileinfo.h:23
#define Config_getList(name)
Definition config.h:38
std::vector< std::string > StringVector
Definition containers.h:33
bool patternMatch(const FileInfo &fi, const StringVector &patList)
Definition util.cpp:5028
2365
2366 DString absName = fi.absFilePath();
2367
2368 // global guard
2369 if (state->curlyCount==0) // not #include inside { ... }
2370 {
2371 std::lock_guard<std::mutex> lock(g_globalDefineMutex);
2372 if (g_defineManager.alreadyProcessed(absName.str()))
2373 {
2374 alreadyProcessed = true;
2375 //printf(" already included 1\n");
2376 return 0; // already done
2377 }
2378 }
2379 // check include stack for absName
bool alreadyProcessed(const std::string &fileName) const
Definition pre.l:207
static std::mutex g_globalDefineMutex
Definition pre.l:234
static DefineManager g_defineManager
Definition pre.l:236
2380
2381 alreadyProcessed = std::any_of(
2382 state->includeStack.begin(),
2383 state->includeStack.end(),
2384 [absName](const std::unique_ptr<FileState> &lfs)
2385 { return lfs->fileName==absName; }
2386 );
2387
2388 if (alreadyProcessed)
2389 {
2390 //printf(" already included 2\n");
2391 return nullptr;
2392 }
2393 //printf("#include %s\n",qPrint(absName));
2394
2395 fs = std::make_unique<FileState>();
2396 if (!readInputFile(absName,fs->fileBuf))
2397 { // error
2398 //printf(" error reading\n");
2399 fs.reset();
2400 }
2401 else
2402 {
2403 addTerminalCharIfMissing(fs->fileBuf,'\n');
2404 fs->oldFileBuf = state->inputBuf;
2405 fs->oldFileBufPos = state->inputBufPos;
2406 }
2407 }
2408 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:4874
2409}

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

Referenced by checkAndOpenFile(), and 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 3594 of file pre.l.

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

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

Referenced by computeExpression().

◆ decrLevel()

void decrLevel ( yyscan_t yyscanner)
static

Definition at line 2312 of file pre.l.

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

References decrLevel(), and warn.

Referenced by decrLevel().

◆ determineBlockName()

void determineBlockName ( yyscan_t yyscanner)
static

Definition at line 3777 of file pre.l.

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

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

Referenced by determineBlockName().

◆ endCondSection()

void endCondSection ( yyscan_t yyscanner)
static

Definition at line 3979 of file pre.l.

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

References endCondSection(), and warn.

◆ escapeAt()

DString escapeAt ( const DString & text)
static

Definition at line 4022 of file pre.l.

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

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

Referenced by escapeAt().

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

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

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

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

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

Referenced by expandMacro().

◆ expandStandardMacro()

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

Definition at line 3627 of file pre.l.

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

References DString::DString(), and expandStandardMacro().

Referenced by expandExpression(), and expandStandardMacro().

◆ expandVAOpt()

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

Definition at line 2733 of file pre.l.

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

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

Referenced by expandVAOpt(), and replaceFunctionMacro().

◆ extractTrailingComment()

DString extractTrailingComment ( const DString & s)
static

Definition at line 2485 of file pre.l.

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

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

Referenced by extractTrailingComment().

◆ extraSpacing()

void extraSpacing ( yyscan_t yyscanner)
inlinestatic

Definition at line 3764 of file pre.l.

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

References extraSpacing().

Referenced by extraSpacing().

◆ findFile()

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

Definition at line 2411 of file pre.l.

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

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

Referenced by findFile(), and readIncludeFile().

◆ forceEndCondSection()

void forceEndCondSection ( yyscan_t yyscanner)
static

Definition at line 4012 of file pre.l.

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

References forceEndCondSection().

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

◆ getCurrentChar()

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

Definition at line 4080 of file pre.l.

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

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

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

◆ getFenceSize()

yy_size_t getFenceSize ( char * txt,
yy_size_t leng )
static

Definition at line 2267 of file pre.l.

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

References getFenceSize().

Referenced by getFenceSize().

◆ getLexerFILE()

const char * getLexerFILE ( )
inlinestatic

Definition at line 358 of file pre.l.

358{return __FILE__;}

References getLexerFILE().

◆ getNextChar()

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

Definition at line 4057 of file pre.l.

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

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

Referenced by addSeparatorsIfNeeded(), addTillEndOfComment(), addTillEndOfString(), getNextChar(), 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 3054 of file pre.l.

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

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

Referenced by expandExpression(), and getNextId().

◆ incrLevel()

void incrLevel ( yyscan_t yyscanner)
static

Definition at line 2305 of file pre.l.

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

References incrLevel().

Referenced by incrLevel().

◆ initPredefined()

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

Definition at line 4156 of file pre.l.

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

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

Referenced by initPredefined(), and 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 4127 of file pre.l.

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

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

Referenced by expandExpression(), and isDefined().

◆ otherCaseDone()

bool otherCaseDone ( yyscan_t yyscanner)
static

Definition at line 2333 of file pre.l.

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

References otherCaseDone(), and warn.

Referenced by otherCaseDone().

◆ outputArray()

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

Definition at line 3735 of file pre.l.

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

References outputArray().

Referenced by outputArray().

◆ outputChar()

void outputChar ( yyscan_t yyscanner,
char c )
inlinestatic

Definition at line 3729 of file pre.l.

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

References outputChar().

Referenced by outputChar(), outputSpace(), and outputSpaces().

◆ outputSpace()

void outputSpace ( yyscan_t yyscanner,
char c )
inlinestatic

Definition at line 3747 of file pre.l.

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

References outputChar(), and outputSpace().

Referenced by outputSpace().

◆ outputSpaces()

void outputSpaces ( yyscan_t yyscanner,
char * s )
inlinestatic

Definition at line 3753 of file pre.l.

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

References outputChar(), and outputSpaces().

Referenced by outputSpaces().

◆ outputString()

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

Definition at line 3741 of file pre.l.

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

References outputString(), and DString::str().

Referenced by outputString(), and 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 2613 of file pre.l.

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

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

Referenced by expandExpression(), and processConcatOperators().

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

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

References processUntilMatchingTerminator(), and term.

Referenced by processUntilMatchingTerminator(), removeIdsAndMarkers(), and removeMarkers().

◆ readIncludeFile()

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

Definition at line 3810 of file pre.l.

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

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(), readIncludeFile(), 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 3328 of file pre.l.

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

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

Referenced by computeExpression(), and removeIdsAndMarkers().

◆ removeMarkers()

DString removeMarkers ( const DString & s)
static

replaces all occurrences of @ in s by @

assumption:
s only contains pairs of @'s

Definition at line 3523 of file pre.l.

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

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

Referenced by computeExpression(), expandMacro(), and removeMarkers().

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

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

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

Referenced by expandExpression(), and replaceFunctionMacro().

◆ resolveTrigraph()

char resolveTrigraph ( char c)
static

Definition at line 4037 of file pre.l.

4038{
4039 switch (c)
4040 {
4041 case '=': return '#';
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 }
4051 return '?';
4052}

References resolveTrigraph().

Referenced by resolveTrigraph().

◆ returnCharToStream()

void returnCharToStream ( yyscan_t yyscanner,
char c )
static

Definition at line 2660 of file pre.l.

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

References returnCharToStream().

Referenced by getCurrentChar(), returnCharToStream(), and unputChar().

◆ setCaseDone()

void setCaseDone ( yyscan_t yyscanner,
bool value )
static

Definition at line 2347 of file pre.l.

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

References setCaseDone().

Referenced by setCaseDone().

◆ setFileName()

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

Definition at line 2278 of file pre.l.

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

References FileInfo::absFilePath(), convertFileNameFortranParserCode(), DString::DString(), 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 2701 of file pre.l.

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

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

Referenced by replaceFunctionMacro(), and skipCommentMacroName().

◆ startCondSection()

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

Definition at line 3965 of file pre.l.

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

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

◆ stateToString()

const char * stateToString ( int state)
static

References stateToString().

◆ stringize()

DString stringize ( const DString & s)
static

Definition at line 2535 of file pre.l.

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

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

Referenced by replaceFunctionMacro(), and stringize().

◆ unputChar()

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

Definition at line 4103 of file pre.l.

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

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

Referenced by addSeparatorsIfNeeded(), replaceFunctionMacro(), and unputChar().

◆ yylex()

int yylex ( yyscan_t yyscanner)

Definition at line 492 of file pre.l.

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

◆ yyread()

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

Definition at line 2257 of file pre.l.

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

References yyread().

Variable Documentation

◆ g_debugMutex

std::mutex g_debugMutex
static

Definition at line 233 of file pre.l.

Referenced by Preprocessor::processFile().

◆ g_defineManager

DefineManager g_defineManager
static

Definition at line 236 of file pre.l.

Referenced by checkAndOpenFile(), and readIncludeFile().

◆ g_globalDefineMutex

std::mutex g_globalDefineMutex
static

Definition at line 234 of file pre.l.

Referenced by checkAndOpenFile(), and readIncludeFile().

◆ g_updateGlobals

std::mutex g_updateGlobals
static

Definition at line 235 of file pre.l.

Referenced by Preprocessor::processFile().