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

Referenced by expandExpression().

◆ YY_INPUT

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

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

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

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

◆ addMacroDefinition()

void addMacroDefinition ( yyscan_t yyscanner)
static

Definition at line 3411 of file pre.l.

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

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

◆ addSeparatorsIfNeeded()

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

Definition at line 2879 of file pre.l.

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

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

Referenced by expandExpression().

◆ addTillEndOfString()

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

Definition at line 2523 of file pre.l.

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

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

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

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

3350{
3351 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
3352 QCString e=expr;
3353 QCString ee=expr;
3354 ee = removeMarkers(ee);
3355 state->expanded.clear();
3356 expandExpression(yyscanner,e,nullptr,0,0);
3357 //printf("after expansion '%s'\n",qPrint(e));
3358 e = removeIdsAndMarkers(e);
3359 if (e.isEmpty()) return FALSE;
3360 //printf("parsing '%s'\n",qPrint(e));
3361 return state->constExpParser.parse(state->fileName.data(),state->yyLineNr,e.str(),ee.str());
static bool expandExpression(yyscan_t yyscanner, QCString &expr, QCString *rest, int pos, int level)
Definition pre.l:2911
static QCString removeIdsAndMarkers(const QCString &s)
Definition pre.l:3092
static QCString removeMarkers(const QCString &s)
Definition pre.l:3287
3362}

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

◆ decrLevel()

void decrLevel ( yyscan_t yyscanner)
static

Definition at line 2176 of file pre.l.

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

References warn.

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

◆ determineBlockName()

void determineBlockName ( yyscan_t yyscanner)
static

Definition at line 3503 of file pre.l.

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

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

◆ endCondSection()

void endCondSection ( yyscan_t yyscanner)
static

Definition at line 3703 of file pre.l.

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

References FALSE, and warn.

◆ escapeAt()

QCString escapeAt ( const QCString & text)
static

Definition at line 3730 of file pre.l.

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

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

◆ expandExpression()

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

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

Definition at line 2911 of file pre.l.

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

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

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

◆ expandMacro()

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

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

Definition at line 3368 of file pre.l.

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

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

◆ extractTrailingComment()

QCString extractTrailingComment ( const QCString & s)
static

Definition at line 2342 of file pre.l.

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

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

◆ extraSpacing()

void extraSpacing ( yyscan_t yyscanner)
inlinestatic

Definition at line 3490 of file pre.l.

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

◆ findFile()

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

Definition at line 2268 of file pre.l.

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

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

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

References FALSE.

Referenced by Preprocessor::processFile().

◆ getCurrentChar()

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

Definition at line 3788 of file pre.l.

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

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

Referenced by replaceFunctionMacro(), and skipCommentMacroName().

◆ getFenceSize()

yy_size_t getFenceSize ( char * txt,
yy_size_t leng )
static

Definition at line 2137 of file pre.l.

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

◆ getLexerFILE()

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

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

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

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

◆ getNextId()

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

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

Definition at line 2823 of file pre.l.

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

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

Referenced by expandExpression().

◆ incrLevel()

void incrLevel ( yyscan_t yyscanner)
static

Definition at line 2169 of file pre.l.

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

◆ initPredefined()

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

Definition at line 3864 of file pre.l.

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

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

Referenced by Preprocessor::processFile().

◆ isDefined()

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

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

Definition at line 3835 of file pre.l.

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

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

Referenced by expandExpression().

◆ otherCaseDone()

bool otherCaseDone ( yyscan_t yyscanner)
static

Definition at line 2190 of file pre.l.

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

References TRUE, and warn.

◆ outputArray()

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

Definition at line 3461 of file pre.l.

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

◆ outputChar()

void outputChar ( yyscan_t yyscanner,
char c )
inlinestatic

Definition at line 3455 of file pre.l.

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

Referenced by outputSpace(), and outputSpaces().

◆ outputSpace()

void outputSpace ( yyscan_t yyscanner,
char c )
inlinestatic

Definition at line 3473 of file pre.l.

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

References outputChar().

◆ outputSpaces()

void outputSpaces ( yyscan_t yyscanner,
char * s )
inlinestatic

Definition at line 3479 of file pre.l.

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

References outputChar().

◆ outputString()

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

Definition at line 3467 of file pre.l.

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

References QCString::str().

Referenced by readIncludeFile().

◆ processConcatOperators()

void processConcatOperators ( QCString & expr)
static

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

Definition at line 2470 of file pre.l.

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

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

Referenced by expandExpression().

◆ processUntilMatchingTerminator()

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

Process string or character literal.

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

Definition at line 3056 of file pre.l.

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

References term.

Referenced by removeIdsAndMarkers(), and removeMarkers().

◆ readIncludeFile()

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

Definition at line 3536 of file pre.l.

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

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

◆ removeIdsAndMarkers()

QCString removeIdsAndMarkers ( const QCString & s)
static

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

Definition at line 3092 of file pre.l.

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

References QCString::data(), FALSE, 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 3287 of file pre.l.

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

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

Referenced by computeExpression(), and expandMacro().

◆ replaceFunctionMacro()

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

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

Definition at line 2573 of file pre.l.

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

References addTillEndOfString(), QCString::at(), QCString::clear(), Define::definition, expandExpression(), FALSE, 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 3745 of file pre.l.

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

◆ returnCharToStream()

void returnCharToStream ( yyscan_t yyscanner,
char c )
static

Definition at line 2517 of file pre.l.

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

Referenced by getCurrentChar(), and unputChar().

◆ setCaseDone()

void setCaseDone ( yyscan_t yyscanner,
bool value )
static

Definition at line 2204 of file pre.l.

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

◆ setFileName()

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

Definition at line 2148 of file pre.l.

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

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

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

References getCurrentChar(), and getNextChar().

Referenced by replaceFunctionMacro().

◆ startCondSection()

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

Definition at line 3689 of file pre.l.

3690{
3691 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
3692 //printf("startCondSection: skip=%d stack=%d\n",state->skip,state->condStack.size());
3693 CondParser prs;
3694 bool expResult = prs.parse(state->fileName.data(),state->yyLineNr,sectId.data());
3695 state->condStack.emplace(std::make_unique<preYY_CondCtx>(state->fileName,state->yyLineNr,sectId,state->skip));
3696 if (!expResult)
3697 {
3698 state->skip=TRUE;
3699 }
3700 //printf(" expResult=%d skip=%d\n",expResult,state->skip);
Copyright (C) 1997-2015 by Dimitri van Heesch.
Definition condparser.h:28
bool parse(const QCString &fileName, int lineNr, const QCString &expr)
Copyright (C) 1997-2015 by Dimitri van Heesch.
3701}

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

◆ stateToString()

const char * stateToString ( int state)
static

◆ stringize()

QCString stringize ( const QCString & s)
static

Definition at line 2392 of file pre.l.

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

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

Referenced by replaceFunctionMacro().

◆ unputChar()

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

Definition at line 3811 of file pre.l.

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

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

Referenced by addSeparatorsIfNeeded(), and replaceFunctionMacro().

◆ yylex()

int yylex ( yyscan_t yyscanner)

Definition at line 456 of file pre.l.

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

◆ yyread()

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

Definition at line 2127 of file pre.l.

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

Variable Documentation

◆ g_debugMutex

std::mutex g_debugMutex
static

Definition at line 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().