Doxygen
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 2879 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:3989

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

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

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

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

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

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

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

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

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

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

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

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

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

◆ decrLevel()

void decrLevel ( yyscan_t yyscanner)
static

Definition at line 2178 of file pre.l.

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

References warn.

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

◆ determineBlockName()

void determineBlockName ( yyscan_t yyscanner)
static

Definition at line 3505 of file pre.l.

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

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

◆ endCondSection()

void endCondSection ( yyscan_t yyscanner)
static

Definition at line 3705 of file pre.l.

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

References FALSE, and warn.

◆ escapeAt()

QCString escapeAt ( const QCString & text)
static

Definition at line 3732 of file pre.l.

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

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

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

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

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

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

◆ extractTrailingComment()

QCString extractTrailingComment ( const QCString & s)
static

Definition at line 2344 of file pre.l.

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

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

◆ extraSpacing()

void extraSpacing ( yyscan_t yyscanner)
inlinestatic

Definition at line 3492 of file pre.l.

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

◆ findFile()

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

Definition at line 2270 of file pre.l.

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

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

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

References FALSE.

Referenced by Preprocessor::processFile().

◆ getCurrentChar()

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

Definition at line 3790 of file pre.l.

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

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

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

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

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

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

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

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

Referenced by expandExpression().

◆ incrLevel()

void incrLevel ( yyscan_t yyscanner)
static

Definition at line 2171 of file pre.l.

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

◆ initPredefined()

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

Definition at line 3866 of file pre.l.

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

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

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

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

Referenced by expandExpression().

◆ otherCaseDone()

bool otherCaseDone ( yyscan_t yyscanner)
static

Definition at line 2192 of file pre.l.

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

References TRUE, and warn.

◆ outputArray()

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

Definition at line 3463 of file pre.l.

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

◆ outputChar()

void outputChar ( yyscan_t yyscanner,
char c )
inlinestatic

Definition at line 3457 of file pre.l.

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

Referenced by outputSpace(), and outputSpaces().

◆ outputSpace()

void outputSpace ( yyscan_t yyscanner,
char c )
inlinestatic

Definition at line 3475 of file pre.l.

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

References outputChar().

◆ outputSpaces()

void outputSpaces ( yyscan_t yyscanner,
char * s )
inlinestatic

Definition at line 3481 of file pre.l.

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

References outputChar().

◆ outputString()

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

Definition at line 3469 of file pre.l.

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

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

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

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

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

References term.

Referenced by removeIdsAndMarkers(), and removeMarkers().

◆ readIncludeFile()

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

Definition at line 3538 of file pre.l.

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

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

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

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

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

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

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

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

Referenced by expandExpression().

◆ resolveTrigraph()

char resolveTrigraph ( char c)
static

Definition at line 3747 of file pre.l.

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

◆ returnCharToStream()

void returnCharToStream ( yyscan_t yyscanner,
char c )
static

Definition at line 2519 of file pre.l.

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

Referenced by getCurrentChar(), and unputChar().

◆ setCaseDone()

void setCaseDone ( yyscan_t yyscanner,
bool value )
static

Definition at line 2206 of file pre.l.

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

◆ setFileName()

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

Definition at line 2150 of file pre.l.

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

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

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

References getCurrentChar(), and getNextChar().

Referenced by replaceFunctionMacro().

◆ startCondSection()

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

Definition at line 3691 of file pre.l.

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

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

◆ stateToString()

const char * stateToString ( int state)
static

◆ stringize()

QCString stringize ( const QCString & s)
static

Definition at line 2394 of file pre.l.

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

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

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

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

Referenced by addSeparatorsIfNeeded(), and replaceFunctionMacro().

◆ yylex()

int yylex ( yyscan_t yyscanner)

Definition at line 455 of file pre.l.

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

◆ yyread()

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

Definition at line 2129 of file pre.l.

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

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