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

Go to the source code of this file.

Classes

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

Macros

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

Typedefs

typedef yyguts_t * yyscan_t
typedef std::map< std::string, DefineDefineMap
 A dictionary of managed Define objects.

Functions

static const char * stateToString (int state)
static QCString escapeAt (const QCString &text)
static QCString extractTrailingComment (const QCString &s)
static char resolveTrigraph (char c)
static void outputArray (yyscan_t yyscanner, const char *a, yy_size_t len)
static void outputString (yyscan_t yyscanner, const QCString &s)
static void outputChar (yyscan_t yyscanner, char c)
static void outputSpaces (yyscan_t yyscanner, char *s)
static void outputSpace (yyscan_t yyscanner, char c)
static void extraSpacing (yyscan_t yyscanner)
static QCString expandMacro (yyscan_t yyscanner, const QCString &name)
static void readIncludeFile (yyscan_t yyscanner, const QCString &inc)
static void incrLevel (yyscan_t yyscanner)
static void decrLevel (yyscan_t yyscanner)
static void setCaseDone (yyscan_t yyscanner, bool value)
static bool otherCaseDone (yyscan_t yyscanner)
static bool computeExpression (yyscan_t yyscanner, const QCString &expr)
static void startCondSection (yyscan_t yyscanner, const QCString &sectId)
static void endCondSection (yyscan_t yyscanner)
static void addMacroDefinition (yyscan_t yyscanner)
static void addDefine (yyscan_t yyscanner)
static void setFileName (yyscan_t yyscanner, const QCString &name)
static int yyread (yyscan_t yyscanner, char *buf, int max_size)
static DefineisDefined (yyscan_t yyscanner, const QCString &name)
 Returns a reference to a Define object given its name or 0 if the Define does not exist.
static void determineBlockName (yyscan_t yyscanner)
static yy_size_t getFenceSize (char *txt, yy_size_t leng)
static const char * getLexerFILE ()
int yylex (yyscan_t yyscanner)
static std::unique_ptr< FileStatecheckAndOpenFile (yyscan_t yyscanner, const QCString &fileName, bool &alreadyProcessed)
static std::unique_ptr< FileStatefindFile (yyscan_t yyscanner, const QCString &fileName, bool localInclude, bool &alreadyProcessed)
static int getNextChar (yyscan_t yyscanner, const QCString &expr, QCString *rest, uint32_t &pos)
static int getCurrentChar (yyscan_t yyscanner, const QCString &expr, QCString *rest, uint32_t pos)
static void unputChar (yyscan_t yyscanner, const QCString &expr, QCString *rest, uint32_t &pos, char c)
static bool expandExpression (yyscan_t yyscanner, QCString &expr, QCString *rest, int pos, int level)
static QCString stringize (const QCString &s)
static void processConcatOperators (QCString &expr)
static void returnCharToStream (yyscan_t yyscanner, char c)
static void addTillEndOfString (yyscan_t yyscanner, const QCString &expr, QCString *rest, uint32_t &pos, char term, QCString &arg)
static void skipCommentMacroName (yyscan_t yyscanner, const QCString &expr, QCString *rest, int &cc, uint32_t &j, int &len)
static QCString expandVAOpt (const QCString &vaStr, bool hasOptionalArgs)
static bool replaceFunctionMacro (yyscan_t yyscanner, const QCString &expr, QCString *rest, int pos, int &len, const Define *def, QCString &result, int level)
static int getNextId (const QCString &expr, int p, int *l)
static void addSeparatorsIfNeeded (yyscan_t yyscanner, const QCString &expr, QCString &resultExpr, QCString &restExpr, int pos)
static const char * processUntilMatchingTerminator (const char *inputStr, QCString &result)
 Process string or character literal.
static QCString removeIdsAndMarkers (const QCString &s)
static QCString removeMarkers (const QCString &s)
static void forceEndCondSection (yyscan_t yyscanner)
static void initPredefined (yyscan_t yyscanner, const QCString &fileName)

Variables

static std::mutex g_debugMutex
static std::mutex g_globalDefineMutex
static std::mutex g_updateGlobals
static DefineManager g_defineManager

Macro Definition Documentation

◆ MAX_EXPANSION_DEPTH

#define MAX_EXPANSION_DEPTH   50

Definition at line 3016 of file pre.l.

◆ YY_INPUT

#define YY_INPUT ( buf,
result,
max_size )
Value:
result=yyread(yyscanner,buf,max_size);
static int yyread(yyscan_t yyscanner, char *buf, int max_size)
Definition code.l:3982

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

◆ yyscan_t

typedef yyguts_t* yyscan_t

Definition at line 24 of file pre.l.

Function Documentation

◆ addDefine()

void addDefine ( yyscan_t yyscanner)
static

Definition at line 3529 of file pre.l.

