summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--INSTALL132
-rw-r--r--LANGUAGE.HOWTO49
-rw-r--r--Makefile178
-rw-r--r--Makefile.config12
-rw-r--r--Makefile.windows57
-rw-r--r--README10
-rw-r--r--doc/Doxyfile30
-rw-r--r--doc/Makefile22
-rw-r--r--doc/Makefile.latex14
-rw-r--r--doc/autolink.doc125
-rw-r--r--doc/commands.doc1075
-rw-r--r--doc/config.doc553
-rw-r--r--doc/doxygen.sty58
-rw-r--r--doc/doxygen_logo.eps3976
-rw-r--r--doc/doxygen_logo.gifbin0 -> 29863 bytes
-rw-r--r--doc/doxygen_logo_low.gifbin0 -> 3952 bytes
-rw-r--r--doc/doxygen_manual.tex42
-rw-r--r--doc/doxygen_usage.doc47
-rw-r--r--doc/doxysearch_usage.doc169
-rw-r--r--doc/doxytag_usage.doc116
-rw-r--r--doc/features.doc79
-rw-r--r--doc/history.doc140
-rw-r--r--doc/htmlcmds.doc111
-rw-r--r--doc/index.doc163
-rw-r--r--doc/install.doc99
-rw-r--r--doc/installdox_usage.doc61
-rw-r--r--doc/starting.doc411
-rw-r--r--doc/trouble.doc67
-rw-r--r--examples/Makefile94
-rw-r--r--examples/Makefile.windows93
-rw-r--r--examples/afterdoc.cfg6
-rw-r--r--examples/afterdoc.h18
-rw-r--r--examples/author.cfg6
-rw-r--r--examples/author.cpp14
-rw-r--r--examples/autolink.cfg6
-rw-r--r--examples/autolink.cpp99
-rw-r--r--examples/class.cfg6
-rw-r--r--examples/class.h11
-rw-r--r--examples/define.cfg7
-rw-r--r--examples/define.h11
-rw-r--r--examples/enum.cfg6
-rw-r--r--examples/enum.h17
-rw-r--r--examples/example.cfg7
-rw-r--r--examples/example.cpp19
-rw-r--r--examples/example.tag2
-rw-r--r--examples/example_test.cpp5
-rw-r--r--examples/file.cfg6
-rw-r--r--examples/file.h10
-rw-r--r--examples/func.cfg6
-rw-r--r--examples/func.h21
-rw-r--r--examples/include.cfg7
-rw-r--r--examples/include.cpp22
-rw-r--r--examples/jdstyle.cfg6
-rw-r--r--examples/jdstyle.cpp66
-rw-r--r--examples/overload.cfg6
-rw-r--r--examples/overload.cpp25
-rw-r--r--examples/page.cfg6
-rw-r--r--examples/page.doc12
-rw-r--r--examples/par.cfg6
-rw-r--r--examples/par.cpp9
-rw-r--r--examples/qtstyle.cfg6
-rw-r--r--examples/qtstyle.cpp65
-rw-r--r--examples/relates.cfg6
-rw-r--r--examples/relates.cpp24
-rw-r--r--examples/resdefine.cfg6
-rw-r--r--examples/resdefine.cpp21
-rw-r--r--examples/restypedef.cfg6
-rw-r--r--examples/restypedef.cpp25
-rw-r--r--examples/structcmd.cfg6
-rw-r--r--examples/structcmd.h57
-rw-r--r--examples/tag.cfg8
-rw-r--r--examples/tag.cpp9
-rw-r--r--examples/templ.cfg6
-rw-r--r--examples/templ.cpp37
-rw-r--r--make.bat4
-rw-r--r--src/Makefile44
-rw-r--r--src/classdef.cpp900
-rw-r--r--src/classdef.h169
-rw-r--r--src/classlist.cpp37
-rw-r--r--src/classlist.h37
-rw-r--r--src/code.h28
-rw-r--r--src/code.l747
-rw-r--r--src/config.h80
-rw-r--r--src/config.l1112
-rw-r--r--src/constexp.h30
-rw-r--r--src/constexp.l110
-rw-r--r--src/constexp.y275
-rw-r--r--src/cppvalue.cpp85
-rw-r--r--src/cppvalue.h59
-rw-r--r--src/debug.cpp62
-rw-r--r--src/debug.h39
-rw-r--r--src/declinfo.h32
-rw-r--r--src/declinfo.l292
-rw-r--r--src/defargs.h27
-rw-r--r--src/defargs.l298
-rw-r--r--src/define.cpp43
-rw-r--r--src/define.h88
-rw-r--r--src/definition.cpp44
-rw-r--r--src/definition.h64
-rw-r--r--src/diagram.cpp1236
-rw-r--r--src/diagram.h128
-rw-r--r--src/doxygen.cpp3763
-rw-r--r--src/doxygen.h134
-rw-r--r--src/doxygen.pro38
-rw-r--r--src/doxygen.t76
-rw-r--r--src/doxysearch.cpp1022
-rw-r--r--src/doxysearch.pro18
-rw-r--r--src/doxytag.l634
-rw-r--r--src/doxytag.pro24
-rw-r--r--src/doxytag.t49
-rw-r--r--src/entry.cpp242
-rw-r--r--src/entry.h153
-rw-r--r--src/example.h45
-rw-r--r--src/filedef.cpp291
-rw-r--r--src/filedef.h158
-rw-r--r--src/filename.cpp133
-rw-r--r--src/filename.h63
-rw-r--r--src/formula.cpp286
-rw-r--r--src/formula.h57
-rw-r--r--src/gifenc.cpp293
-rw-r--r--src/gifenc.h85
-rw-r--r--src/groupdef.cpp158
-rw-r--r--src/groupdef.h64
-rw-r--r--src/htmlgen.cpp512
-rw-r--r--src/htmlgen.h174
-rw-r--r--src/image.cpp443
-rw-r--r--src/image.h50
-rw-r--r--src/index.cpp975
-rw-r--r--src/index.h65
-rw-r--r--src/instdox.cpp164
-rw-r--r--src/instdox.h22
-rw-r--r--src/language.cpp61
-rw-r--r--src/language.h25
-rw-r--r--src/latexgen.cpp876
-rw-r--r--src/latexgen.h178
-rw-r--r--src/logos.cpp519
-rw-r--r--src/logos.h23
-rw-r--r--src/mangen.cpp341
-rw-r--r--src/mangen.h171
-rw-r--r--src/memberdef.cpp180
-rw-r--r--src/memberdef.h186
-rw-r--r--src/memberlist.cpp148
-rw-r--r--src/memberlist.h56
-rw-r--r--src/membername.cpp96
-rw-r--r--src/membername.h111
-rw-r--r--src/message.cpp49
-rw-r--r--src/message.h24
-rw-r--r--src/namespacedef.cpp220
-rw-r--r--src/namespacedef.h70
-rw-r--r--src/outputgen.cpp77
-rw-r--r--src/outputgen.h182
-rw-r--r--src/outputlist.cpp239
-rw-r--r--src/outputlist.h298
-rw-r--r--src/pre.h41
-rw-r--r--src/pre.l1636
-rw-r--r--src/scanner.h34
-rw-r--r--src/scanner.l3386
-rw-r--r--src/searchindex.cpp124
-rw-r--r--src/searchindex.h71
-rw-r--r--src/suffixtree.cpp355
-rw-r--r--src/suffixtree.h93
-rw-r--r--src/tag.h22
-rw-r--r--src/tag.l243
-rw-r--r--src/translator.h280
-rw-r--r--src/translator_cz.h278
-rw-r--r--src/translator_fr.h270
-rw-r--r--src/translator_it.h266
-rw-r--r--src/translator_nl.h266
-rw-r--r--src/translator_se.h250
-rw-r--r--src/unistd.h7
-rw-r--r--src/util.cpp2174
-rw-r--r--src/util.h82
-rw-r--r--src/version.h22
-rw-r--r--tmake/CHANGES39
-rw-r--r--tmake/LICENSE9
-rw-r--r--tmake/README7
-rwxr-xr-xtmake/bin/progen249
-rw-r--r--tmake/bin/progen.bat266
-rwxr-xr-xtmake/bin/tmake1099
-rw-r--r--tmake/bin/tmake.bat1093
-rw-r--r--tmake/doc/m-linux-gcc.html85
-rw-r--r--tmake/doc/m-win32-msvc.html89
-rw-r--r--tmake/doc/tmake.html638
-rw-r--r--tmake/doc/tmake_ref.html508
-rw-r--r--tmake/example/hello.cpp102
-rw-r--r--tmake/example/hello.h34
-rw-r--r--tmake/example/hello.pro3
-rw-r--r--tmake/example/main.cpp38
-rw-r--r--tmake/example/wc.t6
-rwxr-xr-xtmake/lib/aix-g++/app.t2
-rwxr-xr-xtmake/lib/aix-g++/lib.t2
-rwxr-xr-xtmake/lib/aix-g++/subdirs.t2
-rwxr-xr-xtmake/lib/aix-g++/tmake.conf57
-rwxr-xr-xtmake/lib/aix-xlc/app.t2
-rwxr-xr-xtmake/lib/aix-xlc/lib.t2
-rwxr-xr-xtmake/lib/aix-xlc/subdirs.t2
-rwxr-xr-xtmake/lib/aix-xlc/tmake.conf63
-rwxr-xr-xtmake/lib/dgux-g++/app.t2
-rwxr-xr-xtmake/lib/dgux-g++/lib.t2
-rwxr-xr-xtmake/lib/dgux-g++/subdirs.t2
-rwxr-xr-xtmake/lib/dgux-g++/tmake.conf58
-rwxr-xr-xtmake/lib/freebsd-g++/app.t2
-rwxr-xr-xtmake/lib/freebsd-g++/lib.t2
-rwxr-xr-xtmake/lib/freebsd-g++/subdirs.t2
-rwxr-xr-xtmake/lib/freebsd-g++/tmake.conf59
-rwxr-xr-xtmake/lib/gnu-g++/app.t2
-rwxr-xr-xtmake/lib/gnu-g++/lib.t2
-rwxr-xr-xtmake/lib/gnu-g++/subdirs.t2
-rwxr-xr-xtmake/lib/gnu-g++/tmake.conf57
-rwxr-xr-xtmake/lib/hpux-acc/app.t2
-rwxr-xr-xtmake/lib/hpux-acc/lib.t2
-rwxr-xr-xtmake/lib/hpux-acc/subdirs.t2
-rwxr-xr-xtmake/lib/hpux-acc/tmake.conf59
-rwxr-xr-xtmake/lib/hpux-cc/app.t2
-rwxr-xr-xtmake/lib/hpux-cc/lib.t2
-rwxr-xr-xtmake/lib/hpux-cc/subdirs.t2
-rwxr-xr-xtmake/lib/hpux-cc/tmake.conf58
-rwxr-xr-xtmake/lib/hpux-g++/app.t2
-rwxr-xr-xtmake/lib/hpux-g++/lib.t2
-rwxr-xr-xtmake/lib/hpux-g++/subdirs.t2
-rwxr-xr-xtmake/lib/hpux-g++/tmake.conf59
-rwxr-xr-xtmake/lib/irix-64/app.t2
-rwxr-xr-xtmake/lib/irix-64/lib.t2
-rwxr-xr-xtmake/lib/irix-64/subdirs.t2
-rwxr-xr-xtmake/lib/irix-64/tmake.conf59
-rwxr-xr-xtmake/lib/irix-dcc/app.t2
-rwxr-xr-xtmake/lib/irix-dcc/lib.t2
-rwxr-xr-xtmake/lib/irix-dcc/subdirs.t2
-rwxr-xr-xtmake/lib/irix-dcc/tmake.conf59
-rwxr-xr-xtmake/lib/irix-g++/app.t2
-rwxr-xr-xtmake/lib/irix-g++/lib.t2
-rwxr-xr-xtmake/lib/irix-g++/subdirs.t2
-rwxr-xr-xtmake/lib/irix-g++/tmake.conf59
-rwxr-xr-xtmake/lib/irix-n32/app.t2
-rwxr-xr-xtmake/lib/irix-n32/lib.t2
-rwxr-xr-xtmake/lib/irix-n32/subdirs.t2
-rwxr-xr-xtmake/lib/irix-n32/tmake.conf59
-rwxr-xr-xtmake/lib/linux-g++/app.t2
-rwxr-xr-xtmake/lib/linux-g++/lib.t2
-rwxr-xr-xtmake/lib/linux-g++/subdirs.t2
-rwxr-xr-xtmake/lib/linux-g++/tmake.conf57
-rwxr-xr-xtmake/lib/netbsd-g++/app.t2
-rwxr-xr-xtmake/lib/netbsd-g++/lib.t2
-rwxr-xr-xtmake/lib/netbsd-g++/subdirs.t2
-rwxr-xr-xtmake/lib/netbsd-g++/tmake.conf60
-rwxr-xr-xtmake/lib/openbsd-g++/app.t2
-rwxr-xr-xtmake/lib/openbsd-g++/lib.t2
-rwxr-xr-xtmake/lib/openbsd-g++/subdirs.t2
-rwxr-xr-xtmake/lib/openbsd-g++/tmake.conf60
-rwxr-xr-xtmake/lib/osf1-cxx/app.t2
-rwxr-xr-xtmake/lib/osf1-cxx/lib.t2
-rwxr-xr-xtmake/lib/osf1-cxx/subdirs.t2
-rwxr-xr-xtmake/lib/osf1-cxx/tmake.conf57
-rwxr-xr-xtmake/lib/osf1-g++/app.t2
-rwxr-xr-xtmake/lib/osf1-g++/lib.t2
-rwxr-xr-xtmake/lib/osf1-g++/subdirs.t2
-rwxr-xr-xtmake/lib/osf1-g++/tmake.conf57
-rwxr-xr-xtmake/lib/qnx-g++/app.t2
-rwxr-xr-xtmake/lib/qnx-g++/lib.t2
-rwxr-xr-xtmake/lib/qnx-g++/subdirs.t2
-rwxr-xr-xtmake/lib/qnx-g++/tmake.conf57
-rwxr-xr-xtmake/lib/sco-g++/app.t2
-rwxr-xr-xtmake/lib/sco-g++/lib.t2
-rwxr-xr-xtmake/lib/sco-g++/subdirs.t2
-rwxr-xr-xtmake/lib/sco-g++/tmake.conf57
-rwxr-xr-xtmake/lib/solaris-cc/app.t2
-rwxr-xr-xtmake/lib/solaris-cc/lib.t2
-rwxr-xr-xtmake/lib/solaris-cc/subdirs.t2
-rwxr-xr-xtmake/lib/solaris-cc/tmake.conf60
-rwxr-xr-xtmake/lib/solaris-g++/app.t2
-rwxr-xr-xtmake/lib/solaris-g++/lib.t2
-rwxr-xr-xtmake/lib/solaris-g++/subdirs.t2
-rwxr-xr-xtmake/lib/solaris-g++/tmake.conf57
-rwxr-xr-xtmake/lib/sunos-g++/app.t2
-rwxr-xr-xtmake/lib/sunos-g++/lib.t2
-rwxr-xr-xtmake/lib/sunos-g++/subdirs.t2
-rwxr-xr-xtmake/lib/sunos-g++/tmake.conf57
-rwxr-xr-xtmake/lib/ultrix-g++/app.t2
-rwxr-xr-xtmake/lib/ultrix-g++/lib.t2
-rwxr-xr-xtmake/lib/ultrix-g++/subdirs.t2
-rwxr-xr-xtmake/lib/ultrix-g++/tmake.conf57
-rwxr-xr-xtmake/lib/unix/app.t6
-rwxr-xr-xtmake/lib/unix/generic.t268
-rwxr-xr-xtmake/lib/unix/lib.t6
-rwxr-xr-xtmake/lib/unix/subdirs.t36
-rwxr-xr-xtmake/lib/unixware-g++/app.t2
-rwxr-xr-xtmake/lib/unixware-g++/lib.t2
-rwxr-xr-xtmake/lib/unixware-g++/subdirs.t2
-rwxr-xr-xtmake/lib/unixware-g++/tmake.conf57
-rwxr-xr-xtmake/lib/win32-borland/app.t6
-rwxr-xr-xtmake/lib/win32-borland/generic.t229
-rwxr-xr-xtmake/lib/win32-borland/lib.t6
-rwxr-xr-xtmake/lib/win32-borland/subdirs.t33
-rwxr-xr-xtmake/lib/win32-borland/tmake.conf56
-rwxr-xr-xtmake/lib/win32-g++/app.t6
-rwxr-xr-xtmake/lib/win32-g++/generic.t226
-rwxr-xr-xtmake/lib/win32-g++/lib.t6
-rwxr-xr-xtmake/lib/win32-g++/subdirs.t2
-rwxr-xr-xtmake/lib/win32-g++/tmake.conf56
-rwxr-xr-xtmake/lib/win32-msvc/app.t6
-rwxr-xr-xtmake/lib/win32-msvc/generic.t221
-rwxr-xr-xtmake/lib/win32-msvc/lib.t6
-rwxr-xr-xtmake/lib/win32-msvc/subdirs.t2
-rwxr-xr-xtmake/lib/win32-msvc/tmake.conf64
-rwxr-xr-xtmake/lib/win32-msvc/vcapp.t226
-rwxr-xr-xtmake/lib/win32-msvc/vclib.t178
-rwxr-xr-xtmake/lib/win32-symantec/app.t6
-rwxr-xr-xtmake/lib/win32-symantec/generic.t212
-rwxr-xr-xtmake/lib/win32-symantec/lib.t6
-rwxr-xr-xtmake/lib/win32-symantec/subdirs.t2
-rwxr-xr-xtmake/lib/win32-symantec/tmake.conf56
-rwxr-xr-xtmake/lib/win32-visage/app.t6
-rwxr-xr-xtmake/lib/win32-visage/generic.t208
-rwxr-xr-xtmake/lib/win32-visage/lib.t6
-rwxr-xr-xtmake/lib/win32-visage/subdirs.t2
-rwxr-xr-xtmake/lib/win32-visage/tmake.conf56
-rwxr-xr-xtmake/lib/win32-watcom/app.t6
-rwxr-xr-xtmake/lib/win32-watcom/generic.t202
-rwxr-xr-xtmake/lib/win32-watcom/lib.t6
-rwxr-xr-xtmake/lib/win32-watcom/subdirs.t2
-rwxr-xr-xtmake/lib/win32-watcom/tmake.conf54
-rwxr-xr-xtmake/lib/win32/subdirs.t35
322 files changed, 47322 insertions, 0 deletions
diff --git a/INSTALL b/INSTALL
new file mode 100644
index 0000000..22f0481
--- /dev/null
+++ b/INSTALL
@@ -0,0 +1,132 @@
+DOXYGEN Version 0.49-990425
+
+INSTALLATION INSTRUCTIONS FOR UNIX:
+-----------------------------------
+
+1. Unpack the archive, unless you already have:
+
+ gunzip doxygen-0.49-990425.src.tar.gz # uncompress the archive
+ tar xf doxygen-0.49-990425.src.tar # unpack it
+
+2. Make sure Qt is installed properly (check the environment variable $QTDIR)
+
+ Note: on some systems (like FreeBSD) it is possible that qt is not
+ installed in one single directory. In this case I suggest to create a
+ local qt directory to which the QTDIR variable should point. Then
+ create two links in that directory like this:
+ ln -s <location_of_the_qt_includes> include
+ ln -s <location_of_the_qt_libs> lib
+
+3. Look at the first two entries of Makefile.config and modify them if needed.
+ Note: Doxygen requires GNU make to build. On some systems this is
+ known as gmake. If you have such a system, you must edit Makefile.config
+ and replace make by gmake in rest of this document.
+
+4. Compile the program.
+
+ Type:
+
+ make
+
+ You'll see a list of all supported platforms/compiler combinations.
+
+ To build for the Linux platform with g++ as the compiler for example, type:
+
+ make linux-g++
+
+ The program should compile without problems and three binaries (doxygen,
+ doxytag, and doxysearch) should be available in the bin directory of the
+ distribution.
+
+5. Generate the user manual.
+
+ type:
+
+ make docs
+
+ to let doxygen generate the HTML and LaTeX documentation.
+ (you will need the stream editor `sed' for this)
+
+ type:
+
+ make ps
+
+ to generate a postscript version of the manual.
+ (you will need latex and dvips for this)
+
+ The html directory of the distribution will now contain the html
+ documentation (just point a HTML browser to the file index.html in the
+ html directory).
+
+ The postscript manual doxygen_manual.ps will be located in the latex
+ directory of the distribution. Just send it to a postscript printer to
+ print it or use ghostview to view it.
+
+INSTALLATION INSTRUCTIONS FOR WINDOWS:
+--------------------------------------
+
+Currently, only Microsoft Visual C++ version 5.0 is supported. For other
+platforms you may need to edit the Makefiles a bit. Let me know what you
+had to change if you got Doxygen working with another windows compiler.
+
+You will need to install the windows/dos versions of following tools:
+- Perl 5.0+
+- flex (you can use the DJGPP version)
+- bison (you can use the DJGPP version, but you need to copy
+ lib\bison.sim to c:\djgpp\lib\bison.simple and
+ lib\bison.hai to c:\djgpp\lib\bison.hairy.
+ The paths seem to be hardcoded in the executable)
+- Qt (Hint: only the tools section is required, so you can use the free
+ X-windows version as well!)
+- Microsoft Visual C++ version 5.0, use the vcvars32.bat to set the environment
+ variables.
+
+Make sure all tools are accessible from the command-line.
+
+Open a dos box, goto the doxygen root dir and type:
+
+make.bat
+
+This should build the executables doxygen.exe, doxytag.exe, and doxysearch.exe
+(The compiler should not produce any warnings or errors).
+
+To build the examples type:
+
+nmake -f Makefile.windows examples
+
+-----------------------------------------------------------------------------
+KNOWN CONFIGURATION PROBLEMS
+
+LATEX RELATED PROBLEMS:
+
+- the LaTeX translation of HTML tables doesn't seem to work for all
+ compilers. It is known to work for teTeX (versions 0.4 and 0.9)
+- the file a4wide.sty is not available for all distributions. If
+ your distribution does not have it please select another paper type
+ in the config file (see PAPER_TYPE)
+- the file fancyheader.sty is known as fancyhdr.sty on some systems.
+ Please change that in src/latexgen.cpp
+
+HP-UX PROBLEMS:
+- If you are compiling for HP-UX with aCC and you get this error:
+ /opt/aCC/lbin/ld: Unsatisfied symbols:
+ alloca (code)
+ then you should edit ce_parse.cpp and replace
+ extern "C" {
+ void *alloca (unsigned int);
+ };
+ with
+ #include <alloca.h>
+ This seems to be a problem with bison, but I don't know how to fix it.
+-----------------------------------------------------------------------------
+
+That's it!
+
+Please report any problems to dimitri@stack.nl
+
+The latest version of doxygen can be obtained at
+ http://www.stack.nl/~dimitri/doxygen
+
+Enjoy,
+
+Dimitri van Heesch (25 April 1999)
diff --git a/LANGUAGE.HOWTO b/LANGUAGE.HOWTO
new file mode 100644
index 0000000..21cc9c2
--- /dev/null
+++ b/LANGUAGE.HOWTO
@@ -0,0 +1,49 @@
+This short howto explains how to add support for a new language to Doxygen:
+
+Just follow these steps:
+
+1) Tell me for which language you want to add support. If no one else
+ is already working on support for that language, you will be
+ assigned as the maintainer for the language. I'll create a
+ list on Doxygen's homepage, so everyone knows who is doing what.
+2) Create a copy of translator_nl.h and name it
+ translator_<your_2_letter_counter_code>.h
+ I'll use xx in the rest of this document.
+3) Edit language.cpp:
+ - Add a #include<translator_xx.h>
+ - in setTranslator() add
+
+ else if (L_EQUAL("your_language_name"))
+ {
+ theTranslator = new TranslatorYourlanguage;
+ }
+
+ after the if { ... }
+4) Edit doxygen.pro and add translator_xx.h to the HEADERS line in the
+ file doxygen.pro.
+5) Edit translator_xx.h:
+ - Rename TRANSLATOR_NL_H to TRANSLATOR_XX_H twice.
+ - Rename TranslatorDutch to TranslatorYourlanguage
+ - In the member latexBabelPackage() change "dutch" into the name of the
+ latex package that adds support for your language.
+ - Edit all the strings that are returned by the members that start
+ with tr.
+ Look at the corresponding member in translator.h for the english text
+ that is returned and translate that into your language.
+ Try to match punctuation and capitals!
+ To enter special characters (with accents) you can:
+ a) Enter them directly if your keyboard supports that and you are
+ using a Latin-1 font.
+ Doxygen will translate the characters to proper Latex and
+ leave the Html and man output for what it is.
+ b) Use html codes like &auml; for an a with an umlaut.
+ See the HTML specification for the codes.
+6) Recompile everything (do this from the root of the distribution,
+ because the Makefile.dox* have to be regenerated!)
+7) Now you can use OUTPUT_LANGUAGE = your_language_name
+ in the config file to generate output in your language.
+8) Send translator_xx.h or a diff -u of the changes to me so I can add it
+ to doxygen.
+
+Good luck, and let me know if there are problems.
+
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..037c87a
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,178 @@
+# this Makefile need GNU make
+
+include Makefile.config
+
+variables: Makefile
+ @echo
+ @echo "Select one of the following targets:"
+ @echo
+ @echo "aix-g++ aix-xlc "
+ @echo "dgux-g++ freebsd-g++ "
+ @echo "gnu-g++ hpux-acc "
+ @echo "hpux-cc hpux-g++ "
+ @echo "irix-64 irix-dcc "
+ @echo "irix-g++ irix-n32 "
+ @echo "linux-g++ netbsd-g++ "
+ @echo "openbsd-g++ osf1-cxx "
+ @echo "osf1-g++ qnx-g++ "
+ @echo "sco-g++ solaris-cc "
+ @echo "solaris-g++ sunos-g++ "
+ @echo "ultrix-g++ unixware-g++ "
+ @echo
+ @echo "Make any of them to build Doxygen."
+ @echo "Make will now abort with an error."
+ @exit 1
+
+aix-g++: src/version.cpp
+ cd src; \
+ TMAKEPATH=../tmake/lib/aix-g++ \
+ $(MAKE)
+
+aix-xlc: src/version.cpp
+ cd src; \
+ TMAKEPATH=../tmake/lib/aix-xlc \
+ $(MAKE)
+
+dgux-g++: src/version.cpp
+ cd src; \
+ TMAKEPATH=../tmake/lib/dgux-g++ \
+ $(MAKE)
+
+freebsd-g++: src/version.cpp
+ cd src; \
+ TMAKEPATH=../tmake/lib/freebsd-g++ \
+ $(MAKE)
+
+hpux-acc: src/version.cpp
+ cd src; \
+ TMAKEPATH=../tmake/lib/hpux-acc \
+ $(MAKE)
+
+hpux-cc: src/version.cpp
+ cd src; \
+ TMAKEPATH=../tmake/lib/hpux-cc \
+ $(MAKE)
+
+hpux-g++: src/version.cpp
+ cd src; \
+ TMAKEPATH=../tmake/lib/hpux-g++ \
+ $(MAKE)
+
+irix-64: src/version.cpp
+ cd src; \
+ TMAKEPATH=../tmake/lib/irix-64 \
+ $(MAKE)
+
+irix-dcc: src/version.cpp
+ cd src; \
+ TMAKEPATH=../tmake/lib/irix-dcc \
+ $(MAKE)
+
+irix-g++: src/version.cpp
+ cd src; \
+ TMAKEPATH=../tmake/lib/irix-g++ \
+ $(MAKE)
+
+irix-n32: src/version.cpp
+ cd src; \
+ TMAKEPATH=../tmake/lib/irix-n32 \
+ $(MAKE)
+
+linux-g++: src/version.cpp
+ cd src; \
+ TMAKEPATH=../tmake/lib/linux-g++ \
+ $(MAKE)
+
+netbsd-g++: src/version.cpp
+ cd src; \
+ TMAKEPATH=../tmake/lib/netbsd-g++ \
+ $(MAKE)
+
+openbsd-g++: src/version.cpp
+ cd src; \
+ TMAKEPATH=../tmake/lib/openbsd-g++ \
+ $(MAKE)
+
+osf1-cxx: src/version.cpp
+ cd src; \
+ TMAKEPATH=../tmake/lib/osf1-cxx \
+ $(MAKE)
+
+osf1-g++: src/version.cpp
+ cd src; \
+ TMAKEPATH=../tmake/lib/osf1-g++ \
+ $(MAKE)
+
+qnx-g++: src/version.cpp
+ cd src; \
+ TMAKEPATH=../tmake/lib/qnx-g++ \
+ $(MAKE)
+
+sco-g++: src/version.cpp
+ cd src; \
+ TMAKEPATH=../tmake/lib/sco-g++ \
+ $(MAKE)
+
+solaris-cc: src/version.cpp
+ cd src; \
+ TMAKEPATH=../tmake/lib/solaris-cc \
+ $(MAKE)
+
+solaris-g++: src/version.cpp
+ cd src; \
+ TMAKEPATH=../tmake/lib/solaris-g++ \
+ $(MAKE)
+
+sunos-g++: src/version.cpp
+ cd src; \
+ TMAKEPATH=../tmake/lib/sunos-g++ \
+ $(MAKE)
+
+ultrix-g++: src/version.cpp
+ cd src; \
+ TMAKEPATH=../tmake/lib/ultrix-g++ \
+ $(MAKE)
+
+unixware-g++: src/version.cpp
+ cd src; \
+ TMAKEPATH=../tmake/lib/unixware-g++ \
+ $(MAKE)
+
+
+clean: FORCE
+ cd examples ; $(MAKE) clean
+ cd doc ; $(MAKE) clean
+ -rm -f src/scanner.cpp \
+ src/code.cpp \
+ src/config.cpp \
+ src/pre.cpp \
+ src/tag.cpp \
+ src/ce_lex.cpp \
+ src/ce_parse.cpp \
+ src/ce_parse.h \
+ src/doxytag.cpp \
+ src/declinfo.cpp \
+ src/defargs.cpp \
+ src/Makefile.doxygen \
+ src/Makefile.doxytag \
+ src/Makefile.doxysearch \
+ src/version.cpp
+ -rm -f bin/doxy*
+ -rm -f objects/*.o
+
+docs: FORCE
+ cd examples ; $(MAKE)
+ cd doc ; $(MAKE)
+
+ps: docs
+ cd latex ; $(MAKE)
+
+archive: clean
+ $(TAR) zcvf backup/dx`date +%y%m%d`.tgz tmake doc examples bin objects \
+ src Makefile Makefile.windows INSTALL make.bat Makefile.config \
+ LANGUAGE.HOWTO
+
+src/version.cpp: FORCE
+ echo "char versionString[]=\"$(VERSION)\";" > src/version.cpp
+
+FORCE:
diff --git a/Makefile.config b/Makefile.config
new file mode 100644
index 0000000..0492810
--- /dev/null
+++ b/Makefile.config
@@ -0,0 +1,12 @@
+# name (and path if needed) of the make tool to use
+# note that make must really be GNU make, not BSD or some other make
+MAKE = make
+
+# name (and path if needed) of the perl interpreter
+# note that it must be version 5 or higher (check with perl -v)
+PERL = perl
+
+# The values below should probably be left unmodified
+TAR = tar # name of the GNU tar tool
+TMAKE = ../tmake/bin/tmake
+VERSION = 0.49-990425
diff --git a/Makefile.windows b/Makefile.windows
new file mode 100644
index 0000000..a662b2e
--- /dev/null
+++ b/Makefile.windows
@@ -0,0 +1,57 @@
+# Makefile for Microsoft Visual C++
+
+include Makefile.config
+
+MAKE = nmake /NOLOGO
+TMAKE = ..\tmake\bin\tmake
+
+all:
+ @echo "
+ @echo " Select one of the following targets: "
+ @echo " "
+ @echo " win32-msvc "
+ @echo " "
+ @echo " Make any of them to build Doxygen. "
+ @echo " Make will now abort with an error. "
+ @exit 1
+
+win32-msvc: src\version.cpp
+ cd src
+ $(MAKE) tmake TMAKE=$(TMAKE) PERL=$(PERL)
+ $(MAKE) MAKE=$(MAKE)
+
+clean: FORCE
+ cd examples
+ $(MAKE) -f Makefile.windows clean
+ cd ..
+ -del src\scanner.cpp
+ -del src\code.cpp
+ -del src\config.cpp
+ -del src\pre.cpp
+ -del src\tag.cpp
+ -del src\constexp.lex.cpp
+ -del src\constexp.parse.cpp
+ -del src\constexp.parse.h
+ -del src\doxytag.cpp
+ -del src\declinfo.cpp
+ -del src\defargs.cpp
+ -del src\Makefile.doxygen
+ -del src\Makefile.doxytag
+ -del src\Makefile.doxysearch
+ -del src\version.cpp
+ -del bin\doxy*.*
+ -del objects\*.obj
+
+examples: FORCE
+ cd examples
+ $(MAKE) -f Makefile.windows
+ cd ..
+
+docs: examples
+ @echo Docs cannot be made using windows yet.
+ @echo Get them from the binary distribution...
+
+src\version.cpp:
+ echo char versionString[]="$(VERSION)"; >src\version.cpp
+
+FORCE:
diff --git a/README b/README
new file mode 100644
index 0000000..7ebbeb7
--- /dev/null
+++ b/README
@@ -0,0 +1,10 @@
+DOXYGEN Version 0.49-990425
+
+Please read INSTALL for compilation instructions.
+
+The latest version of doxygen can be obtained at
+ http://www.stack.nl/~dimitri/doxygen
+
+Enjoy,
+
+Dimitri van Heesch (25 April 1999)
diff --git a/doc/Doxyfile b/doc/Doxyfile
new file mode 100644
index 0000000..79cbb31
--- /dev/null
+++ b/doc/Doxyfile
@@ -0,0 +1,30 @@
+PROJECT_NAME =
+OUTPUT_DIRECTORY = ..
+HTML_HEADER =
+HTML_FOOTER =
+QUIET = NO
+WARNINGS = YES
+DISABLE_INDEX = YES
+EXTRACT_ALL = NO
+EXTRACT_PRIVATE = NO
+GENERATE_LATEX = YES
+GENERATE_HTML = YES
+ENABLE_PREPROCESSING = NO
+INPUT = index.doc install.doc starting.doc trouble.doc \
+ history.doc features.doc \
+ doxygen_usage.doc doxytag_usage.doc doxysearch_usage.doc \
+ installdox_usage.doc autolink.doc \
+ config.doc commands.doc htmlcmds.doc
+FILE_PATTERNS = *.cpp *.h *.doc
+EXAMPLE_PATH = ../examples
+RECURSIVE = NO
+TAGFILES =
+ALLEXTERNALS = NO
+PERL_PATH = /usr/local/bin/perl
+SEARCHENGINE = NO
+CGI_NAME = search.cgi
+CGI_URL =
+DOC_URL =
+DOC_ABSPATH =
+BIN_ABSPATH = /usr/local/bin/
+EXT_DOC_PATHS =
diff --git a/doc/Makefile b/doc/Makefile
new file mode 100644
index 0000000..953517a
--- /dev/null
+++ b/doc/Makefile
@@ -0,0 +1,22 @@
+include ../Makefile.config
+
+DOXYDIR=../bin
+DOXYGEN_DOCDIR=..
+
+all: FORCE
+ DOXYGEN_DOCDIR=$(DOXYGEN_DOCDIR); \
+ export DOXYGEN_DOCDIR; \
+ VERSION=$(VERSION) ; \
+ export VERSION; \
+ $(DOXYDIR)/doxygen
+ @rm -f ../latex/refman.tex
+ @cp doxygen_logo*.gif ../html
+ @cp Makefile.latex ../latex/Makefile
+ @sed -e "s/\$$VERSION/$(VERSION)/g" doxygen_manual.tex >../latex/doxygen_manual.tex
+ @sed -e "s/\$$VERSION/$(VERSION)/g" doxygen.sty >../latex/doxygen.sty
+ @cp doxygen_logo.eps ../latex
+
+clean:
+ rm -rf ../html ../latex
+
+FORCE:
diff --git a/doc/Makefile.latex b/doc/Makefile.latex
new file mode 100644
index 0000000..7ab03a3
--- /dev/null
+++ b/doc/Makefile.latex
@@ -0,0 +1,14 @@
+all: doxygen_manual.ps
+
+doxygen_manual.ps: doxygen_manual.dvi
+ dvips -o doxygen_manual.ps doxygen_manual.dvi
+
+doxygen_manual.dvi: doxygen_manual.tex doxygen.sty
+ echo "Running latex..."
+ latex doxygen_manual.tex
+ echo "Running makeindex..."
+ makeindex doxygen_manual.idx
+ echo "Rerunning latex...."
+ latex doxygen_manual.tex
+clean:
+ rm -f *.ps *.dvi *.aux *.toc *.idx *.ind *.ilg *.log
diff --git a/doc/autolink.doc b/doc/autolink.doc
new file mode 100644
index 0000000..b0f0fa4
--- /dev/null
+++ b/doc/autolink.doc
@@ -0,0 +1,125 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+/*! \page autolink Automatic link generation
+
+ Most documentation systems have special `see also' sections where links
+ to other pieces of documentation can be inserted.
+ Although doxygen also has a command to start such a section (See section
+ \ref cmdsa), it does allow you to put these kind of links anywhere in the
+ documentation.
+ For \f$\mbox{\LaTeX}\f$ documentation a reference to the page number
+ is written instead of a link. Furthermore, the index at the end of the
+ document can be used to quickly find the documentation of a member, class,
+ namespace or file.
+ For man pages no reference information is generated.
+
+ The next sections show how to generate links to the various documented
+ entities in a source file.
+
+ \subsection linkclass Links to classes.
+
+ All words in the documentation that correspond to a documented class
+ will automatically be replaced by a link to the page containing the
+ documentation of the class. If you want to prevent that a word
+ that corresponds to a documented class is replaced by a link you
+ should put a \% in front of the word.
+
+ \subsection linkfile Links to files.
+
+ All words that contain a dot (<tt>.</tt>) that is not the last character
+ in the word are considered to be file names.
+ If the word is indeed the name of a documented input file, a link will
+ automatically be created to the documentation of that file.
+
+ \subsection linkfunc Links to functions.
+
+ Links to functions are created if one of the following patterns is
+ encountered:
+ <ol>
+ <li><tt>\<functionName\>"("\<argument-list\>")"</tt>
+ <li><tt>\<functionName\>"()"</tt>
+ <li><tt>"::"\<functionName\></tt>
+ <li><tt>(\<className\>"::")<sup>n</sup>\<functionName\>"("\<argument-list\>")"</tt>
+ <li><tt>(\<className\>"::")<sup>n</sup>\<functionName\>"()"</tt>
+ <li><tt>(\<className\>"::")<sup>n</sup>\<functionName\></tt>
+ </ol>
+ where n>0.
+
+ \par Notice 1:
+ The patterns above should not contain spaces, tabs or newlines.
+ \par Notice 2:
+ For JavaDoc compatibility a \c # may be used instead of a \c :: in
+ the patterns above.
+
+ For non overloaded members the argument list may be omitted.
+
+ If a function is overloaded and no matching argument list is specified
+ (i.e. pattern 2 or 5 is used), a link will be created to the
+ documentation of one of the overloaded members.
+
+ For member functions the class scope (as used in patterns 4 to 6) may
+ be omitted, if:
+ <ol>
+ <li>The pattern points to a documented member that belongs to the same class
+ as the documentation block that contains the pattern.
+ <li>The class that corresponds to the documentation blocks that contains
+ the pattern has a base class that contains a documented member
+ that matches the pattern.
+ </ol>
+
+ \subsection linkother Links to variables, typedefs, enum types, enum values and defines.
+
+ All of these entities can be linked to in the same way as described in the
+ previous section. For sake of clarity it is advised to only use
+ patterns 3 and 6 in this case.
+
+ \par Example:
+ \verbinclude autolink.cpp
+ \htmlonly
+ Click <a href="$(DOXYGEN_DOCDIR)/examples/autolink/html/index.html">here</a>
+ for the corresponding HTML documentation that is generated by Doxygen.
+ \endhtmlonly
+
+ \subsection resolving Resolving of defines and typedefs.
+
+ Macro definitions of the form:
+\verbatim
+#define TypeName ClassName
+\endverbatim
+ will be resolved inside documentation blocks.
+
+ \par Example:
+ \verbinclude resdefine.cpp
+ \htmlonly
+ Click <a href="$(DOXYGEN_DOCDIR)/examples/resdefine/html/exportedname.html">here</a>
+ for the corresponding HTML documentation that is generated by Doxygen.
+ \endhtmlonly
+
+ Typedefs that involve classes, structs and unions, like
+\verbatim
+typedef struct StructName TypeName
+\endverbatim
+ create an alias for StructName, so links will be generated to StructName,
+ when either StructName itself or TypeName is encountered.
+
+ \par Example:
+ \verbinclude restypedef.cpp
+ \htmlonly
+ Click <a href="$(DOXYGEN_DOCDIR)/examples/restypedef/html/restypedef.cpp.html">here</a>
+ for the corresponding HTML documentation that is generated by Doxygen.
+ \endhtmlonly
+
+*/
diff --git a/doc/commands.doc b/doc/commands.doc
new file mode 100644
index 0000000..c288be7
--- /dev/null
+++ b/doc/commands.doc
@@ -0,0 +1,1075 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+/*! \page commands
+
+\section commands Special Commands
+
+All commands in the documentation start with a backslash (<b>\\</b>) or an
+at-sign (<b>\@</b>).
+Some commands have one or more arguments.
+Each argument has a certain range:
+<ul>
+<li>If <sharp> braces are used the argument is a single word.
+<li>If (round) braces are used the argument extends until the end of the line
+ on which the command was found.
+<li>If {curly} braces are used the argument extends until the next paragraph.
+ Paragraphs are delimited by a blank line or by a section indicator.
+</ul>
+If [square] brackets are used the argument is optional.
+
+Here is an alphabetically sorted list of all commands with references to their
+documentation:
+\htmlonly
+<multicol cols=4>
+<ul>
+\endhtmlonly
+\latexonly
+\begin{multicols}{3}
+\begin{CompactList}
+\endlatexonly
+<li> \refitem cmda \a
+<li> \refitem cmdaddindex \addindex
+<li> \refitem cmdarg \arg
+<li> \refitem cmdauthor \author
+<li> \refitem cmdb \b
+<li> \refitem cmdbrief \brief
+<li> \refitem cmdbug \bug
+<li> \refitem cmdc \c
+<li> \refitem cmdclass \class
+<li> \refitem cmdcode \code
+<li> \refitem cmddate \date
+<li> \refitem cmddef \def
+<li> \refitem cmddefgroup \defgroup
+<li> \refitem cmddontinclude \dontinclude
+<li> \refitem cmde \e
+<li> \refitem cmdendcode \endcode
+<li> \refitem cmdendhtmlonly \endhtmlonly
+<li> \refitem cmdendlatexonly \endlatexonly
+<li> \refitem cmdendlink \endlink
+<li> \refitem cmdendverbatim \endverbatim
+<li> \refitem cmdenum \enum
+<li> \refitem cmdexample \example
+<li> \refitem cmdexception \exception
+<li> \refitem cmdfdollar \f$
+<li> \refitem cmdfbropen \f[
+<li> \refitem cmdfbrclose \f]
+<li> \refitem cmdfile \file
+<li> \refitem cmdfn \fn
+<li> \refitem cmdhtmlonly \htmlonly
+<li> \refitem cmdinclude \include
+<li> \refitem cmdingroup \ingroup
+<li> \refitem cmdinternal \internal
+<li> \refitem cmdlatexonly \latexonly
+<li> \refitem cmdline \line
+<li> \refitem cmdlink \link
+<li> \refitem cmdnamespace \namespace
+<li> \refitem cmdoverload \overload
+<li> \refitem cmdpage \page
+<li> \refitem cmdpar \par
+<li> \refitem cmdparam \param
+<li> \refitem cmdref \ref
+<li> \refitem cmdrelates \relates
+<li> \refitem cmdreturn \return
+<li> \refitem cmdsa \sa
+<li> \refitem cmdsection \section
+<li> \refitem cmdskip \skip
+<li> \refitem cmdskipline \skipline
+<li> \refitem cmdstruct \struct
+<li> \refitem cmdsubsection \subsection
+<li> \refitem cmdtypedef \typedef
+<li> \refitem cmdunion \union
+<li> \refitem cmduntil \until
+<li> \refitem cmdvar \var
+<li> \refitem cmdverbatim \verbatim
+<li> \refitem cmdverbinclude \verbinclude
+<li> \refitem cmdversion \version
+<li> \refitem cmdwarning \warning
+<li> \refitem cmddollar \$
+<li> \refitem cmdat \@
+<li> \refitem cmdbackslash \\
+<li> \refitem cmdamp \&
+<li> \refitem cmdlt \\<
+<li> \refitem cmdgt \\>
+<li> \refitem cmdhash \#
+\htmlonly
+</ul>
+</multicol>
+\endhtmlonly
+\latexonly
+\end{CompactList}
+\end{multicols}
+\endlatexonly
+
+The following subsections provide a list of all commands that are recognized by
+Doxygen. Unrecognized commands are treated as normal text.
+
+<h2>\htmlonly <center> --- \endhtmlonly
+ Structural indicators
+ \htmlonly --- </center>\endhtmlonly</h2>
+
+\subsection cmdclass \class <name> [<header-file>] [<header-name>]
+
+ \addindex \class
+ Indicates that a comment block contains documentation for a
+ class with name \<name\>. Optionally a header file and a header name
+ can be specified. If the header-file is specified, a link to a verbatim copy
+ of the header will be included in the HTML documentation.
+ The \<header-name\> argument can be used to overwrite the
+ name of the link that is used in the class documentation to something other
+ than \<header-file\>. This can be useful if the include name is not located
+ on the default include path (like \<X11/X.h\>).
+
+ \par Example:
+ \verbinclude class.h
+ \htmlonly
+ Click <a href="$(DOXYGEN_DOCDIR)/examples/class/html/index.html">here</a>
+ for the corresponding HTML documentation that is generated by Doxygen.
+ \endhtmlonly
+
+<hr>
+\subsection cmdcode \code
+
+ \addindex \\code
+ Starts a block of code. A code block is treated differently
+ from ordinary text. It is interpreted as C/C++ code. The names of the
+ classes and members that are documented are automatically replaced by
+ links to the documentation.
+
+ \sa section \ref cmdendcode, section \ref cmdverbatim
+
+<hr>
+\subsection cmddef \def <name>
+
+ \addindex \def
+ Indicates that a comment block contains documentation for a
+ \c #define macro.
+
+ \par Example:
+ \verbinclude define.h
+ \htmlonly
+ Click <a href="$(DOXYGEN_DOCDIR)/examples/define/html/index.html">here</a>
+ for the corresponding HTML documentation that is generated by Doxygen.
+ \endhtmlonly
+
+<hr>
+\subsection cmddefgroup \defgroup <name> (group title)
+
+ \addindex \defgroup
+ Indicates that a comment block contains documentation for a
+ group of classes, files or namespaces. This can be used to
+ categorize classes, files or namespaces, and document those
+ categories.
+ \sa section \ref cmdingroup
+
+<hr>
+\subsection cmdendcode \endcode
+
+ \addindex \endcode
+ Ends a block of code.
+ \sa section \ref cmdcode
+
+<hr>
+\subsection cmdenum \enum <name>
+
+ \addindex \enum
+ Indicates that a comment block contains documentation for an
+ enumeration, with name \<name\>. If the enum is a member of a class and
+ the documentation block is located outside the class definition,
+ the scope of the class should be specified as well.
+ If a comment block is located directly in front of an enum declaration,
+ the \\enum comment may be omitted.
+
+ \par Notice:
+ The type of an anonymous enum cannot be documented, but the values
+ of an anonymous enum can.
+
+ \par Example:
+ \verbinclude enum.h
+ \htmlonly
+ Click <a href="$(DOXYGEN_DOCDIR)/examples/enum/html/index.html">here</a>
+ for the corresponding HTML documentation that is generated by Doxygen.
+ \endhtmlonly
+
+<hr>
+\subsection cmdexample \example <file-name>
+
+ \addindex \example
+ Indicates that a comment block contains documentation for a source code
+ example. The name of the source file is \<file-name\>. The text of
+ this file will be included in the documentation, just after the
+ documentation contained in the comment block. All examples are placed
+ in a list. The source code is scanned for documented members and classes.
+ If any are found, the names are cross-referenced with the documentation.
+
+ If more that one source file is needed for the example,
+ the \\include command can be used.
+
+ \par Example:
+ \verbinclude example.cpp
+ Where the example file \c example_test.cpp looks as follows:
+ \verbinclude example_test.cpp
+ \htmlonly
+ Click <a href="$(DOXYGEN_DOCDIR)/examples/example/html/index.html">here</a>
+ for the corresponding HTML documentation that is generated by Doxygen.
+ \endhtmlonly
+
+ \sa section \ref cmdinclude.
+
+<hr>
+\subsection cmdfile \file [<name>]
+
+ \addindex \file
+ Indicates that a comment block contains documentation for a source or
+ header file with name \<name\>. The file name may include (part of) the
+ path if the file-name alone is not unique. If the file name is omitted
+ (i.e. the line after \\file is left blank) then the documentation block that
+ contains the \\file command will belong to the file it is located in.
+
+ \par Important:
+ The documentation of global functions, variables, typedefs, and enums will
+ only be included in the output if the file they are in is documented as well.
+
+ \par Example:
+ \verbinclude file.h
+ \htmlonly
+ Click <a href="$(DOXYGEN_DOCDIR)/examples/file/html/index.html">here</a>
+ for the corresponding HTML documentation that is generated by Doxygen.
+ \endhtmlonly
+
+<hr>
+\subsection cmdfn \fn (function declaration)
+
+ \addindex \fn
+ Indicates that a comment block contains documentation for a function
+ (either global or as a member of a class). This command is needed if a
+ comment block is \e not located before the function declaration
+ or definition. A full function declaration should be specified after the
+ \fn command. The argument ends at the end of the line.
+
+ \par Example:
+ \verbinclude func.h
+ \htmlonly
+ Click <a href="$(DOXYGEN_DOCDIR)/examples/func/html/class_test.html">here</a>
+ for the corresponding HTML documentation that is generated by Doxygen.
+ \endhtmlonly
+
+ \sa section \ref cmdvar and \ref cmdtypedef
+
+<hr>
+\subsection cmdingroup \ingroup <groupname>
+
+ \addindex \ingroup
+ If the \\ingroup command is placed in a comment block of a
+ class, file or namespace, then it will be added to the group.
+
+ \sa section \ref cmddefgroup
+
+<hr>
+\subsection cmdinternal \internal
+
+ \addindex \internal
+ This command writes the message `For internal use only' to the output.
+ All text after a \c \internal command is ignored.
+
+<hr>
+\subsection cmdnamespace \namespace <name>
+
+ \addindex \namespace
+ Indicates that a comment block contains documentation for a
+ namespace with name \<name\>.
+
+<hr>
+\subsection cmdoverload \overload [(function declaration)]
+
+ \addindex \overload
+ This command can be used to generate the following
+ standard text for an overloaded member function:
+
+ `This is an overloaded member function, provided for convenience.
+ It differs from the above function only in what argument(s) it accepts.'
+
+ If the documentation for the overloaded member function is not located
+ in front of the function declaration or definition, the optional
+ argument should be used to specify the correct function.
+
+ Any other documentation that is inside the documentation block will
+ by appended after the generated message.
+
+ \par Notice 1:
+ You are responsible that there is indeed an
+ earlier documented member that is overloaded by this one.
+ \par Notice 2:
+ The \\overload command does not work inside a one-line comment.
+ \par Example:
+ \verbinclude examples/overload.cpp
+ \htmlonly
+ Click <a href="$(DOXYGEN_DOCDIR)/examples/overload/html/class_test.html">here</a>
+ for the corresponding HTML documentation that is generated by Doxygen.
+ \endhtmlonly
+
+<hr>
+\subsection cmdpage \page <name> (title)
+
+ \addindex \page
+ Indicates that a comment block contains a piece of documentation that is
+ not directly related to one specific class, file or member.
+ The HTML generator creates a page containing the documentation. The
+ \htmlonly LaTeX\endhtmlonly\latexonly\LaTeX\ \endlatexonly generator
+ starts a new section in the chapter `Page documentation'.
+
+ \par Example:
+ \verbinclude page.doc
+ \htmlonly
+ Click <a href="$(DOXYGEN_DOCDIR)/examples/page/html/pages.html">here</a>
+ for the corresponding HTML documentation that is generated by Doxygen.
+ \endhtmlonly
+
+ \sa section \ref cmdsection, section \ref cmdsubsection, and
+ section \ref cmdref
+
+<hr>
+\subsection cmdrelates \relates <name>
+
+ \addindex \relates
+ This command can be used in the documentation of a non-member function
+ \<name\>. It puts the function inside the `related function' section
+ of the class documentation. This command is useful for documenting
+ non-friend functions that are nevertheless strongly coupled to a certain
+ class. It prevents the need of having to document a file, but
+ only works for functions.
+
+ \par Example:
+ \verbinclude relates.cpp
+ \htmlonly
+ Click <a href="$(DOXYGEN_DOCDIR)/examples/relates/html/class_string.html">here</a>
+ for the corresponding HTML documentation that is generated by Doxygen.
+ \endhtmlonly
+
+<hr>
+\subsection cmdstruct \struct <name> [<header-file>] [<header-name>]
+
+ \addindex \struct
+ Indicates that a comment block contains documentation for a
+ struct with name \<name\>. The arguments are equal to the \\class
+ command.
+
+ \sa section \ref cmdclass.
+
+<hr>
+\subsection cmdtypedef \typedef (typedef declaration)
+
+ \addindex \typedef
+ Indicates that a comment block contains documentation for a typedef,
+ typedef (either global or as a member of a class).
+ This command is equivalent to \\var and \\fn.
+
+ \sa section \ref cmdfn and \ref cmdvar
+
+<hr>
+\subsection cmdunion \union <name> [<header-file>] [<header-name>]
+
+ \addindex \union
+ Indicates that a comment block contains documentation for a
+ union with name \<name\>. The arguments are equal to the \\class
+ command.
+
+ \sa section \ref cmdclass.
+
+<hr>
+\subsection cmdvar \var (variable declaration)
+
+ \addindex \var
+ Indicates that a comment block contains documentation for a variable,
+ enum value (either global or as a member of a class).
+ This command is equivalent to \\typedef and \\fn.
+
+ \sa section \ref cmdfn and \cmdtypedef
+
+<hr>
+
+<h2>\htmlonly <center> --- \endhtmlonly
+ Section indicators
+ \htmlonly --- </center>\endhtmlonly</h2>
+
+\subsection cmdauthor \author { list of authors }
+
+ \addindex \author
+ Starts a paragraph where one or more author names may be entered.
+ The paragraph will be indented.
+ The text of the paragraph has no special internal structure. All visual
+ enhancement commands may be used inside the paragraph.
+ Multiple adjacent \\author commands will be joined into a single paragraph
+ and separated by commas. Alternatively, one \\author command may mention
+ several authors. The \\author command ends when a blank line or some other
+ sectioning command is encountered.
+
+ \par Example:
+ \verbinclude author.cpp
+ \htmlonly
+ Click <a href="$(DOXYGEN_DOCDIR)/examples/author/html/class_windowsnt.html">here</a>
+ for the corresponding HTML documentation that is generated by Doxygen.
+ \endhtmlonly
+
+ \sa Section \ref cmdjdauthor.
+
+<hr>
+\subsection cmdbrief \brief {brief description}
+
+ \addindex \brief
+ Starts a paragraph that serves as a brief description. For classes and files
+ the brief description will be used in lists and at the start of the
+ documentation page. For class and file members, the brief description
+ will be placed at the declaration of the member and prepended to the
+ detailed description. A brief description may span several lines (although
+ it is advised to keep it brief!). A brief description ends when a
+ blank line or another sectioning command is encountered. If multiple
+ \\brief commands are present they will be joined. See section
+ \ref cmdauthor for an example.
+
+ \sa Section \ref cmdjdshort
+
+<hr>
+\subsection cmdbug \bug { bug description }
+
+ \addindex \bug
+ Starts a paragraph where one or more bugs may be reported.
+ The paragraph will be indented.
+ The text of the paragraph has no special internal structure. All visual
+ enhancement commands may be used inside the paragraph.
+ Multiple adjacent \\bug commands will be joined into a single paragraph.
+ Each bug description will start on a new line.
+ Alternatively, one \\bug command may mention
+ several bugs. The \\bug command ends when a blank line or some other
+ sectioning command is encountered. See section \ref cmdauthor for an
+ example.
+
+<hr>
+\subsection cmddate \date { date description }
+
+ \addindex \date
+ Starts a paragraph where one or more dates may be entered.
+ The paragraph will be indented.
+ The text of the paragraph has no special internal structure. All visual
+ enhancement commands may be used inside the paragraph.
+ Multiple adjacent \\date commands will be joined into a single paragraph.
+ Each date description will start on a new line.
+ Alternatively, one \\date command may mention
+ several dates. The \\date command ends when a blank line or some other
+ sectioning command is encountered. See section \ref cmdauthor for an
+ example.
+
+ \sa Section \ref cmdjddate.
+
+<hr>
+\subsection cmdpar \par (paragraph title) { paragraph }
+
+ \addindex \par
+ Starts a paragraph with a user defined heading. The heading is
+ specified using the paragraph title argument and extends until the end of the
+ line. The paragraph will be indented.
+ The text of the paragraph has no special internal structure. All visual
+ enhancement commands may be used inside the paragraph.
+ The \\par command ends when a blank line or some other
+ sectioning command is encountered.
+
+ \par Example:
+ \verbinclude par.cpp
+ \htmlonly
+ Click <a href="$(DOXYGEN_DOCDIR)/examples/par/html/class_test.html">here</a>
+ for the corresponding HTML documentation that is generated by Doxygen.
+ \endhtmlonly
+
+<hr>
+\subsection cmdparam \param <parameter-name> { parameter description }
+
+ \addindex \param
+ Starts a parameter description for a function parameter with name
+ \<parameter-name\>. Followed by a description of the parameter.
+ The existence of the parameter is not checked.
+ The text of the paragraph has no special internal structure. All visual
+ enhancement commands may be used inside the paragraph.
+ Multiple adjacent \\param commands will be joined into a single paragraph.
+ Each parameter description will start on a new line.
+ The \\param description ends when a blank line or some other
+ sectioning command is encountered. See section \ref cmdfn for an
+ example.
+
+ \sa Section \ref cmdjdparam.
+
+<hr>
+\subsection cmdexception \exception <exception-object> { exception description }
+
+ \addindex \exception
+ Starts an exception description for an exception object with name
+ \<exception-object\>. Followed by a description of the exception.
+ The existence of the exception object is not checked.
+ The text of the paragraph has no special internal structure. All visual
+ enhancement commands may be used inside the paragraph.
+ Multiple adjacent \\exception commands will be joined into a single paragraph.
+ Each parameter description will start on a new line.
+ The \\exception description ends when a blank line or some other
+ sectioning command is encountered. See section \ref cmdfn for an
+ example.
+
+ \sa Section \ref cmdjdexception.
+
+<hr>
+\subsection cmdreturn \return { description of the return value }
+
+ \addindex \return
+ Starts a return value description for a function.
+ The text of the paragraph has no special internal structure. All visual
+ enhancement commands may be used inside the paragraph.
+ Multiple adjacent \\return commands will be joined into a single paragraph.
+ The \\return description ends when a blank line or some other
+ sectioning command is encountered. See section \ref cmdfn for an
+ example.
+
+ \sa Section \ref cmdjdreturn.
+
+<hr>
+\subsection cmdsa \sa { references }
+
+ \addindex \sa
+ Starts a paragraph where one or more cross-references to classes,
+ functions, methods, variables, files or URL may be specified.
+ The separators \c :: and \c # may be used to separate a class from the
+ name of its members. One of several overloaded methods or constructors
+ may be selected by including a parenthesized list of argument types after
+ the method.
+
+ \sa section \ref autolink for information on how to create links to objects
+ and section \ref cmdjdsee for the JavaDoc version of this command.
+
+<hr>
+\subsection cmdversion \version { version number }
+
+ \addindex \version
+ Starts a paragraph where one or more version strings may be entered.
+ The paragraph will be indented.
+ The text of the paragraph has no special internal structure. All visual
+ enhancement commands may be used inside the paragraph.
+ Multiple adjacent \\version commands will be joined into a single paragraph.
+ Each version description will start on a new line.
+ Alternatively, one \\version command may mention
+ several dates. The \\version command ends when a blank line or some other
+ sectioning command is encountered. See section \ref cmdauthor for an
+ example.
+
+ \sa Section \ref cmdjdversion.
+
+<hr>
+\subsection cmdwarning \warning { warning message }
+
+ \addindex \warning
+ Starts a paragraph where one or more warning messages may be entered.
+ The paragraph will be indented.
+ The text of the paragraph has no special internal structure. All visual
+ enhancement commands may be used inside the paragraph.
+ Multiple adjacent \\warning commands will be joined into a single paragraph.
+ Each warning description will start on a new line.
+ Alternatively, one \\warning command may mention
+ several warnings. The \\warning command ends when a blank line or some other
+ sectioning command is encountered. See section \ref cmdauthor for an
+ example.
+
+<h2>\htmlonly <center> --- \endhtmlonly
+ Commands to create links
+ \htmlonly --- </center>\endhtmlonly</h2>
+
+\subsection cmdaddindex \addindex <word>
+
+ \addindex \addindex
+ This command adds \<word\> to the \htmlonly LaTeX\endhtmlonly
+ \latexonly\LaTeX\ \endlatexonly index.
+
+\subsection cmdendlink \endlink
+
+ \addindex \endlink
+ This command ends a link that is started with the \\link command.
+
+ \sa section \ref cmdlink.
+
+<hr>
+\subsection cmdlink \link <link-object>
+
+ \addindex \link
+ The links that are automatically generated by Doxygen always have the
+ name of the object they point to as link-text.
+
+ The \\link command can be used to create a link to an object (a file,
+ class, or member) with a user specified link-text.
+ The link command should end with an \\endlink command. All text between
+ the \\link and \\endlink commands serves as text for a link to
+ the \<link-object\> specified as the first argument of \\link.
+
+ See section \ref autolink for more information on automatically
+ generated links and valid link-objects.
+
+ \b Notice:
+ Keep in mind that links are only meaningful in HTML text;
+ in \htmlonly LaTeX\endhtmlonly\latexonly\LaTeX\ \endlatexonly
+ text, the link text is just written to the output.
+
+<hr>
+\subsection cmdref \ref <section-name>
+
+ \addindex \ref
+ Creates a reference to a named section, subsection, or page.
+ For HTML documentation the reference command will generate a link to
+ the section, the title of the section will be used as the link text.
+ For \htmlonly LaTeX\endhtmlonly\latexonly\LaTeX\ \endlatexonly documentation the reference command will generate a section
+ number.
+
+ See section \ref cmdpage for an example of the \\ref command.
+
+<hr>
+\subsection cmdsection \section <section-name> (section title)
+
+ \addindex \section
+ Creates a section with name \<section-name\>. The title of the
+ section should be specified as the second argument of the \\section
+ command.
+
+ See section \ref cmdpage for an example of the \\cmdsection command.
+<hr>
+\subsection cmdsubsection \subsection <subsection-name> (subsection title)
+
+ \addindex \subsection
+ Creates a subsection with name \<subsection-name\>. The title of the
+ subsection should be specified as the second argument of the \\subsection
+ command.
+
+ See section \ref cmdpage for an example of the \\cmdsubsection command.
+<hr>
+
+<h2>\htmlonly <center> --- \endhtmlonly
+ Commands for displaying examples
+ \htmlonly --- </center>\endhtmlonly</h2>
+
+\subsection cmddontinclude \dontinclude <file-name>
+
+ \addindex \dontinclude
+ This command can be used to parse a source file without actually
+ including it. Any class and member declarations inside the code
+ are `remembered' during the parsing of the comment block that contained
+ the \\dontinclude command.
+
+ For line by line description of source files, one or more lines
+ of the example can be displayed using the \\line, \\skip, \\skipline, and
+ \\until commands. An internal pointer is used for these commands. The
+ \\dontinclude command sets the pointer to the first line of the example.
+
+ \par Example:
+ \verbinclude include.cpp
+ Where the example file \c example_test.cpp looks as follows:
+ \verbinclude example_test.cpp
+ \htmlonly
+ Click <a href="$(DOXYGEN_DOCDIR)/examples/include/html/example.html">here</a>
+ for the corresponding HTML documentation that is generated by Doxygen.
+ \endhtmlonly
+
+ \sa sections \ref cmdline, \ref cmdskip, \ref cmdskipline, and \ref cmduntil.
+
+<hr>
+\subsection cmdinclude \include <file-name>
+
+ \addindex \include
+ This command can be used to include a source file as a block of code.
+ The command takes the name of an include file as an argument.
+ Include files or directories can be specified using the
+ \c INCLUDE_PATH tag of Doxygen's configuration file.
+
+ Using the \\include command is equivalent to inserting the file into
+ the documentation block and surrounding it
+ with \\code and \\endcode commands.
+
+ The main purpose of the \\include command is to avoid code
+ duplication in case of example blocks that consist of multiple
+ source and header files.
+
+ For line by line description of source files, one or more lines
+ of the example can be displayed using the \\line, \\skip, \\skipline, and
+ \\until commands. An internal pointer is used for these command. The
+ \\include command sets the pointer to the first line of the example.
+
+ \sa section \ref cmdexample and \ref cmddontinclude.
+
+<hr>
+\subsection cmdline \line ( pattern )
+
+ \addindex \line
+ This command searches line by line through the example that was last
+ included using \\include or \\dontinclude until it finds a non-blank
+ line. If that line contains the specified pattern, it is written
+ to the output.
+
+ The internal pointer that is used to keep track of the current line in
+ the example, is set to the start of the line following the non-blank
+ line that was found (or to the end of the example if no such line could
+ be found).
+
+ See section \ref cmddontinclude for an example.
+
+<hr>
+\subsection cmdskip \skip ( pattern )
+
+ \addindex \skip
+ This command searches line by line through the example that was last
+ included using \\include or \\dontinclude until it finds a line that contains
+ the specified pattern.
+
+ The internal pointer that is used to keep track of the current line in
+ the example, is set to the start of the line that contains the specified
+ pattern (or to the end of the example if the pattern could not be found).
+
+ See section \ref cmddontinclude for an example.
+
+<hr>
+\subsection cmdskipline \skipline ( pattern )
+
+ \addindex \skipline
+ This command searches line by line through the example that was last
+ included using \\include or \\dontinclude until it finds a line that contains
+ the specified pattern. It then writes the line to the output.
+
+ The internal pointer that is used to keep track of the current line in
+ the example, is set to the start of the line following the line that is
+ written (or to the end of the example if the pattern could not be found).
+
+ \par Notice:
+ The command:
+ \verbatim\skipline pattern\endverbatim
+ is equivalent to:
+\verbatim
+\skip pattern
+\line pattern\endverbatim
+
+ See section \ref cmddontinclude for an example.
+
+<hr>
+\subsection cmduntil \until ( pattern )
+
+ \addindex \until
+ This command writes all lines of the example that was last
+ included using \\include or \\dontinclude to the output, until it finds
+ a line containing the specified pattern. The line containing the pattern
+ will be written as well.
+
+ The internal pointer that is used to keep track of the current line in
+ the example, is set to the start of the line following last written
+ line (or to the end of the example if the pattern could not be found).
+
+ See section \ref cmddontinclude for an example.
+
+<hr>
+\subsection cmdverbinclude \verbinclude <file-name>
+
+ \addindex \verbinclude
+ This command includes the file \<file-name\> verbatim in the documentation.
+ The command is equivalent to pasting the file in the documentation and
+ placing \\verbatim and \\endverbatim commands around it.
+
+<hr>
+<h2>\htmlonly <center> --- \endhtmlonly
+ Commands for visual enhancements
+ \htmlonly --- </center>\endhtmlonly</h2>
+
+\subsection cmda \a <word>
+
+ \addindex \a
+ Displays the argument \<word\> using a special font.
+ Use this command to refer to member arguments in the running text.
+
+ \par Example:
+ \verbatim
+ ... the \a x and \y coordinates are used to ...
+ \endverbatim
+ This will result in the following text:<br><br>
+ ... the \a x and \a y coordinates are used to ...
+
+<hr>
+\subsection cmdarg \arg { item-description }
+
+ \addindex \arg
+ This command has one argument that continues until the first
+ blank line or until another \\arg is encountered.
+ The command can be used to generate a simple, not nested list of
+ arguments.
+ Each argument should start with a \\arg command.
+
+ \par Example:
+ Typing:
+ \verbatim
+ \arg \c AlignLeft left alignment.
+ \arg \c AlignCenter center alignment.
+ \arg \c AlignRight right alignment
+
+ No other types of alignment are supported.
+ \endverbatim
+ will result in the following text:<br><br>
+ <ul>
+ <li> \c AlignLeft left alignment.
+ <li> \c AlignCenter center alignment.
+ <li> \c AlignRight right alignment
+ </ul><br>
+ No other types of alignment are supported.
+
+ \par Notice:
+ For nested lists, HTML commands should be used.
+
+<hr>
+\subsection cmdb \b <word>
+
+ \addindex \b
+ Displays the argument \<word\> using a bold font.
+ Equivalent to \<b\>word\</b\>.
+
+<hr>
+\subsection cmdc \c <word>
+
+ \addindex \c
+ Displays the argument \<word\> using a typewriter font.
+ Use this to refer to a word of code.
+ Equivalent to \<tt\>word\</tt\>.
+
+ \par Example:
+ Typing:
+ \verbatim
+ ... This function returns \c void and not \c int ...
+ \endverbatim
+ will result in the following text:<br><br>
+ ... This function returns \c void and not \c int ...
+
+<hr>
+\subsection cmde \e <word>
+
+ \addindex \e
+ Displays the argument \<word\> in italics.
+ Use this command to emphasize words.
+
+ \par Example:
+ Typing:
+ \verbatim
+ ... this is a \e really good example ...
+ \endverbatim
+ will result in the following text:<br><br>
+ ... this is a \e really good example ...
+
+<hr>
+\subsection cmdendhtmlonly \endhtmlonly
+
+ \addindex \endhtmlonly
+ Ends a block of text that was started with a \\htmlonly command.
+
+ \sa section \ref cmdhtmlonly.
+
+<hr>
+\subsection cmdendlatexonly \endlatexonly
+
+ \addindex \endlatexonly
+ Ends a block of text that was started with a \\latexonly command.
+
+ \sa section \ref cmdlatexonly.
+
+<hr>
+\subsection cmdendverbatim \endverbatim
+
+ \addindex \endverbatim
+ Ends a block of text that was started with a \\verbatim command.
+
+ \sa section \ref cmdverbatim.
+
+<hr>
+\subsection cmdfdollar \f$
+
+ \addindex \\f$
+
+ Marks the start and end of an in-text formula.
+ \sa section \ref formulas for an example.
+
+<hr>
+\subsection cmdfbropen \f[
+
+ \addindex \\f[
+
+ Marks the start of a long formula that is displayed
+ centered on a separate line.
+ \sa section \ref cmdfbrclose and section \ref formulas.
+
+<hr>
+\subsection cmdfbrclose \f]
+
+ \addindex \\f]
+
+ Marks the end of a long formula that is displayed
+ centered on a separate line.
+ \sa section \ref cmdfbropen and section \ref formulas.
+
+<hr>
+\subsection cmdhtmlonly \htmlonly
+
+ \addindex \htmlonly
+ Starts a block of text that will be verbatim included in the
+ generated HTML documentation only. The block ends with a
+ endhtmlonly command.
+
+ This command can be used to include HTML code that is too complex
+ for Doxygen (i.e. images, applets, java-scripts, and HTML tags that
+ require attributes). You can use the \\latexonly and \\endlatexonly
+ pair to provide a proper \htmlonly LaTeX\endhtmlonly\latexonly\LaTeX\ \endlatexonly alternative.
+
+ \b Notice:
+ environment variables (like \$(HOME) ) are resolved inside a
+ HTML-only block.
+
+ \sa section \ref cmdhtmlonly and section \ref cmdlatexonly.
+
+<hr>
+\subsection cmdlatexonly \latexonly
+
+ \addindex \latexonly
+ Starts a block of text that will be verbatim included in the
+ generated \htmlonly LaTeX\endhtmlonly\latexonly\LaTeX\ \endlatexonly documentation only. The block ends with a
+ endlatexonly command.
+
+ This command can be used to include \htmlonly LaTeX\endhtmlonly\latexonly\LaTeX\ \endlatexonly code that is too complex
+ for Doxygen (i.e. images, formulas, special characters). You can use the
+ \\htmlonly and \\endhtmlonly pair to provide a proper HTML alternative.
+
+ \b Notice:
+ environment variables (like \$(HOME) ) are resolved inside a
+ \htmlonly LaTeX\endhtmlonly\latexonly\LaTeX\endlatexonly-only block.
+
+ \sa section \ref cmdlatexonly and section \ref cmdhtmlonly.
+
+<hr>
+\subsection cmdverbatim \verbatim
+
+ \addindex \verbatim
+ Starts a block of text that will be verbatim included in both the
+ HTML and the \htmlonly LaTeX\endhtmlonly\latexonly\LaTeX\ \endlatexonly documentation. The block should end with a
+ \\endverbatim block. All commands are disabled in a verbatim block.
+
+ \warning Make sure you include a \\endverbatim command for each
+ \\verbatim command or the parser will get confused!
+
+<hr>
+\subsection cmdbackslash \\
+
+ \addindex \\
+ This command writes a backslash character (\\) to the HTML and \htmlonly LaTeX\endhtmlonly\latexonly\LaTeX\ \endlatexonly output.
+ The backslash has to be escaped in some cases because Doxygen uses it to
+ detect commands.
+
+<hr>
+\subsection cmdat \@
+
+ \addindex \@
+ This command writes an at-sign (@) to the HTML and \htmlonly LaTeX\endhtmlonly\latexonly\LaTeX\ \endlatexonly output.
+ The at-sign has to be escaped in some cases because Doxygen uses it to
+ detect JavaDoc commands.
+
+<hr>
+\subsection cmdamp \&
+
+ \addindex \&
+ This command writes the \& character to the HTML and \htmlonly LaTeX\endhtmlonly\latexonly\LaTeX\ \endlatexonly output. This
+ character has to be escaped because it has a special meaning in HTML.
+
+<hr>
+\subsection cmddollar \$
+
+ \addindex \$
+ This command writes the \$ character to the HTML and \htmlonly LaTeX\endhtmlonly\latexonly\LaTeX\ \endlatexonly output. This
+ character has to be escaped in some cases, because it is used to expand
+ environment variables.
+
+<hr>
+\subsection cmdhash \#
+
+ \addindex \#
+ This command writes the \# character to the HTML and \htmlonly LaTeX\endhtmlonly\latexonly\LaTeX\ \endlatexonly output. This
+ character has to be escaped in some cases, because it is used to refer
+ to documented entities.
+
+<hr>
+\subsection cmdlt \\<
+
+ \addindex \\<
+ This command writes the \< character to the HTML and \htmlonly LaTeX\endhtmlonly\latexonly\LaTeX\ \endlatexonly output. This
+ character has to be escaped because it has a special meaning in HTML.
+
+<hr>
+\subsection cmdgt \\>
+
+ \addindex \\>
+ This command writes the \> character to the HTML and \htmlonly LaTeX\endhtmlonly\latexonly\LaTeX\ \endlatexonly output. This
+ character has to be escaped because it has a special meaning in HTML.
+
+<hr>
+
+<h2>\htmlonly <center> --- \endhtmlonly
+ Commands included for JavaDoc compatibility
+ \htmlonly --- </center>\endhtmlonly</h2>
+
+The following command JavaDoc command are support.
+
+\subsection cmdjdauthor @author { list of authors }
+ \addindex @author
+ Equivalent to \\author (see section \ref cmdauthor).
+\subsection cmdjddate @date { date description }
+ \addindex @date
+ Equivalent to \\date (see section \ref cmddate).
+\subsection cmdjdparam @param <parameter-name> { parameter-description }
+ \addindex @param
+ Equivalent to \\param (see section \ref cmdparam).
+\subsection cmdjdexception @exception <exception-object> { exception-description }
+ \addindex @exception
+ Equivalent to \\exception (see section \ref cmdexception).
+\subsection cmdjdreturn @return { description of the return value }
+ \addindex @return
+ Equivalent to \\return (see section \ref cmdreturn).
+\subsection cmdjdsee @see { references }
+ \addindex @see
+ Equivalent to \\sa (see section \ref cmdsa).
+\subsection cmdjdshort @short { brief description }
+ \addindex @short
+ Equivalent to \\brief (see section \ref cmdbrief).
+\subsection cmdjdversion @version { version number }
+ \addindex @version
+ Equivalent to \\version (see section \ref cmdversion).
+
+<h2>\htmlonly <center> --- \endhtmlonly
+ Commands included for Qt compatibility
+ \htmlonly --- </center>\endhtmlonly</h2>
+
+The following commands are supported to remain compatible to the Qt class
+browser generator. Do \e not use these commands in your own documentation.
+<ul>
+<li>\\annotatedclasslist
+<li>\\classhierarchy
+<li>\\define
+<li>\\functionindex
+<li>\\header
+<li>\\headerfilelist
+<li>\\ingroup
+<li>\\inherit
+<li>\\l
+<li>\\postheader
+</ul>
+
+*/
diff --git a/doc/config.doc b/doc/config.doc
new file mode 100644
index 0000000..0412634
--- /dev/null
+++ b/doc/config.doc
@@ -0,0 +1,553 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+/*! \page config
+
+\section config Configuration
+
+\subsection config_format Format
+
+A configuration file is a free-form ASCII text file with a structure that
+is similar to that of a Makefile. It is parsed by a
+recursive-descent parser that is built into \c doxygen.
+The file may contain tabs and newlines for formatting purposes.
+The statements in the file are case-sensitive.
+Comments may be placed anywhere within the file (except within quotes).
+Comments begin with the \c # character and end at the end of the
+line.
+
+The file essentially consists of a list of assignment statements.
+Each statement consists of a \c TAG_NAME written in capitals,
+followed by the \c = character and one or more values.
+Values are sequences of non-blanks. If the value should contain one or more
+blanks it must be surrounded by quotes (&quot;...&quot;).
+Multiple lines can be concatenated by inserting a backslash (\\)
+as the last character of a line.
+Environment variables can expanded using the pattern \$(ENV_VARIABLE_NAME).
+
+The configuration options can be divided into several categories.
+Below is a list of tags that are recognized for each category.
+
+\subsection config_general General options
+<dl>
+
+<dt>\c PROJECT_NAME <dd>
+ \addindex PROJECT_NAME
+ The \c PROJECT_NAME tag is a single word (or a sequence of words
+ surrounded by double-quotes) that should identify the project for which the
+ documentation is generated. This name is used in the title of most
+ generated pages and in a few other places.
+
+<dt>\c PROJECT_NUMBER <dd>
+ \addindex PROJECT_NUMBER
+ The \c PROJECT_NUMBER tag can be used to enter a project or revision number.
+ This could be handy for archiving the generated documentation or
+ if some version control system is used.
+
+<dt>\c OUTPUT_DIRECTORY <dd>
+ \addindex OUTPUT_DIRECTORY
+ The \c OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
+ path into which the generated HTML and Latex documentation will be written.
+ If a relative path is entered, it will be relative to the location
+ where doxygen was started. If left blank the current directory will be used.
+
+<dt>\c QUIET <dd>
+ \addindex QUIET
+ The \c QUIET tag can be used to turn on/off the messages that are generated
+ to standard output by doxygen. Possible values are \c YES and \c NO,
+ where \c YES implies that the messages are off.
+ If left blank \c NO is used.
+
+<dt>\c WARNINGS <dd>
+ \addindex WARNINGS
+ The \c WARNINGS tag can be used to turn on/off the warning messages that are
+ generated to standard error by doxygen. Possible values are \c YES and \c NO,
+ where \c YES implies that the warnings are on. If left blank \c NO is used.
+
+ \b Tip: Turn warnings on while writing the documentation.
+
+<dt>\c DISABLE_INDEX <dd>
+ \addindex DISABLE_INDEX
+ If you want full control over the layout of the generated HTML pages it
+ might be necessary to disable the index and replace it with your own.
+ The DISABLE_INDEX tag can be used to turn on/off the condensed index at
+ top of each page. A value of NO (the default) enables the index and the
+ value YES disables it.
+
+<dt>\c EXTRACT_ALL <dd>
+ \addindex EXTRACT_ALL
+ If the \c EXTRACT_ALL tag is set to \c YES all classes and functions will be
+ included in the documentation, even if no documentation was available.
+
+ \b Notice: This will also disable the warnings about undocumented members
+ that are normally produced when \c WARNINGS is set to \c YES
+
+<dt>\c EXTRACT_PRIVATE <dd>
+ \addindex EXTRACT_PRIVATE
+ If the \c EXTRACT_PRIVATE tag is set to \c YES all
+ documentation for private members will be extracted as well.
+
+<dt>\c HIDE_UNDOC_MEMBERS <dd>
+ \addindex HIDE_UNDOC_MEMBERS
+ If the \c HIDE_UNDOC_MEMBERS tag is set to \c YES, Doxygen will hide all
+ undocumented members inside documented classes or files.
+ If set to \c NO (the default) these members will be included in the
+ various overviews, but no documentation section is generated.
+
+<dt>\c HIDE_UNDOC_CLASSES <dd>
+ \addindex HIDE_UNDOC_CLASSES
+ If the \c HIDE_UNDOC_CLASSESS tag is set to \c YES, Doxygen will hide all
+ undocumented classes.
+ If set to \c NO (the default) these classes will be included in the
+ various overviews.
+
+<dt>\c BRIEF_MEMBER_DESC <dd>
+ \addindex BRIEF_MEMBER_DESC
+ If the \c BRIEF_MEMBER_DESC tag is set to \c YES (the default) Doxygen will
+ include brief member descriptions after the members that are listed in
+ the file and class documentation (similar to JavaDoc).
+ Set to NO to disable this.
+
+<dt>\c INTERNAL_DOCS <dd>
+ \addindex INTERNAL_DOCS
+ The \c INTERNAL_DOCS tag determines if documentation
+ that is typed after a \\internal command is included. If the tag is set
+ to \c NO (the default) then the documentation will be excluded.
+ Set it to \c YES to include the internal documentation.
+
+<dt>\c REPEAT_BRIEF <dd>
+ \addindex REPEAT_BRIEF
+ If the \c REPEAT_BRIEF tag is set to \c YES (the default) Doxygen will
+ prepend the brief description of a member or function before the detailed
+ description
+
+ \par Notice:
+ If both \c HIDE_UNDOC_MEMBERS and \c BRIEF_MEMBER_DESC are set to \c NO, the
+ brief descriptions will be completely suppressed.
+
+<dt>\c FULL_PATH_NAMES <dd>
+ \addindex FULL_PATH_NAMES
+ If the \c FULL_PATH_NAMES tag is set to \c YES Doxygen will prepend the full
+ path before files name in the file list and in the header files. If set
+ to NO the shortest path that makes the file name unique will be used
+
+<dt>\c STRIP_FROM_PATH <dd>
+ \addindex STRIP_FROM_PATH
+ If the \c FULL_PATH_NAMES tag is set to \c YES then the \c STRIP_FROM_PATH tag
+ can be used to strip a user defined part of the path. Stripping is
+ only done if the specified string matches the left-hand part of the
+ path.
+
+<dt>\c CLASS_DIAGRAMS <dd>
+ \addindex CLASS_DIAGRAMS
+ If the \c CLASS_DIAGRAMS tag is set to \c YES (the default) Doxygen will
+ generate a class diagram (in Html and LaTeX) for classes with base or
+ super classes. Setting the tag to \c NO turns the diagrams off.
+
+<dt>\c CASE_SENSE_NAMES <dd>
+ \addindex CASE_SENSE_NAMES
+ If the \c CASE_SENSE_NAMES tag is set to \c NO (the default) then Doxygen
+ will only generate file names in lower case letters. If set to
+ \c YES upper case letters are also allowed. This is useful if you have
+ classes or files whose names only differ in case and if your file system
+ supports case sensitive file names.
+
+<dt>\c VERBATIM_HEADERS <dd>
+ \addindex VERBATIM_HEADERS
+ If the VERBATIM_HEADERS tag is set the YES (the default) then Doxygen\n";
+ will generate a verbatim copy of the header file for each class for\n";
+ which an include is specified. Set to NO to disable this.\n";
+ \sa Section \ref cmdclass.
+
+</dl>
+
+\subsection config_input Input related options
+<dl>
+
+<dt>\c INPUT <dd>
+ \addindex INPUT
+ The \c INPUT tag is used to specify the files and/or directories that contain
+ documented source files. You may enter file names like
+ \c myfile.cpp or directories like \c /usr/src/myproject.
+ Separate the files or directories with spaces.<br>
+
+ \b Notice: This tag (and only this tag) is \e required.
+
+<dt>\c FILE_PATTERNS <dd>
+ \addindex FILE_PATTERNS
+ If the value of the \c INPUT tag contains directories, you can use the
+ \c FILE_PATTERNS tag to specify one or more wildcard patterns
+ (like \c *.cpp and \c *.h ) to filter out the source-files
+ in the directories. If left blank all files are included
+ (i.e. wildcard <tt>*</tt>).
+
+<dt>\c RECURSIVE <dd>
+ \addindex RECURSIVE
+ The \c RECURSIVE tag can be used to specify whether or not subdirectories
+ should be searched for input files as well. Possible values are \c YES
+ and \c NO. If left blank \c NO is used.
+
+<dt>\c EXCLUDE <dd>
+ \addindex EXCLUDE
+ The \c EXCLUDE tag can be used to specify files and/or directories that should
+ excluded from the \c INPUT source files. This way you can easily exclude a
+ subdirectory from a directory tree whose root is specified with the \c INPUT tag.
+
+<dt>\c EXCLUDE_PATTERNS <dd>
+ \addindex EXCLUDE_PATTERNS
+ If the value of the INPUT tag contains directories, you can use the
+ \c EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+ certain files from those directories.
+
+
+<dt>\c EXAMPLE_PATH <dd>
+ \addindex EXAMPLE_PATH
+ The \c EXAMPLE_PATH tag can be used to specify one or more files or
+ directories that contain example code fragments that are included (see
+ the \\include command in section \ref cmdinclude).
+
+<dt>\c INCLUDE_PATH <dd>
+ \addindex INCLUDE_PATH
+ The INCLUDE_PATH tag can be used to specify one or more directories that
+ contain include files that are not input files but should be processed by
+ the preprocessor.
+
+<dt>\c INPUT_FILTER <dd>
+ \addindex INPUT_FILTER
+ The \c INPUT_FILTER tag can be used to specify a program that doxygen should
+ invoke to filter for each input file. Doxygen will invoke the filter program
+ by executing (via popen()) the command:
+\verbatim <filter> <input-file>
+\endverbatim
+
+ where \<filter\>
+ is the value of the \c INPUT_FILTER tag, and \<input-file\> is the name of an
+ input file. Doxygen will then use the output that the filter program writes
+ to standard output.
+
+</dl>
+
+\subsection html_output HTML related options
+<dl>
+
+<dt>\c GENERATE_HTML <dd>
+ \addindex GENERATE_HTML
+ If the \c GENERATE_HTML tag is set to \c YES (the default) Doxygen will
+ generate HTML output
+
+<dt>\c HTML_OUTPUT <dd>
+ \addindex HTML_OUTPUT
+ The \c HTML_OUTPUT tag is used to specify where the HTML docs will be put.
+ If a relative path is entered the value of \c OUTPUT_DIRECTORY will be
+ put in front of it. If left blank `html' will be used as the default path.
+
+<dt>\c HTML_HEADER <dd>
+ \addindex HTML_HEADER
+ The \c HTML_HEADER tag can be used to specify a user defined HTML
+ header file for each generated HTML page. To get valid HTML the header file
+ should contain at least a \c <HTML> and a \c <BODY> tag. Example:
+\verbatim
+ <HTML>
+ <HEAD>
+ <TITLE>My title</TITLE>
+ </HEAD>
+ <BODY BGCOLOR="#FFFFFF">
+\endverbatim
+ If the tag is left blank doxygen will generate a
+ standard header.
+
+<dt>\c HTML_FOOTER <dd>
+ \addindex HTML_FOOTER
+ The \c HTML_FOOTER tag can be used to specify a user defined HTML footer for
+ each generated HTML page. To get valid HTML the header file should contain
+ at least a \c </BODY> and a \c </HTML> tag. Example:
+\verbatim
+ </BODY>
+ </HTML>
+\endverbatim
+ If the tag is left blank doxygen will generate a standard footer.
+
+</dl>
+
+\subsection latex_output LaTeX related options
+<dl>
+
+<dt>\c GENERATE_LATEX <dd>
+ \addindex GENERATE_LATEX
+ If the \c GENERATE_LATEX tag is set to \c YES (the default) Doxygen will
+ generate Latex output.
+
+<dt>\c LATEX_OUTPUT <dd>
+ \addindex LATEX_OUTPUT
+ The \c LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
+ If a relative path is entered the value of \c OUTPUT_DIRECTORY will be
+ put in front of it. If left blank `latex' will be used as the default path.
+
+<dt>\c COMPACT_LATEX <dd>
+ \addindex COMPACT_LATEX
+ If the \c COMPACT_LATEX tag is set to \c YES Doxygen generates more compact
+ LaTeX documents. This may be useful for small projects and may help to
+ save some trees in general.
+
+<dt>\c PAPER_TYPE <dd>
+ \addindex PAPER_TYPE
+ The PAPER_TYPE tag can be used to set the paper type that is used
+ by the printer. Possible values are:
+ <ul>
+ <li><code>a4</code> (210 x 297 mm).
+ <li><code>a4wide</code> (same as a4, but including the a4wide package).
+ <li><code>letter</code> (8.5 x 11 inches).
+ <li><code>legal</code> (8.5 x 14 inches).
+ <li><code>executive</code> (7.25 x 10.5 inches)
+ </ul>
+ If left blank a4wide will be used.
+
+<dt>\c EXTRA_PACKAGES <dd>
+ \addindex EXTRA_PACKAGES
+ The EXTRA_PACKAGES tag can be used to specify one or more LaTeX
+ package names that should be included in the LaTeX output.
+ To get the times font for instance you can specify
+\verbatim
+EXTRA_PACKAGES = times
+\endverbatim
+ If left blank no extra packages will be included.
+</dl>
+
+\subsection man_output Man page related options
+<dl>
+
+<dt>\c GENERATE_MAN <dd>
+ \addindex GENERATE_MAN
+ If the \c GENERATE_MAN tag is set to \c YES (the default) Doxygen will
+ generate man pages for classes and files.
+
+<dt>\c MAN_OUTPUT <dd>
+ \addindex MAN_OUTPUT
+ The \c MAN_OUTPUT tag is used to specify where the man pages will be put.
+ If a relative path is entered the value of \c OUTPUT_DIRECTORY will be
+ put in front of it. If left blank `man' will be used as the default path.
+ A directory man3 will be created inside the directory specified by
+ \c MAN_OUTPUT.
+
+</dl>
+
+\subsection config_prepro Preprocessor related options
+<dl>
+
+<dt>\c ENABLE_PREPROCESSING <dd>
+ \addindex ENABLE_PREPROCESSING
+ If the \c ENABLE_PREPROCESSING tag is set to \c YES (the default) Doxygen will
+ evaluate all C-preprocessor directives found in the sources and include
+ files.
+
+<dt>\c MACRO_EXPANSION <dd>
+ \addindex MACRO_EXPANSION
+ If the \c MACRO_EXPANSION tag is set to \c YES Doxygen will expand all macro
+ names in the source code. If set to \c NO (the default) only conditional
+ compilation will be performed.
+
+<dt>\c SEARCH_INCLUDES <dd>
+ \addindex SEARCH_INCLUDES
+ If the \c SEARCH_INCLUDES tag is set to \c YES (the default) the includes files
+ in the \c INCLUDE_PATH (see below) will be search if a \#include is found.
+
+<dt>\c INCLUDE_PATH <dd>
+ \addindex INCLUDE_PATH
+ The \c INCLUDE_PATH tag can be used to specify one or more directories that
+ contain include files that are not input files but should be processed by
+ the preprocessor.
+
+<dt>\c PREDEFINED <dd>
+ \addindex PREDEFINED
+ The \c PREDEFINED tag can be used to specify one or more macro names that
+ are defined before the preprocessor is started (similar to the -D option of
+ gcc). The argument of the tag is a list of macros of the form:
+ <code>name</code> or <code>name=definition</code> (no spaces).
+ If the definition and the = are omitted =1 is assumed.
+
+<dt>\c EXPAND_ONLY_PREDEF <dd>
+ \addindex EXPAND_ONLY_PREDEF
+ If the \c EXPAND_ONLY_PREDEF and \c MACRO_EXPANSION tags are both set to YES
+ then the macro expansion is limited to the macros specified with the
+ \c PREDEFINED tag.
+
+</dl>
+
+\subsection config_extref External reference options
+<dl>
+
+<dt>\c TAGFILES <dd>
+ \addindex TAGFILES
+ The \c TAGFILES tag can be used to specify one or more tagfiles.
+ See section \ref doxytag_usage for more information about the usage of
+ tag files.
+
+ \par Notice:
+ Each tag file most have a unique name and if a tag file is not located
+ in the directory in which doxygen is run, you must also specify the
+ path to the tagfile here.
+
+<dt>\c GENERATE_TAGFILE <dd>
+ \addindex GENERATE_TAGFILE
+ When a file name is specified after \c GENERATE_TAGFILE, doxygen will create
+ a tag file that is based on the input files it reads.
+ See section \ref doxytag_usage for more information about the usage of
+ tag files.
+
+<dt>\c ALLEXTERNALS <dd>
+ \addindex ALLEXTERNALS
+ if the \c ALLEXTERNALS tag is set to \c YES all external class will be listed
+ in the class index. If set to \c NO only the inherited external classes
+ will be listed.
+
+<dt>\c PERL_PATH <dd>
+ \addindex PERL_PATH
+ The \c PERL_PATH should be the absolute path and name of the perl script
+ interpreter (i.e. the result of `<tt>which perl</tt>').
+
+</dl>
+\subsection config_search Search engine options
+<dl>
+
+<dt>\c SEARCHENGINE <dd>
+ \addindex SEARCHENGINE
+ The \c SEARCHENGINE tag specifies whether or not a
+ search should be used. Possible values are \c YES and \c NO.
+ If set to \c NO or left blank, the values of all other tags in this section
+ will be ignored.
+
+<dt>\c CGI_NAME <dd>
+ \addindex CGI_NAME
+ The \c CGI_NAME tag should be the name of the CGI script that
+ starts the search engine (<tt>doxysearch</tt>) with the correct parameters.
+ A script with this name will be generated by doxygen.
+
+<dt>\c CGI_URL <dd>
+ \addindex CGI_URL
+ The \c CGI_URL tag should be the absolute URL to the directory where the
+ cgi binaries are located. See the documentation of your http daemon for
+ details.
+
+<dt>\c DOC_URL <dd>
+ \addindex DOC_URL
+ The \c DOC_URL tag should be the absolute URL to the directory where the
+ documentation is located. If left blank the absolute path to the
+ documentation, with <tt>file://</tt> prepended to it, will be used.
+ This is correct for local viewing only.
+
+<dt>\c DOC_ABSPATH <dd>
+ \addindex DOC_ABSPATH
+ The \c DOC_ABSPATH tag should be the absolute path to the directory where the
+ documentation is located. If left blank the directory on the local machine
+ will be used.
+
+<dt>\c BIN_ABSPATH <dd>
+ \addindex BIN_ABSPATH
+ The \c BIN_ABSPATH tag must point to the directory where the doxysearch binary
+ is installed.
+
+<dt>\c EXT_DOC_PATHS <dd>
+ \addindex EXT_DOC_PATHS
+ The \c EXT_DOC_PATHS tag can be used to specify one or more paths to
+ documentation generated for other projects. This allows doxysearch to search
+ the documentation for these projects as well. All paths must be absolute.
+
+</dl>
+<h2>Examples</h2>
+
+Suppose you have a simple project consisting of two files: a source file
+\c example.cc and a header file \c example.h.
+Then a minimal configuration file is as simple as:
+\verbatim
+INPUT = example.cc example.h
+\endverbatim
+
+Assuming the example makes use of Qt classes and perl is located
+in <code>/usr/bin</code>, a more realistic configuration file would be:
+\verbatim
+PROJECT_NAME = Example
+INPUT = example.cc example.h
+WARNINGS = YES
+TAGFILES = qt.tag
+PERL_PATH = /usr/bin/perl
+SEARCHENGINE = NO
+\endverbatim
+
+To generate the documentation for the
+<a href="http://www.stack.nl/~dimitri/qdbttabular/index.html">QdbtTabular</a> package
+I have used the following configuration file:
+\verbatim
+PROJECT_NAME = QdbtTabular
+OUTPUT_DIRECTORY = html
+WARNINGS = YES
+INPUT = examples/examples.doc src
+FILE_PATTERNS = *.cc *.h
+INCLUDE_PATH = examples
+TAGFILES = qt.tag
+PERL_PATH = /usr/local/bin/perl
+SEARCHENGINE = YES
+CGI_NAME = search.cgi
+CGI_URL = http://www.stack.nl/~dimitri/cgi-bin
+DOC_URL = http://www.stack.nl/~dimitri/qdbttabular
+DOC_ABSPATH = /home/dimitri/.html/qdbttabular
+BIN_ABSPATH = /home/dimitri/bin
+\endverbatim
+
+To regenerate the Qt documentation from the sources, you could use the
+following config file:
+\verbatim
+PROJECT_NAME = Qt
+OUTPUT_DIRECTORY = qt_docs
+HIDE_UNDOC_MEMBERS = YES
+HIDE_UNDOC_CLASSES = YES
+ENABLE_PREPROCESSING = YES
+MACRO_EXPANSION = YES
+EXPAND_ONLY_PREDEF = YES
+SEARCH_INCLUDES = YES
+FULL_PATH_NAMES = YES
+STRIP_FROM_PATH = $(QTDIR)/
+PREDEFINED = USE_TEMPLATECLASS Q_EXPORT= \
+ QArrayT=QArray \
+ QListT=QList \
+ QDictT=QDict \
+ QQueueT=QQueue \
+ QVectorT=QVector \
+ QPtrDictT=QPtrDict \
+ QIntDictT=QIntDict \
+ QStackT=QStack \
+ QDictIteratorT=QDictIterator \
+ QListIteratorT=QListIterator \
+ QCacheT=QCache \
+ QCacheIteratorT=QCacheIterator \
+ QIntCacheT=QIntCache \
+ QIntCacheIteratorT=QIntCacheIterator \
+ QIntDictIteratorT=QIntDictIterator \
+ QPtrDictIteratorT=QPtrDictIterator
+INPUT = $(QTDIR)/doc \
+ $(QTDIR)/src/widgets \
+ $(QTDIR)/src/kernel \
+ $(QTDIR)/src/dialogs \
+ $(QTDIR)/src/tools
+FILE_PATTERNS = *.cpp *.h q*.doc
+INCLUDE_PATH = $(QTDIR)/include
+RECURSIVE = YES
+\endverbatim
+
+Here Doxygen's preprocessor is used to substitute some
+macro names that are normally substituted by the C preprocessor,
+but without doing full macro expansion.
+
+*/
+
diff --git a/doc/doxygen.sty b/doc/doxygen.sty
new file mode 100644
index 0000000..33835f0
--- /dev/null
+++ b/doc/doxygen.sty
@@ -0,0 +1,58 @@
+\NeedsTeXFormat{LaTeX2e}
+\ProvidesPackage{doxygen}
+\RequirePackage{calc}
+\RequirePackage{array}
+\pagestyle{fancyplain}
+\addtolength{\headwidth}{\marginparsep}
+\addtolength{\headwidth}{\marginparwidth}
+\newcommand{\clearemptydoublepage}{\newpage{\pagestyle{empty}\cleardoublepage}}
+\lhead[\fancyplain{}{\bfseries\thepage}]
+ {\fancyplain{}{\bfseries\rightmark}}
+\rhead[\fancyplain{}{\bfseries\leftmark}]
+ {\fancyplain{}{\bfseries\thepage}}
+\rfoot[\fancyplain{}{\bfseries\scriptsize User Manual for Doxygen $VERSION, written by Dimitri van Heesch \copyright 1997-1998}]{}
+\lfoot[]{\fancyplain{}{\bfseries\scriptsize User Manual for Doxygen $VERSION, written by Dimitri van Heesch \copyright 1997-1998}}
+\cfoot{}
+\newenvironment{CompactList}
+{\begin{list}{}{
+ \setlength{\leftmargin}{0.5cm}
+ \setlength{\itemsep}{0pt}
+ \setlength{\parsep}{0pt}
+ \setlength{\topsep}{0pt}
+ \renewcommand{\makelabel}{}}}
+{\end{list}}
+\newenvironment{CompactItemize}
+{
+ \begin{itemize}
+ \setlength{\itemsep}{-4pt}
+ \setlength{\parsep}{0pt}
+ \setlength{\topsep}{0pt}
+ \setlength{\partopsep}{0pt}
+}
+{\end{itemize}}
+\newcommand{\PBS}[1]{\let\temp=\\#1\let\\=\temp}
+\newlength{\tmplength}
+\newenvironment{TabularC}[1]
+{
+\setlength{\tmplength}
+ {\linewidth/(#1)-\tabcolsep*2-\arrayrulewidth*(#1+1)/(#1)}
+ \par\begin{tabular*}{\linewidth}
+ {*{#1}{|>{\PBS\raggedright\hspace{0pt}}p{\the\tmplength}}|}
+}
+{\end{tabular*}\par}
+\newcommand{\entrylabel}[1]{
+ {\parbox[b]{\labelwidth-4pt}{\makebox[0pt][l]{\textbf{#1}}\\}}}
+\newenvironment{Desc}
+{\begin{list}{}
+ {
+ \settowidth{\labelwidth}{40pt}
+ \setlength{\leftmargin}{\labelwidth}
+ \setlength{\parsep}{0pt}
+ \setlength{\itemsep}{-4pt}
+ \renewcommand{\makelabel}{\entrylabel}
+ }
+}
+{\end{list}}
+\setlength{\parindent}{0cm}
+\setlength{\parskip}{0.2cm}
+\sloppy
diff --git a/doc/doxygen_logo.eps b/doc/doxygen_logo.eps
new file mode 100644
index 0000000..90c6c92
--- /dev/null
+++ b/doc/doxygen_logo.eps
@@ -0,0 +1,3976 @@
+%!PS-Adobe-3.0 EPSF-3.0
+%%Creator: (ImageMagick)
+%%Title: (doxygen_logo.eps)
+%%CreationDate: (Thu Aug 13 14:21:32 1998)
+%%BoundingBox: 0 0 633 196
+%%DocumentData: Clean7Bit
+%%LanguageLevel: 1
+%%Pages: 0
+%%EndComments
+
+%%BeginDefaults
+%%PageOrientation: Portrait
+%%EndDefaults
+
+%%BeginProlog
+%
+% Display a color image. The image is displayed in color on
+% Postscript viewers or printers that support color, otherwise
+% it is displayed as grayscale.
+%
+/buffer 512 string def
+/byte 1 string def
+/color_packet 3 string def
+/pixels 768 string def
+
+/DirectClassPacket
+{
+ %
+ % Get a DirectClass packet.
+ %
+ % Parameters:
+ % red.
+ % green.
+ % blue.
+ % length: number of pixels minus one of this color (optional).
+ %
+ currentfile color_packet readhexstring pop pop
+ compression 0 gt
+ {
+ /number_pixels 3 def
+ }
+ {
+ currentfile byte readhexstring pop 0 get
+ /number_pixels exch 1 add 3 mul def
+ } ifelse
+ 0 3 number_pixels 1 sub
+ {
+ pixels exch color_packet putinterval
+ } for
+ pixels 0 number_pixels getinterval
+} bind def
+
+/DirectClassImage
+{
+ %
+ % Display a DirectClass image.
+ %
+ systemdict /colorimage known
+ {
+ columns rows 8
+ [
+ columns 0 0
+ rows neg 0 rows
+ ]
+ { DirectClassPacket } false 3 colorimage
+ }
+ {
+ %
+ % No colorimage operator; convert to grayscale.
+ %
+ columns rows 8
+ [
+ columns 0 0
+ rows neg 0 rows
+ ]
+ { GrayDirectClassPacket } image
+ } ifelse
+} bind def
+
+/GrayDirectClassPacket
+{
+ %
+ % Get a DirectClass packet; convert to grayscale.
+ %
+ % Parameters:
+ % red
+ % green
+ % blue
+ % length: number of pixels minus one of this color (optional).
+ %
+ currentfile color_packet readhexstring pop pop
+ color_packet 0 get 0.299 mul
+ color_packet 1 get 0.587 mul add
+ color_packet 2 get 0.114 mul add
+ cvi
+ /gray_packet exch def
+ compression 0 gt
+ {
+ /number_pixels 1 def
+ }
+ {
+ currentfile byte readhexstring pop 0 get
+ /number_pixels exch 1 add def
+ } ifelse
+ 0 1 number_pixels 1 sub
+ {
+ pixels exch gray_packet put
+ } for
+ pixels 0 number_pixels getinterval
+} bind def
+
+/GrayPseudoClassPacket
+{
+ %
+ % Get a PseudoClass packet; convert to grayscale.
+ %
+ % Parameters:
+ % index: index into the colormap.
+ % length: number of pixels minus one of this color (optional).
+ %
+ currentfile byte readhexstring pop 0 get
+ /offset exch 3 mul def
+ /color_packet colormap offset 3 getinterval def
+ color_packet 0 get 0.299 mul
+ color_packet 1 get 0.587 mul add
+ color_packet 2 get 0.114 mul add
+ cvi
+ /gray_packet exch def
+ compression 0 gt
+ {
+ /number_pixels 1 def
+ }
+ {
+ currentfile byte readhexstring pop 0 get
+ /number_pixels exch 1 add def
+ } ifelse
+ 0 1 number_pixels 1 sub
+ {
+ pixels exch gray_packet put
+ } for
+ pixels 0 number_pixels getinterval
+} bind def
+
+/PseudoClassPacket
+{
+ %
+ % Get a PseudoClass packet.
+ %
+ % Parameters:
+ % index: index into the colormap.
+ % length: number of pixels minus one of this color (optional).
+ %
+ currentfile byte readhexstring pop 0 get
+ /offset exch 3 mul def
+ /color_packet colormap offset 3 getinterval def
+ compression 0 gt
+ {
+ /number_pixels 3 def
+ }
+ {
+ currentfile byte readhexstring pop 0 get
+ /number_pixels exch 1 add 3 mul def
+ } ifelse
+ 0 3 number_pixels 1 sub
+ {
+ pixels exch color_packet putinterval
+ } for
+ pixels 0 number_pixels getinterval
+} bind def
+
+/PseudoClassImage
+{
+ %
+ % Display a PseudoClass image.
+ %
+ % Parameters:
+ % class: 0-PseudoClass or 1-Grayscale.
+ %
+ currentfile buffer readline pop
+ token pop /class exch def pop
+ class 0 gt
+ {
+ currentfile buffer readline pop
+ token pop /depth exch def pop
+ /grays columns 8 add depth sub depth mul 8 idiv string def
+ columns rows depth
+ [
+ columns 0 0
+ rows neg 0 rows
+ ]
+ { currentfile grays readhexstring pop } image
+ }
+ {
+ %
+ % Parameters:
+ % colors: number of colors in the colormap.
+ % colormap: red, green, blue color packets.
+ %
+ currentfile buffer readline pop
+ token pop /colors exch def pop
+ /colors colors 3 mul def
+ /colormap colors string def
+ currentfile colormap readhexstring pop pop
+ systemdict /colorimage known
+ {
+ columns rows 8
+ [
+ columns 0 0
+ rows neg 0 rows
+ ]
+ { PseudoClassPacket } false 3 colorimage
+ }
+ {
+ %
+ % No colorimage operator; convert to grayscale.
+ %
+ columns rows 8
+ [
+ columns 0 0
+ rows neg 0 rows
+ ]
+ { GrayPseudoClassPacket } image
+ } ifelse
+ } ifelse
+} bind def
+
+/DisplayImage
+{
+ %
+ % Display a DirectClass or PseudoClass image.
+ %
+ % Parameters:
+ % x & y translation.
+ % x & y scale.
+ % label pointsize.
+ % image label.
+ % image columns & rows.
+ % class: 0-DirectClass or 1-PseudoClass.
+ % compression: 0-RunlengthEncodedCompression or 1-NoCompression.
+ % hex color packets.
+ %
+ gsave
+ currentfile buffer readline pop
+ token pop /x exch def
+ token pop /y exch def pop
+ x y translate
+ currentfile buffer readline pop
+ token pop /x exch def
+ token pop /y exch def pop
+ currentfile buffer readline pop
+ token pop /pointsize exch def pop
+ /NewCenturySchlbk-Roman findfont pointsize scalefont setfont
+ x y scale
+ currentfile buffer readline pop
+ token pop /columns exch def
+ token pop /rows exch def pop
+ currentfile buffer readline pop
+ token pop /class exch def pop
+ currentfile buffer readline pop
+ token pop /compression exch def pop
+ class 0 gt { PseudoClassImage } { DirectClassImage } ifelse
+ grestore
+} bind def
+%%EndProlog
+%%Page: 1 1
+%%PageBoundingBox: 0 0 633 196
+userdict begin
+%%BeginData:
+DisplayImage
+0 0
+634 197
+18
+634 197
+0
+0
+ffffffffffffffffffffffffffffffffffffffffffffff4bfcfebc03fcfe9a00dcca9400
+fcf4c600ffffffffffffffffffffff68fcfebc00ffffff00fcfebc0bfcfe9a02fcdc8700
+e9d9b900ffffffffffffffffffffff60fcfebc0efcfe9a00fcfebc00fcfe9a01fcfebc00
+fcfe9a02fcfe8001fcdc8700e8cbab00fcf4c600ffffffffffffffffffffff5dfcfebc0f
+fcfe9a00fcfebc01fcfe9a03fcfe8000fcf49700fcfe8000fcfe9a00fcfebc00fcf49700
+fcecc400ffffffffffffffffffffff5bfcfebc07fcfe9a00fcfebc04fcfe9a00fcfebc01
+fcfe9a00fcfebc00fcfe9a02fcfe8000fcfe9a00fcfe8000fcfe9a01fcfebc01fcfe9a00
+fcf47100ffffffffffffffffffffff5afcfe9a00fcfebc00fcfe9a00fcfebc02fcfe9a00
+fcfebc03fcfe9a00fcfebc00fcfe9a00fcfebc01fcfe9a00fcfebc00fcfe9a00fcfebc00
+fcfe9a00fcfe8000fcfe9a00fcfe8001fcfe9a01fcfebc00fcfe9a01fcfe8000ffffffff
+ffffffffffffff5afcfebc03fcfe9a00fcfebc02fcfe9a00fcfebc03fcfe9a00fcfebc00
+fcfe9a00fcfebc00fcfe9a04fcfe8000fcfe9a00fcfe8001fcfebc01fcfe9a01fcfe8000
+fcfebc00ffffffffffffffffffffff59fcfe9a00fcfebc00fcfe9a00fcfebc03fcfe9a00
+fcfebc01fcfe9a00fcfebc00fcfe9a00fcfebc01fcfe9a01fcfebc00fcfe9a00fcfebc00
+fcfe9a00fcfe8000fcfe9a00fcfe8002fcfe9a00fcfebc01fcfe8001ffffffffffffffff
+ffffff5afcfebc01fcfe9a00fcfebc02fcfe9a00fcfebc01fcfe9a00fcfebc01fcfe9a00
+fcfebc00fcfe9a00fcfebc00fcfe9a04fcfe8001fcfe9a00fcfe8000fcfe9a01fcfebc00
+fcfe9a00fcfe8001fcfebc00ffffffffffffffffffffff59fcfebc00fcfe9a00fcfebc01
+fcfe9a00fcfebc06fcfe9a00fcfebc00fcfe9a01fcfebc00fcfe9a00fcfebc00fcfe9a01
+fcfe8001fcfe9a00fcfe8001fcfe9a02fcfe8001ffffffffffffffffffffff5afcfe9a00
+fcfebc00fcfe9a00fcfebc01fcfe9a00fcfebc00fcfe9a00fcfebc00fcfe9a00fcfebc00
+fcfe9a00fcfebc00fcfe9a00fcfebc00fcfe9a05fcfe8000fcfe9a00fcfe8000fcfe9a00
+fcfe8000fcfebc01fcfe9a00fcfe8001fcfebc00ffffffffffffffffffffff59fcfe9a00
+fcfebc02fcfe9a00fcfebc02fcfe9a00fcfebc02fcfe9a00fcfebc00fcfe9a02fcfebc00
+fcfe9a02fcfe8001fcfe9a00fcfe8001fcfe9a02fcfe8001fcfebc00ffffffffffffffff
+ffffff57f4f6f900ffffff00fcfe9a00fcfebc00fcfe9a00fcfebc00fcfe9a00fcfebc00
+fcfe9a00fcfebc01fcfe9a01fcfebc00fcfe9a00fcfebc00fcfe9a00fcfebc00fcfe9a04
+fcfe8001fcfe9a00fcfe8000fcfe9a01fcfebc00fcfe9a00fcfe8001ffffffffffffffff
+ffffff58f4f6f900fcfebc03fcfe9a00fcfebc01fcfe9a00fcfebc00fcfe9a00fcfebc01
+fcfe9a00fcfebc00fcfe9a00fcfebc00fcfe9a05fcfe8002fcfe9a00fcfe8000fcfe9a02
+fcfe8001fcfebc00ffffffffffffffffffffff56ecf3f501ffffff00fcfe9a01fcfebc01
+fcfe9a00fcfebc00fcfe9a00fcfebc00fcfe9a00fcfebc00fcfe9a00fcfebc00fcfe9a00
+fcfebc00fcfe9a01fcfebc00fcfe9a02fcfe8002fcfe9a00fcfe8001fcfebc00fcfe9a01
+fcfe8001fcfebc00ffffffffffffffffffffff55f4f6f900ecf3f500e8ecef00fcf4c600
+fcfe9a00fcfebc00fcfe9a00fcfebc00fcfe9a00fcfebc00fcfe9a00fcfebc00fcfe9a00
+fcfebc00fcfe9a00fcfebc01fcfe9a00fcfebc00fcfe9a05fcfe8001fcfe9a00fcfe8001
+fcfe9a01fcfe8001fcfe9a00fcfebc00ffffffffffffffffffffff55f4f6f900e8ecef00
+e0e4e700fcf4c600fcfebc00fcfe9a00fcfebc00fcfe9a00fcfebc00fcfe9a00fcfebc00
+fcfe9a00fcfebc00fcfe9a00fcfebc00fcfe9a00fcfebc00fcfe9a00fcfebc00fcfe9a04
+fcfe8002fcfe9a00fcfe8001fcfe9a01fcfe8002fcfebc00ffffffffffffffffffffff55
+f4f6f900e8ecef01fcf4c600fcfe9a00fcfebc00fcfe9a00fcfebc00fcfe9a00fcfebc00
+fcfe9a01fcfebc00fcfe9a00fcfebc00fcfe9a00fcfebc01fcfe9a06fcfe8001fcfe9a00
+fcfe8001fcfe9a00fcfe8000fcfe9a00fcfe8001fcfebc00ffffffffffffffffffffff55
+ecf3f500e8ecef00e0e4e700fcf4c600fcfebc00fcfe9a00fcfebc00fcfe9a00fcfebc00
+fcfe9a00fcfebc00fcfe9a01fcfebc00fcfe9a00fcfebc00fcfe9a01fcfebc00fcfe9a04
+fcfe8002fcfe9a00fcfe8001fcfe9a01fcfe8002fcfebc00ffffffffffffffffffffff55
+f4f6f900e8ecef01fcf4c600fcfe9a03fcfebc00fcfe9a02fcfebc00fcfe9a00fcfebc00
+fcfe9a00fcfebc01fcfe9a01fcfebc00fcfe9a03fcfe8000fcfe9a00fcfe8002fcfe9a00
+fcfe8003fcfebc00ffffffffffffffffffffff55f4f6f900e8ecef01fcf4c600fcfebc00
+fcfe9a00fcfebc00fcfe9a01fcfebc00fcfe9a00fcfebc00fcfe9a01fcfebc00fcfe9a00
+fcfebc00fcfe9a00fcfebc00fcfe9a05fcfe8000fcfe9a00fcfe8004fcfe9a00fcfe8001
+fcfebc00ffffffffffffffffffffff55f4f6f901e0e4e700fcf4c600fcfe9a00fcfebc00
+fcfe9a00fcfebc00fcfe9a03fcfebc00fcfe9a01fcfebc00fcfe9a00fcfebc00fcfe9a00
+fcfebc00fcfe9a00fcfebc00fcfe9a00fcfebc00fcfe9a00fcfe8001fcfe9a00fcfe8001
+fcfe9a00fcfe8003fcfebc00ffffffffffffffffffffff55f4f6f900ecf3f500e0e4e700
+f4f6f900fcfe9a0afcfebc00fcfe9a00fcfebc00fcfe9a08fcfe8007fcfebc00ffffffff
+ffffffffffffff55f4f6f900ecf3f500e8ecef00fcf4c600fcfe9a0dfcfebc00fcfe9a00
+fcfebc00fcfe9a00fcfebc00fcfe9a00fcfebc00fcfe8000fcfe9a01fcfe8006fcfebc00
+ffffffffffffffffffffff55f4f6f900ecf3f500e8ecef00fcf4c600fcfe9a0bfcfebc00
+fcfe9a00fcfebc00fcfe9a00fcfebc00fcfe9a01fcfebc00fcfe9a00fcfe8000fcfe9a00
+fcfe8000fcfe9a00fcfe8004fcf47100fcfebc00ffffffffffffffffffffff56e8ecef01
+fcf4c600fcfe9a04fcfe8000fcfe9a01fcfe8000fcfe9a04fcfebc00fcfe9a01fcfebc00
+fcfe9a05fcfe8002fcf47100fcfe8002fcfebc00ffffffffffffffffffffff55f4f6f900
+ecf3f500e8ecef00fcecc400fcfe9a00fcfe8000fcfe9a00fcfe8000fcfe9a01fcfe8000
+fcfe9a00fcfe8000fcfe9a00fcfe8000fcfe9a04fcfebc00fcfe9a01fcfebc00fcfe9a00
+fcfe8008fcf47100fcfebc00ffffffffffffffffffffff56e8ecef01fcf4c600fcfe8000
+fcfe9a00fcfe8000fcfe9a00fcfe8001fcfe9a00fcfe8000fcfe9a00fcfe8000fcfe9a00
+fcfe8000fcfe9a08fcfe8000fcfe9a00fcfe8001fcfe9a00fcfe8000fcf47100fcfe8002
+fcfebc00ffffffffffffffffffffff55f4f6f901e8ecef00f7ece700fcfe8000fcfe9a00
+fcfe8000fcfe9a00fcfe8000fcfe9a00fcfe8002fcfe9a00fcfe8000fcfe9a06fcfebc00
+fcfe9a02fcfe8008fcfebc00ffffffffffffffffffffff55f4f6f900e8ecef01fcf4c600
+fcfe8001fcfe9a00fcfe8003fcfe9a00fcfe8001fcfe9a00fcfe8000fcfe9a08fcfe8009
+fcfebc00ffffffffffffffffffffff55f4f6f901e0e4e700fcf4c600fcfe9a00fcfe8001
+fcfe9a00fcfe8000fcfe9a00fcfe8002fcfe9a00fcfe8000fcfe9a00fcfe8000fcfe9a07
+fcfe8002fcfe9a00fcfe8005fcfebc00ffffffffffffffffffffff55f4f6f900ecf3f500
+e8ecef00fcf4c600fcfe9a00fcfe8000fcfe9a00fcfe8004fcfe9a00fcfe8002fcfe9a08
+fcfe8009fcfebc00ffffffffffffffffffffff55f4f6f900ecf3f500e8ecef00fcecc400
+fcfe8000fcfe9a00fcfe8001fcfe9a00fcfe8000fcfe9a00fcfe8001fcfe9a01fcfe8000
+fcfe9a00fcfe8000fcfe9a06fcfe8004fcf47101fcfe8002fcfebc00ffffffffffffffff
+ffffff56e8ecef01fcf4c600fcfe8002fcfe9a00fcfe8003fcfe9a00fcfe8001fcfe9a02
+fcfe8000fcfe9a05fcfe8003fcf47102fcfe8002fcfebc00ffffffffffffffffffffff55
+f4f6f901e0e4e700fcf4c600fcfe9a00fcfe8003fcfe9a00fcfe8000fcfe9a00fcfe8000
+fcfe9a00fcfe8000fcfe9a00fcfe8000fcfe9a02fcfe8000fcfe9a02fcfe8002fcf47100
+fcfe8000fcf47101fcfe8002fcf47100fcfebc00ffffffffffffffffffffff55f4f6f900
+e8ecef01fcf4c600fcfe8005fcfe9a00fcfe8001fcfe9a00fcfe8000fcfe9a00fcfe8000
+fcfe9a00fcfe8000fcfe9a02fcfe8000fcfe9a00fcfe8003fcf47103fcfe8002fcfebc00
+ffffffffffffffffffffff55f4f6f901e8ecef00fcecc400fcfe8007fcfe9a00fcfe8001
+fcfe9a04fcfe8000fcfe9a02fcfe8001fcf47105fcfe8001fcf47100fcfebc00ffffffff
+ffffffffffffff56e8ecef01fcecc400fcfe8005fcfe9a00fcfe8002fcfe9a00fcfe8001
+fcfe9a00fcfe8000fcfe9a00fcfe8000fcfe9a00fcfe8002fcf47100fcfe8000fcf47103
+fcfe8000fcf47101fcfe8000fcfebc00ffffffffffffffffffffff55f4f6f900ecf3f500
+e8ecef00fcecc400fcfe8007fcfe9a00fcfe8000fcfe9a00fcfe8000fcfe9a00fcfe8000
+fcfe9a00fcfe8000fcfe9a00fcfe8000fcfe9a01fcfe8001fcf47101fce66a00fcf47102
+fcfe8000fcf47101fcfebc00ffffffffffffffffffffff55f4f6f900e8ecef01fcecc400
+fcfe8008fcfe9a00fcfe8000fcfe9a00fcfe8000fcfe9a00fcfe8000fcfe9a00fcfe8004
+fcf47102fce66a00fcf47101fcfe8000fcf47102fcfebc00ffffffffffffffffffffff55
+f4f6f901e8ecef00fcecc400fcfe8005fcfe9a00fcfe8000fcfe9a00fcfe8000fcfe9a00
+fcfe8000fcfe9a00fcfe8002fcfe9a00fcfe8000fcfe9a00fcfe8001fcf47102fce66a01
+fcf47101fcfe8000fcf47100fcec7600fcfebc00ffffffffffffffffffffff55f4f6f900
+ecf3f500e8ecef00fcecc400fcfe8007fcfe9a00fcfe8000fcfe9a00fcfe8002fcfe9a00
+fcfe8005fcf47101fce66a02fcf47103fce66a00fcfebc00ffffffffffffffffffffff55
+f4f6f900ecf3f500e8ecef00fcecc400fcfe8005fcfe9a01fcfe8000fcfe9a00fcfe8005
+fcfe9a00fcfe8000fcfe9a00fcfe8001fcf47101fce66a02fcf47104fcfebc00ffffffff
+ffffffffffffff56e8ecef01fcecc400fcfe8004fcfe9a00fcfe8001fcfe9a00fcfe8001
+fcfe9a00fcfe8008fcec7600fcf47100fce66a03fcf47102fce66a00fcfebc00ffffffff
+ffffffffffffff55f4f6f900ecf3f500e8ecef00fcecc400fcfe8006fcfe9a00fcfe8000
+fcfe9a00fcfe8008fcfe9a00fcfe8000fcf47100fce66a03fcf47103fcec7600fcfebc00
+ffffffffffffffffffffff55f4f6f900e8ecef01fcecc400fcfe8004fcfe9a00fcfe8000
+fcfe9a00fcfe800cfcf47100fce66a04fcf47102fcec7600fcfebc00ffffffffffffffff
+ffffff55f4f6f900ecf3f500e8ecef00fcecc400fcfe8005fcfe9a00fcfe800dfcf47100
+fce66a04fcf47100fcec7601fcf47100fcf4c600ffffffffffffffffffffff55f4f6f900
+e8ecef01fcecc400fcfe8004fcfe9a00fcfe8002fcfe9a00fcfe8007fcfe9a00fcfe8001
+fcf47100fce66a01fcdc6600fce66a01fcf47102fcec7600fcfebc00ffffffffffffffff
+ffffff55f4f6f900ecf3f500e0e4e700fcecc400fcfe8005fcfe9a00fcfe8000fcfe9a00
+fcfe800bfcec7600fce66a04fcf47100fcec7600fcf47101fcf4c600ffffffffffffffff
+ffffff55f4f6f900ecf3f500e8ecef00fcecc400fcfe8004fcfe9a00fcfe8000fcfe9a00
+fcfe800cfcf47100fce66a04fcf47100fcec7600fcf47100fcec7600fcfebc00ffffffff
+ffffffffffffff55f4f6f900ecf3f500e0e4e700fcecc400fcfe8006fcfe9a00fcfe800c
+fce66a02fcdc6600fce66a01fcec7601fcf47101fcf4c600ffffffffffffffffffffff55
+f4f6f900ecf3f500e8ecef00fcecc400fcfe8007fcfe9a00fcfe8000fcfe9a00fcfe8009
+fcec7600fce66a04fcf47100fcec7600fcf47100fce66a00fcfebc00ffffffffffffffff
+ffffff55f4f6f900ecf3f500e0e4e700fcecc400fcfe8005fcfe9a00fcfe800dfce66a00
+fcec7600fce66a02fcec7602fcf47100fce66a00fcfebc00ffffffffffffffffffffff55
+f4f6f900e8ecef01fcecc400fcfe8007fcfe9a00fcfe8000fcfe9a00fcfe8000fcfe9a00
+fcfe8007fce66a01fcdc6600fce66a00fcec7600fce66a00fcec7602fce66a00fcf4c600
+ffffffffffffffffffffff55f4f6f901e0e4e700fcecc400fcfe8009fcfe9a00fcfe8002
+fcfe9a00fcfe8001fcfe9a00fcfe8002fce66a00fcec7600fce66a02fcec7600fce66a00
+fcec7600fcf47100fce66a00fcf49700ffffffffffffffffffffff55f4f6f900e8ecef01
+fcecc400fcfe8007fcfe9a00fcfe8001fcfe9a00fcfe8000fcfe9a00fcfe8006fce66a01
+fcdc6600fce66a00fcec7601fce66a00fcec7600fce66a00fcdc6600fcf4c600ffffffff
+ffffffffffffff55f4f6f900ecf3f500e0e4e700fcecc400fcfe8008fcfe9a00fcfe8001
+fcfe9a00fcfe8001fcfe9a00fcfe8000fcfe9a00fcfe8002fce66a08fcdc6600fcf49700
+ffffffffffffffffffffff55f4f6f901e0e4e700fcecc400fcfe8006fcfe9a00fcfe8001
+fcfe9a00fcfe8001fcfe9a00fcfe8000fcfe9a00fcfe8003fcf47100fce66a00fcdc6601
+fce66a05fcdc6600fcf4c600ffffffffffffffffffffff55f4f6f900ecf3f500e0e4e700
+fcecc400fcfe8008fcfe9a00fcfe8001fcfe9a00fcfe8002fcfe9a00fcfe8003fcdc6602
+fce66a02fcdc6600fce66a01fcdc6600fcf49700ffffffffffffffffffffff55ecf3f500
+f4f6f900e0e4e700fcecc400fcfe8009fcfe9a00fcfe8002fcfe9a00fcfe8005fcdc6604
+fce66a00fcdc6601fce66a00fcdc6600fcf4c600ffffffffffffffffffffff55f4f6f900
+ecf3f500e0e4e700fcecc400fcf47100fcfe800afcfe9a00fcfe8006fcf47100fce66a00
+fcd46101fcdc6604fce66a00fcdc6600fcf49700ffffffffffffffffffffff55f4f6f900
+e8ecef01fbe4c100fcfe8000fcf47100fcfe8007fcfe9a00fcfe8008fcf47100fcd46103
+fcdc6601fcd46100fcdc6602fcf4c600ffffffffffffffffffffff55f4f6f900ecf3f500
+e0e4e700fbe4c100fcf47100fcfe8012fcf47100fcd46101fccc5d00fcd46104fcdc6600
+fcd46100fcf4c600ffffffffffffffffffffff55f4f6f900e8ecef01fcecc400fcf47103
+fcfe800ffcf47100fcd46100fccc5d03fcd46100fccc5d00fcd46101fcdc6600fcf4c600
+ffffffffffffffffffffff55f4f6f900ecf3f500e8ecef00fbe4c100fcf47105fcfe8000
+fcf47100fcfe8007fcf47100fcfe8000fcf47101fcec7600fcd46100fccc5d06fcd46101
+fceb9900ffffffffffffffffffffff55f4f6f900ecf3f500e0e4e700fcecc400fce66a01
+fcf47109fcfe8002fcf47104fce66a00fccc5d00fcc45900fccc5d00fcc45901fccc5d00
+fcc45900fccc5d01fcd46100fcf4c600ffffffffffffffffffffff55f4f6f900ecf3f500
+e8ecef00fbe4c100fce66a01fcf47100fcec7600fcf4710dfcec7600fcf47100fce66a00
+fcc45901fcbc5400fcc45900fcbc5400fcc45903fccc5d00fcf4c600ffffffffffffffff
+ffffff55f4f6f901e0e4e700fbe4c100fce66a03fcec7607fcf47101fcec7600fcf47100
+fcec7600fcf47100fce66a00fcec7600fcdc6600fcbc5400fcc45902fcbc5400fcc45900
+fcbc5401fcc45900fccc5d00fcecc400ffffffffffffffffffffff55f4f6f900e8ecef01
+fbe4c100fce66a08fcec7600fce66a00fcec7605fce66a00fcec7600fce66a00fcdc6600
+fcbc5400fcc45900fcbc5402fcc45900fcbc5402fccc5d00fceb9900ffffffffffffffff
+ffffff54f4f6f900ecf3f500e8ecef00e0e4e700fadcaf00fcdc6601fce66a0afcec7600
+fce66a05fcd46100fcbc5400fcc45900fcbc5401fcb45000fcbc5403fcc45900fcecc400
+ffffff2ffcfebc00ffffffffffffffffffffff0bfcfebc00fcf4c600fcf49700fceb9900
+fcec7600fceb9902fcf49700fcf4c603ffffff00fcf4c600ffffff07f4f6f900ecf3f501
+e0e4e701fadcaf00fcdc6608fce66a08fcdc6600fce66a00fcd46100fcbc5403fcb45000
+fcbc5400fcb45002fcbc5400fceb9900ffffff29fcfe9a00fcf49700fce66a07fcec7601
+fceb9900fcf49700fcf4c601ffffff3dfcfebc00ffffff49fcfebc01ffffffffffffff73
+fcf4c600fcdc8700fcd46103fcdc6601fcd46101fcdc6600fcd46100fcdc6602fce66a00
+fcdc6600fcd46100fccc5d00fcc45900fcbc5401fcc45900fcbc6c00fccd8300fcd48800
+fadcaf00fbe4c100f7ece700e8ecef00e0e4e700d9dcde00fadcaf00fcdc6603fcd46100
+fcdc6600fcd46100fcdc6606fce66a00fcdc6604fccc5d00fcb45001fcbc5400fcb45000
+fcac4c00fcbc5400fcb45000fcac4c01fcb45000fcecc400ffffff25fcfebc00fcec7600
+fce66a0ffcdc6601fcd46100fcc45900fcbc5400fcc45900fadcaf00fcf4c600ffffff35
+fcf49700fce66a00fcd46100fcb45000fcbc5400fcd48800fcf4c600ffffff1ffcfe9a00
+fcf47100fcec7600fcf49700ffffff1dfcfebc00fcfe9a00fcf47100fcec7602fcf4c600
+ffffff2cfcf4c600fccc5d00fce66a00fcec7600fcfe9a00ffffff39fcfebc04ffffff4d
+fcf4c600fcecc400fadcaf01fce3a100fceb9900fcec7601fce66a00fcec7601fce66a03
+fcec7600fcf49700fcfe9a00ffffff3cf4f6f900ecf3f505f4f6f900ecf3f500f4f6f900
+ffffff00f4f6f901f7ece700fcecc401fbe4c100fadcaf01fce3a101fceb9901fcec7601
+fce66a00fcec7602fcf49700fcfebc00ffffff42fceb9900fcd46100fcc45900fccc5d03
+fcd46104fcdc6600fcd46101fcdc6604fce66a00fcdc6602fccc5d00fcbc5400fcb45000
+fcac4c01fca44800fcac4c00fca44800fcb45000fcbc6c00e8cbab00facca600fcd46105
+fcdc6600fcd46100fcdc6600fcd46100fcdc6609fccc5d00fcb45003fcac4c00fcb45001
+fcac4c01fcb45000fce3a100ffffff22fcfebc00fce66a02fcdc6600fce66a00fcdc6602
+fce66a01fcdc6600fce66a00fcdc6601fce66a00fcdc6601fce66a00fcdc6606fccc5d00
+fcbc5400fcac4c01fcc45900fadcaf00ffffff30fcf47100fce66a03fcc45900fcac4c01
+fcbc5400ffffff1ffcec7602fcf47100fce66a00fce3a100ffffff18fcfe9a00fcec7600
+fce66a06fcdc6600ffffff2cfcc45900fcd46100fcdc6603fce66a00fcf47100fcfebc00
+ffffff2ffcfebc01fcf47100fcec7607fcf47101fcec7600fcf47101fcf49700fcfe9a00
+fcfebc02ffffff3cf4f6f901fbe4c100fadcaf00fac58900fcbc5400fcac4c00fcb45000
+fcc45900fcdc6600fcec7601fce66a00fcec7601fce66a01fcec7600fce66a04fcec7601
+fcf47102fcfebc01ffffff2ffcecc402fbe4c100fceb9901fce3a100fceb9901fcec7601
+fcecc400e8ecef00e0e4e700e9d9b900fad4b000fac58900fcbc6c00fcb45000fcac4c00
+fcb45000fcac4c01fcb45000fcc45900fcd46100fce66a01fcec7600fce66a0bfcf49700
+fcfebc00ffffff3bfcecc400fccc5d00fcc45903fcbc5400fcc45900fccc5d00fcc45900
+fccc5d02fcd46103fcdc6600fcd46100fcdc6602fcd46100fcdc6601fcd46100fcdc6600
+fcd46101fcc45900fcb45000fcac4c00fca44802fc9c4200fca44801fcb45000fccc5d00
+fcd46100fccc5d00fcd46104fcdc6600fcd4610afcc45900fcac4c00fcb45001fcac4c02
+fca44802fcac4c00fbe4c100ffffff1ffcfebc00fce66a00fcdc6602fcd46100fcdc6613
+fcd46102fcdc6600fcd46101fcc45900fcac4c00fca44800fcac4c00fcbc5400fadcaf00
+ffffff2bfcec7600fce66a06fcb45000fcac4c01fcc45900ffffff1dfcec7600fce66a00
+fcec7600fce66a01fcec7601fce66a00fceb9900ffffff12fcfebc00fcf49700fce66a03
+fcdc6600fce66a00fcdc6600fce66a00fcdc6600fce66a01fcdc6600fcf4c600ffffff2a
+fbe4c100fcc45900fcdc6606fce66a01fcec7600fcfe9a00ffffff27fcecc400fce3a100
+fceb9900fcec7600fcf47102fcec7603fce66a01fcec7603fce66a00fcec7608fcf47100
+fcec7602fcf47100fcf49701fcfe9a00fcfebc04ffffff00fcfebc00ffffff01fcfebc00
+ffffff00fcfebc00ffffff00fcfebc03fcfe9a00ffffff1df4f6f900ecf3f500e8ecef00
+fadcaf00fac58900fcb45000fcac4c01fcb45000fcc45900fcdc6600fce66a00fcec7600
+fce66a0efcec7606fcf49700fcfebc00ffffff16f4f6f900ffffff00f4f6f901ecf3f504
+f4f6f901f7ece700fcecc400fbe4c101fce3a101fcdc8701fcd46101fcdc6600fce66a01
+fcec7601fce66a00fcec7602fce66a01fcec7600fcd48800fbb47200fcb45000fcac4c01
+fcb45000fcac4c00fcb45000fcac4c01fcc45900fcd46100fce66a07fcdc6605fce66a00
+fcdc6600fce66a00fcdc6600fce66a00fcdc6600fcec7600fcf4c600ffffff37fce3a100
+fcc45900fcbc5400fcc45900fcbc5403fcc45900fcbc5400fcc45901fccc5d02fcd46107
+fcdc6600fcd46106fccc5d01fcbc5400fca44803fc9c4201fcac4c00fccc5d05fcd46101
+fccc5d00fcd46101fccc5d00fcd46107fcc45900fcac4c05fca44801fc9c4200fca44800
+fce3a100ffffff1dfcf49700fcdc6601fcd46108fcdc6606fcd46101fcdc6600fcd46100
+fcdc6601fcd46105fccc5d00fcd46101fccc5d00fcd46100fcc45900fcac4c00fc9c4200
+fca44800fcac4c00fcbc6c00fcf4c600ffffff25fcfebc00fcec7600fcdc6603fce66a00
+fcdc6600fce66a00fcdc6600fce66a00fccc5d00fcac4c00fca44800fcb45000fce3a100
+ffffff1bfcec7600fce66a05fcec7600fce66a01fcdc6600fceb9900ffffff0cfcfebc00
+fcf49700fcec7600fce66a04fcdc6606fcd46100fcdc6601fcd46100ffffff2afcbc6c00
+fccc5d00fcdc6600fcd46100fcdc6601fcd46100fcdc6603fce66a00fcdc6600fce66a01
+fcec7600fcfebc00ffffff1ff4f6f900fadcaf00fcd48800fcd46100fcec7607fce66a08
+fcec7600fce66a0efcec7600fce66a00fcec7606fce66a01fcec7602fce66a00fcec7602
+fce66a00fcf49700ffffff19f4f6f901ecf3f500e8ecef00e9d9b900fac58900fcb45000
+fca44800fcac4c01fcbc5400fcd46100fce66a00fcec7601fce66a07fcdc6600fce66a00
+fcdc6604fce66a02fcec7602fce66a03fcdc8700fcec7600fcf49700ffffff10f4f6f901
+ecf3f502e8ecef00e9d9b900f9dcd100e8cbab00fac58901fcbc8800fbb47200fcb45000
+fcac4c00fca44800fcbc5400fce66a09fcdc8700fcec7600fce66a07fcbc5400fcac4c06
+fcb45000fcdc6600fce66a02fcdc6604fcd46100fcdc6603fcd46100fcdc6601fcd46100
+fcdc6606fce66a00fcecc400ffffff33fcdc8700fcbc5406fcc45900fcbc5402fcc45902
+fccc5d00fcc45900fccc5d01fcd46108fccc5d04fcc45900fccc5d00fcc45901fcac4c00
+fc9c4201fca44800fc9c4200fca44800fcc45901fccc5d07fcc45900fccc5d08fcc45900
+fcac4c03fc9c4200fcac4c00fc9c4203fbe4c100ffffff1bfceb9900fcd46101fccc5d00
+fcd46100fccc5d01fcd46100fccc5d02fcd46100fccc5d00fcd46110fccc5d08fcd46100
+fcbc5400fcac4c00fc9c4200fca44801fcb45000fadcaf00ffffff21fcfebc00fcdc8700
+fcdc6600fcd46100fcdc6606fce66a00fcdc6601fcbc5400fca44801fcb45000ffffff1a
+fceb9900fcdc6602fce66a00fcdc6600fce66a02fcec7600fce66a00fcec7600fcdc8700
+fcd46100fce3a100ffffff07fcf49700fce66a07fcdc6601fcd46100fcdc6600fcd46102
+fccc5d00fcd46104fcf4c600ffffff23f4f6f904fadcaf00fcbc5400fcd46100fcdc6600
+fcd46103fcdc6609fce66a00fcec7600fcfe9a00ffffff1afadcaf00fac58900fcc45900
+fcdc6600fce66a00fcec7600fce66a01fcec7600fce66a0efcdc6601fce66a00fcdc6601
+fce66a00fcdc6600fce66a00fcdc6600fce66a00fcdc6600fce66a00fcdc6600fce66a00
+fcdc6601fce66a03fcec7600fce66a09fcec7600fce66a00fcec7600fcfebc00ffffff17
+ecf3f502e0e4e700facca600fbb47200fca44800fcac4c00fca44800fcac4c00fcbc5400
+fcdc6600fce66a0bfcdc6609fce66a00fcec7600fce66a03fcdc6600fce66a01fcdc6600
+fce66a01fcec7600ffffff0cf4f6f900ecf3f501e8ecef01e0e4e701fac58900fcac4c00
+fca44800fc9c4200fca44802fcac4c00fca44802fcbc5400fcdc6602fce66a00fcdc6600
+fce66a00fcdc6600fce66a00fcdc6600fce66a03fcdc8700fce66a00fcdc8700fce66a00
+fcdc6600fce66a01fcbc5400fcac4c00fca44800fcac4c02fca44800fccc5d00fcdc6600
+fce66a00fcdc6604fcd46100fcdc6600fcd46100fcdc6600fcd46107fcdc6602fcd46101
+fcdc6600fcd46101fcdc6601fcf4c600ffffff2ffcdc8700fcbc540efcc45903fccc5d03
+fcd46100fccc5d05fcc45905fcbc5400fcc45900fcbc5400fcb45000fc9c4202fca44800
+fcc4590dfccc5d00fcc45900fccc5d01fcc45900fccc5d00fcbc5400fca44802fc9c4201
+fca44800fc9c4203fce3a100ffffff19fceb9900fcd46100fccc5d06fcc45900fccc5d00
+fcc45900fccc5d00fcc45900fccc5d03fcd46101fccc5d00fcd46102fccc5d00fcd46102
+fccc5d05fcc45900fccc5d03fcc45900fccc5d00fcc45902fcb45000fc9c4201fc944100
+fca44800fcac4c00fadcaf00ffffff1dfcf4c600fcd46100fccc5d00fcd46105fcdc6606
+fcd46100fcac4c00fc9c4200fca44800fcbc6c00ffffff17f4f6f900fcecc400fcd46102
+fcdc6600fcd46100fcdc6603fce66a00fcdc6600fce66a02fcdc6600fcd46100fbe4c100
+ffffff05fcdc6602fcdc8700fcdc6601fcd46108fccc5d00fcd46100fccc5d04fcd46100
+ffffff21f4f6f900ecf3f501e8ecef03fcbc6c00fcc45900fcd46106fcdc6603fcd46100
+fcdc6606fce66a01ffffff15f7ece700fad4b000fcb45000fcc45900fcdc6600fce66a08
+fcdc6600fce66a00fcdc6600fce66a01fcdc6614fcd46100fcdc6604fce66a00fcdc6600
+fce66a01fcdc6600fce66a00fcdc6600fce66a07ffffff15f4f6f900ecf3f501e8ecef00
+e0e4e700fac58900fca44802fc9c4200fca44800fcbc5400fcd46100fce66a00fcdc6600
+fce66a00fcdc6601fce66a00fcdc6600fce66a00fcdc6605fce66a00fcdc6600fce66a00
+fcdc6606fce66a01fcdc8700fce66a01fcdc6603fce66a00fcdc6601fce66a00fcdc6600
+fceb9900ffffff09ecf3f501e8ecef00e0e4e700d9dcde03efbc8e00fca44800fc9c4203
+fca44801fc9c4202fcbc5400fcdc660cfce66a02fcdc6600fcdc8700fce66a00fcdc6600
+fcbc5400fca44801fcac4c00fc9c4200fcb45000fcd46100fce66a01fcdc6601fcd4610a
+fccc5d01fcd4610afccc5d00fcd46101fce3a100ffffff2cfce3a100fcc45900fcbc5404
+fcb45006fcbc5402fcc45900fcbc5401fcc45904fccc5d00fcc45900fccc5d01fcc45906
+fcbc5403fcb45000fcbc5401fcb45000fc9c4200fc944100fc9c4200fcbc5402fcc45900
+fcbc5400fcc45900fcbc5408fcc45904fcb45000fca44800fc9c4200fca44800fc9c4202
+fc944100f38b3600fc944100fc9c4200fadcaf00ffffff17fcf4c600fccd8300fccc5d02
+fcc45907fcbc5400fcc45900fcbc5400fcc45902fccc5d00fcc45901fccc5d00fcc45900
+fccc5d07fcc4590ffcac4c00fc9c4200fc944101fc9c4200fca44800fbe4c100ffffff19
+fcecc400fcd46100fcc45900fccc5d05fcd46103fcdc8700fcd46100fcdc6600fcd46100
+fcdc6601fcc45900fc9c4201fca44800fbe4c100ffffff14f4f6f900e8ecef00f7ece700
+fccd8300fcd46100fccc5d00fcd46104fcdc6603fcd46100fcdc6600fcd46100fcdc6601
+fcd46100fcc45900fadcaf00ffffff03fcdc8700fcd46100fcdc6600fcd46105fccc5d00
+fcd46100fccc5d04fcc45900fccc5d04fcbc5400ffffff20f4f6f900e8ecef01e0e4e703
+e6ccc900fcac4c00fccc5d01fcd46100fccc5d00fcd46102fcdc6600fcd46108fcdc6600
+fcd46100fcdc6601fcf4c600ffffff13f7ece700fac58900fcac4c00fcbc5400fcdc6600
+fce66a00fcdc6605fcd46100fcdc6600fcd46100fcdc6600fcd46100fcdc6601fcd46100
+fcdc6600fcd46100fcdc6600fcd46100fcdc6602fcd46100fcdc6600fcd46100fcdc6600
+fcd46104fcdc6600fcd46109fcdc6603fcdc8700fcdc6600fce66a00fcdc8700fce66a00
+fcdc6600fcdc8700fcdc6601fce66a00fcdc8700fcec7600ffffff13f4f6f900ecf3f501
+e8ecef00e6dcdc00fcbc8800fca44800fc9c4203fcac4c00fcd46100fcdc6602fce66a00
+fcdc6607fce66a00fcdc6608fcd46100fcdc6604fce66a00fcdc660cfcf4c600ffffff06
+ecf3f501e0e4e701d9dcde01d2d4d602efbc8e00fc9c4209fcac4c00fccc5d00fcd4610a
+fcdc6600fcd46100fcdc6601fce66a00fcdc6601fce66a00fcb45000fca44801fc9c4200
+fcbc5400fcdc6602fcd46100fcdc6600fcd46104fccc5d00fcd46100fccc5d00fcd46100
+fccc5d07fcd46102fccc5d08fcd46100ffffff29fcf4c600fcbc6c00fcbc5404fcb45001
+fcbc5400fcb45006fcbc5400fcb45000fcbc5405fcc45900fcbc5401fcc45900fcbc5400
+fcc45900fcbc5400fcc45900fcbc5404fcb45007fcac4c00fc9c4201fcbc5402fcb45000
+fcbc5400fcb45000fcbc5400fcb45003fcbc5407fcc45900fcb45000fc9c4201fca44800
+fc9c4202f38b3602fc9c4200fad4b000ffffff16fcd46100fcc45905fcbc5400fcc45900
+fcbc5406fcc45900fcbc5400fcc45900fcbc5400fcc45900fcbc5400fcc4590cfcbc5406
+fcc45900fcbc5406fcb45000fc9c4200f38b3601fc944100fc9c4200fbb47200ffffff16
+fcecc400fcd46100fcc45906fccc5d03fccd8300fccc5d00fcd46101fccd8300fcd46103
+fcac4c00fc9c4201fcac4c00ffffff13ecf3f500e8ecef01fccd8300fcc45900fccc5d04
+fcd46105fcdc6600fcd46100fcdc6600fcd48800fcd46102fccc5d00fcbc6c00fadcaf00
+ffffff01fcecc400fcd46103fccc5d07fcc45909fccd8300ffffff1ef4f6f900e8ecef00
+e0e4e700d9dcde02d2d4d600d9dcde00ecae7c00fcbc5400fccc5d06fcd46104fccc5d00
+fcd46104fcd48800fcd46101ffffff12f4f6f900fac58900fca44800fcb45000fcd46100
+fcdc6606fcd46106fccc5d01fcd46100fccc5d00fcd46112fccc5d00fcd46101fccc5d00
+fcd46104fcdc6603fcdc8700fcdc6602fce66a00fcdc6603fcf4c600ffffff11f4f6f901
+ecf3f500e8ecef00d9dcde00efbc8e00fc9c4200fc944103fc9c4200fcbc5400fcd46102
+fcdc6601fcd46100fcd48800fcdc6600fcd46100fcdc6600fcd46101fcdc6601fcd46100
+fcdc6604fcd46100fcdc6600fcd46103fcdc6601fcdc8700fcdc6600fcdc8700fcdc6601
+fcd46100fcdc6600fcd46109fcec7600ffffff04ecf3f501e0e4e701d9dcde00d2d4d600
+cbcccd02c4c5c500e4ae7c00fc944104fc9c4201fc944102fcac4c00fccc5d04fcd46109
+fcdc6600fcd46100fcdc6602fcb45000fc9c4201fcc45900fcdc6602fcd46100fcdc6600
+fcd46101fccc5d0afcc45900fccc5d00fcc45900fccc5d03fcc45900fccc5d04fcc45900
+fccc5d00fcc45900fccc5d00fcc45900fcd48800ffffff27fccd8300fcb4500afcac4c00
+fcb45000fcac4c00fcb45002fcac4c00fcb4500bfcbc5404fcb45002fcac4c00fcb45000
+fcac4c06fcb45000fc9c4200fcb45004fcac4c00fcb45006fcbc5400fcb45000fcbc5404
+fcb45000fc9c4203fc944100fc9c4200f38b3602fc8c3d00fadcaf00ffffff14fce3a100
+fcbc5401fcc45901fcbc5406fcb45000fcbc5400fcb45002fcbc5400fcb45003fcbc5400
+fcb45000fcbc5404fcc45900fcbc5401fcc45903fcbc5409fcb45000fcbc5400fcb45003
+fcbc5401fcac4c00fc944100f38b3600fb843a00fc944101fccd8300ffffff12fcecc400
+fcc45905fcbc5400fcc45900fcbc5400fcc45905fccc5d00fcc45901fccc5d00fcc45901
+fccc5d01fcc45900fc9c4200fc944101fcbc8800ffffff10f4f6f900e8ecef01e0e4e700
+fcd48800fcc45903fccc5d00fcc45900fccc5d03fcd46102fcd48800fcd46104fccc5d00
+fcd46100fccc5d00fcc45900fcac6600facca600f7ece700fcd48800fcd46100fccd8300
+fccc5d02fcc45900fccc5d00fcc45904fcbc5400fcc45901fcbc5401fcc45900fcbc5402
+fcb45000ffffff1df4f6f900e8ecef00e0e4e700d9dcde00d2d4d601cbcccd01d7c4bd00
+fca44800fcc45901fccc5d11fcd46100fceb9900ffffff10f4f6f900f8d4c900fca44800
+fc9d4c00fcc45900fcd46101fcdc6600fcd46100fcd48800fcdc6600fcd46106fccc5d0c
+fcd46100fccc5d00fcd46100fccc5d00fcd46100fccc5d0cfcd46100fccc5d00fcd46105
+fcdc6601fcdc8700fcd46104fcdc6600fcfebc00ffffff10ecf3f500e8ecef01e0e4e700
+e8cbab00f19e5c00f38b3600fc944102f38b3600fcac4c00fcc45900fcd46100fccc5d00
+fcd46101fccd8300fcd4610afcd48800fcd46100fcdc6600fcd48800fcd4610afcdc6600
+fcd46108fccc5d00fcd46102fccc5d01fcd46100ffffff02f4f6f900ecf3f500e8ecef00
+d9dcde01d2d4d600c4c5c501bbbcbd00c4c5c500bbbcbd00d8a47800fc944101f38b3600
+fc944100f38b3600fc944102f38b3601fc9c4200fcc45903fccc5d00fcc45901fccc5d00
+fcc45900fccc5d02fccd8300fcd46106fcac4c00fc9c4200fccc5d00fcd46104fccc5d04
+fcc45900fccc5d00fcc45919fcdc8700ffffff24fcf4c600fcbc6c00fcac4c09fca44800
+fcac4c01fca44800fcac4c01fca44800fcac4c0cfcb45000fcac4c00fcb45000fcac4c00
+fcb45001fcac4c00fcb45000fcac4c02fca44800fcac4c00fca44802fcac4c00fca44800
+fcac4c0dfcb45003fcbc6c00fcbc5402fcac4c00fc944105f38b3602fc944100fcd48800
+ffffff13fccd8300fcb45002fcbc5401fcb45000fcbc5400fcb45006fcac4c00fcb45000
+fcac4c02fcb45000fcac4c01fcb45004fcbc5400fcb45000fcbc5409fcb4500efcbc5400
+fcb45000fc944100f38b3600fb843a00f38b3600fc944100fca46d00ffffff11fbe4c100
+fcbc540afcbc6c00fcc45907fcbc6c00fcc45902fcb45000fc8c3d00f38b3600fc944100
+fbe4c100ffffff0ef4f6f900ecf3f500e0e4e701e9d5d700fcbc5402fcc45905fccc5d04
+fcd46100fccc5d00fccd8300fcd46100fccc5d00fccd8300fccc5d02fcbc5400fc8c3d00
+fc9c4200e6dcdc00fcd48800fccc5d03fcc45906fcbc5400fcc45900fcbc5407fcb45000
+fcd48800ffffff1bf4f6f900e8ecef00e0e4e700d9dcde00d2d4d600d8cccb00c4c5c500
+cbcccd00c4c5c500e4ae7c00fcac4c00fccc5d00fcc45901fccc5d00fcc45902fccc5d00
+fcc45901fccc5d00fcc45901fccc5d00fcc45900fccc5d01fccd8300fccc5d01fccd8300
+ffffff0ef4f6f901e8ecef00efbc8e00fc944100fca44800fcc45900fccc5d01fcd46100
+fccc5d01fcd46100fccc5d00fcd46100fccd8300fcd46100fccd8300fccc5d00fcd46100
+fccc5d02fcc45907fccc5d00fcc45900fccc5d00fcc45900fccc5d00fcc45901fccc5d00
+fcc45900fccc5d00fcc45900fccc5d00fcc45907fccc5d00fcc45900fccc5d02fccd8300
+fcd46102fccd8300fcd46100fccc5d00fcd46100fccc5d00fcd46100fccd8300fcd46101
+ffffff0fecf3f501e8ecef00e0e4e700d9dcde00e4ae7c00fc944101fc9c4200f38b3601
+fc944100fcb45000fccc5d09fccd8300fccc5d00fccd8300fccc5d01fccd8300fccc5d01
+fcd46105fccd8300fccc5d03fcd46102fcd48800fcd46101fccd8300fccc5d07fcc45901
+fccc5d00fcc45900fccc5d00fcc45900fccd8300fcf4c600ffffff00ecf3f500e8ecef00
+d9dcde01cbcccd00c4c5c500bbbcbd02b4b4b401d8a47800f38b3606fc8c3d00f38b3600
+fb843a00fc9c4200fcc45900fcbc5400fcc45900fcbc5401fcc45900fcbc6c00fcc45901
+fcbc6c00fcc45900fccc5d00fcc45901fccc5d00fccd8300fccc5d00fcd46100fccd8300
+fcd46100fcac4c00fcc45900fccc5d03fcc45900fccc5d00fcc4590afcbc5400fcc45900
+fcbc5406fcc45900fcbc5400fcc45900fcbc5400fcc45900fcbc5401fcc45900fcbc5405
+fcf4c600ffffff22fbe4c100fcac4c01fca44801fcac4c01fca44800fcac4c00fca44808
+fc9c4200fca44802fc9c4200fca44800fc9c4202fca44800fc9c4200fca44802fcac4c00
+fca44800fcac4c02fca44800fcac4c00fca44800fcac4c00fca44802fc9c4201fca44800
+fc9c4201fca44803fcac4c00fca44807fcac4c04fcac6600fcb45004fca44800fc944100
+fc8c3d01fc944100f38b3600fb843a04fad4b000ffffff12fcbc6c00fcac4c00fcb45005
+fcac4c01fcb45000fcac4c04fca44800fcac4c00fca44800fcac4c01fca44800fcac4c01
+fca44800fcac4c06fcb45003fcbc5400fcb4500afcac4c04fcb45004fcbc5400fc9c4200
+fb843a02fc8c3d00fc9c4200fcecc400ffffff10fccd8300fcb45009fcbc5403fcbc6c00
+fcbc5400fcc45900fcbc6c00fcbc5400fcc45900fcbc6c00fcc45901fcbc5400fca44800
+f38b3601fc9c4200ffffff0ee8ecef01d9dcde00e9d5d700fcbc6c00fcb45000fcbc5408
+fcc45902fccc5d00fac58900fccc5d02fcc45900fccc5d00fcc45900fccc5d00fcbc5400
+fc944101e8cbab00d9dcde00e6dcdc00fac58900fcc45905fcbc5400fcc45900fcbc5405
+fcb45000fcbc5400fcb45004fcac4c00ffffff1be8ecef01d9dcde00d2d4d600cbcccd00
+c4c5c502c6bcba00fc9c4200fcbc5400fcc4590afccc5d00fcc45900fccc5d00fcc45901
+fccc5d00fcc45902fcdc8700ffffff0df4f6f900ecf3f500f9e4e100f19e5c00fc8c3d00
+fc944100fcbc5400fcc45901fcbc6c00fcc45902fccc5d00fcc45900fccc5d05fcc45906
+fcbc5400fcc45908fcbc5400fcc45900fcbc5400fcc45900fcbc5400fcc45900fcbc5400
+fcc45901fcbc5400fcc45900fcbc5400fcc45900fcbc5400fcc45903fccc5d02fccd8300
+fccc5d05fcc45900fccc5d01fcdc8700ffffff0df4f6f900ecf3f500e8ecef00e0e4e701
+d8cccb00fc9d4c00fc944100f38b3600fc8c3d00f38b3601fc9c4200fcbc5400fcc45900
+fccc5d00fcc45901fccc5d00fcc45900fccc5d00fcc45900fccc5d00fcc45906fccc5d00
+fcc45900fccc5d02fccd8300fccc5d00fccd8300fccc5d05fccd8300fccc5d00fccd8300
+fccc5d04fcc45901fccc5d00fcbc6c00fcc45900fcbc5400fcc45908f7ece700e8ecef00
+e0e4e700d9dcde00d2d4d600cbcccd00bbbcbd00b4b4b401abacad02cc916400f38b3601
+fb843a02f38b3600fb843a00f38b3600fb843a01fc9c4200fcb45000fcbc5400fcb45001
+fcbc5400fcb45000fcbc5403fcc45900fcbc5400fcc45901fcbc5401fcc45905fcbc5400
+fcc45900fcbc5400fcc45902fcbc5400fcc45900fcbc540bfcb45000fcbc5400fcb45000
+fcbc5402fcb45000fcbc5400fcb45000fcbc5403fcb45000fcbc5403fcb45000fcbc5400
+fccd8300ffffff21fadcaf00fca44800fc9d4c00fca44802fc9c4200fca44801fc9c4200
+fca44801fc9c4200fca44800fc9c4213fca44800fc9c4200fca44802fc9c4200fca44800
+fc9c420bfca44800fc9c4201fca44800fc9c4203fca44803fcac4c05fcac6600fcac4c01
+fca44800fc8c3d00f38b3603fb843a02ec742a00f38b3600fcd48800ffffff10f4f6f900
+fcb45000fcac4c03fcac6600fcac4c01fca46d00fcac4c00fca44801fcac4c00fca44805
+fc9c4200fca44800fc9c4200fca44801fc9c4200fca44805fcac4c00fca44800fcac4c03
+fcac6600fcb45001fcac4c01fcb45000fcac4c0dfcb45003fc9c4200fb843a02f38b3600
+fc8c3d00fbe4c100ffffff0ef4f6f900f7ece700fcbc5400fcac4c00fcb45009fcbc5400
+fcb45000fcbc5400fcb45001fcbc5401fcb45000fcbc5403fcb45000fc8c3d00f38b3600
+fb843a00fbb47200ffffff0bf4f6f900ecf3f500e8ecef00e6dcdc00d9dcde00fac58900
+fcb45003fcbc5400fcb45000fcbc5400fcb45000fcbc5403fcbc6c00fcc45900fcbc6c00
+fcc45901fcbc6c00fcc45900fac58900fcc45900fcbc6c01fc9c4200fc8c3d00ecae7c00
+d9dcde00d2d4d601fac58900fcbc5409fcb45006fcac4c01fcb45000fcac4c00fcb45000
+fadcaf00ffffff19ecf3f500e8ecef00e0e4e700d2d4d601cbcccd00c4c5c502e4ae7c00
+fca44800fcc45900fcbc5400fcc45900fcbc5400fcc45901fcbc5400fcc45906fcbc6c00
+fcc45900fac58900fcc45901fac58900fcc45900ffffff0cf4f6f900ecf3f500e8ecef00
+e6dcdc00f19e5c00f38b3600fc8c3d00fcb45000fcbc5403fcc45900fcbc6c00fcc45900
+fcbc6c00fcc4590afcbc5405fcbc6c00fcbc540cfcb45000fcbc5400fcb45001fcbc5400
+fcb45000fcbc5402fcc4590afcbc6c00fcc45902fcf4c600ffffff0cf4f6f900ecf3f500
+e8ecef00e0e4e700d9dcde00d7c4bd00fc944100f38b3603fb843a00fc944100fcc45906
+fcbc6c00fcc45900fcbc6c00fcc45900fcbc6c00fcc45900fcbc6c00fcc45900fcbc6c00
+fcbc5400fcbc6c00fcc45900fcbc6c00fcc45900fac58900fcc45900fccc5d00fcc45900
+fccc5d00fcc45900fccc5d00fcc45900fccd8300fcc45900fccc5d04fcc45901fcbc6c00
+fcc45900fcbc6c00fcc45901fcbc6c00fcc45900fcbc5405fcbc6c00fcbc5400fcc45900
+fcbc5400fcc45900f9dcd100e0e4e700d2d4d600cbcccd00bbbcbd01abacad01a4a5a402
+cc916400fc8c3d00fb7c3800fb843a05fb7c3800ec742a00fc944100fcb45001fcac4c00
+fcb45000fcac4c00fcb45003fcbc5400fcb45003fcbc5401fcb45000fcbc5402fcb45000
+fcbc5401fcb45000fcbc5402fcb45000fcbc5400fcb45001fcbc5401fcb45000fcbc5400
+fcb4501bfcf4c600ffffff1ffad4b000fc9c4200fc944100fc9c4200fc944102fc9c4201
+fc944100fc9c4200fc944100fc9c4200fc944100fc9c4200fc944100fc9c4200fc944100
+fc9c4200fc944100fc9c4200fc944105fc9c4200fc944105fc9c4200fc944100fc9c4200
+fc944100fc9c4200fc944100fc9c4200fc944100fc9c4200fc94410afc9c4200fc944100
+fc9c4201fc944100fc9c4204fca4480afc9c4200f38b3600fb7c3800fb843a00f38b3600
+fb843a01ec742a00fb843a00fb7c3800fb843a00facca600ffffff10fcac4c00fca4480a
+fc9c4200fca44800fc9c4200fca44800fc9c4200fca44800fc9c4201fca44800fc9c4201
+fca44800fc9c4200fca44800fc9c4204fca44804fcac4c03fcac6600fcac4c00fcac6600
+fcac4c03fca44800fcac4c00fca44800fcac4c00fca44802fcac4c00fca44800fcac4c06
+fc944100ec742a00fb7c3800ec742a00f38b3600fb843a00fbe4c100ffffff0cf4f6f900
+e8ecef01f9dcd100fca44801fcac4c00fca44800fcac4c03fcb45001fcac4c00fcb4500c
+fca44800fb843a02fbe4c100ffffff0af4f6f900e8ecef00e0e4e700d9dcde00e8cbab00
+fcac4c03fcb45000fcac4c00fcb45000fcac4c00fcb45005fcbc5402fcbc6c00fcc45900
+fcbc6c00fcbc5400fcc45900fcbc5400fc9c4200fb843a00f19e5c00d2d4d600cbcccd02
+e6ccc900fcb4500bfcac4c00fcb45000fcac4c08ffffff18f4f6f900ecf3f500e0e4e700
+d9dcde00d2d4d600cbcccd00c4c5c502c6bcba00fc955100fcb45000fcbc540afcc45900
+fcbc6c00fcc45902fcbc6c00fcc45901fcbc5400fccd8300ffffff0af4f6f900ecf3f500
+e8ecef01d9dcde00f19e5c00fb843a01fcac4c00fcb45003fbb47200fcb45001fcbc5402
+fcbc6c00fcc45900fcbc6c00fcc45901fcbc6c00fcc45900fcbc6c00fcbc5404fcb45000
+fcbc5400fcb45006fcac4c00fcb45001fcac4c00fcb45000fcac4c00fcb45002fcac4c00
+fcb45005fcbc5401fcbc6c00fcc45900fcbc6c00fcc45903fcbc5400fcbc6c00fcc45900
+fcbc5400fcc45900fcbc5401ffffff0cecf3f500e8ecef00e0e4e700d9dcde01d8bcb600
+f38b3603fb843a00f38b3600fc944100fcbc5405fcbc6c00fcbc5401fcbc6c00fcbc5402
+fcb45000fcbc5401fcb45000fcbc5402fcbc6c00fcc45901fcbc6c00fcc45901fcbc6c00
+fcc45900fcbc6c00fcc45900fcbc5400fcc45900fcbc6c00fcc45900fcbc6c00fcc45900
+fcbc6c00fcc45900fcbc6c00fcc45900fcbc6c00fcc45900fcbc6c00fcbc5403fcbc6c00
+fcb45000fcbc5408e9d9b900d2d4d600cbcccd00bbbcbd00b4b4b400abacad009c9e9c00
+a4a5a402cc916400fb7c3800fb843a00ec742a00fb7c3800ec742a01f38b3600ec742a00
+f38b3600fb7c3800fc8c3d00fcac4c06fcb45000fcac4c00fcb45000fcac4c00fcb45001
+fcac4c02fcb45000fcac6600fcac4c00fcb4500afcac4c00fcb45000fcac4c00fcb45000
+fcac4c00fcb45000fcac4c00fcb45002fcac4c00fcb45000fcac4c08fcb45000fcac4c02
+fcb45000fcac4c06facca600ffffff1efcecc400fc955100fc944107fc8c3d00fc944101
+fc8c3d00fc944100fc8c3d00fc944100f38b3600fc8c3d04fc944100f38b3600fc8c3d01
+fc944100fc8c3d00fc944110fc8c3d00fc944100fc8c3d00fc944103fc9c4200fc944101
+fc9c4200fc944102fc9c4200fc944100fc9c4201fc9d4c04fca44800fc9d4c00fca44804
+fc9c4200fb7c3801fb843a02ec742a00fb843a00ec742a00fb7c3801facca600ffffff0f
+fbb47200fc9c4202fca44800fc9d4c00fca44800fc9d4c00fca44800fc9d4c00fc9c4205
+fc944100fc9c4200fc944100fc9c4200fc944100fc9c4201fc944100fc9c4201fc944100
+fc9c4206fca44814fcac4c00fca44800fcac4c00fca44800fcac4c01fca44800fcac4c00
+fca44801f38b3600ec742a00fb7c3800ec742a00fb7c3800f38b3600f4f6f900ffffff0a
+ecf3f500e8ecef00e0e4e701d9dcde00fac58900fca44804fcac4c00fca44800fcac4c0b
+fcac6600fcac4c01fcb45000fcac4c00fc8c3d00fb7c3801fc944100ffffff09f4f6f900
+e8ecef00e0e4e700d9dcde00e9d5d700fcb45000fca44800fcac4c00fca44800fcac4c01
+fca44800fcac4c04fcb45003fbb47200fcb45000fcbc5400fcb45000fcbc5400fcbc6c00
+fcb45000fcac4c00fb7c3800f38b3600c4c5c500cbcccd03c4c5c500fcbc8800fcac4c00
+fcb45000fcac4c02fcb45001fcac4c00fcb45000fcac4c00fcb45000fcac4c03fca44800
+fcac4c00fca44801fcac4c00fca44801fbe4c100ffffff17f4f6f900e8ecef00e0e4e700
+d9dcde00d8cccb00cbcccd00c4c5c502d8ac9f00f38b3600fcb45006fbb47200fcbc5400
+fcb45000fcbc6c00fcb45000fcbc6c00fcbc5400fcbc6c01fcbc5401fcbc6c00fcb45000
+fcbc5400fcf4c600ffffff09ecf3f501e8ecef00e0e4e700d9dcde00e8a58f00fb7c3800
+ec742a00fc9c4200fcb45000fcac4c00fcac6600fcb45000fcac4c01fcb45002fbb47200
+fcb45000fcbc5400fcb45000fcbc5400fcb45000fcbc6c00fcb45001fcbc5400fcb45005
+fcac4c00fcb45000fcac4c00fcb45000fcac4c00fcac6600fcac4c02fca44800fcac4c00
+fca44800fcac4c00fca44800fcac4c00fca44800fcac4c01fca44800fcac4c00fca44800
+fcac4c01fcb45002fcbc5403fbb47200fcbc5400fcb45000fcbc5400fcb45004fcbc6c00
+ffffff0af4f6f900ecf3f500e8ecef00e0e4e700d9dcde00d2d4d600c6bcba00f38b3602
+fb843a00ec742a00fb7c3800f38b3600fcac4c00fcbc5401fcb45004fcbc5400fcb45009
+fcac6600fcb45002fcbc5401fcbc6c01fcbc5400fcbc6c00fcbc5401fbb47200fcbc5401
+fcbc6c00fcbc5401fcb45001fcbc5400fcb4500efbb47200fcb45002fbb47200e8cbab00
+c4c5c500bbbcbd00b4b4b400abacad00a4a5a403cc916400f38b3600ec742a02fb843a00
+ec742a00fb7c3800ec742a02fc944100fcac4c02fca44800fcac4c00fca44801fcac4c00
+fca44800fcac4c01fca44801fcac4c00fca44803fcac4c00fca44802fcac4c00fca44801
+fcac4c05fca44800fcac4c00fca44800fcac4c00fca44800fcac4c00fca44801fcac4c00
+fca44800fcac4c00fca44800fcac4c00fca44800fcac4c00fca44801fcac4c00fca44801
+fcac4c00fca44800fcac4c01fca44800fcac4c00fca44802fc9c4200fca44800fc9c4200
+fcac6600ffffff1efc9d4c00fc8c3d0cf38b3601fb843a00f38b3604fb843a00f38b3600
+fb843a00f38b3602fc8c3d04fc944100fc8c3d0cfc944100fc8c3d00fc94410dfc9c4200
+fc944101fc9c4200fc944100fc9d4c01fc955100fc9d4c04fc944100ec742a03fb7c3800
+ec742a04facca600ffffff0efac58900fc944101fc9c4200fc944100fc9c4200fc944100
+fc9d4c00fc944100fc9d4c00fc9c4200fc944100fc9d4c00fc944106fc8c3d00fc944100
+fc8c3d01fc944100fc8c3d00fc944104fc9c4200fc944100fc9c4203fc9d4c01fca44800
+fc9d4c00fca46d00fca44804fc9d4c00fca44800fc9d4c00fc9c4200fca44800fc9c4200
+fca44804fc9c4200fca44806fc9c4200fb843a00ec742a02fb7c3800fc8c3d00ffffff09
+f4f6f900e8ecef00e0e4e700e6dcdc00d9dcde00d2d4d600d9dcde00fbb47200fc9c4201
+fca44812fcac4c00fca44801fb7c3800ec742a01fbb47200ffffff07f4f6f901e0e4e701
+d9dcde00fcb58e00fca4480cfcac4c00fca46d00fcac4c02fcac6600fcb45000fcac6600
+fcb45000fcac4c00fb7c3800f38b3600d8bcb600d8cccb00cbcccd00c4c5c500cbcccd00
+c4c5c500cbcccd00e8c2b000fcac4c00fcac6600fcac4c05fca44800fcac4c00fca44800
+fcac4c00fca44809fcac6600ffffff17ecf3f500e8ecef00d9dcde00d2d4d601c4c5c503
+e68d5600fca44800fcac4c02fcac6600fcac4c00fcac6600fcac4c00fcb45000fcac6600
+fcb45000fcac6600fcb45004fbb47200fcb45002fcbc6c00ffffff08f4f6f900ecf3f500
+e8ecef00e0e4e700d9dcde00d2d4d600d7c4bd00ec742a00fb7c3800fc8c3d00fcac4c00
+fca44800fcac4c01fca44800fcac4c01fca44800fcac6600fcac4c02fcb45000fbb47200
+fcb45001fcac4c00fcb45001fcac4c00fcb45000fcac4c05fca44800fcac4c00fca4480d
+fc9c4200fca44805fcac4c01fcb45000fcac6600fcb45001fcac4c00fcb45003fcac4c00
+fcb45001fcac6600fcd48800ffffff09f4f6f900ecf3f500e0e4e700d9dcde01d2d4d600
+c4c5c500e68d5600ec742a00fb843a00ec742a01fb7c3800ec742a00fca44800fcac4c00
+fcb45001fcac4c00fcb45000fcac4c00fcb45000fcac6600fcb45001fcac6600fcb45000
+fcac6600fcac4c00fcac6600fcac4c00fca46d00fca44800fcac4c05fcac6600fcb45004
+fcac4c00fcb45000fcac6600fcac4c00fcb45002fcac6600fcb45000fcac4c00fcac6600
+fcb45003fcac6600fcac4c00fcac6600fcac4c00fcac6600fcac4c00fcac6600fca44800
+fca46d00fcac4c02fcac6600fcac4c01fbb47200c4c5c500bbbcbd00b4b4b400a4a5a404
+cc916400ec742a01fb7c3800ec742a01f38b3600ec742a00f38b3600fb843a00ec742a00
+f38b3600fcac4c00fca44800fcac4c00fca44809fc9d4c03fca44800fc9d4c00fca4480f
+fc9c4200fca44800fc9c4200fca44800fc9c4200fca44800fc9c4200fca44802fc9c4200
+fca44807fc9c4200fca44800fc9c4207fcecc400ffffff1cfbb47200fb843a00fc8c3d03
+fb843a00fc8c3d00fb843a11f38b3600fb843a00f38b3602fc8c3d00fc944100fc8c3d0b
+fc944100fc8c3d00fc944100fc8c3d00fc944100fc8c3d01fc944101fc8c3d00fc944100
+fc8c3d00fc944100fc8c3d00fc944104fc955100fc9c4200fc944102fc9c4200fc944100
+fc9c4200fc944101fc955100fc9c4200fc944100fc8c3d00ec742a02fb7c3800ec742a05
+facca600ffffff0df9dcd100fc944106fc9c4200fc944109fc8c3d03f38b3601fc8c3d02
+fc944100fc8c3d00fc944108fc9d4c01fc9c4201fc9d4c05fc9c4202fc944100fc9c4202
+fc944100fc9c4205fc9d4c00fc9c4200fca44800fc9d4c00fc9c4200fc8c3d00ec742a04
+fbb47200ffffff07f4f6f900ecf3f500e8ecef00e0e4e700d9dcde00d2d4d601d8cccb01
+fca46d00fc9c4207fc9d4c00fc9c4200fc9d4c00fc9c4200fc9d4c09fca44800fc8c3d00
+ec742a00fc6c3300ec742a00f9dcd100ffffff06ecf3f500e8ecef00e6dcdc00d9dcde00
+fac4ac00fc9c4207fca44800fc9c4200fca44800fc9c4200fca44800fc9d4c00fca44803
+fcac4c01fca44800fcac4c00fca44800fb7c3801d8a47800cbcccd03c4c5c500cbcccd00
+c4c5c500cbcccd00fcac6600fca44800fcac4c00fca44808fc9c4200fca44800fc9c4201
+fca44800fc9c4200fca44800fc9c4200fca44801fc9c4200fcecc400ffffff15f4f6f900
+e8ecef00e0e4e700d9dcde00d2d4d600c4c5c500cbcccd00c4c5c501c8aca500fb7c3800
+fca44800fcac4c00fca44802fcac6600fcac4c05fcac6602fcac4c00fcac6600fcac4c01
+fca46d00fca44800fcecc400ffffff07f4f6f900ecf3f500e0e4e700d9dcde01d2d4d600
+d8cccb00e68d5600ec742a01fca44805fca46d00fca44802fcac4c01fcac6600fcac4c02
+fcac6600fcac4c00fca44800fcac4c00fca44800fcac4c00fca44806fc9d4c00fca44800
+fc9d4c00fc9c4200fc9d4c00fc9c420efca4480bfcac4c00fca44800fcac4c00fca44800
+fcac4c00fcf4c600ffffff08ecf3f501e0e4e700d9dcde00d2d4d601c4c5c500d6938100
+ec742a05fc8c3d00fcac4c00fca44801fcac4c00fca44800fcac6600fca44800fcac4c01
+fca44800fcac6600fcac4c01fca44807fca46d00fca44800fcac4c00fca44800fcac4c00
+fca44800fcac6600fca44800fcac6600fca44800fcac6600fca44800fcac4c01fcac6600
+fcac4c00fcac6600fca44800fcac4c00fca44800fcac4c00fca46d00fcac4c00fca46d00
+fcac4c01fca44800fcac4c00fca44801fcac4c00fca44806fcac4c00fca44800fcac4c00
+fcac6600c6bcba00b4b4b400a4a5a404cc916400ec742a09fb843a00fca44804fc9c4200
+fca44800fc9c4201fc9d4c00fc9c4200fc9d4c01fc9c4202fc944100fc9c4200fc9d4c02
+fca44800fc9d4c00fca44800fc9c4200fca44800fc9c420bfc944100fc9c4211fc944100
+fc9c4201fc944100fc9c4201fc944100fac4ac00ffffff1bfad4b000fb843a04fb7c3800
+fb843a01fb7c3800fb843a12f38b3600fb843a00f38b3601fc8c3d04f38b3603fc8c3d12
+fc944100fc8c3d00fc944103fc955100fc944108fc8c3d01ec742a00ec6c2800ec742a02
+ec6c2800ec742a00ec6c2802fac4ac00ffffff0dfc9d4c00fc8c3d00fc944100fc8c3d02
+fc944106fc8c3d00fc944100fc8c3d00fc944100fc8c3d04fb843a03f38b3600fb843a00
+f38b3600fc8c3d00f38b3600fc8c3d06fc944100fc8c3d00fc944100fc8c3d00fc944100
+fc8c3d00fc944100fc955100fc8c3d00fc944103fc9c4200fc94410afc955100fc944100
+fc9d4c00fc9c4202fb7c3800fc733900ec742a03f9dcd100ffffff06f4f6f900ecf3f500
+e0e4e700e6dcdc00d2d4d602cbcccd00d8cccb00d7c4bd00fc944117fc733900ec6c2801
+fb7c3800ffffff05f4f6f900e8ecef00e0e4e700d9dcde00e6ccc900fca44800fc944100
+fc9c4200fc944104fc9c4200fc944100fc9c4200fc944101fc9c4200fc944100fc9c4201
+fc9d4c05fb843a00ec6c2800e68d5600d8cccb00d2d4d600cbcccd00c4c5c500cbcccd00
+d8cccb00c4c5c500cbcccd01e8bcb000fc9d4c02fca44800fc9d4c00fca44800fc9c4206
+fca44800fc9c4207fcac6600ffffff15ecf3f500e8ecef00d9dcde00d2d4d600cbcccd00
+c4c5c503e68d5600fc944100fca44801fcac4c00fca46d00fca44801fca46d00fca44801
+fca46d00fca44800fca46d00fca44800fcac4c00fca44805fcac6600ffffff07f4f6f900
+e8ecef00e0e4e701d2d4d601cbcccd00d79c7e00ec6c2800ec742a00fc8c3d00fca44800
+fc9d4c00fca44800fc9d4c02fc9c4200fc9d4c00fca44800fc9d4c00fca44800fc9d4c00
+fca44802fcac4c00fca44803fc9d4c00fca44801fc9d4c05fc955100fc9c4200fc955100
+fc9c4201fc944100fc9c4200fc944102fc9d4c00fc944100fc9c4200fc944100fc9c4200
+fc944100fc9c4200fc944100fc9c4204fc9d4c07facca600f7ece700fcf4c600f7ece700
+fcf4c600f4f6f900ffffff08f4f6f900e8ecef00e0e4e700d9dcde00d2d4d600cbcccd00
+c4c5c500c8aca500ec6c2800ec742a00ec6c2800ec742a00eb642400ec6c2800fc733900
+fc9c4201fc9d4c00fca44801fc9d4c00fca44800fc9d4c00fca44800fc9d4c00fca44806
+fc9d4c01fca44800fc9d4c01fc9c4200fc9d4c06fc944101fc8c3d00fc944100fc955100
+fc9d4c00fca4480cfc9d4c00fca44801fc9d4c02fca44800fc9d4c00fca44800fc9d4c00
+fca44802fc9d4c00fca44800fca46d00b4b4b400a4a5a404c8856300ec6c2800ec742a00
+ec6c2804ec742a00ec6c2801fb7c3800fca44800fc9c4200fca44800fc9c4203fc944100
+fc9c4200fc94410afc9c4200fc9d4c00fc944100fc9c4202fc944100fc9c4200fc944100
+fc9c4200fc94410dfc9c4200fc944100fc9c4200fc944100fc9c4200fc944101fc9c4200
+fc944107fc9c4200fc944101fc9c4200fca46d00ffffff1bfb8d5500fb7c3812fb843a00
+fb7c3803fb843a00fb7c3800fb843a06f38b3604fb843a00fc8c3d00fb843a00f38b3601
+fc8c3d00fb843a00fc8c3d00fb843a00fc8c3d01fb843a00fc8c3d0efc944100fc8c3d00
+fc944100fc8c3d08fb843a00eb642400ec6c2808fac4ac00ffffff0cfcbc8800fb843a00
+fc8c3d00fb843a00fc8c3d04fb843a00fc8c3d08fb843a06fb7c3800fb843a06fb7c3801
+fb843a01fc8c3d00fb843a00fc8c3d02fb8d5500fc8c3d08fc944100fc8c3d00fc944100
+fc8c3d00fc944100fc8c3d04fc944106fc8c3d00ec6c2804fb843a00ffffff06f4f6f900
+e8ecef00e0e4e700d9dcde01d2d4d600d8cccb00cbcccd02efbc8e00fc8c3d12fb8d5500
+fc8c3d00fc944101fc8c3d00ec6c2800eb642401fca46d00ffffff03f4f6f900e8ecef00
+e0e4e700e6dcdc00d9dcde00fca46d00fc944101fc8c3d00fc944106fc8c3d00fc944101
+fc8c3d00fc944101fc8c3d00fc955100fc944100fc955102fb843a00fc653100e7764400
+d2d4d602cbcccd02c4c5c500cbcccd01c4c5c500d7c4bd00fca46d00fc944100fc9d4c00
+fc944110fc9c4200fc944101ffffff14f4f6f900e8ecef00e0e4e700d9dcde00d2d4d600
+cbcccd01c4c5c500c6bcba00c7b5b100fb7c3800fca44804fc9d4c01fc9c4200fc9d4c01
+fca44800fc9d4c00fca44800fc9d4c05fc955100fc9d4c00fad4b000ffffff06f4f6f900
+e8ecef00e0e4e700d9dcde00d2d4d600cbcccd01c7b5b100ec742a00ec6c2800fc733900
+fc9c4200fc9d4c0dfca44800fc9d4c00fca44800fc9d4c03fc955101fc9d4c00fc944102
+fc8c3d00fc944101fc8c3d00fc944100fc8c3d00fc944100fc8c3d00fc955100fc8c3d00
+fc944103fc955100fc8c3d00fc944100fc8c3d00fc944101fc8c3d00fc944100fc955100
+fc944100fc955100fc944104fc955100fc9c4200fc944100fbb47200ffffff0cecf3f500
+e8ecef00e0e4e700d9dcde00d2d4d600cbcccd00c4c5c500bbbcbd00e7764400eb642400
+ec6c2800eb642403fb843a00fc9c4201fc955100fc9d4c0dfc955100fc9c4200fc955100
+fc944100fc9d4c00fc944102fc955100fc9d4c00f9a58b00d79c7e00da846200ec742a00
+eb642401ec6c2803fb7c3800fb843a00fc944100fc9d4c01fca44800fc9d4c09fc9c4200
+fc9d4c00fc944100fc9d4c00fc955100fc9d4c01fc955100fc9c4200fc9d4c00fc9c4201
+fca46d00abacad00a4a5a4009c9e9c00a4a5a401c8856300ec6c2800eb642403ec6c2804
+fb7c3800fc9c4201fc944100fc9c4200fc944103fc8c3d00fc944101fc8c3d00fc944100
+fc8c3d00fc944100fc8c3d00fc944100fc8c3d00fc944104fc955100fc944103fc8c3d00
+fc944100fc8c3d00fc944100fc8c3d05fc944100fc8c3d00fc944103fc8c3d00fc94410c
+fc8c3d00fc944100fc8c3d00fc944101fc8c3d00fc944100fcf4c600ffffff19fbb47200
+fc733901fb7c3800fc733900fb7c3800fc733900fb7c3800fc733901fb7c3800fc733901
+fb7c3800fc733901fb7c3800fc733900fb7c380dfb843a00fb7c3801fc733903fb7c3800
+fb843a12fc8c3d01fb843a01fc8c3d00fb843a00fc8c3d02fb843a00fc8c3d00fb843a00
+fc8c3d00fb843a06fb7c3800eb642402ec6c2800eb642405fac4ac00ffffff0bf9e4e100
+fb843a08fc8c3d00fb843a00fc8c3d00fb843a00fc8c3d00fb843a00fc8c3d00fb843a04
+fb7c3808fc6c3300fc653100eb642401e5541f00eb642400e75c2a00eb642400eb826400
+e8a58f00fca46d00fb8d5500fb843a05fb8d5500fb843a00fc8c3d14fb7c3800ec6c2804
+fcb58e00ffffff05f4f6f900ecf3f500e8ecef00e6dcdc00d9dcde00d2d4d601cbcccd00
+d2d4d600cbcccd00d2d4d600f9a58b00fc8c3d01fb843a04fb7c3800fb843a00fb7c3800
+fb843a06fc8c3d02fb8d5500fc8c3d01fc733900e75c2a00eb642401f8cbc000ffffff01
+f4f6f900ecf3f500e8ecef00e0e4e700d9dcde00fcb58e00fc8c3d0ffb8d5500fc8c3d04
+fb843a00eb642400ec6c2800e8c2b000d9dcde01d2d4d601cbcccd02c4c5c500cbcccd02
+eeb48e00fc8c3d01fb8d5500fc8c3d07fc944100fc8c3d02fc944100fc8c3d00fc944104
+fbb47200ffffff13ecf3f500e8ecef00e0e4e700d9dcde00d8cccb00cbcccd00c4c5c502
+d6938100fb843a00fc9c4200fc9d4c08fc955100fc9d4c05fc955100fc944100fc955100
+fc9d4c00ffffff06f4f6f900e8ecef00e0e4e700d9dcde00d2d4d600cbcccd02d98c7800
+ec6c2800eb642400fc8c3d00fc9d4c03fc955100fc944100fc9d4c00fc944102fc955100
+fc944100fc955100fc944100fc955101fc9d4c00fc955100fc9d4c00fc955100fc9c4200
+fc955100fc944102fc955100fc8c3d01fb8d5500fc8c3d04fb843a00fc8c3d00fb843a00
+fc8c3d00fb843a00fc8c3d02fb843a00fc8c3d00fb8d5500fc8c3d02fb8d5500fc8c3d04
+fc944100fc8c3d00fc955100fc8c3d01fc944100fc8c3d00fc944100fbe4c100ffffff0a
+f4f6f900e8ecef00e0e4e700d9dcde00cbcccd00c4c5c501bbbcbd00cc916400e75c2a00
+eb642400e75c2a01e5541f00e75c2a00fc6c3300fc8c3d02fc944102fc955100fc944100
+fc955100fc944100fc955101fc944100fb8d5500fc944101fb8d5500fc8c3d00fc944100
+fc8c3d00fc944100fb8d5500fc8c3d01fc955100e59c8700c8a49d00abacad02a4a5a400
+abacad00b8938b00d3725300eb642404ec6c2800eb642400fc733900fc8c3d00fc955100
+fc9d4c01fc9c4200fc955100fc944100fc955100fc944100fc955100fc944100fc955100
+fc944106fc955100fc944101fc955100fc9d4c00fc944100dba39300a4a5a403c8856300
+eb642402e75c2a00eb642405fc733900fc944103fc8c3d02fb843a00fc8c3d01fb843a00
+fc8c3d06fb843a00fc8c3d06fb843a0cfc8c3d08fb843a00fc8c3d01fb843a00fc8c3d0c
+fad4b000ffffff18f7ece700fc733900fc6c3300fc733900fc6c3305fc73390ffb7c3800
+fc733901fb7c3800fc733901fc6c3300eb642401e75c2a00eb642400e75c2a00eb642400
+e75c2a00eb642402fc733900fb843a00fb7c3805fb843a00fb7c3800fb843a02fb7c3800
+fb843a01fb7c3800fb843a00fb7c3800fb843a01fb7c3800fb843a00fb7c3800fb843a04
+fb7c3800fb843a01fb7c3800fb843a00fb7c3800fb843a00fb7c3800fc733900eb642400
+e75c2a00eb642404e75c2a00eb642401efbc8e00ffffff0bfca46d00fb7c3806fb843a01
+fb7c3800fb843a05fb7c3800fb843a00fb7c3800fb843a00fb7c3804fc733900fb7c3800
+fc6c3300fc653100e5541f04e75c2a00ec6c2800d79c7e00d7c4bd00d2d4d600d8cccb00
+cbcccd00d8cccb00e8b3a800fa9c7900fb843a07fc8c3d00fb843a00fc8c3d00fb843a08
+fc8c3d00fb843a00fc8c3d00fb843a00fc8c3d01fb843a01eb642404ec6c2800ffffff06
+f4f6f900e8ecef00e0e4e700d9dcde00d2d4d602d8cccb00cbcccd01d8cccb00fc9d4c00
+fb7c3800fb843a00fb7c380bfb843a08fc653100e75c2a01ec6c2800f7ece700f4f6f900
+ecf3f500e8ecef00e0e4e700d9dcde00e8c2b000fb843a03fc8c3d00fb843a00fc8c3d00
+fb843a00fc8c3d00fb843a00fc8c3d08fb8d5500fc8c3d00fb843a01fc6c3300e75c2a00
+e6ad9b00e0e4e701d9dcde01d2d4d600d8cccb00cbcccd01c4c5c500cbcccd00c4c5c500
+cbcccd00d7c4bd00fb8d5500fb843a0bfc8c3d00fb843a00fc8c3d01fb843a00fc8c3d00
+fb843a00fc8c3d01fb843a00ffffff12f4f6f900ecf3f500e0e4e700d9dcde00d2d4d600
+c4c5c503c7b5b100ec742a00fc944102fc955100fc944100fc955100fc944101fb8d5500
+fc944100fc955100fc944100fc955104fc944100fc955100fc944101facca600ffffff05
+f4f6f900ecf3f500e0e4e700d9dcde00d2d4d600cbcccd01c4c5c500c7b5b100ec6c2801
+fc6c3300fc944101fc955100fc8c3d00fc955100fc944100fc8c3d00fc944100fc955100
+fc8c3d00fc944100fc8c3d00fc944102fc955100fc944101fc955100fc944100fc8c3d00
+fb8d5500fc8c3d02fb843a00fc8c3d00fb8d5500fa9c7900f2a27200e59c8700d8755c00
+fc653100e75c2a00fb5c2e00fc6c3300fc733900fb7c3801fb843a00fb7c3800fb843a00
+fa7c5800fb843a00fb7c3800fb843a00fb7c3800fb843a05fb8d5500fc8c3d00fb843a00
+fc8c3d00fb843a00fc8c3d01fb843a00fb8d5500fc8c3d00fc955100ffffff09f4f6f900
+ecf3f500e0e4e700d9dcde00cbcccd01c4c5c500bbbcbd00b8adaa00eb642400e5541f03
+e75c2a00e5541f00fb843a00fc8c3d02fb8d5500fc8c3d0dfb843a00fc8c3d02fc955100
+e8a58f00b4b4b401abacad07b8938b00dc6c3c00e75c2a00eb642401e75c2a00eb642402
+ec6c2800fb843a00fc8c3d00fc944100fc8c3d00fc944100fc8c3d05fb8d5500fc8c3d01
+fb8d5500fc8c3d02fc944101fc8c3d00fc944101fc955100c7998d00abacad009c9e9c00
+a4a5a400c8856300e75c2a01e5541f01eb642400d9542d00ec6c2800da633600e75c2a01
+fc6c3300fc8c3d03fb843a04fb7c3800fb843a00fb7c3800fb843a00fb7c3800fb843a09
+fb7c380bfb843a00fb7c3800fb843a00fb7c3800fb843a04fb7c3800fb843a02fb7c3800
+fb843a02fb7c3800fb843a0afcb58e00ffffff18fa9c7900fc653100fc6c3300fc653100
+fc6c3302fc653100fc6c3308fc733900fc6c3300fc733900fc6c3300fc733902fc6c3300
+fc733900fc6c3300fc733900fc6c3300fc653100eb642400e75c2a00e5541f02e75c2a00
+e5541f04da633600e68d5600d8b4ac00d7c4bd00ecae7c00fb843a00fb7c3809fc733900
+fb7c3809fc733900fb7c3800fc733900fb7c3802fc733900fb7c3800fc733902fb7c3800
+fc733900e75c2a04e5541f00e75c2a01e5541f00e75c2a00fac4ac00ffffff0afad4b000
+fc733900fb7c3800fc733902fb7c3800fc733900fb7c3812fc6c3300eb642400e5541f02
+e75c2a01e5541f00e7764400d8ac9f00d2d4d600d9dcde00d2d4d604d8cccb00cbcccd00
+e8c2b000fa9c7900fb843a00fb7c3800fb843a02fb7c3800fb843a01fb7c3800fb843a01
+fb7c3800fb843a00fb7c3800fb843a00fb7c3800fb843a01fb7c3800fb843a00fb7c3800
+fb843a01fb7c3800fb843a00fb7c3800fc733900e75c2a00eb642403fa9c7900ffffff05
+f4f6f901e0e4e701d9dcde01d2d4d601cbcccd00d2d4d600cbcccd00d7c4bd00fb843a00
+fb7c3806fc733900fb7c3800fc733900fb7c3807fb843a00fb7c3800fb843a01fc733900
+e5541f02e9947d00e8ecef01e0e4e700d9dcde00e9d5d700fb8d5500fb7c3801fb843a0c
+fc8c3d00fb843a05fc6c3300e75c2a00e68d5600e8ecef02e0e4e700e6dcdc00d2d4d601
+cbcccd00d8cccb00c4c5c500cbcccd00c4c5c501cbcccd00f9a58b00fb7c3800fb843a00
+fb7c3800fb843a12fcbc8800ffffff11f4f6f900e8ecef00e0e4e700d2d4d601cbcccd01
+c4c5c501d6938100fb7c3800fc8c3d00fc944100fb8d5500fc8c3d02fb8d5500fc8c3d01
+fb843a00fc8c3d01fb8d5500fc8c3d00fc944100fc8c3d00fb8d5500fc8c3d02fc955100
+ffffff06f4f6f900e0e4e701d2d4d600cbcccd00c4c5c502cc916400e75c2a00eb642400
+fb7c3800fc944100fc8c3d00fc955100fc8c3d02fb8d5500fc8c3d00fb843a00fc8c3d00
+fb8d5500fb843a00fb8d5500fb843a00fc8c3d06fb843a03f9947500e8a58f00c7b5b100
+bbbcbd01b4b4b400bbbcbd00b8adaa00c88b7d00e9644000e5541f00e54d1d00fb5c2e00
+fb6c4100fb7c3806fa7c5800fb843a00fb7c3800fb843a00fa7c5800fb843a00fb7c3800
+fb843a00fb7c3800fb843a02fa7c5800fb843a04fac4ac00ffffff07f4f6f900ecf3f500
+e0e4e700d9dcde00cbcccd01c4c5c500bbbcbd00b4b4b400c8856300e5541f05fc653100
+fb843a07fb8d5500fb843a06fb7c3800fb843a00fb7c3800fb843a01fb8d5500e6ad9b00
+c6bcba00bbbcbd02b4b4b400abacad00b4b4b400abacad05a4a5a400c8856300e5541f05
+e75c2a00e5541f00fc6c3300fb843a09fc8c3d00fb843a00fc8c3d00fb843a00fc8c3d01
+fb8d5500fc8c3d01fb8d5500fc8c3d01fc955100a4a5a402b77c6a00e75c2a00e5541f00
+d9542d00e5541f00d9542d00e75c2a01e5541f00e75c2a00e5541f00fc6c3300fc8c3d00
+fb843a04fb7c3803fb744e00fb7c3807fa7c5800fb7c3802fc733900fb7c3801fc733900
+fb7c3800fc733900fb7c3800fc6c3300fc653100eb642400fb552700e5541f00fb552700
+fc653100fc6c3300fc733900fb7c3801fc733900fb7c3801fc733900fb7c3801fc733900
+fb7c3802fc733900fb7c3800fa7c5800fb7c3801fb843a00fb7c3800fb843a00fb7c3804
+fb843a00fc955100ffffff17f9e4e100fc6c3300fc653101fb5c2e02fc653106fc6c3300
+fc653100fc6c3300fc653100fc6c3309fb5c2e00e5541f08d9542d00e5541f00e75c2a00
+cc916400d7c4bd00d2d4d601cbcccd01d8cccb00e4ae7c00fb843a00fc733906fb7c3800
+fc73390afc6c3300fc733900fc6c3303fc733900fc6c3300fc733903fc653100e5541f04
+e75c2a00e5541f01e75c2a00e5541f00f7b9a600ffffff09f4f6f900f9947500fc6c3302
+fc733907fb7c3801fb744e00fb7c3802fc733900fb7c3801fc733900fb7c3801fc733900
+fc6c3300eb642400e5541f03e75c2a00e5541f00eb642400e6ad9b00e0e4e703e6dcdc00
+d9dcde01d2d4d603cbcccd00d8cccb00d7c4bd00f9947500fc733900fb7c3806fc733900
+fb7c3801fc733900fb7c3801fc733900fb7c3801fc733900fb7c3801fc733900fb7c3802
+fc733900eb642400e5541f00e75c2a02eb642400f7ece700ffffff05f4f6f900e8ecef01
+e6dcdc00d9dcde00d2d4d601cbcccd01d2d4d600cbcccd00e8bcb000fb7c3801fc73390c
+fb7c3800fb744e00fb7c3800fb744e00fb7c3800fc733900fb7c3801fc653100e54d1d01
+e5541f00e8bcb000e0e4e701d9dcde00fa9c7900fb7c3800fc733900fb7c3800fc733900
+fb7c3804fb843a00fb7c3800fb843a04fa7c5800fb843a00fb7c3802fb843a00fc733900
+e75c2a00e7764400f7ece700ecf3f501e8ecef00e0e4e700e6dcdc00d9dcde00d2d4d600
+cbcccd03c4c5c500cbcccd00c4c5c500d8bcb600fb843a00fb7c3802fb744e00fb7c3800
+fc733900fb7c3800fc733900fb7c380afa7c5800fb843a00fa7c5800ffffff10f4f6f900
+ecf3f500e0e4e700d9dcde00d2d4d600cbcccd00c4c5c502c6bcba00ec6c2800fb843a01
+fc8c3d00fb843a00fc8c3d00fb843a05f8836200fb843a08fcb58e00ffffff05ecf3f500
+e8ecef00e0e4e700d2d4d601cbcccd00c4c5c501c7b5b100e75c2a01eb642400fb843a01
+fb8d5500fb843a00fc8c3d00fb843a01fc8c3d00fb843a0bfa7c5800fb843a01fa7c5800
+fb8d5500e6ad9b00c6bcba01bbbcbd04b4b4b400bbbcbd00b8adaa00c88b7d00e75c2a00
+d94b2000e4461800fb552700fc653100fc733900fb7c3800fb744e00fb7c3801fc733900
+fb7c3801fb744e00fb7c3804fa7c5800fb7c3805fb843a02ffffff07ecf3f500e0e4e700
+d9dcde00d2d4d600cbcccd00c4c5c500bbbcbd01b8adaa00d9542d00e4461800d94b2000
+e54d1d00d94b2000e5541f00e54d1d00fc733900fb7c3802fa7c5800fb7c3801fa7c5800
+fb7c3802fa7c5800fb7c3800fa7c5800fb7c3800fa7c5800fc733900fb7c3800fa7c5800
+fc733900fa7c5800fca46d00d8cccb00cbcccd01c4c5c500bbbcbd02b4b4b400abacad07
+a89a9500dc6c3c00e5541f07fc653100fb843a00fa7c5800fb7c3800fb843a00fa7c5800
+fb7c3801fa7c5800fb7c3800fb843a00fa7c5800fb843a00fb7c3800fb843a04fc8c3d02
+fb843a00f9947500a4a5a401c8745e00e5541f00d9542d00e5541f02d9542d00e5541f00
+d9542d00e5541f01fc653100fb7c3803fb744e00fc733906fb6c4100fc6c3300fb6c4100
+fc6c3300fc733908fc6c3300fc733900fc6c3300fb5c2e00fb552700e4461803d94b2001
+e4461801e5541f00fb552700fc6c3300fc733901fc6c3300fc733900fc6c3301fc733901
+fc6c3300fc733905fb744e00fc733902fb7c3801fc733900fb7c3800fc733900fb7c3800
+f4f6f900ffffff16fa9c7900fc653100fb552700fb5c2e03fb552702fb5c2e02fc653100
+fb5c2e00fc653101fb5c2e00fc653107fb552700e54d1d00e5541f00d94b2000e54d1d00
+d94b2004e5541f00d94b2000e5541f00da846200d7c4bd00d9dcde03d2d4d602d8cccb00
+cbcccd00f2a27200fc733902fc6c3300fc733900fc6c3301fc733900fc6c3300fc733900
+fc6c3305fc653100fc6c3300fc653101fc6c3300fc653105fc6c3300fc653100fc6c3300
+fc653100e5541f03d9542d00e5541f01d94b2000e5541f01f7b9a600ffffff08f4f6f900
+f8cbc000fc6c3300fc653100fc6c3300fc653101fc6c3300fc653100fc6c3300fc653100
+fc6c3305fc733900fc6c3300fc733901fc6c3300fc733901fc6c3301fb5c2e00e5541f00
+e54d1d02e5541f02eb826400e9d9b900ecf3f501f7ece700e8ecef02e0e4e700d9dcde02
+d2d4d603cbcccd00d8cccb00f9ad9400fb7c3800fb6c4100fc733915fc653100e5541f04
+fa9c7900ffffff06f4f6f900e8ecef00e0e4e700d9dcde01d2d4d602cbcccd00d8cccb00
+cbcccd00f2a27200fc733902fc6c3300fc733900fc6c3300fc733900fc6c3300fc733900
+fc6c3309fc733900fc6c3300fc733900fc6c3300e5541f00e4461801e75c2a00e9d5d700
+d9dcde00f7b9a600fc733907fb7c3800fc733901fb7c3800fc733900fb7c3800fc733900
+fb744e00fb7c3805fc733900e5541f00e75c2a00f9dcd100ffffff01f4f6f901e8ecef01
+d9dcde01d2d4d600cbcccd01c4c5c500cbcccd02c4c5c500fa9c7900fc733905fc6c3300
+fc733905fb7c3800fc733901fb7c3800fb744e00fb7c3800fc733900fb7c3800fc733900
+fac4ac00ffffff0ff4f6f900e8ecef00e0e4e700d9dcde00d2d4d600d8cccb00c4c5c502
+d79c7e00fc6c3300fb7c3800fb843a00fb7c3800fb843a00fb7c3801fa7c5800fb843a00
+fb7c3800fa7c5800fb843a01fb7c3802fa7c5800fb7c3801fa7c5800fb7c3801f4f6f900
+ffffff04f4f6f900e8ecef00e0e4e700d9dcde00d2d4d600cbcccd00c4c5c500c6bcba00
+c4c5c500c88b7d00e5541f00e54d1d00fc653100fb7c3803fa7c5800fb843a01fa7c5800
+fb843a03fb7c3800fb843a00fb7c3800fa7c5800fb7c3800fa7c5800fb843a00fa7c5800
+fb7c3801fb843a00f9ad9400cbcccd01c4c5c500bbbcbd00c4c5c500bbbcbd00c6bcba00
+b4b4b400bbbcbd01b4b4b400bbbcbd01b8adaa00d3725300d94b2000e4461800d9431900
+fb552700fc6c3300fc733907fb6c4100fc733900fb6c4100fc733902fb7c3800fc733901
+fb7c3800fb744e00fc733900fa7c5800fb7c3800fcb58e00ffffff05ecf3f500e8ecef00
+e0e4e700d2d4d600cbcccd00c4c5c500bbbcbd01b4b4b400c97c6700e4461800d9431900
+e4461803fb552700fc6c3300fc733900fb6c4100fc733905fb6c4100fc733906fc6c3300
+fc733900fb7c3800fac4ac00d9dcde01d2d4d600cbcccd01c4c5c500bbbcbd01b4b4b401
+b8adaa00abacad03a4a5a400b98a7c00e5541f00d94b2000e4461800d94b2001e5541f00
+d94b2000e5541f01fc6c3300fb7c3803fc733900fb7c3800fb744e00fb7c3802fc733900
+fb7c3802fa7c5800fb7c3801fa7c5800fb843a00fb7c3800fb843a00fb7c3800fb843a01
+c7998d00a4a5a400c8745e00d94b2003e5541f00d94b2000e5541f00d94b2000e5541f00
+d94b2000fb5c2e00fb7c3800fc733908fc6c330feb826400b78d8500c86d5400d9431905
+e4461800d9431901e4461802fb552700fc653100fc6c330cfc733900fc6c3300fc733900
+fc6c3302fc733900fc6c3300fc733901f9dcd100ffffff15f7ece700fc653100fb552700
+fb5c2e00fb552703fb5c2e00fb552702fb5c2e01fb552700fb5c2e04fb552700fb5c2e01
+fc653101fb5c2e00e5541f00e4461800e54d1d00e4461800d94b2000e54d1d00e4461800
+e54d1d01d94b2000e4461801d9542d00d8ac9f00e0e4e701e8ecef00d9dcde00e0e4e700
+d9dcde02d2d4d601cbcccd00d2d4d600d8bcb600fb843a00fc6c3300fc653101fc6c3300
+fc653105fb5c2e06fc653100fb5c2e00fc653101fb5c2e01fc653100fb5c2e00fc653102
+fb5c2e00e54d1d00e4461800d94b2002e54d1d00d94b2000e54d1d00e4461800d94b2000
+eeb48e00ffffff08f4f6f900fb8d5500fc653100fb5c2e01fc653100fb5c2e01fc653100
+fb5c2e00fc653105fc6c3300fc653102fc6c3300fc653103e54d1d00e4461802d94b2000
+e4461800d9431900d94b2000e9947d00ecf3f500f4f6f904ecf3f500e8ecef01e0e4e701
+e6dcdc00d9dcde00d2d4d602d8cccb00cbcccd01d8bcb600fa7c5800fc6c3301fc653100
+fc6c3301fc653100fc6c3304fc653100fc6c3300fc653100fc6c3307fc653100e5541f00
+e54d1d00d94b2000e54d1d00d94b2000e5541f00ffffff07f4f6f900e8ecef00e0e4e700
+e6dcdc00d2d4d602cbcccd00d2d4d600cbcccd01f9947500fc6c3304fc65310afc6c3300
+fc653100fc6c3303fc653100e4461800d94b2000d9431900da846200d8cccb00fb7c3800
+fc6c3302fc733902fc6c3300fc733900fc6c3300fc733903fc6c3300fc733902fc6c3300
+fc733902fb6c4100fb552700d94b2000fac4ac00ffffff03f4f6f901e8ecef00d9dcde01
+d2d4d600d8cccb00cbcccd00c4c5c500cbcccd00c4c5c501cbcccd00d8bcb600fc6c330a
+fc733900fc6c3301fc733901fc6c3300fc733905ffffff0fecf3f500e0e4e700d9dcde00
+d2d4d600cbcccd00c4c5c502c6bcba00dc6c3c00fc6c3300fb7c3801fb744e00fc733900
+fb7c3800fb744e00fb7c3800fc733900fb7c3800fc733904fb6c4100fc6c3300fb6c4100
+fc6c3302fa9c7900ffffff05f4f6f900e8ecef00d9dcde00d2d4d600cbcccd01c4c5c500
+bbbcbd01da633600d9431900e4461800fc6c3300fc733903fb7c3800fc733900fb7c3800
+fc733900fb7c3800fb744e01fb7c3801fb744e00fb7c3806f5886c00e6ccc900d9dcde00
+d2d4d600cbcccd02c4c5c500bbbcbd05b4b4b400bbbcbd02c88b7d00d9431900e4461800
+dc3e1400e4461800fb5c2e00fc6c3300fc733900fc6c3300fb6c4100fc6c3306fb6c4100
+fc6c3300fc733900fb6c4100fc733900fb6c4100fc733901fc6c3300fc733900fb744e00
+ffffff04f4f6f900ecf3f500e0e4e700d9dcde00cbcccd00c4c5c500bbbcbd01b4b4b400
+b8adaa00d94b2000dc3e1400e4461800dc3e1402e4461800fb5c2e00fc6c3310fb6c4100
+fc733900f8cbc000e8ecef00e0e4e700d9dcde01d2d4d600cbcccd00c4c5c501bbbcbd00
+b4b4b400abacad04b99a9400c7634a00e4461803d94b2000e54d1d00e4461801fb552700
+fc6c3300fc733903fb7c3800fc733909fb7c3800fc733900fb7c3801fc733900fb7c3800
+fb744e00fb7c3802fb843a00a4a5a400c86d5400e4461802d9431901e4461800d9431900
+e4461802fb552700fc733900fc6c3300fc733900fc6c3301fc733900fc6c3303fc733900
+fc6c3303fc653101fc6c3300fc653101fc6c3300fc653100fc6c3301fb6c4100cc916400
+9c9e9c02b7746200e4461801d9431900e4461801dc3e1400e4461800d9431900e4461800
+dc3e1400e4461801fb552700fc653100fc6c3300fc653108fc6c3300fc653102fc6c3300
+fc653100fc6c3300fc653100fc6c3303fac4ac00ffffff15f9ad9400fb552717e4461801
+d9431901dc3e1400e4461800d9431901dc3e1400e4461800d9431901da633600d8cccb00
+e8ecef06e0e4e700d9dcde02d2d4d601cbcccd01f9947500fc653101fb5c2e02fc653100
+fb552706fb5c2e00fb552706fb5c2e00fb552700fb5c2e03fb552700d9431901e4461800
+d9431900e4461800dc3e1400e4461800d9431901dc3e1400f7b9a600ffffff07f4f6f900
+f8d4c900fc653100fb552700fc653100fb5c2e06fb552700fb5c2e00fb552700fb5c2e03
+fc653100fb5c2e01fc653101fb552700e4461802d9431900e4461800d9431900dc3e1400
+e4461800e8a58f00f4f6f900ffffff06f4f6f901f7ece700e8ecef00e0e4e701e6dcdc00
+d9dcde00d2d4d603cbcccd00d7c4bd00fa7c5800fc653105fb5c2e01fc653100fb5c2e00
+fc653101fb5c2e00fc653100fb5c2e00fc653103fb5c2e00fc653101fb552700dc3e1400
+e4461800dc3e1400e4461800d9431900fa9c7900ffffff06f4f6f900f7ece700e8ecef00
+e0e4e700d9dcde01d2d4d601cbcccd01d2d4d600d7c4bd00fb7c3800fc6c3301fc65310e
+fb5c2e00fc653103fb552700dc3e1400e4461801fb744e00fc653101fc6c3300fc653100
+fc6c3300fc653103fc6c3300fc653102fc6c3300fc653100fc6c3300fc653100fc6c3302
+fb6c4100fc6c3300fb552700d9431900fa9c7900ffffff05f4f6f900e8ecef01d9dcde00
+d2d4d600cbcccd04d8cccb00c4c5c500cbcccd00f8836200fc653104f9653d00fc653101
+fc6c3300fc653101fc6c3300fc653104fc6c3300fc653100fc6c3302f8cbc000ffffff0d
+f4f6f900e8ecef00e0e4e700d9dcde00d2d4d600cbcccd01c4c5c501c8a49d00fb552700
+fc733901fc6c3300fc733901fc6c3303fb6c4100fc6c3300fb6c4100fc653100fb6c4100
+fc653100fc6c3300fc653100fc6c3300fc653100fc6c3300fc653100f9e4e100ffffff04
+f4f6f900e8ecef00e0e4e700d9dcde00d2d4d600cbcccd00c4c5c500bbbcbd00c4c5c500
+c8aca500d9431900dc3e1400fb552700fc6c3306fb6c4100fc6c3300fb6c4100fc733906
+fb6c4100fc733900fb6c4100fc733900fa7c5800f8d4c900e0e4e701d9dcde01d2d4d600
+cbcccd01c4c5c501bbbcbd00c6bcba00b4b4b400bbbcbd02b4b4b402c97c6700dc3e1400
+d9431900dc3e1400e4461800fb5c2e00fc653101fc6c3302fc653100fc6c3300fc653100
+fc6c3300fc653100fc6c330af9ad9400ffffff03ecf3f500e8ecef00d9dcde00d2d4d600
+cbcccd00c4c5c500bbbcbd01b4b4b400c8847200d9431900dc3e1401e4461800dc3e1400
+e4461800e54d1d00fc6c3305fc653100fc6c3301fc653102fc6c3300fc653100fb6c4100
+fc6c3302fc653100fac4ac00f4f6f900e8ecef01e0e4e700d9dcde00d2d4d600cbcccd01
+bbbcbd01b4b4b400bbbcbd00abacad02b9857800d9542d00dc3e1400d9431900dc3e1400
+d9431902dc3e1400e4461800fb5c2e00fc6c3305fb6c4100fc6c3300fc733900fc6c3301
+fb6c4100fc6c3300fb6c4100fc6c3303fb6c4100fc6c3300fb6c4100fc733904fb744e00
+e78b7100a4a5a400c86d5400d9431900dc3e1401d9431900dc3e1401d9431900dc3e1401
+d9431900fb552700fc653100fc6c3303fc653100fc6c3301fc653100fc6c3300fc653101
+fc6c3300fc653109fb6c4100c7998d009c9e9c02a4a5a4009c9e9c00ba654f00dc3e1400
+e4461800dc3e1409fb552700fc653104fc6c3300f9653d00fc65310cfb5c2e00fc653100
+f9a58b00ffffff14f4f6f900fc653100fb552705fb5c2e00fb552700fb5c2e00fb552700
+fb5c2e00fb552701fb5c2e00fb552701fb5c2e00fb552701fb5c2e00fb552702dc3e1402
+d9431906dc3e1401da633600e6dcdc00e8ecef01ecf3f501f7ece700ecf3f501e8ecef02
+e0e4e700d9dcde02d2d4d601cbcccd00e9947d00fb552704fb5c2e03fc653100fb5c2e06
+fb552700fb5c2e01fb552701fb5c2e00fb552701fb5c2e00fb552700e4461800dc3e1401
+e4461800dc3e1402e4461800dc3e1400e4461800f9ad9400ffffff07ecf3f500fa9c7900
+fb5c2e01fb552700fb5c2e02fb552700fb5c2e03fc653100fb5c2e03fb552700fb5c2e00
+fb552700fb5c2e00fb552701e4461801dc3e1405e8866c00ffffff0af4f6f900ecf3f500
+e8ecef01e0e4e700d9dcde02d2d4d601d8cccb00cbcccd00d7c4bd00fc6c3300fb5c2e04
+fc653100fb5c2e01fc653100fb5c2e00fc653102fb5c2e00fc653100fb5c2e00fc653100
+fb552700fc653100fb5c2e01fb552700dc3e1401d9431900dc3e1400d9431900e75c2a00
+ffffff07f4f6f900ecf3f500e8ecef00e6dcdc00d9dcde00d2d4d602d8cccb00cbcccd01
+d8bcb600fc6c3300fc653100fb5c2e00fc653100fb5c2e00fc653100fb5c2e00fc653103
+f9653d00fc653100f9653d00fc653104fb5c2e00fc653101fb5c2e00e4461800dc3e1400
+fb552700fc653103fb5c2e00fc653109fb5c2e00fc653105fb552700dc3e1400e86c4c00
+ffffff07f4f6f900e8ecef00e6dcdc00d9dcde00d2d4d600cbcccd01c4c5c500cbcccd00
+c4c5c500cbcccd00c4c5c500e8b3a800fb6c4100fc6c3300fb6c410bfc6c3300fb6c4100
+fc653105fa7c5800ffffff0decf3f500e8ecef00d9dcde00d2d4d600d8cccb00c4c5c503
+da633600fb5c2e00fc6c3300fc653103fb6c4100fc653100fc6c3300fc653100fb6c4100
+fc653100fc6c3300fb6c4100fc6c3300f9653d00fb6c4100fc6c3300fb6c4102f5886c00
+ffffff05ecf3f500e8ecef00d9dcde00d2d4d600cbcccd00c4c5c501c6bcba00bbbcbd00
+c8847200dc3e1401fb552700fc653101f9653d00fc653101f9653d00fc6c3300fc653100
+fc6c3301fc653100fc6c3301fc653100fc6c3306f7b9a600f4f6f900ecf3f500e8ecef00
+e0e4e700d9dcde01d2d4d601cbcccd00c4c5c501bbbcbd02b4b4b400bbbcbd00b4b4b400
+bbbcbd01b8adaa00d45e4400d9431902e4461800fc653100fb6c4100fc6c3300fb6c4106
+fc6c3300fc653102fc6c3305fc653100fc733900ffffff02f4f6f900ecf3f500e0e4e700
+d9dcde00cbcccd00c4c5c500bbbcbd01b4b4b401c9593b00dc3e1405fb552700fc6c3301
+fc653101fc6c3300f9653d00fc6c3300fc653100f9653d00fc6c3300fb6c4101fc6c3300
+fb6c4100fc653101f9653d00fc6c3300fa9c7900ffffff00f4f6f901ecf3f500e0e4e701
+d2d4d601c4c5c501bbbcbd00b4b4b400abacad00b4b4b400a4a5a400c7634a00dc3e1404
+d9431900dc3e1401e54d1d00fc653101fc6c3300fc653100fc6c3300fc653100fc6c3300
+fc653103fc6c3301fc653100fc6c3300fc653100fc6c3300fc653100fc6c3300fc653100
+fc6c3300fc653102fc6c3301fb6c4100fa7c5800b99a9400a4a5a401b7746200dc3e1401
+d9431901dc3e1400d9431900dc3e1401d9431900dc3e1400e54d1d00fc65310afb6c4100
+fc653100fb6c4100fc6c3300fb6c4100fc6c3300f9653d00fc6c3300fc653100fb6c4100
+fc653100fc6c3300e8866c009c9e9c00a4a5a4009c9e9c03a88c8600d94b2000d9431909
+dc3e1400d9431900fc653100fc6c3300fb6c4101f9653d00fb6c4100fc6c3300fb6c4100
+fc653100f9653d00fc6c3300fc653100fb6c4100fc6c3300f9653d00fc653100f9653d00
+fc653100f9653d00fc653100fb6c4100fc653100f9947500ffffff14fac4ac00fb552705
+fb5c2e00fb552700fb5c2e0de75c2a00d9431902c9452200d9431900d94b2000d9431900
+d94b2000d9431900d94b2000d9431900c9452200d9542d00e6ccc900e8ecef00ecf3f500
+f4f6f902ffffff01f4f6f902f7ece700e8ecef00e0e4e701d9dcde01d2d4d601cbcccd00
+f8836200fb5c2e00fc653100fb5c2e00fc653100fb5c2e05fc653100fb5c2e08fc653100
+fb5c2e02fb552701dc3e1401d9431900dc3e1401d9431900dc3e1400d9431901dc3e1400
+e8b3a800ffffff06f4f6f900f9e4e100fb6c4100fb5c2e01fc653100fb5c2e01fc653100
+fb5c2e00fc653100fb5c2e00fc653100fb5c2e01fc653100fb5c2e01fc653100fb5c2e01
+fc653100fb5c2e00fc653100fb552700dc3e1400d9431901dc3e1400d9431902d95d3b00
+f4f6f900ffffff0bf4f6f901e8ecef02e6dcdc00d9dcde01d2d4d600cbcccd00d2d4d600
+cbcccd00e8b3a800fb5c2e00fc653100fb5c2e00fc653101fb5c2e00fc653105f9653d00
+fc653100fc6c3301fc653103fc6c3300fc653100e5541f00d9431900d94b2000d9431902
+f8cbc000ffffff07f4f6f900e8ecef01e6dcdc00d9dcde01cbcccd00d2d4d600cbcccd00
+d8cccb00cbcccd00e8a58f00fc653107f9653d00fc653100f9653d01fc653100f9653d04
+fc653103fb5c2e00e4461800fc653103f9653d00fc65310af9653d00fc653104fb5c2e00
+d9431900e5541f00f4f6f900ffffff07f4f6f900e8ecef01d9dcde00d2d4d600d8cccb00
+cbcccd00d8cccb00c4c5c500cbcccd00c4c5c500cbcccd01f8836200fb6c4103fb744e00
+fc733900fb744e00fc733900fb744e00fb6c4100fc733900fb6c4100fc733900fb6c4106
+f9653d00fc653100f9e4e100ffffff0bf4f6f900e8ecef00e0e4e700d9dcde00d2d4d600
+cbcccd01c4c5c501c8aca500e54d1d00fc653100fc6c3300fb6c4105fc733900fb6c410b
+f9dcd100ffffff04f4f6f900e8ecef00e0e4e700d9dcde00cbcccd01c4c5c502c6bcba00
+d45e4400d9431901fc653100fb6c4100fc6c3300fb6c4102fc6c3300fb6c4101fc6c3300
+f9653d00fc6c3300fc653100f9653d00fc653100f9653d00fc6c3300f9653d00fc653100
+fc6c3300f9653d00fb8d5500ffffff01f4f6f901e8ecef01e0e4e700d9dcde00d2d4d601
+cbcccd00c4c5c501c6bcba00bbbcbd00c6bcba00b4b4b400bbbcbd00b4b4b400bbbcbd01
+b99a9400d94b2000d9431902fb552700fb6c410cfc653100fb6c4100fc653100f9653d00
+fc6c3300f9653d00fc6c3300fb6c4100f8cbc000ffffff01ecf3f500e0e4e700d9dcde00
+d2d4d600cbcccd00c4c5c500bbbcbd00b4b4b401b8938b00dc3e1400d9431903dc3e1400
+e4461800fc6c3300fc653101fb6c4100fc653100f9653d00fc6c3300fb6c4101fc6c3300
+fb6c4100fc6c3300fb6c4100fc6c3300fb6c4101fc6c3300fb6c4100fb744e00f4f6f900
+ffffff02ecf3f500e8ecef00e0e4e700d9dcde00cbcccd01bbbcbd02b4b4b400b98a7c00
+d9542d00d9431907fb5c2e00fc6c3303fb6c4100fc6c3300fb6c4100f9653d00fb6c4100
+fc6c3300fb6c4100fc6c3300f9653d00fc6c3300f9653d00fc6c3300fb6c4102fc6c3300
+fb6c4100f9653d00fc6c3300fb6c4100fc653101fb6c4100d98c7800a4a5a403b66c5900
+d9431900c9452200d9431907fb552700fc6c3300fb6c4104fc6c3300fb6c4103fc6c3300
+fb6c4102fc6c3300f9653d00fc6c3300fb6c4101fc6c3300fb6c4100fb744e00a4a5a401
+9c9e9c01a89a95009c9e9c02ba654f00d9431900c9452200d9431904d94b2000d9431903
+fb552700fb6c4100fc6c3300fb6c4102f9653d00fb6c4100fc6c3300fb6c4102f9653d00
+fc6c3300fb6c4103fc6c3300fb6c4100fc653101fa7c5800ffffff14f5886c00fb552700
+fb5c2e14d94b2000c9452202d94b2000c9452207dba39300e8ecef00f4f6f901ffffff07
+f4f6f900ecf3f500e8ecef01e0e4e700e6dcdc00d9dcde00d2d4d601d8cccb00fb6c4100
+fb5c2e05fc653100fb5c2e03fc653100fb5c2e01fc653100fb5c2e00fc653100fb5c2e03
+fc653100fb5c2e01fb552700d9431901c9452200d9431900c9452200d9431901c9452200
+d9431900c9452200e6ad9b00ffffff06ecf3f500e8bcb000fb5c2e03fc653100fb5c2e00
+fc653101fb5c2e00fc653106fb5c2e00fc653101fb5c2e00fc653100fb552700d9431901
+c9452200d9431902c9452200d9431900e8bcb000ffffff0ef4f6f900e8ecef01e0e4e700
+d9dcde02d2d4d601d8cccb00cbcccd00f5886c00fc653104f9653d00fc653100f9653d01
+fb6c4100f9653d00fb6c4102f9653d00fb6c4105fb5c2e00c74b2a00d94b2000c74b2a00
+d94b2000c74b2a00ea7c5e00ffffff08ecf3f500e8ecef00e0e4e700d9dcde01d2d4d601
+cbcccd00d2d4d600cbcccd01f9947500fc653102f9653d00fc653100fb6c4100f9653d01
+fb6c410af9653d00fc6c3300fb6c4100f9653d00fb6c410cfb744e00fb6c4105f9653d01
+e54d1d00d94b2000f8d4c900ffffff09ecf3f500e8ecef00d9dcde01cbcccd02c4c5c500
+cbcccd01c4c5c500cbcccd00e6ad9b00fb744e00fc733900fb744e0efc733900fb744e00
+fb6c4100fc733900fb744e00f9947500ffffff0bf4f6f900e8ecef00d9dcde00d2d4d601
+cbcccd00c4c5c502c8745e00fb5c2e00fb6c4102fc733900fb6c4100fb744e00fc733900
+fb744e00fc733900fb744e00fc733900fb744e00fc733900fb744e00fc733900fb744e00
+fc733900fb744e00fc733900fb744e00fb8d5500ffffff05f4f6f900e8ecef00e0e4e700
+d2d4d600cbcccd00c4c5c501bbbcbd01b8adaa00d94b2000c9452200e5541f00fb6c4102
+fc733900fb6c4100fc733900fb6c410ef9dcd100ffffff03f4f6f900ecf3f500e8ecef00
+e0e4e700d9dcde00d2d4d601c4c5c502bbbcbd03b4b4b400bbbcbd00b4b4b400bbbcbd00
+c86d5400c9452201c74b2a00c9452200fb6c4100fc733905fb6c4100fc733901fb6c4103
+fc6c3300fb6c4105fca46d00ffffff00f4f6f900ecf3f500e0e4e700d9dcde00cbcccd00
+c4c5c500bbbcbd00b4b4b402b77c6a00d9431905fb552700fc6c3300fb6c4100fc6c3300
+fc653100fb6c4103fc6c3300fb6c4105fc733900fb6c4101fac4ac00ffffff03f4f6f900
+e8ecef00e0e4e700d2d4d601c4c5c501bbbcbd00abacad00c8745e00c74b2a00d9431900
+c9452201d94b2000c9452200d94b2000c9452200e5541f00fc6c3300fb6c4105fc733900
+fb6c4100fc733900fb6c410cfc6c3300fb6c4100fc6c3300f9653d00f8836200c8a49d00
+a4a5a404c8745e00c9452209e54d1d00fb6c410cfc6c3300f9653d00fb6c4101fc653100
+f9653d00fb6c4100f9653d00fb6c4100e78b7100abacad00a4a5a4019c9e9c04a7847c00
+c9452200d9431900c9452207d9431900c9452200d9431900fb6c4107f9653d00fb6c410b
+fc733900ffffff13f9e4e100fb5c2e00e75c2a00fb552700e75c2a00fb552700e75c2a00
+fb552700e75c2a04e5541f00e9644000e75c2a03e9644000e75c2a00e9644000e75c2a00
+d9542d00c9452200c74b2a00c9452200c74b2a01c9452200c74b2a01c9452200c74b2a01
+c9452200c86d5400e8ecef00f4f6f901ffffff0af4f6f900e8ecef01e0e4e700e6dcdc00
+d9dcde00d2d4d601d8ac9f00fb5c2e00f9653d00e9644000fb5c2e00f9653d00fb5c2e02
+f9653d00fb5c2e00f9653d00fb5c2e00f9653d00fb5c2e00fc653100fb5c2e00f9653d00
+fb5c2e00fc653101fb5c2e01fc653100fb5c2e00e75c2a00c9452203d94b2000c9452203
+d9431900e8b3a800ffffff05f4f6f900e8ecef00f9947500f9653d04fc653100f9653d0c
+fc653100f9653d00e5541f00c9452201d94b2000c9452203da6d5000ffffff10f4f6f900
+ecf3f500e8ecef01e6dcdc00d9dcde00d2d4d601cbcccd00d2d4d600d7c4bd00fb6c4100
+f9653d02fb6c4100f9653d00fb6c410fd94b2000c74b2a02c9452200c9593b00ffffff09
+ecf3f500e8ecef00e6dcdc00d9dcde01d2d4d601cbcccd01d2d4d600d7c4bd00f5886c00
+fb6c4119fc733900fb744e09fc733900fb744e00fb6c4103e5541f00c9452200e8a58f00
+ffffff0af4f6f900e8ecef00e0e4e700d9dcde00d2d4d601cbcccd01c4c5c500cbcccd00
+c4c5c500d8cccb00c4c5c500f8836200fb744e03fa7c5800fb744e00fa7c5806fb744e00
+fa7c5800fb744e05fb6c4100f4f6f900ffffff09f4f6f900ecf3f500e0e4e700d9dcde00
+d2d4d600cbcccd00c4c5c502c7b5b100d9542d00fb6c4101fc733900fb6c4100fb744e00
+fc733900fb744e00fb6c4100fb744e08fa7c5800fb744e00fa7c5800fb744e00f9dcd100
+ffffff04f4f6f900ecf3f500e0e4e700d9dcde00d2d4d600cbcccd00c4c5c500c6bcba00
+c4c5c500bbbcbd00c7998d00c74b2a01fb5c2e00fb744e05fc733900fb744e00fc733903
+fb744e00fc733903fb6c4100fc733901f9947500ffffff06ecf3f500e8ecef00e0e4e700
+d9dcde00d2d4d601c4c5c501bbbcbd02b4b4b400bbbcbd00b4b4b400bbbcbd00b4b4b400
+b99a9400c9452200d94b2000c9452200d94b2000e75c2a00fb6c4100fb744e02fb6c4100
+fb744e00fc733900fb744e00fb6c4100fb744e00fc733902fb6c4104fc733900fb6c4100
+fa7c5800ffffff00ecf3f500e8ecef00d9dcde00d2d4d600cbcccd00c4c5c500bbbcbd01
+b4b4b400b8adaa00c9593b00c9452201d9431900c9452202f9653d00fb6c4102fb744e00
+fc733902fb6c4100fb744e00fc733900fb744e00fc733901fb744e00fc733900fb744e00
+fc733900f8836200ffffff03f4f6f900ecf3f500e8ecef00e0e4e700d9dcde00d2d4d600
+c4c5c501b7a4a000c9593b00c74b2a04c9452200c74b2a01f9653d00fb744e0cfc733900
+fb744e00fc733900fb744e00fc733901fb6c4100fc733900fb6c4104fb744e00e8a58f00
+bbbcbd00abacad00a4a5a404b7746200c9452209e5541f00fc733900fb6c4100fc733900
+fb6c4100fc733900fb6c4110c8a49d00b8adaa00a4a5a4019c9e9c00a89a95009c9e9c02
+a89a9500c945220cfb5c2e00f9653d00fb6c4106fc733900fb6c4100fb744e00fb6c4101
+fb744e00fc733900fb6c4105f4f6f900ffffff12f7b9a600e75c2a07fb5c2e00e75c2a00
+e9644000e75c2a00e9644000e75c2a01e9644000e75c2a00e9644000e75c2a01e9644000
+e75c2a00c74b2a00b9462700c9452200c74b2a01b9462700c9452200b9462700c9452200
+c74b2a00b9462700c9452200c74b2a00d8bcb600f4f6f900ffffff0df4f6f900ecf3f500
+e8ecef01d9dcde01d2d4d601eb826400e75c2a00f9653d00e9644000e75c2a00e9644001
+fb5c2e00e9644001fb5c2e00e9644000fb5c2e00e9644000f9653d00e9644000f9653d01
+fb5c2e00e9644000f9653d01fb5c2e00f9653d00e5541f00c9452203c74b2a00c9452203
+c74b2a00e6ad9b00ffffff05f4f6f900e6dcdc00f9653d06fb6c4101f9653d00fb6c4104
+f9653d00fb6c4100f9653d03fb5c2e00c9452207fac4ac00ffffff11f4f6f900f7ece700
+e8ecef00e0e4e700d9dcde02d2d4d600cbcccd01e59c8700f9653d00fb6c4102f9653d03
+fb6c4100f9653d00fb6c4102fb744e00fb6c4106e75c2a00c9452200c74b2a02c9452200
+f7b9a600ffffff08f4f6f901e8ecef00e6dcdc00d9dcde00d2d4d602cbcccd02d7c4bd00
+fa7c5800fb6c4108fb744e00fb6c4100fb744e00fc733900fb744e1be9644000c74b2a00
+d8846e00ffffff0cecf3f500e8ecef00d9dcde01d8cccb00cbcccd01c4c5c500cbcccd00
+c4c5c500cbcccd00c4c5c500e8a58f00fb744e01fa7c5800fb744e01fa7c5801fb744e00
+fa7c5800fb744e01fa7c5800fb744e00fa7c5800fb744e00fa7c5804fb744e00fa7c5800
+f9a58b00ffffff09f4f6f900e8ecef00e0e4e700d2d4d601cbcccd00c4c5c502c8847200
+fb5c2e00fb744e0cfa7c5800fb744e00fa7c5800fb744e00fa7c5801fb744e00f5886c00
+ffffff05f4f6f900e8ecef00e0e4e700d2d4d600cbcccd01c4c5c500bbbcbd01c4c5c500
+c97c6700c74b2a01fb6c4100fa7c5800fb744e00fa7c5800fb744e07fb6c4100fb744e02
+fb6c4100fb744e03f9dcd100ffffff07ecf3f500e8ecef00e0e4e700d9dcde00d2d4d601
+c4c5c500bbbcbd00c4c5c500b4b4b400bbbcbd00b4b4b400bbbcbd00b4b4b400bbbcbd01
+c7634a00c9452200c74b2a00c9452200c74b2a00fb6c4100fb744e01fc733900fb744e00
+fb6c4100fb744e00fb6c4100fb744e00fc733900fb744e02fc733900fb744e00fc733901
+fb6c4100fb744e01fc733900f9e4e100e8ecef00e0e4e700d9dcde00cbcccd00c4c5c500
+bbbcbd00b4b4b402b8938b00c9452205d94b2000fb6c4100fc733900fb744e01fc733900
+fb744e00fb6c4100fb744e0afac4ac00ffffff03f4f6f900ecf3f500e0e4e700d9dcde00
+d2d4d600cbcccd00c4c5c500b77c6a00c74b2a07d95d3b00fc733900fa7c5800fb744e00
+fa7c5800fb7c3800fa7c5800fb744e00fb7c3800fb744e00fa7c5800fb744e0cfc733900
+fb744e00fc733900fb744e00f9947500d7c4bd00c4c5c500b4b4b401a4a5a404b66c5900
+c9452209e5541f00fb744e00fb6c4101fb744e01fc733900fb744e00fc733900fb744e00
+fc733900fb744e00fb6c4100fc733900fb6c4104fc733900fb6c4100fb744e00f8836200
+bbbcbd00b4b4b400abacad00a4a5a4019c9e9c04ba5d4500c945220be5541f00fb6c4103
+fc733900fb6c4100fb744e00fb6c4100fb744e00fb6c4100fb744e02fb6c4100fb744e04
+fb6c4101f9e4e100ffffff11f4f6f900ea7c5e00e75c2a00d95d3b00e75c2a02d9542d00
+e9644000e75c2a00d95d3b01e75c2a02d95d3b00e9644001d95d3b00e75c2a00e9644000
+d95d3b00e9644000c74b2a00b9462700c9452200b9462702c9452200b9462700c74b2a00
+b9462703c86d5400f4f6f900ffffff0ff4f6f900e8ecef01e0e4e701d9dcde00d2d4d600
+d8b4ac00e9644000e75c2a00fb5c2e00e9644000fb5c2e00e9644002fb5c2e00e9644000
+f9653d00e9644001fb5c2e00e9644000fb5c2e00e9644000f9653d00e9644000fb5c2e00
+e9644000f9653d00e9644000e75c2a00c74b2a02c9452200b9462700c9452200c74b2a02
+c9452200e8b3a800ffffff04f4f6f900e8ecef00e8b3a800f9653d04fb6c4100f9653d01
+fb6c4100f9653d00fb6c4100f9653d00fb6c4100f9653d00fb6c4100f9653d00fb6c4100
+f9653d03d94b2000c9452200c74b2a00c9452200c74b2a02c9452200c86d5400ffffff13
+f4f6f900ecf3f500e8ecef00e0e4e700e6dcdc00d2d4d602d8cccb00d7c4bd00fb6c4100
+f9653d00fb6c4100f9653d00fb6c4109fb744e00fb6c4100fb744e00fb6c4101fb744e00
+f9653d00e9644000c74b2a01c9452200c74b2a01d77c6200ffffff09f4f6f900e8ecef01
+e6dcdc00d9dcde00d2d4d601cbcccd00d2d4d600cbcccd00d8cccb00d8b4ac00fb744e02
+fb6c4100fb744e00fb6c4101fb744e00fb6c4100fb744e01fb6c4100fb744e00fb6c4100
+fb744e12fa7c5800fb744e05fb6c4100c74b2a00c7634a00ffffff0df4f6f900ecf3f500
+e6dcdc00d9dcde00d2d4d600cbcccd04c4c5c500cbcccd00d7c4bd00f8836200fa7c5800
+fb744e00fa7c5800fb744e00fa7c5800fb744e00fa7c5800fb744e00fa7c580bfb744e01
+ffffff08f4f6f900e8ecef01d9dcde00d2d4d600d8cccb00cbcccd00c4c5c501c6bcba00
+c9593b00fb744e09fa7c5800fb744e00fa7c5800fb744e02fa7c5800fb744e00fa7c5800
+fb744e00fa7c5800fad4b000ffffff05ecf3f500e8ecef00d9dcde00d2d4d600cbcccd00
+c4c5c502bbbcbd00c6bcba00b66c5900b7533a00c74b2a00fb744e00fa7c5801fb744e00
+fa7c5801fb744e00fa7c5800fb744e07fa7c5800fb744e02f8836200ffffff09ecf3f500
+e8ecef00e0e4e700d9dcde00d2d4d600cbcccd00c4c5c500bbbcbd00c6bcba00b4b4b400
+bbbcbd00b4b4b400bbbcbd00b4b4b401b9857800b84c3000c74b2a01c9452200e9644000
+fb744e04fc733900fb744e00fb6c4100fb744e00fb6c4100fb744e00fb6c4100fb744e00
+fb6c4100fb744e03fb6c4100fb744e00fac4ac00e8ecef00e0e4e700d2d4d600cbcccd00
+c4c5c500bbbcbd00b4b4b402b7746200b9462700c9452200b9462700c9452202e75c2a00
+fb744e0bfb6c4100fb744e03fa7c5800ffffff03f4f6f900ecf3f500e0e4e701d9dcde00
+cbcccd00c8aca500ba654f00b7533a00b84c3000b7533a00b84c3000b7533a01c74b2a00
+b7533a00e9644000fa7c5809fb744e00fa7c5807fb744e00fa7c5800fb744e04f5886c00
+e8bcb000d9dcde00cbcccd00c4c5c500bbbcbd00abacad00a4a5a404b7746200b9462701
+c9452200b9462701c9452200b9462700c9452200b9462700c9452200d9542d00fb744e03
+fb6c4100fb744e01fb6c4100fb744e01fb6c4100fb744e01fb6c4100fb744e06e9947d00
+bbbcbd00b4b4b400abacad00a4a5a4019c9e9c01a89a95009c9e9c01a9746500b9462706
+c9452200b9462701c9452200b9462700d9542d00fb6c4103fb744e00fb6c4100fb744e00
+fb6c4100fb744e02fb6c4100fb744e03fb6c4100fb744e00fb6c4100fb744e01f9dcd100
+ffffff11f9e4e100d9654700d95d3b04e75c2a00d95d3b00d9542d00e75c2a00d95d3b00
+d9542d00d95d3b01e75c2a00d95d3b01e9644000d95d3b03b946270cd8b4ac00f4f6f900
+ffffff10f4f6f900ecf3f500e8ecef00e0e4e700d9dcde01d2d4d600e8866c00e9644003
+e75c2a00e9644002e75c2a00e964400cd9542d00c74b2a00b9462700c9452200b9462700
+c74b2a00b9462704d8b4ac00ffffff04f4f6f900e8ecef00e78b7100f9653d00e9644001
+e86c4c00e9644000e86c4c00e9644000e86c4c02e9644000e86c4c04e9644000fb6c4100
+e9644000fb6c4100e9644000b84c3000c9452200b84c3000b9462700c74b2a00b9462701
+c74b2a00d8ac9f00ffffff14f4f6f900ecf3f500e8ecef00d9dcde02d2d4d600cbcccd01
+e9947d00fb6c4100f9653d00fb6c4101f9653d00fb6c4100f9653d00fb6c4101e86c4c00
+fb6c4101e86c4c00fb6c4101e86c4c00fb6c4100fb744e00fb6c4100e86c4c00fb6c4100
+c74b2a00b84c3000c74b2a00b84c3001c9593b00ffffff0aecf3f500e8ecef01d9dcde01
+d2d4d601cbcccd03e8a58f00fb744e07fb6c4100fb744e07fa7c5800fb744e00fa7c5803
+fb744e00fa7c5800fb744e00fa7c5801fb744e00fa7c5802fb744e00fa7c5800fb744e00
+fa7c5800fb744e00fa7c5800fb744e00b7533a00c9593b00f9e4e100ffffff0df4f6f900
+ecf3f500e8ecef00d9dcde00d2d4d601cbcccd01c4c5c502cbcccd00c4c5c500e8a58f00
+fb744e00fa7c5802fb744e00fa7c5809f8836200fa7c5805f7b9a600ffffff07f4f6f900
+e8ecef00e0e4e700d9dcde00d2d4d600cbcccd00c4c5c502c88b7d00e75c2a00fb744e00
+fa7c5800fb744e00fa7c5800fb744e00fa7c5804fb744e00fa7c5800fb744e00fa7c5801
+fb7c3800fb744e00fa7c5801fb744e00f8836200ffffff05f4f6f900ecf3f500e0e4e700
+d9dcde00d2d4d600c4c5c501bbbcbd01c4c5c500bbbcbd00c75c4d00b7533a00c9593b00
+f8836200fa7c5806fb744e00fa7c5803fb744e00fa7c5800fb744e00fa7c5803fcb58e00
+ffffff0aecf3f500e0e4e700d9dcde00d2d4d601c4c5c501bbbcbd01b4b4b400bbbcbd00
+b4b4b400bbbcbd00b4b4b400c8a49d00b9462700c74b2a00b84c3000c74b2a01fb744e13
+f9ad9400e0e4e700d9dcde00d2d4d600c4c5c500bbbcbd01b4b4b401abacad00ba5d4500
+c9452200b84c3000b9462700b84c3000b9462700b84c3000fb6c4100fb744e04fa7c5802
+fb744e01fa7c5800fb744e05f9ad9400ffffff02ecf3f501e0e4e701d2d4d600cbcccd00
+b78d8500b7533a00b84c3001c74b2a00b84c3001c74b2a00b84c3000c9593b00fb744e00
+fa7c5819f9ad9400e0e4e700e6dcdc00d9dcde00cbcccd00c4c5c500b4b4b400abacad00
+a4a5a404b7746200b9462709d9542d00fb744e0dfb6c4100fb744e00fb6c4100fb744e03
+d8ac9f00c4c5c500bbbcbd00b4b4b400abacad00a4a5a4009c9e9c04a7847c00b9462704
+c4363800b9462706fb6c4100fb744e02fb6c4100fb744e00fb6c4100fb744e0bfb6c4100
+fb744e00f8d4c900ffffff11e8b3a800d45e4400d95d3b00d45e4401d95d3b00e9644000
+cc545800d95d3b0dc74b2a00b9462704a6442b00b9462700a6442b00b9462700a6442b00
+b9462700a6442b00ba5d4500e8ecef00ffffff12f4f6f900f7ece700e0e4e701d9dcde00
+d2d4d600d8ac9f00e9644000d9654700e9644000d45e4400e9644003e86c4c00e964400c
+d95d3b00b84c3000b9462700b84c3001b9462700b84c3000b9462700b84c3002d8ac9f00
+f4f6f900ffffff02f4f6f900ecf3f500e6dcdc00e8745600e86c4c00e9644000e86c4c00
+e9644000fb6c4100e9644000e86c4c01e9644000e86c4c04e9644000e86c4c03e9644000
+d95d3b00b84c3002b9462700b84c3002b7533a00f7ece700ffffff15f7ece700e8ecef01
+e6dcdc00d9dcde00d2d4d601d8cccb00d8b4ac00e86c4c00fb6c4102e86c4c00f9653d00
+fb744e00fb6c4100e86c4c00fb6c4100e86c4c00fb744e00fb6c4100e86c4c00fb744e00
+e86c4c00fb744e00fb6c4100e86c4c00fb744e01d45e4400b84c3001c9593b00b84c3001
+f8cbc000ffffff0aecf3f500e8ecef00e6dcdc00d9dcde01d2d4d601cbcccd00d2d4d600
+d8cccb00cbcccd00e9947d00fb744e0dfa7c5801fb744e00fa7c5800fb744e00fa7c5800
+fb744e00fa7c5801fb744e00fa7c5801fb744e00fa7c5801fb744e00fa7c5800fb744e00
+fa7c5803fb744e00c75c4d00b84c3000e8b3a800ffffff0ff4f6f900e8ecef00e6dcdc00
+d9dcde00d2d4d600d8cccb00c4c5c500cbcccd02c4c5c500cbcccd00d8bcb600fa7c5811
+f8836200fa7c5802ea7c5e00ffffff07ecf3f500e8ecef00d9dcde00d2d4d600cbcccd01
+c4c5c502c7634a00fb744e00fa7c5800fb744e00fa7c5803fb744e00fa7c580cf8cbc000
+ffffff05f4f6f900e8ecef00e0e4e700d2d4d601c4c5c501c6bcba00c4c5c500bbbcbd00
+c7b5b100b7533a01d45e4400f8836200fa7c5809fb744e00fa7c5804fb744e00fa7c5801
+f9e4e100ffffff0af4f6f900ecf3f500e0e4e700d9dcde00d2d4d600cbcccd00c4c5c500
+bbbcbd02b4b4b400bbbcbd00b4b4b400bbbcbd01c75c4d00b84c3000c74b2a00b84c3000
+c74b2a00fb744e00fa7c5800fb744e00fa7c5801fb744e00fa7c5801fb744e00fa7c5806
+fb744e00fa7c5801fb744e00f9a58b00e0e4e700d9dcde00cbcccd00c4c5c500bbbcbd00
+b4b4b402b99a9400b84c3003b9462700b84c3000c74b2a00fb744e00fa7c5800fb744e00
+fa7c5802fb744e00fa7c5800fb744e00fa7c5801fb744e00fa7c5802fb744e00fa7c5800
+fb744e00f9dcd100ffffff00f4f6f900ecf3f500e0e4e701d9dcde00d2d4d600c7b5b100
+a8655400b84c3007da633600fa7c5805f8836200fa7c5800f8836200fa7c5800f8836200
+fa7c5800f8836200fa7c580cf9947500f9dcd100f4f6f900e8ecef00e0e4e700d2d4d600
+cbcccd00c4c5c500bbbcbd00abacad00a4a5a404a9746500b84c3003b9462700b84c3000
+b9462701b84c3000b9462700d45e4400fb744e14d7c4bd00c4c5c500bbbcbd00b4b4b400
+abacad00a4a5a4019c9e9c03a88c8600a6442b01c4363800a6442b00b9462700a6442b01
+c4363800a6442b00b9462700a6442b00b9462701e9644000e86c4c00fb6c4100e86c4c00
+fb744e00e86c4c00fb744e00e86c4c00fb744e00e86c4c00fb744e00e8745600e86c4c00
+fb744e00e8745600e86c4c01fb744e00e8745600e86c4c00fb744e00f9dcd100ffffff11
+d6938100d45e4406d95d3b00d45e4400d95d3b01d45e4400d95d3b00cc545800d95d3b00
+d45e4400cc545800d9542d00d45e4400cc545800d95d3b00b9462700a6442b04b9462700
+a6442b01b9462700a6442b02cc916400f4f6f900ffffff13ecf3f501e8ecef00d9dcde01
+d8cccb00d3725300d9654700e9644000d9654705da6d5000d9654700e86c4c00d9654700
+da6d5000e86c4c00d9654700e86c4c00d9654700e86c4c00d9654700e9644000d9654700
+d95d3b00b84c3009d8ac9f00ffffff00f4f6f903ecf3f500e5c4c200e86c4c03da6d5000
+e86c4c00da6d5000e86c4c00e9644000e86c4c08da6d5000e86c4c00da6d5000b84c3003
+a84d3500b84c3000b7533a00b84c3000c97c6700ffffff17ecf3f500e8ecef00d9dcde01
+d2d4d601cbcccd01ea7c5e00e86c4c06fb744e01e86c4c00fb744e00e8745600e86c4c00
+fb744e00e86c4c00fb744e00e8745600fb744e00e8745601d9654700b7533a01b84c3000
+b7533a01dba39300ffffff0af4f6f900ecf3f500e8ecef00e6dcdc00d9dcde00d2d4d602
+cbcccd02d8cccb00e78b7100fa7c5807fb744e00fa7c5800fb744e00fa7c5801fb744e00
+fa7c5811e8745600fa7c5800ea7c5e00d9654700b7533a00c88b7d00ffffff10f4f6f900
+ecf3f500e8ecef00d9dcde00d2d4d601cbcccd01c4c5c500d8cccb00c4c5c500cbcccd00
+c4c5c500e59c8700fa7c580af8836200fa7c5801f8836200fa7c5803f8836200fa7c5801
+f8cbc000ffffff05f4f6f900e8ecef00e0e4e700d9dcde00d2d4d600d8cccb00c4c5c502
+c7998d00c75c4d00fa7c580af8836200fa7c5801f8836200fa7c5800f8836200fa7c5800
+f8836200fa7c5800f8836200ffffff06ecf3f500e8ecef00d9dcde01cbcccd00c4c5c501
+bbbcbd02b8adaa00b7533a01da633600f8836203fa7c580df8836200fa7c5800ffffff0c
+ecf3f500e8ecef00e0e4e700d2d4d600cbcccd00c4c5c500bbbcbd01b4b4b400bbbcbd00
+b4b4b400bbbcbd00b4b4b401b7746200b84c3002b7533a00e86c4c00fa7c5812f9947500
+d9dcde00d2d4d600cbcccd00c4c5c500bbbcbd01b4b4b401a88c8600b84c3000a84d3500
+b84c3003c9593b00fa7c5809fb744e00fa7c5800fb744e00fa7c5800fb744e00fa7c5801
+f5886c00f4f6f901e8ecef00e0e4e701d2d4d600cbcccd00b78d8500a7543f00b84c3000
+a84d3500b84c3000a84d3500b84c3002b7533a00e8745600fa7c5805f8836200fa7c5800
+f8836201ea7c5e00f8836201fa7c5800f8836202fa7c5800f8836200fa7c5800f8836200
+fa7c5800f8836200fa7c5801f5886c00fac4ac00ffffff01f4f6f900e8ecef00e0e4e700
+d2d4d600cbcccd00c4c5c500b4b4b401a4a5a404a96d5f00a84d3500b84c3000a84d3500
+b9462700a84d3500b84c3001a84d3500b84c3001c9593b00fa7c5809fb744e00e8745600
+fa7c5800e8745600fa7c5800e8745604e8866c00d2d4d600cbcccd00c4c5c500b4b4b400
+abacad00a4a5a4009c9e9c0499939300a84d3500a6442b08b9462700a6442b01d95d3b00
+fb744e00e86c4c02fb744e00e86c4c02e8745600e86c4c00e8745609f9dcd100ffffff10
+f4f6f900d3725300c75c4d02d45e4400c75c4d00c9593b01d45e4400c9593b00c75c4d00
+c9593b00cc545800d45e4400c9593b00d45e4400c9593b00d95d3b00c9593b00d95d3b00
+c75c4d00c74b2a00a6442b0cd2d4d600ffffff14f4f6f901e8ecef00e0e4e700d9dcde00
+d2d4d600d6938100d9654704da6d5005e86c4c00d9654700da6d5003e86c4c00da6d5001
+e86c4c00c7634a00b84c3001a84d3500b7533a00a84d3500b7533a01a84d3500b7533a00
+a7543f00d8ac9f00ecf3f500f4f6f902ecf3f500e8ecef00e8a58f00da6d500bd9654700
+da6d5004e86c4c00da6d5000d9654700b84c3000a7543f00a84d3501b7533a00a84d3502
+d8bcb600ffffff17f4f6f900e8ecef01d9dcde01d2d4d601cbcccd00dba39300e8745606
+e86c4c00e8745601e86c4c00e8745608e86c4c00a7543f00b7533a01a7543f00b7533a00
+b66c5900ffffff0bf4f6f900ecf3f500e8ecef00d9dcde00e6dcdc00d2d4d602cbcccd02
+d8bcb600ea7c5e00fa7c5800e8745600fa7c5800e8745600fa7c5800e8745600fb744e00
+fa7c5809ea7c5e00fa7c5801ea7c5e00fa7c5801ea7c5e00fa7c5800ea7c5e01fa7c5800
+ea7c5e01fa7c5800eb826400f8836200dc725400b7533a00b7746200ffffff12f4f6f900
+e8ecef00e0e4e700d9dcde00cbcccd00d8cccb00cbcccd01c4c5c500cbcccd00c4c5c500
+cbcccd00c6bcba00f8836201fa7c5800f8836202fa7c5800f8836206fa7c5800f8836205
+fa7c5800e8866c00ffffff05ecf3f500e8ecef00d9dcde00d2d4d601c4c5c503b7746200
+e8745600f8836213fac4ac00ffffff06e8ecef01d9dcde00d2d4d600cbcccd00c6bcba00
+c4c5c500bbbcbd00c4c5c500bbbcbd00c7b5b100b7533a01da6d5000f8836202fa7c5800
+f8836204fa7c5800f8836201fa7c5800f8836205f5886c00ffffff0cf4f6f900ecf3f500
+e0e4e700d9dcde00d2d4d600c4c5c501c6bcba00bbbcbd00b4b4b400bbbcbd00b4b4b400
+bbbcbd00b4b4b400b77c6a00b84c3000b7533a01b84c3000d9654700fa7c5807f8836200
+fa7c5800f8836207fa7c5800f5886c00d9dcde00d2d4d600c4c5c500bbbcbd00b4b4b403
+b7746200a84d3500b84c3000a84d3500b84c3000a84d3501d9654700f8836200fa7c5803
+ea7c5e00fa7c5802f8836200fa7c5806f9a58b00ecf3f500e8ecef00e0e4e700d9dcde00
+d2d4d600c7b5b100b66c5900a84d3501b84c3000a6442b00a84d3500b84c3000a84d3500
+b84c3000c7634a00fa7c5800ea7c5e00fa7c5800ea7c5e01fa7c5800ea7c5e05fa7c5800
+eb826400ea7c5e00eb826400ea7c5e00f8836200ea7c5e01f8836200ea7c5e00f8836200
+eb826401f8836200f9a58b00f4f6f900ffffff02f4f6f900e8ecef00e0e4e700d9dcde00
+d2d4d600bbbcbd01abacad00a4a5a404a9746500b84c3000a84d3502b84c3000a84d3501
+b84c3000a84d3501c75c4d00e8745601ea7c5e00e8745601fa7c5800e8745603ea7c5e00
+fa7c5800e8745600ea7c5e01e8745600ea7c5e00e8745600ea7c5e00e8745600d69a9000
+d9dcde00d2d4d600c4c5c500bbbcbd00b4b4b400a4a5a4019c9e9c00a89a95009c9e9c02
+a84d3500a6442b0bc75c4d00e86c4c01e8745600e86c4c01e8745600e86c4c00e8745600
+e86c4c00e8745600e86c4c00e8745600e86c4c00e8745604e86c4c00e8745600f9dcd100
+ffffff10e9d5d700c9593b03c75c4d00c9593b00c75c4d01c9593b00c75c4d00c9593b00
+c75c4d00c9593b05c75c4d00c9593b01b84c3000a6442b0bba654f00f4f6f900ffffff15
+f4f6f900ecf3f500e8ecef00e6dcdc00d9dcde00d8bcb600d9654700da6d500ad3725300
+da6d5003d3725300da6d5001d3725300c86d5400b7533a00a7543f00b7533a00a7543f00
+b7533a00a7543f01b7533a00a7543f00b7533a00d8b4ac00ecf3f500f4f6f900ecf3f502
+e8ecef00d98c7800da6d5009dc725400da6d5008ba5d4500a84d3501b84c3000a84d3504
+f9e4e100ffffff17f4f6f901e8ecef00e6dcdc00d9dcde00d2d4d601cbcccd00d8bcb600
+dc725400d8755c00e8745600d8755c00e8745601d8755c00e8745600dc725400e8745609
+d77c6200e8745600b7533a00a7543f01b7533a00a7543f01ffffff0cf4f6f900e8ecef01
+d9dcde01d2d4d602d8cccb00cbcccd01d8ac9f00eb826400ea7c5e00fa7c5800ea7c5e00
+fa7c5800ea7c5e10eb826402f8836200ea7c5e00eb826400f8836200eb826401ea7c5e00
+e8745600ba5d4501f9e4e100ffffff12f4f6f900ecf3f500e0e4e700d9dcde01cbcccd02
+c4c5c500cbcccd00c4c5c500cbcccd00c4c5c500e59c8700f8836200e8866c00f8836201
+eb826400f5886c00eb826400f8836200eb826400f8836208fa7c5800eb826400f8836200
+ea7c5e00f8cbc000ffffff03f4f6f900e8ecef00e0e4e700d9dcde00d2d4d600cbcccd01
+c4c5c501c8a49d00c7634a00f8836201f5886c00f8836201f5886c00f8836202f5886c00
+f8836209f5886c00ffffff06f4f6f900ecf3f500e0e4e700d9dcde00d2d4d600c4c5c500
+bbbcbd01c4c5c500bbbcbd00c4c5c500b8adaa00b7533a01c86d5400fa7c5800f8836203
+fa7c5800f8836201fa7c5800f8836209f5886c00ffffff0decf3f500e8ecef00d9dcde00
+d2d4d600cbcccd00c4c5c500bbbcbd00b4b4b400bbbcbd00b4b4b400bbbcbd00b4b4b400
+bbbcbd00a77c7000a84d3500a7543f00a84d3500b7533a00c7634a00f8836208eb826400
+f5886c00f8836200eb826400f8836200eb826400f8836200eb826400f8836200eb826401
+d2d4d600cbcccd00c4c5c500bbbcbd00b4b4b402abacad00a8655400a84d3504b84c3000
+e8745600ea7c5e01f8836200ea7c5e01f8836200ea7c5e00eb826400fa7c5800ea7c5e00
+fa7c5806e8bcb000e0e4e701d9dcde00d2d4d600b8938b00a7543f00a84d3506b7533a00
+da6d5000fa7c5800ea7c5e00fa7c5800ea7c5e01f8836200ea7c5e00eb826400ea7c5e00
+f8836200eb826406ea7c5e00eb826406f5886c00f8d4c900ffffff04ecf3f500e8ecef00
+e0e4e700d2d4d600cbcccd00c4c5c500b4b4b401a4a5a404a9746500a84d3508b84c3000
+c9593b00ea7c5e00f8836200ea7c5e04fa7c5800ea7c5e00e8745602ea7c5e00e8745602
+ea7c5e00e8745602e8a58f00d9dcde00d2d4d600c4c5c500bbbcbd00b4b4b400abacad00
+a4a5a4009c9e9c04a65b4500a6442b0bb84c3000e86c4c00da6d5000e86c4c00e8745600
+da6d5000e86c4c00e8745600e86c4c00dc725400e8745600dc725400e8745600dc725402
+da6d5000dc725401da6d5000e8745600e9d5d700ffffff10d8bcb600ba5d4500c75c4d00
+c9593b00ba5d4500c9593b00c7634a00ba5d4500c9593b01c7634a00c9593b02c75c4d00
+c9593b00c75c4d00c9593b00c75c4d00c9593b01ba5d4500a6442b0cc8938400f4f6f900
+ffffff16f4f6f900e8ecef00e0e4e700d9dcde00d2d4d600c97c6700d9654700d3725300
+c7634a00da6d5000c86d5400da6d5000c86d5400da6d5000c86d5400d3725300c86d5400
+da6d5000d3725300da6d5000d3725300da6d5000d3725300dc725400d8755c00dc725400
+c86d5400a7543f00a65b4500b7533a00a7543f01a65b4500b7533a00a7543f00a65b4501
+c8aca500ecf3f502f4f6f900e8ecef00e0e4e700d8755c00dc725400d3725300dc725400
+d3725300dc725401d3725300dc725400d3725301d8755c00d3725300d8755c02da6d5000
+d8755c00dc725400d3725300dc725400ba5d4500a84d3500a7543f01a84d3501a7543f00
+a84d3500b66c5900ffffff19f4f6f900e8ecef01e6dcdc00d2d4d601d8cccb00cbcccd00
+d8846e00d8755c00d77c6200d8755c03e8745600d8755c01e8745600d8755c00e8745600
+d8755c00e8745600d8755c00ea7c5e00d8755c00d77c6200ea7c5e00d77c6200ba5d4500
+a7543f04f9e4e100ffffff0cf4f6f900e8ecef00e0e4e700e6dcdc00d9dcde00d2d4d600
+cbcccd00d2d4d600cbcccd02e59c8700ea7c5e06fa7c5800ea7c5e02fa7c5800ea7c5e04
+f8836200eb826400f8836200eb826402ea7c5e00eb826406c7634a00a65b4500e8bcb000
+ffffff14f4f6f900e8ecef00e6dcdc00d9dcde00d2d4d600cbcccd02c4c5c500cbcccd00
+c4c5c500cbcccd00d8b4ac00e8866c00f8836200e8866c03f5886c00e8866c03eb82640a
+d98c7800ffffff03f4f6f900e8ecef00e6dcdc00d2d4d600d8cccb00cbcccd00c4c5c502
+b77c6a00d8755c00eb826400f5886c01f8836200e8866c00f8836200f5886c00f8836200
+f5886c00f8836200f5886c01f8836200f5886c06f7b9a600ffffff06f4f6f900e8ecef00
+e0e4e700d9dcde00cbcccd00c4c5c502bbbcbd00c4c5c500bbbcbd00c6bcba00a8655400
+b7533a00c86d5400f5886c00f8836200f5886c00f8836201f5886c00f8836202f5886c00
+f8836200f5886c00f8836200f5886c00f8836200f5886c03f9947500ffffff0df4f6f900
+e8ecef00e0e4e700d9dcde00cbcccd00c4c5c500bbbcbd01b4b4b400bbbcbd00b4b4b400
+bbbcbd00b4b4b400b7746200a7543f03c7634a00eb826408f8836200eb826407ea7c5e00
+f5886c00d2d4d600cbcccd00c4c5c500bbbcbd00b4b4b402b8adaa00a7543f00a84d3501
+a7543f00a84d3501a7543f00ea7c5e00eb826406f8836200eb826400f8836200eb826403
+ea7c5e01eb826400e6ccc900d9dcde00d2d4d600c7b5b100a96d5f00a84d3507c7634a00
+ea7c5e04eb826401ea7c5e00eb826403ea7c5e00eb826402e8866c00eb826400e8866c00
+eb826406f9a58b00ffffff06f4f6f900e8ecef00e0e4e700d2d4d600cbcccd00c4c5c500
+bbbcbd00abacad00a4a5a404a9746500a84d3509c7634a00ea7c5e05e8745602ea7c5e00
+e8745603d8755c00e8745600d8755c03d8b4ac00d9dcde00d2d4d600cbcccd00c4c5c500
+b4b4b400abacad00a4a5a4009c9e9c0498594900a6442b0bb7533a00da6d5000e8745600
+dc725400da6d5000e86c4c00dc725400da6d5000dc725403da6d5000dc725406da6d5000
+f9dcd100ffffff0ff4f6f900d69a9000c7634a00ba5d4501c9593b00ba5d4501c9593b00
+ba5d4501c9593b00ba5d4500c7634a00c9593b00ba654f00c7634a00c9593b00c7634a03
+b7533a00a6442b05994f3c00a6442b02994f3c00a6442b00994f3c00d8bcb600ffffff17
+f4f6f900ecf3f500e8ecef00d9dcde01d6938100c86d5401d3725300c86d5400da6d5000
+c86d5401d3725300da6d5000c56e5e00d3725303d8755c01c8745e00d8755c02c56e5e00
+a7543f00a65b4500a7543f00a65b4501a7543f00a65b4501a7543f01c8aca500f7ece700
+ecf3f500e8ecef02e9d5d700d8755c13d3725300a7543f07c8938400ffffff19f4f6f900
+ecf3f500e8ecef00d9dcde01d2d4d600cbcccd01d69a9000d8755c02ea7c5e00d8755c03
+e8745600d8755c01e8745600d8755c01ea7c5e00d8755c00d77c6200e8745600d77c6200
+d8755c00c7634a00a7543f04e8bcb000ffffff0cf4f6f900ecf3f500e8ecef00e6dcdc00
+d9dcde01d2d4d601cbcccd00d8cccb00cbcccd01e9947d00ea7c5e00eb826400ea7c5e00
+eb826404ea7c5e00eb826406e8866c00ea7c5e00e8866c06eb826403cc626500a65b4500
+c8938400ffffff15f4f6f900ecf3f500e0e4e700d9dcde00d2d4d600d8cccb00cbcccd00
+c4c5c500cbcccd00c4c5c501cbcccd00c4c5c500e59c8700e8866c02e78b7100e8866c00
+e78b7102e8866c01e78b7100e8866c00f5886c00e8866c00eb826400e8866c00eb826400
+e8866c00eb826401f5886c00ea7c5e00e9d5d700ffffff01f4f6f900ecf3f500e0e4e700
+d9dcde00d2d4d600cbcccd01c4c5c501c7b5b100ba654f00e8866c00f5886c00eb826400
+e8866c01e78b7100e8866c00e78b7100e8866c00e78b7100e8866c01e78b7100e8866c00
+e78b7100e8866c03e78b7101ffffff07f4f6f900e8ecef00e0e4e700d9dcde00d8cccb00
+c4c5c500bbbcbd00c6bcba00bbbcbd01c4c5c500bbbcbd00b66c5900a65b4500c7634a00
+f5886c03e8866c00f5886c05e8866c00f5886c00e8866c00f5886c00e78b7100f5886c01
+e78b7100f5886c00ffffff0ee8ecef00e0e4e700d9dcde00d2d4d600c4c5c500bbbcbd01
+b4b4b400bbbcbd00b4b4b400bbbcbd00b4b4b400a65b4500a7543f03d3725300e8866c00
+eb826400e8866c00f5886c00eb826401e8866c00eb826400e8866c01eb826401e8866c00
+eb826400e8866c00eb826403e8866c00cbcccd00c4c5c500bbbcbd00b4b4b402abacad00
+a89a9500a7543f05ba5d4500eb826400ea7c5e00eb826400e8866c00eb826401e8866c00
+eb826400e8866c00eb826408d8cccb00d2d4d600b99a9400a65b4500a84d3500994f3c00
+a84d3500a7543f00a84d3502b7533a00d3725300ea7c5e00eb826401f8836200eb826405
+e8866c00eb826400e8866c08eb826400e8866c00eb826400e8866c00e78b7100f9dcd100
+ffffff07f4f6f900e8ecef00e0e4e700d9dcde00cbcccd00c4c5c500b4b4b400abacad00
+a4a5a404a9746500994f3c00a84d3500994f3c00a84d3506ba654f00ea7c5e01e8745601
+ea7c5e00e8745600d77c6200ea7c5e00d77c6200e8745600d77c6200e8745600d8755c01
+e8745600d8755c04e5c4c200e0e4e700d2d4d600cbcccd00c4c5c500b4b4b401a4a5a400
+9c9e9c01a89a95009c9e9c0198594900994f3c00a6442b01994f3c00a6442b017c3a3c00
+a6442b04ba5d4500dc725400d8755c00e8745600dc725400d8755c00dc725404d8755c00
+dc725400d8755c00d3725300dc725402d8755c00dc725400d8755c00e9d5d700ffffff10
+c8847200ba5d4503ba654f00c9593b00ba5d4500ba654f00c9593b00ba654f00c7634a00
+ba654f00ba5d4500c7634a00ba654f00c7634a00ba654f00c7634a00ba654f00c7634a00
+a7543f00a84d3500994f3c04a6442b00994f3c02a6442b00994f3c00a7543f00e0e4e700
+ffffff17f4f6f901e8ecef00e0e4e700d9dcde00c8aca500c56e5e00c86d5400c56e5e01
+c8745e00c56e5e00c8745e00c56e5e00c8745e03c56e5e00c8745e00c56e5e00c8745e04
+c86d5400a7543f00a65b4500a7543f00a65b4500a7543f00a65b4500a7543f0098594900
+a7543f00a65b4500c8aca500e8ecef01ecf3f500e8ecef01d8bcb600c8745e02d8755c00
+c8745e00d77c6200c97c6700d8755c00d77c6200c8745e00d77c6200d8755c00d77c6200
+c97c6701d77c6200c97c6700d77c6200c8745e00d77c6200c56e5e00a7543f04a65b4500
+a7543f00a65b4500d8ac9f00ffffff1af4f6f900e8ecef01d9dcde00d2d4d601cbcccd00
+d8ac9f00d8755c00d77c6200d8755c00d77c6200d8755c00d77c6200d8755c02d77c6200
+d8755c00d77c6201d8755c00d77c6201d8755c00d77c6202c56e5e00a7543f03994f3c00
+d8ac9f00ffffff0df4f6f900ecf3f500e8ecef00e6dcdc00d9dcde00d2d4d603cbcccd01
+c6bcba00e78b7100d8846e00e8866c00eb826400d8846e00ea7c5e00d8846e00eb826400
+e8866c00d77c6200e8866c00d77c6200eb826400d8846e00ea7c5e00e8866c00d77c6200
+e8866c00d8846e00eb826400d8846e00e8866c00d8846e00e8866c01d8846e00e8866c01
+c8745e00a65b4500b77c6a00ffffff17ecf3f500e8ecef00e6dcdc00d2d4d601cbcccd03
+c4c5c500cbcccd00c4c5c500c7b5b100e78b7100e8866c00e78b7101e8866c00e78b7101
+e8866c00e78b7101e8866c00e78b7100e8866c06eb826400e8866c01d69a9000ffffff01
+f4f6f900e8ecef00e0e4e700d2d4d601cbcccd00c4c5c502a7847c00d3725300e8866c01
+e78b7102e8866c00e78b7100e8866c00e78b710bf9ad9400ffffff07f4f6f900e8ecef00
+e0e4e700d2d4d601c4c5c500bbbcbd00c4c5c500bbbcbd00c4c5c500bbbcbd00c4c5c500
+a77c7000a7543f00ba5d4500e78b7100e8866c01e78b7100f5886c00e78b7102e8866c00
+e78b7100e8866c00e78b7102f5886c00e8866c00e78b7102f5886c00f4f6f900ffffff0c
+f4f6f900ecf3f500e0e4e700d9dcde00d2d4d600c4c5c500c6bcba00bbbcbd01b4b4b400
+bbbcbd00b4b4b400b99a9400a65b4500994f3c00a65b4500a7543f01d77c6200e8866c12
+e9947d00d2d4d600cbcccd00bbbcbd00b4b4b403a894900098594900a7543f0098594900
+a7543f02ba654f00e8866c0ad77c6200e8866c04e78b7100c6bcba00a96d5f00a7543f00
+994f3c00a7543f02994f3c00a7543f01ba654f00ea7c5e00e8866c00eb826400e8866c00
+eb826400e8866c00eb826400f5886c00e8866c11f7b9a600ffffff09ecf3f500e8ecef00
+e0e4e700d2d4d600cbcccd00c4c5c500bbbcbd00b4b4b400a4a5a404a77c7000994f3c00
+a84d3500994f3c00a84d3500994f3c01a84d3500994f3c02ba5d4500d77c6201eb826400
+d77c6201d8755c00ea7c5e00d8755c0cd7c4bd00d9dcde01cbcccd00c4c5c500b4b4b401
+a4a5a4009c9e9c0498594900a6442b008a514200a6442b008a514200a6442b00994f3c00
+a6442b00994f3c00a6442b007c3a3c00994f3c01ba5d4500d8755c00e8745600d8755c0c
+c56e5e00d8755c01c8745e00d8755c00f9dcd100ffffff0fecf3f500b77c6a00ba5d4504
+ba654f01c7634a00ba654f02c7634a00ba654f00c86d5400ba654f02c7634a00ba654f01
+a7543f00994f3c01a6442b00994f3c0898594900f4f6f900ffffff18f4f6f900e8ecef01
+e6dcdc00d7c4bd00c56e5e00c8745e0bc97c6700c8745e02c97c6700c8745e00c97c6700
+b66c590098594902994f3c0098594901994f3c0098594902c8aca500e8ecef04d8b4ac00
+c8745e01d8755c00c97c6700c8745e00d77c6200c8745e00d77c6200c97c6700d77c6200
+c97c6701d77c6200c8745e00d77c6200c97c6700d77c6200c97c6700d77c6200c97c6700
+b66c5900a7543f00a65b4502a7543f00a65b4501a7543f00d7c4bd00ffffff1af4f6f900
+ecf3f500e0e4e700e6dcdc00d2d4d601cbcccd00d8b4ac00d77c6202d8755c00d77c6200
+d8755c00d77c6202d8755c00d77c6203d8755c00d77c6204c8745e00994f3c00a7543f00
+98594900a7543f0098594900c7998d00ffffff0ef4f6f900ecf3f500e8ecef00d9dcde01
+d2d4d601cbcccd01d8cccb00cbcccd00d8b4ac00d8846e00e8866c00d8846e00e8866c00
+d8846e00e8866c00d8846e01eb826400d8846e02ea7c5e00d8846e02d77c6200e8866c00
+d77c6200d8846e01e8866c00d77c6200d8846e00e8866c00d8846e00d77c6200a65b4500
+a8655400f7ece700ffffff17f4f6f900ecf3f500e0e4e700d9dcde00d2d4d601c4c5c502
+cbcccd00c4c5c502e9947d00d98c7800d8846e00e78b7100d98c7800e78b7104d98c7800
+e78b7100d98c7800e8866c00d98c7800e8866c06d77c6200e9d5d700ecf3f500e8ecef00
+e0e4e700d9dcde00d2d4d600cbcccd01c4c5c501c6bcba00ba654f00da846200e8866c03
+e78b7105e9947d00e78b7104e9947d01e78b7100e9947d00ffffff08f4f6f900e8ecef00
+e0e4e700d9dcde00cbcccd00c4c5c500bbbcbd00c4c5c500bbbcbd00c4c5c500bbbcbd01
+b78d850098594900a65b4500e8866c00e78b7101e8866c00e78b7100e8866c01e78b7100
+e8866c00e78b7100e8866c02e78b7106f8cbc000ffffff0decf3f500e8ecef00d9dcde00
+d2d4d600c4c5c500bbbcbd01b4b4b400bbbcbd00b4b4b400bbbcbd00a7847c0098594900
+a65b450098594900a7543f00a65b4500d98c7800e78b7100e8866c00d8846e00e8866c00
+d8846e00e8866c00d8846e00e8866c00d8846e01e78b7100d8846e00e78b7100d8846e00
+e78b7100d8846e00e8866c00d8846e00e8866c00d69a9000cbcccd00c4c5c500bbbcbd00
+b4b4b403a88c8600a7543f0098594900a7543f0098594901a7543f00b66c5900e78b7100
+d98c7800e8866c00e78b7100d98c7800e8866c00d8846e00e8866c00d8846e01e8866c00
+d8846e00e8866c00d8846e03d77c6200a8655400994f3c01a7543f00994f3c02a7543f01
+c8745e00e8866c0ae78b7109d8846e00e78b7100d8846e01e9947d00f9e4e100f4f6f900
+ffffff09ecf3f500e8ecef00e0e4e700d9dcde00cbcccd00c4c5c500b4b4b400abacad00
+a4a5a40497746b00994f3c07a7543f00994f3c00ba654f00ea7c5e00d8846e00d77c6201
+ea7c5e00d77c6200d8755c00d77c6200ea7c5e00d77c6200d8755c00d77c6200ea7c5e00
+d77c6200d8755c00d77c6200ea7c5e00d8755c00d77c6200d8755c00e5c4c200e0e4e700
+d9dcde00cbcccd00c4c5c500bbbcbd00abacad019c9e9c0496635500994f3c00a6442b00
+8a514200a6442b008a514200a6442b00994f3c02a6442b01994f3c00b7533a00d77c6202
+ea7c5e00d77c6203d8755c00d77c6200d8755c00c97c6700d8755c01c8745e00d8755c01
+c8745e00d8755c00c8745e00e9d5d700ffffff0ef4f6f901b66c5900ba654f0ab66c5900
+ba654f05b66c5900ba654f00994f3c0ca77c7000f4f6f900ffffff18f4f6f900ecf3f500
+e0e4e701d2d4d600c8745e00b7746200b66c5900b7746207c47b7d00b7746200c8745e00
+b7746200c47b7d00c8745e00b77c6a00c8745e00b77c6a00b66c590098594909c8a49d00
+e8ecef03e0e4e700d8ac9f00c8745e00c97c6700c8745e00c97c6701c8745e00c97c6701
+c8745e00c97c6700d8755c00c97c6704c8745e00c97c6700c8745e00d77c6200ba654f00
+98594900a7543f0098594900a7543f0098594903e6ccc900ffffff1bf7ece700e8ecef00
+d9dcde01d2d4d600d8cccb00c4c5c500d77c6201c97c6700d77c620bc97c6700d8755c00
+c97c6700d77c6200c97c6700c8745e00a65b450098594900a7543f0098594901c8938400
+ffffff0ff7ece700e8ecef00e0e4e700e6dcdc00d9dcde00d2d4d600d8cccb00d2d4d600
+cbcccd02d8ac9f00d8846e06d77c6200d8846e00d77c6200d8846e02d77c6200d8846e05
+d98c7800d8846e03a8655400a65b4500d7c4bd00ffffff18f4f6f900ecf3f500e8ecef00
+d9dcde00d2d4d601cbcccd00d8cccb00c4c5c500cbcccd00c4c5c500cbcccd00c4c5c500
+d8b4ac00d8846e00d98c7801d8846e00d98c7801d8846e00d98c7800d8846e00d98c7800
+d8846e00d98c7800d8846e00e78b7100d8846e00d98c7800d8846e00d98c7800d8846e02
+e8866c00c7998d00e8ecef01e0e4e700d9dcde00d2d4d600cbcccd00c4c5c502b8938b00
+b66c5900e8866c00e78b7100d98c7800e78b7100d98c7800e78b7100d8846e00d98c7800
+e78b7100d98c7808d8846e00d98c7800e8a58f00ffffff08f4f6f900e8ecef00e0e4e700
+d2d4d601c4c5c500bbbcbd00c4c5c500bbbcbd00c6bcba00bbbcbd00c4c5c500b7a4a000
+98594900a65b4500c97c6700e8866c00d98c7800e78b7100d98c7800e78b7100d98c7800
+e8866c00d98c7800d8846e00d98c7800e78b7100d8846e00d98c7800e8866c00d98c7800
+e78b7100e8866c00e78b7101e59c8700ffffff0cf4f6f900ecf3f500e0e4e700d9dcde00
+d2d4d600cbcccd00bbbcbd02b4b4b400bbbcbd00b4b4b400a8655400a65b450098594900
+a65b450098594900b7746200d98c7800e78b7100d98c7801e8866c00d98c7800e78b7100
+d8846e00d98c7800e8866c00d98c7800e78b7100d8846e00d98c7800e78b7100d98c7800
+e78b7100d98c7802d8b4ac00cbcccd00c4c5c500b4b4b404a88c860098594902a7543f00
+98594901c8745e00e78b7100d98c7802d8846e00d98c7802d8846e00d98c7800d8846e04
+e8866c00d8846e0198594900994f3c0098594900994f3c0098594900a7543f0098594900
+ba654f00d8846e00da846200e78b7100d8846e00e78b7100d8846e00e8866c00e78b7100
+d8846e00e8866c00d98c7800e78b7100d98c7800e78b7101d98c7800e78b7100d98c7800
+e78b7100d98c7800e78b7100d98c7802e8866c00d98c7800f7b9a600ffffff0cecf3f500
+e8ecef00e0e4e700d2d4d600cbcccd00c4c5c500bbbcbd00b4b4b400a4a5a40497746b00
+994f3c0098594900994f3c07ba654f00d8846e03d77c6200d8846e00d77c6203eb826400
+d77c6203d8846e00d77c6203d8cccb00e0e4e700d9dcde00d2d4d600c4c5c500bbbcbd00
+b4b4b400a4a5a4019c9e9c02a89a950098594900994f3c008a514200a6442b008a514200
+a6442b00994f3c008a514200a6442b00994f3c03ba5d4500d8755c00d77c6200d8755c00
+d77c6205d8846e00d77c6200d8755c00c97c6700d77c6200d8755c00c97c6700d8755c00
+c97c6700d77c6200c8745e00f9dcd100ffffff0ef4f6f900e8ecef00ba654f07b66c5900
+ba654f00b66c5900ba654f00b66c5908994f3c028a514200994f3c028a51420098594900
+8a514200985949008a51420098594900a77c7000ffffff1aecf3f500e8ecef00e0e4e700
+d9dcde00b77c6a00b7746201c8745e00b7746202c8745e00b7746203c97c6700b7746200
+b77c6a00b7746200b77c6a00b7746200b77c6a00c8745e00a96d5f0098594900994f3c00
+985949028a514200985949008a514202b8adaa00e8ecef01e0e4e700e8ecef00e0e4e700
+dba39300b77c6a00c8745e00c97c6703c47b7d00c97c6702c47b7d00c97c6703d77c6200
+c97c6703a8655400a7543f0098594903a7543f0098594901e6ccc900ffffff1becf3f500
+e8ecef00e0e4e700d9dcde00d2d4d600cbcccd00c4c5c500d77c6202c97c6700d77c6200
+c97c6700d77c6201d8846e00d77c6200d8846e00d77c6200c47b7d00d8846e00c47b7d00
+d8846e01c47b7d00d8846e01c97c670098594902a65b450098594900b8938b00ffffff10
+ecf3f500e8ecef00e0e4e700d9dcde01d2d4d601cbcccd03d69a9000d8846e05c47b7d00
+d8846e01c8847200d8846e00c47b7d00d8846e02c8847200d8846e01d98c7800d8846e00
+d98c7802b66c59009859490096635500f4f6f900ffffff19f4f6f900e8ecef00e0e4e700
+d9dcde00d2d4d600d8cccb00cbcccd01c4c5c501cbcccd00c4c5c501d6938100d98c7803
+d8846e00d98c7802d8846e00d98c7800d8846e00d98c7800d8846e00d98c7801e8866c00
+d98c7801e8866c00d98c7800d8846e00c97c6700d2d4d600e0e4e700d9dcde00d2d4d600
+d8cccb00c4c5c500cbcccd00c4c5c500c6bcba00a96d5f00d8846e00d98c7800e78b7100
+d98c7800e78b7100d98c7800e9947d00d98c7803d8846e00e78b7100d98c7807f7ece700
+ffffff08f4f6f900e8ecef00e0e4e700d9dcde00cbcccd00c4c5c501bbbcbd00c4c5c500
+bbbcbd01c4c5c500b4b4b400a65b450098594900b7746200d98c7800e78b7100d98c7801
+d8846e00d98c7800d8846e00d98c7801d8846e00d98c7803d8846e00d98c7802e78b7101
+ffffff0decf3f500e8ecef00d9dcde00d2d4d600c4c5c500bbbcbd01b4b4b400bbbcbd00
+b4b4b400a894900098594902a65b450098594900d8846e00d98c7800e78b7100d98c7800
+e78b7100d98c7801e78b7100d98c7804e78b7100d98c7802e78b7100d98c7800e78b7100
+d98c7800d8bcb600c4c5c500bbbcbd01b4b4b402abacad00a88c860098594905b7746200
+d98c7801d8846e00d98c7801d8846e01d98c7800d8846e00d98c7801d8846e00d98c7801
+d8846e0398594903994f3c0098594900c8745e00d98c7800d8846e00d98c7800d8846e00
+e78b7100d98c7801e78b7100d8846e00d98c7800e78b7100d8846e00d98c7800e78b7100
+d98c7808d8846e00d98c7800e59c8700f9e4e100ffffff0df4f6f900e8ecef00e0e4e700
+d9dcde00cbcccd00c4c5c500bbbcbd00abacad00a4a5a404987c75008a514200994f3c00
+8a514200994f3c0098594900994f3c04a8655400d77c6201d8846e00d77c6200d8846e00
+d77c6201d8846e00d77c6202d8846e03d77c6200d8846e00c47b7d00d8846e00d77c6200
+d8cccb00e0e4e700d9dcde00d2d4d600c4c5c500bbbcbd00b4b4b400abacad009c9e9c04
+96635500994f3c028a514200994f3c028a514200994f3c018a514200994f3c00a65b4500
+d77c6202d8846e00d8755c00c47b7d00d77c6200c97c6700d77c6200c97c6701d8846e00
+c47b7d00d77c6200c97c6700d77c6200c47b7d00d77c6200c97c6701e6dcdc00ffffff0f
+e0e4e700a8655400ba654f00a8655400ba654f00a8655400b66c590aba654f00b7746200
+b66c5902985949008a514200994f3c00985949008a514200985949008a51420098594900
+994f3c008a51420098594900994f3c01a7847c00f4f6f900ffffff18f4f6f901e8ecef00
+e0e4e700d9dcde00b9857800b66c5900b7746200b66c5900b7746208b77c6a00b7746202
+b77c6a00b7746200b77c6a00a96d5f008a514200985949008a514202885a4e008a514200
+885a4e0098594900885a4e00c8a49d00e0e4e700e8ecef00e6dcdc00e8ecef00e0e4e700
+c8a49d00c97c6700c8745e00c97c6700b77c6a00c97c6700b77c6a00c97c6702c8847200
+c97c6700c8847200d77c6200c8847201c47b7d00c97c6700c47b7d00c97c6701a8655400
+98594901a65b450098594904d7c4bd00ffffff1bf4f6f900e8ecef00e0e4e700d9dcde00
+d2d4d600cbcccd00d7c4bd00c97c6701d77c6200c47b7d00d77c6200c47b7d00d77c6200
+c47b7d00c97c6701c47b7d00d77c6200c8847200d8846e01c97c6700d8846e00c8847200
+d77c6200c884720198594900a65b4500985949009663550098594900c7998d00ffffff10
+f4f6f900e8ecef01d9dcde01d2d4d601cbcccd00d8cccb00cbcccd00d2d4d600c6bcba00
+c8847200d8846e00c8847201c47b7d00c8847200d8846e00c8847200d8846e00c47b7d00
+d8846e00c8847200d8846e00c8847201d8846e00c8847200d98c7800c8847200d98c7800
+c88b7d00d8846e00c47b7d00a86554009663550098594900b9857800ffffff19f4f6f900
+ecf3f500e8ecef00e6dcdc00d2d4d600cbcccd02c4c5c500d8cccb00c4c5c501cbcccd00
+c8aca500d98c7802c88b7d00d98c7800c88b7d00d98c7800c88b7d00d98c7800c88b7d00
+d98c780bc8a49d00e6dcdc00d9dcde00d2d4d600cbcccd00c4c5c502b99a9400b66c5900
+d98c7800e78b7100d98c7801e78b7100d98c7803d8846e00d98c7804d8846e00d98c7803
+e8a58f00ffffff09f4f6f900e8ecef00e0e4e700d2d4d601c4c5c500bbbcbd00c4c5c500
+bbbcbd00c4c5c500bbbcbd00c6bcba00bbbcbd00a77c700098594900b66c5900d98c7809
+d8846e00d98c7800d8846e00d98c7803d8846e00d6938100d98c7800e8b3a800ffffff0b
+f4f6f900ecf3f500e0e4e700d9dcde00d2d4d600c4c5c501bbbcbd00b4b4b400bbbcbd00
+b4b4b400a9746500985949009663550098594901a8655400d98c7800d6938100d98c7801
+d6938100d98c7803e78b7100d98c7800e78b7100d98c7802e78b7100d98c7804cbcccd01
+bbbcbd00b4b4b404a7847c0098594905b77c6a00d98c7802c88b7d00d8846e00c88b7d00
+d8846e00c88b7d00c8847200d98c7800c8847200d98c7800c88b7d00d8846e00c88b7d00
+d98c7800c88b7d00d8846e00966355008a51420098594900994f3c00a96d5f00c8847200
+d98c7805d8846e00d98c7808e9947d00d6938100d98c7800e9947d00d98c7803d6938100
+fac4ac00ffffff0fecf3f500e8ecef00e0e4e700d9dcde00cbcccd00c4c5c500b4b4b401
+a4a5a40497746b008a514209a8655400c8847200d8846e00c47b7d00d77c6200c47b7d00
+d8846e00d77c6200c47b7d00d8846e00c8847200d77c6200c47b7d00d77c6201c47b7d00
+d8846e00c8847200d8846e00c8847200d8846e00d8cccb00e8ecef00d9dcde00d2d4d600
+cbcccd00bbbcbd00b4b4b400a4a5a4019c9e9c00a89a95009c9e9c01966355008a514200
+994f3c008a514200994f3c018a514200994f3c018a514200994f3c02a8655400d8846e00
+d77c6200c47b7d00d77c6200c47b7d00d77c6201c47b7d00d77c6200c47b7d00d77c6200
+c97c6700d8846e00c47b7d00d8846e00c97c6700c8847200c97c6702f9dcd100ffffff0e
+f4f6f900e0e4e700b66c5900a96d5f00b66c5900a8655400b7746200a8655400b66c5900
+a96d5f02b66c5900a9746500a96d5f00b66c5900a96d5f00b66c5900b7746200b66c5900
+b7746200b66c5900a96d5f00985949018a514200985949008a514200985949008a514200
+985949008a514200985949008a51420198594900986d6200ffffff1af4f6f900ecf3f500
+e8ecef00e6dcdc00b9857800b66c5900b7746200a9746500b7746200a96d5f00b7746200
+a9746500b7746200a9746500b7746200a77c7000b7746200a77c7000b7746200b77c6a01
+b7746200b77c6a00b7746200a96d5f00885a4e0198594901885a4e0098594900885a4e00
+98594900885a4e0098594900b7a4a000e0e4e704c8a49d00c97c6700b77c6a00b7746200
+c97c6702b77c6a00c47b7d00c8847200c97c6700c8847200c47b7d00c8847201c97c6700
+c8847203c97c6700a96d5f00985949049663550098594901c8aca500ffffff1bf4f6f900
+ecf3f500e0e4e700e6dcdc00d2d4d601c6bcba00c97c6700c8847202c97c6700c8847201
+c97c6700c8847201d8846e00c8847205d8846e00c8847202985949009663550198594900
+96635500c8aca500ffffff11f4f6f900e8ecef00e0e4e700d9dcde00d2d4d601cbcccd03
+c7998d00c8847200c47b7d00c8847203c97c6700c8847200c97c6700c8847204c88b7d00
+c8847200c88b7d01c8847200c88b7d00d8846e00c88b7d00c8847200c97c670098594901
+96635500c8a49d00ffffff19f4f6f900e8ecef00d9dcde01d2d4d600cbcccd01c4c5c500
+cbcccd00c4c5c500cbcccd00c4c5c501d6938100c88b7d03d98c7800c88b7d01d98c7800
+c88b7d00d98c7800c88b7d01d98c7800c88b7d00d98c7800c88b7d00d98c7800c88b7d01
+d98c7800c88b7d00b77c6a00d8cccb00d2d4d600cbcccd01c4c5c502986d6200c8847200
+d98c780cc88b7d00d98c7800c88b7d00d98c7800c88b7d00d98c7800c88b7d00f9e4e100
+ffffff09f4f6f900ecf3f500e0e4e700d9dcde00d2d4d600c4c5c501bbbcbd00c6bcba00
+bbbcbd00c4c5c500bbbcbd01a89490009859490096635500d98c7800d6938100d98c7804
+c88b7d00d8846e00d98c7800c88b7d01d98c7800c8847200d98c7800c88b7d00d8846e00
+c88b7d00d98c7802ffffff0bf4f6f900ecf3f500e0e4e700d9dcde00cbcccd00c4c5c500
+bbbcbd02b4b4b400a89490009859490396635500c97c6700d6938100d98c7800d6938104
+d98c7800d6938100d98c7800d6938100d98c7800d6938100e9947d00d98c7805d69a9000
+d2d4d600c4c5c500bbbcbd00b4b4b404999393008a514202885a4e00985949008a514200
+b7746200d6938100c88b7d00d98c7800c8847201d98c7800c8847201d8846e00c88b7d00
+c8847200c88b7d00d8846e00c88b7d01c8847200d98c7800c88b7d00a8655400885a4e00
+98594900b77c6a00c8847200d98c7800c88b7d00d98c7800c88b7d00d98c7802d6938100
+d98c7800d6938101d98c7800d6938101d98c7800d6938106d98c7801dba39300f4f6f900
+ffffff10f4f6f900e8ecef00e0e4e700d9dcde00cbcccd00c4c5c500bbbcbd00abacad01
+a4a5a40397746b008a514209a65b4500c8847200c47b7d00c8847202c97c6700c8847201
+c97c6700c47b7d00c8847202c97c6700c8847200c97c6700c8847203e6ccc900e0e4e700
+d9dcde00d2d4d600c4c5c500bbbcbd01abacad009c9e9c0496635500994f3c008a514200
+994f3c008a514201994f3c008a514201994f3c008a514201994f3c00a8655400c8847200
+d8846e00c8847200d77c6200c8847200d8846e00c8847209c97c6700c8847200c47b7d00
+c97c6700e6dcdc00ffffff0ef4f6f900e8ecef00b7746200a96d5f01a9746500a96d5f00
+b7746200a9746500a96d5f00b7746200a96d5f00a9746500b66c5900a96d5f00b66c5900
+a9746500b66c5900a96d5f00b7746200a96d5f00b7746200b66c59008a51420098594900
+8a514200985949008a514200985949008a51420398594900885a4e008a51420098594900
+e8ecef00ffffff19f4f6f900ecf3f500e0e4e700d9dcde00b77c6a00a9746500a96d5f00
+b7746201a9746500b7746201a9746500b7746201a9746501b7746200a9746500a77c7000
+b7746200a77c7000b77c6a01a96d5f00885a4e0098594900885a4e0398594900885a4e02
+c8aca500e0e4e701e8ecef00e0e4e701d8ac9f00b77c6a00b7746200c97c6700b77c6a01
+c97c6700b9857800c97c6700b9857800c8847206c97c6700c8847200b77c6a00c8847200
+a974650096635500985949008a6358009859490096635500985949008a63580098594900
+b78d8500ffffff1bf4f6f900e8ecef01d9dcde00d2d4d600d8cccb00c6bcba00c97c6700
+c8847200c47b7d00c97c6700c8847200c97c6700c8847208c88b7d03c8847200b9857800
+98594900966355009859490096635501d7c4bd00ffffff11f4f6f900e8ecef00e0e4e700
+e6dcdc00d2d4d602d8cccb00cbcccd00c8a49d00c8847200c47b7d00c8847201c47b7d00
+c97c6701c47b7d00c8847200c47b7d00c8847200c97c6700c8847200d8846e00c88b7d00
+c8847200d8846e00c88b7d00c8847200d98c7800c88b7d02d98c7800c88b7d00b7746200
+9663550098594901e6ccc900ffffff18f4f6f900ecf3f500e8ecef00d9dcde00d2d4d600
+cbcccd00d8cccb00cbcccd00c4c5c500cbcccd00c4c5c501cbcccd00c8a49d00c88b7d03
+c8847200c88b7d01c8847200c88b7d01c8847200d98c7800c8847200c88b7d00c8847200
+c88b7d01d8846e00c88b7d00c8847200d98c7800c8847200b7a4a000d2d4d600cbcccd01
+c4c5c501b7a4a000a8655400d98c7800d8846e02d98c7801c8847200d98c7800c8847200
+d98c7800c8847200d98c7800c88b7d00c8847200d8846e00c88b7d00c8847202c88b7d00
+d6938100ffffff0af4f6f900ecf3f500e0e4e700d9dcde00d2d4d600c4c5c502bbbcbd01
+c4c5c500bbbcbd00c4c5c500b8adaa008a63580098594900c8847200c88b7d00d6938100
+c88b7d00d6938100c88b7d00d98c7800c88b7d00d6938100c88b7d01d8846e00c88b7d01
+c8847200c88b7d01c8847200c88b7d00c8847200c88b7d00e8bcb000ffffff0aecf3f500
+e8ecef00e0e4e700d2d4d601c4c5c500bbbcbd00b4b4b400bbbcbd00b8adaa00986d6200
+885a4e0098594900885a4e0098594900a8655400c8938400d98c7800d69a9000d6938104
+d69a9000d6938104d98c7800d6938102d98c7801d6938100d8b4ac00cbcccd01bbbcbd00
+b4b4b401abacad00b4b4b401a89a9500885a4e0098594900885a4e008a51420098594900
+885a4e00b7746200c88b7d00d98c7800c8847200d98c7800c88b7d00c8847202c88b7d00
+c8847200d98c7800c88b7d01c8847200d98c7800c88b7d02a96d5f00a8655400c8847200
+c88b7d00d98c7800c88b7d00d98c7800c88b7d00d98c7800c88b7d00d6938100c88b7d01
+d6938100c88b7d00d98c7800d6938100d98c7800d6938108d69a9000f8d4c900ffffff12
+ecf3f500e8ecef00e0e4e700d9dcde00cbcccd00c4c5c500b4b4b401a4a5a4019c9e9c00
+a4a5a401987c75008a51420996635500c8847203c47b7d00c8847201c97c6700c8847201
+c97c6700c8847200c47b7d00c8847206d8cccb00e8ecef00d9dcde00d2d4d600cbcccd00
+bbbcbd00b4b4b400abacad00a4a5a4009c9e9c00a89a95009c9e9c018a635800885a4e00
+8a514204985949008a514201994f3c008a514200994f3c00a8655400c8847201d8846e00
+c8847205d8846e00c8847203c97c6700c8847204e6dcdc00ffffff0eecf3f501b9857800
+a96d5f00a9746500a96d5f00a9746500a96d5f01a9746500a96d5f00a9746500a96d5f00
+a9746502a96d5f00b7746200a9746500b66c5900a9746500b66c5900a974650098594900
+8a514200885a4e008a514200885a4e008a514200885a4e01985949008a514200885a4e00
+8a514200885a4e01d8cccb00ffffff19f4f6f900ecf3f500e8ecef00d8cccb00a9746500
+b7746200a9746500b7746200a9746501b7746200a77c7000b7746200a77c7000a9746504
+b7746200a77c7000b77c6a00a9746500b77c6a00a9746500885a4e0098594900885a4e00
+98594900885a4e0098594900885a4e0198594900885a4e00b8adaa00e0e4e704c7b5b100
+b7746200c97c6700b77c6a01c47b7d00b77c6a00c97c6700b9857800c97c6700b9857800
+c8847200b9857800c8847200b9857800c8847200b9857801c8847200b9857800b77c6a01
+985949008a635800985949008a635800885a4e0096635500885a4e0096635500986d6200
+ffffff1bf4f6f900ecf3f500e8ecef00d9dcde00d2d4d601c8a49d00c8847202b9857800
+c8847204c88b7d00b98a7c00c88b7d04c8847200c88b7d02b77c6a0096635504e6dcdc00
+ffffff11f4f6f901e8ecef00d9dcde01d2d4d600cbcccd01c7b5b100c8847200b77c6a00
+c8847200b77c6a01c8847200b9857800b77c6a00c8847200b9857800c8847200c97c6700
+c8847204c88b7d00c8847200c88b7d00c8847200c88b7d00c8847200c88b7d00c8847200
+c88b7d00c8847200a86554009859490196635500ffffff19ecf3f500e8ecef00e6dcdc00
+d9dcde00d2d4d600cbcccd01c4c5c501d8cccb00c4c5c501c6bcba00c88b7d00c8847200
+c88b7d00c8847200c88b7d00c8847200c88b7d02c8847200c88b7d00c8847201c88b7d01
+c8847200c88b7d00c8847204b77c6a00cbcccd01c4c5c50297746b00b7746200c8847201
+c88b7d00c8847202d8846e00c8847200c88b7d00c8847200c88b7d00c8847200c88b7d02
+c8847200c88b7d01c8847200c88b7d00f8d4c900ffffff0becf3f500e8ecef00d9dcde00
+d2d4d600cbcccd00c4c5c500bbbcbd00c4c5c500bbbcbd00c4c5c500bbbcbd00c6bcba00
+bbbcbd00986d620098594900a9746500d98c7800c88b7d00d6938100c88b7d00d6938100
+c88b7d01c8847200c88b7d03c8847200c88b7d00c8847200c88b7d01c8847200c88b7d01
+c8847200f4f6f900ffffff09ecf3f500e0e4e700d9dcde00d2d4d600c4c5c501bbbcbd01
+b4b4b400987c7500885a4e00966355008a635800885a4e0096635500b9857800d6938100
+c8938400d6938100c8938400d69a9000d6938100d69a9000d6938102d69a9000d6938102
+c8938400d6938101c8938400d6938100c8938400d98c7800d8cccb00d2d4d600c4c5c500
+bbbcbd00b4b4b404a4a5a400885a4e038a514200885a4e00a96d5f00c88b7d03c8847200
+c88b7d01c8847202c88b7d00c8847200c88b7d05c8847200c88b7d02c8938400c88b7d00
+d6938100c88b7d00d6938100c88b7d00d98c7800c88b7d00d6938101c88b7d00d6938100
+c8938400d6938105d69a9000d6938101e8b3a800ffffff14f4f6f900e8ecef00e0e4e700
+d9dcde00cbcccd00c4c5c500bbbcbd00abacad01a4a5a403987c750076524a00885a4e00
+76524a008a51420076524a008a51420076524a008a51420296635500c8847200b9857800
+c8847202b9857800c8847201b9857800c8847200b9857800c8847200b9857800c47b7d00
+b9857800c8847200c47b7d00c8847201b9857800d8cccb00e0e4e700d9dcde00d2d4d600
+cbcccd00bbbcbd01a4a5a4019c9e9c0396635500885a4e008a514200885a4e018a514200
+885a4e008a514205a96d5f00c8847213e6dcdc00ffffff0ef4f6f900e8ecef00b8938b00
+a96d5f00a9746500a96d5f00a9746501a96d5f00a9746500a96d5f00a9746500a96d5f02
+a9746501a96d5f00a974650496635500885a4e018a514200885a4e018a514200885a4e00
+8a514200885a4e04c8aca500ffffff1af7ece700e8ecef00c4c5c500b7746200a9746503
+b7746200a77c7000a9746500a77c7000b7746200a77c7000b7746200a77c7000b77c6a00
+a77c7001b7746200a77c7000b77c6a01a974650098594900885a4e008a63580098594900
+885a4e008a635801985949008a635800885a4e00c8aca500e0e4e704d7c4bd00b77c6a04
+c8847200b9857800c8847200b9857800c8847200b9857800c8847200b9857802c8847200
+b985780496635501885a4e00966355048a635800f9e4e100ffffff1be8ecef01e6dcdc00
+d2d4d601c7998d00b9857803c88b7d00b98a7c02c88b7d00b78d8500c88b7d00b98a7c00
+c88b7d00b98a7c00c88b7d01b78d8500c88b7d00b78d8500c88b7d00a97465008a635800
+966355008a635800966355008a635800ffffff12f4f6f901e0e4e701d2d4d601d8cccb00
+c6bcba00b9857801b77c6a00b9857800b77c6a05c8847200b77c6a00b9857801c47b7d00
+b9857800c8847202c88b7d04d6938100c88b7d00d98c7800c88b7d00c884720096635501
+98594900a77c7000ffffff18f4f6f900ecf3f500e8ecef00d9dcde00d2d4d600cbcccd02
+c4c5c500cbcccd00c4c5c500cbcccd00c4c5c500c7998d00b9857802c88b7d00b9857801
+c8847200b9857800c88b7d00c8847200b9857800c8847202c88b7d00c8847200b9857800
+c88b7d00c8847200c88b7d01b77c6a00b7a4a000c4c5c502b8adaa0098594900c8847204
+c88b7d00c8847200c88b7d00c8847202c88b7d01c8847200c88b7d00c8847200c88b7d01
+c8847200c88b7d00c8938400ffffff0cf4f6f900e8ecef00e0e4e700d2d4d600cbcccd00
+c4c5c501bbbcbd00c6bcba00bbbcbd00c4c5c500bbbcbd01a894900096635501c8938400
+c88b7d01d6938100c88b7d08b9857800c8847200b9857801c88b7d00b9857800b98a7c00
+c88b7d00d69a9000ffffff08ecf3f500e8ecef00e0e4e700d9dcde00d2d4d600c4c5c501
+bbbcbd00b4b4b400987c7500966355008a635800885a4e0096635500885a4e00a77c7000
+d6938100c8938401d69a9000c7998d00d6938100c7998d01d69a9000c7998d00d69a9000
+c7998d00d69a9000c7998d00d69a9001c8938400d69a9000d6938100c8938400d6938100
+c8a49d00d9dcde00cbcccd00c4c5c500bbbcbd00b4b4b402abacad00b4b4b400b8adaa00
+8a63580098594900885a4e0198594900885a4e00a96d5f00c88b7d00c8938400c88b7d02
+c8847200c88b7d07b98a7c00c88b7d04c8938401d6938100c8938403d6938100c7998d00
+d6938100c7998d00d6938100c8938400d6938100c8938400d6938100c8938400d6938100
+c7998d00d6938100d69a9000d6938100d69a9000f8d4c900ffffff15ecf3f500e8ecef00
+e0e4e700d9dcde00cbcccd00c4c5c500b4b4b401a4a5a404987c7500795b54008a514200
+885a4e008a514200885a4e008a514200885a4e0176524a00885a4e00986d6200b98a7c00
+c88b7d00c8847200b98a7c00b9857800c88b7d00b9857801c8847200b9857801b77c6a00
+b9857801b77c6a00b9857802c47b7d00b9857800d8cccb00e8ecef00e0e4e700d2d4d600
+cbcccd00bbbcbd00b4b4b400abacad00a4a5a4009c9e9c038a635800885a4e038a514200
+885a4e008a514200885a4e038a514200986d6200c8847200c88b7d01c8847200c88b7d00
+c8847203b9857800c8847200b9857800c8847201b9857800c8847200b9857800c8847200
+b9857800c8847200e6dcdc00ffffff0eecf3f501b7a4a000a96d5f00986d6200a9746500
+986d6200a96d5f00a9746500a96d5f02a9746500a96d5f01a9746502a96d5f00a9746503
+966355008a514200885a4e028a514200885a4e07a88c8600ffffff19f4f6f900ecf3f500
+e8ecef00c8a49d00a9746501b77c6a00a77c7000a9746500a77c7000a9746500a77c7004
+a9746500a77c7000b7746200a77c7001b77c6a00a77c7000b77c6a0097746b00885a4e00
+8a635800885a4e008a635800885a4e028a635800885a4e008a635800b8adaa00f9e4e100
+e0e4e703d8cccb00b9857800b77c6a00b9857802b77c6a00b985780bc8847200b9857801
+966355018a635800966355008a635804c6bcba00ffffff1af4f6f900ecf3f500e0e4e700
+d9dcde00d2d4d600cbcccd00b98a7c00c8847200b9857801c8847200b98a7c01c88b7d00
+b98a7c01c88b7d00b78d8500c88b7d00b78d8501c88b7d00b8938b00c88b7d00b78d8500
+c88b7d00b78d8500a97465008a635803a77c7000ffffff13e8ecef01e6dcdc00d2d4d601
+c4c5c500c88b7d00b9857800b77c6a01b9857800b77c6a00b9857800b77c6a01b9857800
+b77c6a00b9857800c8847200b77c6a00c8847200b9857800c8847200c88b7d00b9857800
+c8847200c88b7d02d98c7800c88b7d05c8847200885a4e0096635500885a4e00b8938b00
+ffffff18ecf3f500e0e4e700d9dcde01d2d4d600cbcccd01c4c5c503cbcccd00c7b5b100
+b9857803b98a7c00c88b7d00b9857803c88b7d00b9857801c88b7d00b9857800c8847200
+c88b7d00b9857801c8847202a7847c00c4c5c502a7847c00a96d5f00b9857800c8847200
+b9857800c8847202c88b7d00c8847200c88b7d03c8847200c88b7d00b98a7c00c88b7d00
+b78d8500c88b7d00b9857800c88b7d00e6ccc900ffffff0cecf3f500e8ecef00e0e4e700
+d9dcde00cbcccd00c4c5c501bbbcbd01c4c5c500bbbcbd00c4c5c500bbbcbd00b4b4b400
+96635501c8847200c7998d00c8938401c88b7d00c8938400c88b7d02b78d8500c88b7d00
+b9857800b98a7c03c88b7d00b9857800b98a7c00c88b7d00b78d8500b98a7c00c8a49d00
+ffffff06f4f6f900ecf3f500e0e4e700d9dcde00d2d4d600cbcccd00c4c5c500bbbcbd00
+a4a5a400986d62008a635804a77c7000c7998d00d79c7e00c7998d05d69a9000c7998d00
+c8938400c7998d00d69a9000c8938400d69a9000c8938400c7998d00d6938100c7998d00
+d69a9000c8938400d69a9000d8bcb600d2d4d601c4c5c500bbbcbd00b4b4b40597746b00
+885a4e0496635500c8938400c88b7d00c8938400c88b7d01c8938400c88b7d04b78d8500
+c88b7d01c8938400b78d8500c88b7d00b78d8500c8938404c7998d00c8938400d69a9000
+c8938400c7998d00d69a9000c7998d00d69a9000c8938400d69a9000c7998d00d6938100
+c8938400d6938100c7998d00d69a9000c8938401e8bcb000ffffff17f4f6f900ecf3f500
+e0e4e700d2d4d600cbcccd00c4c5c500bbbcbd00abacad00a4a5a404987c750076524a00
+885a4e0076524a00885a4e00795b5400885a4e0076524a00885a4e018a514200986d6200
+c88b7d00b98a7c03b9857807b77c6a00b9857800b77c6a00a7847c00b77c6a00a7847c00
+b9857800d8cccb00e0e4e700d9dcde00d2d4d600cbcccd00bbbcbd01abacad009c9e9c04
+876d6700885a4e0676524a00885a4e018a514200885a4e00986d6200c88b7d00b98a7c00
+b9857800b98a7c00b9857800c88b7d00b9857802c8847200b9857802c88b7d00b9857805
+e6dcdc00ffffff0ef4f6f900e8ecef00c7b5b100986d6200a96d5f00986d6201a9746500
+986d6200a9746500986d6201a9746500986d6200a9746500a96d5f00a974650798594900
+885a4e0b96635500e8ecef00ffffff19e8ecef01b8938b00a77c7000a9746500a77c7000
+a9746500a77c7004a9746500a77c7004b77c6a00a77c7000a7847c00b77c6a00a7847c00
+a97465008a635800885a4e008a635800885a4e008a635804885a4e00b8adaa00e0e4e700
+e8ecef00e0e4e702d9dcde00b8938b00b9857800b77c6a00b9857800b77c6a00b9857800
+b77c6a00b9857803b98a7c00b9857804b98a7c00b9857800b98a7c00b9857800a9746500
+8a635800966355008a635800885a4e00966355008a63580096635500885a4e00a7847c00
+ffffff1af4f6f900e8ecef01e6dcdc00d9dcde00c6bcba00b9857801b98a7c00b9857800
+b78d8500b98a7c00b9857800b98a7c01b78d8502b8938b00c88b7d00b78d8500b8938b00
+c88b7d00b78d8501c88b7d00b78d8500986d62008a635801966355008a635800b7a4a000
+ffffff12f4f6f900e8ecef01d9dcde01d8cccb00c7998d00b9857800b77c6a00b9857801
+b77c6a00b9857800b77c6a00b9857800b77c6a00b9857801b77c6a00b9857803c88b7d00
+b9857800c88b7d00b98a7c00c88b7d03c8938400c88b7d05b77c6a00885a4e02d8bcb600
+ffffff17f4f6f900f7ece700e0e4e700d9dcde00d2d4d600d8cccb00cbcccd00c4c5c500
+d8cccb00c4c5c500cbcccd00c4c5c501b99a9400b9857805c88b7d00b98a7c01b9857800
+c88b7d00b9857805c8847200b98a7c01b9857800b77c6a00b7a4a000c4c5c500bbbcbd00
+885a4e00b77c6a01b9857802c88b7d00b78d8500b9857800b98a7c01c88b7d00b9857800
+b78d8500c88b7d00b78d8500c88b7d00b78d8500c8938400c88b7d00b78d8500c7998d00
+ffffff0df4f6f900ecf3f500e0e4e700d9dcde00d2d4d600c4c5c503bbbcbd00c4c5c500
+bbbcbd00c6bcba00c4c5c500978c8a008a635800a9746500c8938402c7998d00c8938400
+c7998d00c88b7d00b8938b00c88b7d00b78d8501c88b7d00b78d8500c88b7d00b78d8500
+b98a7c00b78d8503c88b7d00b78d8500c8a49d00f7ece700ffffff03f4f6f900ecf3f500
+e8ecef00d9dcde01d2d4d600cbcccd00b4b4b400987c75008a635805b9857800c8938400
+c7998d04d69a9000c7998d03d69a9000c7998d03d69a9000c7998d00d69a9000c7998d03
+d9dcde01d2d4d600c4c5c500bbbcbd00b4b4b40597848100885a4e05c88b7d00c8938400
+c88b7d00c8938401c88b7d00c8938400b78d8500c8938400b78d8500c8938402b78d8500
+c88b7d00c8938402c88b7d00b78d8500c8938403c7998d00c8938400c7998d01c8938400
+c7998d02c8938400c7998d03d6938100c7998d00d69a9000f9e4e100ffffff18ecf3f500
+e8ecef00e0e4e700d9dcde00d2d4d600c4c5c500bbbcbd00b4b4b400a4a5a404987c7500
+76524a008a51420076524a018a51420076524a00885a4e0076524a00885a4e0076524a00
+986d6200b98a7c02c88b7d00b98a7c00b9857800b78d8500b9857804b77c6a00b9857800
+a77c7000b9857801a77c7000b9857800b77c6a00cbcccd00e0e4e701d2d4d600cbcccd00
+bbbcbd00b4b4b400abacad00a4a5a4009c9e9c03876d6700885a4e01795b5400885a4e01
+795b5400885a4e05986d6200c88b7d00b78d8500c88b7d00b98a7c00c88b7d00b98a7c01
+b9857803c8847200b9857804c47b7d00b9857801e6dcdc00ffffff0eecf3f501d8cccb00
+986d6202a9746500986d6201a974650097746b00a9746500986d6200a9746500986d6200
+a9746503a77c7001a9746500a77c7000a97465008a635800885a4e0296635500885a4e08
+c6bcba00ffffff18f4f6f900ecf3f500d9dcde00a9746501a77c7000a9746500a77c7007
+b77c6a00a77c7001a7847c00a77c7000b77c6a00a7847c00a77c7000b985780097746b00
+8a635802885a4e008a635800885a4e02795b54008a635800b8adaa00e0e4e701e8ecef00
+e0e4e701d2d4d600c8a49d00a7847c00b9857800b77c6a00a7847c00b77c6a00a7847c00
+b9857800a77c7000b9857804b98a7c00b9857802a7847c00b9857801a7847c008a635803
+885a4e008a635800885a4e008a635800885a4e00e8ecef00ffffff19f4f6f900ecf3f500
+e0e4e700d9dcde00d2d4d600c8a49d00b98a7c03b9857800b78d8500b98a7c00b78d8500
+b98a7c00b78d8504b8938b00b98a7c00b8938b00b98a7c00b8938b00b78d8500b9857800
+8a635804d8cccb00ffffff12f4f6f900e8ecef00e0e4e700d9dcde00d2d4d600c8aca500
+b985780cb98a7c00b9857800c8847200b98a7c00c88b7d00b98a7c00c88b7d01c8938400
+b78d8500c8938402c88b7d00c8938400c88b7d00b8938b00c88b7d00b8938b00c88b7d00
+97746b008a635800885a4e008a635800e6dcdc00ffffff17ecf3f500e8ecef00d9dcde00
+d2d4d601cbcccd01c4c5c500cbcccd00c4c5c500cbcccd00c4c5c500c7b5b100b9857801
+b78d8500b98a7c00b78d8500b98a7c05b78d8500c88b7d00b78d8500c88b7d00b98a7c02
+b9857800b98a7c00c88b7d00b98a7c00a7847c00c4c5c500a88c8600986d6200b9857803
+b98a7c02c88b7d00b78d8500c88b7d00b78d8500c8938400b78d8500c8938400b78d8500
+c8938400b78d8500c8938400b78d8500c8938400d7c4bd00ffffff0eecf3f500e8ecef00
+d9dcde00d2d4d600cbcccd00c4c5c500bbbcbd00c6bcba00bbbcbd01c4c5c500bbbcbd01
+b4b4b400986d62008a635800c8938400c7998d03b8938b00c8938400b8938b00c8938400
+b8938b00c88b7d00b8938b00b78d8502c8938400b78d8501c8938400b78d8500b8938b01
+c88b7d00b8938b00d7c4bd00f4f6f900ffffff00f4f6f900ecf3f500e8ecef00d9dcde01
+cbcccd00a4a5a400987c7500885a4e008a635800885a4e008a635800885a4e008a635800
+97746b00b98a7c00c7998d10c8938400c7998d01c8938400c7998d00d69a9000d8bcb600
+e0e4e700d9dcde00cbcccd00c4c5c500bbbcbd00b4b4b401abacad00b4b4b401abacad00
+a89a9500885a4e0077646000885a4e008a635800885a4e01a7847c00c8938400b78d8500
+c8938400b78d8500c8938400b78d8500c8938402b78d8500c8938402b78d8500c8938400
+b78d8500c8938401c7998d00c8938400b8938b00c7998d00c8938400c7998d08c8938400
+c7998d00c8938400c7998d01d8b4ac00ffffff1af4f6f900e8ecef00e0e4e700d9dcde00
+cbcccd00c4c5c500bbbcbd00abacad019c9e9c00a4a5a402867c7b0076524a01795b5400
+8a51420076524a018a51420076524a018a514200986d6200b9857800b98a7c00b9857800
+b98a7c00b9857802b98a7c01a7847c00b9857800a7847c00b9857800a7847c00a77c7000
+a7847c00a77c7000b9857800a77c7000a7847c00d8cccb00e0e4e700d9dcde00d2d4d600
+cbcccd00bbbcbd01abacad00a4a5a4009c9e9c0199939300a4a5a400876d6700795b5400
+885a4e00795b5400885a4e00795b5400885a4e008a635800795b5400885a4e0077646000
+885a4e008a635800986d6200b8938b00c88b7d00b78d8500c88b7d00b78d8500b98a7c00
+c88b7d00b985780aa77c7000b9857800e6dcdc00ffffff0ef4f6f900ecf3f500e6dcdc00
+97746b00986d620497746b00a96d5f0097746b00986d6200a974650097746b00a9746500
+97746b00a77c7001a9746500a77c7001a9746500a77c7000986d6200885a4e09795b5400
+885a4e00795b5400a7847c00ffffff18f4f6f900e8ecef00c7b5b10097746b02987c7500
+97746b01a77c700097746b00a77c7003a7847c00a77c7002a7847c00a77c7000a7847c00
+a77c7000a7847c0097746b00885a4e01795b54008a635800795b5400885a4e0077646000
+8a635800795b5400885a4e00b7a4a000e8ecef01e0e4e700e8ecef00e0e4e700d9dcde00
+c7b5b100b9857800a77c7000a7847c01b77c6a00a7847c00a77c7000b9857800a7847c08
+b9857800b98a7c00a7847c00b985780096635500885a4e028a635800795b5400885a4e00
+77646000885a4e00b8adaa00ffffff19f4f6f900e8ecef00e0e4e700d9dcde00d2d4d600
+b8938b00b98a7c00b9857800b78d8500b9857800a88c8600b9857800b78d8505b8938b00
+b78d8503b8938b00b98a7c00b8938b00a77c70008a635803876d6700ffffff12f4f6f901
+e8ecef00e0e4e700d9dcde00c7b5b100a88c8600b9857800a7847c00b9857803a7847c00
+b9857802b78d8500b9857800b98a7c01c88b7d00b78d8501b98a7c00c8938400b78d8500
+c8938400b78d8500c88b7d00b78d8500c8938400b78d8500b8938b00b78d8501b8938b00
+c88b7d00b78d8500c88b7d00b98a7c00986d62008a63580197746b00ffffff17f4f6f900
+e8ecef00e0e4e700d9dcde00d2d4d600cbcccd02c4c5c500cbcccd00c4c5c502a8949000
+b98a7c00a7847c00b98a7c00b78d8500a7847c00b98a7c00b78d8500b98a7c01b78d8504
+b98a7c00b78d8500b98a7c00b9857800b78d8500b9857800b98a7c00a77c7000b7a4a000
+885a4e00a7847c00b9857800b98a7c02b78d8500b9857800b78d850dffffff0ff4f6f900
+e8ecef00e0e4e700d9dcde00cbcccd00c4c5c502bbbcbd00c4c5c500bbbcbd00c6bcba00
+c4c5c500bbbcbd00a89a95008a63580097746b00c7998d06b8938b00c7998d00b8938b02
+c8938400b8938b00b78d8500b8938b01b78d8500b8938b01b78d8500b8938b01b78d8500
+c7998d00c7b5b100c6bcba00b4b4b400b8adaa00a89a9500987c75008a635800885a4e00
+795b5403885a4e0097746b00b98a7c00c7998d01c8938400c7998d14c8a49d00e0e4e700
+e8ecef00d9dcde00d2d4d600cbcccd00bbbcbd00b4b4b405a4a5a4008a635800795b5400
+8a635800885a4e00795b54008a635800a9746500c8938400b8938b00c8938400b8938b00
+c8938400b8938b00c8938400b8938b00c8938402b8938b00c8938401c7998d00c8938400
+c7998d00b8938b00c8938400b8938b00c8938400c7998d00c8938400b8938b00c8938400
+c7998d03c8938400c7998d00c8938401c7998d01c8a49d00f9e4e100ffffff1becf3f500
+e8ecef00e0e4e700d9dcde00cbcccd00c4c5c500b4b4b401a4a5a404987c750076524a04
+795b540076524a038a635800b78d8500b9857800b78d8500b9857800b78d8500a7847c00
+b9857800a7847c00b9857800a7847c00b98a7c00b9857800a77c7000b9857800a77c7001
+b9857800a77c7000a7847c00a77c7000d8cccb00e0e4e701d2d4d600cbcccd00bbbcbd00
+b4b4b400abacad00a4a5a40099939300a4a5a4009c9e9c01876d6700795b5400885a4e00
+795b5401885a4e00795b5401885a4e00795b5400885a4e00795b5400885a4e0097746b00
+b78d8500b8938b02b78d8502b98a7c00b78d8500b9857807a7847c00b9857800a77c7000
+e6dcdc00ffffff0ef4f6f900ecf3f500e8ecef00a88c8600986d620297746b00986d6201
+97746b00986d620097746b00986d620097746b00a77c7001a9746500987c7500a77c7000
+a9746500a77c7000a9746500a77c7000986d6200885a4e00795b5400885a4e00795b5401
+885a4e00795b5403885a4e00795b540076524a008a635800d9dcde00ffffff17ecf3f500
+e8ecef00a894900097746b00a974650097746b00a77c700097746b00a77c700097746b00
+987c7500a77c7000987c7501a77c7002a7847c00a77c7001a7847c00a77c7000a7847c00
+a77c700097746b008a63580077646000885a4e00795b54008a635800795b5404b8adaa00
+e8ecef00e0e4e700e8ecef00e0e4e701e6dcdc00cbcccd00a7847c00a77c7004a7847c00
+a77c7002a7847c00a77c7001b9857800a77c7000b9857800a7847c0497746b00885a4e00
+77646000885a4e00795b54008a635800795b5400885a4e0077646000986d6200ffffff19
+ecf3f500e8ecef00e6dcdc00d9dcde00c7b5b100a7847c00b9857800a88c8600a7847c00
+b98a7c00b9857800a88c8600b78d8503b8938b00b78d8502b8938b00b78d8500b8938b00
+b78d850297746b008a635801776460008a635800a88c8600ffffff12f4f6f900e8ecef00
+e0e4e701d8cccb00b78d8500b9857800a7847c00b98a7c00a88c8600b78d8500a7847c00
+b78d8500b9857800b78d8500a88c8600b78d8501b98a7c00b78d8500b8938b00b78d8500
+b8938b00c8938400b78d8500c8938400b78d8501c8938400b78d8500c8938400b78d8500
+c8938400b78d8500c8938400b78d8500c88b7d00b8938b00b78d8500b8938b00c88b7d00
+b98a7c008a635801885a4e00a7847c00ffffff16f4f6f900ecf3f500e8ecef00d9dcde00
+d2d4d601cbcccd01c4c5c501d8cccb00c4c5c500cbcccd00c8aca500a7847c00b98a7c00
+a7847c00b98a7c00a88c8600b98a7c00a88c8600b78d8500b98a7c00b78d8503c8938400
+b78d8500b98a7c00b78d8500b98a7c00b78d8500b9857800b78d8500b9857800876d6701
+b9857801a7847c00b78d8500b9857800b78d8500b98a7c02b78d8501b98a7c00b78d8502
+b8938b00b78d8503d8bcb600ffffff0ff4f6f900ecf3f500e0e4e700d9dcde00d2d4d600
+cbcccd00c4c5c500bbbcbd00c4c5c500bbbcbd02c4c5c500bbbcbd00c4c5c50097848100
+8a635800b78d8500c7998d00b8938b00c7998d00b99a9400b8938b00c7998d00b99a9400
+c7998d00b8938b00c7998d00b8938b00b99a9400b8938b02b78d8500b8938b03b98a7c00
+b8938b00b78d8501b8938b00c88b7d00b78d850097746b00986d6200795b54038a635800
+986d6200987c7500b98a7c00b8938b05c8938400b99a9400c7998d03b99a9400c7998d0c
+e6dcdc00f4f6f900e0e4e700d9dcde00d2d4d600c4c5c500bbbcbd00b4b4b40687747000
+795b5401885a4e0077646000885a4e00876d6700c7998d00b8938b01c8938400b8938b00
+c8938400b8938b00c8938400b99a9400c7998d00b99a9400c7998d09b8938b00c7998d01
+b99a9400c8938400b8938b00c8938400b8938b00c8938400b8938b03d8bcb600ffffff1d
+f4f6f900ecf3f500e0e4e700d2d4d601c4c5c500bbbcbd00abacad01a4a5a4029c9e9c00
+8774700076524a09986d6200a7847c00b9857800a7847c02b9857800a7847c02b9857800
+a7847c01a77c7001a7847c00a77c7003a7847c00d8cccb00e0e4e700d9dcde00d2d4d600
+cbcccd00bbbcbd01a4a5a4019c9e9c03876d670076524a00795b5407885a4e00795b5401
+97746b00b98a7c00b8938b00b98a7c00b8938b00b78d8500c88b7d00b78d8500b9857800
+a7847c00b9857800a7847c03a77c7000a7847c00a77c7000a7847c00a77c7001e6dcdc00
+ffffff0ef4f6f900ecf3f500e8ecef00b8adaa00986d6200876d6700986d6200876d6700
+986d620497746b03a77c700097746b00a9746500987c750097746b00a77c700097746b01
+8a635800885a4e00795b5400885a4e0076524a00795b5402885a4e0076524a00795b5400
+76524a00795b540076524a00a89a9500ffffff16f4f6f901d9dcde0097746b04987c7500
+97746b00a77c700097746b00987c750097746b00a77c7000987c7501a77c7000987c7500
+a77c7000987c7500a77c7000a7847c00a77c700197746b00885a4e00795b54058a635800
+795b5401b8adaa00e8ecef02f7ece700e0e4e701d2d4d600a88c8600a77c7000987c7500
+a77c7000987c7500a77c7000987c7500a7847c00a77c7006a7847c00a77c7000a7847c00
+b77c6a00a7847c01a77c70008a63580077646000885a4e0077646000885a4e0077646000
+885a4e0077646000885a4e00c4c5c500ffffff17f4f6f900e8ecef01d9dcde01b99a9400
+a88c8600b98a7c00a7847c00b98a7c00a7847c00a88c8600b78d8501a88c8600b78d8507
+a88c8600b8938b00b78d8501876d67008a635800776460008a635801c4c5c500ffffff11
+f4f6f901e8ecef00e0e4e700d8cccb00b8938b00a7847c00a88c8600b98a7c00a88c8600
+b78d8500a7847c00b78d8500a7847c00b78d8500a88c8600b98a7c00b78d8503b8938b01
+b78d8500b8938b0fb78d8500b8938b00b78d8500a7847c008a635801795b5400b7a4a000
+ffffff16f4f6f900e8ecef00e6dcdc00d9dcde00d2d4d600cbcccd02c4c5c504b8938b00
+a7847c00a88c8600b98a7c00a88c8600b78d8505b8938b00b78d8508a7847c00a77c7001
+a88c8600b9857800a88c8600b9857800a88c8600a7847c01a88c8600a7847c00b78d8500
+a88c8600b78d8506a88c8600b78d8500ffffff11f4f6f900e8ecef00e0e4e700d2d4d600
+cbcccd00c4c5c502bbbcbd00c4c5c501bbbcbd0397746b00876d6700b8938b00c7998d00
+b99a9400c7998d00b99a9400c7998d00b8938b00b99a9400c7998d00b99a9400b8938b00
+b99a9400b8938b10b98a7c00a88c8600b9857800a88c8600b98a7c00b8938b0ac7998d00
+b8938b00b99a9401c7998d00b99a9401c7998d00b99a9403c7998d00b99a9400c7998d02
+e6ccc900ffffff00ecf3f500e8ecef00d9dcde00d2d4d600cbcccd00c4c5c500b4b4b403
+abacad00b4b4b401978481008a635800795b54038a635800b78d8500c8938400b8938b00
+c8938400b8938b01c8938400b8938b00c7998d00b8938b00c7998d02b99a9400c7998d00
+b99a9400c8938400b99a9400c7998d00b99a9400c7998d01b99a9400c7998d01b8938b00
+c7998d00b99a9400c8938400b99a9400b8938b00c8938400c8a49d00f7ece700ffffff1e
+ecf3f500e8ecef00e0e4e700d9dcde00cbcccd00c4c5c500bbbcbd00b4b4b400a4a5a404
+867c7b0076524a01684f490076524a068a635800a7847c02b9857800a7847c00a77c7000
+a7847c02a77c7000a7847c00a77c7000a7847c00a77c7001a7847c00a77c7000a7847c01
+a77c7000cbcccd00e8ecef00d9dcde00d2d4d600cbcccd00bbbcbd00b4b4b400abacad00
+9c9e9c02999393009c9e9c0077646000795b540076524a00795b540076524a00795b5400
+76524a00795b5405986d6200b78d8501b8938b00b78d8500b8938b00a88c8600b78d8501
+a7847c00b78d8500a7847c00b9857800a7847c00b9857800a7847c01a77c7000a7847c02
+e6dcdc00ffffff0fecf3f500e8ecef00c4c5c500986d6200876d6700986d62008a635800
+97746b00876d670097746b00986d620097746b0c986d620076524a00795b540276524a00
+795b540076524a00795b540176524a00795b540176524a0077646000e8ecef00ffffff15
+f4f6f900ecf3f500b7a4a000986d620097746b05987c7501a77c7000987c7501a77c7000
+987c7501a77c7000987c7500a77c7000987c7502a77c700087747000795b5409b8adaa00
+e8ecef04d9dcde01b7a4a000987c7500a77c7000987c7500a77c7000987c7500a77c7000
+97746b00987c7502a77c7000987c7501a77c7000a7847c00a77c7000a7847c04876d6700
+885a4e0077646000795b540177646000885a4e0077646000795b540097746b00ffffff17
+f4f6f900ecf3f500e0e4e700e6dcdc00cbcccd00a88c8600b98a7c00a88c8602b98a7c00
+a88c8600b78d8500a88c8600b78d8501a8949000b78d8500a88c8600b8938b00a88c8600
+b78d8500a88c8600b78d8500a88c8600b8938b00978481008a635800776460008a635800
+776460008a635800ffffff12f4f6f900e0e4e701d9dcde00b7a4a000b78d8500a88c8600
+b98a7c00a88c8600b9857800a88c8600b98a7c00a88c8600b98a7c00a88c8600a7847c00
+b78d8500a88c8600b78d8500b8938b11b78d8500b8938b00b78d8500b8938b00b98a7c00
+b78d8501987c7500795b5402d7c4bd00ffffff15f4f6f900ecf3f500e8ecef00d9dcde00
+d2d4d600d8cccb00cbcccd00c4c5c500cbcccd00c4c5c500cbcccd00c4c5c500cbcccd00
+b8adaa00b78d8501a88c8600b78d8500a88c8600b78d8500a88c8600b8938b00b78d8500
+b8938b01b78d8500b8938b02b78d8508a88c8600b78d8500a88c8600b78d8501a88c8600
+b78d8501a88c8600b78d8500b8938b00a88c8600b78d8500a88c8600b78d8500a88c8601
+b9857800c8aca500ffffff11f4f6f900e8ecef00e0e4e700d9dcde00d2d4d600cbcccd00
+c4c5c501bbbcbd00c6bcba00bbbcbd01c4c5c500bbbcbd01b8adaa00876d670097746b00
+b99a9402c7998d00b99a9404b8938b14b78d8500b8938b01a88c8600b8938b01a88c8600
+b8938b08c7998d00b99a9401c7998d00b99a9401c7998d01b99a9400c7998d00b99a9400
+c7998d00b99a9401d7c4bd00ffffff01ecf3f500e8ecef00e0e4e700d2d4d600cbcccd00
+c4c5c500b4b4b405abacad00a4a5a400795b540177646000885a4e00795b5401a7847c00
+b8938b00b99a9400b8938b00b99a9403c7998d00b99a9400c7998d00b99a9401c7998d00
+b99a9400c7998d00b99a9400c7998d00b99a9400c7998d00b99a9400b8938b00c7998d00
+b99a9400c7998d00b8938b00c8938400b8938b02c8938400d7c4bd00ffffff20f4f6f900
+ecf3f500e0e4e700d9dcde00cbcccd00c4c5c500bbbcbd00abacad019c9e9c00a4a5a402
+87747000684f490176524a00684f490076524a00684f490076524a038a635800b98a7c00
+a7847c05a77c7001987c7500a77c700097848100a77c7000a7847c06cbcccd00e0e4e700
+d9dcde00d2d4d600c4c5c500bbbcbd00b4b4b400abacad00a4a5a4009c9e9c02a89a9500
+7764600076524a00684f4900795b5400684f490076524a04795b540076524a01876d6700
+a88c8602b78d8500a88c8600b78d8500a88c8601b78d8500a7847c00a88c8600a7847c03
+a77c7000a7847c01a77c7000a7847c00e6dcdc00ffffff0ef4f6f901e8ecef00e0e4e700
+987c7500876d6702986d6200876d6700986d62008774700097746b0d795b540176524a01
+795b540076524a00795b540076524a00684f4900795b5400684f490076524a00684f4900
+76524a00a8949000ffffff15f4f6f900e6dcdc00987c7500876d670097746b0087747000
+97746b05987c7501a77c7000987c7501a77c7000987c7502a77c7000987c7500a77c7000
+987c750097746b00795b5409b8adaa00f7ece700e8ecef03e6dcdc00d9dcde00c6bcba00
+987c750097746b01987c750097746b00987c750097746b06987c7502a77c7000987c7500
+a7847c02987c7500795b540077646000795b54008a635800795b540077646000795b5400
+77646001c6bcba00ffffff16f4f6f900e8ecef00e0e4e700d9dcde00b7a4a000a88c8601
+a7847c01a88c8601b78d8500a88c8600b78d8500a88c8600b78d8500a88c8600b78d8500
+a88c8600b78d8500a88c8600b78d8500a88c8600b8938b00a88c8600b78d850097746b00
+776460008a63580077646000885a4e00978c8a00ffffff11f4f6f900e8ecef00e0e4e700
+d9dcde00c8aca500a7847c01a88c8600a7847c00a88c8603a7847c00a88c8600b98a7c00
+a88c8601b78d8500a88c8601b8938b00a88c8600b8938b00a8949000b8938b0bb78d8500
+b8938b00a88c8600b78d8501a88c8600b78d8500a88c8600b9857800876d6700795b5401
+77646000f7ece700ffffff15f4f6f900e0e4e701d9dcde00d2d4d600d8cccb00cbcccd00
+c4c5c503cbcccd00c6bcba00a8949000a88c8601b78d8500a8949000b78d8500a8949000
+b78d8500a8949000b8938b00b78d8500a8949000b78d8500b8938b00b78d8500b8938b00
+b78d8502a88c8600b78d8500a88c8601b78d8500b8938b00b78d8501a88c8601b78d8500
+a88c8601b78d8500a88c8601b78d8500a88c8600b78d8500a88c8600a7847c00a88c8600
+a7847c00f4f6f900ffffff12f4f6f900e8ecef00e0e4e700d2d4d600cbcccd01c4c5c502
+bbbcbd00c4c5c500bbbcbd00c6bcba00bbbcbd01b8adaa00776d6b00a77c7000b99a9406
+b8938b00b99a9400b8938b03a8949000b8938b07b78d8501a88c8600b78d8500b8938b00
+a88c8600b8938b00a88c8600b8938b00a88c8600b8938b01a8949000b8938b0ab99a9400
+b8938b00b99a9406c7998d00b99a9401e5c4c200ffffff02f4f6f900e8ecef00e0e4e700
+d9dcde00cbcccd00c4c5c500bbbcbd00b4b4b406876d6700795b54037764600097746b00
+b8938b02b99a9400b8938b00b99a9400b8938b00b99a9400c7998d00b99a9401c7998d00
+b99a9402c7998d00b8938b00b99a9400b8938b00c7998d00b99a9400c7998d00b8938b00
+c7998d00b8938b00b99a9400b8938b00b99a9400c8a49d00f4f6f900ffffff15e8ecef00
+876d6700867c7b00a89a9500c7b5b100d2d4d600f4f6f900ffffff04ecf3f500e8ecef00
+e0e4e700d2d4d601c4c5c500bbbcbd00b4b4b400a4a5a4048774700076524a00684f4903
+76524a00684f49038a635800a7847c05987c7500a77c7000987c7500a77c7001987c7500
+a7847c01987c7500a7847c04cbcccd00e0e4e700d9dcde00d2d4d600cbcccd00bbbcbd00
+b4b4b400abacad009c9e9c0477646000684f4902795b5400684f4901795b5400684f4901
+76524a00675c5a0076524a008a635800a88c8601a7847c00a88c8601a7847c00b78d8500
+a7847c00a88c8600a7847c00b78d8500a7847c08e6dcdc00ffffff0ff4f6f900ecf3f500
+e8ecef00b99a9400986d6200876d6700986d6200876d670197746b00876d670097746b00
+876d670097746b00876d670097746b008774700097746b0087747000986d620087747000
+986d62008774700097746b00877470008a635800684f4900795b5400684f4904795b5400
+684f4901795b5400684f4901795b5400d9dcde00ffffff14ecf3f500b8adaa00876d6702
+97746b008774700297746b00987c7505a7847c00987c750097746b00987c750597746b00
+795b540376524a00795b5402684f4900795b5400b8adaa00ecf3f501f7ece700ecf3f500
+e8ecef00e0e4e700d9dcde00d2d4d600a7847c0097746b07876d670097746b02987c7500
+97746b00987c7502a7847c0097848100a7847c01876d67008a63580077646000795b5400
+77646000795b540077646000885a4e00795b5400776d6b00f4f6f900ffffff14f4f6f900
+ecf3f500e8ecef00e6dcdc00cbcccd00a88c8601a7847c00a88c8604a8949000a88c8600
+a8949000a88c8604b8938b00a88c8602b78d8500a88c86008a635800795b540077646000
+795b540077646000d8cccb00ffffff10f4f6f900e8ecef00e0e4e701c6bcba00a7847c02
+a88c8600a7847c00a88c8600a7847c01a88c8600a7847c00a88c8600a7847c00a88c8600
+a7847c00a88c8601b78d8500a88c8600a8949000b78d8500a8949000b8938b00a8949003
+b8938b00a8949000a88c8600a8949000b78d8500a8949000a88c860a8a635800795b5401
+87747000ffffff15f4f6f900ecf3f500e0e4e700d9dcde00d2d4d600cbcccd02c4c5c500
+cbcccd00c4c5c501cbcccd00b7a4a000b8938b00a88c8600a8949000a88c8601b78d8500
+a88c8603b78d8500a88c8605b78d8500a88c8600b78d8500a88c8600b8938b01a8949000
+b8938b00a8949000b78d8500a88c8600b8938b00a88c8603b78d8500a88c8604a7847c00
+c8a49d00ffffff13f4f6f900ecf3f500e0e4e700e6dcdc00d2d4d600cbcccd00c4c5c502
+bbbcbd00c6bcba00bbbcbd01c4c5c500bbbcbd01a4a5a400876d6700a7847c00b99a9404
+b8938b00a89a9500b8938b00a8949002b8938b00a8949000b8938b00a8949000a88c8600
+a8949000b78d8500a8949000a88c8600a8949000a88c8601b78d8500a88c8602b78d8500
+a8949000b8938b00a8949000b8938b00a8949000b8938b00a8949000b8938b00a89a9500
+b8938b00a89a9500b8938b01a8949000b8938b00a8949000b8938b00a8949000b8938b01
+b99a9405b8938b00b99a9400d7c4bd00ffffff03f4f6f900ecf3f500e0e4e700d2d4d601
+c4c5c500bbbcbd00b4b4b403abacad00b4b4b401978c8a00795b540077646000795b5400
+77646000795b54008a635800a8949000b99a9402b8938b00b99a9406b8938b00c7998d00
+b99a9401c7998d00b99a9400c7998d00b99a9403b8938b00b99a9400b8938b00c7998d00
+e9d5d700ffffff16e6dcdc0077646000795b5400684f4900795b5400675c5a0076524a00
+795b5401987c7500a89a9500b4b4b400e8ecef00f4f6f900ecf3f500e0e4e700d9dcde00
+cbcccd00c4c5c500bbbcbd00abacad01a4a5a40387747000684f490776524a00684f4900
+8a635800a7847c01987c7500a77c7000987c7500a77c7000987c7500a77c7000987c7500
+a7847c00987c7500a77c7000987c7500a7847c02987c7500a7847c02cbcccd00e0e4e700
+d9dcde00d2d4d600c4c5c500bbbcbd00b4b4b400abacad009c9e9c0477646000684f4900
+76524a00684f4905795b5400684f490076524a00684f4900876d6700a88c8600a7847c02
+a88c8600a7847c00a88c8600a7847c02a88c8600a7847c02987c7500a7847c03987c7500
+d9dcde00ffffff0ff4f6f900ecf3f500e8ecef00c4c5c50087747000876d670397746b00
+87747001986d6200876d670187747000876d6700986d6200876d6703986d6200876d6702
+795b5400684f4901795b5400684f4900795b5400684f4901795b5400684f4901675c5a00
+684f490187747000f4f6f900ffffff12f4f6f900e0e4e70097746b00876d6700986d6200
+876d670297746b0187747000987c750a97746b00987c75028774700076524a00795b5401
+76524a00675c5a00795b5400684f4900675c5a00795b5400684f4900b4b4b400ecf3f502
+f4f6f900e8ecef00e0e4e700d9dcde00d2d4d600b7a4a000876d67008774700097746b00
+876d670097746b00876d670097746b00876d67008774700197746b008774700097746b00
+987c750497848100a7847c01987c750077646001795b540177646000795b540077646001
+795b540097848100ffffff14f4f6f900e8ecef00e0e4e700d9dcde00b99a9400a88c8600
+a7847c01a88c8600a7847c00a88c8602b78d8500a88c8602b78d8500a88c8600b8938b00
+a88c8602b98a7c00a88c8601987c7500776460008a635800776460008a63580087747000
+ffffff10f4f6f900e8ecef01e0e4e700c4c5c500a88c8600a7847c0097848100a7847c01
+a88c8600a7847c0497848100a7847c00a88c8600a7847c00a88c8605a8949002b8938b00
+a8949000b8938b00a8949000b8938b00a8949000b78d8500a8949000a88c8603a7847c03
+a88c860397848100795b540177646000978c8a00ffffff15f4f6f900e8ecef00d9dcde01
+d2d4d600cbcccd01c4c5c502cbcccd00c4c5c500c6bcba00a8949001a88c860fa8949001
+b8938b00a8949001b8938b00a8949000b8938b00a8949000b8938b00a8949000a88c8601
+b8938b00a88c8605a7847c00a88c8600f7ece700ffffff14f4f6f900e8ecef00e0e4e700
+d9dcde00d2d4d600cbcccd00c4c5c502bbbcbd00c4c5c500bbbcbd01c4c5c500bbbcbd00
+c6bcba00a89a9500776d6b00a88c8600b99a9401a8949000b99a9400a8949000b8938b00
+a8949001b8938b00a88c8603a8949000b78d8500a88c8601a8949000b78d8500a88c8600
+b78d8500a88c8607b8938b00a88c8600a8949000b8938b00a8949002b8938b00a8949000
+b8938b00a8949000b8938b00a8949000a88c8601b8938b00a8949000b8938b00a8949000
+b8938b00b99a9400b8938b00b99a9401b8938b00e9d5d700ffffff04f4f6f900ecf3f500
+e8ecef00d9dcde00cbcccd01bbbcbd01b4b4b400abacad00b4b4b403a4a5a400795b5405
+a88c8600b8938b00b99a9407c7998d00b99a9403b8938b00b99a9400b8938b00b99a9401
+b8938b00c7998d00b99a9400b8938b00b99a9400c8aca500ffffff17c4c5c500675c5a00
+684f4904795b5400684f4900675c5a0176524a0087747000c6bcba00ecf3f500e8ecef00
+e0e4e700d9dcde00d2d4d600c4c5c500bbbcbd00b4b4b400a4a5a40487747000684f4900
+55454100684f49007c3a3c00684f49057764600097848100a7847c00987c7500a7847c01
+987c7500a7847c00987c750097848100a77c7000987c7501a7847c00987c7500a7847c00
+97848100a7847c0197848100a7847c00cbcccd00e0e4e700d9dcde00d2d4d600c4c5c500
+bbbcbd00b4b4b400abacad009c9e9c0477646000684f490b8a635800a7847c0097848100
+a7847c05a88c8600a7847c0297848100a7847c0097848100a7847c0097848100a7847c00
+97848100a7847c00e6dcdc00ffffff0ff4f6f901e8ecef00e0e4e700987c7500876d6707
+87747000986d6200876d67028a635800876d67038774700097746b00876d6701684f4900
+675c5a00684f4901675c5a00684f490899939300ffffff12ecf3f500a89a950087747000
+876d670397746b008774700197746b008774700097746b008774700097746b0087747000
+97746b008774700097746b0187747000987c750097746b00987c750097746b00987c7500
+876d670076524a00675c5a00684f4900675c5a0076524a00684f4900675c5a00684f4902
+b4b4b400f4f6f902ecf3f501e8ecef00e0e4e700d9dcde00c4c5c50097746b00876d6702
+8774700097746b00876d670087747000986d62008774700197746b00987c750097746b00
+987c750297848101a7847c00978c8a00a7847c00987c7500795b540077646001795b5400
+77646000795b540077646002a89a9500ffffff12f4f6f901e8ecef00e0e4e700c7b5b100
+978c8a00a7847c00978c8a00a7847c00a88c861197746b0077646000795b540077646001
+b8adaa00ffffff10ecf3f500e8ecef00e6dcdc00d2d4d600a8949000a7847c0097848101
+a7847c0097848102a7847c00978c8a0097848100a7847c0097848103a7847c00978c8a00
+a7847c00a88c860fa7847c00978c8a00a88c860097848100a88c8603a8949000a88c8600
+a8949000987c750077646000795b5401b8adaa00ffffff14f4f6f900e8ecef00e0e4e700
+d9dcde00d2d4d600d8cccb00cbcccd00c4c5c500d8cccb00c4c5c501cbcccd00c4c5c500
+b7a4a000a8949000a88c860eb8938b00a88c8600b78d8500a8949000a88c860da7847c00
+a88c8600a7847c00a88c8600b99a9400ffffff16ecf3f500e8ecef00d9dcde01d2d4d600
+cbcccd00c4c5c501bbbcbd00c4c5c500bbbcbd00c4c5c500bbbcbd03a4a5a40077646000
+a88c8600a8949004a88c8613a8949000a88c8600a8949002b8938b00a88c8600a8949000
+b8938b00a8949001b99a9400a8949000b8938b00a8949000b8938b00a89a9500b8938b00
+a8949000b8938b00a89a9500b99a9401a8949000b99a9402e0e4e700ffffff06ecf3f500
+e0e4e701d2d4d600cbcccd00c4c5c500bbbcbd00b4b4b402abacad00b4b4b401b8adaa00
+8774700077646000795b540177646000795b540087747000b8938b01b99a9403b8938b00
+b99a9400b8938b00b99a9401b8938b00b99a9407b8938b00b99a9401e6dcdc00ffffff0f
+f4f6f901ecf3f501f4f6f901ffffff00f4f6f9009c9e9c00684f490a87747000a88c8600
+a8949000e0e4e700ecf3f500e0e4e700d9dcde00cbcccd00c4c5c500bbbcbd00abacad01
+a4a5a40377747400684f490055454100684f4900584c4800684f490055454100684f4903
+885a4e0097848100a77c700097848101987c7500a7847c0097848100a77c700097848100
+a7847c0097848100a7847c0097848100a7847c0097848100a7847c01978c8a00a7847c00
+a88c8600cbcccd00e0e4e700d9dcde00d2d4d600c4c5c500bbbcbd00b4b4b400a4a5a401
+9c9e9c01a89a95009c9e9c0077646000684f490b77646000a7847c00987c750097848103
+a7847c0097848100a7847c0097848100a7847c0097848100a7847c0097848102a7847c00
+97848100a7847c00978c8a00e6dcdc00ffffff10f4f6f900e8ecef01b7a4a000876d6701
+8a635800876d6709776d6b008a635800876d670677646000684f490a584c4800684f4901
+a89a9500ffffff10f4f6f900d8cccb00876d67078774700097746b0087747001987c7500
+8774700097746b00867c7b0097746b00867c7b0097746b00867c7b0097746b00867c7b00
+8774700197746b00876d6700675c5a00684f4902675c5a00684f4904b8adaa00f4f6f904
+e8ecef00e0e4e700d9dcde00d2d4d60099939300986d6200876d670797746b0087747001
+987c7500867c7b00987c750097848100987c750097848101a7847c0097848101876d6700
+795b540077646004675c5a00795b540077646000978c8a00ffffff11f4f6f900e8ecef00
+e0e4e700cbcccd00978c8a00a7847c0097848101a88c8600978c8a00a7847c00978c8a00
+a88c8601a8949000a88c8601a8949000a88c8607a7847c0077646004ffffff10e8ecef01
+e0e4e700d9dcde00a89a950097848105a7847c0097848106a7847c0097848101a7847c00
+97848100978c8a00a88c8600978c8a00987c750077646000a88c8601a8949000a88c8608
+a7847c0097848100a88c860097848100a88c8605a89490008774700077646000675c5a00
+795b5400d9dcde00ffffff13f4f6f901e8ecef00e0e4e700d2d4d601cbcccd01c4c5c500
+cbcccd00c4c5c502c6bcba00a8949000a88c8603a7847c00978c8a00a7847c00a88c8609
+a8949000a88c8601a8949001a88c8600a8949000a88c8607978c8a00a88c860097848100
+a88c860097848100e8ecef00ffffff16f4f6f901e0e4e700d9dcde00d2d4d600cbcccd01
+c4c5c502bbbcbd01c6bcba00bbbcbd00c4c5c500bbbcbd00c6bcba00a4a5a400876d6700
+978c8a00b8938b00a88c8600a8949000a88c8601a8949000a88c8603978c8a00a88c860a
+a8949000a88c8604a8949004a89a9500b8938b00a8949001a89a9500b99a9400a89a9500
+b8938b00a89a9500b99a9400a89a9500b99a9401a89a9500b99a9401b7a4a000ffffff08
+f4f6f900ecf3f500e0e4e700d9dcde00cbcccd00c4c5c500bbbcbd00b4b4b405abacad00
+99939300795b540077646000675c5a00795b540177646000a8949000b99a9400b8938b00
+b99a9400b8938b00b99a9403b8938b00b99a9403b8938b01b99a9400b8938b01b99a9400
+b8938b00c7b5b100ffffff10ecf3f501e8ecef03ecf3f500e0e4e700867c7b0055454103
+584c4802684f4900584c4800684f490197746b00a88c860097848100a7847c00bbbcbd00
+e8ecef00e0e4e700d2d4d601c4c5c500b4b4b401a4a5a4048774700055454100684f4900
+55454100684f4900584c48007c3a3c00684f490055454101684f4900795b5400a77c7000
+97848100987c7500a7847c00987c750097848100a7847c0097848100987c750097848100
+987c750097848100a7847c0097848101a7847c0097848100a88c8601978c8a00cbcccd00
+e0e4e700d9dcde00d2d4d600c4c5c500bbbcbd00b4b4b400abacad009c9e9c0099939300
+9c9e9c02675c5a0055454104684f49068a63580097848100987c7502a77c700097848100
+a7847c00978c8a00a7847c0097848103987c7500a7847c0097848103a7847c00d9dcde00
+ffffff10f4f6f900ecf3f500e8ecef00cbcccd00876d6701776d6b008a635800876d6705
+776460008a635800776d6b0077646000776d6b008a635800776d6b00876d670287747000
+876d6701684f4904584c4800684f4900584c4800684f4900584c4800684f4901584c4801
+684f4900867c7b00e8ecef00ffffff0ed9dcde0087747000876d6703776d6b00876d6703
+8774700497746b0087747000867c7b008774700197746b008774700297746b00867c7b00
+876d6700684f4907584c4800684f4900b4b4b400f4f6f900ffffff00f4f6f902e8ecef00
+e0e4e700e6dcdc00d2d4d600b4b4b400876d670087747000876d67068774700197746b00
+867c7b0097746b00867c7b00987c750097848101a7847c0097848101a88c860097848100
+776d6b0077646000795b5400675c5a00795b540077646000795b5400675c5a0077646000
+795b540087747000d2d4d600ffffff0ef4f6f900ecf3f500e0e4e700d8cccb00a88c8600
+97848106a88c8600978c8a00a88c8602a8949000a88c8601a8949000a88c8602a8949000
+a88c8601867c7b0077646000795b540077646000795b5400a4a5a400ffffff0ff4f6f900
+e8ecef00e0e4e700e6dcdc00b8adaa0097848100987c750097848100987c750097848104
+987c750097848100987c750097848101987c750097848102978c8a00a7847c0097848100
+a88c86009784810077646000675c5a00978c8a00a88c8600978c8a00a88c8600978c8a01
+a88c8600978c8a01a88c8600978c8a01a88c8600978c8a00a7847c00978c8a00a88c8600
+978c8a00a88c8601a8949001a88c8601776d6b00795b5400675c5a0077646000ffffff14
+f4f6f900e8ecef00e0e4e700d9dcde00d2d4d600cbcccd00c4c5c500cbcccd00c4c5c501
+cbcccd00c4c5c501a89a9500a88c8600978c8a00a7847c00978c8a0097848100a88c8600
+97848100a88c8600978c8a00a7847c00978c8a0097848100a88c8600978c8a00a88c8600
+978c8a00a88c8609978c8a00a88c860097848100978c8a00a7847c00978c8a00a7847c00
+97848100978c8a0097848100a8949000ffffff18f4f6f900e8ecef01d9dcde00d2d4d601
+cbcccd00c4c5c501bbbcbd00c4c5c500bbbcbd01c6bcba00bbbcbd02a4a5a40087747000
+97848100a8949000a88c8603978c8a01a88c860097848100a7847c00978c8a0097848100
+978c8a00a88c8600978c8a00a88c8600978c8a00a88c8600978c8a00a88c8600978c8a00
+a88c8602a8949000a88c8600a8949000b8938b00a8949000b8938b00a8949001b8938b00
+a8949000a89a9500b99a9400a8949001a89a9500b99a9400a89a9500b99a9400a89a9500
+b99a9400a89a9500b99a9400a89a9500c4c5c500ffffff09f4f6f900ecf3f500e0e4e700
+d9dcde00d2d4d600c4c5c500bbbcbd01b4b4b402abacad00b4b4b401abacad0077646000
+675c5a00795b5400675c5a0077646000795b5400a88c8600a89a9500b99a9400a89a9500
+b99a9401a8949000b99a9401a8949000b99a9400b8938b00b99a9400a8949000b99a9401
+a89a9500b99a9400a89a9500b99a9401d8cccb00ffffff0ef4f6f900ecf3f500e0e4e702
+d9dcde00e0e4e701b4b4b400675c5a0055454109684f4900867c7b0097848103a8949000
+e0e4e701d9dcde00cbcccd00c4c5c500bbbcbd00b4b4b400a4a5a40487747000684f4900
+584c480055454100684f490055454100584c4800684f490055454100684f490055454100
+795b540097848100987c750097848100987c750097848100987c750097848106a7847c00
+978c8a0097848100a88c860097848100a88c860097848100d2d4d600e0e4e700d2d4d601
+c4c5c500bbbcbd00b4b4b400a4a5a4019c9e9c03675c5a0055454102684f490055454105
+684f49005545410077646000987c750297848100987c750197848104987c750097848100
+987c750097848100987c750097848100a7847c0097848101e6dcdc00ffffff10f4f6f900
+ecf3f500e8ecef00e0e4e700978c8a0077646000876d670077646000776d6b0077646001
+776d6b0077646000776d6b0077646000776d6b008a63580077646001776d6b0077646002
+776d6b00876d670077646001876d6700675c5a00584c4800684f4900584c4800684f4900
+584c4800684f4900584c4800684f4900584c4802684f4900584c480177646000bbbcbd00
+ffffff0cd9dcde00867c7b00876d6701776d6b00876d6700776d6b00876d6701776d6b00
+876d670087747000876d67008774700597746b0087747003876d67018774700177646000
+684f4902584c4800684f4900584c4804b4b4b400ffffff03f4f6f901e0e4e701d9dcde00
+d8cccb0097848100876d670787747004867c7b00987c750397848104876d6700675c5a00
+795b540077646000675c5a0077646000675c5a0077646000675c5a01795b540099939300
+f4f6f900ffffff0bf4f6f901e8ecef00c4c5c50097848101987c750097848100987c7500
+97848102a7847c0097848101a88c8600978c8a00a88c8600978c8a00a88c8600978c8a00
+a88c860199939300a88c860199939300a88c860077646004f4f6f900ffffff0ef4f6f900
+e8ecef00e0e4e700d9dcde00c6bcba0097848108867c7b00987c7500867c7b00987c7500
+867c7b00987c750097848100987c750097848101a7847c00978c8a01a88c8600776d6b00
+76524a00867c7b00c4c5c500a89a950097848100978c8a0097848100a88c8600978c8a00
+a88c8600978c8a00a88c8600978c8a00a88c8600978c8a00a88c8600978c8a00a88c8600
+97848100978c8a01a88c860099939300a88c8600a8949000a88c8600978c8a0077646000
+684f4900675c5a00867c7b00ffffff14e8ecef01d9dcde00d2d4d601d8cccb00c4c5c500
+cbcccd00c4c5c503bbbcbd0097848100a88c860097848101a88c860097848100a88c8600
+978c8a00a88c860097848100a88c860097848100a7847c0097848100978c8a00a7847c00
+978c8a0097848100978c8a03a88c8600978c8a00a88c860097848100978c8a0097848101
+a7847c00978c8a0097848100978c8a01a7847c00978c8a00e9d5d700ffffff19f4f6f900
+e8ecef00e0e4e700d9dcde00d2d4d600cbcccd01c4c5c502bbbcbd00c4c5c500bbbcbd01
+c4c5c500bbbcbd00c6bcba00b8adaa00776d6b0097848100a8949001a88c8600978c8a00
+a88c8600978c8a00a7847c0097848102a7847c0097848102a88c8600978c8a00a88c8600
+978c8a00a88c8601978c8a00a88c8600978c8a00a88c8600a8949000a88c8600a8949001
+a89a9500b99a9400a89a9501b99a9400a89a9500a8949001a89a9500b8938b00a89a9500
+b99a9400a8949000b99a9400a89a9500b99a9400a89a9500d7c4bd00ffffff0becf3f500
+e8ecef00d9dcde00d2d4d600c4c5c501bbbcbd00b4b4b404abacad00b4b4b40088848400
+795b5400675c5a0077646000795b5400675c5a00876d6700a8949001b99a9400a89a9500
+a8949000b99a9400a8949000a89a9500b99a9401a89a9500a8949000b99a9400a89a9500
+b99a9400a8949000b99a9401a8949000a89a9500b99a9400e6dcdc00ffffff0cecf3f501
+e0e4e701d9dcde00d2d4d601cbcccd008c8b8c005545410a684f490087747000987c7502
+97848100987c750088848400c4c5c500e0e4e700d9dcde00d2d4d600c4c5c500bbbcbd00
+b4b4b400a4a5a4048774700055454100684f490055454100684f4900584c4800684f4900
+55454100684f490055454100584c4800795b5400987c750097848101987c750097848100
+987c750097848100987c750197848104a88c860097848100978c8a01a88c8600978c8a00
+cbcccd00e0e4e700d9dcde00d2d4d600c4c5c500bbbcbd00abacad019c9e9c0476524a00
+5545410b795b5400867c7b00987c7500867c7b00987c750197848100987c750297848100
+987c750097848100987c750197848101987c750097848102d9dcde00ffffff11f4f6f900
+e8ecef01c6bcba00776d6b00776460028a635800776d6b008a63580077646006795b5400
+77646004776d6b0077646002795b5400584c4800684f4900584c4800684f4900584c4801
+684f4900584c4800684f490055454100584c480055454100584c48005545410187747000
+cbcccd00ffffff09c4c5c50087747000876d670077646000876d6700776d6b0077646000
+876d6700776d6b00876d670177747400876d670087747000876d670087747003867c7b00
+87747003876d670077747400876d67018774700077646000584c4804684f4900584c4801
+684f4900584c4800b4b4b400ffffff03f4f6f900ecf3f500e8ecef00e0e4e700d9dcde00
+d2d4d600b8adaa0077646000876d6700776d6b00876d6700776d6b00876d6701776d6b00
+876d670087747003987c750087747000867c7b0088848400987c750088848400987c7501
+97848101978c8a00987c750077646000675c5a00795b5400675c5a00795b5400675c5a00
+77646001675c5a0077646000675c5a009c9e9c00f7ece700ffffff08f4f6f901e0e4e700
+b7a4a00097848101867c7b0097848103987c7500978c8a0097848100978c8a00a88c8600
+978c8a00a88c8600978c8a00a88c8600a8949000978c8a00a88c8600978c8a00a88c8600
+99939300978c8a00a88c86008774700077646001675c5a0077646000a89a9500ffffff0e
+f4f6f900e8ecef01e0e4e700cbcccd00978c8a0097848107987c7500867c7b00987c7500
+867c7b00987c7500867c7b009784810188848400987c750097848102a7847c0087747000
+684f4900675c5a00c4c5c500d8cccb00c6bcba00a88c8600978c8a0097848100978c8a00
+97848100a88c8600978c8a01a88c8600978c8a00a88c8600978c8a01a88c8600978c8a00
+a88c8601978c8a00a88c8600a894900099939300a88c8600978c8a0097848100675c5a00
+684f490199939300ffffff13f4f6f900e8ecef00e0e4e700d9dcde00d2d4d600cbcccd01
+c4c5c500cbcccd00c4c5c501d7c4bd00c4c5c500a894900097848104978c8a00a7847c00
+978c8a0197848101978c8a00a7847c0097848100978c8a0097848103a7847c00978c8a01
+a88c8600978c8a0097848106a7847c0097848101a8949000ffffff1bf4f6f900e8ecef00
+e0e4e700d9dcde01cbcccd01c4c5c501bbbcbd01c4c5c500bbbcbd03b4b4b400684f4901
+87747000978c8a01a7847c00978c8a0097848101978c8a0097848103a7847c00978c8a01
+a88c8600978c8a00a88c8600978c8a00a88c8600978c8a00a88c8600a894900199939300
+a8949003a89a9500a8949000a89a9500a8949000a89a9500b99a9400a89a9504b99a9400
+a89a9503a8949000e6dcdc00ffffff0aecf3f500e8ecef00e0e4e700d9dcde00cbcccd00
+c4c5c500bbbcbd00b4b4b401abacad00b4b4b403a4a5a400675c5a01684f4900675c5a00
+795b5400675c5a00a88c8600a8949004b99a9400a8949000a89a9500a8949000b99a9400
+a89a9500a8949000a89a9500a8949000a89a9500b99a9400a89a9500a8949000b99a9400
+a8949000a89a9500e0e4e700ffffff09ecf3f501e8ecef00e0e4e700d9dcde00d2d4d601
+cbcccd00abacad00636465005545410a77646000987c7500867c7b01987c7500867c7b00
+987c75019784810099939300e0e4e700d9dcde00cbcccd00c4c5c500bbbcbd00b4b4b400
+a4a5a40477747400584c480055454100684f490055454100684f490055454100684f4900
+55454100684f4901675c5a0097848100987c750197848100867c7b0097848100987c7500
+8884840097848100987c750097848106978c8a0097848100978c8a00cbcccd00e0e4e700
+d9dcde00cbcccd00c4c5c500bbbcbd00b4b4b400a4a5a4009c9e9c0399939300675c5a00
+5545410b76524a0087747000987c750087747000987c7500867c7b0087747000867c7b00
+987c7500867c7b00987c7501867c7b02987c750088848400987c750097848100987c7500
+978c8a00e6dcdc00ffffff11f4f6f900ecf3f500e8ecef00e6dcdc00867c7b0077646004
+675c5a0077646000795b540077646002795b54007764600c684f4900584c480455454101
+584c480055454102584c48005545410277747400bbbcbd00ffffff05e0e4e700a89a9500
+77646000876d6700776d6b0177646000876d6700776d6b0077646000776d6b01876d6700
+776d6b00876d6700776d6b0087747000876d6700877470097774740087747000776d6b00
+77646000684f4900584c4801684f4900584c4805b4b4b400ffffff04f4f6f900e8ecef00
+e0e4e701d2d4d600cbcccd00867c7b00876d670077646000876d6701776d6b00876d6701
+776d6b0087747000876d670087747000876d670087747000867c7b0087747000867c7b00
+987c7500867c7b01888484009784810288848400987c750087747000675c5a0077646000
+675c5a0077646000675c5a03795b5400675c5a01978c8a00c4c5c500ffffff05f4f6f900
+ecf3f500c6bcba00978c8a0088848400987c75008884840097848100867c7b0097848100
+867c7b0097848104978c8a02a88c8600978c8a01a88c8600978c8a0099939300a88c8600
+978c8a00a88c8600978c8a0077646000675c5a0077646000675c5a0077646000f4f6f900
+ffffff0ee8ecef01e6dcdc00d2d4d600a8949000978c8a0097848103978c8a0097848101
+978c8a009784810088848400987c750088848400867c7b00987c7500867c7b00987c7500
+9784810188848400987c750097848100867c7b00684f490054545500b8adaa00cbcccd01
+c4c5c500b8adaa0097848100a88c860097848100a88c8600978c8a01a88c8600978c8a00
+a88c860099939300a88c8600978c8a00a88c8600978c8a00a88c8600978c8a00a88c8600
+99939300978c8a00a88c8600978c8a0287747000684f490054545500684f4900bbbcbd00
+ffffff12f4f6f901e0e4e700d9dcde00d2d4d600cbcccd01d8cccb00c4c5c501cbcccd00
+c4c5c501b8adaa0097848101978c8a0097848102978c8a0097848101a88c860097848103
+987c750097848101987c75009784810388848400987c750097848101987c750088848400
+987c750097848104d8cccb00ffffff1cf4f6f900e8ecef00e6dcdc00d9dcde00d2d4d600
+cbcccd00c4c5c503bbbcbd00c6bcba00bbbcbd00c4c5c500bbbcbd009c9e9c00584c4800
+684f4900584c480087747000a7847c00978c8a0097848100a88c8600978c8a00a7847c00
+97848100987c750097848101978c8a01a88c860199939300a88c860099939300a88c8600
+99939300a88c860099939300a8949001a89a9506b99a9400a89a9501a8949000b99a9400
+a89a9500b99a9400a89a9503a8949000b99a9400a89a9501e6dcdc00ffffff0aecf3f500
+e0e4e700d9dcde00cbcccd01bbbcbd01b4b4b403abacad00b4b4b401867c7b00684f4900
+675c5a0387747000a8949003a89a9501a8949000a89a9500a8949004b99a9400a8949000
+a89a9500a8949000a89a9500a8949003d2d4d600ffffff06ecf3f502e0e4e701d9dcde00
+d2d4d600cbcccd00abacad006a6c6e00584c480055454105463d3c0055454102684f4900
+876d6700987c7500867c7b00987c7500867c7b06c4c5c500d9dcde00d2d4d600c4c5c500
+bbbcbd00b4b4b400a4a5a4048774700055454100584c480055454104684f490055454100
+584c4800675c5a0097848101867c7b00987c7500867c7b0097848100867c7b00987c7500
+867c7b00987c750088848400987c75008884840097848102978c8a0097848100978c8a01
+cbcccd00e0e4e700d9dcde00d2d4d600c4c5c500bbbcbd00b4b4b400abacad009c9e9c03
+a89a9500675c5a00554541047c3a3c0055454105675c5a00867c7b0087747002867c7b00
+87747001867c7b0087747000867c7b0087747000867c7b00987c7500867c7b00987c7500
+867c7b0097848102978c8a00d9dcde00ffffff12f4f6f900e8ecef00e0e4e700b8adaa00
+77646001675c5a00795b5400675c5a0077646000795b54006364650077646000675c5a00
+77646000636465007764600d675c5a00584c480055454105584c480055454103584c4800
+4544450055454101684f490099939300cbcccd00ecf3f500e8ecef00b4b4b40087747000
+77646000776d6b0077646000776d6b0077646000776d6b0077646001776d6b01876d6700
+776d6b00876d6700777474008774700177747400877470007774740087747001867c7b00
+8774700077747400877470007774740087747000876d6700777474008774700077646000
+584c4803684f4900584c4800684f4900584c4800684f4900584c4800bbbcbd00ffffff04
+f4f6f901e8ecef00e6dcdc00d9dcde00d2d4d600b8adaa00876d6700776d6b00876d6700
+776d6b00876d6700776d6b00876d6700776d6b00876d6700776d6b008774700077747400
+876d670087747001867c7b0087747000867c7b00987c750188848400987c750097848103
+88848400876d6700675c5a00795b5400675c5a00795b5400675c5a0077646000675c5a00
+795b5400675c5a027764600088848400b8adaa00c4c5c500d9dcde00d2d4d600c4c5c500
+a88c860088848400867c7b00987c7500867c7b0097848100867c7b009784810288848400
+987c75008884840097848100978c8a01a88c8600978c8a01a8949000978c8a01a88c8600
+978c8a02a88c8600867c7b0077646000675c5a0077646000675c5a00b4b4b400ffffff0e
+ecf3f500e8ecef00e0e4e700d9dcde00a4a5a400a88c8600978c8a0197848100978c8a00
+97848101978c8a009784810388848400987c7500867c7b01978481008884840097848102
+88848400867c7b00675c5a00684f490097848100d2d4d600cbcccd03a89a950097848100
+978c8a0097848100978c8a00a88c8600978c8a01a88c8600978c8a00a894900099939300
+978c8a00a894900099939300a88c860099939300978c8a00a88c8600978c8a0297848101
+776d6b00684f4900584c480054545500e6dcdc00ffffff12ecf3f500e8ecef00e0e4e700
+d9dcde00d2d4d600cbcccd00c4c5c500cbcccd00c4c5c501cbcccd00c4c5c50197848101
+987c750097848100978c8a009784810688848400867c7b00987c7500867c7b02987c7500
+88848400987c750088848400987c7500867c7b03987c7500867c7b029784810088848400
+97848100ffffff1df4f6f900ecf3f500e8ecef00d9dcde01d2d4d600cbcccd00c4c5c501
+bbbcbd03c6bcba00bbbcbd00867c7b00584c480287747000978c8a0097848100a88c8600
+978c8a0097848104978c8a00a88c8600978c8a00a88c860099939300a88c860099939300
+a88c860099939300a894900099939300a894900199939300a8949000a89a9500a8949000
+a89a9504a8949000a89a9503a8949000a89a9500a8949000a89a9504a8949000a89a9500
+e0e4e700ffffff09ecf3f500e8ecef00e0e4e700d2d4d600cbcccd00c4c5c500bbbcbd00
+b4b4b406a4a5a400675c5a01684f4900675c5a00684f4900675c5a00a8949004a89a9502
+a8949000a89a9500a8949001a89a9500a8949002a89a9500a8949005c6bcba00f4f6f900
+ffffff01f4f6f900ecf3f501e8ecef00e0e4e701d9dcde00d2d4d600b4b4b4008c8b8c00
+675c5a0045444500584c480055454109795b5400867c7b0387747000867c7b00987c7500
+867c7b00987c7500867c7b00987c7500867c7b00a4a5a400d9dcde00cbcccd00c4c5c500
+bbbcbd00b4b4b400a4a5a40477747400584c4804684f490055454102684f4900675c5a00
+987c7500867c7b01987c7500867c7b01987c7500867c7b0088848400987c7500867c7b01
+978481008884840097848105cbcccd00e0e4e700d2d4d601c4c5c500bbbcbd00b4b4b400
+a4a5a4009c9e9c04675c5a00463d3c0055454100463d3c0055454100463d3c0055454106
+76524a00867c7b00987c750087747000867c7b0087747001867c7b0087747001867c7b00
+87747001867c7b0197848100867c7b0097848101978c8a01e6dcdc00ffffff12f4f6f900
+ecf3f500e8ecef00d9dcde007774740077646000675c5a0077646000675c5a0077646000
+675c5a0177646000675c5a0077646003675c5a0077646000675c5a00795b540063646500
+77646002776d6b0077646000776d6b0177646001675c5a00584c480155454100584c4800
+5545410345444500554541004544450055454101454445005545410045444500584c4800
+776d6b00867c7b008774700077646000776d6b0077646000776d6b0077646000876d6700
+776d6b0277646000876d6700776d6b03876d670077747400877470027774740087747001
+867c7b0187747000867c7b0087747000777474008774700177646000584c4802684f4900
+584c480054545500684f4900584c480054545500684f4900b4b4b400ffffff05f4f6f900
+e8ecef00e0e4e701d2d4d600cbcccd00867c7b0087747001876d670077747400876d6700
+776d6b0087747000776d6b00877470007774740087747003867c7b01987c750088848401
+987c7500888484008c8b8c00978481008c8b8c00978481028c8b8c008774700077646000
+63646500675c5a0963646500876d6700867c7b0097848100867c7b0088848400987c7500
+88848400867c7b0088848400987c75008884840097848100888484009784810088848400
+97848102978c8a01a88c8600978c8a04a88c8600978c8a00999393009784810077646001
+675c5a0187747000ffffff0ef4f6f900e8ecef00e0e4e700d9dcde00b8adaa0097848100
+978c8a00a7847c00978c8a0197848100978c8a0097848100978c8a0097848100978c8a00
+978481018884840097848100867c7b0097848100888484009784810288848400987c7500
+77646000584c4800776d6b00cbcccd05c4c5c50097848101978c8a0097848100978c8a0f
+97848102867c7b00675c5a00584c4801675c5a00ffffff12f4f6f901e0e4e700d9dcde00
+d2d4d600d8cccb00cbcccd00c4c5c500cbcccd00c4c5c503a4a5a400867c7b0097848100
+8884840097848102978c8a0097848100978c8a0097848101867c7b0097848100867c7b01
+987c7500867c7b01987c7500867c7b0cc6bcba00ffffff1ef4f6f900e8ecef00e0e4e700
+d9dcde00d2d4d600cbcccd00c4c5c501bbbcbd01c4c5c500bbbcbd02675c5a00584c4801
+684f4900867c7b0097848100978c8a02a88c8600978c8a0397848100978c8a00a88c8600
+978c8a00a8949000978c8a00a894900099939300a894900099939300a894900199939300
+a8949000a89a9500a8949000a89a9500a8949000a89a9500a8949000a89a9500a8949000
+a89a9503a8949000a89a950af4f6f900ffffff08f4f6f900ecf3f500e0e4e700d9dcde00
+cbcccd00c4c5c500bbbcbd01b4b4b401abacad00b4b4b401abacad00b4b4b400867c7b00
+675c5a01684f4900675c5a018774700099939301a8949001a89a9501a8949000a89a9500
+a8949000a89a9500a8949000a89a9500a8949000a89a9500a8949001a89a9500a8949000
+a89a950099939300a8949000978c8a0099939300b8adaa00e0e4e700ecf3f501e8ecef00
+e0e4e700d2d4d600bbbcbd009c9e9c007b7b7d00585c5e00554541004544450055454100
+584c480055454100584c480055454100584c480055454100584c480055454101584c4800
+795b540087747000867c7b0387747000867c7b0187747000867c7b0087747000867c7b00
+87747000867c7b0088848400cbcccd00d2d4d600c4c5c500bbbcbd00abacad01a4a5a403
+87747000584c480055454101584c480055454100584c4804675c5a009784810088848400
+97848100867c7b0097848100867c7b0088848400987c7500867c7b01987c750088848400
+97848102978c8a018c8b8c0097848100978c8a00c4c5c500e0e4e700d9dcde00d2d4d600
+c4c5c500bbbcbd00b4b4b400a4a5a4019c9e9c03684f4900463d3c0155454100463d3c00
+55454101463d3c0155454103684f4900867c7b0297746b00867c7b0187747004867c7b00
+87747000867c7b00987c75008884840097848102978c8a00d9dcde00ffffff12f4f6f900
+ecf3f500e8ecef00e0e4e700b8adaa00675c5a00776460006364650077646000675c5a00
+776460006364650077646000675c5a007764600063646500776460006364650077646000
+63646500776460006364650077646001636465007764600063646500776460006a6c6e00
+776460006364650077646002675c5a00584c480145444500554541004544450055454105
+584c4800675c5a0077646000877470007774740087747000776d6b0077747400876d6700
+776d6b0277646000776d6b00876d6700776d6b02876d6700776d6b0087747000776d6b00
+77747400877470007774740087747000777474008774700077747400877470007b7b7d00
+87747000867c7b0087747000867c7b01877470007b7b7d00776d6b00584c4800684f4900
+54545500584c4800684f490054545500584c4800675c5a00584c480054545500c6bcba00
+ffffff05f4f6f900ecf3f500e8ecef00d9dcde01d2d4d600b4b4b400776d6b0087747000
+777474008774700177747400876d670077747400877470027b7b7d00867c7b0187747000
+867c7b02987c750088848401987c750097848101978c8a0097848102978c8a0097848100
+8884840087747000776d6b0077646000675c5a0077646000675c5a0077646000776d6b00
+87747000867c7b00978481008884840097848100867c7b009784810088848400867c7b01
+987c7500867c7b0088848400867c7b0088848400987c750088848400978481008c8b8c00
+88848400978c8a0b87747000675c5a03d2d4d600ffffff0df4f6f900e8ecef00e0e4e700
+e6dcdc00c6bcba00978c8a0297848100978c8a0097848100978c8a0097848100978c8a00
+97848101888484009784810088848401987c750088848400987c75008884840097848100
+8884840097848101776d6b00584c4800684f4900bbbcbd00d2d4d602cbcccd03b8adaa00
+8884840097848102978c8a0d97848100978c8a0088848400978481008884840087747000
+584c480055454100584c480077747400ffffff12ecf3f500e8ecef00e0e4e700d9dcde00
+d2d4d600cbcccd01c4c5c501cbcccd00c4c5c500cbcccd00c6bcba00978c8a0088848400
+97848101978c8a01978481008c8b8c00978c8a0097848100888484009784810088848400
+867c7b0088848400867c7b0188848400867c7b0088848400987c7500867c7b0187747003
+867c7b0087747000867c7b01987c7500ffffff20ecf3f500e8ecef00d9dcde01cbcccd01
+c4c5c500c6bcba00bbbcbd03a4a5a40055454101584c4800684f4900978c8a0097848100
+978c8a0097848100978c8a0397848100978c8a0399939300978c8a00a8949000978c8a00
+a8949000978c8a00a894900099939301a894900099939300a89490009c9e9c00a8949000
+9c9e9c00a8949000a89a9500a8949000a89a9501a8949000a89a9506a8949000a89a9504
+a8949000a4a5a400ffffff09ecf3f500e0e4e700d9dcde00d2d4d600cbcccd00c4c5c500
+bbbcbd00b4b4b403abacad00b4b4b401a4a5a400675c5a00584c4800675c5a0054545500
+675c5a01978c8a00a894900099939300a89a9500a8949000a89a9500a8949000a89a9500
+99939300a894900099939300a89a950099939300a89a950099939300a89a95009c9e9c00
+a894900099939300a894900099939300a8949000978c8a01a89a95009c9e9c0088848400
+777474006a6c6e00584c480355454100584c480055454101454445005545410145444500
+55454101584c4800675c5a0077646000867c7b0188848400987c7500867c7b0087747001
+867c7b0087747001867c7b0087747001867c7b0087747000867c7b0097848100abacad00
+d2d4d600c4c5c500bbbcbd00b4b4b400a4a5a40477747400584c480255454100584c4800
+55454102584c480055454100675c5a0097848100867c7b009784810088848400867c7b00
+97848100867c7b008884840097848100867c7b0088848400978481008c8b8c0097848100
+8c8b8c00978c8a00978481018c8b8c0097848100cbcccd00e0e4e700d9dcde00cbcccd00
+c4c5c500bbbcbd00b4b4b400a4a5a4009c9e9c02999393009c9e9c0054545500463d3c05
+55454100463d3c0055454100463d3c0055454101684f4900867c7b0187747000867c7b01
+87747000867c7b0387747000867c7b0288848400867c7b0097848101978c8a0097848100
+e0e4e700ffffff13f4f6f900ecf3f500e0e4e700d9dcde007b7b7d007764600163646500
+77646000675c5a0077646000675c5a007764600063646500795b540063646500675c5a00
+77646000675c5a0177646000675c5a007764600063646500776460006364650077646000
+636465007764600263646500776d6b00675c5a0077646000675c5a02684f490054545500
+684f490054545500585c5e00675c5a0077646000776d6b0077747401867c7b0087747000
+7774740087747000876d6700776d6b0487747000776d6b0077747400876d6700776d6b06
+8774700077747401877470007b7b7d008774700077747400867c7b06776d6b00684f4900
+54545500684f490054545500684f490054545500684f490054545500684f490054545500
+bbbcbd00ffffff06f4f6f900e8ecef01d9dcde00d2d4d600d8cccb00978c8a00776d6b00
+8774700077747400877470007774740087747000777474008774700077747400867c7b03
+88848400867c7b0088848400987c750088848401987c7500888484008c8b8c0097848100
+8c8b8c00978481008c8b8c00888484008c8b8c0097848101888484009784810088848400
+978481008884840197848100867c7b0188848400987c750088848400867c7b0097848100
+888484019784810088848400867c7b0488848403978481008884840097848100978c8a08
+9784810063646500675c5a02a89a9500ffffff0df4f6f900e8ecef01d9dcde00cbcccd00
+99939300978c8a0097848100978c8a0197848100978c8a0197848101978c8a0097848100
+978c8a0097848101888484009784810088848400978481008884840097848100867c7b00
+88848400867c7b00684f4900584c48009c9e9c00d9dcde01d2d4d601d8cccb00cbcccd02
+c4c5c500a89a95008884840297848100978c8a0097848100978c8a0597848100978c8a00
+97848100978c8a0088848400978c8a0097848100888484009784810088848400867c7b00
+776d6b00584c4800554541019c9e9c00ffffff12e8ecef00e0e4e700d9dcde00d2d4d600
+d8cccb00c4c5c500d8cccb00c4c5c504a4a5a40097848100978c8a0897848100867c7b00
+97848100867c7b0097848100867c7b067b7b7d00877470007b7b7d007774740087747000
+7774740087747001b8adaa00ffffff20ecf3f500e8ecef00e0e4e700d2d4d601cbcccd00
+c4c5c500bbbcbd01c4c5c500bbbcbd00c6bcba0088848400554541004544450055454100
+63646500867c7b008884840097848101978c8a09a894900099939303978c8a00a8949000
+99939300a894900099939300978c8a00999393009c9e9c00a89490019c9e9c00a8949000
+9c9e9c00a89a950099939300a89a950099939300a89a950099939300a89a950099939300
+a89a950199939300a89a950199939300a89a9501a8949000b8adaa00ffffff08ecf3f500
+e8ecef00e0e4e700d9dcde00cbcccd00c4c5c500bbbcbd00b4b4b401abacad00b4b4b403
+abacad008c8b8c00684f490054545500684f4900584c4800675c5a0087747000978c8a01
+99939308a894900099939300a89a950099939300a89490009c9e9c00a89a9500a8949000
+99939302978c8a0099939300978c8a01867c7b0077646000675c5a00584c480855454100
+675c5a01776d6b0087747000867c7b0188848400867c7b0587747000867c7b0087747000
+867c7b0087747000867c7b0087747000867c7b01888484008c8b8c00cbcccd00c4c5c500
+bbbcbd00b4b4b400abacad00a4a5a40377747400584c480055454100584c480455454100
+584c4801675c5a009784810088848400867c7b0097848101888484009784810188848400
+97848100888484008c8b8c0097848100978c8a03978481008c8b8c0088848400c4c5c500
+e0e4e700d9dcde00d2d4d600c4c5c500bbbcbd00b4b4b400abacad009c9e9c03a89a9500
+675c5a00463d3c0b545455008774700077747400877470007774740087747001867c7b00
+87747002867c7b0288848400987c7500867c7b0088848402978c8a00d9dcde00ffffff13
+f4f6f900ecf3f500e8ecef00e0e4e700b4b4b40063646500776460006364650077646000
+63646500675c5a0b6364650077646000675c5a0077646000675c5a007764600063646500
+675c5a006364650077646000675c5a00776d6b00675c5a00776d6b00675c5a0077646000
+6a6c6e00776460006a6c6e0077646000776d6b0277747400877470007774740087747000
+7b7b7d00867c7b0077747402876d670077747400776d6b00877470007774740187747000
+776d6b0487747000776d6b0077747400776d6b00877470007774740287747000867c7b01
+77747400867c7b0287747000867c7b00776d6b0054545500684f4900585c5e00684f4900
+54545500684f4900585c5e00684f490054545500684f4900bbbcbd00ffffff06f4f6f900
+ecf3f500e0e4e701d9dcde00d2d4d600bbbcbd0087747000777474008774700077747400
+87747000777474008774700077747400867c7b00877470007b7b7d00867c7b02987c7500
+88848402987c7500888484019784810088848400978481008c8b8c009784810088848400
+97848100888484029784810088848403867c7b0088848400867c7b0088848400867c7b00
+888484009784810088848400867c7b0088848400867c7b06978481008884840097848100
+8884840197848100978c8a09776d6b00675c5a027b7b7d00ffffff0df4f6f900ecf3f500
+e0e4e701d2d4d600a8949000978c8a0097848101978c8a04978481008c8b8c0097848100
+8c8b8c009784810088848400978481008884840097848100888484009784810088848401
+867c7b01675c5a00584c48007b7b7d00e0e4e701d9dcde01d2d4d601cbcccd03c4c5c500
+978c8a0088848401978481008c8b8c00978c8a0788848400978481008c8b8c0097848100
+978c8a0088848403867c7b01675c5a00584c48004544450055454100c4c5c500ffffff11
+ecf3f500e8ecef00d9dcde01d2d4d600cbcccd00c4c5c501d8cccb00c4c5c500cbcccd00
+c4c5c500c6bcba00978c8a0088848400978c8a018c8b8c00978c8a038c8b8c0088848401
+867c7b05877470007b7b7d00867c7b0087747000867c7b00777474008774700077747400
+87747000777474008774700077747400ffffff21f4f6f900ecf3f500e0e4e700d9dcde00
+d2d4d600c4c5c502bbbcbd01c4c5c500bbbcbd0063646500463d3c0055454101776d6b00
+88848400867c7b00978481008884840097848101978c8a02a88c8600978c8a02a88c8600
+99939300978c8a00a88c860099939300a894900099939300a894900099939302a8949000
+99939300a8949000999393009c9e9c00a894900099939300a894900099939300a89a9500
+9c9e9c00a89a950199939300a89a950199939300a89a950199939300a89a950099939300
+a89a950099939300a89a95009c9e9c00c4c5c500ffffff08ecf3f500e0e4e700d9dcde00
+d2d4d600cbcccd00c4c5c500bbbcbd00b4b4b402abacad00b4b4b402abacad006a6c6e00
+684f4900585c5e00684f490054545500675c5a008884840099939300978c8a0199939300
+a894900099939301a894900099939304a89a950099939300a89a950099939302a8949000
+978c8a0099939300978c8a0099939300978c8a0388848400867c7b00776d6b006a6c6e00
+63646500776460006a6c6e00776d6b0077747400867c7b0b87747000867c7b0087747000
+777474008774700077747400867c7b0077747400867c7b0188848400867c7b0097848100
+b4b4b400c4c5c500bbbcbd00b4b4b400a4a5a40477747400584c48034a4c4d00584c4803
+55454100675c5a0088848400867c7b00978481008884840097848100978c8a008c8b8c00
+888484009784810088848400978481018c8b8c00978c8a028c8b8c0188848401c4c5c500
+e0e4e700d9dcde00d2d4d600c4c5c500bbbcbd00b4b4b400a4a5a4009c9e9c0454545500
+463d3c0155454100463d3c08684f49007774740087747000777474008774700077747401
+8774700077747400867c7b017b7b7d00867c7b0288848400867c7b009784810088848401
+97848100d9dcde00ffffff14f4f6f900e8ecef01e0e4e7008c8b8c007764600063646500
+675c5a0263646500675c5a0363646500675c5a02636465007764600063646500675c5a01
+63646501675c5a0463646500675c5a006364650177646000636465007764600063646500
+776460006a6c6e0077646000776d6b02777474017b7b7d00877470007b7b7d0087747000
+777474008774700077747403776d6b0177747400776d6b0277747400776d6b0177747401
+776d6b0077747400776d6b01877470007774740187747000867c7b047b7b7d00776d6b00
+684f490054545501684f490054545501684f4900585c5e00684f490054545500bbbcbd00
+ffffff07ecf3f500f7ece700e0e4e700d9dcde01d2d4d600a4a5a400776d6b0077747401
+87747000776d6b0077747400867c7b00877470007b7b7d00867c7b0087747000867c7b05
+88848403978481008884840a97848100867c7b008884840197848100867c7b0088848401
+867c7b0088848400867c7b0088848400867c7b0888848400987c7500888484018c8b8c00
+88848400978c8a008c8b8c0097848100978c8a0197848100978c8a0087747000675c5a02
+63646500e8ecef00ffffff0de8ecef02d2d4d600a4a5a400978c8a018c8b8c0097848100
+978c8a0197848100978c8a00978481008c8b8c00978c8a009784810088848400978c8a00
+888484009784810088848400978481008884840197848100867c7b01776d6b00584c4800
+675c5a00d9dcde00e8ecef01e0e4e700e6dcdc00d9dcde00d2d4d600cbcccd00d8cccb00
+cbcccd02b4b4b4009784810088848401978c8a07978481008c8b8c00978c8a0088848400
+8c8b8c009784810088848401987c750088848400867c7b0177747400675c5a00584c4800
+5545410054545500e8ecef00ffffff10f4f6f900e8ecef00e0e4e700d9dcde00d2d4d600
+cbcccd02c4c5c504a4a5a400978481008c8b8c00978c8a018c8b8c00978c8a008c8b8c01
+9784810088848400867c7b0477747400867c7b007b7b7d0087747000867c7b0077747400
+877470007774740387747000777474009c9e9c00ffffff22e8ecef01d9dcde00d2d4d600
+cbcccd00c4c5c500c6bcba00c4c5c502b4b4b40055454100463d3c0155454100867c7b01
+88848401978481008c8b8c0097848100978c8a0499939300978c8a0099939300978c8a00
+99939301a89a950099939300a89a950099939301a894900099939303a89a950099939300
+a89a9500999393009c9e9c00a89a950099939300a89a950099939301a89a950099939300
+a894900099939302a89a950099939300a89a950099939300a89a950099939301a8949000
+e8ecef00ffffff07ecf3f501e0e4e700d2d4d600cbcccd00c4c5c500bbbcbd00b4b4b405
+abacad00b8adaa009c9e9c00675c5a0054545501684f490054545500776d6b00978c8a00
+a8949000978c8a009993930ca894900099939301978c8a0099939300978c8a048c8b8c01
+978c8a008c8b8c00978481008884840097848100888484019784810088848401867c7b00
+88848400867c7b0c77747401867c7b04888484008c8b8c009c9e9c00c4c5c500bbbcbd00
+b4b4b400a4a5a40477747400584c48014a4c4d00584c480345444500584c4801675c5a00
+9784810088848400978481008884840397848100888484028c8b8c00978c8a018c8b8c00
+978c8a0288848401c4c5c500e0e4e700d9dcde00d2d4d600c4c5c500bbbcbd00b4b4b400
+a4a5a4019c9e9c03684f4900463d3c0a55454100545455008774700077747400776d6b00
+7774740187747000777474027b7b7d0087747000867c7b0388848400867c7b0088848402
+d9dcde00ffffff15f4f6f900e8ecef00e0e4e700cbcccd0063646500675c5a0963646500
+675c5a056364650077646000675c5a016364650077646000675c5a006364650077646000
+675c5a0077646000675c5a006a6c6e0063646500776d6b00776460006a6c6e00776d6b00
+6a6c6e00776d6b01777474018774700077747401877470007774740387747000776d6b00
+77747400776d6b0077747400776d6b0277747400776d6b0177747400776d6b0087747000
+77747400776d6b0177747400776d6b0077747402867c7b0077747400867c7b03776d6b00
+54545500684f4900675c5a0054545500675c5a00684f4900585c5e00584c4800585c5e00
+684f4900bbbcbd00ffffff08ecf3f500e8ecef00e0e4e700d9dcde00d2d4d600d8cccb00
+8884840077747400776d6b00777474018774700077747401867c7b0077747400867c7b00
+7b7b7d0087747000867c7b0488848400867c7b0088848404867c7b0088848400867c7b00
+97848100867c7b0088848400867c7b0088848402867c7b0088848400867c7b0588848400
+867c7b0188848401867c7b0288848400867c7b0088848401867c7b008884840197848100
+978c8a0088848400978c8a008c8b8c01978c8a008c8b8c00867c7b00675c5a03d2d4d600
+ffffff0df4f6f900e8ecef00e0e4e700d9dcde00b8adaa00978c8a078c8b8c00978c8a00
+978481008c8b8c01978481008c8b8c00978c8a008c8b8c00978481008c8b8c0097848100
+88848400867c7b008884840087747000584c480054545500bbbcbd00f4f6f900e8ecef02
+e0e4e700d9dcde01d2d4d601cbcccd03a4a5a40088848402978c8a008c8b8c00978c8a03
+8c8b8c00978c8a008c8b8c00978481008c8b8c0088848404867c7b0088848400867c7b01
+77747400584c48015545410063646500ffffff11ecf3f500e8ecef00d9dcde00d2d4d601
+cbcccd00c4c5c501cbcccd00c4c5c502bbbcbd00888484008c8b8c00978c8a008c8b8c00
+978c8a008c8b8c00978c8a0088848403867c7b017b7b7d00867c7b02777474007b7b7d00
+77747400877470007774740187747000776d6b007774740187747000e8ecef00ffffff22
+ecf3f500e8ecef00d9dcde01cbcccd00c4c5c502cbcccd019c9e9c00463d3c02684f4900
+7b7b7d0087747000867c7b0088848402978481008c8b8c00978c8a0299939300a8949000
+a4a5a400abacad00b8adaa00b4b4b401bbbcbd02b4b4b401abacad00a4a5a400a8949000
+a89a9500999393009c9e9c00999393009c9e9c0099939300a89a950099939302a89a9500
+99939304a894900099939308a89a9500ffffff08ecf3f500e0e4e700d9dcde00d2d4d600
+cbcccd00c4c5c500bbbcbd00b4b4b402abacad00b4b4b401abacad00b4b4b40088848400
+584c480154545500684f4900585c5e0088848400978c8a0099939302978c8a0099939300
+978c8a0099939300978c8a0099939305978c8a0099939301978c8a028c8b8c00978c8a00
+8c8b8c01978c8a0088848400978c8a00888484008c8b8c0088848402867c7b0088848400
+867c7b0188848401867c7b097b7b7d00877470007b7b7d0087747000867c7b0077747400
+867c7b0288848401978481008c8b8c00b4b4b400bbbcbd00b4b4b400abacad00a4a5a403
+77747400584c48004a4c4d00584c480055454100584c4805675c5a0088848401867c7b00
+888484019784810088848400978481008c8b8c00978481008c8b8c00978481008c8b8c00
+978c8a028c8b8c00978481008c8b8c0088848400c4c5c500e0e4e700d9dcde00cbcccd00
+c4c5c500bbbcbd00b4b4b400a4a5a4009c9e9c02a89a95009c9e9c0054545500463d3c08
+55454100463d3c01684f490077747402776d6b0077747400776d6b007774740287747000
+777474007b7b7d0087747000867c7b0488848401d9dcde00ffffff15f4f6f901e0e4e701
+a4a5a400675c5a02585c5e00675c5a00585c5e00675c5a00585c5e00675c5a0163646500
+675c5a0863646500675c5a0063646500675c5a0363646501675c5a007764600063646500
+776d6b0063646500776d6b00776460006a6c6e00776d6b01777474018774700077747400
+7b7b7d00867c7b007774740087747000777474018774700077747401776d6b016a6c6e00
+776d6b0177747401776d6b0077747401776d6b0077747401776d6b017774740187747000
+77747400867c7b04776d6b0054545500675c5a0054545500584c480054545501684f4900
+54545500584c480054545500bbbcbd00ffffff08f4f6f900e8ecef00e0e4e700e6dcdc00
+d9dcde00d2d4d600c4c5c50087747000776d6b01777474008774700077747400867c7b02
+877470007b7b7d00867c7b007b7b7d00867c7b007b7b7d00867c7b0188848400867c7b00
+88848400867c7b0088848400867c7b01888484059784810088848400867c7b0088848400
+867c7b0088848400867c7b037b7b7d00867c7b0588848401867c7b06888484028c8b8c00
+9784810088848400978c8a00888484008c8b8c0077646000585c5e00675c5a01d2d4d600
+ffffff0df4f6f900e8ecef00e0e4e700d9dcde00c6bcba00978c8a048c8b8c00978c8a00
+8c8b8c00978c8a008c8b8c0088848400978c8a0088848400978c8a00888484018c8b8c00
+9784810088848404867c7b00675c5a0054545500978c8a00ffffff02f4f6f900e8ecef01
+e0e4e700d9dcde00d2d4d601cbcccd03c4c5c500978c8a00888484009784810088848400
+8c8b8c00978c8a00999393008c8b8c00978c8a0088848400978c8a00888484008c8b8c00
+978c8a0097848100888484009784810088848400867c7b0088848400867c7b03776d6b00
+584c48005545410045444500867c7b00ffffff10f4f6f900e8ecef00e0e4e700d9dcde00
+d2d4d600cbcccd01c4c5c501cbcccd00c4c5c5029c9e9c00888484008c8b8c0099939300
+978c8a0188848400978c8a0088848401867c7b0288848401867c7b007b7b7d00867c7b01
+77747403776d6b0077747400776d6b007774740099939300ffffff23ecf3f500e8ecef00
+e0e4e700d9dcde00d2d4d602cbcccd00d2d4d601867c7b00463d3c026364650077747400
+867c7b0288848402978c8a0099939300abacad00bbbcbd00c4c5c500cbcccd00c4c5c502
+bbbcbd00c4c5c500bbbcbd00b4b4b400bbbcbd00b4b4b400bbbcbd00b4b4b400bbbcbd00
+b4b4b400abacad0099939301a894900099939300a89a950099939304978c8a0a99939304
+c4c5c500ffffff07ecf3f501e0e4e700d2d4d600cbcccd00c4c5c500bbbcbd01b4b4b401
+abacad00b4b4b401abacad00b4b4b400abacad0077747400584c480154545500584c4800
+675c5a00978c8a0299939307978c8a0099939300978c8a0199939301978c8a008c8b8c00
+978c8a008c8b8c02978c8a008c8b8c01978c8a008c8b8c00978c8a008c8b8c0097848100
+88848403867c7b0288848400867c7b007b7b7d00867c7b007b7b7d00867c7b0777747401
+7b7b7d00867c7b007b7b7d00867c7b02888484018c8b8c00a4a5a400bbbcbd00b4b4b400
+a4a5a40477747400584c48024a4c4d00584c48004a4c4d00584c48004a4c4d00584c4801
+675c5a0088848400867c7b008884840097848100867c7b00888484008c8b8c0297848100
+8c8b8c01978c8a018c8b8c00978c8a008c8b8c0188848401c4c5c500e0e4e700d9dcde00
+d2d4d600c4c5c500bbbcbd00b4b4b400abacad009c9e9c04584c4800463d3c0135343400
+463d3c0535343400463d3c015454550077747400776d6b0077747400776d6b0177747400
+776d6b0277747400776d6b0077747400776d6b0077747402867c7b0288848400d9dcde00
+ffffff16ecf3f500e8ecef01d9dcde008884840054545500675c5a0054545500675c5a01
+54545500675c5a03585c5e01675c5a0054545500675c5a00585c5e00675c5a0463646500
+7764600063646500675c5a00636465007764600063646500776460006a6c6e0063646500
+7764600063646500776d6b0063646500776d6b006a6c6e00776d6b0177747402867c7b00
+77747401867c7b0077747404776d6b0077747400776d6b016a6c6e00776d6b0077747401
+87747000777474008774700077747400776d6b0077747400776d6b008774700077747400
+867c7b017b7b7d00867c7b017b7b7d00867c7b00776d6b0054545500584c4800684f4900
+585c5e00584c480054545502584c480054545500bbbcbd00ffffff09f4f6f900e8ecef00
+e0e4e700d9dcde01d2d4d600b4b4b400776d6b0177747401867c7b00777474007b7b7d01
+867c7b007b7b7d00877470007b7b7d0077747400867c7b0077747400867c7b0588848400
+867c7b0288848400867c7b0088848401867c7b0088848400867c7b017b7b7d0077747400
+867c7b007b7b7d00777474007b7b7d0077747400867c7b007b7b7d01867c7b007b7b7d00
+867c7b01888484007b7b7d00888484007b7b7d0088848402867c7b00888484038c8b8c01
+88848400978c8a00776d6b00585c5e00675c5a006a6c6e00d2d4d600ffffff0df4f6f900
+e8ecef01e6dcdc00cbcccd00999393008c8b8c03978c8a008c8b8c00978c8a008c8b8c00
+978c8a008c8b8c00978c8a008c8b8c0088848400978c8a0088848400978481008c8b8c00
+88848403867c7b0088848400776d6b00584c48006a6c6e00f4f6f900ffffff03f4f6f900
+e8ecef01e6dcdc00d9dcde00d2d4d601d8cccb00cbcccd02bbbcbd0088848401978c8a00
+8c8b8c00978c8a008c8b8c00978c8a008c8b8c01888484009784810088848403867c7b01
+88848400867c7b0277747400867c7b00777474006a6c6e0045444501463d3c009c9e9c00
+ffffff0ff4f6f901e0e4e700e6dcdc00d2d4d600d8cccb00cbcccd00c4c5c503d7c4bd00
+c4c5c500b4b4b400978c8a008c8b8c03978c8a008c8b8c0088848404867c7b0088848401
+867c7b007b7b7d0087747000777474008774700077747403776d6b0077747400d9dcde00
+ffffff23ecf3f500e8ecef00e0e4e700d9dcde01d2d4d602d9dcde0154545500463d3c01
+55454100776d6b00867c7b0288848402a89a9500bbbcbd00d9dcde02d2d4d601cbcccd01
+c4c5c502bbbcbd04b4b4b401bbbcbd00b4b4b401867c7b008884840099939302a89a9500
+99939303978c8a0099939300978c8a008c8b8c01978c8a0099939300978c8a0499939303
+f4f6f900ffffff07ecf3f500e0e4e700d9dcde00d2d4d600cbcccd00c4c5c500bbbcbd00
+b4b4b404abacad00b4b4b401abacad006a6c6e004a4c4d00584c48004a4c4d00584c4800
+636465008c8b8c00978c8a0399939301978c8a0099939300978c8a0299939300978c8a00
+8c8b8c00978c8a028c8b8c01978481008c8b8c0088848400978c8a008c8b8c0197848100
+8c8b8c0088848402867c7b017b7b7d00867c7b017b7b7d00867c7b007b7b7d00867c7b00
+7b7b7d00867c7b017b7b7d00867c7b007b7b7d00867c7b007b7b7d00867c7b0388848406
+978c8a008c8b8c00978c8a00b4b4b401a4a5a4047774740054545500584c48024a4c4d00
+584c48024a4c4d00584c48006364650088848404978481008c8b8c00978481008c8b8c01
+978481008c8b8c00978c8a008c8b8c00978c8a008c8b8c00888484009784810088848400
+867c7b00cbcccd00e0e4e700d9dcde00d2d4d600c4c5c500bbbcbd00b4b4b400a4a5a400
+9c9e9c0454545500463d3c0235343400463d3c0135343400463d3c04584c480077747401
+776d6b0077747401776d6b0177747400776d6b0077747401776d6b00777474037b7b7d01
+867c7b01d9dcde00ffffff16f4f6f901e8ecef00e0e4e700d2d4d60077747400675c5a02
+585c5e00675c5a0163646500675c5a00585c5e00675c5a0154545500675c5a0054545500
+675c5a0054545500675c5a0063646500675c5a0063646501675c5a0063646501675c5a01
+6364650177646000636465017764600063646503776d6b0077747400776d6b0077747402
+7b7b7d00867c7b007b7b7d00777474018774700077747402776d6b0077747402776d6b01
+77747403776d6b0077747403867c7b00777474007b7b7d0077747400867c7b007b7b7d00
+867c7b007b7b7d00776d6b0054545502584c480054545501684f490054545501584c4800
+bbbcbd00ffffff09f4f6f901e8ecef00e0e4e700d9dcde00d2d4d601a4a5a4006a6c6e00
+776d6b007774740287747000777474007b7b7d00777474007b7b7d01877470007b7b7d00
+867c7b007b7b7d00867c7b007b7b7d00888484007b7b7d00867c7b0688848400867c7b02
+7b7b7d01777474008774700077747405867c7b00777474007b7b7d00867c7b007b7b7d01
+867c7b007b7b7d00867c7b007b7b7d00867c7b0288848405978c8a0088848400776d6b00
+585c5e00675c5a0088848400e8ecef00ffffff0df4f6f901e0e4e701d2d4d60099939300
+88848400978c8a0188848400978c8a008c8b8c00978481008c8b8c00978c8a0088848400
+8c8b8c00978c8a00888484008c8b8c00888484008c8b8c0088848403867c7b0188848400
+776d6b00584c4801d9dcde00ffffff05f4f6f900e8ecef00e0e4e700d9dcde01d2d4d600
+cbcccd02c4c5c500cbcccd00b8adaa00888484008c8b8c00888484008c8b8c00978c8a00
+888484008c8b8c00978481008c8b8c0088848403867c7b0088848400867c7b0377747400
+7b7b7d00777474008774700077747400675c5a00463d3c0135343400d2d4d600ffffff0f
+f4f6f900e8ecef00e0e4e700d9dcde00d2d4d600d8cccb00c4c5c500d8cccb00c4c5c501
+cbcccd00c4c5c50199939300978c8a018c8b8c00978c8a008c8b8c01888484027b7b7d00
+888484007b7b7d00867c7b0088848401867c7b007b7b7d00867c7b007b7b7d0077747401
+8774700077747401978c8a00ffffff24f4f6f900ecf3f500e8ecef00e0e4e700d9dcde02
+e0e4e701bbbcbd00554541004544450055454100584c48007b7b7d02867c7b0088848400
+a89a9500cbcccd00e8ecef00ecf3f500e8ecef01e0e4e701d9dcde00d2d4d602c4c5c502
+bbbcbd00c6bcba00b4b4b400bbbcbd02b4b4b400bbbcbd00b4b4b400abacad00675c5a00
+6a6c6e008c8b8c00999393068c8b8c00978c8a028c8b8c00978c8a008c8b8c0099939300
+978c8a008c8b8c0099939304bbbcbd00ffffff07f4f6f900ecf3f500e0e4e700d9dcde00
+d2d4d600c4c5c500bbbcbd01b4b4b405abacad00b4b4b400abacad007774740055454100
+454445004a4c4d00584c4800776d6b008c8b8c02978c8a028c8b8c00978c8a008c8b8c00
+999393008c8b8c00978c8a008c8b8c01978c8a008c8b8c04978c8a00888484008c8b8c00
+888484018c8b8c0088848402867c7b017b7b7d00777474007b7b7d01867c7b007b7b7d00
+867c7b007b7b7d00867c7b017b7b7d00867c7b007b7b7d00867c7b007b7b7d00867c7b00
+888484007b7b7d0088848400867c7b01888484018c8b8c00978c8a00888484008c8b8c02
+88848400abacad00b4b4b400a4a5a40477747400584c48014a4c4d00584c480054545500
+584c48004a4c4d00584c4802675c5a00888484058c8b8c01978481008c8b8c01978c8a00
+8c8b8c00978c8a008c8b8c02888484017b7b7d00c4c5c500e0e4e700d9dcde00d2d4d600
+c4c5c500bbbcbd00b4b4b400abacad009c9e9c00a89a95009c9e9c01a89a950054545500
+463d3c0735343400463d3c02584c480077747403776d6b017774740a7b7b7d00867c7b00
+7b7b7d00d9dcde00ffffff17f4f6f900ecf3f500e0e4e701cbcccd0077747400675c5a00
+63646500675c5a0063646501675c5a0063646500675c5a0154545500675c5a0054545500
+675c5a0054545500675c5a01585c5e00675c5a0063646500675c5a006364650177646000
+63646501675c5a0063646504675c5a00636465007764600063646500776d6b006a6c6e00
+776d6b0077747401867c7b017b7b7d0077747400867c7b007b7b7d017774740087747000
+777474078774700077747402776d6b0087747000777474077b7b7d0077747400776d6b00
+584c480054545500684f490054545501584c480054545500584c480154545500bbbcbd00
+ffffff0af4f6f900ecf3f500e8ecef00e0e4e700d9dcde01d2d4d600a4a5a400776d6b00
+6a6c6e00776d6b0077747404867c7b00777474007b7b7d00777474017b7b7d01867c7b00
+7b7b7d00867c7b007b7b7d01888484007b7b7d00867c7b007b7b7d00867c7b017b7b7d01
+776d6b0077747400776d6b00777474017b7b7d00777474008774700077747400867c7b00
+777474007b7b7d0077747400877470007b7b7d00867c7b007b7b7d00867c7b007b7b7d01
+867c7b007b7b7d02867c7b02888484018c8b8c0088848400776d6b0054545500675c5a00
+a4a5a400ffffff0ef4f6f900ecf3f500e8ecef00e0e4e700d2d4d600a4a5a4008c8b8c00
+978c8a00888484008c8b8c02888484008c8b8c0388848400978c8a008c8b8c00978c8a00
+8c8b8c00978c8a0088848401867c7b037b7b7d00585c5e0055454100abacad00ffffff07
+f4f6f900e8ecef00e0e4e700d9dcde00d2d4d601d8cccb00cbcccd02c4c5c50099939300
+978c8a018c8b8c00978c8a008c8b8c0088848404867c7b007b7b7d00867c7b007b7b7d01
+867c7b007b7b7d0077747400867c7b0077747403776d6b004544450035343400463d3c00
+45444500ffffff0ff4f6f900e8ecef00e0e4e700d9dcde00d2d4d600cbcccd02c4c5c504
+b8adaa008c8b8c02978c8a008c8b8c0188848402867c7b0088848407867c7b027b7b7d00
+867c7b007b7b7d00d2d4d600ffffff25ecf3f501e8ecef00e0e4e700e8ecef00e0e4e700
+e8ecef00ecf3f5009c9e9c00463d3c0055454100463d3c0063646500867c7b0299939300
+cbcccd00f4f6f900ffffff00f4f6f901ecf3f501e8ecef01e0e4e700d9dcde01d2d4d600
+cbcccd01c4c5c501bbbcbd05b4b4b400bbbcbd019993930054545500675c5a007b7b7d00
+99939305978c8a00999393008c8b8c02999393008c8b8c00999393028c8b8c0099939304
+ffffff08ecf3f500e8ecef00d9dcde00d2d4d600cbcccd00c4c5c500bbbcbd01b4b4b401
+abacad00b4b4b401abacad00b4b4b400abacad00b8adaa00888484004a4c4d0055454100
+45444500584c480077747400888484018c8b8c02978c8a008c8b8c08888484028c8b8c02
+88848404867c7b007b7b7d0177747402867c7b00777474007b7b7d00867c7b007b7b7d01
+867c7b007b7b7d00867c7b007b7b7d00867c7b007b7b7d00888484078c8b8c0088848400
+8c8b8c01978c8a008c8b8c0199939300b4b4b401abacad00a4a5a403777474004a4c4d00
+584c48004a4c4d00584c48004a4c4d00584c48014a4c4d00584c480163646500978c8a00
+888484008c8b8c0088848400978c8a00888484008c8b8c00978c8a008c8b8c01978c8a00
+8c8b8c00999393008c8b8c01978481008c8b8c00867c7b00888484007b7b7d00c4c5c500
+e0e4e700d9dcde00d2d4d600c4c5c500bbbcbd00b4b4b400a4a5a4019c9e9c03585c5e00
+45444501463d3c09584c4800777474007b7b7d00777474007b7b7d0177747408867c7b00
+7b7b7d00867c7b0288848400d9dcde00ffffff18f4f6f901e0e4e701cbcccd00867c7b00
+63646501675c5a0063646502675c5a02585c5e00675c5a00585c5e00675c5a00585c5e00
+675c5a0163646500675c5a0063646500675c5a0163646500675c5a0a636465016a6c6e00
+776d6b01777474007b7b7d00867c7b0077747400867c7b0077747404776d6b0077747400
+776d6b0077747401776d6b0077747403776d6b00777474038774700077747402776d6b01
+77747402776d6b0054545500584c480054545500584c480254545500584c480054545500
+584c4800b4b4b400ffffff0bf4f6f900f7ece700e8ecef00e0e4e700d9dcde01d2d4d600
+b4b4b400777474006a6c6e00776d6b0077747400776d6b0077747400776d6b0077747401
+7b7b7d00777474037b7b7d00777474007b7b7d0877747403776d6b0077747401776d6b00
+777474057b7b7d00777474027b7b7d05867c7b017b7b7d01888484036364650054545500
+867c7b00e0e4e700ffffff0ff4f6f900e8ecef00e0e4e700d9dcde00b8adaa0088848400
+8c8b8c00888484008c8b8c00978c8a0088848400978c8a00888484008c8b8c0188848400
+978c8a008c8b8c00888484008c8b8c01888484008c8b8c00888484017b7b7d03675c5a00
+463d3c0077747400ffffff08f4f6f900e8ecef01e6dcdc00d9dcde00d2d4d601cbcccd03
+bbbcbd00999393008c8b8c00978c8a008c8b8c01888484008c8b8c00867c7b0088848400
+867c7b00888484007b7b7d00777474017b7b7d01867c7b007b7b7d00777474036a6c6e00
+776d6b00675c5a00463d3c003534340163646500ffffff0ff4f6f900e8ecef00e0e4e700
+d9dcde00d2d4d600cbcccd00c4c5c501cbcccd00c4c5c503999393008c8b8c05867c7b00
+888484017b7b7d00888484018c8b8c00888484057b7b7d01867c7b0088848400ffffff26
+f4f6f902e8ecef01ecf3f500f4f6f9019c9e9c0045444502776d6b007b7b7d0088848400
+bbbcbd00ffffff07f4f6f900ecf3f500e8ecef00e0e4e700d9dcde02cbcccd01c4c5c501
+bbbcbd00c6bcba00b4b4b400bbbcbd00b4b4b400bbbcbd00b4b4b400bbbcbd00b4b4b400
+77747400545455017b7b7d00999393008c8b8c00999393018c8b8c00999393008c8b8c05
+999393008c8b8c00999393038c8b8c0099939301d2d4d600ffffff07f4f6f900ecf3f500
+e8ecef00d9dcde00d2d4d601c4c5c500bbbcbd01b4b4b402abacad00b4b4b400abacad00
+b4b4b400abacad0199939300545455004a4c4d00454445004a4c4d007774740088848400
+8c8b8c02888484008c8b8c01978c8a008c8b8c04888484008c8b8c00888484087b7b7d00
+867c7b007b7b7d01777474037b7b7d02867c7b017b7b7d02867c7b007b7b7d00867c7b00
+888484038c8b8c00888484008c8b8c00888484008c8b8c04888484009c9e9c00c4c5c500
+bbbcbd00b4b4b400a4a5a404777474004a4c4d00584c48004a4c4d01584c48004a4c4d01
+584c48004a4c4d00584c480063646500888484008c8b8c00888484028c8b8c0088848400
+8c8b8c03978c8a008c8b8c00978c8a008c8b8c0088848401867c7b007b7b7d01c4c5c500
+e0e4e700d9dcde00d2d4d600c4c5c500bbbcbd00b4b4b400abacad009c9e9c04675c5a00
+45444500584c4800463d3c004a4c4d004544450055454100463d3c0055454100463d3c02
+4544450054545500777474007b7b7d00877470007b7b7d00777474007b7b7d0377747404
+867c7b00777474007b7b7d01888484007b7b7d00d9dcde00ffffff19ecf3f500e8ecef01
+e0e4e700d2d4d600978c8a00636465017764600063646504675c5a03585c5e0063646500
+675c5a0063646500675c5a0063646500675c5a0063646500675c5a00585c5e00675c5a00
+585c5e01675c5a0054545500585c5e0054545500585c5e01675c5a016364650077646000
+6a6c6e01776d6b0077747405776d6b0177747400776d6b0077747400776d6b0063646500
+776d6b0077747400776d6b0077747409776d6b0277747400776d6b007b7b7d0077747400
+6a6c6e00584c480054545500584c480154545500584c48004a4c4d00584c48004a4c4d01
+bbbcbd00ffffff0cf4f6f900ecf3f500e8ecef00e0e4e700e6dcdc00d9dcde00d2d4d600
+c4c5c5008884840063646500776d6b0377747400776d6b0077747400776d6b0077747407
+8774700077747400776d6b0077747400776d6b0077747402776d6b0077747400776d6b00
+77747400776d6b0077747400776d6b0177747402776d6b00777474017b7b7d0077747400
+867c7b0077747401867c7b01888484007b7b7d00888484007b7b7d00888484007b7b7d00
+8884840077747400675c5a0063646500c4c5c500ffffff10f4f6f900e8ecef00e0e4e700
+e6dcdc00bbbcbd008c8b8c00888484008c8b8c00888484008c8b8c00888484008c8b8c00
+888484008c8b8c00888484018c8b8c00888484008c8b8c01888484008c8b8c0188848401
+7b7b7d01776d6b007774740063646500463d3c0054545500f4f6f900ffffff09f4f6f900
+e8ecef01d9dcde01d2d4d600d8cccb00cbcccd03b4b4b4008c8b8c03888484027b7b7d03
+777474017b7b7d00777474007b7b7d0077747401776d6b026a6c6e02675c5a0035343401
+978c8a00ffffff0ff4f6f900e8ecef00e0e4e700d9dcde00d2d4d600cbcccd01c4c5c502
+cbcccd00c4c5c501abacad00888484028c8b8c00888484008c8b8c00888484068c8b8c03
+888484027b7b7d00867c7b00d2d4d600ffffff27f4f6f903ffffff03a4a5a4004a4c4d01
+7b7b7d00a4a5a400f4f6f900ffffff0af4f6f900ecf3f500e8ecef00e0e4e700d9dcde00
+d2d4d601cbcccd00c4c5c501bbbcbd03b4b4b401bbbcbd00b4b4b400a89a950054545500
+684f4900585c5e00888484008c8b8c00999393028c8b8c00999393008c8b8c00978c8a00
+8c8b8c01999393008c8b8c00999393058c8b8c0099939300abacad00ffffff08f4f6f900
+ecf3f500e0e4e700d9dcde00d2d4d600cbcccd00c4c5c500bbbcbd01b4b4b403b8adaa00
+abacad00b4b4b402a4a5a40077747400584c480045444500584c48006a6c6e0088848411
+867c7b027b7b7d00867c7b007b7b7d0177747402776d6b0177747401867c7b007b7b7d00
+867c7b007b7b7d00867c7b007b7b7d00867c7b007b7b7d00888484038c8b8c0088848400
+8c8b8c03888484018c8b8c0088848400978c8a00abacad00cbcccd00c4c5c500bbbcbd00
+b4b4b400a4a5a404776d6b00454445004a4c4d0045444500584c48004a4c4d00584c4800
+4a4c4d00584c48004a4c4d01675c5a008884840a8c8b8c01888484027b7b7d0277747400
+c4c5c500e0e4e700d9dcde00d2d4d600c4c5c500bbbcbd00b4b4b400a4a5a4019c9e9c01
+99939300a4a5a400545455004544450255454101454445024a4c4d0055454100463d3c00
+45444500585c5e00867c7b007b7b7d0477747400867c7b02888484007b7b7d00867c7b00
+7b7b7d02867c7b007b7b7d01867c7b00d9dcde00ffffff1af4f6f900e8ecef00e0e4e700
+d9dcde01abacad00776d6b0063646500776460006a6c6e00776460006a6c6e00675c5a00
+63646500585c5e0063646500675c5a0063646500675c5a01585c5e00675c5a02585c5e00
+675c5a00585c5e00675c5a0054545503675c5a0054545502585c5e00636465046a6c6e01
+77747400776d6b0177747400776d6b016a6c6e00776d6b006a6c6e00776d6b00585c5e00
+54545500776d6b0077747400776d6b00777474007b7b7d0077747400867c7b0077747402
+6a6c6e00776d6b006a6c6e03776d6b00777474026a6c6e00584c48024a4c4d0545444500
+b4b4b400ffffff0df4f6f900e8ecef01e0e4e701d9dcde00d2d4d601a4a5a400776d6b00
+6a6c6e02776d6b0177747403776d6b0077747400776d6b0077747400776d6b007b7b7d00
+77747400776d6b007b7b7d0077747402776d6b0077747400776d6b0077747402776d6b00
+6a6c6e00777474006a6c6e00776d6b01777474067b7b7d04888484007b7b7d00867c7b00
+7b7b7d0077747400636465006a6c6e00b4b4b400ffffff11f4f6f900e8ecef00e0e4e701
+c4c5c5008c8b8c00888484068c8b8c00888484038c8b8c00888484008c8b8c0088848403
+7b7b7d0177747401776d6b004a4c4d0045444500c4c5c500ffffff0bf4f6f900e8ecef00
+e6dcdc00d9dcde00d2d4d601cbcccd03c4c5c5009c9e9c008c8b8c0288848400867c7b00
+888484007b7b7d00867c7b01777474007b7b7d0077747406776d6b006a6c6e00776d6b00
+6364650254545500584c4800ffffff10f4f6f900ecf3f500e8ecef00d9dcde00d2d4d600
+d8cccb00cbcccd01c4c5c504867c7b007b7b7d00888484038c8b8c00888484028c8b8c00
+888484038c8b8c04888484007b7b7d008c8b8c00ffffff31c4c5c500776d6b00d9dcde00
+ffffff0df4f6f900ecf3f500e0e4e701d9dcde00d2d4d601c4c5c501bbbcbd00c6bcba00
+b4b4b400bbbcbd00b4b4b400bbbcbd00b4b4b400bbbcbd00b4b4b4006a6c6e0054545501
+636465008c8b8c00999393008c8b8c00999393028c8b8c00999393008c8b8c0099939300
+8c8b8c00999393018c8b8c02999393008c8b8c03ffffff09f4f6f900ecf3f500e0e4e700
+d9dcde00d2d4d600cbcccd00c4c5c501bbbcbd01b4b4b401abacad00b4b4b400abacad00
+b4b4b400abacad00b4b4b400abacad009c9e9c00675c5a0045444501636465007b7b7d01
+888484007b7b7d00888484047b7b7d00888484057b7b7d00888484007b7b7d0477747400
+7b7b7d0077747401776d6b01777474007b7b7d01867c7b007b7b7d00867c7b007b7b7d00
+867c7b007b7b7d00888484048c8b8c04888484008c8b8c0299939300c4c5c500d9dcde00
+cbcccd00c4c5c500bbbcbd00abacad01a4a5a40377747400454445025545410045444502
+4a4c4d00584c48004a4c4d006364650088848400867c7b00888484037b7b7d0088848407
+7b7b7d0277747401c4c5c500e0e4e700d9dcde00d2d4d600cbcccd00bbbcbd00b4b4b400
+abacad009c9e9c04675c5a00454445005545410045444500463d3c004544450255454100
+454445014a4c4d0045444500675c5a007b7b7d01867c7b007b7b7d02867c7b007b7b7d00
+888484007b7b7d00867c7b007b7b7d00867c7b007b7b7d03867c7b007b7b7d01d2d4d600
+ffffff1af4f6f901ecf3f500e8ecef00e0e4e700d9dcde00c4c5c5008884840063646503
+6a6c6e00675c5a0063646501585c5e00675c5a00585c5e0354545500585c5e015454550a
+675c5a00585c5e00675c5a0063646500776d6b0063646500776460006a6c6e0263646500
+6a6c6e00776d6b006a6c6e03545455004544450054545500776d6b006a6c6e0177747402
+776d6b026a6c6e01636465006a6c6e00675c5a006a6c6e02776d6b02636465004a4c4d03
+554541004a4c4d00554541024a4c4d00b4b4b400ffffff0ff4f6f900e8ecef00e0e4e701
+d9dcde01d2d4d600c4c5c5008c8b8c006a6c6e02776d6b006a6c6e00776d6b0177747401
+776d6b0277747404776d6b0177747400776d6b00777474006a6c6e0077747400776d6b00
+777474006a6c6e0077747400776d6b006a6c6e00777474006a6c6e0077747400776d6b00
+77747400776d6b00777474017b7b7d00777474007b7b7d02888484007b7b7d026a6c6e00
+77747400b4b4b400ffffff13f4f6f900ecf3f500e0e4e700d2d4d6009993930088848400
+7b7b7d00888484057b7b7d00888484007b7b7d00888484007b7b7d00888484057b7b7d00
+88848400777474016a6c6e0054545500554541008c8b8c00ffffff0cf4f6f900ecf3f500
+e8ecef00d9dcde01d2d4d601d8cccb00cbcccd02c4c5c500978c8a00888484017b7b7d06
+777474017b7b7d0077747400867c7b007b7b7d00777474016a6c6e00777474006a6c6e01
+63646500776460008c8b8c00e8ecef00ffffff11ecf3f500e8ecef00e6dcdc00d9dcde00
+cbcccd01c4c5c501cbcccd00c4c5c501b4b4b400585c5e00867c7b00888484038c8b8c00
+888484068c8b8c0588848401c4c5c500ffffff43f4f6f901e8ecef00e0e4e700d9dcde00
+d2d4d600cbcccd01c4c5c500bbbcbd02b4b4b400bbbcbd00b4b4b401bbbcbd00978c8a00
+584c480054545501777474008c8b8c00999393008c8b8c01999393008c8b8c0ee0e4e700
+ffffff09f4f6f900e8ecef00e0e4e700d9dcde00d2d4d600cbcccd00c4c5c500bbbcbd02
+b4b4b402abacad00b4b4b400abacad00b4b4b400abacad028c8b8c005454550045444500
+545455007b7b7d01888484037b7b7d01888484007b7b7d00888484007b7b7d0088848400
+7b7b7d01888484007b7b7d03777474007b7b7d0077747402776d6b00777474006a6c6e00
+777474007b7b7d03888484007b7b7d00888484038c8b8c00888484018c8b8c00978c8a00
+8c8b8c0488848400a4a5a400d9dcde00e0e4e700d2d4d601c4c5c500bbbcbd00b4b4b400
+a4a5a404776d6b003b3c3d00463d3c003b3c3d00463d3c004544450055454101463d3c00
+45444501675c5a007b7b7d00888484007b7b7d03888484007b7b7d00888484017b7b7d07
+77747401bbbcbd00e0e4e700d9dcde00d2d4d600c4c5c500bbbcbd00b4b4b400abacad00
+9c9e9c04585c5e00454445004a4c4d00454445005545410045444503463d3c0045444500
+5545410045444500585c5e007b7b7d03867c7b007b7b7d01888484007b7b7d0677747400
+7b7b7d03d9dcde00ffffff1bf4f6f901e8ecef01e0e4e700d9dcde01abacad0077747400
+63646501675c5a0063646501585c5e00675c5a00585c5e0054545506584c480054545500
+584c480054545500584c480054545500584c480054545501584c480054545501675c5a00
+636465086a6c6e01776d6b006a6c6e00675c5a0045444502584c48006a6c6e03776d6b00
+6a6c6e04675c5a0063646500675c5a0063646501675c5a00636465006a6c6e0263646500
+4a4c4d02554541004a4c4d0045444500463d3c00454445003b3c3d00463d3c00bbbcbd00
+ffffff0ff4f6f901f7ece700e8ecef00e0e4e701d9dcde01d2d4d600b4b4b400867c7b00
+6a6c6e04777474006a6c6e00777474096a6c6e00777474006a6c6e00777474006a6c6e00
+777474026a6c6e00777474016a6c6e00777474016a6c6e0077747403776d6b0077747402
+7b7b7d027774740099939300cbcccd00ffffff15f4f6f900e8ecef00e0e4e700d2d4d600
+abacad008c8b8c00888484007b7b7d01888484007b7b7d00888484007b7b7d0088848400
+7b7b7d03777474007b7b7d0777747400636465004544450063646500ffffff0ef4f6f900
+e8ecef01d9dcde01d2d4d600cbcccd01c4c5c500cbcccd01abacad008c8b8c007b7b7d00
+888484007b7b7d00888484007b7b7d02777474086a6c6e00776d6b006a6c6e00776d6b00
+a4a5a400e8ecef00ffffff13f4f6f900e8ecef00d9dcde01cbcccd01c4c5c5047b7b7d00
+6a6c6e007b7b7d00888484007b7b7d00888484058c8b8c007b7b7d00888484018c8b8c05
+888484008c8b8c00ffffff46e8ecef01e0e4e700d9dcde00d2d4d600cbcccd00c4c5c500
+c6bcba00bbbcbd02b4b4b400bbbcbd01b4b4b400abacad00585c5e00584c4801585c5e00
+8c8b8c05888484008c8b8c01888484008c8b8c09bbbcbd00ffffff09f4f6f901ecf3f500
+e0e4e700d9dcde00d2d4d600cbcccd01c4c5c500bbbcbd02b4b4b401abacad00b8adaa00
+abacad00b4b4b400abacad00b4b4b400b8adaa00abacad0088848400545455004a4c4d00
+636465007b7b7d00888484007b7b7d00888484027b7b7d00888484007b7b7d0088848400
+7b7b7d00888484007b7b7d01777474007b7b7d00777474007b7b7d00777474046a6c6e02
+776d6b00777474017b7b7d04888484038c8b8c02999393008c8b8c028884840099939300
+c4c5c500ecf3f500e8ecef00e0e4e700d9dcde00cbcccd00c4c5c500bbbcbd00abacad00
+a4a5a404776d6b00353434013b3c3d00463d3c003b3c3d02454445005545410045444500
+585c5e007b7b7d02888484007b7b7d02888484007b7b7d05777474007b7b7d0277747400
+6a6c6e00c4c5c500e0e4e700d9dcde00d2d4d600c4c5c500bbbcbd00b4b4b400abacad00
+9c9e9c01a89a95009c9e9c01675c5a0045444500554541004a4c4d004544450155454100
+4a4c4d014544450255454100545455007b7b7d0e867c7b00777474007b7b7d02d2d4d600
+ffffff1df4f6f900ecf3f500e8ecef00e0e4e701d9dcde00d2d4d6009c9e9c0077747400
+63646501675c5a0054545500585c5e0054545503584c480354545501584c480054545502
+584c480054545505585c5e00675c5a01585c5e0063646502675c5a006364650354545500
+45444500463d3c013b3c3d0045444500636465026a6c6e0163646504675c5a0063646501
+585c5e00675c5a00585c5e0063646502776d6b00675c5a005545410045444500463d3c00
+45444500463d3c01454445003b3c3d00463d3c0063646500d2d4d600ffffff11f4f6f900
+ecf3f500e8ecef01e0e4e700e6dcdc00d9dcde01d2d4d600b8adaa007b7b7d006a6c6e00
+776d6b006a6c6e00776d6b00777474016a6c6e00777474006a6c6e00777474006a6c6e01
+776d6b006a6c6e01777474006a6c6e0077747400776d6b00777474017b7b7d0077747402
+6a6c6e00776d6b006a6c6e01777474006a6c6e00777474006a6c6e017774740488848400
+abacad00e0e4e700ffffff17f4f6f900ecf3f500e8ecef00d9dcde01d2d4d600bbbcbd00
+9c9e9c008c8b8c007b7b7d00888484017b7b7d03777474047b7b7d04777474006a6c6e00
+4a4c4d01d2d4d600ffffff0fecf3f500e8ecef00e6dcdc00d9dcde00d2d4d602d8cccb00
+cbcccd029c9e9c00888484007b7b7d01777474007b7b7d01777474026a6c6e0077747404
+6a6c6e0188848400bbbcbd00ffffff16ecf3f500e8ecef00e0e4e700d9dcde00cbcccd01
+c4c5c500d8cccb00c4c5c501b4b4b40054545500888484037b7b7d00888484007b7b7d00
+888484027b7b7d00888484028c8b8c0588848400bbbcbd00ffffff46f4f6f900ecf3f500
+e0e4e700d9dcde00d2d4d601c4c5c501bbbcbd01b4b4b400bbbcbd00b4b4b401bbbcbd00
+b4b4b400776d6b0054545502777474008c8b8c00888484047b7b7d00888484007b7b7d00
+888484018c8b8c079c9e9c00ffffff0bf4f6f900ecf3f500e0e4e701d9dcde00d2d4d600
+cbcccd00c4c5c501bbbcbd02b4b4b402abacad00b4b4b400abacad02b8adaa00abacad00
+8c8b8c0063646500545455006a6c6e007b7b7d01888484027b7b7d00888484007b7b7d00
+888484007b7b7d02777474056a6c6e00777474006a6c6e00777474006a6c6e02776d6b00
+777474017b7b7d01888484008c8b8c007b7b7d008c8b8c00888484008c8b8c0599939300
+8c8b8c00abacad00ecf3f500ffffff00ecf3f500e8ecef00e0e4e700d2d4d601bbbcbd01
+b4b4b400a4a5a40463646500353434033b3c3d00463d3c003b3c3d02463d3c0054545500
+7b7b7d0b777474066a6c6e00bbbcbd00e8ecef00d9dcde00d2d4d600c4c5c500bbbcbd00
+b4b4b400abacad00a4a5a4009c9e9c035454550045444501463d3c00454445004a4c4d00
+4544450155454100454445004a4c4d0045444501585c5e00867c7b007b7b7d0288848400
+7b7b7d00888484007b7b7d0b77747400d2d4d600ffffff1ef4f6f901e8ecef01e0e4e701
+d9dcde00cbcccd009c9e9c006a6c6e00585c5e00675c5a0054545503584c480054545500
+4a4c4d00545455004a4c4d00545455004a4c4d0154545500584c48004a4c4d0054545500
+4a4c4d00584c480154545505585c5e00675c5a0054545500585c5e0163646500675c5a00
+585c5e0045444500463d3c00353434013b3c3d0054545500776d6b00585c5e00675c5a03
+63646501675c5a0063646500675c5a0063646500585c5e00675c5a0054545500585c5e00
+54545501675c5a00636465015454550045444500463d3c0045444500463d3c003b3c3d00
+545455007b7b7d00abacad00e8ecef00ffffff14f4f6f901f7ece700e8ecef01e0e4e701
+d9dcde01d2d4d600b4b4b4008c8b8c006a6c6e00777474006a6c6e00777474006a6c6e00
+77747400776d6b006a6c6e01777474006a6c6e01776d6b006a6c6e00777474006a6c6e00
+777474017b7b7d00777474007b7b7d00777474046a6c6e00777474006a6c6e0277747402
+7b7b7d0099939300cbcccd00ffffff1bf4f6f900e8ecef00e0e4e701d9dcde02cbcccd00
+b4b4b40099939300888484017b7b7d01777474026a6c6e037774740454545500463d3c00
+a4a5a400ffffff11ecf3f500e8ecef00e6dcdc00d9dcde00d2d4d601cbcccd02d2d4d600
+cbcccd008c8b8c007b7b7d01777474007b7b7d00777474026a6c6e00777474016a6c6e00
+777474017b7b7d009c9e9c00d9dcde00ffffff18f4f6f900e8ecef00e0e4e700d9dcde00
+d8cccb00cbcccd00c4c5c501cbcccd00c4c5c500867c7b00636465007b7b7d0688848400
+7b7b7d00888484018c8b8c007b7b7d008c8b8c007b7b7d008c8b8c05ffffff48f4f6f900
+ecf3f500e8ecef00d9dcde00d2d4d600cbcccd00c4c5c500bbbcbd02b4b4b401bbbcbd00
+b4b4b400bbbcbd008884840054545500584c480054545500636465008c8b8c007b7b7d00
+8c8b8c007b7b7d008c8b8c007b7b7d03888484007b7b7d018c8b8c007b7b7d0088848401
+8c8b8c03ffffff0bf4f6f901ecf3f500e8ecef00d9dcde01d2d4d601cbcccd00c4c5c500
+bbbcbd03b4b4b402abacad00b4b4b401abacad039c9e9c0077747400636465007b7b7d03
+888484007b7b7d00888484007b7b7d05777474006a6c6e007b7b7d006a6c6e0077747400
+6a6c6e01636465006a6c6e00636465006a6c6e03777474007b7b7d02888484007b7b7d00
+888484008c8b8c03999393008c8b8c009c9e9c00e0e4e700ffffff02ecf3f500e8ecef00
+e0e4e700d9dcde00cbcccd00c4c5c500bbbcbd00abacad00a4a5a4046a6c6e0035343402
+2e2c2d00353434002e2c2d00353434003b3c3d00353434003b3c3d004a4c4d0077747400
+6a6c6e00777474006a6c6e00777474017b7b7d00777474026a6c6e00777474006a6c6e00
+777474006a6c6e00777474006a6c6e03bbbcbd00e0e4e700d9dcde00d2d4d600c4c5c500
+bbbcbd00b4b4b400abacad009c9e9c04675c5a00454445004a4c4d00454445004a4c4d00
+454445004a4c4d00454445024a4c4d004544450055454100636465007b7b7d0588848400
+7b7b7d01777474007b7b7d00777474007b7b7d00777474007b7b7d02777474017b7b7d00
+d2d4d600ffffff1ff4f6f901ecf3f500e8ecef00e0e4e702d9dcde00d8cccb009c9e9c00
+6a6c6e0054545501584c48004a4c4d02584c48004a4c4d02584c4800545455004a4c4d01
+54545500584c4800545455004a4c4d0054545503585c5e0054545500585c5e0054545505
+45444500353434003b3c3d0054545500867c7b00a4a5a400c4c5c500d2d4d600b8adaa00
+585c5e04675c5a00585c5e02675c5a00585c5e00675c5a00585c5e0054545504585c5e00
+675c5a00545455003b3c3d004a4c4d006364650099939300c4c5c500f4f6f900ffffff19
+f4f6f900ecf3f500f4f6f900e8ecef01e0e4e701d9dcde02c4c5c5009c9e9c007b7b7d00
+6a6c6e00777474016a6c6e00777474006a6c6e0177747400776d6b00777474057b7b7d01
+777474007b7b7d00777474026a6c6e03777474006a6c6e00777474007b7b7d00abacad00
+e0e4e700ffffff1df4f6f901e8ecef00e0e4e701d9dcde02d2d4d601c4c5c500a4a5a400
+8c8b8c007b7b7d00777474016a6c6e01636465016a6c6e0177747402585c5e00463d3c00
+63646500ffffff12f4f6f900ecf3f500e8ecef00d9dcde01d2d4d600d9dcde00d2d4d602
+d9dcde00c4c5c5007b7b7d03777474007b7b7d00777474016a6c6e017774740088848400
+b4b4b400ecf3f500ffffff1aecf3f500e8ecef00d9dcde01cbcccd01c4c5c502b4b4b400
+4a4c4d00777474007b7b7d08888484007b7b7d00888484047b7b7d008c8b8c0188848400
+b4b4b400ffffff49ecf3f500e8ecef00e0e4e700d9dcde00cbcccd00c4c5c501bbbcbd00
+b4b4b400bbbcbd01b4b4b400bbbcbd00b4b4b4009c9e9c004a4c4d00545455004a4c4d00
+54545500888484008c8b8c01888484008c8b8c007b7b7d058c8b8c007b7b7d008c8b8c00
+888484007b7b7d008c8b8c007b7b7d008c8b8c01ecf3f500ffffff0cf4f6f900ecf3f501
+e0e4e700d9dcde01d2d4d601cbcccd00c4c5c500bbbcbd02b4b4b403abacad00b4b4b400
+abacad00b4b4b400abacad038c8b8c007b7b7d018c8b8c007b7b7d07777474027b7b7d00
+6a6c6e00777474006a6c6e00636465026a6c6e00636465006a6c6e00777474006a6c6e00
+777474007b7b7d02888484007b7b7d008c8b8c007b7b7d008c8b8c029c9e9c00c4c5c500
+ffffff04f4f6f900e8ecef00e0e4e700d2d4d600cbcccd00c4c5c500b4b4b401a4a5a404
+776d6b00353434042e2c2d01353434024a4c4d006a6c6e03777474006a6c6e0ebbbcbd00
+e8ecef00d9dcde00d2d4d600c4c5c500bbbcbd00b4b4b400abacad009c9e9c04675c5a00
+454445004a4c4d00554541004544450055454100454445024a4c4d00463d3c0045444501
+585c5e007b7b7d00888484007b7b7d00888484037b7b7d04777474007b7b7d0077747405
+d2d4d600ffffff21f4f6f902e8ecef01e0e4e701d9dcde01abacad00867c7b0054545501
+4a4c4d02584c48004a4c4d04545455004a4c4d0054545502584c480054545504584c4800
+54545500584c4800545455026364650088848400b8adaa00d2d4d600e0e4e701d9dcde00
+e0e4e700d9dcde00b4b4b40054545507584c480054545505584c4800585c5e00776d6b00
+7b7b7d008c8b8c01abacad00d9dcde00ecf3f500ffffff1ef4f6f901f7ece700e8ecef02
+e0e4e701d9dcde01d2d4d600b4b4b4008c8b8c00777474016a6c6e00777474006a6c6e00
+777474036a6c6e00777474027b7b7d03777474016a6c6e047b7b7d009c9e9c00cbcccd00
+ffffff21f4f6f901e8ecef02e0e4e701d9dcde03d2d4d600bbbcbd009993930077747400
+6a6c6e0063646500585c5e026a6c6e00636465006a6c6e0063646500463d3c00585c5e00
+ecf3f500ffffff13f4f6f900e8ecef01e0e4e700d9dcde00e6dcdc00d9dcde01e6dcdc00
+d9dcde00e0e4e700b4b4b400888484007b7b7d00777474007b7b7d00777474006a6c6e02
+8c8b8c00cbcccd00ffffff1cf4f6f901e8ecef00d9dcde01cbcccd01c4c5c501cbcccd00
+867c7b00585c5e00777474077b7b7d03888484018c8b8c047b7b7d008c8b8c00ffffff4b
+ecf3f500e0e4e700d9dcde00d2d4d600c4c5c501bbbcbd01b4b4b402bbbcbd00b4b4b400
+a4a5a4004a4c4d00545455004a4c4d00545455007b7b7d00888484067b7b7d0488848400
+7b7b7d00888484018c8b8c00888484008c8b8c00d2d4d600ffffff0eecf3f501e8ecef00
+e0e4e700d9dcde01d2d4d601cbcccd00c4c5c501bbbcbd02b4b4b403abacad00b4b4b400
+abacad04a4a5a4008c8b8c037b7b7d04777474006a6c6e00777474016a6c6e0077747400
+6a6c6e01636465036a6c6e01777474027b7b7d02888484007b7b7d00888484008c8b8c00
+99939300c4c5c500ffffff06ecf3f500e8ecef00d9dcde00d2d4d600cbcccd00c4c5c500
+bbbcbd00abacad01a4a5a400abacad00a4a5a4017b7b7d0045444500463d3c0035343400
+463d3c00353434042e2c2d00454445006a6c6e04636465006a6c6e00636465026a6c6e00
+636465066a6c6e01bbbcbd00e0e4e700d9dcde00d2d4d600cbcccd00bbbcbd00b4b4b400
+abacad009c9e9c00a4a5a4009c9e9c00a4a5a4009c9e9c006a6c6e00454445054a4c4d01
+454445004a4c4d0145444500585c5e007b7b7d00888484017b7b7d00888484007b7b7d00
+888484008c8b8c007b7b7d00888484007b7b7d01777474016a6c6e0277747402d2d4d600
+ffffff22f4f6f901ecf3f500e8ecef02e0e4e701d9dcde00e0e4e700c4c5c5009c9e9c00
+776d6b00545455004a4c4d08545455084a4c4d00545455007774740099939300bbbcbd00
+d9dcde00e8ecef06e0e4e701bbbcbd00585c5e0154545502636465006a6c6e0077747400
+7b7b7d008c8b8c009c9e9c00a4a5a400b4b4b400c6bcba00cbcccd00d9dcde00e0e4e700
+e8ecef00ecf3f501f4f6f902ffffff21f4f6f902e8ecef03e0e4e702d9dcde00d2d4d600
+b4b4b400999393007b7b7d00777474006a6c6e00777474006a6c6e007b7b7d0077747400
+7b7b7d00777474007b7b7d04777474006a6c6e00777474006a6c6e007b7b7d0099939300
+c4c5c500ecf3f500ffffff24f4f6f900ffffff00f4f6f900e8ecef02e0e4e702d9dcde00
+e0e4e702d2d4d600b4b4b40088848400585c5e01636465026a6c6e00454445008c8b8c00
+ffffff16f4f6f900ecf3f500e8ecef01e0e4e700e8ecef00e0e4e700e8ecef01ecf3f500
+e8ecef00999393007b7b7d01777474017b7b7d00a4a5a400e8ecef00ffffff1ef4f6f900
+ecf3f500e0e4e700e6dcdc00d2d4d600cbcccd01c4c5c501b4b4b4004a4c4d006a6c6e01
+777474046a6c6e007b7b7d006a6c6e007b7b7d028c8b8c00888484018c8b8c0088848400
+8c8b8c0088848401abacad00ffffff4becf3f500e8ecef00e0e4e700d9dcde00cbcccd00
+c4c5c500bbbcbd01b4b4b400c6bcba00bbbcbd00b4b4b400bbbcbd00a4a5a4004a4c4d00
+584c48004a4c4d00584c480063646500888484027b7b7d008c8b8c007b7b7d0a8c8b8c00
+7b7b7d01bbbcbd00ffffff0ff4f6f900ecf3f500e8ecef00e0e4e701d9dcde01d2d4d601
+cbcccd01c4c5c501bbbcbd02b4b4b400bbbcbd00b4b4b408abacad009c9e9c0088848400
+7b7b7d036a6c6e00777474006a6c6e01777474006a6c6e01636465056a6c6e027b7b7d04
+8c8b8c00b4b4b400d9dcde00f4f6f900ffffff07f4f6f900e8ecef00e0e4e700d9dcde00
+d2d4d600cbcccd00bbbcbd01abacad00b4b4b404a4a5a4008c8b8c00776d6b004a4c4d00
+463d3c013b3c3d0035343402454445006a6c6e04636465006a6c6e00636465006a6c6e00
+636465016a6c6e00636465066a6c6e00bbbcbd00e8ecef00d9dcde01cbcccd00c4c5c500
+bbbcbd00b4b4b400abacad00a4a5a400abacad03a4a5a4008c8b8c0077747400585c5e00
+4a4c4d014544450055454100454445004a4c4d00454445004a4c4d00585c5e007b7b7d00
+888484037b7b7d00888484007b7b7d00888484007b7b7d036a6c6e00777474026a6c6e00
+777474006a6c6e00d2d4d600ffffff25f4f6f901e8ecef03e0e4e702d9dcde00cbcccd00
+a4a5a4007b7b7d00636465004a4c4d03545455004a4c4d0054545504585c5e006a6c6e00
+888484009c9e9c00bbbcbd00e0e4e700e8ecef01ecf3f500f4f6f904ecf3f501f7ece700
+e8ecef01d9dcde00abacad00bbbcbd00c4c5c500cbcccd00d9dcde00e0e4e701e8ecef06
+ecf3f501f4f6f903ffffff27f4f6f901f7ece700ecf3f500e8ecef03e0e4e702d9dcde00
+c4c5c500a4a5a4009c9e9c00888484007b7b7d00777474027b7b7d00777474016a6c6e00
+7b7b7d008c8b8c009c9e9c00b4b4b400d2d4d600f4f6f900ffffff2af4f6f901ecf3f501
+e8ecef04e0e4e700ecf3f500e8ecef00ecf3f500d9dcde00a4a5a400777474006a6c6e00
+636465006a6c6e00cbcccd00ffffff18f4f6f901f7ece700ecf3f500e8ecef00ecf3f501
+f4f6f902e0e4e7007b7b7d018c8b8c00c4c5c500f4f6f900ffffff20f4f6f900e8ecef00
+e0e4e700d9dcde00d2d4d600cbcccd01c4c5c5018884840054545500777474017b7b7d01
+777474007b7b7d03777474006a6c6e007b7b7d04888484028c8b8c0088848400ecf3f500
+ffffff35f4f6f900ffffff14f4f6f900e8ecef00e0e4e700d9dcde00d2d4d600c4c5c500
+c6bcba00bbbcbd01b4b4b400bbbcbd00b4b4b4019c9e9c004a4c4d03585c5e0088848400
+8c8b8c007b7b7d008c8b8c007b7b7d046a6c6e00777474007b7b7d05888484007b7b7d00
+abacad00ffffff10f4f6f901ecf3f501e0e4e701d9dcde01d2d4d601cbcccd02c4c5c502
+bbbcbd08c4c5c500bbbcbd00c4c5c500bbbcbd00b4b4b4009c9e9c00888484007b7b7d01
+6a6c6e0463646502585c5e00636465026a6c6e03888484009c9e9c00c4c5c500e8ecef00
+ffffff0bf4f6f900ecf3f500e8ecef00e0e4e700d9dcde00d2d4d600c4c5c501bbbcbd00
+b4b4b400bbbcbd05c4c5c500bbbcbd00a4a5a4008c8b8c006364650045444500463d3c01
+4a4c4d00777474016a6c6e01777474006a6c6e037b7b7d018c8b8c009c9e9c00a4a5a400
+b4b4b400bbbcbd00cbcccd00d2d4d600e0e4e700e8ecef02e0e4e700d9dcde00d2d4d601
+c4c5c500bbbcbd00b4b4b405bbbcbd00b4b4b401bbbcbd00b4b4b4009c9e9c008c8b8c00
+6a6c6e0054545500463d3c004544450055454100585c5e007b7b7d00888484028c8b8c00
+7b7b7d00888484007b7b7d018c8b8c019c9e9c00a4a5a400abacad00bbbcbd01cbcccd00
+d9dcde00e8ecef00ecf3f500ffffff27f4f6f900ffffff00f4f6f900e8ecef03e0e4e704
+d9dcde00cbcccd00b4b4b4009c9e9c00978c8a00888484018c8b8c019c9e9c00b4b4b400
+c4c5c500d2d4d600e0e4e700e8ecef02ecf3f501f4f6f902ffffff01f4f6f900ffffff00
+f4f6f905e8ecef05ecf3f500e8ecef00f4f6f900e8ecef00f4f6f901ecf3f500f4f6f903
+ffffff2df4f6f901ecf3f501e8ecef08d9dcde00d2d4d600c4c5c500bbbcbd00c4c5c500
+bbbcbd00cbcccd00d9dcde00e8ecef00ecf3f500ffffff30f4f6f902ecf3f505f4f6f901
+ffffff02d9dcde00b4b4b400ffffff1df4f6f902ffffff04d9dcde01f4f6f900ffffff22
+f4f6f900e8ecef00d9dcde00d2d4d601cbcccd00c4c5c501c6bcba004a4c4d006a6c6e01
+777474007b7b7d006a6c6e007b7b7d01777474016a6c6e027b7b7d006a6c6e007b7b7d01
+8c8b8c007b7b7d008c8b8c007b7b7d008c8b8c009c9e9c00ffffff35b4b4b4004a4c4d00
+d9dcde00ffffff14ecf3f500e0e4e700d9dcde00d2d4d600c4c5c501bbbcbd00b4b4b402
+bbbcbd01978c8a004a4c4d00454445004a4c4d0154545500888484007b7b7d008c8b8c00
+7b7b7d008c8b8c007b7b7d046a6c6e007b7b7d006a6c6e007b7b7d059c9e9c00ffffff12
+f4f6f901ecf3f500e8ecef00e0e4e701d9dcde02d2d4d601cbcccd04c4c5c500cbcccd00
+c4c5c505cbcccd00c4c5c500d2d4d600cbcccd00d2d4d600cbcccd00bbbcbd00abacad00
+9c9e9c007b7b7d00777474006a6c6e0163646505777474008c8b8c00abacad00cbcccd00
+ecf3f500f4f6f900ffffff0ef4f6f900ecf3f500e8ecef00e0e4e700d9dcde01cbcccd01
+c4c5c504cbcccd02c4c5c500cbcccd01d2d4d602abacad008c8b8c006a6c6e008c8b8c00
+9c9e9c00abacad00bbbcbd00c4c5c500d2d4d600e0e4e700e8ecef00f4f6f900ffffff09
+ecf3f502e8ecef00e0e4e700d9dcde00d2d4d600c4c5c501bbbcbd04c4c5c500bbbcbd00
+c4c5c500bbbcbd00c4c5c501cbcccd00d2d4d601d9dcde00c4c5c500a4a5a40088848400
+7b7b7d009c9e9c00abacad00b4b4b400c4c5c500cbcccd00d9dcde00e0e4e700e8ecef00
+ecf3f500f4f6f900ffffff03f4f6f900ffffff01f4f6f900ffffff2cf4f6f902ecf3f501
+e8ecef03e0e4e700e8ecef00e0e4e705e8ecef05ecf3f501f4f6f902ffffff0bf4f6f90a
+ffffff00f4f6f900ffffff35f4f6f900ecf3f500ffffff00ecf3f50bf4f6f902ffffff38
+f4f6f900ffffff53f4f6f900e8ecef00e0e4e700d9dcde00d2d4d600cbcccd02c4c5c500
+8c8b8c004a4c4d00777474006a6c6e00777474026a6c6e017b7b7d006a6c6e007b7b7d00
+6a6c6e027b7b7d006a6c6e007b7b7d05e0e4e700ffffff34d2d4d600454445014a4c4d00
+d2d4d600ffffff12f4f6f900ecf3f500e8ecef00e0e4e700d2d4d600cbcccd00bbbcbd03
+b4b4b400bbbcbd00b4b4b40077747400454445004a4c4d038c8b8c007b7b7d008c8b8c00
+7b7b7d06777474007b7b7d016a6c6e007b7b7d006a6c6e007b7b7d0299939300ffffff14
+f4f6f901ecf3f501e8ecef00e0e4e701d9dcde03d2d4d601cbcccd00d2d4d600cbcccd01
+d2d4d600cbcccd00d2d4d606d9dcde01e0e4e702e8ecef00d9dcde00cbcccd00c4c5c500
+bbbcbd00c4c5c500bbbcbd00d2d4d600e0e4e700ecf3f500ffffff15ecf3f502e0e4e700
+d9dcde01d2d4d600cbcccd02d2d4d601cbcccd02d2d4d602d9dcde00e0e4e701e8ecef00
+ecf3f500f4f6f900ffffff13ecf3f501e8ecef00e0e4e700d9dcde01d2d4d601c4c5c503
+cbcccd00c4c5c501cbcccd03d2d4d600d9dcde00e0e4e702ecf3f502f4f6f906ffffff3a
+f4f6f901ecf3f500f4f6f900e8ecef00ecf3f500e8ecef04ecf3f500e8ecef00ecf3f500
+e8ecef00ecf3f500e8ecef00f4f6f904ffffff12f4f6f900ffffff44f4f6f900ffffff02
+f4f6f900ffffff93ecf3f500e8ecef00d9dcde01d2d4d600cbcccd00c4c5c501bbbcbd00
+4a4c4d00636465006a6c6e01777474006a6c6e02777474006a6c6e007b7b7d006a6c6e06
+7b7b7d038c8b8c00ffffff34e0e4e700454445003b3c3d00463d3c00454445004a4c4d00
+d2d4d600ffffff12ecf3f500e8ecef00d9dcde00d2d4d600cbcccd00c4c5c500bbbcbd00
+b4b4b401bbbcbd00b4b4b40154545500454445004a4c4d00454445004a4c4d017b7b7d01
+8c8b8c007b7b7d076a6c6e007b7b7d006a6c6e007b7b7d00777474016a6c6e007b7b7d00
+8c8b8c00ffffff16f4f6f901ecf3f502e0e4e702d9dcde0de0e4e704e8ecef01ecf3f502
+f4f6f901ffffff1becf3f501e8ecef01d9dcde01d2d4d600d9dcde02d2d4d600d9dcde04
+e0e4e702ecf3f501f4f6f902ffffff12f4f6f900ecf3f502e0e4e701d9dcde00d2d4d602
+cbcccd00d2d4d607d9dcde01e0e4e700e8ecef00ecf3f502f4f6f900ffffff44f4f6f908
+ecf3f500f4f6f904fffffff4f4f6f900e8ecef00e0e4e700d9dcde00d2d4d600cbcccd01
+c4c5c500cbcccd008c8b8c004a4c4d006a6c6e0c777474006a6c6e047b7b7d006a6c6e00
+d2d4d600ffffff2ff4f6f902ffffff00e8ecef00545455003b3c3d034a4c4d0088848400
+ffffff12ecf3f500e8ecef00e0e4e700d2d4d600cbcccd00c4c5c500bbbcbd01b4b4b400
+bbbcbd00b4b4b40099939300454445024a4c4d0045444500585c5e008c8b8c007b7b7d07
+6a6c6e007b7b7d016a6c6e007b7b7d006a6c6e017b7b7d006a6c6e00777474008c8b8c00
+ffffff17f4f6f901ecf3f502e8ecef01e0e4e702d9dcde00e0e4e700d9dcde03e0e4e700
+d9dcde00e0e4e704e8ecef01ecf3f503f4f6f900ffffff1df4f6f900ecf3f502e8ecef00
+e0e4e701d9dcde04e0e4e700d9dcde00e0e4e704e8ecef00ecf3f502f4f6f900ffffff13
+f4f6f900ecf3f501e8ecef01e0e4e701d9dcde00d2d4d607d9dcde02e0e4e701e8ecef00
+ecf3f502f4f6f901ffffff44f4f6f900ffffff00f4f6f904ecf3f500f4f6f900ffffff00
+f4f6f901fffffff7f4f6f900e8ecef00e0e4e700d2d4d600d8cccb00cbcccd00c4c5c500
+cbcccd00c6bcba004a4c4d006a6c6e0c7b7b7d006a6c6e067b7b7d00ffffff2eecf3f501
+e8ecef00ecf3f501e8ecef0063646500353434013b3c3d0145444500636465007b7b7d00
+c4c5c500ffffff11ecf3f500e8ecef00d9dcde01cbcccd00c4c5c500b4b4b400bbbcbd00
+b4b4b400bbbcbd00b4b4b40063646500454445015545410045444501636465007b7b7d07
+6a6c6e007b7b7d006a6c6e017b7b7d006a6c6e007b7b7d006a6c6e007b7b7d006a6c6e01
+a4a5a400ffffff17f4f6f901ecf3f501e8ecef00e0e4e700e8ecef00e0e4e702d9dcde00
+e0e4e700d9dcde00e0e4e700d9dcde02e0e4e704e8ecef03ecf3f502f4f6f901ffffff1b
+f4f6f901ecf3f501e8ecef01e0e4e701d9dcde02e0e4e700d9dcde01e0e4e701d9dcde00
+e0e4e702e8ecef01ecf3f501f4f6f902ffffff10ecf3f502e8ecef01e0e4e701d9dcde01
+d2d4d601d9dcde00d2d4d600d9dcde00d2d4d600d9dcde01d2d4d600d9dcde01e0e4e701
+ecf3f500e8ecef00ecf3f501f4f6f900ffffff43f4f6f900ffffff00f4f6f901ffffff00
+f4f6f90bfffffff3f4f6f900e8ecef00e0e4e700d9dcde00d2d4d600cbcccd02c4c5c500
+8c8b8c004a4c4d00636465006a6c6e13c4c5c500ffffff2decf3f500e8ecef01e0e4e702
+7b7b7d002e2c2d00353434013b3c3d01585c5e007b7b7d02ffffff11ecf3f500e8ecef00
+d9dcde00d2d4d600cbcccd00bbbcbd01b4b4b400bbbcbd00b4b4b4009c9e9c0045444500
+463d3c00454445036a6c6e007b7b7d046a6c6e007b7b7d006a6c6e077b7b7d006a6c6e02
+b4b4b400ffffff17f4f6f902ecf3f500e8ecef01e0e4e702d9dcde00e0e4e700d9dcde02
+e0e4e700d9dcde00e0e4e700d9dcde00e0e4e702e8ecef00e0e4e700e8ecef02ecf3f501
+f4f6f902ffffff19f4f6f901ecf3f502e8ecef01e0e4e701d9dcde02e0e4e700d9dcde00
+e0e4e701d9dcde00e0e4e704e8ecef02ecf3f504f4f6f90decf3f502e8ecef02e0e4e701
+d9dcde02d2d4d602d9dcde00d2d4d600d9dcde00d2d4d601d9dcde01e0e4e703ecf3f502
+f4f6f901ffffff43f4f6f90effffff00f4f6f900fffffff2f4f6f900e8ecef00e0e4e700
+d2d4d601cbcccd00c4c5c50254545500636465036a6c6e11f4f6f900ffffff2bf4f6f900
+ecf3f500e8ecef00e0e4e700d9dcde0299939300353434002e2c2d00353434002e2c2d00
+353434004a4c4d00777474017b7b7d019c9e9c00ffffff10ecf3f500e8ecef00d9dcde00
+d2d4d600cbcccd00c4c5c500bbbcbd00b4b4b402585c5e003b3c3d01454445024a4c4d00
+7b7b7d056a6c6e0a7b7b7d006a6c6e01d2d4d600ffffff16f4f6f901ecf3f502e8ecef01
+e0e4e703d9dcde00e0e4e700d9dcde02e0e4e700d9dcde00e0e4e704e8ecef02ecf3f504
+f4f6f900ecf3f500f4f6f901ffffff00f4f6f900ffffff00f4f6f900ffffff00f4f6f901
+ffffff00f4f6f907ecf3f500f4f6f900ecf3f500f4f6f900ecf3f500f4f6f900ecf3f502
+e8ecef01e0e4e700e8ecef00e0e4e702d9dcde00e0e4e700d9dcde03e0e4e700d9dcde00
+e0e4e700d9dcde00e0e4e702e8ecef00e0e4e700e8ecef02ecf3f501e8ecef00ecf3f502
+e8ecef00ecf3f500e8ecef06ecf3f500e8ecef03e0e4e702d9dcde03d2d4d604d9dcde02
+d2d4d600d9dcde00d2d4d600d9dcde00e0e4e701e8ecef00ecf3f502f4f6f901ffffff41
+f4f6f911fffffff2f4f6f900e8ecef00e0e4e700d9dcde00d2d4d600cbcccd02c4c5c500
+999393003b3c3d00636465056a6c6e00636465006a6c6e03636465026a6c6e0463646500
+abacad00ffffff2cecf3f500e8ecef00d9dcde01d2d4d601a4a5a4003b3c3d0035343400
+2e2c2d01353434003b3c3d006a6c6e02777474007b7b7d01c4c5c500ffffff0ef4f6f900
+e8ecef00e0e4e700d9dcde00d2d4d600c4c5c500bbbcbd02b4b4b400888484003b3c3d04
+45444500636465007b7b7d046a6c6e007b7b7d006a6c6e02636465056a6c6e03e0e4e700
+ffffff09f4f6f900ffffff00f4f6f900ffffff00f4f6f900ffffff00f4f6f901ffffff00
+f4f6f901ecf3f500e8ecef03e0e4e703d9dcde02d2d4d601cbcccd00d2d4d602cbcccd00
+d2d4d608d9dcde03e0e4e700d9dcde07d2d4d600d9dcde00d2d4d608cbcccd00d2d4d600
+cbcccd06c4c5c504bbbcbd0bb4b4b400bbbcbd09b4b4b400bbbcbd00b4b4b401bbbcbd00
+b4b4b402bbbcbd00b4b4b400abacad00b4b4b400abacad00b4b4b400abacad00b4b4b400
+abacad02a4a5a400abacad00a4a5a4019c9e9c00a4a5a4009c9e9c02a4a5a4009c9e9c07
+a4a5a402abacad02b4b4b402bbbcbd01cbcccd00ffffff2fe8ecef00b4b4b4009c9e9c04
+999393009c9e9c01999393009c9e9c01999393009c9e9c028c8b8c009c9e9c018c8b8c00
+9c9e9c00999393019c9e9c00999393068c8b8c00999393048c8b8c02999393008c8b8c01
+999393008c8b8c01999393008c8b8c0b888484048c8b8c00888484018c8b8c0088848400
+8c8b8c00888484047b7b7d008c8b8c00888484017b7b7d00888484007b7b7d00867c7b00
+7b7b7d01888484007b7b7d01867c7b007b7b7d0a777474007b7b7d007774740a6a6c6e00
+777474006a6c6e00777474006a6c6e00777474006a6c6e00777474006a6c6e0077747400
+6a6c6e0c636465006a6c6e00636465006a6c6e00636465006a6c6e00636465006a6c6e00
+636465006a6c6e00675c5a0063646502675c5a0063646505585c5e00675c5a00585c5e00
+675c5a00585c5e0063646500585c5e00675c5a00585c5e00675c5a00585c5e0154545500
+585c5e0054545500585c5e0054545500585c5e0054545500585c5e0054545500585c5e00
+545455094a4c4d00584c48004a4c4d00584c48004a4c4d00584c48004a4c4d01584c4800
+4a4c4d00584c48004a4c4d00454445004a4c4d00454445004a4c4d0145444500584c4800
+4a4c4d00454445004a4c4d004544450a463d3c003b3c3d00454445003b3c3d00463d3c00
+3b3c3d00463d3c003b3c3d00463d3c003b3c3d00463d3c003b3c3d00353434003b3c3d00
+353434003b3c3d00353434003b3c3d00353434003b3c3d00353434003b3c3d003534340a
+2e2c2d00353434002e2c2d03353434002e2c2d00353434022e2c2d00353434002e2c2d03
+675c5a00ffffff00ecf3f500e8ecef00e0e4e700d9dcde00d2d4d600cbcccd00c4c5c502
+5454550163646501585c5e0063646501585c5e0063646500585c5e0063646500585c5e00
+63646502585c5e00636465006a6c6e0063646504ecf3f500ffffff06867c7b00150e0d00
+1a1b1a00150e0d011a1b1a00150e0d0a0c0b0c02150e0d000c0b0c00150e0d05e0e4e700
+ffffff07ecf3f500e8ecef00d9dcde01d2d4d600cbcccd00b4b4b4004544450035343402
+2e2c2d003b3c3d00636465016a6c6e01777474007b7b7d00777474007b7b7d00d9dcde00
+ffffff0decf3f500e8ecef00d9dcde01cbcccd00c4c5c501bbbcbd00b4b4b4008c8b8c00
+3b3c3d00353434003b3c3d02454445016a6c6e007b7b7d026a6c6e007b7b7d006a6c6e04
+63646502585c5e02636465016a6c6e007b7b7d00e0e4e700150e0d000402049e2e2c2d00
+7b7b7d00cbcccd00ffffff27e8ecef00b4b4b4006a6c6e001a1b1a00040204ff04020410
+585c5e00f4f6f900e8ecef00e0e4e700d9dcde00d2d4d600cbcccd01c4c5c5019c9e9c00
+3534340063646501585c5e0063646503585c5e0063646500585c5e0163646500585c5e00
+63646506585c5e009c9e9c00ffffff05f4f6f900e0e4e7000402041b24232400ffffff06
+ecf3f500e8ecef00d9dcde01d2d4d600cbcccd00bbbcbd00545455003b3c3d0035343402
+3b3c3d00585c5e006a6c6e00636465006a6c6e03777474007b7b7d008c8b8c00d2d4d600
+ffffff0becf3f500e8ecef00e0e4e700d9dcde00d2d4d601c4c5c500bbbcbd00b4b4b400
+7b7b7d00353434023b3c3d00353434003b3c3d01585c5e007b7b7d006a6c6e007b7b7d00
+6a6c6e007b7b7d006a6c6e007b7b7d006a6c6e0263646502585c5e0063646500585c5e01
+636465016a6c6e009c9e9c01040204a3353434007b7b7d00d2d4d600ffffff1ff4f6f900
+bbbcbd006a6c6e0024232400040204ff04020414bbbcbd00ecf3f500e8ecef00e0e4e700
+d9dcde00d8cccb00cbcccd01c4c5c501585c5e004a4c4d0063646500585c5e006a6c6e00
+63646504585c5e00636465046a6c6e0063646500585c5e0063646500585c5e0063646500
+585c5e00d9dcde00ffffff02f4f6f901ecf3f501777474000402041ca4a5a400ffffff04
+f4f6f900e8ecef00e0e4e700d9dcde00d2d4d600cbcccd00c4c5c5006a6c6e003b3c3d01
+35343402545455006a6c6e047b7b7d02777474007b7b7d006a6c6e008c8b8c00d2d4d600
+ffffff08ecf3f500e8ecef00e0e4e701d2d4d600cbcccd00c4c5c5019c9e9c004a4c4d00
+2e2c2d03353434013b3c3d00454445006a6c6e01777474006a6c6e007b7b7d006a6c6e03
+63646501585c5e0063646503585c5e00636465016a6c6e01b4b4b4002e2c2d0004020430
+170204000402040217020400040204021702040004020400170204000402040017020400
+040204001702040004020400170204000402040017020400040204001702040104020400
+170204020402040017020402040204001702042127020400170204002702040017020400
+270204001702040027020400170204012702040017020400270204001702040027020400
+170204002702040017020400270204001702040027020400170204002702041f58020400
+a6442b00e8bcb000ffffff1ba65b4500580204003a020406480204003a02040348020400
+3a020401480204003a020401480204013a020400480204013a020400480204013a020400
+480204165802040048020400580204004802040158020400480204005802040048020400
+580204004802040058020401480204005802041568020400580204036802040058020401
+680204005802040068020400580204006802040058020400680204005802040068020400
+580204006802041779020400680204017902040068020402790204006802040079020400
+680204007902040068020400790204016802040079020401680204007902041688020400
+790204008802040079020400880204007902040088020400790204008802040079020400
+88020403790204008802041c940204018802040094020401880204009402040188020400
+9402040ca002040094020400a002040094020400a002040094020400a002040094020400
+a002040094020400a002040294020400a002041cc4363800ecf3f500f7ece700e0e4e700
+d9dcde00d2d4d600cbcccd01c4c5c501a4a5a4003b3c3d00585c5e026a6c6e0163646500
+6a6c6e0063646502585c5e00636465036a6c6e0163646501585c5e018c8b8c00ffffff02
+f4f6f900ecf3f500e8ecef01d9dcde0004020401b302041bbf181800ffffff03ecf3f500
+e8ecef00e0e4e700d2d4d601cbcccd017b7b7d00454445013b3c3d013534340054545500
+6a6c6e00636465006a6c6e067b7b7d006a6c6e007b7b7d00636465003b3c3d0063646500
+b4b4b400ecf3f500ffffff04ecf3f501e0e4e701d2d4d601c4c5c5008c8b8c004a4c4d00
+2e2c2d00242324002e2c2d04353434003b3c3d00585c5e006a6c6e0763646503585c5e00
+63646500585c5e006a6c6e047b7b7d00abacad0004020405b3020400a0020400b3020400
+a0020400b3020400a0020400b3020400a0020400b3020400a0020400b3020400a0020400
+b3020400a0020400b3020400a0020400b3020400a0020400b3020400a0020400b3020400
+a0020400b3020401a0020400b3020401a0020400b3020400a0020400b3020400a0020400
+b3020400a0020400b3020401a0020400b3020402a0020400b3020401a0020400b3020400
+a0020400b3020401a0020400b3020400a0020400b3020400a0020400b3020400a0020401
+b3020400a0020401b3020400a0020401b3020400a0020402b3020400a0020402b3020400
+a0020402b3020400a002043894020400a002040094020400a002040094020400a0020400
+94020400a002040094020400a002040094020400a002040294020400a002040194020400
+a002040194020400a002040bcc626500ffffff1af9e4e100c4363800a0020400b3020400
+a0020400b3020400a0020401b3020400a0020401b3020400a0020400b3020400a0020400
+b3020400a0020401b3020400a0020400b3020400a0020400b3020400a0020401b3020400
+a0020400b3020400a0020400b3020400a0020401b3020400a0020400b3020400a0020400
+b3020400a0020400b3020400a0020400b302040aa0020400b3020404a0020400b3020404
+a0020400b3020402a0020400b3020401a0020400b3020484bc0b0e00b3020400bc0b0e01
+b3020400bc0b0e01b3020400bc0b0e01b3020400bc0b0e00b3020404bc0b0e00b3020404
+bc0b0e00b3020404bc0b0e00b3020423bc0b0e01b3020401bc0b0e00b3020400bc0b0e00
+b3020403e8a58f00e8ecef01e0e4e700d9dcde00d2d4d600cbcccd01c4c5c501585c5e00
+4a4c4d00636465036a6c6e00585c5e0063646501585c5e0263646500585c5e0063646501
+6a6c6e0063646500585c5e0063646501585c5e00d2d4d600f4f6f901ecf3f500e8ecef00
+e0e4e701d9dcde0077747400040204003a020400b302041cea7c5e00ffffff01f4f6f900
+ecf3f500e0e4e700d9dcde00d2d4d600cbcccd01999393003b3c3d01454445013b3c3d00
+4a4c4d006a6c6e087b7b7d006a6c6e01777474006a6c6e013b3c3d00353434003b3c3d00
+6364650099939300c4c5c500d9dcde00ecf3f500e8ecef00e0e4e700d9dcde00bbbcbd00
+8c8b8c00636465002e2c2d00242324022e2c2d0535343400545455006a6c6e0863646500
+585c5e0063646500585c5e026a6c6e037b7b7d006a6c6e008c8b8c004a4c4d0004020404
+58020400a0020400b3020401a0020400b3020401a0020400b3020400a0020400b3020401
+a0020400b3020400a0020400b3020400a0020400b3020400a0020400b3020400a0020400
+b3020400a0020400b3020400a0020400b3020400a0020401b3020400a0020400b3020400
+a0020400b3020400a0020400b3020400a0020401b3020400a0020402b3020400a0020401
+b3020400a0020401b3020400a0020402b3020400a0020403b3020400a0020401b3020400
+a0020401b3020400a002044194020400a002040194020400a002040294020400a0020401
+94020400a002040194020400a002040094020400a002040094020400a002040094020400
+a002040094020400a002040094020400a002040094020401a002040094020400a0020400
+94020405a002040094020400b2181a00e9d5d700ffffff19f4f6f900d8846e00b3020400
+a0020401b3020400a0020401b3020400a0020400b3020400a0020401b3020400a0020401
+b3020400a0020400b3020400a0020400b3020400a0020401b3020400a0020400b3020400
+a0020401b3020400a0020400b3020400a0020400b3020400a0020401b3020400a0020400
+b3020400a0020400b3020400a0020401b3020400a0020401b3020400a0020401b3020400
+a0020400b3020400a0020400b3020400a0020401b3020401a0020400b3020400a0020400
+b3020400a0020400b3020402a0020400b3020401a0020400b3020402a0020400b3020400
+a0020400b3020401a0020400b3020401a0020400b302044ebc0b0e00b3020400bc0b0e00
+b3020400bc0b0e00b3020400bc0b0e00b3020400bc0b0e00b3020400bc0b0e00b302040d
+bc0b0e00b3020405bc0b0e00b3020400bc0b0e00b3020400bc0b0e00b3020400bc0b0e01
+b3020400bc0b0e00b3020400bc0b0e00b3020400bc0b0e00b3020400bc0b0e00b3020400
+bc0b0e00b3020400bc0b0e00b3020400bc0b0e01b3020400bc0b0e02b3020400bc0b0e04
+b3020400bc0b0e05b3020400bc0b0e07b3020400bc0b0e01b3020400bc0b0e02b3020400
+bc0b0e02b3020400bc0b0e00b3020402bc0b0e06b3020400bc0b0e02b3020400bc0b0e00
+b3020400bc0b0e00b3020400bc0b0e00b3020400bc0b0e00b3020400bc0b0e01c4232400
+e8ecef01e0e4e700d9dcde00d2d4d600d8cccb00cbcccd00c4c5c501a4a5a4003b3c3d00
+585c5e0063646500585c5e0063646504585c5e0463646500585c5e01636465006a6c6e00
+6364650288848400ecf3f500f4f6f900ecf3f500e0e4e701d9dcde01d8cccb0004020401
+a0020400b3020402bc0b0e00b3020401bc0b0e00b3020400bc0b0e00b3020401bc0b0e00
+b3020411e5c4c200f4f6f900e8ecef00e0e4e700d9dcde01cbcccd01a4a5a4003b3c3d00
+353434003b3c3d00454445003b3c3d004a4c4d007b7b7d006a6c6e007b7b7d006a6c6e03
+636465016a6c6e027b7b7d006a6c6e02636465004a4c4d0035343401242324002e2c2d00
+242324003b3c3d01454445002e2c2d001a1b1a03242324042e2c2d012423240035343400
+54545500636465046a6c6e00636465006a6c6e0063646502585c5e01636465026a6c6e05
+9c9e9c0004020405a0020400b3020400a0020400b3020400a0020400b3020400a0020400
+b3020400a0020400b3020401a0020400b3020400a0020400b3020400a0020400b3020400
+a0020400b3020400a0020400b3020400a0020400b3020400a0020400b3020400a0020400
+b3020400a0020400b3020400a0020400b3020400a0020400b3020400a0020400b3020400
+a0020400b3020400a0020400b3020400a0020400b3020400a0020400b3020400a0020401
+b3020400a0020401b3020400a0020400b3020400a0020402b3020400a0020409b3020400
+a0020400b3020400a0020400b3020400a0020400b3020400a0020401b3020400a0020401
+b3020400a0020401b3020400a0020401b3020400a002041f94020400a002040394020400
+a002040094020400a002040094020400a002040094020400a002040194020400a0020401
+94020400a002040094020400a002040194020400a002040194020400a002040294020400
+a002040194020400a002040194020400a002040094020400a002040094020400a0020400
+94020401a002040094020400a002040194020400a002040094020401a0020401d98c7800
+ffffff1ad7c4bd00bf181800a0020401b3020400a0020401b3020400a0020401b3020400
+a0020400b3020400a0020400b3020400a0020401b3020400a0020400b3020400a0020400
+b3020400a0020401b3020400a0020400b3020400a0020400b3020400a0020400b3020400
+a0020400b3020400a0020400b3020400a0020400b3020400a0020400b3020401a0020400
+b3020401a0020400b3020401a0020400b3020401a0020400b3020402a0020400b3020401
+a0020400b3020400a0020400b3020401a0020400b3020401a0020400b3020401a0020400
+b3020400a0020400b3020403a0020400b3020404a0020400b3020400a0020400b3020400
+a0020400b3020401a0020400b3020401a0020400b302043bbc0b0e00b3020400bc0b0e00
+b3020400bc0b0e00b3020404bc0b0e00b3020401bc0b0e00b3020400bc0b0e00b3020400
+bc0b0e00b3020400bc0b0e07b3020400bc0b0e01b3020400bc0b0e00b3020400bc0b0e00
+b3020400bc0b0e01b3020400bc0b0e00b3020400bc0b0e00b3020400bc0b0e00b3020400
+bc0b0e00b3020400bc0b0e00b3020400bc0b0e01b3020400bc0b0e00b3020400bc0b0e00
+b3020400bc0b0e01b3020400bc0b0e01b3020400bc0b0e00b3020400bc0b0e00b3020400
+bc0b0e00b3020400bc0b0e00b3020400bc0b0e00b3020400bc0b0e01b3020400bc0b0e00
+b3020400bc0b0e00b3020400bc0b0e00b3020400bc0b0e00b3020400bc0b0e01b3020400
+bc0b0e00b3020400bc0b0e02b3020400bc0b0e00b3020400bc0b0e00b3020400bc0b0e01
+b3020400bc0b0e01b3020400bc0b0e02b3020400bc0b0e00b3020400bc0b0e00b3020401
+bc0b0e00b3020400bc0b0e00b3020400bc0b0e01b3020400bc0b0e02b3020400bc0b0e00
+b3020400bc0b0e00b3020401e59c8700e8ecef01e0e4e700d9dcde00d2d4d600cbcccd01
+c4c5c500cbcccd00636465004a4c4d0063646503585c5e0d63646502c4c5c500ecf3f501
+e0e4e700d9dcde01d2d4d600cbcccd007b7b7d000402040027020400b3020401bc0b0e00
+b3020400bc0b0e00b3020400bc0b0e00b3020402bc0b0e00b3020401bc0b0e00b3020400
+bc0b0e00b3020400bc0b0e00b3020400bc0b0e00b3020400bc0b0e00b3020408b0262800
+d9dcde00e8ecef00d9dcde01cbcccd01c4c5c500636465002e2c2d01353434003b3c3d00
+45444500777474007b7b7d01777474006a6c6e0263646501585c5e006a6c6e0763646500
+585c5e004544450035343400242324002e2c2d001a1b1a04242324001a1b1a0124232400
+1a1b1a0124232402353434004a4c4d00585c5e0463646502585c5e0063646502585c5e00
+63646500585c5e00636465026a6c6e00636465006a6c6e017b7b7d014a4c4d0004020404
+27020400b3020400a0020400b3020402a0020400b3020401a0020400b3020400a0020400
+b3020400a0020400b3020400a0020400b3020400a0020400b3020401a0020400b3020400
+a0020401b3020400a0020400b3020400a0020400b3020400a0020401b3020400a0020401
+b3020400a0020401b3020400a0020400b3020400a0020400b3020400a0020401b3020400
+a0020401b3020400a0020403b3020400a0020400b3020400a0020401b3020400a0020400
+b3020400a0020400b3020400a0020400b3020400a0020418b3020400a002041d94020400
+a002040794020400a002040294020400a002040294020400a002040194020400a0020400
+94020400a002040094020400a002040194020400a002040094020400a002040094020400
+a002040194020400a002040194020400a002040094020400a002040094020402a0020400
+94020400a002040094020400a002040094020400a0020400b0262800f9e4e100ffffff08
+f4f6f900ffffff0ef4f6f900e0e4e700c75c4d00b3020400a0020400b3020400a0020401
+b3020400a0020400b3020400a0020401b3020400a0020401b3020400a0020401b3020400
+a0020400b3020400a0020400b3020400a0020400b3020400a0020400b3020400a0020400
+b3020400a0020400b3020400a0020400b3020400a0020400b3020400a0020400b3020400
+a0020400b3020400a0020400b3020400a0020400b3020401a0020400b3020400a0020400
+b3020401a0020400b3020400a0020400b3020401a0020400b3020404a0020400b3020400
+a0020400b3020401a0020400b3020404a0020400b3020404a0020400b3020405a0020400
+b3020408a0020400b3020428bc0b0e00b3020401bc0b0e00b3020402bc0b0e00b3020400
+bc0b0e00b3020400bc0b0e00b3020400bc0b0e00b3020404bc0b0e01b3020400bc0b0e00
+b3020400bc0b0e00b3020400bc0b0e00b3020400bc0b0e00b3020401bc0b0e00b3020400
+bc0b0e00b3020406bc0b0e00b3020400bc0b0e00b3020400bc0b0e01b3020400bc0b0e00
+b3020400bc0b0e00b3020400bc0b0e00b3020400bc0b0e00b3020400bc0b0e00b3020400
+bc0b0e01b3020400bc0b0e00b3020401bc0b0e00b3020400bc0b0e00b3020400bc0b0e00
+b3020400bc0b0e00b3020400bc0b0e00b3020400bc0b0e00b3020400bc0b0e00b3020400
+bc0b0e00b3020400bc0b0e02b3020400bc0b0e00b3020400bc0b0e01b3020400bc0b0e00
+b3020400bc0b0e02b3020400bc0b0e00b3020400bc0b0e03b3020401bc0b0e00b3020400
+bc0b0e01b3020400bc0b0e01b3020400bc0b0e00b3020400bc0b0e02b3020400bc0b0e00
+b3020400bc0b0e00b3020400bc0b0e00b3020400bc0b0e02b3020400bc0b0e00b3020400
+bc0b0e00b3020400bc0b0e00b3020401bc0b0e01b3020400bc0b0e01bf181800e0e4e700
+e8ecef00e0e4e700d9dcde00d2d4d600cbcccd02c4c5c500a4a5a4003b3c3d00585c5e00
+63646504585c5e0063646500585c5e0354545500585c5e0363646500585c5e0063646501
+7b7b7d00ecf3f501e0e4e701d2d4d600cbcccd02170204000402040094020400bc0b0e00
+b3020401bc0b0e00b3020403bc0b0e00b3020401bc0b0e00b3020401bc0b0e00b3020401
+bc0b0e00b3020403bc0b0e00b3020408a8655400d9dcde01d2d4d600cbcccd00c4c5c501
+a4a5a400353434002e2c2d013b3c3d0063646500777474006a6c6e01777474006a6c6e01
+63646502585c5e00636465006a6c6e05585c5e0063646502585c5e004a4c4d0035343400
+2e2c2d00242324001a1b1a06242324001a1b1a00242324002e2c2d004a4c4d0054545500
+585c5e10636465026a6c6e038c8b8c000402040588020400b3020401a0020400b3020400
+a0020400b3020401a0020400b3020400a0020400b3020400a0020400b3020400a0020400
+b3020400a0020400b3020400a0020401b3020400a0020400b3020401a0020401b3020400
+a0020401b3020400a0020400b3020400a0020400b3020400a0020401b3020400a0020400
+b3020400a0020402b3020400a0020400b3020400a0020400b3020400a0020401b3020400
+a0020400b3020400a0020403b3020400a0020408b3020400a0020401b3020400a0020402
+b3020400a0020401b3020400a0020401b3020400a002042294020400a002040194020400
+a002040294020400a002040194020400a002040094020400a002040294020400a0020402
+94020400a002040294020400a002040194020400a002040194020400a002040094020400
+a002040094020400a002040194020400a002040094020400a002040094020400a0020400
+94020400a002040094020400a002040194020400a002040094020400a002040094020400
+a002040094020401a0020401dba39300ffffff04f4f6f900ffffff11f4f6f900ecf3f500
+e8ecef00c8a49d00b3020400a0020400b3020400a0020401b3020400a0020401b3020400
+a0020401b3020400a0020400b3020400a0020401b3020400a0020400b3020400a0020400
+b3020400a0020400b3020400a0020400b3020400a0020400b3020400a0020400b3020400
+a0020400b3020400a0020400b3020401a0020400b3020401a0020400b3020400a0020400
+b3020400a0020400b3020401a0020400b3020400a0020400b3020401a0020400b3020401
+a0020400b3020400a0020400b3020400a0020400b3020403a0020400b3020401a0020400
+b3020400a0020400b3020401a0020400b3020400a0020400b302040ba0020400b3020401
+a0020400b3020405a0020400b3020422bc0b0e00b3020409bc0b0e00b3020401bc0b0e00
+b3020401bc0b0e00b3020400bc0b0e00b3020400bc0b0e00b3020401bc0b0e00b3020402
+bc0b0e00b3020401bc0b0e00b3020400bc0b0e00b3020401bc0b0e00b3020400bc0b0e04
+b3020400bc0b0e00b3020400bc0b0e00b3020400bc0b0e00b3020400bc0b0e00b3020400
+bc0b0e00b3020400bc0b0e00b3020400bc0b0e00b3020400bc0b0e00b3020400bc0b0e00
+b3020401bc0b0e01b3020400bc0b0e00b3020400bc0b0e00b3020400bc0b0e01b3020400
+bc0b0e01b3020400bc0b0e00b3020400bc0b0e00b3020400bc0b0e00b3020400bc0b0e00
+b3020400bc0b0e01b3020400bc0b0e00b3020400bc0b0e00b3020400bc0b0e02b3020400
+bc0b0e00b3020400bc0b0e02b3020401bc0b0e03b3020400bc0b0e00b3020400bc0b0e00
+b3020400bc0b0e00b3020400bc0b0e01b3020400bc0b0e00b3020400bc0b0e00b3020400
+bc0b0e00b3020400bc0b0e02b3020400bc0b0e00b3020400bc0b0e02b3020400bc0b0e00
+b3020400bc0b0e02b3020400bc0b0e00b3020400bc0b0e00b3020400e78b7100e8ecef00
+e0e4e700e6dcdc00d9dcde00d2d4d600cbcccd01c4c5c501636465004a4c4d00585c5e03
+63646500585c5e0263646500585c5e0863646500585c5e0063646500b4b4b400ecf3f500
+e8ecef00d9dcde00d2d4d601cbcccd00c4c5c500888484000402040017020400b3020401
+bc0b0e00b3020401bc0b0e00b3020400bc0b0e00b3020400bc0b0e00b3020400bc0b0e00
+b3020401bc0b0e00b3020401bc0b0e00b3020401bc0b0e00b3020403bc0b0e00b3020401
+bc0b0e00b3020403a0020400b7a4a000d2d4d600cbcccd00c4c5c502bbbcbd008c8b8c00
+2e2c2d0035343400545455006a6c6e046364650b585c5e0063646500585c5e0063646503
+585c5e014a4c4d003b3c3d002e2c2d001a1b1a01242324022e2c2d003b3c3d004a4c4d00
+545455004a4c4d01545455004a4c4d02545455004a4c4d03585c5e08636465016a6c6e01
+7b7b7d01454445000402040417020400b3020400a0020400b3020401a0020400b3020400
+a0020400b3020400a0020400b3020401a0020400b3020400a0020400b3020401a0020400
+b3020400a0020400b3020400a0020400b3020400a0020401b3020400a0020400b3020400
+a0020400b3020400a0020400b3020400a0020400b3020400a0020400b3020400a0020400
+b3020400a0020401b3020400a0020400b3020400a0020402b3020400a0020401b3020400
+a0020400b3020400a0020401b3020400a0020403b3020400a0020400b3020400a0020400
+b3020400a0020400b3020400a0020405b3020400a0020409b3020400a002042894020400
+a002040194020400a002040094020400a002040194020400a002040094020400a0020401
+94020400a002040194020400a002040094020400a002040094020400a002040094020400
+a002040194020400a002040094020400a002040094020400a002040194020400a0020400
+94020400a002040094020401a002040094020401a002040094020402a002040094020400
+a002040094020400a0020400cf4d4f00e8ecef00ffffff15f4f6f901e8ecef00e0e4e700
+d8cccb00b9462700a0020401b3020400a0020400b3020400a0020400b3020400a0020400
+b3020400a0020401b3020400a0020400b3020400a0020401b3020400a0020400b3020400
+a0020400b3020400a0020401b3020400a0020400b3020400a0020400b3020400a0020400
+b3020400a0020400b3020400a0020400b3020400a0020400b3020400a0020400b3020400
+a0020400b3020401a0020400b3020400a0020400b3020401a0020400b3020400a0020400
+b3020400a0020400b3020401a0020400b3020401a0020400b3020400a0020400b3020401
+a0020400b3020403a0020400b3020404a0020400b3020401a0020400b3020400a0020400
+b3020401a0020400b3020406a0020400b3020404a0020400b3020402a0020400b3020423
+bc0b0e00b3020400bc0b0e00b3020404bc0b0e00b3020402bc0b0e00b3020401bc0b0e00
+b3020402bc0b0e01b3020401bc0b0e00b3020401bc0b0e00b3020400bc0b0e00b3020401
+bc0b0e00b3020403bc0b0e00b3020400bc0b0e00b3020400bc0b0e00b3020400bc0b0e00
+b3020400bc0b0e00b3020400bc0b0e00b3020400bc0b0e00b3020400bc0b0e00b3020400
+bc0b0e00b3020400bc0b0e01b3020400bc0b0e00b3020400bc0b0e00b3020400bc0b0e01
+b3020400bc0b0e00b3020400bc0b0e00b3020400bc0b0e00b3020400bc0b0e01b3020400
+bc0b0e01b3020400bc0b0e00b3020400bc0b0e01b3020400bc0b0e01b3020400bc0b0e00
+b3020400bc0b0e00b3020400bc0b0e02b3020400bc0b0e02b3020400bc0b0e00b3020400
+bc0b0e00b3020400bc0b0e01b3020400bc0b0e00b3020400bc0b0e00b3020400bc0b0e00
+b3020400bc0b0e00b3020400bc0b0e02b3020400bc0b0e00b3020400bc0b0e01b3020400
+bc0b0e00b3020400bc0b0e00b3020400bc0b0e01b3020400bc0b0e00b3020401bc0b0e00
+b3020400bc0b0e00b3020400bf181800e6dcdc00e8ecef00e0e4e700d9dcde00d2d4d600
+d8cccb00cbcccd00c4c5c501abacad002e2c2d00585c5e0463646502585c5e026a6c6e00
+585c5e01636465006a6c6e0063646500585c5e00636465026a6c6e00e8ecef01e0e4e700
+d9dcde01cbcccd00c4c5c5011a1b1a000402040088020400b3020401bc0b0e00b3020400
+bc0b0e00b3020400bc0b0e00b3020400bc0b0e00b3020403bc0b0e00b3020401bc0b0e00
+b3020405bc0b0e00b302040988020400c4c5c503bbbcbd02585c5e0045444500585c5e00
+63646504585c5e0063646500585c5e0163646506585c5e0263646500585c5e0063646500
+585c5e05545455014a4c4d01545455034a4c4d07454445024a4c4d04545455024a4c4d01
+585c5e02636465016a6c6e007b7b7d000402040579020400b3020400a0020400b3020400
+a0020400b3020401a0020400b3020401a0020400b3020400a0020400b3020401a0020400
+b3020400a0020400b3020400a0020400b3020400a0020400b3020400a0020400b3020400
+a0020400b3020400a0020400b3020400a0020400b3020400a0020401b3020400a0020401
+b3020400a0020401b3020400a0020400b3020400a0020400b3020400a0020400b3020400
+a0020401b3020400a0020402b3020400a0020402b3020400a0020400b3020400a0020408
+b3020400a0020400b3020400a0020403b3020400a0020402b3020400a0020406b3020400
+a0020407b3020400a002040e94020400a002040394020400a002040394020400a0020402
+94020400a002040494020400a002040394020400a002040094020400a002040094020400
+a002040194020400a002040394020400a002040194020400a002040094020400a0020400
+94020400a002040094020400a002040094020400a002040094020400a002040094020400
+a002040094020400a002040094020400a002040094020400a002040094020400a0020400
+94020400a0020401e8bcb000ffffff03f4f6f900ffffff10f4f6f900ecf3f500e8ecef01
+e0e4e700c88b7d00b3020400a0020402b3020400a0020401b3020400a0020400b3020400
+a0020400b3020400a0020400b3020400a0020401b3020400a0020400b3020400a0020400
+b3020400a0020400b3020400a0020400b3020400a0020400b3020401a0020400b3020400
+a0020400b3020400a0020400b3020400a0020400b3020401a0020400b3020400a0020400
+b3020402a0020400b3020401a0020400b3020402a0020400b3020401a0020400b3020403
+a0020400b3020401a0020400b3020400a0020400b3020402a0020400b3020400a0020400
+b302040ba0020400b302042ebc0b0e00b3020401bc0b0e00b3020404bc0b0e00b3020402
+bc0b0e00b3020400bc0b0e00b3020400bc0b0e00b3020401bc0b0e00b3020400bc0b0e00
+b3020401bc0b0e00b3020400bc0b0e00b3020400bc0b0e00b3020401bc0b0e00b3020400
+bc0b0e00b3020400bc0b0e01b3020400bc0b0e00b3020400bc0b0e00b3020400bc0b0e00
+b3020400bc0b0e00b3020400bc0b0e00b3020400bc0b0e00b3020400bc0b0e00b3020400
+bc0b0e00b3020400bc0b0e00b3020400bc0b0e00b3020401bc0b0e00b3020400bc0b0e01
+b3020400bc0b0e00b3020400bc0b0e00b3020400bc0b0e00b3020400bc0b0e00b3020400
+bc0b0e00b3020400bc0b0e00b3020400bc0b0e00b3020400bc0b0e00b3020400bc0b0e00
+b3020400bc0b0e00b3020400bc0b0e01b3020400bc0b0e00b3020400bc0b0e01b3020400
+bc0b0e00b3020400bc0b0e00b3020400bc0b0e00b3020400bc0b0e00b3020400bc0b0e00
+b3020400bc0b0e01b3020400bc0b0e02b3020400bc0b0e00b3020400bc0b0e00b3020400
+bc0b0e00b3020400bc0b0e00b3020400bc0b0e00b3020400bc0b0e00b3020400bc0b0e01
+b3020400bc0b0e01b3020400bc0b0e00b3020400bc0b0e00b3020400bc0b0e01b3020400
+bc0b0e01b3020400d8846e00e8ecef00e0e4e701d9dcde00d2d4d600cbcccd00c4c5c501
+cbcccd00636465003b3c3d00585c5e05636465046a6c6e00636465006a6c6e0063646503
+585c5e02b4b4b400ecf3f501e8ecef00d9dcde01d2d4d601b4b4b4000402040017020400
+b3020401bc0b0e00b3020401bc0b0e00b3020403bc0b0e00b3020400bc0b0e00b3020401
+bc0b0e00b3020401bc0b0e00b3020400bc0b0e00b302040e7c3a3c00c4c5c501bbbcbd03
+abacad006a6c6e0063646500585c5e0063646500585c5e0763646500585c5e0063646500
+585c5e0063646500585c5e0463646503585c5e02545455044a4c4d06454445064a4c4d00
+454445014a4c4d06585c5e03636465017b7b7d008c8b8c000402040417020400b3020400
+a0020400b3020401a0020400b3020400a0020400b3020400a0020400b3020400a0020400
+b3020400a0020400b3020400a0020400b3020400a0020400b3020400a0020400b3020400
+a0020400b3020400a0020400b3020400a0020400b3020400a0020400b3020400a0020400
+b3020400a0020400b3020400a0020401b3020400a0020400b3020400a0020400b3020400
+a0020402b3020400a0020400b3020400a0020400b3020400a0020402b3020400a0020401
+b3020400a0020405b3020400a0020400b3020400a0020401b3020400a002040ab3020400
+a0020402b3020400a002042494020400a002040394020400a002040294020400a0020400
+94020400a002040194020400a002040094020400a002040194020400a002040194020400
+a002040094020400a002040094020401a002040094020400a002040094020400a0020401
+94020400a002040094020400a002040094020401a002040094020401a002040094020400
+a002040094020401a002040094020402a002040094020403a002040094020400cc626500
+ffffff15f4f6f901e8ecef01e0e4e700d8bcb600c42c3000a0020400b3020400a0020401
+b3020400a0020400b3020400a0020401b3020400a0020401b3020400a0020400b3020400
+a0020401b3020400a0020400b3020400a0020400b3020400a0020400b3020400a0020400
+b3020400a0020400b3020401a0020400b3020400a0020400b3020401a0020400b3020400
+a0020400b3020401a0020400b3020400a0020400b3020400a0020400b3020401a0020400
+b3020401a0020400b3020401a0020400b3020400a0020400b3020401a0020400b3020401
+a0020400b3020401a0020400b3020406a0020400b3020401a0020400b3020401a0020400
+b3020404a0020400b3020402a0020400b302042dbc0b0e00b3020402bc0b0e00b3020400
+bc0b0e00b3020404bc0b0e00b3020401bc0b0e00b3020400bc0b0e00b3020401bc0b0e00
+b3020400bc0b0e00b3020401bc0b0e00b3020400bc0b0e00b3020400bc0b0e00b3020401
+bc0b0e00b3020400bc0b0e00b3020400bc0b0e00b3020400bc0b0e00b3020401bc0b0e00
+b3020400bc0b0e00b3020400bc0b0e00b3020400bc0b0e00b3020400bc0b0e00b3020400
+bc0b0e01b3020400bc0b0e00b3020400bc0b0e00b3020400bc0b0e01b3020400bc0b0e00
+b3020400bc0b0e01b3020400bc0b0e01b3020400bc0b0e00b3020400bc0b0e00b3020400
+bc0b0e01b3020400bc0b0e00b3020400bc0b0e01b3020400bc0b0e01b3020400bc0b0e00
+b3020400bc0b0e01b3020400bc0b0e00b3020400bc0b0e02b3020400bc0b0e01b3020400
+bc0b0e00b3020400bc0b0e00b3020400bc0b0e01b3020400bc0b0e01b3020400bc0b0e02
+b3020400bc0b0e00b3020400bc0b0e01b3020401bc0b0e01b3020400bc0b0e00b3020400
+bc0b0e00b3020400bc0b0e01b3020400bc0b0e00b3020400bc0b0e01e6dcdc00e8ecef01
+d9dcde00d2d4d600cbcccd02c4c5c500b4b4b4002e2c2d004a4c4d00545455014a4c4d00
+54545500585c5e04636465016a6c6e01636465006a6c6e0163646501585c5e016a6c6e00
+ecf3f500f4f6f901ecf3f500e8ecef00d9dcde02c4c5c5000402040079020400b3020402
+bc0b0e00b3020401bc0b0e00b3020400bc0b0e00b3020401bc0b0e00b3020400bc0b0e00
+b3020401bc0b0e00b3020403bc0b0e00b3020401bc0b0e00b3020401bc0b0e00b3020407
+a0020400978c8a00c4c5c500bbbcbd00c4c5c500bbbcbd02a4a5a40063646500585c5e05
+54545501585c5e0463646500585c5e0063646501585c5e0063646500585c5e0063646504
+585c5e04545455014a4c4d02454445013b3c3d004544450b3b3c3d00454445004a4c4d05
+585c5e00636465029c9e9c00cbcccd00b4b4b400241a18000402040279020400a0020400
+b3020401a0020400b3020400a0020400b3020401a0020400b3020401a0020400b3020400
+a0020400b3020400a0020400b3020400a0020400b3020400a0020400b3020400a0020400
+b3020400a0020401b3020400a0020400b3020400a0020401b3020400a0020400b3020400
+a0020400b3020400a0020401b3020400a0020400b3020400a0020400b3020400a0020404
+b3020400a0020400b3020400a0020400b3020400a0020402b3020400a0020400b3020400
+a0020400b3020400a0020407b3020400a0020402b3020400a0020400b3020400a0020409
+b3020400a0020404b3020400a002041594020400a002040694020400a002040394020400
+a002040294020400a002040194020400a002040194020400a002040194020400a0020401
+94020400a002040294020400a002040094020400a002040094020401a002040094020400
+a002040094020401a002040094020400a002040094020400a002040094020401a0020400
+94020401a002040094020400a002040094020402a002040094020400a002040094020401
+b2181a00d2d4d600ffffff00f4f6f900ffffff13ecf3f501e8ecef01d9dcde00c8745e00
+b3020400a0020400b3020400a0020401b3020400a0020400b3020400a0020400b3020400
+a0020400b3020400a0020400b3020400a0020400b3020400a0020400b3020400a0020400
+b3020400a0020400b3020400a0020400b3020400a0020400b3020400a0020400b3020400
+a0020400b3020401a0020400b3020400a0020400b3020401a0020400b3020400a0020400
+b3020401a0020400b3020400a0020400b3020400a0020400b3020400a0020400b3020401
+a0020400b3020401a0020400b3020402a0020400b3020402a0020400b3020401a0020400
+b3020400a0020400b3020400a0020400b3020402a0020400b3020404a0020400b3020411
+a0020400b3020419bc0b0e00b3020402bc0b0e00b3020401bc0b0e00b3020402bc0b0e00
+b3020401bc0b0e00b3020401bc0b0e00b3020400bc0b0e00b3020401bc0b0e00b3020403
+bc0b0e00b3020403bc0b0e00b3020400bc0b0e00b3020401bc0b0e00b3020400bc0b0e00
+b3020400bc0b0e00b3020401bc0b0e00b3020400bc0b0e00b3020400bc0b0e00b3020400
+bc0b0e00b3020400bc0b0e00b3020400bc0b0e00b3020400bc0b0e00b3020400bc0b0e00
+b3020400bc0b0e00b3020400bc0b0e00b3020400bc0b0e00b3020400bc0b0e00b3020400
+bc0b0e00b3020400bc0b0e00b3020400bc0b0e00b3020400bc0b0e00b3020401bc0b0e00
+b3020400bc0b0e00b3020400bc0b0e00b3020400bc0b0e01b3020400bc0b0e00b3020400
+bc0b0e00b3020400bc0b0e00b3020400bc0b0e00b3020400bc0b0e00b3020400bc0b0e00
+b3020400bc0b0e00b3020400bc0b0e00b3020400bc0b0e02b3020400bc0b0e01b3020400
+bc0b0e00b3020400bc0b0e03b3020400bc0b0e00b3020400bc0b0e00b3020400bc0b0e00
+b3020400bc0b0e00b3020400bc0b0e01b3020400bc0b0e00b3020400bc0b0e01b3020400
+bc0b0e01b3020400bc0b0e00b3020400bc0b0e00b3020400bc0b0e00d8755c00f7ece700
+e0e4e700e6dcdc00d9dcde00d2d4d600cbcccd01c4c5c5016a6c6e002e2c2d0054545500
+4a4c4d0054545501585c5e004a4c4d00585c5e0263646500585c5e00636465006a6c6e00
+636465016a6c6e0163646500585c5e02a4a5a400f4f6f900ffffff00f4f6f900ecf3f500
+e8ecef01e0e4e700d9dcde00e0e4e7003a020400b3020402bc0b0e00b3020401bc0b0e00
+b3020401bc0b0e00b3020400bc0b0e00b3020402bc0b0e00b3020401bc0b0e00b3020401
+bc0b0e00b3020401bc0b0e00b3020401bc0b0e00b30204099c161400c6bcba00bbbcbd05
+99939300585c5e00545455024a4c4d0154545502585c5e0463646500585c5e0063646500
+585c5e02636465016a6c6e0063646500585c5e06545455004a4c4d00545455004a4c4d00
+4544450f4a4c4d00454445004a4c4d0354545500585c5e01636465007b7b7d00cbcccd00
+d2d4d601d9dcde007b7b7d000402040017020400b3020401a0020400b3020401a0020400
+b3020400a0020400b3020400a0020400b3020400a0020400b3020401a0020400b3020400
+a0020400b3020400a0020400b3020400a0020400b3020400a0020400b3020400a0020400
+b3020400a0020400b3020400a0020400b3020400a0020400b3020400a0020400b3020400
+a0020401b3020400a0020401b3020400a0020400b3020400a0020400b3020400a0020400
+b3020400a0020402b3020400a0020402b3020400a0020400b3020400a0020405b3020400
+a0020400b3020400a0020400b3020400a0020403b3020400a0020408b3020400a0020423
+94020400a002040294020400a002040194020400a002040294020400a002040094020400
+a002040194020400a002040194020400a002040094020400a002040194020400a0020401
+94020400a002040094020400a002040194020400a002040094020400a002040094020400
+a002040094020400a002040094020400a002040094020400a002040094020401a0020400
+94020401a002040094020401a002040094020400a002040094020400a002040094020402
+a002040094020400a0020401c47b7d00ffffff15f4f6f901e8ecef01e0e4e700d8b4ac00
+b2181a00a0020401b3020400a0020402b3020400a0020401b3020400a0020400b3020400
+a0020400b3020400a0020400b3020400a0020401b3020400a0020400b3020400a0020400
+b3020400a0020400b3020400a0020400b3020401a0020400b3020400a0020400b3020401
+a0020400b3020412a0020400b3020427bc0b0e00b3020405bc0b0e00b3020402bc0b0e00
+b3020401bc0b0e00b3020400bc0b0e0cbf181800bc0b0e06bf181800bc0b0e00bf181800
+bc0b0e00bf181800bc0b0e00bf181801bc0b0e00bf181800bc0b0e00bf18180ec4232400
+bf181801c4232400bf181803c4232402bf181800c4232402bf181800c4232403c42c3000
+c4232400c42c3000c4232401c42c3000c4232400c42c3000c4232400c42c300ac4363801
+c42c3000c4363800c42c3000c4363800c42c3000c4363800c42c3000c4363800c42c3000
+c436380acc3c3f00c4363800cc3c3f00c4363800cc3c3f00c4363802cc3c3f00c4363801
+cc3c3f0acc444400cc3c3f00cc444400cc3c3f00cc444400cc3c3f00cc444400cc3c3f00
+cc444400cc3c3f00cc444401cf4d4f00cc444400cf4d4f06e9d5d700e8ecef00e0e4e700
+d9dcde00d2d4d600d8cccb00cbcccd00c4c5c501b4b4b4002e2c2d00454445004a4c4d01
+54545500585c5e0054545500585c5e0054545500585c5e0363646500585c5e0063646500
+585c5e0063646500585c5e0063646501585c5e0063646500ecf3f500ffffff02f4f6f900
+ecf3f500e8ecef03c47b7d00c75c4d00cc54580ad45e4400cc626500cc545801cc626500
+cc545800d45e4400cc545800cc626500cc545800cc626505d9654700cc626502cc545800
+cc626501cc545800ba5d4500cc545800b7533a00b7a4a000bbbcbd00c4c5c500bbbcbd04
+7b7b7d0054545500585c5e0054545501585c5e004a4c4d0054545502585c5e0863646502
+6a6c6e0163646501585c5e06545455004a4c4d01454445013b3c3d00454445003b3c3d00
+454445023b3c3d00454445003b3c3d00454445013b3c3d00454445014a4c4d0354545501
+585c5e0063646501b4b4b400d9dcde00e0e4e700d9dcde02bbbcbd00b77c6a00c47b7d00
+c8745e00c47b7d00c8745e00c47b7d01c97c6700c47b7d32c8847200c47b7d00c8847200
+c47b7d00b9857800c47b7d00b9857800c47b7d00b9857800c47b7d00c8847200c47b7d00
+c88b7d00c47b7d00b9857800c88b7d00c47b7d00c88b7d00c47b7d00c88b7d00c47b7d00
+c88b7d00b78d8500c88b7d00b98a7c00c88b7d02b98a7c00c88b7d00b98a7c00c88b7d00
+b98a7c00c88b7d00b78d8500c88b7d00b78d8500c88b7d01b78d8500c88b7d00b78d8500
+c88b7d00b98a7c00c8938400b78d8500c8938400b78d8500c8938400b78d8500c8938400
+b78d8504b8938b03c8938400b78d8500b8938b01c8938400b78d8500b8938b05b78d8500
+b8938b00b78d8500b8938b00b78d8500b8938b00b99a9400b8938b02b99a9400b8938b03
+b99a940ac8a49d00b7a4a000c8aca502d8b4ac00d8bcb601d7c4bd00e5c4c200e6ccc900
+e9d5d701f8d4c900e9d5d708e6dcdc00e9d5d700f9dcd100e9d5d700f4f6f900ffffff15
+f4f6f902ecf3f501e8ecef00e6ccc901d7c4bd00d8cccb00e6ccc900d8cccb01e6ccc900
+d8cccb07e9d5d700d8cccb00d2d4d600e9d5d700d8cccb00d2d4d600e9d5d700d2d4d600
+e9d5d700d2d4d600e9d5d700d9dcde00e9d5d700e6dcdc00e9d5d700d9dcde00e9d5d700
+d9dcde00e6dcdc00d9dcde00e9d5d700d9dcde00e6dcdc02d9dcde00e0e4e700e6dcdc02
+d9dcde00e6dcdc00e0e4e703e6dcdc00e8ecef00e6dcdc00e0e4e701e6dcdc00e0e4e700
+e8ecef00e0e4e700e8ecef00e0e4e700e8ecef0aecf3f500e8ecef00ecf3f500e8ecef00
+ecf3f500e8ecef00ecf3f500e8ecef00f4f6f900e8ecef00f4f6f900e8ecef00f4f6f900
+e8ecef00f4f6f900e8ecef00f4f6f900e8ecef00ecf3f500e8ecef00ecf3f500f7ece700
+ecf3f501e8ecef00f4f6f900e8ecef01f4f6f900f7ece700f4f6f900e8ecef00f4f6f900
+f7ece700f4f6f900f7ece700f4f6f900f7ece700f4f6f900f7ece700f4f6f900f7ece700
+f4f6f902f7ece700f4f6f901f7ece700f4f6f909f7ece700f4f6f902f7ece700f4f6f901
+f7ece700f4f6f900f7ece700f4f6f904f7ece700f4f6f90dffffff01f4f6f906ffffff00
+f4f6f91dffffff00f4f6f902ffffff00f4f6f903ffffff00f4f6f901ffffff00f4f6f91a
+ffffff00f4f6f903ffffff00f4f6f900ffffff09f4f6f901e8ecef01e0e4e700d9dcde00
+d2d4d600cbcccd01c4c5c501777474002e2c2d004a4c4d0254545500585c5e0054545500
+585c5e0e9c9e9c00f4f6f900ffffff04f4f6f900ecf3f503e8ecef00f4f6f902ecf3f500
+f4f6f900ecf3f500f4f6f900ecf3f500f4f6f900ecf3f500f4f6f900e8ecef00f4f6f902
+f7ece700ecf3f501f4f6f900f7ece700ecf3f500f4f6f907f7ece700e8ecef01e0e4e700
+d9dcde01d2d4d600cbcccd00c4c5c501c6bcba00bbbcbd067b7b7d004a4c4d0054545506
+585c5e0a6a6c6e0163646500585c5e04545455004a4c4d00545455014a4c4d0054545500
+4a4c4d03454445004a4c4d04454445024a4c4d06585c5e004a4c4d00585c5e028c8b8c00
+e8ecef01e0e4e700e8ecef01e0e4e700e8ecef00e0e4e707e6dcdc00e0e4e700d9dcde00
+e0e4e700d9dcde00e0e4e700d9dcde00e0e4e700d9dcde00e0e4e702d9dcde00e0e4e701
+d9dcde00e0e4e700d9dcde00e0e4e701d9dcde00e0e4e700d9dcde00e0e4e700d9dcde00
+e0e4e700d9dcde00e0e4e700d9dcde00e0e4e704d9dcde00e0e4e700d9dcde00e0e4e700
+d9dcde00e0e4e700d9dcde00e0e4e700d9dcde15e0e4e700d9dcde0bd2d4d600d9dcde00
+d2d4d600d9dcde00d2d4d616d9dcde00d2d4d600d9dcde00d2d4d600d9dcde00d2d4d60a
+cbcccd00d2d4d602cbcccd00d2d4d600cbcccd00d2d4d600cbcccd00d2d4d600cbcccd00
+d2d4d600cbcccd01d2d4d600cbcccd00d2d4d600cbcccd03d2d4d600cbcccd03d2d4d600
+cbcccd00d2d4d600cbcccd00d2d4d601e0e4e701e8ecef01ecf3f501ffffff2bf4f6f902
+e8ecef00ecf3f500e8ecef11ecf3f500f7ece700e8ecef02f4f6f900e8ecef00ecf3f500
+e8ecef00ecf3f501e8ecef00ecf3f500f4f6f900e8ecef00ecf3f505f4f6f902ecf3f501
+f4f6f901ecf3f500f4f6f903ecf3f501f7ece700ecf3f500f4f6f900ecf3f500f4f6f904
+f7ece700f4f6f900ecf3f500f7ece700f4f6f90bffffff00f4f6f905ffffff00f4f6f902
+ffffff00f4f6f914ffffff00f4f6f900ffffff00f4f6f900ffffff00f4f6f900ffffff13
+f4f6f900ffffff01f4f6f900ffffff01f4f6f900ffffff71f4f6f901e8ecef00e0e4e700
+d9dcde00d2d4d600cbcccd01c4c5c501bbbcbd0035343400454445004a4c4d04585c5e00
+4a4c4d00585c5e004a4c4d0054545502585c5e004a4c4d0454545501585c5e00ecf3f500
+ffffff09f4f6f900ffffff01f4f6f901ffffff00f4f6f906ffffff00f4f6f901ffffff00
+f4f6f900ffffff01f4f6f900ffffff01f4f6f900ffffff06f4f6f901ecf3f500e8ecef00
+e0e4e700d9dcde00d2d4d601cbcccd00c4c5c502bbbcbd00c4c5c500bbbcbd01c4c5c500
+bbbcbd00b4b4b40077747400585c5e0054545500585c5e00545455014a4c4d0054545502
+585c5e004a4c4d0054545504585c5e0263646502585c5e0554545501585c5e0054545501
+4a4c4d04545455004a4c4d07545455004a4c4d00585c5e0054545502585c5e026a6c6e00
+e0e4e700ecf3f50ce8ecef25e0e4e700e8ecef00e0e4e700e8ecef00e0e4e702e8ecef00
+e0e4e702e8ecef00e0e4e703e8ecef01e0e4e700e8ecef00e0e4e701e8ecef00e0e4e700
+e8ecef00e0e4e700e8ecef01e0e4e701e8ecef00e0e4e701e8ecef00e0e4e700e8ecef00
+e0e4e707d9dcde00e0e4e701d9dcde00e0e4e702d9dcde00e0e4e701d9dcde00e0e4e701
+d9dcde00e0e4e701d9dcde00e0e4e700d9dcde00e0e4e700d9dcde00e0e4e702d9dcde01
+e0e4e700d9dcde03e0e4e700d9dcde00e0e4e700d9dcde0cd2d4d600d9dcde0cd2d4d600
+d9dcde03d2d4d600d9dcde03e0e4e702e8ecef00ecf3f500f4f6f902ffffff2cf4f6f915
+ecf3f500f4f6f90bffffff00f4f6f901ffffff00f4f6f900ffffff01f4f6f900ffffff03
+f4f6f900ffffff00f4f6f903ffffff00f4f6f900ffffff01f4f6f901ffffff00f4f6f902
+ffffff00f4f6f900ffffff01f4f6f900ffffffc0f4f6f900ecf3f500e8ecef00e0e4e700
+d9dcde00d2d4d600d8cccb00cbcccd00c4c5c5017b7b7d002e2c2d004a4c4d0554545500
+4a4c4d00585c5e014a4c4d0a8c8b8c00ffffff2bf4f6f900ecf3f500e8ecef00e0e4e700
+d9dcde00d2d4d601cbcccd00c4c5c501bbbcbd06b4b4b4007b7b7d00585c5e0054545504
+585c5e004a4c4d00545455004a4c4d00545455004a4c4d00585c5e004a4c4d00585c5e03
+63646500585c5e0163646500585c5e02545455004a4c4d0054545500585c5e0054545500
+585c5e005454550a4a4c4d00545455004a4c4d00585c5e0054545500585c5e0254545500
+585c5e0263646500d2d4d600ecf3f501f4f6f902ffffff02f4f6f906ffffff00f4f6f912
+ecf3f500f4f6f901ecf3f500f4f6f909ecf3f501f4f6f900ecf3f50fe8ecef00ecf3f501
+e8ecef00ecf3f501e8ecef00ecf3f501e8ecef00ecf3f500e8ecef00ecf3f500e8ecef00
+ecf3f501e8ecef00ecf3f500e8ecef00ecf3f501e8ecef01ecf3f500e8ecef08e0e4e700
+e8ecef08e0e4e700e8ecef05e0e4e700e8ecef02e0e4e700e8ecef03e0e4e700e8ecef04
+e0e4e700e8ecef00e0e4e704d9dcde00e0e4e704d9dcde00e0e4e702d9dcde00e0e4e70f
+e8ecef03ecf3f501f4f6f901ffffff11f4f6f900ffffff1ff4f6f900ffffff01f4f6f900
+ffffff00f4f6f900ffffff00f4f6f900ffffff01f4f6f900fffffff3f4f6f901e0e4e700
+e6dcdc00d2d4d601cbcccd01c4c5c500bbbcbd00353434004a4c4d00545455004a4c4d04
+454445004a4c4d00454445004a4c4d01454445004a4c4d003b3c3d0645444500e8ecef00
+ffffff2df4f6f900e8ecef01d9dcde00d2d4d601cbcccd00c4c5c503bbbcbd04b4b4b400
+7b7b7d004a4c4d00585c5e0054545500585c5e0054545500585c5e00545455014a4c4d02
+545455004a4c4d01585c5e08545455044a4c4d0054545502585c5e0154545500585c5e00
+54545501585c5e0254545502585c5e0763646500bbbcbd00ffffff29f4f6f900ffffff04
+f4f6f900ffffff00f4f6f900ffffff00f4f6f900ffffff00f4f6f900ffffff00f4f6f900
+ffffff00f4f6f904ecf3f500f4f6f905ecf3f500f4f6f907ecf3f500f4f6f901ecf3f500
+f4f6f901ecf3f500f4f6f901ecf3f500f4f6f903ecf3f500f4f6f900ecf3f50be8ecef00
+ecf3f515e8ecef04ecf3f500e8ecef12e0e4e700e8ecef01e0e4e700e8ecef05e0e4e700
+e8ecef02ecf3f502f4f6f903ffffff0ff4f6f900ffffffffffffff20ecf3f500e8ecef00
+e0e4e700d9dcde00d2d4d600cbcccd01c4c5c5017b7b7d002e2c2d004a4c4d0345444501
+3b3c3d004a4c4d00454445033b3c3d087b7b7d00f4f6f900ffffff2ef4f6f900e8ecef00
+e0e4e701d2d4d601cbcccd00c4c5c501bbbcbd01c4c5c500bbbcbd03b4b4b4007b7b7d00
+585c5e01545455034a4c4d00545455004a4c4d03585c5e0054545500585c5e0554545500
+4a4c4d00545455004a4c4d0254545503585c5e0054545500585c5e0054545500585c5e00
+54545500585c5e0054545500585c5e0254545500585c5e0363646500585c5e0263646500
+bbbcbd00f4f6f900ffffff5af4f6f900ffffff01f4f6f900ffffff02f4f6f900ffffff00
+f4f6f917ffffff00f4f6f909ecf3f500f4f6f901ecf3f51ff4f6f903ffffffffffffff32
+f4f6f900ecf3f500e8ecef00e0e4e700d2d4d601cbcccd01c4c5c500bbbcbd0035343400
+3b3c3d004a4c4d01454445004a4c4d00454445033b3c3d004a4c4d00454445004a4c4d00
+3b3c3d08d9dcde00ffffff30f4f6f900ecf3f500e0e4e700d9dcde01d2d4d600cbcccd01
+c4c5c502bbbcbd058c8b8c0054545500585c5e0054545500585c5e00545455014a4c4d00
+545455004a4c4d01545455004a4c4d0054545502585c5e05545455024a4c4d0054545500
+4a4c4d0054545501585c5e0054545501585c5e004a4c4d0054545502585c5e0663646500
+585c5e026a6c6e00d9dcde00ffffff8af4f6f900ffffff02f4f6f901ffffff00f4f6f917
+ffffff00f4f6f900ffffff13f4f6f900ffffff00f4f6f900ffffff00f4f6f900ffffffff
+ffffff1df4f6f900ecf3f500e0e4e700d9dcde00d2d4d600cbcccd01c4c5c5017b7b7d00
+242324004a4c4d003b3c3d06454445094a4c4d00454445016a6c6e00f4f6f900ffffff31
+f4f6f900ecf3f500e8ecef00d9dcde01d2d4d600cbcccd00c4c5c502bbbcbd00c4c5c500
+bbbcbd049c9e9c00585c5e0054545500585c5e0054545503585c5e0154545500585c5e00
+54545504585c5e02545455014a4c4d0054545502585c5e01545455024a4c4d0154545501
+585c5e0463646501585c5e0063646500585c5e0063646500585c5e008c8b8c00ecf3f500
+ffffffc1f4f6f900ffffffffffffff20ecf3f500e8ecef00e6dcdc00d2d4d601cbcccd00
+c4c5c5024a4c4d003b3c3d04454445003b3c3d04454445014a4c4d003b3c3d0045444506
+d9dcde00ffffff33f4f6f900e8ecef01e0e4e700d9dcde01d2d4d600cbcccd01c4c5c501
+bbbcbd00c4c5c500bbbcbd03a4a5a4006a6c6e0054545500585c5e0054545501585c5e05
+545455014a4c4d00585c5e0354545500585c5e0054545504585c5e0154545500585c5e00
+545455004a4c4d0154545500585c5e02636465067b7b7d00d2d4d600ffffffc1f4f6f900
+ffffff02f4f6f900ffffffffffffff1eecf3f500e8ecef00e0e4e700d9dcde00d2d4d600
+cbcccd02bbbcbd002e2c2d003b3c3d012e2c2d00353434013b3c3d01454445004a4c4d01
+454445004a4c4d00454445003b3c3d004a4c4d00454445004a4c4d046a6c6e00f4f6f900
+ffffff35ecf3f500e8ecef00e0e4e701d9dcde00d2d4d601cbcccd01c4c5c502bbbcbd00
+c4c5c500bbbcbd01b4b4b40088848400585c5e0163646500585c5e0e54545504585c5e00
+54545500585c5e0154545500585c5e05636465016a6c6e03bbbcbd00f4f6f901ffffffc0
+f4f6f900ffffff01f4f6f900ffffffffffffff20f4f6f900e8ecef00e0e4e700d9dcde00
+d2d4d602cbcccd00a4a5a4002e2c2d00353434012e2c2d00353434002e2c2d003b3c3d01
+454445013b3c3d00454445013b3c3d004a4c4d00454445014a4c4d01454445004a4c4d01
+cbcccd00ffffff37ecf3f501e0e4e701d9dcde01d2d4d601cbcccd02c4c5c503bbbcbd01
+a4a5a4007b7b7d0063646501585c5e0d54545501585c5e0054545501585c5e004a4c4d00
+585c5e0054545502585c5e02636465016a6c6e00636465006a6c6e007b7b7d00b4b4b400
+ffffffc8f4f6f900ffffff00f4f6f900ffffffffffffff1eecf3f500e8ecef00e0e4e701
+d9dcde00d2d4d60188848400353434002e2c2d01353434002e2c2d00353434013b3c3d00
+454445004a4c4d0b6a6c6e00f4f6f900ffffff38f4f6f900ecf3f501e0e4e701d9dcde02
+d2d4d601cbcccd02c4c5c500cbcccd00c4c5c501bbbcbd009c9e9c007b7b7d0063646500
+585c5e0463646500585c5e024a4c4d00585c5e004a4c4d0054545501585c5e004a4c4d00
+585c5e0054545501585c5e004a4c4d0054545500585c5e0054545500585c5e0263646502
+8c8b8c00cbcccd00f4f6f901ffffffc5f4f6f900ffffffffffffff23f4f6f901e8ecef00
+e0e4e703a4a5a4006a6c6e00585c5e003b3c3d002e2c2d00353434002e2c2d003b3c3d02
+454445004a4c4d00454445004a4c4d02545455034a4c4d01bbbcbd00ffffff3bf4f6f900
+ecf3f500e8ecef00ecf3f500e0e4e701d9dcde02d2d4d603cbcccd00d2d4d600cbcccd02
+b4b4b4008c8b8c006a6c6e00585c5e054a4c4d00585c5e0054545500585c5e014a4c4d00
+54545505585c5e004a4c4d00545455004a4c4d01585c5e0163646500a4a5a400e8ecef00
+f4f6f900ffffffc7f4f6f900ffffff01f4f6f900ffffff00f4f6f900ffffffffffffff20
+f4f6f901e8ecef03e0e4e703c4c5c500b4b4b4009c9e9c008c8b8c007b7b7d0063646500
+4a4c4d003b3c3d004a4c4d01545455044a4c4d0054545500585c5e00ffffff3ef4f6f900
+ecf3f501e8ecef01e0e4e702d9dcde03d2d4d601d9dcde00d2d4d600d9dcde00d2d4d601
+bbbcbd009c9e9c0077747400585c5e004a4c4d01585c5e014a4c4d00585c5e004a4c4d0b
+585c5e009c9e9c00d2d4d600f4f6f901ffffffcbf4f6f900ffffff02f4f6f900ffffffff
+ffffff21f4f6f901ecf3f504e8ecef00ecf3f500e8ecef00ecf3f500e8ecef00ecf3f502
+e0e4e700cbcccd00bbbcbd00abacad008c8b8c007b7b7d00585c5e0054545502b4b4b400
+ffffff3ff4f6f901ecf3f502e8ecef01e0e4e702d9dcde00e0e4e701d9dcde00e0e4e700
+d9dcde01e0e4e700d9dcde01e0e4e700d9dcde00c4c5c500a4a5a4008c8b8c007b7b7d00
+585c5e00545455014a4c4d06585c5e008c8b8c00b4b4b400e0e4e700ffffff00f4f6f900
+ffffffcdf4f6f900ffffff01f4f6f900ffffffffffffff27f4f6f902ecf3f504f4f6f903
+ffffff00f4f6f902ffffff00f4f6f900ffffff00ecf3f500e0e4e700f4f6f900ffffff42
+f4f6f900ecf3f500f4f6f900ecf3f502e8ecef02e0e4e700e8ecef00e0e4e700e8ecef01
+e0e4e700e8ecef03ecf3f504e0e4e700d2d4d601c4c5c500cbcccd00d2d4d600d9dcde00
+e0e4e700ecf3f500ffffff00f4f6f901ffffffcdf4f6f900ffffff03f4f6f900ffffff01
+f4f6f900ffffffffffffff81f4f6f901ecf3f500f4f6f900ecf3f50cf4f6f901ffffff00
+f4f6f900ffffff00f4f6f900ffffff00f4f6f900ffffff00f4f6f900ffffffd5f4f6f900
+ffffff00f4f6f900ffffff01f4f6f900ffffffffffffff86f4f6f900ffffff00f4f6f902
+ecf3f500f4f6f902ffffffe0f4f6f900ffffff04f4f6f900ffffff01f4f6f900ffffff00
+
+%%EndData
+end
+%%PageTrailer
+%%Trailer
+%%BoundingBox: 0 0 633 196
+%%EOF
diff --git a/doc/doxygen_logo.gif b/doc/doxygen_logo.gif
new file mode 100644
index 0000000..6b45597
--- /dev/null
+++ b/doc/doxygen_logo.gif
Binary files differ
diff --git a/doc/doxygen_logo_low.gif b/doc/doxygen_logo_low.gif
new file mode 100644
index 0000000..02e3c9a
--- /dev/null
+++ b/doc/doxygen_logo_low.gif
Binary files differ
diff --git a/doc/doxygen_manual.tex b/doc/doxygen_manual.tex
new file mode 100644
index 0000000..8d28a55
--- /dev/null
+++ b/doc/doxygen_manual.tex
@@ -0,0 +1,42 @@
+\documentclass[a4paper]{article}
+\usepackage{a4wide}
+\usepackage{makeidx}
+\usepackage{fancyheadings}
+\usepackage{epsf}
+\usepackage{doxygen}
+\usepackage{multicol}
+\makeindex
+\setcounter{tocdepth}{1}
+\setlength{\footrulewidth}{0.4pt}
+\begin{document}
+\begin{titlepage}
+\setlength{\epsfxsize}{\textwidth}
+\epsffile{doxygen_logo.eps}
+\begin{center}
+Manual for version $VERSION\\[2ex]
+Written by Dimitri van Heesch\\[2ex]
+\copyright 1997-1998
+\end{center}
+\end{titlepage}
+\clearemptydoublepage
+\tableofcontents
+\clearemptydoublepage
+\pagenumbering{arabic}
+\include{index}
+\part{User Manual}
+\input{install}
+\input{starting}
+\input{trouble}
+\part{Reference Manual}
+\input{features}
+\input{history}
+\input{doxygen_usage}
+\input{doxytag_usage}
+\input{doxysearch_usage}
+\input{installdox_usage}
+\input{autolink}
+\input{config}
+\input{commands}
+\input{htmlcmds}
+\printindex
+\end{document}
diff --git a/doc/doxygen_usage.doc b/doc/doxygen_usage.doc
new file mode 100644
index 0000000..e6fee75
--- /dev/null
+++ b/doc/doxygen_usage.doc
@@ -0,0 +1,47 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+/*! \page doxygen_usage Doxygen usage
+
+Doxygen is a command line based utility. Calling \c doxygen with the
+\c -h option at the command line will give you a brief description of the
+usage of the program.
+
+All options consist of a leading character <tt>-</tt>,
+followed by one character and optionally an argument.
+
+To generate a class browser you typically need to follow these steps:
+<ol>
+<li> You document your source code with
+ special documentation blocks.
+<li> You generate a configuration file (see section \ref config) by
+ calling doxygen with the \c -g option:
+\verbatim
+doxygen -g <config_file>
+\endverbatim
+<li> You edit the configuration file so it matches your project.
+ In the configuration file you can specify the input files and
+ a lot of optional information.
+<li> You let doxygen generate the documentation, based on the settings in the
+ configuration file:
+\verbatim
+doxygen <config_file>
+\endverbatim
+</ol>
+
+If you also want a search engine to be generated, you should look
+at section \ref doxysearch_usage.
+
+*/
diff --git a/doc/doxysearch_usage.doc b/doc/doxysearch_usage.doc
new file mode 100644
index 0000000..a4a3e96
--- /dev/null
+++ b/doc/doxysearch_usage.doc
@@ -0,0 +1,169 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+/*! \page doxysearch_usage Doxysearch usage
+
+Doxysearch is a small, fast and highly portable search engine that allows
+you to search for strings or words in the documentation generated by
+<a href="doxygen_usage.html">doxygen</a> or
+in the Qt documentation (see <a href="#searchqt">below</a>).
+Doxysearch must be run as a CGI binary. This implies the following:
+<ul>
+<li> There must be a HTTP daemon running on the system where you want to
+ install the documentation (the <em>target</em>)
+<li> You must have permission to install and execute a CGI binary on the
+ target.
+</ul>
+Ask you system administrator or provider if you are unsure if this is possible.
+
+In order to be able to search fast and efficient, doxysearch does not
+search the generated documentation directly. Instead, it uses an
+<em>index file</em>, that should be generated with
+<a href="doxytag_usage.html">doxytag</a>. The index file is extracted from
+the generated HTML files and contains all words and substrings of words
+present in the HTML files, in a compact form, together with their
+frequencies and links. Although I tried to store all information
+as compactly as possible, the size of the index is still quite large.
+Usually it is about the same size as the original HTML files.
+
+I have tried to make the search engine highly portable, because it
+must run on the target system. As a result doxysearch does not require the
+Qt library. All that is required to build doxysearch is a C++ compiler.
+If you are using \c g++ for example, you can build the search engine manually,
+by typing:
+\verbatim
+ g++ doxysearch.cpp -o doxysearch
+\endverbatim
+
+<a name="se">
+<h3>Generating the search engine</h3>
+</a>
+
+To include a search engine in the documentation generated by doxygen
+follow these steps:
+<ol>
+<li>Generate a configuration file with
+ <a href="doxygen_usage.html">doxygen</a> using the
+ <code>-g</code> option, if you haven't done this already.
+
+<li>Edit the search engine section (see section \ref config_search of
+ the configuration file).
+ Make sure the \c SEARCHENGINE tag is set to \c YES
+ and that all paths are correct.
+
+<li>Use <a href="doxygen_usage.html">doxygen</a> to generate the
+ documentation. Apart from the documentation, Doxygen will create the
+ following files:
+ <ul>
+ <li>A small CGI script. the name of the script is determined by the
+ \c CGI_NAME tag in the configuration file.
+ The script is a small wrapper that calls \c doxysearch with
+ the correct parameters. Using this script allows multiple
+ search engines for different projects to be present in one directory.
+ <li>\c search.cfg: this file is a small configuration file
+ for the search engine. It contains two lines of text. The first line
+ should be the absolute URL to the documentation. The second line should
+ be the absolute URL to the CGI script. This information is taken from
+ the configuration file.
+ <li>\c search.gif: this is the image that is used for the search button.
+ </ul>
+
+<li>Copy (or move) the CGI script to the directory where the CGI binaries
+ are located.
+ This is usually a special directory on your system or in your
+ home directory.
+ Consult the manual of your HTTP daemon or your system administrator to
+ find out, where this directory resides on your system.
+
+<li>Goto the directory where the generated HTML files are located and run
+ doxytag as follows:
+ <pre>doxytag -s search.idx</pre>
+ This will create a search index with the name <code>search.idx</code>.
+ Currently the index file <em>must</em> be called like this.
+
+<li>Run <a href="installdox_usage.html">installdox</a> to replace
+ any dummy links in the documentation with real links.
+
+ <b>Notice:</b> When using a search engine this step is <em>required</em>
+ even if no tag files are used. If tag files are used you must specify
+ the correct options.
+</ol>
+
+<a name="searchqt">
+<h3>Creating a search engine to search in the Qt documentation</h3>
+</a>
+
+Using <code>doxytag</code> and <code>doxysearch</code> it is possible to create a search engine for
+the Qt documentation, without needing the sources!
+This can be done by carefully following these steps:
+<ol>
+<li>Goto the html directory of the Qt-distribution:
+ <pre>cd $QTDIR/html</pre>
+<li>Generate the search index by typing:
+ <pre>doxytag -s search.idx *.html</pre>
+ This will parse all files and build a search index.
+ Apart from the file <code>search.idx</code> two other files
+ will be generated: <code>search.gif</code> and <code>search.cgi</code>
+
+ \par Notice:
+ Doxytag requires quite a large amount of memory to
+ generate the search index (about 30 Mb on my Linux box)!
+ The resulting index file requires about 3 Mb space on your disk.
+
+<li>Edit the shell script <code>search.cgi</code> with a text editor.
+
+ Fill in the absolute path to the <code>doxysearch</code> binary after
+ the <code>DOXYSEARCH=</code> tag.
+ On my system this becomes:
+ <pre>DOXYSEARCH=/usr/local/bin/doxysearch</pre>
+
+ Fill in the absolute path to the qt documentation after the
+ <code>DOXYPATH=</code> tag.
+ On my system this becomes:
+ <pre>DOXYPATH=/usr/local/qt/html</pre>
+<li>
+ CGI binaries are usually located in a special directory.
+ Consult the manual of your HTTP daemon or your system administrator to
+ find out, where this directory resides on your system.
+ Copy (or move) the <code>search.cgi</code> script to this directory.
+ If needed you may change the name of the script.
+ On my system, this becomes:
+ <pre>cp search.cgi /usr/local/lib/httpd/cgi-bin/</pre>
+
+<li>Create a text-file with the name <code>search.cfg</code>.
+ On the first line, you must put the <em>absolute</em> URL to the Qt
+ documentation.
+ Since, I only use the search engine on my own standalone system, I use
+ the <code>file:</code> protocol.
+ On the second line, you must put the <em>absolute</em> URL to the
+ cgi script.
+ On my system the resulting file looks like this:
+\verbatim
+file:///usr/local/qt/html
+http://blizzard/cgi-bin/search.cgi
+\endverbatim
+
+<li>Add a link to the search engine in the Qt documentation.
+ On my system, I have put a line
+\verbatim
+<li><a href="http://blizzard/cgi-bin/search.cgi">Search the documentation<a>
+\endverbatim
+ in the additional information section of the <code>index.html</code> file.
+<li>Start your favourite web browser and click on the link.
+ If everything is ok, you should get a page where you can enter
+ search terms.
+</ol>
+
+*/
diff --git a/doc/doxytag_usage.doc b/doc/doxytag_usage.doc
new file mode 100644
index 0000000..fb966fd
--- /dev/null
+++ b/doc/doxytag_usage.doc
@@ -0,0 +1,116 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+/*! \page doxytag_usage Doxytag usage
+
+Doxytag is a small command line based utility.
+It has two functions:
+<ul>
+<li>
+ Doxytag can generate <em>tag files</em>.
+ These tag files can be used with <a href="doxygen_usage.html">doxygen</a>
+ to generate references to external documentation
+ (i.e. documentation not contained in the input files that are used by
+ doxygen).
+ A tag file contains information about files, classes and members
+ documented in external documentation. Doxytag extracts this information
+ directly from the HTML files. This has the advantage that you do not need
+ to have the sources from which the documentation was extracted.
+ If you do have the sources you can also let \c doxygen generate the
+ tag file by putting the name of the tag file after \c GENERATE_TAGFILE in
+ the configuration file.
+<li>
+ Doxytag can generate a <em>search index</em> for the documentation
+ generated with doxygen or for the Qt documentation. See the documentation of
+ <a href="doxysearch_usage.html">doxysearch</a> for more information on how
+ to do this.
+ A search index contains information about all the words (and all substrings
+ thereof) that are contained in the documentation.
+ For each string the index contains the set of documentation blocks that
+ contain the string and the frequency of occurrence. This way
+ <code>doxysearch</code> can search for words very quickly
+ (most queries are processed within a few milliseconds on my system.)
+</ul>
+In both cases the input of doxytag consists of a set of HTML files.
+
+\par Important:
+ If you use tag files or use a search engine, the links that
+ are generated by doxygen will contain \e dummy links. You have to run
+ the \c installdox script to change these dummy links into real links.
+ See \ref installdox_usage for more information.
+ The use of dummy links may seem redundant, but it is really useful,
+ if you want to move the external documentation to another location.
+ Then the documentation does not need to be regenerated by \c doxygen,
+ only \c installdox has to be run.
+
+\par Notice:
+Because the HTML files are expected to have a certain
+structure, only HTML files generated with doxygen or with Qt's class
+browser generator can be used. Doxytag only <em>reads</em> the HTML files,
+they are not altered in any way.
+
+Doxytag expects a list of all HTML files that form the documentation
+or a directory that contains all HTML files. If neither is present doxytag
+will read all files with a <tt>.html</tt> extension from the current directory.
+If doxytag is used with the <code>-t</code> flag it generates a tag file.
+
+\par Example 1:
+ Suppose the file \c example.cpp from the \c examples directory that is listed
+ below is included in some package for which you do not have the sources.
+ Fortunately, the distributor of the packages included the HTML documentation
+ that was generated by doxygen in the package.
+ \verbinclude example.cpp
+ Now you can create a tag file from the HTML files in the package by
+ typing:
+\verbatim
+doxytag -t example.tag example/html
+\endverbatim
+ from the examples directory.
+ Finally you can use this tag file with your own piece of code, such
+ as done in the following example:
+ \verbinclude tag.cpp
+ Doxygen will now include links to the external package in your own
+ documentation. Because the tag file does not specify where the
+ documentation is located, you will have to specify that by running the
+ installdox script that doxygen generates
+ (See \ref installdox_usage for more information).
+
+ Notice that this is actually a feature because if you (or someone else)
+ moves the external documentation to a different
+ directory or URL you can simply run the script again and all links in
+ the HTML files will be updated.
+
+ \htmlonly
+ Click <a href="$(DOXYGEN_DOCDIR)/examples/tag/html/index.html">here</a>
+ for the corresponding HTML documentation that is generated by Doxygen using
+ only the tag file and second piece of code.
+ \endhtmlonly
+
+\par Example 2:
+ To generate a tag file of the Qt documentation you can do the following:
+\verbatim
+doxytag -t qt.tag $QTDIR/html
+\endverbatim
+
+A typical example to use doxytag to generate a search index is:
+\verbatim
+doxytag -s search.idx
+\endverbatim
+
+\par Notice:
+In the current version of doxygen, the search index must be
+called \c search.idx.
+
+*/
diff --git a/doc/features.doc b/doc/features.doc
new file mode 100644
index 0000000..2f34e18
--- /dev/null
+++ b/doc/features.doc
@@ -0,0 +1,79 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+/*! \page features.html
+
+\section features Features
+
+\addindex features
+<UL>
+<li>Requires very little overhead from the writer of the documentation.
+ Plain text will do, but for more fancy or structured output HTML tags
+ and/or some of doxygen's special commands can be used.
+<li>Outputs documentation in on-line format (HTML and man page) and off-line
+ format (LaTeX) simulatiously (one can be disabled if desired).
+ Both formats are optimized for ease of reading.
+<li>Allows documentation of files, classes, templates, variables, functions,
+ typedefs, enums and defines.
+<li>Includes a full C preprocessor to allow proper parsing of conditional
+ code fragments and to allow expansion of all or part of the define macros.
+<li>Automatically detects public, protected and private sections, as well as
+ the Qt specific signal and slots sections. Extraction of private class
+ members is optional.
+<li>Automatically generates of class diagrams in HTML (as clickable
+ image maps) and Latex (as encapsulated postscript).
+<li>JavaDoc (1.1) and Qt-Doc compatible.
+<li>References to base/super classes and inherited/overridden members are
+ generated automatically.
+<li>Includes a fast, rank based search engine to search for strings or words
+ in the class and member documentation.
+<li>Automatic generation of references to documented classes, files and
+ members. Documentation of global functions, globals variables,
+ typedefs, defines and enumerations is also supported.
+<li>Documentation may be placed either at the declaration or at the definition
+ of a member function or class. Most documentation systems (such as Javadoc) only
+ support the former, others (such as Qt) only the latter.
+<li>You can type normal HTML tags in your documentation. Doxygen will convert
+ them to Latex automatically.
+<li>Allows references to documentation generated for other projects
+ (or another part of the same project) in a location independent way.
+<li>Allows inclusion of source code examples that are automatically
+ cross-referenced with the documentation.
+<li>Inclusion of undocumented classes is also supported, allowing to quickly
+ learn the structure and interfaces of a (large) piece of code without
+ looking into the implementation details.
+<li>All options are read from an easy to edit and documented configuration
+ file.
+<li>Documentation and search engine can be transferred to another
+ location or machine without regenerating the documentation.
+<li>Can cope with large projects easily.
+</UL>
+
+Although doxygen can be used in any C or C++ project, it was specifically
+designed to be used for projects that make use of Troll Tech's
+<A HREF="http://www.troll.no/qt">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 very similar to the
+one that is generated by Troll Tech. Doxygen understands the C++ extensions
+used by Qt such as signals and slots.
+
+Doxygen can also automatically generate links to existing documentation
+that was generated with Doxygen or with Qt's non-public class browser
+generator. For a Qt based project this means that whenever you refer to
+members or classes belonging to the Qt toolkit, a link will be generated to
+the Qt documentation. This is done independent of where this documentation
+is located!
+
+*/
diff --git a/doc/history.doc b/doc/history.doc
new file mode 100644
index 0000000..3571bd6
--- /dev/null
+++ b/doc/history.doc
@@ -0,0 +1,140 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+
+/*! \page history Doxygen History
+
+<h3>TODO/Wish list</h3>
+<ul>
+<li>Add support for grouping members, and document then as a group.
+<li>Support for K&R-style function arguments.
+<li>More ouput formats: suggested are info format and RTF format.
+<li>Reintroduction of the multi-column class list (and file list) to quickly
+ select a class or file
+<li>Split long lists in an index to a set of smaller lists.
+<li>Add a nice graphical front-end for creating and modifying the
+ configuration file (it should be flexible enough to quickly add new options).
+<li>Improve the search index generation, so it uses less memory and
+ is easier to get running.
+<li>Generate code metrics (Anyone know a good book about code metrics?)
+<li>Add features that you think are missing... So if you know any that are
+ not yet listed here, please let me know.
+</ul>
+
+<h3>Features scheduled for version 0.5</h3>
+<ul>
+<li>Proper support for namespaces.
+<li>Include LaTeX style formulas in LaTeX and HTML output (in HTML as a gif).
+<li>Proper support for template classes, members, functions and specializations.
+<li>Multi-lingual support.
+<li>Generation of class diagrams (clickable image maps in HTML, eps images in
+ postscript).
+<li>Add generator for man pages format.
+</ul>
+
+<h3>Version 0.4</h3>
+
+<h4>New features:</h4>
+<ul>
+<li>LaTeX output generation.
+<li>Full JavaDoc support.
+<li>Build-in C-preprocessor for correct conditional parsing of source code
+ that is read by Doxygen.
+<li>Build-in HTML to LaTeX converter. This allows you to use HTML tags in
+ your documentation, while doxygen still generates proper LaTeX output.
+<li>Many new commands (there are now more than 60!) to document
+ more entities, to make the documentation look nicer, and to include
+ examples or pieces of examples.
+<li>Enum types, enum values, typedefs, #defines, and files can now be
+ documented.
+<li>Completely new documentation, that is now generated by Doxygen.
+<li>A lot of small examples are now included.
+</ul>
+<h4>Bug fixes:</h4>
+<ul>
+<li>A lot of parser bugs are fixed.
+<li>Improved support for documenting C code.
+</ul>
+
+<h3>Version 0.3</h3>
+<h4>New features:</h4>
+<ul>
+<li>A search engine <a href="doxysearch_usage.html">doxysearch</a>,
+ that allows you to search through the generated documentation.
+<li>A configuration file instead of command-line options. A default
+ configuration file can be generated
+ by <a href="doxygen_usage.html">doxygen</a>.
+<li>Added an option to generate output for undocumented classes.
+<li>Added an option to generate output for private members.
+<li>Every page now contains a condensed index page, allowing much faster
+ navigation through the documentation.
+<li>Global and member variables can now be documented.
+<li>A project name can now given, which will be included in the
+ documentation.
+</ul>
+
+<h4>Bug fixes:</h4>
+<ul>
+<li>Fixed bug when files with the same name but in different directories
+ are used as include files.
+<li>Template classes now work.
+<li>Inner classes now work.
+<li>Fixed a bug regarding unrelated functions and <code>\fn</code>.
+<li>Fixed parse bug with <code>/**/</code> comments
+<li>Fixed a bug regarding inline friend functions.
+<li>The list of all members now also contains the undocumented members.
+<li>Special documentation is now removed from code blocks.
+<li>Doxygen should compile on Sun Solaris (with <code>CC</code>), HP-UX (with
+ <code>CC</code>), Irix (with DCC) and Linux (with <code>GCC</code>)
+<li>Fixed several minor bugs.
+</ul>
+
+<h3>Version 0.2</h3>
+<h4>New features:</h4>
+<ul>
+<li>Blocks of code are now parsed. Function calls and variables are
+ replaced by links to their documentation if possible.
+<li>Special example documentation block added. This can be used to
+ provide cross references between the documentation and some example code.
+<li>Documentation blocks can now be placed inside the body of a class.
+<li>Documentation blocks with line range may now be created using
+ special <code>//!</code> C++ line comments.
+<li>Unrelated members can now be documented. A page containing a
+ list of these members is generated.
+<li>Added an <code>\include</code> command to insert blocks of source code
+ into the documentation.
+<li>Warnings are generated for members that are undocumented.
+<li>You can now specify your own HTML headers and footers for the
+ generated pages.
+<li>Option added to generated indices containing all external classes
+ instead of only the used ones.
+</ul>
+
+<h4>Bug fixes:</h4>
+<ul>
+<li>Fixed a link generation problem with mixed case filenames are used.
+<li>Made doxygen a little more portable.
+ (doxygen should now compile on Linux (with g++) and HP-UX (with CC))
+<li>Fixed a bug in err() function.
+<li>Fixed a problem with the type cast operator.
+<li>Removed some typo's from the docs.
+<li>Several small bug fixes and enhancements.
+</ul>
+
+<h3>Version 0.1</h3>
+Initial version.
+
+*/
diff --git a/doc/htmlcmds.doc b/doc/htmlcmds.doc
new file mode 100644
index 0000000..7a35200
--- /dev/null
+++ b/doc/htmlcmds.doc
@@ -0,0 +1,111 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+/*! \page htmlcmds HTML Commands
+
+Here is a list of all HTML commands that may be used inside the
+documentation. Notice that all attributes of a HTML tag are ignored
+(the HREF and NAME attributes for the A tag are the only exception).
+
+<ul>
+<li><tt>\<A HREF="..."\></tt> Starts a HTML hyper-link (HTML only).
+<li><tt>\<A NAME="..."\></tt> Starts an named anchor (HTML only).
+<li>\c </A> Ends a link or anchor (HTML only).
+<li>\c <B> Starts a piece of text displayed in a bold font.
+<li>\c </B> Ends a \c <B> section.
+<li>\c <BODY> Does not generate any output.
+<li>\c </BODY> Does not generate any output.
+<li>\c <BR> Forces a line break.
+<li>\c <CENTER> starts a section of centered text.
+<li>\c </CENTER> ends a section of centered text.
+<li>\c <CODE> Starts a piece of text displayed in a typewriter font.
+<li>\c </CODE> End a \c <CODE> section.
+<li>\c <DD> Starts an item description.
+<li>\c <DFN> Starts a piece of text displayed in a typewriter font.
+<li>\c </DFN> Ends a \c <DFN> section.
+<li>\c <DL> Starts a description list.
+<li>\c </DL> Ends a description list.
+<li>\c <DT> Starts a item title.
+<li>\c </DT> Does not generate any output.
+<li>\c <EM> Starts a piece of text displayed in an italic font.
+<li>\c </EM> Ends a \c <EM> section.
+<li>\c <FORM> Does not generate any output.
+<li>\c </FORM> Does not generate any output.
+<li>\c <HR> Writes a horizontal ruler.
+<li>\c <H1> Starts an unnumbered section.
+<li>\c </H1> Ends an unnumberd section.
+<li>\c <H2> Starts an unnumbered subsection.
+<li>\c </H2> Ends an unnumbered subsection.
+<li>\c <H?> Where ? is one of {3,4,5,6}, starts an unnumbered subsubsection.
+<li>\c </H?> Where ? is one of {3,4,5,6}, ends an unnumbered subsubsection.
+<li>\c <I> Starts a piece of text displayed in an italic font.
+<li>\c <INPUT> Does not generated any output.
+<li>\c </I> Ends a \c <I> section.
+<li>\c <IMG> This command is written with attributes to the HTML output only.
+<li>\c <LI> Starts a new list item.
+<li>\c </LI> Does not generate any output.
+<li>\c <META> Does not generate any output.
+<li>\c <MULTICOL> ignored by Doxygen.
+<li>\c </MUTLICOL> ignored by Doxygen.
+<li>\c <OL> Starts a numbered item list.
+<li>\c </OL> Ends a numbered item list.
+<li>\c <P> Starts a new paragraph.
+<li>\c </P> Does not generate any output.
+<li>\c <PRE> starts a code fragment,
+ equivalent to the command \\code (see section \ref cmdcode).
+<li>\c </PRE> ends a code fragment,
+ equivalent to the command \\endcode (see section \ref cmdendcode).
+<li>\c <SMALL> starts a section of text displayed in a smaller font.
+<li>\c </SMALL> ends a \c <SMALL> section.
+<li>\c <STRONG> starts a section of bold text.
+<li>\c </STRONG> ends a section of bold text.
+<li>\c <SUB> Starts a piece of text displayed in superscript.
+<li>\c </SUB> Ends a \c <SUB> section.
+<li>\c <SUP> Starts a piece of text displayed in subscript.
+<li>\c </SUP> Ends a \c </SUP> section.
+<li>\c <TABLE> starts a table, the available space of a page is always
+ divided equally amount the columns.
+<li>\c </TABLE> ends a table
+<li>\c <TD> Starts a new table element.
+<li>\c </TD> Does not generate any output.
+<li>\c <TR> Starts a new table row.
+<li>\c </TR> Does not generate any output.
+<li>\c <TT> Starts a piece of text displayed in a typewriter font.
+<li>\c </TT> Ends a \c <TT> section.
+<li>\c <UL> Starts an unnumbered item list.
+<li>\c </UL> Ends an unnumbered item list.
+<li>\c <VAR> Starts a piece of text displayed in an italic font.
+<li>\c </VAR> Ends a \c </VAR> section.
+</ul>
+
+The special HTML characters entities that are recognized by Doxygen:
+
+<ul>
+<li>\c &copy; the copyright symbol
+<li>\c &quot; a double quote
+<li>\c &?uml; where ? is one of {A,E,I,O,U,Y,a,e,i,o,u,y},
+ writes a character with a diaeresis accent (like &auml;).
+<li>\c &?acute; where ? is one of {A,E,I,O,U,Y,a,e,i,o,u,y},
+ writes a character with a acute accent (like &aacute;).
+<li>\c &?grave; where ? is one of {A,E,I,O,U,a,e,i,o,u,y},
+ writes a character with a grave accent (like &agrave;).
+<li>\c &?circ; where ? is one of {A,E,I,O,U,a,e,i,o,u,y},
+ writes a character with a circumflex accent (like &acirc;).
+<li>\c &?tilde; where ? is one of {A,N,O,a,n,o},
+ writes a character with a tilde accent (like &atilde;).
+</ul>
+
+*/
+
diff --git a/doc/index.doc b/doc/index.doc
new file mode 100644
index 0000000..add62b4
--- /dev/null
+++ b/doc/index.doc
@@ -0,0 +1,163 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+/*! \page index
+<center>
+\htmlonly
+<img align=center lowsrc="doxygen_logo_low.gif" src="doxygen_logo.gif"
+ width=634 height=197 alt="doxygen"><br>
+Version: $(VERSION)
+\endhtmlonly
+</center>
+
+<h2>Doxygen license</h2>
+\addindex license
+\addindex GPL
+
+Copyright &copy; 1997-1999 by
+<a href="mailto:dimitri@stack.nl">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
+granted. No representations are made about the suitability of this software
+for any purpose. It is provided "as is" without express or implied warranty.
+See the GNU General Public License for more details.
+<p>
+All output generated by Doxygen is not covered by this license.
+
+<h2>Introduction</h2>
+Doxygen is a documentation system for C and C++. It can generate an on-line
+class browser (in HTML) and/or an off-line reference manual
+(in \f$\mbox{\LaTeX}\f$) from a set
+of documented source files. The documentation is extracted directly from the
+sources. Doxygen is developed on a <a href="http://www.linux.org">Linux</a>
+platform, but it runs on most other UNIX flavors as well.
+An executable for Windows 95/NT is also available.
+
+Doxygen can also be configured to extract the code-structure from undocumented
+source files. This can be very useful to quickly find your way in large
+source distributions.
+
+You can even `abuse' doxygen for creating normal documentation (as I did
+for this manual).
+
+This manual is divided into two parts, each of which is divided into several
+sections.
+
+The first part forms a user manual:
+<ul>
+<li>Section \ref install discusses how to download, compile and install
+ doxygen for your platform.
+<li>Section \ref starting tells you how to generate your first piece of
+ documentation quickly.
+<li>Section \ref trouble tells you what to do when you have problems.
+</ul>
+
+The second part forms a reference manual:
+
+<ul>
+<li>Section \ref features presents an overview of what Doxygen can do.
+<li>Section \ref history shows what has changed during the development
+ of Doxygen and what still has to be done.
+<li>Section \ref doxygen_usage shows how to use the \c doxygen program.
+<li>Section \ref doxytag_usage shows how to use the \c doxytag program.
+<li>Section \ref doxysearch_usage shows how to use the \c doxysearch program.
+<li>Section \ref installdox_usage shows how to use the \c installdox
+ script that is generated by Doxygen if you use tag files.
+<li>Section \ref autolink shows how to put links to files, classes,
+ and members in the documentation.
+<li>Section \ref config shows how to fine-tune doxygen, so it
+ generates the documentation you want.
+<li>Section \ref commands shows an overview of the special commands that can be
+ used within the documentation.
+<li>Section \ref htmlcmds shows an overview of the HTML commands that
+ can be used within the documentation.
+</ul>
+
+<h2>Acknowledgements</h2>
+\addindex acknowledgements
+Thanks go to:
+<ul>
+\addindex Doc++
+<li>Malte Z&ouml;ckler and Roland Wunderling, authors of Doc++.
+ The first version of Doxygen was based on an old version of Doc++.
+ Although I have rewritten practically all code since then, Doc++ has still
+ given me a good start in writing Doxygen.
+<li>All people at Troll Tech, for creating a beautiful GUI Toolkit.
+ (which is even useful for GUI-less applications like doxygen :-)
+<li>My brother <a href="http://www.stack.nl/~fidget/index.html">Frank</a>
+ for rendering the logos.
+<li>
+Arnt Gulbrandsen,
+Adam P. Jenkins,
+Frank van de Pol,
+Ulrich Quill,
+Karl Robillard,
+Frugal the Curious,
+Michael Figley,
+Eric Bos,
+Barry Roberts,
+Mark Tigges,
+Jan Ekholm,
+Andre Johansen,
+Martin Franken,
+Martin Hofmann,
+Ulrich Ring,
+Andy Guy,
+Ryan Mclean,
+Joseph Reklow,
+Morten Eriksen,
+Arthur Pope,
+Andreas Felber,
+Matthias Schwartz,
+Bj&ouml;rn Bon,
+Volker B&ouml;rchers,
+Baruch Even,
+Kor de Jong,
+Thomas Eschenbacher,
+Bert Scholten,
+Germar Morgenthaler,
+Daniel Bellen,
+Terry Brown,
+Anke Selig,
+David Aspinwall,
+Hellmar Becker,
+Harald Krummeck,
+Christoph Koegl,
+Martin Reinecke,
+Joseph Turian,
+Craig P Earls,
+Greg Sjaardema,
+Vlado Sironja,
+Jens Schmidt,
+Lutz Sammer,
+Robert Dale,
+Ionutz Borcoman,
+Markus Noga,
+Darren Kelly,
+Joerg Ott,
+Kostya Serebrainy,
+Marco Molteni,
+Johannes Zellner,
+Ole Gerden,
+Olaf Meeuwissen,
+Feiyi Wang,
+Robert J. Clark,
+Matthias Baas and
+Walter Mueller
+ for suggestions, patches and bug reports.
+</ul>
+*/
+
diff --git a/doc/install.doc b/doc/install.doc
new file mode 100644
index 0000000..2c5f0ac
--- /dev/null
+++ b/doc/install.doc
@@ -0,0 +1,99 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+/*! \page install Installation
+
+\addindex installation
+First go to the
+<a href="http://www.stack.nl/~dimitri/doxygen/download.html">download</a> page
+\latexonly({\tt http://www.stack.nl/$\sim$dimitri/doxygen/download.html})\endlatexonly
+to get the latest distribution and unpack it.
+
+If you downloaded the source distribution, you need at least the
+following to build the executable:
+<UL>
+<LI>Troll Tech's GUI toolkit <A HREF="http://www.troll.no/dl">Qt</A>
+ \latexonly(see {\tt http://www.troll.no/dl})\endlatexonly.
+ \addindex Qt
+<LI>The <a href="ftp://prep.ai.mit.edu/pub/gnu">GNU</a> tools
+ flex, bison and make
+ \latexonly(see {\tt ftp://prep.ai.mit.edu/pub/gnu})\endlatexonly.
+ \addindex flex
+ \addindex bison
+ \addindex make
+<LI>In order to generate a Makefile for your platform, you need
+ <a href="http://www.perl.com>perl</a>
+ \latexonly(see {\tt http://www.perl.com})\endlatexonly.
+ \addindex perl
+</UL>
+
+\addindex HTTP
+\addindex CGI
+To use the search engine \c doxysearch, you will also need
+a HTTP daemon running on the target system and permission to execute a
+CGI binary.
+
+Once you have Qt installed correctly, you can simply enter:
+\verbatim
+make
+\endverbatim
+to get a list of all supported platforms/compilers.
+Typing <tt>make</tt> followed by your platform will compile doxygen.
+For Linux you can enter the following:
+\verbatim
+make linux-g++
+\endverbatim
+
+Doxygen should compile without errors or warnings.
+If it does not, please send the compilation errors or warnings along
+with a description of your platform to
+<a href="mailto:dimitri@stack.nl>dimitri@stack.nl</a>.
+
+After compilation, the binaries will be located in the \c bin
+directory of the distribution.
+You may want to copy these files to a location in your path
+(\c /usr/local/bin for instance) or add the \c bin
+directory of the distribution to your search path.
+
+The following binaries should now be available:
+<UL>
+<LI>\c doxygen: for generating the class browser.
+<LI>\c doxytag: for creating a tag file containing references
+ to external documentation.
+<LI>\c doxysearch: the search engine. This binary should not be
+ executed directly. It must be called from an CGI script that will be
+ generated by doxygen.
+</UL>
+
+Doxygen was developed and tested under Linux using the following tools:
+<ul>
+<li>GCC version 2.8.1
+<li>GNU flex version 2.5.4
+<li>GNU bison version 1.25
+<li>GNU make version 3.77
+<li>Perl version 5.001 (patch level 1m)
+<li>VIM version 5.3
+<li>Netscape 4.04 & 4.5
+<li>Troll Tech's tmake version 1.2 (included in the distribution)
+<li>teTeX version 0.4
+</ul>
+
+\htmlonly
+Go to the <a href="starting.html">next</a> section or return to the
+ <a href="index.html">index</a>.
+\endhtmlonly
+
+*/
+
diff --git a/doc/installdox_usage.doc b/doc/installdox_usage.doc
new file mode 100644
index 0000000..d22e4a7
--- /dev/null
+++ b/doc/installdox_usage.doc
@@ -0,0 +1,61 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+/*! \page installdox_usage Installdox usage
+
+Installdox is a perl script that is generated by doxygen whenever
+tag files are used (See \c TAGFILES
+in section \ref config_extref)
+or the search engine is enabled (See \c SEARCHENGINE
+in section \ref config_search). The script is
+located in the same directory where the HTML files are located.
+
+Its purpose is to set the location of the external documentation
+for each tag file and to set the correct links to the search engine
+at install time.
+
+Calling \c installdox with option <b>-h</b> at the command line
+will give you a brief description of the usage of the program.
+
+The following options are available:
+<dl>
+<dt><b>-l <tt>\<tagfile\>\@\<location\></tt></b><dd>
+ Each tag file contains information about the files, classes and members
+ documented in a set of HTML files. A user can install these
+ HTML files anywhere on his/her hard disk or web site.
+ Therefore installdox \e requires the location of the
+ documentation for each tag file <tt>\<tagfile\></tt>
+ that is used by doxygen. The location <tt>\<location\></tt> can be
+ an absolute path or a URL.
+
+ \par Notice:
+ Each <tagfile> must be unique and should only be the name of the
+ file, not including the path.
+
+<dt><b>-q</b><dd>
+ When this option is specified, installdox will generate no output other
+ than fatal errors.
+</dl>
+Optionally a list of HTML files may be given.
+These files are scanned and modified if needed.
+If this list is omitted all files in the current directory
+that end with \c .html are used.
+
+The \c installdox script is unique for each generated class browser
+in the sense that it `knows' what tag files are used. It will generate an error if
+the <b>-l</b> option is missing for a tag file or if an invalid tag file
+is given.
+
+*/
diff --git a/doc/starting.doc b/doc/starting.doc
new file mode 100644
index 0000000..1d3cbcd
--- /dev/null
+++ b/doc/starting.doc
@@ -0,0 +1,411 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+/*! \page starting Getting started
+
+The executable \c doxygen is the main program that parses the sources and
+generates the documentation. See section \ref doxygen_usage for more
+detailed usage information.
+
+The executable \c doxytag is only needed if you want to generate references
+to external documentation (i.e. documentation that was generated by Doxygen)
+for which you do not have the sources or to create a search index for
+the search engine. See section \ref doxytag_usage for more detailed usage
+information.
+
+The executable \c doxysearch is only needed if you want to use the search
+engine. See section \ref doxysearch_usage for more detailed usage information.
+
+\subsection step1 Step 1: Creating a configuration file
+
+Doxygen uses a configuration file to determine all of its settings.
+Each project should get its own configuration file. A project can consist
+of a single source file, but can also be an entire source tree that is
+recursively scanned.
+
+To simplify the creation of a configuration file, Doxygen can create a
+template configuration file for you. To do this call \c doxygen with the \c -g
+option:
+
+\verbatim
+doxygen -g <config-file>
+\endverbatim
+where \<config-file\> is the name of the configuration file. If you omit
+the file name, a file named \c Doxyfile will be created. If a file with the
+name \<config-file\> already exists, Doxygen will rename it to
+\<config-file\>.bak before generating the configuration template.
+
+The configuration file has a format that is similar to that of a (simple)
+Makefile. It contains of a number of assignments (tags) of the form:
+
+<tt>TAGNAME = VALUE</tt> or <br>
+<tt>TAGNAME = VALUE1 VALUE2 ... </tt><br>
+
+You can probably leave the values of most tags to their default value.
+
+The \c INPUT tag is the only tag for which you are required to provide
+a value. See section \ref config for more details about the configuration file.
+For a small project consisting of a few C and/or C++ source and header files,
+you can add the names of the files after the \c INPUT tag.
+If you have a larger project consisting of a source directory or tree
+this may become tiresome. In this case you should put the root directory or
+directories after the \c INPUT tag, and add one or more file
+patterns to the \c FILE_PATTERN tag. Only files that match one of the
+patterns will be parsed (if the patterns are omitted all files will be parsed).
+For recursive parsing of a source tree you must set
+the \c RECURSIVE tag to \c YES. To further finetune the list of files
+that is parsed the \c EXCLUDE and \c EXCLUDE_PATTERNS tags can be used.
+
+If you start using Doxygen for an existing project (thus without any
+documentation that Doxygen is aware of), you can still get an idea of
+what the documented result would be. To do so, you must set the \c EXTRACT_ALL
+tag in the configuration file to \c YES. Then, Doxygen will pretend
+everything in your sources is documented. Please note that warnings of
+undocumented members will not be generated as long as \c EXTRACT_ALL is set
+to \c YES.
+
+\subsection step2 Step 2: Running doxygen
+
+To generate the documentation you can now enter:
+\verbatim
+doxygen <config-file>
+\endverbatim
+
+Doxygen will create a \c html, \c latex and/or \c man directory inside
+the output directory.
+As the names suggest the \c html directory contains the
+generated documentation in HTML format and the \c latex directory contains the
+generated documentation in \f$\mbox{\LaTeX}\f$ format. Man pages are put
+in a man3 directory inside the \c man directory.
+
+The default output directory is the directory in which \c doxygen
+is started. The directory to which the output is written can be changed
+using the \c OUTPUT_DIRECTORY , \c HTML_OUTPUT, \c LATEX_OUTPUT, and
+\c MAN_OUTPUT tags of the configuration file. If the output directory does not
+exist, \c doxygen will try to create it for you.
+
+\addindex browser
+The generated HTML documentation can be viewed by pointing a HTML browser
+to the \c index.html file in the \c html directory. For the best results
+a browser that supports cascading style sheets (CSS) should be used
+(I'm currently using Netscape 4.0 to test the generated output).
+\addindex LaTeX
+
+The generated \f$\mbox{\LaTeX}\f$ documentation must first be compiled by
+a \f$\mbox{\LaTeX}\f$ compiler. (I use teTeX distribution version 0.4
+that contains \f$\mbox{\TeX}\f$ version 3.14159). To simplify the process
+of compiling the generated
+documentation, \c doxygen writes a \c Makefile into the \c latex directory.
+By typing \c make in the \c latex directory the dvi file \c refman.dvi
+will be generated. This file can then be viewed using \c xdvi or
+converted into a postscript file \c refman.ps by typing <code>make ps</code>
+(this requires \c dvips ). The Postscript file can be send to a postscript
+printer. If you do not have a postscript printer, you can try to use
+ghostscript to convert postscript into something your printer understands.
+
+The generated man pages can be viewed using the \c man program. You do need
+to make sure the man directory is in the man path (see the MANPATH
+environment variable). Notice that there are some limitations to the
+capabilities of the man page format, so some information
+(like class diagrams, cross references and formulas) will be lost.
+
+\subsection step3 Step 3: Documenting the sources
+
+Although documenting the source is presented as step 3, in a new project
+this should ofcourse be step 1. Here I assume
+you already have some code and you want Doxygen to generate a nice document
+describing the API and maybe the internals as well.
+
+If the \c EXTRACT_ALL option is set to \c NO in the configuration file
+(the default), then doxygen will only generate documentation for
+\e documented members, files, classes and namespaces. So how do you document
+these? For members, classes and namespaces there are basicly two options:
+<ol>
+<li>Place a \e special documentation block in front of the declaration or
+ definition of the member, class or namespace. For file, class and namespace
+ members it is also allowed to place the documention directly after the
+ member. See section \ref specialblock to learn more about special
+ documentation blocks.
+<li>Place a special documentation block somewhere else (another file or
+ another location) \e and put a <em>structural command</em> in the
+ documentation block. A structural command links a documentation block
+ to a certain object that can be documented (e.g. a member, class,
+ namespace or file). See section \ref structuralcommands to learn more
+ about structural commands.
+</ol>
+Files can only be documented using the second option.
+The text inside a special documentation block is parsed
+before it is written to the HTML and/or \f$\mbox{\LaTeX}\f$ output files.
+
+\addindex parsing
+During parsing the following steps take place:
+<ul>
+<li> The special commands inside the documentation are executed. See
+ section \ref commands for an overview of all commands.
+<li> If a line starts with some whitespace followed by one or more asterixes
+ (<tt>*</tt>) then the whitespace and asterixes are removed.
+<li> All resulting blank lines are treated as a paragraph separators.
+ This saves you from placing new-paragraph commands yourself,
+ in order to make the generated documentation readable.
+<li> Links are created for words corresponding to documented classes.
+<li> Links to members are created when certain patterns are found in the
+ text. See section \ref autolink
+ for more information on how the automatic link generation works.
+<li> HTML tags that are in the documentation are interpreted and converted
+ to \f$\mbox{\LaTeX}\f$ equivalents for the \f$\mbox{\LaTeX}\f$ output.
+ See section \ref htmlcmds for an overview of all supported HTML tags.
+</ul>
+
+\subsection specialblock Special documentation blocks
+
+The following types of special documentation blocks are supported by Doxygen:
+<ul>
+<li>The Qt style, where special documentation blocks look like:
+\verbatim
+/*!
+ ... text ...
+*/
+\endverbatim and the one line version:
+\verbatim
+//! ... one line of text ...
+\endverbatim
+<li>The JavaDoc style, where special documentation blocks look like:
+\verbatim
+/**
+ * ... text ...
+ */
+\endverbatim and the one line version:
+\verbatim
+/// ... one line of text ...
+\endverbatim
+</ul>
+
+Here is an example of a documented piece of C++ code using the Qt style:
+\verbinclude qtstyle.cpp
+ \htmlonly
+ Click <a href="$(DOXYGEN_DOCDIR)/examples/qtstyle/html/class_test.html">here</a>
+ for the corresponding HTML documentation that is generated by Doxygen.
+ \endhtmlonly
+
+The one-line comments should contain a brief description,
+whereas the multi-line comment blocks contain a more detailed description.
+The brief descriptions are included in the member overview of a class,
+namespace or file and are printed using a small italic font
+(this description can be omitted by setting \c BRIEF_MEMBER_DESC to \c NO in
+the config file). By default the brief descriptions are also the first
+sentence of the detailed description
+(this can be changed by setting the \c REPEAT_BRIEF tag to \c NO).
+Both the brief and the detailed descriptions are optional
+for the Qt style.
+
+Here is the same piece of code, this time documented using the JavaDoc
+style:
+\verbinclude jdstyle.cpp
+ \htmlonly
+ Click <a href="$(DOXYGEN_DOCDIR)/examples/jdstyle/html/class_test.html">here</a>
+ for the corresponding HTML documentation that is generated by Doxygen.
+ \endhtmlonly
+
+Notice that the first sentence of the documentation (until the <tt>.</tt>)
+is treated as a brief description, whereas the documentation block as a whole
+forms the detailed description. The brief description is required for the
+JavaDoc style.
+
+Unlike most other documentation systems, Doxygen also allows you to put
+the documentation of members (including global functions) in front of
+the \e definition. This way the documentation can be placed in the source
+file instead of the header file. This keeps the header file compact, and allows the
+implementer of the members more direct access to the documentation.
+As a compromise the brief description could be placed before the
+declaration and the detailed description before the member definition
+(assuming you use the Qt style comments).
+
+\subsection structuralcommands Structural commands
+
+So far we have assumed that the documentation blocks are always located in
+front of the declaration or definition of a file, class or namespace or in
+front of one of its members.
+Although this is often comfortable, it may sometimes be better to put the
+documentation somewhere else. For some types of documentation blocks (like file
+documentation) this is even required. Doxygen allows you to put your
+documentation blocks practically anywhere (the exception is inside the body
+of a function or inside a normal C style comment block), as long as you put a
+structural command inside the documentation block.
+
+Structural commands (like all other commands) start with a backslash
+(<tt>\\</tt>) followed by a command name and one or more parameters.
+For instance, if you want to document the class \c Test in the example
+above, you could have also put the following documentation block somewhere
+in the input that is read by Doxygen:
+\verbatim
+/*! \class Test
+ \brief A test class.
+
+ A more detailed class description.
+*/
+\endverbatim
+
+Here the special command \c \class is used to indicated that the
+comment block contains documentation for the class \c Test.
+Other structural commands are:
+<ul>
+<li>\c \struct to document a C-struct.
+<li>\c \union to document a union.
+<li>\c \enum to document an enumeration type.
+<li>\c \fn to document a function.
+<li>\c \var to document a variable or typedef or enum value.
+<li>\c \def to document a \#define.
+<li>\c \file to document a file.
+<li>\c \namespace to document a namespace.
+</ul>
+See section \ref commands for detailed information about these and other
+commands. Notice that the documentation block belonging to a file
+should always contain a structural command.
+
+To document a member of a C++ class, you must also document the class
+itself. The same holds for namespaces. To document a C function, typedef,
+enum or preprocessor definition you must first document the file that
+contains it (usually this will be a header file, because that file contains
+the information that is exported to other source files).
+
+Here is an example of a C header named \c structcmd.h that is documented
+using structural commands:
+\verbinclude structcmd.h
+ \htmlonly
+ Click <a href="$(DOXYGEN_DOCDIR)/examples/structcmd/html/structcmd.h.html">here</a>
+ for the corresponding HTML documentation that is generated by Doxygen.
+ \endhtmlonly
+
+\par Notice:
+ Because each comment block in the example above contains a structural command, all
+ the comment blocks could be moved to another location or input file
+ (the source file for instance), without affecting the generated
+ documentation. The disadvantage of this approach is that prototypes are
+ duplicated, so all changes have to be made twice!
+
+\subsection memberdoc Documenting compound members.
+
+If you want to document the members of a file, struct, union, class, or enum
+and you want to put the documentation for these members inside the compound,
+it is sometimes desired to place the documentation block after the member
+instead of before. For this purpose Doxygen has the following
+additional comment blocks:
+\verbatim
+/*!< ... */
+\endverbatim
+This block can be used to put a qt style documentation blocks after a member.
+The one line version look as follows:
+\verbatim
+//!< ...
+\endverbatim
+There are also JavaDoc versions:
+\verbatim
+/**< ... */
+\endverbatim
+and
+\verbatim
+///< ...
+\endverbatim
+Notice that these blocks have the same structure and meaning as the
+special comment blocks above only the \< indicates that the member is
+located in front of the block instead of after the block.
+
+Here is an example of a the use of these comment blocks:
+\verbinclude afterdoc.h
+ \htmlonly
+ Click <a href="$(DOXYGEN_DOCDIR)/examples/afterdoc/html/class_test.html">here</a>
+ for the corresponding HTML documentation that is generated by Doxygen.
+ \endhtmlonly
+
+\warning These blocks can only be used to document \e members.
+ They cannot be used to document file classes, unions, structs and
+ enums. Furthermore, the structural commands mentioned in the
+ previous section are ignored inside these comment blocks.
+
+\subsection formulas Including formulas in the documentation
+
+Doxygen allows you to put \f$\mbox{\LaTeX}\f$ formulas in the
+output (this works only for the HTML and \f$\mbox{\LaTeX}\f$ formats,
+not for the man page output). To be able to include formulas (as images)
+in the HTML documentation, you will also need to have the following tools
+installed
+<ul>
+<li>\c latex: the \f$\mbox{\LaTeX}\f$ compiler, needed to parse the formulas.
+ To test I have used the teTeX 0.4 distribution.
+<li>\c dvips: a tool to convert dvi files to postscript files
+ I have used version 5.58f from Radical Eye software for testing.
+<li>\c gs: the ghostscript interpreter for converting postscript files
+ to bitmaps. I have used Aladdin Ghostscript 5.01 for testing.
+</ul>
+
+There are two ways to include formulas in the documentation.
+<ol>
+<li>Using in-text formulas that appear in the running text.
+ These formulas should be put between a pair of \\f\$
+ commands, so
+\verbatim
+ The distance between \f$(x_1,y_1)\f$ and \f$(x_2,y_2)\f$ is
+ \f$\sqrt{(x_2-x_1)^2+(y_2-y_1)^2}\f$.
+\endverbatim results in:
+
+ The distance between \f$(x_1,y_1)\f$ and \f$(x_2,y_2)\f$ is
+ \f$\sqrt{(x_2-x_1)^2+(y_2-y_1)^2}\f$.
+<br>
+<li>Unnumbered displayed formulas that are centered on a separate line.
+ These formulas should be put between \\f\[ and \\f\] commands.
+ An example:
+\verbatim
+ \f[
+ |I_2|=\left| \int_{0}^T \psi(t)
+ \left\{
+ u(a,t)-
+ \int_{\gamma(t)}^a
+ \frac{d\theta}{k(\theta,t)}
+ \int_{a}^\theta c(\xi)u_t(\xi,t)\,d\xi
+ \right\} dt
+ \right|
+ \f]
+\endverbatim
+ results in:
+ \f[
+ |I_2|=\left| \int_{0}^T \psi(t)
+ \left\{
+ u(a,t)-
+ \int_{\gamma(t)}^a
+ \frac{d\theta}{k(\theta,t)}
+ \int_{a}^\theta c(\xi)u_t(\xi,t)\,d\xi
+ \right\} dt
+ \right|
+ \f]
+</ol>
+Formulas should be valid commands in \f$\mbox{\LaTeX}\f$'s math-mode.
+
+\warning Currently, Doxygen is not very fault tolerant in recovering
+from typos in formulas. It may have to be necessary to remove the
+file formula.repository that is written in the html directory to
+a rid of an incorrect formula
+
+\subsection moreinfo More information
+
+\addindex QdbtTabular
+For a more elaborate example see <a href="http://www.stack.nl/~dimitri/qdbttabular/html/index.html">
+the documentation of QdbtTabular</a> \latexonly
+({\tt http://www.stack.nl/$\sim$dimitri/qdbttabular/html})\endlatexonly.
+\htmlonly
+I hope that was clear. If not, please let me know, so I can improve this document. If you have problems
+take a look at the <a href="trouble.html">troubleshooting</a> section.
+\endhtmlonly
+
+*/
diff --git a/doc/trouble.doc b/doc/trouble.doc
new file mode 100644
index 0000000..5103bda
--- /dev/null
+++ b/doc/trouble.doc
@@ -0,0 +1,67 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+/*! \page trouble Troubleshooting
+
+<h2>Known problems:</h2>
+<ul>
+<li>Doxygen is <em>not</em> a compiler, it is only a lexical scanner.
+ This means that it can and will not detect errors in your source code.
+<li>Since it impossible to test all possible code fragments, it is
+ very well possible, that some valid piece of C/C++ code is not handled
+ properly. If you find such a piece, please send it to me, so I can
+ improve doxygen's parsing capabilities. Try to make the piece of code
+ you send as small as possible, to help me narrow down the search.
+<li>Using declarations and directives are not yet. They are
+ simply ignored.
+<li>Doxygen does not work properly if there are multiple classes, structs
+ or unions with the same name in your code. It should not crash however,
+ rather it should ignore all of the classes with the same name except one.
+<li>Some commands do not work inside the arguments of other commands.
+ Inside a HTML link (i.e \<a href="..."\>...\<a\>) for instance
+ other commands (including other HTML commands) do not work!
+ The sectioning commands are an important exception.
+<li>Redundant braces can confuse doxygen in some cases.
+ For example:
+\verbatim
+ void f (int);
+\endverbatim
+ is properly parsed as a function declaration, but
+\verbatim
+ const int (a);
+\endverbatim
+ is also seen as a function declaration, because only the syntax is analysed,
+ not the semantics. If the redundant braces can be detected, as in
+\verbatim
+ int *(a[20]);
+\endverbatim
+ then doxygen will remove the braces and correctly parse the result.
+</ul>
+
+
+<h2>How to help</h2>
+The development of Doxygen highly depends on your input!
+
+If you are trying Doxygen let me know what you think of it (do you
+miss certain features?). Even if you decide not to use it, please let me
+know why.
+
+Furthermore, I would appreciate a mail if you have found
+a bug, or if you have ideas (or even better some code or a patch)
+how to fix existing bugs and limitations.
+
+My email address: <a href="mailto:dimitri@stack.nl">dimitri@stack.nl</a>
+*/
+
diff --git a/examples/Makefile b/examples/Makefile
new file mode 100644
index 0000000..dd97c2c
--- /dev/null
+++ b/examples/Makefile
@@ -0,0 +1,94 @@
+include ../Makefile.config
+DOXYDIR = ../bin
+
+all: class/html/index.html \
+ define/html/index.html \
+ enum/html/index.html \
+ file/html/index.html \
+ func/html/index.html \
+ page/html/index.html \
+ relates/html/index.html \
+ author/html/index.html \
+ par/html/index.html \
+ overload/html/index.html \
+ example/html/index.html \
+ include/html/index.html \
+ qtstyle/html/index.html \
+ jdstyle/html/index.html \
+ structcmd/html/index.html \
+ autolink/html/index.html \
+ resdefine/html/index.html \
+ restypedef/html/index.html \
+ afterdoc/html/index.html \
+ template/html/index.html \
+ tag/html/index.html
+
+clean:
+ rm -rf class define enum file func page relates author \
+ par overload example include qtstyle jdstyle structcmd \
+ autolink tag resdefine restypedef afterdoc template
+
+class/html/index.html: class.h class.cfg
+ $(DOXYDIR)/doxygen class.cfg
+
+define/html/index.html: define.h define.cfg
+ $(DOXYDIR)/doxygen define.cfg
+
+enum/html/index.html: enum.h enum.cfg
+ $(DOXYDIR)/doxygen enum.cfg
+
+file/html/index.html: file.h file.cfg
+ $(DOXYDIR)/doxygen file.cfg
+
+func/html/index.html: func.h func.cfg
+ $(DOXYDIR)/doxygen func.cfg
+
+page/html/index.html: page.doc page.cfg
+ $(DOXYDIR)/doxygen page.cfg
+
+relates/html/index.html: relates.cpp relates.cfg
+ $(DOXYDIR)/doxygen relates.cfg
+
+author/html/index.html: author.cpp author.cfg
+ $(DOXYDIR)/doxygen author.cfg
+
+par/html/index.html: par.cpp par.cfg
+ $(DOXYDIR)/doxygen par.cfg
+
+overload/html/index.html: overload.cpp overload.cfg
+ $(DOXYDIR)/doxygen overload.cfg
+
+example/html/index.html: example.cpp example_test.cpp example.cfg
+ $(DOXYDIR)/doxygen example.cfg
+
+include/html/index.html: include.cpp example_test.cpp include.cfg
+ $(DOXYDIR)/doxygen include.cfg
+
+qtstyle/html/index.html: qtstyle.cpp qtstyle.cfg
+ $(DOXYDIR)/doxygen qtstyle.cfg
+
+jdstyle/html/index.html: jdstyle.cpp jdstyle.cfg
+ $(DOXYDIR)/doxygen jdstyle.cfg
+
+structcmd/html/index.html: structcmd.h structcmd.cfg
+ $(DOXYDIR)/doxygen structcmd.cfg
+
+autolink/html/index.html: autolink.cpp autolink.cfg
+ $(DOXYDIR)/doxygen autolink.cfg
+
+tag/html/index.html: tag.cpp tag.cfg
+ $(DOXYDIR)/doxygen tag.cfg
+ sed -e "1,1s.perl.$(PERL).g" tag/html/installdox >tag/html/installdox.perl
+ cd tag/html ; $(PERL) installdox.perl -lexample.tag@../../example/html
+
+resdefine/html/index.html: resdefine.cpp resdefine.cfg
+ $(DOXYDIR)/doxygen resdefine.cfg
+
+restypedef/html/index.html: restypedef.cpp restypedef.cfg
+ $(DOXYDIR)/doxygen restypedef.cfg
+
+afterdoc/html/index.html: afterdoc.h afterdoc.cfg
+ $(DOXYDIR)/doxygen afterdoc.cfg
+
+template/html/index.html: templ.cpp templ.cfg
+ $(DOXYDIR)/doxygen templ.cfg
diff --git a/examples/Makefile.windows b/examples/Makefile.windows
new file mode 100644
index 0000000..da7cd09
--- /dev/null
+++ b/examples/Makefile.windows
@@ -0,0 +1,93 @@
+DOXYDIR = ..\bin
+
+all: class/html/index.html \
+ define/html/index.html \
+ enum/html/index.html \
+ file/html/index.html \
+ func/html/index.html \
+ page/html/index.html \
+ relates/html/index.html \
+ author/html/index.html \
+ par/html/index.html \
+ overload/html/index.html \
+ example/html/index.html \
+ include/html/index.html \
+ qtstyle/html/index.html \
+ jdstyle/html/index.html \
+ structcmd/html/index.html \
+ autolink/html/index.html \
+ tag/html/index.html \
+ resdefine/html/index.html \
+ restypedef/html/index.html \
+ afterdoc/html/index.html
+
+clean:
+ deltree /y class define enum file
+ deltree /y func page relates author
+ deltree /y par overload example include qtstyle
+ deltree /y jdstyle structcmd autolink tag resdefine
+ deltree /y restypedef
+
+class/html/index.html: class.h class.cfg
+ $(DOXYDIR)\doxygen class.cfg
+
+define/html/index.html: define.h define.cfg
+ $(DOXYDIR)\doxygen define.cfg
+
+enum/html/index.html: enum.h enum.cfg
+ $(DOXYDIR)\doxygen enum.cfg
+
+file/html/index.html: file.h file.cfg
+ $(DOXYDIR)\doxygen file.cfg
+
+func/html/index.html: func.h func.cfg
+ $(DOXYDIR)\doxygen func.cfg
+
+page/html/index.html: page.doc page.cfg
+ $(DOXYDIR)\doxygen page.cfg
+
+relates/html/index.html: relates.cpp relates.cfg
+ $(DOXYDIR)\doxygen relates.cfg
+
+author/html/index.html: author.cpp author.cfg
+ $(DOXYDIR)\doxygen author.cfg
+
+par/html/index.html: par.cpp par.cfg
+ $(DOXYDIR)\doxygen par.cfg
+
+overload/html/index.html: overload.cpp overload.cfg
+ $(DOXYDIR)\doxygen overload.cfg
+
+example/html/index.html: example.cpp example_test.cpp example.cfg
+ $(DOXYDIR)\doxygen example.cfg
+
+include/html/index.html: include.cpp example_test.cpp include.cfg
+ $(DOXYDIR)\doxygen include.cfg
+
+qtstyle/html/index.html: qtstyle.cpp qtstyle.cfg
+ $(DOXYDIR)\doxygen qtstyle.cfg
+
+jdstyle/html/index.html: jdstyle.cpp jdstyle.cfg
+ $(DOXYDIR)\doxygen jdstyle.cfg
+
+structcmd/html/index.html: structcmd.h structcmd.cfg
+ $(DOXYDIR)\doxygen structcmd.cfg
+
+autolink/html/index.html: autolink.cpp autolink.cfg
+ $(DOXYDIR)\doxygen autolink.cfg
+
+tag/html/index.html: tag.cpp tag.cfg
+ $(DOXYDIR)\doxygen tag.cfg
+ cd tag\html
+ echo perl installdox -lexample.tag@../../example/html >runperl.bat
+ runperl.bat
+ cd ..\..
+
+resdefine/html/index.html: resdefine.cpp resdefine.cfg
+ $(DOXYDIR)\doxygen resdefine.cfg
+
+restypedef/html/index.html: restypedef.cpp restypedef.cfg
+ $(DOXYDIR)\doxygen restypedef.cfg
+
+afterdoc/html/index.html: afterdoc.h afterdoc.cfg
+ $(DOXYDIR)\doxygen afterdoc.cfg
diff --git a/examples/afterdoc.cfg b/examples/afterdoc.cfg
new file mode 100644
index 0000000..9ebe07a
--- /dev/null
+++ b/examples/afterdoc.cfg
@@ -0,0 +1,6 @@
+PROJECT_NAME = "AfterDocs"
+OUTPUT_DIRECTORY = afterdoc
+GENERATE_LATEX = NO
+GENERATE_MAN = NO
+INPUT = afterdoc.h
+QUIET = YES
diff --git a/examples/afterdoc.h b/examples/afterdoc.h
new file mode 100644
index 0000000..907dabe
--- /dev/null
+++ b/examples/afterdoc.h
@@ -0,0 +1,18 @@
+/*! A test class */
+
+class Test
+{
+ public:
+ /** An enum type.
+ * The documentation block cannot be put after the enum!
+ */
+ enum EnumType
+ {
+ int EVal1, /**< enum value 1 */
+ int EVal2 /**< enum value 2 */
+ };
+ void member(); //!< a member function.
+
+ protected:
+ int value; /*!< an integer value */
+};
diff --git a/examples/author.cfg b/examples/author.cfg
new file mode 100644
index 0000000..f099903
--- /dev/null
+++ b/examples/author.cfg
@@ -0,0 +1,6 @@
+PROJECT_NAME = "Author Command"
+OUTPUT_DIRECTORY = author
+GENERATE_LATEX = NO
+GENERATE_MAN = NO
+INPUT = author.cpp
+QUIET = YES
diff --git a/examples/author.cpp b/examples/author.cpp
new file mode 100644
index 0000000..ce1c58c
--- /dev/null
+++ b/examples/author.cpp
@@ -0,0 +1,14 @@
+/*! \class WindowsNT
+ * \brief Windows Nice Try.
+ * \author Bill Gates
+ * \author Several hundred furry animals gathered in a cave and grooving
+ * with a pit.
+ * \version 4.0
+ * \date 1996-1998
+ * \bug It crashes a lot and requires huge amounts of memory.
+ * \bug The class introduces the more bugs, the longer it is used.
+ * \warning This class may explode in your face.
+ * \warning If you inherit anything from this class, you're doomed.
+ */
+
+class WindowsNT {};
diff --git a/examples/autolink.cfg b/examples/autolink.cfg
new file mode 100644
index 0000000..ff77f83
--- /dev/null
+++ b/examples/autolink.cfg
@@ -0,0 +1,6 @@
+PROJECT_NAME = "Automatic link generation"
+OUTPUT_DIRECTORY = autolink
+GENERATE_LATEX = NO
+GENERATE_MAN = NO
+INPUT = autolink.cpp
+QUIET = YES
diff --git a/examples/autolink.cpp b/examples/autolink.cpp
new file mode 100644
index 0000000..924256b
--- /dev/null
+++ b/examples/autolink.cpp
@@ -0,0 +1,99 @@
+/*! \file autolink.cpp
+ Testing automatic link generation.
+
+ A link to a member of the Test class: Test::member,
+
+ More specific links to the each of the overloaded members:
+ Test::member(int) and Test#member(int,int)
+
+ A link to a protected member variable of Test: Test#var,
+
+ A link to the global enumeration type #GlobEnum.
+
+ A link to the define #ABS(x).
+
+ A link to the destructor of the Test class: Test::~Test,
+
+ A link to the typedef ::B.
+
+ A link to the enumeration type Test::EType
+
+ A link to some enumeration values Test::Val1 and ::GVal2
+*/
+
+/*!
+ Since this documentation block belongs to the class Test no link to
+ Test is generated.
+
+ Two ways to link to a constructor are: #Test and Test().
+
+ Links to the destructor are: #~Test and ~Test().
+
+ A link to a member in this class: member().
+
+ More specific links to the each of the overloaded members:
+ member(int) and member(int,int).
+
+ A link to the variable #var.
+
+ A link to the global typedef ::B.
+
+ A link to the global enumeration type #GlobEnum.
+
+ A link to the define ABS(x).
+
+ A link to a variable \link #var using another text\endlink as a link.
+
+ A link to the enumeration type #EType.
+
+ A link to some enumeration values: ::Val1 and ::GVal1.
+
+ And last but not least a link to a file: autolink.cpp.
+
+ \sa Inside a see also section any word is checked, so EType,
+ Val1, GVal1, ~Test and member will be replaced by links in HTML.
+*/
+
+class Test
+{
+ public:
+ Test(); //!< constructor
+ ~Test(); //!< destructor
+ void member(int); /**< A member function. Details. */
+ void member(int,int); /**< An overloaded member function. Details */
+
+ /** An enum type. More details */
+ enum EType {
+ Val1, /**< enum value 1 */
+ Val2 /**< enum value 2 */
+ };
+
+ protected:
+ int var; /**< A member variable */
+};
+
+/*! details. */
+Test::Test() { }
+
+/*! details. */
+Test::~Test() { }
+
+/*! A global variable. */
+int globVar;
+
+/*! A global enum. */
+enum GlobEnum {
+ GVal1, /*!< global enum value 1 */
+ GVal2 /*!< global enum value 2 */
+ };
+
+/*!
+ * A macro definition.
+ */
+#define ABS(x) (((x)>0)?(x):-(x))
+
+typedef Test B;
+
+/*! \fn typedef Test B
+ * A type definition.
+ */
diff --git a/examples/class.cfg b/examples/class.cfg
new file mode 100644
index 0000000..dfc59eb
--- /dev/null
+++ b/examples/class.cfg
@@ -0,0 +1,6 @@
+PROJECT_NAME = "Class Command"
+OUTPUT_DIRECTORY = class
+GENERATE_LATEX = NO
+GENERATE_MAN = NO
+INPUT = class.h
+QUIET = YES
diff --git a/examples/class.h b/examples/class.h
new file mode 100644
index 0000000..e5c4e2d
--- /dev/null
+++ b/examples/class.h
@@ -0,0 +1,11 @@
+/* A dummy class */
+
+class Test
+{
+}
+
+/*! \class Test class.h inc/class.h
+ * \brief This is a test class.
+ *
+ * Some details about the Test class
+ */
diff --git a/examples/define.cfg b/examples/define.cfg
new file mode 100644
index 0000000..4960748
--- /dev/null
+++ b/examples/define.cfg
@@ -0,0 +1,7 @@
+PROJECT_NAME = "Define Command"
+OUTPUT_DIRECTORY = define
+GENERATE_LATEX = NO
+GENERATE_MAN = NO
+INPUT = define.h
+ENABLE_PREPROCESSING = YES
+QUIET = YES
diff --git a/examples/define.h b/examples/define.h
new file mode 100644
index 0000000..9a8e4d0
--- /dev/null
+++ b/examples/define.h
@@ -0,0 +1,11 @@
+/*! \file define.h
+ \brief testing defines
+
+ This is to test the documentation of defines.
+*/
+
+/*! \def ABS(x)
+ The define ABS computes the absolute value of its argument \a x.
+*/
+
+#define ABS(x) (((x)>0)?(x):-(x))
diff --git a/examples/enum.cfg b/examples/enum.cfg
new file mode 100644
index 0000000..b38291a
--- /dev/null
+++ b/examples/enum.cfg
@@ -0,0 +1,6 @@
+PROJECT_NAME = "Enum Command"
+OUTPUT_DIRECTORY = enum
+GENERATE_LATEX = NO
+GENERATE_MAN = NO
+INPUT = enum.h
+QUIET = YES
diff --git a/examples/enum.h b/examples/enum.h
new file mode 100644
index 0000000..1586074
--- /dev/null
+++ b/examples/enum.h
@@ -0,0 +1,17 @@
+class Test
+{
+ public:
+ enum TEnum { Val1, Val2 };
+};
+
+/*! \class Test
+ * The class description.
+ */
+
+/*! \enum Test::TEnum
+ * A description of the enum type.
+ */
+
+/*! \var Test::TEnum Test::Val1
+ * The description of the first enum value.
+ */
diff --git a/examples/example.cfg b/examples/example.cfg
new file mode 100644
index 0000000..a30b3ff
--- /dev/null
+++ b/examples/example.cfg
@@ -0,0 +1,7 @@
+PROJECT_NAME = "Example Command"
+OUTPUT_DIRECTORY = example
+GENERATE_LATEX = NO
+GENERATE_MAN = NO
+INPUT = example.cpp
+EXAMPLE_PATH = example_test.cpp
+QUIET = YES
diff --git a/examples/example.cpp b/examples/example.cpp
new file mode 100644
index 0000000..230d6ec
--- /dev/null
+++ b/examples/example.cpp
@@ -0,0 +1,19 @@
+/** A Test class.
+ * More details about this class.
+ */
+
+class Test
+{
+ public:
+ /** An example member function.
+ * More details about this function.
+ */
+ void example();
+};
+
+void Test::example() {}
+
+/** \example example_test.cpp
+ * This is an example of how to use the Test class.
+ * More details about this example.
+ */
diff --git a/examples/example.tag b/examples/example.tag
new file mode 100644
index 0000000..3998b90
--- /dev/null
+++ b/examples/example.tag
@@ -0,0 +1,2 @@
+>Test:
+example a0 "()"
diff --git a/examples/example_test.cpp b/examples/example_test.cpp
new file mode 100644
index 0000000..a7e1643
--- /dev/null
+++ b/examples/example_test.cpp
@@ -0,0 +1,5 @@
+void main()
+{
+ Test t;
+ t.example();
+}
diff --git a/examples/file.cfg b/examples/file.cfg
new file mode 100644
index 0000000..52b766a
--- /dev/null
+++ b/examples/file.cfg
@@ -0,0 +1,6 @@
+PROJECT_NAME = "File Command"
+OUTPUT_DIRECTORY = file
+GENERATE_LATEX = NO
+GENERATE_MAN = NO
+INPUT = file.h
+QUIET = YES
diff --git a/examples/file.h b/examples/file.h
new file mode 100644
index 0000000..8dff6cb
--- /dev/null
+++ b/examples/file.h
@@ -0,0 +1,10 @@
+/** \file file.h
+ * A brief file description.
+ * A more elaborated file description.
+ */
+
+/**
+ * A global integer value.
+ * More details about this value.
+ */
+extern int globalValue;
diff --git a/examples/func.cfg b/examples/func.cfg
new file mode 100644
index 0000000..44d67c6
--- /dev/null
+++ b/examples/func.cfg
@@ -0,0 +1,6 @@
+PROJECT_NAME = "Fn Command"
+OUTPUT_DIRECTORY = func
+GENERATE_LATEX = NO
+GENERATE_MAN = NO
+INPUT = func.h
+QUIET = YES
diff --git a/examples/func.h b/examples/func.h
new file mode 100644
index 0000000..b335448
--- /dev/null
+++ b/examples/func.h
@@ -0,0 +1,21 @@
+class Test
+{
+ public:
+ const char *member(char,int) throw(std::out_of_range);
+};
+
+const char *Test::member(char c,int n) throw(std::out_of_range) {}
+
+/*! \class Test
+ * \brief Test class.
+ *
+ * Details about Test.
+ */
+
+/*! \fn const char *Test::member(char c,int n)
+ * \brief A member function.
+ * \param c a character.
+ * \param n an integer.
+ * \exception std::out_of_range parameter is out of range.
+ * \return a character pointer.
+ */
diff --git a/examples/include.cfg b/examples/include.cfg
new file mode 100644
index 0000000..c4f997e
--- /dev/null
+++ b/examples/include.cfg
@@ -0,0 +1,7 @@
+PROJECT_NAME = "Include Command"
+OUTPUT_DIRECTORY = include
+GENERATE_LATEX = NO
+GENERATE_MAN = NO
+INPUT = include.cpp
+EXAMPLE_PATH = example_test.cpp
+QUIET = YES
diff --git a/examples/include.cpp b/examples/include.cpp
new file mode 100644
index 0000000..c50ab96
--- /dev/null
+++ b/examples/include.cpp
@@ -0,0 +1,22 @@
+
+/*! A test class. */
+
+class Test
+{
+ public:
+ /// a member function
+ void example();
+};
+
+/*! \page example
+ * \dontinclude example_test.cpp
+ * Our main function starts like this:
+ * \skip main
+ * \until {
+ * First we create a object \c t of the Test class.
+ * \skipline Test
+ * Then we call the example member function
+ * \line example
+ * After that our little test routine ends.
+ * \line }
+ */
diff --git a/examples/jdstyle.cfg b/examples/jdstyle.cfg
new file mode 100644
index 0000000..833a4aa
--- /dev/null
+++ b/examples/jdstyle.cfg
@@ -0,0 +1,6 @@
+PROJECT_NAME = "JavaDoc Style"
+OUTPUT_DIRECTORY = jdstyle
+GENERATE_LATEX = NO
+GENERATE_MAN = NO
+INPUT = jdstyle.cpp
+QUIET = YES
diff --git a/examples/jdstyle.cpp b/examples/jdstyle.cpp
new file mode 100644
index 0000000..bbd2149
--- /dev/null
+++ b/examples/jdstyle.cpp
@@ -0,0 +1,66 @@
+/**
+ * A test class. A more elaborate class description.
+ */
+
+class Test
+{
+ public:
+
+ /**
+ * An enum.
+ * More detailed enum description.
+ */
+
+ enum TEnum {
+ TVal1, /**< enum value TVal1. */
+ TVal2, /**< enum value TVal2. */
+ TVal3 /**< enum value TVal3. */
+ }
+ *enumPtr, /**< enum pointer. Details. */
+ enumVar; /**< enum variable. Details. */
+
+ /**
+ * A constructor.
+ * A more elaborate description of the constructor.
+ */
+ Test();
+
+ /**
+ * A destructor.
+ * A more elaborate description of the destructor.
+ */
+ ~Test();
+
+ /**
+ * a normal member taking two arguments and returning an integer value.
+ * @param a an integer argument.
+ * @param s a constant chararcter pointer.
+ * @see Test()
+ * @see ~Test()
+ * @see testMeToo()
+ * @see publicVar()
+ * @return The test results
+ */
+ int testMe(int a,const char *s);
+
+ /**
+ * A pure virtual member.
+ * @see testMe()
+ * @param c1 the first argument.
+ * @param c2 the second argument.
+ */
+ virtual void testMeToo(char c1,char c2) = 0;
+
+ /**
+ * a public variable.
+ * Details.
+ */
+ int publicVar;
+
+ /**
+ * a function variable.
+ * Details.
+ */
+ int (*handler)(int a,int b);
+};
+
diff --git a/examples/overload.cfg b/examples/overload.cfg
new file mode 100644
index 0000000..690edae
--- /dev/null
+++ b/examples/overload.cfg
@@ -0,0 +1,6 @@
+PROJECT_NAME = "Overloaded Command"
+OUTPUT_DIRECTORY = overload
+GENERATE_LATEX = NO
+GENERATE_MAN = NO
+INPUT = overload.cpp
+QUIET = YES
diff --git a/examples/overload.cpp b/examples/overload.cpp
new file mode 100644
index 0000000..02bcced
--- /dev/null
+++ b/examples/overload.cpp
@@ -0,0 +1,25 @@
+class Test
+{
+ public:
+ void drawRect(int,int,int,int);
+ void drawRect(const Rect &r);
+};
+
+void Test::drawRect(int x,int y,int w,int h) {}
+void Test::drawRect(const Rect &r) {}
+
+/*! \class Test
+ * \brief A short description.
+ *
+ * More text.
+ */
+
+/*! \fn void Test::drawRect(int x,int y,int w,int h)
+ * This command draws a rectangle with a left upper corner at ( \a x , \a y ),
+ * width \a w and height \a h.
+ */
+
+/*!
+ * \overload void Test::drawRect(const Rect &r)
+ */
+
diff --git a/examples/page.cfg b/examples/page.cfg
new file mode 100644
index 0000000..40a8869
--- /dev/null
+++ b/examples/page.cfg
@@ -0,0 +1,6 @@
+PROJECT_NAME = "Page Command"
+OUTPUT_DIRECTORY = page
+GENERATE_LATEX = NO
+GENERATE_MAN = NO
+INPUT = page.doc
+QUIET = YES
diff --git a/examples/page.doc b/examples/page.doc
new file mode 100644
index 0000000..41c9e02
--- /dev/null
+++ b/examples/page.doc
@@ -0,0 +1,12 @@
+/*! \page page1 A documentation page
+ This page contains the subsections \ref subsection1 and \ref subsection2.
+ For more info see section \ref page2.
+ \subsection subsection1 The first subsection
+ Text.
+ \subsection subsection2 The second subsection
+ More text.
+*/
+
+/*! \page page2 Another page
+ Even more info.
+*/
diff --git a/examples/par.cfg b/examples/par.cfg
new file mode 100644
index 0000000..76dab9f
--- /dev/null
+++ b/examples/par.cfg
@@ -0,0 +1,6 @@
+PROJECT_NAME = "Par Command"
+OUTPUT_DIRECTORY = par
+GENERATE_LATEX = NO
+GENERATE_MAN = NO
+INPUT = par.cpp
+QUIET = YES
diff --git a/examples/par.cpp b/examples/par.cpp
new file mode 100644
index 0000000..144d1af
--- /dev/null
+++ b/examples/par.cpp
@@ -0,0 +1,9 @@
+/*! \class Test
+ * Normal text.
+ * \par User defined paragraph:
+ * Contents of the paragraph.
+ *
+ * More normal text.
+ */
+
+class Test {};
diff --git a/examples/qtstyle.cfg b/examples/qtstyle.cfg
new file mode 100644
index 0000000..6d20b53
--- /dev/null
+++ b/examples/qtstyle.cfg
@@ -0,0 +1,6 @@
+PROJECT_NAME = "Qt Style"
+OUTPUT_DIRECTORY = qtstyle
+GENERATE_LATEX = NO
+GENERATE_MAN = NO
+INPUT = qtstyle.cpp
+QUIET = YES
diff --git a/examples/qtstyle.cpp b/examples/qtstyle.cpp
new file mode 100644
index 0000000..de5ad34
--- /dev/null
+++ b/examples/qtstyle.cpp
@@ -0,0 +1,65 @@
+//! A test class.
+/*!
+ A more elaborate class description.
+*/
+
+class Test
+{
+ public:
+
+ //! An enum.
+ /*! More detailed enum description. */
+ enum TEnum {
+ TVal1, /*!< Enum value TVal1. */
+ TVal2, /*!< Enum value TVal2. */
+ TVal3 /*!< Enum value TVal3. */
+ }
+ //! Enum pointer.
+ /*! Details. */
+ *enumPtr,
+ //! Enum variable.
+ /*! Details. */
+ enumVar;
+
+ //! A constructor.
+ /*!
+ A more elaborate description of the constructor.
+ */
+ Test();
+
+ //! A destructor.
+ /*!
+ A more elaborate description of the destructor.
+ */
+ ~Test();
+
+ //! A normal member taking two arguments and returning an integer value.
+ /*!
+ \param a an integer argument.
+ \param s a constant chararcter pointer.
+ \return The test results
+ \sa Test(), ~Test(), testMeToo() and publicVar()
+ */
+ int testMe(int a,const char *s);
+
+ //! A pure virtual member.
+ /*!
+ \sa testMe()
+ \param c1 the first argument.
+ \param c2 the second argument.
+ */
+ virtual void testMeToo(char c1,char c2) = 0;
+
+ //! A public variable.
+ /*!
+ Details.
+ */
+ int publicVar;
+
+ //! A function variable.
+ /*!
+ Details.
+ */
+ int (*handler)(int a,int b);
+};
+
diff --git a/examples/relates.cfg b/examples/relates.cfg
new file mode 100644
index 0000000..83e2be5
--- /dev/null
+++ b/examples/relates.cfg
@@ -0,0 +1,6 @@
+PROJECT_NAME = "Relates Command"
+OUTPUT_DIRECTORY = relates
+GENERATE_LATEX = NO
+GENERATE_MAN = NO
+INPUT = relates.cpp
+QUIET = YES
diff --git a/examples/relates.cpp b/examples/relates.cpp
new file mode 100644
index 0000000..d5e483d
--- /dev/null
+++ b/examples/relates.cpp
@@ -0,0 +1,24 @@
+/*!
+ * A String class.
+ */
+
+class String
+{
+ friend int strcmp(const String &,const String &);
+};
+
+/*!
+ * Compares two strings.
+ */
+
+int strcmp(const String &s1,const String &s2)
+{
+}
+
+/*! \relates String
+ * A string debug function.
+ */
+
+void stringDebug()
+{
+}
diff --git a/examples/resdefine.cfg b/examples/resdefine.cfg
new file mode 100644
index 0000000..009a4e8
--- /dev/null
+++ b/examples/resdefine.cfg
@@ -0,0 +1,6 @@
+PROJECT_NAME = "Resolving Defines"
+OUTPUT_DIRECTORY = resdefine
+GENERATE_LATEX = NO
+GENERATE_MAN = NO
+INPUT = resdefine.cpp
+QUIET = YES
diff --git a/examples/resdefine.cpp b/examples/resdefine.cpp
new file mode 100644
index 0000000..05a77c5
--- /dev/null
+++ b/examples/resdefine.cpp
@@ -0,0 +1,21 @@
+#define ExportedName InternalName
+
+class InternalName
+{
+ public:
+ InternalName() {}
+ ~InternalName() {}
+};
+
+/*! \class ExportedName
+ * This class's real name is InternalName but everyone should use
+ * ExportedName.
+ */
+
+/*! \fn ExportedName::ExportedName()
+ * The constructor
+ */
+
+/*! \fn ExportedName::~ExportedName()
+ * The destructor
+ */
diff --git a/examples/restypedef.cfg b/examples/restypedef.cfg
new file mode 100644
index 0000000..f17ba4d
--- /dev/null
+++ b/examples/restypedef.cfg
@@ -0,0 +1,6 @@
+PROJECT_NAME = "Resolving Typedefs"
+OUTPUT_DIRECTORY = restypedef
+GENERATE_LATEX = NO
+GENERATE_MAN = NO
+INPUT = restypedef.cpp
+QUIET = YES
diff --git a/examples/restypedef.cpp b/examples/restypedef.cpp
new file mode 100644
index 0000000..2cd3f8f
--- /dev/null
+++ b/examples/restypedef.cpp
@@ -0,0 +1,25 @@
+/*! \file restypedef.cpp
+ * An example of resolving typedefs.
+ */
+
+/*! \struct CoordStruct
+ * A coordinate pair.
+ */
+struct CoordStruct
+{
+ /*! The x coordinate */
+ float x;
+ /*! The y coordinate */
+ float y;
+};
+
+/*! Creates a type name for CoordStruct */
+typedef struct CoordStruct Coord;
+
+/*!
+ * This function returns the addition of \a c1 and \a c2, i.e:
+ * (c1.x+c2.x,c1.y+c2.y)
+ */
+Coord add(Coord c1,Coord c2)
+{
+}
diff --git a/examples/structcmd.cfg b/examples/structcmd.cfg
new file mode 100644
index 0000000..bbc4e71
--- /dev/null
+++ b/examples/structcmd.cfg
@@ -0,0 +1,6 @@
+PROJECT_NAME = "Structural commands"
+OUTPUT_DIRECTORY = structcmd
+GENERATE_LATEX = NO
+GENERATE_MAN = NO
+INPUT = structcmd.h
+QUIET = YES
diff --git a/examples/structcmd.h b/examples/structcmd.h
new file mode 100644
index 0000000..3e27029
--- /dev/null
+++ b/examples/structcmd.h
@@ -0,0 +1,57 @@
+/*! \file structcmd.h
+ \brief A Documented file.
+
+ Details.
+*/
+
+/*! \def MAX(a,b)
+ \brief A macro that returns the maximum of \a a and \a b.
+
+ Details.
+*/
+
+/*! \var typedef unsigned int UINT32
+ \brief A type definition for a .
+
+ Details.
+*/
+
+/*! \var int errno
+ \brief Contains the last error code.
+
+ \warning Not thread safe!
+*/
+
+/*! \fn int open(const char *pathname,int flags)
+ \brief Opens a file descriptor.
+
+ \param pathname The name of the descriptor.
+ \param flags Opening flags.
+*/
+
+/*! \fn int close(int fd)
+ \brief Closes the file descriptor \a fd.
+ \param fd The descriptor to close.
+*/
+
+/*! \fn size_t write(int fd,const char *buf, size_t count)
+ \brief Writes \a count bytes from \a buf to the filedescriptor \a fd.
+ \param fd The descriptor to write to.
+ \param buf The data buffer to write.
+ \param count The number of bytes to write.
+*/
+
+/*! \fn int read(int fd,char *buf,size_t count)
+ \brief Read bytes from a file descriptor.
+ \param fd The descriptor to read from.
+ \param buf The buffer to read into.
+ \param count The number of bytes to read.
+*/
+
+#define MAX(a,b) (((a)>(b))?(a):(b))
+typedef unsigned int UINT32;
+int errno;
+int open(const char *,int);
+int close(int);
+size_t write(int,const char *, size_t);
+int read(int,char *,size_t);
diff --git a/examples/tag.cfg b/examples/tag.cfg
new file mode 100644
index 0000000..79c2ec0
--- /dev/null
+++ b/examples/tag.cfg
@@ -0,0 +1,8 @@
+PROJECT_NAME = "Tag Files"
+OUTPUT_DIRECTORY = tag
+GENERATE_LATEX = NO
+GENERATE_MAN = NO
+INPUT = tag.cpp
+TAGFILES = example.tag
+PERL_PATH = perl
+QUIET = YES
diff --git a/examples/tag.cpp b/examples/tag.cpp
new file mode 100644
index 0000000..6497dd4
--- /dev/null
+++ b/examples/tag.cpp
@@ -0,0 +1,9 @@
+/*! A class that is inherited from the external class Test.
+*/
+
+class Tag : public Test
+{
+ public:
+ /*! an overloaded member. */
+ void example();
+};
diff --git a/examples/templ.cfg b/examples/templ.cfg
new file mode 100644
index 0000000..ec16654
--- /dev/null
+++ b/examples/templ.cfg
@@ -0,0 +1,6 @@
+PROJECT_NAME = "Template Test"
+OUTPUT_DIRECTORY = template
+GENERATE_LATEX = NO
+GENERATE_MAN = NO
+INPUT = templ.cpp
+QUIET = YES
diff --git a/examples/templ.cpp b/examples/templ.cpp
new file mode 100644
index 0000000..c838c6e
--- /dev/null
+++ b/examples/templ.cpp
@@ -0,0 +1,37 @@
+/*! A template class */
+template<class T,int i=100> class Test
+{
+ public:
+ Test();
+ Test(const Test &);
+ friend void friendTempFunc(Test &, int=5);
+};
+
+/*! complete specialization */
+template<> class Test<void *,200>
+{
+ public:
+ Test();
+};
+
+/*! A partial template specialization */
+template<class T> class Test< T * > : public Test<void *,200>
+{
+ public:
+ Test();
+};
+
+/*! The constructor of the template class*/
+template<class T,int i> Test<T,i>::Test() {}
+
+/*! The copy constructor */
+template<class T,int i> Test<T,i>::Test(const Test<T,i> &t) {}
+
+/*! A friend function of a template class */
+template<class T,int i> void friendTempFunc(Test<T,i> &t,int a) {}
+
+/*! The constructor of the specilization */
+template<> Test<void *,200>::Test() {}
+
+/*! The constructor of the partial specilization */
+template<class T> Test<T*>::Test() {}
diff --git a/make.bat b/make.bat
new file mode 100644
index 0000000..a8a2f4e
--- /dev/null
+++ b/make.bat
@@ -0,0 +1,4 @@
+REM make script for Microsoft Visual C++
+
+set TMAKEPATH=..\tmake\lib\win32-msvc
+nmake /NOLOGO -f Makefile.windows win32-msvc
diff --git a/src/Makefile b/src/Makefile
new file mode 100644
index 0000000..e57994c
--- /dev/null
+++ b/src/Makefile
@@ -0,0 +1,44 @@
+#
+# $Id$
+#
+# Copyright (C) 1997-1999 by Dimitri van Heesch.
+#
+# Permission to use, copy, modify, and distribute this software and its
+# documentation under the terms of the GNU General Public License is hereby
+# granted. No representations are made about the suitability of this software
+# for any purpose. It is provided "as is" without express or implied warranty.
+# See the GNU General Public License for more details.
+#
+# All output generated with Doxygen is not covered by this license.
+#
+
+include ../Makefile.config
+
+all: Makefile.doxygen Makefile.doxytag Makefile.doxysearch Makefile
+ $(MAKE) -f Makefile.doxygen $@
+ $(MAKE) -f Makefile.doxytag $@
+ $(MAKE) -f Makefile.doxysearch $@
+
+Makefile.doxygen: doxygen.pro doxygen.t
+ $(PERL) $(TMAKE) doxygen.pro >Makefile.doxygen
+
+Makefile.doxytag: doxytag.pro doxytag.t
+ $(PERL) $(TMAKE) doxytag.pro >Makefile.doxytag
+
+Makefile.doxysearch: doxysearch.pro
+ $(PERL) $(TMAKE) doxysearch.pro >Makefile.doxysearch
+
+tmake:
+ $(PERL) $(TMAKE) doxygen.pro >Makefile.doxygen
+ $(PERL) $(TMAKE) doxytag.pro >Makefile.doxytag
+ $(PERL) $(TMAKE) doxysearch.pro >Makefile.doxysearch
+
+clean:
+ $(MAKE) -f Makefile.doxygen clean
+ $(MAKE) -f Makefile.doxytag clean
+ $(MAKE) -f Makefile.doxysearch clean
+ -rm -f scanner.cpp code.cpp config.cpp pre.cpp ce_lex.cpp \
+ ce_parse.cpp ce_parse.h doxytag.cpp tag.cpp \
+ declinfo.cpp defargs.cpp version.cpp
+
+FORCE:
diff --git a/src/classdef.cpp b/src/classdef.cpp
new file mode 100644
index 0000000..079252d
--- /dev/null
+++ b/src/classdef.cpp
@@ -0,0 +1,900 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#include <stdio.h>
+#include <qfile.h>
+#include <qregexp.h>
+#include "classdef.h"
+#include "classlist.h"
+#include "entry.h"
+#include "scanner.h"
+#include "doxygen.h"
+#include "membername.h"
+#include "message.h"
+#include "config.h"
+#include "util.h"
+#include "diagram.h"
+#include "language.h"
+
+static QString stripExtension(const char *fName)
+{
+ QString result=fName;
+ if (result.right(5)==".html") result=result.left(result.length()-5);
+ return result;
+}
+
+// constructs a new class definition
+ClassDef::ClassDef(const char *nm,int ct,const char *ref,const char *fName)
+ : Definition(removeRedundantWhiteSpace(nm))
+{
+ //name=n;
+ if (fName)
+ fileName=stripExtension(fName);
+ else
+ fileName="class_"+nameToFile(nm);
+ if (ref)
+ {
+ //url=(QString)"doxygen=\""+ref+":\" href=\""+fileName;
+ exampleList = 0;
+ exampleDict = 0;
+ }
+ else
+ {
+ //url="href=\""+fileName;
+ exampleList = new ExampleList;
+ exampleDict = new ExampleDict(29);
+ }
+ memListFileName="class_"+nameToFile(nm)+"-members";
+ inherits = new BaseClassList;
+ inherits->setAutoDelete(TRUE);
+ inheritedBy = new BaseClassList;
+ inheritedBy->setAutoDelete(TRUE);
+ allMemberNameInfoList = new MemberNameInfoList;
+ allMemberNameInfoList->setAutoDelete(TRUE);
+ allMemberNameInfoDict = new MemberNameInfoDict(1009);
+ visited=FALSE;
+ reference=ref;
+ compType=ct;
+ incFile=0;
+ tempArgs=0;
+ prot=Public;
+ nspace=0;
+}
+
+// destroy the class definition
+ClassDef::~ClassDef()
+{
+ delete inherits;
+ delete inheritedBy;
+ delete allMemberNameInfoList;
+ delete allMemberNameInfoDict;
+ delete exampleList;
+ delete exampleDict;
+}
+
+// inserts a base class in the inheritance list
+void ClassDef::insertBaseClass(ClassDef *cd,Protection p,
+ Specifier s,const char *t)
+{
+ inherits->inSort(new BaseClassDef(cd,p,s,t));
+}
+
+// inserts a super class in the inherited list
+void ClassDef::insertSuperClass(ClassDef *cd,Protection p,
+ Specifier s,const char *t)
+{
+ inheritedBy->inSort(new BaseClassDef(cd,p,s,t));
+}
+
+// adds new member definition to the class
+void ClassDef::insertMember(const MemberDef *md)
+{
+ //printf("adding %s::%s\n",name(),md->name());
+ if (!reference)
+ {
+ if (md->isRelated() && (extractPrivateFlag || md->protection()!=Private))
+ {
+ related.append(md);
+ }
+ else if (md->isFriend())
+ {
+ friends.append(md);
+ }
+ else
+ {
+ switch (md->memberType())
+ {
+ case MemberDef::Signal:
+ signals.append(md);
+ break;
+ case MemberDef::Slot:
+ switch (md->protection())
+ {
+ case Protected: proSlots.append(md); break;
+ case Public: pubSlots.append(md); break;
+ case Private: priSlots.append(md); break;
+ }
+ break;
+ default: // any of the other members
+ if (md->isStatic())
+ {
+ switch (md->protection())
+ {
+ case Protected: proStaticMembers.append(md); break;
+ case Public: pubStaticMembers.append(md); break;
+ case Private: priStaticMembers.append(md); break;
+ }
+ }
+ else
+ {
+ switch (md->protection())
+ {
+ case Protected: proMembers.append(md); break;
+ case Public: pubMembers.append(md); break;
+ case Private: priMembers.append(md); break;
+ }
+ }
+ break;
+ }
+ }
+ }
+ // check if we should add this member in the `all members' list
+ if (md->isFriend() || md->protection()!=Private || extractPrivateFlag)
+ {
+ MemberInfo *mi = new MemberInfo((MemberDef *)md,Public,Normal);
+ MemberNameInfo *mni;
+ if ((mni=(*allMemberNameInfoDict)[md->name()]))
+ {
+ mni->append(mi);
+ }
+ else
+ {
+ mni = new MemberNameInfo(md->name());
+ mni->append(mi);
+ allMemberNameInfoList->inSort(mni);
+ allMemberNameInfoDict->insert(mni->memberName(),mni);
+ }
+ }
+}
+
+
+// compute the anchors for all members
+void ClassDef::computeAnchors()
+{
+ setAnchors('a',&pubMembers);
+ setAnchors('b',&proMembers);
+ setAnchors('c',&priMembers);
+ setAnchors('d',&pubStaticMembers);
+ setAnchors('e',&proStaticMembers);
+ setAnchors('f',&priStaticMembers);
+ setAnchors('g',&pubSlots);
+ setAnchors('h',&proSlots);
+ setAnchors('i',&priSlots);
+ setAnchors('j',&signals);
+ setAnchors('k',&related);
+ setAnchors('l',&friends);
+}
+
+// add a file name to the used files set
+void ClassDef::insertUsedFile(const char *f)
+{
+ if (files.find(f)==-1) files.append(f);
+}
+
+static void writeInheritanceSpecifier(OutputList &ol,BaseClassDef *bcd)
+{
+ if (bcd->prot!=Public || bcd->virt!=Normal)
+ {
+ ol.startTypewriter();
+ ol.docify(" [");
+ QStrList sl;
+ if (bcd->prot==Protected) sl.append("protected");
+ else if (bcd->prot==Private) sl.append("private");
+ if (bcd->virt==Virtual) sl.append("virtual");
+ const char *s=sl.first();
+ while (s)
+ {
+ ol.docify(s);
+ s=sl.next();
+ if (s) ol.docify(", ");
+ }
+ ol.docify("]");
+ ol.endTypewriter();
+ }
+}
+
+// write all documentation for this class
+void ClassDef::writeDocumentation(OutputList &ol)
+{
+ // write title
+ QString pageTitle=name().copy();
+ QString pageType;
+ switch(compType)
+ {
+ case Class: pageType=" Class"; break;
+ case Struct: pageType=" Struct"; break;
+ case Union: pageType=" Union"; break;
+ default: pageType+=compType; break; // an error
+ }
+ pageTitle+=pageType+" Reference";
+ startFile(ol,fileName,pageTitle);
+ startTitle(ol);
+ ol.docify(name()+" "+pageType.right(pageType.length()-1)+" ");
+ parseDoc(ol,0,0,theTranslator->trReference());
+ endTitle(ol,name());
+
+ // write brief description
+ OutputList briefOutput(&ol);
+ if (!briefDescription().isEmpty())
+ {
+ parseDoc(briefOutput,name(),0,briefDescription());
+ ol+=briefOutput;
+ ol.writeString(" \n");
+ ol.disableAllBut(OutputGenerator::Html);
+ ol.startTextLink(0,"details");
+ parseDoc(ol,0,0,theTranslator->trMore());
+ ol.endTextLink();
+ ol.enableAll();
+ }
+ ol.disable(OutputGenerator::Man);
+ ol.newParagraph();
+ ol.enable(OutputGenerator::Man);
+ ol.writeSynopsis();
+
+ if (incFile)
+ {
+ QString nm=incName.copy();
+ if (incName.isNull()) nm=incFile->name();
+ ol.startTypewriter();
+ ol.docify("#include <");
+ ol.disable(OutputGenerator::Man);
+ if (verbatimHeaderFlag)
+ {
+ ol.writeObjectLink(0,fileName+"-include",0,nm);
+ }
+ else
+ {
+ ol.docify(nm);
+ }
+ ol.enable(OutputGenerator::Man);
+ ol.disableAllBut(OutputGenerator::Man);
+ ol.docify(nm);
+ ol.enableAll();
+ ol.docify(">");
+ ol.endTypewriter();
+ ol.newParagraph();
+ }
+
+ if (genTagFile.length()>0) tagFile << ">" << name() << ":";
+
+ if (classDiagramFlag) ol.disableAllBut(OutputGenerator::Man);
+
+ // write superclasses
+ int count;
+ if ((count=inherits->count())>0)
+ {
+ parseDoc(ol,0,0,theTranslator->trInherits()+" ");
+ BaseClassDef *bcd=inherits->first();
+ while (bcd)
+ {
+ ClassDef *cd=bcd->classDef;
+ if (cd->hasDocumentation() || cd->isReference())
+ {
+ if (genTagFile.length()>0) tagFile << cd->classFile() << "?";
+ ol.writeObjectLink(cd->getReference(),cd->classFile(),0,cd->name()+bcd->templSpecifiers);
+ }
+ else
+ {
+ ol.docify(cd->name());
+ }
+ writeInheritanceSpecifier(ol,bcd);
+ bcd=inherits->next();
+ if (bcd)
+ {
+ if (inherits->at()==count-1)
+ parseDoc(ol,0,0," "+theTranslator->trAnd()+" ");
+ else
+ ol.writeString(", ");
+ }
+ }
+ ol.writeString(".");
+ ol.newParagraph();
+ }
+
+ if (genTagFile.length()>0) tagFile << " \"" << fileName << ".html\"\n";
+
+ // write subclasses
+ if ((count=inheritedBy->count())>0)
+ {
+ parseDoc(ol,0,0,theTranslator->trInheritedBy()+" ");
+ BaseClassDef *bcd=inheritedBy->first();
+ while (bcd)
+ {
+ ClassDef *cd=bcd->classDef;
+ if (cd->hasDocumentation() || cd->isReference())
+ {
+ ol.writeObjectLink(cd->getReference(),cd->classFile(),0,cd->name());
+ }
+ else
+ {
+ ol.docify(cd->name());
+ }
+ writeInheritanceSpecifier(ol,bcd);
+ bcd=inheritedBy->next();
+ if (bcd)
+ {
+ if (inheritedBy->at()==count-1)
+ parseDoc(ol,0,0," "+theTranslator->trAnd()+" ");
+ else
+ ol.writeString(", ");
+ }
+ }
+ ol.writeString(".");
+ ol.newParagraph();
+ }
+
+ if (classDiagramFlag) ol.enableAll();
+
+ count=0;
+ BaseClassDef *ibcd;
+ ibcd=inheritedBy->first();
+ while (ibcd)
+ {
+ ClassDef *icd=ibcd->classDef;
+ if (//(icd->protection()!=Private || extractPrivateFlag) &&
+ //(icd->hasDocumentation() || !hideClassFlag || icd->isReference())
+ icd->isVisibleExt()
+ ) count++;
+ ibcd=inheritedBy->next();
+ }
+ ibcd=inherits->first();
+ while (ibcd)
+ {
+ ClassDef *icd=ibcd->classDef;
+ if (//(icd->protection()!=Private || extractPrivateFlag) &&
+ //(icd->hasDocumentation() || !hideClassFlag | icd->isReference())
+ icd->isVisibleExt()
+ ) count++;
+ ibcd=inherits->next();
+ }
+ if (classDiagramFlag && count>0)
+ // write class diagram
+ {
+ ClassDiagram diagram(this); // create a diagram of this class.
+ ol.startClassDiagram();
+ ol.disable(OutputGenerator::Man);
+ parseDoc(ol,name(),0,theTranslator->trClassDiagram(name()));
+ ol.enable(OutputGenerator::Man);
+ ol.endClassDiagram(diagram,fileName,name());
+ }
+
+ // write link to list of all members (HTML only)
+ if (allMemberNameInfoList->count()>0 && compType==Class)
+ {
+ ol.disableAllBut(OutputGenerator::Html);
+ ol.startTextLink(memListFileName,0);
+ parseDoc(ol,0,0,theTranslator->trListOfAllMembers());
+ ol.endTextLink();
+ ol.enableAll();
+ }
+
+ // write member groups
+ writeMemberDecs(ol,this,0,0,"Public Members",0,&pubMembers);
+ writeMemberDecs(ol,this,0,0,"Public Slots",0,&pubSlots);
+ writeMemberDecs(ol,this,0,0,"Signals",0,&signals);
+ writeMemberDecs(ol,this,0,0,"Static Public Members",0,&pubStaticMembers);
+ writeMemberDecs(ol,this,0,0,"Protected Members",0,&proMembers);
+ writeMemberDecs(ol,this,0,0,"Protected Slots",0,&proSlots);
+ writeMemberDecs(ol,this,0,0,"Static Protected Members",0,&proStaticMembers);
+ if (extractPrivateFlag)
+ {
+ writeMemberDecs(ol,this,0,0,"Private Members",0,&priMembers);
+ writeMemberDecs(ol,this,0,0,"Private Slots",0,&priSlots);
+ writeMemberDecs(ol,this,0,0,"Static Private Members",0,&priStaticMembers);
+ }
+ writeMemberDecs(ol,this,0,0,"Friends",0,&friends);
+ writeMemberDecs(ol,this,0,0,
+ theTranslator->trRelatedFunctions(),
+ theTranslator->trRelatedSubscript(),
+ &related
+ );
+
+ // write detailed description
+ bool exampleFlag=hasExamples();
+ if (!briefDescription().isEmpty() || !documentation().isEmpty() || exampleFlag)
+ {
+ ol.writeRuler();
+ ol.writeAnchor("details");
+ ol.startGroupHeader();
+ parseDoc(ol,0,0,theTranslator->trDetailedDescription());
+ ol.endGroupHeader();
+ if (tempArgs) // class is a template
+ {
+ ol.startSubsubsection();
+ ArgumentList *al=tempArgs;
+ ol.docify("template<");
+ Argument *a=al->first();
+ while (a)
+ {
+ ol.docify(a->type);
+ ol.docify(a->name);
+ if (a->defval.length()!=0)
+ {
+ ol.docify(" = ");
+ ol.docify(a->defval);
+ }
+ a=al->next();
+ if (a) ol.docify(", ");
+ }
+ ol.docify("> "+pageType.lower()+" "+name());
+ ol.endSubsubsection();
+ ol.writeString("\n");
+ }
+
+ // repeat brief description
+ if (!briefDescription().isEmpty())
+ {
+ ol+=briefOutput;
+ ol.newParagraph();
+ }
+ // write documentation
+ if (!documentation().isEmpty())
+ {
+ parseDoc(ol,name(),0,documentation()+"\n");
+ }
+ // write examples
+ if (exampleFlag)
+ {
+ ol.startDescList();
+ ol.startBold();
+ parseDoc(ol,0,0,theTranslator->trExamples()+": ");
+ ol.endBold();
+ ol.endDescTitle();
+ ol.writeDescItem();
+ writeExample(ol);
+ //ol.endDescItem();
+ ol.endDescList();
+ }
+ }
+
+ pubMembers.countDocMembers();
+ proMembers.countDocMembers();
+ priMembers.countDocMembers();
+ pubStaticMembers.countDocMembers();
+ proStaticMembers.countDocMembers();
+ priStaticMembers.countDocMembers();
+ pubSlots.countDocMembers();
+ proSlots.countDocMembers();
+ priSlots.countDocMembers();
+ related.countDocMembers();
+ friends.countDocMembers();
+ signals.countDocMembers();
+
+ if ( pubMembers.typedefCount() + proMembers.typedefCount() +
+ (extractPrivateFlag ? priMembers.typedefCount() : 0 )
+ )
+ {
+ ol.writeRuler();
+ ol.startGroupHeader();
+ parseDoc(ol,0,0,theTranslator->trMemberTypedefDocumentation());
+ ol.endGroupHeader();
+
+ writeMemberDocs(ol,&pubMembers,name(),MemberDef::Typedef);
+ writeMemberDocs(ol,&proMembers,name(),MemberDef::Typedef);
+ if (extractPrivateFlag)
+ {
+ writeMemberDocs(ol,&priMembers,name(),MemberDef::Typedef);
+ }
+ }
+
+ if (pubMembers.enumCount() +
+ proMembers.enumCount() +
+ ( extractPrivateFlag ? priMembers.enumCount() : 0 )
+ )
+ {
+ ol.writeRuler();
+ ol.startGroupHeader();
+ parseDoc(ol,0,0,theTranslator->trMemberEnumerationDocumentation());
+ ol.endGroupHeader();
+
+ writeMemberDocs(ol,&pubMembers,name(),MemberDef::Enumeration);
+ writeMemberDocs(ol,&proMembers,name(),MemberDef::Enumeration);
+ if (extractPrivateFlag)
+ {
+ writeMemberDocs(ol,&priMembers,name(),MemberDef::Enumeration);
+ }
+ }
+
+ if (pubMembers.enumValueCount() +
+ proMembers.enumValueCount() +
+ ( extractPrivateFlag ? priMembers.enumValueCount() : 0 )
+ )
+ {
+ ol.writeRuler();
+ ol.startGroupHeader();
+ parseDoc(ol,0,0,theTranslator->trEnumerationValueDocumentation());
+ ol.endGroupHeader();
+
+ writeMemberDocs(ol,&pubMembers,name(),MemberDef::EnumValue);
+ writeMemberDocs(ol,&proMembers,name(),MemberDef::EnumValue);
+ if (extractPrivateFlag)
+ {
+ writeMemberDocs(ol,&priMembers,name(),MemberDef::EnumValue);
+ }
+ }
+
+ if ( pubMembers.funcCount() + pubSlots.funcCount() +
+ pubStaticMembers.funcCount() +
+ proMembers.funcCount() + proSlots.funcCount() +
+ proStaticMembers.funcCount() +
+ (extractPrivateFlag ?
+ priMembers.funcCount() + priSlots.funcCount() +
+ priStaticMembers.funcCount() : 0
+ )
+ )
+ {
+ ol.writeRuler();
+ ol.startGroupHeader();
+ parseDoc(ol,0,0,theTranslator->trMemberFunctionDocumentation());
+ ol.endGroupHeader();
+
+ writeMemberDocs(ol,&pubMembers,name(),MemberDef::Function);
+ writeMemberDocs(ol,&pubSlots,name(),MemberDef::Slot);
+ writeMemberDocs(ol,&signals,name(),MemberDef::Signal);
+ writeMemberDocs(ol,&pubStaticMembers,name(),MemberDef::Function);
+ writeMemberDocs(ol,&proMembers,name(),MemberDef::Function);
+ writeMemberDocs(ol,&proSlots,name(),MemberDef::Slot);
+ writeMemberDocs(ol,&proStaticMembers,name(),MemberDef::Function);
+ if (extractPrivateFlag)
+ {
+ writeMemberDocs(ol,&priMembers,name(),MemberDef::Function);
+ writeMemberDocs(ol,&priSlots,name(),MemberDef::Slot);
+ writeMemberDocs(ol,&priStaticMembers,name(),MemberDef::Function);
+ }
+ }
+
+ if ( friends.count() + related.count() )
+ {
+ ol.writeRuler();
+ ol.startGroupHeader();
+ parseDoc(ol,0,0,theTranslator->trRelatedFunctionDocumentation());
+ ol.endGroupHeader();
+ writeMemberDocs(ol,&friends,name(),MemberDef::Friend);
+ writeMemberDocs(ol,&related,name(),MemberDef::Function);
+ }
+
+
+ if ( pubMembers.varCount() + pubStaticMembers.varCount() +
+ proMembers.varCount() + proStaticMembers.varCount() +
+ (extractPrivateFlag ?
+ priMembers.varCount() + priStaticMembers.varCount() : 0
+ )
+ )
+ {
+ ol.writeRuler();
+ ol.startGroupHeader();
+ parseDoc(ol,0,0,theTranslator->trMemberDataDocumentation());
+ ol.endGroupHeader();
+
+ writeMemberDocs(ol,&pubMembers,name(),MemberDef::Variable);
+ writeMemberDocs(ol,&pubStaticMembers,name(),MemberDef::Variable);
+ writeMemberDocs(ol,&proMembers,name(),MemberDef::Variable);
+ writeMemberDocs(ol,&proStaticMembers,name(),MemberDef::Variable);
+ if (extractPrivateFlag)
+ {
+ writeMemberDocs(ol,&priMembers,name(),MemberDef::Variable);
+ writeMemberDocs(ol,&priStaticMembers,name(),MemberDef::Variable);
+ }
+ }
+
+ // write the list of used files (Html and LaTeX only)
+ ol.disable(OutputGenerator::Man);
+ ol.writeRuler();
+ parseDoc(ol,0,0,
+ theTranslator->trGeneratedFrom(pageType.lower(),
+ files.count()==1));
+ ol.startItemList();
+
+ const char *file = files.first();
+ while (file)
+ {
+ QFileInfo fi(file);
+ ol.writeListItem();
+ FileDef *fd;
+ bool ambig;
+ if ((fd=findFileDef(&inputNameDict,fi.absFilePath(),ambig))
+ && fd->hasDocumentation())
+ {
+ ol.writeObjectLink(fd->getReference(),fd->diskName(),0,
+ fi.fileName());
+ }
+ else
+ {
+ ol.docify(fi.fileName());
+ }
+ file=files.next();
+ }
+
+ ol.endItemList();
+ ol.enable(OutputGenerator::Man);
+
+ // write Author section (Man only)
+ ol.disableAllBut(OutputGenerator::Man);
+ ol.writeString("\n");
+ ol.startGroupHeader();
+ parseDoc(ol,0,0,theTranslator->trAuthor());
+ ol.endGroupHeader();
+ parseDoc(ol,0,0,theTranslator->trGeneratedAutomatically(projectName));
+ ol.enableAll();
+
+ endFile(ol);
+}
+
+// write the list of all (inherited) members for this class
+void ClassDef::writeMemberList(OutputList &ol)
+{
+ if (allMemberNameInfoList->count()==0) return;
+ // do not generate Latex output
+ ol.disableAllBut(OutputGenerator::Html);
+ startFile(ol,memListFileName,theTranslator->trMemberList());
+ startTitle(ol);
+ parseDoc(ol,name(),0,name()+" "+theTranslator->trMemberList());
+ endTitle(ol,0);
+ parseDoc(ol,0,0,theTranslator->trThisIsTheListOfAllMembers());
+ ol.writeString(" ");
+ ol.writeObjectLink(reference,fileName,0,name());
+ ol.writeString(", ");
+ parseDoc(ol,0,0,theTranslator->trIncludingInheritedMembers());
+
+ ol.startItemList();
+
+ MemberNameInfo *mni=allMemberNameInfoList->first();
+ while (mni)
+ {
+ MemberInfo *mi=mni->first();
+ while (mi)
+ {
+ MemberDef *md=mi->memberDef;
+ ClassDef *cd=md->memberClass();
+
+ // compute the protection level for this member
+ Protection protect=md->protection();
+ if (mi->prot==Protected) // inherited protection
+ {
+ if (protect==Public) protect=Protected;
+ else if (protect==Protected) protect=Private;
+ }
+
+ //printf("Member %s of class %s mi->prot=%d prot=%d\n",
+ // md->name().data(),cd->name().data(),mi->prot,protect);
+
+ Specifier virt=md->virtualness();
+ MemberDef *rmd=md->reimplements();
+ while (rmd && virt==Normal)
+ {
+ virt = rmd->virtualness()==Normal ? Normal : Virtual;
+ rmd = rmd->reimplements();
+ }
+
+ if (cd && !md->name().isEmpty() && md->name()[0]!='@' &&
+ (
+ md->isFriend() ||
+ (mi->prot!=Private && (protect!=Private || extractPrivateFlag))
+ )
+ )
+ {
+ bool memberWritten=FALSE;
+ if (cd->isVisible() && (md->hasDocumentation() || md->isReference()))
+ // create a link to the documentation
+ {
+ QString name=mi->ambiguityResolutionScope+md->name();
+ ol.writeListItem();
+ ol.writeObjectLink(cd->getReference(),cd->classFile(),
+ md->anchor(),name);
+ if ( md->isFunction() || md->isSignal() || md->isSlot() )
+ ol.docify(md->argsString());
+ else if (md->isEnumerate())
+ parseDoc(ol,0,0," "+theTranslator->trEnumName());
+ else if (md->isEnumValue())
+ parseDoc(ol,0,0," "+theTranslator->trEnumValue());
+ else if (md->isTypedef())
+ ol.docify(" typedef");
+ else if (md->isFriend() && !strcmp(md->typeString(),"friend class"))
+ ol.docify(" class");
+ ol.writeString("\n");
+ memberWritten=TRUE;
+ }
+ else if (!hideMemberFlag) // no documentation,
+ // generate link to the class instead.
+ {
+ ol.writeListItem();
+ ol.writeBoldString(md->name());
+ if ( md->isFunction() || md->isSignal() || md->isSlot() )
+ ol.docify(md->argsString());
+ else if (md->isEnumerate())
+ parseDoc(ol,0,0," "+theTranslator->trEnumName());
+ else if (md->isEnumValue())
+ parseDoc(ol,0,0," "+theTranslator->trEnumValue());
+ else if (md->isTypedef())
+ ol.docify(" typedef");
+ ol.writeString(" (");
+ parseDoc(ol,0,0,theTranslator->trDefinedIn()+" ");
+ if (cd->isVisible())
+ {
+ ol.writeObjectLink(cd->getReference(),cd->classFile(),0,cd->name());
+ }
+ else
+ {
+ ol.writeBoldString(cd->name());
+ }
+ ol.writeString(")");
+ memberWritten=TRUE;
+ }
+ if ((protect!=Public || md->isStatic() || virt!=Normal ||
+ md->isFriend() || md->isRelated()
+ )
+ && memberWritten)
+ {
+ ol.startTypewriter();
+ ol.docify(" [");
+ QStrList sl;
+ if (md->isFriend()) sl.append("friend");
+ else if (md->isRelated()) sl.append("related");
+ else
+ {
+ if (protect==Protected) sl.append("protected");
+ else if (protect==Private) sl.append("private");
+ if (virt==Virtual) sl.append("virtual");
+ else if (virt==Pure) sl.append("pure virtual");
+ if (md->isStatic()) sl.append("static");
+ if (md->isSignal()) sl.append("signal");
+ if (md->isSlot()) sl.append("slot");
+ }
+ const char *s=sl.first();
+ while (s)
+ {
+ ol.docify(s);
+ s=sl.next();
+ if (s) ol.docify(", ");
+ }
+ ol.docify("]");
+ ol.endTypewriter();
+ }
+ }
+ mi=mni->next();
+ }
+ mni=allMemberNameInfoList->next();
+ }
+ ol.endItemList();
+ endFile(ol);
+ ol.enableAll();
+}
+
+void ClassDef::writeIncludeFile(OutputList &ol)
+{
+ if (!incFile) return;
+ //printf("incFile=%s\n",incFile->absFilePath().data());
+ ol.disableAllBut(OutputGenerator::Html);
+ startFile(ol,fileName+"-include",name()+" Include File");
+ startTitle(ol);
+ QString n=incName.copy();
+ if (incName.isNull()) n=incFile->name();
+ parseDoc(ol,0,0,n);
+ endTitle(ol,0);
+ parseDoc(ol,0,0,theTranslator->trVerbatimText(incFile->name()));
+ ol.writeRuler();
+ ol.startCodeFragment();
+ parseCode(ol,n,fileToString(incFile->absFilePath()),FALSE,0);
+ ol.endCodeFragment();
+ endFile(ol);
+ ol.enableAll();
+}
+
+// add a reference to an example
+bool ClassDef::addExample(const char *anchor,const char *nameStr,
+ const char *file)
+{
+ if (exampleDict && !exampleDict->find(nameStr))
+ {
+ Example *e=new Example;
+ e->anchor=anchor;
+ e->name=nameStr;
+ e->file=file;
+ exampleDict->insert(nameStr,e);
+ exampleList->inSort(e);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+// returns TRUE if this class is used in an example
+bool ClassDef::hasExamples()
+{
+ if (exampleList==0)
+ return FALSE;
+ else
+ return exampleList->count()>0;
+}
+
+// write the list of all examples that are use this class.
+void ClassDef::writeExample(OutputList &ol)
+{
+ Example *e=exampleList->first();
+ while (e)
+ {
+ ol.writeObjectLink(0,e->file,e->anchor,e->name);
+ e=exampleList->next();
+ if (e)
+ {
+ if (exampleList->at()==(int)exampleList->count()-1)
+ parseDoc(ol,0,0," "+theTranslator->trAnd()+" ");
+ else
+ ol.writeString(", ");
+ }
+ }
+ ol.writeString(".");
+}
+
+void ClassDef::setTemplateArguments(ArgumentList *al)
+{
+ if (al==0) return;
+ if (!tempArgs) delete tempArgs; // delete old list if needed
+ tempArgs=new ArgumentList;
+ tempArgs->setAutoDelete(TRUE);
+ ArgumentListIterator ali(*al);
+ Argument *a;
+ for (;(a=ali.current());++ali)
+ {
+ tempArgs->append(new Argument(*a));
+ }
+}
+
+QString ClassDef::getTemplateNameString()
+{
+ QString result;
+ if (!tempArgs || tempArgs->count()==0) return result;
+ result="<";
+ Argument *a=tempArgs->first();
+ while (a)
+ {
+ if (a->name.length()>0) // add template argument name
+ {
+ result+=a->name;
+ }
+ else // extract name from type
+ {
+ int i=a->type.length()-1;
+ while (i>=0 && isId(a->type.at(i))) i--;
+ if (i>0)
+ {
+ result+=a->type.right(a->type.length()-i-1);
+ }
+ }
+ a=tempArgs->next();
+ if (a) result+=", ";
+ }
+ result+=">";
+ return result;
+}
+
+bool ClassDef::hasNonReferenceSuperClass()
+{
+ bool found=!isReference();
+ BaseClassListIterator bcli(*inheritedBy);
+ for ( ; bcli.current() && !found ; ++bcli )
+ found=found || bcli.current()->classDef->hasNonReferenceSuperClass();
+ return found;
+}
diff --git a/src/classdef.h b/src/classdef.h
new file mode 100644
index 0000000..8fe0f21
--- /dev/null
+++ b/src/classdef.h
@@ -0,0 +1,169 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#ifndef CLASSDEF_H
+#define CLASSDEF_H
+
+#include <qstring.h>
+#include <qfileinf.h>
+#include <qlist.h>
+#include <qdict.h>
+#include <qtstream.h>
+#include <qstrlist.h>
+
+#include "membername.h"
+#include "memberlist.h"
+#include "memberdef.h"
+#include "example.h"
+#include "entry.h"
+#include "definition.h"
+
+typedef QDict<MemberDef> MemberDict;
+class ClassList;
+class OutputList;
+class FileDef;
+class BaseClassList;
+class MemberInfoList;
+class MemberInfoDict;
+class NamespaceDef;
+
+class ClassDef : public Definition
+{
+ public:
+
+ enum CompoundType { Class=Entry::CLASS_SEC,
+ Struct=Entry::STRUCT_SEC,
+ Union=Entry::UNION_SEC
+ };
+
+ ClassDef(const char *name,int ct,const char *ref=0,const char *fName=0);
+ ~ClassDef();
+ QString classFile() const { return fileName; }
+ int compoundType() const { return compType; }
+ const char *memberListFileName() const { return memListFileName; }
+ void insertBaseClass(ClassDef *,Protection p,Specifier s,const char *t=0);
+ BaseClassList *baseClasses() { return inherits; }
+ void insertSuperClass(ClassDef *,Protection p,Specifier s,const char *t=0);
+ BaseClassList *superClasses() { return inheritedBy; }
+ void setIncludeFile(FileDef *fd) { incFile=fd; }
+ FileDef *includeFile() const { return incFile; }
+ void setIncludeName(const char *n_) { incName=n_; }
+ MemberNameInfoList *memberNameInfoList() { return allMemberNameInfoList; }
+ MemberNameInfoDict *memberNameInfoDict() { return allMemberNameInfoDict; }
+ bool isReference() { return !reference.isNull(); }
+ const char *getReference() const { return reference; }
+ void insertMember(const MemberDef *);
+ void insertUsedFile(const char *);
+ void computeAnchors();
+ void setAnchor(MemberDef *);
+ void dumpMembers();
+ void writeDocumentation(OutputList &ol);
+ void writeMemberList(OutputList &ol);
+ void writeIncludeFile(OutputList &ol);
+ bool addExample(const char *anchor,const char *name, const char *file);
+ bool hasExamples();
+ void writeExample(OutputList &ol);
+ void setProtection(Protection p) { prot=p; }
+ Protection protection() const { return prot; }
+ bool isVisible()
+ { return !name().isEmpty() && name().at(0)!='@' &&
+ (prot!=Private || extractPrivateFlag) &&
+ hasDocumentation();
+ }
+ bool hasNonReferenceSuperClass();
+ bool isVisibleExt()
+ { return (allExtFlag || hasNonReferenceSuperClass()) &&
+ !name().isEmpty() && name().at(0)!='@' &&
+ (prot!=Private || extractPrivateFlag) &&
+ (hasDocumentation() || !hideClassFlag || !reference.isNull());
+ }
+
+ // template argument functions
+ ArgumentList *templateArguments() const { return tempArgs; }
+ void setTemplateArguments(ArgumentList *al);
+ QString getTemplateNameString();
+ void setNamespace(NamespaceDef *nd) { nspace = nd; }
+ NamespaceDef *getNamespace() { return nspace; }
+
+ bool visited;
+
+ private:
+ //QString name; // name of the class
+ QString fileName; // HTML containing the class docs
+ //QString doc; // general class documentation
+ FileDef *incFile; // header file to refer to
+ QString incName; // alternative include file name
+ //QString brief; // brief class discription
+ QString memListFileName;
+ BaseClassList *inherits;
+ BaseClassList *inheritedBy;
+ NamespaceDef *nspace; // the namespace this class is in
+ MemberList pubMembers;
+ MemberList proMembers;
+ MemberList priMembers;
+ MemberList pubStaticMembers;
+ MemberList proStaticMembers;
+ MemberList priStaticMembers;
+ MemberList pubSlots;
+ MemberList proSlots;
+ MemberList priSlots;
+ MemberList related;
+ MemberList signals;
+ MemberList friends;
+ MemberNameInfoList *allMemberNameInfoList;
+ MemberNameInfoDict *allMemberNameInfoDict;
+ ArgumentList *tempArgs;
+ QStrList files;
+ QString reference;
+ ExampleList *exampleList;
+ ExampleDict *exampleDict;
+ int compType;
+ Protection prot;
+};
+
+
+struct BaseClassDef
+{
+ BaseClassDef(ClassDef *cd,Protection p,Specifier v,const char *t) :
+ classDef(cd), prot(p), virt(v), templSpecifiers(t) {}
+ ClassDef *classDef;
+ Protection prot;
+ Specifier virt;
+ QString templSpecifiers;
+};
+
+class BaseClassList : public QList<BaseClassDef>
+{
+ public:
+ int compareItems(GCI item1,GCI item2)
+ {
+ ClassDef *c1=((BaseClassDef *)item1)->classDef;
+ ClassDef *c2=((BaseClassDef *)item2)->classDef;
+ if (c1==0 || c2==0)
+ return FALSE;
+ else
+ return strcmp(c1->name(),c2->name());
+ }
+};
+
+class BaseClassListIterator : public QListIterator<BaseClassDef>
+{
+ public:
+ BaseClassListIterator(const BaseClassList &bcl) :
+ QListIterator<BaseClassDef>(bcl) {}
+};
+
+#endif
diff --git a/src/classlist.cpp b/src/classlist.cpp
new file mode 100644
index 0000000..518f757
--- /dev/null
+++ b/src/classlist.cpp
@@ -0,0 +1,37 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#include "classlist.h"
+
+ClassList::ClassList() : QList<ClassDef>()
+{
+}
+
+ClassList::~ClassList()
+{
+}
+
+int ClassList::compareItems(GCI item1, GCI item2)
+{
+ ClassDef *c1=(ClassDef *)item1;
+ ClassDef *c2=(ClassDef *)item2;
+ return strcmp(c1->name(),c2->name());
+}
+
+ClassListIterator::ClassListIterator(const ClassList &cllist) :
+ QListIterator<ClassDef>(cllist)
+{
+}
diff --git a/src/classlist.h b/src/classlist.h
new file mode 100644
index 0000000..28d8454
--- /dev/null
+++ b/src/classlist.h
@@ -0,0 +1,37 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#ifndef CLASSLIST_H
+#define CLASSLIST_H
+
+#include "classdef.h"
+
+class ClassList : public QList<ClassDef>
+{
+ public:
+ ClassList();
+ ~ClassList();
+
+ int compareItems(GCI item1,GCI item2);
+};
+
+class ClassListIterator : public QListIterator<ClassDef>
+{
+ public:
+ ClassListIterator(const ClassList &list);
+};
+
+#endif
diff --git a/src/code.h b/src/code.h
new file mode 100644
index 0000000..4b781fb
--- /dev/null
+++ b/src/code.h
@@ -0,0 +1,28 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#ifndef CODE_H
+#define CODE_H
+
+#include <stdio.h>
+#include <qstring.h>
+
+class OutputList;
+
+extern void parseCode(OutputList &,const char *,const QString &,
+ bool ,const char *);
+extern void initParseCodeContext();
+#endif
diff --git a/src/code.l b/src/code.l
new file mode 100644
index 0000000..8bff410
--- /dev/null
+++ b/src/code.l
@@ -0,0 +1,747 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+%{
+
+/*
+ * includes
+ */
+#include <stdio.h>
+#include <iostream.h>
+#include <assert.h>
+#include <ctype.h>
+
+#include <qstring.h>
+
+#include "scanner.h"
+#include "entry.h"
+#include "doxygen.h"
+#include "message.h"
+#include "outputlist.h"
+#include "util.h"
+
+#define YY_NO_UNPUT
+#define YY_NEVER_INTERACTIVE 1
+
+class CodeClassDef
+{
+ public:
+ CodeClassDef() {}
+ CodeClassDef(const CodeClassDef &d)
+ {
+ name = d.name;
+ bases = d.bases;
+ }
+ ~CodeClassDef() {}
+
+ QString name;
+ QStrList bases;
+};
+
+class CodeVarDef
+{
+ public:
+ CodeVarDef() {}
+ CodeVarDef(const CodeVarDef &d)
+ {
+ name = d.name;
+ type = d.type;
+ classScope = d.classScope;
+ }
+ ~CodeVarDef() {}
+
+ QString name;
+ QString type;
+ QString classScope;
+};
+
+typedef QList<CodeClassDef> CodeClassList;
+typedef QDict<CodeClassDef> CodeClassDict;
+typedef QList<CodeVarDef> CodeVarList;
+
+static CodeClassList codeClassList;
+static CodeClassDict codeClassDict(17);
+static CodeVarList codeVarList;
+static CodeVarList codeParmList;
+
+/* -----------------------------------------------------------------
+ *
+ * statics
+ */
+
+static const char * inputString;
+static int inputPosition;
+static int lastCContext;
+static int lastDContext;
+static int lastStringContext;
+static int bracketCount = 0;
+static int curlyCount = 0;
+static int sharpCount = 0;
+static int yyLineNr = 0;
+static QString type;
+static QString name;
+static QString args;
+static QString parmType;
+static QString parmName;
+static bool inClass;
+static QString classScope;
+static OutputList *code;
+static CodeClassDef ccd;
+static CodeVarDef cvd;
+static bool exampleBlock;
+static QString exampleName;
+static QString exampleFile;
+static int anchorCount;
+
+static void addType()
+{
+ if (name=="const") { name.resize(0); return; }
+ if (type.length()) type += ' ' ;
+ type += name ;
+ name.resize(0) ;
+ if (type.length()) type += ' ' ;
+ type += args ;
+ args.resize(0) ;
+}
+
+static void addParmType()
+{
+ if (parmName=="const") { parmName.resize(0); return; }
+ if (parmType.length()) parmType += ' ' ;
+ parmType += parmName ;
+ parmName.resize(0) ;
+}
+
+static void setClassScope(const QString &name)
+{
+ QString n=name;
+ n=n.simplifyWhiteSpace();
+ int index;
+ if ((index=n.find("::"))!=-1)
+ classScope=n.left(index);
+ else
+ classScope.resize(0);
+ //printf("--->New class scope `%s'\n",classScope.data());
+}
+
+static void addVariable()
+{
+ cvd.name=name.copy().simplifyWhiteSpace();
+ cvd.type=type.copy().simplifyWhiteSpace();
+ if (type.length()==0)
+ return;
+ else if ((getClass(cvd.type)) || (codeClassDict[cvd.type]))
+ {
+ cvd.classScope=classScope;
+ codeVarList.append(new CodeVarDef(cvd)); // add it to a list
+ }
+}
+
+static void addParameter()
+{
+ cvd.name=parmName.copy().simplifyWhiteSpace();
+ cvd.type=parmType.copy().simplifyWhiteSpace();
+ if (cvd.type.length()==0)
+ return;
+ else if ((getClass(cvd.type)) || (codeClassDict[cvd.type]))
+ {
+ cvd.classScope=classScope;
+ codeParmList.append(new CodeVarDef(cvd)); // add it to a list
+ }
+}
+
+static void generateClassLink(OutputList &ol,const char *clName)
+{
+ QString className=clName;
+ if (className.length()==0) return;
+ ClassDef *cd;
+ if ((cd=getClass(className)) && cd->isVisible())
+ {
+ if (exampleBlock)
+ {
+ QString anchor;
+ anchor.sprintf("a%d",anchorCount);
+ //printf("addExampleClass(%s,%s,%s)\n",anchor.data(),exampleName.data(),
+ // exampleFile.data());
+ if (cd->addExample(anchor,exampleName,exampleFile))
+ {
+ ol.writeAnchor(anchor);
+ anchorCount++;
+ }
+ }
+ ol.writeCodeLink(cd->getReference(),cd->classFile(),0,className);
+ }
+ else
+ {
+ ol.codify(clName);
+ }
+}
+
+static bool getLink(const char *className,
+ const char *memberName,OutputList &result)
+{
+ MemberDef *md;
+ ClassDef *cd;
+ FileDef *fd;
+ QString m=memberName;
+ QString c=className;
+ //printf("Trying `%s'::`%s'\n",c.data(),m.data());
+ if (getDefs(m,c,"()",md,cd,fd) &&
+ (md->hasDocumentation() || md->isReference()))
+ {
+ //printf("Found!\n");
+ if (exampleBlock)
+ {
+ QString anchor;
+ anchor.sprintf("a%d",anchorCount);
+ //printf("addExampleFile(%s,%s,%s)\n",anchor.data(),exampleName.data(),
+ // exampleFile.data());
+ if (md->addExample(anchor,exampleName,exampleFile))
+ {
+ result.writeAnchor(anchor);
+ anchorCount++;
+ }
+ }
+ if (cd)
+ {
+ result.writeCodeLink(cd->getReference(),cd->classFile(),
+ md->anchor(),memberName);
+ return TRUE;
+ }
+ else if (fd)
+ {
+ result.writeCodeLink(fd->getReference(),fd->diskName(),
+ md->anchor(),memberName);
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+static void generateMemberLink(OutputList &ol,const char *varName,
+ const char *memName)
+{
+ //printf("generateMemberLink(object=%s,mem=%s) classScope=%s\n",
+ // varName,memName,classScope.data());
+ CodeVarDef *cvd=codeParmList.last();
+ while (cvd && cvd->name!=varName) cvd=codeParmList.prev();
+ if (!cvd)
+ {
+ cvd=codeVarList.last();
+ while (cvd && cvd->name!=varName) cvd=codeVarList.prev();
+ }
+ if (cvd) // variable found
+ {
+ CodeClassDef *ccd=codeClassDict[cvd->type];
+ if (ccd)
+ {
+ char *s=ccd->bases.first();
+ while (s)
+ {
+ OutputList result(&ol);
+ if (getLink(s,memName,result))
+ {
+ ol+=result;
+ return;
+ }
+ s=ccd->bases.next();
+ }
+ }
+ else
+ {
+ OutputList result(&ol);
+ if (getLink(cvd->type,memName,result))
+ {
+ ol+=result;
+ }
+ else
+ {
+ ol.codify(memName);
+ }
+ return;
+ }
+ }
+ ol.codify(memName);
+ return;
+}
+
+static void generateFunctionLink(OutputList &ol,const char *funcName)
+{
+ //printf("generateFunctionLink(%s) classScope=%s\n",funcName,classScope.data());
+ OutputList result(&ol);
+ CodeClassDef *ccd=0;
+ if (classScope.length()>0 && (ccd=codeClassDict[classScope]))
+ {
+ //printf("using classScope %s\n",classScope.data());
+ char *s=ccd->bases.first();
+ while (s)
+ {
+ if (getLink(s,funcName,result))
+ {
+ ol+=result;
+ return;
+ }
+ s=ccd->bases.next();
+ }
+ }
+ if (getLink(classScope,funcName,result))
+ {
+ ol+=result;
+ }
+ else
+ {
+ ol.codify(funcName);
+ }
+ return;
+}
+
+/* -----------------------------------------------------------------
+ */
+#undef YY_INPUT
+#define YY_INPUT(buf,result,max_size) result=yyread(buf,max_size);
+
+static int yyread(char *buf,int max_size)
+{
+ int c=0;
+ while( c < max_size && inputString[inputPosition] )
+ {
+ *buf = inputString[inputPosition++] ;
+ c++; buf++;
+ }
+ return c;
+}
+
+%}
+
+ID [a-z_A-Z][a-z_A-Z0-9]*
+
+%x SkipString
+%x SkipCPP
+%x SkipComment
+%x SkipSpecialComment
+%x SkipCxxComment
+%x SkipSpecialCxxComment
+%x Body
+%x FuncCall
+%x MemberCall
+%x MemberCall2
+%x SkipInits
+%x ClassName
+%x Bases
+%x SkipSharp
+%x ReadInclude
+
+%%
+
+<*>\x0d
+<Body>^([ \t]*"#include"[ \t]*)("<"|"\"") {
+ code->codify(yytext);
+ BEGIN( ReadInclude );
+ }
+<Body>("class"|"struct"|"union")[ \t\n]+ {
+ code->codify(yytext);
+ BEGIN( ClassName );
+ }
+<ReadInclude>[a-z_A-Z0-9.]+(("/"[a-z_A-Z0-9.]+)*)/(">"|"\"") {
+ //FileInfo *f;
+ bool ambig;
+ FileDef *fd;
+ if ((fd=findFileDef(&inputNameDict,yytext,ambig)) &&
+ fd->hasDocumentation())
+ {
+ code->writeCodeLink(0,fd->diskName(),0,yytext);
+ }
+ else
+ {
+ code->codify(yytext);
+ }
+ char c=yyinput();
+ QString text;
+ text+=c;
+ code->codify(text);
+ BEGIN( Body );
+ }
+<Body>^[ \t]*"#" {
+ code->codify(yytext);
+ BEGIN( SkipCPP ) ;
+ }
+<SkipCPP>. {
+ code->codify(yytext);
+ }
+<SkipCPP>\\\n {
+ code->codify(yytext);
+ yyLineNr++ ;
+ }
+<SkipCPP>\n {
+ yyLineNr++ ;
+ code->codify(yytext);
+ BEGIN( Body ) ;
+ }
+<SkipCPP>"//" {
+ code->codify(yytext);
+ }
+<Body>"{" {
+ code->codify(yytext);
+ curlyCount++;
+ type.resize(0); name.resize(0);
+ }
+<Body>"}" {
+ code->codify(yytext);
+ inClass=FALSE;
+ if (--curlyCount<=0)
+ {
+ classScope.resize(0);
+ codeParmList.clear();
+ }
+ }
+<ClassName>";" {
+ code->codify(yytext);
+ BEGIN( Body );
+ }
+<ClassName>[*&]+ {
+ addType();
+ code->codify(yytext);
+ }
+<ClassName>{ID} {
+ ccd.name=yytext;
+ addType();
+ generateClassLink(*code,yytext);
+ }
+<ClassName>[ \t\n]*":"[ \t\n]* {
+ code->codify(yytext);
+ BEGIN( Bases );
+ }
+<Bases,ClassName>[ \t]*"{"[ \t]* {
+ code->codify(yytext);
+ curlyCount++;
+ inClass=TRUE;
+ if (ccd.name.length()>0)
+ {
+ classScope=ccd.name.copy();
+ CodeClassDef *cd=new CodeClassDef(ccd);
+ codeClassList.append(cd);
+ codeClassDict.insert(cd->name,cd);
+ }
+ BEGIN( Body );
+ }
+<Bases>"virtual" {
+ code->codify(yytext);
+ }
+<Bases>"public" {
+ code->codify(yytext);
+ }
+<Bases>"protected" {
+ code->codify(yytext);
+ }
+<Bases>"private" {
+ code->codify(yytext);
+ }
+<Bases>{ID} {
+ //printf("%s:addBase(%s)\n",ccd.name.data(),yytext);
+ ccd.bases.inSort(yytext);
+ generateClassLink(*code,yytext);
+ }
+<Bases>"<" {
+ code->codify(yytext);
+ sharpCount=1;
+ BEGIN ( SkipSharp );
+ }
+<SkipSharp>"<" {
+ code->codify(yytext);
+ ++sharpCount;
+ }
+<SkipSharp>">" {
+ code->codify(yytext);
+ if (--sharpCount<=0)
+ BEGIN ( Bases );
+ }
+<Bases>"," {
+ code->codify(yytext);
+ }
+
+
+<Body>("asm"|"auto"|"break"|"case"|"catch"|"continue"|"default"|"delete"|"do"|"else"|"for"|"goto"|"if"|"new"|"return"|"switch"|"this"|"throw"|"try"|"typedef"|"while")([ \t\n]*)/"(" {
+ code->codify(yytext);
+ name.resize(0);type.resize(0);
+ }
+<Body>("asm"|"auto"|"break"|"case"|"catch"|"continue"|"default"|"delete"|"do"|"else"|"for"|"goto"|"if"|"new"|"return"|"switch"|"this"|"throw"|"try"|"typedef"|"while")([ \t\n]*) {
+ code->codify(yytext);
+ name.resize(0);type.resize(0);
+ }
+<Body>([a-z_A-Z~][a-z_A-Z0-9]*)/([ \t]*) {
+ generateClassLink(*code,yytext);
+ addType();
+ name+=yytext;
+ }
+<Body>[a-z_A-Z~]([a-z_A-Z0-9]*[ \t\n]*"::")+[ \t\n]*[~a-z_A-Z][a-z_A-Z0-9]*[ \t\n]* {
+ code->codify(yytext);
+ addType();
+ name+=yytext;
+ }
+<Body>([a-z_A-Z~][a-z_A-Z0-9:]*)/([ \t]*"(") {
+ addType();
+ if (type.length()==0)
+ generateFunctionLink(*code,yytext);
+ else
+ code->codify(yytext);
+ bracketCount=1;
+ args.resize(0);
+ name+=yytext;
+ BEGIN( FuncCall );
+ }
+<FuncCall,Body,MemberCall>\" {
+ code->codify(yytext);
+ lastStringContext=YY_START;
+ BEGIN( SkipString );
+ }
+<SkipString>[^\"\\]* {
+ code->codify(yytext);
+ }
+<SkipString>\" {
+ code->codify(yytext);
+ BEGIN( lastStringContext );
+ }
+<SkipString>\\\" {
+ code->codify(yytext);
+ }
+<Body>":" {
+ code->codify(yytext);
+ name.resize(0);type.resize(0);
+ }
+<Body>"'"."'" {
+ code->codify(yytext);
+ }
+<Body>"."|"->" {
+ code->codify(yytext);
+ BEGIN( MemberCall );
+ }
+<MemberCall>([a-z_A-Z~][a-z_A-Z0-9]*)/([ \t\n]*"(") {
+ if (name.length()>0)
+ generateMemberLink(*code,name,yytext);
+ else
+ code->codify(yytext);
+ name.resize(0);type.resize(0);
+ bracketCount=0;
+ BEGIN(FuncCall);
+ }
+<MemberCall>[^a-z_A-Z0-9(] {
+ code->codify(yytext);
+ type.resize(0);
+ name.resize(0);
+ BEGIN(Body);
+ }
+<Body>[,=;\[] {
+ code->codify(yytext);
+ if (type.length()>0)
+ addVariable();
+ name.resize(0);
+ if (*yytext!=',') type.resize(0);
+ args.resize(0);
+ }
+<Body>[0-9]+ {
+ code->codify(yytext);
+ }
+<MemberCall2,FuncCall>[a-z_A-Z][:a-z_A-Z0-9]* {
+ addParmType();
+ parmName=yytext;
+ generateClassLink(*code,yytext);
+ }
+<MemberCall2,FuncCall>, {
+ code->codify(yytext);
+ addParameter();
+ parmType.resize(0);parmName.resize(0);
+ }
+<MemberCall2,FuncCall>"(" {
+ code->codify(yytext);
+ bracketCount++;
+ }
+<MemberCall2,FuncCall>")" {
+ code->codify(yytext);
+ if (--bracketCount<=0)
+ name.resize(0);args.resize(0);
+ parmType.resize(0);parmName.resize(0);
+ BEGIN( Body );
+ }
+<MemberCall2,FuncCall>")"[ \t\n]*";" {
+ code->codify(yytext);
+ bracketCount=0;
+ if (!inClass && type.length()>0)
+ addVariable();
+ name.resize(0);type.resize(0);
+ parmType.resize(0);parmName.resize(0);
+ BEGIN( Body );
+ }
+<MemberCall2,FuncCall>")"[ \t\n]*"{" {
+ addParameter();
+ parmType.resize(0);parmName.resize(0);
+ if (name.length()>0) setClassScope(name);
+ code->codify(yytext);
+ curlyCount++;
+ type.resize(0); name.resize(0);
+ BEGIN( Body );
+ }
+<MemberCall2,FuncCall>")"[ \t\n]*":" {
+ addParameter();
+ parmType.resize(0);parmName.resize(0);
+ if (name.length()>0) setClassScope(name);
+ code->codify(yytext);
+ type.resize(0); name.resize(0);
+ BEGIN( SkipInits );
+ }
+<SkipInits>"{" {
+ code->codify(yytext);
+ curlyCount++;
+ BEGIN( Body );
+ }
+<SkipInits>{ID} {
+ generateClassLink(*code,yytext);
+ }
+<FuncCall>([a-z_A-Z][a-z_A-Z0-9]*)/"(" {
+ generateFunctionLink(*code,yytext);
+ }
+<FuncCall>([a-z_A-Z][a-z_A-Z0-9]*)/("."|"->") {
+ code->codify(yytext);
+ args=yytext;
+ BEGIN( MemberCall2 );
+ }
+<MemberCall2>([a-z_A-Z][a-z_A-Z0-9]*)/([ \t\n]*"(") {
+ if (args.length()>0)
+ generateMemberLink(*code,args,yytext);
+ else
+ code->codify(yytext);
+ args.resize(0);
+ BEGIN( FuncCall );
+ }
+<MemberCall2>([a-z_A-Z][a-z_A-Z0-9]*)/([ \t\n]*("."|"->")) {
+ code->codify(yytext);
+ args=yytext;
+ }
+<SkipComment>"//" {
+ code->codify(yytext);
+ }
+<SkipComment>[ \t]*"*/" {
+ code->codify(yytext);
+ BEGIN( lastCContext ) ;
+ }
+<SkipCxxComment>.*\n {
+ code->codify(yytext);
+ yyLineNr++ ;
+ BEGIN( lastCContext ) ;
+ }
+<SkipSpecialComment>"//"
+ /*!
+<SkipSpecialComment>[ \t]*"* /"[ \t]* /"\n" {
+ BEGIN( lastDContext ) ;
+ }
+ */
+<SkipSpecialComment>[ \t]*"*/" {
+ BEGIN( lastDContext ) ;
+ }
+<SkipSpecialComment>[ \t]*"*/"[ \t\n]*"\n"/"/*" {
+ //code->codify("\n");
+ QString lineText=yytext;
+ yyLineNr+=lineText.contains('\n');
+ BEGIN( lastDContext ) ;
+ }
+<SkipSpecialComment>.
+<SkipSpecialComment>\n { yyLineNr++; }
+<SkipSpecialCxxComment>.*/\n {
+ yyLineNr++ ;
+ BEGIN( lastDContext ) ;
+ }
+<SkipSpecialCxxComment>.
+<SkipSpecialCxxComment>\n { yyLineNr++; }
+<*>[ \t]*"/*!"|"/**" {
+ lastDContext = YY_START ;
+ BEGIN( SkipSpecialComment );
+ }
+<*>"/*" {
+ code->codify(yytext);
+ lastCContext = YY_START ;
+ BEGIN( SkipComment ) ;
+ }
+<*>[ \t]*"//!" {
+ lastDContext = YY_START ;
+ BEGIN( SkipSpecialCxxComment );
+ }
+<*>"//" {
+ code->codify(yytext);
+ lastCContext = YY_START ;
+ BEGIN( SkipCxxComment ) ;
+ }
+<*>. {
+ code->codify(yytext);
+ }
+<*>\n {
+ code->codify(yytext);
+ }
+<*>([ \t\n]*"\n"){2,} { // combine multiple blank lines
+ QString sepLine=yytext;
+ code->codify("\n\n");
+ yyLineNr+=sepLine.contains('\n');
+ }
+
+%%
+
+/*@ ----------------------------------------------------------------------------
+ */
+
+void initParseCodeContext()
+{
+ codeClassList.setAutoDelete(TRUE);
+ codeVarList.setAutoDelete(TRUE);
+ codeParmList.setAutoDelete(TRUE);
+ codeClassDict.clear();
+ codeClassList.clear();
+ codeVarList.clear();
+ codeParmList.clear();
+ ccd.bases.clear();
+ anchorCount = 0;
+}
+
+void parseCode(OutputList &ol,const char *className,const QString &s,
+ bool e, const char *exName)
+{
+ code = new OutputList(&ol);
+ if (s.length()==0) return;
+ inputString = s;
+ inputPosition = 0;
+ yyLineNr = 0;
+ curlyCount = 0;
+ bracketCount = 0;
+ sharpCount = 0;
+ classScope = className;
+ exampleBlock = e;
+ exampleName = exName;
+ exampleFile = convertSlashes(exampleName,TRUE)+"-example";
+ type.resize(0);
+ name.resize(0);
+ args.resize(0);
+ parmName.resize(0);
+ parmType.resize(0);
+ codeYYrestart( codeYYin );
+ BEGIN( Body );
+ codeYYlex();
+ ol+=*code;
+ delete code;
+ return;
+}
+
+extern "C" { // some bogus code to keep the compiler happy
+ int codeYYwrap() { return 1 ; }
+ void codeYYdummy() { yy_flex_realloc(0,0); }
+}
diff --git a/src/config.h b/src/config.h
new file mode 100644
index 0000000..6269e85
--- /dev/null
+++ b/src/config.h
@@ -0,0 +1,80 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#ifndef CONFIG_H
+#define CONFIG_H
+
+#include <qstring.h>
+#include <qstrlist.h>
+#include <qfile.h>
+
+extern void parseConfig(const QString &config);
+extern void writeTemplateConfig(QFile *f,bool shortList);
+
+extern QString projectName; // the name of the project
+extern QString projectNumber; // the number of the project
+extern QString htmlOutputDir; // the directory to put the HTML files
+extern QString latexOutputDir; // the directory to put the Latex files
+extern QString manOutputDir; // the directory to put the man pages
+extern QString headerFile; // the name of the personal HTML header
+extern QString footerFile; // the name of the personal HTML footer
+extern QString cgiName; // the name of the CGI binary
+extern QString cgiURL; // the absolute URL to the CGI binary
+extern QString docURL; // the absolute URL to the documentation
+extern QString binAbsPath; // the absolute path to the doxysearch
+extern QString docAbsPath; // the absolute path to the documentation
+extern QString perlPath; // the absolute path to perl
+extern QString genTagFile; // the tag file to generate
+extern QString inputFilter; // a filter command that is applied to input files
+extern QString paperType; // the page type to generate docs for
+extern QString stripFromPath; // the string to strip from the file path
+extern QStrList includePath; // list of include paths
+extern QStrList examplePath; // list of example paths
+extern QStrList inputSources; // list of input files
+extern QStrList excludeSources; // list of files to exclude from the input
+extern QStrList filePatternList; // list of file patterns
+extern QStrList excludePatternList; // list of patterns to exclude from input
+extern QStrList tagFileList; // list of tag files
+extern QStrList extDocPathList; // list of external doc. directories.
+extern QStrList predefined; // list of predefined macro names.
+extern QStrList extraPackageList; // list of extra LaTeX packages.
+extern bool quietFlag; // generate progress messages flag
+extern bool warningFlag; // generate warnings flag
+extern bool recursiveFlag; // scan directories recursively
+extern bool allExtFlag; // include all external classes flag
+extern bool searchEngineFlag; // generate search engine flag
+extern bool extractAllFlag; // gererate docs for all classes flag
+extern bool extractPrivateFlag; // generate docs for private members flag
+extern bool noIndexFlag; // generate condensed index flag
+extern bool generateHtml; // generate HTML output
+extern bool generateLatex; // generate Latex output
+extern bool generateMan; // generate Man pages
+extern bool preprocessingFlag; // enable preprocessing
+extern bool briefMemDescFlag; // enable `inline' brief member descr.
+extern bool hideMemberFlag; // hide undocumented members.
+extern bool hideClassFlag; // hide undocumented members.
+extern bool searchIncludeFlag; // search for included files
+extern bool macroExpansionFlag; // expand macros in the source.
+extern bool onlyPredefinedFlag; // expand only predefined macros
+extern bool fullPathNameFlag; // using full path name in output
+extern bool classDiagramFlag; // enable the generation of class diagrams.
+extern bool compactLatexFlag; // generate compact LaTeX documentation.
+extern bool repeatBriefFlag; // repeat brief descriptions.
+extern bool internalDocsFlag; // determines what happens to internal docs.
+extern bool caseSensitiveNames; // determines if output can be mixed case.
+extern bool verbatimHeaderFlag; // enable/disable generation of verb headers.
+
+#endif
diff --git a/src/config.l b/src/config.l
new file mode 100644
index 0000000..232f531
--- /dev/null
+++ b/src/config.l
@@ -0,0 +1,1112 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+%{
+
+/*
+ * includes
+ */
+#include <stdio.h>
+#include <iostream.h>
+#include <assert.h>
+#include <ctype.h>
+
+#include <qstring.h>
+#include <qfileinf.h>
+#include <qdir.h>
+#include <qtstream.h>
+
+#include "doxygen.h"
+#include "config.h"
+#include "message.h"
+#include "pre.h"
+#include "version.h"
+#include "language.h"
+
+#define YY_NEVER_INTERACTIVE 1
+
+/* -----------------------------------------------------------------
+ *
+ * exported variables
+ */
+
+QString projectName;
+QString projectNumber;
+QString outputDir;
+QString htmlOutputDir;
+QString latexOutputDir;
+QString manOutputDir;
+QString headerFile;
+QString footerFile;
+QString cgiName;
+QString cgiURL;
+QString docURL;
+QString binAbsPath;
+QString docAbsPath;
+QString perlPath;
+QString genTagFile;
+QString inputFilter;
+QString paperType;
+QString outputLanguage;
+QString stripFromPath;
+QStrList includePath;
+QStrList examplePath;
+QStrList inputSources;
+QStrList excludeSources;
+QStrList filePatternList;
+QStrList excludePatternList;
+QStrList tagFileList;
+QStrList extDocPathList;
+QStrList predefined;
+QStrList extraPackageList;
+bool quietFlag = FALSE;
+bool warningFlag = FALSE;
+bool recursiveFlag = FALSE;
+bool allExtFlag = FALSE;
+bool searchEngineFlag = FALSE;
+bool extractAllFlag = FALSE;
+bool extractPrivateFlag = FALSE;
+bool noIndexFlag = FALSE;
+bool hideMemberFlag = FALSE;
+bool hideClassFlag = FALSE;
+bool macroExpansionFlag = FALSE;
+bool onlyPredefinedFlag = FALSE;
+bool fullPathNameFlag = FALSE;
+bool compactLatexFlag = FALSE;
+bool internalDocsFlag = FALSE;
+bool caseSensitiveNames = FALSE;
+bool generateHtml = TRUE;
+bool generateLatex = TRUE;
+bool generateMan = TRUE;
+bool preprocessingFlag = TRUE;
+bool briefMemDescFlag = TRUE;
+bool searchIncludeFlag = TRUE;
+bool classDiagramFlag = TRUE;
+bool repeatBriefFlag = TRUE;
+bool verbatimHeaderFlag = TRUE;
+
+/* -----------------------------------------------------------------
+ *
+ * static variables
+ */
+
+static const char * inputString;
+static int inputPosition;
+static int yyLineNr;
+static QString tmpString;
+static QString * s=0;
+static bool * b=0;
+static QStrList * l=0;
+static int lastState;
+static int lastEnvState;
+static QString elemStr;
+
+/* -----------------------------------------------------------------
+ */
+#undef YY_INPUT
+#define YY_INPUT(buf,result,max_size) result=yyread(buf,max_size);
+
+static int yyread(char *buf,int max_size)
+{
+ int c=0;
+ while( c < max_size && inputString[inputPosition] )
+ {
+ *buf = inputString[inputPosition++] ;
+ c++; buf++;
+ }
+ return c;
+}
+
+%}
+
+%x Start
+%x SkipComment
+%x GetString
+%x GetBool
+%x GetStrList
+%x GetQuotedString
+%x GetEnvVar
+
+%%
+
+<*>\0x0d
+<Start,GetString,GetStrList,GetBool>"#" { BEGIN(SkipComment); }
+<Start>"PROJECT_NAME"[ \t]*"=" { BEGIN(GetString); s=&projectName; }
+<Start>"PROJECT_NUMBER"[ \t]*"=" { BEGIN(GetString); s=&projectNumber; }
+<Start>"OUTPUT_DIRECTORY"[ \t]*"=" { BEGIN(GetString); s=&outputDir; }
+<Start>"HTML_OUTPUT"[ \t]*"=" { BEGIN(GetString); s=&htmlOutputDir; }
+<Start>"MAN_OUTPUT"[ \t]*"=" { BEGIN(GetString); s=&manOutputDir; }
+<Start>"LATEX_OUTPUT"[ \t]*"=" { BEGIN(GetString); s=&latexOutputDir; }
+<Start>"HTML_HEADER"[ \t]*"=" { BEGIN(GetString); s=&headerFile; }
+<Start>"HTML_FOOTER"[ \t]*"=" { BEGIN(GetString); s=&footerFile; }
+<Start>"CGI_NAME"[ \t]*"=" { BEGIN(GetString); s=&cgiName; }
+<Start>"CGI_URL"[ \t]*"=" { BEGIN(GetString); s=&cgiURL; }
+<Start>"DOC_URL"[ \t]*"=" { BEGIN(GetString); s=&docURL; }
+<Start>"BIN_ABSPATH"[ \t]*"=" { BEGIN(GetString); s=&binAbsPath; }
+<Start>"DOC_ABSPATH"[ \t]*"=" { BEGIN(GetString); s=&docAbsPath; }
+<Start>"PERL_PATH"[ \t]*"=" { BEGIN(GetString); s=&perlPath; }
+<Start>"GENERATE_TAGFILE"[ \t]*"=" { BEGIN(GetString); s=&genTagFile; }
+<Start>"INPUT_FILTER"[ \t]*"=" { BEGIN(GetString); s=&inputFilter; }
+<Start>"PAPER_TYPE"[ \t]*"=" { BEGIN(GetString); s=&paperType; }
+<Start>"OUTPUT_LANGUAGE"[ \t]*"=" { BEGIN(GetString); s=&outputLanguage; }
+<Start>"STRIP_FROM_PATH"[ \t]*"=" { BEGIN(GetString); s=&stripFromPath; }
+<Start>"INCLUDE_PATH"[ \t]*"=" { BEGIN(GetStrList); l=&includePath; elemStr=""; }
+<Start>"EXAMPLE_PATH"[ \t]*"=" { BEGIN(GetStrList); l=&examplePath; elemStr=""; }
+<Start>"INPUT"[ \t]*"=" { BEGIN(GetStrList); l=&inputSources; elemStr=""; }
+<Start>"EXCLUDE"[ \t]*"=" { BEGIN(GetStrList); l=&excludeSources; elemStr=""; }
+<Start>"FILE_PATTERNS"[ \t]*"=" { BEGIN(GetStrList); l=&filePatternList; elemStr=""; }
+<Start>"EXCLUDE_PATTERNS"[ \t]*"=" { BEGIN(GetStrList); l=&excludePatternList; elemStr=""; }
+<Start>"TAGFILES"[ \t]*"=" { BEGIN(GetStrList); l=&tagFileList; elemStr=""; }
+<Start>"EXT_DOC_PATHS"[ \t]*"=" { BEGIN(GetStrList); l=&extDocPathList; elemStr=""; }
+<Start>"PREDEFINED"[ \t]*"=" { BEGIN(GetStrList); l=&predefined; elemStr=""; }
+<Start>"EXTRA_PACKAGES"[ \t]*"=" { BEGIN(GetStrList); l=&extraPackageList; elemStr=""; }
+<Start>"QUIET"[ \t]*"=" { BEGIN(GetBool); b=&quietFlag; }
+<Start>"WARNINGS"[ \t]*"=" { BEGIN(GetBool); b=&warningFlag; }
+<Start>"RECURSIVE"[ \t]*"=" { BEGIN(GetBool); b=&recursiveFlag; }
+<Start>"ALLEXTERNALS"[ \t]*"=" { BEGIN(GetBool); b=&allExtFlag; }
+<Start>"SEARCHENGINE"[ \t]*"=" { BEGIN(GetBool); b=&searchEngineFlag; }
+<Start>"EXTRACT_ALL"[ \t]*"=" { BEGIN(GetBool); b=&extractAllFlag; }
+<Start>"EXTRACT_PRIVATE"[ \t]*"=" { BEGIN(GetBool); b=&extractPrivateFlag; }
+<Start>"DISABLE_INDEX"[ \t]*"=" { BEGIN(GetBool); b=&noIndexFlag; }
+<Start>"GENERATE_LATEX"[ \t]*"=" { BEGIN(GetBool); b=&generateLatex; }
+<Start>"GENERATE_HTML"[ \t]*"=" { BEGIN(GetBool); b=&generateHtml; }
+<Start>"GENERATE_MAN"[ \t]*"=" { BEGIN(GetBool); b=&generateMan; }
+<Start>"ENABLE_PREPROCESSING"[ \t]*"=" { BEGIN(GetBool); b=&preprocessingFlag; }
+<Start>"MACRO_EXPANSION"[ \t]*"=" { BEGIN(GetBool); b=&macroExpansionFlag; }
+<Start>"SEARCH_INCLUDES"[ \t]*"=" { BEGIN(GetBool); b=&searchIncludeFlag; }
+<Start>"BRIEF_MEMBER_DESC"[ \t]*"=" { BEGIN(GetBool); b=&briefMemDescFlag; }
+<Start>"HIDE_UNDOC_MEMBERS"[ \t]*"=" { BEGIN(GetBool); b=&hideMemberFlag; }
+<Start>"HIDE_UNDOC_CLASSES"[ \t]*"=" { BEGIN(GetBool); b=&hideClassFlag; }
+<Start>"EXPAND_ONLY_PREDEF"[ \t]*"=" { BEGIN(GetBool); b=&onlyPredefinedFlag; }
+<Start>"FULL_PATH_NAMES"[ \t]*"=" { BEGIN(GetBool); b=&fullPathNameFlag; }
+<Start>"CLASS_DIAGRAMS"[ \t]*"=" { BEGIN(GetBool); b=&classDiagramFlag; }
+<Start>"COMPACT_LATEX"[ \t]*"=" { BEGIN(GetBool); b=&compactLatexFlag; }
+<Start>"REPEAT_BRIEF"[ \t]*"=" { BEGIN(GetBool); b=&repeatBriefFlag; }
+<Start>"INTERNAL_DOCS"[ \t]*"=" { BEGIN(GetBool); b=&internalDocsFlag; }
+<Start>"CASE_SENSE_NAMES"[ \t]*"=" { BEGIN(GetBool); b=&caseSensitiveNames; }
+<Start>"VERBATIM_HEADERS"[ \t]*"=" { BEGIN(GetBool); b=&verbatimHeaderFlag; }
+<Start>[a-z_A-Z0-9]+ { err("Warning: ignoring unknown tag `%s' at line %d\n",yytext,yyLineNr); }
+<GetString,GetBool>\n { yyLineNr++; BEGIN(Start); }
+<GetStrList>\n {
+ yyLineNr++;
+ if (elemStr.length()>0)
+ {
+ //printf("elemStr1=`%s'\n",elemStr.data());
+ l->append(elemStr);
+ }
+ BEGIN(Start);
+ }
+<GetStrList>[ \t]+ {
+ if (elemStr.length()>0)
+ {
+ //printf("elemStr2=`%s'\n",elemStr.data());
+ l->append(elemStr);
+ }
+ elemStr.resize(0);
+ }
+<GetString>[^ \"\$\t\r\n]+ { (*s)+=yytext; }
+<GetString,GetStrList>"\"" { lastState=YY_START;
+ BEGIN(GetQuotedString);
+ tmpString.resize(0);
+ }
+<GetString,GetStrList,GetQuotedString>"\$\(" {
+ //printf(">> Enter env\n");
+ lastEnvState=YY_START;
+ BEGIN(GetEnvVar);
+ }
+<GetEnvVar>[a-z_A-Z0-9]+")" {
+ yytext[yyleng-1]='\0';
+ const char *env=getenv(yytext);
+ int i;
+ int l=strlen(env);
+ //printf("env name=`%s' text=`%s'\n",yytext,env);
+ for (i=l-1;i>=0;i--) unput(env[i]);
+ BEGIN(lastEnvState);
+ }
+<GetQuotedString>"\""|"\n" {
+ //printf("Quoted String = `%s'\n",tmpString.data());
+ if (lastState==GetString)
+ (*s)+=tmpString;
+ else
+ elemStr+=tmpString;
+ if (*yytext=='\n')
+ {
+ err("Warning: Missing end quote (\") on line %d\n",yyLineNr);
+ yyLineNr++;
+ }
+ BEGIN(lastState);
+ }
+<GetQuotedString>"\\\"" {
+ tmpString+='"';
+ }
+<GetQuotedString>. { tmpString+=*yytext; }
+<GetBool>[a-zA-Z]+ {
+ QString bs=yytext;
+ bs=bs.upper();
+ if (bs=="YES")
+ *b=TRUE;
+ else if (bs=="NO")
+ *b=FALSE;
+ else
+ {
+ *b=FALSE;
+ warn("Warning: Invalid value `%s' for "
+ "boolean tag in line %d; use YES or NO\n",
+ bs.data(),yyLineNr);
+ }
+ }
+ /*
+<GetStrList>[a-z_A-Z.*:?~0-9/\\\-]+ {
+ elemStr+=yytext;
+ }
+ */
+<GetStrList>[^ \#\"\$\t\r\n]+ {
+ elemStr+=yytext;
+ }
+<SkipComment>\n { yyLineNr++; BEGIN(Start); }
+<SkipComment>\\[ \r\t]*\n { yyLineNr++; BEGIN(Start); }
+<*>\\[ \r\t]*\n { yyLineNr++; }
+<*>.
+<*>\n { yyLineNr++ ; }
+
+%%
+
+/*@ ----------------------------------------------------------------------------
+ */
+
+
+void dumpConfig()
+{
+ printf("projectName=`%s'\n",projectName.data());
+ printf("outputDir=`%s'\n", outputDir.data());
+ printf("headerFile=`%s'\n", headerFile.data());
+ printf("footerFile=`%s'\n", footerFile.data());
+ char *ip=includePath.first();
+ while (ip)
+ {
+ printf("includePath=`%s'\n",ip);
+ ip=includePath.next();
+ }
+ printf("quiet=`%d'\n", quietFlag);
+ printf("warnings=`%d'\n", warningFlag);
+ char *is=inputSources.first();
+ while (is)
+ {
+ printf("inputSources=`%s'\n",is);
+ is=inputSources.next();
+ }
+ char *fp=filePatternList.first();
+ while (fp)
+ {
+ printf("filePattern=`%s'\n",fp);
+ fp=filePatternList.next();
+ }
+ printf("recusive=`%d'\n",recursiveFlag);
+ printf("inputFilter=`%s'\n",inputFilter.data());
+ char *tf=tagFileList.first();
+ while (tf)
+ {
+ printf("tagFile=`%s'\n",tf);
+ tf=tagFileList.next();
+ }
+ printf("allExternals=`%d'\n",allExtFlag);
+ printf("searchEngine=`%d'\n",searchEngineFlag);
+ printf("cgiName=`%s'\n",cgiName.data());
+ printf("cgiURL=`%s'\n",cgiURL.data());
+ printf("docURL=`%s'\n",docURL.data());
+ printf("binAbsPath=`%s'\n",binAbsPath.data());
+ char *ed=extDocPathList.first();
+ while (ed)
+ {
+ printf("binAbsPathFile=`%s'\n",ed);
+ ed=extDocPathList.next();
+ }
+}
+
+void writeTemplateConfig(QFile *f,bool sl)
+{
+ QTextStream t(f);
+ t << "# Doxyfile " << versionString << endl;
+ if (!sl)
+ {
+ t << "# This file describes the settings to be used by doxygen for a project\n";
+ t << "#\n";
+ t << "# All text after a hash (#) is considered a comment and will be ignored\n";
+ t << "# The format is:\n";
+ t << "# TAG = value [value, ...]\n";
+ t << "# Values that contain spaces should be placed between quotes (\" \")\n";
+ t << "\n";
+ t << "#---------------------------------------------------------------------------\n";
+ t << "# General configuration options\n";
+ t << "#---------------------------------------------------------------------------\n";
+ t << "\n";
+ t << "# The PROJECT_NAME tag is a single word (or a sequence of word surrounded\n";
+ t << "# by quotes) that should identify the project. \n";
+ t << "\n";
+ }
+ t << "PROJECT_NAME =\n";
+ if (!sl)
+ {
+ t << "\n";
+ t << "# The PROJECT_NUMBER tag can be used to enter a project or revision number.\n" ;
+ t << "# This could be handy for archiving the generated documentation or \n";
+ t << "# if some version control system is used.\n";
+ t << "\n";
+ }
+ t << "PROJECT_NUMBER =\n";
+ if (!sl)
+ {
+ t << "\n";
+ t << "# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) \n";
+ t << "# base path where the generated documentation will be put. \n";
+ t << "# If a relative path is entered, it will be relative to the location \n";
+ t << "# where doxygen was started. If left blank the current directory will be used.\n";
+ t << "\n";
+ }
+ t << "OUTPUT_DIRECTORY =\n";
+ if (!sl)
+ {
+ t << "\n";
+ t << "# The OUTPUT_LANGUAGE tag is used to specify the language in which all\n";
+ t << "# documentation generated by doxygen is written. Doxygen will use this\n";
+ t << "# information to generate all constant output in the proper language.\n";
+ t << "# The default language is English, other supported languages are: Dutch\n";
+ t << "\n";
+ }
+ t << "OUTPUT_LANGUAGE = English\n";
+ if (!sl)
+ {
+ t << "\n";
+ t << "# The QUIET tag can be used to turn on/off the messages that are generated\n";
+ t << "# by doxygen. Possible values are YES and NO. If left blank NO is used.\n";
+ t << "\n";
+ }
+ t << "QUIET = NO\n";
+ if (!sl)
+ {
+ t << "\n";
+ t << "# The WARNINGS tag can be used to turn on/off the warning messages that are\n";
+ t << "# generated by doxygen. Possible values are YES and NO. If left blank\n";
+ t << "# NO is used.\n";
+ t << "\n";
+ }
+ t << "WARNINGS = YES\n";
+ if (!sl)
+ {
+ t << "\n";
+ t << "# The DISABLE_INDEX tag can be used to turn on/off the condensed index at\n";
+ t << "# top of each HTML page. The value NO (the default) enables the index and\n";
+ t << "# the value YES disables it.\n";
+ t << "\n";
+ }
+ t << "DISABLE_INDEX = NO\n";
+ if (!sl)
+ {
+ t << "\n";
+ t << "# If the EXTRACT_ALL tag is set to YES all classes and functions will be\n";
+ t << "# included in the documentation, even if no documentation was available.\n";
+ t << "\n";
+ }
+ t << "EXTRACT_ALL = NO\n";
+ if (!sl)
+ {
+ t << "\n";
+ t << "# If the EXTRACT_PRIVATE tag is set to YES all private members of a class\n";
+ t << "# will be included in the documentation.\n";
+ t << "\n";
+ }
+ t << "EXTRACT_PRIVATE = NO\n";
+ if (!sl)
+ {
+ t << "\n";
+ t << "# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all\n";
+ t << "# undocumented members inside documented classes or files.\n";
+ t << "\n";
+ }
+ t << "HIDE_UNDOC_MEMBERS = NO\n";
+ if (!sl)
+ {
+ t << "\n";
+ t << "# If the HIDE_UNDOC_CLASSESS tag is set to YES, Doxygen will hide all\n";
+ t << "# undocumented classes.\n";
+ t << "\n";
+ }
+ t << "HIDE_UNDOC_CLASSES = NO\n";
+ if (!sl)
+ {
+ t << "\n";
+ t << "# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will\n";
+ t << "# include brief member descriptions after the members that are listed in \n";
+ t << "# the file and class documentation (similar to JavaDoc).\n";
+ t << "# Set to NO to disable this.\n";
+ t << "\n";
+ }
+ t << "BRIEF_MEMBER_DESC = YES\n";
+ if (!sl)
+ {
+ t << "\n";
+ t << "# The INTERNAL_DOCS tag determines if documentation\n";
+ t << "# that is typed after a \\internal command is included. If the tag is set \n";
+ t << "# to NO (the default) then the documentation will be excluded.\n";
+ t << "# Set it to YES to include the internal documentation.\n";
+ t << "\n";
+ }
+ t << "INTERNAL_DOCS = NO\n";
+ if (!sl)
+ {
+ t << "\n";
+ t << "# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend\n";
+ t << "# the brief description of a member or function before the detailed description.\n";
+ t << "# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the \n";
+ t << "# brief descriptions will be completely suppressed.\n";
+ t << "\n";
+ }
+ t << "REPEAT_BRIEF = YES\n";
+ if (!sl)
+ {
+ t << "\n";
+ t << "# If the FULL_PATH_NAMES tag is set to YES Doxygen will prepend the full\n";
+ t << "# path before files name in the file list and in the header files. If set\n" ;
+ t << "# to NO the shortest path that makes the file name unique will be used.\n";
+ t << "\n";
+ }
+ t << "FULL_PATH_NAMES = NO\n";
+ if (!sl)
+ {
+ t << "\n";
+ t << "# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag\n";
+ t << "# can be used to strip a user defined part of the path. Stripping is\n" ;
+ t << "# only done if the specified string matches the left-hand part of the path.\n";
+ t << "\n";
+ }
+ t << "STRIP_FROM_PATH =\n";
+ if (!sl)
+ {
+ t << "\n";
+ t << "# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will\n";
+ t << "# generate a class diagram (in Html and LaTeX) for classes with base or\n";
+ t << "# super classes. Setting the tag to NO turns the diagrams off.\n";
+ t << "\n";
+ }
+ t << "CLASS_DIAGRAMS = YES\n";
+ if (!sl)
+ {
+ t << "\n";
+ t << "# If the CASE_SENSE_NAMES tag is set to NO (the default) then Doxygen\n";
+ t << "# will only generate file names in lower case letters. If set to\n";
+ t << "# YES upper case letters are also allowed. This is useful if you have\n";
+ t << "# classes or files whose names only differ in case and if your file system\n";
+ t << "# supports case sensitive file names.\n";
+ t << "\n";
+ }
+ t << "CASE_SENSE_NAMES = NO\n";
+ if (!sl)
+ {
+ t << "\n";
+ t << "# If the VERBATIM_HEADERS tag is set the YES (the default) then Doxygen\n";
+ t << "# will generate a verbatim copy of the header file for each class for\n";
+ t << "# which an include is specified. Set to NO to disable this.\n";
+ t << "\n";
+ }
+ t << "VERBATIM_HEADERS = YES\n";
+ if (!sl)
+ {
+ t << "\n";
+ t << "#---------------------------------------------------------------------------\n";
+ t << "# configuration options related to the input files\n";
+ t << "#---------------------------------------------------------------------------\n";
+ t << "\n";
+ t << "# The INPUT tag can be used to specify the files and/or directories that contain \n";
+ t << "# documented source files. You may enter file names like \"myfile.cpp\" or \n";
+ t << "# directories like \"/usr/src/myproject\". Separate the files or directories \n";
+ t << "# with spaces.\n";
+ t << "\n";
+ }
+ t << "INPUT =\n";
+ if (!sl)
+ {
+ t << "\n";
+ t << "# If the value of the INPUT tag contains directories, you can use the \n";
+ t << "# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp \n";
+ t << "# and *.h) to filter out the source-files in the directories. If left \n";
+ t << "# blank all files are included.\n";
+ t << "\n";
+ }
+ t << "FILE_PATTERNS =\n";
+ if (!sl)
+ {
+ t << "\n";
+ t << "# The RECURSIVE tag can be used to turn specify whether or not subdirectories\n";
+ t << "# should be searched for input files as well. Possible values are YES and NO.\n";
+ t << "# If left blank NO is used.\n";
+ t << "\n";
+ }
+ t << "RECURSIVE = NO\n";
+ if (!sl)
+ {
+ t << "\n";
+ t << "# The EXCLUDE tag can be used to specify files and/or directories that should\n";
+ t << "# excluded from the INPUT source files. This way you can easily exclude a \n";
+ t << "# subdirectory from a directory tree whose root is specified with the INPUT tag.\n";
+ t << "\n";
+ }
+ t << "EXCLUDE =\n";
+ if (!sl)
+ {
+ t << "\n";
+ t << "# If the value of the INPUT tag contains directories, you can use the\n";
+ t << "# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude\n";
+ t << "# certain files from those directories.\n";
+ t << "\n";
+ }
+ t << "EXCLUDE_PATTERNS =\n";
+ if (!sl)
+ {
+ t << "\n";
+ t << "# The EXAMPLE_PATH tag can be used to specify one or more files or \n";
+ t << "# directories that contain example code fragments that are included (see \n";
+ t << "# the \\include command).\n";
+ t << "\n";
+ }
+ t << "EXAMPLE_PATH =\n";
+ if (!sl)
+ {
+ t << "\n";
+ t << "# The INPUT_FILTER tag can be used to specify a program that doxygen should\n";
+ t << "# invoke to filter for each input file. Doxygen will invoke the filter program \n";
+ t << "# by executing (via popen()) the command <filter> <input-file>, where <filter>\n";
+ t << "# is the value of the INPUT_FILTER tag, and <input-file> is the name of an\n";
+ t << "# input file. Doxygen will then use the output that the filter program writes\n";
+ t << "# to standard output.\n";
+ t << "\n";
+ }
+ t << "INPUT_FILTER =\n";
+ if (!sl)
+ {
+ t << "\n";
+ t << "#---------------------------------------------------------------------------\n";
+ t << "# configuration options related to the HTML output\n";
+ t << "#---------------------------------------------------------------------------\n";
+ t << "\n";
+ t << "# If the GENERATE_HTML tag is set to YES (the default) Doxygen will\n";
+ t << "# generate HTML output\n";
+ t << "\n";
+ }
+ t << "GENERATE_HTML = YES\n";
+ if (!sl)
+ {
+ t << "\n";
+ t << "# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.\n";
+ t << "# If a relative path is entered the value of OUTPUT_DIRECTORY will be\n";
+ t << "# put in front of it. If left blank `html' will be used as the default path.\n";
+ t << "\n";
+ }
+ t << "HTML_OUTPUT =\n";
+ if (!sl)
+ {
+ t << "\n";
+ t << "# The HTML_HEADER tag can be used to specify a personal HTML header for \n";
+ t << "# each generated HTML page. If it is left blank doxygen will generate a \n";
+ t << "# standard header.\n";
+ t << "\n";
+ }
+ t << "HTML_HEADER =\n";
+ if (!sl)
+ {
+ t << "\n";
+ t << "# The HTML_FOOTER tag can be used to specify a personal HTML footer for \n";
+ t << "# each generated HTML page. If it is left blank doxygen will generate a \n";
+ t << "# standard footer.\n";
+ t << "\n";
+ }
+ t << "HTML_FOOTER =\n";
+ if (!sl)
+ {
+ t << "\n";
+ t << "#---------------------------------------------------------------------------\n";
+ t << "# configuration options related to the LaTeX output\n";
+ t << "#---------------------------------------------------------------------------\n";
+ t << "\n";
+ t << "# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will\n";
+ t << "# generate Latex output.\n";
+ t << "\n";
+ }
+ t << "GENERATE_LATEX = YES\n";
+ if (!sl)
+ {
+ t << "\n";
+ t << "# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.\n";
+ t << "# If a relative path is entered the value of OUTPUT_DIRECTORY will be\n";
+ t << "# put in front of it. If left blank `latex' will be used as the default path.\n";
+ t << "\n";
+ }
+ t << "LATEX_OUTPUT =\n";
+ if (!sl)
+ {
+ t << "\n";
+ t << "# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact\n";
+ t << "# LaTeX documents. This may be useful for small projects and may help to\n";
+ t << "# save some trees in general.\n";
+ t << "\n";
+ }
+ t << "COMPACT_LATEX = NO\n";
+ if (!sl)
+ {
+ t << "\n";
+ t << "# The PAPER_TYPE tag can be used to set the paper type that is used\n";
+ t << "# by the printer. Possible values are: a4, a4wide, letter, legal and \n";
+ t << "# executive. If left blank a4wide will be used.\n";
+ t << "\n";
+ }
+ t << "PAPER_TYPE = a4wide\n";
+ if (!sl)
+ {
+ t << "\n";
+ t << "# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX\n";
+ t << "# packages that should be included in the LaTeX output.\n";
+ t << "\n";
+ }
+ t << "EXTRA_PACKAGES =\n";
+ if (!sl)
+ {
+ t << "\n";
+ t << "#---------------------------------------------------------------------------\n";
+ t << "# configuration options related to the man page output\n";
+ t << "#---------------------------------------------------------------------------\n";
+ t << "\n";
+ t << "# If the GENERATE_MAN tag is set to YES (the default) Doxygen will\n";
+ t << "# generate man pages\n";
+ t << "\n";
+ }
+ t << "GENERATE_MAN = YES\n";
+ if (!sl)
+ {
+ t << "\n";
+ t << "# The MAN_OUTPUT tag is used to specify where the man pages will be put.\n";
+ t << "# If a relative path is entered the value of OUTPUT_DIRECTORY will be\n";
+ t << "# put in front of it. If left blank `man' will be used as the default path.\n";
+ t << "\n";
+ }
+ t << "MAN_OUTPUT =\n";
+ if (!sl)
+ {
+ t << "\n";
+ t << "#---------------------------------------------------------------------------\n";
+ t << "# Configuration options related to the preprocessor \n";
+ t << "#---------------------------------------------------------------------------\n";
+ t << "\n";
+ t << "# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will\n";
+ t << "# evaluate all C-preprocessor directives found in the sources and include\n";
+ t << "# files.\n";
+ t << "\n";
+ }
+ t << "ENABLE_PREPROCESSING = YES\n";
+ if (!sl)
+ {
+ t << "\n";
+ t << "# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro\n";
+ t << "# names in the source code. If set to NO (the default) only conditional \n";
+ t << "# compilation will be performed.\n";
+ t << "\n";
+ }
+ t << "MACRO_EXPANSION = NO\n";
+ if (!sl)
+ {
+ t << "\n";
+ t << "# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files\n";
+ t << "# in the INCLUDE_PATH (see below) will be search if a #include is found.\n";
+ t << "\n";
+ }
+ t << "SEARCH_INCLUDES = YES\n";
+ if (!sl)
+ {
+ t << "\n";
+ t << "# The INCLUDE_PATH tag can be used to specify one or more directories that\n";
+ t << "# contain include files that are not input files but should be processed by\n";
+ t << "# the preprocessor.\n" ;
+ t << "\n";
+ }
+ t << "INCLUDE_PATH =\n";
+ if (!sl)
+ {
+ t << "\n";
+ t << "# The PREDEFINED tag can be used to specify one or more macro names that\n";
+ t << "# are defined before the preprocessor is started (similar to the -D option of\n";
+ t << "# gcc). The argument of the tag is a list of macros of the form: name\n";
+ t << "# or name=definition (no spaces). If the definition and the = are \n";
+ t << "# omitted =1 is assumed.\n";
+ t << "\n";
+ }
+ t << "PREDEFINED =\n";
+ if (!sl)
+ {
+ t << "\n";
+ t << "# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES\n";
+ t << "# then the macro expansion is limited to the macros specified with the\n";
+ t << "# PREDEFINED tag.\n";
+ t << "\n";
+ }
+ t << "EXPAND_ONLY_PREDEF = NO\n";
+ if (!sl)
+ {
+ t << "\n";
+ t << "#---------------------------------------------------------------------------\n";
+ t << "# Configuration options related to external references \n";
+ t << "#---------------------------------------------------------------------------\n";
+ t << "\n";
+ t << "# The TAGFILES tag can be used to specify one or more tagfiles. \n";
+ t << "\n";
+ }
+ t << "TAGFILES =\n";
+ if (!sl)
+ {
+ t << "\n";
+ t << "# When a file name is specified after GENERATE_TAGFILE, doxygen will create\n";
+ t << "# a tag file that is based on the input files it reads.\n";
+ t << "\n";
+ }
+ t << "GENERATE_TAGFILE =\n";
+ if (!sl)
+ {
+ t << "\n";
+ t << "# If the ALLEXTERNALS tag is set to YES all external classes will be listed\n";
+ t << "# in the class index. If set to NO only the inherited external classes\n";
+ t << "# will be listed.\n";
+ t << "\n";
+ }
+ t << "ALLEXTERNALS = NO\n";
+ if (!sl)
+ {
+ t << "\n";
+ t << "# The PERL_PATH should be the absolute path and name of the perl script\n";
+ t << "# interpreter (i.e. the result of `which perl').\n";
+ t << "\n";
+ }
+ t << "PERL_PATH = /usr/local/bin/perl\n";
+ if (!sl)
+ {
+ t << "\n";
+ t << "#---------------------------------------------------------------------------\n";
+ t << "# Configuration options related to the search engine \n";
+ t << "#---------------------------------------------------------------------------\n";
+ t << "\n";
+ t << "# The SEARCHENGINE tag specifies whether or not a search engine should be \n";
+ t << "# used. If set to NO the values of all tags below this one will be ignored.\n";
+ t << "\n";
+ }
+ t << "SEARCHENGINE = NO\n";
+ if (!sl)
+ {
+ t << "\n";
+ t << "# The CGI_NAME tag should be the name of the CGI script that\n";
+ t << "# starts the search engine (doxysearch) with the correct parameters.\n";
+ t << "# A script with this name will be generated by doxygen.\n";
+ t << "\n";
+ }
+ t << "CGI_NAME = search.cgi\n";
+ if (!sl)
+ {
+ t << "\n";
+ t << "# The CGI_URL tag should be the absolute URL to the directory where the\n";
+ t << "# cgi binaries are located. See the documentation of your http daemon for \n";
+ t << "# details.\n";
+ t << "\n";
+ }
+ t << "CGI_URL =\n";
+ if (!sl)
+ {
+ t << "\n";
+ t << "# The DOC_URL tag should be the absolute URL to the directory where the\n";
+ t << "# documentation is located. If left blank the absolute path to the \n";
+ t << "# documentation, with file:// prepended to it, will be used.\n";
+ t << "\n";
+ }
+ t << "DOC_URL =\n";
+ if (!sl)
+ {
+ t << "\n";
+ t << "# The DOC_ABSPATH tag should be the absolute path to the directory where the\n";
+ t << "# documentation is located. If left blank the directory on the local machine\n";
+ t << "# will be used.\n";
+ t << "\n";
+ }
+ t << "DOC_ABSPATH =\n";
+ if (!sl)
+ {
+ t << "\n";
+ t << "# The BIN_ABSPATH tag must point to the directory where the doxysearch binary\n";
+ t << "# is installed.\n";
+ t << "\n";
+ }
+ t << "BIN_ABSPATH = /usr/local/bin/\n";
+ if (!sl)
+ {
+ t << "\n";
+ t << "# The EXT_DOC_PATHS tag can be used to specify one or more paths to \n";
+ t << "# documentation generated for other projects. This allows doxysearch to search\n";
+ t << "# the documentation for these projects as well.\n";
+ t << "\n";
+ }
+ t << "EXT_DOC_PATHS =\n";
+}
+
+void checkConfig()
+{
+ //if (projectName.length()>0)
+ //{
+ // projectName[0]=toupper(projectName[0]);
+ //}
+
+ paperType = paperType.lower().stripWhiteSpace();
+ if (paperType.isEmpty())
+ {
+ paperType = "a4wide";
+ }
+ if (paperType!="a4" && paperType!="a4wide" && paperType!="letter" &&
+ paperType!="legal" && paperType!="executive")
+ {
+ err("Error: Unknown page type specified");
+ }
+
+ outputLanguage=outputLanguage.stripWhiteSpace();
+ if (outputLanguage.isEmpty())
+ {
+ setTranslator("English");
+ }
+ else
+ {
+ if (!setTranslator(outputLanguage))
+ {
+ err("Error: Output language %s not supported! Using english instead.\n",
+ outputLanguage.data());
+ }
+ }
+
+ // Test to see if output directory is valid
+ if (outputDir.isEmpty())
+ outputDir=QDir::currentDirPath();
+ else
+ {
+ QDir dir(outputDir);
+ if (!dir.exists())
+ {
+ dir.setPath(QDir::currentDirPath());
+ if (!dir.mkdir(outputDir))
+ {
+ err("Error: tag OUTPUT_DIRECTORY: Output directory `%s' does not "
+ "exist and cannot be created\n",outputDir.data());
+ exit(1);
+ }
+ else if (!quietFlag)
+ {
+ err("Notice: Output directory `%s' does not exist. "
+ "I have created it for you.\n", outputDir.data());
+ }
+ dir.cd(outputDir);
+ }
+ outputDir=dir.absPath();
+ }
+
+ if (htmlOutputDir.isEmpty() && generateHtml)
+ {
+ htmlOutputDir=outputDir+"/html";
+ }
+ else if (htmlOutputDir && htmlOutputDir[0]!='/')
+ {
+ htmlOutputDir.prepend(outputDir+'/');
+ }
+ QDir htmlDir(htmlOutputDir);
+ if (!htmlDir.exists() && !htmlDir.mkdir(htmlOutputDir))
+ {
+ err("Could not create output directory %s\n",htmlOutputDir.data());
+ exit(1);
+ }
+
+ if (latexOutputDir.isEmpty() && generateLatex)
+ {
+ latexOutputDir=outputDir+"/latex";
+ }
+ else if (latexOutputDir && latexOutputDir[0]!='/')
+ {
+ latexOutputDir.prepend(outputDir+'/');
+ }
+ QDir latexDir(latexOutputDir);
+ if (!latexDir.exists() && !latexDir.mkdir(latexOutputDir))
+ {
+ err("Could not create output directory %s\n",latexOutputDir.data());
+ exit(1);
+ }
+
+ if (manOutputDir.isEmpty() && generateMan)
+ {
+ manOutputDir=outputDir+"/man";
+ }
+ else if (manOutputDir && manOutputDir[0]!='/')
+ {
+ manOutputDir.prepend(outputDir+'/');
+ }
+ QDir manDir(manOutputDir);
+ if (!manDir.exists() && !manDir.mkdir(manOutputDir))
+ {
+ err("Could not create output directory %s\n",manOutputDir.data());
+ exit(1);
+ }
+
+ // Test to see if HTML header is valid
+ if (headerFile.length()>0)
+ {
+ QFileInfo fi(headerFile);
+ if (!fi.exists())
+ {
+ err("Error: tag HTML_HEADER: header file `%s' "
+ "does not exist\n",headerFile.data());
+ exit(1);
+ }
+ }
+ // Test to see if HTML footer is valid
+ if (footerFile.length()>0)
+ {
+ QFileInfo fi(footerFile);
+ if (!fi.exists())
+ {
+ err("Error: tag HTML_FOOTER: footer file `%s' "
+ "does not exist\n",footerFile.data());
+ exit(1);
+ }
+ }
+ // check include path
+ char *s=includePath.first();
+ while (s)
+ {
+ QFileInfo fi(s);
+ if (!fi.exists()) err("Warning: tag INCLUDE_PATH: include path `%s' "
+ "does not exist\n",s);
+ addSearchDir(fi.absFilePath());
+ s=includePath.next();
+ }
+ // check input
+ if (inputSources.count()==0)
+ {
+ err("Error: tag INPUT: no input files specified after the INPUT tag.\n");
+ exit(1);
+ }
+ else
+ {
+ s=inputSources.first();
+ while (s)
+ {
+ QFileInfo fi(s);
+ if (!fi.exists())
+ {
+ err("Error: tag INPUT: input source `%s' does not exist\n",s);
+ exit(1);
+ }
+ s=inputSources.next();
+ }
+ }
+ // add default pattern if needed
+ if (filePatternList.count()==0)
+ {
+ filePatternList.append("*");
+ }
+
+ // more checks needed if and only if the search engine is enabled.
+ if (searchEngineFlag)
+ {
+ // check cgi name
+ if (cgiName.length()==0)
+ {
+ err("Error: tag CGI_NAME: no cgi script name after the CGI_NAME tag.\n");
+ exit(1);
+ }
+ // check cgi URL
+ if (cgiURL.length()==0)
+ {
+ err("Error: tag CGI_URL: no URL to cgi directory specified.\n");
+ exit(1);
+ }
+ else if (cgiURL.left(7)!="http://")
+ {
+ err("Error: tag CGI_URL: URL to cgi directory is invalid (must "
+ "start with http://).\n");
+ exit(1);
+ }
+ // check documentation URL
+ if (docURL.length()==0)
+ {
+ docURL = outputDir.copy().prepend("file://").append("html");
+ }
+ else if (docURL.left(7)!="http://" && docURL.left(7)!="file://")
+ {
+ err("Error: tag DOC_URL: URL to documentation is invalid or "
+ "not absolute.\n");
+ exit(1);
+ }
+ // check absolute documentation path
+ if (docAbsPath.length()==0)
+ {
+ docAbsPath = outputDir+"/html";
+ }
+ else if (docAbsPath && docAbsPath[0]!='/')
+ {
+ err("Error: tag DOC_ABSPATH: path is not absolute\n");
+ exit(1);
+ }
+ // check path to doxysearch
+ if (binAbsPath.length()==0)
+ {
+ err("Error: tag BIN_ABSPATH: no absolute path to doxysearch "
+ "specified.\n");
+ exit(1);
+ }
+ else
+ {
+ if (binAbsPath && binAbsPath[0]!='/')
+ {
+ err("Error: tag BIN_ABSPATH: path is not absolute "
+ "(must start with /).\n");
+ exit(1);
+ }
+ }
+ // check perl path
+ if (perlPath.length()==0)
+ {
+ perlPath="/usr/local/bin/perl";
+ }
+ QFileInfo fi(perlPath);
+ if (!fi.exists())
+ {
+ err("Error: tag PERL_PATH: perl interpreter not found at `%s'\n",
+ perlPath.data());
+ exit(1);
+ }
+ }
+}
+
+void parseConfig(const QString &s)
+{
+ inputString = s;
+ inputPosition = 0;
+ yyLineNr = 1;
+ configYYrestart( configYYin );
+ BEGIN( Start );
+ configYYlex();
+ checkConfig();
+}
+
+extern "C" { // some bogus code to keep the compiler happy
+ int configYYwrap() { return 1 ; }
+}
diff --git a/src/constexp.h b/src/constexp.h
new file mode 100644
index 0000000..9979bfd
--- /dev/null
+++ b/src/constexp.h
@@ -0,0 +1,30 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#ifndef _CONSTEXP_H
+#define _CONSTEXP_H
+
+#include <qstring.h>
+#include "cppvalue.h"
+
+extern bool parseCppExpression(const QString &s);
+extern int cppExpYYparse();
+extern int cppExpYYdebug;
+extern QString strToken;
+extern CPPValue resultValue;
+
+#endif
diff --git a/src/constexp.l b/src/constexp.l
new file mode 100644
index 0000000..f023507
--- /dev/null
+++ b/src/constexp.l
@@ -0,0 +1,110 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+%{
+
+#include "constexp.h"
+#include "cppvalue.h"
+#include "ce_parse.h" // generated header file
+
+#define YY_NO_UNPUT
+#define YY_NEVER_INTERACTIVE 1
+
+QString strToken;
+
+static const char *inputString;
+static int inputPosition;
+CPPValue resultValue;
+
+#undef YY_INPUT
+#define YY_INPUT(buf,result,max_size) result=yyread(buf,max_size);
+
+static int yyread(char *buf,int max_size)
+{
+ int c=0;
+ while( c < max_size && inputString[inputPosition] )
+ {
+ *buf = inputString[inputPosition++] ;
+ c++; buf++;
+ }
+ return c;
+}
+
+%}
+
+%%
+
+"?" { return TOK_QUESTIONMARK; }
+":" { return TOK_COLON; }
+"||" { return TOK_OR; }
+"&&" { return TOK_AND; }
+"|" { return TOK_BITWISEOR; }
+"^" { return TOK_BITWISEXOR; }
+"&" { return TOK_AMPERSAND; }
+"!=" { return TOK_NOTEQUAL; }
+"==" { return TOK_EQUAL; }
+"<" { return TOK_LESSTHAN; }
+">" { return TOK_GREATERTHAN; }
+"<=" { return TOK_LESSTHANOREQUALTO; }
+">=" { return TOK_GREATERTHANOREQUALTO; }
+"<<" { return TOK_SHIFTLEFT; }
+">>" { return TOK_SHIFTRIGHT; }
+"+" { return TOK_PLUS; }
+"-" { return TOK_MINUS; }
+"*" { return TOK_STAR; }
+"/" { return TOK_DIVIDE; }
+"%" { return TOK_MOD; }
+"~" { return TOK_TILDE; }
+"!" { return TOK_NOT; }
+"(" { return TOK_LPAREN; }
+")" { return TOK_RPAREN; }
+"'"(([^\'\n\r\\]+)|(\\(([ntvbrfa\\?'\"])|([0-9]+)|([xX][0-9a-fA-F]+))))"'" {
+ strToken=yytext;
+ return TOK_CHARACTER;
+ }
+0[0-7]*[uUlL]* { strToken=yytext;
+ return TOK_OCTALINT;
+ }
+[1-9][0-9]*[uUlL]* { strToken=yytext;
+ return TOK_DECIMALINT;
+ }
+(0x|0X)[0-9a-fA-F]+[uUlL]* { strToken=yytext; return TOK_HEXADECIMALINT; }
+(([0-9]+\.[0-9]*)|([0-9]*\.[0-9]+))([eE]([\-\+])?[0-9]+)?([fFlL])? {
+ strToken=yytext; return TOK_FLOAT;
+ }
+([0-9]+[eE])([\-\+])?[0-9]+([fFlL])? {
+ strToken=yytext; return TOK_FLOAT;
+ }
+.
+\n
+
+%%
+
+bool parseCppExpression(const QString &s)
+{
+ //printf("Expression: `%s'\n",s.data());
+ inputString = s;
+ inputPosition = 0;
+ cppExpYYrestart( cppExpYYin );
+ cppExpYYparse();
+ //printf("Result: %ld\n",(long)resultValue);
+ return (long)resultValue!=0;
+}
+
+extern "C" {
+ int cppExpYYwrap() { return 1; }
+}
diff --git a/src/constexp.y b/src/constexp.y
new file mode 100644
index 0000000..fa13d6e
--- /dev/null
+++ b/src/constexp.y
@@ -0,0 +1,275 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+%{
+
+#include "cppvalue.h"
+#include "constexp.h"
+
+#if defined(_MSC_VER)
+#define MSDOS
+#endif
+
+#define YYSTYPE CPPValue
+
+#include <stdio.h>
+#include <stdlib.h>
+
+int cppExpYYerror(const char *s)
+{
+ printf("ERROR: %s\n",s);
+ return 0;
+}
+
+int cppExpYYlex();
+
+%}
+
+%token TOK_QUESTIONMARK
+%token TOK_COLON
+%token TOK_OR
+%token TOK_AND
+%token TOK_BITWISEOR
+%token TOK_BITWISEXOR
+%token TOK_AMPERSAND
+%token TOK_NOTEQUAL
+%token TOK_EQUAL
+%token TOK_LESSTHAN
+%token TOK_GREATERTHAN
+%token TOK_LESSTHANOREQUALTO
+%token TOK_GREATERTHANOREQUALTO
+%token TOK_SHIFTLEFT
+%token TOK_SHIFTRIGHT
+%token TOK_PLUS
+%token TOK_MINUS
+%token TOK_STAR
+%token TOK_DIVIDE
+%token TOK_MOD
+%token TOK_TILDE
+%token TOK_NOT
+%token TOK_LPAREN
+%token TOK_RPAREN
+%token TOK_OCTALINT
+%token TOK_DECIMALINT
+%token TOK_HEXADECIMALINT
+%token TOK_CHARACTER
+%token TOK_FLOAT
+
+%%
+
+start: constant_expression
+ { resultValue = $1; return 0; }
+;
+
+constant_expression: logical_or_expression
+ { $$ = $1; }
+ | logical_or_expression
+ TOK_QUESTIONMARK logical_or_expression
+ TOK_COLON logical_or_expression
+ {
+ bool c = ($1.isInt() ? ((long)$1 != 0) : ((double)$1 != 0.0));
+ $$ = c ? $3 : $5;
+ }
+;
+
+logical_or_expression: logical_and_expression
+ { $$ = $1; }
+ | logical_or_expression TOK_OR logical_and_expression
+ {
+ $$ = CPPValue( (long)((long)$1 || (long)$3) );
+ }
+;
+
+logical_and_expression: inclusive_or_expression
+ { $$ = $1; }
+ | logical_and_expression TOK_AND inclusive_or_expression
+ {
+ $$ = CPPValue( (long)((long)$1 && (long)$3) );
+ }
+;
+
+inclusive_or_expression: exclusive_or_expression
+ { $$ = $1; }
+ | inclusive_or_expression TOK_BITWISEOR
+ exclusive_or_expression
+ {
+ $$ = CPPValue( (long)$1 | (long)$3 );
+ }
+;
+
+exclusive_or_expression: and_expression
+ { $$ = $1; }
+ | exclusive_or_expression TOK_BITWISEXOR and_expression
+ {
+ $$ = CPPValue( (long)$1 ^ (long)$3 );
+ }
+;
+
+and_expression: equality_expression
+ { $$ = $1; }
+ | and_expression TOK_AMPERSAND equality_expression
+ {
+ $$ = CPPValue( (long)$1 & (long)$3 );
+ }
+;
+
+equality_expression: relational_expression
+ { $$ = $1; }
+ | equality_expression TOK_EQUAL relational_expression
+ {
+ $$ = CPPValue( (long)((double)$1 == (double)$3) );
+ }
+ | equality_expression TOK_NOTEQUAL relational_expression
+ {
+ $$ = CPPValue( (long)((double)$1 != (double)$3) );
+ }
+;
+
+relational_expression: shift_expression
+ { $$ = $1; }
+ | relational_expression TOK_LESSTHAN shift_expression
+ {
+ $$ = CPPValue( (long)((double)$1 < (double)$3) );
+ }
+ | relational_expression TOK_GREATERTHAN shift_expression
+ {
+ $$ = CPPValue( (long)((double)$1 > (double)$3) );
+ }
+ | relational_expression TOK_LESSTHANOREQUALTO
+ shift_expression
+ {
+ $$ = CPPValue( (long)((double)$1 <= (double)$3) );
+ }
+ | relational_expression TOK_GREATERTHANOREQUALTO
+ shift_expression
+ {
+ $$ = CPPValue( (long)((double)$1 >= (double)$3) );
+ }
+;
+
+shift_expression: additive_expression
+ { $$ = $1; }
+ | shift_expression TOK_SHIFTLEFT additive_expression
+ {
+ $$ = CPPValue( (long)$1 << (long)$3 );
+ }
+ | shift_expression TOK_SHIFTRIGHT additive_expression
+ {
+ $$ = CPPValue( (long)$1 >> (long)$3 );
+ }
+;
+
+additive_expression: multiplicative_expression
+ { $$ = $1; }
+ | additive_expression TOK_PLUS multiplicative_expression
+ {
+ if (!$1.isInt() || !$3.isInt())
+ {
+ $$ = CPPValue( (double)$1 + (double)$3 );
+ }
+ else
+ {
+ $$ = CPPValue( (long)$1 + (long)$3 );
+ }
+ }
+ | additive_expression TOK_MINUS multiplicative_expression
+ {
+ if (!$1.isInt() || !$3.isInt())
+ {
+ $$ = CPPValue( (double)$1 - (double)$3 );
+ }
+ else
+ {
+ $$ = CPPValue( (long)$1 - (long)$3 );
+ }
+ }
+;
+
+multiplicative_expression: unary_expression
+ { $$ = $1; }
+ | multiplicative_expression TOK_STAR unary_expression
+ {
+ if (!$1.isInt() || !$3.isInt())
+ {
+ $$ = CPPValue( (double)$1 * (double)$3 );
+ }
+ else
+ {
+ $$ = CPPValue( (long)$1 * (long)$3 );
+ }
+ }
+ | multiplicative_expression TOK_DIVIDE unary_expression
+ {
+ if (!$1.isInt() || !$3.isInt())
+ {
+ $$ = CPPValue( (double)$1 / (double)$3 );
+ }
+ else
+ {
+ long value = $3;
+ if (value==0) value=1;
+ $$ = CPPValue( (long)$1 / value );
+ }
+ }
+ | multiplicative_expression TOK_MOD unary_expression
+ {
+ long value = $3;
+ if (value==0) value=1;
+ $$ = CPPValue( (long)$1 % value );
+ }
+;
+
+unary_expression: primary_expression
+ { $$ = $1; }
+ | TOK_PLUS unary_expression
+ { $$ = $1; }
+ | TOK_MINUS unary_expression
+ {
+ if ($2.isInt())
+ $$ = CPPValue(-(long)$2);
+ else
+ $$ = CPPValue(-(double)$2);
+ }
+ | TOK_TILDE unary_expression
+ {
+ $$ = CPPValue(~(long)$2);
+ }
+ | TOK_NOT unary_expression
+ {
+ $$ = CPPValue((long)!(long)$2);
+ }
+;
+
+primary_expression: constant
+ { $$ = $1; }
+ | TOK_LPAREN constant_expression TOK_RPAREN
+ { $$ = $2; }
+;
+
+constant: TOK_OCTALINT
+ { $$ = parseOctal(); }
+ | TOK_DECIMALINT
+ { $$ = parseDecimal(); }
+ | TOK_HEXADECIMALINT
+ { $$ = parseHexadecimal(); }
+ | TOK_CHARACTER
+ { $$ = parseCharacter(); }
+ | TOK_FLOAT
+ { $$ = parseFloat(); }
+;
+
+%%
diff --git a/src/cppvalue.cpp b/src/cppvalue.cpp
new file mode 100644
index 0000000..ab2a1d4
--- /dev/null
+++ b/src/cppvalue.cpp
@@ -0,0 +1,85 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#include <stdlib.h>
+
+#include "cppvalue.h"
+#include "constexp.h"
+
+CPPValue parseOctal()
+{
+ long val = 0;
+ for (const char *p = strToken.data(); *p != 0; p++)
+ {
+ if (*p >= '0' && *p <= '7') val = val * 8 + *p - '0';
+ }
+ return CPPValue(val);
+}
+
+CPPValue parseDecimal()
+{
+ long val = 0;
+ for (const char *p = strToken.data(); *p != 0; p++)
+ {
+ if (*p >= '0' && *p <= '9') val = val * 10 + *p - '0';
+ }
+ return CPPValue(val);
+}
+
+CPPValue parseHexadecimal()
+{
+ long val = 0;
+ for (const char *p = strToken.data(); *p != 0; p++)
+ {
+ if (*p >= '0' && *p <= '9') val = val * 16 + *p - '0';
+ else if (*p >= 'a' && *p <= 'f') val = val * 16 + *p - 'a' + 10;
+ else if (*p >= 'A' && *p <= 'F') val = val * 16 + *p - 'A' + 10;
+ }
+ return CPPValue(val);
+}
+
+CPPValue parseCharacter() // does not work for '\n' and the alike
+{
+ if (strToken[1]=='\\')
+ {
+ switch(strToken[2])
+ {
+ case 'n': return CPPValue((long)'\n');
+ case 't': return CPPValue((long)'\t');
+ case 'v': return CPPValue((long)'\v');
+ case 'b': return CPPValue((long)'\b');
+ case 'r': return CPPValue((long)'\r');
+ case 'f': return CPPValue((long)'\f');
+ case 'a': return CPPValue((long)'\a');
+ case '\\': return CPPValue((long)'\\');
+ case '?': return CPPValue((long)'\?');
+ case '\'': return CPPValue((long)'\'');
+ case '"': return CPPValue((long)'"');
+ case '0': return parseOctal();
+ case 'x':
+ case 'X': return parseHexadecimal();
+ default: printf("Invalid escape sequence %s found!\n",strToken.data());
+ return CPPValue(0L);
+ }
+ }
+ return CPPValue((long)strToken[1]);
+}
+
+CPPValue parseFloat()
+{
+ return CPPValue(atof(strToken));
+}
diff --git a/src/cppvalue.h b/src/cppvalue.h
new file mode 100644
index 0000000..d3751b2
--- /dev/null
+++ b/src/cppvalue.h
@@ -0,0 +1,59 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#ifndef _CPPVALUE_H
+#define _CPPVALUE_H
+
+#include <stdio.h>
+#include <qglobal.h>
+
+class CPPValue
+{
+ friend CPPValue parseOctal();
+ friend CPPValue parseDecimal();
+ friend CPPValue parseHexadecimal();
+ friend CPPValue parseCharacter();
+ friend CPPValue parseFloat();
+
+ public:
+ enum Type { Int, Float };
+
+ CPPValue(long val=0) : type(Int) { v.l = val; }
+ CPPValue(double val) : type(Float) { v.d = val; }
+
+ operator double () const { return type==Int ? (double)v.l : v.d; }
+ operator long () const { return type==Int ? v.l : (long)v.d; }
+
+ bool isInt() const { return type == Int; }
+
+ void print() const
+ {
+ if (type==Int)
+ printf("(%ld)\n",v.l);
+ else
+ printf("(%f)\n",v.d);
+ }
+
+ private:
+ Type type;
+ union {
+ double d;
+ long l;
+ } v;
+};
+
+#endif
diff --git a/src/debug.cpp b/src/debug.cpp
new file mode 100644
index 0000000..fc2731d
--- /dev/null
+++ b/src/debug.cpp
@@ -0,0 +1,62 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#include "debug.h"
+#include <stdarg.h>
+#include <stdio.h>
+#include <qstring.h>
+
+Debug::DebugMask Debug::curMask = Debug::Quiet;
+int Debug::curPrio = 0;
+
+void Debug::print(DebugMask mask,int prio,const char *fmt,...)
+{
+ if ((curMask&mask) && prio<=curPrio)
+ {
+ va_list args;
+ va_start(args,fmt);
+ vfprintf(stdout, fmt, args);
+ va_end(args);
+ }
+}
+
+static int labelToEnumValue(const char *l)
+{
+ QString label=l;
+ if (label=="FindMembers")
+ return Debug::FindMembers;
+ else if (label=="Functions")
+ return Debug::Functions;
+ else if (label=="Variables")
+ return Debug::Variables;
+ else
+ return 0;
+}
+
+void Debug::setFlag(const char *lab)
+{
+ curMask = (DebugMask)(curMask | labelToEnumValue(lab));
+}
+
+void Debug::clearFlag(const char *lab)
+{
+ curMask = (DebugMask)(curMask & ~labelToEnumValue(lab));
+}
+
+void Debug::setPriority(int p)
+{
+ curPrio = p;
+}
diff --git a/src/debug.h b/src/debug.h
new file mode 100644
index 0000000..b2b389f
--- /dev/null
+++ b/src/debug.h
@@ -0,0 +1,39 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#ifndef _DEBUG_H
+#define _DEBUG_H
+
+class Debug
+{
+ public:
+ enum DebugMask { Quiet = 0x00000000,
+ FindMembers = 0x00000001,
+ Functions = 0x00000002,
+ Variables = 0x00000004
+ };
+ static void print(DebugMask mask,int prio,const char *fmt,...);
+ static void setFlag(const char *label);
+ static void clearFlag(const char *label);
+ static void setPriority(int p);
+
+ private:
+ static DebugMask curMask;
+ static int curPrio;
+};
+
+#endif
diff --git a/src/declinfo.h b/src/declinfo.h
new file mode 100644
index 0000000..4ec3ec5
--- /dev/null
+++ b/src/declinfo.h
@@ -0,0 +1,32 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#ifndef DECLINFO_H
+#define DECLINFO_H
+
+#include <stdio.h>
+#include <qstring.h>
+
+extern void parseFuncDecl(const QString &decl,
+ QString &clName,
+ QString &classTempList,
+ QString &type,
+ QString &name,
+ QString &args,
+ QString &funcTempList,
+ QString &exceptions
+ );
+#endif
diff --git a/src/declinfo.l b/src/declinfo.l
new file mode 100644
index 0000000..0f0505d
--- /dev/null
+++ b/src/declinfo.l
@@ -0,0 +1,292 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+%{
+
+/*
+ * includes
+ */
+#include <stdio.h>
+#include <iostream.h>
+#include <assert.h>
+#include <ctype.h>
+
+#include "declinfo.h"
+#include "util.h"
+
+
+#define YY_NO_UNPUT
+
+/* -----------------------------------------------------------------
+ *
+ * statics
+ */
+
+static const char * inputString;
+static int inputPosition;
+static QString scope;
+static QString className;
+static QString classTempList;
+static QString funcTempList;
+static QString type;
+static QString name;
+static QString args;
+static QString tmpType;
+static int sharpCount;
+static bool classTempListFound;
+static bool funcTempListFound;
+static QString exceptionString;
+
+static void addType()
+{
+ //printf("addType() type=`%s' scope=`%s' name=`%s'\n",
+ // type.data(),scope.data(),name.data());
+ if (name.isEmpty() && scope.isEmpty()) return;
+ if (!type.isNull()) type+=' ';
+ if (!scope.isEmpty()) type+=scope+"::";
+ type+=name;
+ scope.resize(0);
+ name.resize(0);
+}
+
+static void addTypeName()
+{
+ //printf("addTypeName() type=`%s' scope=`%s' name=`%s'\n",
+ // type.data(),scope.data(),name.data());
+ if (name.isEmpty()) return;
+ if (!type.isNull()) type+=' ';
+ type+=name;
+ name.resize(0);
+}
+
+#define YY_NEVER_INTERACTIVE 1
+
+/* -----------------------------------------------------------------
+ */
+#undef YY_INPUT
+#define YY_INPUT(buf,result,max_size) result=yyread(buf,max_size);
+
+static int yyread(char *buf,int max_size)
+{
+ int c=0;
+ while( c < max_size && inputString[inputPosition] )
+ {
+ *buf = inputString[inputPosition++] ;
+ c++; buf++;
+ }
+ return c;
+}
+
+%}
+
+B [ \t]
+ID [a-z_A-Z][a-z_A-Z0-9]*
+
+%x Start
+%x Template
+%x ReadArgs
+%x Operator
+%x FuncPtr
+%x EndTemplate
+%x StripTempArgs
+%x SkipSharp
+%x ReadExceptions
+
+%%
+
+<Start>"operator" { // operator rule must be before {ID} rule
+ name += yytext;
+ BEGIN(Operator);
+ }
+<Start>(~{B}*)?{ID} {
+ addTypeName();
+ name += yytext;
+ }
+<Start>{B}*"::"{B}* { // found a scope specifier
+ if (!scope.isEmpty())
+ {
+ scope+="::"+name; // add name to scope
+ }
+ else
+ {
+ scope = name.copy(); // scope becomes name
+ }
+ name.resize(0);
+ }
+<Start>[*&]+ {
+ addType();
+ type+=yytext;
+ }
+<Start>{B}+ {
+ addType();
+ }
+<Start>{B}*"("{B}*"*" {
+ addType();
+ type+="(*";
+ }
+<Start>{B}*")" {
+ type+=")";
+ }
+<Start>{B}*"(" { // TODO: function pointers
+ args+="(";
+ BEGIN(ReadArgs);
+ }
+<Start>{B}*"[" {
+ args+="[";
+ BEGIN(ReadArgs);
+ }
+<Start>{B}*"<" {
+ name+="<";
+ sharpCount=0;
+ BEGIN(Template);
+ }
+<Template>"<" {
+ name+="<";
+ sharpCount++;
+ }
+<Template>">" {
+ name+=">";
+ if (sharpCount)
+ --sharpCount;
+ else
+ {
+ BEGIN(Start);
+ }
+ }
+<Template>. {
+ name+=*yytext;
+ }
+<Operator>{B}*"()"{B}*"<>"{B}*/"(" {
+ name+="() <>";
+ BEGIN(ReadArgs);
+ }
+<Operator>{B}*"()"{B}*/"(" {
+ name+="()";
+ BEGIN(ReadArgs);
+ }
+<Operator>[^(]*{B}*("<>"{B}*)?/"(" {
+ name+=yytext;
+ BEGIN(ReadArgs);
+ }
+<ReadArgs>"throw"{B}*"(" {
+ exceptionString="throw(";
+ BEGIN(ReadExceptions);
+ }
+<ReadArgs>. {
+ args+=*yytext;
+ }
+<ReadExceptions>. {
+ exceptionString+=*yytext;
+ }
+<*>.
+
+%%
+
+/*@ ----------------------------------------------------------------------------
+ */
+
+void parseFuncDecl(const QString &decl,QString &cl,QString &ctl,QString &t,
+ QString &n,QString &a,QString &ftl,QString &exc)
+{
+ inputString = decl;
+ //printf("Input=`%s'\n",inputString);
+ if (inputString==0) return;
+ inputPosition = 0;
+ classTempListFound = FALSE;
+ funcTempListFound = FALSE;
+ scope.resize(0);
+ className.resize(0);
+ classTempList.resize(0);
+ funcTempList.resize(0);
+ name.resize(0);
+ type.resize(0);
+ args.resize(0);
+ exceptionString.resize(0);
+ // first we try to find the type, scope, name and arguments
+ declinfoYYrestart( declinfoYYin );
+ BEGIN( Start );
+ declinfoYYlex();
+
+ cl=scope.copy();
+ int i;
+ if ((i=cl.find('<'))!=-1) // split up scope and template arguments
+ {
+ ctl=removeRedundantWhiteSpace(cl.right(cl.length()-i));
+ cl=cl.left(i);
+ }
+ n=removeRedundantWhiteSpace(name);
+ if ((i=n.find('<'))!=-1 && n.left(8)!="operator")
+ {
+ ftl=removeRedundantWhiteSpace(n.right(n.length()-i));
+ n=n.left(i);
+ }
+
+ //ctl=classTempList.copy();
+ //ftl=funcTempList.copy();
+ t=removeRedundantWhiteSpace(type);
+ a=removeRedundantWhiteSpace(args);
+ exc=removeRedundantWhiteSpace(exceptionString);
+
+ if (t.length()>0 && t.at(t.length()-1)==')')
+ {
+ a.prepend(")");
+ t=t.left(t.length()-1);
+ }
+ //printf("type=`%s' class=`%s' name=`%s' args=`%s'\n",
+ // t.data(),cl.data(),n.data(),a.data());
+
+ return;
+
+
+}
+
+extern "C" { // some bogus code to keep the compiler happy
+ int declinfoYYwrap() { return 1 ; }
+ void declinfoYYdummy() { yy_flex_realloc(0,0); }
+}
+
+#if 0
+void dumpDecl(const char *s)
+{
+ QString className;
+ QString classTNames;
+ QString type;
+ QString name;
+ QString args;
+ QString funcTNames;
+ printf("-----------------------------------------\n");
+ parseFuncDecl(s,className,classTNames,type,name,args,funcTNames);
+ printf("type=`%s' class=`%s' classTempl=`%s' name=`%s' "
+ "funcTemplateNames=`%s' args=`%s'\n",
+ type.data(),className.data(),classTNames.data(),
+ name.data(),funcTNames.data(),args.data()
+ );
+}
+
+// some test code
+int main()
+{
+ dumpDecl("A < T > :: Value * A < T > :: getValue < S > ( const A < T > & a )");
+ dumpDecl("const A<T>::Value* A<T>::getValue<S>(const A<T>&a)");
+ dumpDecl("func()");
+ dumpDecl("friend void bla<>()");
+ dumpDecl("name< T > :: operator () (int bla)");
+ dumpDecl("name< T > :: operator << (int bla)");
+ dumpDecl("name< T > :: operator << <> (int bla)");
+ dumpDecl("className::func()");
+ dumpDecl("void ( * Name < T > :: bla ) ( int, char * )");
+}
+#endif
diff --git a/src/defargs.h b/src/defargs.h
new file mode 100644
index 0000000..d2cd8f2
--- /dev/null
+++ b/src/defargs.h
@@ -0,0 +1,27 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#ifndef DEFARGS_H
+#define DEFARGS_H
+
+#include <stdio.h>
+#include <qstring.h>
+
+class ArgumentList;
+
+extern void stringToArgumentList(const char *argsString,ArgumentList* &argList);
+
+#endif
diff --git a/src/defargs.l b/src/defargs.l
new file mode 100644
index 0000000..b7dfd57
--- /dev/null
+++ b/src/defargs.l
@@ -0,0 +1,298 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+%{
+
+/*
+ * includes
+ */
+#include <stdio.h>
+#include <iostream.h>
+#include <assert.h>
+#include <ctype.h>
+#include <qregexp.h>
+
+#include "defargs.h"
+#include "entry.h"
+#include "util.h"
+
+#define YY_NO_UNPUT
+#define YY_NEVER_INTERACTIVE 1
+
+/* -----------------------------------------------------------------
+ *
+ * statics
+ */
+
+static const char *inputString;
+static int inputPosition;
+static ArgumentList *argList;
+static QString *copyArgValue;
+static QString curArgTypeName;
+static QString curArgDefValue;
+static QString curArgName;
+static int argRoundCount;
+static int argSharpCount;
+static int argCurlyCount;
+static int readArgContext;
+
+
+
+/* -----------------------------------------------------------------
+ */
+#undef YY_INPUT
+#define YY_INPUT(buf,result,max_size) result=yyread(buf,max_size);
+
+static int yyread(char *buf,int max_size)
+{
+ int c=0;
+ while( c < max_size && inputString[inputPosition] )
+ {
+ *buf = inputString[inputPosition++] ;
+ c++; buf++;
+ }
+ return c;
+}
+
+%}
+
+B [ \t]
+ID [a-z_A-Z][a-z_A-Z0-9]*
+
+%x Start
+%x CopyArgString
+%x CopyArgRound
+%x CopyArgRound2
+%x CopyArgSharp
+%x CopyArgCurly
+%x ReadFuncArgType
+%x ReadFuncArgDef
+%x ReadFuncArgPtr
+%x FuncQual
+
+
+%%
+
+<Start>[<(] { BEGIN(ReadFuncArgType); }
+
+<ReadFuncArgType>{B}* {
+ curArgTypeName+=" ";
+ }
+<ReadFuncArgDef>"'"\\[0-7]{1,3}"'" { curArgDefValue+=yytext; }
+<ReadFuncArgDef>"'"\\."'" { curArgDefValue+=yytext; }
+<ReadFuncArgDef>"'"."'" { curArgDefValue+=yytext; }
+<ReadFuncArgDef>\" {
+ curArgDefValue+=*yytext;
+ BEGIN( CopyArgString );
+ }
+<ReadFuncArgType>"("([^:)]+{B}*"::")*{B}*[&*]+{B}*/{ID} {
+ // function pointer as argument
+ curArgTypeName+=yytext;
+ //curArgTypeName=curArgTypeName.simplifyWhiteSpace();
+ BEGIN( ReadFuncArgPtr );
+ }
+<ReadFuncArgPtr>{ID} {
+ curArgName=yytext;
+ }
+<ReadFuncArgPtr>")"{B}*"(" {
+ curArgTypeName+=yytext;
+ //curArgTypeName=curArgTypeName.simplifyWhiteSpace();
+ readArgContext = ReadFuncArgType;
+ copyArgValue=&curArgTypeName;
+ argRoundCount=0;
+ BEGIN( CopyArgRound2 );
+ }
+<ReadFuncArgPtr>")" { // redundant braces detected / remove them
+ int i=curArgTypeName.findRev('('),l=curArgTypeName.length();
+ if (i!=-1)
+ curArgTypeName=curArgTypeName.left(i)+
+ curArgTypeName.right(l-i-1);
+ curArgTypeName+=curArgName;
+ BEGIN( ReadFuncArgType );
+ }
+<ReadFuncArgType,ReadFuncArgDef>[({<] {
+ if (YY_START==ReadFuncArgType)
+ {
+ curArgTypeName+=*yytext;
+ copyArgValue=&curArgTypeName;
+ }
+ else // YY_START==ReadFuncArgDef
+ {
+ curArgDefValue+=*yytext;
+ copyArgValue=&curArgDefValue;
+ }
+ readArgContext = YY_START;
+ if (*yytext=='(')
+ {
+ argRoundCount=0;
+ BEGIN( CopyArgRound );
+ }
+ else if (*yytext=='{')
+ {
+ argCurlyCount=0;
+ BEGIN( CopyArgCurly );
+ }
+ else // yytext=='<'
+ {
+ argSharpCount=0;
+ BEGIN( CopyArgSharp );
+ }
+ }
+<CopyArgRound,CopyArgRound2>"(" {
+ argRoundCount++;
+ *copyArgValue += *yytext;
+ }
+<CopyArgRound,CopyArgRound2>")" {
+ *copyArgValue += *yytext;
+ if (argRoundCount>0)
+ {
+ argRoundCount--;
+ }
+ else
+ {
+ if (YY_START==CopyArgRound2)
+ {
+ *copyArgValue+=" "+curArgName;
+ }
+ BEGIN( readArgContext );
+ }
+ }
+<CopyArgSharp>"<" {
+ argSharpCount++;
+ *copyArgValue += *yytext;
+ }
+<CopyArgSharp>">" {
+ *copyArgValue += *yytext;
+ if (argSharpCount>0) argSharpCount--;
+ else BEGIN( readArgContext );
+ }
+<CopyArgCurly>"{" {
+ argCurlyCount++;
+ *copyArgValue += *yytext;
+ }
+<CopyArgSharp>"}" {
+ *copyArgValue += *yytext;
+ if (argCurlyCount>0) argCurlyCount--;
+ else BEGIN( readArgContext );
+ }
+<CopyArgString>\\. {
+ curArgDefValue+=yytext;
+ }
+<CopyArgString>\" {
+ curArgDefValue+=*yytext;
+ BEGIN( ReadFuncArgDef );
+ }
+<ReadFuncArgType>"=" {
+ BEGIN( ReadFuncArgDef );
+ }
+<ReadFuncArgType,ReadFuncArgDef>[,)>] {
+ curArgTypeName=removeRedundantWhiteSpace(
+ curArgTypeName.simplifyWhiteSpace());
+ curArgDefValue=curArgDefValue.stripWhiteSpace();
+ int l=curArgTypeName.length();
+ if (l>0)
+ {
+ int i=l-1;
+ while (i>=0 &&
+ (
+ isspace(curArgTypeName.at(i)) ||
+ isId(curArgTypeName.at(i))
+ )
+ ) i--;
+ Argument *a = new Argument;
+ if (i>=0 && curArgTypeName.at(i)!=':')
+ { // type contains a name
+ a->type = curArgTypeName.left(i+1).stripWhiteSpace();
+ a->name = curArgTypeName.right(curArgTypeName.length()-i-1);
+ }
+ else // assume only the type was specified, try to determine name later
+ {
+ a->type = curArgTypeName.stripWhiteSpace();
+ }
+ a->defval = curArgDefValue.copy();
+ //printf("----> Adding argument `%s' `%s' `%s'\n",a->type.data(),a->name.data(),a->defval.data());
+ argList->append(a);
+ }
+ curArgTypeName.resize(0);
+ curArgDefValue.resize(0);
+ if (*yytext==')')
+ {
+ BEGIN(FuncQual);
+ //printf(">>> end of argument list\n");
+ }
+ else
+ {
+ BEGIN( ReadFuncArgType );
+ }
+ }
+<ReadFuncArgType,ReadFuncArgPtr>{ID} {
+ QString name=yytext; //resolveDefines(yytext);
+ //printf("resolveName `%s'->`%s'\n",yytext,name.data());
+ curArgTypeName+=name;
+ }
+<ReadFuncArgType,ReadFuncArgPtr>. {
+ curArgTypeName+=*yytext;
+ }
+<ReadFuncArgDef,CopyArgString>. {
+ curArgDefValue+=*yytext;
+ }
+<CopyArgRound,CopyArgRound2,CopyArgSharp,CopyArgCurly>{ID} {
+ QString name=yytext; //resolveDefines(yytext);
+ *copyArgValue+=name;
+ }
+<CopyArgRound,CopyArgRound2,CopyArgSharp,CopyArgCurly>. {
+ *copyArgValue += *yytext;
+ }
+<FuncQual>"const" {
+ argList->constSpecifier=TRUE;
+ }
+<FuncQual>"volatile" {
+ argList->volatileSpecifier=TRUE;
+ }
+<FuncQual>"="{B}*"0" {
+ argList->pureSpecifier=TRUE;
+ }
+<*>.
+
+%%
+
+/* ----------------------------------------------------------------------------
+ */
+
+// converts an argument string into a list of Arguments.
+// an Argument consists of a type, an optional name, and an optional
+// default initializer.
+
+void stringToArgumentList(const char *argsString,ArgumentList* &al)
+{
+ //if (al==0) al=new ArgumentList; // allocate new list if needed.
+ if (al==0) return;
+ if (!argsString) return;
+ inputString = argsString;
+ inputPosition = 0;
+ curArgTypeName.resize(0);
+ curArgDefValue.resize(0);
+ curArgName.resize(0);
+ argList = al;
+ defargsYYrestart( defargsYYin );
+ BEGIN( Start );
+ defargsYYlex();
+}
+
+extern "C" { // some bogus code to keep the compiler happy
+ int defargsYYwrap() { return 1 ; }
+ void defargsYYdummy() { yy_flex_realloc(0,0); }
+}
diff --git a/src/define.cpp b/src/define.cpp
new file mode 100644
index 0000000..2fa7fa4
--- /dev/null
+++ b/src/define.cpp
@@ -0,0 +1,43 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#include "define.h"
+#include "config.h"
+
+Define::Define()
+{
+ undef=FALSE;
+ fileDef=0;
+}
+
+Define::Define(const Define &d)
+ : name(d.name),definition(d.definition),fileName(d.fileName)
+{
+ //name=d.name; definition=d.definition; fileName=d.fileName;
+ lineNr=d.lineNr;
+ nargs=d.nargs;
+ undef=d.undef;
+ fileDef=0;
+}
+
+Define::~Define()
+{
+}
+
+bool Define::hasDocumentation()
+{
+ return definition && (doc || extractAllFlag);
+}
diff --git a/src/define.h b/src/define.h
new file mode 100644
index 0000000..14ac008
--- /dev/null
+++ b/src/define.h
@@ -0,0 +1,88 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#ifndef DEFINE_H
+#define DEFINE_H
+
+#include <qdict.h>
+#include <qstring.h>
+#include "util.h"
+
+class FileDef;
+
+class Define
+{
+ public:
+ Define();
+ Define(const Define &d);
+ ~Define();
+ bool hasDocumentation();
+ QString name;
+ QString definition;
+ QString fileName;
+ QString doc;
+ QString brief;
+ QString args;
+ QString anchor;
+ FileDef *fileDef;
+ int lineNr;
+ int nargs;
+ bool undef;
+ bool varArgs;
+};
+
+class DefineList : public QList<Define>
+{
+ public:
+ DefineList() : QList<Define>() {}
+ ~DefineList() {}
+ int compareItems(GCI i1,GCI i2)
+ {
+ return strcmp(((Define *)i1)->name,((Define *)i2)->name);
+ }
+};
+
+class DefineName : public QList<Define>
+{
+ public:
+ DefineName(const char *n) : QList<Define>() { name=n; }
+ ~DefineName() {}
+ const char *nameString() const { return name; }
+ int compareItems(GCI i1,GCI i2)
+ {
+ return strcmp(((Define *)i1)->name,((Define *)i2)->name);
+ }
+
+ private:
+ QString name;
+};
+
+class DefineNameList : public QList<DefineName>
+{
+ public:
+ DefineNameList() : QList<DefineName>() {}
+ ~DefineNameList() {}
+ int compareItems(GCI i1,GCI i2)
+ {
+ return stricmp(((DefineName *)i1)->nameString(),
+ ((DefineName *)i2)->nameString());
+ }
+};
+
+typedef QDict<Define> DefineDict;
+typedef QDict<DefineName> DefineNameDict;
+
+#endif
diff --git a/src/definition.cpp b/src/definition.cpp
new file mode 100644
index 0000000..535612b
--- /dev/null
+++ b/src/definition.cpp
@@ -0,0 +1,44 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#include <ctype.h>
+#include "definition.h"
+
+QString Definition::nameToFile(const char *name)
+{
+ QString result;
+ char c;
+ const char *p=name;
+ while ((c=*p++)!=0)
+ {
+ switch(c)
+ {
+ case ':': break;
+ case '<': result+="_lt"; break;
+ case '>': result+="_gt"; break;
+ case '*': result+="_ast"; break;
+ case '&': result+="_amp"; break;
+ case ' ': break;
+ default:
+ if (caseSensitiveNames)
+ result+=c;
+ else
+ result+=tolower(c);
+ break;
+ }
+ }
+ return result;
+}
diff --git a/src/definition.h b/src/definition.h
new file mode 100644
index 0000000..2dbee89
--- /dev/null
+++ b/src/definition.h
@@ -0,0 +1,64 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#ifndef DEFINITION_H
+#define DEFINITION_H
+
+#include <qstring.h>
+#include "config.h"
+
+/*! The common base class of all definitions. */
+class Definition
+{
+ public:
+ //! create a new definition
+ Definition(const char *name,const char *b=0,const char *d=0)
+ { n=name; brief=b; doc=d; }
+ //! destroys the definition
+ virtual ~Definition() {}
+ //! returns the name of the definition
+ QString name() const { return n; }
+ //! returns the detailed description of this definition
+ QString documentation() const { return doc; }
+ //! returns the brief description of this definition
+ QString briefDescription() const { return brief; }
+ //! sets a new name for the definition
+ void setName(const char *name) { n=name; }
+ //! sets the documentation of this definition
+ void setDocumentation(const char *d)
+ {
+ doc=d; doc=doc.stripWhiteSpace();
+ }
+ //! sets the brief description of this definition
+ void setBriefDescription(const char *b)
+ {
+ brief=b; brief=brief.stripWhiteSpace();
+ int bl=brief.length();
+ if (bl>0 && brief.at(bl-1)!='.' && brief.at(bl-1)!='!' &&
+ brief.at(bl-1)!='?') brief+='.';
+ }
+ //! returns TRUE iff the definition is documented
+ bool hasDocumentation()
+ { return !doc.isNull() || !brief.isNull() || extractAllFlag; }
+ QString nameToFile(const char *name);
+
+ private:
+ QString n; // name of the definition
+ QString brief; // brief description
+ QString doc; // detailed description
+};
+
+#endif
diff --git a/src/diagram.cpp b/src/diagram.cpp
new file mode 100644
index 0000000..0fd30a5
--- /dev/null
+++ b/src/diagram.cpp
@@ -0,0 +1,1236 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <qlist.h>
+#include <qstring.h>
+#include <qarray.h>
+#include <qtstream.h>
+#include <qfile.h>
+
+#include "diagram.h"
+#include "image.h"
+#include "classdef.h"
+#include "config.h"
+#include "message.h"
+#include "util.h"
+#include "latexgen.h"
+#include "htmlgen.h"
+
+//-----------------------------------------------------------------------------
+
+const uint maxTreeWidth = 8;
+const int gridWidth = 100;
+const int gridHeight = 100;
+
+const uint labelHorSpacing = 10; // horizontal distance between labels
+const uint labelVertSpacing = 32; // vertical distance between labels
+const uint labelHorMargin = 6; // horiz. spacing between label and box
+const uint fontHeight = 12; // height of a character
+
+//static QString escapeLatex(const char *s)
+//{
+// QString result;
+// char c;
+// while ((c=*s++))
+// {
+// if (c=='_') result+="\\_";
+// else result+=c;
+// }
+// return result;
+//}
+
+static uint protToMask(Protection p)
+{
+ switch(p)
+ {
+ case Public: return 0xffffffff;
+ case Protected: return 0xcccccccc;
+ case Private: return 0xaaaaaaaa;
+ }
+ return 0;
+}
+
+static uint protToColor(Protection p)
+{
+ switch(p)
+ {
+ case Public: return 6;
+ case Protected: return 5;
+ case Private: return 4;
+ }
+ return 0;
+}
+
+static QString protToString(Protection p)
+{
+ switch(p)
+ {
+ case Public: return "solid";
+ case Protected: return "dashed";
+ case Private: return "dotted";
+ }
+ return 0;
+}
+
+static uint virtToMask(Specifier p)
+{
+ switch(p)
+ {
+ case Normal: return 0xffffffff;
+ case Virtual: return 0xf0f0f0f0;
+ default: return 0;
+ }
+ return 0;
+}
+
+// pre: dil is not empty
+static Protection getMinProtectionLevel(DiagramItemList *dil)
+{
+ DiagramItem *di=dil->first();
+ Protection result=di->protection();
+ di=dil->next();
+ while (di)
+ {
+ Protection p=di->protection();
+ if (p!=result)
+ {
+ if (result==Protected && p==Public) result=p;
+ else if (result==Private) result=p;
+ }
+ di=dil->next();
+ }
+ return result;
+}
+
+static void writeBitmapBox(DiagramItem *di,Image *image,
+ int x,int y,int w,int h,bool firstRow,
+ bool hasDocs,bool children=FALSE)
+{
+ int colFill = hasDocs ? (firstRow ? 0 : 2) : 7;
+ int colBorder = (firstRow || !hasDocs) ? 1 : 3;
+ int l = stringLength(di->label());
+ uint mask=virtToMask(di->virtualness());
+ image->fillRect(x+1,y+1,w-2,h-2,colFill,mask);
+ image->drawRect(x,y,w,h,colBorder,mask);
+ image->writeString(x+(w-l)/2, y+(h-fontHeight)/2, di->label(),1);
+ if (children)
+ {
+ int i;
+ for (i=0;i<5;i++)
+ image->drawHorzLine(y+h+i-6,x+w-2-i,x+w-2,firstRow?1:3,0xffffffff);
+ }
+}
+
+static void writeVectorBox(QTextStream &t,DiagramItem *di,
+ float x,float y,bool children=FALSE)
+{
+ if (di->virtualness()==Virtual) t << "dashed\n";
+ t << " (" << di->label() << ") " << x << " " << y << " box\n";
+ if (children) t << x << " " << y << " mark\n";
+ if (di->virtualness()==Virtual) t << "solid\n";
+}
+
+static void writeMapArea(QTextStream &t,ClassDef *cd,int x,int y,int w,int h)
+{
+ if (cd->hasDocumentation() || cd->isReference())
+ {
+ t << "<area ";
+ if (cd->getReference()) t << "doxygen=\"" << cd->getReference() << ":\" ";
+ t << "href=\"" << cd->classFile() << ".html\" ";
+ t << "ALT=\"" << cd->name();
+ t << "\" shape=\"rect\" coords=\"" << x << "," << y << ",";
+ t << x+w << "," << y+h << "\">" << endl;
+ }
+}
+//-----------------------------------------------------------------------------
+
+DiagramItem::DiagramItem(DiagramItem *p,int number,ClassDef *cd,
+ Protection pr,Specifier vi,const char *ts)
+{
+ parent=p;
+ x=y=0;
+ //name=n;
+ num=number;
+ children = new DiagramItemList;
+ prot=pr;
+ virt=vi;
+ inList=FALSE;
+ classDef=cd;
+ templSpec=ts;
+}
+
+DiagramItem::~DiagramItem()
+{
+ delete children;
+}
+
+QString DiagramItem::label() const
+{
+ return classDef->name()+templSpec;
+}
+
+QString DiagramItem::fileName() const
+{
+ return classDef->classFile();
+}
+
+int DiagramItem::avgChildPos() const
+{
+ DiagramItem *di;
+ int c=children->count();
+ if (c==0) // no children -> don't move
+ return xPos();
+ if ((di=children->getFirst())->isInList()) // children should be in a list
+ return di->xPos();
+ if (c&1) // odd number of children -> get pos of middle child
+ return children->at(c/2)->xPos();
+ else // even number of children -> get middle of most middle children
+ return (children->at(c/2-1)->xPos()+children->at(c/2)->xPos())/2;
+}
+
+int DiagramItem::numChildren() const
+{
+ return children->count();
+}
+
+void DiagramItem::addChild(DiagramItem *di)
+{
+ children->append(di);
+}
+
+void DiagramRow::insertClass(DiagramItem *parent,ClassDef *cd,bool doBases,
+ Protection prot,Specifier virt,const char *ts)
+{
+ DiagramItem *di=new DiagramItem(parent, diagram->at(level)->count(),
+ cd,prot,virt,ts);
+ if (parent) parent->addChild(di);
+ di->move(count()*gridWidth,level*gridHeight);
+ append(di);
+ BaseClassList *bcl=doBases ? cd->baseClasses() : cd->superClasses();
+ /* there are base/super classes */
+ int count=0;
+ BaseClassDef *bcd=bcl->first();
+ while (bcd)
+ {
+ ClassDef *ccd=bcd->classDef;
+ if (ccd && ccd->isVisibleExt()
+ //(ccd->protection()!=Private || extractPrivateFlag) &&
+ //(ccd->hasDocumentation() || !hideClassFlag)
+ ) count++;
+ bcd=bcl->next();
+ }
+ if (count>0 && (prot!=Private || !doBases))
+ {
+ DiagramRow *row=0;
+ if (diagram->count()<=level+1) /* add new row */
+ {
+ row = new DiagramRow(diagram,level+1);
+ diagram->append(row);
+ }
+ else /* get next row */
+ {
+ row=diagram->at(level+1);
+ }
+ /* insert base classes in the next row */
+ BaseClassDef *bcd=bcl->last();
+ while (bcd)
+ {
+ ClassDef *ccd=bcd->classDef;
+ if (ccd && ccd->isVisibleExt()
+ //(ccd->protection()!=Private || extractPrivateFlag) &&
+ //(ccd->hasDocumentation() || !hideClassFlag)
+ )
+ {
+ row->insertClass(di,ccd,doBases,bcd->prot,
+ doBases?bcd->virt:Normal,
+ doBases?bcd->templSpecifiers.data():"");
+ }
+ bcd=bcl->prev();
+ }
+ }
+}
+
+TreeDiagram::TreeDiagram(ClassDef *root,bool doBases)
+{
+ setAutoDelete(TRUE);
+ DiagramRow *row=new DiagramRow(this,0);
+ append(row);
+ row->insertClass(0,root,doBases,Public,Normal,0);
+}
+
+TreeDiagram::~TreeDiagram()
+{
+}
+
+
+void TreeDiagram::moveChildren(DiagramItem *root,int dx)
+{
+ DiagramItemList *dil=root->getChildren();
+ DiagramItem *di=dil->first();
+ while (di)
+ {
+ di->move(dx,0);
+ moveChildren(di,dx);
+ di=dil->next();
+ }
+}
+
+bool TreeDiagram::layoutTree(DiagramItem *root,int r)
+{
+ bool moved=FALSE;
+ //printf("layoutTree(%s,%d)\n",root->label().data(),r);
+
+ DiagramItemList *dil=root->getChildren();
+ if (dil->count()>0)
+ {
+ uint k;
+ int pPos=root->xPos();
+ int cPos=root->avgChildPos();
+ if (pPos>cPos) // move children
+ {
+ DiagramRow *row=at(r+1);
+ //printf("Moving children %d-%d in row %d\n",
+ // dil->getFirst()->number(),row->count()-1,r+1);
+ for (k=dil->getFirst()->number();k<row->count();k++)
+ row->at(k)->move(pPos-cPos,0);
+ moved=TRUE;
+ }
+ else if (pPos<cPos) // move parent
+ {
+ DiagramRow *row=at(r);
+ //printf("Moving parents %d-%d in row %d\n",
+ // root->number(),row->count()-1,r);
+ for (k=root->number();k<row->count();k++)
+ row->at(k)->move(cPos-pPos,0);
+ moved=TRUE;
+ }
+
+ // recurse to children
+ DiagramItem *di=dil->first();
+ while (di && !moved && !di->isInList())
+ {
+ moved = moved || layoutTree(di,r+1);
+ di=dil->next();
+ }
+ }
+ return moved;
+}
+
+void TreeDiagram::computeLayout()
+{
+ DiagramRow *row=first();
+ while (row && row->count()<maxTreeWidth) row=next();
+ if (row)
+ {
+ //printf("computeLayout() list row at %d\n",row->number());
+ DiagramItem *di=row->first();
+ DiagramItem *opi=0;
+ int delta=0;
+ bool first=TRUE;
+ while (di)
+ {
+ DiagramItem *pi=di->parentItem();
+ if (pi==opi && !first) { delta-=gridWidth; }
+ first = pi!=opi;
+ opi=pi;
+ di->move(delta,0); // collapse all items in the same
+ // list (except the first)
+ di->putInList();
+ di=row->next();
+ }
+ }
+
+ // re-organize the diagram items
+ DiagramItem *root=getFirst()->getFirst();
+ while (layoutTree(root,0));
+
+ // move first items of the lists
+ if (row)
+ {
+ DiagramItem *di=row->first();
+ while (di)
+ {
+ DiagramItem *pi=di->parentItem();
+ if (pi->getChildren()->count()>1)
+ {
+ di->move(gridWidth,0);
+ while (di && di->parentItem()==pi) di=row->next();
+ }
+ else
+ {
+ di=row->next();
+ }
+ }
+ }
+}
+
+uint TreeDiagram::computeRows()
+{
+ //printf("TreeDiagram::computeRows()=%d\n",count());
+ int count=0;
+ DiagramRow *row=first();
+ while (row && !row->getFirst()->isInList())
+ {
+ count++;
+ row=next();
+ }
+ //printf("count=%d row=%p\n",count,row);
+ if (row)
+ {
+ int maxListLen=0;
+ int curListLen=0;
+ DiagramItem *di=row->first(),*opi=0;
+ while (di)
+ {
+ if (di->parentItem()!=opi) curListLen=1; else curListLen++;
+ if (curListLen>maxListLen) maxListLen=curListLen;
+ opi=di->parentItem();
+ di=row->next();
+ }
+ //printf("maxListLen=%d\n",maxListLen);
+ count+=maxListLen;
+ }
+ return count;
+}
+
+#if 0
+uint TreeDiagram::computeCols()
+{
+ uint count=0;
+ DiagramRow *row=first();
+ while (row && !row->getFirst()->isInList())
+ {
+ if (row->count()>count) count=row->count();
+ row=next();
+ }
+ if (row)
+ {
+ row=prev();
+ uint cols=row->count();
+ if (row->getLast()->getChildren()->count()>1) cols++;
+ if (cols>count) count=cols;
+ }
+ return count;
+};
+#endif
+
+void TreeDiagram::computeExtremes(uint *maxLabelLen,uint *maxXPos)
+{
+ uint ml=0,mx=0;
+ DiagramRow *dr=first();
+ bool done=FALSE;
+ while (dr && !done)
+ {
+ DiagramItem *di=dr->first();
+ while (di)
+ {
+ if (di->isInList()) done=TRUE;
+ if (maxXPos) mx=QMAX(mx,(uint)di->xPos());
+ if (maxLabelLen) ml=QMAX(ml,stringLength(di->label()));
+ di=dr->next();
+ }
+ dr=next();
+ }
+ if (maxLabelLen) *maxLabelLen=ml;
+ if (maxXPos) *maxXPos=mx;
+}
+
+void TreeDiagram::drawBoxes(QTextStream &t,Image *image,
+ bool doBase,bool bitmap,
+ uint baseRows,uint superRows,
+ uint cellWidth,uint cellHeight)
+{
+ DiagramRow *dr=first();
+ if (!doBase) dr=next();
+ bool done=FALSE;
+ bool firstRow = doBase;
+ while (dr && !done)
+ {
+ int x=0,y=0;
+ float xf=0.0,yf=0.0;
+ DiagramItem *di=dr->first();
+ if (di->isInList()) // put boxes in a list
+ {
+ DiagramItem *opi=0;
+ if (doBase) di=dr->last();
+ while (di)
+ {
+ if (di->parentItem()==opi)
+ {
+ if (bitmap)
+ {
+ if (doBase) y -= cellHeight+labelVertSpacing;
+ else y += cellHeight+labelVertSpacing;
+ }
+ else
+ {
+ if (doBase) yf += 1.0;
+ else yf -= 1.0;
+ }
+ }
+ else
+ {
+ if (bitmap)
+ {
+ x = di->xPos()*(cellWidth+labelHorSpacing)/gridWidth;
+ if (doBase)
+ {
+ y = image->getHeight()-
+ superRows*cellHeight-
+ (superRows-1)*labelVertSpacing-
+ di->yPos()*(cellHeight+labelVertSpacing)/gridHeight;
+ }
+ else
+ {
+ y = (baseRows-1)*(cellHeight+labelVertSpacing)+
+ di->yPos()*(cellHeight+labelVertSpacing)/gridHeight;
+ }
+ }
+ else
+ {
+ xf = di->xPos()/(float)gridWidth;
+ if (doBase)
+ {
+ yf = di->yPos()/(float)gridHeight+superRows-1;
+ }
+ else
+ {
+ yf = superRows-1-di->yPos()/(float)gridHeight;
+ }
+ }
+ }
+ opi=di->parentItem();
+
+ if (bitmap)
+ {
+ bool hasDocs=di->getClassDef()->hasDocumentation() ||
+ di->getClassDef()->isReference();
+ writeBitmapBox(di,image,x,y,cellWidth,cellHeight,firstRow,
+ hasDocs,di->getChildren()->count()>0);
+ if (!firstRow) writeMapArea(t,di->getClassDef(),x,y,cellWidth,cellHeight);
+ }
+ else
+ {
+ writeVectorBox(t,di,xf,yf,di->getChildren()->count()>0);
+ }
+
+ if (doBase) di=dr->prev(); else di=dr->next();
+ }
+ done=TRUE;
+ }
+ else // draw a tree of boxes
+ {
+ while (di)
+ {
+ if (bitmap)
+ {
+ x = di->xPos()*(cellWidth+labelHorSpacing)/gridWidth;
+ if (doBase)
+ {
+ y = image->getHeight()-
+ superRows*cellHeight-
+ (superRows-1)*labelVertSpacing-
+ di->yPos()*(cellHeight+labelVertSpacing)/gridHeight;
+ }
+ else
+ {
+ y = (baseRows-1)*(cellHeight+labelVertSpacing)+
+ di->yPos()*(cellHeight+labelVertSpacing)/gridHeight;
+ }
+ bool hasDocs=di->getClassDef()->hasDocumentation() ||
+ di->getClassDef()->isReference();
+ writeBitmapBox(di,image,x,y,cellWidth,cellHeight,firstRow,hasDocs);
+ if (!firstRow) writeMapArea(t,di->getClassDef(),x,y,cellWidth,cellHeight);
+ }
+ else
+ {
+ xf=di->xPos()/(float)gridWidth;
+ if (doBase)
+ {
+ yf = di->yPos()/(float)gridHeight+superRows-1;
+ }
+ else
+ {
+ yf = superRows-1-di->yPos()/(float)gridHeight;
+ }
+ writeVectorBox(t,di,xf,yf);
+ }
+
+ di=dr->next();
+ }
+ }
+ dr=next();
+ firstRow=FALSE;
+ }
+}
+
+void TreeDiagram::drawConnectors(QTextStream &t,Image *image,
+ bool doBase,bool bitmap,
+ uint baseRows,uint superRows,
+ uint cellWidth,uint cellHeight)
+{
+ DiagramRow *dr=first();
+ bool done=FALSE;
+ while (dr && !done) // for each row
+ {
+ DiagramItem *di=dr->first();
+ if (di->isInList()) // row consists of list connectors
+ {
+ int x=0,y=0,ys=0;
+ float xf=0.0,yf=0.0,ysf=0.0;
+ while (di)
+ {
+ DiagramItem *pi=di->parentItem();
+ DiagramItemList *dil=pi->getChildren();
+ DiagramItem *last=dil->getLast();
+ if (di==last) // single child
+ {
+ if (bitmap) // draw pixels
+ {
+ x = di->xPos()*(cellWidth+labelHorSpacing)/gridWidth + cellWidth/2;
+ if (doBase) // base classes
+ {
+ y = image->getHeight()-
+ (superRows-1)*(cellHeight+labelVertSpacing)-
+ di->yPos()*(cellHeight+labelVertSpacing)/gridHeight;
+ image->drawVertArrow(x,y,y+labelVertSpacing/2,
+ protToColor(di->protection()),
+ protToMask(di->protection()));
+ }
+ else // super classes
+ {
+ y = (baseRows-1)*(cellHeight+labelVertSpacing)-
+ labelVertSpacing/2+
+ di->yPos()*(cellHeight+labelVertSpacing)/gridHeight;
+ image->drawVertLine(x,y,y+labelVertSpacing/2,
+ protToColor(di->protection()),
+ protToMask(di->protection()));
+ }
+ }
+ else // draw vectors
+ {
+ t << protToString(di->protection()) << endl;
+ if (doBase)
+ {
+ t << "1 " << di->xPos()/(float)gridWidth << " "
+ << di->yPos()/(float)gridHeight+superRows-1 << " in\n";
+ }
+ else
+ {
+ t << "0 " << di->xPos()/(float)gridWidth << " "
+ << (float)superRows-0.25-di->yPos()/(float)gridHeight
+ << " in\n";
+ }
+ }
+ }
+ else // multiple children, put them in a vertical list
+ {
+ if (bitmap)
+ {
+ x = di->parentItem()->xPos()*
+ (cellWidth+labelHorSpacing)/gridWidth+cellWidth/2;
+ if (doBase) // base classes
+ {
+ ys = image->getHeight()-
+ (superRows-1)*(cellHeight+labelVertSpacing)-
+ di->yPos()*(cellHeight+labelVertSpacing)/gridHeight;
+ y = ys - cellHeight/2;
+ }
+ else // super classes
+ {
+ ys = (baseRows-1)*(cellHeight+labelVertSpacing)+
+ di->yPos()*(cellHeight+labelVertSpacing)/gridHeight;
+ y = ys + cellHeight/2;
+ }
+ }
+ else
+ {
+ xf = di->parentItem()->xPos()/(float)gridWidth;
+ if (doBase)
+ {
+ ysf = di->yPos()/(float)gridHeight+superRows-1;
+ yf = ysf + 0.5;
+ }
+ else
+ {
+ ysf = (float)superRows-0.25-di->yPos()/(float)gridHeight;
+ yf = ysf - 0.25;
+ }
+ }
+ while (di!=last) // more children to add
+ {
+ if (bitmap)
+ {
+ if (doBase) // base classes
+ {
+ image->drawHorzArrow(y,x,x+cellWidth/2+labelHorSpacing,
+ protToColor(di->protection()),
+ protToMask(di->protection()));
+ y -= cellHeight+labelVertSpacing;
+ }
+ else // super classes
+ {
+ image->drawHorzLine(y,x,x+cellWidth/2+labelHorSpacing,
+ protToColor(di->protection()),
+ protToMask(di->protection()));
+ y += cellHeight+labelVertSpacing;
+ }
+ }
+ else
+ {
+ t << protToString(di->protection()) << endl;
+ if (doBase)
+ {
+ t << "1 " << xf << " " << yf << " hedge\n";
+ yf += 1.0;
+ }
+ else
+ {
+ t << "0 " << xf << " " << yf << " hedge\n";
+ yf -= 1.0;
+ }
+ }
+ di=dr->next();
+ }
+ // add last horizonal line and a vertical connection line
+ if (bitmap)
+ {
+ if (doBase) // base classes
+ {
+ image->drawHorzArrow(y,x,x+cellWidth/2+labelHorSpacing,
+ protToColor(di->protection()),
+ protToMask(di->protection()));
+ image->drawVertLine(x,y,ys+labelVertSpacing/2,
+ protToColor(getMinProtectionLevel(dil)),
+ protToMask(getMinProtectionLevel(dil)));
+ }
+ else // super classes
+ {
+ image->drawHorzLine(y,x,x+cellWidth/2+labelHorSpacing,
+ protToColor(di->protection()),
+ protToMask(di->protection()));
+ image->drawVertLine(x,ys-labelVertSpacing/2,y,
+ protToColor(getMinProtectionLevel(dil)),
+ protToMask(getMinProtectionLevel(dil)));
+ }
+ }
+ else
+ {
+ t << protToString(di->protection()) << endl;
+ if (doBase)
+ {
+ t << "1 " << xf << " " << yf << " hedge\n";
+ }
+ else
+ {
+ t << "0 " << xf << " " << yf << " hedge\n";
+ }
+ t << protToString(getMinProtectionLevel(dil)) << endl;
+ if (doBase)
+ {
+ t << xf << " " << ysf << " " << yf << " vedge\n";
+ }
+ else
+ {
+ t << xf << " " << ysf + 0.25 << " " << yf << " vedge\n";
+ }
+ }
+ }
+ di=dr->next();
+ }
+ done=TRUE; // the tree is drawn now
+ }
+ else // normal tree connector
+ {
+ while (di)
+ {
+ int x=0,y=0;
+ DiagramItemList *dil = di->getChildren();
+ DiagramItem *parent = di->parentItem();
+ if (parent) // item has a parent -> connect to it
+ {
+ if (bitmap) // draw pixels
+ {
+ x = di->xPos()*(cellWidth+labelHorSpacing)/gridWidth + cellWidth/2;
+ if (doBase) // base classes
+ {
+ y = image->getHeight()-
+ (superRows-1)*(cellHeight+labelVertSpacing)-
+ di->yPos()*(cellHeight+labelVertSpacing)/gridHeight;
+ /* write input line */
+ image->drawVertArrow(x,y,y+labelVertSpacing/2,
+ protToColor(di->protection()),
+ protToMask(di->protection()));
+ }
+ else // super classes
+ {
+ y = (baseRows-1)*(cellHeight+labelVertSpacing)-
+ labelVertSpacing/2+
+ di->yPos()*(cellHeight+labelVertSpacing)/gridHeight;
+ /* write output line */
+ image->drawVertLine(x,y,y+labelVertSpacing/2,
+ protToColor(di->protection()),
+ protToMask(di->protection()));
+ }
+ }
+ else // draw pixels
+ {
+ t << protToString(di->protection()) << endl;
+ if (doBase)
+ {
+ t << "1 " << di->xPos()/(float)gridWidth << " "
+ << di->yPos()/(float)gridHeight+superRows-1 << " in\n";
+ }
+ else
+ {
+ t << "0 " << di->xPos()/(float)gridWidth << " "
+ << (float)superRows-0.25-di->yPos()/(float)gridHeight
+ << " in\n";
+ }
+ }
+ }
+ if (dil->count()>0)
+ {
+ Protection p=getMinProtectionLevel(dil);
+ uint mask=protToMask(p);
+ uint col=protToColor(p);
+ if (bitmap)
+ {
+ x = di->xPos()*(cellWidth+labelHorSpacing)/gridWidth + cellWidth/2;
+ if (doBase) // base classes
+ {
+ y = image->getHeight()-
+ (superRows-1)*(cellHeight+labelVertSpacing)-
+ cellHeight-labelVertSpacing/2-
+ di->yPos()*(cellHeight+labelVertSpacing)/gridHeight;
+ image->drawVertLine(x,y,y+labelVertSpacing/2-1,col,mask);
+ }
+ else // super classes
+ {
+ y = (baseRows-1)*(cellHeight+labelVertSpacing)+
+ cellHeight+
+ di->yPos()*(cellHeight+labelVertSpacing)/gridHeight;
+ image->drawVertArrow(x,y,y+labelVertSpacing/2-1,col,mask);
+ }
+ }
+ else
+ {
+ t << protToString(p) << endl;
+ if (doBase)
+ {
+ t << "0 " << di->xPos()/(float)gridWidth << " "
+ << di->yPos()/(float)gridHeight+superRows-1 << " out\n";
+ }
+ else
+ {
+ t << "1 " << di->xPos()/(float)gridWidth << " "
+ << (float)superRows-1.75-di->yPos()/(float)gridHeight
+ << " out\n";
+ }
+ }
+ /* write input line */
+ DiagramItem *first = dil->first();
+ DiagramItem *last = dil->last();
+ if (first!=last && !first->isInList()) /* connect with all base classes */
+ {
+ if (bitmap)
+ {
+ int xs = first->xPos()*(cellWidth+labelHorSpacing)/gridWidth
+ + cellWidth/2;
+ int xe = last->xPos()*(cellWidth+labelHorSpacing)/gridWidth
+ + cellWidth/2;
+ if (doBase) // base classes
+ {
+ image->drawHorzLine(y,xs,xe,col,mask);
+ }
+ else // super classes
+ {
+ image->drawHorzLine(y+labelVertSpacing/2,xs,xe,col,mask);
+ }
+ }
+ else
+ {
+ t << protToString(p) << endl;
+ if (doBase)
+ {
+ t << first->xPos()/(float)gridWidth << " "
+ << last->xPos()/(float)gridWidth << " "
+ << first->yPos()/(float)gridHeight+superRows-1
+ << " conn\n";
+ }
+ else
+ {
+ t << first->xPos()/(float)gridWidth << " "
+ << last->xPos()/(float)gridWidth << " "
+ << (float)superRows-first->yPos()/(float)gridHeight
+ << " conn\n";
+ }
+ }
+ }
+ }
+ di=dr->next();
+ }
+ dr=next();
+ }
+ }
+}
+
+ClassDiagram::ClassDiagram(ClassDef *root)
+{
+ base = new TreeDiagram(root,TRUE);
+ base->computeLayout();
+ super = new TreeDiagram(root,FALSE);
+ super->computeLayout();
+ DiagramItem *baseItem = base->first()->first();
+ DiagramItem *superItem = super->first()->first();
+ int xbase = baseItem->xPos();
+ int xsuper = superItem->xPos();
+ if (xbase>xsuper)
+ {
+ superItem->move(xbase-xsuper,0);
+ super->moveChildren(superItem,xbase-xsuper);
+ }
+ else if (xbase<xsuper)
+ {
+ baseItem->move(xsuper-xbase,0);
+ base->moveChildren(baseItem,xsuper-xbase);
+ }
+}
+
+ClassDiagram::~ClassDiagram()
+{
+ delete base;
+ delete super;
+}
+
+void ClassDiagram::writeFigure(QTextStream &output,const char *path,
+ const char *fileName)
+{
+ uint baseRows=base->computeRows();
+ uint superRows=super->computeRows();
+ uint baseMaxX, baseMaxLabelWidth, superMaxX, superMaxLabelWidth;
+ base->computeExtremes(&baseMaxLabelWidth,&baseMaxX);
+ super->computeExtremes(&superMaxLabelWidth,&superMaxX);
+
+ uint rows=baseRows+superRows-1;
+ uint cols=(QMAX(baseMaxX,superMaxX)+gridWidth*2-1)/gridWidth;
+
+ // Estimate the image aspect width and height in pixels.
+ uint estHeight = rows*40;
+ uint estWidth = cols*(20+QMAX(baseMaxLabelWidth,superMaxLabelWidth));
+ //printf("Estimated size %d x %d\n",estWidth,estHeight);
+
+ const float pageWidth = 14.0; // estimated page width in cm.
+ // Somewhat lower to deal with estimation
+ // errors.
+
+ // compute the image height in centimeters based on the estimates
+ float realHeight = QMIN(rows,12); // real height in cm
+ float realWidth = realHeight * estWidth/(float)estHeight;
+ if (realWidth>pageWidth) // assume that the page width is about 15 cm
+ {
+ realHeight*=pageWidth/realWidth;
+ realWidth=pageWidth;
+ }
+
+ output << "}\n"
+ "\\begin{figure}[H]\n"
+ "\\begin{center}\n"
+ "\\leavevmode\n";
+ output << "\\setlength{\\epsfysize}{" << realHeight << "cm}\n";
+ output << "\\epsfbox{" << fileName << ".eps}\n"
+ "\\end{center}\n"
+ "\\end{figure}\n";
+
+ //printf("writeFigure rows=%d cols=%d\n",rows,cols);
+
+ QFile f1((QString)path+"/"+fileName+".eps");
+ if (!f1.open(IO_WriteOnly))
+ {
+ err("Could not open file %s for writing\n",f1.name());
+ exit(1);
+ }
+ QTextStream t(&f1);
+
+ //printf("writeEPS() rows=%d cols=%d\n",rows,cols);
+
+ // generate EPS header and postscipt variables and procedures
+
+ t << "%!PS-Adobe-2.0 EPSF-2.0\n";
+ t << "%%Title: ClassName\n";
+ t << "%%Creator: Doxygen\n";
+ t << "%%CreationDate: Time\n";
+ t << "%%For: \n";
+ t << "%Magnification: 1.00\n";
+ t << "%%Orientation: Portrait\n";
+ t << "%%BoundingBox: 0 0 500 " << estHeight*500.0/(float)estWidth << "\n";
+ t << "%%Pages: 0\n";
+ t << "%%BeginSetup\n";
+ t << "%%EndSetup\n";
+ t << "%%EndComments\n";
+ t << "\n";
+ t << "% ----- variables -----\n";
+ t << "\n";
+ t << "/boxwidth 0 def\n";
+ t << "/boxheight 40 def\n";
+ t << "/fontheight 24 def\n";
+ t << "/marginwidth 10 def\n";
+ t << "/distx 20 def\n";
+ t << "/disty 40 def\n";
+ t << "/boundaspect " << estWidth/(float)estHeight << " def % aspect ratio of the BoundingBox (width/height)\n";
+ t << "/boundx 500 def\n";
+ t << "/boundy boundx boundaspect div def\n";
+ t << "/xspacing 0 def\n";
+ t << "/yspacing 0 def\n";
+ t << "/rows " << rows << " def\n";
+ t << "/cols " << cols << " def\n";
+ t << "/scalefactor 0 def\n";
+ t << "/boxfont /Times-Roman findfont fontheight scalefont def\n";
+ t << "\n";
+ t << "% ----- procedures -----\n";
+ t << "\n";
+ t << "/dotted { [1 4] 0 setdash } def\n";
+ t << "/dashed { [5] 0 setdash } def\n";
+ t << "/solid { [] 0 setdash } def\n";
+ t << "\n";
+ t << "/max % result = MAX(arg1,arg2)\n";
+ t << "{\n";
+ t << " /a exch def\n";
+ t << " /b exch def\n";
+ t << " a b gt {a} {b} ifelse\n";
+ t << "} def\n";
+ t << "\n";
+ t << "/xoffset % result = MAX(0,(scalefactor-(boxwidth*cols+distx*(cols-1)))/2)\n";
+ t << "{\n";
+ t << " 0 scalefactor boxwidth cols mul distx cols 1 sub mul add sub 2 div max\n";
+ t << "} def\n";
+ t << "\n";
+ t << "/cw % boxwidth = MAX(boxwidth, stringwidth(arg1))\n";
+ t << "{\n";
+ t << " /str exch def\n";
+ t << " /boxwidth boxwidth str stringwidth pop max def\n";
+ t << "} def\n";
+ t << "\n";
+ t << "/box % draws a box with text `arg1' at grid pos (arg2,arg3)\n";
+ t << "{ gsave\n";
+ t << " 2 setlinewidth\n";
+ t << " newpath\n";
+ t << " exch xspacing mul xoffset add\n";
+ t << " exch yspacing mul\n";
+ t << " moveto\n";
+ t << " boxwidth 0 rlineto \n";
+ t << " 0 boxheight rlineto \n";
+ t << " boxwidth neg 0 rlineto \n";
+ t << " 0 boxheight neg rlineto \n";
+ t << " closepath\n";
+ t << " dup stringwidth pop neg boxwidth add 2 div\n";
+ t << " boxheight fontheight 2 div sub 2 div\n";
+ t << " rmoveto show stroke\n";
+ t << " grestore\n";
+ t << "} def \n";
+ t << "\n";
+ t << "/mark\n";
+ t << "{ newpath\n";
+ t << " exch xspacing mul xoffset add boxwidth add\n";
+ t << " exch yspacing mul\n";
+ t << " moveto\n";
+ t << " 0 boxheight 4 div rlineto\n";
+ t << " boxheight neg 4 div boxheight neg 4 div rlineto\n";
+ t << " closepath\n";
+ t << " eofill\n";
+ t << " stroke\n";
+ t << "} def\n";
+ t << "\n";
+ t << "/arrow\n";
+ t << "{ newpath\n";
+ t << " moveto\n";
+ t << " 3 -8 rlineto\n";
+ t << " -6 0 rlineto\n";
+ t << " 3 8 rlineto\n";
+ t << " closepath\n";
+ t << " eofill\n";
+ t << " stroke\n";
+ t << "} def\n";
+ t << "\n";
+ t << "/out % draws an output connector for the block at (arg1,arg2)\n";
+ t << "{\n";
+ t << " newpath\n";
+ t << " exch xspacing mul xoffset add boxwidth 2 div add\n";
+ t << " exch yspacing mul boxheight add\n";
+ t << " /y exch def\n";
+ t << " /x exch def\n";
+ t << " x y moveto\n";
+ t << " 0 disty 2 div rlineto \n";
+ t << " stroke\n";
+ t << " 1 eq { x y disty 2 div add arrow } if\n";
+ t << "} def\n";
+ t << "\n";
+ t << "/in % draws an input connector for the block at (arg1,arg2)\n";
+ t << "{\n";
+ t << " newpath\n";
+ t << " exch xspacing mul xoffset add boxwidth 2 div add\n";
+ t << " exch yspacing mul disty 2 div sub\n";
+ t << " /y exch def\n";
+ t << " /x exch def\n";
+ t << " x y moveto\n";
+ t << " 0 disty 2 div rlineto\n";
+ t << " stroke\n";
+ t << " 1 eq { x y disty 2 div add arrow } if\n";
+ t << "} def\n";
+ t << "\n";
+ t << "/hedge\n";
+ t << "{\n";
+ t << " exch xspacing mul xoffset add boxwidth 2 div add\n";
+ t << " exch yspacing mul boxheight 2 div sub\n";
+ t << " /y exch def\n";
+ t << " /x exch def\n";
+ t << " newpath\n";
+ t << " x y moveto\n";
+ t << " boxwidth 2 div distx add 0 rlineto\n";
+ t << " stroke\n";
+ t << " 1 eq\n";
+ t << " { newpath x boxwidth 2 div distx add add y moveto\n";
+ t << " -8 3 rlineto\n";
+ t << " 0 -6 rlineto\n";
+ t << " 8 3 rlineto\n";
+ t << " closepath\n";
+ t << " eofill\n";
+ t << " stroke\n";
+ t << " } if\n";
+ t << "} def\n";
+ t << "\n";
+ t << "/vedge\n";
+ t << "{\n";
+ t << " /ye exch def\n";
+ t << " /ys exch def\n";
+ t << " /xs exch def\n";
+ t << " newpath\n";
+ t << " xs xspacing mul xoffset add boxwidth 2 div add dup\n";
+ t << " ys yspacing mul boxheight 2 div sub\n";
+ t << " moveto\n";
+ t << " ye yspacing mul boxheight 2 div sub\n";
+ t << " lineto\n";
+ t << " stroke\n";
+ t << "} def\n";
+ t << "\n";
+ t << "/conn % connections the blocks from col `arg1' to `arg2' of row `arg3'\n";
+ t << "{\n";
+ t << " /ys exch def\n";
+ t << " /xe exch def\n";
+ t << " /xs exch def\n";
+ t << " newpath\n";
+ t << " xs xspacing mul xoffset add boxwidth 2 div add\n";
+ t << " ys yspacing mul disty 2 div sub\n";
+ t << " moveto\n";
+ t << " xspacing xe xs sub mul 0\n";
+ t << " rlineto\n";
+ t << " stroke\n";
+ t << "} def\n";
+ t << "\n";
+ t << "% ----- main ------\n";
+ t << "\n";
+ t << "boxfont setfont\n";
+ t << "1 boundaspect scale\n";
+
+
+ bool done=FALSE;
+ DiagramRow *dr=base->first();
+ while (dr && !done)
+ {
+ DiagramItem *di=dr->first();
+ while (di)
+ {
+ done=di->isInList();
+ t << "(" << di->label() << ") cw\n";
+ di=dr->next();
+ }
+ dr=base->next();
+ }
+ dr=super->first();
+ dr=super->next();
+ done=FALSE;
+ while (dr && !done)
+ {
+ DiagramItem *di=dr->first();
+ while (di)
+ {
+ done=di->isInList();
+ t << "(" << di->label() << ") cw\n";
+ di=dr->next();
+ }
+ dr=super->next();
+ }
+
+ t << "/boxwidth boxwidth marginwidth 2 mul add def\n"
+ << "/xspacing boxwidth distx add def\n"
+ << "/yspacing boxheight disty add def\n"
+ << "/scalefactor \n"
+ << " boxwidth cols mul distx cols 1 sub mul add\n"
+ << " boxheight rows mul disty rows 1 sub mul add boundaspect mul \n"
+ << " max def\n"
+ << "boundx scalefactor div boundy scalefactor div scale\n";
+
+ t << "\n% ----- classes -----\n\n";
+ base->drawBoxes(t,0,TRUE,FALSE,baseRows,superRows,0,0);
+ super->drawBoxes(t,0,FALSE,FALSE,baseRows,superRows,0,0);
+
+ t << "\n% ----- relations -----\n\n";
+ base->drawConnectors(t,0,TRUE,FALSE,baseRows,superRows,0,0);
+ super->drawConnectors(t,0,FALSE,FALSE,baseRows,superRows,0,0);
+}
+
+
+void ClassDiagram::writeImageMap(QTextStream &t,const char *path,
+ const char *fileName)
+{
+ uint baseRows=base->computeRows();
+ uint superRows=super->computeRows();
+ uint rows=baseRows+superRows-1;
+
+// t << "<p>Class diagram for ";
+// HtmlGenerator::docifyStatic(t,name);
+// t << ".\n<p><center><img src=\""
+// << fileName << ".gif\" usemap=\"#" << name << "_map\""
+// << " border=\"0\"></center>" << endl
+// << "<map name=\"" << name << "_map\"><p>" << endl;
+
+ uint lb,ls,xb,xs;
+ base->computeExtremes(&lb,&xb);
+ super->computeExtremes(&ls,&xs);
+
+ uint cellWidth = QMAX(lb,ls)+labelHorMargin*2;
+ uint maxXPos = QMAX(xb,xs);
+ uint labelVertMargin = 6; //QMAX(6,(cellWidth-fontHeight)/6); // aspect at least 1:3
+ uint cellHeight = labelVertMargin*2+fontHeight;
+ uint imageWidth = (maxXPos+gridWidth)*cellWidth/gridWidth+
+ (maxXPos*labelHorSpacing)/gridWidth;
+ uint imageHeight = rows*cellHeight+(rows-1)*labelVertSpacing;
+
+ Image image(imageWidth,imageHeight);
+
+ base->drawBoxes(t,&image,TRUE,TRUE,baseRows,superRows,cellWidth,cellHeight);
+ super->drawBoxes(t,&image,FALSE,TRUE,baseRows,superRows,cellWidth,cellHeight);
+ base->drawConnectors(t,&image,TRUE,TRUE,baseRows,superRows,cellWidth,cellHeight);
+ super->drawConnectors(t,&image,FALSE,TRUE,baseRows,superRows,cellWidth,cellHeight);
+
+ image.save((QString)path+"/"+fileName+".gif");
+
+ t << "</MAP></P>" << endl;
+}
+
diff --git a/src/diagram.h b/src/diagram.h
new file mode 100644
index 0000000..5bc30f8
--- /dev/null
+++ b/src/diagram.h
@@ -0,0 +1,128 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#include "entry.h"
+
+class ClassDef;
+class DiagramRow;
+class TreeDiagram;
+class ClassDiagram;
+class DiagramItemList;
+class Image;
+
+class DiagramItem
+{
+ public:
+ DiagramItem(DiagramItem *p,int number,ClassDef *cd,
+ Protection prot,Specifier virt,const char *ts);
+ ~DiagramItem();
+ QString label() const;
+ QString fileName() const;
+ DiagramItem *parentItem() { return parent; }
+ DiagramItemList *getChildren() { return children; }
+ void move(int dx,int dy) { x+=dx; y+=dy; }
+ int xPos() const { return x; }
+ int yPos() const { return y; }
+ int avgChildPos() const;
+ int numChildren() const;
+ void addChild(DiagramItem *di);
+ int number() const { return num; }
+ Protection protection() const { return prot; }
+ Specifier virtualness() const { return virt; }
+ void putInList() { inList=TRUE; }
+ bool isInList() const { return inList; }
+ ClassDef *getClassDef() const { return classDef; }
+ private:
+ DiagramItemList *children;
+ DiagramItem *parent;
+ int x,y;
+ int num;
+ Protection prot;
+ Specifier virt;
+ QString templSpec;
+ bool inList;
+ ClassDef *classDef;
+};
+
+class DiagramItemList : public QList<DiagramItem>
+{
+ public:
+ DiagramItemList() : QList<DiagramItem>() {}
+ ~DiagramItemList() {}
+};
+
+class DiagramRow : public QList<DiagramItem>
+{
+ public:
+ DiagramRow(TreeDiagram *d,int l) : QList<DiagramItem>()
+ {
+ diagram=d;
+ level=l;
+ setAutoDelete(TRUE);
+ }
+ void insertClass(DiagramItem *parent,ClassDef *cd,bool doBases,
+ Protection prot,Specifier virt,const char *ts);
+ uint number() { return level; }
+ private:
+ TreeDiagram *diagram;
+ uint level;
+};
+
+class DiagramRowIterator : public QListIterator<DiagramRow>
+{
+ public:
+ DiagramRowIterator(const QList<DiagramRow> &d)
+ : QListIterator<DiagramRow>(d) {}
+};
+
+class TreeDiagram : public QList<DiagramRow>
+{
+ public:
+ TreeDiagram(ClassDef *root,bool doBases);
+ ~TreeDiagram();
+ void computeLayout();
+ uint computeRows();
+ //uint computeCols();
+ void moveChildren(DiagramItem *root,int dx);
+ void computeExtremes(uint *labelWidth,uint *xpos);
+ void drawBoxes(QTextStream &t,Image *image,
+ bool doBase,bool bitmap,
+ uint baseRows,uint superRows,
+ uint cellWidth,uint cellHeight);
+ void drawConnectors(QTextStream &t,Image *image,
+ bool doBase,bool bitmap,
+ uint baseRows,uint superRows,
+ uint cellWidth,uint cellheight);
+ private:
+ bool layoutTree(DiagramItem *root,int row);
+ TreeDiagram &operator=(const TreeDiagram &);
+ TreeDiagram(const TreeDiagram &);
+};
+
+class ClassDiagram
+{
+ public:
+ ClassDiagram(ClassDef *root);
+ ~ClassDiagram();
+ void writeFigure(QTextStream &t,const char *path,
+ const char *file);
+ void writeImageMap(QTextStream &t,const char *path,
+ const char *file);
+ private:
+ TreeDiagram *base;
+ TreeDiagram *super;
+};
diff --git a/src/doxygen.cpp b/src/doxygen.cpp
new file mode 100644
index 0000000..3d641ef
--- /dev/null
+++ b/src/doxygen.cpp
@@ -0,0 +1,3763 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#include <qstring.h>
+#include <qfileinf.h>
+#include <qfile.h>
+#include <qdir.h>
+#include <qdict.h>
+#include <qregexp.h>
+#include <qstrlist.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+
+#include "version.h"
+#include "doxygen.h"
+#include "scanner.h"
+#include "entry.h"
+#include "index.h"
+#include "logos.h"
+#include "instdox.h"
+#include "message.h"
+#include "code.h"
+#include "config.h"
+#include "util.h"
+#include "pre.h"
+#include "tag.h"
+
+#include "outputlist.h"
+#include "declinfo.h"
+#include "htmlgen.h"
+#include "latexgen.h"
+#include "mangen.h"
+#include "language.h"
+#include "debug.h"
+
+#if defined(_MSC_VER)
+#define popen _popen
+#endif
+
+
+// lists
+ClassList classList; // list of all documented classes
+NamespaceList namespaceList; // list of all namespaces
+PageList exampleList; // list of all example files
+PageList pageList; // list of all related documentation pages
+MemberNameList memberNameList; // list of class member + related functions
+MemberNameList functionNameList; // list of all unrelated functions
+FileNameList inputNameList; // list of all input files
+StringList inputFiles;
+FileList includeFiles;
+GroupList groupList; // list of all groups
+FormulaList formulaList; // list of all formulas
+
+// dictionaries
+PageDict pageDict(1009); // dictionary of all doc pages
+PageDict exampleDict(1009); // dictionary of all examples
+ClassDict classDict(1009); // dictionary of all documented classes
+NamespaceDict namespaceDict(257); // dictionary of all documented namespaces
+MemberNameDict memberNameDict(10007); // dictionary of all member names
+MemberNameDict functionNameDict(10007); // dictionary of all functions
+StringDict substituteDict(1009); // dictionary of class name substitutes
+SectionDict sectionDict(257); // dictionary of all page sections
+FileNameDict inputNameDict(1009); // dictionary of sections
+StringDict excludeNameDict(1009); // dictionary of sections
+FileNameDict includeNameDict(1009); // dictionary of include names
+FileNameDict exampleNameDict(1009); // dictionary of examples
+FileDict includeDict(1009); // dictionary of include files
+DefineDict defineDict(10007); // dictionary of all defines
+StringDict typedefDict(1009); // dictionary of all typedefs
+GroupDict groupDict(257); // dictionary of all groups
+FormulaDict formulaDict(1009); // dictionary of all formulas
+FormulaDict formulaNameDict(1009); // dictionary of the label name of all formulas
+
+OutputList *outputList; // list of output generating objects
+
+//bool unrelatedFunctionsUsed;
+
+//ClassDef unrelatedClass("nothing",ClassDef::Class);
+ // dummy class for unrelated functions
+
+int annotatedClasses;
+int hierarchyClasses;
+int documentedFunctions;
+int documentedMembers;
+int documentedFiles;
+int documentedGroups;
+int documentedNamespaces;
+
+QTextStream tagFile;
+
+void addMemberDocs(Entry *root,MemberDef *md, const char *funcDecl,
+ bool over_load);
+
+
+//----------------------------------------------------------------------
+// Returns the standard string that is generated when the \overload
+// command is used.
+
+const char *getOverloadDocs()
+{
+ return "This is an overloaded member function, "
+ "provided for convenience. It differs from the above "
+ "function only in what argument(s) it accepts.";
+}
+
+//----------------------------------------------------------------------------
+
+
+void buildGroupList(Entry *root)
+{
+ if (root->section==Entry::GROUPDOC_SEC && root->name.length()>0)
+ {
+ //printf("Found group %s title=`%s'\n",root->name.data(),root->type.data());
+
+ GroupDef *gd;
+
+ if ((gd=groupDict[root->name]))
+ {
+ warn("Warning: group %s already documented\n"
+ " skipping documentation in file %s at line %d\n",
+ root->name.data(),root->fileName.data(),root->startLine);
+ }
+ else
+ {
+ gd = new GroupDef(root->name,root->type);
+ gd->setBriefDescription(root->brief);
+ gd->setDocumentation(root->doc);
+ groupList.inSort(gd);
+ groupDict.insert(root->name,gd);
+ }
+ }
+ EntryListIterator eli(*root->sublist);
+ Entry *e;
+ for (;(e=eli.current());++eli)
+ {
+ buildGroupList(e);
+ }
+}
+
+//----------------------------------------------------------------------
+
+//void computeGroupRelations(Entry *root)
+//{
+// if (root->section==Entry::GROUPDOC_SEC && root->name.length()>0)
+// {
+// GroupDef *gd;
+//
+// if ((gd=groupDict[root->name]))
+// {
+// QListIterator<QString> sli(*root->groups);
+// QString *s;
+// for (;(s=sli.current());++sli)
+// {
+// GroupDef *pgd;
+// if (s->length()>0 && (pgd=groupDict[*s]))
+// {
+// pgd->addGroup(gd);
+// printf("Group %s: in group %s\n",gd->groupName(),s->data());
+// }
+// }
+// }
+// }
+// EntryListIterator eli(*root->sublist);
+// Entry *e;
+// for (;(e=eli.current());++eli)
+// {
+// computeGroupRelations(e);
+// }
+//}
+
+//----------------------------------------------------------------------
+
+void buildFileList(Entry *root)
+{
+ if (((root->section==Entry::FILEDOC_SEC) ||
+ ((root->section & Entry::FILE_MASK) && extractAllFlag)) &&
+ root->name.length()>0
+ )
+ {
+ bool ambig;
+ FileDef *fd=findFileDef(&inputNameDict,root->name,ambig);
+ if (fd && !ambig)
+ {
+ if ((root->doc.length()>0 && fd->documentation()) ||
+ (root->brief.length()>0 && fd->briefDescription()))
+ {
+ warn("Warning: file %s already documented\n"
+ " skipping documentation in file %s at line %d\n",
+ root->name.data(),root->fileName.data(),root->startLine);
+ }
+ else
+ {
+ fd->setDocumentation(root->doc);
+ fd->setBriefDescription(root->brief);
+ QListIterator<QString> sli(*root->groups);
+ QString *s;
+ for (;(s=sli.current());++sli)
+ {
+ GroupDef *gd=0;
+ if (s->length()>0 && (gd=groupDict[*s]))
+ {
+ gd->addFile(fd);
+ //printf("File %s: in group %s\n",fd->name().data(),s->data());
+ }
+ }
+ }
+ }
+ else
+ {
+ warn("Warning: the name `%s' supplied as "
+ "the second argument in the \\file statement in file "
+ "%s at line %d ",
+ root->name.data(),
+ root->fileName.data(),
+ root->startLine);
+ if (ambig) // name is ambigious
+ {
+ warn("matches the following input files:\n");
+ showFileDefMatches(&inputNameDict,root->name);
+ warn("Please use a more specific name by "
+ "including a (larger) part of the path!\n");
+ }
+ else // name is not an input file
+ warn("is not an input file\n");
+ }
+ }
+ EntryListIterator eli(*root->sublist);
+ Entry *e;
+ for (;(e=eli.current());++eli)
+ {
+ buildFileList(e);
+ }
+}
+
+void addIncludeFile(ClassDef *cd,FileDef *ifd,Entry *root)
+{
+ //printf(">>>>>> includeFile=%s\n",root->includeFile.data());
+
+ bool ambig;
+ FileDef *fd=0;
+ // see if we need to include a verbatim copy of the header file
+ if (!root->includeFile.isNull() &&
+ (fd=findFileDef(&inputNameDict,root->includeFile,ambig))==0
+ )
+ { // explicit request
+ warn("Warning: the name `%s' supplied as "
+ "the second argument in the \\class statement in file "
+ "%s at line %d ",
+ root->includeFile.data(),
+ root->fileName.data(),
+ root->startLine);
+ if (ambig) // name is ambigious
+ {
+ warn("matches the following input files:\n");
+ showFileDefMatches(&inputNameDict,root->includeFile);
+ warn("Please use a more specific name by "
+ "including a (larger) part of the path!\n");
+ }
+ else // name is not an input file
+ warn("is not an input file\n");
+ }
+ else if (root->includeFile.length()==0 &&
+ // see if the file extension makes sense
+ guessSection(root->includeFile)==Entry::HEADER_SEC)
+ { // implicit assumption
+ fd=ifd;
+ }
+
+ // if a file is found, we mark it for verbatim inclusion.
+ if (fd)
+ {
+ //printf("fd->name()=%s fd->absFilePath()=%s\n",fd->name().data(),
+ // fd->absFilePath().data());
+ // set include file definition
+ cd->setIncludeFile(fd);
+ // set include supplied name
+ cd->setIncludeName(root->includeName);
+ fd->setIncludeName((QString)cd->classFile()+"-include");
+ if (includeDict[fd->absFilePath()]==0) // include not inserted earlier
+ {
+ includeFiles.inSort(fd);
+ includeDict.insert(fd->absFilePath(),fd);
+ }
+ }
+}
+
+/*! Input is a scopeName, output is the scopename split into a
+ * namespace part (as large as possible) and a classname part.
+ */
+void extractNamespaceName(const QString &scopeName,
+ QString &className,QString &namespaceName)
+{
+ QString clName=scopeName.copy();
+ QString nsName;
+ if (clName.length()>0 && namespaceDict[clName])
+ { // the whole name is a namespace
+ namespaceName=clName.copy();
+ className.resize(0);
+ return;
+ }
+ int i,p=clName.length()-2;
+ while (p>=0 && (i=clName.findRev("::",p))!=-1)
+ // see if the first part is a namespace
+ {
+ if (i>0 && namespaceDict[clName.left(i)])
+ {
+ namespaceName=clName.left(i);
+ className=clName.right(clName.length()-i-2);
+ return;
+ }
+ p=i-2; // try a smaller piece of the scope
+ }
+ className=scopeName.copy();
+ namespaceName.resize(0);
+ return;
+}
+
+static bool addNamespace(Entry *root,ClassDef *cd)
+{
+ // see if this class is defined inside a namespace
+ if (root->section & Entry::COMPOUND_MASK)
+ {
+ Entry *e = root->parent;
+ while (e)
+ {
+ if (e->section==Entry::NAMESPACE_SEC)
+ {
+ NamespaceDef *nd=0;
+ if (!e->name.isEmpty() && (nd=namespaceDict[e->name]))
+ {
+ cd->setNamespace(nd);
+ nd->insertClass(cd);
+ return TRUE;
+ }
+ }
+ e=e->parent;
+ }
+ }
+ return FALSE;
+}
+
+//----------------------------------------------------------------------
+// build a list of all classes mentioned in the documentation
+// and all classes that have a documentation block before their definition.
+void buildClassList(Entry *root)
+{
+ if (
+ ((root->section & Entry::COMPOUNDDOC_MASK) ||
+ ((root->section & Entry::COMPOUND_MASK))) &&
+ root->name.length()>0
+ )
+ {
+ QString fullName=root->name.copy();
+ if (fullName.length()==0)
+ {
+ // this should not be called
+ warn("Warning: invalid class found in file %s at %d\n",
+ root->fileName.data(),root->startLine);
+ }
+ else
+ {
+ //QString className;
+ //QString namespaceName;
+ //extractNamespaceName(fullName,className,namespaceName);
+
+ //printf("Found class %s in %s at line %d\n",fullName.data(),
+ // root->fileName.data(),root->startLine);
+ // add class name substitution entry iff the class name is alterned by a
+ // define. This is needed to properly document Qt's template classes
+ // (although, it's quite general)
+ //if (resolveDefines(fullName)!=fullName)
+ //{
+ // substituteDict.insert(resolveDefines(fullName),new QString(fullName));
+ //}
+
+ bool ambig;
+ ClassDef *cd;
+ if ((cd=getClass(fullName)))
+ {
+ if (cd->templateArguments()==0)
+ {
+ //printf("existing ClassDef tempArgList=%p\n",root->tArgList);
+ cd->setTemplateArguments(root->tArgList);
+ }
+ if (root->doc.length()>0 || root->brief.length()>0) // block contains docs
+ {
+ if (cd->documentation()) // class already documented
+ {
+ warn("Warning: class %s already documented\n"
+ " skipping documentation in file %s at line %d\n",
+ fullName.data(),root->fileName.data(),root->startLine);
+ }
+ else // class not documented, use docs in block
+ {
+ cd->setDocumentation(root->doc);
+ cd->setBriefDescription(root->brief);
+ cd->setName(fullName); // change name to match docs
+ }
+ }
+ if (cd->includeFile()==0)
+ {
+ addIncludeFile(cd,
+ findFileDef(&inputNameDict,root->fileName,ambig),
+ root
+ );
+ }
+ addNamespace(root,cd);
+ }
+ else if (fullName[0]!='@' /* &&
+ (root->doc.length()>0 ||
+ root->brief.length()>0 ||
+ extractAllFlag
+ )*/
+ )
+ // new class
+ {
+ int sec=ClassDef::Class;
+ switch(root->section)
+ {
+ case Entry::UNION_SEC:
+ case Entry::UNIONDOC_SEC:
+ sec=ClassDef::Union; break;
+ case Entry::STRUCT_SEC:
+ case Entry::STRUCTDOC_SEC:
+ sec=ClassDef::Struct; break;
+ }
+ ClassDef *cd=new ClassDef(fullName,sec);
+ cd->setDocumentation(root->doc); // copy docs to definition
+ cd->setBriefDescription(root->brief);
+ //printf("new ClassDef tempArgList=%p\n",root->tArgList);
+ cd->setTemplateArguments(root->tArgList);
+ cd->setProtection(root->protection);
+
+ QListIterator<QString> sli(*root->groups);
+ QString *s;
+ for (;(s=sli.current());++sli)
+ {
+ GroupDef *gd=0;
+ if (s->length()>0 && (gd=groupDict[*s]))
+ {
+ gd->addClass(cd);
+ //printf("Compound %s: in group %s\n",cd->name().data(),s->data());
+ }
+ }
+
+ bool found=addNamespace(root,cd);
+
+ // file definition containing the class cd
+ FileDef *ifd=findFileDef(&inputNameDict,root->fileName,ambig);
+
+ addIncludeFile(cd,ifd,root);
+
+ // if the class is not in a namespace then we insert
+ // it in the file definition
+ if (!found && ifd) ifd->insertClass(cd);
+
+ // the empty string test is needed for extract all case
+ cd->setBriefDescription(root->brief);
+ cd->insertUsedFile(root->fileName);
+ // add class to the list
+ classList.inSort(cd);
+ //printf("ClassDict.insert(%s)\n",resolveDefines(fullName).data());
+ //classDict.insert(resolveDefines(fullName),cd);
+ classDict.insert(fullName,cd);
+ }
+ }
+ }
+ EntryListIterator eli(*root->sublist);
+ Entry *e;
+ for (;(e=eli.current());++eli)
+ {
+ buildClassList(e);
+ }
+}
+
+//----------------------------------------------------------------------
+// build a list of all namespaces mentioned in the documentation
+// and all namespaces that have a documentation block before their definition.
+void buildNamespaceList(Entry *root)
+{
+ if (
+ (root->section==Entry::NAMESPACE_SEC) ||
+ (root->section==Entry::NAMESPACEDOC_SEC) &&
+ root->name.length()>0
+ )
+ {
+ QString fullName=root->name.copy();
+ if (fullName.length()==0)
+ {
+ // this should not be called
+ warn("Warning: invalid namespace found in file %s at %d\n",
+ root->fileName.data(),root->startLine);
+ }
+ else
+ {
+ //printf("Found namespace %s in %s at line %d\n",root->name.data(),
+ // root->fileName.data(), root->startLine);
+ NamespaceDef *nd;
+ if ((nd=namespaceDict[fullName]))
+ {
+ if (root->doc.length()>0 || root->brief.length()>0) // block contains docs
+ {
+ if (nd->documentation().isEmpty() && root->doc.length()>0)
+ {
+ nd->setDocumentation(root->doc);
+ nd->setName(fullName); // change name to match docs
+ }
+ else if (!nd->documentation().isEmpty() && root->doc.length()>0)
+ {
+ warn("Warning: namespace %s already has a detailed description,\n"
+ " skipping documentation in file %s at line %d\n",
+ fullName.data(),root->fileName.data(),root->startLine);
+ }
+ if (nd->briefDescription().isEmpty() && root->brief.length()>0)
+ {
+ nd->setBriefDescription(root->brief);
+ nd->setName(fullName); // change name to match docs
+ }
+ else if (!nd->briefDescription().isEmpty() && root->brief.length()>0)
+ {
+ warn("Warning: namespace %s already has a brief description,\n"
+ " skipping documentation in file %s at line %d\n",
+ fullName.data(),root->fileName.data(),root->startLine);
+ }
+ }
+ }
+ else if (root->doc.length()>0 ||
+ root->brief.length()>0 ||
+ extractAllFlag
+ )
+ {
+ NamespaceDef *nd=new NamespaceDef(fullName);
+ nd->setDocumentation(root->doc); // copy docs to definition
+ nd->setBriefDescription(root->brief);
+
+ QListIterator<QString> sli(*root->groups);
+ QString *s;
+ for (;(s=sli.current());++sli)
+ {
+ GroupDef *gd=0;
+ if (s->length()>0 && (gd=groupDict[*s]))
+ gd->addNamespace(nd);
+ }
+
+ bool ambig;
+ // file definition containing the class cd
+ FileDef *fd=findFileDef(&inputNameDict,root->fileName,ambig);
+ // insert the namespace in the file definition
+ if (fd) fd->insertNamespace(nd);
+
+ // the empty string test is needed for extract all case
+ nd->setBriefDescription(root->brief);
+ nd->insertUsedFile(root->fileName);
+ // add class to the list
+ namespaceList.inSort(nd);
+ namespaceDict.insert(fullName,nd);
+ }
+ }
+ }
+ EntryListIterator eli(*root->sublist);
+ Entry *e;
+ for (;(e=eli.current());++eli)
+ {
+ buildNamespaceList(e);
+ }
+}
+
+
+//----------------------------------------------------------------------
+// Searches the Entry tree for Variable documentation sections.
+// If found they are stored in their class or in the global list.
+
+void buildVarList(Entry *root)
+{
+ QRegExp re("([^)]*)");
+ int i=-1;
+ if (root->name.length()>0 &&
+ root->type!="class" &&
+ (
+ (root->section==Entry::VARIABLE_SEC
+ ) ||
+ (root->section==Entry::FUNCTION_SEC && // function variable
+ !root->type.isNull() && root->type.find(re,0)!=-1 &&
+ root->type.find("operator")==-1 && root->type.find(")(")==-1
+ )
+ )
+ ) // documented variable
+ {
+ Debug::print(Debug::Variables,0,
+ "VARIABLE_SEC: \n"
+ " type=`%s' name=`%s' args=`%s'\n",
+ root->type.data(),
+ root->name.data(),
+ root->args.data()
+ );
+ //printf("root->parent->name=%s\n",root->parent->name.data());
+
+ if (root->type.isNull() && root->name.find("operator")==-1 &&
+ (root->name.find('*')!=-1 || root->name.find('&')!=-1))
+ {
+ // recover from parse error caused by redundant braces
+ root->type=root->name;
+ QRegExp re("[a-z_A-Z][a-z_A-Z0-9]*");
+ int i,l;
+ i=re.match(root->args,0,&l);
+ root->name=root->args.mid(i,l);
+ root->args=root->args.mid(i+l,
+ root->args.find(')',i+l)-i-l);
+ //printf("new: type=`%s' name=`%s' args=`%s'\n",
+ // root->type.data(),root->name.data(),root->args.data());
+ }
+ else
+ {
+ QRegExp re("([^)]*)");
+ i=root->type.find(re,0);
+ if (i!=-1) // function variable
+ {
+ root->type=root->type.left(root->type.length()-1);
+ root->args.prepend(")");
+ }
+ }
+
+ QString scope,name=root->name.copy();
+ bool stat=root->stat;
+ ClassDef *cd=0;
+ Entry *p = root->parent;
+ while ((p->section & Entry::COMPOUND_MASK))
+ {
+ if (p->name.length()>0 && p->name[0]!='@')
+ {
+ if (!scope.isEmpty()) scope.prepend("::");
+ scope.prepend(p->name);
+ }
+ p=p->parent;
+ }
+
+ //printf("scope=%s\n",scope.data());
+
+ int ni;
+ if ((ni=root->name.findRev("::"))!=-1)
+ {
+ if (scope.length()>0) scope+="::";
+ scope+=root->name.left(ni);
+ name=root->name.right(root->name.length()-ni-2);
+ stat=TRUE;
+ }
+
+ MemberDef::MemberType mtype;
+ QString type=root->type.stripWhiteSpace();
+ if (type=="@")
+ mtype=MemberDef::EnumValue;
+ else if (type.left(8)=="typedef ")
+ mtype=MemberDef::Typedef;
+ else if (type.left(7)=="friend ")
+ mtype=MemberDef::Friend;
+ else
+ mtype=MemberDef::Variable;
+
+ if (scope.length()>0 && name.length()>0 && (cd=getClass(scope)))
+ {
+
+ Debug::print(Debug::Variables,0,
+ " class variable:\n"
+ " %s' %s'::`%s' `%s' prot=`%d\n",
+ root->type.data(),
+ scope.data(),
+ name.data(),
+ root->args.data(),
+ root->protection
+ );
+ // add template names, if the class is a non-specialized template
+ //if (scope.find('<')==-1 && cd->templateArguments())
+ //{
+ // scope+=cd->getTemplateNameString();
+ //}
+ // generate member definition.
+ QString def;
+ if (root->type.length()>0)
+ {
+ if (mtype==MemberDef::Friend)
+ {
+ def=root->type+" "+name+root->args;
+ }
+ else
+ {
+ def=root->type+" "+scope+"::"+name+root->args;
+ }
+ }
+ else
+ {
+ def=scope+"::"+name+root->args;
+ }
+ if (def.left(7)=="static ") def=def.right(def.length()-7);
+
+ // see if the member is already found in the same scope
+ // (this may be the case for a static member that is initialized
+ // outside the class)
+ bool found=FALSE;
+ MemberName *mn=memberNameDict[name];
+ if (mn)
+ {
+ MemberDef *md=mn->first();
+ while (md)
+ {
+ if (md->memberClass()==cd) // member already in the scope
+ {
+ addMemberDocs(root,md,def,FALSE);
+ found=TRUE;
+ }
+ md=mn->next();
+ }
+ }
+ if (!found) // found a fresh variable
+ {
+ // new member variable, typedef or enum value
+ MemberDef *md=new MemberDef(root->type,name,root->args,0,
+ root->protection,Normal,stat,FALSE,
+ mtype,0,0);
+ md->setMemberClass(cd);
+ md->setDefFile(root->fileName);
+ md->setDefLine(root->startLine);
+ md->setDocumentation(root->doc);
+ md->setBriefDescription(root->brief);
+ md->setDefinition(def);
+
+ // add the member to the global list
+ if (mn)
+ {
+ //printf("Member already found! %s\n",md->name());
+ //addMemberDocs(root,mn->first(),def,FALSE);
+ //delete md;
+ mn->inSort(md);
+ }
+ else // new variable name
+ {
+ mn = new MemberName(name);
+ mn->inSort(md);
+ //printf("Adding memberName=%s\n",mn->memberName());
+ memberNameDict.insert(name,mn);
+ memberNameList.inSort(mn);
+ // add the member to the class
+ }
+ cd->insertMember(md);
+
+ //TODO: insert FileDef instead of filename strings.
+ cd->insertUsedFile(root->fileName);
+ }
+ }
+ else if (name.length()>0) // global variable
+ {
+ Debug::print(Debug::Variables,0,
+ " global variable:\n"
+ " type=`%s' scope=`%s' name=`%s' args=`%s' prot=`%d\n",
+ root->type.data(),
+ scope.data(),
+ name.data(),
+ root->args.data(),
+ root->protection
+ );
+
+ // new global variable, enum value or typedef
+ MemberDef *md=new MemberDef(root->type,name,root->args,0,
+ Public, Normal,root->stat,FALSE,
+ mtype,0,0);
+ md->setDefFile(root->fileName);
+ md->setDefLine(root->startLine);
+ md->setDocumentation(root->doc);
+ md->setBriefDescription(root->brief);
+ QString def;
+
+ // see if the function is inside a namespace
+ NamespaceDef *nd = 0;
+ if (root->parent->section == Entry::NAMESPACE_SEC )
+ {
+ nd = namespaceDict[root->parent->name];
+ }
+ if (nd)
+ {
+ nd->insertMember(md);
+ md->setNamespace(nd);
+ }
+ else
+ {
+ // find file definition
+ FileDef *fd=0;
+ bool ambig;
+ if (root->fileName.length()>0 &&
+ (fd=findFileDef(&inputNameDict,root->fileName,ambig))
+ )
+ {
+ fd->insertMember(md);
+ md->setFileDef(fd);
+ }
+ }
+
+ // determine the definition of the global variable
+ if (nd) // variable is inside a namespace, so put the scope
+ // before the name
+ {
+ if (root->type.length()>0)
+ {
+ def=root->type+" "+nd->name()+"::"+name+root->args;
+ }
+ else
+ {
+ def=nd->name()+"::"+name+root->args;
+ }
+ }
+ else
+ {
+ if (root->type.length()>0)
+ {
+ def=root->type+" "+name+root->args;
+ }
+ else
+ {
+ def=name+root->args;
+ }
+ }
+ if (def.left(7)=="static ") def=def.right(def.length()-7);
+ md->setDefinition(def);
+
+ MemberName *mn;
+ // add member definition to the list of globals
+ if ((mn=functionNameDict[name]))
+ {
+ mn->inSort(md);
+ }
+ else
+ {
+ mn = new MemberName(name);
+ mn->inSort(md);
+ functionNameDict.insert(name,mn);
+ functionNameList.inSort(mn);
+ }
+ }
+ }
+ EntryListIterator eli(*root->sublist);
+ Entry *e;
+ for (;(e=eli.current());++eli)
+ {
+ if (e->section!=Entry::ENUM_SEC) buildVarList(e);
+ }
+}
+
+//----------------------------------------------------------------------
+// Searches the Entry tree for Function sections.
+// If found they are stored in their class or in the global list.
+
+void buildMemberList(Entry *root)
+{
+ if (root->section==Entry::FUNCTION_SEC)
+ {
+ Debug::print(Debug::Functions,0,
+ "FUNCTION_SEC:\n"
+ " `%s' `%s'::`%s' `%s' relates=`%s' file=`%s' #targs=%d\n",
+ root->type.data(),
+ root->parent->name.data(),
+ root->name.data(),
+ root->args.data(),
+ root->relates.data(),
+ root->fileName.data(),
+ root->tArgList ? (int)root->tArgList->count() : -1
+ );
+
+ bool isFriend=root->type.find("friend ")!=-1;
+ //if (isFriend && root->relates.length()==0)
+ // root->relates=root->parent->name.copy();
+ if (root->name.length()>0 /* && !isFriend */)
+ {
+
+ ClassDef *cd=0;
+ // check if this function's parent is a class
+ QRegExp re("([a-zA-Z0-9: ]*[ *]*[ ]*");
+ //printf("root->parent=`%s' cd=%p root->type.find(re,0)=%d\n",
+ // root->parent->name.data(),getClass(root->parent->name),
+ // root->type.find(re,0));
+ int i;
+ if (root->parent &&
+ root->parent->name.length()>0 &&
+ (root->parent->section & Entry::COMPOUND_MASK) &&
+ (cd=getClass(root->parent->name)) &&
+ // do some fuzzy things to exclude function pointers
+ (root->type.isNull() || root->type.find(re,0)==-1 ||
+ root->type.find(")(")!=-1 || root->type.find("operator")!=-1
+ )
+ )
+ {
+ int l;
+ if ((i=re.match(root->type,0,&l))!=-1) // function variable
+ {
+ root->args+=root->type.right(root->type.length()-i-l);
+ root->type=root->type.left(i+l);
+ }
+
+ QString name=removeRedundantWhiteSpace(root->name);
+ if (name.left(2)=="::") name=name.right(name.length()-2);
+
+ MemberDef::MemberType mtype;
+ if (isFriend) mtype=MemberDef::Friend;
+ else if (root->sig) mtype=MemberDef::Signal;
+ else if (root->slot) mtype=MemberDef::Slot;
+ else mtype=MemberDef::Function;
+ // new member of function, signal or slot.
+ MemberDef *md=new MemberDef(root->type,name,root->args,root->exception,
+ root->protection,root->virt,root->stat,root->relates.length()>0,
+ mtype,root->tArgList,root->argList);
+ md->setMemberClass(cd);
+ md->setDefFile(root->fileName);
+ md->setDefLine(root->startLine);
+ md->setDocumentation(root->doc);
+ md->setBriefDescription(root->brief);
+ QString def;
+ if (root->relates.length()>0 || isFriend)
+ {
+ if (root->type.length()>0)
+ {
+ if (root->argList)
+ {
+ def=root->type+" "+name;
+ }
+ else
+ {
+ def=root->type+" "+name+root->args;
+ }
+ }
+ else
+ {
+ if (root->argList)
+ {
+ def=name;
+ }
+ else
+ {
+ def=name+root->args;
+ }
+ }
+ }
+ else
+ {
+ QString scope=root->parent->name.copy();
+ if (root->type.length()>0)
+ {
+ if (root->argList)
+ {
+ def=root->type+" "+scope+"::"+name;
+ }
+ else
+ {
+ def=root->type+" "+scope+"::"+name+root->args;
+ }
+ }
+ else
+ {
+ if (root->argList)
+ {
+ def=scope+"::"+name;
+ }
+ else
+ {
+ def=scope+"::"+name+root->args;
+ }
+ }
+ }
+ if (def.left(7)=="friend ") def=def.right(def.length()-7);
+ md->setDefinition(def);
+
+ Debug::print(Debug::Functions,0,
+ " Func Member:\n"
+ " `%s' `%s'::`%s' `%s' proto=%d\n"
+ " def=`%s'\n",
+ root->type.data(),
+ root->parent->name.data(),
+ root->name.data(),
+ root->args.data(),
+ root->proto,
+ def.data()
+ );
+
+ // add member to the global list of all members
+ MemberName *mn;
+ if ((mn=memberNameDict[name]))
+ {
+ mn->inSort(md);
+ }
+ else
+ {
+ mn = new MemberName(name);
+ mn->inSort(md);
+ //printf("Adding memberName=%s\n",mn->memberName());
+ memberNameDict.insert(name,mn);
+ memberNameList.inSort(mn);
+ }
+
+ // add member to the class cd
+ cd->insertMember(md);
+ // add file to list of used files
+ cd->insertUsedFile(root->fileName);
+ }
+ else if (root->parent &&
+ !(root->parent->section & Entry::COMPOUND_MASK) &&
+ root->name.find("::")==-1 &&
+ root->relates.length()==0 &&
+ root->type.left(7)!="extern ")
+ // no member => unrelated function
+ {
+ /* check the uniqueness of the function name in the file.
+ * A file could contain a function prototype and a function definition
+ * or even multiple function prototypes.
+ */
+ bool found=FALSE;
+ MemberName *mn;
+ //MemberDef *fmd;
+ if ((mn=functionNameDict[root->name]))
+ {
+ MemberDef *md=mn->first();
+ while (md && !found)
+ {
+ if (md->getFileDef() &&
+ md->getFileDef()->absFilePath()==root->fileName &&
+ /*matchArguments(md->argsString(),root->args)*/
+ matchArguments(md->argumentList(),root->argList)
+ )
+ {
+ // function already found in the same file, one is probably
+ // a prototype.
+ found=TRUE;
+ if (!md->documentation() && !root->doc.isEmpty())
+ {
+ md->setDocumentation(root->doc);
+ }
+ if (!md->briefDescription() && !root->brief.isEmpty())
+ {
+ md->setBriefDescription(root->brief);
+ }
+ }
+ md=mn->next();
+ }
+ }
+ if (!found) /* global function is unique with respect to the file */
+ {
+ //printf("New function type=`%s' name=`%s' args=`%s'\n",
+ // root->type.data(),root->name.data(),root->args.data());
+
+ // new global function
+ QString name=removeRedundantWhiteSpace(root->name);
+ MemberDef *md=new MemberDef(root->type,name,root->args,root->exception,
+ root->protection,root->virt,root->stat,FALSE,
+ MemberDef::Function,root->tArgList,root->argList);
+ md->setDefFile(root->fileName);
+ md->setDefLine(root->startLine);
+ md->setDocumentation(root->doc);
+ md->setBriefDescription(root->brief);
+ md->setPrototype(root->proto);
+ QString def;
+ if (root->type.length()>0)
+ {
+ if (root->argList)
+ {
+ def=root->type+" "+name;
+ }
+ else
+ {
+ def=root->type+" "+name+root->args;
+ }
+ }
+ else
+ {
+ if (root->argList)
+ {
+ def=name.copy();
+ }
+ else
+ {
+ def=name+root->args;
+ }
+ }
+ Debug::print(Debug::Functions,0,
+ " Global Function:\n"
+ " `%s' `%s'::`%s' `%s' proto=%d\n"
+ " def=`%s'\n",
+ root->type.data(),
+ root->parent->name.data(),
+ root->name.data(),
+ root->args.data(),
+ root->proto,
+ def.data()
+ );
+ md->setDefinition(def);
+
+ // see if the function is inside a namespace
+ NamespaceDef *nd = 0;
+ if (root->parent->section == Entry::NAMESPACE_SEC )
+ {
+ nd = namespaceDict[root->parent->name];
+ }
+ if (nd)
+ {
+ nd->insertMember(md);
+ md->setNamespace(nd);
+ }
+ else
+ {
+ // find file definition
+ FileDef *fd=0;
+ bool ambig;
+ if (root->fileName.length()>0 &&
+ (fd=findFileDef(&inputNameDict,root->fileName,ambig))
+ )
+ {
+ // add member to the file
+ fd->insertMember(md);
+ md->setFileDef(fd);
+ }
+ }
+
+ // add member to the list of file members
+ MemberName *mn;
+ if ((mn=functionNameDict[name]))
+ {
+ mn->inSort(md);
+ }
+ else
+ {
+ mn = new MemberName(name);
+ mn->inSort(md);
+ functionNameDict.insert(name,mn);
+ functionNameList.inSort(mn);
+ }
+ }
+ else
+ {
+ //printf("Function already found!\n");
+ }
+
+ //printf("unrelated function %d `%s' `%s' `%s'\n",
+ // root->parent->section,root->type.data(),root->name.data(),root->args.data());
+ }
+ }
+ else if (root->name.length()==0)
+ {
+ warn("Warning: Illegal member name found in file %s at line %d\n",
+ root->fileName.data(),root->startLine);
+ }
+ }
+ EntryListIterator eli(*root->sublist);
+ Entry *e;
+ for (;(e=eli.current());++eli)
+ {
+ buildMemberList(e);
+ }
+}
+
+//----------------------------------------------------------------------
+
+void findFriends()
+{
+ //printf("findFriends()\n");
+ MemberNameListIterator fnli(functionNameList);
+ MemberName *fn;
+ for (;(fn=fnli.current());++fnli) // for each global function name
+ {
+ //printf("Function name=`%s'\n",fn->memberName());
+ MemberName *mn;
+ if ((mn=memberNameDict[fn->memberName()]))
+ { // there are members with the same name
+ //printf("Function name is also a member name\n");
+ MemberNameIterator fni(*fn);
+ MemberDef *fmd;
+ for (;(fmd=fni.current());++fni) // for each function with that name
+ {
+ MemberNameIterator mni(*mn);
+ MemberDef *mmd;
+ for (;(mmd=mni.current());++mni) // for each member with that name
+ {
+ //printf("Checking for matching arguments
+ // mmd->isRelated()=%d mmd->isFriend()=%d mmd->isFunction()=%d\n",
+ // mmd->isRelated(),mmd->isFriend(),mmd->isFunction());
+ NamespaceDef *nd=mmd->getNamespace();
+ if ((mmd->isFriend() || (mmd->isRelated() && mmd->isFunction())) &&
+ matchArguments(mmd->argumentList(),
+ fmd->argumentList(),
+ mmd->memberClass()->name(),
+ nd ? nd->name().data() : 0
+ )
+ ) // if the member is related and the arguments match then the
+ // function is actually a friend.
+ {
+ //printf("Found friend function\n");
+ mergeArguments(mmd->argumentList(),fmd->argumentList());
+ if (fmd->documentation())
+ mmd->setDocumentation(fmd->documentation());
+ else if (mmd->documentation())
+ fmd->setDocumentation(mmd->documentation());
+ if (!mmd->briefDescription() && fmd->briefDescription())
+ mmd->setBriefDescription(fmd->briefDescription());
+ else if (mmd->briefDescription() && !fmd->briefDescription())
+ fmd->setBriefDescription(mmd->briefDescription());
+ }
+ }
+ }
+ }
+ }
+}
+
+//----------------------------------------------------------------------
+
+void transferFunctionDocumentation()
+{
+ //printf("transferFunctionDocumentation()\n");
+ MemberNameListIterator mnli(functionNameList);
+ MemberName *mn;
+ for (;(mn=mnli.current());++mnli)
+ {
+ MemberDef *md,*mdef=0,*mdec=0;
+ MemberNameIterator mni(*mn);
+ /* find a matching function declaration and definition for this function */
+ for (;(md=mni.current());++mni)
+ {
+ if (md->isPrototype()) mdec=md;
+ if (md->isFunction() && !md->isStatic() && !md->isPrototype()) mdef=md;
+ }
+ if (mdef && mdec &&
+ matchArguments(mdef->argumentList(),mdec->argumentList())
+ ) /* match found */
+ {
+ //printf("Found member %s: def in %s and dec in %s\n",
+ // mn->memberName(),mdef->getFileDef()->name(),mdec->getFileDef()->name());
+
+ /* copy documentation between function definition and declaration */
+ if (mdec->briefDescription())
+ {
+ mdef->setBriefDescription(mdec->briefDescription());
+ }
+ else if (mdef->briefDescription())
+ {
+ mdec->setBriefDescription(mdef->briefDescription());
+ }
+ if (mdef->documentation())
+ {
+ mdec->setDocumentation(mdef->documentation());
+ }
+ else if (mdec->documentation())
+ {
+ mdef->setDocumentation(mdec->documentation());
+ }
+ }
+ }
+}
+
+
+//----------------------------------------------------------------------
+// Computes the base and super classes for each class in the tree
+
+void computeClassRelations(Entry *root)
+{
+ if (
+ (
+ (
+ root->section & Entry::COMPOUND_MASK
+ )
+ ||
+ (
+ (root->section & Entry::COMPOUNDDOC_MASK) && root->extends->count()>0
+ )
+ )
+ &&
+ root->name.length()>0
+ )
+ {
+ ClassDef *cd;
+ if ((cd=getClass(root->name)))
+ {
+ //printf("Class %s %d\n",cd->name().data(),root->extends->count());
+ if (!cd->visited)
+ {
+ cd->visited=TRUE; // mark class as used (in case the are multiple classes
+ // with the same name!)
+ if (root->extends->count()>0) // there are base classes
+ {
+ QString scopePrefix;
+ Entry *p=root->parent;
+ // For nested classes the base class could also be nested!
+ // To find the correct scope, we try to prepend the scope to the base
+ // name, starting with the largest, most inner scope.
+ while (p->section&Entry::COMPOUND_MASK)
+ {
+ scopePrefix=p->name+"::";
+ QList<BaseInfo> *baseList=root->extends;
+ BaseInfo *bi=baseList->first();
+ while (bi) // for each base class
+ {
+ QString cName=scopePrefix+bi->name;
+ //printf("Base class %s\n",cName.data());
+ ClassDef *baseClass=getClass(cName);
+ if (baseClass) // base class is documented
+ {
+ //printf("Adding!\n");
+ // add base class to this class
+ cd->insertBaseClass(baseClass,bi->prot,bi->virt);
+ // add this class as super class to the base class
+ baseClass->insertSuperClass(cd,bi->prot,bi->virt);
+ }
+ //else // base class not documented
+ //{
+ // warn("Warning: Base class %s referred to in file %s at line %d is not "
+ // "documented\n",s->data(),root->fileName.data(),root->startLine);
+ //}
+ bi=baseList->next();
+ }
+ p=p->parent;
+ }
+ // The base class could ofcouse also be a non-nested class
+ QList<BaseInfo> *baseList=root->extends;
+ BaseInfo *bi=baseList->first();
+ while (bi) // for each base class
+ {
+ ClassDef *baseClass=getClass(bi->name);
+ //printf("baseClass %s of %s found (%s and %s)\n",
+ // bi->name.data(),
+ // root->name.data(),
+ // (bi->prot==Private)?"private":((bi->prot==Protected)?"protected":"public"),
+ // (bi->virt==Normal)?"normal":"virtual"
+ // );
+ int i;
+ QString templSpec,baseClassName=bi->name.copy();
+ if (!baseClass && (i=bi->name.find('<'))!=-1)
+ // base class has template specifiers
+ {
+ // TODO: here we should try to find the correct template specialization
+ // but for now, we only look for the unspecializated base class.
+ baseClassName=bi->name.left(i);
+ baseClass=getClass(baseClassName);
+ templSpec=bi->name.right(bi->name.length()-i);
+ }
+ if (baseClass) // base class is documented
+ {
+ // add base class to this class
+ cd->insertBaseClass(baseClass,bi->prot,bi->virt,templSpec);
+ // add this class as super class to the base class
+ baseClass->insertSuperClass(cd,bi->prot,bi->virt,templSpec);
+ }
+ else // base class not documented
+ {
+ //printf("Found undocumented base class %s\n",bi->name.data());
+ NamespaceDef *nd=cd->getNamespace();
+ if (nd && (baseClass=getClass(nd->name()+"::"+baseClassName)))
+ // class is defined inside namespace
+ {
+ // add base class to this class
+ cd->insertBaseClass(baseClass,bi->prot,bi->virt,templSpec);
+ // add this class as super class to the base class
+ baseClass->insertSuperClass(cd,bi->prot,bi->virt,templSpec);
+ }
+ else // undocumented base class
+ {
+ baseClass=new ClassDef(bi->name,Entry::CLASS_SEC);
+ // add base class to this class
+ cd->insertBaseClass(baseClass,bi->prot,bi->virt,templSpec);
+ // add this class as super class to the base class
+ baseClass->insertSuperClass(cd,bi->prot,bi->virt,templSpec);
+ // the undocumented base was found in this file
+ baseClass->insertUsedFile(root->fileName);
+ // add class to the list
+ classList.inSort(baseClass);
+ //printf("ClassDict.insert(%s)\n",resolveDefines(fullName).data());
+ //classDict.insert(resolveDefines(bi->name),baseClass);
+ classDict.insert(bi->name,baseClass);
+ }
+ }
+ bi=baseList->next();
+ }
+ }
+// else // class has no base classes
+// {
+// QString resName=resolveDefines(root->name);
+// int i;
+// // Check if this class is a template instance of another class.
+// // If this is the case, we act as if this class `inherits' from the
+// // template class.
+// if ((i=resName.find('<'))!=-1)
+// {
+// ClassDef *baseClass=getClass(resName.left(i));
+// if (baseClass)
+// {
+// // add base class to this class
+// cd->insertBaseClass(baseClass,Public,Normal);
+// // add this class as super class to the base class
+// baseClass->insertSuperClass(cd,Public,Normal);
+// }
+// }
+// }
+ } // else class is already found
+ }
+ else if (root->name.right(2)!="::")
+ {
+ if (root->name.length()>0 && root->name[0]!='@')
+ warn("Warning: Compound %s\n"
+ " defined in file %s at line %d\n"
+ " is not documented\n",
+ root->name.data(),root->fileName.data(),root->startLine);
+ }
+ }
+ EntryListIterator eli(*root->sublist);
+ Entry *e;
+ for (;(e=eli.current());++eli)
+ {
+ computeClassRelations(e);
+ }
+}
+
+//-----------------------------------------------------------------------
+// compute the references (anchors in HTML) for each member in the class
+
+void computeMemberReferences()
+{
+ ClassDef *cd=classList.first();
+ while (cd)
+ {
+ cd->computeAnchors();
+ cd=classList.next();
+ }
+}
+
+//-----------------------------------------------------------------------
+// compute the references (anchors in HTML) for each function in the file
+
+void computeFunctionReferences()
+{
+ FileName *fn=inputNameList.first();
+ while (fn)
+ {
+ FileDef *fd=fn->first();
+ while (fd)
+ {
+ fd->computeAnchors();
+ fd=fn->next();
+ }
+ fn=inputNameList.next();
+ }
+ NamespaceDef *nd=namespaceList.first();
+ while (nd)
+ {
+ nd->computeAnchors();
+ nd=namespaceList.next();
+ }
+}
+
+
+
+//----------------------------------------------------------------------
+// Copy the documentation in entry `root' to member definition `md' and
+// set the function declaration of the member to `funcDecl'. If the boolean
+// over_load is set the standard overload text is added.
+
+void addMemberDocs(Entry *root,MemberDef *md, const char *funcDecl,
+ bool over_load)
+{
+ //printf("addMemberDocs: `%s'::`%s' `%s' funcDecl=`%s'\n",
+ // root->parent->name.data(),md->name().data(),md->argsString(),funcDecl);
+ QString fDecl=funcDecl;
+ // strip extern specifier
+ if (fDecl.left(7)=="extern ") fDecl=fDecl.right(fDecl.length()-7);
+ md->setDefinition(fDecl);
+ ClassDef *cd=md->memberClass();
+ NamespaceDef *nd=md->getNamespace();
+ if (matchArguments(md->argumentList(),root->argList,
+ cd ? cd->name().data() : 0,
+ nd ? nd->name().data() : 0
+ )
+ ) mergeArguments(md->argumentList(),root->argList);
+ if (over_load) // the \overload keyword was used
+ {
+ QString doc=getOverloadDocs();
+ if (!root->doc.isNull())
+ {
+ doc+="<p>";
+ doc+=root->doc;
+ }
+ md->setDocumentation(doc);
+ }
+ else
+ {
+ // documentation outside a compound overrides the documentation inside it
+ if ( /* !md->isStatic() && !root->stat && do not replace doc of a static */
+ (
+ !md->documentation() || /* no docs yet */
+ (root->parent->name.isNull() && /* or overwrite prototype docs */
+ !root->proto && md->isPrototype() /* with member definition docs */
+ )
+ ) && root->doc.length()>0
+ )
+ {
+ md->setDocumentation(root->doc);
+ }
+
+ // brief descriptions inside a compound override the documentation
+ // outside it
+ if ( /* !md->isStatic() && !root->stat && do not replace doc of static */
+ (
+ !md->briefDescription() || /* no docs yet */
+ !root->parent->name.isNull() /* member of a class */
+ ) && root->brief.length()>0
+ )
+ {
+ md->setBriefDescription(root->brief);
+ }
+ }
+ md->setDefFile(root->fileName);
+ md->setDefLine(root->startLine);
+ if (cd) cd->insertUsedFile(root->fileName);
+}
+
+//----------------------------------------------------------------------
+// Adds the documentation contained in `root' to a global function
+// with name `name' and argument list `args' (for overloading) and
+// function declaration `decl' to the corresponding member definition.
+
+bool findUnrelatedFunction(Entry *root,
+ const QString &namespaceName,
+ const char *name,
+ const char *,
+ const char *decl)
+{
+ MemberName *mn=0;
+ QString n=name;
+ if (n.find("::")!=-1) return FALSE; // skip undefined class members
+ //printf("findUnrelatedFunction(%s)\n",name);
+ if (n.length()>0 && (mn=functionNameDict[n])) // function name defined
+ {
+ int count=0;
+ MemberDef *md=mn->first();
+ while (md)
+ {
+ NamespaceDef *nd=md->getNamespace();
+ QString nsName = nd ? nd->name().data() : "";
+ if (namespaceName.length()==0 ||
+ nsName==namespaceName)
+ {
+ //printf("Searching for match between %s and %s\n",
+ // argListToString(md->argumentList()).data(),
+ // argListToString(root->argList).data());
+ bool matching=
+ /*matchArguments(md->argsString(),args);*/
+ (md->argumentList()==0 && root->argList->count()==0) ||
+ matchArguments(md->argumentList(),root->argList,0,nsName);
+ if (matching) // add docs to the member
+ {
+ //printf("Match found\n");
+ addMemberDocs(root,md,decl,FALSE);
+ count++;
+ }
+ }
+ md=mn->next();
+ }
+ if (count==0) // more than one match (each member will get the same docs)!
+ {
+ warn("Warning: no matching members found for \n%s\n"
+ "in file %s at line %d\n",
+ decl,root->fileName.data(),root->startLine);
+ }
+#if 0
+ else if (count>1) // no match!
+ {
+ warn("Warning: multiple matching members for\n%s\n",decl);
+ if (mn->count()>0) // there is a member with that name
+ {
+ warn("Possible candidates are:\n");
+ MemberDef *md=mn->first();
+ while (md) // list all possible members with the same name
+ {
+ warn(" %s%s\n",md->name(),md->argsString());
+ md=mn->next();
+ }
+ }
+ }
+#endif
+ }
+ else // got docs for an undefined member!
+ {
+ warn("Warning: documented function `%s' in file %s at line %d "
+ "was not defined \n",decl,
+ root->fileName.data(),root->startLine);
+ }
+ return TRUE;
+}
+
+
+//----------------------------------------------------------------------
+// This function tries to find a member (in a documented class/file/namespace)
+// that corresponds to the function declaration given in `funcDecl'.
+//
+// The related field may be used to specify a related class name.
+// It is only used if the class name cannot be extracted from the function
+// declaration.
+//
+// The boolean overloaded is used to specify whether or not a standard
+// overload documentation line should be generated.
+
+void findMember(Entry *root,QString funcDecl,QString related,bool overloaded,
+ bool isFunc)
+{
+ Debug::print(Debug::FindMembers,0,
+ "findMember(root=%p,funcDecl=`%s',related=`%s',overload=%d,isFunc=%d)\n",
+ root,funcDecl.data(),related.data(),overloaded,isFunc
+ );
+
+ QString scopeName;
+ QString className;
+ QString namespaceName;
+ QString classTempList;
+ QString funcType;
+ QString funcName;
+ QString funcArgs;
+ QString funcTempList;
+ QString exceptions;
+ bool isRelated=FALSE;
+ bool isFriend=FALSE;
+
+ if (funcDecl.left(7)=="friend ") // treat friends as related members
+ {
+ funcDecl=funcDecl.right(funcDecl.length()-7);
+ isFriend=TRUE;
+ }
+
+ // delete any ; from the function declaration
+ int sep;
+ while ((sep=funcDecl.find(';'))!=-1)
+ {
+ funcDecl=(funcDecl.left(sep)+funcDecl.right(funcDecl.length()-sep-1)).stripWhiteSpace();
+ }
+
+ // make sure the first character is a space to simplify searching.
+ if (funcDecl.length()>0 && funcDecl[0]!=' ') funcDecl.prepend(" ");
+
+ // remove some superfluous spaces
+ funcDecl=substitute(
+ substitute(
+ substitute(funcDecl,"~ ","~"),
+ ":: ","::"
+ ),
+ " ::","::"
+ );
+
+ // extract information from the declarations
+ parseFuncDecl(funcDecl,scopeName,classTempList,funcType,funcName,
+ funcArgs,funcTempList,exceptions
+ );
+
+ // the class name can also be a namespace name, we decide this later.
+ // if a related class name is specified and the class name could
+ // not be derived from the function declaration, then use the
+ // related field.
+ //printf("scopeName=`%s' className=`%s'\n",scopeName.data(),className.data());
+ if (/*scopeName.isEmpty() &&*/ !related.isEmpty() && !isRelated)
+ {
+ isRelated=TRUE;
+ //scopeName=resolveDefines(related);
+ if (!scopeName.isEmpty() && scopeName!=related)
+ scopeName+="::"+related;
+ else
+ scopeName=related.copy();
+ }
+ else if (scopeName.isEmpty() && related.isEmpty() && root->parent &&
+ !root->parent->name.isNull())
+ {
+ Entry *p=root->parent;
+ while (p) // get full scope as class name
+ {
+ if (((p->section & Entry::COMPOUND_MASK) ||
+ p->section == Entry::NAMESPACE_SEC
+ ) && !p->name.isEmpty() && p->name[0]!='@'
+ )
+ {
+ if (!scopeName.isEmpty()) scopeName.prepend("::");
+ scopeName.prepend(p->name);
+ break; // stop here because the class name already contains
+ // the whole scope!
+ }
+ p=p->parent;
+ }
+ }
+
+ if (scopeName.length()>0 && scopeName.find('<')==-1 && classTempList.length()==0 )
+ { // class is a template, but no template name list found
+ ClassDef *cd=getClass(scopeName);
+ if (cd) // class exists
+ {
+ classTempList = cd->getTemplateNameString();
+ }
+ }
+
+ //printf("scopeName=`%s' className=`%s'\n",scopeName.data(),className.data());
+ // rebuild the function declaration (needed to get the scope right).
+ if (scopeName.length()>0 && !isRelated && !isFriend)
+ {
+ if (funcType.length()>0)
+ {
+ if (isFunc) // a function -> we use argList for the arguments
+ {
+ funcDecl=funcType+" "+scopeName+classTempList+"::"+funcName+funcTempList;
+ }
+ else
+ {
+ funcDecl=funcType+" "+scopeName+classTempList+"::"+funcName+funcArgs;
+ }
+ }
+ else
+ {
+ if (isFunc) // a function => we use argList for the arguments
+ {
+ funcDecl=scopeName+classTempList+"::"+funcName+funcTempList;
+ }
+ else // variable => add `argument' list
+ {
+ funcDecl=scopeName+classTempList+"::"+funcName+funcArgs;
+ }
+ }
+ }
+ else // build declaration without scope
+ {
+ if (funcType.length()>0) // but with a type
+ {
+ if (isFunc) // function => omit argument list
+ {
+ funcDecl=funcType+" "+funcName+funcTempList;
+ }
+ else // variable => add `argument' list
+ {
+ funcDecl=funcType+" "+funcName+funcArgs;
+ }
+ }
+ else // no type
+ {
+ if (isFunc)
+ {
+ funcDecl=funcName+funcTempList;
+ }
+ else
+ {
+ funcDecl=funcName+funcArgs;
+ }
+ }
+ }
+
+ QString fullFuncDecl=funcDecl.copy();
+ if (isFunc) fullFuncDecl+=argListToString(root->argList);
+
+ //printf("scopeName=`%s' className=`%s'\n",scopeName.data(),className.data());
+ // see if (part of) the scope name is a namespace name
+ extractNamespaceName(scopeName,className,namespaceName);
+ //printf("scopeName=`%s' className=`%s'\n",scopeName.data(),className.data());
+
+ // destructor => do backward class name substitution if needed
+ //if (funcName.length()>0 && funcName[0]=='~')
+ // funcName="~"+resolveDefines(className);
+ // constructor => do backward class name substitution if needed
+ //if (funcName==className) funcName=resolveDefines(className);
+ //if (funcDecl.left(7)=="inline ") funcDecl=funcDecl.right(funcDecl.length()-7);
+
+ Debug::print(Debug::FindMembers,0,
+ "findMember() Parse results:\n"
+ " namespaceName=`%s'\n"
+ " className=`%s`\n"
+ " classTempList=`%s'\n"
+ " funcType=`%s'\n"
+ " funcName=`%s'\n"
+ " funcArgs=`%s'\n"
+ " funcTempList=`%s'\n"
+ " funcDecl=`%s'\n"
+ " related=`%s'\n"
+ " exceptions=`%s'\n"
+ " isRelated=%d\n"
+ " isFiend=%d\n"
+ " isFunc=%d\n\n",
+ namespaceName.data(),className.data(),classTempList.data(),
+ funcType.data(),funcName.data(),funcArgs.data(),funcTempList.data(),
+ funcDecl.data(),related.data(),exceptions.data(),isRelated,isFriend,
+ isFunc
+ );
+
+ MemberName *mn;
+ if (funcName.length()>0) // function name is valid
+ {
+ if (!isRelated && (mn=memberNameDict[funcName])) // function name already found
+ {
+ if (className.length()>0) // class name is valid
+ {
+ int count=0;
+ MemberDef *md=mn->first();
+ while (md)
+ {
+ ClassDef *cd=md->memberClass();
+ //printf("Member %s member className=%s this className=%s\n",md->name().data(),cd->name().data(),className.data());
+ ClassDef *tcd=0;
+ if (classTempList.length()>0) // try to find the correct specialization
+ {
+ tcd=getClass(scopeName+classTempList);
+ if (!tcd) tcd=getClass(scopeName); // try general class
+ }
+ else
+ {
+ tcd=getClass(scopeName);
+ }
+ //printf("tcd=%p\n",tcd);
+ if (cd && tcd==cd)
+ {
+ //printf("Class %s\n",cd->name().data());
+ bool matching=
+ md->isVariable() || md->isTypedef() || // needed for function pointers
+ (md->argumentList()==0 && root->argList->count()==0) ||
+ matchArguments(md->argumentList(), root->argList,
+ className,namespaceName);
+ if (matching)
+ {
+ addMemberDocs(root,md,funcDecl,overloaded);
+ count++;
+ }
+ }
+ md=mn->next();
+ }
+ if (count==0)
+ warn("Warning: no matching member found for \n%s\n"
+ "in file %s at line %d\n",
+ fullFuncDecl.data(),root->fileName.data(),root->startLine);
+#if 0
+ else if (count>1)
+ {
+ warn("Warning: multiple matching members for\n%s\n",funcDecl.data());
+ int matchCount=0;
+ MemberDef *md=mn->first();
+ while (md)
+ {
+ if (md->memberClass() && className==md->memberClass()->name())
+ matchCount++;
+ md=mn->next();
+ }
+ if (matchCount>0)
+ {
+ warn("Possible candidates are:\n");
+ md=mn->first();
+ while (md)
+ {
+ ClassDef *cd=md->memberClass();
+ if (cd && className==cd->name())
+ warn(" %s::%s%s\n",md->memberClass()->name(),
+ md->name(),md->argsString());
+ md=mn->next();
+ }
+ }
+ }
+#endif
+ }
+ else if (overloaded) // check if the function belongs to only one class
+ {
+ // for unique overloaded member we allow the class to be
+ // omitted, this is to be Qt compatable. Using this should
+ // however be avoided, because it is error prone
+ MemberDef *md=mn->first();
+ ASSERT(md);
+ ClassDef *cd=md->memberClass();
+ ASSERT(cd);
+ QString className=cd->name().copy();
+ md=mn->next();
+ bool unique=TRUE;
+ while (md)
+ {
+ ClassDef *cd=md->memberClass();
+ if (className!=cd->name()) unique=FALSE;
+ md=mn->next();
+ }
+ if (unique)
+ {
+ MemberDef::MemberType mtype;
+ if (root->sig) mtype=MemberDef::Signal;
+ else if (root->slot) mtype=MemberDef::Slot;
+ else mtype=MemberDef::Function;
+
+ // new overloaded member function
+ MemberDef *md=new MemberDef(funcType,funcName,funcArgs,exceptions,
+ root->protection,root->virt,root->stat,TRUE,
+ mtype,root->tArgList,root->argList);
+ md->setMemberClass(cd);
+ md->setDefinition(funcDecl);
+ QString doc=getOverloadDocs();
+ doc+="<p>";
+ doc+=root->doc;
+ md->setDocumentation(doc);
+ //md->setDecFile(root->fileName);
+ //md->setDecLine(root->startLine);
+ md->setDefFile(root->fileName);
+ md->setDefLine(root->startLine);
+ md->setPrototype(root->proto);
+ mn->inSort(md);
+ cd->insertMember(md);
+ cd->insertUsedFile(root->fileName);
+ }
+ }
+ else // unrelated function with the same name as a member
+ {
+ if (!findUnrelatedFunction(root,namespaceName,funcName+funcTempList,funcArgs,funcDecl))
+ {
+ warn("Warning: Cannot determine class for function\n%s\n"
+ "in file %s at line %d\n",fullFuncDecl.data(),
+ root->fileName.data(),root->startLine);
+ }
+ }
+ }
+ else if (isRelated && related.length()>0)
+ {
+ if (className.isEmpty()) className=related.copy();
+ ClassDef *cd;
+ if ((cd=getClass(scopeName)))
+ {
+ bool newMember=TRUE; // assume we have a new member
+ bool newMemberName=FALSE;
+ if ((mn=memberNameDict[funcName])==0)
+ {
+ mn=new MemberName(funcName);
+ newMemberName=TRUE; // we create a new member name
+ }
+ else
+ {
+ MemberDef *rmd=mn->first();
+ while (rmd && newMember) // see if we got another member with matching arguments
+ {
+ newMember=newMember &&
+ !matchArguments(rmd->argumentList(),root->argList,className,namespaceName);
+ if (newMember) rmd=mn->next();
+ }
+ if (!newMember && rmd) // member already exists as rmd -> add docs
+ {
+ addMemberDocs(root,rmd,funcDecl,overloaded);
+ }
+ }
+ if (newMember) // need to create a new member
+ {
+ MemberDef::MemberType mtype;
+ if (root->sig)
+ mtype=MemberDef::Signal;
+ else if (root->slot)
+ mtype=MemberDef::Slot;
+ else
+ mtype=MemberDef::Function;
+
+ // new related (member) function
+ MemberDef *md=new MemberDef(funcType,funcName,funcArgs,exceptions,
+ root->protection,root->virt,root->stat,TRUE,
+ mtype,root->tArgList,root->argList);
+ //printf("Related member name=`%s' decl=`%s'\n",funcName.data(),funcDecl.data());
+ md->setMemberClass(cd);
+ md->setDefinition(funcDecl);
+ md->setDocumentation(root->doc);
+ md->setBriefDescription(root->brief);
+ md->setDefFile(root->fileName);
+ md->setDefLine(root->startLine);
+ md->setPrototype(root->proto);
+ mn->inSort(md);
+ cd->insertMember(md);
+ cd->insertUsedFile(root->fileName);
+ if (newMemberName)
+ {
+ //printf("Adding memberName=%s\n",mn->memberName());
+ memberNameList.inSort(mn);
+ memberNameDict.insert(funcName,mn);
+ }
+ }
+ }
+ else
+ {
+ warn("Warning: class `%s' for related function `%s' is not "
+ "documented\n", className.data(),funcName.data());
+ }
+ }
+ else // unrelated not overloaded member found
+ {
+ if (className.length()==0 &&
+ !findUnrelatedFunction(root,namespaceName,funcName+funcTempList,funcArgs,funcDecl))
+ {
+ warn("Warning: class for member %s (file %s at line %d) cannot "
+ "be found\n", funcName.data(),root->fileName.data(),
+ root->startLine);
+ }
+ }
+ }
+ else
+ {
+ // this should not be called
+ warn("Warning: member with no name found in %s at line %d\n",
+ root->fileName.data(),root->startLine);
+ }
+ return;
+}
+
+//----------------------------------------------------------------------
+// find the members corresponding to the different documentation blocks
+// that are extracted from the sources.
+
+void findMemberDocumentation(Entry *root)
+{
+ int i,l;
+ QRegExp re("([a-zA-Z0-9: ]*[ *]+[ ]*");
+ Debug::print(Debug::FindMembers,0,
+ "root->type=`%s' root->name=`%s' root->args=`%s'\n",
+ root->type.data(),root->name.data(),root->args.data()
+ );
+ bool isFunc=TRUE;
+ if ((i=re.match(root->type,0,&l))!=-1) // func variable/typedef to func ptr
+ {
+ root->args+=root->type.right(root->type.length()-i-l);
+ root->type=root->type.left(i+l);
+ isFunc=FALSE;
+ }
+ else if (root->name.find(re)!=-1 && root->name.find("operator")!=-1)
+ // func ptr entered with \fn, \var or \typedef
+ {
+ isFunc=FALSE;
+ }
+ else if ((root->type.isEmpty() && root->name.left(8)=="typedef ")
+ || root->args.find('(')==-1)
+ {
+ isFunc=FALSE;
+ }
+ //printf("Member %s isFunc=%d\n",root->name.data(),isFunc);
+ if (root->section==Entry::MEMBERDOC_SEC)
+ {
+ //printf("Documentation for inline member `%s' found args=`%s'\n",
+ // root->name.data(),root->args.data());
+ //if (root->relates.length()) printf(" Relates %s\n",root->relates.data());
+ findMember(root,root->name+root->args+root->exception,root->relates,FALSE,isFunc);
+ }
+ else if (root->section==Entry::OVERLOADDOC_SEC)
+ {
+ //printf("Overloaded member %s found\n",root->name.data());
+ findMember(root,root->name,root->relates,TRUE,isFunc);
+ }
+ else if (root->section==Entry::FUNCTION_SEC &&
+ (root->doc.length()>0 || root->brief.length()>0 || extractAllFlag))
+ {
+ //printf("Documentation for member `%s' found args=`%s' excp=`%s'\n",
+ // root->name.data(),root->args.data(),root->exception.data());
+ //if (root->relates.length()) printf(" Relates %s\n",root->relates.data());
+ //printf("Inside=%s\n Relates=%s\n",root->inside.data(),root->relates.data());
+ if (root->type.length()>0)
+ {
+ findMember(root,
+ root->type+" "+root->inside+root->name+root->args+root->exception,
+ root->relates,
+ FALSE,isFunc);
+ }
+ else
+ {
+ findMember(root,
+ root->inside+root->name+root->args+root->exception,
+ root->relates,
+ FALSE,isFunc);
+ }
+ }
+ else if (root->section==Entry::VARIABLEDOC_SEC)
+ {
+ //printf("Documentation for variable %s found\n",root->name.data());
+ //if (root->relates.length()>0) printf(" Relates %s\n",root->relates.data());
+ findMember(root,root->name,root->relates,FALSE,FALSE);
+ }
+ EntryListIterator eli(*root->sublist);
+ Entry *e;
+ for (;(e=eli.current());++eli)
+ {
+ if (e->section!=Entry::ENUM_SEC) findMemberDocumentation(e);
+ }
+}
+
+//----------------------------------------------------------------------
+// find and add the enumeration to their classes, namespaces or files
+
+void findEnums(Entry *root)
+{
+ if (root->section==Entry::ENUM_SEC)
+ // non anonymous enumeration
+ {
+ MemberDef *md=0;
+ ClassDef *cd=0;
+ FileDef *fd=0;
+ NamespaceDef *nd=0;
+ MemberNameDict *mnd=0;
+ MemberNameList *mnl=0;
+ bool isGlobal;
+ //printf("Found enum with name `%s'\n",root->name.data());
+ int i;
+
+ QString name;
+ if ((i=root->name.findRev("::"))!=-1) // scope is specified
+ {
+ QString scope=root->name.left(i); // extract scope
+ name=root->name.right(root->name.length()-i-2); // extract name
+ cd=getClass(scope);
+ if (!cd) nd=namespaceDict[scope];
+ }
+ else // no scope, check the scope in which the docs where found
+ {
+ if (( root->parent->section & Entry::COMPOUND_MASK )
+ && root->parent->name.length()>0
+ ) // found enum docs inside a compound
+ {
+ cd=getClass(root->parent->name);
+ }
+ name=root->name.copy();
+ }
+ if (cd && name.length()>0) // found a enum inside a compound
+ {
+ //printf("Enum `%s'::`%s'\n",cd->name(),name.data());
+ fd=0;
+ mnd=&memberNameDict;
+ mnl=&memberNameList;
+ isGlobal=FALSE;
+ }
+ else if (nd) // found enum inside namespace
+ {
+ mnd=&functionNameDict;
+ mnl=&functionNameList;
+ isGlobal=TRUE;
+ }
+ else // found a global enum
+ {
+ bool ambig;
+ fd=findFileDef(&inputNameDict,root->fileName,ambig);
+ mnd=&functionNameDict;
+ mnl=&functionNameList;
+ isGlobal=TRUE;
+ }
+ if (name.length()>0)
+ {
+ // new enum type
+ md = new MemberDef(0,name,0,0,root->protection,Normal,FALSE,FALSE,
+ MemberDef::Enumeration,0,0);
+ if (!isGlobal) md->setMemberClass(cd); else md->setFileDef(fd);
+ md->setDefFile(root->fileName);
+ md->setDefLine(root->startLine);
+ if (nd)
+ {
+ md->setDefinition(nd->name()+"::"+name);
+ nd->insertMember(md);
+ md->setNamespace(nd);
+ }
+ else if (isGlobal)
+ {
+ md->setDefinition(name);
+ fd->insertMember(md);
+ }
+ else if (cd)
+ {
+ md->setDefinition(cd->name()+"::"+name);
+ cd->insertMember(md);
+ cd->insertUsedFile(root->fileName);
+ }
+ md->setDocumentation(root->doc);
+ md->setBriefDescription(root->brief);
+
+ MemberName *mn;
+ if ((mn=(*mnd)[name]))
+ {
+ // this is used if the same enum is in multiple namespaces/classes
+ mn->inSort(md);
+ }
+ else // new enum name
+ {
+ mn = new MemberName(name);
+ mn->inSort(md);
+ mnd->insert(name,mn);
+ mnl->inSort(mn);
+ //printf("add %s to new memberName. Now %d members\n",
+ // name.data(),mn->count());
+ }
+
+ EntryListIterator eli(*root->sublist);
+ Entry *e;
+ for (;(e=eli.current());++eli)
+ {
+ MemberName *fmn=0;
+ if (e->name.length()>0 && (fmn=(*mnd)[e->name]))
+ // get list of members with the same name as the field
+ {
+ MemberDef *fmd=fmn->first();
+ while (fmd) // search for the class with the right name
+ {
+ if (nd)
+ {
+ NamespaceDef *fnd=fmd->getNamespace();
+ if (fnd==nd)
+ {
+ md->insertEnumField(fmd);
+ fmd->setEnumScope(md);
+ }
+ }
+ else if (isGlobal)
+ {
+ FileDef *ffd=fmd->getFileDef();
+ if (ffd==fd)
+ {
+ md->insertEnumField(fmd);
+ fmd->setEnumScope(md);
+ }
+ }
+ else
+ {
+ ClassDef *fcd=fmd->memberClass();
+ if (fcd==cd)
+ {
+ md->insertEnumField(fmd); // add field def to list
+ fmd->setEnumScope(md); // cross ref with enum name
+ }
+ }
+ fmd=fmn->next();
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ EntryListIterator eli(*root->sublist);
+ Entry *e;
+ for (;(e=eli.current());++eli)
+ {
+ findEnums(e);
+ }
+ }
+}
+
+//----------------------------------------------------------------------
+// find the documentation blocks for the enumerations
+
+void findEnumDocumentation(Entry *root)
+{
+ if (root->section==Entry::ENUMDOC_SEC
+ && root->name.length()>0
+ && root->name[0]!='@' // skip anonymous enums
+ )
+ {
+ //printf("Found docs for enum with name `%s'\n",root->name.data());
+ int i;
+ ClassDef *cd=0;
+ QString name;
+ if ((i=root->name.findRev("::"))!=-1) // scope is specified
+ {
+ QString scope=root->name.left(i); // extract scope
+ name=root->name.right(root->name.length()-i-2); // extract name
+ cd=getClass(scope);
+ //printf("Scope=`%s' Name=`%s'\n",scope.data(),name.data());
+ }
+ else // no scope, check the scope in which the docs where found
+ {
+ if (( root->parent->section & Entry::COMPOUND_MASK )
+ && root->parent->name.length()>0
+ ) // found enum docs inside a compound
+ {
+ cd=getClass(root->parent->name);
+ }
+ name=root->name.copy();
+ }
+ if (name.length()>0)
+ {
+ bool found=FALSE;
+ if (cd)
+ {
+ //printf("Enum: scope=`%s' name=`%s'\n",cd->name(),name.data());
+ QString className=cd->name().copy();
+ MemberName *mn=memberNameDict[name];
+ if (mn)
+ {
+ MemberDef *md=mn->first();
+ while (md && !found)
+ {
+ ClassDef *cd=md->memberClass();
+ if (cd && cd->name()==className)
+ {
+ // documentation outside a compound overrides the documentation inside it
+ if (!md->documentation() || root->parent->name.length()==0)
+ {
+ md->setDocumentation(root->doc);
+ }
+
+ // brief descriptions inside a compound override the documentation
+ // outside it
+ if (!md->briefDescription() || root->parent->name.length()>0)
+ {
+ md->setBriefDescription(root->brief);
+ }
+ found=TRUE;
+ }
+ md=mn->next();
+ }
+ }
+ else
+ {
+ //printf("MemberName %s not found!\n",name.data());
+ }
+ }
+ else // enum outside class
+ {
+ MemberDef *md;
+ MemberName *mn=functionNameDict[name];
+ if (mn && (md=mn->first()))
+ {
+ md->setDocumentation(root->doc);
+ md->setBriefDescription(root->brief);
+ found=TRUE;
+ }
+ }
+ if (!found)
+ {
+ warn("Warning: Documentation for undefined enum `%s' found at"
+ " line %d of file %s\n",name.data(),
+ root->startLine,root->fileName.data());
+ }
+ }
+ }
+ EntryListIterator eli(*root->sublist);
+ Entry *e;
+ for (;(e=eli.current());++eli)
+ {
+ findEnumDocumentation(e);
+ }
+}
+
+//----------------------------------------------------------------------
+// recursive function:
+// returns TRUE iff class definition `bcd' represents an (in)direct base
+// class of class definition `cd'.
+
+bool isBaseClass(ClassDef *bcd,ClassDef *cd)
+{
+ bool found=FALSE;
+ //printf("isBaseClass(cd=%s) looking for %s\n",cd->name().data(),bcd->name().data());
+ BaseClassListIterator bcli(*cd->baseClasses());
+ for ( ; bcli.current() && !found ; ++bcli)
+ {
+ ClassDef *ccd=bcli.current()->classDef;
+ //printf("isBaseClass() baseclass %s\n",ccd->name().data());
+ if (ccd==bcd)
+ found=TRUE;
+ else
+ found=isBaseClass(bcd,ccd);
+ }
+ return found;
+}
+
+//----------------------------------------------------------------------
+// computes the relation between all members. For each member `m'
+// the members that override the implementation of `m' are searched and
+// the member that `m' overrides is searched.
+
+void computeMemberRelations()
+{
+ MemberName *mn=memberNameList.first();
+ while (mn) // for each member name
+ {
+ MemberNameIterator mdi(*mn);
+ for ( ; mdi.current() ; ++mdi) // for each function with a specific name
+ {
+ MemberDef *md=mdi.current();
+ MemberNameIterator bmdi(*mn);
+ for ( ; bmdi.current() ; ++bmdi) // for each other function with that name
+ {
+ MemberDef *bmd=bmdi.current();
+ if (md!=bmd && bmd->memberClass() && md->memberClass() &&
+ isBaseClass(bmd->memberClass(),md->memberClass()))
+ {
+ //printf("Checking Base: %s\nWith normal : %s\n",bmd->definition(),md->definition());
+ if (/*matchArguments(bmd->argsString(),md->argsString())*/
+ matchArguments(bmd->argumentList(),md->argumentList())
+ )
+ {
+ //printf("Base: %s\nNorm: %s\n",bmd->definition(),md->definition());
+ ClassDef *bmcd = bmd->memberClass();
+ ClassDef *mcd = md->memberClass();
+ if (mcd && bmcd &&
+ (bmcd->protection()!=Private || extractPrivateFlag) &&
+ (bmcd->hasDocumentation() || !hideClassFlag) &&
+ (mcd->protection()!=Private || extractPrivateFlag) &&
+ (mcd->hasDocumentation() || !hideClassFlag)
+ )
+ {
+ md->setReimplements(bmd);
+ bmd->insertReimplementedBy(md);
+ }
+ }
+ }
+ }
+ }
+ mn=memberNameList.next();
+ }
+}
+
+//----------------------------------------------------------------------------
+// recusively merges the `all members' lists of class cd's base classes
+// with that of class `cd' itself.
+
+void mergeMembers(ClassDef *cd,BaseClassList *bcl)
+{
+ //if (mcd->flag==TRUE)
+ //{
+ // err("Error: Cyclic inhertance dependency found for class %s\n",mcd->name());
+ // return;
+ //}
+ //mcd->flag=TRUE;
+
+ BaseClassListIterator bcli(*bcl);
+ BaseClassDef *bcd;
+ for ( ; (bcd=bcli.current()) ; ++bcli )
+ {
+ ClassDef *bClass=bcd->classDef;
+ // merge the members of bClass with the onces from cd
+
+ mergeMembers(bClass,bClass->baseClasses());
+ // the all member list of the branch until bClass is now complete
+ // so we can merge it with cd
+
+ MemberNameInfoList *srcMnl = bClass->memberNameInfoList();
+ MemberNameInfoDict *dstMnd = cd->memberNameInfoDict();
+ MemberNameInfoList *dstMnl = cd->memberNameInfoList();
+
+ MemberNameInfoListIterator srcMnili(*srcMnl);
+ MemberNameInfo *srcMni;
+ for ( ; (srcMni=srcMnili.current()) ; ++srcMnili)
+ {
+ //printf("Base member name %s\n",srcMni->memberName());
+ MemberNameInfo *dstMni;
+ if ((dstMni=dstMnd->find(srcMni->memberName())))
+ // a member with that name is already in the class.
+ // the member may hide or reimplement the one in the super class
+ // or there may be another path to the base class that is already
+ // visited via another branch in the class hierarchy.
+ {
+ MemberNameInfoIterator srcMnii(*srcMni);
+ MemberInfo *srcMi;
+ for ( ; (srcMi=srcMnii.current()) ; ++srcMnii )
+ {
+ MemberDef *srcMd = srcMi->memberDef;
+ bool found=FALSE;
+ bool ambigue=FALSE;
+ MemberNameInfoIterator dstMnii(*dstMni);
+ MemberInfo *dstMi;
+ for ( ; (dstMi=dstMnii.current()) && !found; ++dstMnii )
+ {
+ MemberDef *dstMd = dstMi->memberDef;
+ if (srcMd!=dstMd) // different members
+ {
+ ClassDef *srcCd = srcMd->memberClass();
+ ClassDef *dstCd = dstMd->memberClass();
+ //printf("Is %s a base class of %s?\n",srcCd->name(),dstCd->name());
+ if (srcCd==dstCd || isBaseClass(srcCd,dstCd))
+ // member is in the same or a base class
+ {
+ found =
+ /*matchArguments(srcMd->argsString(),dstMd->argsString());*/
+ matchArguments(srcMd->argumentList(),dstMd->argumentList());
+ }
+ else // member is in a non base class => multiple inheritance
+ // using the same base class.
+ {
+ //printf("$$ Existing member %s %s add scope %s\n",
+ // dstMi->ambiguityResolutionScope.data(),
+ // dstMd->name().data(),
+ // dstMi->scopePath.left(dstMi->scopePath.find("::")+2).data());
+
+ QString scope=dstMi->scopePath.left(dstMi->scopePath.find("::")+2);
+ if (scope!=dstMi->ambiguityResolutionScope.left(scope.length()))
+ dstMi->ambiguityResolutionScope.prepend(scope);
+ ambigue=TRUE;
+ }
+ }
+ else // same members
+ {
+ // do not add if base class is virtual or
+ // if scope paths are equal
+ if ((srcMi->virt==Virtual && dstMi->virt==Virtual) ||
+ bClass->name()+"::"+srcMi->scopePath == dstMi->scopePath
+ ) found=TRUE;
+ else // member can be reached via multiple paths in the
+ // inheritance tree
+ {
+ //printf("$$ Existing member %s %s add scope %s\n",
+ // dstMi->ambiguityResolutionScope.data(),
+ // dstMd->name().data(),
+ // dstMi->scopePath.left(dstMi->scopePath.find("::")+2).data());
+
+ QString scope=dstMi->scopePath.left(dstMi->scopePath.find("::")+2);
+ if (scope!=dstMi->ambiguityResolutionScope.left(scope.length()))
+ dstMi->ambiguityResolutionScope.prepend(scope);
+ ambigue=TRUE;
+ }
+ }
+ }
+ if (!found && srcMd->protection()!=Private)
+ {
+ Specifier virt=srcMi->virt;
+ if (srcMi->virt==Normal && bcd->virt!=Normal) virt=bcd->virt;
+ MemberInfo *newMi = new MemberInfo(srcMd,bcd->prot,virt);
+ //if (srcMi->memberDef->memberClass()!=bClass)
+ newMi->scopePath=bClass->name()+"::"+srcMi->scopePath;
+ if (ambigue)
+ {
+ //printf("$$ New member %s %s add scope %s::\n",
+ // srcMi->ambiguityResolutionScope.data(),
+ // srcMd->name().data(),
+ // bClass->name().data());
+
+ QString scope=bClass->name().copy(); scope+="::";
+ if (scope!=srcMi->ambiguityResolutionScope.left(scope.length()))
+ newMi->ambiguityResolutionScope=
+ scope+srcMi->ambiguityResolutionScope;
+ }
+ dstMni->append(newMi);
+ }
+ }
+ }
+ else // base class has a member that is not in the super class => copy
+ {
+ // create a deep copy of the list (only the MemberInfo's will be
+ // copied, not the actual MemberDef's)
+ MemberNameInfo *newMni = new MemberNameInfo(srcMni->memberName());
+
+ // copy the member(s) from the base to the super class
+ MemberNameInfoIterator mnii(*srcMni);
+ MemberInfo *mi;
+ for (;(mi=mnii.current());++mnii)
+ {
+ if (mi->memberDef->protection()!=Private)
+ {
+ Specifier virt=mi->virt;
+ if (mi->virt==Normal && bcd->virt!=Normal) virt=bcd->virt;
+ MemberInfo *newMi=new MemberInfo(mi->memberDef,bcd->prot,virt);
+ //if (mi->memberDef->memberClass()!=bClass)
+ newMi->scopePath=bClass->name()+"::"+mi->scopePath;
+ newMi->ambiguityResolutionScope=mi->ambiguityResolutionScope.copy();
+ newMni->append(newMi);
+ }
+ }
+
+ // add it to the list and dictionary
+ dstMnl->inSort(newMni);
+ dstMnd->insert(newMni->memberName(),newMni);
+ }
+ }
+ }
+}
+
+//----------------------------------------------------------------------------
+// builds the list of all members for each class
+
+void buildCompleteMemberLists()
+{
+ ClassDef *cd;
+ ClassListIterator cli(classList);
+ for (;(cd=cli.current());++cli)
+ {
+ //if (!cd->isReference()) printf("Building member for class %s\n",cd->name());
+ //ClassListIterator vcli(classList);
+ //for (;(vcd=vcli.current());++vcli) vcd->flag = FALSE;
+ if (!cd->isReference() && // not an external class
+ cd->superClasses()->count()==0 && // is a root of the hierarchy
+ cd->baseClasses()->count()>0) // and has at least one base class
+ {
+ //printf("merging members for class %s\n",cd->name());
+ mergeMembers(cd,cd->baseClasses());
+ }
+ }
+}
+
+//----------------------------------------------------------------------------
+
+void generateFileDocs()
+{
+ if (documentedFiles==0) return;
+ writeFileIndex(*outputList);
+
+ if (inputNameList.count()>0)
+ {
+ FileName *fn=inputNameList.first();
+ while (fn)
+ {
+ FileDef *fd=fn->first();
+ while (fd)
+ {
+ if (!fd->isReference() && fd->hasDocumentation())
+ {
+ msg("Generating docs for file %s...\n",fd->name().data());
+ fd->writeDocumentation(*outputList);
+ }
+ fd=fn->next();
+ }
+ fn=inputNameList.next();
+ }
+ }
+}
+
+//----------------------------------------------------------------------------
+// generate the documentation of all classes
+
+void generateClassDocs()
+{
+ // write the installdox script if necessary
+ if (generateHtml && (tagFileList.count()>0 || searchEngineFlag))
+ writeInstallScript();
+
+ msg("Generating index page...\n");
+ writeIndex(*outputList);
+
+ msg("Generating compound index...\n");
+ writeAnnotatedIndex(*outputList);
+
+ msg("Generating hierarchical class index...\n");
+ writeHierarchicalIndex(*outputList);
+
+ if (includeFiles.count()>0)
+ {
+ msg("Generating header index...\n");
+ writeHeaderIndex(*outputList);
+ }
+
+ msg("Generating member index...\n");
+ writeMemberIndex(*outputList);
+
+ if (exampleList.count()>0)
+ {
+ msg("Generating example index...\n");
+ }
+
+ ClassListIterator cli(classList);
+ for ( ; cli.current() ; ++cli )
+ {
+ ClassDef *cd=cli.current();
+ if (!cd->isReference() &&
+ //!cd->name().isEmpty() &&
+ //cd->name().at(0)!='@' &&
+ //(cd->protection()!=Private || extractPrivateFlag) &&
+ //(cd->hasDocumentation() || !hideClassFlag)
+ cd->isVisible()
+ )
+ // skip external references and anonymous compounds
+ {
+ msg("Generating docs for compound %s...\n",cd->name().data());
+
+ cd->writeDocumentation(*outputList);
+ cd->writeMemberList(*outputList);
+ if (verbatimHeaderFlag) cd->writeIncludeFile(*outputList);
+ }
+ }
+}
+
+//----------------------------------------------------------------------------
+
+void findDefineDocumentation(Entry *root)
+{
+ if ((root->section==Entry::DEFINEDOC_SEC ||
+ root->section==Entry::DEFINE_SEC) && root->name.length()>0
+ )
+ {
+ //printf("found define `%s' `%s' brief=`%s' doc=`%s'\n",
+ // root->name.data(),root->args.data(),root->brief.data(),root->doc.data());
+ MemberName *mn=functionNameDict[root->name];
+ if (mn)
+ {
+ int count=0;
+ MemberDef *md=mn->first();
+ while (md)
+ {
+ if (md->memberType()==MemberDef::Define) count++;
+ md=mn->next();
+ }
+ if (count==1)
+ {
+ md=mn->first();
+ while (md)
+ {
+ if (md->memberType()==MemberDef::Define)
+ {
+ if (md->documentation().isEmpty())
+ md->setDocumentation(root->doc);
+ if (md->briefDescription().isEmpty())
+ md->setBriefDescription(root->brief);
+ }
+ md=mn->next();
+ }
+ }
+ else if (count>1 && (root->doc.length()>0 || root->brief.length()>0))
+ // multiple defines don't know where to add docs
+ {
+ md=mn->first();
+ while (md)
+ {
+ if (md->memberType()==MemberDef::Define)
+ {
+ FileDef *fd=md->getFileDef();
+ if (fd && fd->absFilePath()==root->fileName)
+ // doc and define in the same file assume they belong together.
+ {
+ if (md->documentation().isEmpty())
+ md->setDocumentation(root->doc);
+ if (md->briefDescription().isEmpty())
+ md->setBriefDescription(root->brief);
+ }
+ }
+ md=mn->next();
+ }
+ //warn("Warning: define %s found in the following files:\n",root->name.data());
+ //warn("Cannot determine where to add the documentation found "
+ // "at line %d of file %s. \n",
+ // root->startLine,root->fileName.data());
+ }
+ }
+ else // define not found
+ {
+ warn("Warning: documentation for unknown define %s found at line %d of "
+ "file %s\n",root->name.data(),root->startLine,root->fileName.data());
+ }
+ }
+ EntryListIterator eli(*root->sublist);
+ Entry *e;
+ for (;(e=eli.current());++eli)
+ {
+ findDefineDocumentation(e);
+ }
+}
+
+//----------------------------------------------------------------------------
+
+//----------------------------------------------------------------------------
+// create a (sorted) list of separate documentation pages
+
+void buildPageList(Entry *root)
+{
+ if (root->section == Entry::PAGEDOC_SEC)
+ {
+ if (root->name.length()>0)
+ {
+ PageInfo *pi=0;
+ if ((pi=pageDict[root->name]))
+ {
+ //warn("Warning: Page %s was already documented. Ignoring documentation "
+ // "at line %d of %s\n",root->name.data(),root->startLine,
+ // root->fileName.data());
+
+ // append documentation block to the page.
+ pi->doc+="\n\n"+root->doc;
+ }
+ else
+ {
+ QString baseName=root->name.copy();
+ if (baseName.right(4)==".tex")
+ baseName=baseName.left(baseName.length()-4);
+ else if (baseName.right(5)==".html")
+ baseName=baseName.left(baseName.length()-5);
+ pi=new PageInfo(baseName, root->doc,
+ root->args.stripWhiteSpace());
+ pageList.append(pi);
+ pageDict.insert(baseName,pi);
+ if (pi->title.length()>0)
+ {
+ QString pageName;
+ if (caseSensitiveNames)
+ pageName=pi->name.copy();
+ else
+ pageName=pi->name.lower();
+ //outputList->writeTitle(pi->name,pi->title);
+ SectionInfo *si=new SectionInfo(pageName+".html",
+ pi->name,pi->title,FALSE);
+ //printf("Adding section info %s\n",pi->name.data());
+ sectionDict.insert(pi->name,si);
+ }
+ }
+ }
+ }
+ EntryListIterator eli(*root->sublist);
+ Entry *e;
+ for (;(e=eli.current());++eli)
+ {
+ buildPageList(e);
+ }
+}
+
+//----------------------------------------------------------------------------
+// generate all separate documentation pages
+
+void generatePageDocs()
+{
+ PageInfo *pi=pageList.first();
+ while (pi)
+ {
+ if (!pi->title.isEmpty())
+ {
+ msg("Generating docs for page %s...\n",pi->title.data());
+ }
+ else
+ {
+ msg("Generating docs for page %s...\n",pi->name.data());
+ }
+ outputList->disable(OutputGenerator::Man);
+ QString pageName;
+ if (caseSensitiveNames)
+ pageName=pi->name.copy();
+ else
+ pageName=pi->name.lower();
+
+ startFile(*outputList,pageName,pi->title);
+ SectionInfo *si=0;
+ if (pi->title.length()>0 && pi->name.length()>0 &&
+ (si=sectionDict[pi->name])!=0)
+ {
+ outputList->writeSection(si->label,si->title,FALSE);
+ }
+ parseDoc(*outputList,0,0,pi->doc);
+ endFile(*outputList);
+ outputList->enable(OutputGenerator::Man);
+ pi=pageList.next();
+ }
+}
+
+//----------------------------------------------------------------------------
+// create a (sorted) list & dictionary of example pages
+
+void buildExampleList(Entry *root)
+{
+ if (root->section == Entry::EXAMPLE_SEC)
+ {
+ if (root->name.length()>0)
+ {
+ if (exampleDict[root->name])
+ {
+ warn("Warning: Example %s was already documented. Ignoring "
+ "documentation at line %d of %s\n",root->name.data(),
+ root->startLine,root->fileName.data());
+ }
+ else
+ {
+ PageInfo *pi=new PageInfo(root->name,root->doc,root->args);
+ exampleList.inSort(pi);
+ exampleDict.insert(root->name,pi);
+ }
+ }
+ }
+ //EntryList *entryList=root->sublist;
+ //Entry *e = entryList->first();
+ //while (e)
+ //{
+ // buildExampleList(e);
+ // e=entryList->next();
+ //}
+ EntryListIterator eli(*root->sublist);
+ Entry *e;
+ for (;(e=eli.current());++eli)
+ {
+ buildExampleList(e);
+ }
+}
+
+//----------------------------------------------------------------------------
+// generate the example documentation
+
+void generateExampleDocs()
+{
+ PageInfo *pi=exampleList.first();
+ while (pi)
+ {
+ msg("Generating docs for example %s...\n",pi->name.data());
+ QString n=convertSlashes(pi->name,TRUE)+"-example";
+ startFile(*outputList,n,"Example Documentation");
+ //outputList->writeTitle(pi->name,pi->name);
+ parseExample(*outputList,pi->doc+"\n\\include "+pi->name,pi->name);
+ endFile(*outputList);
+ pi=exampleList.next();
+ }
+}
+
+//----------------------------------------------------------------------------
+// generate module pages
+
+void generateGroupDocs()
+{
+ GroupListIterator gli(groupList);
+ GroupDef *gd;
+ for (;(gd=gli.current());++gli)
+ {
+ //printf("group %s #members=%d\n",gd->name().data(),gd->countMembers());
+ if (gd->countMembers()>0) gd->writeDocumentation(*outputList);
+ }
+}
+
+//----------------------------------------------------------------------------
+// generate module pages
+
+void generateNamespaceDocs()
+{
+ writeNamespaceIndex(*outputList);
+
+ NamespaceListIterator nli(namespaceList);
+ NamespaceDef *nd;
+ for (;(nd=nli.current());++nli)
+ {
+ msg("Generating docs for namespace %s\n",nd->name().data());
+ nd->writeDocumentation(*outputList);
+ }
+}
+
+//----------------------------------------------------------------------------
+// generate files for the search engine
+
+void generateSearchIndex()
+{
+ if (searchEngineFlag && generateHtml)
+ {
+ // create search index
+ QString fileName;
+ writeSearchButton(htmlOutputDir);
+
+ // create cgi script
+ fileName = htmlOutputDir+"/"+cgiName;
+ QFile f(fileName);
+ if (f.open(IO_WriteOnly))
+ {
+ QTextStream t(&f);
+ t << "#!/bin/sh" << endl
+ << "DOXYSEARCH=" << binAbsPath << "/doxysearch" << endl
+ << "DOXYPATH=" << docAbsPath << " ";
+
+ char *s=extDocPathList.first();
+ while (s)
+ {
+ t << s << " ";
+ s=extDocPathList.next();
+ }
+
+ t << endl
+ << "if [ -f $DOXYSEARCH ]" << endl
+ << "then" << endl
+ << " $DOXYSEARCH $DOXYPATH" << endl
+ << "else" << endl
+ << " echo \"Content-Type: text/html\"" << endl
+ << " echo \"\"" << endl
+ << " echo \"<H1>Error: $DOXYSEARCH not found. Check cgi script!\"" << endl
+ << "fi" << endl;
+
+ f.close();
+ struct stat stat_struct;
+ stat(fileName,&stat_struct);
+#if !defined(_WIN32)
+ chmod(fileName,stat_struct.st_mode|S_IXUSR|S_IXGRP|S_IXOTH);
+#endif
+ }
+ else
+ {
+ err("Error: Cannot open file %s for writing\n",fileName.data());
+ }
+
+ // create config file
+ fileName = htmlOutputDir+"/search.cfg";
+ f.setName(fileName);
+ if (f.open(IO_WriteOnly))
+ {
+ QTextStream t(&f);
+ t << docURL << endl << cgiURL << "/" << cgiName << endl;
+ f.close();
+ }
+ else
+ {
+ err("Error: Cannot open file %s for writing\n",fileName.data());
+ }
+ //outputList->generateExternalIndex();
+ outputList->disableAllBut(OutputGenerator::Html);
+ startFile(*outputList,"header.html","Search Engine",TRUE);
+ outputList->endPlainFile();
+ outputList->startPlainFile("footer.html");
+ endFile(*outputList,TRUE);
+ outputList->enableAll();
+ }
+}
+
+//----------------------------------------------------------------------------
+// generate the configuration file
+
+void generateConfigFile(const char *configFile,bool shortList)
+{
+ QFileInfo fi(configFile);
+ QFile f(configFile);
+
+ if (fi.exists()) // create a backup
+ {
+ QDir dir=fi.dir();
+ dir.rename(fi.fileName(),fi.fileName()+".bak");
+ }
+ if (f.open(IO_WriteOnly))
+ {
+ writeTemplateConfig(&f,shortList);
+ f.close();
+ msg("\n\nConfiguration file `%s' created.\n\n",configFile);
+ msg("Now edit the configuration file and enter\n\n");
+ if (strcmp(configFile,"Doxyfile") || strcmp(configFile,"doxyfile"))
+ msg(" doxygen %s\n\n",configFile);
+ else
+ msg(" doxygen\n\n");
+ msg("to generate the documentation for your project\n\n");
+ }
+ else
+ {
+ err("Error: Cannot open file %s for writing\n");
+ exit(1);
+ }
+}
+
+//----------------------------------------------------------------------------
+// read and parse a tag file
+
+bool readLineFromFile(QFile &f,QString &s)
+{
+ char c=0;
+ s.resize(0);
+ while (!f.atEnd() && (c=f.getch())!='\n') s+=c;
+ return f.atEnd();
+}
+
+void readTagFile(const char *file)
+{
+ QFileInfo fi(file);
+ if (!fi.exists() || !fi.isFile())
+ {
+ err("Error: Tag file `%s' does not exist or is not a file\n",file);
+ exit(1);
+ }
+ msg("Reading tag file %s...\n",file);
+ parseTagFile(file);
+}
+
+//----------------------------------------------------------------------------
+// returns TRUE if the name of the file represented by `fi' matches
+// one of the file patterns in the `patList' list.
+
+bool patternMatch(QFileInfo *fi,QStrList *patList)
+{
+ bool found=FALSE;
+ if (patList)
+ {
+ char *pattern=patList->first();
+ while (pattern && !found)
+ {
+ found = found || QDir::match(pattern,fi->fileName());
+ pattern=patList->next();
+ }
+ }
+ return found;
+}
+
+//----------------------------------------------------------------------------
+// reads a file into an array and filters out any 0x00 and 0x06 bytes,
+// because these are special for the parser.
+
+void copyAndFilterFile(const char *fileName,BufStr &dest)
+{
+ // try to open file
+ int size=0;
+ uint oldPos = dest.curPos();
+
+ QFileInfo fi(fileName);
+ if (!fi.exists()) return;
+ if (inputFilter.isEmpty())
+ {
+ QFile f(fileName);
+ if (!f.open(IO_ReadOnly))
+ {
+ err("Error: could not open file %s\n",fileName);
+ return;
+ }
+ size=fi.size();
+ // read the file
+ dest.skip(size);
+ if (f.readBlock(dest.data()+oldPos,size)!=size)
+ {
+ err("Error while reading file %s\n",fileName);
+ return;
+ }
+ }
+ else
+ {
+ int c;
+// char *p=dest;
+ QString cmd=inputFilter+" "+fileName;
+ FILE *f=popen(cmd,"r");
+ if (!f)
+ {
+ err("Error: could not execute filter %s\n",inputFilter.data());
+ return;
+ }
+ while ((c=fgetc(f))!=EOF) dest.addChar(c),size++;
+ }
+ // filter unwanted bytes from the resulting data
+ uchar *p=(uchar *)dest.data()+oldPos;
+ uchar conv[256];
+ int i;
+ for (i=0;i<256;i++) conv[i]=i;
+ conv[0x06]=0x20; // replace the offending characters with spaces
+ conv[0x00]=0x20;
+ // remove any special markers from the input
+ for (i=0;i<size;i++,p++) *p=conv[*p];
+ // adjust pointer
+}
+
+//----------------------------------------------------------------------------
+// Reads a file to a string.
+// The name of the file is written in front of the file's contents and
+// between 0x06 markers
+
+
+void readFiles(BufStr &output)
+{
+ QString *s=inputFiles.first();
+// char *p=output.data();
+ while (s)
+ {
+ QString fileName=*s;
+
+ //int fileSize=fi->fileInfo()->size();
+ int fileNameSize=fileName.length();
+ //int streamLength=fileSize+fileNameSize+4;
+
+ //QString fileText(streamLength);
+
+ // add begin filename marker
+// *p++=0x06;
+ output.addChar(0x06);
+ // copy filename
+// memcpy(p,fileName.data(),fileNameSize);
+// p+=fileNameSize;
+ output.addArray(fileName.data(),fileNameSize);
+
+ // add end filename marker
+// *p++=0x06;
+ output.addChar(0x06);
+// *p++='\n'; // to make ^ work while scanning the first line of a file!
+ output.addChar('\n');
+ if (preprocessingFlag)
+ {
+ msg("Preprocessing %s...\n",s->data());
+ preprocessFile(fileName,output);
+ }
+ else
+ {
+ msg("Reading %s...\n",s->data());
+ copyAndFilterFile(fileName,output);
+ }
+
+ s=inputFiles.next();
+ }
+// *p++='\0';
+ output.addChar(0);
+ //printf("Output after preprocessing:\n---------\n%s\n----------\n",output.data());
+ //printf("Final length = %d\n",p-output.data());
+}
+
+//----------------------------------------------------------------------------
+// Read all files matching at least one pattern in `patList' in the
+// directory represented by `fi'.
+// The directory is read iff the recusiveFlag is set.
+// The contents of all files is append to the input string
+
+int readDir(QFileInfo *fi,
+ FileNameList *fnList,
+ FileNameDict *fnDict,
+ StringDict *exclDict,
+ QStrList *patList,
+ QStrList *exclPatList,
+ StringList *resultList,
+ StringDict *resultDict
+ )
+{
+ QDir dir((const char *)fi->absFilePath());
+ dir.setFilter( QDir::Files | QDir::Dirs );
+ int totalSize=0;
+
+ const QFileInfoList *list = dir.entryInfoList();
+ QFileInfoListIterator it( *list );
+ QFileInfo *cfi;
+
+ while ((cfi=it.current()))
+ {
+ if (exclDict==0 || exclDict->find(cfi->absFilePath())==0)
+ { // file should not be excluded
+ if (!cfi->exists() || !cfi->isReadable())
+ {
+ err("Error: source %s is not a readable file or directory... skipping.\n",cfi->absFilePath().data());
+ }
+ else if (cfi->isFile() &&
+ patternMatch(cfi,patList) && !patternMatch(cfi,exclPatList))
+ {
+ totalSize+=cfi->size()+cfi->absFilePath().length()+3;
+ QString name=cfi->fileName();
+ if (fnDict)
+ {
+ FileDef *fd=new FileDef(cfi->dirPath()+"/",name);
+ FileName *fn=0;
+ if (name.length()>0 && (fn=(*fnDict)[name]))
+ {
+ fn->append(fd);
+ }
+ else
+ {
+ fn = new FileName(name);
+ fn->append(fd);
+ if (fnList) fnList->inSort(fn);
+ fnDict->insert(name,fn);
+ }
+ }
+ QString *rs=0;
+ if (resultList || resultDict)
+ {
+ rs=new QString(cfi->absFilePath());
+ }
+ if (resultList) resultList->append(rs);
+ if (resultDict) resultDict->insert(cfi->absFilePath(),rs);
+ }
+ else if (recursiveFlag && cfi->isDir() && cfi->fileName()!="." &&
+ cfi->fileName()!="..")
+ {
+ cfi->setFile(cfi->absFilePath());
+ totalSize+=readDir(cfi,fnList,fnDict,exclDict,
+ patList,exclPatList,resultList,resultDict);
+ }
+ }
+ ++it;
+ }
+ return totalSize;
+}
+
+//----------------------------------------------------------------------------
+// read the file with name `name' into a string.
+
+QString readExampleFile(const char *name)
+{
+ QString example;
+ QFileInfo fi(name);
+ if (fi.exists())
+ {
+ QFile f((const char *)fi.absFilePath());
+ if (f.open(IO_ReadOnly))
+ {
+ example.resize(fi.size()+1);
+ if ((int)fi.size()!=f.readBlock(example.data(),fi.size()))
+ {
+ err("Error while reading file %s\n",fi.absFilePath().data());
+ //exit(1);
+ return "";
+ }
+ example.at(fi.size())='\0';
+ }
+ else
+ {
+ err("Error opening file %s\n",fi.absFilePath().data());
+ //exit(1);
+ return "";
+ }
+ }
+ else
+ {
+ err("Error: example file %s does not exist\n",name);
+ exit(1);
+ }
+ return example;
+}
+
+//----------------------------------------------------------------------------
+// read a file or all files in a directory and append their contents to the
+// input string. The names of the files are appended to the `fiList' list.
+
+int readFileOrDirectory(const char *s,
+ FileNameList *fnList,
+ FileNameDict *fnDict,
+ StringDict *exclDict,
+ QStrList *patList,
+ QStrList *exclPatList,
+ StringList *resultList,
+ StringDict *resultDict
+ )
+{
+ QFileInfo fi(s);
+ int totalSize=0;
+ {
+ if (exclDict==0 || exclDict->find(fi.absFilePath())==0)
+ {
+ if (!fi.exists() || !fi.isReadable())
+ {
+ err("Error: source %s is not a readable file or directory... skipping.\n",s);
+ }
+ else if (fi.isFile())
+ {
+ totalSize+=fi.size()+fi.absFilePath().length()+3; //readFile(&fi,fiList,input);
+ //fiList->inSort(new FileInfo(fi));
+ QString name=fi.fileName();
+ if (fnDict)
+ {
+ FileDef *fd=new FileDef(fi.dirPath(TRUE)+"/",name);
+ FileName *fn=0;
+ if (name.length()>0 && (fn=(*fnDict)[name]))
+ {
+ fn->append(fd);
+ }
+ else
+ {
+ fn = new FileName(name);
+ fn->append(fd);
+ if (fnList) fnList->inSort(fn);
+ fnDict->insert(name,fn);
+ }
+ }
+ QString *rs=0;
+ if (resultList || resultDict)
+ {
+ rs=new QString(fi.absFilePath());
+ }
+ if (resultList) resultList->append(rs);
+ if (resultDict) resultDict->insert(fi.absFilePath(),rs);
+ }
+ else if (fi.isDir()) // readable dir
+ totalSize+=readDir(&fi,fnList,fnDict,exclDict,patList,
+ exclPatList,resultList,resultDict);
+ }
+ }
+ return totalSize;
+}
+
+//----------------------------------------------------------------------------
+
+void readFormulaRepository()
+{
+ QFile f(htmlOutputDir+"/formula.repository");
+ if (f.open(IO_ReadOnly)) // open repository
+ {
+ QTextStream t(&f);
+ QString line;
+ while (!t.eof())
+ {
+ line=t.readLine();
+ int se=line.find(':'); // find name and text separator.
+ if (se==-1)
+ {
+ warn("Warning: formula.repository is corrupted!\n");
+ break;
+ }
+ else
+ {
+ QString formName = line.left(se);
+ QString formText = line.right(line.length()-se-1);
+ Formula *f=new Formula(formText);
+ formulaList.append(f);
+ formulaDict.insert(formText,f);
+ formulaNameDict.insert(formName,f);
+ }
+ }
+ }
+}
+
+//----------------------------------------------------------------------------
+// print the usage of doxygen
+
+void usage(const char *name)
+{
+ msg("Doxygen version %s\nCopyright Dimitri van Heesch 1997-1999\n\n",versionString);
+ msg("You can use doxygen in two ways:\n\n");
+ msg("1) Use doxygen to generate a template configuration file:\n");
+ msg(" %s [-s] -g [configName]\n\n",name);
+ msg(" if -s is specified the comments in the config file will be omitted.\n\n");
+ msg("2) Use doxygen to generate documentation using an existing ");
+ msg("configuration file:\n");
+ msg(" %s [configName]\n\n",name);
+ msg("If configName is omitted `Doxyfile' will be used as a default.\n\n");
+ exit(1);
+}
+
+//----------------------------------------------------------------------------
+// read the argument of option `c' from the comment argument list and
+// update the option index `optind'.
+
+const char *getArg(int argc,char **argv,int &optind)
+{
+ char *s=0;
+ if (strlen(&argv[optind][2])>0)
+ s=&argv[optind][2];
+ else if (optind+1<argc)
+ s=argv[++optind];
+ return s;
+}
+
+//----------------------------------------------------------------------------
+
+int main(int argc,char **argv)
+{
+
+ initPreprocessor();
+
+ /**************************************************************************
+ * Handle arguments *
+ **************************************************************************/
+
+ char *s;
+ int optind=1;
+ const char *configName=0;
+ const char *debugLabel;
+ bool genConfig=FALSE;
+ bool shortList=FALSE;
+ while (optind<argc && argv[optind][0]=='-')
+ {
+ switch(argv[optind][1])
+ {
+ case 'g':
+ genConfig=TRUE;
+ configName=getArg(argc,argv,optind);
+ if (!configName) configName="Doxyfile";
+ break;
+ case 'd':
+ debugLabel=getArg(argc,argv,optind);
+ Debug::setFlag(debugLabel);
+ break;
+ case 's':
+ shortList=TRUE;
+ break;
+ case 'h':
+ case '?':
+ usage(argv[0]);
+ break;
+ default:
+ err("Unknown option -%c\n",argv[optind][1]);
+ usage(argv[0]);
+ }
+ optind++;
+ }
+
+ /**************************************************************************
+ * Parse or generate the config file *
+ **************************************************************************/
+
+ if (genConfig)
+ {
+ generateConfigFile(configName,shortList);
+ exit(1);
+ }
+
+ QFileInfo configFileInfo1("Doxyfile"),configFileInfo2("doxyfile");
+ QString config;
+ if (optind>=argc)
+ {
+ if (configFileInfo1.exists())
+ config=fileToString("Doxyfile");
+ else if (configFileInfo2.exists())
+ {
+ config=fileToString("doxyfile");
+ }
+ else
+ {
+ err("Doxyfile not found and no input file specified!\n");
+ usage(argv[0]);
+ }
+ }
+ else
+ config=fileToString(argv[1]);
+
+ parseConfig(config);
+
+ /**************************************************************************
+ * Initialize output generators *
+ **************************************************************************/
+
+ outputList = new OutputList(TRUE);
+ if (generateHtml)
+ {
+ outputList->add(new HtmlGenerator);
+ HtmlGenerator::init();
+ }
+ if (generateLatex)
+ {
+ outputList->add(new LatexGenerator);
+ LatexGenerator::init();
+ }
+ if (generateMan)
+ {
+ outputList->add(new ManGenerator);
+ ManGenerator::init();
+ }
+
+ /**************************************************************************
+ * Read and preprocess input *
+ **************************************************************************/
+
+ // gather names of all files in the include path
+ msg("Searching for include files...\n");
+ s=includePath.first();
+ while (s)
+ {
+ readFileOrDirectory(s,0,&includeNameDict,0,&filePatternList,
+ &excludePatternList,0,0);
+ s=includePath.next();
+ }
+
+ msg("Searching for example files...\n");
+ s=examplePath.first();
+ while (s)
+ {
+ readFileOrDirectory(s,0,&exampleNameDict,0,&filePatternList,
+ &excludePatternList,0,0);
+ s=examplePath.next();
+ }
+
+ msg("Searching for files to exclude\n");
+ s=excludeSources.first();
+ while (s)
+ {
+ readFileOrDirectory(s,0,0,0,&filePatternList,
+ 0,0,&excludeNameDict);
+ s=excludeSources.next();
+ }
+
+ msg("Reading input files...\n");
+ int inputSize=0;
+ s=inputSources.first();
+ while (s)
+ {
+ inputSize+=readFileOrDirectory(s,&inputNameList,
+ &inputNameDict,&excludeNameDict,
+ &filePatternList,&excludePatternList,
+ &inputFiles,0);
+ s=inputSources.next();
+ }
+ //msg("Input size %d bytes\n",inputSize);
+
+ BufStr input(inputSize+1); // Add one byte extra for \0 termination
+ readFiles(input);
+
+ if (input.length()==0)
+ {
+ warn("No input read, no output generated!\n");
+ exit(1);
+ }
+ else
+ {
+ msg("Read %d bytes\n",input.length());
+ }
+
+ /**************************************************************************
+ * Handle Tag Files *
+ **************************************************************************/
+
+ msg("Reading tag files\n");
+
+ s=tagFileList.first();
+ while (s)
+ {
+ readTagFile(s);
+ s=tagFileList.next();
+ }
+
+ QFile *tag =new QFile(genTagFile);
+ if (genTagFile.length()>0)
+ {
+ if (!tag->open(IO_WriteOnly))
+ {
+ err("Error: cannot open tag file %s for writing\n",genTagFile.data());
+ exit(1);
+ }
+ tagFile.setDevice(tag);
+ }
+
+ /**************************************************************************
+ * Gather information *
+ **************************************************************************/
+
+ // Notice: the order of the function calls below is very important!
+
+ if (generateHtml)
+ {
+ msg("Reading formula repository...\n");
+ readFormulaRepository();
+ }
+
+ Entry *root=new Entry;
+ root->program=input;
+
+ msg("Parsing input...\n");
+ parseMain(root); // build a tree of entries
+
+ msg("Freeing input...\n");
+ input.resize(0);
+
+ msg("Building namespace list...\n");
+ buildNamespaceList(root);
+
+ msg("Building group list...\n");
+ buildGroupList(root);
+
+ //msg("Computing group relations...\n");
+ //computeGroupRelations(root);
+
+ msg("Building file list...\n");
+ buildFileList(root);
+
+ msg("Building class list...\n");
+ buildClassList(root);
+
+ msg("Building example list...\n");
+ buildExampleList(root);
+
+ msg("Building page list...\n");
+ buildPageList(root);
+
+// msg("Adding compounds to file pages...\n");
+// findClassDefsInFiles(root);
+
+ msg("Building member list...\n"); // using class info only !
+ buildMemberList(root);
+ transferFunctionDocumentation();
+
+ msg("Searching for friends...\n");
+ findFriends();
+
+
+ msg("Searching for documented variables...\n");
+ buildVarList(root);
+
+ msg("Searching for documented defines...\n");
+ findDefineDocumentation(root);
+
+ msg("Computing class relations...\n");
+ computeClassRelations(root);
+
+ msg("Searching for enumerations...\n");
+ findEnums(root);
+ findEnumDocumentation(root);
+
+// msg("Searching for function prototypes...\n");
+// findPrototypes(root); // may introduce new members !
+
+ msg("Searching for member function documentation...\n");
+ findMemberDocumentation(root); // may introduce new members !
+
+ msg("Freeing entry tree\n");
+ delete root;
+
+ msg("Computing member references...\n");
+ computeMemberReferences();
+
+ msg("Computing function references...\n");
+ computeFunctionReferences();
+
+ msg("Computing member relations...\n");
+ computeMemberRelations();
+
+ msg("Building full member lists recursively...\n");
+ buildCompleteMemberLists();
+
+ //unrelatedFunctionsUsed=hasUnrelatedFunctions();
+
+ /**************************************************************************
+ * Generate documentation *
+ **************************************************************************/
+
+ // count the number of documented elements in the lists we have built.
+ // If the result is 0 we do not generate the lists and omit the
+ // corresponding links in the index.
+ msg("Counting data structures...\n");
+ annotatedClasses = countAnnotatedClasses();
+ hierarchyClasses = countClassHierarchy();
+ documentedMembers = countMemberList();
+ documentedFunctions = countFunctionList();
+ documentedFiles = countFileList();
+ documentedGroups = countGroupList();
+ documentedNamespaces = countNamespaceList();
+
+ // compute the shortest possible names of all files
+ // without loosing the uniqueness of the file names.
+ msg("Generating disk names...\n");
+ inputNameList.generateDiskNames();
+
+ msg("Generating example documentation...\n");
+ generateExampleDocs();
+
+ msg("Generating file documentation...\n");
+ generateFileDocs();
+
+ msg("Generating class documentation...\n");
+ generateClassDocs();
+
+ msg("Generating page documentation...\n");
+ generatePageDocs();
+
+ msg("Generating group documentation...\n");
+ generateGroupDocs();
+
+ msg("Generating namespace index...\n");
+ generateNamespaceDocs();
+
+ msg("Generating group index...\n");
+ writeGroupIndex(*outputList);
+
+ msg("Generating example index...\n");
+ writeExampleIndex(*outputList);
+
+ msg("Generating function index...\n");
+ writeFunctionIndex(*outputList);
+
+// msg("Generating define index...\n");
+// writeDefineIndex(*outputList);
+
+ msg("Generating page index...\n");
+ writePageIndex(*outputList);
+
+ msg("Generating search index...\n");
+ generateSearchIndex();
+
+ msg("Generating style sheet...\n");
+ outputList->writeStyleInfo(0); // write first part
+ outputList->disableAllBut(OutputGenerator::Latex);
+ parseDoc(*outputList,0,0,
+ theTranslator->trGeneratedAt(dateToString(TRUE),projectName)
+ );
+ outputList->writeStyleInfo(1); // write second part
+ parseDoc(*outputList,0,0, theTranslator->trWrittenBy());
+ outputList->writeStyleInfo(2); // write third part
+ parseDoc(*outputList,0,0,
+ theTranslator->trGeneratedAt(dateToString(TRUE),projectName)
+ );
+ outputList->writeStyleInfo(3); // write fourth part
+ parseDoc(*outputList,0,0, theTranslator->trWrittenBy());
+ outputList->writeStyleInfo(4); // write last part
+ outputList->enableAll();
+
+ if (formulaList.count()>0 && generateHtml)
+ {
+ msg("Generating bitmaps for formulas in HTML...\n");
+ formulaList.generateBitmaps(htmlOutputDir);
+ }
+
+ if (searchEngineFlag || tagFileList.count()>0)
+ {
+ msg("\nNow copy the file\n\n %s\n\nto the directory where the CGI binaries are "
+ "located and don't forget to run\n\n",(htmlOutputDir+"/"+cgiName).data());
+ msg(" %s/installdox\n\nto replace any dummy links.\n\n",
+ htmlOutputDir.data());
+ }
+
+ delete tag;
+ return 0;
+}
diff --git a/src/doxygen.h b/src/doxygen.h
new file mode 100644
index 0000000..05ca854
--- /dev/null
+++ b/src/doxygen.h
@@ -0,0 +1,134 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#ifndef DOXYGEN_H
+#define DOXYGEN_H
+
+#include "groupdef.h"
+#include "filedef.h"
+#include "classdef.h"
+#include "memberdef.h"
+#include "classlist.h"
+#include "membername.h"
+#include "filename.h"
+#include "define.h"
+#include "namespacedef.h"
+#include "formula.h"
+
+struct PageInfo
+{
+ PageInfo(const char *n,const char *d,const char *t)
+ { name=n; doc=d; title=t; }
+ QString name;
+ QString doc;
+ QString title;
+};
+
+class PageList : public QList<PageInfo>
+{
+ int compareItems(GCI i1,GCI i2)
+ {
+ return stricmp(((PageInfo *)i1)->name,((PageInfo *)i2)->name);
+ }
+};
+
+class BufStr : public QString
+{
+ public:
+ BufStr(int size) : QString(size), offset(0), spareRoom(10240) {}
+ void addChar(char c)
+ {
+ if (offset>=size()) resize(size()+spareRoom);
+ data()[offset++]=c;
+ }
+ void addArray(const char *a,int len)
+ {
+ if (offset+len>=size()) resize(size()+len+spareRoom);
+ memcpy(data()+offset,a,len);
+ offset+=len;
+ }
+ uint curPos() { return offset; }
+ void skip(uint s)
+ {
+ if (offset+s>=size()) resize(size()+s+spareRoom);
+ offset+=s;
+ }
+ private:
+ uint offset;
+ const int spareRoom; // 10Kb extra room to avoid frequent resizing
+};
+
+struct SectionInfo
+{
+ SectionInfo(const char *n,const char *l,const char *t,bool sub)
+ { pageName=n; label=l; title=t; isSubsection=sub; }
+ QString pageName;
+ QString label;
+ QString title;
+ bool isSubsection;
+};
+
+typedef QList<QString> StringList;
+typedef QDict<MemberDef> MemberDict;
+typedef QDict<ClassDef> ClassDict;
+typedef QDict<FileDef> FileDict;
+typedef QDict<QString> StringDict;
+typedef QDict<PageInfo> PageDict;
+typedef QDict<SectionInfo> SectionDict;
+typedef QDict<GroupDef> GroupDict;
+
+extern const char * getOverloadDocs();
+extern ClassList classList;
+extern ClassDict classDict;
+extern QStrList tagfileList;
+extern PageList exampleList;
+extern PageDict exampleDict;
+extern PageList pageList;
+extern PageDict pageDict;
+extern MemberNameList memberNameList;
+extern MemberNameList functionNameList;
+extern MemberNameDict memberNameDict;
+extern MemberNameDict functionNameDict;
+extern StringDict substituteDict;
+extern FileList fileList;
+extern FileDict fileDict;
+extern DefineDict defineDict;
+extern ClassDef unrelatedClass;
+extern QTextStream tagFile;
+extern SectionDict sectionDict;
+extern FileNameList inputNameList;
+extern FileNameDict includeNameDict;
+extern FileNameDict exampleNameDict;
+extern FileNameDict inputNameDict;
+extern FileList includeFiles;
+extern StringDict typedefDict;
+extern GroupList groupList;
+extern NamespaceList namespaceList;
+extern FormulaList formulaList;
+extern FormulaDict formulaDict;
+extern FormulaDict formulaNameDict;
+
+extern int annotatedClasses;
+extern int hierarchyClasses;
+extern int documentedFunctions;
+extern int documentedMembers;
+extern int documentedDefines;
+extern int documentedFiles;
+extern int documentedGroups;
+extern int documentedNamespaces;
+
+#endif
diff --git a/src/doxygen.pro b/src/doxygen.pro
new file mode 100644
index 0000000..e6dd3c0
--- /dev/null
+++ b/src/doxygen.pro
@@ -0,0 +1,38 @@
+#
+# $Id$
+#
+# Copyright (C) 1997-1999 by Dimitri van Heesch.
+#
+# Permission to use, copy, modify, and distribute this software and its
+# documentation under the terms of the GNU General Public License is hereby
+# granted. No representations are made about the suitability of this software
+# for any purpose. It is provided "as is" without express or implied warranty.
+# See the GNU General Public License for more details.
+#
+# All output generated with Doxygen is not covered by this license.
+#
+# TMake project file for doxygen
+
+TEMPLATE = doxygen.t
+CONFIG = console qt warn_on release #debug
+HEADERS = doxygen.h scanner.h classdef.h classlist.h memberdef.h \
+ membername.h index.h memberlist.h definition.h \
+ entry.h logos.h instdox.h message.h code.h \
+ filedef.h util.h cppvalue.h constexp.h \
+ outputgen.h outputlist.h htmlgen.h latexgen.h tag.h \
+ filename.h defargs.h groupdef.h gifenc.h diagram.h image.h \
+ namespacedef.h version.h language.h translator.h \
+ translator_nl.h translator_se.h translator_cz.h translator_fr.h \
+ translator_it.h formula.h debug.h
+SOURCES = doxygen.cpp scanner.cpp classdef.cpp classlist.cpp memberdef.cpp \
+ membername.cpp index.cpp memberlist.cpp \
+ entry.cpp logos.cpp instdox.cpp message.cpp code.cpp \
+ config.cpp filedef.cpp util.cpp groupdef.cpp \
+ outputgen.cpp outputlist.cpp htmlgen.cpp latexgen.cpp mangen.cpp \
+ cppvalue.cpp ce_lex.cpp ce_parse.cpp pre.cpp \
+ tag.cpp filename.cpp declinfo.cpp defargs.cpp define.cpp \
+ diagram.cpp gifenc.cpp image.cpp namespacedef.cpp \
+ version.cpp language.cpp definition.cpp formula.cpp debug.cpp
+win32:INCLUDEPATH += .
+TARGET = ../bin/doxygen
+OBJECTS_DIR = ../objects
diff --git a/src/doxygen.t b/src/doxygen.t
new file mode 100644
index 0000000..badf33e
--- /dev/null
+++ b/src/doxygen.t
@@ -0,0 +1,76 @@
+#
+# $Id$
+#
+# Copyright (C) 1997-1999 by Dimitri van Heesch.
+#
+# Permission to use, copy, modify, and distribute this software and its
+# documentation under the terms of the GNU General Public License is hereby
+# granted. No representations are made about the suitability of this software
+# for any purpose. It is provided "as is" without express or implied warranty.
+# See the GNU General Public License for more details.
+#
+# All output generated with Doxygen is not covered by this license.
+#!
+#! doxygen.t: This is a custom template for building Doxygen
+#!
+#$ IncludeTemplate("app.t");
+
+LEX = flex
+YACC = bison
+
+#${
+sub GenerateDep {
+ my($obj,$src,$dep) = @_;
+ my(@objv,$srcv,$i,$s,$o,$d,$c);
+ @objv = split(/\s+/,$obj);
+ @srcv = split(/\s+/,$src);
+ for $i ( 0..$#objv ) {
+ $s = $srcv[$i];
+ $o = $objv[$i];
+ next if $s eq "";
+ $text .= $o . ": " . $s;
+ $text .= " ${linebreak}\n\t\t" . $dep if $dep ne "";
+ if ( $moc_output{$s} ne "" ) {
+ $text .= " ${linebreak}\n\t\t" . $moc_output{$s};
+ }
+ $d = &make_depend($s);
+ $text .= " ${linebreak}\n\t\t" . $d if $d ne "";
+ $text .= "\n";
+ }
+ chop $text;
+}
+#$}
+
+####################
+
+#$ GenerateDep("scanner.cpp","scanner.l");
+ $(LEX) -PscanYY -t scanner.l >scanner.cpp
+
+#$ GenerateDep("code.cpp","code.l");
+ $(LEX) -PcodeYY -t code.l >code.cpp
+
+#$ GenerateDep("pre.cpp","pre.l");
+ $(LEX) -PpreYY -t pre.l >pre.cpp
+
+#$ GenerateDep("tag.cpp","tag.l");
+ $(LEX) -PtagYY -t tag.l >tag.cpp
+
+#$ GenerateDep("config.cpp","config.l");
+ $(LEX) -PconfigYY -t config.l >config.cpp
+
+#$ GenerateDep("declinfo.cpp","declinfo.l");
+ $(LEX) -PdeclinfoYY -t declinfo.l >declinfo.cpp
+
+#$ GenerateDep("defargs.cpp","defargs.l");
+ $(LEX) -PdefargsYY -t defargs.l >defargs.cpp
+
+#$ GenerateDep("ce_lex.cpp","constexp.l","ce_parse.h");
+ $(LEX) -PcppExpYY -t constexp.l >ce_lex.cpp
+
+#$ GenerateDep("ce_parse.cpp","constexp.y");
+ $(YACC) -l -p cppExpYY constexp.y -o ce_parse.cpp
+
+#$ GenerateDep("ce_parse.h","constexp.y");
+ $(YACC) -l -d -p cppExpYY constexp.y -o ce_parse.c
+ -rm ce_parse.c
+
diff --git a/src/doxysearch.cpp b/src/doxysearch.cpp
new file mode 100644
index 0000000..cd59d02
--- /dev/null
+++ b/src/doxysearch.cpp
@@ -0,0 +1,1022 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+// includes
+
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <sys/stat.h>
+#ifdef PROFILING
+#include <sys/time.h>
+#include <unistd.h>
+#endif
+
+// defines
+
+#ifndef bool
+#define bool int
+#endif
+
+#define MAXSTRLEN 1024
+#ifndef TRUE
+#define TRUE 1
+#endif
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#define NORMAL 1 // OR search results
+#define INCLUDE 2 // AND search results
+#define EXCLUDE 3 // AND NOT search results
+
+#define TERMMASK (1<<31)
+#define OFFSETMASK (~TERMMASK)
+
+// structs
+
+//----------------------------------------------------------------------------
+
+struct FileInfo
+{
+ FileInfo() { f=0; url=0; }
+ ~FileInfo() { if (f) fclose(f);
+ delete[] url;
+ }
+ FILE *f;
+ int index;
+ int refOffset;
+ char *url;
+ FileInfo *next;
+};
+
+//----------------------------------------------------------------------------
+
+struct FileList
+{
+ FileList() { first=0; last=0; index=0; }
+ ~FileList() { FileInfo *fi=first;
+ while (fi) { FileInfo *ofi=fi; fi=fi->next; delete ofi; }
+ }
+ FileInfo *add()
+ {
+ FileInfo *nf=new FileInfo;
+ nf->next=0;
+ nf->index=index++;
+ if (last) { last->next=nf; last=nf; } else { first=nf; last=nf; }
+ return nf;
+ }
+ FileInfo *first;
+ FileInfo *last;
+ int index;
+};
+
+//----------------------------------------------------------------------------
+
+struct WordInfo
+{
+ WordInfo() { word=0; }
+ ~WordInfo() { delete[] word; }
+ char *word;
+ int freq;
+ WordInfo *next;
+};
+
+//----------------------------------------------------------------------------
+
+struct WordList
+{
+ WordList() { first=0; last=0; }
+ ~WordList() { WordInfo *wi=first;
+ while (wi) { WordInfo *owi=wi; wi=wi->next; delete owi; }
+ }
+ void add(const char *word,int freq)
+ {
+ WordInfo *nw=new WordInfo;
+ nw->word = new char[strlen(word)+1];
+ strcpy(nw->word,word);
+ nw->freq=freq;
+ nw->next=0;
+ if (last) { last->next=nw; last=nw; } else { first=nw; last=nw; }
+ }
+ WordInfo *first;
+ WordInfo *last;
+};
+
+//----------------------------------------------------------------------------
+
+struct SearchDoc
+{
+ FileInfo *fileInfo;
+ int index;
+ int freq;
+ double rank;
+ SearchDoc *next;
+};
+
+//----------------------------------------------------------------------------
+
+struct SearchResults
+{
+ SearchResults() { totalFreq=0; docList=0; last=0; }
+ ~SearchResults() { SearchDoc *d=docList;
+ while (d) { SearchDoc *od=d; d=d->next; delete od; }
+ }
+ void add(FileInfo *fi,int index,int freq)
+ {
+ SearchDoc *nd=new SearchDoc;
+ nd->fileInfo=fi;
+ nd->index=index;
+ nd->freq=freq;
+ nd->next=0;
+ if (last) { last->next=nd; last=nd; } else { docList=nd; last=nd; }
+ }
+ SearchDoc *docList;
+ SearchDoc *last;
+ int totalFreq;
+};
+
+//----------------------------------------------------------------------------
+
+// global vars
+
+static WordList wordList;
+static FileList fileList;
+static char cgiBin[MAXSTRLEN];
+static char queryInput[MAXSTRLEN];
+static char encQueryInput[MAXSTRLEN];
+static char firstDocUrl[MAXSTRLEN];
+static bool nameOnly;
+static bool wordOnly;
+static bool helpOnly;
+static int page;
+static char *headerBuf=0;
+static char *footerBuf=0;
+
+//----------------------------------------------------------------------------
+
+// functions
+
+void printHeader()
+{
+ if (headerBuf)
+ {
+ printf("Content-Type: text/html\r\n\r\n%s",headerBuf);
+ }
+ else
+ {
+ printf("Content-Type: text/html\r\n\r\n");
+ printf("<html><head><title>Search the documentation</title></head>\n"
+ "<body bgcolor=\"#ffffff\" text=\"#000000\" link=\"#0000ee\" \n"
+ "vlink=\"#551a8b\" alink=\"#ff0000\">\n");
+ }
+}
+
+//----------------------------------------------------------------------------
+
+void printFooter()
+{
+ if (footerBuf)
+ {
+ printf("%s",footerBuf);
+ }
+ else
+ {
+ printf("</body></html>\n");
+ }
+}
+
+//----------------------------------------------------------------------------
+
+void message(char *fmt,...)
+{
+ printHeader();
+ printf("<h2>");
+ va_list args;
+ va_start(args, fmt);
+ vfprintf(stdout, fmt, args);
+ va_end(args);
+ printf("</h2>");
+ printFooter();
+}
+
+//----------------------------------------------------------------------------
+
+void printSearchPage(bool open=FALSE)
+{
+ printf("<form name=doxyform method=GET action=\"%s\">\n"
+ "<center>\n"
+ "<input type=hidden name=page value=0>\n"
+ "<table border=0 bgcolor=\"#ffffcc\" cellspacing=0 cellpadding=4>\n"
+ " <tr>\n"
+ " <td valign=top><font size=-1 face=\"arial, helvetica\"><b>"
+ " Search for\n"
+ " <select name=which>\n"
+ " <option value=string %s>strings\n"
+ " <option value=word %s>words\n"
+ " </select>\n"
+ " in function and class\n"
+ " <select name=what>\n"
+ " <option value=doc %s>documentation\n"
+ " <option value=name %s>names</select></b></font>\n"
+ " </td>\n"
+ " <td valign=top align=right>\n"
+ " <a href=\"%s?help=on\"><font size=-1>Help</font></a>\n"
+ " </td>\n"
+ " </tr>\n"
+ " <tr>\n"
+ " <td><input name=query size=44 wrap=virtual maxlength=1000 value=\"%s\">\n"
+ " </td>\n"
+ " <td><input type=image src=\"%s/search.gif\" height=26 width=120 border=0 name=\"search\">\n"
+ " </td>\n"
+ " </tr>\n",
+ cgiBin,
+ (wordOnly?"":"selected"),(wordOnly?"selected":""),
+ (nameOnly?"":"selected"),(nameOnly?"selected":""),
+ cgiBin,queryInput,firstDocUrl);
+ if (!open)
+ {
+ printf("</table>\n</center></form>\n");
+ }
+}
+
+//----------------------------------------------------------------------------
+
+int readInt(FILE *f)
+{
+ return (fgetc(f)<<24)+(fgetc(f)<<16)+(fgetc(f)<<8)+fgetc(f);
+}
+
+//----------------------------------------------------------------------------
+
+int readEncodedNumber(FILE *f)
+{
+ int n=0,b,s=0;
+ do { b=fgetc(f); n|=(b&0x7f)<<s; s+=7; } while (b&0x80);
+ return n;
+}
+
+void readString(FILE *f,char *s,int n)
+{
+ int i=0,b;
+ if (n<=0) return;
+ while (i<n-1 && (b=fgetc(f))!=0) s[i++]=b;
+ s[i]='\0';
+}
+
+//----------------------------------------------------------------------------
+
+bool searchRecursive(SearchResults *sr,FileInfo *fi,const char *word)
+{
+ char entry[MAXSTRLEN];
+ readString(fi->f,entry,MAXSTRLEN);
+ while (entry[0]!='\0')
+ {
+ //printf("Found entry `%s'\n",entry);
+ int i=0, w=word[0], e=entry[0];
+ while (w!=0 && e!=0 && w==e) { i++; w=word[i]; e=entry[i]; }
+ if (w==0 && e!=0) // word is a substring of entry
+ {
+ if (wordOnly) return FALSE; // no full word match
+ //printf("Word found as substring of `%s%s'\n",&word[-index],&entry[i]);
+ int offset=readInt(fi->f); // <= follow for extensions
+ if (!(offset&TERMMASK)) // extra info available
+ {
+ int tfreq=readEncodedNumber(fi->f);
+ sr->totalFreq+=tfreq;
+ //printf("Total frequency %d\n",tfreq);
+ int s=-1,k;
+ while ((k=readEncodedNumber(fi->f))!=0)
+ {
+ bool inName = (k&2)==2;
+ s+=(k>>3);
+ int freq=readEncodedNumber(fi->f);
+ //printf("Doc index %d frequency %d\n",s,freq);
+ if (!nameOnly || inName)
+ //addResult(fi,sr,s,freq);
+ sr->add(fi,s,freq);
+ }
+ }
+ return TRUE;
+ }
+ else if (e==0) // entry is a substring of word
+ {
+ if (w==0) // word is equal to entry => exact match found
+ {
+ int offset=readInt(fi->f); // <= follow for extensions
+ if (!(offset&TERMMASK)) // extra info available
+ {
+ //printf("Match found\n");
+ int tfreq=readEncodedNumber(fi->f);
+ sr->totalFreq+=tfreq;
+ //printf("Total frequency %d\n",tfreq);
+ int s=-1,k;
+ while ((k=readEncodedNumber(fi->f))!=0)
+ {
+ bool fullWord = (k&1)==1;
+ bool inName = (k&2)==2;
+ bool wordInName = (k&4)==4;
+ s+=(k>>3);
+ int freq=readEncodedNumber(fi->f);
+ if (nameOnly && wordOnly)
+ {
+ if (wordInName) sr->add(fi,s,freq);
+ }
+ else if (!nameOnly && wordOnly)
+ {
+ if (fullWord) sr->add(fi,s,freq);
+ }
+ else if (nameOnly && !wordOnly)
+ {
+ if (inName) sr->add(fi,s,freq);
+ }
+ else // !nameOnly && !wordOnly
+ {
+ sr->add(fi,s,freq);
+ }
+ }
+ }
+ return TRUE;
+ }
+ else // follow branch to next entry
+ {
+ int offset=readInt(fi->f);
+ if ((offset&OFFSETMASK)==0) // no next entry (leaf node)
+ {
+ return FALSE;
+ }
+ else // follow branch
+ {
+ fseek(fi->f,offset&OFFSETMASK,SEEK_SET);
+ //printf("Recursive call; jump to %lx\n",ftell(f));
+ return searchRecursive(sr,fi,&word[i]);
+ }
+ }
+ }
+ else // skip rest of the entry
+ {
+ int offset=readInt(fi->f);
+ if (!(offset&TERMMASK)) while (readEncodedNumber(fi->f)!=0);
+ }
+ readString(fi->f,entry,MAXSTRLEN);
+ }
+ //printf("Sorry no match found\n");
+ return FALSE;
+}
+
+//----------------------------------------------------------------------------
+
+
+void searchIndex(const char *word,SearchResults *results)
+{
+ FileInfo *fi=fileList.first;
+ while (fi)
+ {
+ fseek(fi->f,8,SEEK_SET);
+ searchRecursive(results,fi,word);
+ fi=fi->next;
+ }
+
+ SearchDoc *ds = results->docList;
+ while (ds)
+ {
+ ds->rank = ds->freq/(double)results->totalFreq;
+ ds = ds->next;
+ }
+
+ wordList.add(word,results->totalFreq);
+}
+
+//----------------------------------------------------------------------------
+
+int sortResults(const void *a1,const void *a2)
+{
+ SearchDoc **d1=(SearchDoc **)a1;
+ SearchDoc **d2=(SearchDoc **)a2;
+ if ((*d1)->rank > (*d2)->rank)
+ return -1;
+ else if ((*d1)->rank == (*d2)->rank)
+ return 0;
+ else
+ return 1;
+}
+
+//----------------------------------------------------------------------------
+
+void generateResults(SearchResults *sr)
+{
+ // compute the maximum rank
+ SearchDoc *ds = sr->docList;
+ double maxRank = 0.00000001;
+ int resultCount=0;
+ if (ds)
+ {
+ while (ds)
+ {
+ if (ds->rank>maxRank) maxRank = ds->rank;
+ ds = ds->next;
+ }
+
+ // scale ranks, so the highest is 1 and count the number of links
+ double oneOverMaxRank = 1.0/maxRank;
+ ds = sr->docList;
+ while (ds)
+ {
+ ds->rank *= oneOverMaxRank;
+ resultCount++;
+ ds = ds->next;
+ }
+ }
+ SearchDoc **docPtrArray=0;
+ if (resultCount>0)
+ {
+ docPtrArray=(SearchDoc **)calloc(resultCount,sizeof(SearchDoc *));
+ int offset=0;
+ ds = sr->docList;
+ while (ds)
+ {
+ docPtrArray[offset++]=ds;
+ ds = ds->next;
+ }
+ qsort(docPtrArray,resultCount,sizeof(SearchDoc *),sortResults);
+ }
+
+ // start generating output
+ printHeader();
+ printSearchPage(TRUE);
+
+ printf(" <tr bgcolor=#ffffff>\n"
+ " <td colspan=2>"
+ "<br><h3>Search results</h3>\n"
+ " </td>\n"
+ " </tr>\n");
+ if (resultCount==0) // nothing found
+ {
+ printf(" <tr bgcolor=#ffffff>\n"
+ " <td colspan=2>Sorry, no documents matching your query.\n"
+ " </td>\n"
+ " </tr>\n");
+ }
+ else // something found
+ {
+ printf(" <tr bgcolor=#ffffff>\n"
+ " <td colspan=2>"
+ "Found <b>%d</b> document%s matching your query. ",
+ resultCount,resultCount==1?"":"s");
+
+ if (resultCount>1)
+ printf("Showing best matches first.\n");
+
+ printf(" <br><br>\n");
+ printf(" </td>\n"
+ " </tr>\n");
+
+ const int lpp=20;
+ int numPages = (resultCount+lpp-1)/lpp;
+
+ // clip page
+ if (page<0) page=0;
+ if (page>=numPages) page=numPages-1;
+ int skipEntries = page * lpp;
+ int pageEntries = lpp;
+
+ printf(" <tr><td colspan=2 bgcolor=\"#4040c0\">"
+ "<center><b><font color=\"#ffffff\">Page %d / %d</font></b>"
+ "</center></td></tr>\n",page+1,numPages);
+ printf(" <tr bgcolor=#ffffff>\n"
+ " <td colspan=2>\n"
+ " <dl compact>\n");
+ int i;
+ for (i=0 ; i < resultCount && pageEntries > 0; i++)
+ {
+ if (skipEntries == 0)
+ {
+ SearchDoc *d=docPtrArray[i];
+ FILE *f=d->fileInfo->f;
+ fseek(f,d->fileInfo->refOffset+d->index*4,SEEK_SET);
+ int offset=readInt(f);
+ fseek(f,offset,SEEK_SET);
+ char linkName[MAXSTRLEN];
+ char htmlName[MAXSTRLEN];
+ readString(f,linkName,MAXSTRLEN);
+ readString(f,htmlName,MAXSTRLEN);
+ int rank=(int)(d->rank*100+0.5);
+ if (rank==0) rank++;
+ printf(" <dt><b><font color=#%2x00%2x>%d</font></b>"
+ "<dd><a href=\"%s/%s\">%s</a>\n",
+ rank*2+55, 255-rank*2, rank,
+ d->fileInfo->url, htmlName, linkName);
+ pageEntries--;
+ }
+ else
+ {
+ skipEntries--;
+ }
+ }
+ printf(" </dl>\n"
+ " </td>\n"
+ " </tr>\n"
+ " <tr><td colspan=2 bgcolor=\"#4040c0\"><center>&nbsp;");
+
+ if (page>0)
+ {
+ printf("<a href=\"%s?page=%d&which=%s&what=%s&query=%s\">"
+ "<font color=\"ffffff\">prev</font></a>&nbsp;",
+ cgiBin, page-1,
+ wordOnly?"word":"doc",
+ nameOnly?"name":"string",
+ encQueryInput);
+ }
+ int startPage = page-5 < 0 ? 0 : page-5;
+ int endPage = page+6 > numPages ? numPages : page+5;
+ if (endPage-startPage>1)
+ {
+ for (i=startPage;i<endPage;i++)
+ {
+ if (i!=page)
+ {
+ printf("<a href=\"%s?page=%d&which=%s&what=%s&query=%s\">"
+ "<font color=\"ffffff\">%d</font></a>&nbsp;",
+ cgiBin, i,
+ wordOnly?"word":"doc",
+ nameOnly?"name":"string",
+ encQueryInput, i+1);
+ }
+ else
+ {
+ printf("<b><font color=\"ffffff\">%d</font></b></a>&nbsp;",i+1);
+ }
+ }
+ }
+ if (page<numPages-1)
+ {
+ printf("<a href=\"%s?page=%d&which=%s&what=%s&query=%s\">"
+ "<font color=\"ffffff\">next</font></a>",
+ cgiBin, page+1,
+ wordOnly?"word":"doc",
+ nameOnly?"name":"string",
+ encQueryInput);
+ }
+ printf(" &nbsp;</center></td></tr>\n"
+ " <tr bgcolor=#ffffff>\n"
+ " <td colspan=2><p>\n"
+ " Occurrence count: ");
+ WordInfo *wi=wordList.first;
+ while (wi)
+ {
+ printf("<b><font color=#ff0000>%s</font></b> ",wi->word);
+ if (wi->freq>0) printf("(%d)",wi->freq); else printf("(ignored)");
+ wi=wi->next;
+ if (wi)
+ {
+ if (wi->next) printf(", "); else printf(" and ");
+ }
+ }
+ printf("\n"
+ " </td>\n"
+ " </tr>\n");
+ }
+ printf("</table>\n</center>\n</form>\n");
+ printFooter();
+ free(docPtrArray);
+}
+
+//----------------------------------------------------------------------------
+
+void generateHelpPage()
+{
+ printHeader();
+ printf("<h3>Doxysearch help page</h3>\n"
+ "<b>Basic search instructions</b>\n"
+ "<ul>\n"
+ "Just type in one or more words or fragments of words and press the "
+ "search button. Doxysearch will return a list of functions and class names, "
+ "whose documentation or name matches one or more of the words. "
+ "Documents containing more matches will appear earlier in the list. "
+ "\n"
+ "</ul>\n"
+ "<b>Search modes</b>\n"
+ "<ul>\n"
+ "Doxysearch has four search modes. From least restrictive to most "
+ "restrictive they are:\n"
+ " <ul><p>\n"
+ " <li><em>Search for strings in the documentation:</em>\n"
+ " The words you type will be searched in the documentation as substrings."
+ " Typing the word &quot;<b>the</b>&quot; for example, will find "
+ " documents containing the words &quot;<b>the</b>&quot;, "
+ " &quot;<b>the</b>re&quot;, and &quot;fea<b>the</b>r&quot;.<p>\n"
+ " <li><em>Search for words in the documentation:</em>\n"
+ " The words you type will be searched in the documentation as words."
+ " Typing the word &quot;<b>the</b>&quot; for example, will look "
+ " for documents containing the word &quot;<b>the</b>&quot; and not for"
+ " documents containing the word &quot;<b>the</b>re&quot;.<p>\n"
+ " <li><em>Search for strings in the function and class names:</em>\n"
+ " The words you type will be searched in the function and class names "
+ " as substrings. Typing the word &quot;<b>set</b>&quot; for example, will "
+ " result in a list of links to the documentation of all functions and classes "
+ " that contain the word &quot;<b>set</b>&quot; in the name, such as the function "
+ " <code><b>set</b>Cursor</code>.<p>\n"
+ " <li><em>Search for words in the function and class names:</em>\n"
+ " The words you type will be matched against the function and class names."
+ " The result will be a list of links to the documentation of all function "
+ " and class names that are equal to one of the words.\n"
+ " </ul>\n"
+ "</ul>\n"
+ "<b>Requiring/Excluding words</b>\n"
+ "<ul>\n"
+ " Often you will know a word that will be guaranteed to appear in a document "
+ " for which you are searching. If this is the case, require that the word appears "
+ " in all of the results by attaching a &quot;<b>+</b>&quot; to the beginning of "
+ " the word. You can quickly reject results by adding a word that appears only "
+ " in unwanted documents with a &quot;<b>-</b>&quot; before it."
+ "</ul>\n"
+ );
+
+ printFooter();
+}
+
+//----------------------------------------------------------------------------
+
+void mergeSearchResults(SearchResults *totalResults,
+ SearchResults *sr,int mode)
+{
+ SearchDoc *otd = 0,
+ *td = totalResults->docList,
+ *d = sr->docList;
+ totalResults->totalFreq += sr->totalFreq;
+ if (!d) return; // nothing to add
+ while (td && d)
+ {
+ int otdih = otd ? otd->fileInfo->index : -1,
+ otdil = otd ? otd->index : -1,
+ tdih = td->fileInfo->index,
+ tdil = td->index,
+ dih = d->fileInfo->index,
+ dil = d->index;
+ if (tdih==dih && tdil==dil) // combine results
+ {
+ if (mode != EXCLUDE)
+ {
+ td->rank += d->rank;
+ td->rank *= 2; // put extra emphasis on multiple word matches
+ td->freq += d->freq;
+ d = d->next;
+ otd = td; td = td->next;
+ }
+ else // mode == EXCLUDE => remove entry from results
+ {
+ SearchDoc *tmp=td;
+ td=td->next;
+ if (otd) otd->next=td; else totalResults->docList = td;
+ delete tmp;
+ }
+ }
+ else if ((otdih<dih || (otdih==dih && otdil<dil)) &&
+ (tdih>dih || (tdih==dih && tdil>dil))) // insert
+ {
+ if (mode == NORMAL)
+ {
+ SearchDoc *nd = new SearchDoc(*d);
+ if (otd) otd->next = nd; else totalResults->docList = nd;
+ nd->next = td;
+ td = nd;
+ }
+ d = d->next;
+ }
+ else if (tdih<dih || (tdih==dih && tdil<dil)) // remove or skip
+ {
+ if (mode == INCLUDE)
+ {
+ SearchDoc *tmp=td;
+ td=td->next;
+ if (otd) otd->next=td; else totalResults->docList = td;
+ delete tmp;
+ }
+ else // mode == EXCLUDE or mode == NORMAL
+ {
+ otd = td; td = td->next;
+ }
+ }
+ }
+ if (td==0 && d && mode==NORMAL) // append rest of sr to totalResults
+ {
+ while (d)
+ {
+ SearchDoc *nd = new SearchDoc(*d);
+ if (otd) otd->next = nd; else totalResults->docList = nd;
+ nd->next = 0;
+ d = d->next;
+ otd = nd;
+ }
+ }
+ if (td && d==0 && mode==INCLUDE) // delete the rest of the results
+ {
+ while (td)
+ {
+ SearchDoc *tmp=td;
+ td=td->next;
+ if (otd) otd->next = td; else totalResults->docList = td;
+ delete tmp;
+ }
+ }
+}
+
+//----------------------------------------------------------------------------
+
+int asciiToHex(char c)
+{
+ char l=tolower(c);
+ if (l>='0' && l<='9')
+ return l-'0';
+ else if (l>='a' && l<='f')
+ return l+10-'a';
+ else // invalid hex char
+ return 0;
+}
+
+//----------------------------------------------------------------------------
+
+void fileToBuf(const char *name, char **buf)
+{
+ FILE *f;
+ struct stat file_stats;
+ if ((f=fopen(name,"r"))==NULL) return;
+ if (stat(name,&file_stats)==-1)
+ {
+ message("Error: could not fstat header file %s\n",name);
+ exit(1);
+ }
+ unsigned int len=file_stats.st_size;
+ if ((*buf=(char *)malloc(len+1))==NULL)
+ {
+ message("Error: out of memory\n");
+ exit(1);
+ }
+ if (fread(*buf,1,len,f)!=len)
+ {
+ message("Error: could not read header file %s\n",name);
+ exit(1);
+ }
+ (*buf)[len]='\0';
+ fclose(f);
+}
+
+//----------------------------------------------------------------------------
+
+void getConfig(const char *s)
+{
+ int l;
+ char configFile[MAXSTRLEN];
+ strcpy(configFile,s);
+ strcat(configFile,"/search.cfg");
+
+ FILE *f;
+ if ((f=fopen(configFile,"r"))==NULL)
+ {
+ message("Error: could not open config file %s\n",configFile);
+ exit(1);
+ }
+
+ // get the URL to the documentation
+ fgets(firstDocUrl,MAXSTRLEN,f);
+ l=strlen(firstDocUrl)-1;
+ if (firstDocUrl[l]=='\n') firstDocUrl[l]='\0';
+ l=strlen(firstDocUrl);
+ if (firstDocUrl[l]=='/') firstDocUrl[l]='\0';
+
+ // get the URL to the cgi script
+ fgets(cgiBin,MAXSTRLEN,f);
+ l=strlen(cgiBin)-1;
+ if (cgiBin[l]=='\n') cgiBin[l]='\0';
+
+ fclose(f);
+
+ char headerFile[MAXSTRLEN];
+ strcpy(headerFile,s);
+ strcat(headerFile,"/header.html");
+ fileToBuf(headerFile,&headerBuf);
+
+ char footerFile[MAXSTRLEN];
+ strcpy(footerFile,s);
+ strcat(footerFile,"/footer.html");
+ fileToBuf(footerFile,&footerBuf);
+
+}
+
+//----------------------------------------------------------------------------
+// copy and convert string to lower case
+
+void strlowercpy(char *d,const char *s)
+{
+ while (*s!='\0') *d++=tolower(*s++); *d='\0';
+}
+
+//----------------------------------------------------------------------------
+
+int main(int argc,char **argv)
+{
+#ifdef PROFILING
+ struct timeval tv_start,tv_end;
+ gettimeofday(&tv_start,0);
+#endif
+ char *argString=getenv("QUERY_STRING");
+ if (argc==1)
+ {
+ message("Error: invalid number of arguments. "
+ "Usage: %s doc_path [doc_path ...]",argv[0]);
+ exit(1);
+ }
+ // read the configuration file for this instance of the search engine
+ getConfig(argv[1]);
+
+ if (!argString)
+ {
+ printHeader();
+ printSearchPage();
+ printFooter();
+ exit(1);
+ }
+
+ SearchResults tsr;
+
+ // parse cgi arguments
+ char *arg=strtok(argString,"&");
+ char *query = 0;
+ char *what = 0;
+ char *which = 0;
+ char *help = 0;
+ page = 0;
+ while (arg)
+ {
+ int namelen=strcspn(arg,"=");
+ if (!strncmp(arg,"query", namelen)) query = &arg[namelen+1];
+ else if (!strncmp(arg,"what", namelen)) what = &arg[namelen+1];
+ else if (!strncmp(arg,"which", namelen)) which = &arg[namelen+1];
+ else if (!strncmp(arg,"help", namelen)) help = &arg[namelen+1];
+ else if (!strncmp(arg,"page", namelen)) page = atoi(&arg[namelen+1]);
+ arg=strtok(0,"&");
+ }
+
+ wordOnly=which ? strcmp(which,"word")==0 : FALSE;
+ nameOnly=what ? strcmp(what, "name")==0 : FALSE;
+ helpOnly=help ? strcmp(help, "on" )==0 : FALSE;
+
+ // store encoded query string
+ if (query) strcpy(encQueryInput,query); else encQueryInput[0]='\0';
+
+ // convert query string to original input
+ char *s=query,*d=queryInput;
+ if (s)
+ {
+ while (*s!='\0')
+ {
+ char c=*s++;
+ if (c=='+')
+ *d++=' ';
+ else if (c=='%')
+ *d++=asciiToHex(*s++)*16+asciiToHex(*s++);
+ else
+ *d++=c;
+ }
+ }
+ *d='\0';
+
+ if (helpOnly)
+ {
+ generateHelpPage();
+ exit(1);
+ }
+
+ // read search index files
+ int argIndex=0;
+ for (argIndex=1;argIndex<argc;argIndex++)
+ {
+ char configFile[MAXSTRLEN];
+ strcpy(configFile,argv[argIndex]);
+ strcat(configFile,"/search.cfg");
+
+ char indexFile[MAXSTRLEN];
+ strcpy(indexFile,argv[argIndex]);
+ strcat(indexFile,"/search.idx");
+
+ FileInfo *fi=fileList.add();
+ FILE *g;
+
+ if ((fi->f=fopen(indexFile,"r"))==NULL)
+ {
+ message("Error: could not open index file %s\n",indexFile);
+ exit(1);
+ }
+ if ((g=fopen(configFile,"r"))==NULL)
+ {
+ message("Error: could not open config file %s\n",configFile);
+ exit(1);
+ }
+
+ // get URL to the documentation
+ char tmp[MAXSTRLEN];
+ fgets(tmp,MAXSTRLEN,g);
+ if (tmp[strlen(tmp)-1]=='\n') tmp[strlen(tmp)-1]='\0';
+ if (tmp[strlen(tmp)-1]=='/') tmp[strlen(tmp)-1]='\0';
+ fi->url = new char[strlen(tmp)+1];
+ strcpy(fi->url,tmp);
+ fclose(g);
+
+ // read & check the format of the search index file
+ fseek(fi->f,0,SEEK_SET);
+ char header[5];
+ if (fread(header,1,4,fi->f)!=4)
+ {
+ message("Error: Couldn't read header of the index file %s\n",indexFile);
+ exit(1);
+ }
+ header[4]='\0';
+ if (strcmp(header,"DOXI"))
+ {
+ message("Error: Index file %s has an unknown format\n",indexFile);
+ exit(1);
+ }
+ // read and store the offset to the link index
+ fi->refOffset=readInt(fi->f);
+ }
+
+ char *word;
+ char wordString[MAXSTRLEN];
+
+ // search for included words
+ strlowercpy(wordString,queryInput);
+ word=strtok(wordString," ");
+ bool first=TRUE;
+ while (word)
+ {
+ if (word[0]=='+') // + character => include
+ {
+ SearchResults sr;
+ searchIndex(&word[1],&sr);
+ if (first)
+ mergeSearchResults(&tsr,&sr,NORMAL);
+ else
+ mergeSearchResults(&tsr,&sr,INCLUDE);
+ first=FALSE;
+ }
+ word=strtok(0," ");
+ }
+
+ // search for normal words
+ strlowercpy(wordString,queryInput);
+ word=strtok(wordString," ");
+ while (word)
+ {
+ if (word[0]!='-' && word[0]!='+') // normal word
+ {
+ SearchResults sr;
+ searchIndex(word,&sr);
+ mergeSearchResults(&tsr,&sr,NORMAL);
+ }
+ word=strtok(0," ");
+ }
+
+ // search for excluded words
+ strlowercpy(wordString,queryInput);
+ word=strtok(wordString," ");
+ while (word)
+ {
+ if (word[0]=='-') // - character => exclude
+ {
+ SearchResults sr;
+ searchIndex(&word[1],&sr);
+ mergeSearchResults(&tsr,&sr,EXCLUDE);
+ }
+ word=strtok(0," ");
+ }
+
+ // write results to HTML page
+ generateResults(&tsr);
+
+ free(headerBuf);
+ free(footerBuf);
+
+#ifdef PROFILING
+ gettimeofday(&tv_end,0);
+ printf("processing time %3.3f msec\n",
+ ((tv_end.tv_sec-tv_start.tv_sec)*1000000+
+ tv_end.tv_usec-tv_start.tv_usec)/1000.0
+ );
+#endif
+ return 0;
+}
diff --git a/src/doxysearch.pro b/src/doxysearch.pro
new file mode 100644
index 0000000..ab34adc
--- /dev/null
+++ b/src/doxysearch.pro
@@ -0,0 +1,18 @@
+#
+# $Id$
+#
+# Copyright (C) 1997-1999 by Dimitri van Heesch.
+#
+# Permission to use, copy, modify, and distribute this software and its
+# documentation under the terms of the GNU General Public License is hereby
+# granted. No representations are made about the suitability of this software
+# for any purpose. It is provided "as is" without express or implied warranty.
+# See the GNU General Public License for more details.
+#
+# All output generated with Doxygen is not covered by this license.
+
+TEMPLATE = app.t
+CONFIG = console warn_on release
+SOURCES = doxysearch.cpp
+TARGET = ../bin/doxysearch
+OBJECTS_DIR = ../objects
diff --git a/src/doxytag.l b/src/doxytag.l
new file mode 100644
index 0000000..4f9fac1
--- /dev/null
+++ b/src/doxytag.l
@@ -0,0 +1,634 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+%{
+/*
+ * includes
+ */
+#include <stdio.h>
+#include <iostream.h>
+#include <assert.h>
+#include <ctype.h>
+
+#include <qstring.h>
+#include <qstrlist.h>
+#include <qfileinf.h>
+#include <qfile.h>
+#include <qdict.h>
+#include <qtstream.h>
+#include <qdir.h>
+
+#include "version.h"
+#include "suffixtree.h"
+#include "searchindex.h"
+#include "logos.h"
+
+struct MemberDef
+{
+ QString name;
+ QString anchor;
+ QString args;
+};
+
+struct ClassDef
+{
+ QString name;
+ QStrList bases;
+ QString fileName;
+ bool isFile;
+ QList<MemberDef> memberList;
+};
+
+QList<ClassDef> classList;
+QDict<ClassDef> classDict(1009);
+QList<ClassDef> fileList;
+QDict<ClassDef> fileDict(1009);
+
+static bool genTag;
+static bool genIndex;
+
+static QStrList bases;
+static QString inputString;
+static int inputPosition;
+static QString yyFileName;
+static int yyLineNr;
+static QString classFile;
+static QString memberRef;
+static QString memberName;
+static QString memberArgs;
+static QString className;
+//static bool newClass;
+static QString docBaseLink;
+static QString docAnchor;
+static QString docRefName;
+static bool nameBug;
+static SearchIndex searchIndex;
+
+#define YY_NEVER_INTERACTIVE 1
+
+/* -----------------------------------------------------------------
+ */
+#undef YY_INPUT
+#define YY_INPUT(buf,result,max_size) result=yyread(buf,max_size);
+
+static int yyread(char *buf,int max_size)
+{
+ int c=0;
+ while( c < max_size && inputString[inputPosition] )
+ {
+ *buf = inputString[inputPosition++] ;
+ c++; buf++;
+ }
+ return c;
+}
+
+static void addClass(const char *clName)
+{
+ if (classDict[clName]==0)
+ {
+ ClassDef *cd=new ClassDef;
+ cd->name=clName;
+ cd->fileName=yyFileName;
+ cd->isFile=FALSE;
+ classList.append(cd);
+ classDict.insert(clName,cd);
+ }
+}
+
+static void addFile(const char *fName)
+{
+ if (classDict[fName]==0)
+ {
+ ClassDef *fd=new ClassDef;
+ fd->name=fName;
+ fd->fileName=yyFileName;
+ fd->isFile=TRUE;
+ classList.append(fd);
+ classDict.insert(fName,fd);
+ }
+}
+
+static void addBases(const char *clName)
+{
+ ClassDef *cd=0;
+ if (clName && (cd=classDict[clName])) cd->bases=bases;
+}
+
+static void addMember(const char *memName,const char *memRef,const char *memArgs)
+{
+ ClassDef *cd=classList.last();
+ MemberDef *md;
+ md=new MemberDef;
+ md->name=memName;
+ md->anchor=memRef;
+ md->args=memArgs;
+ cd->memberList.append(md);
+}
+
+static void addReference()
+{
+ //printf("addReference() key: %s ref:%s\n",
+ // docRefName.data(),(docBaseLink+"#"+docAnchor).data());
+ if (genIndex && docRefName.length()>0 && docBaseLink.length()>0)
+ {
+ if (docAnchor.length()==0)
+ searchIndex.addReference(docRefName,docBaseLink);
+ else
+ searchIndex.addReference(docRefName,docBaseLink+"#"+docAnchor);
+ searchIndex.addWord(docRefName,docRefName,TRUE);
+ }
+}
+
+QString unhtmlify(const char *str)
+{
+ QString result;
+ const char *p=str;
+ char c;
+ while ((c=*p)!='\0')
+ {
+ if (c!='&') { result+=c; p++; }
+ else
+ {
+ if (strncmp(p,"&amp;",5)==0) { result+='&'; p+=5; }
+ else if (strncmp(p,"&lt;",4)==0) { result+='<'; p+=4; }
+ else if (strncmp(p,"&gt;",4)==0) { result+='>'; p+=4; }
+ else /* should not happen */ { result+='&'; p++; }
+ }
+ }
+ return result;
+}
+
+%}
+
+%x Start
+%x SearchClassFile
+%x ReadClassFile
+%x CheckClassName
+%x ReadClassName
+%x SearchMemberRef
+%x ReadMemberRef
+%x SearchMemberName
+%x ReadMemberName
+%x ReadOperator
+%x SearchBaseClasses
+%x ReadBaseClass
+%x SearchRefName
+%x ReadRefName
+%x SearchArgs
+%x ReadArgs
+%x SearchWords
+%x SkipHTMLTag
+%x CheckConstructor
+%x SkipPreformated
+
+%%
+
+<Start>^"<li>" {
+ BEGIN( SearchClassFile );
+ }
+<Start>^"<h1 align=center>" { // Qt variant
+ BEGIN( ReadClassName );
+ }
+<Start>^"<h1>" { // Doxygen variant
+ BEGIN( ReadClassName );
+ }
+<Start>^"Inherits " {
+ //printf("Inherits found\n");
+ BEGIN( SearchBaseClasses );
+ }
+<Start>^"<h3 class=\"fn\">"/[a-z_A-Z0-9] { // needed due to inconsistency in the Qt docs
+ BEGIN( CheckConstructor );
+ }
+<Start>"<pre>" {
+ BEGIN( SkipPreformated );
+ }
+<Start>"<a name=\"" {
+ BEGIN( SearchWords );
+ }
+<Start>"<" {
+ BEGIN( SkipHTMLTag );
+ }
+<Start>"&"[a-zA-Z]+";"
+<Start>[a-z_A-Z][a-z_A-Z0-9]* {
+ //printf("tag: %s#%s ref: %s word: `%s'\n",
+ // docBaseLink.data(),docAnchor.data(),
+ // docRefName.data(),yytext);
+ if (genIndex && docRefName.length()>0 && yyleng>2)
+ searchIndex.addWord(docRefName,
+ yytext,FALSE
+ );
+ }
+<SkipPreformated>"</pre>" {
+ BEGIN( Start );
+ }
+<SkipPreformated>[^\<]+
+<CheckConstructor>[a-z_A-Z0-9~:]+ {
+ QString s=yytext;
+ if (s.find("::")!=-1)
+ {
+ docRefName=yytext;
+ addReference();
+ nameBug=TRUE;
+ }
+ else
+ {
+ nameBug=FALSE;
+ }
+ BEGIN( Start );
+ }
+<SearchWords>[a-z_A-Z0-9]+ {
+ docAnchor = yytext;
+ if (docAnchor=="details")
+ {
+ docRefName=className.copy();
+ addReference();
+ BEGIN( Start );
+ }
+ else
+ {
+ BEGIN( SearchRefName );
+ }
+ }
+<SearchRefName>"\" doxytag=\"" {
+ BEGIN( ReadRefName );
+ }
+<SearchRefName>"\"></a>" {
+ if (nameBug)
+ BEGIN( Start );
+ else
+ BEGIN( ReadRefName );
+ }
+
+<ReadRefName>[a-z_A-Z0-9:\.\+\-]*"operator"[ \t]*("new"|"delete"|("&amp;"("&amp"|"=")*)|("&gt;"("&gt;"|"=")*)|("&lt;"("&lt;"|"=")*)|("-&gt;"[*]*)|[+\-*%/|~!=,\^]|[+\-*%/\^!|~=\[(][=|+\-\])]) { // hmm, looks impressive :-)
+ docRefName=unhtmlify(yytext);
+ addReference();
+ BEGIN( Start );
+ }
+<ReadRefName>[a-z_A-Z0-9~:\.\+\-]+ {
+ //printf("ReadRef=%s\n",yytext);
+ docRefName=yytext;
+ addReference();
+ BEGIN( Start );
+ }
+<SearchBaseClasses>"<a "[a-z_A-Z0-9 .:\=\"\-\+\/\@]+">" {
+ //printf("Search %s\n",yytext);
+ BEGIN( ReadBaseClass );
+ }
+<SearchBaseClasses>\n {
+ addBases(className);
+ BEGIN( Start );
+ }
+<ReadBaseClass>[a-z_A-Z0-9]+ {
+ bases.append(yytext);
+ BEGIN( SearchBaseClasses );
+ }
+<SearchClassFile>"<a class=\"el\" href=\"" {
+ BEGIN( ReadClassFile );
+ }
+<SearchClassFile>"<a href=\"" {
+ BEGIN( ReadClassFile );
+ }
+<ReadClassName>[a-z_A-Z0-9:\.\-\+]+ {
+ className=yytext;
+ BEGIN( CheckClassName);
+ }
+<CheckClassName>"Class Reference" {
+ //printf("className=%s\n",className.data());
+ addClass(className);
+ BEGIN( Start );
+ }
+<CheckClassName>"File Reference" {
+ //printf("className=%s\n",className.data());
+ addFile(className);
+ BEGIN( Start );
+ }
+<CheckClassName>[a-z_A-Z0-9]+ { // not a class file
+ className.resize(0);
+ BEGIN( Start );
+ }
+<ReadClassFile>[a-z_A-Z0-9.\-\+]+ {
+ classFile=yytext;
+ BEGIN( SearchMemberRef );
+ }
+<SearchMemberRef>"#" {
+ BEGIN( ReadMemberRef );
+ }
+<ReadMemberRef>[a-z_A-Z0-9]+ {
+ memberRef=yytext;
+ BEGIN( SearchMemberName );
+ }
+<SearchMemberName>"<strong>" {
+ BEGIN( ReadMemberName );
+ }
+<SearchMemberName>[a-z_A-Z~] {
+ unput(*yytext);
+ BEGIN( ReadMemberName );
+ }
+<ReadMemberName>"operator" {
+ memberName="operator";
+ BEGIN( ReadOperator );
+ }
+<ReadOperator>[+\-*/%\^&|~!=()\[\]] { memberName+=*yytext; }
+<ReadOperator>"&lt;" { memberName+="<"; }
+<ReadOperator>"&gt;" { memberName+=">"; }
+<ReadOperator>"new" { memberName+=" new"; }
+<ReadOperator>"delete" { memberName+=" delete"; }
+<ReadOperator>"<" { BEGIN( SearchArgs ); }
+<ReadMemberName>[a-z_A-Z0-9]+ {
+ memberName=yytext;
+ BEGIN( SearchArgs );
+ }
+<SearchArgs>"</a>" {
+ //printf("SearchArg className=%s memberName=%s\n",className.data(),memberName.data());
+ if (className.length()>0 && memberName.length()>0)
+ BEGIN( ReadArgs );
+ else
+ BEGIN( Start );
+ }
+<ReadArgs>"&amp;" { memberArgs+="&"; }
+<ReadArgs>"&lt;" { memberArgs+="<"; }
+<ReadArgs>"&gt;" { memberArgs+=">"; }
+ /*
+<ReadArgs>[{}] { // handle enums
+ memberArgs.resize(0);
+ addMember(memberName,memberRef,memberArgs);
+ if (*yytext=='}')
+ BEGIN( Start );
+ else
+ BEGIN( SearchClassFile );
+ }
+ */
+<ReadArgs>"<"|"\n" {
+ //printf("adding member %s\n",memberName.data());
+ memberArgs=memberArgs.stripWhiteSpace();
+ //if (newClass)
+ //{
+ // newClass=FALSE;
+ // addClass(className);
+ //}
+ addMember(memberName,memberRef,memberArgs);
+ memberArgs.resize(0);
+ if (*yytext=='<')
+ BEGIN( SkipHTMLTag);
+ else
+ BEGIN( Start );
+ }
+<ReadArgs>. { memberArgs+=(*yytext)&0x7f; }
+<SkipHTMLTag>">" { BEGIN( Start ); }
+<SkipHTMLTag>[a-zA-Z]+
+<*>.
+<*>\n { yyLineNr++;
+ if (YY_START!=SkipHTMLTag) BEGIN( Start );
+ }
+
+%%
+
+/*@ ----------------------------------------------------------------------------
+ */
+
+
+void parse(QString &s)
+{
+ bases.clear();
+ nameBug = FALSE;
+ //newClass = TRUE;
+ inputString = s;
+ inputPosition = 0;
+ yyLineNr = 0;
+ tagYYrestart( tagYYin );
+ BEGIN( Start );
+ tagYYlex();
+ //printf("Number of lines scanned: %d\n",yyLineNr);
+}
+
+void parseFile(QFileInfo &fi)
+{
+ fprintf(stderr,"Parsing file %s...\n",fi.fileName().data());
+ QFile f(fi.absFilePath());
+ if (f.open(IO_ReadOnly))
+ {
+ yyFileName = fi.fileName();
+ className.resize(0);
+ memberName.resize(0);
+ //printf("Parsing file %s...\n",fi.fileName().data());
+ QString input(fi.size()+1);
+ docBaseLink=fi.fileName();
+ docRefName=fi.fileName().copy();
+ searchIndex.addReference(docRefName,docBaseLink);
+ searchIndex.addWord(docRefName,docRefName,TRUE);
+ f.readBlock(input.data(),fi.size());
+ input.at(fi.size())='\0';
+ parse(input);
+ }
+ else
+ {
+ fprintf(stderr,"Warning: Cannot open file %s\n",fi.fileName().data());
+ }
+}
+
+void parseFileOrDir(const char *fileName)
+{
+ QFileInfo fi(fileName);
+ if (fi.exists())
+ {
+ if (fi.isFile())
+ {
+ parseFile(fi);
+ }
+ else if (fi.isDir())
+ {
+ QDir dir(fileName);
+ dir.setFilter( QDir::Files );
+ dir.setNameFilter( "*.html" );
+ const QFileInfoList *list = dir.entryInfoList();
+ QFileInfoListIterator it( *list );
+ QFileInfo *cfi;
+ for ( it.toFirst() ; (cfi=it.current()) ; ++it)
+ {
+ if (cfi->isFile())
+ {
+ parseFile(*cfi);
+ }
+ }
+ }
+ }
+ else
+ {
+ fprintf(stderr,"Warning: File %s does not exist\n",fileName);
+ }
+}
+
+void usage(const char *name)
+{
+ fprintf(stderr,"Doxytag version %s\nCopyright Dimitri van Heesch 1997-1999\n\n",
+ versionString);
+ fprintf(stderr," Generates a tag file and/or a search index for a set of HTML files\n\n");
+ fprintf(stderr,"Usage: %s [-t tag_file] [-s index_file] [ html_file [html_file...] ]\n",name);
+ fprintf(stderr,"Options:\n");
+ fprintf(stderr," -t <tag_file> Generate tag file <tag_file>.\n");
+ fprintf(stderr," -s <index_file> Generate search index <index_file>.\n\n");
+ fprintf(stderr,"If no HTML files are given all files in the current dir that\n"
+ "have a .html extension are parsed.\n\n");
+ exit(1);
+}
+
+const char *getArg(int argc,char **argv,int &optind,const char c)
+{
+ char *s=0;
+ if (strlen(&argv[optind][2])>0)
+ s=&argv[optind][2];
+ else if (optind+1<argc)
+ s=argv[++optind];
+ else
+ {
+ fprintf(stderr,"option -%c requires an argument\n",c);
+ exit(1);
+ }
+ return s;
+}
+
+int main(int argc,char **argv)
+{
+ QString tagName;
+ QString indexName;
+
+ int optind=1;
+ const char *arg;
+ while (optind<argc && argv[optind][0]=='-')
+ {
+ switch(argv[optind][1])
+ {
+ case 't':
+ arg=getArg(argc,argv,optind,'t');
+ tagName=arg;
+ break;
+ case 's':
+ arg=getArg(argc,argv,optind,'s');
+ indexName=arg;
+ break;
+ case 'h':
+ case '?':
+ usage(argv[0]);
+ break;
+ default:
+ fprintf(stderr,"Unknown option -%c\n",argv[optind][1]);
+ usage(argv[0]);
+ }
+ optind++;
+ }
+
+ genTag = tagName.length()>0;
+ genIndex = indexName.length()>0;
+
+ if (!genTag && !genIndex)
+ {
+ fprintf(stderr,"Nothing to do !\n\n");
+ usage(argv[0]);
+ }
+
+ int i;
+ if (optind>=argc)
+ {
+ parseFileOrDir(".");
+ }
+ else
+ {
+ for (i=optind;i<argc;i++)
+ {
+ parseFileOrDir(argv[i]);
+ }
+ }
+ if (genIndex)
+ {
+ printf("Writing search index\n");
+ if (!searchIndex.saveIndex(indexName))
+ {
+ fprintf(stderr,"Error: Could not write search index\n");
+ }
+ QFileInfo fi(indexName);
+ if (fi.exists())
+ {
+ QString dir=fi.dir().absPath();
+ fi.setFile(dir+"/search.gif");
+ if (!fi.exists()) writeSearchButton(dir);
+ fi.setFile(dir+"/doxygen.gif");
+ if (!fi.exists()) writeLogo(dir);
+ fi.setFile(dir+"/search.cgi");
+ if (!fi.exists())
+ {
+ QFile f(dir+"/search.cgi");
+ if (f.open(IO_WriteOnly))
+ {
+ QTextStream t(&f);
+ t << "#!/bin/sh" << endl
+ << "DOXYSEARCH=" << endl
+ << "DOXYPATH=" << endl
+ << "if [ -f $DOXYSEARCH ]" << endl
+ << "then" << endl
+ << " $DOXYSEARCH $DOXYPATH" << endl
+ << "else" << endl
+ << " echo \"Content-Type: text/html\"" << endl
+ << " echo \"\"" << endl
+ << " echo \"<H1>Error: $DOXYSEARCH not found. Check cgi script!\"" << endl
+ << "fi" << endl;
+ f.close();
+ }
+ else
+ {
+ fprintf(stderr,"Error: could not open file %s for writing\n",(dir+"/search.cgi").data());
+ }
+ }
+ }
+ }
+ if (genTag)
+ {
+ QFile f(tagName);
+ if (f.open(IO_WriteOnly))
+ {
+ QTextStream t(&f);
+ ClassDef *cd=classList.first();
+ while (cd)
+ {
+ if (cd->isFile) t << "&"; else t << ">";
+ t << cd->name << ":";
+ char *base=cd->bases.first();
+ while (base)
+ {
+ t << base << "?";
+ base=cd->bases.next();
+ }
+ if (!cd->isFile) t << " \"" << cd->fileName << "\"";
+ t << endl;
+ MemberDef *md=cd->memberList.first();
+ while (md)
+ {
+ t << md->name << " " << md->anchor << " \"" << md->args << "\"" << endl;
+ md=cd->memberList.next();
+ }
+ cd=classList.next();
+ }
+ }
+ else
+ {
+ fprintf(stderr,"Error: Could not write tag file %s\n",tagName.data());
+ }
+ }
+ return 0;
+}
+
+extern "C" {
+int tagYYwrap() { return 1 ; }
+};
diff --git a/src/doxytag.pro b/src/doxytag.pro
new file mode 100644
index 0000000..3389c00
--- /dev/null
+++ b/src/doxytag.pro
@@ -0,0 +1,24 @@
+#
+# $Id$
+#
+# Copyright (C) 1997-1999 by Dimitri van Heesch.
+#
+# Permission to use, copy, modify, and distribute this software and its
+# documentation under the terms of the GNU General Public License is hereby
+# granted. No representations are made about the suitability of this software
+# for any purpose. It is provided "as is" without express or implied warranty.
+# See the GNU General Public License for more details.
+#
+# All output generated with Doxygen is not covered by this license.
+#
+# TMake project file for doxytag
+
+TEMPLATE = doxytag.t
+CONFIG = console warn_on qt release
+HEADERS = suffixtree.h searchindex.h logos.h version.h
+SOURCES = doxytag.cpp suffixtree.cpp searchindex.cpp \
+ logos.cpp version.cpp
+TARGET = ../bin/doxytag
+win32:INCLUDEPATH += .
+#unix:INCLUDEPATH += /usr/include
+OBJECTS_DIR = ../objects
diff --git a/src/doxytag.t b/src/doxytag.t
new file mode 100644
index 0000000..1ee8ec5
--- /dev/null
+++ b/src/doxytag.t
@@ -0,0 +1,49 @@
+#
+# $Id$
+#
+# Copyright (C) 1997-1999 by Dimitri van Heesch.
+#
+# Permission to use, copy, modify, and distribute this software and its
+# documentation under the terms of the GNU General Public License is hereby
+# granted. No representations are made about the suitability of this software
+# for any purpose. It is provided "as is" without express or implied warranty.
+# See the GNU General Public License for more details.
+#
+# All output generated with Doxygen is not covered by this license.
+#
+#!
+#! doxytag.t: This is a custom template for building Doxytag
+#!
+#$ IncludeTemplate("app.t");
+
+LEX = flex
+
+#${
+sub GenerateDep {
+ my($obj,$src,$dep) = @_;
+ my(@objv,$srcv,$i,$s,$o,$d,$c);
+ @objv = split(/\s+/,$obj);
+ @srcv = split(/\s+/,$src);
+ for $i ( 0..$#objv ) {
+ $s = $srcv[$i];
+ $o = $objv[$i];
+ next if $s eq "";
+ $text .= $o . ": " . $s;
+ $text .= " ${linebreak}\n\t\t" . $dep if $dep ne "";
+ if ( $moc_output{$s} ne "" ) {
+ $text .= " ${linebreak}\n\t\t" . $moc_output{$s};
+ }
+ $d = &make_depend($s);
+ $text .= " ${linebreak}\n\t\t" . $d if $d ne "";
+ $text .= "\n";
+ }
+ chop $text;
+}
+#$}
+
+#####################
+
+#$ GenerateDep("doxytag.cpp","doxytag.l");
+ $(LEX) -PtagYY -t doxytag.l >doxytag.cpp
+
+
diff --git a/src/entry.cpp b/src/entry.cpp
new file mode 100644
index 0000000..2520fa3
--- /dev/null
+++ b/src/entry.cpp
@@ -0,0 +1,242 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#include "entry.h"
+
+static int newCount=0;
+
+Entry::Entry()
+{
+ num=newCount++;
+ //printf("New Entry %d\n",num);
+ parent=0;
+ sublist = new QList<Entry>;
+ sublist->setAutoDelete(TRUE);
+ extends = new QList<BaseInfo>;
+ extends->setAutoDelete(TRUE);
+ groups = new QList<QString>;
+ groups->setAutoDelete(TRUE);
+ argList = new ArgumentList;
+ argList->setAutoDelete(TRUE);
+ //printf("Entry::Entry() tArgList=0\n");
+ tArgList = 0;
+ reset();
+}
+
+Entry::Entry(const Entry &e)
+{
+ num=newCount++;
+ //printf("Copy New Entry %d\n",num);
+ section = e.section;
+ protection = e.protection;
+ sig = e.sig;
+ slot = e.slot;
+ stat = e.stat;
+ virt = e.virt;
+ parent = e.parent;
+ type = e.type.copy();
+ name = e.name.copy();
+ args = e.args.copy();
+ exception = e.exception.copy();
+ program = e.program.copy();
+ includeFile = e.includeFile.copy();
+ includeName = e.includeFile.copy();
+ doc = e.doc.copy();
+ relates = e.relates.copy();
+ brief = e.brief.copy();
+ inside = e.inside.copy();
+ fileName = e.fileName.copy();
+ startLine = e.startLine;
+ sublist = new QList<Entry>;
+ sublist->setAutoDelete(TRUE);
+ extends = new QList<BaseInfo>;
+ extends->setAutoDelete(TRUE);
+ groups = new QList<QString>;
+ groups->setAutoDelete(TRUE);
+ argList = new ArgumentList;
+ argList->setAutoDelete(TRUE);
+ //printf("Entry::Entry(copy) tArgList=0\n");
+ tArgList = 0;
+
+ // deep copy of the child entry list
+ QListIterator<Entry> eli(*e.sublist);
+ Entry *cur;
+ for (;(cur=eli.current());++eli)
+ {
+ sublist->append(new Entry(*cur));
+ }
+
+ // deep copy base class list
+ QListIterator<BaseInfo> bli(*e.extends);
+ BaseInfo *bi;
+ for (;(bi=bli.current());++bli)
+ {
+ extends->append(new BaseInfo(*bi));
+ }
+
+ // deep copy group list
+ QListIterator<QString> sli(*e.groups);
+ QString *s;
+ for (;(s=sli.current());++sli)
+ {
+ groups->append(new QString(*s));
+ }
+
+ // deep copy argument list
+ QListIterator<Argument> ali(*e.argList);
+ Argument *a;
+ for (;(a=ali.current());++ali)
+ {
+ argList->append(new Argument(*a));
+ }
+ argList->constSpecifier = e.argList->constSpecifier;
+ argList->volatileSpecifier = e.argList->volatileSpecifier;
+ argList->pureSpecifier = e.argList->pureSpecifier;
+
+ // deep copy template argument list
+ if (e.tArgList)
+ {
+ tArgList = new ArgumentList;
+ tArgList->setAutoDelete(TRUE);
+ //printf("Entry::Entry(copy) new tArgList=%p\n",tArgList);
+ QListIterator<Argument> tali(*e.tArgList);
+ for (;(a=tali.current());++tali)
+ {
+ tArgList->append(new Argument(*a));
+ //printf("appending argument %s %s\n",a->type.data(),a->name.data());
+ }
+ }
+}
+
+Entry::~Entry()
+{
+ //printf("Deleting entry %d name %s type %x chilren %d\n",
+ // num,name.data(),section,sublist->count());
+ delete sublist;
+ delete extends;
+ delete groups;
+ delete argList;
+ //printf("Entry::~Entry() tArgList=%p\n",tArgList);
+ delete tArgList;
+}
+
+void Entry::addSubEntry(Entry *current)
+{
+ //printf("Entry %d with name %s type 0x%x added\n",
+ // current->num,current->name.data(),current->section);
+ //printf("Entry::addSubEntry(%s) %p\n",current->name.data(),current->tArgList);
+ current->parent=this;
+ sublist->append(current);
+
+ //if (current->tArgList)
+ //{
+ // Argument * a=current->tArgList->first();
+ // while (a)
+ // {
+ // printf("type=%s name=%s\n",a->type.data(),a->name.data());
+ // a=current->tArgList->next();
+ // }
+ //}
+
+}
+
+void Entry::reset()
+{
+ name.resize(0);
+ type.resize(0);
+ args.resize(0);
+ exception.resize(0);
+ program.resize(0);
+ includeFile.resize(0);
+ includeName.resize(0);
+ doc.resize(0);
+ relates.resize(0);
+ brief.resize(0);
+ inside.resize(0);
+ fileName.resize(0);
+ section = EMPTY_SEC;
+ sig = FALSE;
+ virt = Normal;
+ slot = FALSE;
+ stat = FALSE;
+ proto = FALSE;
+ protection = Public;
+ sublist->clear();
+ extends->clear();
+ groups->clear();
+ argList->clear();
+ if (tArgList) { delete tArgList; tArgList=0; }
+}
+
+
+int Entry::getSize()
+{
+ int size=sizeof(Entry);
+ size+=type.length()+1;
+ size+=name.length()+1;
+ size+=args.length()+1;
+ size+=exception.length()+1;
+ size+=program.length()+1;
+ size+=includeFile.length()+1;
+ size+=includeName.length()+1;
+ size+=doc.length()+1;
+ size+=relates.length()+1;
+ size+=brief.length()+1;
+ size+=inside.length()+1;
+ size+=fileName.length()+1;
+ BaseInfo *bi=extends->first();
+ while (bi)
+ {
+ size+=sizeof(QLNode);
+ size+=bi->name.length()+1+sizeof(bi->prot)+sizeof(bi->virt);
+ bi=extends->next();
+ }
+ QString *s=groups->first();
+ while (s)
+ {
+ size+=sizeof(QLNode);
+ size+=s->length()+1;
+ s=groups->next();
+ }
+ Entry *e=sublist->first();
+ while (e)
+ {
+ size+=e->getSize();
+ e=sublist->next();
+ }
+ Argument *a=argList->first();
+ while (e)
+ {
+ size+=sizeof(Argument);
+ size+=a->type.length()+1
+ +a->name.length()+1
+ +a->defval.length()+1;
+ a=argList->next();
+ }
+ if (tArgList)
+ {
+ a=tArgList->first();
+ while (e)
+ {
+ size+=sizeof(Argument);
+ size+=a->type.length()+1
+ +a->name.length()+1
+ +a->defval.length()+1;
+ a=tArgList->next();
+ }
+ }
+ return size;
+}
diff --git a/src/entry.h b/src/entry.h
new file mode 100644
index 0000000..40624d8
--- /dev/null
+++ b/src/entry.h
@@ -0,0 +1,153 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#ifndef ENTRY_H
+#define ENTRY_H
+
+#include <qstring.h>
+#include <qlist.h>
+
+enum Protection { Public, Protected, Private } ;
+enum Specifier { Normal, Virtual, Pure } ;
+
+struct BaseInfo
+{
+ BaseInfo(const char *n,Protection p,Specifier v) : name(n),prot(p),virt(v) {}
+ QString name; // the name of the base class
+ Protection prot; // inheritance type
+ Specifier virt; // virtualness
+};
+
+struct Argument
+{
+ Argument() {}
+ Argument(const Argument &a)
+ {
+ type=a.type.copy();
+ name=a.name.copy();
+ defval=a.defval.copy();
+ }
+ Argument &operator=(const Argument &a)
+ {
+ if (this!=&a)
+ {
+ type=a.type.copy();
+ name=a.name.copy();
+ defval=a.defval.copy();
+ }
+ return *this;
+ }
+
+ QString type; // argument type
+ QString name; // argument name (if any)
+ QString defval; // argument default value (if any)
+};
+
+class ArgumentList : public QList<Argument>
+{
+ public:
+ ArgumentList() : QList<Argument>(),
+ constSpecifier(FALSE),
+ volatileSpecifier(FALSE),
+ pureSpecifier(FALSE) {}
+ bool constSpecifier;
+ bool volatileSpecifier;
+ bool pureSpecifier;
+};
+
+typedef QListIterator<Argument> ArgumentListIterator;
+
+class Entry
+{
+ public:
+
+ enum Sections {
+ CLASS_SEC = 0x00000001,
+ STRUCT_SEC = 0x00000002,
+ UNION_SEC = 0x00000004,
+ ENUM_SEC = 0x00000008,
+ EMPTY_SEC = 0x00000010,
+ PAGEDOC_SEC = 0x00000020,
+ VARIABLE_SEC = 0x00000040,
+ FUNCTION_SEC = 0x00000080,
+ TYPEDEF_SEC = 0x00000100,
+ CLASSDOC_SEC = 0x00000200,
+ MEMBERDOC_SEC = 0x00000400,
+ OVERLOADDOC_SEC = 0x00000800,
+ EXAMPLE_SEC = 0x00001000,
+ VARIABLEDOC_SEC = 0x00002000,
+ ENUMDOC_SEC = 0x00004000,
+ UNIONDOC_SEC = 0x00008000,
+ STRUCTDOC_SEC = 0x00010000,
+ SOURCE_SEC = 0x00020000,
+ HEADER_SEC = 0x00040000,
+ FILEDOC_SEC = 0x00080000,
+ DEFINEDOC_SEC = 0x00100000,
+ INCLUDE_SEC = 0x00200000,
+ DEFINE_SEC = 0x00400000,
+ GROUPDOC_SEC = 0x00800000,
+ NAMESPACE_SEC = 0x01000000,
+ NAMESPACEDOC_SEC = 0x02000000,
+ COMPOUND_MASK = CLASS_SEC | STRUCT_SEC | UNION_SEC,
+ COMPOUNDDOC_MASK = CLASSDOC_SEC | STRUCTDOC_SEC | UNIONDOC_SEC,
+ SCOPE_MASK = COMPOUND_MASK | NAMESPACE_SEC,
+ FILE_MASK = SOURCE_SEC | HEADER_SEC
+ };
+
+ Entry();
+ Entry(const Entry &);
+ ~Entry();
+ int getSize();
+
+ void addSubEntry (Entry* e) ;
+ void reset();
+
+ int section; // entry type;
+ Protection protection; // class protection
+ bool sig; // a Qt signal ?
+ bool slot; // a Qt slot ?
+ bool stat; // static ?
+ bool proto; // prototype ?
+ Specifier virt; // virtualness of the entry
+ Entry *parent; // parent node in the tree
+ QString type; // member type
+ QString name; // member name
+ QString args; // member argument string
+ ArgumentList *argList; // member arguments as a list
+ ArgumentList *tArgList; // template argument list
+ ArgumentList *tNameList; // template name list
+ QString program; // the program text
+ QString includeFile; // include file (2 arg of \class, must be unique)
+ QString includeName; // include name (3 arg of \class)
+ QString doc; // documentation block (partly parsed)
+ QString relates; // related class (doc block)
+ QString brief; // brief description (doc block)
+ QString inside; // name of the class in which documents are found
+ QString exception; // throw specification
+ QList<Entry> *sublist; // entries that are children of this one
+ QList<BaseInfo> *extends; // list of base classes
+ QList<QString> *groups; // list of groups this entry belongs to
+ QString fileName; // file this entry was extracted from
+ int startLine; // start line of entry in the source
+ int num;
+ private:
+ Entry &operator=(const Entry &);
+} ;
+
+typedef QList<Entry> EntryList;
+typedef QListIterator<Entry> EntryListIterator;
+
+#endif
diff --git a/src/example.h b/src/example.h
new file mode 100644
index 0000000..eef33ce
--- /dev/null
+++ b/src/example.h
@@ -0,0 +1,45 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#ifndef EXAMPLE_H
+#define EXAMPLE_H
+
+#include <qstring.h>
+
+class ClassDef;
+class MemberName;
+
+struct Example
+{
+ QString anchor;
+ QString name;
+ QString file;
+};
+
+class ExampleList : public QList<Example>
+{
+ public:
+ ExampleList() : QList<Example>() {}
+ ~ExampleList() {}
+ int compareItems(GCI item1,GCI item2)
+ {
+ return stricmp(((Example *)item1)->name,((Example *)item2)->name);
+ }
+};
+
+typedef QDict<Example> ExampleDict;
+
+#endif
diff --git a/src/filedef.cpp b/src/filedef.cpp
new file mode 100644
index 0000000..54266a5
--- /dev/null
+++ b/src/filedef.cpp
@@ -0,0 +1,291 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#include "memberlist.h"
+#include "classlist.h"
+#include "define.h"
+#include "filedef.h"
+#include "scanner.h"
+#include "doxygen.h"
+#include "memberdef.h"
+#include "classdef.h"
+#include "namespacedef.h"
+#include "util.h"
+#include "language.h"
+
+/*! create a new file definition, where \a p is the file path,
+ \a the file name, and \a ref is an HTML anchor name if the
+ file was read from a tag file or 0 otherwise
+*/
+FileDef::FileDef(const char *p,const char *nm,const char *ref)
+ : Definition(nm)
+{
+ path=p;
+ filepath=path+nm;
+ filename=nameToFile(nm);
+ reference=ref;
+ memList = new MemberList;
+ classList = new ClassList;
+ includeList = new FileList;
+ defineList = new DefineList;
+ namespaceList = new NamespaceList;
+}
+
+/*! destroy the file definition */
+FileDef::~FileDef()
+{
+ delete memList;
+ delete classList;
+ delete includeList;
+ delete defineList;
+}
+
+/*! Compute the HTML anchor names for all members in the class */
+void FileDef::computeAnchors()
+{
+ setAnchors('a',memList);
+}
+
+/*! Write the documentation page for this file to the file of output
+ generators \a ol.
+*/
+void FileDef::writeDocumentation(OutputList &ol)
+{
+ //funcList->countDecMembers();
+
+ QString pageTitle=name()+" File Reference";
+ startFile(ol,diskname,pageTitle);
+ startTitle(ol);
+ ol.docify(pageTitle);
+ endTitle(ol,name());
+ //ol.newParagraph();
+
+ if (genTagFile.length()>0) tagFile << "&" << name() << ":\n";
+
+ //brief=brief.stripWhiteSpace();
+ //int bl=brief.length();
+ OutputList briefOutput(&ol);
+ if (briefDescription())
+ {
+ //if (brief.at(bl-1)!='.' && brief.at(bl-1)!='!' && brief.at(bl!='?'))
+ // brief+='.';
+ parseDoc(briefOutput,0,0,briefDescription());
+ ol+=briefOutput;
+ ol.writeString(" \n");
+ ol.disableAllBut(OutputGenerator::Html);
+ ol.startTextLink(0,"details");
+ parseDoc(ol,0,0,theTranslator->trMore());
+ ol.endTextLink();
+ ol.enableAll();
+ }
+ ol.disable(OutputGenerator::Man);
+ ol.newParagraph();
+ ol.enable(OutputGenerator::Man);
+ ol.writeSynopsis();
+
+ if (classList->count()>0)
+ {
+ ClassDef *cd=classList->first();
+ bool found=FALSE;
+ while (cd)
+ {
+ if (//cd->name()[0]!='@' &&
+ //(cd->protection()!=Private || extractPrivateFlag) &&
+ //(cd->hasDocumentation() || !hideClassFlag))
+ cd->isVisibleExt()
+ )
+ {
+ if (!found)
+ {
+ ol.startMemberHeader();
+ parseDoc(ol,0,0,theTranslator->trCompounds());
+ ol.endMemberHeader();
+ ol.startMemberList();
+ found=TRUE;
+ }
+ ol.startMemberItem();
+ switch (cd->compoundType())
+ {
+ case ClassDef::Class: ol.writeString("class"); break;
+ case ClassDef::Struct: ol.writeString("struct"); break;
+ case ClassDef::Union: ol.writeString("union"); break;
+ }
+ ol.writeString(" ");
+ if (cd->hasDocumentation())
+ {
+ ol.writeObjectLink(cd->getReference(),
+ cd->classFile(),
+ 0,
+ cd->name()
+ );
+ }
+ else
+ {
+ ol.startBold();
+ ol.docify(cd->name());
+ ol.endBold();
+ }
+ ol.endMemberItem();
+ }
+ cd=classList->next();
+ }
+ if (found) ol.endMemberList();
+ }
+
+ writeMemberDecs(ol,0,0,this,0,0,memList);
+
+ //doc=doc.stripWhiteSpace();
+ //int bl=brief.length();
+ //int dl=doc.length();
+ if (!briefDescription().isEmpty() || !documentation().isEmpty())
+ {
+ ol.writeRuler();
+ ol.writeAnchor("details");
+ ol.startGroupHeader();
+ parseDoc(ol,0,0,theTranslator->trDetailedDescription());
+ ol.endGroupHeader();
+ if (!briefDescription().isEmpty())
+ {
+ ol+=briefOutput;
+ ol.newParagraph();
+ }
+ if (!documentation().isEmpty())
+ {
+ //if (doc.at(dl-1)!='.' && doc.at(dl-1)!='!' && doc.at(dl-1)!='?')
+ // doc+='.';
+ parseDoc(ol,0,0,documentation()+"\n");
+ ol.newParagraph();
+ }
+ }
+
+ memList->countDocMembers();
+
+ if ( memList->defineCount()>0 )
+ {
+ ol.writeRuler();
+ ol.startGroupHeader();
+ parseDoc(ol,0,0,theTranslator->trDefineDocumentation());
+ ol.endGroupHeader();
+ writeMemberDocs(ol,memList,name(),MemberDef::Define);
+ }
+
+ if ( memList->protoCount()>0 )
+ {
+ ol.writeRuler();
+ ol.startGroupHeader();
+ parseDoc(ol,0,0,theTranslator->trFunctionPrototypeDocumentation());
+ ol.endGroupHeader();
+ writeMemberDocs(ol,memList,name(),MemberDef::Prototype);
+ }
+
+ if ( memList->typedefCount()>0 )
+ {
+ ol.writeRuler();
+ ol.startGroupHeader();
+ parseDoc(ol,0,0,theTranslator->trTypedefDocumentation());
+ ol.endGroupHeader();
+ writeMemberDocs(ol,memList,name(),MemberDef::Typedef);
+ }
+
+ if ( memList->enumCount()>0 )
+ {
+ ol.writeRuler();
+ ol.startGroupHeader();
+ parseDoc(ol,0,0,theTranslator->trEnumerationTypeDocumentation());
+ ol.endGroupHeader();
+ writeMemberDocs(ol,memList,name(),MemberDef::Enumeration);
+ }
+
+ if ( memList->enumValueCount()>0 )
+ {
+ ol.writeRuler();
+ ol.startGroupHeader();
+ parseDoc(ol,0,0,theTranslator->trEnumerationValueDocumentation());
+ ol.endGroupHeader();
+ writeMemberDocs(ol,memList,name(),MemberDef::EnumValue);
+ }
+
+ if ( memList->funcCount()>0 )
+ {
+ ol.writeRuler();
+ ol.startGroupHeader();
+ parseDoc(ol,0,0,theTranslator->trFunctionDocumentation());
+ ol.endGroupHeader();
+ writeMemberDocs(ol,memList,name(),MemberDef::Function);
+ }
+
+ if ( memList->varCount()>0 )
+ {
+ ol.writeRuler();
+ ol.startGroupHeader();
+ parseDoc(ol,0,0,theTranslator->trVariableDocumentation());
+ ol.endGroupHeader();
+ writeMemberDocs(ol,memList,name(),MemberDef::Variable);
+ }
+
+ // write Author section (Man only)
+ ol.disableAllBut(OutputGenerator::Man);
+ ol.startGroupHeader();
+ parseDoc(ol,0,0,theTranslator->trAuthor());
+ ol.endGroupHeader();
+ parseDoc(ol,0,0,theTranslator->trGeneratedAutomatically(projectName));
+ ol.enableAll();
+ endFile(ol);
+}
+
+/*! Adds member definition \a md to the list of all members of this file */
+void FileDef::insertMember(MemberDef *md)
+{
+ memList->append(md);
+}
+
+/*! Adds compound definition \a cd to the list of all compounds of this file */
+void FileDef::insertClass(ClassDef *cd)
+{
+ classList->append(cd);
+}
+
+/*! Adds namespace definition \a nd to the list of all compounds of this file */
+void FileDef::insertNamespace(NamespaceDef *nd)
+{
+ namespaceList->append(nd);
+}
+
+//-----------------------------------------------------------------------------
+
+/*! Creates a file list. */
+FileList::FileList() : QList<FileDef>()
+{
+}
+
+/*! Destroys a file list */
+FileList::~FileList()
+{
+}
+
+/*! Compares two files by name. */
+int FileList::compareItems(GCI item1, GCI item2)
+{
+ FileDef *c1=(FileDef *)item1;
+ FileDef *c2=(FileDef *)item2;
+ return strcmp(c1->name(),c2->name());
+}
+
+/*! Create a file list iterator. */
+FileListIterator::FileListIterator(const FileList &cllist) :
+ QListIterator<FileDef>(cllist)
+{
+}
diff --git a/src/filedef.h b/src/filedef.h
new file mode 100644
index 0000000..36ce9cb
--- /dev/null
+++ b/src/filedef.h
@@ -0,0 +1,158 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#ifndef FILEDEF_H
+#define FILEDEF_H
+
+#include <qlist.h>
+#include "index.h"
+#include "config.h"
+#include "definition.h"
+
+class MemberList;
+class FileList;
+class ClassList;
+class MemberDef;
+class ClassDef;
+class OutputList;
+class DefineList;
+class NamespaceDef;
+class NamespaceList;
+
+/*! \class FileDef filedef.h
+ \brief A File definition.
+
+ An object of this class contains all file information that is gathered.
+ This includes the members and compounds defined in the file.
+
+ The member writeDocumentation() can be used to generate the page of
+ documentation to HTML and LaTeX.
+*/
+
+class FileDef : public Definition
+{
+ friend class FileName;
+
+ public:
+ //enum FileType { Source, Header, Unknown };
+
+ FileDef(const char *p,const char *n,const char *ref=0);
+ ~FileDef();
+
+ /*! Returns the unique file name (this may include part of the path). */
+ QString name() const
+ {
+ if (fullPathNameFlag)
+ return filename;
+ else
+ return Definition::name();
+ }
+
+ /*! Returns nameString with all slashes replaced by underscores. */
+ const char *diskName() const { return diskname; }
+
+ /*! Returns the absolute path including the file name. */
+ QString absFilePath() const { return filepath; }
+
+ /*! Returns the name of the verbatim copy of this file (if any). */
+ const char *includeName() const { return incName; }
+
+ /*! Returns the documentation that was available for this file. */
+ //const char *documentation() const { return doc; }
+
+ /*! Returns the brief description that was given for this file. */
+ //const char *briefDescription() const { return brief; }
+
+ /*! Sets the name of the include file to \a n. */
+ void setIncludeName(const char *n_) { incName=n_; }
+
+ /*! Sets the name of the include file to \a n. */
+ //void setBriefDescription(const char *b) { brief=b; }
+
+ /*! Sets the documentaton of this file to \a d. */
+ //void setDocumentation(const char *d) { doc=d; }
+
+ /*! Returns the absolute path of this file. */
+ QString getPath() const { return path; }
+
+ /*! Returns true iff any documentation for this file is found. */
+ //bool hasDocumentation()
+ // { return extractAllFlag || !doc.isNull() || !brief.isNull(); }
+
+ /*! Returns true iff this file was externally defined
+ (i.e. read from a tag file) */
+ bool isReference() { return !reference.isNull(); }
+
+ /*! Returns the reference name of the external file, if any or 0
+ if the file is not defined. */
+ const char *getReference() { return reference; }
+
+ //void setFileType(FileType ft) { ftype = ft; }
+ //FileType fileType() const { return ftype; }
+
+ void writeDocumentation(OutputList &ol);
+ friend void generatedFileNames();
+ void insertMember(MemberDef *fd);
+ void insertClass(ClassDef *cd);
+ void insertNamespace(NamespaceDef *nd);
+ void computeAnchors();
+
+ private:
+ MemberList *memList;
+ ClassList *classList;
+ FileList *includeList;
+ NamespaceList *namespaceList;
+ DefineList *defineList;
+ //QString n;
+ //QString doc;
+ //QString brief;
+ QString reference;
+ QString path;
+ QString filepath;
+ QString diskname;
+ QString filename;
+ QString incName;
+ //FileType ftype;
+};
+
+/*! \class FileList filedef.h
+ \brief This class is list of file definitions.
+
+ It is based on QList.
+*/
+
+class FileList : public QList<FileDef>
+{
+ public:
+ FileList();
+ ~FileList();
+
+ int compareItems(GCI item1,GCI item2);
+};
+
+/*! \class FileListIterator filedef.h
+ \brief This class represents a file list iterator.
+
+ It is based on QListIterator.
+*/
+
+class FileListIterator : public QListIterator<FileDef>
+{
+ public:
+ FileListIterator(const FileList &list);
+};
+
+#endif
diff --git a/src/filename.cpp b/src/filename.cpp
new file mode 100644
index 0000000..60367dc
--- /dev/null
+++ b/src/filename.cpp
@@ -0,0 +1,133 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#include "filename.h"
+#include "util.h"
+
+FileName::FileName(const char *n) : QList<FileDef>()
+{
+ name=n;
+}
+
+FileName::~FileName()
+{
+}
+
+//static QString convertSlashes(const char *s)
+//{
+// QString result=s;
+// int i,l=result.length();
+// for (i=0;i<l;i++) if (result.at(i)=='/') result.at(i)='_';
+// return result;
+//}
+
+void FileName::generateDiskNames()
+{
+ QString commonPrefix;
+ FileDef *fd=first();
+ int count=0;
+ while (fd) { if (!fd->isReference()) count++; fd=next(); }
+ if (count==1)
+ {
+ fd=first();
+ // skip references
+ while (fd && fd->isReference()) fd=next();
+ // name if unique, so diskname is simply the name
+ fd->diskname=name;
+ }
+ else if (count>1) // multiple occurrences of the same file name
+ {
+ //printf("Multiple occurrences of %s\n",name.data());
+ int i=0,j=0;
+ bool found=FALSE;
+ while (!found)
+ {
+ fd=first();
+ while (fd && fd->isReference()) fd=next();
+ char c=fd->path.at(i);
+ if (c=='/') j=i; // remember last position of dirname
+ while (fd && !found)
+ {
+ if (!fd->isReference())
+ {
+ //printf("i=%d fd->path=`%s' fd->name=`%s'\n",i,fd->path.data(),fd->name().data());
+ if (i==(int)fd->path.length())
+ {
+ warning("Warning: Input file found multiple times!\n"
+ " The generated documentation for this file may not be correct!\n");
+ found=TRUE;
+ }
+ else if (fd->path[i]!=c)
+ {
+ found=TRUE;
+ }
+ }
+ fd=next();
+ }
+ i++;
+ }
+ fd=first();
+ while (fd)
+ {
+ //printf("fd->setName(%s)\n",(fd->path.right(fd->path.length()-j-1)+name).data());
+ fd->setName(fd->path.right(fd->path.length()-j-1)+name);
+ fd->diskname=convertSlashes(fd->name());
+ fd=next();
+ }
+ }
+}
+
+int FileName::compareItems(GCI item1, GCI item2)
+{
+ FileName *f1=(FileName *)item1;
+ FileName *f2=(FileName *)item2;
+ return stricmp(f1->fileName(),f2->fileName());
+}
+
+FileNameIterator::FileNameIterator(const FileName &fname) :
+ QListIterator<FileDef>(fname)
+{
+}
+
+FileNameList::FileNameList() : QList<FileName>()
+{
+}
+
+FileNameList::~FileNameList()
+{
+}
+
+void FileNameList::generateDiskNames()
+{
+ FileName *fn=first();
+ while (fn)
+ {
+ fn->generateDiskNames();
+ fn=next();
+ }
+}
+
+int FileNameList::compareItems(GCI item1, GCI item2)
+{
+ FileName *f1=(FileName *)item1;
+ FileName *f2=(FileName *)item2;
+ return stricmp(f1->fileName(),f2->fileName());
+}
+
+FileNameListIterator::FileNameListIterator(const FileNameList &fnlist) :
+ QListIterator<FileName>(fnlist)
+{
+}
diff --git a/src/filename.h b/src/filename.h
new file mode 100644
index 0000000..2932d18
--- /dev/null
+++ b/src/filename.h
@@ -0,0 +1,63 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#ifndef FILENAME_H
+#define FILENAME_H
+
+#include <qdict.h>
+#include "filedef.h"
+
+class FileName : public QList<FileDef>
+{
+ public:
+ FileName(const char *name);
+ ~FileName();
+ const char *fileName() const { return name; }
+ void generateDiskNames();
+ int compareItems(GCI item1,GCI item2);
+
+ private:
+ QString name;
+};
+
+class FileNameIterator : public QListIterator<FileDef>
+{
+ public:
+ FileNameIterator(const FileName &list);
+};
+
+class FileNameList : public QList<FileName>
+{
+ public:
+ FileNameList();
+ ~FileNameList();
+ void generateDiskNames();
+ int compareItems(GCI item1,GCI item2);
+};
+
+class FileNameListIterator : public QListIterator<FileName>
+{
+ public:
+ FileNameListIterator( const FileNameList &list );
+};
+
+class FileNameDict : public QDict<FileName>
+{
+ public:
+ FileNameDict(uint size) : QDict<FileName>(size) {}
+};
+
+#endif
diff --git a/src/formula.cpp b/src/formula.cpp
new file mode 100644
index 0000000..53e8b38
--- /dev/null
+++ b/src/formula.cpp
@@ -0,0 +1,286 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <qfile.h>
+#include <qtstream.h>
+#include <qfileinf.h>
+#include <qdir.h>
+
+#include "formula.h"
+#include "image.h"
+#include "util.h"
+#include "message.h"
+
+Formula::Formula(const char *text)
+{
+ static int count=0;
+ number = count++;
+ form=text;
+}
+
+Formula::~Formula()
+{
+}
+
+int Formula::getId()
+{
+ return number;
+}
+
+void FormulaList::generateBitmaps(const char *path)
+{
+ int x1,y1,x2,y2;
+ QDir d(path);
+ // store the original directory
+ if (!d.exists()) { err("Error: Output dir %s does not exist!\n",path); exit(1); }
+ QString oldDir = QDir::currentDirPath().copy();
+ // goto the html output directory (i.e. path)
+ QDir::setCurrent(d.absPath());
+ QDir thisDir;
+ // generate a latex file containing one formula per page.
+ QString texName="_formulas.tex";
+ QList<int> pagesToGenerate;
+ pagesToGenerate.setAutoDelete(TRUE);
+ FormulaListIterator fli(*this);
+ Formula *formula;
+ QFile f(texName);
+ if (f.open(IO_WriteOnly))
+ {
+ QTextStream t(&f);
+ t << "\\documentclass{article}" << endl;
+ t << "\\usepackage{epsf}" << endl; // for those who want to include images
+ t << "\\pagestyle{empty}" << endl;
+ t << "\\begin{document}" << endl;
+ int page=0;
+ for (fli.toFirst();(formula=fli.current());++fli)
+ {
+ QString resultName;
+ resultName.sprintf("form-%d.gif",formula->getId());
+ // only formulas for which no image exists are generated
+ QFileInfo fi(resultName);
+ if (!fi.exists())
+ {
+ // we force a pagebreak after each formula
+ t << formula->getFormulaText() << endl << "\\pagebreak\n\n";
+ pagesToGenerate.append(new int(page));
+ }
+ page++;
+ }
+ t << "\\end{document}" << endl;
+ f.close();
+ }
+ if (pagesToGenerate.count()>0) // there are new formulas
+ {
+ //printf("Running latex...\n");
+ //system("latex _formulas.tex </dev/null >/dev/null");
+ system("latex _formulas.tex");
+ //printf("Running dvips...\n");
+ QListIterator<int> pli(pagesToGenerate);
+ int *pagePtr;
+ int pageIndex=1;
+ for (;(pagePtr=pli.current());++pli,++pageIndex)
+ {
+ int pageNum=*pagePtr;
+ msg("Generating image form-%d.gif for formula\n",pageNum);
+ char dviCmd[256];
+ QString formBase;
+ formBase.sprintf("_form%d",pageNum);
+ // run dvips to convert the page with number pageIndex to an
+ // encapsulated postscript.
+ sprintf(dviCmd,"dvips -q -D 600 -E -n 1 -p %d -o %s.eps _formulas.dvi",
+ pageIndex,formBase.data());
+ system(dviCmd);
+ // now we read the generated postscript file to extract the bounding box
+ QFileInfo fi(formBase+".eps");
+ if (fi.exists())
+ {
+ QString eps = fileToString(formBase+".eps");
+ int i=eps.find("%%BoundingBox:");
+ if (i!=-1)
+ {
+ sscanf(eps.data()+i,"%%%%BoundingBox:%d %d %d %d",&x1,&y1,&x2,&y2);
+ }
+ else
+ {
+ err("Error: Couldn't extract bounding box!\n");
+ }
+ }
+ // next we generate a postscript file which contains the eps
+ // and displays it in the right colors and the right bounding box
+ f.setName(formBase+".ps");
+ if (f.open(IO_WriteOnly))
+ {
+ QTextStream t(&f);
+ t << "1 1 1 setrgbcolor" << endl; // anti-alias to white background
+ t << "newpath" << endl;
+ t << "-1 -1 moveto" << endl;
+ t << x2-x1+2 << " -1 lineto" << endl;
+ t << x2-x1+2 << " " << y2-y1+2 << " lineto" << endl;
+ t << "-1 " << y2-y1+2 << " lineto" <<endl;
+ t << "closepath" << endl;
+ t << "fill" << endl;
+ t << -x1 << " " << -y1 << " translate" << endl;
+ t << "0 0 0 setrgbcolor" << endl;
+ t << "(" << formBase << ".eps) run" << endl;
+ f.close();
+ }
+ // scale the image so that it is four times larger than needed.
+ // and the sizes are a multiple of four.
+ const double scaleFactor = 16.0/3.0;
+ int gx = (((int)((x2-x1)*scaleFactor))+3)&~2;
+ int gy = (((int)((y2-y1)*scaleFactor))+3)&~2;
+ char gsCmd[256];
+ // Then we run ghostscript to convert the postscript to a pixmap
+ // The pixmap is a truecolor image, where only black and white are
+ // used.
+ sprintf(gsCmd,"gs -q -g%dx%d -r%dx%dx -sDEVICE=ppmraw "
+ "-sOutputFile=%s.pnm -DNOPAUSE -- %s.ps",
+ gx,gy,(int)(scaleFactor*72),(int)(scaleFactor*72),
+ formBase.data(),formBase.data()
+ );
+ //printf("Running ghostscript...\n");
+ system(gsCmd);
+ f.setName(formBase+".pnm");
+ uint imageX=0,imageY=0;
+ // we read the generated image again, to obtain the pixel data.
+ if (f.open(IO_ReadOnly))
+ {
+ QTextStream t(&f);
+ QString s;
+ if (!t.eof())
+ s=t.readLine();
+ if (s.length()<2 || s.left(2)!="P6")
+ err("Error: ghostscript produced an illegal image format!");
+ else
+ {
+ // assume the size if after the first line that does not start with
+ // # excluding the first line of the file.
+ while (!t.eof() && (s=t.readLine()) && !s.isEmpty() && s.at(0)=='#');
+ sscanf(s,"%d %d",&imageX,&imageY);
+ }
+ if (imageX>0 && imageY>0)
+ {
+ //printf("Converting image...\n");
+ char *data = new char[imageX*imageY*3]; // rgb 8:8:8 format
+ uint i,x,y,ix,iy;
+ f.readBlock(data,imageX*imageY*3);
+ Image srcImage(imageX,imageY),
+ filteredImage(imageX,imageY),
+ dstImage(imageX/4,imageY/4);
+ uchar *ps=srcImage.getData();
+ // convert image to black (1) and white (0) index.
+ for (i=0;i<imageX*imageY;i++) *ps++= (data[i*3]==0 ? 1 : 0);
+ // apply a simple box filter to the image
+ static int filterMask[]={1,2,1,2,8,2,1,2,1};
+ for (y=0;y<srcImage.getHeight();y++)
+ {
+ for (x=0;x<srcImage.getWidth();x++)
+ {
+ int s=0;
+ for (iy=0;iy<2;iy++)
+ {
+ for (ix=0;ix<2;ix++)
+ {
+ s+=srcImage.getPixel(x+ix-1,y+iy-1)*filterMask[iy*3+ix];
+ }
+ }
+ filteredImage.setPixel(x,y,s);
+ }
+ }
+ // down-sample the image to 1/16th of the area using 16 gray scale
+ // colors.
+ for (y=0;y<dstImage.getHeight();y++)
+ {
+ for (x=0;x<dstImage.getWidth();x++)
+ {
+ int xp=x<<2;
+ int yp=y<<2;
+ int c=filteredImage.getPixel(xp+0,yp+0)+
+ filteredImage.getPixel(xp+1,yp+0)+
+ filteredImage.getPixel(xp+2,yp+0)+
+ filteredImage.getPixel(xp+3,yp+0)+
+ filteredImage.getPixel(xp+0,yp+1)+
+ filteredImage.getPixel(xp+1,yp+1)+
+ filteredImage.getPixel(xp+2,yp+1)+
+ filteredImage.getPixel(xp+3,yp+1)+
+ filteredImage.getPixel(xp+0,yp+2)+
+ filteredImage.getPixel(xp+1,yp+2)+
+ filteredImage.getPixel(xp+2,yp+2)+
+ filteredImage.getPixel(xp+3,yp+2)+
+ filteredImage.getPixel(xp+0,yp+3)+
+ filteredImage.getPixel(xp+1,yp+3)+
+ filteredImage.getPixel(xp+2,yp+3)+
+ filteredImage.getPixel(xp+3,yp+3);
+ // here we scale and clip the color value so the
+ // resulting image has a reasonable contrast
+ dstImage.setPixel(x,y,QMIN(15,(c*15)/(16*10)));
+ }
+ }
+ // save the result as a gif
+ QString resultName;
+ resultName.sprintf("form-%d.gif",pageNum);
+ // the option parameter 1 is used here as a temporary hack
+ // to select the right color palette!
+ dstImage.save(resultName,1);
+ delete[] data;
+ }
+ f.close();
+ }
+ // remove intermediate image files
+ thisDir.remove(formBase+".eps");
+ thisDir.remove(formBase+".pnm");
+ thisDir.remove(formBase+".ps");
+ }
+ // remove intermediate files produced by latex
+ thisDir.remove("_formulas.dvi");
+ thisDir.remove("_formulas.log");
+ thisDir.remove("_formulas.aux");
+ }
+ // remove the latex file itself
+ thisDir.remove("_formulas.tex");
+ // write/update the formula repository so we know what text the
+ // generated gifs represent (we use this next time to avoid regeneration
+ // of the gifs, and to avoid forcing the user to delete all gifs in order
+ // to let a browser refresh the images).
+ f.setName("formula.repository");
+ if (f.open(IO_WriteOnly))
+ {
+ QTextStream t(&f);
+ for (fli.toFirst();(formula=fli.current());++fli)
+ {
+ t << "\\form#" << formula->getId() << ":" << formula->getFormulaText() << endl;
+ }
+ f.close();
+ }
+ // reset the directory to the original location.
+ QDir::setCurrent(oldDir);
+}
+
+
+#ifdef FORMULA_TEST
+int main()
+{
+ FormulaList fl;
+ fl.append(new Formula("$x^2$"));
+ fl.append(new Formula("$y^2$"));
+ fl.append(new Formula("$\\sqrt{x_0^2+x_1^2+x_2^2}$"));
+ fl.generateBitmaps("dest");
+ return 0;
+}
+#endif
diff --git a/src/formula.h b/src/formula.h
new file mode 100644
index 0000000..977ccfe
--- /dev/null
+++ b/src/formula.h
@@ -0,0 +1,57 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#ifndef FORMULA_H
+#define FORMULA_H
+
+#include <qstring.h>
+#include <qlist.h>
+#include <qdict.h>
+
+class Formula
+{
+ public:
+ Formula(const char *text);
+ ~Formula();
+ int getId();
+ QString getFormulaText() const { return form; }
+
+ private:
+ int number;
+ QString form;
+};
+
+class FormulaList : public QList<Formula>
+{
+ public:
+ void generateBitmaps(const char *path);
+};
+
+class FormulaListIterator : public QListIterator<Formula>
+{
+ public:
+ FormulaListIterator(const FormulaList &l) :
+ QListIterator<Formula>(l) {}
+};
+
+class FormulaDict : public QDict<Formula>
+{
+ public:
+ FormulaDict(uint size) :
+ QDict<Formula>(size) {}
+};
+
+#endif
diff --git a/src/gifenc.cpp b/src/gifenc.cpp
new file mode 100644
index 0000000..1160531
--- /dev/null
+++ b/src/gifenc.cpp
@@ -0,0 +1,293 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ * The GIF compression code below is based on the file ppmtogif.c of the
+ * netpbm package. The original copyright message follows:
+ *
+ * ---------------------------------------------------------------------------
+ *
+ * Copyright (C) 1989 by Jef Poskanzer.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose and without fee is hereby granted, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation. This software is provided "as is" without express or
+ * implied warranty.
+ *
+ * ---------------------------------------------------------------------------
+ *
+ * The Graphics Interchange Format(c) is the Copyright property of
+ * CompuServe Incorporated. GIF(sm) is a Service Mark property of
+ * CompuServe Incorporated.
+ */
+
+#include "gifenc.h"
+
+static const unsigned int masks[] = { 0x0000, 0x0001, 0x0003, 0x0007, 0x000F,
+ 0x001F, 0x003F, 0x007F, 0x00FF,
+ 0x01FF, 0x03FF, 0x07FF, 0x0FFF,
+ 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF };
+
+GifEncoder::GifEncoder(Byte *rawBytes,Color *p,int w,int h, Byte d,
+ int t)
+ : colorResolution(8),globalPaletteFlag(0x80),bits(12),
+ maxMaxCode(1<<bits)
+{
+ width = w;
+ height = h;
+ depth = d;
+ transIndex = t;
+ palette = p;
+ data = rawBytes;
+ dataPtr = data;
+}
+
+GifEncoder::~GifEncoder()
+{
+}
+
+void GifEncoder::writeGIF(QFile &fp)
+{
+ // Write the Magic header
+ fp.writeBlock( transIndex < 0 ? "GIF87a" : "GIF89a", 6 );
+
+ // Write the logical screen descriptor
+ putWord( width, fp );
+ putWord( height, fp );
+ Byte pack = globalPaletteFlag | ((colorResolution-1)<<4) | (depth-1);
+ putByte( pack, fp );
+ putByte( 0, fp ); // the background color
+ putByte( 0, fp ); // no aspect ration defined
+
+ // Write global color table
+ int i; for ( i=0 ; i< (1<<depth) ; i++)
+ {
+ putByte(palette[i].red, fp);
+ putByte(palette[i].green,fp);
+ putByte(palette[i].blue, fp);
+ }
+
+ if ( transIndex >= 0)
+ {
+ // Write graphic control extension (needed for GIF transparancy)
+ putByte( 0x21, fp); // extension introducer
+ putByte( 0xf9, fp); // graphic control label
+ putByte( 4, fp); // block size
+ putByte( 1, fp); // announce transparacy value
+ putWord( 0, fp); // zero delay time
+ putByte( transIndex, fp); // write transparant index
+ putByte( 0, fp); // end block
+ }
+
+ // Write the image descriptor
+ putByte( 0x2c, fp); // image separator
+ putWord( 0, fp); // image left position
+ putWord( 0, fp); // image top position
+ putWord( width, fp); // image width
+ putWord( height, fp); // image height
+ putByte( 0, fp); // no local color table, no interlacing
+
+ // Write table based image data
+ Byte initCodeSize = depth<=1 ? 2 : depth;
+ putByte( initCodeSize, fp); // LZW Minimum Code Size
+ compress( initCodeSize+1, fp);
+ putByte( 0, fp); // end of blocks
+
+ // Write GIF Trailer
+ putByte( 0x3b, fp);
+}
+
+void GifEncoder::compress( int ibits, QFile &outfile )
+{
+ int i;
+ int entry;
+
+ initBits = ibits;
+ numPixels = width*height;
+ dataPtr = data;
+ clearFlag = FALSE;
+ nBits = initBits;
+ maxCode = (1<<nBits) -1;
+ ClearCode = (1 << (initBits - 1));
+ EOFCode = ClearCode + 1;
+ freeEntry = ClearCode + 2;
+ aCount = 0;
+ curAccum = 0;
+ curBits = 0;
+
+ entry = nextPixel();
+
+ int hshift = 0;
+ int fcode;
+ for ( fcode = hashTableSize; fcode < 65536L; fcode *= 2L ) ++hshift;
+ hshift = 8 - hshift; /* set hash code range bound */
+
+ clearHashTable(); /* clear hash table */
+
+ writeCode( ClearCode,outfile );
+
+ int c;
+ while ( (c = nextPixel()) != EOF )
+ {
+ fcode = (c << bits) + entry;
+ i = (c << hshift) ^ entry; /* xor hashing */
+
+ bool found=FALSE;
+ if (htab[i]==fcode)
+ {
+ entry = codetab[i];
+ found=TRUE;
+ }
+ else if (htab[i]>=0)
+ {
+ int disp = hashTableSize - i;
+ if (i==0) disp=1;
+ do
+ {
+ if ((i-=disp)<0) i+=hashTableSize;
+ if (htab[i]==fcode)
+ {
+ entry=codetab[i];
+ found=TRUE;
+ }
+ } while (htab[i]>0 && !found);
+ }
+ if (!found)
+ {
+ writeCode( entry, outfile );
+ entry = c;
+ if ( freeEntry < maxMaxCode )
+ {
+ codetab[i] = freeEntry++; /* code -> hashtable */
+ htab[i] = fcode;
+ }
+ else
+ {
+ clearHashTable();
+ freeEntry = ClearCode + 2;
+ clearFlag = TRUE;
+ writeCode( ClearCode, outfile );
+ }
+ }
+ }
+ writeCode( entry, outfile );
+ writeCode( EOFCode, outfile );
+}
+
+void GifEncoder::putWord( Word w, QFile &fp )
+{
+ fp.putch( w & 0xff );
+ fp.putch( (w>>8) & 0xff );
+}
+
+void GifEncoder::putByte( Byte b, QFile &fp )
+{
+ fp.putch( b );
+}
+
+int GifEncoder::nextPixel()
+{
+ if ( --numPixels < 0) return EOF;
+ return *dataPtr++;
+}
+
+void GifEncoder::writeCode( int code, QFile &outfile )
+{
+ curAccum &= masks[ curBits ];
+
+ if ( curBits > 0 )
+ {
+ curAccum |= (code << curBits);
+ }
+ else
+ {
+ curAccum = code;
+ }
+
+ curBits += nBits;
+
+ while( curBits >= 8 )
+ {
+ writeChar( (Byte)(curAccum & 0xff),outfile );
+ curAccum >>= 8;
+ curBits -= 8;
+ }
+
+ /*
+ * If the next entry is going to be too big for the code size,
+ * then increase it, if possible.
+ */
+ if ( freeEntry > maxCode || clearFlag )
+ {
+ if( clearFlag )
+ {
+ nBits = initBits;
+ maxCode = (1<<nBits)-1;
+ clearFlag = FALSE;
+ }
+ else
+ {
+ ++nBits;
+ if ( nBits == bits )
+ maxCode = maxMaxCode;
+ else
+ maxCode = (1<<nBits)-1;
+ }
+ }
+
+ if ( code == EOFCode )
+ {
+ /* At EOF, write the rest of the buffer. */
+ while( curBits > 0 )
+ {
+ writeChar( (Byte)(curAccum & 0xff), outfile );
+ curAccum >>= 8;
+ curBits -= 8;
+ }
+
+ writePacket(outfile);
+ }
+}
+
+/*
+ * Add a character to the end of the current packet, and if it is 254
+ * characters, flush the packet to disk.
+ */
+void GifEncoder::writeChar( Byte c, QFile &fp )
+{
+ accum[ aCount++ ] = c;
+ if( aCount >= 254 ) writePacket(fp);
+}
+
+/*
+ * Flush the packet to disk, and reset the accumulator
+ */
+void GifEncoder::writePacket(QFile &fp)
+{
+ if ( aCount > 0 )
+ {
+ fp.putch( aCount );
+ fp.writeBlock( (const char *)accum, aCount );
+ aCount = 0;
+ }
+}
+
+void GifEncoder::clearHashTable() /* reset code table */
+{
+ int *htab_p = htab;
+ int i; for (i=0;i<hashTableSize;i++) *htab_p++ = -1;
+}
+
diff --git a/src/gifenc.h b/src/gifenc.h
new file mode 100644
index 0000000..161e032
--- /dev/null
+++ b/src/gifenc.h
@@ -0,0 +1,85 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#ifndef _GIFENC_H
+#define _GIFENC_H
+#include <qfile.h>
+
+typedef unsigned char Byte;
+typedef unsigned short Word;
+
+struct Color
+{
+ Byte red;
+ Byte green;
+ Byte blue;
+};
+
+const int hashTableSize=5003; // size of the hash table
+
+class GifEncoder
+{
+ public:
+ GifEncoder(Byte *rawBytes,Color *p,int w,int h,Byte d,int t);
+ ~GifEncoder();
+ void writeGIF(QFile &fp);
+
+ protected:
+ void putWord( Word w, QFile &fp );
+ void putByte( Byte b, QFile &fp );
+ void compress(int csize, QFile &fp);
+ void writeCode(int code, QFile &fp);
+ void writeChar( Byte c, QFile &fp );
+ void writePacket(QFile &fp);
+ int nextPixel();
+ void clearHashTable();
+
+ private:
+ const int colorResolution; // 8 bit for Red, Green and Blue;
+ const int globalPaletteFlag;
+ const int bits;
+ const int maxMaxCode;
+
+ // image variables
+ int width; // image width
+ int height; // image height
+ Byte depth; // bits per CLUT entry
+ int transIndex; // index of the transparant color; -1 = none
+ Color *palette; // pointer to the color palette
+ int numPixels; // total number of pixel (i.e. width * height)
+ Byte *data; // pointer to the image data (one byte per pixel)
+ Byte *dataPtr; // pointer located at the current pixel.
+
+ // compression variables
+ bool clearFlag; // clear hash table flag
+ int freeEntry; // first free entry in the hash table
+ unsigned int curAccum; // encoded bit accumulator
+ int curBits; // number of bits in curAccum
+ Byte accum[256]; // Buffer for a packet
+ int aCount; // Number of characters so far in this 'packet'
+ int nBits; // number of bits/code
+ int maxCode; // maximum code, given n_bits
+ int initBits; // initial number of bits
+ int EOFCode; // code for signaling the end of the file
+ int ClearCode; // the clear code for the decompressor
+
+ // tables
+ int htab[hashTableSize]; // the hash table
+ Word codetab[hashTableSize]; // the code table
+};
+
+#endif
diff --git a/src/groupdef.cpp b/src/groupdef.cpp
new file mode 100644
index 0000000..6a2d79b
--- /dev/null
+++ b/src/groupdef.cpp
@@ -0,0 +1,158 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#include <ctype.h>
+#include "groupdef.h"
+#include "classdef.h"
+#include "filedef.h"
+#include "classlist.h"
+#include "outputlist.h"
+#include "scanner.h"
+#include "namespacedef.h"
+#include "language.h"
+#include "util.h"
+
+GroupDef::GroupDef(const char *na,const char *t) : Definition(na)
+{
+ fileList = new FileList;
+ classList = new ClassList;
+// groupList = new GroupList;
+// name = n;
+ if (t)
+ title = t;
+ else
+ {
+ title = na;
+ title.at(0)=toupper(title.at(0));
+ }
+ fileName = "group_"+nameToFile(na);
+}
+
+GroupDef::~GroupDef()
+{
+ delete fileList;
+ delete classList;
+// delete groupList;
+}
+
+void GroupDef::addFile(const FileDef *def)
+{
+ fileList->append(def);
+}
+
+void GroupDef::addClass(const ClassDef *def)
+{
+ classList->append(def);
+}
+
+void GroupDef::addNamespace(const NamespaceDef *def)
+{
+ namespaceList->append(def);
+}
+
+//void GroupDef::addGroup(const GroupDef *def)
+//{
+// groupList->append(def);
+//}
+
+int GroupDef::countMembers() const
+{
+ return fileList->count()+classList->count();
+}
+
+void GroupDef::writeDocumentation(OutputList &ol)
+{
+ ol.disable(OutputGenerator::Man);
+ startFile(ol,fileName,title);
+ startTitle(ol);
+ ol.docify(title);
+ endTitle(ol,name());
+
+ //brief=brief.stripWhiteSpace();
+ //int bl=brief.length();
+ OutputList briefOutput(&ol);
+ if (!briefDescription().isEmpty())
+ {
+ parseDoc(briefOutput,name(),0,briefDescription());
+ ol+=briefOutput;
+ ol.writeString(" \n");
+ ol.disable(OutputGenerator::Latex);
+ ol.startTextLink(0,"details");
+ parseDoc(ol,0,0,theTranslator->trMore());
+ ol.enable(OutputGenerator::Latex);
+ }
+ if (fileList->count()>0)
+ {
+ ol.startMemberHeader();
+ parseDoc(ol,0,0,theTranslator->trFiles());
+ ol.endMemberHeader();
+ ol.startIndexList();
+ FileDef *fd=fileList->first();
+ while (fd)
+ {
+ ol.writeStartAnnoItem("file ",fd->diskName(),0,fd->name());
+ ol.writeEndAnnoItem(fd->name());
+ fd=fileList->next();
+ }
+ ol.endIndexList();
+ }
+ if (classList->count()>0)
+ {
+ ol.startMemberHeader();
+ parseDoc(ol,0,0,theTranslator->trCompounds());
+ ol.endMemberHeader();
+ ol.startIndexList();
+ ClassDef *cd=classList->first();
+ while (cd)
+ {
+ QString type;
+ switch (cd->compoundType())
+ {
+ case ClassDef::Class: type="class"; break;
+ case ClassDef::Struct: type="struct"; break;
+ case ClassDef::Union: type="union"; break;
+ }
+ ol.writeStartAnnoItem(type,cd->classFile(),0,cd->name());
+ ol.writeEndAnnoItem(cd->name());
+ cd=classList->next();
+ }
+ ol.endIndexList();
+ }
+ //int dl=doc.length();
+ //doc=doc.stripWhiteSpace();
+ if (!briefDescription().isEmpty() || !documentation().isEmpty())
+ {
+ ol.writeRuler();
+ ol.writeAnchor("details");
+ ol.startGroupHeader();
+ parseDoc(ol,0,0,theTranslator->trDetailedDescription());
+ ol.endGroupHeader();
+ // repeat brief description
+ if (!briefDescription().isEmpty())
+ {
+ ol+=briefOutput;
+ ol.newParagraph();
+ }
+ // write documentation
+ if (!documentation().isEmpty())
+ {
+ parseDoc(ol,name(),0,documentation()+"\n");
+ }
+ }
+
+ endFile(ol);
+ ol.enable(OutputGenerator::Man);
+}
diff --git a/src/groupdef.h b/src/groupdef.h
new file mode 100644
index 0000000..421b701
--- /dev/null
+++ b/src/groupdef.h
@@ -0,0 +1,64 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#ifndef GROUPDEF_H
+#define GROUPDEF_H
+
+#include <qstring.h>
+#include <qlist.h>
+#include "definition.h"
+
+class FileList;
+class ClassList;
+class FileDef;
+class ClassDef;
+class NamespaceDef;
+class GroupList;
+class OutputList;
+class NamespaceList;
+
+class GroupDef : public Definition
+{
+ public:
+ GroupDef(const char *name,const char *title);
+ ~GroupDef();
+ const char *groupFile() const { return fileName; }
+ const char *groupTitle() const { return title; }
+ void addFile(const FileDef *def);
+ void addClass(const ClassDef *def);
+ void addNamespace(const NamespaceDef *def);
+ void writeDocumentation(OutputList &ol);
+ int countMembers() const;
+
+ private:
+ QString title; // title of the group
+ QString fileName; // base name of the generated file
+ FileList *fileList; // list of all files in the group
+ ClassList *classList; // list of all classes in the group
+ NamespaceList *namespaceList; // list of all namespace in the group
+};
+
+class GroupList : public QList<GroupDef>
+{
+};
+
+class GroupListIterator : public QListIterator<GroupDef>
+{
+ public:
+ GroupListIterator(const GroupList &l) : QListIterator<GroupDef>(l) {}
+};
+
+#endif
diff --git a/src/htmlgen.cpp b/src/htmlgen.cpp
new file mode 100644
index 0000000..4ab337f
--- /dev/null
+++ b/src/htmlgen.cpp
@@ -0,0 +1,512 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#include <qdir.h>
+#include <stdlib.h>
+#include "message.h"
+#include "htmlgen.h"
+#include "config.h"
+#include "util.h"
+#include "doxygen.h"
+#include "logos.h"
+#include "diagram.h"
+
+HtmlGenerator::HtmlGenerator() : OutputGenerator()
+{
+ if (headerFile.length()>0) header=fileToString(headerFile);
+ if (footerFile.length()>0) footer=fileToString(footerFile);
+ dir=htmlOutputDir;
+}
+
+HtmlGenerator::~HtmlGenerator()
+{
+}
+
+void HtmlGenerator::append(const OutputGenerator *g)
+{
+ t << g->getContents();
+}
+
+void HtmlGenerator::init()
+{
+ QDir d(htmlOutputDir);
+ if (!d.exists() && !d.mkdir(htmlOutputDir))
+ {
+ err("Could not create output directory %s\n",htmlOutputDir.data());
+ exit(1);
+ }
+ writeLogo(htmlOutputDir);
+}
+
+//void HtmlGenerator::generateExternalIndex()
+//{
+// //printf("Generating external index...\n");
+// QFile f;
+// f.setName(htmlOutputDir+"/header.html");
+// if (f.open(IO_WriteOnly))
+// {
+// QTextStream tt(&f);
+// if (header.length()==0)
+// {
+// tt << "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\">\n"
+// "<html><head><meta name=\"robots\" content=\"noindex\">\n"
+// "<title>Doxysearch</title>\n"
+// "</head><body bgcolor=\"#ffffff\">\n";
+// }
+// else
+// {
+// tt << header;
+// }
+// if (!noIndexFlag)
+// {
+// tt << "<center>";
+// if (documentedGroups>0)
+// tt << "<a doxygen=\"_doc:\" href=\"/modules.html\">Modules</a> &nbsp; ";
+// if (hierarchyClasses>0)
+// tt << "<a doxygen=\"_doc:\" href=\"/hierarchy.html\">Class hierarchy</a> &nbsp; ";
+// if (annotatedClasses>0)
+// tt << "<a doxygen=\"_doc:\" href=\"/annotated.html\">Compound list</a> &nbsp; ";
+// if (documentedFiles>0)
+// tt << "<a doxygen=\"_doc:\" href=\"/files.html\">File list</a> &nbsp; ";
+// if (includeFiles.count()>0)
+// tt << "<a doxygen=\"_doc:\" href=\"/headers.html\">Header files</a> &nbsp; ";
+// if (documentedMembers>0)
+// tt << "<a doxygen=\"_doc:\" href=\"/functions.html\">Compound Members</a> &nbsp; ";
+// if (documentedFunctions>0)
+// tt << "<a doxygen=\"_doc:\" href=\"/globals.html\">File Members</a> &nbsp; ";
+// if (pageList.count()>0)
+// tt << "<a doxygen=\"_doc:\" href=\"/pages.html\">Related Pages</a> &nbsp; ";
+// if (exampleList.count()>0)
+// tt << "<a doxygen=\"_doc:\" href=\"/examples.html\">Examples</a> &nbsp; ";
+// if (searchEngineFlag)
+// tt << "<a doxygen=\"_cgi:\" href=\"\">Search</a>";
+// tt << endl << "</center><hr>" << endl;
+// }
+// }
+// f.close();
+//
+// f.setName(htmlOutputDir+"/footer.html");
+// if (f.open(IO_WriteOnly))
+// {
+// QTextStream tt(&f);
+// if (footer.length()==0)
+// {
+// tt << "<hr><address><small>Generated at " << dateToString(TRUE);
+// if (projectName.length()>0) tt << " for " << projectName;
+// tt << " by <a href=\"http://www.stack.nl/~dimitri/doxygen/index.html\">"
+// "doxygen</a>&nbsp; written by <a href="
+// "\"mailto:dimitri@stack.nl\">Dimitri van Heesch</a>, &copy; "
+// "1997-1999</small></address>\n</body>\n</html>\n";
+// }
+// else
+// {
+// tt << footer;
+// }
+// }
+// f.close();
+//}
+
+void HtmlGenerator::startFile(const char *name,const char *title,bool external)
+{
+ QString fileName=name;
+ if (fileName.right(5)!=".html") fileName+=".html";
+ startPlainFile(fileName);
+ if (header.length()==0)
+ {
+ t << "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\">\n"
+ "<html><head><meta name=\"robots\" content=\"noindex\">\n"
+ "<title>" << title << "</title>\n";
+ t << "<link ";
+ if (external)
+ t << "doxygen=\"_doc:\" href=\"/";
+ else
+ t << "href=\"";
+ t << "doxygen.css\" rel=\"stylesheet\" type=\"text/css\">\n"
+ "</head><body bgcolor=\"#ffffff\">\n";
+ }
+ else
+ {
+ t << header;
+ }
+
+// if (!noIndexFlag)
+// {
+// t << "<center>";
+// if (documentedGroups>0)
+// t << "<a href=\"modules.html\">Modules</a> &nbsp; ";
+// if (hierarchyClasses>0)
+// t << "<a href=\"hierarchy.html\">Class hierarchy</a> &nbsp; ";
+// if (annotatedClasses>0)
+// t << "<a href=\"annotated.html\">Compound list</a> &nbsp; ";
+// if (documentedFiles>0)
+// t << "<a href=\"files.html\">File list</a> &nbsp; ";
+// if (includeFiles.count()>0)
+// t << "<a href=\"headers.html\">Header files</a> &nbsp; ";
+// if (documentedMembers>0)
+// t << "<a href=\"functions.html\">Compound Members</a> &nbsp; ";
+// if (documentedFunctions>0)
+// t << "<a href=\"globals.html\">File Members</a> &nbsp; ";
+// if (pageList.count()>0)
+// t << "<a href=\"pages.html\">Related Pages</a> &nbsp; ";
+// if (exampleList.count()>0)
+// t << "<a href=\"examples.html\">Examples</a> &nbsp; ";
+// if (searchEngineFlag)
+// t << "<a doxygen=\"_cgi:\" href=\"\">Search</a>";
+// t << endl << "</center><hr>" << endl;
+// }
+}
+
+void HtmlGenerator::startQuickIndexItem(const char *s,const char *l)
+{
+ t << "<a ";
+ if (s) t << "doxygen=\"" << s << "\" ";
+ t << "href=\"" << l << "\">";
+}
+
+void HtmlGenerator::endQuickIndexItem()
+{
+ t << "</a> &nbsp; ";
+}
+
+void HtmlGenerator::writeFooter(int part,bool external)
+{
+ switch (part)
+ {
+ case 0:
+ if (footer.length()==0)
+ t << "<hr><address><small>";
+ else
+ t << footer;
+ break;
+ case 1:
+ if (footer.length()==0)
+ {
+ t << " <a href=\"http://www.stack.nl/~dimitri/doxygen/index.html\">";
+ t << "<img ";
+ if (external)
+ {
+ t << "doxygen=\"_doc:\" src=\"/";
+ }
+ else
+ {
+ t << "src=\"";
+ }
+ t << "doxygen.gif\" alt=\"doxygen\" align=center border=0 "
+ "width=118 height=53></a>&nbsp; ";
+ }
+ break;
+ default:
+ if (footer.length()==0)
+ t << " <a href=\"mailto:dimitri@stack.nl\">Dimitri van Heesch</a>, &copy; "
+ "1997-1999</small></address>\n</body>\n</html>\n";
+ break;
+
+ }
+}
+
+void HtmlGenerator::endFile()
+{
+// if (footer.length()==0)
+// {
+// t << "<hr><address><small>Generated at " << dateToString(TRUE);
+// if (projectName.length()>0)
+// {
+// t << " for ";
+// docify(projectName);
+// }
+// t << " by <a href=\"http://www.stack.nl/~dimitri/doxygen/index.html\">"
+// "<img src=\"doxygen.gif\" alt=\"doxygen\" align=center border=0 "
+// "width=118 height=53></a>&nbsp; written by <a href="
+// "\"mailto:dimitri@stack.nl\">Dimitri van Heesch</a>, &copy; "
+// "1997-1999</small></address>\n</body>\n</html>\n";
+// }
+// else
+// {
+// t << footer;
+// }
+ endPlainFile();
+}
+
+void HtmlGenerator::startProjectNumber()
+{
+ t << "<h3 align=center>";
+}
+
+void HtmlGenerator::endProjectNumber()
+{
+ t << "</h3>";
+}
+
+//void HtmlGenerator::writeIndex()
+//{
+// startFile("index.html","Main Index");
+// t << "<h1 align=center>";
+// docify(projectName);
+// t << " Documentation</h1>"
+// << "<p>" << endl << "<p>" << endl;
+// if (!projectNumber.isEmpty())
+// {
+// t << "<h3 align=center>";
+// docify(projectNumber);
+// t << "</h3>\n<p>\n<p>\n";
+// }
+// if (noIndexFlag)
+// {
+// t << "<ul>" << endl;
+// if (hierarchyClasses>0)
+// t << "<li><a href=\"hierarchy.html\">Class hierarchy</a>" << endl;
+// if (annotatedClasses>0)
+// t << "<li><a href=\"annotated.html\">Compound list</a>" << endl;
+// if (documentedFiles>0)
+// t << "<li><a href=\"files.html\">File list</a>" << endl;
+// if (includeFiles.count()>0)
+// t << "<li><a href=\"headers.html\">Header files</a>" << endl;
+// if (documentedMembers>0)
+// t << "<li><a href=\"functions.html\">Compound Members</a>" << endl;
+// if (documentedFunctions>0)
+// t << "<li><a href=\"globals.html\">File Members</a>" << endl;
+// if (pageList.count()>0)
+// t << "<li><a href=\"pageList.html\">Related Pages</a>" << endl;
+// if (exampleList.count()>0)
+// t << "<li><a href=\"examples.html\">Examples</a>" << endl;
+// if (searchEngineFlag)
+// t << "<li><a doxygen=\"_cgi:\" href=\"\">Search</a>" << endl;
+// t << "</ul>" << endl;
+// }
+// endFile();
+//}
+
+void HtmlGenerator::writeStyleInfo(int part)
+{
+ if (part==0)
+ {
+ startPlainFile("doxygen.css");
+ t << "H1 { border-width: thin; border: solid; text-align: center }" << endl
+ << "A.el { text-decoration: none; font-weight: bold }" << endl
+ << "DL.el { margin-left: -1cm }" << endl
+ << "DIV.fragment { width: 100%; border: none; background-color: #eeeeee }" << endl
+ << "DIV.in { margin-left: 16 }" << endl
+ << endl;
+ endPlainFile();
+ }
+}
+
+void HtmlGenerator::writeDoxyAnchor(const char *,const char *anchor, const char *name)
+{
+ t << "<a name=\"" << anchor << "\" doxytag=\"" << name << "\"></a>";
+}
+
+void HtmlGenerator::newParagraph()
+{
+ t << endl << "<p>" << endl;
+}
+
+void HtmlGenerator::writeString(const char *text)
+{
+ t << text;
+}
+
+void HtmlGenerator::writeIndexItem(const char *ref,const char *f,
+ const char *name)
+{
+ t << "<li>";
+ if (ref || f)
+ {
+ t << "<a class=\"el\" ";
+ if (ref) t << "doxygen=\"" << ref << ":\" ";
+ t << "href=\"";
+ if (f) t << f << ".html\">";
+ }
+ else
+ {
+ t << "<b>";
+ }
+ docify(name);
+ if (ref || f)
+ {
+ t << "</a>" << endl;
+ }
+ else
+ {
+ t << "</b>";
+ }
+}
+
+void HtmlGenerator::writeStartAnnoItem(const char *,const char *f,
+ const char *path,const char *name)
+{
+ t << "<li>";
+ if (path) docify(path);
+ t << "<a class=\"el\" href=\"" << f << ".html\">";
+ docify(name);
+ t << "</a> ";
+}
+
+void HtmlGenerator::writeObjectLink(const char *ref,const char *f,
+ const char *anchor, const char *name)
+{
+ t << "<a class=\"el\" ";
+ if (ref) t << "doxygen=\"" << ref << ":\" ";
+ t << "href=\"";
+ if (f) t << f << ".html";
+ if (anchor) t << "#" << anchor;
+ t << "\">";
+ docify(name);
+ t << "</a>";
+}
+
+void HtmlGenerator::startTextLink(const char *f,const char *anchor)
+{
+ t << "<a href=\"";
+ if (f) t << f << ".html";
+ if (anchor) t << "#" << anchor;
+ t << "\">";
+}
+
+void HtmlGenerator::endTextLink()
+{
+ t << "</a>";
+}
+
+void HtmlGenerator::writeHtmlLink(const char *url,const char *text)
+{
+ t << "<a href=\"";
+ if (url) t << url;
+ t << "\">";
+ docify(text);
+ t << "</a>";
+}
+
+void HtmlGenerator::startGroupHeader()
+{
+ t << "<h2>";
+}
+
+void HtmlGenerator::endGroupHeader()
+{
+ t << "</h2>" << endl;
+}
+
+void HtmlGenerator::writeSection(const char *lab,const char *title,bool sub)
+{
+ t << "<a name=\"" << lab << "\">";
+ if (sub) t << "<h3>"; else t << "<h2>";
+ docify(title);
+ if (sub) t << "</h3>"; else t << "</h2>";
+ t << "</a>" << endl;
+}
+
+void HtmlGenerator::writeSectionRef(const char *name,const char *lab,
+ const char *title)
+{
+ QString refName=name;
+ if (refName.right(5)!=".html") refName+=".html";
+ t << "&quot;<a href=\"" << refName << "#" << lab << "\">";
+ docify(title);
+ t << "</a>&quot;";
+}
+
+void HtmlGenerator::writeSectionRefItem(const char *name,const char *lab,
+ const char *title)
+{
+ QString refName=name;
+ if (refName.right(5)!=".html") refName+=".html";
+ t << "<a href=\"" << refName << "#" << lab << "\">";
+ docify(title);
+ t << "</a>";
+}
+
+//void HtmlGenerator::docify(const char *str)
+//{
+// docifyStatic(t,str);
+//}
+
+//void HtmlGenerator::docifyStatic(QTextStream &t,const char *str)
+void HtmlGenerator::docify(const char *str)
+{
+ if (str)
+ {
+ const char *p=str;
+ char c;
+ while (*p)
+ {
+ c=*p++;
+ switch(c)
+ {
+ case '<': t << "&lt;"; break;
+ case '>': t << "&gt;"; break;
+ case '&': t << "&amp;"; break;
+ case '\\':
+ if (*p=='<')
+ { t << "&lt;"; p++; }
+ else if (*p=='>')
+ { t << "&gt;"; p++; }
+ else
+ t << "\\";
+ break;
+ default: t << c;
+ }
+ }
+ }
+}
+
+void HtmlGenerator::codify(const char *str)
+{
+ docify(str);
+}
+
+void HtmlGenerator::writeChar(char c)
+{
+ char cs[2];
+ cs[0]=c;
+ cs[1]=0;
+ docify(cs);
+}
+
+void HtmlGenerator::startClassDiagram()
+{
+ t << "<p>";
+}
+
+void HtmlGenerator::endClassDiagram(ClassDiagram &d,
+ const char *fileName,const char *name)
+{
+ t << ":\n<p><center><img src=\""
+ << fileName << ".gif\" usemap=\"#" << name << "_map\""
+ << " border=\"0\"></center>" << endl
+ << "<map name=\"" << name << "_map\"><p>" << endl;
+
+ d.writeImageMap(t,dir,fileName);
+}
+
+void HtmlGenerator::startColorFont(uchar red,uchar green,uchar blue)
+{
+ QString colorString;
+ colorString.sprintf("%02x%02x%02x",red,green,blue);
+ t << "<font color=\"#" << colorString << "\">";
+}
+
+void HtmlGenerator::endColorFont()
+{
+ t << "</font>";
+}
+
+void HtmlGenerator::writeFormula(const char *n,const char *text)
+{
+ if (text && text[0]=='\\') t << "<p><center>" << endl;
+ t << "<img align=\"top\" src=\"" << n << "\">" << endl;
+ if (text && text[0]=='\\') t << "</center></p>" << endl;
+}
diff --git a/src/htmlgen.h b/src/htmlgen.h
new file mode 100644
index 0000000..c8a5223
--- /dev/null
+++ b/src/htmlgen.h
@@ -0,0 +1,174 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#ifndef HTMLGEN_H
+#define HTMLGEN_H
+
+#include "outputgen.h"
+
+class QFile;
+
+class HtmlGenerator : public OutputGenerator
+{
+ public:
+ HtmlGenerator();
+ ~HtmlGenerator();
+
+ OutputGenerator *copy() { return new HtmlGenerator; }
+ //OutputGenerator *clone() { return new HtmlGenerator(*this); }
+ void append(const OutputGenerator *o);
+ void enable() { active=TRUE; }
+ void disable() { active=FALSE; }
+ void enableIf(OutputType o) { if (o==Html) active=TRUE; }
+ void disableIf(OutputType o) { if (o==Html) active=FALSE; }
+ void disableIfNot(OutputType o) { if (o!=Html) active=FALSE; }
+ bool isEnabled(OutputType o) { return (o==Html && active); }
+ OutputGenerator *get(OutputType o) { return (o==Html) ? this : 0; }
+
+ static void init();
+ //void generateExternalIndex();
+ void startFile(const char *name,const char *title,bool external);
+ void writeFooter(int,bool);
+ void endFile();
+ void clearBuffer();
+
+ //void writeIndex();
+ void startIndexSection(IndexSections) {}
+ void endIndexSection(IndexSections) {}
+ void startProjectNumber();
+ void endProjectNumber();
+ void writeStyleInfo(int part);
+ void startTitleHead() { startTitle(); }
+ void endTitleHead(const char *) { endTitle(); }
+ void startTitle() { t << "<h1>"; }
+ void endTitle() { t << "</h1>"; }
+
+ void newParagraph();
+ void writeString(const char *text);
+ void startIndexList() { t << "<ul>" << endl; }
+ void endIndexList() { t << "</ul>" << endl; }
+ void startItemList() { t << "<ul>" << endl; }
+ void endItemList() { t << "</ul>" << endl; }
+ void startEnumList() { t << "<ol>" << endl; }
+ void endEnumList() { t << "</ol>" << endl; }
+ void writeIndexItem(const char *ref,const char *file,const char *name);
+ void docify(const char *text);
+ void codify(const char *text);
+ void writeObjectLink(const char *ref,const char *file,
+ const char *anchor,const char *name);
+ void writeCodeLink(const char *ref,const char *f,
+ const char *anchor,const char *name)
+ { writeObjectLink(ref,f,anchor,name); }
+ void startTextLink(const char *file,const char *anchor);
+ void endTextLink();
+ void writeHtmlLink(const char *url,const char *text);
+ void startTypewriter() { t << "<code>"; }
+ void endTypewriter() { t << "</code>"; }
+ void startGroupHeader();
+ void endGroupHeader();
+ void writeListItem() { t << "<li>"; }
+
+ void startMemberHeader() { startGroupHeader(); }
+ void endMemberHeader() { endGroupHeader(); }
+ void startMemberList() { t << "<ul>" << endl; }
+ void endMemberList() { t << "</ul>" << endl; }
+ void startMemberItem() { t << "<li>"; }
+ void endMemberItem() { t << endl; }
+
+ void writeRuler() { t << "<hr>"; }
+ void writeAnchor(const char *name)
+ { t << "<a name=\"" << name <<"\"></a>"; }
+ void startCodeFragment() { t << "<div class=\"fragment\"><pre>"; }
+ void endCodeFragment() { t << "</div></pre>"; }
+ void writeBoldString(const char *text)
+ { t << "<b>"; docify(text); t << "</b>"; }
+ void startEmphasis() { t << "<em>"; }
+ void endEmphasis() { t << "</em>"; }
+ void startBold() { t << "<b>"; }
+ void endBold() { t << "</b>"; }
+ void startDescription() { t << endl << "<dl compact>" << endl; }
+ void endDescription() { t << endl << "</dl>" << endl; }
+ void startDescItem() { t << "<dt>"; }
+ void endDescItem() { t << "<dd>"; }
+ void lineBreak() { t << "<br>" << endl; }
+ void writeChar(char c);
+ void startMemberDoc(const char *,const char *,const char *)
+ { t << endl << "<h3>"; }
+ void endMemberDoc() { t << "</h3>" << endl; }
+ void writeDoxyAnchor(const char *clName,const char *anchor,
+ const char *name);
+ void writeLatexSpacing() {}
+ void writeStartAnnoItem(const char *type,const char *file,
+ const char *path,const char *name);
+ void writeEndAnnoItem(const char *) { t << endl; }
+ void startSubsection() { t << "<h2>"; }
+ void endSubsection() { t << "</h2>" << endl; }
+ void startSubsubsection() { t << "<h3>"; }
+ void endSubsubsection() { t << "</h3>" << endl; }
+ void startCenter() { t << "<center>" << endl; }
+ void endCenter() { t << "</center>" << endl; }
+ void startSmall() { t << "<small>" << endl; }
+ void endSmall() { t << "</small>" << endl; }
+ void startSubscript() { t << "<sub>"; }
+ void endSubscript() { t << "</sub>"; }
+ void startSuperscript() { t << "<sup>"; }
+ void endSuperscript() { t << "</sup>"; }
+ void startTable(int) { t << "<table border=1 cellspacing=3 cellpadding=3>"; }
+ void endTable() { t << "</table>" << endl; }
+ void nextTableRow() { t << endl << "<tr><td>"; }
+ void endTableRow() { t << "</tr>" << endl; }
+ void nextTableColumn() { t << "<td>"; }
+ void endTableColumn() { t << "</td>"; }
+ void writeCopyright() { t << "&copy;"; }
+ void writeQuote() { t << "&quot;"; }
+ void writeUmlaut(char c) { t << "&" << c << "uml;"; }
+ void writeAcute(char c) { t << "&" << c << "acute;"; }
+ void writeGrave(char c) { t << "&" << c << "grave;"; }
+ void writeCirc(char c) { t << "&" << c << "circ;"; }
+ void writeTilde(char c) { t << "&" << c << "tilde;"; }
+ void startMemberDescription() { t << "<dl class=\"el\"><dd><font size=-1><em>"; }
+ void endMemberDescription() { t << "</em></font></dl>"; }
+ void startDescList() { t << "<dl compact><dt>" << endl; }
+ void endDescTitle() {}
+ void writeDescItem() { t << "<dd>" << endl; }
+ void endDescList() { t << "</dl>"; }
+ void writeSection(const char *,const char *,bool);
+ void writeSectionRef(const char *,const char *,const char *);
+ void writeSectionRefItem(const char *,const char *,const char *);
+ void addToIndex(const char *,const char *) {}
+ void startIndent() { t << "<div class=\"in\">" << endl; }
+ void endIndent() { t << "</div>" << endl; }
+ void writeSynopsis() {}
+ void startClassDiagram();
+ void endClassDiagram(ClassDiagram &,const char *,const char *);
+ void startColorFont(uchar r,uchar g,uchar b);
+ void endColorFont();
+ void writePageRef(const char *,const char *) {}
+ void startQuickIndexItem(const char *,const char *);
+ void endQuickIndexItem();
+ void writeFormula(const char *,const char *);
+
+ //static void docifyStatic(QTextStream &t,const char *str);
+
+ private:
+ QString header;
+ QString footer;
+
+ HtmlGenerator &operator=(const HtmlGenerator &g);
+ HtmlGenerator(const HtmlGenerator &g);
+};
+
+#endif
diff --git a/src/image.cpp b/src/image.cpp
new file mode 100644
index 0000000..853d4ea
--- /dev/null
+++ b/src/image.cpp
@@ -0,0 +1,443 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#include "image.h"
+#include "gifenc.h"
+#include <qglobal.h>
+#include <qstring.h>
+
+const int charSetWidth=80;
+const int charHeight=12;
+const int numChars=96;
+
+unsigned short charPos[numChars] =
+ {
+ 0, 5, 8, 13, 20, 27, 38, 47,
+ 50, 54, 58, 65, 72, 76, 83, 87,
+ 91, 98,105,112,119,126,133,140,
+ 147,154,161,164,167,174,181,188,
+ 195,207,216,224,233,242,250,258,
+ 267,276,279,286,294,301,312,321,
+ 331,339,349,357,365,372,380,389,
+ 400,409,418,427,430,434,437,443,
+ 450,453,460,467,474,481,488,492,
+ 499,506,509,512,518,521,530,537,
+ 544,551,557,562,568,571,578,585,
+ 594,600,607,613,617,620,624,631
+ };
+
+unsigned char charWidth[numChars] =
+ {
+ 5, 3, 5, 7, 7,11, 9, 3,
+ 4, 4, 7, 7, 4, 7, 4, 4,
+
+ 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 3, 3, 7, 7, 7, 7,
+ 12, 9, 8, 9, 9, 8, 8, 9,
+ 9, 3, 7, 8, 7,11, 9,10,
+ 8,10, 8, 8, 7, 8, 9,11,
+ 9, 9, 9, 3, 4, 3, 6, 7,
+ 3, 7, 7, 7, 7, 7, 4, 7,
+ 7, 3, 3, 6, 3, 9, 7, 7,
+ 7, 6, 5, 6, 3, 7, 7, 9,
+ 6, 7, 6, 4, 3, 4, 7, 5
+ };
+
+unsigned char fontRaw[charSetWidth*charHeight] = {
+ 0x02, 0x50, 0x01, 0x06, 0x20, 0x60, 0xc6, 0x04, 0x00, 0x00, 0x00, 0x27,
+ 0x04, 0x1c, 0x38, 0x11, 0xf1, 0xc7, 0xc7, 0x0e, 0x00, 0x00, 0x00, 0x03,
+ 0x81, 0xf0, 0x10, 0x7c, 0x1e, 0x3e, 0x1f, 0x9f, 0x87, 0x88, 0x24, 0x09,
+ 0x09, 0x02, 0x02, 0x41, 0x0f, 0x0f, 0x83, 0xc3, 0xe1, 0xe7, 0xf4, 0x24,
+ 0x12, 0x22, 0x41, 0x20, 0x9f, 0xce, 0x30, 0x00, 0x10, 0x04, 0x00, 0x01,
+ 0x00, 0x30, 0x08, 0x12, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0xac, 0x00, 0x00, 0x02, 0x51, 0x43, 0x89,
+ 0x40, 0x90, 0x49, 0x15, 0x00, 0x00, 0x00, 0x28, 0x9c, 0x22, 0x44, 0x31,
+ 0x02, 0x20, 0x48, 0x91, 0x00, 0x00, 0x00, 0x04, 0x46, 0x08, 0x28, 0x42,
+ 0x21, 0x21, 0x10, 0x10, 0x08, 0x48, 0x24, 0x09, 0x11, 0x03, 0x06, 0x61,
+ 0x10, 0x88, 0x44, 0x22, 0x12, 0x10, 0x84, 0x24, 0x12, 0x22, 0x22, 0x20,
+ 0x80, 0x4a, 0x11, 0x00, 0x20, 0x04, 0x00, 0x01, 0x00, 0x40, 0x08, 0x00,
+ 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00,
+ 0x02, 0x22, 0x00, 0x00, 0x02, 0x51, 0x45, 0x49, 0x40, 0x90, 0x89, 0x0a,
+ 0x00, 0x00, 0x00, 0x48, 0x84, 0x02, 0x04, 0x51, 0x02, 0x00, 0x88, 0x91,
+ 0x00, 0x00, 0x00, 0x04, 0x44, 0xd4, 0x28, 0x42, 0x40, 0x20, 0x90, 0x10,
+ 0x10, 0x08, 0x24, 0x09, 0x21, 0x03, 0x06, 0x51, 0x20, 0x48, 0x48, 0x12,
+ 0x12, 0x00, 0x84, 0x22, 0x22, 0x22, 0x22, 0x11, 0x00, 0x89, 0x12, 0x80,
+ 0x31, 0xc5, 0x87, 0x0d, 0x1c, 0xe3, 0x4b, 0x12, 0x49, 0x29, 0x16, 0x1c,
+ 0x58, 0x69, 0x4c, 0xe8, 0x91, 0x44, 0x61, 0x44, 0xf2, 0x22, 0x00, 0x00,
+ 0x02, 0x07, 0xe5, 0x06, 0x80, 0x60, 0x10, 0x95, 0x08, 0x00, 0x00, 0x48,
+ 0x84, 0x04, 0x18, 0x51, 0xe2, 0xc0, 0x87, 0x11, 0x24, 0x18, 0x03, 0x00,
+ 0x89, 0x24, 0x44, 0x42, 0x40, 0x20, 0x90, 0x10, 0x10, 0x08, 0x24, 0x09,
+ 0x41, 0x02, 0x8a, 0x51, 0x20, 0x48, 0x48, 0x12, 0x11, 0x80, 0x84, 0x22,
+ 0x21, 0x24, 0x14, 0x11, 0x01, 0x09, 0x14, 0x40, 0x02, 0x26, 0x48, 0x93,
+ 0x22, 0x44, 0xcc, 0x92, 0x51, 0x36, 0x99, 0x22, 0x64, 0x99, 0x92, 0x48,
+ 0x91, 0x44, 0x52, 0x44, 0x12, 0x22, 0x00, 0x00, 0x02, 0x01, 0x43, 0x80,
+ 0x80, 0xa0, 0x10, 0x84, 0x08, 0x00, 0x00, 0x88, 0x84, 0x08, 0x04, 0x90,
+ 0x13, 0x21, 0x08, 0x8f, 0x00, 0x61, 0xf0, 0xc0, 0x8a, 0x24, 0x44, 0x7c,
+ 0x40, 0x20, 0x9f, 0x9f, 0x11, 0xcf, 0xe4, 0x09, 0xc1, 0x02, 0x8a, 0x49,
+ 0x20, 0x4f, 0x88, 0x13, 0xe0, 0x60, 0x84, 0x22, 0x21, 0x54, 0x08, 0x0a,
+ 0x02, 0x08, 0x90, 0x00, 0x00, 0x24, 0x48, 0x11, 0x22, 0x44, 0x48, 0x92,
+ 0x61, 0x24, 0x91, 0x22, 0x44, 0x89, 0x10, 0x48, 0x91, 0x24, 0x8c, 0x44,
+ 0x22, 0x22, 0x64, 0x00, 0x02, 0x07, 0xe1, 0x41, 0x31, 0x14, 0x10, 0x80,
+ 0x3e, 0x07, 0xc0, 0x88, 0x84, 0x10, 0x05, 0x10, 0x12, 0x21, 0x08, 0x81,
+ 0x01, 0x80, 0x00, 0x31, 0x0a, 0x24, 0x7c, 0x42, 0x40, 0x20, 0x90, 0x10,
+ 0x10, 0x48, 0x24, 0x09, 0x21, 0x02, 0x52, 0x45, 0x20, 0x48, 0x08, 0x92,
+ 0x20, 0x10, 0x84, 0x21, 0x41, 0x54, 0x14, 0x04, 0x04, 0x08, 0x90, 0x00,
+ 0x01, 0xe4, 0x48, 0x11, 0x3e, 0x44, 0x48, 0x92, 0x61, 0x24, 0x91, 0x22,
+ 0x44, 0x89, 0x0c, 0x48, 0x8a, 0x24, 0x8c, 0x48, 0x44, 0x21, 0x98, 0x00,
+ 0x02, 0x02, 0x85, 0x41, 0x49, 0x08, 0x10, 0x80, 0x08, 0x00, 0x00, 0x88,
+ 0x84, 0x20, 0x45, 0xf9, 0x12, 0x21, 0x08, 0x81, 0x00, 0x61, 0xf0, 0xc1,
+ 0x0a, 0x68, 0x82, 0x42, 0x40, 0x20, 0x90, 0x10, 0x10, 0x48, 0x24, 0x89,
+ 0x11, 0x02, 0x52, 0x45, 0x20, 0x48, 0x08, 0x52, 0x12, 0x10, 0x84, 0x21,
+ 0x40, 0x88, 0x22, 0x04, 0x08, 0x08, 0x90, 0x00, 0x02, 0x24, 0x48, 0x11,
+ 0x20, 0x44, 0x48, 0x92, 0x51, 0x24, 0x91, 0x22, 0x44, 0x89, 0x02, 0x48,
+ 0x8a, 0x2a, 0x92, 0x28, 0x42, 0x22, 0x00, 0x00, 0x00, 0x02, 0x85, 0x41,
+ 0x49, 0x18, 0x10, 0x80, 0x08, 0x00, 0x01, 0x08, 0x84, 0x20, 0x44, 0x11,
+ 0x12, 0x22, 0x08, 0x91, 0x00, 0x18, 0x03, 0x00, 0x09, 0xb0, 0x82, 0x42,
+ 0x21, 0x21, 0x10, 0x10, 0x08, 0xc8, 0x24, 0x89, 0x09, 0x02, 0x22, 0x43,
+ 0x10, 0x88, 0x04, 0x22, 0x12, 0x10, 0x84, 0x20, 0x80, 0x88, 0x22, 0x04,
+ 0x10, 0x08, 0x50, 0x00, 0x02, 0x26, 0x48, 0x93, 0x22, 0x44, 0xc8, 0x92,
+ 0x49, 0x24, 0x91, 0x22, 0x64, 0x99, 0x12, 0x49, 0x84, 0x11, 0x21, 0x28,
+ 0x82, 0x22, 0x00, 0x00, 0x02, 0x02, 0x83, 0x82, 0x30, 0xe4, 0x10, 0x80,
+ 0x00, 0x20, 0x05, 0x07, 0x04, 0x3e, 0x38, 0x10, 0xe1, 0xc2, 0x07, 0x0e,
+ 0x24, 0x00, 0x00, 0x01, 0x04, 0x00, 0x82, 0x7c, 0x1e, 0x3e, 0x1f, 0x90,
+ 0x07, 0x48, 0x24, 0x71, 0x05, 0xf2, 0x22, 0x41, 0x0f, 0x08, 0x03, 0xd2,
+ 0x11, 0xe0, 0x83, 0xc0, 0x80, 0x88, 0x41, 0x04, 0x1f, 0xc8, 0x50, 0x00,
+ 0x01, 0xd5, 0x87, 0x0d, 0x1c, 0x43, 0x48, 0x92, 0x45, 0x24, 0x91, 0x1c,
+ 0x58, 0x69, 0x0c, 0x66, 0x84, 0x11, 0x21, 0x10, 0xf2, 0x22, 0x00, 0x00,
+ 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x20, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x03, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x40, 0x02, 0x00, 0x00, 0x00, 0x00, 0x40, 0x08, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x10, 0x02, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x09, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x08, 0x10, 0x1f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x04, 0x40, 0x02,
+ 0x00, 0x00, 0x00, 0x00, 0x40, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20,
+ 0x02, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x30, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x80, 0x04, 0x00, 0x00, 0x00, 0x00,
+ 0x40, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x01, 0xac, 0x00, 0x00
+};
+
+
+#if 0
+const int charSetWidth=68;
+const int charHeight=12;
+const int numChars=80;
+
+unsigned short charPos[numChars] =
+ { 0, 7, 14, 21, 28, 35, 42, 49,
+ 56, 63, 70, 73, 76, 83, 90, 97,
+ 104,116,125,133,142,151,159,167,
+ 176,185,188,195,203,210,221,230,
+ 240,248,258,266,274,281,289,298,
+ 309,318,327,336,339,343,346,352,
+ 359,362,369,376,383,390,397,401,
+ 407,414,417,420,426,429,438,445,
+ 452,459,465,470,476,479,486,493,
+ 502,508,515,521,525,528,532,539
+ };
+
+unsigned char charWidth[numChars] =
+ {
+ 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 3, 3, 7, 7, 7, 7,
+ 12, 9, 8, 9, 9, 8, 8, 9,
+ 9, 3, 7, 8, 7,11, 9,10,
+ 8,10, 8, 8, 7, 8, 9,11,
+ 9, 9, 9, 3, 4, 3, 6, 7,
+ 3, 7, 7, 7, 7, 7, 4, 6,
+ 7, 3, 3, 6, 3, 9, 7, 7,
+ 7, 6, 5, 6, 3, 7, 7, 9,
+ 6, 7, 6, 4, 3, 4, 7, 5
+ };
+
+unsigned char fontRaw[charSetWidth*charHeight] = {
+ 0x38, 0x20, 0xe1, 0xc0, 0x8f, 0x8e, 0x3e, 0x38, 0x70, 0x00, 0x00, 0x00,
+ 0x1c, 0x0f, 0x80, 0x83, 0xe0, 0xf1, 0xf0, 0xfc, 0xfc, 0x3c, 0x41, 0x20,
+ 0x48, 0x48, 0x10, 0x12, 0x08, 0x78, 0x7c, 0x1e, 0x1f, 0x0f, 0x3f, 0xa1,
+ 0x20, 0x91, 0x12, 0x09, 0x04, 0xfe, 0x71, 0x80, 0x00, 0x80, 0x20, 0x00,
+ 0x08, 0x01, 0x80, 0x81, 0x24, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x1a, 0xc0, 0x00, 0x44, 0xe1, 0x12, 0x21,
+ 0x88, 0x11, 0x02, 0x44, 0x88, 0x00, 0x00, 0x00, 0x22, 0x30, 0x41, 0x42,
+ 0x11, 0x09, 0x08, 0x80, 0x80, 0x42, 0x41, 0x20, 0x48, 0x88, 0x18, 0x33,
+ 0x08, 0x84, 0x42, 0x21, 0x10, 0x90, 0x84, 0x21, 0x20, 0x91, 0x11, 0x11,
+ 0x04, 0x02, 0x50, 0x88, 0x01, 0x00, 0x20, 0x00, 0x08, 0x02, 0x00, 0x80,
+ 0x04, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x22, 0x20, 0x00, 0x44, 0x20, 0x10, 0x22, 0x88, 0x10, 0x04, 0x44,
+ 0x88, 0x00, 0x00, 0x00, 0x22, 0x26, 0xa1, 0x42, 0x12, 0x01, 0x04, 0x80,
+ 0x80, 0x80, 0x41, 0x20, 0x49, 0x08, 0x18, 0x32, 0x89, 0x02, 0x42, 0x40,
+ 0x90, 0x90, 0x04, 0x21, 0x11, 0x11, 0x11, 0x10, 0x88, 0x04, 0x48, 0x94,
+ 0x01, 0x8e, 0x2c, 0x38, 0x68, 0xe7, 0x34, 0xb1, 0x24, 0x92, 0x91, 0x61,
+ 0xc5, 0x86, 0x94, 0xce, 0x89, 0x14, 0x46, 0x14, 0x4f, 0x22, 0x20, 0x00,
+ 0x44, 0x20, 0x20, 0xc2, 0x8f, 0x16, 0x04, 0x38, 0x89, 0x20, 0xc0, 0x18,
+ 0x04, 0x49, 0x22, 0x22, 0x12, 0x01, 0x04, 0x80, 0x80, 0x80, 0x41, 0x20,
+ 0x4a, 0x08, 0x14, 0x52, 0x89, 0x02, 0x42, 0x40, 0x90, 0x8c, 0x04, 0x21,
+ 0x11, 0x09, 0x20, 0xa0, 0x88, 0x08, 0x48, 0xa2, 0x00, 0x11, 0x32, 0x44,
+ 0x99, 0x12, 0x4c, 0xc9, 0x25, 0x13, 0x69, 0x92, 0x26, 0x49, 0x99, 0x24,
+ 0x89, 0x14, 0x45, 0x24, 0x41, 0x22, 0x20, 0x00, 0x44, 0x20, 0x40, 0x24,
+ 0x80, 0x99, 0x08, 0x44, 0x78, 0x03, 0x0f, 0x86, 0x04, 0x51, 0x22, 0x23,
+ 0xe2, 0x01, 0x04, 0xfc, 0xf8, 0x8e, 0x7f, 0x20, 0x4e, 0x08, 0x14, 0x52,
+ 0x49, 0x02, 0x7c, 0x40, 0x9f, 0x03, 0x04, 0x21, 0x11, 0x0a, 0xa0, 0x40,
+ 0x50, 0x10, 0x44, 0x80, 0x00, 0x01, 0x22, 0x40, 0x89, 0x12, 0x44, 0x89,
+ 0x26, 0x12, 0x49, 0x12, 0x24, 0x48, 0x91, 0x04, 0x89, 0x12, 0x48, 0xc4,
+ 0x42, 0x22, 0x26, 0x40, 0x44, 0x20, 0x80, 0x28, 0x80, 0x91, 0x08, 0x44,
+ 0x08, 0x0c, 0x00, 0x01, 0x88, 0x51, 0x23, 0xe2, 0x12, 0x01, 0x04, 0x80,
+ 0x80, 0x82, 0x41, 0x20, 0x49, 0x08, 0x12, 0x92, 0x29, 0x02, 0x40, 0x44,
+ 0x91, 0x00, 0x84, 0x21, 0x0a, 0x0a, 0xa0, 0xa0, 0x20, 0x20, 0x44, 0x80,
+ 0x00, 0x0f, 0x22, 0x40, 0x89, 0xf2, 0x44, 0x89, 0x26, 0x12, 0x49, 0x12,
+ 0x24, 0x48, 0x90, 0xc4, 0x88, 0xa2, 0x48, 0xc4, 0x84, 0x42, 0x19, 0x80,
+ 0x44, 0x21, 0x02, 0x2f, 0xc8, 0x91, 0x08, 0x44, 0x08, 0x03, 0x0f, 0x86,
+ 0x08, 0x53, 0x44, 0x12, 0x12, 0x01, 0x04, 0x80, 0x80, 0x82, 0x41, 0x24,
+ 0x48, 0x88, 0x12, 0x92, 0x29, 0x02, 0x40, 0x42, 0x90, 0x90, 0x84, 0x21,
+ 0x0a, 0x04, 0x41, 0x10, 0x20, 0x40, 0x44, 0x80, 0x00, 0x11, 0x22, 0x40,
+ 0x89, 0x02, 0x44, 0x89, 0x25, 0x12, 0x49, 0x12, 0x24, 0x48, 0x90, 0x24,
+ 0x88, 0xa2, 0xa9, 0x22, 0x84, 0x22, 0x20, 0x00, 0x44, 0x21, 0x02, 0x20,
+ 0x88, 0x91, 0x10, 0x44, 0x88, 0x00, 0xc0, 0x18, 0x00, 0x4d, 0x84, 0x12,
+ 0x11, 0x09, 0x08, 0x80, 0x80, 0x46, 0x41, 0x24, 0x48, 0x48, 0x11, 0x12,
+ 0x18, 0x84, 0x40, 0x21, 0x10, 0x90, 0x84, 0x21, 0x04, 0x04, 0x41, 0x10,
+ 0x20, 0x80, 0x42, 0x80, 0x00, 0x11, 0x32, 0x44, 0x99, 0x12, 0x4c, 0x89,
+ 0x24, 0x92, 0x49, 0x12, 0x26, 0x49, 0x91, 0x24, 0x98, 0x41, 0x12, 0x12,
+ 0x88, 0x22, 0x20, 0x00, 0x38, 0x21, 0xf1, 0xc0, 0x87, 0x0e, 0x10, 0x38,
+ 0x71, 0x20, 0x00, 0x00, 0x08, 0x20, 0x04, 0x13, 0xe0, 0xf1, 0xf0, 0xfc,
+ 0x80, 0x3a, 0x41, 0x23, 0x88, 0x2f, 0x91, 0x12, 0x08, 0x78, 0x40, 0x1e,
+ 0x90, 0x8f, 0x04, 0x1e, 0x04, 0x04, 0x42, 0x08, 0x20, 0xfe, 0x42, 0x80,
+ 0x00, 0x0e, 0xac, 0x38, 0x68, 0xe2, 0x34, 0x89, 0x24, 0x52, 0x49, 0x11,
+ 0xc5, 0x86, 0x90, 0xc6, 0x68, 0x41, 0x12, 0x11, 0x0f, 0x22, 0x20, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
+ 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x80, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x04, 0x00, 0x20, 0x00, 0x00, 0x00, 0x04, 0x00, 0x80, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x22, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x40, 0x80, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x00,
+ 0x20, 0x00, 0x00, 0x00, 0x04, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x02,
+ 0x00, 0x22, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x61, 0x80,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x40, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x1a, 0xc0, 0x00
+};
+#endif
+
+static Color palette[] =
+{
+ { 0xff, 0xff, 0xff },
+ { 0x00, 0x00, 0x00 },
+ { 0xff, 0xff, 0xc0 },
+ { 0x9f, 0x9f, 0x60 },
+ { 0x90, 0x00, 0x00 },
+ { 0x00, 0x90, 0x00 },
+ { 0x00, 0x00, 0x90 },
+ { 0xc0, 0xc0, 0xc0 }
+};
+
+static Color palette2[] =
+{
+ { 0xff, 0xff, 0xff },
+ { 0xe0, 0xe0, 0xe0 },
+ { 0xd0, 0xd0, 0xd0 },
+ { 0xc0, 0xc0, 0xc0 },
+ { 0xb0, 0xb0, 0xb0 },
+ { 0xa0, 0xa0, 0xa0 },
+ { 0x90, 0x90, 0x90 },
+ { 0x80, 0x80, 0x80 },
+ { 0x70, 0x70, 0x70 },
+ { 0x60, 0x60, 0x60 },
+ { 0x50, 0x50, 0x50 },
+ { 0x40, 0x40, 0x40 },
+ { 0x30, 0x30, 0x30 },
+ { 0x20, 0x20, 0x20 },
+ { 0x10, 0x10, 0x10 },
+ { 0x00, 0x00, 0x00 }
+};
+
+Image::Image(int w,int h)
+{
+ data = new uchar[w*h];
+ memset(data,0,w*h);
+ width = w;
+ height = h;
+}
+
+Image::~Image()
+{
+ delete[] data;
+}
+
+void Image::setPixel(int x,int y,uchar val)
+{
+ if (x>=0 && x<width && y>=0 && y<height)
+ data[y*width+x] = val;
+}
+
+uchar Image::getPixel(int x,int y) const
+{
+ if (x>=0 && x<width && y>=0 && y<height)
+ return data[y*width+x];
+ else
+ return 0;
+}
+
+void Image::writeChar(int x,int y,char c,uchar fg)
+{
+ if (c>=' ')
+ {
+ int xf,yf,ci=c-' ';
+ int rowOffset=0;
+ int cw = charWidth[ci];
+ int cp = charPos[ci];
+ for (yf=0;yf<charHeight;yf++)
+ {
+ unsigned short bitPattern=0;
+ int bitsLeft=cw;
+ int byteOffset = rowOffset+(cp>>3);
+ int bitOffset = cp&7;
+ // get the bit pattern for row yf of the character from the font data
+ while (bitsLeft>0)
+ {
+ int bits=8-bitOffset;
+ if (bits>bitsLeft) bits=bitsLeft;
+ bitPattern<<=bits;
+ bitPattern|=((fontRaw[byteOffset]<<bitOffset)&0xff)>>(8-bits);
+ bitsLeft-=bits;
+ bitOffset=0;
+ byteOffset++;
+ }
+ int mask=1<<(cw-1);
+ // draw character row yf
+ for (xf=0;xf<cw;xf++)
+ {
+ setPixel(x+xf,y+yf,(bitPattern&mask) ? fg : getPixel(x+xf,y+yf));
+ mask>>=1;
+ }
+ rowOffset+=charSetWidth;
+ }
+ }
+}
+
+void Image::writeString(int x,int y,const char *s,uchar fg)
+{
+ if (s)
+ {
+ char c;
+ while ((c=*s++))
+ {
+ writeChar(x,y,c,fg);
+ x+=charWidth[c-' '];
+ }
+ }
+}
+
+uint stringLength(const char *s)
+{
+ int w=0;
+ if (s)
+ {
+ char c;
+ while ((c=*s++)) w+=charWidth[c-' '];
+ }
+ return w;
+}
+
+void Image::drawHorzLine(int y,int xs,int xe,uchar colIndex,uint mask)
+{
+ int x,i=0,j=0;
+ for (x=xs;x<=xe;x++,j++)
+ {
+ if (j&1) i++;
+ if (mask&(1<<(i&0x1f))) setPixel(x,y,colIndex);
+ }
+}
+
+void Image::drawHorzArrow(int y,int xs,int xe,uchar colIndex,uint mask)
+{
+ drawHorzLine(y,xs,xe,colIndex,mask);
+ int i;
+ for (i=0;i<6;i++)
+ {
+ int h=i>>1;
+ drawVertLine(xe-i,y-h,y+h,colIndex,0xffffffff);
+ }
+}
+
+void Image::drawVertLine(int x,int ys,int ye,uchar colIndex,uint mask)
+{
+ int y,i=0;
+ for (y=ys;y<=ye;y++,i++)
+ {
+ if (mask&(1<<(i&0x1f))) setPixel(x,y,colIndex);
+ }
+}
+
+void Image::drawVertArrow(int x,int ys,int ye,uchar colIndex,uint mask)
+{
+ drawVertLine(x,ys,ye,colIndex,mask);
+ int i;
+ for (i=0;i<6;i++)
+ {
+ int h=i>>1;
+ drawHorzLine(ys+i,x-h,x+h,colIndex,0xffffffff);
+ }
+}
+
+void Image::drawRect(int x,int y,int w,int h,uchar colIndex,uint mask)
+{
+ drawHorzLine(y,x,x+w-1,colIndex,mask);
+ drawHorzLine(y+h-1,x,x+w-1,colIndex,mask);
+ drawVertLine(x,y,y+h-1,colIndex,mask);
+ drawVertLine(x+w-1,y,y+h-1,colIndex,mask);
+}
+
+void Image::fillRect(int x,int y,int width,int height,uchar colIndex,uint mask)
+{
+ int xp,yp,xi,yi;
+ for (yp=y,yi=0;yp<y+height;yp++,yi++)
+ for (xp=x,xi=0;xp<x+width;xp++,xi++)
+ if (mask&(1<<((xi+yi)&0x1f)))
+ setPixel(xp,yp,colIndex);
+}
+
+bool Image::save(const char *fileName,int mode)
+{
+ GifEncoder gifenc(data,
+ mode==0 ? palette : palette2,
+ width,height,
+ mode==0 ? 3 : 4,
+ 0);
+ QFile file(fileName);
+ if (file.open(IO_WriteOnly))
+ {
+ gifenc.writeGIF(file);
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+}
diff --git a/src/image.h b/src/image.h
new file mode 100644
index 0000000..a48a1f8
--- /dev/null
+++ b/src/image.h
@@ -0,0 +1,50 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#ifndef _IMAGE_H
+#define _IMAGE_H
+#include <qglobal.h>
+
+class Image
+{
+ public:
+ Image(int w,int h);
+ ~Image();
+
+ void setPixel(int x,int y,uchar val);
+ uchar getPixel(int x,int y) const;
+ void writeChar(int x,int y,char c,uchar fg);
+ void writeString(int x,int y,const char *s,uchar fg);
+ void drawHorzLine(int y,int xs,int xe,uchar colIndex,uint mask);
+ void drawHorzArrow(int y,int xs,int xe,uchar colIndex,uint mask);
+ void drawVertLine(int x,int ys,int ye,uchar colIndex,uint mask);
+ void drawVertArrow(int x,int ys,int ye,uchar colIndex,uint mask);
+ void drawRect(int x,int y,int width,int height,uchar colIndex,uint mask);
+ void fillRect(int x,int y,int width,int height,uchar colIndex,uint mask);
+ bool save(const char *fileName,int mode=0);
+ friend uint stringLength(const char *s);
+ uint getWidth() const { return width; }
+ uint getHeight() const { return height; }
+ uchar *getData() const { return data; }
+
+ private:
+ int width;
+ int height;
+ uchar *data;
+};
+
+#endif
diff --git a/src/index.cpp b/src/index.cpp
new file mode 100644
index 0000000..d472542
--- /dev/null
+++ b/src/index.cpp
@@ -0,0 +1,975 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#include <qtstream.h>
+#include <qdatetm.h>
+#include <qdir.h>
+#include <stdlib.h>
+
+#include "message.h"
+#include "index.h"
+#include "doxygen.h"
+#include "scanner.h"
+#include "code.h"
+#include "config.h"
+#include "filedef.h"
+#include "outputlist.h"
+#include "util.h"
+#include "groupdef.h"
+#include "language.h"
+
+//----------------------------------------------------------------------------
+
+// strips w from s iff s starts with w
+bool stripWord(QString &s,QString w)
+{
+ bool success=FALSE;
+ if (s.left(w.length())==w)
+ {
+ success=TRUE;
+ s=s.right(s.length()-w.length());
+ }
+ return success;
+}
+
+//----------------------------------------------------------------------------
+// some quasi intelligent brief description abbreviator :^)
+QString abbreviate(const char *s,const char *name)
+{
+ QString result=s;
+ QString start1=(QString)"The "+name+" class ";
+ QString start2=(QString)"The "+name+" widget ";
+ QString start3=(QString)"The "+name+" file ";
+ result=result.simplifyWhiteSpace();
+ // strip trailing .
+ if (result.length()>0 && result.at(result.length()-1)=='.')
+ result=result.left(result.length()-1);
+ bool found=FALSE;
+ found = found || stripWord(result,start1);
+ found = found || stripWord(result,start2);
+ found = found || stripWord(result,start3);
+ if (found)
+ {
+ bool found=FALSE;
+ found = found || stripWord(result,"is ");
+ found = found || stripWord(result,"provides ");
+ found = found || stripWord(result,"specifies ");
+ found = found || stripWord(result,"contains ");
+ found = found || stripWord(result,"represents ");
+ if (found)
+ {
+ stripWord(result,"a ");
+ stripWord(result,"an ");
+ stripWord(result,"the ");
+ }
+ }
+ if (result.length()>0)
+ {
+ int c=result[0];
+ if (c>='a' && c<='z') c+='A'-'a';
+ result[0]=c;
+ }
+ return result;
+}
+
+//----------------------------------------------------------------------------
+
+void initBaseClassHierarchy(BaseClassList *bcl)
+{
+ BaseClassListIterator bcli(*bcl);
+ for ( ; bcli.current(); ++bcli)
+ {
+ ClassDef *cd=bcli.current()->classDef;
+ if (cd->baseClasses()->count()==0) // no base classes => new root
+ {
+ initBaseClassHierarchy(cd->baseClasses());
+ }
+ cd->visited=FALSE;
+ }
+}
+
+//----------------------------------------------------------------------------
+
+void initClassHierarchy(ClassList *cl)
+{
+ ClassListIterator cli(*cl);
+ ClassDef *cd;
+ for ( ; (cd=cli.current()); ++cli)
+ {
+ cd->visited=FALSE;
+ initBaseClassHierarchy(cd->baseClasses());
+ }
+}
+
+//----------------------------------------------------------------------------
+
+bool hasVisibleRoot(BaseClassList *bcl)
+{
+ BaseClassListIterator bcli(*bcl);
+ for ( ; bcli.current(); ++bcli)
+ {
+ ClassDef *cd=bcli.current()->classDef;
+ if (cd->isVisibleExt()) return TRUE;
+ hasVisibleRoot(cd->baseClasses());
+ }
+ return FALSE;
+}
+
+//----------------------------------------------------------------------------
+
+void writeClassTree(OutputList &ol,BaseClassList *bcl,bool hideSuper)
+{
+ BaseClassListIterator bcli(*bcl);
+ bool started=FALSE;
+ for ( ; bcli.current() ; ++bcli)
+ {
+ ClassDef *cd=bcli.current()->classDef;
+ if (cd->isVisibleExt() && hasVisibleRoot(cd->baseClasses()))
+ {
+ if (!started)
+ {
+ ol.startIndexList();
+ started=TRUE;
+ }
+ //printf("Passed...\n");
+ if (cd->hasDocumentation() || cd->isReference())
+ {
+ ol.writeIndexItem(cd->getReference(),cd->classFile(),cd->name());
+ if (cd->isReference())
+ {
+ ol.startTypewriter();
+ ol.docify(" [external]");
+ ol.endTypewriter();
+ }
+ }
+ else
+ {
+ ol.writeIndexItem(0,0,cd->name());
+ }
+ if (!cd->visited && !hideSuper && cd->superClasses()->count()>0)
+ {
+ writeClassTree(ol,cd->superClasses(),cd->visited);
+ cd->visited=TRUE;
+ }
+ }
+ }
+ if (started) ol.endIndexList();
+}
+
+//----------------------------------------------------------------------------
+
+void writeClassHierarchy(OutputList &ol)
+{
+ initClassHierarchy(&classList);
+
+ bool started=FALSE;
+ ClassListIterator cli(classList);
+ for (;cli.current(); ++cli)
+ {
+ ClassDef *cd=cli.current();
+ if (!hasVisibleRoot(cd->baseClasses()))
+ {
+ if (cd->isVisibleExt())
+ {
+ if (!started)
+ {
+ ol.startIndexList();
+ started=TRUE;
+ }
+ if (cd->hasDocumentation() || cd->isReference())
+ {
+ ol.writeIndexItem(cd->getReference(),cd->classFile(),cd->name());
+ if (cd->isReference())
+ {
+ ol.startTypewriter();
+ ol.docify(" [external]");
+ ol.endTypewriter();
+ }
+ }
+ else
+ {
+ ol.writeIndexItem(0,0,cd->name());
+ }
+ }
+ if (!cd->visited && cd->superClasses()->count()>0)
+ {
+ writeClassTree(ol,cd->superClasses(),cd->visited);
+ cd->visited=TRUE;
+ }
+ }
+ }
+ if (started) ol.endIndexList();
+}
+
+//----------------------------------------------------------------------------
+
+int countClassHierarchy()
+{
+ initClassHierarchy(&classList);
+ int count=0;
+ ClassListIterator cli(classList);
+ for ( ; cli.current(); ++cli)
+ {
+ if (cli.current()->superClasses()->count()>0) count++;
+ }
+ return count;
+}
+
+//----------------------------------------------------------------------------
+
+void writeHierarchicalIndex(OutputList &ol)
+{
+ if (hierarchyClasses==0) return;
+ ol.disable(OutputGenerator::Man);
+ startFile(ol,"hierarchy","Hierarchical Index");
+ startTitle(ol);
+ parseDoc(ol,0,0,projectName+" "+theTranslator->trClassHierarchy());
+ endTitle(ol,0);
+ parseDoc(ol,0,0,theTranslator->trClassHierarchyDescription());
+ ol.newParagraph();
+ writeClassHierarchy(ol);
+ endFile(ol);
+ ol.enable(OutputGenerator::Man);
+}
+
+//----------------------------------------------------------------------------
+
+int countFileList()
+{
+ int count=0;
+ FileNameListIterator fnli(inputNameList);
+ FileName *fn;
+ for (;(fn=fnli.current());++fnli)
+ {
+ FileNameIterator fni(*fn);
+ FileDef *fd;
+ for (;(fd=fni.current());++fni)
+ {
+ if (fd->hasDocumentation()) count++;
+ }
+ }
+ return count;
+}
+
+//----------------------------------------------------------------------------
+
+void writeFileIndex(OutputList &ol)
+{
+ if (documentedFiles==0) return;
+ ol.disable(OutputGenerator::Man);
+ startFile(ol,"files","File Index");
+ startTitle(ol);
+ parseDoc(ol,0,0,projectName+" "+theTranslator->trFileList());
+ endTitle(ol,0);
+ ol.newParagraph();
+ parseDoc(ol,0,0,theTranslator->trFileListDescription(extractAllFlag));
+ ol.newParagraph();
+
+ ol.startIndexList();
+ FileName *fn=inputNameList.first();
+ while (fn)
+ {
+ FileDef *fd=fn->first();
+ while (fd)
+ {
+ if (fd->hasDocumentation() && !fd->isReference())
+ {
+ //ol.writeIndexItem(fd->getReference(),fd->diskName(),
+ // fd->name());
+ QString path;
+ if (fullPathNameFlag)
+ {
+ path=fd->getPath().copy();
+ // strip part of the path
+ if (path.left(stripFromPath.length())==stripFromPath)
+ path=path.right(path.length()-stripFromPath.length());
+ }
+
+ ol.writeStartAnnoItem("file",
+ fd->diskName(),
+ path,
+ fd->name()
+ );
+ ol.docify(" (");
+ if (fd->briefDescription())
+ {
+ OutputList briefOutput(&ol);
+ parseDoc(briefOutput,0,0,
+ abbreviate(fd->briefDescription(),fd->name()));
+ ol+=briefOutput;
+ }
+ else
+ {
+ ol.startEmphasis();
+ parseDoc(ol,0,0,theTranslator->trNoDescriptionAvailable());
+ ol.endEmphasis();
+ }
+ ol.docify(")");
+ ol.writeEndAnnoItem(fd->name());
+ }
+ fd=fn->next();
+ }
+ fn=inputNameList.next();
+ }
+ ol.endIndexList();
+ endFile(ol);
+ ol.enable(OutputGenerator::Man);
+}
+
+//----------------------------------------------------------------------------
+
+int countNamespaceList()
+{
+ int count=0;
+ NamespaceListIterator nli(namespaceList);
+ NamespaceDef *nd;
+ for (;(nd=nli.current());++nli)
+ {
+ if (nd->hasDocumentation()) count++;
+ }
+ return count;
+}
+
+//----------------------------------------------------------------------------
+
+void writeNamespaceIndex(OutputList &ol)
+{
+ if (documentedNamespaces==0) return;
+ ol.disable(OutputGenerator::Man);
+ startFile(ol,"namespaces","Namespace Index");
+ startTitle(ol);
+ parseDoc(ol,0,0,projectName+" "+theTranslator->trNamespaceList());
+ endTitle(ol,0);
+ ol.newParagraph();
+ parseDoc(ol,0,0,theTranslator->trNamespaceListDescription(extractAllFlag));
+ ol.newParagraph();
+
+ ol.startIndexList();
+ NamespaceDef *nd=namespaceList.first();
+ while (nd)
+ {
+ if (nd->hasDocumentation())
+ {
+ ol.writeStartAnnoItem("namespace",nd->namespaceFile(),0,nd->name());
+ ol.docify(" (");
+ if (nd->briefDescription())
+ {
+ OutputList briefOutput(&ol);
+ parseDoc(briefOutput,nd->name(),0,
+ abbreviate(nd->briefDescription(),nd->name()));
+ ol+=briefOutput;
+ }
+ else
+ {
+ ol.startEmphasis();
+ parseDoc(ol,0,0,theTranslator->trNoDescriptionAvailable());
+ ol.endEmphasis();
+ }
+ ol.docify(")");
+ ol.writeEndAnnoItem(nd->name());
+ }
+ nd=namespaceList.next();
+ }
+ ol.endIndexList();
+ endFile(ol);
+ ol.enable(OutputGenerator::Man);
+}
+
+//----------------------------------------------------------------------------
+
+int countAnnotatedClasses()
+{
+ int count=0;
+ //ClassDef *cd=classList.first();
+ ClassListIterator cli(classList);
+ ClassDef *cd;
+ for (;(cd=cli.current());++cli)
+ {
+ if (!cd->isReference() && cd->isVisible())
+ {
+ //printf("Annotated class %s\n",cd->name().data());
+ count++;
+ }
+ }
+ return count;
+}
+
+//----------------------------------------------------------------------
+
+void writeAnnotatedClassList(OutputList &ol)
+{
+ ol.startIndexList();
+ //ClassDef *cd=classList.first();
+ //while (cd)
+ ClassListIterator cli(classList);
+ ClassDef *cd;
+ for (;(cd=cli.current());++cli)
+ {
+ if (!cd->isReference() &&
+ //!cd->name().isEmpty() && cd->name()[0]!='@' &&
+ //(cd->protection()!=Private || extractPrivateFlag) &&
+ //(cd->hasDocumentation() || !hideClassFlag)
+ cd->isVisible()
+ )
+ {
+ QString type;
+ switch (cd->compoundType())
+ {
+ case ClassDef::Class: type="class"; break;
+ case ClassDef::Struct: type="struct"; break;
+ case ClassDef::Union: type="union"; break;
+ default: type="unknown"; break; // an error
+ }
+ ol.writeStartAnnoItem(type,cd->classFile(),0,cd->name());
+ ol.docify(" (");
+ if (cd->briefDescription())
+ {
+ OutputList briefOutput(&ol);
+ parseDoc(briefOutput,cd->name(),0,
+ abbreviate(cd->briefDescription(),cd->name()));
+ ol+=briefOutput;
+ }
+ else
+ {
+ ol.startEmphasis();
+ parseDoc(ol,0,0,theTranslator->trNoDescriptionAvailable());
+ ol.endEmphasis();
+ }
+ ol.docify(")");
+ ol.writeEndAnnoItem(cd->name());
+ }
+ cd=classList.next();
+ }
+ ol.endIndexList();
+}
+
+//----------------------------------------------------------------------------
+
+void writeAnnotatedIndex(OutputList &ol)
+{
+ if (annotatedClasses==0) return;
+
+ //if (classList.count()==0) return;
+ ol.disable(OutputGenerator::Man);
+ startFile(ol,"annotated","Annotated Index");
+ startTitle(ol);
+ parseDoc(ol,0,0,projectName+" "+theTranslator->trCompoundList());
+ endTitle(ol,0);
+ parseDoc(ol,0,0,theTranslator->trCompoundListDescription());
+ writeAnnotatedClassList(ol);
+ endFile(ol);
+ ol.enable(OutputGenerator::Man);
+}
+
+//----------------------------------------------------------------------------
+
+void writeMemberList(OutputList &ol)
+{
+ ol.startItemList();
+ MemberName *mn=memberNameList.first();
+ while (mn)
+ {
+ MemberDef *md=mn->first();
+ bool found=FALSE;
+ bool isFunc=FALSE;
+ while (md && !found)
+ {
+ ClassDef *cd;
+ if ((md->isFriend() || md->protection()!=Private || extractPrivateFlag) &&
+ !md->isReference() && md->hasDocumentation() &&
+ md->name()[0]!='@' && (cd=md->memberClass()) &&
+ cd->isVisible()
+ )
+ {
+ found=TRUE;
+ isFunc=md->isFunction();
+ }
+ md=mn->next();
+ }
+ if (found)
+ {
+ ol.writeListItem();
+ ol.docify(substituteClassNames(mn->memberName()));
+ if (isFunc) ol.docify("()");
+ ol.writeString("\n");
+
+ int count=0;
+ md=mn->first();
+ QString prevName;
+ while (md)
+ {
+ ClassDef *cd=md->memberClass();
+ if (cd && (md->isFriend() || md->protection()!=Private || extractPrivateFlag) &&
+ !md->isReference() && md->hasDocumentation() &&
+ prevName!=cd->name() &&
+ cd->isVisible()
+ )
+ {
+ if (count==0)
+ ol.docify(": ");
+ else
+ ol.docify(", ");
+ ol.writeObjectLink(cd->getReference(),cd->classFile(),md->anchor(),
+ cd->name());
+ count++;
+ prevName=cd->name();
+ }
+ md=mn->next();
+ }
+ }
+ mn=memberNameList.next();
+ }
+ ol.endItemList();
+}
+
+//----------------------------------------------------------------------------
+
+int countMemberList()
+{
+ int count=0;
+ MemberName *mn=memberNameList.first();
+ while (mn)
+ {
+ MemberDef *md=mn->first();
+ bool found=FALSE;
+ MemberDef *otherMd=0;
+ ClassDef *cd;
+ while (md && !found)
+ {
+ if ((md->isFriend() || md->protection()!=Private || extractPrivateFlag) &&
+ !md->isReference() && !md->isRelated() && md->hasDocumentation() &&
+ md->name()[0]!='@' && (cd=md->memberClass()) && cd->isVisible())
+ otherMd=md;
+ if ((md->isFriend() || md->protection()!=Private || extractPrivateFlag) &&
+ !md->isReference() && md->isRelated() && md->hasDocumentation() &&
+ md->name()[0]!='@' && (cd=md->memberClass()) && cd->isVisible())
+ found=TRUE;
+ else
+ md=mn->next();
+ }
+ if (found || otherMd) count++;
+ mn=memberNameList.next();
+ }
+ return count;
+}
+
+//----------------------------------------------------------------------------
+
+void writeMemberIndex(OutputList &ol)
+{
+ if (memberNameList.count()==0) return;
+ ol.disable(OutputGenerator::Man);
+ ol.disable(OutputGenerator::Latex);
+ startFile(ol,"functions","Compound Member Index");
+ startTitle(ol);
+ parseDoc(ol,0,0,projectName+" "+theTranslator->trCompoundMembers());
+ endTitle(ol,0);
+ parseDoc(ol,0,0,theTranslator->trCompoundMembersDescription(extractAllFlag));
+ writeMemberList(ol);
+ endFile(ol);
+ ol.enable(OutputGenerator::Latex);
+ ol.enable(OutputGenerator::Man);
+}
+
+//----------------------------------------------------------------------------
+
+void writeFunctionList(OutputList &ol)
+{
+ ol.startItemList();
+ MemberName *mn=functionNameList.first();
+ while (mn)
+ {
+ MemberDef *md=mn->first();
+ bool found=FALSE;
+ while (md && !found)
+ {
+ FileDef *fd=md->getFileDef() ? md->getFileDef() : md->getFileDec();
+ bool hasDocs =
+ (md->getFileDef() && md->getFileDef()->hasDocumentation()) ||
+ (md->getFileDec() && md->getFileDec()->hasDocumentation());
+
+ if (fd && hasDocs &&
+ !md->isReference() &&
+ md->hasDocumentation() &&
+ md->name()[0]!='@') found=TRUE;
+ else
+ md=mn->next();
+ }
+ if (found) // function is documented
+ {
+ ol.writeListItem();
+ ol.docify(md->name());
+ if (md->isFunction()) ol.docify("()");
+ ol.writeString("\n");
+
+ int count=0;
+ md=mn->first();
+ QString prevName;
+ while (md)
+ {
+ FileDef *fd=md->getFileDef() ? md->getFileDef() : md->getFileDec();
+ bool hasDocs =
+ (md->getFileDef() && md->getFileDef()->hasDocumentation()) ||
+ (md->getFileDec() && md->getFileDec()->hasDocumentation());
+ if (fd && hasDocs &&
+ !md->isReference() &&
+ md->hasDocumentation() &&
+ md->name()[0]!='@' &&
+ prevName!=fd->name())
+ {
+ if (count==0)
+ ol.docify(": ");
+ else
+ ol.docify(", ");
+ QString baseName=fd->name().copy();
+ //int s;
+ //if ((s=baseName.findRev("/"))!=-1)
+ // baseName=baseName.right(baseName.length()-s-1);
+ ol.writeObjectLink(fd->getReference(),
+ fd->diskName(),md->anchor(), baseName);
+ count++;
+ prevName=fd->name();
+ }
+ md=mn->next();
+ }
+ }
+ mn=functionNameList.next();
+ }
+ ol.endItemList();
+}
+
+//----------------------------------------------------------------------------
+
+int countFunctionList()
+{
+ int count=0;
+ MemberName *mn=functionNameList.first();
+ while (mn)
+ {
+ MemberDef *md=mn->first();
+ FileDef *fd;
+ bool found=FALSE;
+ while (md && !found)
+ {
+ if (!md->isReference() && md->hasDocumentation() &&
+ md->name()[0]!='@' &&
+ (((fd=md->getFileDef()) && fd->hasDocumentation())
+ ||
+ ((fd=md->getFileDec()) && fd->hasDocumentation())
+ )
+ )
+ found=TRUE;
+ else
+ md=mn->next();
+ }
+ if (found) count++;
+ mn=functionNameList.next();
+ }
+ return count;
+}
+
+//----------------------------------------------------------------------------
+
+void writeFunctionIndex(OutputList &ol)
+{
+ if (documentedFunctions==0) return;
+ ol.disable(OutputGenerator::Man);
+ ol.disable(OutputGenerator::Latex);
+ startFile(ol,"globals","File Member Index");
+ startTitle(ol);
+ parseDoc(ol,0,0,projectName+" "+theTranslator->trFileMembers());
+ endTitle(ol,0);
+ parseDoc(ol,0,0,theTranslator->trFileMembersDescription(extractAllFlag));
+ writeFunctionList(ol);
+ endFile(ol);
+ ol.enable(OutputGenerator::Latex);
+ ol.enable(OutputGenerator::Man);
+}
+
+//----------------------------------------------------------------------------
+
+void writeHeaderFileList(OutputList &ol)
+{
+ if (includeFiles.count()>0)
+ {
+ ol.startItemList();
+ FileDef *fd=includeFiles.first();
+ while (fd)
+ {
+ ol.writeListItem();
+ QString path;
+ if (fullPathNameFlag)
+ {
+ path=fd->getPath().copy();
+ // strip part of the path
+ if (path.left(stripFromPath.length())==stripFromPath)
+ path=path.right(path.length()-stripFromPath.length());
+ }
+ if (!path.isEmpty()) ol.docify(path);
+ ol.writeObjectLink(0,fd->includeName(),0,fd->name());
+ ol.writeString("\n");
+ fd=includeFiles.next();
+ }
+ ol.endItemList();
+ }
+}
+
+//----------------------------------------------------------------------------
+
+void writeHeaderIndex(OutputList &ol)
+{
+ if (includeFiles.count()==0) return;
+ ol.disable(OutputGenerator::Man);
+ ol.disable(OutputGenerator::Latex);
+ startFile(ol,"headers","Header File Index");
+ startTitle(ol);
+ parseDoc(ol,0,0,projectName+" "+theTranslator->trHeaderFiles());
+ endTitle(ol,0);
+ parseDoc(ol,0,0,theTranslator->trHeaderFilesDescription());
+ writeHeaderFileList(ol);
+ endFile(ol);
+ ol.enable(OutputGenerator::Latex);
+ ol.enable(OutputGenerator::Man);
+}
+
+//----------------------------------------------------------------------------
+
+void writeExampleIndex(OutputList &ol)
+{
+ if (exampleList.count()==0) return;
+ ol.disable(OutputGenerator::Man);
+ startFile(ol,"examples","Example Index");
+ startTitle(ol);
+ parseDoc(ol,0,0,projectName+" "+theTranslator->trExamples());
+ endTitle(ol,0);
+ parseDoc(ol,0,0,theTranslator->trExamplesDescription());
+ ol.startIndexList();
+ PageInfo *pi=exampleList.first();
+ while (pi)
+ {
+ ol.writeListItem();
+ QString n=convertSlashes(pi->name,TRUE)+"-example";
+ if (!pi->title.isEmpty())
+ {
+ ol.writeObjectLink(0,n,0,pi->title);
+ }
+ else
+ {
+ ol.writeObjectLink(0,n,0,pi->name);
+ }
+ ol.writeString("\n");
+ pi=exampleList.next();
+ }
+ ol.endIndexList();
+ endFile(ol);
+ ol.enable(OutputGenerator::Man);
+}
+
+//----------------------------------------------------------------------------
+
+void writePageIndex(OutputList &ol)
+{
+ if (pageList.count()==0) return;
+ ol.disable(OutputGenerator::Man);
+ startFile(ol,"pages","Page Index");
+ startTitle(ol);
+ ol.docify(projectName+" "+theTranslator->trRelatedPages());
+ endTitle(ol,0);
+ parseDoc(ol,0,0,theTranslator->trRelatedPagesDescription());
+ ol.startIndexList();
+ PageInfo *pi=pageList.first();
+ while (pi)
+ {
+ QString pageName;
+ if (caseSensitiveNames)
+ pageName=pi->name.copy();
+ else
+ pageName=pi->name.lower();
+ ol.writeListItem();
+ ol.writeObjectLink(0,pageName,0,pi->name);
+ ol.writeString("\n");
+ pi=pageList.next();
+ }
+ ol.endIndexList();
+ endFile(ol);
+ ol.enable(OutputGenerator::Man);
+}
+
+//----------------------------------------------------------------------------
+
+int countGroupList()
+{
+ int count=0;
+ GroupListIterator gli(groupList);
+ GroupDef *gd;
+ for (;(gd=gli.current());++gli)
+ {
+ if (gd->countMembers()>0) count++;
+ gd=groupList.next();
+ }
+ return count;
+}
+
+//----------------------------------------------------------------------------
+
+void writeGroupList(OutputList &ol)
+{
+ ol.startDescription();
+ GroupListIterator gli(groupList);
+ GroupDef *gd;
+ for (;(gd=gli.current());++gli)
+ {
+ if (gd->countMembers()>0)
+ {
+ ol.startDescItem();
+ ol.startTextLink(gd->groupFile(),0);
+ parseDoc(ol,0,0,gd->groupTitle());
+ ol.endTextLink();
+ ol.endDescItem();
+ parseDoc(ol,0,0,gd->briefDescription());
+ ol.newParagraph();
+ }
+ }
+ ol.endDescription();
+}
+
+//----------------------------------------------------------------------------
+
+void writeGroupIndex(OutputList &ol)
+{
+ if (documentedGroups==0) return;
+ ol.disable(OutputGenerator::Man);
+ startFile(ol,"modules","Module Index");
+ startTitle(ol);
+ parseDoc(ol,0,0,projectName+" "+theTranslator->trModules());
+ endTitle(ol,0);
+ parseDoc(ol,0,0,theTranslator->trModulesDescription());
+ writeGroupList(ol);
+ endFile(ol);
+ ol.enable(OutputGenerator::Man);
+}
+
+void writeIndex(OutputList &ol)
+{
+ // save old generator state
+ bool manEnabled = ol.isEnabled(OutputGenerator::Man);
+ bool texEnabled = ol.isEnabled(OutputGenerator::Latex);
+ bool htmEnabled = ol.isEnabled(OutputGenerator::Html);
+
+ QString projPrefix;
+ if (!projectName.isEmpty())
+ {
+ projPrefix=projectName+" ";
+ }
+ // write HTML index
+ ol.disable(OutputGenerator::Man);
+ ol.disable(OutputGenerator::Latex);
+ ol.startFile("index","Main Index",FALSE);
+ if (!noIndexFlag) writeQuickLinks(ol,TRUE);
+ ol.startTitleHead();
+ parseDoc(ol,0,0,projPrefix+theTranslator->trDocumentation());
+ ol.endTitleHead(0);
+ ol.newParagraph();
+ if (!projectNumber.isEmpty())
+ {
+ ol.startProjectNumber();
+ parseDoc(ol,0,0,projectNumber);
+ ol.endProjectNumber();
+ }
+ if (noIndexFlag) writeQuickLinks(ol,FALSE);
+ endFile(ol);
+ ol.disable(OutputGenerator::Html);
+
+ // write LaTeX index
+ ol.enable(OutputGenerator::Latex);
+ ol.startFile("refman",0,FALSE);
+ ol.startIndexSection(isTitlePageStart);
+ parseDoc(ol,0,0,projPrefix+theTranslator->trReferenceManual());
+ if (!projectNumber.isEmpty())
+ {
+ ol.startProjectNumber();
+ parseDoc(ol,0,0,projectNumber);
+ ol.endProjectNumber();
+ }
+ ol.endIndexSection(isTitlePageStart);
+ ol.startIndexSection(isTitlePageAuthor);
+ parseDoc(ol,0,0,theTranslator->trGeneratedBy());
+ ol.endIndexSection(isTitlePageAuthor);
+ if (documentedGroups>0)
+ {
+ ol.startIndexSection(isModuleIndex);
+ parseDoc(ol,0,0,projPrefix+theTranslator->trModuleIndex());
+ ol.endIndexSection(isModuleIndex);
+ }
+ if (hierarchyClasses>0)
+ {
+ ol.startIndexSection(isClassHierarchyIndex);
+ parseDoc(ol,0,0,projPrefix+theTranslator->trHierarchicalIndex());
+ ol.endIndexSection(isClassHierarchyIndex);
+ }
+ if (annotatedClasses>0)
+ {
+ ol.startIndexSection(isCompoundIndex);
+ parseDoc(ol,0,0,projPrefix+theTranslator->trCompoundIndex());
+ ol.endIndexSection(isCompoundIndex);
+ }
+ if (documentedFiles>0)
+ {
+ ol.startIndexSection(isFileIndex);
+ parseDoc(ol,0,0,projPrefix+theTranslator->trFileIndex());
+ ol.endIndexSection(isFileIndex);
+ }
+ if (documentedGroups>0)
+ {
+ ol.startIndexSection(isModuleDocumentation);
+ parseDoc(ol,0,0,projPrefix+theTranslator->trModuleDocumentation());
+ ol.endIndexSection(isModuleDocumentation);
+ }
+ if (annotatedClasses>0)
+ {
+ ol.startIndexSection(isClassDocumentation);
+ parseDoc(ol,0,0,projPrefix+theTranslator->trClassDocumentation());
+ ol.endIndexSection(isClassDocumentation);
+ }
+ if (documentedFiles>0)
+ {
+ ol.startIndexSection(isFileDocumentation);
+ parseDoc(ol,0,0,projPrefix+theTranslator->trFileDocumentation());
+ ol.endIndexSection(isFileDocumentation);
+ }
+ if (exampleList.count()>0)
+ {
+ ol.startIndexSection(isExampleDocumentation);
+ parseDoc(ol,0,0,projPrefix+theTranslator->trExampleDocumentation());
+ ol.endIndexSection(isExampleDocumentation);
+ }
+ if (pageList.count()>0)
+ {
+ ol.startIndexSection(isPageDocumentation);
+ parseDoc(ol,0,0,projPrefix+theTranslator->trPageDocumentation());
+ ol.endIndexSection(isPageDocumentation);
+ }
+ ol.endIndexSection(isEndIndex);
+ endFile(ol);
+
+ // restore generator state
+ if (manEnabled) ol.enable(OutputGenerator::Man);
+ else ol.disable(OutputGenerator::Man);
+ if (texEnabled) ol.enable(OutputGenerator::Latex);
+ else ol.disable(OutputGenerator::Latex);
+ if (htmEnabled) ol.enable(OutputGenerator::Html);
+ else ol.disable(OutputGenerator::Html);
+}
diff --git a/src/index.h b/src/index.h
new file mode 100644
index 0000000..5b3cc67
--- /dev/null
+++ b/src/index.h
@@ -0,0 +1,65 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#ifndef INDEX_H
+#define INDEX_H
+
+#include <qfile.h>
+#include <qtstream.h>
+
+enum IndexSections
+{
+ isTitlePageStart,
+ isTitlePageAuthor,
+ isModuleIndex,
+ isClassHierarchyIndex,
+ isCompoundIndex,
+ isFileIndex,
+ isModuleDocumentation,
+ isClassDocumentation,
+ isFileDocumentation,
+ isExampleDocumentation,
+ isPageDocumentation,
+ isEndIndex
+};
+
+class OutputList;
+
+void writeIndex(OutputList &ol);
+void writeHierarchicalIndex(OutputList &ol);
+void writeClassHierarchy(OutputList &ol);
+void writeFileIndex(OutputList &ol);
+void writeAnnotatedIndex(OutputList &ol);
+void writeAnnotatedClassList(OutputList &ol);
+void writeMemberIndex(OutputList &ol);
+void writeMemberList(OutputList &ol);
+void writeHeaderIndex(OutputList &ol);
+void writeHeaderFileList(OutputList &ol);
+void writeExampleIndex(OutputList &ol);
+void writePageIndex(OutputList &ol);
+void writeFunctionIndex(OutputList &ol);
+void writeGroupIndex(OutputList &ol);
+void writeNamespaceIndex(OutputList &ol);
+
+int countClassHierarchy();
+int countMemberList();
+int countFunctionList();
+int countFileList();
+int countGroupList();
+int countNamespaceList();
+int countAnnotatedClasses();
+
+#endif
diff --git a/src/instdox.cpp b/src/instdox.cpp
new file mode 100644
index 0000000..ad22c89
--- /dev/null
+++ b/src/instdox.cpp
@@ -0,0 +1,164 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <qstring.h>
+#include <qfile.h>
+#include <qfileinf.h>
+#include <qtstream.h>
+
+#include "instdox.h"
+#include "doxygen.h"
+#include "config.h"
+#include "message.h"
+
+void writeInstallScript()
+{
+ QString fileName=htmlOutputDir+"/installdox";
+ QFile f(fileName);
+ if (f.open(IO_WriteOnly))
+ {
+ QTextStream t(&f);
+ t << "#!" << perlPath << endl << endl << "%subst = ( ";
+
+ char *s=tagFileList.first();
+ while (s)
+ {
+ QFileInfo fi(s);
+ t << "\"" << fi.fileName() << "\", \"\"";
+ s=tagFileList.next();
+ if (s) t << ", ";
+ }
+
+ t << ");\n";
+ t << "$quiet = 0;\n";
+ t << "\n";
+ t << "if (open(F,\"search.cfg\"))\n";
+ t << "{\n";
+ t << " $_=<F> ; s/[ \\t\\n]*$//g ; $subst{\"_doc\"} = $_;\n";
+ t << " $_=<F> ; s/[ \\t\\n]*$//g ; $subst{\"_cgi\"} = $_;\n";
+ t << "}\n";
+ t << "\n";
+ t << "while ( @ARGV ) {\n";
+ t << " $_ = shift @ARGV;\n";
+ t << " if ( s/^-// ) {\n";
+ t << " if ( /^l(.*)/ ) {\n";
+ t << " $v = ($1 eq \"\") ? shift @ARGV : $1;\n";
+ t << " ($v =~ /\\/$/) || ($v .= \"/\");\n";
+ t << " $_ = $v;\n";
+ t << " if ( /(.+)\\@(.+)/ ) {\n";
+ t << " if ( exists $subst{$1} ) {\n";
+ t << " $subst{$1} = $2;\n";
+ t << " } else {\n";
+ t << " print STDERR \"Unknown tag file $1 given with option -l\\n\";\n";
+ t << " &usage();\n";
+ t << " }\n";
+ t << " } else {\n";
+ t << " print STDERR \"Argument $_ is invalid for option -l\\n\";\n";
+ t << " &usage();\n";
+ t << " }\n";
+ t << " }\n";
+ t << " elsif ( /^q/ ) {\n";
+ t << " $quiet = 1;\n";
+ t << " }\n";
+ t << " elsif ( /^\\?|^h/ ) {\n";
+ t << " &usage();\n";
+ t << " }\n";
+ t << " else {\n";
+ t << " print STDERR \"Illegal option -$_\\n\";\n";
+ t << " &usage();\n";
+ t << " }\n";
+ t << " }\n";
+ t << " else {\n";
+ t << " push (@files, $_ );\n";
+ t << " }\n";
+ t << "}\n";
+ t << "\n";
+ t << "foreach $sub (keys %subst)\n";
+ t << "{\n";
+ t << " if ( $subst{$sub} eq \"\" ) \n";
+ t << " {\n";
+ t << " print STDERR \"No substitute given for tag file `$sub'\\n\";\n";
+ t << " &usage();\n";
+ t << " }\n";
+ t << " elsif ( ! $quiet && $sub!=\"_doc\" && $sub!=\"_cgi\" )\n";
+ t << " {\n";
+ t << " print \"Substituting $subst{$sub} for each occurence of tag file $sub\\n\"; \n";
+ t << " }\n";
+ t << "}\n";
+ t << "\n";
+ t << "if ( ! @files ) {\n";
+ t << " if (opendir(D,\".\")) {\n";
+ t << " foreach $file ( readdir(D) ) {\n";
+ t << " $match = \".html\";\n";
+ t << " next if ( $file =~ /^\\.\\.?$/ );\n";
+ t << " ($file =~ /$match/) && (push @files, $file);\n";
+ t << " }\n";
+ t << " closedir(D);\n";
+ t << " }\n";
+ t << "}\n";
+ t << "\n";
+ t << "if ( ! @files ) {\n";
+ t << " print STDERR \"Warning: No input files given and non found!\\n\";\n";
+ t << "}\n";
+ t << "\n";
+ t << "foreach $f (@files)\n";
+ t << "{\n";
+ t << " if ( ! $quiet ) {\n";
+ t << " print \"Editing: $f...\\n\";\n";
+ t << " }\n";
+ t << " $oldf = $f;\n";
+ t << " $f .= \".bak\";\n";
+ t << " unless (rename $oldf,$f) {\n";
+ t << " print STDERR \"Error: cannot rename file $oldf\\n\";\n";
+ t << " exit 1;\n";
+ t << " }\n";
+ t << " if (open(F,\"<$f\")) {\n";
+ t << " unless (open(G,\">$oldf\")) {\n";
+ t << " print STDERR \"Error: opening file $oldf for writing\\n\";\n";
+ t << " exit 1;\n";
+ t << " }\n";
+ t << " while (<F>) {\n";
+ t << " s/doxygen\\=\\\"([^ \\\"\\:\\t\\>\\<]*)\\:([^ \\\"\\t\\>\\<]*)\\\" (href|src)=\\\"\\2/doxygen\\=\\\"$1:$subst{$1}\\\" \\3=\\\"$subst{$1}/g;\n";
+ t << " print G \"$_\";\n";
+ t << " }\n";
+ t << " } \n";
+ t << " else {\n";
+ t << " print STDERR \"Warning file $f does not exist\\n\";\n";
+ t << " }\n";
+ t << " unlink $f;\n";
+ t << "}\n";
+ t << "\n";
+ t << "sub usage {\n";
+ t << " print STDERR \"Usage: installdox [options] [html-file [html-file ...]]\\n\";\n";
+ t << " print STDERR \"Options:\\n\";\n";
+ t << " print STDERR \" -l tagfile\\@linkName tag file + URL or directory \\n\";\n";
+ t << " print STDERR \" -q Quiet mode\\n\\n\";\n";
+ t << " exit 1;\n";
+ t << "}\n";
+ }
+ else
+ {
+ err("Error: Cannot open file %s for writing\n",fileName.data());
+ }
+ f.close();
+ struct stat stat_struct;
+ stat(fileName,&stat_struct);
+#if !defined(_WIN32)
+ chmod(fileName,stat_struct.st_mode|S_IXUSR|S_IXGRP|S_IXOTH);
+#endif
+}
diff --git a/src/instdox.h b/src/instdox.h
new file mode 100644
index 0000000..a149310
--- /dev/null
+++ b/src/instdox.h
@@ -0,0 +1,22 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#ifndef INSTDOX_H
+#define INSTDOX_H
+
+extern void writeInstallScript();
+
+#endif
diff --git a/src/language.cpp b/src/language.cpp
new file mode 100644
index 0000000..f5e2dde
--- /dev/null
+++ b/src/language.cpp
@@ -0,0 +1,61 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#include "language.h"
+#include "translator_nl.h"
+#include "translator_se.h"
+#include "translator_cz.h"
+#include "translator_fr.h"
+#include "translator_it.h"
+#include <qstring.h>
+
+#define L_EQUAL(a) !stricmp(langName,a)
+
+Translator *theTranslator=0;
+
+bool setTranslator(const char *langName)
+{
+ if (L_EQUAL("english"))
+ {
+ theTranslator=new Translator;
+ }
+ else if (L_EQUAL("dutch"))
+ {
+ theTranslator=new TranslatorDutch;
+ }
+ else if (L_EQUAL("swedish"))
+ {
+ theTranslator=new TranslatorSwedish;
+ }
+ else if (L_EQUAL("czech"))
+ {
+ theTranslator=new TranslatorCzech;
+ }
+ else if (L_EQUAL("french"))
+ {
+ theTranslator=new TranslatorFrench;
+ }
+ else if (L_EQUAL("italian"))
+ {
+ theTranslator=new TranslatorItalian;
+ }
+ else // use the default language (i.e. english)
+ {
+ theTranslator=new Translator;
+ return FALSE;
+ }
+ return TRUE;
+}
diff --git a/src/language.h b/src/language.h
new file mode 100644
index 0000000..c18eaed
--- /dev/null
+++ b/src/language.h
@@ -0,0 +1,25 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#ifndef LANGUAGE_H
+#define LANGUAGE_H
+
+#include "translator.h"
+
+extern Translator *theTranslator;
+extern bool setTranslator(const char *languageName);
+
+#endif
diff --git a/src/latexgen.cpp b/src/latexgen.cpp
new file mode 100644
index 0000000..50ec496
--- /dev/null
+++ b/src/latexgen.cpp
@@ -0,0 +1,876 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#include <stdlib.h>
+#include <qdir.h>
+#include "latexgen.h"
+#include "config.h"
+#include "message.h"
+#include "doxygen.h"
+#include "util.h"
+#include "diagram.h"
+#include "language.h"
+
+//static QString escapeLabelName(const QString &s)
+//{
+// QString result;
+// uint i;
+// for (i=0;i<s.length();i++)
+// {
+// char c=s.at(i);
+// switch (c)
+// {
+// case '~': result+=".1"; break;
+// case '%': result+=".2"; break;
+// default: result+=c;
+// }
+// }
+// return result;
+//}
+
+
+LatexGenerator::LatexGenerator()
+ : OutputGenerator()
+{
+ dir=latexOutputDir;
+ col=0;
+}
+
+LatexGenerator::~LatexGenerator()
+{
+}
+
+//LatexGenerator::LatexGenerator(const LatexGenerator &g)
+// : OutputGenerator(g)
+//{
+// col=g.col;
+//}
+
+void LatexGenerator::append(const OutputGenerator *g)
+{
+ t << g->getContents();
+ col+=((LatexGenerator *)g)->col;
+}
+
+
+void LatexGenerator::init()
+{
+ QString dir=latexOutputDir;
+ QDir d(dir);
+ if (!d.exists() && !d.mkdir(dir))
+ {
+ err("Could not create output directory %s\n",dir.data());
+ exit(1);
+ }
+
+ QString fileName=dir+"/Makefile";
+ QFile file(fileName);
+ if (!file.open(IO_WriteOnly))
+ {
+ err("Could not open file %s for writing\n",fileName.data());
+ exit(1);
+ }
+ QTextStream t(&file);
+ t << "all: refman.dvi" << endl
+ << endl
+ << "ps: refman.ps" << endl
+ << endl
+ << "refman.ps: refman.dvi" << endl
+ << "\tdvips -o refman.ps refman.dvi" << endl
+ << endl
+ << "refman.dvi: refman.tex doxygen.sty" << endl
+ << "\techo \"Running latex...\"" << endl
+ << "\tlatex refman.tex" << endl
+ << "\techo \"Running makeindex...\"" << endl
+ << "\tmakeindex refman.idx" << endl
+ << "\techo \"Rerunning latex....\"" << endl
+ << "\tlatex refman.tex" << endl
+ << "clean:" << endl
+ << "\trm -f *.ps *.dvi *.aux *.toc *.idx *.ind *.ilg *.log" << endl;
+}
+
+void LatexGenerator::startFile(const char *name,const char *,bool)
+{
+ QString fileName=name;
+ if (fileName.right(4)!=".tex" && fileName.right(4)!=".sty") fileName+=".tex";
+ startPlainFile(fileName);
+}
+
+void LatexGenerator::endFile()
+{
+ endPlainFile();
+}
+
+//void LatexGenerator::writeIndex()
+//{
+// startFile("refman.tex");
+//}
+
+void LatexGenerator::startProjectNumber()
+{
+ t << "\\\\[1ex]\\large ";
+}
+
+void LatexGenerator::startIndexSection(IndexSections is)
+{
+ QString paperName;
+ switch (is)
+ {
+ case isTitlePageStart:
+ {
+ if (paperType=="a4wide") paperName="a4"; else paperName=paperType;
+ t << "\\documentclass[" << paperName << "paper]{";
+ if (compactLatexFlag) t << "article"; else t << "book";
+ t << "}\n";
+ if (paperType=="a4wide") t << "\\usepackage{a4wide}\n";
+ t << "\\usepackage{makeidx}\n"
+ "\\usepackage{fancyheadings}\n"
+ "\\usepackage{epsf}\n"
+ "\\usepackage{float}\n"
+ "\\usepackage{doxygen}\n";
+ if (!theTranslator->latexBabelPackage().isEmpty())
+ {
+ t << "\\usepackage{" << theTranslator->latexBabelPackage() << "}\n";
+ }
+ const char *s=extraPackageList.first();
+ while (s)
+ {
+ t << "\\usepackage{" << s << "}\n";
+ s=extraPackageList.next();
+ }
+ t << "\\makeindex\n"
+ "\\setcounter{tocdepth}{1}\n"
+ "\\setlength{\\footrulewidth}{0.4pt}\n"
+ "\\begin{document}\n"
+ "\\title{";
+ //docify(projectName);
+ //t << " Reference Manual";
+ //if (!projectNumber.isEmpty())
+ //{
+ // t << "\\\\[1ex]\\large ";
+ // docify(projectNumber);
+ //}
+ }
+ break;
+ case isTitlePageAuthor:
+ t << "}\n\\author{";
+ break;
+ case isModuleIndex:
+ if (compactLatexFlag) t << "\\section"; else t << "\\chapter";
+ t << "{"; //Module Index}\n"
+ break;
+ case isClassHierarchyIndex:
+ if (compactLatexFlag) t << "\\section"; else t << "\\chapter";
+ t << "{"; //Hierarchical Index}\n"
+ break;
+ case isCompoundIndex:
+ if (compactLatexFlag) t << "\\section"; else t << "\\chapter";
+ t << "{"; //Annotated Compound Index}\n"
+ break;
+ case isFileIndex:
+ if (compactLatexFlag) t << "\\section"; else t << "\\chapter";
+ t << "{"; //Annotated File Index}\n"
+ break;
+ case isModuleDocumentation:
+ {
+ GroupDef *gd=groupList.first();
+ bool found=FALSE;
+ while (gd && !found)
+ {
+ if (gd->hasDocumentation() || gd->countMembers()>0)
+ {
+ if (compactLatexFlag) t << "\\section"; else t << "\\chapter";
+ t << "{"; //Module Documentation}\n";
+ found=TRUE;
+ }
+ gd=groupList.next();
+ }
+ }
+ break;
+ case isClassDocumentation:
+ {
+ ClassDef *cd=classList.first();
+ bool found=FALSE;
+ while (cd && !found)
+ {
+ //if (cd->classFile()[0]!='@' && !cd->getReference() &&
+ // (cd->hasDocumentation() || !hideClassFlag) &&
+ // (cd->protection()!=Private || extractPrivateFlag)
+ // )
+
+ if (!cd->isReference() && cd->isVisible())
+ {
+ if (compactLatexFlag) t << "\\section"; else t << "\\chapter";
+ t << "{"; //Compound Documentation}\n";
+ found=TRUE;
+ }
+ cd=classList.next();
+ }
+ }
+ break;
+ case isFileDocumentation:
+ {
+ bool isFirst=TRUE;
+ FileName *fn=inputNameList.first();
+ while (fn)
+ {
+ FileDef *fd=fn->first();
+ while (fd)
+ {
+ if (fd->hasDocumentation() && !fd->isReference())
+ {
+ if (isFirst)
+ {
+ if (compactLatexFlag) t << "\\section"; else t << "\\chapter";
+ t << "{"; //File Documentation}\n";
+ isFirst=FALSE;
+ break;
+ }
+ }
+ fd=fn->next();
+ }
+ fn=inputNameList.next();
+ }
+ }
+ break;
+ case isExampleDocumentation:
+ {
+ if (compactLatexFlag) t << "\\section"; else t << "\\chapter";
+ t << "{"; //Example Documentation}\n";
+ }
+ break;
+ case isPageDocumentation:
+ {
+ if (compactLatexFlag) t << "\\section"; else t << "\\chapter";
+ t << "{"; //Page Documentation}\n";
+ }
+ break;
+ case isEndIndex:
+ break;
+ }
+}
+
+void LatexGenerator::endIndexSection(IndexSections is)
+{
+ switch (is)
+ {
+ case isTitlePageStart:
+ break;
+ case isTitlePageAuthor:
+ t << " Doxygen}\n"
+ "\\date{" << dateToString(TRUE) << "}\n"
+ "\\maketitle\n"
+ "\\pagenumbering{roman}\n";
+ if (!compactLatexFlag) t << "\\clearemptydoublepage\n";
+ t << "\\tableofcontents\n";
+ if (!compactLatexFlag) t << "\\clearemptydoublepage\n";
+ t << "\\pagenumbering{arabic}\n";
+ break;
+ case isModuleIndex:
+ t << "}\n\\input{modules}\n";
+ break;
+ case isClassHierarchyIndex:
+ t << "}\n\\input{hierarchy}\n";
+ break;
+ case isCompoundIndex:
+ t << "}\n\\input{annotated}\n";
+ break;
+ case isFileIndex:
+ t << "}\n\\input{files}\n";
+ break;
+ case isModuleDocumentation:
+ {
+ GroupDef *gd=groupList.first();
+ bool found=FALSE;
+ while (gd && !found)
+ {
+ if (gd->hasDocumentation() || gd->countMembers()>0)
+ {
+ t << "}\n\\input{" << gd->groupFile() << "}\n";
+ found=TRUE;
+ }
+ gd=groupList.next();
+ }
+ while (gd)
+ {
+ if (gd->hasDocumentation() || gd->countMembers()>0)
+ {
+ if (compactLatexFlag) t << "\\input"; else t << "\\include";
+ t << "{" << gd->groupFile() << "}\n";
+ }
+ gd=groupList.next();
+ }
+ }
+ break;
+ case isClassDocumentation:
+ {
+ ClassDef *cd=classList.first();
+ bool found=FALSE;
+ while (cd && !found)
+ {
+ //if (cd->classFile()[0]!='@' && !cd->getReference() &&
+ // (cd->hasDocumentation() || !hideClassFlag) &&
+ // (cd->protection()!=Private || extractPrivateFlag)
+ // )
+ if (!cd->isReference() && cd->isVisible())
+ {
+ t << "}\n\\input{" << cd->classFile() << "}\n";
+ found=TRUE;
+ }
+ cd=classList.next();
+ }
+ while (cd)
+ {
+ //if (cd->classFile()[0]!='@' && !cd->getReference() &&
+ // (cd->hasDocumentation() || !hideClassFlag) &&
+ // (cd->protection()!=Private || extractPrivateFlag)
+ // )
+ if (!cd->isReference() && cd->isVisible())
+ {
+ if (compactLatexFlag) t << "\\input"; else t << "\\include";
+ t << "{" << cd->classFile() << "}\n";
+ }
+ cd=classList.next();
+ }
+ }
+ break;
+ case isFileDocumentation:
+ {
+ bool isFirst=TRUE;
+ FileName *fn=inputNameList.first();
+ while (fn)
+ {
+ FileDef *fd=fn->first();
+ while (fd)
+ {
+ if (fd->hasDocumentation() && !fd->isReference())
+ {
+ if (isFirst)
+ {
+ t << "}\n\\input{" << fd->diskName() << "}\n";
+ isFirst=FALSE;
+ }
+ else
+ {
+ if (compactLatexFlag) t << "\\input" ; else t << "\\include";
+ t << "{" << fd->diskName() << "}\n";
+ }
+ }
+ fd=fn->next();
+ }
+ fn=inputNameList.next();
+ }
+ }
+ break;
+ case isExampleDocumentation:
+ {
+ t << "}\n";
+ PageInfo *pi=exampleList.first();
+ if (pi)
+ {
+ t << "\\input{" << convertSlashes(pi->name,TRUE) << "-example}\n";
+ pi=exampleList.next();
+ }
+ while (pi)
+ {
+ if (compactLatexFlag) t << "\\input" ; else t << "\\include";
+ t << "{" << convertSlashes(pi->name,TRUE) << "-example}\n";
+ pi=exampleList.next();
+ }
+ }
+ break;
+ case isPageDocumentation:
+ {
+ t << "}\n";
+ PageInfo *pi=pageList.first();
+ if (pi)
+ {
+ QString pageName;
+ if (caseSensitiveNames)
+ pageName=pi->name.copy();
+ else
+ pageName=pi->name.lower();
+ t << "\\input{" << pageName << "}\n";
+ pi=pageList.next();
+ }
+ while (pi)
+ {
+ if (compactLatexFlag) t << "\\input" ; else t << "\\include";
+ QString pageName;
+ if (caseSensitiveNames)
+ pageName=pi->name.copy();
+ else
+ pageName=pi->name.lower();
+ t << "{" << pageName << "}\n";
+ pi=pageList.next();
+ }
+ }
+ break;
+ case isEndIndex:
+ t << "\\printindex\n";
+ t << "\\end{document}\n";
+ break;
+ }
+}
+void LatexGenerator::writeStyleInfo(int part)
+{
+ switch(part)
+ {
+ case 0:
+ {
+ QString pname=projectName.stripWhiteSpace();
+ startPlainFile("doxygen.sty");
+ t << "\\NeedsTeXFormat{LaTeX2e}\n";
+ t << "\\ProvidesPackage{doxygen}\n";
+ t << "\\RequirePackage{calc}\n";
+ t << "\\RequirePackage{array}\n";
+ t << "\\pagestyle{fancyplain}\n";
+ t << "\\addtolength{\\headwidth}{\\marginparsep}\n";
+ t << "\\addtolength{\\headwidth}{\\marginparwidth}\n";
+ t << "\\newcommand{\\clearemptydoublepage}{\\newpage{\\pagestyle{empty}";
+ t << "\\cleardoublepage}}\n";
+ if (!compactLatexFlag)
+ t << "\\renewcommand{\\chaptermark}[1]{\\markboth{#1}{}}\n";
+ t << "\\renewcommand{\\sectionmark}[1]{\\markright{\\thesection\\ #1}}\n";
+ t << "\\lhead[\\fancyplain{}{\\bfseries\\thepage}]\n";
+ t << " {\\fancyplain{}{\\bfseries\\rightmark}}\n";
+ t << "\\rhead[\\fancyplain{}{\\bfseries\\leftmark}]\n";
+ t << " {\\fancyplain{}{\\bfseries\\thepage}}\n";
+ t << "\\rfoot[\\fancyplain{}{\\bfseries\\scriptsize ";
+ }
+ break;
+ case 1:
+ case 3:
+ t << " Doxygen ";
+ break;
+ case 2:
+ {
+ t << " Dimitri van Heesch \\copyright 1997-1999}]{}\n";
+ //QString dtString=dateToString(FALSE);
+ t << "\\lfoot[]{\\fancyplain{}{\\bfseries\\scriptsize ";
+ }
+ break;
+ case 4:
+ {
+ t << " Dimitri van Heesch \\copyright 1997-1999}}\n";
+ t << "\\cfoot{}\n";
+ t << "\\newenvironment{CompactList}\n";
+ t << "{\\begin{list}{}{\n";
+ t << " \\setlength{\\leftmargin}{0.5cm}\n";
+ t << " \\setlength{\\itemsep}{0pt}\n";
+ t << " \\setlength{\\parsep}{0pt}\n";
+ t << " \\setlength{\\topsep}{0pt}\n";
+ t << " \\renewcommand{\\makelabel}{}}}\n";
+ t << "{\\end{list}}\n";
+ t << "\\newenvironment{CompactItemize}\n";
+ t << "{\n";
+ t << " \\begin{itemize}\n";
+ t << " \\setlength{\\itemsep}{-4pt}\n";
+ t << " \\setlength{\\parsep}{0pt}\n";
+ t << " \\setlength{\\topsep}{0pt}\n";
+ t << " \\setlength{\\partopsep}{0pt}\n";
+ t << "}\n";
+ t << "{\\end{itemize}}\n";
+ t << "\\newcommand{\\PBS}[1]{\\let\\temp=\\\\#1\\let\\\\=\\temp}\n";
+ t << "\\newlength{\\tmplength}\n";
+ t << "\\newenvironment{TabularC}[1]\n";
+ t << "{\n";
+ t << "\\setlength{\\tmplength}\n";
+ t << " {\\linewidth/(#1)-\\tabcolsep*2-\\arrayrulewidth*(#1+1)/(#1)}\n";
+ t << " \\par\\begin{tabular*}{\\linewidth}\n";
+ t << " {*{#1}{|>{\\PBS\\raggedright\\hspace{0pt}}p{\\the\\tmplength}}|}\n";
+ t << "}\n";
+ t << "{\\end{tabular*}\\par}\n";
+ t << "\\newcommand{\\entrylabel}[1]{\n";
+ t << " {\\parbox[b]{\\labelwidth-4pt}{\\makebox[0pt][l]{\\textbf{#1}}\\\\}}}\n";
+ t << "\\newenvironment{Desc}\n";
+ t << "{\\begin{list}{}\n";
+ t << " {\n";
+ t << " \\settowidth{\\labelwidth}{40pt}\n";
+ t << " \\setlength{\\leftmargin}{\\labelwidth}\n";
+ t << " \\setlength{\\parsep}{0pt}\n";
+ t << " \\setlength{\\itemsep}{-4pt}\n";
+ t << " \\renewcommand{\\makelabel}{\\entrylabel}\n";
+ t << " }\n";
+ t << "}\n";
+ t << "{\\end{list}}\n";
+ t << "\\setlength{\\parindent}{0cm}\n";
+ t << "\\setlength{\\parskip}{0.2cm}\n";
+ t << "\\sloppy\n";
+ endPlainFile();
+ }
+ break;
+ }
+}
+
+void LatexGenerator::endTitleHead(const char *name)
+{
+ t << "}" << endl;
+ if (name)
+ {
+ t << "\\label{" << name << "}\\index{"
+ << name << "@{";
+ docify(name);
+ t << "}}";
+ }
+ t << endl;
+}
+
+void LatexGenerator::newParagraph()
+{
+ t << endl << endl;
+}
+
+void LatexGenerator::writeString(const char *text)
+{
+ t << text;
+}
+
+void LatexGenerator::writeIndexItem(const char *ref,const char *fn,
+ const char *name)
+{
+ t << "\\item ";
+ if (!ref && fn)
+ {
+ t << "\\contentsline{section}{";
+ docify(name);
+ t << "}{\\pageref{" << name << "}}" << endl;
+ }
+ else
+ docify(name);
+}
+
+//void LatexGenerator::writeIndexFileItem(const char *,const char *text)
+//{
+// t << "\\item\\contentsline{section}{";
+// docify(text);
+// t << "}{\\pageref{" << text << "}}" << endl;
+//}
+
+
+void LatexGenerator::writeHtmlLink(const char *url,const char *text)
+{
+ docify(text);
+ if (url)
+ {
+ // t << " {\\tt (";
+ // docify(url);
+ // t << ")}";
+ }
+}
+
+void LatexGenerator::writeStartAnnoItem(const char *,const char *,
+ const char *path,const char *name)
+{
+ t << "\\item\\contentsline{section}{{\\bf ";
+ if (path) docify(path);
+ docify(name);
+ t << "} ";
+}
+
+void LatexGenerator::writeEndAnnoItem(const char *name)
+{
+ t << "}{\\pageref{" << name << "}}" << endl;
+}
+
+//void LatexGenerator::writeClassLink(const char *,const char *,
+// const char *,const char *name)
+//{
+// t << "{\\bf ";
+// docify(name);
+// t << "}";
+//}
+
+void LatexGenerator::writeObjectLink(const char *, const char *,
+ const char *, const char *text)
+{
+ t << "{\\bf ";
+ docify(text);
+ t << "}";
+}
+
+void LatexGenerator::writePageRef(const char *clname, const char *anchor)
+{
+ t << " {\\rm (p. \\pageref{";
+ if (clname) t << clname;
+ if (anchor) t << "_" << anchor;
+ t << "})}";
+}
+
+void LatexGenerator::writeCodeLink(const char *,const char *,
+ const char *,const char *name)
+{
+ t << name;
+ col+=strlen(name);
+}
+
+
+void LatexGenerator::startTitle()
+{
+ if (compactLatexFlag) t << "\\subsection{"; else t << "\\section{";
+}
+
+void LatexGenerator::startGroupHeader()
+{
+ if (compactLatexFlag) t << "\\subsubsection*{"; else t << "\\subsection*{";
+}
+
+void LatexGenerator::endGroupHeader()
+{
+ t << "}" << endl;
+}
+
+void LatexGenerator::startMemberDoc(const char *clname,
+ const char *memname,const char *)
+{
+ t << "\\index{";
+ if (clname)
+ {
+ t << clname << "@{";
+ docify(clname);
+ t << "}!";
+ }
+ t << memname << "@{";
+ docify(memname);
+ t << "}}" << endl;
+
+ t << "\\index{" << memname << "@{";
+ docify(memname);
+ t << "}";
+ if (clname)
+ {
+ t << "!" << clname << "@{";
+ docify(clname);
+ t << "}";
+ }
+ t << "}" << endl;
+ //
+ if (compactLatexFlag) t << "\\subsubsection{"; else t << "\\subsection{";
+ t << "\\setlength{\\rightskip}{0pt plus 5cm}";
+}
+
+void LatexGenerator::writeDoxyAnchor(const char *clname,const char *anchor,const char *)
+{
+ t << "\\label{";
+ if (clname) t << clname;
+ if (anchor) t << "_" << anchor;
+ t << "}" << endl;
+}
+
+void LatexGenerator::addToIndex(const char *s1,const char *s2)
+{
+ if (s1)
+ {
+ t << "\\index{" << s1 << "@{";
+ docify(s1);
+ t << "}";
+ if (s2)
+ {
+ t << "!" << s2 << "@{";
+ docify(s2);
+ t << "}";
+ }
+ t << "}";
+ }
+}
+
+void LatexGenerator::writeSection(const char *lab,const char *title,bool sub)
+{
+ t << "\\";
+ if (sub) t << "subsection{"; else t << "section{";
+ docify(title);
+ t << "}\\label{" << lab << "}" << endl;
+}
+
+void LatexGenerator::writeSectionRef(const char *,const char *lab,
+ const char *)
+{
+ t << "\\ref{" << lab << "}";
+}
+
+void LatexGenerator::writeSectionRefItem(const char *,const char *lab,
+ const char *title)
+{
+ t << "\\contentsline{section}{";
+ docify(title);
+ t << "}{\\ref{" << lab << "}}" << endl;
+}
+
+//void LatexGenerator::docify(const char *str)
+//{
+// docifyStatic(t,str);
+//}
+
+//void LatexGenerator::docifyStatic(QTextStream &t,const char *str)
+void LatexGenerator::docify(const char *str)
+{
+ if (str)
+ {
+ const unsigned char *p=(const unsigned char *)str;
+ unsigned char c;
+ unsigned char pc='\0';
+ while (*p)
+ {
+ c=*p++;
+ switch(c)
+ {
+ case '#': t << "\\#"; break;
+ case '$': t << "\\$"; break;
+ case '%': t << "\\%"; break;
+ case '^': t << "$^\\wedge$"; break;
+ case '&': t << "\\&"; break;
+ case '*': t << "$\\ast$"; break;
+ case '_': t << "\\_\\-"; break;
+ case '{': t << "\\{"; break;
+ case '}': t << "\\}"; break;
+ case '<': t << "$<$"; break;
+ case '>': t << "$>$"; break;
+ case '|': t << "$|$"; break;
+ case '~': t << "$\\sim$"; break;
+ case '-': if (*p=='>')
+ { t << " $\\rightarrow$ "; p++; }
+ else
+ { t << (char)c; }
+ break;
+ case '\\': if (*p=='<')
+ { t << "$<$"; p++; }
+ else if (*p=='>')
+ { t << "$>$"; p++; }
+ else
+ { t << "$\\backslash$"; }
+ break;
+ // the Latin-1 characters
+ case 161: t << "!`"; break;
+ case 181: t << "$\\mu$"; break;
+ case 191: t << "?`"; break;
+ case 192: t << "\\`{A}"; break;
+ case 193: t << "\\'{A}"; break;
+ case 194: t << "\\^{A}"; break;
+ case 195: t << "\\~{A}"; break;
+ case 196: t << "\\\"{A}"; break;
+ case 197: t << "\\AA "; break;
+ case 198: t << "\\AE "; break;
+ case 199: t << "\\c{C}"; break;
+ case 200: t << "\\`{E}"; break;
+ case 201: t << "\\'{E}"; break;
+ case 202: t << "\\^{E}"; break;
+ case 203: t << "\\\"{E}"; break;
+ case 204: t << "\\`{I}"; break;
+ case 205: t << "\\'{I}"; break;
+ case 206: t << "\\^{I}"; break;
+ case 207: t << "\\\"{I}"; break;
+ case 208: t << "D "; break; // anyone know the real code?
+ case 209: t << "\\~{N}"; break;
+ case 210: t << "\\`{O}"; break;
+ case 211: t << "\\'{O}"; break;
+ case 212: t << "\\^{O}"; break;
+ case 213: t << "\\~{O}"; break;
+ case 214: t << "\\\"{O}"; break;
+ case 215: t << "$\\times$"; break;
+ case 216: t << "\\O"; break;
+ case 217: t << "\\`{U}"; break;
+ case 218: t << "\\'{U}"; break;
+ case 219: t << "\\^{U}"; break;
+ case 220: t << "\\\"{U}"; break;
+ case 221: t << "\\'{Y}"; break;
+ case 223: t << "\"s "; break; // assumes german package
+ case 224: t << "\\`{a}"; break;
+ case 225: t << "\\'{a}"; break;
+ case 226: t << "\\^{a}"; break;
+ case 227: t << "\\~{a}"; break;
+ case 228: t << "\\\"{a}"; break;
+ case 229: t << "\\aa "; break;
+ case 230: t << "\\ae "; break;
+ case 231: t << "\\c{c}"; break;
+ case 232: t << "\\`{e}"; break;
+ case 233: t << "\\'{e}"; break;
+ case 234: t << "\\^{e}"; break;
+ case 235: t << "\\\"{e}"; break;
+ case 236: t << "\\`{\\i}"; break;
+ case 237: t << "\\'{\\i}"; break;
+ case 238: t << "\\^{\\i}"; break;
+ case 239: t << "\\\"{\\i}"; break;
+ case 241: t << "\\~{n}"; break;
+ case 242: t << "\\`{o}"; break;
+ case 243: t << "\\'{o}"; break;
+ case 244: t << "\\^{o}"; break;
+ case 245: t << "\\~{o}"; break;
+ case 246: t << "\\\"{o}"; break;
+ case 248: t << "\\o "; break;
+ case 249: t << "\\`{u}"; break;
+ case 250: t << "\\'{u}"; break;
+ case 251: t << "\\^{u}"; break;
+ case 252: t << "\\\"{u}"; break;
+ case 253: t << "\\'{y}"; break;
+ case 255: t << "\\\"{y}"; break;
+
+ default:
+ if ((isupper(c) && islower(pc))
+ // ||
+ // (pc!=':' && c==':') ||
+ // (pc==':' && c!=':')
+ ) t << "\\-";
+ t << (char)c;
+ }
+ pc = c;
+ }
+ }
+}
+
+void LatexGenerator::codify(const char *str)
+{
+ static char spaces[]=" ";
+ if (str)
+ {
+ const char *p=str;
+ char c;
+ while (*p)
+ {
+ c=*p++;
+ switch(c)
+ {
+ case '\t': t << &spaces[col&7]; col+=8-(col&7); break;
+ case '\n': t << '\n'; col=0; break;
+ default: t << c; col++; break;
+ }
+ }
+ }
+}
+
+void LatexGenerator::writeChar(char c)
+{
+ char cs[2];
+ cs[0]=c;
+ cs[1]=0;
+ docify(cs);
+}
+
+void LatexGenerator::startClassDiagram()
+{
+ if (compactLatexFlag) t << "\\subsubsection*"; else t << "\\subsection*";
+ t << "{";
+}
+
+void LatexGenerator::endClassDiagram(ClassDiagram &d,
+ const char *fileName,const char *)
+{
+ d.writeFigure(t,dir,fileName);
+}
+
+void LatexGenerator::writeFormula(const char *,const char *text)
+{
+ t << text;
+}
diff --git a/src/latexgen.h b/src/latexgen.h
new file mode 100644
index 0000000..5a3dd1c
--- /dev/null
+++ b/src/latexgen.h
@@ -0,0 +1,178 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#ifndef OUTPUT_H
+#define OUTPUT_H
+
+#include "outputgen.h"
+
+class QFile;
+
+class LatexGenerator : public OutputGenerator
+{
+ public:
+ LatexGenerator();
+ ~LatexGenerator();
+
+ OutputGenerator *copy() { return new LatexGenerator; }
+ //OutputGenerator *clone() { return new LatexGenerator(*this); }
+ void append(const OutputGenerator *o);
+ void enable() { active=TRUE; }
+ void disable() { active=FALSE; }
+ void enableIf(OutputType o) { if (o==Latex) active=TRUE; }
+ void disableIf(OutputType o) { if (o==Latex) active=FALSE; }
+ void disableIfNot(OutputType o) { if (o!=Latex) active=FALSE; }
+ bool isEnabled(OutputType o) { return (o==Latex && active); }
+ OutputGenerator *get(OutputType o) { return (o==Latex) ? this : 0; }
+
+ static void init();
+ void startFile(const char *name,const char *title, bool external);
+ void writeFooter(int,bool) {}
+ void endFile();
+ void clearBuffer();
+
+ //void writeIndex();
+ void startIndexSection(IndexSections);
+ void endIndexSection(IndexSections);
+ void startProjectNumber();
+ void endProjectNumber() {}
+ void writeStyleInfo(int part);
+ void startTitleHead() { startTitle(); }
+ void startTitle();
+ void endTitleHead(const char *name);
+ void endTitle() { t << "}"; }
+
+ void newParagraph();
+ void writeString(const char *text);
+ void startIndexList() { t << "\\begin{CompactList}" << endl; }
+ void endIndexList() { t << "\\end{CompactList}" << endl; }
+ void startItemList() { t << "\\begin{CompactItemize}" << endl; }
+ void endItemList() { t << "\\end{CompactItemize}" << endl; }
+ void startEnumList() { t << "\\begin{enumerate}" << endl; }
+ void endEnumList() { t << "\\end{enumerate}" << endl; }
+ void writeIndexItem(const char *ref,const char *file,const char *name);
+ void docify(const char *text);
+ void codify(const char *text);
+ void writeObjectLink(const char *ref,const char *file,
+ const char *anchor,const char *text);
+ void writeCodeLink(const char *ref, const char *file,
+ const char *anchor,const char *text);
+ void startTextLink(const char *,const char *) {}
+ void endTextLink() {}
+ void writeHtmlLink(const char *,const char *);
+ void startTypewriter() { t << "{\\tt "; }
+ void endTypewriter() { t << "}"; }
+ void startGroupHeader();
+ void endGroupHeader();
+ void writeListItem() { t << "\\item " << endl; }
+
+ void startMemberHeader() { startGroupHeader(); }
+ void endMemberHeader() { endGroupHeader(); }
+ void startMemberList() { t << "\\begin{CompactItemize}" << endl; }
+ void endMemberList() { t << "\\end{CompactItemize}" << endl; }
+ void startMemberItem() { t << "\\item " << endl; }
+ void endMemberItem() { t << endl; }
+
+ void writeRuler() { t << "\\vspace{0.4cm}\\hrule\\vspace{0.2cm}"; }
+ void writeAnchor(const char *) {}
+ void startCodeFragment() { t << "\\small\\begin{verbatim}"; }
+ void endCodeFragment() { t << "\\end{verbatim}\\normalsize "; }
+ void writeBoldString(const char *text)
+ { t << "{\\bf "; docify(text); t << "}"; }
+ void startEmphasis() { t << "{\\em "; }
+ void endEmphasis() { t << "}"; }
+ void startBold() { t << "{\\bf "; }
+ void endBold() { t << "}"; }
+ void startDescription() { t << "\\begin{description}" << endl; }
+ void endDescription() { t << "\\end{description}" << endl; }
+ void startDescItem() { t << "\\item["; }
+ void endDescItem() { t << "]"; }
+ void lineBreak() { t << "\\par\n"; }
+ void startMemberDoc(const char *,const char *,const char *);
+ void endMemberDoc() { t << "}"; }
+ void writeDoxyAnchor(const char *,const char *,const char *);
+ void writeChar(char c);
+ void writeLatexSpacing() { t << "\\hspace{0.3cm}"; }
+ void writeStartAnnoItem(const char *type,const char *file,
+ const char *path,const char *name);
+ void writeEndAnnoItem(const char *name);
+ void startSubsection() { t << "\\subsection*{"; }
+ void endSubsection() { t << "}" << endl; }
+ void startSubsubsection() { t << "\\subsubsection*{"; }
+ void endSubsubsection() { t << "}" << endl; }
+ void startCenter() { t << "\\begin{center}" << endl; }
+ void endCenter() { t << "\\end{center}" << endl; }
+ void startSmall() { t << "\\footnotesize "; }
+ void endSmall() { t << "\\normalsize "; }
+ void startSubscript() { t << "$_{\\mbox{"; }
+ void endSubscript() { t << "}}$"; }
+ void startSuperscript() { t << "$^{\\mbox{"; }
+ void endSuperscript() { t << "}}$"; }
+ void startTable(int c) { t << "\\begin{TabularC}{" << c
+ << "}\n\\hline\n";
+ }
+ void endTable() { t << "\\\\\\hline\n\\end{TabularC}\n"; }
+ void nextTableRow() {}
+ void endTableRow() { t << "\\\\\\hline\n"; }
+ void nextTableColumn() { t << "&"; }
+ void endTableColumn() {}
+ void writeCopyright() { t << "\\copyright"; }
+ void writeQuote() { t << "''"; }
+ void writeUmlaut(char c) { if (c=='i') t << "\\\"{\\i}"; else
+ t << "\\\"{" << c << "}";
+ }
+ void writeAcute(char c) { if (c=='i') t << "\\'{\\i}"; else
+ t << "\\'{" << c << "}";
+ }
+ void writeGrave(char c) { if (c=='i') t << "\\`{\\i}"; else
+ t << "\\`{" << c << "}";
+ }
+ void writeCirc(char c) { if (c=='i') t << "\\^{\\i}"; else
+ t << "\\^{" << c << "}";
+ }
+ void writeTilde(char c) { t << "\\~{" << c << "}"; }
+ void startMemberDescription() { t << "\\begin{CompactList}\\small\\item\\em "; }
+ void endMemberDescription() { t << "\\item\\end{CompactList}"; }
+ void startDescList() { t << "\\begin{Desc}\\item["; }
+ void endDescTitle() { t << "]"; }
+ void writeDescItem() { t << "\\par "; }
+ void endDescList() { t << "\\end{Desc}"; }
+ void writeSection(const char *,const char *,bool);
+ void writeSectionRef(const char *,const char *,const char *);
+ void writeSectionRefItem(const char *,const char *,const char *);
+ void addToIndex(const char *,const char *);
+ void startIndent() {}
+ void endIndent() {}
+ void writeSynopsis() {}
+ //void generateExternalIndex() {}
+ void startClassDiagram();
+ void endClassDiagram(ClassDiagram &,const char *,const char *);
+ void startColorFont(uchar,uchar,uchar) {}
+ void endColorFont() {}
+ void writePageRef(const char *,const char *);
+ void startQuickIndexItem(const char *,const char *) {}
+ void endQuickIndexItem() {}
+ void writeFormula(const char *,const char *);
+
+ //static void docifyStatic(QTextStream &t,const char *str);
+
+ private:
+ LatexGenerator(const LatexGenerator &);
+ LatexGenerator &operator=(const LatexGenerator &);
+ int col;
+};
+
+#endif
diff --git a/src/logos.cpp b/src/logos.cpp
new file mode 100644
index 0000000..090309a
--- /dev/null
+++ b/src/logos.cpp
@@ -0,0 +1,519 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#include <qstring.h>
+#include <qfile.h>
+#include <stdio.h>
+
+unsigned char logo_data[] = {
+ 0x47, 0x49, 0x46, 0x38, 0x37, 0x61, 0x76, 0x00, 0x35, 0x00, 0xf7, 0x00,
+ 0x00, 0x31, 0x7b, 0x6b, 0x31, 0x7b, 0x73, 0x31, 0x84, 0x7b, 0x31, 0x84,
+ 0x84, 0x31, 0x8c, 0x7b, 0x31, 0x8c, 0x84, 0x31, 0x8c, 0x8c, 0x39, 0x7b,
+ 0x7b, 0x39, 0x84, 0x7b, 0x39, 0x84, 0x84, 0x39, 0x8c, 0x84, 0x39, 0x94,
+ 0x8c, 0x39, 0x94, 0x94, 0x39, 0x9c, 0x94, 0x42, 0x7b, 0x73, 0x42, 0x8c,
+ 0x84, 0x42, 0x94, 0x8c, 0x42, 0x9c, 0x8c, 0x42, 0x9c, 0x94, 0x42, 0xa5,
+ 0x9c, 0x4a, 0x5a, 0x5a, 0x4a, 0x84, 0x84, 0x4a, 0x8c, 0x84, 0x4a, 0x94,
+ 0x8c, 0x4a, 0x94, 0x94, 0x4a, 0x9c, 0x94, 0x4a, 0xa5, 0x94, 0x4a, 0xa5,
+ 0x9c, 0x4a, 0xa5, 0xa5, 0x52, 0x52, 0x52, 0x52, 0x73, 0x73, 0x52, 0x7b,
+ 0x7b, 0x52, 0x84, 0x84, 0x52, 0x94, 0x8c, 0x52, 0x9c, 0x94, 0x52, 0xa5,
+ 0x9c, 0x52, 0xad, 0xa5, 0x52, 0xb5, 0xad, 0x5a, 0x5a, 0x5a, 0x5a, 0x63,
+ 0x63, 0x5a, 0x6b, 0x6b, 0x5a, 0x7b, 0x7b, 0x5a, 0x8c, 0x84, 0x5a, 0x8c,
+ 0x8c, 0x5a, 0x94, 0x8c, 0x5a, 0x94, 0x94, 0x5a, 0x9c, 0x94, 0x5a, 0xa5,
+ 0x9c, 0x5a, 0xa5, 0xa5, 0x5a, 0xad, 0xa5, 0x5a, 0xb5, 0xad, 0x5a, 0xbd,
+ 0xb5, 0x63, 0x63, 0x63, 0x63, 0x6b, 0x6b, 0x63, 0x73, 0x73, 0x63, 0x7b,
+ 0x7b, 0x63, 0x84, 0x84, 0x63, 0x8c, 0x8c, 0x63, 0x94, 0x94, 0x63, 0xa5,
+ 0x9c, 0x63, 0xa5, 0xa5, 0x63, 0xad, 0xa5, 0x63, 0xb5, 0xad, 0x63, 0xb5,
+ 0xb5, 0x63, 0xbd, 0xbd, 0x6b, 0x6b, 0x6b, 0x6b, 0x73, 0x73, 0x6b, 0x7b,
+ 0x7b, 0x6b, 0x8c, 0x8c, 0x6b, 0x9c, 0x94, 0x6b, 0xa5, 0x9c, 0x6b, 0xad,
+ 0xa5, 0x6b, 0xb5, 0xad, 0x6b, 0xb5, 0xb5, 0x6b, 0xbd, 0xb5, 0x6b, 0xbd,
+ 0xbd, 0x6b, 0xc6, 0xbd, 0x6b, 0xc6, 0xc6, 0x6b, 0xce, 0xc6, 0x73, 0x73,
+ 0x73, 0x73, 0x7b, 0x7b, 0x73, 0x84, 0x84, 0x73, 0x8c, 0x8c, 0x73, 0x94,
+ 0x8c, 0x73, 0x94, 0x94, 0x73, 0x9c, 0x94, 0x73, 0x9c, 0x9c, 0x73, 0xa5,
+ 0x9c, 0x73, 0xa5, 0xa5, 0x73, 0xad, 0xad, 0x73, 0xb5, 0xad, 0x73, 0xb5,
+ 0xb5, 0x73, 0xbd, 0xbd, 0x73, 0xce, 0xce, 0x7b, 0x7b, 0x7b, 0x7b, 0x8c,
+ 0x8c, 0x7b, 0x94, 0x94, 0x7b, 0x9c, 0x9c, 0x7b, 0xa5, 0xa5, 0x7b, 0xb5,
+ 0xb5, 0x7b, 0xbd, 0xb5, 0x7b, 0xbd, 0xbd, 0x7b, 0xc6, 0xc6, 0x7b, 0xce,
+ 0xc6, 0x7b, 0xce, 0xce, 0x7b, 0xd6, 0xce, 0x7b, 0xd6, 0xd6, 0x7b, 0xde,
+ 0xd6, 0x84, 0x84, 0x84, 0x84, 0x8c, 0x8c, 0x84, 0x9c, 0x94, 0x84, 0x9c,
+ 0x9c, 0x84, 0xa5, 0x9c, 0x84, 0xad, 0xad, 0x84, 0xb5, 0xb5, 0x84, 0xc6,
+ 0xc6, 0x84, 0xce, 0xce, 0x84, 0xd6, 0xd6, 0x8c, 0x7b, 0x7b, 0x8c, 0x84,
+ 0x84, 0x8c, 0x8c, 0x8c, 0x8c, 0xa5, 0xa5, 0x8c, 0xad, 0xad, 0x8c, 0xb5,
+ 0xb5, 0x8c, 0xbd, 0xb5, 0x8c, 0xbd, 0xbd, 0x8c, 0xc6, 0xc6, 0x8c, 0xce,
+ 0xce, 0x8c, 0xde, 0xde, 0x94, 0x7b, 0x7b, 0x94, 0x94, 0x94, 0x94, 0x9c,
+ 0x9c, 0x94, 0xa5, 0xa5, 0x94, 0xad, 0xad, 0x94, 0xbd, 0xb5, 0x94, 0xc6,
+ 0xbd, 0x9c, 0x9c, 0x9c, 0x9c, 0xa5, 0xa5, 0x9c, 0xb5, 0xb5, 0x9c, 0xbd,
+ 0xbd, 0x9c, 0xc6, 0xbd, 0x9c, 0xc6, 0xc6, 0x9c, 0xce, 0xc6, 0x9c, 0xce,
+ 0xce, 0x9c, 0xd6, 0xd6, 0xa5, 0x5a, 0x5a, 0xa5, 0x63, 0x63, 0xa5, 0x84,
+ 0x84, 0xa5, 0x94, 0x94, 0xa5, 0xa5, 0xa5, 0xa5, 0xad, 0xa5, 0xa5, 0xbd,
+ 0xbd, 0xa5, 0xc6, 0xc6, 0xa5, 0xce, 0xce, 0xa5, 0xd6, 0xd6, 0xa5, 0xde,
+ 0xde, 0xa5, 0xe7, 0xde, 0xad, 0x21, 0x18, 0xad, 0x21, 0x21, 0xad, 0x52,
+ 0x52, 0xad, 0x63, 0x63, 0xad, 0x7b, 0x7b, 0xad, 0xad, 0xad, 0xad, 0xb5,
+ 0xb5, 0xad, 0xbd, 0xbd, 0xad, 0xce, 0xc6, 0xad, 0xce, 0xce, 0xad, 0xd6,
+ 0xce, 0xad, 0xd6, 0xd6, 0xb5, 0x21, 0x21, 0xb5, 0x52, 0x52, 0xb5, 0x5a,
+ 0x5a, 0xb5, 0x63, 0x63, 0xb5, 0x6b, 0x6b, 0xb5, 0xb5, 0xb5, 0xb5, 0xc6,
+ 0xc6, 0xb5, 0xce, 0xce, 0xb5, 0xd6, 0xce, 0xb5, 0xd6, 0xd6, 0xb5, 0xde,
+ 0xd6, 0xb5, 0xde, 0xde, 0xb5, 0xe7, 0xe7, 0xbd, 0x21, 0x21, 0xbd, 0x29,
+ 0x29, 0xbd, 0x42, 0x42, 0xbd, 0x52, 0x52, 0xbd, 0x73, 0x73, 0xbd, 0x7b,
+ 0x7b, 0xbd, 0x84, 0x84, 0xbd, 0xbd, 0xbd, 0xbd, 0xc6, 0xc6, 0xbd, 0xce,
+ 0xce, 0xbd, 0xd6, 0xd6, 0xbd, 0xde, 0xde, 0xc6, 0x39, 0x39, 0xc6, 0x73,
+ 0x73, 0xc6, 0x7b, 0x7b, 0xc6, 0x84, 0x84, 0xc6, 0x8c, 0x8c, 0xc6, 0x94,
+ 0x94, 0xc6, 0xc6, 0xc6, 0xc6, 0xce, 0xce, 0xc6, 0xd6, 0xd6, 0xc6, 0xde,
+ 0xde, 0xc6, 0xef, 0xe7, 0xce, 0x7b, 0x7b, 0xce, 0x8c, 0x8c, 0xce, 0x94,
+ 0x94, 0xce, 0xce, 0xce, 0xce, 0xd6, 0xd6, 0xce, 0xde, 0xde, 0xce, 0xe7,
+ 0xe7, 0xd6, 0x84, 0x84, 0xd6, 0x94, 0x8c, 0xd6, 0x94, 0x94, 0xd6, 0x9c,
+ 0x9c, 0xd6, 0xad, 0xad, 0xd6, 0xd6, 0xd6, 0xd6, 0xe7, 0xde, 0xd6, 0xef,
+ 0xef, 0xde, 0xa5, 0xa5, 0xde, 0xbd, 0xbd, 0xde, 0xce, 0xce, 0xde, 0xde,
+ 0xde, 0xde, 0xe7, 0xe7, 0xde, 0xef, 0xe7, 0xde, 0xef, 0xef, 0xe7, 0xbd,
+ 0xbd, 0xe7, 0xe7, 0xe7, 0xe7, 0xef, 0xef, 0xe7, 0xf7, 0xf7, 0xef, 0xd6,
+ 0xd6, 0xef, 0xef, 0xef, 0xef, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xff,
+ 0xf7, 0xf7, 0xff, 0xff, 0xff, 0xf7, 0xf7, 0xff, 0xff, 0xff, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x76, 0x00, 0x35, 0x00, 0x00, 0x08,
+ 0xfe, 0x00, 0xdd, 0x09, 0x1c, 0x48, 0xb0, 0xa0, 0xba, 0x45, 0x71, 0x76,
+ 0xc8, 0x29, 0xc8, 0xb0, 0xa1, 0xc3, 0x87, 0x10, 0x23, 0x4a, 0x9c, 0x48,
+ 0xb1, 0xa2, 0x3a, 0x74, 0xe4, 0xb4, 0x05, 0x10, 0x10, 0xa0, 0x48, 0xc5,
+ 0x8f, 0x20, 0x43, 0x8a, 0x1c, 0x59, 0x10, 0x5d, 0xb6, 0x5e, 0xae, 0x14,
+ 0x08, 0x10, 0xe0, 0x91, 0xa4, 0xcb, 0x97, 0x30, 0x43, 0xaa, 0xfb, 0xd6,
+ 0x4b, 0x50, 0x1b, 0x08, 0x1c, 0x8d, 0xc4, 0xdc, 0xc9, 0xb3, 0xe7, 0x40,
+ 0x75, 0xd9, 0x2a, 0x3d, 0x09, 0xb2, 0x40, 0xa5, 0x4e, 0x9f, 0x48, 0x93,
+ 0xca, 0x84, 0x86, 0xe8, 0x09, 0x8d, 0x05, 0x0b, 0x04, 0x1c, 0x55, 0x4a,
+ 0xb5, 0xaa, 0x43, 0x93, 0x88, 0x82, 0xd0, 0xb8, 0xb0, 0x60, 0xc0, 0x54,
+ 0xab, 0x60, 0xad, 0x02, 0xcd, 0x4a, 0x43, 0x42, 0xd4, 0x23, 0x61, 0xd3,
+ 0x56, 0x55, 0xc7, 0x34, 0x48, 0x8d, 0x0d, 0x10, 0x14, 0x60, 0x51, 0x4b,
+ 0x17, 0x29, 0x5b, 0xb2, 0x19, 0x24, 0x14, 0xf8, 0x5a, 0xb7, 0xaf, 0xcb,
+ 0xb1, 0x41, 0x4e, 0x60, 0x90, 0xa0, 0x00, 0xad, 0xdf, 0xc3, 0x24, 0xef,
+ 0x6a, 0xcd, 0xab, 0x80, 0x2f, 0xe2, 0xc7, 0x13, 0xd1, 0xb5, 0xad, 0x31,
+ 0xc2, 0xac, 0x61, 0xc8, 0x98, 0x1d, 0x5e, 0x64, 0xa6, 0xe9, 0x8f, 0x9f,
+ 0x38, 0x42, 0x68, 0x90, 0x20, 0x7c, 0x59, 0xa0, 0x3a, 0x75, 0xe0, 0x64,
+ 0x39, 0xfa, 0x03, 0xa9, 0x96, 0x39, 0x87, 0xe6, 0x82, 0x31, 0x04, 0x06,
+ 0xcc, 0xdd, 0xe9, 0x69, 0xb3, 0x50, 0x35, 0x54, 0x17, 0x2c, 0xd8, 0xeb,
+ 0x9f, 0xea, 0xd2, 0x2d, 0xcb, 0xc4, 0xa8, 0x14, 0x30, 0x69, 0xe1, 0xc0,
+ 0x81, 0x33, 0xa8, 0x4e, 0x1a, 0x26, 0x39, 0x87, 0x62, 0x95, 0x2b, 0xb8,
+ 0xae, 0x9c, 0xb4, 0x5f, 0xda, 0xd4, 0x4d, 0x3b, 0xe5, 0xa7, 0xd1, 0x34,
+ 0xcd, 0xe8, 0xc0, 0xfe, 0xbd, 0xda, 0xf2, 0x03, 0xc8, 0x92, 0x25, 0x40,
+ 0x62, 0xdc, 0xa8, 0xbc, 0xe0, 0xb2, 0x3a, 0x72, 0xdf, 0x0c, 0xbd, 0x28,
+ 0xf1, 0xc3, 0x89, 0x13, 0x26, 0x4d, 0x38, 0xa5, 0x13, 0x88, 0x51, 0x9b,
+ 0x26, 0x34, 0x4e, 0x7c, 0xf7, 0x1e, 0x39, 0xd2, 0x2c, 0x50, 0x00, 0x16,
+ 0xc9, 0x64, 0xb1, 0x80, 0x04, 0x1b, 0xfc, 0xe6, 0x0e, 0x46, 0x19, 0x95,
+ 0xc0, 0xe0, 0x21, 0x0f, 0x96, 0x13, 0x1f, 0x09, 0x25, 0x4c, 0x30, 0xc0,
+ 0x4a, 0x01, 0x74, 0x88, 0xc0, 0x7e, 0x17, 0x81, 0xe3, 0x0b, 0x16, 0x12,
+ 0x44, 0x10, 0x41, 0x89, 0x0f, 0x30, 0x72, 0x1a, 0x39, 0xe4, 0x44, 0xd3,
+ 0x61, 0x00, 0x71, 0x5c, 0x02, 0x01, 0x07, 0x24, 0x28, 0x70, 0x00, 0x85,
+ 0x25, 0x7d, 0x03, 0x4d, 0x1c, 0x1b, 0xc8, 0xf0, 0x43, 0x79, 0x33, 0xfc,
+ 0x20, 0x03, 0x09, 0x70, 0xb5, 0x67, 0x9b, 0x49, 0xbe, 0xec, 0x30, 0x01,
+ 0x09, 0x32, 0xe0, 0x77, 0x46, 0x13, 0x4d, 0x74, 0x51, 0xc7, 0x36, 0x26,
+ 0x21, 0x83, 0x49, 0x13, 0xf6, 0x9d, 0x61, 0x21, 0x32, 0xbd, 0xbc, 0xd0,
+ 0xd5, 0x02, 0x7a, 0xc4, 0xb1, 0xe0, 0x06, 0x8f, 0x98, 0xf6, 0x0d, 0x32,
+ 0xae, 0xf0, 0xc1, 0xc1, 0x06, 0x0b, 0x98, 0x42, 0xce, 0x49, 0x2e, 0x18,
+ 0xc0, 0xc1, 0x0c, 0x1c, 0x14, 0xc5, 0x51, 0x87, 0x56, 0xb4, 0x83, 0xce,
+ 0x99, 0x70, 0x44, 0xa0, 0x81, 0x06, 0x7e, 0x6a, 0xf0, 0x80, 0x02, 0x04,
+ 0x60, 0x71, 0x66, 0x2f, 0x89, 0x00, 0xb0, 0xd1, 0x03, 0x03, 0x48, 0x20,
+ 0x43, 0x09, 0x06, 0x0a, 0xb0, 0x0c, 0x41, 0x26, 0xf5, 0xf2, 0x06, 0x04,
+ 0x1b, 0x8c, 0x50, 0x82, 0x0c, 0x48, 0xf8, 0x30, 0xe4, 0x06, 0x66, 0xb5,
+ 0x77, 0x11, 0x34, 0xa2, 0xe4, 0xc0, 0xa0, 0x0c, 0x3e, 0x70, 0x91, 0x05,
+ 0x19, 0x67, 0x38, 0x81, 0x46, 0x17, 0xfe, 0x74, 0x64, 0xe3, 0x8a, 0x20,
+ 0x82, 0xf8, 0xe1, 0x04, 0x94, 0x87, 0xf4, 0x82, 0x88, 0x11, 0x05, 0x30,
+ 0x50, 0xc0, 0x0e, 0x6c, 0xe0, 0x01, 0x41, 0x03, 0x1b, 0xc4, 0x90, 0xce,
+ 0x7b, 0xba, 0xe2, 0x11, 0x03, 0xa8, 0x30, 0x9c, 0x59, 0x89, 0x0e, 0x0b,
+ 0xd2, 0x07, 0x43, 0x06, 0x76, 0x06, 0x70, 0x85, 0x36, 0xe5, 0x40, 0xe3,
+ 0x8a, 0x1b, 0x10, 0x44, 0x30, 0xc2, 0x08, 0x2c, 0x54, 0x91, 0x50, 0x04,
+ 0x0a, 0x04, 0x20, 0x46, 0x25, 0x6c, 0x44, 0xd1, 0xa1, 0x00, 0x0a, 0x2c,
+ 0xb0, 0xc1, 0x0c, 0x30, 0xb0, 0xa9, 0x40, 0x1c, 0x03, 0xed, 0xe9, 0x0a,
+ 0x1e, 0x17, 0x40, 0xc0, 0xe0, 0x0e, 0x37, 0xd0, 0x40, 0x03, 0x0a, 0x21,
+ 0x80, 0x6a, 0x99, 0x64, 0x95, 0x7c, 0xc1, 0xe0, 0x06, 0x24, 0x10, 0xa1,
+ 0x55, 0x10, 0x6e, 0xcc, 0xe1, 0x44, 0x1a, 0x6a, 0x68, 0x52, 0x89, 0x17,
+ 0x41, 0xb0, 0xe1, 0x47, 0x13, 0x3f, 0x94, 0xf0, 0x46, 0x14, 0x02, 0x8b,
+ 0xd0, 0x46, 0x10, 0x4f, 0x5c, 0x21, 0xc1, 0x04, 0x1b, 0xa0, 0x02, 0xd4,
+ 0xc4, 0x39, 0xac, 0x29, 0xc1, 0x22, 0x35, 0xe1, 0xa0, 0x2f, 0x07, 0x3f,
+ 0xe0, 0x70, 0xc2, 0x09, 0x29, 0xe0, 0x24, 0x40, 0x08, 0x6f, 0x8a, 0xc2,
+ 0x46, 0x08, 0x7e, 0xee, 0x30, 0x44, 0x10, 0x41, 0x78, 0x41, 0xc8, 0x05,
+ 0xe4, 0x12, 0x10, 0x45, 0x60, 0x2b, 0x25, 0x00, 0x81, 0x05, 0x28, 0x0c,
+ 0x91, 0xc5, 0x68, 0x0b, 0xbc, 0x60, 0x1a, 0x39, 0x35, 0xd9, 0xb0, 0xa0,
+ 0x04, 0x2d, 0xe0, 0xc1, 0x86, 0x53, 0x1d, 0x74, 0x10, 0x82, 0x04, 0x10,
+ 0xb4, 0xf7, 0x8d, 0x2b, 0x6c, 0x7c, 0x50, 0x02, 0x93, 0x57, 0x08, 0xb2,
+ 0x35, 0x0d, 0x41, 0xb4, 0x71, 0x46, 0x17, 0x69, 0xd0, 0x31, 0xca, 0x1d,
+ 0x40, 0xbf, 0x01, 0xa5, 0x0f, 0x9e, 0x62, 0x28, 0x81, 0xfe, 0x22, 0x78,
+ 0x68, 0x15, 0x85, 0x04, 0x19, 0x4c, 0xe0, 0x03, 0x39, 0xc8, 0xf4, 0xfd,
+ 0x02, 0xa8, 0x23, 0xf8, 0x32, 0xb1, 0x07, 0x0c, 0x6c, 0x50, 0x42, 0x18,
+ 0x5c, 0x9b, 0x90, 0x83, 0x4a, 0x01, 0x5c, 0x42, 0xb6, 0x10, 0x19, 0x8c,
+ 0x10, 0x43, 0x1e, 0x78, 0x38, 0x45, 0x44, 0x0f, 0x23, 0x68, 0x00, 0x41,
+ 0x11, 0x50, 0x98, 0x40, 0x41, 0x00, 0x08, 0x14, 0x80, 0x41, 0x10, 0x26,
+ 0x98, 0xf0, 0x84, 0x0f, 0xa0, 0x2a, 0xa0, 0x8e, 0x6d, 0x41, 0x3d, 0xe1,
+ 0xc0, 0x02, 0x79, 0x29, 0x82, 0x12, 0x22, 0x5e, 0xd0, 0xd0, 0x81, 0x07,
+ 0x70, 0x0d, 0xb0, 0x03, 0x32, 0x82, 0x04, 0x81, 0x00, 0x91, 0x89, 0xa3,
+ 0x29, 0x88, 0x53, 0x41, 0xf4, 0x01, 0xb7, 0x1a, 0xb0, 0x4c, 0xcc, 0x36,
+ 0x1c, 0x4c, 0x64, 0xbc, 0xc1, 0x06, 0x1c, 0x18, 0x02, 0x8d, 0xf4, 0x4f,
+ 0xe8, 0xc0, 0x01, 0x83, 0xa6, 0x4c, 0x7c, 0x03, 0x09, 0x13, 0x48, 0xd0,
+ 0x47, 0x2f, 0x77, 0xd0, 0x80, 0x40, 0x04, 0x24, 0xfc, 0x30, 0x0a, 0xef,
+ 0xfe, 0x46, 0xa1, 0x92, 0x00, 0x71, 0x2c, 0x9f, 0x02, 0x93, 0x5b, 0xb8,
+ 0x82, 0xc8, 0x17, 0x58, 0x54, 0x2f, 0xc3, 0x16, 0x97, 0x10, 0x85, 0x17,
+ 0x4c, 0x87, 0x00, 0x01, 0xec, 0xa5, 0x6f, 0x26, 0x08, 0xc2, 0xd3, 0x30,
+ 0x00, 0x81, 0xd9, 0xa1, 0xa3, 0x17, 0x7d, 0x4b, 0x80, 0x02, 0x24, 0xf0,
+ 0x82, 0x6f, 0xec, 0x09, 0x19, 0x4d, 0x31, 0xc1, 0x09, 0x44, 0x50, 0x94,
+ 0x1d, 0xb8, 0xc2, 0x0b, 0x6f, 0x81, 0x00, 0x04, 0xc6, 0x80, 0x11, 0x9a,
+ 0x14, 0x8f, 0x06, 0x60, 0x80, 0x58, 0x1a, 0x68, 0x41, 0x3c, 0xe6, 0x59,
+ 0x01, 0x08, 0x32, 0x00, 0xd5, 0x1e, 0x30, 0x02, 0x41, 0x7f, 0x49, 0x01,
+ 0x54, 0x13, 0xc8, 0x42, 0xf1, 0x0e, 0x27, 0x81, 0x11, 0x28, 0x43, 0x7a,
+ 0xfe, 0x15, 0x90, 0x40, 0xfb, 0xb4, 0x41, 0x3c, 0xad, 0x40, 0x61, 0x7e,
+ 0x55, 0x60, 0x43, 0x10, 0x58, 0x10, 0x03, 0x19, 0x2c, 0x42, 0x14, 0x79,
+ 0x50, 0xc2, 0x7d, 0x96, 0xc0, 0x07, 0x68, 0x64, 0x43, 0x80, 0x1a, 0x2c,
+ 0xe0, 0x02, 0xf6, 0x20, 0x40, 0x7f, 0x61, 0x01, 0x06, 0x60, 0x63, 0x87,
+ 0x3b, 0xc6, 0xd6, 0x3b, 0x05, 0xe8, 0x8b, 0x07, 0xb3, 0x7b, 0x0f, 0xd9,
+ 0x68, 0x70, 0x82, 0x10, 0x84, 0xad, 0x05, 0x42, 0x41, 0xc1, 0x02, 0x18,
+ 0x20, 0x81, 0x32, 0x3d, 0xa8, 0x76, 0x34, 0x88, 0x42, 0x17, 0xd6, 0xa0,
+ 0x06, 0x5a, 0x8c, 0x0d, 0x0f, 0xbe, 0xb3, 0xc1, 0xa3, 0x24, 0xa4, 0x8c,
+ 0x8b, 0xe0, 0xf1, 0x09, 0x2f, 0x20, 0x01, 0x09, 0x38, 0x10, 0x85, 0x1a,
+ 0x70, 0x80, 0x03, 0x25, 0xe8, 0x43, 0xed, 0x4c, 0x80, 0x03, 0x21, 0xce,
+ 0x20, 0x18, 0x57, 0x74, 0x0a, 0x0e, 0x0a, 0x50, 0x00, 0x01, 0x80, 0x81,
+ 0x62, 0x22, 0x68, 0x52, 0x19, 0xe4, 0x70, 0x2b, 0x27, 0x94, 0xe1, 0x12,
+ 0xd9, 0xb0, 0x50, 0x17, 0x6b, 0xa0, 0x12, 0x08, 0x1c, 0xc2, 0x17, 0x80,
+ 0xa4, 0x01, 0x16, 0x48, 0x90, 0x81, 0x06, 0x8e, 0x51, 0x14, 0x4e, 0x79,
+ 0x00, 0xe0, 0x46, 0xb0, 0x9f, 0x07, 0x15, 0x91, 0x06, 0x1b, 0xa8, 0xa5,
+ 0x0b, 0xb2, 0x72, 0x82, 0xca, 0x48, 0x00, 0x09, 0x53, 0x5b, 0x23, 0x15,
+ 0xba, 0xc0, 0x4c, 0x66, 0x48, 0x86, 0x98, 0x48, 0x80, 0xe1, 0x06, 0x1a,
+ 0xd0, 0x83, 0x63, 0x51, 0x2d, 0x96, 0x37, 0xc4, 0xde, 0x0a, 0x54, 0x80,
+ 0xbd, 0x0d, 0x48, 0x03, 0x8f, 0x43, 0x10, 0xe2, 0x0f, 0xcc, 0x10, 0xbd,
+ 0x27, 0xdc, 0x20, 0x03, 0x0a, 0x28, 0xc0, 0x02, 0x06, 0xe1, 0x94, 0x22,
+ 0xd4, 0x87, 0x0b, 0x50, 0x72, 0xc2, 0x2b, 0xc9, 0x71, 0x1a, 0x32, 0xd2,
+ 0xc0, 0x06, 0xe9, 0xfe, 0x5c, 0xc0, 0x22, 0x7e, 0x39, 0x4b, 0xb8, 0xcc,
+ 0xee, 0x1b, 0x42, 0xa1, 0x41, 0x0a, 0x32, 0x40, 0xd0, 0x49, 0xb1, 0x43,
+ 0x32, 0x82, 0x10, 0x68, 0x06, 0xd8, 0xb4, 0x03, 0xb2, 0xb8, 0x80, 0x41,
+ 0x24, 0xd8, 0x86, 0x40, 0xec, 0xb9, 0x05, 0x66, 0xa2, 0xc1, 0x1c, 0xcf,
+ 0x7c, 0x82, 0x11, 0x96, 0x10, 0xa4, 0x35, 0x4d, 0x80, 0x0c, 0x0f, 0x62,
+ 0x8a, 0x53, 0x9e, 0x30, 0x82, 0x0d, 0x2c, 0x09, 0x7b, 0x13, 0x18, 0xc3,
+ 0x4c, 0xd6, 0x18, 0x04, 0x2b, 0x38, 0x6e, 0x06, 0x40, 0x40, 0xc2, 0xe1,
+ 0x20, 0x60, 0x00, 0x05, 0x5c, 0x22, 0x2b, 0x94, 0xc4, 0x8f, 0x7d, 0xe6,
+ 0xf0, 0x8a, 0x6c, 0xd0, 0xb3, 0x9e, 0x1f, 0xa4, 0x81, 0x10, 0xbe, 0xc4,
+ 0x08, 0x68, 0x9c, 0xd0, 0x08, 0x23, 0x10, 0xa1, 0x18, 0xc9, 0xd1, 0x45,
+ 0x1b, 0x2c, 0x74, 0x03, 0x3d, 0x28, 0x07, 0xb2, 0xda, 0x60, 0x83, 0x92,
+ 0xc2, 0x65, 0x07, 0x01, 0xc5, 0x81, 0x22, 0x65, 0x50, 0x86, 0x72, 0x98,
+ 0x44, 0x28, 0x56, 0xc0, 0x92, 0x1a, 0x38, 0xb1, 0x52, 0x3c, 0x50, 0xe1,
+ 0x56, 0x4b, 0x38, 0xc2, 0x16, 0x1c, 0xc7, 0x81, 0x4c, 0xb0, 0x83, 0x26,
+ 0x6c, 0x60, 0x23, 0x0e, 0x48, 0x36, 0x01, 0x92, 0x6d, 0x60, 0x19, 0xed,
+ 0x28, 0x47, 0x0b, 0x69, 0xf0, 0x84, 0x22, 0xf4, 0xe8, 0x51, 0xdf, 0x33,
+ 0x4b, 0x29, 0x26, 0x79, 0x82, 0x24, 0x70, 0xe1, 0x0c, 0x65, 0x80, 0xc6,
+ 0x37, 0xc8, 0x81, 0x8e, 0xd3, 0xa0, 0x02, 0x13, 0x4d, 0x2d, 0xca, 0x02,
+ 0x1a, 0x61, 0x54, 0xad, 0xe8, 0x40, 0x60, 0xb3, 0x23, 0x5c, 0x2c, 0x5d,
+ 0x60, 0x55, 0x1f, 0x98, 0xc2, 0x17, 0x89, 0x98, 0x02, 0x06, 0xbe, 0x75,
+ 0xbd, 0x23, 0x04, 0x55, 0x08, 0x89, 0x64, 0x92, 0x19, 0x50, 0x71, 0x89,
+ 0x37, 0x64, 0x81, 0x09, 0xae, 0x4a, 0xfe, 0xc3, 0x34, 0x08, 0x27, 0x88,
+ 0x2f, 0x38, 0x81, 0x99, 0x4b, 0x10, 0x42, 0x1b, 0x62, 0x18, 0x03, 0x0e,
+ 0x48, 0xe3, 0x99, 0xac, 0x3b, 0x41, 0x8f, 0x38, 0x30, 0x81, 0x12, 0x24,
+ 0xc1, 0x4c, 0x64, 0x5b, 0x18, 0xc2, 0xce, 0x26, 0xb0, 0x01, 0xf0, 0x81,
+ 0x8c, 0xad, 0x33, 0x02, 0x96, 0x9a, 0xa0, 0x09, 0x6d, 0x64, 0x23, 0x1a,
+ 0xca, 0x80, 0x04, 0x13, 0xb8, 0x30, 0x8a, 0xde, 0x0d, 0x75, 0x00, 0x05,
+ 0xa0, 0xec, 0x09, 0x75, 0x20, 0x01, 0xb0, 0x39, 0x50, 0xa4, 0x34, 0xc0,
+ 0xc1, 0x08, 0x14, 0xb9, 0x5e, 0x84, 0x2d, 0x52, 0x91, 0x24, 0x88, 0x81,
+ 0x16, 0x7e, 0x29, 0x05, 0x12, 0xc0, 0x94, 0x09, 0x5d, 0x40, 0x03, 0x80,
+ 0xcc, 0x80, 0xa5, 0x4d, 0x90, 0x63, 0x7b, 0x51, 0xe0, 0x82, 0x7e, 0xbb,
+ 0x10, 0x06, 0xb6, 0x89, 0x01, 0x08, 0x68, 0x90, 0x41, 0x0c, 0xc4, 0x31,
+ 0x36, 0x36, 0x98, 0xa0, 0x03, 0x20, 0x60, 0x6e, 0x09, 0x64, 0x51, 0xaf,
+ 0xed, 0xf5, 0x2e, 0x05, 0x23, 0x58, 0x81, 0x07, 0x50, 0xa0, 0x82, 0x5a,
+ 0x72, 0xb2, 0x14, 0x45, 0x34, 0x81, 0x10, 0xe0, 0xc9, 0x85, 0x2e, 0xa8,
+ 0x81, 0x0e, 0x5c, 0x60, 0xc2, 0x76, 0x65, 0x50, 0x08, 0xef, 0xa6, 0x53,
+ 0x01, 0x45, 0x1d, 0x6f, 0x2d, 0x6d, 0x39, 0x13, 0x08, 0xfa, 0x0d, 0x06,
+ 0xf0, 0x25, 0x99, 0x22, 0x79, 0x80, 0x63, 0x12, 0x6c, 0xa1, 0xc1, 0x5a,
+ 0xc1, 0x41, 0x12, 0x96, 0x60, 0xd1, 0x34, 0xa0, 0x01, 0x4b, 0x9a, 0xc8,
+ 0x19, 0x1b, 0xb4, 0x90, 0x86, 0x34, 0x74, 0xc1, 0x11, 0xcb, 0xe3, 0xeb,
+ 0x0e, 0x0e, 0x56, 0x06, 0x74, 0x14, 0xb1, 0x03, 0x27, 0x28, 0x01, 0x07,
+ 0x30, 0xe0, 0x83, 0xd9, 0x99, 0xa9, 0x26, 0x78, 0xf8, 0x42, 0x1b, 0x28,
+ 0x66, 0x02, 0x1a, 0x7c, 0x61, 0x04, 0x45, 0xe1, 0xc1, 0xfe, 0x15, 0x7b,
+ 0x87, 0xc2, 0x2d, 0x60, 0x09, 0x40, 0x4e, 0x48, 0x31, 0x13, 0xca, 0xa0,
+ 0x08, 0xef, 0x1a, 0x08, 0x02, 0xe2, 0xd5, 0x0a, 0x0b, 0x82, 0x89, 0x81,
+ 0x75, 0xf0, 0xe7, 0x8a, 0x4a, 0xbc, 0xe7, 0x0a, 0x60, 0xf0, 0x3d, 0x0c,
+ 0x94, 0x60, 0x05, 0x35, 0x90, 0x81, 0xa2, 0xfd, 0x40, 0x30, 0x25, 0x02,
+ 0xad, 0x08, 0x5c, 0x00, 0x44, 0x1d, 0xd2, 0xd0, 0x84, 0x3e, 0x00, 0x83,
+ 0x45, 0x2d, 0x94, 0x42, 0x16, 0xd4, 0x00, 0x88, 0x68, 0xd4, 0x64, 0x28,
+ 0x82, 0x50, 0xf4, 0x23, 0xc4, 0x71, 0x32, 0xd6, 0xa5, 0x40, 0xcb, 0x13,
+ 0xd0, 0x04, 0x41, 0x46, 0xd5, 0x0b, 0x52, 0xf4, 0xa2, 0x17, 0xa2, 0x88,
+ 0xf2, 0x13, 0xc2, 0x00, 0x95, 0x0d, 0x80, 0x83, 0x29, 0x14, 0x0b, 0xc2,
+ 0x10, 0xb0, 0xe0, 0x2a, 0xb4, 0x72, 0x21, 0x13, 0xda, 0x58, 0xe3, 0x10,
+ 0x8a, 0x22, 0x01, 0xf1, 0x0a, 0x21, 0x08, 0x3a, 0x58, 0x68, 0x06, 0xbc,
+ 0x1c, 0xd2, 0x59, 0x79, 0x61, 0x28, 0x42, 0xc0, 0x01, 0x11, 0xa8, 0xf0,
+ 0x05, 0x2f, 0xb0, 0x81, 0x10, 0xaf, 0x20, 0x47, 0x3b, 0x46, 0xe5, 0x6c,
+ 0x68, 0x4f, 0x21, 0x0e, 0x7a, 0x18, 0x85, 0x4f, 0xdf, 0xb3, 0x3d, 0x3c,
+ 0xdc, 0xa1, 0x12, 0xbf, 0xa0, 0x92, 0xac, 0xd4, 0x36, 0x08, 0x52, 0x44,
+ 0x23, 0x8d, 0x93, 0xe4, 0xc1, 0x90, 0x48, 0x30, 0x1d, 0x4a, 0xc1, 0x67,
+ 0xb1, 0x6f, 0xba, 0x17, 0xd0, 0xc0, 0x90, 0x97, 0x11, 0x6c, 0x83, 0x70,
+ 0x95, 0xc0, 0x43, 0xae, 0xa1, 0x60, 0x85, 0x2c, 0xc4, 0x81, 0x11, 0xd1,
+ 0xc0, 0x88, 0xb3, 0xdb, 0x10, 0x07, 0x4c, 0x28, 0x23, 0x1c, 0x41, 0x61,
+ 0x83, 0x17, 0xc4, 0xb0, 0x08, 0x60, 0x7c, 0xe7, 0x27, 0x55, 0x12, 0x05,
+ 0x22, 0x68, 0x85, 0x08, 0x51, 0xb8, 0x42, 0x14, 0x95, 0x10, 0x45, 0x2f,
+ 0xfe, 0xb2, 0xd1, 0xd8, 0x15, 0x65, 0x03, 0x4d, 0x88, 0xd8, 0x78, 0xc7,
+ 0x91, 0x31, 0x6e, 0x43, 0xc2, 0xda, 0x15, 0xc8, 0xb0, 0xe0, 0x7b, 0x64,
+ 0xe5, 0x0a, 0x57, 0x44, 0xe3, 0xa7, 0x19, 0xbd, 0x81, 0x0c, 0x66, 0x50,
+ 0x02, 0x48, 0xb0, 0xa3, 0x1d, 0x18, 0xc7, 0x88, 0x3a, 0x32, 0x31, 0x0d,
+ 0xe0, 0xd2, 0xa0, 0x08, 0xc8, 0x13, 0x07, 0x46, 0xb4, 0x55, 0x09, 0x41,
+ 0xe0, 0x01, 0x0f, 0x82, 0xb0, 0xc4, 0xc8, 0x19, 0xfb, 0x5f, 0x8d, 0x8b,
+ 0x02, 0x19, 0xf4, 0xb4, 0x57, 0x25, 0x2a, 0xe1, 0x8a, 0x6f, 0x30, 0xfb,
+ 0x48, 0xe4, 0xf0, 0x86, 0x31, 0x8a, 0xc1, 0x0b, 0x5e, 0xec, 0x82, 0x17,
+ 0xc5, 0x28, 0xc6, 0xd8, 0x8b, 0xe1, 0x8c, 0x67, 0x5c, 0xe3, 0xed, 0x6f,
+ 0x7f, 0x86, 0x31, 0x8c, 0x61, 0xf6, 0x5d, 0xa4, 0xdd, 0x19, 0xd6, 0xb8,
+ 0x46, 0xde, 0xad, 0xf1, 0x8c, 0x63, 0xa8, 0x1d, 0xef, 0x7b, 0x97, 0xfb,
+ 0xdc, 0xf1, 0x0e, 0x77, 0x5e, 0xd0, 0x8d, 0x07, 0x40, 0xf8, 0xc1, 0x0c,
+ 0xa4, 0x41, 0x0e, 0xbd, 0x57, 0xe3, 0xf1, 0xdd, 0xb0, 0xa2, 0x29, 0x8c,
+ 0x2b, 0x8d, 0x22, 0xde, 0xc0, 0x53, 0x25, 0x58, 0x02, 0x39, 0xb0, 0x41,
+ 0x0c, 0x62, 0xe8, 0xa2, 0x15, 0xac, 0x08, 0x3d, 0x2b, 0x5a, 0x31, 0x8c,
+ 0xce, 0x37, 0xc3, 0xf3, 0xad, 0x48, 0x7d, 0xe9, 0x4f, 0xaf, 0x8b, 0xcf,
+ 0x93, 0xbe, 0x19, 0xd4, 0xb0, 0x06, 0xd0, 0x6d, 0xf3, 0xa6, 0x5e, 0xe8,
+ 0xe2, 0x16, 0xb7, 0x48, 0x05, 0xee, 0x77, 0xbf, 0x7b, 0xdd, 0xf3, 0x1e,
+ 0xf7, 0xb6, 0xe0, 0x7d, 0xf0, 0x6d, 0x11, 0xfc, 0xdd, 0x0f, 0xdf, 0xf8,
+ 0xb7, 0x20, 0xfe, 0xf1, 0x81, 0x8f, 0x8b, 0x27, 0x0c, 0x01, 0x08, 0x30,
+ 0x2d, 0x03, 0x32, 0x8c, 0x41, 0xfc, 0x54, 0xd8, 0x22, 0x15, 0xc2, 0xa8,
+ 0x44, 0x21, 0x7e, 0xfe, 0x34, 0x03, 0x19, 0x64, 0x21, 0x0c, 0x3a, 0xe0,
+ 0xfe, 0x0f, 0x58, 0x76, 0xfd, 0x54, 0x98, 0xff, 0xfc, 0xe8, 0x37, 0xbf,
+ 0x27, 0xd0, 0xef, 0x89, 0xf6, 0xbb, 0xff, 0xfd, 0x9e, 0xe8, 0x44, 0x2e,
+ 0xce, 0xf1, 0x20, 0x9a, 0x80, 0x7c, 0x12, 0x91, 0xf8, 0x84, 0xfe, 0xf3,
+ 0xff, 0x89, 0xfc, 0x47, 0x42, 0x15, 0xfd, 0x07, 0x80, 0xfe, 0x07, 0x80,
+ 0xfb, 0xb7, 0x0a, 0x91, 0x60, 0x80, 0xab, 0x00, 0x0a, 0x0a, 0xb8, 0x80,
+ 0x0c, 0xd8, 0x80, 0xa0, 0xc0, 0x0a, 0xad, 0xd7, 0x0a, 0x81, 0xa0, 0x40,
+ 0x5d, 0x00, 0x25, 0x8a, 0x50, 0x09, 0xa1, 0x00, 0x0a, 0xad, 0xa0, 0x0b,
+ 0x9e, 0x07, 0x0a, 0x76, 0xc0, 0x06, 0x5c, 0x90, 0x78, 0x42, 0x12, 0x24,
+ 0xe6, 0x01, 0x04, 0x5c, 0x60, 0x09, 0x94, 0x10, 0x09, 0x0a, 0x28, 0x09,
+ 0xa0, 0x10, 0x09, 0x91, 0x20, 0x09, 0x2a, 0xf8, 0x82, 0x32, 0x08, 0x83,
+ 0x30, 0x38, 0x83, 0x92, 0x70, 0x83, 0x1a, 0xc8, 0x0b, 0xcf, 0xc0, 0x0d,
+ 0xd7, 0x30, 0x0e, 0xb6, 0xa1, 0x23, 0xae, 0x50, 0x09, 0x88, 0xb0, 0x75,
+ 0x89, 0xb0, 0x75, 0x5b, 0x37, 0x84, 0x46, 0x58, 0x09, 0x45, 0x68, 0x84,
+ 0x4b, 0x98, 0x84, 0x44, 0x28, 0x84, 0x50, 0x58, 0x84, 0x43, 0x38, 0x84,
+ 0x52, 0x58, 0x84, 0x22, 0xd7, 0x0b, 0x13, 0x33, 0x04, 0x50, 0xd2, 0x04,
+ 0x73, 0x00, 0x6b, 0x56, 0xd8, 0x0b, 0xd0, 0x80, 0x0c, 0x13, 0x13, 0x04,
+ 0x42, 0x90, 0x05, 0x4d, 0x00, 0x7d, 0x4b, 0xb0, 0x85, 0x3c, 0x05, 0x72,
+ 0x4e, 0xd8, 0x86, 0x6e, 0xc8, 0x86, 0x4e, 0xe8, 0x71, 0x31, 0xd7, 0x4b,
+ 0xfc, 0xf1, 0x26, 0xd0, 0x10, 0x86, 0xc8, 0x90, 0x87, 0x7a, 0x88, 0x87,
+ 0x7a, 0xd8, 0x87, 0x79, 0x18, 0x86, 0x80, 0x88, 0x0c, 0x81, 0x18, 0x86,
+ 0xc9, 0x80, 0x87, 0x84, 0x68, 0x88, 0xbf, 0x82, 0x78, 0x87, 0xba, 0xf2,
+ 0x04, 0x60, 0x50, 0x06, 0x73, 0xd0, 0x05, 0xc0, 0x90, 0x0d, 0x77, 0x78,
+ 0x87, 0xda, 0xf0, 0x0d, 0x27, 0x21, 0x08, 0xb9, 0x86, 0x03, 0x47, 0x90,
+ 0x86, 0x4d, 0xe0, 0x07, 0xb2, 0x60, 0x89, 0x92, 0x38, 0x89, 0xa2, 0x38,
+ 0x8a, 0xa4, 0x58, 0x8a, 0x77, 0x98, 0x0d, 0x8b, 0xf5, 0x75, 0x47, 0x82,
+ 0x0e, 0xac, 0xd8, 0x8a, 0xae, 0xf8, 0x8a, 0xb0, 0x18, 0x8b, 0xb2, 0x38,
+ 0x8b, 0xac, 0x58, 0x75, 0xb4, 0x22, 0x0a, 0x24, 0x77, 0x1a, 0xaf, 0x78,
+ 0x11, 0x34, 0xd1, 0x74, 0x12, 0x17, 0x2c, 0x95, 0x30, 0x72, 0xac, 0x78,
+ 0x11, 0xb0, 0x48, 0x8c, 0xc6, 0x38, 0x8c, 0x8d, 0x95, 0x8c, 0xe9, 0x90,
+ 0x8c, 0x17, 0xd1, 0x8c, 0xaa, 0xb8, 0x6a, 0x03, 0xd1, 0x0e, 0x62, 0x34,
+ 0x7b, 0x11, 0xf1, 0x8c, 0x32, 0xf1, 0x5f, 0x79, 0x38, 0x6e, 0x9a, 0x31,
+ 0x73, 0x68, 0x52, 0x73, 0x82, 0xc8, 0x58, 0xd4, 0x98, 0x19, 0x69, 0x71,
+ 0x11, 0x2c, 0x82, 0x0e, 0xe1, 0xb8, 0x1b, 0xb5, 0x58, 0x8e, 0x8d, 0x25,
+ 0x8e, 0xec, 0xd8, 0x8e, 0xee, 0xf8, 0x8e, 0xf0, 0x18, 0x8f, 0xf2, 0x38,
+ 0x8f, 0xf4, 0x58, 0x8f, 0xf6, 0x78, 0x8f, 0xf8, 0x98, 0x8f, 0xfa, 0xb8,
+ 0x8f, 0xfc, 0xd8, 0x8f, 0xfe, 0xf8, 0x8f, 0x00, 0x19, 0x90, 0x02, 0x39,
+ 0x90, 0x04, 0xb9, 0x8f, 0x01, 0x01, 0x00, 0x3b
+};
+const unsigned int logo_len = 3536;
+
+unsigned char search_data[] = {
+ 0x47, 0x49, 0x46, 0x38, 0x39, 0x61, 0x78, 0x00, 0x1a, 0x00, 0xe7, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x01, 0x4c, 0x01, 0x01, 0x4c, 0x00,
+ 0x02, 0x4c, 0x01, 0x02, 0x4c, 0x02, 0x01, 0x63, 0x01, 0x02, 0x63, 0x02,
+ 0x02, 0x63, 0x01, 0x04, 0x63, 0x02, 0x04, 0x63, 0x04, 0x04, 0x63, 0x04,
+ 0x07, 0x72, 0x02, 0x04, 0x72, 0x04, 0x04, 0x72, 0x04, 0x07, 0x72, 0x07,
+ 0x07, 0x72, 0x04, 0x09, 0x72, 0x07, 0x09, 0x7d, 0x07, 0x09, 0x7d, 0x09,
+ 0x09, 0x7d, 0x09, 0x0d, 0x87, 0x09, 0x0d, 0x87, 0x09, 0x11, 0x87, 0x0d,
+ 0x11, 0x90, 0x0d, 0x11, 0x90, 0x0d, 0x15, 0x90, 0x11, 0x15, 0x9a, 0x11,
+ 0x15, 0x9a, 0x11, 0x1a, 0x9a, 0x15, 0x1a, 0xa2, 0x15, 0x1a, 0xa2, 0x15,
+ 0x20, 0xa2, 0x1a, 0x20, 0xa9, 0x1a, 0x20, 0xa9, 0x1a, 0x26, 0xa0, 0x20,
+ 0x28, 0xa0, 0x24, 0x28, 0xa7, 0x2f, 0x37, 0xa7, 0x32, 0x37, 0xb0, 0x20,
+ 0x26, 0xb0, 0x20, 0x2d, 0xb7, 0x26, 0x2d, 0xbd, 0x2d, 0x2d, 0xb7, 0x26,
+ 0x34, 0xb2, 0x29, 0x36, 0xb7, 0x2d, 0x34, 0xbd, 0x2d, 0x34, 0xb5, 0x32,
+ 0x3c, 0xad, 0x3e, 0x45, 0x8e, 0x43, 0x3b, 0xad, 0x41, 0x45, 0xbf, 0x43,
+ 0x4e, 0xb3, 0x4d, 0x53, 0xb3, 0x53, 0x4f, 0xb3, 0x50, 0x53, 0xba, 0x5e,
+ 0x62, 0xb8, 0x71, 0x5f, 0xc3, 0x34, 0x3b, 0xc9, 0x3b, 0x44, 0xc9, 0x3b,
+ 0x4d, 0xc9, 0x44, 0x4d, 0xcf, 0x44, 0x56, 0xcf, 0x4d, 0x56, 0xd5, 0x4d,
+ 0x5f, 0xd5, 0x56, 0x5f, 0xcc, 0x54, 0x61, 0xda, 0x56, 0x6b, 0xda, 0x5f,
+ 0x6b, 0xdf, 0x5f, 0x6b, 0xc0, 0x6b, 0x70, 0xc0, 0x6d, 0x70, 0xcd, 0x7f,
+ 0x6a, 0xc6, 0x7a, 0x7f, 0xc6, 0x7c, 0x7f, 0xd7, 0x64, 0x72, 0xd6, 0x66,
+ 0x72, 0xd7, 0x6f, 0x72, 0xd7, 0x6d, 0x79, 0xd6, 0x71, 0x71, 0xe5, 0x6b,
+ 0x75, 0xe5, 0x75, 0x75, 0xe9, 0x75, 0x8c, 0xcd, 0x81, 0x6e, 0xcd, 0x85,
+ 0x72, 0xcd, 0x88, 0x8d, 0xcd, 0x8a, 0x8d, 0xd3, 0x98, 0x9a, 0xd9, 0xa7,
+ 0xa9, 0xdc, 0xaa, 0xa0, 0xdf, 0xb6, 0xb7, 0xee, 0x80, 0x8c, 0xe5, 0x8b,
+ 0x92, 0xee, 0x8c, 0x9a, 0xf2, 0x8c, 0x9a, 0xea, 0x8c, 0xa0, 0xec, 0x99,
+ 0xa3, 0xf7, 0x9a, 0xb4, 0xe1, 0xac, 0xa3, 0xea, 0xae, 0xa0, 0xef, 0xae,
+ 0xb1, 0xe6, 0xb5, 0xac, 0xf7, 0xa6, 0xb4, 0xfc, 0xa6, 0xc1, 0xfa, 0xaf,
+ 0xc0, 0xf3, 0xc1, 0xb3, 0xf2, 0xd6, 0xac, 0xff, 0xff, 0xa3, 0xe6, 0xc4,
+ 0xc6, 0xec, 0xd2, 0xd0, 0xec, 0xd3, 0xd4, 0xf6, 0xcd, 0xc9, 0xfb, 0xc5,
+ 0xd1, 0xfb, 0xc9, 0xd4, 0xf2, 0xd6, 0xd3, 0xf7, 0xd3, 0xd2, 0xf5, 0xd0,
+ 0xd7, 0xf3, 0xdc, 0xdc, 0xf9, 0xd4, 0xd7, 0xfa, 0xd1, 0xd8, 0xfa, 0xd6,
+ 0xda, 0xf9, 0xda, 0xd5, 0xf9, 0xdf, 0xe1, 0xfc, 0xde, 0xe0, 0xff, 0xff,
+ 0xcb, 0xff, 0xff, 0xcc, 0xf2, 0xe2, 0xe2, 0xfa, 0xe5, 0xe8, 0xfe, 0xed,
+ 0xe9, 0xfe, 0xef, 0xf0, 0xf9, 0xf0, 0xf1, 0xfd, 0xf0, 0xf1, 0xff, 0xf4,
+ 0xf0, 0xff, 0xf6, 0xf2, 0xff, 0xf8, 0xf8, 0xff, 0xfa, 0xf8, 0xff, 0xfb,
+ 0xfa, 0xff, 0xfb, 0xfb, 0xff, 0xfd, 0xfa, 0xff, 0xfd, 0xfd, 0xff, 0xff,
+ 0xfd, 0xff, 0xff, 0xff, 0x00, 0xcc, 0x22, 0x00, 0xcc, 0x55, 0x00, 0xcc,
+ 0x99, 0x00, 0xcc, 0xcc, 0x00, 0xaa, 0xcc, 0x00, 0x66, 0xcc, 0x00, 0x33,
+ 0xcc, 0x00, 0x00, 0xcc, 0x11, 0x00, 0xcc, 0x44, 0x00, 0xcc, 0x55, 0x00,
+ 0xcc, 0x88, 0x00, 0xcc, 0xbb, 0x00, 0xcc, 0xcc, 0x00, 0xcc, 0xcc, 0x00,
+ 0xbb, 0xcc, 0x00, 0x88, 0xcc, 0x00, 0x66, 0xcc, 0x00, 0x44, 0xcc, 0x00,
+ 0x22, 0x99, 0x00, 0x00, 0x99, 0x11, 0x00, 0x99, 0x33, 0x00, 0x99, 0x44,
+ 0x00, 0x99, 0x66, 0x00, 0x99, 0x88, 0x00, 0x99, 0x99, 0x00, 0x88, 0x99,
+ 0x00, 0x66, 0x99, 0x00, 0x55, 0x99, 0x00, 0x33, 0x99, 0x00, 0x11, 0x99,
+ 0x00, 0x00, 0x99, 0x00, 0x00, 0x99, 0x11, 0x00, 0x99, 0x44, 0x00, 0x99,
+ 0x77, 0x00, 0x99, 0x99, 0x00, 0x77, 0x99, 0x00, 0x55, 0x99, 0x00, 0x22,
+ 0x99, 0x00, 0x00, 0x99, 0x11, 0x00, 0x99, 0x33, 0x00, 0x99, 0x44, 0x00,
+ 0x99, 0x66, 0x00, 0x99, 0x88, 0x00, 0x99, 0x99, 0x00, 0x99, 0x99, 0x00,
+ 0x88, 0x99, 0x00, 0x66, 0x99, 0x00, 0x55, 0x99, 0x00, 0x33, 0x99, 0x00,
+ 0x11, 0x66, 0x00, 0x00, 0x66, 0x11, 0x00, 0x66, 0x22, 0x00, 0x66, 0x33,
+ 0x00, 0x66, 0x44, 0x00, 0x66, 0x55, 0x00, 0x66, 0x66, 0x00, 0x55, 0x66,
+ 0x00, 0x44, 0x66, 0x00, 0x33, 0x66, 0x00, 0x22, 0x66, 0x00, 0x11, 0x66,
+ 0x00, 0x00, 0x66, 0x00, 0x00, 0x66, 0x11, 0x00, 0x66, 0x22, 0x00, 0x66,
+ 0x44, 0x00, 0x66, 0x66, 0x00, 0x55, 0x66, 0x00, 0x33, 0x66, 0x00, 0x11,
+ 0x66, 0x00, 0x00, 0x66, 0x11, 0x00, 0x66, 0x22, 0x00, 0x66, 0x33, 0x00,
+ 0x66, 0x44, 0x00, 0x66, 0x55, 0x00, 0x66, 0x66, 0x00, 0x66, 0x66, 0x00,
+ 0x55, 0x66, 0x00, 0x44, 0x66, 0x00, 0x33, 0x66, 0x00, 0x22, 0x66, 0x00,
+ 0x11, 0x33, 0x00, 0x00, 0x33, 0x00, 0x00, 0x33, 0x11, 0x00, 0x33, 0x11,
+ 0x00, 0x33, 0x22, 0x00, 0x33, 0x22, 0x00, 0x33, 0x33, 0x00, 0x33, 0x33,
+ 0x00, 0x22, 0x33, 0x00, 0x11, 0x33, 0x00, 0x11, 0x33, 0x00, 0x00, 0x33,
+ 0x00, 0x00, 0x33, 0x00, 0x00, 0x33, 0x00, 0x00, 0x33, 0x11, 0x00, 0x33,
+ 0x22, 0x00, 0x33, 0x33, 0x00, 0x22, 0x33, 0x00, 0x11, 0x33, 0x00, 0x00,
+ 0x33, 0x00, 0x00, 0x33, 0x00, 0x00, 0x33, 0x11, 0x00, 0x33, 0x11, 0x00,
+ 0x33, 0x22, 0x00, 0x33, 0x22, 0x00, 0x33, 0x33, 0x00, 0x33, 0x33, 0x00,
+ 0x22, 0x33, 0x00, 0x22, 0x33, 0x00, 0x11, 0x33, 0x00, 0x11, 0x33, 0x00,
+ 0x00, 0x21, 0xf9, 0x04, 0x09, 0x01, 0x00, 0x7c, 0x00, 0x2c, 0x00, 0x00,
+ 0x00, 0x00, 0x78, 0x00, 0x1a, 0x00, 0x00, 0x08, 0xff, 0x00, 0xf9, 0x08,
+ 0x1c, 0x48, 0xb0, 0xa0, 0xc1, 0x83, 0x08, 0x13, 0x2a, 0x5c, 0xc8, 0xb0,
+ 0xa1, 0xc3, 0x87, 0x08, 0xd3, 0xa0, 0x21, 0x43, 0xe6, 0xcb, 0x17, 0x22,
+ 0x42, 0x80, 0x68, 0xdc, 0xc8, 0xb1, 0xa3, 0xc7, 0x8f, 0x20, 0x43, 0x8a,
+ 0x1c, 0x49, 0x52, 0xa4, 0x8f, 0x1d, 0x2e, 0x50, 0x70, 0x90, 0x20, 0x01,
+ 0x07, 0x96, 0x34, 0x0c, 0x25, 0xa2, 0x59, 0x43, 0x73, 0xcc, 0x17, 0x33,
+ 0x5d, 0xb4, 0x68, 0xe1, 0xc2, 0xb3, 0xa7, 0xcf, 0x9f, 0x40, 0x83, 0x0a,
+ 0x1d, 0x4a, 0xb4, 0xa8, 0x51, 0xa1, 0x51, 0x9e, 0xf8, 0x70, 0x71, 0x02,
+ 0xc4, 0x06, 0x96, 0x37, 0xb0, 0x28, 0x9c, 0xc8, 0xa6, 0x8f, 0x9f, 0x3c,
+ 0x6e, 0xc6, 0x68, 0x11, 0xf2, 0xc3, 0x87, 0xd7, 0xaf, 0x60, 0xc3, 0x8a,
+ 0x1d, 0x4b, 0xb6, 0xac, 0xd9, 0xb3, 0x68, 0xcd, 0xf6, 0xe0, 0x91, 0x23,
+ 0x85, 0x08, 0x0f, 0x1b, 0x34, 0x48, 0x70, 0x50, 0x43, 0xea, 0x1e, 0x83,
+ 0x13, 0xf1, 0xf8, 0xa1, 0xb3, 0xe6, 0x8b, 0x93, 0x20, 0x30, 0x3e, 0x08,
+ 0x1e, 0x4c, 0xb8, 0xb0, 0xe1, 0xc3, 0x88, 0x13, 0x2b, 0x5e, 0xcc, 0xb8,
+ 0xf1, 0x60, 0x10, 0x70, 0x33, 0x5c, 0x90, 0xc0, 0xa0, 0x2e, 0x5e, 0x32,
+ 0x74, 0xfc, 0xac, 0xd9, 0xb2, 0x64, 0x06, 0x8b, 0x11, 0x20, 0x3a, 0x88,
+ 0x1e, 0xdd, 0x81, 0x84, 0x8d, 0xd3, 0x36, 0x48, 0xab, 0x5e, 0xcd, 0xba,
+ 0xb5, 0xeb, 0xd7, 0xac, 0x4d, 0xa0, 0x36, 0x01, 0xbb, 0x36, 0x07, 0x0d,
+ 0x18, 0x2a, 0xb0, 0xac, 0x41, 0x86, 0xa0, 0xc4, 0x3c, 0x7e, 0xd0, 0x38,
+ 0x81, 0x41, 0x22, 0x34, 0x6b, 0x23, 0x6d, 0x18, 0x29, 0x57, 0x1e, 0xc8,
+ 0x0a, 0xe9, 0x2b, 0xcb, 0xa3, 0x47, 0x97, 0xa1, 0x3a, 0x49, 0xf4, 0x35,
+ 0xab, 0xa1, 0x4b, 0x5f, 0xde, 0x27, 0x89, 0x6a, 0x12, 0x55, 0xfa, 0x48,
+ 0xff, 0xef, 0x43, 0x7d, 0xb4, 0x78, 0xe5, 0xce, 0x47, 0x6b, 0x67, 0xd4,
+ 0x86, 0xf4, 0xed, 0x0a, 0x13, 0x24, 0x20, 0xb8, 0x71, 0x97, 0x4f, 0x1a,
+ 0x32, 0x68, 0x34, 0x3b, 0x79, 0x61, 0x7c, 0x35, 0x89, 0xe4, 0xdb, 0x29,
+ 0x67, 0xc4, 0x68, 0x81, 0x04, 0xc8, 0x9d, 0x6a, 0x32, 0x14, 0xb8, 0x5c,
+ 0x7b, 0xaa, 0x29, 0x68, 0x20, 0x23, 0xa9, 0x89, 0x76, 0x83, 0x83, 0xd2,
+ 0x05, 0x42, 0x5b, 0x07, 0x32, 0x4c, 0x47, 0x9a, 0x83, 0xde, 0xb9, 0x97,
+ 0x01, 0x05, 0x12, 0x34, 0x80, 0x80, 0x13, 0x02, 0x89, 0xf1, 0xc5, 0x1b,
+ 0x77, 0x78, 0x01, 0x43, 0x7f, 0xab, 0xad, 0xb1, 0xdc, 0x15, 0x37, 0x58,
+ 0x11, 0x5d, 0x15, 0x12, 0x3e, 0x88, 0x9e, 0x6a, 0x00, 0x46, 0xa7, 0xda,
+ 0x0d, 0xd7, 0xad, 0x91, 0xa3, 0x72, 0x34, 0x76, 0x60, 0x84, 0x8d, 0x8c,
+ 0x74, 0x28, 0xa3, 0x72, 0x7d, 0x90, 0xc6, 0xe3, 0x72, 0x17, 0x92, 0xb6,
+ 0xc1, 0x64, 0x10, 0x34, 0x40, 0x82, 0x40, 0x5b, 0x6c, 0x71, 0xc6, 0x19,
+ 0x4b, 0xa0, 0xe0, 0xda, 0x90, 0xca, 0x31, 0xd8, 0x81, 0x8b, 0x40, 0x8a,
+ 0xb6, 0x9e, 0x97, 0xae, 0x1d, 0x29, 0x9d, 0x6a, 0xeb, 0x25, 0x59, 0xe3,
+ 0x72, 0x37, 0x74, 0xb0, 0xa4, 0x72, 0x59, 0x50, 0x97, 0xe0, 0x8b, 0xa2,
+ 0x9d, 0xc7, 0x48, 0x7a, 0x62, 0x2e, 0xc8, 0x1a, 0x07, 0x93, 0x3d, 0x20,
+ 0x22, 0x4c, 0x38, 0x00, 0xc1, 0xc5, 0x16, 0x33, 0xb0, 0xa8, 0x5a, 0x16,
+ 0xcb, 0x35, 0x77, 0x03, 0x09, 0x32, 0x34, 0x59, 0x5a, 0x74, 0x1d, 0xba,
+ 0x66, 0xc3, 0x72, 0x55, 0xe8, 0xb8, 0xe1, 0x72, 0x78, 0x56, 0xca, 0x5c,
+ 0x69, 0x0e, 0x5e, 0x41, 0x9a, 0x15, 0x6b, 0x58, 0x61, 0x84, 0x9c, 0x1a,
+ 0x12, 0xb8, 0x5c, 0xa4, 0xaa, 0x65, 0x30, 0x81, 0x9f, 0x06, 0x48, 0x25,
+ 0x83, 0x0e, 0x43, 0x00, 0xff, 0xc1, 0xc2, 0x6b, 0x88, 0x6e, 0x97, 0x45,
+ 0x84, 0xa2, 0x71, 0xd9, 0x25, 0x4d, 0xbc, 0x66, 0x41, 0x1a, 0x09, 0x0a,
+ 0xf6, 0x41, 0x82, 0xa5, 0x6b, 0x2a, 0x97, 0x84, 0x0d, 0x31, 0x46, 0xd7,
+ 0xa6, 0xa6, 0x8c, 0x04, 0x42, 0xc2, 0x6b, 0x66, 0xda, 0xe8, 0xa8, 0x93,
+ 0x14, 0x38, 0xd0, 0x40, 0xab, 0x7c, 0x68, 0xc0, 0x82, 0x0e, 0x39, 0x88,
+ 0xf0, 0xda, 0x9b, 0xdb, 0x79, 0x2a, 0x5a, 0xad, 0x06, 0x8a, 0x3b, 0xee,
+ 0x72, 0xa9, 0x11, 0xdb, 0xc1, 0x7a, 0x06, 0x0e, 0xd8, 0x81, 0x9d, 0x41,
+ 0xba, 0x66, 0xe7, 0x83, 0x64, 0xaa, 0xb6, 0x41, 0x05, 0xd6, 0x62, 0x7b,
+ 0x01, 0x08, 0x29, 0xa4, 0x60, 0xe8, 0x6a, 0x36, 0x80, 0xb9, 0x1d, 0x6d,
+ 0xc3, 0xda, 0xd8, 0xa6, 0x68, 0xd6, 0xdd, 0xd8, 0x81, 0xba, 0x14, 0x46,
+ 0xd7, 0xc7, 0x15, 0x17, 0x4e, 0xba, 0x5c, 0x79, 0xad, 0x65, 0x48, 0x64,
+ 0x91, 0xae, 0xdd, 0xeb, 0xc0, 0x02, 0xd8, 0x52, 0xa0, 0x01, 0x08, 0x21,
+ 0x78, 0xc0, 0x9a, 0xa1, 0x26, 0x24, 0x41, 0xae, 0x72, 0xa9, 0xe9, 0x0a,
+ 0x21, 0x6a, 0xa8, 0x8d, 0x36, 0xa7, 0x72, 0x37, 0x9c, 0x56, 0x2a, 0xb8,
+ 0x55, 0x08, 0x1c, 0x88, 0xbb, 0x1d, 0x30, 0x1b, 0x88, 0x6a, 0x46, 0x1c,
+ 0x2c, 0x9a, 0x99, 0x7d, 0x54, 0x21, 0x74, 0x15, 0x27, 0x4f, 0x4b, 0x9a,
+ 0x06, 0x13, 0x6c, 0x4c, 0x80, 0x54, 0x11, 0x5c, 0xa0, 0x81, 0x6b, 0x26,
+ 0x08, 0x9d, 0xc5, 0x1a, 0x14, 0x47, 0xfb, 0x2c, 0xb9, 0xbe, 0xba, 0xf6,
+ 0x63, 0x80, 0x11, 0x8e, 0xd9, 0x81, 0x09, 0xd1, 0xed, 0x2c, 0x9a, 0xc0,
+ 0xd8, 0x8d, 0x26, 0x71, 0x20, 0x41, 0xda, 0x89, 0xe7, 0xba, 0x7a, 0xb6,
+ 0xc6, 0x41, 0x06, 0x12, 0x28, 0x40, 0xc0, 0xd2, 0x7c, 0xd4, 0x40, 0x81,
+ 0xd3, 0x1c, 0x70, 0xa0, 0x1a, 0x08, 0x34, 0x28, 0xff, 0x3b, 0x1a, 0xb9,
+ 0x9e, 0x16, 0x2c, 0x60, 0x99, 0x17, 0x47, 0xc8, 0xa1, 0x68, 0x14, 0x46,
+ 0x68, 0x73, 0x79, 0x13, 0xb2, 0xd9, 0x81, 0xc4, 0xca, 0x51, 0xdc, 0xc1,
+ 0xe1, 0xad, 0x3d, 0xe9, 0x80, 0xdc, 0xc3, 0xc0, 0x84, 0x45, 0x04, 0x77,
+ 0x67, 0x90, 0x37, 0x69, 0x20, 0x40, 0xce, 0x5e, 0xcf, 0xe4, 0x0a, 0x2b,
+ 0x24, 0x91, 0xbe, 0x8a, 0xfe, 0x60, 0x6a, 0xe0, 0x5e, 0x28, 0x30, 0x23,
+ 0xee, 0x32, 0xab, 0xdc, 0x1a, 0x14, 0x8a, 0x9b, 0xa6, 0x92, 0xd1, 0x19,
+ 0x2d, 0x1a, 0x07, 0xf7, 0x36, 0x90, 0x00, 0x01, 0x38, 0xc0, 0x94, 0x46,
+ 0x0d, 0x11, 0x48, 0x50, 0x01, 0x06, 0x9f, 0x8f, 0x06, 0xc3, 0xbc, 0xd2,
+ 0xb5, 0x51, 0xde, 0xc9, 0x01, 0x1a, 0x01, 0xec, 0xa9, 0xa4, 0x89, 0x9e,
+ 0x9a, 0xd7, 0xa2, 0xc9, 0x1e, 0xa4, 0x09, 0x0d, 0x47, 0x87, 0xa7, 0x83,
+ 0xf1, 0xb2, 0xdd, 0x65, 0xc6, 0x17, 0x3c, 0x90, 0x40, 0x00, 0x31, 0x4c,
+ 0x31, 0x10, 0x16, 0x31, 0x14, 0x7f, 0xfc, 0x06, 0x79, 0xe7, 0x3d, 0xc2,
+ 0xcb, 0x61, 0x57, 0xf1, 0xec, 0xa3, 0x44, 0x92, 0x40, 0x6e, 0xd9, 0x66,
+ 0x47, 0x97, 0x1a, 0xe5, 0x8f, 0xbb, 0xce, 0x68, 0x1a, 0xd7, 0x3c, 0x5c,
+ 0xb5, 0x6e, 0x34, 0x82, 0xc3, 0xd8, 0x6a, 0x78, 0x77, 0x81, 0x08, 0x28,
+ 0xe0, 0x00, 0x01, 0xa8, 0x41, 0x7d, 0x04, 0xc2, 0x3e, 0xf7, 0x61, 0x00,
+ 0x03, 0x19, 0x80, 0x5f, 0xfc, 0x68, 0x80, 0x04, 0x2a, 0x50, 0x01, 0x09,
+ 0x34, 0x88, 0x9f, 0xfc, 0x68, 0x40, 0xc2, 0x12, 0x9a, 0x90, 0x06, 0x30,
+ 0x18, 0x81, 0x09, 0x47, 0x20, 0x42, 0x0e, 0xa8, 0xb0, 0x84, 0x23, 0x78,
+ 0x21, 0x09, 0x59, 0x38, 0xc2, 0x12, 0xc2, 0xa0, 0x85, 0x34, 0xf0, 0x20,
+ 0x15, 0x8a, 0x70, 0x43, 0x11, 0x96, 0xc0, 0x84, 0x22, 0x94, 0x21, 0x0d,
+ 0xb7, 0x68, 0x18, 0xbf, 0x0d, 0x6c, 0x00, 0x03, 0x16, 0x78, 0xc0, 0x03,
+ 0xd1, 0x67, 0x05, 0x83, 0x54, 0xd0, 0x01, 0x2c, 0xa9, 0x40, 0x05, 0x2e,
+ 0x70, 0x81, 0x0c, 0x58, 0xf1, 0x8a, 0x58, 0xcc, 0xa2, 0x16, 0xb7, 0xc8,
+ 0xc5, 0x2e, 0x7a, 0xf1, 0x8b, 0x60, 0x0c, 0xa3, 0x15, 0x31, 0x70, 0x81,
+ 0x0a, 0x3c, 0xe0, 0x72, 0x07, 0x10, 0x40, 0x30, 0xd4, 0x77, 0x10, 0xf6,
+ 0x0d, 0x23, 0x18, 0x0d, 0x70, 0xc0, 0x03, 0x1e, 0x10, 0x81, 0x3a, 0xda,
+ 0xf1, 0x8e, 0x78, 0xcc, 0xa3, 0x1e, 0xf7, 0xc8, 0xc7, 0x3e, 0xfa, 0xf1,
+ 0x8f, 0x80, 0xb4, 0xe3, 0x03, 0x16, 0xa0, 0x80, 0x04, 0x1c, 0x20, 0x8d,
+ 0xc2, 0xc0, 0x81, 0x42, 0xd2, 0xe0, 0xc6, 0x60, 0x1c, 0xc0, 0x90, 0x09,
+ 0x50, 0x80, 0x24, 0x27, 0x49, 0xc9, 0x4a, 0x5a, 0xf2, 0x92, 0x98, 0xcc,
+ 0xa4, 0x26, 0x37, 0xc9, 0xc9, 0x4e, 0x4a, 0xd2, 0x90, 0x06, 0x20, 0x80,
+ 0x30, 0x6a, 0x50, 0x85, 0x86, 0x30, 0xb2, 0x7d, 0x02, 0x48, 0xa5, 0x00,
+ 0x02, 0x10, 0x80, 0x01, 0xb0, 0xf2, 0x95, 0xb0, 0x8c, 0xa5, 0x2c, 0x67,
+ 0x49, 0xcb, 0x5a, 0xda, 0xf2, 0x96, 0xb8, 0xbc, 0x25, 0x01, 0x58, 0x39,
+ 0x8c, 0x18, 0x58, 0x01, 0x26, 0x10, 0x09, 0xa6, 0x30, 0x87, 0x49, 0xcc,
+ 0x62, 0x3a, 0x24, 0x20, 0x00, 0x3b
+};
+unsigned int search_len = 2010;
+
+
+void writeLogo(const char *dir)
+{
+ QString fileName=(QString)dir+"/doxygen.gif";
+ QFile f(fileName);
+ if (f.open(IO_WriteOnly))
+ f.writeBlock((char *)logo_data,logo_len);
+ else
+ {
+ fprintf(stderr,"Warning: Cannot open file %s for writing\n",fileName.data());
+ }
+ f.close();
+}
+
+void writeSearchButton(const char *dir)
+{
+ QString fileName=(QString)dir+"/search.gif";
+ QFile f(fileName);
+ if (f.open(IO_WriteOnly))
+ f.writeBlock((char *)search_data,search_len);
+ else
+ {
+ fprintf(stderr,"Warning: Cannot open file %s for writing\n",fileName.data());
+ }
+ f.close();
+}
+
+
diff --git a/src/logos.h b/src/logos.h
new file mode 100644
index 0000000..1054fdb
--- /dev/null
+++ b/src/logos.h
@@ -0,0 +1,23 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#ifndef LOGOS_H
+#define LOGOS_H
+
+extern void writeLogo(const char *dir);
+extern void writeSearchButton(const char *dir);
+
+#endif
diff --git a/src/mangen.cpp b/src/mangen.cpp
new file mode 100644
index 0000000..55bf8c7
--- /dev/null
+++ b/src/mangen.cpp
@@ -0,0 +1,341 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#include <qdir.h>
+#include <stdlib.h>
+#include "message.h"
+#include "mangen.h"
+#include "config.h"
+#include "util.h"
+#include "doxygen.h"
+
+ManGenerator::ManGenerator() : OutputGenerator()
+{
+ dir=manOutputDir+"/man3";
+ firstCol=TRUE;
+ paragraph=FALSE;
+ col=0;
+ upperCase=FALSE;
+}
+
+ManGenerator::~ManGenerator()
+{
+}
+
+void ManGenerator::append(const OutputGenerator *g)
+{
+ QString r=g->getContents();
+ if (upperCase)
+ t << r.upper();
+ else
+ t << r;
+ if (r.length()>0)
+ firstCol = r.at(r.length()-1)=='\n';
+ else
+ firstCol = ((ManGenerator *)g)->firstCol;
+ col+=((ManGenerator *)g)->col;
+ paragraph=FALSE;
+}
+
+void ManGenerator::init()
+{
+ QDir d(manOutputDir);
+ if (!d.exists() && !d.mkdir(manOutputDir))
+ {
+ err("Could not create output directory %s\n",manOutputDir.data());
+ exit(1);
+ }
+ d.setPath(manOutputDir+"/man3");
+ if (!d.exists() && !d.mkdir(manOutputDir+"/man3"))
+ {
+ err("Could not create output directory %s/man3\n",manOutputDir.data());
+ exit(1);
+ }
+}
+
+void ManGenerator::startFile(const char *name,const char *,bool)
+{
+ QString fileName=name;
+ if (fileName.left(6)=="class_")
+ {
+ fileName=fileName.right(fileName.length()-6);
+ }
+ int i;
+ if ((i=fileName.findRev('.'))!=-1)
+ {
+ fileName=fileName.left(i);
+ }
+ if (fileName.right(2)!=".3") fileName+=".3";
+ startPlainFile(fileName);
+ firstCol=TRUE;
+}
+
+void ManGenerator::endFile()
+{
+ endPlainFile();
+}
+
+void ManGenerator::writeDoxyAnchor(const char *, const char *,const char *)
+{
+}
+
+void ManGenerator::endTitleHead(const char *name)
+{
+ t << ".TH " << name << " 3 \"" << dateToString(FALSE) << "\" \"";
+ if (projectName.isEmpty())
+ t << "Doxygen";
+ else
+ t << projectName;
+ t << "\" \\\" -*- nroff -*-" << endl;
+ t << ".ad l" << endl;
+ t << ".nh" << endl;
+ t << ".SH NAME" << endl;
+ t << name << " \\- ";
+ firstCol=FALSE;
+}
+
+void ManGenerator::newParagraph()
+{
+ if (!paragraph)
+ {
+ if (!firstCol) t << endl;
+ t << ".PP" << endl;
+ firstCol=TRUE;
+ }
+ paragraph=TRUE;
+}
+
+void ManGenerator::writeString(const char *text)
+{
+ docify(text);
+}
+
+void ManGenerator::writeIndexItem(const char *,const char *,
+ const char *)
+{
+}
+
+void ManGenerator::writeStartAnnoItem(const char *,const char *,
+ const char *,const char *)
+{
+}
+
+void ManGenerator::writeObjectLink(const char *,const char *,
+ const char *, const char *name)
+{
+ startBold(); docify(name); endBold();
+}
+
+void ManGenerator::writeCodeLink(const char *,const char *,
+ const char *, const char *name)
+{
+ docify(name);
+}
+
+void ManGenerator::writeHtmlLink(const char *,const char *text)
+{
+ docify(text);
+}
+
+void ManGenerator::startGroupHeader()
+{
+ if (!firstCol) t << endl;
+ t << ".SH ";
+ upperCase=TRUE;
+ firstCol=FALSE;
+}
+
+void ManGenerator::endGroupHeader()
+{
+ t << "\n.PP " << endl;
+ firstCol=TRUE;
+ paragraph=TRUE;
+ upperCase=FALSE;
+}
+
+void ManGenerator::startMemberHeader()
+{
+ if (!firstCol) t << endl;
+ t << ".SS ";
+}
+
+void ManGenerator::endMemberHeader()
+{
+ t << "\n";
+ firstCol=TRUE;
+ paragraph=FALSE;
+}
+
+void ManGenerator::docify(const char *str)
+{
+ if (str)
+ {
+ const char *p=str;
+ char c=0;
+ while ((c=*p++))
+ {
+ switch(c)
+ {
+ case '\\': t << "\\\\"; col++; break;
+ case '\n': t << "\n"; col=0; break;
+ default: t << c; col++; break;
+ }
+ }
+ firstCol=(c=='\n');
+ //printf("%s",str);fflush(stdout);
+ }
+ paragraph=FALSE;
+}
+
+void ManGenerator::codify(const char *str)
+{
+ static char spaces[]=" ";
+ if (str)
+ {
+ const char *p=str;
+ char c;
+ while (*p)
+ {
+ c=*p++;
+ switch(c)
+ {
+ case '\t': t << &spaces[col&7]; col+=8-(col&7); break;
+ case '\n': t << "\n.br\n"; firstCol=TRUE; col=0; break;
+ case '\\': t << "\\\\"; col++; break;
+ default: t << c; firstCol=FALSE; col++; break;
+ }
+ }
+ //printf("%s",str);fflush(stdout);
+ }
+ paragraph=FALSE;
+}
+
+void ManGenerator::writeChar(char c)
+{
+ firstCol=(c=='\n');
+ if (firstCol) col=0; else col++;
+ switch (c)
+ {
+ case '\\': t << "\\\\"; break;
+ default: t << c; break;
+ }
+ //printf("%c",c);fflush(stdout);
+ paragraph=FALSE;
+}
+
+void ManGenerator::startDescList()
+{
+ if (!firstCol)
+ { t << endl << ".PP" << endl;
+ firstCol=TRUE; paragraph=TRUE;
+ col=0;
+ }
+ paragraph=FALSE;
+}
+
+void ManGenerator::startTitle()
+{
+ if (!firstCol) t << endl;
+ t << ".SH ";
+ firstCol=FALSE;
+ paragraph=FALSE;
+}
+
+void ManGenerator::writeListItem()
+{
+ if (!firstCol) t << endl;
+ t << ".TP" << endl;
+ firstCol=TRUE;
+ paragraph=FALSE;
+ col=0;
+}
+
+void ManGenerator::startCodeFragment()
+{
+ newParagraph();
+ t << ".nf";
+ firstCol=FALSE;
+ paragraph=FALSE;
+}
+
+void ManGenerator::endCodeFragment()
+{
+ if (!firstCol) t << endl;
+ t << ".fi" << endl;
+ firstCol=TRUE;
+ paragraph=FALSE;
+ col=0;
+}
+
+void ManGenerator::startMemberDoc(const char *,const char *,const char *)
+{
+ if (!firstCol) t << endl;
+ t << ".SS ";
+ firstCol=FALSE;
+ paragraph=FALSE;
+}
+
+void ManGenerator::startSubsection()
+{
+ if (!firstCol) t << endl;
+ t << ".SS ";
+ firstCol=FALSE;
+ paragraph=FALSE;
+}
+
+void ManGenerator::startSubsubsection()
+{
+ if (!firstCol) t << endl;
+ t << "\n.SS ";
+ firstCol=FALSE;
+ paragraph=FALSE;
+}
+
+void ManGenerator::writeSynopsis()
+{
+ if (!firstCol) t << endl;
+ t << ".SH SYNOPSIS\n.br\n.PP\n";
+ firstCol=TRUE;
+ paragraph=FALSE;
+}
+
+void ManGenerator::startDescItem()
+{
+ if (!firstCol) t << endl;
+ t << ".IP \"";
+ firstCol=FALSE;
+}
+
+void ManGenerator::endDescTitle()
+{
+ paragraph=TRUE;
+}
+
+void ManGenerator::writeDescItem()
+{
+ if (!firstCol) t << endl;
+ if (!paragraph) t << ".in -1c" << endl;
+ t << ".in +1c" << endl;
+ firstCol=TRUE;
+ paragraph=FALSE;
+ col=0;
+}
+
+void ManGenerator::endDescItem()
+{
+ t << "\" 1c" << endl;
+ firstCol=TRUE;
+}
diff --git a/src/mangen.h b/src/mangen.h
new file mode 100644
index 0000000..d091782
--- /dev/null
+++ b/src/mangen.h
@@ -0,0 +1,171 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#ifndef MANGEN_H
+#define MANGEN_H
+
+#include "outputgen.h"
+
+class QFile;
+
+class ManGenerator : public OutputGenerator
+{
+ public:
+ ManGenerator();
+ ~ManGenerator();
+
+ OutputGenerator *copy() { return new ManGenerator; }
+ //OutputGenerator *clone() { return new ManGenerator(*this); }
+ void append(const OutputGenerator *o);
+ void enable() { active=TRUE; }
+ void disable() { active=FALSE; }
+ void enableIf(OutputType o) { if (o==Man) active=TRUE; }
+ void disableIf(OutputType o) { if (o==Man) active=FALSE; }
+ void disableIfNot(OutputType o) { if (o!=Man) active=FALSE; }
+ bool isEnabled(OutputType o) { return (o==Man && active); }
+ OutputGenerator *get(OutputType o) { return (o==Man) ? this : 0; }
+
+ static void init();
+ void startFile(const char *name,const char *title,bool external);
+ void writeFooter(int,bool) {}
+ void endFile();
+ void clearBuffer();
+
+ //void writeIndex();
+ void startIndexSection(IndexSections) {}
+ void endIndexSection(IndexSections) {}
+ void startProjectNumber() {}
+ void endProjectNumber() {}
+ void writeStyleInfo(int) {}
+ void startTitleHead() {}
+ void endTitleHead(const char *);
+ void startTitle();
+ void endTitle() {}
+
+ void newParagraph();
+ void writeString(const char *text);
+ void startIndexList() {}
+ void endIndexList() {}
+ void startItemList() {}
+ void endItemList() {}
+ void startEnumList() {}
+ void endEnumList() {}
+ void writeIndexItem(const char *ref,const char *file,const char *name);
+ void docify(const char *text);
+ void codify(const char *text);
+ void writeObjectLink(const char *ref,const char *file,
+ const char *anchor,const char *name);
+ void writeCodeLink(const char *ref,const char *f,
+ const char *anchor,const char *name);
+ void startTextLink(const char *,const char *) {}
+ void endTextLink() {}
+ void writeHtmlLink(const char *url,const char *text);
+ void startTypewriter() { t << "\\fC"; firstCol=FALSE; }
+ void endTypewriter() { t << "\\fR"; firstCol=FALSE; }
+ void startGroupHeader();
+ void endGroupHeader();
+ void startMemberHeader();
+ void endMemberHeader();
+ void writeListItem();
+ void startMemberList() { t << "\n.in +1c"; firstCol=FALSE; }
+ void endMemberList() { t << "\n.in -1c"; firstCol=FALSE; }
+ void startMemberItem() { if (firstCol) t << ".in +1c";
+ t << "\n.ti -1c\n.RI \"";
+ firstCol=FALSE;
+ }
+ void endMemberItem() { t << "\"\n.br"; }
+ void writeRuler() {}
+ void writeAnchor(const char *) {}
+ void startCodeFragment();
+ void endCodeFragment();
+ void writeBoldString(const char *text)
+ { t << "\\fB"; docify(text); t << "\\fR"; firstCol=FALSE; }
+ void startEmphasis() { t << "\\fI"; firstCol=FALSE; }
+ void endEmphasis() { t << "\\fR"; firstCol=FALSE; }
+ void startBold() { t << "\\fB"; firstCol=FALSE; }
+ void endBold() { t << "\\fR"; firstCol=FALSE; }
+ void startDescription() {}
+ void endDescription() {}
+ void startDescItem();
+ void endDescItem();
+ void lineBreak() { t << "\n.br" << endl; }
+ void writeChar(char c);
+ void startMemberDoc(const char *,const char *,const char *);
+ void endMemberDoc() {}
+ void writeDoxyAnchor(const char *clName,const char *anchor,const char *name);
+ void writeLatexSpacing() {}
+ void writeStartAnnoItem(const char *type,const char *file,
+ const char *path,const char *name);
+ void writeEndAnnoItem(const char *) { t << endl; firstCol=TRUE; }
+ void startSubsection();
+ void endSubsection() {}
+ void startSubsubsection();
+ void endSubsubsection() {}
+ void startCenter() {}
+ void endCenter() {}
+ void startSmall() {}
+ void endSmall() {}
+ void startSubscript() { t << "\\*<"; firstCol=FALSE; }
+ void endSubscript() { t << "\\*>"; firstCol=FALSE; }
+ void startSuperscript() { t << "\\*{"; firstCol=FALSE; }
+ void endSuperscript() { t << "\\*}"; firstCol=FALSE; }
+ void startTable(int) {}
+ void endTable() {}
+ void nextTableRow() {}
+ void endTableRow() {}
+ void nextTableColumn() {}
+ void endTableColumn() {}
+ void writeCopyright() { t << "(c)"; firstCol=FALSE; }
+ void writeQuote() { t << "\""; firstCol=FALSE; }
+ void writeUmlaut(char c) { t << c << "\\*'"; firstCol=FALSE; }
+ void writeAcute(char c) { t << c << "\\*`"; firstCol=FALSE; }
+ void writeGrave(char c) { t << c << "\\*:"; firstCol=FALSE; }
+ void writeCirc(char c) { t << c << "\\*^"; firstCol=FALSE; }
+ void writeTilde(char c) { t << c << "\\*~"; firstCol=FALSE; }
+ void startMemberDescription() { t << "\n.RI \"\\fI"; firstCol=FALSE; }
+ void endMemberDescription() { t << "\\fR\""; firstCol=FALSE; }
+ void startDescList();
+ void endDescTitle();
+ void writeDescItem();
+ void endDescList() {}
+ void writeSection(const char *,const char *,bool) {}
+ void writeSectionRef(const char *,const char *,const char *) {}
+ void writeSectionRefItem(const char *,const char *,const char *) {}
+ void addToIndex(const char *,const char *) {}
+ void startIndent() {}
+ void endIndent() {}
+ void writeSynopsis();
+ //void generateExternalIndex() {}
+ void startClassDiagram() {}
+ void endClassDiagram(ClassDiagram &,const char *,const char *) {}
+ void startColorFont(uchar,uchar,uchar) {}
+ void endColorFont() {}
+ void writePageRef(const char *,const char *) {}
+ void startQuickIndexItem(const char *,const char *) {}
+ void endQuickIndexItem() {}
+ void writeFormula(const char *,const char *) {}
+
+ private:
+ bool firstCol;
+ bool paragraph;
+ int col;
+ bool upperCase;
+
+ ManGenerator(const ManGenerator &g);
+ ManGenerator &operator=(const ManGenerator &g);
+};
+
+#endif
diff --git a/src/memberdef.cpp b/src/memberdef.cpp
new file mode 100644
index 0000000..f96a2d6
--- /dev/null
+++ b/src/memberdef.cpp
@@ -0,0 +1,180 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#include <stdio.h>
+#include <qregexp.h>
+#include "memberdef.h"
+#include "membername.h"
+#include "doxygen.h"
+#include "util.h"
+
+/*! Creates a new member definition.
+ * Members can be function/variables/enums/etc. inside a class or inside a
+ * file.
+ *
+ * \param t A string representing the type of the member.
+ * \param n A string representing the name of the member.
+ * \param a A string representing the arguments of the member.
+ * \param p The type of protection of the member, possible values are:
+ * \c Public, \c Protected, \c Private.
+ * \param v The `virtualness' of the member, possible values are:
+ * \c Normal, \c Virtual, \c Pure.
+ * \param s A boolean that is true if the member is static.
+ * \param r A boolean that is true if the member is only related.
+ * \param mt The kind of member. See #MemberDef::MemberType for a list of
+ * all types.
+ */
+
+MemberDef::MemberDef(const char *t,const char *na,const char *a,const char *e,
+ Protection p,Specifier v,bool s,bool r,MemberType mt,
+ const ArgumentList *tal,const ArgumentList *al
+ ) : Definition(substituteClassNames(na))
+{
+ //printf("++++++ MemberDef(%s,%s,%s) ++++++ \n",t,na,a);
+ classDef=0;
+ fileDef=0;
+ fileDec=0;
+ redefines=0;
+ redefinedBy=0;
+ nspace=0;
+ memDef=0;
+ memDec=0;
+ exampleList=0;
+ exampleDict=0;
+ enumFields=0;
+ enumScope=0;
+ enumDeclList=0;
+ type=substituteClassNames(t);
+ args=substituteClassNames(a);
+ if (type.isNull()) decl=name()+args; else decl=type+" "+name()+args;
+ declLine=0;
+ defLine=0;
+ virt=v;
+ prot=p;
+ related=r;
+ stat=s;
+ mtype=mt;
+ exception=e;
+ eUsed=FALSE;
+ proto=FALSE;
+ docEnumValues=FALSE;
+ // copy function template arguments (if any)
+ if (tal)
+ {
+ tArgList = new ArgumentList;
+ tArgList->setAutoDelete(TRUE);
+ ArgumentListIterator ali(*tal);
+ Argument *a;
+ for (;(a=ali.current());++ali)
+ {
+ tArgList->append(new Argument(*a));
+ }
+ }
+ else
+ {
+ tArgList=0;
+ }
+ // copy function arguments (if any)
+ if (al)
+ {
+ argList = new ArgumentList;
+ argList->setAutoDelete(TRUE);
+ ArgumentListIterator ali(*al);
+ Argument *a;
+ for (;(a=ali.current());++ali)
+ {
+ argList->append(new Argument(*a));
+ }
+ argList->constSpecifier = al->constSpecifier;
+ argList->volatileSpecifier = al->volatileSpecifier;
+ argList->pureSpecifier = al->pureSpecifier;
+ }
+ else
+ {
+ argList=0;
+ }
+
+}
+
+MemberDef::~MemberDef()
+{
+ delete redefinedBy;
+ delete exampleList;
+ delete exampleDict;
+ delete enumFields;
+ delete argList;
+ delete tArgList;
+}
+
+void MemberDef::insertReimplementedBy(MemberDef *md)
+{
+ if (redefinedBy==0) redefinedBy = new MemberList;
+ redefinedBy->inSort(md);
+}
+
+void MemberDef::insertEnumField(MemberDef *md)
+{
+ if (enumFields==0) enumFields=new MemberList;
+ enumFields->append(md);
+}
+
+bool MemberDef::addExample(const char *anchor,const char *nameStr,
+ const char *file)
+{
+ //printf("%s::addExample(%s,%s,%s)\n",name.data(),anchor,nameStr,file);
+ if (exampleDict==0) exampleDict = new ExampleDict;
+ if (exampleList==0) exampleList = new ExampleList;
+ if (exampleDict->find(nameStr)==0)
+ {
+ //printf("Add reference to example %s to member %s\n",nameStr,name.data());
+ Example *e=new Example;
+ e->anchor=anchor;
+ e->name=nameStr;
+ e->file=file;
+ exampleDict->insert(nameStr,e);
+ exampleList->inSort(e);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+bool MemberDef::hasExamples()
+{
+ if (exampleList==0)
+ return FALSE;
+ else
+ return exampleList->count()>0;
+}
+
+
+void MemberDef::writeExample(OutputList &ol)
+{
+ Example *e=exampleList->first();
+ while (e)
+ {
+ ol.writeObjectLink(0,e->file,e->anchor,e->name);
+ e=exampleList->next();
+ if (e)
+ {
+ if (exampleList->at()==(int)exampleList->count()-1)
+ ol.writeString(" and ");
+ else
+ ol.writeString(", ");
+ }
+ }
+ ol.writeString(".");
+}
+
diff --git a/src/memberdef.h b/src/memberdef.h
new file mode 100644
index 0000000..fba76f8
--- /dev/null
+++ b/src/memberdef.h
@@ -0,0 +1,186 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#ifndef MEMBERDEF_H
+#define MEMBERDEF_H
+
+#include <qstring.h>
+#include <qlist.h>
+#include <qdict.h>
+
+#include "entry.h"
+#include "example.h"
+#include "config.h"
+#include "outputlist.h"
+#include "definition.h"
+#include "config.h"
+
+class FileDef;
+class MemberList;
+class NamespaceDef;
+
+class MemberDef : public Definition
+{
+ public:
+
+ enum MemberType {
+ Define,
+ Function,
+ Variable,
+ Typedef,
+ Enumeration,
+ EnumValue,
+ Prototype,
+ Signal,
+ Slot,
+ Friend
+ };
+
+ MemberDef(const char *type,const char *name,const char *args,
+ const char *excp,Protection prot,Specifier virt,bool stat,
+ bool related,MemberType t,const ArgumentList *tal,
+ const ArgumentList *al);
+ ~MemberDef();
+
+ const char *declaration() const { return decl; }
+ const char *definition() const { return def; }
+ const char *typeString() const { return type; }
+ const char *argsString() const { return args; }
+ const char *excpString() const { return exception; }
+ const char *anchor() const { return ref; }
+ ClassDef *memberClass() { return classDef; }
+ Protection protection() const { return prot; }
+ Specifier virtualness() const { return virt; }
+ MemberType memberType() const { return mtype; }
+ void setMemberType(MemberType t) { mtype=t; }
+ void setDefinition(const char *d) { def=d; }
+ void setDefFile(const char *f) { defFile=f; }
+ void setDefLine(int l) { defLine=l; }
+ void setFileDef(FileDef *fd) { fileDef=fd; }
+ void setFileDec(FileDef *fd) { fileDec=fd; }
+ void setAnchor(const char *a) { ref=a; }
+ FileDef *getFileDef() { return fileDef; }
+ FileDef *getFileDec() { return fileDec; }
+ void setMemberClass(ClassDef *cd) { classDef=cd; }
+ bool isRelated() const { return related; }
+ bool isStatic() const { return stat; }
+ bool detailsAreVisible() const
+ { return !documentation().isEmpty() ||
+ (mtype==Enumeration && docEnumValues) ||
+ (mtype==EnumValue && !briefDescription().isEmpty()) ||
+ (!briefDescription().isEmpty() &&
+ !briefMemDescFlag && repeatBriefFlag);
+ }
+
+ // relation to other members
+ void setReimplements(MemberDef *md) { redefines=md; }
+ void insertReimplementedBy(MemberDef *md);
+ MemberDef *reimplements() { return redefines; }
+ MemberList *reimplementedBy() { return redefinedBy; }
+
+ // enumeration specific members
+ void insertEnumField(MemberDef *md);
+ void setEnumScope(MemberDef *md) { enumScope=md; }
+ MemberDef *getEnumScope() const { return enumScope; }
+ void setEnumDecl(OutputList &ed) { enumDeclList=new OutputList(&ed); }
+ void setEnumUsed() { eUsed=TRUE; }
+ bool enumUsed() const { return eUsed; }
+ OutputList *enumDecl() const { return enumDeclList; }
+ MemberList *enumFieldList() { return enumFields; }
+ void setDocumentedEnumValues(bool value) { docEnumValues=value; }
+ bool hasDocumentedEnumValues() const { return docEnumValues; }
+
+ // example related members
+ bool addExample(const char *anchor,const char *name,const char *file);
+ void writeExample(OutputList &ol);
+ bool hasExamples();
+
+ // prototype related members
+ const char *getDefFile() { return defFile; }
+ int getDefLine() { return defLine; }
+ void setDecFile(const char *f) { declFile=f; }
+ void setDecLine(int l) { defLine=l; }
+
+ // convenience members
+ bool isSignal() const { return mtype==Signal; }
+ bool isSlot() const { return mtype==Slot; }
+ bool isVariable() const { return mtype==Variable; }
+ bool isEnumerate() const { return mtype==Enumeration; }
+ bool isEnumValue() const { return mtype==EnumValue; }
+ bool isTypedef() const { return mtype==Typedef; }
+ bool isFunction() const { return mtype==Function; }
+ bool isDefine() const { return mtype==Define; }
+ bool isFriend() const { return mtype==Friend; }
+
+ // prototype related members
+ void setPrototype(bool p) { proto=p; }
+ bool isPrototype() const { return proto; }
+
+ // tag file related members
+ void setReference(const char *r) { external=r; }
+ bool isReference() { return !external.isNull(); }
+
+ // argument related members
+ ArgumentList *argumentList() const { return argList; }
+ ArgumentList *templateArguments() const { return tArgList; }
+
+ // namespace related members
+ NamespaceDef *getNamespace() { return nspace; }
+ void setNamespace(NamespaceDef *nd) { nspace=nd; }
+
+ private:
+ ClassDef *classDef; // member of or related to
+ FileDef *fileDef; // member of file definition
+ FileDef *fileDec; // member of file declaration
+ MemberDef *redefines; // the member that is redefined by this one
+ MemberDef *enumScope; // the enclosing scope, if this is an enum field
+ MemberList *redefinedBy; // the list of members that redefine this one
+ MemberDef *memDef; // member definition for this declaration
+ MemberDef *memDec; // member declaration for this definition
+ ExampleList *exampleList; // a list of all examples using this member
+ ExampleDict *exampleDict; // a dictionary of all examples for quick access
+ MemberList *enumFields; // enumeration fields
+ OutputList *enumDeclList; // stored piece of documentation for enumeration.
+ NamespaceDef *nspace; // the namespace this member is in.
+ QString type; // return type
+ QString args; // function arguments/variable array specifiers
+ QString exception; // exceptions that can be thrown
+ QString decl; // member declaration in class
+ QString declFile; // file where the declaration was found
+ int declLine; // line where the declaration was found
+ QString def; // member definition in code (fully qualified name)
+ QString defFile; // file where the definition was found
+ int defLine; // line where the definition was found
+ QString ref; // HTML anchor name
+ Specifier virt; // normal/virtual/pure virtual
+ Protection prot; // protection type [Public/Protected/Private]
+ bool related; // is this a member that is only related to a class
+ QString external; // anchor of a member if extracted from a tag file
+ bool stat; // is it a static function?
+ MemberType mtype; // returns the kind of member
+ bool eUsed; // is the enumerate already placed in a list
+ bool proto; // is it a prototype;
+ bool docEnumValues; // is an enum with documented enum values.
+ ArgumentList *argList; // argument list of this member
+ ArgumentList *tArgList; // template argument list of function template
+
+ // disable copying of member defs
+ MemberDef(const MemberDef &);
+ MemberDef &operator=(const MemberDef &);
+};
+
+
+#endif
diff --git a/src/memberlist.cpp b/src/memberlist.cpp
new file mode 100644
index 0000000..4d7cc73
--- /dev/null
+++ b/src/memberlist.cpp
@@ -0,0 +1,148 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#include "memberlist.h"
+#include "classdef.h"
+#include "message.h"
+#include <qregexp.h>
+
+MemberList::MemberList() : QList<MemberDef>()
+{
+}
+
+MemberList::~MemberList()
+{
+}
+
+int MemberList::compareItems(GCI item1, GCI item2)
+{
+ MemberDef *c1=(MemberDef *)item1;
+ MemberDef *c2=(MemberDef *)item2;
+ return strcmp(c1->name(),c2->name());
+}
+
+void MemberList::countDecMembers()
+{
+ varCnt=funcCnt=enumCnt=enumValCnt=typeCnt=protoCnt=defCnt=friendCnt=0;
+ MemberDef *md=first();
+ while (md)
+ {
+ if ((!hideMemberFlag || md->hasDocumentation()) &&
+ (!hideMemberFlag || !md->documentation().isEmpty() ||
+ briefMemDescFlag || repeatBriefFlag
+ ) || extractAllFlag
+ )
+ {
+ switch(md->memberType())
+ {
+ case MemberDef::Variable: varCnt++; break;
+ case MemberDef::Function: // fall through
+ case MemberDef::Signal: // fall through
+ case MemberDef::Slot: funcCnt++; break;
+ case MemberDef::Enumeration: enumCnt++; break;
+ case MemberDef::EnumValue: enumValCnt++; break;
+ case MemberDef::Typedef: typeCnt++; break;
+ case MemberDef::Prototype: protoCnt++; break;
+ case MemberDef::Define: if (extractAllFlag || md->argsString() || md->hasDocumentation() )
+ defCnt++;
+ break;
+ case MemberDef::Friend: friendCnt++; break;
+ default:
+ err("Error: Unknown member type found!");
+ }
+ }
+ md=next();
+ }
+}
+
+void MemberList::countDocMembers()
+{
+ varCnt=funcCnt=enumCnt=enumValCnt=typeCnt=protoCnt=defCnt=friendCnt;
+ MemberDef *md=first();
+ while (md)
+ {
+ //if (extractAllFlag || /*md->hasDocumentation()*/
+ // !md->documentation().isEmpty() ||
+ // (!md->briefDescription().isEmpty() &&
+ // !briefMemDescFlag &&
+ // repeatBriefFlag
+ // )
+ // )
+ if (extractAllFlag || md->detailsAreVisible())
+ {
+ QRegExp r("@[0-9]+");
+ int dummy;
+ switch(md->memberType())
+ {
+ case MemberDef::Variable:
+ varCnt++;
+ break;
+ case MemberDef::Function:
+ case MemberDef::Signal:
+ case MemberDef::Slot:
+ funcCnt++;
+ break;
+ case MemberDef::Enumeration:
+ if (r.match(md->name(),0,&dummy)==-1)
+ {
+ enumCnt++;
+ }
+ break;
+ case MemberDef::EnumValue:
+ {
+ MemberDef *scope;
+ scope=md->getEnumScope();
+ if (scope && r.match(scope->name(),0,&dummy)!=-1)
+ enumValCnt++;
+ }
+ break;
+ case MemberDef::Typedef:
+ typeCnt++;
+ break;
+ case MemberDef::Prototype:
+ protoCnt++;
+ break;
+ case MemberDef::Define:
+ defCnt++;
+ break;
+ case MemberDef::Friend:
+ friendCnt++;
+ }
+ }
+ md=next();
+ }
+}
+
+bool MemberList::insert(uint index,const MemberDef *md)
+{
+ return QList<MemberDef>::insert(index,md);
+}
+
+void MemberList::inSort(const MemberDef *md)
+{
+ QList<MemberDef>::inSort(md);
+}
+
+void MemberList::append(const MemberDef *md)
+{
+ QList<MemberDef>::append(md);
+}
+
+MemberListIterator::MemberListIterator(const QList<MemberDef> &l) :
+ QListIterator<MemberDef>(l)
+{
+}
+
diff --git a/src/memberlist.h b/src/memberlist.h
new file mode 100644
index 0000000..c26f055
--- /dev/null
+++ b/src/memberlist.h
@@ -0,0 +1,56 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#ifndef MEMBERLIST_H
+#define MEMBERLIST_H
+
+#include <qlist.h>
+#include "memberdef.h"
+
+class MemberList : public QList<MemberDef>
+{
+ public:
+ MemberList();
+ ~MemberList();
+ bool insert(uint index,const MemberDef *md);
+ void inSort(const MemberDef *md);
+ void append(const MemberDef *md);
+ int compareItems(GCI item1,GCI item2);
+ int varCount() const { return varCnt; }
+ int funcCount() const { return funcCnt; }
+ int enumCount() const { return enumCnt; }
+ int enumValueCount() const { return enumValCnt; }
+ int typedefCount() const { return typeCnt; }
+ int protoCount() const { return protoCnt; }
+ int defineCount() const { return defCnt; }
+ int friendCount() const { return friendCnt; }
+ void countDecMembers();
+ void countDocMembers();
+ int totalCount() const
+ { return varCnt+funcCnt+enumCnt+enumValCnt+typeCnt+
+ protoCnt+defCnt+friendCnt; }
+
+ private:
+ int varCnt,funcCnt,enumCnt,enumValCnt,typeCnt,protoCnt,defCnt,friendCnt;
+};
+
+class MemberListIterator : public QListIterator<MemberDef>
+{
+ public:
+ MemberListIterator(const QList<MemberDef> &list);
+};
+
+#endif
diff --git a/src/membername.cpp b/src/membername.cpp
new file mode 100644
index 0000000..2605f86
--- /dev/null
+++ b/src/membername.cpp
@@ -0,0 +1,96 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#include "membername.h"
+#include "classdef.h"
+#include "util.h"
+#include "filedef.h"
+
+MemberName::MemberName(const char *n) : QList<MemberDef>()
+{
+ name=n;
+}
+
+MemberName::~MemberName()
+{
+}
+
+int MemberName::compareItems(GCI item1, GCI item2)
+{
+ MemberDef *m1=(MemberDef *)item1;
+ MemberDef *m2=(MemberDef *)item2;
+ ClassDef *c1=m1->memberClass();
+ ClassDef *c2=m2->memberClass();
+ FileDef *f1=m1->getFileDef();
+ FileDef *f2=m2->getFileDef();
+ if (c1 && c2)
+ return stricmp(c1->name(),c2->name());
+ else if (f1 && f2)
+ return stricmp(f1->name(),f2->name());
+ else
+ return 0;
+}
+
+MemberNameInfo::MemberNameInfo(const char *n) : QList<MemberInfo>()
+{
+ name=n;
+ setAutoDelete(TRUE);
+}
+
+MemberNameInfo::~MemberNameInfo()
+{
+}
+
+int MemberNameInfo::compareItems(GCI item1, GCI item2)
+{
+ MemberInfo *m1=(MemberInfo *)item1;
+ MemberInfo *m2=(MemberInfo *)item2;
+ ClassDef *c1=m1->memberDef->memberClass();
+ ClassDef *c2=m2->memberDef->memberClass();
+ FileDef *f1=m1->memberDef->getFileDef();
+ FileDef *f2=m2->memberDef->getFileDef();
+ if (c1 && c2)
+ return stricmp(c1->name(),c2->name());
+ else if (f1 && f2)
+ return stricmp(f1->name(),f2->name());
+ else
+ return 0;
+}
+MemberNameIterator::MemberNameIterator(const MemberName &mnlist) :
+ QListIterator<MemberDef>(mnlist)
+{
+}
+
+MemberNameList::MemberNameList() : QList<MemberName>()
+{
+}
+
+MemberNameList::~MemberNameList()
+{
+}
+
+int MemberNameList::compareItems(GCI item1, GCI item2)
+{
+ MemberName *n1=(MemberName *)item1;
+ MemberName *n2=(MemberName *)item2;
+ return stricmp(n1->memberName(),n2->memberName());
+}
+
+MemberNameListIterator::MemberNameListIterator(const MemberNameList &mnlist) :
+ QListIterator<MemberName>(mnlist)
+{
+}
+
diff --git a/src/membername.h b/src/membername.h
new file mode 100644
index 0000000..4754fa7
--- /dev/null
+++ b/src/membername.h
@@ -0,0 +1,111 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#ifndef MEMBERNAME_H
+#define MEMBERNAME_H
+
+#include <qlist.h>
+#include "memberdef.h"
+
+class MemberName : public QList<MemberDef>
+{
+ public:
+ MemberName(const char *name);
+ ~MemberName();
+ const char *memberName() const { return name; }
+
+ int compareItems(GCI item1,GCI item2);
+ private:
+ QString name;
+};
+
+class MemberNameIterator : public QListIterator<MemberDef>
+{
+ public:
+ MemberNameIterator( const MemberName &list);
+};
+
+class MemberNameList : public QList<MemberName>
+{
+ public:
+ MemberNameList();
+ ~MemberNameList();
+
+ int compareItems(GCI item1,GCI item2);
+};
+
+class MemberNameListIterator : public QListIterator<MemberName>
+{
+ public:
+ MemberNameListIterator( const MemberNameList &list );
+};
+
+typedef QDict<MemberName> MemberNameDict;
+
+struct MemberInfo
+{
+ MemberInfo(MemberDef *md,Protection p,Specifier v) :
+ memberDef(md), prot(p), virt(v) {}
+ MemberDef *memberDef;
+ Protection prot;
+ Specifier virt;
+ QString scopePath;
+ QString ambiguityResolutionScope;
+};
+
+class MemberNameInfo : public QList<MemberInfo>
+{
+ public:
+ MemberNameInfo(const char *name);
+ ~MemberNameInfo();
+ const char *memberName() const { return name; }
+ int compareItems(GCI item1,GCI item2);
+ private:
+ QString name;
+};
+
+class MemberNameInfoIterator : public QListIterator<MemberInfo>
+{
+ public:
+ MemberNameInfoIterator(const MemberNameInfo &mnii)
+ : QListIterator<MemberInfo>(mnii) {}
+};
+
+class MemberNameInfoList : public QList<MemberNameInfo>
+{
+ public:
+ int compareItems(GCI item1,GCI item2)
+ { return stricmp(
+ ((MemberNameInfo *)item1)->memberName(),
+ ((MemberNameInfo *)item2)->memberName()
+ );
+ }
+};
+
+class MemberNameInfoDict : public QDict<MemberNameInfo>
+{
+ public:
+ MemberNameInfoDict(int size) : QDict<MemberNameInfo>(size) {}
+};
+
+class MemberNameInfoListIterator : public QListIterator<MemberNameInfo>
+{
+ public:
+ MemberNameInfoListIterator(const MemberNameInfoList &mil) :
+ QListIterator<MemberNameInfo>(mil) {}
+};
+
+#endif
diff --git a/src/message.cpp b/src/message.cpp
new file mode 100644
index 0000000..9f98107
--- /dev/null
+++ b/src/message.cpp
@@ -0,0 +1,49 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#include <stdarg.h>
+#include <stdio.h>
+#include "config.h"
+
+void msg(const char *fmt, ...)
+{
+ if (!quietFlag)
+ {
+ va_list args;
+ va_start(args, fmt);
+ vfprintf(stdout, fmt, args);
+ va_end(args);
+ }
+}
+
+void warn(const char *fmt, ...)
+{
+ if (warningFlag)
+ {
+ va_list args;
+ va_start(args, fmt);
+ vfprintf(stderr, fmt, args);
+ va_end(args);
+ }
+}
+
+void err(const char *fmt, ...)
+{
+ va_list args;
+ va_start(args, fmt);
+ vfprintf(stderr, fmt, args);
+ va_end(args);
+}
diff --git a/src/message.h b/src/message.h
new file mode 100644
index 0000000..f7586ca
--- /dev/null
+++ b/src/message.h
@@ -0,0 +1,24 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#ifndef MESSAGE_H
+#define MESSAGE_H
+
+extern void msg(const char *fmt, ...);
+extern void warn(const char *fmt, ...);
+extern void err(const char *fmt, ...);
+
+#endif
diff --git a/src/namespacedef.cpp b/src/namespacedef.cpp
new file mode 100644
index 0000000..9d055b2
--- /dev/null
+++ b/src/namespacedef.cpp
@@ -0,0 +1,220 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#include "namespacedef.h"
+#include "outputlist.h"
+#include "util.h"
+#include "scanner.h"
+#include "language.h"
+#include "classdef.h"
+#include "classlist.h"
+#include "memberlist.h"
+
+NamespaceDef::NamespaceDef(const char *name) : Definition(name)
+{
+ fileName="namespace_"+nameToFile(name);
+ classList = new ClassList;
+ memList = new MemberList;
+}
+
+NamespaceDef::~NamespaceDef()
+{
+ delete classList;
+ delete memList;
+}
+
+void NamespaceDef::insertUsedFile(const char *f)
+{
+ if (files.find(f)==-1) files.append(f);
+}
+
+void NamespaceDef::insertClass(ClassDef *cd)
+{
+ classList->append(cd);
+}
+
+void NamespaceDef::insertMember(MemberDef *md)
+{
+ memList->append(md);
+}
+
+void NamespaceDef::computeAnchors()
+{
+ setAnchors('a',memList);
+}
+
+void NamespaceDef::writeDocumentation(OutputList &ol)
+{
+ QString pageTitle=name()+" Namespace Reference";
+ startFile(ol,fileName,pageTitle);
+ startTitle(ol);
+ ol.docify(pageTitle);
+ endTitle(ol,name());
+
+ OutputList briefOutput(&ol);
+ if (briefDescription())
+ {
+ parseDoc(briefOutput,0,0,briefDescription());
+ ol+=briefOutput;
+ ol.writeString(" \n");
+ ol.disableAllBut(OutputGenerator::Html);
+ ol.startTextLink(0,"details");
+ parseDoc(ol,0,0,theTranslator->trMore());
+ ol.endTextLink();
+ ol.enableAll();
+ }
+ ol.disable(OutputGenerator::Man);
+ ol.newParagraph();
+ ol.enable(OutputGenerator::Man);
+ ol.writeSynopsis();
+
+ if (classList->count()>0)
+ {
+ ClassDef *cd=classList->first();
+ bool found=FALSE;
+ while (cd)
+ {
+ if (cd->isVisibleExt())
+ {
+ if (!found)
+ {
+ ol.startMemberHeader();
+ parseDoc(ol,0,0,theTranslator->trCompounds());
+ ol.endMemberHeader();
+ ol.startMemberList();
+ found=TRUE;
+ }
+ QString clName=cd->name().copy();
+ if (clName.left(name().length()+2)==name()+"::")
+ {
+ clName = clName.right(clName.length()-name().length()-2);
+ }
+
+ ol.startMemberItem();
+ switch (cd->compoundType())
+ {
+ case ClassDef::Class: ol.writeString("class"); break;
+ case ClassDef::Struct: ol.writeString("struct"); break;
+ case ClassDef::Union: ol.writeString("union"); break;
+ }
+ ol.writeString(" ");
+ if (cd->hasDocumentation())
+ {
+ ol.writeObjectLink(cd->getReference(),
+ cd->classFile(),
+ 0,
+ clName
+ );
+ }
+ else
+ {
+ ol.startBold();
+ ol.docify(clName);
+ ol.endBold();
+ }
+ ol.endMemberItem();
+ }
+ cd=classList->next();
+ }
+ if (found) ol.endMemberList();
+ }
+
+ writeMemberDecs(ol,0,this,0,0,0,memList);
+
+ if (!briefDescription().isEmpty() || !documentation().isEmpty())
+ {
+ ol.writeRuler();
+ ol.writeAnchor("details");
+ ol.startGroupHeader();
+ parseDoc(ol,0,0,theTranslator->trDetailedDescription());
+ ol.endGroupHeader();
+ if (!briefDescription().isEmpty())
+ {
+ ol+=briefOutput;
+ ol.newParagraph();
+ }
+ if (!documentation().isEmpty())
+ {
+ parseDoc(ol,0,0,documentation()+"\n");
+ ol.newParagraph();
+ }
+ }
+
+ memList->countDocMembers();
+
+ if ( memList->protoCount()>0 )
+ {
+ ol.writeRuler();
+ ol.startGroupHeader();
+ parseDoc(ol,0,0,theTranslator->trFunctionPrototypeDocumentation());
+ ol.endGroupHeader();
+ writeMemberDocs(ol,memList,name(),MemberDef::Prototype);
+ }
+
+ if ( memList->typedefCount()>0 )
+ {
+ ol.writeRuler();
+ ol.startGroupHeader();
+ parseDoc(ol,0,0,theTranslator->trTypedefDocumentation());
+ ol.endGroupHeader();
+ writeMemberDocs(ol,memList,name(),MemberDef::Typedef);
+ }
+
+ if ( memList->enumCount()>0 )
+ {
+ ol.writeRuler();
+ ol.startGroupHeader();
+ parseDoc(ol,0,0,theTranslator->trEnumerationTypeDocumentation());
+ ol.endGroupHeader();
+ writeMemberDocs(ol,memList,name(),MemberDef::Enumeration);
+ }
+
+ if ( memList->enumValueCount()>0 )
+ {
+ ol.writeRuler();
+ ol.startGroupHeader();
+ parseDoc(ol,0,0,theTranslator->trEnumerationValueDocumentation());
+ ol.endGroupHeader();
+ writeMemberDocs(ol,memList,name(),MemberDef::EnumValue);
+ }
+
+ if ( memList->funcCount()>0 )
+ {
+ ol.writeRuler();
+ ol.startGroupHeader();
+ parseDoc(ol,0,0,theTranslator->trFunctionDocumentation());
+ ol.endGroupHeader();
+ writeMemberDocs(ol,memList,name(),MemberDef::Function);
+ }
+
+ if ( memList->varCount()>0 )
+ {
+ ol.writeRuler();
+ ol.startGroupHeader();
+ parseDoc(ol,0,0,theTranslator->trVariableDocumentation());
+ ol.endGroupHeader();
+ writeMemberDocs(ol,memList,name(),MemberDef::Variable);
+ }
+
+ // write Author section (Man only)
+ ol.disableAllBut(OutputGenerator::Man);
+ ol.startGroupHeader();
+ parseDoc(ol,0,0,theTranslator->trAuthor());
+ ol.endGroupHeader();
+ parseDoc(ol,0,0,theTranslator->trGeneratedAutomatically(projectName));
+ ol.enableAll();
+ endFile(ol);
+}
diff --git a/src/namespacedef.h b/src/namespacedef.h
new file mode 100644
index 0000000..9da6b2c
--- /dev/null
+++ b/src/namespacedef.h
@@ -0,0 +1,70 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#ifndef NAMESPACEDEF_H
+#define NAMESPACEDEF_H
+
+#include <qstring.h>
+#include <qstrlist.h>
+#include <qdict.h>
+#include "definition.h"
+
+class ClassDef;
+class OutputList;
+class ClassList;
+class MemberList;
+class MemberDef;
+
+class NamespaceDef : public Definition
+{
+ public:
+ NamespaceDef(const char *name);
+ ~NamespaceDef();
+ QString namespaceFile() const { return fileName; }
+ void insertUsedFile(const char *fname);
+ void writeDocumentation(OutputList &ol);
+ void insertClass(ClassDef *cd);
+ void insertMember(MemberDef *md);
+ void computeAnchors();
+
+ private:
+ QString fileName;
+ QStrList files;
+ ClassList *classList;
+ MemberList *memList;
+};
+
+class NamespaceList : public QList<NamespaceDef>
+{
+ public:
+ int compareItems(GCI item1,GCI item2)
+ {
+ return strcmp(((NamespaceDef *)item1)->name(),
+ ((NamespaceDef *)item2)->name()
+ );
+ }
+};
+
+class NamespaceListIterator : public QListIterator<NamespaceDef>
+{
+ public:
+ NamespaceListIterator(const NamespaceList &l) :
+ QListIterator<NamespaceDef>(l) {}
+};
+
+typedef QDict<NamespaceDef> NamespaceDict;
+
+#endif
diff --git a/src/outputgen.cpp b/src/outputgen.cpp
new file mode 100644
index 0000000..ca07302
--- /dev/null
+++ b/src/outputgen.cpp
@@ -0,0 +1,77 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#include <stdlib.h>
+#include "outputgen.h"
+#include <qstring.h>
+#include "message.h"
+
+OutputGenerator::OutputGenerator()
+{
+ //printf("OutputGenerator::OutputGenerator()\n");
+ file=0;
+ b.setBuffer(a);
+ b.open( IO_WriteOnly );
+ t.setDevice(&b);
+ active=TRUE;
+}
+
+OutputGenerator::~OutputGenerator()
+{
+ //printf("OutputGenerator::~OutputGenerator()\n");
+ delete file;
+}
+
+void OutputGenerator::startPlainFile(const char *name)
+{
+ //printf("startPlainFile(%s)\n",name);
+ QString fileName=dir+"/"+name;
+ file = new QFile(fileName);
+ if (!file)
+ {
+ err("Could not create file object for %s\n",fileName.data());
+ exit(1);
+ }
+ if (!file->open(IO_WriteOnly))
+ {
+ err("Could not open file %s for writing\n",fileName.data());
+ exit(1);
+ }
+ fs.setDevice(file);
+}
+
+void OutputGenerator::endPlainFile()
+{
+ //printf("endPlainFile(%s)\n",file->name());
+ fs.writeRawBytes(a.data(),a.size()) ; // write string buffer to file
+ delete file;
+ file=0;
+ b.close();
+ a.resize(0);
+ b.setBuffer(a);
+ b.open(IO_WriteOnly);
+ t.setDevice(&b);
+}
+
+QString OutputGenerator::getContents() const
+{
+ QString s;
+ s.resize(a.size()+1);
+ memcpy(s.data(),a.data(),a.size());
+ s.at(a.size())='\0';
+ return s;
+}
+
diff --git a/src/outputgen.h b/src/outputgen.h
new file mode 100644
index 0000000..457dd80
--- /dev/null
+++ b/src/outputgen.h
@@ -0,0 +1,182 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#ifndef OUTPUTGEN_H
+#define OUTPUTGEN_H
+
+#include <qstring.h>
+#include <qtstream.h>
+#include <qbuffer.h>
+#include <qfile.h>
+#include "index.h"
+
+class ClassDiagram;
+
+class OutputGenerator
+{
+ public:
+ enum OutputType { Html, Latex, Man };
+
+ OutputGenerator();
+ virtual ~OutputGenerator();
+
+ virtual OutputGenerator *copy() = 0;
+ //virtual OutputGenerator *clone() = 0;
+ virtual void append(const OutputGenerator *) = 0;
+ virtual void enable() = 0;
+ virtual void disable() = 0;
+ virtual void enableIf(OutputType o) = 0;
+ virtual void disableIf(OutputType o) = 0;
+ virtual void disableIfNot(OutputType o) = 0;
+ virtual bool isEnabled(OutputType o) = 0;
+ virtual OutputGenerator *get(OutputType o) = 0;
+
+ virtual void startFile(const char *name,const char *title,bool ext) = 0;
+ virtual void writeFooter(int,bool) = 0;
+ virtual void endFile() = 0;
+ //virtual void writeIndex() = 0;
+ virtual void startIndexSection(IndexSections) = 0;
+ virtual void endIndexSection(IndexSections) = 0;
+ virtual void startProjectNumber() = 0;
+ virtual void endProjectNumber() = 0;
+ virtual void writeStyleInfo(int part) = 0;
+ virtual void startTitleHead() = 0;
+ virtual void endTitleHead(const char *name) = 0;
+ virtual void startTitle() = 0;
+ virtual void endTitle() = 0;
+ virtual void newParagraph() = 0;
+ virtual void writeString(const char *text) = 0;
+ virtual void startIndexList() = 0;
+ virtual void endIndexList() = 0;
+ virtual void startItemList() = 0;
+ virtual void endItemList() = 0;
+ virtual void startEnumList() = 0;
+ virtual void endEnumList() = 0;
+ virtual void startBold() = 0;
+ virtual void endBold() = 0;
+ virtual void writeIndexItem(const char *ref,const char *file,
+ const char *text) = 0;
+ virtual void docify(const char *s) = 0;
+ virtual void codify(const char *s) = 0;
+ virtual void writeObjectLink(const char *ref,const char *file,
+ const char *anchor, const char *text) = 0;
+ virtual void writeCodeLink(const char *ref,const char *file,
+ const char *anchor,const char *text) = 0;
+ virtual void startTextLink(const char *file,const char *anchor) = 0;
+ virtual void endTextLink() = 0;
+ virtual void writeHtmlLink(const char *url,const char *text) = 0;
+ virtual void startTypewriter() = 0;
+ virtual void endTypewriter() = 0;
+ virtual void startGroupHeader() = 0;
+ virtual void endGroupHeader() = 0;
+ virtual void writeListItem() = 0;
+
+ virtual void startMemberHeader() = 0;
+ virtual void endMemberHeader() = 0;
+ virtual void startMemberList() = 0;
+ virtual void endMemberList() = 0;
+ virtual void startMemberItem() = 0;
+ virtual void endMemberItem() = 0;
+
+ virtual void writeRuler() = 0;
+ virtual void writeAnchor(const char *name) = 0;
+ virtual void startCodeFragment() = 0;
+ virtual void endCodeFragment() = 0;
+ virtual void writeBoldString(const char *text) = 0;
+ virtual void startEmphasis() = 0;
+ virtual void endEmphasis() = 0;
+ virtual void writeChar(char c) = 0;
+ virtual void startMemberDoc(const char *,const char *,const char *) = 0;
+ virtual void endMemberDoc() = 0;
+ virtual void writeDoxyAnchor(const char *clName,const char *anchor,const char *name) = 0;
+ virtual void writeLatexSpacing() = 0;
+ virtual void writeStartAnnoItem(const char *type,const char *file,
+ const char *path,const char *name) = 0;
+ virtual void writeEndAnnoItem(const char *name) = 0;
+ virtual void startDescription() = 0;
+ virtual void endDescription() = 0;
+ virtual void startDescItem() = 0;
+ virtual void endDescItem() = 0;
+ virtual void startSubsection() = 0;
+ virtual void endSubsection() = 0;
+ virtual void startSubsubsection() = 0;
+ virtual void endSubsubsection() = 0;
+ virtual void startCenter() = 0;
+ virtual void endCenter() = 0;
+ virtual void startSmall() = 0;
+ virtual void endSmall() = 0;
+ virtual void startSubscript() = 0;
+ virtual void endSubscript() = 0;
+ virtual void startSuperscript() = 0;
+ virtual void endSuperscript() = 0;
+ virtual void startTable(int cols) = 0;
+ virtual void endTable() = 0;
+ virtual void nextTableRow() = 0;
+ virtual void endTableRow() = 0;
+ virtual void nextTableColumn() = 0;
+ virtual void endTableColumn() = 0;
+ virtual void writeQuote() = 0;
+ virtual void writeCopyright() = 0;
+ virtual void writeUmlaut(char) = 0;
+ virtual void writeAcute(char) = 0;
+ virtual void writeGrave(char) = 0;
+ virtual void writeCirc(char) = 0;
+ virtual void writeTilde(char) = 0;
+ virtual void startMemberDescription() = 0;
+ virtual void endMemberDescription() = 0;
+ virtual void startDescList() = 0;
+ virtual void endDescTitle() = 0;
+ virtual void writeDescItem() = 0;
+ virtual void endDescList() = 0;
+ virtual void writeSection(const char *,const char *,bool) = 0;
+ virtual void writeSectionRef(const char *,const char *,const char *) = 0;
+ virtual void writeSectionRefItem(const char *,const char *,const char *) = 0;
+ virtual void lineBreak() = 0;
+ virtual void addToIndex(const char *s1,const char *s2) = 0;
+ virtual void startIndent() = 0;
+ virtual void endIndent() = 0;
+ virtual void writeSynopsis() = 0;
+ //virtual void generateExternalIndex() = 0;
+ virtual void startClassDiagram() = 0;
+ virtual void endClassDiagram(ClassDiagram &,const char *,const char *) = 0;
+ virtual void startColorFont(uchar r,uchar g,uchar b) = 0;
+ virtual void endColorFont() = 0;
+ virtual void writePageRef(const char *,const char *) = 0;
+ virtual void startQuickIndexItem(const char *s,const char *l) = 0;
+ virtual void endQuickIndexItem() = 0;
+ virtual void writeFormula(const char *,const char *) = 0;
+
+ void clear() { b.close(); a.resize(0); b.setBuffer(a);
+ b.open(IO_WriteOnly); t.setDevice(&b); }
+ void startPlainFile(const char *name);
+ void endPlainFile();
+ QString getContents() const;
+ bool isEnabled() const { return active; }
+ protected:
+ QTextStream fs;
+ QByteArray a;
+ QBuffer b;
+ QTextStream t;
+ QFile *file;
+ QString dir;
+ bool active;
+
+ private:
+ OutputGenerator(const OutputGenerator &o);
+ OutputGenerator &operator=(const OutputGenerator &o);
+};
+
+#endif
diff --git a/src/outputlist.cpp b/src/outputlist.cpp
new file mode 100644
index 0000000..daa83ed
--- /dev/null
+++ b/src/outputlist.cpp
@@ -0,0 +1,239 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+/*! \file
+ * This class represents a list of output generators that work in "parallel".
+ * The class only knows about the abstract base class OutputGenerators.
+ * All output is produced by calling a method of this class, which forwards
+ * the call to all output generators.
+ */
+
+#include "outputlist.h"
+#include "outputgen.h"
+#include "config.h"
+#include "message.h"
+
+OutputList::OutputList(bool)
+{
+ //printf("OutputList::OutputList()\n");
+ outputs = new QList<OutputGenerator>;
+ outputs->setAutoDelete(TRUE);
+}
+
+OutputList::OutputList(const OutputList *olist)
+{
+ //printf("OutputList::OutputList() deep copy\n");
+ outputs = new QList<OutputGenerator>;
+ outputs->setAutoDelete(TRUE);
+
+ QList<OutputGenerator> *ol=olist->outputs;
+ OutputGenerator *og=ol->first();
+ while (og)
+ {
+ OutputGenerator *ogc=og->copy();
+ outputs->append(ogc);
+ if (og->isEnabled()) ogc->enable(); else ogc->disable();
+ og=ol->next();
+ }
+ //printf("OutputList::OutputList dst=%d res=%d\n",ol->count(),outputs->count());
+}
+
+OutputList::~OutputList()
+{
+ delete outputs;
+}
+
+OutputList &OutputList::operator=(const OutputList &olist)
+{
+ if (this!=&olist)
+ {
+ QList<OutputGenerator> *ol=olist.outputs;
+ OutputGenerator *ogsrc=ol->first();
+ OutputGenerator *ogdst=outputs->first();
+ //printf("OutputList::operator= src=%d dst=%d\n",outputs->count(),ol->count());
+ while (ogdst)
+ {
+ ogdst=ogsrc->copy();
+ ogsrc=ol->next();
+ ogdst=outputs->next();
+ }
+ }
+ return *this;
+}
+
+void OutputList::add(const OutputGenerator *og)
+{
+ if (og) outputs->append(og);
+}
+
+//HtmlGenerator *OutputList::getHtmlGenerator()
+//{
+// OutputGenerator *og=outputs->first();
+// while (og)
+// {
+// if (og->get(OutputGenerator::Html)) return (HtmlGenerator *)og;
+// og=outputs->next();
+// }
+// return 0; // should not happen!
+//}
+
+void OutputList::disableAllBut(OutputGenerator::OutputType o)
+{
+ OutputGenerator *og=outputs->first();
+ while (og)
+ {
+ og->disableIfNot(o);
+ og=outputs->next();
+ }
+}
+
+void OutputList::enableAll()
+{
+ OutputGenerator *og=outputs->first();
+ while (og)
+ {
+ og->enable();
+ og=outputs->next();
+ }
+}
+
+void OutputList::disable(OutputGenerator::OutputType o)
+{
+ OutputGenerator *og=outputs->first();
+ while (og)
+ {
+ og->disableIf(o);
+ og=outputs->next();
+ }
+}
+
+void OutputList::enable(OutputGenerator::OutputType o)
+{
+ OutputGenerator *og=outputs->first();
+ while (og)
+ {
+ og->enableIf(o);
+ og=outputs->next();
+ }
+}
+
+bool OutputList::isEnabled(OutputGenerator::OutputType o)
+{
+ bool result=FALSE;
+ OutputGenerator *og=outputs->first();
+ while (og)
+ {
+ result=result || og->isEnabled(o);
+ og=outputs->next();
+ }
+ return result;
+}
+
+OutputList &OutputList::operator+=(const OutputList &outputList)
+{
+ OutputList *ol=(OutputList *)&outputList;
+ OutputGenerator *ogsrc=ol->outputs->first();
+ OutputGenerator *ogdst=outputs->first();
+ //printf("OutputList::operator+= src=%d dst=%d\n",outputs->count(),ol->outputs->count());
+ while (ogdst && ogsrc)
+ {
+ ogdst->append(ogsrc);
+ ogsrc=ol->outputs->next();
+ ogdst=outputs->next();
+ }
+ return *this;
+}
+
+//--------------------------------------------------------------------------
+// Create some overloaded definitions of the forall function.
+// Using template functions here would have made it a little less
+// portable (I guess).
+
+// zero arguments
+void OutputList::forall(void (OutputGenerator::*func)())
+{
+ OutputGenerator *og=outputs->first();
+ while (og)
+ {
+ if (og->isEnabled()) (og->*func)();
+ og=outputs->next();
+ }
+}
+
+// one argument
+#define FORALL1(a1,p1) \
+void OutputList::forall(void (OutputGenerator::*func)(a1),a1) \
+{ \
+ OutputGenerator *og=outputs->first(); \
+ while (og) \
+ { \
+ if (og->isEnabled()) (og->*func)(p1); \
+ og=outputs->next(); \
+ } \
+}
+
+// two arguments
+#define FORALL2(a1,a2,p1,p2) \
+void OutputList::forall(void (OutputGenerator::*func)(a1,a2),a1,a2) \
+{ \
+ OutputGenerator *og=outputs->first(); \
+ while (og) \
+ { \
+ if (og->isEnabled()) (og->*func)(p1,p2); \
+ og=outputs->next(); \
+ } \
+}
+
+// three arguments
+#define FORALL3(a1,a2,a3,p1,p2,p3) \
+void OutputList::forall(void (OutputGenerator::*func)(a1,a2,a3),a1,a2,a3) \
+{ \
+ OutputGenerator *og=outputs->first(); \
+ while (og) \
+ { \
+ if (og->isEnabled()) (og->*func)(p1,p2,p3); \
+ og=outputs->next(); \
+ } \
+}
+
+// four arguments
+#define FORALL4(a1,a2,a3,a4,p1,p2,p3,p4) \
+void OutputList::forall(void (OutputGenerator::*func)(a1,a2,a3,a4),a1,a2,a3,a4) \
+{ \
+ OutputGenerator *og=outputs->first(); \
+ while (og) \
+ { \
+ if (og->isEnabled()) (og->*func)(p1,p2,p3,p4); \
+ og=outputs->next(); \
+ } \
+}
+
+// now instantiate only the ones we need.
+
+FORALL1(const char *a1,a1)
+FORALL1(char a1,a1)
+FORALL1(int a1,a1)
+FORALL1(IndexSections a1,a1)
+FORALL2(const char *a1,const char *a2,a1,a2)
+FORALL2(int a1,bool a2,a1,a2)
+FORALL3(ClassDiagram &a1,const char *a2,const char *a3,a1,a2,a3)
+FORALL3(const char *a1,const char *a2,const char *a3,a1,a2,a3)
+FORALL3(const char *a1,const char *a2,bool a3,a1,a2,a3)
+FORALL3(uchar a1,uchar a2,uchar a3,a1,a2,a3)
+FORALL4(const char *a1,const char *a2,const char *a3,const char *a4,a1,a2,a3,a4)
+
+
+//--------------------------------------------------------------------------
diff --git a/src/outputlist.h b/src/outputlist.h
new file mode 100644
index 0000000..2c57dad
--- /dev/null
+++ b/src/outputlist.h
@@ -0,0 +1,298 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#ifndef OUTPUTLIST_H
+#define OUTPUTLIST_H
+
+#include <qlist.h>
+#include <qstring.h>
+#include "index.h" // for IndexSections
+#include "outputgen.h"
+
+#define FORALLPROTO1(arg1) \
+ void forall(void (OutputGenerator::*func)(arg1),arg1)
+#define FORALLPROTO2(arg1,arg2) \
+ void forall(void (OutputGenerator::*func)(arg1,arg2),arg1,arg2)
+#define FORALLPROTO3(arg1,arg2,arg3) \
+ void forall(void (OutputGenerator::*func)(arg1,arg2,arg3),arg1,arg2,arg3)
+#define FORALLPROTO4(arg1,arg2,arg3,arg4) \
+ void forall(void (OutputGenerator::*func)(arg1,arg2,arg3,arg4),arg1,arg2,arg3,arg4)
+
+class ClassDiagram;
+
+class OutputList
+{
+ public:
+ OutputList(bool);
+ ~OutputList();
+ OutputList(const OutputList *ol);
+ OutputList &operator=(const OutputList &ol);
+ OutputList &operator+=(const OutputList &ol);
+
+ void add(const OutputGenerator *);
+
+ void disableAllBut(OutputGenerator::OutputType o);
+ void enableAll();
+ void disable(OutputGenerator::OutputType o);
+ void enable(OutputGenerator::OutputType o);
+ bool isEnabled(OutputGenerator::OutputType o);
+
+ //void writeIndex()
+ //{ forall(&OutputGenerator::writeIndex); }
+ void startIndexSection(IndexSections is)
+ { forall(&OutputGenerator::startIndexSection,is); }
+ void endIndexSection(IndexSections is)
+ { forall(&OutputGenerator::endIndexSection,is); }
+ void startProjectNumber()
+ { forall(&OutputGenerator::startProjectNumber); }
+ void endProjectNumber()
+ { forall(&OutputGenerator::endProjectNumber); }
+ void writeStyleInfo(int part)
+ { forall(&OutputGenerator::writeStyleInfo,part); }
+ void startFile(const char *name,const char *title,bool external)
+ { forall(&OutputGenerator::startFile,name,title,external); }
+ void startPlainFile(const char *name)
+ { forall(&OutputGenerator::startPlainFile,name); }
+ void writeFooter(int fase,bool external)
+ { forall(&OutputGenerator::writeFooter,fase,external); }
+ void endFile()
+ { forall(&OutputGenerator::endFile); }
+ void endPlainFile()
+ { forall(&OutputGenerator::endPlainFile); }
+ void startTitleHead()
+ { forall(&OutputGenerator::startTitleHead); }
+ void endTitleHead(const char *name)
+ { forall(&OutputGenerator::endTitleHead,name); }
+ void startTitle()
+ { forall(&OutputGenerator::startTitle); }
+ void endTitle()
+ { forall(&OutputGenerator::endTitle); }
+ void newParagraph()
+ { forall(&OutputGenerator::newParagraph); }
+ void writeString(const char *text)
+ { forall(&OutputGenerator::writeString,text); }
+ void startIndexList()
+ { forall(&OutputGenerator::startIndexList); }
+ void endIndexList()
+ { forall(&OutputGenerator::endIndexList); }
+ void startItemList()
+ { forall(&OutputGenerator::startItemList); }
+ void endItemList()
+ { forall(&OutputGenerator::endItemList); }
+ void startEnumList()
+ { forall(&OutputGenerator::startEnumList); }
+ void endEnumList()
+ { forall(&OutputGenerator::endEnumList); }
+ void writeIndexItem(const char *ref,const char *file,const char *text)
+ { forall(&OutputGenerator::writeIndexItem,ref,file,text); }
+ void docify(const char *s)
+ { forall(&OutputGenerator::docify,s); }
+ void codify(const char *s)
+ { forall(&OutputGenerator::codify,s); }
+ void writeObjectLink(const char *ref,const char *file,
+ const char *anchor, const char *text)
+ { forall(&OutputGenerator::writeObjectLink,ref,file,anchor,text); }
+ void writeCodeLink(const char *ref,const char *file,
+ const char *anchor,const char *text)
+ { forall(&OutputGenerator::writeCodeLink,ref,file,anchor,text); }
+ void startTextLink(const char *file,const char *anchor)
+ { forall(&OutputGenerator::startTextLink,file,anchor); }
+ void endTextLink()
+ { forall(&OutputGenerator::endTextLink); }
+ void writeHtmlLink(const char *url,const char *text)
+ { forall(&OutputGenerator::writeHtmlLink,url,text); }
+ void writeStartAnnoItem(const char *type,const char *file,
+ const char *path,const char *name)
+ { forall(&OutputGenerator::writeStartAnnoItem,type,file,path,name); }
+ void writeEndAnnoItem(const char *name)
+ { forall(&OutputGenerator::writeEndAnnoItem,name); }
+ void startTypewriter()
+ { forall(&OutputGenerator::startTypewriter); }
+ void endTypewriter()
+ { forall(&OutputGenerator::endTypewriter); }
+ void startGroupHeader()
+ { forall(&OutputGenerator::startGroupHeader); }
+ void endGroupHeader()
+ { forall(&OutputGenerator::endGroupHeader); }
+ void writeListItem()
+ { forall(&OutputGenerator::writeListItem); }
+ void startMemberHeader()
+ { forall(&OutputGenerator::startMemberHeader); }
+ void endMemberHeader()
+ { forall(&OutputGenerator::endMemberHeader); }
+ void startMemberList()
+ { forall(&OutputGenerator::startMemberList); }
+ void endMemberList()
+ { forall(&OutputGenerator::endMemberList); }
+ void startMemberItem()
+ { forall(&OutputGenerator::startMemberItem); }
+ void endMemberItem()
+ { forall(&OutputGenerator::endMemberItem); }
+ void writeRuler()
+ { forall(&OutputGenerator::writeRuler); }
+ void writeAnchor(const char *name)
+ { forall(&OutputGenerator::writeAnchor,name); }
+ void startCodeFragment()
+ { forall(&OutputGenerator::startCodeFragment); }
+ void endCodeFragment()
+ { forall(&OutputGenerator::endCodeFragment); }
+ void writeBoldString(const char *text)
+ { forall(&OutputGenerator::writeBoldString,text); }
+ void startEmphasis()
+ { forall(&OutputGenerator::startEmphasis); }
+ void endEmphasis()
+ { forall(&OutputGenerator::endEmphasis); }
+ void writeChar(char c)
+ { forall(&OutputGenerator::writeChar,c); }
+ void startMemberDoc(const char *clName,const char *memName,const char *anchor)
+ { forall(&OutputGenerator::startMemberDoc,clName,memName,anchor); }
+ void endMemberDoc()
+ { forall(&OutputGenerator::endMemberDoc); }
+ void writeDoxyAnchor(const char *clName,const char *anchor,const char *name)
+ { forall(&OutputGenerator::writeDoxyAnchor,clName,anchor,name); }
+ void writeLatexSpacing()
+ { forall(&OutputGenerator::writeLatexSpacing); }
+ void startDescription()
+ { forall(&OutputGenerator::startDescription); }
+ void endDescription()
+ { forall(&OutputGenerator::endDescription); }
+ void startDescItem()
+ { forall(&OutputGenerator::startDescItem); }
+ void endDescItem()
+ { forall(&OutputGenerator::endDescItem); }
+ void startSubsection()
+ { forall(&OutputGenerator::startSubsection); }
+ void endSubsection()
+ { forall(&OutputGenerator::endSubsection); }
+ void startSubsubsection()
+ { forall(&OutputGenerator::startSubsubsection); }
+ void endSubsubsection()
+ { forall(&OutputGenerator::endSubsubsection); }
+ void startCenter()
+ { forall(&OutputGenerator::startCenter); }
+ void endCenter()
+ { forall(&OutputGenerator::endCenter); }
+ void startSmall()
+ { forall(&OutputGenerator::startSmall); }
+ void endSmall()
+ { forall(&OutputGenerator::endSmall); }
+ void startSubscript()
+ { forall(&OutputGenerator::startSubscript); }
+ void endSubscript()
+ { forall(&OutputGenerator::endSubscript); }
+ void startSuperscript()
+ { forall(&OutputGenerator::startSuperscript); }
+ void endSuperscript()
+ { forall(&OutputGenerator::endSuperscript); }
+ void startTable(int cols)
+ { forall(&OutputGenerator::startTable,cols); }
+ void endTable()
+ { forall(&OutputGenerator::endTable); }
+ void nextTableRow()
+ { forall(&OutputGenerator::nextTableRow); }
+ void endTableRow()
+ { forall(&OutputGenerator::endTableRow); }
+ void nextTableColumn()
+ { forall(&OutputGenerator::nextTableColumn); }
+ void endTableColumn()
+ { forall(&OutputGenerator::endTableColumn); }
+ void lineBreak()
+ { forall(&OutputGenerator::lineBreak); }
+ void startBold()
+ { forall(&OutputGenerator::startBold); }
+ void endBold()
+ { forall(&OutputGenerator::endBold); }
+ void writeCopyright()
+ { forall(&OutputGenerator::writeCopyright); }
+ void writeQuote()
+ { forall(&OutputGenerator::writeQuote); }
+ void writeUmlaut(char c)
+ { forall(&OutputGenerator::writeUmlaut,c); }
+ void writeAcute(char c)
+ { forall(&OutputGenerator::writeAcute,c); }
+ void writeGrave(char c)
+ { forall(&OutputGenerator::writeGrave,c); }
+ void writeCirc(char c)
+ { forall(&OutputGenerator::writeCirc,c); }
+ void writeTilde(char c)
+ { forall(&OutputGenerator::writeTilde,c); }
+ void startMemberDescription()
+ { forall(&OutputGenerator::startMemberDescription); }
+ void endMemberDescription()
+ { forall(&OutputGenerator::endMemberDescription); }
+ void startDescList()
+ { forall(&OutputGenerator::startDescList); }
+ void endDescTitle()
+ { forall(&OutputGenerator::endDescTitle); }
+ void writeDescItem()
+ { forall(&OutputGenerator::writeDescItem); }
+ void endDescList()
+ { forall(&OutputGenerator::endDescList); }
+ void startIndent()
+ { forall(&OutputGenerator::startIndent); }
+ void endIndent()
+ { forall(&OutputGenerator::endIndent); }
+ void writeSection(const char *lab,const char *title,bool sub)
+ { forall(&OutputGenerator::writeSection,lab,title,sub); }
+ void writeSectionRef(const char *page,const char *lab, const char *title)
+ { forall(&OutputGenerator::writeSectionRef,page,lab,title); }
+ void writeSectionRefItem(const char *page,const char *lab, const char *title)
+ { forall(&OutputGenerator::writeSectionRefItem,page,lab,title); }
+ void addToIndex(const char *s1,const char *s2)
+ { forall(&OutputGenerator::addToIndex,s1,s2); }
+ void writeSynopsis()
+ { forall(&OutputGenerator::writeSynopsis); }
+ //void generateExternalIndex()
+ //{ forall(&OutputGenerator::generateExternalIndex); }
+ void startClassDiagram()
+ { forall(&OutputGenerator::startClassDiagram); }
+ void endClassDiagram(ClassDiagram &d,const char *f,const char *n)
+ { forall(&OutputGenerator::endClassDiagram,d,f,n); }
+ void startColorFont(uchar r,uchar g,uchar b)
+ { forall(&OutputGenerator::startColorFont,r,g,b); }
+ void endColorFont()
+ { forall(&OutputGenerator::endColorFont); }
+ void writePageRef(const char *c,const char *a)
+ { forall(&OutputGenerator::writePageRef,c,a); }
+ void startQuickIndexItem(const char *s,const char *l)
+ { forall(&OutputGenerator::startQuickIndexItem,s,l); }
+ void endQuickIndexItem()
+ { forall(&OutputGenerator::endQuickIndexItem); }
+ void writeFormula(const char *n,const char *t)
+ { forall(&OutputGenerator::writeFormula,n,t); }
+
+ private:
+ void debug();
+ void clear();
+
+ void forall(void (OutputGenerator::*func)());
+ FORALLPROTO1(const char *);
+ FORALLPROTO1(char);
+ FORALLPROTO1(int);
+ FORALLPROTO1(IndexSections);
+ FORALLPROTO2(const char *,const char *);
+ FORALLPROTO2(int,bool);
+ FORALLPROTO3(const char *,const char *,bool);
+ FORALLPROTO3(uchar,uchar,uchar);
+ FORALLPROTO3(const char *,const char *,const char *);
+ FORALLPROTO3(ClassDiagram &,const char *,const char *);
+ FORALLPROTO4(const char *,const char *,const char *,const char *);
+
+ OutputList(const OutputList &ol);
+ QList<OutputGenerator> *outputs;
+};
+
+#endif
diff --git a/src/pre.h b/src/pre.h
new file mode 100644
index 0000000..5028929
--- /dev/null
+++ b/src/pre.h
@@ -0,0 +1,41 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#ifndef PRE_H
+#define PRE_H
+
+#include <stdio.h>
+#include <qstring.h>
+#include <qfile.h>
+
+#if 0
+class Define
+{
+ public:
+ Define(const char *n) { name=n; }
+ ~Define();
+
+ private:
+ QString name;
+ QStrList args;
+};
+#endif
+
+void initPreprocessor();
+void addSearchDir(const char *dir);
+void preprocessFile(const char *fileName,BufStr &output);
+
+#endif
diff --git a/src/pre.l b/src/pre.l
new file mode 100644
index 0000000..92f7553
--- /dev/null
+++ b/src/pre.l
@@ -0,0 +1,1636 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+%{
+
+/*
+ * includes
+ */
+
+#include <stdio.h>
+#include <iostream.h>
+#include <assert.h>
+#include <ctype.h>
+
+#include <qarray.h>
+#include <qstring.h>
+#include <qstack.h>
+#include <qfile.h>
+#include <qstrlist.h>
+#include <qdict.h>
+#include <qregexp.h>
+
+#include "constexp.h"
+#include "define.h"
+#include "doxygen.h"
+#include "message.h"
+#include "util.h"
+
+#if defined(_MSC_VER)
+#define popen _popen
+#define pclose _pclose
+#endif
+
+#define YY_NEVER_INTERACTIVE 1
+
+#define DUMP_OUTPUT 0 // set this to one to see what the preprocessor
+ // produces.
+#define SHOW_INCLUDES 0 // set this to one to list all parsed include files
+
+struct FileState
+{
+ int lineNr;
+ FILE *filePtr;
+ YY_BUFFER_STATE bufState;
+ QString fileName;
+};
+
+/* -----------------------------------------------------------------
+ *
+ * statics
+ */
+
+static int yyLineNr = 1;
+static QString yyFileName;
+static int ifcount = 0;
+static QStrList *pathList = 0;
+static QStack<FileState> includeStack;
+static QDict<int> *argDict;
+static int defArgs = 0;
+static QString defName;
+static QString defText;
+static QString defArgsStr;
+static bool defVarArgs;
+static int level;
+static int lastCContext;
+static int lastCPPContext;
+static QArray<int> levelGuard;
+static QString guardExpr;
+static BufStr *outputBuf;
+//static DefineCache *fileDefineCache;
+static int roundCount;
+//static const Define *expandDefine;
+static bool quoteArg;
+static DefineDict *fileDefineDict;
+static DefineDict *expandedDict;
+static int findDefArgContext;
+
+
+static void incrLevel()
+{
+ level++;
+ levelGuard.resize(level);
+ levelGuard[level-1]=FALSE;
+ //printf("%s line %d: incrLevel %d\n",yyFileName.data(),yyLineNr,level);
+}
+
+static void decrLevel()
+{
+ //printf("%s line %d: decrLevel %d\n",yyFileName.data(),yyLineNr,level);
+ if (level > 0)
+ {
+ level--;
+ levelGuard.resize(level);
+ }
+ else
+ {
+ err("Error: More #endif's than #if's found.\n");
+ }
+}
+
+static bool otherCaseDone()
+{
+ return levelGuard[level-1];
+}
+
+static void setCaseDone(bool value)
+{
+ levelGuard[level-1]=value;
+}
+
+static Define *isDefined(const char *name)
+{
+ if (name)
+ {
+ Define *def;
+ //if ((def=fileDefineCache->findDefine(yyFileName,name)) && !def->undef)
+ // return def;
+ if ((def=fileDefineDict->find(name)) && !def->undef) return def;
+ }
+ return 0;
+}
+
+static FILE *findFile(const char *fileName)
+{
+ if (pathList==0)
+ {
+ return 0;
+ }
+ char *s=pathList->first();
+ while (s)
+ {
+ QString absName=(QString)s+"/"+fileName;
+ QFileInfo fi(absName);
+ if (fi.exists())
+ {
+ FILE *f;
+ if (!inputFilter.isEmpty())
+ {
+ QString cmd = inputFilter+" "+absName;
+ f=popen(cmd,"r");
+ if (!f) warn("Warning: could not execute filter %s\n",cmd.data());
+ }
+ else
+ {
+ f=fopen(absName,"r");
+ if (!f) warn("Warning: could not open file %s for reading\n",absName.data());
+ }
+ if (f)
+ {
+ yyFileName=absName;
+ yyLineNr=1;
+ return f;
+ }
+ }
+ s=pathList->next();
+ }
+ return 0;
+}
+
+
+static int getNextChar(const QString &expr,QString *rest,uint &pos);
+static int getCurrentChar(const QString &expr,QString *rest,uint pos);
+static void unputChar(const QString &expr,QString *rest,uint &pos,char c);
+static void expandExpression(QString &expr,QString *rest,int pos);
+
+static QString stringize(const QString &s)
+{
+ QString result;
+ uint i=0;
+ bool inString=FALSE;
+ bool inChar=FALSE;
+ char c,pc;
+ while (i<s.length())
+ {
+ if (!inString && !inChar)
+ {
+ while (i<s.length() && !inString && !inChar)
+ {
+ c=s.at(i++);
+ if (c=='"')
+ {
+ result+="\\\"";
+ inString=TRUE;
+ }
+ else if (c=='\'')
+ {
+ result+=c;
+ inChar=TRUE;
+ }
+ else
+ {
+ result+=c;
+ }
+ }
+ }
+ else if (inChar)
+ {
+ while (i<s.length() && inChar)
+ {
+ c=s.at(i++);
+ if (c=='\'')
+ {
+ result+='\'';
+ inChar=FALSE;
+ }
+ else if (c=='\\')
+ {
+ result+="\\\\";
+ }
+ else
+ {
+ result+=c;
+ }
+ }
+ }
+ else
+ {
+ pc=0;
+ while (i<s.length() && inString)
+ {
+ char c=s.at(i++);
+ if (c=='"')
+ {
+ result+="\\\"";
+ inString= pc=='\\';
+ }
+ else if (c=='\\')
+ result+="\\\\";
+ else
+ result+=c;
+ pc=c;
+ }
+ }
+ }
+ //printf("stringize `%s'->`%s'\n",s.data(),result.data());
+ return result;
+}
+
+/*! Execute all ## operators in expr.
+ * If the macro name before or after the operator contains a no-rescan
+ * marker (@-) then this is removed (before the concatenated macro name
+ * may be expanded again.
+ */
+static void processConcatOperators(QString &expr)
+{
+ QRegExp r("[ \\t\\n]*##[ \\t\\n]*");
+ int l,n,i=0;
+ while ((n=r.match(expr,i,&l))!=-1)
+ {
+ if (n+l+1<(int)expr.length() && expr.at(n+l)=='@' && expr.at(n+l+1)=='-')
+ {
+ // remove no-rescan marker after ID
+ l+=2;
+ }
+ // remove the ## operator and the surrounding whitespace
+ expr=expr.left(n)+expr.right(expr.length()-n-l);
+ int k=n-1;
+ while (k>=0 && isId(expr.at(k))) k--;
+ if (k>0 && expr.at(k)=='-' && expr.at(k-1)=='@')
+ {
+ // remove no-rescan marker before ID
+ expr=expr.left(k-1)+expr.right(expr.length()-k-1);
+ n-=2;
+ }
+ i=n+l;
+ }
+}
+
+/*! replaces the function macro \a def whose argument list starts at
+ * \a pos in expression \a expr.
+ * Notice that this routine may scan beyond the \a expr string if needed.
+ * The characters from the input file will be read.
+ * The replacement string will be returned in \a result and the
+ * length of the (unexpanded) argument list is stored in \a len.
+ */
+static bool replaceFunctionMacro(const QString &expr,QString *rest,int pos,int &len,const Define *def,QString &result)
+{
+ //printf("replaceFunctionMacro(expr=%s,rest=%s,pos=%d,def=%s) level=%d\n",expr.data(),rest ? rest->data() : 0,pos,def->name.data(),level);
+ //bool replaced=FALSE;
+ uint j=pos;
+ len=0;
+ result.resize(0);
+ int cc;
+ // TODO: use a checkNextChar function.
+ //while ((cc=getNextChar(expr,rest,j))!=EOF && cc==' ') len++;
+ //if (cc!='(') return FALSE;
+ while ((cc=getCurrentChar(expr,rest,j))!=EOF && cc==' ')
+ {
+ len++;
+ getNextChar(expr,rest,j);
+ }
+ if (cc!='(')
+ {
+ unputChar(expr,rest,j,' ');
+ return FALSE;
+ }
+ getNextChar(expr,rest,j); // eat the `(' character
+
+ //while (j<expr.length() && expr.at(j)!='(') j++;
+ //j++; // skip opening paren
+
+ QDict<QString> argTable; // list of arguments
+ argTable.setAutoDelete(TRUE);
+ QString arg;
+ int argCount=0;
+ bool done=FALSE;
+ // FASE 1: read the macro arguments
+ while ((argCount<def->nargs || def->varArgs) &&
+ ((cc=getNextChar(expr,rest,j))!=EOF) && !done
+ )
+ {
+ char c=(char)cc;
+ if (c=='(') // argument is a function => search for matching )
+ {
+ int level=1;
+ arg+=c;
+ char term='\0';
+ while ((cc=getNextChar(expr,rest,j))!=EOF)
+ {
+ char c=(char)cc;
+ if (c=='\'' || c=='\"') // skip ('s and )'s inside strings
+ {
+ if (term!='\0')
+ {
+ if (c==term && expr.at(j-2)!='\\') term='\0';
+ }
+ else
+ {
+ term=c;
+ }
+ }
+ if (term=='\0' && c==')')
+ {
+ level--;
+ arg+=c;
+ if (level==0) break;
+ }
+ else if (term=='\0' && c=='(')
+ {
+ level++;
+ arg+=c;
+ }
+ else
+ arg+=c;
+ }
+ }
+ else if (c==')' || c==',') // last or next argument found
+ {
+ if (c==',' && argCount==def->nargs-1 && def->varArgs)
+ {
+ arg=arg.stripWhiteSpace();
+ arg+=',';
+ }
+ else
+ {
+ QString argKey;
+ argKey.sprintf("@%d",argCount++); // key name
+ arg=arg.stripWhiteSpace();
+ // add argument to the lookup table
+ argTable.insert(argKey, new QString(arg));
+ arg.resize(0);
+ if (c==')') // end of the argument list
+ {
+ done=TRUE;
+ }
+ }
+ }
+ else if (c=='\"') // append literal strings
+ {
+ arg+=c;
+ char pc=c;
+ bool found=FALSE;
+ while (!found && (cc=getNextChar(expr,rest,j))!=EOF)
+ {
+ found = pc!='\\' && cc=='"';
+ c=(char)cc;
+ pc=c;
+ arg+=c;
+ }
+ }
+ else if (c=='\'') // append literal characters
+ {
+ arg+=c;
+ char pc=c;
+ bool found=FALSE;
+ while (!found && (cc=getNextChar(expr,rest,j))!=EOF)
+ {
+ found = pc!='\\' && cc=='\'';
+ c=(char)cc;
+ pc=c;
+ arg+=c;
+ }
+ }
+ else // append other characters
+ {
+ arg+=c;
+ }
+ }
+
+ // FASE 2: apply the macro function
+ if (argCount==def->nargs ||
+ (argCount>def->nargs && def->varArgs)) // matching parameters lists
+ {
+ uint k=0;
+ // substitution of all formal arguments
+ QString resExpr;
+ const QString d=def->definition.stripWhiteSpace();
+ bool inString=FALSE;
+ while (k<d.length())
+ {
+ if (d.at(k)=='@') // maybe a marker, otherwise an escaped @
+ {
+ if (d.at(k+1)=='@') // escaped @ => copy it (is unescaped later)
+ {
+ k+=2;
+ resExpr+="@@"; // we unescape these later
+ }
+ else if (d.at(k+1)=='-') // no-rescan marker
+ {
+ k+=2;
+ resExpr+="@-";
+ }
+ else // argument marker => read the argument number
+ {
+ QString key="@";
+ QString *subst=0;
+ bool hash=FALSE;
+ int l=k-1;
+ // search for ## backward
+ if (l>=0 && d.at(l)=='"') l--;
+ while (l>=0 && d.at(l)==' ') l--;
+ if (l>0 && d.at(l)=='#' && d.at(l-1)=='#') hash=TRUE;
+ k++;
+ // scan the number
+ while (k<d.length() && d.at(k)>='0' && d.at(k)<='9') key+=d.at(k++);
+ if (!hash)
+ {
+ // search for ## forward
+ l=k;
+ if (l<(int)d.length() && d.at(l)=='"') l++;
+ while (l<(int)d.length() && d.at(l)==' ') l++;
+ if (l<(int)d.length()-1 && d.at(l)=='#' && d.at(l+1)=='#') hash=TRUE;
+ }
+ //printf("request key %s result %s\n",key.data(),args[key]->data());
+ if (key.length()>1 && (subst=argTable[key]))
+ {
+ QString substArg=*subst;
+ // only if no ## operator is before or after the argument
+ // marker we do macro expansion.
+ if (!hash) expandExpression(substArg,0,0);
+ if (inString)
+ {
+ //printf("`%s'=stringize(`%s')\n",stringize(*subst).data(),subst->data());
+
+ // if the marker is inside a string (because a # was put
+ // before the macro name) we must escape " and \ characters
+ resExpr+=stringize(substArg);
+ }
+ else
+ {
+ resExpr+=substArg;
+ }
+ }
+ }
+ }
+ else // no marker, just copy
+ {
+ if (!inString && d.at(k)=='\"')
+ {
+ inString=TRUE; // entering a literal string
+ }
+ else if (inString && d.at(k)=='\"' && d.at(k-1)!='\\')
+ {
+ inString=FALSE; // leaving a literal string
+ }
+ resExpr+=d.at(k++);
+ }
+ }
+ len=j-pos;
+ result=resExpr;
+ //printf("result after substitution `%s' expr=`%s'\n",
+ // result.data(),expr.mid(pos,len).data());
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+}
+
+
+/*! returns the next identifier in string \a expr by starting at position \a p.
+ * The position of the identifier is returned (or -1 if nothing is found)
+ * and \a l is its length. Any quoted strings are skipping during the search.
+ */
+static int getNextId(const QString &expr,int p,int *l)
+{
+ int n;
+ while (p<(int)expr.length())
+ {
+ char c=expr.at(p++);
+ if (isalpha(c) || c=='_') // read id
+ {
+ n=p-1;
+ while (p<(int)expr.length() && isId(expr.at(p))
+ ) p++;
+ *l=p-n;
+ return n;
+ }
+ else if (c=='"') // skip string
+ {
+ char pc=c;
+ if (p<(int)expr.length()) c=expr.at(p);
+ while (p<(int)expr.length() && (c!='"' || pc=='\\'))
+ {
+ pc=c;
+ c=expr.at(p);
+ p++;
+ }
+ }
+ }
+ return -1;
+}
+
+/*! preforms recursive macro expansion on the string \a expr
+ * starting at position \a pos.
+ * May read additional characters from the input while re-scanning!
+ * If \a expandAll is \c TRUE then all macros in the expression are
+ * expanded, otherwise only the first is expanded.
+ */
+static void expandExpression(QString &expr,QString *rest,int pos)
+{
+ //printf("expandExpression(%s,%s)\n",expr.data(),rest ? rest->data() : 0);
+ QString macroName;
+ QString expMacro;
+ int i=pos,l,p,len;
+ while ((p=getNextId(expr,i,&l))!=-1) // search for an macro name
+ {
+ bool replaced=FALSE;
+ macroName=expr.mid(p,l);
+ //printf("macroName %s found\n",macroName.data());
+ if (p<2 || !(expr.at(p-2)=='@' && expr.at(p-1)=='-')) // no-rescan marker?
+ {
+ if (expandedDict->find(macroName)==0) // expand macro
+ {
+ Define *def=isDefined(macroName);
+ //printf("name is not an expanded macro def=%s\n",def ? def->name.data() : 0);
+ if (def && def->nargs==0) // simple macro
+ {
+ // substitute the definition of the macro
+ expMacro=def->definition.stripWhiteSpace();
+ replaced=TRUE;
+ len=l;
+ //printf("simple macro expansion=`%s'->`%s'\n",macroName.data(),expMacro.data());
+ }
+ else if (def && def->nargs>0) // function macro
+ {
+ replaced=replaceFunctionMacro(expr,rest,p+l,len,def,expMacro);
+ len+=l;
+ }
+
+ if (replaced) // expand the macro and rescan the expression
+ {
+ //printf("replacing `%s'->`%s'\n",expr.mid(p,len).data(),expMacro.data());
+ QString resultExpr=expMacro;
+ QString restExpr=expr.right(expr.length()-len-p);
+ processConcatOperators(resultExpr);
+ expandedDict->insert(macroName,def);
+ expandExpression(resultExpr,&restExpr,0);
+ expandedDict->remove(macroName);
+ expr=expr.left(p)+resultExpr+restExpr;
+ i=p;
+ //printf("new expression: %s\n",expr.data());
+ }
+ else // move to the next macro name
+ {
+ //printf("moving to the next macro old=%d new=%d\n",i,p+l);
+ i=p+l;
+ }
+ }
+ else // move to the next macro name
+ {
+ expr=expr.left(p)+"@-"+expr.right(expr.length()-p);
+ //printf("macro already expanded, moving to the next macro expr=%s\n",expr.data());
+ i=p+l+2;
+ //i=p+l;
+ }
+ }
+ else // no re-scan marker found, skip the macro name
+ {
+ //printf("skipping marked macro\n");
+ i=p+l;
+ }
+ }
+}
+
+/*! replaces all occurrences of @@ in \a s by @
+ * All identifiers found are replaced by 0L
+ * \par assumption:
+ * \a s only contains pairs of @@'s.
+ */
+QString removeIdsAndMarkers(const char *s)
+{
+ //printf("removeIdsAndMarkers(%s)\n",s);
+ const char *p=s;
+ char c;
+ bool inNum=FALSE;
+ QString result;
+ if (p)
+ {
+ while ((c=*p))
+ {
+ if (c=='@') // replace @@ with @
+ {
+ if (*(p+1)=='@')
+ {
+ result+=c;
+ }
+ p+=2;
+ }
+ else if (isdigit(c))
+ {
+ result+=c;
+ p++;
+ inNum=TRUE;
+ }
+ else if ((isalpha(c) || c=='_') && !inNum) // replace identifier with 0L
+ {
+ result+="0L";
+ p++;
+ while ((c=*p) && isId(c)) p++;
+ }
+ else
+ {
+ result+=c;
+ char lc=tolower(c);
+ if (lc!='l' && lc!='u') inNum=FALSE;
+ p++;
+ }
+ }
+ }
+ return result;
+}
+
+/*! replaces all occurrences of @@ in \a s by @
+ * \par assumption:
+ * \a s only contains pairs of @@'s
+ */
+QString removeMarkers(const char *s)
+{
+ const char *p=s;
+ char c;
+ QString result;
+ if (p)
+ {
+ while ((c=*p))
+ {
+ if (c=='@') // replace @@ with @
+ {
+ if (*(p+1)=='@')
+ {
+ result+=c;
+ }
+ p+=2;
+ }
+ else
+ {
+ result+=c;
+ p++;
+ }
+ }
+ }
+ return result;
+}
+
+/*! compute the value of the expression in string \a expr.
+ * If needed the function may read additional characters from the input.
+ */
+
+bool computeExpression(const QString &expr)
+{
+ QString e=expr;
+ expandExpression(e,0,0);
+ e = removeIdsAndMarkers(e);
+ if (e.length()==0) return FALSE;
+ //printf("computeExpession(%s)\n",e.data());
+ return parseCppExpression(e);
+}
+
+/*! expands the macro definition in \a name
+ * If needed the function may read additional characters from the input
+ */
+
+QString expandMacro(const QString &name)
+{
+ QString n=name;
+ expandExpression(n,0,0);
+ n=removeMarkers(n);
+ //printf("expandMacro `%s'->`%s'\n",name.data(),n.data());
+ return n;
+}
+
+Define *newDefine()
+{
+ Define *def=new Define;
+ def->name = defName;
+ def->definition = defText.stripWhiteSpace();
+ def->nargs = defArgs;
+ def->fileName = yyFileName;
+ def->lineNr = yyLineNr;
+ def->varArgs = defVarArgs;
+ return def;
+}
+
+void addDefine()
+{
+ bool ambig;
+ FileDef *fd=findFileDef(&inputNameDict,yyFileName,ambig);
+ MemberDef *md=new MemberDef("#define",defName,defArgsStr,0,
+ Public,Normal,FALSE,FALSE,MemberDef::Define,0,0);
+ md->setDefFile(yyFileName);
+ md->setDefLine(yyLineNr);
+ md->setFileDef(fd);
+ md->setDefinition("#define "+defName+defArgsStr);
+
+ MemberName *mn=functionNameDict[defName];
+ if (mn==0)
+ {
+ mn = new MemberName(defName);
+ functionNameList.inSort(mn);
+ functionNameDict.insert(defName,mn);
+ }
+ mn->append(md);
+ if (fd) fd->insertMember(md);
+
+ Define *d;
+ if ((d=defineDict[defName])==0) defineDict.insert(defName,newDefine());
+
+}
+
+static void outputChar(char c)
+{
+ if (includeStack.isEmpty()) outputBuf->addChar(c);
+}
+
+static void outputArray(const char *a,int len)
+{
+ if (includeStack.isEmpty()) outputBuf->addArray(a,len);
+}
+
+static void readIncludeFile(const QString &inc)
+{
+ if (!searchIncludeFlag) return; // do not read include files
+ uint i=0;
+ // find the start of the include file name
+ while (i<inc.length() &&
+ (inc.at(i)==' ' || inc.at(i)=='"' || inc.at(i)=='<')
+ ) i++;
+ uint s=i;
+ // find the end of the include file name
+ while (i<inc.length() &&
+ inc.at(i)!='"' && inc.at(i)!='>') i++;
+ if (s<inc.length() && i>s) // valid include file name found
+ {
+ QString incFileName=inc.mid(s,i-s).stripWhiteSpace();
+
+ FILE *f;
+ QString oldFileName=yyFileName.copy();
+ if ((f=findFile(incFileName))) // see if the include file can be found
+ {
+#if SHOW_INCLUDES
+ for (i=0;i<includeStack.count();i++) msg(" ");
+ msg("#include %s: parsing...\n",incFileName.data());
+#endif
+ // store the state of the old file
+ FileState *fs=new FileState;
+ fs->bufState=YY_CURRENT_BUFFER;
+ fs->lineNr=yyLineNr;
+ fs->fileName=oldFileName;
+ fs->filePtr=f;
+ // push the state on the stack
+ includeStack.push(fs);
+ // set the scanner to the include file
+ preYYin=f;
+ yy_switch_to_buffer(yy_create_buffer(preYYin, YY_BUF_SIZE));
+ }
+ else
+ {
+#if SHOW_INCLUDES
+ msg("#include %s: not found! skipping...\n",incFileName.data());
+ //printf("Error: include file %s not found\n",yytext);
+#endif
+ }
+ }
+}
+
+/* ----------------------------------------------------------------- */
+
+%}
+
+ID [a-z_A-Z][a-z_A-Z0-9]*
+B [ \t]
+BN [ \t\r\n]
+
+%x Start
+%x Command
+%x SkipCommand
+%x SkipLine
+%x CopyLine
+%x Include
+%x IncludeID
+%x DefineName
+%x DefineArg
+%x DefineText
+%x SkipCPPBlock
+%x Ifdef
+%x Ifndef
+%x SkipCComment
+%x SkipCPPComment
+%x RemoveCComment
+%x RemoveCPPComment
+%x Guard
+%x DefinedExpr1
+%x DefinedExpr2
+%x SkipDoubleQuote
+%x SkipSingleQuote
+%x UndefName
+%x IgnoreLine
+%x FindDefineArgs
+%x ReadString
+
+%%
+
+<*>\x06
+<*>\x00
+<*>\r
+ /*
+<Start>^{B}*([^ \t#\n\/][^\n]*)?"\n" {
+ //printf("%s line %d: %s",yyFileName.data(),yyLineNr,yytext);
+ if (includeStack.isEmpty())
+ {
+ //preprocessedFile+=yytext;
+ //char *s=yytext,c;
+ //if (s) while ((c=*s++)) *dataPtr++=c;
+ outputBuf->addArray(yytext,yyleng);
+ }
+ yyLineNr++;
+ }
+ */
+<Start>^{B}*"#" { BEGIN(Command); }
+<Start>^{B}*/[^#] {
+ outputArray(yytext,yyleng);
+ BEGIN(CopyLine);
+ }
+ /*
+<CopyLine>[^\n/]+ {
+ outputArray(yytext,yyleng);
+ }
+ */
+<CopyLine>{ID}/{BN}*"(" {
+ if (includeStack.isEmpty() &&
+ macroExpansionFlag &&
+ /* (expandDefine=fileDefineCache->findDefine(yyFileName,yytext)) */
+ fileDefineDict->find(yytext)
+ )
+ {
+ roundCount=0;
+ defArgsStr=yytext;
+ findDefArgContext = CopyLine;
+ BEGIN(FindDefineArgs);
+ }
+ else
+ {
+ outputArray(yytext,yyleng);
+ }
+ }
+<CopyLine>{ID} {
+ Define *def=0;
+ if (includeStack.isEmpty() &&
+ macroExpansionFlag &&
+ (def=fileDefineDict->find(yytext)) &&
+ def->nargs==0
+ )
+ {
+ QString name=yytext;
+ QString result=expandMacro(name);
+ outputArray(result,result.length());
+ }
+ else
+ {
+ outputArray(yytext,yyleng);
+ }
+ }
+<CopyLine>. {
+ outputChar(*yytext);
+ }
+<CopyLine>\n {
+ outputChar('\n');
+ BEGIN(Start);
+ yyLineNr++;
+ }
+<FindDefineArgs>"(" {
+ defArgsStr+='(';
+ roundCount++;
+ }
+<FindDefineArgs>")" {
+ defArgsStr+=')';
+ roundCount--;
+ if (roundCount==0)
+ {
+ QString result=expandMacro(defArgsStr);
+ if (findDefArgContext==CopyLine)
+ {
+ outputArray(result,result.length());
+ BEGIN(findDefArgContext);
+ }
+ else // findDefArgContext==IncludeID
+ {
+ readIncludeFile(result);
+ BEGIN(Start);
+ }
+ }
+ }
+ /*
+<FindDefineArgs>")"{B}*"(" {
+ defArgsStr+=yytext;
+ }
+ */
+<FindDefineArgs>"\"" {
+ defArgsStr+=*yytext;
+ BEGIN(ReadString);
+ }
+<FindDefineArgs>\n {
+ yyLineNr++;
+ outputChar('\n');
+ }
+<FindDefineArgs>"@" {
+ defArgsStr+="@@";
+ }
+<FindDefineArgs>. {
+ defArgsStr+=*yytext;
+ }
+<ReadString>"\\\"" {
+ defArgsStr+=yytext;
+ }
+<ReadString>"\"" {
+ defArgsStr+=*yytext;
+ BEGIN(FindDefineArgs);
+ }
+<ReadString>. {
+ defArgsStr+=*yytext;
+ }
+<Command>"include"{B}*/{ID} {
+ if (macroExpansionFlag)
+ BEGIN(IncludeID);
+ }
+<Command>"include"{B}*[<"] {
+ BEGIN(Include);
+ }
+<Command>"define"{B}+ {
+ //printf("!!!DefineName\n");
+ BEGIN(DefineName);
+ }
+<Command>"ifdef"/{B}*"(" {
+ incrLevel();
+ guardExpr.resize(0);
+ BEGIN(DefinedExpr2);
+ }
+<Command>"ifdef"/{B}+ {
+ //printf("Pre.l: ifdef\n");
+ incrLevel();
+ guardExpr.resize(0);
+ BEGIN(DefinedExpr1);
+ }
+<Command>"ifndef"/{B}*"(" {
+ incrLevel();
+ guardExpr="! ";
+ BEGIN(DefinedExpr2);
+ }
+<Command>"ifndef"/{B}+ {
+ incrLevel();
+ guardExpr="! ";
+ BEGIN(DefinedExpr1);
+ }
+<Command>"if"/[ \t(] {
+ incrLevel();
+ guardExpr.resize(0);
+ BEGIN(Guard);
+ }
+<Command>"elif"/[ \t(] {
+ if (!otherCaseDone())
+ {
+ guardExpr.resize(0);
+ BEGIN(Guard);
+ }
+ else
+ {
+ ifcount=0;
+ BEGIN(SkipCPPBlock);
+ }
+ }
+<Command>"else"/[^a-z_A-Z0-9] {
+ //printf("else levelGuard[%d]=%d\n",level-1,levelGuard[level-1]);
+ if (otherCaseDone())
+ {
+ ifcount=0;
+ BEGIN(SkipCPPBlock);
+ }
+ else
+ {
+ setCaseDone(TRUE);
+ //levelGuard[level-1]=TRUE;
+ }
+ }
+<Command>"undef"{B}+ {
+ BEGIN(UndefName);
+ }
+<Command>"elif"/[ \t(] {
+ if (!otherCaseDone())
+ {
+ guardExpr.resize(0);
+ BEGIN(Guard);
+ }
+ }
+<Command>"endif"/[^a-z_A-Z0-9] {
+ //printf("Pre.l: #endif\n");
+ decrLevel();
+ }
+<Command,IgnoreLine>\n {
+ outputChar('\n');
+ BEGIN(Start);
+ yyLineNr++;
+ }
+<Command>{ID} { // unknown directive
+ BEGIN(IgnoreLine);
+ }
+<IgnoreLine>.
+<Command>.
+<UndefName>{ID} {
+ Define *def;
+ if ((def=isDefined(yytext)))
+ {
+ //printf("undefining %s\n",yytext);
+ def->undef=TRUE;
+ }
+ BEGIN(Start);
+ }
+<Guard>\\\n {
+ outputChar('\n');
+ guardExpr+=' ';
+ yyLineNr++;
+ }
+<Guard>"defined"/{B}*"(" {
+ BEGIN(DefinedExpr2);
+ }
+<Guard>"defined"/{B}+ {
+ BEGIN(DefinedExpr1);
+ }
+<Guard>. { guardExpr+=*yytext; }
+<Guard>\n {
+ outputChar('\n');
+ yyLineNr++;
+ //printf("Guard: `%s'\n",
+ // guardExpr.data());
+ bool guard=computeExpression(guardExpr);
+ setCaseDone(guard);
+ //printf("if levelGuard[%d]=%d\n",level-1,levelGuard[level-1]);
+ if (guard)
+ {
+ BEGIN(Start);
+ }
+ else
+ {
+ ifcount=0;
+ BEGIN(SkipCPPBlock);
+ }
+ }
+<DefinedExpr1,DefinedExpr2>\\\n { yyLineNr++; outputChar('\n'); }
+<DefinedExpr1>{ID} {
+ if (isDefined(yytext))
+ guardExpr+=" 1L ";
+ else
+ guardExpr+=" 0L ";
+ BEGIN(Guard);
+ }
+<DefinedExpr2>{ID} {
+ if (isDefined(yytext))
+ guardExpr+=" 1L ";
+ else
+ guardExpr+=" 0L ";
+ }
+<DefinedExpr1,DefinedExpr2>\n { // should not happen, handle anyway
+ ifcount=0;
+ BEGIN(SkipCPPBlock);
+ }
+<DefinedExpr2>")" {
+ BEGIN(Guard);
+ }
+<DefinedExpr1,DefinedExpr2>.
+<SkipCPPBlock>^{B}*"#" { BEGIN(SkipCommand); }
+<SkipCPPBlock>^{B}*/[^#] { BEGIN(SkipLine); }
+<SkipCPPBlock>.
+<SkipCommand>"if"(("n")?("def"))?/[ \t(] {
+ incrLevel();
+ ifcount++;
+ //printf("#if... depth=%d\n",ifcount);
+ }
+<SkipCommand>"else"/[^a-z_A-Z0-9] {
+ //printf("Else! ifcount=%d otherCaseDone=%d\n",ifcount,otherCaseDone());
+ if (ifcount==0 && !otherCaseDone())
+ {
+ setCaseDone(TRUE);
+ //outputChar('\n');
+ BEGIN(Start);
+ }
+ }
+<SkipCommand>"elif"/[ \t(] {
+ if (ifcount==0)
+ {
+ if (!otherCaseDone())
+ {
+ guardExpr.resize(0);
+ BEGIN(Guard);
+ }
+ else
+ {
+ BEGIN(Start);
+ }
+ }
+ }
+<SkipCommand>"endif"/[^a-z_A-Z0-9] {
+ decrLevel();
+ if (--ifcount<0)
+ {
+ //outputChar('\n');
+ BEGIN(Start);
+ }
+ }
+<SkipCommand>\n {
+ outputChar('\n');
+ yyLineNr++;
+ BEGIN(SkipCPPBlock);
+ }
+<SkipCommand>{ID} { // unknown directive
+ BEGIN(SkipLine);
+ }
+<SkipCommand>.
+<SkipLine>[^/\n]+
+<SkipLine>.
+<SkipLine>"//" {
+ lastCPPContext=YY_START;
+ BEGIN(RemoveCPPComment);
+ }
+<SkipLine>"/*" {
+ lastCContext=YY_START;
+ BEGIN(RemoveCComment);
+ }
+<SkipLine>\n {
+ outputChar('\n');
+ yyLineNr++;
+ BEGIN(SkipCPPBlock);
+ }
+<IncludeID>{ID}{B}*/"(" {
+ roundCount=0;
+ defArgsStr=yytext;
+ findDefArgContext = IncludeID;
+ BEGIN(FindDefineArgs);
+ }
+<IncludeID>{ID} {
+ readIncludeFile(expandMacro(yytext));
+ BEGIN(Start);
+ }
+<Include>[^\">\n]+[\">] {
+ QString incName=yytext;
+ //int l=incName.length();
+ //QString incFileName=incName.left(l-1);
+ //if (fileDefineCache->fileCached(incFileName))
+ //{
+ // printf("file already cached!\n");
+ // fileDefineCache->merge(incFileName,yyFileName);
+ //}
+ //else if ((f=findFile(incFileName)))
+ readIncludeFile(incName);
+
+ BEGIN(Start);
+ }
+<DefineName>{ID}/"(" {
+ //printf("Define() `%s'\n",yytext);
+ argDict = new QDict<int>(31);
+ argDict->setAutoDelete(TRUE);
+ defArgs = 0;
+ defArgsStr.resize(0);
+ defText.resize(0);
+ defName = yytext;
+ defVarArgs = FALSE;
+ BEGIN(DefineArg);
+ }
+<DefineName>{ID}/{B}* {
+ //printf("Define `%s'\n",yytext);
+ argDict = 0;
+ defArgs = 0;
+ defArgsStr.resize(0);
+ defText.resize(0);
+ defName = yytext;
+ defVarArgs = FALSE;
+ QString tmp=(QString)"#define "+defName+defArgsStr;
+ outputArray(tmp.data(),tmp.length());
+ quoteArg=FALSE;
+ BEGIN(DefineText);
+ }
+<DefineArg>","{B}* { defArgsStr+=yytext; }
+<DefineArg>"("{B}* { defArgsStr+=yytext; }
+<DefineArg>")"{B}* {
+ defArgsStr+=yytext;
+ QString tmp=(QString)"#define "+defName+defArgsStr;
+ outputArray(tmp.data(),tmp.length());
+ quoteArg=FALSE;
+ BEGIN(DefineText);
+ }
+<DefineArg>{ID}("..."?) {
+ //printf("Define addArg(%s)\n",yytext);
+ QString argName=yytext;
+ defVarArgs = yytext[yyleng-1]=='.';
+ if (defVarArgs)
+ argName=argName.left(argName.length()-3);
+ defArgsStr+=yytext;
+ argDict->insert(argName,new int(defArgs));
+ defArgs++;
+ }
+<DefineText>"/*" {
+ outputChar('/');outputChar('*');
+ defText+=' ';
+ lastCContext=YY_START;
+ BEGIN(SkipCComment);
+ }
+<DefineText>"//" {
+ outputChar('/');outputChar('/');
+ lastCPPContext=YY_START;
+ BEGIN(SkipCPPComment);
+ }
+<SkipCComment>"*/" {
+ outputChar('*');outputChar('/');
+ BEGIN(lastCContext);
+ }
+<SkipCComment>"//" {
+ outputChar('/');outputChar('/');
+ }
+<SkipCComment>"/*" {
+ outputChar('/');outputChar('*');
+ }
+<SkipCComment>[^*\n]+ {
+ outputArray(yytext,yyleng);
+ }
+<SkipCComment>\n {
+ yyLineNr++;
+ outputChar('\n');
+ }
+<SkipCComment>. {
+ outputChar(*yytext);
+ }
+<RemoveCComment>"*/" { BEGIN(lastCContext); }
+<RemoveCComment>"//"
+<RemoveCComment>"/*"
+<RemoveCComment>[^*\n]+
+<RemoveCComment>\n { yyLineNr++; outputChar('\n'); }
+<RemoveCComment>.
+<SkipCPPComment,RemoveCPPComment>\n {
+ unput(*yytext);
+ BEGIN(lastCPPContext);
+ }
+<SkipCPPComment>"/*" {
+ outputChar('/');outputChar('*');
+ }
+<SkipCPPComment>"//" {
+ outputChar('/');outputChar('/');
+ }
+<SkipCPPComment>[^\n]+ {
+ outputArray(yytext,yyleng);
+ }
+<SkipCPPComment>. {
+ outputChar(*yytext);
+ }
+<RemoveCPPComment>"/*"
+<RemoveCPPComment>"//"
+<RemoveCPPComment>[^\n]+
+<RemoveCPPComment>.
+<DefineText>"#" {
+ quoteArg=TRUE;
+ }
+<DefineText>{ID} {
+ //bool quote=FALSE;
+ //char *p=yytext;
+ //if (p[0]=='#')
+ //{
+ // p++;
+ // quote=TRUE;
+ // defText+="\"";
+ //}
+ if (quoteArg)
+ {
+ defText+="\"";
+ }
+ if (defArgs>0)
+ {
+ int *n;
+ if ((n=(*argDict)[yytext]))
+ {
+ if (!quoteArg) defText+=' ';
+ defText+='@';
+ QString numStr;
+ numStr.setNum(*n);
+ defText+=numStr;
+ if (!quoteArg) defText+=' ';
+ }
+ else
+ {
+ defText+=yytext;
+ }
+ }
+ else
+ {
+ defText+=yytext;
+ }
+ if (quoteArg)
+ {
+ defText+="\"";
+ }
+ quoteArg=FALSE;
+ }
+<DefineText>\\\n {
+ outputChar('\n');
+ defText += ' '; yyLineNr++;
+ }
+<DefineText>\n {
+ outputChar('\n');
+ Define *def=0;
+ //printf("Define name=`%s' text=`%s'\n",defName.data(),defText.data());
+ if (includeStack.isEmpty()) addDefine();
+ if (!onlyPredefinedFlag && (def=fileDefineDict->find(defName))==0)
+ {
+ fileDefineDict->insert(defName,newDefine());
+ }
+ //if ((def=fileDefineCache->findDefine(yyFileName,defName))==0)
+ //{
+ // printf("define is not found\n");
+ // fileDefineCache->insertDefine(yyFileName,defName,newDefine());
+ //}
+ else if (def)// name already exists
+ {
+ //printf("define found\n");
+ if (def->undef) // undefined name
+ {
+ def->undef = FALSE;
+ def->name = defName;
+ def->definition = defText.stripWhiteSpace();
+ def->nargs = defArgs;
+ def->fileName = yyFileName;
+ def->lineNr = yyLineNr;
+ }
+ else
+ {
+ //printf("Error: define %s is defined more than once!\n",defName.data());
+ }
+ }
+ delete argDict;
+ yyLineNr++;
+ BEGIN(Start);
+ }
+<DefineText>{B}* { defText += ' '; }
+<DefineText>{B}*"##"{B}* { defText += "##"; }
+<DefineText>"@" { defText += "@@"; }
+<DefineText>\" { defText += *yytext;
+ BEGIN(SkipDoubleQuote);
+ }
+<DefineText>\' { defText += *yytext;
+ BEGIN(SkipSingleQuote);
+ }
+<SkipDoubleQuote>\" {
+ defText += *yytext;
+ BEGIN(DefineText);
+ }
+<SkipSingleQuote>\' {
+ defText += *yytext;
+ BEGIN(DefineText);
+ }
+<SkipDoubleQuote>. { defText += *yytext; }
+<SkipSingleQuote>. { defText += *yytext; }
+<DefineText>. { defText += *yytext; }
+<<EOF>> {
+ //printf("End of include file\n");
+ //printf("Include stack depth=%d\n",includeStack.count());
+ if (includeStack.isEmpty())
+ {
+ //printf("Terminating scanner!\n");
+ yyterminate();
+ }
+ else
+ {
+ FileState *fs=includeStack.pop();
+ //fileDefineCache->merge(yyFileName,fs->fileName);
+ if (inputFilter.isEmpty())
+ fclose(fs->filePtr);
+ else
+ pclose(fs->filePtr);
+ YY_BUFFER_STATE oldBuf = YY_CURRENT_BUFFER;
+ yy_switch_to_buffer( fs->bufState );
+ yy_delete_buffer( oldBuf );
+ yyLineNr=fs->lineNr;
+ yyFileName=fs->fileName.copy();
+ //printf("######## FileName %s\n",yyFileName.data());
+ delete fs;
+ }
+ }
+<*>"/*" {
+ outputChar('/');outputChar('*');
+ lastCContext=YY_START;
+ BEGIN(SkipCComment);
+ }
+<*>"//" {
+ outputChar('/');outputChar('/');
+ lastCPPContext=YY_START;
+ BEGIN(SkipCPPComment);
+ }
+<*>\n {
+ outputChar('\n');
+ yyLineNr++;
+ }
+<*>. {
+ outputChar(*yytext);
+ }
+
+%%
+
+/*@ ----------------------------------------------------------------------------
+ */
+
+static int getNextChar(const QString &expr,QString *rest,uint &pos)
+{
+ //printf("getNextChar(%s,%s,%d)\n",expr.data(),rest ? rest->data() : 0,pos);
+ if (pos<expr.length())
+ {
+ //printf("%c=expr()\n",expr.at(pos));
+ return expr.at(pos++);
+ }
+ else if (rest && rest->length()>0)
+ {
+ int cc=rest->at(0);
+ *rest=rest->right(rest->length()-1);
+ //printf("%c=rest\n",cc);
+ return cc;
+ }
+ else
+ {
+ int cc=yyinput();
+ //printf("%c=yyinput()\n",cc);
+ return cc;
+ }
+}
+
+static int getCurrentChar(const QString &expr,QString *rest,uint pos)
+{
+ //printf("getCurrentChar(%s,%s,%d)\n",expr.data(),rest ? rest->data() : 0,pos);
+ if (pos<expr.length())
+ {
+ //printf("%c=expr()\n",expr.at(pos));
+ return expr.at(pos);
+ }
+ else if (rest && rest->length()>0)
+ {
+ int cc=rest->at(0);
+ //printf("%c=rest\n",cc);
+ return cc;
+ }
+ else
+ {
+ int cc=yyinput();unput(cc);
+ //printf("%c=yyinput()\n",cc);
+ return cc;
+ }
+}
+
+static void unputChar(const QString &expr,QString *rest,uint &pos,char c)
+{
+ //printf("unputChar(%s,%s,%d,%c)\n",expr.data(),rest ? rest->data() : 0,pos,c);
+ if (pos<expr.length())
+ {
+ pos++;
+ }
+ else if (rest)
+ {
+ //printf("Prepending to rest!\n");
+ char cs[2];cs[0]=c;cs[1]='\0';
+ rest->prepend(cs);
+ }
+ else
+ {
+ unput(c);
+ }
+ //printf("result: unputChar(%s,%s,%d,%c)\n",expr.data(),rest ? rest->data() : 0,pos,c);
+}
+
+void addSearchDir(const char *dir)
+{
+ QFileInfo fi(dir);
+ if (fi.isDir()) pathList->append(fi.absFilePath());
+}
+
+void initPreprocessor()
+{
+ pathList = new QStrList;
+ addSearchDir(".");
+ //defineNameList.setAutoDelete(TRUE);
+ //defineNameList.clear();
+ defineDict.clear();
+ //fileDefineCache = new DefineCache(1009);
+ expandedDict = new DefineDict(17);
+ fileDefineDict = new DefineDict(1009);
+}
+
+void cleanupPreprocessor()
+{
+ //delete fileDefineCache;
+ delete fileDefineDict;
+ delete expandedDict;
+ delete pathList;
+}
+
+
+void preprocessFile(const char *fileName,BufStr &output)
+{
+#if DUMP_OUTPUT
+ uint orgOffset=output.curPos();
+#endif
+
+ outputBuf=&output;
+ includeStack.setAutoDelete(TRUE);
+ includeStack.clear();
+ fileDefineDict->setAutoDelete(TRUE);
+ fileDefineDict->clear();
+ expandedDict->setAutoDelete(FALSE);
+ expandedDict->clear();
+
+ // add predefined macros
+ char *defStr = predefined.first();
+ while (defStr)
+ {
+ QString ds = defStr;
+ int i;
+ if ((i=ds.find('='))==-1)
+ {
+ if (ds.length()>0)
+ {
+ Define *def = new Define;
+ def->name = ds;
+ def->definition = "1";
+ def->nargs = 0;
+ fileDefineDict->insert(ds,def);
+ }
+ }
+ else
+ {
+ if (i>0 && (int)ds.length()>i)
+ {
+ Define *def = new Define;
+ def->name = ds.left(i);
+ def->definition = ds.right(ds.length()-i-1);
+ def->nargs = 0;
+ fileDefineDict->insert(ds.left(i),def);
+ }
+ }
+ defStr=predefined.next();
+ }
+
+ if (inputFilter.isEmpty())
+ {
+ preYYin = fopen(fileName,"r");
+ if (!preYYin)
+ {
+ err("Error: could not open file %s\n",fileName);
+ return;
+ }
+ }
+ else
+ {
+ QString cmd = inputFilter+" "+fileName;
+ preYYin = popen(cmd,"r");
+ if (!preYYin)
+ {
+ err("Error: could not execute filter %s\n",cmd.data());
+ return;
+ }
+ }
+ yyLineNr = 1;
+ level = 0;
+ yyFileName = fileName;
+ BEGIN( Start );
+ preYYlex();
+ if (inputFilter.isEmpty())
+ fclose(preYYin);
+ else
+ pclose(preYYin);
+
+#if DUMP_OUTPUT
+ char *orgPos=output.data()+orgOffset;
+ char *newPos=output.data()+output.curPos();
+ printf("Resulting size: %d bytes\n",newPos-orgPos);
+ int line=1;
+ printf("---------\n00001 ");
+ while (orgPos<newPos)
+ {
+ putchar(*orgPos);
+ if (*orgPos=='\n') printf("%05d ",++line);
+ orgPos++;
+ }
+ printf("\n---------\n");
+#endif
+}
+
+
+extern "C" { // some bogus code to keep the compiler happy
+ int preYYwrap() { return 1 ; }
+ void preYYdummy() { yy_flex_realloc(0,0); }
+}
diff --git a/src/scanner.h b/src/scanner.h
new file mode 100644
index 0000000..59d5966
--- /dev/null
+++ b/src/scanner.h
@@ -0,0 +1,34 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#ifndef SCANNER_H
+#define SCANNER_H
+
+#include <stdio.h>
+#include <qlist.h>
+#include <qstring.h>
+
+#include "entry.h"
+#include "code.h"
+
+class OutputList;
+
+extern void parseMain(Entry *);
+extern void parseDoc(OutputList &ol,const char *clName, const char *memName,
+ const QString &docString);
+extern void parseExample(OutputList &ol,const QString &docString,
+ const char *fileName);
+#endif
diff --git a/src/scanner.l b/src/scanner.l
new file mode 100644
index 0000000..0beadae
--- /dev/null
+++ b/src/scanner.l
@@ -0,0 +1,3386 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+%{
+
+/*
+ * includes
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <iostream.h>
+#include <assert.h>
+#include <ctype.h>
+
+#include <qarray.h>
+#include <qstring.h>
+#include <qstack.h>
+#include <qregexp.h>
+
+#include "scanner.h"
+#include "entry.h"
+#include "doxygen.h"
+#include "message.h"
+#include "config.h"
+#include "util.h"
+#include "index.h"
+#include "defargs.h"
+#include "language.h"
+
+#ifndef WIN32
+#include <unistd.h>
+#endif
+
+#define YY_NEVER_INTERACTIVE 1
+
+/* -----------------------------------------------------------------
+ *
+ * statics
+ */
+static bool insideArgumentList;
+static QString className;
+static QString memberName;
+static QString refName;
+static OutputList * outDoc;
+static QString code;
+static QString linkRef;
+static QString linkText;
+static QString codeBlock;
+static const char * inputString;
+static int inputPosition;
+static int lastContext;
+static int lastCContext;
+static int lastDocContext;
+static int lastDocRelContext;
+static int lastCPPContext;
+static int lastSkipSharpContext;
+static int lastSkipRoundContext;
+static int lastBriefContext;
+static int lastVerbState;
+static int lastStringContext;
+static int lastCurlyContext;
+static int lastCodeState;
+static int lastAfterDocContext;
+static int lastGroupContext;
+static int lastFormulaContext;
+static int nextDefContext;
+static Protection protection;
+static Protection baseProt;
+static int bracketCount = 0 ;
+static int sharpCount = 0 ;
+static int roundCount = 0 ;
+static int ifCount = 0 ;
+static Entry* current_root = 0 ;
+static Entry* global_root = 0 ;
+static Entry* current = 0 ;
+static int yyLineNr = 0 ;
+static int anonCount = 0 ;
+static char yyFileName[2048] ;
+static bool sig;
+static bool slot;
+static bool gstat;
+static bool removeSlashes;
+static Specifier virt;
+static Specifier baseVirt;
+static bool exampleDoc;
+static QString exampleName;
+static QString htmlUrl,htmlText;
+static QString currentIncludeFile;
+static QString msType,msName,msArgs;
+static int includeFileOffset = 0;
+static int includeFileLength = 0;
+static bool firstLine;
+static bool isTypedef;
+static bool inParamBlock;
+static bool inExceptionBlock;
+static bool inSeeBlock;
+static bool inReturnBlock;
+static bool inAuthorBlock;
+static bool inVersionBlock;
+static bool inDateBlock;
+static bool inBugBlock;
+static bool inWarningBlock;
+static bool inParBlock;
+static bool firstSeeArg;
+static bool javaDocSee;
+static char afterDocTerminator;
+static int tmpDocType;
+static QString sectionLabel;
+static QString sectionTitle;
+static bool isSubsection;
+static QString funcPtrType;
+static QString templateStr;
+static QString baseName;
+static QString *specName;
+static QString formulaText;
+static QString sectionRef;
+
+// state variable for reading the argument list of a function
+static int argRoundCount;
+static int argSharpCount;
+static int currentArgumentContext;
+static int lastCopyArgStringContext;
+static int lastCopyArgContext;
+static QString *copyArgString;
+
+
+
+//-----------------------------------------------------------------------------
+
+static void initParser()
+{
+ insideArgumentList=FALSE;
+ className.resize(0);
+ memberName.resize(0);
+ refName.resize(0);
+ code.resize(0);
+ linkRef.resize(0);
+ linkText.resize(0);
+ codeBlock.resize(0);
+ htmlUrl.resize(0);
+ htmlText.resize(0);
+ currentIncludeFile.resize(0);
+ sectionLabel.resize(0);
+ sectionTitle.resize(0);
+ baseName.resize(0);
+ formulaText.resize(0);
+ protection = Public;
+ baseProt = Public;
+ bracketCount = 0;
+ sharpCount = 0;
+ roundCount = 0;
+ ifCount = 0;
+ sig = FALSE;
+ slot = FALSE;
+ gstat = FALSE;
+ virt = Normal;
+ baseVirt = Normal;
+ includeFileOffset = 0;
+ includeFileLength = 0;
+ firstLine = TRUE;
+ isTypedef = FALSE;
+ inParamBlock = FALSE;
+ inExceptionBlock = FALSE;
+ inSeeBlock = FALSE;
+ inReturnBlock = FALSE;
+ inAuthorBlock = FALSE;
+ inVersionBlock = FALSE;
+ inDateBlock = FALSE;
+ inBugBlock = FALSE;
+ inWarningBlock = FALSE;
+ inParBlock = FALSE;
+ firstSeeArg = FALSE;
+ javaDocSee = FALSE;
+ isSubsection = FALSE;
+}
+
+//-----------------------------------------------------------------------------
+
+void scanString(const char *s);
+
+//-----------------------------------------------------------------------------
+
+class TableElem
+{
+ public:
+ TableElem(int r,int c);
+ ~TableElem();
+ int getRow() { return row; }
+ int getCol() { return col; }
+ OutputList *outputList() { return ol; }
+
+ private:
+ OutputList *ol;
+ int row;
+ int col;
+};
+
+TableElem::TableElem(int r,int c)
+{
+ //printf("TableElem::TableElem(%d,%d)\n",r,c);
+ ol=new OutputList(outDoc);
+ outDoc=ol;
+ row=r;
+ col=c;
+}
+
+TableElem::~TableElem()
+{
+ //printf("TableElem::~TableElem(%d,%d)\n",row,col);
+ delete ol;
+}
+
+class Table
+{
+ public:
+ Table();
+ ~Table();
+ void newRow();
+ void newElem();
+
+ private:
+ OutputList *parentDoc;
+ QList<TableElem> *elemList;
+ int curRow;
+ int curCol;
+ int rows;
+ int cols;
+};
+
+Table::Table()
+{
+ parentDoc=outDoc;
+ elemList=new QList<TableElem>;
+ elemList->setAutoDelete(TRUE);
+ curRow=curCol=rows=cols=0;
+}
+
+Table::~Table()
+{
+ //printf("Table::~Table()\n");
+ // use elemList & cols & rows
+ if (cols>0 && rows>0)
+ {
+ parentDoc->startTable(cols);
+ TableElem *e=elemList->first();
+ while (e)
+ {
+ if (e->getRow()>0)
+ {
+ if (e->getCol()==0)
+ {
+ if (e->getRow()>1) parentDoc->endTableRow();
+ parentDoc->nextTableRow();
+ }
+ else
+ {
+ parentDoc->nextTableColumn();
+ }
+ *parentDoc+=*e->outputList();
+ parentDoc->endTableColumn();
+ }
+ e=elemList->next();
+ }
+ parentDoc->endTable();
+ }
+ delete elemList;
+ outDoc=parentDoc;
+}
+
+void Table::newRow()
+{
+ //printf("Table::newRow()\n");
+ curRow++;
+ if (curRow>rows) rows=curRow;
+ curCol=0;
+}
+
+void Table::newElem()
+{
+ //printf("Table::newElem(%d,%d)\n",curRow,curCol);
+ TableElem *te = new TableElem(curRow,curCol);
+ elemList->append(te);
+
+ curCol++;
+ if (curCol>cols) cols=curCol;
+}
+
+static QStack<Table> tableStack;
+static Table *curTable;
+
+static void startTable()
+{
+ //printf("startTable()\n");
+ curTable=new Table;
+ tableStack.push(curTable);
+}
+
+static void endTable()
+{
+ //printf("endTable()\n");
+ delete tableStack.pop(); // the destructor adds the table to the stream!
+ curTable=tableStack.top();
+}
+
+//-----------------------------------------------------------------------------
+
+static void lineCount()
+{
+ for( const char* c = yytext ; *c ; ++c )
+ yyLineNr += (*c == '\n') ;
+}
+
+static void endArgumentList()
+{
+ if (insideArgumentList)
+ {
+ insideArgumentList=FALSE;
+ outDoc->endItemList();
+ }
+}
+
+static void addType( Entry* current )
+{
+ if( current->type.length() )
+ current->type += ' ' ;
+ current->type += current->name ;
+ current->name.resize(0) ;
+ if( current->type.length() )
+ current->type += ' ' ;
+ current->type += current->args ;
+ current->args.resize(0) ;
+ current->argList->clear();
+}
+
+static void includeFile(OutputList &ol,const char *fileName,bool quiet)
+{
+ //FileInfo *f;
+ bool ambig;
+ FileDef *fd;
+ if ((fd=findFileDef(&exampleNameDict,fileName,ambig)))
+ {
+ currentIncludeFile=fileToString(fd->absFilePath());
+ includeFileOffset=0;
+ includeFileLength=currentIncludeFile.length();
+ OutputList codeFrag(&ol);
+ parseCode(codeFrag,0,currentIncludeFile,exampleDoc,exampleName);
+ if (!quiet)
+ {
+ ol.startCodeFragment();
+ ol+=codeFrag;
+ ol.endCodeFragment();
+ }
+ }
+ else if (ambig)
+ {
+ warn("Include file name %s is ambigious.\n",fileName);
+ warn("Possible candidates:\n");
+ //includeFileList.writeMatches(fileName);
+ showFileDefMatches(&exampleNameDict,fileName);
+ }
+ else
+ {
+ warn("Warning: example file %s is not found. ",fileName);
+ warn("Check your EXAMPLE_PATH\n");
+ }
+}
+
+static void verbIncludeFile(OutputList &ol,const char *name)
+{
+ //FileInfo *f;
+ bool ambig;
+ FileDef *fd;
+ if ((fd=findFileDef(&exampleNameDict,name,ambig)))
+ {
+ ol.startCodeFragment();
+ ol.codify(fileToString(fd->absFilePath()));
+ ol.endCodeFragment();
+ }
+ else if (ambig)
+ {
+ warn("Include file name %s is ambigious.\n",name);
+ warn("Possible candidates:\n");
+ showFileDefMatches(&exampleNameDict,name);
+ }
+ else
+ {
+ warn("Warning: example file %s is not found. ",name);
+ warn("Check your EXAMPLE_PATH\n");
+ }
+}
+
+
+static QString stripQuotes(const char *s)
+{
+ QString name;
+ if (s==0 || *s==0) return name;
+ name=s;
+ if (name.at(0)=='"' && name.at(name.length()-1)=='"')
+ {
+ name=name.mid(1,name.length()-2);
+ }
+ return name;
+}
+
+static QString stripKnownExtensions(const char *text)
+{
+ QString result=text;
+ if (result.right(4)==".tex") result=result.left(result.length()-4);
+ else if (result.right(5)==".html") result=result.left(result.length()-5);
+ //printf("%s stripKnowExtensions(%s)\n",result.data(),text);
+ return result;
+}
+
+static void skipLine(OutputList &ol,const char *key)
+{
+ bool found=FALSE;
+ while (!found)
+ {
+ QString s;
+ char c;
+ while ( includeFileOffset<includeFileLength &&
+ (c=currentIncludeFile[includeFileOffset++])!='\n' && c!=0
+ ) s+=c;
+ if (s.find(key)!=-1)
+ {
+ found=TRUE;
+ ol.writeString(" ");
+ parseCode(ol,className,s,exampleDoc,exampleName);
+ ol.writeString("\n");
+ }
+ else if (includeFileOffset==includeFileLength) found=TRUE;
+ }
+}
+
+static void skipUntil(const char *key)
+{
+ bool found=FALSE;
+ while (!found)
+ {
+ QString s;
+ int i=includeFileOffset;
+ char c;
+ while ( i<includeFileLength &&
+ (c=currentIncludeFile[i++])!='\n' && c!=0
+ ) s+=c;
+ if (s.find(key)!=-1 || i==includeFileLength)
+ {
+ found=TRUE;
+ }
+ else
+ {
+ includeFileOffset=i;
+ }
+ }
+}
+
+static void showLine(OutputList &ol,const char *key)
+{
+ QString s;
+ char c;
+ bool found=FALSE;
+ while (!found)
+ {
+ while ( includeFileOffset<includeFileLength &&
+ (c=currentIncludeFile[includeFileOffset++])!='\n' && c!=0
+ ) s+=c;
+ if (s.stripWhiteSpace().length()>0 ||
+ includeFileOffset==includeFileLength) found=TRUE;
+ }
+ if (s.find(key)!=-1)
+ {
+ ol.writeString(" ");
+ parseCode(ol,className,s,exampleDoc,exampleName);
+ ol.writeString("\n");
+ }
+}
+
+static void showUntil(OutputList &ol,const char *key)
+{
+ bool found=FALSE;
+ while (!found)
+ {
+ QString s;
+ char c;
+ while ( includeFileOffset<includeFileLength &&
+ (c=currentIncludeFile[includeFileOffset++])!='\n' && c!=0
+ ) s+=c;
+ if (s.stripWhiteSpace().length()>0)
+ {
+ ol.writeString(" ");
+ parseCode(ol,className,s,exampleDoc,exampleName);
+ ol.writeString("\n");
+ if (s.find(key)!=-1) found=TRUE;
+ }
+ if (includeFileOffset==includeFileLength) found=TRUE;
+ }
+}
+
+static void newDocState();
+
+//-----------------------------------------------------------------
+
+static bool inBlock()
+{
+ return inParamBlock || inSeeBlock || inReturnBlock || inAuthorBlock ||
+ inVersionBlock || inDateBlock || inWarningBlock || inBugBlock ||
+ inParBlock || inExceptionBlock;
+}
+
+static void endBlock()
+{
+ outDoc->endDescList();
+ inParamBlock=inSeeBlock=inReturnBlock=inAuthorBlock=
+ inVersionBlock=inDateBlock=inBugBlock=inWarningBlock=
+ inParBlock=inExceptionBlock=FALSE;
+}
+
+static void addSection()
+{
+ //printf("New section pageName=%s label=%s title=%s\n",
+ // current->name.data(),sectionLabel.data(),sectionTitle.data());
+ SectionInfo *si=new SectionInfo(current->name,
+ sectionLabel,sectionTitle,isSubsection);
+ sectionDict.insert(sectionLabel,si);
+}
+
+
+// Adds a formula text to the list/dictionary of formulas if it was
+// not already added. Returns the label of the formula.
+static QString addFormula()
+{
+ QString formLabel;
+ QString fText=formulaText.simplifyWhiteSpace();
+ Formula *f=0;
+ if ((f=formulaDict[fText])==0)
+ {
+ f = new Formula(fText);
+ formulaList.append(f);
+ formulaDict.insert(fText,f);
+ formLabel.sprintf("\\form#%d",f->getId());
+ formulaNameDict.insert(formLabel,f);
+ }
+ else
+ {
+ formLabel.sprintf("\\form#%d",f->getId());
+ }
+ return formLabel;
+}
+
+/* -----------------------------------------------------------------
+ */
+#undef YY_INPUT
+#define YY_INPUT(buf,result,max_size) result=yyread(buf,max_size);
+
+static int yyread(char *buf,int max_size)
+{
+ int c=0;
+ while( c < max_size && inputString[inputPosition] )
+ {
+ *buf = inputString[inputPosition++] ;
+ //printf("%d (%c)\n",*buf,*buf);
+ c++; buf++;
+ }
+ return c;
+}
+
+//ATTR ((({BN}+[^\>]+)/">")?)
+%}
+
+BN [ \t\n\r]
+BL [ \t\r]*"\n"
+B [ \t]
+BS ^(({B}*"//")?)(({B}*"*"+)?){B}*
+FILE ([a-z_A-Z0-9\.\\:\/\-\+]+)|("\""[^\n\"]+"\"")
+FILEMASK [a-z_A-Z0-9\.\\:\/\-\+]+"."[a-z_A-Z0-9\.\-\+]*[a-z_A-Z0-9\-\+]
+ID [a-z_A-Z][a-z_A-Z0-9]*
+SCOPEID {ID}({ID}*{BN}*"::"{BN}*)*({ID}?)
+SCOPENAME (({ID}?{BN}*"::"{BN}*)*)((~{BN}*)?{ID})
+SCOPEMASK {ID}?(("::"|"#")?(~)?{ID})+
+URLMASK [a-z_A-Z0-9\~\:\@\#\.\-\+\/]+
+ATTR ({B}+[^>\n]*)?
+A [aA]
+BOLD [bB]
+BODY [bB][oO][dD][yY]
+BR [bB][rR]
+EM [eE][mM]
+CENTER [cC][eE][nN][tT][eE][rR]
+CODE [cC][oO][dD][eE]
+DL [dD][lL]
+DD [dD][dD]
+DT [dD][tT]
+DFN [dD][fF][nN]
+FORM [fF][oO][rR][mM]
+H1 [hH]1
+H2 [hH]2
+H3 [hH][3-6]
+HEAD [hH][eE][aA][dD]
+HR [hH][rR]
+HREF [hH][rR][eE][fF]
+I [iI]
+IMG [iI][mM][gG]
+INPUT [iI][nN][pP][uU][tT]
+LI [lL][iI]
+META [mM][eE][tT][aA]
+MULTICOL [mM][uU][lL][tT][iI][cC][oO][lL]
+NAME [nN][aA][mM][eE]
+OL [oO][lL]
+P [pP]
+PRE [pP][rR][eE]
+SMALL [sS][mM][aA][lL][lL]
+STRONG [sS][tT][rR][oO][nN][gG]
+SUB [sS][uU][bB]
+SUP [sS][uU][pP]
+SRC [sS][rR][cC]
+TABLE [tT][aA][bB][lL][eE]
+TITLE [tT][iI][tT][lL][eE]
+TD [tT][dD]
+TR [tT][rR]
+TT [tT][tT]
+UL [uU][lL]
+VAR [vV][aA][rR]
+
+%x Define
+%x DefineArg
+%x DefineEnd
+%x Include
+%x ClassName
+%x ClassVar
+%x Bases
+%x NextSemi
+%x FindMembers
+%x FindMemberName
+%x FindFields
+%x FindFieldArg
+%x Function
+%x FuncRound
+%x ExcpRound
+%x FuncQual
+%x Operator
+%x Array
+%x Curly
+%x Using
+%x NameSpaceDocArg1
+%x SkipCurly
+%x SkipCurlyCpp
+%x SkipString
+%x SkipInits
+%x SkipCPP
+%x SkipCPPBlock
+%x SkipComment
+%x SkipCxxComment
+%x SkipBlock
+%x SkipCode
+%x Sharp
+%x SkipSharp
+%x SkipRound
+%x TypedefName
+%x Comment
+%x Doc
+%x JavaDoc
+%x ClassDoc
+%x LineDoc
+%x DefLineDoc
+%x ClassDocArg1
+%x ClassDocArg2
+%x ClassDocArg3
+%x ClassDocFunc
+%x ClassDocFuncPtr
+%x ClassDocFuncQual
+%x ClassDocFuncExc
+%x ClassDocDefine
+%x ClassDocRelates
+%x ClassDocBrief
+%x ClassDocOverload
+%x ClassDefineArgs
+%x GroupDocArg1
+%x GroupDocArg2
+%x GroupName
+%x AfterDoc
+%x AfterDocBrief
+%x AfterDocLine
+%x PageDoc
+%x PageDocTitle
+%x PageDocArg1
+%x PageDocArg2
+%x FileDocArg1
+%x FileDocArg2
+%x ExampleDoc
+%x ExampleDocArg1
+%x EnumDoc
+%x EnumDocArg1
+%x FuncPtr
+%x EndFuncPtr
+%x FuncFunc
+%x FuncFuncEnd
+%x FuncFuncType
+%x MemberSpec
+%x MemberSpecSkip
+%x SkipVerbatim
+%x DocScan
+%x DocParam
+%x DocException
+%x DocHtmlScan
+%x DocLatexScan
+%x DocEmphasis
+%x DocBold
+%x DocCode
+%x DocCodeBlock
+%x DocInternal
+%x DocLink
+%x DocLinkText
+%x DocSkipWord
+%x DocInclude
+%x DocDontInclude
+%x DocDescItem
+%x DocHtmlLink
+%x DocHtmlAnchor
+%x DocHtmlHref1
+%x DocHtmlHref2
+%x DocBaseClass
+%x DocSkiplineKey
+%x DocSkipKey
+%x DocLineKey
+%x DocUntilKey
+%x DocKeyEnd
+%x DocPar
+%x DocRefName
+%x DocVerbatim
+%x DocVerbInc
+%x DocIndexWord
+%x DocRef
+%x DocRefItem
+%x DocRefItemName
+%x SectionLabel
+%x SectionTitle
+%x EndTemplate
+%x CopyArgString
+%x CopyArgRound
+%x CopyArgSharp
+%x ReadFuncArgType
+%x ReadTempArgs
+%x Specialization
+%x DocSkipHtmlComment
+%x ReadFormulaShort
+%x ReadFormulaLong
+
+%%
+
+<*>\x06[^\x06]*\x06 { // new file
+ yyLineNr= 1 ;
+ int i;
+ for( i = 0 ; yytext[i+1] != 6 ; i++ )
+ yyFileName[i] = yytext[i+1] ;
+ yyFileName[i] = 0 ;
+ msg("Parsing file %s...\n",yyFileName);
+ current_root = global_root ;
+ initParser();
+ current->reset();
+ int sec=guessSection(yyFileName);
+ if (sec)
+ {
+ current->name = yyFileName;
+ current->name = current->name;
+ current->section = sec;
+ current_root->addSubEntry(current);
+ current = new Entry;
+ }
+ BEGIN( FindMembers );
+ }
+<*>\x0d
+ /*
+<DocScan>^{BL} {
+ if (insideArgumentList)
+ {
+ insideArgumentList=FALSE;
+ outDoc->endItemList();
+ }
+ else
+ {
+ outDoc->newParagraph();
+ }
+ if (inBlock()) endBlock();
+ }
+ */
+<DocScan>"<!--" { BEGIN(DocSkipHtmlComment); }
+<DocSkipHtmlComment>"--"[!]?">" { BEGIN(DocScan); }
+<DocSkipHtmlComment>.
+<DocScan>"&copy;" { outDoc->writeCopyright(); }
+<DocScan>"&quot;" { outDoc->writeQuote(); }
+<DocScan>"&"[AEIOUYaeiouy]"uml;" { outDoc->writeUmlaut(yytext[1]); }
+<DocScan>"&"[AEIOUYaeiouy]"acute;" { outDoc->writeAcute(yytext[1]); }
+<DocScan>"&"[AEIOUaeiou]"grave;" { outDoc->writeGrave(yytext[1]); }
+<DocScan>"&"[AEIOUaeiou]"circ;" { outDoc->writeCirc(yytext[1]); }
+<DocScan>"&"[ANOano]"tilde;" { outDoc->writeTilde(yytext[1]); }
+<DocScan,DocHtmlScan,DocLatexScan>"$("[a-z_A-Z]+")" {
+ QString envvar=&yytext[2];
+ envvar=envvar.left(envvar.length()-1);
+ outDoc->docify(getenv(envvar));
+ }
+<DocScan>("\\"|"@")"htmlonly"/[^a-z_A-Z0-9] {
+ outDoc->disableAllBut(OutputGenerator::Html);
+ BEGIN(DocHtmlScan);
+ }
+<DocHtmlScan>("\\"|"@")"endhtmlonly"/[^a-z_A-Z0-9] {
+ outDoc->enableAll();
+ BEGIN(DocScan);
+ }
+<DocScan>("\\"|"@")"latexonly"/[^a-z_A-Z0-9] {
+ outDoc->disableAllBut(OutputGenerator::Latex);
+ BEGIN(DocLatexScan);
+ }
+<DocHtmlScan,DocLatexScan>"//"|"/*"|"*/" {
+ outDoc->writeString(yytext);
+ }
+<DocHtmlScan,DocLatexScan>. {
+ char c[2];
+ c[0]=*yytext;c[1]='\0';
+ outDoc->writeString(c);
+ }
+<DocLatexScan>("\\"|"@")"endlatexonly"/[^a-z_A-Z0-9] {
+ outDoc->enableAll();
+ BEGIN(DocScan);
+ }
+<DocScan>"\\postheader"/{BN}
+<DocScan>"\\functionindex"/{BN} { writeMemberList(*outDoc); }
+<DocScan>"\\classhierarchy"/{BN} { writeClassHierarchy(*outDoc); }
+<DocScan>"\\annotatedclasslist"/{BN} { writeAnnotatedClassList(*outDoc); }
+<DocScan>"\\headerfilelist"/{BN} { /*TODO: fix this writeHeaderFileList(*outDoc); */ }
+<DocScan>"\\header"/{BN} { BEGIN( DocSkipWord ); }
+<DocScan>"\\define"/{BN} { BEGIN( DocSkipWord ); }
+<DocScan>("\\"|"@")"verbinclude"/{BN} { BEGIN( DocVerbInc ); }
+<DocVerbInc>{FILE} {
+ verbIncludeFile(*outDoc,stripQuotes(yytext));
+ BEGIN( DocScan );
+ }
+<DocScan>("\\"|"@")"verbatim"/[^a-z_A-Z0-9] {
+ outDoc->startCodeFragment();
+ BEGIN(DocVerbatim);
+ }
+<DocVerbatim>("\\"|"@")"endverbatim"/[^a-z_A-Z0-9] {
+ outDoc->endCodeFragment();
+ BEGIN(DocScan);
+ }
+<DocVerbatim>[^\n\\]*"\n" {
+ //printf("docifying: %s\n",yytext);
+ outDoc->codify(yytext);
+ }
+<DocVerbatim>"\n"|"//"|"/*"|"*/" {
+ outDoc->codify(yytext);
+ }
+<DocVerbatim>. {
+ //printf("char %c\n",*yytext);
+ char c[2];c[0]=*yytext;c[1]='\0';
+ outDoc->codify(c);
+ }
+<DocScan>("\\"|"@")"internal"/{BN} {
+ if (!internalDocsFlag)
+ {
+ outDoc->newParagraph();
+ scanString(theTranslator->trForInternalUseOnly()+"\n");
+ //outDoc->writeString("For internal use only.\n");
+ BEGIN( DocInternal );
+ }
+ }
+<DocScan>"\\reimp"/{BN} {
+ outDoc->newParagraph();
+ scanString(theTranslator->trReimplementedForInternalReasons()+"\n");
+ }
+<DocScan>("\\"|"@")"link"/{BN} { BEGIN( DocLink ); }
+<DocSkipWord>[a-z_A-Z0-9.:()]+ { BEGIN( DocScan ); }
+<DocLink>[a-z_A-Z0-9:#.~/()\-\+]+ {
+ linkRef = stripKnownExtensions(yytext);
+ linkText = "";
+ BEGIN( DocLinkText );
+ }
+<DocLinkText>. { linkText += *yytext; }
+<DocLinkText>"\n" { linkText += " "; }
+<DocLink,DocLinkText>("\\"|"@")"endlink"/[^a-z_A-Z0-9] { // <- needed for things like \endlink.
+ generateLink(*outDoc,className,linkRef,inSeeBlock,linkText);
+ BEGIN( DocScan );
+ }
+<DocScan>"@ref"{B}+ {
+ BEGIN(DocRef);
+ }
+<DocRef>{SCOPENAME} {
+ generateLink(*outDoc,className,yytext,TRUE,0);
+ BEGIN( DocScan );
+ }
+<DocScan>("\\"|"@")"endlink"/[^a-z_A-Z0-9] { warn("Warning: \\endlink without \\link "
+ "in documentation of %s\n", refName.data());
+ }
+<DocScan>("\\"|"@")"addindex"/{BN} {
+ BEGIN(DocIndexWord);
+ }
+<DocScan>"\\form#"[0-9]+ {
+ Formula *formula=formulaNameDict[yytext];
+ if (formula)
+ {
+ QString formName;
+ formName.sprintf("form-%d.gif",formula->getId());
+ outDoc->writeFormula(formName,formula->getFormulaText());
+ }
+ }
+<DocIndexWord>[^\n\t ]+ {
+ //printf("Adding %s to index\n",yytext);
+ outDoc->addToIndex(yytext,0);
+ BEGIN(DocScan);
+ }
+<DocScan>("\\"|"@")"arg"{BN}+ {
+ if (insideArgumentList)
+ {
+ outDoc->writeListItem();
+ }
+ else
+ {
+ outDoc->startItemList();
+ outDoc->writeListItem();
+ insideArgumentList=TRUE;
+ }
+ }
+<DocScan>("\\"|"@")"par"{B}+ {
+ BEGIN(DocPar);
+ }
+<DocPar>[^\n]*{BN}+ {
+ endArgumentList();
+ if (inBlock()) endBlock();
+ inParBlock=TRUE;
+ outDoc->startDescList();
+ outDoc->startBold();
+ outDoc->docify(((QString)yytext).stripWhiteSpace());
+ outDoc->endBold();
+ outDoc->endDescTitle();
+ outDoc->writeDescItem();
+ BEGIN(DocScan);
+ }
+<DocScan>("\\"|"@")"warning"{BN}+ {
+ endArgumentList();
+ if (!inWarningBlock)
+ {
+ if (inBlock()) endBlock();
+ inWarningBlock=TRUE;
+ outDoc->startDescList();
+ //outDoc->writeBoldString("Warning: ");
+ outDoc->startBold();
+ scanString(theTranslator->trWarning()+": ");
+ outDoc->endBold();
+ outDoc->endDescTitle();
+ outDoc->writeDescItem();
+ }
+ else
+ {
+ outDoc->writeDescItem();
+ }
+ }
+<DocScan>("\\"|"@")"bug"{BN}+ {
+ endArgumentList();
+ if (!inBugBlock)
+ {
+ if (inBlock()) endBlock();
+ inBugBlock=TRUE;
+ outDoc->startDescList();
+ //outDoc->writeBoldString("Bugs and limitations: ");
+ outDoc->startBold();
+ scanString(theTranslator->trBugsAndLimitations()+": ");
+ outDoc->endBold();
+ outDoc->endDescTitle();
+ outDoc->writeDescItem();
+ }
+ else
+ {
+ outDoc->writeDescItem();
+ }
+ }
+<DocScan>("\\"|"@")"version"{BN}+ {
+ endArgumentList();
+ if (!inVersionBlock)
+ {
+ if (inBlock()) endBlock();
+ inVersionBlock=TRUE;
+ outDoc->startDescList();
+ //outDoc->writeBoldString("Version: ");
+ outDoc->startBold();
+ scanString(theTranslator->trVersion()+": ");
+ outDoc->endBold();
+ outDoc->endDescTitle();
+ outDoc->writeDescItem();
+ }
+ else
+ {
+ outDoc->writeDescItem();
+ }
+ }
+<DocScan>("\\"|"@")"date"{BN}+ {
+ endArgumentList();
+ if (!inDateBlock)
+ {
+ if (inBlock()) endBlock();
+ inDateBlock=TRUE;
+ outDoc->startDescList();
+ //outDoc->writeBoldString("Date: ");
+ outDoc->startBold();
+ scanString(theTranslator->trDate()+": ");
+ outDoc->endBold();
+ outDoc->endDescTitle();
+ outDoc->writeDescItem();
+ }
+ else
+ {
+ outDoc->writeDescItem();
+ }
+ }
+<DocScan>("\\"|"@")"author"{BN}+ {
+ endArgumentList();
+ if (!inAuthorBlock)
+ {
+ if (inBlock()) endBlock();
+ inAuthorBlock=TRUE;
+ outDoc->startDescList();
+ //outDoc->writeBoldString("Author(s): ");
+ outDoc->startBold();
+ scanString(theTranslator->trAuthors()+": ");
+ outDoc->endBold();
+ outDoc->endDescTitle();
+ outDoc->writeDescItem();
+ }
+ else
+ {
+ outDoc->docify(", ");
+ }
+ }
+<DocScan>("\\"|"@")"return"{BN}+ {
+ endArgumentList();
+ if (!inReturnBlock)
+ {
+ if (inBlock()) endBlock();
+ inReturnBlock=TRUE;
+ outDoc->startDescList();
+ //outDoc->writeBoldString("Returns: ");
+ outDoc->startBold();
+ scanString(theTranslator->trReturns()+": ");
+ outDoc->endBold();
+ outDoc->endDescTitle();
+ outDoc->writeDescItem();
+ }
+ }
+<DocScan>("\\sa"|"@see"){BN}+ {
+ endArgumentList();
+ if (!inSeeBlock)
+ {
+ if (inBlock()) endBlock();
+ inSeeBlock=TRUE;
+ //firstSeeArg=TRUE;
+ //javaDocSee=!strcmp(yytext,"@see");
+ outDoc->startDescList();
+ //outDoc->writeBoldString("See also: ");
+ outDoc->startBold();
+ scanString(theTranslator->trSeeAlso()+": ");
+ outDoc->endBold();
+ outDoc->endDescTitle();
+ outDoc->writeDescItem();
+ }
+ else
+ {
+ outDoc->docify(", ");
+ }
+ }
+<DocScan>("\\"|"@")"param"{BN}+ {
+ endArgumentList();
+ if (!inParamBlock)
+ {
+ if (inBlock()) endBlock();
+ inParamBlock=TRUE;
+ outDoc->startDescList();
+ //outDoc->writeBoldString("Parameters: ");
+ outDoc->startBold();
+ scanString(theTranslator->trParameters()+": ");
+ outDoc->endBold();
+ outDoc->endDescTitle();
+ }
+ BEGIN(DocParam);
+ }
+<DocScan>("\\"|"@")"exception"{BN}+ {
+ endArgumentList();
+ if (!inExceptionBlock)
+ {
+ if (inBlock()) endBlock();
+ inExceptionBlock=TRUE;
+ outDoc->startDescList();
+ //outDoc->writeBoldString("Exceptions: ");
+ outDoc->startBold();
+ scanString(theTranslator->trExceptions()+": ");
+ outDoc->endBold();
+ outDoc->endDescTitle();
+ }
+ BEGIN(DocException);
+ }
+<DocScan>"\\capt".*
+<DocParam>{SCOPENAME} {
+ outDoc->writeDescItem();
+ outDoc->startEmphasis();
+ outDoc->docify(yytext);
+ outDoc->endEmphasis();
+ outDoc->docify(" - ");
+ BEGIN(DocScan);
+ }
+<DocException>{SCOPENAME} {
+ outDoc->writeDescItem();
+ outDoc->startEmphasis();
+ outDoc->docify(yytext);
+ outDoc->endEmphasis();
+ outDoc->docify(" - ");
+ BEGIN(DocScan);
+ }
+<DocScan>("\\"|"@")"section "{ID}"\n" {
+ QString secName=&yytext[9]; // skip "\section "
+ secName=secName.left(secName.length()-1); // remove \n
+ //printf("SectionName %s found\n",secName.data());
+ SectionInfo *sec;
+ if ((sec=sectionDict[secName]))
+ {
+ //printf("Title %s\n",sec->title.data());
+ outDoc->writeSection(sec->label,sec->title,sec->isSubsection);
+ }
+ }
+<DocScan>"\\ref" {
+ BEGIN(DocRefName);
+ }
+<DocScan>"\\refitem" {
+ BEGIN(DocRefItem);
+ }
+<DocRefName>{ID} {
+ QString ref=yytext;
+ SectionInfo *sec;
+ if ((sec=sectionDict[ref]))
+ {
+ outDoc->writeSectionRef(sec->pageName,sec->label,sec->title);
+ }
+ else
+ {
+ warn("Warning: reference to unknown section %s!\n",yytext);
+ outDoc->writeBoldString("unknown reference!");
+ }
+ BEGIN(DocScan);
+ }
+<DocRefItem>{ID} {
+ sectionRef=yytext;
+ BEGIN(DocRefItemName);
+ }
+<DocRefItemName>.*/"\n" {
+ SectionInfo *sec;
+ if ((sec=sectionDict[sectionRef]))
+ {
+ outDoc->writeSectionRefItem(sec->pageName,sec->label,yytext);
+ }
+ else
+ {
+ warn("Warning: reference to unknown section %s!\n",sectionRef.data());
+ outDoc->writeBoldString("unknown reference!");
+ }
+ BEGIN(DocScan);
+ }
+<DocScan>("\\"|"@")"code"/{BN}+ {
+ outDoc->startCodeFragment();
+ codeBlock.resize(0);
+ BEGIN( DocCodeBlock );
+ }
+<DocScan>("\\"|"@")"endcode"/[^a-z_A-Z0-9] {
+ warn("Warning: \\endcode without <PRE> or \\code "
+ "in the documentation of %s\n",refName.data());
+ }
+<DocScan>{SCOPEMASK}"("[a-z_A-Z,\<\> \t\*\&]+")" {
+ generateRef(*outDoc,className,yytext,inSeeBlock);
+ }
+<DocScan>{SCOPEMASK}(("()")?) {
+ generateRef(*outDoc,className,yytext,inSeeBlock);
+ }
+<DocScan>({SCOPEMASK}"::")?"operator"[^(\r\n.,]*"("[a-z_A-Z,\<\> \t\*\&]*")" {
+ QString oName=yytext;
+ generateRef(*outDoc,className,
+ removeRedundantWhiteSpace(oName),inSeeBlock);
+ }
+<DocScan>({SCOPEMASK}"::")?"operator()("[a-z_A-Z,\<\> \t\*\&]*")" {
+ QString oName=yytext;
+ generateRef(*outDoc,className,
+ removeRedundantWhiteSpace(oName),inSeeBlock);
+ }
+<DocScan>{FILEMASK} {
+ generateFileRef(*outDoc,yytext);
+ }
+<DocCodeBlock>{BN}*("\\"|"@")"endcode"/[^a-z_A-Z0-9] { // needed to match things like \endcode. (note the dot)
+ parseCode(*outDoc,className,codeBlock,exampleDoc,exampleName);
+ //printf("Code block\n-------------\n%s\n--------------\n",codeBlock.data());
+ outDoc->endCodeFragment();
+ BEGIN( DocScan );
+ }
+<DocCodeBlock>"</"{PRE}{ATTR}">" {
+ parseCode(*outDoc,className,codeBlock,exampleDoc,exampleName);
+ //printf("Code block\n-------------\n%s\n--------------\n",codeBlock.data());
+ outDoc->endCodeFragment();
+ BEGIN( DocScan );
+ }
+<DocScan>("\\"|"@")"e"{BN}+ { BEGIN( DocEmphasis ); }
+<DocScan>("\\"|"@")"a"{BN}+ { BEGIN( DocEmphasis ); }
+<DocScan>("\\"|"@")"b"{BN}+ { BEGIN( DocBold ); }
+<DocScan>("\\"|"@")"c"{BN}+ { BEGIN( DocCode ); }
+<DocScan>("\\"|"@")"l"{BN}+
+<DocScan>("\\"|"@")"include"{BN}+ { BEGIN( DocInclude ); }
+<DocScan>("\\"|"@")"dontinclude"{BN}+ { BEGIN( DocDontInclude ); }
+<DocScan>("\\"|"@")"skip"{BN}+ { BEGIN( DocSkipKey ); }
+<DocScan>("\\"|"@")"skipline"{BN}+ { BEGIN( DocSkiplineKey ); firstLine=TRUE; }
+<DocScan>("\\"|"@")"line"{BN}+ { BEGIN( DocLineKey ); firstLine=TRUE; }
+<DocScan>("\\"|"@")"until"{BN}+ { BEGIN( DocUntilKey ); firstLine=TRUE; }
+<DocSkipKey>[^ \t\r\n]+ {
+ if (includeFileLength>0)
+ skipUntil(yytext);
+ BEGIN( DocScan );
+ }
+<DocLineKey>[^ \t\r\n]+ {
+ if (includeFileLength>0)
+ {
+ if (firstLine) outDoc->startCodeFragment();
+ firstLine=FALSE;
+ showLine(*outDoc,yytext);
+ BEGIN( DocKeyEnd );
+ }
+ else
+ {
+ BEGIN( DocScan );
+ }
+ }
+<DocSkiplineKey>[^ \t\r\n]+ {
+ if (includeFileLength>0)
+ {
+ if (firstLine) outDoc->startCodeFragment();
+ firstLine=FALSE;
+ skipLine(*outDoc,yytext);
+ BEGIN( DocKeyEnd );
+ }
+ else
+ {
+ BEGIN( DocScan );
+ }
+ }
+<DocUntilKey>[^ \t\r\n]+ {
+ if (includeFileLength>0)
+ {
+ if (firstLine) outDoc->startCodeFragment();
+ firstLine=FALSE;
+ showUntil(*outDoc,yytext);
+ BEGIN( DocKeyEnd );
+ }
+ else
+ {
+ BEGIN( DocScan );
+ }
+ }
+<DocKeyEnd>("\\"|"@")"line"{BN}+ { BEGIN(DocLineKey); }
+<DocKeyEnd>("\\"|"@")"until"{BN}+ { BEGIN(DocUntilKey); }
+<DocKeyEnd>("\\"|"@")"skipline"{BN}+ { BEGIN(DocSkiplineKey); }
+<DocKeyEnd>\n
+<DocKeyEnd>. {
+ unput(*yytext);
+ if (!firstLine) outDoc->endCodeFragment();
+ BEGIN( DocScan );
+ }
+<DocScan>"<"{MULTICOL}{ATTR}">"
+<DocScan>"</"{MULTICOL}{ATTR}">"
+<DocScan>"<"{STRONG}{ATTR}">" { outDoc->startBold(); }
+<DocScan>"</"{STRONG}{ATTR}">" { outDoc->endBold(); }
+<DocScan>"<"{CENTER}{ATTR}">" { outDoc->startCenter(); }
+<DocScan>"</"{CENTER}{ATTR}">" { outDoc->endCenter(); }
+<DocScan>"<"{TABLE}{ATTR}">" {
+ startTable();
+ /*outDoc->startTable();*/ }
+<DocScan>"</"{TABLE}{ATTR}">" {
+ endTable();
+ /*outDoc->endTable();*/
+ }
+<DocScan>"<"{INPUT}{ATTR}">"
+<DocScan>"<"{SMALL}{ATTR}">" { outDoc->startSmall(); }
+<DocScan>"</"{SMALL}{ATTR}">" { outDoc->endSmall(); }
+<DocScan>"<"{META}{ATTR}">"
+<DocScan>"<"{FORM}{ATTR}">"
+<DocScan>"</"{FORM}{ATTR}">"
+<DocScan>"<"{HEAD}{ATTR}">"
+<DocScan>"</"{HEAD}{ATTR}">"
+<DocScan>"<"{BODY}{ATTR}">"
+<DocScan>"</"{BODY}{ATTR}">"
+<DocScan>"<"{CODE}{ATTR}">" { outDoc->startTypewriter(); }
+<DocScan>"</"{CODE}{ATTR}">" { outDoc->endTypewriter(); }
+<DocScan>"<"{DFN}{ATTR}">" { outDoc->startTypewriter(); }
+<DocScan>"</"{DFN}{ATTR}">" { outDoc->endTypewriter(); }
+<DocScan>"<"{VAR}{ATTR}">" { outDoc->startEmphasis(); }
+<DocScan>"</"{VAR}{ATTR}">" { outDoc->endEmphasis(); }
+<DocScan>"<"{IMG}{ATTR}">" { outDoc->disableAllBut(OutputGenerator::Html);
+ outDoc->writeString(yytext);
+ outDoc->enableAll();
+ }
+<DocScan>"<"{PRE}{ATTR}">" {
+ outDoc->startCodeFragment();
+ codeBlock.resize(0);
+ BEGIN( DocCodeBlock );
+ }
+<DocScan>"</"{PRE}{ATTR}">" {
+ warn("Warning: </PRE> without <PRE> or \\code"
+ "in the documentation of %s\n",refName.data());
+ }
+<DocScan>"<"{SUB}{ATTR}">" { outDoc->startSubscript(); }
+<DocScan>"</"{SUB}{ATTR}">" { outDoc->endSubscript(); }
+<DocScan>"<"{SUP}{ATTR}">" { outDoc->startSuperscript(); }
+<DocScan>"</"{SUP}{ATTR}">" { outDoc->endSuperscript(); }
+<DocScan>"<"{TR}{ATTR}">" { if (curTable) curTable->newRow(); }
+<DocScan>"</"{TR}{ATTR}">"
+<DocScan>"<"{TD}{ATTR}">" { if (curTable) curTable->newElem(); }
+<DocScan>"</"{TD}{ATTR}">"
+<DocScan>"<"{OL}{ATTR}">" { outDoc->startEnumList(); }
+<DocScan>"</"{OL}{ATTR}">" { outDoc->endEnumList(); }
+<DocScan>"<"{UL}{ATTR}">" { outDoc->startItemList(); }
+<DocScan>"</"{UL}{ATTR}">" { outDoc->endItemList(); }
+<DocScan>"<"{LI}{ATTR}">" { outDoc->writeListItem(); }
+<DocScan>"</"{LI}{ATTR}">"
+<DocScan>"<"{TT}{ATTR}">" { outDoc->startTypewriter(); }
+<DocScan>"</"{TT}{ATTR}">" { outDoc->endTypewriter(); }
+<DocScan>"<"{EM}{ATTR}">" { outDoc->startEmphasis(); }
+<DocScan>"</"{EM}{ATTR}">" { outDoc->endEmphasis(); }
+<DocScan>"<"{HR}{ATTR}">" { outDoc->writeRuler(); }
+<DocScan>"<"{DL}{ATTR}">" { outDoc->startDescription(); }
+<DocScan>"</"{DL}{ATTR}">" { outDoc->endDescription(); }
+<DocScan>"<"{DT}{ATTR}">" { outDoc->startDescItem(); }
+<DocScan>"</"{DT}{ATTR}">"
+<DocScan>"<"{DD}{ATTR}">" { outDoc->endDescItem(); }
+<DocScan>"</"{DD}{ATTR}">"
+<DocScan>"<"{BR}{ATTR}">" { outDoc->lineBreak(); }
+<DocScan>"<"{I}{ATTR}">" { outDoc->startEmphasis(); }
+<DocScan>"</"{I}{ATTR}">" { outDoc->endEmphasis(); }
+<DocScan>"</"{A}{ATTR}">"
+<DocScan>"<"{A} { BEGIN(DocHtmlLink); }
+<DocScan>"<"{BOLD}{ATTR}">" { outDoc->startBold(); }
+<DocScan>"</"{BOLD}{ATTR}">" { outDoc->endBold(); }
+<DocScan>"<"{P}{ATTR}">" {
+ if (inBlock()) endBlock();
+ outDoc->newParagraph(); }
+<DocScan>"</"{P}{ATTR}">"
+<DocScan>"<"{H1}{ATTR}">" { outDoc->startTitle(); }
+<DocScan>"</"{H1}{ATTR}">" { outDoc->endTitle(); }
+<DocScan>"<"{H2}{ATTR}">" { outDoc->startSubsection(); }
+<DocScan>"</"{H2}{ATTR}">" { outDoc->endSubsection(); }
+<DocScan>"<"{H3}{ATTR}">" { outDoc->startSubsubsection(); }
+<DocScan>"</"{H3}{ATTR}">" { outDoc->endSubsubsection(); }
+<DocHtmlLink>{NAME}{BN}*"="{BN}*("\""?) { BEGIN(DocHtmlAnchor); }
+<DocHtmlAnchor>[a-z_A-Z0-9.\-\+\/]+ { outDoc->writeAnchor(yytext); }
+<DocHtmlLink>{HREF}{BN}*"="{BN}*("\""?) {
+ htmlUrl.resize(0);
+ htmlText.resize(0);
+ BEGIN(DocHtmlHref1); }
+<DocHtmlHref1>{URLMASK}+ {
+ htmlUrl=yytext;
+ }
+<DocHtmlHref1>">" { BEGIN(DocHtmlHref2); }
+<DocHtmlHref2>[^<]* { htmlText+=yytext; }
+ /*
+<DocHtmlHref2>\n { htmlText+='\n'; }
+ */
+<DocHtmlHref2>"<" {
+ outDoc->writeHtmlLink(htmlUrl,htmlText);
+ unput(*yytext);
+ BEGIN(DocScan);
+ }
+<DocHtmlLink,DocHtmlAnchor>">" { BEGIN(DocScan); }
+
+<DocScan>"\\\\" {
+ outDoc->docify("\\");
+ }
+<DocScan>"\\@" {
+ outDoc->docify("@");
+ }
+<DocScan>"\\<" {
+ outDoc->docify("<");
+ }
+<DocScan>"\\>" {
+ outDoc->docify(">");
+ }
+<DocScan>"\\&" {
+ outDoc->docify("&");
+ }
+<DocScan>"\\$" {
+ outDoc->docify("$");
+ }
+<DocScan>"\\#" {
+ outDoc->docify("#");
+ }
+<DocScan>"\\%" {
+ outDoc->docify("%");
+ }
+<DocScan>"%"[a-zA-Z_0-9\-]+ {
+ outDoc->docify(yytext+1);
+ }
+<DocEmphasis>[^ \t\n\r]+ {
+ outDoc->startEmphasis();
+ generateRef(*outDoc,className,yytext,inSeeBlock);
+ outDoc->endEmphasis();
+ BEGIN( DocScan );
+ //addToIndex(yytext);
+ }
+<DocBold>[^ \t\n\r]+ {
+ outDoc->startBold();
+ generateRef(*outDoc,className,yytext,inSeeBlock);
+ outDoc->endBold();
+ BEGIN( DocScan );
+ }
+<DocCode>[^ \t\n\r]+ {
+ outDoc->startTypewriter();
+ generateRef(*outDoc,className,yytext,inSeeBlock);
+ outDoc->endTypewriter();
+ BEGIN( DocScan );
+ }
+<DocInclude>{FILE} {
+ includeFile(*outDoc,stripQuotes(yytext),FALSE);
+ BEGIN( DocScan );
+ }
+<DocDontInclude>{FILE} {
+ includeFile(*outDoc,stripQuotes(yytext),TRUE);
+ BEGIN( DocScan );
+ }
+<DocCodeBlock>"//" { codeBlock += yytext; }
+<DocCodeBlock>"/*" { codeBlock += yytext; }
+<DocCodeBlock>\n { codeBlock += '\n'; }
+<DocCodeBlock>[^\/\\\<\n]* { codeBlock += yytext; }
+<DocCodeBlock>. { codeBlock += *yytext; }
+<DocCode,DocEmphasis,DocScan,DocBold>"//" {
+ outDoc->docify(yytext);
+ }
+<DocCode,DocEmphasis,DocScan,DocBold>"/*" {
+ outDoc->docify(yytext);
+ }
+<DocCode,DocEmphasis,DocBold>"\n" { outDoc->writeChar('\n'); }
+<DocScan>({B}*"\n"{B}*){2,} {
+ if (insideArgumentList)
+ {
+ insideArgumentList=FALSE;
+ outDoc->endItemList();
+ }
+ else
+ {
+ outDoc->newParagraph();
+ }
+ if (inBlock()) endBlock();
+ }
+<DocScan>{BN}+ {
+ outDoc->writeChar(' ');
+ }
+<DocCode,DocEmphasis,DocBold,DocScan>. {
+ outDoc->writeChar(*yytext);
+ }
+<NextSemi>"{" { BEGIN(SkipBlock); }
+<SkipBlock>"{" { ++bracketCount ; }
+<SkipBlock>"}" { if( bracketCount )
+ --bracketCount ;
+ else
+ BEGIN( NextSemi ) ;
+ }
+<NextSemi>\" {
+ lastStringContext=NextSemi;
+ BEGIN(SkipString);
+ }
+<NextSemi>[;,] {
+ unput(*yytext);
+ BEGIN( FindMembers ) ;
+ }
+<FindMembers>{B}*"signals"{BN}*":"{BN}* { current->sig = sig = TRUE;
+ current->slot = slot = FALSE;
+ current->protection = protection = Public ;
+ current->type.resize(0);
+ current->name.resize(0);
+ current->args.resize(0);
+ current->argList->clear();
+ lineCount() ;
+ }
+
+<FindMembers>{B}*"public"{BN}*"slots"{BN}*":"{BN}* {
+ current->protection = protection = Public ;
+ current->slot = slot = TRUE;
+ current->sig = sig = FALSE;
+ current->type.resize(0);
+ current->name.resize(0);
+ current->args.resize(0);
+ current->argList->clear();
+ lineCount();
+ }
+
+<FindMembers>{B}*"protected"{BN}*"slots"{BN}*":"{BN}* {
+ current->protection = protection = Protected ;
+ current->slot = slot = TRUE;
+ current->sig = sig = FALSE;
+ current->type.resize(0);
+ current->name.resize(0);
+ current->args.resize(0);
+ current->argList->clear();
+ lineCount();
+ }
+
+<FindMembers>{B}*"private"{BN}*"slots"{BN}*":"{BN}* {
+ current->protection = protection = Private ;
+ current->slot = slot = TRUE;
+ current->sig = sig = FALSE;
+ current->type.resize(0);
+ current->name.resize(0);
+ current->args.resize(0);
+ current->argList->clear();
+ lineCount();
+ }
+
+<FindMembers>{B}*"public"{BN}*":"{BN}* {
+ current->protection = protection = Public ;
+ current->slot = slot = FALSE;
+ current->sig = sig = FALSE;
+ current->type.resize(0);
+ current->name.resize(0);
+ current->args.resize(0);
+ current->argList->clear();
+ lineCount() ;
+ }
+<FindMembers>{B}*"protected"{BN}*":"{BN}* {
+ current->protection = protection = Protected ;
+ current->slot = slot = FALSE;
+ current->sig = sig = FALSE;
+ current->type.resize(0);
+ current->name.resize(0);
+ current->args.resize(0);
+ current->argList->clear();
+ lineCount() ;
+ }
+<FindMembers>{B}*"private"{BN}*":"{BN}* {
+ current->protection = protection = Private ;
+ current->slot = slot = FALSE;
+ current->sig = sig = FALSE;
+ current->type.resize(0);
+ current->name.resize(0);
+ current->args.resize(0);
+ current->argList->clear();
+ lineCount() ;
+ }
+ /*
+<FindMembers>"inline"
+ */
+<FindMembers>{B}*"static"{BN}+ { //current->type += " static ";
+ current->stat = TRUE;
+ lineCount();
+ }
+<FindMembers>{B}*"extern"{BN}+ {
+ current->stat = FALSE;
+ lineCount();
+ }
+<FindMembers>{B}*"virtual"{BN}+ { current->type += " virtual ";
+ current->virt = Virtual;
+ lineCount();
+ }
+<FindMembers>{B}*"inline"{BN}+ { lineCount(); }
+<FindMembers>{B}*"typename"{BN}+ { lineCount(); }
+<FindMembers>{B}*"namespace"{BN}+ {
+ isTypedef=FALSE;
+ current->section = Entry::NAMESPACE_SEC;
+ current->type = "namespace" ;
+ current->fileName = yyFileName;
+ current->startLine = yyLineNr;
+ lineCount();
+ BEGIN( ClassName );
+ }
+<FindMembers>{B}*(("typedef"{BN}+)?)"class"{BN}+ {
+ isTypedef=((QString)yytext).find("typedef")!=-1;
+ current->section = Entry::CLASS_SEC ;
+ addType( current ) ;
+ current->type += " class" ;
+ current->fileName = yyFileName;
+ current->startLine = yyLineNr;
+ lineCount() ;
+ BEGIN( ClassName ) ;
+ }
+<FindMembers>{B}*(("typedef"{BN}+)?)"struct"{BN}+ {
+ isTypedef=((QString)yytext).find("typedef")!=-1;
+ current->section = Entry::STRUCT_SEC ;
+ addType( current ) ;
+ current->type += " struct" ;
+ current->fileName = yyFileName;
+ current->startLine = yyLineNr;
+ lineCount() ;
+ BEGIN( ClassName ) ;
+ }
+<FindMembers>{B}*(("typedef"{BN}+)?)"union"{BN}+ {
+ isTypedef=((QString)yytext).find("typedef")!=-1;
+ current->section = Entry::UNION_SEC ;
+ addType( current ) ;
+ current->type += " union" ;
+ current->fileName = yyFileName;
+ current->startLine = yyLineNr;
+ lineCount() ;
+ BEGIN( ClassName ) ;
+ }
+<FindMembers>{B}*(("typedef"{BN}+)?)"enum"{BN}+ {
+ isTypedef=((QString)yytext).find("typedef")!=-1;
+ current->section = Entry::ENUM_SEC ;
+ addType( current ) ;
+ current->type += " enum" ;
+ current->fileName = yyFileName;
+ current->startLine = yyLineNr;
+ lineCount() ;
+ BEGIN( ClassName ) ;
+ }
+<Operator>"("{BN}*")"{BN}*/"(" {
+ lineCount();
+ current->name += yytext ;
+ current->name = current->name.simplifyWhiteSpace();
+ BEGIN( FindMembers ) ;
+ }
+<Operator>[^(] {
+ current->name += *yytext ;
+ }
+<Operator>"<>" { /* skip guided templ specifiers */ }
+<Operator>"(" {
+ current->name = current->name.simplifyWhiteSpace();
+ unput(*yytext);
+ BEGIN( FindMembers ) ;
+ }
+<FindMembers>"template"({BN}*)"<"/[>]? {
+ lineCount();
+ if (current->tArgList)
+ {
+ //printf("scanner.l current->tArgList->clear() %p\n",current->tArgList);
+ current->tArgList->clear();
+ }
+ else
+ {
+ current->tArgList = new ArgumentList;
+ current->tArgList->setAutoDelete(TRUE);
+ //printf("scanner.l new tArgList %p\n",current->tArgList);
+ }
+ templateStr="<";
+ copyArgString=&templateStr;
+ currentArgumentContext = FindMembers;
+ //printf("Start template list\n");
+ BEGIN( ReadTempArgs );
+ }
+ /*
+<FindMembers>({ID}{BN}*"::")*{BN}*"operator"{BN}*[<=]+ {
+ lineCount();
+ addType( current );
+ current->name = yytext;
+ }
+<FindMembers>"operator"{BN}*"/"[=]?/[^/ *] { space added!
+ lineCount();
+ addType( current );
+ current->name = yytext;
+ }
+<FindMembers>"operator"{BN}*"({B}*)"{BN}* /"(" { space added!
+ lineCount();
+ addType( current );
+ current->name = yytext;
+ }
+<FindMembers>"operator"{BN}*[^(/]+ {
+ lineCount();
+ addType( current ) ;
+ current->name = yytext ;
+ }
+ */
+<FindMembers>"using"{BN}+ { lineCount(); BEGIN(Using); }
+<Using>";" { BEGIN(FindMembers); }
+<FindMembers>{SCOPENAME}{BN}*"<>" { // guided template decl
+ QString n=yytext;
+ addType( current );
+ current->name=n.left(n.length()-2);
+ }
+<FindMembers>{SCOPENAME}{BN}*/"<" {
+ sharpCount=0;
+ lineCount();
+ addType( current );
+ current->name=yytext;
+ current->name=current->name.stripWhiteSpace();
+ if (current->name.right(8)=="operator")
+ BEGIN( Operator );
+ else
+ BEGIN( EndTemplate );
+ }
+<EndTemplate>"<" {
+ current->name+='<';
+ sharpCount++;
+ }
+ /*
+<EndTemplate>">"({BN}*"::"{SCOPENAME})? {
+ */
+<EndTemplate>">" {
+ current->name+=*yytext;
+ if (--sharpCount<=0)
+ {
+ //printf("Found %s\n",current->name.data());
+ BEGIN(FindMembers);
+ }
+ }
+<EndTemplate>">"{BN}*"(" {
+ lineCount();
+ current->name+='>';
+ if (--sharpCount<=0)
+ {
+ current->args = "(";
+ currentArgumentContext = FuncQual;
+ copyArgString=&current->args;
+ //printf("Found %s\n",current->name.data());
+ BEGIN( ReadFuncArgType ) ;
+ }
+ }
+<EndTemplate>">"{BN}*/"::" {
+ lineCount();
+ current->name+='>';
+ if (--sharpCount<=0)
+ {
+ BEGIN(FindMemberName);
+ }
+ }
+<EndTemplate>. { current->name+=*yytext; }
+<FindMembers,FindMemberName>{SCOPENAME} {
+ lineCount();
+ if (YY_START==FindMembers)
+ {
+ addType( current ) ;
+ current->name = yytext;
+ }
+ else
+ {
+ current->name += yytext;
+ }
+ QString tmp=yytext;
+ if (tmp.right(8)=="operator")
+ BEGIN( Operator );
+ else
+ BEGIN(FindMembers);
+ }
+<FindMembers>^{B}*"#" { lastCPPContext = YY_START;
+ BEGIN( SkipCPP ) ;
+ }
+<FindMembers>^{B}*"#define" {
+ BEGIN( Define );
+ }
+<SkipCPP>.
+<SkipCPP>\\[\r]*"\n"[\r]* { yyLineNr++ ; }
+<SkipCPP>[\r]*\n[\r]* { yyLineNr++ ;
+ BEGIN( lastCPPContext) ;
+ }
+<Define>{ID}/"(" {
+ current->name = yytext;
+ BEGIN( DefineArg );
+ }
+<DefineArg>")" {
+ //printf("Define with args\n");
+ current->args += ')';
+ BEGIN( DefineEnd );
+ }
+<DefineArg>. {
+ current->args += *yytext;
+ }
+<Define>{ID} {
+ //printf("Define `%s' without args\n",yytext);
+ current->name = yytext;
+ BEGIN(DefineEnd);
+ }
+<DefineEnd>\n {
+ //printf("End define\n");
+ current->fileName = yyFileName;
+ current->startLine = yyLineNr;
+ current->type.resize(0);
+ current->args = current->args.simplifyWhiteSpace();
+ current->name = current->name.stripWhiteSpace();
+ current->section = Entry::DEFINE_SEC;
+ current_root->addSubEntry(current);
+ current = new Entry ;
+ current->protection = protection ;
+ current->sig = sig;
+ current->virt = virt;
+ current->stat = gstat;
+ current->slot = slot;
+ BEGIN(FindMembers);
+ }
+<DefineEnd>\\\n
+<DefineEnd>.
+
+<FindMembers>[*&]+ { current->name += yytext ; }
+<FindMembers,MemberSpec,Function,NextSemi>";"{BN}*("/**"|"//!"|"/*!")"<" {
+ lineCount();
+ current->doc.resize(0);
+ current->brief.resize(0);
+ lastAfterDocContext = YY_START;
+ afterDocTerminator = ';';
+ if (yytext[yyleng-3]=='/')
+ BEGIN(AfterDocLine);
+ else if (yytext[yyleng-2]=='*')
+ BEGIN(AfterDocBrief);
+ else
+ BEGIN(AfterDoc);
+ }
+<MemberSpec,FindFields,FindMembers,NextSemi>","{BN}*("/**"|"//!"|"/*!")"<" {
+ lineCount();
+ current->doc.resize(0);
+ current->brief.resize(0);
+ lastAfterDocContext = YY_START;
+ afterDocTerminator = ',';
+ if (yytext[yyleng-3]=='/')
+ BEGIN(AfterDocLine);
+ else if (yytext[yyleng-2]=='*')
+ BEGIN(AfterDocBrief);
+ else
+ BEGIN(AfterDoc);
+ }
+<DefineEnd,FindFields,FindFieldArg>{BN}*("/**"|"//!"|"/*!")"<" {
+ lineCount();
+ current->doc.resize(0);
+ current->brief.resize(0);
+ lastAfterDocContext = YY_START;
+ if (YY_START==DefineEnd)
+ afterDocTerminator = '\n';
+ else
+ afterDocTerminator = 0;
+ if (yytext[yyleng-3]=='/')
+ BEGIN(AfterDocLine);
+ else if (yytext[yyleng-2]=='*')
+ BEGIN(AfterDocBrief);
+ else
+ BEGIN(AfterDoc);
+ }
+<FindMembers>"=" {
+ BEGIN(NextSemi);
+ }
+<FindMembers>[:;,] {
+ QString oldType = current->type.copy();
+ QString oldDocs = current->doc.copy();
+ current->type=current->type.simplifyWhiteSpace();
+ current->args=current->args.simplifyWhiteSpace();
+ current->name=current->name.stripWhiteSpace();
+ current->section = Entry::VARIABLE_SEC ;
+ current->fileName = yyFileName;
+ current->startLine = yyLineNr;
+ current_root->addSubEntry( current ) ;
+ current = new Entry ;
+ // variable found
+ current->section = Entry::EMPTY_SEC ;
+ current->protection = protection;
+ current->slot = slot = FALSE;
+ current->sig = sig = FALSE;
+ current->virt = Normal;
+ current->stat = gstat;
+ // skip expression or bitfield if needed
+ if ( *yytext == ':')
+ BEGIN( NextSemi );
+ else
+ {
+ if ( *yytext == ',' )
+ {
+ int i=oldType.length();
+ while (i>0 && (oldType[i-1]=='*' || oldType[i-1]==' ')) i--;
+ current->type = oldType.left(i);
+ current->doc = oldDocs;
+ }
+ BEGIN( FindMembers ) ;
+ }
+ }
+
+<FindMembers>"[" { current->args += yytext ;
+ sharpCount=1;
+ BEGIN( Array ) ;
+ }
+<Array>"]" { current->args += *yytext ;
+ if (--sharpCount<=0)
+ BEGIN( FindMembers ) ;
+ }
+<Array>"[" { current->args += *yytext ;
+ sharpCount++;
+ }
+<Array>. { current->args += *yytext ; }
+
+<FindMembers>"<" { addType( current ) ;
+ current->type += yytext ;
+ BEGIN( Sharp ) ;
+ }
+<Sharp>">" { current->type += *yytext ;
+ if (--sharpCount<=0)
+ BEGIN( FindMembers ) ;
+ }
+<Sharp>"<" { current->type += *yytext ;
+ sharpCount++;
+ }
+<Sharp>{BN}+ {
+ lineCount();
+ }
+<Sharp>. { current->type += *yytext ; }
+<FindFields>{ID} {
+ current->name = yytext;
+ }
+<FindFields>"=" {
+ BEGIN(FindFieldArg);
+ }
+<FindFields>"," {
+ //printf("adding `%s' `%s' `%s' to enum `%s'\n",
+ // current->type.data(), current->name.data(),
+ // current->args.data(), current_root->name.data());
+ current->fileName = yyFileName;
+ current->startLine = yyLineNr;
+ current->type = "@"; // enum marker
+ current->args = current->args.simplifyWhiteSpace();
+ current->name = current->name.stripWhiteSpace();
+ current->section = Entry::VARIABLE_SEC;
+ // add to the scope of the enum
+ current_root->addSubEntry(current);
+ current = new Entry(*current);
+ // add to the scope surrounding the enum (copy!)
+ current_root->parent->addSubEntry(current);
+ current = new Entry ;
+ current->protection = protection ;
+ current->sig = sig;
+ current->virt = virt;
+ current->stat = gstat;
+ current->slot = slot;
+ }
+<FindFieldArg>"," { unput(*yytext); BEGIN(FindFields); }
+<Curly>[^\r\n{}"/]* { current->program += yytext ; }
+<Curly>"//".* { current->program += yytext ; }
+<Curly>\"[^\r\n"]*\" { current->program += yytext ; }
+<Curly>"/*"{B}* { current->program += yytext ;
+ lastContext = Curly ;
+ BEGIN( Comment ) ;
+ }
+<Curly>"/*"{BL} { current->program += yytext ;
+ ++yyLineNr ;
+ lastContext = Curly ;
+ BEGIN( Comment ) ;
+ }
+<Curly>"{" { current->program += yytext ;
+ ++bracketCount ;
+ }
+<Curly>"}" { if ( bracketCount )
+ {
+ current->program += yytext ;
+ --bracketCount ;
+ }
+ else
+ {
+ QString &cn = current->name;
+ QString &rn = current_root->name;
+ //printf("current->name=`%s' current_root->name=`%s'\n",
+ // cn.data(),rn.data());
+ if (cn && cn[0]!='@' &&
+ (current_root->section & Entry::SCOPE_MASK))
+ {
+ cn.prepend(rn+"::");
+ }
+ if (isTypedef && cn.length()==0)
+ {
+ //printf("Typedef Name\n");
+ BEGIN( TypedefName );
+ }
+ else
+ {
+ if (current->section == Entry::ENUM_SEC)
+ {
+ current->program+=','; // add field terminator
+ }
+ // add compound definition to the tree
+ current->args = current->args.simplifyWhiteSpace();
+ current->type = current->type.simplifyWhiteSpace();
+ current->name = current->name.stripWhiteSpace();
+ //printf("adding `%s' `%s' `%s' brief=%s\n",current->type.data(),current->name.data(),current->args.data(),current->brief.data());
+ current_root->addSubEntry( current ) ;
+ current = new Entry(*current);
+ if (current->section == Entry::NAMESPACE_SEC)
+ { // a namespace ends with a closing bracket
+ current->reset();
+ current->protection = protection ;
+ current->sig = sig;
+ current->virt = virt;
+ current->stat = gstat;
+ current->slot = slot;
+ BEGIN( FindMembers ) ;
+ }
+ else
+ BEGIN( MemberSpec ) ;
+ }
+ }
+ }
+<TypedefName>{ID} {
+ if (current->section == Entry::ENUM_SEC)
+ {
+ current->program+=","; // add field terminator
+ }
+ current->name=yytext;
+ if (current_root->section & Entry::SCOPE_MASK)
+ {
+ current->name.prepend(current_root->name+"::");
+ }
+ current->args = current->args.simplifyWhiteSpace();
+ current->type = current->type.simplifyWhiteSpace();
+ //printf("Adding compound %s %s %s\n",current->type.data(),current->name.data(),current->args.data());
+ current_root->addSubEntry( current ) ;
+ current = new Entry;
+ current->protection = protection ;
+ current->sig = sig;
+ current->virt = virt;
+ current->stat = gstat;
+ current->slot = slot;
+ BEGIN(MemberSpecSkip);
+ }
+<MemberSpec>([*&]*{BN}*)*{ID}("["[a-z_A-Z0-9]*"]")* { // the [] part could be improved.
+ lineCount();
+ int i=0,l=yyleng,j;
+ while (i<l && (!isalpha(yytext[i]))) i++;
+ msName = yytext;
+ msName = msName.right(msName.length()-i);
+ j=msName.find("[");
+ if (j!=-1)
+ {
+ msArgs=msName.right(msName.length()-j);
+ msName=msName.left(j);
+ }
+ msType = yytext; msType=msType.left(i);
+ }
+<MemberSpec>[,;] {
+ if (msName.length()>0)
+ {
+ Entry *varEntry=new Entry;
+ varEntry->protection = current->protection ;
+ varEntry->sig = current->sig;
+ varEntry->virt = current->virt;
+ varEntry->stat = current->stat;
+ varEntry->slot = current->slot;
+ varEntry->section = Entry::VARIABLE_SEC;
+ varEntry->name = msName.stripWhiteSpace();
+ varEntry->type = current->type.simplifyWhiteSpace()+" ";
+ varEntry->args = msArgs; //current->args.simplifyWhiteSpace();
+ //if (current->name.length()>0 && current->name[0]!='@' &&
+ // current->parent->section & Entry::COMPOUND_MASK)
+ // varEntry->type+=current->parent->name+"::";
+ if (isTypedef)
+ varEntry->type.prepend("typedef ");
+ varEntry->type+=current->name+msType;
+ varEntry->fileName = yyFileName;
+ varEntry->startLine = yyLineNr;
+ varEntry->doc = current->doc.copy();
+ varEntry->brief = current->brief.copy();
+ //printf("Add: type=`%s',name=`%s',args=`%s'\n",
+ // varEntry->type.data(),varEntry->name.data(),varEntry->args.data());
+ current_root->addSubEntry(varEntry);
+ }
+ if (*yytext==';')
+ {
+ msType.resize(0);
+ msName.resize(0);
+ msArgs.resize(0);
+ isTypedef=FALSE;
+ current->reset();
+ current->protection = protection ;
+ current->sig = sig;
+ current->virt = virt;
+ current->stat = gstat;
+ current->slot = slot;
+ BEGIN( FindMembers );
+ }
+ }
+<MemberSpec>"=" { BEGIN(MemberSpecSkip); }
+<MemberSpecSkip>"{" {
+ bracketCount=0;
+ lastCurlyContext = MemberSpecSkip;
+ BEGIN(SkipCurly);
+ }
+<MemberSpecSkip>"," { BEGIN(MemberSpec); }
+<MemberSpecSkip>";" { unput(';'); BEGIN(MemberSpec); }
+<Curly>\n { current->program += yytext ;
+ yyLineNr++ ;
+ }
+<Curly>. { current->program += yytext ; }
+
+<FindMembers>"("({ID}{BN}*"::"{BN}*)*("*"{BN}*)+ {
+ lineCount();
+ addType(current);
+ funcPtrType=yytext;
+ //current->type += yytext;
+ BEGIN( FuncPtr );
+ }
+<FuncPtr>{SCOPENAME} {
+ current->name = yytext;
+ BEGIN( EndFuncPtr );
+ }
+<FuncPtr>. {
+ //printf("Error: FuncPtr `%c' unexpected at line %d of %s\n",*yytext,yyLineNr,yyFileName);
+ }
+<EndFuncPtr>")"{BN}*/";" { // a variable with extra braces
+ lineCount();
+ current->type+=funcPtrType.data()+1;
+ BEGIN(FindMembers);
+ }
+<EndFuncPtr>")"{BN}*/"(" { // a variable function
+ lineCount();
+ current->type+=funcPtrType+")";
+ BEGIN(FindMembers);
+ }
+<EndFuncPtr>"(" { // a function returning a function
+ current->args += *yytext ;
+ bracketCount=0;
+ BEGIN( FuncFunc );
+ }
+<EndFuncPtr>")" {
+ BEGIN(FindMembers);
+ }
+<FuncFunc>"(" {
+ current->args += *yytext ;
+ ++bracketCount;
+ }
+<FuncFunc>")" {
+ current->args += *yytext ;
+ if ( bracketCount )
+ --bracketCount;
+ else
+ {
+ BEGIN(FuncFuncEnd);
+ }
+ }
+<FuncFuncEnd>")"{BN}*"(" {
+ lineCount();
+ current->type+=funcPtrType+")(";
+ BEGIN(FuncFuncType);
+ }
+<FuncFuncEnd>")"{BN}*/[;{] {
+ lineCount();
+ current->type+=funcPtrType.data()+1;
+ BEGIN(Function);
+ }
+<FuncFuncEnd>. {
+ current->args += *yytext;
+ }
+<FuncFuncType>"(" {
+ current->type += *yytext;
+ bracketCount++;
+ }
+<FuncFuncType>")" {
+ current->type += *yytext;
+ if (bracketCount)
+ --bracketCount;
+ else
+ BEGIN(Function);
+ }
+<FuncFuncType>{BN}*","{BN}* { lineCount() ; current->type += ", " ; }
+<FuncFuncType>{BN}+ { lineCount() ; current->type += ' ' ; }
+<FuncFuncType>. {
+ current->type += *yytext;
+ }
+<FindMembers>"(" { current->args = yytext;
+ currentArgumentContext = FuncQual;
+ copyArgString=&current->args;
+ BEGIN( ReadFuncArgType ) ;
+ //printf(">>> Read function arguments!\n");
+ }
+ /*
+<FindMembers>"("{BN}*("void"{BN}*)?")" {
+ lineCount();
+ current->args = "()";
+ BEGIN( FuncQual );
+ }
+ */
+
+ /*- Function argument reading rules ---------------------------------------*/
+
+<ReadFuncArgType>[^ \/\r\t\n\)\(\"\']+ { *copyArgString+=yytext; }
+<CopyArgString>[^\n\\\"\']+ { *copyArgString+=yytext; }
+<CopyArgRound>[^\/\n\)\(\"\']+ { *copyArgString+=yytext; }
+<ReadFuncArgType,ReadTempArgs>{BN}* {
+ *copyArgString+=" ";
+ lineCount();
+ }
+<ReadFuncArgType,CopyArgRound,CopyArgSharp,ReadTempArgs>\" {
+ *copyArgString+=*yytext;
+ lastCopyArgStringContext = YY_START;
+ BEGIN( CopyArgString );
+ }
+<ReadFuncArgType,ReadTempArgs>"(" {
+ *copyArgString+=*yytext;
+ argRoundCount=0;
+ lastCopyArgContext = YY_START;
+ BEGIN( CopyArgRound );
+ }
+<ReadFuncArgType>")" {
+ *copyArgString+=*yytext;
+ stringToArgumentList(*copyArgString,current->argList);
+ BEGIN( currentArgumentContext );
+ }
+<ReadTempArgs>"<" {
+ *copyArgString+=*yytext;
+ argSharpCount=0;
+ BEGIN( CopyArgSharp );
+ }
+<ReadTempArgs>">" {
+ *copyArgString+=*yytext;
+ //printf("end template list %s\n",copyArgString->data());
+ stringToArgumentList(*copyArgString,current->tArgList);
+ BEGIN( currentArgumentContext );
+ }
+<CopyArgRound>"(" {
+ argRoundCount++;
+ *copyArgString+=*yytext;
+ }
+<CopyArgRound>")" {
+ *copyArgString+=*yytext;
+ if (argRoundCount>0)
+ argRoundCount--;
+ else
+ BEGIN( lastCopyArgContext );
+ }
+<CopyArgSharp>"<" {
+ argSharpCount++;
+ *copyArgString+=*yytext;
+ }
+<CopyArgSharp>">" {
+ *copyArgString+=*yytext;
+ if (argRoundCount>0)
+ argRoundCount--;
+ else
+ BEGIN( ReadTempArgs );
+ }
+<CopyArgString>\\. {
+ *copyArgString+=yytext;
+ }
+<CopyArgString>\" {
+ *copyArgString+=*yytext;
+ BEGIN( lastCopyArgStringContext );
+ }
+<ReadFuncArgType,ReadTempArgs,CopyArgRound,CopyArgSharp>"'"\\[0-7]{1,3}"'" { *copyArgString+=yytext; }
+<ReadFuncArgType,ReadTempArgs,CopyArgRound,CopyArgSharp>"'"\\."'" { *copyArgString+=yytext; }
+<ReadFuncArgType,ReadTempArgs,CopyArgRound,CopyArgSharp>"'"."'" { *copyArgString+=yytext; }
+<ReadFuncArgType,ReadTempArgs,CopyArgString,CopyArgRound,CopyArgSharp>\n { yyLineNr++; *copyArgString+=*yytext; }
+<ReadFuncArgType,ReadTempArgs,CopyArgString,CopyArgRound,CopyArgSharp>. { *copyArgString+=*yytext; }
+
+
+
+ /*------------------------------------------------------------------------*/
+
+
+<FuncRound>"(" { current->args += *yytext ;
+ ++bracketCount ;
+ }
+<FuncRound>")" { current->args += *yytext ;
+ if ( bracketCount )
+ --bracketCount ;
+ else
+ BEGIN( FuncQual ) ;
+ }
+ /*
+<FuncQual>"#" { lastCPPContext = YY_START;
+ BEGIN(SkipCPP);
+ }
+ */
+<FuncQual>[{:;] { unput(*yytext); BEGIN( Function ); }
+<FuncQual>{BN}*"const"{BN}* {
+ lineCount() ;
+ current->args += " const ";
+ current->argList->constSpecifier=TRUE;
+ }
+<FuncQual>{BN}*"volatile"{BN}* {
+ lineCount() ;
+ current->args += " volatile ";
+ current->argList->volatileSpecifier=TRUE;
+ }
+<FuncQual>{BN}*"="{BN}*"0"{BN}* {
+ lineCount() ;
+ current->args += " = 0";
+ current->virt = Pure;
+ current->argList->pureSpecifier=TRUE;
+ }
+<FuncRound,FuncFunc>{BN}*","{BN}* {
+ lineCount() ;
+ current->args += ", " ;
+ }
+<FuncQual,FuncRound,FuncFunc>{BN}+ {
+ lineCount() ;
+ current->args += ' ' ;
+ }
+<FuncQual,FuncRound,FuncFunc>. { current->args += *yytext; }
+<FuncQual>{BN}*"throw"{BN}*"(" {
+ current->exception = " throw(" ;
+ lineCount() ;
+ BEGIN( ExcpRound ) ;
+ }
+<ExcpRound>"(" { current->exception += *yytext ;
+ ++bracketCount ;
+ }
+<ExcpRound>")" { current->exception += *yytext ;
+ if ( bracketCount )
+ --bracketCount ;
+ else
+ BEGIN( FuncQual ) ;
+ }
+<ExcpRound>. {
+ current->exception += yytext;
+ }
+<Function>"(" { current->type += current->name ;
+ current->name = current->args ;
+ current->args = yytext ;
+ BEGIN( FuncRound ) ;
+ }
+<Function>"#" { lastCPPContext = YY_START;
+ BEGIN(SkipCPP);
+ }
+<Function>[:;{] {
+ current->name=current->name.simplifyWhiteSpace();
+ current->type=current->type.simplifyWhiteSpace();
+ current->args=current->args.simplifyWhiteSpace();
+ QString &cn=current->name;
+ QString &rn=current_root->name;
+ //printf("current_root->name=`%s'\n",rn.data());
+ //printf("Function: `%s' `%s' `%s'\n",current->type.data(),cn.data(),current->args.data());
+ int i;
+ if ((i=cn.findRev("::"))!=-1) // name contains scope
+ {
+ if (cn.left(i)==rn.right(i)) // scope name is redundant
+ {
+ cn=cn.right(cn.length()-i-2); // strip scope
+ //printf("new name=`%s'\n",cn.data());
+ }
+ }
+ //if (cname.left(current_root->name.length()+2)==current_root->name+"::")
+ //{ // strip redundant scope
+ // current->name=current->name.right(current->name.length()-current_root->name.length()-2);
+ // printf("new name=`%s'\n",current->name.data());
+ //}
+ current->fileName = yyFileName;
+ current->startLine = yyLineNr;
+ if (*yytext!=';' || (current_root->section&Entry::SCOPE_MASK) )
+ {
+ int tempArg=current->name.find('<');
+ QString tempName;
+ if (tempArg==-1)
+ tempName=current->name;
+ else
+ tempName=current->name.left(tempArg);
+ if (current->type.isNull() && tempName.find("operator")==-1 &&
+ (tempName.find('*')!=-1 || tempName.find('&')!=-1))
+ {
+ //printf("Scanner.l: found in class variable: `%s' `%s' `%s'\n",
+ // current->type.data(),current->name.data(),current->args.data());
+ current->section = Entry::VARIABLE_SEC ;
+ }
+ else
+ {
+ //printf("Scanner.l: found in class function: `%s' `%s' `%s'\n",
+ // current->type.data(),current->name.data(),current->args.data());
+ current->section = Entry::FUNCTION_SEC ;
+ }
+ }
+ else // a global function prototype or function variable
+ {
+ //printf("Scanner.l: prototype? type=`%s' name=`%s' args=`%s'\n",current->type.data(),current->name.data(),current->args.data());
+ QRegExp re("([^)])");
+ if (!current->type.isNull() && current->type.find(re,0)!=-1)
+ {
+ //printf("Scanner.l: found function variable!\n");
+ current->section = Entry::VARIABLE_SEC;
+ }
+ else
+ {
+ //printf("Scanner.l: found prototype\n");
+ current->section = Entry::FUNCTION_SEC;
+ current->proto = TRUE;
+ }
+ }
+ current_root->addSubEntry(current);
+ current = new Entry ;
+ current->protection = protection;
+ current->sig = sig;
+ current->virt = virt;
+ current->stat = gstat;
+ current->slot = slot;
+ lastCurlyContext = FindMembers;
+ if( *yytext == '{' )
+ BEGIN( SkipCurly ) ;
+ else if( *yytext == ':' )
+ BEGIN( SkipInits ) ;
+ else
+ BEGIN( FindMembers ) ;
+ }
+
+<SkipInits>"{" {
+ lastCurlyContext = FindMembers;
+ BEGIN( SkipCurly ) ;
+ }
+<SkipCurly,SkipCurlyCpp>"{" { ++bracketCount ; }
+<SkipCurly,SkipCurlyCpp>"}" { if( bracketCount )
+ --bracketCount ;
+ else
+ //BEGIN( FindMembers ) ;
+ BEGIN( lastCurlyContext ) ;
+ }
+<SkipCurly>\'.\'
+<SkipCurly>\" {
+ lastStringContext=SkipCurly;
+ BEGIN( SkipString );
+ }
+<SkipCurly>^{B}*"#" { BEGIN( SkipCurlyCpp ); }
+<SkipCurlyCpp>\n { yyLineNr++;
+ lastCurlyContext = FindMembers;
+ BEGIN( SkipCurly );
+ }
+<SkipCurlyCpp>\\[\r]*"\n"[\r]* { yyLineNr++; }
+<SkipCurlyCpp>"/*"
+<SkipCurlyCpp>"*/"
+<SkipCurlyCpp>"//"
+<SkipString>\\.
+<SkipString>\" { BEGIN( lastStringContext ); }
+<SkipString>"/*"
+<SkipString>"*/"
+<SkipString>"//"
+
+<Bases,ClassName>";" {
+ current->section = Entry::EMPTY_SEC ;
+ current->type.resize(0) ;
+ current->name.resize(0) ;
+ current->args.resize(0) ;
+ current->argList->clear();
+ BEGIN( FindMembers ) ;
+ }
+<ClassName>{ID} {
+ current->name = yytext ;
+ BEGIN( ClassVar );
+ }
+ /*
+<ClassVar>{ID}/{BN}*"{" { // we probably got some M$ extension
+ current->name = yytext ;
+ }
+<ClassVar>{ID}/{BN}*":" { // we probably got some M$ extension
+ current->name = yytext ;
+ }
+ */
+<ClassVar>{ID} {
+ if (isTypedef)
+ {
+ typedefDict.insert(yytext,new QString(current->name));
+ current->type.prepend("typedef ");
+ }
+ current->type += ' ' ;
+ current->type += current->name ;
+ current->name = yytext ;
+ //BEGIN( FindMembers );
+ }
+<ClassVar>"(" {
+ roundCount=1;
+ lastSkipRoundContext=YY_START;
+ BEGIN(SkipRound);
+ }
+<ClassVar>":" {
+ current->type.resize(0);
+ baseProt=Private;
+ baseVirt=Normal;
+ baseName.resize(0);
+ BEGIN( Bases ) ;
+ }
+<ClassVar>[;=*&] {
+ unput(*yytext);
+ BEGIN( FindMembers );
+ }
+<ClassName,ClassVar>{B}*"{"{B}* { current->fileName = yyFileName ;
+ current->startLine = yyLineNr ;
+ if (current->name.length()==0 && !isTypedef) // anonymous compound
+ current->name.sprintf("@%d",anonCount++);
+ BEGIN( Curly ) ;
+ }
+<Bases>"virtual" { baseVirt = Virtual; }
+<Bases>"public" { baseProt = Public; }
+<Bases>"protected" { baseProt = Protected; }
+<Bases>"private" { baseProt = Private; }
+<Bases>({ID}{BN}*"::"{BN}*)*{ID} {
+ //current->extends->append(
+ // new BaseInfo(yytext,baseProt,baseVirt)
+ //) ;
+ baseName += yytext;
+ current->args += ' ' ;
+ current->args += yytext ;
+ }
+<ClassVar>"<" { current->name += *yytext;
+ sharpCount=1;
+ lastSkipSharpContext = YY_START;
+ specName = &current->name;
+ BEGIN ( Specialization );
+ }
+<Bases>"<" { baseName += *yytext;
+ sharpCount=1;
+ lastSkipSharpContext = YY_START;
+ specName = &baseName;
+ BEGIN ( Specialization );
+ }
+<Specialization>"<" { *specName += *yytext;
+ sharpCount++;
+ }
+<Specialization>">" {
+ *specName += *yytext;
+ if (--sharpCount<=0)
+ BEGIN(lastSkipSharpContext);
+ }
+<Specialization>{BN}+ { lineCount(); *specName +=' '; }
+<Specialization>. {
+ *specName += *yytext;
+ }
+<SkipSharp>"<" { ++sharpCount; }
+<SkipSharp>">" { if (--sharpCount<=0)
+ BEGIN ( lastSkipSharpContext );
+ }
+<SkipRound>"(" { ++roundCount; }
+<SkipRound>")" { if (--roundCount<=0)
+ BEGIN ( lastSkipRoundContext );
+ }
+<Bases>"," { current->args += ',' ;
+ if (baseName.length()>0)
+ current->extends->append(
+ new BaseInfo(baseName,baseProt,baseVirt)
+ );
+ baseProt=Private;
+ baseVirt=Normal;
+ baseName.resize(0);
+ }
+<Bases>{B}*"{"{B}* { current->fileName = yyFileName ;
+ current->startLine = yyLineNr ;
+ if (baseName.length()>0)
+ current->extends->append(
+ new BaseInfo(baseName,baseProt,baseVirt)
+ );
+ BEGIN( Curly ) ;
+ }
+<Comment>\n { current->program += yytext ;
+ yyLineNr++ ;
+ }
+<Comment>"/*" { current->program += yytext ; }
+<Comment>"//" { current->program += yytext ; }
+<Comment>. { current->program += *yytext ; }
+<Comment>.*"*/" { current->program += yytext ;
+ BEGIN( Curly ) ;
+ }
+
+<FindMembers,FindFields,MemberSpec,FuncQual,SkipCurly,Operator>("//"{B}*)?"/*!" {
+ removeSlashes=(yytext[1]=='/');
+ tmpDocType=-1;
+ if (YY_START==Curly)
+ current->doc+="\n\n";
+ else
+ current->doc.resize(0);
+ lastDocContext = YY_START;
+ if (current_root->section & Entry::SCOPE_MASK)
+ current->inside = current_root->name+"::";
+ BEGIN( Doc );
+ }
+<FindMembers,FindFields,MemberSpec,FuncQual,SkipCurly,Operator>("//"{B}*)?"/**"/[^/*] {
+ removeSlashes=(yytext[1]=='/');
+ if (current_root->section & Entry::SCOPE_MASK)
+ current->inside = current_root->name+"::";
+ if (YY_START==Curly)
+ {
+ tmpDocType=-1;
+ current->doc+="\n\n";
+ lastDocContext = Curly;
+ BEGIN( Doc );
+ }
+ else
+ {
+ tmpDocType=Doc;
+ current->doc.resize(0);
+ current->brief.resize(0);
+ lastDocContext = YY_START;
+ BEGIN( JavaDoc );
+ }
+ }
+<FindMembers,FindFields,MemberSpec,FuncQual,Operator>"//!" {
+ current->brief.resize(0);
+ tmpDocType=-1;
+ lastDocContext = YY_START;
+ if (current_root->section & Entry::SCOPE_MASK)
+ current->inside = current_root->name+"::";
+ BEGIN( LineDoc );
+ }
+<FindMembers,FindFields,MemberSpec,FuncQual,Operator>"///"/[^/] {
+ current->brief.resize(0);
+ tmpDocType=-1;
+ lastDocContext = YY_START;
+ if (current_root->section & Entry::SCOPE_MASK)
+ current->inside = current_root->name+"::";
+ BEGIN( LineDoc );
+ }
+<FindMembers>"extern"{BN}+"\"C"("++")?"\""{BN}+("{")?
+<FindMembers>"{" {
+ current->type.resize(0);
+ current->name.resize(0);
+ current->args.resize(0);
+ current->argList->clear();
+ bracketCount=0;
+ BEGIN( SkipBlock );
+
+ }
+<JavaDoc>"@short"{B}+ {
+ lastBriefContext=Doc;
+ BEGIN( ClassDocBrief );
+ }
+<JavaDoc>^(({B}*"*"+)?){BL} {
+ lineCount();
+ if (!current->brief.stripWhiteSpace().isEmpty())
+ {
+ BEGIN( tmpDocType );
+ }
+ }
+<JavaDoc>"@" {
+ unput(*yytext);
+ BEGIN(Doc);
+ }
+<JavaDoc>^{B}*"*"+/[^/] {
+ //printf("---> removing %s\n",yytext);
+ }
+ /*
+<JavaDoc>[^\n\@\*\.\\]+ {
+ current->brief+=yytext;
+ }
+ */
+<JavaDoc>. {
+ //printf("---> copy %c\n",*yytext);
+ current->brief+=*yytext;
+ }
+<JavaDoc>\n {
+ current->brief+=' ';
+ lineCount();
+ }
+<JavaDoc>"."[ \t\r\n] {
+ lineCount();
+ current->brief+=".";
+ BEGIN( tmpDocType );
+ }
+<JavaDoc>("\\"|"@")"internal" {
+ current->doc+="\\internal";
+ BEGIN( tmpDocType );
+ }
+<Doc,JavaDoc>{B}*("\\"|"@")("fn"|"var"|"typedef"){B}* {
+ current->section = Entry::MEMBERDOC_SEC;
+ current->fileName = yyFileName;
+ current->startLine = yyLineNr;
+ BEGIN( ClassDocFunc );
+ }
+<LineDoc,Doc,JavaDoc>{B}*("\\"|"@")"def"{B}* {
+ nextDefContext = YY_START==LineDoc ? DefLineDoc : ClassDoc;
+ current->section = Entry::DEFINEDOC_SEC;
+ current->fileName = yyFileName;
+ current->startLine = yyLineNr;
+ BEGIN( ClassDocDefine );
+ }
+<Doc,JavaDoc>{B}*("\\"|"@")"overload"{B}* {
+ BEGIN( ClassDocOverload );
+ }
+<ClassDocOverload>{B}*"\n" {
+ QString orgDoc = current->doc;
+ current->doc = getOverloadDocs();
+ current->doc += "\n\n";
+ current->doc += orgDoc;
+ yyLineNr++;
+ BEGIN( Doc );
+ }
+<ClassDocOverload>. { unput(*yytext);
+ current->section = Entry::OVERLOADDOC_SEC;
+ current->fileName = yyFileName;
+ current->startLine = yyLineNr;
+ BEGIN( ClassDocFunc );
+ }
+<Doc,JavaDoc>{B}*("\\"|"@")"enum"{B}* {
+ current->section = Entry::ENUMDOC_SEC;
+ current->fileName = yyFileName;
+ current->startLine = yyLineNr;
+ BEGIN( EnumDocArg1 );
+ }
+<Doc,JavaDoc>{B}*("\\"|"@")"defgroup"{B}* {
+ current->section = Entry::GROUPDOC_SEC;
+ current->fileName = yyFileName;
+ current->startLine = yyLineNr;
+ BEGIN( GroupDocArg1 );
+ }
+<Doc,JavaDoc>{B}*("\\"|"@")"namespace"{B}* {
+ current->section = Entry::NAMESPACEDOC_SEC;
+ current->fileName = yyFileName;
+ current->startLine = yyLineNr;
+ BEGIN( NameSpaceDocArg1 );
+ }
+<Doc,JavaDoc>{B}*("\\"|"@")"class"{B}* {
+ current->section = Entry::CLASSDOC_SEC;
+ current->fileName = yyFileName;
+ current->startLine = yyLineNr;
+ BEGIN( ClassDocArg1 );
+ }
+<Doc,JavaDoc>{B}*("\\"|"@")"union"{B}* {
+ current->section = Entry::UNIONDOC_SEC;
+ current->fileName = yyFileName;
+ current->startLine = yyLineNr;
+ BEGIN( ClassDocArg1 );
+ }
+<Doc,JavaDoc>{B}*("\\"|"@")"struct"{B}* {
+ current->section = Entry::STRUCTDOC_SEC;
+ current->fileName = yyFileName;
+ current->startLine = yyLineNr;
+ BEGIN( ClassDocArg1 );
+ }
+<Doc,JavaDoc>{B}*("\\"|"@")"page"{B}* {
+ current->section = Entry::PAGEDOC_SEC;
+ current->fileName = yyFileName;
+ current->startLine = yyLineNr;
+ BEGIN( PageDocArg1 );
+ }
+<Doc,JavaDoc>{B}*("\\"|"@")"file"{B}* {
+ current->section = Entry::FILEDOC_SEC;
+ current->fileName = yyFileName;
+ current->startLine = yyLineNr;
+ BEGIN( FileDocArg1 );
+ }
+<Doc,JavaDoc>{B}*("\\"|"@")"example"{B}* {
+ current->section = Entry::EXAMPLE_SEC;
+ current->fileName = yyFileName;
+ current->startLine = yyLineNr;
+ BEGIN( ExampleDocArg1 );
+ }
+<ExampleDocArg1>{FILE} {
+ current->name = stripQuotes(yytext);
+ BEGIN( ExampleDoc );
+ }
+<ClassDoc,Doc,JavaDoc>{B}*("\\"|"@")"relate"[sd]{B}* {
+ lastDocRelContext = YY_START;
+ BEGIN( ClassDocRelates );
+ }
+<ClassDocRelates>{ID} {
+ current->relates = yytext;
+ BEGIN( lastDocRelContext );
+ }
+<NameSpaceDocArg1>{SCOPENAME} {
+ current->name = yytext;
+ newDocState();
+ }
+<NameSpaceDocArg1>"\n" {
+ warn("Warning: missing argument after "
+ "\\namespace at line %d of %s.\n",yyLineNr,yyFileName);
+ yyLineNr++;
+ }
+<ClassDocArg1>{SCOPENAME} {
+ current->name = yytext;
+ // prepend outer scope name
+ if (current_root->section & Entry::SCOPE_MASK)
+ {
+ current->name.prepend(current_root->name+"::");
+ }
+ BEGIN( ClassDocArg2 );
+ }
+<ClassDocArg1>"\n" {
+ warn("Warning: missing argument after "
+ "\\class at line %d of %s.\n",yyLineNr,yyFileName);
+ yyLineNr++;
+
+ }
+<GroupDocArg1>{ID}(".html"?) {
+ current->name = yytext;
+ if (current->name.right(5)==".html")
+ current->name=current->name.left(current->name.length()-5);
+ BEGIN(GroupDocArg2);
+ }
+<GroupDocArg1>"\n" {
+ warn("Warning: missing argument after "
+ "\\defgroup at line %d of %s.\n",yyLineNr,yyFileName);
+ yyLineNr++;
+ BEGIN( Doc );
+ }
+<GroupDocArg2>.* {
+ current->type = yytext;
+ current->type = current->type.stripWhiteSpace();
+ newDocState();
+ }
+<GroupDocArg2>"\n" {
+ newDocState();
+ }
+<ClassDocArg2>{FILE} {
+ //printf("ClassDocArg2=%s\n",yytext);
+ current->includeFile = stripQuotes(yytext);
+ BEGIN( ClassDocArg3 );
+ }
+<ClassDocArg2>{BL} { yyLineNr++;
+ newDocState();
+ }
+<ClassDocArg3>{FILE} {
+ //printf("ClassDocArg3=%s\n",yytext);
+ current->includeName = stripQuotes(yytext);
+ newDocState();
+ }
+<ClassDocArg3>{BL} { yyLineNr++;
+ newDocState();
+ }
+<FileDocArg1>{FILE} {
+ current->name = stripQuotes(yytext);
+ newDocState();
+ }
+<FileDocArg1>"\n" {
+ //warn("Warning: missing argument after "
+ // "\\file at line %d of %s.\n",yyLineNr,yyFileName);
+ current->name = yyFileName;
+ yyLineNr++;
+ newDocState();
+ }
+<PageDocArg1>{FILE} {
+ current->name = stripQuotes(yytext);
+ BEGIN( PageDocArg2 );
+ }
+<PageDocArg1>"\n" {
+ warn("Warning: missing argument after "
+ "\\page at line %d of %s.\n",yyLineNr,yyFileName);
+ yyLineNr++;
+ BEGIN( Doc );
+ }
+<PageDocArg2>.*"\n" {
+ yyLineNr++;
+ current->args = yytext;
+ BEGIN( PageDoc );
+ }
+<EnumDocArg1>{SCOPEID} {
+ current->name = yytext;
+ if (current_root->section & Entry::SCOPE_MASK)
+ {
+ current->name.prepend(current_root->name+"::");
+ }
+ newDocState();
+ }
+<EnumDocArg1>"\n" {
+ warn("Warning: missing argument after "
+ "\\enum at line %d of %s.\n",yyLineNr,yyFileName);
+ yyLineNr++;
+ BEGIN( Doc );
+ }
+<PageDoc>"\\refitem".*"\n" {
+ current->doc+=yytext;
+ }
+<PageDoc>("\\"|"@")"section"{B}+ {
+ isSubsection=FALSE;
+ BEGIN(SectionLabel);
+ }
+<PageDoc>("\\"|"@")"subsection"{B}+ {
+ isSubsection=TRUE;
+ BEGIN(SectionLabel);
+ }
+<Doc,PageDoc,JavaDoc,ClassDoc>"\\\\verbatim"/[^a-z_A-Z0-9] {
+ current->doc+="\\\\verbatim";
+ }
+<Doc,PageDoc,JavaDoc,ClassDoc>("\\"|"@")"verbatim"/[^a-z_A-Z0-9] {
+ lastVerbState=YY_START;
+ current->doc+="\\verbatim";
+ BEGIN(SkipVerbatim);
+ }
+<Doc,PageDoc,JavaDoc,ClassDoc>"\\\\code"/[^a-z_A-Z0-9] {
+ current->doc+="\\\\code";
+ }
+<Doc,PageDoc,JavaDoc,ClassDoc>("\\"|"@")"code"/[^a-z_A-Z0-9] {
+ lastCodeState=YY_START;
+ current->doc+="\\code";
+ BEGIN(SkipCode);
+ }
+<Doc,PageDoc,JavaDoc,ClassDoc>"<"{PRE}{ATTR}">" {
+ lastCodeState=YY_START;
+ current->doc+="<PRE>";
+ BEGIN(SkipCode);
+ }
+<SkipVerbatim>("\\"|"@")"endverbatim"/[^a-z_A-Z0-9] {
+ current->doc+=yytext;
+ BEGIN(lastVerbState);
+ }
+<SkipVerbatim>[^ \t\/\\\n]* {
+ current->doc+=yytext;
+ }
+<SkipVerbatim>^"//" {
+ if (!removeSlashes)
+ current->doc+=yytext;
+ }
+ /*
+<SkipVerbatim>^"//"({B}*"*"+)? {
+ if (!removeSlashes)
+ current->doc+=yytext;
+ }
+<SkipVerbatim>^{B}*"*"+
+ */
+<SkipVerbatim>"//"|"/*" {
+ current->doc+=yytext;
+ }
+<SkipVerbatim>"\n" {
+ yyLineNr++;
+ current->doc+=*yytext;
+ }
+<SkipVerbatim>. {
+ current->doc+=*yytext;
+ }
+<SkipCode>("\\"|"@")"endcode" {
+ current->doc+="\\endcode";
+ BEGIN(lastCodeState);
+ }
+<SkipCode>"</"{PRE}{ATTR}">" {
+ current->doc+="</PRE>";
+ BEGIN(lastCodeState);
+ }
+<SkipCode>^"//"({B}*"*"+)? {
+ if (!removeSlashes)
+ current->doc+=yytext;
+ }
+<SkipCode>^{B}*"*"+
+<SkipCode>"//" {
+ current->doc+=yytext;
+ }
+<SkipCode>[^ \*\t\/\\\n]+ {
+ current->doc+=yytext;
+ }
+<SkipCode>\n {
+ yyLineNr++;
+ current->doc+=*yytext;
+ }
+<SkipCode>. {
+ current->doc+=*yytext;
+ }
+<SectionLabel>[a-z_A-Z0-9]+ {
+ sectionLabel=yytext;
+ sectionTitle.resize(0);
+ BEGIN(SectionTitle);
+ }
+<SectionTitle>[^\n*]*/"\n" {
+ sectionTitle+=yytext;
+ sectionTitle=sectionTitle.stripWhiteSpace();
+ addSection();
+ current->doc += "\\section "+sectionLabel+"\n";
+ BEGIN(PageDoc);
+ }
+<SectionTitle>"*" {
+ sectionTitle+=yytext;
+ }
+<ExampleDoc,PageDoc,ClassDoc>"\n" { yyLineNr++ ; current->doc+=yytext; }
+<ExampleDoc,PageDoc,ClassDoc>[a-z_A-Z0-9 \t]+ { current->doc += yytext; }
+<ExampleDoc,PageDoc,ClassDoc>. { current->doc += yytext; }
+<Doc,JavaDoc,LineDoc,ExampleDoc,PageDoc,ClassDoc>^{B}*"//"
+<Doc,JavaDoc,LineDoc,ExampleDoc,PageDoc,ClassDoc>"//" { current->doc += yytext; }
+<Doc,JavaDoc,LineDoc,ExampleDoc,ClassDocBrief,PageDoc,ClassDoc>"\\\\f"[$\[\]] {
+ current->doc += &yytext[1];
+ }
+<Doc,JavaDoc,LineDoc,ExampleDoc,ClassDocBrief,PageDoc,ClassDoc>"\\f$" {
+ lastFormulaContext = YY_START;
+ formulaText="$";
+ BEGIN(ReadFormulaShort);
+ }
+<Doc,JavaDoc,LineDoc,ExampleDoc,ClassDocBrief,PageDoc,ClassDoc>"\\f[" {
+ lastFormulaContext = YY_START;
+ formulaText="\\[";
+ BEGIN(ReadFormulaLong);
+ }
+<ReadFormulaShort>"\\f$" {
+ formulaText+="$";
+ if (lastFormulaContext==ClassDocBrief)
+ current->brief += addFormula();
+ else
+ current->doc += addFormula();
+ BEGIN(lastFormulaContext);
+ }
+<ReadFormulaLong>"\\f]" {
+ formulaText+="\\]";
+ if (lastFormulaContext==ClassDocBrief)
+ current->brief += addFormula();
+ else
+ current->doc += addFormula();
+ BEGIN(lastFormulaContext);
+ }
+<ReadFormulaLong,ReadFormulaShort>. { formulaText+=*yytext; }
+<ExampleDoc,PageDoc,ClassDocBrief,ClassDoc>"*/" {
+ if (YY_START==ClassDocBrief &&
+ lastBriefContext==Doc)
+ {
+ current->doc += "\n\n";
+ BEGIN( lastDocContext );
+ }
+ else
+ {
+ current->doc += "\n\n";
+ //printf("Add docs for class %s\n",current->name.data());
+ current_root->addSubEntry(current);
+ current = new Entry ;
+ current->protection = protection ;
+ current->sig = sig;
+ current->virt = virt;
+ current->stat = gstat;
+ current->slot = slot;
+ }
+ BEGIN( FindMembers );
+ }
+<PageDoc>"<"{TITLE}">" {
+ current->args.resize(0);
+ current->argList->clear();
+ BEGIN( PageDocTitle);
+ }
+<PageDocTitle>\n { yyLineNr++; current->args+=" "; }
+<PageDocTitle>[^\n\<] { current->args+=yytext; }
+<PageDocTitle>"</"{TITLE}">" { BEGIN( PageDoc ); }
+<ClassDoc,Doc,JavaDoc>("\\"|"@")"ingroup"{B}+ {
+ lastGroupContext = YY_START;
+ lineCount();
+ BEGIN( GroupName );
+ }
+<GroupName>{ID} {
+ current->groups->append(
+ new QString(yytext)
+ );
+ }
+<GroupName>\n {
+ yyLineNr++; BEGIN( lastGroupContext );
+ }
+<ClassDoc,Doc>{B}*("\\brief"|"@short") {
+ lastBriefContext=YY_START;
+ BEGIN( ClassDocBrief );
+ }
+<ClassDoc>{B}*"\\inherit"{B}+ { BEGIN( DocBaseClass ); }
+<DocBaseClass>{ID} {
+ //printf("Adding base class %s\n",yytext);
+ current->extends->append(
+ new BaseInfo(yytext,Public,Normal)
+ );
+ }
+<DocBaseClass>\n { yyLineNr++; BEGIN( ClassDoc ); }
+<ClassDocBrief>{BS}{BL} {
+ current->brief=current->brief.stripWhiteSpace();
+ yyLineNr++;
+ BEGIN( lastBriefContext );
+ }
+<ClassDocBrief>"\n" { yyLineNr++ ; current->brief += " "; }
+<ClassDocBrief>"<"{BR}{ATTR}">"
+<ClassDocBrief>{BS}/("\\"|"@")"ingroup" {
+ current->brief=current->brief.stripWhiteSpace();
+ BEGIN( lastBriefContext );
+ }
+<ClassDocBrief>{BS}/("\\"|"@")"author" { BEGIN( lastBriefContext ); }
+<ClassDocBrief>{BS}/("\\"|"@")"internal" { BEGIN( lastBriefContext ); }
+<ClassDocBrief>{BS}/("\\"|"@")"version" { BEGIN( lastBriefContext ); }
+<ClassDocBrief>{BS}/"\\date" { BEGIN( lastBriefContext ); }
+<ClassDocBrief>{BS}/("\\"|"@")"param" { BEGIN( lastBriefContext ); }
+<ClassDocBrief>{BS}/("\\"|"@")"exception" { BEGIN( lastBriefContext ); }
+<ClassDocBrief>{BS}/("\\"|"@")"return" { BEGIN( lastBriefContext ); }
+<ClassDocBrief>{BS}/("\\sa"|"@see") { BEGIN( lastBriefContext ); }
+<ClassDocBrief>{BS}/("\\"|"@")"bug" { BEGIN( lastBriefContext ); }
+<ClassDocBrief>{BS}/("\\"|"@")"warning" { BEGIN( lastBriefContext ); }
+<ClassDocBrief>{BS}/("\\"|"@")"par"{BN}+ { BEGIN( lastBriefContext ); }
+<ClassDocBrief>{BS}/("\\brief"|"@short"){BN}+ {
+ lastBriefContext=YY_START;
+ BEGIN( ClassDocBrief );
+ }
+<ClassDocBrief>. { current->brief += *yytext; }
+<ClassDocDefine>{ID}/"(" {
+ current->name = yytext;
+ BEGIN( ClassDefineArgs );
+ }
+<ClassDocDefine>{ID} {
+ current->name = yytext;
+ if (nextDefContext==ClassDoc)
+ newDocState();
+ else
+ BEGIN( nextDefContext );
+ }
+<ClassDefineArgs>")" {
+ current->args+=")";
+ if (nextDefContext==ClassDoc)
+ newDocState();
+ else
+ BEGIN( nextDefContext );
+ }
+<ClassDefineArgs>. {
+ current->args+= yytext;
+ }
+<ClassDocFunc>"\n" {
+ yyLineNr++;
+ current->name = current->name.stripWhiteSpace();
+ if (current->section == Entry::MEMBERDOC_SEC && current->args.length()==0)
+ current->section = Entry::VARIABLEDOC_SEC;
+ newDocState();
+ }
+<ClassDocFunc>"(" {
+ current->args+=*yytext;
+ currentArgumentContext = ClassDocFuncQual;
+ copyArgString=&current->args;
+ BEGIN( ReadFuncArgType ) ;
+ }
+<ClassDocFunc>"("({B}*"*")+ {
+ current->name+="(*";
+ BEGIN( ClassDocFuncPtr );
+ }
+<ClassDocFuncPtr>{SCOPENAME} {
+ current->name+=yytext;
+ }
+<ClassDocFuncPtr>")" {
+ current->name+=')';
+ BEGIN( ClassDocFunc );
+ }
+<ClassDocFuncQual>{B}*"const"{B}* {
+ current->args += " const ";
+ current->argList->constSpecifier=TRUE;
+ }
+<ClassDocFuncQual>{B}*"volatile"{B}* {
+ current->args += " volatile ";
+ current->argList->volatileSpecifier=TRUE;
+ }
+<ClassDocFuncQual>{B}*"="{B}*"0"{B}* {
+ current->args += " = 0";
+ current->virt = Pure;
+ current->argList->pureSpecifier=TRUE;
+ }
+<ClassDocFuncQual>"throw"{B}*"(" {
+ current->exception = "throw(";
+ BEGIN(ClassDocFuncExc);
+ }
+<ClassDocFuncExc>")" {
+ current->exception += ')';
+ BEGIN(ClassDocFuncQual);
+ }
+<ClassDocFuncExc>. {
+ current->exception += *yytext;
+ }
+<ClassDocFunc,ClassDocFuncQual>. {
+ current->name += *yytext;
+ }
+<ClassDocFuncQual>"\n" {
+ yyLineNr++;
+ current->name = current->name.stripWhiteSpace();
+ newDocState();
+ }
+<Doc>. { current->doc += *yytext; }
+<DefLineDoc,LineDoc>. { current->brief += *yytext; }
+<Doc>\n { yyLineNr++; current->doc += *yytext; }
+<LineDoc>\n {
+ yyLineNr++;
+ BEGIN( lastDocContext );
+ }
+<DefLineDoc>\n {
+ yyLineNr++;
+ unput('/');unput('*');
+ BEGIN( ClassDoc );
+ }
+
+<AfterDocLine>"/*"|"//" { current->brief+=yytext; }
+<AfterDocLine>\n {
+ if (afterDocTerminator!=0)
+ unput(afterDocTerminator);
+ BEGIN(lastAfterDocContext);
+ }
+<AfterDocLine>. { current->brief+=yytext; }
+<AfterDocBrief>"/*"|"//" { current->brief+=yytext; }
+<AfterDocBrief>^{B}*"*"+/[^/\n]
+<AfterDocBrief>\n { current->brief+=yytext; yyLineNr++; }
+<AfterDocBrief>. { current->brief+=*yytext; }
+<AfterDocBrief>^{B}*"*"/[^/\n]{BL} { yyLineNr++;
+ if (!current->brief.stripWhiteSpace().isEmpty())
+ BEGIN(AfterDoc);
+ }
+<AfterDocBrief>"*/" {
+ if (afterDocTerminator!=0)
+ unput(afterDocTerminator);
+ BEGIN(lastAfterDocContext);
+ }
+<AfterDocBrief>"."/{BN} { BEGIN(AfterDoc); }
+<AfterDoc>("\\"|"@")"brief" { BEGIN(AfterDocBrief); }
+<AfterDoc>"/*"|"//" { current->doc+=yytext; }
+<AfterDoc>^{B}*"*"+/[^/]
+<AfterDoc>\n { current->doc+=yytext; yyLineNr++; }
+<AfterDoc>. { current->doc+=*yytext; }
+<AfterDoc>"*/" {
+ if (afterDocTerminator!=0)
+ unput(afterDocTerminator);
+ BEGIN(lastAfterDocContext);
+ }
+<ClassDocRelates,ClassDocFunc,ClassDocDefine,GroupDocArg1,ClassDocArg1,SectionTitle,EnumDocArg1,FileDocArg1,PageDocArg1,ExampleDocArg1,ClassDefineArgs>"*/" {
+ current->doc += "\n\n";
+ err("Warning: unexpected end of "
+ "documentation block found in "
+ "file %s at line %d\n",yyFileName,yyLineNr);
+ BEGIN( lastDocContext );
+ }
+<Doc>"*/" {
+ current->doc += "\n\n";
+ BEGIN( lastDocContext );
+ }
+<JavaDoc>"*/" {
+ unput('/');unput('*');
+ BEGIN( tmpDocType );
+ }
+<Doc,JavaDoc,ClassDoc,PageDoc,ExampleDoc,ReadFormulaShort,ReadFormulaLong,ClassDocBrief>^{B}*(("//"{B}*)?)"*"+/[^/]
+<DefLineDoc,LineDoc,ClassDoc,Doc>"/*" { current->doc += yytext; }
+
+<SkipCxxComment>.*\n { yyLineNr++ ;
+ BEGIN( lastCContext ) ;
+ }
+<*>.
+<*>\n { yyLineNr++ ; }
+<SkipComment>"//"|"/*"
+<*>"/*" { lastCContext = YY_START ;
+ BEGIN( SkipComment ) ;
+ }
+<SkipComment>{B}*"*/" { BEGIN( lastCContext ) ; }
+<*>"//" {
+ lastCContext = YY_START ;
+ BEGIN( SkipCxxComment ) ;
+ }
+%%
+
+//----------------------------------------------------------------------------
+
+void scanString(const char *s)
+{
+ const char *oldInputString = inputString;
+ int oldInputPosition = inputPosition;
+ YY_BUFFER_STATE oldBuffer = YY_CURRENT_BUFFER;
+ yy_switch_to_buffer(yy_create_buffer(scanYYin, YY_BUF_SIZE));
+ inputString = s;
+ inputPosition = 0;
+ scanYYlex();
+ yy_delete_buffer(YY_CURRENT_BUFFER);
+ yy_switch_to_buffer(oldBuffer);
+ inputString = oldInputString;
+ inputPosition = oldInputPosition;
+}
+
+//----------------------------------------------------------------------------
+
+static void newDocState()
+{
+ if (tmpDocType!=-1)
+ {
+ tmpDocType=ClassDoc;
+ BEGIN(JavaDoc);
+ }
+ else
+ {
+ BEGIN(ClassDoc);
+ }
+}
+
+//----------------------------------------------------------------------------
+
+void parseCompounds(Entry *rt)
+{
+ //printf("parseCompounds(%s)\n",rt->name.data());
+ EntryListIterator eli(*rt->sublist);
+ Entry *ce;
+ for (;(ce=eli.current());++eli)
+ {
+ if (ce->program.length()>0)
+ {
+ //printf("-- %s ---------\n%s\n---------------\n",
+ // ce->name.data(),ce->program.data());
+ // init scanner state
+ inputString = ce->program;
+ inputPosition = 0;
+ scanYYrestart( scanYYin ) ;
+ if (ce->section==Entry::ENUM_SEC)
+ BEGIN( FindFields ) ;
+ else
+ BEGIN( FindMembers ) ;
+ current_root = ce ;
+ strcpy( yyFileName, ce->fileName ) ;
+ yyLineNr = ce->startLine ;
+ //current->reset();
+ current = new Entry;
+ // set default protection based on the compound type
+ if( ce->section==Entry::CLASS_SEC ) // class
+ current->protection = protection = Private ;
+ else if (ce->section == Entry::ENUM_SEC ) // enum
+ current->protection = protection = ce->protection;
+ else if (ce->name.length()>0 && ce->name.at(0)=='@') // anonymous union
+ current->protection = protection = ce->protection;
+ else // named struct or union
+ current->protection = protection = Public ;
+ sig = FALSE;
+ slot = FALSE;
+ gstat = FALSE;
+ virt = Normal;
+ scanYYlex() ;
+ delete current;
+ ce->program.resize(0);
+ }
+ parseCompounds(ce);
+ }
+}
+
+//----------------------------------------------------------------------------
+
+void parseMain(Entry *rt)
+{
+ initParser();
+ anonCount = 0;
+ protection = Public;
+ sig = FALSE;
+ slot = FALSE;
+ gstat = FALSE;
+ virt = Normal;
+ current_root = rt;
+ global_root = rt;
+ current = new Entry;
+ inputString = rt->program;
+ inputPosition = 0;
+ ifCount=0;
+ scanYYrestart( scanYYin );
+ BEGIN( FindMembers );
+ scanYYlex();
+ rt->program.resize(0);
+ delete current;
+ parseCompounds(rt);
+}
+
+//----------------------------------------------------------------------------
+
+void parseDocument(OutputList &ol,const QString &docString)
+{
+ //inParamBlock=inSeeBlock=inReturnBlock=FALSE;
+ curTable = 0;
+ outDoc = new OutputList(&ol);
+ currentIncludeFile.resize(0);
+ includeFileOffset=0;
+ includeFileLength=0;
+ if (!docString) return;
+ linkRef = "";
+ linkText = "";
+ inputString = docString;
+ inputPosition = 0;
+ scanYYrestart( scanYYin );
+ BEGIN( DocScan );
+ insideArgumentList = FALSE;
+ scanYYlex();
+ if (insideArgumentList) { insideArgumentList=FALSE; outDoc->endItemList(); }
+ if (inBlock()) endBlock();
+ ol+=*outDoc;
+ delete outDoc;
+ return;
+}
+
+//----------------------------------------------------------------------------
+
+void parseDoc(OutputList &ol,const char *clName,
+ const char *memName,const QString &docString)
+{
+ initParser();
+ initParseCodeContext();
+ exampleDoc=FALSE; // do not cross reference with member docs
+ className=clName;
+ memberName=memName;
+ if (memName)
+ {
+ refName=className+"::"+memberName;
+ }
+ else
+ {
+ refName=className;
+ }
+ parseDocument(ol,docString);
+}
+
+//----------------------------------------------------------------------------
+
+void parseExample(OutputList &ol,const QString &docString,
+ const char *fileName)
+{
+ initParser();
+ initParseCodeContext();
+ exampleDoc=TRUE; // cross reference with member docs
+ exampleName=fileName;
+ parseDocument(ol,docString);
+}
+
+//----------------------------------------------------------------------------
+
+extern "C" { // some sillyness to keep the compiler happy
+int scanYYwrap() { return 1 ; }
+void bogus() { yy_flex_realloc(0,0); }
+}
+
diff --git a/src/searchindex.cpp b/src/searchindex.cpp
new file mode 100644
index 0000000..241d0a8
--- /dev/null
+++ b/src/searchindex.cpp
@@ -0,0 +1,124 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#include "searchindex.h"
+#include "suffixtree.h"
+
+SearchIndex::SearchIndex() : refDict(10007), nameIndex(10007)
+{
+ indexCount=1;
+ //indexTree = new IndexTree;
+ suffixTree = new SuffixTree;
+}
+
+SearchIndex::~SearchIndex()
+{
+ //delete indexTree;
+ delete suffixTree;
+}
+
+void SearchIndex::addReference(const char *key,const char *ref)
+{
+ DocRef *dr=new DocRef(indexCount,key,ref);
+ nameIndex.insert(indexCount,dr);
+ refList.append(dr);
+ refDict.insert(key,dr);
+ indexCount++;
+}
+
+bool SearchIndex::addWord(const char *key,const char *word,bool special)
+{
+ DocRef *dr=0;
+ if (word && key && strlen(key)>0 && (dr=refDict[key]))
+ {
+ suffixTree->insertWord(((QString)word).lower(),dr->index(),special);
+ return TRUE;
+ }
+ else if (word)
+ {
+ printf("SearchIndex::addWord() key `%s' not found!\n",key);
+ return FALSE;
+ }
+ else
+ {
+ printf("SearchIndex::addWord() trying to insert word with length 0\n");
+ return FALSE;
+ }
+}
+
+bool SearchIndex::saveIndex(const char *fileName)
+{
+ QFile f(fileName);
+ if (!f.open(IO_WriteOnly)) return FALSE;
+
+ // write header
+ if (f.writeBlock("DOXI",4)!=4) return FALSE; // write header
+
+ // compute forward offsets for all children of each node.
+ suffixTree->resolveForwardReferences();
+
+ // compute offset to the reference index table
+ int offset=suffixTree->size()+9;
+
+ // write the offset
+ if (writeNumber(f,offset)) return FALSE;
+
+ // write the suffix tree
+ if (!suffixTree->write(f)) return FALSE;
+
+ f.putch(0);
+
+ // write the index reference table
+ DocRef *dr=refList.first();
+ offset+=refList.count()*4;
+ while (dr)
+ {
+ writeNumber(f,offset);
+ offset+=strlen(dr->name())+strlen(dr->url())+2;
+ dr=refList.next();
+ }
+
+ // write the references
+ dr=refList.first();
+ while (dr)
+ {
+ writeString(f,dr->name());
+ writeString(f,dr->url());
+ dr=refList.next();
+ }
+
+ //printf("Building index tree\n");
+ printf("Size of the suffix tree is %d bytes\n",suffixTree->size());
+ printf("Number of tree nodes is %d\n",suffixTree->numberOfNodes());
+ printf("Number of links %d\n",indexCount);
+ //suffixTree->buildIndex();
+ //printf("Computing reference offsets\n");
+ //int offset=suffixTree->size()+8;
+ //indexTree->setOffsets(&nameIndex);
+ //printf("Saving suffix tree\n");
+ //printf("Saving index tree\n");
+ //result&=indexTree->write(f);
+ //printf("Saving reference list\n");
+ //dr=refList.first();
+ //while (dr)
+ //{
+ // result&=!writeString(f,dr->name());
+ // result&=!writeString(f,dr->url());
+ // dr=refList.next();
+ //}
+ //suffixTree->dump();
+ return TRUE;
+}
diff --git a/src/searchindex.h b/src/searchindex.h
new file mode 100644
index 0000000..64071fb
--- /dev/null
+++ b/src/searchindex.h
@@ -0,0 +1,71 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#ifndef _SEARCHINDEX_H
+#define _SEARCHINDEX_H
+
+#include <qintdict.h>
+#include <qstring.h>
+#include <qlist.h>
+#include <qdict.h>
+
+#include "suffixtree.h"
+
+//class IndexTree;
+class SuffixTree;
+
+class DocRef
+{
+ public:
+ DocRef(int index,const char *name,const char *url)
+ { i=index; n=name; u=url; }
+ ~DocRef() {}
+ void setOffset(int offset) { o=offset; }
+ const char *name() const { return n; }
+ const char *url() const { return u; }
+ int index() const { return i; }
+ int offset() const { return o; }
+
+ private:
+ QString n;
+ QString u;
+ int i;
+ int o;
+};
+
+typedef QList<DocRef> DocRefList;
+typedef QDict<DocRef> DocRefDict;
+
+class SearchIndex
+{
+ public:
+ SearchIndex();
+ ~SearchIndex();
+ void addReference(const char *key,const char *ref);
+ bool addWord(const char *key,const char *word,bool special);
+ bool saveIndex(const char *fileName);
+ void dump() { suffixTree->dump(); }
+
+ private:
+ //IndexTree *indexTree;
+ SuffixTree *suffixTree;
+ DocRefList refList;
+ DocRefDict refDict;
+ QIntDict<DocRef> nameIndex;
+ int indexCount;
+};
+
+#endif
diff --git a/src/suffixtree.cpp b/src/suffixtree.cpp
new file mode 100644
index 0000000..604531f
--- /dev/null
+++ b/src/suffixtree.cpp
@@ -0,0 +1,355 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#include <stdio.h>
+#include "suffixtree.h"
+
+#define MAXWORDLEN 1024
+
+//----------------------------------------------------------------------------
+
+bool writeString(QFile &f,const char *s)
+{
+ int len=strlen(s)+1;
+ return (f.writeBlock(s,len)!=len);
+}
+
+bool writeNumber(QFile &f,int num)
+{
+ return (f.putch((num>>24)&0xff)==-1) ||
+ (f.putch((num>>16)&0xff)==-1) ||
+ (f.putch((num>>8)&0xff)==-1) ||
+ (f.putch(num&0xff)==-1);
+}
+
+bool writeEncodedNumber(QFile &f,uint number)
+{
+ bool error=FALSE;
+ uint n=number;
+ while (n>=128)
+ {
+ int frac=n&0x7f;
+ error = error || (f.putch(frac|0x80)==-1);
+ n>>=7;
+ }
+ error = error || (f.putch(n)==-1);
+ return error;
+}
+
+int encodedNumberSize(uint number)
+{
+ uint n=number;
+ int size=1;
+ while (n>=128) { size++; n>>=7; }
+ return size;
+}
+
+//----------------------------------------------------------------------------
+
+int SuffixNodeList::compareItems(GCI item1,GCI item2)
+{
+ SuffixNode *n1=(SuffixNode *)item1;
+ SuffixNode *n2=(SuffixNode *)item2;
+ return strcmp(n1->label,n2->label);
+}
+
+SuffixNode::SuffixNode(const char *lab) : references(0)
+{
+ children = new SuffixNodeList;
+ children->setAutoDelete(TRUE);
+ label=lab;
+ totalFreq=0;
+ branchOffset=0;
+}
+
+SuffixNode::~SuffixNode()
+{
+ delete children;
+}
+
+void SuffixNode::addReference(int refId,int inName,int fullWord)
+{
+ totalFreq++;
+ uint s=references.size();
+ if (s>0 && references.at(s-1).id==refId) // word occured in the same document
+ {
+ references.at(s-1).freq++; // increase word's frequency
+ references.at(s-1).flags=((references.at(s-1).flags & INNAME_MASK)
+ | (inName<<INNAME_BIT))
+ +((references.at(s-1).flags & FULLWORD_MASK)
+ | (fullWord<<FULLWORD_BIT))
+ +((references.at(s-1).flags & WORDINNAME_MASK)
+ | ((inName & fullWord)<<WORDINNAME_BIT));
+ }
+ else
+ {
+ references.resize(s+1);
+ references.at(s).id=refId;
+ references.at(s).freq=1;
+ references.at(s).flags=(inName<<INNAME_BIT)
+ +(fullWord<<FULLWORD_BIT)
+ +((inName && fullWord)<<WORDINNAME_BIT);
+ }
+}
+
+int SuffixNode::insert(const char *word,int refId,int inName,int fullWord)
+{
+ int numNewNodes=0;
+ //printf("SuffixNode::insert(%s,%d)\n",word,refId);
+ SuffixNode *sn=children->first();
+ while (sn)
+ {
+ char *lab=sn->label.data();
+ char w=word[0],l=lab[0],i=0;
+ while (w!=0 && l!=0 && w==l) { i++; w=word[i]; l=lab[i]; }
+ if (w==0 && l==0) // match found
+ {
+ sn->addReference(refId,inName,fullWord);
+ return numNewNodes;
+ }
+ if (i>0) // w and l contain a common prefix of length i
+ {
+ if (l==0) // w!=0 => follow this branch
+ {
+ sn->addReference(refId,inName,FALSE);
+ numNewNodes+=sn->insert(&word[i],refId,inName,fullWord);
+ }
+ else // l!=0 => split branch
+ {
+ char leftlab[MAXWORDLEN];
+ memcpy(leftlab,lab,i);
+ leftlab[i]='\0';
+ SuffixNode *r = new SuffixNode(leftlab);
+ numNewNodes++;
+ SuffixNode *n2 = children->take();
+ // copy reference info
+ r->references = n2->references.copy();
+ int j,refSize = r->references.size();
+ for (j=0;j<refSize;j++)
+ {
+ //r->references[j].fullWord=FALSE;
+ //r->references[j].wordInName=FALSE;
+ r->references[j].flags &= ~(FULLWORD_MASK|WORDINNAME_MASK);
+ }
+ r->totalFreq = n2->totalFreq;
+ //printf("root branch `%s'\n",leftlab);
+ if (w!=0) // two sub branches
+ {
+ SuffixNode *n1 = new SuffixNode(&word[i]);
+ numNewNodes++;
+ n1->addReference(refId,inName,fullWord);
+ r->addReference(refId,inName,FALSE);
+ r->children->append(n1);
+ //printf("Right branch `%s'\n",&word[i]);
+ }
+ else // one sub branch
+ {
+ r->addReference(refId,inName,fullWord);
+ }
+ //printf("Left branch `%s'\n",&lab[i]);
+ n2->label=&lab[i];
+ r->children->append(n2);
+ children->append(r);
+ }
+ return numNewNodes;
+ }
+ sn=children->next();
+ }
+ //printf("new branch `%s'\n",word);
+ SuffixNode *n=new SuffixNode(word);
+ numNewNodes++;
+ n->addReference(refId,inName,fullWord);
+ children->append(n);
+ return numNewNodes;
+}
+
+void SuffixNode::dump(int level,const char *prefix)
+{
+ uint i;
+ if (references.size()>0)
+ {
+ printf("%s (level=%d offset=%d freq=%d) ",
+ prefix,level,branchOffset,totalFreq);
+ for (i=0;i<references.size();i++)
+ printf("%d->%d ",references.at(i).id,references.at(i).freq);
+ printf("\n");
+ }
+ SuffixNode *sn=children->first();
+ while (sn)
+ {
+ sn->dump(level+1,prefix+("-"+sn->label));
+ sn=children->next();
+ }
+}
+
+void SuffixNode::resolveForwardReferences(int &offset)
+{
+ if (children->count()>0)
+ {
+ if (label.length()>0) offset++; // terminator for the previous level
+ branchOffset=offset;
+ }
+ else
+ branchOffset=0;
+ SuffixNode *sn=children->first();
+ while (sn)
+ {
+ offset+=sn->label.length()+5;
+ uint i,refs=sn->references.size();
+ if (refs>0)
+ {
+ offset+=encodedNumberSize(sn->totalFreq);
+ offset+=encodedNumberSize((sn->references[0].id<<3)+
+ sn->references[0].flags);
+ offset+=encodedNumberSize(sn->references[0].freq);
+ for (i=1;i<refs;i++)
+ {
+ offset+=encodedNumberSize(
+ ((sn->references.at(i).id - sn->references.at(i-1).id)<<3)+
+ sn->references.at(i).flags);
+ offset+=encodedNumberSize(sn->references.at(i).freq);
+ }
+ offset+=encodedNumberSize(0);
+ }
+ //printf("Lab=%s offset=%d\n",sn->lab.data(),offset);
+ sn=children->next();
+ }
+ sn=children->first();
+ while (sn)
+ {
+ //printf("Lab=%s offset=%d\n",sn->lab.data(),offset);
+ sn->resolveForwardReferences(offset);
+ sn=children->next();
+ }
+}
+
+int SuffixNode::size()
+{
+ int s=0;
+ if (label.length()>0 && children->count()>0) s++; // for the terminator
+ SuffixNode *sn=children->first();
+ while (sn)
+ {
+ uint i,refs=sn->references.size();
+ s+=sn->size()+sn->label.length()+5;
+ if (refs>0)
+ {
+ s+=encodedNumberSize(sn->totalFreq);
+ s+=encodedNumberSize(
+ (sn->references[0].id<<3)+
+ sn->references[0].flags);
+ s+=encodedNumberSize(sn->references[0].freq);
+ for (i=1;i<refs;i++)
+ {
+ s+=encodedNumberSize(
+ ((sn->references.at(i).id - sn->references.at(i-1).id)<<3)+
+ sn->references.at(i).flags);
+ s+=encodedNumberSize(sn->references.at(i).freq);
+ }
+ s+=encodedNumberSize(0);
+ }
+ sn=children->next();
+ }
+ return s;
+}
+
+bool SuffixNode::write(QFile &f)
+{
+ bool error=FALSE;
+ if (children->count()>0 && label.length()>0) error=error || (f.putch(0)==-1);
+ SuffixNode *sn=children->first();
+ while (sn)
+ {
+ //offset+=sn->lab.length()+1+2*sizeof(int);
+ int i,refs=sn->references.size();
+ error=error || writeString(f,sn->label);
+ error=error || writeNumber(f,sn->branchOffset|((refs==0)?0x80000000:0));
+ if (refs>0)
+ {
+ error=error || writeEncodedNumber(f,sn->totalFreq);
+ error=error || writeEncodedNumber(f,
+ (sn->references[0].id<<3)+
+ sn->references[0].flags);
+ error=error || writeEncodedNumber(f,sn->references[0].freq);
+ for (i=1;i<refs;i++)
+ {
+ error=error || writeEncodedNumber(f,
+ ((sn->references[i].id - sn->references[i-1].id)<<3)+
+ sn->references[i].flags);
+ error=error || writeEncodedNumber(f,sn->references[i].freq);
+ }
+ error=error || writeEncodedNumber(f,0);
+ }
+ //printf("Lab=%s offset=%d\n",sn->lab.data(),offset);
+ sn=children->next();
+ }
+ sn=children->first();
+ while (sn)
+ {
+ error=error || sn->write(f);
+ sn=children->next();
+ }
+ return error;
+}
+
+//----------------------------------------------------------------------------
+
+SuffixTree::SuffixTree()
+{
+ root=new SuffixNode("");
+ nodes=1;
+}
+
+SuffixTree::~SuffixTree()
+{
+ delete root;
+}
+
+void SuffixTree::insertWord(const char *word,int index,bool inName)
+{
+ QString suffix=word;
+ uint i;
+ for (i=2;i<suffix.length()-1;i++)
+ {
+ //printf("Inserting suffix %s\n",suffix.right(i).data());
+ nodes+=root->insert(suffix.right(i),index,inName?1:0,FALSE);
+ }
+ nodes+=root->insert(word,index,inName?1:0,TRUE);
+}
+
+void SuffixTree::dump()
+{
+ root->dump(0,"");
+}
+
+void SuffixTree::resolveForwardReferences()
+{
+ int offset=8;
+ root->resolveForwardReferences(offset);
+}
+
+int SuffixTree::size()
+{
+ return root->size();
+}
+
+bool SuffixTree::write(QFile &f)
+{
+ if (!f.isOpen()) { printf("File not open\n"); return FALSE; }
+ bool error=FALSE;
+ error = error || root->write(f);
+ return !error;
+}
diff --git a/src/suffixtree.h b/src/suffixtree.h
new file mode 100644
index 0000000..381253c
--- /dev/null
+++ b/src/suffixtree.h
@@ -0,0 +1,93 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#ifndef SUFFIXTREE_H
+#define SUFFIXTREE_H
+
+#include <qlist.h>
+#include <qarray.h>
+#include <qstring.h>
+#include <qfile.h>
+
+class SuffixNodeList;
+class IndexTree;
+
+enum WordRefMasks { WORDINNAME_MASK=4, INNAME_MASK=2, FULLWORD_MASK=1 };
+enum WordRefBits { WORDINNAME_BIT=2, INNAME_BIT=1, FULLWORD_BIT=0 };
+
+// bool inName;
+// bool fullWord;
+// bool wordInName;
+
+struct WordRef
+{
+ int id;
+ short freq;
+ char flags;
+};
+
+class SuffixNode
+{
+ friend class SuffixTree;
+ friend class IndexNode;
+ friend class SuffixNodeList;
+ public:
+ SuffixNode(const char *);
+ ~SuffixNode();
+ int insert(const char *word,int refId,int inName,int full);
+ void addReference(int refId,int inName,int fullWord);
+ void dump(int,const char *);
+ void resolveForwardReferences(int &offset);
+ int size(); // return the size of the tree whose root is this node
+ bool write(QFile &f);
+ private:
+ SuffixNodeList *children;
+ QArray<WordRef> references;
+ QString label;
+ int branchOffset;
+ int totalFreq;
+};
+
+class SuffixNodeList : public QList<SuffixNode>
+{
+ public:
+ SuffixNodeList() : QList<SuffixNode>() {}
+ ~SuffixNodeList() {}
+ int compareItems(GCI item1,GCI item2);
+};
+
+class SuffixTree
+{
+ friend class SuffixNode;
+ public:
+ SuffixTree();
+ ~SuffixTree();
+ void insertWord(const char *word,int index,bool inName);
+ //void buildIndex();
+ void resolveForwardReferences();
+ void dump();
+ int size(); // return the size of the (flat) tree in bytes
+ bool write(QFile &f);
+ int numberOfNodes() { return nodes; }
+ private:
+ int nodes;
+ SuffixNode *root;
+};
+
+extern bool writeNumber(QFile &f,int);
+extern bool writeString(QFile &f,const char *s);
+
+#endif
diff --git a/src/tag.h b/src/tag.h
new file mode 100644
index 0000000..d301f4d
--- /dev/null
+++ b/src/tag.h
@@ -0,0 +1,22 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#ifndef TAG_H
+#define TAG_H
+
+extern void parseTagFile(const char *fileName);
+
+#endif
diff --git a/src/tag.l b/src/tag.l
new file mode 100644
index 0000000..edc5cf1
--- /dev/null
+++ b/src/tag.l
@@ -0,0 +1,243 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+%{
+
+/*
+ * includes
+ */
+#include <stdio.h>
+#include <qstring.h>
+#include <qfileinf.h>
+
+#include "classdef.h"
+#include "filedef.h"
+#include "memberdef.h"
+#include "doxygen.h"
+#include "util.h"
+#include "message.h"
+
+#define YY_NO_UNPUT
+#define YY_NEVER_INTERACTIVE 1
+
+static int yyLineNr;
+static QString className;
+static QString fileName;
+static QString tagName;
+static QString memberName;
+static QString anchorName;
+static QString argString;
+static ClassDef *cd;
+static FileDef *fd;
+
+static void addClass(const char *name,const char *fileName)
+{
+ //printf("adding class %s\n",name);
+ if (name!=0 && strlen(name)>0 && classDict[name]==0)
+ {
+ cd = new ClassDef(name,ClassDef::Class,tagName,fileName);
+ fd = 0;
+ classList.inSort(cd);
+ classDict.insert(className,cd);
+ }
+}
+
+static void addFile(const char *name)
+{
+ //printf("adding file %s\n",name);
+ fd = new FileDef(0,name,tagName);
+ FileName *mn;
+ if ((mn=inputNameDict[name]))
+ {
+ mn->append(fd);
+ }
+ else
+ {
+ mn = new FileName(name);
+ mn->append(fd);
+ inputNameList.inSort(mn);
+ inputNameDict.insert(name,mn);
+ }
+ cd = 0;
+ //fileList.inSort(fd);
+ //fileDict.insert(fileName,fd);
+}
+
+static void addMember(const char *name,const char *anchor,const char *args)
+{
+ //printf("adding member %s\n",name);
+ if (cd || fd)
+ {
+ MemberNameDict *mnd=0;
+ MemberNameList *mnl=0;
+ MemberDef *md;
+ md=new MemberDef(0,name,args,0,Public,Normal,FALSE,FALSE,
+ MemberDef::Function,0,0);
+ md->setReference(anchor);
+ if (cd)
+ {
+ //md=new MemberDef(cd,name,args,anchor,tagName);
+ md->setMemberClass(cd);
+ cd->insertMember(md);
+ //printf("Adding member %s %s to class\n",name,args);
+ mnd=&memberNameDict;
+ mnl=&memberNameList;
+ }
+ else
+ {
+ //md=new MemberDef(&unrelatedClass,name,args,anchor,tagName);
+ md->setFileDef(fd);
+ fd->insertMember(md);
+ //printf("Adding global member %s %s\n",name,args);
+ mnd=&functionNameDict;
+ mnl=&functionNameList;
+ }
+ MemberName *mn;
+ if ((mn=(*mnd)[memberName]))
+ {
+ //printf("mn->inSort()\n");
+ mn->append(md);
+ }
+ else
+ {
+ //printf("mn->append()\n");
+ mn=new MemberName(memberName);
+ mn->append(md);
+ //printf("Adding memberName=%s\n",mn->memberName());
+ mnl->inSort(mn);
+ mnd->insert(memberName,mn);
+ }
+ }
+}
+
+/* -----------------------------------------------------------------
+ */
+
+%}
+
+ID [a-z_A-Z][a-z_A-Z0-9]*
+FILE [a-z_A-Z0-9\.\-\+\:\\\/]+
+
+%x Pass1
+%x Pass2
+%x AnchorName
+%x ArgString1
+%x ArgString2
+%x ClassName1
+%x ClassName2
+%x FileName
+%x BaseClasses
+%x ClassFile1
+%x ClassFile2
+
+%%
+
+<Pass1>^">" {
+ BEGIN(ClassName1);
+ }
+<Pass1>^"&" {
+ BEGIN(FileName);
+ }
+<Pass1>^[~a-z_A-Z][^ \n]*/" " {
+ memberName=yytext;
+ BEGIN(AnchorName);
+ }
+<Pass2>^">" {
+ BEGIN(ClassName2);
+ }
+<AnchorName>{ID} {
+ anchorName=yytext;
+ BEGIN(ArgString1);
+ }
+<ArgString1>"\"" {
+ BEGIN(ArgString2);
+ }
+<ArgString2>[^\"\n]*/"\"" {
+ argString=yytext;
+ addMember(memberName,anchorName,argString);
+ BEGIN(Pass1);
+ }
+<FileName>{FILE}/":" {
+ fileName=yytext;
+ addFile(yytext);
+ BEGIN(Pass1);
+ }
+<ClassName1>{ID}/":" {
+ className=yytext;
+ BEGIN(ClassFile1);
+ }
+<ClassFile1>\" {
+ BEGIN(ClassFile2);
+ }
+<ClassFile2>[^\"]*/\" {
+ addClass(className,yytext);
+ BEGIN(Pass1);
+ }
+<ClassFile2>\n {
+ yyLineNr++;
+ BEGIN(Pass1);
+ }
+<ClassName2>{ID}/":" {
+ cd=getClass(yytext);
+ BEGIN(BaseClasses);
+ }
+<BaseClasses>{ID}/"?" {
+ ClassDef *bcd=getClass(yytext);
+ if (cd && bcd)
+ {
+ cd->insertBaseClass(bcd,Public,Normal);
+ bcd->insertSuperClass(cd,Public,Normal);
+ }
+ }
+<BaseClasses>\n {
+ yyLineNr++;
+ BEGIN(Pass2);
+ }
+<*>.
+<*>\n { yyLineNr++ ; }
+
+%%
+
+/*@ ----------------------------------------------------------------------------
+ */
+
+void parseTagFile(const char *fileName)
+{
+ FILE *f=fopen(fileName,"r");
+ QFileInfo fi(fileName);
+ if (!f || !fi.exists());
+ tagName = fi.fileName();
+ tagYYin = f;
+
+ cd=0;
+ yyLineNr = 1;
+ tagYYrestart( tagYYin );
+ BEGIN(Pass1);
+ tagYYlex();
+
+ rewind(f);
+ cd=0;
+ yyLineNr = 1;
+ tagYYrestart( tagYYin );
+ BEGIN(Pass2);
+ tagYYlex();
+
+ fclose(f);
+}
+
+extern "C" { // some bogus code to keep the compiler happy
+ int tagYYwrap() { return 1 ; }
+}
diff --git a/src/translator.h b/src/translator.h
new file mode 100644
index 0000000..55b6eaf
--- /dev/null
+++ b/src/translator.h
@@ -0,0 +1,280 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#ifndef TRANSLATOR_H
+#define TRANSLATOR_H
+
+#include <qstring.h>
+
+class Translator
+{
+ public:
+ virtual QString latexBabelPackage()
+ { return ""; }
+ virtual QString trInherits()
+ { return "Inherits"; }
+ virtual QString trAnd()
+ { return "and"; }
+ virtual QString trInheritedBy()
+ { return "Inherited By"; }
+ virtual QString trRelatedFunctions()
+ { return "Related Functions"; }
+ virtual QString trRelatedSubscript()
+ { return "(Note that these are not member functions.)"; }
+ virtual QString trDetailedDescription()
+ { return "Detailed Description"; }
+ virtual QString trMemberTypedefDocumentation()
+ { return "Member Typedef Documentation"; }
+ virtual QString trMemberEnumerationDocumentation()
+ { return "Member Enumeration Documentation"; }
+ virtual QString trMemberFunctionDocumentation()
+ { return "Member Function Documentation"; }
+ virtual QString trMemberDataDocumentation()
+ { return "Member Data Documentation"; }
+ virtual QString trGeneratedFrom(const char *s,bool single)
+ { // here s is one of " Class", " Struct" or " Union"
+ // single is true implies a single file
+ QString result=(QString)"The documentation for this"+s+
+ " was generated from the following file";
+ if (single) result+=":"; else result+="s:";
+ return result;
+ }
+ virtual QString trMore()
+ { return "More..."; }
+ virtual QString trReference()
+ { return "Reference"; }
+ virtual QString trListOfAllMembers()
+ { return "List of all members."; }
+ virtual QString trMemberList()
+ { return "Member List"; }
+ virtual QString trThisIsTheListOfAllMembers()
+ { return "This is the complete list of members for"; }
+ virtual QString trIncludingInheritedMembers()
+ { return "including all inherited members."; }
+ virtual QString trGeneratedAutomatically(const char *s)
+ { QString result="Generated automatically by Doxygen";
+ if (s) result+=(QString)" for "+s;
+ result+=" from the source code.";
+ return result;
+ }
+ virtual QString trEnumName()
+ { return "enum name"; }
+ virtual QString trEnumValue()
+ { return "enum value"; }
+ virtual QString trDefinedIn()
+ { return "defined in"; }
+ virtual QString trIncludeFile()
+ { return "Include File"; }
+ virtual QString trVerbatimText(const char *f)
+ { return (QString)"This is the verbatim text of the "+f+" include file."; }
+
+
+ virtual QString trModules()
+ { return "Modules"; }
+ virtual QString trClassHierarchy()
+ { return "Class Hierarchy"; }
+ virtual QString trCompoundList()
+ { return "Compound List"; }
+ virtual QString trFileList()
+ { return "File List"; }
+ virtual QString trHeaderFiles()
+ { return "Header Files"; }
+ virtual QString trCompoundMembers()
+ { return "Compound Members"; }
+ virtual QString trFileMembers()
+ { return "File Members"; }
+ virtual QString trRelatedPages()
+ { return "Related Pages"; }
+ virtual QString trExamples()
+ { return "Examples"; }
+ virtual QString trSearch()
+ { return "Search"; }
+
+ virtual QString trClassHierarchyDescription()
+ { return "This inheritance list is sorted roughly, "
+ "but not completely, alphabetically:";
+ }
+ virtual QString trFileListDescription(bool extractAll)
+ {
+ QString result="Here is a list of all ";
+ if (!extractAll) result+="documented ";
+ result+="files with brief descriptions:";
+ return result;
+ }
+ virtual QString trCompoundListDescription()
+ { return "Here are the classes, structs and "
+ "unions with brief descriptions:";
+ }
+ virtual QString trCompoundMembersDescription(bool extractAll)
+ {
+ QString result="Here is a list of all ";
+ if (!extractAll) result+="documented ";
+ result+="class members with links to ";
+ if (extractAll)
+ result+="the class documentation for each member:";
+ else
+ result+="the classes they belong to:";
+ return result;
+ }
+ virtual QString trFileMembersDescription(bool extractAll)
+ {
+ QString result="Here is a list of all ";
+ if (!extractAll) result+="documented ";
+ result+="file members with links to ";
+ if (extractAll)
+ result+="the file documentation for each member:";
+ else
+ result+="the files they belong to:";
+ return result;
+ }
+ virtual QString trHeaderFilesDescription()
+ { return "Here are the header files that make up the API:"; }
+ virtual QString trExamplesDescription()
+ { return "Here is a list of all examples:"; }
+ virtual QString trRelatedPagesDescription()
+ { return "Here is a list of all related documentation pages:"; }
+ virtual QString trModulesDescription()
+ { return "Here is a list of all modules:"; }
+ virtual QString trNoDescriptionAvailable()
+ { return "No description available"; }
+
+ virtual QString trDocumentation()
+ { return "Documentation"; }
+ virtual QString trModuleIndex()
+ { return "Module Index"; }
+ virtual QString trHierarchicalIndex()
+ { return "Hierarchical Index"; }
+ virtual QString trCompoundIndex()
+ { return "Compound Index"; }
+ virtual QString trFileIndex()
+ { return "File Index"; }
+ virtual QString trModuleDocumentation()
+ { return "Module Documentation"; }
+ virtual QString trClassDocumentation()
+ { return "Class Documentation"; }
+ virtual QString trFileDocumentation()
+ { return "File Documentation"; }
+ virtual QString trExampleDocumentation()
+ { return "Example Documentation"; }
+ virtual QString trPageDocumentation()
+ { return "Page Documentation"; }
+ virtual QString trReferenceManual()
+ { return "Reference Manual"; }
+
+ virtual QString trDefines()
+ { return "Defines"; }
+ virtual QString trFuncProtos()
+ { return "Function Prototypes"; }
+ virtual QString trTypedefs()
+ { return "Typedefs"; }
+ virtual QString trEnumerations()
+ { return "Enumerations"; }
+ virtual QString trFunctions()
+ { return "Functions"; }
+ virtual QString trVariables()
+ { return "Variables"; }
+ virtual QString trEnumerationValues()
+ { return "Enumeration values"; }
+ virtual QString trReimplementedFrom()
+ { return "Reimplemented from"; }
+ virtual QString trReimplementedIn()
+ { return "Reimplemented in"; }
+ virtual QString trAuthor()
+ { return "Author"; }
+ virtual QString trDefineDocumentation()
+ { return "Define Documentation"; }
+ virtual QString trFunctionPrototypeDocumentation()
+ { return "Function Prototype Documentation"; }
+ virtual QString trTypedefDocumentation()
+ { return "Typedef Documentation"; }
+ virtual QString trEnumerationTypeDocumentation()
+ { return "Enumeration Type Documentation"; }
+ virtual QString trEnumerationValueDocumentation()
+ { return "Enumeration Value Documentation"; }
+ virtual QString trFunctionDocumentation()
+ { return "Function Documentation"; }
+ virtual QString trVariableDocumentation()
+ { return "Variable Documentation"; }
+ virtual QString trCompounds()
+ { return "Compounds"; }
+ virtual QString trFiles()
+ { return "Files"; }
+
+ virtual QString trGeneratedAt(const char *date,const char *projName)
+ {
+ QString result=(QString)"Generated at "+date;
+ if (projName) result+=(QString)" for "+projName;
+ result+=(QString)" by";
+ return result;
+ }
+ virtual QString trWrittenBy()
+ {
+ return "written by";
+ }
+
+ virtual QString trClassDiagram(const char *clName)
+ {
+ return (QString)"Class diagram for "+clName;
+ }
+
+ virtual QString trForInternalUseOnly()
+ { return "For internal use only."; }
+ virtual QString trReimplementedForInternalReasons()
+ { return "Reimplemented for internal reasons; the API is not affected."; }
+ virtual QString trWarning()
+ { return "Warning"; }
+ virtual QString trBugsAndLimitations()
+ { return "Bugs and limitations"; }
+ virtual QString trVersion()
+ { return "Version"; }
+ virtual QString trDate()
+ { return "Date"; }
+ virtual QString trAuthors()
+ { return "Author(s)"; }
+ virtual QString trReturns()
+ { return "Returns"; }
+ virtual QString trSeeAlso()
+ { return "See also"; }
+ virtual QString trParameters()
+ { return "Parameters"; }
+ virtual QString trExceptions()
+ { return "Exceptions"; }
+ virtual QString trGeneratedBy()
+ { return "Generated by"; }
+
+ // new since 0.49-990307
+
+ virtual QString trNamespaces()
+ { return "Namespaces"; }
+ virtual QString trNamespaceList()
+ { return "Namespace List"; }
+ virtual QString trNamespaceListDescription(bool extractAll)
+ {
+ QString result="Here is a list of all ";
+ if (!extractAll) result+="documented ";
+ result+="namespaces with brief descriptions:";
+ return result;
+ }
+ virtual QString trFriends()
+ { return "Friends"; }
+
+ // new since 0.49-990405
+
+ virtual QString trRelatedFunctionDocumentation()
+ { return "Friends And Related Function Documentation"; }
+};
+
+#endif
diff --git a/src/translator_cz.h b/src/translator_cz.h
new file mode 100644
index 0000000..9a0656e
--- /dev/null
+++ b/src/translator_cz.h
@@ -0,0 +1,278 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#ifndef TRANSLATOR_CZ_H
+#define TRANSLATOR_CZ_H
+
+#include <qstring.h>
+
+// The translation from English to Czech by Vlastimil Havran.
+// In the cases where are more translations possible I hope
+// that I have selected the most reasonable text. If not, please,
+// mail the comments and text proposals to
+//
+// havran@fel.cvut.cz, 1999/04/11
+
+class TranslatorCzech : public Translator
+{
+ public:
+ QString latexBabelPackage()
+ { return "czech"; }
+ QString trInherits()
+ { return "Dedi"; }
+ QString trAnd()
+ { return "a"; }
+ QString trInheritedBy()
+ { return "Je Potomkem"; }
+ QString trRelatedFunctions()
+ { return "Pribuzne Metody"; }
+ QString trRelatedSubscript()
+ { return "(Tyto funkce nejsou metody.)"; }
+ QString trDetailedDescription()
+ { return "Podrobna Dokumentace"; }
+ QString trMemberTypedefDocumentation()
+ { return "Dokumentace pro Deklaraci Typu (typedef) ve Tride";}
+ QString trMemberEnumerationDocumentation()
+ { return "Dokumentace Vyctovych Typu"; }
+ QString trEnumerationValueDocumentation()
+ { return "Dokumentace Hodnot Vyctovych Typu"; }
+ QString trMemberFunctionDocumentation()
+ { return "Dokumentace Metod"; }
+ QString trMemberDataDocumentation()
+ { return "Dokumentace Datovych Slozek Tridy"; }
+ QString trGeneratedFrom(const char *s,bool single)
+ {
+ QString result=(QString)"Dokumentace pro tento"+s+
+ " byla generovana z nasledujiciho souboru";
+ if (single) result+=":"; else result+="s:";
+ return result;
+ }
+ QString trMore()
+ { return "Detaily"; }
+ QString trReference()
+ { return "Reference"; }
+ QString trListOfAllMembers()
+ { return "Seznam vsech datovych slozek a metod tridy."; }
+ QString trMemberList()
+ { return "Seznam datovych polozek a metod tridy"; }
+ QString trThisIsTheListOfAllMembers()
+ { return "Toto je uplny seznam datovych slozek a metod tridy pro"; }
+ QString trIncludingInheritedMembers()
+ { return "zahrnuje vsechny nasledujici zdedene datove slozky a metody."; }
+ QString trGeneratedAutomatically(const char *s)
+ { QString result="Automaticky vygenerovany pomoci programu Doxygen";
+ if (s) result+=(QString)" pro "+s;
+ result+=" ze zdrojoveho souboru.";
+ return result;
+ }
+ QString trEnumName()
+ { return "pojmenovani vyctoveho typu"; }
+ QString trEnumValue()
+ { return "hodnota vyctoveho typu"; }
+ QString trDefinedIn()
+ { return "definovany v"; }
+ QString trIncludeFile()
+ { return "Vklada soubor"; }
+ QString trVerbatimText(const char *f)
+ { return (QString)"Toto je presny text z vlozeneho souboru "+f+""; }
+ QString trModules()
+ { return "Moduly"; }
+ QString trClassHierarchy()
+ { return "Hierarchie trid"; }
+ QString trCompoundList()
+ { return "Seznam objektovych typu"; }
+ QString trFileList()
+ { return "Seznam souboru"; }
+ QString trHeaderFiles()
+ { return "Hlavickove soubory"; }
+ QString trCompoundMembers()
+ { return "Datove slozky a metody objektovych typu"; }
+ QString trFileMembers()
+ { return "Globalni deklarace"; }
+ QString trRelatedPages()
+ { return "Souvisejici stranky"; }
+ QString trExamples()
+ { return "Priklady:"; }
+ QString trSearch()
+ { return "Hledej"; }
+ QString trClassHierarchyDescription()
+ { return "Tento seznam dedicnych zavislosti je temer setriden"
+ " podle abecedy:";
+ }
+ QString trFileListDescription(bool extractAll)
+ {
+ QString result="A toto je seznam vsech ";
+ if (!extractAll) result+="dokumentovanych ";
+ result+="souboru s kratkymi popisy:";
+ return result;
+ }
+ QString trCompoundListDescription()
+ { return "Zde jsou tridy, struktury a "
+ "unie s kratkymi popisy:";
+ }
+ QString trCompoundMembersDescription(bool extractAll)
+ {
+ QString result="Zde je seznam vsech ";
+ if (!extractAll) result+="dokumentovanych ";
+ result+="clenu tridy (metod a datovych slozek) s odkazy na ";
+ if (extractAll) result+="dokumentaci tridy pro kazdo polozku:";
+ else result+="tridy, kam patri:";
+ return result;
+ }
+ QString trFileMembersDescription(bool extractAll)
+ {
+ QString result="Zde je seznam vsech ";
+ if (!extractAll) result+="zdokumentovanych ";
+ result+="globalnich deklaraci s odkazy ";
+ if (extractAll) result+="na dokumentaci k souboru pro kazdou deklaraci:";
+ else result+="na soubory, kde jsou umisteny:";
+ return result;
+ }
+ QString trHeaderFilesDescription()
+ {return "Zde jsou hlavickove soubory ktere tvori programove"
+ " rozhrani aplikace(API):";
+ }
+ QString trExamplesDescription()
+ { return "Zde je seznam vsech prikladu:"; }
+ QString trRelatedPagesDescription()
+ { return "Zde je seznam vsech souvisejicich stranek dokumentace:"; }
+ QString trModulesDescription()
+ { return "Zde je seznam vsech modulu:"; }
+ QString trNoDescriptionAvailable()
+ { return "Zadny popis neni k dispozici."; }
+
+ QString trDocumentation()
+ { return "Dokumentace"; }
+ QString trModuleIndex()
+ { return "Index modulu"; }
+ QString trHierarchicalIndex()
+ { return "Index Hierarchie"; }
+ QString trCompoundIndex()
+ { return "Index objektovych typu"; }
+ QString trFileIndex()
+ { return "Index souboru"; }
+ QString trModuleDocumentation()
+ { return "Dokumentace modulu"; }
+ QString trClassDocumentation()
+ { return "Dokumentace tridy"; }
+ QString trFileDocumentation()
+ { return "Dokumentace souboru"; }
+ QString trExampleDocumentation()
+ { return "Dokumentace prikladu"; }
+ QString trPageDocumentation()
+ { return "Dokumentace stranek"; }
+ QString trReferenceManual()
+ { return "Referencni manual"; }
+
+ QString trDefines()
+ { return "Definice"; }
+ QString trFuncProtos()
+ { return "Prototypy funkci"; }
+ QString trTypedefs()
+ { return "Deklarace datovych typu(typedefs)"; }
+ QString trEnumerations()
+ { return "Vyctove typy (enumerations)"; }
+ QString trFunctions()
+ { return "Funkce"; }
+ QString trVariables()
+ { return "Promenne"; }
+ QString trEnumerationValues()
+ { return "Hodnoty vyctovych typu"; }
+ QString trReimplementedFrom()
+ { return "Je znovu implementovan z"; }
+ QString trReimplementedIn()
+ { return "Je znovu implementovan v"; }
+ QString trAuthor()
+ { return "Autor"; }
+ QString trDefineDocumentation()
+ { return "Dokumentace definic pomoci maker"; }
+ QString trFunctionPrototypeDocumentation()
+ { return "Dokumentace prototypu funkci"; }
+ QString trTypedefDocumentation()
+ { return "Dokumentace deklaraci datovych typu(typedefs)"; }
+ QString trEnumerationTypeDocumentation()
+ { return "Dokumentace vyctovych typu"; }
+ QString trFunctionDocumentation()
+ { return "Dokumentace funkci"; }
+ QString trVariableDocumentation()
+ { return "Dokumentace promennych"; }
+ QString trCompounds()
+ { return "Polozky objektovych typu"; }
+ QString trFiles()
+ { return "Soubory:"; }
+ QString trGeneratedAt(const char *date,const char *projName)
+ {
+ QString result=(QString)"Gegenerovany v "+date;
+ if (projName) result+=(QString)" pro "+projName;
+ result+=(QString)" ";
+ return result;
+ }
+ QString trWrittenBy()
+ {
+ return "napsany ";
+ }
+ QString trClassDiagram(const char *clName)
+ {
+ return (QString)"Diagram trid pro "+clName;
+ }
+ QString trForInternalUseOnly()
+ { return "Jen pro interni pouziti."; }
+ QString trReimplementedForInternalReasons()
+ {
+ return "Znovu implementovany z internich duvodu; programove rozhrani"
+ " aplikace(API) neni zmeneno.";
+ }
+ QString trWarning()
+ { return "Upozorneni"; }
+ QString trBugsAndLimitations()
+ { return "Chyby a omezeni"; }
+ QString trVersion()
+ { return "Verze"; }
+ QString trDate()
+ { return "Datum"; }
+ QString trAuthors()
+ { return "Autor(i)"; }
+ QString trReturns()
+ { return "ma navratovou hodnotu"; }
+ QString trSeeAlso()
+ { return "Podivej se take na"; }
+ QString trParameters()
+ { return "Parametry"; }
+ QString trExceptions()
+ { return "Vyjimky"; }
+ QString trGeneratedBy()
+ { return "Gegenerovan podle"; }
+
+ // new since 0.49-990307
+
+ QString trNamespaces()
+ { return "Prostory jmen"; }
+ QString trNamespaceList()
+ { return "Seznam prostoru jmen"; }
+ QString trNamespaceListDescription(bool extractAll)
+ {
+ QString result="Zde jsou vsechny ";
+ if (!extractAll) result+="dokumentovane ";
+ result+="prostory jem s kratkymi popisy:";
+ return result;
+ }
+ QString trFriends()
+ { return "Spratelene tridy, funkce a metody"; }
+};
+
+#endif // TRANSLATOR_CZ_H
+
+
diff --git a/src/translator_fr.h b/src/translator_fr.h
new file mode 100644
index 0000000..cd78053
--- /dev/null
+++ b/src/translator_fr.h
@@ -0,0 +1,270 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#ifndef TRANSLATOR_FR_H
+#define TRANSLATOR_FR_H
+
+#include <qstring.h>
+
+class TranslatorFrench : public Translator
+{
+ public:
+ QString latexBabelPackage()
+ { return "french"; }
+ QString trInherits()
+ { return "Hérite de"; }
+ QString trAnd()
+ { return "et"; }
+ QString trInheritedBy()
+ { return "Dérivée par"; }
+ QString trRelatedFunctions()
+ { return "Fonctions associées"; }
+ QString trRelatedSubscript()
+ { return "(Noter que ces fonctions ne sont pas des méthodes de la classe)"; }
+ QString trDetailedDescription()
+ { return "Description détaillée"; }
+ QString trMemberTypedefDocumentation()
+ { return "Documentation des types imbriqués"; }
+ QString trMemberEnumerationDocumentation()
+ { return "Documentation des énumérations imbriqués"; }
+ QString trMemberFunctionDocumentation()
+ { return "Documentation des méthodes"; }
+ QString trMemberDataDocumentation()
+ { return "Documentation des données imbriqués"; }
+ QString trGeneratedFrom(const char *s,bool single)
+ {
+ QString result=(QString)"La documentation pour cette"+s+
+ " a été générée à partir ";
+ if (single) result+="du fichier suivant:";
+ else result+="des fichiers suivants:";
+ return result;
+ }
+ QString trMore()
+ { return "Plus de détails..."; }
+ QString trReference()
+ { return "Référence"; }
+ QString trListOfAllMembers()
+ { return "Liste de tous les membres"; }
+ QString trMemberList()
+ { return "Liste des membres"; }
+ QString trThisIsTheListOfAllMembers()
+ { return "Ceci est la liste complète des membres de"; }
+ QString trIncludingInheritedMembers()
+ { return "y compris des membres des classes héritées."; }
+ QString trGeneratedAutomatically(const char *s)
+ { QString result="Généré automatiquement par Doxygen";
+ if (s) result+=(QString)" pour "+s;
+ result+=" à partir du code source.";
+ return result;
+ }
+ QString trEnumName()
+ { return "énumération"; }
+ QString trEnumValue()
+ { return "élément d'une énumération"; }
+ QString trDefinedIn()
+ { return "défini dans"; }
+ QString trIncludeFile()
+ { return "Fichier inclu"; }
+ QString trVerbatimText(const char *f)
+ { return (QString)"Ce texte provient du fichier inclu "+f+"."; }
+
+
+ QString trModules()
+ { return "Modules"; }
+ QString trClassHierarchy()
+ { return "Hiérarchie des classes"; }
+ QString trCompoundList()
+ { return "Liste des composants"; }
+ QString trFileList()
+ { return "Liste des fichiers"; }
+ QString trHeaderFiles()
+ { return "Fichiers d'entête"; }
+ QString trCompoundMembers()
+ { return "Composants"; }
+ QString trFileMembers()
+ { return "Déclarations"; }
+ QString trRelatedPages()
+ { return "Pages associées"; }
+ QString trExamples()
+ { return "Exemples"; }
+ QString trSearch()
+ { return "Recherche"; }
+ QString trClassHierarchyDescription()
+ { return "Cette liste d'héritage est, autant que possible, "
+ "classée par ordre alphabétique"; }
+ QString trFileListDescription(bool extractAll)
+ {
+ QString result="Liste de tous les fichiers ";
+ if (!extractAll) result+="documentés ";
+ result+="avec une brève description :";
+ return result;
+ }
+ QString trCompoundListDescription()
+ { return "Liste des classes, des strutures et des unions "
+ "avec une brève description :";
+ }
+ QString trCompoundMembersDescription(bool extractAll)
+ {
+ QString result="Liste de tous les membres de classe ";
+ if (!extractAll) result+="documentés ";
+ result+="avec les liens vers ";
+ if (extractAll) result+="la documentation de la classe correspondante :";
+ else result+="les classes auxquelles ils appartiennent :";
+ return result;
+ }
+ QString trFileMembersDescription(bool extractAll)
+ {
+ QString result="Liste de toutes les déclarations";
+ if (!extractAll) result+="documentées ";
+ result+="avec liens sur ";
+ if (extractAll) result+="la documentation du fichier correspondant "
+ "pour chacune :";
+ else result+="les fichiers dans lesquels elles sont définies :";
+ return result;
+ }
+ QString trHeaderFilesDescription()
+ { return "Liste de tous les fichiers d'entête constituant "
+ "l'interface de programmation :"; }
+ QString trExamplesDescription()
+ { return "Liste de tous les exemples :"; }
+ QString trRelatedPagesDescription()
+ { return "Liste de toutes les pages de documentation associées :"; }
+ QString trModulesDescription()
+ { return "Liste de tous les modules"; }
+ QString trNoDescriptionAvailable()
+ { return "Aucune description n'est disponible"; }
+
+ QString trDocumentation()
+ { return "Documentation"; }
+ QString trModuleIndex()
+ { return "Index des modules"; }
+ QString trHierarchicalIndex()
+ { return "Index hiérarchique"; }
+ QString trCompoundIndex()
+ { return "Index des composants"; }
+ QString trFileIndex()
+ { return "Index des fichiers"; }
+ QString trModuleDocumentation()
+ { return "Documentation du module"; }
+ QString trClassDocumentation()
+ { return "Documentation de la classe"; }
+ QString trFileDocumentation()
+ { return "Documentation du fichier"; }
+ QString trExampleDocumentation()
+ { return "Documentation de l'exemple"; }
+ QString trPageDocumentation()
+ { return "Documentation de la page"; }
+ QString trReferenceManual()
+ { return "Manuel de référence"; }
+
+ QString trDefines()
+ { return "Définitions des macros"; }
+ QString trFuncProtos()
+ { return "Prototypes des fonctions"; }
+ QString trTypedefs()
+ { return "Définitions des types"; }
+ QString trEnumerations()
+ { return "Enumérations"; }
+ QString trFunctions()
+ { return "Fonctions"; }
+ QString trVariables()
+ { return "Variables"; }
+ QString trEnumerationValues()
+ { return "Eléments énumérés"; }
+ QString trReimplementedFrom()
+ { return "Redéfini à partir de"; }
+ QString trReimplementedIn()
+ { return "Redéfini dans"; }
+ QString trAuthor()
+ { return "Auteur"; }
+ QString trDefineDocumentation()
+ { return "Documentation de la macro"; }
+ QString trFunctionPrototypeDocumentation()
+ { return "Documentation du prototype de la fonction"; }
+ QString trTypedefDocumentation()
+ { return "Documentation du type"; }
+ QString trEnumerationTypeDocumentation()
+ { return "Documentation du type de l'énumeration"; }
+ QString trEnumerationValueDocumentation()
+ { return "Documentation de l'élément de l'énumeration"; }
+ QString trFunctionDocumentation()
+ { return "Documentation de la fonction"; }
+ QString trVariableDocumentation()
+ { return "Documentation de la variable"; }
+ QString trCompounds()
+ { return "Composants"; }
+ QString trFiles()
+ { return "Fichiers"; }
+ QString trGeneratedAt(const char *date,const char *projName)
+ {
+ QString result=(QString)"Généré le "+date;
+ if (projName) result+=(QString)" pour "+projName;
+ result+=(QString)" par ";
+ return result;
+ }
+ QString trWrittenBy()
+ {
+ return "écrit par";
+ }
+ QString trClassDiagram(const char *clName)
+ {
+ return (QString)"Graphe d'héritage de la classe "+clName;
+ }
+ QString trForInternalUseOnly()
+ { return "A usage interne uniquement."; }
+ QString trReimplementedForInternalReasons()
+ { return "Redéfini pour des raisons internes; "
+ "l'interface n'est pas modifiée";
+ }
+ QString trWarning()
+ { return "Avertissement"; }
+ QString trBugsAndLimitations()
+ { return "Bogues et limitations"; }
+ QString trVersion()
+ { return "Version"; }
+ QString trDate()
+ { return "Date"; }
+ QString trAuthors()
+ { return "Auteur(s)"; }
+ QString trReturns()
+ { return "Renvoie"; }
+ QString trSeeAlso()
+ { return "Voir également"; }
+ QString trParameters()
+ { return "Paramètres"; }
+ QString trExceptions()
+ { return "Exceptions"; }
+ QString trGeneratedBy()
+ { return "Généré par"; }
+
+ // new since 0.49-990307
+
+ virtual QString trNamespaces()
+ { return "Namespaces"; }
+ virtual QString trNamespaceList()
+ { return "List des Namespaces"; }
+ virtual QString trNamespaceListDescription(bool extractAll)
+ {
+ QString result="Liste de tous les namespaces ";
+ if (!extractAll) result+="documentés ";
+ result+="avec une brève description :";
+ return result;
+ }
+ virtual QString trFriends()
+ { return "Friends"; }
+};
+
+#endif
diff --git a/src/translator_it.h b/src/translator_it.h
new file mode 100644
index 0000000..316f43a
--- /dev/null
+++ b/src/translator_it.h
@@ -0,0 +1,266 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#ifndef TRANSLATOR_IT_H
+#define TRANSLATOR_IT_H
+
+#include <qstring.h>
+
+class TranslatorItalian : public Translator
+{
+ public:
+ QString latexBabelPackage()
+ { return "italian"; }
+ QString trInherits()
+ { return "eredita"; }
+ QString trAnd()
+ { return "e"; }
+ QString trInheritedBy()
+ { return "Ereditato da"; }
+ QString trRelatedFunctions()
+ { return "Funzioni relative"; }
+ QString trRelatedSubscript()
+ { return "(Nota che questo no sono funzioni membro)"; }
+ QString trDetailedDescription()
+ { return "Descrizione dettagliata"; }
+ QString trMemberTypedefDocumentation()
+ { return "Documentazione dei membri Typedef"; }
+ QString trMemberEnumerationDocumentation()
+ { return "Documentazione dei membri enumerati"; }
+ QString trEnumerationValueDocumentation()
+ { return "Documentazione dei tipi enumerati"; }
+ QString trMemberFunctionDocumentation()
+ { return "Documentazione delle funzioni membro"; }
+ QString trMemberDataDocumentation()
+ { return "Documentazione dei dati membro"; }
+ QString trGeneratedFrom(const char *s,bool single)
+ {
+ QString result=(QString)"La documentazione di questa "+s+
+ " e stata generata dal seguente file";
+ if (single) result+=":"; else result+=":";
+ return result;
+ }
+ QString trMore()
+ { return "Continua..."; }
+ QString trReference()
+ { return "Riferimento"; }
+ QString trListOfAllMembers()
+ { return "Lista di tuti i memberi."; }
+ QString trMemberList()
+ { return "Lista membri"; }
+ QString trThisIsTheListOfAllMembers()
+ { return "Questa e la lista completa di tutti i membri"; }
+ QString trIncludingInheritedMembers()
+ { return "includendo tutti i membri ereditati."; }
+ QString trGeneratedAutomatically(const char *s)
+ { QString result="Generato automaticalmenta da Doxygen";
+ if (s) result+=(QString)" per "+s;
+ result+=" dall codice.";
+ return result;
+ }
+ QString trEnumName()
+ { return "nome dell enum"; }
+ QString trEnumValue()
+ { return "valore dell enum"; }
+ QString trDefinedIn()
+ { return "definito in"; }
+ QString trIncludeFile()
+ { return "Include il file"; }
+ QString trVerbatimText(const char *f)
+ { return (QString)"Questo e il contenuto verbatim dell file "+f+"."; }
+ QString trModules()
+ { return "Moduli"; }
+ QString trClassHierarchy()
+ { return "gerarchia delle classi"; }
+ QString trCompoundList()
+ { return "Lista dei tipi composti"; }
+ QString trFileList()
+ { return "Lista dei file"; }
+ QString trHeaderFiles()
+ { return "List dei fei file header"; }
+ QString trCompoundMembers()
+ { return "Membri composti"; }
+ QString trFileMembers()
+ { return "Membri dell file"; }
+ QString trRelatedPages()
+ { return "Relativo a pagina"; }
+ QString trExamples()
+ { return "Esempio"; }
+ QString trSearch()
+ { return "Ricerca"; }
+ QString trClassHierarchyDescription()
+ { return "Qua sono la lista delle classi, structs e unions"
+ "gesorte:";
+ }
+ QString trFileListDescription(bool extractAll)
+ {
+ QString result="Hieronder volgt de lijst met alle ";
+ if (!extractAll) result+="gedocumenteerde ";
+ result+="files, elk met een korte beschrijving:";
+ return result;
+ }
+ QString trCompoundListDescription()
+ { return "Hieronder volgen de klassen, structs en "
+ "unions met voor elk een korte beschrijving:";
+ }
+ QString trCompoundMembersDescription(bool extractAll)
+ {
+ QString result="Hieronder volgt de lijst met alle ";
+ if (!extractAll) result+="gedocumenteerde ";
+ result+="klasse members met links naar ";
+ if (extractAll) result+="de klasse Documentazione voor elke member:";
+ else result+="de klassen waartoe ze behoren:";
+ return result;
+ }
+ QString trFileMembersDescription(bool extractAll)
+ {
+ QString result="Hieronder volgt de lijst met alle ";
+ if (!extractAll) result+="gedocumenteerde ";
+ result+="file members met links naar ";
+ if (extractAll) result+="de file Documentazione voor elke member:";
+ else result+="de files waartoe ze behoren:";
+ return result;
+ }
+ QString trHeaderFilesDescription()
+ { return "Hieronder volgen de header files die de API vormen:"; }
+ QString trExamplesDescription()
+ { return "Hieronder volgt de lijst met alle voorbeelden:"; }
+ QString trRelatedPagesDescription()
+ { return "Hieronder volgt de lijst met alle pagina's die gerelateerde Documentazione bevatten:"; }
+ QString trModulesDescription()
+ { return "Hieronder volgt de lijst met alle modules:"; }
+ QString trNoDescriptionAvailable()
+ { return "Geen korte beschrijving beschikbaar"; }
+
+ QString trDocumentation()
+ { return "Documentazione"; }
+ QString trModuleIndex()
+ { return "Module Index"; }
+ QString trHierarchicalIndex()
+ { return "Hi&euml;rarchische Index"; }
+ QString trCompoundIndex()
+ { return "Compound Index"; }
+ QString trFileIndex()
+ { return "File Index"; }
+ QString trModuleDocumentation()
+ { return "Module Documentazione"; }
+ QString trClassDocumentation()
+ { return "Klasse Documentazione"; }
+ QString trFileDocumentation()
+ { return "File Documentazione"; }
+ QString trExampleDocumentation()
+ { return "Documentazione di voorbeelden"; }
+ QString trPageDocumentation()
+ { return "Documentazione di gerelateerde pagina's"; }
+ QString trReferenceManual()
+ { return "Naslagwerk"; }
+
+ QString trDefines()
+ { return "Defines"; }
+ QString trFuncProtos()
+ { return "Functie Prototypes"; }
+ QString trTypedefs()
+ { return "Typedefs"; }
+ QString trEnumerations()
+ { return "Enumeraties"; }
+ QString trFunctions()
+ { return "Functies"; }
+ QString trVariables()
+ { return "Variabelen"; }
+ QString trEnumerationValues()
+ { return "Enumeratie waarden"; }
+ QString trReimplementedFrom()
+ { return "Nieuwe implementatie di"; }
+ QString trReimplementedIn()
+ { return "Opnieuw ge&iuml;mplementeerd in"; }
+ QString trAuthor()
+ { return "auteur"; }
+ QString trDefineDocumentation()
+ { return "Lista "; }
+ QString trFunctionPrototypeDocumentation()
+ { return "Documentazione di functie Prototypes"; }
+ QString trTypedefDocumentation()
+ { return "Documentazione di typedefs"; }
+ QString trEnumerationTypeDocumentation()
+ { return "Documentazione di enumeratie types"; }
+ QString trFunctionDocumentation()
+ { return "Documentazione di functies"; }
+ QString trVariableDocumentation()
+ { return "Lista variabelen"; }
+ QString trCompounds()
+ { return "Compounds"; }
+ QString trFiles()
+ { return "Files"; }
+ QString trGeneratedAt(const char *date,const char *projName)
+ {
+ QString result=(QString)"Gegenereerd op "+date;
+ if (projName) result+=(QString)" voor "+projName;
+ result+=(QString)" door";
+ return result;
+ }
+ QString trWrittenBy()
+ {
+ return "geschreven door";
+ }
+ QString trClassDiagram(const char *clName)
+ {
+ return (QString)"Klasse diagram voor "+clName;
+ }
+ QString trForInternalUseOnly()
+ { return "Alleen voor intern gebruik."; }
+ QString trReimplementedForInternalReasons()
+ { return "Om interne rederene opnieuwd ge&iuml;mplemented; "
+ "de API wordt er niet door be&iuml;nvloed.";
+ }
+ QString trWarning()
+ { return "Waarschuwing"; }
+ QString trBugsAndLimitations()
+ { return "Fouten en beperkingen"; }
+ QString trVersion()
+ { return "Versie"; }
+ QString trDate()
+ { return "Datum"; }
+ QString trAuthors()
+ { return "Auteur(s)"; }
+ QString trReturns()
+ { return "Retourneerd"; }
+ QString trSeeAlso()
+ { return "Zie ook"; }
+ QString trParameters()
+ { return "Parameters"; }
+ QString trExceptions()
+ { return "Excepties"; }
+ QString trGeneratedBy()
+ { return "Gegenereerd door"; }
+
+ // new since 0.49-990307
+
+ QString trNamespaces()
+ { return "Namespaces"; }
+ QString trNamespaceList()
+ { return "Namespace Lijst"; }
+ QString trNamespaceListDescription(bool extractAll)
+ {
+ QString result="Hier is een lijst met alle ";
+ if (!extractAll) result+="gedocumenteerde ";
+ result+="namespaces met voor elk een korte beschrijving:";
+ return result;
+ }
+ QString trFriends()
+ { return "Friends"; }
+};
+
+#endif
diff --git a/src/translator_nl.h b/src/translator_nl.h
new file mode 100644
index 0000000..25e7ed4
--- /dev/null
+++ b/src/translator_nl.h
@@ -0,0 +1,266 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#ifndef TRANSLATOR_NL_H
+#define TRANSLATOR_NL_H
+
+#include <qstring.h>
+
+class TranslatorDutch : public Translator
+{
+ public:
+ QString latexBabelPackage()
+ { return "dutch"; }
+ QString trInherits()
+ { return "Erft over van"; }
+ QString trAnd()
+ { return "en"; }
+ QString trInheritedBy()
+ { return "Wordt overge&euml;rfd door"; }
+ QString trRelatedFunctions()
+ { return "Gerelateerde functies"; }
+ QString trRelatedSubscript()
+ { return "(Merk op dat dit geen member functies zijn.)"; }
+ QString trDetailedDescription()
+ { return "Gedetaileerde Beschrijving"; }
+ QString trMemberTypedefDocumentation()
+ { return "Documentatie van type definitie members"; }
+ QString trMemberEnumerationDocumentation()
+ { return "Documentatie van enumeratie members"; }
+ QString trEnumerationValueDocumentation()
+ { return "Documentatie van enumeratie waarden"; }
+ QString trMemberFunctionDocumentation()
+ { return "Documentatie van functie members"; }
+ QString trMemberDataDocumentation()
+ { return "Documentatie van data members"; }
+ QString trGeneratedFrom(const char *s,bool single)
+ {
+ QString result=(QString)"De documentatie voor deze"+s+
+ " is gegenereerd op grond van de volgende file";
+ if (single) result+=":"; else result+="s:";
+ return result;
+ }
+ QString trMore()
+ { return "Meer..."; }
+ QString trReference()
+ { return "Referentie"; }
+ QString trListOfAllMembers()
+ { return "Lijst van alle members."; }
+ QString trMemberList()
+ { return "Member Lijst"; }
+ QString trThisIsTheListOfAllMembers()
+ { return "Dit is de complete lijst van alle members voor"; }
+ QString trIncludingInheritedMembers()
+ { return "inclusief alle overge&euml;rfde members."; }
+ QString trGeneratedAutomatically(const char *s)
+ { QString result="Automatisch gegenereerd door Doxygen";
+ if (s) result+=(QString)" voor "+s;
+ result+=" uit de programmacode.";
+ return result;
+ }
+ QString trEnumName()
+ { return "enum naam"; }
+ QString trEnumValue()
+ { return "enum waarde"; }
+ QString trDefinedIn()
+ { return "gedefinieerd in"; }
+ QString trIncludeFile()
+ { return "Include File"; }
+ QString trVerbatimText(const char *f)
+ { return (QString)"Dit is de letterlijke tekst van de include file "+f+"."; }
+ QString trModules()
+ { return "Modules"; }
+ QString trClassHierarchy()
+ { return "Klasse Hi&euml;rarchie"; }
+ QString trCompoundList()
+ { return "Compound Lijst"; }
+ QString trFileList()
+ { return "File Lijst"; }
+ QString trHeaderFiles()
+ { return "Header Lijst"; }
+ QString trCompoundMembers()
+ { return "Compound Members"; }
+ QString trFileMembers()
+ { return "File members"; }
+ QString trRelatedPages()
+ { return "Gerelateerde pagina's"; }
+ QString trExamples()
+ { return "Voorbeelden"; }
+ QString trSearch()
+ { return "Zoeken"; }
+ QString trClassHierarchyDescription()
+ { return "Deze inheritance lijst is min of meer alfabetisch "
+ "gesorteerd:";
+ }
+ QString trFileListDescription(bool extractAll)
+ {
+ QString result="Hieronder volgt de lijst met alle ";
+ if (!extractAll) result+="gedocumenteerde ";
+ result+="files, elk met een korte beschrijving:";
+ return result;
+ }
+ QString trCompoundListDescription()
+ { return "Hieronder volgen de klassen, structs en "
+ "unions met voor elk een korte beschrijving:";
+ }
+ QString trCompoundMembersDescription(bool extractAll)
+ {
+ QString result="Hieronder volgt de lijst met alle ";
+ if (!extractAll) result+="gedocumenteerde ";
+ result+="klasse members met links naar ";
+ if (extractAll) result+="de klasse documentatie voor elke member:";
+ else result+="de klassen waartoe ze behoren:";
+ return result;
+ }
+ QString trFileMembersDescription(bool extractAll)
+ {
+ QString result="Hieronder volgt de lijst met alle ";
+ if (!extractAll) result+="gedocumenteerde ";
+ result+="file members met links naar ";
+ if (extractAll) result+="de file documentatie voor elke member:";
+ else result+="de files waartoe ze behoren:";
+ return result;
+ }
+ QString trHeaderFilesDescription()
+ { return "Hieronder volgen de header files die de API vormen:"; }
+ QString trExamplesDescription()
+ { return "Hieronder volgt de lijst met alle voorbeelden:"; }
+ QString trRelatedPagesDescription()
+ { return "Hieronder volgt de lijst met alle pagina's die gerelateerde documentatie bevatten:"; }
+ QString trModulesDescription()
+ { return "Hieronder volgt de lijst met alle modules:"; }
+ QString trNoDescriptionAvailable()
+ { return "Geen korte beschrijving beschikbaar"; }
+
+ QString trDocumentation()
+ { return "Documentatie"; }
+ QString trModuleIndex()
+ { return "Module Index"; }
+ QString trHierarchicalIndex()
+ { return "Hi&euml;rarchische Index"; }
+ QString trCompoundIndex()
+ { return "Compound Index"; }
+ QString trFileIndex()
+ { return "File Index"; }
+ QString trModuleDocumentation()
+ { return "Module Documentatie"; }
+ QString trClassDocumentation()
+ { return "Klasse Documentatie"; }
+ QString trFileDocumentation()
+ { return "File Documentatie"; }
+ QString trExampleDocumentation()
+ { return "Documentatie van voorbeelden"; }
+ QString trPageDocumentation()
+ { return "Documentatie van gerelateerde pagina's"; }
+ QString trReferenceManual()
+ { return "Naslagwerk"; }
+
+ QString trDefines()
+ { return "Defines"; }
+ QString trFuncProtos()
+ { return "Functie Prototypes"; }
+ QString trTypedefs()
+ { return "Typedefs"; }
+ QString trEnumerations()
+ { return "Enumeraties"; }
+ QString trFunctions()
+ { return "Functies"; }
+ QString trVariables()
+ { return "Variabelen"; }
+ QString trEnumerationValues()
+ { return "Enumeratie waarden"; }
+ QString trReimplementedFrom()
+ { return "Nieuwe implementatie van"; }
+ QString trReimplementedIn()
+ { return "Opnieuw ge&iuml;mplementeerd in"; }
+ QString trAuthor()
+ { return "auteur"; }
+ QString trDefineDocumentation()
+ { return "Documentatie van defines"; }
+ QString trFunctionPrototypeDocumentation()
+ { return "Documentatie van functie Prototypes"; }
+ QString trTypedefDocumentation()
+ { return "Documentatie van typedefs"; }
+ QString trEnumerationTypeDocumentation()
+ { return "Documentatie van enumeratie types"; }
+ QString trFunctionDocumentation()
+ { return "Documentatie van functies"; }
+ QString trVariableDocumentation()
+ { return "Documentatie van variabelen"; }
+ QString trCompounds()
+ { return "Compounds"; }
+ QString trFiles()
+ { return "Files"; }
+ QString trGeneratedAt(const char *date,const char *projName)
+ {
+ QString result=(QString)"Gegenereerd op "+date;
+ if (projName) result+=(QString)" voor "+projName;
+ result+=(QString)" door";
+ return result;
+ }
+ QString trWrittenBy()
+ {
+ return "geschreven door";
+ }
+ QString trClassDiagram(const char *clName)
+ {
+ return (QString)"Klasse diagram voor "+clName;
+ }
+ QString trForInternalUseOnly()
+ { return "Alleen voor intern gebruik."; }
+ QString trReimplementedForInternalReasons()
+ { return "Om interne rederene opnieuwd ge&iuml;mplemented; "
+ "de API wordt er niet door be&iuml;nvloed.";
+ }
+ QString trWarning()
+ { return "Waarschuwing"; }
+ QString trBugsAndLimitations()
+ { return "Fouten en beperkingen"; }
+ QString trVersion()
+ { return "Versie"; }
+ QString trDate()
+ { return "Datum"; }
+ QString trAuthors()
+ { return "Auteur(s)"; }
+ QString trReturns()
+ { return "Retourneerd"; }
+ QString trSeeAlso()
+ { return "Zie ook"; }
+ QString trParameters()
+ { return "Parameters"; }
+ QString trExceptions()
+ { return "Excepties"; }
+ QString trGeneratedBy()
+ { return "Gegenereerd door"; }
+
+ // new since 0.49-990307
+
+ QString trNamespaces()
+ { return "Namespaces"; }
+ QString trNamespaceList()
+ { return "Namespace Lijst"; }
+ QString trNamespaceListDescription(bool extractAll)
+ {
+ QString result="Hier is een lijst met alle ";
+ if (!extractAll) result+="gedocumenteerde ";
+ result+="namespaces met voor elk een korte beschrijving:";
+ return result;
+ }
+ QString trFriends()
+ { return "Friends"; }
+};
+
+#endif
diff --git a/src/translator_se.h b/src/translator_se.h
new file mode 100644
index 0000000..15b6c18
--- /dev/null
+++ b/src/translator_se.h
@@ -0,0 +1,250 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#ifndef TRANSLATOR_SE_H
+#define TRANSLATOR_SE_H
+
+#include <qstring.h>
+
+class TranslatorSwedish : public Translator
+{
+ public:
+ QString latexBabelPackage()
+ { return "swedish"; }
+ QString trInherits()
+ { return "Ärver"; }
+ QString trAnd()
+ { return "och"; }
+ QString trInheritedBy()
+ { return "Ärvd av"; }
+ QString trRelatedFunctions()
+ { return "Besläktade funktioner"; }
+ QString trRelatedSubscript()
+ { return "(Observera att dessa inte är medlemsfunktioner)"; }
+ QString trDetailedDescription()
+ { return "Utökad beskrivning"; }
+ QString trMemberTypedefDocumentation()
+ { return "Har inte en aning..."; }
+ QString trMemberEnumerationDocumentation()
+ { return "Uppräknad dokumentation???"; }
+ QString trEnumerationValueDocumentation()
+ { return "Documentatie van enumeratie waarden"; }
+ QString trMemberFunctionDocumentation()
+ { return "Dokumentation av medlemsfunktioner"; }
+ QString trMemberDataDocumentation()
+ { return "Dokumentation av datamedlemmar"; }
+ QString trGeneratedFrom(const char *s,bool single)
+ {
+ QString result=(QString)"Dokumentationen för detta"+s+
+ " är skapad ur följande fil";
+ if (single) result+=":"; else result+="s:";
+ return result;
+ }
+ QString trMore()
+ { return "Fler..."; }
+ QString trReference()
+ { return "Hänvisning?"; }
+ QString trListOfAllMembers()
+ { return "Lista över alla medlemmar."; }
+ QString trMemberList()
+ { return "Medlemslista"; }
+ QString trThisIsTheListOfAllMembers()
+ { return "Det här är en fullständig lista av medlemmar för?"; }
+ QString trIncludingInheritedMembers()
+ { return "med alla ärvda medlemmar."; }
+ QString trGeneratedAutomatically(const char *s)
+ { QString result="Automatiskt skapad av Doxygen";
+ if (s) result+=(QString)" för "+s;
+ result+=" från källkoden.";
+ return result;
+ }
+ QString trEnumName()
+ { return "enum namn?"; }
+ QString trEnumValue()
+ { return "enum värde?"; }
+ QString trDefinedIn()
+ { return "deklarerad i"; }
+ QString trIncludeFile()
+ { return "Include Fil"; }
+ QString trVerbatimText(const char *f)
+ { return (QString)"Detta är den ordagranna texten av "+f+" include fil."; }
+ QString trModules()
+ { return "Moduler?"; }
+ QString trClassHierarchy()
+ { return "Klasshierarki?"; }
+ QString trCompoundList()
+ { return "Inhägnad lista???"; }
+ QString trFileList()
+ { return "Fillista"; }
+ QString trHeaderFiles()
+ { return "Headerfiler"; }
+ QString trCompoundMembers()
+ { return "Inhägnade medlemmar??"; }
+ QString trFileMembers()
+ { return "Filmedlemmar???"; }
+ QString trRelatedPages()
+ { return "Besläktade sidor"; }
+ QString trExamples()
+ { return "Exempel"; }
+ QString trSearch()
+ { return "Sök"; }
+ QString trClassHierarchyDescription()
+ { return "Denna lista över arv är grovsorterad, men inte helt "
+ "i alfabetisk ordning:";
+ }
+ QString trFileListDescription(bool extractAll)
+ {
+ QString result="Här följer en lista över alla ";
+ if (!extractAll) result+="dokumenterade ";
+ result+="filer, med en kort beskrivning:";
+ return result;
+ }
+ QString trCompoundListDescription()
+ { return "Här följer klasserna, structs och "
+ "unions? med en kort beskrivning:";
+ }
+ QString trCompoundMembersDescription(bool extractAll)
+ {
+ QString result="Här följer en lista över alla ";
+ if (!extractAll) result+="dokumenterade ";
+ result+="klassmedlemmar med länkar till ";
+ if (extractAll) result+="klassdokumentationen för varje medlem:";
+ else result+="klasserna som de tillhör:";
+ return result;
+ }
+ QString trFileMembersDescription(bool extractAll)
+ {
+ QString result="Här följer en lista över alla ";
+ if (!extractAll) result+="dokumenterade ";
+ result+="filmedlemmar? med länkar till ";
+ if (extractAll) result+="dokumentationsfilen för varje medlem:";
+ else result+="filerna som de tillhör:";
+ return result;
+ }
+ QString trHeaderFilesDescription()
+ { return "Här följer headerfilerna som API:n består av???:"; }
+ QString trExamplesDescription()
+ { return "Här följer en lista med alla exempel:"; }
+ QString trRelatedPagesDescription()
+ { return "Här följer en lista med alla relevanta? dokumentationssidor:"; }
+ QString trModulesDescription()
+ { return "Här följer en lista över alla moduler:"; }
+ QString trNoDescriptionAvailable()
+ { return "Beskrivning saknas"; }
+
+ QString trDocumentation()
+ { return "Dokumentation"; }
+ QString trModuleIndex()
+ { return "Module Index"; }
+ QString trHierarchicalIndex()
+ { return "Hierarkiskt Index"; }
+ QString trCompoundIndex()
+ { return "Compound Index"; }
+ QString trFileIndex()
+ { return "Fil Index"; }
+ QString trModuleDocumentation()
+ { return "Dokumentation över moduler"; }
+ QString trClassDocumentation()
+ { return "Dokumentation över klasser"; }
+ QString trFileDocumentation()
+ { return "Dokumentation över filer"; }
+ QString trExampleDocumentation()
+ { return "Dokumentation över exempel"; }
+ QString trPageDocumentation()
+ { return "Dokumentation av sidor"; }
+ QString trReferenceManual()
+ { return "Uppslagsbok"; }
+
+ QString trDefines()
+ { return "Definerar"; }
+ QString trFuncProtos()
+ { return "Funktionsprototyper"; }
+ QString trTypedefs()
+ { return "Typedefs"; }
+ QString trEnumerations()
+ { return "Uppräkning???"; }
+ QString trFunctions()
+ { return "Funktioner"; }
+ QString trVariables()
+ { return "Variabler"; }
+ QString trEnumerationValues()
+ { return "Enum värden??"; }
+ QString trReimplementedFrom()
+ { return "Återanvänd från???"; }
+ QString trReimplementedIn()
+ { return "Återanvänd i??"; }
+ QString trAuthor()
+ { return "Författare"; }
+ QString trDefineDocumentation()
+ { return "Definiera dokumentation"; }
+ QString trFunctionPrototypeDocumentation()
+ { return "Dokumentation över funktionsprototyper"; }
+ QString trTypedefDocumentation()
+ { return "Dokumentation över typedefs"; }
+ QString trEnumerationTypeDocumentation()
+ { return "Dokumentation över enum typer"; }
+ QString trFunctionDocumentation()
+ { return "Dokumentation över funktioner"; }
+ QString trVariableDocumentation()
+ { return "Dokumentation över variabler"; }
+ QString trCompounds()
+ { return "Compounds??"; }
+ QString trFiles()
+ { return "Filer"; }
+ QString trGeneratedAt(const char *date,const char *projName)
+ {
+ QString result=(QString)"Skapad "+date;
+ if (projName) result+=(QString)" för "+projName;
+ result+=(QString)" av";
+ return result;
+ }
+ QString trWrittenBy()
+ {
+ return "skriven av";
+ }
+ QString trClassDiagram(const char *clName)
+ {
+ return (QString)"Klass diagram för "+clName;
+ }
+ QString trForInternalUseOnly()
+ { return "Endast för internt bruk."; }
+ QString trReimplementedForInternalReasons()
+ { return "Omskriven av interna orsaker???; "
+ "API:n påverkas inte.";
+ }
+ QString trWarning()
+ { return "Varning"; }
+ QString trBugsAndLimitations()
+ { return "Fel och begränsningar"; }
+ QString trVersion()
+ { return "Version"; }
+ QString trDate()
+ { return "Datum"; }
+ QString trAuthors()
+ { return "Författare"; }
+ QString trReturns()
+ { return "Returnerar"; }
+ QString trSeeAlso()
+ { return "Se även"; }
+ QString trParameters()
+ { return "Parametrar"; }
+ QString trExceptions()
+ { return "Undantag"; }
+ QString trGeneratedBy()
+ { return "Skapad av"; }
+};
+
+#endif
diff --git a/src/unistd.h b/src/unistd.h
new file mode 100644
index 0000000..46a5fbc
--- /dev/null
+++ b/src/unistd.h
@@ -0,0 +1,7 @@
+/* this is a dummy file, that is needed for compiling files that are
+ * generated with flex under Windows 95/NT.
+ */
+#if defined(_MSC_VER)
+#include <io.h>
+#endif
+
diff --git a/src/util.cpp b/src/util.cpp
new file mode 100644
index 0000000..6b4578d
--- /dev/null
+++ b/src/util.cpp
@@ -0,0 +1,2174 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#include <stdlib.h>
+#include <qregexp.h>
+#include <qstring.h>
+#include <ctype.h>
+#include "util.h"
+#include "message.h"
+#include "classdef.h"
+#include "filedef.h"
+#include "doxygen.h"
+#include "scanner.h"
+#include "outputlist.h"
+#include "defargs.h"
+#include "language.h"
+#include "config.h"
+
+// an inheritance tree of depth of 100000 should be enough for everyone :-)
+const int maxInheritanceDepth = 100000;
+
+bool isId(char c)
+{
+ return c=='_' || isalnum(c);
+}
+
+
+// try to determine if this files is a source or a header file by looking
+// at the extension (5 variations are allowed in both upper and lower case)
+// If anyone knows or uses another extension please let me know :-)
+int guessSection(const char *name)
+{
+ QString n=((QString)name).lower();
+ if (n.right(2)==".c" ||
+ n.right(3)==".cc" ||
+ n.right(4)==".cxx" ||
+ n.right(4)==".cpp" ||
+ n.right(4)==".c++"
+ ) return Entry::SOURCE_SEC;
+ if (n.right(2)==".h" ||
+ n.right(3)==".hh" ||
+ n.right(4)==".hxx" ||
+ n.right(4)==".hpp" ||
+ n.right(4)==".h++"
+ ) return Entry::HEADER_SEC;
+ return 0;
+}
+
+
+//QString resolveDefines(const char *n)
+//{
+// return n;
+// if (n)
+// {
+// Define *def=defineDict[n];
+// if (def && def->nargs==0 && !def->definition.isNull())
+// {
+// return def->definition;
+// }
+// return n;
+// }
+// return 0;
+//}
+
+QString resolveTypedefs(const QString &n)
+{
+ QString *subst=typedefDict[n];
+ if (subst && !subst->isNull())
+ {
+ return *subst;
+ }
+ else
+ {
+ return n;
+ }
+}
+
+ClassDef *getClass(const char *name)
+{
+ if (!name) return 0;
+ //QString key=resolveTypedefs(resolveDefines(name));
+ //Define *def=defineDict[key];
+ //if (def && def->nargs==0 && def->definition.length()>0) // normal define
+ // key=def->definition; // use substitution
+
+ return classDict[resolveTypedefs(name)];
+}
+
+QString removeRedundantWhiteSpace(const QString &s)
+{
+ if (s.length()==0) return s;
+ QString result;
+ uint i;
+ for (i=0;i<s.length();i++)
+ {
+ char c=s.at(i);
+ if (c!=' ' ||
+ (i!=0 && i!=s.length()-1 && isId(s.at(i-1)) && isId(s.at(i+1)))
+ )
+ {
+ if ((c=='*' || c=='&') &&
+ result.length()>0 && isId(result.at(result.length()-1))
+ ) result+=' ';
+ result+=c;
+ }
+ }
+ return result;
+}
+
+void writeTemplatePrefix(OutputList &ol,ArgumentList *al)
+{
+ ol.docify("template<");
+ Argument *a=al->first();
+ while (a)
+ {
+ ol.docify(a->type);
+ ol.docify(a->name);
+ if (a->defval.length()!=0)
+ {
+ ol.docify(" = ");
+ ol.docify(a->defval);
+ }
+ a=al->next();
+ if (a) ol.docify(", ");
+ }
+ ol.docify("> ");
+ bool latexEnabled = ol.isEnabled(OutputGenerator::Latex);
+ bool manEnabled = ol.isEnabled(OutputGenerator::Man);
+ if (latexEnabled) ol.disable(OutputGenerator::Latex);
+ if (manEnabled) ol.disable(OutputGenerator::Man);
+ ol.lineBreak();
+ if (latexEnabled) ol.enable(OutputGenerator::Latex);
+ if (manEnabled) ol.enable(OutputGenerator::Man);
+}
+
+QString addTemplateNames(const QString &s,const QString &n,const QString &t)
+{
+ //printf("addTemplateNames(%s)\n",s.data());
+ QString result;
+ QString clRealName=n;
+ int p=0,i;
+ if ((i=clRealName.find('<'))!=-1)
+ {
+ clRealName=clRealName.left(i); // strip template specialization
+ }
+ while ((i=s.find(clRealName,p))!=-1)
+ {
+ result+=s.mid(p,i-p);
+ uint j=clRealName.length()+i;
+ if (s.length()==j || (s.at(j)!='<' && !isId(s.at(j))))
+ { // add template names
+ //printf("Adding %s+%s\n",clRealName.data(),t.data());
+ result+=clRealName+t;
+ }
+ else
+ { // template names already present
+ //printf("Adding %s\n",clRealName.data());
+ result+=clRealName;
+ }
+ p=i+clRealName.length();
+ }
+ result+=s.right(s.length()-p);
+ //printf("result=%s\n",result.data());
+ return result;
+}
+
+static void linkifyText(OutputList &ol,const char *clName,const char *name,const char *text)
+{
+ //printf("class %s name %s Text: %s\n",clName,name,text);
+ QRegExp regExp("[a-z_A-Z0-9:<>]+");
+ QString txtStr=text;
+ OutputList result(&ol);
+ int matchLen;
+ int index=0;
+ int newIndex;
+ int skipIndex=0;
+ // read a word from the text string
+ while ((newIndex=regExp.match(txtStr,index,&matchLen))!=-1)
+ {
+ // add non-word part to the result
+ result.docify(txtStr.mid(skipIndex,newIndex-skipIndex));
+ // get word from string
+ QString word=txtStr.mid(newIndex,matchLen);
+ ClassDef *cd=0;
+ FileDef *fd=0;
+ MemberDef *md=0;
+
+ // check if `word' is a documented class name
+ if (word.length()>0 && word!=name && word!=clName)
+ {
+ if ((cd=getClass(word)))
+ {
+ // add link to the result
+ if (cd->isVisible())
+ {
+ result.writeObjectLink(cd->getReference(),cd->classFile(),0,word);
+ }
+ else
+ {
+ result.docify(word);
+ }
+ }
+ else if (getDefs(word,clName,0,md,cd,fd) && md->hasDocumentation())
+ {
+ if (cd && cd->isVisible() && !md->isFunction()) // word is a member of cd
+ {
+ result.writeObjectLink(cd->getReference(),
+ cd->classFile(),md->anchor(),word);
+ }
+ else if (fd && fd->hasDocumentation()) // word is a global in file fd
+ {
+ result.writeObjectLink(fd->getReference(),
+ fd->diskName(),md->anchor(),word);
+ }
+ else // add word to the result
+ {
+ result.docify(word);
+ }
+ }
+ else // add word to the result
+ {
+ result.docify(word);
+ }
+ }
+ else // add word to the result
+ {
+ result.docify(word);
+ }
+ // set next start point in the string
+ skipIndex=index=newIndex+matchLen;
+ }
+ // add last part of the string to the result.
+ result.docify(txtStr.right(txtStr.length()-skipIndex));
+ //printf("linkify: %s\n",result.data());
+ ol+=result;
+}
+
+static void writeDefArgumentList(OutputList &ol,ClassDef *cd,
+ const QString &scopeName,MemberDef *md)
+{
+ ArgumentList *argList=md->argumentList();
+ if (argList==0) return; // member has no function like argument list
+ ol.docify(" ("); // start argument list
+ Argument *a=argList->first();
+ QString cName;
+ if (cd && cd->templateArguments())
+ {
+ cName=cd->getTemplateNameString();
+ }
+ while (a)
+ {
+ QRegExp re(")(");
+ int vp;
+ if ((vp=a->type.find(re))!=-1) // argument type is a function pointer
+ {
+ QString n=a->type.left(vp);
+ if (cName.length()>0) n=addTemplateNames(n,cd->name(),cName);
+ linkifyText(ol,scopeName,md->name(),n);
+ }
+ else // non-function pointer type
+ {
+ QString n=a->type;
+ if (cName.length()>0) n=addTemplateNames(n,cd->name(),cName);
+ linkifyText(ol,scopeName,md->name(),n);
+ }
+ if (a->name.length()>0) // argument has a name
+ {
+ ol.docify(" ");
+ ol.disable(OutputGenerator::Man);
+ ol.startEmphasis();
+ ol.enable(OutputGenerator::Man);
+ ol.docify(a->name);
+ ol.disable(OutputGenerator::Man);
+ ol.endEmphasis();
+ ol.enable(OutputGenerator::Man);
+ }
+ if (vp!=-1) // write the part of the argument type
+ // that comes after the name
+ {
+ linkifyText(ol,scopeName,md->name(),a->type.right(a->type.length()-vp));
+ }
+ if (a->defval.length()>0) // write the default value
+ {
+ QString n=a->defval;
+ if (cName.length()>0) n=addTemplateNames(n,cd->name(),cName);
+ ol.docify(" = ");
+ linkifyText(ol,scopeName,md->name(),n);
+ }
+ a=argList->next();
+ if (a) ol.docify(", "); // there are more arguments
+ }
+ ol.docify(")"); // end argument list
+ if (argList->constSpecifier)
+ {
+ ol.docify(" const");
+ }
+ if (argList->volatileSpecifier)
+ {
+ ol.docify(" volatile");
+ }
+}
+
+QString argListToString(ArgumentList *al)
+{
+ QString result;
+ if (al==0) return result;
+ Argument *a=al->first();
+ result+="(";
+ while (a)
+ {
+ result+= a->type+" "+a->name;
+ a = al->next();
+ if (a) result+=",";
+ }
+ result+=")";
+ if (al->constSpecifier) result+=" const";
+ if (al->volatileSpecifier) result+=" volatile";
+ return result;
+}
+
+static void writeLink(OutputList &ol,ClassDef *cd,NamespaceDef *nd,
+ FileDef *fd,MemberDef *md,const char *name)
+{
+ if (nd)
+ ol.writeObjectLink(0 /*TODO: references */,nd->namespaceFile(),md->anchor(),name);
+ else if (fd)
+ ol.writeObjectLink(fd->getReference(),fd->diskName(),md->anchor(),name);
+ else
+ ol.writeObjectLink(cd->getReference(),cd->classFile(),md->anchor(),name);
+}
+
+static void warnForUndocumentedMember(MemberDef *md)
+{
+ ClassDef *cd=md->memberClass();
+ FileDef *fd=md->getFileDef();
+ if (cd)
+ {
+ if (!md->hasDocumentation() && md->name() && md->name()[0]!='@')
+ warn("Warning: Member %s of class %s is not documented\n",
+ md->name().data(),cd->name().data());
+ }
+ else if (fd)
+ {
+ if (!md->hasDocumentation() && md->name() && md->name()[0]!='@')
+ warn("Warning: Member %s of file %s is not documented\n",
+ md->name().data(),fd->name().data());
+ }
+}
+
+static bool manIsEnabled;
+
+void startTitle(OutputList &ol)
+{
+ ol.startTitleHead();
+ manIsEnabled=ol.isEnabled(OutputGenerator::Man);
+ if (manIsEnabled) ol.disable(OutputGenerator::Man);
+}
+
+void endTitle(OutputList &ol,const char *name)
+{
+ if (manIsEnabled) ol.enable(OutputGenerator::Man);
+ ol.endTitleHead(name);
+}
+
+void writeQuickLinks(OutputList &ol,bool compact,bool ext)
+{
+ bool manEnabled = ol.isEnabled(OutputGenerator::Man);
+ bool texEnabled = ol.isEnabled(OutputGenerator::Latex);
+ QString extLink,absPath;
+ if (ext) { extLink="_doc:"; absPath="/"; }
+ if (manEnabled) ol.disable(OutputGenerator::Man);
+ if (texEnabled) ol.disable(OutputGenerator::Latex);
+ if (compact) ol.startCenter(); else ol.startItemList();
+ if (documentedGroups>0)
+ {
+ if (!compact) ol.writeListItem();
+ ol.startQuickIndexItem(extLink,absPath+"modules.html");
+ parseDoc(ol,0,0,theTranslator->trModules());
+ ol.endQuickIndexItem();
+ }
+ if (documentedNamespaces>0)
+ {
+ if (!compact) ol.writeListItem();
+ ol.startQuickIndexItem(extLink,absPath+"namespaces.html");
+ parseDoc(ol,0,0,theTranslator->trNamespaces());
+ ol.endQuickIndexItem();
+ }
+ if (hierarchyClasses>0)
+ {
+ if (!compact) ol.writeListItem();
+ ol.startQuickIndexItem(extLink,absPath+"hierarchy.html");
+ parseDoc(ol,0,0,theTranslator->trClassHierarchy());
+ ol.endQuickIndexItem();
+ }
+ if (annotatedClasses>0)
+ {
+ if (!compact) ol.writeListItem();
+ ol.startQuickIndexItem(extLink,absPath+"annotated.html");
+ parseDoc(ol,0,0,theTranslator->trCompoundList());
+ ol.endQuickIndexItem();
+ }
+ if (documentedFiles>0)
+ {
+ if (!compact) ol.writeListItem();
+ ol.startQuickIndexItem(extLink,absPath+"files.html");
+ parseDoc(ol,0,0,theTranslator->trFileList());
+ ol.endQuickIndexItem();
+ }
+ if (includeFiles.count()>0 && verbatimHeaderFlag)
+ {
+ if (!compact) ol.writeListItem();
+ ol.startQuickIndexItem(extLink,absPath+"headers.html");
+ parseDoc(ol,0,0,theTranslator->trHeaderFiles());
+ ol.endQuickIndexItem();
+ }
+ if (documentedMembers>0)
+ {
+ if (!compact) ol.writeListItem();
+ ol.startQuickIndexItem(extLink,absPath+"functions.html");
+ parseDoc(ol,0,0,theTranslator->trCompoundMembers());
+ ol.endQuickIndexItem();
+ }
+ if (documentedFunctions>0)
+ {
+ if (!compact) ol.writeListItem();
+ ol.startQuickIndexItem(extLink,absPath+"globals.html");
+ parseDoc(ol,0,0,theTranslator->trFileMembers());
+ ol.endQuickIndexItem();
+ }
+ if (pageList.count()>0)
+ {
+ if (!compact) ol.writeListItem();
+ ol.startQuickIndexItem(extLink,absPath+"pages.html");
+ parseDoc(ol,0,0,theTranslator->trRelatedPages());
+ ol.endQuickIndexItem();
+ }
+ if (exampleList.count()>0)
+ {
+ if (!compact) ol.writeListItem();
+ ol.startQuickIndexItem(extLink,absPath+"examples.html");
+ parseDoc(ol,0,0,theTranslator->trExamples());
+ ol.endQuickIndexItem();
+ }
+ if (searchEngineFlag)
+ {
+ if (!compact) ol.writeListItem();
+ ol.startQuickIndexItem("_cgi:","");
+ parseDoc(ol,0,0,theTranslator->trSearch());
+ ol.endQuickIndexItem();
+ }
+ if (compact)
+ {
+ ol.endCenter();
+ ol.writeRuler();
+ }
+ else
+ {
+ ol.endItemList();
+ }
+ if (manEnabled) ol.enable(OutputGenerator::Man);
+ if (texEnabled) ol.enable(OutputGenerator::Latex);
+}
+
+void startFile(OutputList &ol,const char *name,const char *title,bool external)
+{
+ ol.startFile(name,title,external);
+ if (!noIndexFlag) writeQuickLinks(ol,TRUE,external);
+}
+
+void endFile(OutputList &ol,bool external)
+{
+ bool latexEnabled = ol.isEnabled(OutputGenerator::Latex);
+ bool manEnabled = ol.isEnabled(OutputGenerator::Man);
+ if (latexEnabled) ol.disable(OutputGenerator::Latex);
+ if (manEnabled) ol.disable(OutputGenerator::Man);
+ ol.writeFooter(0,external); // write the footer
+ if (footerFile.length()==0)
+ {
+ parseDoc(ol,0,0,theTranslator->trGeneratedAt(
+ dateToString(TRUE),
+ projectName
+ ));
+ }
+ ol.writeFooter(1,external); // write the link to the picture
+ if (footerFile.length()==0)
+ {
+ parseDoc(ol,0,0,theTranslator->trWrittenBy());
+ }
+ ol.writeFooter(2,external); // end the footer
+ if (latexEnabled) ol.enable(OutputGenerator::Latex);
+ if (manEnabled) ol.enable(OutputGenerator::Man);
+ ol.endFile();
+}
+
+
+static void writeMemberDef(OutputList &ol, ClassDef *cd, NamespaceDef *nd,
+ FileDef *fd, MemberDef *md)
+{
+ int i,l;
+ bool hasDocs=md->hasDocumentation();
+ if ((!hasDocs && hideMemberFlag) ||
+ (hideMemberFlag &&
+ md->documentation().isEmpty() &&
+ !briefMemDescFlag &&
+ !repeatBriefFlag
+ )
+ ) return;
+ QString type=md->typeString();
+ QRegExp r("@[0-9]+");
+ if ((i=r.match(type,0,&l))==-1 || !md->enumUsed())
+ {
+ // strip `static' keyword from type
+ if (type.left(7)=="static ") type=type.right(type.length()-7);
+ // strip `friend' keyword from type
+ if (type.left(7)=="friend ") type=type.right(type.length()-7);
+
+ if (genTagFile.length()>0)
+ {
+ tagFile << md->name() << " " << md->anchor() << " \""
+ << md->argsString() << "\"\n";
+ }
+
+ QString cname;
+ if (cd) cname=cd->name();
+ else if (nd) cname=nd->name();
+ else if (fd) cname=fd->name();
+
+ // If there is no detailed description we need to write the anchor here.
+ if (!md->detailsAreVisible() && !extractAllFlag)
+ {
+ ol.writeDoxyAnchor(cname,md->anchor(),md->name());
+ ol.addToIndex(md->name(),cname);
+ ol.addToIndex(cname,md->name());
+ ol.docify("\n");
+ }
+
+ ol.startMemberItem();
+
+ // write type
+ if (i!=-1)
+ {
+ QString newType = type.left(i) + " { ... } " +
+ type.right(type.length()-i-l);
+ type = newType;
+ ol.docify(type);
+ }
+ else
+ {
+ ol.docify(type);
+ }
+ QString name=md->name().copy();
+ if (type.length()>0) ol.writeString(" ");
+
+ // write name
+ if ( extractAllFlag ||
+ (md->briefDescription().isEmpty() || !briefMemDescFlag) &&
+ (!md->documentation().isEmpty() ||
+ (!md->briefDescription().isEmpty() &&
+ !briefMemDescFlag &&
+ repeatBriefFlag
+ )
+ )
+ )
+ {
+ //printf("writeLink %s->%d\n",name.data(),md->hasDocumentation());
+ writeLink(ol,cd,nd,fd,md,name);
+ }
+ else // there is a brief member description and brief member
+ // descriptions are enabled or there is no detailed description.
+ {
+ ol.writeBoldString(name);
+ }
+
+ if (md->argsString())
+ {
+ ol.writeString(" ");
+ ol.docify(md->argsString());
+ }
+
+ if (md->excpString())
+ {
+ ol.writeString(" ");
+ ol.docify(md->excpString());
+ }
+
+ ol.endMemberItem();
+
+ // write brief description
+ if (!md->briefDescription().isEmpty() && briefMemDescFlag)
+ {
+ ol.startMemberDescription();
+ parseDoc(ol,cname,md->name(),md->briefDescription());
+ if (!md->documentation().isEmpty())
+ {
+ ol.disableAllBut(OutputGenerator::Html);
+ ol.endEmphasis();
+ ol.docify(" ");
+ ol.startTextLink(0,md->anchor());
+ //ol.writeObjectLink(0,0,md->anchor()," More...");
+ parseDoc(ol,0,0,theTranslator->trMore());
+ ol.endTextLink();
+ ol.startEmphasis();
+ ol.enableAll();
+ }
+ ol.endMemberDescription();
+ ol.newParagraph();
+ }
+ }
+ warnForUndocumentedMember(md);
+}
+
+
+// write a list in HTML of all members of a certain category
+// cd!=0 => ml is a list of class members
+// fd!=0 => ml is a list of file `members'
+void writeMemberDecs(OutputList &ol,ClassDef *cd,NamespaceDef *nd, FileDef *fd,
+ const char *title, const char *subtitle,MemberList *ml)
+{
+ ml->countDecMembers();
+ if (ml->totalCount()==0) return;
+ if (title)
+ {
+ ol.startMemberHeader();
+ parseDoc(ol,0,0,title);
+ ol.endMemberHeader();
+ }
+ if (subtitle) ol.writeString(subtitle);
+
+
+ if (!fd && !nd) ol.startMemberList();
+ MemberDef *md;
+
+ if (fd && ml->defineCount()>0)
+ {
+ ol.startMemberHeader();
+ parseDoc(ol,0,0,theTranslator->trDefines());
+ ol.endMemberHeader();
+ ol.startMemberList();
+ MemberListIterator mli(*ml);
+ for ( ; (md=mli.current()); ++mli )
+ {
+ if (md->isDefine() &&
+ (md->argsString() || md->hasDocumentation() || extractAllFlag)
+ )
+ writeMemberDef(ol,cd,nd,fd,md);
+ }
+ ol.endMemberList();
+ }
+
+ if ((fd || nd) && ml->protoCount()>0)
+ {
+ ol.startMemberHeader();
+ parseDoc(ol,0,0,theTranslator->trFuncProtos());
+ ol.startMemberList();
+ MemberListIterator mli(*ml);
+ for ( ; (md=mli.current()); ++mli )
+ {
+ if (md->isPrototype()) writeMemberDef(ol,cd,nd,fd,md);
+ }
+ ol.endMemberList();
+ }
+
+ if (ml->typedefCount()>0)
+ {
+ if (fd || nd)
+ {
+ ol.startMemberHeader();
+ parseDoc(ol,0,0,theTranslator->trTypedefs());
+ ol.endMemberHeader();
+ //ol.writeMemberHeader("Typedefs");
+ ol.startMemberList();
+ }
+ MemberListIterator mli(*ml);
+ for ( ; (md=mli.current()) ; ++mli )
+ {
+ if (md->isTypedef()) writeMemberDef(ol,cd,nd,fd,md);
+ }
+ if (fd || nd) ol.endMemberList();
+ }
+
+ // write enums
+ if (ml->enumCount()>0)
+ {
+ if (fd || nd)
+ {
+ ol.startMemberHeader();
+ parseDoc(ol,0,0,theTranslator->trEnumerations());
+ ol.endMemberHeader();
+ ol.startMemberList();
+ }
+ MemberListIterator mli(*ml);
+ for ( ; (md=mli.current()) ; ++mli )
+ {
+ bool hasDocs=md->hasDocumentation();
+ QString type=md->typeString();
+ type=type.stripWhiteSpace();
+ if (md->isEnumerate() && (hasDocs || !hideMemberFlag))
+ {
+ // see if there are any documented enum values
+ // we need this info to decide if we need to generate a link.
+ QList<MemberDef> *fmdl=md->enumFieldList();
+ int documentedEnumValues=0;
+ if (fmdl)
+ {
+ MemberDef *fmd=fmdl->first();
+ while (fmd)
+ {
+ if (fmd->hasDocumentation()) documentedEnumValues++;
+ fmd=fmdl->next();
+ }
+ }
+ if (documentedEnumValues>0) md->setDocumentedEnumValues(TRUE);
+
+ if (!hideMemberFlag || // do not hide undocumented members or
+ !md->documentation().isEmpty() || // member has detailed descr. or
+ documentedEnumValues>0 || // member has documented enum vales.
+ briefMemDescFlag || // brief descr. is shown or
+ repeatBriefFlag // brief descr. is repeated.
+ )
+ {
+ OutputList typeDecl(&ol);
+ QString name=md->name().copy();
+ int i=name.findRev("::");
+ if (i!=-1) name=name.right(name.length()-i-2); // strip scope
+ if (name[0]!='@') // not an anonymous enum
+ {
+ if (extractAllFlag ||
+ (md->briefDescription().isEmpty() || !briefMemDescFlag) &&
+ (!md->documentation().isEmpty() || documentedEnumValues>0 ||
+ (!md->briefDescription().isEmpty() &&
+ !briefMemDescFlag &&
+ repeatBriefFlag
+ )
+ )
+ )
+ {
+ if (genTagFile.length()>0)
+ tagFile << md->name() << " " << md->anchor()
+ << " \"" << md->argsString() << "\"";
+ writeLink(typeDecl,cd,nd,fd,md,name);
+ }
+ else
+ {
+ typeDecl.writeBoldString(name);
+ }
+ typeDecl.writeChar(' ');
+ }
+
+ typeDecl.docify("{ ");
+ if (fmdl)
+ {
+ MemberDef *fmd=fmdl->first();
+ while (fmd)
+ {
+ if (fmd->hasDocumentation())
+ {
+ if (genTagFile.length()>0)
+ tagFile << fmd->name() << " " << fmd->anchor()
+ << " \"" << fmd->argsString() << "\"";
+ writeLink(typeDecl,cd,nd,fd,fmd,fmd->name());
+ }
+ else
+ typeDecl.writeBoldString(fmd->name());
+ fmd=fmdl->next();
+ if (fmd) typeDecl.writeString(", ");
+ typeDecl.disable(OutputGenerator::Man);
+ typeDecl.writeString("\n"); // to prevent too long lines in LaTeX
+ typeDecl.enable(OutputGenerator::Man);
+ }
+ }
+ typeDecl.docify(" }");
+ md->setEnumDecl(typeDecl);
+ int enumVars=0;
+ MemberListIterator vmli(*ml);
+ MemberDef *vmd;
+ if (name[0]=='@') // anonymous enum => append variables
+ {
+ for ( ; (vmd=vmli.current()) ; ++vmli)
+ {
+ QString vtype=vmd->typeString();
+ if ((vtype.find(name))!=-1) enumVars++;
+ }
+ }
+ if (enumVars==0) // no variable of this enum type
+ {
+ ol.startMemberItem();
+ ol.writeString("enum ");
+ ol+=typeDecl;
+ ol.endMemberItem();
+ //QString brief=md->briefDescription();
+ //brief=brief.stripWhiteSpace();
+ if (!md->briefDescription().isEmpty() && briefMemDescFlag)
+ {
+ ol.startMemberDescription();
+ parseDoc(ol,cd?cd->name().data():0,
+ md->name().data(),md->briefDescription());
+ if (!md->documentation().isEmpty() || documentedEnumValues>0)
+ {
+ ol.disableAllBut(OutputGenerator::Html);
+ ol.endEmphasis();
+ ol.docify(" ");
+ ol.startTextLink(0,md->anchor());
+ //ol.writeObjectLink(0,0,md->anchor()," More...");
+ parseDoc(ol,0,0,theTranslator->trMore());
+ ol.endTextLink();
+ ol.startEmphasis();
+ ol.enableAll();
+ }
+ ol.endMemberDescription();
+ ol.disable(OutputGenerator::Man);
+ ol.newParagraph();
+ ol.enable(OutputGenerator::Man);
+ }
+ }
+ warnForUndocumentedMember(md);
+ }
+ } // md->isEnumerate()
+ } // enum loop
+ if (fd || nd) ol.endMemberList();
+ } // write enums
+
+ // write functions
+ if (ml->funcCount()>0)
+ {
+ if (fd || nd)
+ {
+ ol.startMemberHeader();
+ parseDoc(ol,0,0,theTranslator->trFunctions());
+ ol.endMemberHeader();
+ ol.startMemberList();
+ }
+ MemberListIterator mli(*ml);
+ for ( ; (md=mli.current()) ; ++mli )
+ {
+ if ( md->isFunction() || md->isSignal() ||
+ md->isSlot())
+ writeMemberDef(ol,cd,nd,fd,md);
+ }
+ if (fd || nd) ol.endMemberList();
+ }
+
+ if (ml->friendCount()>0)
+ {
+ MemberListIterator mli(*ml);
+ for ( ; (md=mli.current()) ; ++mli )
+ {
+ if ( md->isFriend())
+ {
+ QString type=md->typeString();
+ //printf("Friend: type=%s name=%s\n",type.data(),md->name().data());
+ if (md->hasDocumentation() && type!="friend class")
+ {
+ writeMemberDef(ol,cd,nd,fd,md);
+ }
+ else // friend is undocumented as a member but it is a class,
+ // so generate a link to the class if that is documented.
+ {
+ ClassDef *cd=getClass(md->name());
+ if (md->hasDocumentation()) // friend is documented
+ {
+ ol.startMemberItem();
+ ol.docify("class ");
+ ol.writeObjectLink(0,0,md->anchor(),md->name());
+ ol.endMemberItem();
+ }
+ else if (cd && cd->isVisibleExt()) // class is documented
+ {
+ ol.startMemberItem();
+ ol.docify("class ");
+ ol.writeObjectLink(cd->getReference(),cd->classFile(),0,cd->name());
+ ol.endMemberItem();
+ }
+ else if (!hideMemberFlag) // no documentation
+ {
+ ol.startMemberItem();
+ ol.docify("class ");
+ ol.writeBoldString(md->name());
+ ol.endMemberItem();
+ }
+ }
+ }
+ }
+ }
+
+ // write variables
+ if (ml->varCount()>0)
+ {
+ if (fd || nd)
+ {
+ ol.startMemberHeader();
+ parseDoc(ol,0,0,theTranslator->trVariables());
+ ol.endMemberHeader();
+ ol.startMemberList();
+ }
+ MemberListIterator mli(*ml);
+ for ( ; (md=mli.current()) ; ++mli )
+ {
+ if (md->isVariable()) writeMemberDef(ol,cd,nd,fd,md);
+ }
+ if (fd || nd) ol.endMemberList();
+ }
+
+ if (!fd && !nd) { ol.endMemberList(); ol.writeChar('\n'); }
+}
+
+// compute the HTML anchors for a list of members
+void setAnchors(char id,MemberList *ml)
+{
+ int count=0;
+ MemberDef *md=ml->first();
+ while (md)
+ {
+ QString anchor;
+ anchor.sprintf("%c%d",id,count++);
+ //printf("Member %s anchor %s\n",md->name(),anchor.data());
+ md->setAnchor(anchor);
+ md=ml->next();
+ }
+}
+
+void writeMemberDocs(OutputList &ol,MemberList *ml,const char *scopeName,
+ MemberDef::MemberType m)
+{
+ MemberListIterator mli(*ml);
+ MemberDef *md;
+ for ( ; (md=mli.current()) ; ++mli)
+ {
+ bool hasDocs = md->detailsAreVisible();
+ // !md->documentation().isEmpty() || // member has a detailed description
+ // (md->memberType()==MemberDef::Enumeration && // or member is an enum and
+ // md->hasDocumentedEnumValues() // one of its values is documented
+ // ) || // or
+ // (!md->briefDescription().isEmpty() && // member has brief description and
+ // !briefMemDescFlag && // brief description not shown earlier and
+ // repeatBriefFlag // brief description should be repeated.
+ // );
+ if (md->memberType()==m && // filter member type
+ (extractAllFlag || hasDocs)
+ )
+ {
+ if (extractAllFlag && !hasDocs)
+ {
+ ol.disable(OutputGenerator::Latex); // Latex cannot insert a pagebreak
+ // if there are a lot of empty sections,
+ // so we disable LaTeX for all empty
+ // sections even if extractAllFlag is enabled
+ }
+ QString cname;
+ NamespaceDef *nd=md->getNamespace();
+ ClassDef *cd=md->memberClass();
+ FileDef *fd=md->getFileDef();
+ if (cd) cname=cd->name();
+ else if (nd) cname=nd->name();
+ else if (fd) cname=fd->name();
+ // get member name
+ QString doxyName=md->name().copy();
+ // prepend scope if there is any (TODO: prepend namespace scope as well)
+ if (scopeName) doxyName.prepend((QString)scopeName+"::");
+
+ QString def = md->definition();
+ if (md->isEnumerate()) def.prepend("enum ");
+ MemberDef *smd;
+ if (md->isEnumValue() && def[0]=='@') def = def.right(def.length()-2);
+ int i=0,l,dummy;
+ QRegExp r("@[0-9]+");
+ if (md->isEnumerate() && r.match(def,0,&l)!=-1) continue;
+ if (md->isEnumValue() && (smd = md->getEnumScope())
+ && r.match(smd->name(),0,&dummy)==-1) continue;
+ if ((md->isVariable() || md->isTypedef()) && (i=r.match(def,0,&l))!=-1)
+ {
+ // find enum type an insert it in the definition
+ MemberListIterator vmli(*ml);
+ MemberDef *vmd;
+ bool found=FALSE;
+ for ( ; (vmd=vmli.current()) && !found ; ++vmli)
+ {
+ if (vmd->isEnumerate() && def.mid(i,l)==vmd->name())
+ {
+ ol.startMemberDoc(cname,md->name(),md->anchor());
+ ol.writeDoxyAnchor(cname,md->anchor(),doxyName);
+ linkifyText(ol,scopeName,md->name(),def.left(i));
+ ol+=*vmd->enumDecl();
+ linkifyText(ol,scopeName,md->name(),def.right(def.length()-i-l));
+ found=TRUE;
+ }
+ }
+ if (!found) // anonymous compound
+ {
+ ol.startMemberDoc(cname,md->name(),md->anchor());
+ ol.writeDoxyAnchor(cname,md->anchor(),doxyName);
+ linkifyText(ol,scopeName,md->name(),def.left(i));
+ ol.docify(" { ... } ");
+ linkifyText(ol,scopeName,md->name(),def.right(def.length()-i-l));
+ }
+ }
+ else
+ {
+ ol.startMemberDoc(cname,md->name(),md->anchor());
+ ol.writeDoxyAnchor(cname,md->anchor(),doxyName);
+ ArgumentList *al=0;
+ if (cd && (!md->isRelated() || !md->templateArguments()) &&
+ (al=cd->templateArguments())) // class template prefix
+ {
+ writeTemplatePrefix(ol,al);
+ }
+ if (al && md->templateArguments()) ol.docify(" ");
+ al=md->templateArguments();
+ if (al) // function template prefix
+ {
+ writeTemplatePrefix(ol,al);
+ }
+ if (cd && cd->templateArguments())
+ {
+ // add template name lists to all occurrences of the class name.
+ def=addTemplateNames(def,cd->name(),cd->getTemplateNameString());
+ }
+ linkifyText(ol,scopeName,md->name(),def);
+ writeDefArgumentList(ol,cd,scopeName,md);
+ if (md->excpString())
+ {
+ ol.docify(" ");
+ linkifyText(ol,scopeName,md->name(),md->excpString());
+ }
+ }
+
+ Specifier virt=md->virtualness();
+ MemberDef *rmd=md->reimplements();
+ while (rmd && virt==Normal)
+ {
+ virt = rmd->virtualness()==Normal ? Normal : Virtual;
+ rmd = rmd->reimplements();
+ }
+
+ if (md->isStatic() || md->protection()!=Public ||
+ virt!=Normal || md->isSignal() || md->isFriend() ||
+ md->isRelated() || md->isSlot()
+ )
+ {
+ // write the member specifier list
+ ol.writeLatexSpacing();
+ ol.startTypewriter();
+ ol.docify(" [");
+ QStrList sl;
+ if (md->isFriend()) sl.append("friend");
+ else if (md->isRelated()) sl.append("related");
+ else
+ {
+ if (md->isStatic()) sl.append("static");
+ if (md->protection()==Protected) sl.append("protected");
+ else if (md->protection()==Private) sl.append("private");
+ if (virt==Virtual) sl.append("virtual");
+ else if (virt==Pure) sl.append("pure virtual");
+ if (md->isSignal()) sl.append("signal");
+ if (md->isSlot()) sl.append("slot");
+ }
+ const char *s=sl.first();
+ while (s)
+ {
+ ol.docify(s);
+ s=sl.next();
+ if (s) ol.docify(", ");
+ }
+ ol.docify("]");
+ ol.endTypewriter();
+ }
+ ol.endMemberDoc();
+ ol.startIndent();
+ ol.newParagraph();
+
+ if (!md->briefDescription().isEmpty() &&
+ (repeatBriefFlag ||
+ (!briefMemDescFlag && md->documentation().isEmpty())
+ )
+ )
+ {
+ parseDoc(ol,scopeName,md->name(),md->briefDescription());
+ ol.newParagraph();
+ }
+ if (!md->documentation().isEmpty())
+ {
+ parseDoc(ol,scopeName,md->name(),md->documentation()+"\n");
+ }
+
+ if (md->isEnumerate())
+ {
+ bool first=TRUE;
+ MemberList *fmdl=md->enumFieldList();
+ if (fmdl)
+ {
+ MemberDef *fmd=fmdl->first();
+ while (fmd)
+ {
+ if (fmd->hasDocumentation())
+ {
+ if (first)
+ {
+ ol.newParagraph();
+ ol.startBold();
+ parseDoc(ol,0,0,theTranslator->trEnumerationValues());
+ //ol.writeBoldString("Enumeration values:");
+ ol.docify(":");
+ ol.endBold();
+ ol.startMemberList();
+ }
+ ol.writeDoxyAnchor(cname,fmd->anchor(),fmd->name());
+ ol.addToIndex(fmd->name(),cname);
+ ol.addToIndex(cname,fmd->name());
+ ol.writeListItem();
+ first=FALSE;
+ ol.startBold();
+ ol.docify(fmd->name());
+ ol.endBold();
+ ol.newParagraph();
+
+ if (!fmd->briefDescription().isEmpty())
+ {
+ parseDoc(ol,scopeName,fmd->name(),fmd->briefDescription());
+ ol.newParagraph();
+ }
+ if (!fmd->documentation().isEmpty())
+ {
+ parseDoc(ol,scopeName,fmd->name(),fmd->documentation()+"\n");
+ }
+ ol.disable(OutputGenerator::Man);
+ ol.newParagraph();
+ ol.enable(OutputGenerator::Man);
+ }
+ fmd=fmdl->next();
+ }
+ }
+ if (!first) { ol.endMemberList(); ol.writeChar('\n'); }
+ }
+
+ MemberDef *bmd=md->reimplements();
+ if (bmd)
+ {
+ if (virt!=Normal) // search for virtual member of the deepest base class
+ {
+ MemberDef *lastBmd=bmd;
+ while (lastBmd)
+ {
+ if (lastBmd->virtualness()!=Normal) bmd=lastBmd;
+ lastBmd=lastBmd->reimplements();
+ }
+ }
+ // write class that contains a member that is reimplemented by this one
+ ClassDef *bcd = bmd->memberClass();
+ ol.newParagraph();
+ parseDoc(ol,0,0,theTranslator->trReimplementedFrom());
+ //ol.writeString("Reimplemented from ");
+ ol.docify(" ");
+ if (bmd->hasDocumentation())
+ {
+ ol.writeObjectLink(bcd->getReference(),bcd->classFile(),
+ bmd->anchor(),bcd->name());
+ if (
+ !bcd->isReference() &&
+ //(bcd->hasDocumentation() || !hideClassFlag) &&
+ //(bcd->protection()!=Private || extractPrivateFlag)
+ bcd->isVisible()
+ /*&& bmd->detailsAreVisible()*/
+ ) ol.writePageRef(bcd->name(),bmd->anchor());
+ }
+ else
+ {
+ ol.writeObjectLink(bcd->getReference(),bcd->classFile(),
+ 0,bcd->name());
+ if (
+ !bcd->isReference() &&
+ //(bcd->hasDocumentation() || !hideClassFlag) &&
+ //(bcd->protection()!=Private || extractPrivateFlag)
+ bcd->isVisible()
+ ) ol.writePageRef(bcd->name(),0);
+ }
+ ol.writeString(".");
+ }
+ MemberList *bml=md->reimplementedBy();
+ int count;
+ if (bml && (count=bml->count())>0)
+ {
+ // write the list of classes that overwrite this member
+ ol.newParagraph();
+ parseDoc(ol,0,0,theTranslator->trReimplementedIn());
+ //ol.writeString("Reimplemented in ");
+ ol.docify(" ");
+ bmd=bml->first();
+ while (bmd)
+ {
+ ClassDef *bcd = bmd->memberClass();
+ if (bmd->hasDocumentation())
+ {
+ ol.writeObjectLink(bcd->getReference(),bcd->classFile(),
+ bmd->anchor(),bcd->name());
+ if (
+ !bcd->isReference() &&
+ //(bcd->hasDocumentation() || !hideClassFlag) &&
+ //(bcd->protection()!=Private || extractPrivateFlag)
+ bcd->isVisible()
+ /*&& bmd->detailsAreVisible()*/
+ ) ol.writePageRef(bcd->name(),bmd->anchor());
+ }
+ else
+ {
+ ol.writeObjectLink(bcd->getReference(),bcd->classFile(),
+ 0,bcd->name());
+ if (
+ !bcd->isReference() &&
+ //(bcd->hasDocumentation() || !hideClassFlag) &&
+ //(bcd->protection()!=Private || extractPrivateFlag)
+ bcd->isVisible()
+ ) ol.writePageRef(bcd->name(),0);
+ }
+ bmd=bml->next();
+ if (bmd)
+ {
+ if (bml->at()==count-1)
+ //ol.writeString(" and ");
+ parseDoc(ol,0,0," "+theTranslator->trAnd()+" ");
+ else
+ ol.writeString(", ");
+ }
+ }
+ ol.writeString(".");
+ }
+ // write the list of examples that use this member
+ if (md->hasExamples())
+ {
+ ol.startDescList();
+ ol.startBold();
+ parseDoc(ol,0,0,theTranslator->trExamples()+": ");
+ //ol.writeBoldString("Examples: ");
+ ol.endBold();
+ ol.endDescTitle();
+ ol.writeDescItem();
+ md->writeExample(ol);
+ //ol.endDescItem();
+ ol.endDescList();
+ }
+ ol.endIndent();
+ // enable LaTeX again
+ if (extractAllFlag && !hasDocs) ol.enable(OutputGenerator::Latex);
+
+ }
+ }
+}
+
+//----------------------------------------------------------------------------
+// read a file with `name' to a string.
+
+QString fileToString(const char *name)
+{
+ if (name==0 || name[0]==0) return 0;
+ QFileInfo fi(name);
+ if (!fi.exists() || !fi.isFile())
+ {
+ err("Error: file `%s' not found\n",name);
+ exit(1);
+ }
+ QFile f(name);
+ if (!f.open(IO_ReadOnly))
+ {
+ err("Error: cannot open file `%s'\n",name);
+ exit(1);
+ }
+ int fsize=fi.size();
+ QString contents(fsize+1);
+ f.readBlock(contents.data(),fsize);
+ contents[fsize]='\0';
+ f.close();
+ return contents;
+}
+
+QString dateToString(bool includeTime)
+{
+ if (includeTime)
+ {
+ return QDateTime::currentDateTime().toString();
+ }
+ else
+ {
+ const QDate &d=QDate::currentDate();
+ QString result;
+ result.sprintf("%d %s %d",
+ d.day(),
+ d.monthName(d.month()),
+ d.year());
+ return result;
+ }
+ //QDate date=dt.date();
+ //QTime time=dt.time();
+ //QString dtString;
+ //dtString.sprintf("%02d:%02d, %04d/%02d/%02d",
+ // time.hour(),time.minute(),date.year(),date.month(),date.day());
+ //return dtString;
+}
+
+
+//----------------------------------------------------------------------
+// recursive function that returns the number of branches in the
+// inheritance tree that the base class `bcd' is below the class `cd'
+
+static int minClassDistance(ClassDef *cd,ClassDef *bcd,int level=0)
+{
+ if (cd==bcd) return level;
+ BaseClassListIterator bcli(*cd->baseClasses());
+ int m=maxInheritanceDepth;
+ for ( ; bcli.current() ; ++bcli)
+ {
+ m=QMIN(minClassDistance(bcli.current()->classDef,bcd,level+1),m);
+ }
+ return m;
+}
+
+//static void printArgList(ArgumentList *al)
+//{
+// if (al==0) return;
+// ArgumentListIterator ali(*al);
+// Argument *a;
+// printf("(");
+// for (;(a=ali.current());++ali)
+// {
+// printf("t=`%s' n=`%s' v=`%s' ",a->type.data(),a->name.length()>0?a->name.data():"",a->defval.length()>0?a->defval.data():"");
+// }
+// printf(")");
+//}
+
+// strip any template specifiers that follow className in string s
+static QString trimTemplateSpecifiers(const QString &className,const QString &s)
+{
+ // first we resolve any defines
+ //int i=0,p,l;
+ //QString result;
+ //QRegExp r("[A-Z_a-z][A-Z_a-z0-9]*");
+ //while ((p=r.match(s,i,&l))!=-1)
+ //{
+ // if (p>i) result+=s.mid(i,p-i);
+ // result+=resolveDefines(s.mid(p,l));
+ // i=p+l;
+ //}
+ //if (i<(int)s.length()) result+=s.mid(i,s.length()-i);
+
+ // We strip the template arguments following className (if any)
+ QString result=s.copy();
+ int l=className.length();
+ if (l>0) // there is a class name
+ {
+ int i,p=0;
+ while ((i=result.find(className,p))!=-1) // class name is in the argument type
+ {
+ uint s=i+l;
+ if (s<result.length() && result.at(s)=='<') // class has template args
+ {
+ int b=1;
+ uint e=s+1;
+ while (b>0 && e<result.length()) // find matching >
+ {
+ if (result.at(e)=='<') b++;
+ else if (result.at(e)=='>') b--;
+ e++;
+ }
+ // remove template argument
+ result=result.left(s)+result.right(result.length()-e);
+ if (result.length()>s && (result.at(s)=='*' || result.at(s)=='&'))
+ {
+ // insert a space to keep the argument in the canonical form
+ result=result.left(s)+" "+result.right(result.length()-s);
+ }
+ }
+ p=i+l;
+ }
+ }
+ return result;
+}
+
+// removes the (one and only) occurrence of name:: from s.
+static QString trimScope(const QString &name,const QString &s)
+{
+ int spos;
+ spos=s.find(name+"::");
+ if (spos!=-1)
+ {
+ return s.left(spos)+s.right(s.length()-spos-name.length()-2);
+ }
+ return s;
+}
+
+static QString trimBaseClassScope(BaseClassList *bcl,const QString &s)
+{
+ BaseClassListIterator bcli(*bcl);
+ BaseClassDef *bcd;
+ for (;(bcd=bcli.current());++bcli)
+ {
+ ClassDef *cd=bcd->classDef;
+ int spos=s.find(cd->name());
+ if (spos!=-1)
+ {
+ return s.left(spos)+s.right(
+ s.length()-spos-cd->name().length()-2
+ );
+ }
+ if (cd->baseClasses()->count()>0)
+ trimBaseClassScope(cd->baseClasses(),s);
+ }
+ return s;
+}
+
+//----------------------------------------------------------------------
+// Matches the arguments list srcAl with the argument list dstAl
+// Returns TRUE if the argument lists are equal. Two argument list are
+// considered equal if the number of arguments is equal and the types of all
+// arguments are equal. Furthermore the const and volatile specifiers
+// stored in the list should be equal.
+
+bool matchArguments(ArgumentList *srcAl,ArgumentList *dstAl,
+ const char *cl,const char *ns)
+{
+ QString className=cl;
+ QString namespaceName=ns;
+ //printf("matchArguments(%s,%s) className=%s namespaceName=%s\n",
+ // srcAl ? argListToString(srcAl).data() : "",
+ // dstAl ? argListToString(dstAl).data() : "",
+ // cl,ns);
+ if (srcAl==0 || dstAl==0)
+ {
+ return srcAl==dstAl; // at least one of the members is not a function
+ }
+ if ( srcAl->count()==0 && dstAl->count()==1 &&
+ dstAl->getFirst()->type=="void" )
+ { // special case for finding match between func() and func(void)
+ Argument *a=new Argument;
+ a->type = "void";
+ srcAl->append(a);
+ }
+ if ( dstAl->count()==0 && srcAl->count()==1 &&
+ srcAl->getFirst()->type=="void" )
+ { // special case for finding match between func(void) and func()
+ Argument *a=new Argument;
+ a->type = "void";
+ dstAl->append(a);
+ return TRUE;
+ }
+ if (srcAl->count() != dstAl->count())
+ {
+ return FALSE; // different number of arguments -> no match
+ }
+ if (srcAl->constSpecifier != dstAl->constSpecifier)
+ {
+ return FALSE; // one member is const, the other not -> no match
+ }
+ if (srcAl->volatileSpecifier != dstAl->volatileSpecifier)
+ {
+ return FALSE; // one member is volatile, the other not -> no match
+ }
+
+ // so far the argument list could match, so we need to compare the types of
+ // all arguments.
+ ArgumentListIterator srcAli(*srcAl),dstAli(*dstAl);
+ Argument *srcA,*dstA;
+ for (;(srcA=srcAli.current(),dstA=dstAli.current());++srcAli,++dstAli)
+ {
+ QString srcAType=trimTemplateSpecifiers(className,srcA->type);
+ QString dstAType=trimTemplateSpecifiers(className,dstA->type);
+
+ if (srcAType!=dstAType) // check if the argument only differs on name
+ {
+ //printf("`%s' <=> `%s'\n",srcAType.data(),dstAType.data());
+
+ QString srcScope;
+ QString dstScope;
+
+ // strip redundant scope specifiers
+ if (!className.isEmpty())
+ {
+ srcAType=trimScope(className,srcAType);
+ dstAType=trimScope(className,dstAType);
+ ClassDef *cd=getClass(className);
+ if (cd->baseClasses()->count()>0)
+ {
+ srcAType=trimBaseClassScope(cd->baseClasses(),srcAType);
+ dstAType=trimBaseClassScope(cd->baseClasses(),dstAType);
+ }
+ }
+ if (!namespaceName.isEmpty())
+ {
+ srcAType=trimScope(namespaceName,srcAType);
+ dstAType=trimScope(namespaceName,dstAType);
+ }
+
+ //printf("`%s' <=> `%s'\n",srcAType.data(),dstAType.data());
+ uint srcPos=0,dstPos=0;
+ bool equal=TRUE;
+ while (srcPos<srcAType.length() && dstPos<dstAType.length() && equal)
+ {
+ equal=srcAType.at(srcPos)==dstAType.at(dstPos);
+ if (equal) srcPos++,dstPos++;
+ }
+ if (srcPos<srcAType.length() && dstPos<dstAType.length())
+ {
+ // if nothing matches or the match ends in the middle or at the
+ // end of a string then there is no match
+ //if (srcPos==0 || isalnum(srcAType.at(srcPos-1)) ||
+ // dstPos==0 || isalnum(dstAType.at(dstPos-1))) { printf("No match1\n"); return FALSE; }
+ int srcStart=srcPos;
+ int dstStart=dstPos;
+ if (srcPos==0 || dstPos==0) return FALSE;
+ if (isId(srcAType.at(srcPos)) && isId(dstAType.at(dstPos)))
+ {
+ // check if a name if already found -> if no then there is no match
+ if (srcA->name.length()>0 || dstA->name.length()>0) return FALSE;
+ while (srcPos<srcAType.length() && isId(srcAType.at(srcPos))) srcPos++;
+ while (dstPos<dstAType.length() && isId(dstAType.at(dstPos))) dstPos++;
+ if (srcPos<srcAType.length() || dstPos<dstAType.length()) return FALSE;
+ // find the start of the name
+ while (srcStart>=0 && isId(srcAType.at(srcStart))) srcStart--;
+ while (dstStart>=0 && isId(dstAType.at(dstStart))) dstStart--;
+ if (srcStart>0) // move the name from the type to the name field
+ {
+ srcA->name=srcAType.right(srcAType.length()-srcStart-1);
+ srcA->type=srcAType.left(srcStart+1).stripWhiteSpace();
+ }
+ if (dstStart>0) // move the name from the type to the name field
+ {
+ dstA->name=dstAType.right(dstAType.length()-dstStart-1);
+ dstA->type=dstAType.left(dstStart+1).stripWhiteSpace();
+ }
+ }
+ else
+ {
+ // otherwise we assume that a name starts at the current position.
+ while (srcPos<srcAType.length() && isId(srcAType.at(srcPos))) srcPos++;
+ while (dstPos<dstAType.length() && isId(dstAType.at(dstPos))) dstPos++;
+ // if nothing more follows for both types then we assume we have
+ // found a match. Note that now `signed int' and `signed' match, but
+ // seeing that int is not a name can only be done by looking at the
+ // semantics.
+
+ if (srcPos!=srcAType.length() || dstPos!=dstAType.length()) { return FALSE; }
+ dstA->name=dstAType.right(dstAType.length()-dstStart);
+ dstA->type=dstAType.left(dstStart).stripWhiteSpace();
+ srcA->name=srcAType.right(dstAType.length()-srcStart);
+ srcA->type=srcAType.left(srcStart).stripWhiteSpace();
+ }
+ }
+ else if (dstPos<dstAType.length())
+ {
+ if (!isspace(dstAType.at(dstPos))) // maybe the names differ
+ {
+ int startPos=dstPos;
+ while (dstPos<dstAType.length() && isId(dstAType.at(dstPos))) dstPos++;
+ if (dstPos!=dstAType.length()) return FALSE; // more than a difference in name -> no match
+ while (startPos>=0 && isId(dstAType.at(startPos))) startPos--;
+ if (startPos>0)
+ {
+ dstA->name=dstAType.right(dstAType.length()-startPos-1);
+ dstA->type=dstAType.left(startPos+1).stripWhiteSpace();
+ }
+ }
+ else // maybe dst has a name while src has not
+ {
+ dstPos++;
+ int startPos=dstPos;
+ while (dstPos<dstAType.length() && isId(dstAType.at(dstPos))) dstPos++;
+ if (dstPos!=dstAType.length()) return FALSE; // nope not a name -> no match
+ else // its a name (most probably) so move it
+ {
+ dstA->name=dstAType.right(dstAType.length()-startPos);
+ dstA->type=dstAType.left(startPos).stripWhiteSpace();
+ }
+ }
+ }
+ else if (srcPos<srcAType.length())
+ {
+ if (!isspace(srcAType.at(srcPos))) // maybe the names differ
+ {
+ int startPos=srcPos;
+ while (srcPos<srcAType.length() && isId(srcAType.at(srcPos))) srcPos++;
+ if (srcPos!=srcAType.length()) return FALSE; // more than a difference in name -> no match
+ while (startPos>=0 && isId(srcAType.at(startPos))) startPos--;
+ if (startPos>0)
+ {
+ srcA->name=srcAType.right(srcAType.length()-startPos-1);
+ srcA->type=srcAType.left(startPos+1).stripWhiteSpace();
+ }
+ }
+ else // maybe src has a name while dst has not
+ {
+ srcPos++;
+ int startPos=srcPos;
+ while (srcPos<srcAType.length() && isId(srcAType.at(srcPos))) srcPos++;
+ if (srcPos!=srcAType.length()) return FALSE; // nope not a name -> no match
+ else // its a name (most probably) so move it
+ {
+ srcA->name=srcAType.right(srcAType.length()-startPos);
+ srcA->type=srcAType.left(startPos).stripWhiteSpace();
+ }
+ }
+ }
+ else // without scopes the names match exactly
+ {
+ }
+ }
+ else if (srcA->name.length()==0 && dstA->name.length()==0)
+ // arguments match exactly but no name ->
+ // see if we can find the name
+ {
+ int i=srcAType.length()-1;
+ while (i>=0 && isId(srcAType.at(i))) i--;
+ if (i>0 && i<(int)srcAType.length()-1 && srcAType.at(i)!=':')
+ // there is (probably) a name
+ {
+ srcA->name=srcAType.right(srcAType.length()-i-1);
+ srcA->type=srcAType.left(i+1).stripWhiteSpace();
+ dstA->name=dstAType.right(dstAType.length()-i-1);
+ dstA->type=dstAType.left(i+1).stripWhiteSpace();
+ }
+ }
+ }
+ //printf("Match found!\n");
+ return TRUE; // all arguments match
+}
+
+// merges the initializer of two argument lists
+// pre: the types of the arguments in the list should match.
+void mergeArguments(ArgumentList *srcAl,ArgumentList *dstAl)
+{
+ //printf("mergeArguments `%s', `%s'\n",
+ // argListToString(srcAl).data(),argListToString(dstAl).data());
+ //printArgList(srcAl);printf(" <=> ");
+ //printArgList(dstAl);printf("\n");
+ if (srcAl==0 || dstAl==0 || srcAl->count()!=dstAl->count())
+ {
+ return; // invalid argument lists -> do not merge
+ }
+
+ ArgumentListIterator srcAli(*srcAl),dstAli(*dstAl);
+ Argument *srcA,*dstA;
+ for (;(srcA=srcAli.current(),dstA=dstAli.current());++srcAli,++dstAli)
+ {
+ if (srcA->defval.length()==0 && dstA->defval.length()>0)
+ {
+ //printf("Defval changing `%s'->`%s'\n",srcA->defval.data(),dstA->defval.data());
+ srcA->defval=dstA->defval.copy();
+ }
+ else if (srcA->defval.length()>0 && dstA->defval.length()==0)
+ {
+ //printf("Defval changing `%s'->`%s'\n",dstA->defval.data(),srcA->defval.data());
+ dstA->defval=srcA->defval.copy();
+ }
+ if (srcA->name.isEmpty() && !dstA->name.isEmpty())
+ {
+ //printf("type: `%s':=`%s'\n",srcA->type.data(),dstA->type.data());
+ //printf("name: `%s':=`%s'\n",srcA->name.data(),dstA->name.data());
+ srcA->type = dstA->type.copy();
+ srcA->name = dstA->name.copy();
+ }
+ else if (!srcA->name.isEmpty() && dstA->name.isEmpty())
+ {
+ //printf("type: `%s':=`%s'\n",dstA->type.data(),srcA->type.data());
+ //printf("name: `%s':=`%s'\n",dstA->name.data(),srcA->name.data());
+ dstA->type = srcA->type.copy();
+ dstA->name = dstA->name.copy();
+ }
+ int i1=srcA->type.find("::"),
+ i2=dstA->type.find("::"),
+ j1=srcA->type.length()-i1-2,
+ j2=dstA->type.length()-i2-2;
+ if (i1!=-1 && i2==-1 && srcA->type.right(j1)==dstA->type)
+ {
+ //printf("type: `%s':=`%s'\n",dstA->type.data(),srcA->type.data());
+ //printf("name: `%s':=`%s'\n",dstA->name.data(),srcA->name.data());
+ dstA->type = srcA->type.left(i1+2)+dstA->type;
+ dstA->name = dstA->name.copy();
+ }
+ else if (i1==-1 && i2!=-1 && dstA->type.right(j2)==srcA->type)
+ {
+ //printf("type: `%s':=`%s'\n",srcA->type.data(),dstA->type.data());
+ //printf("name: `%s':=`%s'\n",dstA->name.data(),srcA->name.data());
+ srcA->type = dstA->type.left(i2+2)+srcA->type;
+ srcA->name = dstA->name.copy();
+ }
+ }
+ //printf("result mergeArguments `%s', `%s'\n",
+ // argListToString(srcAl).data(),argListToString(dstAl).data());
+}
+
+//----------------------------------------------------------------------
+// searches for the class and member definitions corresponding with
+// memberName and className.
+// These classes are returned using `md' and `cd'.
+// returns TRUE if the class and member both could be found
+
+bool getDefs(const QString &memberName,const QString &className,
+ const char *args,MemberDef *&md, ClassDef *&cd, FileDef *&fd)
+{
+ //printf("Search for %s::%s %s\n",className.data(),memberName.data(),args);
+ fd=0; md=0; cd=0;
+ if (memberName.length()==0) return FALSE;
+ MemberName *mn;
+ if ((mn=memberNameDict[memberName]) && className.length()>0)
+ {
+ //printf(" >member name found\n");
+ ClassDef *fcd=0;
+ if ((fcd=getClass(className)))
+ {
+ //printf(" >member class found\n");
+ MemberDef *mmd=mn->first();
+ int mdist=maxInheritanceDepth;
+ while (mmd)
+ {
+ if ((mmd->protection()!=Private || extractPrivateFlag) &&
+ mmd->hasDocumentation()
+ /*mmd->detailsAreVisible()*/
+ /* && (args==0 || matchArgumentsOld(mmd->argsString(),args)) */
+ )
+ {
+ bool match=TRUE;
+ ArgumentList *argList=0;
+ if (args)
+ {
+ match=FALSE;
+ argList=new ArgumentList;
+ stringToArgumentList(args,argList);
+ match=matchArguments(mmd->argumentList(),argList);
+ }
+ if (match)
+ {
+ ClassDef *mcd=mmd->memberClass();
+ int m=minClassDistance(fcd,mcd);
+ if (m<mdist && mcd->isVisible())
+ {
+ mdist=m;
+ cd=mcd;
+ md=mmd;
+ fd=0;
+ }
+ }
+ if (argList)
+ {
+ delete argList;
+ }
+ }
+ mmd=mn->next();
+ }
+ if (mdist==maxInheritanceDepth && !strcmp(args,"()"))
+ // no exact match found, but if args="()" an arbitrary member will do
+ {
+ //printf(" >Searching for arbitrary member\n");
+ mmd=mn->first();
+ while (mmd)
+ {
+ if ((mmd->protection()!=Private || extractPrivateFlag) &&
+ (
+ mmd->hasDocumentation()
+ /*mmd->detailsAreVisible()*/
+ || mmd->isReference()
+ )
+ )
+ {
+ ClassDef *mcd=mmd->memberClass();
+ //printf(" >Class %s found\n",mcd->name().data());
+ int m=minClassDistance(fcd,mcd);
+ if (m<mdist && mcd->isVisible())
+ {
+ //printf("Class distance %d\n",m);
+ mdist=m;
+ cd=mcd;
+ md=mmd;
+ fd=0;
+ }
+ }
+ mmd=mn->next();
+ }
+ }
+ //printf(" >Succes=%d\n",mdist<maxInheritanceDepth);
+ return mdist<maxInheritanceDepth;
+ }
+ }
+ else // maybe an unrelated member ?
+ {
+ MemberName *mn;
+ if ((mn=functionNameDict[memberName]))
+ {
+ md=mn->first();
+ while (md)
+ {
+ if (/*md->detailsAreVisible()*/ md->hasDocumentation())
+ {
+ fd=md->getFileDef();
+ if (fd && fd->hasDocumentation())
+ {
+ cd=0;
+ return TRUE;
+ }
+ }
+ md=mn->next();
+ }
+ }
+ }
+ return FALSE;
+}
+
+//----------------------------------------------------------------------
+// Generate a hypertext link to the class with name `clName'.
+// If linkTxt is not null this text is used as the link, otherwise
+// the name of the class will be used. If the class could be found a
+// hypertext link (in HTML) is written, otherwise the text of the link will
+// be written.
+
+void generateClassRef(OutputList &ol,const char *clName,const char *linkTxt)
+{
+ QString className=clName;
+ QString linkText=linkTxt ? linkTxt : (const char *)className;
+ if (className.length()==0)
+ {
+ ol.docify(linkText);
+ return;
+ }
+ ClassDef *cd;
+ if ((cd=getClass(className)) && cd->isVisible())
+ {
+ ol.writeObjectLink(cd->getReference(),cd->classFile(),0,linkText);
+ if (!cd->isReference()) ol.writePageRef(cd->name(),0);
+ }
+ else
+ ol.docify(linkText);
+}
+
+//----------------------------------------------------------------------
+// generate a reference to a class or member.
+// `clName' is the name of the class that contains the documentation
+// string that is returned.
+// `name' is the name of the member or class that we want to link to.
+// `name' may have five formats:
+// 1) "ClassName"
+// 2) "memberName()" one of the (overloaded) function or define
+// with name memberName.
+// 3) "memberName(...)" a specific (overloaded) function or define
+// with name memberName
+// 4) "::memberName a non-function member or define
+// 5) ("ClassName::")+"memberName()"
+// 6) ("ClassName::")+"memberName(...)"
+// 7) ("ClassName::")+"memberName"
+
+void generateRef(OutputList &ol,const char *clName,
+ const char *name,bool inSeeBlock,const char *rt)
+{
+ //printf("generateRef(clName=%s,name=%s,rt=%s)\n",clName,name,rt);
+
+ // check if we have a plane name
+ QString tmpName = substitute(name,"#","::");
+ QString linkText = rt;
+ int scopePos=tmpName.findRev("::");
+ int bracePos=tmpName.find('(');
+ if (scopePos==-1 && bracePos==-1)
+ {
+ if (!inSeeBlock) /* check for class link */
+ {
+ if (linkText.isNull()) linkText=tmpName;
+ // check if this is a class reference
+ if (clName!=tmpName)
+ generateClassRef(ol,name,linkText);
+ else
+ ol.docify(linkText);
+ return;
+ }
+ else /* check if it is a class, if not continue to search */
+ {
+ if (clName!=tmpName && getClass(tmpName)!=0)
+ {
+ generateClassRef(ol,tmpName,linkText);
+ return;
+ }
+ }
+ }
+
+ // extract scope
+ QString scopeStr;
+ if (scopePos>0) scopeStr=tmpName.left(scopePos); else scopeStr=clName;
+
+ // extract name
+ int startNamePos=scopePos!=-1 ? scopePos+2 : 0;
+ int endNamePos=bracePos!=-1 ? bracePos : tmpName.length();
+ QString nameStr=tmpName.mid(startNamePos,endNamePos-startNamePos);
+
+ // extract arguments
+ QString argsStr;
+ if (bracePos!=-1) argsStr=tmpName.right(tmpName.length()-bracePos);
+
+ bool explicitLink=TRUE;
+ // create a default link text if none was explicitly given
+ if (linkText.isNull())
+ {
+ if (!scopeStr.isNull() && scopePos>0) linkText=scopeStr+"::";
+ linkText+=nameStr;
+ explicitLink=FALSE;
+ }
+
+ //printf("scope=`%s' name=`%s' arg=`%s' linkText=`%s'\n",
+ // scopeStr.data(),nameStr.data(),argsStr.data(),linkText.data());
+
+ //Define *d=0;
+ MemberDef *md;
+ ClassDef *cd;
+ FileDef *fd;
+ // check if nameStr is a member or global.
+ if (getDefs(nameStr,scopeStr,argsStr,md,cd,fd))
+ {
+ QString anchor = md->hasDocumentation() ? md->anchor() : 0;
+ QString cName,aName;
+ if (cd) // nameStr is a member of cd
+ {
+ //printf("addObjectLink(%s,%s,%s,%s)\n",cd->getReference(),
+ // cd->classFile(),anchor.data(),resultName.stripWhiteSpace().data());
+ ol.writeObjectLink(cd->getReference(),
+ cd->classFile(),anchor,
+ linkText.stripWhiteSpace());
+ cName=cd->name();
+ aName=md->anchor();
+ }
+ else if (fd) // nameStr is a global in file fd
+ {
+ //printf("addFileLink(%s,%s,%s)\n",fd->diskName(),anchor.data(),
+ // resultName.stripWhiteSpace().data());
+ ol.writeObjectLink(fd->getReference(),fd->diskName(),
+ anchor, linkText.stripWhiteSpace());
+ cName=fd->name();
+ aName=md->anchor();
+ }
+ else // should not be reached
+ {
+ //printf("add no link fd=cd=0\n");
+ ol.docify(linkText);
+ }
+
+ // for functions we add the arguments if explicitly specified or else "()"
+ if (!rt && (md->isFunction() || md->isPrototype() || md->isSignal() || md->isSlot()))
+ {
+ if (argsStr.isNull())
+ ol.writeString("()");
+ else
+ ol.docify(argsStr);
+ }
+
+ // generate the page reference (for LaTeX)
+ if (cName.length()>0 || aName.length()>0)
+ {
+ if (/*md->detailsAreVisible() &&*/
+ (
+ (cd && !cd->isReference() &&
+ // (cd->hasDocumentation() || !hideClassFlag) &&
+ // (cd->protection()!=Private || extractPrivateFlag)
+ cd->isVisible()
+ ) ||
+ (fd && !fd->isReference())
+ )
+ ) ol.writePageRef(cName,aName);
+ }
+ }
+// else if (!nameStr.isNull() && (d=defineDict[nameStr]))
+// // check if nameStr is perhaps a define
+// {
+// if (d->hasDocumentation() && d->fileDef)
+// {
+// ol.writeObjectLink(0,d->fileDef->diskName(),d->anchor,
+// linkText.stripWhiteSpace());
+// if (!explicitLink) ol.docify(argsStr);
+// }
+// }
+ else // nameStr is a false alarm or a typo.
+ {
+ if (rt)
+ ol.docify(rt);
+ else
+ {
+ ol.docify(linkText);
+ if (!argsStr.isNull()) ol.docify(argsStr);
+ }
+ }
+ return;
+}
+
+//----------------------------------------------------------------------
+// General function that generates the HTML code for a reference to some
+// file, class or member from text `lr' within the context of class `clName'.
+// This link has the text 'lt' (if not 0), otherwise `lr' is used as a
+// basis for the link's text.
+
+void generateLink(OutputList &ol,const char *clName,
+ const char *lr,bool inSeeBlock,const char *lt)
+{
+ QString linkRef=lr;
+ //PageInfo *pi=0;
+ //printf("generateLink(%s,%s)\n",lr,lt);
+ //FileInfo *fi=0;
+ FileDef *fd;
+ bool ambig;
+ if (linkRef.length()==0) // no reference name!
+ ol.docify(lt);
+ else if ((pageDict[linkRef])) // link to a page
+ ol.writeObjectLink(0,linkRef,0,lt);
+ else if ((exampleDict[linkRef])) // link to an example
+ ol.writeObjectLink(0,linkRef+"-example",0,lt);
+ else if ((fd=findFileDef(&inputNameDict,linkRef,ambig))
+ && fd->hasDocumentation())
+ // link to documented input file
+ ol.writeObjectLink(fd->getReference(),fd->diskName(),0,lt);
+ else // probably a class or member reference
+ generateRef(ol,clName,lr,inSeeBlock,lt);
+}
+
+void generateFileRef(OutputList &ol,const char *name,const char *text)
+{
+ QString linkText = text ? text : name;
+ //FileInfo *fi;
+ FileDef *fd;
+ bool ambig;
+ if ((fd=findFileDef(&inputNameDict,name,ambig)) &&
+ fd->hasDocumentation())
+ // link to documented input file
+ ol.writeObjectLink(fd->getReference(),fd->diskName(),0,linkText);
+ else
+ ol.docify(linkText);
+}
+
+//----------------------------------------------------------------------
+
+QString substituteClassNames(const QString &s)
+{
+ int i=0,l,p;
+ QString result;
+ QRegExp r("[a-z_A-Z][a-z_A-Z0-9]*");
+ while ((p=r.match(s,i,&l))!=-1)
+ {
+ QString *subst;
+ if (p>i) result+=s.mid(i,p-i);
+ if ((subst=substituteDict[s.mid(p,l)]))
+ {
+ result+=*subst;
+ }
+ else
+ {
+ result+=s.mid(p,l);
+ }
+ i=p+l;
+ }
+ result+=s.mid(i,s.length()-i);
+ return result;
+}
+
+//----------------------------------------------------------------------
+
+QString convertSlashes(const QString &s,bool dots)
+{
+ QString result;
+ int i,l=s.length();
+ for (i=0;i<l;i++)
+ if (s.at(i)!='/' && (!dots || s.at(i)!='.'))
+ {
+ if (caseSensitiveNames)
+ {
+ result+=s[i];
+ }
+ else
+ {
+ result+=tolower(s[i]);
+ }
+ }
+ else
+ result+="_";
+ return result;
+}
+
+//----------------------------------------------------------------------
+// substitute all occurences of `src' in `s' by `dst'
+
+QString substitute(const char *s,const char *src,const char *dst)
+{
+ QString input=s;
+ QString output;
+ int i=0,p;
+ while ((p=input.find(src,i))!=-1)
+ {
+ output+=input.mid(i,p-i);
+ output+=dst;
+ i=p+strlen(src);
+ }
+ output+=input.mid(i,input.length()-i);
+ return output;
+}
+
+//----------------------------------------------------------------------
+
+FileDef *findFileDef(const FileNameDict *fnDict,const char *n,bool &ambig)
+{
+ ambig=FALSE;
+ QString name=n;
+ QString path;
+ if (name.isNull()) return 0;
+ int slashPos=QMAX(name.findRev('/'),name.findRev('\\'));
+ if (slashPos!=-1)
+ {
+ path=name.left(slashPos+1);
+ name=name.right(name.length()-slashPos-1);
+ }
+ //printf("findFileDef path=`%s' name=`%s'\n",path.data(),name.data());
+ if (name.isNull()) return 0;
+ FileName *fn;
+ if ((fn=(*fnDict)[name]))
+ {
+ if (fn->count()==1)
+ {
+ return fn->first();
+ }
+ else // file name alone is ambigious
+ {
+ int count=0;
+ FileDef *fd=fn->first();
+ FileDef *lastMatch=0;
+ while (fd)
+ {
+ if (path.isNull() || fd->getPath().right(path.length())==path)
+ {
+ count++;
+ lastMatch=fd;
+ }
+ fd=fn->next();
+ }
+ ambig=(count>1);
+ return lastMatch;
+ }
+ }
+ return 0;
+}
+
+//----------------------------------------------------------------------
+
+void showFileDefMatches(const FileNameDict *fnDict,const char *n)
+{
+ QString name=n;
+ QString path;
+ int slashPos=QMAX(name.findRev('/'),name.findRev('\\'));
+ if (slashPos!=-1)
+ {
+ path=name.left(slashPos+1);
+ name=name.right(name.length()-slashPos-1);
+ }
+ FileName *fn;
+ if ((fn=(*fnDict)[name]))
+ {
+ FileDef *fd=fn->first();
+ while (fd)
+ {
+ if (path.isNull() || fd->getPath().right(path.length())==path)
+ {
+ msg(" %s\n",fd->absFilePath().data());
+ }
+ fd=fn->next();
+ }
+ }
+}
+
diff --git a/src/util.h b/src/util.h
new file mode 100644
index 0000000..9dfd097
--- /dev/null
+++ b/src/util.h
@@ -0,0 +1,82 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#ifndef UTIL_H
+#define UTIL_H
+
+#include <qlist.h>
+#include <qtstream.h>
+#include <ctype.h>
+//#include "filedef.h"
+//#include "filename.h"
+#include "memberdef.h"
+//#include "outputlist.h"
+
+
+class ClassDef;
+class FileDef;
+class MemberList;
+class NamespaceDef;
+class FileNameDict;
+class ArgumentList;
+class OutputList;
+
+extern void writeMemberDecs(OutputList &ol, ClassDef *cd, NamespaceDef *nd,
+ FileDef *fd, const char *title, const char *subtitle,
+ MemberList *ml);
+extern void writeMemberDocs(OutputList &ol,
+ MemberList *ml,const char *scopeName,MemberDef::MemberType m);
+extern void setAnchors(char id,MemberList *ml);
+//extern int countMemberDocs(MemberList *ml,MemberDef::MemberType m);
+extern QString fileToString(const char *name);
+extern QString dateToString(bool);
+//extern OutputList linkifyText(const char *clName,const char *name,
+// const char *text);
+extern bool getDefs(const QString &memberName,const QString &className,
+ const char *, MemberDef *&md, ClassDef *&cd,FileDef *&fd);
+extern void generateRef(OutputList &ol,const char *,
+ const char *,bool inSeeBlock,const char * =0);
+extern void generateLink(OutputList &ol,const char *,
+ const char *,bool inSeeBlock,const char *);
+extern void generateClassRef(OutputList &ol,const char *clName,
+ const char *linkTxt=0);
+extern void generateFileRef(OutputList &ol,const char *,
+ const char *linkTxt=0);
+extern bool matchArguments(ArgumentList *,ArgumentList *,
+ const char *cl=0,const char *ns=0);
+extern void mergeArguments(ArgumentList *,ArgumentList *);
+extern QString substituteClassNames(const QString &s);
+extern QString convertSlashes(const QString &s,bool dots=FALSE);
+extern QString substitute(const char *s,const char *src,const char *dst);
+extern QString resolveDefines(const char *n);
+extern ClassDef *getClass(const char *key);
+//extern int strcscmp(const char *s1,const char *s2);
+extern FileDef *findFileDef(const FileNameDict *fnDict,const char *n,
+ bool &ambig);
+extern void showFileDefMatches(const FileNameDict *fnDict,const char *n);
+extern int guessSection(const char *name);
+//extern QString nameToFile(const char *name);
+extern bool isId(char c);
+extern QString removeRedundantWhiteSpace(const QString &s);
+extern void startTitle(OutputList &ol);
+extern void endTitle(OutputList &ol,const char *name);
+void startFile(OutputList &ol,const char *name,
+ const char *title,bool external=FALSE);
+void endFile(OutputList &ol,bool external=FALSE);
+void writeQuickLinks(OutputList &ol,bool compact,bool external=FALSE);
+QString argListToString(ArgumentList *al);
+
+#endif
diff --git a/src/version.h b/src/version.h
new file mode 100644
index 0000000..c148ab7
--- /dev/null
+++ b/src/version.h
@@ -0,0 +1,22 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#ifndef VERSION_H
+#define VERSION_H
+
+extern char versionString[];
+
+#endif
diff --git a/tmake/CHANGES b/tmake/CHANGES
new file mode 100644
index 0000000..000ac7d
--- /dev/null
+++ b/tmake/CHANGES
@@ -0,0 +1,39 @@
+ Changes from version 1.1 to 1.2
+
+* tmake is no longer restricted to C++ only. You can now use both C++
+ and C files in your project. Thanks to Ulrich Ring for valuable feed-
+ back and comments.
+
+* Added support for building DLL libraries under Windows.
+ NOTE: Qt 1.42 and later now uses qtmain.lib in addition to qt.lib
+ when your application uses the Qt DLL. Add "DEFINES = QT_DLL" to
+ your project file to use the Qt DLL.
+
+* New dist target added in the app and lib templates.
+ Run "make dist" to pack all files in your project using tar/gzip or zip.
+ Thanks to Kalle Dalheimer for this patch.
+
+* Fixed bad command line interpretation bug in tmake.exe and progen.exe.
+
+* Added support for Borland C++ builder 3.
+
+* Initial support for QNX/g++ and the IBM Visual Age compiler on Win32.
+ Thanks to Igor Kovalenko and Joost Kraaijeveld.
+
+* Many fixes in tmake.conf for several Unix configurations.
+
+
+ Changes from version 1.0 to 1.1
+
+* Provides tmake.exe and progen.exe for Windows users without perl.
+
+* Added many new Unix templates.
+
+* Added subdirs.t templates.
+
+* Added system-dependent project settings
+ (e.g. solaris-cc:TMAKE_CFLAGS = -pts)
+
+* Many bug fixes and improvements for existing templates.
+
+* Improved documentation.
diff --git a/tmake/LICENSE b/tmake/LICENSE
new file mode 100644
index 0000000..2836b6a
--- /dev/null
+++ b/tmake/LICENSE
@@ -0,0 +1,9 @@
+ License Statement for tmake
+
+Copyright (C) 1996-1998 by Troll Tech AS. All rights reserved.
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted, provided
+that the this copyright notice appears in all copies.
+No representations are made about the suitability of this software for any
+purpose. It is provided "as is" without express or implied warranty.
diff --git a/tmake/README b/tmake/README
new file mode 100644
index 0000000..defb697
--- /dev/null
+++ b/tmake/README
@@ -0,0 +1,7 @@
+ tmake version 1.2
+
+tmake is an easy-to-use tool for creating and maintaining makefiles across
+many platforms and compilers. The tmake manual (doc/tmake.html) explains
+how to install and use tmake.
+
+Download the latest version from: <ftp://ftp.troll.no/freebies/tmake>
diff --git a/tmake/bin/progen b/tmake/bin/progen
new file mode 100755
index 0000000..8237fd5
--- /dev/null
+++ b/tmake/bin/progen
@@ -0,0 +1,249 @@
+#!/usr/bin/perl
+############################################################################
+# $Id$
+#
+# Generates a tmake project file.
+#
+# Copyright (C) 1996-1998 by Troll Tech AS. All rights reserved.
+#
+# Permission to use, copy, modify, and distribute this software and its
+# documentation for any purpose and without fee is hereby granted, provided
+# that this copyright notice appears in all copies.
+# No representations are made about the suitability of this software for any
+# purpose. It is provided "as is" without express or implied warranty.
+#
+############################################################################
+
+# Default project settings
+$project{"TEMPLATE"} = "app";
+$project{"CONFIG"} = "qt warn_on release";
+
+@project_extra = ();
+
+while ( @ARGV ) { # parse command line args
+ $_ = shift @ARGV;
+ if ( s/^-// ) {
+ if ( /^o(.*)/ ) {
+ $outfile = ($1 eq "") ? shift @ARGV : $1;
+ ($outfile eq "-") && ($outfile = "");
+ } elsif ( /^n(.*)/ ) {
+ $project{"TARGET"} = ($1 eq "") ? shift @ARGV : $1;
+ } elsif ( /^t(.*)/ ) {
+ $project{"TEMPLATE"} = ($1 eq "") ? shift @ARGV : $1;
+ $project{"TEMPLATE"} =~ s/\.t$//i;
+ } elsif ( /lower/ ) {
+ $tolower = 1;
+ } else {
+ &progen_usage;
+ }
+ } elsif ( /^\s*(?:[\w\-]+:)?\w+\s*[\+\-\*\/]?=/ ) { # project override
+ push( @project_extra, $_ );
+ } else {
+ push (@files, $_ );
+ }
+}
+
+$outfile eq "" || open(STDOUT,">" . $outfile) ||
+ &progen_error("Can't create \"$outfile\"");
+
+if ( ! @files ) {
+ @files = &find_files(".",".*",1);
+}
+
+if ( $tolower ) {
+ foreach $f ( @files ) {
+ $f =~ tr/A-Z/a-z/;
+ }
+}
+
+@hdr = sort grep(/\.(h|hh|hpp|hxx)$/i,@files);
+@src = sort grep(/\.(c|cpp|cc|cxx)$/i && ! /moc_/i,@files);
+
+# Remove source files that are included by other source files
+foreach $f ( @src ) {
+ $srcdict{$f} = 1;
+}
+foreach $f ( @src ) {
+ if ( open(F,"< $f") ) {
+ while ( <F> ) {
+ if ( /^\s*#\s*include\s+\"([^\"]*)\"/ ) {
+ $srcdict{$1} = 0;
+ }
+ }
+ }
+}
+foreach $f( @src ) {
+ $srcdict{$f} && (push(@src2,$f));
+}
+@src = @src2;
+
+$project{"HEADERS"} = join(" ",sort @hdr);
+$project{"SOURCES"} = join(" ",sort @src);
+
+foreach $p ( @project_extra ) {
+ if ( $p =~ /^\s*((?:[\w\-]+:)?\w+)\s*([\+\-\*\/])?=\s*(.*)/ ) {
+ if ( $project{$1} ne "" ) {
+ Project($p);
+ }
+ }
+}
+
+$project{"HEADERS"} =~ s/\s+/ \\\n\t\t /g;
+$project{"SOURCES"} =~ s/\s+/ \\\n\t\t /g;
+
+print "TEMPLATE\t= " . $project{"TEMPLATE"} . "\n";
+print "CONFIG\t\t= " . $project{"CONFIG"} . "\n";
+print "HEADERS\t\t= " . $project{"HEADERS"} . "\n";
+print "SOURCES\t\t= " . $project{"SOURCES"} . "\n";
+if ( $project{"TARGET"} ne "" ) {
+ print "TARGET\t\t= " . $project{"TARGET"} . "\n";
+}
+
+foreach ( @project_extra ) {
+ if ( /^\s*((?:[\w\-]+:)?\w+)\s*([\+\-\*\/])?=\s*(.*)/ ) {
+ if ( $project{$1} eq "" ) {
+ $t = $1;
+ if ( length($t) < 8 ) {
+ $t .= "\t\t";
+ } elsif ( length($t) < 16 ) {
+ $t .= "\t";
+ } else {
+ $t .= " ";
+ }
+ print "$t$2= $3\n";
+ }
+ }
+}
+
+exit 0;
+
+
+#
+# progen_usage()
+#
+# Prints a message about program usage and exits
+#
+
+sub progen_usage {
+ print STDERR "Usage:\n progen [options] [files]\n";
+ print STDERR "Options:\n";
+ print STDERR " -lower Lower-case letters filenames (useful for non-Unix)\n";
+ print STDERR " -n name Specify a project name (= TARGET)\n";
+ print STDERR " -o file Write output to \"file\"\n";
+ print STDERR " -t file Specify a template file other than qtapp\n";
+ exit 1;
+}
+
+
+#
+# progen_error(msg)
+#
+# Prints the message and exits
+#
+
+sub progen_error {
+ my($msg) = @_;
+ print STDERR "progen error: " . $msg . "\n";
+ exit 1;
+}
+
+
+#
+# Finds files.
+#
+# Examples:
+# find_files("/usr","\.cpp$",1) - finds .cpp files in /usr and below
+# find_files("/tmp","^#",0) - finds #* files in /tmp
+#
+
+sub find_files {
+ my($dir,$match,$descend) = @_;
+ my($file,$p,@files);
+ local(*D);
+ $dir =~ s=\\=/=g;
+ ($dir eq "") && ($dir = ".");
+ if ( opendir(D,$dir) ) {
+ if ( $dir eq "." ) {
+ $dir = "";
+ } else {
+ ($dir =~ /\/$/) || ($dir .= "/");
+ }
+ foreach $file ( readdir(D) ) {
+ next if ( $file =~ /^\.\.?$/ );
+ $p = $dir . $file;
+ ($file =~ /$match/i) && (push @files, $p);
+ if ( $descend && -d $p && ! -l $p ) {
+ push @files, &find_files($p,$match,$descend);
+ }
+ }
+ closedir(D);
+ }
+ return @files;
+}
+
+
+#
+# strip_project_val(tag)
+#
+# Strips white space from project value strings.
+#
+
+sub strip_project_val {
+ my($v) = @_;
+ $v =~ s/^\s+//; # trim white space
+ $v =~ s/\s+$//;
+ return $v;
+}
+
+
+#
+# Project(strings)
+#
+# This is a powerful function for setting or reading project variables.
+# Returns the resulting project variables (joined with space between).
+#
+# This is a slightly modified version of the Project function in tmake.
+
+sub Project {
+ my @settings = @_;
+ my($r,$t,$s,$v,$p,$c);
+ $r = "";
+ foreach ( @settings ) {
+ $v = $_;
+ if ( $v =~ s/^\s*((?:[\w\-]+:)?\w+)\s*(\+=|\*=|\-=|\/=|=)\s*// ) {
+ $t = $1;
+ $s = $2;
+ $v = strip_project_val($v);
+ $p = $project{$t};
+ if ( $s eq "=" ) { # set variable
+ $p = $v;
+ } elsif ( $s eq "+=" ) { # append
+ if ( $p eq "" ) {
+ $p = $v;
+ } else {
+ $p .= " " . $v;
+ }
+ } elsif ( $s eq "*=" ) { # append if not contained
+ if ( !($p =~ /(?:^|\s)\Q$v\E(?:\s|$)/) ) {
+ if ( $p eq "" ) {
+ $p = $v;
+ } else {
+ $p .= " " . $v;
+ }
+ }
+ } elsif ( $s eq "-=" ) { # subtract
+ $p =~ s/$v//g;
+ } elsif ( $s eq "/=" ) { # sed
+ $cmd = '$p =~ ' . $v;
+ eval $cmd;
+ }
+ $project{$t} = strip_project_val($p);
+ } else {
+ $p = strip_project_val($project{$v});
+ }
+ if ( $p ne "" ) {
+ $r = ($r eq "") ? $p : ($r . " " . $p);
+ }
+ }
+ return $r;
+}
diff --git a/tmake/bin/progen.bat b/tmake/bin/progen.bat
new file mode 100644
index 0000000..54475ee
--- /dev/null
+++ b/tmake/bin/progen.bat
@@ -0,0 +1,266 @@
+@rem = '--*-PERL-*--';
+@rem = '
+@echo off
+rem setlocal
+set ARGS=
+:loop
+if .%1==. goto endloop
+set ARGS=%ARGS% %1
+shift
+goto loop
+:endloop
+rem ***** This assumes PERL is in the PATH *****
+perl.exe -S progen.bat %ARGS%
+goto endofperl
+@rem ';
+#!/usr/bin/perl
+############################################################################
+# $Id$
+#
+# Generates a tmake project file.
+#
+# Copyright (C) 1996-1998 by Troll Tech AS. All rights reserved.
+#
+# Permission to use, copy, modify, and distribute this software and its
+# documentation for any purpose and without fee is hereby granted, provided
+# that this copyright notice appears in all copies.
+# No representations are made about the suitability of this software for any
+# purpose. It is provided "as is" without express or implied warranty.
+#
+############################################################################
+
+# Default project settings
+$project{"TEMPLATE"} = "app";
+$project{"CONFIG"} = "qt warn_on release";
+
+@project_extra = ();
+
+while ( @ARGV ) { # parse command line args
+ $_ = shift @ARGV;
+ if ( s/^-// ) {
+ if ( /^o(.*)/ ) {
+ $outfile = ($1 eq "") ? shift @ARGV : $1;
+ ($outfile eq "-") && ($outfile = "");
+ } elsif ( /^n(.*)/ ) {
+ $project{"TARGET"} = ($1 eq "") ? shift @ARGV : $1;
+ } elsif ( /^t(.*)/ ) {
+ $project{"TEMPLATE"} = ($1 eq "") ? shift @ARGV : $1;
+ $project{"TEMPLATE"} =~ s/\.t$//i;
+ } elsif ( /lower/ ) {
+ $tolower = 1;
+ } else {
+ &progen_usage;
+ }
+ } elsif ( /^\s*(?:[\w\-]+:)?\w+\s*[\+\-\*\/]?=/ ) { # project override
+ push( @project_extra, $_ );
+ } else {
+ push (@files, $_ );
+ }
+}
+
+$outfile eq "" || open(STDOUT,">" . $outfile) ||
+ &progen_error("Can't create \"$outfile\"");
+
+if ( ! @files ) {
+ @files = &find_files(".",".*",1);
+}
+
+if ( $tolower ) {
+ foreach $f ( @files ) {
+ $f =~ tr/A-Z/a-z/;
+ }
+}
+
+@hdr = sort grep(/\.(h|hh|hpp|hxx)$/i,@files);
+@src = sort grep(/\.(c|cpp|cc|cxx)$/i && ! /moc_/i,@files);
+
+# Remove source files that are included by other source files
+foreach $f ( @src ) {
+ $srcdict{$f} = 1;
+}
+foreach $f ( @src ) {
+ if ( open(F,"< $f") ) {
+ while ( <F> ) {
+ if ( /^\s*#\s*include\s+\"([^\"]*)\"/ ) {
+ $srcdict{$1} = 0;
+ }
+ }
+ }
+}
+foreach $f( @src ) {
+ $srcdict{$f} && (push(@src2,$f));
+}
+@src = @src2;
+
+$project{"HEADERS"} = join(" ",sort @hdr);
+$project{"SOURCES"} = join(" ",sort @src);
+
+foreach $p ( @project_extra ) {
+ if ( $p =~ /^\s*((?:[\w\-]+:)?\w+)\s*([\+\-\*\/])?=\s*(.*)/ ) {
+ if ( $project{$1} ne "" ) {
+ Project($p);
+ }
+ }
+}
+
+$project{"HEADERS"} =~ s/\s+/ \\\n\t\t /g;
+$project{"SOURCES"} =~ s/\s+/ \\\n\t\t /g;
+
+print "TEMPLATE\t= " . $project{"TEMPLATE"} . "\n";
+print "CONFIG\t\t= " . $project{"CONFIG"} . "\n";
+print "HEADERS\t\t= " . $project{"HEADERS"} . "\n";
+print "SOURCES\t\t= " . $project{"SOURCES"} . "\n";
+if ( $project{"TARGET"} ne "" ) {
+ print "TARGET\t\t= " . $project{"TARGET"} . "\n";
+}
+
+foreach ( @project_extra ) {
+ if ( /^\s*((?:[\w\-]+:)?\w+)\s*([\+\-\*\/])?=\s*(.*)/ ) {
+ if ( $project{$1} eq "" ) {
+ $t = $1;
+ if ( length($t) < 8 ) {
+ $t .= "\t\t";
+ } elsif ( length($t) < 16 ) {
+ $t .= "\t";
+ } else {
+ $t .= " ";
+ }
+ print "$t$2= $3\n";
+ }
+ }
+}
+
+exit 0;
+
+
+#
+# progen_usage()
+#
+# Prints a message about program usage and exits
+#
+
+sub progen_usage {
+ print STDERR "Usage:\n progen [options] [files]\n";
+ print STDERR "Options:\n";
+ print STDERR " -lower Lower-case letters filenames (useful for non-Unix)\n";
+ print STDERR " -n name Specify a project name (= TARGET)\n";
+ print STDERR " -o file Write output to \"file\"\n";
+ print STDERR " -t file Specify a template file other than qtapp\n";
+ exit 1;
+}
+
+
+#
+# progen_error(msg)
+#
+# Prints the message and exits
+#
+
+sub progen_error {
+ my($msg) = @_;
+ print STDERR "progen error: " . $msg . "\n";
+ exit 1;
+}
+
+
+#
+# Finds files.
+#
+# Examples:
+# find_files("/usr","\.cpp$",1) - finds .cpp files in /usr and below
+# find_files("/tmp","^#",0) - finds #* files in /tmp
+#
+
+sub find_files {
+ my($dir,$match,$descend) = @_;
+ my($file,$p,@files);
+ local(*D);
+ $dir =~ s=\\=/=g;
+ ($dir eq "") && ($dir = ".");
+ if ( opendir(D,$dir) ) {
+ if ( $dir eq "." ) {
+ $dir = "";
+ } else {
+ ($dir =~ /\/$/) || ($dir .= "/");
+ }
+ foreach $file ( readdir(D) ) {
+ next if ( $file =~ /^\.\.?$/ );
+ $p = $dir . $file;
+ ($file =~ /$match/i) && (push @files, $p);
+ if ( $descend && -d $p && ! -l $p ) {
+ push @files, &find_files($p,$match,$descend);
+ }
+ }
+ closedir(D);
+ }
+ return @files;
+}
+
+
+#
+# strip_project_val(tag)
+#
+# Strips white space from project value strings.
+#
+
+sub strip_project_val {
+ my($v) = @_;
+ $v =~ s/^\s+//; # trim white space
+ $v =~ s/\s+$//;
+ return $v;
+}
+
+
+#
+# Project(strings)
+#
+# This is a powerful function for setting or reading project variables.
+# Returns the resulting project variables (joined with space between).
+#
+# This is a slightly modified version of the Project function in tmake.
+
+sub Project {
+ my @settings = @_;
+ my($r,$t,$s,$v,$p,$c);
+ $r = "";
+ foreach ( @settings ) {
+ $v = $_;
+ if ( $v =~ s/^\s*((?:[\w\-]+:)?\w+)\s*(\+=|\*=|\-=|\/=|=)\s*// ) {
+ $t = $1;
+ $s = $2;
+ $v = strip_project_val($v);
+ $p = $project{$t};
+ if ( $s eq "=" ) { # set variable
+ $p = $v;
+ } elsif ( $s eq "+=" ) { # append
+ if ( $p eq "" ) {
+ $p = $v;
+ } else {
+ $p .= " " . $v;
+ }
+ } elsif ( $s eq "*=" ) { # append if not contained
+ if ( !($p =~ /(?:^|\s)\Q$v\E(?:\s|$)/) ) {
+ if ( $p eq "" ) {
+ $p = $v;
+ } else {
+ $p .= " " . $v;
+ }
+ }
+ } elsif ( $s eq "-=" ) { # subtract
+ $p =~ s/$v//g;
+ } elsif ( $s eq "/=" ) { # sed
+ $cmd = '$p =~ ' . $v;
+ eval $cmd;
+ }
+ $project{$t} = strip_project_val($p);
+ } else {
+ $p = strip_project_val($project{$v});
+ }
+ if ( $p ne "" ) {
+ $r = ($r eq "") ? $p : ($r . " " . $p);
+ }
+ }
+ return $r;
+}
+__END__
+:endofperl
diff --git a/tmake/bin/tmake b/tmake/bin/tmake
new file mode 100755
index 0000000..2d7e6a7
--- /dev/null
+++ b/tmake/bin/tmake
@@ -0,0 +1,1099 @@
+#!/usr/bin/perl
+############################################################################
+# $Id$
+#
+# Creates a Makefile from a template and a project file.
+#
+# Copyright (C) 1996-1998 by Troll Tech AS. All rights reserved.
+#
+# Permission to use, copy, modify, and distribute this software and its
+# documentation for any purpose and without fee is hereby granted, provided
+# that this copyright notice appears in all copies.
+# No representations are made about the suitability of this software for any
+# purpose. It is provided "as is" without express or implied warranty.
+#
+#
+# Some important, global variables in tmake:
+# cpp_ext C++ extension added to moc output (.cpp)
+# obj_ext Object file extension (.o on Unix, .obj otherwise)
+# moc_aware Will scan for files containing Qt signals/slots
+# moc_pre Moc prefix for generated moc file: x.h -> moc_x.cpp
+# moc_ext Moc extension for generated moc file: x.cpp -> x.moc
+# moc_cmd The moc command in your makefile, $(MOC)
+# linebreak Line break character (\)
+# dir_sep Directory separator (/ on Unix, \ on Windows)
+# is_unix Autodetected. If not Unix, assume Windows (Win32).
+#
+# If you need to customize any of these settings, do it before
+# calling StdInit() in the template file.
+#
+############################################################################
+
+if ($] < 5.0) {
+ &tmake_error("This program requires perl version 5 or newer");
+}
+
+$cpp_ext = "cpp";
+$obj_ext = "o";
+$moc_aware = 0;
+$moc_pre = "moc_";
+$moc_ext = "moc";
+$moc_cmd = '$(MOC)';
+$linebreak = "\\";
+$dir_sep = "/";
+$is_unix = 1;
+$really_unix = &check_unix();
+$guess_os = 1;
+$depend_path = "";
+$nodepend = 0;
+$output_count = 0;
+
+$template_name = "";
+$project_name = "";
+$outfile = "";
+@project_extra = ();
+@project_files = ();
+@eval_expr = ();
+$eval_done = 0;
+
+while ( @ARGV ) { # parse command line args
+ $_ = shift @ARGV;
+ if ( s/^-// ) {
+ if ( /^e(.*)/ ) {
+ push( @eval_expr, ($1 eq "") ? shift @ARGV : $1);
+ } elsif ( /^t(.*)/ ) {
+ $template_name = ($1 eq "") ? shift @ARGV : $1;
+ } elsif ( /^o(.*)/ ) {
+ $outfile = ($1 eq "") ? shift @ARGV : $1;
+ ($outfile eq "-") && ($outfile = "");
+ } elsif ( /^p(.*)/ ) {
+ push( @project_files, ($1 eq "") ? shift @ARGV : $1);
+ } elsif ( /^unix$/ ) {
+ $guess_os = 0;
+ $is_unix = 1;
+ } elsif ( /^win32$/ ) {
+ $guess_os = 0;
+ $is_unix = 0;
+ } elsif ( /^nodepend$/ ) {
+ $nodepend = 1; # don't generate dependencies
+ } elsif ( /^v$/ ) {
+ $verbose = 1;
+ } else {
+ &tmake_usage();
+ }
+ } elsif ( /^\s*(?:[\w\-]+:)?\w+\s*[\+\-\*\/]?=/ ) { # project override
+ push( @project_extra, $_ );
+ } else {
+ $project_name &&
+ &tmake_error("You can only specify one project file");
+ $project_name = $_;
+ }
+}
+
+($project_name ne "") || &tmake_usage();
+
+if ( $guess_os && ! check_unix() ) { # probably non-Unix,
+ $is_unix = 0;
+ &tmake_verb("Win32 detected");
+}
+if ( ! $is_unix ) {
+ $obj_ext = "obj";
+ $dir_sep = "\\";
+}
+$outfile eq "" || open(STDOUT,">" . fix_path($outfile)) ||
+ &tmake_error("Can't create \"$outfile\"");
+
+%project = ();
+&ScanProject( &find_template("tmake.conf") );
+&tmake_verb("Reading the project file $project_name");
+if ( ! ($project_name =~ /\.pro$/i) && -f fix_path($project_name . ".pro") ) {
+ $project_name .= ".pro";
+}
+$project{"PROJECT"} = $project_name;
+$project{"PROJECT"} =~ s/\.pro$//i;
+$project{"TARGET"} = $project{"PROJECT"};
+
+unshift(@project_files,$project_name);
+foreach ( @project_files ) {
+ if ( ! ($_ =~ /\.pro$/i) && -f fix_path($_ . ".pro") ) {
+ $_ .= ".pro";
+ }
+ if ( !&ScanProject($_) ) {
+ &tmake_error("Can't open project file \"$_\"");
+ }
+}
+&Project( @project_extra );
+
+if ( $template_name eq "" ) {
+ $template_name = $project{"TEMPLATE"} ?
+ $project{"TEMPLATE"} : "default.t";
+}
+
+foreach ( @eval_expr ) {
+ $text = "";
+ eval( $_ );
+ die $@ if $@;
+ print $text . "\n" if ($text ne "");
+ $eval_done = 1;
+}
+if ( $eval_done ) {
+ &tmake_verb("Done!");
+ exit 0;
+}
+
+$template_name = &find_template($template_name);
+&IncludeTemplate($template_name);
+&tmake_verb("Done!");
+exit 0; # finished!
+
+
+
+##############################################################################
+# Subroutines from here
+##############################################################################
+
+#
+# tmake_usage()
+#
+# Prints a message about program usage and exits
+#
+
+sub tmake_usage {
+ print STDERR "Usage:\n tmake [options] project-file\n";
+ print STDERR "Options:\n";
+ print STDERR " -e expr Evaluate expression, ignore template file\n";
+ print STDERR " -nodepend Don't generate dependency information\n";
+ print STDERR " -o file Write output to file\n";
+ print STDERR " -p project Load additional project file\n";
+ print STDERR " -t file Specify a template file\n";
+ print STDERR " -unix Create output for Unix (auto detects)\n";
+ print STDERR " -v Verbose/debug mode\n";
+ print STDERR " -win32 Create output for Win32 (auto detects)\n";
+ exit 1;
+}
+
+
+#
+# tmake_error(msg)
+#
+# Prints the message and exits
+#
+
+sub tmake_error {
+ my($msg) = @_;
+ print STDERR "tmake error: " . $msg . "\n";
+ exit 1;
+}
+
+
+#
+# tmake_verb()
+#
+# Prints a verbose message
+#
+
+sub tmake_verb {
+ my($msg) = @_;
+ $verbose && print STDERR "tmake: " . $msg . "\n";
+}
+
+
+#
+# check_unix()
+#
+# Returns 1 if this is a Unix, 0 otherwise.
+#
+
+sub check_unix {
+ my($r);
+ $r = 0;
+ if ( -f "/bin/uname" || -f "/usr/bin/uname" ) {
+ $r = 1;
+ (-f "\\bin\\uname") && ($r = 0);
+ }
+ return $r;
+}
+
+
+#
+# find_template(filename)
+#
+# Looks for the template file.
+# 1. search the current directory
+# 2. search the directories in TMAKEPATH
+# 3. search in $HOME/.tmake
+#
+
+sub find_template {
+ my($filename) = @_;
+ my($tb,$d,$p,@dirs);
+ if ( !defined($template_base) || ($template_base eq "") ) {
+ $tb = "";
+ } else {
+ $tb = $template_base . ";";
+ }
+ $d = ";" . $tb . $ENV{"TMAKEPATH"} . ";" . $ENV{"HOME"} . "/.tmake/";
+ @dirs = &split_path( $d );
+ $filename .= ".t" unless ($filename =~ /\.\w+$/);
+ for $d ( @dirs ) {
+ $p = $d . $filename;
+ if ( -f fix_path($p) ) {
+ if ( $filename eq "tmake.conf" ) {
+ $tmake_platform = $d;
+ $tmake_platform =~ s-.*[/\\]([^/\\]*)[/\\]-$1-;
+ &tmake_verb("Detected platform $tmake_platform");
+ }
+ return $p;
+ }
+ return ($d . $filename) if ( -f fix_path($d . $filename) );
+ }
+ &tmake_error("Template file " . $filename . " not found");
+}
+
+
+##############################################################################
+# User functions
+##############################################################################
+
+#
+# StdInit()
+#
+# Standard initialization
+#
+
+sub StdInit {
+ my($p);
+ return if $stdinit_done;
+ $stdinit_done = 1;
+ if ( defined($project{"OBJECTS_DIR"}) ) {
+ $project{"OBJECTS_DIR"} = FixPath($project{"OBJECTS_DIR"});
+ }
+ if ( defined($project{"MOC_DIR"}) ) {
+ $project{"MOC_DIR"} = FixPath($project{"MOC_DIR"});
+ }
+ $project{"OBJECTS"} = &Objects($project{"SOURCES"});
+ if ( $moc_aware ) {
+ $project{"_HDRMOC"} = &list_moc($project{"HEADERS"},$moc_pre,$cpp_ext);
+ $project{"_SRCMOC"} = &list_moc($project{"SOURCES"},"",$moc_ext);
+ $project{"OBJMOC"} = &Objects($project{"_HDRMOC"});
+ $p = $project{"_HDRMOC"} . " " . $project{"_SRCMOC"};
+ $p =~ s/(^\s+|\s+$)//g;
+ $project{"SRCMOC"} = $p;
+ }
+ &AddIncludePath("");
+}
+
+
+sub FixPath {
+ my($p) = @_;
+ if ( !defined($p) || ($p eq "") || ($p eq ".") ) {
+ $p = "";
+ } else {
+ $p .= $dir_sep;
+ $p =~ s-[\\/]+-${dir_sep}-g;
+ }
+ return $p;
+}
+
+
+#
+# Config(name)
+#
+# Returns true if the project variable CONFIG contains the
+# configuration name.
+#
+
+sub Config {
+ my($name) = @_;
+ return $project{"CONFIG"} =~ /\b\Q$name\E\b/;
+}
+
+
+#
+# DisableOutput()
+#
+# Disables tmake output. Must be restored by calling a corresponding
+# EnableOutput().
+#
+
+sub DisableOutput {
+ $output_count++;
+}
+
+
+#
+# EnableOutput()
+#
+# Enables tmake output again after DisableOutput() has been called.
+#
+
+sub EnableOutput {
+ $output_count--;
+}
+
+
+#
+# Now() - sets $text
+#
+# Sets $text to the current date and time.
+#
+
+sub Now {
+ my($sec,$min,$hour,$mday,$mon,$year);
+ ($sec,$min,$hour,$mday,$mon,$year) = localtime(time());
+ $text = sprintf("%02d:%02d, %4d/%02d/%02d",
+ $hour, $min, 1900+$year, 1+$mon, $mday);
+}
+
+
+#
+# expand_project_val(tag)
+#
+# Internal function for Project().
+# Expands a project value string.
+#
+
+sub expand_project_val {
+ my($v) = @_;
+ my($c);
+ return "" if !defined($v);
+ $v =~ s/^\s+//; # trim white space
+ $v =~ s/\s+$//;
+ $c = 0;
+ while ( $c < 100 ) { # expand $$
+ if ( $v =~ s/(\$\$\w+)/\035/ ) {
+ $_ = $1;
+ s/\$\$//g;
+ if ( !defined($project{$_}) ) {
+ $v =~ s/\035//g;
+ } else {
+ $v =~ s/\035/$project{$_}/g;
+ }
+ $c++;
+ } else {
+ $c = 100;
+ }
+ }
+ return $v;
+}
+
+
+#
+# Project(strings)
+#
+# This is a powerful function for setting or reading project variables.
+# Returns the resulting project variables (joined with space between).
+#
+# Get a project variable:
+# $s = Project("TEMPLATE"); -> $s = "TEMPLATE"
+#
+# Set a project variable:
+# Project("TEMPLATE = lib"); -> TEMPLATE = lib
+# Project("CONFIG =";) -> CONFIG empty
+#
+# Append to a project variable:
+# Project("CONFIG = qt"); -> CONFIG = qt
+# Project("CONFIG += debug"); -> CONFIG = qt debug
+#
+# Append to a project variable if it does not contain the value already:
+# Project("CONFIG = qt release"); -> CONFIG = qt release
+# Project("CONFIG *= qt"); -> CONFIG = qt release
+# Project("CONFIG *= opengl"); -> CONFIG = qt release opengl
+#
+# Subtract from a project variable:
+# Project("THINGS = abc xyz"); -> THINGS = abc xyz
+# Project("THINGS -= abc"); -> THINGS = xyz
+#
+# Search/replace on a project variable:
+# Project("CONFIG = tq opengl"); -> CONFIG = tq opengl
+# Project("CONFIG /= s/tq/qt/"); -> CONFIG = qt opengl
+#
+# The operations can be performed on several project variables at a time.
+#
+# Project("TEMPLATE = app", "CONFIG *= opengl", "THINGS += klm");
+#
+
+sub Project {
+ my @settings = @_;
+ my($r,$if_tag,$t,$s,$v,$p,$c);
+ $r = "";
+ foreach ( @settings ) {
+ $v = $_;
+ if ( $v =~ s/^\s*((?:[^:]*?:)?)(\w+)\s*(\+=|\*=|\-=|\/=|=)\s*// ) {
+ $if_tag = $1;
+ if ( $if_tag ne "" ) {
+ chop $if_tag;
+ if ( $if_tag eq "unix" ) {
+ return "" if !$is_unix;
+ } elsif ( $if_tag eq "win32" ) {
+ return "" if $is_unix;
+ } elsif ( ($if_tag ne $tmake_platform) && !Config($if_tag) ) {
+ return "";
+ }
+ }
+ $t = $2;
+ $s = $3;
+ $v = expand_project_val($v);
+ $p = $project{$t};
+ if ( $s eq "=" ) { # set variable
+ $p = $v;
+ } elsif ( $s eq "+=" ) { # append
+ if ( $p eq "" ) {
+ $p = $v;
+ } else {
+ $p .= " " . $v;
+ }
+ } elsif ( $s eq "*=" ) { # append if not contained
+ if ( !($p =~ /(?:^|\s)\Q$v\E(?:\s|$)/) ) {
+ if ( $p eq "" ) {
+ $p = $v;
+ } else {
+ $p .= " " . $v;
+ }
+ }
+ } elsif ( $s eq "-=" ) { # subtract
+ $p =~ s/$v//g;
+ } elsif ( $s eq "/=" ) { # sed
+ $cmd = '$p =~ ' . $v;
+ eval $cmd;
+ }
+ $project{$t} = expand_project_val($p);
+ } else {
+ $p = expand_project_val($project{$v});
+ }
+ if ( $p ne "" ) {
+ $r = ($r eq "") ? $p : ($r . " " . $p);
+ }
+ }
+ return $r;
+}
+
+
+#
+# Substitute(string)
+#
+# This function substitutes project variables in a text.
+#
+# Example:
+# Substitute('The project name is "$$PROJECT"')
+#
+
+sub Substitute {
+ my($subst) = @_;
+ $text = expand_project_val($subst);
+ return $text;
+}
+
+
+#
+# ScanProject(file)
+#
+# Scans a project file. Inserts project variables into the global
+# associative project array.
+#
+
+sub ScanProject {
+ my($file) = @_;
+ my($tag,$var,@v,$more,$line);
+
+ $tag = "";
+ $line = 0;
+ open(TMP,fix_path($file)) || return 0;
+
+ while ( <TMP> ) {
+ $line++;
+ s/\#.*//; # strip comment
+ s/^\s+//; # strip white space
+ s/\s+$//;
+ if ( /^\s*((?:(?:[^:]*?:)?)\w+\s*(\+|\-|\*|\/)?=)/ ) {
+ $tag = $1; # tag also contains the ".="
+ s/^.*?=\s*//;
+ }
+ if ( $tag ne "" ) {
+ $more = ( $_ =~ s/\s*\\\s*$// ); # more if \ at end of line
+ push( @v, split( /\s+/, $_ ) );
+ if ( ! $more ) {
+ $var = join(" ",@v);
+ Project( $tag . $var );
+ $tag = "";
+ @v = ();
+ }
+ } elsif ( $_ ne "" ) {
+ tmake_error("$file:$line: Syntax error");
+ }
+ }
+ close(TMP);
+ return 1;
+}
+
+
+#
+# IncludeTemplate(template_name)
+#
+# Includes and processes a template file.
+#
+# Below, we read the template file and executes any perl code found.
+# Perl code comes after "#$". The variable $text contains the text
+# to replace the perl code that was executed.
+# Template comments begin with "#!".
+#
+
+sub IncludeTemplate {
+ my($t_name) = @_;
+ my($cmd,$cmd_block,$cmd_end,$is_cmd_block,$saveline,$spaceonly);
+ local($text);
+ local(*T);
+
+ $t_name = &find_template($t_name);
+ if ( $tmake_template_dict{$t_name} ) {
+ &tmake_error("Cyclic template inclusion for $t_name");
+ } else {
+ $tmake_template_dict{$t_name} = 1;
+ }
+ $template_base = $t_name;
+ $template_base =~ s-(.*[/\\]).*-$1-;
+ &tmake_verb("Reading the template $t_name");
+ open(T,fix_path($t_name)) ||
+ &tmake_error("Can't open template file \"$t_name\"");
+
+ while ( <T> ) {
+ if ( /\#\!/ ) { # tmake comment
+ s/\s*\#\!.*//;
+ next if /^$/;
+ }
+ if ( /\#\$(\{)?\s*(.*)\n/ ) { # code
+ $cmd = $2;
+ $is_cmd_block = defined($1) && ($1 eq "{");
+ s/\#\$.*\n//;
+ if ( $is_cmd_block ) { # code block #${ ...
+ $saveline = $_;
+ $cmd_block = $cmd;
+ $cmd_end = 0;
+ while ( <T> ) {
+ $cmd = $_;
+ $cmd =~ s/\s*\#\!.*//; # tmake comment
+ if ( $cmd =~ /^\s*\#\$\}/ ) {
+ $_ = "";
+ $cmd_end = 1;
+ last;
+ }
+ $cmd =~ s/^\s*\#(\$)?\s*//;
+ $cmd_block .= $cmd;
+ }
+ $cmd_end || &tmake_error('#$} expected but not found');
+ $cmd = $cmd_block;
+ $_ = $saveline;
+ }
+ $spaceonly = /^\s*$/;
+ $saveline = $_;
+ &tmake_verb("Evaluate: $cmd");
+ $text = "";
+ eval $cmd;
+ die $@ if $@;
+ next if $spaceonly && ($text =~ /^\s*$/);
+ print $saveline . $text . "\n" if $output_count <= 0;
+ } else { # something else
+ print if $output_count <= 0;
+ }
+ }
+ close( T );
+}
+
+
+#
+# Expand(tag) - appends to $text
+#
+# Expands a list of $project{} variables with a space character between them.
+#
+
+sub Expand {
+ my @tags = @_;
+ my($t);
+ $t = Project(@tags);
+ if ( $text eq "" ) {
+ $text = $t;
+ } elsif ( $t ne "" ) {
+ $text .= " " . $t;
+ }
+ return $text;
+}
+
+
+#
+# ExpandGlue(tag,prepend,glue,append) - appends to $text
+#
+# Expands a $project{} tag, splits on whitespace
+# and joins with $glue. $prepend is put at the start
+# of the string and $append is put at the end of the
+# string. The resulting string becomes "" if the project
+# tag is empty or not defined.
+#
+# Example:
+#
+# The project file defines:
+# SOURCES = a b c
+#
+# ExpandGlue("SOURCES","<","-",">")
+#
+# The result:
+# $text = "<a-b-c>"
+#
+
+sub ExpandGlue {
+ my($tag,$prepend,$glue,$append) = @_;
+ my($t,$v);
+ $v = Project($tag);
+ if ( $v eq "" ) {
+ $t = "";
+ } else {
+ $t = $prepend . join($glue,split(/\s+/,$v)) . $append;
+ }
+ if ( $text eq "" ) {
+ $text = $t;
+ } elsif ( $t ne "" ) {
+ $text .= " " . $t;
+ }
+ return $text;
+}
+
+
+#
+# ExpandList(tag) - sets $text.
+#
+# Suitable for expanding HEADERS = ... etc. in a Makefile
+#
+
+sub ExpandList {
+ my($tag) = @_;
+ return ExpandGlue($tag,""," ${linebreak}\n\t\t","");
+}
+
+
+#
+# TmakeSelf()
+#
+# Generates makefile rule to regenerate the makefile using tmake.
+#
+
+sub TmakeSelf {
+ my $a = "tmake $project_name";
+ if ( $nodepend ) {
+ $a .= " -nodepend";
+ }
+ if ( $outfile ) {
+ $text = "tmake: $outfile\n\n$outfile: $project_name\n\t";
+ $a .= " -o $outfile";
+ } else {
+ $text = "tmake:\n\t";
+ }
+ $text .= $a
+}
+
+
+#
+# Objects(files)
+#
+# Replaces any extension with .o ($obj_ext).
+#
+
+sub Objects {
+ local($_) = @_;
+ my(@a);
+ @a = split(/\s+/,$_);
+ foreach ( @a ) {
+ s-\.\w+$-.${obj_ext}-;
+ if ( defined($project{"OBJECTS_DIR"}) ) {
+ s-^.*[\\/]--;
+ $_ = $project{"OBJECTS_DIR"} . $_;
+ }
+ }
+ return join(" ",@a);
+}
+
+
+#
+# list_moc(files,prefix,extension)
+#
+# Scans all files and selects all files that contain Q_OBJECT.
+# Insert a prefix before the filename and replaces the filename extention.
+#
+
+sub list_moc {
+ my($files,$pre,$ext) = @_;
+ my(@v,@m,@lines,$contents,$n,$f,$t);
+ @v = split(/\s+/,$files);
+ undef $/;
+ foreach $f ( @v ) {
+ if ( open(TMP,fix_path($f)) ) {
+ $contents = <TMP>;
+ close(TMP);
+ $n = 0;
+ @lines = split(/\n/,$contents);
+ grep( /tmake\s+ignore\s+Q_OBJECT/ && $n--, @lines );
+ $contents =~ s-/\*.*?\*/--gs; # strip C/C++ comments
+ $contents =~ s-//.*\n--g;
+ @lines = split(/\n/,$contents);
+ grep( /(^|\W)Q_OBJECT(\W|$)/ && $n++, @lines );
+ if ( $n > 0 ) {
+ $t = $f;
+ $t =~ s-^(.*[/\\])?([^/\\]*?)\.(\w+)$-$1${pre}$2.${ext}-;
+ if ( defined($project{"MOC_DIR"}) ) {
+ $t =~ s-^.*[\\/]--;
+ $t = $project{"MOC_DIR"} . $t;
+ }
+ $moc_output{$f} = $t;
+ $moc_input{$t} = $f;
+ push(@m,$t);
+ }
+ $contents = "";
+ }
+ }
+ $/ = "\n";
+ return join(" ",@m);
+}
+
+
+#
+# BuildObj(objects,sources)
+#
+# Builds the object files.
+#
+
+sub BuildObj {
+ my($obj,$src) = @_;
+ my(@objv,$srcv,$i,$s,$o,$d,$c,$comp,$cimp);
+ @objv = split(/\s+/,$obj);
+ @srcv = split(/\s+/,$src);
+ for $i ( 0..$#objv ) {
+ $s = $srcv[$i];
+ $o = $objv[$i];
+ next if $s eq "";
+ $text .= $o . ": " . $s;
+ if ( defined($moc_output{$s}) && ($moc_output{$s} ne "") ) {
+ $text .= " ${linebreak}\n\t\t" . $moc_output{$s};
+ }
+ $d = &make_depend($s);
+ $text .= " ${linebreak}\n\t\t" . $d if $d ne "";
+ if ( ($s =~ /\.c$/) ) {
+ $comp = "TMAKE_RUN_CC";
+ $cimp = "TMAKE_RUN_CC_IMP";
+ } else {
+ $comp = "TMAKE_RUN_CXX";
+ $cimp = "TMAKE_RUN_CXX_IMP";
+ }
+ if ( defined($project{"OBJECTS_DIR"}) ||
+ !defined($project{$cimp}) ) {
+ $c = $project{$comp};
+ $c =~ s/\$src/$s/;
+ $c =~ s/\$obj/$o/;
+ $text .= "\n\t$c";
+ }
+ $text .= "\n\n";
+ }
+ chop $text;
+}
+
+
+#
+# BuildMocObj(objects,sources)
+#
+# Builds the moc object files.
+#
+
+sub BuildMocObj {
+ my($obj,$src) = @_;
+ my(@objv,$srcv,$i,$s,$o,$hdr,$d);
+ @objv = split(/\s+/,$obj);
+ @srcv = split(/\s+/,$src);
+ for $i ( 0..$#objv ) {
+ $s = $srcv[$i];
+ $o = $objv[$i];
+ $hdr = $moc_input{$srcv[$i]};
+ $text .= $o . ": " . $s . " ${linebreak}\n\t\t" . $hdr;
+ $d = &make_depend($hdr);
+ $text .= " ${linebreak}\n\t\t" . $d if $d ne "";
+ if ( defined($project{"OBJECTS_DIR"}) || defined($project{"MOC_DIR"})||
+ !defined($project{"TMAKE_RUN_CXX_IMP"}) ) {
+ $c = $project{"TMAKE_RUN_CXX"};
+ $c =~ s/\$src/$s/;
+ $c =~ s/\$obj/$o/;
+ $text .= "\n\t$c";
+ }
+ $text .= "\n\n";
+ }
+ chop $text;
+}
+
+
+#
+# BuildMocSrc(files)
+#
+# Builds the moc source files from headers and sources.
+#
+
+sub BuildMocSrc {
+ my($f) = @_;
+ my(@v,$m,$o);
+ @v = split(/\s+/,$f);
+ foreach $m ( @v ) {
+ $o = $moc_output{$m};
+ if ( defined($o) && ($o ne "") ) {
+ $text .= "$o: $m\n\t$moc_cmd $m -o $o\n\n";
+ }
+ }
+ chop $text;
+}
+
+
+#
+# AddIncludePath(path)
+#
+# Adds path to the current include path, $project{"INCLUDEPATH"}.
+#
+
+sub AddIncludePath {
+ my($path) = @_;
+ my($p);
+ if ( $project{"INCPATH"} &&
+ ($project{"INCPATH"} =~ /(?:^|\s)\Q$path\E(?:\s|$)/) ) {
+ return;
+ }
+ $project{"INCLUDEPATH"} = "" if !defined($project{"INCLUDEPATH"});
+ $p = $project{"INCLUDEPATH"};
+ $p = ($p && $path) ? ($p . ";" . $path) : ($p . $path);
+ $project{"INCLUDEPATH"} = $p;
+ $p = join(" ",&split_path($p));
+ $p =~ s=[\\/](\s|$)= =g;
+ $project{"INCPATH"} = $p;
+}
+
+
+#
+# FindHighestLibVersion(dir,name)
+#
+# Returns the newest library version. Scans all the files in the specifies
+# directory and returns the highest version number.
+#
+# Used on Windows only.
+#
+# Example:
+# FindHighestLibVersion("c:\qt\lib","qt") returns "200" if
+# the c:\qt\lib directory contains qt141.lib and qt200.lib.
+#
+
+sub FindHighestLibVersion {
+ my($dir,$name) = @_;
+ my(@files,$f,$v,$highest);
+ $highest = "";
+ @files = find_files($dir,"${name}.*\.lib");
+ for $f ( @files ) {
+ if ( $f =~ /(\d+)\.lib/ ) {
+ $v = $1;
+ if ( $highest eq "" || $v > $highest ) {
+ $highest = $v;
+ }
+ }
+ }
+ return $highest;
+}
+
+
+#
+# Finds files.
+#
+# Examples:
+# find_files("/usr","\.cpp$",1) - finds .cpp files in /usr and below
+# find_files("/tmp","^#",0) - finds #* files in /tmp
+#
+
+sub find_files {
+ my($dir,$match,$descend) = @_;
+ my($file,$p,@files);
+ local(*D);
+ $dir =~ s=\\=/=g;
+ ($dir eq "") && ($dir = ".");
+ if ( opendir(D,fix_path($dir)) ) {
+ if ( $dir eq "." ) {
+ $dir = "";
+ } else {
+ ($dir =~ /\/$/) || ($dir .= "/");
+ }
+ foreach $file ( readdir(D) ) {
+ next if ( $file =~ /^\.\.?$/ );
+ $p = $dir . $file;
+ if ( $is_unix ) {
+ ($file =~ /$match/) && (push @files, $p);
+ } else {
+ ($file =~ /$match/i) && (push @files, $p);
+ }
+ if ( $descend && -d $p && ! -l $p ) {
+ push @files, &find_files($p,$match,$descend);
+ }
+ }
+ closedir(D);
+ }
+ return @files;
+}
+
+
+#
+# make_depend(file)
+#
+# Returns a list of included files.
+# Uses the global $depend_path variable.
+#
+
+sub make_depend {
+ my($file) = @_;
+ my($i,$count);
+ if ( $nodepend ) {
+ return "";
+ }
+ if ( ! $depend_path_fixed ) {
+ $depend_path_fixed = 1;
+ if ( defined($project{"DEPENDPATH"}) ) {
+ $depend_path = $project{"DEPENDPATH"};
+ } else {
+ $depend_path = "";
+ }
+ $count = 0;
+ while ( $count < 100 ) {
+ if ( $depend_path =~ s/(\$[\{\(]?\w+[\}\)]?)/035/ ) {
+ $_ = $1;
+ s/[\$\{\}\(\)]//g;
+ $depend_path =~ s/035/$ENV{$_}/g;
+ } else {
+ $count = 100;
+ }
+ }
+ @dep_path = &split_path($depend_path);
+ }
+ @cur_dep_path = @dep_path;
+ if ( $file =~ /(.*[\/\\])/ ) {
+ $dep_curdir = $1;
+ splice( @cur_dep_path, 0, 0, $dep_curdir );
+ } else {
+ $dep_curdir = "";
+ }
+ $dep_file = $file;
+ &canonical_dep($file);
+ %dep_dict = ();
+ $i = &build_dep($file);
+ chop $i;
+ $i =~ s=/=$dir_sep=g unless $is_unix;
+ $i =~ s=([a-zA-Z]):/=//$1/=g if (defined($gnuwin32) && $gnuwin32);
+ return join(" ${linebreak}\n\t\t",split(/ /,$i) );
+}
+
+#
+# build_dep() - Internal for make_depend()
+#
+
+sub build_dep {
+ my($file) = @_;
+ my(@i,$a,$n);
+ $a = "";
+ return $a if !(defined $depend_dict{$file});
+ @i = split(/ /,$depend_dict{$file});
+ for $n ( @i ) {
+ if ( !defined($dep_dict{$n}) && defined($full_path{$n}) ) {
+ $dep_dict{$n} = 1;
+ $a .= $full_path{$n} . " " . &build_dep($n);
+ }
+ }
+ return $a;
+}
+
+#
+# canonical_dep(file) - Internal for make_depend()
+#
+# Reads the file and all included files recursively.
+# %depend_dict associates a file name to a list of included files.
+#
+
+sub canonical_dep {
+ my($file) = @_;
+ my(@inc,$i);
+ @inc = &scan_dep($file);
+ if ( @inc ) {
+ $depend_dict{$file} = join(" ",@inc);
+ for $i ( @inc ) {
+ &canonical_dep($i) if !defined($depend_dict{$i});
+ }
+ }
+}
+
+#
+# scan_dep(file) - Internal for make_depend()
+#
+# Returns an array of included files.
+#
+
+sub scan_dep {
+ my($file) = @_;
+ my($dir,$path,$found,@allincs,@includes,%incs);
+ $path = ($file eq $dep_file) ? $file : $dep_curdir . $file;
+ @includes = ();
+ return @includes if $file =~ /\.$moc_ext$/; # avoid .moc files
+ if ( ! (-f fix_path($path)) ) {
+ $found = 0;
+ for $dir ( @cur_dep_path ) {
+ $path = $dir . $file;
+ last if ( $found = (-f fix_path($path)) );
+ }
+ return @includes if ! $found;
+ }
+ undef $/;
+ if ( open(TMP,fix_path($path)) ) {
+ $full_path{$file} = $path;
+ $_ = <TMP>;
+ s-/\*.*?\*/--gs; # strip C/C++ comments
+ s-//.*\n-\n-g;
+ @allincs = split(/\n/,$_);
+ @allincs = grep(/^\s*#\s*include/,@allincs);
+ foreach ( @allincs ) { # all #include lines
+ next if !(/^\s*#\s*include\s+[<"]([^>"]*)[>"]/) || defined($incs{$1});
+ push(@includes,$1);
+ $incs{$1} = "1";
+ }
+ close(TMP);
+ }
+ $/ = "\n";
+ return @includes;
+}
+
+
+#
+# split_path(path)
+#
+# Splits a path containing : (Unix) or ; (MSDOS, NT etc.) separators.
+# Returns an array.
+#
+
+sub split_path {
+ my($p) = @_;
+ return "" if !defined($p);
+ $p =~ s=:=;=g if $is_unix;
+ $p =~ s=[/\\]+=/=g;
+ $p =~ s=([^/:]);=$1/;=g;
+ $p =~ s=([^:;/])$=$1/=;
+ $p =~ s=/=$dir_sep=g unless $is_unix;
+ return split(/;/,$p);
+}
+
+
+#
+# fix_path(path)
+#
+# Converts all '\' to '/' if this really seems to be a Unix box.
+#
+
+sub fix_path {
+ my($p) = @_;
+ if ( $really_unix ) {
+ $p =~ s-\\-/-g;
+ } else {
+ $p =~ s-/-\\-g;
+ }
+ return $p;
+}
diff --git a/tmake/bin/tmake.bat b/tmake/bin/tmake.bat
new file mode 100644
index 0000000..6fbd6b2
--- /dev/null
+++ b/tmake/bin/tmake.bat
@@ -0,0 +1,1093 @@
+@rem = '--*-PERL-*--';
+@rem = '
+@echo off
+rem setlocal
+set ARGS=
+:loop
+if .%1==. goto endloop
+set ARGS=%ARGS% %1
+shift
+goto loop
+:endloop
+rem ***** This assumes PERL is in the PATH *****
+perl.exe -S tmake.bat %ARGS%
+goto endofperl
+@rem ';
+#!/usr/bin/perl
+############################################################################
+# $Id$
+#
+# Creates a Makefile from a template and a project file.
+#
+# Copyright (C) 1996-1998 by Troll Tech AS. All rights reserved.
+#
+# Permission to use, copy, modify, and distribute this software and its
+# documentation for any purpose and without fee is hereby granted, provided
+# that this copyright notice appears in all copies.
+# No representations are made about the suitability of this software for any
+# purpose. It is provided "as is" without express or implied warranty.
+#
+#
+# Some important, global variables in tmake:
+# cpp_ext C++ extension added to moc output (.cpp)
+# obj_ext Object file extension (.o on Unix, .obj otherwise)
+# moc_aware Will scan for files containing Qt signals/slots
+# moc_pre Moc prefix for generated moc file: x.h -> moc_x.cpp
+# moc_ext Moc extension for generated moc file: x.cpp -> x.moc
+# moc_cmd The moc command in your makefile, $(MOC)
+# linebreak Line break character (\)
+# dir_sep Directory separator (/ on Unix, \ on Windows)
+# is_unix Autodetected. If not Unix, assume Windows (Win32).
+#
+# If you need to customize any of these settings, do it before
+# calling StdInit() in the template file.
+#
+############################################################################
+
+if ($] < 5.0) {
+ &tmake_error("This program requires perl version 5 or newer");
+}
+
+$cpp_ext = "cpp";
+$obj_ext = "o";
+$moc_aware = 0;
+$moc_pre = "moc_";
+$moc_ext = "moc";
+$moc_cmd = '$(MOC)';
+$linebreak = "\\";
+$dir_sep = "/";
+$is_unix = 1;
+$really_unix = &check_unix();
+$guess_os = 1;
+$depend_path = "";
+$nodepend = 0;
+$output_count = 0;
+
+$template_name = "";
+$project_name = "";
+$outfile = "";
+@project_extra = ();
+@project_files = ();
+@eval_expr = ();
+$eval_done = 0;
+
+while ( @ARGV ) { # parse command line args
+ $_ = shift @ARGV;
+ if ( s/^-// ) {
+ if ( /^e(.*)/ ) {
+ push( @eval_expr, ($1 eq "") ? shift @ARGV : $1);
+ } elsif ( /^t(.*)/ ) {
+ $template_name = ($1 eq "") ? shift @ARGV : $1;
+ } elsif ( /^o(.*)/ ) {
+ $outfile = ($1 eq "") ? shift @ARGV : $1;
+ ($outfile eq "-") && ($outfile = "");
+ } elsif ( /^p(.*)/ ) {
+ push( @project_files, ($1 eq "") ? shift @ARGV : $1);
+ } elsif ( /^unix$/ ) {
+ $guess_os = 0;
+ $is_unix = 1;
+ } elsif ( /^win32$/ ) {
+ $guess_os = 0;
+ $is_unix = 0;
+ } elsif ( /^nodepend$/ ) {
+ $nodepend = 1; # don't generate dependencies
+ } elsif ( /^v$/ ) {
+ $verbose = 1;
+ } else {
+ &tmake_usage();
+ }
+ } elsif ( /^\s*(?:[\w\-]+:)?\w+\s*[\+\-\*\/]?=/ ) { # project override
+ push( @project_extra, $_ );
+ } else {
+ $project_name &&
+ &tmake_error("You can only specify one project file");
+ $project_name = $_;
+ }
+}
+
+($project_name ne "") || &tmake_usage();
+
+if ( $guess_os && ! check_unix() ) { # probably non-Unix,
+ $is_unix = 0;
+ &tmake_verb("Win32 detected");
+}
+if ( ! $is_unix ) {
+ $obj_ext = "obj";
+ $dir_sep = "\\";
+}
+$outfile eq "" || open(STDOUT,">" . fix_path($outfile)) ||
+ &tmake_error("Can't create \"$outfile\"");
+
+%project = ();
+&ScanProject( &find_template("tmake.conf") );
+&tmake_verb("Reading the project file $project_name");
+if ( ! ($project_name =~ /\.pro$/i) && -f fix_path($project_name . ".pro") ) {
+ $project_name .= ".pro";
+}
+$project{"PROJECT"} = $project_name;
+$project{"PROJECT"} =~ s/\.pro$//i;
+$project{"TARGET"} = $project{"PROJECT"};
+
+unshift(@project_files,$project_name);
+foreach ( @project_files ) {
+ if ( ! ($_ =~ /\.pro$/i) && -f fix_path($_ . ".pro") ) {
+ $_ .= ".pro";
+ }
+ if ( !&ScanProject($_) ) {
+ &tmake_error("Can't open project file \"$_\"");
+ }
+}
+&Project( @project_extra );
+
+if ( $template_name eq "" ) {
+ $template_name = $project{"TEMPLATE"} ?
+ $project{"TEMPLATE"} : "default.t";
+}
+
+foreach ( @eval_expr ) {
+ $text = "";
+ eval( $_ );
+ die $@ if $@;
+ print $text . "\n" if ($text ne "");
+ $eval_done = 1;
+}
+if ( $eval_done ) {
+ &tmake_verb("Done!");
+ exit 0;
+}
+
+$template_name = &find_template($template_name);
+&IncludeTemplate($template_name);
+&tmake_verb("Done!");
+exit 0; # finished!
+
+
+
+##############################################################################
+# Subroutines from here
+##############################################################################
+
+#
+# tmake_usage()
+#
+# Prints a message about program usage and exits
+#
+
+sub tmake_usage {
+ print STDERR "Usage:\n tmake [options] project-file\n";
+ print STDERR "Options:\n";
+ print STDERR " -e expr Evaluate expression, ignore template file\n";
+ print STDERR " -nodepend Don't generate dependency information\n";
+ print STDERR " -o file Write output to file\n";
+ print STDERR " -p project Load additional project file\n";
+ print STDERR " -t file Specify a template file\n";
+ print STDERR " -unix Create output for Unix (auto detects)\n";
+ print STDERR " -v Verbose/debug mode\n";
+ print STDERR " -win32 Create output for Win32 (auto detects)\n";
+ exit 1;
+}
+
+
+#
+# tmake_error(msg)
+#
+# Prints the message and exits
+#
+
+sub tmake_error {
+ my($msg) = @_;
+ print STDERR "tmake error: " . $msg . "\n";
+ exit 1;
+}
+
+
+#
+# tmake_verb()
+#
+# Prints a verbose message
+#
+
+sub tmake_verb {
+ my($msg) = @_;
+ $verbose && print STDERR "tmake: " . $msg . "\n";
+}
+
+
+#
+# check_unix()
+#
+# Returns 1 if this is a Unix, 0 otherwise.
+#
+
+sub check_unix {
+ my($r);
+ $r = 0;
+ if ( -f "/bin/uname" ) {
+ $r = 1;
+ (-f "\\bin\\uname") && ($r = 0);
+ }
+ return $r;
+}
+
+
+#
+# find_template(filename)
+#
+# Looks for the template file.
+# 1. search the current directory
+# 2. search the directories in TMAKEPATH
+# 3. search in $HOME/.tmake
+#
+
+sub find_template {
+ my($filename) = @_;
+ my($tb,$d,$p,@dirs);
+ $tb = ($template_base eq "") ? "" : $template_base . ";";
+ $d = ";" . $tb . $ENV{"TMAKEPATH"} . ";" . $ENV{"HOME"} . "/.tmake/";
+ @dirs = &split_path( $d );
+ $filename .= ".t" unless ($filename =~ /\.\w+$/);
+ for $d ( @dirs ) {
+ $p = $d . $filename;
+ if ( -f fix_path($p) ) {
+ if ( $filename eq "tmake.conf" ) {
+ $tmake_platform = $d;
+ $tmake_platform =~ s-.*[/\\]([^/\\]*)[/\\]-$1-;
+ &tmake_verb("Detected platform $tmake_platform");
+ }
+ return $p;
+ }
+ return ($d . $filename) if ( -f fix_path($d . $filename) );
+ }
+ &tmake_error("Template file " . $filename . " not found");
+}
+
+
+##############################################################################
+# User functions
+##############################################################################
+
+#
+# StdInit()
+#
+# Standard initialization
+#
+
+sub StdInit {
+ my($p);
+ return if $stdinit_done;
+ $stdinit_done = 1;
+ if ( defined($project{"OBJECTS_DIR"}) ) {
+ $project{"OBJECTS_DIR"} = FixPath($project{"OBJECTS_DIR"});
+ }
+ if ( defined($project{"MOC_DIR"}) ) {
+ $project{"MOC_DIR"} = FixPath($project{"MOC_DIR"});
+ }
+ $project{"OBJECTS"} = &Objects($project{"SOURCES"});
+ if ( $moc_aware ) {
+ $project{"_HDRMOC"} = &list_moc($project{"HEADERS"},$moc_pre,$cpp_ext);
+ $project{"_SRCMOC"} = &list_moc($project{"SOURCES"},"",$moc_ext);
+ $project{"OBJMOC"} = &Objects($project{"_HDRMOC"});
+ $p = $project{"_HDRMOC"} . " " . $project{"_SRCMOC"};
+ $p =~ s/(^\s+|\s+$)//g;
+ $project{"SRCMOC"} = $p;
+ }
+ &AddIncludePath("");
+}
+
+
+sub FixPath {
+ my($p) = @_;
+ if ( $p eq "." ) { $p = ""; }
+ elsif ( length($p) > 0 ) {
+ $p .= $dir_sep;
+ $p =~ s-[\\/]+-${dir_sep}-g;
+ }
+ return $p;
+}
+
+
+#
+# Config(name)
+#
+# Returns true if the project variable CONFIG contains the
+# configuration name.
+#
+
+sub Config {
+ my($name) = @_;
+ return $project{"CONFIG"} =~ /\b$name\b/;
+}
+
+
+#
+# DisableOutput()
+#
+# Disables tmake output. Must be restored by calling a corresponding
+# EnableOutput().
+#
+
+sub DisableOutput {
+ $output_count++;
+}
+
+
+#
+# EnableOutput()
+#
+# Enables tmake output again after DisableOutput() has been called.
+#
+
+sub EnableOutput {
+ $output_count--;
+}
+
+
+#
+# Now() - sets $text
+#
+# Sets $text to the current date and time.
+#
+
+sub Now {
+ my($sec,$min,$hour,$mday,$mon,$year);
+ ($sec,$min,$hour,$mday,$mon,$year) = localtime(time());
+ $text = sprintf("%02d:%02d, %4d/%02d/%02d",
+ $hour, $min, 1900+$year, 1+$mon, $mday);
+}
+
+
+#
+# expand_project_val(tag)
+#
+# Internal function for Project().
+# Expands a project value string.
+#
+
+sub expand_project_val {
+ my($v) = @_;
+ my($c);
+ $v =~ s/^\s+//; # trim white space
+ $v =~ s/\s+$//;
+ $c = 0;
+ while ( $c < 100 ) { # expand $$
+ if ( $v =~ s/(\$\$\w+)/\035/ ) {
+ $_ = $1;
+ s/\$\$//g;
+ $v =~ s/\035/$project{$_}/g;
+ $c++;
+ } else {
+ $c = 100;
+ }
+ }
+ return $v;
+}
+
+
+#
+# Project(strings)
+#
+# This is a powerful function for setting or reading project variables.
+# Returns the resulting project variables (joined with space between).
+#
+# Get a project variable:
+# $s = Project("TEMPLATE"); -> $s = "TEMPLATE"
+#
+# Set a project variable:
+# Project("TEMPLATE = lib"); -> TEMPLATE = lib
+# Project("CONFIG =";) -> CONFIG empty
+#
+# Append to a project variable:
+# Project("CONFIG = qt"); -> CONFIG = qt
+# Project("CONFIG += debug"); -> CONFIG = qt debug
+#
+# Append to a project variable if it does not contain the value already:
+# Project("CONFIG = qt release"); -> CONFIG = qt release
+# Project("CONFIG *= qt"); -> CONFIG = qt release
+# Project("CONFIG *= opengl"); -> CONFIG = qt release opengl
+#
+# Subtract from a project variable:
+# Project("THINGS = abc xyz"); -> THINGS = abc xyz
+# Project("THINGS -= abc"); -> THINGS = xyz
+#
+# Search/replace on a project variable:
+# Project("CONFIG = tq opengl"); -> CONFIG = tq opengl
+# Project("CONFIG /= s/tq/qt/"); -> CONFIG = qt opengl
+#
+# The operations can be performed on several project variables at a time.
+#
+# Project("TEMPLATE = app", "CONFIG *= opengl", "THINGS += klm");
+#
+
+sub Project {
+ my @settings = @_;
+ my($r,$if_tag,$t,$s,$v,$p,$c);
+ $r = "";
+ foreach ( @settings ) {
+ $v = $_;
+ if ( $v =~ s/^\s*([\w\-]+:)?(\w+)\s*(\+=|\*=|\-=|\/=|=)\s*// ) {
+ $if_tag = $1;
+ if ( $if_tag ne "" ) {
+ chop $if_tag;
+ if ( $if_tag eq "unix" ) {
+ return "" if !$is_unix;
+ } elsif ( $if_tag eq "win32" ) {
+ return "" if $is_unix;
+ } elsif ( ($if_tag ne $tmake_platform) && !Config($if_tag) ) {
+ return "";
+ }
+ }
+ $t = $2;
+ $s = $3;
+ $v = expand_project_val($v);
+ $p = $project{$t};
+ if ( $s eq "=" ) { # set variable
+ $p = $v;
+ } elsif ( $s eq "+=" ) { # append
+ if ( $p eq "" ) {
+ $p = $v;
+ } else {
+ $p .= " " . $v;
+ }
+ } elsif ( $s eq "*=" ) { # append if not contained
+ if ( !($p =~ /(?:^|\s)\Q$v\E(?:\s|$)/) ) {
+ if ( $p eq "" ) {
+ $p = $v;
+ } else {
+ $p .= " " . $v;
+ }
+ }
+ } elsif ( $s eq "-=" ) { # subtract
+ $p =~ s/$v//g;
+ } elsif ( $s eq "/=" ) { # sed
+ $cmd = '$p =~ ' . $v;
+ eval $cmd;
+ }
+ $project{$t} = expand_project_val($p);
+ } else {
+ $p = expand_project_val($project{$v});
+ }
+ if ( $p ne "" ) {
+ $r = ($r eq "") ? $p : ($r . " " . $p);
+ }
+ }
+ return $r;
+}
+
+
+#
+# Substitute(string)
+#
+# This function substitutes project variables in a text.
+#
+# Example:
+# Substitute('The project name is "$$PROJECT"')
+#
+
+sub Substitute {
+ my($subst) = @_;
+ $text = expand_project_val($subst);
+ return $text;
+}
+
+
+#
+# ScanProject(file)
+#
+# Scans a project file. Inserts project variables into the global
+# associative project array.
+#
+
+sub ScanProject {
+ my($file) = @_;
+ my($tag,$var,@v,$more,$line);
+
+ $tag = "";
+ $line = 0;
+ open(TMP,fix_path($file)) || return 0;
+
+ while ( <TMP> ) {
+ $line++;
+ s/\#.*//; # strip comment
+ s/^\s+//; # strip white space
+ s/\s+$//;
+ if ( /^\s*((?:[\w\-]+:)?\w+\s*(\+|\-|\*|\/)?=)/ ) {
+ $tag = $1; # tag also contains the ".="
+ s/^.*?=\s*//;
+ }
+ if ( $tag ne "" ) {
+ $more = ( $_ =~ s/\s*\\\s*$// ); # more if \ at end of line
+ push( @v, split( /\s+/, $_ ) );
+ if ( ! $more ) {
+ $var = join(" ",@v);
+ Project( $tag . $var );
+ $tag = "";
+ @v = ();
+ }
+ } elsif ( $_ ne "" ) {
+ tmake_error("$file:$line: Syntax error");
+ }
+ }
+ close(TMP);
+ return 1;
+}
+
+
+#
+# IncludeTemplate(template_name)
+#
+# Includes and processes a template file.
+#
+# Below, we read the template file and executes any perl code found.
+# Perl code comes after "#$". The variable $text contains the text
+# to replace the perl code that was executed.
+# Template comments begin with "#!".
+#
+
+sub IncludeTemplate {
+ my($t_name) = @_;
+ my($cmd,$cmd_block,$cmd_end,$is_cmd_block,$saveline,$spaceonly);
+ local($text);
+ local(*T);
+
+ $t_name = &find_template($t_name);
+ if ( $tmake_template_dict{$t_name} ) {
+ &tmake_error("Cyclic template inclusion for $t_name");
+ } else {
+ $tmake_template_dict{$t_name} = 1;
+ }
+ $template_base = $t_name;
+ $template_base =~ s-(.*[/\\]).*-$1-;
+ &tmake_verb("Reading the template $t_name");
+ open(T,fix_path($t_name)) ||
+ &tmake_error("Can't open template file \"$t_name\"");
+
+ while ( <T> ) {
+ if ( /\#\!/ ) { # tmake comment
+ s/\s*\#\!.*//;
+ next if /^$/;
+ }
+ if ( /\#\$(\{)?\s*(.*)\n/ ) { # code
+ $cmd = $2;
+ $is_cmd_block = ($1 eq "{");
+ s/\#\$.*\n//;
+ if ( $is_cmd_block ) { # code block #${ ...
+ $saveline = $_;
+ $cmd_block = $cmd;
+ $cmd_end = 0;
+ while ( <T> ) {
+ $cmd = $_;
+ $cmd =~ s/\s*\#\!.*//; # tmake comment
+ if ( $cmd =~ /^\s*\#\$\}/ ) {
+ $_ = "";
+ $cmd_end = 1;
+ last;
+ }
+ $cmd =~ s/^\s*\#(\$)?\s*//;
+ $cmd_block .= $cmd;
+ }
+ $cmd_end || &tmake_error('#$} expected but not found');
+ $cmd = $cmd_block;
+ $_ = $saveline;
+ }
+ $spaceonly = /^\s*$/;
+ $saveline = $_;
+ &tmake_verb("Evaluate: $cmd");
+ $text = "";
+ eval $cmd;
+ die $@ if $@;
+ next if $spaceonly && ($text =~ /^\s*$/);
+ print $saveline . $text . "\n" if $output_count <= 0;
+ } else { # something else
+ print if $output_count <= 0;
+ }
+ }
+ close( T );
+}
+
+
+#
+# Expand(tag) - appends to $text
+#
+# Expands a list of $project{} variables with a space character between them.
+#
+
+sub Expand {
+ my @tags = @_;
+ my($t);
+ $t = Project(@tags);
+ if ( $text eq "" ) {
+ $text = $t;
+ } elsif ( $t ne "" ) {
+ $text .= " " . $t;
+ }
+ return $text;
+}
+
+
+#
+# ExpandGlue(tag,prepend,glue,append) - appends to $text
+#
+# Expands a $project{} tag, splits on whitespace
+# and joins with $glue. $prepend is put at the start
+# of the string and $append is put at the end of the
+# string. The resulting string becomes "" if the project
+# tag is empty or not defined.
+#
+# Example:
+#
+# The project file defines:
+# SOURCES = a b c
+#
+# ExpandGlue("SOURCES","<","-",">")
+#
+# The result:
+# $text = "<a-b-c>"
+#
+
+sub ExpandGlue {
+ my($tag,$prepend,$glue,$append) = @_;
+ my($t,$v);
+ $v = Project($tag);
+ if ( $v eq "" ) {
+ $t = "";
+ } else {
+ $t = $prepend . join($glue,split(/\s+/,$v)) . $append;
+ }
+ if ( $text eq "" ) {
+ $text = $t;
+ } elsif ( $t ne "" ) {
+ $text .= " " . $t;
+ }
+ return $text;
+}
+
+
+#
+# ExpandList(tag) - sets $text.
+#
+# Suitable for expanding HEADERS = ... etc. in a Makefile
+#
+
+sub ExpandList {
+ my($tag) = @_;
+ return ExpandGlue($tag,""," ${linebreak}\n\t\t","");
+}
+
+
+#
+# TmakeSelf()
+#
+# Generates makefile rule to regenerate the makefile using tmake.
+#
+
+sub TmakeSelf {
+ my $a = "tmake $project_name";
+ if ( $nodepend ) {
+ $a .= " -nodepend";
+ }
+ if ( $outfile ) {
+ $text = "tmake: $outfile\n\n$outfile: $project_name\n\t";
+ $a .= " -o $outfile";
+ } else {
+ $text = "tmake:\n\t";
+ }
+ $text .= $a
+}
+
+
+#
+# Objects(files)
+#
+# Replaces any extension with .o ($obj_ext).
+#
+
+sub Objects {
+ local($_) = @_;
+ my(@a);
+ @a = split(/\s+/,$_);
+ foreach ( @a ) {
+ s-\.\w+$-.${obj_ext}-;
+ if ( defined($project{"OBJECTS_DIR"}) ) {
+ s-^.*[\\/]--;
+ $_ = $project{"OBJECTS_DIR"} . $_;
+ }
+ }
+ return join(" ",@a);
+}
+
+
+#
+# list_moc(files,prefix,extension)
+#
+# Scans all files and selects all files that contain Q_OBJECT.
+# Insert a prefix before the filename and replaces the filename extention.
+#
+
+sub list_moc {
+ my($files,$pre,$ext) = @_;
+ my(@v,@m,@lines,$contents,$n,$f,$t);
+ @v = split(/\s+/,$files);
+ undef $/;
+ foreach $f ( @v ) {
+ if ( open(TMP,fix_path($f)) ) {
+ $contents = <TMP>;
+ close(TMP);
+ $n = 0;
+ @lines = split(/\n/,$contents);
+ grep( /tmake\s+ignore\s+Q_OBJECT/ && $n--, @lines );
+ $contents =~ s-/\*.*?\*/--gs; # strip C/C++ comments
+ $contents =~ s-//.*\n--g;
+ @lines = split(/\n/,$contents);
+ grep( /(^|\W)Q_OBJECT(\W|$)/ && $n++, @lines );
+ if ( $n > 0 ) {
+ $t = $f;
+ $t =~ s-^(.*[/\\])?([^/\\]*?)\.(\w+)$-$1${pre}$2.${ext}-;
+ if ( defined($project{"MOC_DIR"}) ) {
+ $t =~ s-^.*[\\/]--;
+ $t = $project{"MOC_DIR"} . $t;
+ }
+ $moc_output{$f} = $t;
+ $moc_input{$t} = $f;
+ push(@m,$t);
+ }
+ $contents = "";
+ }
+ }
+ $/ = "\n";
+ return join(" ",@m);
+}
+
+
+#
+# BuildObj(objects,sources)
+#
+# Builds the object files.
+#
+
+sub BuildObj {
+ my($obj,$src) = @_;
+ my(@objv,$srcv,$i,$s,$o,$d,$c);
+ @objv = split(/\s+/,$obj);
+ @srcv = split(/\s+/,$src);
+ for $i ( 0..$#objv ) {
+ $s = $srcv[$i];
+ $o = $objv[$i];
+ next if $s eq "";
+ $text .= $o . ": " . $s;
+ if ( $moc_output{$s} ne "" ) {
+ $text .= " ${linebreak}\n\t\t" . $moc_output{$s};
+ }
+ $d = &make_depend($s);
+ $text .= " ${linebreak}\n\t\t" . $d if $d ne "";
+ if ( defined($project{"OBJECTS_DIR"}) ||
+ !defined($project{"TMAKE_COMPILE_IMP"}) ) {
+ $c = $project{"TMAKE_COMPILE"};
+ $c =~ s/\$src/$s/;
+ $c =~ s/\$obj/$o/;
+ $text .= "\n\t$c";
+ }
+ $text .= "\n\n";
+ }
+ chop $text;
+}
+
+
+#
+# BuildMocObj(objects,sources)
+#
+# Builds the moc object files.
+#
+
+sub BuildMocObj {
+ my($obj,$src) = @_;
+ my(@objv,$srcv,$i,$s,$o,$hdr,$d);
+ @objv = split(/\s+/,$obj);
+ @srcv = split(/\s+/,$src);
+ for $i ( 0..$#objv ) {
+ $s = $srcv[$i];
+ $o = $objv[$i];
+ $hdr = $moc_input{$srcv[$i]};
+ $text .= $o . ": " . $s . " ${linebreak}\n\t\t" . $hdr;
+ $d = &make_depend($hdr);
+ $text .= " ${linebreak}\n\t\t" . $d if $d ne "";
+ if ( defined($project{"OBJECTS_DIR"}) || defined($project{"MOC_DIR"})||
+ !defined($project{"TMAKE_COMPILE_IMP"}) ) {
+ $c = $project{"TMAKE_COMPILE"};
+ $c =~ s/\$src/$s/;
+ $c =~ s/\$obj/$o/;
+ $text .= "\n\t$c";
+ }
+ $text .= "\n\n";
+ }
+ chop $text;
+}
+
+
+#
+# BuildMocSrc(files)
+#
+# Builds the moc source files from headers and sources.
+#
+
+sub BuildMocSrc {
+ my($f) = @_;
+ my(@v,$m,$o);
+ @v = split(/\s+/,$f);
+ foreach $m ( @v ) {
+ $o = $moc_output{$m};
+ if ( $o ne "" ) {
+ $text .= "$o: $m\n\t$moc_cmd $m -o $o\n\n";
+ }
+ }
+ chop $text;
+}
+
+
+#
+# AddIncludePath(path)
+#
+# Adds path to the current include path, $project{"INCLUDEPATH"}.
+#
+
+sub AddIncludePath {
+ my($path) = @_;
+ my($p);
+ if ( $project{"INCPATH"} &&
+ ($project{"INCPATH"} =~ /(?:^|\s)\Q$path\E(?:\s|$)/) ) {
+ return;
+ }
+ $p = $project{"INCLUDEPATH"};
+ $p = ($p && $path) ? ($p . ";" . $path) : ($p . $path);
+ $project{"INCLUDEPATH"} = $p;
+ $p = join(" ",&split_path($p));
+ $p =~ s=[\\/](\s|$)= =g;
+ $project{"INCPATH"} = $p;
+}
+
+
+#
+# FindHighestLibVersion(dir,name)
+#
+# Returns the newest library version. Scans all the files in the specifies
+# directory and returns the highest version number.
+#
+# Used on Windows only.
+#
+# Example:
+# FindHighestLibVersion("c:\qt\lib","qt") returns "200" if
+# the c:\qt\lib directory contains qt141.lib and qt200.lib.
+#
+
+sub FindHighestLibVersion {
+ my($dir,$name) = @_;
+ my(@files,$f,$v,$highest);
+ $highest = "";
+ @files = find_files($dir,"${name}.*\.lib");
+ for $f ( @files ) {
+ if ( $f =~ /(\d+)\.lib/ ) {
+ $v = $1;
+ if ( $highest eq "" || $v > $highest ) {
+ $highest = $v;
+ }
+ }
+ }
+ return $highest;
+}
+
+
+#
+# Finds files.
+#
+# Examples:
+# find_files("/usr","\.cpp$",1) - finds .cpp files in /usr and below
+# find_files("/tmp","^#",0) - finds #* files in /tmp
+#
+
+sub find_files {
+ my($dir,$match,$descend) = @_;
+ my($file,$p,@files);
+ local(*D);
+ $dir =~ s=\\=/=g;
+ ($dir eq "") && ($dir = ".");
+ if ( opendir(D,fix_path($dir)) ) {
+ if ( $dir eq "." ) {
+ $dir = "";
+ } else {
+ ($dir =~ /\/$/) || ($dir .= "/");
+ }
+ foreach $file ( readdir(D) ) {
+ next if ( $file =~ /^\.\.?$/ );
+ $p = $dir . $file;
+ if ( $is_unix ) {
+ ($file =~ /$match/) && (push @files, $p);
+ } else {
+ ($file =~ /$match/i) && (push @files, $p);
+ }
+ if ( $descend && -d $p && ! -l $p ) {
+ push @files, &find_files($p,$match,$descend);
+ }
+ }
+ closedir(D);
+ }
+ return @files;
+}
+
+
+#
+# make_depend(file)
+#
+# Returns a list of included files.
+# Uses the global $depend_path variable.
+#
+
+sub make_depend {
+ my($file) = @_;
+ my($i,$count);
+ if ( $nodepend ) {
+ return "";
+ }
+ if ( ! $depend_path_fixed ) {
+ $depend_path_fixed = 1;
+ $depend_path = $project{"DEPENDPATH"};
+ $count = 0;
+ while ( $count < 100 ) {
+ if ( $depend_path =~ s/(\$[\{\(]?\w+[\}\)]?)/035/ ) {
+ $_ = $1;
+ s/[\$\{\}\(\)]//g;
+ $depend_path =~ s/035/$ENV{$_}/g;
+ } else {
+ $count = 100;
+ }
+ }
+ @dep_path = &split_path($depend_path);
+ }
+ @cur_dep_path = @dep_path;
+ if ( $file =~ /(.*[\/\\])/ ) {
+ $dep_curdir = $1;
+ splice( @cur_dep_path, 0, 0, $dep_curdir );
+ } else {
+ $dep_curdir = "";
+ }
+ $dep_file = $file;
+ &canonical_dep($file);
+ %dep_dict = ();
+ $i = &build_dep($file);
+ chop $i;
+ $i =~ s=/=$dir_sep=g unless $is_unix;
+ $i =~ s=([a-zA-Z]):/=//$1/=g if $gnuwin32;
+ return join(" ${linebreak}\n\t\t",split(/ /,$i) );
+}
+
+#
+# build_dep() - Internal for make_depend()
+#
+
+sub build_dep {
+ my($file) = @_;
+ my(@i,$a,$n);
+ $a = "";
+ return $a if !(defined $depend_dict{$file});
+ @i = split(/ /,$depend_dict{$file});
+ for $n ( @i ) {
+ if ( !defined($dep_dict{$n}) && defined($full_path{$n}) ) {
+ $dep_dict{$n} = 1;
+ $a .= $full_path{$n} . " " . &build_dep($n);
+ }
+ }
+ return $a;
+}
+
+#
+# canonical_dep(file) - Internal for make_depend()
+#
+# Reads the file and all included files recursively.
+# %depend_dict associates a file name to a list of included files.
+#
+
+sub canonical_dep {
+ my($file) = @_;
+ my(@inc,$i);
+ @inc = &scan_dep($file);
+ if ( @inc ) {
+ $depend_dict{$file} = join(" ",@inc);
+ for $i ( @inc ) {
+ &canonical_dep($i) if !defined($depend_dict{$i});
+ }
+ }
+}
+
+#
+# scan_dep(file) - Internal for make_depend()
+#
+# Returns an array of included files.
+#
+
+sub scan_dep {
+ my($file) = @_;
+ my($dir,$path,$found,@allincs,@includes,%incs);
+ $path = ($file eq $dep_file) ? $file : $dep_curdir . $file;
+ @includes = ();
+ return @includes if $file =~ /\.$moc_ext$/; # avoid .moc files
+ if ( ! (-f fix_path($path)) ) {
+ $found = 0;
+ for $dir ( @cur_dep_path ) {
+ $path = $dir . $file;
+ last if ( $found = (-f fix_path($path)) );
+ }
+ return @includes if ! $found;
+ }
+ undef $/;
+ if ( open(TMP,fix_path($path)) ) {
+ $full_path{$file} = $path;
+ $_ = <TMP>;
+ s-/\*.*?\*/--gs; # strip C/C++ comments
+ s-//.*\n-\n-g;
+ @allincs = split(/\n/,$_);
+ @allincs = grep(/^\s*#\s*include/,@allincs);
+ foreach ( @allincs ) { # all #include lines
+ next if !(/^\s*#\s*include\s+[<"]([^>"]*)[>"]/) || defined($incs{$1});
+ push(@includes,$1);
+ $incs{$1} = "1";
+ }
+ close(TMP);
+ }
+ $/ = "\n";
+ return @includes;
+}
+
+
+#
+# split_path(path)
+#
+# Splits a path containing : (Unix) or ; (MSDOS, NT etc.) separators.
+# Returns an array.
+#
+
+sub split_path {
+ my($p) = @_;
+ $p =~ s=:=;=g if $is_unix;
+ $p =~ s=[/\\]+=/=g;
+ $p =~ s=([^/:]);=$1/;=g;
+ $p =~ s=([^:;/])$=$1/=;
+ $p =~ s=/=$dir_sep=g unless $is_unix;
+ return split(/;/,$p);
+}
+
+
+#
+# fix_path(path)
+#
+# Converts all '\' to '/' if this really seems to be a Unix box.
+#
+
+sub fix_path {
+ my($p) = @_;
+ if ( $really_unix ) {
+ $p =~ s-\\-/-g;
+ } else {
+ $p =~ s-/-\\-g;
+ }
+ return $p;
+}
+__END__
+:endofperl
diff --git a/tmake/doc/m-linux-gcc.html b/tmake/doc/m-linux-gcc.html
new file mode 100644
index 0000000..300ef35
--- /dev/null
+++ b/tmake/doc/m-linux-gcc.html
@@ -0,0 +1,85 @@
+<!doctype HTML public "-//W3C//DTD HTML 3.2//EN">
+<html><head><title>
+Generated Makefile for Linux / GNU g++
+</title></head><body bgcolor="#ffffff">
+<h2 align=center>Generated Makefile for Linux / GNU gcc</h2>
+
+<pre>
+#############################################################################
+# Makefile for building hello
+# Generated by tmake at 10:11, 1998/07/07
+# Project: hello
+# Template: app
+#############################################################################
+
+####### Compiler, tools and options
+
+CC = g++
+CFLAGS = -Wall -W -O2 -fno-strength-reduce
+INCPATH = -I$(QTDIR)/include
+LINK = g++
+LFLAGS =
+LIBS = -L$(QTDIR)/lib -lqt -L/usr/X11R6/lib -lX11
+MOC = moc
+
+####### Files
+
+HEADERS = hello.h
+SOURCES = hello.cpp \
+ main.cpp
+OBJECTS = hello.o \
+ main.o
+SRCMOC = moc_hello.cpp
+OBJMOC = moc_hello.o
+TARGET = hello
+
+####### Implicit rules
+
+.SUFFIXES: .cpp .cxx .cc .C .c
+
+.cpp.o:
+ $(CC) -c $(CFLAGS) $(INCPATH) -o $@ $<
+
+.cxx.o:
+ $(CC) -c $(CFLAGS) $(INCPATH) -o $@ $<
+
+.cc.o:
+ $(CC) -c $(CFLAGS) $(INCPATH) -o $@ $<
+
+.C.o:
+ $(CC) -c $(CFLAGS) $(INCPATH) -o $@ $<
+
+.c.o:
+ $(CC) -c $(CFLAGS) $(INCPATH) -o $@ $<
+
+####### Build rules
+
+all: $(TARGET)
+
+$(TARGET): $(OBJECTS) $(OBJMOC)
+ $(LINK) $(LFLAGS) -o $(TARGET) $(OBJECTS) $(OBJMOC) $(LIBS)
+
+moc: $(SRCMOC)
+
+tmake:
+ tmake hello.pro
+
+clean:
+ -rm -f $(OBJECTS) $(OBJMOC) $(SRCMOC) $(TARGET)
+ -rm -f *~ core
+
+####### Compile
+
+hello.o: hello.cpp \
+ hello.h
+
+main.o: main.cpp \
+ hello.h
+
+moc_hello.o: moc_hello.cpp \
+ hello.h
+
+moc_hello.cpp: hello.h
+ $(MOC) hello.h -o moc_hello.cpp
+</pre>
+</body></html>
diff --git a/tmake/doc/m-win32-msvc.html b/tmake/doc/m-win32-msvc.html
new file mode 100644
index 0000000..24097cc
--- /dev/null
+++ b/tmake/doc/m-win32-msvc.html
@@ -0,0 +1,89 @@
+<!doctype HTML public "-//W3C//DTD HTML 3.2//EN">
+<html><head><title>
+Generated Makefile for Win32 / Microsoft Visual C++
+</title></head><body bgcolor="#ffffff">
+<h2 align=center>Generated Makefile for Win32 / Microsoft Visual C++</h2>
+
+<pre>
+#############################################################################
+# Makefile for building hello
+# Generated by tmake at 20:40, 1998/02/27
+# Project: hello
+# Template: app
+#############################################################################
+
+####### Compiler, tools and options
+
+CC = cl
+CFLAGS = -nologo -W3 -O2
+INCPATH = -I"$(QTDIR)\include"
+LINK = link
+LFLAGS = /NOLOGO /SUBSYSTEM:windows
+LIBS = $(QTDIR)\lib\qt.lib user32.lib gdi32.lib comdlg32.lib wsock32.lib
+MOC = moc
+
+####### Files
+
+HEADERS = hello.h
+SOURCES = hello.cpp \
+ main.cpp
+OBJECTS = hello.obj \
+ main.obj
+SRCMOC = moc_hello.cpp
+OBJMOC = moc_hello.obj
+TARGET = hello.exe
+
+####### Implicit rules
+
+.SUFFIXES: .cpp .cxx .cc .c
+
+.cpp.obj:
+ $(CC) -c $(CFLAGS) $(INCPATH) -Fo$@ $<
+
+.cxx.obj:
+ $(CC) -c $(CFLAGS) $(INCPATH) -Fo$@ $<
+
+.cc.obj:
+ $(CC) -c $(CFLAGS) $(INCPATH) -Fo$@ $<
+
+.c.obj:
+ $(CC) -c $(CFLAGS) $(INCPATH) -Fo$@ $<
+
+####### Build rules
+
+all: $(TARGET)
+
+$(TARGET): $(OBJECTS) $(OBJMOC)
+ $(LINK) $(LFLAGS) /OUT:$(TARGET) @<<
+ $(OBJECTS) $(OBJMOC) $(LIBS)
+<<
+
+moc: $(SRCMOC)
+
+tmake: Makefile
+
+Makefile: hello.pro
+ tmake hello.pro -o Makefile
+
+clean:
+ -del hello.obj
+ -del main.obj
+ -del moc_hello.cpp
+ -del moc_hello.obj
+ -del $(TARGET)
+
+####### Compile
+
+hello.obj: hello.cpp \
+ hello.h
+
+main.obj: main.cpp \
+ hello.h
+
+moc_hello.obj: moc_hello.cpp \
+ hello.h
+
+moc_hello.cpp: hello.h
+ $(MOC) hello.h -o moc_hello.cpp
+</pre>
+</body></html>
diff --git a/tmake/doc/tmake.html b/tmake/doc/tmake.html
new file mode 100644
index 0000000..b19af51
--- /dev/null
+++ b/tmake/doc/tmake.html
@@ -0,0 +1,638 @@
+<!doctype HTML public "-//W3C//DTD HTML 3.2//EN">
+<html><head><title>
+tmake User's Guide
+</title></head><body bgcolor="#ffffff">
+<p><h1 align=center>tmake User's Guide</h1>
+
+
+<hr>
+<h2>License Statement</h2>
+
+Copyright (C) 1996-1998 by Troll Tech AS. All rights reserved.<p>
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted, provided
+that this copyright notice appears in all copies.
+No representations are made about the suitability of this software for any
+purpose. It is provided "as is" without express or implied warranty.
+
+
+<hr>
+<h2>Introduction</h2>
+
+tmake is an easy-to-use tool for creating and maintaining makefiles across
+many platforms and compilers. The idea is that you should spend your time
+writing code, not makefiles.
+
+<p>
+We wrote tmake because we spent too much time maintaining makefiles for
+Windows and Unix compilers. Being the developer of the multi-platform GUI
+toolkit <a href="http://www.troll.no/qt">Qt</a>, Troll Tech must provide
+Qt makefiles for more than 30 different OS/compiler combinations.
+
+<p>
+We looked at GNU autoconf, but it was Unix-specific and not flexible
+enough in our opinion. Our makefile system also had to deal with Qt
+<a href="http://www.troll.no/qt/metaobjects.html">meta object
+compiler</a> (moc) issues. The moc program extracts meta information from
+C++ files and generates a C++ file with data tables etc. It takes work to
+add makefile rules for the moc and wanted to automate this task.
+
+<p>
+The tmake project was started around mid 1996 and version 1.0 was released
+in September 1997. It soon became a success and is now widely used among
+Qt programmers.
+
+<p>
+tmake is written in Perl and requires perl version 5 or newer. You do not
+need to be familiar with Perl programming to use tmake, but you should
+learn Perl if you want to write your own makefile templates.
+
+<p>
+<b>Windows users:</b> The tmake distribution for Win32 includes tmake.exe
+(built by the perl2exe utility) and you do not need to download and
+install perl unless you want to modify the tmake source code or run other
+perl scripts. You can download perl for Win32 (Windows NT and 95) from <a
+href="http://www.activestate.com">www.activestate.com</a>
+
+<p>
+Feedback is highly appreciated. Contact the author hanord@troll.no if you
+have ideas, patches etc. for tmake.
+
+
+<hr>
+<h2>Installation</h2>
+
+<ol>
+<li>Make sure you have perl version 5 or later installed (optional
+for Windows users).
+<li>Unpack the tmake tar.gz or zip archive.
+<li>Set the TMAKEPATH environment variable to the directories
+containing the template files (see below).
+<li>Add the tmake/bin directory to your PATH.
+</ol>
+
+Here are some examples:<p>
+<strong>Unix Bourne shell:</strong><pre>
+ TMAKEPATH=/local/tmake/lib/linux-g++
+ PATH=$PATH:/local/tmake/bin
+ export TMAKEPATH PATH
+</pre>
+
+<strong>Unix C shell:</strong><pre>
+ setenv TMAKEPATH /local/tmake/lib/linux-g++
+ setenv PATH $PATH:/local/tmake/bin
+</pre>
+
+<strong>Windows NT and Windows 95:</strong><pre>
+ set TMAKEPATH=c:\tmake\lib\win32-msvc
+ set PATH=%PATH%;c:\tmake\bin
+</pre>
+
+<p>
+The template directory name has the form <em>platform</em>-<em>compiler</em>.
+Each template directory contains template files and a configuration file.
+
+<p>
+Supported platforms: AIX, Data General, FreeBSD, HPUX, SGI Irix, Linux,
+NetBSD, OpenBSD, OSF1/DEC, SCO, Solaris, SunOS, Ultrix, Unixware and
+Win32.
+
+<p>
+Have a look at the tmake/lib directory to see if your platform-compiler
+combination is supported. If it's not there, please tell us.
+
+<p>
+<b>Unix users:</b> tmake requires that perl is in /usr/bin. If your
+version of perl is elsewehere, either change the first line of tmake or
+make a small shell script which invokes tmake with the correct perl.
+
+
+<hr>
+<h2>Getting Started</h2>
+
+Let's assume you have a small Qt application consisting of one C++ header
+file and two source files.
+
+First you need to create a project file, e.g. hello.pro:<pre>
+ HEADERS = hello.h
+ SOURCES = hello.cpp main.cpp
+ TARGET = hello
+</pre>
+
+Then run tmake to create a Makefile:<pre>
+ tmake hello.pro -o Makefile
+</pre>
+And finally:<pre>
+ make
+</pre>
+This builds the hello program. Remember to set the <code>TMAKEPATH</code>
+environment variable before you run tmake.
+<p>
+See <a href="m-linux-gcc.html">Makefile for Linux/g++</a>.<br>
+See <a href="m-win32-msvc.html">Makefile for Win32/msvc</a>
+(Microsoft Visual C++).<br>
+
+
+<hr>
+<h2>Makefile Templates</h2>
+
+The tmake distribution includes three makefile templates and one
+configuration file for each platform/compiler combination. The
+<code>TMAKEPATH</code> environment variable tells tmake where to find
+these files:
+<p>
+<table border="0">
+ <tr>
+ <td>&nbsp;</td>
+ <td>app.t</td>
+ <td>&nbsp;</td>
+ <td>Creates a makefile for building applications.</td>
+ </tr>
+ <tr>
+ <td>&nbsp;</td>
+ <td>lib.t</td>
+ <td>&nbsp;</td>
+ <td>Creates a makefile for building libraries.</td>
+ </tr>
+ <tr>
+ <td>&nbsp;</td>
+ <td>subdirs.t</td>
+ <td>&nbsp;</td>
+ <td>Creates a makefile for building targets in subdirectories.</td>
+ </tr>
+ <tr>
+ <td>&nbsp;</td>
+ <td>tmake.conf</td>
+ <td>&nbsp;</td>
+ <td>This configuration file contains compiler options and lists
+ tools and libraries.
+ </tr>
+</table>
+
+
+<p>
+The hello.pro project file above does not have a <code>TEMPLATE</code> or
+a <code>CONFIG</code> tag. The default template is <tt>app</tt> (the .t
+extension is optional) and the default configuration is <tt>qt warn_on
+release</tt>.
+
+This project file produces exactly the same result as the hello.pro
+above:<pre>
+ TEMPLATE = app
+ CONFIG = qt warn_on release
+ HEADERS = hello.h
+ SOURCES = hello.cpp main.cpp
+ TARGET = hello
+</pre>
+
+
+
+<h4>Makefile Configuration</h4>
+
+<p>
+The <code>CONFIG</code> tag is recognized by both the app.t and lib.t
+templates and specifies what compiler options to use and which extra
+libraries to link in.
+
+These options control the compilation flags:
+<p>
+<table border="0">
+ <tr>
+ <td>&nbsp;</td>
+ <td>release</td>
+ <td>&nbsp;</td>
+ <td>Compile with optimization enabled, ignored if
+ "debug" is specified.</td>
+ </tr>
+ <tr>
+ <td>&nbsp;</td>
+ <td>debug</td>
+ <td>&nbsp;</td>
+ <td>Compile with debug options enabled.</td>
+ </tr>
+ <tr>
+ <td>&nbsp;</td>
+ <td>warn_on</td>
+ <td>&nbsp;</td>
+ <td>The compiler should emit more warnings than normally, ignored if
+ "warn_off" is specified.</td>
+ </tr>
+ <tr>
+ <td>&nbsp;</td>
+ <td>warn_off</td>
+ <td>&nbsp;</td>
+ <td>The compiler should emit no warnings or as few as possible.</td>
+ </tr>
+</table>
+
+<p>
+These options defines the application/library type:
+<p>
+<table border="0">
+ <tr>
+ <td>&nbsp;</td>
+ <td>qt</td>
+ <td>&nbsp;</td>
+ <td>The target is a Qt application/library and requires Qt header
+ files/library.</td>
+ </tr>
+ <tr>
+ <td>&nbsp;</td>
+ <td>opengl</td>
+ <td>&nbsp;</td>
+ <td>The target requires the OpenGL (or Mesa) headers/libraries.</td>
+ </tr>
+ <tr>
+ <td>&nbsp;</td>
+ <td>x11</td>
+ <td>&nbsp;</td>
+ <td>The target is a X11 application (app.t only).</td>
+ </tr>
+ <tr>
+ <td>&nbsp;</td>
+ <td>windows</td>
+ <td>&nbsp;</td>
+ <td>The target is a Win32 window application (app.t only).</td>
+ </tr>
+ <tr>
+ <td>&nbsp;</td>
+ <td>console</td>
+ <td>&nbsp;</td>
+ <td>The target is a Win32 console application (app.t only).</td>
+ </tr>
+ <tr>
+ <td>&nbsp;</td>
+ <td>dll</td>
+ <td>&nbsp;</td>
+ <td>The target is a shared object/DLL (app.t only).</td>
+ </tr>
+ <tr>
+ <td>&nbsp;</td>
+ <td>staticlib</td>
+ <td>&nbsp;</td>
+ <td>The target is a static library (lib.t only).</td>
+ </tr>
+</table>
+
+<p>
+As an example, if the hello application uses both Qt and OpenGL and you
+want to compile it for debugging, your <code>CONFIG</code> line should
+read:<pre>
+ CONFIG = qt opengl debug
+</pre>
+
+<p>
+The most common tmake options and project tags are described here.
+See the tmake <a href="tmake_ref.html">reference manual</a> for
+details.<p>
+
+
+
+<h4>The Application Template</h4>
+
+The application template, app.t, lets you compile and link executable
+programs or shared objects (DLLs).
+
+This template recognizes several tags.
+<p>
+<table border="0">
+ <tr>
+ <td>&nbsp;</td>
+ <td>HEADERS</td>
+ <td>&nbsp;</td>
+ <td>Header files.</td>
+ </tr>
+ <tr>
+ <td>&nbsp;</td>
+ <td>SOURCES</td>
+ <td>&nbsp;</td>
+ <td>Source files.</td>
+ </tr>
+ <tr>
+ <td>&nbsp;</td>
+ <td>TARGET</td>
+ <td>&nbsp;</td>
+ <td>Name of executable (adds .exe if on Windows).</td>
+ </tr>
+ <tr>
+ <td>&nbsp;</td>
+ <td>DESTDIR</td>
+ <td>&nbsp;</td>
+ <td>Where to put the target.</td>
+ </tr>
+ <tr>
+ <td>&nbsp;</td>
+ <td>DEFINES</td>
+ <td>&nbsp;</td>
+ <td>Tell compiler to define C preprocessor macros (-D option).</td>
+ </tr>
+ <tr>
+ <td>&nbsp;</td>
+ <td>INCLUDEPATH</td>
+ <td>&nbsp;</td>
+ <td>Sets the include file search path for the compiler (-I
+ option).
+ </td>
+ </tr>
+ <tr>
+ <td>&nbsp;</td>
+ <td>DEPENDPATH</td>
+ <td>&nbsp;</td>
+ <td>Sets the dependency search path for tmake.</td>
+ </tr>
+ <tr>
+ <td>&nbsp;</td>
+ <td>DEF_FILE</td>
+ <td>&nbsp;</td>
+ <td>Win32 only: Link with a .def file.</td>
+ </tr>
+ <tr>
+ <td>&nbsp;</td>
+ <td>RC_FILE</td>
+ <td>&nbsp;</td>
+ <td>Win32 only: Use a .rc file (compile to temporary .res).
+ </td>
+ </tr>
+ <tr>
+ <td>&nbsp;</td>
+ <td>RES_FILE</td>
+ <td>&nbsp;</td>
+ <td>Win32 only: Link with a .res file.
+ </td>
+ </tr>
+</table>
+
+<p>
+
+
+<h4>The Library Template</h4>
+
+The library template, lib.t, lets you compile and create static or shared
+libraries.
+
+<p>
+The lib.t template supports the same project tags as app.t, but also
+<code>VERSION</code>. <code>VERSION</code> is the version number of the
+target library, e.g. 1.40. The version is important for Unix shared
+libraries, but ignored on Windows.
+
+
+
+<h4>The Subdirs Template</h4>
+
+The subdirs template, subdirs.t, lets you invoke make in subdirectories.
+
+<p>The <code>SUBDIRS</code> tag contains the name of all subdirectories to
+be processed.
+
+
+<h4>Special Templates for Microsoft Visual C++</h4>
+
+If you have Microsoft Visual C++ 5.0, you can use two special templates to
+generate a MSVC++ IDE project (.dsp file). After you have generated
+e.g. hello.dsp, choose "File"->"Open Workspace" and select the hello.dsp
+file. Visual C++ will then create a workspace (.dsw file) for you.<p>
+<table border="0">
+ <tr>
+ <td>&nbsp;</td>
+ <td>vcapp.t</td>
+ <td>&nbsp;</td>
+ <td>Creates an application project file (Microsoft Visual C++ 5.0
+ only).</td>
+ </tr>
+ <tr>
+ <td>&nbsp;</td>
+ <td>vclib.t</td>
+ <td>&nbsp;</td>
+ <td>Creates a library project file (Microsoft Visual C++ 5.0
+ only).</td>
+ </tr>
+</table>
+
+<p>
+Run tmake to create a hello.dsp file (use -t to override the default
+template):<pre>
+ tmake -t vcapp -o hello.dsp hello.pro
+</pre>
+
+
+<hr>
+<h2><a name="usage"></a>Program Usage: tmake</h2>
+
+Usage:<pre>
+ tmake [options] <em>project-file</em>
+</pre>
+Options:<pre>
+ -e expr Evaluate the Perl expression. Ignores the template file.
+ -nodepend Don't generate dependency information.
+ -o <em>file</em> Write output to <em>file</em> instead of stdout.
+ -p <em>file</em> Load an additional project file.
+ -t <em>file</em> Specify a template <em>file</em>.
+ -unix Force tmake into Unix mode.
+ -v Verbose/debugging on.
+ -win32 Force tmake into Win32 mode.
+</pre>
+
+The -t option overrides any <code>TEMPLATE</code> tag in the project file.
+<p>
+The default project file extension is ".pro". The default template file
+extension is ".t". If you do not specify these extension tmake will
+automatically add them for you.
+<p>
+
+
+<hr>
+<h2><a name="progen"></a>The progen Utility</h2>
+
+The progen utility creates project files for you. It can be used like
+this:<pre>
+ progen -n hello -o hello.pro
+</pre>
+If no .cpp or .h files are specified on the command line, progen
+searches for .cpp and .h (except moc_*.cpp) in the current directory
+and below.
+<p>
+Usage:<pre>
+ progen [options] [<em>C/C++ header files and source files</em>]
+</pre>
+Options:<pre>
+ -lower Lower-case letters in filenames (useful on Windows).
+ -n <em>name</em> Specify a project name (<code>TARGET</code>).
+ -o <em>file</em> Write output to <em>file</em> instead of stdout.
+ -t <em>file</em> Specify a template <em>file</em>.
+</pre>
+
+
+<hr>
+<h2>Advanced Topics</h2>
+
+In most cases you will be happy with using tmake as described above, but
+sometimes you need to add special compiler options or even add new
+makefile rules. This chapter describes how to customize your makefiles.
+
+<h4>Conditional Project Settings</h4>
+
+If you need a special compiler option etc., you can add platform-dependent
+settings in your project file:<pre>
+ solaris-cc:TMAKE_CC = /opt/bin/CC_5.0
+ solaris-cc:TMAKE_CFLAGS = -pts
+ unix:TMAKE_LIBS = -lXext
+ win32:INCLUDE_PATH = c:\myinclude
+ win32-borland:DEFINES = NO_BOOL
+</pre>
+
+You can prefix a project tag with unix: or win32: to make it specific for
+either Unix or Windows. You can also prefix tags with
+<em>platform-compiler</em>
+
+<h4>Your Own Templates</h4>
+
+If you know Perl programming, there is virtually no limitation to what you
+can do with tmake. First you need to know how tmake works.
+
+<h4>Template Processing</h4>
+
+When you run tmake, it first reads the <tt>tmake.conf</tt> file.
+This configuration file has the same syntax as the project file.
+
+tmake then reads the project file and sets the project tags it
+finds, e.g. <code>HEADERS</code>, <code>SOURCES</code> etc.
+
+All tags and values are stored in a global associative Perl hash
+array called <code>project</code>. For example,
+<code>$project{"SOURCES"}</code> contains "hello.cpp main.cpp"
+after processing hello.pro.
+
+When both the <tt>tmake.conf</tt> and the project files have been
+read, tmake starts reading the template file line by line and
+executes any Perl code it finds in the template.
+
+<ul>
+<li>Anything after <code>#$</code> until newline is
+ evaluated as perl code. The perl code is substituted
+ with the contents of the <code>$text</code>
+ variable.
+<li>Block of perl code: <code>#${</code> until
+ <code>#$}</code>.
+<li>Comments; <code>#!</code> until newline is stripped.
+<li>Anything else is copied directly from the template to
+ the output.
+</ul>
+
+<p>
+Example:<pre>
+ #! This is a comment which will be removed.
+ This text will appear in the output.
+ #$ $text = "The header file(s) are: " . $project{"HEADERS"};
+ # This text also appears in the output.
+ #${
+ $a = 12;
+ $b = 13;
+ $text = $a * $b;
+ #$}
+ That's all.
+</pre>
+Output:<pre>
+ This text will appear in the output.
+ The header file(s) are: hello.h
+ # This text also appears in the output.
+ 156
+ That's all.
+</pre>
+
+
+<h3>Using tmake With Lex and Yacc</h3>
+
+The standard tmake templates knows how to process C and C++ files, but
+sometimes you need to process additional files and link them into your
+project. A typical example is to process lex and yacc files when you're
+building a parser.
+
+<p>
+Parser template:<pre>
+ #!
+ #! parser.t: This is a custom template for building a parser
+ #!
+ #$ IncludeTemplate("app.t");
+
+ ####### Lex/yacc programs and options
+
+ LEX = flex
+ YACC = #$ $text = ($is_unix ? "yacc -d" : "byacc -d");
+
+ ####### Lex/yacc files
+
+ LEXIN = #$ Expand("LEXINPUT");
+ LEXOUT = lex.yy.c
+ YACCIN = #$ Expand("YACCINPUT");
+ YACCOUT = y.tab.c
+ YACCHDR = y.tab.h
+ PARSER = #$ Expand("PARSER");
+
+ ####### Process lex/yacc files
+
+ $(LEXOUT): $(LEXIN)
+ $(LEX) $(LEXIN)
+
+ $(PARSER): $(YACCIN) $(LEXOUT)
+ $(YACC) $(YACCIN)
+ #$ $text = ($is_unix ? "-rm -f " : "-del ") . '$(PARSER)';
+ #$ $text = ($is_unix ? "-mv " : "-ren ") . '$(YACCOUT) $(PARSER)';
+</pre>
+
+The parser template adds some extra rules to the application template
+in order to build the lex and yacc portions of the project. This
+template is portable across Unix and Windows since it generates different
+commands depending on the <code>$is_unix</code> variable.
+
+<p>
+To learn more about the Expand() function and other Perl functions which
+tmake provides, consult the <a href="tmake_ref.html">reference manual</a>.
+
+<p>
+Example project file:<pre>
+ TEMPLATE = parser.t
+ CONFIG = console release
+ LEXINPUT = lexer.l
+ YACCINPUT = grammar.y
+ PARSER = parser.cpp
+ SOURCES = $$PARSER \
+ node.cpp \
+ asmgen.cpp
+ TARGET = parser
+</pre>
+
+Here we use macro expansion <code>$$PARSER</code> to avoid writing parser.cpp
+two places.
+
+
+<h3>Counting the Number of Code Lines</h3>
+
+tmake is generic since it is based on Perl. You can create your own
+templates for other purposes than producing makefiles. Here is an example
+template that counts the number of code lines in our project.
+
+<p>
+Template wc.t:<pre>
+ #! Template that count number of C++ lines.
+ The number of C++ code lines for #$ $text=$project_name;
+ #${
+ $files = $project{"HEADERS"} . " " . $project{"SOURCES"};
+ $text = `wc -l $files`;
+ #$}
+</pre>
+Run it:<pre>
+ tmake -t wc hello
+</pre>
+Output:<pre>
+ The number of C++ code lines for hello.pro
+ 25 hello.h
+ 98 hello.cpp
+ 38 main.cpp
+ 161 total
+</pre>
+This will only work if the wc program is installed on your system.
+
+
+</body></html>
diff --git a/tmake/doc/tmake_ref.html b/tmake/doc/tmake_ref.html
new file mode 100644
index 0000000..0b89b28
--- /dev/null
+++ b/tmake/doc/tmake_ref.html
@@ -0,0 +1,508 @@
+<!doctype HTML public "-//W3C//DTD HTML 3.2//EN">
+<html><head><title>
+tmake Reference Manual
+</title></head><body bgcolor="#ffffff">
+<p><h1 align=center>tmake Reference Manual</h1>
+
+<hr>
+<h2>Project Settings</h2>
+
+tmake recognizes several project tags. The syntax for setting a
+project variable is:<pre>
+ TAG = value
+</pre>
+You can also do tag expansion using $$:<pre>
+ ALLFILES = Project files: $$HEADERS $$SOURCES
+</pre>
+Normally you assign to a tag, but you can also add to a tag, subtract
+from a tag or replace parts of the tag.<pre>
+ A = abc
+ X = xyz
+ A += def # A = abc def
+ X *= xyz # X = xyz
+ B = $$A # B = abc def
+ B -= abc # B = def
+ X /= s/y/Y/ # X = xYz
+</pre>
+The *= operation adds the value if the tag does not already contain it.
+The /= operation performs regular expression substitution.
+
+<p>
+You can also set tags from the command line when running the tmake program.
+For instance, if you want to generate a makefile with debug information:<pre>
+ tmake hello.pro "CONFIG+=debug"
+</pre>
+
+<p>
+Use the <tt>unix:</tt> or <tt>win32:</tt> qualifier if you want a
+platform-specific tag:<pre>
+ SOURCES = common.cpp # common for all platforms
+ unix:SOURCES += unix.cpp # additional sources for Unix
+ win32:SOURCES += win32.cpp # additional sources for Windows
+ unix:LIBS += -lm # on Unix we need the math lib
+</pre>
+If none of the platforms match, tmake looks for the tag in <a
+href="#CONFIG">CONFIG</a> setting:<pre>
+ debug:SOURCES += dbgstuff.cpp # additional source for debugging
+</pre>
+
+Finally, you can set platform and compiler-dependent tags:<pre>
+ linux-g++:TMAKE_CFLAGS = -fno-rtti
+</pre>
+
+<p>
+You may define your own project tags to be used by custom templates. A
+project tag is stored in <code>%project</code>, which is an associative
+Perl array. Access it like this: <code>$project{"tag"}</code> or via the
+function <code>Project('tag')</code>. For example, after reading
+"hello.pro", <code>$project{"SOURCES"}</code> contains "hello.cpp
+main.cpp". One limitation of tmake is that it cannot handle file names
+with white space.<p>
+
+
+<hr>
+<h2>Project Tag Reference</h2>
+
+<h4><a name="ALL_DEPS"></a>ALL_DEPS</h4>
+Specifies additional dependencies for the makefile target "all:".<p>
+
+
+<h4><a name="CLEAN_FILES"></a>CLEAN_FILES</h4>
+Specifies additional files to be removed for "make clean".<p>
+Example:<pre>
+ CLEAN_FILES = core *~
+</pre>
+
+
+<h4><a name="CONFIG"></a>CONFIG</h4>
+Sets the make configuration. It tells the tmake templates what compiler
+options to use and which extra libraries to link in.<p>
+These options control the compilation flags:
+<p>
+<table border="0">
+ <tr>
+ <td>&nbsp;</td>
+ <td>release</td>
+ <td>&nbsp;</td>
+ <td>Compile with optimization enabled, ignored if
+ "debug" is specified.</td>
+ </tr>
+ <tr>
+ <td>&nbsp;</td>
+ <td>debug</td>
+ <td>&nbsp;</td>
+ <td>Compile with debug options enabled.</td>
+ </tr>
+ <tr>
+ <td>&nbsp;</td>
+ <td>warn_on</td>
+ <td>&nbsp;</td>
+ <td>The compiler should emit more warnings than normally, ignored if
+ "warn_off" is specified.</td>
+ </tr>
+ <tr>
+ <td>&nbsp;</td>
+ <td>warn_off</td>
+ <td>&nbsp;</td>
+ <td>The compiler should emit no warnings or as few as possible.</td>
+ </tr>
+</table>
+
+<p>
+These options defines the application/library type:
+<p>
+<table border="0">
+ <tr>
+ <td>&nbsp;</td>
+ <td>qt</td>
+ <td>&nbsp;</td>
+ <td>The target is a Qt application/library and requires Qt header
+ files/library.</td>
+ </tr>
+ <tr>
+ <td>&nbsp;</td>
+ <td>opengl</td>
+ <td>&nbsp;</td>
+ <td>The target requires the OpenGL (or Mesa) headers/libraries.</td>
+ </tr>
+ <tr>
+ <td>&nbsp;</td>
+ <td>x11</td>
+ <td>&nbsp;</td>
+ <td>The target is a X11 application (app.t only).</td>
+ </tr>
+ <tr>
+ <td>&nbsp;</td>
+ <td>windows</td>
+ <td>&nbsp;</td>
+ <td>The target is a Win32 window application (app.t only).</td>
+ </tr>
+ <tr>
+ <td>&nbsp;</td>
+ <td>console</td>
+ <td>&nbsp;</td>
+ <td>The target is a Win32 console application (app.t only).</td>
+ </tr>
+ <tr>
+ <td>&nbsp;</td>
+ <td>dll</td>
+ <td>&nbsp;</td>
+ <td>The target is a shared object/DLL (app.t only).</td>
+ </tr>
+ <tr>
+ <td>&nbsp;</td>
+ <td>staticlib</td>
+ <td>&nbsp;</td>
+ <td>The target is a static library (lib.t only).</td>
+ </tr>
+</table>
+
+
+<h4><a name="DEF_FILE"></a>DEF_FILE</h4>
+Win32/app.t only: Specifies a .def file.
+
+
+<h4><a name="DESTDIR"></a>DESTDIR</h4>
+Specifies where to put the target file.
+Example:<pre>
+ DESTDIR = ../../lib
+</pre>
+You must create this directory before running make.
+
+
+<h4><a name="HEADERS"></a>HEADERS</h4>
+Defines the header files of the project.
+
+
+<h4><a name="INCPATH"></a>INCPATH</h4>
+This tag is generated from <code>INCLUDEPATH</code>. The ';' or ':'
+separators have been replaced by ' ' (single space). This makes it
+easier to split. qtapp.t and other templates expand
+<code>INCPATH</code> to set -I options for the C++ compiler.
+
+
+<h4><a name="INCLUDEPATH"></a>INCLUDEPATH</h4>
+This tag specifies the #include directories. It can be set in the
+project file, or by the <a href="#AddIncludePath">AddIncludePath()</a>
+function.<p>
+Example:<pre>
+ INCLUDEPATH = c:\msdev\include d:\stl\include
+</pre>
+Use ';' or space as the directory separator.
+
+
+<h4><a name="LIBS"></a>LIBS</h4>
+Defines additional libraries to be linked in when creating an application
+or a shared library. You probably want to use a platform qualifier since
+libraries are specified differently on Unix and Win32.<p>
+Example:<pre>
+ unix:LIBS = -lXext -lm
+ win32:LIBS = ole32.lib
+</pre>
+
+
+<h4><a name="MOC_DIR"></a>MOC_DIR</h4>
+Specifies where to put the temporary moc output files. By default they
+are stored in the directory where the moc input files are.
+<p>
+Example:<pre>
+ MOC_DIR = tmp
+</pre>
+You must create this directory before running make.
+<p>
+See also: <a href="#OBJECTS_DIR">OBJECTS_DIR</a>.
+
+
+<h4><a name="OBJECTS"></a>OBJECTS</h4>
+This tag is generated from <code>SOURCES</code> by the StdInit() function.
+The extension of each source file has been replaced by .o (Unix) or .obj
+(Win32).<p>
+Example:<pre>
+ SOURCES = a.x b.y
+</pre>
+Then <code>OBJECTS</code> become "a.o b.o" on Unix and "a.obj b.obj" on
+Win32.
+
+
+<h4><a name="OBJECTS_DIR"></a>OBJECTS_DIR</h4>
+Specifies where to put object files. By default they are stored in
+the directory where the source files are.<p>
+Example:<pre>
+ OBJECTS_DIR = tmp
+</pre>
+You must create this directory before running make.
+<p>
+See also: <a href="#MOC_DIR">MOC_DIR</a>.
+
+
+<h4><a name="OBJMOC"></a>OBJMOC</h4>
+This tag is generated by the <a href="#StdInit">StdInit()</a> function if
+<code>$moc_aware</code> is true. <code>OBJMOC</code> contains the name of
+all intermediate moc object files.<p>
+Example:<pre>
+ HEADERS = demo.h
+ SOURCES = demo.cpp main.cpp
+</pre>
+If <tt>demo.h</tt> and <tt>main.cpp</tt> define classes that use signals
+and slots (i.e. the <code>Q_OBJECT</code> "keyword" is found in these two
+files), <code>OBJMOC</code> becomes:<pre>
+ OBJMOC = moc_demo.obj
+</pre>
+See also: <a href="#SRCMOC">SRCMOC</a>.
+
+
+<h4><a name="PROJECT"></a>PROJECT</h4>
+This is the name of the project. It defaults to the name of the project
+file, excluding the .pro extension.
+
+
+<h4><a name="RC_FILE"></a>RC_FILE</h4>
+Win32/app.t only: Specifies a .rc file. Cannot be used with the RES_FILE
+tag.
+
+
+<h4><a name="RES_FILE"></a>RES_FILE</h4>
+Win32/app.t only: Specifies a .res file. You can either specify a
+.rc file or one or more .res files.
+
+
+<h4><a name="SOURCES"></a>SOURCES</h4>
+Defines the source files of the project.
+
+
+<h4><a name="SRCMOC"></a>SRCMOC</h4>
+This tag is generated by the <a href="#StdInit">StdInit()</a> function if
+<code>CONFIG</code> contains "qt". <code>SRCMOC</code> contains the name of
+all intermediate moc files.<p>
+Example:<pre>
+ HEADERS = demo.h
+ SOURCES = demo.cpp main.cpp
+</pre>
+If <tt>demo.h</tt> and <tt>main.cpp</tt> define classes that use signals
+and slots (i.e. the <code>Q_OBJECT</code> "keyword" is found in these two
+files), <code>SRCMOC</code> becomes:<pre>
+ SRCMOC = moc_demo.cpp main.moc
+</pre>
+See also: <a href="#OBJMOC">OBJMOC</a>.
+
+
+<h4><a name="TARGET"></a>TARGET</h4>
+Sets the makefile target, i.e. what program to build.
+
+
+<h4><a name="TEMPLATE"></a>TEMPLATE</h4>
+Sets the default template. This can be overridden by the tmake -t
+<a href="tmake.html#usage">option</a>.
+
+
+<h4><a name="TMAKE_CC"></a>TMAKE_CC</h4>
+Contains the name of the compiler.
+
+
+<h4><a name="TMAKE_CFLAGS"></a>TMAKE_CFLAGS</h4>
+Contains the default compiler flags.
+
+
+<h4><a name="TMAKE_FILETAGS"></a>TMAKE_FILETAGS</h4>
+Tells tmake which tags contain file names. This is because tmake
+on Windows replace the directory separator / with \.
+
+
+<hr>
+<h2>Function Reference</h2>
+This section contains a brief description of some important
+tmake functions used by the templates.
+
+
+<h3><a name="AddIncludePath"></a>AddIncludePath(path)</h3>
+Adds <em>path</em> to the include path variable,
+<a href="#INCLUDEPATH">INCLUDEPATH</a>. The include path is used
+for two purposes:<ol>
+<li>Searching files when generating include dependencies.
+<li>Setting -I options for the C/C++ compiler.
+</ol>
+<p>
+Example:<pre>
+ #$ AddIncludePath('$QTDIR/include;/local/include');
+</pre>
+
+
+<h3>BuildMocObj(objects,sources)</h3>
+Creates build rules for moc source files. Generates
+include dependencies.<p>
+Example:<pre>
+ #$ BuildMocObj($project{"OBJMOC"},$project{"SRCMOC"});
+</pre>Output:<pre>
+ moc_hello.o: moc_hello.cpp \
+ hello.h \
+ ...
+</pre>
+
+<h3>BuildMocSrc(files)</h3>
+Creates moc source files from C++ files containing classes that
+define signals and slots. For a header file <tt>x.h</tt>, the
+generated moc file is called <tt>moc_x.h</tt>. For a source file
+<tt>y.cpp</tt>, the generates moc file is called <tt>y.moc</tt> and
+should be #include'd by <tt>y.cpp</tt>.<p>
+Example:<pre>
+ #$ BuildMocSrc($project{"HEADERS"});
+ #$ BuildMocSrc($project{"SOURCES"});
+</pre>Output:<pre>
+ moc_hello.cpp: hello.h
+ $(MOC) hello.h -o moc_hello.cpp
+</pre>
+
+
+<h3>BuildObj(objects,sources)</h3>
+Creates build rules for source files. Generates
+include dependencies.<p>
+Example:<pre>
+ #$ BuildObj($project{"OBJECTS"},$project{"SOURCES"});
+</pre>Output:<pre>
+ hello.o: hello.cpp \
+ hello.h \
+ ...
+
+ main.o: main.cpp \
+ hello.h \
+ ...
+</pre>
+
+
+<h3>Config(string)</h3>
+Returns true if the <code>CONFIG</code> tag contains the given string.
+<p>Example:<pre>
+ #$ if ( Config("release") { }
+</pre>
+
+
+<h3>DisableOutput()</h3>
+Call this function to force tmake to generate no output until
+EnableOutput() is called.
+<p>Example:<pre>
+ #$ Config("debug") && DisableOutput();
+ Anything here is skipped if CONFIG contains "debug".
+ #$ Config("debug") && EnableOutput();
+</pre>
+
+
+<h3>EnableOutput()</h3>
+Enables tmake output after DisableOutput() was called.
+
+
+<h3>Expand(tag)</h3>
+Expands a project tag. Equivalent to <code>$text = $project{$tag}</code>.
+<p>Example:<pre>
+ VERSION = #$ Expand("VERSION");
+</pre>Output:<pre>
+ VERSION = 1.1
+</pre>
+
+<h3>ExpandGlue(tag,prepend,glue,append)</h3>
+Expands a $project{} tag, splits on whitespace
+and joins with $glue. $prepend is put at the start
+of the string and $append is put at the end of the
+string. The resulting string ($text) becomes "" if
+the project tag is empty or not defined.<p>
+Example:<pre>
+ clear:
+ #$ ExpandGlue("OBJECTS","-del","\n\t-del ","");
+</pre>Output (Windows NT):<pre>
+ clear:
+ -del hello.obj
+ -del main.obj
+</pre>
+
+
+<h3>ExpandList(tag)</h3>
+This function is suitable for expanding lists of files.
+Equivalent with <code>ExpandGlue($tag,""," \\\n\t\t","")</code>.<p>
+Example:<pre>
+ OBJECTS = #$ ExpandList("OBJECTS");
+</pre>Output:<pre>
+ OBJECTS = hello.o \
+ main.o
+</pre>
+
+
+<h3>IncludeTemplate(file)</h3>
+Includes a template file. The ".t" extension is optional.<p>
+Example:<pre>
+ #$ IncludeTemplate("mytemplate");
+</pre>
+
+
+<h3>Now()</h3>
+Sets $text to the current date and time.<p>
+Example:<pre>
+ # Generated at #$ Now()
+</pre>Output:<pre>
+ # Generated at 12:58, 1996/11/19
+</pre>
+
+
+<h3>Project(strings)</h3>
+This is a powerful function for setting and reading project
+variables. Returns the resulting project variables (joined with space
+between).
+<p>Examples:<pre>
+# Get a project variable:
+ $s = Project("TEMPLATE"); -> $s = "TEMPLATE"
+
+# Set a project variable:
+ Project("TEMPLATE = lib"); -> TEMPLATE = lib
+ Project("CONFIG =";) -> CONFIG empty
+
+# Append to a project variable:
+ Project("CONFIG = qt"); -> CONFIG = qt
+ Project("CONFIG += debug"); -> CONFIG = qt debug
+
+# Append to a project variable if it does not contain the value already:
+ Project("CONFIG = qt release"); -> CONFIG = qt release
+ Project("CONFIG *= qt"); -> CONFIG = qt release
+ Project("CONFIG *= opengl"); -> CONFIG = qt release opengl
+
+# Subtract from a project variable:
+ Project("THINGS = abc xyz"); -> THINGS = abc xyz
+ Project("THINGS -= abc"); -> THINGS = xyz
+
+# Search/replace on a project variable:
+ Project("CONFIG = tq opengl"); -> CONFIG = tq opengl
+ Project("CONFIG /= s/tq/qt/"); -> CONFIG = qt opengl
+
+# The operations can be performed on several project variables at a time.
+
+ Project("TEMPLATE = app", "CONFIG *= opengl", "THINGS += klm");
+</pre>
+
+
+<h3><a name="ScanProject"></a>ScanProject(file)</h3>
+Scans a project file and stores the project tags and values in the
+global associative <code>%project</code> array.
+
+
+<h3><a name="StdInit"></a>StdInit()</h3>
+Standard initialization of tmake. StdInit() should be
+called from one of the first lines in the template.<p>
+
+This function creates some new project tags:<ul>
+<li><code><a href="#OBJECTS">OBJECTS</a></code>
+ - Object files corresponding to
+ <code><a href="#SOURCES">SOURCES</a></code>.
+<li><code><a href="#SRCMOC">SRCMOC</a></code> - moc source files.
+<li><code><a href="#OBJMOC">OBJMOC</a></code> - moc object files.
+</ul>
+
+The moc-related tags are created only if <code>CONFIG</code> contains "qt"
+
+
+<h3>Substitute(string)</h3>
+This function takes a string and substitutes any occurrence of $$tag
+with the actual content of the tag. Returns the substituted string.
+Also sets $text.
+<p>
+Important: Use single quotes around the string, otherwise perl will expand
+any $tags it finds.
+<p>Example:<pre>
+ Substitute('Project name: $$PROJECT, uses template $$TEMPLATE');
+</pre>
diff --git a/tmake/example/hello.cpp b/tmake/example/hello.cpp
new file mode 100644
index 0000000..dc6ff77
--- /dev/null
+++ b/tmake/example/hello.cpp
@@ -0,0 +1,102 @@
+/****************************************************************************
+** $Id$
+**
+** Copyright (C) 1992-1998 Troll Tech AS. All rights reserved.
+**
+** This file is part of an example program for Qt. This example
+** program may be used, distributed and modified without limitation.
+**
+*****************************************************************************/
+
+#include "hello.h"
+#include <qpushbutton.h>
+#include <qtimer.h>
+#include <qpainter.h>
+#include <qpixmap.h>
+
+
+/*
+ Constructs a Hello widget. Starts a 40 ms animation timer.
+*/
+
+Hello::Hello( const char *text, QWidget *parent, const char *name )
+ : QWidget(parent,name), t(text), b(0)
+{
+ QTimer *timer = new QTimer(this);
+ connect( timer, SIGNAL(timeout()), SLOT(animate()) );
+ timer->start( 40 );
+
+ resize( 200, 100 );
+}
+
+
+/*
+ This private slot is called each time the timer fires.
+*/
+
+void Hello::animate()
+{
+ b = (b + 1) & 15;
+ repaint( FALSE );
+}
+
+
+/*
+ Handles mouse button release events for the Hello widget.
+
+ We emit the clicked() signal when the mouse is released inside
+ the widget.
+*/
+
+void Hello::mouseReleaseEvent( QMouseEvent *e )
+{
+ if ( rect().contains( e->pos() ) )
+ emit clicked();
+}
+
+
+/*
+ Handles paint events for the Hello widget.
+
+ Flicker-free update. The text is first drawn in the pixmap and the
+ pixmap is then blt'ed to the screen.
+*/
+
+void Hello::paintEvent( QPaintEvent * )
+{
+ static int sin_tbl[16] = {
+ 0, 38, 71, 92, 100, 92, 71, 38, 0, -38, -71, -92, -100, -92, -71, -38};
+
+ if ( t.isEmpty() )
+ return;
+
+ // 1: Compute some sizes, positions etc.
+ QFontMetrics fm = fontMetrics();
+ int w = fm.width(t) + 20;
+ int h = fm.height() * 2;
+ int pmx = width()/2 - w/2;
+ int pmy = height()/2 - h/2;
+
+ // 2: Create the pixmap and fill it with the widget's background
+ QPixmap pm( w, h );
+ pm.fill( this, pmx, pmy );
+
+ // 3: Paint the pixmap. Cool wave effect
+ QPainter p;
+ int x = 10;
+ int y = h/2 + fm.descent();
+ int i = 0;
+ p.begin( &pm );
+ p.setFont( font() );
+ while ( t[i] ) {
+ int i16 = (b+i) & 15;
+ p.setPen( QColor((15-i16)*16,255,255,QColor::Hsv) );
+ p.drawText( x, y-sin_tbl[i16]*h/800, &t[i], 1 );
+ x += fm.width( t[i] );
+ i++;
+ }
+ p.end();
+
+ // 4: Copy the pixmap to the Hello widget
+ bitBlt( this, pmx, pmy, &pm );
+}
diff --git a/tmake/example/hello.h b/tmake/example/hello.h
new file mode 100644
index 0000000..16e0871
--- /dev/null
+++ b/tmake/example/hello.h
@@ -0,0 +1,34 @@
+/****************************************************************************
+** $Id$
+**
+** Copyright (C) 1992-1998 Troll Tech AS. All rights reserved.
+**
+** This file is part of an example program for Qt. This example
+** program may be used, distributed and modified without limitation.
+**
+*****************************************************************************/
+
+#ifndef HELLO_H
+#define HELLO_H
+
+#include <qwidget.h>
+
+
+class Hello : public QWidget
+{
+ Q_OBJECT
+public:
+ Hello( const char *text, QWidget *parent=0, const char *name=0 );
+signals:
+ void clicked();
+protected:
+ void mouseReleaseEvent( QMouseEvent * );
+ void paintEvent( QPaintEvent * );
+private slots:
+ void animate();
+private:
+ QString t;
+ int b;
+};
+
+#endif
diff --git a/tmake/example/hello.pro b/tmake/example/hello.pro
new file mode 100644
index 0000000..a299923
--- /dev/null
+++ b/tmake/example/hello.pro
@@ -0,0 +1,3 @@
+HEADERS = hello.h
+SOURCES = hello.cpp main.cpp
+TARGET = hello
diff --git a/tmake/example/main.cpp b/tmake/example/main.cpp
new file mode 100644
index 0000000..4b55a58
--- /dev/null
+++ b/tmake/example/main.cpp
@@ -0,0 +1,38 @@
+//
+// File: main.cpp
+//
+// A small Qt example application written by Troll Tech.
+//
+// It displays a text in a window and quits when you click
+// the mouse in the window.
+//
+
+#include "hello.h"
+#include <qapp.h>
+
+
+/*
+ The program starts here. It parses the command line and build a message
+ string to be displayed by the Hello widget.
+*/
+
+int main( int argc, char **argv )
+{
+ QApplication a(argc,argv);
+ QString s;
+ for ( int i=1; i<argc; i++ ) {
+ s += argv[i];
+ if ( i<argc-1 )
+ s += " ";
+ }
+ if ( s.isEmpty() )
+ s = "Hello, World";
+ Hello h( s );
+ h.setCaption( "Qt says hello" );
+ QObject::connect( &h, SIGNAL(clicked()), &a, SLOT(quit()) );
+ h.setFont( QFont("times",32,QFont::Bold) ); // default font
+ h.setBackgroundColor( white ); // default bg color
+ a.setMainWidget( &h );
+ h.show();
+ return a.exec();
+}
diff --git a/tmake/example/wc.t b/tmake/example/wc.t
new file mode 100644
index 0000000..dc041b5
--- /dev/null
+++ b/tmake/example/wc.t
@@ -0,0 +1,6 @@
+#! Template that count number of C++ lines
+The number of C++ code lines for #$ $text=$project_name;
+#${
+ $files = $project{"HEADERS"} . " " . $project{"SOURCES"};
+ $text = `wc -l $files`;
+#$}
diff --git a/tmake/lib/aix-g++/app.t b/tmake/lib/aix-g++/app.t
new file mode 100755
index 0000000..867725e
--- /dev/null
+++ b/tmake/lib/aix-g++/app.t
@@ -0,0 +1,2 @@
+#! Use the common Unix template
+#$ IncludeTemplate("../unix/app.t");
diff --git a/tmake/lib/aix-g++/lib.t b/tmake/lib/aix-g++/lib.t
new file mode 100755
index 0000000..2523b2f
--- /dev/null
+++ b/tmake/lib/aix-g++/lib.t
@@ -0,0 +1,2 @@
+#! Use the common Unix template
+#$ IncludeTemplate("../unix/lib.t");
diff --git a/tmake/lib/aix-g++/subdirs.t b/tmake/lib/aix-g++/subdirs.t
new file mode 100755
index 0000000..5e888af
--- /dev/null
+++ b/tmake/lib/aix-g++/subdirs.t
@@ -0,0 +1,2 @@
+#! Use the common Unix template
+#$ IncludeTemplate("../unix/subdirs.t");
diff --git a/tmake/lib/aix-g++/tmake.conf b/tmake/lib/aix-g++/tmake.conf
new file mode 100755
index 0000000..f2fe571
--- /dev/null
+++ b/tmake/lib/aix-g++/tmake.conf
@@ -0,0 +1,57 @@
+#
+# $Id$
+#
+# tmake configuration for aix-g++
+#
+
+TEMPLATE = app
+CONFIG = qt warn_on release
+
+TMAKE_CC = gcc
+TMAKE_CFLAGS =
+TMAKE_CFLAGS_WARN_ON = -Wall -W
+TMAKE_CFLAGS_WARN_OFF =
+TMAKE_CFLAGS_RELEASE = -O2 -fno-strength-reduce
+TMAKE_CFLAGS_DEBUG = -g
+TMAKE_CFLAGS_SHLIB =
+TMAKE_CFLAGS_YACC = -Wno-unused -Wno-parentheses
+
+TMAKE_CXX = g++
+TMAKE_CXXFLAGS = $$TMAKE_CFLAGS
+TMAKE_CXXFLAGS_WARN_ON = $$TMAKE_CFLAGS_WARN_ON
+TMAKE_CXXFLAGS_WARN_OFF = $$TMAKE_CFLAGS_WARN_OFF
+TMAKE_CXXFLAGS_RELEASE = $$TMAKE_CFLAGS_RELEASE
+TMAKE_CXXFLAGS_DEBUG = $$TMAKE_CFLAGS_DEBUG
+TMAKE_CXXFLAGS_SHLIB = $$TMAKE_CFLAGS_SHLIB
+TMAKE_CXXFLAGS_YACC = $$TMAKE_CFLAGS_YACC
+
+TMAKE_INCDIR =
+TMAKE_LIBDIR =
+TMAKE_INCDIR_X11 = /usr/X11R6/include
+TMAKE_LIBDIR_X11 = /usr/X11R6/lib
+TMAKE_INCDIR_QT = $(QTDIR)/include
+TMAKE_LIBDIR_QT = $(QTDIR)/lib
+TMAKE_INCDIR_OPENGL = /usr/X11R6/include
+TMAKE_LIBDIR_OPENGL = /usr/X11R6/lib
+
+TMAKE_LINK = g++
+TMAKE_LINK_SHLIB =
+TMAKE_LFLAGS =
+TMAKE_LFLAGS_RELEASE =
+TMAKE_LFLAGS_DEBUG =
+TMAKE_LFLAGS_SHLIB =
+TMAKE_LFLAGS_SONAME =
+
+TMAKE_LIBS =
+TMAKE_LIBS_X11 = -lX11 -lXext
+TMAKE_LIBS_QT = -lqt
+TMAKE_LIBS_QT_OPENGL = -lqgl
+TMAKE_LIBS_OPENGL = -lMesaGL -lMesaGLU -lXmu -lXext -lm
+
+TMAKE_MOC = moc
+
+TMAKE_AR = ar cqs
+TMAKE_RANLIB =
+
+TMAKE_TAR = tar -cf
+TMAKE_GZIP = gzip -9f
diff --git a/tmake/lib/aix-xlc/app.t b/tmake/lib/aix-xlc/app.t
new file mode 100755
index 0000000..867725e
--- /dev/null
+++ b/tmake/lib/aix-xlc/app.t
@@ -0,0 +1,2 @@
+#! Use the common Unix template
+#$ IncludeTemplate("../unix/app.t");
diff --git a/tmake/lib/aix-xlc/lib.t b/tmake/lib/aix-xlc/lib.t
new file mode 100755
index 0000000..2523b2f
--- /dev/null
+++ b/tmake/lib/aix-xlc/lib.t
@@ -0,0 +1,2 @@
+#! Use the common Unix template
+#$ IncludeTemplate("../unix/lib.t");
diff --git a/tmake/lib/aix-xlc/subdirs.t b/tmake/lib/aix-xlc/subdirs.t
new file mode 100755
index 0000000..5e888af
--- /dev/null
+++ b/tmake/lib/aix-xlc/subdirs.t
@@ -0,0 +1,2 @@
+#! Use the common Unix template
+#$ IncludeTemplate("../unix/subdirs.t");
diff --git a/tmake/lib/aix-xlc/tmake.conf b/tmake/lib/aix-xlc/tmake.conf
new file mode 100755
index 0000000..401e390
--- /dev/null
+++ b/tmake/lib/aix-xlc/tmake.conf
@@ -0,0 +1,63 @@
+#
+# $Id$
+#
+# tmake configuration for aix-xlc
+#
+
+TEMPLATE = app
+CONFIG = qt warn_on release
+
+TMAKE_CC = xlC
+TMAKE_CFLAGS = -+ -qstrict -D_BSD
+TMAKE_CFLAGS_WARN_ON =
+TMAKE_CFLAGS_WARN_OFF =
+TMAKE_CFLAGS_RELEASE = -O3
+TMAKE_CFLAGS_DEBUG = -g
+TMAKE_CFLAGS_SHLIB =
+TMAKE_CFLAGS_YACC =
+
+TMAKE_CXX = xlC
+TMAKE_CXXFLAGS = $$TMAKE_CFLAGS
+TMAKE_CXXFLAGS_WARN_ON = $$TMAKE_CFLAGS_WARN_ON
+TMAKE_CXXFLAGS_WARN_OFF = $$TMAKE_CFLAGS_WARN_OFF
+TMAKE_CXXFLAGS_RELEASE = $$TMAKE_CFLAGS_RELEASE
+TMAKE_CXXFLAGS_DEBUG = $$TMAKE_CFLAGS_DEBUG
+TMAKE_CXXFLAGS_SHLIB = $$TMAKE_CFLAGS_SHLIB
+TMAKE_CXXFLAGS_YACC = $$TMAKE_CFLAGS_YACC
+
+TMAKE_INCDIR =
+TMAKE_LIBDIR =
+TMAKE_INCDIR_X11 =
+TMAKE_LIBDIR_X11 =
+TMAKE_INCDIR_QT = $(QTDIR)/include
+TMAKE_LIBDIR_QT = $(QTDIR)/lib
+TMAKE_INCDIR_OPENGL =
+TMAKE_LIBDIR_OPENGL =
+
+TMAKE_LINK = xlC
+TMAKE_LINK_SHLIB = ld
+TMAKE_LINK_SHLIB_CMD = /usr/lpp/xlC/bin/makeC++SharedLib -p 0 \
+ -o lib$(TARGET).so.$(VER_MAJ).$(VER_MIN) \
+ -lX11 -lXext $(OBJECTS) $(OBJMOC); \
+ ar q lib$(TARGET).a lib$(TARGET).so.$(VER_MAJ).$(VER_MIN); \
+ ranlib lib$(TARGET).a; \
+ mv lib$(TARGET).a $(DESTDIR)
+TMAKE_LFLAGS =
+TMAKE_LFLAGS_RELEASE =
+TMAKE_LFLAGS_DEBUG =
+TMAKE_LFLAGS_SHLIB =
+TMAKE_LFLAGS_SONAME =
+
+TMAKE_LIBS =
+TMAKE_LIBS_X11 = -lX11 -lXext
+TMAKE_LIBS_QT = -lqt
+TMAKE_LIBS_QT_OPENGL = -lqgl
+TMAKE_LIBS_OPENGL = -lGL -lGLU -lXmu
+
+TMAKE_MOC = moc
+
+TMAKE_AR = ar cq
+TMAKE_RANLIB = ranlib
+
+TMAKE_TAR = tar -cf
+TMAKE_GZIP = gzip -9f
diff --git a/tmake/lib/dgux-g++/app.t b/tmake/lib/dgux-g++/app.t
new file mode 100755
index 0000000..867725e
--- /dev/null
+++ b/tmake/lib/dgux-g++/app.t
@@ -0,0 +1,2 @@
+#! Use the common Unix template
+#$ IncludeTemplate("../unix/app.t");
diff --git a/tmake/lib/dgux-g++/lib.t b/tmake/lib/dgux-g++/lib.t
new file mode 100755
index 0000000..2523b2f
--- /dev/null
+++ b/tmake/lib/dgux-g++/lib.t
@@ -0,0 +1,2 @@
+#! Use the common Unix template
+#$ IncludeTemplate("../unix/lib.t");
diff --git a/tmake/lib/dgux-g++/subdirs.t b/tmake/lib/dgux-g++/subdirs.t
new file mode 100755
index 0000000..5e888af
--- /dev/null
+++ b/tmake/lib/dgux-g++/subdirs.t
@@ -0,0 +1,2 @@
+#! Use the common Unix template
+#$ IncludeTemplate("../unix/subdirs.t");
diff --git a/tmake/lib/dgux-g++/tmake.conf b/tmake/lib/dgux-g++/tmake.conf
new file mode 100755
index 0000000..54e4ac3
--- /dev/null
+++ b/tmake/lib/dgux-g++/tmake.conf
@@ -0,0 +1,58 @@
+#
+# $Id$
+#
+# tmake configuration for linux-g++
+#
+
+TEMPLATE = app
+CONFIG = qt warn_on release
+
+TMAKE_CC = gcc
+TMAKE_CFLAGS =
+TMAKE_CFLAGS_WARN_ON = -Wall -W
+TMAKE_CFLAGS_WARN_OFF =
+TMAKE_CFLAGS_RELEASE = -O2 -fno-strength-reduce
+TMAKE_CFLAGS_DEBUG = -g
+TMAKE_CFLAGS_SHLIB = -fPIC
+TMAKE_CFLAGS_YACC = -Wno-unused -Wno-parentheses
+
+TMAKE_CXX = g++
+TMAKE_CXXFLAGS = $$TMAKE_CFLAGS
+TMAKE_CXXFLAGS_WARN_ON = $$TMAKE_CFLAGS_WARN_ON
+TMAKE_CXXFLAGS_WARN_OFF = $$TMAKE_CFLAGS_WARN_OFF
+TMAKE_CXXFLAGS_RELEASE = $$TMAKE_CFLAGS_RELEASE
+TMAKE_CXXFLAGS_DEBUG = $$TMAKE_CFLAGS_DEBUG
+TMAKE_CXXFLAGS_SHLIB = $$TMAKE_CFLAGS_SHLIB
+TMAKE_CXXFLAGS_YACC = $$TMAKE_CFLAGS_YACC
+
+TMAKE_INCDIR =
+TMAKE_LIBDIR =
+TMAKE_INCDIR_X11 = /usr/X11R6/include
+TMAKE_LIBDIR_X11 = /usr/X11R6/lib
+TMAKE_INCDIR_QT = $(QTDIR)/include
+TMAKE_LIBDIR_QT = $(QTDIR)/lib
+TMAKE_INCDIR_OPENGL = /usr/X11R6/include
+TMAKE_LIBDIR_OPENGL = /usr/X11R6/lib
+
+TMAKE_LINK = g++
+TMAKE_LINK_SHLIB = g++
+TMAKE_LFLAGS =
+TMAKE_LFLAGS_RELEASE =
+TMAKE_LFLAGS_DEBUG =
+TMAKE_LFLAGS_SHLIB = -shared
+# "Frithjof.Brestrich" <brest@infp.fzk.de> suggests -h not -soname
+TMAKE_LFLAGS_SONAME = -Wl,-h,
+
+TMAKE_LIBS =
+TMAKE_LIBS_X11 = -lX11 -lXext
+TMAKE_LIBS_QT = -lqt
+TMAKE_LIBS_QT_OPENGL = -lqgl
+TMAKE_LIBS_OPENGL = -lMesaGL -lMesaGLU -lXmu -lXext -lm
+
+TMAKE_MOC = moc
+
+TMAKE_AR = ar cq
+TMAKE_RANLIB =
+
+TMAKE_TAR = tar -cf
+TMAKE_GZIP = gzip -9f
diff --git a/tmake/lib/freebsd-g++/app.t b/tmake/lib/freebsd-g++/app.t
new file mode 100755
index 0000000..867725e
--- /dev/null
+++ b/tmake/lib/freebsd-g++/app.t
@@ -0,0 +1,2 @@
+#! Use the common Unix template
+#$ IncludeTemplate("../unix/app.t");
diff --git a/tmake/lib/freebsd-g++/lib.t b/tmake/lib/freebsd-g++/lib.t
new file mode 100755
index 0000000..2523b2f
--- /dev/null
+++ b/tmake/lib/freebsd-g++/lib.t
@@ -0,0 +1,2 @@
+#! Use the common Unix template
+#$ IncludeTemplate("../unix/lib.t");
diff --git a/tmake/lib/freebsd-g++/subdirs.t b/tmake/lib/freebsd-g++/subdirs.t
new file mode 100755
index 0000000..5e888af
--- /dev/null
+++ b/tmake/lib/freebsd-g++/subdirs.t
@@ -0,0 +1,2 @@
+#! Use the common Unix template
+#$ IncludeTemplate("../unix/subdirs.t");
diff --git a/tmake/lib/freebsd-g++/tmake.conf b/tmake/lib/freebsd-g++/tmake.conf
new file mode 100755
index 0000000..d7dbb21
--- /dev/null
+++ b/tmake/lib/freebsd-g++/tmake.conf
@@ -0,0 +1,59 @@
+#
+# $Id$
+#
+# tmake configuration for freebsd-g++
+#
+
+TEMPLATE = app
+CONFIG = qt warn_on release
+
+TMAKE_CC = gcc
+TMAKE_CFLAGS = -pipe
+TMAKE_CFLAGS_WARN_ON = -Wall -W
+TMAKE_CFLAGS_WARN_OFF =
+TMAKE_CFLAGS_RELEASE = -O2 -fno-strength-reduce
+TMAKE_CFLAGS_DEBUG = -g
+TMAKE_CFLAGS_SHLIB = -fPIC
+TMAKE_CFLAGS_YACC = -Wno-unused -Wno-parentheses
+
+TMAKE_CXX = g++
+TMAKE_CXXFLAGS = $$TMAKE_CFLAGS
+TMAKE_CXXFLAGS_WARN_ON = $$TMAKE_CFLAGS_WARN_ON
+TMAKE_CXXFLAGS_WARN_OFF = $$TMAKE_CFLAGS_WARN_OFF
+TMAKE_CXXFLAGS_RELEASE = $$TMAKE_CFLAGS_RELEASE
+TMAKE_CXXFLAGS_DEBUG = $$TMAKE_CFLAGS_DEBUG
+TMAKE_CXXFLAGS_SHLIB = $$TMAKE_CFLAGS_SHLIB
+TMAKE_CXXFLAGS_YACC = $$TMAKE_CFLAGS_YACC
+
+TMAKE_INCDIR =
+TMAKE_LIBDIR =
+TMAKE_INCDIR_X11 = /usr/X11R6/include
+TMAKE_LIBDIR_X11 = /usr/X11R6/lib
+TMAKE_INCDIR_QT = $(QTDIR)/include
+TMAKE_LIBDIR_QT = $(QTDIR)/lib
+TMAKE_INCDIR_OPENGL = /usr/X11R6/include
+TMAKE_LIBDIR_OPENGL = /usr/X11R6/lib
+
+TMAKE_LINK = g++
+TMAKE_LINK_SHLIB = g++
+TMAKE_LFLAGS =
+TMAKE_LFLAGS_RELEASE =
+TMAKE_LFLAGS_DEBUG =
+TMAKE_LFLAGS_SHLIB = -shared
+
+# soname does not work on fbsd 2.x
+#TMAKE_LFLAGS_SONAME = -Wl,-soname
+
+TMAKE_LIBS =
+TMAKE_LIBS_X11 = -lX11 -lXext
+TMAKE_LIBS_QT = -lqt
+TMAKE_LIBS_QT_OPENGL = -lqgl
+TMAKE_LIBS_OPENGL = -lMesaGL -lMesaGLU -lXmu -lXext -lm
+
+TMAKE_MOC = moc
+
+TMAKE_AR = ar cqs
+TMAKE_RANLIB =
+
+TMAKE_TAR = tar -cf
+TMAKE_GZIP = gzip -9f
diff --git a/tmake/lib/gnu-g++/app.t b/tmake/lib/gnu-g++/app.t
new file mode 100755
index 0000000..867725e
--- /dev/null
+++ b/tmake/lib/gnu-g++/app.t
@@ -0,0 +1,2 @@
+#! Use the common Unix template
+#$ IncludeTemplate("../unix/app.t");
diff --git a/tmake/lib/gnu-g++/lib.t b/tmake/lib/gnu-g++/lib.t
new file mode 100755
index 0000000..2523b2f
--- /dev/null
+++ b/tmake/lib/gnu-g++/lib.t
@@ -0,0 +1,2 @@
+#! Use the common Unix template
+#$ IncludeTemplate("../unix/lib.t");
diff --git a/tmake/lib/gnu-g++/subdirs.t b/tmake/lib/gnu-g++/subdirs.t
new file mode 100755
index 0000000..5e888af
--- /dev/null
+++ b/tmake/lib/gnu-g++/subdirs.t
@@ -0,0 +1,2 @@
+#! Use the common Unix template
+#$ IncludeTemplate("../unix/subdirs.t");
diff --git a/tmake/lib/gnu-g++/tmake.conf b/tmake/lib/gnu-g++/tmake.conf
new file mode 100755
index 0000000..eed7c32
--- /dev/null
+++ b/tmake/lib/gnu-g++/tmake.conf
@@ -0,0 +1,57 @@
+#
+# $Id$
+#
+# tmake configuration for linux-g++
+#
+
+TEMPLATE = app
+CONFIG = qt warn_on release
+
+TMAKE_CC = gcc
+TMAKE_CFLAGS =
+TMAKE_CFLAGS_WARN_ON = -Wall -W
+TMAKE_CFLAGS_WARN_OFF =
+TMAKE_CFLAGS_RELEASE = -O2 -fno-strength-reduce
+TMAKE_CFLAGS_DEBUG = -g
+TMAKE_CFLAGS_SHLIB = -fPIC
+TMAKE_CFLAGS_YACC = -Wno-unused -Wno-parentheses
+
+TMAKE_CXX = g++
+TMAKE_CXXFLAGS = $$TMAKE_CFLAGS
+TMAKE_CXXFLAGS_WARN_ON = $$TMAKE_CFLAGS_WARN_ON
+TMAKE_CXXFLAGS_WARN_OFF = $$TMAKE_CFLAGS_WARN_OFF
+TMAKE_CXXFLAGS_RELEASE = $$TMAKE_CFLAGS_RELEASE
+TMAKE_CXXFLAGS_DEBUG = $$TMAKE_CFLAGS_DEBUG
+TMAKE_CXXFLAGS_SHLIB = $$TMAKE_CFLAGS_SHLIB
+TMAKE_CXXFLAGS_YACC = $$TMAKE_CFLAGS_YACC
+
+TMAKE_INCDIR =
+TMAKE_LIBDIR =
+TMAKE_INCDIR_X11 = /usr/X11R6/include
+TMAKE_LIBDIR_X11 = /usr/X11R6/lib
+TMAKE_INCDIR_QT = $(QTDIR)/include
+TMAKE_LIBDIR_QT = $(QTDIR)/lib
+TMAKE_INCDIR_OPENGL = /usr/X11R6/include
+TMAKE_LIBDIR_OPENGL = /usr/X11R6/lib
+
+TMAKE_LINK = g++
+TMAKE_LINK_SHLIB = g++
+TMAKE_LFLAGS = -Wl,-rpath=/lib:/usr/X11R6/lib:$(QTDIR)/lib
+TMAKE_LFLAGS_RELEASE =
+TMAKE_LFLAGS_DEBUG =
+TMAKE_LFLAGS_SHLIB = -shared
+TMAKE_LFLAGS_SONAME = -Wl,-soname,
+
+TMAKE_LIBS =
+TMAKE_LIBS_X11 = -lX11 -lXext
+TMAKE_LIBS_QT = -lqt
+TMAKE_LIBS_QT_OPENGL = -lqgl
+TMAKE_LIBS_OPENGL = -lMesaGL -lMesaGLU -lXmu -lXext -lm
+
+TMAKE_MOC = moc
+
+TMAKE_AR = ar cqs
+TMAKE_RANLIB =
+
+TMAKE_TAR = tar -cf
+TMAKE_GZIP = gzip -9f
diff --git a/tmake/lib/hpux-acc/app.t b/tmake/lib/hpux-acc/app.t
new file mode 100755
index 0000000..867725e
--- /dev/null
+++ b/tmake/lib/hpux-acc/app.t
@@ -0,0 +1,2 @@
+#! Use the common Unix template
+#$ IncludeTemplate("../unix/app.t");
diff --git a/tmake/lib/hpux-acc/lib.t b/tmake/lib/hpux-acc/lib.t
new file mode 100755
index 0000000..2523b2f
--- /dev/null
+++ b/tmake/lib/hpux-acc/lib.t
@@ -0,0 +1,2 @@
+#! Use the common Unix template
+#$ IncludeTemplate("../unix/lib.t");
diff --git a/tmake/lib/hpux-acc/subdirs.t b/tmake/lib/hpux-acc/subdirs.t
new file mode 100755
index 0000000..5e888af
--- /dev/null
+++ b/tmake/lib/hpux-acc/subdirs.t
@@ -0,0 +1,2 @@
+#! Use the common Unix template
+#$ IncludeTemplate("../unix/subdirs.t");
diff --git a/tmake/lib/hpux-acc/tmake.conf b/tmake/lib/hpux-acc/tmake.conf
new file mode 100755
index 0000000..381fa97
--- /dev/null
+++ b/tmake/lib/hpux-acc/tmake.conf
@@ -0,0 +1,59 @@
+#
+# $Id$
+#
+# tmake configuration for hpux-acc
+#
+
+TEMPLATE = app
+CONFIG = qt warn_on release
+
+TMAKE_CC = aCC
+TMAKE_CFLAGS = -w -D__STRICT_ANSI__
+TMAKE_CFLAGS_WARN_ON =
+TMAKE_CFLAGS_WARN_OFF =
+TMAKE_CFLAGS_RELEASE = -O
+TMAKE_CFLAGS_DEBUG = -g
+TMAKE_CFLAGS_SHLIB = +Z
+TMAKE_CFLAGS_YACC =
+
+TMAKE_CXX = aCC
+TMAKE_CXXFLAGS = $$TMAKE_CFLAGS
+TMAKE_CXXFLAGS_WARN_ON = $$TMAKE_CFLAGS_WARN_ON
+TMAKE_CXXFLAGS_WARN_OFF = $$TMAKE_CFLAGS_WARN_OFF
+TMAKE_CXXFLAGS_RELEASE = $$TMAKE_CFLAGS_RELEASE
+TMAKE_CXXFLAGS_DEBUG = $$TMAKE_CFLAGS_DEBUG
+TMAKE_CXXFLAGS_SHLIB = $$TMAKE_CFLAGS_SHLIB
+TMAKE_CXXFLAGS_YACC = $$TMAKE_CFLAGS_YACC
+
+TMAKE_INCDIR =
+TMAKE_LIBDIR =
+TMAKE_INCDIR_X11 =
+TMAKE_LIBDIR_X11 =
+TMAKE_INCDIR_QT = $(QTDIR)/include
+TMAKE_LIBDIR_QT = $(QTDIR)/lib
+TMAKE_INCDIR_OPENGL =
+TMAKE_LIBDIR_OPENGL =
+
+TMAKE_LINK = aCC
+TMAKE_LINK_SHLIB = aCC
+TMAKE_LFLAGS =
+TMAKE_LFLAGS_RELEASE =
+TMAKE_LFLAGS_DEBUG =
+TMAKE_LFLAGS_SHLIB = -b
+TMAKE_LFLAGS_SONAME =
+TMAKE_HPUX_SHLIB = 1
+
+TMAKE_LIBS =
+TMAKE_LIBS_X11 = -lX11 -lXext
+TMAKE_LIBS_QT = -lqt
+TMAKE_LIBS_QT_OPENGL = -lqgl
+TMAKE_LIBS_OPENGL = -lGL -lGLU -lXmu
+TMAKE_LIBS_YACC = -ly
+
+TMAKE_MOC = moc
+
+TMAKE_AR = ar cq
+TMAKE_RANLIB =
+
+TMAKE_TAR = tar -cf
+TMAKE_GZIP = gzip -9f
diff --git a/tmake/lib/hpux-cc/app.t b/tmake/lib/hpux-cc/app.t
new file mode 100755
index 0000000..867725e
--- /dev/null
+++ b/tmake/lib/hpux-cc/app.t
@@ -0,0 +1,2 @@
+#! Use the common Unix template
+#$ IncludeTemplate("../unix/app.t");
diff --git a/tmake/lib/hpux-cc/lib.t b/tmake/lib/hpux-cc/lib.t
new file mode 100755
index 0000000..2523b2f
--- /dev/null
+++ b/tmake/lib/hpux-cc/lib.t
@@ -0,0 +1,2 @@
+#! Use the common Unix template
+#$ IncludeTemplate("../unix/lib.t");
diff --git a/tmake/lib/hpux-cc/subdirs.t b/tmake/lib/hpux-cc/subdirs.t
new file mode 100755
index 0000000..5e888af
--- /dev/null
+++ b/tmake/lib/hpux-cc/subdirs.t
@@ -0,0 +1,2 @@
+#! Use the common Unix template
+#$ IncludeTemplate("../unix/subdirs.t");
diff --git a/tmake/lib/hpux-cc/tmake.conf b/tmake/lib/hpux-cc/tmake.conf
new file mode 100755
index 0000000..851cb67
--- /dev/null
+++ b/tmake/lib/hpux-cc/tmake.conf
@@ -0,0 +1,58 @@
+#
+# $Id$
+#
+# tmake configuration for hpux-cc
+#
+
+TEMPLATE = app
+CONFIG = qt warn_on release
+
+TMAKE_CC = cc
+TMAKE_CFLAGS = -w +a1
+TMAKE_CFLAGS_WARN_ON =
+TMAKE_CFLAGS_WARN_OFF =
+TMAKE_CFLAGS_RELEASE = -O
+TMAKE_CFLAGS_DEBUG = -g
+TMAKE_CFLAGS_SHLIB = +Z
+TMAKE_CFLAGS_YACC =
+
+TMAKE_CXX = CC
+TMAKE_CXXFLAGS = $$TMAKE_CFLAGS
+TMAKE_CXXFLAGS_WARN_ON = $$TMAKE_CFLAGS_WARN_ON
+TMAKE_CXXFLAGS_WARN_OFF = $$TMAKE_CFLAGS_WARN_OFF
+TMAKE_CXXFLAGS_RELEASE = $$TMAKE_CFLAGS_RELEASE
+TMAKE_CXXFLAGS_DEBUG = $$TMAKE_CFLAGS_DEBUG
+TMAKE_CXXFLAGS_SHLIB = $$TMAKE_CFLAGS_SHLIB
+TMAKE_CXXFLAGS_YACC = $$TMAKE_CFLAGS_YACC
+
+TMAKE_INCDIR =
+TMAKE_LIBDIR =
+TMAKE_INCDIR_X11 =
+TMAKE_LIBDIR_X11 =
+TMAKE_INCDIR_QT = $(QTDIR)/include
+TMAKE_LIBDIR_QT = $(QTDIR)/lib
+TMAKE_INCDIR_OPENGL =
+TMAKE_LIBDIR_OPENGL =
+
+TMAKE_LINK = CC
+TMAKE_LINK_SHLIB = CC
+TMAKE_LFLAGS =
+TMAKE_LFLAGS_RELEASE =
+TMAKE_LFLAGS_DEBUG =
+TMAKE_LFLAGS_SHLIB = -b
+TMAKE_LFLAGS_SONAME =
+TMAKE_HPUX_SHLIB = 1
+
+TMAKE_LIBS =
+TMAKE_LIBS_X11 = -lX11 -lXext
+TMAKE_LIBS_QT = -lqt
+TMAKE_LIBS_QT_OPENGL = -lqgl
+TMAKE_LIBS_OPENGL = -lGL -lGLU -lXmu
+
+TMAKE_MOC = moc
+
+TMAKE_AR = ar cq
+TMAKE_RANLIB =
+
+TMAKE_TAR = tar -cf
+TMAKE_GZIP = gzip -9f
diff --git a/tmake/lib/hpux-g++/app.t b/tmake/lib/hpux-g++/app.t
new file mode 100755
index 0000000..867725e
--- /dev/null
+++ b/tmake/lib/hpux-g++/app.t
@@ -0,0 +1,2 @@
+#! Use the common Unix template
+#$ IncludeTemplate("../unix/app.t");
diff --git a/tmake/lib/hpux-g++/lib.t b/tmake/lib/hpux-g++/lib.t
new file mode 100755
index 0000000..2523b2f
--- /dev/null
+++ b/tmake/lib/hpux-g++/lib.t
@@ -0,0 +1,2 @@
+#! Use the common Unix template
+#$ IncludeTemplate("../unix/lib.t");
diff --git a/tmake/lib/hpux-g++/subdirs.t b/tmake/lib/hpux-g++/subdirs.t
new file mode 100755
index 0000000..5e888af
--- /dev/null
+++ b/tmake/lib/hpux-g++/subdirs.t
@@ -0,0 +1,2 @@
+#! Use the common Unix template
+#$ IncludeTemplate("../unix/subdirs.t");
diff --git a/tmake/lib/hpux-g++/tmake.conf b/tmake/lib/hpux-g++/tmake.conf
new file mode 100755
index 0000000..f9b47d4
--- /dev/null
+++ b/tmake/lib/hpux-g++/tmake.conf
@@ -0,0 +1,59 @@
+#
+# $Id$
+#
+# tmake configuration for hpux-g++
+#
+
+TEMPLATE = app
+CONFIG = qt warn_on release
+
+TMAKE_CC = gcc
+TMAKE_CFLAGS =
+TMAKE_CFLAGS_WARN_ON = -Wall -W
+TMAKE_CFLAGS_WARN_OFF =
+TMAKE_CFLAGS_RELEASE = -O2 -fno-strength-reduce
+TMAKE_CFLAGS_DEBUG = -g
+TMAKE_CFLAGS_SHLIB = -fPIC
+TMAKE_CFLAGS_YACC = -Wno-unused -Wno-parentheses
+
+TMAKE_CXX = g++
+TMAKE_CXXFLAGS = $$TMAKE_CFLAGS
+TMAKE_CXXFLAGS_WARN_ON = $$TMAKE_CFLAGS_WARN_ON
+TMAKE_CXXFLAGS_WARN_OFF = $$TMAKE_CFLAGS_WARN_OFF
+TMAKE_CXXFLAGS_RELEASE = $$TMAKE_CFLAGS_RELEASE
+TMAKE_CXXFLAGS_DEBUG = $$TMAKE_CFLAGS_DEBUG
+TMAKE_CXXFLAGS_SHLIB = $$TMAKE_CFLAGS_SHLIB
+TMAKE_CXXFLAGS_YACC = $$TMAKE_CFLAGS_YACC
+
+TMAKE_INCDIR =
+TMAKE_LIBDIR =
+TMAKE_INCDIR_X11 =
+TMAKE_LIBDIR_X11 =
+TMAKE_INCDIR_QT = $(QTDIR)/include
+TMAKE_LIBDIR_QT = $(QTDIR)/lib
+TMAKE_INCDIR_OPENGL =
+TMAKE_LIBDIR_OPENGL =
+
+TMAKE_LINK = g++
+TMAKE_LINK_SHLIB = g++
+TMAKE_LFLAGS =
+TMAKE_LFLAGS_RELEASE =
+TMAKE_LFLAGS_DEBUG =
+TMAKE_LFLAGS_SHLIB = -fPIC -shared
+TMAKE_LFLAGS_SONAME =
+TMAKE_HPUX_SHLIB = 1
+
+TMAKE_LIBS =
+TMAKE_LIBS_X11 = -lX11 -lXext
+TMAKE_LIBS_QT = -lqt
+TMAKE_LIBS_QT_OPENGL = -lqgl
+TMAKE_LIBS_OPENGL =
+TMAKE_LIBS_OPENGL = -lGL -lGLU -lXmu
+
+TMAKE_MOC = moc
+
+TMAKE_AR = ar cq
+TMAKE_RANLIB =
+
+TMAKE_TAR = tar -cf
+TMAKE_GZIP = gzip -9f
diff --git a/tmake/lib/irix-64/app.t b/tmake/lib/irix-64/app.t
new file mode 100755
index 0000000..867725e
--- /dev/null
+++ b/tmake/lib/irix-64/app.t
@@ -0,0 +1,2 @@
+#! Use the common Unix template
+#$ IncludeTemplate("../unix/app.t");
diff --git a/tmake/lib/irix-64/lib.t b/tmake/lib/irix-64/lib.t
new file mode 100755
index 0000000..2523b2f
--- /dev/null
+++ b/tmake/lib/irix-64/lib.t
@@ -0,0 +1,2 @@
+#! Use the common Unix template
+#$ IncludeTemplate("../unix/lib.t");
diff --git a/tmake/lib/irix-64/subdirs.t b/tmake/lib/irix-64/subdirs.t
new file mode 100755
index 0000000..5e888af
--- /dev/null
+++ b/tmake/lib/irix-64/subdirs.t
@@ -0,0 +1,2 @@
+#! Use the common Unix template
+#$ IncludeTemplate("../unix/subdirs.t");
diff --git a/tmake/lib/irix-64/tmake.conf b/tmake/lib/irix-64/tmake.conf
new file mode 100755
index 0000000..2d20f07
--- /dev/null
+++ b/tmake/lib/irix-64/tmake.conf
@@ -0,0 +1,59 @@
+#
+# $Id$
+#
+# tmake configuration for irix-64
+#
+
+TEMPLATE = app
+CONFIG = qt warn_on release
+
+TMAKE_CC = CC
+TMAKE_CFLAGS = -64 LANG:bool=ON -woff 1209,1233,1314,1355,1375,1506
+TMAKE_CFLAGS_WARN_ON = -fullwarn
+TMAKE_CFLAGS_WARN_OFF =
+TMAKE_CFLAGS_RELEASE = -O2 -OPT:Olimit=3000
+TMAKE_CFLAGS_DEBUG = -g
+TMAKE_CFLAGS_SHLIB =
+TMAKE_CFLAGS_YACC = -woff 1110,1174,3262
+
+TMAKE_CXX = CC
+TMAKE_CXXFLAGS = -64 LANG:bool=ON -woff 1209,1233,1314,1355,1375,1506
+TMAKE_CXXFLAGS_WARN_ON = $$TMAKE_CFLAGS_WARN_ON
+TMAKE_CXXFLAGS_WARN_OFF = $$TMAKE_CFLAGS_WARN_OFF
+TMAKE_CXXFLAGS_RELEASE = $$TMAKE_CFLAGS_RELEASE
+TMAKE_CXXFLAGS_DEBUG = $$TMAKE_CFLAGS_DEBUG
+TMAKE_CXXFLAGS_SHLIB = $$TMAKE_CFLAGS_SHLIB
+TMAKE_CXXFLAGS_YACC = $$TMAKE_CFLAGS_YACC
+
+TMAKE_INCDIR =
+TMAKE_LIBDIR =
+TMAKE_INCDIR_X11 =
+TMAKE_LIBDIR_X11 =
+TMAKE_INCDIR_QT = $(QTDIR)/include
+TMAKE_LIBDIR_QT = $(QTDIR)/lib
+TMAKE_INCDIR_OPENGL =
+TMAKE_LIBDIR_OPENGL =
+
+TMAKE_LINK = CC
+TMAKE_LINK_SHLIB = CC
+TMAKE_LFLAGS = -64
+TMAKE_LFLAGS_RELEASE =
+TMAKE_LFLAGS_DEBUG =
+TMAKE_LFLAGS_SHLIB = -shared
+TMAKE_LFLAGS_SONAME = -Wl,-soname,
+
+TMAKE_LIBS =
+TMAKE_LIBS_X11 = -lX11 -lXext
+TMAKE_LIBS_QT = -lqt
+TMAKE_LIBS_QT_OPENGL = -lqgl
+TMAKE_LIBS_OPENGL = -lGL -lGLU -lXmu
+
+TMAKE_MOC = moc
+
+TMAKE_AR = ar cq
+TMAKE_RANLIB =
+
+TMAKE_CLEAN = so_locations
+
+TMAKE_TAR = tar -cf
+TMAKE_GZIP = gzip -9f
diff --git a/tmake/lib/irix-dcc/app.t b/tmake/lib/irix-dcc/app.t
new file mode 100755
index 0000000..867725e
--- /dev/null
+++ b/tmake/lib/irix-dcc/app.t
@@ -0,0 +1,2 @@
+#! Use the common Unix template
+#$ IncludeTemplate("../unix/app.t");
diff --git a/tmake/lib/irix-dcc/lib.t b/tmake/lib/irix-dcc/lib.t
new file mode 100755
index 0000000..2523b2f
--- /dev/null
+++ b/tmake/lib/irix-dcc/lib.t
@@ -0,0 +1,2 @@
+#! Use the common Unix template
+#$ IncludeTemplate("../unix/lib.t");
diff --git a/tmake/lib/irix-dcc/subdirs.t b/tmake/lib/irix-dcc/subdirs.t
new file mode 100755
index 0000000..5e888af
--- /dev/null
+++ b/tmake/lib/irix-dcc/subdirs.t
@@ -0,0 +1,2 @@
+#! Use the common Unix template
+#$ IncludeTemplate("../unix/subdirs.t");
diff --git a/tmake/lib/irix-dcc/tmake.conf b/tmake/lib/irix-dcc/tmake.conf
new file mode 100755
index 0000000..5f69690
--- /dev/null
+++ b/tmake/lib/irix-dcc/tmake.conf
@@ -0,0 +1,59 @@
+#
+# $Id$
+#
+# tmake configuration for irix-dcc
+#
+
+TEMPLATE = app
+CONFIG = qt warn_on release
+
+TMAKE_CC = DCC
+TMAKE_CFLAGS =
+TMAKE_CFLAGS_WARN_ON = -fullwarn
+TMAKE_CFLAGS_WARN_OFF =
+TMAKE_CFLAGS_RELEASE = -O2
+TMAKE_CFLAGS_DEBUG = -g
+TMAKE_CFLAGS_SHLIB =
+TMAKE_CFLAGS_YACC =
+
+TMAKE_CXX = DCC
+TMAKE_CXXFLAGS = $$TMAKE_CFLAGS
+TMAKE_CXXFLAGS_WARN_ON = $$TMAKE_CFLAGS_WARN_ON
+TMAKE_CXXFLAGS_WARN_OFF = $$TMAKE_CFLAGS_WARN_OFF
+TMAKE_CXXFLAGS_RELEASE = $$TMAKE_CFLAGS_RELEASE
+TMAKE_CXXFLAGS_DEBUG = $$TMAKE_CFLAGS_DEBUG
+TMAKE_CXXFLAGS_SHLIB = $$TMAKE_CFLAGS_SHLIB
+TMAKE_CXXFLAGS_YACC = $$TMAKE_CFLAGS_YACC
+
+TMAKE_INCDIR =
+TMAKE_LIBDIR =
+TMAKE_INCDIR_X11 =
+TMAKE_LIBDIR_X11 =
+TMAKE_INCDIR_QT = $(QTDIR)/include
+TMAKE_LIBDIR_QT = $(QTDIR)/lib
+TMAKE_INCDIR_OPENGL =
+TMAKE_LIBDIR_OPENGL =
+
+TMAKE_LINK = DCC
+TMAKE_LINK_SHLIB = DCC
+TMAKE_LFLAGS =
+TMAKE_LFLAGS_RELEASE =
+TMAKE_LFLAGS_DEBUG =
+TMAKE_LFLAGS_SHLIB = -shared
+TMAKE_LFLAGS_SONAME = -Wl,-soname,
+
+TMAKE_LIBS =
+TMAKE_LIBS_X11 = -lX11 -lXext
+TMAKE_LIBS_QT = -lqt
+TMAKE_LIBS_QT_OPENGL = -lqgl
+TMAKE_LIBS_OPENGL = -lGL -lGLU -lXmu
+
+TMAKE_MOC = moc
+
+TMAKE_AR = ar cq
+TMAKE_RANLIB =
+
+TMAKE_CLEAN = so_locations
+
+TMAKE_TAR = tar -cf
+TMAKE_GZIP = gzip -9f
diff --git a/tmake/lib/irix-g++/app.t b/tmake/lib/irix-g++/app.t
new file mode 100755
index 0000000..867725e
--- /dev/null
+++ b/tmake/lib/irix-g++/app.t
@@ -0,0 +1,2 @@
+#! Use the common Unix template
+#$ IncludeTemplate("../unix/app.t");
diff --git a/tmake/lib/irix-g++/lib.t b/tmake/lib/irix-g++/lib.t
new file mode 100755
index 0000000..2523b2f
--- /dev/null
+++ b/tmake/lib/irix-g++/lib.t
@@ -0,0 +1,2 @@
+#! Use the common Unix template
+#$ IncludeTemplate("../unix/lib.t");
diff --git a/tmake/lib/irix-g++/subdirs.t b/tmake/lib/irix-g++/subdirs.t
new file mode 100755
index 0000000..5e888af
--- /dev/null
+++ b/tmake/lib/irix-g++/subdirs.t
@@ -0,0 +1,2 @@
+#! Use the common Unix template
+#$ IncludeTemplate("../unix/subdirs.t");
diff --git a/tmake/lib/irix-g++/tmake.conf b/tmake/lib/irix-g++/tmake.conf
new file mode 100755
index 0000000..f6fea61
--- /dev/null
+++ b/tmake/lib/irix-g++/tmake.conf
@@ -0,0 +1,59 @@
+#
+# $Id$
+#
+# tmake configuration for irix-g++
+#
+
+TEMPLATE = app
+CONFIG = qt warn_on release
+
+TMAKE_CC = gcc
+TMAKE_CFLAGS =
+TMAKE_CFLAGS_WARN_ON = -Wall -W
+TMAKE_CFLAGS_WARN_OFF =
+TMAKE_CFLAGS_RELEASE = -O2 -fno-strength-reduce
+TMAKE_CFLAGS_DEBUG = -g
+TMAKE_CFLAGS_SHLIB = -fPIC
+TMAKE_CFLAGS_YACC = -Wno-unused -Wno-parentheses
+
+TMAKE_CXX = g++
+TMAKE_CXXFLAGS = $$TMAKE_CFLAGS
+TMAKE_CXXFLAGS_WARN_ON = $$TMAKE_CFLAGS_WARN_ON
+TMAKE_CXXFLAGS_WARN_OFF = $$TMAKE_CFLAGS_WARN_OFF
+TMAKE_CXXFLAGS_RELEASE = $$TMAKE_CFLAGS_RELEASE
+TMAKE_CXXFLAGS_DEBUG = $$TMAKE_CFLAGS_DEBUG
+TMAKE_CXXFLAGS_SHLIB = $$TMAKE_CFLAGS_SHLIB
+TMAKE_CXXFLAGS_YACC = $$TMAKE_CFLAGS_YACC
+
+TMAKE_INCDIR =
+TMAKE_LIBDIR =
+TMAKE_INCDIR_X11 =
+TMAKE_LIBDIR_X11 =
+TMAKE_INCDIR_QT = $(QTDIR)/include
+TMAKE_LIBDIR_QT = $(QTDIR)/lib
+TMAKE_INCDIR_OPENGL =
+TMAKE_LIBDIR_OPENGL =
+
+TMAKE_LINK = g++
+TMAKE_LINK_SHLIB = g++
+TMAKE_LFLAGS =
+TMAKE_LFLAGS_RELEASE =
+TMAKE_LFLAGS_DEBUG =
+TMAKE_LFLAGS_SHLIB = -shared
+TMAKE_LFLAGS_SONAME = -Wl,-soname,
+
+TMAKE_LIBS =
+TMAKE_LIBS_X11 = -lX11 -lXext
+TMAKE_LIBS_QT = -lqt
+TMAKE_LIBS_QT_OPENGL = -lqgl
+TMAKE_LIBS_OPENGL = -lGL -lGLU -lXmu
+
+TMAKE_MOC = moc
+
+TMAKE_AR = ar cq
+TMAKE_RANLIB = ranlib
+
+TMAKE_CLEAN = so_locations
+
+TMAKE_TAR = tar -cf
+TMAKE_GZIP = gzip -9f
diff --git a/tmake/lib/irix-n32/app.t b/tmake/lib/irix-n32/app.t
new file mode 100755
index 0000000..867725e
--- /dev/null
+++ b/tmake/lib/irix-n32/app.t
@@ -0,0 +1,2 @@
+#! Use the common Unix template
+#$ IncludeTemplate("../unix/app.t");
diff --git a/tmake/lib/irix-n32/lib.t b/tmake/lib/irix-n32/lib.t
new file mode 100755
index 0000000..2523b2f
--- /dev/null
+++ b/tmake/lib/irix-n32/lib.t
@@ -0,0 +1,2 @@
+#! Use the common Unix template
+#$ IncludeTemplate("../unix/lib.t");
diff --git a/tmake/lib/irix-n32/subdirs.t b/tmake/lib/irix-n32/subdirs.t
new file mode 100755
index 0000000..5e888af
--- /dev/null
+++ b/tmake/lib/irix-n32/subdirs.t
@@ -0,0 +1,2 @@
+#! Use the common Unix template
+#$ IncludeTemplate("../unix/subdirs.t");
diff --git a/tmake/lib/irix-n32/tmake.conf b/tmake/lib/irix-n32/tmake.conf
new file mode 100755
index 0000000..52a6a38
--- /dev/null
+++ b/tmake/lib/irix-n32/tmake.conf
@@ -0,0 +1,59 @@
+#
+# $Id$
+#
+# tmake configuration for irix-n32
+#
+
+TEMPLATE = app
+CONFIG = qt warn_on release
+
+TMAKE_CC = CC
+TMAKE_CFLAGS = -n32 LANG:bool=ON -woff 1209,1233,1314,1355,1375,1506
+TMAKE_CFLAGS_WARN_ON = -fullwarn
+TMAKE_CFLAGS_WARN_OFF =
+TMAKE_CFLAGS_RELEASE = -O2 -OPT:Olimit=3000
+TMAKE_CFLAGS_DEBUG = -g
+TMAKE_CFLAGS_SHLIB =
+TMAKE_CFLAGS_YACC = -woff 1110,1174,3262
+
+TMAKE_CXX = CC
+TMAKE_CXXFLAGS = -n32 LANG:bool=ON -woff 1209,1233,1314,1355,1375,1506
+TMAKE_CXXFLAGS_WARN_ON = $$TMAKE_CFLAGS_WARN_ON
+TMAKE_CXXFLAGS_WARN_OFF = $$TMAKE_CFLAGS_WARN_OFF
+TMAKE_CXXFLAGS_RELEASE = $$TMAKE_CFLAGS_RELEASE
+TMAKE_CXXFLAGS_DEBUG = $$TMAKE_CFLAGS_DEBUG
+TMAKE_CXXFLAGS_SHLIB = $$TMAKE_CFLAGS_SHLIB
+TMAKE_CXXFLAGS_YACC = $$TMAKE_CFLAGS_YACC
+
+TMAKE_INCDIR =
+TMAKE_LIBDIR =
+TMAKE_INCDIR_X11 =
+TMAKE_LIBDIR_X11 =
+TMAKE_INCDIR_QT = $(QTDIR)/include
+TMAKE_LIBDIR_QT = $(QTDIR)/lib
+TMAKE_INCDIR_OPENGL =
+TMAKE_LIBDIR_OPENGL =
+
+TMAKE_LINK = CC
+TMAKE_LINK_SHLIB = CC
+TMAKE_LFLAGS = -n32
+TMAKE_LFLAGS_RELEASE =
+TMAKE_LFLAGS_DEBUG =
+TMAKE_LFLAGS_SHLIB = -shared
+TMAKE_LFLAGS_SONAME = -Wl,-soname,
+
+TMAKE_LIBS =
+TMAKE_LIBS_X11 = -lX11 -lXext
+TMAKE_LIBS_QT = -lqt
+TMAKE_LIBS_QT_OPENGL = -lqgl
+TMAKE_LIBS_OPENGL = -lGL -lGLU -lXmu
+
+TMAKE_MOC = moc
+
+TMAKE_AR = ar cq
+TMAKE_RANLIB =
+
+TMAKE_CLEAN = so_locations
+
+TMAKE_TAR = tar -cf
+TMAKE_GZIP = gzip -9f
diff --git a/tmake/lib/linux-g++/app.t b/tmake/lib/linux-g++/app.t
new file mode 100755
index 0000000..867725e
--- /dev/null
+++ b/tmake/lib/linux-g++/app.t
@@ -0,0 +1,2 @@
+#! Use the common Unix template
+#$ IncludeTemplate("../unix/app.t");
diff --git a/tmake/lib/linux-g++/lib.t b/tmake/lib/linux-g++/lib.t
new file mode 100755
index 0000000..2523b2f
--- /dev/null
+++ b/tmake/lib/linux-g++/lib.t
@@ -0,0 +1,2 @@
+#! Use the common Unix template
+#$ IncludeTemplate("../unix/lib.t");
diff --git a/tmake/lib/linux-g++/subdirs.t b/tmake/lib/linux-g++/subdirs.t
new file mode 100755
index 0000000..5e888af
--- /dev/null
+++ b/tmake/lib/linux-g++/subdirs.t
@@ -0,0 +1,2 @@
+#! Use the common Unix template
+#$ IncludeTemplate("../unix/subdirs.t");
diff --git a/tmake/lib/linux-g++/tmake.conf b/tmake/lib/linux-g++/tmake.conf
new file mode 100755
index 0000000..01b0d82
--- /dev/null
+++ b/tmake/lib/linux-g++/tmake.conf
@@ -0,0 +1,57 @@
+#
+# $Id$
+#
+# tmake configuration for linux-g++
+#
+
+TEMPLATE = app
+CONFIG = qt warn_on release
+
+TMAKE_CC = gcc
+TMAKE_CFLAGS = -pipe
+TMAKE_CFLAGS_WARN_ON = -Wall -W
+TMAKE_CFLAGS_WARN_OFF =
+TMAKE_CFLAGS_RELEASE = -O2 -fno-strength-reduce
+TMAKE_CFLAGS_DEBUG = -g
+TMAKE_CFLAGS_SHLIB = -fPIC
+TMAKE_CFLAGS_YACC = -Wno-unused -Wno-parentheses
+
+TMAKE_CXX = g++
+TMAKE_CXXFLAGS = $$TMAKE_CFLAGS
+TMAKE_CXXFLAGS_WARN_ON = $$TMAKE_CFLAGS_WARN_ON
+TMAKE_CXXFLAGS_WARN_OFF = $$TMAKE_CFLAGS_WARN_OFF
+TMAKE_CXXFLAGS_RELEASE = $$TMAKE_CFLAGS_RELEASE
+TMAKE_CXXFLAGS_DEBUG = $$TMAKE_CFLAGS_DEBUG
+TMAKE_CXXFLAGS_SHLIB = $$TMAKE_CFLAGS_SHLIB
+TMAKE_CXXFLAGS_YACC = $$TMAKE_CFLAGS_YACC
+
+TMAKE_INCDIR =
+TMAKE_LIBDIR =
+TMAKE_INCDIR_X11 = /usr/X11R6/include
+TMAKE_LIBDIR_X11 = /usr/X11R6/lib
+TMAKE_INCDIR_QT = $(QTDIR)/include
+TMAKE_LIBDIR_QT = $(QTDIR)/lib
+TMAKE_INCDIR_OPENGL = /usr/X11R6/include
+TMAKE_LIBDIR_OPENGL = /usr/X11R6/lib
+
+TMAKE_LINK = g++
+TMAKE_LINK_SHLIB = g++
+TMAKE_LFLAGS =
+TMAKE_LFLAGS_RELEASE =
+TMAKE_LFLAGS_DEBUG =
+TMAKE_LFLAGS_SHLIB = -shared
+TMAKE_LFLAGS_SONAME = -Wl,-soname,
+
+TMAKE_LIBS =
+TMAKE_LIBS_X11 = -lX11 -lXext
+TMAKE_LIBS_QT = -lqt
+TMAKE_LIBS_QT_OPENGL = -lqgl
+TMAKE_LIBS_OPENGL = -lMesaGL -lMesaGLU -lXmu -lXext -lm
+
+TMAKE_MOC = moc
+
+TMAKE_AR = ar cqs
+TMAKE_RANLIB =
+
+TMAKE_TAR = tar -cf
+TMAKE_GZIP = gzip -9f
diff --git a/tmake/lib/netbsd-g++/app.t b/tmake/lib/netbsd-g++/app.t
new file mode 100755
index 0000000..867725e
--- /dev/null
+++ b/tmake/lib/netbsd-g++/app.t
@@ -0,0 +1,2 @@
+#! Use the common Unix template
+#$ IncludeTemplate("../unix/app.t");
diff --git a/tmake/lib/netbsd-g++/lib.t b/tmake/lib/netbsd-g++/lib.t
new file mode 100755
index 0000000..2523b2f
--- /dev/null
+++ b/tmake/lib/netbsd-g++/lib.t
@@ -0,0 +1,2 @@
+#! Use the common Unix template
+#$ IncludeTemplate("../unix/lib.t");
diff --git a/tmake/lib/netbsd-g++/subdirs.t b/tmake/lib/netbsd-g++/subdirs.t
new file mode 100755
index 0000000..5e888af
--- /dev/null
+++ b/tmake/lib/netbsd-g++/subdirs.t
@@ -0,0 +1,2 @@
+#! Use the common Unix template
+#$ IncludeTemplate("../unix/subdirs.t");
diff --git a/tmake/lib/netbsd-g++/tmake.conf b/tmake/lib/netbsd-g++/tmake.conf
new file mode 100755
index 0000000..53bbadc
--- /dev/null
+++ b/tmake/lib/netbsd-g++/tmake.conf
@@ -0,0 +1,60 @@
+#
+# $Id$
+#
+# tmake configuration for netbsd-g++
+#
+
+TEMPLATE = app
+CONFIG = qt warn_on release
+
+TMAKE_CC = gcc
+TMAKE_CFLAGS =
+TMAKE_CFLAGS_WARN_ON = -Wall -W
+TMAKE_CFLAGS_WARN_OFF =
+TMAKE_CFLAGS_RELEASE = -O2 -fno-strength-reduce
+TMAKE_CFLAGS_DEBUG = -g
+TMAKE_CFLAGS_SHLIB = -fPIC
+TMAKE_CFLAGS_YACC = -Wno-unused -Wno-parentheses
+
+TMAKE_CXX = g++
+TMAKE_CXXFLAGS = $$TMAKE_CFLAGS
+TMAKE_CXXFLAGS_WARN_ON = $$TMAKE_CFLAGS_WARN_ON
+TMAKE_CXXFLAGS_WARN_OFF = $$TMAKE_CFLAGS_WARN_OFF
+TMAKE_CXXFLAGS_RELEASE = $$TMAKE_CFLAGS_RELEASE
+TMAKE_CXXFLAGS_DEBUG = $$TMAKE_CFLAGS_DEBUG
+TMAKE_CXXFLAGS_SHLIB = $$TMAKE_CFLAGS_SHLIB
+TMAKE_CXXFLAGS_YACC = $$TMAKE_CFLAGS_YACC
+
+TMAKE_INCDIR =
+TMAKE_LIBDIR =
+TMAKE_INCDIR_X11 = /usr/X11R6/include
+TMAKE_LIBDIR_X11 = /usr/X11R6/lib
+TMAKE_INCDIR_QT = $(QTDIR)/include
+TMAKE_LIBDIR_QT = $(QTDIR)/lib
+TMAKE_INCDIR_OPENGL = /usr/X11R6/include
+TMAKE_LIBDIR_OPENGL = /usr/X11R6/lib
+
+TMAKE_LINK = g++
+TMAKE_LINK_SHLIB = ld
+TMAKE_LINK_SHLIB_CMD = $(SYSCONF_LINK_SHLIB) -Bshareable $(LFLAGS) -o $(DESTDIR)$(SYSCONF_LINK_TARGET_SHARED) \
+ `lorder /usr/lib/c++rt0.o $(OBJECTS) $(OBJMOC) | \
+ tsort` $(LIBS)
+TMAKE_LFLAGS =
+TMAKE_LFLAGS_RELEASE =
+TMAKE_LFLAGS_DEBUG =
+TMAKE_LFLAGS_SHLIB = -Bshareable
+TMAKE_LFLAGS_SONAME =
+
+TMAKE_LIBS =
+TMAKE_LIBS_X11 = -lX11 -lXext
+TMAKE_LIBS_QT = -lqt
+TMAKE_LIBS_QT_OPENGL = -lqgl
+TMAKE_LIBS_OPENGL = -lMesaGL -lMesaGLU -lXmu -lXext -lm
+
+TMAKE_MOC = moc
+
+TMAKE_AR = ar cqs
+TMAKE_RANLIB =
+
+TMAKE_TAR = tar -cf
+TMAKE_GZIP = gzip -9f
diff --git a/tmake/lib/openbsd-g++/app.t b/tmake/lib/openbsd-g++/app.t
new file mode 100755
index 0000000..867725e
--- /dev/null
+++ b/tmake/lib/openbsd-g++/app.t
@@ -0,0 +1,2 @@
+#! Use the common Unix template
+#$ IncludeTemplate("../unix/app.t");
diff --git a/tmake/lib/openbsd-g++/lib.t b/tmake/lib/openbsd-g++/lib.t
new file mode 100755
index 0000000..2523b2f
--- /dev/null
+++ b/tmake/lib/openbsd-g++/lib.t
@@ -0,0 +1,2 @@
+#! Use the common Unix template
+#$ IncludeTemplate("../unix/lib.t");
diff --git a/tmake/lib/openbsd-g++/subdirs.t b/tmake/lib/openbsd-g++/subdirs.t
new file mode 100755
index 0000000..5e888af
--- /dev/null
+++ b/tmake/lib/openbsd-g++/subdirs.t
@@ -0,0 +1,2 @@
+#! Use the common Unix template
+#$ IncludeTemplate("../unix/subdirs.t");
diff --git a/tmake/lib/openbsd-g++/tmake.conf b/tmake/lib/openbsd-g++/tmake.conf
new file mode 100755
index 0000000..e45b6d7
--- /dev/null
+++ b/tmake/lib/openbsd-g++/tmake.conf
@@ -0,0 +1,60 @@
+#
+# $Id$
+#
+# tmake configuration for netbsd-g++
+#
+
+TEMPLATE = app
+CONFIG = qt warn_on release
+
+TMAKE_CC = gcc
+TMAKE_CFLAGS =
+TMAKE_CFLAGS_WARN_ON = -Wall -W
+TMAKE_CFLAGS_WARN_OFF =
+TMAKE_CFLAGS_RELEASE = -O2 -fno-strength-reduce
+TMAKE_CFLAGS_DEBUG = -g
+TMAKE_CFLAGS_SHLIB = -fPIC
+TMAKE_CFLAGS_YACC = -Wno-unused -Wno-parentheses
+
+TMAKE_CXX = g++
+TMAKE_CXXFLAGS = $$TMAKE_CFLAGS
+TMAKE_CXXFLAGS_WARN_ON = $$TMAKE_CFLAGS_WARN_ON
+TMAKE_CXXFLAGS_WARN_OFF = $$TMAKE_CFLAGS_WARN_OFF
+TMAKE_CXXFLAGS_RELEASE = $$TMAKE_CFLAGS_RELEASE
+TMAKE_CXXFLAGS_DEBUG = $$TMAKE_CFLAGS_DEBUG
+TMAKE_CXXFLAGS_SHLIB = $$TMAKE_CFLAGS_SHLIB
+TMAKE_CXXFLAGS_YACC = $$TMAKE_CFLAGS_YACC
+
+TMAKE_INCDIR =
+TMAKE_LIBDIR =
+TMAKE_INCDIR_X11 = /usr/X11R6/include
+TMAKE_LIBDIR_X11 = /usr/X11R6/lib
+TMAKE_INCDIR_QT = $(QTDIR)/include
+TMAKE_LIBDIR_QT = $(QTDIR)/lib
+TMAKE_INCDIR_OPENGL = /usr/X11R6/include
+TMAKE_LIBDIR_OPENGL = /usr/X11R6/lib
+
+TMAKE_LINK = g++
+TMAKE_LINK_SHLIB = ld
+TMAKE_LINK_SHLIB_CMD = $(SYSCONF_LINK_SHLIB) -Bshareable $(LFLAGS) -o $(DESTDIR)$(SYSCONF_LINK_TARGET_SHARED) \
+ `lorder /usr/lib/c++rt0.o $(OBJECTS) $(OBJMOC) | \
+ tsort` $(LIBS)
+TMAKE_LFLAGS =
+TMAKE_LFLAGS_RELEASE =
+TMAKE_LFLAGS_DEBUG =
+TMAKE_LFLAGS_SHLIB = -Bshareable
+TMAKE_LFLAGS_SONAME =
+
+TMAKE_LIBS =
+TMAKE_LIBS_X11 = -lX11 -lXext
+TMAKE_LIBS_QT = -lqt
+TMAKE_LIBS_QT_OPENGL = -lqgl
+TMAKE_LIBS_OPENGL = -lMesaGL -lMesaGLU -lXmu -lXext -lm
+
+TMAKE_MOC = moc
+
+TMAKE_AR = ar q
+TMAKE_RANLIB = ranlib
+
+TMAKE_TAR = tar -cf
+TMAKE_GZIP = gzip -9f
diff --git a/tmake/lib/osf1-cxx/app.t b/tmake/lib/osf1-cxx/app.t
new file mode 100755
index 0000000..867725e
--- /dev/null
+++ b/tmake/lib/osf1-cxx/app.t
@@ -0,0 +1,2 @@
+#! Use the common Unix template
+#$ IncludeTemplate("../unix/app.t");
diff --git a/tmake/lib/osf1-cxx/lib.t b/tmake/lib/osf1-cxx/lib.t
new file mode 100755
index 0000000..2523b2f
--- /dev/null
+++ b/tmake/lib/osf1-cxx/lib.t
@@ -0,0 +1,2 @@
+#! Use the common Unix template
+#$ IncludeTemplate("../unix/lib.t");
diff --git a/tmake/lib/osf1-cxx/subdirs.t b/tmake/lib/osf1-cxx/subdirs.t
new file mode 100755
index 0000000..5e888af
--- /dev/null
+++ b/tmake/lib/osf1-cxx/subdirs.t
@@ -0,0 +1,2 @@
+#! Use the common Unix template
+#$ IncludeTemplate("../unix/subdirs.t");
diff --git a/tmake/lib/osf1-cxx/tmake.conf b/tmake/lib/osf1-cxx/tmake.conf
new file mode 100755
index 0000000..7e4200e
--- /dev/null
+++ b/tmake/lib/osf1-cxx/tmake.conf
@@ -0,0 +1,57 @@
+#
+# $Id$
+#
+# tmake configuration for osf1-cxx (a.k.a. DEC Unix)
+#
+
+TEMPLATE = app
+CONFIG = qt warn_on release
+
+TMAKE_CC = cxx
+TMAKE_CFLAGS = -x cxx -w -D_POSIX_SOURCE -D_OSF_SOURCE -D_AES_SOURCE
+TMAKE_CFLAGS_WARN_ON =
+TMAKE_CFLAGS_WARN_OFF =
+TMAKE_CFLAGS_RELEASE = -O2
+TMAKE_CFLAGS_DEBUG = -g
+TMAKE_CFLAGS_SHLIB =
+TMAKE_CFLAGS_YACC = -Olimit 1000
+
+TMAKE_CXX = cxx
+TMAKE_CXXFLAGS = -x cxx -w -D_POSIX_SOURCE -D_OSF_SOURCE -D_AES_SOURCE
+TMAKE_CXXFLAGS_WARN_ON = $$TMAKE_CFLAGS_WARN_ON
+TMAKE_CXXFLAGS_WARN_OFF = $$TMAKE_CFLAGS_WARN_OFF
+TMAKE_CXXFLAGS_RELEASE = $$TMAKE_CFLAGS_RELEASE
+TMAKE_CXXFLAGS_DEBUG = $$TMAKE_CFLAGS_DEBUG
+TMAKE_CXXFLAGS_SHLIB = $$TMAKE_CFLAGS_SHLIB
+TMAKE_CXXFLAGS_YACC = $$TMAKE_CFLAGS_YACC
+
+TMAKE_INCDIR =
+TMAKE_LIBDIR =
+TMAKE_INCDIR_X11 = /usr/X11R6/include
+TMAKE_LIBDIR_X11 = /usr/X11R6/lib
+TMAKE_INCDIR_QT = $(QTDIR)/include
+TMAKE_LIBDIR_QT = $(QTDIR)/lib
+TMAKE_INCDIR_OPENGL = /usr/X11R6/include
+TMAKE_LIBDIR_OPENGL = /usr/X11R6/lib
+
+TMAKE_LINK = cxx
+TMAKE_LINK_SHLIB = cxx
+TMAKE_LFLAGS =
+TMAKE_LFLAGS_RELEASE =
+TMAKE_LFLAGS_DEBUG =
+TMAKE_LFLAGS_SHLIB = -shared
+TMAKE_LFLAGS_SONAME =
+
+TMAKE_LIBS =
+TMAKE_LIBS_X11 = -lX11 -lXext
+TMAKE_LIBS_QT = -lqt
+TMAKE_LIBS_QT_OPENGL = -lqgl
+TMAKE_LIBS_OPENGL = -lMesaGL -lMesaGLU -lXmu -lXext -lm
+
+TMAKE_MOC = moc
+
+TMAKE_AR = ar cqs
+TMAKE_RANLIB =
+
+TMAKE_TAR = tar -cf
+TMAKE_GZIP = gzip -9f
diff --git a/tmake/lib/osf1-g++/app.t b/tmake/lib/osf1-g++/app.t
new file mode 100755
index 0000000..867725e
--- /dev/null
+++ b/tmake/lib/osf1-g++/app.t
@@ -0,0 +1,2 @@
+#! Use the common Unix template
+#$ IncludeTemplate("../unix/app.t");
diff --git a/tmake/lib/osf1-g++/lib.t b/tmake/lib/osf1-g++/lib.t
new file mode 100755
index 0000000..2523b2f
--- /dev/null
+++ b/tmake/lib/osf1-g++/lib.t
@@ -0,0 +1,2 @@
+#! Use the common Unix template
+#$ IncludeTemplate("../unix/lib.t");
diff --git a/tmake/lib/osf1-g++/subdirs.t b/tmake/lib/osf1-g++/subdirs.t
new file mode 100755
index 0000000..5e888af
--- /dev/null
+++ b/tmake/lib/osf1-g++/subdirs.t
@@ -0,0 +1,2 @@
+#! Use the common Unix template
+#$ IncludeTemplate("../unix/subdirs.t");
diff --git a/tmake/lib/osf1-g++/tmake.conf b/tmake/lib/osf1-g++/tmake.conf
new file mode 100755
index 0000000..54aa2c1
--- /dev/null
+++ b/tmake/lib/osf1-g++/tmake.conf
@@ -0,0 +1,57 @@
+#
+# $Id$
+#
+# tmake configuration for osf1-g++ (a.k.a. DEC Unix)
+#
+
+TEMPLATE = app
+CONFIG = qt warn_on release
+
+TMAKE_CC = gcc
+TMAKE_CFLAGS = -D_POSIX_SOURCE -D_OSF_SOURCE -D_AES_SOURCE
+TMAKE_CFLAGS_WARN_ON = -Wall -W
+TMAKE_CFLAGS_WARN_OFF =
+TMAKE_CFLAGS_RELEASE = -O2 -fno-strength-reduce
+TMAKE_CFLAGS_DEBUG = -g
+TMAKE_CFLAGS_SHLIB = -fPIC
+TMAKE_CFLAGS_YACC = -Wno-unused -Wno-parentheses
+
+TMAKE_CXX = g++
+TMAKE_CXXFLAGS = $$TMAKE_CFLAGS
+TMAKE_CXXFLAGS_WARN_ON = $$TMAKE_CFLAGS_WARN_ON
+TMAKE_CXXFLAGS_WARN_OFF = $$TMAKE_CFLAGS_WARN_OFF
+TMAKE_CXXFLAGS_RELEASE = $$TMAKE_CFLAGS_RELEASE
+TMAKE_CXXFLAGS_DEBUG = $$TMAKE_CFLAGS_DEBUG
+TMAKE_CXXFLAGS_SHLIB = $$TMAKE_CFLAGS_SHLIB
+TMAKE_CXXFLAGS_YACC = $$TMAKE_CFLAGS_YACC
+
+TMAKE_INCDIR =
+TMAKE_LIBDIR =
+TMAKE_INCDIR_X11 = /usr/X11R6/include
+TMAKE_LIBDIR_X11 = /usr/X11R6/lib
+TMAKE_INCDIR_QT = $(QTDIR)/include
+TMAKE_LIBDIR_QT = $(QTDIR)/lib
+TMAKE_INCDIR_OPENGL = /usr/X11R6/include
+TMAKE_LIBDIR_OPENGL = /usr/X11R6/lib
+
+TMAKE_LINK = g++
+TMAKE_LINK_SHLIB = g++
+TMAKE_LFLAGS =
+TMAKE_LFLAGS_RELEASE =
+TMAKE_LFLAGS_DEBUG =
+TMAKE_LFLAGS_SHLIB = -shared
+TMAKE_LFLAGS_SONAME = -Wl,-soname,
+
+TMAKE_LIBS =
+TMAKE_LIBS_X11 = -lX11 -lXext
+TMAKE_LIBS_QT = -lqt
+TMAKE_LIBS_QT_OPENGL = -lqgl
+TMAKE_LIBS_OPENGL = -lMesaGL -lMesaGLU -lXmu -lXext -lm
+
+TMAKE_MOC = moc
+
+TMAKE_AR = ar cqs
+TMAKE_RANLIB =
+
+TMAKE_TAR = tar -cf
+TMAKE_GZIP = gzip -9f
diff --git a/tmake/lib/qnx-g++/app.t b/tmake/lib/qnx-g++/app.t
new file mode 100755
index 0000000..867725e
--- /dev/null
+++ b/tmake/lib/qnx-g++/app.t
@@ -0,0 +1,2 @@
+#! Use the common Unix template
+#$ IncludeTemplate("../unix/app.t");
diff --git a/tmake/lib/qnx-g++/lib.t b/tmake/lib/qnx-g++/lib.t
new file mode 100755
index 0000000..2523b2f
--- /dev/null
+++ b/tmake/lib/qnx-g++/lib.t
@@ -0,0 +1,2 @@
+#! Use the common Unix template
+#$ IncludeTemplate("../unix/lib.t");
diff --git a/tmake/lib/qnx-g++/subdirs.t b/tmake/lib/qnx-g++/subdirs.t
new file mode 100755
index 0000000..5e888af
--- /dev/null
+++ b/tmake/lib/qnx-g++/subdirs.t
@@ -0,0 +1,2 @@
+#! Use the common Unix template
+#$ IncludeTemplate("../unix/subdirs.t");
diff --git a/tmake/lib/qnx-g++/tmake.conf b/tmake/lib/qnx-g++/tmake.conf
new file mode 100755
index 0000000..0bb70ae
--- /dev/null
+++ b/tmake/lib/qnx-g++/tmake.conf
@@ -0,0 +1,57 @@
+#
+# $Id$
+#
+# tmake configuration for qnx-g++
+#
+
+TEMPLATE = app
+CONFIG = qt warn_on release
+
+TMAKE_CC = gcc
+TMAKE_CFLAGS = -pipe
+TMAKE_CFLAGS_WARN_ON = -Wall -W
+TMAKE_CFLAGS_WARN_OFF =
+TMAKE_CFLAGS_RELEASE = -O -fno-inline -fno-pack-struct
+TMAKE_CFLAGS_DEBUG = -g -fno-inline -fno-pack-struct
+TMAKE_CFLAGS_SHLIB =
+TMAKE_CFLAGS_YACC = -Wno-unused -Wno-parentheses -fno-inline -fno-pack-struct
+
+TMAKE_CXX = g++
+TMAKE_CXXFLAGS = $$TMAKE_CFLAGS
+TMAKE_CXXFLAGS_WARN_ON = $$TMAKE_CFLAGS_WARN_ON
+TMAKE_CXXFLAGS_WARN_OFF = $$TMAKE_CFLAGS_WARN_OFF
+TMAKE_CXXFLAGS_RELEASE = $$TMAKE_CFLAGS_RELEASE
+TMAKE_CXXFLAGS_DEBUG = $$TMAKE_CFLAGS_DEBUG
+TMAKE_CXXFLAGS_SHLIB = $$TMAKE_CFLAGS_SHLIB
+TMAKE_CXXFLAGS_YACC = $$TMAKE_CFLAGS_YACC
+
+TMAKE_INCDIR =
+TMAKE_LIBDIR =
+TMAKE_INCDIR_X11 = /usr/X11R6/include
+TMAKE_LIBDIR_X11 = /usr/X11R6/lib
+TMAKE_INCDIR_QT = $(QTDIR)/include
+TMAKE_LIBDIR_QT = $(QTDIR)/lib
+TMAKE_INCDIR_OPENGL = /usr/X11R6/include
+TMAKE_LIBDIR_OPENGL = /usr/X11R6/lib
+
+TMAKE_LINK = g++
+TMAKE_LINK_SHLIB = g++
+TMAKE_LFLAGS =
+TMAKE_LFLAGS_RELEASE =
+TMAKE_LFLAGS_DEBUG =
+TMAKE_LFLAGS_SHLIB =
+TMAKE_LFLAGS_SONAME =
+
+TMAKE_LIBS = -lunix
+TMAKE_LIBS_X11 = -lX11 -lXext
+TMAKE_LIBS_QT = -lqt
+TMAKE_LIBS_QT_OPENGL = -lqgl
+TMAKE_LIBS_OPENGL = -lMesaGL -lMesaGLU -lXmu -lXext -lm
+
+TMAKE_MOC = moc
+
+TMAKE_AR = ar cqs
+TMAKE_RANLIB =
+
+TMAKE_TAR = tar -cf
+TMAKE_GZIP = gzip -9f
diff --git a/tmake/lib/sco-g++/app.t b/tmake/lib/sco-g++/app.t
new file mode 100755
index 0000000..867725e
--- /dev/null
+++ b/tmake/lib/sco-g++/app.t
@@ -0,0 +1,2 @@
+#! Use the common Unix template
+#$ IncludeTemplate("../unix/app.t");
diff --git a/tmake/lib/sco-g++/lib.t b/tmake/lib/sco-g++/lib.t
new file mode 100755
index 0000000..2523b2f
--- /dev/null
+++ b/tmake/lib/sco-g++/lib.t
@@ -0,0 +1,2 @@
+#! Use the common Unix template
+#$ IncludeTemplate("../unix/lib.t");
diff --git a/tmake/lib/sco-g++/subdirs.t b/tmake/lib/sco-g++/subdirs.t
new file mode 100755
index 0000000..5e888af
--- /dev/null
+++ b/tmake/lib/sco-g++/subdirs.t
@@ -0,0 +1,2 @@
+#! Use the common Unix template
+#$ IncludeTemplate("../unix/subdirs.t");
diff --git a/tmake/lib/sco-g++/tmake.conf b/tmake/lib/sco-g++/tmake.conf
new file mode 100755
index 0000000..8ee470c
--- /dev/null
+++ b/tmake/lib/sco-g++/tmake.conf
@@ -0,0 +1,57 @@
+#
+# $Id$
+#
+# tmake configuration for sco-g++
+#
+
+TEMPLATE = app
+CONFIG = qt warn_on release
+
+TMAKE_CC = gcc
+TMAKE_CFLAGS =
+TMAKE_CFLAGS_WARN_ON = -Wall -W
+TMAKE_CFLAGS_WARN_OFF =
+TMAKE_CFLAGS_RELEASE = -O2 -fno-strength-reduce
+TMAKE_CFLAGS_DEBUG = -g
+TMAKE_CFLAGS_SHLIB = -fPIC
+TMAKE_CFLAGS_YACC = -Wno-unused -Wno-parentheses
+
+TMAKE_CXX = g++
+TMAKE_CXXFLAGS = $$TMAKE_CFLAGS
+TMAKE_CXXFLAGS_WARN_ON = $$TMAKE_CFLAGS_WARN_ON
+TMAKE_CXXFLAGS_WARN_OFF = $$TMAKE_CFLAGS_WARN_OFF
+TMAKE_CXXFLAGS_RELEASE = $$TMAKE_CFLAGS_RELEASE
+TMAKE_CXXFLAGS_DEBUG = $$TMAKE_CFLAGS_DEBUG
+TMAKE_CXXFLAGS_SHLIB = $$TMAKE_CFLAGS_SHLIB
+TMAKE_CXXFLAGS_YACC = $$TMAKE_CFLAGS_YACC
+
+TMAKE_INCDIR =
+TMAKE_LIBDIR =
+TMAKE_INCDIR_X11 =
+TMAKE_LIBDIR_X11 =
+TMAKE_INCDIR_QT = $(QTDIR)/include
+TMAKE_LIBDIR_QT = $(QTDIR)/lib
+TMAKE_INCDIR_OPENGL =
+TMAKE_LIBDIR_OPENGL =
+
+TMAKE_LINK = g++
+TMAKE_LINK_SHLIB = g++
+TMAKE_LFLAGS =
+TMAKE_LFLAGS_RELEASE =
+TMAKE_LFLAGS_DEBUG =
+TMAKE_LFLAGS_SHLIB = -shared
+TMAKE_LFLAGS_SONAME =
+
+TMAKE_LIBS =
+TMAKE_LIBS_X11 = -lX11 -lXext -lsocket
+TMAKE_LIBS_QT = -lqt -lsocket
+TMAKE_LIBS_QT_OPENGL = -lqgl
+TMAKE_LIBS_OPENGL = -lMesaGL -lMesaGLU -lXmu -lXext -lm
+
+TMAKE_MOC = moc
+
+TMAKE_AR = ar cq
+TMAKE_RANLIB = ranlib
+
+TMAKE_TAR = tar -cf
+TMAKE_GZIP = gzip -9f
diff --git a/tmake/lib/solaris-cc/app.t b/tmake/lib/solaris-cc/app.t
new file mode 100755
index 0000000..867725e
--- /dev/null
+++ b/tmake/lib/solaris-cc/app.t
@@ -0,0 +1,2 @@
+#! Use the common Unix template
+#$ IncludeTemplate("../unix/app.t");
diff --git a/tmake/lib/solaris-cc/lib.t b/tmake/lib/solaris-cc/lib.t
new file mode 100755
index 0000000..2523b2f
--- /dev/null
+++ b/tmake/lib/solaris-cc/lib.t
@@ -0,0 +1,2 @@
+#! Use the common Unix template
+#$ IncludeTemplate("../unix/lib.t");
diff --git a/tmake/lib/solaris-cc/subdirs.t b/tmake/lib/solaris-cc/subdirs.t
new file mode 100755
index 0000000..5e888af
--- /dev/null
+++ b/tmake/lib/solaris-cc/subdirs.t
@@ -0,0 +1,2 @@
+#! Use the common Unix template
+#$ IncludeTemplate("../unix/subdirs.t");
diff --git a/tmake/lib/solaris-cc/tmake.conf b/tmake/lib/solaris-cc/tmake.conf
new file mode 100755
index 0000000..dd8801b
--- /dev/null
+++ b/tmake/lib/solaris-cc/tmake.conf
@@ -0,0 +1,60 @@
+#
+# $Id$
+#
+# tmake configuration for solaris-cc
+#
+
+TEMPLATE = app
+CONFIG = qt warn_on release
+
+TMAKE_CC = cc
+TMAKE_CFLAGS = -pto
+TMAKE_CFLAGS_WARN_ON =
+TMAKE_CFLAGS_WARN_OFF = -w
+TMAKE_CFLAGS_RELEASE = -O2
+TMAKE_CFLAGS_DEBUG = -g
+TMAKE_CFLAGS_SHLIB = -PIC
+TMAKE_CFLAGS_YACC =
+
+TMAKE_CXX = CC
+TMAKE_CXXFLAGS = $$TMAKE_CFLAGS
+TMAKE_CXXFLAGS_WARN_ON = $$TMAKE_CFLAGS_WARN_ON
+TMAKE_CXXFLAGS_WARN_OFF = $$TMAKE_CFLAGS_WARN_OFF
+TMAKE_CXXFLAGS_RELEASE = $$TMAKE_CFLAGS_RELEASE
+TMAKE_CXXFLAGS_DEBUG = $$TMAKE_CFLAGS_DEBUG
+TMAKE_CXXFLAGS_SHLIB = $$TMAKE_CFLAGS_SHLIB
+TMAKE_CXXFLAGS_YACC = $$TMAKE_CFLAGS_YACC
+
+TMAKE_INCDIR =
+TMAKE_LIBDIR =
+TMAKE_INCDIR_X11 = /usr/openwin/include
+TMAKE_LIBDIR_X11 = /usr/openwin/lib
+TMAKE_INCDIR_QT = $(QTDIR)/include
+TMAKE_LIBDIR_QT = $(QTDIR)/lib
+TMAKE_INCDIR_OPENGL =
+TMAKE_LIBDIR_OPENGL =
+
+TMAKE_LINK = CC
+# Jan Wortelboer <janw@wins.uva.nl> suggests avoiding $LD_LIBRARY_PATH:
+TMAKE_LINK_SHLIB = CC -R$(QTDIR)/lib:/usr/openwin/lib
+TMAKE_LFLAGS =
+TMAKE_LFLAGS_RELEASE =
+TMAKE_LFLAGS_DEBUG =
+TMAKE_LFLAGS_SHLIB = -G
+TMAKE_LFLAGS_SONAME =
+
+TMAKE_LIBS =
+TMAKE_LIBS_X11 = -lX11 -lXext
+TMAKE_LIBS_QT = -lqt
+TMAKE_LIBS_QT_OPENGL = -lqgl
+TMAKE_LIBS_OPENGL = -lGL -lGLU -lXmu
+
+TMAKE_MOC = moc
+
+TMAKE_AR = CC -xar -o
+TMAKE_RANLIB =
+
+TMAKE_CLEAN = -r Templates.DB
+
+TMAKE_TAR = tar -cf
+TMAKE_GZIP = gzip -9f
diff --git a/tmake/lib/solaris-g++/app.t b/tmake/lib/solaris-g++/app.t
new file mode 100755
index 0000000..867725e
--- /dev/null
+++ b/tmake/lib/solaris-g++/app.t
@@ -0,0 +1,2 @@
+#! Use the common Unix template
+#$ IncludeTemplate("../unix/app.t");
diff --git a/tmake/lib/solaris-g++/lib.t b/tmake/lib/solaris-g++/lib.t
new file mode 100755
index 0000000..2523b2f
--- /dev/null
+++ b/tmake/lib/solaris-g++/lib.t
@@ -0,0 +1,2 @@
+#! Use the common Unix template
+#$ IncludeTemplate("../unix/lib.t");
diff --git a/tmake/lib/solaris-g++/subdirs.t b/tmake/lib/solaris-g++/subdirs.t
new file mode 100755
index 0000000..5e888af
--- /dev/null
+++ b/tmake/lib/solaris-g++/subdirs.t
@@ -0,0 +1,2 @@
+#! Use the common Unix template
+#$ IncludeTemplate("../unix/subdirs.t");
diff --git a/tmake/lib/solaris-g++/tmake.conf b/tmake/lib/solaris-g++/tmake.conf
new file mode 100755
index 0000000..c23c9b4
--- /dev/null
+++ b/tmake/lib/solaris-g++/tmake.conf
@@ -0,0 +1,57 @@
+#
+# $Id$
+#
+# tmake configuration for solaris-g++
+#
+
+TEMPLATE = app
+CONFIG = qt warn_on release
+
+TMAKE_CC = gcc
+TMAKE_CFLAGS =
+TMAKE_CFLAGS_WARN_ON = -Wall -W
+TMAKE_CFLAGS_WARN_OFF =
+TMAKE_CFLAGS_RELEASE = -O2 -fno-strength-reduce
+TMAKE_CFLAGS_DEBUG = -g
+TMAKE_CFLAGS_SHLIB = -fPIC
+TMAKE_CFLAGS_YACC = -Wno-unused -Wno-parentheses
+
+TMAKE_CXX = g++
+TMAKE_CXXFLAGS = $$TMAKE_CFLAGS
+TMAKE_CXXFLAGS_WARN_ON = $$TMAKE_CFLAGS_WARN_ON
+TMAKE_CXXFLAGS_WARN_OFF = $$TMAKE_CFLAGS_WARN_OFF
+TMAKE_CXXFLAGS_RELEASE = $$TMAKE_CFLAGS_RELEASE
+TMAKE_CXXFLAGS_DEBUG = $$TMAKE_CFLAGS_DEBUG
+TMAKE_CXXFLAGS_SHLIB = $$TMAKE_CFLAGS_SHLIB
+TMAKE_CXXFLAGS_YACC = $$TMAKE_CFLAGS_YACC
+
+TMAKE_INCDIR =
+TMAKE_LIBDIR =
+TMAKE_INCDIR_X11 = /usr/openwin/include
+TMAKE_LIBDIR_X11 = /usr/openwin/lib
+TMAKE_INCDIR_QT = $(QTDIR)/include
+TMAKE_LIBDIR_QT = $(QTDIR)/lib
+TMAKE_INCDIR_OPENGL =
+TMAKE_LIBDIR_OPENGL =
+
+TMAKE_LINK = g++
+TMAKE_LINK_SHLIB = g++
+TMAKE_LFLAGS =
+TMAKE_LFLAGS_RELEASE =
+TMAKE_LFLAGS_DEBUG =
+TMAKE_LFLAGS_SHLIB = -B dynamic -h lib$(TARGET).so.$(VER_MAJ) -shared
+TMAKE_LFLAGS_SONAME =
+
+TMAKE_LIBS =
+TMAKE_LIBS_X11 = -lX11 -lXext
+TMAKE_LIBS_QT = -lqt
+TMAKE_LIBS_QT_OPENGL = -lqgl
+TMAKE_LIBS_OPENGL = -lGL -lGLU -lXmu
+
+TMAKE_MOC = moc
+
+TMAKE_AR = ar cq
+TMAKE_RANLIB =
+
+TMAKE_TAR = tar -cf
+TMAKE_GZIP = gzip -9f
diff --git a/tmake/lib/sunos-g++/app.t b/tmake/lib/sunos-g++/app.t
new file mode 100755
index 0000000..867725e
--- /dev/null
+++ b/tmake/lib/sunos-g++/app.t
@@ -0,0 +1,2 @@
+#! Use the common Unix template
+#$ IncludeTemplate("../unix/app.t");
diff --git a/tmake/lib/sunos-g++/lib.t b/tmake/lib/sunos-g++/lib.t
new file mode 100755
index 0000000..2523b2f
--- /dev/null
+++ b/tmake/lib/sunos-g++/lib.t
@@ -0,0 +1,2 @@
+#! Use the common Unix template
+#$ IncludeTemplate("../unix/lib.t");
diff --git a/tmake/lib/sunos-g++/subdirs.t b/tmake/lib/sunos-g++/subdirs.t
new file mode 100755
index 0000000..5e888af
--- /dev/null
+++ b/tmake/lib/sunos-g++/subdirs.t
@@ -0,0 +1,2 @@
+#! Use the common Unix template
+#$ IncludeTemplate("../unix/subdirs.t");
diff --git a/tmake/lib/sunos-g++/tmake.conf b/tmake/lib/sunos-g++/tmake.conf
new file mode 100755
index 0000000..43115f8
--- /dev/null
+++ b/tmake/lib/sunos-g++/tmake.conf
@@ -0,0 +1,57 @@
+#
+# $Id$
+#
+# tmake configuration for sunos-g++
+#
+
+TEMPLATE = app
+CONFIG = qt warn_on release
+
+TMAKE_CC = gcc
+TMAKE_CFLAGS =
+TMAKE_CFLAGS_WARN_ON = -Wall -W
+TMAKE_CFLAGS_WARN_OFF =
+TMAKE_CFLAGS_RELEASE = -O2 -fno-strength-reduce
+TMAKE_CFLAGS_DEBUG = -g
+TMAKE_CFLAGS_SHLIB = -fPIC
+TMAKE_CFLAGS_YACC = -Wno-unused -Wno-parentheses
+
+TMAKE_CXX = g++
+TMAKE_CXXFLAGS = $$TMAKE_CFLAGS
+TMAKE_CXXFLAGS_WARN_ON = $$TMAKE_CFLAGS_WARN_ON
+TMAKE_CXXFLAGS_WARN_OFF = $$TMAKE_CFLAGS_WARN_OFF
+TMAKE_CXXFLAGS_RELEASE = $$TMAKE_CFLAGS_RELEASE
+TMAKE_CXXFLAGS_DEBUG = $$TMAKE_CFLAGS_DEBUG
+TMAKE_CXXFLAGS_SHLIB = $$TMAKE_CFLAGS_SHLIB
+TMAKE_CXXFLAGS_YACC = $$TMAKE_CFLAGS_YACC
+
+TMAKE_INCDIR =
+TMAKE_LIBDIR =
+TMAKE_INCDIR_X11 = /usr/openwin/include
+TMAKE_LIBDIR_X11 = /usr/openwin/lib
+TMAKE_INCDIR_QT = $(QTDIR)/include
+TMAKE_LIBDIR_QT = $(QTDIR)/lib
+TMAKE_INCDIR_OPENGL =
+TMAKE_LIBDIR_OPENGL =
+
+TMAKE_LINK = g++
+TMAKE_LINK_SHLIB = g++
+TMAKE_LFLAGS =
+TMAKE_LFLAGS_RELEASE =
+TMAKE_LFLAGS_DEBUG =
+TMAKE_LFLAGS_SHLIB = -fPIC -shared
+TMAKE_LFLAGS_SONAME =
+
+TMAKE_LIBS =
+TMAKE_LIBS_X11 = -lX11 -lXext
+TMAKE_LIBS_QT = -lqt
+TMAKE_LIBS_QT_OPENGL = -lqgl
+TMAKE_LIBS_OPENGL = -lGL -lGLU -lXmu
+
+TMAKE_MOC = moc
+
+TMAKE_AR = ar cq
+TMAKE_RANLIB = ranlib
+
+TMAKE_TAR = tar -cf
+TMAKE_GZIP = gzip -9f
diff --git a/tmake/lib/ultrix-g++/app.t b/tmake/lib/ultrix-g++/app.t
new file mode 100755
index 0000000..867725e
--- /dev/null
+++ b/tmake/lib/ultrix-g++/app.t
@@ -0,0 +1,2 @@
+#! Use the common Unix template
+#$ IncludeTemplate("../unix/app.t");
diff --git a/tmake/lib/ultrix-g++/lib.t b/tmake/lib/ultrix-g++/lib.t
new file mode 100755
index 0000000..2523b2f
--- /dev/null
+++ b/tmake/lib/ultrix-g++/lib.t
@@ -0,0 +1,2 @@
+#! Use the common Unix template
+#$ IncludeTemplate("../unix/lib.t");
diff --git a/tmake/lib/ultrix-g++/subdirs.t b/tmake/lib/ultrix-g++/subdirs.t
new file mode 100755
index 0000000..5e888af
--- /dev/null
+++ b/tmake/lib/ultrix-g++/subdirs.t
@@ -0,0 +1,2 @@
+#! Use the common Unix template
+#$ IncludeTemplate("../unix/subdirs.t");
diff --git a/tmake/lib/ultrix-g++/tmake.conf b/tmake/lib/ultrix-g++/tmake.conf
new file mode 100755
index 0000000..59147d7
--- /dev/null
+++ b/tmake/lib/ultrix-g++/tmake.conf
@@ -0,0 +1,57 @@
+#
+# $Id$
+#
+# tmake configuration for ultrix-g++
+#
+
+TEMPLATE = app
+CONFIG = qt warn_on release
+
+TMAKE_CC = gcc
+TMAKE_CFLAGS =
+TMAKE_CFLAGS_WARN_ON = -Wall -W
+TMAKE_CFLAGS_WARN_OFF =
+TMAKE_CFLAGS_RELEASE = -O2 -fno-strength-reduce
+TMAKE_CFLAGS_DEBUG = -g
+TMAKE_CFLAGS_SHLIB =
+TMAKE_CFLAGS_YACC = -Wno-unused -Wno-parentheses
+
+TMAKE_CXX = g++
+TMAKE_CXXFLAGS = $$TMAKE_CFLAGS
+TMAKE_CXXFLAGS_WARN_ON = $$TMAKE_CFLAGS_WARN_ON
+TMAKE_CXXFLAGS_WARN_OFF = $$TMAKE_CFLAGS_WARN_OFF
+TMAKE_CXXFLAGS_RELEASE = $$TMAKE_CFLAGS_RELEASE
+TMAKE_CXXFLAGS_DEBUG = $$TMAKE_CFLAGS_DEBUG
+TMAKE_CXXFLAGS_SHLIB = $$TMAKE_CFLAGS_SHLIB
+TMAKE_CXXFLAGS_YACC = $$TMAKE_CFLAGS_YACC
+
+TMAKE_INCDIR =
+TMAKE_LIBDIR =
+TMAKE_INCDIR_X11 = /usr/X11R6/include
+TMAKE_LIBDIR_X11 = /usr/X11R6/lib
+TMAKE_INCDIR_QT = $(QTDIR)/include
+TMAKE_LIBDIR_QT = $(QTDIR)/lib
+TMAKE_INCDIR_OPENGL = /usr/X11R6/include
+TMAKE_LIBDIR_OPENGL = /usr/X11R6/lib
+
+TMAKE_LINK = g++
+#TMAKE_LINK_SHLIB = g++
+TMAKE_LFLAGS =
+TMAKE_LFLAGS_RELEASE =
+TMAKE_LFLAGS_DEBUG =
+#TMAKE_LFLAGS_SHLIB = -shared
+#TMAKE_LFLAGS_SONAME = -Wl,-soname,
+
+TMAKE_LIBS =
+TMAKE_LIBS_X11 = -lX11 -lXext
+TMAKE_LIBS_QT = -lqt
+TMAKE_LIBS_QT_OPENGL = -lqgl
+TMAKE_LIBS_OPENGL = -lMesaGL -lMesaGLU -lXmu -lXext -lm
+
+TMAKE_MOC = moc
+
+TMAKE_AR = ar cqs
+TMAKE_RANLIB =
+
+TMAKE_TAR = tar -cf
+TMAKE_GZIP = gzip -9f
diff --git a/tmake/lib/unix/app.t b/tmake/lib/unix/app.t
new file mode 100755
index 0000000..f59c9f9
--- /dev/null
+++ b/tmake/lib/unix/app.t
@@ -0,0 +1,6 @@
+#############################################################################
+#!
+#! This is a tmake template for building Unix applications.
+#!
+#$ Project('TMAKE_APP_FLAG = 1');
+#$ IncludeTemplate("generic.t");
diff --git a/tmake/lib/unix/generic.t b/tmake/lib/unix/generic.t
new file mode 100755
index 0000000..d9dc6ea
--- /dev/null
+++ b/tmake/lib/unix/generic.t
@@ -0,0 +1,268 @@
+#!
+#! This is a tmake template for building UNIX applications or libraries.
+#!
+#${
+ if ( Project("TMAKE_LIB_FLAG") && !Config("staticlib") ) {
+ Project('CONFIG *= dll');
+ } elsif ( Project("TMAKE_APP_FLAG") || Config("dll") ) {
+ Project('CONFIG -= staticlib');
+ }
+ if ( Config("warn_off") ) {
+ Project('TMAKE_CFLAGS += $$TMAKE_CFLAGS_WARN_OFF');
+ Project('TMAKE_CXXFLAGS += $$TMAKE_CXXFLAGS_WARN_OFF');
+ } elsif ( Config("warn_on") ) {
+ Project('TMAKE_CFLAGS += $$TMAKE_CFLAGS_WARN_ON');
+ Project('TMAKE_CXXFLAGS += $$TMAKE_CXXFLAGS_WARN_ON');
+ }
+ if ( Config("debug") ) {
+ Project('TMAKE_CFLAGS += $$TMAKE_CFLAGS_DEBUG');
+ Project('TMAKE_CXXFLAGS += $$TMAKE_CXXFLAGS_DEBUG');
+ Project('TMAKE_LFLAGS += $$TMAKE_LFLAGS_DEBUG');
+ } elsif ( Config("release") ) {
+ Project('TMAKE_CFLAGS += $$TMAKE_CFLAGS_RELEASE');
+ Project('TMAKE_CXXFLAGS += $$TMAKE_CXXFLAGS_RELEASE');
+ Project('TMAKE_LFLAGS += $$TMAKE_LFLAGS_RELEASE');
+ }
+ if ( Config("qt") || Config("opengl") ) {
+ Project('CONFIG *= x11lib');
+ if ( Config("opengl") ) {
+ Project('CONFIG *= x11inc');
+ }
+ }
+ if ( Config("x11") ) {
+ Project('CONFIG *= x11lib');
+ Project('CONFIG *= x11inc');
+ }
+ if ( Config("qt") ) {
+ $moc_aware = 1;
+ AddIncludePath(Project("TMAKE_INCDIR_QT"));
+ if ( Config("opengl") ) {
+ Project("TMAKE_LIBDIR_QT") &&
+ Project('TMAKE_LIBS *= -L$$TMAKE_LIBDIR_QT');
+ Project('TMAKE_LIBS *= $$TMAKE_LIBS_QT_OPENGL');
+ }
+ if ( !((Project("TARGET") eq "qt") && Project("TMAKE_LIB_FLAG")) ) {
+ Project("TMAKE_LIBDIR_QT") &&
+ Project('TMAKE_LIBS *= -L$$TMAKE_LIBDIR_QT');
+ Project('TMAKE_LIBS *= $$TMAKE_LIBS_QT');
+ }
+ }
+ if ( Config("opengl") ) {
+ AddIncludePath(Project("TMAKE_INCDIR_OPENGL"));
+ Project("TMAKE_LIBDIR_OPENGL") &&
+ Project('TMAKE_LIBS *= -L$$TMAKE_LIBDIR_OPENGL');
+ Project('TMAKE_LIBS *= $$TMAKE_LIBS_OPENGL');
+ }
+ if ( Config("x11inc") ) {
+ AddIncludePath(Project("TMAKE_INCDIR_X11"));
+ }
+ if ( Config("x11lib") ) {
+ Project("TMAKE_LIBDIR_X11") &&
+ Project('TMAKE_LIBS *= -L$$TMAKE_LIBDIR_X11');
+ Project('TMAKE_LIBS *= $$TMAKE_LIBS_X11');
+ }
+ Project('TMAKE_LIBS += $$LIBS');
+ if ( !Project("TMAKE_RUN_CC") ) {
+ Project('TMAKE_RUN_CC = $(CC) -c $(CFLAGS) $(INCPATH) -o $obj $src');
+ }
+ if ( !Project("TMAKE_RUN_CC_IMP") ) {
+ Project('TMAKE_RUN_CC_IMP = $(CC) -c $(CFLAGS) $(INCPATH) -o $@ $<');
+ }
+ if ( !Project("TMAKE_RUN_CXX") ) {
+ Project('TMAKE_RUN_CXX = $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $obj $src');
+ }
+ if ( !Project("TMAKE_RUN_CXX_IMP") ) {
+ Project('TMAKE_RUN_CXX_IMP = $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $<');
+ }
+ Project('TMAKE_FILETAGS = HEADERS SOURCES TARGET DESTDIR $$FILETAGS');
+ StdInit();
+ $project{"DESTDIR"} = FixPath($project{"DESTDIR"});
+ $project{"VERSION"} || ($project{"VERSION"} = "1.0");
+ $project{"VER_MAJ"} = $project{"VERSION"};
+ $project{"VER_MAJ"} =~ s/\.\d+$//;
+ $project{"VER_MIN"} = $project{"VERSION"};
+ $project{"VER_MIN"} =~ s/^\d+\.//;
+ Project('DESTDIR_TARGET = $(TARGET)');
+ if ( Project("TMAKE_APP_FLAG") ) {
+ if ( Config("dll") ) {
+ Project('TARGET = $$TARGET.so');
+ Project("TMAKE_LFLAGS_SONAME") &&
+ ($project{"TMAKE_LFLAGS_SONAME"} .= $project{"TARGET"});
+ }
+ $project{"TARGET"} = $project{"DESTDIR"} . $project{"TARGET"};
+ } elsif ( Config("staticlib") ) {
+ $project{"TARGET"} = $project{"DESTDIR"} . "lib" .
+ $project{"TARGET"} . ".a";
+ Project("TMAKE_AR_CMD") ||
+ Project('TMAKE_AR_CMD = $(AR) $(TARGET) $(OBJECTS) $(OBJMOC)');
+ } else {
+ $project{"TARGETA"} = $project{"DESTDIR"} . "lib" .
+ $project{"TARGET"} . ".a";
+ if ( Project("TMAKE_AR_CMD") ) {
+ $project{"TMAKE_AR_CMD"} =~ s/\(TARGET\)/\(TARGETA\)/g;
+ } else {
+ Project('TMAKE_AR_CMD = $(AR) $(TARGETA) $(OBJECTS) $(OBJMOC)');
+ }
+ if ( $project{"TMAKE_HPUX_SHLIB"} ) {
+ $project{"TARGET_x.y"} = "lib" . $project{"TARGET"} . ".sl";
+ } else {
+ $project{"TARGET_"} = "lib" . $project{"TARGET"} . ".so";
+ $project{"TARGET_x"} = $project{"TARGET_"} . "." .
+ $project{"VER_MAJ"};
+ $project{"TARGET_x.y"} = $project{"TARGET_"} . "." .
+ $project{"VERSION"};
+ $project{"TMAKE_LN_SHLIB"} = "-ln -s";
+ }
+ $project{"TARGET"} = $project{"TARGET_x.y"};
+ if ( $project{"DESTDIR"} ) {
+ $project{"DESTDIR_TARGET"} = $project{"DESTDIR"} .
+ $project{"TARGET"};
+ }
+ Project("TMAKE_LFLAGS_SONAME") &&
+ ($project{"TMAKE_LFLAGS_SONAME"} .= $project{"TARGET_x"});
+ $project{"TMAKE_LINK_SHLIB_CMD"} ||
+ ($project{"TMAKE_LINK_SHLIB_CMD"} =
+ '$(LINK) $(LFLAGS) -o $(TARGETD) $(OBJECTS) $(OBJMOC) $(LIBS)');
+ }
+ if ( Config("dll") ) {
+ Project('TMAKE_CFLAGS *= $$TMAKE_CFLAGS_SHLIB' );
+ Project('TMAKE_CXXFLAGS *= $$TMAKE_CXXFLAGS_SHLIB' );
+ Project('TMAKE_LFLAGS *= $$TMAKE_LFLAGS_SHLIB $$TMAKE_LFLAGS_SONAME');
+ }
+#$}
+#!
+# Makefile for building #$ Expand("TARGET")
+# Generated by tmake at #$ Now();
+# Project: #$ Expand("PROJECT");
+# Template: #$ Expand("TEMPLATE");
+#############################################################################
+
+####### Compiler, tools and options
+
+CC = #$ Expand("TMAKE_CC");
+CXX = #$ Expand("TMAKE_CXX");
+CFLAGS = #$ Expand("TMAKE_CFLAGS"); ExpandGlue("DEFINES","-D"," -D","");
+CXXFLAGS= #$ Expand("TMAKE_CXXFLAGS"); ExpandGlue("DEFINES","-D"," -D","");
+INCPATH = #$ ExpandGlue("INCPATH","-I"," -I","");
+#$ Config("staticlib") && DisableOutput();
+LINK = #$ Expand("TMAKE_LINK");
+LFLAGS = #$ Expand("TMAKE_LFLAGS");
+LIBS = #$ Expand("TMAKE_LIBS");
+#$ Config("staticlib") && EnableOutput();
+#$ Project("TMAKE_LIB_FLAG") || DisableOutput();
+AR = #$ Expand("TMAKE_AR");
+RANLIB = #$ Expand("TMAKE_RANLIB");
+#$ Project("TMAKE_LIB_FLAG") || EnableOutput();
+MOC = #$ Expand("TMAKE_MOC");
+
+TAR = #$ Expand("TMAKE_TAR");
+GZIP = #$ Expand("TMAKE_GZIP");
+
+####### Files
+
+HEADERS = #$ ExpandList("HEADERS");
+SOURCES = #$ ExpandList("SOURCES");
+OBJECTS = #$ ExpandList("OBJECTS");
+SRCMOC = #$ ExpandList("SRCMOC");
+OBJMOC = #$ ExpandList("OBJMOC");
+DIST = #$ ExpandList("DISTFILES");
+TARGET = #$ Expand("TARGET");
+#$ (Project("TMAKE_APP_FLAG") || Config("staticlib")) && DisableOutput();
+TARGETA = #$ Expand("TARGETA");
+TARGETD = #$ Expand("TARGET_x.y");
+TARGET0 = #$ Expand("TARGET_");
+TARGET1 = #$ Expand("TARGET_x");
+#$ (Project("TMAKE_APP_FLAG") || Config("staticlib")) && EnableOutput();
+
+####### Implicit rules
+
+.SUFFIXES: .cpp .cxx .cc .C .c
+
+.cpp.o:
+ #$ Expand("TMAKE_RUN_CXX_IMP");
+
+.cxx.o:
+ #$ Expand("TMAKE_RUN_CXX_IMP");
+
+.cc.o:
+ #$ Expand("TMAKE_RUN_CXX_IMP");
+
+.C.o:
+ #$ Expand("TMAKE_RUN_CXX_IMP");
+
+.c.o:
+ #$ Expand("TMAKE_RUN_CC_IMP");
+
+####### Build rules
+
+#$ Project("TMAKE_APP_FLAG") || DisableOutput();
+all: #$ ExpandGlue("ALL_DEPS",""," "," "); $text .= '$(TARGET)';
+
+$(TARGET): $(OBJECTS) $(OBJMOC) #$ Expand("TARGETDEPS");
+ $(LINK) $(LFLAGS) -o $(TARGET) $(OBJECTS) $(OBJMOC) $(LIBS)
+#$ Project("TMAKE_APP_FLAG") || EnableOutput();
+#$ (Config("staticlib") || Project("TMAKE_APP_FLAG")) && DisableOutput();
+all: #$ ExpandGlue("ALL_DEPS",""," ",""); Expand("DESTDIR_TARGET");
+
+#$ Substitute('$$DESTDIR_TARGET: $(OBJECTS) $(OBJMOC) $$TARGETDEPS');
+ -rm -f $(TARGET) $(TARGET0) $(TARGET1)
+ #$ Expand("TMAKE_LINK_SHLIB_CMD");
+ #$ ExpandGlue("TMAKE_LN_SHLIB",""," "," \$(TARGET) \$(TARGET0)");
+ #$ ExpandGlue("TMAKE_LN_SHLIB",""," "," \$(TARGET) \$(TARGET1)");
+ #${
+ $d = Project("DESTDIR");
+ if ( $d ) {
+ $d =~ s-([^/])$-$1/-;
+ if ( Project("TMAKE_HPUX_SHLIB") ) {
+ $text = "-rm -f $d\$(TARGET)\n\t" .
+ "-mv \$(TARGET) $d";
+ } else {
+ $text = "-rm -f $d\$(TARGET)\n\t" .
+ "-rm -f $d\$(TARGET0)\n\t" .
+ "-rm -f $d\$(TARGET1)\n\t" .
+ "-mv \$(TARGET) \$(TARGET0) \$(TARGET1) $d";
+ }
+ }
+ #$}
+
+staticlib: $(TARGETA)
+
+$(TARGETA): $(OBJECTS) $(OBJMOC) #$ Expand("TARGETDEPS");
+ -rm -f $(TARGETA)
+ #$ Expand("TMAKE_AR_CMD");
+ #$ ExpandGlue("TMAKE_RANLIB","",""," \$(TARGETA)");
+#$ (Config("staticlib") || Project("TMAKE_APP_FLAG")) && EnableOutput();
+#$ Config("staticlib") || DisableOutput();
+all: #$ ExpandGlue("ALL_DEPS",""," "," "); $text .= '$(TARGET)';
+
+staticlib: $(TARGET)
+
+$(TARGET): $(OBJECTS) $(OBJMOC) #$ Expand("TARGETDEPS");
+ -rm -f $(TARGET)
+ #$ Expand("TMAKE_AR_CMD");
+ #$ ExpandGlue("TMAKE_RANLIB","",""," \$(TARGET)");
+#$ Config("staticlib") || EnableOutput();
+
+moc: $(SRCMOC)
+
+#$ TmakeSelf();
+
+dist:
+ #$ Substitute('$(TAR) $$PROJECT.tar $$PROJECT.pro $(SOURCES) $(HEADERS) $(DIST)');
+ #$ Substitute('$(GZIP) $$PROJECT.tar');
+
+clean:
+ -rm -f $(OBJECTS) $(OBJMOC) $(SRCMOC) $(TARGET)
+#$ (Config("staticlib") || Project("TMAKE_APP_FLAG")) && DisableOutput();
+ -rm -f $(TARGET0) $(TARGET1) $(TARGETA)
+#$ (Config("staticlib") || Project("TMAKE_APP_FLAG")) && EnableOutput();
+ #$ ExpandGlue("TMAKE_CLEAN","-rm -f "," ","");
+ -rm -f *~ core
+ #$ ExpandGlue("CLEAN_FILES","-rm -f "," ","");
+
+####### Compile
+
+#$ BuildObj(Project("OBJECTS"),Project("SOURCES"));
+#$ BuildMocObj(Project("OBJMOC"),Project("SRCMOC"));
+#$ BuildMocSrc(Project("HEADERS"));
+#$ BuildMocSrc(Project("SOURCES"));
diff --git a/tmake/lib/unix/lib.t b/tmake/lib/unix/lib.t
new file mode 100755
index 0000000..dd24c63
--- /dev/null
+++ b/tmake/lib/unix/lib.t
@@ -0,0 +1,6 @@
+#############################################################################
+#!
+#! This is a tmake template for building Unix libraries.
+#!
+#$ Project('TMAKE_LIB_FLAG = 1');
+#$ IncludeTemplate("generic.t");
diff --git a/tmake/lib/unix/subdirs.t b/tmake/lib/unix/subdirs.t
new file mode 100755
index 0000000..8f20097
--- /dev/null
+++ b/tmake/lib/unix/subdirs.t
@@ -0,0 +1,36 @@
+#############################################################################
+#!
+#! This is a tmake template for creating a makefile that invokes make in
+#! sub directories - for Unix.
+#!
+#${
+ StdInit();
+ Project('MAKEFILE') || Project('MAKEFILE = Makefile');
+ Project('TMAKE') || Project('TMAKE = tmake');
+#$}
+#!
+# Makefile for building targets in sub directories.
+# Generated by tmake at #$ Now();
+# Project: #$ Expand("PROJECT");
+# Template: #$ Expand("TEMPLATE");
+#############################################################################
+
+MAKEFILE= #$ Expand("MAKEFILE");
+TMAKE = #$ Expand("TMAKE");
+
+SUBDIRS = #$ ExpandList("SUBDIRS");
+
+all: $(SUBDIRS)
+
+$(SUBDIRS): FORCE
+ cd $@; $(MAKE)
+
+tmake:
+#${
+ $text = "\t" . 'for i in $(SUBDIRS); do ( cd $$i ; $(TMAKE) $$i.pro -o $(MAKEFILE); grep "TEMPLATE.*subdirs" $$i.pro 2>/dev/null >/dev/null && $(MAKE) -f $(MAKEFILE) tmake ) ; done';
+#$}
+
+clean:
+ for i in $(SUBDIRS); do ( cd $$i ; $(MAKE) clean ) ; done
+
+FORCE:
diff --git a/tmake/lib/unixware-g++/app.t b/tmake/lib/unixware-g++/app.t
new file mode 100755
index 0000000..867725e
--- /dev/null
+++ b/tmake/lib/unixware-g++/app.t
@@ -0,0 +1,2 @@
+#! Use the common Unix template
+#$ IncludeTemplate("../unix/app.t");
diff --git a/tmake/lib/unixware-g++/lib.t b/tmake/lib/unixware-g++/lib.t
new file mode 100755
index 0000000..2523b2f
--- /dev/null
+++ b/tmake/lib/unixware-g++/lib.t
@@ -0,0 +1,2 @@
+#! Use the common Unix template
+#$ IncludeTemplate("../unix/lib.t");
diff --git a/tmake/lib/unixware-g++/subdirs.t b/tmake/lib/unixware-g++/subdirs.t
new file mode 100755
index 0000000..5e888af
--- /dev/null
+++ b/tmake/lib/unixware-g++/subdirs.t
@@ -0,0 +1,2 @@
+#! Use the common Unix template
+#$ IncludeTemplate("../unix/subdirs.t");
diff --git a/tmake/lib/unixware-g++/tmake.conf b/tmake/lib/unixware-g++/tmake.conf
new file mode 100755
index 0000000..24300a9
--- /dev/null
+++ b/tmake/lib/unixware-g++/tmake.conf
@@ -0,0 +1,57 @@
+#
+# $Id$
+#
+# tmake configuration for sco-g++
+#
+
+TEMPLATE = app
+CONFIG = qt warn_on release
+
+TMAKE_CC = gcc
+TMAKE_CFLAGS = -D_UNIXWARE
+TMAKE_CFLAGS_WARN_ON = -Wall -W
+TMAKE_CFLAGS_WARN_OFF =
+TMAKE_CFLAGS_RELEASE = -O2 -fno-strength-reduce
+TMAKE_CFLAGS_DEBUG = -g
+TMAKE_CFLAGS_SHLIB = -fPIC
+TMAKE_CFLAGS_YACC = -Wno-unused -Wno-parentheses
+
+TMAKE_CXX = g++
+TMAKE_CXXFLAGS = $$TMAKE_CFLAGS
+TMAKE_CXXFLAGS_WARN_ON = $$TMAKE_CFLAGS_WARN_ON
+TMAKE_CXXFLAGS_WARN_OFF = $$TMAKE_CFLAGS_WARN_OFF
+TMAKE_CXXFLAGS_RELEASE = $$TMAKE_CFLAGS_RELEASE
+TMAKE_CXXFLAGS_DEBUG = $$TMAKE_CFLAGS_DEBUG
+TMAKE_CXXFLAGS_SHLIB = $$TMAKE_CFLAGS_SHLIB
+TMAKE_CXXFLAGS_YACC = $$TMAKE_CFLAGS_YACC
+
+TMAKE_INCDIR =
+TMAKE_LIBDIR =
+TMAKE_INCDIR_X11 =
+TMAKE_LIBDIR_X11 = /usr/X/lib
+TMAKE_INCDIR_QT = $(QTDIR)/include
+TMAKE_LIBDIR_QT = $(QTDIR)/lib
+TMAKE_INCDIR_OPENGL =
+TMAKE_LIBDIR_OPENGL =
+
+TMAKE_LINK = g++
+TMAKE_LINK_SHLIB = g++
+TMAKE_LFLAGS =
+TMAKE_LFLAGS_RELEASE =
+TMAKE_LFLAGS_DEBUG =
+TMAKE_LFLAGS_SHLIB = -shared
+TMAKE_LFLAGS_SONAME =
+
+TMAKE_LIBS = -lsocket -lnsl -lc
+TMAKE_LIBS_X11 = -lX11 -lXext
+TMAKE_LIBS_QT = -lqt
+TMAKE_LIBS_QT_OPENGL = -lqgl
+TMAKE_LIBS_OPENGL = -lMesaGL -lMesaGLU -lXmu -lXt -lXext -lm
+
+TMAKE_MOC = moc
+
+TMAKE_AR = ar cq
+TMAKE_RANLIB =
+
+TMAKE_TAR = tar -cf
+TMAKE_GZIP = gzip -9f
diff --git a/tmake/lib/win32-borland/app.t b/tmake/lib/win32-borland/app.t
new file mode 100755
index 0000000..fc4dc2c
--- /dev/null
+++ b/tmake/lib/win32-borland/app.t
@@ -0,0 +1,6 @@
+#############################################################################
+#!
+#! This is a tmake template for building Win32 applications.
+#!
+#$ Project('TMAKE_APP_FLAG = 1');
+#$ IncludeTemplate("generic.t");
diff --git a/tmake/lib/win32-borland/generic.t b/tmake/lib/win32-borland/generic.t
new file mode 100755
index 0000000..88190d8
--- /dev/null
+++ b/tmake/lib/win32-borland/generic.t
@@ -0,0 +1,229 @@
+#!
+#! This is a tmake template for building Win32 applications or libraries.
+#!
+#${
+ if ( Config("qt") ) {
+ if ( !(Project("DEFINES") =~ /QT_NODLL/) &&
+ ((Project("DEFINES") =~ /QT_(?:MAKE)?DLL/) ||
+ ($ENV{"QT_DLL"} && !$ENV{"QT_NODLL"})) ) {
+ Project('TMAKE_QT_DLL = 1');
+ if ( (Project("TARGET") eq "qt") && Project("TMAKE_LIB_FLAG") ) {
+ Project('CONFIG += dll');
+ }
+ }
+ }
+ if ( Config("dll") || Project("TMAKE_APP_FLAG") ) {
+ Project('CONFIG -= staticlib');
+ Project('TMAKE_APP_OR_DLL = 1');
+ } else {
+ Project('CONFIG += staticlib');
+ }
+ if ( Config("warn_off") ) {
+ Project('TMAKE_CFLAGS += $$TMAKE_CFLAGS_WARN_OFF');
+ Project('TMAKE_CXXFLAGS += $$TMAKE_CXXFLAGS_WARN_OFF');
+ } elsif ( Config("warn_on") ) {
+ Project('TMAKE_CFLAGS += $$TMAKE_CFLAGS_WARN_ON');
+ Project('TMAKE_CXXFLAGS += $$TMAKE_CXXFLAGS_WARN_ON');
+ }
+ if ( Config("debug") ) {
+ Project('TMAKE_CFLAGS += $$TMAKE_CFLAGS_DEBUG');
+ Project('TMAKE_CXXFLAGS += $$TMAKE_CXXFLAGS_DEBUG');
+ Project('TMAKE_LFLAGS += $$TMAKE_LFLAGS_DEBUG');
+ } elsif ( Config("release") ) {
+ Project('TMAKE_CFLAGS += $$TMAKE_CFLAGS_RELEASE');
+ Project('TMAKE_CXXFLAGS += $$TMAKE_CXXFLAGS_RELEASE');
+ Project('TMAKE_LFLAGS += $$TMAKE_LFLAGS_RELEASE');
+ }
+ if ( Config("qt") || Config("opengl") ) {
+ Project('CONFIG += windows' );
+ }
+ if ( Config("qt") ) {
+ $moc_aware = 1;
+ AddIncludePath(Project("TMAKE_INCDIR_QT"));
+ if ( Config("opengl") ) {
+ Project('TMAKE_LIBS *= $$TMAKE_LIBS_QT_OPENGL');
+ }
+ if ( (Project("TARGET") eq "qt") && Project("TMAKE_LIB_FLAG") ) {
+ if ( Project("TMAKE_QT_DLL") ) {
+ Project('DEFINES -= QT_DLL');
+ Project('DEFINES *= QT_MAKEDLL');
+ }
+ } else {
+ if ( Project("TMAKE_QT_DLL") ) {
+ Project('DEFINES *= QT_DLL');
+ }
+ Project('TMAKE_LIBS *= $$TMAKE_LIBS_QT');
+ if ( Project("TMAKE_QT_DLL") ) {
+ my $qtver =FindHighestLibVersion($ENV{"QTDIR"} . "/lib", "qt");
+ Project("TMAKE_LIBS /= s/qt.lib/qt${qtver}.lib/");
+ Project('TMAKE_LIBS *= $$TMAKE_LIBS_QT_DLL');
+ }
+ }
+ }
+ if ( Config("opengl") ) {
+ Project('TMAKE_LIBS *= $$TMAKE_LIBS_OPENGL');
+ }
+ if ( Config("dll") ) {
+ Project('TMAKE_LFLAGS_CONSOLE_ANY = $$TMAKE_LFLAGS_CONSOLE_DLL');
+ Project('TMAKE_LFLAGS_WINDOWS_ANY = $$TMAKE_LFLAGS_WINDOWS_DLL');
+ if ( Project("TMAKE_LIB_FLAG") ) {
+ my $ver = Project("VERSION");
+ $ver =~ s/\.//g;
+ $project{"TARGET_EXT"} = "${ver}.dll";
+ } else {
+ $project{"TARGET_EXT"} = ".dll";
+ }
+ } else {
+ Project('TMAKE_LFLAGS_CONSOLE_ANY = $$TMAKE_LFLAGS_CONSOLE');
+ Project('TMAKE_LFLAGS_WINDOWS_ANY = $$TMAKE_LFLAGS_WINDOWS');
+ if ( Project("TMAKE_APP_FLAG") ) {
+ $project{"TARGET_EXT"} = ".exe";
+ } else {
+ $project{"TARGET_EXT"} = ".lib";
+ }
+ }
+ if ( Config("windows") ) {
+ if ( Config("console") ) {
+ Project('TMAKE_LFLAGS *= $$TMAKE_LFLAGS_CONSOLE_ANY');
+ Project('TMAKE_LIBS *= $$TMAKE_LIBS_CONSOLE');
+ } else {
+ Project('TMAKE_LFLAGS *= $$TMAKE_LFLAGS_WINDOWS_ANY');
+ }
+ Project('TMAKE_LIBS *= $$TMAKE_LIBS_WINDOWS');
+ } else {
+ Project('TMAKE_LFLAGS *= $$TMAKE_LFLAGS_CONSOLE_ANY');
+ Project('TMAKE_LIBS *= $$TMAKE_LIBS_CONSOLE');
+ }
+ Project('TMAKE_LIBS += $$LIBS');
+ Project('TMAKE_FILETAGS = HEADERS SOURCES DEF_FILE RC_FILE TARGET TMAKE_LIBS DESTDIR DLLDESTDIR $$FILETAGS');
+ foreach ( split(/\s/,Project("TMAKE_FILETAGS")) ) {
+ $project{$_} =~ s-[/\\]+-\\-g;
+ }
+ if ( Project("DEF_FILE") ) {
+ Project('TMAKE_LFLAGS *= /DEF:$$DEF_FILE');
+ }
+ if ( Project("RC_FILE") ) {
+ if ( Project("RES_FILE") ) {
+ tmake_error("Both .rc and .res file specified.\n" .
+ "Please specify one of them, not both.");
+ }
+ $project{"RES_FILE"} = $project{"RC_FILE"};
+ $project{"RES_FILE"} =~ s/\.rc$/.res/i;
+ Project('TARGETDEPS += $$RES_FILE');
+ }
+ if ( Project("RES_FILE") ) {
+ Project('TMAKE_LIBS *= $$RES_FILE');
+ }
+ StdInit();
+ $project{"DESTDIR"} = FixPath($project{"DESTDIR"});
+ if ( Project("VERSION") ) {
+ $project{"VER_MAJ"} = $project{"VERSION"};
+ $project{"VER_MAJ"} =~ s/\.\d+$//;
+ $project{"VER_MIN"} = $project{"VERSION"};
+ $project{"VER_MIN"} =~ s/^\d+\.//;
+ }
+ Project('TMAKE_CLEAN += $$TARGET.tds');
+#$}
+#!
+# Makefile for building #$ Expand("TARGET")
+# Generated by tmake at #$ Now();
+# Project: #$ Expand("PROJECT");
+# Template: #$ Expand("TEMPLATE");
+#############################################################################
+
+!if !$d(BCB)
+BCB = $(MAKEDIR)\..
+!endif
+
+####### Compiler, tools and options
+
+CC = #$ Expand("TMAKE_CC");
+CXX = #$ Expand("TMAKE_CXX");
+CFLAGS = #$ Expand("TMAKE_CFLAGS"); ExpandGlue("DEFINES","-D"," -D","");
+CXXFLAGS= #$ Expand("TMAKE_CXXFLAGS"); ExpandGlue("DEFINES","-D"," -D","");
+INCPATH = #$ ExpandGlue("INCPATH",'-I"','" -I"','"');
+#$ !Project("TMAKE_APP_OR_DLL") && DisableOutput();
+LINK = #$ Expand("TMAKE_LINK");
+LFLAGS = #$ Expand("TMAKE_LFLAGS");
+LIBS = #$ Expand("TMAKE_LIBS");
+#$ !Project("TMAKE_APP_OR_DLL") && EnableOutput();
+#$ Project("TMAKE_APP_OR_DLL") && DisableOutput();
+LIB = #$ Expand("TMAKE_LIB");
+#$ Project("TMAKE_APP_OR_DLL") && EnableOutput();
+MOC = #$ Expand("TMAKE_MOC");
+
+ZIP = #$ Expand("TMAKE_ZIP");
+
+####### Files
+
+HEADERS = #$ ExpandList("HEADERS");
+SOURCES = #$ ExpandList("SOURCES");
+OBJECTS = #$ ExpandList("OBJECTS");
+SRCMOC = #$ ExpandList("SRCMOC");
+OBJMOC = #$ ExpandList("OBJMOC");
+DIST = #$ ExpandList("DISTFILES");
+TARGET = #$ ExpandGlue("TARGET",$project{"DESTDIR"},"",$project{"TARGET_EXT"});
+
+####### Implicit rules
+
+.SUFFIXES: .cpp .cxx .cc .c
+
+.cpp.obj:
+ #$ Expand("TMAKE_RUN_CXX_IMP");
+
+.cxx.obj:
+ #$ Expand("TMAKE_RUN_CXX_IMP");
+
+.cc.obj:
+ #$ Expand("TMAKE_RUN_CXX_IMP");
+
+.c.obj:
+ #$ Expand("TMAKE_RUN_CC_IMP");
+
+####### Build rules
+
+all: #$ ExpandGlue("ALL_DEPS",""," "," "); $text .= '$(TARGET)';
+
+$(TARGET): $(OBJECTS) $(OBJMOC) #$ Expand("TARGETDEPS");
+#$ Project("TMAKE_APP_OR_DLL") || DisableOutput();
+ $(LINK) @&&|
+ $(LFLAGS) $(OBJECTS) $(OBJMOC), $(TARGET),,$(LIBS)
+#$ Project("TMAKE_APP_OR_DLL") || EnableOutput();
+#$ Project("TMAKE_APP_OR_DLL") && DisableOutput();
+ -del $(TARGET)
+ $(LIB) $(TARGET) @&&|
+#${
+# $text = "+" . join(" \\\n+",split(/\s+/,$project{"OBJECTS"})) . " \\\n+"
+# . join(" \\\n+",split(/\s+/,$project{"OBJMOC"}));
+#$}
+#$ Project("TMAKE_APP_OR_DLL") && EnableOutput();
+|
+#$ (Config("dll") && Project("DLLDESTDIR")) || DisableOutput();
+ -copy $(TARGET) #$ Expand("DLLDESTDIR");
+#$ (Config("dll") && Project("DLLDESTDIR")) || EnableOutput();
+#$ Project("RC_FILE") || DisableOutput();
+
+#$ Substitute("\$\$RES_FILE: \$\$RC_FILE\n\t\$\$TMAKE_RC \$\$RC_FILE");
+#$ Project("RC_FILE") || EnableOutput();
+
+moc: $(SRCMOC)
+
+#$ TmakeSelf();
+
+dist:
+ #$ Substitute('$(ZIP) $$PROJECT.zip $$PROJECT.pro $(SOURCES) $(HEADERS) $(DIST)');
+
+clean:
+ #$ ExpandGlue("OBJECTS","-del ","\n\t-del ","");
+ #$ ExpandGlue("SRCMOC" ,"-del ","\n\t-del ","");
+ #$ ExpandGlue("OBJMOC" ,"-del ","\n\t-del ","");
+ -del $(TARGET)
+ #$ ExpandGlue("TMAKE_CLEAN","-del ","\n\t-del ","");
+ #$ ExpandGlue("CLEAN_FILES","-del ","\n\t-del ","");
+
+####### Compile
+
+#$ BuildObj(Project("OBJECTS"),Project("SOURCES"));
+#$ BuildMocObj(Project("OBJMOC"),Project("SRCMOC"));
+#$ BuildMocSrc(Project("HEADERS"));
+#$ BuildMocSrc(Project("SOURCES"));
diff --git a/tmake/lib/win32-borland/lib.t b/tmake/lib/win32-borland/lib.t
new file mode 100755
index 0000000..d8ac6c7
--- /dev/null
+++ b/tmake/lib/win32-borland/lib.t
@@ -0,0 +1,6 @@
+#############################################################################
+#!
+#! This is a tmake template for building Win32 libraries.
+#!
+#$ Project('TMAKE_LIB_FLAG = 1');
+#$ IncludeTemplate("generic.t");
diff --git a/tmake/lib/win32-borland/subdirs.t b/tmake/lib/win32-borland/subdirs.t
new file mode 100755
index 0000000..8e70c0e
--- /dev/null
+++ b/tmake/lib/win32-borland/subdirs.t
@@ -0,0 +1,33 @@
+#############################################################################
+#!
+#! This is a tmake template for creating a makefile that invokes make in
+#! sub directories - for Win32/Borland C++.
+#!
+#${
+ StdInit();
+ $m = "";
+ foreach ( split(/\s+/,$project{"SUBDIRS"}) ) {
+ $m = $m . "\tcd $_\n\tDOMAKE\n\t\@cd ..\n";
+ }
+ $project{"SUBMAKE"} = $m;
+#$}
+#!
+# Makefile for building targets in sub directories.
+# Generated by tmake at #$ Now();
+# Project: #$ Expand("PROJECT");
+# Template: #$ Expand("TEMPLATE");
+#############################################################################
+
+SUBDIRS = #$ ExpandList("SUBDIRS");
+
+all: $(SUBDIRS)
+
+#${
+ foreach ( split(/\s+/,$project{"SUBDIRS"}) ) {
+ $text = $text . $_ . ":\n\t" .
+ "cd $_\n\t\$(MAKE\)\n\t\@cd ..\n\n";
+ }
+#$}
+
+clean:
+#$ $text = $project{"SUBMAKE"}; $text =~ s/DOMAKE/\$(MAKE\) clean/g;
diff --git a/tmake/lib/win32-borland/tmake.conf b/tmake/lib/win32-borland/tmake.conf
new file mode 100755
index 0000000..4dd3636
--- /dev/null
+++ b/tmake/lib/win32-borland/tmake.conf
@@ -0,0 +1,56 @@
+#
+# $Id$
+#
+# tmake configuration for Win32/Borland C++
+#
+
+TEMPLATE = app
+CONFIG = qt warn_on release
+
+TMAKE_CC = bcc32
+TMAKE_CFLAGS =
+TMAKE_CFLAGS_WARN_ON = -w
+TMAKE_CFLAGS_WARN_OFF = -w-
+TMAKE_CFLAGS_RELEASE = -O2
+TMAKE_CFLAGS_DEBUG = -v
+TMAKE_CFLAGS_YACC =
+
+TMAKE_CXX = $$TMAKE_CC
+TMAKE_CXXFLAGS = $$TMAKE_CFLAGS
+TMAKE_CXXFLAGS_WARN_ON = $$TMAKE_CFLAGS_WARN_ON
+TMAKE_CXXFLAGS_WARN_OFF = $$TMAKE_CFLAGS_WARN_OFF
+TMAKE_CXXFLAGS_RELEASE = $$TMAKE_CFLAGS_RELEASE
+TMAKE_CXXFLAGS_DEBUG = $$TMAKE_CFLAGS_DEBUG
+TMAKE_CXXFLAGS_YACC = $$TMAKE_CFLAGS_YACC
+
+TMAKE_INCDIR =
+TMAKE_INCDIR_QT = $(QTDIR)\include
+
+TMAKE_RUN_CC = $(CC) -c $(CFLAGS) $(INCPATH) -o$obj $src
+TMAKE_RUN_CC_IMP = $(CC) -c $(CFLAGS) $(INCPATH) -o$@ $<
+TMAKE_RUN_CXX = $(CXX) -c $(CXXFLAGS) $(INCPATH) -o$obj $src
+TMAKE_RUN_CXX_IMP = $(CXX) -c $(CXXFLAGS) $(INCPATH) -o$@ $<
+
+TMAKE_LINK = ilink32
+TMAKE_LFLAGS = -L$(BCB)\lib -c -x -Gn
+TMAKE_LFLAGS_RELEASE =
+TMAKE_LFLAGS_DEBUG = -v
+TMAKE_LFLAGS_CONSOLE = -ap -Tpe c0x32.obj
+TMAKE_LFLAGS_WINDOWS = -aa -Tpe c0w32.obj
+TMAKE_LFLAGS_CONSOLE_DLL= -Gi -ap -Tpd c0d32.obj
+TMAKE_LFLAGS_WINDOWS_DLL= -Gi -aa -Tpd c0d32.obj
+
+TMAKE_LIBS = import32.lib cw32.lib
+TMAKE_LIBS_CONSOLE =
+TMAKE_LIBS_WINDOWS =
+TMAKE_LIBS_QT = $(QTDIR)\lib\qt.lib
+TMAKE_LIBS_QT_DLL = $(QTDIR)\lib\qtmain.lib
+TMAKE_LIBS_QT_OPENGL = $(QTDIR)\lib\qgl.lib
+TMAKE_LIBS_OPENGL =
+
+TMAKE_MOC = moc
+
+TMAKE_LIB = tlib /C /P256
+TMAKE_RC = rc
+
+TMAKE_ZIP = zip -r -9
diff --git a/tmake/lib/win32-g++/app.t b/tmake/lib/win32-g++/app.t
new file mode 100755
index 0000000..fc4dc2c
--- /dev/null
+++ b/tmake/lib/win32-g++/app.t
@@ -0,0 +1,6 @@
+#############################################################################
+#!
+#! This is a tmake template for building Win32 applications.
+#!
+#$ Project('TMAKE_APP_FLAG = 1');
+#$ IncludeTemplate("generic.t");
diff --git a/tmake/lib/win32-g++/generic.t b/tmake/lib/win32-g++/generic.t
new file mode 100755
index 0000000..253c401
--- /dev/null
+++ b/tmake/lib/win32-g++/generic.t
@@ -0,0 +1,226 @@
+#!
+#! This is a tmake template for building Win32 applications or libraries.
+#!
+#${
+ if ( Config("qt") ) {
+ if ( $ENV{"QT_DLL"} && !$ENV{"QT_NODLL"} ) {
+ Project('TMAKE_QT_DLL = 1');
+ if ( Project("TARGET") eq "qt" ) {
+ Project('CONFIG += dll');
+ }
+ }
+ }
+ if ( Config("dll") || Project("TMAKE_APP_FLAG") ) {
+ Project('CONFIG -= staticlib');
+ Project('TMAKE_APP_OR_DLL = 1');
+ } else {
+ Project('CONFIG += staticlib');
+ }
+ if ( Config("warn_off") ) {
+ Project('TMAKE_CFLAGS += $$TMAKE_CFLAGS_WARN_OFF');
+ } elsif ( Config("warn_on") ) {
+ Project('TMAKE_CFLAGS += $$TMAKE_CFLAGS_WARN_ON');
+ }
+ if ( Config("debug") ) {
+ Project('TMAKE_CFLAGS += $$TMAKE_CFLAGS_DEBUG');
+ Project('TMAKE_LFLAGS += $$TMAKE_LFLAGS_DEBUG');
+ } elsif ( Config("release") ) {
+ Project('TMAKE_CFLAGS += $$TMAKE_CFLAGS_RELEASE');
+ Project('TMAKE_LFLAGS += $$TMAKE_LFLAGS_RELEASE');
+ }
+ if ( Config("qt") || Config("opengl") ) {
+ Project('CONFIG += windows' );
+ }
+ if ( Config("qt") ) {
+ $moc_aware = 1;
+ AddIncludePath(Project('TMAKE_INCDIR_QT'));
+ if ( Config("opengl") ) {
+ Project('TMAKE_LIBS *= $$TMAKE_LIBS_QT_OPENGL');
+ }
+ if ( Project("TARGET") eq "qt" ) {
+ if ( Project("TMAKE_QT_DLL") && !(Project("DEFINES") =~ /QT_NODLL/) ) {
+ Project('DEFINES *= QT_MAKEDLL');
+ }
+ } else {
+ if ( Project("TMAKE_QT_DLL") && !(Project("DEFINES") =~ /QT_NODLL/) ) {
+ Project('DEFINES *= QT_DLL');
+ }
+ Project('TMAKE_LIBS *= $$TMAKE_LIBS_QT');
+ if ( (Project("DEFINES") =~ /QT_DLL/) ) {
+ my $qtver =FindHighestLibVersion($ENV{"QTDIR"} . "/lib", "qt");
+ Project("TMAKE_LIBS /= s/qt.lib/qt${qtver}.lib/");
+ Project('TMAKE_LIBS *= $$TMAKE_LIBS_QT_DLL');
+ }
+ }
+ }
+ if ( Config("opengl") ) {
+ Project('TMAKE_LIBS *= $$TMAKE_LIBS_OPENGL');
+ }
+ if ( Config("dll") ) {
+ Project('TMAKE_LFLAGS_CONSOLE_ANY = $$TMAKE_LFLAGS_CONSOLE_DLL');
+ Project('TMAKE_LFLAGS_WINDOWS_ANY = $$TMAKE_LFLAGS_WINDOWS_DLL');
+ if ( Project("TMAKE_LIB_FLAG") ) {
+ my $ver = Project("VERSION");
+ $ver =~ s/\.//g;
+ $project{"TARGET_EXT"} = "${ver}.dll";
+ } else {
+ $project{"TARGET_EXT"} = ".dll";
+ }
+ } else {
+ Project('TMAKE_LFLAGS_CONSOLE_ANY = $$TMAKE_LFLAGS_CONSOLE');
+ Project('TMAKE_LFLAGS_WINDOWS_ANY = $$TMAKE_LFLAGS_WINDOWS');
+ if ( Project('TMAKE_APP_FLAG') ) {
+ $project{"TARGET_EXT"} = ".exe";
+ } else {
+ $project{"TARGET_EXT"} = ".a";
+ }
+ }
+ if ( Config("windows") ) {
+ if ( Config("console") ) {
+ Project('TMAKE_LFLAGS *= $$TMAKE_LFLAGS_CONSOLE_ANY');
+ Project('TMAKE_LIBS *= $$TMAKE_LIBS_CONSOLE');
+ } else {
+ Project('TMAKE_LFLAGS *= $$TMAKE_LFLAGS_WINDOWS_ANY');
+ }
+ Project('TMAKE_LIBS *= $$TMAKE_LIBS_WINDOWS');
+ } else {
+ Project('TMAKE_LFLAGS *= $$TMAKE_LFLAGS_CONSOLE_ANY');
+ Project('TMAKE_LIBS *= $$TMAKE_LIBS_CONSOLE');
+ }
+ Project('TMAKE_LIBS += $$LIBS');
+ Project('TMAKE_FILETAGS = HEADERS SOURCES DEF_FILE RC_FILE TARGET TMAKE_LIBS DESTDIR DLLDESTDIR $$FILETAGS');
+ foreach ( split(/\s/,Project('TMAKE_FILETAGS')) ) {
+ $project{$_} =~ s-[/\\]+-/-g;
+ }
+ $obj_ext = "o";
+ $dir_sep = "/";
+ $gnuwin32 = 1;
+ if ( Config("qt") ) {
+ $qtdir = $ENV{"QTDIR"};
+ $project{"INCPATH"} =~ s/\$\(QTDIR\)/$qtdir/;
+ $project{"INCPATH"} =~ s/\\/\//g;
+ $project{"TMAKE_LIBS"} =~ s/\$\(QTDIR\)/$qtdir/;
+ $project{"TMAKE_LIBS"} =~ s/\\/\//g;
+ }
+ if ( Project('DEF_FILE') ) {
+ Project('TMAKE_LFLAGS *= $$DEF_FILE');
+ }
+ if ( Project('RC_FILE') ) {
+ if ( Project('RES_FILE') ) {
+ tmake_error("Both .rc and .res file specified.\n" .
+ "Please specify one of them, not both.");
+ }
+ $project{"RES_FILE"} = $project{"RC_FILE"};
+ $project{"RES_FILE"} =~ s/\.rc$/.res/i;
+ Project('TARGETDEPS += $$RES_FILE');
+ }
+ if ( Project('RES_FILE') ) {
+ Project('TMAKE_LFLAGS *= $$RES_FILE');
+ }
+ StdInit();
+ $project{"DESTDIR"} = FixPath($project{"DESTDIR"});
+ if ( Project("VERSION") ) {
+ $project{"VER_MAJ"} = $project{"VERSION"};
+ $project{"VER_MAJ"} =~ s/\.\d+$//;
+ $project{"VER_MIN"} = $project{"VERSION"};
+ $project{"VER_MIN"} =~ s/^\d+\.//;
+ }
+ if ( Config("staticlib") ) {
+ $project{"TARGET"} = $project{"DESTDIR"} . "lib" . $project{"TARGET"} .
+ $project{"TARGET_EXT"};
+ } else {
+ $project{"TARGET"} = $project{"DESTDIR"} . $project{"TARGET"} .
+ $project{"TARGET_EXT"};
+ }
+#$}
+#!
+# Makefile for building #$ Expand("TARGET")
+# Generated by tmake at #$ Now();
+# Project: #$ Expand("PROJECT");
+# Template: #$ Expand("TEMPLATE");
+#############################################################################
+
+####### Compiler, tools and options
+
+CC = #$ Expand("TMAKE_CC");
+CFLAGS = #$ Expand("TMAKE_CFLAGS"); ExpandGlue("DEFINES","-D"," -D","");
+INCPATH = #$ ExpandGlue("INCPATH","-I"," -I","");
+#$ !Project("TMAKE_APP_OR_DLL") && DisableOutput();
+LINK = #$ Expand("TMAKE_LINK");
+LFLAGS = #$ Expand("TMAKE_LFLAGS");
+LIBS = #$ Expand("TMAKE_LIBS");
+#$ !Project("TMAKE_APP_OR_DLL") && EnableOutput();
+#$ Project("TMAKE_APP_OR_DLL") && DisableOutput();
+AR = #$ Expand("TMAKE_AR");
+RANLIB = #$ Expand("TMAKE_RANLIB");
+#$ Project("TMAKE_APP_OR_DLL") && EnableOutput();
+MOC = #$ Expand("TMAKE_MOC");
+
+ZIP = #$ Expand("TMAKE_ZIP");
+
+####### Files
+
+HEADERS = #$ ExpandList("HEADERS");
+SOURCES = #$ ExpandList("SOURCES");
+OBJECTS = #$ ExpandList("OBJECTS");
+SRCMOC = #$ ExpandList("SRCMOC");
+OBJMOC = #$ ExpandList("OBJMOC");
+DIST = #$ ExpandList("DISTFILES");
+TARGET = #$ ExpandGlue("TARGET",$project{"DESTDIR"},"",$project{"TARGET_EXT"});
+
+####### Implicit rules
+
+.SUFFIXES: .cpp .cxx .cc .c
+
+.cpp.o:
+ #$ Expand("TMAKE_COMPILE_IMP");
+
+.cxx.o:
+ #$ Expand("TMAKE_COMPILE_IMP");
+
+.cc.o:
+ #$ Expand("TMAKE_COMPILE_IMP");
+
+.c.o:
+ #$ Expand("TMAKE_COMPILE_IMP");
+
+####### Build rules
+
+all: #$ ExpandGlue("ALL_DEPS",""," "," "); $text .= '$(TARGET)';
+
+$(TARGET): $(OBJECTS) $(OBJMOC) #$ Expand("TARGETDEPS");
+#$ Project("TMAKE_APP_OR_DLL") || DisableOutput();
+ $(LINK) $(LFLAGS) -o $(TARGET) $(OBJECTS) $(OBJMOC) $(LIBS)
+#$ Project("TMAKE_APP_OR_DLL") || EnableOutput();
+#$ Project("TMAKE_APP_OR_DLL") && DisableOutput();
+ -rm -f $(TARGET)
+ $(AR) $(TARGET) $(OBJECTS) $(OBJMOC)
+ #$ ExpandGlue("TMAKE_RANLIB","",""," \$(TARGET)");
+#$ Project("TMAKE_APP_OR_DLL") && EnableOutput();
+#$ (Config("dll") && Project("DLLDESTDIR")) || DisableOutput();
+ -cp $(TARGET) #$ Expand("DLLDESTDIR");
+#$ (Config("dll") && Project("DLLDESTDIR")) || EnableOutput();
+#$ Project('RC_FILE') || DisableOutput();
+
+#$ Substitute("\$\$RES_FILE: \$\$RC_FILE\n\t\$\$TMAKE_RC \$\$RC_FILE");
+#$ Project('RC_FILE') || EnableOutput();
+
+moc: $(SRCMOC)
+
+#$ TmakeSelf();
+
+dist:
+ #$ Substitute('$(ZIP) $$PROJECT.zip $$PROJECT.pro $(SOURCES) $(HEADERS) $(DIST)');
+
+clean:
+ -rm -f $(OBJECTS) $(OBJMOC) $(SRCMOC) $(TARGET)
+ #$ ExpandGlue("TMAKE_CLEAN","-rm -f "," ","");
+ -rm -f *~ core
+ #$ ExpandGlue("CLEAN_FILES","-rm -f "," ","");
+
+####### Compile
+
+#$ BuildObj(Project("OBJECTS"),Project("SOURCES"));
+#$ BuildMocObj(Project("OBJMOC"),Project("SRCMOC"));
+#$ BuildMocSrc(Project("HEADERS"));
+#$ BuildMocSrc(Project("SOURCES"));
diff --git a/tmake/lib/win32-g++/lib.t b/tmake/lib/win32-g++/lib.t
new file mode 100755
index 0000000..d8ac6c7
--- /dev/null
+++ b/tmake/lib/win32-g++/lib.t
@@ -0,0 +1,6 @@
+#############################################################################
+#!
+#! This is a tmake template for building Win32 libraries.
+#!
+#$ Project('TMAKE_LIB_FLAG = 1');
+#$ IncludeTemplate("generic.t");
diff --git a/tmake/lib/win32-g++/subdirs.t b/tmake/lib/win32-g++/subdirs.t
new file mode 100755
index 0000000..8b881ab
--- /dev/null
+++ b/tmake/lib/win32-g++/subdirs.t
@@ -0,0 +1,2 @@
+#! Use the common Win32 template
+#$ IncludeTemplate("../win32/subdirs.t");
diff --git a/tmake/lib/win32-g++/tmake.conf b/tmake/lib/win32-g++/tmake.conf
new file mode 100755
index 0000000..59667bd
--- /dev/null
+++ b/tmake/lib/win32-g++/tmake.conf
@@ -0,0 +1,56 @@
+#
+# $Id$
+#
+# tmake configuration for Win32/g++ (Cygnus gnu-win32)
+#
+
+TEMPLATE = app
+CONFIG = qt warn_on release
+
+TMAKE_CC = g++
+TMAKE_CFLAGS =
+TMAKE_CFLAGS_WARN_ON =
+TMAKE_CFLAGS_WARN_OFF =
+TMAKE_CFLAGS_RELEASE = -O
+TMAKE_CFLAGS_DEBUG = -g
+TMAKE_CFLAGS_YACC = -Wno-unused -Wno-parentheses
+
+TMAKE_CXX = $$TMAKE_CC
+TMAKE_CXXFLAGS = $$TMAKE_CFLAGS
+TMAKE_CXXFLAGS_WARN_ON = $$TMAKE_CFLAGS_WARN_ON
+TMAKE_CXXFLAGS_WARN_OFF = $$TMAKE_CFLAGS_WARN_OFF
+TMAKE_CXXFLAGS_RELEASE = $$TMAKE_CFLAGS_RELEASE
+TMAKE_CXXFLAGS_DEBUG = $$TMAKE_CFLAGS_DEBUG
+TMAKE_CXXFLAGS_YACC = $$TMAKE_CFLAGS_YACC
+
+TMAKE_INCDIR =
+TMAKE_INCDIR_QT = $(QTDIR)/include
+
+TMAKE_RUN_CC = $(CC) -c $(CFLAGS) $(INCPATH) -o $obj $src
+TMAKE_RUN_CC_IMP = $(CC) -c $(CFLAGS) $(INCPATH) -o $@ $<
+TMAKE_RUN_CXX = $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $obj $src
+TMAKE_RUN_CXX_IMP = $(CXX) -c $(CXXFLAGS) $(INCPATH) -o $@ $<
+
+TMAKE_LINK = g++
+TMAKE_LFLAGS =
+TMAKE_LFLAGS_RELEASE =
+TMAKE_LFLAGS_DEBUG =
+TMAKE_LFLAGS_CONSOLE = -Wl,-subsystem,console
+TMAKE_LFLAGS_WINDOWS = -Wl,-subsystem,windows
+TMAKE_LFLAGS_CONSOLE_DLL= -Wl,-subsystem,console
+TMAKE_LFLAGS_WINDOWS_DLL= -Wl,-subsystem,windows
+
+TMAKE_LIBS =
+TMAKE_LIBS_CONSOLE =
+TMAKE_LIBS_WINDOWS = -luser32 -lgdi32 -lcomdlg32 -lole32 -luuid -lwsock32
+TMAKE_LIBS_QT = -L$(QTDIR)/lib -lqt
+TMAKE_LIBS_QT_DLL = -lqtmain
+TMAKE_LIBS_QT_OPENGL = -lqgl
+TMAKE_LIBS_OPENGL = -lopengl32
+
+TMAKE_MOC = moc
+
+TMAKE_AR = ar cqs
+TMAKE_RANLIB =
+
+TMAKE_ZIP = zip -r -9
diff --git a/tmake/lib/win32-msvc/app.t b/tmake/lib/win32-msvc/app.t
new file mode 100755
index 0000000..fc4dc2c
--- /dev/null
+++ b/tmake/lib/win32-msvc/app.t
@@ -0,0 +1,6 @@
+#############################################################################
+#!
+#! This is a tmake template for building Win32 applications.
+#!
+#$ Project('TMAKE_APP_FLAG = 1');
+#$ IncludeTemplate("generic.t");
diff --git a/tmake/lib/win32-msvc/generic.t b/tmake/lib/win32-msvc/generic.t
new file mode 100755
index 0000000..e57180d
--- /dev/null
+++ b/tmake/lib/win32-msvc/generic.t
@@ -0,0 +1,221 @@
+#!
+#! This is a tmake template for building Win32 applications or libraries.
+#!
+#${
+ if ( Config("qt") ) {
+ if ( !(Project("DEFINES") =~ /QT_NODLL/) &&
+ ((Project("DEFINES") =~ /QT_(?:MAKE)?DLL/) ||
+ ($ENV{"QT_DLL"} && !$ENV{"QT_NODLL"})) ) {
+ Project('TMAKE_QT_DLL = 1');
+ if ( (Project("TARGET") eq "qt") && Project("TMAKE_LIB_FLAG") ) {
+ Project('CONFIG += dll');
+ }
+ }
+ }
+ if ( Config("dll") || Project("TMAKE_APP_FLAG") ) {
+ Project('CONFIG -= staticlib');
+ Project('TMAKE_APP_OR_DLL = 1');
+ } else {
+ Project('CONFIG += staticlib');
+ }
+ if ( Config("warn_off") ) {
+ Project('TMAKE_CFLAGS += $$TMAKE_CFLAGS_WARN_OFF');
+ Project('TMAKE_CXXFLAGS += $$TMAKE_CXXFLAGS_WARN_OFF');
+ } elsif ( Config("warn_on") ) {
+ Project('TMAKE_CFLAGS += $$TMAKE_CFLAGS_WARN_ON');
+ Project('TMAKE_CXXFLAGS += $$TMAKE_CXXFLAGS_WARN_ON');
+ }
+ if ( Config("debug") ) {
+ Project('TMAKE_CFLAGS += $$TMAKE_CFLAGS_DEBUG');
+ Project('TMAKE_CXXFLAGS += $$TMAKE_CXXFLAGS_DEBUG');
+ Project('TMAKE_LFLAGS += $$TMAKE_LFLAGS_DEBUG');
+ } elsif ( Config("release") ) {
+ Project('TMAKE_CFLAGS += $$TMAKE_CFLAGS_RELEASE');
+ Project('TMAKE_CXXFLAGS += $$TMAKE_CXXFLAGS_RELEASE');
+ Project('TMAKE_LFLAGS += $$TMAKE_LFLAGS_RELEASE');
+ }
+ if ( Config("qt") || Config("opengl") ) {
+ Project('CONFIG += windows' );
+ }
+ if ( Config("qt") ) {
+ $moc_aware = 1;
+ AddIncludePath(Project("TMAKE_INCDIR_QT"));
+ if ( Config("opengl") ) {
+ Project('TMAKE_LIBS *= $$TMAKE_LIBS_QT_OPENGL');
+ }
+ if ( (Project("TARGET") eq "qt") && Project("TMAKE_LIB_FLAG") ) {
+ if ( Project("TMAKE_QT_DLL") ) {
+ Project('DEFINES -= QT_DLL');
+ Project('DEFINES *= QT_MAKEDLL');
+ }
+ } else {
+ if ( Project("TMAKE_QT_DLL") ) {
+ Project('DEFINES *= QT_DLL');
+ }
+ Project('TMAKE_LIBS *= $$TMAKE_LIBS_QT');
+ if ( Project("TMAKE_QT_DLL") ) {
+ my $qtver =FindHighestLibVersion($ENV{"QTDIR"} . "/lib", "qt");
+ Project("TMAKE_LIBS /= s/qt.lib/qt${qtver}.lib/");
+ Project('TMAKE_LIBS *= $$TMAKE_LIBS_QT_DLL');
+ }
+ }
+ }
+ if ( Config("opengl") ) {
+ Project('TMAKE_LIBS *= $$TMAKE_LIBS_OPENGL');
+ }
+ if ( Config("dll") ) {
+ Project('TMAKE_LFLAGS_CONSOLE_ANY = $$TMAKE_LFLAGS_CONSOLE_DLL');
+ Project('TMAKE_LFLAGS_WINDOWS_ANY = $$TMAKE_LFLAGS_WINDOWS_DLL');
+ if ( Project("TMAKE_LIB_FLAG") ) {
+ my $ver = Project("VERSION");
+ $ver =~ s/\.//g;
+ $project{"TARGET_EXT"} = "${ver}.dll";
+ } else {
+ $project{"TARGET_EXT"} = ".dll";
+ }
+ } else {
+ Project('TMAKE_LFLAGS_CONSOLE_ANY = $$TMAKE_LFLAGS_CONSOLE');
+ Project('TMAKE_LFLAGS_WINDOWS_ANY = $$TMAKE_LFLAGS_WINDOWS');
+ if ( Project("TMAKE_APP_FLAG") ) {
+ $project{"TARGET_EXT"} = ".exe";
+ } else {
+ $project{"TARGET_EXT"} = ".lib";
+ }
+ }
+ if ( Config("windows") ) {
+ if ( Config("console") ) {
+ Project('TMAKE_LFLAGS *= $$TMAKE_LFLAGS_CONSOLE_ANY');
+ Project('TMAKE_LIBS *= $$TMAKE_LIBS_CONSOLE');
+ } else {
+ Project('TMAKE_LFLAGS *= $$TMAKE_LFLAGS_WINDOWS_ANY');
+ }
+ Project('TMAKE_LIBS *= $$TMAKE_LIBS_WINDOWS');
+ } else {
+ Project('TMAKE_LFLAGS *= $$TMAKE_LFLAGS_CONSOLE_ANY');
+ Project('TMAKE_LIBS *= $$TMAKE_LIBS_CONSOLE');
+ }
+ Project('TMAKE_LIBS += $$LIBS');
+ Project('TMAKE_FILETAGS = HEADERS SOURCES DEF_FILE RC_FILE TARGET TMAKE_LIBS DESTDIR DLLDESTDIR $$FILETAGS');
+ foreach ( split(/\s/,Project("TMAKE_FILETAGS")) ) {
+ $project{$_} =~ s-[/\\]+-\\-g;
+ }
+ if ( Project("DEF_FILE") ) {
+ Project('TMAKE_LFLAGS *= /DEF:$$DEF_FILE');
+ }
+ if ( Project("RC_FILE") ) {
+ if ( Project("RES_FILE") ) {
+ tmake_error("Both .rc and .res file specified.\n" .
+ "Please specify one of them, not both.");
+ }
+ $project{"RES_FILE"} = $project{"RC_FILE"};
+ $project{"RES_FILE"} =~ s/\.rc$/.res/i;
+ Project('TARGETDEPS += $$RES_FILE');
+ }
+ if ( Project("RES_FILE") ) {
+ Project('TMAKE_LIBS *= $$RES_FILE');
+ }
+ StdInit();
+ $project{"DESTDIR"} = FixPath($project{"DESTDIR"});
+ if ( Project("VERSION") ) {
+ $project{"VER_MAJ"} = $project{"VERSION"};
+ $project{"VER_MAJ"} =~ s/\.\d+$//;
+ $project{"VER_MIN"} = $project{"VERSION"};
+ $project{"VER_MIN"} =~ s/^\d+\.//;
+ }
+ Project('debug:TMAKE_CLEAN += $$TARGET.pdb vc*.pdb $$TARGET.ilk');
+#$}
+#!
+# Makefile for building #$ Expand("TARGET")
+# Generated by tmake at #$ Now();
+# Project: #$ Expand("PROJECT");
+# Template: #$ Expand("TEMPLATE");
+#############################################################################
+
+####### Compiler, tools and options
+
+CC = #$ Expand("TMAKE_CC");
+CXX = #$ Expand("TMAKE_CXX");
+CFLAGS = #$ Expand("TMAKE_CFLAGS"); ExpandGlue("DEFINES","-D"," -D","");
+CXXFLAGS= #$ Expand("TMAKE_CXXFLAGS"); ExpandGlue("DEFINES","-D"," -D","");
+INCPATH = #$ ExpandGlue("INCPATH",'-I"','" -I"','"');
+#$ !Project("TMAKE_APP_OR_DLL") && DisableOutput();
+LINK = #$ Expand("TMAKE_LINK");
+LFLAGS = #$ Expand("TMAKE_LFLAGS");
+LIBS = #$ Expand("TMAKE_LIBS");
+#$ !Project("TMAKE_APP_OR_DLL") && EnableOutput();
+#$ Project("TMAKE_APP_OR_DLL") && DisableOutput();
+LIB = #$ Expand("TMAKE_LIB");
+#$ Project("TMAKE_APP_OR_DLL") && EnableOutput();
+MOC = #$ Expand("TMAKE_MOC");
+
+ZIP = #$ Expand("TMAKE_ZIP");
+
+####### Files
+
+HEADERS = #$ ExpandList("HEADERS");
+SOURCES = #$ ExpandList("SOURCES");
+OBJECTS = #$ ExpandList("OBJECTS");
+SRCMOC = #$ ExpandList("SRCMOC");
+OBJMOC = #$ ExpandList("OBJMOC");
+DIST = #$ ExpandList("DISTFILES");
+TARGET = #$ ExpandGlue("TARGET",$project{"DESTDIR"},"",$project{"TARGET_EXT"});
+
+####### Implicit rules
+
+.SUFFIXES: .cpp .cxx .cc .c
+
+.cpp.obj:
+ #$ Expand("TMAKE_RUN_CXX_IMP");
+
+.cxx.obj:
+ #$ Expand("TMAKE_RUN_CXX_IMP");
+
+.cc.obj:
+ #$ Expand("TMAKE_RUN_CXX_IMP");
+
+.c.obj:
+ #$ Expand("TMAKE_RUN_CC_IMP");
+
+####### Build rules
+
+all: #$ ExpandGlue("ALL_DEPS",""," "," "); $text .= '$(TARGET)';
+
+$(TARGET): $(OBJECTS) $(OBJMOC) #$ Expand("TARGETDEPS");
+#$ Project("TMAKE_APP_OR_DLL") || DisableOutput();
+ $(LINK) $(LFLAGS) /OUT:$(TARGET) @<<
+ $(OBJECTS) $(OBJMOC) $(LIBS)
+#$ Project("TMAKE_APP_OR_DLL") || EnableOutput();
+#$ Project("TMAKE_APP_OR_DLL") && DisableOutput();
+ $(LIB) /OUT:$(TARGET) @<<
+ $(OBJECTS) $(OBJMOC)
+#$ Project("TMAKE_APP_OR_DLL") && EnableOutput();
+<<
+#$ (Config("dll") && Project("DLLDESTDIR")) || DisableOutput();
+ -copy $(TARGET) #$ Expand("DLLDESTDIR");
+#$ (Config("dll") && Project("DLLDESTDIR")) || EnableOutput();
+#$ Project("RC_FILE") || DisableOutput();
+
+#$ Substitute("\$\$RES_FILE: \$\$RC_FILE\n\t\$\$TMAKE_RC \$\$RC_FILE");
+#$ Project("RC_FILE") || EnableOutput();
+
+moc: $(SRCMOC)
+
+#$ TmakeSelf();
+
+dist:
+ #$ Substitute('$(ZIP) $$PROJECT.zip $$PROJECT.pro $(SOURCES) $(HEADERS) $(DIST)');
+
+clean:
+ #$ ExpandGlue("OBJECTS","-del ","\n\t-del ","");
+ #$ ExpandGlue("SRCMOC" ,"-del ","\n\t-del ","");
+ #$ ExpandGlue("OBJMOC" ,"-del ","\n\t-del ","");
+ -del $(TARGET)
+ #$ ExpandGlue("TMAKE_CLEAN","-del ","\n\t-del ","");
+ #$ ExpandGlue("CLEAN_FILES","-del ","\n\t-del ","");
+
+####### Compile
+
+#$ BuildObj(Project("OBJECTS"),Project("SOURCES"));
+#$ BuildMocObj(Project("OBJMOC"),Project("SRCMOC"));
+#$ BuildMocSrc(Project("HEADERS"));
+#$ BuildMocSrc(Project("SOURCES"));
diff --git a/tmake/lib/win32-msvc/lib.t b/tmake/lib/win32-msvc/lib.t
new file mode 100755
index 0000000..d8ac6c7
--- /dev/null
+++ b/tmake/lib/win32-msvc/lib.t
@@ -0,0 +1,6 @@
+#############################################################################
+#!
+#! This is a tmake template for building Win32 libraries.
+#!
+#$ Project('TMAKE_LIB_FLAG = 1');
+#$ IncludeTemplate("generic.t");
diff --git a/tmake/lib/win32-msvc/subdirs.t b/tmake/lib/win32-msvc/subdirs.t
new file mode 100755
index 0000000..8b881ab
--- /dev/null
+++ b/tmake/lib/win32-msvc/subdirs.t
@@ -0,0 +1,2 @@
+#! Use the common Win32 template
+#$ IncludeTemplate("../win32/subdirs.t");
diff --git a/tmake/lib/win32-msvc/tmake.conf b/tmake/lib/win32-msvc/tmake.conf
new file mode 100755
index 0000000..cb64ac9
--- /dev/null
+++ b/tmake/lib/win32-msvc/tmake.conf
@@ -0,0 +1,64 @@
+#
+# $Id$
+#
+# tmake configuration for Win32/Microsoft C++
+#
+
+TEMPLATE = app
+CONFIG = qt warn_on release
+
+TMAKE_CC = cl
+TMAKE_CFLAGS = -nologo
+TMAKE_CFLAGS_WARN_ON = -W3
+TMAKE_CFLAGS_WARN_OFF = -W0
+TMAKE_CFLAGS_RELEASE = -O2
+TMAKE_CFLAGS_DEBUG = -Zi
+TMAKE_CFLAGS_MT = -MT
+TMAKE_CFLAGS_MT_DBG = -MTd
+TMAKE_CFLAGS_MT_DLL = -MD
+TMAKE_CFLAGS_MT_DLLDBG = -MDd
+TMAKE_CFLAGS_YACC =
+
+TMAKE_CXX = $$TMAKE_CC
+TMAKE_CXXFLAGS = $$TMAKE_CFLAGS
+TMAKE_CXXFLAGS_WARN_ON = $$TMAKE_CFLAGS_WARN_ON
+TMAKE_CXXFLAGS_WARN_OFF = $$TMAKE_CFLAGS_WARN_OFF
+TMAKE_CXXFLAGS_RELEASE = $$TMAKE_CFLAGS_RELEASE
+TMAKE_CXXFLAGS_DEBUG = $$TMAKE_CFLAGS_DEBUG
+TMAKE_CXXFLAGS_MT = $$TMAKE_CFLAGS_MT
+TMAKE_CXXFLAGS_MT_DBG = $$TMAKE_CFLAGS_MT_DBG
+TMAKE_CXXFLAGS_MT_DLL = $$TMAKE_CFLAGS_MT_DLL
+TMAKE_CXXFLAGS_MT_DLLDBG= $$TMAKE_CFLAGS_MT_DLLDBG
+TMAKE_CXXFLAGS_YACC = $$TMAKE_CFLAGS_YACC
+
+TMAKE_INCDIR =
+TMAKE_INCDIR_QT = $(QTDIR)\include
+
+TMAKE_RUN_CC = $(CC) -c $(CFLAGS) $(INCPATH) -Fo$obj $src
+TMAKE_RUN_CC_IMP = $(CC) -c $(CFLAGS) $(INCPATH) -Fo$@ $<
+TMAKE_RUN_CXX = $(CXX) -c $(CXXFLAGS) $(INCPATH) -Fo$obj $src
+TMAKE_RUN_CXX_IMP = $(CXX) -c $(CXXFLAGS) $(INCPATH) -Fo$@ $<
+
+TMAKE_LINK = link
+TMAKE_LFLAGS = /NOLOGO
+TMAKE_LFLAGS_RELEASE =
+TMAKE_LFLAGS_DEBUG = /DEBUG
+TMAKE_LFLAGS_CONSOLE = /SUBSYSTEM:console
+TMAKE_LFLAGS_WINDOWS = /SUBSYSTEM:windows
+TMAKE_LFLAGS_CONSOLE_DLL= /SUBSYSTEM:console /DLL
+TMAKE_LFLAGS_WINDOWS_DLL= /SUBSYSTEM:windows /DLL
+
+TMAKE_LIBS =
+TMAKE_LIBS_CONSOLE =
+TMAKE_LIBS_WINDOWS = user32.lib gdi32.lib comdlg32.lib ole32.lib uuid.lib wsock32.lib
+TMAKE_LIBS_QT = $(QTDIR)\lib\qt.lib
+TMAKE_LIBS_QT_DLL = $(QTDIR)\lib\qtmain.lib
+TMAKE_LIBS_QT_OPENGL = $(QTDIR)\lib\qgl.lib
+TMAKE_LIBS_OPENGL = opengl32.lib glu32.lib
+
+TMAKE_MOC = moc
+
+TMAKE_LIB = lib /NOLOGO
+TMAKE_RC = rc
+
+TMAKE_ZIP = zip -r -9
diff --git a/tmake/lib/win32-msvc/vcapp.t b/tmake/lib/win32-msvc/vcapp.t
new file mode 100755
index 0000000..02e15e4
--- /dev/null
+++ b/tmake/lib/win32-msvc/vcapp.t
@@ -0,0 +1,226 @@
+#!
+#! This TMAKE template - Microsoft Visual C++ 5.0 applications
+#!
+#${
+ if ( Config("qt") || Config("opengl") ) {
+ Project('CONFIG += windows');
+ }
+ if ( Config("qt") ) {
+ $moc_aware = 1;
+ AddIncludePath(Project('TMAKE_INCDIR_QT'));
+ if ( Config("opengl") ) {
+ Project('TMAKE_LIBS *= $$TMAKE_LIBS_QT_OPENGL');
+ }
+ Project('TMAKE_LIBS *= $$TMAKE_LIBS_QT');
+ }
+ if ( Config("opengl") ) {
+ Project('TMAKE_LIBS *= $$TMAKE_LIBS_OPENGL');
+ }
+ Project('TMAKE_LIBS += $$LIBS');
+
+ if ( Config("windows") ) {
+ $project{"VC_PROJ_TYPE"} = 'Win32 (x86) Application';
+ $project{"VC_PROJ_CODE"} = '0x0101';
+ $vc_base_libs = 'kernel32.lib user32.lib gdi32.lib winspool.lib ' .
+ 'comdlg32.lib advapi32.lib shell32.lib ole32.lib ' .
+ 'oleaut32.lib uuid.lib odbc32.lib odbccp32.lib ';
+ $vc_libs = $vc_base_libs . 'wsock32.lib ';
+ $vc_link_release = '/nologo /subsystem:windows /machine:I386';
+ $vc_link_debug = '/nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept';
+ $vc_cpp_def_release = '/D "NDEBUG" /D "WIN32" /D "_WINDOWS" ';
+ $vc_cpp_def_debug = '/D "_DEBUG" /D "WIN32" /D "_WINDOWS" ';
+ } else {
+ $project{"VC_PROJ_TYPE"} = 'Win32 (x86) Console Application';
+ $project{"VC_PROJ_CODE"} = '0x0103';
+ $vc_base_libs = 'kernel32.lib user32.lib gdi32.lib winspool.lib ' .
+ 'comdlg32.lib advapi32.lib shell32.lib ole32.lib ' .
+ 'oleaut32.lib uuid.lib odbc32.lib odbccp32.lib ';
+ $vc_libs = $vc_base_libs;
+ $vc_link_release = '/nologo /subsystem:console /machine:I386';
+ $vc_link_debug = '/nologo /subsystem:console /debug /machine:I386 /pdbtype:sept';
+ $vc_cpp_def_release = '/D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" ';
+ $vc_cpp_def_debug = '/D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "_MBCS" ';
+ }
+ $project{"VC_BASE_LINK_RELEASE"} = $vc_base_libs . $vc_link_release;
+ $project{"VC_BASE_LINK_DEBUG"} = $vc_base_libs . $vc_link_debug;
+ $tmake_libs = Project('TMAKE_LIBS') ? (Project('TMAKE_LIBS') . " ") : "";
+ $project{"VC_LINK_RELEASE"} = $vc_libs . $tmake_libs . $vc_link_release;
+ $project{"VC_LINK_DEBUG"} = $vc_libs . $tmake_libs . $vc_link_debug;
+
+ $vc_cpp_opt_release = '/nologo /W3 /GX /O2 ';
+ $vc_cpp_opt_debug = '/nologo /W3 /Gm /GX /Zi /Od ';
+ $vc_cpp_opt_common = '/YX /FD /c';
+ $project{"VC_BASE_CPP_RELEASE"} = $vc_cpp_opt_release . $vc_cpp_def_release . $vc_cpp_opt_common;
+ $project{"VC_BASE_CPP_DEBUG"} = $vc_cpp_opt_debug . $vc_cpp_def_debug . $vc_cpp_opt_common;
+ ExpandGlue("INCPATH",'/I "','" /I "','"');
+ if ( $text ne "" ) { $vc_inc = $text . " "; $text = ""; } else { $vc_inc = ""; }
+ ExpandGlue("DEFINES",'/D "','" /D "','"');
+ if ( $text ne "" ) { $vc_def = $text . " "; $text = ""; } else { $vc_def = ""; }
+ $project{"VC_CPP_RELEASE"} = $vc_cpp_opt_release . $vc_inc . $vc_cpp_def_release . $vc_def . $vc_cpp_opt_common;
+ $project{"VC_CPP_DEBUG"} = $vc_cpp_opt_debug . $vc_inc . $vc_cpp_def_debug . $vc_def . $vc_cpp_opt_common;
+
+ $project{"MAKEFILE"} = $project{"PROJECT"} . ".mak";
+ $project{"TARGETAPP"} = $project{"TARGET"} . ".exe";
+ Project('TMAKE_FILETAGS = HEADERS SOURCES TARGET DESTDIR $$FILETAGS');
+ foreach ( split(/\s/,Project('TMAKE_FILETAGS')) ) {
+ $project{$_} =~ s-/-\\-g;
+ }
+ StdInit();
+ if ( defined($project{"DESTDIR"}) ) {
+ $project{"TARGETAPP"} = $project{"DESTDIR"} . "\\" . $project{"TARGETAPP"};
+ $project{"TARGETAPP"} =~ s/\\+/\\/g;
+ }
+ %all_files = ();
+ @files = split(/\s+/,$project{"HEADERS"});
+ foreach ( @files ) { $all_files{$_} = "h" };
+ @files = split(/\s+/,$project{"SOURCES"});
+ foreach ( @files ) { $all_files{$_} = "s" };
+ if ( $moc_aware ) {
+ @files = split(/\s+/,$project{"_HDRMOC"});
+ foreach ( @files ) { $all_files{$_} = "m"; }
+ @files = split(/\s+/,$project{"_SRCMOC"});
+ foreach ( @files ) { $all_files{$_} = "i"; }
+ }
+ %file_names = ();
+ foreach $f ( %all_files ) {
+ $n = $f;
+ $n =~ s/^.*\\//;
+ $file_names{$n} = $f;
+ $file_path{$n} = ".\\" . $f;
+ $file_path2{$n} = (($f =~ /^\./) ? "" : ".\\") . $f;
+ }
+#$}
+# Microsoft Developer Studio Project File - #$ Substitute('Name="$$TARGET" - Package Owner=<4>');
+# Microsoft Developer Studio Generated Build File, Format Version 5.00
+# ** DO NOT EDIT **
+
+# TARGTYPE #$ Substitute('"$$VC_PROJ_TYPE" $$VC_PROJ_CODE');
+
+CFG=#$ Substitute('$$TARGET - Win32 Debug');
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "#$ ExpandGlue('MAKEFILE','','','".');
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f #$ Substitute('"$$MAKEFILE" CFG="$$TARGET - Win32 Debug"');
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE #$ Substitute('"$$TARGET - Win32 Release" (based on "$$VC_PROJ_TYPE")');
+!MESSAGE #$ Substitute('"$$TARGET - Win32 Debug" (based on "$$VC_PROJ_TYPE")');
+!MESSAGE
+
+# Begin Project
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+#$ Config("windows") && ($text='MTL=midl.exe');
+RSC=rc.exe
+
+!IF "$(CFG)" == #$ Substitute('"$$TARGET - Win32 Release"');
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+#$ Config("windows") && ($text='# PROP Ignore_Export_Lib 0');
+# PROP Target_Dir ""
+# ADD BASE CPP #$ Expand("VC_BASE_CPP_RELEASE");
+# ADD CPP #$ Expand("VC_CPP_RELEASE");
+#$ Config("windows") || DisableOutput();
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o NUL /win32
+#$ Config("windows") || EnableOutput();
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 #$ Expand("VC_BASE_LINK_RELEASE");
+# ADD LINK32 #$ Expand("VC_LINK_RELEASE");
+
+!ELSEIF "$(CFG)" == #$ Substitute('"$$TARGET - Win32 Debug"');
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+#$ Config("windows") && ($text='# PROP Ignore_Export_Lib 0');
+# PROP Target_Dir ""
+# ADD BASE CPP #$ Expand("VC_BASE_CPP_DEBUG");
+# ADD CPP #$ Expand("VC_CPP_DEBUG");
+#$ Config("windows") || DisableOutput();
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o NUL /win32
+#$ Config("windows") || EnableOutput();
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 #$ Expand("VC_BASE_LINK_DEBUG");
+# ADD LINK32 #$ Expand("VC_LINK_DEBUG");
+
+!ENDIF
+
+# Begin Target
+
+# Name #$Substitute('"$$TARGET - Win32 Release"');
+# Name #$Substitute('"$$TARGET - Win32 Debug"');
+#${
+ foreach $n ( sort keys %file_names ) {
+ $f = $file_names{$n};
+ $p = $file_path{$n};
+ $p2 = $file_path2{$n};
+ $t = $all_files{$f};
+ if ( ($t eq "h") && $moc_output{$f} ) {
+ my($build);
+ $build = "\n\n# Begin Custom Build - Running moc...\nInputPath=" . $p2 . "\n\n"
+ . '"' . $moc_output{$f} . '" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"'
+ . "\n\tmoc $p2 -o " . $moc_output{$f} . "\n\n"
+ . "# End Custom Build\n\n";
+ $text .= ("# Begin Source File\n\nSOURCE=$p\n\n"
+ . '!IF "$(CFG)" == "' . $project{"TARGET"} . ' - Win32 Release"'
+ . $build);
+ $text .= ('!ELSEIF "$(CFG)" == "' . $project{"TARGET"} . ' - Win32 Debug"'
+ . $build
+ . "!ENDIF \n\n# End Source File\n");
+ } elsif ( $t eq "i" ) {
+ my($build,$dn);
+ $build = "\n\n# Begin Custom Build - Running moc...\nInputPath=" . $p2 . "\n\n"
+ . '"' . $f . '" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"'
+ . "\n\tmoc ". $moc_input{$f} . " -o $f\n\n"
+ . "# End Custom Build\n\n";
+ $dn = $n;
+ $dn =~ s/\..*//;
+ $dn =~ tr/a-z/A-Z/;
+ $text .= ("# Begin Source File\n\nSOURCE=$p\n"
+ . "USERDEP__$dn=" . '"' . $moc_input{$f} . '"' . "\n\n"
+ . '!IF "$(CFG)" == "' . $project{"TARGET"} . ' - Win32 Release"'
+ . $build);
+ $text .= ('!ELSEIF "$(CFG)" == "' . $project{"TARGET"} . ' - Win32 Debug"'
+ . $build
+ . "!ENDIF \n\n# End Source File\n");
+ } elsif ( $t eq "s" || $t eq "m" || $t eq "h" ) {
+ $text .= "# Begin Source File\n\nSOURCE=$p\n# End Source File\n";
+ }
+ }
+ chop $text;
+#$}
+# End Target
+# End Project
diff --git a/tmake/lib/win32-msvc/vclib.t b/tmake/lib/win32-msvc/vclib.t
new file mode 100755
index 0000000..e56409e
--- /dev/null
+++ b/tmake/lib/win32-msvc/vclib.t
@@ -0,0 +1,178 @@
+#!
+#! This TMAKE template - Microsoft Visual C++ 5.0 libraries
+#!
+#${
+ if ( Config("qt") || Config("opengl") ) {
+ Project('CONFIG += windows');
+ }
+ if ( Config("qt") ) {
+ $moc_aware = 1;
+ AddIncludePath(Project('TMAKE_INCDIR_QT'));
+ }
+
+ $project{"VC_PROJ_TYPE"} = 'Win32 (x86) Static Library';
+ $project{"VC_PROJ_CODE"} = '0x0104';
+
+ $vc_cpp_def_release = '/D "NDEBUG" /D "WIN32" /D "_WINDOWS" ';
+ $vc_cpp_def_debug = '/D "_DEBUG" /D "WIN32" /D "_WINDOWS" ';
+ $vc_cpp_opt_release = '/nologo /W3 /GX /O2 ';
+ $vc_cpp_opt_debug = '/nologo /W3 /Gm /GX /Zi /Od ';
+ $vc_cpp_opt_common = '/YX /FD /c';
+ $project{"VC_BASE_CPP_RELEASE"} = $vc_cpp_opt_release . $vc_cpp_def_release . $vc_cpp_opt_common;
+ $project{"VC_BASE_CPP_DEBUG"} = $vc_cpp_opt_debug . $vc_cpp_def_debug . $vc_cpp_opt_common;
+ ExpandGlue("INCPATH",'/I "','" /I "','"');
+ if ( $text ne "" ) { $vc_inc = $text . " "; $text = ""; } else { $vc_inc = ""; }
+ ExpandGlue("DEFINES",'/D "','" /D "','"');
+ if ( $text ne "" ) { $vc_def = $text . " "; $text = ""; } else { $vc_def = ""; }
+ $project{"VC_CPP_RELEASE"} = $vc_cpp_opt_release . $vc_inc . $vc_cpp_def_release . $vc_def . $vc_cpp_opt_common;
+ $project{"VC_CPP_DEBUG"} = $vc_cpp_opt_debug . $vc_inc . $vc_cpp_def_debug . $vc_def . $vc_cpp_opt_common;
+
+ $project{"MAKEFILE"} = $project{"PROJECT"} . ".mak";
+ $project{"TARGETLIB"} = $project{"TARGET"} . ".lib";
+ Project('TMAKE_FILETAGS = HEADERS SOURCES TARGET DESTDIR $$FILETAGS');
+ foreach ( split(/\s/,Project('TMAKE_FILETAGS')) ) {
+ $project{$_} =~ s-/-\\-g;
+ }
+ StdInit();
+ if ( defined($project{"DESTDIR"}) ) {
+ $project{"TARGETLIB"} = $project{"DESTDIR"} . "\\" . $project{"TARGETLIB"};
+ $project{"TARGETLIB"} =~ s/\\+/\\/g;
+ }
+ %all_files = ();
+ @files = split(/\s+/,$project{"HEADERS"});
+ foreach ( @files ) { $all_files{$_} = "h" };
+ @files = split(/\s+/,$project{"SOURCES"});
+ foreach ( @files ) { $all_files{$_} = "s" };
+ if ( $moc_aware ) {
+ @files = split(/\s+/,$project{"_HDRMOC"});
+ foreach ( @files ) { $all_files{$_} = "m"; }
+ @files = split(/\s+/,$project{"_SRCMOC"});
+ foreach ( @files ) { $all_files{$_} = "i"; }
+ }
+ %file_names = ();
+ foreach $f ( %all_files ) {
+ $n = $f;
+ $n =~ s/^.*\\//;
+ $file_names{$n} = $f;
+ $file_path{$n} = ".\\" . $f;
+ $file_path2{$n} = (($f =~ /^\./) ? "" : ".\\") . $f;
+ }
+#$}
+# Microsoft Developer Studio Project File - #$ Substitute('Name="$$TARGET" - Package Owner=<4>');
+# Microsoft Developer Studio Generated Build File, Format Version 5.00
+# ** DO NOT EDIT **
+
+# TARGTYPE #$ Substitute('"$$VC_PROJ_TYPE" $$VC_PROJ_CODE');
+
+CFG=#$ Substitute('$$TARGET - Win32 Debug');
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "#$ ExpandGlue('MAKEFILE','','','".');
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f #$ Substitute('"$$MAKEFILE" CFG="$$TARGET - Win32 Debug"');
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE #$ Substitute('"$$TARGET - Win32 Release" (based on "$$VC_PROJ_TYPE")');
+!MESSAGE #$ Substitute('"$$TARGET - Win32 Debug" (based on "$$VC_PROJ_TYPE")');
+!MESSAGE
+
+# Begin Project
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+
+!IF "$(CFG)" == #$ Substitute('"$$TARGET - Win32 Release"');
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Target_Dir ""
+# ADD BASE CPP #$ Expand("VC_BASE_CPP_RELEASE");
+# ADD CPP #$ Expand("VC_CPP_RELEASE");
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo #$ Project("TARGETLIB") && Substitute('/out:"$$TARGETLIB"');
+
+!ELSEIF "$(CFG)" == #$ Substitute('"$$TARGET - Win32 Debug"');
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Target_Dir ""
+# ADD BASE CPP #$ Expand("VC_BASE_CPP_DEBUG");
+# ADD CPP #$ Expand("VC_CPP_DEBUG");
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo #$ Project("TARGETLIB") && Substitute('/out:"$$TARGETLIB"');
+
+!ENDIF
+
+# Begin Target
+
+# Name #$Substitute('"$$TARGET - Win32 Release"');
+# Name #$Substitute('"$$TARGET - Win32 Debug"');
+#${
+ foreach $n ( sort keys %file_names ) {
+ $f = $file_names{$n};
+ $p = $file_path{$n};
+ $p2 = $file_path2{$n};
+ $t = $all_files{$f};
+ if ( ($t eq "h") && $moc_output{$f} ) {
+ my($build);
+ $build = "\n\n# Begin Custom Build - Running moc...\nInputPath=" . $p2 . "\n\n"
+ . '"' . $moc_output{$f} . '" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"'
+ . "\n\tmoc $p2 -o " . $moc_output{$f} . "\n\n"
+ . "# End Custom Build\n\n";
+ $text .= ("# Begin Source File\n\nSOURCE=$p\n\n"
+ . '!IF "$(CFG)" == "' . $project{"TARGET"} . ' - Win32 Release"'
+ . $build);
+ $text .= ('!ELSEIF "$(CFG)" == "' . $project{"TARGET"} . ' - Win32 Debug"'
+ . $build
+ . "!ENDIF \n\n# End Source File\n");
+ } elsif ( $t eq "i" ) {
+ my($build,$dn);
+ $build = "\n\n# Begin Custom Build - Running moc...\nInputPath=" . $p2 . "\n\n"
+ . '"' . $f . '" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"'
+ . "\n\tmoc ". $moc_input{$f} . " -o $f\n\n"
+ . "# End Custom Build\n\n";
+ $dn = $n;
+ $dn =~ s/\..*//;
+ $dn =~ tr/a-z/A-Z/;
+ $text .= ("# Begin Source File\n\nSOURCE=$p\n"
+ . "USERDEP__$dn=" . '"' . $moc_input{$f} . '"' . "\n\n"
+ . '!IF "$(CFG)" == "' . $project{"TARGET"} . ' - Win32 Release"'
+ . $build);
+ $text .= ('!ELSEIF "$(CFG)" == "' . $project{"TARGET"} . ' - Win32 Debug"'
+ . $build
+ . "!ENDIF \n\n# End Source File\n");
+ } elsif ( $t eq "s" || $t eq "m" || $t eq "h" ) {
+ $text .= "# Begin Source File\n\nSOURCE=$p\n# End Source File\n";
+ }
+ }
+ chop $text;
+#$}
+# End Target
+# End Project
diff --git a/tmake/lib/win32-symantec/app.t b/tmake/lib/win32-symantec/app.t
new file mode 100755
index 0000000..fc4dc2c
--- /dev/null
+++ b/tmake/lib/win32-symantec/app.t
@@ -0,0 +1,6 @@
+#############################################################################
+#!
+#! This is a tmake template for building Win32 applications.
+#!
+#$ Project('TMAKE_APP_FLAG = 1');
+#$ IncludeTemplate("generic.t");
diff --git a/tmake/lib/win32-symantec/generic.t b/tmake/lib/win32-symantec/generic.t
new file mode 100755
index 0000000..e22d9c1
--- /dev/null
+++ b/tmake/lib/win32-symantec/generic.t
@@ -0,0 +1,212 @@
+#!
+#! This is a tmake template for building Win32 applications or libraries.
+#!
+#${
+ if ( Config("qt") ) {
+ if ( $ENV{"QT_DLL"} && !$ENV{"QT_NODLL"} ) {
+ Project('TMAKE_QT_DLL = 1');
+ if ( Project("TARGET") eq "qt" ) {
+ Project('CONFIG += dll');
+ }
+ }
+ }
+ if ( Config("dll") || Project("TMAKE_APP_FLAG") ) {
+ Project('CONFIG -= staticlib');
+ Project('TMAKE_APP_OR_DLL = 1');
+ } else {
+ Project('CONFIG += staticlib');
+ }
+ if ( Config("warn_off") ) {
+ Project('TMAKE_CFLAGS += $$TMAKE_CFLAGS_WARN_OFF');
+ } elsif ( Config("warn_on") ) {
+ Project('TMAKE_CFLAGS += $$TMAKE_CFLAGS_WARN_ON');
+ }
+ if ( Config("debug") ) {
+ Project('TMAKE_CFLAGS += $$TMAKE_CFLAGS_DEBUG');
+ Project('TMAKE_LFLAGS += $$TMAKE_LFLAGS_DEBUG');
+ } elsif ( Config("release") ) {
+ Project('TMAKE_CFLAGS += $$TMAKE_CFLAGS_RELEASE');
+ Project('TMAKE_LFLAGS += $$TMAKE_LFLAGS_RELEASE');
+ }
+ if ( Config("qt") || Config("opengl") ) {
+ Project('CONFIG += windows' );
+ }
+ if ( Config("qt") ) {
+ $moc_aware = 1;
+ AddIncludePath(Project('TMAKE_INCDIR_QT'));
+ if ( Config("opengl") ) {
+ Project('TMAKE_LIBS *= $$TMAKE_LIBS_QT_OPENGL');
+ }
+ if ( Project("TARGET") eq "qt" ) {
+ if ( Project("TMAKE_QT_DLL") && !(Project("DEFINES") =~ /QT_NODLL/) ) {
+ Project('DEFINES *= QT_MAKEDLL');
+ }
+ } else {
+ if ( Project("TMAKE_QT_DLL") && !(Project("DEFINES") =~ /QT_NODLL/) ) {
+ Project('DEFINES *= QT_DLL');
+ }
+ Project('TMAKE_LIBS *= $$TMAKE_LIBS_QT');
+ if ( (Project("DEFINES") =~ /QT_DLL/) ) {
+ my $qtver =FindHighestLibVersion($ENV{"QTDIR"} . "/lib", "qt");
+ Project("TMAKE_LIBS /= s/qt.lib/qt${qtver}.lib/");
+ Project('TMAKE_LIBS *= $$TMAKE_LIBS_QT_DLL');
+ }
+ }
+ }
+ if ( Config("opengl") ) {
+ Project('TMAKE_LIBS *= $$TMAKE_LIBS_OPENGL');
+ }
+ if ( Config("dll") ) {
+ Project('TMAKE_LFLAGS_CONSOLE_ANY = $$TMAKE_LFLAGS_CONSOLE_DLL');
+ Project('TMAKE_LFLAGS_WINDOWS_ANY = $$TMAKE_LFLAGS_WINDOWS_DLL');
+ if ( Project("TMAKE_LIB_FLAG") ) {
+ my $ver = Project("VERSION");
+ $ver =~ s/\.//g;
+ $project{"TARGET_EXT"} = "${ver}.dll";
+ } else {
+ $project{"TARGET_EXT"} = ".dll";
+ }
+ } else {
+ Project('TMAKE_LFLAGS_CONSOLE_ANY = $$TMAKE_LFLAGS_CONSOLE');
+ Project('TMAKE_LFLAGS_WINDOWS_ANY = $$TMAKE_LFLAGS_WINDOWS');
+ if ( Project('TMAKE_APP_FLAG') ) {
+ $project{"TARGET_EXT"} = ".exe";
+ } else {
+ $project{"TARGET_EXT"} = ".lib";
+ }
+ }
+ if ( Config("windows") ) {
+ if ( Config("console") ) {
+ Project('TMAKE_LFLAGS *= $$TMAKE_LFLAGS_CONSOLE_ANY');
+ Project('TMAKE_LIBS *= $$TMAKE_LIBS_CONSOLE');
+ } else {
+ Project('TMAKE_LFLAGS *= $$TMAKE_LFLAGS_WINDOWS_ANY');
+ }
+ Project('TMAKE_LIBS *= $$TMAKE_LIBS_WINDOWS');
+ } else {
+ Project('TMAKE_LFLAGS *= $$TMAKE_LFLAGS_CONSOLE_ANY');
+ Project('TMAKE_LIBS *= $$TMAKE_LIBS_CONSOLE');
+ }
+ Project('TMAKE_LIBS += $$LIBS');
+ Project('TMAKE_FILETAGS = HEADERS SOURCES DEF_FILE RC_FILE TARGET TMAKE_LIBS DESTDIR DLLDESTDIR $$FILETAGS');
+ foreach ( split(/\s/,Project('TMAKE_FILETAGS')) ) {
+ $project{$_} =~ s-[/\\]+-\\-g;
+ }
+ if ( Project('DEF_FILE') ) {
+ Project('TMAKE_LFLAGS *= /DEF:$$DEF_FILE');
+ }
+ if ( Project('RC_FILE') ) {
+ if ( Project('RES_FILE') ) {
+ tmake_error("Both .rc and .res file specified.\n" .
+ "Please specify one of them, not both.");
+ }
+ $project{"RES_FILE"} = $project{"RC_FILE"};
+ $project{"RES_FILE"} =~ s/\.rc$/.res/i;
+ Project('TARGETDEPS += $$RES_FILE');
+ }
+ if ( Project('RES_FILE') ) {
+ Project('TMAKE_LIBS *= $$RES_FILE');
+ }
+ StdInit();
+ $project{"DESTDIR"} = FixPath($project{"DESTDIR"});
+ if ( Project("VERSION") ) {
+ $project{"VER_MAJ"} = $project{"VERSION"};
+ $project{"VER_MAJ"} =~ s/\.\d+$//;
+ $project{"VER_MIN"} = $project{"VERSION"};
+ $project{"VER_MIN"} =~ s/^\d+\.//;
+ }
+#$}
+#!
+# Makefile for building #$ Expand("TARGET")
+# Generated by tmake at #$ Now();
+# Project: #$ Expand("PROJECT");
+# Template: #$ Expand("TEMPLATE");
+#############################################################################
+
+####### Compiler, tools and options
+
+CC = #$ Expand("TMAKE_CC");
+CFLAGS = #$ Expand("TMAKE_CFLAGS"); ExpandGlue("DEFINES","-D"," -D","");
+INCPATH = #$ ExpandGlue("INCPATH",'-I"','" -I"','"');
+#$ !Project("TMAKE_APP_OR_DLL") && DisableOutput();
+LINK = #$ Expand("TMAKE_LINK");
+LFLAGS = #$ Expand("TMAKE_LFLAGS");
+LIBS = #$ Expand("TMAKE_LIBS");
+#$ !Project("TMAKE_APP_OR_DLL") && EnableOutput();
+#$ Project("TMAKE_APP_OR_DLL") && DisableOutput();
+LIB = #$ Expand("TMAKE_LIB");
+#$ Project("TMAKE_APP_OR_DLL") && EnableOutput();
+MOC = #$ Expand("TMAKE_MOC");
+
+ZIP = #$ Expand("TMAKE_ZIP");
+
+####### Files
+
+HEADERS = #$ ExpandList("HEADERS");
+SOURCES = #$ ExpandList("SOURCES");
+OBJECTS = #$ ExpandList("OBJECTS");
+SRCMOC = #$ ExpandList("SRCMOC");
+OBJMOC = #$ ExpandList("OBJMOC");
+DIST = #$ ExpandList("DISTFILES");
+TARGET = #$ ExpandGlue("TARGET",$project{"DESTDIR"},"",$project{"TARGET_EXT"});
+
+####### Implicit rules
+
+.SUFFIXES: .cpp .cxx .cc .c
+
+.cpp.obj:
+ #$ Expand("TMAKE_COMPILE_IMP");
+
+.cxx.obj:
+ #$ Expand("TMAKE_COMPILE_IMP");
+
+.cc.obj:
+ #$ Expand("TMAKE_COMPILE_IMP");
+
+.c.obj:
+ #$ Expand("TMAKE_COMPILE_IMP");
+
+####### Build rules
+
+all: #$ ExpandGlue("ALL_DEPS",""," "," "); $text .= '$(TARGET)';
+
+$(TARGET): $(OBJECTS) $(OBJMOC) #$ Expand("TARGETDEPS");
+#$ Project("TMAKE_APP_OR_DLL") || DisableOutput();
+ $(LINK) $(LFLAGS) $(OBJECTS) $(OBJMOC), $(TARGET),, $(LIBS)
+#$ Project("TMAKE_APP_OR_DLL") || EnableOutput();
+#$ Project("TMAKE_APP_OR_DLL") && DisableOutput();
+ -del $(TARGET)
+#${
+# $text = "\t\$(LIB) \$(TARGET) "
+# . join(" \\\n+",split(/\s+/,$project{"OBJECTS"})) . " \\\n+"
+# . join(" \\\n+",split(/\s+/,$project{"OBJMOC"})) . ",;";
+#$}
+#$ Project("TMAKE_APP_OR_DLL") && EnableOutput();
+#$ (Config("dll") && Project("DLLDESTDIR")) || DisableOutput();
+ -copy $(TARGET) #$ Expand("DLLDESTDIR");
+#$ (Config("dll") && Project("DLLDESTDIR")) || EnableOutput();
+#$ Project('RC_FILE') || DisableOutput();
+
+#$ Substitute("\$\$RES_FILE: \$\$RC_FILE\n\t\$\$TMAKE_RC \$\$RC_FILE");
+#$ Project('RC_FILE') || EnableOutput();
+
+moc: $(SRCMOC)
+
+#$ TmakeSelf();
+
+dist:
+ #$ Substitute('$(ZIP) $$PROJECT.zip $$PROJECT.pro $(SOURCES) $(HEADERS) $(DIST)');
+
+clean:
+ #$ ExpandGlue("OBJECTS","-del ","\n\t-del ","");
+ #$ ExpandGlue("SRCMOC" ,"-del ","\n\t-del ","");
+ #$ ExpandGlue("OBJMOC" ,"-del ","\n\t-del ","");
+ -del $(TARGET)
+ #$ ExpandGlue("CLEAN_FILES","-del ","\n\t-del ","");
+
+####### Compile
+
+#$ BuildObj(Project("OBJECTS"),Project("SOURCES"));
+#$ BuildMocObj(Project("OBJMOC"),Project("SRCMOC"));
+#$ BuildMocSrc(Project("HEADERS"));
+#$ BuildMocSrc(Project("SOURCES"));
diff --git a/tmake/lib/win32-symantec/lib.t b/tmake/lib/win32-symantec/lib.t
new file mode 100755
index 0000000..d8ac6c7
--- /dev/null
+++ b/tmake/lib/win32-symantec/lib.t
@@ -0,0 +1,6 @@
+#############################################################################
+#!
+#! This is a tmake template for building Win32 libraries.
+#!
+#$ Project('TMAKE_LIB_FLAG = 1');
+#$ IncludeTemplate("generic.t");
diff --git a/tmake/lib/win32-symantec/subdirs.t b/tmake/lib/win32-symantec/subdirs.t
new file mode 100755
index 0000000..8b881ab
--- /dev/null
+++ b/tmake/lib/win32-symantec/subdirs.t
@@ -0,0 +1,2 @@
+#! Use the common Win32 template
+#$ IncludeTemplate("../win32/subdirs.t");
diff --git a/tmake/lib/win32-symantec/tmake.conf b/tmake/lib/win32-symantec/tmake.conf
new file mode 100755
index 0000000..c2b7e68
--- /dev/null
+++ b/tmake/lib/win32-symantec/tmake.conf
@@ -0,0 +1,56 @@
+#
+# $Id$
+#
+# tmake configuration for Win32/Symantec C++
+#
+
+TEMPLATE = app
+CONFIG = qt warn_on release
+
+TMAKE_CC = sc
+TMAKE_CFLAGS = -mn -w2
+TMAKE_CFLAGS_WARN_ON =
+TMAKE_CFLAGS_WARN_OFF = -w
+TMAKE_CFLAGS_RELEASE = -o
+TMAKE_CFLAGS_DEBUG = -g
+TMAKE_CFLAGS_YACC =
+
+TMAKE_CXX = $$TMAKE_CC
+TMAKE_CXXFLAGS = $$TMAKE_CFLAGS
+TMAKE_CXXFLAGS_WARN_ON = $$TMAKE_CFLAGS_WARN_ON
+TMAKE_CXXFLAGS_WARN_OFF = $$TMAKE_CFLAGS_WARN_OFF
+TMAKE_CXXFLAGS_RELEASE = $$TMAKE_CFLAGS_RELEASE
+TMAKE_CXXFLAGS_DEBUG = $$TMAKE_CFLAGS_DEBUG
+TMAKE_CXXFLAGS_YACC = $$TMAKE_CFLAGS_YACC
+
+TMAKE_INCDIR =
+TMAKE_INCDIR_QT = $(QTDIR)\include
+
+TMAKE_RUN_CC = $(CC) -c $(CFLAGS) $(INCPATH) -o$obj $src
+TMAKE_RUN_CC_IMP = $(CC) -c $(CFLAGS) $(INCPATH) -o$@ $<
+TMAKE_RUN_CXX = $(CXX) -c $(CXXFLAGS) $(INCPATH) -o$obj $src
+TMAKE_RUN_CXX_IMP = $(CXX) -c $(CXXFLAGS) $(INCPATH) -o$@ $<
+
+TMAKE_LINK = link
+TMAKE_LFLAGS = /NOLOGO /NOI
+TMAKE_LFLAGS_RELEASE =
+TMAKE_LFLAGS_DEBUG = /DEBUG
+TMAKE_LFLAGS_CONSOLE = /SUBSYSTEM:console
+TMAKE_LFLAGS_WINDOWS = /SUBSYSTEM:windows
+TMAKE_LFLAGS_CONSOLE_DLL= /SUBSYSTEM:console /DLL
+TMAKE_LFLAGS_WINDOWS_DLL= /SUBSYSTEM:windows /DLL
+
+TMAKE_LIBS =
+TMAKE_LIBS_CONSOLE =
+TMAKE_LIBS_WINDOWS = user32.lib gdi32.lib comdlg32.lib ole32.lib uuid.lib wsock32.lib
+TMAKE_LIBS_QT = $(QTDIR)\lib\qt.lib
+TMAKE_LIBS_QT_DLL = $(QTDIR)\lib\qtmain.lib
+TMAKE_LIBS_QT_OPENGL = $(QTDIR)\lib\qgl.lib
+TMAKE_LIBS_OPENGL = opengl32.lib
+
+TMAKE_MOC = moc
+
+TMAKE_LIB = lib /C /N /NOI /P:32
+TMAKE_RC = rc
+
+TMAKE_ZIP = zip -r -9
diff --git a/tmake/lib/win32-visage/app.t b/tmake/lib/win32-visage/app.t
new file mode 100755
index 0000000..fc4dc2c
--- /dev/null
+++ b/tmake/lib/win32-visage/app.t
@@ -0,0 +1,6 @@
+#############################################################################
+#!
+#! This is a tmake template for building Win32 applications.
+#!
+#$ Project('TMAKE_APP_FLAG = 1');
+#$ IncludeTemplate("generic.t");
diff --git a/tmake/lib/win32-visage/generic.t b/tmake/lib/win32-visage/generic.t
new file mode 100755
index 0000000..fd928ad
--- /dev/null
+++ b/tmake/lib/win32-visage/generic.t
@@ -0,0 +1,208 @@
+#!
+#! This is a tmake template for building Win32 applications or libraries.
+#!
+#${
+ if ( Config("qt") ) {
+ if ( $ENV{"QT_DLL"} && !$ENV{"QT_NODLL"} ) {
+ Project('TMAKE_QT_DLL = 1');
+ if ( Project("TARGET") eq "qt" ) {
+ Project('CONFIG += dll');
+ }
+ }
+ }
+ if ( Config("dll") || Project("TMAKE_APP_FLAG") ) {
+ Project('CONFIG -= staticlib');
+ Project('TMAKE_APP_OR_DLL = 1');
+ } else {
+ Project('CONFIG += staticlib');
+ }
+ if ( Config("warn_off") ) {
+ Project('TMAKE_CFLAGS += $$TMAKE_CFLAGS_WARN_OFF');
+ } elsif ( Config("warn_on") ) {
+ Project('TMAKE_CFLAGS += $$TMAKE_CFLAGS_WARN_ON');
+ }
+ if ( Config("debug") ) {
+ Project('TMAKE_CFLAGS += $$TMAKE_CFLAGS_DEBUG');
+ Project('TMAKE_LFLAGS += $$TMAKE_LFLAGS_DEBUG');
+ } elsif ( Config("release") ) {
+ Project('TMAKE_CFLAGS += $$TMAKE_CFLAGS_RELEASE');
+ Project('TMAKE_LFLAGS += $$TMAKE_LFLAGS_RELEASE');
+ }
+ if ( Config("qt") || Config("opengl") ) {
+ Project('CONFIG += windows' );
+ }
+ if ( Config("qt") ) {
+ $moc_aware = 1;
+ AddIncludePath(Project('TMAKE_INCDIR_QT'));
+ if ( Config("opengl") ) {
+ Project('TMAKE_LIBS *= $$TMAKE_LIBS_QT_OPENGL');
+ }
+ if ( Project("TARGET") eq "qt" ) {
+ if ( Project("TMAKE_QT_DLL") && !(Project("DEFINES") =~ /QT_NODLL/) ) {
+ Project('DEFINES *= QT_MAKEDLL');
+ }
+ } else {
+ if ( Project("TMAKE_QT_DLL") && !(Project("DEFINES") =~ /QT_NODLL/) ) {
+ Project('DEFINES *= QT_DLL');
+ }
+ Project('TMAKE_LIBS *= $$TMAKE_LIBS_QT');
+ if ( (Project("DEFINES") =~ /QT_DLL/) ) {
+ my $qtver =FindHighestLibVersion($ENV{"QTDIR"} . "/lib", "qt");
+ Project("TMAKE_LIBS /= s/qt.lib/qt${qtver}.lib/");
+ Project('TMAKE_LIBS *= $$TMAKE_LIBS_QT_DLL');
+ }
+ }
+ }
+ if ( Config("opengl") ) {
+ Project('TMAKE_LIBS *= $$TMAKE_LIBS_OPENGL');
+ }
+ if ( Config("dll") ) {
+ Project('TMAKE_LFLAGS_CONSOLE_ANY = $$TMAKE_LFLAGS_CONSOLE_DLL');
+ Project('TMAKE_LFLAGS_WINDOWS_ANY = $$TMAKE_LFLAGS_WINDOWS_DLL');
+ if ( Project("TMAKE_LIB_FLAG") ) {
+ my $ver = Project("VERSION");
+ $ver =~ s/\.//g;
+ $project{"TARGET_EXT"} = "${ver}.dll";
+ } else {
+ $project{"TARGET_EXT"} = ".dll";
+ }
+ } else {
+ Project('TMAKE_LFLAGS_CONSOLE_ANY = $$TMAKE_LFLAGS_CONSOLE');
+ Project('TMAKE_LFLAGS_WINDOWS_ANY = $$TMAKE_LFLAGS_WINDOWS');
+ if ( Project('TMAKE_APP_FLAG') ) {
+ $project{"TARGET_EXT"} = ".exe";
+ } else {
+ $project{"TARGET_EXT"} = ".lib";
+ }
+ }
+ if ( Config("windows") ) {
+ if ( Config("console") ) {
+ Project('TMAKE_LFLAGS *= $$TMAKE_LFLAGS_CONSOLE_ANY');
+ Project('TMAKE_LIBS *= $$TMAKE_LIBS_CONSOLE');
+ } else {
+ Project('TMAKE_LFLAGS *= $$TMAKE_LFLAGS_WINDOWS_ANY');
+ }
+ Project('TMAKE_LIBS *= $$TMAKE_LIBS_WINDOWS');
+ } else {
+ Project('TMAKE_LFLAGS *= $$TMAKE_LFLAGS_CONSOLE_ANY');
+ Project('TMAKE_LIBS *= $$TMAKE_LIBS_CONSOLE');
+ }
+ Project('TMAKE_LIBS += $$LIBS');
+ Project('TMAKE_FILETAGS = HEADERS SOURCES DEF_FILE RC_FILE TARGET TMAKE_LIBS DESTDIR DLLDESTDIR $$FILETAGS');
+ foreach ( split(/\s/,Project('TMAKE_FILETAGS')) ) {
+ $project{$_} =~ s-[/\\]+-\\-g;
+ }
+ if ( Project('DEF_FILE') ) {
+ Project('TMAKE_LFLAGS *= /DEF:$$DEF_FILE');
+ }
+ if ( Project('RC_FILE') ) {
+ if ( Project('RES_FILE') ) {
+ tmake_error("Both .rc and .res file specified.\n" .
+ "Please specify one of them, not both.");
+ }
+ $project{"RES_FILE"} = $project{"RC_FILE"};
+ $project{"RES_FILE"} =~ s/\.rc$/.res/i;
+ Project('TARGETDEPS += $$RES_FILE');
+ }
+ if ( Project('RES_FILE') ) {
+ Project('TMAKE_LIBS *= $$RES_FILE');
+ }
+ StdInit();
+ $project{"DESTDIR"} = FixPath($project{"DESTDIR"});
+ if ( Project("VERSION") ) {
+ $project{"VER_MAJ"} = $project{"VERSION"};
+ $project{"VER_MAJ"} =~ s/\.\d+$//;
+ $project{"VER_MIN"} = $project{"VERSION"};
+ $project{"VER_MIN"} =~ s/^\d+\.//;
+ }
+#$}
+#!
+# Makefile for building #$ Expand("TARGET")
+# Generated by tmake at #$ Now();
+# Project: #$ Expand("PROJECT");
+# Template: #$ Expand("TEMPLATE");
+#############################################################################
+
+####### Compiler, tools and options
+
+CC = #$ Expand("TMAKE_CC");
+CFLAGS = #$ Expand("TMAKE_CFLAGS"); ExpandGlue("DEFINES","-D"," -D","");
+INCPATH = #$ ExpandGlue("INCPATH",'-I"','" -I"','"');
+#$ !Project("TMAKE_APP_OR_DLL") && DisableOutput();
+LINK = #$ Expand("TMAKE_LINK");
+LFLAGS = #$ Expand("TMAKE_LFLAGS");
+LIBS = #$ Expand("TMAKE_LIBS");
+#$ !Project("TMAKE_APP_OR_DLL") && EnableOutput();
+#$ Project("TMAKE_APP_OR_DLL") && DisableOutput();
+LIB = #$ Expand("TMAKE_LIB");
+#$ Project("TMAKE_APP_OR_DLL") && EnableOutput();
+MOC = #$ Expand("TMAKE_MOC");
+
+ZIP = #$ Expand("TMAKE_ZIP");
+
+####### Files
+
+HEADERS = #$ ExpandList("HEADERS");
+SOURCES = #$ ExpandList("SOURCES");
+OBJECTS = #$ ExpandList("OBJECTS");
+SRCMOC = #$ ExpandList("SRCMOC");
+OBJMOC = #$ ExpandList("OBJMOC");
+DIST = #$ ExpandList("DISTFILES");
+TARGET = #$ ExpandGlue("TARGET",$project{"DESTDIR"},"",$project{"TARGET_EXT"});
+
+####### Implicit rules
+
+.SUFFIXES: .cpp .cxx .cc .c
+
+.cpp.obj:
+ #$ Expand("TMAKE_COMPILE_IMP");
+
+.cxx.obj:
+ #$ Expand("TMAKE_COMPILE_IMP");
+
+.cc.obj:
+ #$ Expand("TMAKE_COMPILE_IMP");
+
+.c.obj:
+ #$ Expand("TMAKE_COMPILE_IMP");
+
+####### Build rules
+
+all: #$ ExpandGlue("ALL_DEPS",""," "," "); $text .= '$(TARGET)';
+
+$(TARGET): $(OBJECTS) $(OBJMOC) #$ Expand("TARGETDEPS");
+#$ Project("TMAKE_APP_OR_DLL") || DisableOutput();
+$(TARGET): $(OBJECTS) $(LIBS) #$ Expand("TARGETDEPS");
+ $(LINK) -B"$(LFLAGS)" $(OBJECTS) $(LIBS) -Fe$(TARGET)
+#$ Project("TMAKE_APP_OR_DLL") || EnableOutput();
+#$ Project("TMAKE_APP_OR_DLL") && DisableOutput();
+ $(LIB) /OUT:$(TARGET) $(OBJECTS) $(OBJMOC)
+#$ Project("TMAKE_APP_OR_DLL") && EnableOutput();
+#$ (Config("dll") && Project("DLLDESTDIR")) || DisableOutput();
+ -copy $(TARGET) #$ Expand("DLLDESTDIR");
+#$ (Config("dll") && Project("DLLDESTDIR")) || EnableOutput();
+#$ Project('RC_FILE') || DisableOutput();
+
+#$ Substitute("\$\$RES_FILE: \$\$RC_FILE\n\t\$\$TMAKE_RC \$\$RC_FILE");
+#$ Project('RC_FILE') || EnableOutput();
+
+moc: $(SRCMOC)
+
+#$ TmakeSelf();
+
+dist:
+ #$ Substitute('$(ZIP) $$PROJECT.zip $$PROJECT.pro $(SOURCES) $(HEADERS) $(DIST)');
+
+clean:
+ #$ ExpandGlue("OBJECTS","-del ","\n\t-del ","");
+ #$ ExpandGlue("SRCMOC" ,"-del ","\n\t-del ","");
+ #$ ExpandGlue("OBJMOC" ,"-del ","\n\t-del ","");
+ -del $(TARGET)
+ #$ ExpandGlue("CLEAN_FILES","-del ","\n\t-del ","");
+
+####### Compile
+
+#$ BuildObj(Project("OBJECTS"),Project("SOURCES"));
+#$ BuildMocObj(Project("OBJMOC"),Project("SRCMOC"));
+#$ BuildMocSrc(Project("HEADERS"));
+#$ BuildMocSrc(Project("SOURCES"));
diff --git a/tmake/lib/win32-visage/lib.t b/tmake/lib/win32-visage/lib.t
new file mode 100755
index 0000000..d8ac6c7
--- /dev/null
+++ b/tmake/lib/win32-visage/lib.t
@@ -0,0 +1,6 @@
+#############################################################################
+#!
+#! This is a tmake template for building Win32 libraries.
+#!
+#$ Project('TMAKE_LIB_FLAG = 1');
+#$ IncludeTemplate("generic.t");
diff --git a/tmake/lib/win32-visage/subdirs.t b/tmake/lib/win32-visage/subdirs.t
new file mode 100755
index 0000000..8b881ab
--- /dev/null
+++ b/tmake/lib/win32-visage/subdirs.t
@@ -0,0 +1,2 @@
+#! Use the common Win32 template
+#$ IncludeTemplate("../win32/subdirs.t");
diff --git a/tmake/lib/win32-visage/tmake.conf b/tmake/lib/win32-visage/tmake.conf
new file mode 100755
index 0000000..3e20294
--- /dev/null
+++ b/tmake/lib/win32-visage/tmake.conf
@@ -0,0 +1,56 @@
+#
+# $Id$
+#
+# tmake configuration for Win32/IBM Visual Age
+#
+
+TEMPLATE = app
+CONFIG = qt warn_on release
+
+TMAKE_CC = icc -C
+TMAKE_CFLAGS = -Q -Ft -Gd -Gm+ -qrtti=all
+TMAKE_CFLAGS_WARN_ON = -W3
+TMAKE_CFLAGS_WARN_OFF = -W0
+TMAKE_CFLAGS_RELEASE = -Gl+ -O -Oc+
+TMAKE_CFLAGS_DEBUG = -Fb* -Ti -Tm
+TMAKE_CFLAGS_YACC =
+
+TMAKE_CXX = $$TMAKE_CC
+TMAKE_CXXFLAGS = $$TMAKE_CFLAGS
+TMAKE_CXXFLAGS_WARN_ON = $$TMAKE_CFLAGS_WARN_ON
+TMAKE_CXXFLAGS_WARN_OFF = $$TMAKE_CFLAGS_WARN_OFF
+TMAKE_CXXFLAGS_RELEASE = $$TMAKE_CFLAGS_RELEASE
+TMAKE_CXXFLAGS_DEBUG = $$TMAKE_CFLAGS_DEBUG
+TMAKE_CXXFLAGS_YACC = $$TMAKE_CFLAGS_YACC
+
+TMAKE_INCDIR =
+TMAKE_INCDIR_QT = $(QTDIR)\include
+
+TMAKE_RUN_CC = $(CC) -c $(CFLAGS) $(INCPATH) -Fo"$obj" $src
+TMAKE_RUN_CC_IMP = $(CC) -c $(CFLAGS) $(INCPATH) -Fo"$@" $<
+TMAKE_RUN_CXX = $(CXX) -c $(CXXFLAGS) $(INCPATH) -Fo"$obj" $src
+TMAKE_RUN_CXX_IMP = $(CXX) -c $(CXXFLAGS) $(INCPATH) -Fo"$@" $<
+
+TMAKE_LINK = icc -Tdp $(CFLAGS)
+TMAKE_LFLAGS = -nologo -code:RX -data:RW -def -noe
+TMAKE_LFLAGS_RELEASE = -OPTF
+TMAKE_LFLAGS_DEBUG = -de -br
+TMAKE_LFLAGS_CONSOLE = -pmtype:vio
+TMAKE_LFLAGS_WINDOWS = -pmtype:pm
+TMAKE_LFLAGS_CONSOLE_DLL= -DLL
+TMAKE_LFLAGS_WINDOWS_DLL= -DLL
+
+TMAKE_LIBS =
+TMAKE_LIBS_CONSOLE =
+TMAKE_LIBS_WINDOWS = user32.lib gdi32.lib comdlg32.lib ole32.lib uuid.lib wsock32.lib
+TMAKE_LIBS_QT = $(QTDIR)\lib\qt.lib
+TMAKE_LIBS_QT_DLL = $(QTDIR)\lib\qtmain.lib
+TMAKE_LIBS_QT_OPENGL = $(QTDIR)\lib\qgl.lib
+TMAKE_LIBS_OPENGL = opengl32.lib glu32.lib
+
+TMAKE_MOC = moc
+
+TMAKE_LIB = ilib
+TMAKE_RC = rc
+
+TMAKE_ZIP = zip -r -9
diff --git a/tmake/lib/win32-watcom/app.t b/tmake/lib/win32-watcom/app.t
new file mode 100755
index 0000000..fc4dc2c
--- /dev/null
+++ b/tmake/lib/win32-watcom/app.t
@@ -0,0 +1,6 @@
+#############################################################################
+#!
+#! This is a tmake template for building Win32 applications.
+#!
+#$ Project('TMAKE_APP_FLAG = 1');
+#$ IncludeTemplate("generic.t");
diff --git a/tmake/lib/win32-watcom/generic.t b/tmake/lib/win32-watcom/generic.t
new file mode 100755
index 0000000..a8c3990
--- /dev/null
+++ b/tmake/lib/win32-watcom/generic.t
@@ -0,0 +1,202 @@
+#!
+#! This is a tmake template for building Win32 applications or libraries.
+#!
+#${
+ if ( Config("qt") ) {
+ if ( $ENV{"QT_DLL"} && !$ENV{"QT_NODLL"} ) {
+ Project('TMAKE_QT_DLL = 1');
+ if ( Project("TARGET") eq "qt" ) {
+ Project('CONFIG += dll');
+ }
+ }
+ }
+ if ( Config("dll") || Project("TMAKE_APP_FLAG") ) {
+ Project('CONFIG -= staticlib');
+ Project('TMAKE_APP_OR_DLL = 1');
+ } else {
+ Project('CONFIG += staticlib');
+ }
+ if ( Config("warn_off") ) {
+ Project('TMAKE_CFLAGS += $$TMAKE_CFLAGS_WARN_OFF');
+ } elsif ( Config("warn_on") ) {
+ Project('TMAKE_CFLAGS += $$TMAKE_CFLAGS_WARN_ON');
+ }
+ if ( Config("debug") ) {
+ Project('TMAKE_CFLAGS += $$TMAKE_CFLAGS_DEBUG');
+ Project('TMAKE_LFLAGS += $$TMAKE_LFLAGS_DEBUG');
+ } elsif ( Config("release") ) {
+ Project('TMAKE_CFLAGS += $$TMAKE_CFLAGS_RELEASE');
+ Project('TMAKE_LFLAGS += $$TMAKE_LFLAGS_RELEASE');
+ }
+ if ( Config("qt") || Config("opengl") ) {
+ Project('CONFIG += windows' );
+ }
+ if ( Config("qt") ) {
+ $moc_aware = 1;
+ AddIncludePath(Project('TMAKE_INCDIR_QT'));
+ if ( Config("opengl") ) {
+ Project('TMAKE_LIBS *= $$TMAKE_LIBS_QT_OPENGL');
+ }
+ if ( Project("TARGET") eq "qt" ) {
+ if ( Project("TMAKE_QT_DLL") && !(Project("DEFINES") =~ /QT_NODLL/) ) {
+ Project('DEFINES *= QT_MAKEDLL');
+ }
+ } else {
+ if ( Project("TMAKE_QT_DLL") && !(Project("DEFINES") =~ /QT_NODLL/) ) {
+ Project('DEFINES *= QT_DLL');
+ }
+ Project('TMAKE_LIBS *= $$TMAKE_LIBS_QT');
+ if ( (Project("DEFINES") =~ /QT_DLL/) ) {
+ my $qtver =FindHighestLibVersion($ENV{"QTDIR"} . "/lib", "qt");
+ Project("TMAKE_LIBS /= s/qt.lib/qt${qtver}.lib/");
+ Project('TMAKE_LIBS *= $$TMAKE_LIBS_QT_DLL');
+ }
+ }
+ }
+ if ( Config("opengl") ) {
+ Project('TMAKE_LIBS *= $$TMAKE_LIBS_OPENGL');
+ }
+ if ( Config("dll") ) {
+ Project('TMAKE_LFLAGS_CONSOLE_ANY = $$TMAKE_LFLAGS_CONSOLE_DLL');
+ Project('TMAKE_LFLAGS_WINDOWS_ANY = $$TMAKE_LFLAGS_WINDOWS_DLL');
+ if ( Project("TMAKE_LIB_FLAG") ) {
+ my $ver = Project("VERSION");
+ $ver =~ s/\.//g;
+ $project{"TARGET_EXT"} = "${ver}.dll";
+ } else {
+ $project{"TARGET_EXT"} = ".dll";
+ }
+ } else {
+ Project('TMAKE_LFLAGS_CONSOLE_ANY = $$TMAKE_LFLAGS_CONSOLE');
+ Project('TMAKE_LFLAGS_WINDOWS_ANY = $$TMAKE_LFLAGS_WINDOWS');
+ if ( Project('TMAKE_APP_FLAG') ) {
+ $project{"TARGET_EXT"} = ".exe";
+ } else {
+ $project{"TARGET_EXT"} = ".lib";
+ }
+ }
+ if ( Config("windows") ) {
+ if ( Config("console") ) {
+ Project('TMAKE_LFLAGS *= $$TMAKE_LFLAGS_CONSOLE_ANY');
+ Project('TMAKE_LIBS *= $$TMAKE_LIBS_CONSOLE');
+ } else {
+ Project('TMAKE_LFLAGS *= $$TMAKE_LFLAGS_WINDOWS_ANY');
+ }
+ Project('TMAKE_LIBS *= $$TMAKE_LIBS_WINDOWS');
+ } else {
+ Project('TMAKE_LFLAGS *= $$TMAKE_LFLAGS_CONSOLE_ANY');
+ Project('TMAKE_LIBS *= $$TMAKE_LIBS_CONSOLE');
+ }
+ Project('TMAKE_LIBS += $$LIBS');
+ Project('TMAKE_FILETAGS = HEADERS SOURCES DEF_FILE RC_FILE TARGET TMAKE_LIBS DESTDIR DLLDESTDIR $$FILETAGS');
+ foreach ( split(/\s/,Project('TMAKE_FILETAGS')) ) {
+ $project{$_} =~ s-[/\\]+-\\-g;
+ }
+ if ( Project('DEF_FILE') ) {
+ Project('TMAKE_LFLAGS *= /DEF:$$DEF_FILE');
+ }
+ if ( Project('RC_FILE') ) {
+ if ( Project('RES_FILE') ) {
+ tmake_error("Both .rc and .res file specified.\n" .
+ "Please specify one of them, not both.");
+ }
+ $project{"RES_FILE"} = $project{"RC_FILE"};
+ $project{"RES_FILE"} =~ s/\.rc$/.res/i;
+ Project('TARGETDEPS += $$RES_FILE');
+ }
+ if ( Project('RES_FILE') ) {
+ Project('TMAKE_LIBS *= $$RES_FILE');
+ }
+ $linebreak = '&';
+ StdInit();
+ $project{"DESTDIR"} = FixPath($project{"DESTDIR"});
+ if ( Project("VERSION") ) {
+ $project{"VER_MAJ"} = $project{"VERSION"};
+ $project{"VER_MAJ"} =~ s/\.\d+$//;
+ $project{"VER_MIN"} = $project{"VERSION"};
+ $project{"VER_MIN"} =~ s/^\d+\.//;
+ }
+#$}
+#!
+# Makefile for building #$ Expand("TARGET")
+# Generated by tmake at #$ Now();
+# Project: #$ Expand("PROJECT");
+# Template: #$ Expand("TEMPLATE");
+#############################################################################
+
+####### Compiler, tools and options
+
+#$ Config("qt") || DisableOutput();
+QTDIR = #$ $text = $ENV{"QTDIR"};
+#$ Config("qt") || EnableOutput();
+CC = #$ Expand("TMAKE_CC");
+CFLAGS = #$ Expand("TMAKE_CFLAGS"); ExpandGlue("DEFINES","-d="," -d=","");
+INCPATH = #$ ExpandGlue("INCPATH","-i="," -i=","");
+#$ !Project("TMAKE_APP_OR_DLL") && DisableOutput();
+LINK = #$ Expand("TMAKE_LINK");
+LFLAGS = #$ Expand("TMAKE_LFLAGS");
+LIBS = #$ Expand("TMAKE_LIBS");
+#$ !Project("TMAKE_APP_OR_DLL") && EnableOutput();
+#$ Project("TMAKE_APP_OR_DLL") && DisableOutput();
+LIB = #$ Expand("TMAKE_LIB");
+#$ Project("TMAKE_APP_OR_DLL") && EnableOutput();
+MOC = #$ Expand("TMAKE_MOC");
+
+ZIP = #$ Expand("TMAKE_ZIP");
+
+####### Files
+
+HEADERS = #$ ExpandList("HEADERS");
+SOURCES = #$ ExpandList("SOURCES");
+OBJECTS = #$ ExpandList("OBJECTS");
+SRCMOC = #$ ExpandList("SRCMOC");
+OBJMOC = #$ ExpandList("OBJMOC");
+DIST = #$ ExpandList("DISTFILES");
+TARGET = #$ ExpandGlue("TARGET",$project{"DESTDIR"},"",$project{"TARGET_EXT"});
+TMPLIST = #$ ExpandGlue("TARGET","","",".lst");
+####### Build rules
+
+all: #$ ExpandGlue("ALL_DEPS",""," "," "); $text .= '$(TARGET)';
+
+$(TARGET): $(OBJECTS) $(OBJMOC) #$ Expand("TARGETDEPS");
+ @%create $(TMPLIST)
+#$ Project("TMAKE_APP_OR_DLL") || DisableOutput();
+ @%append $(TMPLIST) NAME #$ Expand("TARGET");
+ #$ ExpandGlue("OBJECTS",'@%append $(TMPLIST) FIL ',",","");
+ #$ ExpandGlue("OBJMOC" ,'@%append $(TMPLIST) FIL ',",","");
+ #$ ExpandGlue("TMAKE_LIBS" ,'@%append $(TMPLIST) LIBR ',",","");
+ $(LINK) $(LFLAGS) @$(TMPLIST)
+#$ Project("TMAKE_APP_OR_DLL") || EnableOutput();
+#$ Project("TMAKE_APP_OR_DLL") && DisableOutput();
+ @for %i in ( $(OBJECTS) $(OBJMOC) ) do @%append $(TMPLIST) +'%i'
+ $(LIB) $(TARGET) @$(TMPLIST)
+#$ Project("TMAKE_APP_OR_DLL") && EnableOutput();
+ del $(TMPLIST)
+#$ (Config("dll") && Project("DLLDESTDIR")) || DisableOutput();
+ -copy $(TARGET) #$ Expand("DLLDESTDIR");
+#$ (Config("dll") && Project("DLLDESTDIR")) || EnableOutput();
+#$ Project('RC_FILE') || DisableOutput();
+
+#$ Substitute("\$\$RES_FILE: \$\$RC_FILE\n\t\$\$TMAKE_RC \$\$RC_FILE");
+#$ Project('RC_FILE') || EnableOutput();
+
+moc: $(SRCMOC)
+
+#$ TmakeSelf();
+
+dist:
+ #$ Substitute('$(ZIP) $$PROJECT.zip $$PROJECT.pro $(SOURCES) $(HEADERS) $(DIST)');
+
+clean:
+ #$ ExpandGlue("OBJECTS","-del ","\n\t-del ","");
+ #$ ExpandGlue("SRCMOC" ,"-del ","\n\t-del ","");
+ #$ ExpandGlue("OBJMOC" ,"-del ","\n\t-del ","");
+ -del $(TARGET)
+ #$ ExpandGlue("CLEAN_FILES","-del ","\n\t-del ","");
+
+####### Compile
+
+#$ BuildObj(Project("OBJECTS"),Project("SOURCES"));
+#$ BuildMocObj(Project("OBJMOC"),Project("SRCMOC"));
+#$ BuildMocSrc(Project("HEADERS"));
+#$ BuildMocSrc(Project("SOURCES"));
diff --git a/tmake/lib/win32-watcom/lib.t b/tmake/lib/win32-watcom/lib.t
new file mode 100755
index 0000000..d8ac6c7
--- /dev/null
+++ b/tmake/lib/win32-watcom/lib.t
@@ -0,0 +1,6 @@
+#############################################################################
+#!
+#! This is a tmake template for building Win32 libraries.
+#!
+#$ Project('TMAKE_LIB_FLAG = 1');
+#$ IncludeTemplate("generic.t");
diff --git a/tmake/lib/win32-watcom/subdirs.t b/tmake/lib/win32-watcom/subdirs.t
new file mode 100755
index 0000000..8b881ab
--- /dev/null
+++ b/tmake/lib/win32-watcom/subdirs.t
@@ -0,0 +1,2 @@
+#! Use the common Win32 template
+#$ IncludeTemplate("../win32/subdirs.t");
diff --git a/tmake/lib/win32-watcom/tmake.conf b/tmake/lib/win32-watcom/tmake.conf
new file mode 100755
index 0000000..3a3e0bf
--- /dev/null
+++ b/tmake/lib/win32-watcom/tmake.conf
@@ -0,0 +1,54 @@
+#
+# $Id$
+#
+# tmake configuration for Win32/Watcom C++
+#
+
+TEMPLATE = app
+CONFIG = qt warn_on release
+
+TMAKE_CC = wcl386
+TMAKE_CFLAGS = -zq
+TMAKE_CFLAGS_WARN_ON = -w2
+TMAKE_CFLAGS_WARN_OFF = -w0
+TMAKE_CFLAGS_RELEASE = -ox
+TMAKE_CFLAGS_DEBUG = -d2
+TMAKE_CFLAGS_YACC =
+
+TMAKE_CXX = $$TMAKE_CC
+TMAKE_CXXFLAGS = $$TMAKE_CFLAGS
+TMAKE_CXXFLAGS_WARN_ON = $$TMAKE_CFLAGS_WARN_ON
+TMAKE_CXXFLAGS_WARN_OFF = $$TMAKE_CFLAGS_WARN_OFF
+TMAKE_CXXFLAGS_RELEASE = $$TMAKE_CFLAGS_RELEASE
+TMAKE_CXXFLAGS_DEBUG = $$TMAKE_CFLAGS_DEBUG
+TMAKE_CXXFLAGS_YACC = $$TMAKE_CFLAGS_YACC
+
+TMAKE_INCDIR =
+TMAKE_INCDIR_QT = $(QTDIR)\include
+
+TMAKE_RUN_CC = $(CC) -c $(CFLAGS) $(INCPATH) -fo=$obj $src
+TMAKE_RUN_CXX = $(CXX) -c $(CXXFLAGS) $(INCPATH) -fo=$obj $src
+
+TMAKE_LINK = wlink
+TMAKE_LFLAGS = op quiet op c
+TMAKE_LFLAGS_RELEASE =
+TMAKE_LFLAGS_DEBUG = d all
+TMAKE_LFLAGS_CONSOLE = sys nt
+TMAKE_LFLAGS_WINDOWS = sys nt_win
+TMAKE_LFLAGS_CONSOLE_DLL= sys nt
+TMAKE_LFLAGS_WINDOWS_DLL= sys nt_win
+
+TMAKE_LIBS =
+TMAKE_LIBS_CONSOLE =
+TMAKE_LIBS_WINDOWS =
+TMAKE_LIBS_QT = %QTDIR%\lib\qt.lib
+TMAKE_LIBS_QT_DLL = %QTDIR%\lib\qtmain.lib
+TMAKE_LIBS_QT_OPENGL = %QTDIR%\lib\qgl.lib
+TMAKE_LIBS_OPENGL = opengl32.lib
+
+TMAKE_MOC = moc
+
+TMAKE_LIB = wlib -b -c -n -q -p=512
+TMAKE_RC = rc
+
+TMAKE_ZIP = zip -r -9
diff --git a/tmake/lib/win32/subdirs.t b/tmake/lib/win32/subdirs.t
new file mode 100755
index 0000000..57464c6
--- /dev/null
+++ b/tmake/lib/win32/subdirs.t
@@ -0,0 +1,35 @@
+#############################################################################
+#!
+#! This is a tmake template for creating a makefile that invokes make in
+#! sub directories - for Win32.
+#!
+#${
+ StdInit();
+ $m = "";
+ foreach ( split(/\s+/,$project{"SUBDIRS"}) ) {
+ $m = $m . "\tcd $_\n\tDOMAKE\n\t\@cd ..\n";
+ }
+ $project{"SUBMAKE"} = $m;
+#$}
+#!
+# Makefile for building targets in sub directories.
+# Generated by tmake at #$ Now();
+# Project: #$ Expand("PROJECT");
+# Template: #$ Expand("TEMPLATE");
+#############################################################################
+
+SUBDIRS = #$ ExpandList("SUBDIRS");
+
+all: $(SUBDIRS)
+
+#${
+ foreach ( split(/\s+/,$project{"SUBDIRS"}) ) {
+ $text = $text . $_ . ": FORCE\n\t" .
+ "cd $_\n\t\$(MAKE\)\n\t\@cd ..\n\n";
+ }
+#$}
+
+clean:
+#$ $text = $project{"SUBMAKE"}; $text =~ s/DOMAKE/\$(MAKE\) clean/g;
+
+FORCE: