diff options
107 files changed, 5921 insertions, 1708 deletions
diff --git a/.travis.yml b/.travis.yml index 28b8401..829e54e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,6 @@ language: cpp os: - - linux-ppc64le + - linux-ppc64le - linux dist: xenial compiler: @@ -13,6 +13,7 @@ addons: update: true packages: - texlive + - texlive-generic-recommended - texlive-extra-utils - texlive-latex-extra - texlive-font-utils @@ -21,6 +22,34 @@ addons: - cmake - cmake-data +jobs: + include: + - os: osx + compiler: clang + +before_script: + - if [ "${TRAVIS_OS_NAME}" == "osx" ]; then + sudo mkdir -p /usr/local/man; + sudo chown -R "${USER}:admin" /usr/local/man; + pip install --quiet conan; + export HOMEBREW_NO_AUTO_UPDATE=1; + brew install ghostscript; + + travis_wait brew cask install mactex-no-gui; + curl -O -L http://mirrors.ctan.org/support/epstopdf.zip; + unzip epstopdf.zip; + mkdir -p /Users/travis/Library/TeX/texbin/; + mv epstopdf/epstopdf.pl /Users/travis/Library/TeX/texbin/epstopdf; + chmod a+x /Users/travis/Library/TeX/texbin/epstopdf; + rm -rf epstopdf*; + export PATH=/Users/travis/Library/TeX/texbin:/Library/TeX/texbin:$PATH; + + conan remote add bincrafters https://api.bintray.com/conan/bincrafters/public-conan; + printf "[requires] \nlibxml2/2.9.8@bincrafters/stable \nQt/5.11.1@bincrafters/stable" >> conanfile.txt; + conan install . -g virtualrunenv; + source activate_run.sh; + fi; + script: - mkdir build - cd build diff --git a/CMakeLists.txt b/CMakeLists.txt index 1e0fb55..45c2f2c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -86,7 +86,10 @@ find_package(BISON REQUIRED) find_package(Threads) if (sqlite3) - find_package(SQLite3 REQUIRED) + find_package(SQLite3 REQUIRED) + if (SQLITE3_VERSION VERSION_LESS 3.9.0) + message(SEND_ERROR "Doxygen requires at least sqlite3 version 3.9.0 (installed: ${SQLITE3_VERSION})") + endif() endif() find_package(Iconv REQUIRED) @@ -1,25 +1,25 @@ Doxygen =============== -Doxygen is the de facto standard tool for generating documentation from -annotated C++ sources, but it also supports other popular programming -languages such as C, Objective-C, C#, PHP, Java, Python, IDL -(Corba, Microsoft, and UNO/OpenOffice flavors), Fortran, VHDL, Tcl, +Doxygen is the de facto standard tool for generating documentation from +annotated C++ sources, but it also supports other popular programming +languages such as C, Objective-C, C#, PHP, Java, Python, IDL +(Corba, Microsoft, and UNO/OpenOffice flavors), Fortran, VHDL, Tcl, and to some extent D. Doxygen can help you in three ways: -1. It can generate an on-line documentation browser (in HTML) and/or an - off-line reference manual (in LaTeX) from a set of documented source files. - There is also support for generating output in RTF (MS-Word), PostScript, - hyperlinked PDF, compressed HTML, DocBook and Unix man pages. - The documentation is extracted directly from the sources, which makes +1. It can generate an on-line documentation browser (in HTML) and/or an + off-line reference manual (in LaTeX) from a set of documented source files. + There is also support for generating output in RTF (MS-Word), PostScript, + hyperlinked PDF, compressed HTML, DocBook and Unix man pages. + The documentation is extracted directly from the sources, which makes it much easier to keep the documentation consistent with the source code. -2. You can configure doxygen to extract the code structure from undocumented - source files. This is very useful to quickly find your way in large - source distributions. Doxygen can also visualize the relations between - the various elements by means of include dependency graphs, inheritance +2. You can configure doxygen to extract the code structure from undocumented + source files. This is very useful to quickly find your way in large + source distributions. Doxygen can also visualize the relations between + the various elements by means of include dependency graphs, inheritance diagrams, and collaboration diagrams, which are all generated automatically. -3. You can also use doxygen for creating normal documentation (as I did for +3. You can also use doxygen for creating normal documentation (as I did for the doxygen user manual and doxygen web-site). Download @@ -29,15 +29,14 @@ The latest binaries and source of Doxygen can be downloaded from: Developers --------- -* Build Status: <a href="https://travis-ci.org/doxygen/doxygen"><img src="https://secure.travis-ci.org/doxygen/doxygen.png?branch=master"/></a> +* Linux & macOS Build Status: <a href="https://travis-ci.org/doxygen/doxygen"><img src="https://secure.travis-ci.org/doxygen/doxygen.png?branch=master"/></a> +* Windows Build Status: <a href="https://ci.appveyor.com/project/doxygen/doxygen"><img src="https://ci.appveyor.com/api/projects/status/github/doxygen/doxygen"/></a> * Coverity Scan Build Status: <a href="https://scan.coverity.com/projects/2860"> <img alt="Coverity Scan Build Status" src="https://scan.coverity.com/projects/2860/badge.svg"/> </a> * Doxygen's Doxygen Documentation: <a href="https://codedocs.xyz/doxygen/doxygen/"><img src="https://codedocs.xyz/doxygen/doxygen.svg"/></a> -* Install - * Quick install see (./INSTALL) - * else http://www.doxygen.org/manual/install.html +* Install: Please read the installation section of the manual (http://www.doxygen.org/manual/install.html) * Project stats: https://www.openhub.net/p/doxygen @@ -59,10 +58,10 @@ There are three mailing lists: Source Code ---------------------------------- -In May 2013, Doxygen moved from +In May 2013, Doxygen moved from subversion to git hosted at GitHub * https://github.com/doxygen/doxygen Enjoy, -Dimitri van Heesch (dimitri at stack.nl) +Dimitri van Heesch (doxygen at gmail.com) diff --git a/addon/doxypysql/search.py b/addon/doxypysql/search.py index c185138..5f820de 100755 --- a/addon/doxypysql/search.py +++ b/addon/doxypysql/search.py @@ -17,19 +17,19 @@ import json import re class MemberType: - Define="0" - Function="1" - Variable="2" - Typedef="3" - Enumeration="4" - EnumValue="5" - Signal="6" - Slot="7" - Friend="8" - DCOP="9" - Property="10" - Event="11" - File="12" + Define="macro definition" + Function="function" + Variable="variable" + Typedef="typedef" + Enumeration="enumeration" + EnumValue="enumvalue" + Signal="signal" + Slot="slot" + Friend="friend" + DCOP="dcop" + Property="property" + Event="event" + File="file" class RequestType: References="9901" @@ -69,27 +69,27 @@ class Finder: def match(self,row): if self.row_type is int: - return " id=?" + return " rowid=?" else: if g_use_regexp == True: return " REGEXP (?,%s)" %row else: return " %s=?" %row - def fileName(self,id_file): - if self.cn.execute("SELECT COUNT(*) FROM files WHERE rowid=?",[id_file]).fetchone()[0] > 1: - print >>sys.stderr,"WARNING: non-uniq fileid [%s]. Considering only the first match." % id_file + def fileName(self,file_id): + if self.cn.execute("SELECT COUNT(*) FROM path WHERE rowid=?",[file_id]).fetchone()[0] > 1: + sys.stderr.write("WARNING: non-uniq fileid [%s]. Considering only the first match." % file_id) - for r in self.cn.execute("SELECT * FROM files WHERE rowid=?",[id_file]).fetchall(): + for r in self.cn.execute("SELECT * FROM path WHERE rowid=?",[file_id]).fetchall(): return r['name'] return "" def fileId(self,name): - if self.cn.execute("SELECT COUNT(*) FROM files WHERE"+self.match("name"),[name]).fetchone()[0] > 1: - print >>sys.stderr,"WARNING: non-uniq file name [%s]. Considering only the first match." % name + if self.cn.execute("SELECT COUNT(*) FROM path WHERE"+self.match("name"),[name]).fetchone()[0] > 1: + sys.stderr.write("WARNING: non-uniq file name [%s]. Considering only the first match." % name) - for r in self.cn.execute("SELECT rowid FROM files WHERE"+self.match("name"),[name]).fetchall(): + for r in self.cn.execute("SELECT rowid FROM path WHERE"+self.match("name"),[name]).fetchall(): return r[0] return -1 @@ -97,23 +97,24 @@ class Finder: def references(self): o=[] cur = self.cn.cursor() - cur.execute("SELECT refid FROM memberdef WHERE"+self.match("name"),[self.name]) - refids = cur.fetchall() + cur.execute("SELECT rowid FROM memberdef WHERE"+self.match("name"),[self.name]) + rowids = cur.fetchall() - if len(refids) == 0: + if len(rowids) == 0: return o - refid = refids[0]['refid'] + rowid = rowids[0]['rowid'] cur = self.cn.cursor() - #TODO:SELECT rowid from refids where refid=refid - for info in cur.execute("SELECT * FROM xrefs WHERE refid_dst LIKE '%"+refid+"%'"): + #TODO:SELECT rowid from refid where refid=refid + for info in cur.execute("SELECT * FROM xrefs WHERE dst_rowid=?", [rowid]): item={} cur = self.cn.cursor() - for i2 in cur.execute("SELECT * FROM memberdef WHERE refid=?",[info['src']]): + for i2 in cur.execute("SELECT * FROM memberdef WHERE rowid=?",[info['src_rowid']]): item['name']=i2['name'] - item['src']=info['src'] - item['file']=self.fileName(info['id_file']) - item['line']=info['line'] + item['src']=info['src_rowid'] + # Below no longer directly supported on this entry; can be found from either memberdef + #item['file']=self.fileName(info['file_id']) + #item['line']=info['line'] o.append(item) return o @@ -126,7 +127,7 @@ class Finder: item['name'] = r['name'] item['definition'] = r['definition'] item['argsstring'] = r['argsstring'] - item['file'] = self.fileName(r['id_file']) + item['file'] = self.fileName(r['file_id']) item['line'] = r['line'] item['detaileddescription'] = r['detaileddescription'] o.append(item) @@ -134,7 +135,7 @@ class Finder: ############################################################################### def file(self): o=[] - for r in self.cn.execute("SELECT rowid,* FROM files WHERE"+self.match("name"),[self.name]).fetchall(): + for r in self.cn.execute("SELECT rowid,name FROM local_file WHERE"+self.match("name"),[self.name]).fetchall(): item={} item['name'] = r['name'] item['id'] = r['rowid'] @@ -151,7 +152,7 @@ class Finder: if r['argsstring']: item['argsstring'] = r['argsstring'] item['definition'] = r['initializer'] - item['file'] = self.fileName(r['id_file']) + item['file'] = self.fileName(r['file_id']) item['line'] = r['line'] o.append(item) return o @@ -163,7 +164,7 @@ class Finder: item={} item['name'] = r['name'] item['definition'] = r['definition'] - item['file'] = self.fileName(r['id_file']) + item['file'] = self.fileName(r['file_id']) item['line'] = r['line'] o.append(item) return o @@ -175,16 +176,16 @@ class Finder: item={} item['name'] = r['name'] item['definition'] = r['definition'] - item['file'] = self.fileName(r['id_file']) + item['file'] = self.fileName(r['file_id']) item['line'] = r['line'] o.append(item) return o ############################################################################### def params(self): o=[] - c=self.cn.execute('SELECT id FROM memberdef WHERE'+self.match("name"),[self.name]) + c=self.cn.execute('SELECT rowid FROM memberdef WHERE'+self.match("name"),[self.name]) for r in c.fetchall(): - #a=("SELECT * FROM params where id=(SELECT id_param FROM memberdef_params where id_memberdef=?",[id_memberdef]) + #a=("SELECT * FROM param where id=(SELECT param_id FROM memberdef_param where memberdef_id=?",[memberdef_id]) item={} item['id'] = r['id'] o.append(item) @@ -202,20 +203,20 @@ class Finder: def includers(self): o=[] fid = self.fileId(self.name) - c=self.cn.execute('SELECT * FROM includes WHERE id_dst=?',[fid]) + c=self.cn.execute('SELECT * FROM includes WHERE dst_id=?',[fid]) for r in c.fetchall(): item={} - item['name'] = self.fileName(r['id_src']) + item['name'] = self.fileName(r['src_id']) o.append(item) return o ############################################################################### def includees(self): o=[] fid = self.fileId(self.name) - c=self.cn.execute('SELECT * FROM includes WHERE id_src=?',[fid]) + c=self.cn.execute('SELECT * FROM includes WHERE src_id=?',[fid]) for r in c.fetchall(): item={} - item['name'] = self.fileName(r['id_dst']) + item['name'] = self.fileName(r['dst_id']) o.append(item) return o ############################################################################### @@ -227,7 +228,7 @@ class Finder: item['name'] = r['name'] item['definition'] = r['definition'] item['argsstring'] = r['argsstring'] - item['file'] = self.fileName(r['id_file']) + item['file'] = self.fileName(r['file_id']) item['line'] = r['line'] #item['documentation'] = r['documentation'] o.append(item) @@ -235,19 +236,19 @@ class Finder: ############################################################################### def baseClasses(self): o=[] - c=self.cn.execute('SELECT base FROM basecompoundref WHERE'+self.match("derived"),[self.name]) + c=self.cn.execute('SELECT compounddef.name FROM compounddef JOIN compoundref ON compounddef.rowid=compoundref.base_rowid WHERE compoundref.derived_rowid IN (SELECT rowid FROM compounddef WHERE'+self.match("name")+')',[self.name]) for r in c.fetchall(): item={} - item['name'] = r['base'] + item['name'] = r['name'] o.append(item) return o ############################################################################### def subClasses(self): o=[] - c=self.cn.execute('SELECT derived FROM basecompoundref WHERE'+self.match("base"),[self.name]) + c=self.cn.execute('SELECT compounddef.name FROM compounddef JOIN compoundref ON compounddef.rowid=compoundref.derived_rowid WHERE compoundref.base_rowid IN (SELECT rowid FROM compounddef WHERE'+self.match("name")+')',[self.name]) for r in c.fetchall(): item={} - item['name'] = r['derived'] + item['name'] = r['name'] o.append(item) return o ############################################################################### @@ -268,21 +269,23 @@ def process(f,kind): } return request_processors[kind]() ############################################################################### + +# the -H option isn't documented. It's one of the more recent additions, but it's treating refids as if they would be a string. I'm just taking a stab at updating it for now, converting to use rowid, and making other edits necessary to get it to run. def processHref(cn,ref): j={} # is it in memberdef ? table="memberdef" - if ( cn.execute("SELECT count(*) from %s WHERE refid=?"%table,[ref] ).fetchone()[0] > 0 ): - for r in cn.execute("SELECT kind,id FROM %s WHERE refid='%s'" % (table,ref) ).fetchall(): - f=Finder(cn,r['id'],int) + if ( cn.execute("SELECT count(*) from %s WHERE rowid=?"%table,[ref] ).fetchone()[0] > 0 ): + for r in cn.execute("SELECT kind,rowid FROM %s WHERE rowid=?" % table,[ref]).fetchall(): + f=Finder(cn,r['rowid'],int) j=process(f,str(r['kind'])) # is it in compounddef ? table="compounddef" - if ( cn.execute("SELECT count(*) from %s WHERE refid=?"%table,[ref]).fetchone()[0] > 0 ): - for r in cn.execute("SELECT id FROM %s WHERE refid=?"%table,[ref] ).fetchall(): - f=Finder(cn,r['id'],int) + if ( cn.execute("SELECT count(*) from %s WHERE rowid=?"%table,[ref]).fetchone()[0] > 0 ): + for r in cn.execute("SELECT rowid FROM %s WHERE rowid=?"%table,[ref] ).fetchall(): + f=Finder(cn,r[0],int) j=process(f,RequestType.Struct) return j @@ -290,7 +293,7 @@ def processHref(cn,ref): def serveCgi(): import cgi - print 'Content-Type: application/json\n' + print('Content-Type: application/json\n') fieldStorage = cgi.FieldStorage() form = dict((key, fieldStorage.getvalue(key)) for key in fieldStorage.keys()) @@ -298,17 +301,17 @@ def serveCgi(): if 'href' in form: ref = form['href'] else: - print '{"result": null, "error": "no refid given"}' + print('{"result": null, "error": "no refid given"}') sys.exit(0) cn=openDb('doxygen_sqlite3.db') j = processHref(cn,ref) - print json.dumps({"result":j,"error":None}) + print(json.dumps({"result":j,"error":None})) ############################################################################### def usage(): - print >>sys.stderr,"""Usage: search.py [Options] + sys.stderr.write("""Usage: search.py [Options] Options: -h, --help -d <D> Use database <D> for queries. @@ -323,7 +326,7 @@ Options: -M <C> Get all members of class <C>. -S <C> Get the sub classes of class <C>. -R Consider the search <term> to be a regex. -""" +""") ############################################################################### def serveCli(argv): try: @@ -362,6 +365,8 @@ def serveCli(argv): elif a in ('-f'): kind=MemberType.Function elif a in ('-F'): + # undocumented + # seems to fit with the lower case "search" patterns? kind=MemberType.File elif a in ('-m'): kind=MemberType.Define @@ -370,6 +375,7 @@ def serveCli(argv): elif a in ('-v'): kind=MemberType.Variable elif a in ('-H'): + # undocumented ref = o cn=openDb(dbname) @@ -378,7 +384,7 @@ def serveCli(argv): j=processHref(cn,ref) else: j=process(f,kind) - print json.dumps(j,indent=4) + print(json.dumps(j,indent=4)) def main(argv): diff --git a/addon/doxywizard/doxywizard.cpp b/addon/doxywizard/doxywizard.cpp index 492912b..4e0d1aa 100755 --- a/addon/doxywizard/doxywizard.cpp +++ b/addon/doxywizard/doxywizard.cpp @@ -267,7 +267,7 @@ void MainWindow::saveConfig(const QString &fileName) { if (fileName.isEmpty()) return; QFile f(fileName); - if (!f.open(QIODevice::WriteOnly)) + if (!f.open(QIODevice::WriteOnly | QIODevice::Text )) { QMessageBox::warning(this, tr("Error saving"), diff --git a/addon/doxywizard/expert.cpp b/addon/doxywizard/expert.cpp index 66a0955..44dea78 100644 --- a/addon/doxywizard/expert.cpp +++ b/addon/doxywizard/expert.cpp @@ -765,9 +765,10 @@ void Expert::saveTopic(QTextStream &t,QDomElement &elem,QTextCodec *codec, t << convertToComment(option->templateDocs()); t << endl; } - t << name.leftJustified(MAX_OPTION_LENGTH) << "= "; - if (option) + t << name.leftJustified(MAX_OPTION_LENGTH) << "="; + if (option && !option->isEmpty()) { + t << " "; option->writeValue(t,codec); } t << endl; diff --git a/addon/doxywizard/input.h b/addon/doxywizard/input.h index 9e0a1bf..5d86cc8 100644 --- a/addon/doxywizard/input.h +++ b/addon/doxywizard/input.h @@ -30,6 +30,7 @@ class Input virtual void reset() = 0; virtual void writeValue(QTextStream &t,QTextCodec *codec) = 0; virtual void setTemplateDocs(const QString &docs) = 0; + virtual bool isEmpty() { return false; }; }; diff --git a/addon/doxywizard/inputstring.h b/addon/doxywizard/inputstring.h index dba31f6..6234256 100644 --- a/addon/doxywizard/inputstring.h +++ b/addon/doxywizard/inputstring.h @@ -60,6 +60,7 @@ class InputString : public QObject, public Input void updateDependencies() {} void writeValue(QTextStream &t,QTextCodec *codec); void setTemplateDocs(const QString &docs) { m_tdocs = docs; } + bool isEmpty() { return m_str.isEmpty(); } public slots: void reset(); diff --git a/addon/doxywizard/inputstrlist.cpp b/addon/doxywizard/inputstrlist.cpp index 660ce40..822bc4c 100644 --- a/addon/doxywizard/inputstrlist.cpp +++ b/addon/doxywizard/inputstrlist.cpp @@ -260,3 +260,11 @@ void InputStrList::writeValue(QTextStream &t,QTextCodec *codec) } } +bool InputStrList::isEmpty() +{ + foreach (QString s, m_strList) + { + if (!s.isEmpty()) return false; + } + return true; +} diff --git a/addon/doxywizard/inputstrlist.h b/addon/doxywizard/inputstrlist.h index 53f3bcc..c374092 100644 --- a/addon/doxywizard/inputstrlist.h +++ b/addon/doxywizard/inputstrlist.h @@ -55,6 +55,7 @@ class InputStrList : public QObject, public Input void updateDependencies() {} void writeValue(QTextStream &t,QTextCodec *codec); void setTemplateDocs(const QString &docs) { m_tdocs = docs; } + bool isEmpty(); public slots: void reset(); diff --git a/appveyor.yml b/appveyor.yml new file mode 100644 index 0000000..1119f38 --- /dev/null +++ b/appveyor.yml @@ -0,0 +1,52 @@ +image: Visual Studio 2017 + +configuration: + - Release + - Debug + +platform: + - x64 + - Win32 + +environment: + # VS VERSION IN CMAKE STYLE + matrix: + - VSVERSION: "15 2017" + - VSVERSION: "14 2015" + +init: + - cmake --version + - perl --version + - msbuild /version + +install: + - ps: Invoke-WebRequest https://github.com/lexxmark/winflexbison/releases/download/v2.5.15/win_flex_bison-2.5.15.zip -OutFile flex.zip + - 7z x flex.zip -oC:\deps\flex + - ps: Invoke-WebRequest https://github.com/ArtifexSoftware/ghostpdl-downloads/releases/download/gs924/gs924w32.exe -OutFile gswin32c.exe + - gswin32c /S /D=C:\deps\ghostscript + - ps: if($env:platform -eq "x64") { Invoke-WebRequest https://miktex.org/download/win/miktexsetup-x64.zip -OutFile miktexsetup.zip } + - ps: if($env:platform -eq "Win32") { Invoke-WebRequest https://miktex.org/download/win/miktexsetup-x86.zip -OutFile miktexsetup.zip } + - 7z x miktexsetup.zip -oC:\tmpmiktex + - C:\tmpmiktex\miktexsetup --local-package-repository=C:\temp\miktex --package-set=basic download + - C:\tmpmiktex\miktexsetup --verbose --local-package-repository=C:\temp\miktex --package-set=basic install + - refreshenv + - pip install conan + - conan install libxml2/2.9.8@bincrafters/stable -g virtualrunenv + - activate_run.bat + - set "PATH=%PATH%;C:\deps\ghostscript\bin;C:\deps\flex" + +before_build: + - if "%platform%"=="Win32" ( set "CMAKE_GENERATOR_NAME=Visual Studio %VSVERSION%" ) + - if "%platform%"=="x64" ( set "CMAKE_GENERATOR_NAME=Visual Studio %VSVERSION% Win64") + - mkdir build + - cd build + - cmake -G "%CMAKE_GENERATOR_NAME%" .. + +build: + project: "build\\PACKAGE.vcxproj" + parallel: false + +test_script: + - msbuild "testing\tests.vcxproj" /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" + - cmake -G "%CMAKE_GENERATOR_NAME%" -D build_doc=ON .. +# - msbuild "doc\docs.vcxproj" /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" diff --git a/cmake/FindSQLite3.cmake b/cmake/FindSQLite3.cmake index 77b8eb4..45cc212 100644 --- a/cmake/FindSQLite3.cmake +++ b/cmake/FindSQLite3.cmake @@ -71,8 +71,16 @@ else (SQLITE3_LIBRARIES AND SQLITE3_INCLUDE_DIRS) endif (SQLITE3_INCLUDE_DIRS AND SQLITE3_LIBRARIES) if (SQLITE3_FOUND) + + # Extract version from header file + find_file(SQLITE3_HEADER "sqlite3.h" HINTS ${SQLITE3_INCLUDE_DIRS}) + if(SQLITE3_HEADER) + file(STRINGS "${SQLITE3_HEADER}" _DEF_TMP REGEX "^#define SQLITE_VERSION +\\\"[^\\\"]+\\\"") + string (REGEX REPLACE ".*\\\"(([0-9]+[.]?)+).*" "\\1" SQLITE3_VERSION "${_DEF_TMP}") + endif (SQLITE3_HEADER) + if (NOT Sqlite3_FIND_QUIETLY) - message(STATUS "Found Sqlite3: ${SQLITE3_LIBRARIES}") + message(STATUS "Found Sqlite3: ${SQLITE3_LIBRARIES} (found version \"${SQLITE3_VERSION}\")") endif (NOT Sqlite3_FIND_QUIETLY) else (SQLITE3_FOUND) if (Sqlite3_FIND_REQUIRED) diff --git a/doc/arch.doc b/doc/arch.doc index ed9d579..bd51a1b 100644 --- a/doc/arch.doc +++ b/doc/arch.doc @@ -248,7 +248,21 @@ Note that by running doxygen with `-d lex` you get information about which <h3>Testing</h3> Doxygen has a small set of tests available to test, some, code integrity. -The tests can be run by means of the command `make tests`. When only one or a few tests are required one can set the variable \c TEST_FLAGS when running the test e.g. `make TEST_FLAGS="--id 5" tests` or for multiple tests `make TEST_FLAGS="--id 5 --id 7" tests`. +The tests can be run by means of the command `make tests`. When only one or a +few tests are required one can set the variable \c TEST_FLAGS when running the +test e.g. `make TEST_FLAGS="--id 5" tests` or for multiple tests +`make TEST_FLAGS="--id 5 --id 7" tests`. For a full set of possibilities give the +command `make TEST_FLAGS="--help" tests`. It is also possible to specify the +`TEST_FLAGS` as an environment variable (works also for testing through Visual +Studio projects), e.g. `setenv TEST_FLAGS "--id 5 --id 7"` and `make tests`. + +<h3>Doxyfile differences</h3> + +In case one has to communicate through e.g. a forum the configuration settings that +are different from the standard doxygen configuration file settings one can run the +doxygen command: with the `-x` option and the name of the configuration file (default +is `Doxyfile`). The output will be a list of the not default settings (in `Doxyfile` +format). \htmlonly Return to the <a href="index.html">index</a>. diff --git a/doc/changelog.doc b/doc/changelog.doc index 0b245b6..ca00728 100644 --- a/doc/changelog.doc +++ b/doc/changelog.doc @@ -718,7 +718,7 @@ <li>Bug <a href="https://github.com/doxygen/doxygen/issues/5569">5569</a> - Fix a potential null pointer dereference in src/searchindex.cpp [<a href="http://github.com/doxygen/doxygen/commit/e21aaadb920775f431a27957542da80e39d0c947">view</a>]</li> <li>Bug <a href="https://github.com/doxygen/doxygen/issues/5570">5570</a> - Fix wrong pointer initialization in src/definition.cpp [<a href="http://github.com/doxygen/doxygen/commit/cb5d8e6198fe0d0852fb06d6fa18b8ae2682e2c0">view</a>]</li> <li>Bug <a href="https://github.com/doxygen/doxygen/issues/5571">5571</a> - Fix potential modulo by zero in src/template.cpp [<a href="http://github.com/doxygen/doxygen/commit/c4007c3abea9c8494bf32181a1352b5366bede69">view</a>]</li> -<li>Bug <a href="https://github.com/doxygen/doxygen/issues/5572">5572</a> - Reached end of file while still insided a (nested) comment in Markdown [<a href="http://github.com/doxygen/doxygen/commit/c7f7c954ec1356e7f361da0d655c72ca0012a0cf">view</a>]</li> +<li>Bug <a href="https://github.com/doxygen/doxygen/issues/5572">5572</a> - Reached end of file while still inside a (nested) comment in Markdown [<a href="http://github.com/doxygen/doxygen/commit/c7f7c954ec1356e7f361da0d655c72ca0012a0cf">view</a>]</li> <li>Bug <a href="https://github.com/doxygen/doxygen/issues/5573">5573</a> - Fix a terminating null character after fread in src/filedef.cpp [<a href="http://github.com/doxygen/doxygen/commit/a4003db44dfb624c03b7e0a518e368d3e4b8c1ca">view</a>]</li> <li>Bug <a href="https://github.com/doxygen/doxygen/issues/5574">5574</a> - Remove not needed variable initialization in src/classdef.cpp [<a href="http://github.com/doxygen/doxygen/commit/5f01852bbfd3c81320ee4aa8cd45875a80b50ee1">view</a>]</li> <li>Bug <a href="https://github.com/doxygen/doxygen/issues/5575">5575</a> - Remove not needed pointer initialization in src/entry.cpp [<a href="http://github.com/doxygen/doxygen/commit/88832b15f1256846b1228ac411d270c6d092a50b">view</a>]</li> @@ -2182,7 +2182,7 @@ make sure you add the following: <h3>New features</h3> <ul> <li> Added support for - <a href="http://daringfireball.net/projects/markdown/">Markdown</a> + <a href="https://daringfireball.net/projects/markdown/">Markdown</a> formatting. This is enabled by default, but can be disabled by setting MARKDOWN_SUPPORT to NO. When enabled the following is @@ -2803,7 +2803,7 @@ make sure you add the following: <li> id <a href="https://github.com/doxygen/doxygen/issues/3190">3190</a>: dropped support for a4wide paper format for LaTeX, since it is on the LaTeX taboo list.</li> <li> id <a href="https://github.com/doxygen/doxygen/issues/3261">3261</a>: Behaviour of CLASS_DIAGRAM=NO in combination with - HAVE_DOT=YES, was not propely documented.</li> + HAVE_DOT=YES, was not properly documented.</li> <li> id <a href="https://github.com/doxygen/doxygen/issues/3332">3332</a>: Python comments for next class or method could end up in code of a method/class when enabling INLINE_SOURCES.</li> <li> id <a href="https://github.com/doxygen/doxygen/issues/3688">3688</a>: Fixed problem handling nested classes in Python.</li> diff --git a/doc/commands.doc b/doc/commands.doc index a630aac..840c3b7 100644 --- a/doc/commands.doc +++ b/doc/commands.doc @@ -1888,7 +1888,7 @@ Commands to create links \section cmdaddindex \\addindex (text) \addindex \\addindex - This command adds (text) to the \LaTeX index. + This command adds (text) to the \LaTeX , DocBook and RTF index. <hr> \section cmdanchor \\anchor <word> @@ -2034,7 +2034,7 @@ Make sure you have first read \ref intro "the introduction". \addindex \\tableofcontents Creates a table of contents at the top of a page, listing all sections and subsections in the page. The `option` can be `HTML` or `LaTeX` - or `XML`. When a `level` is specified this means the maximum nesting level + or `XML` or `DocBook`. When a `level` is specified this means the maximum nesting level that is shown. The value of `level` should be in the range 1..5, values outside this range are considered to be 5. In case no `level` is specified `level` is set to 5 (show all) @@ -2608,7 +2608,7 @@ only copy the detailed documentation, not the brief description. \addindex \\docbookonly Starts a block of text that will be verbatim included in the - generated docbook documentation only. The block ends with a + generated DocBook documentation only. The block ends with a \ref cmdenddocbookonly "\\enddocbookonly" command. \sa section \ref cmdmanonly "\\manonly", @@ -3082,7 +3082,7 @@ class Receiver spaces. The quotes are stripped before the caption is displayed. The fourth argument is also optional and can be used to specify the - width or height of the image. This can be useful for \LaTeX or docbook output + width or height of the image. This can be useful for \LaTeX or DocBook output (i.e. format=<code>latex</code> or format=<code>docbook</code>). \anchor image_sizeindicator \par Size indication The \c sizeindication can specify the width or height to be used (or a combination). diff --git a/doc/custcmd.doc b/doc/custcmd.doc index acc0224..02805da 100644 --- a/doc/custcmd.doc +++ b/doc/custcmd.doc @@ -44,6 +44,11 @@ Note that you can put `\n`'s in the value part of an alias to insert newlines (in the resulting output). You can put `^^` in the value part of an alias to insert a newline as if a physical newline was in the original file. +Note when you need a literal `{` or `}` or `,` in the value part of an alias you have to +escape them by means of a backslash (`\`), this can lead to conflicts with the +commands \c \\{ and \c \\} for these it is advised to use the version \c @@{ and \c @@} or +use a double escape (\c \\\\{ and \c \\\\}) + Also note that you can redefine existing special commands if you wish. Some commands, such as \ref cmdxrefitem "\\xrefitem" are designed to be used in diff --git a/doc/docblocks.doc b/doc/docblocks.doc index f02e55b..ab144af 100644 --- a/doc/docblocks.doc +++ b/doc/docblocks.doc @@ -632,7 +632,7 @@ and is ideal for a short description. For longer descriptions you often will find the need for some more structure, like a block of verbatim text, a list, or a simple table. For this doxygen supports the -<a href="http://daringfireball.net/projects/markdown/syntax">Markdown</a> +<a href="https://daringfireball.net/projects/markdown/syntax">Markdown</a> syntax, including parts of the <a href="https://michelf.ca/projects/php-markdown/extra/">Markdown Extra</a> extension. @@ -648,8 +648,9 @@ forms of additional markup on top of Markdown formatting. 1. <a href="https://en.wikipedia.org/wiki/Javadoc">Javadoc</a> like markup. See \ref commands for a complete overview of all commands supported by doxygen. -2. <a href="https://en.wikipedia.org/wiki/C_Sharp_(programming_language)#XML_documentation_system">XML</a> markup - as specified in the C# standard. See \ref xmlcmds for the XML commands supported by doxygen. +2. <a href="https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/xmldoc/recommended-tags-for-documentation-comments">XML</a> markup + as specified in the <a href="http://standards.iso.org/ittf/PubliclyAvailableStandards/c042926_ISO_IEC_23270_2006(E).zip">C# standard</a>. + See \ref xmlcmds for the XML commands supported by doxygen. If this is still not enough doxygen also supports a \ref htmlcmds "subset" of the <a href="https://en.wikipedia.org/wiki/HTML">HTML</a> markup language. diff --git a/doc/doxygen.1 b/doc/doxygen.1 index 5ac287e..a9c6b38 100644 --- a/doc/doxygen.1 +++ b/doc/doxygen.1 @@ -41,6 +41,10 @@ LaTeX: doxygen \fB\-w\fR latex headerFile footerFile styleSheetFile [configFile] .TP RTF: doxygen \fB\-e\fR rtf extensionsFile +.TP +7) Use doxygen to compare the used configuration file with the template configuration file +.TP +doxygen \fB\-x\fR [configFile] .PP If \fB\-s\fR is specified the comments in the config file will be omitted. If configName is omitted `Doxyfile' will be used as a default. diff --git a/doc/faq.doc b/doc/faq.doc index e9c93d8..f48e109 100644 --- a/doc/faq.doc +++ b/doc/faq.doc @@ -216,7 +216,7 @@ If you don't mind spending some time on it, there are several options: - If the grammar of X is somewhat different than you can write an input filter that translates X into something similar enough to C/C++ for doxygen to understand (this approach is taken for VB, Object Pascal, and - Javascript, see http://www.stack.nl/~dimitri/doxygen/download.html#helpers). + Javascript, see http://www.doxygen.org/download.html#helpers). - If the grammar is completely different one could write a parser for X and write a backend that produces a similar syntax tree as is done by \c src/scanner.l (and also by \c src/tagreader.cpp while reading tag files). diff --git a/doc/features.doc b/doc/features.doc index f6aa7c1..fbbdf44 100644 --- a/doc/features.doc +++ b/doc/features.doc @@ -100,7 +100,7 @@ Although doxygen can now be used in any project written in a language that is supported by doxygen, initially it was specifically designed to be used for projects that make use of Qt Software's -<A HREF="http://qt-project.org/">Qt toolkit</A>. I have tried to +<A HREF="https://www.qt.io/developers/">Qt toolkit</A>. I have tried to make doxygen `Qt-compatible'. That is: Doxygen can read the documentation contained in the Qt source code and create a class browser that looks quite similar to the one that is generated by Qt Software. Doxygen understands the C++ extensions diff --git a/doc/htmlcmds.doc b/doc/htmlcmds.doc index b8324f8..d483237 100644 --- a/doc/htmlcmds.doc +++ b/doc/htmlcmds.doc @@ -83,6 +83,8 @@ of a HTML tag are passed on to the HTML output only <li><tt>\</SMALL\></tt> Ends a <tt>\<SMALL\></tt> section. <li><tt>\<SPAN></tt> Starts an inline text fragment with a specific style (HTML only) <li><tt>\</SPAN></tt> Ends an inline text fragment with a specific style (HTML only) +<li><tt>\<STRIKE\></tt> Starts a section of strike through text. +<li><tt>\</STRIKE\></tt> Ends a section of strike through text. <li><tt>\<STRONG\></tt> Starts a section of bold text. <li><tt>\</STRONG\></tt> Ends a section of bold text. <li><tt>\<SUB\></tt> Starts a piece of text displayed in subscript. @@ -101,6 +103,8 @@ of a HTML tag are passed on to the HTML output only <li><tt>\</TT\></tt> Ends a <tt>\<TT\></tt> section. <li><tt>\<KBD\></tt> Starts a piece of text displayed in a typewriter font. <li><tt>\</KBD\></tt> Ends a <tt>\<KBD\></tt> section. +<li><tt>\<U\></tt> Starts a section of underlined text. +<li><tt>\</U\></tt> Ends a section of underlined text. <li><tt>\<UL\></tt> Starts an unnumbered item list. <li><tt>\</UL\></tt> Ends an unnumbered item list. <li><tt>\<VAR\></tt> Starts a piece of text displayed in an italic font. diff --git a/doc/index.doc b/doc/index.doc index 5bb7b2b..b8f6e8e 100644 --- a/doc/index.doc +++ b/doc/index.doc @@ -119,7 +119,7 @@ The third part provides information for developers: \addindex GPL Copyright © 1997-2016 by -<a href="mailto:dimitri@stack.nl">Dimitri van Heesch</a>.<p> +<a href="mailto:doxygen@gmail.com">Dimitri van Heesch</a>.<p> Permission to use, copy, modify, and distribute this software and its documentation under the terms of the GNU General Public License is hereby @@ -143,7 +143,7 @@ of real-life projects using doxygen. These are part of a larger <a href="http://www.doxygen.org/projects.html">list of projects</a> that use doxygen. -If you know other projects, let <a href="mailto:dimitri@stack.nl?subject=New%20project%20using%20Doxygen">me</a> +If you know other projects, let <a href="mailto:doxygen@gmail.com?subject=New%20project%20using%20Doxygen">me</a> know and I'll add them. <h2>Future work</h2> diff --git a/doc/install.doc b/doc/install.doc index 497a0c0..d64b259 100644 --- a/doc/install.doc +++ b/doc/install.doc @@ -36,6 +36,7 @@ following to build the executable: \addindex make \addindex strip \addindex python +<li>You need \c python (version 2.6 or higher, see https://www.python.org). <li>In order to generate a \c Makefile for your platform, you need <a href="https://cmake.org/">cmake</a> version 2.8.12 or later. \addindex cmake @@ -46,9 +47,9 @@ tools should be installed. <ul> <li>Qt Software's GUI toolkit - <a href="http://qt-project.org/">Qt</A> + <a href="https://www.qt.io/developers/">Qt</A> \addindex Qt - version 4.3 or higher (but currently, Qt 5.x is not yet supported). + version 4.3 or higher (including Qt 5). This is needed to build the GUI front-end doxywizard. <li>A \LaTeX distribution: for instance <a href="http://www.tug.org/interest.html#free">TeX Live</a> @@ -151,6 +152,7 @@ standard installation procedure that is required for these packages. From version 1.8.10 onwards, build files need to be generated by cmake. cmake can be downloaded from https://cmake.org/download/ +\addindex cmake At the moment only the express version of Visual Studio 2013 is tested, but other version might also work. @@ -160,9 +162,12 @@ Alternatively, you can compile doxygen <a href="https://en.wikipedia.org/wiki/Cygwin">Cygwin</a> or <a href="http://www.mingw.org/">MinGW</a>. +\addindex flex +\addindex bison The next step is to install modern versions of \c bison and \c flex (see https://sourceforge.net/projects/winflexbison/. After installation and adding them to your `path` rename `win_flex.exe` to `flex.exe` and `win_bison.exe` to `bison.exe`) +\addindex python Furthermore you have to install \c python (version 2.6 or higher, see https://www.python.org). These packages are needed during the compilation process. @@ -174,7 +179,7 @@ cd c:\tools tar zxvf doxygen-x.y.z.src.tar.gz \endverbatim to unpack the sources (you can obtain \c tar from e.g. http://gnuwin32.sourceforge.net/packages.html). -Alternatively you can use an unpack program, like 7-Zip (see http://www.7-zip.org) +Alternatively you can use an unpack program, like 7-Zip (see https://www.7-zip.org/) or use the build in unpack feature of modern Windows systems). Now your environment is setup to generate the required project files for \c doxygen. @@ -186,8 +191,8 @@ cd build cmake -G "Visual Studio 12 2013" .. \endverbatim -Note that compiling Doxywizard currently requires Qt version 4 -(see http://qt-project.org/). +Note that compiling Doxywizard requires Qt 4.3 or newer +(see https://www.qt.io/developers/). Also read the next section for additional tools you may need to install to run doxygen with certain features enabled. @@ -206,12 +211,12 @@ If you want to produce compressed HTML files (see \ref cfg_generate_htmlhelp "GENERATE_HTMLHELP") in the configuration file, then you need the Microsoft HTML help workshop. You can download it from -<a href="http://www.microsoft.com/en-us/download/details.aspx?id=21138">Microsoft</a>. +<a href="https://www.microsoft.com/en-us/download/details.aspx?id=21138">Microsoft</a>. If you want to produce Qt Compressed Help files (see \ref cfg_qhg_location "QHG_LOCATION") in the configuration file, then you need qhelpgenerator which is part of Qt. -You can download Qt from <a href="http://qt-project.org/downloads">Qt Software Downloads</a>. +You can download Qt from <a href="https://www.qt.io/download">Qt Software Downloads</a>. In order to generate PDF output or use scientific formulas you will also need to install <a href="https://en.wikipedia.org/wiki/LaTeX">LaTeX</a> and @@ -219,7 +224,7 @@ install <a href="https://en.wikipedia.org/wiki/LaTeX">LaTeX</a> and For \LaTeX a number of distributions exists. Popular ones that should work with doxygen are <a href="https://miktex.org/">MikTex</a> -and <a href="http://www.tug.org/protext/">proTeXt</a>. +and <a href="https://www.tug.org/protext/">proTeXt</a>. Ghostscript can be <a href="https://sourceforge.net/projects/ghostscript/">downloaded</a> from Sourceforge. diff --git a/doc/maintainers.txt b/doc/maintainers.txt index 3fa4fff..7ea40ac 100644 --- a/doc/maintainers.txt +++ b/doc/maintainers.txt @@ -50,10 +50,10 @@ Poul-Erik Hansen: pouhan at gnotometrics dot dk Erik Søe Sørensen: eriksoe+doxygen at daimi dot au dot dk TranslatorDutch -Dimitri van Heesch: dimitri at stack dot nl +Dimitri van Heesch: doxygen at gmail dot com TranslatorEnglish -Dimitri van Heesch: dimitri at stack dot nl +Dimitri van Heesch: doxygen at gmail dot com TranslatorEsperanto Ander MartÃnez: ander dot basaundi at gmail dot com diff --git a/doc/markdown.doc b/doc/markdown.doc index 92612ca..5edbaf9 100644 --- a/doc/markdown.doc +++ b/doc/markdown.doc @@ -41,7 +41,7 @@ the extensions that doxygen supports. Finally section \ref markdown_dox discusses some specifics for doxygen's implementation of the Markdown standard. -[markdown]: http://daringfireball.net/projects/markdown/ +[markdown]: https://daringfireball.net/projects/markdown/ [mdextra]: https://michelf.ca/projects/php-markdown/extra/ [github]: https://github.github.com/github-flavored-markdown/ @@ -173,7 +173,18 @@ Examples: * __double underscores__ See section \ref mddox_emph_spans for more info how doxygen handles -emphasis spans slightly different than standard Markdown. +emphasis / strikethrough spans slightly different than standard / Markdown GitHub Flavored Markdown. + +\subsection md_strikethrough Strikethrough + +To strikethrough a text fragment you start and end the fragment with two tildes. + +Examples: + +* ~~double tilde~~ + +See section \ref mddox_emph_spans for more info how doxygen handles +emphasis / strikethrough spans slightly different than standard Markdown / GitHub Flavored Markdown. \subsection md_codespan code spans @@ -567,22 +578,22 @@ For Item1 the indentation is 4 (when treating the list marker as whitespace), so the next paragraph "More text..." starts at the same indentation level and is therefore not seen as a code block. -\subsection mddox_emph_spans Emphasis limits +\subsection mddox_emph_spans Emphasis and strikethrough limits -Unlike standard Markdown, doxygen will not touch internal underscores or -stars, so the following will appear as-is: +Unlike standard Markdown and Github Flavored Markdown doxygen will not touch internal underscores or +stars or tildes, so the following will appear as-is: a_nice_identifier -Furthermore, a `*` or `_` only starts an emphasis if +Furthermore, a `*` or `_` only starts an emphasis and a `~` only starts a strikethrough if - it is followed by an alphanumerical character, and - it is preceded by a space, newline, or one the following characters `<{([,:;` -An emphasis ends if +An emphasis or a strikethrough ends if - it is not followed by an alphanumerical character, and - it is not preceded by a space, newline, or one the following characters `({[<=+-\@` -Lastly, the span of the emphasis is limited to a single paragraph. +Lastly, the span of the emphasis or strikethrough is limited to a single paragraph. \subsection mddox_code_spans Code Spans Limits diff --git a/doc/output.doc b/doc/output.doc index 3a24a60..6d1a567 100644 --- a/doc/output.doc +++ b/doc/output.doc @@ -32,7 +32,7 @@ The following output formats are \e directly supported by doxygen: Word. If you have success with other programs, please let me know. <dt><b>XML</b> <dd>Generated if \ref cfg_generate_xml "GENERATE_XML" is set to \c YES in the configuration file.<p> -<dt><b>Docbook</b> +<dt><b>DocBook</b> <dd>Generated if \ref cfg_generate_docbook "GENERATE_DOCBOOOK" is set to \c YES in the configuration file.<p> </dl> diff --git a/doc/searching.doc b/doc/searching.doc index cb6b84a..9bc518a 100644 --- a/doc/searching.doc +++ b/doc/searching.doc @@ -126,7 +126,7 @@ has its own advantages and disadvantages: options you may want to set. After doxygen has finished you will find a Makefile in the HTML output directory. Running "make install" on this Makefile will compile and install the doc set. - See <a href="https://developer.apple.com/library/mac/#featuredarticles/DoxygenXcode/_index.html">this + See <a href="https://developer.apple.com/library/archive/featuredarticles/DoxygenXcode/_index.html">this article</a> for more info. Advantage of this method is that it nicely integrates with the Xcode @@ -139,7 +139,7 @@ has its own advantages and disadvantages: <h2>6. Qt Compressed Help</h2> If you develop for or want to install the Qt application framework, you will get an application - called <a href="http://qt-project.org/doc/qt-4.8/assistant-manual.html">Qt assistant</a>. + called <a href="http://doc.qt.io/archives/qt-4.8/assistant-manual.html">Qt assistant</a>. This is a help viewer for Qt Compressed Help files (<code>.qch</code>). To enable this feature set \ref cfg_generate_qhp "GENERATE_QHP" to \c YES. diff --git a/doc/starting.doc b/doc/starting.doc index 0765a3b..64d3be0 100644 --- a/doc/starting.doc +++ b/doc/starting.doc @@ -263,7 +263,7 @@ capabilities of the man page format, so some information \subsection docbook_out DocBook output \addindex docbook Doxygen can also generate output in the -<a href="http://docbook.org/">DocBook</a> format. How to process the +<a href="https://docbook.org/">DocBook</a> format. How to process the DocBook output is beyond the scope of this manual. \section step3 Step 3: Documenting the sources diff --git a/doc/trouble.doc b/doc/trouble.doc index 6b05cd3..c490ae1 100644 --- a/doc/trouble.doc +++ b/doc/trouble.doc @@ -128,7 +128,7 @@ please use PATCH as a keyword in the bug entry form. If you have ideas how to fix existing bugs and limitations please discuss them on the <a href="http://sourceforge.net/mail/?group_id=5971">developers mailing list</a> -(subscription required). Patches can also be sent directly to dimitri@stack.nl if +(subscription required). Patches can also be sent directly to doxygen@gmail.com if you prefer not to send them via the bug tracker or mailing list. For patches please use diff --git a/examples/dbusxml.cfg b/examples/dbusxml.cfg deleted file mode 100644 index d964ea2..0000000 --- a/examples/dbusxml.cfg +++ /dev/null @@ -1,14 +0,0 @@ -PROJECT_NAME = "DBusXMLDocs" -OUTPUT_DIRECTORY = ../html/examples/dbusxml -GENERATE_LATEX = YES -GENERATE_MAN = NO -GENERATE_RTF = NO -CASE_SENSE_NAMES = NO -INPUT = dbusxml.xml -QUIET = YES -JAVADOC_AUTOBRIEF = YES -EXTRACT_ALL = YES -SEARCHENGINE = NO -EXTENSION_MAPPING = xml=dbusxml -COMPACT_LATEX = YES -LATEX_HIDE_INDICES = YES diff --git a/examples/dbusxml.xml b/examples/dbusxml.xml deleted file mode 100644 index 4ab7f78..0000000 --- a/examples/dbusxml.xml +++ /dev/null @@ -1,78 +0,0 @@ -<?xml version="1.0" ?> -<!-- Comment --> -<!--*< File comment --> -<node name="/SomeNode" xmlns:dx="http://psiamp.org/dtd/doxygen_dbusxml.dtd"> - <!--* test struct outside a namespace and interface --> - <dx:struct name="StructOutsideNamespace"> - <!--* member 1 --> - <dx:member name="member1" type="s"/> - <!--* complex member 1 --> - <dx:member name="complexMember1" type="(ssu)"/> - </dx:struct> - - <!--* Test flag set --> - <dx:flagset name="flagset"> - <!--* Flag 1 of flagset. --> - <dx:value name="FLAG1"/> - </dx:flagset> - - <!--* namespace comment --> - <dx:namespace name="SomeNamespace"> - <!--* struct inside a namespace --> - <dx:struct name="StructInNamespace"> - <!--* member 2 --> - <dx:member name="member2" type="s"/> - </dx:struct> - </dx:namespace> - <!--* Documentation on the interface --> - <interface name="nl.stack.doxygen.test.interface"> - <!--* Test Enum documentation --> - <dx:enum name="TestEnum"> - <!--* key 1 with value 13 --> - <dx:value name="KEY1" value="13"/> - <!--* key 2 without a value --> - <dx:value name="KEY2"/> - </dx:enum> - - <!--* struct inside a interface --> - <dx:struct name="StructInInterface"> - <!--* member 3 --> - <dx:member name="member3" type="s"/> - <!--* Struct in a struct --> - <dx:struct name="StructInAStruct"> - <!--* member4 --> - <dx:member name="member4" type="s"/> - </dx:struct> - <!--* struct member --> - <dx:member name="structMembor" type="(s)" named-type="StructInAStruct"/> - </dx:struct> - <!--* Document method - - Some extended documentation for the method. - - @param[in] input blah. - @param[out] output blub - --> - <method name="method"> - <arg direction="in" name="input" type="(s(s))" named-type="::nl::stack::doxygen::test::interface::StructInInterface"/> - <arg direction="out" type="v" name="output"/> - </method> - - <signal name="signal"> - <!--*< Documentation for signal. - - @param parameter some parameter. - --> - <arg name="parameter" type="s"/> - </signal> - - <!--* property documentation --> - <property name="property" type="s" access="readwrite"/> - - <!--* property documentation read-only --> - <property name="propertyRead" type="s" access="read"/> - <!--* property documentation write-only --> - <property name="propertyWrite" type="s" access="write"/> - </interface> -</node> -<!-- vim:set sw=2 sts=2 et ft=xml: --> diff --git a/src/clangparser.cpp b/src/clangparser.cpp index 78b8faa..18dd404 100644 --- a/src/clangparser.cpp +++ b/src/clangparser.cpp @@ -964,6 +964,7 @@ void ClangParser::writeSources(CodeOutputInterface &,FileDef *) ClangParser::ClangParser() { + p = NULL; } ClangParser::~ClangParser() diff --git a/src/classdef.cpp b/src/classdef.cpp index 657968e..28308db 100644 --- a/src/classdef.cpp +++ b/src/classdef.cpp @@ -671,6 +671,10 @@ void ClassDef::internalInsertMember(MemberDef *md, case MemberType_Variable: addMemberToList(MemberListType_variableMembers,md,FALSE); break; + case MemberType_Define: + warn(md->getDefFileName(),md->getDefLine()-1,"A define (%s) cannot be made a member of %s", + md->name().data(), this->name().data()); + break; default: err("Unexpected member type %d found!\n",md->memberType()); } @@ -1013,13 +1017,13 @@ void ClassDef::writeDetailedDocumentationBody(OutputList &ol) // write examples if (hasExamples() && m_impl->exampleSDict) { - ol.startSimpleSect(BaseOutputDocInterface::Examples,0,0,theTranslator->trExamples()+": "); + ol.startExamples(); ol.startDescForItem(); //ol.startParagraph(); writeExample(ol,m_impl->exampleSDict); //ol.endParagraph(); ol.endDescForItem(); - ol.endSimpleSect(); + ol.endExamples(); } //ol.newParagraph(); writeSourceDef(ol,name()); @@ -1110,7 +1114,15 @@ void ClassDef::showUsedFiles(OutputList &ol) ol.writeRuler(); - ol.parseText(generatedFromFiles()); + ol.pushGeneratorState(); + ol.disableAllBut(OutputGenerator::Docbook); + ol.startParagraph(); + ol.parseText(generatedFromFiles()); + ol.endParagraph(); + ol.popGeneratorState(); + ol.disable(OutputGenerator::Docbook); + ol.parseText(generatedFromFiles()); + ol.enable(OutputGenerator::Docbook); bool first=TRUE; QListIterator<FileDef> li(m_impl->files); @@ -1223,7 +1235,7 @@ void ClassDef::writeInheritanceGraph(OutputList &ol) } } else if (Config_getBool(CLASS_DIAGRAMS) && count>0) - // write class diagram using build-in generator + // write class diagram using built-in generator { ClassDiagram diagram(this); // create a diagram of this class. ol.startClassDiagram(); @@ -1839,6 +1851,7 @@ void ClassDef::writeMoreLink(OutputList &ol,const QCString &anchor) // LaTeX + RTF ol.disable(OutputGenerator::Html); ol.disable(OutputGenerator::Man); + ol.disable(OutputGenerator::Docbook); if (!(usePDFLatex && pdfHyperlinks)) { ol.disable(OutputGenerator::Latex); diff --git a/src/cmdmapper.cpp b/src/cmdmapper.cpp index 2c8effc..71da3f3 100644 --- a/src/cmdmapper.cpp +++ b/src/cmdmapper.cpp @@ -193,6 +193,8 @@ CommandMap htmlTagMap[] = { "span", HTML_SPAN }, { "div", HTML_DIV }, { "blockquote", HTML_BLOCKQUOTE }, + { "strike", HTML_STRIKE }, + { "u", HTML_UNDERLINE }, { "c", XML_C }, // { "code", XML_CODE }, <= ambiguous <code> is also a HTML tag diff --git a/src/cmdmapper.h b/src/cmdmapper.h index 8cb529d..d06de63 100644 --- a/src/cmdmapper.h +++ b/src/cmdmapper.h @@ -175,6 +175,8 @@ enum HtmlTagType HTML_SPAN = 31, HTML_DIV = 32, HTML_BLOCKQUOTE= 33, + HTML_STRIKE = 34, + HTML_UNDERLINE = 35, XML_CmdMask = 0x100, @@ -983,7 +983,7 @@ static void generateClassOrGlobalLink(CodeOutputInterface &ol,const char *clName } } NamespaceDef *nd = getResolvedNamespace(className); - if (nd) + if (nd && nd->isLinkableInProject()) { g_theCallContext.setScope(nd); addToSearchIndex(className); @@ -1324,7 +1324,9 @@ static void generateFunctionLink(CodeOutputInterface &ol,const char *funcName) //CodeClassDef *ccd=0; ClassDef *ccd=0; QCString locScope=g_classScope; - QCString locFunc=removeRedundantWhiteSpace(funcName); + QString qq=removeRedundantWhiteSpace(funcName); + if (g_insidePHP && qq.startsWith("self::")) qq=qq.mid(4); + QCString locFunc(qq.data()); QCString funcScope; QCString funcWithScope=locFunc; QCString funcWithFullScope=locFunc; @@ -2170,8 +2172,12 @@ RAWEND ")"[^ \t\(\)\\]{0,16}\" g_code->codify(yytext); endFontClass(); } +<ClassName>{ID}("."{ID})* | <ClassName>{ID}("::"{ID})* { - g_curClassName=yytext; + if(g_insideCS) + g_curClassName=substitute(yytext,".","::"); + else + g_curClassName=yytext; addType(); if (g_curClassName=="alignas") { @@ -2596,7 +2602,7 @@ RAWEND ")"[^ \t\(\)\\]{0,16}\" generatePHPVariableLink(*g_code,yytext); g_name+=yytext+7; } -<Body,TemplCast>{SCOPENAME}{B}*"<"[^\n\/\-\.\{\"\>]*">"("::"{ID})*/{B}* { // A<T> *pt; +<Body,TemplCast>{SCOPENAME}{B}*"<"[^\n\/\-\.\{\"\>\(]*">"("::"{ID})*/{B}* { // A<T> *pt; int i=QCString(yytext).find('<'); QCString kw = QCString(yytext).left(i).stripWhiteSpace(); if (kw.right(5)=="_cast" && YY_START==Body) @@ -2627,6 +2633,7 @@ RAWEND ")"[^ \t\(\)\\]{0,16}\" addType(); g_name=varname; } +<Body>{SCOPETNAME}{B}*"<"[^\n\/\-\.\{\"\>]*">"/{BN}*"(" | <Body>{SCOPETNAME}/{BN}*"(" { // a() or c::a() or t<A,B>::a() or A\B\foo() addType(); generateFunctionLink(*g_code,yytext); diff --git a/src/commentscan.l b/src/commentscan.l index 39b0edc..1d84917 100644 --- a/src/commentscan.l +++ b/src/commentscan.l @@ -1005,7 +1005,7 @@ RCSTAG "$"{ID}":"[^\n$]+"$" * words and whitespace and other characters (#,?!, etc). * grouping commands (e.g. @{ and @}) * language switch (e.g. \~english or \~). - * mail address (e.g. dimitri@stack.nl). + * mail address (e.g. doxygen@gmail.com). * quoted text, such as "foo@bar" * XML commands, <summary></summary><remarks></remarks> */ @@ -1589,8 +1589,12 @@ RCSTAG "$"{ID}":"[^\n$]+"$" <PageDocArg1>. { // ignore other stuff } <PageDocArg2>.*"\n" { // second argument; page title - yyLineNr++; - current->args = yytext; + yyLineNr++; + // bug 748927 + QCString tmp = yytext; + tmp = substitute(substitute(tmp,"@<","<"),"@>",">"); + tmp = substitute(substitute(tmp,"\\<","<"),"\\>",">"); + current->args = tmp; addOutput('\n'); BEGIN( Comment ); } @@ -2949,6 +2953,10 @@ static bool handleToc(const QCString &, const QCStringList &optList) { current->localToc.enableXml(level); } + else if (opt == "docbook") + { + current->localToc.enableDocbook(level); + } else { warn(yyFileName,yyLineNr,"Unknown option specified with \\tableofcontents: `%s'", (*it).stripWhiteSpace().data()); diff --git a/src/config.h b/src/config.h index e86e950..102774e 100644 --- a/src/config.h +++ b/src/config.h @@ -51,6 +51,11 @@ namespace Config */ void writeTemplate(FTextStream &t,bool shortList,bool updateOnly=FALSE); + /*! Writes a the differences between the current configuration and the + * template configuration to stream \a t. + */ + void compareDoxyfile(FTextStream &t); + /*! Parses a configuration file with name \a fn. * \returns TRUE if successful, FALSE if the file could not be * opened or read. @@ -61,7 +66,7 @@ namespace Config * and replaces environment variables. * \param clearHeaderAndFooter set to TRUE when writing header and footer templates. */ - void postProcess(bool clearHeaderAndFooter); + void postProcess(bool clearHeaderAndFooter, bool compare = FALSE); /*! Check the validity of the parsed options and correct or warn the user where needed. */ void checkAndCorrect(); diff --git a/src/config.xml b/src/config.xml index 2e0f430..0c09cca 100644 --- a/src/config.xml +++ b/src/config.xml @@ -110,7 +110,7 @@ SEARCHENGINE = NO \endverbatim To generate the documentation for the -<a href="http://www.stack.nl/~dimitri/qdbttabular/index.html">QdbtTabular</a> package +<a href="https://sourceforge.net/projects/qdbttabular/">QdbtTabular</a> package I have used the following configuration file: \verbatim PROJECT_NAME = QdbtTabular @@ -551,6 +551,30 @@ Go to the <a href="commands.html">next</a> section or return to the a physical newline was in the original file. ]]> </docs> + <docs doxyfile='0' documentation='0'> +<![CDATA[ + When you need a literal `{` or `}` or `,` in the value part of an alias you have to + escape them by means of a backslash, this can lead to conflicts with the + commands \c \\{ and \c \\} for these it is advised to use the version \c @{ and \c @} or + use a double escape (\c \\\\{ and \c \\\\}) +]]> + </docs> + <docs doxywizard='0' documentation='0'> +<![CDATA[ + When you need a literal `{` or `}` or `,` in the value part of an alias you have to + escape them by means of a backslash (\c \\), this can lead to conflicts with the + commands \c \\{ and \c \\} for these it is advised to use the version \c @{ and \c @} or + use a double escape (\c \\\\{ and \c \\\\}) +]]> + </docs> + <docs doxyfile='0' doxywizard='0'> +<![CDATA[ + When you need a literal `{` or `}` or `,` in the value part of an alias you have to + escape them by means of a backslash (`\`), this can lead to conflicts with the + commands \c \\{ and \c \\} for these it is advised to use the version \c @@{ and \c @@} or + use a double escape (\c \\\\{ and \c \\\\}) +]]> + </docs> </option> <option type='list' id='TCL_SUBST' format='string'> <docs> @@ -626,7 +650,7 @@ Go to the <a href="commands.html">next</a> section or return to the <![CDATA[ If the \c MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments according to the Markdown format, which allows for more readable - documentation. See http://daringfireball.net/projects/markdown/ for details. + documentation. See https://daringfireball.net/projects/markdown/ for details. The output of markdown processing is further processed by doxygen, so you can mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in case of backward compatibilities issues. @@ -2015,15 +2039,15 @@ hr.footer { <![CDATA[ If the \c GENERATE_DOCSET tag is set to \c YES, additional index files will be generated that can be used as input for - <a href="https://developer.apple.com/tools/xcode/">Apple's Xcode 3 + <a href="https://developer.apple.com/xcode/">Apple's Xcode 3 integrated development environment</a>, introduced with OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a Makefile in the HTML output directory. Running \c make will produce the docset in that directory and running <code>make install</code> will install the docset in <code>~/Library/Developer/Shared/Documentation/DocSets</code> so that Xcode will find it at startup. See - https://developer.apple.com/tools/creatingdocsetswithdoxygen.html for - more information. + https://developer.apple.com/library/archive/featuredarticles/DoxygenXcode/_index.html + for more information. ]]> </docs> </option> @@ -2071,7 +2095,7 @@ The \c DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. doxygen generates three additional HTML index files: \c index.hhp, \c index.hhc, and \c index.hhk. The \c index.hhp is a project file that can be read by - <a href="http://www.microsoft.com/en-us/download/details.aspx?id=21138"> + <a href="https://www.microsoft.com/en-us/download/details.aspx?id=21138"> Microsoft's HTML Help Workshop</a> on Windows. <br> @@ -2167,7 +2191,7 @@ The \c DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. <![CDATA[ The \c QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help Project output. For more information please see - <a href="http://doc.qt.io/qt-4.8/qthelpproject.html#namespace">Qt Help Project / Namespace</a>. + <a href="http://doc.qt.io/archives/qt-4.8/qthelpproject.html#namespace">Qt Help Project / Namespace</a>. ]]> </docs> </option> @@ -2176,7 +2200,7 @@ The \c DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. <![CDATA[ The \c QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt Help Project output. For more information please see - <a href="http://doc.qt.io/qt-4.8/qthelpproject.html#virtual-folders">Qt Help Project / Virtual Folders</a>. + <a href="http://doc.qt.io/archives/qt-4.8/qthelpproject.html#virtual-folders">Qt Help Project / Virtual Folders</a>. ]]> </docs> </option> @@ -2184,7 +2208,7 @@ The \c DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. <docs> <![CDATA[ If the \c QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom filter to add. For more information please see - <a href="http://doc.qt.io/qt-4.8/qthelpproject.html#custom-filters">Qt Help Project / Custom Filters</a>. + <a href="http://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters">Qt Help Project / Custom Filters</a>. ]]> </docs> </option> @@ -2193,7 +2217,7 @@ The \c DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. <![CDATA[ The \c QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the custom filter to add. For more information please see - <a href="http://doc.qt.io/qt-4.8/qthelpproject.html#custom-filters">Qt Help Project / Custom Filters</a>. + <a href="http://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters">Qt Help Project / Custom Filters</a>. ]]> </docs> </option> @@ -2201,7 +2225,7 @@ The \c DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. <docs> <![CDATA[ The \c QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this project's filter section matches. - <a href="http://doc.qt.io/qt-4.8/qthelpproject.html#filter-attributes">Qt Help Project / Filter Attributes</a>. + <a href="http://doc.qt.io/archives/qt-4.8/qthelpproject.html#filter-attributes">Qt Help Project / Filter Attributes</a>. ]]> </docs> </option> @@ -2351,7 +2375,7 @@ The \c DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. <value name="NativeMML" desc="(i.e. MathML)"/> <value name="SVG"/> </option> - <option type='string' id='MATHJAX_RELPATH' format='string' defval='https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.2/' depends='USE_MATHJAX'> + <option type='string' id='MATHJAX_RELPATH' format='string' defval='https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/' depends='USE_MATHJAX'> <docs> <![CDATA[ When MathJax is enabled you need to specify the location relative to the diff --git a/src/configimpl.h b/src/configimpl.h index c901198..1594d47 100644 --- a/src/configimpl.h +++ b/src/configimpl.h @@ -73,7 +73,9 @@ class ConfigOption protected: virtual void writeTemplate(FTextStream &t,bool sl,bool upd) = 0; + virtual void compareDoxyfile(FTextStream &t) = 0; virtual void convertStrToVal() {} + virtual void emptyValueToDefault() {} virtual void substEnvVars() = 0; virtual void init() {} @@ -103,6 +105,7 @@ class ConfigInfo : public ConfigOption m_doc = doc; } void writeTemplate(FTextStream &t, bool sl,bool); + void compareDoxyfile(FTextStream &){}; void substEnvVars() {} }; @@ -124,6 +127,7 @@ class ConfigList : public ConfigOption WidgetType widgetType() const { return m_widgetType; } QStrList *valueRef() { return &m_value; } void writeTemplate(FTextStream &t,bool sl,bool); + void compareDoxyfile(FTextStream &t); void substEnvVars(); void init() { m_value = m_defaultValue; } private: @@ -153,6 +157,7 @@ class ConfigEnum : public ConfigOption QCString *valueRef() { return &m_value; } void substEnvVars(); void writeTemplate(FTextStream &t,bool sl,bool); + void compareDoxyfile(FTextStream &t); void init() { m_value = m_defValue.copy(); } private: @@ -182,8 +187,10 @@ class ConfigString : public ConfigOption void setDefaultValue(const char *v) { m_defValue = v; } QCString *valueRef() { return &m_value; } void writeTemplate(FTextStream &t,bool sl,bool); + void compareDoxyfile(FTextStream &t); void substEnvVars(); void init() { m_value = m_defValue.copy(); } + void emptyValueToDefault() { if(m_value.isEmpty()) m_value=m_defValue; }; private: QCString m_value; @@ -213,6 +220,7 @@ class ConfigInt : public ConfigOption void convertStrToVal(); void substEnvVars(); void writeTemplate(FTextStream &t,bool sl,bool upd); + void compareDoxyfile(FTextStream &t); void init() { m_value = m_defValue; } private: int m_value; @@ -241,6 +249,7 @@ class ConfigBool : public ConfigOption void substEnvVars(); void setValueString(const QCString &v) { m_valueString = v; } void writeTemplate(FTextStream &t,bool sl,bool upd); + void compareDoxyfile(FTextStream &t); void init() { m_value = m_defValue; } private: bool m_value; @@ -256,6 +265,7 @@ class ConfigObsolete : public ConfigOption ConfigObsolete(const char *name) : ConfigOption(O_Obsolete) { m_name = name; } void writeTemplate(FTextStream &,bool,bool); + void compareDoxyfile(FTextStream &) {} void substEnvVars() {} }; @@ -267,6 +277,7 @@ class ConfigDisabled : public ConfigOption ConfigDisabled(const char *name) : ConfigOption(O_Disabled) { m_name = name; } void writeTemplate(FTextStream &,bool,bool); + void compareDoxyfile(FTextStream &) {} void substEnvVars() {} }; @@ -466,6 +477,11 @@ class ConfigImpl */ void writeTemplate(FTextStream &t,bool shortIndex,bool updateOnly); + /*! Writes a the differences between the current configuration and the + * template configuration to stream \a t. + */ + void compareDoxyfile(FTextStream &t); + void setHeader(const char *header) { m_header = header; } ///////////////////////////// @@ -477,6 +493,10 @@ class ConfigImpl */ void convertStrToVal(); + /*! Sets default value in case value is empty + */ + void emptyValueToDefault(); + /*! Replaces references to environment variable by the actual value * of the environment variable. */ diff --git a/src/configimpl.l b/src/configimpl.l index df032a6..ed5b052 100644 --- a/src/configimpl.l +++ b/src/configimpl.l @@ -315,6 +315,77 @@ void ConfigList::writeTemplate(FTextStream &t,bool sl,bool) t << "\n"; } +void ConfigList::compareDoxyfile(FTextStream &t) +{ + const char *p = m_value.first(); + const char *q = m_defaultValue.first(); + int defCnt = 0; + int valCnt = 0; + + // count non empty elements + while (p) + { + QCString s=p; + if (!s.stripWhiteSpace().isEmpty()) valCnt += 1; + p = m_value.next(); + } + + while (q) + { + QCString s=q; + if (!s.stripWhiteSpace().isEmpty()) defCnt += 1; + q = m_defaultValue.next(); + } + if ( valCnt != defCnt) + { + writeTemplate(t,TRUE,TRUE); + return; + } + + // get first non empry element + q = m_defaultValue.first(); + p = m_value.first(); + QCString sp = p; + while (p && sp.stripWhiteSpace().isEmpty()) + { + p = m_value.next(); + sp = p; + } + QCString sq = q; + while (q && sq.stripWhiteSpace().isEmpty()) + { + q = m_value.next(); + sq = q; + } + while (p) + { + // skip empty elements + sp = p; + while (p && sp.stripWhiteSpace().isEmpty()) + { + p = m_value.next(); + sp = p; + } + sq = q; + while (q && sq.stripWhiteSpace().isEmpty()) + { + q = m_value.next(); + sq = q; + } + // be sure we have still an element (p and q have same number of 'filled' elements) + if (p) + { + if (sp.stripWhiteSpace() != sq.stripWhiteSpace()) + { + writeTemplate(t,TRUE,TRUE); + return; + } + p = m_value.next(); + q = m_defaultValue.next(); + } + } +} + void ConfigEnum::writeTemplate(FTextStream &t,bool sl,bool) { if (!sl) @@ -332,6 +403,11 @@ void ConfigEnum::writeTemplate(FTextStream &t,bool sl,bool) t << "\n"; } +void ConfigEnum::compareDoxyfile(FTextStream &t) +{ + if (m_value != m_defValue) writeTemplate(t,TRUE,TRUE); +} + void ConfigString::writeTemplate(FTextStream &t,bool sl,bool) { if (!sl) @@ -349,6 +425,11 @@ void ConfigString::writeTemplate(FTextStream &t,bool sl,bool) t << "\n"; } +void ConfigString::compareDoxyfile(FTextStream &t) +{ + if (m_value.stripWhiteSpace() != m_defValue.stripWhiteSpace()) writeTemplate(t,TRUE,TRUE); +} + void ConfigInt::writeTemplate(FTextStream &t,bool sl,bool upd) { if (!sl) @@ -373,6 +454,11 @@ void ConfigInt::writeTemplate(FTextStream &t,bool sl,bool upd) t << "\n"; } +void ConfigInt::compareDoxyfile(FTextStream &t) +{ + if (m_value != m_defValue) writeTemplate(t,TRUE,TRUE); +} + void ConfigBool::writeTemplate(FTextStream &t,bool sl,bool upd) { if (!sl) @@ -397,6 +483,11 @@ void ConfigBool::writeTemplate(FTextStream &t,bool sl,bool upd) t << "\n"; } +void ConfigBool::compareDoxyfile(FTextStream &t) +{ + if (m_value != m_defValue) writeTemplate(t,TRUE,TRUE); +} + void ConfigObsolete::writeTemplate(FTextStream &,bool,bool) {} void ConfigDisabled::writeTemplate(FTextStream &,bool,bool) {} @@ -777,7 +868,7 @@ static void readIncludeFile(const char *incName) } BEGIN(Start); } -<GetStrList>[ \t]+ { +<GetStrList>[ \t,]+ { if (!elemStr.isEmpty()) { //printf("elemStr2=`%s'\n",elemStr.data()); @@ -831,7 +922,7 @@ static void readIncludeFile(const char *incName) bs.data(),yyLineNr,yyFileName.data()); } } -<GetStrList>[^ \#\"\t\r\n]+ { +<GetStrList>[^ \#\"\t\r\n,]+ { elemStr+=configStringRecode(yytext,encoding,"UTF-8"); } <SkipComment>\n { yyLineNr++; BEGIN(Start); } @@ -871,6 +962,18 @@ void ConfigImpl::writeTemplate(FTextStream &t,bool sl,bool upd) } } +void ConfigImpl::compareDoxyfile(FTextStream &t) +{ + t << "# Difference with default Doxyfile " << versionString << endl; + QListIterator<ConfigOption> it = iterator(); + ConfigOption *option; + for (;(option=it.current());++it) + { + option->m_userComment = ""; + option->compareDoxyfile(t); + } +} + void ConfigImpl::convertStrToVal() { QListIterator<ConfigOption> it = iterator(); @@ -880,6 +983,15 @@ void ConfigImpl::convertStrToVal() option->convertStrToVal(); } } +void ConfigImpl::emptyValueToDefault() +{ + QListIterator<ConfigOption> it = iterator(); + ConfigOption *option; + for (;(option=it.current());++it) + { + option->emptyValueToDefault(); + } +} static void substEnvVarsInString(QCString &s) { @@ -1749,14 +1861,21 @@ void Config::writeTemplate(FTextStream &t,bool shortList,bool update) ConfigImpl::instance()->writeTemplate(t,shortList,update); } +void Config::compareDoxyfile(FTextStream &t) +{ + postProcess(FALSE, TRUE); + ConfigImpl::instance()->compareDoxyfile(t); +} + bool Config::parse(const char *fileName,bool update) { return ConfigImpl::instance()->parse(fileName,update); } -void Config::postProcess(bool clearHeaderAndFooter) +void Config::postProcess(bool clearHeaderAndFooter, bool compare) { ConfigImpl::instance()->substituteEnvironmentVars(); + if (!compare)ConfigImpl::instance()->emptyValueToDefault(); ConfigImpl::instance()->convertStrToVal(); // avoid bootstrapping issues when the config file already diff --git a/src/context.cpp b/src/context.cpp index c9a6bb3..33e7dcf 100644 --- a/src/context.cpp +++ b/src/context.cpp @@ -6978,7 +6978,8 @@ class NamespaceTreeContext::Private SharedPtr<NestingContext> m_namespaceTree; struct Cachable { - Cachable() : maxDepthComputed(FALSE), preferredDepthComputed(FALSE) {} + Cachable() : maxDepth(0), maxDepthComputed(FALSE), + preferredDepth(0), preferredDepthComputed(FALSE) {} int maxDepth; bool maxDepthComputed; int preferredDepth; @@ -7352,7 +7353,8 @@ class PageTreeContext::Private SharedPtr<NestingContext> m_pageTree; struct Cachable { - Cachable() : maxDepthComputed(FALSE), preferredDepthComputed(FALSE) {} + Cachable() : maxDepth(0), maxDepthComputed(FALSE), + preferredDepth(0), preferredDepthComputed(FALSE) {} int maxDepth; bool maxDepthComputed; int preferredDepth; @@ -7604,7 +7606,8 @@ class ModuleTreeContext::Private SharedPtr<NestingContext> m_moduleTree; struct Cachable { - Cachable() : maxDepthComputed(FALSE), preferredDepthComputed(FALSE) {} + Cachable() : maxDepth(0), maxDepthComputed(FALSE), + preferredDepth(0), preferredDepthComputed(FALSE) {} int maxDepth; bool maxDepthComputed; int preferredDepth; @@ -7807,7 +7810,8 @@ class ExampleTreeContext::Private SharedPtr<NestingContext> m_exampleTree; struct Cachable { - Cachable() : maxDepthComputed(FALSE), preferredDepthComputed(FALSE) {} + Cachable() : maxDepth(0), maxDepthComputed(FALSE), + preferredDepth(0), preferredDepthComputed(FALSE) {} int maxDepth; bool maxDepthComputed; int preferredDepth; diff --git a/src/definition.cpp b/src/definition.cpp index cbfad94..bd97f6d 100644 --- a/src/definition.cpp +++ b/src/definition.cpp @@ -42,6 +42,7 @@ #include "filedef.h" #include "dirdef.h" #include "pagedef.h" +#include "bufstr.h" #define START_MARKER 0x4445465B // DEF[ #define END_MARKER 0x4445465D // DEF] @@ -304,6 +305,7 @@ Definition::Definition(const Definition &d) : DefinitionIntf(), m_cookie(0) { m_name = d.m_name; m_defLine = d.m_defLine; + m_defColumn = d.m_defColumn; m_impl = new DefinitionImpl; *m_impl = *d.m_impl; m_impl->sectionDict = 0; @@ -715,6 +717,139 @@ void Definition::setInbodyDocumentation(const char *d,const char *inbodyFile,int _setInbodyDocumentation(d,inbodyFile,inbodyLine); } +//--------------------------------------- + +struct FilterCacheItem +{ + portable_off_t filePos; + uint fileSize; +}; + +/*! Cache for storing the result of filtering a file */ +class FilterCache +{ + public: + FilterCache() : m_endPos(0) { m_cache.setAutoDelete(TRUE); } + bool getFileContents(const QCString &fileName,BufStr &str) + { + static bool filterSourceFiles = Config_getBool(FILTER_SOURCE_FILES); + QCString filter = getFileFilter(fileName,TRUE); + bool usePipe = !filter.isEmpty() && filterSourceFiles; + FILE *f=0; + const int blockSize = 4096; + char buf[blockSize]; + FilterCacheItem *item=0; + if (usePipe && (item = m_cache.find(fileName))) // cache hit: reuse stored result + { + //printf("getFileContents(%s): cache hit\n",qPrint(fileName)); + // file already processed, get the results after filtering from the tmp file + Debug::print(Debug::FilterOutput,0,"Reusing filter result for %s from %s at offset=%d size=%d\n", + qPrint(fileName),qPrint(Doxygen::filterDBFileName),(int)item->filePos,(int)item->fileSize); + f = portable_fopen(Doxygen::filterDBFileName,"rb"); + if (f) + { + bool success=TRUE; + str.resize(item->fileSize+1); + if (portable_fseek(f,item->filePos,SEEK_SET)==-1) + { + err("Failed to seek to position %d in filter database file %s\n",(int)item->filePos,qPrint(Doxygen::filterDBFileName)); + success=FALSE; + } + if (success) + { + int numBytes = fread(str.data(),1,item->fileSize,f); + if (numBytes!=item->fileSize) + { + err("Failed to read %d bytes from position %d in filter database file %s: got %d bytes\n", + (int)item->fileSize,(int)item->filePos,qPrint(Doxygen::filterDBFileName),numBytes); + success=FALSE; + } + } + str.addChar('\0'); + fclose(f); + return success; + } + else + { + err("Failed to open filter database file %s\n",qPrint(Doxygen::filterDBFileName)); + return FALSE; + } + } + else if (usePipe) // cache miss: filter active but file not previously processed + { + //printf("getFileContents(%s): cache miss\n",qPrint(fileName)); + // filter file + QCString cmd=filter+" \""+fileName+"\""; + Debug::print(Debug::ExtCmd,0,"Executing popen(`%s`)\n",qPrint(cmd)); + f = portable_popen(cmd,"r"); + FILE *bf = portable_fopen(Doxygen::filterDBFileName,"a+b"); + FilterCacheItem *item = new FilterCacheItem; + item->filePos = m_endPos; + if (bf==0) + { + // handle error + err("Error opening filter database file %s\n",qPrint(Doxygen::filterDBFileName)); + str.addChar('\0'); + delete item; + portable_pclose(f); + return FALSE; + } + // append the filtered output to the database file + int size=0; + while (!feof(f)) + { + int bytesRead = fread(buf,1,blockSize,f); + int bytesWritten = fwrite(buf,1,bytesRead,bf); + if (bytesRead!=bytesWritten) + { + // handle error + err("Failed to write to filter database %s. Wrote %d out of %d bytes\n", + qPrint(Doxygen::filterDBFileName),bytesWritten,bytesRead); + str.addChar('\0'); + delete item; + portable_pclose(f); + fclose(bf); + return FALSE; + } + size+=bytesWritten; + str.addArray(buf,bytesWritten); + } + str.addChar('\0'); + item->fileSize = size; + // add location entry to the dictionary + m_cache.append(fileName,item); + Debug::print(Debug::FilterOutput,0,"Storing new filter result for %s in %s at offset=%d size=%d\n", + qPrint(fileName),qPrint(Doxygen::filterDBFileName),(int)item->filePos,(int)item->fileSize); + // update end of file position + m_endPos += size; + portable_pclose(f); + fclose(bf); + } + else // no filtering + { + // normal file + //printf("getFileContents(%s): no filter\n",qPrint(fileName)); + f = portable_fopen(fileName,"r"); + while (!feof(f)) + { + int bytesRead = fread(buf,1,blockSize,f); + str.addArray(buf,bytesRead); + } + str.addChar('\0'); + fclose(f); + } + return TRUE; + } + private: + SDict<FilterCacheItem> m_cache; + portable_off_t m_endPos; +}; + +static FilterCache g_filterCache; + +//----------------------------------------- + + /*! Reads a fragment of code from file \a fileName starting at * line \a startLine and ending at line \a endLine (inclusive). The fragment is * stored in \a result. If FALSE is returned the code fragment could not be @@ -729,67 +864,60 @@ void Definition::setInbodyDocumentation(const char *d,const char *inbodyFile,int bool readCodeFragment(const char *fileName, int &startLine,int &endLine,QCString &result) { + //printf("readCodeFragment(%s,startLine=%d,endLine=%d)\n",fileName,startLine,endLine); static bool filterSourceFiles = Config_getBool(FILTER_SOURCE_FILES); - static int tabSize = Config_getInt(TAB_SIZE); - //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; + int tabSize = Config_getInt(TAB_SIZE); SrcLangExt lang = getLanguageFromFileName(fileName); - if (!usePipe) // no filter given or wanted - { - f = portable_fopen(fileName,"r"); - } - else // use filter - { - QCString cmd=filter+" \""+fileName+"\""; - Debug::print(Debug::ExtCmd,0,"Executing popen(`%s`)\n",qPrint(cmd)); - f = portable_popen(cmd,"r"); - } - bool found = lang==SrcLangExt_VHDL || - lang==SrcLangExt_Tcl || - lang==SrcLangExt_Python || - lang==SrcLangExt_Fortran; + const int blockSize = 4096; + BufStr str(blockSize); + g_filterCache.getFileContents(fileName,str); + + 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) + char *p=str.data(); + if (p) { int c=0; int col=0; int lineNr=1; // skip until the startLine has reached - while (lineNr<startLine && !feof(f)) + while (lineNr<startLine && *p) { - while ((c=fgetc(f))!='\n' && c!=EOF) /* skip */; - lineNr++; + while ((c=*p++)!='\n' && c!=0) /* skip */; + lineNr++; if (found && c == '\n') c = '\0'; } - if (!feof(f)) + if (*p) { // skip until the opening bracket or lonely : is found char cn=0; - while (lineNr<=endLine && !feof(f) && !found) + while (lineNr<=endLine && *p && !found) { int pc=0; - while ((c=fgetc(f))!='{' && c!=':' && c!=EOF) // } so vi matching brackets has no problem + while ((c=*p++)!='{' && c!=':' && c!=0) { //printf("parsing char `%c'\n",c); - if (c=='\n') + if (c=='\n') { - lineNr++,col=0; + lineNr++,col=0; } - else if (c=='\t') + else if (c=='\t') { col+=tabSize - (col%tabSize); } else if (pc=='/' && c=='/') // skip single line comment { - while ((c=fgetc(f))!='\n' && c!=EOF) pc=c; + while ((c=*p++)!='\n' && c!=0) pc=c; if (c=='\n') lineNr++,col=0; } else if (pc=='/' && c=='*') // skip C style comment { - while (((c=fgetc(f))!='/' || pc!='*') && c!=EOF) + while (((c=*p++)!='/' || pc!='*') && c!=0) { if (c=='\n') lineNr++,col=0; pc=c; @@ -803,16 +931,16 @@ bool readCodeFragment(const char *fileName, } if (c==':') { - cn=fgetc(f); + cn=*p++; if (cn!=':') found=TRUE; } - else if (c=='{') // } so vi matching brackets has no problem + else if (c=='{') { found=TRUE; } } //printf(" -> readCodeFragment(%s,%d,%d) lineNr=%d\n",fileName,startLine,endLine,lineNr); - if (found) + if (found) { // For code with more than one line, // fill the line with spaces until we are at the right column @@ -826,57 +954,47 @@ bool readCodeFragment(const char *fileName, // copy until end of line if (c) result+=c; startLine=lineNr; - if (c==':') + if (c==':') { result+=cn; if (cn=='\n') lineNr++; } - const int maxLineLength=4096; - char lineStr[maxLineLength]; - do + char lineStr[blockSize]; + do { //printf("reading line %d in range %d-%d\n",lineNr,startLine,endLine); int size_read; - do + do { // read up to maxLineLength-1 bytes, the last byte being zero - char *p = fgets(lineStr, maxLineLength,f); - //printf(" read %s",p); - if (p) + int i=0; + while ((c=*p++) && i<blockSize-1) { - size_read=qstrlen(p); + lineStr[i++]=c; + if (c=='\n') break; // stop at end of the line } - else // nothing read - { - size_read=-1; - lineStr[0]='\0'; - } - result+=lineStr; - } while (size_read == (maxLineLength-1)); - - lineNr++; - } while (lineNr<=endLine && !feof(f)); + lineStr[i]=0; + size_read=i; + result+=lineStr; // append line to the output + } while (size_read == (blockSize-1)); // append more if line does not fit in buffer + lineNr++; + } while (lineNr<=endLine && *p); // strip stuff after closing bracket int newLineIndex = result.findRev('\n'); int braceIndex = result.findRev('}'); - if (braceIndex > newLineIndex) + if (braceIndex > newLineIndex) { result.truncate(braceIndex+1); } endLine=lineNr-1; } } - if (usePipe) + if (usePipe) { - portable_pclose(f); Debug::print(Debug::FilterOutput, 0, "Filter output\n"); Debug::print(Debug::FilterOutput,0,"-------------\n%s\n-------------\n",qPrint(result)); } - else - { - fclose(f); - } } result = transcodeCharacterStringToUTF8(result); if (!result.isEmpty() && result.at(result.length()-1)!='\n') result += "\n"; @@ -921,6 +1039,7 @@ void Definition::writeSourceDef(OutputList &ol,const char *) { static bool latexSourceCode = Config_getBool(LATEX_SOURCE_CODE); static bool rtfSourceCode = Config_getBool(RTF_SOURCE_CODE); + static bool docbookSourceCode = Config_getBool(DOCBOOK_PROGRAMLISTING); ol.pushGeneratorState(); //printf("Definition::writeSourceRef %d %p\n",bodyLine,bodyDef); QCString fn = getSourceFileBase(); @@ -945,11 +1064,15 @@ void Definition::writeSourceDef(OutputList &ol,const char *) { ol.disable(OutputGenerator::Latex); } + if (!docbookSourceCode) + { + ol.disable(OutputGenerator::Docbook); + } if (!rtfSourceCode) { ol.disable(OutputGenerator::RTF); } - // write line link (HTML, LaTeX optionally, RTF optionally) + // write line link (HTML and optionally LaTeX, Docbook, RTF) ol.writeObjectLink(0,fn,anchorStr,lineStr); ol.enableAll(); ol.disable(OutputGenerator::Html); @@ -957,6 +1080,10 @@ void Definition::writeSourceDef(OutputList &ol,const char *) { ol.disable(OutputGenerator::Latex); } + if (docbookSourceCode) + { + ol.disable(OutputGenerator::Docbook); + } if (rtfSourceCode) { ol.disable(OutputGenerator::RTF); @@ -975,6 +1102,10 @@ void Definition::writeSourceDef(OutputList &ol,const char *) { ol.disable(OutputGenerator::Latex); } + if (!docbookSourceCode) + { + ol.disable(OutputGenerator::Docbook); + } if (!rtfSourceCode) { ol.disable(OutputGenerator::RTF); @@ -987,6 +1118,10 @@ void Definition::writeSourceDef(OutputList &ol,const char *) { ol.disable(OutputGenerator::Latex); } + if (docbookSourceCode) + { + ol.disable(OutputGenerator::Docbook); + } if (rtfSourceCode) { ol.disable(OutputGenerator::RTF); @@ -1009,6 +1144,10 @@ void Definition::writeSourceDef(OutputList &ol,const char *) { ol.disable(OutputGenerator::Latex); } + if (!docbookSourceCode) + { + ol.disable(OutputGenerator::Docbook); + } if (!rtfSourceCode) { ol.disable(OutputGenerator::RTF); @@ -1021,6 +1160,10 @@ void Definition::writeSourceDef(OutputList &ol,const char *) { ol.disable(OutputGenerator::Latex); } + if (docbookSourceCode) + { + ol.disable(OutputGenerator::Docbook); + } if (rtfSourceCode) { ol.disable(OutputGenerator::RTF); @@ -1040,6 +1183,10 @@ void Definition::writeSourceDef(OutputList &ol,const char *) { ol.enable(OutputGenerator::Latex); } + if (docbookSourceCode) + { + ol.enable(OutputGenerator::Docbook); + } if (rtfSourceCode) { ol.enable(OutputGenerator::RTF); @@ -1052,6 +1199,10 @@ void Definition::writeSourceDef(OutputList &ol,const char *) { ol.disable(OutputGenerator::Latex); } + if (docbookSourceCode) + { + ol.disable(OutputGenerator::Docbook); + } if (rtfSourceCode) { ol.disable(OutputGenerator::RTF); @@ -1145,6 +1296,7 @@ void Definition::_writeSourceRefList(OutputList &ol,const char *scopeName, const QCString &text,MemberSDict *members,bool /*funcOnly*/) { static bool latexSourceCode = Config_getBool(LATEX_SOURCE_CODE); + static bool docbookSourceCode = Config_getBool(DOCBOOK_PROGRAMLISTING); static bool rtfSourceCode = Config_getBool(RTF_SOURCE_CODE); static bool sourceBrowser = Config_getBool(SOURCE_BROWSER); static bool refLinkSource = Config_getBool(REFERENCES_LINK_SOURCE); @@ -1203,6 +1355,10 @@ void Definition::_writeSourceRefList(OutputList &ol,const char *scopeName, { ol.disable(OutputGenerator::Latex); } + if (!docbookSourceCode) + { + ol.disable(OutputGenerator::Docbook); + } if (!rtfSourceCode) { ol.disable(OutputGenerator::RTF); @@ -1221,6 +1377,10 @@ void Definition::_writeSourceRefList(OutputList &ol,const char *scopeName, { ol.disable(OutputGenerator::Latex); } + if (docbookSourceCode) + { + ol.disable(OutputGenerator::Docbook); + } if (rtfSourceCode) { ol.disable(OutputGenerator::RTF); @@ -1238,6 +1398,10 @@ void Definition::_writeSourceRefList(OutputList &ol,const char *scopeName, { ol.disable(OutputGenerator::Latex); } + if (!docbookSourceCode) + { + ol.disable(OutputGenerator::Docbook); + } if (!rtfSourceCode) { ol.disable(OutputGenerator::RTF); @@ -1255,6 +1419,10 @@ void Definition::_writeSourceRefList(OutputList &ol,const char *scopeName, { ol.disable(OutputGenerator::Latex); } + if (docbookSourceCode) + { + ol.disable(OutputGenerator::Docbook); + } if (rtfSourceCode) { ol.disable(OutputGenerator::RTF); @@ -1633,7 +1801,7 @@ void Definition::writeToc(OutputList &ol, const LocalToc &localToc) int level=1,l; char cs[2]; cs[1]='\0'; - bool inLi[5]={ FALSE, FALSE, FALSE, FALSE }; + bool inLi[5]={ FALSE, FALSE, FALSE, FALSE, FALSE }; for (li.toFirst();(si=li.current());++li) { if (si->type==SectionInfo::Section || @@ -1681,6 +1849,55 @@ void Definition::writeToc(OutputList &ol, const LocalToc &localToc) ol.popGeneratorState(); } + if (localToc.isDocbookEnabled()) + { + ol.pushGeneratorState(); + ol.disableAllBut(OutputGenerator::Docbook); + ol.writeString(" <toc>\n"); + ol.writeString(" <title>" + theTranslator->trRTFTableOfContents() + "</title>\n"); + SectionDict *sectionDict = getSectionDict(); + SDict<SectionInfo>::Iterator li(*sectionDict); + SectionInfo *si; + int level=1,l; + bool inLi[5]={ FALSE, FALSE, FALSE, FALSE, FALSE }; + int maxLevel = localToc.docbookLevel(); + for (li.toFirst();(si=li.current());++li) + { + if (si->type==SectionInfo::Section || + si->type==SectionInfo::Subsection || + si->type==SectionInfo::Subsubsection || + si->type==SectionInfo::Paragraph) + { + //printf(" level=%d title=%s\n",level,si->title.data()); + int nextLevel = (int)si->type; + if (nextLevel>level) + { + for (l=level;l<nextLevel;l++) + { + if (l < maxLevel) ol.writeString(" <tocdiv>\n"); + } + } + else if (nextLevel<level) + { + for (l=level;l>nextLevel;l--) + { + inLi[l]=FALSE; + if (l <= maxLevel) ol.writeString(" </tocdiv>\n"); + } + } + if (nextLevel <= maxLevel) + { + QCString titleDoc = convertToDocBook(si->title); + ol.writeString(" <tocentry>" + (si->title.isEmpty()?si->label:titleDoc) + "</tocentry>\n"); + } + inLi[nextLevel]=TRUE; + level = nextLevel; + } + } + ol.writeString(" </toc>\n"); + ol.popGeneratorState(); + } + if (localToc.isLatexEnabled()) { ol.pushGeneratorState(); diff --git a/src/docbookgen.cpp b/src/docbookgen.cpp index 345629e..9398f59 100644 --- a/src/docbookgen.cpp +++ b/src/docbookgen.cpp @@ -1,6 +1,6 @@ /****************************************************************************** * -* +* * * Copyright (C) 1997-2015 by Dimitri van Heesch. * @@ -21,11 +21,14 @@ #include <qfile.h> #include <qtextstream.h> #include <qintdict.h> +#include <qregexp.h> #include "docbookgen.h" #include "doxygen.h" #include "message.h" #include "config.h" #include "classlist.h" +#include "classdef.h" +#include "diagram.h" #include "util.h" #include "defargs.h" #include "outputgen.h" @@ -54,6 +57,17 @@ // debug inside output //#define Docbook_DB(x) QCString __t;__t.sprintf x;m_t << __t +#if 0 +#define DB_GEN_C DB_GEN_C1(t) +#define DB_GEN_C1(x) x << "<!-- DB_GEN_C " << __LINE__ << " -->\n"; +#define DB_GEN_C2(y) DB_GEN_C2a(t,y) +#define DB_GEN_C2a(x,y) x << "<!-- DB_GEN_C " << __LINE__ << " " << y << " -->\n"; +#else +#define DB_GEN_C +#define DB_GEN_C1(x) +#define DB_GEN_C2(y) +#define DB_GEN_C2a(x,y) +#endif //------------------ class DocbookSectionMapper : public QIntDict<char> @@ -104,7 +118,7 @@ static DocbookSectionMapper g_docbookSectionMapper; inline void writeDocbookString(FTextStream &t,const char *s) { - t << convertToXML(s); + t << convertToDocBook(s); } inline void writeDocbookCodeString(FTextStream &t,const char *s, int &col) @@ -128,27 +142,44 @@ inline void writeDocbookCodeString(FTextStream &t,const char *s, int &col) case '&': t << "&"; col++; break; case '\'': t << "'"; col++; break; case '"': t << """; col++; break; + case '\007': t << "^G"; col++; break; // bell + case '\014': t << "^L"; col++; break; // form feed default: t << c; col++; break; } } } -static void writeDocbookHeaderMainpage(FTextStream &t) +static void writeDocbookHeaderMainpage(FTextStream &t, QCString &pageName) { t << "<?xml version='1.0' encoding='UTF-8' standalone='no'?>" << endl;; - t << "<chapter xmlns=\"http://docbook.org/ns/docbook\" version=\"5.0\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">" << endl; + t << "<chapter xmlns=\"http://docbook.org/ns/docbook\" version=\"5.0\" xmlns:xlink=\"http://www.w3.org/1999/xlink\""; + if (!pageName.isEmpty()) t << " xml:id=\"_" << pageName << "\""; + t << ">" << endl; } static void writeDocbookHeader_ID(FTextStream &t, QCString id) { t << "<?xml version='1.0' encoding='UTF-8' standalone='no'?>" << endl;; - t << "<section xmlns=\"http://docbook.org/ns/docbook\" version=\"5.0\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" xml:id=\"" << id << "\">" << endl; + t << "<section xmlns=\"http://docbook.org/ns/docbook\" version=\"5.0\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" xml:id=\"_" << id << "\">" << endl; } +static void addIndexTerm(FTextStream &t, QCString prim, QCString sec = "") +{ + t << "<indexterm><primary>"; + t << convertToDocBook(prim); + t << "</primary>"; + if (!sec.isEmpty()) + { + t << "<secondary>"; + t << convertToDocBook(sec); + t << "</secondary>"; + } + t << "</indexterm>" << endl; +} void writeDocbookLink(FTextStream &t,const char * /*extRef*/,const char *compoundId, const char *anchorId,const char * text,const char * /*tooltip*/) { - t << "<link linkend=\"" << compoundId; + t << "<link linkend=\"_" << stripPath(compoundId); if (anchorId) t << "_1" << anchorId; t << "\""; t << ">"; @@ -175,110 +206,127 @@ class TextGeneratorDocbookImpl : public TextGeneratorIntf FTextStream &m_t; }; -class DocbookCodeGenerator : public CodeOutputInterface +DocbookCodeGenerator::DocbookCodeGenerator(FTextStream &t) : m_lineNumber(-1), m_col(0), + m_insideCodeLine(FALSE), m_insideSpecialHL(FALSE) { - public: - DocbookCodeGenerator(FTextStream &t) : m_t(t), m_lineNumber(-1), m_col(0), - m_insideCodeLine(FALSE), m_insideSpecialHL(FALSE) {} - virtual ~DocbookCodeGenerator() {} + m_prettyCode=Config_getBool(DOCBOOK_PROGRAMLISTING); + setTextStream(t); +} - void codify(const char *text) - { - Docbook_DB(("(codify \"%s\")\n",text)); - writeDocbookCodeString(m_t,text,m_col); - } - void writeCodeLink(const char *ref,const char *file, - const char *anchor,const char *name, - const char *tooltip) - { - Docbook_DB(("(writeCodeLink)\n")); - writeDocbookLink(m_t,ref,file,anchor,name,tooltip); - m_col+=strlen(name); - } - void writeTooltip(const char *, const DocLinkInfo &, const char *, - const char *, const SourceLinkInfo &, const SourceLinkInfo & - ) - { - Docbook_DB(("(writeToolTip)\n")); - } - void startCodeLine(bool) - { - Docbook_DB(("(startCodeLine)\n")); - if (m_lineNumber!=-1) - { - if (!m_refId.isEmpty()) - { - m_t << "<link linkend=\"" << m_refId << "\">"; - } - m_t << m_lineNumber << " "; - if (!m_refId.isEmpty()) - { - m_t << "</link>"; - } - } - m_insideCodeLine=TRUE; - m_col=0; - } - void endCodeLine() - { - m_t << endl; - Docbook_DB(("(endCodeLine)\n")); - m_lineNumber = -1; - m_refId.resize(0); - m_external.resize(0); - m_insideCodeLine=FALSE; - } - void startFontClass(const char *colorClass) - { - Docbook_DB(("(startFontClass)\n")); - m_t << "<emphasis class=\"" << colorClass << "\">"; - m_insideSpecialHL=TRUE; - } - void endFontClass() - { - Docbook_DB(("(endFontClass)\n")); - m_t << "</emphasis>"; // non DocBook - m_insideSpecialHL=FALSE; - } - void writeCodeAnchor(const char *) - { - Docbook_DB(("(writeCodeAnchor)\n")); - } - void writeLineNumber(const char *extRef,const char *compId, - const char *anchorId,int l) - { - Docbook_DB(("(writeLineNumber)\n")); - // we remember the information provided here to use it - // at the <codeline> start tag. - m_lineNumber = l; - if (compId) - { - m_refId=compId; - if (anchorId) m_refId+=(QCString)"_1"+anchorId; - if (extRef) m_external=extRef; - } - } - void setCurrentDoc(Definition *,const char *,bool) - { - } - void addWord(const char *,bool) +DocbookCodeGenerator::DocbookCodeGenerator() : m_lineNumber(-1), m_col(0), + m_insideCodeLine(FALSE), m_insideSpecialHL(FALSE), m_streamSet(FALSE) +{ + m_prettyCode=Config_getBool(DOCBOOK_PROGRAMLISTING); +} + +DocbookCodeGenerator::~DocbookCodeGenerator() {} + +void DocbookCodeGenerator::codify(const char *text) +{ + Docbook_DB(("(codify \"%s\")\n",text)); + writeDocbookCodeString(m_t,text,m_col); +} +void DocbookCodeGenerator::writeCodeLink(const char *ref,const char *file, + const char *anchor,const char *name, + const char *tooltip) +{ + Docbook_DB(("(writeCodeLink)\n")); + writeDocbookLink(m_t,ref,file,anchor,name,tooltip); + m_col+=strlen(name); +} +void DocbookCodeGenerator::writeCodeLinkLine(const char *ref,const char *file, + const char *anchor,const char *name, + const char *tooltip) +{ + Docbook_DB(("(writeCodeLinkLine)\n")); + m_t << "<anchor xml:id=\"_" << stripExtensionGeneral(stripPath(file),".xml"); + m_t << "_1l"; + writeDocbookString(m_t,name); + m_t << "\"/>"; + m_col+=strlen(name); +} +void DocbookCodeGenerator::writeTooltip(const char *, const DocLinkInfo &, const char *, + const char *, const SourceLinkInfo &, const SourceLinkInfo & + ) +{ + Docbook_DB(("(writeToolTip)\n")); +} +void DocbookCodeGenerator::startCodeLine(bool) +{ + Docbook_DB(("(startCodeLine)\n")); + m_insideCodeLine=TRUE; + m_col=0; +} +void DocbookCodeGenerator::endCodeLine() +{ + m_t << endl; + Docbook_DB(("(endCodeLine)\n")); + m_lineNumber = -1; + m_refId.resize(0); + m_external.resize(0); + m_insideCodeLine=FALSE; +} +void DocbookCodeGenerator::startFontClass(const char *colorClass) +{ + Docbook_DB(("(startFontClass)\n")); + m_t << "<emphasis role=\"" << colorClass << "\">"; + m_insideSpecialHL=TRUE; +} +void DocbookCodeGenerator::endFontClass() +{ + Docbook_DB(("(endFontClass)\n")); + m_t << "</emphasis>"; // non DocBook + m_insideSpecialHL=FALSE; +} +void DocbookCodeGenerator::writeCodeAnchor(const char *) +{ + Docbook_DB(("(writeCodeAnchor)\n")); +} +void DocbookCodeGenerator::writeLineNumber(const char *ref,const char *fileName, + const char *anchor,int l) +{ + Docbook_DB(("(writeLineNumber)\n")); + m_insideCodeLine = TRUE; + if (m_prettyCode) + { + QCString lineNumber; + lineNumber.sprintf("%05d",l); + + if (fileName && !m_sourceFileName.isEmpty()) { + writeCodeLinkLine(ref,m_sourceFileName,anchor,lineNumber,0); + writeCodeLink(ref,fileName,anchor,lineNumber,0); } - void finish() + else { - if (m_insideCodeLine) endCodeLine(); + codify(lineNumber); } + m_t << " "; + } + else + { + m_t << l << " "; + } - private: - FTextStream &m_t; - QCString m_refId; - QCString m_external; - int m_lineNumber; - int m_col; - bool m_insideCodeLine; - bool m_insideSpecialHL; -}; - +} +void DocbookCodeGenerator::setCurrentDoc(Definition *,const char *,bool) +{ +} +void DocbookCodeGenerator::addWord(const char *,bool) +{ +} +void DocbookCodeGenerator::finish() +{ + if (m_insideCodeLine) endCodeLine(); +} +void DocbookCodeGenerator::startCodeFragment() +{ + m_t << "<literallayout><computeroutput>" << endl; +} +void DocbookCodeGenerator::endCodeFragment() +{ + m_t << "</computeroutput></literallayout>" << endl; +} static void writeTemplateArgumentList(ArgumentList *al, FTextStream &t, @@ -389,10 +437,205 @@ static QCString memberOutputFileBase(MemberDef *md) return md->getOutputFileBase(); } +static void generateTOC(FTextStream &t, PageDef *pd) +{ + if (pd->localToc().isDocbookEnabled()) + { + t << " <toc>" << endl; + t << " <title>" << theTranslator->trRTFTableOfContents() << "</title>" << endl; + SectionDict *sectionDict = pd->getSectionDict(); + SDict<SectionInfo>::Iterator li(*sectionDict); + SectionInfo *si; + int level=1,l; + bool inLi[5]={ FALSE, FALSE, FALSE, FALSE, FALSE }; + int maxLevel = pd->localToc().docbookLevel(); + for (li.toFirst();(si=li.current());++li) + { + if (si->type==SectionInfo::Section || + si->type==SectionInfo::Subsection || + si->type==SectionInfo::Subsubsection || + si->type==SectionInfo::Paragraph) + { + //printf(" level=%d title=%s\n",level,si->title.data()); + int nextLevel = (int)si->type; + if (nextLevel>level) + { + for (l=level;l<nextLevel;l++) + { + if (l < maxLevel) t << " <tocdiv>" << endl; + } + } + else if (nextLevel<level) + { + for (l=level;l>nextLevel;l--) + { + inLi[l]=FALSE; + if (l <= maxLevel) t << " </tocdiv>" << endl; + } + } + if (nextLevel <= maxLevel) + { + QCString titleDoc = convertToDocBook(si->title); + t << " <tocentry>" << (si->title.isEmpty()?si->label:titleDoc) << "</tocentry>" << endl; + } + inLi[nextLevel]=TRUE; + level = nextLevel; + } + } + t << " </toc>" << endl; + } +} + +static void generateSourceRefList(FTextStream &t,const char *scopeName, const QCString &text,MemberSDict *members, Definition *def) +{ + static bool sourceBrowser = Config_getBool(SOURCE_BROWSER); + static bool refLinkSource = Config_getBool(REFERENCES_LINK_SOURCE); -static void generateDocbookForMember(MemberDef *md,FTextStream &t,Definition *def, bool detailed=0) + if (members) + { + members->sort(); + + t << "<formalpara><title>" << convertToDocBook(text) << "</title><para>"; + + QCString ldefLine=theTranslator->trWriteList(members->count()); + + QRegExp marker("@[0-9]+"); + int index=0,newIndex,matchLen; + // now replace all markers in inheritLine with links to the classes + while ((newIndex=marker.match(ldefLine,index,&matchLen))!=-1) + { + bool ok; + t << convertToDocBook(ldefLine.mid(index,newIndex-index)); + uint entryIndex = ldefLine.mid(newIndex+1,matchLen-1).toUInt(&ok); + MemberDef *md=members->at(entryIndex); + if (ok && md) + { + QCString scope=md->getScopeString(); + QCString name=md->name(); + //printf("class=%p scope=%s scopeName=%s\n",md->getClassDef(),scope.data(),scopeName); + if (!scope.isEmpty() && scope!=scopeName) + { + name.prepend(scope+getLanguageSpecificSeparator(def->getLanguage())); + } + if (!md->isObjCMethod() && + (md->isFunction() || md->isSlot() || + md->isPrototype() || md->isSignal() + ) + ) + { + name+="()"; + } + //Definition *d = md->getOutputFileBase(); + //if (d==Doxygen::globalScope) d=md->getBodyDef(); + if (sourceBrowser && + !(md->isLinkable() && !refLinkSource) && + md->getStartBodyLine()!=-1 && + md->getBodyDef() + ) + { + //printf("md->getBodyDef()=%p global=%p\n",md->getBodyDef(),Doxygen::globalScope); + + const int maxLineNrStr = 10; + char anchorStr[maxLineNrStr]; + qsnprintf(anchorStr,maxLineNrStr,"l%05d",md->getStartBodyLine()); + //printf("Write object link to %s\n",md->getBodyDef()->getSourceFileBase().data()); + t << convertToDocBook(name); + // or + // ol.writeObjectLink(0,md->getBodyDef()->getSourceFileBase(),anchorStr,name); + } + else if (md->isLinkable() /*&& d && d->isLinkable()*/) + { + t << convertToDocBook(name); + // or + // ol.writeObjectLink(md->getReference(), md->getOutputFileBase(), md->anchor(),name); + } + else + { + t << convertToDocBook(name); + } + } + index=newIndex+matchLen; + } + t << ldefLine.right(ldefLine.length()-index); + t<< "."; + t << "</para></formalpara>"; + } +} +static void generateInlineCode(FTextStream &t,const char *scopeName, Definition *def) +{ + static bool inlineSources = Config_getBool(INLINE_SOURCES); + //printf("Source Fragment %s: %d-%d bodyDef=%p\n",name().data(), + // m_startBodyLine,m_endBodyLine,m_bodyDef); + if (inlineSources && def->hasSources()) + { + QCString codeFragment; + int actualStart=def->getStartBodyLine(),actualEnd=def->getEndBodyLine(); + if (readCodeFragment(def->getBodyDef()->absFilePath(), + actualStart,actualEnd,codeFragment) + ) + { + //printf("Adding code fragment '%s' ext='%s'\n", + // codeFragment.data(),m_impl->defFileExt.data()); + ParserInterface *pIntf = Doxygen::parserManager->getParser(def->getDefFileExtension()); + pIntf->resetCodeParserState(); + //printf("Read:\n`%s'\n\n",codeFragment.data()); + MemberDef *thisMd = 0; + if (def->definitionType()==Definition::TypeMember) thisMd = (MemberDef *)def; + + DocbookCodeGenerator *docbookGen = new DocbookCodeGenerator(t); + docbookGen->startCodeFragment(); + pIntf->parseCode(*docbookGen, // codeOutIntf + scopeName, // scope + codeFragment, // input + def->getLanguage(), // lang + FALSE, // isExample + 0, // exampleName + def->getBodyDef(), // fileDef + actualStart, // startLine + actualEnd, // endLine + TRUE, // inlineFragment + thisMd, // memberDef + TRUE // show line numbers + ); + docbookGen->finish(); + docbookGen->endCodeFragment(); + delete docbookGen; + } + } +} + +static void definedAtLine(int line, QCString fileName, FTextStream &t) { + QCString refText = theTranslator->trDefinedAtLineInSourceFile(); + int lineMarkerPos = refText.find("@0"); + int fileMarkerPos = refText.find("@1"); + if (lineMarkerPos!=-1 && fileMarkerPos!=-1) // should always pass this. + { + if (lineMarkerPos<fileMarkerPos) // line marker before file marker + { + t << refText.left(lineMarkerPos) + << line + << refText.mid(lineMarkerPos+2, fileMarkerPos-lineMarkerPos-2) + << fileName + << refText.right(refText.length()-fileMarkerPos-2); + } + else // file marker before line marker + { + t << refText.left(fileMarkerPos) + << fileName + << refText.mid(fileMarkerPos+2, lineMarkerPos-fileMarkerPos-2) + << line + << refText.right(refText.length()-lineMarkerPos-2); + } + } + else + { + err("translation error: invalid markers in trDefinedAtLineInSourceFile()\n"); + } +} +static void generateDocbookForMember(MemberDef *md,FTextStream &t,Definition *def, bool detailed=0) +{ // + declaration/definition arg lists // + reimplements // + reimplementedBy @@ -441,17 +684,18 @@ static void generateDocbookForMember(MemberDef *md,FTextStream &t,Definition *de { scopeName=md->getNamespaceDef()->name(); } - if (detailed==0) + if (detailed==0) { t << " <para>" << endl; t << " <itemizedlist>" << endl; t << " <listitem>" << endl; //enum bool closePara=TRUE; - if (md->memberType()==MemberType_Enumeration) + if (md->memberType()==MemberType_Enumeration) { + bool inLi[5]={ FALSE, FALSE, FALSE, FALSE, FALSE }; MemberList *enumFields = md->enumFieldList(); - t << " <para><literallayout>" << memType << " <link linkend=\""; + t << " <para><literallayout>" << memType << " <link linkend=\"_"; if (md->getGroupDef() && def->definitionType()==Definition::TypeGroup) { t << md->getGroupDef()->getOutputFileBase(); @@ -460,23 +704,23 @@ static void generateDocbookForMember(MemberDef *md,FTextStream &t,Definition *de { t << memberOutputFileBase(md); } - t << "_1" << md->anchor() << "\">" << convertToXML(md->name()) << "</link>"; - if (enumFields!=0) + t << "_1" << md->anchor() << "\">" << convertToDocBook(md->name()) << "</link>"; + if (enumFields!=0) { MemberListIterator emli(*enumFields); MemberDef *emd; t << " {" << endl; int cnt=0; - for (emli.toFirst();(emd=emli.current());++emli) + for (emli.toFirst();(emd=emli.current());++emli) { - if (cnt!=0) + if (cnt!=0) { t << "," << endl; } - t << "<link linkend=\"" << memberOutputFileBase(emd) << "_1" << emd->anchor() << "\">"; + t << "<link linkend=\"_" << memberOutputFileBase(emd) << "_1" << emd->anchor() << "\">"; writeDocbookString(t,emd->name()); t << "</link>"; - if (!emd->initializer().isEmpty()) + if (!emd->initializer().isEmpty()) { writeDocbookString(t,emd->initializer()); } @@ -492,9 +736,9 @@ static void generateDocbookForMember(MemberDef *md,FTextStream &t,Definition *de t << "</emphasis></para>" << endl; } } - else if (md->memberType()==MemberType_Define) + else if (md->memberType()==MemberType_Define) { - t << " <para>" << "#" << memType << " <link linkend=\""; + t << " <para>" << "#" << memType << " <link linkend=\"_"; if (md->getGroupDef() && def->definitionType()==Definition::TypeGroup) { t << md->getGroupDef()->getOutputFileBase(); @@ -503,36 +747,36 @@ static void generateDocbookForMember(MemberDef *md,FTextStream &t,Definition *de { t << memberOutputFileBase(md); } - t << "_1" << md->anchor() << "\">" << convertToXML(md->name()) << "</link>"; - if (!md->initializer().isEmpty() && md->initializer().length()<2000) + t << "_1" << md->anchor() << "\">" << convertToDocBook(md->name()) << "</link>"; + if (!md->initializer().isEmpty() && md->initializer().length()<2000) { t << " "; linkifyText(TextGeneratorDocbookImpl(t),def,md->getBodyDef(),md,md->initializer()); } - if (md->briefDescription()) + if (md->briefDescription()) { t << "<para><emphasis>"; writeDocbookString(t,md->briefDescription()); t << "</emphasis></para>" << endl; } } - else if (md->memberType()==MemberType_Variable) + else if (md->memberType()==MemberType_Variable) { - if (md->getClassDef()) + if (md->getClassDef()) { - t << " <para>" << convertToXML(md->declaration()); - if (md->briefDescription()) + t << " <para>" << convertToDocBook(md->declaration()); + if (md->briefDescription()) { t << "<para><emphasis>"; writeDocbookString(t,md->briefDescription()); t << "</emphasis></para>"; } - } - else + } + else { t << " <para>"; linkifyText(TextGeneratorDocbookImpl(t),def,md->getBodyDef(),md,md->typeString()); - t << " <link linkend=\""; + t << " <link linkend=\"_"; if (md->getGroupDef() && def->definitionType()==Definition::TypeGroup) { t << md->getGroupDef()->getOutputFileBase(); @@ -541,7 +785,7 @@ static void generateDocbookForMember(MemberDef *md,FTextStream &t,Definition *de { t << memberOutputFileBase(md); } - t << "_1" << md->anchor() << "\">" << convertToXML(md->name()) << "</link>"; + t << "_1" << md->anchor() << "\">" << convertToDocBook(md->name()) << "</link>"; if (md->briefDescription()) { t << "<para><emphasis>"; @@ -550,13 +794,13 @@ static void generateDocbookForMember(MemberDef *md,FTextStream &t,Definition *de } } } - else if (md->memberType()==MemberType_Typedef) + else if (md->memberType()==MemberType_Typedef) { t << " <para>" << memType; t << " "; linkifyText(TextGeneratorDocbookImpl(t),def,md->getBodyDef(),md,md->typeString()); t << " "; - t << " <link linkend=\""; + t << " <link linkend=\"_"; if (md->getGroupDef() && def->definitionType()==Definition::TypeGroup) { t << md->getGroupDef()->getOutputFileBase(); @@ -565,7 +809,7 @@ static void generateDocbookForMember(MemberDef *md,FTextStream &t,Definition *de { t << memberOutputFileBase(md); } - t << "_1" << md->anchor() << "\">" << convertToXML(md->name()) << "</link>"; + t << "_1" << md->anchor() << "\">" << convertToDocBook(md->name()) << "</link>"; if (md->briefDescription()) { t << "<para><emphasis>"; @@ -573,11 +817,11 @@ static void generateDocbookForMember(MemberDef *md,FTextStream &t,Definition *de t << "</emphasis></para>" << endl; } } - else if (md->memberType()==MemberType_Function) + else if (md->memberType()==MemberType_Function) { t << " <para>"; linkifyText(TextGeneratorDocbookImpl(t),def,md->getBodyDef(),md,md->typeString()); - t << " <link linkend=\""; + t << " <link linkend=\"_"; if (md->getGroupDef() && def->definitionType()==Definition::TypeGroup) { t << md->getGroupDef()->getOutputFileBase(); @@ -586,7 +830,7 @@ static void generateDocbookForMember(MemberDef *md,FTextStream &t,Definition *de { t << memberOutputFileBase(md); } - t << "_1" << md->anchor() << "\">" << convertToXML(md->name()) << "</link>"; + t << "_1" << md->anchor() << "\">" << convertToDocBook(md->name()) << "</link>"; t << " (" << endl; ArgumentList *declAl = md->declArgumentList(); if (declAl && declAl->count()>0) @@ -596,7 +840,7 @@ static void generateDocbookForMember(MemberDef *md,FTextStream &t,Definition *de int cnt=0; for (declAli.toFirst();(a=declAli.current());++declAli) { - if (cnt!=0) + if (cnt!=0) { t << ", "; } @@ -634,7 +878,7 @@ static void generateDocbookForMember(MemberDef *md,FTextStream &t,Definition *de if (md->memberType()==MemberType_Enumeration) { MemberList *enumFields = md->enumFieldList(); - t << " <section xml:id=\""; + t << " <section xml:id=\"_"; if (md->getGroupDef() && def->definitionType()==Definition::TypeGroup) { t << md->getGroupDef()->getOutputFileBase(); @@ -644,20 +888,20 @@ static void generateDocbookForMember(MemberDef *md,FTextStream &t,Definition *de t << memberOutputFileBase(md); } t << "_1" << md->anchor() << "\">" << endl; - t << " <title>" << memType << " " << convertToXML(md->name()) << " " << "</title>" << endl; + t << " <title>" << memType << " " << convertToDocBook(md->name()) << " " << "</title>" << endl; t << " "; writeDocbookDocBlock(t,md->docFile(),md->docLine(),md->getOuterScope(),md,md->documentation()); t << endl; - if (enumFields!=0) + if (enumFields!=0) { MemberListIterator emli(*enumFields); MemberDef *emd; t << " <formalpara>" << endl; t << " <title>" << theTranslator->trEnumerationValues() << ":</title>" << endl; t << " <variablelist>" << endl; - for (emli.toFirst();(emd=emli.current());++emli) + for (emli.toFirst();(emd=emli.current());++emli) { - t << " <varlistentry xml:id=\""; + t << " <varlistentry xml:id=\"_"; t << memberOutputFileBase(emd) << "_1" << emd->anchor() << "\">" << endl; t << " <term>"; writeDocbookString(t,emd->name()); @@ -675,27 +919,30 @@ static void generateDocbookForMember(MemberDef *md,FTextStream &t,Definition *de t << " </variablelist>" << endl; t << " </formalpara>" << endl; t << " <para>"; - t << "Definition at line " << md->getDefLine() << " of file " << stripPath(md->getDefFileName()) << endl; - t << " <computeroutput><literallayout>" << endl; + t << " <para>"; + definedAtLine(md->getDefLine(),stripPath(md->getDefFileName()),t); + t << "</para>" << endl; + + t << " <literallayout><computeroutput>" << endl; t << "{" << endl; - for (emli.toFirst();(emd=emli.current());++emli) + for (emli.toFirst();(emd=emli.current());++emli) { writeDocbookString(t,emd->name()); - if (!emd->initializer().isEmpty()) + if (!emd->initializer().isEmpty()) { writeDocbookString(t,emd->initializer()); } t << ", " << endl; } - t << "}" << convertToXML(md->name()) << ";" << endl; - t << " </literallayout></computeroutput>" << endl; + t << "}" << convertToDocBook(md->name()) << ";" << endl; + t << " </computeroutput></literallayout>" << endl; t << " </para>" << endl; - t << " </section>" << endl; } + t << " </section>" << endl; } - else if (md->memberType()==MemberType_Typedef) + else if (md->memberType()==MemberType_Typedef) { - t << " <section xml:id=\""; + t << " <section xml:id=\"_"; if (md->getGroupDef() && def->definitionType()==Definition::TypeGroup) { t << md->getGroupDef()->getOutputFileBase(); @@ -705,7 +952,7 @@ static void generateDocbookForMember(MemberDef *md,FTextStream &t,Definition *de t << memberOutputFileBase(md); } t << "_1" << md->anchor() << "\">" << endl; - t << " <title>" << convertToXML(md->definition()) << "</title>"; + t << " <title>" << convertToDocBook(md->definition()) << "</title>"; if(Config_getBool(REPEAT_BRIEF)) { t << " <emphasis>"; @@ -717,9 +964,9 @@ static void generateDocbookForMember(MemberDef *md,FTextStream &t,Definition *de t << endl; t << " </section>" << endl; } - else if (md->memberType()==MemberType_Function) + else if (md->memberType()==MemberType_Function) { - t << " <section xml:id=\""; + t << " <section xml:id=\"_"; if (md->getGroupDef() && def->definitionType()==Definition::TypeGroup) { t << md->getGroupDef()->getOutputFileBase(); @@ -729,23 +976,38 @@ static void generateDocbookForMember(MemberDef *md,FTextStream &t,Definition *de t << memberOutputFileBase(md); } t << "_1" << md->anchor() << "\">" << endl; - t << " <title>" << convertToXML(md->definition()) << " " << convertToXML(md->argsString()) << "</title>"; + t << " <title>" << convertToDocBook(md->definition()) << " " << convertToDocBook(md->argsString()) << "</title>"; + addIndexTerm(t,md->name(),def->name()); + addIndexTerm(t,def->name(),md->name()); if(Config_getBool(REPEAT_BRIEF)) { + if (!md->briefDescription().isEmpty()) + { t << " <emphasis>"; writeDocbookString(t,md->briefDescription()); t << "</emphasis>" << endl; + } } t << " "; writeDocbookDocBlock(t,md->docFile(),md->docLine(),md->getOuterScope(),md,md->documentation()); t << endl; + + if (Config_getBool(REFERENCED_BY_RELATION)) + { + generateSourceRefList(t,md->name(),theTranslator->trReferencedBy(),md->getReferencedByMembers(),md); + } + if (Config_getBool(REFERENCES_RELATION)) + { + generateSourceRefList(t,md->name(),theTranslator->trReferences(),md->getReferencesMembers(),md); + } + generateInlineCode(t,md->name(),md); t << " </section>" << endl; } - else if (md->memberType()==MemberType_Define) + else if (md->memberType()==MemberType_Define) { - if (md->documentation()) + if (md->documentation()) { - t << " <section xml:id=\""; + t << " <section xml:id=\"_"; if (md->getGroupDef() && def->definitionType()==Definition::TypeGroup) { t << md->getGroupDef()->getOutputFileBase(); @@ -755,36 +1017,41 @@ static void generateDocbookForMember(MemberDef *md,FTextStream &t,Definition *de t << memberOutputFileBase(md); } t << "_1" << md->anchor() << "\">" << endl; - t << " <title>" << convertToXML(md->definition()) << "</title>"; + t << " <title>" << convertToDocBook(md->definition()) << "</title>"; t << " "; writeDocbookDocBlock(t,md->docFile(),md->docLine(),md->getOuterScope(),md,md->documentation()); t << endl; - t << " <para>Definition at line " << md->getDefLine() << " of file " << stripPath(md->getDefFileName()) << "</para>" << endl; - t << " <para>The Documentation for this define was generated from the following file: </para>" << endl; - t << " <para><itemizedlist><listitem><para>" << stripPath(md->getDefFileName()) << "</para></listitem></itemizedlist></para>" << endl; t << " </section>" << endl; } } - else if (md->memberType()==MemberType_Variable) + else if (md->memberType()==MemberType_Variable) { - if (md->getClassDef()) + if (md->getClassDef()) { - if (md->documentation()) + if (md->documentation()) { - t << " <simplesect>" << endl; - t << " <title>" << convertToXML(md->definition()) << "</title>"; + t << " <section xml:id=\"_"; + if (md->getGroupDef() && def->definitionType()==Definition::TypeGroup) + { + t << md->getGroupDef()->getOutputFileBase(); + } + else + { + t << memberOutputFileBase(md); + } + t << "_1" << md->anchor() << "\">" << endl; + t << " <title>" << convertToDocBook(md->definition()) << "</title>"; + addIndexTerm(t,md->name(),def->name()); + addIndexTerm(t,def->name(),md->name()); t << " "; writeDocbookDocBlock(t,md->docFile(),md->docLine(),md->getOuterScope(),md,md->documentation()); t << endl; - t << " <para>Definition at line " << md->getDefLine() << " of file " << stripPath(md->getDefFileName()) << "</para>" << endl; - t << " <para>The Documentation for this struct was generated from the following file: </para>" << endl; - t << " <para><itemizedlist><listitem><para>" << stripPath(md->getDefFileName()) << "</para></listitem></itemizedlist></para>" << endl; - t << " </simplesect>" << endl; + t << " </section>" << endl; } } - else + else { - t << " <section xml:id=\""; + t << " <section xml:id=\"_"; if (md->getGroupDef() && def->definitionType()==Definition::TypeGroup) { t << md->getGroupDef()->getOutputFileBase(); @@ -794,7 +1061,9 @@ static void generateDocbookForMember(MemberDef *md,FTextStream &t,Definition *de t << memberOutputFileBase(md); } t << "_1" << md->anchor() << "\">" << endl; - t << " <title>" << convertToXML(md->definition()) << "</title>"; + t << " <title>" << convertToDocBook(md->definition()) << "</title>"; + addIndexTerm(t,md->name(),def->name()); + addIndexTerm(t,def->name(),md->name()); if(Config_getBool(REPEAT_BRIEF)) { t << " <emphasis>"; @@ -818,23 +1087,33 @@ static void generateDocbookSection(Definition *d,FTextStream &t,MemberList *ml,c MemberDef *md; int count=0; int doc_count=0; - QCString title, desctitle; + QCString title, desctitle, subtitle; - for (mli.toFirst();(md=mli.current());++mli) + for (mli.toFirst();(md=mli.current());++mli) { // namespace members are also inserted in the file scope, but // to prevent this duplication in the Docbook output, we filter those here. - if (d->definitionType()!=Definition::TypeFile || md->getNamespaceDef()==0) + if (d->definitionType()!=Definition::TypeFile || md->getNamespaceDef()==0) { count++; } } - + if (count==0) return; // empty list + subtitle = ""; switch (ml->listType()) { - case MemberListType_decDefineMembers: title=theTranslator->trDefines(); desctitle=theTranslator->trDefineDocumentation(); break; + case MemberListType_pubMethods: d->getLanguage()==SrcLangExt_ObjC ? title = theTranslator->trInstanceMethods() : title = theTranslator->trPublicMembers(); + switch (d->getLanguage()) + { + case SrcLangExt_ObjC: desctitle = theTranslator->trMethodDocumentation(); break; + case SrcLangExt_Fortran: desctitle = theTranslator->trMemberFunctionDocumentationFortran(); break; + default: desctitle = theTranslator->trMemberFunctionDocumentation(); break; + }; + break; + case MemberListType_priMethods: title=theTranslator->trPrivateMembers(); desctitle=""; break; + case MemberListType_decTypedefMembers: title=theTranslator->trTypedefs(); desctitle=theTranslator->trTypedefDocumentation(); break; case MemberListType_decEnumMembers: title=theTranslator->trEnumerations(); desctitle=theTranslator->trEnumerationTypeDocumentation(); break; case MemberListType_decFuncMembers: title=theTranslator->trFunctions(); desctitle=theTranslator->trFunctionDocumentation(); break; @@ -842,10 +1121,13 @@ static void generateDocbookSection(Definition *d,FTextStream &t,MemberList *ml,c case MemberListType_pubAttribs: title=theTranslator->trPublicAttribs(); desctitle=theTranslator->trMemberDataDocumentation(); break; case MemberListType_priAttribs: title=theTranslator->trPrivateAttribs(); desctitle=theTranslator->trMemberDataDocumentation(); break; case MemberListType_proAttribs: title=theTranslator->trProtectedAttribs(); desctitle=theTranslator->trMemberDataDocumentation(); break; - default: title=""; desctitle=""; break; + case MemberListType_decDefineMembers: title=theTranslator->trDefines(); desctitle=theTranslator->trDefineDocumentation(); break; + case MemberListType_related: title=theTranslator->trRelatedFunctions(); desctitle=theTranslator->trRelatedFunctionDocumentation(); + subtitle=theTranslator->trRelatedSubscript(); break; + default: title=""; desctitle=""; } - if (detailed) + if (detailed) { for (mli.toFirst();(md=mli.current());++mli) { @@ -857,40 +1139,45 @@ static void generateDocbookSection(Definition *d,FTextStream &t,MemberList *ml,c break; } - if(doc_count == 0) + if(doc_count == 0) return; + + if (!QCString(header).isEmpty()) { - return; + t << " <section>" << endl; + t << " <title>" << convertToDocBook(header) << "</title>" << endl; } - - if (desctitle) + else if (desctitle) { - t << " <section>" << endl; - t << " <title>" << desctitle << "</title>" << endl; + t << " <section>" << endl; + t << " <title>" << desctitle << "</title>" << endl; } - } else + } + else { t << " <section>" << endl; - if (header) + if (!QCString(header).isEmpty()) { - t << " <title>" << convertToXML(header) << "</title>" << endl; - } - else + t << " <title>" << convertToDocBook(header) << "</title>" << endl; + } + else { t << " <title>" << title << "</title>" << endl; } + if (!subtitle.isEmpty()) + t << " <para>" << subtitle << "</para>" << endl; } - if (documentation) + if (documentation) { t << " <description>"; writeDocbookDocBlock(t,d->docFile(),d->docLine(),d,0,documentation); t << "</description>" << endl; } - for (mli.toFirst();(md=mli.current());++mli) + for (mli.toFirst();(md=mli.current());++mli) { // namespace members are also inserted in the file scope, but // to prevent this duplication in the Docbook output, we filter those here. - if (d->definitionType()!=Definition::TypeFile || md->getNamespaceDef()==0) + if (d->definitionType()!=Definition::TypeFile || md->getNamespaceDef()==0) { if (detailed && md->documentation().isEmpty() && !Config_getBool(REPEAT_BRIEF)) { @@ -900,14 +1187,18 @@ static void generateDocbookSection(Definition *d,FTextStream &t,MemberList *ml,c generateDocbookForMember(md,t,d,detailed); } } - if (detailed) + if (detailed) { - if (desctitle) + if (!QCString(header).isEmpty()) + { + t << " </section>" << endl; + } + else if (desctitle) { - t << " </section>" << endl; + t << " </section>" << endl; } - } - else + } + else { t << " </section>" << endl; } @@ -921,19 +1212,19 @@ static void writeInnerClasses(const ClassSDict *cl,FTextStream &t) ClassDef *cd; QCString title = theTranslator->trClasses(); - if (cli.toFirst()) + if (cli.toFirst()) { t << " <section>" << endl; t << " <title> " << title << " </title>" << endl; } for (cli.toFirst();(cd=cli.current());++cli) { - if (!cd->isHidden() && cd->name().find('@')==-1) + if (!cd->isHidden() && cd->name().find('@')==-1) { t << " <para>" << endl; t << " <itemizedlist>" << endl; t << " <listitem>" << endl; - t << " <para>" << "struct <link linkend=\"" << classOutputFileBase(cd) << "\">" << convertToXML(cd->name()) << "</link>"; + t << " <para>" << "struct <link linkend=\"_" << classOutputFileBase(cd) << "\">" << convertToDocBook(cd->name()) << "</link>"; t << "</para>" << endl; if (cd->briefDescription()) { @@ -946,7 +1237,7 @@ static void writeInnerClasses(const ClassSDict *cl,FTextStream &t) t << " </para>" << endl; } } - if (cli.toFirst()) + if (cli.toFirst()) { t << " </section>" << endl; } @@ -961,26 +1252,26 @@ static void writeInnerNamespaces(const NamespaceSDict *nl,FTextStream &t) NamespaceDef *nd; QCString title = theTranslator->trNamespaces(); - if (nli.toFirst()) + if (nli.toFirst()) { t << " <simplesect>" << endl; t << " <title> " << title << " </title>" << endl; } for (nli.toFirst();(nd=nli.current());++nli) { - if (!nd->isHidden() && nd->name().find('@')==-1) // skip anonymouse scopes + if (!nd->isHidden() && nd->name().find('@')==-1) // skip anonymous scopes { t << " <para>" << endl; t << " <itemizedlist>" << endl; t << " <listitem>" << endl; - t << " <para>" << "struct <link linkend=\"" << nd->getOutputFileBase() << "\">" << convertToXML(nd->name()) << "</link>"; + t << " <para>" << "struct <link linkend=\"_" << nd->getOutputFileBase() << "\">" << convertToDocBook(nd->name()) << "</link>"; t << "</para>" << endl; t << " </listitem>" << endl; t << " </itemizedlist>" << endl; t << " </para>" << endl; } } - if (nli.toFirst()) + if (nli.toFirst()) { t << " </simplesect>" << endl; } @@ -995,23 +1286,23 @@ static void writeInnerFiles(const FileList *fl,FTextStream &t) FileDef *fd; QCString title = theTranslator->trFile(TRUE,TRUE); - if (fli.toFirst()) + if (fli.toFirst()) { t << " <simplesect>" << endl; t << " <title> " << title << " </title>" << endl; } - for (fli.toFirst();(fd=fli.current());++fli) + for (fli.toFirst();(fd=fli.current());++fli) { t << " <para>" << endl; t << " <itemizedlist>" << endl; t << " <listitem>" << endl; - t << " <para>" << "file <link linkend=\"" << fd->getOutputFileBase() << "\">" << convertToXML(fd->name()) << "</link>"; + t << " <para>" << "file <link linkend=\"_" << fd->getOutputFileBase() << "\">" << convertToDocBook(fd->name()) << "</link>"; t << "</para>" << endl; t << " </listitem>" << endl; t << " </itemizedlist>" << endl; t << " </para>" << endl; } - if (fli.toFirst()) + if (fli.toFirst()) { t << " </simplesect>" << endl; } @@ -1040,7 +1331,7 @@ static void writeInnerGroups(const GroupList *gl,FTextStream &t) GroupDef *sgd; //Docbook header tags for inner groups - if (gli.toFirst()) + if (gli.toFirst()) { t << " <simplesect>" << endl; t << " <title>" << theTranslator->trModules() << "</title>" << endl; @@ -1051,11 +1342,11 @@ static void writeInnerGroups(const GroupList *gl,FTextStream &t) for (gli.toFirst();(sgd=gli.current());++gli) { - t << " <listitem><para><link linkend=\"" << sgd->getOutputFileBase() << "\">" << convertToXML(sgd->groupTitle()) << "</link></para></listitem>" << endl; + t << " <listitem><para><link linkend=\"_" << sgd->getOutputFileBase() << "\">" << convertToDocBook(sgd->groupTitle()) << "</link></para></listitem>" << endl; } //Docbook footer tags for inner groups - if (gli.toFirst()) + if (gli.toFirst()) { t << " </itemizedlist>" << endl; t << " </para>" << endl; @@ -1071,7 +1362,7 @@ static void writeInnerDirs(const DirList *dl,FTextStream &t) QListIterator<DirDef> subdirs(*dl); DirDef *subdir; QCString title = theTranslator->trDirectories(); - if (subdirs.toFirst()) + if (subdirs.toFirst()) { t << " <simplesect>" << endl; t << " <title> " << title << " </title>" << endl; @@ -1081,13 +1372,13 @@ static void writeInnerDirs(const DirList *dl,FTextStream &t) t << " <para>" << endl; t << " <itemizedlist>" << endl; t << " <listitem>" << endl; - t << " <para>" << "dir <link linkend=\"" << subdir->getOutputFileBase() << "\">" << convertToXML(subdir->displayName()) << "</link>"; + t << " <para>" << "dir <link linkend=\"_" << subdir->getOutputFileBase() << "\">" << convertToDocBook(subdir->displayName()) << "</link>"; t << "</para>" << endl; t << " </listitem>" << endl; t << " </itemizedlist>" << endl; t << " </para>" << endl; } - if (subdirs.toFirst()) + if (subdirs.toFirst()) { t << " </simplesect>" << endl; } @@ -1152,8 +1443,15 @@ static void generateDocbookForClass(ClassDef *cd,FTextStream &ti) writeDocbookHeader_ID(t, classOutputFileBase(cd)); t << "<title>"; writeDocbookString(t,cd->name()); + addIndexTerm(t,cd->name()); t << " " << cd->compoundTypeString() << " Reference"; t << "</title>" << endl; + if (cd->briefDescription()) + { + t << " <para>" << endl; + writeDocbookDocBlock(t,cd->briefFile(),cd->briefLine(),cd,0,cd->briefDescription()); + t << " </para>" << endl; + } IncludeInfo *ii=cd->includeInfo(); if (ii) @@ -1166,7 +1464,7 @@ static void generateDocbookForClass(ClassDef *cd,FTextStream &ti) t << " <programlisting>#include "; if (ii->fileDef && !ii->fileDef->isReference()) // TODO: support external references { - t << "<link linkend=\"" << ii->fileDef->getOutputFileBase() << "\">"; + t << "<link linkend=\"_" << ii->fileDef->getOutputFileBase() << "\">"; } if (ii->local) { @@ -1176,7 +1474,7 @@ static void generateDocbookForClass(ClassDef *cd,FTextStream &ti) { t << "<"; } - t << convertToXML(nm); + t << convertToDocBook(nm); if (ii->local) { t << """; @@ -1196,14 +1494,14 @@ static void generateDocbookForClass(ClassDef *cd,FTextStream &ti) if (Config_getBool(HAVE_DOT) && (Config_getBool(CLASS_DIAGRAMS) || Config_getBool(CLASS_GRAPH))) { - t << "<para>Inheritance diagram for " << convertToXML(cd->name()) << "</para>" << endl; + t << "<para>Inheritance diagram for " << convertToDocBook(cd->name()) << "</para>" << endl; DotClassGraph inheritanceGraph(cd,DotNode::Inheritance); inheritanceGraph.writeGraph(t,GOF_BITMAP,EOF_DocBook,Config_getString(DOCBOOK_OUTPUT),fileName,relPath,TRUE,FALSE); } if (Config_getBool(HAVE_DOT) && Config_getBool(COLLABORATION_GRAPH)) { - t << "<para>Collaboration diagram for " << convertToXML(cd->name()) << "</para>" << endl; + t << "<para>Collaboration diagram for " << convertToDocBook(cd->name()) << "</para>" << endl; DotClassGraph collaborationGraph(cd,DotNode::Collaboration); collaborationGraph.writeGraph(t,GOF_BITMAP,EOF_DocBook,Config_getString(DOCBOOK_OUTPUT),fileName,relPath,TRUE,FALSE); } @@ -1222,7 +1520,6 @@ static void generateDocbookForClass(ClassDef *cd,FTextStream &ti) } } - QListIterator<MemberList> mli(cd->getMemberLists()); MemberList *ml; for (mli.toFirst();(ml=mli.current());++mli) @@ -1233,28 +1530,41 @@ static void generateDocbookForClass(ClassDef *cd,FTextStream &ti) } } - if(Config_getBool(REPEAT_BRIEF)) + if ((Config_getBool(REPEAT_BRIEF) && cd->briefDescription()) || cd->documentation()) { - if (cd->briefDescription()) + t << " <simplesect>" << endl; + t << " <title>" << theTranslator->trDetailedDescription() << "</title>" << endl; + + if(Config_getBool(REPEAT_BRIEF)) + { + if (cd->briefDescription()) { - t << " <simplesect>" << endl; + t << " <para>" << endl; // A title as 'Brief Description' may not be necessary. //t << " <title>" << theTranslator->trBriefDescription() << "</title>" << endl; writeDocbookDocBlock(t,cd->briefFile(),cd->briefLine(),cd,0,cd->briefDescription()); - t << " </simplesect>" << endl; + t << " </para>" << endl; } + } + + if (cd->documentation()) + { + writeDocbookDocBlock(t,cd->docFile(),cd->docLine(),cd,0,cd->documentation()); + } + t << " </simplesect>" << endl; } - if (cd->documentation()) + if (cd->getMemberGroupSDict()) { - t << " <simplesect>" << endl; - t << " <title>" << theTranslator->trDetailedDescription() << "</title>" << endl; - writeDocbookDocBlock(t,cd->docFile(),cd->docLine(),cd,0,cd->documentation()); - t << " <para>Definition at line " << cd->getDefLine() << " of file " << stripPath(cd->getDefFileName()) << "</para>" << endl; - t << " <para>The Documentation for this struct was generated from the following file: </para>" << endl; - t << " <para><itemizedlist><listitem><para>" << stripPath(cd->getDefFileName()) << "</para></listitem></itemizedlist></para>" << endl; - t << " </simplesect>" << endl; + MemberGroupSDict::Iterator mgli(*cd->getMemberGroupSDict()); + MemberGroup *mg; + for (;(mg=mgli.current());++mgli) + { + generateDocbookSection(cd,t,mg->members(),"user-defined",1,mg->header(), + mg->documentation()); + } } + for (mli.toFirst();(ml=mli.current());++mli) { if ((ml->listType()&MemberListType_detailedLists)==0) @@ -1295,6 +1605,8 @@ static void generateDocbookForClass(ClassDef *cd,FTextStream &ti) writeListOfAllMembers(cd,t); */ + t << " <para>" << cd->generatedFromFiles() << "</para>" << endl; + t << " <para><itemizedlist><listitem><para>" << stripPath(cd->getDefFileName()) << "</para></listitem></itemizedlist></para>" << endl; t << "</section>" << endl; } @@ -1329,9 +1641,16 @@ static void generateDocbookForNamespace(NamespaceDef *nd,FTextStream &ti) writeDocbookHeader_ID(t, nd->getOutputFileBase()); t << "<title>"; - writeDocbookString(t,nd->name()); + addIndexTerm(t,nd->displayName()); + writeDocbookString(t,nd->title()); t << "</title>" << endl; + if (nd->briefDescription()) + { + t << " <para>" << endl; + //t << " <title>" << theTranslator->trBriefDescription() << "</title>" << endl; + t << " </para>" << endl; + } writeInnerClasses(nd->getClassSDict(),t); writeInnerNamespaces(nd->getNamespaceSDict(),t); @@ -1356,27 +1675,52 @@ static void generateDocbookForNamespace(NamespaceDef *nd,FTextStream &ti) } } - if(Config_getBool(REPEAT_BRIEF)) + if ((Config_getBool(REPEAT_BRIEF) && nd->briefDescription()) || nd->documentation()) { - if (nd->briefDescription()) + t << " <simplesect>" << endl; + t << " <title>" << theTranslator->trDetailedDescription() << "</title>" << endl; + + if(Config_getBool(REPEAT_BRIEF)) + { + if (nd->briefDescription()) { - t << " <simplesect>" << endl; + t << " <para>" << endl; //t << " <title>" << theTranslator->trBriefDescription() << "</title>" << endl; writeDocbookDocBlock(t,nd->briefFile(),nd->briefLine(),nd,0,nd->briefDescription()); - t << " </simplesect>" << endl; + t << " </para>" << endl; } + } + + if (nd->documentation()) + { + writeDocbookDocBlock(t,nd->docFile(),nd->docLine(),nd,0,nd->documentation()); + } + t << " </simplesect>" << endl; } - if (nd->documentation()) + if (nd->getMemberGroupSDict()) { - t << " <simplesect>" << endl; - t << " <title>" << theTranslator->trDetailedDescription() << "</title>" << endl; - writeDocbookDocBlock(t,nd->docFile(),nd->docLine(),nd,0,nd->documentation()); - t << " <para>Definition at line " << nd->getDefLine() << " of file " << stripPath(nd->getDefFileName()) << "</para>" << endl; - t << " <para>The Documentation for this struct was generated from the following file: </para>" << endl; - t << " <para><itemizedlist><listitem><para>" << stripPath(nd->getDefFileName()) << "</para></listitem></itemizedlist></para>" << endl; - t << " </simplesect>" << endl; + MemberGroupSDict::Iterator mgli(*nd->getMemberGroupSDict()); + MemberGroup *mg; + for (;(mg=mgli.current());++mgli) + { + generateDocbookSection(nd,t,mg->members(),"user-defined",1,mg->header(), + mg->documentation()); + } + } + + for (mli.toFirst();(ml=mli.current());++mli) + { + if ((ml->listType()&MemberListType_detailedLists)==0) + { + if (ml->listType() != MemberListType_allMembersList && + ml->listType() != MemberListType_docFuncMembers) + generateDocbookSection(nd,t,ml,g_docbookSectionMapper.find(ml->listType()),1); + } } + // we actually need here "namespace" + // t << " <para>" << theTranslator->trGeneratedFromFiles(ClassDef::Struct, FALSE) << "</para>" << endl; + // t << " <para><itemizedlist><listitem><para>" << stripPath(nd->getDefFileName()) << "</para></listitem></itemizedlist></para>" << endl; t << "</section>" << endl; } @@ -1421,6 +1765,13 @@ static void generateDocbookForFile(FileDef *fd,FTextStream &ti) t << " File Reference"; t << "</title>" << endl; + if (fd->briefDescription()) + { + t << " <para>" << endl; + writeDocbookDocBlock(t,fd->briefFile(),fd->briefLine(),fd,0,fd->briefDescription()); + t << " </para>" << endl; + } + IncludeInfo *inc; if (fd->includeFileList()) @@ -1437,7 +1788,7 @@ static void generateDocbookForFile(FileDef *fd,FTextStream &ti) { t << "<"; } - t << convertToXML(inc->includeName); + t << convertToDocBook(inc->includeName); if (inc->local) { t << """; @@ -1453,13 +1804,13 @@ static void generateDocbookForFile(FileDef *fd,FTextStream &ti) { if (Config_getBool(INCLUDE_GRAPH)) { - t << "<para>Include dependency diagram for " << convertToXML(fd->name()) << "</para>" << endl; + t << "<para>Include dependency diagram for " << convertToDocBook(fd->name()) << "</para>" << endl; DotInclDepGraph idepGraph(fd, FALSE); idepGraph.writeGraph(t,GOF_BITMAP,EOF_DocBook,Config_getString(DOCBOOK_OUTPUT),fileName,relPath,FALSE); } if (Config_getBool(INCLUDED_BY_GRAPH)) { - t << "<para>Included by dependency diagram for " << convertToXML(fd->name()) << "</para>" << endl; + t << "<para>Included by dependency diagram for " << convertToDocBook(fd->name()) << "</para>" << endl; DotInclDepGraph ibdepGraph(fd, TRUE); ibdepGraph.writeGraph(t,GOF_BITMAP,EOF_DocBook,Config_getString(DOCBOOK_OUTPUT),fileName,relPath,FALSE); } @@ -1497,9 +1848,15 @@ static void generateDocbookForFile(FileDef *fd,FTextStream &ti) t << " <simplesect>" << endl; t << " <title>" << theTranslator->trDetailedDescription() << "</title>" << endl; - writeDocbookDocBlock(t,fd->briefFile(),fd->briefLine(),fd,0,fd->briefDescription()); + if(Config_getBool(REPEAT_BRIEF)) + { + if (fd->briefDescription()) + { + writeDocbookDocBlock(t,fd->briefFile(),fd->briefLine(),fd,0,fd->briefDescription()); + } + } writeDocbookDocBlock(t,fd->docFile(),fd->docLine(),fd,0,fd->documentation()); - if (Config_getBool(FULL_PATH_NAMES)) + if (Config_getBool(FULL_PATH_NAMES)) { t << " <para>Definition in file " << fd->getDefFileName() << "</para>" << endl; } @@ -1509,9 +1866,17 @@ static void generateDocbookForFile(FileDef *fd,FTextStream &ti) } t << " </simplesect>" << endl; + for (mli.toFirst();(ml=mli.current());++mli) + { + if ((ml->listType()&MemberListType_declarationLists)!=0) + { + generateDocbookSection(fd,t,ml,g_docbookSectionMapper.find(ml->listType()),1); + } + } + if (Config_getBool(DOCBOOK_PROGRAMLISTING)) { - t << " <literallayout><computeroutput>" << endl; + t << " <literallayout><computeroutput>" << endl;; writeDocbookCodeBlock(t,fd); t << " </computeroutput></literallayout>" << endl; } @@ -1535,7 +1900,7 @@ static void generateDocbookForGroup(GroupDef *gd,FTextStream &ti) if (gd->isReference()) return; // skip external references - if (!gd->isASubGroup()) + if (!gd->isASubGroup()) { QCString fileDocbook=gd->getOutputFileBase()+".xml"; //Add the file Documentation info to index file @@ -1557,31 +1922,21 @@ static void generateDocbookForGroup(GroupDef *gd,FTextStream &ti) //t.setEncoding(FTextStream::UnicodeUTF8); writeDocbookHeader_ID(t, gd->getOutputFileBase()); - t << " <title>" << convertToXML(gd->groupTitle()) << "</title>" << endl; + t << " <title>" << convertToDocBook(gd->groupTitle()) << "</title>" << endl; + if (gd->briefDescription()) + { + t << " <para>" << endl; + writeDocbookDocBlock(t,gd->briefFile(),gd->briefLine(),gd,0,gd->briefDescription()); + t << " </para>" << endl; + } if (Config_getBool(GROUP_GRAPHS) && Config_getBool(HAVE_DOT)) { - t << "<para>Collaboration diagram for " << convertToXML(gd->groupTitle()) << "</para>" << endl; + t << "<para>Collaboration diagram for " << convertToDocBook(gd->groupTitle()) << "</para>" << endl; DotGroupCollaboration collaborationGraph(gd); collaborationGraph.writeGraph(t,GOF_BITMAP,EOF_DocBook,Config_getString(DOCBOOK_OUTPUT),fileName,relPath,FALSE); } - if (gd->briefDescription()) - { - //t << " <section>" << endl; - //t << " <title>" << theTranslator->trBriefDescription() << "</title>" << endl; - writeDocbookDocBlock(t,gd->briefFile(),gd->briefLine(),gd,0,gd->briefDescription()); - //t << " </section>" << endl; - } - - if (gd->documentation()) - { - t << " <section>" << endl; - t << " <title>" << theTranslator->trDetailedDescription() << "</title>" << endl; - writeDocbookDocBlock(t,gd->docFile(),gd->docLine(),gd,0,gd->documentation()); - t << " </section>" << endl; - } - writeInnerFiles(gd->getFiles(),t); writeInnerClasses(gd->getClasses(),t); writeInnerNamespaces(gd->getNamespaces(),t); @@ -1608,6 +1963,26 @@ static void generateDocbookForGroup(GroupDef *gd,FTextStream &ti) generateDocbookSection(gd,t,ml,g_docbookSectionMapper.find(ml->listType())); } } + + if(Config_getBool(REPEAT_BRIEF)) + { + if (gd->briefDescription()) + { + //t << " <section>" << endl; + //t << " <title>" << theTranslator->trBriefDescription() << "</title>" << endl; + writeDocbookDocBlock(t,gd->briefFile(),gd->briefLine(),gd,0,gd->briefDescription()); + //t << " </section>" << endl; + } + } + + if (gd->documentation()) + { + t << " <simplesect>" << endl; + t << " <title>" << theTranslator->trDetailedDescription() << "</title>" << endl; + writeDocbookDocBlock(t,gd->docFile(),gd->docLine(),gd,0,gd->documentation()); + t << " </simplesect>" << endl; + } + for (mli.toFirst();(ml=mli.current());++mli) { if ((ml->listType()&MemberListType_declarationLists)!=0) @@ -1648,9 +2023,13 @@ static void generateDocbookForDir(DirDef *dd,FTextStream &ti) t << " <title>"; t << theTranslator->trDirReference(dd->displayName()); t << "</title>" << endl; + if (dd->briefDescription()) + { + writeDocbookDocBlock(t,dd->briefFile(),dd->briefLine(),dd,0,dd->briefDescription()); + } if (Config_getBool(DIRECTORY_GRAPH) && Config_getBool(HAVE_DOT)) { - t << "<para>Directory dependency diagram for " << convertToXML(dd->displayName()) << "</para>" << endl; + t << "<para>Directory dependency diagram for " << convertToDocBook(dd->displayName()) << "</para>" << endl; DotDirDeps dirdepGraph(dd); dirdepGraph.writeGraph(t,GOF_BITMAP,EOF_DocBook,Config_getString(DOCBOOK_OUTPUT),fileName,relPath,FALSE); } @@ -1660,7 +2039,12 @@ static void generateDocbookForDir(DirDef *dd,FTextStream &ti) t << " <simplesect>" << endl; t << " <title>" << theTranslator->trDetailedDescription() << "</title>" << endl; - writeDocbookDocBlock(t,dd->briefFile(),dd->briefLine(),dd,0,dd->briefDescription()); + if (dd->briefDescription()) + { + t << " <para>" << endl; + writeDocbookDocBlock(t,dd->briefFile(),dd->briefLine(),dd,0,dd->briefDescription()); + t << " </para>" << endl; + } writeDocbookDocBlock(t,dd->docFile(),dd->docLine(),dd,0,dd->documentation()); t << " <para>Directory location is " << dd->name() << "</para>" << endl; t << " </simplesect>" << endl; @@ -1681,7 +2065,7 @@ static void generateDocbookForPage(PageDef *pd,FTextStream &ti,bool isExample) { pageName+=(QCString)"_"+pd->name(); } - if (pageName=="index") + if (pageName=="index") { pageName="mainpage"; // to prevent overwriting the generated index page. } @@ -1709,9 +2093,9 @@ static void generateDocbookForPage(PageDef *pd,FTextStream &ti,bool isExample) QCString fileDocbook=pageName+".xml"; //Add the file Documentation info to index file ti << " <xi:include href=\"" << fileDocbook << "\" xmlns:xi=\"http://www.w3.org/2001/XInclude\"/>" << endl; - writeDocbookHeaderMainpage(t); - } - else + writeDocbookHeaderMainpage(t,pageName); + } + else { QCString pid; if(isExample) @@ -1728,13 +2112,17 @@ static void generateDocbookForPage(PageDef *pd,FTextStream &ti,bool isExample) SectionInfo *si = Doxygen::sectionDict->find(pd->name()); if (si) { - t << " <title>" << convertToXML(si->title) << "</title>" << endl; - } - else + if ( pageName == "mainpage") + t << " <title>" << convertToDocBook(theTranslator->trMainPage()) << "</title>" << endl; + else + t << " <title>" << convertToDocBook(si->title) << "</title>" << endl; + } + else { - t << " <title>" << convertToXML(pd->name()) << "</title>" << endl; + t << " <title>" << convertToDocBook(pd->name()) << "</title>" << endl; } + generateTOC(t, pd); if (isExample) { writeDocbookDocBlock(t,pd->docFile(),pd->docLine(),pd,0, @@ -1750,14 +2138,13 @@ static void generateDocbookForPage(PageDef *pd,FTextStream &ti,bool isExample) if (!pd->hasParentPage() && !isExample) { t << endl << "</chapter>" << endl; - } - else + } + else { t << endl << "</section>" << endl; } } - -void generateDocbook() +void generateDocbook_v1() { // + classes @@ -1824,7 +2211,7 @@ void generateDocbook() t << "<?xml version='1.0' encoding='UTF-8' standalone='no'?>" << endl;; t << "<book xmlns=\"http://docbook.org/ns/docbook\" version=\"5.0\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">" << endl; t << " <info>" << endl; - t << " <title>" << dbk_projectName << "</title>" << endl; + t << " <title>" << convertToDocBook(dbk_projectName) << "</title>" << endl; t << " </info>" << endl; // NAMESPACE DOCUMENTATION @@ -1832,7 +2219,7 @@ void generateDocbook() NamespaceDef *nd; //Namespace Documentation index header - if (nli.toFirst()) + if (nli.toFirst()) { t << " <chapter>" << endl; t << " <title>Namespace Documentation</title>" << endl; @@ -1845,7 +2232,7 @@ void generateDocbook() } //Namespace Documentation index footer - if (nli.toFirst()) + if (nli.toFirst()) { t << " </chapter>" << endl; } @@ -1876,7 +2263,7 @@ void generateDocbook() GroupDef *gd; //Module group Documentation index header - if (gli.toFirst()) + if (gli.toFirst()) { t << " <chapter>" << endl; t << " <title>" << theTranslator->trModuleDocumentation() << "</title>" << endl; @@ -1889,7 +2276,7 @@ void generateDocbook() } //Module group Documentation index footer - if (gli.toFirst()) + if (gli.toFirst()) { t << " </chapter>" << endl; } @@ -1901,7 +2288,7 @@ void generateDocbook() ClassDef *cd; //Class Documentation index header - if (cli.toFirst()) + if (cli.toFirst()) { t << " <chapter>" << endl; t << " <title>" << theTranslator->trClassDocumentation() << "</title>" << endl; @@ -1913,7 +2300,7 @@ void generateDocbook() } //Class Documentation index footer - if (cli.toFirst()) + if (cli.toFirst()) { t << " </chapter>" << endl; } @@ -1928,7 +2315,7 @@ void generateDocbook() FileName *fn; //File Documentation index header - if (fnli.toFirst()) + if (fnli.toFirst()) { t << " <chapter>" << endl; t << " <title>" << theTranslator->trFileDocumentation() << "</title>" << endl; @@ -1946,7 +2333,7 @@ void generateDocbook() } //File Documentation index footer - if (fnli.toFirst()) + if (fnli.toFirst()) { t << " </chapter>" << endl; } @@ -1959,7 +2346,7 @@ void generateDocbook() DirSDict::Iterator sdi(*Doxygen::directories); //Directory Documentation index header - if (sdi.toFirst()) + if (sdi.toFirst()) { t << " <chapter>" << endl; t << " <title>" << theTranslator->trDirDocumentation() << "</title>" << endl; @@ -1972,7 +2359,7 @@ void generateDocbook() } //Module group Documentation index footer - if (sdi.toFirst()) + if (sdi.toFirst()) { t << " </chapter>" << endl; } @@ -1985,7 +2372,7 @@ void generateDocbook() PageDef *pd=0; //Example Page Documentation index header - if (pdi.toFirst()) + if (pdi.toFirst()) { t << " <chapter>" << endl; t << " <title>" << theTranslator->trExampleDocumentation() << "</title>" << endl; @@ -1998,14 +2385,943 @@ void generateDocbook() } //Example Page Documentation index footer - if (pdi.toFirst()) + if (pdi.toFirst()) { t << " </chapter>" << endl; } } + t << "<index/>" << endl; t << "</book>" << endl; } +DocbookGenerator::DocbookGenerator() : OutputGenerator() +{ +DB_GEN_C + dir=Config_getString(DOCBOOK_OUTPUT); + //insideTabbing=FALSE; + //firstDescItem=TRUE; + //disableLinks=FALSE; + //m_indent=0; + //templateMemberItem = FALSE; + m_prettyCode=Config_getBool(DOCBOOK_PROGRAMLISTING); + m_denseText = FALSE; + m_inGroup = FALSE; + m_inDetail = FALSE; + m_levelListItem = 0; + m_descTable = FALSE; + m_inLevel = -1; + m_firstMember = FALSE; + for (int i = 0 ; i < sizeof(m_inListItem) / sizeof(*m_inListItem) ; i++) m_inListItem[i] = FALSE; + for (int i = 0 ; i < sizeof(m_inSimpleSect) / sizeof(*m_inSimpleSect) ; i++) m_inSimpleSect[i] = FALSE; +} + +DocbookGenerator::~DocbookGenerator() +{ +DB_GEN_C +} + +void DocbookGenerator::init() +{ + QCString dir=Config_getString(DOCBOOK_OUTPUT); + QDir d(dir); + if (!d.exists() && !d.mkdir(dir)) + { + err("Could not create output directory %s\n",dir.data()); + exit(1); + } + createSubDirs(d); +} + +void DocbookGenerator::startFile(const char *name,const char *,const char *) +{ +DB_GEN_C + QCString fileName=name; + QCString pageName; + QCString fileType="section"; + if (fileName == "refman") + { + fileName="index"; + fileType="book"; + } + else if (fileName == "index") + { + fileName="mainpage"; + fileType="chapter"; + } + pageName = fileName; + relPath = relativePathToRoot(fileName); + if (fileName.right(4)!=".xml") fileName+=".xml"; + startPlainFile(fileName); + m_codeGen.setTextStream(t); + m_codeGen.setRelativePath(relPath); + m_codeGen.setSourceFileName(stripPath(fileName)); + + t << "<?xml version='1.0' encoding='UTF-8' standalone='no'?>" << endl;; + t << "<" << fileType << " xmlns=\"http://docbook.org/ns/docbook\" version=\"5.0\" xmlns:xlink=\"http://www.w3.org/1999/xlink\""; + if (!pageName.isEmpty()) t << " xml:id=\"_" << stripPath(pageName) << "\""; + t << ">" << endl; +} + +void DocbookGenerator::endFile() +{ +DB_GEN_C + if (m_inDetail) t << "</section>" << endl; + m_inDetail = FALSE; + while (m_inLevel != -1) + { + t << "</section>" << endl; + m_inLevel--; + } + if (m_inGroup) t << "</section>" << endl; + m_inGroup = FALSE; + + QCString fileType="section"; + QCString fileName= m_codeGen.sourceFileName(); + if (fileName == "index.xml") + { + fileType="book"; + } + else if (fileName == "mainpage.xml") + { + fileType="chapter"; + } + t << "</" << fileType << ">" << endl; + endPlainFile(); + m_codeGen.setSourceFileName(""); +} + +void DocbookGenerator::startIndexSection(IndexSections is) +{ +DB_GEN_C2("IndexSections " << is) + switch (is) + { + case isTitlePageStart: + { + QCString dbk_projectName = Config_getString(PROJECT_NAME); + t << " <info>" << endl; + t << " <title>" << convertToDocBook(dbk_projectName) << "</title>" << endl; + t << " </info>" << endl; + } + break; + case isTitlePageAuthor: + break; + case isMainPage: + t << "<chapter>" << endl; + t << " <title>"; + break; + case isModuleIndex: + //Module Index}\n" + break; + case isDirIndex: + //Directory Index}\n" + break; + case isNamespaceIndex: + //Namespace Index}\n" + break; + case isClassHierarchyIndex: + //Hierarchical Index}\n" + break; + case isCompoundIndex: + //t << "{"; //Class Index}\n" + break; + case isFileIndex: + //Annotated File Index}\n" + break; + case isPageIndex: + //Annotated Page Index}\n" + break; + case isModuleDocumentation: + t << "<chapter>\n"; + t << " <title>"; + break; + case isDirDocumentation: + t << "<chapter>\n"; + t << " <title>"; + break; + case isNamespaceDocumentation: + t << "<chapter>\n"; + t << " <title>"; + break; + case isClassDocumentation: + t << "<chapter>\n"; + t << " <title>"; + break; + case isFileDocumentation: + t << "<chapter>\n"; + t << " <title>"; + break; + case isExampleDocumentation: + t << "<chapter>\n"; + t << " <title>"; + break; + case isPageDocumentation: + break; + case isPageDocumentation2: + break; + case isEndIndex: + break; + } +} + +void DocbookGenerator::endIndexSection(IndexSections is) +{ +DB_GEN_C2("IndexSections " << is) + static bool sourceBrowser = Config_getBool(SOURCE_BROWSER); + switch (is) + { + case isTitlePageStart: + break; + case isTitlePageAuthor: + break; + case isMainPage: + t << "</title>" << endl; + t << " <xi:include href=\"mainpage.xml\" xmlns:xi=\"http://www.w3.org/2001/XInclude\"/>" << endl; + t << "</chapter>" << endl; + break; + case isModuleIndex: + //t << "</chapter>" << endl; + break; + case isDirIndex: + //t << "<xi:include href=\"dirs.xml\" xmlns:xi=\"http://www.w3.org/2001/XInclude\"/>"; + //t << "</chapter>" << endl; + break; + case isNamespaceIndex: + //t << "<xi:include href=\"namespaces.xml\" xmlns:xi=\"http://www.w3.org/2001/XInclude\"/>"; + //t << "</chapter>" << endl; + break; + case isClassHierarchyIndex: + //t << "<xi:include href=\"hierarchy.xml\" xmlns:xi=\"http://www.w3.org/2001/XInclude\"/>"; + //t << "</chapter>" << endl; + break; + case isCompoundIndex: + //t << "</chapter>" << endl; + break; + case isFileIndex: + //t << "<xi:include href=\"files.xml\" xmlns:xi=\"http://www.w3.org/2001/XInclude\"/>"; + //t << "</chapter>" << endl; + break; + case isPageIndex: + //t << "<xi:include href=\"pages.xml\" xmlns:xi=\"http://www.w3.org/2001/XInclude\"/>"; + //t << "</chapter>" << endl; + break; + case isModuleDocumentation: + { + t << "</title>" << endl; + GroupSDict::Iterator gli(*Doxygen::groupSDict); + GroupDef *gd; + bool found=FALSE; + for (gli.toFirst();(gd=gli.current()) && !found;++gli) + { + if (!gd->isReference()) + { + t << " <xi:include href=\"" << gd->getOutputFileBase() << ".xml\" xmlns:xi=\"http://www.w3.org/2001/XInclude\"/>" << endl; + found=TRUE; + } + } + for (;(gd=gli.current());++gli) + { + if (!gd->isReference()) + { + t << " <xi:include href=\"" << gd->getOutputFileBase() << ".xml\" xmlns:xi=\"http://www.w3.org/2001/XInclude\"/>" << endl; + } + } + } + t << "</chapter>\n"; + break; + case isDirDocumentation: + { + t << "</title>" << endl; + SDict<DirDef>::Iterator dli(*Doxygen::directories); + DirDef *dd; + bool found=FALSE; + for (dli.toFirst();(dd=dli.current()) && !found;++dli) + { + if (dd->isLinkableInProject()) + { + t << "< xi:include href=\"" << dd->getOutputFileBase() << ".xml\" xmlns:xi=\"http://www.w3.org/2001/XInclude\"/>" << endl; + found=TRUE; + } + } + for (;(dd=dli.current());++dli) + { + if (dd->isLinkableInProject()) + { + t << " <xi:include href=\"" << dd->getOutputFileBase() << ".xml\" xmlns:xi=\"http://www.w3.org/2001/XInclude\"/>" << endl; + } + } + } + t << "</chapter>\n"; + break; + case isNamespaceDocumentation: + { + t << "</title>" << endl; + NamespaceSDict::Iterator nli(*Doxygen::namespaceSDict); + NamespaceDef *nd; + bool found=FALSE; + for (nli.toFirst();(nd=nli.current()) && !found;++nli) + { + if (nd->isLinkableInProject()) + { + t << "<xi:include href=\"" << nd->getOutputFileBase() << ".xml\" xmlns:xi=\"http://www.w3.org/2001/XInclude\"/>" << endl; + found=TRUE; + } + } + while ((nd=nli.current())) + { + if (nd->isLinkableInProject()) + { + t << "<xi:include href=\"" << nd->getOutputFileBase() << ".xml\" xmlns:xi=\"http://www.w3.org/2001/XInclude\"/>" << endl; + } + ++nli; + } + } + t << "</chapter>\n"; + break; + case isClassDocumentation: + { + t << "</title>" << endl; + ClassSDict::Iterator cli(*Doxygen::classSDict); + ClassDef *cd=0; + bool found=FALSE; + for (cli.toFirst();(cd=cli.current()) && !found;++cli) + { + if (cd->isLinkableInProject() && + cd->templateMaster()==0 && + !cd->isEmbeddedInOuterScope() + ) + { + t << " <xi:include href=\"" << cd->getOutputFileBase() << ".xml\" xmlns:xi=\"http://www.w3.org/2001/XInclude\"/>" << endl; + found=TRUE; + } + } + for (;(cd=cli.current());++cli) + { + if (cd->isLinkableInProject() && + cd->templateMaster()==0 && + !cd->isEmbeddedInOuterScope() + ) + { + t << " <xi:include href=\"" << cd->getOutputFileBase() << ".xml\" xmlns:xi=\"http://www.w3.org/2001/XInclude\"/>" << endl; + } + } + } + t << "</chapter>\n"; + break; + case isFileDocumentation: + { + t << "</title>" << endl; + bool isFirst=TRUE; + FileNameListIterator fnli(*Doxygen::inputNameList); + FileName *fn; + for (fnli.toFirst();(fn=fnli.current());++fnli) + { + FileNameIterator fni(*fn); + FileDef *fd; + for (;(fd=fni.current());++fni) + { + if (fd->isLinkableInProject()) + { + if (isFirst) + { + t << " <xi:include href=\"" << fd->getOutputFileBase() << ".xml\" xmlns:xi=\"http://www.w3.org/2001/XInclude\"/>" << endl; + if (sourceBrowser && m_prettyCode && fd->generateSourceFile()) + { + t << " <xi:include href=\"" << fd->getSourceFileBase() << ".xml\" xmlns:xi=\"http://www.w3.org/2001/XInclude\"/>" << endl; + } + isFirst=FALSE; + } + else + { + t << " <xi:include href=\"" << fd->getOutputFileBase() << ".xml\" xmlns:xi=\"http://www.w3.org/2001/XInclude\"/>" << endl; + if (sourceBrowser && m_prettyCode && fd->generateSourceFile()) + { + t << " <xi:include href=\"" << fd->getSourceFileBase() << ".xml\" xmlns:xi=\"http://www.w3.org/2001/XInclude\"/>" << endl; + } + } + } + } + } + } + t << "</chapter>\n"; + break; + case isExampleDocumentation: + { + t << "</title>" << endl; + PageSDict::Iterator pdi(*Doxygen::exampleSDict); + PageDef *pd=pdi.toFirst(); + if (pd) + { + t << " <xi:include href=\"" << pd->getOutputFileBase() << ".xml\" xmlns:xi=\"http://www.w3.org/2001/XInclude\"/>" << endl; + } + for (++pdi;(pd=pdi.current());++pdi) + { + t << " <xi:include href=\"" << pd->getOutputFileBase() << ".xml\" xmlns:xi=\"http://www.w3.org/2001/XInclude\"/>" << endl; + } + } + t << "</chapter>\n"; + break; + case isPageDocumentation: + break; + case isPageDocumentation2: + break; + case isEndIndex: + t << "<index/>" << endl; + break; + } +} +void DocbookGenerator::writePageLink(const char *name, bool /*first*/) +{ +DB_GEN_C + PageSDict::Iterator pdi(*Doxygen::pageSDict); + PageDef *pd = pdi.toFirst(); + for (pd = pdi.toFirst();(pd=pdi.current());++pdi) + { + if (!pd->getGroupDef() && !pd->isReference() && pd->name() == stripPath(name)) + { + t << "<chapter>\n"; + if (!pd->title().isEmpty()) + { + t << " <title>" << convertToDocBook(pd->title()) << "</title>" << endl; + } + else + { + t << " <title>" << convertToDocBook(pd->name()) << "</title>" << endl; + } + t << " <xi:include href=\"" << pd->getOutputFileBase() << ".xml\" xmlns:xi=\"http://www.w3.org/2001/XInclude\"/>" << endl; + t << "</chapter>\n"; + } + } +} +void DocbookGenerator::writeDoc(DocNode *n,Definition *ctx,MemberDef *) +{ +DB_GEN_C + DocbookDocVisitor *visitor = + new DocbookDocVisitor(t,*this); + n->accept(visitor); + delete visitor; +} + +void DocbookGenerator::startParagraph(const char *) +{ +DB_GEN_C + t << "<para>" << endl; +} + +void DocbookGenerator::endParagraph() +{ +DB_GEN_C + t << "</para>" << endl; +} +void DocbookGenerator::writeString(const char *text) +{ +DB_GEN_C + t << text; +} +void DocbookGenerator::startMemberHeader(const char *name,int) +{ +DB_GEN_C + t << "<simplesect>" << endl; + m_inSimpleSect[m_levelListItem] = TRUE; + t << " <title>"; +} + +void DocbookGenerator::endMemberHeader() +{ +DB_GEN_C + t << " </title>" << endl; +} +void DocbookGenerator::docify(const char *str) +{ +DB_GEN_C + t << convertToDocBook(str); +} +void DocbookGenerator::writeObjectLink(const char *ref, const char *f, + const char *anchor, const char *text) +{ +DB_GEN_C + if (anchor) + if (f) t << "<link linkend=\"_" << stripPath(f) << "_1" << anchor << "\">"; + else t << "<link linkend=\"_" << anchor << "\">"; + else + t << "<link linkend=\"_" << stripPath(f) << "\">"; + docify(text); + t << "</link>"; +} +void DocbookGenerator::startMemberList() +{ +DB_GEN_C + t << " <itemizedlist>" << endl; + m_levelListItem++; +} +void DocbookGenerator::endMemberList() +{ +DB_GEN_C + if (m_inListItem[m_levelListItem]) t << "</listitem>" << endl; + m_inListItem[m_levelListItem] = FALSE; + t << " </itemizedlist>" << endl; + m_levelListItem = (m_levelListItem> 0 ? m_levelListItem - 1 : 0); + if (m_inSimpleSect[m_levelListItem]) t << "</simplesect>" << endl; + m_inSimpleSect[m_levelListItem] = FALSE; +} +void DocbookGenerator::startMemberItem(const char *,int,const char *) +{ +DB_GEN_C + if (m_inListItem[m_levelListItem]) t << "</listitem>" << endl; + t << " <listitem><para>"; + m_inListItem[m_levelListItem] = TRUE; +} +void DocbookGenerator::endMemberItem() +{ +DB_GEN_C + t << "</para>" << endl; +} +void DocbookGenerator::startBold(void) +{ +DB_GEN_C + t << "<emphasis role=\"strong\">"; +} +void DocbookGenerator::endBold(void) +{ +DB_GEN_C + t << "</emphasis>"; +} +void DocbookGenerator::startGroupHeader(int extraIndentLevel) +{ +DB_GEN_C2("m_inLevel " << m_inLevel) +DB_GEN_C2("extraIndentLevel " << extraIndentLevel) + m_firstMember = TRUE; + if (m_inSimpleSect[m_levelListItem]) t << "</simplesect>" << endl; + m_inSimpleSect[m_levelListItem] = FALSE; + if (m_inLevel != -1) m_inGroup = TRUE; + if (m_inLevel == extraIndentLevel) t << "</section>" << endl; + m_inLevel = extraIndentLevel; + t << "<section>" << endl; + t << "<title>"; +} +void DocbookGenerator::writeRuler(void) +{ +DB_GEN_C2("m_inLevel " << m_inLevel) +DB_GEN_C2("m_inGroup " << m_inGroup) + if (m_inGroup) t << "</section>" << endl; + m_inGroup = FALSE; +} + +void DocbookGenerator::endGroupHeader(int) +{ +DB_GEN_C + t << "</title>" << endl; +} + +void DocbookGenerator::startParameterList(bool openBracket) +{ +DB_GEN_C + if (openBracket) t << "("; +} +void DocbookGenerator::endParameterList() +{ +DB_GEN_C +} +void DocbookGenerator::writeNonBreakableSpace(int n) +{ +DB_GEN_C + for (int i=0;i<n;i++) t << " "; +} +void DocbookGenerator::lineBreak(const char *) +{ +DB_GEN_C + t << endl; +} +void DocbookGenerator::startTypewriter() +{ +DB_GEN_C + if (!m_denseText) t << "<computeroutput>"; +} +void DocbookGenerator::endTypewriter() +{ +DB_GEN_C + if (!m_denseText) t << "</computeroutput>" << endl; +} +void DocbookGenerator::startTextBlock(bool dense) +{ +DB_GEN_C + if (dense) + { + m_denseText = TRUE; + t << "<programlisting>"; + } +} +void DocbookGenerator::endTextBlock(bool dense) +{ +DB_GEN_C + if (m_denseText) + { + m_denseText = FALSE; + t << "</programlisting>"; + } +} +void DocbookGenerator::startMemberDoc(const char *clname, const char *memname, const char *anchor, const char *title, + int memCount, int memTotal, bool showInline) +{ +DB_GEN_C2("m_inLevel " << m_inLevel) + t << " <section>" << endl; + t << " <title>" << convertToDocBook(title); + if (memTotal>1) + { + t << "<computeroutput>[" << memCount << "/" << memTotal << "]</computeroutput>"; + } + t << "</title>" << endl; + if (memname && memname[0]!='@') + { + addIndexTerm(t,memname,clname); + addIndexTerm(t,clname,memname); + } +} +void DocbookGenerator::endMemberDoc(bool) +{ +DB_GEN_C + t << "</computeroutput></para>"; +} +void DocbookGenerator::startTitleHead(const char *) +{ +DB_GEN_C + t << "<title>"; +} +void DocbookGenerator::endTitleHead(const char *fileName,const char *name) +{ +DB_GEN_C + t << "</title>" << endl; + if (name) addIndexTerm(t, name); +} +void DocbookGenerator::startDoxyAnchor(const char *fName,const char *manName, + const char *anchor,const char *name, + const char *args) +{ +DB_GEN_C + if (!m_inListItem[m_levelListItem] && !m_descTable) + { + if (!m_firstMember) t << " </section>"; + m_firstMember = FALSE; + } + if (anchor) + { + t << "<anchor xml:id=\"_" << stripPath(fName) << "_1" << anchor << "\"/>"; + } +} +void DocbookGenerator::endDoxyAnchor(const char *fileName,const char *anchor) +{ +DB_GEN_C +} +void DocbookGenerator::startMemberDocName(bool) +{ +DB_GEN_C + t << "<para><computeroutput>"; +} +void DocbookGenerator::endMemberDocName() +{ +DB_GEN_C +} +void DocbookGenerator::startMemberGroupHeader(bool hasHeader) +{ +DB_GEN_C + t << "<simplesect><title>"; +} +void DocbookGenerator::endMemberGroupHeader() +{ +DB_GEN_C + t << "</title>" << endl; +} +void DocbookGenerator::startMemberGroup() +{ +DB_GEN_C +} +void DocbookGenerator::endMemberGroup(bool) +{ +DB_GEN_C + t << "</simplesect>" << endl; +} +void DocbookGenerator::startClassDiagram() +{ +DB_GEN_C + t << "<para>"; +} + +void DocbookGenerator::endClassDiagram(const ClassDiagram &d, const char *fileName,const char *) +{ +DB_GEN_C + visitPreStart(t, FALSE, relPath + fileName + ".png", NULL, NULL); + d.writeImage(t,dir,relPath,fileName,FALSE); + visitPostEnd(t, FALSE); + t << "</para>" << endl; +} +void DocbookGenerator::startLabels() +{ +DB_GEN_C +} + +void DocbookGenerator::writeLabel(const char *l,bool isLast) +{ +DB_GEN_C + t << "<computeroutput>[" << l << "]</computeroutput>"; + if (!isLast) t << ", "; +} + +void DocbookGenerator::endLabels() +{ +DB_GEN_C +} +void DocbookGenerator::startExamples() +{ +DB_GEN_C + t << "<simplesect><title>"; + docify(theTranslator->trExamples()); + t << "</title>"; +} + +void DocbookGenerator::endExamples() +{ +DB_GEN_C + t << "</simplesect>" << endl; +} +void DocbookGenerator::startSubsubsection(void) +{ +DB_GEN_C + t << "<simplesect><title>"; +} +void DocbookGenerator::endSubsubsection(void) +{ +DB_GEN_C + t << "</title></simplesect>" << endl; +} +void DocbookGenerator::writeChar(char c) +{ +DB_GEN_C + char cs[2]; + cs[0]=c; + cs[1]=0; + docify(cs); +} +void DocbookGenerator::startMemberDocPrefixItem() +{ +DB_GEN_C + t << "<computeroutput>"; +} +void DocbookGenerator::endMemberDocPrefixItem() +{ +DB_GEN_C + t << "</computeroutput>"; +} +void DocbookGenerator::exceptionEntry(const char* prefix,bool closeBracket) +{ +DB_GEN_C + if (prefix) + t << " " << prefix << "("; + else if (closeBracket) + t << ")"; + t << " "; +} +void DocbookGenerator::startParameterName(bool) +{ +DB_GEN_C + t << " "; +} +void DocbookGenerator::endParameterName(bool last,bool /*emptyList*/,bool closeBracket) +{ +DB_GEN_C + if (last) + { + if (closeBracket) t << ")"; + } +} +void DocbookGenerator::startCodeFragment() +{ +DB_GEN_C + t << "<programlisting>"; +} +void DocbookGenerator::endCodeFragment() +{ +DB_GEN_C + t << "</programlisting>"; +} +void DocbookGenerator::startMemberTemplateParams() +{ +DB_GEN_C +} + +void DocbookGenerator::endMemberTemplateParams(const char *,const char *) +{ +DB_GEN_C + t << "</para>"; + t << "<para>"; +} +void DocbookGenerator::startSection(const char *lab,const char *,SectionInfo::SectionType type) +{ +DB_GEN_C + t << " <section xml:id=\"_" << stripPath(lab) << "\">"; + t << "<title>"; +} +void DocbookGenerator::endSection(const char *lab,SectionInfo::SectionType) +{ +DB_GEN_C + t << "</title>"; + t << " </section>"; +} +void DocbookGenerator::addIndexItem(const char *prim,const char *sec) +{ +DB_GEN_C + addIndexTerm(t, prim, sec); +} + +void DocbookGenerator::startDescTable(const char *title) +{ +DB_GEN_C + int ncols = 2; + t << "<informaltable frame=\"all\">" << endl; + if (title)t << "<title>" << convertToDocBook(title) << "</title>" << endl; + t << " <tgroup cols=\"" << ncols << "\" align=\"left\" colsep=\"1\" rowsep=\"1\">" << endl; + for (int i = 0; i < ncols; i++) + { + t << " <colspec colname='c" << i+1 << "'/>\n"; + } + t << "<tbody>\n"; + m_descTable = TRUE; +} + +void DocbookGenerator::endDescTable() +{ +DB_GEN_C + t << " </tbody>" << endl; + t << " </tgroup>" << endl; + t << "</informaltable>" << endl; + m_descTable = FALSE; +} + +void DocbookGenerator::startDescTableRow() +{ +DB_GEN_C + t << "<row>"; + t << "<entry>"; +} + +void DocbookGenerator::endDescTableRow() +{ +DB_GEN_C + t << "</row>"; +} + +void DocbookGenerator::startDescTableTitle() +{ +DB_GEN_C +} + +void DocbookGenerator::endDescTableTitle() +{ +DB_GEN_C +} + +void DocbookGenerator::startDescTableData() +{ +DB_GEN_C + t << "</entry><entry>"; +} + +void DocbookGenerator::endDescTableData() +{ +DB_GEN_C + t << "</entry>"; +} +void DocbookGenerator::startGroupCollaboration() +{ +DB_GEN_C +} +void DocbookGenerator::endGroupCollaboration(const DotGroupCollaboration &g) +{ +DB_GEN_C + g.writeGraph(t,GOF_BITMAP,EOF_DocBook,Config_getString(DOCBOOK_OUTPUT),fileName,relPath,FALSE); +} +void DocbookGenerator::startDotGraph() +{ +DB_GEN_C +} +void DocbookGenerator::endDotGraph(const DotClassGraph &g) +{ +DB_GEN_C + g.writeGraph(t,GOF_BITMAP,EOF_DocBook,Config_getString(DOCBOOK_OUTPUT),fileName,relPath,TRUE,FALSE); +} +void DocbookGenerator::startInclDepGraph() +{ +DB_GEN_C +} +void DocbookGenerator::endInclDepGraph(const DotInclDepGraph &g) +{ +DB_GEN_C + QCString fn = g.writeGraph(t,GOF_BITMAP,EOF_DocBook,Config_getString(DOCBOOK_OUTPUT), fileName,relPath,FALSE); +} +void DocbookGenerator::startCallGraph() +{ +DB_GEN_C +} +void DocbookGenerator::endCallGraph(const DotCallGraph &g) +{ +DB_GEN_C + QCString fn = g.writeGraph(t,GOF_BITMAP,EOF_DocBook,Config_getString(DOCBOOK_OUTPUT), fileName,relPath,FALSE); +} +void DocbookGenerator::startDirDepGraph() +{ +DB_GEN_C +} +void DocbookGenerator::endDirDepGraph(const DotDirDeps &g) +{ +DB_GEN_C + QCString fn = g.writeGraph(t,GOF_BITMAP,EOF_DocBook,Config_getString(DOCBOOK_OUTPUT), fileName,relPath,FALSE); +} +void DocbookGenerator::startMemberDocList() +{ +DB_GEN_C +} +void DocbookGenerator::endMemberDocList() +{ +DB_GEN_C + m_inGroup = TRUE; +} +void DocbookGenerator::startConstraintList(const char *header) +{ +DB_GEN_C + t << "<simplesect><title>"; + docify(header); + t << "</title>" << endl; +} +void DocbookGenerator::startConstraintParam() +{ +DB_GEN_C + t << "<para><emphasis role=\"strong\">"; +} +void DocbookGenerator::endConstraintParam() +{ +DB_GEN_C +} +void DocbookGenerator::startConstraintType() +{ +DB_GEN_C + t << ":"; +} +void DocbookGenerator::endConstraintType() +{ +DB_GEN_C + t << "</emphasis></para>" << endl; +} +void DocbookGenerator::startConstraintDocs() +{ +DB_GEN_C +} +void DocbookGenerator::endConstraintDocs() +{ +DB_GEN_C +} +void DocbookGenerator::endConstraintList() +{ +DB_GEN_C + t << "</simplesect>" << endl; +} diff --git a/src/docbookgen.h b/src/docbookgen.h index 866d056..104fbc5 100644 --- a/src/docbookgen.h +++ b/src/docbookgen.h @@ -15,6 +15,351 @@ #ifndef DOCBOOKGEN_H #define DOCBOOKGEN_H -void generateDocbook(); +#include "outputgen.h" + +void generateDocbook_v1(); + +class DocbookCodeGenerator : public CodeOutputInterface +{ + public: + DocbookCodeGenerator(FTextStream &t); + DocbookCodeGenerator(); + virtual ~DocbookCodeGenerator(); + void setTextStream(FTextStream &t) + { + m_streamSet = t.device()!=0; + m_t.setDevice(t.device()); + } + void setRelativePath(const QCString &path) { m_relPath = path; } + void setSourceFileName(const QCString &sourceFileName) { m_sourceFileName = sourceFileName; } + QCString sourceFileName() { return m_sourceFileName; } + + void codify(const char *text); + void writeCodeLink(const char *ref,const char *file, + const char *anchor,const char *name, + const char *tooltip); + void writeCodeLinkLine(const char *ref,const char *file, + const char *anchor,const char *name, + const char *tooltip); + void writeTooltip(const char *, const DocLinkInfo &, const char *, + const char *, const SourceLinkInfo &, const SourceLinkInfo & + ); + void startCodeLine(bool); + void endCodeLine(); + void startFontClass(const char *colorClass); + void endFontClass(); + void writeCodeAnchor(const char *); + void writeLineNumber(const char *extRef,const char *compId, + const char *anchorId,int l); + void setCurrentDoc(Definition *,const char *,bool); + void addWord(const char *,bool); + void finish(); + void startCodeFragment(); + void endCodeFragment(); + + private: + FTextStream m_t; + bool m_streamSet; + QCString m_refId; + QCString m_external; + int m_lineNumber; + int m_col; + bool m_insideCodeLine; + bool m_insideSpecialHL; + QCString m_relPath; + QCString m_sourceFileName; + bool m_prettyCode; +}; + + +#if 0 +// define for cases that have been implemented with an empty body +#define DB_GEN_EMPTY t << "<!-- DBG_GEN_head_check " << __LINE__ << " -->\n"; +#else +#define DB_GEN_EMPTY +#endif + +#if 0 +// Generic debug statements +#define DB_GEN_H DB_GEN_H1(t) +#define DB_GEN_H1(x) x << "<!-- DBG_GEN_head " << __LINE__ << " -->\n"; +#define DB_GEN_H2(y) DB_GEN_H2a(t,y) +#define DB_GEN_H2a(x,y) x << "<!-- DBG_GEN_head " << __LINE__ << " " << y << " -->\n"; +// define for cases that have NOT yet been implemented / considered +#define DB_GEN_NEW fprintf(stderr,"DBG_GEN_head %d\n",__LINE__); DB_GEN_H +#else +#define DB_GEN_H +#define DB_GEN_H1(x) +#define DB_GEN_H2(y) +#define DB_GEN_H2a(x,y) +#define DB_GEN_NEW +#endif + +class DocbookGenerator : public OutputGenerator +{ + public: + DocbookGenerator(); + ~DocbookGenerator(); + static void init(); + + /////////////////////////////////////////////////////////////// + // generic generator methods + /////////////////////////////////////////////////////////////// + void enable() + { if (genStack->top()) active=*genStack->top(); else active=TRUE; } + void disable() { active=FALSE; } + void enableIf(OutputType o) { if (o==Docbook) enable(); } + void disableIf(OutputType o) { if (o==Docbook) disable(); } + void disableIfNot(OutputType o) { if (o!=Docbook) disable(); } + bool isEnabled(OutputType o) { return (o==Docbook && active); } + OutputGenerator *get(OutputType o) { return (o==Docbook) ? this : 0; } + + // --- CodeOutputInterface + void codify(const char *text) + { m_codeGen.codify(text); } + void writeCodeLink(const char *ref, const char *file, + const char *anchor,const char *name, + const char *tooltip) + { m_codeGen.writeCodeLink(ref,file,anchor,name,tooltip); } + void writeLineNumber(const char *ref,const char *file,const char *anchor,int lineNumber) + { m_codeGen.writeLineNumber(ref,file,anchor,lineNumber); } + void writeTooltip(const char *id, const DocLinkInfo &docInfo, const char *decl, + const char *desc, const SourceLinkInfo &defInfo, const SourceLinkInfo &declInfo + ) + { m_codeGen.writeTooltip(id,docInfo,decl,desc,defInfo,declInfo); } + void startCodeLine(bool hasLineNumbers) + { m_codeGen.startCodeLine(hasLineNumbers); } + void endCodeLine() + { m_codeGen.endCodeLine(); } + void startFontClass(const char *s) + { m_codeGen.startFontClass(s); } + void endFontClass() + { m_codeGen.endFontClass(); } + void writeCodeAnchor(const char *anchor) + { m_codeGen.writeCodeAnchor(anchor); } + // --------------------------- + + void writeDoc(DocNode *,Definition *ctx,MemberDef *md); + + /////////////////////////////////////////////////////////////// + // structural output interface + /////////////////////////////////////////////////////////////// + void startFile(const char *name,const char *manName, + const char *title); + void writeSearchInfo(){DB_GEN_EMPTY}; + void writeFooter(const char *navPath){DB_GEN_NEW}; + void endFile(); + void startIndexSection(IndexSections); + void endIndexSection(IndexSections); + void writePageLink(const char *,bool); + void startProjectNumber(){DB_GEN_NEW}; + void endProjectNumber(){DB_GEN_NEW}; + void writeStyleInfo(int part){DB_GEN_EMPTY}; + void startTitleHead(const char *); + void endTitleHead(const char *fileName,const char *name); + void startIndexListItem(){DB_GEN_NEW}; + void endIndexListItem(){DB_GEN_NEW}; + void startIndexList(){DB_GEN_NEW}; + void endIndexList(){DB_GEN_NEW}; + void startIndexKey(){DB_GEN_NEW}; + void endIndexKey(){DB_GEN_NEW}; + void startIndexValue(bool){DB_GEN_NEW}; + void endIndexValue(const char *,bool){DB_GEN_NEW}; + void startItemList() {DB_GEN_EMPTY}; + void endItemList() {DB_GEN_EMPTY}; + + void startIndexItem(const char *ref,const char *file){DB_GEN_NEW}; + void endIndexItem(const char *ref,const char *file){DB_GEN_NEW}; + void startItemListItem() {DB_GEN_EMPTY}; + void endItemListItem() {DB_GEN_EMPTY}; + void docify(const char *text); + void writeChar(char); + void writeString(const char *); + void startParagraph(const char *); + void endParagraph(void); + void writeObjectLink(const char *,const char *,const char *,const char *); + void startHtmlLink(const char *){DB_GEN_NEW}; + void endHtmlLink(void){DB_GEN_NEW}; + void startBold(void); + void endBold(void); + void startTypewriter(void); + void endTypewriter(void); + void startEmphasis(void){DB_GEN_NEW}; + void endEmphasis(void){DB_GEN_NEW}; + void startCodeFragment(void); + void endCodeFragment(void); + void writeRuler(void); + void startDescription(void){DB_GEN_NEW}; + void endDescription(void){DB_GEN_NEW}; + void startDescItem(void){DB_GEN_NEW}; + void startDescForItem(void){DB_GEN_EMPTY}; + void endDescForItem(void){DB_GEN_EMPTY}; + void endDescItem(void){DB_GEN_NEW}; + void startCenter(void){DB_GEN_NEW}; + void endCenter(void){DB_GEN_NEW}; + void startSmall(void){DB_GEN_NEW}; + void endSmall(void){DB_GEN_NEW}; + void startExamples(void); + void endExamples(void); + void startParamList(BaseOutputDocInterface::ParamListTypes,const char *){DB_GEN_NEW}; + void endParamList(void){DB_GEN_NEW}; + void startTitle(void){DB_GEN_NEW}; + void endTitle(void){DB_GEN_NEW}; + void writeAnchor(const char *,const char *){DB_GEN_EMPTY}; + void startSection(const char *,const char *,SectionInfo::SectionType); + void endSection(const char *,SectionInfo::SectionType); + void lineBreak(const char *); + void addIndexItem(const char *,const char *); + void writeNonBreakableSpace(int); + void startDescTable(const char *); + void endDescTable(void); + void startDescTableRow(void); + void endDescTableRow(void); + void startDescTableTitle(void); + void endDescTableTitle(void); + void startDescTableData(void); + void endDescTableData(void); + void startTextLink(const char *,const char *){DB_GEN_NEW}; + void endTextLink(void){DB_GEN_NEW}; + void startPageRef(void){DB_GEN_NEW}; + void endPageRef(const char *,const char *){DB_GEN_NEW}; + void startSubsection(void){DB_GEN_NEW}; + void endSubsection(void){DB_GEN_NEW}; + void startSubsubsection(void); + void endSubsubsection(void); + + + void startGroupHeader(int); + void endGroupHeader(int); + void startMemberSections(){DB_GEN_EMPTY}; + void endMemberSections(){DB_GEN_EMPTY}; + void startHeaderSection(){DB_GEN_EMPTY}; + void endHeaderSection(){DB_GEN_EMPTY}; + void startMemberHeader(const char *anchor, int typ); + void endMemberHeader(); + void startMemberSubtitle(){DB_GEN_EMPTY}; + void endMemberSubtitle(){DB_GEN_EMPTY}; + void startMemberDocList(); + void endMemberDocList(); + void startMemberList(); + void endMemberList(); + void startInlineHeader(){DB_GEN_NEW}; + void endInlineHeader(){DB_GEN_NEW}; + void startAnonTypeScope(int){DB_GEN_EMPTY}; + void endAnonTypeScope(int){DB_GEN_EMPTY}; + void startMemberItem(const char *,int,const char *); + void endMemberItem(); + void startMemberTemplateParams(); + void endMemberTemplateParams(const char *,const char *); + void startMemberGroupHeader(bool); + void endMemberGroupHeader(); + void startMemberGroupDocs(){DB_GEN_EMPTY}; + void endMemberGroupDocs(){DB_GEN_EMPTY}; + void startMemberGroup(); + void endMemberGroup(bool); + void insertMemberAlign(bool){DB_GEN_EMPTY}; + void insertMemberAlignLeft(int,bool){DB_GEN_EMPTY}; + void startMemberDoc(const char *,const char *, + const char *,const char *,int,int,bool); + void endMemberDoc(bool); + void startDoxyAnchor(const char *fName,const char *manName, + const char *anchor,const char *name, + const char *args); + void endDoxyAnchor(const char *fileName,const char *anchor); + void writeLatexSpacing(){DB_GEN_EMPTY} + void writeStartAnnoItem(const char *type,const char *file, + const char *path,const char *name){DB_GEN_NEW}; + void writeEndAnnoItem(const char *name){DB_GEN_NEW}; + void startMemberDescription(const char *anchor,const char *inheritId, bool typ){DB_GEN_EMPTY}; + void endMemberDescription(){DB_GEN_EMPTY}; + void startMemberDeclaration(){DB_GEN_EMPTY}; + void endMemberDeclaration(const char *anchor,const char *inheritId){DB_GEN_EMPTY}; + void writeInheritedSectionTitle(const char *id,const char *ref, + const char *file,const char *anchor, + const char *title,const char *name){DB_GEN_NEW}; + void startIndent(){DB_GEN_EMPTY}; + void endIndent(){DB_GEN_EMPTY}; + void writeSynopsis(){DB_GEN_EMPTY}; + void startClassDiagram(); + void endClassDiagram(const ClassDiagram &,const char *,const char *); + void startDotGraph(); + void endDotGraph(const DotClassGraph &g); + void startInclDepGraph(); + void endInclDepGraph(const DotInclDepGraph &g); + void startGroupCollaboration(); + void endGroupCollaboration(const DotGroupCollaboration &g); + void startCallGraph(); + void endCallGraph(const DotCallGraph &g); + void startDirDepGraph(); + void endDirDepGraph(const DotDirDeps &g); + void writeGraphicalHierarchy(const DotGfxHierarchyTable &g){DB_GEN_NEW}; + void startQuickIndices(){DB_GEN_EMPTY}; + void endQuickIndices(){DB_GEN_EMPTY}; + void writeSplitBar(const char *){DB_GEN_EMPTY}; + void writeNavigationPath(const char *){DB_GEN_NEW}; + void writeLogo(){DB_GEN_NEW}; + void writeQuickLinks(bool compact,HighlightedItem hli,const char *file){DB_GEN_EMPTY}; + void writeSummaryLink(const char *file,const char *anchor,const char *title,bool first){DB_GEN_EMPTY}; + void startContents(){DB_GEN_EMPTY}; + void endContents(){DB_GEN_EMPTY}; + void startPageDoc(const char *pageTitle){DB_GEN_EMPTY} + void endPageDoc() {DB_GEN_EMPTY} + void startTextBlock(bool); + void endTextBlock(bool); + void lastIndexPage(){DB_GEN_EMPTY}; + void startMemberDocPrefixItem(); + void endMemberDocPrefixItem(); + void startMemberDocName(bool); + void endMemberDocName(); + void startParameterType(bool,const char *key){DB_GEN_EMPTY}; + void endParameterType(){DB_GEN_EMPTY}; + void startParameterName(bool); + void endParameterName(bool,bool,bool); + void startParameterList(bool); + void endParameterList(); + void exceptionEntry(const char*,bool); + + void startConstraintList(const char *); + void startConstraintParam(); + void endConstraintParam(); + void startConstraintType(); + void endConstraintType(); + void startConstraintDocs(); + void endConstraintDocs(); + void endConstraintList(); + + void startMemberDocSimple(bool){DB_GEN_NEW}; + void endMemberDocSimple(bool){DB_GEN_NEW}; + void startInlineMemberType(){DB_GEN_NEW}; + void endInlineMemberType(){DB_GEN_NEW}; + void startInlineMemberName(){DB_GEN_NEW}; + void endInlineMemberName(){DB_GEN_NEW}; + void startInlineMemberDoc(){DB_GEN_NEW}; + void endInlineMemberDoc(){DB_GEN_NEW}; + + void startLabels(); + void writeLabel(const char *,bool); + void endLabels(); + + void setCurrentDoc(Definition *,const char *,bool) {DB_GEN_EMPTY} + void addWord(const char *,bool) {DB_GEN_EMPTY} + +private: + DocbookGenerator(const DocbookGenerator &o); + DocbookGenerator &operator=(const DocbookGenerator &o); + + QCString relPath; + DocbookCodeGenerator m_codeGen; + bool m_prettyCode; + bool m_denseText; + bool m_inGroup; + bool m_inDetail; + int m_levelListItem; + bool m_inListItem[20]; + bool m_inSimpleSect[20]; + bool m_descTable; + int m_inLevel; + bool m_firstMember; +}; #endif diff --git a/src/docbookvisitor.cpp b/src/docbookvisitor.cpp index ab10da0..da84931 100644 --- a/src/docbookvisitor.cpp +++ b/src/docbookvisitor.cpp @@ -36,17 +36,34 @@ #include "htmlentity.h" #include "plantuml.h" -static void visitPreStart(FTextStream &t, const bool hasCaption, QCString name, QCString width, QCString height) +#if 0 +#define DB_VIS_C DB_VIS_C1(m_t) +#define DB_VIS_C1(x) x << "<!-- DB_VIS_C " << __LINE__ << " -->\n"; +#define DB_VIS_C2(y) DB_VIS_C2a(m_t,y) +#define DB_VIS_C2a(x,y) x << "<!-- DB_VIS_C " << __LINE__ << " " << y << " -->\n"; +#else +#define DB_VIS_C +#define DB_VIS_C1(x) +#define DB_VIS_C2(y) +#define DB_VIS_C2a(x,y) +#endif +void visitPreStart(FTextStream &t, const bool hasCaption, QCString name, QCString width, QCString height) { QCString tmpStr; - t << " <figure>" << endl; - t << " <title></title>" << endl; + if (hasCaption) + { + t << " <figure>" << endl; + } + else + { + t << " <informalfigure>" << endl; + } t << " <mediaobject>" << endl; t << " <imageobject>" << endl; t << " <imagedata"; if (!width.isEmpty()) { - t << " width=\"" << convertToXML(width) << "\""; + t << " width=\"" << convertToDocBook(width) << "\""; } else { @@ -54,26 +71,33 @@ static void visitPreStart(FTextStream &t, const bool hasCaption, QCString name, } if (!height.isEmpty()) { - t << " depth=\"" << convertToXML(tmpStr) << "\""; + t << " depth=\"" << convertToDocBook(tmpStr) << "\""; } - t << " align=\"center\" valign=\"middle\" scalefit=\"1\" fileref=\"" << name << "\">"; + t << " align=\"center\" valign=\"middle\" scalefit=\"0\" fileref=\"" << name << "\">"; t << "</imagedata>" << endl; t << " </imageobject>" << endl; if (hasCaption) { - t << " <caption>" << endl; + t << " <title>" << endl; } } -static void visitPostEnd(FTextStream &t, const bool hasCaption) +void visitPostEnd(FTextStream &t, const bool hasCaption) { t << endl; if (hasCaption) { - t << " </caption>" << endl; + t << " </title>" << endl; } t << " </mediaobject>" << endl; - t << " </figure>" << endl; + if (hasCaption) + { + t << " </figure>" << endl; + } + else + { + t << " </informalfigure>" << endl; + } } static void visitCaption(DocbookDocVisitor *parent, QList<DocNode> children) @@ -86,6 +110,13 @@ static void visitCaption(DocbookDocVisitor *parent, QList<DocNode> children) DocbookDocVisitor::DocbookDocVisitor(FTextStream &t,CodeOutputInterface &ci) : DocVisitor(DocVisitor_Docbook), m_t(t), m_ci(ci), m_insidePre(FALSE), m_hide(FALSE) { +DB_VIS_C + // m_t << "<section>" << endl; +} +DocbookDocVisitor::~DocbookDocVisitor() +{ +DB_VIS_C + // m_t << "</section>" << endl; } //-------------------------------------- @@ -94,12 +125,14 @@ DocbookDocVisitor::DocbookDocVisitor(FTextStream &t,CodeOutputInterface &ci) void DocbookDocVisitor::visit(DocWord *w) { +DB_VIS_C if (m_hide) return; filter(w->word()); } void DocbookDocVisitor::visit(DocLinkedWord *w) { +DB_VIS_C if (m_hide) return; startLink(w->file(),w->anchor()); filter(w->word()); @@ -108,6 +141,7 @@ void DocbookDocVisitor::visit(DocLinkedWord *w) void DocbookDocVisitor::visit(DocWhiteSpace *w) { +DB_VIS_C if (m_hide) return; if (m_insidePre) { @@ -121,6 +155,7 @@ void DocbookDocVisitor::visit(DocWhiteSpace *w) void DocbookDocVisitor::visit(DocSymbol *s) { +DB_VIS_C if (m_hide) return; const char *res = HtmlEntityMapper::instance()->docbook(s->symbol()); if (res) @@ -135,6 +170,7 @@ void DocbookDocVisitor::visit(DocSymbol *s) void DocbookDocVisitor::visit(DocURL *u) { +DB_VIS_C if (m_hide) return; m_t << "<link xlink:href=\""; if (u->isEmail()) m_t << "mailto:"; @@ -146,12 +182,16 @@ void DocbookDocVisitor::visit(DocURL *u) void DocbookDocVisitor::visit(DocLineBreak *) { +DB_VIS_C if (m_hide) return; - m_t << endl << "<literallayout>\n</literallayout>" << endl; + m_t << endl << "<literallayout> 
</literallayout>" << endl; + // gives nicer results but gives problems as it is not allowed in <pare> and also problems with dblatex + // m_t << endl << "<sbr/>" << endl; } void DocbookDocVisitor::visit(DocHorRuler *) { +DB_VIS_C if (m_hide) return; m_t << "<informaltable frame='bottom'><tgroup cols='1'><colspec align='center'/><tbody><row><entry align='center'>\n"; m_t << "</entry></row></tbody></tgroup></informaltable>\n"; @@ -159,6 +199,7 @@ void DocbookDocVisitor::visit(DocHorRuler *) void DocbookDocVisitor::visit(DocStyleChange *s) { +DB_VIS_C if (m_hide) return; switch (s->style()) { @@ -196,6 +237,8 @@ void DocbookDocVisitor::visit(DocStyleChange *s) /* There is no equivalent Docbook tag for rendering Small text */ case DocStyleChange::Small: /* XSLT Stylesheets can be used */ break; /* HTML only */ + case DocStyleChange::Strike: break; + case DocStyleChange::Underline: break; case DocStyleChange::Div: /* HTML only */ break; case DocStyleChange::Span: /* HTML only */ break; } @@ -203,6 +246,7 @@ void DocbookDocVisitor::visit(DocStyleChange *s) void DocbookDocVisitor::visit(DocVerbatim *s) { +DB_VIS_C if (m_hide) return; SrcLangExt langExt = getLanguageFromFileName(m_langExt); switch(s->type()) @@ -215,9 +259,9 @@ void DocbookDocVisitor::visit(DocVerbatim *s) m_t << "</computeroutput></literallayout>"; break; case DocVerbatim::Verbatim: - m_t << "<literallayout>"; + m_t << "<literallayout><computeroutput>"; filter(s->text()); - m_t << "</literallayout>"; + m_t << "</computeroutput></literallayout>"; break; case DocVerbatim::HtmlOnly: break; @@ -230,7 +274,6 @@ void DocbookDocVisitor::visit(DocVerbatim *s) case DocVerbatim::XmlOnly: break; case DocVerbatim::DocbookOnly: - break; m_t << s->text(); break; case DocVerbatim::Dot: @@ -302,12 +345,14 @@ void DocbookDocVisitor::visit(DocVerbatim *s) void DocbookDocVisitor::visit(DocAnchor *anc) { +DB_VIS_C if (m_hide) return; - m_t << "<anchor id=\"" << anc->file() << "_1" << anc->anchor() << "\"/>"; + m_t << "<anchor xml:id=\"_" << stripPath(anc->file()) << "_1" << anc->anchor() << "\"/>"; } void DocbookDocVisitor::visit(DocInclude *inc) { +DB_VIS_C if (m_hide) return; SrcLangExt langExt = getLanguageFromFileName(inc->extension()); switch(inc->type()) @@ -343,9 +388,9 @@ void DocbookDocVisitor::visit(DocInclude *inc) case DocInclude::LatexInclude: break; case DocInclude::VerbInclude: - m_t << "<verbatim>"; + m_t << "<literallayout>"; filter(inc->text()); - m_t << "</verbatim>"; + m_t << "</literallayout>"; break; case DocInclude::Snippet: m_t << "<literallayout><computeroutput>"; @@ -391,6 +436,7 @@ void DocbookDocVisitor::visit(DocInclude *inc) void DocbookDocVisitor::visit(DocIncOperator *op) { +DB_VIS_C if (op->isFirst()) { if (!m_hide) @@ -427,27 +473,37 @@ void DocbookDocVisitor::visit(DocIncOperator *op) void DocbookDocVisitor::visit(DocFormula *f) { +DB_VIS_C if (m_hide) return; - m_t << "<equation><title>" << f->name() << "</title>"; - filter(f->text()); - m_t << "</equation>"; + + if (f->isInline()) m_t << "<inlinemediaobject>" << endl; + else m_t << " <mediaobject>" << endl; + m_t << " <imageobject>" << endl; + m_t << " <imagedata "; + m_t << "align=\"center\" valign=\"middle\" scalefit=\"0\" fileref=\"" << f->relPath() << f->name() << ".png\"/>" << endl; + m_t << " </imageobject>" << endl; + if (f->isInline()) m_t << "</inlinemediaobject>" << endl; + else m_t << " </mediaobject>" << endl; } void DocbookDocVisitor::visit(DocIndexEntry *ie) { +DB_VIS_C if (m_hide) return; - m_t << "<indexentry><primaryie>" << endl; + m_t << "<indexterm><primary>"; filter(ie->entry()); - m_t << "</primaryie><secondaryie></secondaryie></indexentry>" << endl; + m_t << "</primary></indexterm>" << endl; } void DocbookDocVisitor::visit(DocSimpleSectSep *) { - m_t << "<simplesect/>"; +DB_VIS_C + // m_t << "<simplesect/>"; } void DocbookDocVisitor::visit(DocCite *cite) { +DB_VIS_C if (m_hide) return; if (!cite->file().isEmpty()) startLink(cite->file(),cite->anchor()); filter(cite->text()); @@ -460,6 +516,7 @@ void DocbookDocVisitor::visit(DocCite *cite) void DocbookDocVisitor::visitPre(DocAutoList *l) { +DB_VIS_C if (m_hide) return; if (l->isEnumList()) { @@ -473,6 +530,7 @@ void DocbookDocVisitor::visitPre(DocAutoList *l) void DocbookDocVisitor::visitPost(DocAutoList *l) { +DB_VIS_C if (m_hide) return; if (l->isEnumList()) { @@ -486,18 +544,21 @@ void DocbookDocVisitor::visitPost(DocAutoList *l) void DocbookDocVisitor::visitPre(DocAutoListItem *) { +DB_VIS_C if (m_hide) return; m_t << "<listitem>"; } void DocbookDocVisitor::visitPost(DocAutoListItem *) { +DB_VIS_C if (m_hide) return; m_t << "</listitem>"; } void DocbookDocVisitor::visitPre(DocPara *) { +DB_VIS_C if (m_hide) return; m_t << endl; m_t << "<para>"; @@ -505,6 +566,7 @@ void DocbookDocVisitor::visitPre(DocPara *) void DocbookDocVisitor::visitPost(DocPara *) { +DB_VIS_C if (m_hide) return; m_t << "</para>"; m_t << endl; @@ -512,16 +574,19 @@ void DocbookDocVisitor::visitPost(DocPara *) void DocbookDocVisitor::visitPre(DocRoot *) { +DB_VIS_C //m_t << "<hr><h4><font color=\"red\">New parser:</font></h4>\n"; } void DocbookDocVisitor::visitPost(DocRoot *) { +DB_VIS_C //m_t << "<hr><h4><font color=\"red\">Old parser:</font></h4>\n"; } void DocbookDocVisitor::visitPre(DocSimpleSect *s) { +DB_VIS_C if (m_hide) return; switch(s->type()) { @@ -532,7 +597,7 @@ void DocbookDocVisitor::visitPre(DocSimpleSect *s) } else { - m_t << "<formalpara><title>" << convertToXML(theTranslator->trSeeAlso()) << ": </title>" << endl; + m_t << "<formalpara><title>" << convertToDocBook(theTranslator->trSeeAlso()) << ": </title>" << endl; } break; case DocSimpleSect::Return: @@ -542,7 +607,7 @@ void DocbookDocVisitor::visitPre(DocSimpleSect *s) } else { - m_t << "<formalpara><title>" << convertToXML(theTranslator->trReturns()) << ": </title>" << endl; + m_t << "<formalpara><title>" << convertToDocBook(theTranslator->trReturns()) << ": </title>" << endl; } break; case DocSimpleSect::Author: @@ -552,7 +617,7 @@ void DocbookDocVisitor::visitPre(DocSimpleSect *s) } else { - m_t << "<formalpara><title>" << convertToXML(theTranslator->trAuthor(TRUE, TRUE)) << ": </title>" << endl; + m_t << "<formalpara><title>" << convertToDocBook(theTranslator->trAuthor(TRUE, TRUE)) << ": </title>" << endl; } break; case DocSimpleSect::Authors: @@ -562,7 +627,7 @@ void DocbookDocVisitor::visitPre(DocSimpleSect *s) } else { - m_t << "<formalpara><title>" << convertToXML(theTranslator->trAuthor(TRUE, FALSE)) << ": </title>" << endl; + m_t << "<formalpara><title>" << convertToDocBook(theTranslator->trAuthor(TRUE, FALSE)) << ": </title>" << endl; } break; case DocSimpleSect::Version: @@ -572,7 +637,7 @@ void DocbookDocVisitor::visitPre(DocSimpleSect *s) } else { - m_t << "<formalpara><title>" << convertToXML(theTranslator->trVersion()) << ": </title>" << endl; + m_t << "<formalpara><title>" << convertToDocBook(theTranslator->trVersion()) << ": </title>" << endl; } break; case DocSimpleSect::Since: @@ -582,7 +647,7 @@ void DocbookDocVisitor::visitPre(DocSimpleSect *s) } else { - m_t << "<formalpara><title>" << convertToXML(theTranslator->trSince()) << ": </title>" << endl; + m_t << "<formalpara><title>" << convertToDocBook(theTranslator->trSince()) << ": </title>" << endl; } break; case DocSimpleSect::Date: @@ -592,27 +657,27 @@ void DocbookDocVisitor::visitPre(DocSimpleSect *s) } else { - m_t << "<formalpara><title>" << convertToXML(theTranslator->trDate()) << ": </title>" << endl; + m_t << "<formalpara><title>" << convertToDocBook(theTranslator->trDate()) << ": </title>" << endl; } break; case DocSimpleSect::Note: if (m_insidePre) { - m_t << "<formalpara><title>" << theTranslator->trNote() << ": </title>" << endl; + m_t << "<note><title>" << theTranslator->trNote() << ": </title>" << endl; } else { - m_t << "<formalpara><title>" << convertToXML(theTranslator->trNote()) << ": </title>" << endl; + m_t << "<note><title>" << convertToDocBook(theTranslator->trNote()) << ": </title>" << endl; } break; case DocSimpleSect::Warning: if (m_insidePre) { - m_t << "<formalpara><title>" << theTranslator->trWarning() << ": </title>" << endl; + m_t << "<warning><title>" << theTranslator->trWarning() << ": </title>" << endl; } else { - m_t << "<formalpara><title>" << convertToXML(theTranslator->trWarning()) << ": </title>" << endl; + m_t << "<warning><title>" << convertToDocBook(theTranslator->trWarning()) << ": </title>" << endl; } break; case DocSimpleSect::Pre: @@ -622,7 +687,7 @@ void DocbookDocVisitor::visitPre(DocSimpleSect *s) } else { - m_t << "<formalpara><title>" << convertToXML(theTranslator->trPrecondition()) << ": </title>" << endl; + m_t << "<formalpara><title>" << convertToDocBook(theTranslator->trPrecondition()) << ": </title>" << endl; } break; case DocSimpleSect::Post: @@ -632,7 +697,7 @@ void DocbookDocVisitor::visitPre(DocSimpleSect *s) } else { - m_t << "<formalpara><title>" << convertToXML(theTranslator->trPostcondition()) << ": </title>" << endl; + m_t << "<formalpara><title>" << convertToDocBook(theTranslator->trPostcondition()) << ": </title>" << endl; } break; case DocSimpleSect::Copyright: @@ -642,7 +707,7 @@ void DocbookDocVisitor::visitPre(DocSimpleSect *s) } else { - m_t << "<formalpara><title>" << convertToXML(theTranslator->trCopyright()) << ": </title>" << endl; + m_t << "<formalpara><title>" << convertToDocBook(theTranslator->trCopyright()) << ": </title>" << endl; } break; case DocSimpleSect::Invar: @@ -652,85 +717,121 @@ void DocbookDocVisitor::visitPre(DocSimpleSect *s) } else { - m_t << "<formalpara><title>" << convertToXML(theTranslator->trInvariant()) << ": </title>" << endl; + m_t << "<formalpara><title>" << convertToDocBook(theTranslator->trInvariant()) << ": </title>" << endl; } break; case DocSimpleSect::Remark: + // <remark> is miising the <title> possibility if (m_insidePre) { m_t << "<formalpara><title>" << theTranslator->trRemarks() << ": </title>" << endl; } else { - m_t << "<formalpara><title>" << convertToXML(theTranslator->trRemarks()) << ": </title>" << endl; + m_t << "<formalpara><title>" << convertToDocBook(theTranslator->trRemarks()) << ": </title>" << endl; } break; case DocSimpleSect::Attention: if (m_insidePre) { - m_t << "<formalpara><title>" << theTranslator->trAttention() << ": </title>" << endl; + m_t << "<caution><title>" << theTranslator->trAttention() << ": </title>" << endl; } else { - m_t << "<formalpara><title>" << convertToXML(theTranslator->trAttention()) << ": </title>" << endl; + m_t << "<caution><title>" << convertToDocBook(theTranslator->trAttention()) << ": </title>" << endl; } break; case DocSimpleSect::User: - m_t << "<formalpara><title></title>" << endl; + if (s->hasTitle()) + m_t << "<formalpara>" << endl; + else + m_t << "<para>" << endl; break; case DocSimpleSect::Rcs: - m_t << "<formalpara><title></title>" << endl; + case DocSimpleSect::Unknown: + m_t << "<para>" << endl; break; - case DocSimpleSect::Unknown: m_t << "<formalpara><title></title>" << endl; break; } } -void DocbookDocVisitor::visitPost(DocSimpleSect *) +void DocbookDocVisitor::visitPost(DocSimpleSect *s) { +DB_VIS_C if (m_hide) return; - m_t << "</formalpara>" << endl; + switch(s->type()) + { + case DocSimpleSect::Rcs: + case DocSimpleSect::Unknown: + m_t << "</para>" << endl; + break; + case DocSimpleSect::User: + if (s->hasTitle()) + m_t << "</formalpara>" << endl; + else + m_t << "</para>" << endl; + break; + case DocSimpleSect::Note: + m_t << "</note>" << endl; + break; + case DocSimpleSect::Attention: + m_t << "</caution>" << endl; + break; + case DocSimpleSect::Warning: + m_t << "</warning>" << endl; + break; + default: + m_t << "</formalpara>" << endl; + break; + } } -void DocbookDocVisitor::visitPre(DocTitle *) +void DocbookDocVisitor::visitPre(DocTitle *t) { +DB_VIS_C if (m_hide) return; - m_t << "<title>"; + if (t->hasTitle()) m_t << "<title>"; } -void DocbookDocVisitor::visitPost(DocTitle *) +void DocbookDocVisitor::visitPost(DocTitle *t) { +DB_VIS_C if (m_hide) return; - m_t << "</title>"; + if (t->hasTitle()) m_t << "</title>"; } void DocbookDocVisitor::visitPre(DocSimpleList *) { +DB_VIS_C if (m_hide) return; m_t << "<itemizedlist>\n"; } void DocbookDocVisitor::visitPost(DocSimpleList *) { +DB_VIS_C if (m_hide) return; m_t << "</itemizedlist>\n"; } void DocbookDocVisitor::visitPre(DocSimpleListItem *) { +DB_VIS_C if (m_hide) return; m_t << "<listitem>"; } void DocbookDocVisitor::visitPost(DocSimpleListItem *) { +DB_VIS_C if (m_hide) return; m_t << "</listitem>\n"; } void DocbookDocVisitor::visitPre(DocSection *s) { +DB_VIS_C if (m_hide) return; - m_t << "<section xml:id=\"" << s->file(); + m_t << "<section xml:id=\"_" << stripPath(s->file()); if (!s->anchor().isEmpty()) m_t << "_1" << s->anchor(); m_t << "\">" << endl; m_t << "<title>"; @@ -740,11 +841,13 @@ void DocbookDocVisitor::visitPre(DocSection *s) void DocbookDocVisitor::visitPost(DocSection *) { +DB_VIS_C m_t << "</section>\n"; } void DocbookDocVisitor::visitPre(DocHtmlList *s) { +DB_VIS_C if (m_hide) return; if (s->type()==DocHtmlList::Ordered) m_t << "<orderedlist>\n"; @@ -754,6 +857,7 @@ void DocbookDocVisitor::visitPre(DocHtmlList *s) void DocbookDocVisitor::visitPost(DocHtmlList *s) { +DB_VIS_C if (m_hide) return; if (s->type()==DocHtmlList::Ordered) m_t << "</orderedlist>\n"; @@ -763,143 +867,276 @@ void DocbookDocVisitor::visitPost(DocHtmlList *s) void DocbookDocVisitor::visitPre(DocHtmlListItem *) { +DB_VIS_C if (m_hide) return; m_t << "<listitem>\n"; } void DocbookDocVisitor::visitPost(DocHtmlListItem *) { +DB_VIS_C if (m_hide) return; m_t << "</listitem>\n"; } void DocbookDocVisitor::visitPre(DocHtmlDescList *) { +DB_VIS_C if (m_hide) return; m_t << "<variablelist>\n"; } void DocbookDocVisitor::visitPost(DocHtmlDescList *) { +DB_VIS_C if (m_hide) return; m_t << "</variablelist>\n"; } void DocbookDocVisitor::visitPre(DocHtmlDescTitle *) { +DB_VIS_C if (m_hide) return; m_t << "<varlistentry><term>"; } void DocbookDocVisitor::visitPost(DocHtmlDescTitle *) { +DB_VIS_C if (m_hide) return; m_t << "</term>\n"; } void DocbookDocVisitor::visitPre(DocHtmlDescData *) { +DB_VIS_C if (m_hide) return; m_t << "<listitem>"; } void DocbookDocVisitor::visitPost(DocHtmlDescData *) { +DB_VIS_C if (m_hide) return; m_t << "</listitem></varlistentry>\n"; } +static int colCnt = 0; +static bool bodySet = FALSE; // it is possible to have tables without a header void DocbookDocVisitor::visitPre(DocHtmlTable *t) { +DB_VIS_C + bodySet = FALSE; if (m_hide) return; - m_t << "<table frame=\"all\">" << endl; - m_t << " <title></title>" << endl; + m_t << "<informaltable frame=\"all\">" << endl; m_t << " <tgroup cols=\"" << t->numColumns() << "\" align=\"left\" colsep=\"1\" rowsep=\"1\">" << endl; - m_t << " <tbody>" << endl; + for (int i = 0; i <t->numColumns(); i++) + { + // do something with colwidth based of cell width specification (be aware of possible colspan in the header)? + m_t << " <colspec colname='c" << i+1 << "'/>\n"; + } } void DocbookDocVisitor::visitPost(DocHtmlTable *) { +DB_VIS_C if (m_hide) return; m_t << " </tbody>" << endl; m_t << " </tgroup>" << endl; - m_t << "</table>" << endl; + m_t << "</informaltable>" << endl; } -void DocbookDocVisitor::visitPre(DocHtmlRow *) +void DocbookDocVisitor::visitPre(DocHtmlRow *tr) { +DB_VIS_C + colCnt = 0; if (m_hide) return; - m_t << "<row>\n"; + + if (tr->isHeading()) m_t << "<thead>\n"; + else if (!bodySet) + { + bodySet = TRUE; + m_t << "<tbody>\n"; + } + + m_t << " <row "; + + HtmlAttribListIterator li(tr->attribs()); + HtmlAttrib *opt; + for (li.toFirst();(opt=li.current());++li) + { + if (opt->name=="class") + { + // just skip it + } + else if (opt->name=="style") + { + // just skip it + } + else if (opt->name=="height") + { + // just skip it + } + else if (opt->name=="filter") + { + // just skip it + } + else + { + m_t << " " << opt->name << "='" << opt->value << "'"; + } + } + m_t << ">\n"; } -void DocbookDocVisitor::visitPost(DocHtmlRow *) +void DocbookDocVisitor::visitPost(DocHtmlRow *tr) { +DB_VIS_C if (m_hide) return; m_t << "</row>\n"; + if (tr->isHeading()) + { + bodySet = TRUE; + m_t << "</thead><tbody>\n"; + } } -void DocbookDocVisitor::visitPre(DocHtmlCell *) +void DocbookDocVisitor::visitPre(DocHtmlCell *c) { +DB_VIS_C + colCnt++; if (m_hide) return; - m_t << "<entry>"; + m_t << "<entry"; + + HtmlAttribListIterator li(c->attribs()); + HtmlAttrib *opt; + for (li.toFirst();(opt=li.current());++li) + { + if (opt->name=="colspan") + { + m_t << " namest='c" << colCnt << "'"; + int cols = opt->value.toInt(); + colCnt += (cols - 1); + m_t << " nameend='c" << colCnt << "'"; + } + else if (opt->name=="rowspan") + { + int extraRows = opt->value.toInt() - 1; + m_t << " morerows='" << extraRows << "'"; + } + else if (opt->name=="class") + { + if (opt->value == "markdownTableBodyRight") + { + m_t << " align='right'"; + } + else if (opt->value == "markdownTableBodyLeftt") + { + m_t << " align='left'"; + } + else if (opt->value == "markdownTableBodyCenter") + { + m_t << " align='center'"; + } + else if (opt->value == "markdownTableHeadRight") + { + m_t << " align='right'"; + } + else if (opt->value == "markdownTableHeadLeftt") + { + m_t << " align='left'"; + } + else if (opt->value == "markdownTableHeadCenter") + { + m_t << " align='center'"; + } + } + else if (opt->name=="style") + { + // just skip it + } + else if (opt->name=="width") + { + // just skip it + } + else if (opt->name=="height") + { + // just skip it + } + else + { + m_t << " " << opt->name << "='" << opt->value << "'"; + } + } + m_t << ">"; } -void DocbookDocVisitor::visitPost(DocHtmlCell *) +void DocbookDocVisitor::visitPost(DocHtmlCell *c) { +DB_VIS_C if (m_hide) return; m_t << "</entry>"; } -void DocbookDocVisitor::visitPre(DocHtmlCaption *) +void DocbookDocVisitor::visitPre(DocHtmlCaption *c) { +DB_VIS_C if (m_hide) return; - m_t << "<caption>"; + m_t << "<caption>"; } void DocbookDocVisitor::visitPost(DocHtmlCaption *) { +DB_VIS_C if (m_hide) return; m_t << "</caption>\n"; } void DocbookDocVisitor::visitPre(DocInternal *) { +DB_VIS_C if (m_hide) return; // TODO: to be implemented } void DocbookDocVisitor::visitPost(DocInternal *) { +DB_VIS_C if (m_hide) return; // TODO: to be implemented } void DocbookDocVisitor::visitPre(DocHRef *href) { +DB_VIS_C if (m_hide) return; - m_t << "<link xlink:href=\"" << href->url() << "\">"; + m_t << "<link xlink:href=\"" << convertToDocBook(href->url()) << "\">"; } void DocbookDocVisitor::visitPost(DocHRef *) { +DB_VIS_C if (m_hide) return; m_t << "</link>"; } void DocbookDocVisitor::visitPre(DocHtmlHeader *) { +DB_VIS_C if (m_hide) return; m_t << "<formalpara><title>"; } void DocbookDocVisitor::visitPost(DocHtmlHeader *) { +DB_VIS_C if (m_hide) return; m_t << "</title></formalpara>\n"; } void DocbookDocVisitor::visitPre(DocImage *img) { +DB_VIS_C if (img->type()==DocImage::DocBook) { if (m_hide) return; @@ -910,7 +1147,7 @@ void DocbookDocVisitor::visitPre(DocImage *img) { baseName=baseName.right(baseName.length()-i-1); } - visitPreStart(m_t, img -> hasCaption(), baseName, img -> width(), img -> height()); + visitPreStart(m_t, img -> hasCaption(), img->relPath() + baseName, img -> width(), img -> height()); } else { @@ -921,6 +1158,7 @@ void DocbookDocVisitor::visitPre(DocImage *img) void DocbookDocVisitor::visitPost(DocImage *img) { +DB_VIS_C if (img->type()==DocImage::DocBook) { if (m_hide) return; @@ -961,96 +1199,118 @@ void DocbookDocVisitor::visitPost(DocImage *img) void DocbookDocVisitor::visitPre(DocDotFile *df) { +DB_VIS_C if (m_hide) return; startDotFile(df->file(),df->width(),df->height(),df->hasCaption()); } void DocbookDocVisitor::visitPost(DocDotFile *df) { +DB_VIS_C if (m_hide) return; endDotFile(df->hasCaption()); } void DocbookDocVisitor::visitPre(DocMscFile *df) { +DB_VIS_C if (m_hide) return; startMscFile(df->file(),df->width(),df->height(),df->hasCaption()); } void DocbookDocVisitor::visitPost(DocMscFile *df) { +DB_VIS_C if (m_hide) return; endMscFile(df->hasCaption()); } void DocbookDocVisitor::visitPre(DocDiaFile *df) { +DB_VIS_C if (m_hide) return; startDiaFile(df->file(),df->width(),df->height(),df->hasCaption()); } void DocbookDocVisitor::visitPost(DocDiaFile *df) { +DB_VIS_C if (m_hide) return; endDiaFile(df->hasCaption()); } void DocbookDocVisitor::visitPre(DocLink *lnk) { +DB_VIS_C if (m_hide) return; startLink(lnk->file(),lnk->anchor()); } void DocbookDocVisitor::visitPost(DocLink *) { +DB_VIS_C if (m_hide) return; endLink(); } void DocbookDocVisitor::visitPre(DocRef *ref) { +DB_VIS_C if (m_hide) return; - if (!ref->file().isEmpty()) startLink(ref->file(),ref->anchor()); + if (ref->isSubPage()) + { + startLink(0,ref->anchor()); + } + else + { + if (!ref->file().isEmpty()) startLink(ref->file(),ref->anchor()); + } + if (!ref->hasLinkText()) filter(ref->targetTitle()); } void DocbookDocVisitor::visitPost(DocRef *ref) { +DB_VIS_C if (m_hide) return; if (!ref->file().isEmpty()) endLink(); } void DocbookDocVisitor::visitPre(DocSecRefItem *ref) { +DB_VIS_C if (m_hide) return; - m_t << "<tocitem id=\"" << ref->file() << "_1" << ref->anchor() << "\">"; + //m_t << "<tocentry xml:idref=\"_" << stripPath(ref->file()) << "_1" << ref->anchor() << "\">"; + m_t << "<tocentry>"; } void DocbookDocVisitor::visitPost(DocSecRefItem *) { +DB_VIS_C if (m_hide) return; - m_t << "</tocitem>" << endl; + m_t << "</tocentry>" << endl; } void DocbookDocVisitor::visitPre(DocSecRefList *) { +DB_VIS_C if (m_hide) return; - m_t << "<toclist>" << endl; + m_t << "<toc>" << endl; } void DocbookDocVisitor::visitPost(DocSecRefList *) { +DB_VIS_C if (m_hide) return; - m_t << "</toclist>" << endl; + m_t << "</toc>" << endl; } void DocbookDocVisitor::visitPre(DocParamSect *s) { +DB_VIS_C if (m_hide) return; m_t << endl; m_t << " <formalpara>" << endl; - m_t << " <title/>" << endl; - m_t << " <table frame=\"all\">" << endl; - m_t << " <title>"; + m_t << " <title>" << endl; switch(s->type()) { case DocParamSect::Param: m_t << theTranslator->trParameters(); break; @@ -1060,29 +1320,96 @@ void DocbookDocVisitor::visitPre(DocParamSect *s) default: ASSERT(0); } - m_t << " </title>" << endl; - m_t << " <tgroup cols=\"2\" align=\"left\" colsep=\"1\" rowsep=\"1\">" << endl; - m_t << " <colspec colwidth=\"1*\"/>" << endl; - m_t << " <colspec colwidth=\"4*\"/>" << endl; + m_t << " </title>" << endl; + m_t << " <para>" << endl; + m_t << " <table frame=\"all\">" << endl; + int ncols = 2; + if (s->type() == DocParamSect::Param) + { + bool hasInOutSpecs = s->hasInOutSpecifier(); + bool hasTypeSpecs = s->hasTypeSpecifier(); + if (hasInOutSpecs && hasTypeSpecs) ncols += 2; + else if (hasInOutSpecs || hasTypeSpecs) ncols += 1; + } + m_t << " <tgroup cols=\"" << ncols << "\" align=\"left\" colsep=\"1\" rowsep=\"1\">" << endl; + for (int i = 1; i <= ncols; i++) + { + if (i == ncols) m_t << " <colspec colwidth=\"4*\"/>" << endl; + else m_t << " <colspec colwidth=\"1*\"/>" << endl; + } m_t << " <tbody>" << endl; } void DocbookDocVisitor::visitPost(DocParamSect *) { +DB_VIS_C if (m_hide) return; m_t << " </tbody>" << endl; m_t << " </tgroup>" << endl; m_t << " </table>" << endl; + m_t << " </para>" << endl; m_t << " </formalpara>" << endl; m_t << " "; } void DocbookDocVisitor::visitPre(DocParamList *pl) { +DB_VIS_C if (m_hide) return; + m_t << " <row>" << endl; + + DocParamSect::Type parentType = DocParamSect::Unknown; + DocParamSect *sect = 0; + if (pl->parent() && pl->parent()->kind()==DocNode::Kind_ParamSect) + { + parentType = ((DocParamSect*)pl->parent())->type(); + sect=(DocParamSect*)pl->parent(); + } + + if (sect && sect->hasInOutSpecifier()) + { + m_t << " <entry>"; + if (pl->direction()!=DocParamSect::Unspecified) + { + if (pl->direction()==DocParamSect::In) + { + m_t << "in"; + } + else if (pl->direction()==DocParamSect::Out) + { + m_t << "out"; + } + else if (pl->direction()==DocParamSect::InOut) + { + m_t << "in,out"; + } + } + m_t << " </entry>"; + } + + if (sect && sect->hasTypeSpecifier()) + { + QListIterator<DocNode> li(pl->paramTypes()); + DocNode *type; + bool first=TRUE; + m_t << " <entry>"; + for (li.toFirst();(type=li.current());++li) + { + if (!first) m_t << " | "; else first=FALSE; + if (type->kind()==DocNode::Kind_Word) + { + visit((DocWord*)type); + } + else if (type->kind()==DocNode::Kind_LinkedWord) + { + visit((DocLinkedWord*)type); + } + } + m_t << " </entry>"; + } + QListIterator<DocNode> li(pl->parameters()); DocNode *param; - m_t << " <row>" << endl; if (!li.toFirst()) { m_t << " <entry></entry>" << endl; @@ -1114,6 +1441,7 @@ void DocbookDocVisitor::visitPre(DocParamList *pl) void DocbookDocVisitor::visitPost(DocParamList *) { +DB_VIS_C if (m_hide) return; m_t << "</entry>" << endl; m_t << " </row>" << endl; @@ -1121,10 +1449,11 @@ void DocbookDocVisitor::visitPost(DocParamList *) void DocbookDocVisitor::visitPre(DocXRefItem *x) { +DB_VIS_C if (m_hide) return; if (x->title().isEmpty()) return; - m_t << "<para><link linkend=\""; - m_t << x->file() << "_1" << x->anchor(); + m_t << "<para><link linkend=\"_"; + m_t << stripPath(x->file()) << "_1" << x->anchor(); m_t << "\">"; filter(x->title()); m_t << "</link>"; @@ -1133,6 +1462,7 @@ void DocbookDocVisitor::visitPre(DocXRefItem *x) void DocbookDocVisitor::visitPost(DocXRefItem *x) { +DB_VIS_C if (m_hide) return; if (x->title().isEmpty()) return; m_t << "</para>"; @@ -1140,12 +1470,14 @@ void DocbookDocVisitor::visitPost(DocXRefItem *x) void DocbookDocVisitor::visitPre(DocInternalRef *ref) { +DB_VIS_C if (m_hide) return; startLink(ref->file(),ref->anchor()); } void DocbookDocVisitor::visitPost(DocInternalRef *) { +DB_VIS_C if (m_hide) return; endLink(); m_t << " "; @@ -1153,6 +1485,7 @@ void DocbookDocVisitor::visitPost(DocInternalRef *) void DocbookDocVisitor::visitPre(DocCopy *) { +DB_VIS_C if (m_hide) return; // TODO: to be implemented } @@ -1160,6 +1493,7 @@ void DocbookDocVisitor::visitPre(DocCopy *) void DocbookDocVisitor::visitPost(DocCopy *) { +DB_VIS_C if (m_hide) return; // TODO: to be implemented } @@ -1167,72 +1501,89 @@ void DocbookDocVisitor::visitPost(DocCopy *) void DocbookDocVisitor::visitPre(DocText *) { +DB_VIS_C // TODO: to be implemented } void DocbookDocVisitor::visitPost(DocText *) { +DB_VIS_C // TODO: to be implemented } void DocbookDocVisitor::visitPre(DocHtmlBlockQuote *) { +DB_VIS_C if (m_hide) return; m_t << "<blockquote>"; } void DocbookDocVisitor::visitPost(DocHtmlBlockQuote *) { +DB_VIS_C if (m_hide) return; m_t << "</blockquote>"; } void DocbookDocVisitor::visitPre(DocVhdlFlow *) { +DB_VIS_C // TODO: to be implemented } void DocbookDocVisitor::visitPost(DocVhdlFlow *) { +DB_VIS_C // TODO: to be implemented } void DocbookDocVisitor::visitPre(DocParBlock *) { +DB_VIS_C } void DocbookDocVisitor::visitPost(DocParBlock *) { +DB_VIS_C } void DocbookDocVisitor::filter(const char *str) { - m_t << convertToXML(str); +DB_VIS_C + m_t << convertToDocBook(str); } void DocbookDocVisitor::startLink(const QCString &file,const QCString &anchor) { - m_t << "<link linkend=\"" << file; - if (!anchor.isEmpty()) m_t << "_1" << anchor; +DB_VIS_C + m_t << "<link linkend=\"_" << stripPath(file); + if (!anchor.isEmpty()) + { + if (file) m_t << "_1"; + m_t << anchor; + } m_t << "\">"; } void DocbookDocVisitor::endLink() { +DB_VIS_C m_t << "</link>"; } void DocbookDocVisitor::pushEnabled() { +DB_VIS_C m_enabled.push(new bool(m_hide)); } void DocbookDocVisitor::popEnabled() { +DB_VIS_C bool *v=m_enabled.pop(); ASSERT(v!=0); m_hide = *v; @@ -1241,6 +1592,7 @@ void DocbookDocVisitor::popEnabled() void DocbookDocVisitor::writeMscFile(const QCString &baseName, DocVerbatim *s) { +DB_VIS_C QCString shortName = baseName; int i; if ((i=shortName.findRev('/'))!=-1) @@ -1249,13 +1601,14 @@ void DocbookDocVisitor::writeMscFile(const QCString &baseName, DocVerbatim *s) } QCString outDir = Config_getString(DOCBOOK_OUTPUT); writeMscGraphFromFile(baseName+".msc",outDir,shortName,MSC_BITMAP); - visitPreStart(m_t, s->hasCaption(), shortName, s->width(),s->height()); + visitPreStart(m_t, s->hasCaption(), s->relPath() + shortName + ".png", s->width(),s->height()); visitCaption(this, s->children()); visitPostEnd(m_t, s->hasCaption()); } void DocbookDocVisitor::writePlantUMLFile(const QCString &baseName, DocVerbatim *s) { +DB_VIS_C QCString shortName = baseName; int i; if ((i=shortName.findRev('/'))!=-1) @@ -1264,7 +1617,7 @@ void DocbookDocVisitor::writePlantUMLFile(const QCString &baseName, DocVerbatim } QCString outDir = Config_getString(DOCBOOK_OUTPUT); generatePlantUMLOutput(baseName,outDir,PUML_BITMAP); - visitPreStart(m_t, s->hasCaption(), shortName, s->width(),s->height()); + visitPreStart(m_t, s->hasCaption(), s->relPath() + shortName + ".png", s->width(),s->height()); visitCaption(this, s->children()); visitPostEnd(m_t, s->hasCaption()); } @@ -1275,6 +1628,7 @@ void DocbookDocVisitor::startMscFile(const QCString &fileName, bool hasCaption ) { +DB_VIS_C QCString baseName=fileName; int i; if ((i=baseName.findRev('/'))!=-1) @@ -1294,6 +1648,7 @@ void DocbookDocVisitor::startMscFile(const QCString &fileName, void DocbookDocVisitor::endMscFile(bool hasCaption) { +DB_VIS_C if (m_hide) return; visitPostEnd(m_t, hasCaption); m_t << "</para>" << endl; @@ -1301,6 +1656,7 @@ void DocbookDocVisitor::endMscFile(bool hasCaption) void DocbookDocVisitor::writeDiaFile(const QCString &baseName, DocVerbatim *s) { +DB_VIS_C QCString shortName = baseName; int i; if ((i=shortName.findRev('/'))!=-1) @@ -1320,6 +1676,7 @@ void DocbookDocVisitor::startDiaFile(const QCString &fileName, bool hasCaption ) { +DB_VIS_C QCString baseName=fileName; int i; if ((i=baseName.findRev('/'))!=-1) @@ -1339,6 +1696,7 @@ void DocbookDocVisitor::startDiaFile(const QCString &fileName, void DocbookDocVisitor::endDiaFile(bool hasCaption) { +DB_VIS_C if (m_hide) return; visitPostEnd(m_t, hasCaption); m_t << "</para>" << endl; @@ -1346,6 +1704,7 @@ void DocbookDocVisitor::endDiaFile(bool hasCaption) void DocbookDocVisitor::writeDotFile(const QCString &baseName, DocVerbatim *s) { +DB_VIS_C QCString shortName = baseName; int i; if ((i=shortName.findRev('/'))!=-1) @@ -1354,7 +1713,7 @@ void DocbookDocVisitor::writeDotFile(const QCString &baseName, DocVerbatim *s) } QCString outDir = Config_getString(DOCBOOK_OUTPUT); writeDotGraphFromFile(baseName+".dot",outDir,shortName,GOF_BITMAP); - visitPreStart(m_t, s->hasCaption(), baseName + ".dot", s->width(),s->height()); + visitPreStart(m_t, s->hasCaption(), s->relPath() + shortName + "." + getDotImageExtension(), s->width(),s->height()); visitCaption(this, s->children()); visitPostEnd(m_t, s->hasCaption()); } @@ -1365,6 +1724,7 @@ void DocbookDocVisitor::startDotFile(const QCString &fileName, bool hasCaption ) { +DB_VIS_C QCString baseName=fileName; int i; if ((i=baseName.findRev('/'))!=-1) @@ -1385,6 +1745,7 @@ void DocbookDocVisitor::startDotFile(const QCString &fileName, void DocbookDocVisitor::endDotFile(bool hasCaption) { +DB_VIS_C if (m_hide) return; m_t << endl; visitPostEnd(m_t, hasCaption); diff --git a/src/docbookvisitor.h b/src/docbookvisitor.h index 6c7976c..40f8a68 100644 --- a/src/docbookvisitor.h +++ b/src/docbookvisitor.h @@ -26,11 +26,15 @@ class FTextStream; class CodeOutputInterface; class QCString; +void visitPreStart(FTextStream &t, const bool hasCaption, QCString name, QCString width, QCString height); +void visitPostEnd(FTextStream &t, const bool hasCaption); + /*! @brief Concrete visitor implementation for Docbook output. */ class DocbookDocVisitor : public DocVisitor { public: DocbookDocVisitor(FTextStream &t,CodeOutputInterface &ci); + ~DocbookDocVisitor(); //-------------------------------------- // visitor functions for leaf nodes //-------------------------------------- diff --git a/src/docparser.cpp b/src/docparser.cpp index 2c51507..f1c969b 100644 --- a/src/docparser.cpp +++ b/src/docparser.cpp @@ -266,7 +266,7 @@ static void unescapeCRef(QCString &s) * copies the image to the output directory (which depends on the \a type * parameter). */ -static QCString findAndCopyImage(const char *fileName,DocImage::Type type) +static QCString findAndCopyImage(const char *fileName,DocImage::Type type, bool warn = true) { QCString result; bool ambig; @@ -334,7 +334,7 @@ static QCString findAndCopyImage(const char *fileName,DocImage::Type type) } else { - printf("Source & Destination are the same!\n"); + printf("Source and Destination are the same!\n"); } } else @@ -362,7 +362,7 @@ static QCString findAndCopyImage(const char *fileName,DocImage::Type type) return baseName; } } - else if (ambig) + else if (ambig && warn) { QCString text; text.sprintf("image file name %s is ambiguous.\n",qPrint(fileName)); @@ -373,7 +373,7 @@ static QCString findAndCopyImage(const char *fileName,DocImage::Type type) else { result=fileName; - if (result.left(5)!="http:" && result.left(6)!="https:") + if (result.left(5)!="http:" && result.left(6)!="https:" && warn) { warn_doc_error(g_fileName,doctokenizerYYlineno, "image file %s is not found in IMAGE_PATH: " @@ -1066,16 +1066,18 @@ const char *DocStyleChange::styleString() const { switch (m_style) { - case DocStyleChange::Bold: return "b"; - case DocStyleChange::Italic: return "em"; - case DocStyleChange::Code: return "code"; - case DocStyleChange::Center: return "center"; - case DocStyleChange::Small: return "small"; - case DocStyleChange::Subscript: return "subscript"; - case DocStyleChange::Superscript: return "superscript"; - case DocStyleChange::Preformatted: return "pre"; + case DocStyleChange::Bold: return "b"; + case DocStyleChange::Italic: return "em"; + case DocStyleChange::Code: return "code"; + case DocStyleChange::Center: return "center"; + case DocStyleChange::Small: return "small"; + case DocStyleChange::Subscript: return "subscript"; + case DocStyleChange::Superscript: return "superscript"; + case DocStyleChange::Preformatted: return "pre"; case DocStyleChange::Div: return "div"; case DocStyleChange::Span: return "span"; + case DocStyleChange::Strike: return "strike"; + case DocStyleChange::Underline: return "u"; } return "<invalid>"; } @@ -1564,6 +1566,9 @@ reparsetoken: doctokenizerYYsetStatePara(); } break; + case CMD_IMAGE: + ((DocPara *)parent) -> handleImage("image"); + break; default: return FALSE; } @@ -1588,6 +1593,26 @@ reparsetoken: handleStyleLeave(parent,children,DocStyleChange::Bold,tokenName); } break; + case HTML_STRIKE: + if (!g_token->endTag) + { + handleStyleEnter(parent,children,DocStyleChange::Strike,&g_token->attribs); + } + else + { + handleStyleLeave(parent,children,DocStyleChange::Strike,tokenName); + } + break; + case HTML_UNDERLINE: + if (!g_token->endTag) + { + handleStyleEnter(parent,children,DocStyleChange::Underline,&g_token->attribs); + } + else + { + handleStyleLeave(parent,children,DocStyleChange::Underline,tokenName); + } + break; case HTML_CODE: case XML_C: if (!g_token->endTag) @@ -1730,7 +1755,8 @@ static void handleImg(DocNode *parent,QList<DocNode> &children,const HtmlAttribL // and remove the src attribute bool result = attrList.remove(index); ASSERT(result); - DocImage *img = new DocImage(parent,attrList,opt->value,DocImage::Html,opt->value); + DocImage::Type t = DocImage::Html; + DocImage *img = new DocImage(parent,attrList,findAndCopyImage(opt->value,t,false),t,opt->value); children.append(img); found = TRUE; } @@ -5852,6 +5878,12 @@ int DocPara::handleHtmlStartTag(const QCString &tagName,const HtmlAttribList &ta case HTML_BOLD: handleStyleEnter(this,m_children,DocStyleChange::Bold,&g_token->attribs); break; + case HTML_STRIKE: + handleStyleEnter(this,m_children,DocStyleChange::Strike,&g_token->attribs); + break; + case HTML_UNDERLINE: + handleStyleEnter(this,m_children,DocStyleChange::Underline,&g_token->attribs); + break; case HTML_CODE: if (/*getLanguageFromFileName(g_fileName)==SrcLangExt_CSharp ||*/ g_xmlComment) // for C# source or inside a <summary> or <remark> section we @@ -6261,6 +6293,12 @@ int DocPara::handleHtmlEndTag(const QCString &tagName) case HTML_BOLD: handleStyleLeave(this,m_children,DocStyleChange::Bold,"b"); break; + case HTML_STRIKE: + handleStyleLeave(this,m_children,DocStyleChange::Strike,"strike"); + break; + case HTML_UNDERLINE: + handleStyleLeave(this,m_children,DocStyleChange::Underline,"u"); + break; case HTML_CODE: handleStyleLeave(this,m_children,DocStyleChange::Code,"code"); break; diff --git a/src/docparser.h b/src/docparser.h index 2e932be..2bc716a 100644 --- a/src/docparser.h +++ b/src/docparser.h @@ -367,7 +367,9 @@ class DocStyleChange : public DocNode Superscript = (1<<6), Preformatted = (1<<7), Span = (1<<8), - Div = (1<<9) + Div = (1<<9), + Strike = (1<<10), + Underline = (1<<11) }; DocStyleChange(DocNode *parent,uint position,Style s,bool enable, @@ -705,6 +707,7 @@ class DocTitle : public CompAccept<DocTitle> void parse(); void parseFromString(const QCString &title); Kind kind() const { return Kind_Title; } + bool hasTitle() const { return !m_children.isEmpty(); } private: }; @@ -1090,6 +1093,7 @@ class DocSimpleSect : public CompAccept<DocSimpleSect> int parseRcs(); int parseXml(); void appendLinkWord(const QCString &word); + bool hasTitle() const { return m_title->hasTitle(); } private: Type m_type; @@ -1368,7 +1372,7 @@ class DocHtmlTable : public CompAccept<DocHtmlTable> { public: DocHtmlTable(DocNode *parent,const HtmlAttribList &attribs) - : m_attribs(attribs) { m_caption=0; m_parent = parent; } + : m_attribs(attribs) { m_caption=0; m_numCols=0; m_parent = parent; } ~DocHtmlTable() { delete m_caption; } Kind kind() const { return Kind_HtmlTable; } uint numRows() const { return m_children.count(); } diff --git a/src/doctokenizer.l b/src/doctokenizer.l index dc56ca9..b4b0c18 100644 --- a/src/doctokenizer.l +++ b/src/doctokenizer.l @@ -389,14 +389,14 @@ LNKWORD3 ([0-9a-z_A-Z\-]+("/"|"\\"))*[0-9a-z_A-Z\-]+("."[0-9a-z_A-Z]+)+ CHARWORDQ [^ \t\n\r\\@<>()\[\]:;\?{}&%$#,."='] ESCWORD ("%"{ID}(("::"|"."){ID})*)|("%'") CHARWORDQ1 [^ \-+0-9\t\n\r\\@<>()\[\]:;\?{}&%$#,."='] -WORD1 {ESCWORD}|{CHARWORDQ1}+|"{"|"}"|"'\"'"|("\""[^"\n]*\n?[^"\n]*"\"") +WORD1 {ESCWORD}|{CHARWORDQ1}{CHARWORDQ}*|"{"|"}"|"'\"'"|("\""[^"\n]*\n?[^"\n]*"\"") WORD2 "."|","|"("|")"|"["|"]"|":"|";"|"\?"|"="|"'" WORD1NQ {ESCWORD}|{CHARWORDQ}+|"{"|"}" WORD2NQ "."|","|"("|")"|"["|"]"|":"|";"|"\?"|"="|"'" CAPTION [cC][aA][pP][tT][iI][oO][nN] HTMLTAG "<"(("/")?){ID}({WS}+{ATTRIB})*{WS}*(("/")?)">" -HTMLKEYL "strong"|"center"|"table"|"caption"|"small"|"code"|"dfn"|"var"|"img"|"pre"|"sub"|"sup"|"tr"|"td"|"th"|"ol"|"ul"|"li"|"tt"|"kbd"|"em"|"hr"|"dl"|"dt"|"dd"|"br"|"i"|"a"|"b"|"p" -HTMLKEYU "STRONG"|"CENTER"|"TABLE"|"CAPTION"|"SMALL"|"CODE"|"DFN"|"VAR"|"IMG"|"PRE"|"SUB"|"SUP"|"TR"|"TD"|"TH"|"OL"|"UL"|"LI"|"TT"|"KBD"|"EM"|"HR"|"DL"|"DT"|"DD"|"BR"|"I"|"A"|"B"|"P" +HTMLKEYL "strong"|"center"|"table"|"caption"|"small"|"code"|"dfn"|"var"|"img"|"pre"|"sub"|"sup"|"tr"|"td"|"th"|"ol"|"ul"|"li"|"tt"|"kbd"|"em"|"hr"|"dl"|"dt"|"dd"|"br"|"i"|"a"|"b"|"p"|"strike"|"u" +HTMLKEYU "STRONG"|"CENTER"|"TABLE"|"CAPTION"|"SMALL"|"CODE"|"DFN"|"VAR"|"IMG"|"PRE"|"SUB"|"SUP"|"TR"|"TD"|"TH"|"OL"|"UL"|"LI"|"TT"|"KBD"|"EM"|"HR"|"DL"|"DT"|"DD"|"BR"|"I"|"A"|"B"|"P"|"STRIKE"|"U" HTMLKEYW {HTMLKEYL}|{HTMLKEYU} REFWORD2_PRE ("#"|"::")?((({ID}{TEMPLPART}?)|{ANONNS})("."|"#"|"::"|"-"|"/"))*({ID}{TEMPLPART}?(":")?) REFWORD2 {REFWORD2_PRE}{FUNCARG2}? @@ -660,7 +660,8 @@ REFWORD_NOCV {LABELID}|{REFWORD2_NOCV}|{REFWORD3}|{REFWORD4_NOCV} g_token->text = tagName.mid(text_begin,text_end-text_begin); return TK_RCSTAG; } -<St_Para,St_HtmlOnly>"$("{ID}")" { /* environment variable */ +<St_Para,St_HtmlOnly,St_ManOnly,St_LatexOnly,St_RtfOnly,St_XmlOnly,St_DbOnly>"$("{ID}")" | /* environment variable */ +<St_Para,St_HtmlOnly,St_ManOnly,St_LatexOnly,St_RtfOnly,St_XmlOnly,St_DbOnly>"$("{ID}"("{ID}"))" { /* environment variable */ QCString name = &yytext[2]; name = name.left(name.length()-1); QCString value = portable_getenv(name); diff --git a/src/dot.cpp b/src/dot.cpp index 7b29569..f07a365 100644 --- a/src/dot.cpp +++ b/src/dot.cpp @@ -139,7 +139,7 @@ static const char svgZoomFooter[] = " <path fill=\"none\" stroke=\"white\" stroke-width=\"1.5\" d=\"M0,-3.0v7 M-2.5,-0.5L0,-3.0L2.5,-0.5\"/>\n" " </g>\n" " </g>\n" -// link to orginial SVG +// link to original SVG " <svg viewBox=\"0 0 15 15\" width=\"100%\" height=\"30px\" preserveAspectRatio=\"xMaxYMin meet\">\n" " <g id=\"arrow_out\" transform=\"scale(0.3 0.3)\">\n" " <a xlink:href=\"$orgname\" target=\"_base\">\n" @@ -1383,6 +1383,11 @@ bool DotManager::run() setDotFontPath(Config_getString(RTF_OUTPUT)); setPath=TRUE; } + else if (Config_getBool(GENERATE_DOCBOOK)) + { + setDotFontPath(Config_getString(DOCBOOK_OUTPUT)); + setPath=TRUE; + } portable_sysTimerStart(); // fill work queue with dot operations DotRunner *dr; @@ -3242,29 +3247,15 @@ QCString DotClassGraph::writeGraph(FTextStream &out, if (graphFormat==GOF_BITMAP && textFormat==EOF_DocBook) { out << "<para>" << endl; - out << " <figure>" << endl; - out << " <title>"; - switch (m_graphType) - { - case DotNode::Collaboration: - out << "Collaboration graph"; - break; - case DotNode::Inheritance: - out << "Inheritance graph"; - break; - default: - ASSERT(0); - break; - } - out << "</title>" << endl; + out << " <informalfigure>" << endl; out << " <mediaobject>" << endl; out << " <imageobject>" << endl; out << " <imagedata"; - out << " width=\"50%\" align=\"center\" valign=\"middle\" scalefit=\"1\" fileref=\"" << relPath << baseName << "." << imgExt << "\">"; + out << " width=\"50%\" align=\"center\" valign=\"middle\" scalefit=\"0\" fileref=\"" << relPath << baseName << "." << imgExt << "\">"; out << "</imagedata>" << endl; out << " </imageobject>" << endl; out << " </mediaobject>" << endl; - out << " </figure>" << endl; + out << " </informalfigure>" << endl; out << "</para>" << endl; } else if (graphFormat==GOF_BITMAP && generateImageMap) // produce HTML to include the image @@ -3601,17 +3592,15 @@ QCString DotInclDepGraph::writeGraph(FTextStream &out, if (graphFormat==GOF_BITMAP && textFormat==EOF_DocBook) { out << "<para>" << endl; - out << " <figure>" << endl; - out << " <title>Dependency diagram"; - out << "</title>" << endl; + out << " <informalfigure>" << endl; out << " <mediaobject>" << endl; out << " <imageobject>" << endl; out << " <imagedata"; - out << " width=\"50%\" align=\"center\" valign=\"middle\" scalefit=\"1\" fileref=\"" << relPath << baseName << "." << imgExt << "\">"; + out << " width=\"50%\" align=\"center\" valign=\"middle\" scalefit=\"0\" fileref=\"" << relPath << baseName << "." << imgExt << "\">"; out << "</imagedata>" << endl; out << " </imageobject>" << endl; out << " </mediaobject>" << endl; - out << " </figure>" << endl; + out << " </informalfigure>" << endl; out << "</para>" << endl; } else if (graphFormat==GOF_BITMAP && generateImageMap) @@ -3922,17 +3911,15 @@ QCString DotCallGraph::writeGraph(FTextStream &out, GraphOutputFormat graphForma if (graphFormat==GOF_BITMAP && textFormat==EOF_DocBook) { out << "<para>" << endl; - out << " <figure>" << endl; - out << " <title>Call diagram"; - out << "</title>" << endl; + out << " <informalfigure>" << endl; out << " <mediaobject>" << endl; out << " <imageobject>" << endl; out << " <imagedata"; - out << " width=\"50%\" align=\"center\" valign=\"middle\" scalefit=\"1\" fileref=\"" << relPath << baseName << "." << imgExt << "\">"; + out << " width=\"50%\" align=\"center\" valign=\"middle\" scalefit=\"0\" fileref=\"" << relPath << baseName << "." << imgExt << "\">"; out << "</imagedata>" << endl; out << " </imageobject>" << endl; out << " </mediaobject>" << endl; - out << " </figure>" << endl; + out << " </informalfigure>" << endl; out << "</para>" << endl; } else if (graphFormat==GOF_BITMAP && generateImageMap) @@ -4087,17 +4074,15 @@ QCString DotDirDeps::writeGraph(FTextStream &out, if (graphFormat==GOF_BITMAP && textFormat==EOF_DocBook) { out << "<para>" << endl; - out << " <figure>" << endl; - out << " <title>Directory Dependency diagram"; - out << "</title>" << endl; + out << " <informalfigure>" << endl; out << " <mediaobject>" << endl; out << " <imageobject>" << endl; out << " <imagedata"; - out << " width=\"50%\" align=\"center\" valign=\"middle\" scalefit=\"1\" fileref=\"" << relPath << baseName << "." << imgExt << "\">"; + out << " width=\"50%\" align=\"center\" valign=\"middle\" scalefit=\"0\" fileref=\"" << relPath << baseName << "." << imgExt << "\">"; out << "</imagedata>" << endl; out << " </imageobject>" << endl; out << " </mediaobject>" << endl; - out << " </figure>" << endl; + out << " </informalfigure>" << endl; out << "</para>" << endl; } else if (graphFormat==GOF_BITMAP && generateImageMap) @@ -4650,17 +4635,15 @@ QCString DotGroupCollaboration::writeGraph( FTextStream &t, if (graphFormat==GOF_BITMAP && textFormat==EOF_DocBook) { t << "<para>" << endl; - t << " <figure>" << endl; - t << " <title>Group Collaboration diagram"; - t << "</title>" << endl; + t << " <informalfigure>" << endl; t << " <mediaobject>" << endl; t << " <imageobject>" << endl; t << " <imagedata"; - t << " width=\"50%\" align=\"center\" valign=\"middle\" scalefit=\"1\" fileref=\"" << relPath << baseName << "." << imgExt << "\">"; + t << " width=\"50%\" align=\"center\" valign=\"middle\" scalefit=\"0\" fileref=\"" << relPath << baseName << "." << imgExt << "\">"; t << "</imagedata>" << endl; t << " </imageobject>" << endl; t << " </mediaobject>" << endl; - t << " </figure>" << endl; + t << " </informalfigure>" << endl; t << "</para>" << endl; } else if (graphFormat==GOF_BITMAP && writeImageMap) diff --git a/src/doxygen.cpp b/src/doxygen.cpp index bf93a9b..b706d1d 100644 --- a/src/doxygen.cpp +++ b/src/doxygen.cpp @@ -167,6 +167,7 @@ bool Doxygen::suppressDocWarnings = FALSE; Store *Doxygen::symbolStorage; QCString Doxygen::objDBFileName; QCString Doxygen::entryDBFileName; +QCString Doxygen::filterDBFileName; bool Doxygen::gatherDefines = TRUE; IndexList *Doxygen::indexList; int Doxygen::subpageNestingLevel = 0; @@ -7696,7 +7697,7 @@ static void computeMemberRelations() // bmcd->name().data(),bmd->name().data(),bmd // ); if (md!=bmd && bmcd && mcd && bmcd!=mcd && - (bmd->virtualness()!=Normal || + (bmd->virtualness()!=Normal || bmd->getLanguage()==SrcLangExt_Python || bmcd->compoundType()==ClassDef::Interface || bmcd->compoundType()==ClassDef::Protocol ) && @@ -9151,7 +9152,24 @@ static void generateConfigFile(const char *configFile,bool shortList, exit(1); } } - +static void compareDoxyfile() +{ + QFile f; + char configFile[2]; + configFile[0] = '-'; + configFile[1] = '\0'; + bool fileOpened=openOutputFile(configFile,f); + if (fileOpened) + { + FTextStream t(&f); + Config::compareDoxyfile(t); + } + else + { + err("Cannot open file %s for writing\n",configFile); + exit(1); + } +} //---------------------------------------------------------------------------- // read and parse a tag file @@ -9633,7 +9651,7 @@ int readDir(QFileInfo *fi, { fn = new FileName(cfi->absFilePath().utf8(),name); fn->append(fd); - if (fnList) fnList->inSort(fn); + if (fnList) fnList->append(fn); fnDict->insert(name,fn); } } @@ -9732,7 +9750,7 @@ int readFileOrDirectory(const char *s, { fn = new FileName(filePath,name); fn->append(fd); - if (fnList) fnList->inSort(fn); + if (fnList) fnList->append(fn); fnDict->insert(name,fn); } } @@ -9871,7 +9889,7 @@ static void escapeAliases() while ((in=value.find("^^",p))!=-1) { newValue+=value.mid(p,in-p); - newValue+="\n"; + newValue+="\\_linebr"; p=in+2; } newValue+=value.mid(p,value.length()-p); @@ -10009,6 +10027,8 @@ static void usage(const char *name) msg(" LaTeX: %s -w latex headerFile footerFile styleSheetFile [configFile]\n\n",name); msg("6) Use doxygen to generate a rtf extensions file\n"); msg(" RTF: %s -e rtf extensionsFile\n\n",name); + msg("7) Use doxygen to compare the used configuration file with the template configuration file\n"); + msg(" %s -x [configFile]\n\n",name); msg("If -s is specified the comments of the configuration items in the config file will be omitted.\n"); msg("If configName is omitted `Doxyfile' will be used as a default.\n\n"); msg("-v print version string\n"); @@ -10211,6 +10231,7 @@ void readConfiguration(int argc, char **argv) const char *formatName; bool genConfig=FALSE; bool shortList=FALSE; + bool diffList=FALSE; bool updateConfig=FALSE; int retVal; while (optind<argc && argv[optind][0]=='-' && @@ -10248,6 +10269,9 @@ void readConfiguration(int argc, char **argv) exit(1); } break; + case 'x': + diffList=TRUE; + break; case 's': shortList=TRUE; break; @@ -10498,6 +10522,7 @@ void readConfiguration(int argc, char **argv) exit(1); } } + if (genConfig && g_useOutputTemplate) { generateTemplateFiles("templates"); @@ -10519,6 +10544,13 @@ void readConfiguration(int argc, char **argv) exit(1); } + if (diffList) + { + compareDoxyfile(); + cleanUpDoxygen(); + exit(0); + } + if (updateConfig) { generateConfigFile(configName,shortList,TRUE); @@ -10648,6 +10680,10 @@ static void stopDoxygen(int) { thisDir.remove(Doxygen::objDBFileName); } + if (!Doxygen::filterDBFileName.isEmpty()) + { + thisDir.remove(Doxygen::filterDBFileName); + } killpg(0,SIGINT); exit(1); } @@ -10748,6 +10784,10 @@ static void exitDoxygen() { thisDir.remove(Doxygen::objDBFileName); } + if (!Doxygen::filterDBFileName.isEmpty()) + { + thisDir.remove(Doxygen::filterDBFileName); + } } } @@ -10923,6 +10963,7 @@ void searchInputFiles() } s=inputList.next(); } + Doxygen::inputNameList->sort(); delete killDict; g_s.end(); } @@ -10987,6 +11028,8 @@ void parseInput() Doxygen::objDBFileName.prepend(outputDirectory+"/"); Doxygen::entryDBFileName.sprintf("doxygen_entrydb_%d.tmp",pid); Doxygen::entryDBFileName.prepend(outputDirectory+"/"); + Doxygen::filterDBFileName.sprintf("doxygen_filterdb_%d.tmp",pid); + Doxygen::filterDBFileName.prepend(outputDirectory+"/"); if (Doxygen::symbolStorage->open(Doxygen::objDBFileName)==-1) { @@ -11100,14 +11143,20 @@ void parseInput() // Notice: the order of the function calls below is very important! - if (Config_getBool(GENERATE_HTML)) + if (Config_getBool(GENERATE_HTML) && !Config_getBool(USE_MATHJAX)) { readFormulaRepository(Config_getString(HTML_OUTPUT)); } if (Config_getBool(GENERATE_RTF)) { // in case GENERRATE_HTML is set we just have to compare, both repositories should be identical - readFormulaRepository(Config_getString(RTF_OUTPUT),Config_getBool(GENERATE_HTML)); + readFormulaRepository(Config_getString(RTF_OUTPUT),Config_getBool(GENERATE_HTML) && !Config_getBool(USE_MATHJAX)); + } + if (Config_getBool(GENERATE_DOCBOOK)) + { + // in case GENERRATE_HTML is set we just have to compare, both repositories should be identical + readFormulaRepository(Config_getString(DOCBOOK_OUTPUT), + (Config_getBool(GENERATE_HTML) && !Config_getBool(USE_MATHJAX)) || Config_getBool(GENERATE_RTF)); } /************************************************************************** @@ -11456,6 +11505,7 @@ void generateOutput() bool generateLatex = Config_getBool(GENERATE_LATEX); bool generateMan = Config_getBool(GENERATE_MAN); bool generateRtf = Config_getBool(GENERATE_RTF); + bool generateDocbook = Config_getBool(GENERATE_DOCBOOK); g_outputList = new OutputList(TRUE); @@ -11483,6 +11533,13 @@ void generateOutput() g_outputList->add(new LatexGenerator); LatexGenerator::init(); } +#if 1 + if (generateDocbook) + { + g_outputList->add(new DocbookGenerator); + DocbookGenerator::init(); + } +#endif if (generateMan) { g_outputList->add(new ManGenerator); @@ -11509,6 +11566,7 @@ void generateOutput() if (generateHtml) writeDoxFont(Config_getString(HTML_OUTPUT)); if (generateLatex) writeDoxFont(Config_getString(LATEX_OUTPUT)); + if (generateDocbook) writeDoxFont(Config_getString(DOCBOOK_OUTPUT)); if (generateRtf) writeDoxFont(Config_getString(RTF_OUTPUT)); g_s.begin("Generating style sheet...\n"); @@ -11602,6 +11660,13 @@ void generateOutput() g_s.end(); } + if (Doxygen::formulaList->count()>0 && generateDocbook) + { + g_s.begin("Generating bitmaps for formulas in Docbook...\n"); + Doxygen::formulaList->generateBitmaps(Config_getString(DOCBOOK_OUTPUT)); + g_s.end(); + } + if (Config_getBool(SORT_GROUP_NAMES)) { Doxygen::groupSDict->sort(); @@ -11634,6 +11699,8 @@ void generateOutput() removeDoxFont(Config_getString(RTF_OUTPUT)); if (generateLatex) removeDoxFont(Config_getString(LATEX_OUTPUT)); + if (generateDocbook) + removeDoxFont(Config_getString(DOCBOOK_OUTPUT)); } if (Config_getBool(GENERATE_XML)) @@ -11651,12 +11718,14 @@ void generateOutput() g_s.end(); } - if (Config_getBool(GENERATE_DOCBOOK)) +#if 0 + if (generateDocbook) { g_s.begin("Generating Docbook output...\n"); - generateDocbook(); + generateDocbook_v1(); g_s.end(); } +#endif if (Config_getBool(GENERATE_AUTOGEN_DEF)) { @@ -11728,6 +11797,10 @@ void generateOutput() copyLogo(Config_getString(LATEX_OUTPUT)); copyExtraFiles(Config_getList(LATEX_EXTRA_FILES),"LATEX_EXTRA_FILES",Config_getString(LATEX_OUTPUT)); } + if (generateDocbook) + { + copyLogo(Config_getString(DOCBOOK_OUTPUT)); + } if (generateRtf) { copyLogo(Config_getString(RTF_OUTPUT)); @@ -11806,6 +11879,7 @@ void generateOutput() Doxygen::symbolStorage->close(); QDir thisDir; thisDir.remove(Doxygen::objDBFileName); + thisDir.remove(Doxygen::filterDBFileName); Config::deinit(); QTextCodec::deleteAllCodecs(); delete Doxygen::symbolMap; diff --git a/src/doxygen.h b/src/doxygen.h index 7bd05a4..4ff8a56 100644 --- a/src/doxygen.h +++ b/src/doxygen.h @@ -140,6 +140,7 @@ class Doxygen static Store *symbolStorage; static QCString objDBFileName; static QCString entryDBFileName; + static QCString filterDBFileName; static CiteDict *citeDict; static bool gatherDefines; static bool userComments; diff --git a/src/filedef.cpp b/src/filedef.cpp index e2df9be..d9eaa4b 100644 --- a/src/filedef.cpp +++ b/src/filedef.cpp @@ -348,6 +348,10 @@ void FileDef::writeDetailedDescription(OutputList &ol,const QCString &title) { ol.disable(OutputGenerator::Latex); } + if (ol.isEnabled(OutputGenerator::Docbook) && !Config_getBool(DOCBOOK_PROGRAMLISTING)) + { + ol.disable(OutputGenerator::Docbook); + } if (ol.isEnabled(OutputGenerator::RTF) && !Config_getBool(RTF_SOURCE_CODE)) { ol.disable(OutputGenerator::RTF); @@ -937,6 +941,7 @@ void FileDef::writeSource(OutputList &ol,bool sameTu,QStrList &filesInSameTu) static bool generateTreeView = Config_getBool(GENERATE_TREEVIEW); static bool filterSourceFiles = Config_getBool(FILTER_SOURCE_FILES); static bool latexSourceCode = Config_getBool(LATEX_SOURCE_CODE); + static bool docbookSourceCode = Config_getBool(DOCBOOK_PROGRAMLISTING); static bool rtfSourceCode = Config_getBool(RTF_SOURCE_CODE); DevNullCodeDocInterface devNullIntf; QCString title = m_docname; @@ -947,6 +952,7 @@ void FileDef::writeSource(OutputList &ol,bool sameTu,QStrList &filesInSameTu) QCString pageTitle = theTranslator->trSourceFile(title); ol.disable(OutputGenerator::Man); if (!latexSourceCode) ol.disable(OutputGenerator::Latex); + if (!docbookSourceCode) ol.disable(OutputGenerator::Docbook); if (!rtfSourceCode) ol.disable(OutputGenerator::RTF); bool isDocFile = isDocumentationFile(); @@ -978,13 +984,14 @@ void FileDef::writeSource(OutputList &ol,bool sameTu,QStrList &filesInSameTu) if (isLinkable()) { + ol.pushGeneratorState(); if (latexSourceCode) ol.disable(OutputGenerator::Latex); if (rtfSourceCode) ol.disable(OutputGenerator::RTF); + if (docbookSourceCode) ol.disable(OutputGenerator::Docbook); ol.startTextLink(getOutputFileBase(),0); ol.parseText(theTranslator->trGotoDocumentation()); ol.endTextLink(); - if (latexSourceCode) ol.enable(OutputGenerator::Latex); - if (rtfSourceCode) ol.enable(OutputGenerator::RTF); + ol.popGeneratorState(); } (void)sameTu; diff --git a/src/fortrancode.l b/src/fortrancode.l index 3014dc3..0e610fd 100644 --- a/src/fortrancode.l +++ b/src/fortrancode.l @@ -107,8 +107,9 @@ class Scope public: QCStringList useNames; //!< contains names of used modules QDict<void> localVars; //!< contains names of local variables + QDict<void> externalVars; //!< contains names of external entities - Scope() : localVars(7, FALSE /*caseSensitive*/) {} + Scope() : localVars(7, FALSE /*caseSensitive*/), externalVars(7, FALSE /*caseSensitive*/) {} }; /*===================================================================*/ @@ -122,6 +123,7 @@ static QCString currentClass=0; //!< name of the current enclosing static UseSDict *useMembers= new UseSDict; //!< info about used modules static UseEntry *useEntry = 0; //!< current use statement info static QList<Scope> scopeStack; +static bool g_isExternal = false; // static QCStringList *currentUseNames= new QCStringList; //! contains names of used modules of current program unit static QCString str=""; //!> contents of fortran string @@ -434,7 +436,7 @@ static bool getFortranDefs(const QCString &memberName, const QCString &moduleNam Scope *scope; for (it.toLast();(scope=it.current());--it) { - if (scope->localVars.find(memberName)) + if (scope->localVars.find(memberName) && (!scope->externalVars.find(memberName))) return FALSE; } @@ -648,7 +650,10 @@ static void addUse(const QCString &moduleName) static void addLocalVar(const QCString &varName) { if (!scopeStack.isEmpty()) + { scopeStack.getLast()->localVars.insert(varName, (void*)1); + if (g_isExternal) scopeStack.getLast()->externalVars.insert(varName, (void*)1); + } } //---------------------------------------------------------------------------- @@ -969,11 +974,18 @@ LANGUAGE_BIND_SPEC BIND{BS}"("{BS}C{BS}(,{BS}NAME{BS}"="{BS}"\""(.*)"\""{BS})?") endFontClass(); } <Start>{ATTR_SPEC} { + if (QCString(yytext) == "external") + { + yy_push_state(YY_START); + BEGIN(Declaration); + g_isExternal = true; + } startFontClass("keywordtype"); g_code->codify(yytext); endFontClass(); } <Declaration>({TYPE_SPEC}|{ATTR_SPEC})/[,:( ] { //| variable declaration + if (QCString(yytext) == "external") g_isExternal = true; startFontClass("keywordtype"); g_code->codify(yytext); endFontClass(); @@ -1046,6 +1058,7 @@ LANGUAGE_BIND_SPEC BIND{BS}"("{BS}C{BS}(,{BS}NAME{BS}"="{BS}"\""(.*)"\""{BS})?") g_contLineNr++; if (!(g_hasContLine && g_hasContLine[g_contLineNr - 1])) { + g_isExternal = false; yy_pop_state(); } YY_FTN_RESET diff --git a/src/fortranscanner.l b/src/fortranscanner.l index 884c86e..2bd6788 100644 --- a/src/fortranscanner.l +++ b/src/fortranscanner.l @@ -1638,7 +1638,7 @@ const char* prepassFixedForm(const char* contents, int *hasContLine) } // fallthrough default: - if ((column < 6) && ((c - '0') >= 0) && ((c - '0') <= 9)) { // remove numbers, i.e. labels from first 5 positions. + if (!commented && (column < 6) && ((c - '0') >= 0) && ((c - '0') <= 9)) { // remove numbers, i.e. labels from first 5 positions. newContents[j]=' '; } else if(column==6 && emptyLabel) { // continuation diff --git a/src/ftvhelp.cpp b/src/ftvhelp.cpp index cee39f2..8c46fd5 100644 --- a/src/ftvhelp.cpp +++ b/src/ftvhelp.cpp @@ -171,11 +171,10 @@ void FTVHelp::decContentsDepth() /*! Add a list item to the contents file. * \param isDir TRUE if the item is a directory, FALSE if it is a text - * \param name The name of the item. + * \param name the name of the item. * \param ref the URL of to the item. * \param file the file containing the definition of the item * \param anchor the anchor within the file. - * \param name the name of the item. * \param separateIndex put the entries in a separate index file * \param addToNavIndex add this entry to the quick navigation index * \param def Definition corresponding to this entry diff --git a/src/htmldocvisitor.cpp b/src/htmldocvisitor.cpp index 6a9c142..6e0c62d 100644 --- a/src/htmldocvisitor.cpp +++ b/src/htmldocvisitor.cpp @@ -38,6 +38,31 @@ static const int NUM_HTML_LIST_TYPES = 4; static const char types[][NUM_HTML_LIST_TYPES] = {"1", "a", "i", "A"}; +enum contexts_t +{ + NONE, // 0 + STARTLI, // 1 + STARTDD, // 2 + ENDLI, // 3 + ENDDD, // 4 + STARTTD, // 5 + ENDTD, // 6 + INTERLI, // 7 + INTERDD, // 8 + INTERTD // 9 +}; +static const char *contexts[10] = +{ "", // 0 + "startli", // 1 + "startdd", // 2 + "endli", // 3 + "enddd", // 4 + "starttd", // 5 + "endtd", // 6 + "interli", // 7 + "interdd", // 8 + "intertd" // 9 +}; static QCString convertIndexWordToAnchor(const QString &word) { @@ -271,6 +296,12 @@ void HtmlDocVisitor::visit(DocStyleChange *s) case DocStyleChange::Bold: if (s->enable()) m_t << "<b" << htmlAttribsToString(s->attribs()) << ">"; else m_t << "</b>"; break; + case DocStyleChange::Strike: + if (s->enable()) m_t << "<strike" << htmlAttribsToString(s->attribs()) << ">"; else m_t << "</strike>"; + break; + case DocStyleChange::Underline: + if (s->enable()) m_t << "<u" << htmlAttribsToString(s->attribs()) << ">"; else m_t << "</u>"; + break; case DocStyleChange::Italic: if (s->enable()) m_t << "<em" << htmlAttribsToString(s->attribs()) << ">"; else m_t << "</em>"; break; @@ -887,24 +918,24 @@ static int getParagraphContext(DocPara *p,bool &isFirst,bool &isLast) } isFirst=isFirstChildNode((DocParBlock*)p->parent(),p); isLast =isLastChildNode ((DocParBlock*)p->parent(),p); - t=0; + t=NONE; if (isFirst) { if (kind==DocNode::Kind_HtmlListItem || kind==DocNode::Kind_SecRefItem) { - t=1; + t=STARTLI; } else if (kind==DocNode::Kind_HtmlDescData || kind==DocNode::Kind_XRefItem || kind==DocNode::Kind_SimpleSect) { - t=2; + t=STARTDD; } else if (kind==DocNode::Kind_HtmlCell || kind==DocNode::Kind_ParamList) { - t=5; + t=STARTTD; } } if (isLast) @@ -912,18 +943,37 @@ static int getParagraphContext(DocPara *p,bool &isFirst,bool &isLast) if (kind==DocNode::Kind_HtmlListItem || kind==DocNode::Kind_SecRefItem) { - t=3; + t=ENDLI; + } + else if (kind==DocNode::Kind_HtmlDescData || + kind==DocNode::Kind_XRefItem || + kind==DocNode::Kind_SimpleSect) + { + t=ENDDD; + } + else if (kind==DocNode::Kind_HtmlCell || + kind==DocNode::Kind_ParamList) + { + t=ENDTD; + } + } + if (!isFirst && !isLast) + { + if (kind==DocNode::Kind_HtmlListItem || + kind==DocNode::Kind_SecRefItem) + { + t=INTERLI; } else if (kind==DocNode::Kind_HtmlDescData || kind==DocNode::Kind_XRefItem || kind==DocNode::Kind_SimpleSect) { - t=4; + t=INTERDD; } else if (kind==DocNode::Kind_HtmlCell || kind==DocNode::Kind_ParamList) { - t=6; + t=INTERTD; } } break; @@ -931,47 +981,51 @@ static int getParagraphContext(DocPara *p,bool &isFirst,bool &isLast) case DocNode::Kind_AutoListItem: isFirst=isFirstChildNode((DocAutoListItem*)p->parent(),p); isLast =isLastChildNode ((DocAutoListItem*)p->parent(),p); - t=1; // not used + t=STARTLI; // not used break; case DocNode::Kind_SimpleListItem: isFirst=TRUE; isLast =TRUE; - t=1; // not used + t=STARTLI; // not used break; case DocNode::Kind_ParamList: isFirst=TRUE; isLast =TRUE; - t=1; // not used + t=STARTLI; // not used break; case DocNode::Kind_HtmlListItem: isFirst=isFirstChildNode((DocHtmlListItem*)p->parent(),p); isLast =isLastChildNode ((DocHtmlListItem*)p->parent(),p); - if (isFirst) t=1; - if (isLast) t=3; + if (isFirst) t=STARTLI; + if (isLast) t=ENDLI; + if (!isFirst && !isLast) t = INTERLI; break; case DocNode::Kind_SecRefItem: isFirst=isFirstChildNode((DocSecRefItem*)p->parent(),p); isLast =isLastChildNode ((DocSecRefItem*)p->parent(),p); - if (isFirst) t=1; - if (isLast) t=3; + if (isFirst) t=STARTLI; + if (isLast) t=ENDLI; + if (!isFirst && !isLast) t = INTERLI; break; case DocNode::Kind_HtmlDescData: isFirst=isFirstChildNode((DocHtmlDescData*)p->parent(),p); isLast =isLastChildNode ((DocHtmlDescData*)p->parent(),p); - if (isFirst) t=2; - if (isLast) t=4; + if (isFirst) t=STARTDD; + if (isLast) t=ENDDD; + if (!isFirst && !isLast) t = INTERDD; break; case DocNode::Kind_XRefItem: isFirst=isFirstChildNode((DocXRefItem*)p->parent(),p); isLast =isLastChildNode ((DocXRefItem*)p->parent(),p); - if (isFirst) t=2; - if (isLast) t=4; + if (isFirst) t=STARTDD; + if (isLast) t=ENDDD; + if (!isFirst && !isLast) t = INTERDD; break; case DocNode::Kind_SimpleSect: isFirst=isFirstChildNode((DocSimpleSect*)p->parent(),p); isLast =isLastChildNode ((DocSimpleSect*)p->parent(),p); - if (isFirst) t=2; - if (isLast) t=4; + if (isFirst) t=STARTDD; + if (isLast) t=ENDDD; if (isSeparatedParagraph((DocSimpleSect*)p->parent(),p)) // if the paragraph is enclosed with separators it will // be included in <dd>..</dd> so avoid addition paragraph @@ -979,12 +1033,14 @@ static int getParagraphContext(DocPara *p,bool &isFirst,bool &isLast) { isFirst=isLast=TRUE; } + if (!isFirst && !isLast) t = INTERDD; break; case DocNode::Kind_HtmlCell: isFirst=isFirstChildNode((DocHtmlCell*)p->parent(),p); isLast =isLastChildNode ((DocHtmlCell*)p->parent(),p); - if (isFirst) t=5; - if (isLast) t=6; + if (isFirst) t=STARTTD; + if (isLast) t=ENDTD; + if (!isFirst && !isLast) t = INTERTD; break; default: break; @@ -1052,19 +1108,10 @@ void HtmlDocVisitor::visitPre(DocPara *p) } } - // check if this paragraph is the first or last child of a <li> or <dd>. + // check if this paragraph is the first or last or intermediate child of a <li> or <dd>. // this allows us to mark the tag with a special class so we can // fix the otherwise ugly spacing. int t; - static const char *contexts[7] = - { "", // 0 - "startli", // 1 - "startdd", // 2 - "endli", // 3 - "enddd", // 4 - "starttd", // 5 - "endtd" // 6 - }; bool isFirst; bool isLast; t = getParagraphContext(p,isFirst,isLast); diff --git a/src/htmlgen.cpp b/src/htmlgen.cpp index 87bc10a..f0f627c 100644 --- a/src/htmlgen.cpp +++ b/src/htmlgen.cpp @@ -17,6 +17,7 @@ #include <stdlib.h> +#include <assert.h> #include <qdir.h> #include <qregexp.h> #include "message.h" @@ -690,6 +691,7 @@ HtmlGenerator::HtmlGenerator() : OutputGenerator() { dir=Config_getString(HTML_OUTPUT); m_emptySection=FALSE; + m_sectionCount=0; } HtmlGenerator::~HtmlGenerator() @@ -1943,25 +1945,16 @@ void HtmlGenerator::endDescTableData() t << "</td>"; } -void HtmlGenerator::startSimpleSect(SectionTypes, - const char *filename,const char *anchor, - const char *title) +void HtmlGenerator::startExamples() { - t << "<dl><dt><b>"; - if (filename) - { - writeObjectLink(0,filename,anchor,title); - } - else - { - docify(title); - } - t << "</b></dt>"; + t << "<dl class=\"section examples\"><dt>"; + docify(theTranslator->trExamples()); + t << "</dt>"; } -void HtmlGenerator::endSimpleSect() +void HtmlGenerator::endExamples() { - t << "</dl>"; + t << "</dl>" << endl; } void HtmlGenerator::startParamList(ParamListTypes, @@ -2064,6 +2057,9 @@ static bool quickLinkVisible(LayoutNavEntry::Kind kind) case LayoutNavEntry::FileGlobals: return documentedFileMembers[FMHL_All]>0; //case LayoutNavEntry::Dirs: return documentedDirs>0; case LayoutNavEntry::Examples: return Doxygen::exampleSDict->count()>0; + case LayoutNavEntry::None: // should never happen, means not properly initialized + assert(kind != LayoutNavEntry::None); + return FALSE; } return FALSE; } diff --git a/src/htmlgen.h b/src/htmlgen.h index 2d8d6e0..221269f 100644 --- a/src/htmlgen.h +++ b/src/htmlgen.h @@ -246,13 +246,10 @@ class HtmlGenerator : public OutputGenerator void endCenter() { t << "</center>" << endl; } void startSmall() { t << "<small>" << endl; } void endSmall() { t << "</small>" << endl; } - //void startDescList(SectionTypes) { t << "<dl compact><dt><b>" << endl; } - //void endDescList() { t << "</dl>"; } - void startSimpleSect(SectionTypes,const char *,const char *,const char *); - void endSimpleSect(); + void startExamples(); + void endExamples(); void startParamList(ParamListTypes,const char *); void endParamList(); - //void writeDescItem() { t << "<dd>" << endl; } void startSection(const char *,const char *,SectionInfo::SectionType); void endSection(const char *,SectionInfo::SectionType); void addIndexItem(const char *,const char *); diff --git a/src/index.cpp b/src/index.cpp index 8e5f266..8be6b24 100644 --- a/src/index.cpp +++ b/src/index.cpp @@ -21,6 +21,7 @@ #include <stdlib.h> +#include <assert.h> #include <qtextstream.h> #include <qdatetime.h> #include <qdir.h> @@ -94,9 +95,12 @@ static void startIndexHierarchy(OutputList &ol,int level) ol.disable(OutputGenerator::Man); ol.disable(OutputGenerator::Html); if (level<6) ol.startIndexList(); - ol.enableAll(); + ol.popGeneratorState(); + + ol.pushGeneratorState(); ol.disable(OutputGenerator::Latex); ol.disable(OutputGenerator::RTF); + ol.disable(OutputGenerator::Docbook); ol.startItemList(); ol.popGeneratorState(); } @@ -107,8 +111,11 @@ static void endIndexHierarchy(OutputList &ol,int level) ol.disable(OutputGenerator::Man); ol.disable(OutputGenerator::Html); if (level<6) ol.endIndexList(); - ol.enableAll(); + ol.popGeneratorState(); + + ol.pushGeneratorState(); ol.disable(OutputGenerator::Latex); + ol.disable(OutputGenerator::Docbook); ol.disable(OutputGenerator::RTF); ol.endItemList(); ol.popGeneratorState(); @@ -959,6 +966,7 @@ static void writeHierarchicalIndex(OutputList &ol) ol.pushGeneratorState(); //1.{ ol.disable(OutputGenerator::Man); + ol.disable(OutputGenerator::Docbook); LayoutNavEntry *lne = LayoutDocManager::instance().rootNavEntry()->find(LayoutNavEntry::ClassHierarchy); QCString title = lne ? lne->title() : theTranslator->trClassHierarchy(); @@ -973,15 +981,16 @@ static void writeHierarchicalIndex(OutputList &ol) if (Config_getBool(HAVE_DOT) && Config_getBool(GRAPHICAL_HIERARCHY)) { + ol.pushGeneratorState(); ol.disable(OutputGenerator::Latex); ol.disable(OutputGenerator::RTF); + ol.disable(OutputGenerator::Docbook); ol.startParagraph(); ol.startTextLink("inherits",0); ol.parseText(theTranslator->trGotoGraphicalHierarchy()); ol.endTextLink(); ol.endParagraph(); - ol.enable(OutputGenerator::Latex); - ol.enable(OutputGenerator::RTF); + ol.popGeneratorState(); } ol.parseText(lne ? lne->intro() : theTranslator->trClassHierarchyDescription()); ol.endTextBlock(); @@ -1170,6 +1179,7 @@ static void writeFileIndex(OutputList &ol) ol.pushGeneratorState(); ol.disable(OutputGenerator::Man); + ol.disable(OutputGenerator::Docbook); if (documentedFiles==0) ol.disableAllBut(OutputGenerator::Html); LayoutNavEntry *lne = LayoutDocManager::instance().rootNavEntry()->find(LayoutNavEntry::FileList); @@ -1450,6 +1460,7 @@ static void writeNamespaceIndex(OutputList &ol) if (documentedNamespaces==0) return; ol.pushGeneratorState(); ol.disable(OutputGenerator::Man); + ol.disable(OutputGenerator::Docbook); LayoutNavEntry *lne = LayoutDocManager::instance().rootNavEntry()->find(LayoutNavEntry::NamespaceList); if (lne==0) lne = LayoutDocManager::instance().rootNavEntry()->find(LayoutNavEntry::Namespaces); // fall back QCString title = lne ? lne->title() : theTranslator->trNamespaceList(); @@ -1603,6 +1614,7 @@ static void writeAnnotatedClassList(OutputList &ol) if (cd->isEmbeddedInOuterScope()) { ol.disable(OutputGenerator::Latex); + ol.disable(OutputGenerator::Docbook); ol.disable(OutputGenerator::RTF); } if (cd->isLinkableInProject() && cd->templateMaster()==0) @@ -2021,6 +2033,7 @@ static void writeAlphabeticalIndex(OutputList &ol) if (annotatedClasses==0) return; ol.pushGeneratorState(); ol.disableAllBut(OutputGenerator::Html); + ol.disable(OutputGenerator::Docbook); LayoutNavEntry *lne = LayoutDocManager::instance().rootNavEntry()->find(LayoutNavEntry::ClassIndex); QCString title = lne ? lne->title() : theTranslator->trCompoundIndex(); bool addToIndex = lne==0 || lne->visible(); @@ -2053,6 +2066,7 @@ static void writeAnnotatedIndex(OutputList &ol) ol.pushGeneratorState(); ol.disable(OutputGenerator::Man); + ol.disable(OutputGenerator::Docbook); if (annotatedClassesPrinted==0) { ol.disable(OutputGenerator::Latex); @@ -3022,6 +3036,7 @@ static void writeExampleIndex(OutputList &ol) if (Doxygen::exampleSDict->count()==0) return; ol.pushGeneratorState(); ol.disable(OutputGenerator::Man); + ol.disable(OutputGenerator::Docbook); LayoutNavEntry *lne = LayoutDocManager::instance().rootNavEntry()->find(LayoutNavEntry::Examples); QCString title = lne ? lne->title() : theTranslator->trExamples(); bool addToIndex = lne==0 || lne->visible(); @@ -3621,6 +3636,7 @@ static void writeGroupIndex(OutputList &ol) ol.pushGeneratorState(); // 1.{ ol.disable(OutputGenerator::Man); + ol.disable(OutputGenerator::Docbook); LayoutNavEntry *lne = LayoutDocManager::instance().rootNavEntry()->find(LayoutNavEntry::Modules); QCString title = lne ? lne->title() : theTranslator->trModules(); bool addToIndex = lne==0 || lne->visible(); @@ -3910,6 +3926,7 @@ static void writeIndex(OutputList &ol) // write LaTeX/RTF index //-------------------------------------------------------------------- ol.enable(OutputGenerator::Latex); + ol.enable(OutputGenerator::Docbook); ol.enable(OutputGenerator::RTF); ol.startFile("refman",0,0); @@ -3918,6 +3935,7 @@ static void writeIndex(OutputList &ol) { ol.disable(OutputGenerator::Latex); } + ol.disable(OutputGenerator::Docbook); if (projPrefix.isEmpty()) { @@ -3939,6 +3957,7 @@ static void writeIndex(OutputList &ol) ol.parseText(theTranslator->trGeneratedBy()); ol.endIndexSection(isTitlePageAuthor); ol.enable(OutputGenerator::Latex); + ol.enable(OutputGenerator::Docbook); ol.lastIndexPage(); if (Doxygen::mainPage) @@ -3978,9 +3997,11 @@ static void writeIndex(OutputList &ol) QCString title = pd->title(); if (title.isEmpty()) title=pd->name(); + ol.disable(OutputGenerator::Docbook); ol.startIndexSection(isPageDocumentation); ol.parseText(title); ol.endIndexSection(isPageDocumentation); + ol.enable(OutputGenerator::Docbook); ol.pushGeneratorState(); // write TOC title (RTF only) ol.disableAllBut(OutputGenerator::RTF); @@ -4002,6 +4023,7 @@ static void writeIndex(OutputList &ol) } } + ol.disable(OutputGenerator::Docbook); if (!Config_getBool(LATEX_HIDE_INDICES)) { //if (indexedPages>0) @@ -4049,6 +4071,8 @@ static void writeIndex(OutputList &ol) ol.endIndexSection(isFileIndex); } } + ol.enable(OutputGenerator::Docbook); + if (documentedGroups>0) { ol.startIndexSection(isModuleDocumentation); @@ -4285,6 +4309,9 @@ static void writeIndexHierarchyEntries(OutputList &ol,const QList<LayoutNavEntry } writeUserGroupStubPage(ol,lne); break; + case LayoutNavEntry::None: + assert(kind != LayoutNavEntry::None); // should never happen, means not properly initialized + break; } if (kind!=LayoutNavEntry::User && kind!=LayoutNavEntry::UserGroup) // User entry may appear multiple times { @@ -4334,6 +4361,9 @@ static bool quickLinkVisible(LayoutNavEntry::Kind kind) case LayoutNavEntry::FileGlobals: return documentedFileMembers[FMHL_All]>0; //case LayoutNavEntry::Dirs: return documentedDirs>0; case LayoutNavEntry::Examples: return Doxygen::exampleSDict->count()>0; + case LayoutNavEntry::None: // should never happen, means not properly initialized + assert(kind != LayoutNavEntry::None); + return FALSE; } return FALSE; } diff --git a/src/latexdocvisitor.cpp b/src/latexdocvisitor.cpp index d2c4c5d..51e53e9 100644 --- a/src/latexdocvisitor.cpp +++ b/src/latexdocvisitor.cpp @@ -215,13 +215,14 @@ void LatexDocVisitor::visit(DocURL *u) if (m_hide) return; if (Config_getBool(PDF_HYPERLINKS)) { + m_t << endl << "%% AME " << u->url() <<endl; m_t << "\\href{"; if (u->isEmail()) m_t << "mailto:"; - m_t << u->url() << "}"; + m_t << latexFilterURL(u->url()) << "}"; } - m_t << "\\texttt{ "; + m_t << "{\\texttt{ "; filter(u->url()); - m_t << "}"; + m_t << "}}"; } void LatexDocVisitor::visit(DocLineBreak *) @@ -242,7 +243,13 @@ void LatexDocVisitor::visit(DocStyleChange *s) switch (s->style()) { case DocStyleChange::Bold: - if (s->enable()) m_t << "{\\bfseries "; else m_t << "}"; + if (s->enable()) m_t << "{\\bfseries{"; else m_t << "}}"; + break; + case DocStyleChange::Strike: + if (s->enable()) m_t << "\\sout{"; else m_t << "}"; + break; + case DocStyleChange::Underline: + if (s->enable()) m_t << "\\uline{"; else m_t << "}"; break; case DocStyleChange::Italic: if (s->enable()) m_t << "{\\itshape "; else m_t << "}"; @@ -1171,8 +1178,8 @@ void LatexDocVisitor::visitPre(DocHtmlCell *c) m_t << "r|}{"; break; case DocHtmlCell::Center: - break; m_t << "c|}{"; + break; default: m_t << "l|}{"; break; @@ -1245,17 +1252,18 @@ void LatexDocVisitor::visitPre(DocHRef *href) if (m_hide) return; if (Config_getBool(PDF_HYPERLINKS)) { + m_t << endl << "%% AME " << href->url() <<endl; m_t << "\\href{"; - m_t << href->url(); + m_t << latexFilterURL(href->url()); m_t << "}"; } - m_t << "\\texttt{ "; + m_t << "{\\texttt{ "; } void LatexDocVisitor::visitPost(DocHRef *) { if (m_hide) return; - m_t << "}"; + m_t << "}}"; } void LatexDocVisitor::visitPre(DocHtmlHeader *header) diff --git a/src/latexgen.cpp b/src/latexgen.cpp index 474d368..9f1372e 100644 --- a/src/latexgen.cpp +++ b/src/latexgen.cpp @@ -1369,12 +1369,12 @@ void LatexGenerator::startHtmlLink(const char *url) t << url; t << "}"; } - t << "\\texttt{ "; + t << "{\\texttt{ "; } void LatexGenerator::endHtmlLink() { - t << "}"; + t << "}}"; } //void LatexGenerator::writeMailLink(const char *url) @@ -2095,22 +2095,14 @@ void LatexGenerator::endDescItem() } } -void LatexGenerator::startSimpleSect(SectionTypes,const char *file, - const char *anchor,const char *title) +void LatexGenerator::startExamples() { t << "\\begin{Desc}\n\\item["; - if (file) - { - writeObjectLink(0,file,anchor,title); - } - else - { - docify(title); - } + docify(theTranslator->trExamples()); t << "]"; } -void LatexGenerator::endSimpleSect() +void LatexGenerator::endExamples() { t << "\\end{Desc}" << endl; } @@ -2167,7 +2159,7 @@ void LatexGenerator::endParameterName(bool last,bool /*emptyList*/,bool closeBra void LatexGenerator::exceptionEntry(const char* prefix,bool closeBracket) { if (prefix) - t << " " << prefix; + t << " " << prefix << "("; else if (closeBracket) t << ")"; t << " "; @@ -2230,11 +2222,9 @@ void LatexGenerator::startCodeFragment() void LatexGenerator::endCodeFragment() { - //if (DoxyCodeOpen) - //{ - // t << "}\n"; - // DoxyCodeOpen = FALSE; - //} + //endCodeLine checks is there is still an open code line, if so closes it. + endCodeLine(); + t << "\\end{DoxyCode}\n"; DoxyCodeOpen = FALSE; } diff --git a/src/latexgen.h b/src/latexgen.h index 07c4080..1460000 100644 --- a/src/latexgen.h +++ b/src/latexgen.h @@ -235,8 +235,8 @@ class LatexGenerator : public OutputGenerator const char *,const char *,const char *) {} void startDescList(SectionTypes) { t << "\\begin{Desc}\n\\item["; } void endDescList() { t << "\\end{Desc}" << endl; } - void startSimpleSect(SectionTypes,const char *,const char *,const char *); - void endSimpleSect(); + void startExamples(); + void endExamples(); void startParamList(ParamListTypes,const char *title); void endParamList(); void startDescForItem() { t << "\\par" << endl; } diff --git a/src/layout.cpp b/src/layout.cpp index 1d9a5ed..a3849b5 100644 --- a/src/layout.cpp +++ b/src/layout.cpp @@ -1268,7 +1268,7 @@ class LayoutParser : public QXmlDefaultHandler } private: - LayoutParser() : m_sHandler(163), m_eHandler(17), m_invalidEntry(FALSE) { } + LayoutParser() : m_sHandler(163), m_eHandler(17), m_invalidEntry(FALSE), m_part(0), m_rootNav(NULL) { } ~LayoutParser() { delete m_rootNav; } QDict<StartElementHandler> m_sHandler; diff --git a/src/layout.h b/src/layout.h index 0b9ad9e..1906a3d 100644 --- a/src/layout.h +++ b/src/layout.h @@ -119,6 +119,7 @@ struct LayoutNavEntry { public: enum Kind { + None = -1, MainPage, Pages, Modules, @@ -158,7 +159,7 @@ struct LayoutNavEntry LayoutNavEntry *find(LayoutNavEntry::Kind k,const char *file=0) const; private: - LayoutNavEntry() : m_parent(0) {} + LayoutNavEntry() : m_parent(0), m_kind(None), m_visible(FALSE) {} LayoutNavEntry *m_parent; Kind m_kind; bool m_visible; diff --git a/src/mandocvisitor.cpp b/src/mandocvisitor.cpp index 2233cc6..e09cc8e 100644 --- a/src/mandocvisitor.cpp +++ b/src/mandocvisitor.cpp @@ -120,6 +120,13 @@ void ManDocVisitor::visit(DocStyleChange *s) if (s->enable()) m_t << "\\fB"; else m_t << "\\fP"; m_firstCol=FALSE; break; + case DocStyleChange::Strike: + /* not supported */ + break; + case DocStyleChange::Underline: //underline is shown as emphasis + if (s->enable()) m_t << "\\fI"; else m_t << "\\fP"; + m_firstCol=FALSE; + break; case DocStyleChange::Italic: if (s->enable()) m_t << "\\fI"; else m_t << "\\fP"; m_firstCol=FALSE; diff --git a/src/mangen.cpp b/src/mangen.cpp index d23b2fe..b3ae732 100644 --- a/src/mangen.cpp +++ b/src/mangen.cpp @@ -34,7 +34,7 @@ static QCString getExtension() { /* - * [.][nuber][rest] + * [.][number][rest] * in case of . missing, just ignore it * in case number missing, just place a 3 in front of it */ @@ -650,8 +650,25 @@ void ManGenerator::endSection(const char *,SectionInfo::SectionType type) } } -void ManGenerator::startSimpleSect(SectionTypes,const char *, - const char *,const char *title) +void ManGenerator::startExamples() +{ + if (!firstCol) + { t << endl << ".PP" << endl; + firstCol=TRUE; paragraph=TRUE; + col=0; + } + paragraph=FALSE; + startBold(); + docify(theTranslator->trExamples()); + endBold(); + paragraph=TRUE; +} + +void ManGenerator::endExamples() +{ +} + +void ManGenerator::startDescTable(const char *title) { if (!firstCol) { t << endl << ".PP" << endl; @@ -663,10 +680,12 @@ void ManGenerator::startSimpleSect(SectionTypes,const char *, docify(title); endBold(); paragraph=TRUE; + startDescForItem(); } -void ManGenerator::endSimpleSect() +void ManGenerator::endDescTable() { + endDescForItem(); } void ManGenerator::startParamList(ParamListTypes,const char *title) diff --git a/src/mangen.h b/src/mangen.h index 0413ffd..e109355 100644 --- a/src/mangen.h +++ b/src/mangen.h @@ -169,8 +169,8 @@ class ManGenerator : public OutputGenerator const char *,const char *,const char *) {} void startDescList(SectionTypes); void endDescList() {} - void startSimpleSect(SectionTypes,const char *,const char *,const char *); - void endSimpleSect(); + void startExamples(); + void endExamples(); void startParamList(ParamListTypes,const char *title); void endParamList(); //void writeDescItem(); @@ -197,9 +197,8 @@ class ManGenerator : public OutputGenerator void endContents() {} void writeNonBreakableSpace(int n) { int i; for (i=0;i<n;i++) t << " "; } - void startDescTable(const char *t) - { startSimpleSect(EnumValues,0,0,t); startDescForItem(); } - void endDescTable() { endDescForItem(); endSimpleSect(); } + void startDescTable(const char *t); + void endDescTable(); void startDescTableRow() {} void endDescTableRow() {} void startDescTableTitle() { startItemListItem(); startBold(); startEmphasis(); endItemListItem(); } diff --git a/src/markdown.cpp b/src/markdown.cpp index dff64ff..59ce108 100644 --- a/src/markdown.cpp +++ b/src/markdown.cpp @@ -76,7 +76,7 @@ // so for example *bla (*.txt) is cool* #define ignoreCloseEmphChar(i) \ (data[i]=='(' || data[i]=='{' || data[i]=='[' || data[i]=='<' || \ - data[i]=='=' || data[i]=='+' || data[i]=='-' || data[i]=='\\' || \ + data[i]=='\\' || \ data[i]=='@') //---------- @@ -396,9 +396,11 @@ static int processEmphasis2(GrowBuf &out, const char *data, int size, char c) data[i-1]!='\n' ) { - out.addStr("<strong>"); + if (c == '~') out.addStr("<strike>"); + else out.addStr("<strong>"); processInline(out,data,i); - out.addStr("</strong>"); + if (c == '~') out.addStr("</strike>"); + else out.addStr("</strong>"); return i + 2; } i++; @@ -406,7 +408,7 @@ static int processEmphasis2(GrowBuf &out, const char *data, int size, char c) return 0; } -/** Parsing tripple emphasis. +/** Parsing triple emphasis. * Finds the first closing tag, and delegates to the other emph */ static int processEmphasis3(GrowBuf &out, const char *data, int size, char c) @@ -616,7 +618,7 @@ static int processEmphasis(GrowBuf &out,const char *data,int offset,int size) char c = data[0]; int ret; - if (size>2 && data[1]!=c) // _bla or *bla + if (size>2 && c!='~' && data[1]!=c) // _bla or *bla { // whitespace cannot follow an opening emphasis if (data[1]==' ' || data[1]=='\n' || @@ -635,7 +637,7 @@ static int processEmphasis(GrowBuf &out,const char *data,int offset,int size) } return ret+2; } - if (size>4 && data[1]==c && data[2]==c && data[3]!=c) // ___bla or ***bla + if (size>4 && c!='~' && data[1]==c && data[2]==c && data[3]!=c) // ___bla or ***bla { if (data[3]==' ' || data[3]=='\n' || (ret = processEmphasis3(out, data+3, size-3, c)) == 0) @@ -647,6 +649,27 @@ static int processEmphasis(GrowBuf &out,const char *data,int offset,int size) return 0; } +static void writeMarkdownImage(GrowBuf &out, const char *fmt, bool explicitTitle, QCString title, QCString content, QCString link, FileDef *fd) +{ + out.addStr("@image "); + out.addStr(fmt); + out.addStr(" "); + out.addStr(link.mid(fd ? 0 : 5)); + if (!explicitTitle && !content.isEmpty()) + { + out.addStr(" \""); + out.addStr(content); + out.addStr("\""); + } + else if ((content.isEmpty() || explicitTitle) && !title.isEmpty()) + { + out.addStr(" \""); + out.addStr(title); + out.addStr("\""); + } + out.addStr("\n"); +} + static int processLink(GrowBuf &out,const char *data,int,int size) { QCString content; @@ -854,20 +877,10 @@ static int processLink(GrowBuf &out,const char *data,int,int size) (fd=findFileDef(Doxygen::imageNameDict,link,ambig))) // assume doxygen symbol link or local image link { - out.addStr("@image html "); - out.addStr(link.mid(fd ? 0 : 5)); - if (!explicitTitle && !content.isEmpty()) - { - out.addStr(" \""); - out.addStr(content); - out.addStr("\""); - } - else if ((content.isEmpty() || explicitTitle) && !title.isEmpty()) - { - out.addStr(" \""); - out.addStr(title); - out.addStr("\""); - } + writeMarkdownImage(out, "html", explicitTitle, title, content, link, fd); + writeMarkdownImage(out, "latex", explicitTitle, title, content, link, fd); + writeMarkdownImage(out, "rtf", explicitTitle, title, content, link, fd); + writeMarkdownImage(out, "docbook", explicitTitle, title, content, link, fd); } else { @@ -2513,6 +2526,7 @@ QCString processMarkdown(const QCString &fileName,const int lineNr,Entry *e,cons // setup callback table for special characters g_actions[(unsigned int)'_']=processEmphasis; g_actions[(unsigned int)'*']=processEmphasis; + g_actions[(unsigned int)'~']=processEmphasis; g_actions[(unsigned int)'`']=processCodeSpan; g_actions[(unsigned int)'\\']=processSpecialCommand; g_actions[(unsigned int)'@']=processSpecialCommand; diff --git a/src/marshal.cpp b/src/marshal.cpp index fa29aed..f0ed2e8 100644 --- a/src/marshal.cpp +++ b/src/marshal.cpp @@ -350,6 +350,7 @@ void marshalLocalToc(StorageIntf *s,const LocalToc <) marshalInt(s,lt.htmlLevel()); marshalInt(s,lt.latexLevel()); marshalInt(s,lt.xmlLevel()); + marshalInt(s,lt.docbookLevel()); } void marshalEntry(StorageIntf *s,Entry *e) @@ -740,6 +741,7 @@ LocalToc unmarshalLocalToc(StorageIntf *s) int htmlLevel = unmarshalInt(s); int latexLevel = unmarshalInt(s); int xmlLevel = unmarshalInt(s); + int docbookLevel = unmarshalInt(s); if ((mask & (1<<LocalToc::Html))!=0) { result.enableHtml(htmlLevel); @@ -752,6 +754,10 @@ LocalToc unmarshalLocalToc(StorageIntf *s) { result.enableXml(xmlLevel); } + if ((mask & (1<<LocalToc::Docbook))!=0) + { + result.enableDocbook(docbookLevel); + } return result; } diff --git a/src/memberdef.cpp b/src/memberdef.cpp index 819904f..1cedc7f 100644 --- a/src/memberdef.cpp +++ b/src/memberdef.cpp @@ -161,10 +161,12 @@ static bool writeDefArgumentList(OutputList &ol,Definition *scope,MemberDef *md) //ol.disableAllBut(OutputGenerator::Html); bool htmlOn = ol.isEnabled(OutputGenerator::Html); bool latexOn = ol.isEnabled(OutputGenerator::Latex); + bool docbookOn = ol.isEnabled(OutputGenerator::Docbook); { // html and latex if (htmlOn) ol.enable(OutputGenerator::Html); if (latexOn) ol.enable(OutputGenerator::Latex); + if (docbookOn) ol.enable(OutputGenerator::Docbook); ol.endMemberDocName(); ol.startParameterList(!md->isObjCMethod()); @@ -172,6 +174,7 @@ static bool writeDefArgumentList(OutputList &ol,Definition *scope,MemberDef *md) ol.enableAll(); ol.disable(OutputGenerator::Html); ol.disable(OutputGenerator::Latex); + ol.disable(OutputGenerator::Docbook); { // other formats if (!md->isObjCMethod()) ol.docify("("); // start argument list @@ -270,6 +273,7 @@ static bool writeDefArgumentList(OutputList &ol,Definition *scope,MemberDef *md) // ol.docify(" "); //} ol.disable(OutputGenerator::Latex); + ol.disable(OutputGenerator::Docbook); ol.disable(OutputGenerator::Html); ol.docify(" "); /* man page */ if (htmlOn) ol.enable(OutputGenerator::Html); @@ -277,12 +281,15 @@ static bool writeDefArgumentList(OutputList &ol,Definition *scope,MemberDef *md) ol.startEmphasis(); ol.enable(OutputGenerator::Man); if (latexOn) ol.enable(OutputGenerator::Latex); + if (docbookOn) ol.enable(OutputGenerator::Docbook); if (a->name.isEmpty()) ol.docify(a->type); else ol.docify(a->name); ol.disable(OutputGenerator::Man); ol.disable(OutputGenerator::Latex); + ol.disable(OutputGenerator::Docbook); ol.endEmphasis(); ol.enable(OutputGenerator::Man); if (latexOn) ol.enable(OutputGenerator::Latex); + if (docbookOn) ol.enable(OutputGenerator::Docbook); } if (!a->array.isEmpty()) { @@ -338,10 +345,12 @@ static bool writeDefArgumentList(OutputList &ol,Definition *scope,MemberDef *md) ol.pushGeneratorState(); ol.disable(OutputGenerator::Html); ol.disable(OutputGenerator::Latex); + ol.disable(OutputGenerator::Docbook); if (!md->isObjCMethod()) ol.docify(")"); // end argument list ol.enableAll(); if (htmlOn) ol.enable(OutputGenerator::Html); if (latexOn) ol.enable(OutputGenerator::Latex); + if (docbookOn) ol.enable(OutputGenerator::Docbook); if (first) ol.startParameterName(defArgList->count()<2); ol.endParameterName(TRUE,defArgList->count()<2,!md->isObjCMethod()); ol.popGeneratorState(); @@ -1478,6 +1487,7 @@ void MemberDef::writeDeclaration(OutputList &ol, ol.pushGeneratorState(); ol.disable(OutputGenerator::Man); ol.disable(OutputGenerator::Latex); + ol.disable(OutputGenerator::Docbook); ol.docify("\n"); ol.popGeneratorState(); } @@ -2309,11 +2319,11 @@ void MemberDef::_writeExamples(OutputList &ol) // write the list of examples that use this member if (hasExamples()) { - ol.startSimpleSect(BaseOutputDocInterface::Examples,0,0,theTranslator->trExamples()+": "); + ol.startExamples(); ol.startDescForItem(); writeExample(ol,m_impl->exampleSDict); ol.endDescForItem(); - ol.endSimpleSect(); + ol.endExamples(); } } @@ -2346,8 +2356,6 @@ void MemberDef::_writeEnumValues(OutputList &ol,Definition *container, { if (first) { - //ol.startSimpleSect(BaseOutputDocInterface::EnumValues,0,0,theTranslator->trEnumerationValues()+": "); - //ol.startDescForItem(); ol.startDescTable(theTranslator->trEnumerationValues()); } @@ -2355,28 +2363,17 @@ void MemberDef::_writeEnumValues(OutputList &ol,Definition *container, ol.addIndexItem(fmd->name(),ciname); ol.addIndexItem(ciname,fmd->name()); - //Doxygen::indexList->addIndexItem( - // ciname, // level1 - // fmd->name(), // level2 - // separateMemPages ? cfname : cfiname, // contRef - // cfname, // memRef - // fmd->anchor(), // anchor - // fmd); // memberdef Doxygen::indexList->addIndexItem(container,fmd); - //ol.writeListItem(); ol.startDescTableTitle(); ol.startDoxyAnchor(cfname,cname,fmd->anchor(),fmd->name(),fmd->argsString()); first=FALSE; - //ol.startEmphasis(); ol.docify(fmd->name()); - //ol.endEmphasis(); ol.disableAllBut(OutputGenerator::Man); ol.writeString(" "); ol.enableAll(); ol.endDoxyAnchor(cfname,fmd->anchor()); ol.endDescTableTitle(); - //ol.newParagraph(); ol.startDescTableData(); bool hasBrief = !fmd->briefDescription().isEmpty(); @@ -2407,11 +2404,7 @@ void MemberDef::_writeEnumValues(OutputList &ol,Definition *container, } if (!first) { - //ol.endItemList(); ol.endDescTable(); - //ol.endDescForItem(); - //ol.endSimpleSect(); - //ol.writeChar('\n'); } } } @@ -2567,7 +2560,7 @@ void MemberDef::writeDocumentation(MemberList *ml, QCString scopeName = scName; QCString memAnchor = anchor(); - QCString ciname = container->name(); + QCString ciname = container->displayName(); Definition *scopedContainer = container; // see bug 753608 if (container->definitionType()==TypeGroup) { @@ -3853,8 +3846,10 @@ void MemberDef::writeEnumDeclaration(OutputList &typeDecl, typeDecl.pushGeneratorState(); typeDecl.disableAllBut(OutputGenerator::Html); typeDecl.enable(OutputGenerator::Latex); + typeDecl.enable(OutputGenerator::Docbook); typeDecl.lineBreak(); typeDecl.disable(OutputGenerator::Latex); + typeDecl.disable(OutputGenerator::Docbook); typeDecl.writeString("  "); typeDecl.popGeneratorState(); } diff --git a/src/namespacedef.cpp b/src/namespacedef.cpp index d3eb0df..8e6c881 100644 --- a/src/namespacedef.cpp +++ b/src/namespacedef.cpp @@ -326,6 +326,7 @@ void NamespaceDef::writeTagFile(FTextStream &tagFile) } } } + break; case LayoutDocEntry::MemberDecl: { LayoutDocEntryMemberDecl *lmd = (LayoutDocEntryMemberDecl*)lde; diff --git a/src/outputgen.h b/src/outputgen.h index 44d34b8..a99cff3 100644 --- a/src/outputgen.h +++ b/src/outputgen.h @@ -145,7 +145,8 @@ class BaseOutputDocInterface : public CodeOutputInterface Since, Date, Bug, Note, Warning, Par, Deprecated, Pre, Post, Invar, Remark, Attention, - Todo, Test, RCS, */ EnumValues, + Todo, Test, RCS, */ + EnumValues, Examples }; @@ -279,9 +280,8 @@ class BaseOutputDocInterface : public CodeOutputInterface virtual void startSmall() = 0; virtual void endSmall() = 0; - virtual void startSimpleSect(SectionTypes t,const char *file, - const char *anchor,const char *title) = 0; - virtual void endSimpleSect() = 0; + virtual void startExamples() = 0; + virtual void endExamples() = 0; virtual void startParamList(ParamListTypes t,const char *title) = 0; virtual void endParamList() = 0; @@ -322,7 +322,7 @@ class BaseOutputDocInterface : public CodeOutputInterface class OutputGenerator : public BaseOutputDocInterface { public: - enum OutputType { Html, Latex, Man, RTF, XML, DEF, Perl }; + enum OutputType { Html, Latex, Man, RTF, XML, DEF, Perl , Docbook}; OutputGenerator(); virtual ~OutputGenerator(); diff --git a/src/outputlist.h b/src/outputlist.h index 2e89101..5fd8017 100644 --- a/src/outputlist.h +++ b/src/outputlist.h @@ -321,11 +321,10 @@ class OutputList : public OutputDocInterface const char *title,const char *name) { forall(&OutputGenerator::writeInheritedSectionTitle,id,ref, file,anchor,title,name); } - void startSimpleSect(SectionTypes t,const char *file,const char *anchor, - const char *title) - { forall(&OutputGenerator::startSimpleSect,t,file,anchor,title); } - void endSimpleSect() - { forall(&OutputGenerator::endSimpleSect); } + void startExamples() + { forall(&OutputGenerator::startExamples); } + void endExamples() + { forall(&OutputGenerator::endExamples); } void startParamList(ParamListTypes t,const char *title) { forall(&OutputGenerator::startParamList,t,title); } void endParamList() diff --git a/src/pagedef.cpp b/src/pagedef.cpp index d2c3f68..79a78d3 100644 --- a/src/pagedef.cpp +++ b/src/pagedef.cpp @@ -187,6 +187,7 @@ void PageDef::writeDocumentation(OutputList &ol) ol.pushGeneratorState(); //2.{ ol.disable(OutputGenerator::Latex); + ol.disable(OutputGenerator::Docbook); ol.disable(OutputGenerator::RTF); ol.disable(OutputGenerator::Man); if (!title().isEmpty() && !name().isEmpty() && si!=0) @@ -207,7 +208,7 @@ void PageDef::writeDocumentation(OutputList &ol) ol.popGeneratorState(); //2.} - if ((m_localToc.isHtmlEnabled() || m_localToc.isLatexEnabled()) && hasSections()) + if ((m_localToc.isHtmlEnabled() || m_localToc.isLatexEnabled() || m_localToc.isDocbookEnabled()) && hasSections()) { writeToc(ol, m_localToc); } @@ -269,6 +270,7 @@ void PageDef::writePageDocumentation(OutputList &ol) ol.pushGeneratorState(); ol.disableAll(); ol.enable(OutputGenerator::Latex); + ol.enable(OutputGenerator::Docbook); ol.enable(OutputGenerator::RTF); PageSDict::Iterator pdi(*m_subPageDict); diff --git a/src/perlmodgen.cpp b/src/perlmodgen.cpp index 7bf0b82..5b4b6ea 100644 --- a/src/perlmodgen.cpp +++ b/src/perlmodgen.cpp @@ -428,7 +428,7 @@ private: }; PerlModDocVisitor::PerlModDocVisitor(PerlModOutput &output) - : DocVisitor(DocVisitor_Other), m_output(output), m_textmode(false) + : DocVisitor(DocVisitor_Other), m_output(output), m_textmode(false), m_textblockstart(FALSE) { m_output.openList("doc"); } @@ -626,6 +626,8 @@ void PerlModDocVisitor::visit(DocStyleChange *s) switch (s->style()) { case DocStyleChange::Bold: style = "bold"; break; + case DocStyleChange::Strike: style = "strike"; break; + case DocStyleChange::Underline: style = "underline"; break; case DocStyleChange::Italic: style = "italic"; break; case DocStyleChange::Code: style = "code"; break; case DocStyleChange::Subscript: style = "subscript"; break; diff --git a/src/printdocvisitor.h b/src/printdocvisitor.h index d1dbb74..8d9a2b9 100644 --- a/src/printdocvisitor.h +++ b/src/printdocvisitor.h @@ -91,6 +91,12 @@ class PrintDocVisitor : public DocVisitor case DocStyleChange::Bold: if (s->enable()) printf("<bold>"); else printf("</bold>"); break; + case DocStyleChange::Strike: + if (s->enable()) printf("<strike>"); else printf("</strike>"); + break; + case DocStyleChange::Underline: + if (s->enable()) printf("<underline>"); else printf("</underline>"); + break; case DocStyleChange::Italic: if (s->enable()) printf("<italic>"); else printf("</italic>"); break; diff --git a/src/pycode.l b/src/pycode.l index 1b176d6..dfa383f 100644 --- a/src/pycode.l +++ b/src/pycode.l @@ -1311,7 +1311,7 @@ TARGET ({IDENTIFIER}|"("{TARGET_LIST}")"|"["{TARGET_LIST}"]"|{ATTRIBUT \\. { // espaced char codify(yytext); } - {STRINGPREFIX}?{TRIDOUBLEQUOTE} { // tripple double quotes + {STRINGPREFIX}?{TRIDOUBLEQUOTE} { // triple double quotes codify(yytext); } "'" { // end of the string @@ -1334,7 +1334,7 @@ TARGET ({IDENTIFIER}|"("{TARGET_LIST}")"|"["{TARGET_LIST}"]"|{ATTRIBUT \\. { // espaced char codify(yytext); } - {STRINGPREFIX}?{TRISINGLEQUOTE} { // tripple single quotes + {STRINGPREFIX}?{TRISINGLEQUOTE} { // triple single quotes codify(yytext); } "\"" { // end of the string diff --git a/src/pyscanner.l b/src/pyscanner.l index 4718e3b..aed1ede 100644 --- a/src/pyscanner.l +++ b/src/pyscanner.l @@ -118,6 +118,8 @@ static bool g_packageCommentAllowed; static bool g_start_init = FALSE; static int g_search_count = 0; +static QCString g_argType = ""; +static bool g_funcParamsEnd; //----------------------------------------------------------------------------- @@ -513,6 +515,8 @@ STARTDOCSYMS "##" %x FunctionDec %x FunctionParams %x FunctionBody +%x FunctionAnnotation +%x FunctionTypeAnnotation %x FunctionParamDefVal /* Class states */ @@ -932,7 +936,6 @@ STARTDOCSYMS "##" } <FunctionDec>{ - {IDENTIFIER} { //found function name if (current->type.isEmpty()) @@ -943,47 +946,59 @@ STARTDOCSYMS "##" current->name = current->name.stripWhiteSpace(); newFunction(); } - {B}":" { // function without arguments + {B}":"{B} { // function without arguments g_specialBlock = TRUE; // expecting a docstring bodyEntry = current; current->bodyLine = yyLineNr; - BEGIN( FunctionBody ); + BEGIN(FunctionBody); } + "->" { + g_defVal.resize(0); + g_braceCount = 0; + BEGIN(FunctionTypeAnnotation); + } {B}"(" { - BEGIN( FunctionParams ); + g_funcParamsEnd = FALSE; + BEGIN(FunctionParams); } + ")" { // end of parameter list + current->args = argListToString(current->argList); + g_funcParamsEnd = TRUE; + } } <FunctionParams>{ ({BB}|",") { } + [\*]+ { + g_argType = yytext; + } {IDENTIFIER} { // Name of parameter lineCount(); Argument *a = new Argument; current->argList->append(a); current->argList->getLast()->name = QCString(yytext).stripWhiteSpace(); - current->argList->getLast()->type = ""; + current->argList->getLast()->type = g_argType; + g_argType = ""; } "=" { // default value // TODO: this rule is too simple, need to be able to // match things like =")" as well! g_defVal.resize(0); - g_braceCount=0; + g_braceCount = 0; BEGIN(FunctionParamDefVal); } - - ")" { // end of parameter list - current->args = argListToString(current->argList); + ")" { + unput(*yytext); + BEGIN(FunctionDec); } - ":"{B} { - g_specialBlock = TRUE; // expecting a docstring - bodyEntry = current; - current->bodyLine = yyLineNr; - BEGIN( FunctionBody ); - } + g_defVal.resize(0); + g_braceCount = 0; + BEGIN(FunctionAnnotation); + } {POUNDCOMMENT} { // a comment } {PARAMNONEMPTY} { // Default rule inside arguments. @@ -991,31 +1006,131 @@ STARTDOCSYMS "##" } +<FunctionTypeAnnotation>{ + "{" | + "[" | + "(" { + ++g_braceCount; + g_defVal+=*yytext; + } + "}" | + "]" | + ")" { + --g_braceCount; + g_defVal+=*yytext; + } + ":" { + if (g_braceCount == 0) + { + current->type = g_defVal.data(); + unput(*yytext); + BEGIN(FunctionDec); + } + else + g_defVal+=*yytext; + } + "'" { + g_defVal+=*yytext; + g_copyString=&g_defVal; + g_stringContext=FunctionTypeAnnotation; + BEGIN(SingleQuoteString); + } + "\"" { + g_defVal+=*yytext; + g_copyString=&g_defVal; + g_stringContext=FunctionTypeAnnotation; + BEGIN(DoubleQuoteString); + } + \n { + g_defVal+=*yytext; + incLineNr(); + } + . { + g_defVal+=*yytext; + } +} + +<FunctionAnnotation>{ + "{" | + "[" | + "(" { + ++g_braceCount; + g_defVal+=*yytext; + } + "}" | + "]" { + --g_braceCount; + g_defVal+=*yytext; + } + ")" | + "=" | + "," { + if (g_braceCount == 0) + { + if (current->argList->getLast()) + current->argList->getLast()->type += g_defVal.data(); + if (*yytext != ',') + unput(*yytext); + BEGIN(FunctionParams); + } + else + { + if (*yytext == ')') + --g_braceCount; + g_defVal += *yytext; + } + } + "'" { + g_defVal+=*yytext; + g_copyString=&g_defVal; + g_stringContext=FunctionAnnotation; + BEGIN(SingleQuoteString); + } + "\"" { + g_defVal+=*yytext; + g_copyString=&g_defVal; + g_stringContext=FunctionAnnotation; + BEGIN(DoubleQuoteString); + } + \n { + g_defVal+=*yytext; + incLineNr(); + } + . { + g_defVal+=*yytext; + } +} + <FunctionParamDefVal>{ + "{" | "[" | "(" { // internal opening brace, assumption is that we have correct code so braces do match - g_braceCount++; + ++g_braceCount; g_defVal+=*yytext; } - "," | - "]" | - ")" { - if (g_braceCount==0) // end of default argument + "}" | + "]" { + --g_braceCount; + g_defVal+=*yytext; + } + ")" | + "," { + if (g_braceCount == 0) { if (current->argList->getLast()) - { current->argList->getLast()->defval=QCString(g_defVal.data()).stripWhiteSpace(); - } - if (*yytext != ',') - current->args = argListToString(current->argList); + if (*yytext == ')') + unput(*yytext); BEGIN(FunctionParams); } - else // continue - { - if (*yytext != ',')g_braceCount--; - g_defVal+=*yytext; - } + else + { + if (*yytext == ')') + --g_braceCount; + g_defVal += *yytext; + } } + "'" { g_defVal+=*yytext; g_copyString=&g_defVal; @@ -1396,7 +1511,6 @@ STARTDOCSYMS "##" BEGIN(Search); } <<EOF>> { yyterminate(); - newEntry(); } } @@ -1425,7 +1539,7 @@ STARTDOCSYMS "##" actualDoc.prepend("\\verbatim "); actualDoc.append("\\endverbatim "); } - actualDoc.prepend("\\namespace "+g_moduleScope+"\\_linebr "); + actualDoc.prepend("\\namespace "+g_moduleScope+" "); handleCommentBlock(actualDoc, FALSE); } if ((docBlockContext==ClassBody /*&& !g_hideClassDocs*/) || @@ -1508,7 +1622,7 @@ STARTDOCSYMS "##" \\. { // espaced char addToString(yytext); } - "\"\"\"" { // tripple double quotes + "\"\"\"" { // triple double quotes addToString(yytext); } "'" { // end of the string @@ -1531,7 +1645,7 @@ STARTDOCSYMS "##" \\. { // espaced char addToString(yytext); } - "'''" { // tripple single quotes + "'''" { // triple single quotes addToString(yytext); } "\"" { // end of the string diff --git a/src/res2cc_cmd.py b/src/res2cc_cmd.py index 7e0322d..86d999d 100755 --- a/src/res2cc_cmd.py +++ b/src/res2cc_cmd.py @@ -98,10 +98,11 @@ def main(): directory = sys.argv[1] files = [] for dirName, subdirList, fileList in walk(directory): - for fname in sorted(fileList): + for fname in fileList: subdir = dirName[len(directory)+1:] if dirName.startswith(directory) else dirName if subdir: files.append(File.factory(directory,subdir,fname)) + files.sort(key=lambda f: f.subdir + "/" + f.fileName) outputFile = open(sys.argv[2],"w") print("#include \"resourcemgr.h\"\n",file=outputFile) for f in files: diff --git a/src/rtfdocvisitor.cpp b/src/rtfdocvisitor.cpp index ec6d015..0be2266 100644 --- a/src/rtfdocvisitor.cpp +++ b/src/rtfdocvisitor.cpp @@ -192,6 +192,12 @@ void RTFDocVisitor::visit(DocStyleChange *s) case DocStyleChange::Bold: if (s->enable()) m_t << "{\\b "; else m_t << "} "; break; + case DocStyleChange::Strike: + if (s->enable()) m_t << "{\\strike "; else m_t << "} "; + break; + case DocStyleChange::Underline: + if (s->enable()) m_t << "{\\ul "; else m_t << "} "; + break; case DocStyleChange::Italic: if (s->enable()) m_t << "{\\i "; else m_t << "} "; break; @@ -1066,7 +1072,7 @@ void RTFDocVisitor::visitPre(DocHtmlHeader *header) m_t << "{" // start section << rtf_Style_Reset; QCString heading; - int level = QMIN(header->level()+2,4); + int level = QMIN(header->level(),5); heading.sprintf("Heading%d",level); // set style m_t << rtf_Style[heading]->reference; diff --git a/src/rtfgen.cpp b/src/rtfgen.cpp index 64da929..b4a9e65 100644 --- a/src/rtfgen.cpp +++ b/src/rtfgen.cpp @@ -2632,7 +2632,7 @@ void testRTFOutput(const char *name) err: err("RTF integrity test failed at line %d of %s due to a bracket mismatch.\n" " Please try to create a small code example that produces this error \n" - " and send that to dimitri@stack.nl.\n",line,name); + " and send that to doxygen@gmail.com.\n",line,name); } /** @@ -2727,21 +2727,14 @@ void RTFGenerator::endMemberGroup(bool hasHeader) t << "}"; } -void RTFGenerator::startSimpleSect(SectionTypes,const char *file,const char *anchor,const char *title) +void RTFGenerator::startExamples() { - DBG_RTF(t << "{\\comment (startSimpleSect)}" << endl) + DBG_RTF(t << "{\\comment (startExamples)}" << endl) t << "{"; // ends at endDescList t << "{"; // ends at endDescTitle startBold(); newParagraph(); - if (file) - { - writeObjectLink(0,file,anchor,title); - } - else - { - docify(title); - } + docify(theTranslator->trExamples()); endBold(); t << "}"; newParagraph(); @@ -2749,9 +2742,9 @@ void RTFGenerator::startSimpleSect(SectionTypes,const char *file,const char *anc t << rtf_Style_Reset << rtf_DList_DepthStyle(); } -void RTFGenerator::endSimpleSect() +void RTFGenerator::endExamples() { - DBG_RTF(t << "{\\comment (endSimpleSect)}" << endl) + DBG_RTF(t << "{\\comment (endExamples)}" << endl) m_omitParagraph = FALSE; newParagraph(); decrementIndentLevel(); @@ -2802,7 +2795,7 @@ void RTFGenerator::exceptionEntry(const char* prefix,bool closeBracket) { DBG_RTF(t << "{\\comment (exceptionEntry)}" << endl) if (prefix) - t << " " << prefix; + t << " " << prefix << "("; else if (closeBracket) t << ")"; t << " "; diff --git a/src/rtfgen.h b/src/rtfgen.h index bb3146a..b6b32c7 100644 --- a/src/rtfgen.h +++ b/src/rtfgen.h @@ -164,8 +164,8 @@ class RTFGenerator : public OutputGenerator void writeInheritedSectionTitle(const char *,const char *,const char *, const char *,const char *,const char *) {} void startDescList(SectionTypes); - void startSimpleSect(SectionTypes,const char *,const char *,const char *); - void endSimpleSect(); + void startExamples(); + void endExamples(); void startParamList(ParamListTypes,const char *); void endParamList(); //void writeDescItem(); diff --git a/src/scanner.l b/src/scanner.l index 4846132..e9fca43 100644 --- a/src/scanner.l +++ b/src/scanner.l @@ -597,15 +597,11 @@ static int yyread(char *buf,int max_size) /* start command character */ CMD ("\\"|"@") -SECTIONCMD {CMD}("image"|"author"|"internal"|"version"|"date"|"deprecated"|"param"|"exception"|"return"[s]?|"retval"|"bug"|"warning"|"par"|"sa"|"see"|"pre"|"post"|"invariant"|"note"|"remark"[s]?|"todo"|"test"|"xrefitem"|"ingroup"|"callgraph"|"callergraph"|"latexonly"|"htmlonly"|"xmlonly"|"docbookonly"|"manonly"|"{"|"verbatim"|"dotfile"|"dot"|"defgroup"|"addtogroup"|"weakgroup"|"class"|"namespace"|"union"|"struct"|"fn"|"var"|"details"|"typedef"|"def"|"overload")|("<"{PRE}">") BN [ \t\n\r] BL [ \t\r]*"\n" B [ \t] -BS ^(({B}*"//")?)(({B}*"*"+)?){B}* ID "$"?[a-z_A-Z\x80-\xFF][a-z_A-Z0-9\x80-\xFF]* -SCOPEID {ID}({ID}*{BN}*"::"{BN}*)*({ID}?) SCOPENAME "$"?(({ID}?{BN}*"::"{BN}*)*)(((~|!){BN}*)?{ID}) -PHPSCOPENAME ({ID}"\\")+{ID} TSCOPE {ID}("<"[a-z_A-Z0-9 \t\*\&,:]*">")? CSSCOPENAME (({ID}?{BN}*"."{BN}*)*)((~{BN}*)?{ID}) PRE [pP][rR][eE] @@ -3079,6 +3075,10 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) *pCopyQuotedGString+=*yytext; BEGIN( lastStringContext ); } +<CopyGString,CopyPHPGString>"<?php" { // we had an odd number of quotes. + *pCopyQuotedGString += yytext; + BEGIN( lastStringContext ); + } <CopyGString,CopyPHPGString>"/*"|"*/"|"//" { *pCopyQuotedGString+=yytext; } @@ -3840,6 +3840,28 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) else { current->endBodyLine = yyLineNr; + if (current->section == Entry::NAMESPACE_SEC && current->type == "namespace") + { + int split_point; + while ((split_point = current->name.find("::")) != -1) + { + Entry *new_current = new Entry(*current); + current->program = ""; + new_current->doc = ""; + new_current->docLine = 0; + new_current->docFile = ""; + new_current->brief = ""; + new_current->briefLine = 0; + new_current->briefFile = ""; + new_current->name = current->name.mid(split_point + 2); + current->name = current->name.left(split_point); + if (!current_root->name.isEmpty()) current->name.prepend(current_root->name+"::"); + + current_root->addSubEntry(current); + current_root = current; + current = new_current; + } + } QCString &cn = current->name; QCString rn = current_root->name.copy(); //printf("cn=`%s' rn=`%s' isTypedef=%d\n",cn.data(),rn.data(),isTypedef); diff --git a/src/sqlite3gen.cpp b/src/sqlite3gen.cpp index 6cd9581..a7d7f21 100644 --- a/src/sqlite3gen.cpp +++ b/src/sqlite3gen.cpp @@ -23,11 +23,15 @@ #include "qtbc.h" #include "sqlite3gen.h" #include "doxygen.h" +#include "xmlgen.h" +#include "xmldocvisitor.h" #include "config.h" #include "util.h" +#include "outputlist.h" #include "docparser.h" #include "language.h" +#include "version.h" #include "dot.h" #include "arguments.h" #include "classlist.h" @@ -35,65 +39,129 @@ #include "namespacedef.h" #include "filename.h" #include "groupdef.h" +#include "membername.h" +#include "memberdef.h" #include "pagedef.h" #include "dirdef.h" +#include "section.h" +#include <sys/stat.h> #include <qdir.h> #include <string.h> #include <sqlite3.h> -//#define DBG_CTX(x) printf x -#define DBG_CTX(x) do { } while(0) +// enable to show general debug messages +// #define SQLITE3_DEBUG -const char * schema_queries[][2] = { +// enable to print all executed SQL statements. +// I recommend using the smallest possible input list. +// #define SQLITE3_DEBUG_SQL + +# ifdef SQLITE3_DEBUG +# define DBG_CTX(x) printf x +# else // SQLITE3_DEBUG +# define DBG_CTX(x) do { } while(0) +# endif + +# ifdef SQLITE3_DEBUG_SQL +// used by sqlite3_trace in generateSqlite3() +static void sqlLog(void *dbName, const char *sql){ + msg("SQL: '%s'\n", sql); +} +# endif + +const char * table_schema[][2] = { + /* TABLES */ + { "meta", + "CREATE TABLE IF NOT EXISTS meta (\n" + "\t-- Information about this db and how it was generated.\n" + "\t-- Doxygen info\n" + "\tdoxygen_version TEXT PRIMARY KEY NOT NULL,\n" + /* + Doxygen's version is likely to rollover much faster than the schema, and + at least until it becomes a core output format, we might want to make + fairly large schema changes even on minor iterations for Doxygen itself. + If these tools just track a predefined semver schema version that can + iterate independently, it *might* not be as hard to keep them in sync? + */ + "\tschema_version TEXT NOT NULL, -- Schema-specific semver\n" + "\t-- run info\n" + "\tgenerated_at TEXT NOT NULL,\n" + "\tgenerated_on TEXT NOT NULL,\n" + "\t-- project info\n" + "\tproject_name TEXT NOT NULL,\n" + "\tproject_number TEXT,\n" + "\tproject_brief TEXT\n" + ");" + }, { "includes", "CREATE TABLE IF NOT EXISTS includes (\n" "\t-- #include relations.\n" "\trowid INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,\n" "\tlocal INTEGER NOT NULL,\n" - "\tid_src INTEGER NOT NULL, -- File id of the includer.\n" - "\tid_dst INTEGER NOT NULL -- File id of the includee.\n" - ");\n" - "CREATE UNIQUE INDEX idx_includes ON includes\n" - "\t(local, id_src, id_dst);" + "\tsrc_id INTEGER NOT NULL REFERENCES path, -- File id of the includer.\n" + "\tdst_id INTEGER NOT NULL REFERENCES path, -- File id of the includee.\n" + /* + In theory we could include name here to be informationally equivalent + with the XML, but I don't see an obvious use for it. + */ + "\tUNIQUE(local, src_id, dst_id) ON CONFLICT IGNORE\n" + ");" }, - { "innerclass", - "CREATE TABLE IF NOT EXISTS innerclass (\n" + { "contains", + "CREATE TABLE IF NOT EXISTS contains (\n" + "\t-- inner/outer relations (file, namespace, dir, class, group, page)\n" "\trowid INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,\n" - "\trefid INTEGER NOT NULL,\n" - "\tprot INTEGER NOT NULL,\n" - "\tname TEXT NOT NULL\n" - ");" + "\tinner_rowid INTEGER NOT NULL REFERENCES compounddef,\n" + "\touter_rowid INTEGER NOT NULL REFERENCES compounddef\n" + ");" }, - { "files", - "CREATE TABLE IF NOT EXISTS files (\n" - "\t-- Names of source files and includes.\n" - "\tname TEXT PRIMARY KEY NOT NULL\n" - ");" + /* TODO: Path can also share rowids with refid/compounddef/def. (It could + * even collapse into that table...) + * + * I took a first swing at this by changing insertPath() to: + * - accept a FileDef + * - make its own call to insertRefid + * - return a refid struct. + * + * I rolled this back when I had trouble getting a FileDef for all types + * (PageDef in particular). + * + * Note: all colums referencing path would need an update. + */ + { "path", + "CREATE TABLE IF NOT EXISTS path (\n" + "\t-- Paths of source files and includes.\n" + "\trowid INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,\n" + "\ttype INTEGER NOT NULL, -- 1:file 2:dir\n" + "\tlocal INTEGER NOT NULL,\n" + "\tfound INTEGER NOT NULL,\n" + "\tname TEXT NOT NULL\n" + ");" }, - { "refids", - "CREATE TABLE IF NOT EXISTS refids (\n" - "\trefid TEXT PRIMARY KEY NOT NULL\n" - ");" + { "refid", + "CREATE TABLE IF NOT EXISTS refid (\n" + "\t-- Distinct refid for all documented entities.\n" + "\trowid INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,\n" + "\trefid TEXT NOT NULL UNIQUE\n" + ");" }, { "xrefs", "CREATE TABLE IF NOT EXISTS xrefs (\n" - "\t-- Cross reference relation.\n" + "\t-- Cross-reference relation\n" + "\t-- (combines xml <referencedby> and <references> nodes).\n" "\trowid INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,\n" - "\trefid_src INTEGER NOT NULL, -- referrer id.\n" - "\trefid_dst INTEGER NOT NULL, -- referee id.\n" - "\tid_file INTEGER NOT NULL, -- file where the reference is happening.\n" - "\tline INTEGER NOT NULL, -- line where the reference is happening.\n" - "\tcolumn INTEGER NOT NULL -- column where the reference is happening.\n" - ");\n" - "CREATE UNIQUE INDEX idx_xrefs ON xrefs\n" - "\t(refid_src, refid_dst, id_file, line, column);" + "\tsrc_rowid INTEGER NOT NULL REFERENCES refid, -- referrer id.\n" + "\tdst_rowid INTEGER NOT NULL REFERENCES refid, -- referee id.\n" + "\tcontext TEXT NOT NULL, -- inline, argument, initializer\n" + "\t-- Just need to know they link; ignore duplicates.\n" + "\tUNIQUE(src_rowid, dst_rowid, context) ON CONFLICT IGNORE\n" + ");\n" }, { "memberdef", "CREATE TABLE IF NOT EXISTS memberdef (\n" "\t-- All processed identifiers.\n" - "\trowid INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,\n" - "\trefid INTEGER NOT NULL, -- see the refids table\n" + "\trowid INTEGER PRIMARY KEY NOT NULL,\n" "\tname TEXT NOT NULL,\n" "\tdefinition TEXT,\n" "\ttype TEXT,\n" @@ -107,7 +175,7 @@ const char * schema_queries[][2] = { "\tstatic INTEGER DEFAULT 0, -- 0:no 1:yes\n" "\tconst INTEGER DEFAULT 0, -- 0:no 1:yes\n" "\texplicit INTEGER DEFAULT 0, -- 0:no 1:yes\n" - "\tinline INTEGER DEFAULT 0, -- 0:no 1:yes\n" + "\tinline INTEGER DEFAULT 0, -- 0:no 1:yes 2:both (set after encountering inline and not-inline)\n" "\tfinal INTEGER DEFAULT 0, -- 0:no 1:yes\n" "\tsealed INTEGER DEFAULT 0, -- 0:no 1:yes\n" "\tnew INTEGER DEFAULT 0, -- 0:no 1:yes\n" @@ -138,55 +206,71 @@ const char * schema_queries[][2] = { "\taddable INTEGER DEFAULT 0, -- 0:no 1:yes\n" "\tremovable INTEGER DEFAULT 0, -- 0:no 1:yes\n" "\traisable INTEGER DEFAULT 0, -- 0:no 1:yes\n" - /// @todo make a `kind' table - "\tkind INTEGER DEFAULT 0, -- 0:define 1:function 2:variable 3:typedef 4:enum 5:enumvalue 6:signal 7:slot 8:friend 9:DCOP 10:property 11:event\n" + "\tkind TEXT NOT NULL, -- 'macro definition' 'function' 'variable' 'typedef' 'enumeration' 'enumvalue' 'signal' 'slot' 'friend' 'dcop' 'property' 'event' 'interface' 'service'\n" "\tbodystart INTEGER DEFAULT 0, -- starting line of definition\n" "\tbodyend INTEGER DEFAULT 0, -- ending line of definition\n" - "\tid_bodyfile INTEGER DEFAULT 0, -- file of definition\n" - "\tid_file INTEGER NOT NULL, -- file where this identifier is located\n" + "\tbodyfile_id INTEGER REFERENCES path, -- file of definition\n" + "\tfile_id INTEGER NOT NULL REFERENCES path, -- file where this identifier is located\n" "\tline INTEGER NOT NULL, -- line where this identifier is located\n" "\tcolumn INTEGER NOT NULL, -- column where this identifier is located\n" - /// @todo make a `detaileddescription' table "\tdetaileddescription TEXT,\n" "\tbriefdescription TEXT,\n" - "\tinbodydescription TEXT\n" - ");" + "\tinbodydescription TEXT,\n" + "\tFOREIGN KEY (rowid) REFERENCES refid (rowid)\n" + ");" + }, + { "member", + "CREATE TABLE IF NOT EXISTS member (\n" + "\t-- Memberdef <-> containing compound relation.\n" + "\t-- Similar to XML listofallmembers.\n" + "\trowid INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,\n" + "\tscope_rowid INTEGER NOT NULL REFERENCES compounddef,\n" + "\tmemberdef_rowid INTEGER NOT NULL REFERENCES memberdef,\n" + "\tprot INTEGER NOT NULL,\n" + "\tvirt INTEGER NOT NULL,\n" + "\tUNIQUE(scope_rowid, memberdef_rowid)\n" + ");" + }, + { "reimplements", + "CREATE TABLE IF NOT EXISTS reimplements (\n" + "\t-- Inherited member reimplmentation relations.\n" + "\trowid INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,\n" + "\tmemberdef_rowid INTEGER NOT NULL REFERENCES memberdef, -- reimplementing memberdef id.\n" + "\treimplemented_rowid INTEGER NOT NULL REFERENCES memberdef, -- reimplemented memberdef id.\n" + "\tUNIQUE(memberdef_rowid, reimplemented_rowid) ON CONFLICT IGNORE\n" + ");\n" }, { "compounddef", "CREATE TABLE IF NOT EXISTS compounddef (\n" - "\t-- class/struct definitions.\n" - "\trowid INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,\n" - "\tname TEXT NOT NULL,\n" - "\tkind TEXT NOT NULL,\n" - "\trefid INTEGER NOT NULL,\n" - "\tprot INTEGER NOT NULL,\n" - "\tid_file INTEGER NOT NULL,\n" - "\tline INTEGER NOT NULL,\n" - "\tcolumn INTEGER NOT NULL\n" - ");" - }, - { "basecompoundref", - "CREATE TABLE IF NOT EXISTS basecompoundref (\n" - "\trowid INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,\n" - "\tbase TEXT NOT NULL,\n" - "\tderived TEXT NOT NULL,\n" - "\trefid INTEGER NOT NULL,\n" - "\tprot INTEGER NOT NULL,\n" - "\tvirt INTEGER NOT NULL\n" - ");" + "\t-- Class/struct definitions.\n" + "\trowid INTEGER PRIMARY KEY NOT NULL,\n" + "\tname TEXT NOT NULL,\n" + "\ttitle TEXT,\n" + // probably won't be empty '' or unknown, but the source *could* return them... + "\tkind TEXT NOT NULL, -- 'category' 'class' 'constants' 'dir' 'enum' 'example' 'exception' 'file' 'group' 'interface' 'library' 'module' 'namespace' 'package' 'page' 'protocol' 'service' 'singleton' 'struct' 'type' 'union' 'unknown' ''\n" + "\tprot INTEGER,\n" + "\tfile_id INTEGER NOT NULL REFERENCES path,\n" + "\tline INTEGER NOT NULL,\n" + "\tcolumn INTEGER NOT NULL,\n" + "\theader_id INTEGER REFERENCES path,\n" + "\tdetaileddescription TEXT,\n" + "\tbriefdescription TEXT,\n" + "\tFOREIGN KEY (rowid) REFERENCES refid (rowid)\n" + ");" }, - { "derivedcompoundref", - "CREATE TABLE IF NOT EXISTS derivedcompoundref (\n" - "\trowid INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,\n" - "\tbase TEXT NOT NULL,\n" - "\tderived TEXT NOT NULL,\n" - "\trefid INTEGER NOT NULL,\n" - "\tprot INTEGER NOT NULL,\n" - "\tvirt INTEGER NOT NULL\n" - ");" + { "compoundref", + "CREATE TABLE IF NOT EXISTS compoundref (\n" + "\t-- Inheritance relation.\n" + "\trowid INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,\n" + "\tbase_rowid INTEGER NOT NULL REFERENCES compounddef,\n" + "\tderived_rowid INTEGER NOT NULL REFERENCES compounddef,\n" + "\tprot INTEGER NOT NULL,\n" + "\tvirt INTEGER NOT NULL,\n" + "\tUNIQUE(base_rowid, derived_rowid)\n" + ");" }, - { "params", - "CREATE TABLE IF NOT EXISTS params (\n" + { "param", + "CREATE TABLE IF NOT EXISTS param (\n" "\t-- All processed parameters.\n" "\trowid INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,\n" "\tattributes TEXT,\n" @@ -196,24 +280,222 @@ const char * schema_queries[][2] = { "\tarray TEXT,\n" "\tdefval TEXT,\n" "\tbriefdescription TEXT\n" - ");" - "CREATE UNIQUE INDEX idx_params ON params\n" + ");" + "CREATE UNIQUE INDEX idx_param ON param\n" "\t(type, defname);" }, - { "memberdef_params", - "CREATE TABLE IF NOT EXISTS memberdef_params (\n" + { "memberdef_param", + "CREATE TABLE IF NOT EXISTS memberdef_param (\n" "\t-- Junction table for memberdef parameters.\n" "\trowid INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,\n" - "\tid_memberdef INTEGER NOT NULL,\n" - "\tid_param INTEGER NOT NULL\n" - ");" + "\tmemberdef_id INTEGER NOT NULL REFERENCES memberdef,\n" + "\tparam_id INTEGER NOT NULL REFERENCES param\n" + ");" }, - { "innernamespaces", - "CREATE TABLE IF NOT EXISTS innernamespaces (\n" - "\trowid INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,\n" - "\trefid INTEGER NOT NULL,\n" - "\tname TEXT NOT NULL\n" - ");" +}; + const char * view_schema[][2] = { + /* VIEWS * + We'll set these up AFTER we build the database, so that they can be indexed, + but so we don't have to pay a performance penalty for inserts as we build. + */ + { + /* + Makes all reference/relation tables easier to use. For example: + 1. query xrefs and join this view on either xrefs.dst_rowid=def.rowid or + xrefs.src_rowid=def.rowid + 2. get everything you need to output a list of references to/from an entity + + Also supports simple name search/lookup for both compound and member types. + + NOTES: + - summary for compounds generalizes title and briefdescription because + there's no single field that works as a quick introduction for both + pages and classes + - May be value in eventually extending this to fulltext or levenshtein + distance-driven lookup/search, but I'm avoiding these for now as it + takes some effort to enable them. + */ + "def", + "CREATE VIEW IF NOT EXISTS def (\n" + "\t-- Combined summary of all -def types for easier joins.\n" + "\trowid,\n" + "\trefid,\n" + "\tkind,\n" + "\tname,\n" + "\tsummary" + ")\n" + "as SELECT \n" + "\trefid.rowid,\n" + "\trefid.refid,\n" + "\tmemberdef.kind,\n" + "\tmemberdef.name,\n" + "\tmemberdef.briefdescription \n" + "FROM refid \n" + "JOIN memberdef ON refid.rowid=memberdef.rowid \n" + "UNION ALL \n" + "SELECT \n" + "\trefid.rowid,\n" + "\trefid.refid,\n" + "\tcompounddef.kind,\n" + "\tcompounddef.name,\n" + "\tCASE \n" + "\t\tWHEN briefdescription IS NOT NULL \n" + "\t\tTHEN briefdescription \n" + "\t\tELSE title \n" + "\tEND summary\n" + "FROM refid \n" + "JOIN compounddef ON refid.rowid=compounddef.rowid;" + }, + { + "local_file", + "CREATE VIEW IF NOT EXISTS local_file (\n" + "\t-- File paths found within the project.\n" + "\trowid,\n" + "\tfound,\n" + "\tname\n" + ")\n" + "as SELECT \n" + "\tpath.rowid,\n" + "\tpath.found,\n" + "\tpath.name\n" + "FROM path WHERE path.type=1 AND path.local=1 AND path.found=1;\n" + }, + { + "external_file", + "CREATE VIEW IF NOT EXISTS external_file (\n" + "\t-- File paths outside the project (found or not).\n" + "\trowid,\n" + "\tfound,\n" + "\tname\n" + ")\n" + "as SELECT \n" + "\tpath.rowid,\n" + "\tpath.found,\n" + "\tpath.name\n" + "FROM path WHERE path.type=1 AND path.local=0;\n" + }, + { + "inline_xrefs", + "CREATE VIEW IF NOT EXISTS inline_xrefs (\n" + "\t-- Crossrefs from inline member source.\n" + "\trowid,\n" + "\tsrc_rowid,\n" + "\tdst_rowid\n" + ")\n" + "as SELECT \n" + "\txrefs.rowid,\n" + "\txrefs.src_rowid,\n" + "\txrefs.dst_rowid\n" + "FROM xrefs WHERE xrefs.context='inline';\n" + }, + { + "argument_xrefs", + "CREATE VIEW IF NOT EXISTS argument_xrefs (\n" + "\t-- Crossrefs from member def/decl arguments\n" + "\trowid,\n" + "\tsrc_rowid,\n" + "\tdst_rowid\n" + ")\n" + "as SELECT \n" + "\txrefs.rowid,\n" + "\txrefs.src_rowid,\n" + "\txrefs.dst_rowid\n" + "FROM xrefs WHERE xrefs.context='argument';\n" + }, + { + "initializer_xrefs", + "CREATE VIEW IF NOT EXISTS initializer_xrefs (\n" + "\t-- Crossrefs from member initializers\n" + "\trowid,\n" + "\tsrc_rowid,\n" + "\tdst_rowid\n" + ")\n" + "as SELECT \n" + "\txrefs.rowid,\n" + "\txrefs.src_rowid,\n" + "\txrefs.dst_rowid\n" + "FROM xrefs WHERE xrefs.context='initializer';\n" + }, + { + "inner_outer", + "CREATE VIEW IF NOT EXISTS inner_outer\n" + "\t-- Joins 'contains' relations to simplify inner/outer 'rel' queries.\n" + "as SELECT \n" + "\tinner.*,\n" + "\touter.*\n" + "FROM def as inner\n" + "\tJOIN contains ON inner.rowid=contains.inner_rowid\n" + "\tJOIN def AS outer ON outer.rowid=contains.outer_rowid;\n" + }, + { + "rel", + "CREATE VIEW IF NOT EXISTS rel (\n" + "\t-- Boolean indicator of relations available for a given entity.\n" + "\t-- Join to (compound-|member-)def to find fetch-worthy relations.\n" + "\trowid,\n" + "\treimplemented,\n" + "\treimplements,\n" + "\tinnercompounds,\n" + "\toutercompounds,\n" + "\tinnerpages,\n" + "\touterpages,\n" + "\tinnerdirs,\n" + "\touterdirs,\n" + "\tinnerfiles,\n" + "\touterfiles,\n" + "\tinnerclasses,\n" + "\touterclasses,\n" + "\tinnernamespaces,\n" + "\touternamespaces,\n" + "\tinnergroups,\n" + "\toutergroups,\n" + "\tmembers,\n" + "\tcompounds,\n" + "\tsubclasses,\n" + "\tsuperclasses,\n" + "\tlinks_in,\n" + "\tlinks_out,\n" + "\targument_links_in,\n" + "\targument_links_out,\n" + "\tinitializer_links_in,\n" + "\tinitializer_links_out\n" + ")\n" + "as SELECT \n" + "\tdef.rowid,\n" + "\tEXISTS (SELECT rowid FROM reimplements WHERE reimplemented_rowid=def.rowid),\n" + "\tEXISTS (SELECT rowid FROM reimplements WHERE memberdef_rowid=def.rowid),\n" + "\t-- rowid/kind for inner, [rowid:1/kind:1] for outer\n" + "\tEXISTS (SELECT * FROM inner_outer WHERE [rowid:1]=def.rowid),\n" + "\tEXISTS (SELECT * FROM inner_outer WHERE rowid=def.rowid),\n" + "\tEXISTS (SELECT * FROM inner_outer WHERE [rowid:1]=def.rowid AND kind='page'),\n" + "\tEXISTS (SELECT * FROM inner_outer WHERE rowid=def.rowid AND [kind:1]='page'),\n" + "\tEXISTS (SELECT * FROM inner_outer WHERE [rowid:1]=def.rowid AND kind='dir'),\n" + "\tEXISTS (SELECT * FROM inner_outer WHERE rowid=def.rowid AND [kind:1]='dir'),\n" + "\tEXISTS (SELECT * FROM inner_outer WHERE [rowid:1]=def.rowid AND kind='file'),\n" + "\tEXISTS (SELECT * FROM inner_outer WHERE rowid=def.rowid AND [kind:1]='file'),\n" + "\tEXISTS (SELECT * FROM inner_outer WHERE [rowid:1]=def.rowid AND kind in (\n" + "'category','class','enum','exception','interface','module','protocol',\n" + "'service','singleton','struct','type','union'\n" + ")),\n" + "\tEXISTS (SELECT * FROM inner_outer WHERE rowid=def.rowid AND [kind:1] in (\n" + "'category','class','enum','exception','interface','module','protocol',\n" + "'service','singleton','struct','type','union'\n" + ")),\n" + "\tEXISTS (SELECT * FROM inner_outer WHERE [rowid:1]=def.rowid AND kind='namespace'),\n" + "\tEXISTS (SELECT * FROM inner_outer WHERE rowid=def.rowid AND [kind:1]='namespace'),\n" + "\tEXISTS (SELECT * FROM inner_outer WHERE [rowid:1]=def.rowid AND kind='group'),\n" + "\tEXISTS (SELECT * FROM inner_outer WHERE rowid=def.rowid AND [kind:1]='group'),\n" + "\tEXISTS (SELECT rowid FROM member WHERE scope_rowid=def.rowid),\n" + "\tEXISTS (SELECT rowid FROM member WHERE memberdef_rowid=def.rowid),\n" + "\tEXISTS (SELECT rowid FROM compoundref WHERE base_rowid=def.rowid),\n" + "\tEXISTS (SELECT rowid FROM compoundref WHERE derived_rowid=def.rowid),\n" + "\tEXISTS (SELECT rowid FROM inline_xrefs WHERE dst_rowid=def.rowid),\n" + "\tEXISTS (SELECT rowid FROM inline_xrefs WHERE src_rowid=def.rowid),\n" + "\tEXISTS (SELECT rowid FROM argument_xrefs WHERE dst_rowid=def.rowid),\n" + "\tEXISTS (SELECT rowid FROM argument_xrefs WHERE src_rowid=def.rowid),\n" + "\tEXISTS (SELECT rowid FROM initializer_xrefs WHERE dst_rowid=def.rowid),\n" + "\tEXISTS (SELECT rowid FROM initializer_xrefs WHERE src_rowid=def.rowid)\n" + "FROM def ORDER BY def.rowid;" } }; @@ -224,193 +506,298 @@ struct SqlStmt { sqlite3 *db; }; ////////////////////////////////////////////////////// -SqlStmt incl_insert = { "INSERT INTO includes " - "( local, id_src, id_dst ) " - "VALUES " - "(:local,:id_src,:id_dst )" - ,NULL +/* If you add a new statement below, make sure to add it to + prepareStatements(). If sqlite3 is segfaulting (especially in + sqlite3_clear_bindings()), using an un-prepared statement may + be the cause. */ +SqlStmt meta_insert = { + "INSERT INTO meta " + "( doxygen_version, schema_version, generated_at, generated_on, project_name, project_number, project_brief )" + "VALUES " + "(:doxygen_version,:schema_version,:generated_at,:generated_on,:project_name,:project_number,:project_brief )" + ,NULL +}; +////////////////////////////////////////////////////// +SqlStmt incl_insert = { + "INSERT INTO includes " + "( local, src_id, dst_id ) " + "VALUES " + "(:local,:src_id,:dst_id )" + ,NULL }; -SqlStmt incl_select = { "SELECT COUNT(*) FROM includes WHERE " - "local=:local AND id_src=:id_src AND id_dst=:id_dst" - ,NULL +SqlStmt incl_select = { + "SELECT COUNT(*) FROM includes WHERE " + "local=:local AND src_id=:src_id AND dst_id=:dst_id" + ,NULL }; ////////////////////////////////////////////////////// -SqlStmt innerclass_insert={"INSERT INTO innerclass " - "( refid, prot, name )" - "VALUES " - "(:refid,:prot,:name )" - ,NULL +SqlStmt contains_insert={ + "INSERT INTO contains " + "( inner_rowid, outer_rowid )" + "VALUES " + "(:inner_rowid,:outer_rowid )" + ,NULL }; ////////////////////////////////////////////////////// -SqlStmt files_select = {"SELECT rowid FROM files WHERE name=:name" +SqlStmt path_select = { + "SELECT rowid FROM path WHERE name=:name" ,NULL }; -SqlStmt files_insert = {"INSERT INTO files " - "( name )" - "VALUES " - "(:name )" - ,NULL +SqlStmt path_insert = { + "INSERT INTO path " + "( type, local, found, name )" + "VALUES " + "(:type,:local,:found,:name )" + ,NULL }; ////////////////////////////////////////////////////// -SqlStmt refids_select = {"SELECT rowid FROM refids WHERE " - "refid=:refid" - ,NULL +SqlStmt refid_select = { + "SELECT rowid FROM refid WHERE refid=:refid" + ,NULL }; -SqlStmt refids_insert = {"INSERT INTO refids " - "( refid )" - "VALUES " +SqlStmt refid_insert = { + "INSERT INTO refid " + "( refid )" + "VALUES " "(:refid )" - ,NULL + ,NULL }; ////////////////////////////////////////////////////// -SqlStmt xrefs_insert= {"INSERT INTO xrefs " - "( refid_src, refid_dst, id_file, line, column )" - "VALUES " - "(:refid_src,:refid_dst,:id_file,:line,:column )" - ,NULL +SqlStmt xrefs_insert= { + "INSERT INTO xrefs " + "( src_rowid, dst_rowid, context )" + "VALUES " + "(:src_rowid,:dst_rowid,:context )" + ,NULL +};////////////////////////////////////////////////////// +SqlStmt reimplements_insert= { + "INSERT INTO reimplements " + "( memberdef_rowid, reimplemented_rowid )" + "VALUES " + "(:memberdef_rowid,:reimplemented_rowid )" + ,NULL }; ////////////////////////////////////////////////////// -SqlStmt memberdef_insert={"INSERT INTO memberdef " - "(" - "refid," - "name," - "definition," - "type," - "argsstring," - "scope," - "initializer," - "bitfield," - "read," - "write," - "prot," - "static," - "const," - "explicit," - "inline," - "final," - "sealed," - "new," - "optional," - "required," - "volatile," - "virt," - "mutable," - "initonly," - "attribute," - "property," - "readonly," - "bound," - "constrained," - "transient," - "maybevoid," - "maybedefault," - "maybeambiguous," - "readable," - "writable," - "gettable," - "protectedsettable," - "protectedgettable," - "settable," - "privatesettable," - "privategettable," - "accessor," - "addable," - "removable," - "raisable," - "kind," - "bodystart," - "bodyend," - "id_bodyfile," - "id_file," - "line," - "column," - "detaileddescription," - "briefdescription," - "inbodydescription" - ")" - "VALUES " - "(" - ":refid," - ":name," - ":definition," - ":type," - ":argsstring," - ":scope," - ":initializer," - ":bitfield," - ":read," - ":write," - ":prot," - ":static," - ":const," - ":explicit," - ":inline," - ":final," - ":sealed," - ":new," - ":optional," - ":required," - ":volatile," - ":virt," - ":mutable," - ":initonly," - ":attribute," - ":property," - ":readonly," - ":bound," - ":constrained," - ":transient," - ":maybevoid," - ":maybedefault," - ":maybeambiguous," - ":readable," - ":writable," - ":gettable," - ":protectedsettable," - ":protectedgettable," - ":settable," - ":privatesettable," - ":privategettable," - ":accessor," - ":addable," - ":removable," - ":raisable," - ":kind," - ":bodystart," - ":bodyend," - ":id_bodyfile," - ":id_file," - ":line," - ":column," - ":detaileddescription," - ":briefdescription," - ":inbodydescription" - ")" - ,NULL +SqlStmt memberdef_exists={ + "SELECT EXISTS (SELECT * FROM memberdef WHERE rowid = :rowid)" + ,NULL +}; + +SqlStmt memberdef_incomplete={ + "SELECT EXISTS (" + "SELECT * FROM memberdef WHERE " + "rowid = :rowid AND inline != 2 AND inline != :new_inline" + ")" + ,NULL +}; + +SqlStmt memberdef_insert={ + "INSERT INTO memberdef " + "(" + "rowid," + "name," + "definition," + "type," + "argsstring," + "scope," + "initializer," + "bitfield," + "read," + "write," + "prot," + "static," + "const," + "explicit," + "inline," + "final," + "sealed," + "new," + "optional," + "required," + "volatile," + "virt," + "mutable," + "initonly," + "attribute," + "property," + "readonly," + "bound," + "constrained," + "transient," + "maybevoid," + "maybedefault," + "maybeambiguous," + "readable," + "writable," + "gettable," + "protectedsettable," + "protectedgettable," + "settable," + "privatesettable," + "privategettable," + "accessor," + "addable," + "removable," + "raisable," + "kind," + "bodystart," + "bodyend," + "bodyfile_id," + "file_id," + "line," + "column," + "detaileddescription," + "briefdescription," + "inbodydescription" + ")" + "VALUES " + "(" + ":rowid," + ":name," + ":definition," + ":type," + ":argsstring," + ":scope," + ":initializer," + ":bitfield," + ":read," + ":write," + ":prot," + ":static," + ":const," + ":explicit," + ":inline," + ":final," + ":sealed," + ":new," + ":optional," + ":required," + ":volatile," + ":virt," + ":mutable," + ":initonly," + ":attribute," + ":property," + ":readonly," + ":bound," + ":constrained," + ":transient," + ":maybevoid," + ":maybedefault," + ":maybeambiguous," + ":readable," + ":writable," + ":gettable," + ":protectedsettable," + ":protectedgettable," + ":settable," + ":privatesettable," + ":privategettable," + ":accessor," + ":addable," + ":removable," + ":raisable," + ":kind," + ":bodystart," + ":bodyend," + ":bodyfile_id," + ":file_id," + ":line," + ":column," + ":detaileddescription," + ":briefdescription," + ":inbodydescription" + ")" + ,NULL +}; +/* +We have a slightly different need than the XML here. The XML can have two +memberdef nodes with the same refid to document the declaration and the +definition. This doesn't play very nice with a referential model. It isn't a +big issue if only one is documented, but in case both are, we'll fall back on +this kludge to combine them in a single row... +*/ +SqlStmt memberdef_update_decl={ + "UPDATE memberdef SET " + "inline = :inline," + "file_id = :file_id," + "line = :line," + "column = :column," + "detaileddescription = 'Declaration: ' || :detaileddescription || 'Definition: ' || detaileddescription," + "briefdescription = 'Declaration: ' || :briefdescription || 'Definition: ' || briefdescription," + "inbodydescription = 'Declaration: ' || :inbodydescription || 'Definition: ' || inbodydescription " + "WHERE rowid = :rowid" + ,NULL +}; +SqlStmt memberdef_update_def={ + "UPDATE memberdef SET " + "inline = :inline," + "bodystart = :bodystart," + "bodyend = :bodyend," + "bodyfile_id = :bodyfile_id," + "detaileddescription = 'Declaration: ' || detaileddescription || 'Definition: ' || :detaileddescription," + "briefdescription = 'Declaration: ' || briefdescription || 'Definition: ' || :briefdescription," + "inbodydescription = 'Declaration: ' || inbodydescription || 'Definition: ' || :inbodydescription " + "WHERE rowid = :rowid" + ,NULL }; ////////////////////////////////////////////////////// -SqlStmt compounddef_insert={"INSERT INTO compounddef " - "( name, kind, prot, refid, id_file, line, column ) " - "VALUES " - "(:name,:kind,:prot,:refid,:id_file,:line,:column )" - ,NULL +SqlStmt member_insert={ + "INSERT INTO member " + "( scope_rowid, memberdef_rowid, prot, virt ) " + "VALUES " + "(:scope_rowid,:memberdef_rowid,:prot,:virt )" + ,NULL }; ////////////////////////////////////////////////////// -SqlStmt basecompoundref_insert={"INSERT INTO basecompoundref " - "( base, derived, refid, prot, virt ) " - "VALUES " - "(:base,:derived,:refid,:prot,:virt )" - ,NULL +SqlStmt compounddef_insert={ + "INSERT INTO compounddef " + "(" + "rowid," + "name," + "title," + "kind," + "prot," + "file_id," + "line," + "column," + "header_id," + "briefdescription," + "detaileddescription" + ")" + "VALUES " + "(" + ":rowid," + ":name," + ":title," + ":kind," + ":prot," + ":file_id," + ":line," + ":column," + ":header_id," + ":briefdescription," + ":detaileddescription" + ")" + ,NULL +}; +SqlStmt compounddef_exists={ + "SELECT EXISTS (" + "SELECT * FROM compounddef WHERE rowid = :rowid" + ")" + ,NULL }; ////////////////////////////////////////////////////// -SqlStmt derivedcompoundref_insert={"INSERT INTO derivedcompoundref " - "( refid, prot, virt, base, derived ) " - "VALUES " - "(:refid,:prot,:virt,:base,:derived )" - ,NULL +SqlStmt compoundref_insert={ + "INSERT INTO compoundref " + "( base_rowid, derived_rowid, prot, virt ) " + "VALUES " + "(:base_rowid,:derived_rowid,:prot,:virt )" + ,NULL }; ////////////////////////////////////////////////////// -SqlStmt params_select = { "SELECT rowid FROM params WHERE " +SqlStmt param_select = { + "SELECT rowid FROM param WHERE " "(attributes IS NULL OR attributes=:attributes) AND " "(type IS NULL OR type=:type) AND " "(declname IS NULL OR declname=:declname) AND " @@ -418,27 +805,22 @@ SqlStmt params_select = { "SELECT rowid FROM params WHERE " "(array IS NULL OR array=:array) AND " "(defval IS NULL OR defval=:defval) AND " "(briefdescription IS NULL OR briefdescription=:briefdescription)" - ,NULL + ,NULL }; -SqlStmt params_insert = { "INSERT INTO params " - "( attributes, type, declname, defname, array, defval, briefdescription ) " - "VALUES " +SqlStmt param_insert = { + "INSERT INTO param " + "( attributes, type, declname, defname, array, defval, briefdescription ) " + "VALUES " "(:attributes,:type,:declname,:defname,:array,:defval,:briefdescription)" - ,NULL -}; -////////////////////////////////////////////////////// -SqlStmt memberdef_params_insert={ "INSERT INTO memberdef_params " - "( id_memberdef, id_param)" - "VALUES " - "(:id_memberdef,:id_param)" - ,NULL + ,NULL }; ////////////////////////////////////////////////////// -SqlStmt innernamespace_insert={"INSERT INTO innernamespaces " - "( refid, name)" - "VALUES " - "(:refid,:name)", - NULL +SqlStmt memberdef_param_insert={ + "INSERT INTO memberdef_param " + "( memberdef_id, param_id)" + "VALUES " + "(:memberdef_id,:param_id)" + ,NULL }; @@ -491,7 +873,7 @@ static bool bindIntParameter(SqlStmt &s,const char *name,int value) { int idx = sqlite3_bind_parameter_index(s.stmt, name); if (idx==0) { - msg("sqlite3_bind_parameter_index(%s)[%s] failed: %s\n", name, s.query, sqlite3_errmsg(s.db)); + msg("sqlite3_bind_parameter_index(%s)[%s] failed to find column: %s\n", name, s.query, sqlite3_errmsg(s.db)); return false; } int rv = sqlite3_bind_int(s.stmt, idx, value); @@ -508,7 +890,7 @@ static int step(SqlStmt &s,bool getRowId=FALSE, bool select=FALSE) int rc = sqlite3_step(s.stmt); if (rc!=SQLITE_DONE && rc!=SQLITE_ROW) { - msg("sqlite3_step: %s\n", sqlite3_errmsg(s.db)); + DBG_CTX(("sqlite3_step: %s (rc: %d)\n", sqlite3_errmsg(s.db), rc)); sqlite3_reset(s.stmt); sqlite3_clear_bindings(s.stmt); return -1; @@ -520,72 +902,118 @@ static int step(SqlStmt &s,bool getRowId=FALSE, bool select=FALSE) return rowid; } -static int insertFile(const char* name) +static int insertPath(QCString name, bool local=TRUE, bool found=TRUE, int type=1) { int rowid=-1; if (name==0) return rowid; - bindTextParameter(files_select,":name",name); - rowid=step(files_select,TRUE,TRUE); + name = stripFromPath(name); + + bindTextParameter(path_select,":name",name.data(),FALSE); + rowid=step(path_select,TRUE,TRUE); if (rowid==0) { - bindTextParameter(files_insert,":name",name); - rowid=step(files_insert,TRUE); + bindTextParameter(path_insert,":name",name.data(),FALSE); + bindIntParameter(path_insert,":type",type); + bindIntParameter(path_insert,":local",local?1:0); + bindIntParameter(path_insert,":found",found?1:0); + rowid=step(path_insert,TRUE); } return rowid; } -static int insertRefid(const char *refid) +static void recordMetadata() { - int rowid=-1; - if (refid==0) return rowid; + bindTextParameter(meta_insert,":doxygen_version",versionString); + bindTextParameter(meta_insert,":schema_version","0.2.0"); //TODO: this should be a constant somewhere; not sure where + bindTextParameter(meta_insert,":generated_at",dateToString(TRUE), FALSE); + bindTextParameter(meta_insert,":generated_on",dateToString(FALSE), FALSE); + bindTextParameter(meta_insert,":project_name",Config_getString(PROJECT_NAME)); + bindTextParameter(meta_insert,":project_number",Config_getString(PROJECT_NUMBER)); + bindTextParameter(meta_insert,":project_brief",Config_getString(PROJECT_BRIEF)); + step(meta_insert); +} - bindTextParameter(refids_select,":refid",refid); - rowid=step(refids_select,TRUE,TRUE); - if (rowid==0) +struct Refid { + int rowid; + const char *refid; + bool created; +}; + +struct Refid insertRefid(const char *refid) +{ + struct Refid ret; + ret.rowid=-1; + ret.refid=refid; + ret.created = FALSE; + if (refid==0) return ret; + + bindTextParameter(refid_select,":refid",refid); + ret.rowid=step(refid_select,TRUE,TRUE); + if (ret.rowid==0) { - bindTextParameter(refids_insert,":refid",refid); - rowid=step(refids_insert,TRUE); + bindTextParameter(refid_insert,":refid",refid); + ret.rowid=step(refid_insert,TRUE); + ret.created = TRUE; } - return rowid; + + return ret; +} + +static bool memberdefExists(struct Refid refid) +{ + bindIntParameter(memberdef_exists,":rowid",refid.rowid); + int test = step(memberdef_exists,TRUE,TRUE); + return test ? true : false; } +static bool memberdefIncomplete(struct Refid refid, const MemberDef* md) +{ + bindIntParameter(memberdef_incomplete,":rowid",refid.rowid); + bindIntParameter(memberdef_incomplete,":new_inline",md->isInline()); + int test = step(memberdef_incomplete,TRUE,TRUE); + return test ? true : false; +} -static bool insertMemberReference(int refid_src, int refid_dst, - int id_file, int line, int column) +static bool compounddefExists(struct Refid refid) { - if (id_file==-1||refid_src==-1||refid_dst==-1) + bindIntParameter(compounddef_exists,":rowid",refid.rowid); + int test = step(compounddef_exists,TRUE,TRUE); + return test ? true : false; +} + +static bool insertMemberReference(struct Refid src_refid, struct Refid dst_refid, const char *context) +{ + if (src_refid.rowid==-1||dst_refid.rowid==-1) return false; if ( - !bindIntParameter(xrefs_insert,":refid_src",refid_src) || - !bindIntParameter(xrefs_insert,":refid_dst",refid_dst) || - !bindIntParameter(xrefs_insert,":id_file",id_file) || - !bindIntParameter(xrefs_insert,":line",line) || - !bindIntParameter(xrefs_insert,":column",column) + !bindIntParameter(xrefs_insert,":src_rowid",src_refid.rowid) || + !bindIntParameter(xrefs_insert,":dst_rowid",dst_refid.rowid) ) { return false; } + else + { + bindTextParameter(xrefs_insert,":context",context); + } step(xrefs_insert); return true; } -static void insertMemberReference(const MemberDef *src, const MemberDef *dst) +static void insertMemberReference(const MemberDef *src, const MemberDef *dst, const char *context) { - QCString qrefid_dst = dst->getOutputFileBase() + "_1" + dst->anchor(); - QCString qrefid_src = src->getOutputFileBase() + "_1" + src->anchor(); - if (dst->getStartBodyLine()!=-1 && dst->getBodyDef()) - { - int refid_src = insertRefid(qrefid_src.data()); - int refid_dst = insertRefid(qrefid_dst.data()); - int id_file = insertFile("no-file"); // TODO: replace no-file with proper file - insertMemberReference(refid_src,refid_dst,id_file,dst->getStartBodyLine(),-1); - } + QCString qdst_refid = dst->getOutputFileBase() + "_1" + dst->anchor(); + QCString qsrc_refid = src->getOutputFileBase() + "_1" + src->anchor(); + + struct Refid src_refid = insertRefid(qsrc_refid); + struct Refid dst_refid = insertRefid(qdst_refid); + insertMemberReference(src_refid,dst_refid,context); } -static void insertMemberFunctionParams(int id_memberdef, const MemberDef *md, const Definition *def) +static void insertMemberFunctionParams(int memberdef_id, const MemberDef *md, const Definition *def) { ArgumentList *declAl = md->declArgumentList(); ArgumentList *defAl = md->argumentList(); @@ -600,8 +1028,8 @@ static void insertMemberFunctionParams(int id_memberdef, const MemberDef *md, co if (!a->attrib.isEmpty()) { - bindTextParameter(params_select,":attributes",a->attrib.data()); - bindTextParameter(params_insert,":attributes",a->attrib.data()); + bindTextParameter(param_select,":attributes",a->attrib); + bindTextParameter(param_insert,":attributes",a->attrib); } if (!a->type.isEmpty()) { @@ -612,57 +1040,56 @@ static void insertMemberFunctionParams(int id_memberdef, const MemberDef *md, co QCString *s; while ((s=li.current())) { - QCString qrefid_src = md->getOutputFileBase() + "_1" + md->anchor(); - int refid_src = insertRefid(qrefid_src.data()); - int refid_dst = insertRefid(s->data()); - int id_file = insertFile(stripFromPath(def->getDefFileName())); - insertMemberReference(refid_src,refid_dst,id_file,md->getDefLine(),-1); + QCString qsrc_refid = md->getOutputFileBase() + "_1" + md->anchor(); + struct Refid src_refid = insertRefid(qsrc_refid); + struct Refid dst_refid = insertRefid(s->data()); + insertMemberReference(src_refid,dst_refid, "argument"); ++li; } - bindTextParameter(params_select,":type",a->type.data()); - bindTextParameter(params_insert,":type",a->type.data()); + bindTextParameter(param_select,":type",a->type); + bindTextParameter(param_insert,":type",a->type); } if (!a->name.isEmpty()) { - bindTextParameter(params_select,":declname",a->name.data()); - bindTextParameter(params_insert,":declname",a->name.data()); + bindTextParameter(param_select,":declname",a->name); + bindTextParameter(param_insert,":declname",a->name); } if (defArg && !defArg->name.isEmpty() && defArg->name!=a->name) { - bindTextParameter(params_select,":defname",defArg->name.data()); - bindTextParameter(params_insert,":defname",defArg->name.data()); + bindTextParameter(param_select,":defname",defArg->name); + bindTextParameter(param_insert,":defname",defArg->name); } if (!a->array.isEmpty()) { - bindTextParameter(params_select,":array",a->array.data()); - bindTextParameter(params_insert,":array",a->array.data()); + bindTextParameter(param_select,":array",a->array); + bindTextParameter(param_insert,":array",a->array); } if (!a->defval.isEmpty()) { StringList l; linkifyText(TextGeneratorSqlite3Impl(l),def,md->getBodyDef(),md,a->defval); - bindTextParameter(params_select,":defval",a->defval.data()); - bindTextParameter(params_insert,":defval",a->defval.data()); + bindTextParameter(param_select,":defval",a->defval); + bindTextParameter(param_insert,":defval",a->defval); } if (defArg) ++defAli; - int id_param=step(params_select,TRUE,TRUE); - if (id_param==0) { - id_param=step(params_insert,TRUE); + int param_id=step(param_select,TRUE,TRUE); + if (param_id==0) { + param_id=step(param_insert,TRUE); } - if (id_param==-1) { - msg("error INSERT params failed\n"); + if (param_id==-1) { + DBG_CTX(("error INSERT params failed\n")); continue; } - bindIntParameter(memberdef_params_insert,":id_memberdef",id_memberdef); - bindIntParameter(memberdef_params_insert,":id_param",id_param); - step(memberdef_params_insert); + bindIntParameter(memberdef_param_insert,":memberdef_id",memberdef_id); + bindIntParameter(memberdef_param_insert,":param_id",param_id); + step(memberdef_param_insert); } } } -static void insertMemberDefineParams(int id_memberdef,const MemberDef *md, const Definition *def) +static void insertMemberDefineParams(int memberdef_id,const MemberDef *md, const Definition *def) { if (md->argumentList()->count()==0) // special case for "foo()" to // disguish it from "foo". @@ -675,20 +1102,34 @@ static void insertMemberDefineParams(int id_memberdef,const MemberDef *md, const Argument *a; for (ali.toFirst();(a=ali.current());++ali) { - bindTextParameter(params_insert,":defname",a->type.data()); - int id_param=step(params_insert,TRUE); - if (id_param==-1) { - msg("error INSERT param(%s) failed\n", a->type.data()); + bindTextParameter(param_insert,":defname",a->type); + int param_id=step(param_insert,TRUE); + if (param_id==-1) { continue; } - bindIntParameter(memberdef_params_insert,":id_memberdef",id_memberdef); - bindIntParameter(memberdef_params_insert,":id_param",id_param); - step(memberdef_params_insert); + bindIntParameter(memberdef_param_insert,":memberdef_id",memberdef_id); + bindIntParameter(memberdef_param_insert,":param_id",param_id); + step(memberdef_param_insert); } } } +static void associateMember(const MemberDef *md, struct Refid member_refid, struct Refid scope_refid) +{ + // TODO: skip EnumValue only to guard against recording refids and member records + // for enumvalues until we can support documenting them as entities. + if (md->memberType()==MemberType_EnumValue) return; + if (md->name().at(0)!='@') // skip anonymous members + { + bindIntParameter(member_insert, ":scope_rowid", scope_refid.rowid); + bindIntParameter(member_insert, ":memberdef_rowid", member_refid.rowid); + + bindIntParameter(member_insert, ":prot", md->protection()); + bindIntParameter(member_insert, ":virt", md->virtualness()); + step(member_insert); + } +} static void stripQualifiers(QCString &typeStr) { @@ -720,22 +1161,28 @@ static int prepareStatement(sqlite3 *db, SqlStmt &s) static int prepareStatements(sqlite3 *db) { if ( + -1==prepareStatement(db, meta_insert) || + -1==prepareStatement(db, memberdef_exists) || + -1==prepareStatement(db, memberdef_incomplete) || -1==prepareStatement(db, memberdef_insert) || - -1==prepareStatement(db, files_insert) || - -1==prepareStatement(db, files_select) || - -1==prepareStatement(db, refids_insert) || - -1==prepareStatement(db, refids_select) || + -1==prepareStatement(db, memberdef_update_def) || + -1==prepareStatement(db, memberdef_update_decl) || + -1==prepareStatement(db, member_insert) || + -1==prepareStatement(db, path_insert) || + -1==prepareStatement(db, path_select) || + -1==prepareStatement(db, refid_insert) || + -1==prepareStatement(db, refid_select) || -1==prepareStatement(db, incl_insert)|| -1==prepareStatement(db, incl_select)|| - -1==prepareStatement(db, params_insert) || - -1==prepareStatement(db, params_select) || + -1==prepareStatement(db, param_insert) || + -1==prepareStatement(db, param_select) || -1==prepareStatement(db, xrefs_insert) || - -1==prepareStatement(db, innerclass_insert) || + -1==prepareStatement(db, reimplements_insert) || + -1==prepareStatement(db, contains_insert) || + -1==prepareStatement(db, compounddef_exists) || -1==prepareStatement(db, compounddef_insert) || - -1==prepareStatement(db, basecompoundref_insert) || - -1==prepareStatement(db, derivedcompoundref_insert) || - -1==prepareStatement(db, memberdef_params_insert)|| - -1==prepareStatement(db, innernamespace_insert) + -1==prepareStatement(db, compoundref_insert) || + -1==prepareStatement(db, memberdef_param_insert) ) { return -1; @@ -763,15 +1210,35 @@ static void pragmaTuning(sqlite3 *db) sqlite3_exec(db, "PRAGMA temp_store = MEMORY;", NULL, NULL, &sErrMsg); } -static int initializeSchema(sqlite3* db) +static int initializeTables(sqlite3* db) +{ + int rc; + sqlite3_stmt *stmt = 0; + + msg("Initializing DB schema (tables)...\n"); + for (unsigned int k = 0; k < sizeof(table_schema) / sizeof(table_schema[0]); k++) + { + const char *q = table_schema[k][1]; + char *errmsg; + rc = sqlite3_exec(db, q, NULL, NULL, &errmsg); + if (rc != SQLITE_OK) + { + msg("failed to execute query: %s\n\t%s\n", q, errmsg); + return -1; + } + } + return 0; +} + +static int initializeViews(sqlite3* db) { int rc; sqlite3_stmt *stmt = 0; - msg("Initializing DB schema...\n"); - for (unsigned int k = 0; k < sizeof(schema_queries) / sizeof(schema_queries[0]); k++) + msg("Initializing DB schema (views)...\n"); + for (unsigned int k = 0; k < sizeof(view_schema) / sizeof(view_schema[0]); k++) { - const char *q = schema_queries[k][1]; + const char *q = view_schema[k][1]; char *errmsg; rc = sqlite3_exec(db, q, NULL, NULL, &errmsg); if (rc != SQLITE_OK) @@ -784,40 +1251,122 @@ static int initializeSchema(sqlite3* db) } //////////////////////////////////////////// -static void writeInnerClasses(const ClassSDict *cl) +/* TODO: +I collapsed all innerX tables into 'contains', which raises the prospect that +all of these very similar writeInnerX funcs could be refactored into a one, +or a small set of common parts. + +I think the hurdles are: +- picking a first argument that every call location can pass +- which yields a consistent iterator +- accommodates PageDef's slightly different rules for generating the + inner_refid (unless I'm missing a method that would uniformly return + the correct refid for all types). +*/ +static void writeInnerClasses(const ClassSDict *cl, struct Refid outer_refid) { if (!cl) return; ClassSDict::Iterator cli(*cl); - ClassDef *cd; + const ClassDef *cd; for (cli.toFirst();(cd=cli.current());++cli) { if (!cd->isHidden() && cd->name().find('@')==-1) // skip anonymous scopes { - int refid = insertRefid(cd->getOutputFileBase()); - bindIntParameter(innerclass_insert,":refid", refid); - bindIntParameter(innerclass_insert,":prot",cd->protection()); - bindTextParameter(innerclass_insert,":name",cd->name()); - step(innerclass_insert); + struct Refid inner_refid = insertRefid(cd->getOutputFileBase()); + + bindIntParameter(contains_insert,":inner_rowid", inner_refid.rowid); + bindIntParameter(contains_insert,":outer_rowid", outer_refid.rowid); + step(contains_insert); } } } +static void writeInnerPages(const PageSDict *pl, struct Refid outer_refid) +{ + if (!pl) return; + + PageSDict::Iterator pli(*pl); + const PageDef *pd; + for (pli.toFirst();(pd=pli.current());++pli) + { + struct Refid inner_refid = insertRefid( + pd->getGroupDef() ? pd->getOutputFileBase()+"_"+pd->name() : pd->getOutputFileBase() + ); + + bindIntParameter(contains_insert,":inner_rowid", inner_refid.rowid); + bindIntParameter(contains_insert,":outer_rowid", outer_refid.rowid); + step(contains_insert); -static void writeInnerNamespaces(const NamespaceSDict *nl) + } +} + +static void writeInnerGroups(const GroupList *gl, struct Refid outer_refid) +{ + if (gl) + { + GroupListIterator gli(*gl); + const GroupDef *sgd; + for (gli.toFirst();(sgd=gli.current());++gli) + { + struct Refid inner_refid = insertRefid(sgd->getOutputFileBase()); + + bindIntParameter(contains_insert,":inner_rowid", inner_refid.rowid); + bindIntParameter(contains_insert,":outer_rowid", outer_refid.rowid); + step(contains_insert); + } + } +} + +static void writeInnerFiles(const FileList *fl, struct Refid outer_refid) +{ + if (fl) + { + QListIterator<FileDef> fli(*fl); + const FileDef *fd; + for (fli.toFirst();(fd=fli.current());++fli) + { + struct Refid inner_refid = insertRefid(fd->getOutputFileBase()); + + bindIntParameter(contains_insert,":inner_rowid", inner_refid.rowid); + bindIntParameter(contains_insert,":outer_rowid", outer_refid.rowid); + step(contains_insert); + } + } +} + +static void writeInnerDirs(const DirList *dl, struct Refid outer_refid) +{ + if (dl) + { + QListIterator<DirDef> subdirs(*dl); + const DirDef *subdir; + for (subdirs.toFirst();(subdir=subdirs.current());++subdirs) + { + struct Refid inner_refid = insertRefid(subdir->getOutputFileBase()); + + bindIntParameter(contains_insert,":inner_rowid", inner_refid.rowid); + bindIntParameter(contains_insert,":outer_rowid", outer_refid.rowid); + step(contains_insert); + } + } +} + +static void writeInnerNamespaces(const NamespaceSDict *nl, struct Refid outer_refid) { if (nl) { NamespaceSDict::Iterator nli(*nl); - NamespaceDef *nd; + const NamespaceDef *nd; for (nli.toFirst();(nd=nli.current());++nli) { - if (!nd->isHidden() && nd->name().find('@')==-1) // skip anonymouse scopes + if (!nd->isHidden() && nd->name().find('@')==-1) // skip anonymous scopes { - int refid = insertRefid(nd->getOutputFileBase()); - bindIntParameter(innernamespace_insert,":refid",refid); - bindTextParameter(innernamespace_insert,":name",nd->name(),FALSE); - step(innernamespace_insert); + struct Refid inner_refid = insertRefid(nd->getOutputFileBase()); + + bindIntParameter(contains_insert,":inner_rowid",inner_refid.rowid); + bindIntParameter(contains_insert,":outer_rowid",outer_refid.rowid); + step(contains_insert); } } } @@ -837,24 +1386,24 @@ static void writeTemplateArgumentList(const ArgumentList * al, if (!a->type.isEmpty()) { #warning linkifyText(TextGeneratorXMLImpl(t),scope,fileScope,0,a->type); - bindTextParameter(params_select,":type",a->type); - bindTextParameter(params_insert,":type",a->type); + bindTextParameter(param_select,":type",a->type); + bindTextParameter(param_insert,":type",a->type); } if (!a->name.isEmpty()) { - bindTextParameter(params_select,":declname",a->name); - bindTextParameter(params_insert,":declname",a->name); - bindTextParameter(params_select,":defname",a->name); - bindTextParameter(params_insert,":defname",a->name); + bindTextParameter(param_select,":declname",a->name); + bindTextParameter(param_insert,":declname",a->name); + bindTextParameter(param_select,":defname",a->name); + bindTextParameter(param_insert,":defname",a->name); } if (!a->defval.isEmpty()) { #warning linkifyText(TextGeneratorXMLImpl(t),scope,fileScope,0,a->defval); - bindTextParameter(params_select,":defval",a->defval); - bindTextParameter(params_insert,":defval",a->defval); + bindTextParameter(param_select,":defval",a->defval); + bindTextParameter(param_insert,":defval",a->defval); } - if (!step(params_select,TRUE,TRUE)) - step(params_insert); + if (!step(param_select,TRUE,TRUE)) + step(param_insert); } } } @@ -871,15 +1420,132 @@ static void writeTemplateList(const ClassDef *cd) { writeTemplateArgumentList(cd->templateArguments(),cd,0); } + +QCString getSQLDocBlock(const Definition *scope, + const Definition *def, + const QCString &doc, + const QCString &fileName, + int lineNr) +{ + QGString s; + if (doc.isEmpty()) return s.data(); + FTextStream t(&s); + DocNode *root = validatingParseDoc( + fileName, + lineNr, + const_cast<Definition*>(scope), + const_cast<MemberDef*>(reinterpret_cast<const MemberDef*>(def)), + doc, + FALSE, + FALSE + ); + XMLCodeGenerator codeGen(t); + // create a parse tree visitor for XML + XmlDocVisitor *visitor = new XmlDocVisitor(t,codeGen); + root->accept(visitor); + delete visitor; + delete root; + QCString result = convertCharEntitiesToUTF8(s.data()); + return result.data(); +} + +static void getSQLDesc(SqlStmt &s,const char *col,const char *value,const Definition *def) +{ + bindTextParameter( + s, + col, + getSQLDocBlock( + def->getOuterScope(), + def, + value, + def->docFile(), + def->docLine() + ), + FALSE + ); +} //////////////////////////////////////////// +/* (updated Sep 01 2018) +DoxMemberKind and DoxCompoundKind (compound.xsd) gave me some +faulty assumptions about "kind" strings, so I compiled a reference + +The XML schema claims: + DoxMemberKind: (14) + dcop define enum event friend function interface property prototype + service signal slot typedef variable + + DoxCompoundKind: (17) + category class dir example exception file group interface module + namespace page protocol service singleton struct type union + +Member kind comes from MemberDef::memberTypeName() + types.h defines 14 MemberType_*s + _DCOP _Define _Enumeration _EnumValue _Event _Friend _Function _Interface + _Property _Service _Signal _Slot _Typedef _Variable + - xml doesn't include enumvalue here + (but renders enumvalue as) a sub-node of memberdef/templateparamlist + - xml includes 'prototype' that is unlisted here + vestigial? commented out in docsets.cpp and perlmodgen.cpp + MemberDef::memberTypeName() can return 15 strings: + (sorted by MemberType to match above; quoted because whitespace...) + "dcop" "macro definition" "enumeration" "enumvalue" "event" "friend" + "function" "interface" "property" "service" "signal" "slot" "typedef" + "variable" + + Above describes potential values for memberdef.kind + +Compound kind is more complex. *Def::compoundTypeString() + ClassDef kind comes from ::compoundTypeString() + classdef.h defines 9 compound types + Category Class Exception Interface Protocol Service Singleton Struct Union + But ClassDef::compoundTypeString() "could" return 13 strings + - default "unknown" shouldn't actually return + - other 12 can vary by source language; see method for specifics + category class enum exception interface module protocol service + singleton struct type union + + DirDef, FileDef, GroupDef have no method to return a string + tagfile/outputs hard-code kind to 'dir' 'file' or 'group' + + NamespaceDef kind comes from ::compoundTypeString() + NamespaceDef::compoundTypeString() "could" return 6 strings + - default empty ("") string + - other 5 differ by source language + constants library module namespace package + + PageDef also has no method to return a string + - some locations hard-code the kind to 'page' + - others conditionally output 'page' or 'example' + + All together, that's 23 potential strings (21 excl "" and unknown) + "" category class constants dir enum example exception file group + interface library module namespace package page protocol service singleton + struct type union unknown + + Above describes potential values for compounddef.kind + +For reference, there are 35 potential values of def.kind (33 excl "" and unknown): + "" "category" "class" "constants" "dcop" "dir" "enum" "enumeration" + "enumvalue" "event" "example" "exception" "file" "friend" "function" "group" + "interface" "library" "macro definition" "module" "namespace" "package" + "page" "property" "protocol" "service" "signal" "singleton" "slot" "struct" + "type" "typedef" "union" "unknown" "variable" + +This is relevant because the 'def' view generalizes memberdef and compounddef, +and two member+compound kind strings (interface and service) overlap. + +I have no grasp of whether a real user docset would include one or more +member and compound using the interface or service kind. +*/ + ////////////////////////////////////////////////////////////////////////////// -static void generateSqlite3ForMember(const MemberDef *md, const Definition *def) +static void generateSqlite3ForMember(const MemberDef *md, struct Refid scope_refid, const Definition *def) { // + declaration/definition arg lists // + reimplements // + reimplementedBy - // + exceptions + // - exceptions // + const/volatile specifiers // - examples // + source definition @@ -893,18 +1559,102 @@ static void generateSqlite3ForMember(const MemberDef *md, const Definition *def) // enum values are written as part of the enum if (md->memberType()==MemberType_EnumValue) return; if (md->isHidden()) return; - //if (md->name().at(0)=='@') return; // anonymous member - // group members are only visible in their group - //if (def->definitionType()!=Definition::TypeGroup && md->getGroupDef()) return; QCString memType; // memberdef QCString qrefid = md->getOutputFileBase() + "_1" + md->anchor(); - int refid = insertRefid(qrefid.data()); + struct Refid refid = insertRefid(qrefid); + + associateMember(md, refid, scope_refid); + + // compacting duplicate defs + if(!refid.created && memberdefExists(refid) && memberdefIncomplete(refid, md)) + { + /* + For performance, ideal to skip a member we've already added. + Unfortunately, we can have two memberdefs with the same refid documenting + the declaration and definition. memberdefIncomplete() uses the 'inline' + value to figure this out. Once we get to this point, we should *only* be + seeing the *other* type of def/decl, so we'll set inline to a new value (2), + indicating that this entry covers both inline types. + */ + struct SqlStmt memberdef_update; + + // definitions have bodyfile/start/end + if (md->getStartBodyLine()!=-1) + { + memberdef_update = memberdef_update_def; + int bodyfile_id = insertPath(md->getBodyDef()->absFilePath(),!md->getBodyDef()->isReference()); + if (bodyfile_id == -1) + { + sqlite3_clear_bindings(memberdef_update.stmt); + } + else + { + bindIntParameter(memberdef_update,":bodyfile_id",bodyfile_id); + bindIntParameter(memberdef_update,":bodystart",md->getStartBodyLine()); + bindIntParameter(memberdef_update,":bodyend",md->getEndBodyLine()); + } + } + // declarations don't + else + { + memberdef_update = memberdef_update_decl; + if (md->getDefLine() != -1) + { + int file_id = insertPath(md->getDefFileName(),!md->isReference()); + if (file_id!=-1) + { + bindIntParameter(memberdef_update,":file_id",file_id); + bindIntParameter(memberdef_update,":line",md->getDefLine()); + bindIntParameter(memberdef_update,":column",md->getDefColumn()); + } + } + } - bindIntParameter(memberdef_insert,":refid", refid); - bindIntParameter(memberdef_insert,":kind",md->memberType()); + bindIntParameter(memberdef_update, ":rowid", refid.rowid); + // value 2 indicates we've seen "both" inline types. + bindIntParameter(memberdef_update,":inline", 2); + + /* in case both are used, append/prepend descriptions */ + getSQLDesc(memberdef_update,":briefdescription",md->briefDescription(),md); + getSQLDesc(memberdef_update,":detaileddescription",md->documentation(),md); + getSQLDesc(memberdef_update,":inbodydescription",md->inbodyDocumentation(),md); + + step(memberdef_update,TRUE); + + // don't think we need to repeat params; should have from first encounter + + // + source references + // The cross-references in initializers only work when both the src and dst + // are defined. + MemberSDict *mdict = md->getReferencesMembers(); + if (mdict!=0) + { + MemberSDict::IteratorDict mdi(*mdict); + const MemberDef *rmd; + for (mdi.toFirst();(rmd=mdi.current());++mdi) + { + insertMemberReference(md,rmd, "inline"); + } + } + // + source referenced by + mdict = md->getReferencedByMembers(); + if (mdict!=0) + { + MemberSDict::IteratorDict mdi(*mdict); + const MemberDef *rmd; + for (mdi.toFirst();(rmd=mdi.current());++mdi) + { + insertMemberReference(rmd,md, "inline"); + } + } + return; + } + + bindIntParameter(memberdef_insert,":rowid", refid.rowid); + bindTextParameter(memberdef_insert,":kind",md->memberTypeName(),FALSE); bindIntParameter(memberdef_insert,":prot",md->protection()); bindIntParameter(memberdef_insert,":static",md->isStatic()); @@ -973,6 +1723,7 @@ static void generateSqlite3ForMember(const MemberDef *md, const Definition *def) bindIntParameter(memberdef_insert,":settable",md->isSettable()); bindIntParameter(memberdef_insert,":privatesettable",md->isPrivateSettable()); bindIntParameter(memberdef_insert,":protectedsettable",md->isProtectedSettable()); + if (md->isAssign() || md->isCopy() || md->isRetain() || md->isStrong() || md->isWeak()) { @@ -995,6 +1746,18 @@ static void generateSqlite3ForMember(const MemberDef *md, const Definition *def) bindIntParameter(memberdef_insert,":raisable",md->isRaisable()); } + const MemberDef *rmd = md->reimplements(); + if(rmd) + { + QCString qreimplemented_refid = rmd->getOutputFileBase() + "_1" + rmd->anchor(); + + struct Refid reimplemented_refid = insertRefid(qreimplemented_refid); + + bindIntParameter(reimplements_insert,":memberdef_rowid", refid.rowid); + bindIntParameter(reimplements_insert,":reimplemented_rowid", reimplemented_refid.rowid); + step(reimplements_insert,TRUE); + } + // + declaration/definition arg lists if (md->memberType()!=MemberType_Define && md->memberType()!=MemberType_Enumeration @@ -1008,9 +1771,9 @@ static void generateSqlite3ForMember(const MemberDef *md, const Definition *def) stripQualifiers(typeStr); StringList l; linkifyText(TextGeneratorSqlite3Impl(l), def, md->getBodyDef(),md,typeStr); - if (typeStr.data()) + if (typeStr) { - bindTextParameter(memberdef_insert,":type",typeStr.data(),FALSE); + bindTextParameter(memberdef_insert,":type",typeStr,FALSE); } if (md->definition()) @@ -1029,7 +1792,7 @@ static void generateSqlite3ForMember(const MemberDef *md, const Definition *def) // Extract references from initializer if (md->hasMultiLineInitializer() || md->hasOneLineInitializer()) { - bindTextParameter(memberdef_insert,":initializer",md->initializer().data()); + bindTextParameter(memberdef_insert,":initializer",md->initializer()); StringList l; linkifyText(TextGeneratorSqlite3Impl(l),def,md->getBodyDef(),md,md->initializer()); @@ -1044,11 +1807,10 @@ static void generateSqlite3ForMember(const MemberDef *md, const Definition *def) s->data(), md->getBodyDef()->getDefFileName().data(), md->getStartBodyLine())); - QCString qrefid_src = md->getOutputFileBase() + "_1" + md->anchor(); - int refid_src = insertRefid(qrefid_src.data()); - int refid_dst = insertRefid(s->data()); - int id_file = insertFile(stripFromPath(md->getBodyDef()->getDefFileName())); - insertMemberReference(refid_src,refid_dst,id_file,md->getStartBodyLine(),-1); + QCString qsrc_refid = md->getOutputFileBase() + "_1" + md->anchor(); + struct Refid src_refid = insertRefid(qsrc_refid); + struct Refid dst_refid = insertRefid(s->data()); + insertMemberReference(src_refid,dst_refid, "initializer"); } ++li; } @@ -1056,34 +1818,35 @@ static void generateSqlite3ForMember(const MemberDef *md, const Definition *def) if ( md->getScopeString() ) { - bindTextParameter(memberdef_insert,":scope",md->getScopeString().data(),FALSE); + bindTextParameter(memberdef_insert,":scope",md->getScopeString(),FALSE); } // +Brief, detailed and inbody description - bindTextParameter(memberdef_insert,":briefdescription",md->briefDescription(),FALSE); - bindTextParameter(memberdef_insert,":detaileddescription",md->documentation(),FALSE); - bindTextParameter(memberdef_insert,":inbodydescription",md->inbodyDocumentation(),FALSE); + getSQLDesc(memberdef_insert,":briefdescription",md->briefDescription(),md); + getSQLDesc(memberdef_insert,":detaileddescription",md->documentation(),md); + getSQLDesc(memberdef_insert,":inbodydescription",md->inbodyDocumentation(),md); // File location if (md->getDefLine() != -1) { - int id_file = insertFile(stripFromPath(md->getDefFileName())); - if (id_file!=-1) + int file_id = insertPath(md->getDefFileName(),!md->isReference()); + if (file_id!=-1) { - bindIntParameter(memberdef_insert,":id_file",id_file); + bindIntParameter(memberdef_insert,":file_id",file_id); bindIntParameter(memberdef_insert,":line",md->getDefLine()); bindIntParameter(memberdef_insert,":column",md->getDefColumn()); + // definitions also have bodyfile/start/end if (md->getStartBodyLine()!=-1) { - int id_bodyfile = insertFile(stripFromPath(md->getBodyDef()->absFilePath())); - if (id_bodyfile == -1) + int bodyfile_id = insertPath(md->getBodyDef()->absFilePath(),!md->getBodyDef()->isReference()); + if (bodyfile_id == -1) { sqlite3_clear_bindings(memberdef_insert.stmt); } else { - bindIntParameter(memberdef_insert,":id_bodyfile",id_bodyfile); + bindIntParameter(memberdef_insert,":bodyfile_id",bodyfile_id); bindIntParameter(memberdef_insert,":bodystart",md->getStartBodyLine()); bindIntParameter(memberdef_insert,":bodyend",md->getEndBodyLine()); } @@ -1091,16 +1854,16 @@ static void generateSqlite3ForMember(const MemberDef *md, const Definition *def) } } - int id_memberdef=step(memberdef_insert,TRUE); + int memberdef_id=step(memberdef_insert,TRUE); if (isFunc) { - insertMemberFunctionParams(id_memberdef,md,def); + insertMemberFunctionParams(memberdef_id,md,def); } else if (md->memberType()==MemberType_Define && md->argsString()) { - insertMemberDefineParams(id_memberdef,md,def); + insertMemberDefineParams(memberdef_id,md,def); } // + source references @@ -1110,10 +1873,10 @@ static void generateSqlite3ForMember(const MemberDef *md, const Definition *def) if (mdict!=0) { MemberSDict::IteratorDict mdi(*mdict); - MemberDef *rmd; + const MemberDef *rmd; for (mdi.toFirst();(rmd=mdi.current());++mdi) { - insertMemberReference(md,rmd);//,mdi.currentKey()); + insertMemberReference(md,rmd, "inline"); } } // + source referenced by @@ -1121,62 +1884,79 @@ static void generateSqlite3ForMember(const MemberDef *md, const Definition *def) if (mdict!=0) { MemberSDict::IteratorDict mdi(*mdict); - MemberDef *rmd; + const MemberDef *rmd; for (mdi.toFirst();(rmd=mdi.current());++mdi) { - insertMemberReference(rmd,md);//,mdi.currentKey()); + insertMemberReference(rmd,md, "inline"); } } } static void generateSqlite3Section( const Definition *d, const MemberList *ml, + struct Refid scope_refid, const char * /*kind*/, const char * /*header*/=0, const char * /*documentation*/=0) { if (ml==0) return; MemberListIterator mli(*ml); - MemberDef *md; - int count=0; + const MemberDef *md; + for (mli.toFirst();(md=mli.current());++mli) { + // TODO: necessary? just tracking what xmlgen does; xmlgen says: // namespace members are also inserted in the file scope, but // to prevent this duplication in the XML output, we filter those here. if (d->definitionType()!=Definition::TypeFile || md->getNamespaceDef()==0) { - count++; + generateSqlite3ForMember(md, scope_refid, d); } } - if (count==0) return; // empty list - for (mli.toFirst();(md=mli.current());++mli) +} + +static void associateAllClassMembers(const ClassDef *cd, struct Refid scope_refid) +{ + if (cd->memberNameInfoSDict()) { - // namespace members are also inserted in the file scope, but - // to prevent this duplication in the XML output, we filter those here. - //if (d->definitionType()!=Definition::TypeFile || md->getNamespaceDef()==0) + MemberNameInfoSDict::Iterator mnii(*cd->memberNameInfoSDict()); + MemberNameInfo *mni; + for (mnii.toFirst();(mni=mnii.current());++mnii) { - generateSqlite3ForMember(md,d); + MemberNameInfoIterator mii(*mni); + MemberInfo *mi; + for (mii.toFirst();(mi=mii.current());++mii) + { + MemberDef *md = mi->memberDef; + QCString qrefid = md->getOutputFileBase() + "_1" + md->anchor(); + associateMember(md, insertRefid(qrefid), scope_refid); + } } } } - +// many kinds: category class enum exception interface +// module protocol service singleton struct type union +// enum is Java only (and is distinct from enum memberdefs) static void generateSqlite3ForClass(const ClassDef *cd) { + // NOTE: Skeptical about XML's version of these + // 'x' marks missing items XML claims to include + + // + brief description + // + detailed description + // + template argument list(s) + // + include file + // + member groups + // x inheritance DOT diagram // + list of direct super classes // + list of direct sub classes - // + include file // + list of inner classes - // - template argument list(s) - // + member groups + // x collaboration DOT diagram // + list of all members - // - brief description - // - detailed description - // - inheritance DOT diagram - // - collaboration DOT diagram - // - user defined member sections - // - standard member sections - // - detailed member documentation + // x user defined member sections + // x standard member sections + // x detailed member documentation // - examples using the class if (cd->isReference()) return; // skip external references. @@ -1184,43 +1964,86 @@ static void generateSqlite3ForClass(const ClassDef *cd) if (cd->name().find('@')!=-1) return; // skip anonymous compounds. if (cd->templateMaster()!=0) return; // skip generated template instances. - msg("Generating Sqlite3 output for class %s\n",cd->name().data()); + struct Refid refid = insertRefid(cd->getOutputFileBase()); + + // can omit a class that already has a refid + if(!refid.created && compounddefExists(refid)){return;} + + bindIntParameter(compounddef_insert,":rowid", refid.rowid); bindTextParameter(compounddef_insert,":name",cd->name()); + bindTextParameter(compounddef_insert,":title",cd->title(), FALSE); bindTextParameter(compounddef_insert,":kind",cd->compoundTypeString(),FALSE); bindIntParameter(compounddef_insert,":prot",cd->protection()); - int refid = insertRefid(cd->getOutputFileBase()); - bindIntParameter(compounddef_insert,":refid", refid); - int id_file = insertFile(stripFromPath(cd->getDefFileName())); - bindIntParameter(compounddef_insert,":id_file",id_file); + int file_id = insertPath(cd->getDefFileName()); + bindIntParameter(compounddef_insert,":file_id",file_id); bindIntParameter(compounddef_insert,":line",cd->getDefLine()); bindIntParameter(compounddef_insert,":column",cd->getDefColumn()); + // + include file + /* + TODO: I wonder if this can actually be cut (just here) + + We were adding this "include" to the "includes" table alongside + other includes (from a FileDef). However, FileDef and ClassDef are using + "includes" nodes in very a different way: + - With FileDef, it means the file includes another. + - With ClassDef, it means you should include this file to use this class. + + Because of this difference, I added a column to compounddef, header_id, and + linked it back to the appropriate file. We could just add a nullable text + column that would hold a string equivalent to what the HTML docs include, + but the logic for generating it is embedded in + ClassDef::writeIncludeFiles(OutputList &ol). + + That said, at least on the handful of test sets I have, header_id == file_id, + suggesting it could be cut and clients might be able to reconstruct it from + other values if there's a solid heuristic for *when a class will + have a header file*. + */ + IncludeInfo *ii=cd->includeInfo(); + if (ii) + { + QCString nm = ii->includeName; + if (nm.isEmpty() && ii->fileDef) nm = ii->fileDef->docName(); + if (!nm.isEmpty()) + { + int header_id=insertPath(ii->fileDef->absFilePath(),!ii->fileDef->isReference()); + DBG_CTX(("-----> ClassDef includeInfo for %s\n", nm.data())); + DBG_CTX((" local : %d\n", ii->local)); + DBG_CTX((" imported : %d\n", ii->imported)); + DBG_CTX((" indirect : %d\n", ii->indirect)); + DBG_CTX(("header: %s\n", ii->fileDef->absFilePath().data())); + DBG_CTX((" file_id : %d\n", file_id)); + DBG_CTX((" header_id: %d\n", header_id)); + + if(header_id!=-1) + { + bindIntParameter(compounddef_insert,":header_id",header_id); + } + } + } + + getSQLDesc(compounddef_insert,":briefdescription",cd->briefDescription(),cd); + getSQLDesc(compounddef_insert,":detaileddescription",cd->documentation(),cd); + step(compounddef_insert); // + list of direct super classes if (cd->baseClasses()) { BaseClassListIterator bcli(*cd->baseClasses()); - BaseClassDef *bcd; + const BaseClassDef *bcd; for (bcli.toFirst();(bcd=bcli.current());++bcli) { - int refid = insertRefid(bcd->classDef->getOutputFileBase()); - bindIntParameter(basecompoundref_insert,":refid", refid); - bindIntParameter(basecompoundref_insert,":prot",bcd->prot); - bindIntParameter(basecompoundref_insert,":virt",bcd->virt); - - if (!bcd->templSpecifiers.isEmpty()) - { - bindTextParameter(basecompoundref_insert,":base",insertTemplateSpecifierInScope(bcd->classDef->name(),bcd->templSpecifiers),FALSE); - } - else - { - bindTextParameter(basecompoundref_insert,":base",bcd->classDef->displayName(),FALSE); - } - bindTextParameter(basecompoundref_insert,":derived",cd->displayName(),FALSE); - step(basecompoundref_insert); + struct Refid base_refid = insertRefid(bcd->classDef->getOutputFileBase()); + struct Refid derived_refid = insertRefid(cd->getOutputFileBase()); + bindIntParameter(compoundref_insert,":base_rowid", base_refid.rowid); + bindIntParameter(compoundref_insert,":derived_rowid", derived_refid.rowid); + bindIntParameter(compoundref_insert,":prot",bcd->prot); + bindIntParameter(compoundref_insert,":virt",bcd->virt); + step(compoundref_insert); } } @@ -1228,54 +2051,23 @@ static void generateSqlite3ForClass(const ClassDef *cd) if (cd->subClasses()) { BaseClassListIterator bcli(*cd->subClasses()); - BaseClassDef *bcd; + const BaseClassDef *bcd; for (bcli.toFirst();(bcd=bcli.current());++bcli) { - bindTextParameter(derivedcompoundref_insert,":base",cd->displayName(),FALSE); - if (!bcd->templSpecifiers.isEmpty()) - { - bindTextParameter(derivedcompoundref_insert,":derived",insertTemplateSpecifierInScope(bcd->classDef->name(),bcd->templSpecifiers),FALSE); - } - else - { - bindTextParameter(derivedcompoundref_insert,":derived",bcd->classDef->displayName(),FALSE); - } - int refid = insertRefid(bcd->classDef->getOutputFileBase()); - bindIntParameter(derivedcompoundref_insert,":refid", refid); - bindIntParameter(derivedcompoundref_insert,":prot",bcd->prot); - bindIntParameter(derivedcompoundref_insert,":virt",bcd->virt); - step(derivedcompoundref_insert); + struct Refid derived_refid = insertRefid(bcd->classDef->getOutputFileBase()); + struct Refid base_refid = insertRefid(cd->getOutputFileBase()); + bindIntParameter(compoundref_insert,":base_rowid", base_refid.rowid); + bindIntParameter(compoundref_insert,":derived_rowid", derived_refid.rowid); + bindIntParameter(compoundref_insert,":prot",bcd->prot); + bindIntParameter(compoundref_insert,":virt",bcd->virt); + step(compoundref_insert); } } - // + include file - IncludeInfo *ii=cd->includeInfo(); - if (ii) - { - QCString nm = ii->includeName; - if (nm.isEmpty() && ii->fileDef) nm = ii->fileDef->docName(); - if (!nm.isEmpty()) - { - int id_dst=insertFile(nm); - if (id_dst!=-1) { - bindIntParameter(incl_select,":local",ii->local); - bindIntParameter(incl_select,":id_src",id_file); - bindIntParameter(incl_select,":id_dst",id_dst); - int count=step(incl_select,TRUE,TRUE); - if (count==0) - { - bindIntParameter(incl_insert,":local",ii->local); - bindIntParameter(incl_insert,":id_src",id_file); - bindIntParameter(incl_insert,":id_dst",id_dst); - step(incl_insert); - } - } - } - } // + list of inner classes - writeInnerClasses(cd->getClassSDict()); + writeInnerClasses(cd->getClassSDict(),refid); - // - template argument list(s) + // + template argument list(s) writeTemplateList(cd); // + member groups @@ -1285,41 +2077,62 @@ static void generateSqlite3ForClass(const ClassDef *cd) MemberGroup *mg; for (;(mg=mgli.current());++mgli) { - generateSqlite3Section(cd,mg->members(),"user-defined",mg->header(), + generateSqlite3Section(cd,mg->members(),refid,"user-defined",mg->header(), mg->documentation()); } } - // + list of all members + // this is just a list of *local* members QListIterator<MemberList> mli(cd->getMemberLists()); MemberList *ml; for (mli.toFirst();(ml=mli.current());++mli) { if ((ml->listType()&MemberListType_detailedLists)==0) { - generateSqlite3Section(cd,ml,"user-defined");//g_xmlSectionMapper.find(ml->listType())); + generateSqlite3Section(cd,ml,refid,"user-defined"); } } + + // + list of all members + associateAllClassMembers(cd, refid); } +// kinds: constants library module namespace package static void generateSqlite3ForNamespace(const NamespaceDef *nd) { // + contained class definitions // + contained namespace definitions // + member groups // + normal members - // - brief desc - // - detailed desc - // - location + // + brief desc + // + detailed desc + // + location (file_id, line, column) // - files containing (parts of) the namespace definition if (nd->isReference() || nd->isHidden()) return; // skip external references + struct Refid refid = insertRefid(nd->getOutputFileBase()); + if(!refid.created && compounddefExists(refid)){return;} + bindIntParameter(compounddef_insert,":rowid", refid.rowid); + + bindTextParameter(compounddef_insert,":name",nd->name()); + bindTextParameter(compounddef_insert,":title",nd->title(), FALSE); + bindTextParameter(compounddef_insert,":kind","namespace",FALSE); + + int file_id = insertPath(nd->getDefFileName()); + bindIntParameter(compounddef_insert,":file_id",file_id); + bindIntParameter(compounddef_insert,":line",nd->getDefLine()); + bindIntParameter(compounddef_insert,":column",nd->getDefColumn()); + + getSQLDesc(compounddef_insert,":briefdescription",nd->briefDescription(),nd); + getSQLDesc(compounddef_insert,":detaileddescription",nd->documentation(),nd); + + step(compounddef_insert); // + contained class definitions - writeInnerClasses(nd->getClassSDict()); + writeInnerClasses(nd->getClassSDict(),refid); // + contained namespace definitions - writeInnerNamespaces(nd->getNamespaceSDict()); + writeInnerNamespaces(nd->getNamespaceSDict(),refid); // + member groups if (nd->getMemberGroupSDict()) @@ -1328,7 +2141,7 @@ static void generateSqlite3ForNamespace(const NamespaceDef *nd) MemberGroup *mg; for (;(mg=mgli.current());++mgli) { - generateSqlite3Section(nd,mg->members(),"user-defined",mg->header(), + generateSqlite3Section(nd,mg->members(),refid,"user-defined",mg->header(), mg->documentation()); } } @@ -1340,29 +2153,48 @@ static void generateSqlite3ForNamespace(const NamespaceDef *nd) { if ((ml->listType()&MemberListType_declarationLists)!=0) { - generateSqlite3Section(nd,ml,"user-defined");//g_xmlSectionMapper.find(ml->listType())); + generateSqlite3Section(nd,ml,refid,"user-defined"); } } } +// kind: file static void generateSqlite3ForFile(const FileDef *fd) { // + includes files // + includedby files - // - include graph - // - included by graph + // x include graph + // x included by graph // + contained class definitions // + contained namespace definitions // + member groups // + normal members - // - brief desc - // - detailed desc - // - source code - // - location + // + brief desc + // + detailed desc + // x source code + // + location (file_id, line, column) // - number of lines if (fd->isReference()) return; // skip external references + struct Refid refid = insertRefid(fd->getOutputFileBase()); + if(!refid.created && compounddefExists(refid)){return;} + bindIntParameter(compounddef_insert,":rowid", refid.rowid); + + bindTextParameter(compounddef_insert,":name",fd->name(),FALSE); + bindTextParameter(compounddef_insert,":title",fd->title(),FALSE); + bindTextParameter(compounddef_insert,":kind","file",FALSE); + + int file_id = insertPath(fd->getDefFileName()); + bindIntParameter(compounddef_insert,":file_id",file_id); + bindIntParameter(compounddef_insert,":line",fd->getDefLine()); + bindIntParameter(compounddef_insert,":column",fd->getDefColumn()); + + getSQLDesc(compounddef_insert,":briefdescription",fd->briefDescription(),fd); + getSQLDesc(compounddef_insert,":detaileddescription",fd->documentation(),fd); + + step(compounddef_insert); + // + includes files IncludeInfo *ii; if (fd->includeFileList()) @@ -1370,15 +2202,48 @@ static void generateSqlite3ForFile(const FileDef *fd) QListIterator<IncludeInfo> ili(*fd->includeFileList()); for (ili.toFirst();(ii=ili.current());++ili) { - int id_src=insertFile(fd->absFilePath().data()); - int id_dst=insertFile(ii->includeName.data()); + int src_id=insertPath(fd->absFilePath(),!fd->isReference()); + int dst_id; + QCString dst_path; + + if(ii->fileDef) // found file + { + if(ii->fileDef->isReference()) + { + // strip tagfile from path + QCString tagfile = ii->fileDef->getReference(); + dst_path = ii->fileDef->absFilePath().copy(); + dst_path.stripPrefix(tagfile+":"); + } + else + { + dst_path = ii->fileDef->absFilePath(); + } + dst_id = insertPath(dst_path,ii->local); + } + else // can't find file + { + dst_id = insertPath(ii->includeName,ii->local,FALSE); + } + + DBG_CTX(("-----> FileDef includeInfo for %s\n", ii->includeName.data())); + DBG_CTX((" local: %d\n", ii->local)); + DBG_CTX((" imported: %d\n", ii->imported)); + DBG_CTX((" indirect: %d\n", ii->indirect)); + if(ii->fileDef) + { + DBG_CTX(("include: %s\n", ii->fileDef->absFilePath().data())); + } + DBG_CTX((" src_id : %d\n", src_id)); + DBG_CTX((" dst_id: %d\n", dst_id)); + bindIntParameter(incl_select,":local",ii->local); - bindIntParameter(incl_select,":id_src",id_src); - bindIntParameter(incl_select,":id_dst",id_dst); + bindIntParameter(incl_select,":src_id",src_id); + bindIntParameter(incl_select,":dst_id",dst_id); if (step(incl_select,TRUE,TRUE)==0) { bindIntParameter(incl_insert,":local",ii->local); - bindIntParameter(incl_insert,":id_src",id_src); - bindIntParameter(incl_insert,":id_dst",id_dst); + bindIntParameter(incl_insert,":src_id",src_id); + bindIntParameter(incl_insert,":dst_id",dst_id); step(incl_insert); } } @@ -1390,15 +2255,37 @@ static void generateSqlite3ForFile(const FileDef *fd) QListIterator<IncludeInfo> ili(*fd->includedByFileList()); for (ili.toFirst();(ii=ili.current());++ili) { - int id_src=insertFile(ii->includeName); - int id_dst=insertFile(fd->absFilePath()); + int dst_id=insertPath(fd->absFilePath(),!fd->isReference()); + int src_id; + QCString src_path; + + if(ii->fileDef) // found file + { + if(ii->fileDef->isReference()) + { + // strip tagfile from path + QCString tagfile = ii->fileDef->getReference(); + src_path = ii->fileDef->absFilePath().copy(); + src_path.stripPrefix(tagfile+":"); + } + else + { + src_path = ii->fileDef->absFilePath(); + } + src_id = insertPath(src_path,ii->local); + } + else // can't find file + { + src_id = insertPath(ii->includeName,ii->local,FALSE); + } + bindIntParameter(incl_select,":local",ii->local); - bindIntParameter(incl_select,":id_src",id_src); - bindIntParameter(incl_select,":id_dst",id_dst); + bindIntParameter(incl_select,":src_id",src_id); + bindIntParameter(incl_select,":dst_id",dst_id); if (step(incl_select,TRUE,TRUE)==0) { bindIntParameter(incl_insert,":local",ii->local); - bindIntParameter(incl_insert,":id_src",id_src); - bindIntParameter(incl_insert,":id_dst",id_dst); + bindIntParameter(incl_insert,":src_id",src_id); + bindIntParameter(incl_insert,":dst_id",dst_id); step(incl_insert); } } @@ -1407,13 +2294,13 @@ static void generateSqlite3ForFile(const FileDef *fd) // + contained class definitions if (fd->getClassSDict()) { - writeInnerClasses(fd->getClassSDict()); + writeInnerClasses(fd->getClassSDict(),refid); } // + contained namespace definitions if (fd->getNamespaceSDict()) { - writeInnerNamespaces(fd->getNamespaceSDict()); + writeInnerNamespaces(fd->getNamespaceSDict(),refid); } // + member groups @@ -1423,7 +2310,7 @@ static void generateSqlite3ForFile(const FileDef *fd) MemberGroup *mg; for (;(mg=mgli.current());++mgli) { - generateSqlite3Section(fd,mg->members(),"user-defined",mg->header(), + generateSqlite3Section(fd,mg->members(),refid,"user-defined",mg->header(), mg->documentation()); } } @@ -1435,24 +2322,201 @@ static void generateSqlite3ForFile(const FileDef *fd) { if ((ml->listType()&MemberListType_declarationLists)!=0) { - generateSqlite3Section(fd,ml,"user-defined");//g_xmlSectionMapper.find(ml->listType())); + generateSqlite3Section(fd,ml,refid,"user-defined"); } } } +// kind: group static void generateSqlite3ForGroup(const GroupDef *gd) { -#warning WorkInProgress + // + members + // + member groups + // + files + // + classes + // + namespaces + // - packages + // + pages + // + child groups + // - examples + // + brief description + // + detailed description + + if (gd->isReference()) return; // skip external references. + + struct Refid refid = insertRefid(gd->getOutputFileBase()); + if(!refid.created && compounddefExists(refid)){return;} + bindIntParameter(compounddef_insert,":rowid", refid.rowid); + + bindTextParameter(compounddef_insert,":name",gd->name()); + bindTextParameter(compounddef_insert,":title",gd->groupTitle(), FALSE); + bindTextParameter(compounddef_insert,":kind","group",FALSE); + + int file_id = insertPath(gd->getDefFileName()); + bindIntParameter(compounddef_insert,":file_id",file_id); + bindIntParameter(compounddef_insert,":line",gd->getDefLine()); + bindIntParameter(compounddef_insert,":column",gd->getDefColumn()); + + getSQLDesc(compounddef_insert,":briefdescription",gd->briefDescription(),gd); + getSQLDesc(compounddef_insert,":detaileddescription",gd->documentation(),gd); + + step(compounddef_insert); + + // + files + writeInnerFiles(gd->getFiles(),refid); + + // + classes + writeInnerClasses(gd->getClasses(),refid); + + // + namespaces + writeInnerNamespaces(gd->getNamespaces(),refid); + + // + pages + writeInnerPages(gd->getPages(),refid); + + // + groups + writeInnerGroups(gd->getSubGroups(),refid); + + // + member groups + if (gd->getMemberGroupSDict()) + { + MemberGroupSDict::Iterator mgli(*gd->getMemberGroupSDict()); + MemberGroup *mg; + for (;(mg=mgli.current());++mgli) + { + generateSqlite3Section(gd,mg->members(),refid,"user-defined",mg->header(), + mg->documentation()); + } + } + + // + members + QListIterator<MemberList> mli(gd->getMemberLists()); + MemberList *ml; + for (mli.toFirst();(ml=mli.current());++mli) + { + if ((ml->listType()&MemberListType_declarationLists)!=0) + { + generateSqlite3Section(gd,ml,refid,"user-defined"); + } + } } +// kind: dir static void generateSqlite3ForDir(const DirDef *dd) { -#warning WorkInProgress + // + dirs + // + files + // + briefdescription + // + detaileddescription + // + location (below uses file_id, line, column; XML just uses file) + if (dd->isReference()) return; // skip external references + + struct Refid refid = insertRefid(dd->getOutputFileBase()); + if(!refid.created && compounddefExists(refid)){return;} + bindIntParameter(compounddef_insert,":rowid", refid.rowid); + + bindTextParameter(compounddef_insert,":name",dd->displayName()); + bindTextParameter(compounddef_insert,":kind","dir",FALSE); + + int file_id = insertPath(dd->getDefFileName(),TRUE,TRUE,2); + bindIntParameter(compounddef_insert,":file_id",file_id); + + /* + line and column are weird here, but: + - dir goes into compounddef with all of the others + - the semantics would be fine if we set them to NULL here + - but defining line and column as NOT NULL is an important promise + for other compounds, so I don't want to loosen it + + For reference, the queries return 1. + 0 or -1 make more sense, but I see that as a change for DirDef. + */ + bindIntParameter(compounddef_insert,":line",dd->getDefLine()); + bindIntParameter(compounddef_insert,":column",dd->getDefColumn()); + + getSQLDesc(compounddef_insert,":briefdescription",dd->briefDescription(),dd); + getSQLDesc(compounddef_insert,":detaileddescription",dd->documentation(),dd); + + step(compounddef_insert); + + // + files + writeInnerDirs(&dd->subDirs(),refid); + + // + files + writeInnerFiles(dd->getFiles(),refid); } +// kinds: page, example static void generateSqlite3ForPage(const PageDef *pd,bool isExample) { -#warning WorkInProgress + // + name + // + title + // + brief description + // + documentation (detailed description) + // + inbody documentation + // + sub pages + if (pd->isReference()) return; // skip external references. + + // TODO: do we more special handling if isExample? + + QCString qrefid = pd->getOutputFileBase(); + if (pd->getGroupDef()) + { + qrefid+=(QCString)"_"+pd->name(); + } + if (qrefid=="index") qrefid="indexpage"; // to prevent overwriting the generated index page. + + struct Refid refid = insertRefid(qrefid); + + // can omit a page that already has a refid + if(!refid.created && compounddefExists(refid)){return;} + + bindIntParameter(compounddef_insert,":rowid",refid.rowid); + // + name + bindTextParameter(compounddef_insert,":name",pd->name()); + + QCString title; + if (pd==Doxygen::mainPage) // main page is special + { + if (!pd->title().isEmpty() && pd->title().lower()!="notitle") + { + title = filterTitle(convertCharEntitiesToUTF8(Doxygen::mainPage->title())); + } + else + { + title = Config_getString(PROJECT_NAME); + } + } + else + { + SectionInfo *si = Doxygen::sectionDict->find(pd->name()); + if (si) + { + title = si->title; + } + + if(!title){title = pd->title();} + } + + // + title + bindTextParameter(compounddef_insert,":title",title,FALSE); + + bindTextParameter(compounddef_insert,":kind", isExample ? "example" : "page"); + + int file_id = insertPath(pd->getDefFileName()); + + bindIntParameter(compounddef_insert,":file_id",file_id); + bindIntParameter(compounddef_insert,":line",pd->getDefLine()); + bindIntParameter(compounddef_insert,":column",pd->getDefColumn()); + + // + brief description + getSQLDesc(compounddef_insert,":briefdescription",pd->briefDescription(),pd); + // + documentation (detailed description) + getSQLDesc(compounddef_insert,":detaileddescription",pd->documentation(),pd); + + step(compounddef_insert); + // + sub pages + writeInnerPages(pd->getSubPages(),refid); } @@ -1463,6 +2527,7 @@ static sqlite3* openDbConnection() QDir sqlite3Dir(outputDirectory); sqlite3 *db; int rc; + struct stat buf; rc = sqlite3_initialize(); if (rc != SQLITE_OK) @@ -1470,7 +2535,21 @@ static sqlite3* openDbConnection() msg("sqlite3_initialize failed\n"); return NULL; } - rc = sqlite3_open_v2(outputDirectory+"/doxygen_sqlite3.db", &db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, 0); + + + if (stat (outputDirectory+"/doxygen_sqlite3.db", &buf) == 0) + { + msg("doxygen_sqlite3.db already exists! aborting sqlite3 output generation!\n"); + msg("If you wish to re-generate the database, remove or archive the existing copy first.\n"); + return NULL; + } + + rc = sqlite3_open_v2( + outputDirectory+"/doxygen_sqlite3.db", + &db, + SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, + 0 + ); if (rc != SQLITE_OK) { sqlite3_close(db); @@ -1497,10 +2576,16 @@ void generateSqlite3() { return; } + +# ifdef SQLITE3_DEBUG + // debug: show all executed statements + sqlite3_trace(db, &sqlLog, NULL); +# endif + beginTransaction(db); pragmaTuning(db); - if (-1==initializeSchema(db)) + if (-1==initializeTables(db)) return; if ( -1 == prepareStatements(db) ) @@ -1509,9 +2594,11 @@ void generateSqlite3() return; } + recordMetadata(); + // + classes ClassSDict::Iterator cli(*Doxygen::classSDict); - ClassDef *cd; + const ClassDef *cd; for (cli.toFirst();(cd=cli.current());++cli) { msg("Generating Sqlite3 output for class %s\n",cd->name().data()); @@ -1520,7 +2607,7 @@ void generateSqlite3() // + namespaces NamespaceSDict::Iterator nli(*Doxygen::namespaceSDict); - NamespaceDef *nd; + const NamespaceDef *nd; for (nli.toFirst();(nd=nli.current());++nli) { msg("Generating Sqlite3 output for namespace %s\n",nd->name().data()); @@ -1533,7 +2620,7 @@ void generateSqlite3() for (;(fn=fnli.current());++fnli) { FileNameIterator fni(*fn); - FileDef *fd; + const FileDef *fd; for (;(fd=fni.current());++fni) { msg("Generating Sqlite3 output for file %s\n",fd->name().data()); @@ -1543,7 +2630,7 @@ void generateSqlite3() // + groups GroupSDict::Iterator gli(*Doxygen::groupSDict); - GroupDef *gd; + const GroupDef *gd; for (;(gd=gli.current());++gli) { msg("Generating Sqlite3 output for group %s\n",gd->name().data()); @@ -1553,7 +2640,7 @@ void generateSqlite3() // + page { PageSDict::Iterator pdi(*Doxygen::pageSDict); - PageDef *pd=0; + const PageDef *pd=0; for (pdi.toFirst();(pd=pdi.current());++pdi) { msg("Generating Sqlite3 output for page %s\n",pd->name().data()); @@ -1563,7 +2650,7 @@ void generateSqlite3() // + dirs { - DirDef *dir; + const DirDef *dir; DirSDict::Iterator sdi(*Doxygen::directories); for (sdi.toFirst();(dir=sdi.current());++sdi) { @@ -1575,7 +2662,7 @@ void generateSqlite3() // + examples { PageSDict::Iterator pdi(*Doxygen::exampleSDict); - PageDef *pd=0; + const PageDef *pd=0; for (pdi.toFirst();(pd=pdi.current());++pdi) { msg("Generating Sqlite3 output for example %s\n",pd->name().data()); @@ -1590,6 +2677,11 @@ void generateSqlite3() generateSqlite3ForPage(Doxygen::mainPage,FALSE); } + // TODO: copied from initializeSchema; not certain if we should say/do more + // if there's a failure here? + if (-1==initializeViews(db)) + return; + endTransaction(db); } diff --git a/src/tagreader.cpp b/src/tagreader.cpp index cf64a35..942c55b 100644 --- a/src/tagreader.cpp +++ b/src/tagreader.cpp @@ -18,6 +18,7 @@ #include "tagreader.h" +#include <assert.h> #include <stdio.h> #include <stdarg.h> @@ -95,8 +96,8 @@ class TagMemberInfo class TagClassInfo { public: - enum Kind { Class, Struct, Union, Interface, Exception, Protocol, Category, Enum, Service, Singleton }; - TagClassInfo() { bases=0, templateArguments=0; members.setAutoDelete(TRUE); isObjC=FALSE; } + enum Kind { None=-1, Class, Struct, Union, Interface, Exception, Protocol, Category, Enum, Service, Singleton }; + TagClassInfo() { bases=0, templateArguments=0; members.setAutoDelete(TRUE); isObjC=FALSE; kind = None; } ~TagClassInfo() { delete bases; delete templateArguments; } QCString name; QCString filename; @@ -1322,6 +1323,9 @@ void TagFileParser::buildLists(Entry *root) case TagClassInfo::Category: ce->spec = Entry::Category; break; case TagClassInfo::Service: ce->spec = Entry::Service; break; case TagClassInfo::Singleton: ce->spec = Entry::Singleton; break; + case TagClassInfo::None: // should never happen, means not properly initialized + assert(tci->kind != TagClassInfo::None); + break; } ce->name = tci->name; if (tci->kind==TagClassInfo::Protocol) diff --git a/src/tclscanner.l b/src/tclscanner.l index 7ca5ade..ca5294b 100644 --- a/src/tclscanner.l +++ b/src/tclscanner.l @@ -1431,7 +1431,6 @@ tcl_inf("(%d) ?%s?\n",what,tcl.string_last.data()); yyless(0); tcl_inf("(.%d) ?%s?\n",what,tcl.string_last.data()); return; - myWhite=0; break; default: tcl_err("wrong state: %d\n",what); diff --git a/src/types.h b/src/types.h index e58c8fc..d6f0342 100644 --- a/src/types.h +++ b/src/types.h @@ -227,7 +227,8 @@ class LocalToc Html = 0, // index / also to be used as bit position in mask (1 << Html) Latex = 1, // ... Xml = 2, // ... - numTocTypes = 3 // number of enum values + Docbook = 3, // ... + numTocTypes = 4 // number of enum values }; LocalToc() : m_mask(None) { memset(m_level,0,sizeof(m_level)); } @@ -247,15 +248,22 @@ class LocalToc m_mask|=(1<<Xml); m_level[Xml]=level; } + void enableDocbook(int level) + { + m_mask|=(1<<Docbook); + m_level[Docbook]=level; + } // getters bool isHtmlEnabled() const { return (m_mask & (1<<Html))!=0; } bool isLatexEnabled() const { return (m_mask & (1<<Latex))!=0; } bool isXmlEnabled() const { return (m_mask & (1<<Xml))!=0; } + bool isDocbookEnabled() const { return (m_mask & (1<<Docbook))!=0; } bool nothingEnabled() const { return m_mask == None; } int htmlLevel() const { return m_level[Html]; } int latexLevel() const { return m_level[Latex]; } int xmlLevel() const { return m_level[Xml]; } + int docbookLevel() const { return m_level[Docbook]; } int mask() const { return m_mask; } private: diff --git a/src/util.cpp b/src/util.cpp index b387a84..c931214 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -251,6 +251,7 @@ void writePageRef(OutputDocInterface &od,const char *cn,const char *mn) od.disable(OutputGenerator::Html); od.disable(OutputGenerator::Man); + od.disable(OutputGenerator::Docbook); if (Config_getBool(PDF_HYPERLINKS)) od.disable(OutputGenerator::Latex); if (Config_getBool(RTF_HYPERLINKS)) od.disable(OutputGenerator::RTF); od.startPageRef(); @@ -2215,6 +2216,7 @@ void writeExample(OutputList &ol,ExampleSDict *ed) //if (latexEnabled) ol.disable(OutputGenerator::Latex); ol.disable(OutputGenerator::Latex); ol.disable(OutputGenerator::RTF); + ol.disable(OutputGenerator::Docbook); // link for Html / man //printf("writeObjectLink(file=%s)\n",e->file.data()); ol.writeObjectLink(0,e->file,e->anchor,e->name); @@ -2591,7 +2593,7 @@ QCString dateToString(bool includeTime) static bool warnedOnce=FALSE; if (!warnedOnce) { - warn_uncond("Environment variable SOURCE_DATA_EPOCH must have a value smaller than or equal to %llu; actual value %llu\n",UINT_MAX,epoch); + warn_uncond("Environment variable SOURCE_DATE_EPOCH must have a value smaller than or equal to %llu; actual value %llu\n",UINT_MAX,epoch); warnedOnce=TRUE; } } @@ -2665,7 +2667,7 @@ Protection classInheritedProtectionLevel(ClassDef *cd,ClassDef *bcd,Protection p if (level==256) { err("Internal inconsistency: found class %s seem to have a recursive " - "inheritance relation! Please send a bug report to dimitri@stack.nl\n",cd->name().data()); + "inheritance relation! Please send a bug report to doxygen@gmail.com\n",cd->name().data()); } else if (cd->baseClasses()) { @@ -5932,6 +5934,66 @@ QCString convertToXML(const char *s) return growBuf.get(); } +/*! Converts a string to an DocBook-encoded string */ +QCString convertToDocBook(const char *s) +{ + static GrowBuf growBuf; + growBuf.clear(); + if (s==0) return ""; + const unsigned char *q; + int cnt; + const unsigned char *p=(const unsigned char *)s; + char c; + while ((c=*p++)) + { + switch (c) + { + case '<': growBuf.addStr("<"); break; + case '>': growBuf.addStr(">"); break; + case '&': // possibility to have a special symbol + q = p; + cnt = 2; // we have to count & and ; as well + while ((*q >= 'a' && *q <= 'z') || (*q >= 'A' && *q <= 'Z') || (*q >= '0' && *q <= '9')) + { + cnt++; + q++; + } + if (*q == ';') + { + --p; // we need & as well + DocSymbol::SymType res = HtmlEntityMapper::instance()->name2sym(QCString((char *)p).left(cnt)); + if (res == DocSymbol::Sym_Unknown) + { + p++; + growBuf.addStr("&"); + } + else + { + growBuf.addStr(HtmlEntityMapper::instance()->docbook(res)); + q++; + p = q; + } + } + else + { + growBuf.addStr("&"); + } + break; + case '\'': growBuf.addStr("'"); break; + case '"': growBuf.addStr("""); break; + case '\007': growBuf.addStr("␇"); break; + case 1: case 2: case 3: case 4: case 5: case 6: case 8: + case 11: case 12: case 13: case 14: case 15: case 16: case 17: case 18: + case 19: case 20: case 21: case 22: case 23: case 24: case 25: case 26: + case 27: case 28: case 29: case 30: case 31: + break; // skip invalid XML characters (see http://www.w3.org/TR/2000/REC-xml-20001006#NT-Char) + default: growBuf.addChar(c); break; + } + } + growBuf.addChar(0); + return growBuf.get(); +} + /*! Converts a string to a HTML-encoded string */ QCString convertToHtml(const char *s,bool keepEntities) { @@ -6964,6 +7026,25 @@ QCString latexEscapePDFString(const char *s) return result.data(); } +QCString latexFilterURL(const char *s) +{ + QGString result; + FTextStream t(&result); + const char *p=s; + char c; + while ((c=*p++)) + { + switch (c) + { + case '#': t << "\\#"; break; + default: + t << c; + break; + } + } + return result.data(); +} + QCString rtfFormatBmkStr(const char *name) { @@ -284,6 +284,8 @@ QCString convertToLaTeX(const QCString &s,bool insideTabbing=FALSE,bool keepSpac QCString convertToXML(const char *s); +QCString convertToDocBook(const char *s); + QCString convertToJSString(const char *s, bool applyTextDir = true); QCString getOverloadDocs(); @@ -346,6 +348,7 @@ void filterLatexString(FTextStream &t,const char *str, QCString latexEscapeLabelName(const char *s,bool insideTabbing); QCString latexEscapeIndexChars(const char *s,bool insideTabbing); QCString latexEscapePDFString(const char *s); +QCString latexFilterURL(const char *s); QCString rtfFormatBmkStr(const char *name); diff --git a/src/vhdlcode.l b/src/vhdlcode.l index 68dcafb..ee0731f 100644 --- a/src/vhdlcode.l +++ b/src/vhdlcode.l @@ -370,7 +370,7 @@ static void codifyLines(const char *text,const char *cl=0,bool classlink=FALSE,b //g_code->codify(sp); if (comment) { - writeFont("keyword",line.data()); + writeFont("comment",line.data()); } else { @@ -381,7 +381,7 @@ static void codifyLines(const char *text,const char *cl=0,bool classlink=FALSE,b else { if (comment) - writeFont("keyword",sp); + writeFont("comment",sp); else writeWord(sp,cl,classlink); done=TRUE; @@ -1478,11 +1478,11 @@ XILINX "INST"|"NET"|"PIN"|"BLKNM"|"BUFG"|"COLLAPSE"|"CPLD"|"COMPGRP"|"CONFI writeFont("keyword",vhdlcodeYYtext); } -<Bases>^{B}*{XILINX}[^\n]* { - writeWord(yytext); - //codifyLines(vhdlcodeYYtext,g_CurrClass.data(),TRUE); - } - +<Bases>^{B}*{XILINX}/[^a-zA-Z0-9_] { + writeWord(yytext); + //codifyLines(vhdlcodeYYtext,g_CurrClass.data(),TRUE); + } + <Bases>^{B}*"set_"[^\n]* { writeWord(yytext); } @@ -1497,37 +1497,38 @@ XILINX "INST"|"NET"|"PIN"|"BLKNM"|"BUFG"|"COLLAPSE"|"CPLD"|"COMPGRP"|"CONFI } <*>\n{TEXTT} { // found normal or special comment on its own line - QCString text(vhdlcodeYYtext); - int i=text.find("--"); - if (text.mid(i,3)=="--!" && // hide special comment - Config_getBool(STRIP_CODE_COMMENTS)) - { - g_yyLineNr++; // skip complete line - } - else // normal comment - { - // startFontClass("keyword"); - codifyLines(text,0,FALSE,TRUE); - // endFontClass(); - } + QCString text(vhdlcodeYYtext); + int i=text.find("--"); + if (text.mid(i,3)=="--!") // && // hide special comment + { + if (!Config_getBool(STRIP_CODE_COMMENTS)) + { + codifyLines(text,0,FALSE,TRUE); + } + g_yyLineNr++; // skip complete line + } + else // normal comment + { + codifyLines(text,0,FALSE,TRUE); + } } <*>{TEXTT} { // found normal or special comment after something - QCString text(vhdlcodeYYtext); - int i=text.find("--"); - if (text.mid(i,3)=="--!" && - Config_getBool(STRIP_CODE_COMMENTS)) - { - // hide special comment - } - else // normal comment - { - // startFontClass("keyword"); - codifyLines(text,0,FALSE,TRUE); - // endFontClass(); - } + QCString text(vhdlcodeYYtext); + int i=text.find("--"); + if (text.mid(i,3)=="--!") + { + // hide special comment + if (!Config_getBool(STRIP_CODE_COMMENTS)) + { + codifyLines(text,0,FALSE,TRUE); + } + } + else // normal comment + { + codifyLines(text,0,FALSE,TRUE); + } } - %% /*@ ---------------------------------------------------------------------------- diff --git a/src/vhdldocgen.cpp b/src/vhdldocgen.cpp index 287565b..373e6de 100644 --- a/src/vhdldocgen.cpp +++ b/src/vhdldocgen.cpp @@ -602,7 +602,7 @@ const char* g_vhdlKeyWordMap1[] = { "natural","unsigned","signed","string","boolean", "bit","bit_vector","character", "std_ulogic","std_ulogic_vector","std_logic","std_logic_vector","integer", - "real","float","ufixed","sfixed","time",0 + "real","float","ufixed","sfixed","time","positive",0 }; // logic @@ -667,7 +667,7 @@ const char* g_vhdlKeyWordMap3[] = QCString* VhdlDocGen::findKeyWord(const QCString& tmp) { static QCString vhdlkeyword("vhdlkeyword"); - static QCString vhdltype("comment"); + static QCString vhdltype("keywordtype"); static QCString vhdllogic("vhdllogic"); static QCString preprocessor("keywordflow"); diff --git a/src/xmldocvisitor.cpp b/src/xmldocvisitor.cpp index 93765b1..525dbf5 100644 --- a/src/xmldocvisitor.cpp +++ b/src/xmldocvisitor.cpp @@ -65,7 +65,7 @@ static void visitPreStart(FTextStream &t, const char *cmd, const bool doCaption, { t << " width=\"" << convertToXML(width) << "\""; } - else if (!height.isEmpty()) + if (!height.isEmpty()) { t << " height=\"" << convertToXML(height) << "\""; } @@ -164,6 +164,12 @@ void XmlDocVisitor::visit(DocStyleChange *s) case DocStyleChange::Bold: if (s->enable()) m_t << "<bold>"; else m_t << "</bold>"; break; + case DocStyleChange::Strike: + if (s->enable()) m_t << "<strike>"; else m_t << "</strike>"; + break; + case DocStyleChange::Underline: + if (s->enable()) m_t << "<underline>"; else m_t << "</underline>"; + break; case DocStyleChange::Italic: if (s->enable()) m_t << "<emphasis>"; else m_t << "</emphasis>"; break; diff --git a/src/xmlgen.cpp b/src/xmlgen.cpp index e68c454..e003319 100644 --- a/src/xmlgen.cpp +++ b/src/xmlgen.cpp @@ -222,146 +222,117 @@ class TextGeneratorXMLImpl : public TextGeneratorIntf /** Generator for producing XML formatted source code. */ -class XMLCodeGenerator : public CodeOutputInterface +void XMLCodeGenerator::codify(const char *text) { - public: - - XMLCodeGenerator(FTextStream &t) : m_t(t), m_lineNumber(-1), m_isMemberRef(FALSE), m_col(0), - m_insideCodeLine(FALSE), m_normalHLNeedStartTag(TRUE), m_insideSpecialHL(FALSE) {} - virtual ~XMLCodeGenerator() { } - - void codify(const char *text) - { - XML_DB(("(codify \"%s\")\n",text)); - if (m_insideCodeLine && !m_insideSpecialHL && m_normalHLNeedStartTag) - { - m_t << "<highlight class=\"normal\">"; - m_normalHLNeedStartTag=FALSE; - } - writeXMLCodeString(m_t,text,m_col); - } - void writeCodeLink(const char *ref,const char *file, - const char *anchor,const char *name, - const char *tooltip) - { - XML_DB(("(writeCodeLink)\n")); - if (m_insideCodeLine && !m_insideSpecialHL && m_normalHLNeedStartTag) - { - m_t << "<highlight class=\"normal\">"; - m_normalHLNeedStartTag=FALSE; - } - writeXMLLink(m_t,ref,file,anchor,name,tooltip); - m_col+=qstrlen(name); - } - void writeTooltip(const char *, const DocLinkInfo &, const char *, - const char *, const SourceLinkInfo &, const SourceLinkInfo & - ) - { - XML_DB(("(writeToolTip)\n")); - } - void startCodeLine(bool) - { - XML_DB(("(startCodeLine)\n")); - m_t << "<codeline"; - if (m_lineNumber!=-1) - { - m_t << " lineno=\"" << m_lineNumber << "\""; - if (!m_refId.isEmpty()) - { - m_t << " refid=\"" << m_refId << "\""; - if (m_isMemberRef) - { - m_t << " refkind=\"member\""; - } - else - { - m_t << " refkind=\"compound\""; - } - } - if (!m_external.isEmpty()) - { - m_t << " external=\"" << m_external << "\""; - } - } - m_t << ">"; - m_insideCodeLine=TRUE; - m_col=0; - } - void endCodeLine() - { - XML_DB(("(endCodeLine)\n")); - if (!m_insideSpecialHL && !m_normalHLNeedStartTag) - { - m_t << "</highlight>"; - m_normalHLNeedStartTag=TRUE; - } - m_t << "</codeline>" << endl; // non DocBook - m_lineNumber = -1; - m_refId.resize(0); - m_external.resize(0); - m_insideCodeLine=FALSE; - } - void startFontClass(const char *colorClass) + XML_DB(("(codify \"%s\")\n",text)); + if (m_insideCodeLine && !m_insideSpecialHL && m_normalHLNeedStartTag) + { + m_t << "<highlight class=\"normal\">"; + m_normalHLNeedStartTag=FALSE; + } + writeXMLCodeString(m_t,text,m_col); +} +void XMLCodeGenerator::writeCodeLink(const char *ref,const char *file, + const char *anchor,const char *name, + const char *tooltip) +{ + XML_DB(("(writeCodeLink)\n")); + if (m_insideCodeLine && !m_insideSpecialHL && m_normalHLNeedStartTag) + { + m_t << "<highlight class=\"normal\">"; + m_normalHLNeedStartTag=FALSE; + } + writeXMLLink(m_t,ref,file,anchor,name,tooltip); + m_col+=qstrlen(name); +} +void XMLCodeGenerator::writeTooltip(const char *, const DocLinkInfo &, const char *, + const char *, const SourceLinkInfo &, const SourceLinkInfo & + ) +{ + XML_DB(("(writeToolTip)\n")); +} +void XMLCodeGenerator::startCodeLine(bool) +{ + XML_DB(("(startCodeLine)\n")); + m_t << "<codeline"; + if (m_lineNumber!=-1) + { + m_t << " lineno=\"" << m_lineNumber << "\""; + if (!m_refId.isEmpty()) { - XML_DB(("(startFontClass)\n")); - if (m_insideCodeLine && !m_insideSpecialHL && !m_normalHLNeedStartTag) + m_t << " refid=\"" << m_refId << "\""; + if (m_isMemberRef) { - m_t << "</highlight>"; - m_normalHLNeedStartTag=TRUE; + m_t << " refkind=\"member\""; } - m_t << "<highlight class=\"" << colorClass << "\">"; // non DocBook - m_insideSpecialHL=TRUE; - } - void endFontClass() - { - XML_DB(("(endFontClass)\n")); - m_t << "</highlight>"; // non DocBook - m_insideSpecialHL=FALSE; - } - void writeCodeAnchor(const char *) - { - XML_DB(("(writeCodeAnchor)\n")); - } - void writeLineNumber(const char *extRef,const char *compId, - const char *anchorId,int l) - { - XML_DB(("(writeLineNumber)\n")); - // we remember the information provided here to use it - // at the <codeline> start tag. - m_lineNumber = l; - if (compId) + else { - m_refId=compId; - if (anchorId) m_refId+=(QCString)"_1"+anchorId; - m_isMemberRef = anchorId!=0; - if (extRef) m_external=extRef; + m_t << " refkind=\"compound\""; } } - void setCurrentDoc(Definition *,const char *,bool) - { - } - void addWord(const char *,bool) + if (!m_external.isEmpty()) { + m_t << " external=\"" << m_external << "\""; } - - void finish() - { - if (m_insideCodeLine) endCodeLine(); - } - - private: - FTextStream &m_t; - QCString m_refId; - QCString m_external; - int m_lineNumber; - bool m_isMemberRef; - int m_col; - - bool m_insideCodeLine; - bool m_normalHLNeedStartTag; - bool m_insideSpecialHL; -}; - + } + m_t << ">"; + m_insideCodeLine=TRUE; + m_col=0; +} +void XMLCodeGenerator::endCodeLine() +{ + XML_DB(("(endCodeLine)\n")); + if (!m_insideSpecialHL && !m_normalHLNeedStartTag) + { + m_t << "</highlight>"; + m_normalHLNeedStartTag=TRUE; + } + m_t << "</codeline>" << endl; // non DocBook + m_lineNumber = -1; + m_refId.resize(0); + m_external.resize(0); + m_insideCodeLine=FALSE; +} +void XMLCodeGenerator::startFontClass(const char *colorClass) +{ + XML_DB(("(startFontClass)\n")); + if (m_insideCodeLine && !m_insideSpecialHL && !m_normalHLNeedStartTag) + { + m_t << "</highlight>"; + m_normalHLNeedStartTag=TRUE; + } + m_t << "<highlight class=\"" << colorClass << "\">"; // non DocBook + m_insideSpecialHL=TRUE; +} +void XMLCodeGenerator::endFontClass() +{ + XML_DB(("(endFontClass)\n")); + m_t << "</highlight>"; // non DocBook + m_insideSpecialHL=FALSE; +} +void XMLCodeGenerator::writeCodeAnchor(const char *) +{ + XML_DB(("(writeCodeAnchor)\n")); +} +void XMLCodeGenerator::writeLineNumber(const char *extRef,const char *compId, + const char *anchorId,int l) +{ + XML_DB(("(writeLineNumber)\n")); + // we remember the information provided here to use it + // at the <codeline> start tag. + m_lineNumber = l; + if (compId) + { + m_refId=compId; + if (anchorId) m_refId+=(QCString)"_1"+anchorId; + m_isMemberRef = anchorId!=0; + if (extRef) m_external=extRef; + } +} +void XMLCodeGenerator::finish() +{ + if (m_insideCodeLine) endCodeLine(); +} static void writeTemplateArgumentList(ArgumentList *al, FTextStream &t, @@ -1163,7 +1134,7 @@ static void writeInnerNamespaces(const NamespaceSDict *nl,FTextStream &t) NamespaceDef *nd; for (nli.toFirst();(nd=nli.current());++nli) { - if (!nd->isHidden() && nd->name().find('@')==-1) // skip anonymouse scopes + if (!nd->isHidden() && nd->name().find('@')==-1) // skip anonymous scopes { t << " <innernamespace refid=\"" << nd->getOutputFileBase() << "\">" << convertToXML(nd->name()) << "</innernamespace>" << endl; @@ -1845,7 +1816,7 @@ static void generateXMLForPage(PageDef *pd,FTextStream &ti,bool isExample) SDict<SectionInfo>::Iterator li(*sectionDict); SectionInfo *si; int level=1,l; - bool inLi[5]={ FALSE, FALSE, FALSE, FALSE }; + bool inLi[5]={ FALSE, FALSE, FALSE, FALSE, FALSE }; int maxLevel = pd->localToc().xmlLevel(); for (li.toFirst();(si=li.current());++li) { @@ -1872,16 +1843,16 @@ static void generateXMLForPage(PageDef *pd,FTextStream &ti,bool isExample) if (l <= maxLevel) t << " </tableofcontents>" << endl; } } - if (l <= maxLevel && inLi[nextLevel]) t << " </tocsect>" << endl; if (nextLevel <= maxLevel) { + if (inLi[nextLevel]) t << " </tocsect>" << endl; QCString titleDoc = convertToXML(si->title); t << " <tocsect>" << endl; t << " <name>" << (si->title.isEmpty()?si->label:titleDoc) << "</name>" << endl; t << " <reference>" << convertToXML(pageName) << "_1" << convertToXML(si -> label) << "</reference>" << endl; + inLi[nextLevel]=TRUE; + level = nextLevel; } - inLi[nextLevel]=TRUE; - level = nextLevel; } } while (level>1 && level <= maxLevel) diff --git a/src/xmlgen.h b/src/xmlgen.h index 0447591..0555546 100644 --- a/src/xmlgen.h +++ b/src/xmlgen.h @@ -15,6 +15,48 @@ #ifndef XMLGEN_H #define XMLGEN_H +#include "outputgen.h" + +class XMLCodeGenerator : public CodeOutputInterface +{ + public: + + XMLCodeGenerator(FTextStream &t) : m_t(t), m_lineNumber(-1), m_isMemberRef(FALSE), m_col(0), + m_insideCodeLine(FALSE), m_normalHLNeedStartTag(TRUE), m_insideSpecialHL(FALSE) {} + virtual ~XMLCodeGenerator() { } + + void codify(const char *text); + void writeCodeLink(const char *ref,const char *file, + const char *anchor,const char *name, + const char *tooltip); + void writeTooltip(const char *, const DocLinkInfo &, const char *, + const char *, const SourceLinkInfo &, const SourceLinkInfo & + ); + void startCodeLine(bool); + void endCodeLine(); + void startFontClass(const char *colorClass); + void endFontClass(); + void writeCodeAnchor(const char *); + void writeLineNumber(const char *extRef,const char *compId, + const char *anchorId,int l); + void setCurrentDoc(Definition *,const char *,bool){} + void addWord(const char *,bool){} + + void finish(); + + private: + FTextStream &m_t; + QCString m_refId; + QCString m_external; + int m_lineNumber; + bool m_isMemberRef; + int m_col; + + bool m_insideCodeLine; + bool m_normalHLNeedStartTag; + bool m_insideSpecialHL; +}; + void generateXML(); #endif diff --git a/templates/html/doxygen.css b/templates/html/doxygen.css index 8e87381..bee3bb4 100644 --- a/templates/html/doxygen.css +++ b/templates/html/doxygen.css @@ -80,6 +80,15 @@ p.endtd { margin-bottom: 2px; } +p.interli { +} + +p.interdd { +} + +p.intertd { +} + /* @end */ caption { @@ -1112,14 +1121,12 @@ div.headertitle direction: rtl; } -dl -{ - padding: 0 0 0 10px; +dl { + padding: 0 0 0 0; } -/* dl.note, dl.warning, dl.attention, dl.pre, dl.post, dl.invariant, dl.deprecated, dl.todo, dl.test, dl.bug */ -dl.section -{ +/* dl.note, dl.warning, dl.attention, dl.pre, dl.post, dl.invariant, dl.deprecated, dl.todo, dl.test, dl.bug, dl.examples */ +dl.section { margin-left: 0px; padding-left: 0px; } @@ -1750,3 +1757,8 @@ tt, code, kbd, samp direction:ltr; } /* @end */ + +u { + text-decoration: underline; +} + diff --git a/templates/latex/doxygen.sty b/templates/latex/doxygen.sty index 7798d48..4b8c455 100644 --- a/templates/latex/doxygen.sty +++ b/templates/latex/doxygen.sty @@ -19,7 +19,7 @@ \RequirePackage{adjustbox} \RequirePackage{amssymb} \RequirePackage{stackengine} - +\RequirePackage[normalem]{ulem} % for strikeout, but don't modify emphasis %---------- Internal commands used in this style file ---------------- diff --git a/templates/xml/compound.xsd b/templates/xml/compound.xsd index 72d9097..61da4a7 100644 --- a/templates/xml/compound.xsd +++ b/templates/xml/compound.xsd @@ -384,6 +384,8 @@ <xsd:choice> <xsd:element name="ulink" type="docURLLink" /> <xsd:element name="bold" type="docMarkupType" /> + <xsd:element name="strike" type="docMarkupType" /> + <xsd:element name="underline" type="docMarkupType" /> <xsd:element name="emphasis" type="docMarkupType" /> <xsd:element name="computeroutput" type="docMarkupType" /> <xsd:element name="subscript" type="docMarkupType" /> diff --git a/testing/005_attention.dox b/testing/005_attention.dox index c3c390e..90f67f5 100644 --- a/testing/005_attention.dox +++ b/testing/005_attention.dox @@ -1,4 +1,4 @@ -// objective: test \attention, \not, \remark, \warning, and \par commands +// objective: test \attention, \note, \remark, \warning, and \par commands // check: indexpage.xml /** \mainpage * \attention Attention message. diff --git a/testing/031/indexpage.xml b/testing/031/indexpage.xml index 3b3a2e3..2c1dfd7 100644 --- a/testing/031/indexpage.xml +++ b/testing/031/indexpage.xml @@ -8,6 +8,7 @@ <detaileddescription> <para>Some text. <image type="html" name="sample.png"/> <image type="latex" name="sample.png" width="5cm">Doxygen logo</image> + <image type="docbook" name="sample.png"/> More text. </para> </detaileddescription> </compounddef> diff --git a/testing/031_image.dox b/testing/031_image.dox index f437086..8ba47b7 100644 --- a/testing/031_image.dox +++ b/testing/031_image.dox @@ -5,5 +5,6 @@ * Some text. * \image html sample.png * \image latex sample.png "Doxygen logo" width=5cm + * \image docbook sample.png * More text. */ diff --git a/testing/043_page.dox b/testing/043_page.dox index d554da2..9ac5c0e 100644 --- a/testing/043_page.dox +++ b/testing/043_page.dox @@ -4,7 +4,7 @@ /** \page mypage Page Title * \brief Page brief description. * - * @tableofcontents{xml,html,latex} + * @tableofcontents{xml,html,latex,docbook} * * Text at page level. See \ref mysect for more. * \section mysect Section Title. diff --git a/testing/051/indexpage.xml b/testing/051/indexpage.xml index 776f525..50a6ff8 100644 --- a/testing/051/indexpage.xml +++ b/testing/051/indexpage.xml @@ -6,7 +6,7 @@ <briefdescription> </briefdescription> <detaileddescription> - <para>Dollar $ At @ Backslash \ Amphasand & Less < Greater > Hash # Percent % Quote " Dot . Double colon :: Pipe | Plus + Minus - </para> + <para>Dollar $ At @ Backslash \ Ampersand & Less < Greater > Hash # Percent % Quote " Dot . Double colon :: Pipe | Plus + Minus - </para> </detaileddescription> </compounddef> </doxygen> diff --git a/testing/051_escape.dox b/testing/051_escape.dox index 290b298..2165564 100644 --- a/testing/051_escape.dox +++ b/testing/051_escape.dox @@ -5,7 +5,7 @@ Dollar \$ At \@ Backslash \\ -Amphasand \& +Ampersand \& Less \< Greater \> Hash \# diff --git a/testing/README.txt b/testing/README.txt index a5a0ad9..39b2345 100644 --- a/testing/README.txt +++ b/testing/README.txt @@ -1,4 +1,4 @@ -Doxygen regession test suite +Doxygen regression test suite ============================ This directory contains a set of regression tests. Each test consists of a @@ -7,7 +7,7 @@ has the same 3 digit number. The directory contains one or more reference files that are compared against the XML output produced by doxygen. If the result is the same, there is no regression and the test passes. If there is a difference the test fails and the difference (in diff -u format) will be shown. -It is also possible to see whether or not the test can be build to a xhtml set +It is also possible to see whether or not the test can be built to a xhtml set of files (and tested against a DTD), it is also possible to create a pdf file for each test to see if the LaTeX / pdf generation is possible. @@ -17,6 +17,8 @@ optional parameters: --doxygen [DOXYGEN] path/name of the doxygen executable --xmllint [XMLLINT] path/name of the xmllint executable --id IDS [IDS ...] id of the test to perform + --start_id START_ID run tests starting with number n + --end_id END_ID run tests ending with number n --all perform all tests --inputdir [INPUTDIR] input directory containing the tests @@ -24,10 +26,15 @@ optional parameters: output directory to write the doxygen output to --noredir disable redirection of doxygen warnings --xml create xml output and check + --rtf create rtf output + --docbook create docbook output and check with xmllint --xhtml create xhtml output and check with xmllint --pdf create LaTeX output and create pdf from it + --subdirs use the configuration parameter CREATE_SUBDIRS=YES --keep keep result directories -In case neither --xml, --pdf or --xhtml is used the default is set to --xml. + --cfg CFGS [CFGS ...] run test with extra doxygen configuration settings + (the option may be specified multiple times +In case neither --xml, --pdf, --rtf, --docbook or --xhtml is used the default is set to --xml. The runtest.pl has the following dependencies on 3rd party tools: - python to run the script @@ -57,4 +64,3 @@ There is also a CMakeLists.txt, which can be used from the build directory to run all tests by simply invoking 'make tests', to use the specific options use the flag TEST_FLAGS with make e.g. make tests TEST_FLAGS="--id=5 --id=10 --pdf --xhtml" - diff --git a/testing/runtests.py b/testing/runtests.py index 9330d23..452c36e 100644 --- a/testing/runtests.py +++ b/testing/runtests.py @@ -43,6 +43,28 @@ class Tester: rtnmsg += o return rtnmsg + def cleanup_xmllint_docbook(self,errmsg): + # For future work, first get everything valid XML + msg = self.cleanup_xmllint(errmsg).split('\n') + rtnmsg = "" + cnt = 0 + for o in msg: + if (o): + if (cnt): + cnt -= 1 + pass + elif (o.endswith("does not validate")): + pass + elif (o.find("no DTD found!")!=-1): + pass + elif (o.find("is not an NCName")!=-1): + cnt = 2 + else: + if (rtnmsg): + rtnmsg += '\n' + rtnmsg += o + return rtnmsg + def get_config(self): config = {} with open(self.args.inputdir+'/'+self.test,'r') as f: @@ -53,7 +75,7 @@ class Tester: value = m.group('value') if (key=='config'): value = value.replace('$INPUTDIR',self.args.inputdir) - #print('key=%s value=%s' % (key,value)) + # print('key=%s value=%s' % (key,value)) config.setdefault(key, []).append(value) return config @@ -74,6 +96,16 @@ class Tester: print('XML_OUTPUT=%s/out' % self.test_out, file=f) else: print('GENERATE_XML=NO', file=f) + if (self.args.rtf): + print('GENERATE_RTF=YES', file=f) + print('RTF_OUTPUT=%s/rtf' % self.test_out, file=f) + else: + print('GENERATE_RTF=NO', file=f) + if (self.args.docbook): + print('GENERATE_DOCBOOK=YES', file=f) + print('DOCBOOK_OUTPUT=%s/docbook' % self.test_out, file=f) + else: + print('GENERATE_DOCBOOK=NO', file=f) if (self.args.xhtml): print('GENERATE_HTML=YES', file=f) # HTML_OUTPUT can also be set locally @@ -82,6 +114,14 @@ class Tester: if (self.args.pdf): print('GENERATE_LATEX=YES', file=f) print('LATEX_OUTPUT=%s/latex' % self.test_out, file=f) + if self.args.subdirs: + print('CREATE_SUBDIRS=YES', file=f) + if (self.args.cfgs): + for cfg in list(itertools.chain.from_iterable(self.args.cfgs)): + if cfg.find('=') == -1: + print("Not a doxygen configuration item, missing '=' sign: '%s'."%cfg) + sys.exit(1) + print(cfg, file=f) if 'check' not in self.config or not self.config['check']: print('Test doesn\'t specify any files to check') @@ -97,7 +137,7 @@ class Tester: redir='' if os.system('%s %s/Doxyfile %s' % (self.args.doxygen,self.test_out,redir))!=0: - print('Error: failed to run %s on %s/Doxyfile' % (self.args.doxygen,self.test_out)); + print('Error: failed to run %s on %s/Doxyfile' % (self.args.doxygen,self.test_out)) sys.exit(1) # update the reference data for this test @@ -140,6 +180,8 @@ class Tester: failed_xml=False failed_html=False failed_latex=False + failed_docbook=False + failed_rtf=False msg = () # look for files to check against the reference if self.args.xml: @@ -149,8 +191,14 @@ class Tester: check_file='%s/out/%s' % (self.test_out,check) # check if the file we need to check is actually generated if not os.path.isfile(check_file): - msg += ('Non-existing file %s after \'check:\' statement' % check_file,) - break + # try with sub dirs + check_file = glob.glob('%s/out/*/*/%s' % (self.test_out,check)) + if not check_file: + check_file='%s/out/%s' % (self.test_out,check) + msg += ('Non-existing file %s after \'check:\' statement' % check_file,) + break + else: + check_file = check_file[0] # convert output to canonical form data = os.popen('%s --format --noblanks --nowarning %s' % (self.args.xmllint,check_file)).read() if data: @@ -171,6 +219,34 @@ class Tester: xml_output='%s/out' % self.test_out shutil.rmtree(xml_output,ignore_errors=True) + if (self.args.rtf): + # no tests defined yet + pass + + if (self.args.docbook): + docbook_output='%s/docbook' % self.test_out + if (sys.platform == 'win32'): + redirx=' 2> %s/temp >nul:'%docbook_output + else: + redirx='2>%s/temp >/dev/null'%docbook_output + # For future work, first get everything valid XML + # exe_string = '%s --relaxng db/docbook.rng --nonet --postvalid %s/*xml %s % (self.args.xmllint,docbook_output,redirx) + tests = [] + tests.append(glob.glob('%s/*.xml' % (docbook_output))) + tests.append(glob.glob('%s/*/*/*.xml' % (docbook_output))) + tests = ' '.join(list(itertools.chain.from_iterable(tests))).replace(self.args.outputdir +'/','').replace('\\','/') + exe_string = '%s --nonet --postvalid %s %s' % (self.args.xmllint,tests,redirx) + exe_string += ' %s more "%s/temp"' % (separ,docbook_output) + + failed_docbook=False + xmllint_out = os.popen(exe_string).read() + xmllint_out = self.cleanup_xmllint_docbook(xmllint_out) + if xmllint_out: + msg += (xmllint_out,) + failed_docbook=True + elif not self.args.keep: + shutil.rmtree(docbook_output,ignore_errors=True) + if (self.args.xhtml): html_output='%s/html' % self.test_out if (sys.platform == 'win32'): @@ -206,7 +282,7 @@ class Tester: elif not self.args.keep: shutil.rmtree(latex_output,ignore_errors=True) - if failed_xml or failed_html or failed_latex: + if failed_xml or failed_html or failed_latex or failed_docbook or failed_rtf: testmgr.ok(False,self.test_name,msg) return @@ -268,14 +344,18 @@ def main(): parser = argparse.ArgumentParser(description='run doxygen tests') parser.add_argument('--updateref',help= 'update the reference files. Should be used in combination with -id to ' - 'update the reference file(s) for the given test',action="store_true") + 'update the reference file(s) for the given test',action="store_true") parser.add_argument('--doxygen',nargs='?',default='doxygen',help= 'path/name of the doxygen executable') parser.add_argument('--xmllint',nargs='?',default='xmllint',help= 'path/name of the xmllint executable') parser.add_argument('--id',nargs='+',dest='ids',action='append',type=int,help= - 'run test with number n only (the option may be specified run test with ' - 'number n only (the option may be specified') + 'run test with number n only (the option can be specified to run test with ' + 'number n only (the option can be specified multiple times') + parser.add_argument('--start_id',dest='start_id',type=int,help= + 'run tests starting with number n') + parser.add_argument('--end_id',dest='end_id',type=int,help= + 'run tests ending with number n') parser.add_argument('--all',help= 'can be used in combination with -updateref to update the reference files ' 'for all tests.',action="store_true") @@ -287,17 +367,26 @@ def main(): 'disable redirection of doxygen warnings',action="store_true") parser.add_argument('--xml',help='create xml output and check', action="store_true") + parser.add_argument('--rtf',help= + 'create rtf output',action="store_true") + parser.add_argument('--docbook',help= + 'create docbook output and check with xmllint',action="store_true") parser.add_argument('--xhtml',help= 'create xhtml output and check with xmllint',action="store_true") parser.add_argument('--pdf',help='create LaTeX output and create pdf from it', action="store_true") + parser.add_argument('--subdirs',help='use the configuration parameter CREATE_SUBDIRS=YES', + action="store_true") parser.add_argument('--keep',help='keep result directories', action="store_true") + parser.add_argument('--cfg',nargs='+',dest='cfgs',action='append',help= + 'run test with extra doxygen configuration settings ' + '(the option may be specified multiple times') test_flags = os.getenv('TEST_FLAGS', default='').split() args = parser.parse_args(test_flags + sys.argv[1:]) # sanity check - if (not args.xml) and (not args.pdf) and (not args.xhtml): + if (not args.xml) and (not args.pdf) and (not args.xhtml) and (not args.docbook and (not args.rtf)): args.xml=True if (not args.updateref is None) and (args.ids is None) and (args.all is None): parser.error('--updateref requires either --id or --all') @@ -305,15 +394,26 @@ def main(): starting_directory = os.getcwd() os.chdir(args.inputdir) # find the tests to run - if args.ids: # test ids are given by user - tests = [] + tests = [] + if args.start_id: + if args.end_id: + for id in range(args.start_id, args.end_id + 1): + tests.append(glob.glob('%s_*'%id)) + tests.append(glob.glob('0%s_*'%id)) + tests.append(glob.glob('00%s_*'%id)) + else: + parser.error('--start_id requires --end_id') + elif args.end_id: + parser.error('--end_id requires --start_id') + if args.ids: # test ids are given by user for id in list(itertools.chain.from_iterable(args.ids)): tests.append(glob.glob('%s_*'%id)) tests.append(glob.glob('0%s_*'%id)) tests.append(glob.glob('00%s_*'%id)) - tests = list(itertools.chain.from_iterable(tests)) - else: # find all tests + if (not args.ids and not args.start_id): # find all tests tests = glob.glob('[0-9][0-9][0-9]_*') + else: + tests = list(itertools.chain.from_iterable(tests)) os.chdir(starting_directory) # create test manager to run the tests |