3530{
3531 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
3532 Define def;
3533 def.name = state->defName;
3534 def.definition = state->defText.stripWhiteSpace();
3535 def.nargs = state->defArgs;
3536 def.fileName = state->fileName;
3537 def.fileDef = state->yyFileDef;
3538 def.lineNr = state->yyLineNr-state->yyMLines;
3539 def.columnNr = state->yyColNr;
3540 def.varArgs = state->defVarArgs;
3541 //printf("newDefine: %s %s file: %s\n",qPrint(def.name),qPrint(def.definition),
3542 // def.fileDef ? qPrint(def.fileDef->name()) : qPrint(def.fileName));
3543 //printf("newDefine: '%s'->'%s'\n",qPrint(def.name),qPrint(def.definition));
3544 if (!def.name.isEmpty() &&
3546 {
3547 def.isPredefined=TRUE;
3549 }
3550 auto it = state->localDefines.find(def.name.str());
3551 if (it!=state->localDefines.end()) // redefine
3552 {
3553 state->localDefines.erase(it);
3554 }
3555 state->localDefines.emplace(def.name.str(),def);
A class representing a macro definition.
Definition define.h:31
int lineNr
Definition define.h:38
bool varArgs
Definition define.h:42
QCString fileName
Definition define.h:35
QCString name
Definition define.h:33
FileDef * fileDef
Definition define.h:37
bool isPredefined
Definition define.h:43
int columnNr
Definition define.h:39
QCString definition
Definition define.h:34
int nargs
Definition define.h:40
bool expandAsDefined
Definition define.h:45
static StringUnorderedSet expandAsDefinedSet
Definition doxygen.h:118
bool isEmpty() const
Returns TRUE iff the string is empty.
Definition qcstring.h:163
QCString stripWhiteSpace() const
returns a copy of this string with leading and trailing whitespace removed
Definition qcstring.h:260
const std::string & str() const
Definition qcstring.h:552
#define TRUE
Definition qcstring.h:37
3556}

References Doxygen::expandAsDefinedSet, and TRUE.

◆ addMacroDefinition()

void addMacroDefinition ( yyscan_t yyscanner)
static

Definition at line 3558 of file pre.l.

3559{
3560 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
3561 if (state->skip) return; // do not add this define as it is inside a
3562 // conditional section (cond command) that is disabled.
3563
3564 Define define;
3565 define.fileName = state->fileName;
3566 define.lineNr = state->yyLineNr - state->yyMLines;
3567 define.columnNr = state->yyColNr;
3568 define.name = state->defName;
3569 define.args = state->defArgsStr;
3570 define.fileDef = state->inputFileDef;
QCString args
Definition define.h:36
3571
3572 QCString litText = state->defLitText;
3573 int l=litText.find('\n');
3574 if (l>0 && litText.left(l).stripWhiteSpace()=="\\")
3575 {
3576 // strip first line if it only contains a slash
3577 litText = litText.right(litText.length()-l-1);
3578 }
3579 else if (l>0)
3580 {
3581 // align the items on the first line with the items on the second line
3582 int k=l+1;
3583 const char *p=litText.data()+k;
3584 char c = 0;
3585 while ((c=*p++) && (c==' ' || c=='\t')) k++;
3586 litText=litText.mid(l+1,k-l-1)+litText.stripWhiteSpace();
3587 }
3588 QCString litTextStripped = state->defLitText.stripWhiteSpace();
3589 if (litTextStripped.contains('\n')>=1)
3590 {
3591 define.definition = litText;
3592 }
3593 else
3594 {
3595 define.definition = litTextStripped;
3596 }
3597 {
3598 state->macroDefinitions.push_back(define);
3599 }
This is an alternative implementation of QCString.
Definition qcstring.h:101
int find(char c, int index=0, bool cs=TRUE) const
Definition qcstring.cpp:43
size_t length() const
Returns the length of the string, not counting the 0-terminator.
Definition qcstring.h:166
QCString mid(size_t index, size_t len=static_cast< size_t >(-1)) const
Definition qcstring.h:241
QCString right(size_t len) const
Definition qcstring.h:234
const char * data() const
Returns a pointer to the contents of the string in the form of a 0-terminated C string.
Definition qcstring.h:172
QCString left(size_t len) const
Definition qcstring.h:229
int contains(char c, bool cs=TRUE) const
Definition qcstring.cpp:148
3600}

◆ addSeparatorsIfNeeded()

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

Definition at line 3018 of file pre.l.

3019{
3020 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
3021 if (!state->nospaces)
3022 {
3023 // peek back in the stream, for a colon character
3024 char ccPrev = pos==0 || (int)expr.length()<pos ? state->prevChar : expr.at(pos-1);
3025 QCString leftSpace = ccPrev!=':' && ccPrev!=' ' ? " " : "";
3026 int ccNext = 0;
3027 restExpr=restExpr.stripWhiteSpace();
3028 if (restExpr.isEmpty()) // peek ahead in the stream for non-whitespace
3029 {
3030 uint32_t j=(uint32_t)resultExpr.length();
3031 while ((ccNext=getNextChar(yyscanner,resultExpr,nullptr,j))!=EOF && ccNext==' ') { }
3032 if (ccNext != EOF) unputChar(yyscanner,resultExpr,nullptr,j,(char)ccNext);
3033 }
3034 else // take first char from remainder
3035 {
3036 ccNext=restExpr.at(0);
3037 }
3038 // don't add whitespace before a colon
3039 QCString rightSpace = ccNext!=':' && ccNext!=' ' ? " " : "";
3040 //printf("ccPrev='%c' ccNext='%c' p=%d expr=%zu restExpr='%s' left='%s' right='%s'\n",
3041 // ccPrev,ccNext,pos,expr.length(),qPrint(restExpr),qPrint(leftSpace),qPrint(rightSpace));
3042 resultExpr=leftSpace+resultExpr+rightSpace;
3043 }
char & at(size_t i)
Returns a reference to the character at index i.
Definition qcstring.h:593
static int getNextChar(yyscan_t yyscanner, const QCString &expr, QCString *rest, uint32_t &pos)
Definition pre.l:3912
static void unputChar(yyscan_t yyscanner, const QCString &expr, QCString *rest, uint32_t &pos, char c)
Definition pre.l:3958
3044}

◆ addTillEndOfString()

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

Definition at line 2601 of file pre.l.

2603{
2604 int cc;
2605 while ((cc=getNextChar(yyscanner,expr,rest,pos))!=EOF && cc!=0)
2606 {
2607 if (cc=='\\')
2608 {
2609 arg+=(char)cc;
2610 cc=getNextChar(yyscanner,expr,rest,pos);
2611 }
2612 else if (cc==term)
2613 {
2614 return;
2615 }
2616 arg+=(char)cc;
2617 }
#define term(fmt,...)
Definition message.h:137
2618}

References getNextChar(), and term.

◆ checkAndOpenFile()

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

Definition at line 2289 of file pre.l.

2290{
2291 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
2292 alreadyProcessed = FALSE;
2293 std::unique_ptr<FileState> fs;
2294 //printf("checkAndOpenFile(%s)\n",qPrint(fileName));
2295 FileInfo fi(fileName.str());
2296 if (fi.exists() && fi.isFile())
2297 {
2298 const StringVector &exclPatterns = Config_getList(EXCLUDE_PATTERNS);
2299 if (patternMatch(fi,exclPatterns)) return nullptr;
Minimal replacement for QFileInfo.
Definition fileinfo.h:23
#define Config_getList(name)
Definition config.h:38
std::vector< std::string > StringVector
Definition containers.h:33
#define FALSE
Definition qcstring.h:34
bool patternMatch(const FileInfo &fi, const StringVector &patList)
Definition util.cpp:5684
2300
2301 QCString absName = fi.absFilePath();
2302
2303 // global guard
2304 if (state->curlyCount==0) // not #include inside { ... }
2305 {
2306 std::lock_guard<std::mutex> lock(g_globalDefineMutex);
2307 if (g_defineManager.alreadyProcessed(absName.str()))
2308 {
2309 alreadyProcessed = TRUE;
2310 //printf(" already included 1\n");
2311 return 0; // already done
2312 }
2313 }
2314 // check include stack for absName
static std::mutex g_globalDefineMutex
Definition pre.l:234
static DefineManager g_defineManager
Definition pre.l:236
2315
2316 alreadyProcessed = std::any_of(
2317 state->includeStack.begin(),
2318 state->includeStack.end(),
2319 [absName](const std::unique_ptr<FileState> &lfs)
2320 { return lfs->fileName==absName; }
2321 );
2322
2323 if (alreadyProcessed)
2324 {
2325 //printf(" already included 2\n");
2326 return nullptr;
2327 }
2328 //printf("#include %s\n",qPrint(absName));
2329
2330 fs = std::make_unique<FileState>();
2331 if (!readInputFile(absName,fs->fileBuf))
2332 { // error
2333 //printf(" error reading\n");
2334 fs.reset();
2335 }
2336 else
2337 {
2338 addTerminalCharIfMissing(fs->fileBuf,'\n');
2339 fs->oldFileBuf = state->inputBuf;
2340 fs->oldFileBufPos = state->inputBufPos;
2341 }
2342 }
2343 return fs;
void addTerminalCharIfMissing(std::string &s, char c)
Definition stringutil.h:84
bool readInputFile(const QCString &fileName, std::string &contents, bool filter, bool isSourceCode)
read a file name fileName and optionally filter and transcode it
Definition util.cpp:5530
2344}

References FALSE, g_defineManager, g_globalDefineMutex, and TRUE.

◆ computeExpression()

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

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

Definition at line 3496 of file pre.l.

3497{
3498 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
3499 QCString e=expr;
3500 QCString ee=expr;
3501 ee = removeMarkers(ee);
3502 state->expanded.clear();
3503 expandExpression(yyscanner,e,nullptr,0,0);
3504 //printf("after expansion '%s'\n",qPrint(e));
3505 e = removeIdsAndMarkers(e);
3506 if (e.isEmpty()) return FALSE;
3507 //printf("parsing '%s'\n",qPrint(e));
3508 return state->constExpParser.parse(state->fileName.data(),state->yyLineNr,e.str(),ee.str());
static bool expandExpression(yyscan_t yyscanner, QCString &expr, QCString *rest, int pos, int level)
Definition pre.l:3050
static QCString removeIdsAndMarkers(const QCString &s)
Definition pre.l:3230
static QCString removeMarkers(const QCString &s)
Definition pre.l:3425
3509}

References FALSE.

◆ decrLevel()

void decrLevel ( yyscan_t yyscanner)
static

Definition at line 2254 of file pre.l.

2255{
2256 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
2257 //printf("%s line %d: decrLevel %d\n",qPrint(state->fileName),state->yyLineNr,state->levelGuard.size());
2258 if (!state->levelGuard.empty())
2259 {
2260 state->levelGuard.pop();
2261 }
2262 else
2263 {
2264 warn(state->fileName,state->yyLineNr,"More #endif's than #if's found.");
2265 }
#define warn(file, line, fmt,...)
Definition message.h:97
2266}

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

◆ determineBlockName()

void determineBlockName ( yyscan_t yyscanner)
static

Definition at line 3650 of file pre.l.

3651{
3652 struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
3653 yyextra->fenceSize=0;
3654 char c=0;
3655 if (yytext[1]=='f' && ((c=yytext[2])=='[' || c=='{' || c=='(' || c=='$'))
3656 {
3657 switch (c)
3658 {
3659 case '[': yyextra->blockName="]"; break;
3660 case '{': yyextra->blockName="}"; break;
3661 case '(': yyextra->blockName=")"; break;
3662 case '$': yyextra->blockName="$"; break;
3663 default: break;
3664 }
3665 yyextra->blockName=yyextra->blockName.stripWhiteSpace();
3666 }
3667 else
3668 {
3669 QCString bn=QCString(&yytext[1]).stripWhiteSpace();
3670 if (bn=="startuml")
3671 {
3672 yyextra->blockName="uml";
3673 }
3674 else
3675 {
3676 int i = bn.find('{'); // for \code{.c}
3677 if (i!=-1) bn=bn.left(i).stripWhiteSpace();
3678 yyextra->blockName=bn;
3679 }
3680 }
3681}

◆ endCondSection()

void endCondSection ( yyscan_t yyscanner)
static

Definition at line 3850 of file pre.l.

3851{
3852 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
3853 if (state->condStack.empty())
3854 {
3855 warn(state->fileName,state->yyLineNr,"the \\endcond does not have a corresponding \\cond in this file");
3856 state->skip=FALSE;
3857 }
3858 else
3859 {
3860 const std::unique_ptr<preYY_CondCtx> &ctx = state->condStack.top();
3861 state->skip=ctx->skip;
3862 state->condStack.pop();
3863 }
3864 //printf("endCondSection: skip=%d stack=%d\n",state->skip,state->condStack.count());
3865}

References FALSE.

◆ escapeAt()

QCString escapeAt ( const QCString & text)
static

Definition at line 3877 of file pre.l.

3878{
3879 QCString result;
3880 if (!text.isEmpty())
3881 {
3882 char c = 0;
3883 const char *p=text.data();
3884 while ((c=*p++))
3885 {
3886 if (c=='@') result+="@@"; else result+=c;
3887 }
3888 }
3889 return result;
3890}

References QCString::data().

◆ expandExpression()

bool expandExpression ( yyscan_t yyscanner,
QCString & expr,
QCString * rest,
int pos,
int level )
static

performs recursive macro expansion on the string expr starting at position pos. May read additional characters from the input while re-scanning!

Definition at line 3050 of file pre.l.

3051{
3052 struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
3053 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
3054 //printf(">expandExpression(expr='%s',rest='%s',pos=%d,level=%d)\n",qPrint(expr),rest ? qPrint(*rest) : "", pos, level);
3055 if (expr.isEmpty())
3056 {
3057 //printf("<expandExpression: empty\n");
3058 return TRUE;
3059 }
3060 if (state->expanded.find(expr.str())!=state->expanded.end() &&
3061 level>MAX_EXPANSION_DEPTH) // check for too deep recursive expansions
3062 {
3063 //printf("<expandExpression: already expanded expr='%s'\n",qPrint(expr));
3064 return FALSE;
3065 }
3066 else
3067 {
3068 state->expanded.insert(expr.str());
3069 }
3070 QCString macroName;
3071 QCString expMacro;
3072 bool definedTest=FALSE;
3073 int i=pos, l=0, p=0, len=0;
3074 int startPos = pos;
3075 int samePosCount=0;
3076 while ((p=getNextId(expr,i,&l))!=-1) // search for an macro name
3077 {
3078 bool replaced=FALSE;
3079 macroName=expr.mid(p,l);
3080 //printf(" p=%d macroName=%s\n",p,qPrint(macroName));
3081 if (p<2 || !(expr.at(p-2)=='@' && expr.at(p-1)=='-')) // no-rescan marker?
3082 {
3083 if (state->expandedDict.find(macroName.str())==state->expandedDict.end()) // expand macro
3084 {
3085 bool expanded=false;
3086 Define *def=isDefined(yyscanner,macroName);
3087 // In case EXPAND_ONLY_PREDEF is enabled prevent expansion unless the macro was explicitly
3088 // predefined
3089 if (yyextra->expandOnlyPredef && def && !def->isPredefined) def=nullptr;
3090 if (macroName=="defined")
3091 {
3092 //printf("found defined inside macro definition '%s'\n",qPrint(expr.right(expr.length()-p)));
3093 definedTest=TRUE;
3094 }
3095 else if (definedTest) // macro name was found after defined
3096 {
3097 if (def) expMacro = " 1 "; else expMacro = " 0 ";
3098 replaced=TRUE;
3099 len=l;
3100 definedTest=FALSE;
3101 }
3102 else if (def && def->nargs==-1) // simple macro
3103 {
3104 // substitute the definition of the macro
3105 expMacro=def->definition.stripWhiteSpace();
3106 //expMacro=def->definition.stripWhiteSpace();
3107 replaced=TRUE;
3108 len=l;
3109 //printf("simple macro expansion='%s'->'%s'\n",qPrint(macroName),qPrint(expMacro));
3110 }
3111 else if (def && def->nargs>=0) // function macro
3112 {
3113 //printf(" >>>> call replaceFunctionMacro expr='%s'\n",qPrint(expr));
3114 replaced=replaceFunctionMacro(yyscanner,expr,rest,p+l,len,def,expMacro,level);
3115 //printf(" <<<< call replaceFunctionMacro: replaced=%d\n",replaced);
3116 len+=l;
3117 }
#define MAX_EXPANSION_DEPTH
Definition pre.l:3016
static Define * isDefined(yyscan_t yyscanner, const QCString &name)
Returns a reference to a Define object given its name or 0 if the Define does not exist.
Definition pre.l:3982
static int getNextId(const QCString &expr, int p, int *l)
Definition pre.l:2962
static bool replaceFunctionMacro(yyscan_t yyscanner, const QCString &expr, QCString *rest, int pos, int &len, const Define *def, QCString &result, int level)
Definition pre.l:2704
3118
3119 if (replaced) // expand the macro and rescan the expression
3120 {
3121 //printf(" replacing '%s'->'%s'\n",qPrint(expr.mid(p,len)),qPrint(expMacro));
3122 QCString resultExpr=expMacro;
3123 QCString restExpr=expr.right(expr.length()-len-p);
3124 addSeparatorsIfNeeded(yyscanner,expr,resultExpr,restExpr,p);
3125 processConcatOperators(resultExpr);
3126 //printf(" macroName=%s restExpr='%s' def->nonRecursive=%d\n",qPrint(macroName),qPrint(restExpr),def ? def->nonRecursive : false);
3127 if (def && !def->nonRecursive)
3128 {
3129 state->expandedDict.emplace(toStdString(macroName),def);
3130 expanded = expandExpression(yyscanner,resultExpr,&restExpr,0,level+1);
3131 state->expandedDict.erase(toStdString(macroName));
3132 }
3133 else if (def && def->nonRecursive)
3134 {
3135 expanded = true;
3136 }
3137 if (expanded)
3138 {
3139 //printf("expanded '%s' + '%s' + '%s'\n",qPrint(expr.left(p)),qPrint(resultExpr),qPrint(restExpr));
3140 expr=expr.left(p)+resultExpr+restExpr;
3141 i=p;
3142 }
3143 else
3144 {
3145 //printf("not expanded '%s' + @- '%s'\n",qPrint(expr.left(p)),qPrint(expr.right(expr.length()-p)));
3146 expr=expr.left(p)+"@-"+expr.right(expr.length()-p);
3147 i=p+l+2;
3148 }
3149 }
3150 else // move to the next macro name
3151 {
3152 //printf(" moving to the next macro old i=%d new i=%d\n",i,p+l);
3153 i=p+l;
3154 }
3155 }
3156 else // move to the next macro name
3157 {
3158 expr=expr.left(p)+"@-"+expr.right(expr.length()-p);
3159 //printf("macro already expanded, moving to the next macro expr=%s\n",qPrint(expr));
3160 i=p+l+2;
3161 //i=p+l;
3162 }
3163 // check for too many inplace expansions without making progress
3164 if (i==startPos)
3165 {
3166 samePosCount++;
3167 }
3168 else
3169 {
3170 startPos=i;
3171 samePosCount=0;
3172 }
3173 if (samePosCount>MAX_EXPANSION_DEPTH)
3174 {
3175 break;
3176 }
3177 }
3178 else // no re-scan marker found, skip the macro name
3179 {
3180 //printf("skipping marked macro\n");
3181 i=p+l;
3182 }
3183 }
3184 //printf("<expandExpression(expr='%s',rest='%s',pos=%d,level=%d)\n",qPrint(expr),rest ? qPrint(*rest) : "", pos,level);
3185 return TRUE;
bool nonRecursive
Definition define.h:44
static void addSeparatorsIfNeeded(yyscan_t yyscanner, const QCString &expr, QCString &resultExpr, QCString &restExpr, int pos)
Definition pre.l:3018
static void processConcatOperators(QCString &expr)
Definition pre.l:2548
std::string toStdString(const QCString &s)
Definition qcstring.h:702
3186}

References TRUE.

◆ expandMacro()

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

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

Definition at line 3515 of file pre.l.

3516{
3517 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3518 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
3519 state->prevChar = yyscanner->yytext_r > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ? *(yyscanner->yytext_r-1) : 0;
3520 QCString n=name;
3521 state->expanded.clear();
3522 expandExpression(yyscanner,n,nullptr,0,0);
3523 n=removeMarkers(n);
3524 state->prevChar=0;
3525 //printf("expandMacro '%s'->'%s'\n",qPrint(name),qPrint(n));
3526 return n;
void clear()
Definition qcstring.h:182
3527}

◆ expandVAOpt()

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

Definition at line 2652 of file pre.l.

2653{
2654 //printf("expandVAOpt(vaStr=%s,hasOptionalArgs=%d)\n",qPrint(vaStr),hasOptionalArgs);
2655 QCString result;
2656 int vo=0, vp=0;
2657 result.clear();
2658 int vl = static_cast<int>(vaStr.length());
2659 while ((vo = vaStr.find("__VA_OPT__(",vp))!=-1)
2660 {
2661 bool hasHash = vo>0 && vaStr.at(vo-1)=='#';
2662 if (hasHash)
2663 {
2664 result+=vaStr.mid(vp,vo-vp-1); // don't copy #
2665 result+="\"";
2666 }
2667 else
2668 {
2669 result+=vaStr.mid(vp,vo-vp);
2670 }
2671 int ve=vo+11; // skip over '__VA_OPT__(' part
2672 int bc=1;
2673 while (bc>0 && ve<vl)
2674 {
2675 if (vaStr[ve]==')') bc--;
2676 else if (vaStr[ve]=='(') bc++;
2677 ve++;
2678 }
2679 // ve points to end of __VA_OPT__(....)
2680 if (bc==0 && hasOptionalArgs)
2681 {
2682 QCString voStr = vaStr.mid(vo+11,ve-vo-12);
2683 //printf("vo=%d ve=%d voStr=%s\n",vo,ve,qPrint(voStr));
2684 result+=voStr; // take 'x' from __VA_OPT__(x)
2685 }
2686 if (hasHash)
2687 {
2688 result+="\"";
2689 }
2690 vp=ve;
2691 }
2692 result+=vaStr.mid(vp);
2693 //printf("vaStr='%s'\n -> '%s'\n",qPrint(vaStr),qPrint(result));
2694 return result;
2695}

References QCString::at(), and QCString::mid().

◆ extractTrailingComment()

QCString extractTrailingComment ( const QCString & s)
static

Definition at line 2420 of file pre.l.

2421{
2422 if (s.isEmpty()) return "";
2423 int i=(int)s.length()-1;
2424 while (i>=0)
2425 {
2426 char c=s[i];
2427 switch (c)
2428 {
2429 case '/':
2430 {
2431 i--;
2432 if (i>=0 && s[i]=='*') // end of a comment block
2433 {
2434 i--;
2435 while (i>0 && !(s[i-1]=='/' && s[i]=='*')) i--;
2436 if (i==0)
2437 {
2438 i++;
2439 }
2440 // only /*!< ... */ or /**< ... */ are treated as a comment for the macro name,
2441 // otherwise the comment is treated as part of the macro definition
2442 return ((s[i+1]=='*' || s[i+1]=='!') && s[i+2]=='<') ? &s[i-1] : "";
2443 }
2444 else
2445 {
2446 return "";
2447 }
2448 }
2449 break;
2450 // whitespace or line-continuation
2451 case ' ':
2452 case '\t':
2453 case '\r':
2454 case '\n':
2455 case '\\':
2456 break;
2457 default:
2458 return "";
2459 }
2460 i--;
2461 }
2462 return "";
2463}

◆ extraSpacing()

void extraSpacing ( yyscan_t yyscanner)
inlinestatic

Definition at line 3637 of file pre.l.

3638{
3639 struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
3640 if (!yyextra->defContinue) return;
3641 for (int i=0; i< (int)yyleng; i++)
3642 {
3643 if (yytext[i] == '\t')
3644 yyextra->defExtraSpacing+='\t';
3645 else
3646 yyextra->defExtraSpacing+=' ';
3647 }
3648}

◆ findFile()

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

Definition at line 2346 of file pre.l.

2347{
2348 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
2349 //printf("** findFile(%s,%d) state->fileName=%s\n",qPrint(fileName),localInclude,qPrint(state->fileName));
2350 if (Portable::isAbsolutePath(fileName))
2351 {
2352 auto fs = checkAndOpenFile(yyscanner,fileName,alreadyProcessed);
2353 if (fs)
2354 {
2355 setFileName(yyscanner,fileName);
2356 state->yyLineNr=1;
2357 return fs;
2358 }
2359 else if (alreadyProcessed)
2360 {
2361 return nullptr;
2362 }
2363 }
2364 if (localInclude && !state->fileName.isEmpty())
2365 {
2366 FileInfo fi(state->fileName.str());
2367 if (fi.exists())
2368 {
2369 QCString absName = QCString(fi.dirPath(TRUE))+"/"+fileName;
2370 auto fs = checkAndOpenFile(yyscanner,absName,alreadyProcessed);
2371 if (fs)
2372 {
2373 setFileName(yyscanner,absName);
2374 state->yyLineNr=1;
2375 return fs;
2376 }
2377 else if (alreadyProcessed)
2378 {
2379 return nullptr;
2380 }
2381 }
2382 }
2383 if (state->pathList.empty())
2384 {
2385 return nullptr;
2386 }
2387 for (auto path : state->pathList)
2388 {
2389 QCString absName = path+"/"+fileName;
2390 //printf(" Looking for %s in %s\n",fileName,qPrint(path));
2391 auto fs = checkAndOpenFile(yyscanner,absName,alreadyProcessed);
2392 if (fs)
2393 {
2394 setFileName(yyscanner,absName);
2395 state->yyLineNr=1;
2396 //printf(" -> found it\n");
2397 return fs;
2398 }
2399 else if (alreadyProcessed)
2400 {
2401 return nullptr;
2402 }
2403 }
2404 bool ambig = false;
2406 if (fd && !ambig) // fallback in case the file is uniquely named in the input, use that one
2407 {
2408 auto fs = checkAndOpenFile(yyscanner,fd->absFilePath(),alreadyProcessed);
2409 if (fs)
2410 {
2411 setFileName(yyscanner,fd->absFilePath());
2412 state->yyLineNr=1;
2413 //printf(" -> found it\n");
2414 return fs;
2415 }
2416 }
2417 return nullptr;
static FileNameLinkedMap * inputNameLinkedMap
Definition doxygen.h:104
A model of a file symbol.
Definition filedef.h:99
virtual QCString absFilePath() const =0
bool isAbsolutePath(const QCString &fileName)
Definition portable.cpp:498
static void setFileName(yyscan_t yyscanner, const QCString &name)
Definition pre.l:2226
static std::unique_ptr< FileState > checkAndOpenFile(yyscan_t yyscanner, const QCString &fileName, bool &alreadyProcessed)
Definition pre.l:2289
FileDef * findFileDef(const FileNameLinkedMap *fnMap, const QCString &n, bool &ambig)
Definition util.cpp:2871
2418}

References Portable::isAbsolutePath().

◆ forceEndCondSection()

void forceEndCondSection ( yyscan_t yyscanner)
static

Definition at line 3867 of file pre.l.

3868{
3869 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
3870 while (!state->condStack.empty())
3871 {
3872 state->condStack.pop();
3873 }
3874 state->skip=FALSE;
3875}

◆ getCurrentChar()

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

Definition at line 3935 of file pre.l.

3936{
3937 //printf("getCurrentChar(%s,%s,%d)\n",qPrint(expr),rest ? rest->data() : 0,pos);
3938 if (pos<expr.length())
3939 {
3940 //printf("%c=expr()\n",expr.at(pos));
3941 return expr.at(pos);
3942 }
3943 else if (rest && !rest->isEmpty())
3944 {
3945 int cc=rest->at(0);
3946 //printf("%c=rest\n",cc);
3947 return cc;
3948 }
3949 else
3950 {
3951 int cc=yyinput(yyscanner);
3952 returnCharToStream(yyscanner,(char)cc);
3953 //printf("%c=yyinput()\n",cc);
3954 return cc;
3955 }
static void returnCharToStream(yyscan_t yyscanner, char c)
Definition pre.l:2595
3956}

References QCString::at().

Referenced by skipCommentMacroName().

◆ getFenceSize()

yy_size_t getFenceSize ( char * txt,
yy_size_t leng )
static

Definition at line 2215 of file pre.l.

2216{
2217 yy_size_t fenceSize = 0;
2218 for (size_t i = 0; i < leng; i++)
2219 {
2220 if (txt[i] != ' ' && txt[i] != '*' && txt[i] != '\t') break;
2221 fenceSize++;
2222 }
2223 return leng-fenceSize;
2224}

◆ getLexerFILE()

const char * getLexerFILE ( )
inlinestatic

Definition at line 352 of file pre.l.

352{return __FILE__;}

◆ getNextChar()

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

Definition at line 3912 of file pre.l.

3913{
3914 //printf("getNextChar(%s,%s,%d)\n",qPrint(expr),rest ? rest->data() : 0,pos);
3915 if (pos<expr.length())
3916 {
3917 //printf(" expr()='%c'\n",expr.at(pos));
3918 return expr.at(pos++);
3919 }
3920 else if (rest && !rest->isEmpty())
3921 {
3922 int cc=rest->at(0);
3923 *rest=rest->right(rest->length()-1);
3924 //printf(" rest='%c'\n",cc);
3925 return cc;
3926 }
3927 else
3928 {
3929 int cc=yyinput(yyscanner);
3930 //printf(" yyinput()='%c' %d\n",cc,EOF);
3931 return cc;
3932 }
3933}

References QCString::at().

Referenced by addTillEndOfString(), and skipCommentMacroName().

◆ getNextId()

int getNextId ( const QCString & expr,
int p,
int * l )
static

returns the next identifier in string expr by starting at position p. The position of the identifier is returned (or -1 if nothing is found) and l is its length. Any quoted strings are skipping during the search.

Definition at line 2962 of file pre.l.

2963{
2964 int n;
2965 while (p<(int)expr.length())
2966 {
2967 char c=expr.at(p++);
2968 if (isdigit(c)) // skip number
2969 {
2970 while (p<(int)expr.length() && isId(expr.at(p))) p++;
2971 }
2972 else if (isalpha(c) || c=='_') // read id
2973 {
2974 n=p-1;
2975 while (p<(int)expr.length() && isId(expr.at(p))) p++;
2976 *l=p-n;
2977 return n;
2978 }
2979 else if (c=='"') // skip string
2980 {
2981 char ppc=0,pc=c;
2982 if (p<(int)expr.length()) c=expr.at(p);
2983 while (p<(int)expr.length() && (c!='"' || (pc=='\\' && ppc!='\\')))
2984 // continue as long as no " is found, but ignoring \", but not \\"
2985 {
2986 ppc=pc;
2987 pc=c;
2988 c=expr.at(p);
2989 p++;
2990 }
2991 if (p<(int)expr.length()) ++p; // skip closing quote
2992 }
2993 else if (c=='/') // skip C Comment
2994 {
2995 //printf("Found C comment at p=%d\n",p);
2996 char pc=c;
2997 if (p<(int)expr.length())
2998 {
2999 c=expr.at(p);
3000 if (c=='*') // Start of C comment
3001 {
3002 p++;
3003 while (p<(int)expr.length() && !(pc=='*' && c=='/'))
3004 {
3005 pc=c;
3006 c=expr.at(p++);
3007 }
3008 }
3009 }
3010 //printf("Found end of C comment at p=%d\n",p);
3011 }
3012 }
3013 return -1;
bool isId(int c)
Definition util.h:207
3014}

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

◆ incrLevel()

void incrLevel ( yyscan_t yyscanner)
static

Definition at line 2247 of file pre.l.

2248{
2249 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
2250 state->levelGuard.push(false);
2251 //printf("%s line %d: incrLevel %d\n",qPrint(yyextra->fileName),yyextra->yyLineNr,yyextra->levelGuard.size());
2252}

◆ initPredefined()

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

Definition at line 4011 of file pre.l.

4012{
4013 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
4014
4015 // add predefined macros
4016 const StringVector &predefList = Config_getList(PREDEFINED);
4017 for (const auto &ds : predefList)
4018 {
4019 size_t i_equals=ds.find('=');
4020 size_t i_obrace=ds.find('(');
4021 size_t i_cbrace=ds.find(')');
4022 bool nonRecursive = i_equals!=std::string::npos && i_equals>0 && ds[i_equals-1]==':';
4023
4024 if ((i_obrace==0) || (i_equals==0) || (i_equals==1 && ds[i_equals-1]==':'))
4025 {
4026 continue; // no define name
4027 }
4028
4029 if (i_obrace<i_equals && i_cbrace<i_equals &&
4030 i_obrace!=std::string::npos && i_cbrace!=std::string::npos &&
4031 i_obrace<i_cbrace
4032 ) // predefined function macro definition
4033 {
4034 static const reg::Ex reId(R"(\a\w*)");
4035 std::map<std::string,int> argMap;
4036 std::string args = ds.substr(i_obrace+1,i_cbrace-i_obrace-1); // part between ( and )
4037 bool hasVarArgs = args.find("...")!=std::string::npos;
4038 //printf("predefined function macro '%s'\n",qPrint(ds));
4039 int count = 0;
4040 reg::Iterator arg_it(args,reId,0);
4041 reg::Iterator arg_end;
4042 // gather the formal arguments in a dictionary
4043 for (; arg_it!=arg_end; ++arg_it)
4044 {
4045 argMap.emplace(arg_it->str(),count++);
4046 }
4047 if (hasVarArgs) // add the variable argument if present
4048 {
4049 argMap.emplace("__VA_ARGS__",count++);
4050 }
Class representing a regular expression.
Definition regex.h:39
Class to iterate through matches.
Definition regex.h:230
4051
4052 // strip definition part
4053 std::string definition;
4054 std::string in=ds.substr(i_equals+1);
4055 reg::Iterator re_it(in,reId);
4056 reg::Iterator re_end;
4057 size_t i=0;
4058 // substitute all occurrences of formal arguments by their
4059 // corresponding markers
4060 for (; re_it!=re_end; ++re_it)
4061 {
4062 const auto &match = *re_it;
4063 size_t pi = match.position();
4064 size_t l = match.length();
4065 if (pi>i) definition+=in.substr(i,pi-i);
bool match(std::string_view str, Match &match, const Ex &re)
Matches a given string str for a match against regular expression re.
Definition regex.cpp:855
4066
4067 auto it = argMap.find(match.str());
4068 if (it!=argMap.end())
4069 {
4070 int argIndex = it->second;
4071 QCString marker;
4072 marker.sprintf(" @%d ",argIndex);
4073 definition+=marker.str();
4074 }
4075 else
4076 {
4077 definition+=match.str();
4078 }
4079 i=pi+l;
4080 }
4081 definition+=in.substr(i);
QCString & sprintf(const char *format,...)
Definition qcstring.cpp:29
4082
4083 // add define definition to the dictionary of defines for this file
4084 std::string dname = ds.substr(0,i_obrace);
4085 if (!dname.empty())
4086 {
4087 Define def;
4088 def.name = dname;
4089 def.definition = definition;
4090 def.nargs = count;
4091 def.isPredefined = TRUE;
4092 def.nonRecursive = nonRecursive;
4093 def.fileDef = state->yyFileDef;
4094 def.fileName = fileName;
4095 def.varArgs = hasVarArgs;
4096 state->contextDefines.emplace(def.name.str(),def);
4097
4098 //printf("#define '%s' '%s' #nargs=%d hasVarArgs=%d\n",
4099 // qPrint(def.name),qPrint(def.definition),def.nargs,def.varArgs);
4100 }
4101 }
4102 else if (!ds.empty()) // predefined non-function macro definition
4103 {
4104 //printf("predefined normal macro '%s'\n",qPrint(ds));
4105 Define def;
4106 if (i_equals==std::string::npos) // simple define without argument
4107 {
4108 def.name = ds;
4109 def.definition = "1"; // substitute occurrences by 1 (true)
4110 }
4111 else // simple define with argument
4112 {
4113 int ine=static_cast<int>(i_equals) - (nonRecursive ? 1 : 0);
4114 def.name = ds.substr(0,ine);
4115 def.definition = ds.substr(i_equals+1);
4116 }
4117 if (!def.name.isEmpty())
4118 {
4119 def.nargs = -1;
4120 def.isPredefined = TRUE;
4121 def.nonRecursive = nonRecursive;
4122 def.fileDef = state->yyFileDef;
4123 def.fileName = fileName;
4124 state->contextDefines.emplace(def.name.str(),def);
4125 }
4126 }
4127 }
4128}

◆ isDefined()

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

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

Definition at line 3982 of file pre.l.

3983{
3984 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
3985
3986 bool undef = false;
3987 auto findDefine = [&undef,&name](DefineMap &map)
3988 {
3989 Define *d=nullptr;
3990 auto it = map.find(name.str());
3991 if (it!=map.end())
3992 {
3993 d = &it->second;
3994 if (d->undef)
3995 {
3996 undef=true;
3997 d=nullptr;
3998 }
3999 }
4000 return d;
4001 };
bool undef
Definition define.h:41
std::map< std::string, Define > DefineMap
A dictionary of managed Define objects.
Definition pre.l:109
4002
4003 Define *def = findDefine(state->localDefines);
4004 if (def==nullptr && !undef)
4005 {
4006 def = findDefine(state->contextDefines);
4007 }
4008 return def;
4009}

◆ otherCaseDone()

bool otherCaseDone ( yyscan_t yyscanner)
static

Definition at line 2268 of file pre.l.

2269{
2270 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
2271 if (state->levelGuard.empty())
2272 {
2273 warn(state->fileName,state->yyLineNr,"Found an #else without a preceding #if.");
2274 return TRUE;
2275 }
2276 else
2277 {
2278 return state->levelGuard.top();
2279 }
2280}

References TRUE.

◆ outputArray()

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

Definition at line 3608 of file pre.l.

3609{
3610 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
3611 if (state->includeStack.empty() || state->curlyCount>0) (*state->outputBuf)+=std::string_view(a,len);
3612}

◆ outputChar()

void outputChar ( yyscan_t yyscanner,
char c )
inlinestatic

Definition at line 3602 of file pre.l.

3603{
3604 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
3605 if (state->includeStack.empty() || state->curlyCount>0) (*state->outputBuf)+=c;
3606}

Referenced by outputSpaces().

◆ outputSpace()

void outputSpace ( yyscan_t yyscanner,
char c )
inlinestatic

Definition at line 3620 of file pre.l.

3621{
3622 if (c=='\t') outputChar(yyscanner,'\t');
3623 else outputChar(yyscanner,' ');
static void outputChar(yyscan_t yyscanner, char c)
Definition pre.l:3602
3624}

◆ outputSpaces()

void outputSpaces ( yyscan_t yyscanner,
char * s )
inlinestatic

Definition at line 3626 of file pre.l.

3627{
3628 const char *p=s;
3629 char c = 0;
3630 while ((c=*p++))
3631 {
3632 if (c=='\t') outputChar(yyscanner,'\t');
3633 else outputChar(yyscanner,' ');
3634 }
3635}

References outputChar().

◆ outputString()

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

Definition at line 3614 of file pre.l.

3615{
3616 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
3617 if (state->includeStack.empty() || state->curlyCount>0) (*state->outputBuf)+=a.str();
3618}

◆ processConcatOperators()

void processConcatOperators ( QCString & expr)
static

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

Definition at line 2548 of file pre.l.

2549{
2550 if (expr.isEmpty()) return;
2551 //printf("processConcatOperators: in='%s'\n",qPrint(expr));
2552 std::string e = expr.str();
2553 static const reg::Ex r(R"(\s*##\s*)");
DirIterator end(const DirIterator &) noexcept
Definition dir.cpp:175
2555
2556 size_t i=0;
2557 for (;;)
2558 {
2559 reg::Iterator it(e,r,i);
2560 if (it!=end)
2561 {
2562 const auto &match = *it;
2563 size_t n = match.position();
2564 size_t l = match.length();
2565 //printf("Match: '%s'\n",qPrint(expr.mid(i)));
2566 if (n+l+1<e.length() && e[static_cast<int>(n+l)]=='@' && expr[static_cast<int>(n+l+1)]=='-')
2567 {
2568 // remove no-rescan marker after ID
2569 l+=2;
2570 }
2571 //printf("found '%s'\n",qPrint(expr.mid(n,l)));
2572 // remove the ## operator and the surrounding whitespace
2573 e=e.substr(0,n)+e.substr(n+l);
2574 int k=static_cast<int>(n)-1;
2575 while (k>=0 && isId(e[k])) k--;
2576 if (k>0 && e[k]=='-' && e[k-1]=='@')
2577 {
2578 // remove no-rescan marker before ID
2579 e=e.substr(0,k-1)+e.substr(k+1);
2580 n-=2;
2581 }
2582 i=n;
2583 }
2584 else
2585 {
2586 break;
2587 }
2588 }
2589
2590 expr = e;
2591
2592 //printf("processConcatOperators: out='%s'\n",qPrint(expr));
2593}

References end().

◆ processUntilMatchingTerminator()

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

Process string or character literal.

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

Definition at line 3194 of file pre.l.

3195{
3196 if (inputStr==nullptr) return inputStr;
3197 char term = *inputStr; // capture start character of the literal
3198 if (term!='\'' && term!='"') return inputStr; // not a valid literal
3199 char c=term;
3200 // output start character
3201 result+=c;
3202 inputStr++;
3203 while ((c=*inputStr)) // while inside the literal
3204 {
3205 if (c==term) // found end marker of the literal
3206 {
3207 // output end character and stop
3208 result+=c;
3209 inputStr++;
3210 break;
3211 }
3212 else if (c=='\\') // escaped character, process next character
3213 // as well without checking for end marker.
3214 {
3215 result+=c;
3216 inputStr++;
3217 c=*inputStr;
3218 if (c==0) break; // unexpected end of string after escape character
3219 }
3220 result+=c;
3221 inputStr++;
3222 }
3223 return inputStr;
3224}

References term.

Referenced by removeMarkers().

◆ readIncludeFile()

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

Definition at line 3683 of file pre.l.

3684{
3685 AUTO_TRACE("inc={}",inc);
3686 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
3687 uint32_t i=0;
#define AUTO_TRACE(...)
Definition docnode.cpp:47
3688
3689 // find the start of the include file name
3690 while (i<inc.length() &&
3691 (inc.at(i)==' ' || inc.at(i)=='"' || inc.at(i)=='<')
3692 ) i++;
3693 uint32_t s=i;
3694
3695 // was it a local include?
3696 bool localInclude = s>0 && inc.at(s-1)=='"';
3697
3698 // find the end of the include file name
3699 while (i<inc.length() && inc.at(i)!='"' && inc.at(i)!='>') i++;
3700
3701 if (s<inc.length() && i>s) // valid include file name found
3702 {
3703 // extract include path+name
3704 QCString incFileName=inc.mid(s,i-s).stripWhiteSpace();
3705 if (incFileName.endsWith(".exe") || incFileName.endsWith(".dll") || incFileName.endsWith(".tlb"))
3706 {
3707 // skip imported binary files (e.g. M$ type libraries)
3708 return;
3709 }
bool endsWith(const char *s) const
Definition qcstring.h:524
3710
3711 QCString oldFileName = state->fileName;
3712 FileDef *oldFileDef = state->yyFileDef;
3713 int oldLineNr = state->yyLineNr;
3714 //printf("Searching for '%s'\n",qPrint(incFileName));
3715
3716 QCString absIncFileName = determineAbsoluteIncludeName(state->fileName,incFileName);
QCString determineAbsoluteIncludeName(const QCString &curFile, const QCString &incFileName)
Definition util.cpp:3581
3717
3718 // findFile will overwrite state->yyFileDef if found
3719 std::unique_ptr<FileState> fs;
3720 bool alreadyProcessed = FALSE;
3721 //printf("calling findFile(%s)\n",qPrint(incFileName));
3722 fs=findFile(yyscanner,absIncFileName,localInclude,alreadyProcessed); // see if the absolute include file can be found
3723 if (fs)
3724 {
3725 {
3726 std::lock_guard<std::mutex> lock(g_globalDefineMutex);
3727 g_defineManager.addInclude(oldFileName.str(),absIncFileName.str());
3728 }
static std::unique_ptr< FileState > findFile(yyscan_t yyscanner, const QCString &fileName, bool localInclude, bool &alreadyProcessed)
Definition pre.l:2346
3729
3730 //printf("Found include file!\n");
3732 {
3733 for (i=0;i<state->includeStack.size();i++)
3734 {
3736 }
3737 Debug::print(Debug::Preprocessor,0,"#include {}: parsing...\n",incFileName);
3738 }
@ Preprocessor
Definition debug.h:30
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:76
3739
3740 if (state->includeStack.empty() && oldFileDef)
3741 {
3742 PreIncludeInfo *ii = state->includeRelations.find(absIncFileName);
3743 if (ii==nullptr)
3744 {
3745 bool ambig = false;
3746 FileDef *incFd = findFileDef(Doxygen::inputNameLinkedMap,absIncFileName,ambig);
3747 state->includeRelations.add(
3748 absIncFileName,
3749 oldFileDef,
3750 ambig ? nullptr : incFd,
3751 incFileName,
3752 localInclude,
3753 state->isImported
3754 );
3755 }
3756 }
3757
3758 struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
3759 fs->bufState = YY_CURRENT_BUFFER;
3760 fs->lineNr = oldLineNr;
3761 fs->fileName = oldFileName;
3762 fs->curlyCount = state->curlyCount;
3763 //state->curlyCount = 0; // don't reset counter, see issue #10997
3764 fs->lexRulesPart = state->lexRulesPart;
3765 state->lexRulesPart = false;
3766 // push the state on the stack
3767 FileState *fs_ptr = fs.get();
3768 state->includeStack.push_back(std::move(fs));
3769 // set the scanner to the include file
3770
3771 // Deal with file changes due to
3772 // #include's within { .. } blocks
3773 QCString lineStr(state->fileName.length()+20, QCString::ExplicitSize);
3774 lineStr.sprintf("# 1 \"%s\" 1\n",qPrint(state->fileName));
3775 outputString(yyscanner,lineStr);
@ ExplicitSize
Definition qcstring.h:146
static void outputString(yyscan_t yyscanner, const QCString &s)
Definition pre.l:3614
const char * qPrint(const char *s)
Definition qcstring.h:687
3776
3777 AUTO_TRACE_ADD("Switching to include file {}",incFileName);
3778 state->expectGuard=TRUE;
3779 state->inputBuf = &fs_ptr->fileBuf;
3780 state->inputBufPos=0;
3781 yy_switch_to_buffer(yy_create_buffer(0, YY_BUF_SIZE, yyscanner),yyscanner);
3782 }
3783 else
3784 {
3785 if (alreadyProcessed) // if this header was already process we can just copy the stored macros
3786 // in the local context
3787 {
3788 std::lock_guard<std::mutex> lock(g_globalDefineMutex);
3789 g_defineManager.addInclude(state->fileName.str(),absIncFileName.str());
3790 g_defineManager.retrieve(absIncFileName.str(),state->contextDefines);
3791 }
#define YY_BUF_SIZE
Definition commentcnv.l:19
#define AUTO_TRACE_ADD(...)
Definition docnode.cpp:48
std::string fileBuf
Definition pre.l:86
3792
3793 if (state->includeStack.empty() && oldFileDef)
3794 {
3795 PreIncludeInfo *ii = state->includeRelations.find(absIncFileName);
3796 if (ii==nullptr)
3797 {
3798 bool ambig = false;
3799 FileDef *incFd = findFileDef(Doxygen::inputNameLinkedMap,absIncFileName,ambig);
3800 ii = state->includeRelations.add(absIncFileName,
3801 oldFileDef,
3802 ambig ? nullptr : incFd,
3803 incFileName,
3804 localInclude,
3805 state->isImported
3806 );
3807 }
3808 }
3809
3811 {
3812 for (i=0;i<state->includeStack.size();i++)
3813 {
3815 }
3816 if (alreadyProcessed)
3817 {
3818 Debug::print(Debug::Preprocessor,0,"#include {}: already processed! skipping...\n",incFileName);
3819 }
3820 else
3821 {
3822 Debug::print(Debug::Preprocessor,0,"#include {}: not found! skipping...\n",incFileName);
3823 }
3824 //printf("error: include file %s not found\n",yytext);
3825 }
3826 if (localInclude && !state->includeStack.empty() && state->curlyCount>0 && !alreadyProcessed) // failed to find #include inside { ... }
3827 {
3828 warn(state->fileName,state->yyLineNr,"include file {} not found, perhaps you forgot to add its directory to INCLUDE_PATH?",incFileName);
3829 }
3830 }
3831 }
3832}

◆ removeIdsAndMarkers()

QCString removeIdsAndMarkers ( const QCString & s)
static

replaces all occurrences of @@ in s by @ and removes all occurrences of @E. All identifiers found are replaced by 0L

Definition at line 3230 of file pre.l.

3231{
3232 static const std::vector<std::string> signs = { "signed", "unsigned" };
3233 struct TypeInfo { std::string name; size_t size; };
3234 static const std::vector<TypeInfo> types = {
3235 { "short int", sizeof(short int) },
3236 { "long long int", sizeof(long long int) },
3237 { "long int", sizeof(long int) },
3238 { "long long", sizeof(long long) },
3239 { "long double", sizeof(long double) },
3240 { "int", sizeof(int) },
3241 { "short", sizeof(short) },
3242 { "bool", sizeof(bool) },
3243 { "long", sizeof(long) },
3244 { "char", sizeof(char) },
3245 { "float", sizeof(float) },
3246 { "double", sizeof(double) },
3247 };
3248
3249 // Check if string p starts with basic types ending with a ')', such as 'signed long)' or ' float )'
3250 // and return the pointer just past the ')' and the size of the type as a tuple.
3251 // If the pattern is not found the tuple (nullptr,0) is returned.
3252 auto process_cast_or_sizeof = [](const char *p) -> std::pair<const char *,size_t>
3253 {
3254 const char *q = p;
3255 while (*q==' ' || *q=='\t') q++;
3256 bool found=false;
3257 size_t size = sizeof(int); // '(signed)' or '(unsigned)' is an int type
3258 for (const auto &sgn : signs)
3259 {
3260 if (qstrncmp(q,sgn.c_str(),sgn.length())==0) { q+=sgn.length(); found=true; }
3261 }
3262 if (!found || *q==' ' || *q=='\t' || *q==')') // continue searching
3263 {
3264 while (*q==' ' || *q=='\t') q++;
3265 for (const auto &t : types)
3266 {
3267 if (qstrncmp(q,t.name.c_str(),t.name.length())==0)
3268 {
3269 q += t.name.length();
3270 size = t.size;
3271 break;
3272 }
3273 }
3274 while (*q==' ' || *q=='\t') q++;
3275 if (*q==')') return std::make_pair(++q,size);
3276 }
3277 return std::make_pair(nullptr,0);
3278 };
int qstrncmp(const char *str1, const char *str2, size_t len)
Definition qcstring.h:75
3279
3280 //printf("removeIdsAndMarkers(%s)\n",qPrint(s));
3281 if (s.isEmpty()) return s;
3282 const char *p=s.data();
3283 bool inNum=FALSE;
3284 QCString result;
3285 if (p)
3286 {
3287 char c = 0;
3288 while ((c=*p))
3289 {
3290 if (c=='(') // potential cast, ignore it
3291 {
3292 const char *q = process_cast_or_sizeof(p+1).first;
3293 //printf("potential cast:\nin: %s\nout: %s\n",p,q);
3294 if (q)
3295 {
3296 p=q;
3297 continue;
3298 }
3299 }
3300 else if (c=='s' && literal_at(p,"sizeof")) // sizeof(...)
3301 {
3302 const char *q = p+6;
3303 while (*q==' ' || *q=='\t') q++;
3304 if (*q=='(')
3305 {
3306 auto r = process_cast_or_sizeof(q+1);
3307 //printf("sizeof:\nin: %s\nout: %zu%s\n--> sizeof=%zu\n",p,r.second,r.first,r.second);
3308 if (r.first)
3309 {
3310 result+=QCString().setNum(r.second);
3311 p=r.first;
3312 continue;
3313 }
3314 }
3315 }
QCString & setNum(short n)
Definition qcstring.h:459
bool literal_at(const char *data, const char(&str)[N])
returns TRUE iff data points to a substring that matches string literal str
Definition stringutil.h:98
3316
3317 if (c=='@') // replace @@ with @ and remove @E
3318 {
3319 if (*(p+1)=='@')
3320 {
3321 result+=c;
3322 }
3323 else if (*(p+1)=='E')
3324 {
3325 // skip
3326 }
3327 p+=2;
3328 }
3329 else if (isdigit(c)) // number
3330 {
3331 result+=c;
3332 p++;
3333 inNum=TRUE;
3334 }
3335 else if (c=='\'') // quoted character
3336 {
3337 p = processUntilMatchingTerminator(p,result);
3338 }
3339 else if (c=='d' && !inNum) // identifier starting with a 'd'
3340 {
3341 if (literal_at(p,"defined ") || literal_at(p,"defined("))
3342 // defined keyword
3343 {
3344 p+=7; // skip defined
3345 }
3346 else
3347 {
3348 result+="0L";
3349 p++;
3350 while ((c=*p) && isId(c)) p++;
3351 }
3352 }
3353 else if ((isalpha(c) || c=='_') && !inNum) // replace identifier with 0L
3354 {
3355 result+="0L";
3356 p++;
3357 while ((c=*p) && isId(c)) p++;
3358 while ((c=*p) && isspace((uint8_t)c)) p++;
3359 if (*p=='(') // undefined function macro
3360 {
3361 p++;
3362 int count=1;
3363 while ((c=*p++))
3364 {
3365 if (c=='(') count++;
3366 else if (c==')')
3367 {
3368 count--;
3369 if (count==0) break;
3370 }
3371 else if (c=='/')
3372 {
3373 char pc=c;
3374 c=*++p;
3375 if (c=='*') // start of C comment
3376 {
3377 while (*p && !(pc=='*' && c=='/')) // search end of comment
3378 {
3379 pc=c;
3380 c=*++p;
3381 }
3382 p++;
3383 }
3384 }
3385 }
3386 }
3387 }
3388 else if (c=='/') // skip C comments
3389 {
3390 char pc=c;
3391 c=*++p;
3392 if (c=='*') // start of C comment
3393 {
3394 while (*p && !(pc=='*' && c=='/')) // search end of comment
3395 {
3396 pc=c;
3397 c=*++p;
3398 }
3399 p++;
3400 }
3401 else // oops, not comment but division
3402 {
3403 result+=pc;
3404 goto nextChar;
3405 }
3406 }
3407 else
3408 {
static const char * processUntilMatchingTerminator(const char *inputStr, QCString &result)
Process string or character literal.
Definition pre.l:3194
3409nextChar:
3410 result+=c;
3411 char lc=(char)tolower(c);
3412 if (!isId(lc) && lc!='.' /*&& lc!='-' && lc!='+'*/) inNum=FALSE;
3413 p++;
3414 }
3415 }
3416 }
3417 //printf("removeIdsAndMarkers(%s)=%s\n",s,qPrint(result));
3418 return result;
3419}

◆ removeMarkers()

QCString removeMarkers ( const QCString & s)
static

replaces all occurrences of @ in s by @

assumption:
s only contains pairs of @'s

Definition at line 3425 of file pre.l.

3426{
3427 if (s.isEmpty()) return s;
3428 const char *p=s.data();
3429 QCString result;
3430 if (p)
3431 {
3432 char c = 0;
3433 while ((c=*p))
3434 {
3435 switch(c)
3436 {
3437 case '@': // replace @@ with @
3438 {
3439 if (*(p+1)=='@')
3440 {
3441 result+=c;
3442 }
3443 p+=2;
3444 }
3445 break;
3446 case '/': // skip C comments
3447 {
3448 result+=c;
3449 char pc=c;
3450 c=*++p;
3451 if (c=='*') // start of C comment
3452 {
3453 while (*p && !(pc=='*' && c=='/')) // search end of comment
3454 {
3455 if (*p=='@' && *(p+1)=='@')
3456 {
3457 result+=c;
3458 p++;
3459 }
3460 else
3461 {
3462 result+=c;
3463 }
3464 pc=c;
3465 c=*++p;
3466 }
3467 if (*p)
3468 {
3469 result+=c;
3470 p++;
3471 }
3472 }
3473 }
3474 break;
3475 case '"': // skip string literals
3476 case '\'': // skip char literals
3477 p = processUntilMatchingTerminator(p,result);
3478 break;
3479 default:
3480 {
3481 result+=c;
3482 p++;
3483 }
3484 break;
3485 }
3486 }
3487 }
3488 //printf("RemoveMarkers(%s)=%s\n",s,qPrint(result));
3489 return result;
3490}

References processUntilMatchingTerminator().

◆ replaceFunctionMacro()

bool replaceFunctionMacro ( yyscan_t yyscanner,
const QCString & expr,
QCString * rest,
int pos,
int & len,
const Define * def,
QCString & result,
int level )
static

replaces the function macro def whose argument list starts at pos in expression expr. Notice that this routine may scan beyond the expr string if needed. In that case the characters will be read from the input file. The replacement string will be returned in result and the length of the (unexpanded) argument list is stored in len.

Definition at line 2704 of file pre.l.

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

◆ resolveTrigraph()

char resolveTrigraph ( char c)
static

Definition at line 3892 of file pre.l.

3893{
3894 switch (c)
3895 {
3896 case '=': return '#';
3897 case '/': return '\\';
3898 case '\'': return '^';
3899 case '(': return '[';
3900 case ')': return ']';
3901 case '!': return '|';
3902 case '<': return '{';
3903 case '>': return '}';
3904 case '-': return '~';
3905 }
3906 return '?';
3907}

◆ returnCharToStream()

void returnCharToStream ( yyscan_t yyscanner,
char c )
static

Definition at line 2595 of file pre.l.

2596{
2597 struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
2598 unput(c);
2599}

◆ setCaseDone()

void setCaseDone ( yyscan_t yyscanner,
bool value )
static

Definition at line 2282 of file pre.l.

2283{
2284 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
2285 state->levelGuard.top()=value;
2286}

◆ setFileName()

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

Definition at line 2226 of file pre.l.

2227{
2228 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
2229 bool ambig = false;
2230 FileInfo fi(name.str());
2231 state->fileName=fi.absFilePath();
2232 state->yyFileDef=findFileDef(Doxygen::inputNameLinkedMap,state->fileName,ambig);
2233 if (state->yyFileDef==nullptr) // if this is not an input file check if it is an include file
2234 {
2235 state->yyFileDef=findFileDef(Doxygen::includeNameLinkedMap,state->fileName,ambig);
2236 }
2237 //printf("setFileName(%s) state->fileName=%s state->yyFileDef=%p\n",
2238 // name,qPrint(state->fileName),state->yyFileDef);
2239 if (state->yyFileDef && state->yyFileDef->isReference()) state->yyFileDef=nullptr;
2240 state->insideIDL = getLanguageFromFileName(state->fileName)==SrcLangExt::IDL;
2241 state->insideCS = getLanguageFromFileName(state->fileName)==SrcLangExt::CSharp;
2242 state->insideFtn = getLanguageFromFileName(state->fileName)==SrcLangExt::Fortran;
2243 EntryType section = guessSection(state->fileName);
2244 state->isSource = section.isHeader() || section.isSource();
static FileNameLinkedMap * includeNameLinkedMap
Definition doxygen.h:101
Wrapper class for the Entry type.
Definition types.h:816
SrcLangExt getLanguageFromFileName(const QCString &fileName, SrcLangExt defLang)
Definition util.cpp:5191
EntryType guessSection(const QCString &name)
Definition util.cpp:339
2245}

References Doxygen::includeNameLinkedMap, and Doxygen::inputNameLinkedMap.

◆ skipCommentMacroName()

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

Definition at line 2620 of file pre.l.

2622{
2623 bool changed = false;
2624
2625 do
2626 {
2627 changed = false;
2628 while ((cc=getCurrentChar(yyscanner,expr,rest,j))!=EOF && cc!='\n' && isspace(cc))
2629 {
2630 len++;
2631 getNextChar(yyscanner,expr,rest,j);
2632 }
2633
2634 if (cc=='/') // possible start of a comment
2635 {
2636 int prevChar = '\0';
2637 getNextChar(yyscanner,expr,rest,j);
2638 if ((cc=getCurrentChar(yyscanner,expr,rest,j))!=EOF && cc == '*') // we have a comment
2639 {
2640 while ((cc=getNextChar(yyscanner,expr,rest,j))!=EOF && cc!=0)
2641 {
2642 if (cc == '/' && prevChar == '*') break; // we have an end of comment
2643 prevChar = cc;
2644 }
2645 if (cc != EOF) changed = true;
2646 }
2647 }
2648 } while (changed);
2649}

References getCurrentChar(), and getNextChar().

◆ startCondSection()

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

Definition at line 3836 of file pre.l.

3837{
3838 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
3839 //printf("startCondSection: skip=%d stack=%d\n",state->skip,state->condStack.size());
3840 CondParser prs;
3841 bool expResult = prs.parse(state->fileName.data(),state->yyLineNr,sectId.data());
3842 state->condStack.emplace(std::make_unique<preYY_CondCtx>(state->fileName,state->yyLineNr,sectId,state->skip));
3843 if (!expResult)
3844 {
3845 state->skip=TRUE;
3846 }
3847 //printf(" expResult=%d skip=%d\n",expResult,state->skip);
Copyright (C) 1997-2015 by Dimitri van Heesch.
Definition condparser.h:28
bool parse(const QCString &fileName, int lineNr, const QCString &expr)
Copyright (C) 1997-2015 by Dimitri van Heesch.
3848}

References TRUE.

◆ stateToString()

const char * stateToString ( int state)
static

◆ stringize()

QCString stringize ( const QCString & s)
static

Definition at line 2470 of file pre.l.

2471{
2472 QCString result;
2473 uint32_t i=0;
2474 bool inString=FALSE;
2475 bool inChar=FALSE;
2476 char c,pc;
2477 while (i<s.length())
2478 {
2479 if (!inString && !inChar)
2480 {
2481 while (i<s.length() && !inString && !inChar)
2482 {
2483 c=s.at(i++);
2484 if (c=='"')
2485 {
2486 result+="\\\"";
2487 inString=TRUE;
2488 }
2489 else if (c=='\'')
2490 {
2491 result+=c;
2492 inChar=TRUE;
2493 }
2494 else
2495 {
2496 result+=c;
2497 }
2498 }
2499 }
2500 else if (inChar)
2501 {
2502 while (i<s.length() && inChar)
2503 {
2504 c=s.at(i++);
2505 if (c=='\'')
2506 {
2507 result+='\'';
2508 inChar=FALSE;
2509 }
2510 else if (c=='\\')
2511 {
2512 result+="\\\\";
2513 }
2514 else
2515 {
2516 result+=c;
2517 }
2518 }
2519 }
2520 else
2521 {
2522 pc=0;
2523 while (i<s.length() && inString)
2524 {
2525 c=s.at(i++);
2526 if (c=='"')
2527 {
2528 result+="\\\"";
2529 inString= pc=='\\';
2530 }
2531 else if (c=='\\')
2532 result+="\\\\";
2533 else
2534 result+=c;
2535 pc=c;
2536 }
2537 }
2538 }
2539 //printf("stringize '%s'->'%s'\n",qPrint(s),qPrint(result));
2540 return result;
2541}

References QCString::at(), FALSE, QCString::length(), and TRUE.

◆ unputChar()

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

Definition at line 3958 of file pre.l.

3959{
3960 //printf("unputChar(%s,%s,%d,%c)\n",qPrint(expr),rest ? rest->data() : 0,pos,c);
3961 if (pos<expr.length())
3962 {
3963 pos++;
3964 }
3965 else if (rest)
3966 {
3967 //printf(" prepending '%c' to rest!\n",c);
3968 char cs[2];cs[0]=c;cs[1]='\0';
3969 rest->prepend(cs);
3970 }
3971 else
3972 {
3973 //printf(" yyunput()='%c'\n",c);
3974 returnCharToStream(yyscanner,c);
3975 }
3976 //printf("result: unputChar(%s,%s,%d,%c)\n",qPrint(expr),rest ? rest->data() : 0,pos,c);
QCString & prepend(const char *s)
Definition qcstring.h:422
3977}

◆ yylex()

int yylex ( yyscan_t yyscanner)

Definition at line 485 of file pre.l.

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

◆ yyread()

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

Definition at line 2205 of file pre.l.

2206{
2207 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
2208 int bytesInBuf = static_cast<int>(state->inputBuf->size())-state->inputBufPos;
2209 int bytesToCopy = std::min(max_size,bytesInBuf);
2210 memcpy(buf,state->inputBuf->data()+state->inputBufPos,bytesToCopy);
2211 state->inputBufPos+=bytesToCopy;
2212 return bytesToCopy;
2213}

Variable Documentation

◆ g_debugMutex

std::mutex g_debugMutex
static

Definition at line 233 of file pre.l.

◆ g_defineManager

DefineManager g_defineManager
static

Definition at line 236 of file pre.l.

Referenced by checkAndOpenFile().

◆ g_globalDefineMutex

std::mutex g_globalDefineMutex
static

Definition at line 234 of file pre.l.

Referenced by checkAndOpenFile().

◆ g_updateGlobals

std::mutex g_updateGlobals
static

Definition at line 235 of file pre.l.