diff -Nur doxygen-1.6.2-20100208.orig/addon/doxywizard/config.h doxygen-1.6.2-20100208/addon/doxywizard/config.h --- doxygen-1.6.2-20100208.orig/addon/doxywizard/config.h 1970-01-01 01:00:00.000000000 +0100 +++ doxygen-1.6.2-20100208/addon/doxywizard/config.h 2008-11-21 12:30:03.000000000 +0100 @@ -0,0 +1,18 @@ +#ifndef CONFIG_H +#define CONFIG_H + +#include +#include + +class Input; +class QTextStream; +class QTextCodec; + +bool parseConfig( + const QString &fileName, + const QHash &options + ); + +void writeStringValue(QTextStream &t,QTextCodec *codec,const QString &s); + +#endif diff -Nur doxygen-1.6.2-20100208.orig/addon/doxywizard/config.l doxygen-1.6.2-20100208/addon/doxywizard/config.l --- doxygen-1.6.2-20100208.orig/addon/doxywizard/config.l 1970-01-01 01:00:00.000000000 +0100 +++ doxygen-1.6.2-20100208/addon/doxywizard/config.l 2009-02-15 16:48:43.000000000 +0100 @@ -0,0 +1,539 @@ +/****************************************************************************** + * + * $Id: config_templ.l,v 1.8 2001/01/01 10:15:16 root Exp $ + * + * Copyright (C) 1997-2007 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 "config.h" +#include "input.h" +#include + +#define MAX_INCLUDE_DEPTH 10 + + +/* ----------------------------------------------------------------- + * + * static variables + */ + +struct ConfigFileState +{ + int lineNr; + FILE *file; + YY_BUFFER_STATE oldState; + YY_BUFFER_STATE newState; + QString fileName; +}; + +static const QHash *g_options; +static FILE *g_file; +static QString g_yyFileName; +static QString g_includeName; +static QVariant g_includePathList; +static QStack g_includeStack; +static int g_includeDepth; +static QVariant *g_arg; +static Input *g_curOption=0; +static QString g_elemStr; +static QTextCodec *g_codec = QTextCodec::codecForName("UTF-8"); +static QString g_codecName = QString::fromAscii("UTF-8"); +static int g_lastState; +static QByteArray g_tmpString; + +/* ----------------------------------------------------------------- + */ +#undef YY_INPUT +#define YY_INPUT(buf,result,max_size) result=yyread(buf,max_size); + +static int yyread(char *buf,int maxSize) +{ + // no file included + if (g_includeStack.isEmpty()) + { + return fread(buf,1,maxSize,g_file); + } + else + { + return fread(buf,1,maxSize,g_includeStack.top()->file); + } +} + +void config_err(const char *fmt, ...) +{ + va_list args; + va_start(args, fmt); + vfprintf(stderr, fmt, args); + va_end(args); +} +void config_warn(const char *fmt, ...) +{ + va_list args; + va_start(args, fmt); + vfprintf(stderr, fmt, args); + va_end(args); +} + +static void substEnvVarsInStrList(QStringList &sl); +static void substEnvVarsInString(QString &s); + +static void checkEncoding() +{ + Input *option = g_options->value(QString::fromAscii("DOXYFILE_ENCODING")); + if (option && option->value().toString()!=g_codecName) + { + QTextCodec *newCodec = QTextCodec::codecForName(option->value().toString().toAscii()); + if (newCodec) + { + g_codec = newCodec; + g_codecName = option->value().toString(); + } + } +} + +static FILE *tryPath(const QString &path,const QString &fileName) +{ + QString absName=!path.isEmpty() ? path+QString::fromAscii("/")+fileName : fileName; + QFileInfo fi(absName); + if (fi.exists() && fi.isFile()) + { + FILE *f = fopen(absName.toLocal8Bit(),"r"); + if (f==NULL) + config_err("Error: could not open file %s for reading\n",absName.toLatin1().data()); + else + return f; + } + return NULL; +} + +static FILE *findFile(const QString &fileName) +{ + if (QFileInfo(fileName).isAbsolute()) // absolute path + { + return tryPath(QString(), fileName); + } + + // relative path, try with include paths in the list + QStringList sl = g_includePathList.toStringList(); + substEnvVarsInStrList(sl); + foreach (QString s, sl) + { + FILE *f = tryPath(s,fileName); + if (f) return f; + } + // try cwd if g_includePathList fails + return tryPath(QString::fromAscii("."),fileName); +} + +static void readIncludeFile(const QString &incName) +{ + if (g_includeDepth==MAX_INCLUDE_DEPTH) + { + config_err("Error: maximum include depth (%d) reached, %s is not included. Aborting...\n", + MAX_INCLUDE_DEPTH,qPrintable(incName)); + exit(1); + } + + QString inc = incName; + substEnvVarsInString(inc); + inc = inc.trimmed(); + uint incLen = inc.length(); + if (inc.at(0)==QChar::fromAscii('"') && + inc.at(incLen-1)==QChar::fromAscii('"')) // strip quotes + { + inc=inc.mid(1,incLen-2); + } + + FILE *f = findFile(inc); + if (f) // see if the include file can be found + { + // For debugging +#if SHOW_INCLUDES + for (i=0;ioldState=YY_CURRENT_BUFFER; + fs->fileName=g_yyFileName; + fs->file=f; + // push the state on the stack + g_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; + g_yyFileName=inc; + g_includeDepth++; + } + else + { + config_err("Error: @INCLUDE = %s: not found!\n",inc.toLatin1().data()); + exit(1); + } +} + + +%} + +%option nounput +%option noyywrap +%option yylineno + +%x Start +%x SkipComment +%x SkipInvalid +%x GetString +%x GetStrList +%x GetQuotedString +%x GetEnvVar +%x Include + +%% + +<*>\0x0d +"#" { BEGIN(SkipComment); } +[a-z_A-Z][a-z_A-Z0-9]*[ \t]*"=" { QString cmd = g_codec->toUnicode(yytext); + cmd=cmd.left(cmd.length()-1).trimmed(); + g_curOption = g_options->value(cmd); + if (g_curOption==0) // oops not known + { + config_err("Warning: ignoring unsupported tag `%s' at line %d, file %s\n", + qPrintable(cmd),yylineno,qPrintable(g_yyFileName)); + BEGIN(SkipInvalid); + } + else // known tag + { + //option->setEncoding(encoding); + g_arg = &g_curOption->value(); + switch(g_curOption->kind()) + { + case Input::StrList: + g_elemStr = QString(); + *g_arg = QStringList(); + BEGIN(GetStrList); + break; + case Input::String: + BEGIN(GetString); + break; + case Input::Int: + BEGIN(GetString); + break; + case Input::Bool: + BEGIN(GetString); + break; + case Input::Obsolete: + config_err("Warning: Tag `%s' at line %d of file %s has become obsolete.\n" + "To avoid this warning please update your configuration " + "file using \"doxygen -u\"\n", qPrintable(cmd), + yylineno,qPrintable(g_yyFileName)); + BEGIN(SkipInvalid); + break; + } + } + } +[a-z_A-Z][a-z_A-Z0-9]*[ \t]*"+=" { QString cmd=g_codec->toUnicode(yytext); + cmd=cmd.left(cmd.length()-2).trimmed(); + g_curOption = g_options->value(cmd); + if (g_curOption==0) // oops not known + { + config_err("Warning: ignoring unsupported tag `%s' at line %d, file %s\n", + yytext,yylineno,qPrintable(g_yyFileName)); + BEGIN(SkipInvalid); + } + else // known tag + { + switch(g_curOption->kind()) + { + case Input::StrList: + g_arg = &g_curOption->value(); + g_elemStr=QString(); + BEGIN(GetStrList); + break; + case Input::String: + case Input::Int: + case Input::Bool: + config_err("Warning: operator += not supported for `%s'. Ignoring line at line %d, file %s\n", + yytext,yylineno,qPrintable(g_yyFileName)); + BEGIN(SkipInvalid); + break; + case Input::Obsolete: + config_err("Warning: Tag `%s' at line %d of file %s has become obsolete.\n" + "To avoid this warning please update your configuration " + "file using \"doxygen -u\"\n", + qPrintable(cmd),yylineno,qPrintable(g_yyFileName)); + BEGIN(SkipInvalid); + break; + } + } + } +"@INCLUDE_PATH"[ \t]*"=" { BEGIN(GetStrList); g_arg=&g_includePathList; *g_arg = QStringList(); g_elemStr=QString(); } + /* include a config file */ +"@INCLUDE"[ \t]*"=" { BEGIN(Include);} +([^ \"\t\r\n]+)|("\""[^\n\"]+"\"") { + readIncludeFile(g_codec->toUnicode(yytext)); + BEGIN(Start); + } +<> { + //printf("End of include file\n"); + //printf("Include stack depth=%d\n",g_includeStack.count()); + if (g_includeStack.isEmpty()) + { + //printf("Terminating scanner!\n"); + yyterminate(); + } + else + { + ConfigFileState *fs = g_includeStack.pop(); + fclose(fs->file); + YY_BUFFER_STATE oldBuf = YY_CURRENT_BUFFER; + yy_switch_to_buffer( fs->oldState ); + yy_delete_buffer( oldBuf ); + g_yyFileName=fs->fileName; + delete fs; + g_includeDepth--; + } + } + +[a-z_A-Z0-9]+ { config_err("Warning: ignoring unknown tag `%s' at line %d, file %s\n",yytext,yylineno,qPrintable(g_yyFileName)); } +\n { BEGIN(Start); } +\n { + if (!g_elemStr.isEmpty()) + { + //printf("elemStr1=`%s'\n",elemStr.toLatin1().data()); + *g_arg = QVariant(g_arg->toStringList() << g_elemStr); + } + BEGIN(Start); + } +[ \t]+ { + if (!g_elemStr.isEmpty()) + { + //printf("elemStr2=`%s'\n",elemStr.toLatin1().data()); + *g_arg = QVariant(g_arg->toStringList() << g_elemStr); + } + g_elemStr = QString(); + } +[^ \"\t\r\n]+ { + *g_arg = QVariant(g_codec->toUnicode(yytext)); + checkEncoding(); + } +"\"" { g_lastState=YY_START; + BEGIN(GetQuotedString); + g_tmpString=""; + } +"\""|"\n" { + // we add a bogus space to signal that the string was quoted. This space will be stripped later on. + g_tmpString+=" "; + //printf("Quoted String = `%s'\n",tmpString.toLatin1().data()); + if (g_lastState==GetString) + { + *g_arg = g_codec->toUnicode(g_tmpString); + checkEncoding(); + } + else + { + g_elemStr+=g_codec->toUnicode(g_tmpString); + } + if (*yytext=='\n') + { + config_err("Warning: Missing end quote (\") on line %d, file %s\n",yylineno, + qPrintable(g_yyFileName)); + } + BEGIN(g_lastState); + } +"\\\"" { + g_tmpString+='"'; + } +. { g_tmpString+=*yytext; } +[^ \#\"\t\r\n]+ { + g_elemStr+=g_codec->toUnicode(yytext); + } +\n { BEGIN(Start); } +\\[ \r\t]*\n { BEGIN(Start); } +<*>\\[ \r\t]*\n { } +<*>\n +<*>. + +%% + +/*@ ---------------------------------------------------------------------------- + */ + +static void substEnvVarsInString(QString &s) +{ + static QRegExp re(QString::fromAscii("\\$\\([a-z_A-Z0-9]+\\)")); + if (s.isEmpty()) return; + int p=0; + int i,l; + //printf("substEnvVarInString(%s) start\n",s.toLatin1().data()); + while ((i=re.indexIn(s,p))!=-1) + { + l = re.matchedLength(); + //printf("Found environment var s.mid(%d,%d)=`%s'\n",i+2,l-3,s.mid(i+2,l-3).toLatin1().data()); + QString env=g_codec->toUnicode(getenv(s.mid(i+2,l-3).toLatin1())); + 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 + } + s=s.trimmed(); // to strip the bogus space that was added when an argument + // has quotes + //printf("substEnvVarInString(%s) end\n",s.toLatin1().data()); +} + +static void substEnvVarsInStrList(QStringList &sl) +{ + QStringList out; + + foreach (QString result, sl) + { + // an argument with quotes will have an extra space at the end, so wasQuoted will be TRUE. + bool wasQuoted = (result.indexOf(QChar::fromAscii(' '))!=-1) || + (result.indexOf(QChar::fromAscii('\t'))!=-1); + // here we strip the quote again + substEnvVarsInString(result); + + //printf("Result %s was quoted=%d\n",result.toLatin1().data(),wasQuoted); + + 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 &options + ) +{ + g_file = fopen(fileName.toLocal8Bit(),"r"); + if (g_file==NULL) return false; + g_options = &options; + g_yyFileName = fileName; + g_includeStack.clear(); + g_includeDepth = 0; + configrestart( configin ); + BEGIN( Start ); + configlex(); + QHashIterator i(options); + while (i.hasNext()) + { + i.next(); + if (i.value()) + { + //printf("Updating: %s\n",qPrintable(i.key())); + i.value()->update(); + } + else + { + printf("Invalid option: %s\n",qPrintable(i.key())); + } + } + fclose(g_file); + return true; +} + +void writeStringValue(QTextStream &t,QTextCodec *codec,const QString &s) +{ + QChar c; + bool needsEscaping=FALSE; + // convert the string back to it original encoding + //QByteArray se = codec->fromUnicode(s); + t.setCodec(codec); + const QChar *p=s.data(); + if (!s.isEmpty() && !p->isNull()) + { + while (!(c=*p++).isNull() && !needsEscaping) + { + needsEscaping = (c==QChar::fromAscii(' ') || + c==QChar::fromAscii('\n') || + c==QChar::fromAscii('\t') || + c==QChar::fromAscii('"')); + } + if (needsEscaping) + { + t << "\""; + p=s.data(); + while (!p->isNull()) + { + if (*p ==QChar::fromAscii(' ') && + *(p+1)==QChar::fromAscii('\0')) break; // skip inserted space at the end + if (*p ==QChar::fromAscii('"')) t << "\\"; // escape quotes + t << *p++; + } + t << "\""; + } + else + { + t << s; + } + } +} +