summaryrefslogtreecommitdiffstats
path: root/addon/configgen
diff options
context:
space:
mode:
Diffstat (limited to 'addon/configgen')
-rw-r--r--addon/configgen/config_templ.h2
-rw-r--r--addon/configgen/config_templ.l197
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();