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

Go to the source code of this file.

Classes

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

Macros

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

Typedefs

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

Functions

static const char * stateToString (int state)
 
static QCString escapeAt (const QCString &text)
 
static QCString extractTrailingComment (const QCString &s)
 
static char resolveTrigraph (char c)
 
static void outputArray (yyscan_t yyscanner, const char *a, yy_size_t len)
 
static void outputString (yyscan_t yyscanner, const QCString &s)
 
static void outputChar (yyscan_t yyscanner, char c)
 
static void outputSpaces (yyscan_t yyscanner, char *s)
 
static void outputSpace (yyscan_t yyscanner, char c)
 
static void extraSpacing (yyscan_t yyscanner)
 
static QCString expandMacro (yyscan_t yyscanner, const QCString &name)
 
static void readIncludeFile (yyscan_t yyscanner, const QCString &inc)
 
static void incrLevel (yyscan_t yyscanner)
 
static void decrLevel (yyscan_t yyscanner)
 
static void setCaseDone (yyscan_t yyscanner, bool value)
 
static bool otherCaseDone (yyscan_t yyscanner)
 
static bool computeExpression (yyscan_t yyscanner, const QCString &expr)
 
static void startCondSection (yyscan_t yyscanner, const QCString &sectId)
 
static void endCondSection (yyscan_t yyscanner)
 
static void addMacroDefinition (yyscan_t yyscanner)
 
static void addDefine (yyscan_t yyscanner)
 
static void setFileName (yyscan_t yyscanner, const QCString &name)
 
static int yyread (yyscan_t yyscanner, char *buf, int max_size)
 
static DefineisDefined (yyscan_t yyscanner, const QCString &name)
 Returns a reference to a Define object given its name or 0 if the Define does not exist.
 
static void determineBlockName (yyscan_t yyscanner)
 
static yy_size_t getFenceSize (char *txt, yy_size_t leng)
 
static const char * getLexerFILE ()
 
int yylex (yyscan_t yyscanner)
 
static std::unique_ptr< FileStatecheckAndOpenFile (yyscan_t yyscanner, const QCString &fileName, bool &alreadyProcessed)
 
static std::unique_ptr< FileStatefindFile (yyscan_t yyscanner, const QCString &fileName, bool localInclude, bool &alreadyProcessed)
 
static int getNextChar (yyscan_t yyscanner, const QCString &expr, QCString *rest, uint32_t &pos)
 
static int getCurrentChar (yyscan_t yyscanner, const QCString &expr, QCString *rest, uint32_t pos)
 
static void unputChar (yyscan_t yyscanner, const QCString &expr, QCString *rest, uint32_t &pos, char c)
 
static bool expandExpression (yyscan_t yyscanner, QCString &expr, QCString *rest, int pos, int level)
 
static QCString stringize (const QCString &s)
 
static void processConcatOperators (QCString &expr)
 
static void returnCharToStream (yyscan_t yyscanner, char c)
 
static void addTillEndOfString (yyscan_t yyscanner, const QCString &expr, QCString *rest, uint32_t &pos, char term, QCString &arg)
 
static void skipCommentMacroName (yyscan_t yyscanner, const QCString &expr, QCString *rest, int &cc, uint32_t &j, int &len)
 
static bool replaceFunctionMacro (yyscan_t yyscanner, const QCString &expr, QCString *rest, int pos, int &len, const Define *def, QCString &result, int level)
 
static int getNextId (const QCString &expr, int p, int *l)
 
static void addSeparatorsIfNeeded (yyscan_t yyscanner, const QCString &expr, QCString &resultExpr, QCString &restExpr, int pos)
 
static const char * processUntilMatchingTerminator (const char *inputStr, QCString &result)
 Process string or character literal.
 
static QCString removeIdsAndMarkers (const QCString &s)
 
static QCString removeMarkers (const QCString &s)
 
static void forceEndCondSection (yyscan_t yyscanner)
 
static void initPredefined (yyscan_t yyscanner, const QCString &fileName)
 

Variables

static std::mutex g_debugMutex
 
static std::mutex g_globalDefineMutex
 
static std::mutex g_updateGlobals
 
static DefineManager g_defineManager
 

Macro Definition Documentation

◆ MAX_EXPANSION_DEPTH

#define MAX_EXPANSION_DEPTH   50

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

static void addDefine ( yyscan_t yyscanner)
static

Definition at line 3383 of file pre.l.

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

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

◆ addMacroDefinition()

static void addMacroDefinition ( yyscan_t yyscanner)
static

Definition at line 3412 of file pre.l.

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

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

◆ addSeparatorsIfNeeded()

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

Definition at line 2880 of file pre.l.

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

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

Referenced by expandExpression().

◆ addTillEndOfString()

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

Definition at line 2524 of file pre.l.

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

References getNextChar(), and term.

Referenced by replaceFunctionMacro().

◆ checkAndOpenFile()

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

Definition at line 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:6157
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 fs->oldFileBuf = state->inputBuf;
2263 fs->oldFileBufPos = state->inputBufPos;
2264 }
2265 }
2266 return fs;
bool readInputFile(const QCString &fileName, std::string &contents, bool filter, bool isSourceCode)
read a file name fileName and optionally filter and transcode it
Definition util.cpp:5997
2267}

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

Referenced by findFile().

◆ computeExpression()

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

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

