diff options
Diffstat (limited to 'addon/configgen')
-rw-r--r-- | addon/configgen/config_templ.h | 2 | ||||
-rw-r--r-- | addon/configgen/config_templ.l | 197 |
2 files changed, 160 insertions, 39 deletions
diff --git a/addon/configgen/config_templ.h b/addon/configgen/config_templ.h index 0d5ac13..50b479b 100644 --- a/addon/configgen/config_templ.h +++ b/addon/configgen/config_templ.h @@ -21,7 +21,7 @@ #include <qstrlist.h> #include <qfile.h> -extern void parseConfig(const QCString &config); +extern void parseConfig(const QCString &config,const char *fn); extern void writeTemplateConfig(QFile *f,bool shortList); extern void checkConfig(); extern void configStrToVal(); diff --git a/addon/configgen/config_templ.l b/addon/configgen/config_templ.l index e98ace9..3da3d56 100644 --- a/addon/configgen/config_templ.l +++ b/addon/configgen/config_templ.l @@ -27,6 +27,7 @@ #include <qdir.h> #include <qtextstream.h> #include <qregexp.h> +#include <qstack.h> #include "config.h" #include "version.h" @@ -58,6 +59,7 @@ void initWarningFormat() #include "language.h" #endif +#define MAX_INCLUDE_DEPTH 10 #define YY_NEVER_INTERACTIVE 1 #define YY_NO_UNPUT @@ -72,16 +74,31 @@ void initWarningFormat() * * static variables */ - -static const char * inputString; -static int inputPosition; -static int yyLineNr; -static QCString tmpString; -static QCString * s=0; -static bool * b=0; -static QStrList * l=0; -static int lastState; -static QCString elemStr; + +struct ConfigFileState +{ + int lineNr; + FILE *filePtr; + YY_BUFFER_STATE oldState; + YY_BUFFER_STATE newState; + QCString fileName; +}; + +static const char *inputString; +static int inputPosition; +static int yyLineNr; +static QCString yyFileName; +static QCString tmpString; +static QCString *s=0; +static bool *b=0; +static QStrList *l=0; +static int lastState; +static QCString elemStr; +static QCString includeName; +static QStrList includePathList; +static QStack<ConfigFileState> includeStack; +static int includeDepth; + #CONFIG Static /* ----------------------------------------------------------------- @@ -91,15 +108,100 @@ static QCString elemStr; static int yyread(char *buf,int max_size) { - int c=0; - while( c < max_size && inputString[inputPosition] ) + // no file included + if (includeStack.isEmpty()) { - *buf = inputString[inputPosition++] ; - c++; buf++; + int c=0; + while( c < max_size && inputString[inputPosition] ) + { + *buf = inputString[inputPosition++] ; + c++; buf++; + } + return c; + } + else + { + //assert(includeStack.current()->newState==YY_CURRENT_BUFFER); + return fread(buf,1,max_size,includeStack.current()->filePtr); } - return c; } + +static FILE *tryPath(const char *path,const char *fileName) +{ + QCString absName=(QCString)path+"/"+fileName; + QFileInfo fi(absName); + if (fi.exists() && fi.isFile()) + { + FILE *f=fopen(absName,"r"); + if (!f) err("Error: could not open file %s for reading\n",absName.data()); + return f; + } + return 0; +} + +static FILE *findFile(const char *fileName) +{ + char *s=includePathList.first(); + while (s) // try each of the include paths + { + FILE *f = tryPath(s,fileName); + if (f) return f; + s=includePathList.next(); + } + // try cwd if includePathList fails + return tryPath(".",fileName); +} + +static void readIncludeFile(const char *incName) +{ + if (includeDepth==MAX_INCLUDE_DEPTH) { + err("Error: maximum include depth (%d) reached, %s is not included. Aborting...\n", + MAX_INCLUDE_DEPTH,incName); + exit(1); + } + + QCString inc = incName; + inc = inc.stripWhiteSpace(); + uint incLen = inc.length(); + if (inc.at(0)=='"' && inc.at(incLen-1)=='"') // strip quotes + { + inc=inc.mid(1,incLen-2); + } + + FILE *f; + + //printf("Searching for `%s'\n",incFileName.data()); + if ((f=findFile(inc))) // see if the include file can be found + { + // For debugging +#if SHOW_INCLUDES + for (i=0;i<includeStack.count();i++) msg(" "); + msg("@INCLUDE = %s: parsing...\n",inc.data()); +#endif + + // store the state of the old file + ConfigFileState *fs=new ConfigFileState; + fs->oldState=YY_CURRENT_BUFFER; + fs->lineNr=yyLineNr; + fs->fileName=yyFileName; + fs->filePtr=f; + // push the state on the stack + includeStack.push(fs); + // set the scanner to the include file + yy_switch_to_buffer(yy_create_buffer(f, YY_BUF_SIZE)); + fs->newState=YY_CURRENT_BUFFER; + yyFileName=inc; + includeDepth++; + } + else + { + err("Error: @INCLUDE = %s: not found!\n",inc.data()); + exit(1); + } +} + + %} %option noyywrap @@ -111,13 +213,44 @@ static int yyread(char *buf,int max_size) %x GetStrList %x GetQuotedString %x GetEnvVar +%x Include %% <*>\0x0d <Start,GetString,GetStrList,GetBool>"#" { BEGIN(SkipComment); } #CONFIG Rules -<Start>[a-z_A-Z0-9]+ { err("Warning: ignoring unknown tag `%s' at line %d\n",yytext,yyLineNr); } + +<Start>"@INCLUDE_PATH"[ \t]*"=" { BEGIN(GetStrList); l=&includePathList; l->clear(); elemStr=""; } + /* include a config file */ +<Start>"@INCLUDE"[ \t]*"=" { BEGIN(Include);} +<Include>([^ \"\t\r\n]+)|("\""[^\n\"]+"\"") { + readIncludeFile(yytext); + BEGIN(Start); + } +<<EOF>> { + //printf("End of include file\n"); + //printf("Include stack depth=%d\n",g_includeStack.count()); + if (includeStack.isEmpty()) + { + //printf("Terminating scanner!\n"); + yyterminate(); + } + else + { + ConfigFileState *fs=includeStack.pop(); + pclose(fs->filePtr); + YY_BUFFER_STATE oldBuf = YY_CURRENT_BUFFER; + yy_switch_to_buffer( fs->oldState ); + yy_delete_buffer( oldBuf ); + yyLineNr=fs->lineNr; + yyFileName=fs->fileName; + delete fs; fs=0; + includeDepth--; + } + } + +<Start>[a-z_A-Z0-9]+ { err("Warning: ignoring unknown tag `%s' at line %d, file %s\n",yytext,yyLineNr,yyFileName.data()); } <GetString,GetBool>\n { yyLineNr++; BEGIN(Start); } <GetStrList>\n { yyLineNr++; @@ -141,22 +274,6 @@ static int yyread(char *buf,int max_size) BEGIN(GetQuotedString); tmpString.resize(0); } - /* -<GetString,GetStrList,GetQuotedString>"\$\(" { - //printf(">> Enter env\n"); - lastEnvState=YY_START; - BEGIN(GetEnvVar); - } -<GetEnvVar>[a-z_A-Z0-9]+")" { - yytext[yyleng-1]='\0'; - const char *env=getenv(yytext); - int i; - int l=strlen(env); - //printf("env name=`%s' text=`%s'\n",yytext,env); - for (i=l-1;i>=0;i--) unput(env[i]); - BEGIN(lastEnvState); - } - */ <GetQuotedString>"\""|"\n" { //printf("Quoted String = `%s'\n",tmpString.data()); if (lastState==GetString) @@ -165,7 +282,7 @@ static int yyread(char *buf,int max_size) elemStr+=tmpString; if (*yytext=='\n') { - err("Warning: Missing end quote (\") on line %d\n",yyLineNr); + err("Warning: Missing end quote (\") on line %d, file %s\n",yyLineNr,yyFileName.data()); yyLineNr++; } BEGIN(lastState); @@ -185,8 +302,8 @@ static int yyread(char *buf,int max_size) { *b=FALSE; warn_cont("Warning: Invalid value `%s' for " - "boolean tag in line %d; use YES or NO\n", - bs.data(),yyLineNr); + "boolean tag in line %d, file %s; use YES or NO\n", + bs.data(),yyLineNr,yyFileName.data()); } } <GetStrList>[^ \#\"\t\r\n]+ { @@ -249,7 +366,7 @@ static void writeStringList(QTextStream &t,QStrList &l) const char *s=p; bool hasBlanks=FALSE; while ((c=*p++)!=0 && !hasBlanks) hasBlanks = (c==' ' || c=='\n' || c=='\t'); - if (!first) t << " "; + if (!first) t << " "; first=FALSE; if (hasBlanks) t << "\"" << s << "\""; else t << s; p = l.next(); @@ -378,7 +495,7 @@ static void substEnvVarsInString(QCString &s) QCString env=getenv(s.mid(i+2,l-3)); substEnvVarsInString(env); // recursively expand variables if needed. s = s.left(i)+env+s.right(s.length()-i-l); - p=i+l; + p=i+env.length(); // next time start at the end of the expanded string } //printf("substEnvVarInString(%s) end\n",s.data()); } @@ -866,11 +983,15 @@ void checkConfig() } -void parseConfig(const QCString &s) +void parseConfig(const QCString &s,const char *fn) { inputString = s; inputPosition = 0; yyLineNr = 1; + yyFileName=fn; + includeStack.setAutoDelete(TRUE); + includeStack.clear(); + includeDepth = 0; configYYrestart( configYYin ); BEGIN( Start ); configYYlex(); |