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 2941 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:3963

Definition at line 349 of file pre.l.

◆ YY_NO_UNISTD_H

#define YY_NO_UNISTD_H   1

Definition at line 68 of file pre.l.

◆ YY_TYPEDEF_YY_SCANNER_T

#define YY_TYPEDEF_YY_SCANNER_T

Definition at line 22 of file pre.l.

Typedef Documentation

◆ DefineMap

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

A dictionary of managed Define objects.

Definition at line 109 of file pre.l.

◆ yyscan_t

typedef yyguts_t* yyscan_t

Definition at line 24 of file pre.l.

Function Documentation

◆ addDefine()

void addDefine ( yyscan_t yyscanner)
static

Definition at line 3446 of file pre.l.

3447{
3448 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
3449 Define def;
3450 def.name = state->defName;
3451 def.definition = state->defText.stripWhiteSpace();
3452 def.nargs = state->defArgs;
3453 def.fileName = state->fileName;
3454 def.fileDef = state->yyFileDef;
3455 def.lineNr = state->yyLineNr-state->yyMLines;
3456 def.columnNr = state->yyColNr;
3457 def.varArgs = state->defVarArgs;
3458 //printf("newDefine: %s %s file: %s\n",qPrint(def.name),qPrint(def.definition),
3459 // def.fileDef ? qPrint(def.fileDef->name()) : qPrint(def.fileName));
3460 //printf("newDefine: '%s'->'%s'\n",qPrint(def.name),qPrint(def.definition));
3461 if (!def.name.isEmpty() &&
3463 {
3464 def.isPredefined=TRUE;
3466 }
3467 auto it = state->localDefines.find(def.name.str());
3468 if (it!=state->localDefines.end()) // redefine
3469 {
3470 state->localDefines.erase(it);
3471 }
3472 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:163
QCString stripWhiteSpace() const
returns a copy of this string with leading and trailing whitespace removed
Definition qcstring.h:260
const std::string & str() const
Definition qcstring.h:552
#define TRUE
Definition qcstring.h:37
3473}

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

◆ addMacroDefinition()

void addMacroDefinition ( yyscan_t yyscanner)
static

Definition at line 3475 of file pre.l.

3476{
3477 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
3478 if (state->skip) return; // do not add this define as it is inside a
3479 // conditional section (cond command) that is disabled.
3480
3481 Define define;
3482 define.fileName = state->fileName;
3483 define.lineNr = state->yyLineNr - state->yyMLines;
3484 define.columnNr = state->yyColNr;
3485 define.name = state->defName;
3486 define.args = state->defArgsStr;
3487 define.fileDef = state->inputFileDef;
QCString args
Definition define.h:36
3488
3489 QCString litText = state->defLitText;
3490 int l=litText.find('\n');
3491 if (l>0 && litText.left(l).stripWhiteSpace()=="\\")
3492 {
3493 // strip first line if it only contains a slash
3494 litText = litText.right(litText.length()-l-1);
3495 }
3496 else if (l>0)
3497 {
3498 // align the items on the first line with the items on the second line
3499 int k=l+1;
3500 const char *p=litText.data()+k;
3501 char c = 0;
3502 while ((c=*p++) && (c==' ' || c=='\t')) k++;
3503 litText=litText.mid(l+1,k-l-1)+litText.stripWhiteSpace();
3504 }
3505 QCString litTextStripped = state->defLitText.stripWhiteSpace();
3506 if (litTextStripped.contains('\n')>=1)
3507 {
3508 define.definition = litText;
3509 }
3510 else
3511 {
3512 define.definition = litTextStripped;
3513 }
3514 {
3515 state->macroDefinitions.push_back(define);
3516 }
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:166
QCString mid(size_t index, size_t len=static_cast< size_t >(-1)) const
Definition qcstring.h:241
QCString right(size_t len) const
Definition qcstring.h:234
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:172
QCString left(size_t len) const
Definition qcstring.h:229
int contains(char c, bool cs=TRUE) const
Definition qcstring.cpp:148
3517}

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

◆ addSeparatorsIfNeeded()

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

Definition at line 2943 of file pre.l.

2944{
2945 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
2946 if (!state->nospaces)
2947 {
2948 // peek back in the stream, for a colon character
2949 char ccPrev = pos==0 || (int)expr.length()<pos ? state->prevChar : expr.at(pos-1);
2950 QCString leftSpace = ccPrev!=':' && ccPrev!=' ' ? " " : "";
2951 int ccNext = 0;
2952 restExpr=restExpr.stripWhiteSpace();
2953 if (restExpr.isEmpty()) // peek ahead in the stream for non-whitespace
2954 {
2955 uint32_t j=(uint32_t)resultExpr.length();
2956 while ((ccNext=getNextChar(yyscanner,resultExpr,nullptr,j))!=EOF && ccNext==' ') { }
2957 if (ccNext != EOF) unputChar(yyscanner,resultExpr,nullptr,j,(char)ccNext);
2958 }
2959 else // take first char from remainder
2960 {
2961 ccNext=restExpr.at(0);
2962 }
2963 // don't add whitespace before a colon
2964 QCString rightSpace = ccNext!=':' && ccNext!=' ' ? " " : "";
2965 //printf("ccPrev='%c' ccNext='%c' p=%d expr=%zu restExpr='%s' left='%s' right='%s'\n",
2966 // ccPrev,ccNext,pos,expr.length(),qPrint(restExpr),qPrint(leftSpace),qPrint(rightSpace));
2967 resultExpr=leftSpace+resultExpr+rightSpace;
2968 }
char & at(size_t i)
Returns a reference to the character at index i.
Definition qcstring.h:593
static int getNextChar(yyscan_t yyscanner, const QCString &expr, QCString *rest, uint32_t &pos)
Definition pre.l:3829
static void unputChar(yyscan_t yyscanner, const QCString &expr, QCString *rest, uint32_t &pos, char c)
Definition pre.l:3875
2969}

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

Referenced by expandExpression().

◆ addTillEndOfString()

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

Definition at line 2587 of file pre.l.

2589{
2590 int cc;
2591 while ((cc=getNextChar(yyscanner,expr,rest,pos))!=EOF && cc!=0)
2592 {
2593 if (cc=='\\') arg+=(char)cc,cc=getNextChar(yyscanner,expr,rest,pos);
2594 else if (cc==term) return;
2595 arg+=(char)cc;
2596 }
#define term(fmt,...)
Definition message.h:137
2597}

References getNextChar(), and term.

Referenced by replaceFunctionMacro().

◆ checkAndOpenFile()

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

Definition at line 2275 of file pre.l.

2276{
2277 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
2278 alreadyProcessed = FALSE;
2279 std::unique_ptr<FileState> fs;
2280 //printf("checkAndOpenFile(%s)\n",qPrint(fileName));
2281 FileInfo fi(fileName.str());
2282 if (fi.exists() && fi.isFile())
2283 {
2284 const StringVector &exclPatterns = Config_getList(EXCLUDE_PATTERNS);
2285 if (patternMatch(fi,exclPatterns)) return nullptr;
Minimal replacement for QFileInfo.
Definition fileinfo.h:23
#define Config_getList(name)
Definition config.h:38
std::vector< std::string > StringVector
Definition containers.h:33
#define FALSE
Definition qcstring.h:34
bool patternMatch(const FileInfo &fi, const StringVector &patList)
Definition util.cpp:6207
2286
2287 QCString absName = fi.absFilePath();
2288
2289 // global guard
2290 if (state->curlyCount==0) // not #include inside { ... }
2291 {
2292 std::lock_guard<std::mutex> lock(g_globalDefineMutex);
2293 if (g_defineManager.alreadyProcessed(absName.str()))
2294 {
2295 alreadyProcessed = TRUE;
2296 //printf(" already included 1\n");
2297 return 0; // already done
2298 }
2299 }
2300 // check include stack for absName
static std::mutex g_globalDefineMutex
Definition pre.l:234
static DefineManager g_defineManager
Definition pre.l:236
2301
2302 alreadyProcessed = std::any_of(
2303 state->includeStack.begin(),
2304 state->includeStack.end(),
2305 [absName](const std::unique_ptr<FileState> &lfs)
2306 { return lfs->fileName==absName; }
2307 );
2308
2309 if (alreadyProcessed)
2310 {
2311 //printf(" already included 2\n");
2312 return nullptr;
2313 }
2314 //printf("#include %s\n",qPrint(absName));
2315
2316 fs = std::make_unique<FileState>();
2317 if (!readInputFile(absName,fs->fileBuf))
2318 { // error
2319 //printf(" error reading\n");
2320 fs.reset();
2321 }
2322 else
2323 {
2324 addTerminalCharIfMissing(fs->fileBuf,'\n');
2325 fs->oldFileBuf = state->inputBuf;
2326 fs->oldFileBufPos = state->inputBufPos;
2327 }
2328 }
2329 return fs;
void addTerminalCharIfMissing(std::string &s, char c)
Definition stringutil.h:84
bool readInputFile(const QCString &fileName, std::string &contents, bool filter, bool isSourceCode)
read a file name fileName and optionally filter and transcode it
Definition util.cpp:6053
2330}

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

Referenced by findFile().

◆ computeExpression()

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

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

Definition at line 3413 of file pre.l.

3414{
3415 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
3416 QCString e=expr;
3417 QCString ee=expr;
3418 ee = removeMarkers(ee);
3419 state->expanded.clear();
3420 expandExpression(yyscanner,e,nullptr,0,0);
3421 //printf("after expansion '%s'\n",qPrint(e));
3422 e = removeIdsAndMarkers(e);
3423 if (e.isEmpty()) return FALSE;
3424 //printf("parsing '%s'\n",qPrint(e));
3425 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:2975
static QCString removeIdsAndMarkers(const QCString &s)
Definition pre.l:3156
static QCString removeMarkers(const QCString &s)
Definition pre.l:3351
3426}

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

◆ decrLevel()

void decrLevel ( yyscan_t yyscanner)
static

Definition at line 2240 of file pre.l.

2241{
2242 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
2243 //printf("%s line %d: decrLevel %d\n",qPrint(state->fileName),state->yyLineNr,state->levelGuard.size());
2244 if (!state->levelGuard.empty())
2245 {
2246 state->levelGuard.pop();
2247 }
2248 else
2249 {
2250 warn(state->fileName,state->yyLineNr,"More #endif's than #if's found.");
2251 }
#define warn(file, line, fmt,...)
Definition message.h:97
2252}

References warn.

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

◆ determineBlockName()

void determineBlockName ( yyscan_t yyscanner)
static

Definition at line 3567 of file pre.l.

3568{
3569 struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
3570 yyextra->fenceSize=0;
3571 char c=0;
3572 if (yytext[1]=='f' && ((c=yytext[2])=='[' || c=='{' || c=='(' || c=='$'))
3573 {
3574 switch (c)
3575 {
3576 case '[': yyextra->blockName="]"; break;
3577 case '{': yyextra->blockName="}"; break;
3578 case '(': yyextra->blockName=")"; break;
3579 case '$': yyextra->blockName="$"; break;
3580 default: break;
3581 }
3582 yyextra->blockName=yyextra->blockName.stripWhiteSpace();
3583 }
3584 else
3585 {
3586 QCString bn=QCString(&yytext[1]).stripWhiteSpace();
3587 if (bn=="startuml")
3588 {
3589 yyextra->blockName="uml";
3590 }
3591 else
3592 {
3593 int i = bn.find('{'); // for \code{.c}
3594 if (i!=-1) bn=bn.left(i).stripWhiteSpace();
3595 yyextra->blockName=bn;
3596 }
3597 }
3598}

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

◆ endCondSection()

void endCondSection ( yyscan_t yyscanner)
static

Definition at line 3767 of file pre.l.

3768{
3769 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
3770 if (state->condStack.empty())
3771 {
3772 warn(state->fileName,state->yyLineNr,"the \\endcond does not have a corresponding \\cond in this file");
3773 state->skip=FALSE;
3774 }
3775 else
3776 {
3777 const std::unique_ptr<preYY_CondCtx> &ctx = state->condStack.top();
3778 state->skip=ctx->skip;
3779 state->condStack.pop();
3780 }
3781 //printf("endCondSection: skip=%d stack=%d\n",state->skip,state->condStack.count());
3782}

References FALSE, and warn.

◆ escapeAt()

QCString escapeAt ( const QCString & text)
static

Definition at line 3794 of file pre.l.

3795{
3796 QCString result;
3797 if (!text.isEmpty())
3798 {
3799 char c = 0;
3800 const char *p=text.data();
3801 while ((c=*p++))
3802 {
3803 if (c=='@') result+="@@"; else result+=c;
3804 }
3805 }
3806 return result;
3807}

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

◆ expandExpression()

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

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

Definition at line 2975 of file pre.l.

2976{
2977 struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
2978 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
2979 //printf(">expandExpression(expr='%s',rest='%s',pos=%d,level=%d)\n",qPrint(expr),rest ? qPrint(*rest) : "", pos, level);
2980 if (expr.isEmpty())
2981 {
2982 //printf("<expandExpression: empty\n");
2983 return TRUE;
2984 }
2985 if (state->expanded.find(expr.str())!=state->expanded.end() &&
2986 level>MAX_EXPANSION_DEPTH) // check for too deep recursive expansions
2987 {
2988 //printf("<expandExpression: already expanded expr='%s'\n",qPrint(expr));
2989 return FALSE;
2990 }
2991 else
2992 {
2993 state->expanded.insert(expr.str());
2994 }
2995 QCString macroName;
2996 QCString expMacro;
2997 bool definedTest=FALSE;
2998 int i=pos, l=0, p=0, len=0;
2999 int startPos = pos;
3000 int samePosCount=0;
3001 while ((p=getNextId(expr,i,&l))!=-1) // search for an macro name
3002 {
3003 bool replaced=FALSE;
3004 macroName=expr.mid(p,l);
3005 //printf(" p=%d macroName=%s\n",p,qPrint(macroName));
3006 if (p<2 || !(expr.at(p-2)=='@' && expr.at(p-1)=='-')) // no-rescan marker?
3007 {
3008 if (state->expandedDict.find(macroName.str())==state->expandedDict.end()) // expand macro
3009 {
3010 Define *def=isDefined(yyscanner,macroName);
3011 // In case EXPAND_ONLY_PREDEF is enabled prevent expansion unless the macro was explicitly
3012 // predefined
3013 if (yyextra->expandOnlyPredef && def && !def->isPredefined) def=nullptr;
3014 if (macroName=="defined")
3015 {
3016 //printf("found defined inside macro definition '%s'\n",qPrint(expr.right(expr.length()-p)));
3017 definedTest=TRUE;
3018 }
3019 else if (definedTest) // macro name was found after defined
3020 {
3021 if (def) expMacro = " 1 "; else expMacro = " 0 ";
3022 replaced=TRUE;
3023 len=l;
3024 definedTest=FALSE;
3025 }
3026 else if (def && def->nargs==-1) // simple macro
3027 {
3028 // substitute the definition of the macro
3029 expMacro=def->definition.stripWhiteSpace();
3030 //expMacro=def->definition.stripWhiteSpace();
3031 replaced=TRUE;
3032 len=l;
3033 //printf("simple macro expansion='%s'->'%s'\n",qPrint(macroName),qPrint(expMacro));
3034 }
3035 else if (def && def->nargs>=0) // function macro
3036 {
3037 //printf(" >>>> call replaceFunctionMacro expr='%s'\n",qPrint(expr));
3038 replaced=replaceFunctionMacro(yyscanner,expr,rest,p+l,len,def,expMacro,level);
3039 //printf(" <<<< call replaceFunctionMacro: replaced=%d\n",replaced);
3040 len+=l;
3041 }
3042 //printf(" macroName='%s' expMacro='%s' replaced=%d\n",qPrint(macroName),qPrint(expMacro),replaced);
#define MAX_EXPANSION_DEPTH
Definition pre.l:2941
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:3899
static int getNextId(const QCString &expr, int p, int *l)
Definition pre.l:2887
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:2637
3043
3044 if (replaced) // expand the macro and rescan the expression
3045 {
3046 //printf(" replacing '%s'->'%s'\n",qPrint(expr.mid(p,len)),qPrint(expMacro));
3047 QCString resultExpr=expMacro;
3048 QCString restExpr=expr.right(expr.length()-len-p);
3049 addSeparatorsIfNeeded(yyscanner,expr,resultExpr,restExpr,p);
3050 processConcatOperators(resultExpr);
3051 //printf(" macroName=%s restExpr='%s' def->nonRecursive=%d\n",qPrint(macroName),qPrint(restExpr),def->nonRecursive);
3052 bool expanded=false;
3053 if (def && !def->nonRecursive)
3054 {
3055 state->expandedDict.emplace(toStdString(macroName),def);
3056 expanded = expandExpression(yyscanner,resultExpr,&restExpr,0,level+1);
3057 state->expandedDict.erase(toStdString(macroName));
3058 }
3059 else if (def && def->nonRecursive)
3060 {
3061 expanded = true;
3062 }
3063 if (expanded)
3064 {
3065 //printf("expanded '%s' + '%s' + '%s'\n",qPrint(expr.left(p)),qPrint(resultExpr),qPrint(restExpr));
3066 expr=expr.left(p)+resultExpr+restExpr;
3067 i=p;
3068 }
3069 else
3070 {
3071 //printf("not expanded '%s' + @- '%s'\n",qPrint(expr.left(p)),qPrint(expr.right(expr.length()-p)));
3072 expr=expr.left(p)+"@-"+expr.right(expr.length()-p);
3073 i=p+l+2;
3074 }
3075 }
3076 else // move to the next macro name
3077 {
3078 //printf(" moving to the next macro old i=%d new i=%d\n",i,p+l);
3079 i=p+l;
3080 }
3081 }
3082 else // move to the next macro name
3083 {
3084 expr=expr.left(p)+"@-"+expr.right(expr.length()-p);
3085 //printf("macro already expanded, moving to the next macro expr=%s\n",qPrint(expr));
3086 i=p+l+2;
3087 //i=p+l;
3088 }
3089 // check for too many inplace expansions without making progress
3090 if (i==startPos)
3091 {
3092 samePosCount++;
3093 }
3094 else
3095 {
3096 startPos=i;
3097 samePosCount=0;
3098 }
3099 if (samePosCount>MAX_EXPANSION_DEPTH)
3100 {
3101 break;
3102 }
3103 }
3104 else // no re-scan marker found, skip the macro name
3105 {
3106 //printf("skipping marked macro\n");
3107 i=p+l;
3108 }
3109 }
3110 //printf("<expandExpression(expr='%s',rest='%s',pos=%d,level=%d)\n",qPrint(expr),rest ? qPrint(*rest) : "", pos,level);
3111 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:2943
static void processConcatOperators(QCString &expr)
Definition pre.l:2534
std::string toStdString(const QCString &s)
Definition qcstring.h:702
3112}

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

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

◆ expandMacro()

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

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

Definition at line 3432 of file pre.l.

3433{
3434 struct yyguts_t *yyg = (struct yyguts_t*)yyscanner;
3435 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
3436 state->prevChar = yyscanner->yytext_r > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ? *(yyscanner->yytext_r-1) : 0;
3437 QCString n=name;
3438 state->expanded.clear();
3439 expandExpression(yyscanner,n,nullptr,0,0);
3440 n=removeMarkers(n);
3441 state->prevChar=0;
3442 //printf("expandMacro '%s'->'%s'\n",qPrint(name),qPrint(n));
3443 return n;
void clear()
Definition qcstring.h:182
3444}

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

◆ extractTrailingComment()

QCString extractTrailingComment ( const QCString & s)
static

Definition at line 2406 of file pre.l.

2407{
2408 if (s.isEmpty()) return "";
2409 int i=(int)s.length()-1;
2410 while (i>=0)
2411 {
2412 char c=s[i];
2413 switch (c)
2414 {
2415 case '/':
2416 {
2417 i--;
2418 if (i>=0 && s[i]=='*') // end of a comment block
2419 {
2420 i--;
2421 while (i>0 && !(s[i-1]=='/' && s[i]=='*')) i--;
2422 if (i==0)
2423 {
2424 i++;
2425 }
2426 // only /*!< ... */ or /**< ... */ are treated as a comment for the macro name,
2427 // otherwise the comment is treated as part of the macro definition
2428 return ((s[i+1]=='*' || s[i+1]=='!') && s[i+2]=='<') ? &s[i-1] : "";
2429 }
2430 else
2431 {
2432 return "";
2433 }
2434 }
2435 break;
2436 // whitespace or line-continuation
2437 case ' ':
2438 case '\t':
2439 case '\r':
2440 case '\n':
2441 case '\\':
2442 break;
2443 default:
2444 return "";
2445 }
2446 i--;
2447 }
2448 return "";
2449}

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

◆ extraSpacing()

void extraSpacing ( yyscan_t yyscanner)
inlinestatic

Definition at line 3554 of file pre.l.

3555{
3556 struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
3557 if (!yyextra->defContinue) return;
3558 for (int i=0; i< (int)yyleng; i++)
3559 {
3560 if (yytext[i] == '\t')
3561 yyextra->defExtraSpacing+='\t';
3562 else
3563 yyextra->defExtraSpacing+=' ';
3564 }
3565}

◆ findFile()

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

Definition at line 2332 of file pre.l.

2333{
2334 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
2335 //printf("** findFile(%s,%d) state->fileName=%s\n",qPrint(fileName),localInclude,qPrint(state->fileName));
2336 if (Portable::isAbsolutePath(fileName))
2337 {
2338 auto fs = checkAndOpenFile(yyscanner,fileName,alreadyProcessed);
2339 if (fs)
2340 {
2341 setFileName(yyscanner,fileName);
2342 state->yyLineNr=1;
2343 return fs;
2344 }
2345 else if (alreadyProcessed)
2346 {
2347 return nullptr;
2348 }
2349 }
2350 if (localInclude && !state->fileName.isEmpty())
2351 {
2352 FileInfo fi(state->fileName.str());
2353 if (fi.exists())
2354 {
2355 QCString absName = QCString(fi.dirPath(TRUE))+"/"+fileName;
2356 auto fs = checkAndOpenFile(yyscanner,absName,alreadyProcessed);
2357 if (fs)
2358 {
2359 setFileName(yyscanner,absName);
2360 state->yyLineNr=1;
2361 return fs;
2362 }
2363 else if (alreadyProcessed)
2364 {
2365 return nullptr;
2366 }
2367 }
2368 }
2369 if (state->pathList.empty())
2370 {
2371 return nullptr;
2372 }
2373 for (auto path : state->pathList)
2374 {
2375 QCString absName = path+"/"+fileName;
2376 //printf(" Looking for %s in %s\n",fileName,qPrint(path));
2377 auto fs = checkAndOpenFile(yyscanner,absName,alreadyProcessed);
2378 if (fs)
2379 {
2380 setFileName(yyscanner,absName);
2381 state->yyLineNr=1;
2382 //printf(" -> found it\n");
2383 return fs;
2384 }
2385 else if (alreadyProcessed)
2386 {
2387 return nullptr;
2388 }
2389 }
2390 bool ambig = false;
2392 if (fd && !ambig) // fallback in case the file is uniquely named in the input, use that one
2393 {
2394 auto fs = checkAndOpenFile(yyscanner,fd->absFilePath(),alreadyProcessed);
2395 if (fs)
2396 {
2397 setFileName(yyscanner,fd->absFilePath());
2398 state->yyLineNr=1;
2399 //printf(" -> found it\n");
2400 return fs;
2401 }
2402 }
2403 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:498
static void setFileName(yyscan_t yyscanner, const QCString &name)
Definition pre.l:2212
static std::unique_ptr< FileState > checkAndOpenFile(yyscan_t yyscanner, const QCString &fileName, bool &alreadyProcessed)
Definition pre.l:2275
FileDef * findFileDef(const FileNameLinkedMap *fnMap, const QCString &n, bool &ambig)
Definition util.cpp:3417
2404}

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

◆ forceEndCondSection()

void forceEndCondSection ( yyscan_t yyscanner)
static

Definition at line 3784 of file pre.l.

3785{
3786 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
3787 while (!state->condStack.empty())
3788 {
3789 state->condStack.pop();
3790 }
3791 state->skip=FALSE;
3792}

References FALSE.

Referenced by Preprocessor::processFile().

◆ getCurrentChar()

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

Definition at line 3852 of file pre.l.

3853{
3854 //printf("getCurrentChar(%s,%s,%d)\n",qPrint(expr),rest ? rest->data() : 0,pos);
3855 if (pos<expr.length())
3856 {
3857 //printf("%c=expr()\n",expr.at(pos));
3858 return expr.at(pos);
3859 }
3860 else if (rest && !rest->isEmpty())
3861 {
3862 int cc=rest->at(0);
3863 //printf("%c=rest\n",cc);
3864 return cc;
3865 }
3866 else
3867 {
3868 int cc=yyinput(yyscanner);
3869 returnCharToStream(yyscanner,(char)cc);
3870 //printf("%c=yyinput()\n",cc);
3871 return cc;
3872 }
static void returnCharToStream(yyscan_t yyscanner, char c)
Definition pre.l:2581
3873}

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

Referenced by replaceFunctionMacro(), and skipCommentMacroName().

◆ getFenceSize()

yy_size_t getFenceSize ( char * txt,
yy_size_t leng )
static

Definition at line 2201 of file pre.l.

2202{
2203 yy_size_t fenceSize = 0;
2204 for (size_t i = 0; i < leng; i++)
2205 {
2206 if (txt[i] != ' ' && txt[i] != '*' && txt[i] != '\t') break;
2207 fenceSize++;
2208 }
2209 return leng-fenceSize;
2210}

◆ getLexerFILE()

const char * getLexerFILE ( )
inlinestatic

Definition at line 352 of file pre.l.

352{return __FILE__;}

◆ getNextChar()

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

Definition at line 3829 of file pre.l.

3830{
3831 //printf("getNextChar(%s,%s,%d)\n",qPrint(expr),rest ? rest->data() : 0,pos);
3832 if (pos<expr.length())
3833 {
3834 //printf(" expr()='%c'\n",expr.at(pos));
3835 return expr.at(pos++);
3836 }
3837 else if (rest && !rest->isEmpty())
3838 {
3839 int cc=rest->at(0);
3840 *rest=rest->right(rest->length()-1);
3841 //printf(" rest='%c'\n",cc);
3842 return cc;
3843 }
3844 else
3845 {
3846 int cc=yyinput(yyscanner);
3847 //printf(" yyinput()='%c' %d\n",cc,EOF);
3848 return cc;
3849 }
3850}

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

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

◆ getNextId()

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

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

Definition at line 2887 of file pre.l.

2888{
2889 int n;
2890 while (p<(int)expr.length())
2891 {
2892 char c=expr.at(p++);
2893 if (isdigit(c)) // skip number
2894 {
2895 while (p<(int)expr.length() && isId(expr.at(p))) p++;
2896 }
2897 else if (isalpha(c) || c=='_') // read id
2898 {
2899 n=p-1;
2900 while (p<(int)expr.length() && isId(expr.at(p))) p++;
2901 *l=p-n;
2902 return n;
2903 }
2904 else if (c=='"') // skip string
2905 {
2906 char ppc=0,pc=c;
2907 if (p<(int)expr.length()) c=expr.at(p);
2908 while (p<(int)expr.length() && (c!='"' || (pc=='\\' && ppc!='\\')))
2909 // continue as long as no " is found, but ignoring \", but not \\"
2910 {
2911 ppc=pc;
2912 pc=c;
2913 c=expr.at(p);
2914 p++;
2915 }
2916 if (p<(int)expr.length()) ++p; // skip closing quote
2917 }
2918 else if (c=='/') // skip C Comment
2919 {
2920 //printf("Found C comment at p=%d\n",p);
2921 char pc=c;
2922 if (p<(int)expr.length())
2923 {
2924 c=expr.at(p);
2925 if (c=='*') // Start of C comment
2926 {
2927 p++;
2928 while (p<(int)expr.length() && !(pc=='*' && c=='/'))
2929 {
2930 pc=c;
2931 c=expr.at(p++);
2932 }
2933 }
2934 }
2935 //printf("Found end of C comment at p=%d\n",p);
2936 }
2937 }
2938 return -1;
bool isId(int c)
Definition util.h:208
2939}

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

Referenced by expandExpression().

◆ incrLevel()

void incrLevel ( yyscan_t yyscanner)
static

Definition at line 2233 of file pre.l.

2234{
2235 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
2236 state->levelGuard.push(false);
2237 //printf("%s line %d: incrLevel %d\n",qPrint(yyextra->fileName),yyextra->yyLineNr,yyextra->levelGuard.size());
2238}

◆ initPredefined()

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

Definition at line 3928 of file pre.l.

3929{
3930 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
3931
3932 // add predefined macros
3933 const StringVector &predefList = Config_getList(PREDEFINED);
3934 for (const auto &ds : predefList)
3935 {
3936 size_t i_equals=ds.find('=');
3937 size_t i_obrace=ds.find('(');
3938 size_t i_cbrace=ds.find(')');
3939 bool nonRecursive = i_equals!=std::string::npos && i_equals>0 && ds[i_equals-1]==':';
3940
3941 if ((i_obrace==0) || (i_equals==0) || (i_equals==1 && ds[i_equals-1]==':'))
3942 {
3943 continue; // no define name
3944 }
3945
3946 if (i_obrace<i_equals && i_cbrace<i_equals &&
3947 i_obrace!=std::string::npos && i_cbrace!=std::string::npos &&
3948 i_obrace<i_cbrace
3949 ) // predefined function macro definition
3950 {
3951 static const reg::Ex reId(R"(\a\w*)");
3952 std::map<std::string,int> argMap;
3953 std::string args = ds.substr(i_obrace+1,i_cbrace-i_obrace-1); // part between ( and )
3954 bool hasVarArgs = args.find("...")!=std::string::npos;
3955 //printf("predefined function macro '%s'\n",qPrint(ds));
3956 int count = 0;
3957 reg::Iterator arg_it(args,reId,0);
3958 reg::Iterator arg_end;
3959 // gather the formal arguments in a dictionary
3960 for (; arg_it!=arg_end; ++arg_it)
3961 {
3962 argMap.emplace(arg_it->str(),count++);
3963 }
3964 if (hasVarArgs) // add the variable argument if present
3965 {
3966 argMap.emplace("__VA_ARGS__",count++);
3967 }
Class representing a regular expression.
Definition regex.h:39
Class to iterate through matches.
Definition regex.h:232
3968
3969 // strip definition part
3970 std::string definition;
3971 std::string in=ds.substr(i_equals+1);
3972 reg::Iterator re_it(in,reId);
3973 reg::Iterator re_end;
3974 size_t i=0;
3975 // substitute all occurrences of formal arguments by their
3976 // corresponding markers
3977 for (; re_it!=re_end; ++re_it)
3978 {
3979 const auto &match = *re_it;
3980 size_t pi = match.position();
3981 size_t l = match.length();
3982 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
3983
3984 auto it = argMap.find(match.str());
3985 if (it!=argMap.end())
3986 {
3987 int argIndex = it->second;
3988 QCString marker;
3989 marker.sprintf(" @%d ",argIndex);
3990 definition+=marker.str();
3991 }
3992 else
3993 {
3994 definition+=match.str();
3995 }
3996 i=pi+l;
3997 }
3998 definition+=in.substr(i);
QCString & sprintf(const char *format,...)
Definition qcstring.cpp:29
3999
4000 // add define definition to the dictionary of defines for this file
4001 std::string dname = ds.substr(0,i_obrace);
4002 if (!dname.empty())
4003 {
4004 Define def;
4005 def.name = dname;
4006 def.definition = definition;
4007 def.nargs = count;
4008 def.isPredefined = TRUE;
4009 def.nonRecursive = nonRecursive;
4010 def.fileDef = state->yyFileDef;
4011 def.fileName = fileName;
4012 def.varArgs = hasVarArgs;
4013 state->contextDefines.emplace(def.name.str(),def);
4014
4015 //printf("#define '%s' '%s' #nargs=%d hasVarArgs=%d\n",
4016 // qPrint(def.name),qPrint(def.definition),def.nargs,def.varArgs);
4017 }
4018 }
4019 else if (!ds.empty()) // predefined non-function macro definition
4020 {
4021 //printf("predefined normal macro '%s'\n",qPrint(ds));
4022 Define def;
4023 if (i_equals==std::string::npos) // simple define without argument
4024 {
4025 def.name = ds;
4026 def.definition = "1"; // substitute occurrences by 1 (true)
4027 }
4028 else // simple define with argument
4029 {
4030 int ine=static_cast<int>(i_equals) - (nonRecursive ? 1 : 0);
4031 def.name = ds.substr(0,ine);
4032 def.definition = ds.substr(i_equals+1);
4033 }
4034 if (!def.name.isEmpty())
4035 {
4036 def.nargs = -1;
4037 def.isPredefined = TRUE;
4038 def.nonRecursive = nonRecursive;
4039 def.fileDef = state->yyFileDef;
4040 def.fileName = fileName;
4041 state->contextDefines.emplace(def.name.str(),def);
4042 }
4043 }
4044 }
4045}

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

Referenced by Preprocessor::processFile().

◆ isDefined()

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

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

Definition at line 3899 of file pre.l.

3900{
3901 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
3902
3903 bool undef = false;
3904 auto findDefine = [&undef,&name](DefineMap &map)
3905 {
3906 Define *d=nullptr;
3907 auto it = map.find(name.str());
3908 if (it!=map.end())
3909 {
3910 d = &it->second;
3911 if (d->undef)
3912 {
3913 undef=true;
3914 d=nullptr;
3915 }
3916 }
3917 return d;
3918 };
bool undef
Definition define.h:41
std::map< std::string, Define > DefineMap
A dictionary of managed Define objects.
Definition pre.l:109
3919
3920 Define *def = findDefine(state->localDefines);
3921 if (def==nullptr && !undef)
3922 {
3923 def = findDefine(state->contextDefines);
3924 }
3925 return def;
3926}

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

Referenced by expandExpression().

◆ otherCaseDone()

bool otherCaseDone ( yyscan_t yyscanner)
static

Definition at line 2254 of file pre.l.

2255{
2256 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
2257 if (state->levelGuard.empty())
2258 {
2259 warn(state->fileName,state->yyLineNr,"Found an #else without a preceding #if.");
2260 return TRUE;
2261 }
2262 else
2263 {
2264 return state->levelGuard.top();
2265 }
2266}

References TRUE, and warn.

◆ outputArray()

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

Definition at line 3525 of file pre.l.

3526{
3527 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
3528 if (state->includeStack.empty() || state->curlyCount>0) (*state->outputBuf)+=std::string_view(a,len);
3529}

◆ outputChar()

void outputChar ( yyscan_t yyscanner,
char c )
inlinestatic

Definition at line 3519 of file pre.l.

3520{
3521 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
3522 if (state->includeStack.empty() || state->curlyCount>0) (*state->outputBuf)+=c;
3523}

Referenced by outputSpace(), and outputSpaces().

◆ outputSpace()

void outputSpace ( yyscan_t yyscanner,
char c )
inlinestatic

Definition at line 3537 of file pre.l.

3538{
3539 if (c=='\t') outputChar(yyscanner,'\t');
3540 else outputChar(yyscanner,' ');
static void outputChar(yyscan_t yyscanner, char c)
Definition pre.l:3519
3541}

References outputChar().

◆ outputSpaces()

void outputSpaces ( yyscan_t yyscanner,
char * s )
inlinestatic

Definition at line 3543 of file pre.l.

3544{
3545 const char *p=s;
3546 char c = 0;
3547 while ((c=*p++))
3548 {
3549 if (c=='\t') outputChar(yyscanner,'\t');
3550 else outputChar(yyscanner,' ');
3551 }
3552}

References outputChar().

◆ outputString()

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

Definition at line 3531 of file pre.l.

3532{
3533 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
3534 if (state->includeStack.empty() || state->curlyCount>0) (*state->outputBuf)+=a.str();
3535}

References QCString::str().

Referenced by readIncludeFile().

◆ processConcatOperators()

void processConcatOperators ( QCString & expr)
static

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

Definition at line 2534 of file pre.l.

2535{
2536 if (expr.isEmpty()) return;
2537 //printf("processConcatOperators: in='%s'\n",qPrint(expr));
2538 std::string e = expr.str();
2539 static const reg::Ex r(R"(\s*##\s*)");
DirIterator end(const DirIterator &) noexcept
Definition dir.cpp:175
2541
2542 size_t i=0;
2543 for (;;)
2544 {
2545 reg::Iterator it(e,r,i);
2546 if (it!=end)
2547 {
2548 const auto &match = *it;
2549 size_t n = match.position();
2550 size_t l = match.length();
2551 //printf("Match: '%s'\n",qPrint(expr.mid(i)));
2552 if (n+l+1<e.length() && e[static_cast<int>(n+l)]=='@' && expr[static_cast<int>(n+l+1)]=='-')
2553 {
2554 // remove no-rescan marker after ID
2555 l+=2;
2556 }
2557 //printf("found '%s'\n",qPrint(expr.mid(n,l)));
2558 // remove the ## operator and the surrounding whitespace
2559 e=e.substr(0,n)+e.substr(n+l);
2560 int k=static_cast<int>(n)-1;
2561 while (k>=0 && isId(e[k])) k--;
2562 if (k>0 && e[k]=='-' && e[k-1]=='@')
2563 {
2564 // remove no-rescan marker before ID
2565 e=e.substr(0,k-1)+e.substr(k+1);
2566 n-=2;
2567 }
2568 i=n;
2569 }
2570 else
2571 {
2572 break;
2573 }
2574 }
2575
2576 expr = e;
2577
2578 //printf("processConcatOperators: out='%s'\n",qPrint(expr));
2579}

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

Referenced by expandExpression().

◆ processUntilMatchingTerminator()

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

Process string or character literal.

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

Definition at line 3120 of file pre.l.

3121{
3122 if (inputStr==nullptr) return inputStr;
3123 char term = *inputStr; // capture start character of the literal
3124 if (term!='\'' && term!='"') return inputStr; // not a valid literal
3125 char c=term;
3126 // output start character
3127 result+=c;
3128 inputStr++;
3129 while ((c=*inputStr)) // while inside the literal
3130 {
3131 if (c==term) // found end marker of the literal
3132 {
3133 // output end character and stop
3134 result+=c;
3135 inputStr++;
3136 break;
3137 }
3138 else if (c=='\\') // escaped character, process next character
3139 // as well without checking for end marker.
3140 {
3141 result+=c;
3142 inputStr++;
3143 c=*inputStr;
3144 if (c==0) break; // unexpected end of string after escape character
3145 }
3146 result+=c;
3147 inputStr++;
3148 }
3149 return inputStr;
3150}

References term.

Referenced by removeIdsAndMarkers(), and removeMarkers().

◆ readIncludeFile()

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

Definition at line 3600 of file pre.l.

3601{
3602 AUTO_TRACE("inc={}",inc);
3603 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
3604 uint32_t i=0;
#define AUTO_TRACE(...)
Definition docnode.cpp:46
3605
3606 // find the start of the include file name
3607 while (i<inc.length() &&
3608 (inc.at(i)==' ' || inc.at(i)=='"' || inc.at(i)=='<')
3609 ) i++;
3610 uint32_t s=i;
3611
3612 // was it a local include?
3613 bool localInclude = s>0 && inc.at(s-1)=='"';
3614
3615 // find the end of the include file name
3616 while (i<inc.length() && inc.at(i)!='"' && inc.at(i)!='>') i++;
3617
3618 if (s<inc.length() && i>s) // valid include file name found
3619 {
3620 // extract include path+name
3621 QCString incFileName=inc.mid(s,i-s).stripWhiteSpace();
3622 if (incFileName.endsWith(".exe") || incFileName.endsWith(".dll") || incFileName.endsWith(".tlb"))
3623 {
3624 // skip imported binary files (e.g. M$ type libraries)
3625 return;
3626 }
bool endsWith(const char *s) const
Definition qcstring.h:524
3627
3628 QCString oldFileName = state->fileName;
3629 FileDef *oldFileDef = state->yyFileDef;
3630 int oldLineNr = state->yyLineNr;
3631 //printf("Searching for '%s'\n",qPrint(incFileName));
3632
3633 QCString absIncFileName = determineAbsoluteIncludeName(state->fileName,incFileName);
QCString determineAbsoluteIncludeName(const QCString &curFile, const QCString &incFileName)
Definition util.cpp:4116
3634
3635 // findFile will overwrite state->yyFileDef if found
3636 std::unique_ptr<FileState> fs;
3637 bool alreadyProcessed = FALSE;
3638 //printf("calling findFile(%s)\n",qPrint(incFileName));
3639 fs=findFile(yyscanner,absIncFileName,localInclude,alreadyProcessed); // see if the absolute include file can be found
3640 if (fs)
3641 {
3642 {
3643 std::lock_guard<std::mutex> lock(g_globalDefineMutex);
3644 g_defineManager.addInclude(oldFileName.str(),absIncFileName.str());
3645 }
static std::unique_ptr< FileState > findFile(yyscan_t yyscanner, const QCString &fileName, bool localInclude, bool &alreadyProcessed)
Definition pre.l:2332
3646
3647 //printf("Found include file!\n");
3649 {
3650 for (i=0;i<state->includeStack.size();i++)
3651 {
3653 }
3654 Debug::print(Debug::Preprocessor,0,"#include {}: parsing...\n",incFileName);
3655 }
@ 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
3656
3657 if (state->includeStack.empty() && oldFileDef)
3658 {
3659 PreIncludeInfo *ii = state->includeRelations.find(absIncFileName);
3660 if (ii==nullptr)
3661 {
3662 bool ambig = false;
3663 FileDef *incFd = findFileDef(Doxygen::inputNameLinkedMap,absIncFileName,ambig);
3664 state->includeRelations.add(
3665 absIncFileName,
3666 oldFileDef,
3667 ambig ? nullptr : incFd,
3668 incFileName,
3669 localInclude,
3670 state->isImported
3671 );
3672 }
3673 }
3674
3675 struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
3676 fs->bufState = YY_CURRENT_BUFFER;
3677 fs->lineNr = oldLineNr;
3678 fs->fileName = oldFileName;
3679 fs->curlyCount = state->curlyCount;
3680 //state->curlyCount = 0; // don't reset counter, see issue #10997
3681 fs->lexRulesPart = state->lexRulesPart;
3682 state->lexRulesPart = false;
3683 // push the state on the stack
3684 FileState *fs_ptr = fs.get();
3685 state->includeStack.push_back(std::move(fs));
3686 // set the scanner to the include file
3687
3688 // Deal with file changes due to
3689 // #include's within { .. } blocks
3690 QCString lineStr(state->fileName.length()+20, QCString::ExplicitSize);
3691 lineStr.sprintf("# 1 \"%s\" 1\n",qPrint(state->fileName));
3692 outputString(yyscanner,lineStr);
@ ExplicitSize
Definition qcstring.h:146
static void outputString(yyscan_t yyscanner, const QCString &s)
Definition pre.l:3531
const char * qPrint(const char *s)
Definition qcstring.h:687
3693
3694 AUTO_TRACE_ADD("Switching to include file {}",incFileName);
3695 state->expectGuard=TRUE;
3696 state->inputBuf = &fs_ptr->fileBuf;
3697 state->inputBufPos=0;
3698 yy_switch_to_buffer(yy_create_buffer(0, YY_BUF_SIZE, yyscanner),yyscanner);
3699 }
3700 else
3701 {
3702 if (alreadyProcessed) // if this header was already process we can just copy the stored macros
3703 // in the local context
3704 {
3705 std::lock_guard<std::mutex> lock(g_globalDefineMutex);
3706 g_defineManager.addInclude(state->fileName.str(),absIncFileName.str());
3707 g_defineManager.retrieve(absIncFileName.str(),state->contextDefines);
3708 }
#define YY_BUF_SIZE
Definition commentcnv.l:19
#define AUTO_TRACE_ADD(...)
Definition docnode.cpp:47
std::string fileBuf
Definition pre.l:86
3709
3710 if (state->includeStack.empty() && oldFileDef)
3711 {
3712 PreIncludeInfo *ii = state->includeRelations.find(absIncFileName);
3713 if (ii==nullptr)
3714 {
3715 bool ambig = false;
3716 FileDef *incFd = findFileDef(Doxygen::inputNameLinkedMap,absIncFileName,ambig);
3717 ii = state->includeRelations.add(absIncFileName,
3718 oldFileDef,
3719 ambig ? nullptr : incFd,
3720 incFileName,
3721 localInclude,
3722 state->isImported
3723 );
3724 }
3725 }
3726
3728 {
3729 for (i=0;i<state->includeStack.size();i++)
3730 {
3732 }
3733 if (alreadyProcessed)
3734 {
3735 Debug::print(Debug::Preprocessor,0,"#include {}: already processed! skipping...\n",incFileName);
3736 }
3737 else
3738 {
3739 Debug::print(Debug::Preprocessor,0,"#include {}: not found! skipping...\n",incFileName);
3740 }
3741 //printf("error: include file %s not found\n",yytext);
3742 }
3743 if (localInclude && !state->includeStack.empty() && state->curlyCount>0 && !alreadyProcessed) // failed to find #include inside { ... }
3744 {
3745 warn(state->fileName,state->yyLineNr,"include file {} not found, perhaps you forgot to add its directory to INCLUDE_PATH?",incFileName);
3746 }
3747 }
3748 }
3749}

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

◆ removeIdsAndMarkers()

QCString removeIdsAndMarkers ( const QCString & s)
static

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

Definition at line 3156 of file pre.l.

3157{
3158 static const std::vector<std::string> signs = { "signed", "unsigned" };
3159 struct TypeInfo { std::string name; size_t size; };
3160 static const std::vector<TypeInfo> types = {
3161 { "short int", sizeof(short int) },
3162 { "long long int", sizeof(long long int) },
3163 { "long int", sizeof(long int) },
3164 { "long long", sizeof(long long) },
3165 { "long double", sizeof(long double) },
3166 { "int", sizeof(int) },
3167 { "short", sizeof(short) },
3168 { "bool", sizeof(bool) },
3169 { "long", sizeof(long) },
3170 { "char", sizeof(char) },
3171 { "float", sizeof(float) },
3172 { "double", sizeof(double) },
3173 };
3174
3175 // Check if string p starts with basic types ending with a ')', such as 'signed long)' or ' float )'
3176 // and return the pointer just past the ')' and the size of the type as a tuple.
3177 // If the pattern is not found the tuple (nullptr,0) is returned.
3178 auto process_cast_or_sizeof = [](const char *p) -> std::pair<const char *,size_t>
3179 {
3180 const char *q = p;
3181 while (*q==' ' || *q=='\t') q++;
3182 bool found=false;
3183 size_t size = sizeof(int); // '(signed)' or '(unsigned)' is an int type
3184 for (const auto &sgn : signs)
3185 {
3186 if (qstrncmp(q,sgn.c_str(),sgn.length())==0) { q+=sgn.length(); found=true; }
3187 }
3188 if (!found || *q==' ' || *q=='\t' || *q==')') // continue searching
3189 {
3190 while (*q==' ' || *q=='\t') q++;
3191 for (const auto &t : types)
3192 {
3193 if (qstrncmp(q,t.name.c_str(),t.name.length())==0)
3194 {
3195 q += t.name.length();
3196 size = t.size;
3197 break;
3198 }
3199 }
3200 while (*q==' ' || *q=='\t') q++;
3201 if (*q==')') return std::make_pair(++q,size);
3202 }
3203 return std::make_pair(nullptr,0);
3204 };
int qstrncmp(const char *str1, const char *str2, size_t len)
Definition qcstring.h:75
3205
3206 //printf("removeIdsAndMarkers(%s)\n",qPrint(s));
3207 if (s.isEmpty()) return s;
3208 const char *p=s.data();
3209 bool inNum=FALSE;
3210 QCString result;
3211 if (p)
3212 {
3213 char c = 0;
3214 while ((c=*p))
3215 {
3216 if (c=='(') // potential cast, ignore it
3217 {
3218 const char *q = process_cast_or_sizeof(p+1).first;
3219 //printf("potential cast:\nin: %s\nout: %s\n",p,q);
3220 if (q)
3221 {
3222 p=q;
3223 continue;
3224 }
3225 }
3226 else if (c=='s' && literal_at(p,"sizeof")) // sizeof(...)
3227 {
3228 const char *q = p+6;
3229 while (*q==' ' || *q=='\t') q++;
3230 if (*q=='(')
3231 {
3232 auto r = process_cast_or_sizeof(q+1);
3233 //printf("sizeof:\nin: %s\nout: %zu%s\n--> sizeof=%zu\n",p,r.second,r.first,r.second);
3234 if (r.first)
3235 {
3236 result+=QCString().setNum(r.second);
3237 p=r.first;
3238 continue;
3239 }
3240 }
3241 }
QCString & setNum(short n)
Definition qcstring.h:459
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
3242
3243 if (c=='@') // replace @@ with @ and remove @E
3244 {
3245 if (*(p+1)=='@')
3246 {
3247 result+=c;
3248 }
3249 else if (*(p+1)=='E')
3250 {
3251 // skip
3252 }
3253 p+=2;
3254 }
3255 else if (isdigit(c)) // number
3256 {
3257 result+=c;
3258 p++;
3259 inNum=TRUE;
3260 }
3261 else if (c=='\'') // quoted character
3262 {
3263 p = processUntilMatchingTerminator(p,result);
3264 }
3265 else if (c=='d' && !inNum) // identifier starting with a 'd'
3266 {
3267 if (literal_at(p,"defined ") || literal_at(p,"defined("))
3268 // defined keyword
3269 {
3270 p+=7; // skip defined
3271 }
3272 else
3273 {
3274 result+="0L";
3275 p++;
3276 while ((c=*p) && isId(c)) p++;
3277 }
3278 }
3279 else if ((isalpha(c) || c=='_') && !inNum) // replace identifier with 0L
3280 {
3281 result+="0L";
3282 p++;
3283 while ((c=*p) && isId(c)) p++;
3284 while ((c=*p) && isspace((uint8_t)c)) p++;
3285 if (*p=='(') // undefined function macro
3286 {
3287 p++;
3288 int count=1;
3289 while ((c=*p++))
3290 {
3291 if (c=='(') count++;
3292 else if (c==')')
3293 {
3294 count--;
3295 if (count==0) break;
3296 }
3297 else if (c=='/')
3298 {
3299 char pc=c;
3300 c=*++p;
3301 if (c=='*') // start of C comment
3302 {
3303 while (*p && !(pc=='*' && c=='/')) // search end of comment
3304 {
3305 pc=c;
3306 c=*++p;
3307 }
3308 p++;
3309 }
3310 }
3311 }
3312 }
3313 }
3314 else if (c=='/') // skip C comments
3315 {
3316 char pc=c;
3317 c=*++p;
3318 if (c=='*') // start of C comment
3319 {
3320 while (*p && !(pc=='*' && c=='/')) // search end of comment
3321 {
3322 pc=c;
3323 c=*++p;
3324 }
3325 p++;
3326 }
3327 else // oops, not comment but division
3328 {
3329 result+=pc;
3330 goto nextChar;
3331 }
3332 }
3333 else
3334 {
static const char * processUntilMatchingTerminator(const char *inputStr, QCString &result)
Process string or character literal.
Definition pre.l:3120
3335nextChar:
3336 result+=c;
3337 char lc=(char)tolower(c);
3338 if (!isId(lc) && lc!='.' /*&& lc!='-' && lc!='+'*/) inNum=FALSE;
3339 p++;
3340 }
3341 }
3342 }
3343 //printf("removeIdsAndMarkers(%s)=%s\n",s,qPrint(result));
3344 return result;
3345}

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

Referenced by computeExpression().

◆ removeMarkers()

QCString removeMarkers ( const QCString & s)
static

replaces all occurrences of @ in s by @

assumption:
s only contains pairs of @'s

Definition at line 3351 of file pre.l.

3352{
3353 if (s.isEmpty()) return s;
3354 const char *p=s.data();
3355 QCString result;
3356 if (p)
3357 {
3358 char c = 0;
3359 while ((c=*p))
3360 {
3361 switch(c)
3362 {
3363 case '@': // replace @@ with @
3364 {
3365 if (*(p+1)=='@')
3366 {
3367 result+=c;
3368 }
3369 p+=2;
3370 }
3371 break;
3372 case '/': // skip C comments
3373 {
3374 result+=c;
3375 char pc=c;
3376 c=*++p;
3377 if (c=='*') // start of C comment
3378 {
3379 while (*p && !(pc=='*' && c=='/')) // search end of comment
3380 {
3381 if (*p=='@' && *(p+1)=='@')
3382 result+=c,p++;
3383 else
3384 result+=c;
3385 pc=c;
3386 c=*++p;
3387 }
3388 if (*p) result+=c,p++;
3389 }
3390 }
3391 break;
3392 case '"': // skip string literals
3393 case '\'': // skip char literals
3394 p = processUntilMatchingTerminator(p,result);
3395 break;
3396 default:
3397 {
3398 result+=c;
3399 p++;
3400 }
3401 break;
3402 }
3403 }
3404 }
3405 //printf("RemoveMarkers(%s)=%s\n",s,qPrint(result));
3406 return result;
3407}

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

Referenced by computeExpression(), and expandMacro().

◆ replaceFunctionMacro()

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

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

Definition at line 2637 of file pre.l.

2638{
2639 //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());
2640 uint32_t j=pos;
2641 len=0;
2642 result.clear();
2643 int cc;
2644
2645 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:2599
2646
2647 if (cc!='(')
2648 {
2649 if (cc!=':') // don't add spaces for colons
2650 {
2651 unputChar(yyscanner,expr,rest,j,' ');
2652 }
2653 return FALSE;
2654 }
2655 getNextChar(yyscanner,expr,rest,j); // eat the '(' character
2656
2657 std::map<std::string,std::string> argTable; // list of arguments
2658 QCString arg;
2659 int argCount=0;
2660 bool done=FALSE;
2661
2662 // PHASE 1: read the macro arguments
2663 if (def->nargs==0)
2664 {
2665 while ((cc=getNextChar(yyscanner,expr,rest,j))!=EOF && cc!=0)
2666 {
2667 char c = (char)cc;
2668 if (c==')') break;
2669 }
2670 }
2671 else
2672 {
2673 while (!done && (argCount<def->nargs || def->varArgs) &&
2674 ((cc=getNextChar(yyscanner,expr,rest,j))!=EOF && cc!=0)
2675 )
2676 {
2677 char c=(char)cc;
2678 if (c=='(') // argument is a function => search for matching )
2679 {
2680 int lvl=1;
2681 arg+=c;
2682 //char term='\0';
2683 while ((cc=getNextChar(yyscanner,expr,rest,j))!=EOF && cc!=0)
2684 {
2685 c=(char)cc;
2686 //printf("processing %c: term=%c (%d)\n",c,term,term);
2687 if (c=='\'' || c=='\"') // skip ('s and )'s inside strings
2688 {
2689 arg+=c;
2690 addTillEndOfString(yyscanner,expr,rest,j,c,arg);
2691 }
2692 if (c==')')
2693 {
2694 lvl--;
2695 arg+=c;
2696 if (lvl==0) break;
2697 }
2698 else if (c=='(')
2699 {
2700 lvl++;
2701 arg+=c;
2702 }
2703 else
2704 arg+=c;
2705 }
2706 }
2707 else if (c==')' || c==',') // last or next argument found
2708 {
2709 if (c==',' && argCount==def->nargs-1 && def->varArgs)
2710 {
2711 arg=arg.stripWhiteSpace();
2712 arg+=',';
2713 }
2714 else
2715 {
2716 QCString argKey;
2717 argKey.sprintf("@%d",argCount++); // key name
2718 arg=arg.stripWhiteSpace();
2719 // add argument to the lookup table
2720 argTable.emplace(toStdString(argKey), toStdString(arg));
2721 arg.clear();
2722 if (c==')') // end of the argument list
2723 {
2724 done=TRUE;
2725 }
2726 }
2727 }
2728 else if (c=='\"') // append literal strings
2729 {
2730 arg+=c;
2731 bool found=FALSE;
2732 while (!found && (cc=getNextChar(yyscanner,expr,rest,j))!=EOF && cc!=0)
2733 {
2734 found = cc=='"';
2735 if (cc=='\\')
2736 {
2737 c=(char)cc;
2738 arg+=c;
2739 if ((cc=getNextChar(yyscanner,expr,rest,j))==EOF || cc==0) break;
2740 }
2741 c=(char)cc;
2742 arg+=c;
2743 }
2744 }
2745 else if (c=='\'') // append literal characters
2746 {
2747 arg+=c;
2748 bool found=FALSE;
2749 while (!found && (cc=getNextChar(yyscanner,expr,rest,j))!=EOF && cc!=0)
2750 {
2751 found = cc=='\'';
2752 if (cc=='\\')
2753 {
2754 c=(char)cc;
2755 arg+=c;
2756 if ((cc=getNextChar(yyscanner,expr,rest,j))==EOF || cc==0) break;
2757 }
2758 c=(char)cc;
2759 arg+=c;
2760 }
2761 }
2762 else if (c=='/') // possible start of a comment
2763 {
2764 char prevChar = '\0';
2765 arg+=c;
2766 if ((cc=getCurrentChar(yyscanner,expr,rest,j)) == '*') // we have a comment
2767 {
2768 while ((cc=getNextChar(yyscanner,expr,rest,j))!=EOF && cc!=0)
2769 {
2770 c=(char)cc;
2771 arg+=c;
2772 if (c == '/' && prevChar == '*') break; // we have an end of comment
2773 prevChar = c;
2774 }
2775 }
2776 }
2777 else // append other characters
2778 {
2779 arg+=c;
2780 }
2781 }
2782 }
static int getCurrentChar(yyscan_t yyscanner, const QCString &expr, QCString *rest, uint32_t pos)
Definition pre.l:3852
static void addTillEndOfString(yyscan_t yyscanner, const QCString &expr, QCString *rest, uint32_t &pos, char term, QCString &arg)
Definition pre.l:2587
2783
2784 // PHASE 2: apply the macro function
2785 if (argCount==def->nargs || // same number of arguments
2786 (argCount>=def->nargs-1 && def->varArgs)) // variadic macro with at least as many
2787 // params as the non-variadic part (see bug731985)
2788 {
2789 uint32_t k=0;
2790 // substitution of all formal arguments
2791 QCString resExpr;
2792 const QCString d=def->definition.stripWhiteSpace();
2793 //printf("Macro definition: '%s'\n",qPrint(d));
2794 bool inString=FALSE;
2795 while (k<d.length())
2796 {
2797 if (d.at(k)=='@') // maybe a marker, otherwise an escaped @
2798 {
2799 if (d.at(k+1)=='@') // escaped @ => copy it (is unescaped later)
2800 {
2801 k+=2;
2802 resExpr+="@@"; // we unescape these later
2803 }
2804 else if (d.at(k+1)=='-') // no-rescan marker
2805 {
2806 k+=2;
2807 resExpr+="@-";
2808 }
2809 else // argument marker => read the argument number
2810 {
2811 QCString key="@";
2812 bool hash=FALSE;
2813 int l=k-1;
2814 // search for ## backward
2815 if (l>=0 && d.at(l)=='"') l--;
2816 while (l>=0 && d.at(l)==' ') l--;
2817 if (l>0 && d.at(l)=='#' && d.at(l-1)=='#') hash=TRUE;
2818 k++;
2819 // scan the number
2820 while (k<d.length() && d.at(k)>='0' && d.at(k)<='9') key+=d.at(k++);
2821 if (!hash)
2822 {
2823 // search for ## forward
2824 l=k;
2825 if (l<(int)d.length() && d.at(l)=='"') l++;
2826 while (l<(int)d.length() && d.at(l)==' ') l++;
2827 if (l<(int)d.length()-1 && d.at(l)=='#' && d.at(l+1)=='#') hash=TRUE;
2828 }
2829 //printf("request key %s result %s\n",qPrint(key),argTable[key]->data());
2830 auto it = argTable.find(key.str());
2831 if (it!=argTable.end())
2832 {
2833 QCString substArg = it->second;
2834 //printf("substArg='%s'\n",qPrint(substArg));
2835 // only if no ## operator is before or after the argument
2836 // marker we do macro expansion.
2837 if (!hash)
2838 {
2839 expandExpression(yyscanner,substArg,nullptr,0,level+1);
2840 }
2841 if (inString)
2842 {
2843 //printf("'%s'=stringize('%s')\n",qPrint(stringize(*subst)),subst->data());
2844
2845 // if the marker is inside a string (because a # was put
2846 // before the macro name) we must escape " and \ characters
2847 resExpr+=stringize(substArg);
2848 }
2849 else
2850 {
2851 if (hash && substArg.isEmpty())
2852 {
2853 resExpr+="@E"; // empty argument will be remove later on
2854 }
2855 resExpr+=substArg;
2856 }
2857 }
2858 }
2859 }
2860 else // no marker, just copy
2861 {
2862 if (!inString && d.at(k)=='\"')
2863 {
2864 inString=TRUE; // entering a literal string
2865 }
2866 else if (k>2 && inString && d.at(k)=='\"' && (d.at(k-1)!='\\' || d.at(k-2)=='\\'))
2867 {
2868 inString=FALSE; // leaving a literal string
2869 }
2870 resExpr+=d.at(k++);
2871 }
2872 }
2873 len=j-pos;
2874 result=resExpr;
2875 //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());
2876 return TRUE;
2877 }
2878 //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());
2879 return FALSE;
static QCString stringize(const QCString &s)
Definition pre.l:2456
2880}

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

Referenced by expandExpression().

◆ resolveTrigraph()

char resolveTrigraph ( char c)
static

Definition at line 3809 of file pre.l.

3810{
3811 switch (c)
3812 {
3813 case '=': return '#';
3814 case '/': return '\\';
3815 case '\'': return '^';
3816 case '(': return '[';
3817 case ')': return ']';
3818 case '!': return '|';
3819 case '<': return '{';
3820 case '>': return '}';
3821 case '-': return '~';
3822 }
3823 return '?';
3824}

◆ returnCharToStream()

void returnCharToStream ( yyscan_t yyscanner,
char c )
static

Definition at line 2581 of file pre.l.

2582{
2583 struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
2584 unput(c);
2585}

Referenced by getCurrentChar(), and unputChar().

◆ setCaseDone()

void setCaseDone ( yyscan_t yyscanner,
bool value )
static

Definition at line 2268 of file pre.l.

2269{
2270 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
2271 state->levelGuard.top()=value;
2272}

◆ setFileName()

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

Definition at line 2212 of file pre.l.

2213{
2214 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
2215 bool ambig = false;
2216 FileInfo fi(name.str());
2217 state->fileName=fi.absFilePath();
2218 state->yyFileDef=findFileDef(Doxygen::inputNameLinkedMap,state->fileName,ambig);
2219 if (state->yyFileDef==nullptr) // if this is not an input file check if it is an include file
2220 {
2221 state->yyFileDef=findFileDef(Doxygen::includeNameLinkedMap,state->fileName,ambig);
2222 }
2223 //printf("setFileName(%s) state->fileName=%s state->yyFileDef=%p\n",
2224 // name,qPrint(state->fileName),state->yyFileDef);
2225 if (state->yyFileDef && state->yyFileDef->isReference()) state->yyFileDef=nullptr;
2226 state->insideIDL = getLanguageFromFileName(state->fileName)==SrcLangExt::IDL;
2227 state->insideCS = getLanguageFromFileName(state->fileName)==SrcLangExt::CSharp;
2228 state->insideFtn = getLanguageFromFileName(state->fileName)==SrcLangExt::Fortran;
2229 EntryType section = guessSection(state->fileName);
2230 state->isSource = section.isHeader() || section.isSource();
static FileNameLinkedMap * includeNameLinkedMap
Definition doxygen.h:102
Wrapper class for the Entry type.
Definition types.h:793
SrcLangExt getLanguageFromFileName(const QCString &fileName, SrcLangExt defLang)
Definition util.cpp:5724
EntryType guessSection(const QCString &name)
Definition util.cpp:350
2231}

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

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

◆ skipCommentMacroName()

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

Definition at line 2599 of file pre.l.

2601{
2602 bool changed = false;
2603
2604 do
2605 {
2606 changed = false;
2607 while ((cc=getCurrentChar(yyscanner,expr,rest,j))!=EOF && cc!='\n' && isspace(cc))
2608 {
2609 len++;
2610 getNextChar(yyscanner,expr,rest,j);
2611 }
2612
2613 if (cc=='/') // possible start of a comment
2614 {
2615 int prevChar = '\0';
2616 getNextChar(yyscanner,expr,rest,j);
2617 if ((cc=getCurrentChar(yyscanner,expr,rest,j))!=EOF && cc == '*') // we have a comment
2618 {
2619 while ((cc=getNextChar(yyscanner,expr,rest,j))!=EOF && cc!=0)
2620 {
2621 if (cc == '/' && prevChar == '*') break; // we have an end of comment
2622 prevChar = cc;
2623 }
2624 if (cc != EOF) changed = true;
2625 }
2626 }
2627 } while (changed);
2628}

References getCurrentChar(), and getNextChar().

Referenced by replaceFunctionMacro().

◆ startCondSection()

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

Definition at line 3753 of file pre.l.

3754{
3755 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
3756 //printf("startCondSection: skip=%d stack=%d\n",state->skip,state->condStack.size());
3757 CondParser prs;
3758 bool expResult = prs.parse(state->fileName.data(),state->yyLineNr,sectId.data());
3759 state->condStack.emplace(std::make_unique<preYY_CondCtx>(state->fileName,state->yyLineNr,sectId,state->skip));
3760 if (!expResult)
3761 {
3762 state->skip=TRUE;
3763 }
3764 //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.
3765}

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

◆ stateToString()

const char * stateToString ( int state)
static

◆ stringize()

QCString stringize ( const QCString & s)
static

Definition at line 2456 of file pre.l.

2457{
2458 QCString result;
2459 uint32_t i=0;
2460 bool inString=FALSE;
2461 bool inChar=FALSE;
2462 char c,pc;
2463 while (i<s.length())
2464 {
2465 if (!inString && !inChar)
2466 {
2467 while (i<s.length() && !inString && !inChar)
2468 {
2469 c=s.at(i++);
2470 if (c=='"')
2471 {
2472 result+="\\\"";
2473 inString=TRUE;
2474 }
2475 else if (c=='\'')
2476 {
2477 result+=c;
2478 inChar=TRUE;
2479 }
2480 else
2481 {
2482 result+=c;
2483 }
2484 }
2485 }
2486 else if (inChar)
2487 {
2488 while (i<s.length() && inChar)
2489 {
2490 c=s.at(i++);
2491 if (c=='\'')
2492 {
2493 result+='\'';
2494 inChar=FALSE;
2495 }
2496 else if (c=='\\')
2497 {
2498 result+="\\\\";
2499 }
2500 else
2501 {
2502 result+=c;
2503 }
2504 }
2505 }
2506 else
2507 {
2508 pc=0;
2509 while (i<s.length() && inString)
2510 {
2511 c=s.at(i++);
2512 if (c=='"')
2513 {
2514 result+="\\\"";
2515 inString= pc=='\\';
2516 }
2517 else if (c=='\\')
2518 result+="\\\\";
2519 else
2520 result+=c;
2521 pc=c;
2522 }
2523 }
2524 }
2525 //printf("stringize '%s'->'%s'\n",qPrint(s),qPrint(result));
2526 return result;
2527}

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

Referenced by replaceFunctionMacro().

◆ unputChar()

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

Definition at line 3875 of file pre.l.

3876{
3877 //printf("unputChar(%s,%s,%d,%c)\n",qPrint(expr),rest ? rest->data() : 0,pos,c);
3878 if (pos<expr.length())
3879 {
3880 pos++;
3881 }
3882 else if (rest)
3883 {
3884 //printf(" prepending '%c' to rest!\n",c);
3885 char cs[2];cs[0]=c;cs[1]='\0';
3886 rest->prepend(cs);
3887 }
3888 else
3889 {
3890 //printf(" yyunput()='%c'\n",c);
3891 returnCharToStream(yyscanner,c);
3892 }
3893 //printf("result: unputChar(%s,%s,%d,%c)\n",qPrint(expr),rest ? rest->data() : 0,pos,c);
QCString & prepend(const char *s)
Definition qcstring.h:422
3894}

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

Referenced by addSeparatorsIfNeeded(), and replaceFunctionMacro().

◆ yylex()

int yylex ( yyscan_t yyscanner)

Definition at line 485 of file pre.l.

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

◆ yyread()

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

Definition at line 2191 of file pre.l.

2192{
2193 YY_EXTRA_TYPE state = preYYget_extra(yyscanner);
2194 int bytesInBuf = static_cast<int>(state->inputBuf->size())-state->inputBufPos;
2195 int bytesToCopy = std::min(max_size,bytesInBuf);
2196 memcpy(buf,state->inputBuf->data()+state->inputBufPos,bytesToCopy);
2197 state->inputBufPos+=bytesToCopy;
2198 return bytesToCopy;
2199}

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