Definition at line 3350 of file pre.l.

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

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

◆ decrLevel()

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

static void determineBlockName ( yyscan_t yyscanner)
static

Definition at line 3504 of file pre.l.

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

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

◆ endCondSection()

static void endCondSection ( yyscan_t yyscanner)
static

Definition at line 3704 of file pre.l.

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

References FALSE, and warn.

◆ escapeAt()

static QCString escapeAt ( const QCString & text)
static

Definition at line 3731 of file pre.l.

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

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

◆ expandExpression()

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

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

Definition at line 2912 of file pre.l.

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

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

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

◆ expandMacro()

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

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

Definition at line 3369 of file pre.l.

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

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

◆ extractTrailingComment()

static QCString extractTrailingComment ( const QCString & s)
static

Definition at line 2343 of file pre.l.

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

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

◆ extraSpacing()

static void extraSpacing ( yyscan_t yyscanner)
inlinestatic

Definition at line 3491 of file pre.l.

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

◆ findFile()

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

Definition at line 2269 of file pre.l.

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

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

◆ forceEndCondSection()

static void forceEndCondSection ( yyscan_t yyscanner)
static

Definition at line 3721 of file pre.l.

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

References FALSE.

Referenced by Preprocessor::processFile().

◆ getCurrentChar()

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

Definition at line 3789 of file pre.l.

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

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

Referenced by replaceFunctionMacro(), and skipCommentMacroName().

◆ getFenceSize()

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

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

static const char * getLexerFILE ( )
inlinestatic

Definition at line 352 of file pre.l.

352{return __FILE__;}

◆ getNextChar()

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

Definition at line 3766 of file pre.l.

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

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

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

◆ getNextId()

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

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

Definition at line 2824 of file pre.l.

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

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

Referenced by expandExpression().

◆ incrLevel()

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

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

Definition at line 3865 of file pre.l.

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

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

Referenced by Preprocessor::processFile().

◆ isDefined()

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

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

Definition at line 3836 of file pre.l.

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

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

Referenced by expandExpression().

◆ otherCaseDone()

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

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

Definition at line 3462 of file pre.l.

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

◆ outputChar()

static void outputChar ( yyscan_t yyscanner,
char c )
inlinestatic

Definition at line 3456 of file pre.l.

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

Referenced by outputSpace(), and outputSpaces().

◆ outputSpace()

static void outputSpace ( yyscan_t yyscanner,
char c )
inlinestatic

Definition at line 3474 of file pre.l.

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

References outputChar().

◆ outputSpaces()

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

Definition at line 3480 of file pre.l.

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

References outputChar().

◆ outputString()

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

Definition at line 3468 of file pre.l.

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

References QCString::str().

Referenced by readIncludeFile().

◆ processConcatOperators()

static void processConcatOperators ( QCString & expr)
static

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

Definition at line 2471 of file pre.l.

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

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

Referenced by expandExpression().

◆ processUntilMatchingTerminator()

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

Process string or character literal.

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

Definition at line 3057 of file pre.l.

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

References term.

Referenced by removeIdsAndMarkers(), and removeMarkers().

◆ readIncludeFile()

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

Definition at line 3537 of file pre.l.

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

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

◆ removeIdsAndMarkers()

static QCString removeIdsAndMarkers ( const QCString & s)
static

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

Definition at line 3093 of file pre.l.

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

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

Referenced by computeExpression().

◆ removeMarkers()

static QCString removeMarkers ( const QCString & s)
static

replaces all occurrences of @ in s by @

assumption:
s only contains pairs of @'s

Definition at line 3288 of file pre.l.

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

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

Referenced by computeExpression(), and expandMacro().

◆ replaceFunctionMacro()

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

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

Definition at line 2574 of file pre.l.

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

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

Referenced by expandExpression().

◆ resolveTrigraph()

static char resolveTrigraph ( char c)
static

Definition at line 3746 of file pre.l.

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

◆ returnCharToStream()

static void returnCharToStream ( yyscan_t yyscanner,
char c )
static

Definition at line 2518 of file pre.l.

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

Referenced by getCurrentChar(), and unputChar().

◆ setCaseDone()

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

static 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:631
@ CSharp
Definition types.h:46
@ Fortran
Definition types.h:53
SrcLangExt getLanguageFromFileName(const QCString &fileName, SrcLangExt defLang)
Definition util.cpp:5705
EntryType guessSection(const QCString &name)
Definition util.cpp:349
2169}

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

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

◆ skipCommentMacroName()

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

Definition at line 2536 of file pre.l.

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

References getCurrentChar(), and getNextChar().

Referenced by replaceFunctionMacro().

◆ startCondSection()

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

Definition at line 3690 of file pre.l.

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

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

◆ stateToString()

static const char * stateToString ( int state)
static

◆ stringize()

static QCString stringize ( const QCString & s)
static

Definition at line 2393 of file pre.l.

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

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

Referenced by replaceFunctionMacro().

◆ unputChar()

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

Definition at line 3812 of file pre.l.

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

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:3746
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:3462
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:3369
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:3537
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:3350
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:3480
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:3491
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:3504
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:3690
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:3704
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:3731
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:3412
static void addDefine(yyscan_t yyscanner)
Definition pre.l:3383
static QCString extractTrailingComment(const QCString &s)
Definition pre.l:2343
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()

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