diff options
author | Dimitri van Heesch <dimitri@stack.nl> | 2007-06-10 20:20:58 (GMT) |
---|---|---|
committer | Dimitri van Heesch <dimitri@stack.nl> | 2007-06-10 20:20:58 (GMT) |
commit | 01147699a7fb267e9d9247bdfb640f46e2164d3a (patch) | |
tree | 7cff22f841dca9c505e2db2f685ece0fc7d95142 | |
parent | 0b087b99d43fb3803b26407d771ca32e6cf5c34b (diff) | |
download | Doxygen-01147699a7fb267e9d9247bdfb640f46e2164d3a.zip Doxygen-01147699a7fb267e9d9247bdfb640f46e2164d3a.tar.gz Doxygen-01147699a7fb267e9d9247bdfb640f46e2164d3a.tar.bz2 |
Release-1.5.2-20070610
-rw-r--r-- | INSTALL | 4 | ||||
-rw-r--r-- | Makefile.in | 22 | ||||
-rw-r--r-- | README | 4 | ||||
-rwxr-xr-x | configure | 7 | ||||
-rw-r--r-- | doc/Doxyfile | 2 | ||||
-rw-r--r-- | doc/config.doc | 22 | ||||
-rw-r--r-- | doc/index.doc | 1 | ||||
-rw-r--r-- | doc/install.doc | 20 | ||||
-rw-r--r-- | doc/xmlcmds.doc | 7 | ||||
-rw-r--r-- | src/classdef.cpp | 365 | ||||
-rw-r--r-- | src/classdef.h | 1 | ||||
-rw-r--r-- | src/cmdmapper.cpp | 8 | ||||
-rw-r--r-- | src/cmdmapper.h | 28 | ||||
-rw-r--r-- | src/commentcnv.l | 77 | ||||
-rw-r--r-- | src/config.l | 42 | ||||
-rw-r--r-- | src/docparser.cpp | 198 | ||||
-rw-r--r-- | src/docparser.h | 3 | ||||
-rw-r--r-- | src/dot.cpp | 476 | ||||
-rw-r--r-- | src/dot.h | 12 | ||||
-rw-r--r-- | src/doxygen.cpp | 81 | ||||
-rw-r--r-- | src/filedef.cpp | 6 | ||||
-rw-r--r-- | src/htmldocvisitor.cpp | 10 | ||||
-rw-r--r-- | src/htmlgen.cpp | 2 | ||||
-rw-r--r-- | src/index.cpp | 3 | ||||
-rw-r--r-- | src/latexgen.cpp | 9 | ||||
-rw-r--r-- | src/memberdef.cpp | 13 | ||||
-rw-r--r-- | src/msc.cpp | 6 | ||||
-rw-r--r-- | src/namespacedef.cpp | 2 | ||||
-rw-r--r-- | src/translator_cn.h | 3 | ||||
-rw-r--r-- | src/util.cpp | 166 | ||||
-rw-r--r-- | src/util.h | 11 | ||||
-rw-r--r-- | src/xmlgen.cpp | 2 | ||||
-rwxr-xr-x | tmake/lib/solaris-g++/tmake.conf | 2 |
33 files changed, 901 insertions, 714 deletions
@@ -1,7 +1,7 @@ -DOXYGEN Version 1.5.2-20070506 +DOXYGEN Version 1.5.2-20070610 Please read the installation section of the manual (http://www.doxygen.org/install.html) for instructions. -------- -Dimitri van Heesch (06 May 2007) +Dimitri van Heesch (10 June 2007) diff --git a/Makefile.in b/Makefile.in index 6dabd87..55ac74a 100644 --- a/Makefile.in +++ b/Makefile.in @@ -54,26 +54,24 @@ install: doxywizard_install $(INSTTOOL) -m 755 bin/doxygen $(INSTALL)/bin $(INSTTOOL) -m 755 bin/doxytag $(INSTALL)/bin $(INSTTOOL) -d $(INSTALL)/$(MAN1DIR) - cat doc/doxygen.1 | sed -e "s/DATE/$(DATE)/g" -e "s/VERSION/$(VERSION)/g" > $(INSTALL)/$(MAN1DIR)/doxygen.1 ; \ - cat doc/doxytag.1 | sed -e "s/DATE/$(DATE)/g" -e "s/VERSION/$(VERSION)/g" > $(INSTALL)/$(MAN1DIR)/doxytag.1 ; \ - cat doc/doxywizard.1 | sed -e "s/DATE/$(DATE)/g" -e "s/VERSION/$(VERSION)/g" > $(INSTALL)/$(MAN1DIR)/doxywizard.1 ; + cat doc/doxygen.1 | sed -e "s/DATE/$(DATE)/g" -e "s/VERSION/$(VERSION)/g" doxygen.1 + $(INSTTOOL) -m 644 doxygen.1 $(INSTALL)/$(MAN1DIR)/doxygen.1 + rm doxygen.1 + cat doc/doxytag.1 | sed -e "s/DATE/$(DATE)/g" -e "s/VERSION/$(VERSION)/g" doxytag.1 + $(INSTTOOL) -m 644 doxytag.1 $(INSTALL)/$(MAN1DIR)/doxytag.1 + rm doxytag.1 + cat doc/doxywizard.1 | sed -e "s/DATE/$(DATE)/g" -e "s/VERSION/$(VERSION)/g" doxywizard.1 + $(INSTTOOL) -m 644 doxywizard.1 $(INSTALL)/$(MAN1DIR)/doxywizard.1 + rm doxywizard install_docs: $(INSTTOOL) -d $(DOCDIR) $(MAKE) -C examples $(MAKE) -C doc $(MAKE) -C latex - cp latex/doxygen_manual.pdf $(DOCDIR) - #cp -r doc $(DOCDIR) + $(INSTTOOL) -m 644 latex/doxygen_manual.pdf $(DOCDIR) cp -r examples $(DOCDIR) cp -r html $(DOCDIR) - #echo "DOXYGEN = $(INSTALL)" > $(DOCDIR)/doc/Makefile - #echo "DOXYDOCS = .." >> $(DOCDIR)/doc/Makefile - #echo "VERSION = $(VERSION)" >> $(DOCDIR)/doc/Makefile - #echo "PERL = $(PERL)" >> $(DOCDIR)/doc/Makefile - #cat doc/Makefile.in >> $(DOCDIR)/doc/Makefile - #rm -rf $(DOCDIR)/doc - #rm -rf $(DOCDIR)/latex docs: FORCE cd examples ; $(MAKE) @@ -1,4 +1,4 @@ -DOXYGEN Version 1.5.2_20070506 +DOXYGEN Version 1.5.2_20070610 Please read INSTALL for compilation instructions. @@ -17,4 +17,4 @@ to subscribe to the lists or to visit the archives. Enjoy, -Dimitri van Heesch (dimitri@stack.nl) (06 May 2007) +Dimitri van Heesch (dimitri@stack.nl) (10 June 2007) @@ -20,7 +20,7 @@ doxygen_version_minor=5 doxygen_version_revision=2 #NOTE: Setting version_mmn to "NO" will omit mmn info from the package. -doxygen_version_mmn=20070506 +doxygen_version_mmn=20070610 bin_dirs=`echo $PATH | sed -e "s/:/ /g"` @@ -214,10 +214,7 @@ if test -z "$f_platform"; then UNIX_SV:4.2*) f_platform=unixware-g++ ;; - Cygwin:*) - f_platform=win32-g++ - ;; - CYGWIN:*) + Cygwin:*|CYGWIN:*) f_platform=win32-g++ ;; *MiNT:*) diff --git a/doc/Doxyfile b/doc/Doxyfile index ee3eb96..7ea5784 100644 --- a/doc/Doxyfile +++ b/doc/Doxyfile @@ -33,7 +33,7 @@ CASE_SENSE_NAMES = NO IMAGE_PATH = . INPUT = index.doc install.doc starting.doc docblocks.doc lists.doc \ grouping.doc formulas.doc diagrams.doc preprocessing.doc \ - autolink.doc output.doc external.doc faq.doc trouble.doc history.doc features.doc \ + autolink.doc output.doc custcmd.doc external.doc faq.doc trouble.doc history.doc features.doc \ doxygen_usage.doc doxytag_usage.doc \ doxywizard_usage.doc installdox_usage.doc \ config.doc commands.doc htmlcmds.doc xmlcmds.doc language.doc \ diff --git a/doc/config.doc b/doc/config.doc index 16fe662..9eaf7a4 100644 --- a/doc/config.doc +++ b/doc/config.doc @@ -163,6 +163,7 @@ followed by the descriptions of the tags grouped by category. \refitem cfg_man_extension MAN_EXTENSION \refitem cfg_man_links MAN_LINKS \refitem cfg_man_output MAN_OUTPUT +\refitem cfg_max_dot_graph_depth MAX_DOT_GRAPH_DEPTH \refitem cfg_max_initializer_lines MAX_INITIALIZER_LINES \refitem cfg_mscgen_path MSCGEN_PATH \refitem cfg_multiline_cpp_is_brief MULTILINE_CPP_IS_BRIEF @@ -1771,10 +1772,23 @@ TAGFILES = file1=loc1 "file2 = loc2" ... </pre> <dt>\c DOT_GRAPH_MAX_NODES <dd> \addindex DOT_GRAPH_MAX_NODES The \c MAX_DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of - nodes that will be shown in the graph. If the number of nodes in a graph - becomes larger than this value, doxygen will truncate the graph, which is - visualized by representing a node as a red box. Note that doxygen will always - show the root nodes and its direct children regardless of this setting. + nodes that will be shown in the graph. If the number of nodes in a graph + becomes larger than this value, doxygen will truncate the graph, which is + visualized by representing a node as a red box. Note that doxygen if the number + of direct children of the root node in a graph is already larger than + \c MAX_DOT_GRAPH_NOTES then the graph will not be shown at all. Also note + that the size of a graph can be further restricted by \c MAX_DOT_GRAPH_DEPTH. + +\anchor cfg_max_dot_graph_depth +<dt>\c MAX_DOT_GRAPH_DEPTH <dd> + \addindex MAX_DOT_GRAPH_DEPTH + The \c MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the + graphs generated by dot. A depth value of 3 means that only nodes reachable + from the root by following a path via at most 3 edges will be shown. Nodes + that lay further from the root node will be omitted. Note that setting this + option to 1 or 2 may greatly reduce the computation time needed for large + code bases. Also note that the size of a graph can be further restricted by + \c DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction (the default). \anchor cfg_dot_image_format <dt>\c DOT_IMAGE_FORMAT <dd> diff --git a/doc/index.doc b/doc/index.doc index 7dce69d..faed772 100644 --- a/doc/index.doc +++ b/doc/index.doc @@ -75,6 +75,7 @@ The first part forms a user manual: and members in the documentation. <li>Section \ref output shows how to generate the various output formats supported by doxygen. +<li>Section \ref custcmd show how to define and use custom commands in your comments. <li>Section \ref external explains how to let doxygen create links to externally generated documentation. <li>Section \ref faq gives answers to frequently asked questions. <li>Section \ref trouble tells you what to do when you have problems. diff --git a/doc/install.doc b/doc/install.doc index b9ce3e0..3c75386 100644 --- a/doc/install.doc +++ b/doc/install.doc @@ -38,14 +38,17 @@ If you downloaded the source distribution, you need at least the following to build the executable: <ul> <li>The <a href="ftp://prep.ai.mit.edu/pub/gnu/">GNU</a> tools - flex, bison and make + flex, bison and GNU make, and strip \addindex flex \addindex bison \addindex make + \addindex strip <li>In order to generate a Makefile for your platform, you need <a href="http://www.perl.com/">perl</a> \latexonly(see {\tt http://www.perl.com/})\endlatexonly. \addindex perl +<li>The configure script assume the availibility of standard Unix tools such + as sed, date, find, uname, mv, cp, cat, echo, tr, cd, and rm. </ul> To take full advantage of doxygen's features the following additional @@ -56,7 +59,7 @@ tools should be installed. <A HREF="http://www.trolltech.com/products/qt.html">Qt</A> \latexonly(see {\tt http://www.trolltech.com/products/qt.html})\endlatexonly \addindex Qt - version 3.2 or higher. + version 3.3 or higher. This is needed to build the GUI front-end doxywizard. <li>A \f$\mbox{\LaTeX}\f$ distribution: for instance <a href="http://www.tug.org/interest.html#free">teTeX 1.0</a> @@ -70,8 +73,11 @@ tools should be installed. If you compile graphviz yourself, make sure you do include freetype support (which requires the freetype library and header files), otherwise the graphs will not render proper text labels. -<li>The ghostscript interpreter. To be found at +<li>For formulas or if you do not wish to use pdflatex, the ghostscript interpreter + is needed. You can find it at <a href="http://www.ghostscript.com/">www.ghostscript.com</a>. +<li>In order to generate doxygen's own documentation, Python is needed, you + can find it at <a href="http://www.python.org">www.python.org</a>. </ul> Compilation is now done by performing the following steps: @@ -104,7 +110,7 @@ Compilation is now done by performing the following steps: See the <code>PLATFORMS</code> file for a list of possible platform options. - If you have Qt-3.2.x or higher installed and want to build the GUI + If you have Qt-3.3.x installed and want to build the GUI front-end, you should run the configure script with the <code>--with-doxywizard</code> option: @@ -136,13 +142,11 @@ Compilation is now done by performing the following steps: To let doxygen generate the HTML documentation. - \note You will need the stream editor <code>sed</code> for this, - but this should be available on any Unix platform. - The HTML directory of the distribution will now contain the html documentation (just point a HTML browser to the file <code>index.html</code> in the - html directory). + html directory). You will need the <code>python</code> interpreter + for this. <li>Optional: Generate a PDF version of the manual (you will need <code>pdflatex</code>, <code>makeindex</code>, and diff --git a/doc/xmlcmds.doc b/doc/xmlcmds.doc index 415b00e..8a446e2 100644 --- a/doc/xmlcmds.doc +++ b/doc/xmlcmds.doc @@ -39,7 +39,11 @@ Here is the list of tags supported by doxygen: file. Ignored by doxygen at the moment. <li><tt>\<item\></tt> List item. Can only be used inside a <tt>\<list\></tt> context. <li><tt>\<list type="type"\></tt> Starts a list, supported types are <tt>bullet</tt> - or <tt>number</tt>. A list consists of a number of <tt>\<item\></tt> tags. + or <tt>number</tt> and <tt>table</tt>. + A list consists of a number of <tt>\<item\></tt> tags. + A list of type table, is a two column table which can have + a header. +<li><tt>\<listheader\></tt> Starts the header of a list of type "table". <li><tt>\<para\></tt> Identifies a paragraph of text. <li><tt>\<param name="paramName"\></tt> Marks a piece of text as the documentation for parameter "paramName". Similar to @@ -56,6 +60,7 @@ Here is the list of tags supported by doxygen: to "member". Similar to using \ref cmdsa "\\sa" member. <li><tt>\<summary\></tt> Identifies the brief description. Similar to using \ref cmdbrief "\\brief". +<li><tt>\<term\></tt> Part of a <tt>\<list\></tt> command. <li><tt>\<value\></tt> Identifies a property. Ignored by doxygen. </ul> diff --git a/src/classdef.cpp b/src/classdef.cpp index a5bca00..bbfe3e8 100644 --- a/src/classdef.cpp +++ b/src/classdef.cpp @@ -596,7 +596,7 @@ void ClassDef::internalInsertMember(MemberDef *md, m_impl->isAbstract=TRUE; } - ::addClassMemberNameToIndex(md); + //::addClassMemberNameToIndex(md); if (addToAllList && !(Config_getBool("HIDE_FRIEND_COMPOUNDS") && md->isFriend() && @@ -982,6 +982,192 @@ void ClassDef::showUsedFiles(OutputList &ol) } +void ClassDef::writeClassDiagrams(OutputList &ol) +{ + // count direct inheritance relations + int count=0; + BaseClassDef *ibcd; + if (m_impl->inheritedBy) + { + ibcd=m_impl->inheritedBy->first(); + while (ibcd) + { + ClassDef *icd=ibcd->classDef; + if ( icd->isVisibleInHierarchy()) count++; + ibcd=m_impl->inheritedBy->next(); + } + } + if (m_impl->inherits) + { + ibcd=m_impl->inherits->first(); + while (ibcd) + { + ClassDef *icd=ibcd->classDef; + if ( icd->isVisibleInHierarchy()) count++; + ibcd=m_impl->inherits->next(); + } + } + + + bool renderDiagram = FALSE; + if (Config_getBool("HAVE_DOT") && Config_getBool("CLASS_GRAPH")) + // write class diagram using dot + { + DotClassGraph inheritanceGraph(this,DotNode::Inheritance); + if (!inheritanceGraph.isTrivial() && !inheritanceGraph.isTooBig()) + { + ol.pushGeneratorState(); + ol.disable(OutputGenerator::Man); + ol.startDotGraph(); + ol.parseText(theTranslator->trClassDiagram(displayName())); + ol.endDotGraph(inheritanceGraph); + if (Config_getBool("GENERATE_LEGEND")) + { + ol.pushGeneratorState(); + ol.disableAllBut(OutputGenerator::Html); + ol.writeString("<center><font size=\"2\">["); + ol.startHtmlLink(relativePathToRoot(0)+"graph_legend"+Doxygen::htmlFileExtension); + ol.docify(theTranslator->trLegend()); + ol.endHtmlLink(); + ol.writeString("]</font></center>"); + ol.popGeneratorState(); + } + ol.popGeneratorState(); + renderDiagram = TRUE; + } + } + else if (Config_getBool("CLASS_DIAGRAMS") && count>0) + // write class diagram using build-in generator + { + ClassDiagram diagram(this); // create a diagram of this class. + ol.startClassDiagram(); + ol.disable(OutputGenerator::Man); + ol.parseText(theTranslator->trClassDiagram(displayName())); + ol.enable(OutputGenerator::Man); + ol.endClassDiagram(diagram,getOutputFileBase(),displayName()); + renderDiagram = TRUE; + } + + if (Config_getBool("CLASS_DIAGRAMS") && renderDiagram) + { + ol.disableAllBut(OutputGenerator::Man); + } + + if (m_impl->inherits && (count=m_impl->inherits->count())>0) + { + //parseText(ol,theTranslator->trInherits()+" "); + + QCString inheritLine = theTranslator->trInheritsList(m_impl->inherits->count()); + QRegExp marker("@[0-9]+"); + int index=0,newIndex,matchLen; + // now replace all markers in inheritLine with links to the classes + while ((newIndex=marker.match(inheritLine,index,&matchLen))!=-1) + { + ol.parseText(inheritLine.mid(index,newIndex-index)); + bool ok; + uint entryIndex = inheritLine.mid(newIndex+1,matchLen-1).toUInt(&ok); + BaseClassDef *bcd=m_impl->inherits->at(entryIndex); + if (ok && bcd) + { + ClassDef *cd=bcd->classDef; + if (cd->isLinkable()) + { + if (!Config_getString("GENERATE_TAGFILE").isEmpty()) + { + Doxygen::tagFile << " <base"; + if (bcd->prot==Protected) + { + Doxygen::tagFile << " protection=\"protected\""; + } + else if (bcd->prot==Private) + { + Doxygen::tagFile << " protection=\"private\""; + } + if (bcd->virt==Virtual) + { + Doxygen::tagFile << " virtualness=\"virtual\""; + } + Doxygen::tagFile << ">" << convertToXML(cd->name()) << "</base>" << endl; + } + ol.writeObjectLink(cd->getReference(),cd->getOutputFileBase(),0,cd->displayName()+bcd->templSpecifiers); + } + else + { + ol.docify(cd->displayName()); + } + } + else + { + err("Error: invalid marker %d in inherits list!\n",entryIndex); + } + index=newIndex+matchLen; + } + ol.parseText(inheritLine.right(inheritLine.length()-index)); + ol.newParagraph(); + } + + // write subclasses + if (m_impl->inheritedBy && (count=m_impl->inheritedBy->count())>0) + { + QCString inheritLine = theTranslator->trInheritedByList(m_impl->inheritedBy->count()); + QRegExp marker("@[0-9]+"); + int index=0,newIndex,matchLen; + // now replace all markers in inheritLine with links to the classes + while ((newIndex=marker.match(inheritLine,index,&matchLen))!=-1) + { + ol.parseText(inheritLine.mid(index,newIndex-index)); + bool ok; + uint entryIndex = inheritLine.mid(newIndex+1,matchLen-1).toUInt(&ok); + BaseClassDef *bcd=m_impl->inheritedBy->at(entryIndex); + if (ok && bcd) + { + ClassDef *cd=bcd->classDef; + if (cd->isLinkable()) + { + ol.writeObjectLink(cd->getReference(),cd->getOutputFileBase(),0,cd->displayName()); + } + else + { + ol.docify(cd->displayName()); + } + writeInheritanceSpecifier(ol,bcd); + } + index=newIndex+matchLen; + } + ol.parseText(inheritLine.right(inheritLine.length()-index)); + ol.newParagraph(); + } + + if (Config_getBool("CLASS_DIAGRAMS") && renderDiagram) + { + ol.enableAll(); + } + + if (Config_getBool("HAVE_DOT") && Config_getBool("COLLABORATION_GRAPH")) + { + DotClassGraph usageImplGraph(this,DotNode::Collaboration); + if (!usageImplGraph.isTrivial()) + { + ol.pushGeneratorState(); + ol.disable(OutputGenerator::Man); + ol.startDotGraph(); + ol.parseText(theTranslator->trCollaborationDiagram(displayName())); + ol.endDotGraph(usageImplGraph); + if (Config_getBool("GENERATE_LEGEND")) + { + ol.disableAllBut(OutputGenerator::Html); + ol.writeString("<center><font size=\"2\">["); + ol.startHtmlLink(relativePathToRoot(0)+"graph_legend"+Doxygen::htmlFileExtension); + ol.docify(theTranslator->trLegend()); + ol.endHtmlLink(); + ol.writeString("]</font></center>"); + } + ol.popGeneratorState(); + } + } + +} + // write all documentation for this class void ClassDef::writeDocumentation(OutputList &ol) { @@ -1140,182 +1326,7 @@ void ClassDef::writeDocumentation(OutputList &ol) } } - - if (Config_getBool("CLASS_DIAGRAMS")) ol.disableAllBut(OutputGenerator::Man); - - - // write super classes - int count; - if (m_impl->inherits && (count=m_impl->inherits->count())>0) - { - //parseText(ol,theTranslator->trInherits()+" "); - - QCString inheritLine = theTranslator->trInheritsList(m_impl->inherits->count()); - QRegExp marker("@[0-9]+"); - int index=0,newIndex,matchLen; - // now replace all markers in inheritLine with links to the classes - while ((newIndex=marker.match(inheritLine,index,&matchLen))!=-1) - { - ol.parseText(inheritLine.mid(index,newIndex-index)); - bool ok; - uint entryIndex = inheritLine.mid(newIndex+1,matchLen-1).toUInt(&ok); - BaseClassDef *bcd=m_impl->inherits->at(entryIndex); - if (ok && bcd) - { - ClassDef *cd=bcd->classDef; - if (cd->isLinkable()) - { - if (!Config_getString("GENERATE_TAGFILE").isEmpty()) - { - Doxygen::tagFile << " <base"; - if (bcd->prot==Protected) - { - Doxygen::tagFile << " protection=\"protected\""; - } - else if (bcd->prot==Private) - { - Doxygen::tagFile << " protection=\"private\""; - } - if (bcd->virt==Virtual) - { - Doxygen::tagFile << " virtualness=\"virtual\""; - } - Doxygen::tagFile << ">" << convertToXML(cd->name()) << "</base>" << endl; - } - ol.writeObjectLink(cd->getReference(),cd->getOutputFileBase(),0,cd->displayName()+bcd->templSpecifiers); - } - else - { - ol.docify(cd->displayName()); - } - } - else - { - err("Error: invalid marker %d in inherits list!\n",entryIndex); - } - index=newIndex+matchLen; - } - ol.parseText(inheritLine.right(inheritLine.length()-index)); - ol.newParagraph(); - } - - // write subclasses - if (m_impl->inheritedBy && (count=m_impl->inheritedBy->count())>0) - { - QCString inheritLine = theTranslator->trInheritedByList(m_impl->inheritedBy->count()); - QRegExp marker("@[0-9]+"); - int index=0,newIndex,matchLen; - // now replace all markers in inheritLine with links to the classes - while ((newIndex=marker.match(inheritLine,index,&matchLen))!=-1) - { - ol.parseText(inheritLine.mid(index,newIndex-index)); - bool ok; - uint entryIndex = inheritLine.mid(newIndex+1,matchLen-1).toUInt(&ok); - BaseClassDef *bcd=m_impl->inheritedBy->at(entryIndex); - if (ok && bcd) - { - ClassDef *cd=bcd->classDef; - if (cd->isLinkable()) - { - ol.writeObjectLink(cd->getReference(),cd->getOutputFileBase(),0,cd->displayName()); - } - else - { - ol.docify(cd->displayName()); - } - writeInheritanceSpecifier(ol,bcd); - } - index=newIndex+matchLen; - } - ol.parseText(inheritLine.right(inheritLine.length()-index)); - ol.newParagraph(); - } - - if (Config_getBool("CLASS_DIAGRAMS")) ol.enableAll(); - - - count=0; - BaseClassDef *ibcd; - if (m_impl->inheritedBy) - { - ibcd=m_impl->inheritedBy->first(); - while (ibcd) - { - ClassDef *icd=ibcd->classDef; - if ( icd->isVisibleInHierarchy()) count++; - ibcd=m_impl->inheritedBy->next(); - } - } - if (m_impl->inherits) - { - ibcd=m_impl->inherits->first(); - while (ibcd) - { - ClassDef *icd=ibcd->classDef; - if ( icd->isVisibleInHierarchy()) count++; - ibcd=m_impl->inherits->next(); - } - } - - - if (Config_getBool("HAVE_DOT") && Config_getBool("CLASS_GRAPH")) - // write class diagram using dot - { - DotClassGraph inheritanceGraph(this,DotNode::Inheritance); - if (!inheritanceGraph.isTrivial()) - { - ol.pushGeneratorState(); - ol.disable(OutputGenerator::Man); - ol.startDotGraph(); - ol.parseText(theTranslator->trClassDiagram(displayName())); - ol.endDotGraph(inheritanceGraph); - if (Config_getBool("GENERATE_LEGEND")) - { - ol.pushGeneratorState(); - ol.disableAllBut(OutputGenerator::Html); - ol.writeString("<center><font size=\"2\">["); - ol.startHtmlLink(relativePathToRoot(0)+"graph_legend"+Doxygen::htmlFileExtension); - ol.docify(theTranslator->trLegend()); - ol.endHtmlLink(); - ol.writeString("]</font></center>"); - ol.popGeneratorState(); - } - ol.popGeneratorState(); - } - } - else if (Config_getBool("CLASS_DIAGRAMS") && count>0) - // write class diagram using build-in generator - { - ClassDiagram diagram(this); // create a diagram of this class. - ol.startClassDiagram(); - ol.disable(OutputGenerator::Man); - ol.parseText(theTranslator->trClassDiagram(displayName())); - ol.enable(OutputGenerator::Man); - ol.endClassDiagram(diagram,getOutputFileBase(),displayName()); - } - - if (Config_getBool("HAVE_DOT") && Config_getBool("COLLABORATION_GRAPH")) - { - DotClassGraph usageImplGraph(this,DotNode::Collaboration); - if (!usageImplGraph.isTrivial()) - { - ol.pushGeneratorState(); - ol.disable(OutputGenerator::Man); - ol.startDotGraph(); - ol.parseText(theTranslator->trCollaborationDiagram(displayName())); - ol.endDotGraph(usageImplGraph); - if (Config_getBool("GENERATE_LEGEND")) - { - ol.disableAllBut(OutputGenerator::Html); - ol.writeString("<center><font size=\"2\">["); - ol.startHtmlLink(relativePathToRoot(0)+"graph_legend"+Doxygen::htmlFileExtension); - ol.docify(theTranslator->trLegend()); - ol.endHtmlLink(); - ol.writeString("]</font></center>"); - } - ol.popGeneratorState(); - } - } + writeClassDiagrams(ol); // write link to list of all members (HTML only) if (m_impl->allMemberNameInfoSDict && diff --git a/src/classdef.h b/src/classdef.h index 2153def..b03ae52 100644 --- a/src/classdef.h +++ b/src/classdef.h @@ -310,6 +310,7 @@ class ClassDef : public Definition void mergeMembers(); void distributeMemberGroupDocumentation(); void writeDocumentation(OutputList &ol); + void writeClassDiagrams(OutputList &ol); void writeDocumentationForInnerClasses(OutputList &ol); void writeMemberDocumentation(OutputList &ol); void writeMemberPages(OutputList &ol); diff --git a/src/cmdmapper.cpp b/src/cmdmapper.cpp index 352095c..c4469c7 100644 --- a/src/cmdmapper.cpp +++ b/src/cmdmapper.cpp @@ -162,7 +162,8 @@ CommandMap htmlTagMap[] = { "exception", XML_EXCEPTION }, { "include", XML_INCLUDE }, { "item", XML_ITEM }, - { "list", XML_LIST }, + { "list", XML_LIST }, // type="table|bullet|number" + { "listheader", XML_LISTHEADER }, { "para", XML_PARA }, { "param", XML_PARAM }, { "paramref", XML_PARAMREF }, @@ -172,14 +173,15 @@ CommandMap htmlTagMap[] = { "see", XML_SEE }, { "seealso", XML_SEEALSO }, { "summary", XML_SUMMARY }, + { "term", XML_TERM }, { "value", XML_VALUE }, { 0, 0 } }; //---------------------------------------------------------------------------- -Mapper *Mappers::cmdMapper = new Mapper(cmdMap); -Mapper *Mappers::htmlTagMapper = new Mapper(htmlTagMap); +Mapper *Mappers::cmdMapper = new Mapper(cmdMap,TRUE); +Mapper *Mappers::htmlTagMapper = new Mapper(htmlTagMap,FALSE); void Mappers::freeMappers() { diff --git a/src/cmdmapper.h b/src/cmdmapper.h index 586e766..d5a2376 100644 --- a/src/cmdmapper.h +++ b/src/cmdmapper.h @@ -158,16 +158,18 @@ enum HtmlTagType XML_INCLUDE = XML_CmdMask + 5, XML_ITEM = XML_CmdMask + 6, XML_LIST = XML_CmdMask + 7, - XML_PARA = XML_CmdMask + 8, - XML_PARAM = XML_CmdMask + 9, - XML_PARAMREF = XML_CmdMask + 10, - XML_PERMISSION = XML_CmdMask + 11, - XML_REMARKS = XML_CmdMask + 12, - XML_RETURNS = XML_CmdMask + 13, - XML_SEE = XML_CmdMask + 14, - XML_SEEALSO = XML_CmdMask + 15, - XML_SUMMARY = XML_CmdMask + 16, - XML_VALUE = XML_CmdMask + 17 + XML_LISTHEADER = XML_CmdMask + 8, + XML_PARA = XML_CmdMask + 9, + XML_PARAM = XML_CmdMask + 10, + XML_PARAMREF = XML_CmdMask + 11, + XML_PERMISSION = XML_CmdMask + 12, + XML_REMARKS = XML_CmdMask + 13, + XML_RETURNS = XML_CmdMask + 14, + XML_SEE = XML_CmdMask + 15, + XML_SEEALSO = XML_CmdMask + 16, + XML_SUMMARY = XML_CmdMask + 17, + XML_TERM = XML_CmdMask + 18, + XML_VALUE = XML_CmdMask + 19 }; @@ -177,11 +179,12 @@ class Mapper int map(const char *n) { QCString name=n; + if (!m_cs) name=name.lower(); int *result; - return !name.isEmpty() && (result=m_map.find(name.lower())) ? *result: 0; + return !name.isEmpty() && (result=m_map.find(name)) ? *result: 0; } - Mapper(const CommandMap *cm) : m_map(89) + Mapper(const CommandMap *cm,bool caseSensitive) : m_map(89), m_cs(caseSensitive) { m_map.setAutoDelete(TRUE); const CommandMap *p = cm; @@ -193,6 +196,7 @@ class Mapper } private: QDict<int> m_map; + bool m_cs; }; struct Mappers diff --git a/src/commentcnv.l b/src/commentcnv.l index 9b9a946..b12d9d8 100644 --- a/src/commentcnv.l +++ b/src/commentcnv.l @@ -61,6 +61,10 @@ static QCString g_blockName; static int g_lastCommentContext; static bool g_inSpecialComment; +static QCString g_aliasString; +static int g_blockCount; +static int g_lastBlockContext; + static void replaceCommentMarker(const char *s,int len) { const char *p=s; @@ -223,27 +227,11 @@ static QCString handleCondCmdInAliases(const QCString &s) /** copies string \a s with length \a len to the output, while * replacing any alias commands found in the string. */ -static void replaceAliases(const char *s,int len) +static void replaceAliases(const char *s) { - static QRegExp cmd("[@\\\\][a-z_A-Z][a-z_A-Z0-9]*"); - QCString in=s; - int p=0,i,l; - while ((i=cmd.match(in,p,&l))!=-1) - { - copyToOutput(s+p,i-p); - QCString *pValue=Doxygen::aliasDict[in.mid(i+1,l-1)]; - if (pValue) - { - QCString val = handleCondCmdInAliases(*pValue); - copyToOutput(val.data(),val.length()); - } - else - { - copyToOutput(s+i,l); - } - p=i+l; - } - copyToOutput(s+p,len-p); + QCString result = resolveAliasCmd(s); + //printf("replaceAliases(%s)->'%s'\n",s,result.data()); + copyToOutput(result,result.length()); } @@ -274,6 +262,7 @@ void replaceComment(int offset); %x VerbatimCode %x ReadLine %x CondLine +%x ReadAliasArgs %% @@ -300,8 +289,7 @@ void replaceComment(int offset); } g_blockHeadCol=g_col; copyToOutput("/**",3); - //copyToOutput(yytext+i,yyleng-i); - replaceAliases(yytext+i,yyleng-i); + replaceAliases(yytext+i); g_inSpecialComment=TRUE; BEGIN(SComment); } @@ -310,8 +298,7 @@ void replaceComment(int offset); int i=17; //=strlen("//##Documentation"); g_blockHeadCol=g_col; copyToOutput("/**",3); - //copyToOutput(yytext+i,yyleng-i); - replaceAliases(yytext+i,yyleng-i); + replaceAliases(yytext+i); BEGIN(SComment); } <Scan>"//"/.*\n { /* one line C++ comment */ @@ -521,17 +508,37 @@ void replaceComment(int offset); if (*yytext=='\n') g_lineNr++; BEGIN(g_condCtx); } -<CComment,ReadLine>[\\@][a-z_A-Z][a-z_A-Z0-9]* { // expand alias - QCString *pValue=Doxygen::aliasDict[yytext+1]; - if (pValue) - { - QCString val = handleCondCmdInAliases(*pValue); - copyToOutput(val.data(),val.length()); - } - else - { - copyToOutput(yytext,yyleng); - } +<CComment,ReadLine>[\\@][a-z_A-Z][a-z_A-Z0-9]* { // expand alias without arguments + replaceAliases(yytext); + } +<CComment,ReadLine>[\\@][a-z_A-Z][a-z_A-Z0-9]*"{" { // expand alias with arguments + g_lastBlockContext=YY_START; + g_blockCount=1; + g_aliasString=yytext; + BEGIN( ReadAliasArgs ); + } +<ReadAliasArgs>[^{}\n\*]+ { + g_aliasString+=yytext; + } +<ReadAliasArgs>\n { + g_aliasString+=yytext; + g_lineNr++; + } +<ReadAliasArgs>"{" { + g_aliasString+=yytext; + g_blockCount++; + } +<ReadAliasArgs>"}" { + g_aliasString+=yytext; + g_blockCount--; + if (g_blockCount==0) + { + replaceAliases(g_aliasString); + BEGIN( g_lastBlockContext ); + } + } +<ReadAliasArgs>. { + g_aliasString+=yytext; } <ReadLine>. { copyToOutput(yytext,yyleng); diff --git a/src/config.l b/src/config.l index 0fad432..e3faf84 100644 --- a/src/config.l +++ b/src/config.l @@ -1078,12 +1078,13 @@ void Config::check() s=aliasList.first(); while (s) { - QRegExp re("[a-z_A-Z][a-z_A-Z0-9]*[ \t]*="); + QRegExp re1("[a-z_A-Z][a-z_A-Z0-9]*[ \t]*="); // alias without argument + QRegExp re2("[a-z_A-Z][a-z_A-Z0-9]*{[0-9]*}[ \t]*="); // alias with argument QCString alias=s; alias=alias.stripWhiteSpace(); - if (alias.find(re)!=0) + if (alias.find(re1)!=0 && alias.find(re2)!=0) { - config_err("Illegal alias format `%s'. Use \"name=value\"\n", + config_err("Illegal alias format `%s'. Use \"name=value\" or \"name(n)=value\", where n is the number of arguments\n", alias.data()); } s=aliasList.next(); @@ -1250,16 +1251,12 @@ void Config::check() Config_getBool("INLINE_INFO")=FALSE; } -#if 0 - if (Config_getString("RTF_OUTPUT_ENCODING").isEmpty()) - { - Config_getString("RTF_OUTPUT_ENCODING")="ISO-8859-1"; - } - if (Config_getString("LATEX_OUTPUT_ENCODING").isEmpty()) + int &depth = Config_getInt("MAX_DOT_GRAPH_DEPTH"); + if (depth==0) { - Config_getString("LATEX_OUTPUT_ENCODING")="ISO-8859-1"; + depth=1000; } -#endif + // add default words if needed QStrList &annotationFromBrief = Config_getList("ABBREVIATE_BRIEF"); @@ -2072,7 +2069,9 @@ void Config::create() "If the SOURCE_BROWSER tag is set to YES then a list of source files will \n" "be generated. Documented entities will be cross-referenced with these sources. \n" "Note: To get rid of all source code in the generated output, make sure also \n" - "VERBATIM_HEADERS is set to NO. \n", + "VERBATIM_HEADERS is set to NO. If you have enabled CALL_GRAPH or CALLER_GRAPH \n" + "then you must also enable this option. If you don't then doxygen will produce \n" + "a warning and turn it on anyway \n", FALSE ); cb = addBool( @@ -2895,14 +2894,27 @@ void Config::create() "The MAX_DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of \n" "nodes that will be shown in the graph. If the number of nodes in a graph \n" "becomes larger than this value, doxygen will truncate the graph, which is \n" - "visualized by representing a node as a red box. Note that doxygen will always \n" - "show the root nodes and its direct children regardless of this setting. \n", + "visualized by representing a node as a red box. Note that doxygen if the number \n" + "of direct children of the root node in a graph is already larger than \n" + "MAX_DOT_GRAPH_NOTES then the graph will not be shown at all. Also note \n" + "that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. \n", 0,10000, 50 ); ci->addDependency("HAVE_DOT"); + ci = addInt( + "MAX_DOT_GRAPH_DEPTH", + "The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the \n" + "graphs generated by dot. A depth value of 3 means that only nodes reachable \n" + "from the root by following a path via at most 3 edges will be shown. Nodes \n" + "that lay further from the root node will be omitted. Note that setting this \n" + "option to 1 or 2 may greatly reduce the computation time needed for large \n" + "code bases. Also note that the size of a graph can be further restricted by \n" + "DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.\n", + 0,1000,0 + ); + ci->addDependency("HAVE_DOT"); addObsolete("MAX_DOT_GRAPH_WIDTH"); addObsolete("MAX_DOT_GRAPH_HEIGHT"); - addObsolete("MAX_DOT_GRAPH_DEPTH"); cb = addBool( "DOT_TRANSPARENT", "Set the DOT_TRANSPARENT tag to YES to generate images with a transparent \n" diff --git a/src/docparser.cpp b/src/docparser.cpp index da673bf..01d88ae 100644 --- a/src/docparser.cpp +++ b/src/docparser.cpp @@ -536,6 +536,18 @@ static bool insideOL(DocNode *n) //--------------------------------------------------------------------------- +static bool insideTable(DocNode *n) +{ + while (n) + { + if (n->kind()==DocNode::Kind_HtmlTable) return TRUE; + n=n->parent(); + } + return FALSE; +} + +//--------------------------------------------------------------------------- + ///*! Returns TRUE iff node n is a child of a language node */ //static bool insideLang(DocNode *n) //{ @@ -2820,6 +2832,43 @@ int DocHtmlCell::parse() return retval; } +int DocHtmlCell::parseXml() +{ + int retval=RetVal_OK; + g_nodeStack.push(this); + DBG(("DocHtmlCell::parseXml() start\n")); + + // parse one or more paragraphs + bool isFirst=TRUE; + DocPara *par=0; + do + { + par = new DocPara(this); + if (isFirst) { par->markFirst(); isFirst=FALSE; } + m_children.append(par); + retval=par->parse(); + if (retval==TK_HTMLTAG) + { + int tagId=Mappers::htmlTagMapper->map(g_token->name); + if (tagId==XML_ITEM && g_token->endTag) // found </item> tag + { + retval=TK_NEWPARA; // ignore the tag + } + else if (tagId==XML_DESCRIPTION && g_token->endTag) // found </description> tag + { + retval=TK_NEWPARA; // ignore the tag + } + } + } + while (retval==TK_NEWPARA); + if (par) par->markLast(); + + DBG(("DocHtmlCell::parseXml() end\n")); + DocNode *n=g_nodeStack.pop(); + ASSERT(n==this); + return retval; +} + //--------------------------------------------------------------------------- int DocHtmlRow::parse() @@ -2888,6 +2937,68 @@ endrow: return retval; } +int DocHtmlRow::parseXml(bool isHeading) +{ + int retval=RetVal_OK; + g_nodeStack.push(this); + DBG(("DocHtmlRow::parseXml() start\n")); + + bool isFirst=TRUE; + DocHtmlCell *cell=0; + + // get next token + int tok=doctokenizerYYlex(); + // skip whitespace + while (tok==TK_WHITESPACE || tok==TK_NEWPARA) tok=doctokenizerYYlex(); + // should find a html tag now + if (tok==TK_HTMLTAG) + { + int tagId=Mappers::htmlTagMapper->map(g_token->name); + if (tagId==XML_TERM && !g_token->endTag) // found <term> tag + { + } + else if (tagId==XML_DESCRIPTION && !g_token->endTag) // found <description> tag + { + } + else // found some other tag + { + warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: expected <term> or <description> tag but " + "found <%s> instead!",g_token->name.data()); + doctokenizerYYpushBackHtmlTag(g_token->name); + goto endrow; + } + } + else if (tok==0) // premature end of comment + { + warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: unexpected end of comment while looking" + " for a html description title"); + goto endrow; + } + else // token other than html token + { + warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: expected <td> or <th> tag but found %s token instead!", + tokToString(tok)); + goto endrow; + } + + do + { + cell=new DocHtmlCell(this,g_token->attribs,isHeading); + cell->markFirst(isFirst); + isFirst=FALSE; + m_children.append(cell); + retval=cell->parseXml(); + } + while (retval==RetVal_TableCell || retval==RetVal_TableHCell); + if (cell) cell->markLast(TRUE); + +endrow: + DBG(("DocHtmlRow::parseXml() end\n")); + DocNode *n=g_nodeStack.pop(); + ASSERT(n==this); + return retval; +} + //--------------------------------------------------------------------------- int DocHtmlTable::parse() @@ -2958,6 +3069,48 @@ getrow: return retval==RetVal_EndTable ? RetVal_OK : retval; } +int DocHtmlTable::parseXml() +{ + int retval=RetVal_OK; + g_nodeStack.push(this); + DBG(("DocHtmlTable::parseXml() start\n")); + + // get next token + int tok=doctokenizerYYlex(); + // skip whitespace + while (tok==TK_WHITESPACE || tok==TK_NEWPARA) tok=doctokenizerYYlex(); + // should find a html tag now + int tagId=0; + bool isHeader=FALSE; + if (tok==TK_HTMLTAG) + { + tagId=Mappers::htmlTagMapper->map(g_token->name); + if (tagId==XML_ITEM && !g_token->endTag) // found <item> tag + { + retval=RetVal_TableRow; + } + if (tagId==XML_LISTHEADER && !g_token->endTag) // found <listheader> tag + { + retval=RetVal_TableRow; + isHeader=TRUE; + } + } + + // parse one or more rows + while (retval==RetVal_TableRow) + { + DocHtmlRow *tr=new DocHtmlRow(this,g_token->attribs); + m_children.append(tr); + retval=tr->parseXml(isHeader); + isHeader=FALSE; + } + + DBG(("DocHtmlTable::parseXml() end\n")); + DocNode *n=g_nodeStack.pop(); + ASSERT(n==this); + return retval==RetVal_EndTable ? RetVal_OK : retval; +} + uint DocHtmlTable::numCols() const { uint cols=0; @@ -4788,6 +4941,10 @@ int DocPara::handleHtmlStartTag(const QString &tagName,const HtmlAttribList &tag break; case XML_EXAMPLE: case XML_DESCRIPTION: + if (insideTable(this)) + { + retval=RetVal_TableCell; + } break; case XML_C: handleStyleEnter(this,m_children,DocStyleChange::Code,&g_token->attribs); @@ -4836,19 +4993,31 @@ int DocPara::handleHtmlStartTag(const QString &tagName,const HtmlAttribList &tag } break; case XML_ITEM: - if (!insideUL(this) && !insideOL(this)) + case XML_LISTHEADER: + if (insideTable(this)) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: lonely <item> tag found"); + retval=RetVal_TableRow; } - else + else if (insideUL(this) || insideOL(this)) { retval=RetVal_ListItem; } + else + { + warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: lonely <item> tag found"); + } break; case XML_RETURNS: retval = handleSimpleSection(DocSimpleSect::Return,TRUE); g_hasReturnCommand=TRUE; break; + case XML_TERM: + m_children.append(new DocStyleChange(this,g_nodeStack.count(),DocStyleChange::Bold,TRUE)); + if (insideTable(this)) + { + retval=RetVal_TableCell; + } + break; case XML_SEE: // I'm not sure if <see> is the same as <seealso> or if it // should you link a member without producing a section. The @@ -4923,14 +5092,25 @@ int DocPara::handleHtmlStartTag(const QString &tagName,const HtmlAttribList &tag case XML_LIST: { QString type; + findAttribute(tagHtmlAttribs,"type",&type); DocHtmlList::Type listType = DocHtmlList::Unordered; - if (findAttribute(tagHtmlAttribs,"type",&type) && type=="number") + if (type=="number") { listType=DocHtmlList::Ordered; } - DocHtmlList *list = new DocHtmlList(this,tagHtmlAttribs,listType); - m_children.append(list); - retval=list->parseXml(); + if (type=="table") + { + DocHtmlTable *table = new DocHtmlTable(this,tagHtmlAttribs); + m_children.append(table); + retval=table->parseXml(); + } + else + { + HtmlAttribList emptyList; + DocHtmlList *list = new DocHtmlList(this,emptyList,listType); + m_children.append(list); + retval=list->parseXml(); + } } break; case XML_INCLUDE: @@ -5078,6 +5258,9 @@ int DocPara::handleHtmlEndTag(const QString &tagName) // ignore </a> tag (can be part of <a name=...></a> break; + case XML_TERM: + m_children.append(new DocStyleChange(this,g_nodeStack.count(),DocStyleChange::Bold,FALSE)); + break; case XML_SUMMARY: case XML_REMARKS: case XML_PARA: @@ -5094,6 +5277,7 @@ int DocPara::handleHtmlEndTag(const QString &tagName) handleStyleLeave(this,m_children,DocStyleChange::Code,"c"); break; case XML_ITEM: + case XML_LISTHEADER: case XML_INCLUDE: case XML_PERMISSION: case XML_DESCRIPTION: diff --git a/src/docparser.h b/src/docparser.h index 64b382d..bd51317 100644 --- a/src/docparser.h +++ b/src/docparser.h @@ -1140,6 +1140,7 @@ class DocHtmlCell : public CompAccept<DocHtmlCell>, public DocNode void markLast(bool v=TRUE) { m_isLast=v; } const HtmlAttribList &attribs() const { return m_attribs; } int parse(); + int parseXml(); private: DocNode * m_parent; @@ -1179,6 +1180,7 @@ class DocHtmlRow : public CompAccept<DocHtmlRow>, public DocNode void accept(DocVisitor *v) { CompAccept<DocHtmlRow>::accept(this,v); } const HtmlAttribList &attribs() const { return m_attribs; } int parse(); + int parseXml(bool header); private: DocNode * m_parent; @@ -1199,6 +1201,7 @@ class DocHtmlTable : public CompAccept<DocHtmlTable>, public DocNode bool hasCaption() { return m_caption!=0; } const HtmlAttribList &attribs() const { return m_attribs; } int parse(); + int parseXml(); uint numCols() const; void accept(DocVisitor *v); diff --git a/src/dot.cpp b/src/dot.cpp index 808dcca..603fc38 100644 --- a/src/dot.cpp +++ b/src/dot.cpp @@ -91,123 +91,6 @@ static void writeGraphFooter(QTextStream &t) t << "}" << endl; } -#if 0 -/*! converts the rectangles in a server site image map into a client - * site image map. - * \param t the stream to which the result is written. - * \param mapName the name of the map file. - * \param relPath the relative path to the root of the output directory - * (used in case CREATE_SUBDIRS is enabled). - * \param urlOnly if FALSE the url field in the map contains an external - * references followed by a $ and then the URL. - * \returns TRUE if succesful. - */ -static bool convertMapFile(QTextStream &t,const char *mapName, - const QCString relPath, bool urlOnly=FALSE) -{ - QFile f(mapName); - if (!f.open(IO_ReadOnly)) - { - err("Error opening map file %s for inclusion in the docs!\n",mapName); - return FALSE; - } - const int maxLineLen=1024; - char buf[maxLineLen]; - char url[maxLineLen]; - char ref[maxLineLen]; - int x1,y1,x2,y2; - while (!f.atEnd()) - { - bool isRef = FALSE; - int numBytes = f.readLine(buf,maxLineLen); - buf[numBytes-1]='\0'; - //printf("ReadLine `%s'\n",buf); - if (strncmp(buf,"rect",4)==0) - { - // obtain the url and the coordinates in the order used by graphviz-1.5 - sscanf(buf,"rect %s %d,%d %d,%d",url,&x1,&y1,&x2,&y2); - - if ( strcmp(url,"\\ref") == 0 ) - { - isRef = TRUE; - sscanf(buf,"rect %s %s %d,%d %d,%d",ref,url,&x1,&y1,&x2,&y2); - } - - // later versions of graphviz corrected the y coordinate order - // the rule is that y2>=y1, so test and switch if needed - if (y2<y1) - { - int temp=y2; - y2=y1; - y1=temp; - } - // there shouldn't be any need for this for known versions of graphviz - // but it can't do any harm to check that x follows the rules as well - if (x2<x1) - { - int temp=x2; - x2=x1; - x1=temp; - } - if (urlOnly) - { - t << "<area href=\""; - - if ( isRef ) - { - // handle doxygen \ref tag URL reference - QCString *dest; - DocRef *df = new DocRef( (DocNode*) 0, url ); - if (!df->ref().isEmpty()) - { - if ((dest=Doxygen::tagDestinationDict[df->ref()])) t << *dest << "/"; - } - if (!df->file().isEmpty()) t << relPath << df->file() << Doxygen::htmlFileExtension; - if (!df->anchor().isEmpty()) t << "#" << df->anchor(); - } - else - { - t << url; - } - t << "\" shape=\"rect\" coords=\"" - << x1 << "," << y1 << "," << x2 << "," << y2 << "\"" - << " alt=\"\">" << endl; - } - else // name and external reference are separated by a $ - { - char *refPtr = url; - char *urlPtr = strchr(url,'$'); - //printf("url=`%s'\n",url); - if (urlPtr) - { - QCString *dest; - *urlPtr++='\0'; - //printf("refPtr=`%s' urlPtr=`%s'\n",refPtr,urlPtr); - //printf("Found url=%s coords=%d,%d,%d,%d\n",url,x1,y1,x2,y2); - t << "<area "; - if (*refPtr!='\0') - { - t << "doxygen=\"" << refPtr << ":"; - if ((dest=Doxygen::tagDestinationDict[refPtr])) t << *dest << "/"; - t << "\" "; - } - t << "href=\"" << relPath; - if (*refPtr!='\0') - { - if ((dest=Doxygen::tagDestinationDict[refPtr])) t << *dest << "/"; - } - t << urlPtr << "\" shape=\"rect\" coords=\"" - << x1 << "," << y1 << "," << x2 << "," << y2 << "\"" - << " alt=\"\">" << endl; - } - } - } - } - - return TRUE; -} -#endif - /*! converts the rectangles in a client site image map into a stream * \param t the stream to which the result is written. * \param mapName the name of the map file. @@ -348,45 +231,21 @@ static void resetReNumbering() s_newNumber.resize(s_max_newNumber); } -#if 0 -static bool readBoundingBoxDot(const char *fileName,int *width,int *height) -{ - QFile f(fileName); - if (!f.open(IO_ReadOnly)) return FALSE; - const int maxLineLen=1024; - char buf[maxLineLen]; - while (!f.atEnd()) - { - int numBytes = f.readLine(buf,maxLineLen); - buf[numBytes-1]='\0'; - if (strncmp(buf,"\tgraph [bb",10)==0) - { - int x,y; - if (sscanf(buf,"\tgraph [bb= \"%d,%d,%d,%d\"];",&x,&y,width,height)!=4) - { - return FALSE; - } - return TRUE; - } - } - return FALSE; -} -#endif - static bool readBoundingBoxEPS(const char *fileName,int *width,int *height) { + QCString bb("%%PageBoundingBox:"); QFile f(fileName); if (!f.open(IO_ReadOnly)) return FALSE; const int maxLineLen=1024; char buf[maxLineLen]; while (!f.atEnd()) { - int numBytes = f.readLine(buf,maxLineLen); - buf[numBytes-1]='\0'; - if (strncmp(buf,"%%PageBoundingBox: ",15)==0) + int numBytes = f.readLine(buf,maxLineLen-1); // read line + buf[numBytes]='\0'; + if (strncmp(buf,bb.data(),bb.length()-1)==0) // found PageBoundBox string { int x,y; - if (sscanf(buf,"%%%%PageBoundingBox: %d %d %d %d",&x,&y,width,height)!=4) + if (sscanf(buf+bb.length(),"%d %d %d %d",&x,&y,width,height)!=4) { return FALSE; } @@ -396,33 +255,6 @@ static bool readBoundingBoxEPS(const char *fileName,int *width,int *height) return FALSE; } -#if 0 -/*! returns TRUE if class cd is a leaf (i.e. has no visible children) - */ -static bool isLeaf(ClassDef *cd) -{ - BaseClassList *bcl = cd->subClasses(); - if (bcl->count()>0) // class has children, check their visibility - { - BaseClassListIterator bcli(*bcl); - BaseClassDef *bcd; - for ( ; (bcd=bcli.current()); ++bcli ) - { - ClassDef *bClass = bcd->classDef; - //if (bClass->isLinkable() || !isLeaf(bClass)) return FALSE; - - // if class is not a leaf - if (!isLeaf(bClass)) return FALSE; - // or class is not documented in this project - if (!Config_getBool("ALLEXTERNALS") && !bClass->isLinkableInProject()) return FALSE; - // or class is not documented and all ALLEXTERNALS = YES - if (Config_getBool("ALLEXTERNALS") && !bClass->isLinkable()) return FALSE; - } - } - return TRUE; -} -#endif - // since dot silently reproduces the input file when it does not // support the PNG format, we need to check the result. static void checkDotResult(const QCString &imgName) @@ -583,6 +415,7 @@ DotNode::DotNode(int n,const char *lab,const char *tip, const char *url, , m_classDef(cd) , m_visible(FALSE) , m_truncated(Unknown) + , m_distance(1000) { } @@ -672,6 +505,11 @@ void DotNode::deleteNode(DotNodeList &deletedList,SDict<DotNode> *skipNodes) } } +void DotNode::setDistance(int distance) +{ + if (distance<m_distance) m_distance = distance; +} + static QCString convertLabel(const QCString &l) { QCString result; @@ -847,9 +685,15 @@ void DotNode::writeArrow(QTextStream &t, ) { t << " Node"; - if (topDown) t << reNumberNode(cn->number(),reNumber); else t << reNumberNode(m_number,reNumber); + if (topDown) + t << reNumberNode(cn->number(),reNumber); + else + t << reNumberNode(m_number,reNumber); t << " -> Node"; - if (topDown) t << reNumberNode(m_number,reNumber); else t << reNumberNode(cn->number(),reNumber); + if (topDown) + t << reNumberNode(m_number,reNumber); + else + t << reNumberNode(cn->number(),reNumber); t << " ["; if (pointBack) t << "dir=back,"; t << "color=\"" << edgeColorMap[ei->m_color] @@ -864,7 +708,7 @@ void DotNode::writeArrow(QTextStream &t, ) { if (pointBack) - t << ",arrowtail=\"" <<arrowStyle[ei->m_color] << "\""; + t << ",arrowtail=\"" << arrowStyle[ei->m_color] << "\""; else t << ",arrowhead=\"" << arrowStyle[ei->m_color] << "\""; } @@ -1445,7 +1289,7 @@ DotGfxHierarchyTable::~DotGfxHierarchyTable() int DotClassGraph::m_curNodeNumber = 0; void DotClassGraph::addClass(ClassDef *cd,DotNode *n,int prot, - const char *label,const char *usedName,const char *templSpec,bool base) + const char *label,const char *usedName,const char *templSpec,bool base,int distance) { if (Config_getBool("HIDE_UNDOC_CLASSES") && !cd->isLinkable()) return; @@ -1478,6 +1322,7 @@ void DotClassGraph::addClass(ClassDef *cd,DotNode *n,int prot, bn->addChild(n,prot,edgeStyle,label); n->addParent(bn); } + bn->setDistance(distance); //printf(" add exiting node %s of %s\n",bn->m_label.data(),n->m_label.data()); } else // new class @@ -1507,11 +1352,12 @@ void DotClassGraph::addClass(ClassDef *cd,DotNode *n,int prot, bn->addChild(n,prot,edgeStyle,label); n->addParent(bn); } + bn->setDistance(distance); m_usedNodes->insert(className,bn); //printf(" add new child node `%s' to %s hidden=%d url=%s\n", // className.data(),n->m_label.data(),cd->isHidden(),tmp_url.data()); - buildGraph(cd,bn,base); + buildGraph(cd,bn,base,distance+1); } } @@ -1557,10 +1403,13 @@ void DotClassGraph::determineVisibleNodes(QList<DotNode> &queue, { while (queue.count()>0 && maxNodes>0) { + static int maxDistance = Config_getInt("MAX_DOT_GRAPH_DEPTH"); DotNode *n = queue.take(0); - //printf("*** Processing node %p queue=%d maxNodes=%d m_children=%p m_parents=%p\n", - // n,queue.count(),maxNodes,n->m_children,n->m_parents); - if (!n->isVisible()) // not yet processed + //printf("*** Processing node %p queue=%d maxNodes=%d m_children=%p " + // "m_parents=%p distance=%d maxDistance=%d\n", + // n,queue.count(),maxNodes,n->m_children,n->m_parents,n->distance(), + // maxDistance); + if (!n->isVisible() && n->distance()<maxDistance) // not yet processed { //printf(" Marked as visible!\n"); n->markAsVisible(); @@ -1589,7 +1438,7 @@ void DotClassGraph::determineVisibleNodes(QList<DotNode> &queue, } } -void DotClassGraph::buildGraph(ClassDef *cd,DotNode *n,bool base) +void DotClassGraph::buildGraph(ClassDef *cd,DotNode *n,bool base,int distance) { //printf("DocClassGraph::buildGraph(%s,distance=%d,base=%d)\n", // cd->name().data(),distance,base); @@ -1607,7 +1456,7 @@ void DotClassGraph::buildGraph(ClassDef *cd,DotNode *n,bool base) //printf("-------- inheritance relation %s->%s templ=`%s'\n", // cd->name().data(),bcd->classDef->name().data(),bcd->templSpecifiers.data()); addClass(bcd->classDef,n,bcd->prot,0,bcd->usedName, - bcd->templSpecifiers,base); + bcd->templSpecifiers,base,distance); } } } @@ -1642,14 +1491,15 @@ void DotClassGraph::buildGraph(ClassDef *cd,DotNode *n,bool base) } } addClass(ucd->classDef,n,EdgeInfo::Purple,label,0, - ucd->templSpecifiers,base); + ucd->templSpecifiers,base,distance); } } } // ---- Add template instantiation relations - if (Config_getBool("TEMPLATE_RELATIONS")) + static bool templateRelations = Config_getBool("TEMPLATE_RELATIONS"); + if (templateRelations) { if (base) // template relations for base classes { @@ -1663,7 +1513,7 @@ void DotClassGraph::buildGraph(ClassDef *cd,DotNode *n,bool base) if (templInstance==cd) { addClass(templMaster,n,EdgeInfo::Orange,cli.currentKey(),0, - 0,TRUE); + 0,TRUE,distance); } } } @@ -1678,7 +1528,7 @@ void DotClassGraph::buildGraph(ClassDef *cd,DotNode *n,bool base) for (;(templInstance=cli.current());++cli) { addClass(templInstance,n,EdgeInfo::Orange,cli.currentKey(),0, - 0,FALSE); + 0,FALSE,distance); } } } @@ -1703,23 +1553,25 @@ DotClassGraph::DotClassGraph(ClassDef *cd,DotNode::GraphType t) TRUE, // is a root node cd ); + m_startNode->setDistance(0); m_usedNodes = new QDict<DotNode>(1009); m_usedNodes->insert(className,m_startNode); //printf("Root node %s\n",cd->name().data()); //if (m_recDepth>0) //{ - buildGraph(cd,m_startNode,TRUE); - if (t==DotNode::Inheritance) buildGraph(cd,m_startNode,FALSE); + buildGraph(cd,m_startNode,TRUE,1); + if (t==DotNode::Inheritance) buildGraph(cd,m_startNode,FALSE,1); //} - int maxNodes = Config_getInt("DOT_GRAPH_MAX_NODES"); - int directChildNodes = 1; - if (m_startNode->m_children!=0) - directChildNodes+=m_startNode->m_children->count(); - if (t==DotNode::Inheritance && m_startNode->m_parents!=0) - directChildNodes+=m_startNode->m_parents->count(); - if (directChildNodes>maxNodes) maxNodes=directChildNodes; + static int nodes = Config_getInt("DOT_GRAPH_MAX_NODES"); + int maxNodes = nodes; + //int directChildNodes = 1; + //if (m_startNode->m_children!=0) + // directChildNodes+=m_startNode->m_children->count(); + //if (t==DotNode::Inheritance && m_startNode->m_parents!=0) + // directChildNodes+=m_startNode->m_parents->count(); + //if (directChildNodes>maxNodes) maxNodes=directChildNodes; QList<DotNode> openNodeQueue; openNodeQueue.append(m_startNode); determineVisibleNodes(openNodeQueue,maxNodes,t==DotNode::Inheritance); @@ -1738,65 +1590,23 @@ bool DotClassGraph::isTrivial() const return m_startNode->m_children==0; } -DotClassGraph::~DotClassGraph() +bool DotClassGraph::isTooBig() const { - deleteNodes(m_startNode); - delete m_usedNodes; + static int maxNodes = Config_getInt("DOT_GRAPH_MAX_NODES"); + int numNodes = 0; + numNodes+= m_startNode->m_children ? m_startNode->m_children->count() : 0; + if (m_graphType==DotNode::Inheritance) + { + numNodes+= m_startNode->m_parents ? m_startNode->m_parents->count() : 0; + } + return numNodes>=maxNodes; } -#if 0 -void writeDotGraph(DotNode *root, - DotNode::GraphType gt, - GraphOutputFormat format, - const QCString &baseName, - bool lrRank, - bool renderParents, - int distance, - bool backArrows, - bool reNumber - ) +DotClassGraph::~DotClassGraph() { - // generate the graph description for dot - //printf("writeDotGraph(%s,%d,lrRank=%d)\n",baseName.data(),backArrows,lrRank); - QFile f; - f.setName(baseName+".dot"); - if (f.open(IO_WriteOnly)) - { - QTextStream t(&f); - writeGraphHeader(t); - if (lrRank) - { - t << " rankdir=LR;" << endl; - } - root->clearWriteFlag(); - root->write(t,gt,format,gt!=DotNode::CallGraph,TRUE,distance,backArrows,reNumber); - if (renderParents && root->m_parents) - { - //printf("rendering parents!\n"); - QListIterator<DotNode> dnli(*root->m_parents); - DotNode *pn; - for (dnli.toFirst();(pn=dnli.current());++dnli) - { - if (pn->m_distance<=distance) - { - root->writeArrow(t, - gt, - format, - pn, - pn->m_edgeInfo->at(pn->m_children->findRef(root)), - FALSE, - backArrows, - reNumber - ); - } - pn->write(t,gt,format,TRUE,FALSE,distance,backArrows,reNumber); - } - } - writeGraphFooter(t); - f.close(); - } + deleteNodes(m_startNode); + delete m_usedNodes; } -#endif /*! Computes a 16 byte md5 checksum for a given dot graph. * The md5 checksum is returned as a 32 character ASCII string. @@ -1818,10 +1628,16 @@ QCString computeMd5Signature(DotNode *root, writeGraphHeader(md5stream); if (lrRank) { - md5stream << "rankdir=LR;" << endl; + md5stream << " rankdir=LR;" << endl; } root->clearWriteFlag(); - root->write(md5stream,gt,format,gt!=DotNode::CallGraph,TRUE,backArrows,reNumber); + root->write(md5stream, + gt, + format, + gt!=DotNode::CallGraph && gt!=DotNode::Dependency, + TRUE, + backArrows, + reNumber); if (renderParents && root->m_parents) { QListIterator<DotNode> dnli(*root->m_parents); @@ -1892,95 +1708,6 @@ static bool updateDotGraph(DotNode *root, return FALSE; } -#if 0 -static bool findMaximalDotGraph(DotNode *root, - int maxDist, - const QCString &baseName, - QDir &thisDir, - DotNode::GraphType gt, - GraphOutputFormat format, - bool lrRank /*=FALSE*/, - bool renderParents /*=FALSE*/, - bool backArrows /*=TRUE*/ - ) -{ - bool reNumber=TRUE; - int minDistance=1; // min distance that shows only direct children. - int curDistance; //=QMIN(2,maxDist); // current distance to try - int maxDistance=maxDist; // max distance that show whole graph - int width=0; - int height=0; - int maxDotGraphWidth = Config_getInt("MAX_DOT_GRAPH_WIDTH"); - int maxDotGraphHeight = Config_getInt("MAX_DOT_GRAPH_HEIGHT"); - int lastFit=minDistance; - - // binary search for the maximal inheritance depth that fits in a reasonable - // sized image (dimensions: Config_getInt("MAX_DOT_GRAPH_WIDTH"), Config_getInt("MAX_DOT_GRAPH_HEIGHT")) - while (minDistance<=maxDistance) - { - curDistance = (minDistance+maxDistance)/2; - - writeDotGraph(root,gt,format,baseName,lrRank,renderParents, - curDistance,backArrows,reNumber); - - // create annotated dot file - DotRunner dotRun(baseName+".dot"); - dotRun.addJob("dot",baseName+"_tmp.dot"); - if (!dotRun.run()) - { - return FALSE; - } - - // extract bounding box from the result - readBoundingBoxDot(baseName+"_tmp.dot",&width,&height); - width = width *96/72; // 96 pixels/inch, 72 points/inch - height = height*96/72; // 96 pixels/inch, 72 points/inch - //printf("Found bounding box (%d,%d) max (%d,%d)\n",width,height, - // Config_getInt("MAX_DOT_GRAPH_WIDTH"),Config_getInt("MAX_DOT_GRAPH_HEIGHT")); - - // remove temporary dot file - thisDir.remove(baseName+"_tmp.dot"); - - bool graphFits=(width<maxDotGraphWidth && height<maxDotGraphHeight); - if (graphFits) // graph is small enough - { - lastFit=curDistance; - minDistance=curDistance+1; - //printf("Image fits [%d-%d]\n",minDistance,maxDistance); - } - else // graph does not fit anymore with curDistance - { - //printf("Image does not fit [%d-%d]\n",minDistance,maxDistance); - maxDistance=curDistance-1; - } - } - //printf("lastFit=%d\n",lastFit); - - bool hasLRRank = (lrRank || - (minDistance==1 && - width>Config_getInt("MAX_DOT_GRAPH_WIDTH") && - !Config_getBool("UML_LOOK") - ) - ); - - writeDotGraph(root, - gt, - format, - baseName, - hasLRRank, - renderParents, - lastFit, - backArrows, - reNumber - ); - if (reNumber) - { - resetReNumbering(); - } - return TRUE; -} -#endif - QCString DotClassGraph::diskName() const { QCString result=m_diskName.copy(); @@ -2174,7 +1901,7 @@ void DotClassGraph::writeDEF(QTextStream &t) int DotInclDepGraph::m_curNodeNumber = 0; -void DotInclDepGraph::buildGraph(DotNode *n,FileDef *fd) +void DotInclDepGraph::buildGraph(DotNode *n,FileDef *fd,int distance) { QList<IncludeInfo> *includeFiles = m_inverse ? fd->includedByFileList() : fd->includeFileList(); @@ -2207,6 +1934,7 @@ void DotInclDepGraph::buildGraph(DotNode *n,FileDef *fd) { n->addChild(bn,0,0,0); bn->addParent(n); + bn->setDistance(distance); } else { @@ -2214,17 +1942,19 @@ void DotInclDepGraph::buildGraph(DotNode *n,FileDef *fd) if (bfd) tmp_url=doc || src ? bfd->getReference()+"$"+url : QCString(); QCString tooltip = fd->briefDescriptionAsTooltip(); bn = new DotNode( - m_curNodeNumber++, - ii->includeName, - tooltip, - tmp_url, - 0 //distance + m_curNodeNumber++, // n + ii->includeName, // label + tooltip, // tip + tmp_url, // url + FALSE, // rootNode + 0 // cd ); n->addChild(bn,0,0,0); bn->addParent(n); m_usedNodes->insert(in,bn); + bn->setDistance(distance); - if (bfd) buildGraph(bn,bfd); + if (bfd) buildGraph(bn,bfd,distance+1); } } } @@ -2235,8 +1965,9 @@ void DotInclDepGraph::determineVisibleNodes(QList<DotNode> &queue, int &maxNodes { while (queue.count()>0 && maxNodes>0) { + static int maxDistance = Config_getInt("MAX_DOT_GRAPH_DEPTH"); DotNode *n = queue.take(0); - if (!n->isVisible()) // not yet processed + if (!n->isVisible() && n->distance()<maxDistance) // not yet processed { n->markAsVisible(); maxNodes--; @@ -2293,15 +2024,17 @@ DotInclDepGraph::DotInclDepGraph(FileDef *fd,bool inverse) tmp_url.data(), TRUE // root node ); + m_startNode->setDistance(0); m_usedNodes = new QDict<DotNode>(1009); m_usedNodes->insert(fd->absFilePath(),m_startNode); - buildGraph(m_startNode,fd); - - int maxNodes = Config_getInt("DOT_GRAPH_MAX_NODES"); - int directChildNodes = 1; - if (m_startNode->m_children!=0) - directChildNodes+=m_startNode->m_children->count(); - if (directChildNodes>maxNodes) maxNodes=directChildNodes; + buildGraph(m_startNode,fd,1); + + static int nodes = Config_getInt("DOT_GRAPH_MAX_NODES"); + int maxNodes = nodes; + //int directChildNodes = 1; + //if (m_startNode->m_children!=0) + // directChildNodes+=m_startNode->m_children->count(); + //if (directChildNodes>maxNodes) maxNodes=directChildNodes; QList<DotNode> openNodeQueue; openNodeQueue.append(m_startNode); determineVisibleNodes(openNodeQueue,maxNodes); @@ -2351,10 +2084,10 @@ QCString DotInclDepGraph::writeGraph(QTextStream &out, QCString imgExt = Config_getEnum("DOT_IMAGE_FORMAT"); if (updateDotGraph(m_startNode, - DotNode::CallGraph, + DotNode::Dependency, baseName, format, - TRUE, // lrRank + FALSE, // lrRank FALSE, // renderParents m_inverse // backArrows ) @@ -2450,6 +2183,13 @@ bool DotInclDepGraph::isTrivial() const return m_startNode->m_children==0; } +bool DotInclDepGraph::isTooBig() const +{ + static int maxNodes = Config_getInt("DOT_GRAPH_MAX_NODES"); + int numNodes = m_startNode->m_children ? m_startNode->m_children->count() : 0; + return numNodes>=maxNodes; +} + void DotInclDepGraph::writeXML(QTextStream &t) { QDictIterator<DotNode> dni(*m_usedNodes); @@ -2593,11 +2333,12 @@ DotCallGraph::DotCallGraph(MemberDef *md,bool inverse) m_usedNodes->insert(uniqueId,m_startNode); buildGraph(m_startNode,md); - int maxNodes = Config_getInt("DOT_GRAPH_MAX_NODES"); - int directChildNodes = 1; - if (m_startNode->m_children!=0) - directChildNodes+=m_startNode->m_children->count(); - if (directChildNodes>maxNodes) maxNodes=directChildNodes; + static int nodes = Config_getInt("DOT_GRAPH_MAX_NODES"); + int maxNodes = nodes; + //int directChildNodes = 1; + //if (m_startNode->m_children!=0) + // directChildNodes+=m_startNode->m_children->count(); + //if (directChildNodes>maxNodes) maxNodes=directChildNodes; QList<DotNode> openNodeQueue; openNodeQueue.append(m_startNode); determineVisibleNodes(openNodeQueue,maxNodes); @@ -2730,6 +2471,13 @@ bool DotCallGraph::isTrivial() const return m_startNode->m_children==0; } +bool DotCallGraph::isTooBig() const +{ + static int maxNodes = Config_getInt("DOT_GRAPH_MAX_NODES"); + int numNodes = m_startNode->m_children ? m_startNode->m_children->count() : 0; + return numNodes>=maxNodes; +} + //------------------------------------------------------------- DotDirDeps::DotDirDeps(DirDef *dir) : m_dir(dir) @@ -3433,5 +3181,5 @@ void DotGroupCollaboration::writeGraphHeader(QTextStream &t) t << " edge [fontname=\"FreeSans.ttf\",fontsize=8," "labelfontname=\"FreeSans.ttf\",labelfontsize=8];\n"; t << " node [fontname=\"FreeSans.ttf\",fontsize=10,shape=record];\n"; - t << "rankdir=LR;\n"; + t << " rankdir=LR;\n"; } @@ -82,6 +82,7 @@ class DotNode int number() const { return m_number; } bool isVisible() const { return m_visible; } TruncState isTruncated() const { return m_truncated; } + int distance() const { return m_distance; } private: void colorConnectedNodes(int curColor); @@ -89,6 +90,7 @@ class DotNode bool hasNonReachableChildren, bool reNumber=FALSE); void writeArrow(QTextStream &t,GraphType gt,GraphOutputFormat f,DotNode *cn, EdgeInfo *ei,bool topDown, bool pointBack=TRUE, bool reNumber=FALSE); + void setDistance(int distance); const DotNode *findDocNode() const; // only works for acyclic graphs! void markAsVisible(bool b=TRUE) { m_visible=b; } void markAsTruncated(bool b=TRUE) { m_truncated=b ? Truncated : Untruncated; } @@ -106,6 +108,7 @@ class DotNode ClassDef * m_classDef; //!< class representing this node (can be 0) bool m_visible; //!< is the node visible in the output TruncState m_truncated; //!< does the node have non-visible children/parents + int m_distance; //!< shortest path to the root node friend class DotGfxHierarchyTable; friend class DotClassGraph; @@ -155,6 +158,7 @@ class DotClassGraph DotClassGraph(ClassDef *cd,DotNode::GraphType t); ~DotClassGraph(); bool isTrivial() const; + bool isTooBig() const; QCString writeGraph(QTextStream &t,GraphOutputFormat f,const char *path, const char *relPath, bool TBRank=TRUE,bool imageMap=TRUE); @@ -163,12 +167,12 @@ class DotClassGraph QCString diskName() const; private: - void buildGraph(ClassDef *cd,DotNode *n,bool base); + void buildGraph(ClassDef *cd,DotNode *n,bool base,int distance); void determineVisibleNodes(QList<DotNode> &queue,int &maxNodes,bool includeParents); void determineTruncatedNodes(QList<DotNode> &queue,bool includeParents); void addClass(ClassDef *cd,DotNode *n,int prot,const char *label, const char *usedName,const char *templSpec, - bool base); + bool base,int distance); DotNode * m_startNode; QDict<DotNode> * m_usedNodes; @@ -187,11 +191,12 @@ class DotInclDepGraph const char *relPath, bool writeImageMap=TRUE); bool isTrivial() const; + bool isTooBig() const; QCString diskName() const; void writeXML(QTextStream &t); private: - void buildGraph(DotNode *n,FileDef *fd); + void buildGraph(DotNode *n,FileDef *fd,int distance); void determineVisibleNodes(QList<DotNode> &queue,int &maxNodes); void determineTruncatedNodes(QList<DotNode> &queue); @@ -213,6 +218,7 @@ class DotCallGraph const char *path,const char *relPath,bool writeImageMap=TRUE); void buildGraph(DotNode *n,MemberDef *md); bool isTrivial() const; + bool isTooBig() const; void determineVisibleNodes(QList<DotNode> &queue, int &maxNodes); void determineTruncatedNodes(QList<DotNode> &queue); diff --git a/src/doxygen.cpp b/src/doxygen.cpp index 12d0004..3042aa0 100644 --- a/src/doxygen.cpp +++ b/src/doxygen.cpp @@ -6397,7 +6397,7 @@ static void addEnumValuesToEnums(EntryNav *rootNav) // must create them here e->loadEntry(g_storage); MemberDef *fmd = addVariableToFile(e,MemberDef::EnumValue, - md->getOuterScope() ? md->getOuterScope()->name() : "", + md->getOuterScope() ? md->getOuterScope()->name() : QCString(), e->name(),TRUE,0); md->insertEnumField(fmd); fmd->setEnumScope(md); @@ -6659,6 +6659,43 @@ static void findDocumentedEnumValues() findDEV(*Doxygen::functionNameSDict); } +//---------------------------------------------------------------------- + +static void addMembersToIndex() +{ + MemberName *mn; + MemberNameSDict::Iterator mnli(*Doxygen::memberNameSDict); + // for each member name + for (mnli.toFirst();(mn=mnli.current());++mnli) + { + MemberDef *md; + MemberNameIterator mni(*mn); + // for each member definition + for (mni.toFirst();(md=mni.current());++mni) + { + addClassMemberNameToIndex(md); + } + } + MemberNameSDict::Iterator fnli(*Doxygen::functionNameSDict); + // for each member name + for (fnli.toFirst();(mn=fnli.current());++fnli) + { + MemberDef *md; + MemberNameIterator mni(*mn); + // for each member definition + for (mni.toFirst();(md=mni.current());++mni) + { + if (md->getNamespaceDef()) + { + addNamespaceMemberNameToIndex(md); + } + else + { + addFileMemberNameToIndex(md); + } + } + } +} //---------------------------------------------------------------------- // computes the relation between all members. For each member `m' @@ -8560,49 +8597,13 @@ void readFormulaRepository() //---------------------------------------------------------------------------- -static QDict<void> aliasesProcessed; - -static QCString expandAliasesRec(const QCString s) -{ - QCString result; - static QRegExp cmdPat("[\\\\@][a-z_A-Z][a-z_A-Z0-9]*"); - QCString value=s; - int i,p=0,l; - while ((i=cmdPat.match(value,p,&l))!=-1) - { - result+=value.mid(p,i-p); - QCString cmd=value.mid(i+1,l-1); - //printf("Found command '%s'\n",cmd.data()); - QCString *aliasText=Doxygen::aliasDict.find(cmd); - if (aliasesProcessed.find(cmd)==0 && aliasText) // expand the alias - { - aliasesProcessed.insert(cmd,(void *)0x8); - result+=expandAliasesRec(*aliasText); - aliasesProcessed.remove(cmd); - } - else // command is not an alias - { - result+=value.mid(i,l); - } - p=i+l; - } - result+=value.right(value.length()-p); - - //printf("expandAliases '%s'->'%s'\n",s.data(),result.data()); - return result; -} - static void expandAliases() { QDictIterator<QCString> adi(Doxygen::aliasDict); QCString *s; for (adi.toFirst();(s=adi.current());++adi) { - aliasesProcessed.clear(); - // avoid expanding this command recursively - aliasesProcessed.insert(adi.currentKey(),(void *)0x8); - // expand embedded commands - *s = expandAliasesRec(*s); + *s = expandAlias(adi.currentKey(),*s); } } @@ -8678,7 +8679,6 @@ void readAliases() } expandAliases(); escapeAliases(); - aliasesProcessed.clear(); } //---------------------------------------------------------------------------- @@ -9880,6 +9880,7 @@ void generateOutput() writeGroupIndex(*outputList); msg("Generating class documentation...\n"); + addMembersToIndex(); generateClassDocs(); if (Config_getBool("HAVE_DOT") && Config_getBool("GRAPHICAL_HIERARCHY")) @@ -9979,7 +9980,7 @@ void generateOutput() QDir::setCurrent(Config_getString("HTML_OUTPUT")); if (portable_system(Config_getString("HHC_LOCATION"), "index.hhp", FALSE)) { - err("Error: failed to run html help compiler on index.hhp"); + err("Error: failed to run html help compiler on index.hhp\n"); } QDir::setCurrent(oldDir); } diff --git a/src/filedef.cpp b/src/filedef.cpp index ecbb102..45b7ea6 100644 --- a/src/filedef.cpp +++ b/src/filedef.cpp @@ -391,7 +391,7 @@ void FileDef::writeDocumentation(OutputList &ol) { //printf("Graph for file %s\n",name().data()); DotInclDepGraph incDepGraph(this,FALSE); - if (!incDepGraph.isTrivial()) + if (!incDepGraph.isTrivial() && !incDepGraph.isTooBig()) { ol.startTextBlock(); ol.disable(OutputGenerator::Man); @@ -409,7 +409,7 @@ void FileDef::writeDocumentation(OutputList &ol) { //printf("Graph for file %s\n",name().data()); DotInclDepGraph incDepGraph(this,TRUE); - if (!incDepGraph.isTrivial()) + if (!incDepGraph.isTrivial() && !incDepGraph.isTooBig()) { ol.startTextBlock(); ol.disable(OutputGenerator::Man); @@ -723,7 +723,7 @@ void FileDef::insertMember(MemberDef *md) m_memberLists.append(allMemberList); } allMemberList->append(md); - ::addFileMemberNameToIndex(md); + //::addFileMemberNameToIndex(md); switch (md->memberType()) { case MemberDef::Variable: diff --git a/src/htmldocvisitor.cpp b/src/htmldocvisitor.cpp index 2b8d88d..58f06c1 100644 --- a/src/htmldocvisitor.cpp +++ b/src/htmldocvisitor.cpp @@ -577,18 +577,26 @@ void HtmlDocVisitor::visitPre(DocHtmlList *s) { if (m_hide) return; if (s->type()==DocHtmlList::Ordered) + { m_t << "<ol" << htmlAttribsToString(s->attribs()) << ">\n"; + } else + { m_t << "<ul" << htmlAttribsToString(s->attribs()) << ">\n"; + } } void HtmlDocVisitor::visitPost(DocHtmlList *s) { if (m_hide) return; if (s->type()==DocHtmlList::Ordered) + { m_t << "</ol>"; - else + } + else + { m_t << "</ul>"; + } if (!s->isPreformatted()) m_t << "\n"; } diff --git a/src/htmlgen.cpp b/src/htmlgen.cpp index 3dbec0e..d923186 100644 --- a/src/htmlgen.cpp +++ b/src/htmlgen.cpp @@ -873,7 +873,7 @@ void HtmlGenerator::writeCodeLink(const char *ref,const char *f, if (f) t << f << Doxygen::htmlFileExtension; if (anchor) t << "#" << anchor; t << "\""; - if (tooltip) t << " title=\"" << tooltip << "\""; + if (tooltip) t << " title=\"" << convertToXML(tooltip) << "\""; t << ">"; docify(name); t << "</a>"; diff --git a/src/index.cpp b/src/index.cpp index dc8cdd5..c745659 100644 --- a/src/index.cpp +++ b/src/index.cpp @@ -1667,7 +1667,8 @@ void initClassMemberIndices() void addClassMemberNameToIndex(MemberDef *md) { static bool hideFriendCompounds = Config_getBool("HIDE_FRIEND_COMPOUNDS"); - ClassDef *cd; + ClassDef *cd=0; + if (md->isLinkableInProject() && (cd=md->getClassDef()) && cd->isLinkableInProject() && diff --git a/src/latexgen.cpp b/src/latexgen.cpp index a64ad22..ab06be0 100644 --- a/src/latexgen.cpp +++ b/src/latexgen.cpp @@ -237,21 +237,22 @@ static void writeDefaultHeaderPart1(QTextStream &t) } if (Config_getBool("PDF_HYPERLINKS")) { - t << "\\ifx\\pdfoutput\\undefined" << endl - << "\\usepackage[ps2pdf," << endl + t << "\\usepackage{ifpdf}" << endl + << "\\ifpdf" << endl + << "\\usepackage[pdftex," << endl << " pagebackref=true," << endl << " colorlinks=true," << endl << " linkcolor=blue," << endl << " unicode" << endl << " ]{hyperref}" << endl - << "\\usepackage{pspicture}" << endl << "\\else" << endl - << "\\usepackage[pdftex," << endl + << "\\usepackage[ps2pdf," << endl << " pagebackref=true," << endl << " colorlinks=true," << endl << " linkcolor=blue," << endl << " unicode" << endl << " ]{hyperref}" << endl + << "\\usepackage{pspicture}" << endl << "\\fi" << endl; } // Try to get the command for switching on the language diff --git a/src/memberdef.cpp b/src/memberdef.cpp index d00516b..dffbb82 100644 --- a/src/memberdef.cpp +++ b/src/memberdef.cpp @@ -772,10 +772,15 @@ bool MemberDef::isLinkableInProject() const static bool extractStatic = Config_getBool("EXTRACT_STATIC"); makeResident(); - if (isHidden()) return FALSE; //printf("MemberDef::isLinkableInProject(name=%s)\n",name().data()); + if (isHidden()) + { + //printf("is hidden\n"); + return FALSE; + } if (m_impl->templateMaster) { + //printf("has template master\n"); return m_impl->templateMaster->isLinkableInProject(); } if (name().isEmpty() || name().at(0)=='@') @@ -2157,7 +2162,7 @@ void MemberDef::writeDocumentation(MemberList *ml,OutputList &ol, ) { DotCallGraph callGraph(this,FALSE); - if (!callGraph.isTrivial()) + if (!callGraph.isTrivial() && !callGraph.isTooBig()) { msg("Generating call graph for function %s\n",qualifiedName().data()); ol.disable(OutputGenerator::Man); @@ -2172,8 +2177,8 @@ void MemberDef::writeDocumentation(MemberList *ml,OutputList &ol, && isFunction() && Config_getBool("HAVE_DOT") ) { - DotCallGraph callerGraph(this, true); - if (!callerGraph.isTrivial()) + DotCallGraph callerGraph(this, TRUE); + if (!callerGraph.isTrivial() && !callerGraph.isTooBig()) { msg("Generating caller graph for function %s\n",qualifiedName().data()); ol.disable(OutputGenerator::Man); diff --git a/src/msc.cpp b/src/msc.cpp index aa4ad88..f68858a 100644 --- a/src/msc.cpp +++ b/src/msc.cpp @@ -98,7 +98,7 @@ void writeMscGraphFromFile(const char *inFile,const char *outDir, // go to the html output directory (i.e. path) QDir::setCurrent(outDir); //printf("Going to dir %s\n",QDir::currentDirPath().data()); - QCString mscExe = Config_getString("MSC_PATH")+"mscgen"+portable_commandExtension(); + QCString mscExe = Config_getString("MSCGEN_PATH")+"mscgen"+portable_commandExtension(); QCString mscArgs; QCString extension; if (format==MSC_BITMAP) @@ -151,7 +151,7 @@ QString getMscImageMapFromFile(const QString& inFile, const QString& outDir, QCString mscExe = "mscgen"; QCString mscArgs = "-T ismap -i \""; mscArgs+=inFile + ".msc\" -o \""; - mscArgs+=outFile + ".map\""; + mscArgs+=outFile + "\""; int exitCode; if ((exitCode=portable_system(mscExe,mscArgs,FALSE))!=0) @@ -162,7 +162,7 @@ QString getMscImageMapFromFile(const QString& inFile, const QString& outDir, QString result; QTextOStream tmpout(&result); - convertMapFile(tmpout, outFile+".map", relPath); + convertMapFile(tmpout, outFile, relPath); QDir().remove(outFile); QDir::setCurrent(oldDir); diff --git a/src/namespacedef.cpp b/src/namespacedef.cpp index 1ebaaf9..fe69505 100644 --- a/src/namespacedef.cpp +++ b/src/namespacedef.cpp @@ -179,7 +179,7 @@ void NamespaceDef::insertMember(MemberDef *md) m_memberLists.append(allMemberList); } allMemberList->append(md); - ::addNamespaceMemberNameToIndex(md); + //::addNamespaceMemberNameToIndex(md); //static bool sortBriefDocs=Config_getBool("SORT_BRIEF_DOCS"); switch(md->memberType()) { diff --git a/src/translator_cn.h b/src/translator_cn.h index 4c3168b..7689a0c 100644 --- a/src/translator_cn.h +++ b/src/translator_cn.h @@ -620,7 +620,8 @@ class TranslatorChinese : public Translator */ virtual QCString trNamespaces() { - return "Namespaces"; + // return "Namespaces"; + return "Ãû×Ö¿Õ¼ä"; } ////////////////////////////////////////////////////////////////////////// diff --git a/src/util.cpp b/src/util.cpp index 6521f81..0723ae4 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -116,8 +116,9 @@ void TextGeneratorOLImpl::writeLink(const char *extRef,const char *file, // an inheritance tree of depth of 100000 should be enough for everyone :-) const int maxInheritanceDepth = 100000; -bool isId(char c) +bool isId(int c) { + if (c<0 || c>255) return FALSE; return c=='_' || isalnum(c); } @@ -6080,3 +6081,166 @@ QCString parseCommentAsText(const QString &doc,const QCString &fileName,int line return result.data(); } +//-------------------------------------------------------------------------------------- + +static QDict<void> aliasesProcessed; + +QCString expandAliasRec(const QCString s) +{ + QCString result; + static QRegExp cmdPat("[\\\\@][a-z_A-Z][a-z_A-Z0-9]*"); + QCString value=s; + int i,p=0,l; + while ((i=cmdPat.match(value,p,&l))!=-1) + { + result+=value.mid(p,i-p); + QCString args = extractAliasArgs(value,i+l); + bool hasArgs = !args.isEmpty(); // found directly after command + QCString cmd; + if (hasArgs) + { + int numArgs = countAliasArguments(args); + cmd = value.mid(i+1,l-1)+QCString().sprintf("{%d}",numArgs); // alias name + {n} + } + else + { + cmd = value.mid(i+1,l-1); + } + //printf("Found command '%s' args='%s'\n",cmd.data(),args.data()); + QCString *aliasText=Doxygen::aliasDict.find(cmd); + if (aliasesProcessed.find(cmd)==0 && aliasText) // expand the alias + { + //printf("is an alias!\n"); + aliasesProcessed.insert(cmd,(void *)0x8); + QCString val = *aliasText; + if (hasArgs) + { + val = replaceAliasArguments(val,args); + //printf("replace '%s'->'%s' args='%s'\n", + // aliasText->data(),val.data(),args.data()); + } + result+=expandAliasRec(val); + aliasesProcessed.remove(cmd); + p=i+l; + if (hasArgs) p+=args.length()+2; + } + else // command is not an alias + { + //printf("not an alias!\n"); + result+=value.mid(i,l); + p=i+l; + } + } + result+=value.right(value.length()-p); + + //printf("expandAliases '%s'->'%s'\n",s.data(),result.data()); + return result; +} + +static QCString replaceAliasArgument(const QCString &aliasValue,int paramNum, + const QCString ¶mValue) +{ + QCString result = aliasValue; + QCString paramMarker; + paramMarker.sprintf("\\%d",paramNum); + int markerLen = paramMarker.length(); + int p=0,i; + while ((i=aliasValue.find(paramMarker,p))!=-1) // search for marker + { + //printf("Found marker '%s' at %d len=%d for param '%s' in '%s'\n", + // paramMarker.data(),i,markerLen,paramValue.data(),aliasValue.data()); + if (i==0 || aliasValue.at(i-1)!='\\') // found unescaped marker + { + QCString before = result.left(i); + QCString after = result.mid(i+markerLen); + result = before + paramValue + after; + p=i+paramValue.length(); + } + else // ignore escaped markers + { + p=i+1; + } + } + result = expandAliasRec(substitute(result,"\\,",",")); + //printf("replaceAliasArgument('%s',%d,'%s')->%s\n", + // aliasValue.data(),paramNum,paramValue.data(),result.data()); + return result; +} + +QCString replaceAliasArguments(const QCString &aliasValue,const QCString &argList) +{ + QCString result = aliasValue; + QList<QCString> args; + int p=0,i,c=1; + for (i=0;i<(int)argList.length();i++) + { + if (argList.at(i)==',' && (i==0 || argList.at(i-1)!='\\')) + { + result = replaceAliasArgument(result,c,argList.mid(p,i-p)); + p=i+1; + c++; + } + } + if (p<(int)argList.length()) + { + result = replaceAliasArgument(result,c,argList.right(argList.length()-p)); + } + return result; +} + +int countAliasArguments(const QCString argList) +{ + int count=1; + int l = argList.length(); + int i; + for (i=0;i<l;i++) + { + if (argList.at(i)==',' && (i==0 || argList.at(i-1)!='\\')) count++; + } + return count; +} + +QCString extractAliasArgs(const QCString &args,int pos) +{ + int i; + int bc=0; + if (args.at(pos)=='{') // alias has argument + { + for (i=pos;i<(int)args.length();i++) + { + if (args.at(i)=='{') bc++; + if (args.at(i)=='}') bc--; + if (bc==0) + { + //printf("extractAliasArgs('%s')->'%s'\n",args.data(),args.mid(pos+1,i-pos-1).data()); + return args.mid(pos+1,i-pos-1); + } + } + } + return ""; +} + +QCString resolveAliasCmd(const QCString aliasCmd) +{ + QCString result; + aliasesProcessed.clear(); + //printf("Expanding: '%s'\n",aliasCmd.data()); + result = expandAliasRec(aliasCmd); + //printf("Expanding result: '%s'->'%s'\n",aliasCmd.data(),result.data()); + return result; +} + +QCString expandAlias(const QCString &aliasName,const QCString &aliasValue) +{ + QCString result; + aliasesProcessed.clear(); + // avoid expanding this command recursively + aliasesProcessed.insert(aliasName,(void *)0x8); + // expand embedded commands + //printf("Expanding: '%s'->'%s'\n",aliasName.data(),aliasValue.data()); + result = expandAliasRec(aliasValue); + //printf("Expanding result: '%s'->'%s'\n",aliasName.data(),result.data()); + return result; +} + + @@ -187,7 +187,7 @@ QCString showFileDefMatches(const FileNameDict *fnDict,const char *n); int guessSection(const char *name); -bool isId(char c); +bool isId(int c); QCString removeRedundantWhiteSpace(const QCString &s); @@ -334,5 +334,14 @@ QCString transcodeCharacterStringToUTF8(const QCString &input); QCString recodeString(const QCString &str,const char *fromEncoding,const char *toEncoding); +QCString extractAliasArgs(const QCString &args,int pos); + +int countAliasArguments(const QCString argList); + +QCString replaceAliasArguments(const QCString &aliasValue,const QCString &argList); + +QCString resolveAliasCmd(const QCString aliasCmd); +QCString expandAlias(const QCString &aliasName,const QCString &aliasValue); + #endif diff --git a/src/xmlgen.cpp b/src/xmlgen.cpp index 1cc8375..e66bea3 100644 --- a/src/xmlgen.cpp +++ b/src/xmlgen.cpp @@ -189,7 +189,7 @@ void writeXMLLink(QTextStream &t,const char *extRef,const char *compoundId, if (anchorId) t << "member"; else t << "compound"; t << "\""; if (extRef) t << " external=\"" << extRef << "\""; - if (tooltip) t << " tooltip=\"" << tooltip << "\""; + if (tooltip) t << " tooltip=\"" << convertToXML(tooltip) << "\""; t << ">"; writeXMLString(t,text); t << "</ref>"; diff --git a/tmake/lib/solaris-g++/tmake.conf b/tmake/lib/solaris-g++/tmake.conf index f4adbcd..a6817bf 100755 --- a/tmake/lib/solaris-g++/tmake.conf +++ b/tmake/lib/solaris-g++/tmake.conf @@ -43,7 +43,7 @@ TMAKE_LFLAGS_SHAPP = -shared TMAKE_LFLAGS_SHLIB = -shared -h $(TARGET1) TMAKE_LFLAGS_SONAME = -TMAKE_LIBS = +TMAKE_LIBS = -liconv TMAKE_LIBS_X11 = -lXext -lX11 -lm TMAKE_LIBS_QT = -lqt TMAKE_LIBS_QT_MT = -lqt-mt |