/****************************************************************************** * * * * Copyright (C) 1997-2000 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. * */ %{ /* * includes */ #include #include #include #include #include #include #include #include #include #include #include "config.h" #include "version.h" #ifdef DOXYWIZARD #include void err(const char *fmt, ...) { va_list args; va_start(args, fmt); vfprintf(stderr, fmt, args); va_end(args); } void warn_cont(const char *fmt, ...) { va_list args; va_start(args, fmt); vfprintf(stderr, fmt, args); va_end(args); } void initWarningFormat() { } #else #include "doxygen.h" #include "message.h" #include "pre.h" #include "version.h" #include "language.h" #endif #define MAX_INCLUDE_DEPTH 10 #define YY_NEVER_INTERACTIVE 1 #define YY_NO_UNPUT /* ----------------------------------------------------------------- * * exported variables */ #CONFIG Config /* ----------------------------------------------------------------- * * static variables */ 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 includeStack; static int includeDepth; #CONFIG Static /* ----------------------------------------------------------------- */ #undef YY_INPUT #define YY_INPUT(buf,result,max_size) result=yyread(buf,max_size); static int yyread(char *buf,int max_size) { // no file included if (includeStack.isEmpty()) { 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); } } 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 void substEnvVarsInStrList(QStrList &sl); static void substEnvVarsInString(QCString &s); static FILE *findFile(const char *fileName) { substEnvVarsInStrList(includePathList); 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; substEnvVarsInString(inc); 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;ioldState=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 %x Start %x SkipComment %x GetString %x GetBool %x GetStrList %x GetQuotedString %x GetEnvVar %x Include %% <*>\0x0d "#" { BEGIN(SkipComment); } #CONFIG Rules "@INCLUDE_PATH"[ \t]*"=" { BEGIN(GetStrList); l=&includePathList; l->clear(); elemStr=""; } /* include a config file */ "@INCLUDE"[ \t]*"=" { BEGIN(Include);} ([^ \"\t\r\n]+)|("\""[^\n\"]+"\"") { readIncludeFile(yytext); BEGIN(Start); } <> { //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(); fclose(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--; } } [a-z_A-Z0-9]+ { err("Warning: ignoring unknown tag `%s' at line %d, file %s\n",yytext,yyLineNr,yyFileName.data()); } \n { yyLineNr++; BEGIN(Start); } \n { yyLineNr++; if (!elemStr.isEmpty()) { //printf("elemStr1=`%s'\n",elemStr.data()); l->append(elemStr); } BEGIN(Start); } [ \t]+ { if (!elemStr.isEmpty()) { //printf("elemStr2=`%s'\n",elemStr.data()); l->append(elemStr); } elemStr.resize(0); } [^ \"\t\r\n]+ { (*s)+=yytext; } "\"" { lastState=YY_START; BEGIN(GetQuotedString); tmpString.resize(0); } "\""|"\n" { //printf("Quoted String = `%s'\n",tmpString.data()); if (lastState==GetString) (*s)+=tmpString; else elemStr+=tmpString; if (*yytext=='\n') { err("Warning: Missing end quote (\") on line %d, file %s\n",yyLineNr,yyFileName.data()); yyLineNr++; } BEGIN(lastState); } "\\\"" { tmpString+='"'; } . { tmpString+=*yytext; } [a-zA-Z]+ { QCString bs=yytext; bs=bs.upper(); if (bs=="YES") *b=TRUE; else if (bs=="NO") *b=FALSE; else { *b=FALSE; warn_cont("Warning: Invalid value `%s' for " "boolean tag in line %d, file %s; use YES or NO\n", bs.data(),yyLineNr,yyFileName.data()); } } [^ \#\"\t\r\n]+ { elemStr+=yytext; } \n { yyLineNr++; BEGIN(Start); } \\[ \r\t]*\n { yyLineNr++; BEGIN(Start); } <*>\\[ \r\t]*\n { yyLineNr++; } <*>. <*>\n { yyLineNr++ ; } %% /*@ ---------------------------------------------------------------------------- */ void dumpConfig() { #CONFIG Dump } void Config::init() { #CONFIG Init } static void writeBoolValue(QTextStream &t,bool v) { if (v) t << "YES"; else t << "NO"; } static void writeIntValue(QTextStream &t,int i) { t << i; } static void writeStringValue(QTextStream &t,QCString &s) { const char *p=s.data(); char c; bool hasBlanks=FALSE; if (p) { while ((c=*p++)!=0 && !hasBlanks) hasBlanks = (c==' ' || c=='\n' || c=='\t'); if (hasBlanks) t << "\"" << s << "\""; else t << s; } } static void writeStringList(QTextStream &t,QStrList &l) { const char *p = l.first(); bool first=TRUE; while (p) { char c; const char *s=p; bool hasBlanks=FALSE; while ((c=*p++)!=0 && !hasBlanks) hasBlanks = (c==' ' || c=='\n' || c=='\t'); if (!first) t << " "; first=FALSE; if (hasBlanks) t << "\"" << s << "\""; else t << s; p = l.next(); if (p) t << " \\" << endl; } } void writeTemplateConfig(QFile *f,bool sl) { QTextStream t(f); #ifdef DOXYWIZARD t << "# Doxygen configuration generated by Doxywizard version " << versionString << endl; #else t << "# Doxyfile " << versionString << endl << endl; #endif if (!sl) { t << "# This file describes the settings to be used by doxygen for a project\n"; t << "#\n"; t << "# All text after a hash (#) is considered a comment and will be ignored\n"; t << "# The format is:\n"; t << "# TAG = value [value, ...]\n"; t << "# For lists items can also be appended using:\n"; t << "# TAG += value [value, ...]\n"; t << "# Values that contain spaces should be placed between quotes (\" \")\n"; } #CONFIG Template } void configStrToVal() { if (tabSizeString.isEmpty()) { Config::tabSize=8; } else { bool ok; int ts = tabSizeString.toInt(&ok); if (!ok || ts<1 || ts>16) { warn_cont("Warning: argument of TAB_SIZE is not a valid number, using tab size of 8 spaces!\n"); ts=8; } Config::tabSize = ts; } if (colsInAlphaIndexString.isEmpty()) { Config::colsInAlphaIndex=5; } else { bool ok; int cols = colsInAlphaIndexString.toInt(&ok); if (!ok || cols<1 || cols>20) { warn_cont("Warning: argument of COLS_IN_ALPHA_INDEX is not a valid number in the range [1..20]!\n" "Using the default of 5 columns!\n"); cols = 5; } Config::colsInAlphaIndex=cols; } if (enumValuesPerLineString.isEmpty()) { Config::enumValuesPerLine=4; } else { bool ok; int cols = enumValuesPerLineString.toInt(&ok); if (!ok || cols<1 || cols>20) { warn_cont("Warning: argument of ENUM_VALUES_PER_LINE is not a valid number in the range [1..20]!\n" "Using the default of 4!\n"); cols = 4; } Config::enumValuesPerLine=cols; } if (treeViewWidthString.isEmpty()) { Config::treeViewWidth=250; } else { bool ok; int width = treeViewWidthString.toInt(&ok); if (!ok || width<0 || width>1500) { warn_cont("Warning: argument of TREEVIEW_WIDTH is not a valid number in the range [0..1500]!\n" "Using the default of 250!\n"); width = 250; } Config::treeViewWidth=width; } if (maxDotGraphWidthString.isEmpty()) { Config::maxDotGraphWidth=1024; } else { bool ok; int width =maxDotGraphWidthString.toInt(&ok); if (!ok) { warn_cont("Warning: argument of MAX_DOT_GRAPH_WIDTH is not a valid number in the range [100..30000]!\n" "Using the default of 1024 pixels!\n"); width=1024; } else if (width<100) // clip to lower bound { width=100; } else if (width>30000) // clip to upper bound { width=30000; } Config::maxDotGraphWidth=width; } if (maxDotGraphHeightString.isEmpty()) { Config::maxDotGraphHeight=1024; } else { bool ok; int height =maxDotGraphHeightString.toInt(&ok); if (!ok) { warn_cont("Warning: argument of MAX_DOT_GRAPH_WIDTH is not a valid number in the range [100..30000]!\n" "Using the default of 1024 pixels!\n"); height=1024; } else if (height<100) // clip to lower bound { height=100; } else if (height>30000) // clip to upper bound { height=30000; } Config::maxDotGraphHeight=height; } } static void substEnvVarsInString(QCString &s) { static QRegExp re("\\$\\([a-z_A-Z0-9]+\\)"); if (s.isEmpty()) return; int p=0; int i,l; //printf("substEnvVarInString(%s) start\n",s.data()); while ((i=re.match(s,p,&l))!=-1) { //printf("Found environment var s.mid(%d,%d)=`%s'\n",i+2,l-3,s.mid(i+2,l-3).data()); 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+env.length(); // next time start at the end of the expanded string } //printf("substEnvVarInString(%s) end\n",s.data()); } static void substEnvVarsInStrList(QStrList &sl) { char *s = sl.first(); while (s) { QCString result(s); bool wasQuoted = (result.find(' ')!=-1) || (result.find('\t')!=-1); substEnvVarsInString(result); if (!wasQuoted) /* as a result of the expansion, a single string may have expanded into a list, which we'll add to sl. If the orginal string already contained multiple elements no further splitting is done to allow quoted items with spaces! */ { int l=result.length(); int i,p=0; // skip spaces // search for a "word" for (i=0;i