Commit 367c98ad authored by Dimitri van Heesch's avatar Dimitri van Heesch

Release-1.1.3

parent 59bbbf50
DOXYGEN Version 1.1.2-20000430
DOXYGEN Version 1.1.3
CONTENTS
--------
......@@ -15,8 +15,8 @@ INSTALLATION INSTRUCTIONS FOR UNIX:
1. Unpack the archive, unless you already have:
gunzip doxygen-1.1.2-20000430.src.tar.gz # uncompress the archive
tar xf doxygen-1.1.2-20000430.src.tar # unpack it
gunzip doxygen-1.1.3.src.tar.gz # uncompress the archive
tar xf doxygen-1.1.3.src.tar # unpack it
2. Run the configure script:
......@@ -252,4 +252,4 @@ The latest version of doxygen can be obtained at
Enjoy,
Dimitri van Heesch (30 April 2000)
Dimitri van Heesch (08 May 2000)
DOXYGEN Version 1.1.2-20000430
DOXYGEN Version 1.1.3
Please read INSTALL for compilation instructions.
......@@ -7,4 +7,4 @@ The latest version of doxygen can be obtained at
Enjoy,
Dimitri van Heesch (30 April 2000)
Dimitri van Heesch (08 May 2000)
1.1.2-20000430
1.1.3
......@@ -1427,6 +1427,16 @@ void init()
"toolkit from AT&T and Lucent Bell Labs. The other options in this section \n"
"have no effect if this option is set to NO (the default) \n"
);
ConfigBool::add( "classGraphFlag",
"CLASS_GRAPH",
"TRUE",
"class graph",
"If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen \n"
"will generate a graph for each documented class showing the direct and \n"
"indirect inheritance relations. Setting this tag to YES will force the \n"
"the CLASS_DIAGRAMS tag to NO.\n"
);
addDependency("classGraphFlag","haveDotFlag");
ConfigBool::add( "collGraphFlag",
"COLLABORATION_GRAPH",
"TRUE",
......
......@@ -85,6 +85,7 @@ documentation:
<li> \refitem cmdline \line
<li> \refitem cmdlink \link
<li> \refitem cmdmainpage \mainpage
<li> \refitem cmdname \name
<li> \refitem cmdnamespace \namespace
<li> \refitem cmdoverload \overload
<li> \refitem cmdpage \page
......@@ -186,20 +187,13 @@ Doxygen. Unrecognized commands are treated as normal text.
\addindex \defgroup
Indicates that a comment block contains documentation for a
group of classes, files or namespaces. This can be used to
\ref modules "group" of classes, files or namespaces. This can be used to
categorize classes, files or namespaces, and document those
categories.
categories. You can also uses groups as members of other groups,
thus building a hierarchy of groups.
The \<name\> argument should an single word identifier.
\par Example:
\verbinclude group.cpp
\htmlonly
Click <a href="$(DOXYGEN_DOCDIR)/examples/group/html/modules.html">here</a>
for the corresponding HTML documentation that is generated by Doxygen.
\endhtmlonly
\sa section \ref cmdingroup "\\ingroup"
<hr>
......@@ -354,6 +348,17 @@ Doxygen. Unrecognized commands are treated as normal text.
section \ref cmdsubsection "\\subsection" and
section \ref cmdpage "\\page".
<hr>
\subsection cmdname \name (header)
This command turns a comment block into a header
definition of a member group. The
comment block should be followed by a
<code>//@{ ... //@}</code> block containing the
members of the group.
See section \ref memgroup for an example.
<hr>
\subsection cmdnamespace \namespace <name>
......
......@@ -60,6 +60,7 @@ followed by the descriptions of the tags grouped by category.
<li> \refitem cfg_cgi_name CGI_NAME
<li> \refitem cfg_cgi_url CGI_URL
<li> \refitem cfg_class_diagrams CLASS_DIAGRAMS
<li> \refitem cfg_class_graph CLASS_GRAPH
<li> \refitem cfg_collaboration_graph COLLABORATION_GRAPH
<li> \refitem cfg_cols_in_alpha_index COLS_IN_ALPHA_INDEX
<li> \refitem cfg_compact_latex COMPACT_LATEX
......@@ -115,6 +116,7 @@ followed by the descriptions of the tags grouped by category.
<li> \refitem cfg_output_directory OUTPUT_DIRECTORY
<li> \refitem cfg_output_language OUTPUT_LANGUAGE
<li> \refitem cfg_paper_type PAPER_TYPE
<li> \refitem cfg_pdf_hyperlinks PDF_HYPERLINKS
<li> \refitem cfg_perl_path PERL_PATH
<li> \refitem cfg_predefined PREDEFINED
<li> \refitem cfg_project_name PROJECT_NAME
......@@ -704,6 +706,15 @@ EXTRA_PACKAGES = times
the version number of doxygen, the project name (see PROJECT_NAME), or the
project number (see PROJECT_NUMBER).
\anchor cfg_pdf_hyperlinks
<dt>\c PDF_HYPERLINKS <dd>
\addindex PDF_HYPERLINKS
If the \c PDF_HYPERLINKS tag is set to \c YES, the LaTeX that is generated
is prepared for conversion to pdf (using ps2pdf). The pdf file will
contain links (just like the HTML output) instead of page references
This makes the output suitable for online browsing using a pdf viewer.
\anchor cfg_latex_batchmode
<dt>\c LATEX_BATCHMODE <dd>
\addindex LATEX_BATCHMODE
......@@ -890,6 +901,14 @@ TAGFILES = file1=loc1 "file2 = loc2" ... </pre>
visualization toolkit from AT&T and Lucent Bell Labs. The other options in
this section have no effect if this option is set to \c NO (the default)
\anchor cfg_class_graph
<dt>\c CLASS_GRAPH <dd>
\addindex CLASS_GRAPH
If the \c CLASS_GRAPH and \c HAVE_DOT tags are set to \c YES then doxygen
will generate a graph for each documented class showing the direct and
indirect inheritance relations. Setting this tag to \c YES will force the
the \c CLASS_DIAGRAMS tag to NO.
\anchor cfg_collaboration_graph
<dt>\c COLLABORATION_GRAPH <dd>
\addindex COLLABORATION_GRAPH
......
......@@ -47,6 +47,7 @@ Written by Dimitri van Heesch\\[2ex]
\input{install}
\input{starting}
\input{docblocks}
\input{grouping}
\input{formulas}
\input{diagrams}
\input{preprocessing}
......
......@@ -35,7 +35,7 @@ You should use the \\mainpage command inside a comment block like this:
*/
\endverbatim
<li><b>When I set EXTRACT_ALL to NO non of my function are shown in the documentation.</b></li>
<li><b>When I set EXTRACT_ALL to NO non of my functions are shown in the documentation.</b></li>
In order for global functions, variables, enums, typedefs, and defines
to be documented you should document the file in which these commands are
......@@ -147,6 +147,11 @@ QTime and QIODevice classes.
Another reason is for the nice and bug free utility classes, like QList,
QDict, QString, QArray, QTextStream, QRegExp etc.
<li><b>Can use doxygen on my Java code?</b>
No, at the moment there is no support for Java. I suggest to
use Sun's JavaDoc instead.
</ol>
\htmlonly
......
......@@ -47,23 +47,33 @@ Documents produced by Doxygen are derivative works derived from the
input used in their production; they are not affected by this license.
<h2>Introduction</h2>
Doxygen is a documentation system for C, C++ and IDL. 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. There is also support for generating
man pages and for converting the generated output into
Postscript, hyperlinked PDF or compressed HTML.
The documentation is extracted directly from the
sources. Doxygen is developed on <a href="http://www.linux.org">Linux</a>,
but it runs on most other UNIX flavors as well.
An executable for Windows 9x/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).
Doxygen is a documentation system for C++, IDL (Corba and Microsoft flavors)
and C.
It can help you in three ways:
<ol>
<li> It can generate an on-line documentation browser (in HTML) and/or an
off-line reference manual (in \f$\mbox{\LaTeX}\f$) from a set
of documented source files.
There is also support for generating output in RTF (MS-Word),
Postscript, hyperlinked PDF, compressed HTML, and Unix man pages.
The documentation is extracted directly from the sources, which
makes it much easier to keep the documentation consistent with the
source code.
<li> Doxygen can 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.
The relations between the various elements are be visualized
by means of include dependency graphs, inheritance diagrams,
and collaboration diagrams, which are all generated automatically.
<li> You can even `abuse' doxygen for creating normal documentation (as I did
for this manual).
</ol>
Doxygen is developed on <a href="http://www.linux.org">Linux</a>,
but is set-up to be highly portable. As a result, it runs on most
other UNIX flavors as well. Furthermore, an executable for
Windows 9x/NT is also available.
This manual is divided into two parts, each of which is divided into several
sections.
......@@ -77,6 +87,7 @@ The first part forms a user manual:
documentation quickly.
<li>Section \ref docblocks demonstrates the various ways that code can
be documented.
<li>Section \ref grouping shows how to group things together.
<li>Section \ref formulas shows how to insert formulas in the documentation.
<li>Section \ref diagrams describes the diagrams and graphs that doxygen can generate.
<li>Section \ref preprocessing explains how doxygen deals with macro definitions.
......@@ -112,13 +123,13 @@ The second part forms a reference manual:
<h2>Projects using doxygen</h2>
I have compiled a small
I have compiled a
\htmlonly
<a href="http://www.stack.nl/~dimitri/doxygen/projects.html">list of projects</a>
that use doxygen
that use doxygen.
\endhtmlonly
\latexonly
list of projects that use doxygen (see {\tt http://www.stack.nl/$\sim$dimitri/doxygen/projects.html})
list of projects that use doxygen (see {\tt http://www.stack.nl/$\sim$dimitri/doxygen/projects.html}).
\endlatexonly
If you know other projects, let me know and I'll add them.
......@@ -143,13 +154,13 @@ Thanks go to:
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 :-)
(which is very useful as a Windows/Unix platform abstraction layer :-)
<li>My brother <a href="http://www.stack.nl/~fidget/index.html">Frank</a>
for rendering the logos.
<li>Harm van der Heijden for adding HTML help support.
<li>Parker Waerchter for adding the RTF output generator.
<li>Joerg Baumann, for adding conditional documentation blocks, and
PDF links.
<li>Joerg Baumann, for adding conditional documentation blocks,
PDF links, and the configuration generator.
<li>Matthias Andree for providing a .spec script for building rpms from the
sources.
<li>Jens Breitenstein, Christophe Bordeaux, Samuel Hägglund, Xet Erixon,
......
......@@ -60,33 +60,38 @@ Makefile. It contains of a number of assignments (tags) of the form:
You can probably leave the values of most tags in a generated template
configuration file 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 (for instance <code>*.cpp *.h</code>).
Only files that match one of the
The \ref cfg_input "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
\ref cfg_input "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 \ref cfg_input "INPUT" tag, and add one or more file
patterns to the \ref cfg_file_patterns "FILE_PATTERNS" tag
(for instance <code>*.cpp *.h</code>). 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 fine-tune the list of files
that is parsed the \c EXCLUDE and \c EXCLUDE_PATTERNS tags can be used.
the \ref cfg_recursive "RECURSIVE" tag to \c YES. To further fine-tune the
list of files that is parsed the \ref cfg_exclude "EXCLUDE" and
\ref cfg_exclude_patterns "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.
what the documented result would be. To do so, you must set
the \ref cfg_extract_all "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 \ref cfg_extract_all "EXTRACT_ALL" is set to \c YES.
To analyse an existing piece of software it is useful to cross-reference
a (documented) entity with its definition in the source files. Doxygen will
generate such cross-references if you set the \c SOURCE_BROWSER tag to \c YES.
generate such cross-references if you set
the \ref cfg_source_browser "SOURCE_BROWSER" tag to \c YES.
It can also include the sources directly into the documentation by setting
\c INLINE_SOURCES to \c YES (this can be handly for code reviews for instance).
\ref cfg_inline_sources "INLINE_SOURCES" to \c YES (this can be handly for
code reviews for instance).
\subsection step2 Step 2: Running doxygen
......@@ -95,18 +100,19 @@ To generate the documentation you can now enter:
doxygen <config-file>
\endverbatim
Doxygen will create a \c html, \c latex and/or \c man directory inside
Doxygen will create a \c html, \c rtf, \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 \c man3 directory inside the \c man directory.
As the names suggest the \c html directory contain the
generated documentation in HTML, RTF, \f$\mbox{\LaTeX}\f$ and Unix-Man page
format.
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.
using the \ref cfg_output_directory "OUTPUT_DIRECTORY" ,
\ref cfg_html_output "HTML_OUTPUT", \ref cfg_latex_output "LATEX_OUTPUT",
and \ref cfg_man_output "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
......@@ -127,10 +133,10 @@ converted into a postscript file \c refman.ps by typing <code>make ps</code>
(this requires <code>dvips</code>). 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.
Conversion to PDF is also possible; just type
<code>make pdf</code> (this required <code>ps2pdf</code>).
To get the best results for PDF output you should set the
\c PDF_HYPERLINKS tag to \c YES.
Conversion to PDF is also possible if you have installed the ghostscript
interpreter; just type <code>make pdf</code>. To get the best results for
PDF output you should set the \ref cfg_pdf_hyperlinks "PDF_HYPERLINKS"
tag to \c YES.
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 \c MANPATH
......@@ -145,10 +151,11 @@ 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:
If the \ref cfg_extract_all "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
basically 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
......@@ -174,7 +181,7 @@ During parsing the following steps take place:
<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,
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
......@@ -218,7 +225,7 @@ Using a number of column aligned minus signs at the start of a
More text here.
If you use tabs within lists, please make sure that \c TAB_SIZE in the
If you use tabs within lists, please make sure that \ref cfg_tab_size "TAB_SIZE" in the
configuration file is set to the correct tab size.
\htmlonly
......@@ -272,11 +279,12 @@ 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
(this description can be hidden by
setting \ref cfg_brief_member_desc "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
(this can be changed by setting the \ref cfg_repeat_brief "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
......@@ -287,10 +295,17 @@ style:
for the corresponding HTML documentation that is generated by doxygen.
\endhtmlonly
Note that the first sentence of the documentation (until the <tt>.</tt>)
Note that by default 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.
forms the detailed description. If you want to put a dot in the middle of a
sentence you should put a backslash and space behind it. Example:
\verbatim
/** Brief description (e.g.\ using only a few words). Details follow. */
\endverbatim
The brief description is required for the JavaDoc style, unless you set
\ref cfg_javadoc_autobrief "JAVADOC_AUTOBRIEF" to NO. If you do this,
doxygen treats JavaDoc comments just like Qt comments (i.e. You have
to insert an explicit \ref cmdbrief "\\brief" command to add a brief description).
Unlike most other documentation systems, doxygen also allows you to put
the documentation of members (including global functions) in front of
......@@ -301,6 +316,11 @@ 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).
\par Note:
Each entity can only have \e one brief and \e one detailed description. If you
specify more than one comment block of the same type, only one will be used,
and all others are ignored!
\subsection structuralcommands Structural commands
So far we have assumed that the documentation blocks are always located in
......@@ -399,9 +419,99 @@ Here is an example of a the use of these comment blocks:
\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.
They cannot be used to document files, classes, unions, structs,
groups, namespaces and enums. Furthermore, the structural commands
mentioned in the previous section (like <code>\\class</code>) are ignored
inside these comment blocks.
\htmlonly
Go to the <a href="grouping.html">next</a> section or return to the
<a href="index.html">index</a>.
\endhtmlonly
*/
/*! \page grouping Grouping
Doxygen has two mechanisms to group things together.
One mechanism works at a global level, creating a new page
for each group. These groups are called "modules" in the documentation.
The other mechanism works within a member list of some compound entity,
and is refered to as a "member group".
\subsection modules Modules
Modules are a way to group things together on a separate page. You
can document a group as a whole, as well as all individual members.
Members of a group can be files, namespaces, classes, functions,
variables, enums, typedefs, and defines, but also other groups.
To define a group, you should put the \ref cmddefgroup "\\defgroup"
command in a special comment block. The first argument of the command
is a label that should uniquely identify the group. You can make an
entity a member of a specific group by putting
a \ref cmdingroup "\\ingroup" command inside its documentation.
\par Example:
\verbinclude group.cpp
\htmlonly
Click <a href="$(DOXYGEN_DOCDIR)/examples/group/html/modules.html">here</a>
for the corresponding HTML documentation that is generated by Doxygen.
\endhtmlonly
\subsection memgroup Member Groups
If a compound (e.g. a class or file) has many members, it is often
desired to group them together. Doxygen already automatically groups
things together on type and protection level, but maybe you feel that
this is not enough or that that default grouping is wrong.
For instance, because you feel that members of different (syntactic)
types belong to the same (semantic) group.
A member group is defined by
a
\verbatim
//@{
...
//@}
\endverbatim
block or a
\verbatim
/*@{*/
...
/*@}*/
\endverbatim
block if you prefer C style
comments. Note that the members of the group should be
physcially inside the member group's body.
Before the opening marker of a block a separate comment block should be
placed. This block should contain the \ref cmdname "@name"
(or \ref cmdname "\name") command and is used to specify the header
of the group. Optionally, the comment block may contain more
detailed information about the group.
Nesting of member groups is not allowed.
If all members of a member group have the same type and protection level
(for instance all are static public members), then the whole member
group is displayed as a subgroup of the type/protection level group
(the group is displayed as a subsection of the "Static Public Members"
section for instance). If two or more members have different types,
then the group is put at the same level as the automatically
generated groups.
\par Example:
\verbinclude memgrp.cpp
\htmlonly
Click <a href="$(DOXYGEN_DOCDIR)/examples/memgrp/html/class_test.html">here</a>
for the corresponding HTML documentation that is generated by Doxygen.
\endhtmlonly
Here Group1 is displayed as a subsection of the "Public Members". And
Group2 is a separate section because it contains members with
different protection levels (i.e. public and protected).
\htmlonly
Go to the <a href="formulas.html">next</a> section or return to the
......@@ -501,6 +611,10 @@ Go to the <a href="diagrams.html">next</a> section or return to the
<b>Warning:</b> When you have a very large class hierarchy where many
classes derive from a common base class, the resulting image may become
too big to handle for some browsers.
<li>if \ref cfg_class_graph "CLASS_GRAPH" is set to \c YES,
a graph will be generated for each documented class showing the
direct and indirect inheritance relations. This disables the
generation of the build-in class inheritance diagrams.
<li>if \ref cfg_include_graph "INCLUDE_GRAPH" is set to \c YES, an include
dependency graph is generated for each documented file that includes at
least one other file. This feature is currently supported for HTML and RTF
......@@ -518,52 +632,56 @@ Go to the <a href="diagrams.html">next</a> section or return to the
The elements in the class diagrams in HTML and RTF
have the following meaning:
<ul>
<li> A yellow box indicates a class. A box can have a
<li> A \b yellow box indicates a class. A box can have a
little marker in the lower right corner to indicate that the class
contains base classes that are hidden. If the box is filled with a
contains base classes that are hidden.
For the class diagrams the maximum tree width is currently 8 elements.
If a tree wider some nodes will be hidden.
If the box is filled with a
dashed pattern the inheritance relation is virtual.
<li> A white box indicates that the documentation of the class
<li> A \b white box indicates that the documentation of the class
is currently shown.
<li> A grey box indicates an undocumented class.
<li> A solid dark blue arrows indicates public inheritance.
<li> A dashed dark green arrows indicates protected inheritance.
<li> A dotted dark green arrows indicates private inheritance.
<li> A \b grey box indicates an undocumented class.
<li> A <b>solid dark blue</b> arrow indicates public inheritance.
<li> A <b>dashed dark green</b> arrow indicates protected inheritance.
<li> A <b>dotted dark green</b> arrow indicates private inheritance.
</ul>
The elements in the class diagram in \f$\mbox{\LaTeX}\f$ have the
following meaning:
<ul>
<li> A white box indicates a class.
A marker in the lower right corner of the box indicates that the
<li> A \b white box indicates a class.
A \b marker in the lower right corner of the box indicates that the
class has base classes that are hidden.
If the box has a dashed border this indicates virtual inheritance.
<li> A solid arrow indicates public inheritance.
<li> A dashed arrow indicates protected inheritance.
<li> A dotted arrow indicated private inheritance.
If the box has a \b dashed border this indicates virtual inheritance.
<li> A \b solid arrow indicates public inheritance.
<li> A \b dashed arrow indicates protected inheritance.
<li> A \b dotted arrow indicated private inheritance.
</ul>
The elements in the graphs generated by the dot tool have the following
meaning:
<ul>
<li> A white box indicates a class or struct. If the box has a
red border this indicates that the class contains related classes
that are hidden.
<li> A black box indicates that the class' documentation is currently shown.
<li> A dark blue arrow indicates an include relation (for the
<li> A \b white box indicates a class or struct or file.
<li> A box with a \b red border indicates a node that has
\e more arrows than are shown!
In order words: the graph is \e truncated with respect to this node.
The reason a graph is sometimes truncated is too prevent images
from becoming too large.
For the graphs generated with dot doxygen tries
to limit the width of the resulting image to 1024 pixels.
<li> A \b black box indicates that the class' documentation is currently shown.
<li> A <b>dark blue</b> arrow indicates an include relation (for the
include dependency graph) or public inheritance (for the other graphs).
<li> A dark green arrow indicates protected inheritance.
<li> A dark red arrow indicates private inheritance.
<li> A purple dashed arrow indicated a "usage" relation, the
<li> A <b>dark green</b> arrow indicates protected inheritance.
<li> A <b>dark red</b> arrow indicates private inheritance.
<li> A <b>purple dashed</b> arrow indicated a "usage" relation, the
edge of the arrow is labled with the variable(s) responsible for the
relation.
Class \c A uses class \c B, if class \c A has a member variable \c m
of type C, where B is a subtype of C (e.g. C could be \c B, \c B*, <code>T\<B\>*</code> ).
</ul>
The reason why classes or structs are sometimes hidden is too prevent images
to become too large. For the class diagrams the maximum tree width
is currently 8 elements. For the graphs generated with dot doxygen tries
to limit the width of the resulting image to 1024 pixels.
Here are a couple of header files that together show the various diagrams
that doxygen can generate:
......@@ -622,13 +740,14 @@ Then by default doxygen will feed the following to its parser:
static CONST_STRING version = "2.xx";
\endverbatim
You can disable all preprocessing by setting \c ENABLE_PREPROCESSING to \c
You can disable all preprocessing by setting
\ref cfg_enable_preprocessing "ENABLE_PREPROCESSING" to \c
NO in the configuation file. In the case above doxygen will then read
both statements!
In case you want to expand the \c CONST_STRING macro, you should set the
\c MACRO_EXPANSION tag in the config file to \c YES. Then the result
after preprocessing becomes:
\ref cfg_macro_expansion "MACRO_EXPANSION" tag in the config file
to \c YES. Then the result after preprocessing becomes:
\verbatim
#define VERSION
......@@ -640,8 +759,10 @@ after preprocessing becomes:
Note that doxygen will now expand \e all macro definitions
(recursively if needed). This is often too much. Therefore, doxygen also
allows you to expand only those defines that you explicitly
specify. For this you have to set the \c EXPAND_ONLY_PREDEF tag to \c YES
and specify the macro definitions after the \c PREDEFINED tag.
specify. For this you have to set the
\ref cfg_expand_only_predef "EXPAND_ONLY_PREDEF" tag to \c YES
and specify the macro definitions after
the \ref cfg_predefined "PREDEFINED" tag.
As an example, suppose you have the following obfusciated code fragment
of an abstract base class called \c IUnknown:
......@@ -696,9 +817,11 @@ class IUnknown
};
\endverbatim
Note that the \c PREDEFINED tag accepts function like macro definitions
(like \c DECLARE_INTERFACE), normal macro substitutions (like \c PURE
and \c THIS) and plain defines (like \c __cplusplus).
Note that the \ref cfg_predefined "PREDEFINED" tag accepts function
like macro definitions
(like \c DECLARE_INTERFACE ), normal macro
substitutions (like \c PURE and \c THIS) and plain
defines (like \c __cplusplus).
Note also that preprocessor definitions that are normally defined
automatically by the preprocessor (like \c __cplusplus), have to be defined
......@@ -726,7 +849,7 @@ PREDEFINED = QListT:=QList
As you can see doxygen's preprocessor is quite powerful, but if you want
even more flexibility you can always write an input filter and specify it
after the \c INPUT_FILTER tag.
after the \ref cfg_input_filter "INPUT_FILTER" tag.
If you are unsure what the effect of doxygen's preprocessing will be
you can run doxygen as follows:
......
......@@ -20,12 +20,14 @@ all: class/html/index.html \
template/html/index.html \
tag/html/index.html \
group/html/index.html \
diagrams/html/index.html
diagrams/html/index.html \
memgrp/html/index.html
clean:
rm -rf class define enum file func page relates author \
par overload example include qtstyle jdstyle structcmd \
autolink tag restypedef afterdoc template tag group diagrams
autolink tag restypedef afterdoc template tag group diagrams \
memgrp
class/html/index.html: class.h class.cfg
$(DOXYGEN)/bin/doxygen class.cfg
......@@ -92,6 +94,9 @@ template/html/index.html: templ.cpp templ.cfg
group/html/index.html: group.cpp group.cfg
$(DOXYGEN)/bin/doxygen group.cfg
memgrp/html/index.html: memgrp.cpp memgrp.cfg
$(DOXYGEN)/bin/doxygen memgrp.cfg
diagrams/html/index.html: diagrams_a.h diagrams_b.h diagrams_c.h diagrams_d.h diagrams_e.h diagrams.cfg
ifneq ($(HAVE_DOT),)
$(DOXYGEN)/bin/doxygen diagrams.cfg
......
......@@ -21,14 +21,15 @@ all: class/html/index.html \
template/html/index.html \
tag/html/index.html \
group/html/index.html \
diagrams/html/index.html
diagrams/html/index.html \
memgrp/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 resdefine
deltree /y restypedef afterdoc template tag group diagrams
deltree /y restypedef afterdoc template tag group diagrams memgrp
class/html/index.html: class.h class.cfg
$(DOXYDIR)\doxygen class.cfg
......@@ -97,5 +98,8 @@ template/html/index.html: templ.cpp templ.cfg
group/html/index.html: group.cpp group.cfg
$(DOXYDIR)\doxygen group.cfg
memgrp/html/index.html: memgrp.cpp memgrp.cfg
$(DOXYDIR)\doxygen memgrp.cfg
diagrams/html/index.html: diagrams_a.h diagrams_b.h diagrams_c.h diagrams_d.h diagrams_e.h diagrams.cfg
$(DOXYDIR)\doxygen diagrams.cfg
......@@ -10,6 +10,11 @@
* This is the third group
*/
/*! \defgroup group4 The Fourth Group
* \ingroup group3
* Group 4 is a subgroup of group 3
*/
/*! \ingroup group1
* \brief class C1 in group 1
*/
......@@ -35,11 +40,11 @@ class C4 {};
*/
class C5 {};
/*! \ingroup group1 group2 group3
* \brief class C6 in all groups
* \sa \link group1 The first group\endlink, group2, group3
/*! \ingroup group1 group2 group3 group4
* namespace N1 is in all groups
* \sa \link group1 The first group\endlink, group2, group3, group4
*/
class C6 {};
namespace N1 {};
/*! \file
* \ingroup group3
......
PROJECT_NAME = "Member Grouping"
OUTPUT_DIRECTORY = memgrp
GENERATE_LATEX = NO
GENERATE_MAN = NO
INPUT = memgrp.cpp
QUIET = YES
/** A class. Details */
class Test
{
public:
/** @name Group1
*/
//@{
/** Function 1 in group 1. Details. */
void func1InGroup1();
void func2InGroup1();
//@}
/** Function without group. Details. */
void ungroupedFunction();
void func1InGroup2();
protected:
void func2InGroup2();
};
void Test::func1InGroup1() {}
void Test::func2InGroup1() {}
/** @name Group2
* Description of group 2.
*/
//@{
/** Function 2 in group 2. Details. */
void Test::func2InGroup2() {}
/** Function 1 in group 2. Details. */
void Test::func1InGroup2() {}
//@}
......@@ -7,8 +7,8 @@ type makeconfig Makefile.win.in >Makefile
type makeconfig src\Makefile.in >src\Makefile
type makeconfig examples\Makefile.win.in >examples\Makefile
type makeconfig doc\Makefile.win.in >doc\Makefile
copy src\doxygen.pro.in src\doxygen.pro
copy src\doxytag.pro.in src\doxytag.pro
copy src\doxysearch.pro.in src\doxysearch.pro
type src\doxygen.pro.in | sed "s/\$extraopts/release/g" >src\doxygen.pro
type src\doxytag.pro.in | sed "s/\$extraopts/release/g" >src\doxytag.pro
type src\doxysearch.pro.in | sed "s/\$extraopts/release/g" >src\doxysearch.pro
nmake
Name: doxygen
Version: 1.1.2-20000430
Version: 1.1.3
Summary: documentation system for C, C++ and IDL
Release: 1
Source0: doxygen-%{version}.src.tar.gz
......@@ -24,7 +24,7 @@ BuildPrereq: perl tetex
%build
CFLAGS="$RPM_OPT_FLAGS" ./configure --prefix %{prefix}
CFLAGS="$RPM_OPT_FLAGS" ./configure --prefix %{prefix} --with-doxywizard
make
%install
......@@ -36,6 +36,9 @@ make INSTALL=$RPM_BUILD_ROOT%{prefix} install
( cd $RPM_BUILD_ROOT
mkdir -p ./usr/doc/packages
mv .%{prefix}/doc/doxygen ./usr/doc/packages/doxygen
mv .%{prefix}/doc/doxysearch ./usr/doc/packages/doxysearch
mv .%{prefix}/doc/doxytag ./usr/doc/packages/doxytag
mv .%{prefix}/doc/doxywizard ./usr/doc/packages/doxywizard
)
%files
......
......@@ -243,7 +243,7 @@ void ClassDef::insertMember(MemberDef *md,int groupId)
break;
}
}
else if (md->isTypedef() || md->isEnumerate())
else if (md->isTypedef() || md->isEnumerate() || md->isEnumValue())
{
switch (md->protection())
{
......@@ -675,8 +675,25 @@ void ClassDef::writeDocumentation(OutputList &ol)
if ( icd->isVisibleInHierarchy()) count++;
ibcd=inherits->next();
}
if (Config::classDiagramFlag && count>0)
// write class diagram
if (Config::haveDotFlag && Config::classGraphFlag)
// write class diagram using dot
{
DotClassGraph inheritanceGraph(this,DotClassGraph::Inheritance);
if (!inheritanceGraph.isTrivial())
{
ol.pushGeneratorState();
ol.disable(OutputGenerator::Latex);
ol.disable(OutputGenerator::Man);
ol.startDotGraph();
parseText(ol,theTranslator->trClassDiagram(name()));
ol.endDotGraph(inheritanceGraph);
ol.popGeneratorState();
}
}
else if (Config::classDiagramFlag && count>0)
// write class diagram using build-in generator
{
ClassDiagram diagram(this); // create a diagram of this class.
ol.startClassDiagram();
......@@ -688,20 +705,16 @@ void ClassDef::writeDocumentation(OutputList &ol)
if (Config::haveDotFlag && Config::collGraphFlag)
{
DotGfxUsageGraph usageImplGraph(this,TRUE);
DotClassGraph usageImplGraph(this,DotClassGraph::Implementation);
if (!usageImplGraph.isTrivial())
{
ol.pushGeneratorState();
ol.disable(OutputGenerator::Latex);
ol.disable(OutputGenerator::Man);
ol.startCollaborationDiagram();
ol.startDotGraph();
parseText(ol,theTranslator->trCollaborationDiagram(name()));
//usageImplGraph.writeGraph(Config::htmlOutputDir);
//ol.writeString((QCString)"<p>Interface collaboration diagram for "
// "<a href=\"usage_intf_graph_"+name()+".html\">here</a>");
//ol.writeString((QCString)"<p>Implementation collaboration diagram for "
// "<a href=\"usage_impl_graph_"+name()+".html\">here</a>");
ol.endCollaborationDiagram(usageImplGraph);
ol.enableAll();
ol.endDotGraph(usageImplGraph);
ol.popGeneratorState();
}
}
......@@ -1616,6 +1629,7 @@ void ClassDef::determineImplUsageRelation()
if (md->isVariable()) // for each member variable in this class
{
QCString type=md->typeString();
int typeLen=type.length();
static const QRegExp re("[a-z_A-Z][a-z_A-Z0-9:]*");
//printf("in class %s found var type=`%s' name=`%s'\n",
// name().data(),type.data(),md->name().data());
......@@ -1623,17 +1637,35 @@ void ClassDef::determineImplUsageRelation()
bool found=FALSE;
while ((i=re.match(type,p,&l))!=-1 && !found) // for each class name in the type
{
int ts=p+l;
int te=ts;
while (type.at(ts)==' ' && ts<typeLen) ts++; // skip any whitespace
if (type.at(ts)=='<') // assume template instance
{
// locate end of template
te=ts+1;
int brCount=1;
while (te<typeLen && brCount!=0)
{
if (type.at(te)=='<') brCount++;
if (type.at(te)=='>') brCount--;
te++;
}
}
QCString templSpec;
if (te>ts) templSpec = type.mid(ts,te-ts);
ClassDef *cd=getResolvedClass(name()+"::"+type.mid(i,l));
if (cd==0) cd=getResolvedClass(type.mid(i,l)); // TODO: also try inbetween scopes!
if (cd /*&& cd->isLinkable()*/) // class exists and is linkable
if (cd) // class exists
{
found=TRUE;
if (usesImplClassDict==0) usesImplClassDict = new UsesClassDict(257);
UsesClassDef *ucd=usesImplClassDict->find(cd->name());
if (ucd==0)
if (ucd==0 || ucd->templSpecifiers!=templSpec)
{
ucd = new UsesClassDef(cd);
usesImplClassDict->insert(cd->name(),ucd);
ucd->templSpecifiers = templSpec;
//printf("Adding used class %s to class %s\n",
// cd->name().data(),name().data());
}
......
......@@ -198,6 +198,7 @@ struct UsesClassDef
}
ClassDef *classDef;
QDict<void> *accessors;
QCString templSpecifiers;
};
class UsesClassDict : public QDict<UsesClassDef>
......
......@@ -965,7 +965,15 @@ TYPEKW ("bool"|"char"|"const"|"double"|"float"|"int"|"long"|"short"|"signed"|"u
{
startCodeLine(*g_code);
}
BEGIN(g_lastSpecialCContext);
if (g_lastSpecialCContext==SkipCxxComment)
{ // force end of C++ comment here
endFontClass();
BEGIN( g_lastCContext ) ;
}
else
{
BEGIN(g_lastSpecialCContext);
}
}
<RemoveSpecialCComment>"*/" {
BEGIN(g_lastSpecialCContext);
......
......@@ -106,6 +106,7 @@ struct Config
static bool allExtFlag; // include all external classes flag
static QCString perlPath; // the absolute path to perl
static bool haveDotFlag; // indicates wether or not dot is present
static bool classGraphFlag; // class graph
static bool collGraphFlag; // collaboration graph
static bool includeGraphFlag; // include graph
static bool gfxHierarchyFlag; // flag to enable graphical hierarchy
......
......@@ -138,6 +138,7 @@ QCString Config::genTagFile;
bool Config::allExtFlag = FALSE;
QCString Config::perlPath = "/usr/bin/perl";
bool Config::haveDotFlag = FALSE;
bool Config::classGraphFlag = TRUE;
bool Config::collGraphFlag = TRUE;
bool Config::includeGraphFlag = TRUE;
bool Config::gfxHierarchyFlag = TRUE;
......@@ -275,6 +276,7 @@ static int yyread(char *buf,int max_size)
<Start>"ALLEXTERNALS"[ \t]*"=" { BEGIN(GetBool); b=&Config::allExtFlag; }
<Start>"PERL_PATH"[ \t]*"=" { BEGIN(GetString); s=&Config::perlPath; s->resize(0); }
<Start>"HAVE_DOT"[ \t]*"=" { BEGIN(GetBool); b=&Config::haveDotFlag; }
<Start>"CLASS_GRAPH"[ \t]*"=" { BEGIN(GetBool); b=&Config::classGraphFlag; }
<Start>"COLLABORATION_GRAPH"[ \t]*"=" { BEGIN(GetBool); b=&Config::collGraphFlag; }
<Start>"INCLUDE_GRAPH"[ \t]*"=" { BEGIN(GetBool); b=&Config::includeGraphFlag; }
<Start>"GRAPHICAL_HIERARCHY"[ \t]*"=" { BEGIN(GetBool); b=&Config::gfxHierarchyFlag; }
......@@ -557,6 +559,7 @@ void dumpConfig()
printf("perlPath=`%s'\n",Config::perlPath.data());
printf("# Configuration options related to the dot tool \n");
printf("haveDotFlag=`%d'\n",Config::haveDotFlag);
printf("classGraphFlag=`%d'\n",Config::classGraphFlag);
printf("collGraphFlag=`%d'\n",Config::collGraphFlag);
printf("includeGraphFlag=`%d'\n",Config::includeGraphFlag);
printf("gfxHierarchyFlag=`%d'\n",Config::gfxHierarchyFlag);
......@@ -654,6 +657,7 @@ void Config::init()
Config::allExtFlag = FALSE;
Config::perlPath = "/usr/bin/perl";
Config::haveDotFlag = FALSE;
Config::classGraphFlag = TRUE;
Config::collGraphFlag = TRUE;
Config::includeGraphFlag = TRUE;
Config::gfxHierarchyFlag = TRUE;
......@@ -1632,6 +1636,18 @@ void writeTemplateConfig(QFile *f,bool sl)
writeBoolValue(t,Config::haveDotFlag);
t << "\n";
if (!sl)
{
t << "\n";
t << "# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen \n";
t << "# will generate a graph for each documented class showing the direct and \n";
t << "# indirect inheritance relations. Setting this tag to YES will force the \n";
t << "# the CLASS_DIAGRAMS tag to NO.\n";
t << "\n";
}
t << "CLASS_GRAPH = ";
writeBoolValue(t,Config::classGraphFlag);
t << "\n";
if (!sl)
{
t << "\n";
t << "# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen \n";
......
......@@ -312,14 +312,15 @@ void DotNode::writeBox(QTextStream &t,bool hasNonReachableChildren)
t << "];" << endl;
}
void DotNode::writeArrow(QTextStream &t,DotNode *cn,EdgeInfo *ei,bool topDown)
void DotNode::writeArrow(QTextStream &t,DotNode *cn,EdgeInfo *ei,bool topDown,
bool pointBack)
{
t << " Node";
if (topDown) t << cn->number(); else t << m_number;
t << " -> Node";
if (topDown) t << m_number; else t << cn->number();
t << " [";
t << "dir=back,";
if (pointBack) t << "dir=back,";
t << "color=\"" << edgeColorMap[ei->m_color]
<< "\",fontsize=10,style=\"" << edgeStyleMap[ei->m_style] << "\"";
if (!ei->m_label.isEmpty())
......@@ -330,15 +331,16 @@ void DotNode::writeArrow(QTextStream &t,DotNode *cn,EdgeInfo *ei,bool topDown)
t << "];" << endl;
}
void DotNode::write(QTextStream &t,bool topDown,int distance)
void DotNode::write(QTextStream &t,bool topDown,bool toChildren,int distance)
{
//printf("DotNode::write(%d) name=%s\n",distance,m_label.data());
if (m_written) return; // node already written to the output
if (m_distance>distance) return;
QList<DotNode> *nl = toChildren ? m_children : m_parents;
bool hasNonReachableChildren=FALSE;
if (m_distance==distance && m_children)
if (m_distance==distance && nl)
{
QListIterator<DotNode> dnli(*m_children);
QListIterator<DotNode> dnli(*nl);
DotNode *cn;
for (dnli.toFirst();(cn=dnli.current());++dnli)
{
......@@ -347,15 +349,38 @@ void DotNode::write(QTextStream &t,bool topDown,int distance)
}
writeBox(t,hasNonReachableChildren);
m_written=TRUE;
if (m_children)
if (nl)
{
QListIterator<DotNode> dnli1(*m_children);
QListIterator<EdgeInfo> dnli2(*m_edgeInfo);
DotNode *cn;
for (dnli1.toFirst();(cn=dnli1.current());++dnli1,++dnli2)
if (toChildren)
{
if (cn->m_distance<=distance) writeArrow(t,cn,dnli2.current(),topDown);
cn->write(t,topDown,distance);
QListIterator<DotNode> dnli1(*nl);
QListIterator<EdgeInfo> dnli2(*m_edgeInfo);
DotNode *cn;
for (dnli1.toFirst();(cn=dnli1.current());++dnli1,++dnli2)
{
if (cn->m_distance<=distance)
{
writeArrow(t,cn,dnli2.current(),topDown);
}
cn->write(t,topDown,toChildren,distance);
}
}
else // render parents
{
QListIterator<DotNode> dnli(*nl);
DotNode *pn;
for (dnli.toFirst();(pn=dnli.current());++dnli)
{
if (pn->m_distance<=distance)
{
writeArrow(t,
pn,
pn->m_edgeInfo->at(pn->m_children->findRef(this)),
FALSE
);
}
pn->write(t,TRUE,FALSE,distance);
}
}
}
}
......@@ -510,7 +535,7 @@ void DotGfxHierarchyTable::writeGraph(QTextStream &out,const char *path)
DotNode *node;
for (;(node=dnli2.current());++dnli2)
{
if (node->m_subgraphId==n->m_subgraphId) node->write(t,FALSE);
if (node->m_subgraphId==n->m_subgraphId) node->write(t,FALSE,TRUE);
}
t << "}" << endl;
f.close();
......@@ -712,82 +737,106 @@ DotGfxHierarchyTable::~DotGfxHierarchyTable()
//--------------------------------------------------------------------
int DotGfxUsageGraph::m_curNodeNumber;
int DotClassGraph::m_curNodeNumber;
void DotGfxUsageGraph::addClass(ClassDef *cd,DotNode *n,int prot,
const char *label,int distance)
void DotClassGraph::addClass(ClassDef *cd,DotNode *n,int prot,
const char *label,int distance,const char *templSpec,bool base)
{
//printf(":: DoxGfxUsageGraph::addClass(class=%s,parent=%s,prot=%d,label=%s,dist=%d)\n",
// cd->name().data(),n->m_label.data(),prot,label,distance);
int edgeStyle = label ? EdgeInfo::Dashed : EdgeInfo::Solid;
DotNode *bn = m_usedNodes->find(cd->name());
QCString className;
if (templSpec)
className=insertTemplateSpecifierInScope(cd->name(),templSpec);
else
className=cd->name().copy();
DotNode *bn = m_usedNodes->find(className);
if (bn) // class already inserted
{
n->addChild(bn,prot,edgeStyle,label);
bn->addParent(n);
if (base)
{
n->addChild(bn,prot,edgeStyle,label);
bn->addParent(n);
}
else
{
bn->addChild(n,prot,edgeStyle,label);
n->addParent(bn);
}
bn->setDistance(distance);
//printf(" add exiting node %s of %s\n",bn->m_label.data(),n->m_label.data());
}
else // new class
{
bn = new DotNode(m_curNodeNumber++,
cd->name(),
className,
cd->isLinkable() ?
(cd->getReference()+"$"+cd->getOutputFileBase()).data() : 0,
distance
);
if (distance>m_maxDistance) m_maxDistance=distance;
n->addChild(bn,prot,edgeStyle,label);
bn->addParent(n);
m_usedNodes->insert(cd->name(),bn);
if (base)
{
n->addChild(bn,prot,edgeStyle,label);
bn->addParent(n);
}
else
{
bn->addChild(n,prot,edgeStyle,label);
n->addParent(bn);
}
m_usedNodes->insert(className,bn);
//printf(" add used node %s of %s\n",cd->name().data(),n->m_label.data());
if (distance<m_recDepth) buildGraph(cd,bn,distance+1);
if (distance<m_recDepth) buildGraph(cd,bn,distance+1,base);
}
}
void DotGfxUsageGraph::buildGraph(ClassDef *cd,DotNode *n,int distance)
void DotClassGraph::buildGraph(ClassDef *cd,DotNode *n,int distance,bool base)
{
// add base classes
BaseClassListIterator bcli(*cd->baseClasses());
BaseClassListIterator bcli(base ? *cd->baseClasses() : *cd->superClasses());
BaseClassDef *bcd;
for ( ; (bcd=bcli.current()) ; ++bcli )
{
addClass(bcd->classDef,n,bcd->prot,0,distance);
addClass(bcd->classDef,n,bcd->prot,0,distance,bcd->templSpecifiers,base);
}
UsesClassDict *dict = m_impl ? cd->usedImplementationClasses() :
cd->usedInterfaceClasses();
if (dict)
if (m_graphType != Inheritance)
{
UsesClassDictIterator ucdi(*dict);
UsesClassDef *ucd;
for (;(ucd=ucdi.current());++ucdi)
UsesClassDict *dict =
m_graphType==Implementation ? cd->usedImplementationClasses() :
cd->usedInterfaceClasses();
if (dict)
{
QCString label;
QDictIterator<void> dvi(*ucd->accessors);
const char *s;
bool first=TRUE;
for (;(s=dvi.currentKey());++dvi)
UsesClassDictIterator ucdi(*dict);
UsesClassDef *ucd;
for (;(ucd=ucdi.current());++ucdi)
{
if (first)
{
label=s;
first=FALSE;
}
else
QCString label;
QDictIterator<void> dvi(*ucd->accessors);
const char *s;
bool first=TRUE;
for (;(s=dvi.currentKey());++dvi)
{
label+=QCString("\\n")+s;
if (first)
{
label=s;
first=FALSE;
}
else
{
label+=QCString("\\n")+s;
}
}
//printf("Found label=`%s'\n",label.data());
addClass(ucd->classDef,n,EdgeInfo::Black,label,distance,ucd->templSpecifiers,base);
}
//printf("Found label=`%s'\n",label.data());
addClass(ucd->classDef,n,EdgeInfo::Black,label,distance);
}
}
}
DotGfxUsageGraph::DotGfxUsageGraph(ClassDef *cd,bool impl,int maxRecursionDepth)
DotClassGraph::DotClassGraph(ClassDef *cd,GraphType t,int maxRecursionDepth)
{
//printf("DotGfxUsage::DotGfxUsage %s\n",cd->name().data());
m_impl = impl;
m_graphType = t;
m_maxDistance = 0;
m_recDepth = maxRecursionDepth;
m_startNode = new DotNode(m_curNodeNumber++,
......@@ -800,25 +849,33 @@ DotGfxUsageGraph::DotGfxUsageGraph(ClassDef *cd,bool impl,int maxRecursionDepth)
m_usedNodes = new QDict<DotNode>(1009);
m_usedNodes->insert(cd->name(),m_startNode);
//printf("Root node %s\n",cd->name().data());
if (m_recDepth>0) buildGraph(cd,m_startNode,1);
if (m_recDepth>0)
{
buildGraph(cd,m_startNode,1,TRUE);
if (t==Inheritance) buildGraph(cd,m_startNode,1,FALSE);
}
m_diskName = cd->getOutputFileBase().copy();
}
bool DotGfxUsageGraph::isTrivial() const
bool DotClassGraph::isTrivial() const
{
return m_startNode->m_children==0;
if (m_graphType==Inheritance)
return m_startNode->m_children==0 && m_startNode->m_parents==0;
else
return m_startNode->m_children==0;
}
DotGfxUsageGraph::~DotGfxUsageGraph()
DotClassGraph::~DotClassGraph()
{
deleteNodes(m_startNode);
delete m_usedNodes;
}
static void writeDotGraph(DotNode *root,const QCString &baseName,
bool lrRank,int distance)
void writeDotGraph(DotNode *root,const QCString &baseName,
bool lrRank,bool renderParents,int distance)
{
// generate the graph description for dot
//printf("writeDotGraph(%s,%d)\n",baseName.data(),renderParents);
QFile f;
f.setName(baseName+".dot");
if (f.open(IO_WriteOnly))
......@@ -831,7 +888,25 @@ static void writeDotGraph(DotNode *root,const QCString &baseName,
t << " rankdir=LR;" << endl;
}
root->clearWriteFlag();
root->write(t,TRUE,distance);
root->write(t,TRUE,TRUE,distance);
if (renderParents && root->m_parents)
{
//printf("rendering parents!\n");
QListIterator<DotNode> dnli(*root->m_parents);
DotNode *pn;
for (dnli.toFirst();(pn=dnli.current());++dnli)
{
if (pn->m_distance<=distance)
{
root->writeArrow(t,
pn,
pn->m_edgeInfo->at(pn->m_children->findRef(root)),
FALSE
);
}
pn->write(t,TRUE,FALSE,distance);
}
}
t << "}" << endl;
f.close();
}
......@@ -840,7 +915,8 @@ static void writeDotGraph(DotNode *root,const QCString &baseName,
static void findMaximalDotGraph(DotNode *root,int maxDist,
const QCString &baseName,
QDir &thisDir,
bool lrRank=FALSE
bool lrRank=FALSE,
bool renderParents=FALSE
)
{
bool lastFit;
......@@ -854,7 +930,7 @@ static void findMaximalDotGraph(DotNode *root,int maxDist,
// sized image (dimensions: maxImageWidth, maxImageHeight)
do
{
writeDotGraph(root,baseName,lrRank,curDistance);
writeDotGraph(root,baseName,lrRank,renderParents,curDistance);
QCString dotCmd;
// create annotated dot file
......@@ -891,19 +967,21 @@ static void findMaximalDotGraph(DotNode *root,int maxDist,
if (!lastFit)
{
//printf("Using last fit %d\n",minDistance);
writeDotGraph(root,baseName,
writeDotGraph(root,
baseName,
lrRank || (curDistance==1 && width>maxImageWidth),
renderParents,
minDistance
);
}
}
QCString DotGfxUsageGraph::diskName() const
QCString DotClassGraph::diskName() const
{
return m_diskName + "_coll_graph";
}
void DotGfxUsageGraph::writeGraph(QTextStream &out,
void DotClassGraph::writeGraph(QTextStream &out,
const char *path,
bool isTBRank)
{
......@@ -919,14 +997,27 @@ void DotGfxUsageGraph::writeGraph(QTextStream &out,
QDir thisDir;
QCString baseName;
if (m_impl)
baseName.sprintf("%s_coll_graph",m_diskName.data());
else
baseName.sprintf("%s_intf_graph",m_diskName.data());
QCString mapName;
switch (m_graphType)
{
case Implementation:
baseName.sprintf("%s_coll_graph",m_diskName.data());
mapName="coll_map";
break;
case Interface:
baseName.sprintf("%s_intf_graph",m_diskName.data());
mapName="intf_map";
break;
case Inheritance:
baseName.sprintf("%s_inherit_graph",m_diskName.data());
mapName="inherit_map";
break;
}
// TODO: make sure curDistance>0
findMaximalDotGraph(m_startNode,m_maxDistance,baseName,thisDir,!isTBRank);
findMaximalDotGraph(m_startNode,m_maxDistance,baseName,
thisDir,!isTBRank,m_graphType==Inheritance);
// run dot to create a .gif image
QCString dotCmd;
......@@ -948,12 +1039,12 @@ void DotGfxUsageGraph::writeGraph(QTextStream &out,
//printf("dot -Timap %s.dot -o %s.map\n",baseName.data(),baseName.data());
out << "<p><center><img src=\"" << baseName << ".gif\" border=\"0\" usemap=\"#"
<< m_startNode->m_label << "_impl_map\"></center>" << endl;
out << "<map name=\"" << m_startNode->m_label << "_impl_map\">" << endl;
<< m_startNode->m_label << "_" << mapName << "\"></center>" << endl;
out << "<map name=\"" << m_startNode->m_label << "_" << mapName << "\">" << endl;
convertMapFile(out,baseName+".map");
out << "</map><p>" << endl;
thisDir.remove(baseName+".dot");
//thisDir.remove(baseName+".dot");
thisDir.remove(baseName+".map");
QDir::setCurrent(oldDir);
......
......@@ -41,9 +41,11 @@ struct EdgeInfo
class DotNode
{
friend class DotGfxHierarchyTable;
friend class DotGfxUsageGraph;
friend class DotClassGraph;
friend class DotInclDepGraph;
friend class DotNodeList;
friend void writeDotGraph(DotNode *root,const QCString &baseName,
bool lrRank,bool renderParents,int distance);
public:
DotNode(int n,const char *lab,const char *url,int distance = 0,bool rootNode=FALSE);
~DotNode();
......@@ -60,14 +62,15 @@ class DotNode
void removeChild(DotNode *n);
void removeParent(DotNode *n);
int number() const { return m_number; }
void write(QTextStream &t,bool topDown,int maxDistance=1000);
void write(QTextStream &t,bool topDown,bool toChildren,int maxDistance=1000);
int m_subgraphId;
void clearWriteFlag();
private:
void colorConnectedNodes(int curColor);
void writeBox(QTextStream &t,bool hasNonReachableChildren);
void writeArrow(QTextStream &t,DotNode *cn,EdgeInfo *ei,bool topDown);
void writeArrow(QTextStream &t,DotNode *cn,EdgeInfo *ei,bool topDown,
bool pointBack=TRUE);
const DotNode *findDocNode() const; // only works for acyclic graphs!
int m_number;
QCString m_label; //!< label text
......@@ -98,22 +101,24 @@ class DotGfxHierarchyTable
DotNodeList *m_rootSubgraphs;
};
class DotGfxUsageGraph
class DotClassGraph
{
public:
DotGfxUsageGraph(ClassDef *cd,bool impl,int maxRecusionDepth=1000);
~DotGfxUsageGraph();
enum GraphType { Interface, Implementation, Inheritance };
DotClassGraph(ClassDef *cd,GraphType t,int maxRecusionDepth=1000);
~DotClassGraph();
bool isTrivial() const;
void writeGraph(QTextStream &t,const char *path,bool TBRank=TRUE);
QCString diskName() const;
private:
void buildGraph(ClassDef *cd,DotNode *n,int level);
void addClass(ClassDef *cd,DotNode *n,int prot,const char *label,int level);
void buildGraph(ClassDef *cd,DotNode *n,int level,bool base);
void addClass(ClassDef *cd,DotNode *n,int prot,const char *label,
int level,const char *templSpec,bool base);
DotNode *m_startNode;
QDict<DotNode> *m_usedNodes;
static int m_curNodeNumber;
bool m_impl;
GraphType m_graphType;
int m_recDepth;
QCString m_diskName;
int m_maxDistance;
......
......@@ -154,7 +154,7 @@ int documentedIncludeFiles;
QTextStream tagFile;
void addMemberDocs(Entry *root,MemberDef *md, const char *funcDecl,
bool over_load);
bool over_load,NamespaceList *nl=0);
const char idMask[] = "[A-Za-z_][A-Za-z_0-9]*";
QCString spaces;
......@@ -195,6 +195,7 @@ void buildGroupList(Entry *root)
gd->addSectionsToDefinition(root->anchors);
groupList.append(gd);
groupDict.insert(root->name,gd);
addGroupToGroups(root,gd);
}
}
EntryListIterator eli(*root->sublist);
......@@ -407,48 +408,6 @@ static bool addNamespace(Entry *root,ClassDef *cd)
return FALSE;
}
static void addClassToGroups(Entry *root,ClassDef *cd)
{
QListIterator<QCString> sli(*root->groups);
QCString *s;
for (;(s=sli.current());++sli)
{
GroupDef *gd=0;
if (!s->isEmpty() && (gd=groupDict[*s]))
{
gd->addClass(cd);
//printf("Compound %s: in group %s\n",cd->name().data(),s->data());
}
}
}
static void addMemberToGroups(Entry *root,MemberDef *md)
{
QListIterator<QCString> sli(*root->groups);
QCString *s;
for (;(s=sli.current());++sli)
{
GroupDef *gd=0;
if (!s->isEmpty() && (gd=groupDict[*s]))
{
GroupDef *mgd = md->groupDef();
if (mgd==0)
{
gd->insertMember(md,root->mGrpId);
md->setGroupDef(gd);
}
else if (mgd!=gd)
{
warn("Warning: Member %s found in multiple groups.!\n"
"The member will be put in group %s, and not in group %s",
md->name().data(),mgd->name().data(),gd->name().data()
);
}
//printf("Member %s: in group %s\n",md->name().data(),s->data());
}
}
}
//----------------------------------------------------------------------
// build a list of all classes mentioned in the documentation
// and all classes that have a documentation block before their definition.
......@@ -689,14 +648,8 @@ void buildNamespaceList(Entry *root)
nd->setBriefDescription(root->brief);
nd->addSectionsToDefinition(root->anchors);
QListIterator<QCString> sli(*root->groups);
QCString *s;
for (;(s=sli.current());++sli)
{
GroupDef *gd=0;
if (!s->isEmpty() && (gd=groupDict[*s]))
gd->addNamespace(nd);
}
//printf("Adding namespace to group\n");
addNamespaceToGroups(root,nd);
bool ambig;
// file definition containing the namespace nd
......@@ -710,6 +663,7 @@ void buildNamespaceList(Entry *root)
// add class to the list
namespaceList.inSort(nd);
namespaceDict.insert(fullName,nd);
}
}
}
......@@ -783,6 +737,39 @@ void findUsingDirectives(Entry *root)
fd->addUsingDirective(usingNd);
}
}
else // unknown namespace, but add it anyway.
{
NamespaceDef *nd=new NamespaceDef(root->name);
nd->setDocumentation(root->doc); // copy docs to definition
nd->setBriefDescription(root->brief);
nd->addSectionsToDefinition(root->anchors);
QListIterator<QCString> sli(*root->groups);
QCString *s;
for (;(s=sli.current());++sli)
{
GroupDef *gd=0;
if (!s->isEmpty() && (gd=groupDict[*s]))
gd->addNamespace(nd);
}
bool ambig;
// file definition containing the namespace nd
FileDef *fd=findFileDef(&inputNameDict,root->fileName,ambig);
// insert the namespace in the file definition
if (fd)
{
fd->insertNamespace(nd);
fd->addUsingDirective(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(root->name,nd);
}
}
}
EntryListIterator eli(*root->sublist);
......@@ -1961,7 +1948,7 @@ void computeMemberReferences()
// over_load is set the standard overload text is added.
void addMemberDocs(Entry *root,MemberDef *md, const char *funcDecl,
bool over_load)
bool over_load,NamespaceList *nl)
{
//printf("addMemberDocs: `%s'::`%s' `%s' funcDecl=`%s'\n",
// root->parent->name.data(),md->name().data(),md->argsString(),funcDecl);
......@@ -1973,7 +1960,9 @@ void addMemberDocs(Entry *root,MemberDef *md, const char *funcDecl,
NamespaceDef *nd=md->getNamespace();
if (matchArguments(md->argumentList(),root->argList,
cd ? cd->name().data() : 0,
nd ? nd->name().data() : 0
nd ? nd->name().data() : 0,
TRUE,
nl
)
)
{
......@@ -2715,10 +2704,16 @@ void findMember(Entry *root,QCString funcDecl,QCString related,bool overloaded,
);
// TODO: match loop for all possible scopes
bool ambig;
FileDef *fd=findFileDef(&inputNameDict,root->fileName,ambig);
// list of namespaces using in the file that this member definition is part of
NamespaceList *nl = fd ? fd->getUsedNamespaces() : 0;
bool matching=
md->isVariable() || md->isTypedef() || // needed for function pointers
(md->argumentList()==0 && root->argList->count()==0) ||
matchArguments(argList, root->argList,className,namespaceName);
matchArguments(argList, root->argList,className,namespaceName,TRUE,nl);
Debug::print(Debug::FindMembers,0,
"6. match results = %d\n",matching);
......@@ -2742,7 +2737,7 @@ void findMember(Entry *root,QCString funcDecl,QCString related,bool overloaded,
{
//printf("addMemberDocs root->inLine=%d md->isInline()=%d\n",
// root->inLine,md->isInline());
addMemberDocs(root,md,funcDecl,overloaded);
addMemberDocs(root,md,funcDecl,overloaded,nl);
count++;
}
}
......@@ -4533,7 +4528,8 @@ int readDir(QFileInfo *fi,
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))
(patList==0 || patternMatch(cfi,patList)) &&
!patternMatch(cfi,exclPatList))
{
totalSize+=cfi->size()+cfi->absFilePath().length()+4;
QCString name=convertToQCString(cfi->fileName());
......@@ -4991,13 +4987,13 @@ int main(int argc,char **argv)
msg("Freeing input...\n");
input.resize(0);
msg("Building group list...\n");
buildGroupList(root);
msg("Building namespace list...\n");
buildNamespaceList(root);
findUsingDirectives(root);
msg("Building group list...\n");
buildGroupList(root);
//msg("Computing group relations...\n");
//computeGroupRelations(root);
......
......@@ -36,7 +36,8 @@ GroupDef::GroupDef(const char *na,const char *t) :
{
fileList = new FileList;
classList = new ClassList;
// groupList = new GroupList;
groupList = new GroupList;
namespaceList = new NamespaceList;
allMemberList = new MemberList;
allMemberDict = new QDict<MemberDef>;
......@@ -57,6 +58,10 @@ GroupDef::~GroupDef()
{
delete fileList;
delete classList;
delete groupList;
delete namespaceList;
delete allMemberList;
delete allMemberDict;
delete memberGroupList;
delete memberGroupDict;
}
......@@ -120,14 +125,18 @@ void GroupDef::insertMember(MemberDef *md,int groupId)
}
}
//void GroupDef::addGroup(const GroupDef *def)
//{
// groupList->append(def);
//}
void GroupDef::addGroup(const GroupDef *def)
{
groupList->append(def);
}
int GroupDef::countMembers() const
{
return fileList->count()+classList->count()+allMemberList->count();
return fileList->count()+
classList->count()+
namespaceList->count()+
groupList->count()+
allMemberList->count();
}
/*! Compute the HTML anchor names for all members in the class */
......@@ -188,6 +197,55 @@ void GroupDef::writeDocumentation(OutputList &ol)
}
ol.endMemberList();
}
if (namespaceList->count()>0)
{
ol.startMemberHeader();
parseText(ol,theTranslator->trNamespaces());
ol.endMemberHeader();
ol.startMemberList();
NamespaceDef *nd=namespaceList->first();
while (nd)
{
ol.startMemberItem(0);
ol.docify("namespace");
ol.insertMemberAlign();
ol.writeObjectLink(nd->getReference(),nd->getOutputFileBase(),0,nd->name());
ol.endMemberItem(FALSE);
if (!nd->briefDescription().isEmpty() && Config::briefMemDescFlag)
{
ol.startMemberDescription();
parseDoc(ol,0,0,nd->briefDescription());
ol.endMemberDescription();
ol.newParagraph();
}
nd=namespaceList->next();
}
ol.endMemberList();
}
if (groupList->count()>0)
{
ol.startMemberHeader();
parseText(ol,theTranslator->trModules());
ol.endMemberHeader();
ol.startMemberList();
GroupDef *gd=groupList->first();
while (gd)
{
ol.startMemberItem(0);
//ol.insertMemberAlign();
ol.writeObjectLink(gd->getReference(),gd->getOutputFileBase(),0,gd->groupTitle());
ol.endMemberItem(FALSE);
if (!gd->briefDescription().isEmpty() && Config::briefMemDescFlag)
{
ol.startMemberDescription();
parseDoc(ol,0,0,gd->briefDescription());
ol.endMemberDescription();
ol.newParagraph();
}
gd=groupList->next();
}
ol.endMemberList();
}
classList->writeDeclaration(ol);
......@@ -303,3 +361,79 @@ void GroupDef::writeDocumentation(OutputList &ol)
endFile(ol);
ol.popGeneratorState();
}
//---- helper functions ------------------------------------------------------
void addClassToGroups(Entry *root,ClassDef *cd)
{
QListIterator<QCString> sli(*root->groups);
QCString *s;
for (;(s=sli.current());++sli)
{
GroupDef *gd=0;
if (!s->isEmpty() && (gd=groupDict[*s]))
{
gd->addClass(cd);
//printf("Compound %s: in group %s\n",cd->name().data(),s->data());
}
}
}
void addNamespaceToGroups(Entry *root,NamespaceDef *nd)
{
//printf("root->groups->count()=%d\n",root->groups->count());
QListIterator<QCString> sli(*root->groups);
QCString *s;
for (;(s=sli.current());++sli)
{
GroupDef *gd=0;
//printf("group `%s'\n",s->data());
if (!s->isEmpty() && (gd=groupDict[*s]))
{
gd->addNamespace(nd);
//printf("Namespace %s: in group %s\n",nd->name().data(),s->data());
}
}
}
void addGroupToGroups(Entry *root,GroupDef *subGroup)
{
QListIterator<QCString> sli(*root->groups);
QCString *s;
for (;(s=sli.current());++sli)
{
GroupDef *gd=0;
if (!s->isEmpty() && (gd=groupDict[*s]))
{
gd->addGroup(subGroup);
}
}
}
void addMemberToGroups(Entry *root,MemberDef *md)
{
QListIterator<QCString> sli(*root->groups);
QCString *s;
for (;(s=sli.current());++sli)
{
GroupDef *gd=0;
if (!s->isEmpty() && (gd=groupDict[*s]))
{
GroupDef *mgd = md->groupDef();
if (mgd==0)
{
gd->insertMember(md,root->mGrpId);
md->setGroupDef(gd);
}
else if (mgd!=gd)
{
warn("Warning: Member %s found in multiple groups.!\n"
"The member will be put in group %s, and not in group %s",
md->name().data(),mgd->name().data(),gd->name().data()
);
}
//printf("Member %s: in group %s\n",md->name().data(),s->data());
}
}
}
......@@ -41,12 +41,12 @@ class GroupDef : public Definition
public:
GroupDef(const char *name,const char *title);
~GroupDef();
//const char *groupFile() const { return fileName; }
QCString getOutputFileBase() 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 addGroup(const GroupDef *def);
void insertMember(MemberDef *def,int groupId);
void addMemberToGroup(MemberDef *def,int groupId);
void writeDocumentation(OutputList &ol);
......@@ -64,13 +64,15 @@ class GroupDef : public Definition
private:
QCString title; // title of the group
QCString 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
FileList *fileList; // list of files in the group
ClassList *classList; // list of classes in the group
NamespaceList *namespaceList; // list of namespaces in the group
GroupList *groupList; // list of sub groups.
MemberList *allMemberList; // list of all members in the group
QDict<MemberDef> *allMemberDict;
// members sorted to type
// members sorted by type
MemberList defineMembers;
MemberList protoMembers;
MemberList typedefMembers;
......@@ -80,7 +82,7 @@ class GroupDef : public Definition
MemberList varMembers;
/* user defined member groups */
MemberGroupList *memberGroupList;
MemberGroupList *memberGroupList; // list of member groups in this group
MemberGroupDict *memberGroupDict;
};
......@@ -95,4 +97,9 @@ class GroupListIterator : public QListIterator<GroupDef>
GroupListIterator(const GroupList &l) : QListIterator<GroupDef>(l) {}
};
void addClassToGroups(Entry *root,ClassDef *cd);
void addNamespaceToGroups(Entry *root,NamespaceDef *nd);
void addGroupToGroups(Entry *root,GroupDef *subGroup);
void addMemberToGroups(Entry *root,MemberDef *md);
#endif
......@@ -784,11 +784,11 @@ void HtmlGenerator::endMemberDoc()
t << "</table>" << endl;
}
void HtmlGenerator::startCollaborationDiagram()
void HtmlGenerator::startDotGraph()
{
}
void HtmlGenerator::endCollaborationDiagram(DotGfxUsageGraph &g)
void HtmlGenerator::endDotGraph(DotClassGraph &g)
{
g.writeGraph(t,Config::htmlOutputDir);
}
......
......@@ -214,8 +214,8 @@ class HtmlGenerator : public OutputGenerator
{ t << "</td></tr>" << endl; }
//static void docifyStatic(QTextStream &t,const char *str);
void startCollaborationDiagram();
void endCollaborationDiagram(DotGfxUsageGraph &g);
void startDotGraph();
void endDotGraph(DotClassGraph &g);
void startInclDepGraph();
void endInclDepGraph(DotInclDepGraph &g);
void writeGraphicalHierarchy(DotGfxHierarchyTable &g);
......
......@@ -1449,6 +1449,7 @@ void writeGroupList(OutputList &ol)
GroupDef *gd;
for (;(gd=gli.current());++gli)
{
//printf("gd->name()=%s #members=%d\n",gd->name().data(),gd->countMembers());
if (gd->countMembers()>0)
{
ol.startDescItem();
......
......@@ -47,22 +47,21 @@ static QCString filterTitle(const char *s)
return result;
}
//static QCString escapeLabelName(const QCString &s)
//{
// QCString 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;
//}
static QCString escapeLabelName(const QCString &s)
{
QCString result;
uint i;
for (i=0;i<s.length();i++)
{
char c=s.at(i);
switch (c)
{
case '%': result+="\\%"; break;
default: result+=c;
}
}
return result;
}
LatexGenerator::LatexGenerator() : OutputGenerator()
......@@ -861,11 +860,11 @@ void LatexGenerator::startMemberDoc(const char *clname,
docify(clname);
t << "}!";
}
t << memname << "@{";
t << escapeLabelName(memname) << "@{";
docify(memname);
t << "}}" << endl;
t << "\\index{" << memname << "@{";
t << "\\index{" << escapeLabelName(memname) << "@{";
docify(memname);
t << "}";
if (clname)
......@@ -921,7 +920,7 @@ void LatexGenerator::addToIndex(const char *s1,const char *s2)
{
if (s1)
{
t << "\\index{" << s1 << "@{";
t << "\\index{" << escapeLabelName(s1) << "@{";
docify(s1);
t << "}";
if (s2)
......
......@@ -211,8 +211,8 @@ class LatexGenerator : public OutputGenerator
//static void docifyStatic(QTextStream &t,const char *str);
void startCollaborationDiagram() {}
void endCollaborationDiagram(DotGfxUsageGraph &) {}
void startDotGraph() {}
void endDotGraph(DotClassGraph &) {}
void startInclDepGraph() {}
void endInclDepGraph(DotInclDepGraph &) {}
void writeGraphicalHierarchy(DotGfxHierarchyTable &) {}
......
......@@ -197,8 +197,8 @@ class ManGenerator : public OutputGenerator
void startDescTableData() { }
void endDescTableData() {}
void startCollaborationDiagram() {}
void endCollaborationDiagram(DotGfxUsageGraph &) {}
void startDotGraph() {}
void endDotGraph(DotClassGraph &) {}
void startInclDepGraph() {}
void endInclDepGraph(DotInclDepGraph &) {}
void writeGraphicalHierarchy(DotGfxHierarchyTable &) {}
......
......@@ -104,7 +104,8 @@ static void writeDefArgumentList(OutputList &ol,ClassDef *cd,
bool first=TRUE;
while (a)
{
ol.startParameter(first); first=FALSE;
if (!md->isDefine()) ol.startParameter(first); else ol.docify(" ");
first=FALSE;
QRegExp re(")(");
int vp;
if (!a->attrib.isEmpty()) // argument has an IDL attribute
......@@ -154,7 +155,7 @@ static void writeDefArgumentList(OutputList &ol,ClassDef *cd,
if (a)
{
ol.docify(", "); // there are more arguments
ol.endParameter(FALSE);
if (!md->isDefine()) ol.endParameter(FALSE);
}
}
ol.pushGeneratorState();
......@@ -1004,7 +1005,7 @@ void MemberDef::writeDocumentation(MemberList *ml,OutputList &ol,
ol.docify("]");
ol.endTypewriter();
}
ol.endParameter(TRUE);
if (!isDefine()) ol.endParameter(TRUE);
ol.endMemberDoc();
ol.endDoxyAnchor();
ol.startIndent();
......@@ -1300,11 +1301,11 @@ void MemberDef::writeDocumentation(MemberList *ml,OutputList &ol,
void MemberDef::warnIfUndocumented()
{
//if (memberGroup) return;
if (memberGroup) return;
ClassDef *cd = memberClass();
NamespaceDef *nd = getNamespace();
FileDef *fd = getFileDef();
GroupDef *gd = groupDef();
GroupDef *gd = groupDef();
Definition *d=0;
const char *t=0;
if (cd)
......
......@@ -119,67 +119,7 @@ void MemberList::countDocMembers()
(Config::extractAllFlag || md->detailsAreVisible())
)
{
static QRegExp r("@[0-9]+");
int dummy;
switch(md->memberType())
{
case MemberDef::Enumeration:
if (r.match(md->name(),0,&dummy)==-1)
{
m_count++;
}
break;
case MemberDef::EnumValue:
{
MemberDef *scope;
scope=md->getEnumScope();
if (scope && r.match(scope->name(),0,&dummy)!=-1)
m_count++;
}
break;
default:
m_count++;
break;
}
// 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++;
// }
if (md->memberType()!=MemberDef::EnumValue) m_count++;
}
md=next();
}
......
......@@ -26,7 +26,7 @@
#include "index.h"
class ClassDiagram;
class DotGfxUsageGraph;
class DotClassGraph;
class DotInclDepGraph;
class DotGfxHierarchyTable;
......@@ -200,8 +200,8 @@ class OutputGenerator
virtual void startDescTableData() = 0;
virtual void endDescTableData() = 0;
virtual void startCollaborationDiagram() = 0;
virtual void endCollaborationDiagram(DotGfxUsageGraph &g) = 0;
virtual void startDotGraph() = 0;
virtual void endDotGraph(DotClassGraph &g) = 0;
virtual void startInclDepGraph() = 0;
virtual void endInclDepGraph(DotInclDepGraph &g) = 0;
virtual void writeGraphicalHierarchy(DotGfxHierarchyTable &g) = 0;
......
......@@ -257,7 +257,7 @@ void OutputList::forall(void (OutputGenerator::*func)(a1,a2,a3,a4),a1,a2,a3,a4)
FORALL1(const char *a1,a1)
FORALL1(char a1,a1)
FORALL1(int a1,a1)
FORALL1(DotGfxUsageGraph &a1,a1)
FORALL1(DotClassGraph &a1,a1)
FORALL1(DotInclDepGraph &a1,a1)
FORALL1(DotGfxHierarchyTable &a1,a1)
#if defined(HAS_BOOL_TYPE)
......
......@@ -33,7 +33,7 @@
void forall(void (OutputGenerator::*func)(arg1,arg2,arg3,arg4),arg1,arg2,arg3,arg4)
class ClassDiagram;
class DotGfxUsageGraph;
class DotClassGraph;
class DotInclDepGraph;
class DotGfxHierarchyTable;
......@@ -347,10 +347,10 @@ class OutputList
{ forall(&OutputGenerator::startDescTableData); }
void endDescTableData()
{ forall(&OutputGenerator::endDescTableData); }
void startCollaborationDiagram()
{ forall(&OutputGenerator::startCollaborationDiagram); }
void endCollaborationDiagram(DotGfxUsageGraph &g)
{ forall(&OutputGenerator::endCollaborationDiagram,g); }
void startDotGraph()
{ forall(&OutputGenerator::startDotGraph); }
void endDotGraph(DotClassGraph &g)
{ forall(&OutputGenerator::endDotGraph,g); }
void startInclDepGraph()
{ forall(&OutputGenerator::startInclDepGraph); }
void endInclDepGraph(DotInclDepGraph &g)
......@@ -383,7 +383,7 @@ class OutputList
FORALLPROTO1(char);
FORALLPROTO1(IndexSections);
FORALLPROTO1(int);
FORALLPROTO1(DotGfxUsageGraph &);
FORALLPROTO1(DotClassGraph &);
FORALLPROTO1(DotInclDepGraph &);
FORALLPROTO1(DotGfxHierarchyTable &);
#if defined(HAS_BOOL_TYPE)
......
......@@ -1927,11 +1927,11 @@ static bool PreProcessFile(QDir &d,QCString &infName, QTextStream &t, bool bIncl
return TRUE;
}
void RTFGenerator::startCollaborationDiagram()
void RTFGenerator::startDotGraph()
{
}
void RTFGenerator::endCollaborationDiagram(DotGfxUsageGraph &g)
void RTFGenerator::endDotGraph(DotClassGraph &g)
{
newParagraph();
t <<"{\\comment This would be an image map..." << endl;
......
......@@ -191,8 +191,8 @@ class RTFGenerator : public OutputGenerator
void startDescTableData();
void endDescTableData();
void startCollaborationDiagram();
void endCollaborationDiagram(DotGfxUsageGraph &);
void startDotGraph();
void endDotGraph(DotClassGraph &);
void startInclDepGraph();
void endInclDepGraph(DotInclDepGraph &);
void writeGraphicalHierarchy(DotGfxHierarchyTable &) {}
......
......@@ -830,7 +830,7 @@ static QCString findAndCopyImage(const char *fileName,ImageTypes type)
if (result.left(5)!="http:")
{
warn("Warning: image file %s is not found in IMAGE_PATH: "
"assuming external image. ",fileName);
"assuming external image.\n",fileName);
}
}
return result;
......@@ -877,7 +877,7 @@ 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\~\:\@\#\.\-\+\/]+
URLMASK [a-z_A-Z0-9\~\:\?\@\#\.\-\+\/]+
NONTERM [\{\}\[\]\`\~\@\|\-\+\#\$\/\\\!\%\^\&\*()a-z_A-Z<>0-9]
WORD ({NONTERM}+([^\n\t ]*{NONTERM}+)?)|("\""[^\n\"]"\"")
ATTR ({B}+[^>\n]*)?
......@@ -1125,6 +1125,9 @@ DOCPARAM ([a-z_A-Z0-9:\.\-]+)|("\"".*"\"")
<DocScan>^{B}*(("//"{B}*)?)"*"*{B}*"-"{B}+ { /* found list item marker */
addListItemMarker(yytext);
}
<DocScan>\n{B}*"-" {
addListItemMarker(yytext+1);
}
<DocScan>"<!--" { BEGIN(DocSkipHtmlComment); }
<DocSkipHtmlComment>"--"[!]?">" { BEGIN(DocScan); }
<DocSkipHtmlComment>.
......@@ -3970,6 +3973,9 @@ DOCPARAM ([a-z_A-Z0-9:\.\-]+)|("\"".*"\"")
current->brief+=' ';
lineCount();
}
<JavaDoc>".\\"/[ \t\r\n] {
current->brief+=".";
}
<JavaDoc>"."[ \t\r\n] {
lineCount();
current->brief+=".";
......
......@@ -946,7 +946,8 @@ static void trimNamespaceScope(QCString &t1,QCString &t2)
// stored in the list should be equal.
bool matchArguments(ArgumentList *srcAl,ArgumentList *dstAl,
const char *cl,const char *ns,bool checkCV)
const char *cl,const char *ns,bool checkCV,
NamespaceList *usingList)
{
QCString className=cl;
QCString namespaceName=ns;
......@@ -1048,9 +1049,18 @@ bool matchArguments(ArgumentList *srcAl,ArgumentList *dstAl,
srcAType=trimScope(namespaceName,srcAType);
dstAType=trimScope(namespaceName,dstAType);
}
if (usingList && usingList->count()>0)
{
NamespaceListIterator nli(*usingList);
NamespaceDef *nd;
for (;(nd=nli.current());++nli)
{
srcAType=trimScope(nd->name(),srcAType);
dstAType=trimScope(nd->name(),dstAType);
}
}
//printf("srcAType=%s dstAType=%s\n",srcAType.data(),dstAType.data());
//printf("`%s' <=> `%s'\n",srcAType.data(),dstAType.data());
uint srcPos=0,dstPos=0;
bool equal=TRUE;
while (srcPos<srcAType.length() && dstPos<dstAType.length() && equal)
......@@ -1201,6 +1211,7 @@ void mergeArguments(ArgumentList *srcAl,ArgumentList *dstAl)
// 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
......
......@@ -35,6 +35,7 @@ class ExampleList;
class ClassList;
class BaseClassList;
class GroupDef;
class NamespaceList;
extern void setAnchors(char id,MemberList *ml,int groupId=-1);
extern QCString fileToString(const char *name);
......@@ -53,7 +54,8 @@ extern bool generateLink(OutputList &ol,const char *,
extern void generateFileRef(OutputList &ol,const char *,
const char *linkTxt=0);
extern bool matchArguments(ArgumentList *,ArgumentList *,
const char *cl=0,const char *ns=0,bool checkCV=TRUE);
const char *cl=0,const char *ns=0,bool checkCV=TRUE,
NamespaceList *usingList=0);
extern void mergeArguments(ArgumentList *,ArgumentList *);
extern QCString substituteClassNames(const QCString &s);
extern QCString convertSlashes(const QCString &s,bool dots=FALSE);
......
......@@ -11,7 +11,7 @@ TMAKE_CC = cl
TMAKE_CFLAGS = -nologo
TMAKE_CFLAGS_WARN_ON = -W3
TMAKE_CFLAGS_WARN_OFF = -W0
TMAKE_CFLAGS_RELEASE = -O1
TMAKE_CFLAGS_RELEASE = -O2
TMAKE_CFLAGS_DEBUG = -Zi
TMAKE_CFLAGS_MT = -MT
TMAKE_CFLAGS_MT_DBG = -MTd
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment