diff options
Diffstat (limited to 'src')
40 files changed, 611 insertions, 493 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 7233052..7e54b2b 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -100,25 +100,39 @@ add_custom_command( ) set_source_files_properties(${GENERATED_SRC}/layout_default.xml.h PROPERTIES GENERATED 1) -# Targets for flex/bison generated files -FLEX_TARGET(scanner scanner.l ${GENERATED_SRC}/scanner.cpp COMPILE_FLAGS "${LEX_FLAGS}") -FLEX_TARGET(code code.l ${GENERATED_SRC}/code.cpp COMPILE_FLAGS "${LEX_FLAGS}") -FLEX_TARGET(pyscanner pyscanner.l ${GENERATED_SRC}/pyscanner.cpp COMPILE_FLAGS "${LEX_FLAGS}") -FLEX_TARGET(pycode pycode.l ${GENERATED_SRC}/pycode.cpp COMPILE_FLAGS "${LEX_FLAGS}") -FLEX_TARGET(fortranscanner fortranscanner.l ${GENERATED_SRC}/fortranscanner.cpp COMPILE_FLAGS "${LEX_FLAGS}") -FLEX_TARGET(fortrancode fortrancode.l ${GENERATED_SRC}/fortrancode.cpp COMPILE_FLAGS "${LEX_FLAGS}") -FLEX_TARGET(vhdlcode vhdlcode.l ${GENERATED_SRC}/vhdlcode.cpp COMPILE_FLAGS "${LEX_FLAGS}") -FLEX_TARGET(tclscanner tclscanner.l ${GENERATED_SRC}/tclscanner.cpp COMPILE_FLAGS "${LEX_FLAGS}") -FLEX_TARGET(pre pre.l ${GENERATED_SRC}/pre.cpp COMPILE_FLAGS "${LEX_FLAGS}") -FLEX_TARGET(declinfo declinfo.l ${GENERATED_SRC}/declinfo.cpp COMPILE_FLAGS "${LEX_FLAGS}") -FLEX_TARGET(defargs defargs.l ${GENERATED_SRC}/defargs.cpp COMPILE_FLAGS "${LEX_FLAGS}") -FLEX_TARGET(doctokenizer doctokenizer.l ${GENERATED_SRC}/doctokenizer.cpp COMPILE_FLAGS "${LEX_FLAGS}") -FLEX_TARGET(commentcnv commentcnv.l ${GENERATED_SRC}/commentcnv.cpp COMPILE_FLAGS "${LEX_FLAGS}") -FLEX_TARGET(commentscan commentscan.l ${GENERATED_SRC}/commentscan.cpp COMPILE_FLAGS "${LEX_FLAGS}") -FLEX_TARGET(constexp constexp.l ${GENERATED_SRC}/constexp.cpp COMPILE_FLAGS "${LEX_FLAGS}") -FLEX_TARGET(xmlcode xmlcode.l ${GENERATED_SRC}/xmlcode.cpp COMPILE_FLAGS "${LEX_FLAGS}") -FLEX_TARGET(sqlcode sqlcode.l ${GENERATED_SRC}/sqlcode.cpp COMPILE_FLAGS "${LEX_FLAGS}") -FLEX_TARGET(configimpl configimpl.l ${GENERATED_SRC}/configimpl.cpp COMPILE_FLAGS "${LEX_FLAGS}") +set(LEX_FILES scanner + code + pyscanner + pycode + fortranscanner + fortrancode + vhdlcode + tclscanner + pre + declinfo + defargs + doctokenizer + commentcnv + commentscan + constexp + xmlcode + sqlcode + configimpl) + +# unfortunately ${LEX_FILES_H} and ${LEX_FILES_CPP} don't work in older versions of CMake (like 3.6.2) for add_library +foreach(lex_file ${LEX_FILES}) + set(LEX_FILES_H ${LEX_FILES_H} " " ${GENERATED_SRC}/${lex_file}.l.h CACHE INTERNAL "Stores generated files") + set(LEX_FILES_CPP ${LEX_FILES_CPP} " " ${GENERATED_SRC}/${lex_file}.cpp CACHE INTERNAL "Stores generated files") + add_custom_command( + COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_SOURCE_DIR}/src/scan_states.py ${CMAKE_SOURCE_DIR}/src/${lex_file}.l > ${GENERATED_SRC}/${lex_file}.l.h + DEPENDS ${CMAKE_SOURCE_DIR}/src/scan_states.py ${CMAKE_SOURCE_DIR}/src/${lex_file}.l + OUTPUT ${GENERATED_SRC}/${lex_file}.l.h + ) + set_source_files_properties(${GENERATED_SRC}/${lex_file}.l.h PROPERTIES GENERATED 1) + + FLEX_TARGET(${lex_file} ${lex_file}.l ${GENERATED_SRC}/${lex_file}.cpp COMPILE_FLAGS "${LEX_FLAGS}") +endforeach() + BISON_TARGET(constexp constexp.y ${GENERATED_SRC}/ce_parse.cpp COMPILE_FLAGS "${YACC_FLAGS}") @@ -140,24 +154,45 @@ add_library(_doxygen STATIC ${GENERATED_SRC}/ce_parse.h ${GENERATED_SRC}/configvalues.h ${GENERATED_SRC}/resources.cpp - # generated by flex/bison - ${GENERATED_SRC}/scanner.cpp + # generated for/by flex/bison + #${LEX_FILES_H} #unfortunately doesn't work in older versions of CMake (like 3.6.2) + #${LEX_FILES_CPP} #unfortunately doesn't work in older versions of CMake (like 3.6.2) + ${GENERATED_SRC}/code.l.h + ${GENERATED_SRC}/commentcnv.l.h + ${GENERATED_SRC}/commentscan.l.h + ${GENERATED_SRC}/configimpl.l.h + ${GENERATED_SRC}/constexp.l.h + ${GENERATED_SRC}/declinfo.l.h + ${GENERATED_SRC}/defargs.l.h + ${GENERATED_SRC}/doctokenizer.l.h + ${GENERATED_SRC}/fortrancode.l.h + ${GENERATED_SRC}/fortranscanner.l.h + ${GENERATED_SRC}/pre.l.h + ${GENERATED_SRC}/pycode.l.h + ${GENERATED_SRC}/pyscanner.l.h + ${GENERATED_SRC}/scanner.l.h + ${GENERATED_SRC}/sqlcode.l.h + ${GENERATED_SRC}/tclscanner.l.h + ${GENERATED_SRC}/vhdlcode.l.h + ${GENERATED_SRC}/xmlcode.l.h ${GENERATED_SRC}/code.cpp - ${GENERATED_SRC}/pyscanner.cpp - ${GENERATED_SRC}/pycode.cpp - ${GENERATED_SRC}/fortranscanner.cpp - ${GENERATED_SRC}/fortrancode.cpp - ${GENERATED_SRC}/vhdlcode.cpp - ${GENERATED_SRC}/tclscanner.cpp - ${GENERATED_SRC}/pre.cpp - ${GENERATED_SRC}/declinfo.cpp - ${GENERATED_SRC}/defargs.cpp - ${GENERATED_SRC}/doctokenizer.cpp ${GENERATED_SRC}/commentcnv.cpp ${GENERATED_SRC}/commentscan.cpp + ${GENERATED_SRC}/configimpl.cpp ${GENERATED_SRC}/constexp.cpp - ${GENERATED_SRC}/xmlcode.cpp + ${GENERATED_SRC}/declinfo.cpp + ${GENERATED_SRC}/defargs.cpp + ${GENERATED_SRC}/doctokenizer.cpp + ${GENERATED_SRC}/fortrancode.cpp + ${GENERATED_SRC}/fortranscanner.cpp + ${GENERATED_SRC}/pre.cpp + ${GENERATED_SRC}/pycode.cpp + ${GENERATED_SRC}/pyscanner.cpp + ${GENERATED_SRC}/scanner.cpp ${GENERATED_SRC}/sqlcode.cpp + ${GENERATED_SRC}/tclscanner.cpp + ${GENERATED_SRC}/vhdlcode.cpp + ${GENERATED_SRC}/xmlcode.cpp # ${GENERATED_SRC}/ce_parse.cpp # @@ -181,16 +216,17 @@ add_library(_doxygen STATIC docparser.cpp docsets.cpp dot.cpp - dotcallgraph.cpp - dotclassgraph.cpp - dotdirdeps.cpp - dotfilepatcher.cpp + dotcallgraph.cpp + dotlegendgraph.cpp + dotclassgraph.cpp + dotdirdeps.cpp + dotfilepatcher.cpp dotgfxhierarchytable.cpp dotgraph.cpp - dotgroupcollaboration.cpp - dotincldepgraph.cpp + dotgroupcollaboration.cpp + dotincldepgraph.cpp dotnode.cpp - dotrunner.cpp + dotrunner.cpp doxygen.cpp eclipsehelp.cpp emoji.cpp @@ -251,6 +287,10 @@ add_library(_doxygen STATIC docgroup.cpp ) +##foreach(lex_file ${LEX_FILES}) +##add_library(_doxygen STATIC ${GENERATED_SRC}/${lex_file}.l.h) +##endforeach() + add_executable(doxygen main.cpp) if (use_libclang) diff --git a/src/cite.cpp b/src/cite.cpp index fd7b0e4..a36f62c 100644 --- a/src/cite.cpp +++ b/src/cite.cpp @@ -151,7 +151,7 @@ void CiteDict::generatePage() const p=s+1; int i; - if ((i = line.find("crossref")) != -1) /* assumption crosreference is on one line and the only item */ + if ((i = line.find("crossref")) != -1) /* assumption crossreference is on one line and the only item */ { int j=line.find("{",i); int k=line.find("}",i); @@ -165,6 +165,8 @@ static int g_braceCount=0; static void saveObjCContext(); static void restoreObjCContext(); +static const char *stateToString(int state); + static QCString g_forceTagReference; @@ -3875,3 +3877,4 @@ extern "C" { // some bogus code to keep the compiler happy #error "You seem to be using a version of flex newer than 2.5.4. These are currently incompatible with 2.5.4, and do NOT work with doxygen! Please use version 2.5.4 or expect things to be parsed wrongly! A bug report has been submitted (#732132)." #endif +#include "code.l.h" diff --git a/src/commentcnv.l b/src/commentcnv.l index 2550227..f144aec 100644 --- a/src/commentcnv.l +++ b/src/commentcnv.l @@ -94,6 +94,8 @@ static bool g_vhdl; // for VHDL old style --! comment static SrcLangExt g_lang; static bool isFixedForm; // For Fortran +static const char *stateToString(int state); + static void replaceCommentMarker(const char *s,int len) { const char *p=s; @@ -1145,3 +1147,4 @@ extern "C" { // some bogus code to keep the compiler happy } #endif +#include "commentcnv.l.h" diff --git a/src/commentscan.l b/src/commentscan.l index a495c5e..abf218c 100644 --- a/src/commentscan.l +++ b/src/commentscan.l @@ -78,6 +78,7 @@ static bool handleFile(const QCString &, const QCStringList &); static bool handleDir(const QCString &, const QCStringList &); static bool handleExample(const QCString &, const QCStringList &); static bool handleDetails(const QCString &, const QCStringList &); +static bool handleNoop(const QCString &, const QCStringList &); static bool handleName(const QCString &, const QCStringList &); static bool handleTodo(const QCString &, const QCStringList &); static bool handleTest(const QCString &, const QCStringList &); @@ -132,6 +133,8 @@ static bool handleEndParBlock(const QCString &, const QCStringList &); static bool handleParam(const QCString &, const QCStringList &); static bool handleRetval(const QCString &, const QCStringList &); +static const char *stateToString(int state); + typedef bool (*DocCmdFunc)(const QCString &name, const QCStringList &optList); struct DocCmdMap @@ -279,6 +282,7 @@ static DocCmdMap docCmdMap[] = { "warning", 0, TRUE }, { "snippet", 0, TRUE }, { "snippetlineno", 0, TRUE }, + { "noop", &handleNoop, TRUE }, { 0, 0, FALSE } }; @@ -998,6 +1002,7 @@ RCSTAG "$"{ID}":"[^\n$]+"$" %x CopyDoc %x GuardExpr %x CdataSection +%x Noop %% @@ -2129,6 +2134,14 @@ RCSTAG "$"{ID}":"[^\n$]+"$" current->name+=*yytext; } + /* ----- handle argument of noop command ------- */ +<Noop>{DOCNL} { // end of argument + if (*yytext=='\n') yyLineNr++; + addOutput('\n'); + BEGIN( Comment ); + } +<Noop>. { // ignore other stuff + } /* ----- handle argument of ingroup command ------- */ <InGroupParam>{LABELID} { // group id @@ -2540,6 +2553,12 @@ static bool handleDetails(const QCString &, const QCStringList &) return FALSE; } +static bool handleNoop(const QCString &, const QCStringList &) +{ + BEGIN( Noop ); + return FALSE; +} + static bool handleName(const QCString &, const QCStringList &) { bool stop=makeStructuralIndicator(Entry::MEMBERGRP_SEC); @@ -3278,3 +3297,4 @@ extern "C" { // some bogus code to keep the compiler happy } #endif +#include "commentscan.l.h" diff --git a/src/configimpl.l b/src/configimpl.l index 2d91e12..7d22859 100644 --- a/src/configimpl.l +++ b/src/configimpl.l @@ -30,6 +30,7 @@ #include <qregexp.h> #include <qstack.h> #include <qglobal.h> +#include <qthread.h> #include "configimpl.h" #include "version.h" @@ -43,6 +44,8 @@ #define YY_NO_INPUT 1 #define YY_NO_UNISTD_H 1 +static const char *stateToString(int state); + static const char *warning_str = "warning: "; static const char *error_str = "error: "; @@ -1531,6 +1534,7 @@ void Config::checkAndCorrect() // dotImageFormat = "png"; //} + // correct DOT_FONTNAME if needed QCString &dotFontName=Config_getString(DOT_FONTNAME); if (dotFontName=="FreeSans" || dotFontName=="FreeSans.ttf") { @@ -1538,7 +1542,32 @@ void Config::checkAndCorrect() "You may want to clear or change DOT_FONTNAME.\n" "Otherwise you run the risk that the wrong font is being used for dot generated graphs.\n"); } + else if (dotFontName.isEmpty()) + { + dotFontName = "Helvetica"; + } + + // clip dotFontSize against the maximum bounds + int &dotFontSize = Config_getInt(DOT_FONTSIZE); + if (dotFontSize<4) + { + dotFontSize=4; + } + else if (dotFontSize>24) + { + dotFontSize=24; + } + // clip number of threads + int &dotNumThreads = Config_getInt(DOT_NUM_THREADS); + if (dotNumThreads>32) + { + dotNumThreads=32; + } + else if (dotNumThreads<=0) + { + dotNumThreads=QMAX(2,QThread::idealThreadCount()+1); + } // check dot path QCString &dotPath = Config_getString(DOT_PATH); @@ -1882,3 +1911,4 @@ void Config::deinit() ConfigImpl::instance()->deleteInstance(); } +#include "configimpl.l.h" diff --git a/src/constexp.l b/src/constexp.l index c9b984a..b6b3c5c 100644 --- a/src/constexp.l +++ b/src/constexp.l @@ -32,6 +32,7 @@ #define YY_NO_UNISTD_H 1 +static const char *stateToString(int state); static int yyread(char *buf,int max_size,yyscan_t yyscanner); #undef YY_INPUT @@ -139,3 +140,4 @@ bool parseconstexp(const char *fileName,int lineNr,const QCString &s) extern "C" { int constexpYYwrap(yyscan_t yyscanner) { return 1; } } +#include "constexp.l.h" diff --git a/src/declinfo.l b/src/declinfo.l index 36ef94a..0ac1516 100644 --- a/src/declinfo.l +++ b/src/declinfo.l @@ -63,6 +63,7 @@ struct declinfoYY_state bool insidePHP; }; +static const char *stateToString(int state); static void addType(yyscan_t yyscanner); static void addTypeName(yyscan_t yyscanner); static int yyread(char *buf,int max_size, yyscan_t yyscanner); @@ -391,3 +392,4 @@ extern "C" { // some bogus code to keep the compiler happy } #endif +#include "declinfo.l.h" diff --git a/src/defargs.l b/src/defargs.l index 37d904f..070103a 100644 --- a/src/defargs.l +++ b/src/defargs.l @@ -87,6 +87,7 @@ static int g_lastDocChar; static int g_lastExtendsContext; static QCString g_delimiter; +static const char *stateToString(int state); /* ----------------------------------------------------------------- */ #undef YY_INPUT @@ -637,3 +638,4 @@ extern "C" { // some bogus code to keep the compiler happy } #endif +#include "defargs.l.h" diff --git a/src/doctokenizer.l b/src/doctokenizer.l index 6c02bcf..9786720 100644 --- a/src/doctokenizer.l +++ b/src/doctokenizer.l @@ -76,6 +76,7 @@ struct DocLexerContext static QStack<DocLexerContext> g_lexerStack; +static const char *stateToString(int state); //-------------------------------------------------------------------------- void doctokenizerYYpushContext() @@ -353,8 +354,9 @@ ATTRNAME [a-z_A-Z\x80-\xFF][a-z_A-Z0-9\x80-\xFF\-]* ATTRIB {ATTRNAME}{WS}*("="{WS}*(("\""[^\"]*"\"")|("'"[^\']*"'")|[^ \t\r\n'"><]+))? URLCHAR [a-z_A-Z0-9\!\~\,\:\;\'\$\?\@\&\%\#\.\-\+\/\=] URLMASK ({URLCHAR}+([({]{URLCHAR}*[)}])?)+ -FILESCHAR [a-z_A-Z0-9\\:\\\/\-\+@&#] -FILEECHAR [a-z_A-Z0-9\-\+@&#] +URLPROTOCOL ("http:"|"https:"|"ftp:"|"file:"|"news:"|"irc") +FILESCHAR [a-z_A-Z0-9\\:\\\/\-\+&#] +FILEECHAR [a-z_A-Z0-9\-\+&#] HFILEMASK ("."{FILESCHAR}*{FILEECHAR}+)+ FILEMASK ({FILESCHAR}*{FILEECHAR}+("."{FILESCHAR}*{FILEECHAR}+)*)|{HFILEMASK} LINKMASK [^ \t\n\r\\@<&${}]+("("[^\n)]*")")?({BLANK}*("const"|"volatile"){BLANK}+)? @@ -624,17 +626,17 @@ REFWORD_NOCV {FILEMASK}|{LABELID}|{REFWORD2_NOCV}|{REFWORD3}|{REFWORD4_NOCV} } return TK_COMMAND_SEL(); } -<St_Para>("http:"|"https:"|"ftp:"|"file:"|"news:"){URLMASK}/\. { // URL. +<St_Para>{URLPROTOCOL}{URLMASK}/\. { // URL. g_token->name=yytext; g_token->isEMailAddr=FALSE; return TK_URL; } -<St_Para>("http:"|"https:"|"ftp:"|"file:"|"news:"){URLMASK} { // URL +<St_Para>{URLPROTOCOL}{URLMASK} { // URL g_token->name=yytext; g_token->isEMailAddr=FALSE; return TK_URL; } -<St_Para>"<"("http:"|"https:"|"ftp:"|"file:"|"news:"){URLMASK}">" { // URL +<St_Para>"<"{URLPROTOCOL}{URLMASK}">" { // URL g_token->name=yytext; g_token->name = g_token->name.mid(1,g_token->name.length()-2); g_token->isEMailAddr=FALSE; @@ -1615,3 +1617,4 @@ extern "C" { // some bogus code to keep the compiler happy } #endif +#include "doctokenizer.l.h" diff --git a/src/dot.cpp b/src/dot.cpp index 5cdf92c..5ad3916 100644 --- a/src/dot.cpp +++ b/src/dot.cpp @@ -16,12 +16,6 @@ #include <stdlib.h> #include <qdir.h> -#include <qfile.h> -#include <qqueue.h> -#include <qthread.h> -#include <qmutex.h> -#include <qwaitcondition.h> -#include <qregexp.h> #include "config.h" #include "dot.h" @@ -37,34 +31,8 @@ #define MAP_CMD "cmapx" -static int DOT_NUM_THREADS; // will be initialized in initDot - //-------------------------------------------------------------------- -void initDot() -{ - DotGraph::DOT_FONTNAME = Config_getString(DOT_FONTNAME); - if (DotGraph::DOT_FONTNAME.isEmpty()) - { - DotGraph::DOT_FONTNAME="Helvetica"; - } - - DotGraph::DOT_FONTSIZE = Config_getInt(DOT_FONTSIZE); - if (DotGraph::DOT_FONTSIZE<4) DotGraph::DOT_FONTSIZE=4; - - DOT_NUM_THREADS = Config_getInt(DOT_NUM_THREADS); - if (DOT_NUM_THREADS > 32) DOT_NUM_THREADS = 32; - if (DOT_NUM_THREADS <= 0) DOT_NUM_THREADS = QMAX(2,QThread::idealThreadCount()+1); - - // these are copied to be sure to be thread save - DotRunner::DOT_CLEANUP = Config_getBool(DOT_CLEANUP); - DotRunner::DOT_MULTI_TARGETS = Config_getBool(DOT_MULTI_TARGETS); - DotRunner::DOT_EXE.init(Config_getString(DOT_PATH) + "dot"); - - DotGraph::IMG_EXT = getDotImageExtension(); -} - - static QCString g_dotFontPath; static void setDotFontPath(const char *path) @@ -102,95 +70,6 @@ static void unsetDotFontPath() g_dotFontPath=""; } -// extract size from a dot generated SVG file -static bool readSVGSize(const QCString &fileName,int *width,int *height) -{ - bool found=FALSE; - QFile f(fileName); - if (!f.open(IO_ReadOnly)) - { - return FALSE; - } - const int maxLineLen=4096; - char buf[maxLineLen]; - while (!f.atEnd() && !found) - { - int numBytes = f.readLine(buf,maxLineLen-1); // read line - if (numBytes>0) - { - buf[numBytes]='\0'; - if (qstrncmp(buf,"<!--zoomable ",13)==0) - { - *width=-1; - *height=-1; - sscanf(buf,"<!--zoomable %d",height); - //printf("Found zoomable for %s!\n",fileName.data()); - found=TRUE; - } - else if (sscanf(buf,"<svg width=\"%dpt\" height=\"%dpt\"",width,height)==2) - { - //printf("Found fixed size %dx%d for %s!\n",*width,*height,fileName.data()); - found=TRUE; - } - } - else // read error! - { - //printf("Read error %d!\n",numBytes); - return FALSE; - } - } - return TRUE; -} - -static void writeSVGNotSupported(FTextStream &out) -{ - out << "<p><b>This browser is not able to show SVG: try Firefox, Chrome, Safari, or Opera instead.</b></p>"; -} - -// check if a reference to a SVG figure can be written and does so if possible. -// return FALSE if not possible (for instance because the SVG file is not yet generated). -bool writeSVGFigureLink(FTextStream &out,const QCString &relPath, - const QCString &baseName,const QCString &absImgName) -{ - int width=600,height=600; - if (!readSVGSize(absImgName,&width,&height)) - { - return FALSE; - } - if (width==-1) - { - if (height<=60) - height=300; - else - height+=300; // add some extra space for zooming - if (height>600) height=600; // clip to maximum height of 600 pixels - out << "<div class=\"zoom\">"; - //out << "<object type=\"image/svg+xml\" data=\"" - //out << "<embed type=\"image/svg+xml\" src=\"" - out << "<iframe scrolling=\"no\" frameborder=\"0\" src=\"" - << relPath << baseName << ".svg\" width=\"100%\" height=\"" << height << "\">"; - } - else - { - //out << "<object type=\"image/svg+xml\" data=\"" - //out << "<embed type=\"image/svg+xml\" src=\"" - out << "<iframe scrolling=\"no\" frameborder=\"0\" src=\"" - << relPath << baseName << ".svg\" width=\"" - << ((width*96+48)/72) << "\" height=\"" - << ((height*96+48)/72) << "\">"; - } - writeSVGNotSupported(out); - //out << "</object>"; - //out << "</embed>"; - out << "</iframe>"; - if (width==-1) - { - out << "</div>"; - } - - return TRUE; -} - //-------------------------------------------------------------------- DotManager *DotManager::m_theInstance = 0; @@ -204,15 +83,16 @@ DotManager *DotManager::instance() return m_theInstance; } -DotManager::DotManager() : m_dotMaps(1009) +DotManager::DotManager() : m_runners(1009), m_filePatchers(1009) { m_runners.setAutoDelete(TRUE); - m_dotMaps.setAutoDelete(TRUE); + m_filePatchers.setAutoDelete(TRUE); m_queue = new DotRunnerQueue; int i; - if (DOT_NUM_THREADS!=1) + int dotNumThreads = Config_getInt(DOT_NUM_THREADS); + if (dotNumThreads!=1) { - for (i=0;i<DOT_NUM_THREADS;i++) + for (i=0;i<dotNumThreads;i++) { DotWorkerThread *thread = new DotWorkerThread(m_queue); thread->start(); @@ -253,62 +133,22 @@ DotRunner* DotManager::createRunner(const QCString& absDotName, const QCString& return run; } - -int DotManager::addMap(const QCString &file,const QCString &mapFile, - const QCString &relPath,bool urlOnly,const QCString &context, - const QCString &label) -{ - DotFilePatcher *map = m_dotMaps.find(file); - if (map==0) - { - map = new DotFilePatcher(file); - m_dotMaps.append(file,map); - } - return map->addMap(mapFile,relPath,urlOnly,context,label); -} - -int DotManager::addFigure(const QCString &file,const QCString &baseName, - const QCString &figureName,bool heightCheck) -{ - DotFilePatcher *map = m_dotMaps.find(file); - if (map==0) - { - map = new DotFilePatcher(file); - m_dotMaps.append(file,map); - } - return map->addFigure(baseName,figureName,heightCheck); -} - -int DotManager::addSVGConversion(const QCString &file,const QCString &relPath, - bool urlOnly,const QCString &context,bool zoomable, - int graphId) +DotFilePatcher *DotManager::createFilePatcher(const QCString &fileName) { - DotFilePatcher *map = m_dotMaps.find(file); - if (map==0) + DotFilePatcher *patcher = m_filePatchers.find(fileName); + if (patcher==0) { - map = new DotFilePatcher(file); - m_dotMaps.append(file,map); + patcher = new DotFilePatcher(fileName); + m_filePatchers.append(fileName,patcher); } - return map->addSVGConversion(relPath,urlOnly,context,zoomable,graphId); + return patcher; } -int DotManager::addSVGObject(const QCString &file,const QCString &baseName, - const QCString &absImgName,const QCString &relPath) -{ - DotFilePatcher *map = m_dotMaps.find(file); - if (map==0) - { - map = new DotFilePatcher(file); - m_dotMaps.append(file,map); - } - return map->addSVGObject(baseName,absImgName,relPath); -} - -bool DotManager::run() +bool DotManager::run() const { uint numDotRuns = m_runners.count(); - uint numDotMaps = m_dotMaps.count(); - if (numDotRuns+numDotMaps>1) + uint numFilePatchers = m_filePatchers.count(); + if (numDotRuns+numFilePatchers>1) { if (m_workers.count()==0) { @@ -316,7 +156,7 @@ bool DotManager::run() } else { - msg("Generating dot graphs using %d parallel threads...\n",QMIN(numDotRuns+numDotMaps,m_workers.count())); + msg("Generating dot graphs using %d parallel threads...\n",QMIN(numDotRuns+numFilePatchers,m_workers.count())); } } int i=1; @@ -397,27 +237,27 @@ bool DotManager::run() // patch the output file and insert the maps and figures i=1; - SDict<DotFilePatcher>::Iterator di(m_dotMaps); - DotFilePatcher *map; + SDict<DotFilePatcher>::Iterator di(m_filePatchers); + const DotFilePatcher *fp; // since patching the svg files may involve patching the header of the SVG // (for zoomable SVGs), and patching the .html files requires reading that // header after the SVG is patched, we first process the .svg files and // then the other files. - for (di.toFirst();(map=di.current());++di) + for (di.toFirst();(fp=di.current());++di) { - if (map->file().right(4)==".svg") + if (fp->isSVGFile()) { - msg("Patching output file %d/%d\n",i,numDotMaps); - if (!map->run()) return FALSE; + msg("Patching output file %d/%d\n",i,numFilePatchers); + if (!fp->run()) return FALSE; i++; } } - for (di.toFirst();(map=di.current());++di) + for (di.toFirst();(fp=di.current());++di) { - if (map->file().right(4)!=".svg") + if (!fp->isSVGFile()) { - msg("Patching output file %d/%d\n",i,numDotMaps); - if (!map->run()) return FALSE; + msg("Patching output file %d/%d\n",i,numFilePatchers); + if (!fp->run()) return FALSE; i++; } } @@ -426,63 +266,6 @@ bool DotManager::run() //-------------------------------------------------------------------- -class GraphLegendDotGraph : public DotGraph -{ - private: - virtual QCString getBaseName() const - { - return "graph_legend"; - } - - virtual void computeTheGraph() - { - FTextStream md5stream(&m_theGraph); - writeGraphHeader(md5stream,theTranslator->trLegendTitle()); - md5stream << " Node9 [shape=\"box\",label=\"Inherited\",fontsize=\"" << DOT_FONTSIZE << "\",height=0.2,width=0.4,fontname=\"" << DOT_FONTNAME << "\",fillcolor=\"grey75\",style=\"filled\" fontcolor=\"black\"];\n"; - md5stream << " Node10 -> Node9 [dir=\"back\",color=\"midnightblue\",fontsize=\"" << DOT_FONTSIZE << "\",style=\"solid\",fontname=\"" << DOT_FONTNAME << "\"];\n"; - md5stream << " Node10 [shape=\"box\",label=\"PublicBase\",fontsize=\"" << DOT_FONTSIZE << "\",height=0.2,width=0.4,fontname=\"" << DOT_FONTNAME << "\",color=\"black\",URL=\"$classPublicBase" << Doxygen::htmlFileExtension << "\"];\n"; - md5stream << " Node11 -> Node10 [dir=\"back\",color=\"midnightblue\",fontsize=\"" << DOT_FONTSIZE << "\",style=\"solid\",fontname=\"" << DOT_FONTNAME << "\"];\n"; - md5stream << " Node11 [shape=\"box\",label=\"Truncated\",fontsize=\"" << DOT_FONTSIZE << "\",height=0.2,width=0.4,fontname=\"" << DOT_FONTNAME << "\",color=\"red\",URL=\"$classTruncated" << Doxygen::htmlFileExtension << "\"];\n"; - md5stream << " Node13 -> Node9 [dir=\"back\",color=\"darkgreen\",fontsize=\"" << DOT_FONTSIZE << "\",style=\"solid\",fontname=\"" << DOT_FONTNAME << "\"];\n"; - md5stream << " Node13 [shape=\"box\",label=\"ProtectedBase\",fontsize=\"" << DOT_FONTSIZE << "\",height=0.2,width=0.4,fontname=\"" << DOT_FONTNAME << "\",color=\"black\",URL=\"$classProtectedBase" << Doxygen::htmlFileExtension << "\"];\n"; - md5stream << " Node14 -> Node9 [dir=\"back\",color=\"firebrick4\",fontsize=\"" << DOT_FONTSIZE << "\",style=\"solid\",fontname=\"" << DOT_FONTNAME << "\"];\n"; - md5stream << " Node14 [shape=\"box\",label=\"PrivateBase\",fontsize=\"" << DOT_FONTSIZE << "\",height=0.2,width=0.4,fontname=\"" << DOT_FONTNAME << "\",color=\"black\",URL=\"$classPrivateBase" << Doxygen::htmlFileExtension << "\"];\n"; - md5stream << " Node15 -> Node9 [dir=\"back\",color=\"midnightblue\",fontsize=\"" << DOT_FONTSIZE << "\",style=\"solid\",fontname=\"" << DOT_FONTNAME << "\"];\n"; - md5stream << " Node15 [shape=\"box\",label=\"Undocumented\",fontsize=\"" << DOT_FONTSIZE << "\",height=0.2,width=0.4,fontname=\"" << DOT_FONTNAME << "\",color=\"grey75\"];\n"; - md5stream << " Node16 -> Node9 [dir=\"back\",color=\"midnightblue\",fontsize=\"" << DOT_FONTSIZE << "\",style=\"solid\",fontname=\"" << DOT_FONTNAME << "\"];\n"; - md5stream << " Node16 [shape=\"box\",label=\"Templ< int >\",fontsize=\"" << DOT_FONTSIZE << "\",height=0.2,width=0.4,fontname=\"" << DOT_FONTNAME << "\",color=\"black\",URL=\"$classTempl" << Doxygen::htmlFileExtension << "\"];\n"; - md5stream << " Node17 -> Node16 [dir=\"back\",color=\"orange\",fontsize=\"" << DOT_FONTSIZE << "\",style=\"dashed\",label=\"< int >\",fontname=\"" << DOT_FONTNAME << "\"];\n"; - md5stream << " Node17 [shape=\"box\",label=\"Templ< T >\",fontsize=\"" << DOT_FONTSIZE << "\",height=0.2,width=0.4,fontname=\"" << DOT_FONTNAME << "\",color=\"black\",URL=\"$classTempl" << Doxygen::htmlFileExtension << "\"];\n"; - md5stream << " Node18 -> Node9 [dir=\"back\",color=\"darkorchid3\",fontsize=\"" << DOT_FONTSIZE << "\",style=\"dashed\",label=\"m_usedClass\",fontname=\"" << DOT_FONTNAME << "\"];\n"; - md5stream << " Node18 [shape=\"box\",label=\"Used\",fontsize=\"" << DOT_FONTSIZE << "\",height=0.2,width=0.4,fontname=\"" << DOT_FONTNAME << "\",color=\"black\",URL=\"$classUsed" << Doxygen::htmlFileExtension << "\"];\n"; - writeGraphFooter(md5stream); - } - - virtual QCString getMapLabel() const - { - return ""; - } - - friend void generateGraphLegend(const char* path); -}; - -void generateGraphLegend(const char *path) -{ - QDir d(path); - GraphLegendDotGraph dg; - FTextStream ts; - dg.writeGraph(ts, GOF_BITMAP, EOF_Html, path, "", "", FALSE, 0); - - if (getDotImageExtension()=="svg") - { - DotManager::instance()->addSVGObject( - dg.absBaseName()+Config_getString(HTML_FILE_EXTENSION), - "graph_legend", - dg.absImgName(),QCString()); - } - -} - void writeDotGraphFromFile(const char *inFile,const char *outDir, const char *outFile,GraphOutputFormat format) { @@ -560,10 +343,8 @@ void writeDotImageMapFromFile(FTextStream &t, if (imgExt=="svg") // vector graphics { - //writeSVGFigureLink(t,relPath,inFile,inFile+".svg"); - //DotFilePatcher patcher(inFile+".svg"); QCString svgName=outDir+"/"+baseName+".svg"; - writeSVGFigureLink(t,relPath,baseName,svgName); + DotFilePatcher::writeSVGFigureLink(t,relPath,baseName,svgName); DotFilePatcher patcher(svgName); patcher.addSVGConversion("",TRUE,context,TRUE,graphId); patcher.run(); @@ -575,7 +356,7 @@ void writeDotImageMapFromFile(FTextStream &t, t << "<img src=\"" << relPath << imgName << "\" alt=\"" << imgName << "\" border=\"0\" usemap=\"#" << mapName << "\"/>" << endl; - convertMapFile(tt, absOutFile, relPath ,TRUE, context); + DotFilePatcher::convertMapFile(tt, absOutFile, relPath ,TRUE, context); if (!result.isEmpty()) { t << "<map name=\"" << mapName << "\" id=\"" << mapName << "\">"; @@ -18,66 +18,43 @@ #include <qlist.h> #include <qdict.h> -#include <qwaitcondition.h> -#include <qmutex.h> -#include <qqueue.h> -#include <qthread.h> +#include <qcstring.h> + #include "sortdict.h" -#include "qgstring.h" -#include "qdir.h" -#include "qcstring.h" -#include "dotgraph.h" + +#include "dotgraph.h" // only for GraphOutputFormat #include "dotfilepatcher.h" #include "dotrunner.h" class FTextStream; class DotRunner; class DotRunnerQueue; -class DotWorkerThread; -/** Singleton that manages dot relation actions */ +/** Singleton that manages parallel dot invocations and patching files for embedding image maps */ class DotManager { public: static DotManager *instance(); - DotRunner* createRunner(const QCString& absDotName, const QCString& md5Hash); - int addMap(const QCString &file,const QCString &mapFile, - const QCString &relPath,bool urlOnly, - const QCString &context,const QCString &label); - int addFigure(const QCString &file,const QCString &baseName, - const QCString &figureName,bool heightCheck); - int addSVGConversion(const QCString &file,const QCString &relPath, - bool urlOnly,const QCString &context,bool zoomable,int graphId); - int addSVGObject(const QCString &file,const QCString &baseName, - const QCString &figureNAme,const QCString &relPath); - bool run(); + DotRunner* createRunner(const QCString& absDotName, const QCString& md5Hash); + DotFilePatcher *createFilePatcher(const QCString &fileName); + bool run() const; private: DotManager(); virtual ~DotManager(); QDict<DotRunner> m_runners; - SDict<DotFilePatcher> m_dotMaps; + SDict<DotFilePatcher> m_filePatchers; static DotManager *m_theInstance; DotRunnerQueue *m_queue; QList<DotWorkerThread> m_workers; }; -void initDot(); - -/** Generated a graphs legend page */ -void generateGraphLegend(const char *path); - void writeDotGraphFromFile(const char *inFile,const char *outDir, const char *outFile,GraphOutputFormat format); void writeDotImageMapFromFile(FTextStream &t, const QCString& inFile, const QCString& outDir, const QCString& relPath,const QCString& baseName, const QCString& context,int graphId=-1); -bool writeSVGFigureLink(FTextStream &out,const QCString &relPath, - const QCString &baseName,const QCString &absImgName); -bool convertMapFile(FTextStream &t,const char *mapName, - const QCString relPath, bool urlOnly=FALSE, - const QCString &context=QCString()); #endif diff --git a/src/dotdirdeps.cpp b/src/dotdirdeps.cpp index 85906d1..98c7ca7 100644 --- a/src/dotdirdeps.cpp +++ b/src/dotdirdeps.cpp @@ -22,14 +22,16 @@ void writeDotDirDepGraph(FTextStream &t,const DirDef *dd,bool linkRelations) { + int fontSize = Config_getInt(DOT_FONTSIZE); + QCString fontName = Config_getString(DOT_FONTNAME); t << "digraph \"" << dd->displayName() << "\" {\n"; if (Config_getBool(DOT_TRANSPARENT)) { t << " bgcolor=transparent;\n"; } t << " compound=true\n"; - t << " node [ fontsize=\"" << DotGraph::DOT_FONTSIZE << "\", fontname=\"" << DotGraph::DOT_FONTNAME << "\"];\n"; - t << " edge [ labelfontsize=\"" << DotGraph::DOT_FONTSIZE << "\", labelfontname=\"" << DotGraph::DOT_FONTNAME << "\"];\n"; + t << " node [ fontsize=\"" << fontSize << "\", fontname=\"" << fontName << "\"];\n"; + t << " edge [ labelfontsize=\"" << fontSize << "\", labelfontname=\"" << fontName << "\"];\n"; QDict<DirDef> dirsInGraph(257); @@ -39,7 +41,7 @@ void writeDotDirDepGraph(FTextStream &t,const DirDef *dd,bool linkRelations) t << " subgraph cluster" << dd->parent()->getOutputFileBase() << " {\n"; t << " graph [ bgcolor=\"#ddddee\", pencolor=\"black\", label=\"" << dd->parent()->shortName() - << "\" fontname=\"" << DotGraph::DOT_FONTNAME << "\", fontsize=\"" << DotGraph::DOT_FONTSIZE << "\", URL=\""; + << "\" fontname=\"" << fontName << "\", fontsize=\"" << fontSize << "\", URL=\""; t << dd->parent()->getOutputFileBase() << Doxygen::htmlFileExtension; t << "\"]\n"; } diff --git a/src/dotfilepatcher.cpp b/src/dotfilepatcher.cpp index 91b7c78..92a5618 100644 --- a/src/dotfilepatcher.cpp +++ b/src/dotfilepatcher.cpp @@ -14,6 +14,7 @@ */ #include "dotfilepatcher.h" +#include "dotrunner.h" #include "qstring.h" #include "config.h" @@ -209,7 +210,7 @@ static QCString replaceRef(const QCString &buf,const QCString relPath, * map file was found * \returns TRUE if successful. */ -bool convertMapFile(FTextStream &t,const char *mapName, +bool DotFilePatcher::convertMapFile(FTextStream &t,const char *mapName, const QCString relPath, bool urlOnly, const QCString &context) { @@ -255,9 +256,9 @@ DotFilePatcher::DotFilePatcher(const char *patchFile) m_maps.setAutoDelete(TRUE); } -QCString DotFilePatcher::file() const +bool DotFilePatcher::isSVGFile() const { - return m_patchFile; + return m_patchFile.right(4)==".svg"; } int DotFilePatcher::addMap(const QCString &mapFile,const QCString &relPath, @@ -320,7 +321,7 @@ int DotFilePatcher::addSVGObject(const QCString &baseName, return id; } -bool DotFilePatcher::run() +bool DotFilePatcher::run() const { //printf("DotFilePatcher::run(): %s\n",m_patchFile.data()); bool interactiveSVG_local = Config_getBool(INTERACTIVE_SVG); @@ -479,7 +480,7 @@ bool DotFilePatcher::run() Map *map = m_maps.at(mapId); //printf("patching FIG %d in file %s with contents of %s\n", // mapId,m_patchFile.data(),map->mapFile.data()); - if (!DotGraph::writeVecGfxFigure(t,map->label,map->mapFile)) + if (!writeVecGfxFigure(t,map->label,map->mapFile)) { err("problem writing FIG %d figure!\n",mapId); return FALSE; @@ -537,3 +538,144 @@ bool DotFilePatcher::run() QDir::current().remove(tmpName); return TRUE; } + +//--------------------------------------------------------------------------------------------- + + +// extract size from a dot generated SVG file +static bool readSVGSize(const QCString &fileName,int *width,int *height) +{ + bool found=FALSE; + QFile f(fileName); + if (!f.open(IO_ReadOnly)) + { + return FALSE; + } + const int maxLineLen=4096; + char buf[maxLineLen]; + while (!f.atEnd() && !found) + { + int numBytes = f.readLine(buf,maxLineLen-1); // read line + if (numBytes>0) + { + buf[numBytes]='\0'; + if (qstrncmp(buf,"<!--zoomable ",13)==0) + { + *width=-1; + *height=-1; + sscanf(buf,"<!--zoomable %d",height); + //printf("Found zoomable for %s!\n",fileName.data()); + found=TRUE; + } + else if (sscanf(buf,"<svg width=\"%dpt\" height=\"%dpt\"",width,height)==2) + { + //printf("Found fixed size %dx%d for %s!\n",*width,*height,fileName.data()); + found=TRUE; + } + } + else // read error! + { + //printf("Read error %d!\n",numBytes); + return FALSE; + } + } + return TRUE; +} + +static void writeSVGNotSupported(FTextStream &out) +{ + out << "<p><b>This browser is not able to show SVG: try Firefox, Chrome, Safari, or Opera instead.</b></p>"; +} + +/// Check if a reference to a SVG figure can be written and do so if possible. +/// Returns FALSE if not possible (for instance because the SVG file is not yet generated). +bool DotFilePatcher::writeSVGFigureLink(FTextStream &out,const QCString &relPath, + const QCString &baseName,const QCString &absImgName) +{ + int width=600,height=600; + if (!readSVGSize(absImgName,&width,&height)) + { + return FALSE; + } + if (width==-1) + { + if (height<=60) height=300; else height+=300; // add some extra space for zooming + if (height>600) height=600; // clip to maximum height of 600 pixels + out << "<div class=\"zoom\">"; + //out << "<object type=\"image/svg+xml\" data=\"" + //out << "<embed type=\"image/svg+xml\" src=\"" + out << "<iframe scrolling=\"no\" frameborder=\"0\" src=\"" + << relPath << baseName << ".svg\" width=\"100%\" height=\"" << height << "\">"; + } + else + { + //out << "<object type=\"image/svg+xml\" data=\"" + //out << "<embed type=\"image/svg+xml\" src=\"" + out << "<iframe scrolling=\"no\" frameborder=\"0\" src=\"" + << relPath << baseName << ".svg\" width=\"" + << ((width*96+48)/72) << "\" height=\"" + << ((height*96+48)/72) << "\">"; + } + writeSVGNotSupported(out); + //out << "</object>"; + //out << "</embed>"; + out << "</iframe>"; + if (width==-1) + { + out << "</div>"; + } + + return TRUE; +} + +bool DotFilePatcher::writeVecGfxFigure(FTextStream &out,const QCString &baseName, + const QCString &figureName) +{ + int width=400,height=550; + if (Config_getBool(USE_PDFLATEX)) + { + if (!DotRunner::readBoundingBox(figureName+".pdf",&width,&height,FALSE)) + { + //printf("writeVecGfxFigure()=0\n"); + return FALSE; + } + } + else + { + if (!DotRunner::readBoundingBox(figureName+".eps",&width,&height,TRUE)) + { + //printf("writeVecGfxFigure()=0\n"); + return FALSE; + } + } + //printf("Got PDF/EPS size %d,%d\n",width,height); + int maxWidth = 350; /* approx. page width in points, excl. margins */ + int maxHeight = 550; /* approx. page height in points, excl. margins */ + out << "\\nopagebreak\n" + "\\begin{figure}[H]\n" + "\\begin{center}\n" + "\\leavevmode\n"; + if (width>maxWidth || height>maxHeight) // figure too big for page + { + // c*width/maxWidth > c*height/maxHeight, where c=maxWidth*maxHeight>0 + if (width*maxHeight>height*maxWidth) + { + out << "\\includegraphics[width=" << maxWidth << "pt]"; + } + else + { + out << "\\includegraphics[height=" << maxHeight << "pt]"; + } + } + else + { + out << "\\includegraphics[width=" << width << "pt]"; + } + + out << "{" << baseName << "}\n" + "\\end{center}\n" + "\\end{figure}\n"; + + //printf("writeVecGfxFigure()=1\n"); + return TRUE; +} diff --git a/src/dotfilepatcher.h b/src/dotfilepatcher.h index dd5c511..b68208d 100644 --- a/src/dotfilepatcher.h +++ b/src/dotfilepatcher.h @@ -19,21 +19,37 @@ #include "qcstring.h" #include "qlist.h" +class FTextStream; + /** Helper class to insert a set of map file into an output file */ class DotFilePatcher { public: DotFilePatcher(const char *patchFile); + int addMap(const QCString &mapFile,const QCString &relPath, bool urlOnly,const QCString &context,const QCString &label); + int addFigure(const QCString &baseName, const QCString &figureName,bool heightCheck); + int addSVGConversion(const QCString &relPath,bool urlOnly, const QCString &context,bool zoomable,int graphId); + int addSVGObject(const QCString &baseName, const QCString &figureName, const QCString &relPath); - bool run(); - QCString file() const; + bool run() const; + bool isSVGFile() const; + + static bool convertMapFile(FTextStream &t,const char *mapName, + const QCString relPath, bool urlOnly=FALSE, + const QCString &context=QCString()); + + static bool writeSVGFigureLink(FTextStream &out,const QCString &relPath, + const QCString &baseName,const QCString &absImgName); + + static bool writeVecGfxFigure(FTextStream& out, const QCString& baseName, + const QCString& figureName); private: struct Map @@ -50,4 +66,5 @@ class DotFilePatcher QCString m_patchFile; }; + #endif diff --git a/src/dotgraph.cpp b/src/dotgraph.cpp index ca6bcca..df64d66 100644 --- a/src/dotgraph.cpp +++ b/src/dotgraph.cpp @@ -24,11 +24,12 @@ #include "dotrunner.h" #include "dotgraph.h" #include "dotnode.h" +#include "dotfilepatcher.h" #define MAP_CMD "cmapx" -QCString DotGraph::DOT_FONTNAME; // will be initialized in initDot -int DotGraph::DOT_FONTSIZE; // will be initialized in initDot +//QCString DotGraph::DOT_FONTNAME; // will be initialized in initDot +//int DotGraph::DOT_FONTSIZE; // will be initialized in initDot /*! Checks if a file "baseName".md5 exists. If so the contents * are compared with \a md5. If equal FALSE is returned. @@ -90,7 +91,7 @@ static bool insertMapFile(FTextStream &out,const QCString &mapFile, { QGString tmpstr; FTextStream tmpout(&tmpstr); - convertMapFile(tmpout,mapFile,relPath,FALSE); + DotFilePatcher::convertMapFile(tmpout,mapFile,relPath,FALSE); if (!tmpstr.isEmpty()) { out << "<map name=\"" << mapLabel << "\" id=\"" << mapLabel << "\">" << endl; @@ -104,12 +105,10 @@ static bool insertMapFile(FTextStream &out,const QCString &mapFile, //-------------------------------------------------------------------- -QCString DotGraph::IMG_EXT; - QCString DotGraph::imgName() const { return m_baseName + ((m_graphFormat == GOF_BITMAP) ? - ("." + IMG_EXT) : (Config_getBool(USE_PDFLATEX) ? ".pdf" : ".eps")); + ("." + getDotImageExtension()) : (Config_getBool(USE_PDFLATEX) ? ".pdf" : ".eps")); } QCString DotGraph::writeGraph( @@ -209,6 +208,7 @@ bool DotGraph::prepareDotFile() void DotGraph::generateCode(FTextStream &t) { + QCString imgExt = getDotImageExtension(); if (m_graphFormat==GOF_BITMAP && m_textFormat==EOF_DocBook) { t << "<para>" << endl; @@ -216,7 +216,7 @@ void DotGraph::generateCode(FTextStream &t) t << " <mediaobject>" << endl; t << " <imageobject>" << endl; t << " <imagedata"; - t << " width=\"50%\" align=\"center\" valign=\"middle\" scalefit=\"0\" fileref=\"" << m_relPath << m_baseName << "." << IMG_EXT << "\">"; + t << " width=\"50%\" align=\"center\" valign=\"middle\" scalefit=\"0\" fileref=\"" << m_relPath << m_baseName << "." << imgExt << "\">"; t << "</imagedata>" << endl; t << " </imageobject>" << endl; t << " </mediaobject>" << endl; @@ -225,16 +225,20 @@ void DotGraph::generateCode(FTextStream &t) } else if (m_graphFormat==GOF_BITMAP && m_generateImageMap) // produce HTML to include the image { - if (IMG_EXT=="svg") // add link to SVG file without map file + if (imgExt=="svg") // add link to SVG file without map file { if (!m_noDivTag) t << "<div class=\"center\">"; - if (m_regenerate || !writeSVGFigureLink(t,m_relPath,m_baseName,absImgName())) // need to patch the links in the generated SVG file + if (m_regenerate || !DotFilePatcher::writeSVGFigureLink(t,m_relPath,m_baseName,absImgName())) // need to patch the links in the generated SVG file { if (m_regenerate) { - DotManager::instance()->addSVGConversion(absImgName(),m_relPath,FALSE,QCString(),m_zoomable,m_graphId); + DotManager::instance()-> + createFilePatcher(absImgName())-> + addSVGConversion(m_relPath,FALSE,QCString(),m_zoomable,m_graphId); } - int mapId = DotManager::instance()->addSVGObject(m_fileName,m_baseName,absImgName(),m_relPath); + int mapId = DotManager::instance()-> + createFilePatcher(m_fileName)-> + addSVGObject(m_baseName,absImgName(),m_relPath); t << "<!-- SVG " << mapId << " -->" << endl; } if (!m_noDivTag) t << "</div>" << endl; @@ -247,16 +251,20 @@ void DotGraph::generateCode(FTextStream &t) t << endl; if (m_regenerate || !insertMapFile(t, absMapName(), m_relPath, getMapLabel())) { - int mapId = DotManager::instance()->addMap(m_fileName, absMapName(), m_relPath, m_urlOnly, QCString(), getMapLabel()); + int mapId = DotManager::instance()-> + createFilePatcher(m_fileName)-> + addMap(absMapName(), m_relPath, m_urlOnly, QCString(), getMapLabel()); t << "<!-- MAP " << mapId << " -->" << endl; } } } else if (m_graphFormat==GOF_EPS) // produce tex to include the .eps image { - if (m_regenerate || !writeVecGfxFigure(t,m_baseName,absBaseName())) + if (m_regenerate || !DotFilePatcher::writeVecGfxFigure(t,m_baseName,absBaseName())) { - int figId = DotManager::instance()->addFigure(m_fileName,m_baseName,absBaseName(),FALSE /*TRUE*/); + int figId = DotManager::instance()-> + createFilePatcher(m_fileName)-> + addFigure(m_baseName,absBaseName(),FALSE /*TRUE*/); t << endl << "% FIG " << figId << endl; } } @@ -264,6 +272,8 @@ void DotGraph::generateCode(FTextStream &t) void DotGraph::writeGraphHeader(FTextStream &t,const QCString &title) { + int fontSize = Config_getInt(DOT_FONTSIZE); + QCString fontName = Config_getString(DOT_FONTNAME); t << "digraph "; if (title.isEmpty()) { @@ -284,12 +294,12 @@ void DotGraph::writeGraphHeader(FTextStream &t,const QCString &title) { t << " bgcolor=\"transparent\";" << endl; } - t << " edge [fontname=\"" << DOT_FONTNAME << "\"," - "fontsize=\"" << DOT_FONTSIZE << "\"," - "labelfontname=\"" << DOT_FONTNAME << "\"," - "labelfontsize=\"" << DOT_FONTSIZE << "\"];\n"; - t << " node [fontname=\"" << DOT_FONTNAME << "\"," - "fontsize=\"" << DOT_FONTSIZE << "\",shape=record];\n"; + t << " edge [fontname=\"" << fontName << "\"," + "fontsize=\"" << fontSize << "\"," + "labelfontname=\"" << fontName << "\"," + "labelfontsize=\"" << fontSize << "\"];\n"; + t << " node [fontname=\"" << fontName << "\"," + "fontsize=\"" << fontSize << "\",shape=record];\n"; } void DotGraph::writeGraphFooter(FTextStream &t) @@ -347,54 +357,3 @@ void DotGraph::computeGraph(DotNode *root, graphStr=buf.data(); } -bool DotGraph::writeVecGfxFigure(FTextStream &out,const QCString &baseName, - const QCString &figureName) -{ - int width=400,height=550; - if (Config_getBool(USE_PDFLATEX)) - { - if (!DotRunner::readBoundingBox(figureName+".pdf",&width,&height,FALSE)) - { - //printf("writeVecGfxFigure()=0\n"); - return FALSE; - } - } - else - { - if (!DotRunner::readBoundingBox(figureName+".eps",&width,&height,TRUE)) - { - //printf("writeVecGfxFigure()=0\n"); - return FALSE; - } - } - //printf("Got PDF/EPS size %d,%d\n",width,height); - int maxWidth = 350; /* approx. page width in points, excl. margins */ - int maxHeight = 550; /* approx. page height in points, excl. margins */ - out << "\\nopagebreak\n" - "\\begin{figure}[H]\n" - "\\begin{center}\n" - "\\leavevmode\n"; - if (width>maxWidth || height>maxHeight) // figure too big for page - { - // c*width/maxWidth > c*height/maxHeight, where c=maxWidth*maxHeight>0 - if (width*maxHeight>height*maxWidth) - { - out << "\\includegraphics[width=" << maxWidth << "pt]"; - } - else - { - out << "\\includegraphics[height=" << maxHeight << "pt]"; - } - } - else - { - out << "\\includegraphics[width=" << width << "pt]"; - } - - out << "{" << baseName << "}\n" - "\\end{center}\n" - "\\end{figure}\n"; - - //printf("writeVecGfxFigure()=1\n"); - return TRUE; -} diff --git a/src/dotgraph.h b/src/dotgraph.h index 27d6938..0eda3a8 100644 --- a/src/dotgraph.h +++ b/src/dotgraph.h @@ -34,11 +34,6 @@ class DotGraph DotGraph() : m_curNodeNumber(0), m_doNotAddImageToIndex(FALSE), m_noDivTag(FALSE), m_zoomable(TRUE), m_urlOnly(FALSE) {} virtual ~DotGraph() {} - static QCString DOT_FONTNAME; // will be initialized in initDot - static int DOT_FONTSIZE; // will be initialized in initDot - - static bool writeVecGfxFigure(FTextStream& out, const QCString& baseName, const QCString& figureName); - protected: /** returns node numbers. The Counter is reset by the constructor */ int getNextNodeNumber() { return ++m_curNodeNumber; } @@ -72,10 +67,6 @@ class DotGraph virtual void computeTheGraph() = 0; - static QCString IMG_EXT; - - friend void initDot(); - QCString absBaseName() const { return m_absPath + m_baseName; } QCString absDotName() const { return m_absPath + m_baseName + ".dot"; } QCString imgName() const; diff --git a/src/dotgroupcollaboration.cpp b/src/dotgroupcollaboration.cpp index be55ac0..f9a11e7 100644 --- a/src/dotgroupcollaboration.cpp +++ b/src/dotgroupcollaboration.cpp @@ -356,9 +356,10 @@ bool DotGroupCollaboration::isTrivial() const return m_usedNodes->count() <= 1; } -void DotGroupCollaboration::writeGraphHeader(FTextStream &t, - const QCString &title) const +void DotGroupCollaboration::writeGraphHeader(FTextStream &t,const QCString &title) const { + int fontSize = Config_getInt(DOT_FONTSIZE); + QCString fontName = Config_getString(DOT_FONTNAME); t << "digraph "; if (title.isEmpty()) { @@ -374,8 +375,8 @@ void DotGroupCollaboration::writeGraphHeader(FTextStream &t, { t << " bgcolor=\"transparent\";" << endl; } - t << " edge [fontname=\"" << DOT_FONTNAME << "\",fontsize=\"" << DOT_FONTSIZE << "\"," - "labelfontname=\"" << DOT_FONTNAME << "\",labelfontsize=\"" << DOT_FONTSIZE << "\"];\n"; - t << " node [fontname=\"" << DOT_FONTNAME << "\",fontsize=\"" << DOT_FONTSIZE << "\",shape=box];\n"; + t << " edge [fontname=\"" << fontName << "\",fontsize=\"" << fontSize << "\"," + "labelfontname=\"" << fontName << "\",labelfontsize=\"" << fontSize << "\"];\n"; + t << " node [fontname=\"" << fontName << "\",fontsize=\"" << fontSize << "\",shape=box];\n"; t << " rankdir=LR;\n"; } diff --git a/src/dotlegendgraph.cpp b/src/dotlegendgraph.cpp new file mode 100644 index 0000000..98e1f88 --- /dev/null +++ b/src/dotlegendgraph.cpp @@ -0,0 +1,72 @@ +/****************************************************************************** +* +* Copyright (C) 1997-2019 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. +* +*/ + +#include "dotlegendgraph.h" +#include "util.h" +#include "config.h" +#include "doxygen.h" +#include "dot.h" +#include "language.h" +#include "dotfilepatcher.h" + +void DotLegendGraph::writeGraph(const char *path) +{ + FTextStream ts; + DotGraph::writeGraph(ts, GOF_BITMAP, EOF_Html, path, "", "", FALSE, 0); + + if (getDotImageExtension()=="svg") + { + DotManager::instance()-> + createFilePatcher(absBaseName()+Config_getString(HTML_FILE_EXTENSION))-> + addSVGObject("graph_legend", absImgName(),QCString()); + } +} + +QCString DotLegendGraph::getBaseName() const +{ + return "graph_legend"; +} + +void DotLegendGraph::computeTheGraph() +{ + int fontSize = Config_getInt(DOT_FONTSIZE); + QCString fontName = Config_getString(DOT_FONTNAME); + FTextStream md5stream(&m_theGraph); + writeGraphHeader(md5stream,theTranslator->trLegendTitle()); + md5stream << " Node9 [shape=\"box\",label=\"Inherited\",fontsize=\"" << fontSize << "\",height=0.2,width=0.4,fontname=\"" << fontName << "\",fillcolor=\"grey75\",style=\"filled\" fontcolor=\"black\"];\n"; + md5stream << " Node10 -> Node9 [dir=\"back\",color=\"midnightblue\",fontsize=\"" << fontSize << "\",style=\"solid\",fontname=\"" << fontName << "\"];\n"; + md5stream << " Node10 [shape=\"box\",label=\"PublicBase\",fontsize=\"" << fontSize << "\",height=0.2,width=0.4,fontname=\"" << fontName << "\",color=\"black\"];\n"; + md5stream << " Node11 -> Node10 [dir=\"back\",color=\"midnightblue\",fontsize=\"" << fontSize << "\",style=\"solid\",fontname=\"" << fontName << "\"];\n"; + md5stream << " Node11 [shape=\"box\",label=\"Truncated\",fontsize=\"" << fontSize << "\",height=0.2,width=0.4,fontname=\"" << fontName << "\",color=\"red\"];\n"; + md5stream << " Node13 -> Node9 [dir=\"back\",color=\"darkgreen\",fontsize=\"" << fontSize << "\",style=\"solid\",fontname=\"" << fontName << "\"];\n"; + md5stream << " Node13 [shape=\"box\",label=\"ProtectedBase\",fontsize=\"" << fontSize << "\",height=0.2,width=0.4,fontname=\"" << fontName << "\",color=\"black\"];\n"; + md5stream << " Node14 -> Node9 [dir=\"back\",color=\"firebrick4\",fontsize=\"" << fontSize << "\",style=\"solid\",fontname=\"" << fontName << "\"];\n"; + md5stream << " Node14 [shape=\"box\",label=\"PrivateBase\",fontsize=\"" << fontSize << "\",height=0.2,width=0.4,fontname=\"" << fontName << "\",color=\"black\"];\n"; + md5stream << " Node15 -> Node9 [dir=\"back\",color=\"midnightblue\",fontsize=\"" << fontSize << "\",style=\"solid\",fontname=\"" << fontName << "\"];\n"; + md5stream << " Node15 [shape=\"box\",label=\"Undocumented\",fontsize=\"" << fontSize << "\",height=0.2,width=0.4,fontname=\"" << fontName << "\",color=\"grey75\"];\n"; + md5stream << " Node16 -> Node9 [dir=\"back\",color=\"midnightblue\",fontsize=\"" << fontSize << "\",style=\"solid\",fontname=\"" << fontName << "\"];\n"; + md5stream << " Node16 [shape=\"box\",label=\"Templ< int >\",fontsize=\"" << fontSize << "\",height=0.2,width=0.4,fontname=\"" << fontName << "\",color=\"black\"];\n"; + md5stream << " Node17 -> Node16 [dir=\"back\",color=\"orange\",fontsize=\"" << fontSize << "\",style=\"dashed\",label=\"< int >\",fontname=\"" << fontName << "\"];\n"; + md5stream << " Node17 [shape=\"box\",label=\"Templ< T >\",fontsize=\"" << fontSize << "\",height=0.2,width=0.4,fontname=\"" << fontName << "\",color=\"black\"];\n"; + md5stream << " Node18 -> Node9 [dir=\"back\",color=\"darkorchid3\",fontsize=\"" << fontSize << "\",style=\"dashed\",label=\"m_usedClass\",fontname=\"" << fontName << "\"];\n"; + md5stream << " Node18 [shape=\"box\",label=\"Used\",fontsize=\"" << fontSize << "\",height=0.2,width=0.4,fontname=\"" << fontName << "\",color=\"black\"];\n"; + writeGraphFooter(md5stream); +} + +QCString DotLegendGraph::getMapLabel() const +{ + return ""; +} + diff --git a/src/dotlegendgraph.h b/src/dotlegendgraph.h new file mode 100644 index 0000000..2d8eeec --- /dev/null +++ b/src/dotlegendgraph.h @@ -0,0 +1,35 @@ +/****************************************************************************** +* +* Copyright (C) 1997-2019 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. +* +*/ + +#ifndef DOTLEGENDGRAPH_H +#define DOTLEGENDGRAPH_H + +#include "dotgraph.h" + +/** Representation of a legend explaining the meaning of boxes, arrows, and colors */ +class DotLegendGraph : public DotGraph +{ + public: + void writeGraph(const char *path); + + private: + virtual QCString getBaseName() const; + virtual void computeTheGraph(); + virtual QCString getMapLabel() const; + +}; + +#endif + diff --git a/src/dotnode.cpp b/src/dotnode.cpp index ae06fb2..491bcb5 100644 --- a/src/dotnode.cpp +++ b/src/dotnode.cpp @@ -540,7 +540,7 @@ void DotNode::writeArrow(FTextStream &t, if (pointBack && !umlUseArrow) t << "dir=\"back\","; t << "color=\"" << eProps->edgeColorMap[ei->color()] - << "\",fontsize=\"" << DotGraph::DOT_FONTSIZE << "\","; + << "\",fontsize=\"" << Config_getInt(DOT_FONTSIZE) << "\","; t << "style=\"" << eProps->edgeStyleMap[ei->style()] << "\""; if (!ei->label().isEmpty()) { @@ -559,7 +559,7 @@ void DotNode::writeArrow(FTextStream &t, t << ",arrowhead=\"" << eProps->arrowStyleMap[ei->color()] << "\""; } - if (format==GOF_BITMAP) t << ",fontname=\"" << DotGraph::DOT_FONTNAME << "\""; + if (format==GOF_BITMAP) t << ",fontname=\"" << Config_getString(DOT_FONTNAME) << "\""; t << "];" << endl; } diff --git a/src/dotrunner.cpp b/src/dotrunner.cpp index 3a621c7..c01a4e5 100644 --- a/src/dotrunner.cpp +++ b/src/dotrunner.cpp @@ -28,6 +28,7 @@ #define MAX_LATEX_GRAPH_INCH 150 #define MAX_LATEX_GRAPH_SIZE (MAX_LATEX_GRAPH_INCH * 72) +//----------------------------------------------------------------------------------------- // since dot silently reproduces the input file when it does not // support the PNG format, we need to check the result. @@ -142,12 +143,11 @@ bool DotRunner::readBoundingBox(const char *fileName,int *width,int *height,bool return FALSE; } -bool DotRunner::DOT_CLEANUP; -bool DotRunner::DOT_MULTI_TARGETS; -DotConstString DotRunner::DOT_EXE; +//--------------------------------------------------------------------------------- DotRunner::DotRunner(const QCString& absDotName, const QCString& md5Hash) - : m_file(absDotName), m_md5Hash(md5Hash), m_cleanUp(DOT_CLEANUP) + : m_file(absDotName), m_md5Hash(md5Hash), m_cleanUp(Config_getBool(DOT_CLEANUP)), + m_dotExe(Config_getString(DOT_PATH)+"dot") { m_jobs.setAutoDelete(TRUE); } @@ -183,7 +183,7 @@ bool DotRunner::run() DotJob *s; // create output - if (DOT_MULTI_TARGETS) + if (Config_getBool(DOT_MULTI_TARGETS)) { dotArgs=QCString("\"")+m_file.data()+"\""; for (li.toFirst();(s=li.current());++li) @@ -191,14 +191,14 @@ bool DotRunner::run() dotArgs+=' '; dotArgs+=s->args.data(); } - if ((exitCode=portable_system(DOT_EXE.data(),dotArgs,FALSE))!=0) goto error; + if ((exitCode=portable_system(m_dotExe.data(),dotArgs,FALSE))!=0) goto error; } else { for (li.toFirst();(s=li.current());++li) { dotArgs=QCString("\"")+m_file.data()+"\" "+s->args.data(); - if ((exitCode=portable_system(DOT_EXE.data(),dotArgs,FALSE))!=0) goto error; + if ((exitCode=portable_system(m_dotExe.data(),dotArgs,FALSE))!=0) goto error; } } @@ -214,7 +214,7 @@ bool DotRunner::run() { if (!resetPDFSize(width,height,getBaseNameOfOutput(s->output.data()))) goto error; dotArgs=QCString("\"")+m_file.data()+"\" "+s->args.data(); - if ((exitCode=portable_system(DOT_EXE.data(),dotArgs,FALSE))!=0) goto error; + if ((exitCode=portable_system(m_dotExe.data(),dotArgs,FALSE))!=0) goto error; } } @@ -245,7 +245,7 @@ bool DotRunner::run() return TRUE; error: err("Problems running dot: exit code=%d, command='%s', arguments='%s'\n", - exitCode,DOT_EXE.data(),dotArgs.data()); + exitCode,m_dotExe.data(),dotArgs.data()); return FALSE; } diff --git a/src/dotrunner.h b/src/dotrunner.h index 4128fe8..1b68c18 100644 --- a/src/dotrunner.h +++ b/src/dotrunner.h @@ -34,7 +34,6 @@ class DotConstString DotConstString(const DotConstString &s) : m_str(0) { set(s.data()); } const char *data() const { return m_str; } bool isEmpty() const { return m_str==0 || m_str[0]=='\0'; } - void init(const char *s) { set(s); } private: void set(char const* s) @@ -101,14 +100,9 @@ class DotRunner private: DotConstString m_file; DotConstString m_md5Hash; + DotConstString m_dotExe; bool m_cleanUp; QList<DotJob> m_jobs; - - static bool DOT_CLEANUP; - static bool DOT_MULTI_TARGETS; - static DotConstString DOT_EXE; - friend void initDot(); - }; /** Queue of dot jobs to run. */ diff --git a/src/doxygen.cpp b/src/doxygen.cpp index a6455fc..f8e54de 100644 --- a/src/doxygen.cpp +++ b/src/doxygen.cpp @@ -11680,7 +11680,6 @@ void generateOutput() } initSearchIndexer(); - initDot(); bool generateHtml = Config_getBool(GENERATE_HTML); bool generateLatex = Config_getBool(GENERATE_LATEX); diff --git a/src/formula.cpp b/src/formula.cpp index 1c5042e..534f56a 100644 --- a/src/formula.cpp +++ b/src/formula.cpp @@ -118,11 +118,12 @@ void FormulaList::generateBitmaps(const char *path) int pageNum=*pagePtr; msg("Generating image form_%d.png for formula\n",pageNum); char dviArgs[4096]; + char psArgs[4096]; QCString formBase; formBase.sprintf("_form%d",pageNum); // run dvips to convert the page with number pageIndex to an - // encapsulated postscript. - sprintf(dviArgs,"-q -D 600 -E -n 1 -p %d -o %s.eps _formulas.dvi", + // postscript file. + sprintf(dviArgs,"-q -D 600 -n 1 -p %d -o %s_tmp.ps _formulas.dvi", pageIndex,formBase.data()); portable_sysTimerStart(); if (portable_system("dvips",dviArgs)!=0) @@ -133,6 +134,18 @@ void FormulaList::generateBitmaps(const char *path) return; } portable_sysTimerStop(); + // run ps2epsi to convert to an encapsulated postscript file with + // boundingbox (dvips with -E has some problems here). + sprintf(psArgs,"%s_tmp.ps %s.eps",formBase.data(),formBase.data()); + portable_sysTimerStart(); + if (portable_system("ps2epsi",psArgs)!=0) + { + err("Problems running ps2epsi. Check your installation!\n"); + portable_sysTimerStop(); + QDir::setCurrent(oldDir); + return; + } + portable_sysTimerStop(); // now we read the generated postscript file to extract the bounding box QFileInfo fi(formBase+".eps"); if (fi.exists()) @@ -282,6 +295,7 @@ void FormulaList::generateBitmaps(const char *path) f.close(); } // remove intermediate image files + thisDir.remove(formBase+"_tmp.ps"); thisDir.remove(formBase+".eps"); thisDir.remove(formBase+".pnm"); thisDir.remove(formBase+".ps"); diff --git a/src/fortrancode.l b/src/fortrancode.l index 38188ef..eee4d47 100644 --- a/src/fortrancode.l +++ b/src/fortrancode.l @@ -166,6 +166,8 @@ static int inTypeDecl = 0; static bool g_endComment; +static const char *stateToString(int state); + static void endFontClass() { if (g_currentFontClass) @@ -1405,3 +1407,4 @@ extern "C" { // some bogus code to keep the compiler happy } #endif +#include "fortrancode.l.h" diff --git a/src/fortranscanner.l b/src/fortranscanner.l index 09c4490..38abb89 100644 --- a/src/fortranscanner.l +++ b/src/fortranscanner.l @@ -2882,47 +2882,4 @@ extern "C" { // some bogus code to keep the compiler happy } #endif -#define scanStateToString(x) case x: resultString = #x; break; -static const char *stateToString(int state) -{ - const char *resultString; - switch(state) - { - scanStateToString(INITIAL) - scanStateToString(Subprog) - scanStateToString(SubprogPrefix) - scanStateToString(Parameterlist) - scanStateToString(SubprogBody) - scanStateToString(SubprogBodyContains) - scanStateToString(Start) - scanStateToString(Comment) - scanStateToString(Module) - scanStateToString(Program) - scanStateToString(ModuleBody) - scanStateToString(ModuleBodyContains) - scanStateToString(AttributeList) - scanStateToString(Variable) - scanStateToString(Initialization) - scanStateToString(ArrayInitializer) - scanStateToString(Enum) - scanStateToString(Typedef) - scanStateToString(TypedefBody) - scanStateToString(TypedefBodyContains) - scanStateToString(InterfaceBody) - scanStateToString(StrIgnore) - scanStateToString(String) - scanStateToString(Use) - scanStateToString(UseOnly) - scanStateToString(ModuleProcedure) - scanStateToString(Prepass) - scanStateToString(DocBlock) - scanStateToString(DocBackLine) - scanStateToString(EndDoc) - scanStateToString(BlockData) - scanStateToString(Prototype) - scanStateToString(PrototypeSubprog) - scanStateToString(PrototypeArgs) - default: resultString = "Unknown"; break; - } - return resultString; -} +#include "fortranscanner.l.h" diff --git a/src/index.cpp b/src/index.cpp index 0631ee4..f5faea4 100644 --- a/src/index.cpp +++ b/src/index.cpp @@ -41,6 +41,7 @@ #include "ftvhelp.h" #include "dot.h" #include "dotgfxhierarchytable.h" +#include "dotlegendgraph.h" #include "pagedef.h" #include "dirdef.h" #include "vhdldocgen.h" @@ -3919,7 +3920,9 @@ void writeGraphInfo(OutputList &ol) if (!Config_getBool(HAVE_DOT) || !Config_getBool(GENERATE_HTML)) return; ol.pushGeneratorState(); ol.disableAllBut(OutputGenerator::Html); - generateGraphLegend(Config_getString(HTML_OUTPUT)); + + DotLegendGraph gd; + gd.writeGraph(Config_getString(HTML_OUTPUT)); bool &stripCommentsStateRef = Config_getBool(STRIP_CODE_COMMENTS); bool oldStripCommentsState = stripCommentsStateRef; @@ -3944,7 +3947,7 @@ void writeGraphInfo(OutputList &ol) legendDocs = legendDocs.left(s+8) + "[!-- SVG 0 --]\n" + legendDocs.mid(e); //printf("legendDocs=%s\n",legendDocs.data()); } - FileDef *fd = createFileDef("","graph_legend"); + FileDef *fd = createFileDef("","graph_legend.dox"); ol.generateDoc("graph_legend",1,fd,0,legendDocs,FALSE,FALSE); delete fd; diff --git a/src/markdown.cpp b/src/markdown.cpp index 3ee1b71..48f3dbc 100644 --- a/src/markdown.cpp +++ b/src/markdown.cpp @@ -2069,7 +2069,7 @@ static int writeCodeBlock(GrowBuf &out,const char *data,int size,int refIndent) emptyLines++; i=end; } - else if (indent>=refIndent+codeBlockIndent) // enough indent to contine the code block + else if (indent>=refIndent+codeBlockIndent) // enough indent to continue the code block { while (emptyLines>0) // write skipped empty lines { @@ -62,6 +62,8 @@ //#define DBG_CTX(x) fprintf x #define DBG_CTX(x) do { } while(0) +static const char *stateToString(int state); + struct CondCtx { CondCtx(int line,QCString id,bool b) @@ -3337,3 +3339,4 @@ extern "C" { // some bogus code to keep the compiler happy } #endif +#include "pre.l.h" diff --git a/src/pycode.l b/src/pycode.l index 0f04baa..a76129d 100644 --- a/src/pycode.l +++ b/src/pycode.l @@ -97,6 +97,7 @@ static bool g_endComment; static void endFontClass(); static void adjustScopesAndSuites(unsigned indentLength); +static const char *stateToString(int state); /*! Represents a stack of variable to class mappings as found in the @@ -1646,3 +1647,4 @@ extern "C" { // some bogus code to keep the compiler happy #error "You seem to be using a version of flex newer than 2.5.4. These are currently incompatible with 2.5.4, and do NOT work with doxygen! Please use version 2.5.4 or expect things to be parsed wrongly! A bug report has been submitted (#732132)." #endif +#include "pycode.l.h" diff --git a/src/pyscanner.l b/src/pyscanner.l index 3fe66f2..2320bca 100644 --- a/src/pyscanner.l +++ b/src/pyscanner.l @@ -123,6 +123,7 @@ static int g_search_count = 0; static QCString g_argType = ""; static bool g_funcParamsEnd; //----------------------------------------------------------------------------- +static const char *stateToString(int state); static void initParser() @@ -1994,3 +1995,4 @@ extern "C" { // some bogus code to keep the compiler happy } #endif +#include "pyscanner.l.h" diff --git a/src/scan_states.py b/src/scan_states.py new file mode 100644 index 0000000..e156b97 --- /dev/null +++ b/src/scan_states.py @@ -0,0 +1,49 @@ +#!/usr/bin/python +# python script to generate an overview of the staes based on the input lex file. +# +# Copyright (C) 1997-2019 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. +# +import sys +import os +import re + + +def main(): + if len(sys.argv)!=2: + sys.exit('Usage: %s <lex_file>' % sys.argv[0]) + + lex_file = sys.argv[1] + if (os.path.exists(lex_file)): + #write preamble + print("static const char *stateToString(int state)") + print("{") + print(" switch(state)") + print(" {") + print(" case INITIAL: return \"INITIAL\";") + + with open(lex_file) as f: + for line in f: + if re.search(r'^%x', line) or re.search(r'^%s', line): + state = line.split()[1] + print(" case %s: return \"%s\";" % (state,state)) + elif re.search(r'^%%', line): + break + else: + pass + f.close() + #write post + print(" }") + print(" return \"Unknown\";") + print("}") + +if __name__ == '__main__': + main() diff --git a/src/scanner.l b/src/scanner.l index 75786ef..f6ffdff 100644 --- a/src/scanner.l +++ b/src/scanner.l @@ -193,6 +193,7 @@ static int g_column; static int g_fencedSize=0; static bool g_nestedComment=0; +static const char *stateToString(int state); //----------------------------------------------------------------------------- // forward declarations @@ -7490,3 +7491,4 @@ extern "C" { // some bogus code to keep the compiler happy } #endif +#include "scanner.l.h" diff --git a/src/sqlcode.l b/src/sqlcode.l index eec9732..2685c46 100644 --- a/src/sqlcode.l +++ b/src/sqlcode.l @@ -63,6 +63,7 @@ struct sqlcodeYY_state }; static void codify(const char* text); +static const char *stateToString(int state); static void setCurrentDoc(const QCString &anchor,yyscan_t yyscanner); static void startCodeLine(yyscan_t yyscanner); static void endFontClass(yyscan_t yyscanner); @@ -461,3 +462,4 @@ extern "C" { // some bogus code to keep the compiler happy #error "You seem to be using a version of flex newer than 2.5.4. These are currently incompatible with 2.5.4, and do NOT work with doxygen! Please use version 2.5.4 or expect things to be parsed wrongly! A bug report has been submitted (#732132)." #endif +#include "sqlcode.l.h" diff --git a/src/sqlite3gen.cpp b/src/sqlite3gen.cpp index 012a0c0..49818b2 100644 --- a/src/sqlite3gen.cpp +++ b/src/sqlite3gen.cpp @@ -127,7 +127,7 @@ const char * table_schema[][2] = { * I rolled this back when I had trouble getting a FileDef for all types * (PageDef in particular). * - * Note: all colums referencing path would need an update. + * Note: all columns referencing path would need an update. */ { "path", "CREATE TABLE IF NOT EXISTS path (\n" @@ -233,7 +233,7 @@ const char * table_schema[][2] = { }, { "reimplements", "CREATE TABLE IF NOT EXISTS reimplements (\n" - "\t-- Inherited member reimplmentation relations.\n" + "\t-- Inherited member reimplementation relations.\n" "\trowid INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,\n" "\tmemberdef_rowid INTEGER NOT NULL REFERENCES memberdef, -- reimplementing memberdef id.\n" "\treimplemented_rowid INTEGER NOT NULL REFERENCES memberdef, -- reimplemented memberdef id.\n" diff --git a/src/tclscanner.l b/src/tclscanner.l index 88bd474..a680cf9 100644 --- a/src/tclscanner.l +++ b/src/tclscanner.l @@ -59,6 +59,8 @@ #define MAX_INCLUDE_DEPTH 10 +static const char *stateToString(int state); + //! Application error. #define tcl_err \ printf("Error %d %s() at line %d! ",__LINE__,tcl.file_name.data(),yylineno); \ @@ -3121,3 +3123,4 @@ extern "C" { // some bogus code to keep the compiler happy } #endif +#include "tclscanner.l.h" diff --git a/src/util.cpp b/src/util.cpp index 8816de1..4dc7c71 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -9051,9 +9051,9 @@ bool mainPageHasTitle() QCString getDotImageExtension(void) { - QCString imgExt = Config_getEnum(DOT_IMAGE_FORMAT); - imgExt = imgExt.replace( QRegExp(":.*"), "" ); - return imgExt; + QCString imgExt = Config_getEnum(DOT_IMAGE_FORMAT); + int i= imgExt.find(':'); // strip renderer part when using e.g. 'png:cairo:gd' as format + return i==-1 ? imgExt : imgExt.left(i); } bool openOutputFile(const char *outFile,QFile &f) diff --git a/src/vhdlcode.l b/src/vhdlcode.l index 5f668c6..03bf883 100644 --- a/src/vhdlcode.l +++ b/src/vhdlcode.l @@ -112,6 +112,7 @@ static bool writeColoredWord(QCString& word ); static void generateClassOrGlobalLink(CodeOutputInterface &ol,const char *clName, bool typeOnly=FALSE, const char *curr_class=0); static void endFontClass(); static void startFontClass(const char *s); +static const char *stateToString(int state); //------------------------------------------------------------------- @@ -1646,6 +1647,5 @@ extern "C" { // some bogus code to keep the compiler happy #error "You seem to be using a version of flex newer than 2.5.4 but older than 2.5.33. These versions do NOT work with doxygen! Please use version <=2.5.4 or >=2.5.33 or expect things to be parsed wrongly!" #endif - - +#include "vhdlcode.l.h" diff --git a/src/xmlcode.l b/src/xmlcode.l index 42218b1..bd6e8a8 100644 --- a/src/xmlcode.l +++ b/src/xmlcode.l @@ -69,6 +69,8 @@ static MemberDef * g_currentMemberDef; static bool g_includeCodeFragment; static const char * g_currentFontClass; +static const char *stateToString(int state); + static void codify(const char* text) { g_code->codify(text); @@ -413,3 +415,4 @@ extern "C" { // some bogus code to keep the compiler happy #error "You seem to be using a version of flex newer than 2.5.4. These are currently incompatible with 2.5.4, and do NOT work with doxygen! Please use version 2.5.4 or expect things to be parsed wrongly! A bug report has been submitted (#732132)." #endif +#include "xmlcode.l.h" |