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

Go to the source code of this file.

Classes

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

Macros

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

Typedefs

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

Functions

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

Variables

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

Macro Definition Documentation

◆ MAX_EXPANSION_DEPTH

#define MAX_EXPANSION_DEPTH   50

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

◆ YY_NO_UNISTD_H

#define YY_NO_UNISTD_H   1

Definition at line 66 of file pre.l.

◆ YY_TYPEDEF_YY_SCANNER_T

#define YY_TYPEDEF_YY_SCANNER_T

Definition at line 22 of file pre.l.

Typedef Documentation

◆ DefineMap

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

A dictionary of managed Define objects.

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

3570{
3571 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
3572 Define def;
3573 def.name = state->defName;
3574 def.definition = state->defText.stripWhiteSpace();
3575 def.nargs = state->defArgs;
3576 def.fileName = state->fileName;
3577 def.fileDef = state->yyFileDef;
3578 def.lineNr = state->yyLineNr-state->yyMLines;
3579 def.columnNr = state->yyColNr;
3580 def.varArgs = state->defVarArgs;
3581 //printf("newDefine: %s %s file: %s\n",qPrint(def.name),qPrint(def.definition),
3582 // def.fileDef ? qPrint(def.fileDef->name()) : qPrint(def.fileName));
3583 //printf("newDefine: '%s'->'%s'\n",qPrint(def.name),qPrint(def.definition));
3584 if (!def.name.isEmpty() &&
3586 {
3587 def.isPredefined=TRUE;
3589 }
3590 auto it = state->localDefines.find(def.name.str());
3591 if (it!=state->localDefines.end()) // redefine
3592 {
3593 state->localDefines.erase(it);
3594 }
3595 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
3596}

References Doxygen::expandAsDefinedSet, and TRUE.

◆ addMacroDefinition()

void addMacroDefinition ( yyscan_t yyscanner)
static

Definition at line 3598 of file pre.l.

3599{
3600 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
3601 if (state->skip) return; // do not add this define as it is inside a
3602 // conditional section (cond command) that is disabled.
3603
3604 Define define;
3605 define.fileName = state->fileName;
3606 define.lineNr = state->yyLineNr - state->yyMLines;
3607 define.columnNr = state->yyColNr;
3608 define.name = state->defName;
3609 define.args = state->defArgsStr;
3610 define.fileDef = state->inputFileDef;
QCString args
Definition define.h:36
3611
3612 QCString litText = state->defLitText;
3613 int l=litText.find('\n');
3614 if (l>0 && litText.left(l).stripWhiteSpace()=="\\")
3615 {
3616 // strip first line if it only contains a slash
3617 litText = litText.right(litText.length()-l-1);
3618 }
3619 else if (l>0)
3620 {
3621 // align the items on the first line with the items on the second line
3622 int k=l+1;
3623 const char *p=litText.data()+k;
3624 char c = 0;
3625 while ((c=*p++) && (c==' ' || c=='\t')) k++;
3626 litText=litText.mid(l+1,k-l-1)+litText.stripWhiteSpace();
3627 }
3628 QCString litTextStripped = state->defLitText.stripWhiteSpace();
3629 if (litTextStripped.contains('\n')>=1)
3630 {
3631 define.definition = litText;
3632 }
3633 else
3634 {
3635 define.definition = litTextStripped;
3636 }
3637 {
3638 state->macroDefinitions.push_back(define);
3639 }
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
3640}

◆ addSeparatorsIfNeeded()

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

Definition at line 3023 of file pre.l.

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

◆ addTillEndOfString()

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

Definition at line 2606 of file pre.l.

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

References getNextChar(), and term.

◆ checkAndOpenFile()

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

Definition at line 2294 of file pre.l.

2295{
2296 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
2297 alreadyProcessed = FALSE;
2298 std::unique_ptr<FileState> fs;
2299 //printf("checkAndOpenFile(%s)\n",qPrint(fileName));
2300 FileInfo fi(fileName.str());
2301 if (fi.exists() && fi.isFile())
2302 {
2303 const StringVector &exclPatterns = Config_getList(EXCLUDE_PATTERNS);
2304 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:5686
2305
2306 QCString absName = fi.absFilePath();
2307
2308 // global guard
2309 if (state->curlyCount==0) // not #include inside { ... }
2310 {
2311 std::lock_guard<std::mutex> lock(g_globalDefineMutex);
2312 if (g_defineManager.alreadyProcessed(absName.str()))
2313 {
2314 alreadyProcessed = TRUE;
2315 //printf(" already included 1\n");
2316 return 0; // already done
2317 }
2318 }
2319 // check include stack for absName
static std::mutex g_globalDefineMutex
Definition pre.l:232
static DefineManager g_defineManager
Definition pre.l:234
2320
2321 alreadyProcessed = std::any_of(
2322 state->includeStack.begin(),
2323 state->includeStack.end(),
2324 [absName](const std::unique_ptr<FileState> &lfs)
2325 { return lfs->fileName==absName; }
2326 );
2327
2328 if (alreadyProcessed)
2329 {
2330 //printf(" already included 2\n");
2331 return nullptr;
2332 }
2333 //printf("#include %s\n",qPrint(absName));
2334
2335 fs = std::make_unique<FileState>();
2336 if (!readInputFile(absName,fs->fileBuf))
2337 { // error
2338 //printf(" error reading\n");
2339 fs.reset();
2340 }
2341 else
2342 {
2343 addTerminalCharIfMissing(fs->fileBuf,'\n');
2344 fs->oldFileBuf = state->inputBuf;
2345 fs->oldFileBufPos = state->inputBufPos;
2346 }
2347 }
2348 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:5532
2349}

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

3508{
3509 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
3510 QCString e=expr;
3511 QCString ee=expr;
3512 ee = removeMarkers(ee);
3513 state->expanded.clear();
3514 expandExpression(yyscanner,e,nullptr,0,0);
3515 //printf("after expansion '%s'\n",qPrint(e));
3516 e = removeIdsAndMarkers(e);
3517 if (e.isEmpty()) return FALSE;
3518 //printf("parsing '%s'\n",qPrint(e));
3519 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:3055
static QCString removeIdsAndMarkers(const QCString &s)
Definition pre.l:3241
static QCString removeMarkers(const QCString &s)
Definition pre.l:3436
3520}

References FALSE.

◆ decrLevel()

void decrLevel ( yyscan_t yyscanner)
static

Definition at line 2259 of file pre.l.

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

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

◆ determineBlockName()

void determineBlockName ( yyscan_t yyscanner)
static

Definition at line 3690 of file pre.l.

3691{
3692 struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
3693 yyextra->fenceSize=0;
3694 char c=0;
3695 if (yytext[1]=='f' && ((c=yytext[2])=='[' || c=='{' || c=='(' || c=='$'))
3696 {
3697 switch (c)
3698 {
3699 case '[': yyextra->blockName="]"; break;
3700 case '{': yyextra->blockName="}"; break;
3701 case '(': yyextra->blockName=")"; break;
3702 case '$': yyextra->blockName="$"; break;
3703 default: break;
3704 }
3705 yyextra->blockName=yyextra->blockName.stripWhiteSpace();
3706 }
3707 else
3708 {
3709 QCString bn=QCString(&yytext[1]).stripWhiteSpace();
3710 if (bn=="startuml")
3711 {
3712 yyextra->blockName="uml";
3713 }
3714 else
3715 {
3716 int i = bn.find('{'); // for \code{.c}
3717 if (i!=-1) bn=bn.left(i).stripWhiteSpace();
3718 yyextra->blockName=bn;
3719 }
3720 }
3721}

◆ endCondSection()

void endCondSection ( yyscan_t yyscanner)
static

Definition at line 3890 of file pre.l.

3891{
3892 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
3893 if (state->condStack.empty())
3894 {
3895 warn(state->fileName,state->yyLineNr,"the \\endcond does not have a corresponding \\cond in this file");
3896 state->skip=FALSE;
3897 }
3898 else
3899 {
3900 const std::unique_ptr<preYY_CondCtx> &ctx = state->condStack.top();
3901 state->skip=ctx->skip;
3902 state->condStack.pop();
3903 }
3904 //printf("endCondSection: skip=%d stack=%d\n",state->skip,state->condStack.count());
3905}

References FALSE.

◆ escapeAt()

QCString escapeAt ( const QCString & text)
static

Definition at line 3917 of file pre.l.

3918{
3919 QCString result;
3920 if (!text.isEmpty())
3921 {
3922 char c = 0;
3923 const char *p=text.data();
3924 while ((c=*p++))
3925 {
3926 if (c=='@') result+="@@"; else result+=c;
3927 }
3928 }
3929 return result;
3930}

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

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

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

3527{
3528 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3529 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
3530 state->prevChar = yyscanner->yytext_r > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ? *(yyscanner->yytext_r-1) : 0;
3531 QCString n=name;
3532 state->expanded.clear();
3533 expandExpression(yyscanner,n,nullptr,0,0);
3534 n=removeMarkers(n);
3535 state->prevChar=0;
3536 //printf("expandMacro '%s'->'%s'\n",qPrint(name),qPrint(n));
3537 return n;
void clear()
Definition qcstring.h:182
3538}

◆ expandStandardMacro()

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

Definition at line 3540 of file pre.l.

3541{
3542 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3543 QCString resultExpr;
3544 if (name == "__LINE__")
3545 {
3546 return QCString().setNum(yyextra->yyLineNr);
3547 }
3548 else if (name == "__FILE__")
3549 {
3550 resultExpr = "\"";
3551 resultExpr += yyextra->fileName;
3552 resultExpr += "\"";
3553 }
3554 else if (name == "__DATE__")
3555 {
3556 resultExpr = "\"";
3557 resultExpr += __DATE__;
3558 resultExpr += "\"";
3559 }
3560 else if (name == "__TIME__")
3561 {
3562 resultExpr = "\"";
3563 resultExpr += __TIME__;
3564 resultExpr += "\"";
3565 }
3566 return resultExpr;
QCString & setNum(short n)
Definition qcstring.h:459
3567}

References QCString::setNum().

◆ expandVAOpt()

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

Definition at line 2657 of file pre.l.

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

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

◆ extractTrailingComment()

QCString extractTrailingComment ( const QCString & s)
static

Definition at line 2425 of file pre.l.

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

◆ extraSpacing()

void extraSpacing ( yyscan_t yyscanner)
inlinestatic

Definition at line 3677 of file pre.l.

3678{
3679 struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
3680 if (!yyextra->defContinue) return;
3681 for (int i=0; i< (int)yyleng; i++)
3682 {
3683 if (yytext[i] == '\t')
3684 yyextra->defExtraSpacing+='\t';
3685 else
3686 yyextra->defExtraSpacing+=' ';
3687 }
3688}

◆ findFile()

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

Definition at line 2351 of file pre.l.

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

References Portable::isAbsolutePath().

◆ forceEndCondSection()

void forceEndCondSection ( yyscan_t yyscanner)
static

Definition at line 3907 of file pre.l.

3908{
3909 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
3910 while (!state->condStack.empty())
3911 {
3912 state->condStack.pop();
3913 }
3914 state->skip=FALSE;
3915}

◆ getCurrentChar()

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

Definition at line 3975 of file pre.l.

3976{
3977 //printf("getCurrentChar(%s,%s,%d)\n",qPrint(expr),rest ? rest->data() : 0,pos);
3978 if (pos<expr.length())
3979 {
3980 //printf("%c=expr()\n",expr.at(pos));
3981 return expr.at(pos);
3982 }
3983 else if (rest && !rest->isEmpty())
3984 {
3985 int cc=rest->at(0);
3986 //printf("%c=rest\n",cc);
3987 return cc;
3988 }
3989 else
3990 {
3991 int cc=yyinput(yyscanner);
3992 returnCharToStream(yyscanner,(char)cc);
3993 //printf("%c=yyinput()\n",cc);
3994 return cc;
3995 }
static void returnCharToStream(yyscan_t yyscanner, char c)
Definition pre.l:2600
3996}

References QCString::at().

Referenced by skipCommentMacroName().

◆ getFenceSize()

yy_size_t getFenceSize ( char * txt,
yy_size_t leng )
static

Definition at line 2220 of file pre.l.

2221{
2222 yy_size_t fenceSize = 0;
2223 for (size_t i = 0; i < leng; i++)
2224 {
2225 if (txt[i] != ' ' && txt[i] != '*' && txt[i] != '\t') break;
2226 fenceSize++;
2227 }
2228 return leng-fenceSize;
2229}

◆ getLexerFILE()

const char * getLexerFILE ( )
inlinestatic

Definition at line 351 of file pre.l.

351{return __FILE__;}

◆ getNextChar()

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

Definition at line 3952 of file pre.l.

3953{
3954 //printf("getNextChar(%s,%s,%d)\n",qPrint(expr),rest ? rest->data() : 0,pos);
3955 if (pos<expr.length())
3956 {
3957 //printf(" expr()='%c'\n",expr.at(pos));
3958 return expr.at(pos++);
3959 }
3960 else if (rest && !rest->isEmpty())
3961 {
3962 int cc=rest->at(0);
3963 *rest=rest->right(rest->length()-1);
3964 //printf(" rest='%c'\n",cc);
3965 return cc;
3966 }
3967 else
3968 {
3969 int cc=yyinput(yyscanner);
3970 //printf(" yyinput()='%c' %d\n",cc,EOF);
3971 return cc;
3972 }
3973}

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

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

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

◆ incrLevel()

void incrLevel ( yyscan_t yyscanner)
static

Definition at line 2252 of file pre.l.

2253{
2254 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
2255 state->levelGuard.push(false);
2256 //printf("%s line %d: incrLevel %d\n",qPrint(yyextra->fileName),yyextra->yyLineNr,yyextra->levelGuard.size());
2257}

◆ initPredefined()

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

Definition at line 4051 of file pre.l.

4052{
4053 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
4054
4055 // add predefined macros
4056 const StringVector &predefList = Config_getList(PREDEFINED);
4057 for (const auto &ds : predefList)
4058 {
4059 size_t i_equals=ds.find('=');
4060 size_t i_obrace=ds.find('(');
4061 size_t i_cbrace=ds.find(')');
4062 bool nonRecursive = i_equals!=std::string::npos && i_equals>0 && ds[i_equals-1]==':';
4063
4064 if ((i_obrace==0) || (i_equals==0) || (i_equals==1 && ds[i_equals-1]==':'))
4065 {
4066 continue; // no define name
4067 }
4068
4069 if (i_obrace<i_equals && i_cbrace<i_equals &&
4070 i_obrace!=std::string::npos && i_cbrace!=std::string::npos &&
4071 i_obrace<i_cbrace
4072 ) // predefined function macro definition
4073 {
4074 static const reg::Ex reId(R"(\a\w*)");
4075 std::map<std::string,int> argMap;
4076 std::string args = ds.substr(i_obrace+1,i_cbrace-i_obrace-1); // part between ( and )
4077 bool hasVarArgs = args.find("...")!=std::string::npos;
4078 //printf("predefined function macro '%s'\n",qPrint(ds));
4079 int count = 0;
4080 reg::Iterator arg_it(args,reId,0);
4081 reg::Iterator arg_end;
4082 // gather the formal arguments in a dictionary
4083 for (; arg_it!=arg_end; ++arg_it)
4084 {
4085 argMap.emplace(arg_it->str(),count++);
4086 }
4087 if (hasVarArgs) // add the variable argument if present
4088 {
4089 argMap.emplace("__VA_ARGS__",count++);
4090 }
Class representing a regular expression.
Definition regex.h:39
Class to iterate through matches.
Definition regex.h:230
4091
4092 // strip definition part
4093 std::string definition;
4094 std::string in=ds.substr(i_equals+1);
4095 reg::Iterator re_it(in,reId);
4096 reg::Iterator re_end;
4097 size_t i=0;
4098 // substitute all occurrences of formal arguments by their
4099 // corresponding markers
4100 for (; re_it!=re_end; ++re_it)
4101 {
4102 const auto &match = *re_it;
4103 size_t pi = match.position();
4104 size_t l = match.length();
4105 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
4106
4107 auto it = argMap.find(match.str());
4108 if (it!=argMap.end())
4109 {
4110 int argIndex = it->second;
4111 QCString marker;
4112 marker.sprintf(" @%d ",argIndex);
4113 definition+=marker.str();
4114 }
4115 else
4116 {
4117 definition+=match.str();
4118 }
4119 i=pi+l;
4120 }
4121 definition+=in.substr(i);
QCString & sprintf(const char *format,...)
Definition qcstring.cpp:29
4122
4123 // add define definition to the dictionary of defines for this file
4124 std::string dname = ds.substr(0,i_obrace);
4125 if (!dname.empty())
4126 {
4127 Define def;
4128 def.name = dname;
4129 def.definition = definition;
4130 def.nargs = count;
4131 def.isPredefined = TRUE;
4132 def.nonRecursive = nonRecursive;
4133 def.fileDef = state->yyFileDef;
4134 def.fileName = fileName;
4135 def.varArgs = hasVarArgs;
4136 state->contextDefines.emplace(def.name.str(),def);
4137
4138 //printf("#define '%s' '%s' #nargs=%d hasVarArgs=%d\n",
4139 // qPrint(def.name),qPrint(def.definition),def.nargs,def.varArgs);
4140 }
4141 }
4142 else if (!ds.empty()) // predefined non-function macro definition
4143 {
4144 //printf("predefined normal macro '%s'\n",qPrint(ds));
4145 Define def;
4146 if (i_equals==std::string::npos) // simple define without argument
4147 {
4148 def.name = ds;
4149 def.definition = "1"; // substitute occurrences by 1 (true)
4150 }
4151 else // simple define with argument
4152 {
4153 int ine=static_cast<int>(i_equals) - (nonRecursive ? 1 : 0);
4154 def.name = ds.substr(0,ine);
4155 def.definition = ds.substr(i_equals+1);
4156 }
4157 if (!def.name.isEmpty())
4158 {
4159 def.nargs = -1;
4160 def.isPredefined = TRUE;
4161 def.nonRecursive = nonRecursive;
4162 def.fileDef = state->yyFileDef;
4163 def.fileName = fileName;
4164 state->contextDefines.emplace(def.name.str(),def);
4165 }
4166 }
4167 }
4168}

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

4023{
4024 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
4025
4026 bool undef = false;
4027 auto findDefine = [&undef,&name](DefineMap &map)
4028 {
4029 Define *d=nullptr;
4030 auto it = map.find(name.str());
4031 if (it!=map.end())
4032 {
4033 d = &it->second;
4034 if (d->undef)
4035 {
4036 undef=true;
4037 d=nullptr;
4038 }
4039 }
4040 return d;
4041 };
bool undef
Definition define.h:41
std::map< std::string, Define > DefineMap
A dictionary of managed Define objects.
Definition pre.l:107
4042
4043 Define *def = findDefine(state->localDefines);
4044 if (def==nullptr && !undef)
4045 {
4046 def = findDefine(state->contextDefines);
4047 }
4048 return def;
4049}

◆ otherCaseDone()

bool otherCaseDone ( yyscan_t yyscanner)
static

Definition at line 2273 of file pre.l.

2274{
2275 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
2276 if (state->levelGuard.empty())
2277 {
2278 warn(state->fileName,state->yyLineNr,"Found an #else without a preceding #if.");
2279 return TRUE;
2280 }
2281 else
2282 {
2283 return state->levelGuard.top();
2284 }
2285}

References TRUE.

◆ outputArray()

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

Definition at line 3648 of file pre.l.

3649{
3650 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
3651 if (state->includeStack.empty() || state->curlyCount>0) (*state->outputBuf)+=std::string_view(a,len);
3652}

◆ outputChar()

void outputChar ( yyscan_t yyscanner,
char c )
inlinestatic

Definition at line 3642 of file pre.l.

3643{
3644 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
3645 if (state->includeStack.empty() || state->curlyCount>0) (*state->outputBuf)+=c;
3646}

Referenced by outputSpaces().

◆ outputSpace()

void outputSpace ( yyscan_t yyscanner,
char c )
inlinestatic

Definition at line 3660 of file pre.l.

3661{
3662 if (c=='\t') outputChar(yyscanner,'\t');
3663 else outputChar(yyscanner,' ');
static void outputChar(yyscan_t yyscanner, char c)
Definition pre.l:3642
3664}

◆ outputSpaces()

void outputSpaces ( yyscan_t yyscanner,
char * s )
inlinestatic

Definition at line 3666 of file pre.l.

3667{
3668 const char *p=s;
3669 char c = 0;
3670 while ((c=*p++))
3671 {
3672 if (c=='\t') outputChar(yyscanner,'\t');
3673 else outputChar(yyscanner,' ');
3674 }
3675}

References outputChar().

◆ outputString()

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

Definition at line 3654 of file pre.l.

3655{
3656 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
3657 if (state->includeStack.empty() || state->curlyCount>0) (*state->outputBuf)+=a.str();
3658}

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

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

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

3206{
3207 if (inputStr==nullptr) return inputStr;
3208 char term = *inputStr; // capture start character of the literal
3209 if (term!='\'' && term!='"') return inputStr; // not a valid literal
3210 char c=term;
3211 // output start character
3212 result+=c;
3213 inputStr++;
3214 while ((c=*inputStr)) // while inside the literal
3215 {
3216 if (c==term) // found end marker of the literal
3217 {
3218 // output end character and stop
3219 result+=c;
3220 inputStr++;
3221 break;
3222 }
3223 else if (c=='\\') // escaped character, process next character
3224 // as well without checking for end marker.
3225 {
3226 result+=c;
3227 inputStr++;
3228 c=*inputStr;
3229 if (c==0) break; // unexpected end of string after escape character
3230 }
3231 result+=c;
3232 inputStr++;
3233 }
3234 return inputStr;
3235}

References term.

Referenced by removeMarkers().

◆ readIncludeFile()

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

Definition at line 3723 of file pre.l.

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

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

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

◆ removeMarkers()

QCString removeMarkers ( const QCString & s)
static

replaces all occurrences of @ in s by @

assumption:
s only contains pairs of @'s

Definition at line 3436 of file pre.l.

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

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

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

◆ resolveTrigraph()

char resolveTrigraph ( char c)
static

Definition at line 3932 of file pre.l.

3933{
3934 switch (c)
3935 {
3936 case '=': return '#';
3937 case '/': return '\\';
3938 case '\'': return '^';
3939 case '(': return '[';
3940 case ')': return ']';
3941 case '!': return '|';
3942 case '<': return '{';
3943 case '>': return '}';
3944 case '-': return '~';
3945 }
3946 return '?';
3947}

◆ returnCharToStream()

void returnCharToStream ( yyscan_t yyscanner,
char c )
static

Definition at line 2600 of file pre.l.

2601{
2602 struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
2603 unput(c);
2604}

◆ setCaseDone()

void setCaseDone ( yyscan_t yyscanner,
bool value )
static

Definition at line 2287 of file pre.l.

2288{
2289 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
2290 state->levelGuard.top()=value;
2291}

◆ setFileName()

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

Definition at line 2231 of file pre.l.

2232{
2233 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
2234 bool ambig = false;
2235 FileInfo fi(name.str());
2236 state->fileName=fi.absFilePath();
2237 state->yyFileDef=findFileDef(Doxygen::inputNameLinkedMap,state->fileName,ambig);
2238 if (state->yyFileDef==nullptr) // if this is not an input file check if it is an include file
2239 {
2240 state->yyFileDef=findFileDef(Doxygen::includeNameLinkedMap,state->fileName,ambig);
2241 }
2242 //printf("setFileName(%s) state->fileName=%s state->yyFileDef=%p\n",
2243 // name,qPrint(state->fileName),state->yyFileDef);
2244 if (state->yyFileDef && state->yyFileDef->isReference()) state->yyFileDef=nullptr;
2245 state->insideIDL = getLanguageFromFileName(state->fileName)==SrcLangExt::IDL;
2246 state->insideCS = getLanguageFromFileName(state->fileName)==SrcLangExt::CSharp;
2247 state->insideFtn = getLanguageFromFileName(state->fileName)==SrcLangExt::Fortran;
2248 EntryType section = guessSection(state->fileName);
2249 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:5193
EntryType guessSection(const QCString &name)
Definition util.cpp:338
2250}

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

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

References getCurrentChar(), and getNextChar().

◆ startCondSection()

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

Definition at line 3876 of file pre.l.

3877{
3878 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
3879 //printf("startCondSection: skip=%d stack=%d\n",state->skip,state->condStack.size());
3880 CondParser prs;
3881 bool expResult = prs.parse(state->fileName.data(),state->yyLineNr,sectId.data());
3882 state->condStack.emplace(std::make_unique<preYY_CondCtx>(state->fileName,state->yyLineNr,sectId,state->skip));
3883 if (!expResult)
3884 {
3885 state->skip=TRUE;
3886 }
3887 //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.
3888}

References TRUE.

◆ stateToString()

const char * stateToString ( int state)
static

◆ stringize()

QCString stringize ( const QCString & s)
static

Definition at line 2475 of file pre.l.

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

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

3999{
4000 //printf("unputChar(%s,%s,%d,%c)\n",qPrint(expr),rest ? rest->data() : 0,pos,c);
4001 if (pos<expr.length())
4002 {
4003 pos++;
4004 }
4005 else if (rest)
4006 {
4007 //printf(" prepending '%c' to rest!\n",c);
4008 char cs[2];cs[0]=c;cs[1]='\0';
4009 rest->prepend(cs);
4010 }
4011 else
4012 {
4013 //printf(" yyunput()='%c'\n",c);
4014 returnCharToStream(yyscanner,c);
4015 }
4016 //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
4017}

◆ yylex()

int yylex ( yyscan_t yyscanner)

Definition at line 484 of file pre.l.

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

◆ yyread()

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

Definition at line 2210 of file pre.l.

2211{
2212 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
2213 int bytesInBuf = static_cast<int>(state->inputBuf->size())-state->inputBufPos;
2214 int bytesToCopy = std::min(max_size,bytesInBuf);
2215 memcpy(buf,state->inputBuf->data()+state->inputBufPos,bytesToCopy);
2216 state->inputBufPos+=bytesToCopy;
2217 return bytesToCopy;
2218}

Variable Documentation

◆ g_debugMutex

std::mutex g_debugMutex
static

Definition at line 231 of file pre.l.

◆ g_defineManager

DefineManager g_defineManager
static

Definition at line 234 of file pre.l.

Referenced by checkAndOpenFile().

◆ g_globalDefineMutex

std::mutex g_globalDefineMutex
static

Definition at line 232 of file pre.l.

Referenced by checkAndOpenFile().

◆ g_updateGlobals

std::mutex g_updateGlobals
static

Definition at line 233 of file pre.l.