📄 pre.l
字号:
/****************************************************************************** * * * * Copyright (C) 1997-2001 by Dimitri van Heesch. * * Permission to use, copy, modify, and distribute this software and its * documentation under the terms of the GNU General Public License is hereby * granted. No representations are made about the suitability of this software * for any purpose. It is provided "as is" without express or implied warranty. * See the GNU General Public License for more details. * * Documents produced by Doxygen are derivative works derived from the * input used in their production; they are not affected by this license. * */%{/* * includes */#include <stdio.h>//#include <iostream.h>#include <assert.h>#include <ctype.h>#include "qtbc.h"#include <qarray.h>#include <qstack.h>#include <qfile.h>#include <qstrlist.h>#include <qdict.h>#include <qregexp.h>#include <qfileinfo.h>#include <qdir.h> #include "pre.h"#include "constexp.h"#include "define.h"#include "doxygen.h"#include "message.h"#include "util.h"#include "defargs.h"#include "debug.h"#include "bufstr.h"#if defined(_MSC_VER) || defined(__BORLANDC__)#define popen _popen#define pclose _pclose#endif#define YY_NEVER_INTERACTIVE 1 struct FileState{ int lineNr; FILE *filePtr; YY_BUFFER_STATE bufState; QCString fileName;}; /* ----------------------------------------------------------------- * * scanner's state */static int g_yyLineNr = 1;static QCString g_yyFileName;static FileDef *g_yyFileDef;static int g_ifcount = 0;static QStrList *g_pathList = 0; static QStack<FileState> g_includeStack;static QDict<int> *g_argDict;static int g_defArgs = -1;static QCString g_defName;static QCString g_defText;static QCString g_defLitText;static QCString g_defArgsStr;static bool g_defVarArgs;static int g_level;static int g_lastCContext;static int g_lastCPPContext;static QArray<int> g_levelGuard;static BufStr *g_outputBuf;static int g_roundCount;static bool g_quoteArg;static DefineDict *g_fileDefineDict;static DefineDict *g_expandedDict;static int g_findDefArgContext;static QCString g_lastGuardName;static QCString g_incName;static QCString g_guardExpr;static int g_curlyCount;static bool g_nospaces; // add extra spaces during macro expansionstatic bool g_macroExpansion; // from the configurationstatic bool g_expandOnlyPredef; // from the configurationstatic void setFileName(const char *name){ bool ambig; g_yyFileName=name; g_yyFileDef=findFileDef(Doxygen::inputNameDict,g_yyFileName,ambig);}static void incrLevel(){ g_level++; g_levelGuard.resize(g_level); g_levelGuard[g_level-1]=FALSE; //printf("%s line %d: incrLevel %d\n",g_yyFileName.data(),g_yyLineNr,g_level);}static void decrLevel(){ //printf("%s line %d: decrLevel %d\n",g_yyFileName.data(),g_yyLineNr,g_level); if (g_level > 0) { g_level--; g_levelGuard.resize(g_level); } else { err("%s:%d: Error: More #endif's than #if's found.\n", g_yyFileName.data(),g_yyLineNr); }}static bool otherCaseDone(){ if (g_level==0) { err("%s:%d: Error: Found an #else without a preceding #if.\n", g_yyFileName.data(),g_yyLineNr); return TRUE; } else { return g_levelGuard[g_level-1]; }}static void setCaseDone(bool value){ g_levelGuard[g_level-1]=value;}static Define *isDefined(const char *name){ if (name) { Define *def; //if ((def=fileDefineCache->findDefine(g_yyFileName,name)) && !def->undef) // return def; if ((def=g_fileDefineDict->find(name)) && !def->undef) return def; } return 0;}static FILE *checkAndOpenFile(const QCString &absName){ FILE *f = 0; QFileInfo fi(absName); if (fi.exists() && fi.isFile()) { if (!Config_getString("INPUT_FILTER").isEmpty()) { QCString cmd = Config_getString("INPUT_FILTER")+" "+absName; f=popen(cmd,"r"); if (!f) err("Error: could not execute filter %s\n",cmd.data()); } else { f=fopen(absName,"r"); if (!f) err("Error: could not open file %s for reading\n",absName.data()); } } return f;}static FILE *findFile(const char *fileName,bool localInclude){ if (localInclude && g_yyFileDef) { QCString absName = g_yyFileDef->getPath()+"/"+fileName; FILE *f = checkAndOpenFile(absName); if (f) { setFileName(absName); g_yyLineNr=1; return f; } } if (g_pathList==0) { return 0; } char *s=g_pathList->first(); while (s) { QCString absName = (QCString)s+"/"+fileName; FILE *f = checkAndOpenFile(absName); if (f) { setFileName(absName); g_yyLineNr=1; return f; } s=g_pathList->next(); } return 0;}static int getNextChar(const QCString &expr,QCString *rest,uint &pos);static int getCurrentChar(const QCString &expr,QCString *rest,uint pos);static void unputChar(const QCString &expr,QCString *rest,uint &pos,char c);static void expandExpression(QCString &expr,QCString *rest,int pos);static QCString stringize(const QCString &s){ QCString result; uint i=0; bool inString=FALSE; bool inChar=FALSE; char c,pc; while (i<s.length()) { if (!inString && !inChar) { while (i<s.length() && !inString && !inChar) { c=s.at(i++); if (c=='"') { result+="\\\""; inString=TRUE; } else if (c=='\'') { result+=c; inChar=TRUE; } else { result+=c; } } } else if (inChar) { while (i<s.length() && inChar) { c=s.at(i++); if (c=='\'') { result+='\''; inChar=FALSE; } else if (c=='\\') { result+="\\\\"; } else { result+=c; } } } else { pc=0; while (i<s.length() && inString) { char c=s.at(i++); if (c=='"') { result+="\\\""; inString= pc=='\\'; } else if (c=='\\') result+="\\\\"; else result+=c; pc=c; } } } //printf("stringize `%s'->`%s'\n",s.data(),result.data()); return result;}/*! 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. */static void processConcatOperators(QCString &expr){ //printf("processConcatOperators: in=`%s'\n",expr.data()); QRegExp r("[ \\t\\n]*##[ \\t\\n]*"); int l,n,i=0; if (expr.isEmpty()) return; while ((n=r.match(expr,i,&l))!=-1) { //printf("Match: `%s'\n",expr.data()+i); if (n+l+1<(int)expr.length() && expr.at(n+l)=='@' && expr.at(n+l+1)=='-') { // remove no-rescan marker after ID l+=2; } //printf("found `%s'\n",expr.mid(n,l).data()); // remove the ## operator and the surrounding whitespace expr=expr.left(n)+expr.right(expr.length()-n-l); int k=n-1; while (k>=0 && isId(expr.at(k))) k--; if (k>0 && expr.at(k)=='-' && expr.at(k-1)=='@') { // remove no-rescan marker before ID expr=expr.left(k-1)+expr.right(expr.length()-k-1); n-=2; } i=n; } //printf("processConcatOperators: out=`%s'\n",expr.data());}/*! replaces the function macro \a def whose argument list starts at * \a pos in expression \a expr. * Notice that this routine may scan beyond the \a expr string if needed. * In that case the characters will be read from the input file. * The replacement string will be returned in \a result and the * length of the (unexpanded) argument list is stored in \a len. */ static bool replaceFunctionMacro(const QCString &expr,QCString *rest,int pos,int &len,const Define *def,QCString &result){ //printf("replaceFunctionMacro(expr=%s,rest=%s,pos=%d,def=%s) level=%d\n",expr.data(),rest ? rest->data() : 0,pos,def->name.data(),g_level); uint j=pos; len=0; result.resize(0); int cc; while ((cc=getCurrentChar(expr,rest,j))!=EOF && cc==' ') { len++; getNextChar(expr,rest,j); } if (cc!='(') { unputChar(expr,rest,j,' '); return FALSE; } getNextChar(expr,rest,j); // eat the `(' character QDict<QCString> argTable; // list of arguments argTable.setAutoDelete(TRUE); QCString arg; int argCount=0; bool done=FALSE; // PHASE 1: read the macro arguments if (def->nargs==0) { while ((cc=getNextChar(expr,rest,j))!=EOF) { char c = (char)cc; if (c==')') break; } } else { while (!done && (argCount<def->nargs || def->varArgs) && ((cc=getNextChar(expr,rest,j))!=EOF) ) { char c=(char)cc; if (c=='(') // argument is a function => search for matching ) { int level=1; arg+=c; char term='\0'; while ((cc=getNextChar(expr,rest,j))!=EOF) { char c=(char)cc; if (c=='\'' || c=='\"') // skip ('s and )'s inside strings { if (term!='\0') { if (c==term && expr.at(j-2)!='\\') term='\0'; } else { term=c; } } if (term=='\0' && c==')') { level--; arg+=c; if (level==0) break; } else if (term=='\0' && c=='(') { level++; arg+=c; } else arg+=c; } } else if (c==')' || c==',') // last or next argument found { if (c==',' && argCount==def->nargs-1 && def->varArgs) { arg=arg.stripWhiteSpace(); arg+=','; } else { QCString argKey; argKey.sprintf("@%d",argCount++); // key name arg=arg.stripWhiteSpace(); // add argument to the lookup table argTable.insert(argKey, new QCString(arg)); arg.resize(0); if (c==')') // end of the argument list { done=TRUE; } } } else if (c=='\"') // append literal strings { arg+=c; bool found=FALSE; while (!found && (cc=getNextChar(expr,rest,j))!=EOF) { found = cc=='"'; if (cc=='\\') { c=(char)cc; arg+=c; if ((cc=getNextChar(expr,rest,j))==EOF) break; } c=(char)cc; arg+=c; } } else if (c=='\'') // append literal characters { arg+=c; bool found=FALSE; while (!found && (cc=getNextChar(expr,rest,j))!=EOF) { found = cc=='\''; if (cc=='\\') { c=(char)cc; arg+=c; if ((cc=getNextChar(expr,rest,j))==EOF) break; } c=(char)cc; arg+=c; } } else // append other characters { arg+=c; } } } // PHASE 2: apply the macro function if (argCount==def->nargs || (argCount>def->nargs && def->varArgs)) // matching parameters lists { uint k=0; // substitution of all formal arguments QCString resExpr; const QCString d=def->definition.stripWhiteSpace(); bool inString=FALSE; while (k<d.length()) { if (d.at(k)=='@') // maybe a marker, otherwise an escaped @ { if (d.at(k+1)=='@') // escaped @ => copy it (is unescaped later) { k+=2; resExpr+="@@"; // we unescape these later } else if (d.at(k+1)=='-') // no-rescan marker { k+=2; resExpr+="@-"; } else // argument marker => read the argument number { QCString key="@"; QCString *subst=0; bool hash=FALSE; int l=k-1; // search for ## backward if (l>=0 && d.at(l)=='"') l--; while (l>=0 && d.at(l)==' ') l--; if (l>0 && d.at(l)=='#' && d.at(l-1)=='#') hash=TRUE; k++; // scan the number
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -