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

Go to the source code of this file.

Classes

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

Macros

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

Typedefs

typedef yyguts_t * yyscan_t
typedef std::map< std::string, Define > DefineMap
 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 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.
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< FileState > checkAndOpenFile (yyscan_t yyscanner, const DString &fileName, bool &alreadyProcessed)
static std::unique_ptr< FileState > findFile (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 removeMarkers (const DString &s)
static void expandArgument (yyscan_t yyscanner, DString &arg, 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 bool isFunctionMacroCall (yyscan_t yyscanner, const DString &expr, DString *rest, int pos)
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 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 3205 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 pre.l:2259

Definition at line 357 of file pre.l.

◆ YY_NO_UNISTD_H

#define YY_NO_UNISTD_H   1

Definition at line 68 of file pre.l.

◆ YY_TYPEDEF_YY_SCANNER_T

#define YY_TYPEDEF_YY_SCANNER_T

Definition at line 22 of file pre.l.

Typedef Documentation

◆ DefineMap

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

A dictionary of managed Define objects.

Definition at line 110 of file pre.l.

◆ yyscan_t

typedef yyguts_t* yyscan_t

Definition at line 24 of file pre.l.

Function Documentation

◆ addDefine()

void addDefine ( yyscan_t yyscanner)
static

Definition at line 3762 of file pre.l.

3763{
3764 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
3765 Define def;
3766 def.name = state->defName;
3767 def.definition = state->defText.stripWhiteSpace();
3768 def.nargs = state->defArgs;
3769 def.fileName = state->fileName;
3770 def.fileDef = state->yyFileDef;
3771 def.lineNr = state->yyLineNr-state->yyMLines;
3772 def.columnNr = state->yyColNr;
3773 def.varArgs = state->defVarArgs;
3774 //printf("newDefine: %s %s file: %s\n",qPrint(def.name),qPrint(def.definition),
3775 // def.fileDef ? qPrint(def.fileDef->name()) : qPrint(def.fileName));
3776 //printf("newDefine: '%s'->'%s'\n",qPrint(def.name),qPrint(def.definition));
3777 if (!def.name.empty() &&
3779 {
3780 def.isPredefined=true;
3781 def.expandAsDefined=true;
3782 }
3783 auto it = state->localDefines.find(def.name.str());
3784 if (it!=state->localDefines.end()) // redefine
3785 {
3786 state->localDefines.erase(it);
3787 }
3788 state->localDefines.emplace(def.name.str(),def);
bool empty() const
Returns true iff the string is empty (std::string compatible alias for isEmpty()).
Definition dstring.h:148
DString stripWhiteSpace() const
returns a copy of this string with leading and trailing whitespace removed
Definition dstring.h:337
const std::string & str() const
Definition dstring.h:645
A class representing a macro definition.
Definition define.h:31
int lineNr
Definition define.h:38
bool varArgs
Definition define.h:42
DString name
Definition define.h:33
FileDef * fileDef
Definition define.h:37
bool isPredefined
Definition define.h:43
DString fileName
Definition define.h:35
size_t columnNr
Definition define.h:39
int nargs
Definition define.h:40
bool expandAsDefined
Definition define.h:45
DString definition
Definition define.h:34
static StringUnorderedSet expandAsDefinedSet
Definition doxygen.h:112
3789}

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

◆ addMacroDefinition()

void addMacroDefinition ( yyscan_t yyscanner)
static

Definition at line 3791 of file pre.l.

3792{
3793 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
3794 if (state->skip) return; // do not add this define as it is inside a
3795 // conditional section (cond command) that is disabled.
3796
3797 Define define;
3798 define.fileName = state->fileName;
3799 define.lineNr = state->yyLineNr - state->yyMLines;
3800 define.columnNr = state->yyColNr;
3801 define.name = state->defName;
3802 define.args = state->defArgsStr;
3803 define.fileDef = state->inputFileDef;
DString args
Definition define.h:36
3804
3805 DString litText = state->defLitText;
3806 size_t l=litText.find('\n');
3807 if (l!=DString::npos && l>0 && litText.left(l).stripWhiteSpace()=="\\")
3808 {
3809 // strip first line if it only contains a slash
3810 litText = litText.mid(l+1);
3811 }
3812 else if (l!=DString::npos && l>0)
3813 {
3814 // align the items on the first line with the items on the second line
3815 size_t k=l+1;
3816 const char *p=litText.data()+k;
3817 char c = 0;
3818 while ((c=*p++) && (c==' ' || c=='\t')) k++;
3819 litText=litText.mid(l+1,k-l-1)+litText.stripWhiteSpace();
3820 }
3821 DString litTextStripped = state->defLitText.stripWhiteSpace();
3822 if (litTextStripped.contains('\n')>=1)
3823 {
3824 define.definition = litText;
3825 }
3826 else
3827 {
3828 define.definition = litTextStripped;
3829 }
3830 {
3831 state->macroDefinitions.push_back(define);
3832 }
A String class for use with Doxygen wrapping std::string and adding some additional functionality off...
Definition dstring.h:84
DString mid(size_t index, size_t len=npos) const
Definition dstring.h:318
static constexpr size_t npos
value used to indicate 'not found' or 'to the end of the string', matching std::string::npos
Definition dstring.h:178
int contains(char c, bool cs=true) const
Definition dstring.cpp:85
size_t find(char c, size_t pos=0) const
Definition dstring.h:239
DString left(size_t len) const
Definition dstring.h:306
const char * data() const
Returns a pointer to the contents of the string in the form of a 0-terminated C string.
Definition dstring.h:157
3833}

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

◆ addSeparatorsIfNeeded()

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

Definition at line 3207 of file pre.l.

3208{
3209 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
3210 if (!state->nospaces)
3211 {
3212 // peek back in the stream, for a colon character
3213 char ccPrev = pos==0 || (int)expr.length()<pos ? state->prevChar : expr.at(pos-1);
3214 DString leftSpace = ccPrev!=':' && ccPrev!=' ' ? " " : "";
3215 int ccNext = 0;
3216 restExpr=restExpr.stripWhiteSpace();
3217 if (restExpr.empty()) // peek ahead in the stream for non-whitespace
3218 {
3219 uint32_t j=(uint32_t)resultExpr.length();
3220 while ((ccNext=getNextChar(yyscanner,resultExpr,nullptr,j))!=EOF && ccNext==' ') { }
3221 if (ccNext != EOF) unputChar(yyscanner,resultExpr,nullptr,j,(char)ccNext);
3222 }
3223 else // take first char from remainder
3224 {
3225 ccNext=restExpr.at(0);
3226 }
3227 // don't add whitespace before a colon
3228 DString rightSpace = ccNext!=':' && ccNext!=' ' ? " " : "";
3229 //printf("ccPrev='%c' ccNext='%c' p=%d expr=%zu restExpr='%s' left='%s' right='%s'\n",
3230 // ccPrev,ccNext,pos,expr.length(),qPrint(restExpr),qPrint(leftSpace),qPrint(rightSpace));
3231 resultExpr=leftSpace+resultExpr+rightSpace;
3232 }
char & at(size_t i)
Returns a reference to the character at index i.
Definition dstring.h:686
size_t length() const
Returns the length of the string, not counting the 0-terminator.
Definition dstring.h:151
static void unputChar(yyscan_t yyscanner, const DString &expr, DString *rest, uint32_t &pos, char c)
Definition pre.l:4211
static int getNextChar(yyscan_t yyscanner, const DString &expr, DString *rest, uint32_t &pos)
Definition pre.l:4163
3233}

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

Referenced by expandExpression().

◆ addTillEndOfComment()

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

Definition at line 2737 of file pre.l.

2739{
2740 int cc;
2741 while ((cc=getNextChar(yyscanner,expr,rest,pos))!=EOF && cc!=0)
2742 {
2743 if (cc=='*' && getCurrentChar(yyscanner,expr,rest,pos)=='/')
2744 {
2745 arg+=(char)cc;
2746 cc = getNextChar(yyscanner,expr,rest,pos);
2747 return;
2748 }
2749 arg+=(char)cc;
2750 }
static int getCurrentChar(yyscan_t yyscanner, const DString &expr, DString *rest, uint32_t pos)
Definition pre.l:4187
2751}

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

Referenced by replaceFunctionMacro().

◆ addTillEndOfString()

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

Definition at line 2718 of file pre.l.

2720{
2721 int cc;
2722 while ((cc=getNextChar(yyscanner,expr,rest,pos))!=EOF && cc!=0)
2723 {
2724 if (cc=='\\')
2725 {
2726 arg+=(char)cc;
2727 cc=getNextChar(yyscanner,expr,rest,pos);
2728 }
2729 else if (cc==term)
2730 {
2731 return;
2732 }
2733 arg+=(char)cc;
2734 }
#define term(fmt,...)
Definition message.h:137
2735}

References getNextChar(), and term.

Referenced by replaceFunctionMacro().

◆ checkAndOpenFile()

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

Definition at line 2356 of file pre.l.

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

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

Referenced by findFile().

◆ computeExpression()

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

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

Definition at line 3700 of file pre.l.

3701{
3702 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
3703 DString e=expr;
3704 DString ee=expr;
3705 ee = removeMarkers(ee);
3706 state->expanded.clear();
3707 expandExpression(yyscanner,e,nullptr,0,0);
3708 //printf("after expansion '%s'\n",qPrint(e));
3709 e = removeIdsAndMarkers(e);
3710 if (e.empty()) return false;
3711 //printf("parsing '%s'\n",qPrint(e));
3712 return state->constExpParser.parse(state->fileName.data(),state->yyLineNr,e.str(),ee.str());
static DString removeMarkers(const DString &s)
Definition pre.l:3625
static DString removeIdsAndMarkers(const DString &s)
Definition pre.l:3433
static bool expandExpression(yyscan_t yyscanner, DString &expr, DString *rest, int pos, int level)
Definition pre.l:3239
3713}

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

◆ decrLevel()

void decrLevel ( yyscan_t yyscanner)
static

Definition at line 2314 of file pre.l.

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

References warn.

◆ determineBlockName()

void determineBlockName ( yyscan_t yyscanner)
static

Definition at line 3883 of file pre.l.

3884{
3885 struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
3886 yyextra->fenceSize=0;
3887 char c=0;
3888 if (yytext[1]=='f' && ((c=yytext[2])=='[' || c=='{' || c=='(' || c=='$'))
3889 {
3890 switch (c)
3891 {
3892 case '[': yyextra->blockName="]"; break;
3893 case '{': yyextra->blockName="}"; break;
3894 case '(': yyextra->blockName=")"; break;
3895 case '$': yyextra->blockName="$"; break;
3896 default: break;
3897 }
3898 yyextra->blockName=yyextra->blockName.stripWhiteSpace();
3899 }
3900 else
3901 {
3902 DString bn=DString(&yytext[1]).stripWhiteSpace();
3903 if (bn=="startuml")
3904 {
3905 yyextra->blockName="uml";
3906 }
3907 else
3908 {
3909 if (size_t i = bn.find('{'); // for \code{.c}
3910 i!=DString::npos) bn=bn.left(i).stripWhiteSpace();
3911 yyextra->blockName=bn;
3912 }
3913 }
3914}

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

◆ endCondSection()

void endCondSection ( yyscan_t yyscanner)
static

Definition at line 4085 of file pre.l.

4086{
4087 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
4088 if (state->condGuardCount>0 && state->condGuardErrorLine==0)
4089 {
4090 state->condGuardErrorLine = state->yyLineNr;
4091 state->condGuardErrorFileName = state->fileName;
4092 state->condGuardErrorMessage = "more #if's than #endif's in \\cond..\\endcond section";
4093 }
4094 else if (state->condGuardCount<0 && state->condGuardErrorLine==0)
4095 {
4096 state->condGuardErrorLine = state->yyLineNr;
4097 state->condGuardErrorFileName = state->fileName;
4098 state->condGuardErrorMessage = "more #endif's than #if's in \\cond..\\endcond section";
4099 }
4100 else // balanced again -> no error
4101 {
4102 state->condGuardErrorLine = 0;
4103 }
4104 if (state->condStack.empty())
4105 {
4106 warn(state->fileName,state->yyLineNr,"the \\endcond does not have a corresponding \\cond in this file");
4107 state->skip=false;
4108 }
4109 else
4110 {
4111 const std::unique_ptr<preYY_CondCtx> &ctx = state->condStack.top();
4112 state->skip=ctx->skip;
4113 state->condStack.pop();
4114 }
4115 //printf("endCondSection: skip=%d stack=%d\n",state->skip,state->condStack.count());
4116}

References warn.

◆ escapeAt()

DString escapeAt ( const DString & text)
static

Definition at line 4128 of file pre.l.

4129{
4130 DString result;
4131 if (!text.empty())
4132 {
4133 char c = 0;
4134 const char *p=text.data();
4135 while ((c=*p++))
4136 {
4137 if (c=='@') result+="@@"; else result+=c;
4138 }
4139 }
4140 return result;
4141}

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

◆ expandArgument()

void expandArgument ( yyscan_t yyscanner,
DString & arg,
int level )
static

Definition at line 2538 of file pre.l.

2539{
2540 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
2541 // Argument prescan cannot consume tokens from the enclosing input stream.
2542 bool previous = state->boundedExpansion;
2543 state->boundedExpansion = true;
2544 expandExpression(yyscanner,arg,nullptr,0,level);
2545 state->boundedExpansion = previous;
2546}

References expandExpression().

Referenced by replaceFunctionMacro().

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

3240{
3241 struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
3242 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
3243 //printf(">expandExpression(expr='%s',rest='%s',pos=%d,level=%d)\n",qPrint(expr),rest ? qPrint(*rest) : "", pos, level);
3244 if (expr.empty())
3245 {
3246 //printf("<expandExpression: empty\n");
3247 return true;
3248 }
3249 if (state->expanded.find(expr.str())!=state->expanded.end() &&
3250 level>MAX_EXPANSION_DEPTH) // check for too deep recursive expansions
3251 {
3252 //printf("<expandExpression: already expanded expr='%s'\n",qPrint(expr));
3253 return false;
3254 }
3255 else
3256 {
3257 state->expanded.insert(expr.str());
3258 }
3259 DString macroName;
3260 DString expMacro;
3261 bool definedTest=false;
3262 int i=pos, l=0, p=0, len=0;
3263 int startPos = pos;
3264 int samePosCount=0;
3265 while ((p=getNextId(expr,i,&l))!=-1) // search for an macro name
3266 {
3267 bool replaced=false;
3268 DString resultExpr;
3269 macroName=expr.mid(p,l);
3270 //printf(" p=%d macroName=%s\n",p,qPrint(macroName));
3271 if (!(resultExpr = expandStandardMacro(yyscanner,macroName)).empty())
3272 {
3273 DString restExpr=expr.mid(p+8);
3274 expr=expr.left(p)+resultExpr+restExpr;
3275 }
3276 else if (p<2 || !(expr.at(p-2)=='@' && expr.at(p-1)=='-')) // no-rescan marker?
3277 {
3278 if (state->expandedDict.find(macroName.str())==state->expandedDict.end()) // expand macro
3279 {
3280 bool expanded=false;
3281 Define *def=isDefined(yyscanner,macroName);
3282 // In case EXPAND_ONLY_PREDEF is enabled prevent expansion unless the macro was explicitly
3283 // predefined
3284 if (yyextra->expandOnlyPredef && def && !def->isPredefined) def=nullptr;
3285 if (macroName=="defined")
3286 {
3287 //printf("found defined inside macro definition '%s'\n",qPrint(expr.mid(p)));
3288 definedTest=true;
3289 }
3290 else if (definedTest) // macro name was found after defined
3291 {
3292 if (def) expMacro = " 1 "; else expMacro = " 0 ";
3293 replaced=true;
3294 len=l;
3295 definedTest=false;
3296 }
3297 else if (def && def->nargs==-1) // simple macro
3298 {
3299 // substitute the definition of the macro
3300 expMacro=def->definition.stripWhiteSpace();
3301 //expMacro=def->definition.stripWhiteSpace();
3302 replaced=true;
3303 len=l;
3304 //printf("simple macro expansion='%s'->'%s'\n",qPrint(macroName),qPrint(expMacro));
3305 }
3306 else if (def && def->nargs>=0) // function macro
3307 {
3308 //printf(" >>>> call replaceFunctionMacro expr='%s'\n",qPrint(expr));
3309 replaced=replaceFunctionMacro(yyscanner,expr,rest,p+l,len,def,expMacro,level);
3310 //printf(" <<<< call replaceFunctionMacro: replaced=%d\n",replaced);
3311 len+=l;
3312 }
#define MAX_EXPANSION_DEPTH
Definition pre.l:3205
static DString expandStandardMacro(yyscan_t yyscanner, const DString &name)
Definition pre.l:3733
static int getNextId(const DString &expr, int p, int *l)
Definition pre.l:3151
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:2867
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:4235
3313
3314 if (replaced) // expand the macro and rescan the expression
3315 {
3316 //printf(" replacing '%s'->'%s'\n",qPrint(expr.mid(p,len)),qPrint(expMacro));
3317 resultExpr=expMacro;
3318 DString restExpr=expr.mid(p+len);
3319 addSeparatorsIfNeeded(yyscanner,expr,resultExpr,restExpr,p);
3320 processConcatOperators(resultExpr);
3321 //printf(" macroName=%s restExpr='%s' def->nonRecursive=%d\n",qPrint(macroName),qPrint(restExpr),def ? def->nonRecursive : false);
3322 if (def && !def->nonRecursive)
3323 {
3324 state->expandedDict.emplace(toStdString(macroName),def);
3325 expanded = expandExpression(yyscanner,resultExpr,&restExpr,0,level+1);
3326 state->expandedDict.erase(toStdString(macroName));
3327 }
3328 else if (def && def->nonRecursive)
3329 {
3330 expanded = true;
3331 }
3332 if (expanded)
3333 {
3334 //printf("expanded '%s' + '%s' + '%s'\n",qPrint(expr.left(p)),qPrint(resultExpr),qPrint(restExpr));
3335 expr=expr.left(p)+resultExpr+restExpr;
3336 // The replacement has already been rescanned; continue with the remaining input.
3337 i=p+static_cast<int>(resultExpr.length());
3338 }
3339 else
3340 {
3341 //printf("not expanded '%s' + @- '%s'\n",qPrint(expr.left(p)),qPrint(expr.mid(p)));
3342 expr=expr.left(p)+"@-"+expr.mid(p);
3343 i=p+l+2;
3344 }
3345 }
3346 else // move to the next macro name
3347 {
3348 //printf(" moving to the next macro old i=%d new i=%d\n",i,p+l);
3349 i=p+l;
3350 }
3351 }
3352 else // move to the next macro name
3353 {
3354 const Define *def=state->expandedDict.find(macroName.str())->second;
3355 // A function-like macro without an opening parenthesis is not an invocation.
3356 if (def->nargs>=0 && !isFunctionMacroCall(yyscanner,expr,rest,p+l))
3357 {
3358 i=p+l;
3359 }
3360 else
3361 {
3362 expr=expr.left(p)+"@-"+expr.mid(p);
3363 i=p+l+2;
3364 }
3365 }
3366 // check for too many inplace expansions without making progress
3367 if (i==startPos)
3368 {
3369 samePosCount++;
3370 }
3371 else
3372 {
3373 startPos=i;
3374 samePosCount=0;
3375 }
3376 if (samePosCount>MAX_EXPANSION_DEPTH)
3377 {
3378 break;
3379 }
3380 }
3381 else // no re-scan marker found, skip the macro name
3382 {
3383 //printf("skipping marked macro\n");
3384 i=p+l;
3385 }
3386 }
3387 //printf("<expandExpression(expr='%s',rest='%s',pos=%d,level=%d)\n",qPrint(expr),rest ? qPrint(*rest) : "", pos,level);
3388 return true;
bool nonRecursive
Definition define.h:44
std::string toStdString(const DString &s)
Definition dstring.h:798
static void addSeparatorsIfNeeded(yyscan_t yyscanner, const DString &expr, DString &resultExpr, DString &restExpr, int pos)
Definition pre.l:3207
static void processConcatOperators(DString &expr)
Definition pre.l:2626
static bool isFunctionMacroCall(yyscan_t yyscanner, const DString &expr, DString *rest, int pos)
Definition pre.l:2784
3389}

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

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

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

3720{
3721 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3722 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
3723 state->prevChar = yyscanner->yytext_r > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ? *(yyscanner->yytext_r-1) : 0;
3724 DString n=name;
3725 state->expanded.clear();
3726 expandExpression(yyscanner,n,nullptr,0,0);
3727 n=removeMarkers(n);
3728 state->prevChar=0;
3729 //printf("expandMacro '%s'->'%s'\n",qPrint(name),qPrint(n));
3730 return n;
const char * name(int level)
Definition latexgen.h:368
3731}

References expandExpression(), and removeMarkers().

◆ expandStandardMacro()

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

Definition at line 3733 of file pre.l.

3734{
3735 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3736 DString resultExpr;
3737 if (name == "__LINE__")
3738 {
3739 return DString().setNum(yyextra->yyLineNr);
3740 }
3741 else if (name == "__FILE__")
3742 {
3743 resultExpr = "\"";
3744 resultExpr += yyextra->fileName;
3745 resultExpr += "\"";
3746 }
3747 else if (name == "__DATE__")
3748 {
3749 resultExpr = "\"";
3750 resultExpr += __DATE__;
3751 resultExpr += "\"";
3752 }
3753 else if (name == "__TIME__")
3754 {
3755 resultExpr = "\"";
3756 resultExpr += __TIME__;
3757 resultExpr += "\"";
3758 }
3759 return resultExpr;
DString & setNum(short n)
Definition dstring.h:552
3760}

References DString::setNum().

Referenced by expandExpression().

◆ expandVAOpt()

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

Definition at line 2815 of file pre.l.

2816{
2817 //printf("expandVAOpt(vaStr=%s,hasOptionalArgs=%d)\n",qPrint(vaStr),hasOptionalArgs);
2818 DString result;
2819 size_t vo=0, vp=0;
2820 result.clear();
2821 size_t vl = vaStr.length();
2822 while ((vo = vaStr.find("__VA_OPT__(",vp))!=DString::npos)
2823 {
2824 bool hasHash = vo>0 && vaStr.at(vo-1)=='#';
2825 if (hasHash)
2826 {
2827 result+=vaStr.mid(vp,vo-vp-1); // don't copy #
2828 result+="\"";
2829 }
2830 else
2831 {
2832 result+=vaStr.mid(vp,vo-vp);
2833 }
2834 size_t ve=vo+11; // skip over '__VA_OPT__(' part
2835 int bc=1;
2836 while (bc>0 && ve<vl)
2837 {
2838 if (vaStr[ve]==')') bc--;
2839 else if (vaStr[ve]=='(') bc++;
2840 ve++;
2841 }
2842 // ve points to end of __VA_OPT__(....)
2843 if (bc==0 && hasOptionalArgs)
2844 {
2845 DString voStr = vaStr.mid(vo+11,ve-vo-12);
2846 //printf("vo=%d ve=%d voStr=%s\n",vo,ve,qPrint(voStr));
2847 result+=voStr; // take 'x' from __VA_OPT__(x)
2848 }
2849 if (hasHash)
2850 {
2851 result+="\"";
2852 }
2853 vp=ve;
2854 }
2855 result+=vaStr.mid(vp);
2856 //printf("vaStr='%s'\n -> '%s'\n",qPrint(vaStr),qPrint(result));
2857 return result;
void clear()
Definition dstring.h:214
2858}

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

Referenced by replaceFunctionMacro().

◆ extractTrailingComment()

DString extractTrailingComment ( const DString & s)
static

Definition at line 2487 of file pre.l.

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

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

◆ extraSpacing()

void extraSpacing ( yyscan_t yyscanner)
inlinestatic

Definition at line 3870 of file pre.l.

3871{
3872 struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
3873 if (!yyextra->defContinue) return;
3874 for (int i=0; i< (int)yyleng; i++)
3875 {
3876 if (yytext[i] == '\t')
3877 yyextra->defExtraSpacing+='\t';
3878 else
3879 yyextra->defExtraSpacing+=' ';
3880 }
3881}

◆ findFile()

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

Definition at line 2413 of file pre.l.

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

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

Referenced by readIncludeFile().

◆ forceEndCondSection()

void forceEndCondSection ( yyscan_t yyscanner)
static

Definition at line 4118 of file pre.l.

4119{
4120 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
4121 while (!state->condStack.empty())
4122 {
4123 state->condStack.pop();
4124 }
4125 state->skip=false;
4126}

Referenced by Preprocessor::processFile().

◆ getCurrentChar()

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

Definition at line 4187 of file pre.l.

4188{
4189 //printf("getCurrentChar(%s,%s,%d)\n",qPrint(expr),rest ? rest->data() : 0,pos);
4190 if (pos<expr.length())
4191 {
4192 //printf("%c=expr()\n",expr.at(pos));
4193 return expr.at(pos);
4194 }
4195 else if (rest && !rest->empty())
4196 {
4197 int cc=rest->at(0);
4198 //printf("%c=rest\n",cc);
4199 return cc;
4200 }
4201 else if (!preYYget_extra(yyscanner)->boundedExpansion)
4202 {
4203 int cc=yyinput(yyscanner);
4204 returnCharToStream(yyscanner,(char)cc);
4205 //printf("%c=yyinput()\n",cc);
4206 return cc;
4207 }
4208 return EOF;
static void returnCharToStream(yyscan_t yyscanner, char c)
Definition pre.l:2712
4209}

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

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

◆ getFenceSize()

yy_size_t getFenceSize ( char * txt,
yy_size_t leng )
static

Definition at line 2269 of file pre.l.

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

◆ getLexerFILE()

const char * getLexerFILE ( )
inlinestatic

Definition at line 360 of file pre.l.

360{return __FILE__;}

◆ getNextChar()

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

Definition at line 4163 of file pre.l.

4164{
4165 //printf("getNextChar(%s,%s,%d)\n",qPrint(expr),rest ? rest->data() : 0,pos);
4166 if (pos<expr.length())
4167 {
4168 //printf(" expr()='%c'\n",expr.at(pos));
4169 return expr.at(pos++);
4170 }
4171 else if (rest && !rest->empty())
4172 {
4173 int cc=rest->at(0);
4174 *rest=rest->right(rest->length()-1);
4175 //printf(" rest='%c'\n",cc);
4176 return cc;
4177 }
4178 else if (!preYYget_extra(yyscanner)->boundedExpansion)
4179 {
4180 int cc=yyinput(yyscanner);
4181 //printf(" yyinput()='%c' %d\n",cc,EOF);
4182 return cc;
4183 }
4184 return EOF;
DString right(size_t len) const
Definition dstring.h:311
4185}

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

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

3152{
3153 int n;
3154 while (p<(int)expr.length())
3155 {
3156 char c=expr.at(p++);
3157 if (isdigit(c)) // skip number
3158 {
3159 while (p<(int)expr.length() && isId(expr.at(p))) p++;
3160 }
3161 else if (isalpha(c) || c=='_') // read id
3162 {
3163 n=p-1;
3164 while (p<(int)expr.length() && isId(expr.at(p))) p++;
3165 *l=p-n;
3166 return n;
3167 }
3168 else if (c=='"') // skip string
3169 {
3170 char ppc=0,pc=c;
3171 if (p<(int)expr.length()) c=expr.at(p);
3172 while (p<(int)expr.length() && (c!='"' || (pc=='\\' && ppc!='\\')))
3173 // continue as long as no " is found, but ignoring \", but not \\"
3174 {
3175 ppc=pc;
3176 pc=c;
3177 c=expr.at(p);
3178 p++;
3179 }
3180 if (p<(int)expr.length()) ++p; // skip closing quote
3181 }
3182 else if (c=='/') // skip C Comment
3183 {
3184 //printf("Found C comment at p=%d\n",p);
3185 char pc=c;
3186 if (p<(int)expr.length())
3187 {
3188 c=expr.at(p);
3189 if (c=='*') // Start of C comment
3190 {
3191 p++;
3192 while (p<(int)expr.length() && !(pc=='*' && c=='/'))
3193 {
3194 pc=c;
3195 c=expr.at(p++);
3196 }
3197 }
3198 }
3199 //printf("Found end of C comment at p=%d\n",p);
3200 }
3201 }
3202 return -1;
bool isId(char c)
Returns true if c is a valid character for an identifier.
Definition dstring.h:895
3203}

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

Referenced by expandExpression().

◆ incrLevel()

void incrLevel ( yyscan_t yyscanner)
static

Definition at line 2307 of file pre.l.

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

◆ initPredefined()

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

Definition at line 4264 of file pre.l.

4265{
4266 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
4267
4268 // add predefined macros
4269 StringVector predefList = Config_getList(PREDEFINED);
4270 for (const auto &ds : predefList)
4271 {
4272 size_t i_equals=ds.find('=');
4273 size_t i_obrace=ds.find('(');
4274 size_t i_cbrace=ds.find(')');
4275 bool nonRecursive = i_equals!=std::string::npos && i_equals>0 && ds[i_equals-1]==':';
4276
4277 if ((i_obrace==0) || (i_equals==0) || (i_equals==1 && ds[i_equals-1]==':'))
4278 {
4279 continue; // no define name
4280 }
4281
4282 if (i_obrace<i_equals && i_cbrace<i_equals &&
4283 i_obrace!=std::string::npos && i_cbrace!=std::string::npos &&
4284 i_obrace<i_cbrace
4285 ) // predefined function macro definition
4286 {
4287 static const reg::Ex reId(R"(\a\w*)");
4288 std::map<std::string,int> argMap;
4289 std::string args = ds.substr(i_obrace+1,i_cbrace-i_obrace-1); // part between ( and )
4290 bool hasVarArgs = args.find("...")!=std::string::npos;
4291 //printf("predefined function macro '%s'\n",qPrint(ds));
4292 int count = 0;
4293 reg::Iterator arg_it(args,reId,0);
4294 reg::Iterator arg_end;
4295 // gather the formal arguments in a dictionary
4296 for (; arg_it!=arg_end; ++arg_it)
4297 {
4298 argMap.emplace(arg_it->str(),count++);
4299 }
4300 if (hasVarArgs) // add the variable argument if present
4301 {
4302 argMap.emplace("__VA_ARGS__",count++);
4303 }
Class representing a regular expression.
Definition regex.h:39
Class to iterate through matches.
Definition regex.h:245
4304
4305 // strip definition part
4306 std::string definition;
4307 std::string in=ds.substr(i_equals+1);
4308 reg::Iterator re_it(in,reId);
4309 reg::Iterator re_end;
4310 size_t i=0;
4311 // substitute all occurrences of formal arguments by their
4312 // corresponding markers
4313 for (; re_it!=re_end; ++re_it)
4314 {
4315 const auto &match = *re_it;
4316 size_t pi = match.position();
4317 size_t l = match.length();
4318 if (pi>i) definition+=in.substr(i,pi-i);
bool match(std::string_view str, Match &match, const Ex &re)
Matches a given string str for a match against regular expression re.
Definition regex.cpp:861
4319
4320 auto it = argMap.find(match.str());
4321 if (it!=argMap.end())
4322 {
4323 int argIndex = it->second;
4324 DString marker;
4325 marker.sprintf(" @%d ",argIndex);
4326 definition+=marker.str();
4327 }
4328 else
4329 {
4330 definition+=match.str();
4331 }
4332 i=pi+l;
4333 }
4334 definition+=in.substr(i);
DString & sprintf(const char *format,...)
Definition dstring.cpp:34
4335
4336 // add define definition to the dictionary of defines for this file
4337 std::string dname = ds.substr(0,i_obrace);
4338 if (!dname.empty())
4339 {
4340 Define def;
4341 def.name = dname;
4342 def.definition = definition;
4343 def.nargs = count;
4344 def.isPredefined = true;
4345 def.nonRecursive = nonRecursive;
4346 def.fileDef = state->yyFileDef;
4347 def.fileName = fileName;
4348 def.varArgs = hasVarArgs;
4349 state->contextDefines.emplace(def.name.str(),def);
4350
4351 //printf("#define '%s' '%s' #nargs=%d hasVarArgs=%d\n",
4352 // qPrint(def.name),qPrint(def.definition),def.nargs,def.varArgs);
4353 }
4354 }
4355 else if (!ds.empty()) // predefined non-function macro definition
4356 {
4357 //printf("predefined normal macro '%s'\n",qPrint(ds));
4358 Define def;
4359 if (i_equals==std::string::npos) // simple define without argument
4360 {
4361 def.name = ds;
4362 def.definition = "1"; // substitute occurrences by 1 (true)
4363 }
4364 else // simple define with argument
4365 {
4366 int ine=static_cast<int>(i_equals) - (nonRecursive ? 1 : 0);
4367 def.name = ds.substr(0,ine);
4368 def.definition = ds.substr(i_equals+1);
4369 }
4370 if (!def.name.empty())
4371 {
4372 def.nargs = -1;
4373 def.isPredefined = true;
4374 def.nonRecursive = nonRecursive;
4375 def.fileDef = state->yyFileDef;
4376 def.fileName = fileName;
4377 state->contextDefines.emplace(def.name.str(),def);
4378 }
4379 }
4380 }
DString substr(size_t pos=0, size_t count=npos) const
Returns a substring of length count starting at pos.
Definition dstring.h:223
4381}

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

Referenced by Preprocessor::processFile().

◆ isDefined()

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

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

Definition at line 4235 of file pre.l.

4236{
4237 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
4238
4239 bool undef = false;
4240 auto findDefine = [&undef,&name](DefineMap &map)
4241 {
4242 Define *d=nullptr;
4243 auto it = map.find(name.str());
4244 if (it!=map.end())
4245 {
4246 d = &it->second;
4247 if (d->undef)
4248 {
4249 undef=true;
4250 d=nullptr;
4251 }
4252 }
4253 return d;
4254 };
bool undef
Definition define.h:41
std::map< std::string, Define > DefineMap
A dictionary of managed Define objects.
Definition pre.l:110
4255
4256 Define *def = findDefine(state->localDefines);
4257 if (def==nullptr && !undef)
4258 {
4259 def = findDefine(state->contextDefines);
4260 }
4261 return def;
4262}

References Define::undef.

Referenced by expandExpression().

◆ isFunctionMacroCall()

bool isFunctionMacroCall ( yyscan_t yyscanner,
const DString & expr,
DString * rest,
int pos )
static

Definition at line 2784 of file pre.l.

2785{
2786 DString remaining=expr.mid(pos);
2787 if (rest) remaining+=*rest;
2788 uint32_t cursor=0;
2789 std::string readAhead;
2790 auto next = [&]() -> int
2791 {
2792 bool fromStream=cursor>=remaining.length() && !preYYget_extra(yyscanner)->boundedExpansion;
2793 int c=getNextChar(yyscanner,remaining,nullptr,cursor);
2794 if (fromStream && c!=EOF && c!=0) readAhead+=static_cast<char>(c);
2795 return c;
2796 };
2797 int c=next();
2798 for (;;)
2799 {
2800 while (c!=EOF && c!=0 && c!='\n' && isspace(static_cast<unsigned char>(c))) c=next();
2801 if (c!='/') break;
2802 c=next();
2803 if (c!='*') break;
2804 int previous=0;
2805 while ((c=next())!=EOF && c!=0 && !(previous=='*' && c=='/')) previous=c;
2806 if (c==EOF || c==0) break;
2807 c=next();
2808 }
2809 // Lookahead must not consume characters from the enclosing scanner.
2810 for (auto it=readAhead.rbegin();it!=readAhead.rend();++it) returnCharToStream(yyscanner,*it);
2811 return c=='(';
2812}

References getNextChar(), DString::length(), DString::mid(), and returnCharToStream().

Referenced by expandExpression().

◆ otherCaseDone()

bool otherCaseDone ( yyscan_t yyscanner)
static

Definition at line 2335 of file pre.l.

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

References warn.

◆ outputArray()

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

Definition at line 3841 of file pre.l.

3842{
3843 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
3844 if (state->includeStack.empty() || state->curlyCount>0) (*state->outputBuf)+=std::string_view(a,len);
3845}

◆ outputChar()

void outputChar ( yyscan_t yyscanner,
char c )
inlinestatic

Definition at line 3835 of file pre.l.

3836{
3837 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
3838 if (state->includeStack.empty() || state->curlyCount>0) (*state->outputBuf)+=c;
3839}

Referenced by outputSpace(), and outputSpaces().

◆ outputSpace()

void outputSpace ( yyscan_t yyscanner,
char c )
inlinestatic

Definition at line 3853 of file pre.l.

3854{
3855 if (c=='\t') outputChar(yyscanner,'\t');
3856 else outputChar(yyscanner,' ');
static void outputChar(yyscan_t yyscanner, char c)
Definition pre.l:3835
3857}

References outputChar().

◆ outputSpaces()

void outputSpaces ( yyscan_t yyscanner,
char * s )
inlinestatic

Definition at line 3859 of file pre.l.

3860{
3861 const char *p=s;
3862 char c = 0;
3863 while ((c=*p++))
3864 {
3865 if (c=='\t') outputChar(yyscanner,'\t');
3866 else outputChar(yyscanner,' ');
3867 }
3868}

References outputChar().

◆ outputString()

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

Definition at line 3847 of file pre.l.

3848{
3849 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
3850 if (state->includeStack.empty() || state->curlyCount>0) (*state->outputBuf)+=a.str();
3851}

References DString::str().

Referenced by readIncludeFile().

◆ processConcatOperators()

void processConcatOperators ( DString & expr)
static

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

Definition at line 2626 of file pre.l.

2627{
2628 if (expr.empty()) return;
2629 //printf("processConcatOperators: in='%s'\n",qPrint(expr));
2630 std::string e = expr.str();
2631 static const reg::Ex r(R"(\s*##\s*)");
DirIterator end(const DirIterator &) noexcept
Definition dir.cpp:181
2633
2634 size_t i=0;
2635 for (;;)
2636 {
2637 reg::Iterator it(e,r,i);
2638 if (it!=end)
2639 {
2640 const auto &match = *it;
2641 size_t n = match.position();
2642 size_t l = match.length();
2643 //printf("Match: '%s'\n",qPrint(expr.mid(i)));
2644 // A pasted placemarker disappears, but must not join neighboring tokens.
2645 bool leftEmpty = n>=2 && e.compare(n-2,2,"@E")==0 && (n<3 || e[n-3]!='@');
2646 bool rightEmpty = e.compare(n+l,2,"@E")==0;
2647 if (leftEmpty && rightEmpty)
2648 {
2649 e.erase(n,l+2);
2650 i=n-2;
2651 continue;
2652 }
2653 if (leftEmpty)
2654 {
2655 if (e.compare(n+l,2,"@-")==0) e.erase(n+l,2);
2656 e.replace(n-2,l+2," ");
2657 i=n-1;
2658 continue;
2659 }
2660 if (rightEmpty)
2661 {
2662 int k=static_cast<int>(n)-1;
2663 while (k>=0 && isId(e[k])) k--;
2664 if (k>0 && e[k]=='-' && e[k-1]=='@')
2665 {
2666 e.erase(k-1,2);
2667 n-=2;
2668 }
2669 size_t next=e.find_first_not_of(" \t\r\n",n+l+2);
2670 if (next!=std::string::npos && e.compare(next,2,"##")==0)
2671 {
2672 // Keep the remaining paste operator for chains such as a##empty##b.
2673 e.erase(n,l+2);
2674 i=n;
2675 }
2676 else
2677 {
2678 e.replace(n,l+2," ");
2679 i=n+1;
2680 }
2681 continue;
2682 }
2683 if (n+l+1<e.length() && e[static_cast<int>(n+l)]=='@' && expr[static_cast<int>(n+l+1)]=='-')
2684 {
2685 // remove no-rescan marker after ID
2686 l+=2;
2687 }
2688 //printf("found '%s'\n",qPrint(expr.mid(n,l)));
2689 // remove the ## operator and the surrounding whitespace
2690 e=e.substr(0,n)+e.substr(n+l);
2691 int k=static_cast<int>(n)-1;
2692 while (k>=0 && isId(e[k])) k--;
2693 if (k>0 && e[k]=='-' && e[k-1]=='@')
2694 {
2695 // remove no-rescan marker before ID
2696 e=e.substr(0,k-1)+e.substr(k+1);
2697 n-=2;
2698 }
2699 i=n;
2700 }
2701 else
2702 {
2703 break;
2704 }
2705 }
2706
2707 expr = e;
2708
2709 //printf("processConcatOperators: out='%s'\n",qPrint(expr));
2710}

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

Referenced by expandExpression().

◆ processUntilMatchingTerminator()

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

Process string or character literal.

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

Definition at line 3397 of file pre.l.

3398{
3399 if (inputStr==nullptr) return inputStr;
3400 char term = *inputStr; // capture start character of the literal
3401 if (term!='\'' && term!='"') return inputStr; // not a valid literal
3402 char c=term;
3403 // output start character
3404 result+=c;
3405 inputStr++;
3406 while ((c=*inputStr)) // while inside the literal
3407 {
3408 if (c==term) // found end marker of the literal
3409 {
3410 // output end character and stop
3411 result+=c;
3412 inputStr++;
3413 break;
3414 }
3415 else if (c=='\\') // escaped character, process next character
3416 // as well without checking for end marker.
3417 {
3418 result+=c;
3419 inputStr++;
3420 c=*inputStr;
3421 if (c==0) break; // unexpected end of string after escape character
3422 }
3423 result+=c;
3424 inputStr++;
3425 }
3426 return inputStr;
3427}

References term.

Referenced by removeIdsAndMarkers(), and removeMarkers().

◆ readIncludeFile()

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

Definition at line 3916 of file pre.l.

3917{
3918 AUTO_TRACE("inc={}",inc);
3919 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
3920 uint32_t i=0;
#define AUTO_TRACE(...)
Definition docnode.cpp:53
3921
3922 // find the start of the include file name
3923 while (i<inc.length() &&
3924 (inc.at(i)==' ' || inc.at(i)=='"' || inc.at(i)=='<')
3925 ) i++;
3926 uint32_t s=i;
3927
3928 // was it a local include?
3929 bool localInclude = s>0 && inc.at(s-1)=='"';
3930
3931 // find the end of the include file name
3932 while (i<inc.length() && inc.at(i)!='"' && inc.at(i)!='>') i++;
3933
3934 if (s<inc.length() && i>s) // valid include file name found
3935 {
3936 // extract include path+name
3937 DString incFileName=inc.mid(s,i-s).stripWhiteSpace();
3938 if (incFileName.endsWith(".exe") || incFileName.endsWith(".dll") || incFileName.endsWith(".tlb"))
3939 {
3940 // skip imported binary files (e.g. M$ type libraries)
3941 return;
3942 }
bool endsWith(const char *s) const
Definition dstring.h:617
3943
3944 DString oldFileName = state->fileName;
3945 FileDef *oldFileDef = state->yyFileDef;
3946 int oldLineNr = state->yyLineNr;
3947 //printf("Searching for '%s'\n",qPrint(incFileName));
3948
3949 DString absIncFileName = determineAbsoluteIncludeName(state->fileName,incFileName);
DString determineAbsoluteIncludeName(const DString &curFile, const DString &incFileName)
Definition util.cpp:2935
3950
3951 // findFile will overwrite state->yyFileDef if found
3952 std::unique_ptr<FileState> fs;
3953 bool alreadyProcessed = false;
3954 //printf("calling findFile(%s)\n",qPrint(incFileName));
3955 fs=findFile(yyscanner,absIncFileName,localInclude,alreadyProcessed); // see if the absolute include file can be found
3956 if (fs)
3957 {
3958 {
3959 std::lock_guard<std::mutex> lock(g_globalDefineMutex);
3960 g_defineManager.addInclude(oldFileName.str(),absIncFileName.str());
3961 }
void addInclude(const std::string &fromFileName, const std::string &toFileName)
Definition pre.l:174
static std::unique_ptr< FileState > findFile(yyscan_t yyscanner, const DString &fileName, bool localInclude, bool &alreadyProcessed)
Definition pre.l:2413
3962
3963 //printf("Found include file!\n");
3965 {
3966 for (i=0;i<state->includeStack.size();i++)
3967 {
3969 }
3970 Debug::print(Debug::Preprocessor,0,"#include {}: parsing...\n",incFileName);
3971 }
@ Preprocessor
Definition debug.h:31
static bool isFlagSet(const DebugMask mask)
Definition debug.cpp:132
static void print(DebugMask mask, int prio, fmt::format_string< Args... > fmt, Args &&... args)
Definition debug.h:78
3972
3973 if (state->includeStack.empty() && oldFileDef)
3974 {
3975 PreIncludeInfo *ii = state->includeRelations.find(absIncFileName);
3976 if (ii==nullptr)
3977 {
3978 bool ambig = false;
3979 FileDef *incFd = Doxygen::inputNameLinkedMap->findFileDef(absIncFileName,ambig);
3980 state->includeRelations.add(
3981 absIncFileName,
3982 oldFileDef,
3983 ambig ? nullptr : incFd,
3984 incFileName,
3985 localInclude,
3986 state->isImported
3987 );
3988 }
3989 }
3990
3991 struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
3992 fs->bufState = YY_CURRENT_BUFFER;
3993 fs->lineNr = oldLineNr;
3994 fs->fileName = oldFileName;
3995 fs->curlyCount = state->curlyCount;
3996 //state->curlyCount = 0; // don't reset counter, see issue #10997
3997 fs->lexRulesPart = state->lexRulesPart;
3998 fs->levelGuard = state->levelGuard;
3999 while (!state->levelGuard.empty()) state->levelGuard.pop();
4000 state->lexRulesPart = false;
4001 // push the state on the stack
4002 FileState *fs_ptr = fs.get();
4003 state->includeStack.push_back(std::move(fs));
4004 // set the scanner to the include file
4005
4006 // Deal with file changes due to
4007 // #include's within { .. } blocks
4008 DString lineStr(state->fileName.length()+20, DString::ExplicitSize);
4009 lineStr.sprintf("# 1 \"%s\" 1\n",qPrint(state->fileName));
4010 outputString(yyscanner,lineStr);
@ ExplicitSize
Definition dstring.h:131
const char * qPrint(const char *s)
Definition dstring.h:783
static void outputString(yyscan_t yyscanner, const DString &s)
Definition pre.l:3847
4011
4012 AUTO_TRACE_ADD("Switching to include file {}",incFileName);
4013 state->expectGuard=true;
4014 state->inputBuf = &fs_ptr->fileBuf;
4015 state->inputBufPos=0;
4016 yy_switch_to_buffer(yy_create_buffer(0, YY_BUF_SIZE, yyscanner),yyscanner);
4017 }
4018 else
4019 {
4020 if (alreadyProcessed) // if this header was already process we can just copy the stored macros
4021 // in the local context
4022 {
4023 std::lock_guard<std::mutex> lock(g_globalDefineMutex);
4024 g_defineManager.addInclude(state->fileName.str(),absIncFileName.str());
4025 g_defineManager.retrieve(absIncFileName.str(),state->contextDefines);
4026 }
void retrieve(const std::string &fileName, DefineMap &toMap)
Definition pre.l:197
#define YY_BUF_SIZE
Definition commentcnv.l:19
#define AUTO_TRACE_ADD(...)
Definition docnode.cpp:54
std::string fileBuf
Definition pre.l:86
4027
4028 if (state->includeStack.empty() && oldFileDef)
4029 {
4030 PreIncludeInfo *ii = state->includeRelations.find(absIncFileName);
4031 if (ii==nullptr)
4032 {
4033 bool ambig = false;
4034 FileDef *incFd = Doxygen::inputNameLinkedMap->findFileDef(absIncFileName,ambig);
4035 ii = state->includeRelations.add(absIncFileName,
4036 oldFileDef,
4037 ambig ? nullptr : incFd,
4038 incFileName,
4039 localInclude,
4040 state->isImported
4041 );
4042 }
4043 }
4044
4046 {
4047 for (i=0;i<state->includeStack.size();i++)
4048 {
4050 }
4051 if (alreadyProcessed)
4052 {
4053 Debug::print(Debug::Preprocessor,0,"#include {}: already processed! skipping...\n",incFileName);
4054 }
4055 else
4056 {
4057 Debug::print(Debug::Preprocessor,0,"#include {}: not found! skipping...\n",incFileName);
4058 }
4059 //printf("error: include file %s not found\n",yytext);
4060 }
4061 if (localInclude && !state->includeStack.empty() && state->curlyCount>0 && !alreadyProcessed) // failed to find #include inside { ... }
4062 {
4063 warn(state->fileName,state->yyLineNr,"include file {} not found, perhaps you forgot to add its directory to INCLUDE_PATH?",incFileName);
4064 }
4065 }
4066 }
4067}

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

◆ removeIdsAndMarkers()

DString removeIdsAndMarkers ( const DString & s)
static

replaces all occurrences of @@ in s by @ and replaces empty-argument markers with spaces. All identifiers found are replaced by 0L

Definition at line 3433 of file pre.l.

3434{
3435 static const std::vector<std::string> signs = { "signed", "unsigned" };
3436 struct TypeInfo { std::string name; size_t size; };
3437 static const std::vector<TypeInfo> types = {
3438 { "short int", sizeof(short int) },
3439 { "long long int", sizeof(long long int) },
3440 { "long int", sizeof(long int) },
3441 { "long long", sizeof(long long) },
3442 { "long double", sizeof(long double) },
3443 { "int", sizeof(int) },
3444 { "short", sizeof(short) },
3445 { "bool", sizeof(bool) },
3446 { "long", sizeof(long) },
3447 { "char", sizeof(char) },
3448 { "float", sizeof(float) },
3449 { "double", sizeof(double) },
3450 };
3451
3452 // Check if string p starts with basic types ending with a ')', such as 'signed long)' or ' float )'
3453 // and return the pointer just past the ')' and the size of the type as a tuple.
3454 // If the pattern is not found the tuple (nullptr,0) is returned.
3455 auto process_cast_or_sizeof = [](const char *p) -> std::pair<const char *,size_t>
3456 {
3457 const char *q = p;
3458 while (*q==' ' || *q=='\t') q++;
3459 bool found=false;
3460 size_t size = sizeof(int); // '(signed)' or '(unsigned)' is an int type
3461 for (const auto &sgn : signs)
3462 {
3463 if (dstrncmp(q,sgn.c_str(),sgn.length())==0) { q+=sgn.length(); found=true; }
3464 }
3465 if (!found || *q==' ' || *q=='\t' || *q==')') // continue searching
3466 {
3467 while (*q==' ' || *q=='\t') q++;
3468 for (const auto &t : types)
3469 {
3470 if (dstrncmp(q,t.name.c_str(),t.name.length())==0)
3471 {
3472 q += t.name.length();
3473 size = t.size;
3474 break;
3475 }
3476 }
3477 while (*q==' ' || *q=='\t') q++;
3478 if (*q==')') return std::make_pair(++q,size);
3479 }
3480 return std::make_pair(nullptr,0);
3481 };
int dstrncmp(const char *str1, const char *str2, size_t len)
Definition dstring.h:56
3482
3483 //printf("removeIdsAndMarkers(%s)\n",qPrint(s));
3484 if (s.empty()) return s;
3485 const char *p=s.data();
3486 bool inNum=false;
3487 DString result;
3488 if (p)
3489 {
3490 char c = 0;
3491 while ((c=*p))
3492 {
3493 if (c=='(') // potential cast, ignore it
3494 {
3495 const char *q = process_cast_or_sizeof(p+1).first;
3496 //printf("potential cast:\nin: %s\nout: %s\n",p,q);
3497 if (q)
3498 {
3499 p=q;
3500 continue;
3501 }
3502 }
3503 else if (c=='s' && literal_at(p,"sizeof")) // sizeof(...)
3504 {
3505 const char *q = p+6;
3506 while (*q==' ' || *q=='\t') q++;
3507 if (*q=='(')
3508 {
3509 auto r = process_cast_or_sizeof(q+1);
3510 //printf("sizeof:\nin: %s\nout: %zu%s\n--> sizeof=%zu\n",p,r.second,r.first,r.second);
3511 if (r.first)
3512 {
3513 result+=DString().setNum(r.second);
3514 p=r.first;
3515 continue;
3516 }
3517 }
3518 }
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
3519
3520 if (c=='@') // replace @@ with @ and remove @E
3521 {
3522 if (*(p+1)=='@')
3523 {
3524 result+=c;
3525 }
3526 else if (*(p+1)=='E')
3527 {
3528 result+=' ';
3529 }
3530 p+=2;
3531 }
3532 else if (isdigit(c)) // number
3533 {
3534 result+=c;
3535 p++;
3536 inNum=true;
3537 }
3538 else if (c=='\'') // quoted character
3539 {
3540 p = processUntilMatchingTerminator(p,result);
3541 }
3542 else if (c=='d' && !inNum) // identifier starting with a 'd'
3543 {
3544 if (literal_at(p,"defined ") || literal_at(p,"defined("))
3545 // defined keyword
3546 {
3547 p+=7; // skip defined
3548 }
3549 else
3550 {
3551 result+="0L";
3552 p++;
3553 while ((c=*p) && isId(c)) p++;
3554 }
3555 }
3556 else if ((isalpha(c) || c=='_') && !inNum) // replace identifier with 0L
3557 {
3558 result+="0L";
3559 p++;
3560 while ((c=*p) && isId(c)) p++;
3561 while ((c=*p) && isspace((uint8_t)c)) p++;
3562 if (*p=='(') // undefined function macro
3563 {
3564 p++;
3565 int count=1;
3566 while ((c=*p++))
3567 {
3568 if (c=='(') count++;
3569 else if (c==')')
3570 {
3571 count--;
3572 if (count==0) break;
3573 }
3574 else if (c=='/')
3575 {
3576 char pc=c;
3577 c=*++p;
3578 if (c=='*') // start of C comment
3579 {
3580 while (*p && !(pc=='*' && c=='/')) // search end of comment
3581 {
3582 pc=c;
3583 c=*++p;
3584 }
3585 p++;
3586 }
3587 }
3588 }
3589 }
3590 }
3591 else if (c=='/') // skip C comments
3592 {
3593 char pc=c;
3594 c=*++p;
3595 if (c=='*') // start of C comment
3596 {
3597 while (*p && !(pc=='*' && c=='/')) // search end of comment
3598 {
3599 pc=c;
3600 c=*++p;
3601 }
3602 p++;
3603 }
3604 else // oops, not comment but division
3605 {
3606 result+=pc;
3607 goto nextChar;
3608 }
3609 }
3610 else
3611 {
static const char * processUntilMatchingTerminator(const char *inputStr, DString &result)
Process string or character literal.
Definition pre.l:3397
3612nextChar:
3613 result+=c;
3614 char lc=(char)tolower(c);
3615 if (!isId(lc) && lc!='.' /*&& lc!='-' && lc!='+'*/) inNum=false;
3616 p++;
3617 }
3618 }
3619 }
3620 //printf("removeIdsAndMarkers(%s)=%s\n",s,qPrint(result));
3621 return result;
3622}

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

Referenced by computeExpression().

◆ removeMarkers()

DString removeMarkers ( const DString & s)
static

Replaces escaped @ characters and removes internal expansion markers.

Definition at line 3625 of file pre.l.

3626{
3627 if (s.empty()) return s;
3628 const char *p=s.data();
3629 DString result;
3630 if (p)
3631 {
3632 char c = 0;
3633 while ((c=*p))
3634 {
3635 switch(c)
3636 {
3637 case '@': // replace @@ with @
3638 {
3639 if (*(p+1)=='@')
3640 {
3641 result+=c;
3642 }
3643 else if (*(p+1)=='E')
3644 {
3645 result+=' ';
3646 }
3647 p+=2;
3648 }
3649 break;
3650 case '/': // skip C comments
3651 {
3652 result+=c;
3653 char pc=c;
3654 c=*++p;
3655 if (c=='*') // start of C comment
3656 {
3657 while (*p && !(pc=='*' && c=='/')) // search end of comment
3658 {
3659 if (*p=='@' && *(p+1)=='@')
3660 {
3661 result+=c;
3662 p++;
3663 }
3664 else
3665 {
3666 result+=c;
3667 }
3668 pc=c;
3669 c=*++p;
3670 }
3671 if (*p)
3672 {
3673 result+=c;
3674 p++;
3675 }
3676 }
3677 }
3678 break;
3679 case '"': // skip string literals
3680 case '\'': // skip char literals
3681 p = processUntilMatchingTerminator(p,result);
3682 break;
3683 default:
3684 {
3685 result+=c;
3686 p++;
3687 }
3688 break;
3689 }
3690 }
3691 }
3692 //printf("RemoveMarkers(%s)=%s\n",s,qPrint(result));
3693 return result;
3694}

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

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

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

2868{
2869 //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());
2870 uint32_t j=pos;
2871 len=0;
2872 result.clear();
2873 int cc;
2874
2875 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:2753
2876
2877 if (cc!='(')
2878 {
2879 if (cc!=':') // don't add spaces for colons
2880 {
2881 unputChar(yyscanner,expr,rest,j,' ');
2882 }
2883 return false;
2884 }
2885 getNextChar(yyscanner,expr,rest,j); // eat the '(' character
2886
2887 struct MacroArgument
2888 {
2889 DString raw;
2890 DString expanded;
2891 };
2892 std::map<std::string,MacroArgument> argTable;
2893 DString arg;
2894 DString rawArg;
2895 // The variadic argument may contain an already-expanded prefix.
2896 size_t expandedPrefixLength=0;
2897 int argCount=0;
2898 int argCountNonEmpty=0;
2899 bool done=false;
2900
2901 // PHASE 1: read the macro arguments
2902 if (def->nargs==0)
2903 {
2904 while ((cc=getNextChar(yyscanner,expr,rest,j))!=EOF && cc!=0)
2905 {
2906 char c = (char)cc;
2907 if (c==')') break;
2908 }
2909 }
2910 else
2911 {
2912 while (!done && (argCount<def->nargs || def->varArgs) &&
2913 ((cc=getNextChar(yyscanner,expr,rest,j))!=EOF && cc!=0)
2914 )
2915 {
2916 char c=(char)cc;
2917 if (c=='(') // argument is a function => search for matching )
2918 {
2919 int lvl=1;
2920 arg+=c;
2921 //char term='\0';
2922 while ((cc=getNextChar(yyscanner,expr,rest,j))!=EOF && cc!=0)
2923 {
2924 c=(char)cc;
2925 //printf("processing %c: term=%c (%d)\n",c,term,term);
2926 if (c=='\'' || c=='\"') // skip ('s and )'s inside strings
2927 {
2928 arg+=c;
2929 addTillEndOfString(yyscanner,expr,rest,j,c,arg);
2930 }
2931 else if (c=='/')
2932 {
2933 int nxtChar = getCurrentChar(yyscanner,expr,rest,j);
2934 if (nxtChar == '*')
2935 {
2936 arg+=c;
2937 addTillEndOfComment(yyscanner,expr,rest,j,c,arg);
2938 }
2939 // We don't need to handle the // case as this has already been converted into a /* .. */ comment.
2940 }
static void addTillEndOfComment(yyscan_t yyscanner, const DString &expr, DString *rest, uint32_t &pos, char term, DString &arg)
Definition pre.l:2737
static void addTillEndOfString(yyscan_t yyscanner, const DString &expr, DString *rest, uint32_t &pos, char term, DString &arg)
Definition pre.l:2718
2941
2942 if (c==')')
2943 {
2944 lvl--;
2945 arg+=c;
2946 if (lvl==0) break;
2947 }
2948 else if (c=='(')
2949 {
2950 lvl++;
2951 arg+=c;
2952 }
2953 else
2954 {
2955 arg+=c;
2956 }
2957 }
2958 }
2959 else if (c==')' || c==',') // last or next argument found
2960 {
2961 if (c==',' && argCount==def->nargs-1 && def->varArgs)
2962 {
2963 rawArg+=arg.mid(expandedPrefixLength);
2964 rawArg+=',';
2965 expandArgument(yyscanner,arg,level+1);
2966 arg=arg.stripWhiteSpace();
2967 arg+=',';
2968 expandedPrefixLength=arg.length();
2969 }
2970 else
2971 {
2972 rawArg+=arg.mid(expandedPrefixLength);
2973 rawArg=rawArg.stripWhiteSpace();
2974 DString expandedArg=arg;
2975 expandArgument(yyscanner,expandedArg,level+1);
2976 expandedArg=expandedArg.stripWhiteSpace();
2977 DString argKey;
2978 argKey.sprintf("@%d",argCount++); // key name
2979 if (c==',' || !expandedArg.empty()) argCountNonEmpty++;
2980 // add argument to the lookup table
2981 argTable.emplace(toStdString(argKey), MacroArgument{rawArg,expandedArg});
2982 arg.clear();
2983 rawArg.clear();
2984 expandedPrefixLength=0;
2985 if (c==')') // end of the argument list
2986 {
2987 done=true;
2988 }
2989 }
2990 }
2991 else if (c=='\"') // append literal strings
2992 {
2993 arg+=c;
2994 bool found=false;
2995 while (!found && (cc=getNextChar(yyscanner,expr,rest,j))!=EOF && cc!=0)
2996 {
2997 found = cc=='"';
2998 if (cc=='\\')
2999 {
3000 c=(char)cc;
3001 arg+=c;
3002 if ((cc=getNextChar(yyscanner,expr,rest,j))==EOF || cc==0) break;
3003 }
3004 c=(char)cc;
3005 arg+=c;
3006 }
3007 }
3008 else if (c=='\'') // append literal characters
3009 {
3010 arg+=c;
3011 bool found=false;
3012 while (!found && (cc=getNextChar(yyscanner,expr,rest,j))!=EOF && cc!=0)
3013 {
3014 found = cc=='\'';
3015 if (cc=='\\')
3016 {
3017 c=(char)cc;
3018 arg+=c;
3019 if ((cc=getNextChar(yyscanner,expr,rest,j))==EOF || cc==0) break;
3020 }
3021 c=(char)cc;
3022 arg+=c;
3023 }
3024 }
3025 else if (c=='/') // possible start of a comment
3026 {
3027 char prevChar = '\0';
3028 arg+=c;
3029 if ((cc=getCurrentChar(yyscanner,expr,rest,j)) == '*') // we have a comment
3030 {
3031 while ((cc=getNextChar(yyscanner,expr,rest,j))!=EOF && cc!=0)
3032 {
3033 c=(char)cc;
3034 arg+=c;
3035 if (c == '/' && prevChar == '*') break; // we have an end of comment
3036 prevChar = c;
3037 }
3038 }
3039 }
3040 else // append other characters
3041 {
3042 arg+=c;
3043 }
3044 }
3045 }
static void expandArgument(yyscan_t yyscanner, DString &arg, int level)
Definition pre.l:2538
3046
3047 // PHASE 2: apply the macro function
3048 if (argCount==def->nargs || // same number of arguments
3049 (argCount>=def->nargs-1 && def->varArgs)) // variadic macro with at least as many
3050 // params as the non-variadic part (see bug731985)
3051 {
3052 size_t k=0;
3053 // substitution of all formal arguments
3054 DString resExpr;
3056 //printf("varArgs=%d argCount=%d def->nargs=%d d=%s\n",def->varArgs,argCount,def->nargs,qPrint(d));
3057 if (def->varArgs) d = expandVAOpt(d,argCountNonEmpty!=def->nargs-1);
3058 //printf("Macro definition: '%s'\n",qPrint(d));
3059 bool inString=false;
3060 while (k<d.length())
3061 {
3062 if (d.at(k)=='@') // maybe a marker, otherwise an escaped @
3063 {
3064 if (d.at(k+1)=='@') // escaped @ => copy it (is unescaped later)
3065 {
3066 k+=2;
3067 resExpr+="@@"; // we unescape these later
3068 }
3069 else if (d.at(k+1)=='-') // no-rescan marker
3070 {
3071 k+=2;
3072 resExpr+="@-";
3073 }
3074 else // argument marker => read the argument number
3075 {
3076 DString key="@";
3077 bool hash=false;
3078 int l=static_cast<int>(k)-1;
3079 // search for ## backward
3080 if (l>=0 && d.at(l)=='"') l--;
3081 while (l>=0 && d.at(l)==' ') l--;
3082 if (l>0 && d.at(l)=='#' && d.at(l-1)=='#') hash=true;
3083 k++;
3084 // scan the number
3085 while (k<d.length() && d.at(k)>='0' && d.at(k)<='9') key+=d.at(k++);
3086 if (!hash)
3087 {
3088 // search for ## forward
3089 l=static_cast<int>(k);
3090 if (l<(int)d.length() && d.at(l)=='"') l++;
3091 while (l<(int)d.length() && d.at(l)==' ') l++;
3092 if (l<(int)d.length()-1 && d.at(l)=='#' && d.at(l+1)=='#') hash=true;
3093 }
3094 //printf("request key %s result %s\n",qPrint(key),argTable[key]->data());
3095 auto it = argTable.find(key.str());
3096 if (it!=argTable.end())
3097 {
3098 DString substArg = hash || inString ? it->second.raw : it->second.expanded;
3099 //printf("substArg='%s'\n",qPrint(substArg));
3100 // Stringified and pasted arguments are substituted without prescan.
3101 if (!hash && !inString)
3102 {
3103 expandArgument(yyscanner,substArg,level+1);
3104 }
3105 if (inString)
3106 {
3107 //printf("'%s'=stringize('%s')\n",qPrint(stringize(*subst)),subst->data());
static DString expandVAOpt(const DString &vaStr, bool hasOptionalArgs)
Definition pre.l:2815
3108
3109 // if the marker is inside a string (because a # was put
3110 // before the macro name) we must escape " and \ characters
3111 resExpr+=stringize(removeMarkers(substArg));
3112 }
3113 else
3114 {
3115 if (hash && substArg.empty())
3116 {
3117 resExpr+="@E"; // placemarker for an empty argument next to ##
3118 }
3119 resExpr+=substArg;
3120 }
3121 }
3122 }
3123 }
3124 else // no marker, just copy
3125 {
3126 if (!inString && d.at(k)=='\"')
3127 {
3128 inString=true; // entering a literal string
3129 }
3130 else if (k>2 && inString && d.at(k)=='\"' && (d.at(k-1)!='\\' || d.at(k-2)=='\\'))
3131 {
3132 inString=false; // leaving a literal string
3133 }
3134 resExpr+=d.at(k++);
3135 }
3136 }
3137 len=j-pos;
3138 result=resExpr;
3139 //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());
3140 return true;
3141 }
3142 //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());
3143 return false;
static DString stringize(const DString &s)
Definition pre.l:2548
3144}

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

Referenced by expandExpression().

◆ resolveTrigraph()

char resolveTrigraph ( char c)
static

Definition at line 4143 of file pre.l.

4144{
4145 switch (c)
4146 {
4147 case '=': return '#';
4148 case '/': return '\\';
4149 case '\'': return '^';
4150 case '(': return '[';
4151 case ')': return ']';
4152 case '!': return '|';
4153 case '<': return '{';
4154 case '>': return '}';
4155 case '-': return '~';
4156 }
4157 return '?';
4158}

◆ returnCharToStream()

void returnCharToStream ( yyscan_t yyscanner,
char c )
static

Definition at line 2712 of file pre.l.

2713{
2714 struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
2715 unput(c);
2716}

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

◆ setCaseDone()

void setCaseDone ( yyscan_t yyscanner,
bool value )
static

Definition at line 2349 of file pre.l.

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

◆ setFileName()

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

Definition at line 2280 of file pre.l.

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

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

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

2755{
2756 bool changed = false;
2757
2758 do
2759 {
2760 changed = false;
2761 while ((cc=getCurrentChar(yyscanner,expr,rest,j))!=EOF && cc!='\n' && isspace(cc))
2762 {
2763 len++;
2764 getNextChar(yyscanner,expr,rest,j);
2765 }
2766
2767 if (cc=='/') // possible start of a comment
2768 {
2769 int prevChar = '\0';
2770 getNextChar(yyscanner,expr,rest,j);
2771 if ((cc=getCurrentChar(yyscanner,expr,rest,j))!=EOF && cc == '*') // we have a comment
2772 {
2773 while ((cc=getNextChar(yyscanner,expr,rest,j))!=EOF && cc!=0)
2774 {
2775 if (cc == '/' && prevChar == '*') break; // we have an end of comment
2776 prevChar = cc;
2777 }
2778 if (cc != EOF) changed = true;
2779 }
2780 }
2781 } while (changed);
2782}

References getCurrentChar(), and getNextChar().

Referenced by replaceFunctionMacro().

◆ startCondSection()

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

Definition at line 4071 of file pre.l.

4072{
4073 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
4074 //printf("startCondSection: skip=%d stack=%d\n",state->skip,state->condStack.size());
4075 CondParser prs;
4076 bool expResult = prs.parse(state->fileName.data(),state->yyLineNr,sectId.data());
4077 state->condStack.emplace(std::make_unique<preYY_CondCtx>(state->fileName,state->yyLineNr,sectId,state->skip));
4078 if (!expResult)
4079 {
4080 state->skip=true;
4081 }
4082 //printf(" expResult=%d skip=%d\n",expResult,state->skip);
Copyright (C) 1997-2026 by Dimitri van Heesch.
Definition condparser.h:29
bool parse(const DString &fileName, int lineNr, const DString &expr)
parses and evaluates the given expression.
4083}

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

◆ stateToString()

const char * stateToString ( int state)
static

◆ stringize()

DString stringize ( const DString & s)
static

Definition at line 2548 of file pre.l.

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

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

Referenced by replaceFunctionMacro().

◆ unputChar()

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

Definition at line 4211 of file pre.l.

4212{
4213 //printf("unputChar(%s,%s,%d,%c)\n",qPrint(expr),rest ? rest->data() : 0,pos,c);
4214 if (pos<expr.length())
4215 {
4216 pos++;
4217 }
4218 else if (rest)
4219 {
4220 //printf(" prepending '%c' to rest!\n",c);
4221 char cs[2];cs[0]=c;cs[1]='\0';
4222 rest->prepend(cs);
4223 }
4224 else if (!preYYget_extra(yyscanner)->boundedExpansion)
4225 {
4226 //printf(" yyunput()='%c'\n",c);
4227 returnCharToStream(yyscanner,c);
4228 }
4229 //printf("result: unputChar(%s,%s,%d,%c)\n",qPrint(expr),rest ? rest->data() : 0,pos,c);
DString & prepend(const char *s)
Definition dstring.h:515
4230}

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

Referenced by addSeparatorsIfNeeded(), and replaceFunctionMacro().

◆ yylex()

int yylex ( yyscan_t yyscanner)

Definition at line 494 of file pre.l.

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

◆ yyread()

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

Definition at line 2259 of file pre.l.

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

Variable Documentation

◆ g_debugMutex

std::mutex g_debugMutex
static

Definition at line 234 of file pre.l.

Referenced by Preprocessor::processFile().

◆ g_defineManager

DefineManager g_defineManager
static

Definition at line 237 of file pre.l.

Referenced by checkAndOpenFile(), and readIncludeFile().

◆ g_globalDefineMutex

std::mutex g_globalDefineMutex
static

Definition at line 235 of file pre.l.

Referenced by checkAndOpenFile(), and readIncludeFile().

◆ g_updateGlobals

std::mutex g_updateGlobals
static

Definition at line 236 of file pre.l.

Referenced by Preprocessor::processFile().