From 9be758009e1a4c616377dc33ccf1e55dd8b04d9b Mon Sep 17 00:00:00 2001 From: Dimitri van Heesch Date: Sun, 14 Aug 2011 13:56:38 +0000 Subject: Release-1.7.5 --- INSTALL | 4 +- README | 4 +- configure | 4 +- doc/commands.doc | 55 + doc/docblocks.doc | 74 +- doc/language.doc | 58 +- doc/maintainers.txt | 2 +- doc/translator_report.txt | 261 +--- examples/Makefile.in | 6 +- examples/Makefile.win.in | 6 +- examples/tclexample.cfg | 13 + examples/tclexample.tcl | 82 + qtools/Doxyfile | 2 +- qtools/qmutex.cpp | 5 +- src/Makefile.in | 2 +- src/cite.cpp | 33 +- src/cite.h | 4 - src/classdef.cpp | 215 ++- src/classdef.h | 10 +- src/classlist.cpp | 23 +- src/cmdmapper.cpp | 3 +- src/cmdmapper.h | 1 + src/code.l | 27 +- src/commentcnv.l | 10 +- src/config.l | 2 + src/definition.cpp | 31 +- src/definition.h | 6 + src/docparser.cpp | 88 +- src/docparser.h | 40 +- src/docsets.cpp | 12 +- src/doctokenizer.h | 1 + src/doctokenizer.l | 13 + src/dot.cpp | 127 +- src/doxygen.cpp | 368 +++-- src/filedef.cpp | 11 +- src/filedef.h | 8 +- src/fortranscanner.l | 73 +- src/groupdef.cpp | 35 +- src/htmldocvisitor.cpp | 19 + src/htmlgen.cpp | 11 +- src/index.cpp | 42 +- src/language.cpp | 4 +- src/latexdocvisitor.cpp | 48 +- src/latexdocvisitor.h | 3 +- src/latexgen.cpp | 162 +- src/layout.cpp | 20 +- src/layout.h | 2 +- src/libdoxygen.pro.in | 7 +- src/libdoxygen.t | 3 + src/mandocvisitor.cpp | 17 + src/mangen.cpp | 2 + src/marshal.cpp | 3 +- src/memberdef.cpp | 141 +- src/memberdef.h | 4 +- src/memberlist.cpp | 1 + src/namespacedef.cpp | 50 +- src/namespacedef.h | 1 - src/outputlist.cpp | 4 +- src/outputlist.h | 2 +- src/perlmodgen.cpp | 1 + src/printdocvisitor.h | 1 + src/pycode.l | 43 +- src/rtfdocvisitor.cpp | 17 +- src/rtfgen.cpp | 47 +- src/scanner.l | 59 +- src/sortdict.h | 18 + src/store.cpp | 61 +- src/store.h | 1 + src/tclscanner.h | 52 + src/tclscanner.l | 2410 +++++++++++++++++++++++++++++ src/translator_adapter.h | 47 - src/translator_am.h | 3688 +++++++++++++++++++++++---------------------- src/translator_br.h | 24 +- src/translator_ca.h | 73 +- src/translator_cn.h | 646 ++++---- src/translator_cz.h | 19 +- src/translator_de.h | 20 +- src/translator_dk.h | 22 +- src/translator_gr.h | 32 +- src/translator_hr.h | 17 +- src/translator_kr.h | 2 +- src/translator_nl.h | 16 +- src/translator_pt.h | 808 +++++++--- src/translator_sk.h | 20 +- src/translator_tw.h | 743 +++++---- src/util.cpp | 175 ++- src/util.h | 15 +- src/vhdldocgen.cpp | 12 +- src/vhdlscanner.l | 1 + src/xmldocvisitor.cpp | 11 + src/xmlgen.cpp | 5 +- winbuild/Doxygen.vcproj | 24 +- 92 files changed, 7719 insertions(+), 3676 deletions(-) create mode 100644 examples/tclexample.cfg create mode 100644 examples/tclexample.tcl create mode 100644 src/tclscanner.h create mode 100644 src/tclscanner.l diff --git a/INSTALL b/INSTALL index c5abb84..d004ea5 100644 --- a/INSTALL +++ b/INSTALL @@ -1,7 +1,7 @@ -DOXYGEN Version 1.7.4-20110727 +DOXYGEN Version 1.7.5 Please read the installation section of the manual (http://www.doxygen.org/install.html) for instructions. -------- -Dimitri van Heesch (27 July 2011) +Dimitri van Heesch (14 August 2011) diff --git a/README b/README index 3af697d..5f807ba 100644 --- a/README +++ b/README @@ -1,4 +1,4 @@ -DOXYGEN Version 1.7.4_20110727 +DOXYGEN Version 1.7.5 Please read INSTALL for compilation instructions. @@ -26,4 +26,4 @@ forum. Enjoy, -Dimitri van Heesch (dimitri@stack.nl) (27 July 2011) +Dimitri van Heesch (dimitri@stack.nl) (14 August 2011) diff --git a/configure b/configure index 42ee6d7..6827682 100755 --- a/configure +++ b/configure @@ -17,10 +17,10 @@ doxygen_version_major=1 doxygen_version_minor=7 -doxygen_version_revision=4 +doxygen_version_revision=5 #NOTE: Setting version_mmn to "NO" will omit mmn info from the package. -doxygen_version_mmn=20110727 +doxygen_version_mmn=NO bin_dirs=`echo $PATH | sed -e "s/:/ /g"` diff --git a/doc/commands.doc b/doc/commands.doc index 7bd90e2..d74452a 100644 --- a/doc/commands.doc +++ b/doc/commands.doc @@ -161,6 +161,7 @@ documentation: \refitem cmdsince \\since \refitem cmdskip \\skip \refitem cmdskipline \\skipline +\refitem cmdsnippet \\snippet \refitem cmdstruct \\struct \refitem cmdsubpage \\subpage \refitem cmdsubsection \\subsection @@ -1862,6 +1863,10 @@ Commands for displaying examples for the corresponding HTML documentation that is generated by doxygen. \endhtmlonly + Alternatively, the \ref cmdsnippet "\\snippet" command can be used to + include only a fragment of a source file. For this to work the + fragment has to be marked. + \sa sections \ref cmdline "\\line", \ref cmdskip "\\skip", \ref cmdskipline "\\skipline", \ref cmduntil "\\until", and \ref cmdinclude "\\include". @@ -1894,6 +1899,10 @@ Commands for displaying examples \ref cmdskipline "\\skipline", and \\until commands. + Alternatively, the \ref cmdsnippet "\\snippet" command can be used to + include only a fragment of a source file. For this to work the + fragment has to be marked. + \note Doxygen's special commands do not work inside blocks of code. It is allowed to nest C-style comments inside a code block though. @@ -1962,6 +1971,52 @@ Commands for displaying examples See section \ref cmddontinclude "\\dontinclude" for an example.
+\section cmdsnippet \\snippet ( block_id ) + + \addindex \\snippet + Where the \ref cmdinclude "\\include" command can be used to include + a complete file as source code, this command can be used to quote only + a fragment of a source file. + + For example, the putting the following command in the documentation, + references a snippet in file \c example.cpp residing in a subdirectory + which should be pointed to by \ref cfg_example_path "EXAMPLE_PATH". + +\verbatim + \snippet snippets/example.cpp Adding a resource +\endverbatim + + The text following the file name is the unique identifier for the snippet. + This is used to delimit the quoted code in the relevant snippet file as + shown in the following example that corresponds to the above \\snippet + command: + +\code + QImage image(64, 64, QImage::Format_RGB32); + image.fill(qRgb(255, 160, 128)); + +//! [Adding a resource] + document->addResource(QTextDocument::ImageResource, + QUrl("mydata://image.png"), QVariant(image)); +//! [Adding a resource] + ... +\endcode + + Note that the lines containing the block markers will not be included, + so the output will be: + +\code + document->addResource(QTextDocument::ImageResource, + QUrl("mydata://image.png"), QVariant(image)); +\endcode + + Note also that the [block_id] markers should appear exactly twice in the + source file. + + see section \ref cmddontinclude "\\dontinclude" for an alternative way + to include fragments of a source file that does not require markers. + +
\section cmduntil \\until ( pattern ) \addindex \\until diff --git a/doc/docblocks.doc b/doc/docblocks.doc index e28328c..ea51edd 100644 --- a/doc/docblocks.doc +++ b/doc/docblocks.doc @@ -20,9 +20,10 @@ A special documentation block is a C or C++ style comment block with some additional markings, so doxygen knows it is a piece of documentation that -needs to end up in the generated documentation. For Python, VHDL, and Fortran -code there are different comment conventions, which can be found in sections -\ref pythonblocks, \ref vhdlblocks, and \ref fortranblocks respectively. +needs to end up in the generated documentation. For Python, VHDL, Fortran, and +Tcl code there are different comment conventions, which can be found in sections +\ref pythonblocks, \ref vhdlblocks, \ref fortranblocks, and \ref tclblocks +respectively. For each code item there are two (or in some cases three) types of descriptions, which together form the documentation: a \e brief description and \e detailed @@ -480,4 +481,71 @@ C> input parameter end function A \endverbatim +\section tclblocks Documentation blocks in Tcl + +Doxygen documentation can be included in normal Tcl comments. + +To start a new documentation block start a line with \c ## (two hashes). +All following comment lines and continuation lines will be added to this +block. The block ends with a line not starting with a \c # (hash sign). + +A brief documentation can be added with \c ;#< (semicolon, hash and +lower then sign). The brief documentation also ends at a line not starting +with a \c # (hash sign). + +Inside doxygen comment blocks all normal doxygen markings are supported. +The only expections are described in the following two paragraphs. + +If a doxygen comment block ends with a line containing only +\c #\\code or \c #\@code all code until a line only containing \c #\\endcode +or \c #\@endcode is added to the generated documentation as code block. + +If a doxygen comment block ends with a line containing only +\c #\\verbatim or \c #\@verbatim all code until a line only containing +\c #\\endverbatim or \c #\@endverbatim is added verbatim to the generated +documentation. + +To detect namespaces, classes, functions and variables the following +Tcl commands are recognized. Documentation blocks can be put on the lines +before the command. + + + + + +Following is a example using doxygen style comments: + +\include tclexample.tcl + \htmlonly + Click here + for the corresponding HTML documentation that is generated by doxygen. + \endhtmlonly + +\htmlonly +Go to the next section or return to the + index. +\endhtmlonly + */ diff --git a/doc/language.doc b/doc/language.doc index 17d38f6..9959cd1 100644 --- a/doc/language.doc +++ b/doc/language.doc @@ -68,55 +68,55 @@ when the translator was updated. Armenian Armen Tangamyan armen dot tangamyan at anu dot edu dot au - 1.7.5 + up-to-date Brazilian Portuguese Fabio "FJTC" Jun Takada Chino jun-chino at uol dot com dot br - 1.7.5 + up-to-date Catalan Maximiliano Pin
Albert Mora max dot pin at bitroit dot com
[unreachable] - 1.6.3 + up-to-date Chinese - Lang Yang
Li Daobing
Wei Liu + Lian Yang
Li Daobing
Wei Liu lian dot yang dot cn at gmail dot com
lidaobing at gmail dot com
liuwei at asiainfo dot com - 1.7.5 + up-to-date Chinese Traditional Daniel YC Lin
Gary Lee dlin dot tw at gmail dot com
garywlee at gmail dot com - 1.6.0 + up-to-date Croatian Boris Bralo boris dot bralo at gmail dot com - 1.7.5 + up-to-date Czech Petr Přikryl prikrylp at skil dot cz - 1.7.5 + up-to-date Danish Poul-Erik Hansen
Erik Søe Sørensen pouhan at gnotometrics dot dk
eriksoe+doxygen at daimi dot au dot dk - 1.7.5 + up-to-date Dutch Dimitri van Heesch dimitri at stack dot nl - 1.7.5 + up-to-date English @@ -146,13 +146,13 @@ when the translator was updated. German Peter Grotrian
Jens Seidel Peter dot Grotrian at pdv-FS dot de
jensseidel at users dot sf dot net - 1.7.5 + up-to-date Greek Paul Gessos gessos dot paul at yahoo dot gr - 1.7.5 + up-to-date Hungarian @@ -188,7 +188,7 @@ when the translator was updated. Korean Kim Taedong
SooYoung Jung
Richard Kim fly1004 at gmail dot com
jung5000 at gmail dot com
[unreachable] - 1.7.05 + 1.7.5 KoreanEn @@ -230,7 +230,7 @@ when the translator was updated. Portuguese Rui Godinho Lopes
-- searching for the maintainer -- [resigned]
[Please, try to help to find someone.] - 1.3.3 + up-to-date Romanian @@ -260,7 +260,7 @@ when the translator was updated. Slovak Kali+Laco Švec
Petr Přikryl the Slovak language advisors
prikrylp at skil dot cz - 1.7.5 + up-to-date Slovene @@ -319,28 +319,28 @@ when the translator was updated. Arabic & Moaz Reyad & {\tt\tiny [resigned] moazreyad at yahoo dot com} & 1.4.6 \\ ~ & -- searching for the maintainer -- & {\tt\tiny [Please, try to help to find someone.]} & ~ \\ \hline - Armenian & Armen Tangamyan & {\tt\tiny armen dot tangamyan at anu dot edu dot au} & 1.7.5 \\ + Armenian & Armen Tangamyan & {\tt\tiny armen dot tangamyan at anu dot edu dot au} & up-to-date \\ \hline - Brazilian Portuguese & Fabio "FJTC" Jun Takada Chino & {\tt\tiny jun-chino at uol dot com dot br} & 1.7.5 \\ + Brazilian Portuguese & Fabio "FJTC" Jun Takada Chino & {\tt\tiny jun-chino at uol dot com dot br} & up-to-date \\ \hline - Catalan & Maximiliano Pin & {\tt\tiny max dot pin at bitroit dot com} & 1.6.3 \\ + Catalan & Maximiliano Pin & {\tt\tiny max dot pin at bitroit dot com} & up-to-date \\ ~ & Albert Mora & {\tt\tiny [unreachable] amora at iua dot upf dot es} & ~ \\ \hline - Chinese & Lang Yang & {\tt\tiny lian dot yang dot cn at gmail dot com} & 1.7.5 \\ + Chinese & Lian Yang & {\tt\tiny lian dot yang dot cn at gmail dot com} & up-to-date \\ ~ & Li Daobing & {\tt\tiny lidaobing at gmail dot com} & ~ \\ ~ & Wei Liu & {\tt\tiny liuwei at asiainfo dot com} & ~ \\ \hline - Chinese Traditional & Daniel YC Lin & {\tt\tiny dlin dot tw at gmail dot com} & 1.6.0 \\ + Chinese Traditional & Daniel YC Lin & {\tt\tiny dlin dot tw at gmail dot com} & up-to-date \\ ~ & Gary Lee & {\tt\tiny garywlee at gmail dot com} & ~ \\ \hline - Croatian & Boris Bralo & {\tt\tiny boris dot bralo at gmail dot com} & 1.7.5 \\ + Croatian & Boris Bralo & {\tt\tiny boris dot bralo at gmail dot com} & up-to-date \\ \hline - Czech & Petr Přikryl & {\tt\tiny prikrylp at skil dot cz} & 1.7.5 \\ + Czech & Petr Přikryl & {\tt\tiny prikrylp at skil dot cz} & up-to-date \\ \hline - Danish & Poul-Erik Hansen & {\tt\tiny pouhan at gnotometrics dot dk} & 1.7.5 \\ + Danish & Poul-Erik Hansen & {\tt\tiny pouhan at gnotometrics dot dk} & up-to-date \\ ~ & Erik Søe Sørensen & {\tt\tiny eriksoe+doxygen at daimi dot au dot dk} & ~ \\ \hline - Dutch & Dimitri van Heesch & {\tt\tiny dimitri at stack dot nl} & 1.7.5 \\ + Dutch & Dimitri van Heesch & {\tt\tiny dimitri at stack dot nl} & up-to-date \\ \hline English & Dimitri van Heesch & {\tt\tiny dimitri at stack dot nl} & up-to-date \\ \hline @@ -350,10 +350,10 @@ when the translator was updated. \hline French & Xavier Outhier & {\tt\tiny xouthier at yahoo dot fr} & 1.6.3 \\ \hline - German & Peter Grotrian & {\tt\tiny Peter dot Grotrian at pdv-FS dot de} & 1.7.5 \\ + German & Peter Grotrian & {\tt\tiny Peter dot Grotrian at pdv-FS dot de} & up-to-date \\ ~ & Jens Seidel & {\tt\tiny jensseidel at users dot sf dot net} & ~ \\ \hline - Greek & Paul Gessos & {\tt\tiny gessos dot paul at yahoo dot gr} & 1.7.5 \\ + Greek & Paul Gessos & {\tt\tiny gessos dot paul at yahoo dot gr} & up-to-date \\ \hline Hungarian & Ákos Kiss & {\tt\tiny akiss at users dot sourceforge dot net} & 1.4.6 \\ ~ & Földvári György & {\tt\tiny [unreachable] foldvari lost at cyberspace} & ~ \\ @@ -370,7 +370,7 @@ when the translator was updated. \hline JapaneseEn & see the Japanese language & {\tt\tiny ~} & English based \\ \hline - Korean & Kim Taedong & {\tt\tiny fly1004 at gmail dot com} & 1.7.05 \\ + Korean & Kim Taedong & {\tt\tiny fly1004 at gmail dot com} & 1.7.5 \\ ~ & SooYoung Jung & {\tt\tiny jung5000 at gmail dot com} & ~ \\ ~ & Richard Kim & {\tt\tiny [unreachable] ryk at dspwiz dot com} & ~ \\ \hline @@ -391,7 +391,7 @@ when the translator was updated. ~ & Grzegorz Kowal & {\tt\tiny [unreachable] g\_kowal at poczta dot onet dot pl} & ~ \\ ~ & Krzysztof Kral & {\tt\tiny krzysztof dot kral at gmail dot com} & ~ \\ \hline - Portuguese & Rui Godinho Lopes & {\tt\tiny [resigned] rgl at ruilopes dot com} & 1.3.3 \\ + Portuguese & Rui Godinho Lopes & {\tt\tiny [resigned] rgl at ruilopes dot com} & up-to-date \\ ~ & -- searching for the maintainer -- & {\tt\tiny [Please, try to help to find someone.]} & ~ \\ \hline Romanian & Ionut Dumitrascu & {\tt\tiny reddumy at yahoo dot com} & 1.6.0 \\ @@ -403,7 +403,7 @@ when the translator was updated. \hline SerbianCyrilic & Nedeljko Stefanovic & {\tt\tiny stenedjo at yahoo dot com} & 1.6.0 \\ \hline - Slovak & Kali+Laco Švec & {\tt\tiny the Slovak language advisors} & 1.7.5 \\ + Slovak & Kali+Laco Švec & {\tt\tiny the Slovak language advisors} & up-to-date \\ ~ & Petr Přikryl & {\tt\tiny prikrylp at skil dot cz} & ~ \\ \hline Slovene & Matjaž Ostroveršnik & {\tt\tiny matjaz dot ostroversnik at ostri dot org} & 1.4.6 \\ diff --git a/doc/maintainers.txt b/doc/maintainers.txt index dc4c21a..95310f5 100644 --- a/doc/maintainers.txt +++ b/doc/maintainers.txt @@ -33,7 +33,7 @@ Maximiliano Pin: max dot pin at bitroit dot com Albert Mora: [unreachable] amora at iua dot upf dot es TranslatorChinese -Lang Yang: lian dot yang dot cn at gmail dot com +Lian Yang: lian dot yang dot cn at gmail dot com Li Daobing: lidaobing at gmail dot com Wei Liu: liuwei at asiainfo dot com diff --git a/doc/translator_report.txt b/doc/translator_report.txt index 9cb017e..84e1ea0 100644 --- a/doc/translator_report.txt +++ b/doc/translator_report.txt @@ -10,7 +10,7 @@ Norwegian, Persian, Polish, Portuguese, Romanian, Russian, Serbian, SerbianCyrilic, Slovak, Slovene, Spanish, Swedish, Turkish, Ukrainian, and Vietnamese. -Of them, 1 translators are up-to-date, 38 translators are based on +Of them, 14 translators are up-to-date, 25 translators are based on some adapter class, and 2 are English based. ---------------------------------------------------------------------- @@ -19,7 +19,20 @@ alphabetically). This means that they derive from the Translator class and they implement all 228 of the required methods. Anyway, there still may be some details listed even for them: + TranslatorArmenian -- Change the base class to Translator. + TranslatorBrazilian + TranslatorCatalan + TranslatorChinesetraditional -- Reimplementation using UTF-8 suggested. + TranslatorChinese + TranslatorCroatian + TranslatorCzech + TranslatorDanish -- Reimplementation using UTF-8 suggested. + TranslatorDutch TranslatorEnglish + TranslatorGerman + TranslatorGreek + TranslatorPortuguese + TranslatorSlovak ---------------------------------------------------------------------- The following translator classes need some maintenance (the most @@ -29,34 +42,19 @@ must be implemented to become up-to-date: TranslatorTurkish 1.7.5 3 methods to implement (1 %) TranslatorSpanish 1.7.5 3 methods to implement (1 %) - TranslatorSlovak 1.7.5 3 methods to implement (1 %) TranslatorRussian 1.7.5 3 methods to implement (1 %) Note: Reimplementation using UTF-8 suggested. TranslatorPersian 1.7.5 3 methods to implement (1 %) - TranslatorKorean 1.7.05 3 methods to implement (1 %) - Note: Change the base class to TranslatorAdapter_1_7_5. + TranslatorKorean 1.7.5 3 methods to implement (1 %) + Note: Reimplementation using UTF-8 suggested. TranslatorItalian 1.7.5 3 methods to implement (1 %) - TranslatorGreek 1.7.5 3 methods to implement (1 %) - TranslatorGerman 1.7.5 3 methods to implement (1 %) TranslatorEsperanto 1.7.5 3 methods to implement (1 %) - TranslatorDutch 1.7.5 3 methods to implement (1 %) - TranslatorDanish 1.7.5 3 methods to implement (1 %) - Note: Reimplementation using UTF-8 suggested. - - TranslatorCzech 1.7.5 3 methods to implement (1 %) - TranslatorCroatian 1.7.5 3 methods to implement (1 %) - TranslatorChinese 1.7.5 3 methods to implement (1 %) - Note: Reimplementation using UTF-8 suggested. - - TranslatorBrazilian 1.7.5 3 methods to implement (1 %) - TranslatorArmenian 1.7.5 3 methods to implement (1 %) TranslatorPolish 1.6.3 7 methods to implement (3 %) TranslatorFrench 1.6.3 6 methods to implement (2 %) Note: Reimplementation using UTF-8 suggested. - TranslatorCatalan 1.6.3 7 methods to implement (3 %) TranslatorVietnamese 1.6.0 12 methods to implement (5 %) TranslatorSwedish 1.6.0 12 methods to implement (5 %) Note: Reimplementation using UTF-8 suggested. @@ -73,9 +71,6 @@ must be implemented to become up-to-date: Note: Reimplementation using UTF-8 suggested. TranslatorFinnish 1.6.0 12 methods to implement (5 %) - TranslatorChinesetraditional 1.6.0 12 methods to implement (5 %) - Note: Reimplementation using UTF-8 suggested. - TranslatorAfrikaans 1.6.0 12 methods to implement (5 %) Note: Reimplementation using UTF-8 suggested. @@ -100,9 +95,6 @@ must be implemented to become up-to-date: TranslatorUkrainian 1.4.1 36 methods to implement (15 %) Note: Reimplementation using UTF-8 suggested. - TranslatorPortuguese 1.3.3 47 methods to implement (20 %) - Note: Reimplementation using UTF-8 suggested. - ---------------------------------------------------------------------- The following translator classes derive directly from the @@ -210,125 +202,22 @@ TranslatorArabic (TranslatorAdapter_1_4_6) 35 methods to implement (15 %) virtual QCString trNoDescriptionAvailable() -TranslatorArmenian (TranslatorAdapter_1_7_5) 3 methods to implement (1 %) +TranslatorArmenian (TranslatorAdapter_1_7_5) ------------------ - Implements 225 of the required methods (98 %). + Implements 228 of the required methods (100 %). - Missing methods (should be implemented): - virtual QCString trDirDepGraph(const char * name) - virtual QCString trCiteReferences() - virtual QCString trCopyright() - - -TranslatorBrazilian (TranslatorAdapter_1_7_5) 3 methods to implement (1 %) -------------------- - - Implements 225 of the required methods (98 %). - - Missing methods (should be implemented): - - virtual QCString trDirDepGraph(const char * name) - virtual QCString trCiteReferences() - virtual QCString trCopyright() - - -TranslatorCatalan (TranslatorAdapter_1_6_3) 7 methods to implement (3 %) ------------------ - - Implements 221 of the required methods (96 %). - - Missing methods (should be implemented): - - virtual QCString trDateTime(int year, int month, int day, int dayOfWeek, int hour, int minutes, int seconds, bool includeTime) - virtual QCString trFileIn(const char * name) - virtual QCString trDirDepGraph(const char * name) - virtual QCString trCiteReferences() - virtual QCString trDirDependency(const char * name) - virtual QCString trCopyright() - virtual QCString trIncludesFileIn(const char * name) - - -TranslatorChinese (TranslatorAdapter_1_7_5) 3 methods to implement (1 %) ------------------ - - Implements 225 of the required methods (98 %). - - Missing methods (should be implemented): - - virtual QCString trDirDepGraph(const char * name) - virtual QCString trCiteReferences() - virtual QCString trCopyright() - - -TranslatorChinesetraditional (TranslatorAdapter_1_6_0) 12 methods to implement (5 %) +TranslatorChinesetraditional (Translator) ---------------------------- - Implements 216 of the required methods (94 %). - - Missing methods (should be implemented): - - virtual QCString trSearching() - virtual QCString trNoMatches() - virtual QCString trLoading() - virtual QCString trDateTime(int year, int month, int day, int dayOfWeek, int hour, int minutes, int seconds, bool includeTime) - virtual QCString trFileIn(const char * name) - virtual QCString trGlobalNamespace() - virtual QCString trDirDepGraph(const char * name) - virtual QCString trDirRelation(const char * name) - virtual QCString trCiteReferences() - virtual QCString trDirDependency(const char * name) - virtual QCString trCopyright() - virtual QCString trIncludesFileIn(const char * name) - - -TranslatorCroatian (TranslatorAdapter_1_7_5) 3 methods to implement (1 %) ------------------- - - Implements 225 of the required methods (98 %). - - Missing methods (should be implemented): - - virtual QCString trDirDepGraph(const char * name) - virtual QCString trCiteReferences() - virtual QCString trCopyright() - - -TranslatorCzech (TranslatorAdapter_1_7_5) 3 methods to implement (1 %) ---------------- - - Implements 225 of the required methods (98 %). - - Missing methods (should be implemented): - - virtual QCString trDirDepGraph(const char * name) - virtual QCString trCiteReferences() - virtual QCString trCopyright() + Implements 228 of the required methods (100 %). -TranslatorDanish (TranslatorAdapter_1_7_5) 3 methods to implement (1 %) +TranslatorDanish (Translator) ---------------- - Implements 225 of the required methods (98 %). - - Missing methods (should be implemented): - - virtual QCString trDirDepGraph(const char * name) - virtual QCString trCiteReferences() - virtual QCString trCopyright() - - -TranslatorDutch (TranslatorAdapter_1_7_5) 3 methods to implement (1 %) ---------------- - - Implements 225 of the required methods (98 %). - - Missing methods (should be implemented): - - virtual QCString trDirDepGraph(const char * name) - virtual QCString trCiteReferences() - virtual QCString trCopyright() + Implements 228 of the required methods (100 %). TranslatorEsperanto (TranslatorAdapter_1_7_5) 3 methods to implement (1 %) @@ -379,30 +268,6 @@ TranslatorFrench (TranslatorAdapter_1_6_3) 6 methods to implement (2 %) virtual QCString trIncludesFileIn(const char * name) -TranslatorGerman (TranslatorAdapter_1_7_5) 3 methods to implement (1 %) ----------------- - - Implements 225 of the required methods (98 %). - - Missing methods (should be implemented): - - virtual QCString trDirDepGraph(const char * name) - virtual QCString trCiteReferences() - virtual QCString trCopyright() - - -TranslatorGreek (TranslatorAdapter_1_7_5) 3 methods to implement (1 %) ---------------- - - Implements 225 of the required methods (98 %). - - Missing methods (should be implemented): - - virtual QCString trDirDepGraph(const char * name) - virtual QCString trCiteReferences() - virtual QCString trCopyright() - - TranslatorHungarian (TranslatorAdapter_1_4_6) 36 methods to implement (15 %) ------------------- @@ -563,7 +428,7 @@ TranslatorJapaneseEn (TranslatorEnglish) 223 methods to implement (97 %) virtual QCString latexLanguageSupportCommand() -TranslatorKorean (TranslatorAdapter_1_6_3) 3 methods to implement (1 %) +TranslatorKorean (TranslatorAdapter_1_7_5) 3 methods to implement (1 %) ---------------- Implements 225 of the required methods (98 %). @@ -751,74 +616,6 @@ TranslatorPolish (TranslatorAdapter_1_6_3) 7 methods to implement (3 %) QCString trNoDescriptionAvailable() -TranslatorPortuguese (TranslatorAdapter_1_3_3) 47 methods to implement (20 %) --------------------- - - Implements 181 of the required methods (79 %). - - Missing methods (should be implemented): - - virtual QCString trCompoundMembersDescriptionFortran(bool extractAll) - virtual QCString trSearching() - virtual QCString trOverloadText() - virtual QCString trDirIndex() - virtual QCString trNoMatches() - virtual QCString trGeneratedFromFilesFortran(ClassDef::CompoundType compType, bool single) - virtual QCString trLoading() - virtual QCString trSubprograms() - virtual QCString trDateTime(int year, int month, int day, int dayOfWeek, int hour, int minutes, int seconds, bool includeTime) - virtual QCString trModulesListDescription(bool extractAll) - virtual QCString trModulesList() - virtual QCString trDirDocumentation() - virtual QCString trSearchResultsTitle() - virtual QCString trDirectories() - virtual QCString trTypeConstraints() - virtual QCString trFileIn(const char * name) - virtual QCString trGlobalNamespace() - virtual QCString trMemberFunctionDocumentationFortran() - virtual QCString trDirDescription() - virtual QCString trCompoundListDescriptionFortran() - virtual QCString trTypeDocumentation() - virtual QCString trModuleReference(const char * namespaceName) - virtual QCString trModulesMemberDescription(bool extractAll) - virtual QCString trModulesMembers() - virtual QCString trDirDepGraph(const char * name) - virtual QCString trModulesIndex() - virtual QCString trDirRelation(const char * name) - virtual QCString trCompoundListFortran() - virtual QCString trDataTypes() - virtual QCString trCiteReferences() - virtual QCString trSearchResults(int numDocuments) - virtual QCString trDirDependency(const char * name) - virtual QCString trCopyright() - virtual QCString trIncludesFileIn(const char * name) - virtual QCString trSearchMatches() - virtual QCString trCompoundIndexFortran() - virtual QCString trSubprogram(bool first_capital, bool singular) - virtual QCString trCallerGraph() - virtual QCString trCompoundReferenceFortran(const char * clName, ClassDef::CompoundType compType, bool isTemplate) - virtual QCString trType(bool first_capital, bool singular) - virtual QCString trModule(bool first_capital, bool singular) - virtual QCString trCompoundMembersFortran() - virtual QCString trSourceFile(QCString & filename) - virtual QCString trDirReference(const char * dirName) - virtual QCString trDir(bool first_capital, bool singular) - virtual QCString trSearchForIndex() - virtual QCString trSubprogramDocumentation() - - Obsolete methods (should be removed, never used): - - QCString trHeaderFilesDescription() - virtual QCString trField(bool first_capital, bool singular) - virtual QCString trPackageDocumentation() - virtual QCString trSources() - QCString trReimplementedForInternalReasons() - virtual QCString trInterfaces() - QCString trHeaderFiles() - QCString trBugsAndLimitations() - QCString trNoDescriptionAvailable() - - TranslatorRomanian (TranslatorAdapter_1_6_0) 12 methods to implement (5 %) ------------------ @@ -894,18 +691,6 @@ TranslatorSerbianCyrilic (TranslatorAdapter_1_6_0) 12 methods to implement (5 virtual QCString trIncludesFileIn(const char * name) -TranslatorSlovak (TranslatorAdapter_1_7_5) 3 methods to implement (1 %) ----------------- - - Implements 225 of the required methods (98 %). - - Missing methods (should be implemented): - - virtual QCString trDirDepGraph(const char * name) - virtual QCString trCiteReferences() - virtual QCString trCopyright() - - TranslatorSlovene (TranslatorAdapter_1_4_6) 36 methods to implement (15 %) ----------------- diff --git a/examples/Makefile.in b/examples/Makefile.in index 55bce8f..26b7c24 100644 --- a/examples/Makefile.in +++ b/examples/Makefile.in @@ -24,6 +24,7 @@ all: class/html/index.html \ memgrp/html/index.html \ docstring/html/index.html \ pyexample/html/index.html \ + tclexample/html/index.html \ mux/html/index.html \ manual/html/index.html @@ -34,7 +35,7 @@ clean: rm -rf class define enum file func page relates author \ par overload example include qtstyle jdstyle structcmd \ autolink tag restypedef afterdoc template tag group diagrams \ - memgrp docstring pyexample mux manual dbusxml + memgrp docstring pyexample mux manual dbusxml tclexample class/html/index.html: class.h class.cfg $(DOXYGEN)/bin/doxygen class.cfg @@ -107,6 +108,9 @@ memgrp/html/index.html: memgrp.cpp memgrp.cfg pyexample/html/index.html: pyexample.py pyexample.cfg $(DOXYGEN)/bin/doxygen pyexample.cfg +tclexample/html/index.html: tclexample.tcl tclexample.cfg + $(DOXYGEN)/bin/doxygen tclexample.cfg + mux/html/index.html: mux.vhdl mux.cfg $(DOXYGEN)/bin/doxygen mux.cfg diff --git a/examples/Makefile.win.in b/examples/Makefile.win.in index 0d5e64e..914c5ed 100644 --- a/examples/Makefile.win.in +++ b/examples/Makefile.win.in @@ -25,11 +25,12 @@ all: class/html/index.html \ memgrp/html/index.html \ docstring/html/index.html \ pyexample/html/index.html \ + tclexample/html/index.html \ mux/html/index.html \ manual/html/index.html clean: - del /s/y class define enum file pyexample docstring + del /s/y class define enum file pyexample tclexample docstring del /s/y func page relates author del /s/y par overload example include qtstyle del /s/y jdstyle structcmd autolink resdefine mux manual @@ -104,6 +105,9 @@ memgrp/html/index.html: memgrp.cpp memgrp.cfg pyexample/html/index.html: pyexample.py pyexample.cfg $(DOXYDIR)\doxygen pyexample.cfg +tclexample/html/index.html: tclexample.tcl tclexample.cfg + $(DOXYDIR)\doxygen tclexample.cfg + mux/html/index.html: mux.vhdl mux.cfg $(DOXYDIR)\doxygen mux.cfg diff --git a/examples/tclexample.cfg b/examples/tclexample.cfg new file mode 100644 index 0000000..a02bb2b --- /dev/null +++ b/examples/tclexample.cfg @@ -0,0 +1,13 @@ +PROJECT_NAME = "Tcl" +OUTPUT_DIRECTORY = tclexample +GENERATE_LATEX = NO +GENERATE_MAN = NO +GENERATE_RTF = NO +CASE_SENSE_NAMES = NO +INPUT = tclexample.tcl +QUIET = YES +JAVADOC_AUTOBRIEF = YES +SEARCHENGINE = NO +INLINE_SOURCES = YES +EXTRACT_ALL = YES +EXTRACT_PRIVATE = YES diff --git a/examples/tclexample.tcl b/examples/tclexample.tcl new file mode 100644 index 0000000..6edef66 --- /dev/null +++ b/examples/tclexample.tcl @@ -0,0 +1,82 @@ +## \file tclexample.tcl +# File documentation. +#\verbatim + +# Startup code:\ +exec tclsh "$0" "$@" +#\endverbatim +## Documented namespace \c ns . +# The code is inserted here: +#\code +namespace eval ns { + ## Documented proc \c ns_proc . + # param[in] arg some argument + proc ns_proc {arg} {} + ## Documented var \c ns_var . + # Some documentation. + variable ns_var + ## Documented itcl class \c itcl_class . + itcl::class itcl_class { + ## Create object. + constructor {args} {eval $args} + ## Destroy object. + destructor {exit} + ## Documented itcl method \c itcl_method_x . + # param[in] arg Argument + private method itcl_method_x {arg} + ## Documented itcl method \c itcl_method_y . + # param[in] arg Argument + protected method itcl_method_y {arg} {} + ## Documented itcl method \c itcl_method_z . + # param[in] arg Argument + public method itcl_method_z {arg} {} + ## Documented common itcl var \c itcl_Var . + common itcl_Var + ## \protectedsection + + variable itcl_var1;#< Documented itcl var \c itcl_var1 . + variable itcl_var2;#< Documented itcl var \c itcl_var2 . + } + ## Documented oo class \c oo_class . + oo::class create oo_class { + ## Create object. + # Configure with args + constructor {args} {eval $args} + ## Destroy object. + # Exit. + destructor {exit} + ## Documented oo var \c oo_var . + # Defined inside class + variable oo_var + ## \private Documented oo method \c oo_method_x . + # param[in] arg Argument + method oo_method_x {arg} {} + ## \protected Documented oo method \c oo_method_y . + # param[in] arg Argument + method oo_method_y {arg} {} + ## \public Documented oo method \c oo_method_z . + # param[in] arg Argument + method oo_method_z {arg} {} + } +} +#\endcode + +itcl::body ::ns::itcl_class::itcl_method_x {argx} { + puts "$argx OK" +} + +oo::define ns::oo_class { + ## \public Outside defined variable \c oo_var_out . + # Inside oo_class + variable oo_var_out +} + +## Documented global proc \c glob_proc . +# param[in] arg Argument +proc glob_proc {arg} {puts $arg} + +variable glob_var;#< Documented global var \c glob_var\ + with newline +#< and continued line + +# end of file diff --git a/qtools/Doxyfile b/qtools/Doxyfile index f7b815e..8600643 100644 --- a/qtools/Doxyfile +++ b/qtools/Doxyfile @@ -212,7 +212,7 @@ MAN_LINKS = NO #--------------------------------------------------------------------------- # configuration options related to the XML output #--------------------------------------------------------------------------- -GENERATE_XML = NO +GENERATE_XML = YES XML_OUTPUT = xml XML_SCHEMA = XML_DTD = diff --git a/qtools/qmutex.cpp b/qtools/qmutex.cpp index fda5f07..08a13bc 100644 --- a/qtools/qmutex.cpp +++ b/qtools/qmutex.cpp @@ -59,7 +59,7 @@ void QMutex::lock() { //printf("%p: QMutex::lock(): enter\n",this); bool isLocked; - isLocked = d->contenders == 0 && d->contenders.testAndSet(0, 1); + isLocked = d->contenders.testAndSet(0, 1); if (!isLocked) { isLocked = d->contenders.fetchAndAdd(1)==0; @@ -78,8 +78,7 @@ void QMutex::lock() bool QMutex::tryLock() { - bool isLocked = d->contenders == 0 && - d->contenders.testAndSet(0, 1); + bool isLocked = d->contenders.testAndSet(0, 1); return isLocked; } diff --git a/src/Makefile.in b/src/Makefile.in index 2defba8..6be0bff 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -49,6 +49,6 @@ distclean: clean ce_parse.cpp ce_parse.h doxytag.cpp tag.cpp commentscan.cpp \ declinfo.cpp defargs.cpp commentcnv.cpp doctokenizer.cpp \ pycode.cpp pyscanner.cpp fortrancode.cpp fortranscanner.cpp \ - vhdlscanner.cpp vhdlcode.cpp + vhdlscanner.cpp vhdlcode.cpp tclscanner.cpp FORCE: diff --git a/src/cite.cpp b/src/cite.cpp index f460149..9d67afa 100644 --- a/src/cite.cpp +++ b/src/cite.cpp @@ -36,21 +36,6 @@ const QCString CiteConsts::anchorPrefix("CITEREF_"); //-------------------------------------------------------------------------- -static bool writeBstFile(const QString &fileName) -{ - QCString bstData = doxygen_bst; - QFile f(fileName); - if (!f.open(IO_WriteOnly)) - { - err("error: could not open file %s for writing\n",fileName.data()); - return FALSE; - } - f.writeBlock(bstData, strlen(bstData)); - return TRUE; -} - -//-------------------------------------------------------------------------- - CiteDict::CiteDict(int size) : m_entries(size, FALSE) { m_ordering.setAutoDelete(TRUE); @@ -119,14 +104,16 @@ bool CiteDict::writeAux() bool CiteDict::writeBst() { //msg("..writing bst file\n"); - QCString bstFileName = m_baseFileName + ".bst"; - return writeBstFile(bstFileName); -} - -void CiteDict::writeDefaultBibStyle() -{ - writeBstFile("doxygen.bst"); - msg("wrote doxygen.bst\n"); + QCString fileName = m_baseFileName + ".bst"; + QCString bstData = doxygen_bst; + QFile f(fileName); + if (!f.open(IO_WriteOnly)) + { + err("error: could not open file %s for writing\n",fileName.data()); + return FALSE; + } + f.writeBlock(bstData, bstData.length()); + return TRUE; } void CiteDict::writeLatexBibliography(FTextStream &t) diff --git a/src/cite.h b/src/cite.h index 62524a2..d290c9c 100644 --- a/src/cite.h +++ b/src/cite.h @@ -86,10 +86,6 @@ class CiteDict */ void writeLatexBibliography(FTextStream &t); - /** writes the default bibliography style to the output */ - static void writeDefaultBibStyle(); - - private: bool writeAux(); bool writeBst(); diff --git a/src/classdef.cpp b/src/classdef.cpp index c9cb837..c69c300 100644 --- a/src/classdef.cpp +++ b/src/classdef.cpp @@ -152,9 +152,6 @@ class ClassDefImpl /*! Is the class part of an unnamed namespace? */ bool isStatic; - /*! Language used for this class */ - SrcLangExt lang; - /*! TRUE if classes members are merged with those of the base classes. */ bool membersMerged; @@ -177,6 +174,9 @@ class ClassDefImpl /** Is this a simple (non-nested) C structure? */ bool isSimple; + + ClassList *taggedInnerClasses; + ClassDef *tagLessRef; }; void ClassDefImpl::init(const char *defFileName, const char *name, @@ -217,11 +217,15 @@ void ClassDefImpl::init(const char *defFileName, const char *name, categoryOf = 0; usedOnly = FALSE; isSimple = Config_getBool("INLINE_SIMPLE_STRUCTS"); + taggedInnerClasses = 0; + tagLessRef = 0; //QCString ns; //extractNamespaceName(name,className,ns); //printf("m_name=%s m_className=%s ns=%s\n",m_name.data(),m_className.data(),ns.data()); - if (getLanguageFromFileName(defFileName)!=SrcLangExt_Java && + // we cannot use getLanguage at this point, as setLanguage has not been called. + SrcLangExt lang = getLanguageFromFileName(defFileName); + if ((lang==SrcLangExt_Cpp || lang==SrcLangExt_ObjC) && guessSection(defFileName)==Entry::SOURCE_SEC) { isLocal=TRUE; @@ -254,6 +258,7 @@ ClassDefImpl::~ClassDefImpl() delete templBaseClassNames; delete tempArgs; delete typeConstraints; + delete taggedInnerClasses; } // constructs a new class definition @@ -268,7 +273,6 @@ ClassDef::ClassDef( setReference(lref); m_impl = new ClassDefImpl; m_impl->compType = ct; - m_impl->lang = SrcLangExt_Unknown; m_impl->init(defFileName,name(),compoundTypeString(),fName); } @@ -285,10 +289,11 @@ QCString ClassDef::getMemberListFileName() const QCString ClassDef::displayName() const { - static bool optimizeOutputForJava = Config_getBool("OPTIMIZE_OUTPUT_JAVA"); - static bool vhdlOpt = Config_getBool("OPTIMIZE_OUTPUT_VHDL"); + //static bool optimizeOutputForJava = Config_getBool("OPTIMIZE_OUTPUT_JAVA"); + SrcLangExt lang = getLanguage(); + //static bool vhdlOpt = Config_getBool("OPTIMIZE_OUTPUT_VHDL"); QCString n; - if (vhdlOpt) + if (lang==SrcLangExt_VHDL) { n = VhdlDocGen::getClassName(this); } @@ -296,9 +301,10 @@ QCString ClassDef::displayName() const { n=qualifiedNameWithTemplateParameters(); } - if (optimizeOutputForJava) + QCString sep=getLanguageSpecificSeparator(lang); + if (sep!="::") { - n=substitute(n,"::","."); + n=substitute(n,"::",sep); } if (m_impl->compType==ClassDef::Protocol && n.right(2)=="-p") { @@ -378,8 +384,7 @@ void ClassDef::internalInsertMember(MemberDef *md, //printf("insertInternalMember(%s) isHidden()=%d\n",md->name().data(),md->isHidden()); if (md->isHidden()) return; - static bool optVhdl = Config_getBool("OPTIMIZE_OUTPUT_VHDL"); - if (optVhdl) + if (getLanguage()==SrcLangExt_VHDL) { QCString title=VhdlDocGen::trVhdlType(md->getMemberSpecifiers(),FALSE); if (!m_impl->vhdlSummaryTitles.find(title)) @@ -491,7 +496,7 @@ void ClassDef::internalInsertMember(MemberDef *md, break; case Public: addMemberToList(MemberList::pubAttribs,md,TRUE); - isSimple=TRUE; + isSimple=!md->isFunctionPtr(); break; case Private: addMemberToList(MemberList::priAttribs,md,TRUE); @@ -542,6 +547,7 @@ void ClassDef::internalInsertMember(MemberDef *md, { m_impl->isSimple = FALSE; } + //printf("adding %s simple=%d total_simple=%d\n",name().data(),isSimple,m_impl->isSimple); /*******************************************************/ /* insert member in the detailed documentation section */ @@ -991,19 +997,19 @@ void ClassDef::showUsedFiles(OutputList &ol) { ol.pushGeneratorState(); ol.disable(OutputGenerator::Man); - bool fortranOpt = Config_getBool("OPTIMIZE_FOR_FORTRAN"); + SrcLangExt lang = getLanguage(); ol.writeRuler(); - if (fortranOpt) + if (lang==SrcLangExt_Fortran) { ol.parseText(theTranslator->trGeneratedFromFilesFortran( - m_impl->lang==SrcLangExt_ObjC && m_impl->compType==Interface ? Class : m_impl->compType, + getLanguage()==SrcLangExt_ObjC && m_impl->compType==Interface ? Class : m_impl->compType, m_impl->files.count()==1)); } else { ol.parseText(theTranslator->trGeneratedFromFiles( - m_impl->lang==SrcLangExt_ObjC && m_impl->compType==Interface ? Class : m_impl->compType, + getLanguage()==SrcLangExt_ObjC && m_impl->compType==Interface ? Class : m_impl->compType, m_impl->files.count()==1)); } @@ -1272,7 +1278,7 @@ void ClassDef::writeIncludeFiles(OutputList &ol) { ol.startParagraph(); ol.startTypewriter(); - SrcLangExt lang = getLanguageFromFileName(nm); + SrcLangExt lang = getLanguage(); bool isIDLorJava = lang==SrcLangExt_IDL || lang==SrcLangExt_Java; if (isIDLorJava) { @@ -1422,7 +1428,6 @@ void ClassDef::writeAuthorSection(OutputList &ol) void ClassDef::writeSummaryLinks(OutputList &ol) { - static bool vhdlOpt = Config_getBool("OPTIMIZE_OUTPUT_VHDL"); ol.pushGeneratorState(); ol.disableAllBut(OutputGenerator::Html); QListIterator eli( @@ -1430,7 +1435,7 @@ void ClassDef::writeSummaryLinks(OutputList &ol) LayoutDocEntry *lde; bool first=TRUE; - if (!vhdlOpt) + if (getLanguage()!=SrcLangExt_VHDL) { for (eli.toFirst();(lde=eli.current());++eli) { @@ -1681,11 +1686,12 @@ void ClassDef::writeMoreLink(OutputList &ol,const QCString &anchor) void ClassDef::writeDeclarationLink(OutputList &ol,bool &found,const char *header,bool localNames) { - static bool fortranOpt = Config_getBool("OPTIMIZE_FOR_FORTRAN"); - static bool vhdlOpt = Config_getBool("OPTIMIZE_OUTPUT_VHDL"); + //static bool fortranOpt = Config_getBool("OPTIMIZE_FOR_FORTRAN"); + //static bool vhdlOpt = Config_getBool("OPTIMIZE_OUTPUT_VHDL"); static bool hideUndocClasses = Config_getBool("HIDE_UNDOC_CLASSES"); static bool extractLocalClasses = Config_getBool("EXTRACT_LOCAL_CLASSES"); bool isLink = isLinkable(); + SrcLangExt lang = getLanguage(); if (isLink || (!hideUndocClasses && (!isLocal() || extractLocalClasses) @@ -1699,13 +1705,14 @@ void ClassDef::writeDeclarationLink(OutputList &ol,bool &found,const char *heade { ol.parseText(header); } - else if (vhdlOpt) + else if (lang==SrcLangExt_VHDL) { ol.parseText(VhdlDocGen::trVhdlType(VhdlDocGen::ARCHITECTURE,FALSE)); } else { - ol.parseText(fortranOpt ? theTranslator->trDataTypes() : + ol.parseText(lang==SrcLangExt_Fortran ? + theTranslator->trDataTypes() : theTranslator->trCompounds()); } ol.endMemberHeader(); @@ -1734,7 +1741,7 @@ void ClassDef::writeDeclarationLink(OutputList &ol,bool &found,const char *heade cname = displayName(); } - if (!vhdlOpt) // for VHDL we swap the name and the type + if (lang!=SrcLangExt_VHDL) // for VHDL we swap the name and the type { ol.writeString(ctype); ol.writeString(" "); @@ -1754,7 +1761,7 @@ void ClassDef::writeDeclarationLink(OutputList &ol,bool &found,const char *heade ol.docify(cname); ol.endBold(); } - if (vhdlOpt) // now write the type + if (lang==SrcLangExt_VHDL) // now write the type { ol.writeString(" "); ol.insertMemberAlign(); @@ -1907,25 +1914,26 @@ void ClassDef::writeDocumentationContents(OutputList &ol,const QCString &pageTit void ClassDef::writeDocumentation(OutputList &ol) { static bool generateTreeView = Config_getBool("GENERATE_TREEVIEW"); - static bool fortranOpt = Config_getBool("OPTIMIZE_FOR_FORTRAN"); - static bool vhdlOpt = Config_getBool("OPTIMIZE_OUTPUT_VHDL"); + //static bool fortranOpt = Config_getBool("OPTIMIZE_FOR_FORTRAN"); + //static bool vhdlOpt = Config_getBool("OPTIMIZE_OUTPUT_VHDL"); QCString pageTitle; + SrcLangExt lang = getLanguage(); - if (fortranOpt) + if (lang==SrcLangExt_Fortran) { pageTitle = theTranslator->trCompoundReferenceFortran(displayName(), m_impl->compType, m_impl->tempArgs != 0); } - else if (vhdlOpt) + else if (lang==SrcLangExt_VHDL) { - // TODO: translate + // TODO: TRANSLATE ME pageTitle = VhdlDocGen::getClassTitle(this)+" Reference"; } else { pageTitle = theTranslator->trCompoundReference(displayName(), - m_impl->compType == Interface && m_impl->lang==SrcLangExt_ObjC ? Class : m_impl->compType, + m_impl->compType == Interface && getLanguage()==SrcLangExt_ObjC ? Class : m_impl->compType, m_impl->tempArgs != 0); } @@ -1940,7 +1948,7 @@ void ClassDef::writeDocumentation(OutputList &ol) } startTitle(ol,getOutputFileBase(),this); - ol.parseText(pageTitle,TRUE); + ol.parseText(pageTitle); addGroupListToTitle(ol,this); endTitle(ol,getOutputFileBase(),displayName()); writeDocumentationContents(ol,pageTitle); @@ -2058,7 +2066,7 @@ void ClassDef::writeDocumentationForInnerClasses(OutputList &ol) void ClassDef::writeMemberList(OutputList &ol) { static bool cOpt = Config_getBool("OPTIMIZE_OUTPUT_FOR_C"); - static bool vhdlOpt = Config_getBool("OPTIMIZE_OUTPUT_VHDL"); + //static bool vhdlOpt = Config_getBool("OPTIMIZE_OUTPUT_VHDL"); static bool generateTreeView = Config_getBool("GENERATE_TREEVIEW"); if (m_impl->allMemberNameInfoSDict==0 || cOpt) return; // only for HTML @@ -2077,7 +2085,7 @@ void ClassDef::writeMemberList(OutputList &ol) ol.endQuickIndices(); } startTitle(ol,0); - ol.parseText(displayName()+" "+theTranslator->trMemberList(),TRUE); + ol.parseText(displayName()+" "+theTranslator->trMemberList()); endTitle(ol,0,0); ol.startContents(); ol.parseText(theTranslator->trThisIsTheListOfAllMembers()); @@ -2220,20 +2228,23 @@ void ClassDef::writeMemberList(OutputList &ol) ol.writeString(""); ol.writeString(""); } + SrcLangExt lang = md->getLanguage(); if ( - (prot!=Public || (virt!=Normal && m_impl->lang!=SrcLangExt_ObjC) || + (prot!=Public || (virt!=Normal && getLanguage()!=SrcLangExt_ObjC) || md->isFriend() || md->isRelated() || md->isExplicit() || md->isMutable() || (md->isInline() && Config_getBool("INLINE_INFO")) || md->isSignal() || md->isSlot() || - md->isStatic() || vhdlOpt + md->isStatic() || lang==SrcLangExt_VHDL ) && memberWritten) { ol.startTypewriter(); ol.docify(" ["); QStrList sl; - if (vhdlOpt) sl.append(VhdlDocGen::trVhdlType( - md->getMemberSpecifiers())); //append vhdl type + if (lang==SrcLangExt_VHDL) + { + sl.append(VhdlDocGen::trVhdlType(md->getMemberSpecifiers())); //append vhdl type + } else if (md->isFriend()) sl.append("friend"); else if (md->isRelated()) sl.append("related"); else @@ -2245,8 +2256,8 @@ void ClassDef::writeMemberList(OutputList &ol) if (prot==Protected) sl.append("protected"); else if (prot==Private) sl.append("private"); else if (prot==Package) sl.append("package"); - if (virt==Virtual && - m_impl->lang!=SrcLangExt_ObjC) sl.append("virtual"); + if (virt==Virtual && getLanguage()!=SrcLangExt_ObjC) + sl.append("virtual"); else if (virt==Pure) sl.append("pure virtual"); if (md->isStatic()) sl.append("static"); if (md->isSignal()) sl.append("signal"); @@ -2575,10 +2586,10 @@ void ClassDef::mergeMembers() { if (m_impl->membersMerged) return; - static bool optimizeOutputForJava = Config_getBool("OPTIMIZE_OUTPUT_JAVA"); - static bool vhdlOpt = Config_getBool("OPTIMIZE_OUTPUT_VHDL"); - QCString sep="::"; - if (optimizeOutputForJava || vhdlOpt) sep="."; + //static bool optimizeOutputForJava = Config_getBool("OPTIMIZE_OUTPUT_JAVA"); + //static bool vhdlOpt = Config_getBool("OPTIMIZE_OUTPUT_VHDL"); + SrcLangExt lang = getLanguage(); + QCString sep=getLanguageSpecificSeparator(lang); int sepLen = sep.length(); m_impl->membersMerged=TRUE; @@ -2821,8 +2832,16 @@ void ClassDef::mergeMembers() */ void ClassDef::mergeCategory(ClassDef *category) { + static bool extractLocalMethods = Config_getBool("EXTRACT_LOCAL_METHODS"); + bool makePrivate = category->isLocal(); + // in case extract local methods is not enabled we don't add the methods + // of the category in case it is defined in the .m file. + if (makePrivate && !extractLocalMethods) return; + category->setCategoryOf(this); category->setArtificial(TRUE); + // make methods private for categories defined in the .m file + //printf("%s::mergeCategory makePrivate=%d\n",name().data(),makePrivate); MemberNameInfoSDict *srcMnd = category->memberNameInfoSDict(); MemberNameInfoSDict *dstMnd = m_impl->allMemberNameInfoSDict; @@ -2836,10 +2855,20 @@ void ClassDef::mergeCategory(ClassDef *category) MemberNameInfo *dstMni=dstMnd->find(srcMni->memberName()); if (dstMni) // method is already defined in the class { + //printf("Existing member %s\n",srcMni->memberName()); // TODO: we should remove the other member and insert this one. + MemberInfo *mi = dstMni->getFirst(); + if (mi) + { + Protection prot = mi->prot; + if (makePrivate) prot = Private; + removeMemberFromLists(mi->memberDef); + internalInsertMember(mi->memberDef,prot,FALSE); + } } else // new method name { + //printf("New member %s\n",srcMni->memberName()); // create a deep copy of the list MemberNameInfo *newMni = 0; newMni = new MemberNameInfo(srcMni->memberName()); @@ -2850,14 +2879,16 @@ void ClassDef::mergeCategory(ClassDef *category) for (;(mi=mnii.current());++mnii) { //printf("Adding '%s'\n",mi->memberDef->name().data()); - MemberInfo *newMi=new MemberInfo(mi->memberDef,mi->prot,mi->virt,mi->inherited); + Protection prot = mi->prot; + if (makePrivate) prot = Private; + MemberInfo *newMi=new MemberInfo(mi->memberDef,prot,mi->virt,mi->inherited); newMi->scopePath=mi->scopePath; newMi->ambigClass=mi->ambigClass; newMi->ambiguityResolutionScope=mi->ambiguityResolutionScope; newMni->append(newMi); mi->memberDef->moveTo(this); mi->memberDef->setCategory(category); - internalInsertMember(mi->memberDef,mi->prot,FALSE); + internalInsertMember(mi->memberDef,prot,FALSE); } // add it to the dictionary @@ -3113,8 +3144,8 @@ void ClassDef::determineIntfUsageRelation() QCString ClassDef::compoundTypeString() const { - if (m_impl->compType==Interface && m_impl->lang==SrcLangExt_ObjC) return "class"; - if (Config_getBool("OPTIMIZE_FOR_FORTRAN")) + if (m_impl->compType==Interface && getLanguage()==SrcLangExt_ObjC) return "class"; + if (getLanguage()==SrcLangExt_Fortran) { switch (m_impl->compType) { @@ -3180,8 +3211,8 @@ QCString ClassDef::getOutputFileBase() const } else if (inlineSimpleClasses && m_impl->isSimple && (scope=getOuterScope()) && ( - (scope==Doxygen::globalScope && getFileDef() && getFileDef()->isLinkable()) || - scope->isLinkable() + (scope==Doxygen::globalScope && getFileDef() && getFileDef()->isLinkableInProject()) || + scope->isLinkableInProject() ) ) { @@ -3269,7 +3300,6 @@ void ClassDef::addInnerCompound(Definition *d) m_impl->innerClasses = new ClassSDict(17); } m_impl->innerClasses->inSort(d->localName(),(ClassDef *)d); - m_impl->isSimple = FALSE; } } @@ -3478,7 +3508,7 @@ void ClassDef::getTemplateParameterLists(QList &lists) const QCString ClassDef::qualifiedNameWithTemplateParameters( QList *actualParams) const { - static bool optimizeOutputJava = Config_getBool("OPTIMIZE_OUTPUT_JAVA"); + //static bool optimizeOutputJava = Config_getBool("OPTIMIZE_OUTPUT_JAVA"); static bool hideScopeNames = Config_getBool("HIDE_SCOPE_NAMES"); //printf("qualifiedNameWithTemplateParameters() localName=%s\n",localName().data()); QCString scName; @@ -3496,16 +3526,12 @@ QCString ClassDef::qualifiedNameWithTemplateParameters( } } - QCString scopeSeparator; - if (optimizeOutputJava) - scopeSeparator="."; - else - scopeSeparator="::"; - + SrcLangExt lang = getLanguage(); + QCString scopeSeparator = getLanguageSpecificSeparator(lang); if (!scName.isEmpty()) scName+=scopeSeparator; bool isSpecialization = localName().find('<')!=-1; - bool isGeneric = m_impl->lang==SrcLangExt_CSharp; + bool isGeneric = getLanguage()==SrcLangExt_CSharp; QCString clName = className(); if (isGeneric && clName.right(2)=="-g") @@ -3556,15 +3582,15 @@ void ClassDef::setClassName(const char *name) void ClassDef::addListReferences() { - bool fortranOpt=Config_getBool("OPTIMIZE_FOR_FORTRAN"); + SrcLangExt lang = getLanguage(); if (!isLinkableInProject()) return; //printf("ClassDef(%s)::addListReferences()\n",name().data()); { LockingPtr< QList > xrefItems = xrefListItems(); addRefItem(xrefItems.pointer(), qualifiedName(), - fortranOpt?theTranslator->trType(TRUE,TRUE): - theTranslator->trClass(TRUE,TRUE), + lang==SrcLangExt_Fortran ? theTranslator->trType(TRUE,TRUE) + : theTranslator->trClass(TRUE,TRUE), getOutputFileBase(), displayName(), 0 @@ -3683,11 +3709,11 @@ void ClassDef::writeMemberDeclarations(OutputList &ol,MemberList::ListType lt,co const char *subTitle,bool showInline) { //printf("%s: ClassDef::writeMemberDeclarations\n",name().data()); - static bool optimizeVhdl = Config_getBool("OPTIMIZE_OUTPUT_VHDL"); + //static bool optimizeVhdl = Config_getBool("OPTIMIZE_OUTPUT_VHDL"); MemberList * ml = getMemberList(lt); if (ml) { - if (optimizeVhdl) // use specific declarations function + if (getLanguage()==SrcLangExt_VHDL) // use specific declarations function { VhdlDocGen::writeVhdlDeclarations(ml,ol,0,this,0); } @@ -3820,12 +3846,12 @@ bool ClassDef::isAbstract() const bool ClassDef::isObjectiveC() const { - return m_impl->lang==SrcLangExt_ObjC; + return getLanguage()==SrcLangExt_ObjC; } bool ClassDef::isCSharp() const { - return m_impl->lang==SrcLangExt_CSharp; + return getLanguage()==SrcLangExt_CSharp; } ClassDef *ClassDef::categoryOf() const @@ -3868,11 +3894,6 @@ void ClassDef::setIsStatic(bool b) m_impl->isStatic=b; } -void ClassDef::setLanguage(SrcLangExt lang) -{ - m_impl->lang=lang; -} - void ClassDef::setCompoundType(CompoundType t) { m_impl->compType = t; @@ -3898,11 +3919,6 @@ void ClassDef::setUsedOnly(bool b) m_impl->usedOnly = b; } -SrcLangExt ClassDef::getLanguage() const -{ - return m_impl->lang; -} - bool ClassDef::isUsedOnly() const { return m_impl->usedOnly; @@ -3956,13 +3972,19 @@ bool ClassDef::isEmbeddedInOuterScope() const Definition *container = getOuterScope(); + bool containerLinkable = + container && + ( + (container==Doxygen::globalScope && getFileDef() && getFileDef()->isLinkableInProject()) || // global class in documented file + container->isLinkableInProject() // class in documented scope + ); + // inline because of INLINE_GROUPED_CLASSES=YES ? bool b1 = (inlineGroupedClasses && partOfGroups()!=0); // a grouped class // inline because of INLINE_SIMPLE_STRUCTS=YES ? bool b2 = (inlineSimpleClasses && m_impl->isSimple && // a simple class - ((container && - (container==Doxygen::globalScope || container->isLinkableInProject())) || // with a documented scope - partOfGroups()!=0 // or part of a group + (containerLinkable || // in a documented container + partOfGroups()!=0 // or part of a group ) ); //printf("%s::isEmbeddedInOuterScope(): inlineGroupedClasses=%d " @@ -3973,4 +3995,37 @@ bool ClassDef::isEmbeddedInOuterScope() const return b1 || b2; // either reason will do } +const ClassList *ClassDef::taggedInnerClasses() const +{ + return m_impl->taggedInnerClasses; +} + +void ClassDef::addTaggedInnerClass(ClassDef *cd) +{ + if (m_impl->taggedInnerClasses==0) + { + m_impl->taggedInnerClasses = new ClassList; + } + m_impl->taggedInnerClasses->append(cd); +} + +ClassDef *ClassDef::tagLessReference() const +{ + return m_impl->tagLessRef; +} + +void ClassDef::setTagLessReference(ClassDef *cd) +{ + m_impl->tagLessRef = cd; +} + +void ClassDef::removeMemberFromLists(MemberDef *md) +{ + MemberList *ml = m_impl->memberLists.first(); + while (ml) + { + ml->remove(md); + ml = m_impl->memberLists.next(); + } +} diff --git a/src/classdef.h b/src/classdef.h index a3f4ad1..9673ec9 100644 --- a/src/classdef.h +++ b/src/classdef.h @@ -267,10 +267,11 @@ class ClassDef : public Definition QCString anchor() const; bool isEmbeddedInOuterScope() const; - SrcLangExt getLanguage() const; - bool isSimple() const; + const ClassList *taggedInnerClasses() const; + ClassDef *tagLessReference() const; + //----------------------------------------------------------------------------------- // --- setters ---- //----------------------------------------------------------------------------------- @@ -293,7 +294,6 @@ class ClassDef : public Definition void addUsedClass(ClassDef *cd,const char *accessName,Protection prot); void addUsedByClass(ClassDef *cd,const char *accessName,Protection prot); void setIsStatic(bool b); - void setLanguage(SrcLangExt lang); void setCompoundType(CompoundType t); void setClassName(const char *name); @@ -306,6 +306,9 @@ class ClassDef : public Definition void setCategoryOf(ClassDef *cd); void setUsedOnly(bool b); + void addTaggedInnerClass(ClassDef *cd); + void setTagLessReference(ClassDef *cd); + //----------------------------------------------------------------------------------- // --- actions ---- //----------------------------------------------------------------------------------- @@ -328,6 +331,7 @@ class ClassDef : public Definition void writeInlineDocumentation(OutputList &ol); void writeDeclarationLink(OutputList &ol,bool &found, const char *header,bool localNames); + void removeMemberFromLists(MemberDef *md); bool visited; diff --git a/src/classlist.cpp b/src/classlist.cpp index bb6ab73..cb52541 100644 --- a/src/classlist.cpp +++ b/src/classlist.cpp @@ -36,7 +36,7 @@ static int compItems(void *item1,void *item2) ClassDef *c1=(ClassDef *)item1; ClassDef *c2=(ClassDef *)item2; static bool b = Config_getBool("SORT_BY_SCOPE_NAME"); - //printf("compItems: %d %s<->%s\n",b,c1->qualifiedName().data(),c2->qualifiedName().data()); + //printf("compItems: %d %s<->%s\n",b,c1->name().data(),c2->name().data()); if (b) { return stricmp(c1->name(), @@ -115,7 +115,7 @@ void ClassSDict::writeDeclaration(OutputList &ol,const ClassDef::CompoundType *f } } -void ClassSDict::writeDocumentation(OutputList &ol,Definition *container) +void ClassSDict::writeDocumentation(OutputList &ol,Definition * container) { static bool fortranOpt = Config_getBool("OPTIMIZE_FOR_FORTRAN"); @@ -131,14 +131,19 @@ void ClassSDict::writeDocumentation(OutputList &ol,Definition *container) ClassDef *cd=0; for (sdi.toFirst();(cd=sdi.current());++sdi) { - //printf("%s:writeDocumentation() %p=%p embedded=%d\n", - // cd->name().data(),container,cd->getOuterScope(),cd->isEmbeddedInOuterScope()); + //printf("%s:writeDocumentation() %p embedded=%d container=%p\n", + // cd->name().data(),cd->getOuterScope(),cd->isEmbeddedInOuterScope(), + // container); - if (cd->name().find('@')==-1 && cd->isEmbeddedInOuterScope() && - (container==0 || // no container -> used for groups - cd->getOuterScope()==container || // correct container -> used for namespaces and classes - (container->definitionType()==Definition::TypeFile && cd->getOuterScope()==Doxygen::globalScope && cd->partOfGroups()==0) // non grouped class with file scope -> used for files - ) + if (cd->name().find('@')==-1 && + cd->isLinkableInProject() && + cd->isEmbeddedInOuterScope() && + (container==0 || cd->partOfGroups()==0) // if container==0 -> show as part of the group docs, otherwise only show if not part of a group + //&& + //(container==0 || // no container -> used for groups + // cd->getOuterScope()==container || // correct container -> used for namespaces and classes + // (container->definitionType()==Definition::TypeFile && cd->getOuterScope()==Doxygen::globalScope && cd->partOfGroups()==0) // non grouped class with file scope -> used for files + //) ) { if (!found) diff --git a/src/cmdmapper.cpp b/src/cmdmapper.cpp index eac4657..3c21a75 100644 --- a/src/cmdmapper.cpp +++ b/src/cmdmapper.cpp @@ -34,6 +34,7 @@ CommandMap cmdMap[] = { "copydoc", CMD_COPYDOC }, { "copybrief", CMD_COPYBRIEF }, { "copydetails", CMD_COPYDETAILS }, + { "copyright", CMD_COPYRIGHT }, { "date", CMD_DATE }, { "dontinclude", CMD_DONTINCLUDE }, { "dotfile", CMD_DOTFILE }, @@ -66,7 +67,6 @@ CommandMap cmdMap[] = { "param", CMD_PARAM }, { "post", CMD_POST }, { "pre", CMD_PRE }, - { "copyright", CMD_COPYRIGHT }, { "ref", CMD_REF }, { "refitem", CMD_SECREFITEM }, { "remark", CMD_REMARK }, @@ -78,6 +78,7 @@ CommandMap cmdMap[] = { "sa", CMD_SA }, { "secreflist", CMD_SECREFLIST }, { "section", CMD_SECTION }, + { "snippet", CMD_SNIPPET }, { "subpage", CMD_SUBPAGE }, { "subsection", CMD_SUBSECTION }, { "subsubsection", CMD_SUBSUBSECTION }, diff --git a/src/cmdmapper.h b/src/cmdmapper.h index 75227ab..6a62546 100644 --- a/src/cmdmapper.h +++ b/src/cmdmapper.h @@ -118,6 +118,7 @@ enum CommandType CMD_DCOLON = 84, CMD_COPYRIGHT = 85 | SIMPLESECT_BIT, CMD_CITE = 86, + CMD_SNIPPET = 87 }; enum HtmlTagType diff --git a/src/code.l b/src/code.l index 733be82..0f8506a 100644 --- a/src/code.l +++ b/src/code.l @@ -1264,6 +1264,7 @@ static void generateFunctionLink(CodeOutputInterface &ol,char *funcName) int len=2; int i=locFunc.findRev("::"); if (i==-1) i=locFunc.findRev("."),len=1; + if (i==-1) i=locFunc.findRev("\\"),len=1; // for PHP if (i>0) { if (locScope.isEmpty()) @@ -1715,12 +1716,14 @@ static int yyread(char *buf,int max_size) B [ \t] BN [ \t\n\r] ID "$"?[a-z_A-Z\x80-\xFF][a-z_A-Z0-9\x80-\xFF]* -SCOPENAME "$"?(({ID}?{BN}*"::"{BN}*)*)((~{BN}*)?{ID}) +SCOPESEP ("::"|"\\"){BN}* +SCOPEPRE ({SCOPESEP}{ID}{BN}*)*{SCOPESEP} +SCOPENAME {SCOPEPRE}?(("~"{BN}*)?{ID}) TEMPLIST "<"[^\"\}\{\(\)\/\n\>]*">" -SCOPETNAME ((({ID}{TEMPLIST}?){BN}*"::"{BN}*)*)((~{BN}*)?{ID}) -SCOPEPREFIX ({ID}{TEMPLIST}?{BN}*"::"{BN}*)+ +SCOPETNAME (((({ID}{TEMPLIST}?){BN}*)?("::"|"\\"){BN}*)*)((~{BN}*)?{ID}) +SCOPEPREFIX ({ID}{TEMPLIST}?{BN}*("::"|"\\"){BN}*)+ KEYWORD_OBJC ("@public"|"@private"|"@protected"|"@class"|"@implementation"|"@interface"|"@end"|"@selector"|"@protocol"|"@optional"|"@required"|"@throw"|"@synthesize"|"@property") -KEYWORD ("asm"|"__assume"|"auto"|"class"|"const"|"delete"|"enum"|"explicit"|"extern"|"false"|"friend"|"gcnew"|"gcroot"|"get"|"inline"|"internal"|"mutable"|"namespace"|"new"|"nullptr"|"override"|"operator"|"pin_ptr"|"private"|"protected"|"public"|"raise"|"register"|"remove"|"self"|"set"|"sizeof"|"static"|"struct"|"__super"|"template"|"generic"|"this"|"true"|"typedef"|"typeid"|"typename"|"union"|"using"|"virtual"|"volatile"|"abstract"|"final"|"import"|"synchronized"|"transient"|{KEYWORD_OBJC}) +KEYWORD ("asm"|"__assume"|"auto"|"class"|"const"|"delete"|"enum"|"explicit"|"extern"|"false"|"friend"|"gcnew"|"gcroot"|"get"|"inline"|"internal"|"mutable"|"namespace"|"new"|"nullptr"|"override"|"operator"|"pin_ptr"|"private"|"protected"|"public"|"raise"|"register"|"remove"|"self"|"set"|"sizeof"|"static"|"struct"|"__super"|"function"|"template"|"generic"|"this"|"true"|"typedef"|"typeid"|"typename"|"union"|"using"|"virtual"|"volatile"|"abstract"|"final"|"import"|"synchronized"|"transient"|{KEYWORD_OBJC}) FLOWKW ("break"|"case"|"catch"|"continue"|"default"|"do"|"else"|"finally"|"for"|"foreach"|"for each"|"goto"|"if"|"return"|"switch"|"throw"|"throws"|"try"|"while"|"@try"|"@catch"|"@finally") TYPEKW ("bool"|"char"|"double"|"float"|"int"|"long"|"object"|"short"|"signed"|"unsigned"|"void"|"wchar_t"|"size_t"|"boolean"|"id"|"SEL"|"string") CASTKW ("const_cast"|"dynamic_cast"|"reinterpret_cast"|"static_cast") @@ -2062,9 +2065,14 @@ OPERATOR {ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP} generateClassOrGlobalLink(*g_code,yytext); BEGIN( ClassVar ); } +{ID}("\\"{ID})* { // PHP namespace + g_curClassName=substitute(yytext,"\\","::"); + addType(); + generateClassOrGlobalLink(*g_code,yytext); + BEGIN( ClassVar ); + } {ID}("."{ID})* { - g_curClassName=yytext; - g_curClassName=substitute(g_curClassName,".","::"); + g_curClassName=substitute(yytext,".","::"); //printf("found package: %s\n",g_curClassName.data()); addType(); codifyLines(yytext); @@ -2124,7 +2132,7 @@ OPERATOR {ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP} //fprintf(stderr,"***** g_curClassName=%s\n",g_curClassName.data()); if (getResolvedClass(g_currentDefinition,g_sourceFileDef,g_curClassName)==0) { - //printf("Adding new class %s\n",g_curClassName.data()); + //fprintf(stderr,"Adding new class %s\n",g_curClassName.data()); ClassDef *ncd=new ClassDef("",1, g_curClassName,ClassDef::Class,0,0,FALSE); g_codeClassSDict->append(g_curClassName,ncd); @@ -2406,11 +2414,9 @@ OPERATOR {ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP} addType(); g_name=varname; } -{SCOPETNAME}/{BN}*"(" { // a() or c::a() or t::a() +{SCOPETNAME}/{BN}*"(" { // a() or c::a() or t::a() or A\B\foo() addType(); generateFunctionLink(*g_code,yytext); - //printf("---> g_classScope=%s\n",g_classScope.data()); - //g_theVarContext.addVariable(g_type,yytext); g_bracketCount=0; g_args.resize(0); g_name+=yytext; @@ -2850,6 +2856,7 @@ OPERATOR {ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP} //g_theCallContext.popScope(); g_parmType.resize(0);g_parmName.resize(0); int index = g_name.findRev("::"); + //fprintf(stderr,"g_name=%s\n",g_name.data()); if (index!=-1) { QCString scope = g_name.left(index); diff --git a/src/commentcnv.l b/src/commentcnv.l index ac72394..5408f68 100644 --- a/src/commentcnv.l +++ b/src/commentcnv.l @@ -300,7 +300,7 @@ void replaceComment(int offset); } } "!>" { - if (g_lang!=SrcLangExt_F90) + if (g_lang!=SrcLangExt_Fortran) { REJECT; } @@ -384,7 +384,7 @@ void replaceComment(int offset); } } "!>" { - if (g_lang!=SrcLangExt_F90) + if (g_lang!=SrcLangExt_Fortran) { REJECT; } @@ -587,7 +587,7 @@ void replaceComment(int offset); } } "\n"/[ \t]*[^!] { /* end of Fortran comment */ - if (g_lang!=SrcLangExt_F90) + if (g_lang!=SrcLangExt_Fortran) { REJECT; } @@ -690,7 +690,7 @@ void replaceComment(int offset); //printf("** Adding start of comment!\n"); if (g_lang!=SrcLangExt_Python && g_lang!=SrcLangExt_VHDL && - g_lang!=SrcLangExt_F90) + g_lang!=SrcLangExt_Fortran) { ADDCHAR('/'); ADDCHAR('*'); @@ -709,7 +709,7 @@ void replaceComment(int offset); //printf("** Adding terminator for comment!\n"); if (g_lang!=SrcLangExt_Python && g_lang!=SrcLangExt_VHDL && - g_lang!=SrcLangExt_F90) + g_lang!=SrcLangExt_Fortran) { ADDCHAR('*'); ADDCHAR('/'); diff --git a/src/config.l b/src/config.l index f5e9ee0..7d3f633 100644 --- a/src/config.l +++ b/src/config.l @@ -1325,6 +1325,7 @@ void Config::check() filePatternList.append("*.for"); filePatternList.append("*.vhd"); filePatternList.append("*.vhdl"); + filePatternList.append("*.tcl"); if (portable_fileSystemIsCaseSensitive()) { // unix => case sensitive match => also include useful uppercase versions @@ -1346,6 +1347,7 @@ void Config::check() filePatternList.append("*.F"); filePatternList.append("*.VHD"); filePatternList.append("*.VHDL"); + filePatternList.append("*.TCL"); } } diff --git a/src/definition.cpp b/src/definition.cpp index 0851c9b..a8a7300 100644 --- a/src/definition.cpp +++ b/src/definition.cpp @@ -78,6 +78,8 @@ class DefinitionImpl QCString defFileName; int defLine; QCString defFileExt; + + SrcLangExt lang; }; DefinitionImpl::DefinitionImpl() @@ -135,6 +137,7 @@ void DefinitionImpl::init(const char *df,int dl, xrefListItems = 0; hidden = FALSE; isArtificial = FALSE; + lang = SrcLangExt_Unknown; } //----------------------------------------------------------------------------------------- @@ -540,13 +543,13 @@ void Definition::setInbodyDocumentation(const char *d,const char *inbodyFile,int static bool readCodeFragment(const char *fileName, int &startLine,int &endLine,QCString &result) { - static bool vhdlOpt = Config_getBool("OPTIMIZE_OUTPUT_VHDL"); static bool filterSourceFiles = Config_getBool("FILTER_SOURCE_FILES"); //printf("readCodeFragment(%s,%d,%d)\n",fileName,startLine,endLine); if (fileName==0 || fileName[0]==0) return FALSE; // not a valid file name QCString filter = getFileFilter(fileName,TRUE); FILE *f=0; bool usePipe = !filter.isEmpty() && filterSourceFiles; + SrcLangExt lang = getLanguageFromFileName(fileName); if (!usePipe) // no filter given or wanted { f = portable_fopen(fileName,"r"); @@ -557,7 +560,11 @@ static bool readCodeFragment(const char *fileName, Debug::print(Debug::ExtCmd,0,"Executing popen(`%s`)\n",cmd.data()); f = portable_popen(cmd,"r"); } - bool found=vhdlOpt; // for VHDL no bracket search is possible + bool found = lang==SrcLangExt_VHDL || + lang==SrcLangExt_Tcl || + lang==SrcLangExt_Python || + lang==SrcLangExt_Fortran; + // for VHDL, TCL, Python, and Fortran no bracket search is possible if (f) { int c=0; @@ -913,14 +920,7 @@ void Definition::_writeSourceRefList(OutputList &ol,const char *scopeName, //printf("class=%p scope=%s scopeName=%s\n",md->getClassDef(),scope.data(),scopeName); if (!scope.isEmpty() && scope!=scopeName) { - if (Config_getBool("OPTIMIZE_OUTPUT_JAVA")) - { - name.prepend(scope+"."); - } - else - { - name.prepend(scope+"::"); - } + name.prepend(scope+getLanguageSpecificSeparator(m_impl->lang)); } if (!md->isObjCMethod() && (md->isFunction() || md->isSlot() || @@ -1557,6 +1557,11 @@ void Definition::setReference(const char *r) m_impl->ref=r; } +SrcLangExt Definition::getLanguage() const +{ + return m_impl->lang; +} + void Definition::_setSymbolName(const QCString &name) { m_symbolName=name; @@ -1584,6 +1589,10 @@ void Definition::makeResident() const { } +void Definition::setLanguage(SrcLangExt lang) +{ + m_impl->lang=lang; +} void Definition::flushToDisk() const { @@ -1610,6 +1619,7 @@ void Definition::flushToDisk() const marshalQCString (Doxygen::symbolStorage,m_impl->defFileName); marshalInt (Doxygen::symbolStorage,m_impl->defLine); marshalQCString (Doxygen::symbolStorage,m_impl->defFileExt); + marshalInt (Doxygen::symbolStorage,(int)m_impl->lang); marshalUInt(Doxygen::symbolStorage,END_MARKER); delete that->m_impl; that->m_impl = 0; @@ -1642,6 +1652,7 @@ void Definition::loadFromDisk() const m_impl->defFileName = unmarshalQCString (Doxygen::symbolStorage); m_impl->defLine = unmarshalInt (Doxygen::symbolStorage); m_impl->defFileExt = unmarshalQCString (Doxygen::symbolStorage); + m_impl->lang = (SrcLangExt)unmarshalInt(Doxygen::symbolStorage); marker = unmarshalUInt(Doxygen::symbolStorage); assert(marker==END_MARKER); } diff --git a/src/definition.h b/src/definition.h index 46b81a0..38a11b2 100644 --- a/src/definition.h +++ b/src/definition.h @@ -24,6 +24,7 @@ #include #include "lockingptr.h" +#include "util.h" class FileDef; class OutputList; @@ -240,6 +241,9 @@ class Definition : public DefinitionIntf, public LockableObj */ FileDef *getBodyDef(); + /** Returns the programming language this definition was written in. */ + SrcLangExt getLanguage() const; + LockingPtr partOfGroups() const; LockingPtr< QList > xrefListItems() const; @@ -250,6 +254,7 @@ class Definition : public DefinitionIntf, public LockableObj LockingPtr getReferencesMembers() const; LockingPtr getReferencedByMembers() const; + //----------------------------------------------------------------------------------- // ---- setters ----- //----------------------------------------------------------------------------------- @@ -293,6 +298,7 @@ class Definition : public DefinitionIntf, public LockableObj virtual void setHidden(bool b); void setArtificial(bool b); + void setLanguage(SrcLangExt lang); //----------------------------------------------------------------------------------- // --- actions ---- diff --git a/src/docparser.cpp b/src/docparser.cpp index ee2a1c0..a1ad75c 100644 --- a/src/docparser.cpp +++ b/src/docparser.cpp @@ -332,6 +332,7 @@ static void checkArgumentName(const QCString &name,bool isParam) LockingPtr al=g_memberDef->isDocsForDefinition() ? g_memberDef->argumentList() : g_memberDef->declArgumentList(); + SrcLangExt lang = g_memberDef->getLanguage(); //printf("isDocsForDefinition()=%d\n",g_memberDef->isDocsForDefinition()); if (al==0) return; // no argument list @@ -340,6 +341,7 @@ static void checkArgumentName(const QCString &name,bool isParam) while ((i=re.match(name,p,&l))!=-1) // to handle @param x,y { QCString aName=name.mid(i,l); + if (lang==SrcLangExt_Fortran) aName=aName.lower(); //printf("aName=`%s'\n",aName.data()); ArgumentListIterator ali(*al); Argument *a; @@ -347,6 +349,7 @@ static void checkArgumentName(const QCString &name,bool isParam) for (ali.toFirst();(a=ali.current());++ali) { QCString argName = g_memberDef->isDefine() ? a->type : a->name; + if (lang==SrcLangExt_Fortran) argName=argName.lower(); argName=argName.stripWhiteSpace(); //printf("argName=`%s'\n",argName.data()); if (argName.right(3)=="...") argName=argName.left(argName.length()-3); @@ -399,6 +402,7 @@ static void checkUndocumentedParams() LockingPtr al=g_memberDef->isDocsForDefinition() ? g_memberDef->argumentList() : g_memberDef->declArgumentList(); + SrcLangExt lang = g_memberDef->getLanguage(); if (al!=0) { ArgumentListIterator ali(*al); @@ -407,9 +411,10 @@ static void checkUndocumentedParams() for (ali.toFirst();(a=ali.current());++ali) { QCString argName = g_memberDef->isDefine() ? a->type : a->name; + if (lang==SrcLangExt_Fortran) argName = argName.lower(); argName=argName.stripWhiteSpace(); if (argName.right(3)=="...") argName=argName.left(argName.length()-3); - if (getLanguageFromFileName(g_memberDef->getDefFileName())==SrcLangExt_Python && argName=="self") + if (g_memberDef->getLanguage()==SrcLangExt_Python && argName=="self") { // allow undocumented self parameter for Python } @@ -430,8 +435,9 @@ static void checkUndocumentedParams() for (ali.toFirst();(a=ali.current());++ali) { QCString argName = g_memberDef->isDefine() ? a->type : a->name; + if (lang==SrcLangExt_Fortran) argName = argName.lower(); argName=argName.stripWhiteSpace(); - if (getLanguageFromFileName(g_memberDef->getDefFileName())==SrcLangExt_Python && argName=="self") + if (g_memberDef->getLanguage()==SrcLangExt_Python && argName=="self") { // allow undocumented self parameter for Python } @@ -477,7 +483,7 @@ static void detectNoDocumentedParams() LockingPtr al = g_memberDef->argumentList(); LockingPtr declAl = g_memberDef->declArgumentList(); QCString returnType = g_memberDef->typeString(); - bool isPython = getLanguageFromFileName(g_memberDef->getDefFileName())==SrcLangExt_Python; + bool isPython = g_memberDef->getLanguage()==SrcLangExt_Python; if (!g_memberDef->hasDocumentedParams() && g_hasParamCommand) @@ -1005,7 +1011,7 @@ static void handleLinkedWord(DocNode *parent,QList &children) { Definition *compound=0; MemberDef *member=0; - QCString name = linkToText(g_token->name,TRUE); + QCString name = linkToText(SrcLangExt_Unknown,g_token->name,TRUE); int len = g_token->name.length(); ClassDef *cd=0; bool ambig; @@ -1762,6 +1768,17 @@ void DocInclude::parse() case HtmlInclude: readTextFileByName(m_file,m_text); break; + case Snippet: + readTextFileByName(m_file,m_text); + // check here for the existance of the blockId inside the file, so we + // only generate the warning once. + int count; + if (!m_blockId.isEmpty() && (count=m_text.contains(m_blockId.data()))!=2) + { + warn_doc_error(g_fileName,doctokenizerYYlineno,"warning: block marked with %s for \\snippet should appear twice in file %s, found it %d times\n", + m_blockId.data(),m_file.data(),count); + } + break; } } @@ -2285,7 +2302,7 @@ DocRef::DocRef(DocNode *parent,const QCString &target,const QCString &context) : bool isFile = compound ? (compound->definitionType()==Definition::TypeFile ? TRUE : FALSE) : FALSE; - m_text = linkToText(target,isFile); + m_text = linkToText(compound?compound->getLanguage():SrcLangExt_Unknown,target,isFile); m_anchor = anchor; if (compound && compound->isLinkable()) // ref to compound { @@ -2318,7 +2335,7 @@ DocRef::DocRef(DocNode *parent,const QCString &target,const QCString &context) : return; } } - m_text = linkToText(target,FALSE); + m_text = linkToText(SrcLangExt_Unknown,target,FALSE); warn_doc_error(g_fileName,doctokenizerYYlineno,"warning: unable to resolve reference to `%s' for \\ref command", qPrint(target)); } @@ -2420,7 +2437,7 @@ DocCite::DocCite(DocNode *parent,const QCString &target,const QCString &) //cont // m_text.data(),m_ref.data(),m_file.data(),m_anchor.data()); return; } - m_text = linkToText(target,FALSE); + m_text = linkToText(SrcLangExt_Unknown,target,FALSE); warn_doc_error(g_fileName,doctokenizerYYlineno,"warning: unable to resolve reference to `%s' for \\cite command", qPrint(target)); } @@ -3851,10 +3868,21 @@ int DocHtmlList::parse() { // ok, we can go on. } + else if (((m_type==Unordered && tagId==HTML_UL) || + (m_type==Ordered && tagId==HTML_OL) + ) && g_token->endTag + ) // found empty list + { + // add dummy item to obtain valid HTML + m_children.append(new DocHtmlListItem(this,HtmlAttribList(),1)); + warn_doc_error(g_fileName,doctokenizerYYlineno,"Warning: empty list!"); + retval = RetVal_EndList; + goto endlist; + } else // found some other tag { warn_doc_error(g_fileName,doctokenizerYYlineno,"warning: expected
  • tag but " - "found <%s> instead!",qPrint(g_token->name)); + "found <%s%s> instead!",g_token->endTag?"/":"",qPrint(g_token->name)); doctokenizerYYpushBackHtmlTag(g_token->name); goto endlist; } @@ -4744,7 +4772,22 @@ void DocPara::handleInclude(const QCString &cmdName,DocInclude::Type t) tokToString(tok),qPrint(cmdName)); return; } - DocInclude *inc = new DocInclude(this,g_token->name,g_context,t,g_isExample,g_exampleName); + QCString fileName = g_token->name; + QCString blockId; + if (t==DocInclude::Snippet) + { + doctokenizerYYsetStateSnippet(); + tok=doctokenizerYYlex(); + doctokenizerYYsetStatePara(); + if (tok!=TK_WORD) + { + warn_doc_error(g_fileName,doctokenizerYYlineno,"warning: expected block identifier, but found token %s instead while parsing the %s command", + tokToString(tok),qPrint(cmdName)); + return; + } + blockId = "["+g_token->name+"]"; + } + DocInclude *inc = new DocInclude(this,fileName,g_context,t,g_isExample,g_exampleName,blockId); m_children.append(inc); inc->parse(); } @@ -5150,6 +5193,9 @@ int DocPara::handleCommand(const QCString &cmdName) case CMD_VERBINCLUDE: handleInclude(cmdName,DocInclude::VerbInclude); break; + case CMD_SNIPPET: + handleInclude(cmdName,DocInclude::Snippet); + break; case CMD_SKIP: handleIncludeOperator(cmdName,DocIncOperator::Skip); break; @@ -6440,7 +6486,7 @@ DocNode *validatingParseDoc(const char *fileName,int startLine, //g_token = new TokenInfo; // store parser state so we can re-enter this function if needed - bool fortranOpt = Config_getBool("OPTIMIZE_FOR_FORTRAN"); + //bool fortranOpt = Config_getBool("OPTIMIZE_FOR_FORTRAN"); docParserPushContext(); if (ctx && ctx!=Doxygen::globalScope && @@ -6471,7 +6517,9 @@ DocNode *validatingParseDoc(const char *fileName,int startLine, { g_searchUrl=md->getOutputFileBase(); Doxygen::searchIndex->setCurrentDoc( - (fortranOpt?theTranslator->trSubprogram(TRUE,TRUE):theTranslator->trMember(TRUE,TRUE))+" "+md->qualifiedName(), + (md->getLanguage()==SrcLangExt_Fortran ? + theTranslator->trSubprogram(TRUE,TRUE): + theTranslator->trMember(TRUE,TRUE))+" "+md->qualifiedName(), g_searchUrl, md->anchor()); } @@ -6479,10 +6527,14 @@ DocNode *validatingParseDoc(const char *fileName,int startLine, { g_searchUrl=ctx->getOutputFileBase(); QCString name = ctx->qualifiedName(); - if (Config_getBool("OPTIMIZE_OUTPUT_JAVA")) + + SrcLangExt lang = ctx->getLanguage(); + QCString sep = getLanguageSpecificSeparator(lang); + if (sep!="::") { - name = substitute(name,"::","."); + name = substitute(name,"::",sep); } + switch (ctx->definitionType()) { case Definition::TypePage: @@ -6506,15 +6558,15 @@ DocNode *validatingParseDoc(const char *fileName,int startLine, break; case Definition::TypeNamespace: { - if (Config_getBool("OPTIMIZE_OUTPUT_JAVA")) + if (lang==SrcLangExt_Java || lang==SrcLangExt_CSharp) { name = theTranslator->trPackage(name); } - else if(fortranOpt) + else if (lang==SrcLangExt_Fortran) { name.prepend(theTranslator->trModule(TRUE,TRUE)+" "); } - else + else { name.prepend(theTranslator->trNamespace(TRUE,TRUE)+" "); } @@ -6601,7 +6653,7 @@ DocNode *validatingParseDoc(const char *fileName,int startLine, return root; } -DocNode *validatingParseText(const char *input,bool forceBreaks) +DocNode *validatingParseText(const char *input) { // store parser state so we can re-enter this function if needed docParserPushContext(); @@ -6629,7 +6681,7 @@ DocNode *validatingParseText(const char *input,bool forceBreaks) g_paramsFound.clear(); g_searchUrl=""; - DocText *txt = new DocText(forceBreaks); + DocText *txt = new DocText; if (input) { diff --git a/src/docparser.h b/src/docparser.h index bdd40b0..f679bfb 100644 --- a/src/docparser.h +++ b/src/docparser.h @@ -69,7 +69,7 @@ DocNode *validatingParseDoc(const char *fileName,int startLine, /*! Main entry point for parsing simple text fragments. These * fragments are limited to words, whitespace and symbols. */ -DocNode *validatingParseText(const char *input,bool forceBreaks=FALSE); +DocNode *validatingParseText(const char *input); /*! Searches for section and anchor commands in the input */ void docFindSections(const char *input, @@ -396,35 +396,39 @@ class DocVerbatim : public DocNode class DocInclude : public DocNode { public: - enum Type { Include, DontInclude, VerbInclude, HtmlInclude, IncWithLines }; + enum Type { Include, DontInclude, VerbInclude, HtmlInclude, IncWithLines, Snippet }; DocInclude(DocNode *parent,const QCString &file, const QCString context, Type t, - bool isExample,const QCString exampleFile) : + bool isExample,const QCString exampleFile, + const QCString blockId) : m_file(file), m_context(context), m_type(t), - m_isExample(isExample), m_exampleFile(exampleFile) { m_parent = parent; } - Kind kind() const { return Kind_Include; } + m_isExample(isExample), m_exampleFile(exampleFile), + m_blockId(blockId) { m_parent = parent; } + Kind kind() const { return Kind_Include; } QCString file() const { return m_file; } QCString extension() const { int i=m_file.findRev('.'); - if (i!=-1) - return m_file.right(m_file.length()-i); - else - return ""; - } - Type type() const { return m_type; } + if (i!=-1) + return m_file.right(m_file.length()-i); + else + return ""; + } + Type type() const { return m_type; } QCString text() const { return m_text; } QCString context() const { return m_context; } - bool isExample() const { return m_isExample; } + QCString blockId() const { return m_blockId; } + bool isExample() const { return m_isExample; } QCString exampleFile() const { return m_exampleFile; } - void accept(DocVisitor *v) { v->visit(this); } + void accept(DocVisitor *v) { v->visit(this); } void parse(); private: QCString m_file; QCString m_context; QCString m_text; - Type m_type; - bool m_isExample; + Type m_type; + bool m_isExample; QCString m_exampleFile; + QCString m_blockId; }; /*! @brief Node representing a include/dontinclude operator block */ @@ -1218,14 +1222,10 @@ class DocHtmlTable : public CompAccept, public DocNode class DocText : public CompAccept, public DocNode { public: - DocText(bool forceBreaks) : m_forceBreaks(forceBreaks) {} + DocText() {} Kind kind() const { return Kind_Text; } void accept(DocVisitor *v) { CompAccept::accept(this,v); } void parse(); - bool forceBreaks() const { return m_forceBreaks; } - - private: - bool m_forceBreaks; }; /*! @brief Root node of documentation tree */ diff --git a/src/docsets.cpp b/src/docsets.cpp index 17f8ca8..7d7dd2e 100644 --- a/src/docsets.cpp +++ b/src/docsets.cpp @@ -254,7 +254,14 @@ void DocSets::addIndexItem(Definition *context,MemberDef *md,const char *) // determine language QCString lang; SrcLangExt langExt = SrcLangExt_Cpp; - if (fd) langExt = getLanguageFromFileName(fd->name()); + if (md) + { + langExt = md->getLanguage(); + } + else if (context) + { + langExt = context->getLanguage(); + } switch (langExt) { case SrcLangExt_Cpp: @@ -277,9 +284,10 @@ void DocSets::addIndexItem(Definition *context,MemberDef *md,const char *) case SrcLangExt_Java: lang="java"; break; // Java case SrcLangExt_JS: lang="javascript"; break; // Javascript case SrcLangExt_Python: lang="python"; break; // Python - case SrcLangExt_F90: lang="fortran"; break; // Fortran + case SrcLangExt_Fortran: lang="fortran"; break; // Fortran case SrcLangExt_VHDL: lang="vhdl"; break; // VHDL case SrcLangExt_XML: lang="xml"; break; // DBUS XML + case SrcLangExt_Tcl: lang="tcl"; break; // Tcl case SrcLangExt_Unknown: lang="unknown"; break; // should not happen! } diff --git a/src/doctokenizer.h b/src/doctokenizer.h index 1ea6570..5c352ca 100644 --- a/src/doctokenizer.h +++ b/src/doctokenizer.h @@ -149,5 +149,6 @@ void doctokenizerYYsetStateSkipTitle(); void doctokenizerYYsetStateAnchor(); void doctokenizerYYsetInsidePre(bool b); void doctokenizerYYpushBackHtmlTag(const char *tag); +void doctokenizerYYsetStateSnippet(); #endif diff --git a/src/doctokenizer.l b/src/doctokenizer.l index 104b75b..f68fd40 100644 --- a/src/doctokenizer.l +++ b/src/doctokenizer.l @@ -379,6 +379,7 @@ REFWORD {LABELID}|{REFWORD2}|{REFWORD3} %x St_Text %x St_SkipTitle %x St_Anchor +%x St_Snippet %x St_Sections %s St_SecLabel1 @@ -961,6 +962,13 @@ REFWORD {LABELID}|{REFWORD2}|{REFWORD3} . { warn(g_fileName,yylineno,"warning: Unexpected character `%s' while looking for section label or title",yytext); } + +[^\n]+ | +[^\n]*\n { + g_token->name = yytext; + g_token->name = g_token->name.stripWhiteSpace(); + return TK_WORD; + } /* Generic rules that work for all states */ <*>\n { @@ -1126,6 +1134,11 @@ void doctokenizerYYsetStateAnchor() BEGIN(St_Anchor); } +void doctokenizerYYsetStateSnippet() +{ + BEGIN(St_Snippet); +} + void doctokenizerYYcleanup() { yy_delete_buffer( YY_CURRENT_BUFFER ); diff --git a/src/dot.cpp b/src/dot.cpp index 8609efa..27e559f 100644 --- a/src/dot.cpp +++ b/src/dot.cpp @@ -609,11 +609,14 @@ static void checkDotResult(const QCString &imgName) { if (Config_getEnum("DOT_IMAGE_FORMAT")=="png") { - QFile f(imgName); - if (f.open(IO_ReadOnly)) + //QFile f(imgName); + FILE *f = fopen(imgName,"rb"); + //if (f.open(IO_ReadOnly)) + if (f) { char data[4]; - if (f.readBlock(data,4)==4) + if (fread(data,1,4,f)==4) + //if (f.readBlock(data,4)==4) { if (!(data[1]=='P' && data[2]=='N' && data[3]=='G')) { @@ -628,6 +631,7 @@ static void checkDotResult(const QCString &imgName) { err("error: Could not read image `%s' generated by dot!\n",imgName.data()); } + fclose(f); } else { @@ -757,8 +761,8 @@ void DotRunner::addPostProcessing(const char *cmd,const char *args) bool DotRunner::run() { int exitCode=0; - static QCString dotExe = Config_getString("DOT_PATH")+"dot"; - static bool multiTargets = Config_getBool("DOT_MULTI_TARGETS"); + QCString dotExe = Config_getString("DOT_PATH")+"dot"; + bool multiTargets = Config_getBool("DOT_MULTI_TARGETS"); QCString dotArgs; QListIterator li(m_jobs); QCString *s; @@ -1139,21 +1143,24 @@ DotManager::DotManager() : m_dotMaps(1007) m_queue = new DotRunnerQueue; int i; int numThreads = QMIN(32,Config_getInt("DOT_NUM_THREADS")); - if (numThreads==0) numThreads = QMAX(1,QThread::idealThreadCount()+1); - for (i=0;istart(); - if (thread->isRunning()) + if (numThreads==0) numThreads = QMAX(2,QThread::idealThreadCount()+1); + for (i=0;istart(); + if (thread->isRunning()) + { + m_workers.append(thread); + } + else // no more threads available! + { + delete thread; + } } + ASSERT(m_workers.count()>0); } - ASSERT(m_workers.count()>0); } DotManager::~DotManager() @@ -1222,7 +1229,14 @@ bool DotManager::run() uint numDotMaps = m_dotMaps.count(); if (numDotRuns+numDotMaps>1) { - msg("Generating dot graphs using %d parallel threads...\n",QMIN(numDotRuns+numDotMaps,m_workers.count())); + if (m_workers.count()==0) + { + msg("Generating dot graphs in single threaded mode...\n"); + } + else + { + msg("Generating dot graphs using %d parallel threads...\n",QMIN(numDotRuns+numDotMaps,m_workers.count())); + } } int i=1; QListIterator li(m_dotRuns); @@ -1246,41 +1260,53 @@ bool DotManager::run() portable_sysTimerStart(); // fill work queue with dot operations DotRunner *dr; - for (li.toFirst();(dr=li.current());++li) - { - m_queue->enqueue(dr); - } int prev=1; - // wait for the queue to become empty - while ((i=m_queue->count())>0) + if (m_workers.count()==0) // no threads to work with { - i = numDotRuns - i; - while (i>=prev) + for (li.toFirst();(dr=li.current());++li) { msg("Running dot for graph %d/%d\n",prev,numDotRuns); + dr->run(); prev++; } - portable_sleep(100); } - while ((int)numDotRuns>=prev) + else // use multiple threads to run instances of dot in parallel { - msg("Running dot for graph %d/%d\n",prev,numDotRuns); - prev++; - } - // signal the workers we are done - for (i=0;i<(int)m_workers.count();i++) - { - m_queue->enqueue(0); // add terminator for each worker - } - // wait for the workers to finish - for (i=0;i<(int)m_workers.count();i++) - { - m_workers.at(i)->wait(); - } - // clean up dot files from main thread - for (i=0;i<(int)m_workers.count();i++) - { - m_workers.at(i)->cleanup(); + for (li.toFirst();(dr=li.current());++li) + { + m_queue->enqueue(dr); + } + // wait for the queue to become empty + while ((i=m_queue->count())>0) + { + i = numDotRuns - i; + while (i>=prev) + { + msg("Running dot for graph %d/%d\n",prev,numDotRuns); + prev++; + } + portable_sleep(100); + } + while ((int)numDotRuns>=prev) + { + msg("Running dot for graph %d/%d\n",prev,numDotRuns); + prev++; + } + // signal the workers we are done + for (i=0;i<(int)m_workers.count();i++) + { + m_queue->enqueue(0); // add terminator for each worker + } + // wait for the workers to finish + for (i=0;i<(int)m_workers.count();i++) + { + m_workers.at(i)->wait(); + } + // clean up dot files from main thread + for (i=0;i<(int)m_workers.count();i++) + { + m_workers.at(i)->cleanup(); + } } portable_sysTimerStop(); if (setPath) @@ -1572,7 +1598,7 @@ void DotNode::writeBox(FTextStream &t, writeBoxMemberList(t,'-',m_classDef->getMemberList(MemberList::priStaticMethods),m_classDef,TRUE); writeBoxMemberList(t,'-',m_classDef->getMemberList(MemberList::priSlots),m_classDef); } - if (m_classDef->getLanguage()!=SrcLangExt_F90 && + if (m_classDef->getLanguage()!=SrcLangExt_Fortran && m_classDef->getMemberGroupSDict()) { MemberGroupSDict::Iterator mgdi(*m_classDef->getMemberGroupSDict()); @@ -3301,7 +3327,7 @@ void DotCallGraph::buildGraph(DotNode *n,MemberDef *md,int distance) QCString tooltip = rmd->briefDescriptionAsTooltip(); bn = new DotNode( m_curNodeNumber++, - linkToText(name,FALSE), + linkToText(rmd->getLanguage(),name,FALSE), tooltip, uniqueId, 0 //distance @@ -3388,7 +3414,7 @@ DotCallGraph::DotCallGraph(MemberDef *md,bool inverse) name = md->qualifiedName(); } m_startNode = new DotNode(m_curNodeNumber++, - linkToText(name,FALSE), + linkToText(md->getLanguage(),name,FALSE), "", uniqueId.data(), TRUE // root node @@ -3837,8 +3863,11 @@ void writeDotImageMapFromFile(FTextStream &t, if (imgExt=="svg") // vector graphics { - writeSVGFigureLink(t,relPath,inFile,inFile+".svg"); - DotFilePatcher patcher(inFile+".svg"); + //writeSVGFigureLink(t,relPath,inFile,inFile+".svg"); + //DotFilePatcher patcher(inFile+".svg"); + QCString svgName=outDir+"/"+baseName+".svg"; + writeSVGFigureLink(t,relPath,baseName,svgName); + DotFilePatcher patcher(svgName); patcher.addSVGConversion(relPath,TRUE,context,TRUE,graphId); patcher.run(); } diff --git a/src/doxygen.cpp b/src/doxygen.cpp index 9d4b870..f9918ff 100644 --- a/src/doxygen.cpp +++ b/src/doxygen.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include "version.h" #include "doxygen.h" @@ -70,6 +71,7 @@ #include "pyscanner.h" #include "fortranscanner.h" #include "dbusxmlscanner.h" +#include "tclscanner.h" #include "code.h" #include "objcache.h" #include "store.h" @@ -522,6 +524,7 @@ static void buildGroupListFiltered(EntryNav *rootNav,bool additional, bool inclu gd->setInbodyDocumentation( root->inbodyDocs, root->inbodyFile, root->inbodyLine ); gd->addSectionsToDefinition(root->anchors); gd->setRefItems(root->sli); + gd->setLanguage(root->lang); } else { @@ -540,6 +543,7 @@ static void buildGroupListFiltered(EntryNav *rootNav,bool additional, bool inclu gd->addSectionsToDefinition(root->anchors); Doxygen::groupSDict->append(root->name,gd); gd->setRefItems(root->sli); + gd->setLanguage(root->lang); } } @@ -693,11 +697,10 @@ static void buildFileList(EntryNav *rootNav) else { const char *fn = root->fileName.data(); - QCString text; + QCString text(4096); text.sprintf("warning: the name `%s' supplied as " "the second argument in the \\file statement ", - qPrint(root->name) - ); + qPrint(root->name)); if (ambig) // name is ambiguous { text+="matches the following input files:\n"; @@ -1172,30 +1175,6 @@ static void addClassToContext(EntryNav *rootNav) fullName.data(),root->section,root->tArgLists ? (int)root->tArgLists->count() : -1); cd->setDocumentation(root->doc,root->docFile,root->docLine); // copy docs to definition cd->setBriefDescription(root->brief,root->briefFile,root->briefLine); - cd->setLanguage(root->lang); - cd->setHidden(root->hidden); - cd->setArtificial(root->artificial); - cd->setTypeConstraints(root->typeConstr); - //printf("new ClassDef %s tempArgList=%p specScope=%s\n",fullName.data(),root->tArgList,root->scopeSpec.data()); - - ArgumentList *tArgList = - getTemplateArgumentsFromName(fullName,root->tArgLists); - //printf("class %s template args=%s\n",fullName.data(), - // tArgList ? tempArgListToString(tArgList).data() : ""); - cd->setTemplateArguments(tArgList); - cd->setProtection(root->protection); - cd->setIsStatic(root->stat); - - // file definition containing the class cd - cd->setBodySegment(root->bodyLine,root->endBodyLine); - cd->setBodyDef(fd); - - // see if the class is found inside a namespace - //bool found=addNamespace(root,cd); - - - // the empty string test is needed for extract all case - cd->setBriefDescription(root->brief,root->briefFile,root->briefLine); cd->insertUsedFile(root->fileName); // add class to the list @@ -1351,6 +1330,184 @@ void distributeClassGroupRelations() } } +//---------------------------- + +static ClassDef *createTagLessInstance(ClassDef *rootCd,ClassDef *templ,const QCString &fieldName) +{ + QCString fullName = removeAnonymousScopes(templ->name()); + if (fullName.right(2)=="::") fullName=fullName.left(fullName.length()-2); + fullName+="."+fieldName; + ClassDef *cd = new ClassDef(templ->getDefFileName(), + templ->getDefLine(), + fullName, + templ->compoundType()); + cd->setDocumentation(templ->documentation(),templ->docFile(),templ->docLine()); // copy docs to definition + cd->setBriefDescription(templ->briefDescription(),templ->briefFile(),templ->briefLine()); + cd->setLanguage(templ->getLanguage()); + cd->setBodySegment(templ->getStartBodyLine(),templ->getEndBodyLine()); + cd->setBodyDef(templ->getBodyDef()); + cd->setOuterScope(rootCd->getOuterScope()); + if (rootCd->getOuterScope()!=Doxygen::globalScope) + { + rootCd->getOuterScope()->addInnerCompound(cd); + } + FileDef *fd = templ->getFileDef(); + if (fd) + { + cd->setFileDef(fd); + fd->insertClass(cd); + } + LockingPtr groups = rootCd->partOfGroups(); + if ( groups!=0 ) + { + GroupListIterator gli(*groups); + GroupDef *gd; + for (gli.toFirst();(gd=gli.current());++gli) + { + cd->makePartOfGroup(gd); + gd->addClass(cd); + } + } + //cd->insertUsedFile(root->fileName); + //printf("** adding class %s based on %s\n",fullName.data(),templ->name().data()); + Doxygen::classSDict->append(fullName,cd); + + MemberList *ml = templ->getMemberList(MemberList::pubAttribs); + if (ml) + { + MemberListIterator li(*ml); + MemberDef *md; + for (li.toFirst();(md=li.current());++li) + { + //printf(" Member %s type=%s\n",md->name().data(),md->typeString()); + MemberDef *imd = new MemberDef(md->getDefFileName(),md->getDefLine(), + md->typeString(),md->name(),md->argsString(),md->excpString(), + md->protection(),md->virtualness(),md->isStatic(),Member, + md->memberType(), + 0,0); + imd->setMemberClass(cd); + imd->setDocumentation(md->documentation(),md->docFile(),md->docLine()); + imd->setBriefDescription(md->briefDescription(),md->briefFile(),md->briefLine()); + imd->setInbodyDocumentation(md->inbodyDocumentation(),md->inbodyFile(),md->inbodyLine()); + imd->setMemberSpecifiers(md->getMemberSpecifiers()); + imd->setMemberGroupId(md->getMemberGroupId()); + imd->setInitializer(md->initializer()); + imd->setMaxInitLines(md->initializerLines()); + imd->setBitfields(md->bitfieldString()); + imd->setLanguage(md->getLanguage()); + cd->insertMember(imd); + } + } + return cd; +} + +/** Look through the members of class \a cd and its public members. + * If there is a member m of a tag less struct/union, + * then we create a duplicate of the struct/union with the name of the + * member to identify it. + * So if cd has name S, then the tag less struct/union will get name S.m + * Since tag less structs can be nested we need to call this function + * recursively. Later on we need to patch the member types so we keep + * track of the hierarchy of classes we create. + */ +static void processTagLessClasses(ClassDef *rootCd, + ClassDef *cd, + ClassDef *tagParentCd, + const QCString &prefix,int count) +{ + printf("%d: processTagLessClasses %s\n",count,cd->name().data()); + //printf("checking members for %s\n",cd->name().data()); + if (cd->getInnerClasses()) + { + MemberList *ml = cd->getMemberList(MemberList::pubAttribs); + if (ml) + { + MemberListIterator li(*ml); + MemberDef *md; + for (li.toFirst();(md=li.current());++li) + { + QCString type = md->typeString(); + if (type.find("::@")!=-1) // member of tag less struct/union + { + ClassSDict::Iterator it(*cd->getInnerClasses()); + ClassDef *icd; + for (it.toFirst();(icd=it.current());++it) + { + printf(" member %s: type='%s'\n",md->name().data(),type.data()); + //printf(" comparing '%s'<->'%s'\n",type.data(),icd->name().data()); + if (type.find(icd->name())!=-1) // matching tag less struct/union + { + QCString name = md->name(); + if (name.at(0)=='@') name = "__unnamed__"; + if (!prefix.isEmpty()) name.prepend(prefix+"."); + //printf(" found %s for class %s\n",name.data(),cd->name().data()); + ClassDef *ncd = createTagLessInstance(rootCd,icd,name); + processTagLessClasses(rootCd,icd,ncd,name,count+1); + //printf(" addTagged %s to %s\n",ncd->name().data(),cd->name().data()); + tagParentCd->addTaggedInnerClass(ncd); + ncd->setTagLessReference(icd); + + // replace tag-less type for generated/original member + // by newly created class name. + // note the difference between changing cd and tagParentCd. + // for the initial call this is the same pointer, but for + // recursive calls cd is the original tag-less struct (of which + // there is only one instance) and tagParentCd is the newly + // generated tagged struct of which there can be multiple instances! + MemberList *pml = tagParentCd->getMemberList(MemberList::pubAttribs); + if (pml) + { + MemberListIterator pli(*pml); + MemberDef *pmd; + for (pli.toFirst();(pmd=pli.current());++pli) + { + if (pmd->name()==md->name()) + { + pmd->setType(substitute(pmd->typeString(),icd->name(),ncd->name())); + } + } + } + } + } + } + } + } + } +} + +static void findTagLessClasses(ClassDef *cd) +{ + if (cd->getInnerClasses()) + { + ClassSDict::Iterator it(*cd->getInnerClasses()); + ClassDef *icd; + for (it.toFirst();(icd=it.current());++it) + { + if (icd->name().find("@")==-1) // process all non-anonymous inner classes + { + findTagLessClasses(icd); + } + } + } + + processTagLessClasses(cd,cd,cd,"",0); // process tag less inner struct/classes (if any) +} + +static void findTagLessClasses() +{ + ClassSDict::Iterator cli(*Doxygen::classSDict); + ClassDef *cd; + for (cli.toFirst();(cd=cli.current());++cli) // for each class + { + Definition *scope = cd->getOuterScope(); + if (scope && scope->definitionType()!=Definition::TypeClass) // that is not nested + { + findTagLessClasses(cd); + } + } +} + + //---------------------------------------------------------------------- // build a list of all namespaces mentioned in the documentation // and all namespaces that have a documentation block before their definition. @@ -1383,42 +1540,14 @@ static void buildNamespaceList(EntryNav *rootNav) NamespaceDef *nd; if ((nd=Doxygen::namespaceSDict->find(fullName))) // existing namespace { -#if 0 - if (!root->doc.isEmpty() || !root->brief.isEmpty()) // block contains docs - { - if (nd->documentation().isEmpty() && !root->doc.isEmpty()) - { -#endif - nd->setDocumentation(root->doc,root->docFile,root->docLine); - nd->setName(fullName); // change name to match docs - nd->addSectionsToDefinition(root->anchors); -#if 0 - } - else if (!nd->documentation().isEmpty() && !root->doc.isEmpty()) - { - warn( - root->fileName,root->startLine, - "warning: namespace %s already has a detailed description found in file %s at line %d. " - "Skipping the documentation found here.", - fullName.data(),nd->docFile().data(),nd->docLine()); - } - if (nd->briefDescription().isEmpty() && !root->brief.isEmpty()) - { -#endif - nd->setBriefDescription(root->brief,root->briefFile,root->briefLine); -#if 0 - nd->setName(fullName); // change name to match docs - } - else if (!nd->briefDescription().isEmpty() && !root->brief.isEmpty()) - { - warn(root->fileName,root->startLine, - "warning: namespace %s already has a brief description found in file %s at line %d. " - "Skipping the documentation found here.", - fullName.data(),nd->docFile().data(),nd->docLine() - ); - } + nd->setDocumentation(root->doc,root->docFile,root->docLine); + nd->setName(fullName); // change name to match docs + nd->addSectionsToDefinition(root->anchors); + nd->setBriefDescription(root->brief,root->briefFile,root->briefLine); + if (nd->getLanguage()==SrcLangExt_Unknown) + { + nd->setLanguage(root->lang); } -#endif // file definition containing the namespace nd FileDef *fd=rootNav->fileDef(); @@ -1436,13 +1565,14 @@ static void buildNamespaceList(EntryNav *rootNav) tagName=rootNav->tagInfo()->tagName; tagFileName=rootNav->tagInfo()->fileName; } - //printf("++ new namespace %s\n",fullName.data()); + //printf("++ new namespace %s lang=%s\n",fullName.data(),langToString(root->lang).data()); NamespaceDef *nd=new NamespaceDef(root->fileName,root->startLine,fullName,tagName,tagFileName); nd->setDocumentation(root->doc,root->docFile,root->docLine); // copy docs to definition nd->setBriefDescription(root->brief,root->briefFile,root->briefLine); nd->addSectionsToDefinition(root->anchors); nd->setHidden(root->hidden); nd->setArtificial(root->artificial); + nd->setLanguage(root->lang); //printf("Adding namespace to group\n"); addNamespaceToGroups(root,nd); @@ -1527,7 +1657,7 @@ static void findUsingDirectives(EntryNav *rootNav) // see if the using statement was found inside a namespace or inside // the global file scope. if (rootNav->parent() && rootNav->parent()->section()==Entry::NAMESPACE_SEC && - (fd==0 || !fd->isJava()) // not a .java file + (fd==0 || fd->getLanguage()!=SrcLangExt_Java) // not a .java file ) { nsName=stripAnonymousNamespaceScope(rootNav->parent()->name()); @@ -1604,7 +1734,7 @@ static void findUsingDirectives(EntryNav *rootNav) } else // unknown namespace, but add it anyway. { - //printf("++ new unknown namespace %s\n",name.data()); + //printf("++ new unknown namespace %s lang=%s\n",name.data(),langToString(root->lang).data()); NamespaceDef *nd=new NamespaceDef(root->fileName,root->startLine,name); nd->setDocumentation(root->doc,root->docFile,root->docLine); // copy docs to definition nd->setBriefDescription(root->brief,root->briefFile,root->briefLine); @@ -1612,6 +1742,7 @@ static void findUsingDirectives(EntryNav *rootNav) //printf("** Adding namespace %s hidden=%d\n",name.data(),root->hidden); nd->setHidden(root->hidden); nd->setArtificial(TRUE); + nd->setLanguage(root->lang); QListIterator gli(*root->groups); Grouping *g; @@ -1723,6 +1854,7 @@ static void findUsingDeclarations(EntryNav *rootNav) name,ClassDef::Class); Doxygen::hiddenClasses->append(root->name,usingCd); usingCd->setArtificial(TRUE); + usingCd->setLanguage(root->lang); } else { @@ -1832,6 +1964,7 @@ static void findUsingDeclImports(EntryNav *rootNav) newMd->setMaxInitLines(md->initializerLines()); newMd->setMemberGroupId(root->mGrpId); newMd->setMemberSpecifiers(md->getMemberSpecifiers()); + newMd->setLanguage(root->lang); rootNav->releaseEntry(); } @@ -1895,7 +2028,8 @@ static MemberDef *addVariableToClass( QCString qualScope = cd->qualifiedNameWithTemplateParameters(); QCString scopeSeparator="::"; - if (Config_getBool("OPTIMIZE_OUTPUT_JAVA")) + SrcLangExt lang = cd->getLanguage(); + if (lang==SrcLangExt_Java || lang==SrcLangExt_CSharp) { qualScope = substitute(qualScope,"::","."); scopeSeparator="."; @@ -1999,6 +2133,7 @@ static MemberDef *addVariableToClass( md->enableCallerGraph(root->callerGraph); md->setHidden(root->hidden); md->setArtificial(root->artificial); + md->setLanguage(root->lang); addMemberToGroups(root,md); //if (root->mGrpId!=-1) //{ @@ -2107,9 +2242,8 @@ static MemberDef *addVariableToFile( ) // variable is inside a namespace, so put the scope before the name { - static bool optimizeForJava = Config_getBool("OPTIMIZE_OUTPUT_JAVA"); - QCString sep="::"; - if (optimizeForJava) sep="."; + SrcLangExt lang = nd->getLanguage(); + QCString sep=getLanguageSpecificSeparator(lang); if (!root->type.isEmpty()) { @@ -2164,7 +2298,7 @@ static MemberDef *addVariableToFile( if (md->getFileDef() && ! // not a php array ( - (getLanguageFromFileName(md->getFileDef()->name())==SrcLangExt_PHP) && + (md->getLanguage()==SrcLangExt_PHP) && (md->argsString()!=root->args && root->args.find('[')!=-1) ) ) @@ -2199,6 +2333,7 @@ static MemberDef *addVariableToFile( md->setMaxInitLines(root->initLines); md->setMemberGroupId(root->mGrpId); md->setDefinition(def); + md->setLanguage(root->lang); md->enableCallGraph(root->callGraph); md->enableCallerGraph(root->callerGraph); md->setExplicitExternal(root->explicitExternal); @@ -2246,7 +2381,7 @@ static MemberDef *addVariableToFile( */ static int findFunctionPtr(const QCString &type,int lang, int *pLength=0) { - if (lang == SrcLangExt_F90) return -1; // Fortran does not have function pointers + if (lang == SrcLangExt_Fortran) return -1; // Fortran does not have function pointers static const QRegExp re("([^)]*[\\*\\^][^)]*)"); int i=-1,l; if (!type.isEmpty() && // return type is non-empty @@ -2535,8 +2670,8 @@ static void addVariable(EntryNav *rootNav,int isFuncPtr=-1) { MemberDef *md=0; - // if cd is an anonymous scope we insert the member - // into a non-anonymous scope as well. This is needed to + // if cd is an anonymous (=tag less) scope we insert the member + // into a non-anonymous parent scope as well. This is needed to // be able to refer to it using \var or \fn //int indentDepth=0; @@ -2544,11 +2679,12 @@ static void addVariable(EntryNav *rootNav,int isFuncPtr=-1) //int anonyScopes = 0; bool added=FALSE; - if (si!=-1) // anonymous scope + static bool inlineSimpleStructs = Config_getBool("INLINE_SIMPLE_STRUCTS"); + if (si!=-1 && !inlineSimpleStructs) // anonymous scope or type { QCString pScope; ClassDef *pcd=0; - pScope = scope.left(QMAX(si-2,0)); + pScope = scope.left(QMAX(si-2,0)); // scope without tag less parts if (!pScope.isEmpty()) pScope.prepend(annScopePrefix); else if (annScopePrefix.length()>2) @@ -2679,7 +2815,8 @@ static void addMethodToClass(EntryNav *rootNav,ClassDef *cd, int l,i=-1; static QRegExp re("([a-z_A-Z0-9: ]*[ &*]+[ ]*"); - if (!root->type.isEmpty() && (i=re.match(root->type,0,&l))!=-1) // function variable + if (cd->getLanguage()==SrcLangExt_Cpp && // only C has pointers + !root->type.isEmpty() && (i=re.match(root->type,0,&l))!=-1) // function variable { root->args+=root->type.right(root->type.length()-i-l); root->type=root->type.left(i+l); @@ -2696,7 +2833,7 @@ static void addMethodToClass(EntryNav *rootNav,ClassDef *cd, else mtype=MemberDef::Function; // strip redundant template specifier for constructors - if ((fd==0 || getLanguageFromFileName(fd->name())==SrcLangExt_Cpp) && + if ((fd==0 || fd->getLanguage()==SrcLangExt_Cpp) && name.left(9)!="operator " && (i=name.find('<'))!=-1 && name.find('>')!=-1) { name=name.left(i); @@ -2725,17 +2862,23 @@ static void addMethodToClass(EntryNav *rootNav,ClassDef *cd, md->setMemberSpecifiers(root->spec); md->setMemberGroupId(root->mGrpId); md->setTypeConstraints(root->typeConstr); + md->setLanguage(root->lang); md->setBodyDef(fd); md->setFileDef(fd); //md->setScopeTemplateArguments(root->tArgList); md->addSectionsToDefinition(root->anchors); QCString def; QCString qualScope = cd->qualifiedNameWithTemplateParameters(); - QCString scopeSeparator="::"; - if (Config_getBool("OPTIMIZE_OUTPUT_JAVA")) + SrcLangExt lang = cd->getLanguage(); + QCString scopeSeparator=getLanguageSpecificSeparator(lang); + if (scopeSeparator!="::") { - qualScope = substitute(qualScope,"::","."); - scopeSeparator="."; + qualScope = substitute(qualScope,"::",scopeSeparator); + } + if (lang==SrcLangExt_PHP) + { + // for PHP we use Class::method and Namespace\method + scopeSeparator="::"; } if (!root->relates.isEmpty() || isFriend || Config_getBool("HIDE_SCOPE_NAMES")) { @@ -2910,8 +3053,9 @@ static void buildFunctionList(EntryNav *rootNav) cd && // do some fuzzy things to exclude function pointers (root->type.isEmpty() || - (root->type.find(re,0)==-1 || root->args.find(")[")!=-1) || // type contains ..(..* and args not )[.. -> function pointer - root->type.find(")(")!=-1 || root->type.find("operator")!=-1 // type contains ..)(.. and not "operator" + (root->type.find(re,0)==-1 || root->args.find(")[")!=-1) || // type contains ..(..* and args not )[.. -> function pointer + root->type.find(")(")!=-1 || root->type.find("operator")!=-1 || // type contains ..)(.. and not "operator" + cd->getLanguage()!=SrcLangExt_Cpp // language other than C ) ) { @@ -3083,6 +3227,7 @@ static void buildFunctionList(EntryNav *rootNav) MemberDef::Function,tArgList,root->argList); md->setTagInfo(rootNav->tagInfo()); + md->setLanguage(root->lang); //md->setDefFile(root->fileName); //md->setDefLine(root->startLine); md->setDocumentation(root->doc,root->docFile,root->docLine); @@ -3113,14 +3258,12 @@ static void buildFunctionList(EntryNav *rootNav) if (!scope.isEmpty()) { - if (Config_getBool("OPTIMIZE_OUTPUT_JAVA")) + QCString sep = getLanguageSpecificSeparator(root->lang); + if (sep!="::") { - scope = substitute(scope,"::",".")+"."; - } - else - { - scope+="::"; + scope = substitute(scope,"::",sep); } + scope+=sep; } QCString def; @@ -3825,6 +3968,7 @@ static void findUsedClassesForClass(EntryNav *rootNav, //printf("making %s a template argument!!!\n",usedCd->name().data()); usedCd->makeTemplateArgument(); usedCd->setUsedOnly(TRUE); + usedCd->setLanguage(masterCd->getLanguage()); Doxygen::hiddenClasses->append(usedName,usedCd); } if (usedCd) @@ -3872,6 +4016,7 @@ static void findUsedClassesForClass(EntryNav *rootNav, masterCd->getDefFileName(),masterCd->getDefLine(), type,ClassDef::Class); usedCd->setUsedOnly(TRUE); + usedCd->setLanguage(masterCd->getLanguage()); Doxygen::hiddenClasses->append(type,usedCd); } if (usedCd) @@ -4372,6 +4517,7 @@ static bool findClassRelation( baseClassName,ClassDef::Class); Doxygen::hiddenClasses->append(baseClassName,baseClass); if (isArtificial) baseClass->setArtificial(TRUE); + baseClass->setLanguage(root->lang); } } else @@ -4385,6 +4531,7 @@ static bool findClassRelation( baseClassName,ClassDef::Class); Doxygen::classSDict->append(baseClassName,baseClass); if (isArtificial) baseClass->setArtificial(TRUE); + baseClass->setLanguage(root->lang); } } // add base class to this class @@ -5048,14 +5195,14 @@ static bool findGlobalMember(EntryNav *rootNav, QCString fullFuncDecl=decl; if (root->argList) fullFuncDecl+=argListToString(root->argList,TRUE); QCString warnMsg = - QCString("warning: no matching file member found for \n")+fullFuncDecl; + QCString("warning: no matching file member found for \n")+substitute(fullFuncDecl,"%","%%"); if (mn->count()>0) { warnMsg+="Possible candidates:\n"; for (mni.toFirst();(md=mni.current());++mni) { warnMsg+=" "; - warnMsg+=md->declaration(); + warnMsg+=substitute(md->declaration(),"%","%%"); warnMsg+='\n'; } } @@ -5834,6 +5981,7 @@ static void findMember(EntryNav *rootNav, mtype,tArgList,root->argList); //printf("new specialized member %s args=`%s'\n",md->name().data(),funcArgs.data()); md->setTagInfo(rootNav->tagInfo()); + md->setLanguage(root->lang); md->setMemberClass(cd); md->setTemplateSpecialization(TRUE); md->setTypeConstraints(root->typeConstr); @@ -5897,6 +6045,7 @@ static void findMember(EntryNav *rootNav, root->protection,root->virt,root->stat,Related, mtype,tArgList,root->argList); md->setTagInfo(rootNav->tagInfo()); + md->setLanguage(root->lang); md->setTypeConstraints(root->typeConstr); md->setMemberClass(cd); md->setDefinition(funcDecl); @@ -6109,6 +6258,7 @@ static void findMember(EntryNav *rootNav, md->setBriefDescription(root->brief,root->briefFile,root->briefLine); md->addSectionsToDefinition(root->anchors); md->setMemberGroupId(root->mGrpId); + md->setLanguage(root->lang); //md->setMemberDefTemplateArguments(root->mtArgList); mn->append(md); cd->insertMember(md); @@ -6156,6 +6306,8 @@ localObjCMethod: //printf("scopeName=`%s' className=`%s'\n",scopeName.data(),className.data()); if (Config_getBool("EXTRACT_LOCAL_METHODS") && (cd=getClass(scopeName))) { + Debug::print(Debug::FindMembers,0,"4. Local objective C method %s\n" + " scopeName=%s className=%s\n",root->name.data(),scopeName.data(),className.data()); //printf("Local objective C method `%s' of class `%s' found\n",root->name.data(),cd->name().data()); MemberDef *md=new MemberDef( root->fileName,root->startLine, @@ -6163,6 +6315,7 @@ localObjCMethod: root->protection,root->virt,root->stat,Member, MemberDef::Function,0,root->argList); md->setTagInfo(rootNav->tagInfo()); + md->setLanguage(root->lang); md->makeImplementationDetail(); md->setMemberClass(cd); md->setDefinition(funcDecl); @@ -6491,6 +6644,7 @@ static void findEnums(EntryNav *rootNav) MemberDef::Enumeration, 0,0); md->setTagInfo(rootNav->tagInfo()); + md->setLanguage(root->lang); if (!isGlobal) md->setMemberClass(cd); else md->setFileDef(fd); md->setBodySegment(root->bodyLine,root->endBodyLine); md->setBodyDef(rootNav->fileDef()); @@ -6756,6 +6910,7 @@ static void addEnumValuesToEnums(EntryNav *rootNav) else if (md->getFileDef()) fmd->setFileDef(md->getFileDef()); fmd->setOuterScope(md->getOuterScope()); fmd->setTagInfo(e->tagInfo()); + fmd->setLanguage(root->lang); fmd->setDocumentation(root->doc,root->docFile,root->docLine); fmd->setBriefDescription(root->brief,root->briefFile,root->briefLine); fmd->addSectionsToDefinition(root->anchors); @@ -7178,13 +7333,11 @@ static void createTemplateInstanceMembers() //---------------------------------------------------------------------------- -// builds the list of all members for each class - -static void buildCompleteMemberLists() +static void mergeCategories() { ClassDef *cd; - // merge members of categories into the class they extend ClassSDict::Iterator cli(*Doxygen::classSDict); + // merge members of categories into the class they extend for (cli.toFirst();(cd=cli.current());++cli) { int i=cd->name().find('('); @@ -7200,6 +7353,14 @@ static void buildCompleteMemberLists() } } } +} + +// builds the list of all members for each class + +static void buildCompleteMemberLists() +{ + ClassDef *cd; + ClassSDict::Iterator cli(*Doxygen::classSDict); // merge the member list of base classes into the inherited classes. for (cli.toFirst();(cd=cli.current());++cli) { @@ -7783,6 +7944,7 @@ static void findDefineDocumentation(EntryNav *rootNav) "#define",root->name,root->args,0, Public,Normal,FALSE,Member,MemberDef::Define,0,0); md->setTagInfo(rootNav->tagInfo()); + md->setLanguage(root->lang); //printf("Searching for `%s' fd=%p\n",filePathName.data(),fd); md->setFileDef(rootNav->parent()->fileDef()); //printf("Adding member=%s\n",md->name().data()); @@ -7872,6 +8034,7 @@ static void findDefineDocumentation(EntryNav *rootNav) md->setBodyDef(rootNav->fileDef()); md->addSectionsToDefinition(root->anchors); md->setRefItems(root->sli); + md->setLanguage(root->lang); if (root->mGrpId!=-1) md->setMemberGroupId(root->mGrpId); addMemberToGroups(root,md); } @@ -9255,6 +9418,7 @@ void initDoxygen() Doxygen::parserManager->registerParser("fortran", new FortranLanguageScanner); Doxygen::parserManager->registerParser("vhdl", new VHDLLanguageScanner); Doxygen::parserManager->registerParser("dbusxml", new DBusXMLScanner); + Doxygen::parserManager->registerParser("tcl", new TclLanguageScanner); // register any additional parsers here... @@ -10108,7 +10272,7 @@ void parseInput() msg("Parsing layout file %s...\n",layoutFileName.data()); QTextStream t(&layoutFile); t.setEncoding(QTextStream::Latin1); - LayoutDocManager::instance().parse(t); + LayoutDocManager::instance().parse(t,layoutFileName); } else if (!defaultLayoutUsed) { @@ -10272,6 +10436,11 @@ void parseInput() findInheritedTemplateInstances(); msg("Computing class usage relations...\n"); findUsedTemplateInstances(); + if (Config_getBool("INLINE_SIMPLE_STRUCTS")) + { + msg("Searching for tag less structs...\n"); + findTagLessClasses(); + } msg("Flushing cached template relations that have become invalid...\n"); flushCachedTemplateRelations(); @@ -10282,12 +10451,8 @@ void parseInput() msg("Computing class relations...\n"); computeTemplateClassRelations(); flushUnresolvedRelations(); - computeClassRelations(); - - if (Config_getBool("OPTIMIZE_OUTPUT_VHDL")) - VhdlDocGen::computeVhdlComponentRelations(); - + VhdlDocGen::computeVhdlComponentRelations(); g_classEntries.clear(); msg("Add enum values to enums...\n"); @@ -10336,6 +10501,7 @@ void parseInput() computeMemberRelations(); msg("Building full member lists recursively...\n"); + mergeCategories(); buildCompleteMemberLists(); msg("Adding members to member groups.\n"); diff --git a/src/filedef.cpp b/src/filedef.cpp index d33de00..0c482d8 100644 --- a/src/filedef.cpp +++ b/src/filedef.cpp @@ -92,9 +92,10 @@ FileDef::FileDef(const char *p,const char *nm, { docname.prepend(stripFromPath(path.copy())); } - SrcLangExt lang = getLanguageFromFileName(name()); - m_isJava = lang==SrcLangExt_Java; - m_isCSharp = lang==SrcLangExt_CSharp; + SrcLangExt lang = getLanguageFromFileName(name()); + setLanguage(lang); + //m_isJava = lang==SrcLangExt_Java; + //m_isCSharp = lang==SrcLangExt_CSharp; memberGroupSDict = 0; acquireFileVersion(); m_subGrouping=Config_getBool("SUBGROUPING"); @@ -264,7 +265,7 @@ void FileDef::writeIncludeFiles(OutputList &ol) bool isIDLorJava = FALSE; if (fd) { - SrcLangExt lang = getLanguageFromFileName(fd->name()); + SrcLangExt lang = fd->getLanguage(); isIDLorJava = lang==SrcLangExt_IDL || lang==SrcLangExt_Java; } ol.startTypewriter(); @@ -536,7 +537,7 @@ void FileDef::writeDocumentation(OutputList &ol) ol.parseText(pageTitleShort); // Html only ol.enableAll(); ol.disable(OutputGenerator::Html); - ol.parseText(pageTitle,TRUE); // other output formats + ol.parseText(pageTitle); // other output formats ol.popGeneratorState(); addGroupListToTitle(ol,this); endTitle(ol,getOutputFileBase(),title); diff --git a/src/filedef.h b/src/filedef.h index 8708794..502a957 100644 --- a/src/filedef.h +++ b/src/filedef.h @@ -124,8 +124,8 @@ class FileDef : public Definition } bool isIncluded(const QCString &name) const; - bool isJava() const { return m_isJava; } - bool isCSharp() const { return m_isCSharp; } + //bool isJava() const { return m_isJava; } + //bool isCSharp() const { return m_isCSharp; } void writeDocumentation(OutputList &ol); void writeMemberPages(OutputList &ol); @@ -220,8 +220,8 @@ class FileDef : public Definition QIntDict *srcDefDict; QIntDict *srcMemberDict; bool isSource; - bool m_isJava; - bool m_isCSharp; + //bool m_isJava; + //bool m_isCSharp; QCString fileVersion; PackageDef *package; DirDef *dir; diff --git a/src/fortranscanner.l b/src/fortranscanner.l index 0ea16dc..d83fe85 100644 --- a/src/fortranscanner.l +++ b/src/fortranscanner.l @@ -111,6 +111,10 @@ static const char *directionStrs[] = { "", "intent(in)", "intent(out)", "intent(inout)" }; +static const char *directionParam[] = +{ + "", "[in]", "[out]", "[in,out]" +}; // }}} @@ -127,6 +131,8 @@ static QCString inputStringSemi; ///< Input string after command separet static unsigned int inputPositionPrepass; static int lineCountPrepass = 0; +static QList subrCurrent; + struct CommentInPrepass { int column; QCString str; @@ -185,6 +191,7 @@ static QMap > modifiers; static int yyread(char *buf,int max_size); static void startCommentBlock(bool); static void handleCommentBlock(const QCString &doc,bool brief); +static void subrHandleCommentBlock(const QCString &doc,bool brief); static void addCurrentEntry(); static void addModule(const char *name, bool isModule=FALSE); static void addSubprogram(const char *text); @@ -405,7 +412,7 @@ PREFIX (RECURSIVE{BS_}|PURE{BS_}|ELEMENTAL{BS_}){0,2}(RECURSIVE|PURE|ELEMENTA current->section=Entry::USINGDIR_SEC; current_root->addSubEntry(current); current = new Entry; - current->lang = SrcLangExt_F90; + current->lang = SrcLangExt_Fortran; yy_pop_state(); } {ID}/, { @@ -420,7 +427,7 @@ PREFIX (RECURSIVE{BS_}|PURE{BS_}|ELEMENTAL{BS_}){0,2}(RECURSIVE|PURE|ELEMENTA current->section=Entry::USINGDECL_SEC; current_root->addSubEntry(current); current = new Entry ; - current->lang = SrcLangExt_F90; + current->lang = SrcLangExt_Fortran; } "\n" { yyColNr -= 1; @@ -430,6 +437,7 @@ PREFIX (RECURSIVE{BS_}|PURE{BS_}|ELEMENTAL{BS_}){0,2}(RECURSIVE|PURE|ELEMENTA /* INTERFACE definitions */ { +^{BS}interface{IDSYM}+ { /* variable with interface prefix */ } ^{BS}interface { ifType = IF_SPECIFIC; yy_push_state(InterfaceBody); // do not start a scope here, every @@ -647,6 +655,7 @@ private { if (!endScope(current_root)) yyterminate(); + subrCurrent.remove(0u); yy_pop_state() ; } { @@ -757,8 +766,7 @@ private { if (!argType.isNull()) parameter->type=argType.stripWhiteSpace(); if (!docBlock.isNull()) { - parameter->docs += "\n"; - parameter->docs += docBlock; + subrHandleCommentBlock(docBlock,TRUE); } } // save, it may be function return type @@ -769,7 +777,7 @@ private { else { if ((current_root->name.lower() == argName.lower()) || - (modifiers[current_root->parent()][current_root->name.lower()].returnName == argName.lower())) + (modifiers[current_root->parent()][current_root->name.lower()].returnName.lower() == argName.lower())) { int strt = current_root->type.find("function"); QString lft; @@ -981,7 +989,7 @@ private { /*---- documentation comments --------------------------------------------------------------------*/ -"!<" { /* backward docu comment (only one line) */ +"!<" { /* backward docu comment */ if (v_type != V_IGNORE) { current->docLine = yyLineNr; docBlockJavaStyle = FALSE; @@ -992,7 +1000,16 @@ private { } } .* { // contents of current comment line - docBlock=yytext; + docBlock+=yytext; + } +"\n"{BS}"!"("<"|"!"+) { // comment block (next line is also comment line) + docBlock+="\n"; // \n is necessary for lists + newLine(); + } +"\n" { // comment block ends at the end of this line + //cout <<"3=========> comment block : "<< docBlock << endl; + yyColNr -= 1; + unput(*yytext); if (v_type == V_VARIABLE) { Entry *tmp_entry = current; @@ -1002,11 +1019,12 @@ private { } else if (v_type == V_PARAMETER) { - parameter->docs+=docBlock; + subrHandleCommentBlock(docBlock,TRUE); } - yy_pop_state(); - } - + yy_pop_state(); + docBlock.resize(0); + } + "!>" { yy_push_state(YY_START); current->docLine = yyLineNr; @@ -1831,7 +1849,7 @@ static void initEntry() current->mtype = mtype; current->virt = virt; current->stat = gstat; - current->lang = SrcLangExt_F90; + current->lang = SrcLangExt_Fortran; initGroupInfo(current); } @@ -1882,6 +1900,7 @@ static void addModule(const char *name, bool isModule) static void addSubprogram(const char *text) { //fprintf(stderr,"1=========> got subprog, type: %s\n",text); + subrCurrent.prepend(current); current->section = Entry::FUNCTION_SEC ; QCString subtype = text; subtype=subtype.lower().stripWhiteSpace(); current->type += " " + subtype; @@ -1978,7 +1997,8 @@ static void startCommentBlock(bool brief) } } - //---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- + static void handleCommentBlock(const QCString &doc,bool brief) { docBlockInBody = FALSE; @@ -2011,6 +2031,29 @@ static void handleCommentBlock(const QCString &doc,bool brief) } //---------------------------------------------------------------------------- + +static void subrHandleCommentBlock(const QCString &doc,bool brief) +{ + Entry *tmp_entry = current; + current = subrCurrent.first(); // temporarily switch to the entry of the subroutine / function + if (docBlock.stripWhiteSpace().find("\\param") == 0) + { + handleCommentBlock(doc,brief); + } + else if (docBlock.stripWhiteSpace().find("@param") == 0) + { + handleCommentBlock(doc,brief); + } + else + { + int dir1 = modifiers[current_root][argName.lower()].direction; + handleCommentBlock(QCString("@param ") + directionParam[dir1] + " " + + argName + " " + doc,brief); + } + current=tmp_entry; +} + +//---------------------------------------------------------------------------- static int level=0; static void debugCompounds(Entry *rt) // print Entry structure (for debugging) { @@ -2067,13 +2110,13 @@ static void parseMain(const char *fileName,const char *fileBuf,Entry *rt) groupEnterFile(yyFileName,yyLineNr); current = new Entry; - current->lang = SrcLangExt_F90; + current->lang = SrcLangExt_Fortran; current->name = yyFileName; current->section = Entry::SOURCE_SEC; current_root->addSubEntry(current); file_root = current; current = new Entry; - current->lang = SrcLangExt_F90; + current->lang = SrcLangExt_Fortran; fscanYYrestart( fscanYYin ); { diff --git a/src/groupdef.cpp b/src/groupdef.cpp index 8ecc784..12de564 100644 --- a/src/groupdef.cpp +++ b/src/groupdef.cpp @@ -145,11 +145,42 @@ bool GroupDef::addClass(const ClassDef *cd) if (cd->isHidden()) return FALSE; if (classSDict->find(cd->qualifiedName())==0) { - //printf("addClass %s sort=%d\n",cd->qualifiedName().data(),sortBriefDocs); + QCString qn = cd->qualifiedName(); + //printf("--- addClass %s sort=%d\n",qn.data(),sortBriefDocs); if (sortBriefDocs) + { classSDict->inSort(cd->qualifiedName(),cd); + } else - classSDict->append(cd->qualifiedName(),cd); + { + int i=qn.findRev("::"); + if (i==-1) i=qn.find('.'); + bool found=FALSE; + //printf("i=%d\n",i); + if (i!=-1) + { + // add nested classes (e.g. A::B, A::C) after their parent (A) in + // order of insertion + QCString scope = qn.left(i); + int j=classSDict->findAt(scope); + if (j!=-1) + { + while (j<(int)classSDict->count() && + classSDict->at(j)->qualifiedName().left(i)==scope) + { + //printf("skipping over %s\n",classSDict->at(j)->qualifiedName().data()); + j++; + } + //printf("Found scope at index %d\n",j); + classSDict->insertAt(j,cd->qualifiedName(),cd); + found=TRUE; + } + } + if (!found) // no insertion point found -> just append + { + classSDict->append(cd->qualifiedName(),cd); + } + } return TRUE; } return FALSE; diff --git a/src/htmldocvisitor.cpp b/src/htmldocvisitor.cpp index 410542b..2c5ffb7 100644 --- a/src/htmldocvisitor.cpp +++ b/src/htmldocvisitor.cpp @@ -446,6 +446,25 @@ void HtmlDocVisitor::visit(DocInclude *inc) m_t << PREFRAG_END; forceStartParagraph(inc); break; + case DocInclude::Snippet: + { + forceEndParagraph(inc); + m_t << PREFRAG_START; + Doxygen::parserManager->getParser(inc->extension()) + ->parseCode(m_ci, + inc->context(), + extractBlock(inc->text(),inc->blockId()), + inc->isExample(), + inc->exampleFile(), + 0, + -1, // startLine + -1, // endLine + TRUE // inlineFragment + ); + m_t << PREFRAG_END; + forceStartParagraph(inc); + } + break; } } diff --git a/src/htmlgen.cpp b/src/htmlgen.cpp index 7865fd6..1654733 100644 --- a/src/htmlgen.cpp +++ b/src/htmlgen.cpp @@ -979,7 +979,16 @@ static QCString substituteHtmlKeywords(const QCString &s,const char *title, if (mathJax) { - mathJaxJs = "