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 2876 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:2127

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

3382{
3383 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
3384 Define def;
3385 def.name = state->defName;
3386 def.definition = state->defText.stripWhiteSpace();
3387 def.nargs = state->defArgs;
3388 def.fileName = state->fileName;
3389 def.fileDef = state->yyFileDef;
3390 def.lineNr = state->yyLineNr-state->yyMLines;
3391 def.columnNr = state->yyColNr;
3392 def.varArgs = state->defVarArgs;
3393 //printf("newDefine: %s %s file: %s\n",qPrint(def.name),qPrint(def.definition),
3394 // def.fileDef ? qPrint(def.fileDef->name()) : qPrint(def.fileName));
3395 //printf("newDefine: '%s'->'%s'\n",qPrint(def.name),qPrint(def.definition));
3396 if (!def.name.isEmpty() &&
3398 {
3399 def.isPredefined=TRUE;
3401 }
3402 auto it = state->localDefines.find(def.name.str());
3403 if (it!=state->localDefines.end()) // redefine
3404 {
3405 state->localDefines.erase(it);
3406 }
3407 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:526
#define TRUE
Definition qcstring.h:37
3408}

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

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

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

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

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

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

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

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

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

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

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

◆ decrLevel()

static void decrLevel ( yyscan_t yyscanner)
static

Definition at line 2176 of file pre.l.

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

References warn.

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

◆ determineBlockName()

static void determineBlockName ( yyscan_t yyscanner)
static

Definition at line 3502 of file pre.l.

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

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

◆ endCondSection()

static void endCondSection ( yyscan_t yyscanner)
static

Definition at line 3702 of file pre.l.

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

References FALSE, and warn.

◆ escapeAt()

static QCString escapeAt ( const QCString & text)
static

Definition at line 3729 of file pre.l.

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

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

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

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

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

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

◆ extractTrailingComment()

static QCString extractTrailingComment ( const QCString & s)
static

Definition at line 2341 of file pre.l.

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

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

◆ extraSpacing()

static void extraSpacing ( yyscan_t yyscanner)
inlinestatic

Definition at line 3489 of file pre.l.

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

◆ findFile()

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

Definition at line 2267 of file pre.l.

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

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

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

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

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

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

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

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

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

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

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

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

Referenced by expandExpression().

◆ incrLevel()

static void incrLevel ( yyscan_t yyscanner)
static

Definition at line 2169 of file pre.l.

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

◆ initPredefined()

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

Definition at line 3863 of file pre.l.

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

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

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

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

Referenced by expandExpression().

◆ otherCaseDone()

static bool otherCaseDone ( yyscan_t yyscanner)
static

Definition at line 2190 of file pre.l.

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

References TRUE, and warn.

◆ outputArray()

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

Definition at line 3460 of file pre.l.

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

◆ outputChar()

static void outputChar ( yyscan_t yyscanner,
char c )
inlinestatic

Definition at line 3454 of file pre.l.

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

Referenced by outputSpace(), and outputSpaces().

◆ outputSpace()

static void outputSpace ( yyscan_t yyscanner,
char c )
inlinestatic

Definition at line 3472 of file pre.l.

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

References outputChar().

◆ outputSpaces()

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

Definition at line 3478 of file pre.l.

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

References outputChar().

◆ outputString()

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

Definition at line 3466 of file pre.l.

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

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

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

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

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

References term.

Referenced by removeIdsAndMarkers(), and removeMarkers().

◆ readIncludeFile()

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

Definition at line 3535 of file pre.l.

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

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

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

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

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

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

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

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

3745{
3746 switch (c)
3747 {
3748 case '=': return '#';
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 }
3758 return '?';
3759}

◆ returnCharToStream()

static void returnCharToStream ( yyscan_t yyscanner,
char c )
static

Definition at line 2516 of file pre.l.

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

Referenced by getCurrentChar(), and unputChar().

◆ setCaseDone()

static void setCaseDone ( yyscan_t yyscanner,
bool value )
static

Definition at line 2204 of file pre.l.

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

◆ setFileName()

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

Definition at line 2148 of file pre.l.

2149{
2150 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
2151 bool ambig = false;
2152 FileInfo fi(name.str());
2153 state->fileName=fi.absFilePath();
2154 state->yyFileDef=findFileDef(Doxygen::inputNameLinkedMap,state->fileName,ambig);
2155 if (state->yyFileDef==nullptr) // if this is not an input file check if it is an include file
2156 {
2157 state->yyFileDef=findFileDef(Doxygen::includeNameLinkedMap,state->fileName,ambig);
2158 }
2159 //printf("setFileName(%s) state->fileName=%s state->yyFileDef=%p\n",
2160 // name,qPrint(state->fileName),state->yyFileDef);
2161 if (state->yyFileDef && state->yyFileDef->isReference()) state->yyFileDef=nullptr;
2162 state->insideIDL = getLanguageFromFileName(state->fileName)==SrcLangExt::IDL;
2163 state->insideCS = getLanguageFromFileName(state->fileName)==SrcLangExt::CSharp;
2164 state->insideFtn = getLanguageFromFileName(state->fileName)==SrcLangExt::Fortran;
2165 EntryType section = guessSection(state->fileName);
2166 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
2167}

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

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

References getCurrentChar(), and getNextChar().

Referenced by replaceFunctionMacro().

◆ startCondSection()

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

Definition at line 3688 of file pre.l.

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

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

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

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

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

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:3744
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:3460
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:3367
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:3535
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:2169
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:2190
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:2204
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:2176
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:3348
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:3478
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:3489
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:2137
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:3502
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:3688
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:3702
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:3729
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 //printf("error: define %s is defined more than once!\n",qPrint(yyextra->defName));
1930 }
1931 }
1932 yyextra->argMap.clear();
1933 yyextra->yyLineNr++;
1934 yyextra->yyColNr=1;
1935 yyextra->lastGuardName.clear();
1936 BEGIN(Start);
1937 }
static void addMacroDefinition(yyscan_t yyscanner)
Definition pre.l:3410
static void addDefine(yyscan_t yyscanner)
Definition pre.l:3381
static QCString extractTrailingComment(const QCString &s)
Definition pre.l:2341
const char * comment
1938<DefineText>{B}* { outputString(yyscanner,yytext);
1939 yyextra->defText += ' ';
1940 yyextra->defLitText+=yytext;
1941 }
1942<DefineText>{B}*"##"{B}* { outputString(yyscanner,substitute(yytext,"##"," "));
1943 yyextra->defText += "##";
1944 yyextra->defLitText+=yytext;
1945 }
1946<DefineText>"@" { outputString(yyscanner,substitute(yytext,"@@"," "));
1947 yyextra->defText += "@@";
1948 yyextra->defLitText+=yytext;
1949 }
1950<DefineText>\" {
1951 outputChar(yyscanner,' ');
1952 yyextra->defText += *yytext;
1953 yyextra->defLitText+=yytext;
1954 if (!yyextra->insideComment)
1955 {
1956 BEGIN(SkipDoubleQuote);
1957 }
1958 }
1959<DefineText>\' {
1960 outputChar(yyscanner,' ');
1961 yyextra->defText += *yytext;
1962 yyextra->defLitText+=yytext;
1963 if (!yyextra->insideComment)
1964 {
1965 BEGIN(SkipSingleQuote);
1966 }
1967 }
1968<SkipDoubleQuote>{CPPC}[/]? { outputSpaces(yyscanner,yytext);
1969 yyextra->defText += yytext;
1970 yyextra->defLitText+=yytext;
1971 }
1972<SkipDoubleQuote>{CCS}[*]? { outputSpaces(yyscanner,yytext);
1973 yyextra->defText += yytext;
1974 yyextra->defLitText+=yytext;
1975 }
1976<SkipDoubleQuote>\" {
1977 outputChar(yyscanner,' ');
1978 yyextra->defText += *yytext;
1979 yyextra->defLitText+=yytext;
1980 BEGIN(DefineText);
1981 }
1982<SkipSingleQuote,SkipDoubleQuote>\\. {
1983 outputSpaces(yyscanner,yytext);
1984 yyextra->defText += yytext;
1985 yyextra->defLitText+=yytext;
1986 }
1987<SkipSingleQuote>\' {
1988 outputChar(yyscanner,' ');
1989 yyextra->defText += *yytext;
1990 yyextra->defLitText+=yytext;
1991 BEGIN(DefineText);
1992 }
1993<SkipDoubleQuote,SkipSingleQuote>. { outputSpace(yyscanner,yytext[0]);
1994 yyextra->defText += *yytext;
1995 yyextra->defLitText += *yytext;
1996 }
1997<DefineText>. { outputSpace(yyscanner,yytext[0]);
1998 yyextra->defText += *yytext;
1999 yyextra->defLitText += *yytext;
2000 }
2001<<EOF>> {
2002 TRACE("End of include file");
2003 //printf("Include stack depth=%d\n",yyextra->includeStack.size());
2004 if (yyextra->includeStack.empty())
2005 {
2006 TRACE("Terminating scanner");
2007 yyterminate();
2008 }
2009 else
2010 {
2011 QCString toFileName = yyextra->fileName;
2012 const std::unique_ptr<FileState> &fs=yyextra->includeStack.back();
2013 //fileDefineCache->merge(yyextra->fileName,fs->fileName);
2014 YY_BUFFER_STATE oldBuf = YY_CURRENT_BUFFER;
2015 yy_switch_to_buffer( fs->bufState, yyscanner );
2016 yy_delete_buffer( oldBuf, yyscanner );
2017 yyextra->yyLineNr = fs->lineNr;
2018 //preYYin = fs->oldYYin;
2019 yyextra->inputBuf = fs->oldFileBuf;
2020 yyextra->inputBufPos = fs->oldFileBufPos;
2021 yyextra->curlyCount = fs->curlyCount;
2022 setFileName(yyscanner,fs->fileName);
2023 TRACE("switching to {}",yyextra->fileName);
#define yyterminate()
#define TRACE(...)
Definition trace.h:77
2024
2025 // Deal with file changes due to
2026 // #include's within { .. } blocks
2027 QCString lineStr(15+yyextra->fileName.length(), QCString::ExplicitSize);
2028 lineStr.sprintf("# %d \"%s\" 2",yyextra->yyLineNr,qPrint(yyextra->fileName));
2029 outputString(yyscanner,lineStr);
2030
2031 yyextra->includeStack.pop_back();
2032
2033 {
2034 std::lock_guard<std::mutex> lock(g_globalDefineMutex);
2035 // to avoid deadlocks we allow multiple threads to process the same header file.
2036 // The first one to finish will store the results globally. After that the
2037 // next time the same file is encountered, the stored data is used and the file
2038 // is not processed again.
2039 if (!g_defineManager.alreadyProcessed(toFileName.str()))
2040 {
2041 // now that the file is completely processed, prevent it from processing it again
2042 g_defineManager.addInclude(yyextra->fileName.str(),toFileName.str());
2043 g_defineManager.store(toFileName.str(),yyextra->localDefines);
2044 }
2045 else
2046 {
2048 {
2049 Debug::print(Debug::Preprocessor,0,"#include %s: was already processed by another thread! not storing data...\n",qPrint(toFileName));
2050 }
2051 }
2052 }
2053 // move the local macros definitions for in this file to the translation unit context
2054 for (const auto &kv : yyextra->localDefines)
2055 {
2056 auto pair = yyextra->contextDefines.insert(kv);
2057 if (!pair.second) // define already in context -> replace with local version
2058 {
2059 yyextra->contextDefines.erase(pair.first);
2060 yyextra->contextDefines.insert(kv);
2061 }
2062 }
2063 yyextra->localDefines.clear();
2064 }
2065 }
2066<*>{CCS}/{CCE} |
2067<*>{CCS}[*!]? {
2068 if (YY_START==SkipVerbatim || YY_START == SkipCondVerbatim || YY_START==SkipCond || YY_START==IDLquote || YY_START == PragmaOnce)
2069 {
2070 REJECT;
2071 }
2072 else
2073 {
2074 outputArray(yyscanner,yytext,yyleng);
2075 yyextra->lastCContext=YY_START;
2076 yyextra->commentCount=1;
2077 if (yyleng==3)
2078 {
2079 yyextra->isSpecialComment = true;
2080 yyextra->lastGuardName.clear(); // reset guard in case the #define is documented!
2081 }
2082 else
2083 {
2084 yyextra->isSpecialComment = false;
2085 }
2086 BEGIN(SkipCComment);
2087 }
2088 }
2089<*>{CPPC}[/!]? {
2090 if (YY_START==SkipVerbatim || YY_START == SkipCondVerbatim || YY_START==SkipCond || getLanguageFromFileName(yyextra->fileName)==SrcLangExt::Fortran || YY_START==IDLquote || YY_START == PragmaOnce)
2091 {
2092 REJECT;
2093 }
2094 else if (YY_START==RulesRoundDouble)
2095 {
2096 REJECT;
2097 }
2098 else
2099 {
2100 outputArray(yyscanner,yytext,yyleng);
2101 yyextra->lastCPPContext=YY_START;
2102 if (yyleng==3)
2103 {
2104 yyextra->isSpecialComment = true;
2105 yyextra->lastGuardName.clear(); // reset guard in case the #define is documented!
2106 }
2107 else
2108 {
2109 yyextra->isSpecialComment = false;
2110 }
2111 BEGIN(SkipCPPComment);
2112 }
2113 }
2114<*>\n {
2115 outputChar(yyscanner,'\n');
2116 yyextra->yyLineNr++;
2117 }
2118<*>. {
2119 yyextra->expectGuard = FALSE;
2120 outputChar(yyscanner,*yytext);
2121 }
2122
2123%%

◆ yyread()

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

Definition at line 2127 of file pre.l.

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

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().