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 "doxygen_lex.h"
#include "pre.l.h"
+ Include dependency graph for pre.l:

Go to the source code of this file.

Classes

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

Macros

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

Typedefs

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

Functions

static const char * stateToString (int state)
 
static QCString escapeAt (const QCString &text)
 
static QCString extractTrailingComment (const QCString &s)
 
static char resolveTrigraph (char c)
 
static void outputArray (yyscan_t yyscanner, const char *a, yy_size_t len)
 
static void outputString (yyscan_t yyscanner, const QCString &s)
 
static void outputChar (yyscan_t yyscanner, char c)
 
static void outputSpaces (yyscan_t yyscanner, char *s)
 
static void outputSpace (yyscan_t yyscanner, char c)
 
static void extraSpacing (yyscan_t yyscanner)
 
static QCString expandMacro (yyscan_t yyscanner, const QCString &name)
 
static void readIncludeFile (yyscan_t yyscanner, const QCString &inc)
 
static void incrLevel (yyscan_t yyscanner)
 
static void decrLevel (yyscan_t yyscanner)
 
static void setCaseDone (yyscan_t yyscanner, bool value)
 
static bool otherCaseDone (yyscan_t yyscanner)
 
static bool computeExpression (yyscan_t yyscanner, const QCString &expr)
 
static void startCondSection (yyscan_t yyscanner, const QCString &sectId)
 
static void endCondSection (yyscan_t yyscanner)
 
static void addMacroDefinition (yyscan_t yyscanner)
 
static void addDefine (yyscan_t yyscanner)
 
static void setFileName (yyscan_t yyscanner, const QCString &name)
 
static int yyread (yyscan_t yyscanner, char *buf, int max_size)
 
static DefineisDefined (yyscan_t yyscanner, const QCString &name)
 Returns a reference to a Define object given its name or 0 if the Define does not exist.
 
static void determineBlockName (yyscan_t yyscanner)
 
static yy_size_t getFenceSize (char *txt, yy_size_t leng)
 
static const char * getLexerFILE ()
 
int yylex (yyscan_t yyscanner)
 
static std::unique_ptr< FileStatecheckAndOpenFile (yyscan_t yyscanner, const QCString &fileName, bool &alreadyProcessed)
 
static std::unique_ptr< FileStatefindFile (yyscan_t yyscanner, const QCString &fileName, bool localInclude, bool &alreadyProcessed)
 
static int getNextChar (yyscan_t yyscanner, const QCString &expr, QCString *rest, uint32_t &pos)
 
static int getCurrentChar (yyscan_t yyscanner, const QCString &expr, QCString *rest, uint32_t pos)
 
static void unputChar (yyscan_t yyscanner, const QCString &expr, QCString *rest, uint32_t &pos, char c)
 
static bool expandExpression (yyscan_t yyscanner, QCString &expr, QCString *rest, int pos, int level)
 
static QCString stringize (const QCString &s)
 
static void processConcatOperators (QCString &expr)
 
static void returnCharToStream (yyscan_t yyscanner, char c)
 
static void addTillEndOfString (yyscan_t yyscanner, const QCString &expr, QCString *rest, uint32_t &pos, char term, QCString &arg)
 
static void skipCommentMacroName (yyscan_t yyscanner, const QCString &expr, QCString *rest, int &cc, uint32_t &j, int &len)
 
static 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 2877 of file pre.l.

Referenced by expandExpression().

◆ YY_INPUT

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

Definition at line 348 of file pre.l.

◆ YY_NO_UNISTD_H

#define YY_NO_UNISTD_H   1

Definition at line 67 of file pre.l.

◆ YY_TYPEDEF_YY_SCANNER_T

#define YY_TYPEDEF_YY_SCANNER_T

Definition at line 22 of file pre.l.

Typedef Documentation

◆ DefineMap

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

A dictionary of managed Define objects.

Definition at line 108 of file pre.l.

◆ yyscan_t

typedef yyguts_t* yyscan_t

Definition at line 24 of file pre.l.

Function Documentation

◆ addDefine()

static void addDefine ( yyscan_t yyscanner)
static

Definition at line 3382 of file pre.l.

