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

Go to the source code of this file.

Classes

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

Macros

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

Typedefs

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

Functions

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

Definition at line 349 of file pre.l.

◆ YY_NO_UNISTD_H

#define YY_NO_UNISTD_H   1

Definition at line 68 of file pre.l.

◆ YY_TYPEDEF_YY_SCANNER_T

#define YY_TYPEDEF_YY_SCANNER_T

Definition at line 22 of file pre.l.

Typedef Documentation

◆ DefineMap

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

A dictionary of managed Define objects.

Definition at line 109 of file pre.l.

◆ yyscan_t

typedef yyguts_t* yyscan_t

Definition at line 24 of file pre.l.

Function Documentation

◆ addDefine()

void addDefine ( yyscan_t yyscanner)
static

Definition at line 3385 of file pre.l.

3386{
3387 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
3388 Define def;
3389 def.name = state->defName;
3390 def.definition = state->defText.stripWhiteSpace();
3391 def.nargs = state->defArgs;
3392 def.fileName = state->fileName;
3393 def.fileDef = state->yyFileDef;
3394 def.lineNr = state->yyLineNr-state->yyMLines;
3395 def.columnNr = state->yyColNr;
3396 def.varArgs = state->defVarArgs;
3397 //printf("newDefine: %s %s file: %s\n",qPrint(def.name),qPrint(def.definition),
3398 // def.fileDef ? qPrint(def.fileDef->name()) : qPrint(def.fileName));
3399 //printf("newDefine: '%s'->'%s'\n",qPrint(def.name),qPrint(def.definition));
3400 if (!def.name.isEmpty() &&
3402 {
3403 def.isPredefined=TRUE;
3405 }
3406 auto it = state->localDefines.find(def.name.str());
3407 if (it!=state->localDefines.end()) // redefine
3408 {
3409 state->localDefines.erase(it);
3410 }
3411 state->localDefines.emplace(def.name.str(),def);
A class representing a macro definition.
Definition define.h:31
int lineNr
Definition define.h:38
bool varArgs
Definition define.h:42
QCString fileName
Definition define.h:35
QCString name
Definition define.h:33
FileDef * fileDef
Definition define.h:37
bool isPredefined
Definition define.h:43
int columnNr
Definition define.h:39
QCString definition
Definition define.h:34
int nargs
Definition define.h:40
bool expandAsDefined
Definition define.h:45
static StringUnorderedSet expandAsDefinedSet
Definition doxygen.h:119
bool isEmpty() const
Returns TRUE iff the string is empty.
Definition qcstring.h:150
QCString stripWhiteSpace() const
returns a copy of this string with leading and trailing whitespace removed
Definition qcstring.h:245
const std::string & str() const
Definition qcstring.h:537
#define TRUE
Definition qcstring.h:37
3412}

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

void addMacroDefinition ( yyscan_t yyscanner)
static

Definition at line 3414 of file pre.l.

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

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

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

Definition at line 2882 of file pre.l.

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

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

Referenced by expandExpression().

◆ addTillEndOfString()

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

Definition at line 2526 of file pre.l.

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

References getNextChar(), and term.

Referenced by replaceFunctionMacro().

◆ checkAndOpenFile()

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

Definition at line 2214 of file pre.l.

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

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

Referenced by findFile().

◆ computeExpression()

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

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

Definition at line 3352 of file pre.l.

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

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

◆ decrLevel()

void decrLevel ( yyscan_t yyscanner)
static

Definition at line 2179 of file pre.l.

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

References warn.

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

◆ determineBlockName()

void determineBlockName ( yyscan_t yyscanner)
static

Definition at line 3506 of file pre.l.

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

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

◆ endCondSection()

void endCondSection ( yyscan_t yyscanner)
static

Definition at line 3706 of file pre.l.

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

References FALSE, and warn.

◆ escapeAt()

QCString escapeAt ( const QCString & text)
static

Definition at line 3733 of file pre.l.

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

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

◆ expandExpression()

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

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

Definition at line 2914 of file pre.l.

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

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

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

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

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

◆ extractTrailingComment()

QCString extractTrailingComment ( const QCString & s)
static

Definition at line 2345 of file pre.l.

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

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

◆ extraSpacing()

void extraSpacing ( yyscan_t yyscanner)
inlinestatic

Definition at line 3493 of file pre.l.

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

◆ findFile()

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

Definition at line 2271 of file pre.l.

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

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

◆ forceEndCondSection()

void forceEndCondSection ( yyscan_t yyscanner)
static

Definition at line 3723 of file pre.l.

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

References FALSE.

Referenced by Preprocessor::processFile().

◆ getCurrentChar()

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

Definition at line 3791 of file pre.l.

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

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

Referenced by replaceFunctionMacro(), and skipCommentMacroName().

◆ getFenceSize()

yy_size_t getFenceSize ( char * txt,
yy_size_t leng )
static

Definition at line 2140 of file pre.l.

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

◆ getLexerFILE()

const char * getLexerFILE ( )
inlinestatic

Definition at line 352 of file pre.l.

352{return __FILE__;}

◆ getNextChar()

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

Definition at line 3768 of file pre.l.

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

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

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

◆ getNextId()

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

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

Definition at line 2826 of file pre.l.

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

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

Referenced by expandExpression().

◆ incrLevel()

void incrLevel ( yyscan_t yyscanner)
static

Definition at line 2172 of file pre.l.

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

◆ initPredefined()

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

Definition at line 3867 of file pre.l.

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

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

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

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

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

Referenced by expandExpression().

◆ otherCaseDone()

bool otherCaseDone ( yyscan_t yyscanner)
static

Definition at line 2193 of file pre.l.

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

References TRUE, and warn.

◆ outputArray()

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

Definition at line 3464 of file pre.l.

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

◆ outputChar()

void outputChar ( yyscan_t yyscanner,
char c )
inlinestatic

Definition at line 3458 of file pre.l.

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

Referenced by outputSpace(), and outputSpaces().

◆ outputSpace()

void outputSpace ( yyscan_t yyscanner,
char c )
inlinestatic

Definition at line 3476 of file pre.l.

3477{
3478 if (c=='\t') outputChar(yyscanner,'\t');
3479 else outputChar(yyscanner,' ');
static void outputChar(yyscan_t yyscanner, char c)
Definition pre.l:3458
3480}

References outputChar().

◆ outputSpaces()

void outputSpaces ( yyscan_t yyscanner,
char * s )
inlinestatic

Definition at line 3482 of file pre.l.

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

References outputChar().

◆ outputString()

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

Definition at line 3470 of file pre.l.

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

References QCString::str().

Referenced by readIncludeFile().

◆ processConcatOperators()

void processConcatOperators ( QCString & expr)
static

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

Definition at line 2473 of file pre.l.

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

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

Referenced by expandExpression().

◆ processUntilMatchingTerminator()

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

Process string or character literal.

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

Definition at line 3059 of file pre.l.

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

References term.

Referenced by removeIdsAndMarkers(), and removeMarkers().

◆ readIncludeFile()

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

Definition at line 3539 of file pre.l.

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

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

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

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

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

Referenced by computeExpression().

◆ removeMarkers()

QCString removeMarkers ( const QCString & s)
static

replaces all occurrences of @ in s by @

assumption:
s only contains pairs of @'s

Definition at line 3290 of file pre.l.

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

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

Referenced by computeExpression(), and expandMacro().

◆ replaceFunctionMacro()

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

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

Definition at line 2576 of file pre.l.

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

References addTillEndOfString(), QCString::at(), QCString::clear(), Define::definition, expandExpression(), FALSE, 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()

char resolveTrigraph ( char c)
static

Definition at line 3748 of file pre.l.

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

◆ returnCharToStream()

void returnCharToStream ( yyscan_t yyscanner,
char c )
static

Definition at line 2520 of file pre.l.

2521{
2522 struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
2523 unput(c);
2524}

Referenced by getCurrentChar(), and unputChar().

◆ setCaseDone()

void setCaseDone ( yyscan_t yyscanner,
bool value )
static

Definition at line 2207 of file pre.l.

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

◆ setFileName()

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

Definition at line 2151 of file pre.l.

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

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

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

◆ skipCommentMacroName()

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

Definition at line 2538 of file pre.l.

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

References getCurrentChar(), and getNextChar().

Referenced by replaceFunctionMacro().

◆ startCondSection()

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

Definition at line 3692 of file pre.l.

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

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

◆ stateToString()

const char * stateToString ( int state)
static

◆ stringize()

QCString stringize ( const QCString & s)
static

Definition at line 2395 of file pre.l.

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

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

Referenced by replaceFunctionMacro().

◆ unputChar()

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

Definition at line 3814 of file pre.l.

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

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

Referenced by addSeparatorsIfNeeded(), and replaceFunctionMacro().

◆ yylex()

int yylex ( yyscan_t yyscanner)

Definition at line 456 of file pre.l.

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

◆ yyread()

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

Definition at line 2130 of file pre.l.

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

Variable Documentation

◆ g_debugMutex

std::mutex g_debugMutex
static

Definition at line 233 of file pre.l.

Referenced by Preprocessor::processFile().

◆ g_defineManager

DefineManager g_defineManager
static

Definition at line 236 of file pre.l.

Referenced by checkAndOpenFile(), and readIncludeFile().

◆ g_globalDefineMutex

std::mutex g_globalDefineMutex
static

Definition at line 234 of file pre.l.

Referenced by checkAndOpenFile(), and readIncludeFile().

◆ g_updateGlobals

std::mutex g_updateGlobals
static

Definition at line 235 of file pre.l.

Referenced by Preprocessor::processFile().