3383{
3384 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
3385 Define def;
3386 def.name = state->defName;
3387 def.definition = state->defText.stripWhiteSpace();
3388 def.nargs = state->defArgs;
3389 def.fileName = state->fileName;
3390 def.fileDef = state->yyFileDef;
3391 def.lineNr = state->yyLineNr-state->yyMLines;
3392 def.columnNr = state->yyColNr;
3393 def.varArgs = state->defVarArgs;
3394 //printf("newDefine: %s %s file: %s\n",qPrint(def.name),qPrint(def.definition),
3395 // def.fileDef ? qPrint(def.fileDef->name()) : qPrint(def.fileName));
3396 //printf("newDefine: '%s'->'%s'\n",qPrint(def.name),qPrint(def.definition));
3397 if (!def.name.isEmpty() &&
3399 {
3400 def.isPredefined=TRUE;
3402 }
3403 auto it = state->localDefines.find(def.name.str());
3404 if (it!=state->localDefines.end()) // redefine
3405 {
3406 state->localDefines.erase(it);
3407 }
3408 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:119
bool isEmpty() const
Returns TRUE iff the string is empty.
Definition qcstring.h:150
QCString stripWhiteSpace() const
returns a copy of this string with leading and trailing whitespace removed
Definition qcstring.h:245
const std::string & str() const
Definition qcstring.h:537
#define TRUE
Definition qcstring.h:37
3409}

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

◆ addMacroDefinition()

static void addMacroDefinition ( yyscan_t yyscanner)
static

Definition at line 3411 of file pre.l.

3412{
3413 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
3414 if (state->skip) return; // do not add this define as it is inside a
3415 // conditional section (cond command) that is disabled.
3416
3417 Define define;
3418 define.fileName = state->fileName;
3419 define.lineNr = state->yyLineNr - state->yyMLines;
3420 define.columnNr = state->yyColNr;
3421 define.name = state->defName;
3422 define.args = state->defArgsStr;
3423 define.fileDef = state->inputFileDef;
QCString args
Definition define.h:36
3424
3425 QCString litText = state->defLitText;
3426 int l=litText.find('\n');
3427 if (l>0 && litText.left(l).stripWhiteSpace()=="\\")
3428 {
3429 // strip first line if it only contains a slash
3430 litText = litText.right(litText.length()-l-1);
3431 }
3432 else if (l>0)
3433 {
3434 // align the items on the first line with the items on the second line
3435 int k=l+1;
3436 const char *p=litText.data()+k;
3437 char c = 0;
3438 while ((c=*p++) && (c==' ' || c=='\t')) k++;
3439 litText=litText.mid(l+1,k-l-1)+litText.stripWhiteSpace();
3440 }
3441 QCString litTextStripped = state->defLitText.stripWhiteSpace();
3442 if (litTextStripped.contains('\n')>=1)
3443 {
3444 define.definition = litText;
3445 }
3446 else
3447 {
3448 define.definition = litTextStripped;
3449 }
3450 {
3451 state->macroDefinitions.push_back(define);
3452 }
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:153
QCString mid(size_t index, size_t len=static_cast< size_t >(-1)) const
Definition qcstring.h:226
QCString right(size_t len) const
Definition qcstring.h:219
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:159
QCString left(size_t len) const
Definition qcstring.h:214
int contains(char c, bool cs=TRUE) const
Definition qcstring.cpp:143
3453}

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

◆ addSeparatorsIfNeeded()

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

Definition at line 2879 of file pre.l.

2880{
2881 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
2882 if (!state->nospaces)
2883 {
2884 // peek back in the stream, for a colon character
2885 char ccPrev = pos==0 || (int)expr.length()<pos ? state->prevChar : expr.at(pos-1);
2886 QCString leftSpace = ccPrev!=':' && ccPrev!=' ' ? " " : "";
2887 int ccNext = 0;
2888 restExpr=restExpr.stripWhiteSpace();
2889 if (restExpr.isEmpty()) // peek ahead in the stream for non-whitespace
2890 {
2891 uint32_t j=(uint32_t)resultExpr.length();
2892 while ((ccNext=getNextChar(yyscanner,resultExpr,nullptr,j))!=EOF && ccNext==' ') { }
2893 if (ccNext != EOF) unputChar(yyscanner,resultExpr,nullptr,j,(char)ccNext);
2894 }
2895 else // take first char from remainder
2896 {
2897 ccNext=restExpr.at(0);
2898 }
2899 // don't add whitespace before a colon
2900 QCString rightSpace = ccNext!=':' && ccNext!=' ' ? " " : "";
2901 //printf("ccPrev='%c' ccNext='%c' p=%d expr=%zu restExpr='%s' left='%s' right='%s'\n",
2902 // ccPrev,ccNext,pos,expr.length(),qPrint(restExpr),qPrint(leftSpace),qPrint(rightSpace));
2903 resultExpr=leftSpace+resultExpr+rightSpace;
2904 }
char & at(size_t i)
Returns a reference to the character at index i.
Definition qcstring.h:578
static int getNextChar(yyscan_t yyscanner, const QCString &expr, QCString *rest, uint32_t &pos)
Definition pre.l:3765
static void unputChar(yyscan_t yyscanner, const QCString &expr, QCString *rest, uint32_t &pos, char c)
Definition pre.l:3811
2905}

References QCString::at(), getNextChar(), QCString::isEmpty(), QCString::length(), QCString::stripWhiteSpace(), and unputChar().

Referenced by expandExpression().

◆ addTillEndOfString()

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

Definition at line 2523 of file pre.l.

2525{
2526 int cc;
2527 while ((cc=getNextChar(yyscanner,expr,rest,pos))!=EOF && cc!=0)
2528 {
2529 if (cc=='\\') arg+=(char)cc,cc=getNextChar(yyscanner,expr,rest,pos);
2530 else if (cc==term) return;
2531 arg+=(char)cc;
2532 }
#define term(fmt,...)
Definition message.h:94
2533}

References getNextChar(), and term.

Referenced by replaceFunctionMacro().

◆ checkAndOpenFile()

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

Definition at line 2212 of file pre.l.

2213{
2214 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
2215 alreadyProcessed = FALSE;
2216 std::unique_ptr<FileState> fs;
2217 //printf("checkAndOpenFile(%s)\n",qPrint(fileName));
2218 FileInfo fi(fileName.str());
2219 if (fi.exists() && fi.isFile())
2220 {
2221 const StringVector &exclPatterns = Config_getList(EXCLUDE_PATTERNS);
2222 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:6001
2223
2224 QCString absName = fi.absFilePath();
2225
2226 // global guard
2227 if (state->curlyCount==0) // not #include inside { ... }
2228 {
2229 std::lock_guard<std::mutex> lock(g_globalDefineMutex);
2230 if (g_defineManager.alreadyProcessed(absName.str()))
2231 {
2232 alreadyProcessed = TRUE;
2233 //printf(" already included 1\n");
2234 return 0; // already done
2235 }
2236 }
2237 // check include stack for absName
static std::mutex g_globalDefineMutex
Definition pre.l:233
static DefineManager g_defineManager
Definition pre.l:235
2238
2239 alreadyProcessed = std::any_of(
2240 state->includeStack.begin(),
2241 state->includeStack.end(),
2242 [absName](const std::unique_ptr<FileState> &lfs)
2243 { return lfs->fileName==absName; }
2244 );
2245
2246 if (alreadyProcessed)
2247 {
2248 //printf(" already included 2\n");
2249 return nullptr;
2250 }
2251 //printf("#include %s\n",qPrint(absName));
2252
2253 fs = std::make_unique<FileState>();
2254 if (!readInputFile(absName,fs->fileBuf))
2255 { // error
2256 //printf(" error reading\n");
2257 fs.reset();
2258 }
2259 else
2260 {
2261 fs->oldFileBuf = state->inputBuf;
2262 fs->oldFileBufPos = state->inputBufPos;
2263 }
2264 }
2265 return fs;
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:5841
2266}

References FileInfo::absFilePath(), Config_getList, FileInfo::exists(), FALSE, g_defineManager, g_globalDefineMutex, FileInfo::isFile(), patternMatch(), readInputFile(), QCString::str(), and TRUE.

Referenced by findFile().

◆ computeExpression()

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

3350{
3351 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
3352 QCString e=expr;
3353 QCString ee=expr;
3354 ee = removeMarkers(ee);
3355 state->expanded.clear();
3356 expandExpression(yyscanner,e,nullptr,0,0);
3357 //printf("after expansion '%s'\n",qPrint(e));
3358 e = removeIdsAndMarkers(e);
3359 if (e.isEmpty()) return FALSE;
3360 //printf("parsing '%s'\n",qPrint(e));
3361 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:2911
static QCString removeIdsAndMarkers(const QCString &s)
Definition pre.l:3092
static QCString removeMarkers(const QCString &s)
Definition pre.l:3287
3362}

References expandExpression(), FALSE, QCString::isEmpty(), removeIdsAndMarkers(), removeMarkers(), and QCString::str().

◆ decrLevel()

static void decrLevel ( yyscan_t yyscanner)
static

Definition at line 2177 of file pre.l.

2178{
2179 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
2180 //printf("%s line %d: decrLevel %d\n",qPrint(state->fileName),state->yyLineNr,state->levelGuard.size());
2181 if (!state->levelGuard.empty())
2182 {
2183 state->levelGuard.pop();
2184 }
2185 else
2186 {
2187 warn(state->fileName,state->yyLineNr,"More #endif's than #if's found.");
2188 }
#define warn(file, line, fmt,...)
Definition message.h:59
2189}

References warn.

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

◆ determineBlockName()

static void determineBlockName ( yyscan_t yyscanner)
static

Definition at line 3503 of file pre.l.

3504{
3505 struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
3506 yyextra->fenceSize=0;
3507 char c=0;
3508 if (yytext[1]=='f' && ((c=yytext[2])=='[' || c=='{' || c=='(' || c=='$'))
3509 {
3510 switch (c)
3511 {
3512 case '[': yyextra->blockName="]"; break;
3513 case '{': yyextra->blockName="}"; break;
3514 case '(': yyextra->blockName=")"; break;
3515 case '$': yyextra->blockName="$"; break;
3516 default: break;
3517 }
3518 yyextra->blockName=yyextra->blockName.stripWhiteSpace();
3519 }
3520 else
3521 {
3522 QCString bn=QCString(&yytext[1]).stripWhiteSpace();
3523 if (bn=="startuml")
3524 {
3525 yyextra->blockName="uml";
3526 }
3527 else
3528 {
3529 int i = bn.find('{'); // for \code{.c}
3530 if (i!=-1) bn=bn.left(i).stripWhiteSpace();
3531 yyextra->blockName=bn;
3532 }
3533 }
3534}

References QCString::find(), QCString::left(), and QCString::stripWhiteSpace().

◆ endCondSection()

static void endCondSection ( yyscan_t yyscanner)
static

Definition at line 3703 of file pre.l.

3704{
3705 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
3706 if (state->condStack.empty())
3707 {
3708 warn(state->fileName,state->yyLineNr,"the \\endcond does not have a corresponding \\cond in this file");
3709 state->skip=FALSE;
3710 }
3711 else
3712 {
3713 const std::unique_ptr<preYY_CondCtx> &ctx = state->condStack.top();
3714 state->skip=ctx->skip;
3715 state->condStack.pop();
3716 }
3717 //printf("endCondSection: skip=%d stack=%d\n",state->skip,state->condStack.count());
3718}

References FALSE, and warn.

◆ escapeAt()

static QCString escapeAt ( const QCString & text)
static

Definition at line 3730 of file pre.l.

3731{
3732 QCString result;
3733 if (!text.isEmpty())
3734 {
3735 char c = 0;
3736 const char *p=text.data();
3737 while ((c=*p++))
3738 {
3739 if (c=='@') result+="@@"; else result+=c;
3740 }
3741 }
3742 return result;
3743}

References QCString::data(), and QCString::isEmpty().

◆ expandExpression()

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

2912{
2913 struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
2914 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
2915 //printf(">expandExpression(expr='%s',rest='%s',pos=%d,level=%d)\n",qPrint(expr),rest ? qPrint(*rest) : "", pos, level);
2916 if (expr.isEmpty())
2917 {
2918 //printf("<expandExpression: empty\n");
2919 return TRUE;
2920 }
2921 if (state->expanded.find(expr.str())!=state->expanded.end() &&
2922 level>MAX_EXPANSION_DEPTH) // check for too deep recursive expansions
2923 {
2924 //printf("<expandExpression: already expanded expr='%s'\n",qPrint(expr));
2925 return FALSE;
2926 }
2927 else
2928 {
2929 state->expanded.insert(expr.str());
2930 }
2931 QCString macroName;
2932 QCString expMacro;
2933 bool definedTest=FALSE;
2934 int i=pos, l=0, p=0, len=0;
2935 int startPos = pos;
2936 int samePosCount=0;
2937 while ((p=getNextId(expr,i,&l))!=-1) // search for an macro name
2938 {
2939 bool replaced=FALSE;
2940 macroName=expr.mid(p,l);
2941 //printf(" p=%d macroName=%s\n",p,qPrint(macroName));
2942 if (p<2 || !(expr.at(p-2)=='@' && expr.at(p-1)=='-')) // no-rescan marker?
2943 {
2944 if (state->expandedDict.find(macroName.str())==state->expandedDict.end()) // expand macro
2945 {
2946 Define *def=isDefined(yyscanner,macroName);
2947 // In case EXPAND_ONLY_PREDEF is enabled prevent expansion unless the macro was explicitly
2948 // predefined
2949 if (yyextra->expandOnlyPredef && def && !def->isPredefined) def=nullptr;
2950 if (macroName=="defined")
2951 {
2952 //printf("found defined inside macro definition '%s'\n",qPrint(expr.right(expr.length()-p)));
2953 definedTest=TRUE;
2954 }
2955 else if (definedTest) // macro name was found after defined
2956 {
2957 if (def) expMacro = " 1 "; else expMacro = " 0 ";
2958 replaced=TRUE;
2959 len=l;
2960 definedTest=FALSE;
2961 }
2962 else if (def && def->nargs==-1) // simple macro
2963 {
2964 // substitute the definition of the macro
2965 expMacro=def->definition.stripWhiteSpace();
2966 //expMacro=def->definition.stripWhiteSpace();
2967 replaced=TRUE;
2968 len=l;
2969 //printf("simple macro expansion='%s'->'%s'\n",qPrint(macroName),qPrint(expMacro));
2970 }
2971 else if (def && def->nargs>=0) // function macro
2972 {
2973 //printf(" >>>> call replaceFunctionMacro expr='%s'\n",qPrint(expr));
2974 replaced=replaceFunctionMacro(yyscanner,expr,rest,p+l,len,def,expMacro,level);
2975 //printf(" <<<< call replaceFunctionMacro: replaced=%d\n",replaced);
2976 len+=l;
2977 }
2978 //printf(" macroName='%s' expMacro='%s' replaced=%d\n",qPrint(macroName),qPrint(expMacro),replaced);
#define MAX_EXPANSION_DEPTH
Definition pre.l:2877
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:3835
static int getNextId(const QCString &expr, int p, int *l)
Definition pre.l:2823
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:2573
2979
2980 if (replaced) // expand the macro and rescan the expression
2981 {
2982 //printf(" replacing '%s'->'%s'\n",qPrint(expr.mid(p,len)),qPrint(expMacro));
2983 QCString resultExpr=expMacro;
2984 QCString restExpr=expr.right(expr.length()-len-p);
2985 addSeparatorsIfNeeded(yyscanner,expr,resultExpr,restExpr,p);
2986 processConcatOperators(resultExpr);
2987 //printf(" macroName=%s restExpr='%s' def->nonRecursive=%d\n",qPrint(macroName),qPrint(restExpr),def->nonRecursive);
2988 bool expanded=false;
2989 if (def && !def->nonRecursive)
2990 {
2991 state->expandedDict.emplace(toStdString(macroName),def);
2992 expanded = expandExpression(yyscanner,resultExpr,&restExpr,0,level+1);
2993 state->expandedDict.erase(toStdString(macroName));
2994 }
2995 else if (def && def->nonRecursive)
2996 {
2997 expanded = true;
2998 }
2999 if (expanded)
3000 {
3001 //printf("expanded '%s' + '%s' + '%s'\n",qPrint(expr.left(p)),qPrint(resultExpr),qPrint(restExpr));
3002 expr=expr.left(p)+resultExpr+restExpr;
3003 i=p;
3004 }
3005 else
3006 {
3007 //printf("not expanded '%s' + @- '%s'\n",qPrint(expr.left(p)),qPrint(expr.right(expr.length()-p)));
3008 expr=expr.left(p)+"@-"+expr.right(expr.length()-p);
3009 i=p+l+2;
3010 }
3011 }
3012 else // move to the next macro name
3013 {
3014 //printf(" moving to the next macro old i=%d new i=%d\n",i,p+l);
3015 i=p+l;
3016 }
3017 }
3018 else // move to the next macro name
3019 {
3020 expr=expr.left(p)+"@-"+expr.right(expr.length()-p);
3021 //printf("macro already expanded, moving to the next macro expr=%s\n",qPrint(expr));
3022 i=p+l+2;
3023 //i=p+l;
3024 }
3025 // check for too many inplace expansions without making progress
3026 if (i==startPos)
3027 {
3028 samePosCount++;
3029 }
3030 else
3031 {
3032 startPos=i;
3033 samePosCount=0;
3034 }
3035 if (samePosCount>MAX_EXPANSION_DEPTH)
3036 {
3037 break;
3038 }
3039 }
3040 else // no re-scan marker found, skip the macro name
3041 {
3042 //printf("skipping marked macro\n");
3043 i=p+l;
3044 }
3045 }
3046 //printf("<expandExpression(expr='%s',rest='%s',pos=%d,level=%d)\n",qPrint(expr),rest ? qPrint(*rest) : "", pos,level);
3047 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:2879
static void processConcatOperators(QCString &expr)
Definition pre.l:2470
std::string toStdString(const QCString &s)
Definition qcstring.h:687
3048}

References addSeparatorsIfNeeded(), QCString::at(), Define::definition, expandExpression(), FALSE, getNextId(), isDefined(), QCString::isEmpty(), Define::isPredefined, QCString::left(), QCString::length(), MAX_EXPANSION_DEPTH, QCString::mid(), Define::nargs, Define::nonRecursive, processConcatOperators(), replaceFunctionMacro(), QCString::right(), QCString::str(), QCString::stripWhiteSpace(), toStdString(), and TRUE.

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

◆ expandMacro()

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

3369{
3370 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3371 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
3372 state->prevChar = yyscanner->yytext_r > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ? *(yyscanner->yytext_r-1) : 0;
3373 QCString n=name;
3374 state->expanded.clear();
3375 expandExpression(yyscanner,n,nullptr,0,0);
3376 n=removeMarkers(n);
3377 state->prevChar=0;
3378 //printf("expandMacro '%s'->'%s'\n",qPrint(name),qPrint(n));
3379 return n;
void clear()
Definition qcstring.h:169
3380}

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

◆ extractTrailingComment()

static QCString extractTrailingComment ( const QCString & s)
static

Definition at line 2342 of file pre.l.

2343{
2344 if (s.isEmpty()) return "";
2345 int i=(int)s.length()-1;
2346 while (i>=0)
2347 {
2348 char c=s[i];
2349 switch (c)
2350 {
2351 case '/':
2352 {
2353 i--;
2354 if (i>=0 && s[i]=='*') // end of a comment block
2355 {
2356 i--;
2357 while (i>0 && !(s[i-1]=='/' && s[i]=='*')) i--;
2358 if (i==0)
2359 {
2360 i++;
2361 }
2362 // only /*!< ... */ or /**< ... */ are treated as a comment for the macro name,
2363 // otherwise the comment is treated as part of the macro definition
2364 return ((s[i+1]=='*' || s[i+1]=='!') && s[i+2]=='<') ? &s[i-1] : "";
2365 }
2366 else
2367 {
2368 return "";
2369 }
2370 }
2371 break;
2372 // whitespace or line-continuation
2373 case ' ':
2374 case '\t':
2375 case '\r':
2376 case '\n':
2377 case '\\':
2378 break;
2379 default:
2380 return "";
2381 }
2382 i--;
2383 }
2384 return "";
2385}

References QCString::isEmpty(), and QCString::length().

◆ extraSpacing()

static void extraSpacing ( yyscan_t yyscanner)
inlinestatic

Definition at line 3490 of file pre.l.

3491{
3492 struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
3493 if (!yyextra->defContinue) return;
3494 for (int i=0; i< (int)yyleng; i++)
3495 {
3496 if (yytext[i] == '\t')
3497 yyextra->defExtraSpacing+='\t';
3498 else
3499 yyextra->defExtraSpacing+=' ';
3500 }
3501}

◆ findFile()

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

Definition at line 2268 of file pre.l.

2269{
2270 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
2271 //printf("** findFile(%s,%d) state->fileName=%s\n",qPrint(fileName),localInclude,qPrint(state->fileName));
2272 if (Portable::isAbsolutePath(fileName))
2273 {
2274 auto fs = checkAndOpenFile(yyscanner,fileName,alreadyProcessed);
2275 if (fs)
2276 {
2277 setFileName(yyscanner,fileName);
2278 state->yyLineNr=1;
2279 return fs;
2280 }
2281 else if (alreadyProcessed)
2282 {
2283 return nullptr;
2284 }
2285 }
2286 if (localInclude && !state->fileName.isEmpty())
2287 {
2288 FileInfo fi(state->fileName.str());
2289 if (fi.exists())
2290 {
2291 QCString absName = QCString(fi.dirPath(TRUE))+"/"+fileName;
2292 auto fs = checkAndOpenFile(yyscanner,absName,alreadyProcessed);
2293 if (fs)
2294 {
2295 setFileName(yyscanner,absName);
2296 state->yyLineNr=1;
2297 return fs;
2298 }
2299 else if (alreadyProcessed)
2300 {
2301 return nullptr;
2302 }
2303 }
2304 }
2305 if (state->pathList.empty())
2306 {
2307 return nullptr;
2308 }
2309 for (auto path : state->pathList)
2310 {
2311 std::string absName = (path+"/"+fileName).str();
2312 //printf(" Looking for %s in %s\n",fileName,path.c_str());
2313 auto fs = checkAndOpenFile(yyscanner,absName.c_str(),alreadyProcessed);
2314 if (fs)
2315 {
2316 setFileName(yyscanner,absName.c_str());
2317 state->yyLineNr=1;
2318 //printf(" -> found it\n");
2319 return fs;
2320 }
2321 else if (alreadyProcessed)
2322 {
2323 return nullptr;
2324 }
2325 }
2326 bool ambig = false;
2328 if (fd && !ambig) // fallback in case the file is uniquely named in the input, use that one
2329 {
2330 auto fs = checkAndOpenFile(yyscanner,fd->absFilePath(),alreadyProcessed);
2331 if (fs)
2332 {
2333 setFileName(yyscanner,fd->absFilePath());
2334 state->yyLineNr=1;
2335 //printf(" -> found it\n");
2336 return fs;
2337 }
2338 }
2339 return nullptr;
static FileNameLinkedMap * inputNameLinkedMap
Definition doxygen.h:105
A model of a file symbol.
Definition filedef.h:99
virtual QCString absFilePath() const =0
bool isAbsolutePath(const QCString &fileName)
Definition portable.cpp:514
static void setFileName(yyscan_t yyscanner, const QCString &name)
Definition pre.l:2149
static std::unique_ptr< FileState > checkAndOpenFile(yyscan_t yyscanner, const QCString &fileName, bool &alreadyProcessed)
Definition pre.l:2212
FileDef * findFileDef(const FileNameLinkedMap *fnMap, const QCString &n, bool &ambig)
Definition util.cpp:3262
2340}

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

◆ forceEndCondSection()

static void forceEndCondSection ( yyscan_t yyscanner)
static

Definition at line 3720 of file pre.l.

3721{
3722 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
3723 while (!state->condStack.empty())
3724 {
3725 state->condStack.pop();
3726 }
3727 state->skip=FALSE;
3728}

References FALSE.

Referenced by Preprocessor::processFile().

◆ getCurrentChar()

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

Definition at line 3788 of file pre.l.

3789{
3790 //printf("getCurrentChar(%s,%s,%d)\n",qPrint(expr),rest ? rest->data() : 0,pos);
3791 if (pos<expr.length())
3792 {
3793 //printf("%c=expr()\n",expr.at(pos));
3794 return expr.at(pos);
3795 }
3796 else if (rest && !rest->isEmpty())
3797 {
3798 int cc=rest->at(0);
3799 //printf("%c=rest\n",cc);
3800 return cc;
3801 }
3802 else
3803 {
3804 int cc=yyinput(yyscanner);
3805 returnCharToStream(yyscanner,(char)cc);
3806 //printf("%c=yyinput()\n",cc);
3807 return cc;
3808 }
static void returnCharToStream(yyscan_t yyscanner, char c)
Definition pre.l:2517
3809}

References QCString::at(), QCString::isEmpty(), QCString::length(), and returnCharToStream().

Referenced by replaceFunctionMacro(), and skipCommentMacroName().

◆ getFenceSize()

static yy_size_t getFenceSize ( char * txt,
yy_size_t leng )
static

Definition at line 2138 of file pre.l.

2139{
2140 yy_size_t fenceSize = 0;
2141 for (size_t i = 0; i < leng; i++)
2142 {
2143 if (txt[i] != ' ' && txt[i] != '*' && txt[i] != '\t') break;
2144 fenceSize++;
2145 }
2146 return leng-fenceSize;
2147}

◆ getLexerFILE()

static const char * getLexerFILE ( )
inlinestatic

Definition at line 351 of file pre.l.

351{return __FILE__;}

◆ getNextChar()

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

Definition at line 3765 of file pre.l.

3766{
3767 //printf("getNextChar(%s,%s,%d)\n",qPrint(expr),rest ? rest->data() : 0,pos);
3768 if (pos<expr.length())
3769 {
3770 //printf(" expr()='%c'\n",expr.at(pos));
3771 return expr.at(pos++);
3772 }
3773 else if (rest && !rest->isEmpty())
3774 {
3775 int cc=rest->at(0);
3776 *rest=rest->right(rest->length()-1);
3777 //printf(" rest='%c'\n",cc);
3778 return cc;
3779 }
3780 else
3781 {
3782 int cc=yyinput(yyscanner);
3783 //printf(" yyinput()='%c' %d\n",cc,EOF);
3784 return cc;
3785 }
3786}

References QCString::at(), QCString::isEmpty(), QCString::length(), and QCString::right().

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

◆ getNextId()

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

2824{
2825 int n;
2826 while (p<(int)expr.length())
2827 {
2828 char c=expr.at(p++);
2829 if (isdigit(c)) // skip number
2830 {
2831 while (p<(int)expr.length() && isId(expr.at(p))) p++;
2832 }
2833 else if (isalpha(c) || c=='_') // read id
2834 {
2835 n=p-1;
2836 while (p<(int)expr.length() && isId(expr.at(p))) p++;
2837 *l=p-n;
2838 return n;
2839 }
2840 else if (c=='"') // skip string
2841 {
2842 char ppc=0,pc=c;
2843 if (p<(int)expr.length()) c=expr.at(p);
2844 while (p<(int)expr.length() && (c!='"' || (pc=='\\' && ppc!='\\')))
2845 // continue as long as no " is found, but ignoring \", but not \\"
2846 {
2847 ppc=pc;
2848 pc=c;
2849 c=expr.at(p);
2850 p++;
2851 }
2852 if (p<(int)expr.length()) ++p; // skip closing quote
2853 }
2854 else if (c=='/') // skip C Comment
2855 {
2856 //printf("Found C comment at p=%d\n",p);
2857 char pc=c;
2858 if (p<(int)expr.length())
2859 {
2860 c=expr.at(p);
2861 if (c=='*') // Start of C comment
2862 {
2863 p++;
2864 while (p<(int)expr.length() && !(pc=='*' && c=='/'))
2865 {
2866 pc=c;
2867 c=expr.at(p++);
2868 }
2869 }
2870 }
2871 //printf("Found end of C comment at p=%d\n",p);
2872 }
2873 }
2874 return -1;
bool isId(int c)
Definition util.h:202
2875}

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

Referenced by expandExpression().

◆ incrLevel()

static void incrLevel ( yyscan_t yyscanner)
static

Definition at line 2170 of file pre.l.

2171{
2172 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
2173 state->levelGuard.push(false);
2174 //printf("%s line %d: incrLevel %d\n",qPrint(yyextra->fileName),yyextra->yyLineNr,yyextra->levelGuard.size());
2175}

◆ initPredefined()

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

Definition at line 3864 of file pre.l.

3865{
3866 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
3867
3868 // add predefined macros
3869 const StringVector &predefList = Config_getList(PREDEFINED);
3870 for (const auto &ds : predefList)
3871 {
3872 size_t i_equals=ds.find('=');
3873 size_t i_obrace=ds.find('(');
3874 size_t i_cbrace=ds.find(')');
3875 bool nonRecursive = i_equals!=std::string::npos && i_equals>0 && ds[i_equals-1]==':';
3876
3877 if ((i_obrace==0) || (i_equals==0) || (i_equals==1 && ds[i_equals-1]==':'))
3878 {
3879 continue; // no define name
3880 }
3881
3882 if (i_obrace<i_equals && i_cbrace<i_equals &&
3883 i_obrace!=std::string::npos && i_cbrace!=std::string::npos &&
3884 i_obrace<i_cbrace
3885 ) // predefined function macro definition
3886 {
3887 static const reg::Ex reId(R"(\a\w*)");
3888 std::map<std::string,int> argMap;
3889 std::string args = ds.substr(i_obrace+1,i_cbrace-i_obrace-1); // part between ( and )
3890 bool hasVarArgs = args.find("...")!=std::string::npos;
3891 //printf("predefined function macro '%s'\n",ds.c_str());
3892 int count = 0;
3893 reg::Iterator arg_it(args,reId,0);
3894 reg::Iterator arg_end;
3895 // gather the formal arguments in a dictionary
3896 for (; arg_it!=arg_end; ++arg_it)
3897 {
3898 argMap.emplace(arg_it->str(),count++);
3899 }
3900 if (hasVarArgs) // add the variable argument if present
3901 {
3902 argMap.emplace("__VA_ARGS__",count++);
3903 }
Class representing a regular expression.
Definition regex.h:39
Iterator class to iterator through matches.
Definition regex.h:232
3904
3905 // strip definition part
3906 std::string definition;
3907 std::string in=ds.substr(i_equals+1);
3908 reg::Iterator re_it(in,reId);
3909 reg::Iterator re_end;
3910 size_t i=0;
3911 // substitute all occurrences of formal arguments by their
3912 // corresponding markers
3913 for (; re_it!=re_end; ++re_it)
3914 {
3915 const auto &match = *re_it;
3916 size_t pi = match.position();
3917 size_t l = match.length();
3918 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:759
3919
3920 auto it = argMap.find(match.str());
3921 if (it!=argMap.end())
3922 {
3923 int argIndex = it->second;
3924 QCString marker;
3925 marker.sprintf(" @%d ",argIndex);
3926 definition+=marker.str();
3927 }
3928 else
3929 {
3930 definition+=match.str();
3931 }
3932 i=pi+l;
3933 }
3934 definition+=in.substr(i);
QCString & sprintf(const char *format,...)
Definition qcstring.cpp:29
3935
3936 // add define definition to the dictionary of defines for this file
3937 std::string dname = ds.substr(0,i_obrace);
3938 if (!dname.empty())
3939 {
3940 Define def;
3941 def.name = dname;
3942 def.definition = definition;
3943 def.nargs = count;
3944 def.isPredefined = TRUE;
3945 def.nonRecursive = nonRecursive;
3946 def.fileDef = state->yyFileDef;
3947 def.fileName = fileName;
3948 def.varArgs = hasVarArgs;
3949 state->contextDefines.emplace(def.name.str(),def);
3950
3951 //printf("#define '%s' '%s' #nargs=%d hasVarArgs=%d\n",
3952 // qPrint(def.name),qPrint(def.definition),def.nargs,def.varArgs);
3953 }
3954 }
3955 else if (!ds.empty()) // predefined non-function macro definition
3956 {
3957 //printf("predefined normal macro '%s'\n",ds.c_str());
3958 Define def;
3959 if (i_equals==std::string::npos) // simple define without argument
3960 {
3961 def.name = ds;
3962 def.definition = "1"; // substitute occurrences by 1 (true)
3963 }
3964 else // simple define with argument
3965 {
3966 int ine=static_cast<int>(i_equals) - (nonRecursive ? 1 : 0);
3967 def.name = ds.substr(0,ine);
3968 def.definition = ds.substr(i_equals+1);
3969 }
3970 if (!def.name.isEmpty())
3971 {
3972 def.nargs = -1;
3973 def.isPredefined = TRUE;
3974 def.nonRecursive = nonRecursive;
3975 def.fileDef = state->yyFileDef;
3976 def.fileName = fileName;
3977 state->contextDefines.emplace(def.name.str(),def);
3978 }
3979 }
3980 }
3981}

References Config_getList, Define::definition, Define::fileDef, Define::fileName, QCString::isEmpty(), Define::isPredefined, Define::name, Define::nargs, Define::nonRecursive, QCString::sprintf(), QCString::str(), reg::Match::str(), TRUE, and Define::varArgs.

Referenced by Preprocessor::processFile().

◆ isDefined()

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

3836{
3837 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
3838
3839 bool undef = false;
3840 auto findDefine = [&undef,&name](DefineMap &map)
3841 {
3842 Define *d=nullptr;
3843 auto it = map.find(name.str());
3844 if (it!=map.end())
3845 {
3846 d = &it->second;
3847 if (d->undef)
3848 {
3849 undef=true;
3850 d=nullptr;
3851 }
3852 }
3853 return d;
3854 };
bool undef
Definition define.h:41
std::map< std::string, Define > DefineMap
A dictionary of managed Define objects.
Definition pre.l:108
3855
3856 Define *def = findDefine(state->localDefines);
3857 if (def==nullptr && !undef)
3858 {
3859 def = findDefine(state->contextDefines);
3860 }
3861 return def;
3862}

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

Referenced by expandExpression().

◆ otherCaseDone()

static bool otherCaseDone ( yyscan_t yyscanner)
static

Definition at line 2191 of file pre.l.

2192{
2193 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
2194 if (state->levelGuard.empty())
2195 {
2196 warn(state->fileName,state->yyLineNr,"Found an #else without a preceding #if.");
2197 return TRUE;
2198 }
2199 else
2200 {
2201 return state->levelGuard.top();
2202 }
2203}

References TRUE, and warn.

◆ outputArray()

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

Definition at line 3461 of file pre.l.

3462{
3463 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
3464 if (state->includeStack.empty() || state->curlyCount>0) (*state->outputBuf)+=std::string_view(a,len);
3465}

◆ outputChar()

static void outputChar ( yyscan_t yyscanner,
char c )
inlinestatic

Definition at line 3455 of file pre.l.

3456{
3457 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
3458 if (state->includeStack.empty() || state->curlyCount>0) (*state->outputBuf)+=c;
3459}

Referenced by outputSpace(), and outputSpaces().

◆ outputSpace()

static void outputSpace ( yyscan_t yyscanner,
char c )
inlinestatic

Definition at line 3473 of file pre.l.

3474{
3475 if (c=='\t') outputChar(yyscanner,'\t');
3476 else outputChar(yyscanner,' ');
static void outputChar(yyscan_t yyscanner, char c)
Definition pre.l:3455
3477}

References outputChar().

◆ outputSpaces()

static void outputSpaces ( yyscan_t yyscanner,
char * s )
inlinestatic

Definition at line 3479 of file pre.l.

3480{
3481 const char *p=s;
3482 char c = 0;
3483 while ((c=*p++))
3484 {
3485 if (c=='\t') outputChar(yyscanner,'\t');
3486 else outputChar(yyscanner,' ');
3487 }
3488}

References outputChar().

◆ outputString()

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

Definition at line 3467 of file pre.l.

3468{
3469 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
3470 if (state->includeStack.empty() || state->curlyCount>0) (*state->outputBuf)+=a.str();
3471}

References QCString::str().

Referenced by readIncludeFile().

◆ processConcatOperators()

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

2471{
2472 if (expr.isEmpty()) return;
2473 //printf("processConcatOperators: in='%s'\n",qPrint(expr));
2474 std::string e = expr.str();
2475 static const reg::Ex r(R"(\s*##\s*)");
DirIterator end(const DirIterator &) noexcept
Definition dir.cpp:175
2477
2478 size_t i=0;
2479 for (;;)
2480 {
2481 reg::Iterator it(e,r,i);
2482 if (it!=end)
2483 {
2484 const auto &match = *it;
2485 size_t n = match.position();
2486 size_t l = match.length();
2487 //printf("Match: '%s'\n",qPrint(expr.mid(i)));
2488 if (n+l+1<e.length() && e[static_cast<int>(n+l)]=='@' && expr[static_cast<int>(n+l+1)]=='-')
2489 {
2490 // remove no-rescan marker after ID
2491 l+=2;
2492 }
2493 //printf("found '%s'\n",qPrint(expr.mid(n,l)));
2494 // remove the ## operator and the surrounding whitespace
2495 e=e.substr(0,n)+e.substr(n+l);
2496 int k=static_cast<int>(n)-1;
2497 while (k>=0 && isId(e[k])) k--;
2498 if (k>0 && e[k]=='-' && e[k-1]=='@')
2499 {
2500 // remove no-rescan marker before ID
2501 e=e.substr(0,k-1)+e.substr(k+1);
2502 n-=2;
2503 }
2504 i=n;
2505 }
2506 else
2507 {
2508 break;
2509 }
2510 }
2511
2512 expr = e;
2513
2514 //printf("processConcatOperators: out='%s'\n",qPrint(expr));
2515}

References end(), QCString::isEmpty(), isId(), and QCString::str().

Referenced by expandExpression().

◆ processUntilMatchingTerminator()

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

3057{
3058 if (inputStr==nullptr) return inputStr;
3059 char term = *inputStr; // capture start character of the literal
3060 if (term!='\'' && term!='"') return inputStr; // not a valid literal
3061 char c=term;
3062 // output start character
3063 result+=c;
3064 inputStr++;
3065 while ((c=*inputStr)) // while inside the literal
3066 {
3067 if (c==term) // found end marker of the literal
3068 {
3069 // output end character and stop
3070 result+=c;
3071 inputStr++;
3072 break;
3073 }
3074 else if (c=='\\') // escaped character, process next character
3075 // as well without checking for end marker.
3076 {
3077 result+=c;
3078 inputStr++;
3079 c=*inputStr;
3080 if (c==0) break; // unexpected end of string after escape character
3081 }
3082 result+=c;
3083 inputStr++;
3084 }
3085 return inputStr;
3086}

References term.

Referenced by removeIdsAndMarkers(), and removeMarkers().

◆ readIncludeFile()

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

Definition at line 3536 of file pre.l.

3537{
3538 AUTO_TRACE("inc={}",inc);
3539 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
3540 uint32_t i=0;
#define AUTO_TRACE(...)
Definition docnode.cpp:46
3541
3542 // find the start of the include file name
3543 while (i<inc.length() &&
3544 (inc.at(i)==' ' || inc.at(i)=='"' || inc.at(i)=='<')
3545 ) i++;
3546 uint32_t s=i;
3547
3548 // was it a local include?
3549 bool localInclude = s>0 && inc.at(s-1)=='"';
3550
3551 // find the end of the include file name
3552 while (i<inc.length() && inc.at(i)!='"' && inc.at(i)!='>') i++;
3553
3554 if (s<inc.length() && i>s) // valid include file name found
3555 {
3556 // extract include path+name
3557 QCString incFileName=inc.mid(s,i-s).stripWhiteSpace();
3558 if (incFileName.endsWith(".exe") || incFileName.endsWith(".dll") || incFileName.endsWith(".tlb"))
3559 {
3560 // skip imported binary files (e.g. M$ type libraries)
3561 return;
3562 }
bool endsWith(const char *s) const
Definition qcstring.h:509
3563
3564 QCString oldFileName = state->fileName;
3565 FileDef *oldFileDef = state->yyFileDef;
3566 int oldLineNr = state->yyLineNr;
3567 //printf("Searching for '%s'\n",qPrint(incFileName));
3568
3569 QCString absIncFileName = determineAbsoluteIncludeName(state->fileName,incFileName);
QCString determineAbsoluteIncludeName(const QCString &curFile, const QCString &incFileName)
Definition util.cpp:3954
3570
3571 // findFile will overwrite state->yyFileDef if found
3572 std::unique_ptr<FileState> fs;
3573 bool alreadyProcessed = FALSE;
3574 //printf("calling findFile(%s)\n",qPrint(incFileName));
3575 fs=findFile(yyscanner,absIncFileName,localInclude,alreadyProcessed); // see if the absolute include file can be found
3576 if (fs)
3577 {
3578 {
3579 std::lock_guard<std::mutex> lock(g_globalDefineMutex);
3580 g_defineManager.addInclude(oldFileName.str(),absIncFileName.str());
3581 }
static std::unique_ptr< FileState > findFile(yyscan_t yyscanner, const QCString &fileName, bool localInclude, bool &alreadyProcessed)
Definition pre.l:2268
3582
3583 //printf("Found include file!\n");
3585 {
3586 for (i=0;i<state->includeStack.size();i++)
3587 {
3589 }
3590 Debug::print(Debug::Preprocessor,0,"#include %s: parsing...\n",qPrint(incFileName));
3591 }
@ Preprocessor
Definition debug.h:29
static void print(DebugMask mask, int prio, const char *fmt,...)
Definition debug.cpp:81
static bool isFlagSet(const DebugMask mask)
Definition debug.cpp:135
const char * qPrint(const char *s)
Definition qcstring.h:672
3592
3593 if (state->includeStack.empty() && oldFileDef)
3594 {
3595 PreIncludeInfo *ii = state->includeRelations.find(absIncFileName);
3596 if (ii==nullptr)
3597 {
3598 bool ambig = false;
3599 FileDef *incFd = findFileDef(Doxygen::inputNameLinkedMap,absIncFileName,ambig);
3600 state->includeRelations.add(
3601 absIncFileName,
3602 oldFileDef,
3603 ambig ? nullptr : incFd,
3604 incFileName,
3605 localInclude,
3606 state->isImported
3607 );
3608 }
3609 }
3610
3611 struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
3612 fs->bufState = YY_CURRENT_BUFFER;
3613 fs->lineNr = oldLineNr;
3614 fs->fileName = oldFileName;
3615 fs->curlyCount = state->curlyCount;
3616 //state->curlyCount = 0; // don't reset counter, see issue #10997
3617 fs->lexRulesPart = state->lexRulesPart;
3618 state->lexRulesPart = false;
3619 // push the state on the stack
3620 FileState *fs_ptr = fs.get();
3621 state->includeStack.push_back(std::move(fs));
3622 // set the scanner to the include file
3623
3624 // Deal with file changes due to
3625 // #include's within { .. } blocks
3626 QCString lineStr(state->fileName.length()+20, QCString::ExplicitSize);
3627 lineStr.sprintf("# 1 \"%s\" 1\n",qPrint(state->fileName));
3628 outputString(yyscanner,lineStr);
@ ExplicitSize
Definition qcstring.h:133
static void outputString(yyscan_t yyscanner, const QCString &s)
Definition pre.l:3467
3629
3630 AUTO_TRACE_ADD("Switching to include file {}",incFileName);
3631 state->expectGuard=TRUE;
3632 state->inputBuf = &fs_ptr->fileBuf;
3633 state->inputBufPos=0;
3634 yy_switch_to_buffer(yy_create_buffer(0, YY_BUF_SIZE, yyscanner),yyscanner);
3635 }
3636 else
3637 {
3638 if (alreadyProcessed) // if this header was already process we can just copy the stored macros
3639 // in the local context
3640 {
3641 std::lock_guard<std::mutex> lock(g_globalDefineMutex);
3642 g_defineManager.addInclude(state->fileName.str(),absIncFileName.str());
3643 g_defineManager.retrieve(absIncFileName.str(),state->contextDefines);
3644 }
#define YY_BUF_SIZE
Definition commentcnv.l:19
#define AUTO_TRACE_ADD(...)
Definition docnode.cpp:47
std::string fileBuf
Definition pre.l:85
3645
3646 if (state->includeStack.empty() && oldFileDef)
3647 {
3648 PreIncludeInfo *ii = state->includeRelations.find(absIncFileName);
3649 if (ii==nullptr)
3650 {
3651 bool ambig = false;
3652 FileDef *incFd = findFileDef(Doxygen::inputNameLinkedMap,absIncFileName,ambig);
3653 ii = state->includeRelations.add(absIncFileName,
3654 oldFileDef,
3655 ambig ? nullptr : incFd,
3656 incFileName,
3657 localInclude,
3658 state->isImported
3659 );
3660 }
3661 }
3662
3664 {
3665 for (i=0;i<state->includeStack.size();i++)
3666 {
3668 }
3669 if (alreadyProcessed)
3670 {
3671 Debug::print(Debug::Preprocessor,0,"#include %s: already processed! skipping...\n",qPrint(incFileName));
3672 }
3673 else
3674 {
3675 Debug::print(Debug::Preprocessor,0,"#include %s: not found! skipping...\n",qPrint(incFileName));
3676 }
3677 //printf("error: include file %s not found\n",yytext);
3678 }
3679 if (localInclude && !state->includeStack.empty() && state->curlyCount>0 && !alreadyProcessed) // failed to find #include inside { ... }
3680 {
3681 warn(state->fileName,state->yyLineNr,"include file %s not found, perhaps you forgot to add its directory to INCLUDE_PATH?",qPrint(incFileName));
3682 }
3683 }
3684 }
3685}

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

◆ removeIdsAndMarkers()

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

3093{
3094 static const std::vector<std::string> signs = { "signed", "unsigned" };
3095 struct TypeInfo { std::string name; size_t size; };
3096 static const std::vector<TypeInfo> types = {
3097 { "short int", sizeof(short int) },
3098 { "long long int", sizeof(long long int) },
3099 { "long int", sizeof(long int) },
3100 { "long long", sizeof(long long) },
3101 { "long double", sizeof(long double) },
3102 { "int", sizeof(int) },
3103 { "short", sizeof(short) },
3104 { "bool", sizeof(bool) },
3105 { "long", sizeof(long) },
3106 { "char", sizeof(char) },
3107 { "float", sizeof(float) },
3108 { "double", sizeof(double) },
3109 };
static const char types[][NUM_HTML_LIST_TYPES]
3110
3111 // Check if string p starts with basic types ending with a ')', such as 'signed long)' or ' float )'
3112 // and return the pointer just past the ')' and the size of the type as a tuple.
3113 // If the pattern is not found the tuple (nullptr,0) is returned.
3114 auto process_cast_or_sizeof = [](const char *p) -> std::pair<const char *,size_t>
3115 {
3116 const char *q = p;
3117 while (*q==' ' || *q=='\t') q++;
3118 bool found=false;
3119 size_t size = sizeof(int); // '(signed)' or '(unsigned)' is an int type
3120 for (const auto &sgn : signs)
3121 {
3122 if (qstrncmp(q,sgn.c_str(),sgn.length())==0) { q+=sgn.length(); found=true; }
3123 }
3124 if (!found || *q==' ' || *q=='\t' || *q==')') // continue searching
3125 {
3126 while (*q==' ' || *q=='\t') q++;
3127 for (const auto &t : types)
3128 {
3129 if (qstrncmp(q,t.name.c_str(),t.name.length())==0)
3130 {
3131 q += t.name.length();
3132 size = t.size;
3133 break;
3134 }
3135 }
3136 while (*q==' ' || *q=='\t') q++;
3137 if (*q==')') return std::make_pair(++q,size);
3138 }
3139 return std::make_pair(nullptr,0);
3140 };
int qstrncmp(const char *str1, const char *str2, size_t len)
Definition qcstring.h:75
bool found
Definition util.cpp:984
3141
3142 //printf("removeIdsAndMarkers(%s)\n",qPrint(s));
3143 if (s.isEmpty()) return s;
3144 const char *p=s.data();
3145 bool inNum=FALSE;
3146 QCString result;
3147 if (p)
3148 {
3149 char c = 0;
3150 while ((c=*p))
3151 {
3152 if (c=='(') // potential cast, ignore it
3153 {
3154 const char *q = process_cast_or_sizeof(p+1).first;
3155 //printf("potential cast:\nin: %s\nout: %s\n",p,q);
3156 if (q)
3157 {
3158 p=q;
3159 continue;
3160 }
3161 }
3162 else if (c=='s' && qstrncmp(p,"sizeof",6)==0) // sizeof(...)
3163 {
3164 const char *q = p+6;
3165 while (*q==' ' || *q=='\t') q++;
3166 if (*q=='(')
3167 {
3168 auto r = process_cast_or_sizeof(q+1);
3169 //printf("sizeof:\nin: %s\nout: %zu%s\n--> sizeof=%zu\n",p,r.second,r.first,r.second);
3170 if (r.first)
3171 {
3172 result+=QCString().setNum(r.second);
3173 p=r.first;
3174 continue;
3175 }
3176 }
3177 }
QCString & setNum(short n)
Definition qcstring.h:444
3178
3179 if (c=='@') // replace @@ with @ and remove @E
3180 {
3181 if (*(p+1)=='@')
3182 {
3183 result+=c;
3184 }
3185 else if (*(p+1)=='E')
3186 {
3187 // skip
3188 }
3189 p+=2;
3190 }
3191 else if (isdigit(c)) // number
3192 {
3193 result+=c;
3194 p++;
3195 inNum=TRUE;
3196 }
3197 else if (c=='\'') // quoted character
3198 {
3199 p = processUntilMatchingTerminator(p,result);
3200 }
3201 else if (c=='d' && !inNum) // identifier starting with a 'd'
3202 {
3203 if (qstrncmp(p,"defined ",8)==0 || qstrncmp(p,"defined(",8)==0)
3204 // defined keyword
3205 {
3206 p+=7; // skip defined
3207 }
3208 else
3209 {
3210 result+="0L";
3211 p++;
3212 while ((c=*p) && isId(c)) p++;
3213 }
3214 }
3215 else if ((isalpha(c) || c=='_') && !inNum) // replace identifier with 0L
3216 {
3217 result+="0L";
3218 p++;
3219 while ((c=*p) && isId(c)) p++;
3220 while ((c=*p) && isspace((uint8_t)c)) p++;
3221 if (*p=='(') // undefined function macro
3222 {
3223 p++;
3224 int count=1;
3225 while ((c=*p++))
3226 {
3227 if (c=='(') count++;
3228 else if (c==')')
3229 {
3230 count--;
3231 if (count==0) break;
3232 }
3233 else if (c=='/')
3234 {
3235 char pc=c;
3236 c=*++p;
3237 if (c=='*') // start of C comment
3238 {
3239 while (*p && !(pc=='*' && c=='/')) // search end of comment
3240 {
3241 pc=c;
3242 c=*++p;
3243 }
3244 p++;
3245 }
3246 }
3247 }
3248 }
3249 }
3250 else if (c=='/') // skip C comments
3251 {
3252 char pc=c;
3253 c=*++p;
3254 if (c=='*') // start of C comment
3255 {
3256 while (*p && !(pc=='*' && c=='/')) // search end of comment
3257 {
3258 pc=c;
3259 c=*++p;
3260 }
3261 p++;
3262 }
3263 else // oops, not comment but division
3264 {
3265 result+=pc;
3266 goto nextChar;
3267 }
3268 }
3269 else
3270 {
static const char * processUntilMatchingTerminator(const char *inputStr, QCString &result)
Process string or character literal.
Definition pre.l:3056
3271nextChar:
3272 result+=c;
3273 char lc=(char)tolower(c);
3274 if (!isId(lc) && lc!='.' /*&& lc!='-' && lc!='+'*/) inNum=FALSE;
3275 p++;
3276 }
3277 }
3278 }
3279 //printf("removeIdsAndMarkers(%s)=%s\n",s,qPrint(result));
3280 return result;
3281}

References QCString::data(), FALSE, found, QCString::isEmpty(), isId(), processUntilMatchingTerminator(), qstrncmp(), QCString::setNum(), TRUE, and types.

Referenced by computeExpression().

◆ removeMarkers()

static QCString removeMarkers ( const QCString & s)
static

replaces all occurrences of @ in s by @

assumption:
s only contains pairs of @'s

Definition at line 3287 of file pre.l.

3288{
3289 if (s.isEmpty()) return s;
3290 const char *p=s.data();
3291 QCString result;
3292 if (p)
3293 {
3294 char c = 0;
3295 while ((c=*p))
3296 {
3297 switch(c)
3298 {
3299 case '@': // replace @@ with @
3300 {
3301 if (*(p+1)=='@')
3302 {
3303 result+=c;
3304 }
3305 p+=2;
3306 }
3307 break;
3308 case '/': // skip C comments
3309 {
3310 result+=c;
3311 char pc=c;
3312 c=*++p;
3313 if (c=='*') // start of C comment
3314 {
3315 while (*p && !(pc=='*' && c=='/')) // search end of comment
3316 {
3317 if (*p=='@' && *(p+1)=='@')
3318 result+=c,p++;
3319 else
3320 result+=c;
3321 pc=c;
3322 c=*++p;
3323 }
3324 if (*p) result+=c,p++;
3325 }
3326 }
3327 break;
3328 case '"': // skip string literals
3329 case '\'': // skip char literals
3330 p = processUntilMatchingTerminator(p,result);
3331 break;
3332 default:
3333 {
3334 result+=c;
3335 p++;
3336 }
3337 break;
3338 }
3339 }
3340 }
3341 //printf("RemoveMarkers(%s)=%s\n",s,qPrint(result));
3342 return result;
3343}

References QCString::data(), QCString::isEmpty(), and processUntilMatchingTerminator().

Referenced by computeExpression(), and expandMacro().

◆ replaceFunctionMacro()

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

2574{
2575 //printf(">replaceFunctionMacro(expr='%s',rest='%s',pos=%d,def='%s') level=%zu\n",qPrint(expr),rest ? qPrint(*rest) : 0,pos,qPrint(def->name),state->levelGuard.size());
2576 uint32_t j=pos;
2577 len=0;
2578 result.clear();
2579 int cc;
2580
2581 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:2535
2582
2583 if (cc!='(')
2584 {
2585 if (cc!=':') // don't add spaces for colons
2586 {
2587 unputChar(yyscanner,expr,rest,j,' ');
2588 }
2589 return FALSE;
2590 }
2591 getNextChar(yyscanner,expr,rest,j); // eat the '(' character
2592
2593 std::map<std::string,std::string> argTable; // list of arguments
2594 QCString arg;
2595 int argCount=0;
2596 bool done=FALSE;
2597
2598 // PHASE 1: read the macro arguments
2599 if (def->nargs==0)
2600 {
2601 while ((cc=getNextChar(yyscanner,expr,rest,j))!=EOF && cc!=0)
2602 {
2603 char c = (char)cc;
2604 if (c==')') break;
2605 }
2606 }
2607 else
2608 {
2609 while (!done && (argCount<def->nargs || def->varArgs) &&
2610 ((cc=getNextChar(yyscanner,expr,rest,j))!=EOF && cc!=0)
2611 )
2612 {
2613 char c=(char)cc;
2614 if (c=='(') // argument is a function => search for matching )
2615 {
2616 int lvl=1;
2617 arg+=c;
2618 //char term='\0';
2619 while ((cc=getNextChar(yyscanner,expr,rest,j))!=EOF && cc!=0)
2620 {
2621 c=(char)cc;
2622 //printf("processing %c: term=%c (%d)\n",c,term,term);
2623 if (c=='\'' || c=='\"') // skip ('s and )'s inside strings
2624 {
2625 arg+=c;
2626 addTillEndOfString(yyscanner,expr,rest,j,c,arg);
2627 }
2628 if (c==')')
2629 {
2630 lvl--;
2631 arg+=c;
2632 if (lvl==0) break;
2633 }
2634 else if (c=='(')
2635 {
2636 lvl++;
2637 arg+=c;
2638 }
2639 else
2640 arg+=c;
2641 }
2642 }
2643 else if (c==')' || c==',') // last or next argument found
2644 {
2645 if (c==',' && argCount==def->nargs-1 && def->varArgs)
2646 {
2647 arg=arg.stripWhiteSpace();
2648 arg+=',';
2649 }
2650 else
2651 {
2652 QCString argKey;
2653 argKey.sprintf("@%d",argCount++); // key name
2654 arg=arg.stripWhiteSpace();
2655 // add argument to the lookup table
2656 argTable.emplace(toStdString(argKey), toStdString(arg));
2657 arg.clear();
2658 if (c==')') // end of the argument list
2659 {
2660 done=TRUE;
2661 }
2662 }
2663 }
2664 else if (c=='\"') // append literal strings
2665 {
2666 arg+=c;
2667 bool found=FALSE;
2668 while (!found && (cc=getNextChar(yyscanner,expr,rest,j))!=EOF && cc!=0)
2669 {
2670 found = cc=='"';
2671 if (cc=='\\')
2672 {
2673 c=(char)cc;
2674 arg+=c;
2675 if ((cc=getNextChar(yyscanner,expr,rest,j))==EOF || cc==0) break;
2676 }
2677 c=(char)cc;
2678 arg+=c;
2679 }
2680 }
2681 else if (c=='\'') // append literal characters
2682 {
2683 arg+=c;
2684 bool found=FALSE;
2685 while (!found && (cc=getNextChar(yyscanner,expr,rest,j))!=EOF && cc!=0)
2686 {
2687 found = cc=='\'';
2688 if (cc=='\\')
2689 {
2690 c=(char)cc;
2691 arg+=c;
2692 if ((cc=getNextChar(yyscanner,expr,rest,j))==EOF || cc==0) break;
2693 }
2694 c=(char)cc;
2695 arg+=c;
2696 }
2697 }
2698 else if (c=='/') // possible start of a comment
2699 {
2700 char prevChar = '\0';
2701 arg+=c;
2702 if ((cc=getCurrentChar(yyscanner,expr,rest,j)) == '*') // we have a comment
2703 {
2704 while ((cc=getNextChar(yyscanner,expr,rest,j))!=EOF && cc!=0)
2705 {
2706 c=(char)cc;
2707 arg+=c;
2708 if (c == '/' && prevChar == '*') break; // we have an end of comment
2709 prevChar = c;
2710 }
2711 }
2712 }
2713 else // append other characters
2714 {
2715 arg+=c;
2716 }
2717 }
2718 }
static int getCurrentChar(yyscan_t yyscanner, const QCString &expr, QCString *rest, uint32_t pos)
Definition pre.l:3788
static void addTillEndOfString(yyscan_t yyscanner, const QCString &expr, QCString *rest, uint32_t &pos, char term, QCString &arg)
Definition pre.l:2523
2719
2720 // PHASE 2: apply the macro function
2721 if (argCount==def->nargs || // same number of arguments
2722 (argCount>=def->nargs-1 && def->varArgs)) // variadic macro with at least as many
2723 // params as the non-variadic part (see bug731985)
2724 {
2725 uint32_t k=0;
2726 // substitution of all formal arguments
2727 QCString resExpr;
2728 const QCString d=def->definition.stripWhiteSpace();
2729 //printf("Macro definition: '%s'\n",qPrint(d));
2730 bool inString=FALSE;
2731 while (k<d.length())
2732 {
2733 if (d.at(k)=='@') // maybe a marker, otherwise an escaped @
2734 {
2735 if (d.at(k+1)=='@') // escaped @ => copy it (is unescaped later)
2736 {
2737 k+=2;
2738 resExpr+="@@"; // we unescape these later
2739 }
2740 else if (d.at(k+1)=='-') // no-rescan marker
2741 {
2742 k+=2;
2743 resExpr+="@-";
2744 }
2745 else // argument marker => read the argument number
2746 {
2747 QCString key="@";
2748 bool hash=FALSE;
2749 int l=k-1;
2750 // search for ## backward
2751 if (l>=0 && d.at(l)=='"') l--;
2752 while (l>=0 && d.at(l)==' ') l--;
2753 if (l>0 && d.at(l)=='#' && d.at(l-1)=='#') hash=TRUE;
2754 k++;
2755 // scan the number
2756 while (k<d.length() && d.at(k)>='0' && d.at(k)<='9') key+=d.at(k++);
2757 if (!hash)
2758 {
2759 // search for ## forward
2760 l=k;
2761 if (l<(int)d.length() && d.at(l)=='"') l++;
2762 while (l<(int)d.length() && d.at(l)==' ') l++;
2763 if (l<(int)d.length()-1 && d.at(l)=='#' && d.at(l+1)=='#') hash=TRUE;
2764 }
2765 //printf("request key %s result %s\n",qPrint(key),argTable[key]->data());
2766 auto it = argTable.find(key.str());
2767 if (it!=argTable.end())
2768 {
2769 QCString substArg = it->second.c_str();
2770 //printf("substArg='%s'\n",qPrint(substArg));
2771 // only if no ## operator is before or after the argument
2772 // marker we do macro expansion.
2773 if (!hash)
2774 {
2775 expandExpression(yyscanner,substArg,nullptr,0,level+1);
2776 }
2777 if (inString)
2778 {
2779 //printf("'%s'=stringize('%s')\n",qPrint(stringize(*subst)),subst->data());
2780
2781 // if the marker is inside a string (because a # was put
2782 // before the macro name) we must escape " and \ characters
2783 resExpr+=stringize(substArg);
2784 }
2785 else
2786 {
2787 if (hash && substArg.isEmpty())
2788 {
2789 resExpr+="@E"; // empty argument will be remove later on
2790 }
2791 resExpr+=substArg;
2792 }
2793 }
2794 }
2795 }
2796 else // no marker, just copy
2797 {
2798 if (!inString && d.at(k)=='\"')
2799 {
2800 inString=TRUE; // entering a literal string
2801 }
2802 else if (k>2 && inString && d.at(k)=='\"' && (d.at(k-1)!='\\' || d.at(k-2)=='\\'))
2803 {
2804 inString=FALSE; // leaving a literal string
2805 }
2806 resExpr+=d.at(k++);
2807 }
2808 }
2809 len=j-pos;
2810 result=resExpr;
2811 //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),state->levelGuard.size());
2812 return TRUE;
2813 }
2814 //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),state->levelGuard.size());
2815 return FALSE;
static QCString stringize(const QCString &s)
Definition pre.l:2392
2816}

References addTillEndOfString(), QCString::at(), QCString::clear(), Define::definition, expandExpression(), FALSE, found, getCurrentChar(), getNextChar(), QCString::isEmpty(), QCString::length(), Define::nargs, skipCommentMacroName(), QCString::sprintf(), QCString::str(), stringize(), QCString::stripWhiteSpace(), toStdString(), TRUE, unputChar(), and Define::varArgs.

Referenced by expandExpression().

◆ resolveTrigraph()

static char resolveTrigraph ( char c)
static

Definition at line 3745 of file pre.l.

3746{
3747 switch (c)
3748 {
3749 case '=': return '#';
3750 case '/': return '\\';
3751 case '\'': return '^';
3752 case '(': return '[';
3753 case ')': return ']';
3754 case '!': return '|';
3755 case '<': return '{';
3756 case '>': return '}';
3757 case '-': return '~';
3758 }
3759 return '?';
3760}

◆ returnCharToStream()

static void returnCharToStream ( yyscan_t yyscanner,
char c )
static

Definition at line 2517 of file pre.l.

2518{
2519 struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
2520 unput(c);
2521}

Referenced by getCurrentChar(), and unputChar().

◆ setCaseDone()

static void setCaseDone ( yyscan_t yyscanner,
bool value )
static

Definition at line 2205 of file pre.l.

2206{
2207 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
2208 state->levelGuard.top()=value;
2209}

◆ setFileName()

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

Definition at line 2149 of file pre.l.

2150{
2151 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
2152 bool ambig = false;
2153 FileInfo fi(name.str());
2154 state->fileName=fi.absFilePath();
2155 state->yyFileDef=findFileDef(Doxygen::inputNameLinkedMap,state->fileName,ambig);
2156 if (state->yyFileDef==nullptr) // if this is not an input file check if it is an include file
2157 {
2158 state->yyFileDef=findFileDef(Doxygen::includeNameLinkedMap,state->fileName,ambig);
2159 }
2160 //printf("setFileName(%s) state->fileName=%s state->yyFileDef=%p\n",
2161 // name,qPrint(state->fileName),state->yyFileDef);
2162 if (state->yyFileDef && state->yyFileDef->isReference()) state->yyFileDef=nullptr;
2163 state->insideIDL = getLanguageFromFileName(state->fileName)==SrcLangExt::IDL;
2164 state->insideCS = getLanguageFromFileName(state->fileName)==SrcLangExt::CSharp;
2165 state->insideFtn = getLanguageFromFileName(state->fileName)==SrcLangExt::Fortran;
2166 EntryType section = guessSection(state->fileName);
2167 state->isSource = section.isHeader() || section.isSource();
static FileNameLinkedMap * includeNameLinkedMap
Definition doxygen.h:102
Wrapper class for the Entry type.
Definition types.h:631
@ CSharp
Definition types.h:46
@ Fortran
Definition types.h:53
SrcLangExt getLanguageFromFileName(const QCString &fileName, SrcLangExt defLang)
Definition util.cpp:5549
EntryType guessSection(const QCString &name)
Definition util.cpp:349
2168}

References FileInfo::absFilePath(), CSharp, findFileDef(), Fortran, getLanguageFromFileName(), guessSection(), IDL, Doxygen::includeNameLinkedMap, Doxygen::inputNameLinkedMap, and QCString::str().

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

◆ skipCommentMacroName()

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

Definition at line 2535 of file pre.l.

2537{
2538 bool changed = false;
2539
2540 do
2541 {
2542 changed = false;
2543 while ((cc=getCurrentChar(yyscanner,expr,rest,j))!=EOF && cc!='\n' && isspace(cc))
2544 {
2545 len++;
2546 getNextChar(yyscanner,expr,rest,j);
2547 }
2548
2549 if (cc=='/') // possible start of a comment
2550 {
2551 int prevChar = '\0';
2552 getNextChar(yyscanner,expr,rest,j);
2553 if ((cc=getCurrentChar(yyscanner,expr,rest,j))!=EOF && cc == '*') // we have a comment
2554 {
2555 while ((cc=getNextChar(yyscanner,expr,rest,j))!=EOF && cc!=0)
2556 {
2557 if (cc == '/' && prevChar == '*') break; // we have an end of comment
2558 prevChar = cc;
2559 }
2560 if (cc != EOF) changed = true;
2561 }
2562 }
2563 } while (changed);
2564}

References getCurrentChar(), and getNextChar().

Referenced by replaceFunctionMacro().

◆ startCondSection()

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

Definition at line 3689 of file pre.l.

3690{
3691 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
3692 //printf("startCondSection: skip=%d stack=%d\n",state->skip,state->condStack.size());
3693 CondParser prs;
3694 bool expResult = prs.parse(state->fileName.data(),state->yyLineNr,sectId.data());
3695 state->condStack.emplace(std::make_unique<preYY_CondCtx>(state->fileName,state->yyLineNr,sectId,state->skip));
3696 if (!expResult)
3697 {
3698 state->skip=TRUE;
3699 }
3700 //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.
3701}

References QCString::data(), CondParser::parse(), and TRUE.

◆ stateToString()

static const char * stateToString ( int state)
static

◆ stringize()

static QCString stringize ( const QCString & s)
static

Definition at line 2392 of file pre.l.

2393{
2394 QCString result;
2395 uint32_t i=0;
2396 bool inString=FALSE;
2397 bool inChar=FALSE;
2398 char c,pc;
2399 while (i<s.length())
2400 {
2401 if (!inString && !inChar)
2402 {
2403 while (i<s.length() && !inString && !inChar)
2404 {
2405 c=s.at(i++);
2406 if (c=='"')
2407 {
2408 result+="\\\"";
2409 inString=TRUE;
2410 }
2411 else if (c=='\'')
2412 {
2413 result+=c;
2414 inChar=TRUE;
2415 }
2416 else
2417 {
2418 result+=c;
2419 }
2420 }
2421 }
2422 else if (inChar)
2423 {
2424 while (i<s.length() && inChar)
2425 {
2426 c=s.at(i++);
2427 if (c=='\'')
2428 {
2429 result+='\'';
2430 inChar=FALSE;
2431 }
2432 else if (c=='\\')
2433 {
2434 result+="\\\\";
2435 }
2436 else
2437 {
2438 result+=c;
2439 }
2440 }
2441 }
2442 else
2443 {
2444 pc=0;
2445 while (i<s.length() && inString)
2446 {
2447 c=s.at(i++);
2448 if (c=='"')
2449 {
2450 result+="\\\"";
2451 inString= pc=='\\';
2452 }
2453 else if (c=='\\')
2454 result+="\\\\";
2455 else
2456 result+=c;
2457 pc=c;
2458 }
2459 }
2460 }
2461 //printf("stringize '%s'->'%s'\n",qPrint(s),qPrint(result));
2462 return result;
2463}

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

Referenced by replaceFunctionMacro().

◆ unputChar()

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

Definition at line 3811 of file pre.l.

3812{
3813 //printf("unputChar(%s,%s,%d,%c)\n",qPrint(expr),rest ? rest->data() : 0,pos,c);
3814 if (pos<expr.length())
3815 {
3816 pos++;
3817 }
3818 else if (rest)
3819 {
3820 //printf(" prepending '%c' to rest!\n",c);
3821 char cs[2];cs[0]=c;cs[1]='\0';
3822 rest->prepend(cs);
3823 }
3824 else
3825 {
3826 //printf(" yyunput()='%c'\n",c);
3827 returnCharToStream(yyscanner,c);
3828 }
3829 //printf("result: unputChar(%s,%s,%d,%c)\n",qPrint(expr),rest ? rest->data() : 0,pos,c);
QCString & prepend(const char *s)
Definition qcstring.h:407
3830}

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

Referenced by addSeparatorsIfNeeded(), and replaceFunctionMacro().

◆ yylex()

int yylex ( yyscan_t yyscanner)

Definition at line 454 of file pre.l.

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

◆ yyread()

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

Definition at line 2128 of file pre.l.

2129{
2130 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
2131 int bytesInBuf = static_cast<int>(state->inputBuf->size())-state->inputBufPos;
2132 int bytesToCopy = std::min(max_size,bytesInBuf);
2133 memcpy(buf,state->inputBuf->data()+state->inputBufPos,bytesToCopy);
2134 state->inputBufPos+=bytesToCopy;
2135 return bytesToCopy;
2136}

Variable Documentation

◆ g_debugMutex

std::mutex g_debugMutex
static

Definition at line 232 of file pre.l.

Referenced by Preprocessor::processFile().

◆ g_defineManager

DefineManager g_defineManager
static

Definition at line 235 of file pre.l.

Referenced by checkAndOpenFile(), and readIncludeFile().

◆ g_globalDefineMutex

std::mutex g_globalDefineMutex
static

Definition at line 233 of file pre.l.

Referenced by checkAndOpenFile(), and readIncludeFile().

◆ g_updateGlobals

std::mutex g_updateGlobals
static

Definition at line 234 of file pre.l.

Referenced by Preprocessor::processFile().