diff options
56 files changed, 2717 insertions, 252 deletions
@@ -3,4 +3,4 @@ DOXYGEN Version 1.2.0 Please read the installation section of the manual for instructions. -------- -Dimitri van Heesch (23 July 2000) +Dimitri van Heesch (30 July 2000) diff --git a/Makefile.in b/Makefile.in index 2d2458d..95fc3ae 100644 --- a/Makefile.in +++ b/Makefile.in @@ -8,6 +8,7 @@ clean: FORCE cd src ; $(MAKE) clean cd addon/configgen ; $(MAKE) clean cd addon/doxywizard ; $(MAKE) clean + cd addon/xmlread ; $(MAKE) clean -rm -f bin/doxy* -rm -f objects/*.o @@ -32,11 +33,13 @@ distclean: clean -rm -f addon/configgen/obj/*.o -rm -f addon/doxywizard/obj/*.o -rm -f addon/doxywizard/moc/moc_* + -rm -f addon/xmlread/xmlread.pro + -rm -f addon/xmlread/Makefile addon/xmlread/Makefile.xmlread + -rm -f addon/xmlread/*.o install: doxywizard_install $(INSTTOOL) -d $(INSTALL)/bin $(INSTTOOL) -d $(INSTALL)/doc/doxygen - $(INSTTOOL) -d $(INSTALL)/doc/doxygen $(INSTTOOL) -m 755 bin/doxygen $(INSTALL)/bin $(INSTTOOL) -m 755 bin/doxytag $(INSTALL)/bin $(INSTTOOL) -m 755 bin/doxysearch $(INSTALL)/bin @@ -7,4 +7,4 @@ The latest version of doxygen can be obtained at Enjoy, -Dimitri van Heesch (23 July 2000) +Dimitri van Heesch (30 July 2000) diff --git a/addon/configgen/config_templ.h b/addon/configgen/config_templ.h index f895bab..0d5ac13 100644 --- a/addon/configgen/config_templ.h +++ b/addon/configgen/config_templ.h @@ -1,6 +1,6 @@ /****************************************************************************** * - * $Id$ + * * * Copyright (C) 1997-2000 by Dimitri van Heesch. * diff --git a/addon/configgen/config_templ.l b/addon/configgen/config_templ.l index 6ba22a6..ff570de 100644 --- a/addon/configgen/config_templ.l +++ b/addon/configgen/config_templ.l @@ -1,6 +1,6 @@ /****************************************************************************** * - * $Id$ + * * * Copyright (C) 1997-2000 by Dimitri van Heesch. * diff --git a/addon/configgen/configgen.cpp b/addon/configgen/configgen.cpp index 6521c65..3fd3c1b 100644 --- a/addon/configgen/configgen.cpp +++ b/addon/configgen/configgen.cpp @@ -999,6 +999,22 @@ void init() "The ENABLE_SECTIONS tag can be used to enable conditional \n" "documentation sections, marked by \\if sectionname ... \\endif. \n" ); + ConfigBool::add( "generateTodoList", + "GENERATE_TODOLIST", + "TRUE", + "do we want a todo list?", + "The GENERATE_TODOLIST tag can be used to enable (YES) or \n" + "disable (NO) the todo list. This list is created by putting \\todo \n" + "commands in the documentation.\n" + ); + ConfigBool::add( "generateTestList", + "GENERATE_TESTLIST", + "TRUE", + "do we want a test list?", + "The GENERATE_TESTLIST tag can be used to enable (YES) or \n" + "disable (NO) the test list. This list is created by putting \\test \n" + "commands in the documentation.\n" + ); //----------------------------------------------------------------------------------------------- ConfigInfo::add( "Messages","configuration options related to warning and progress messages"); //----------------------------------------------------------------------------------------------- @@ -1293,6 +1309,15 @@ void init() "This makes the output suitable for online browsing using a pdf viewer. \n" ); addDependency("pdfHyperFlag","generateLatex"); + ConfigBool::add( "usePDFLatexFlag", + "USE_PDFLATEX", + "FALSE", + "use pdflatex instead of plain latex", + "If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of \n" + "plain latex in the generated Makefile. Set this option to YES to get a \n" + "higher quality PDF documentation. \n" + ); + addDependency("usePDFLatexFlag","generateLatex"); ConfigBool::add( "latexBatchModeFlag", "LATEX_BATCHMODE", "FALSE", @@ -1384,6 +1409,18 @@ void init() ); addDependency("manExtension","generateMan"); //----------------------------------------------------------------------------------------------- + ConfigInfo::add( "XML","configuration options related to the XML output"); + //----------------------------------------------------------------------------------------------- + ConfigBool::add( "generateXML", + "GENERATE_XML", + "FALSE", + "generate XML output", + "If the GENERATE_XML tag is set to YES Doxygen will \n" + "generate an XML file that captures the structure of \n" + "the code including all documentation. Warning: This feature \n" + "is still experimental and very incomplete.\n" + ); + //----------------------------------------------------------------------------------------------- ConfigInfo::add( "Preprocessor","Configuration options related to the preprocessor "); //----------------------------------------------------------------------------------------------- ConfigBool::add( "preprocessingFlag", diff --git a/addon/configgen/qtbc.h b/addon/configgen/qtbc.h index d03672f..570bf93 100644 --- a/addon/configgen/qtbc.h +++ b/addon/configgen/qtbc.h @@ -1,6 +1,6 @@ /****************************************************************************** * - * $Id$ + * * * Copyright (C) 1997-2000 by Dimitri van Heesch. * diff --git a/addon/xmlread/Doxyfile b/addon/xmlread/Doxyfile new file mode 100644 index 0000000..fa17d6f --- /dev/null +++ b/addon/xmlread/Doxyfile @@ -0,0 +1,142 @@ +# Doxyfile 1.2.0 + +#--------------------------------------------------------------------------- +# General configuration options +#--------------------------------------------------------------------------- +PROJECT_NAME = xmlread +PROJECT_NUMBER = +OUTPUT_DIRECTORY = doc +OUTPUT_LANGUAGE = English +DISABLE_INDEX = NO +EXTRACT_ALL = NO +EXTRACT_PRIVATE = NO +EXTRACT_STATIC = NO +HIDE_UNDOC_MEMBERS = NO +HIDE_UNDOC_CLASSES = YES +BRIEF_MEMBER_DESC = YES +REPEAT_BRIEF = YES +ALWAYS_DETAILED_SEC = NO +FULL_PATH_NAMES = NO +STRIP_FROM_PATH = +INTERNAL_DOCS = NO +CLASS_DIAGRAMS = YES +SOURCE_BROWSER = YES +INLINE_SOURCES = NO +STRIP_CODE_COMMENTS = YES +CASE_SENSE_NAMES = YES +HIDE_SCOPE_NAMES = NO +VERBATIM_HEADERS = YES +SHOW_INCLUDE_FILES = YES +JAVADOC_AUTOBRIEF = YES +INHERIT_DOCS = YES +INLINE_INFO = YES +SORT_MEMBER_DOCS = YES +TAB_SIZE = 8 +ENABLED_SECTIONS = +GENERATE_TODOLIST = YES +GENERATE_TESTLIST = YES +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- +QUIET = NO +WARNINGS = YES +WARN_IF_UNDOCUMENTED = YES +WARN_FORMAT = "$file:$line: $text" +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- +INPUT = . +FILE_PATTERNS = *.h *.cpp +RECURSIVE = NO +EXCLUDE = +EXCLUDE_PATTERNS = +EXAMPLE_PATH = +EXAMPLE_PATTERNS = +IMAGE_PATH = +INPUT_FILTER = +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- +ALPHABETICAL_INDEX = NO +COLS_IN_ALPHA_INDEX = 5 +IGNORE_PREFIX = +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- +GENERATE_HTML = YES +HTML_OUTPUT = html +HTML_HEADER = +HTML_FOOTER = +HTML_STYLESHEET = +HTML_ALIGN_MEMBERS = YES +GENERATE_HTMLHELP = NO +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- +GENERATE_LATEX = NO +LATEX_OUTPUT = latex +COMPACT_LATEX = NO +PAPER_TYPE = a4wide +EXTRA_PACKAGES = +LATEX_HEADER = +PDF_HYPERLINKS = NO +USE_PDFLATEX = NO +LATEX_BATCHMODE = NO +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- +GENERATE_RTF = NO +RTF_OUTPUT = rtf +COMPACT_RTF = NO +RTF_HYPERLINKS = NO +RTF_STYLESHEET_FILE = +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- +GENERATE_MAN = NO +MAN_OUTPUT = man +MAN_EXTENSION = .3 +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- +GENERATE_XML = YES +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- +ENABLE_PREPROCESSING = YES +MACRO_EXPANSION = NO +EXPAND_ONLY_PREDEF = NO +SEARCH_INCLUDES = YES +INCLUDE_PATH = +INCLUDE_FILE_PATTERNS = +PREDEFINED = +EXPAND_AS_DEFINED = +#--------------------------------------------------------------------------- +# Configuration::addtions related to external references +#--------------------------------------------------------------------------- +TAGFILES = +GENERATE_TAGFILE = +ALLEXTERNALS = NO +PERL_PATH = /usr/bin/perl +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- +HAVE_DOT = YES +CLASS_GRAPH = YES +COLLABORATION_GRAPH = YES +INCLUDE_GRAPH = YES +INCLUDED_BY_GRAPH = NO +GRAPHICAL_HIERARCHY = YES +DOT_PATH = +MAX_DOT_GRAPH_WIDTH = 1024 +MAX_DOT_GRAPH_HEIGHT = 1024 +#--------------------------------------------------------------------------- +# Configuration::addtions related to the search engine +#--------------------------------------------------------------------------- +SEARCHENGINE = NO +CGI_NAME = search.cgi +CGI_URL = +DOC_URL = +DOC_ABSPATH = +BIN_ABSPATH = /usr/local/bin/ +EXT_DOC_PATHS = diff --git a/addon/xmlread/Makefile.in b/addon/xmlread/Makefile.in new file mode 100644 index 0000000..ae31a26 --- /dev/null +++ b/addon/xmlread/Makefile.in @@ -0,0 +1,12 @@ +all clean depend: Makefile.xmlread + $(MAKE) -f Makefile.xmlread $@ + +distclean: clean + $(RM) -f Makefile.xmlread + +tmake: + $(PERL) $(TMAKE) xmlread.pro >Makefile.xmlread + +Makefile.xmlread: xmlread.pro + $(PERL) $(TMAKE) xmlread.pro >Makefile.xmlread + diff --git a/addon/xmlread/README b/addon/xmlread/README new file mode 100644 index 0000000..104917d --- /dev/null +++ b/addon/xmlread/README @@ -0,0 +1,9 @@ +This is a small utility that is used to test and validate the +XML output generated by doxygen (when GENERATE_XML = YES). + +It uses the Xerces-C XML parser/validator (see http://xml.apache.org) +and expects the environment variable XERCES_ROOT to point to the root +of the Xerces package. + +Currently is reads an XML file, validates it, and prints the class +hierarchy contained in it. diff --git a/addon/xmlread/compounddef.h b/addon/xmlread/compounddef.h new file mode 100644 index 0000000..95f5b84 --- /dev/null +++ b/addon/xmlread/compounddef.h @@ -0,0 +1,186 @@ +#ifndef COMPOUNDDEF_H +#define COMPOUNDDEF_H + +#include "qtbc.h" +#include <qlist.h> +#include <qdict.h> +#include <qstrlist.h> + +/*! Abstract interface for a compound as presented to the user */ +class CompoundDef +{ + public: + /*! Possible compound types */ + enum Type { Unknown_t, Class_t, Struct_t, Union_t, + File_t, Namespace_t, Group_t, Interface_t }; + /*! Destructor */ + virtual ~CompoundDef() {} + + /*! Returns the name of this compound */ + virtual QCString name() const = 0; + /*! Returns the type of this compound */ + virtual Type type() const = 0; + /*! Returns the unique identifier for this compound */ + virtual QCString id() const = 0; + /*! Returns the list of base compounds from which this compound inherits */ + virtual QList<CompoundDef> *baseCompounds() const = 0; + /*! Returns the list of compounds that derive from this one */ + virtual QList<CompoundDef> *derivedCompounds() const = 0; +}; + +/*! Ordered dictionary of abstract compounds. */ +class CompoundSDict : public QList<CompoundDef> +{ + friend class CompoundSDictIterator; + + public: + /*! Create an ordered dictionary. + * \param size The size of the dictionary. Should be a prime number for + * best distribution of elements. + */ + CompoundSDict(int size) + { + m_list = new QList<CompoundDef>; + m_list->setAutoDelete(TRUE); + m_dict = new QDict<CompoundDef>(size); + } + /*! Destroys the dictionary */ + ~CompoundSDict() + { + delete m_list; + delete m_dict; + } + /*! Appends a compound to the dictionary. The element is owned by the + * dictionary. + * \param key The unique key to use to quicky find the item later on. + * \param d The compound to add. + * \sa find() + */ + void append(const char *key,CompoundDef *d) + { + m_list->append(d); + m_dict->insert(key,d); + } + /*! Looks up a compound given its key. + * \param key The key to identify this element. + * \return The requested compound or zero if it cannot be found. + * \sa append() + */ + CompoundDef *find(const char *key) + { + return m_dict->find(key); + } + + private: + QList<CompoundDef> *m_list; + QDict<CompoundDef> *m_dict; +}; + +/*! Simple iterator for CompoundSDict. It iterates in the order the + * element were appended. + */ +class CompoundSDictIterator +{ + public: + /*! Create an iterator given the dictionary. */ + CompoundSDictIterator(const CompoundSDict &dict) + { + m_li = new QListIterator<CompoundDef>(*dict.m_list); + } + /*! Destroys the dictionary */ + ~CompoundSDictIterator() + { + delete m_li; + } + /*! Set the iterator to the first element in the list. + * \return The first compound, or zero if the list was empty. + */ + CompoundDef *toFirst() const + { + return m_li->toFirst(); + } + /*! Returns the current compound */ + CompoundDef *current() const + { + return m_li->current(); + } + /*! Moves the iterator to the next element. + * \return the new "current" element, or zero if the iterator was + * already pointing at the last element. + */ + CompoundDef *operator++() + { + return m_li->operator++(); + } + + private: + QListIterator<CompoundDef> *m_li; +}; + +/*! Concrete compound implementation. Used internally by the sax handlers */ +class CompoundDef_Impl : public CompoundDef +{ + public: + /*! Create an compound implementation object */ + CompoundDef_Impl() + { + m_type = Unknown_t; + m_baseCompounds = new QList<CompoundDef>; + m_derivedCompounds = new QList<CompoundDef>; + } + /*! Destroy the implementation object */ + ~CompoundDef_Impl() + { + delete m_baseCompounds; + delete m_derivedCompounds; + } + + /* implementation of the abstract interface */ + Type type() const { return m_type; } + QCString name() const { return m_name; } + QCString id() const { return m_id; } + QList<CompoundDef> *baseCompounds() const { return m_baseCompounds; } + QList<CompoundDef> *derivedCompounds() const { return m_derivedCompounds; } + + /*! Sets the type of the compound to \a t. */ + void setType(Type t) { m_type = t; } + /*! Sets the name of the compound to \a name. */ + void setName(const char *name) { m_name=name; } + /*! Sets the Id of the compound to \a id. */ + void setId(const char *id) { m_id=id; } + /*! Adds a new reference to the internal base class reference list */ + void addBaseRef(const char *name) { m_baseRefs.append(name); } + /*! Adds a new reference to the internal derived class reference list */ + void addDerivedRef(const char *name) { m_derivedRefs.append(name); } + + /*! Resolve the base and derived compound references. */ + void resolveReferences(CompoundSDict *dict) + { + char *refId; + refId = m_baseRefs.first(); + while (refId) + { + CompoundDef *cd = dict->find(refId); + m_baseCompounds->append(cd); + refId = m_baseRefs.next(); + } + refId = m_derivedRefs.first(); + while (refId) + { + CompoundDef *cd = dict->find(refId); + m_derivedCompounds->append(cd); + refId = m_derivedRefs.next(); + } + } + + private: + Type m_type; + QCString m_name; + QCString m_id; + QStrList m_derivedRefs; + QStrList m_baseRefs; + QList<CompoundDef> *m_baseCompounds; + QList<CompoundDef> *m_derivedCompounds; +}; + +#endif diff --git a/addon/xmlread/main.cpp b/addon/xmlread/main.cpp new file mode 100644 index 0000000..3f607f4 --- /dev/null +++ b/addon/xmlread/main.cpp @@ -0,0 +1,133 @@ +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include <util/PlatformUtils.hpp> +#include <parsers/SAXParser.hpp> +#include "strx.h" +#include "saxhandlers.h" +#include "compounddef.h" + +// --------------------------------------------------------------------------- +// Local data +// +// xmlFile +// The path to the file to parser. Set via command line. +// +// --------------------------------------------------------------------------- +static char* xmlFile = 0; + +// --------------------------------------------------------------------------- +// Local helper methods +// --------------------------------------------------------------------------- +static void usage() +{ + cout << "\nUsage: xmlread file.xml\n" + << " Extracts the class hierarchy from a doxygen generated XML file.\n" + << endl; +} + +// recursively display non-root compounds +static void showDerivedCompounds(QList<CompoundDef> *compoundList,int level) +{ + if (compoundList->count()>0) + { + QListIterator<CompoundDef> cli(*compoundList); + CompoundDef *cd; + for (cli.toFirst();(cd=cli.current());++cli) + { + int i; + for (i=0;i<level;i++) cout << " "; + cout << cd->name() << endl; + showDerivedCompounds(cd->derivedCompounds(),level+1); + } + } +} + +// show compound hierarchy +static void showCompoundHierarchy(CompoundSDict *compounds) +{ + CompoundSDictIterator cdi(*compounds); + CompoundDef *cd; + for (cdi.toFirst();(cd=cdi.current());++cdi) + { + if (cd->type()==CompoundDef::Class_t && + cd->baseCompounds()->count()==0) // root compound + { + cout << cd->name() << endl; + showDerivedCompounds(cd->derivedCompounds(),1); + } + } +} + +// --------------------------------------------------------------------------- +// Program entry point +// --------------------------------------------------------------------------- +int main(int argC, char* argV[]) +{ + // Initialize the XML4C2 system + try + { + XMLPlatformUtils::Initialize(); + } + catch (const XMLException& toCatch) + { + cerr << "Error during initialization! :\n" + << StrX(toCatch.getMessage()) << endl; + return 1; + } + + // Check command line and extract arguments. + if (argC!=2) + { + usage(); + return 1; + } + + // Watch for special case help request + if (strcmp(argV[1], "-?") == 0) + { + usage(); + return 0; + } + + // Assume the argument is a file name + xmlFile = argV[1]; + + // + // Create a SAX validating parser object. + // + SAXParser parser; + parser.setDoValidation(TRUE); + + // Create a compound dictionary, where the results will be stored. + // The size of the dictionary is 1009 entries (should be a prime number) + CompoundSDict compounds(1009); + + // + // Create the handler object and install it as the document and error + // handler for the parser. + // + SaxPass1Handlers handler(&compounds); + parser.setDocumentHandler(&handler); + parser.setErrorHandler(&handler); + + // Parse the file and catch any exceptions that propogate out + try + { + parser.parse(xmlFile); + } + catch (const XMLException& toCatch) + { + cerr << "\nFile not found: '" << xmlFile << "'\n" + << "Exception message is: \n" + << StrX(toCatch.getMessage()) + << "\n" << endl; + return -1; + } + + // Show the class hierarchy that we extracted + showCompoundHierarchy(&compounds); + + return 0; +} + diff --git a/addon/xmlread/qtbc.h b/addon/xmlread/qtbc.h new file mode 100644 index 0000000..0091717 --- /dev/null +++ b/addon/xmlread/qtbc.h @@ -0,0 +1,45 @@ +/****************************************************************************** + * + * + * + * Copyright (C) 1997-2000 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. + * + * Documents produced by Doxygen are derivative works derived from the + * input used in their production; they are not affected by this license. + * + */ + +#ifndef QTBC_H +#define QTBC_H + +/*! This file contains some hacks to make Doxygen work with + * Qt version 2.00 and Qt version 1.xx + */ + +#include <qglobal.h> + +#if QT_VERSION >= 200 + +#include <locale.h> + +#define GCI QCollection::Item + +#include <qcstring.h> +#include <qstring.h> +inline QCString convertToQCString(const QString &s) { return s.latin1(); } + +#else /* QT_VERSION < 200 */ + +#include <qstring.h> +#define QCString QString +inline QCString convertToQCString(const QCString &s) { return s; } + +#endif + +#endif diff --git a/addon/xmlread/saxhandlers.cpp b/addon/xmlread/saxhandlers.cpp new file mode 100644 index 0000000..de8de89 --- /dev/null +++ b/addon/xmlread/saxhandlers.cpp @@ -0,0 +1,185 @@ + +// --------------------------------------------------------------------------- +// Includes +// --------------------------------------------------------------------------- +#include <util/XMLUni.hpp> +#include <sax/AttributeList.hpp> +#include "saxhandlers.h" +#include "strx.h" +#include <iostream.h> + +static void error(const SAXParseException& e) +{ + cerr << "\nError at (file " << StrX(e.getSystemId()) + << ", line " << e.getLineNumber() + << ", char " << e.getColumnNumber() + << "): " << StrX(e.getMessage()) << endl; + exit(1); +} + +static void fatalError(const SAXParseException& e) +{ + cerr << "\nFatal Error at (file " << StrX(e.getSystemId()) + << ", line " << e.getLineNumber() + << ", char " << e.getColumnNumber() + << "): " << StrX(e.getMessage()) << endl; + exit(1); +} + +static void warning(const SAXParseException& e) +{ + cerr << "\nWarning at (file " << StrX(e.getSystemId()) + << ", line " << e.getLineNumber() + << ", char " << e.getColumnNumber() + << "): " << StrX(e.getMessage()) << endl; + exit(1); +} + +// --------------------------------------------------------------------------- +// SaxPass1Handlers: Constructors and Destructor +// --------------------------------------------------------------------------- +SaxPass1Handlers::SaxPass1Handlers(CompoundSDict *comp) : m_compounds(comp) +{ + m_currentCompound = 0; +} + +SaxPass1Handlers::~SaxPass1Handlers() +{ +} + +// --------------------------------------------------------------------------- +// SaxPass1Handlers: Overrides of the SAX ErrorHandler interface +// --------------------------------------------------------------------------- +void SaxPass1Handlers::error(const SAXParseException& e) +{ + ::error(e); +} + +void SaxPass1Handlers::fatalError(const SAXParseException& e) +{ + ::fatalError(e); +} + +void SaxPass1Handlers::warning(const SAXParseException& e) +{ + ::warning(e); +} + +// --------------------------------------------------------------------------- +// SaxPass1Handlers: Overrides of the SAX DocumentHandler interface +// --------------------------------------------------------------------------- +void SaxPass1Handlers::characters(const XMLCh* const chars, + const unsigned int /*length*/ + ) +{ + if (m_charAction==ReadCompoundName) + { + m_compoundName=StrX(chars); + m_charAction=Done; + } +} + +void SaxPass1Handlers::endDocument() +{ + // resolve all references + CompoundSDictIterator cdi(*m_compounds); + CompoundDef *cd; + for (cdi.toFirst();(cd=cdi.current());++cdi) + { + CompoundDef_Impl *impl = dynamic_cast<CompoundDef_Impl*>(cd); + impl->resolveReferences(m_compounds); + } +} + +void SaxPass1Handlers::startElement(const XMLCh* const name, + AttributeList& attributes + ) +{ + QCString sname = StrX(name); + if (sname=="compounddef") + { + m_currentCompound = new CompoundDef_Impl; + unsigned int len = attributes.getLength(),index; + for (index = 0; index < len; index++) + { + QCString attName = StrX(attributes.getName(index)); + QCString attValue = StrX(attributes.getValue(index)); + if (attName == "id") + { + m_currentCompound->setId(attValue); + } + else if (attName=="type") + { + if (attValue=="class") + { + m_currentCompound->setType(CompoundDef::Class_t); + } + else if (attValue=="struct") + { + m_currentCompound->setType(CompoundDef::Struct_t); + } + else if (attValue=="union") + { + m_currentCompound->setType(CompoundDef::Union_t); + } + else if (attValue=="interface") + { + m_currentCompound->setType(CompoundDef::Interface_t); + } + else if (attValue=="file") + { + m_currentCompound->setType(CompoundDef::File_t); + } + else + { + cerr << "Unsupported compound type: " << attValue << "\n"; + } + } + } + } + else if (sname=="compoundname") + { + m_charAction = ReadCompoundName; + } + else if (sname=="basecompoundref") + { + unsigned int len = attributes.getLength(),index; + for (index = 0; index < len; index++) + { + QCString attName = StrX(attributes.getName(index)); + QCString attValue = StrX(attributes.getValue(index)); + if (attName=="idref") + { + m_currentCompound->addBaseRef(attValue); + } + } + } + else if (sname=="derivedcompoundref") + { + unsigned int len = attributes.getLength(),index; + for (index = 0; index < len; index++) + { + QCString attName = StrX(attributes.getName(index)); + QCString attValue = StrX(attributes.getValue(index)); + if (attName=="idref") + { + m_currentCompound->addDerivedRef(attValue); + } + } + } +} + +void SaxPass1Handlers::endElement(const XMLCh* const name) +{ + QCString sname = StrX(name); + if (sname=="compounddef") + { + m_compounds->append(m_currentCompound->id(),m_currentCompound); + m_currentCompound=0; + } + else if (sname=="compoundname") + { + m_currentCompound->setName(m_compoundName); + } +} + diff --git a/addon/xmlread/saxhandlers.h b/addon/xmlread/saxhandlers.h new file mode 100644 index 0000000..c9f38b8 --- /dev/null +++ b/addon/xmlread/saxhandlers.h @@ -0,0 +1,101 @@ +#ifndef _SAXHANDLERS_H +#define _SAXHANDLERS_H + +#include "compounddef.h" +#include <sax/HandlerBase.hpp> + +/*! SAX Handlers used for pass 1. */ +class SaxPass1Handlers : public HandlerBase +{ + public: + // ----------------------------------------------------------------------- + //! @name Constructors + // ----------------------------------------------------------------------- + //@{ + /*! Constructor */ + SaxPass1Handlers(CompoundSDict *comp); + /*! Destructor */ + ~SaxPass1Handlers(); + //@} + + // ----------------------------------------------------------------------- + //! @name Implementations of the SAX DocumentHandler interface + // ----------------------------------------------------------------------- + //@{ + /*! Handler called at the start of the XML document */ + void startDocument() {} + /*! Handler called at the end of the XML document */ + void endDocument(); + /*! Handler called when an element is found in the XML file + * \param name The element's name. + * \param attributes The list of attributes for the element. + */ + void startElement(const XMLCh* const name, AttributeList& attributes); + /*! Handler called when the element of an element is found in the XML file + * \param name The element's name. + */ + void endElement(const XMLCh* const name); + /*! Handler called when a character string is found in the XML file. + * \param chars Zero terminated string of characters. + * \param length The number of characters in the string. + */ + void characters(const XMLCh* const chars, const unsigned int length); + + /*! Handler called when an amount of whitespace is found, that is not + * Part of the text. + */ + void ignorableWhitespace(const XMLCh* const /*chars*/, + const unsigned int /*length*/ + ) {} + + /*! Handler called when a preprocessing intruction is found. + */ + void processingInstruction(const XMLCh* const /*target*/, + const XMLCh* const /*data*/ + ) {} + //@} + + // ----------------------------------------------------------------------- + //! @name Implementations of the SAX ErrorHandler interface + // ----------------------------------------------------------------------- + //@{ + /*! Handler called for a parser warning. */ + void warning(const SAXParseException& exception); + /*! Handler called for a parser error. */ + void error(const SAXParseException& exception); + /*! Handler called for a parser fatal error. */ + void fatalError(const SAXParseException& exception); + //@} + + // ----------------------------------------------------------------------- + //! @name Implementation of the SAX DTDHandler interface + // ----------------------------------------------------------------------- + //@{ + /*! Handler for DTD notation declaration. */ + void notationDecl(const XMLCh* const /*name*/, + const XMLCh* const /*publicId*/, + const XMLCh* const /*systemId*/ + ) {} + + /*! Handler for DTD unparsed entity declaration. */ + void unparsedEntityDecl(const XMLCh* const /*name*/, + const XMLCh* const /*publicId*/, + const XMLCh* const /*systemId*/, + const XMLCh* const /*notationName*/ + ) {} + //@} + + private: + // ----------------------------------------------------------------------- + // Private data members + // + // ----------------------------------------------------------------------- + + enum CharActions { Done, ReadCompoundName }; + CompoundSDict *m_compounds; + CompoundDef_Impl *m_currentCompound; + QCString m_compoundName; + CharActions m_charAction; +}; + +#endif diff --git a/addon/xmlread/strx.h b/addon/xmlread/strx.h new file mode 100644 index 0000000..ee58791 --- /dev/null +++ b/addon/xmlread/strx.h @@ -0,0 +1,24 @@ +#ifndef _STRX_H +#define _STRX_H + +// --------------------------------------------------------------------------- +// Includes for all the program files to see +// --------------------------------------------------------------------------- +#include "qtbc.h" +#include <iostream.h> + +/*! + * This is a simple wrapper class around QCString that lets us do easy + * trancoding of XMLCh data to local code page for display. + */ +class StrX : public QCString +{ + public: + /*! Constructor */ + StrX(const XMLCh* const toTranscode) : + QCString(XMLString::transcode(toTranscode)) {} + /*! Destructor */ + ~StrX() {} +}; + +#endif diff --git a/addon/xmlread/xmlread.pro.in b/addon/xmlread/xmlread.pro.in new file mode 100644 index 0000000..61eec2e --- /dev/null +++ b/addon/xmlread/xmlread.pro.in @@ -0,0 +1,7 @@ +TEMPLATE = app +CONFIG = console qt warn_on debug +HEADERS = saxhandler.h strx.h compounddef.h +SOURCES = main.cpp \ + saxhandlers.cpp +LIBS = -lxerces-c1_1 -L$(XERCES_ROOT) +INCLUDEPATH = $(XERCES_ROOT)/include @@ -374,7 +374,7 @@ TMAKE_CXXFLAGS = -DENGLISH_ONLY EOF fi -f_inmakefiles="Makefile.in src/Makefile.in examples/Makefile.in doc/Makefile.in addon/configgen/Makefile.in addon/doxywizard/Makefile.in" +f_inmakefiles="Makefile.in src/Makefile.in examples/Makefile.in doc/Makefile.in addon/configgen/Makefile.in addon/doxywizard/Makefile.in addon/xmlread/Makefile.in" for i in $f_inmakefiles ; do SRC=$i @@ -390,7 +390,7 @@ EOF if test $i = Makefile.in; then echo "configgen:" >> $DST if test $f_configgen = YES; then - echo " $(MAKE) -C addon/configgen" >> $DST + echo " \$(MAKE) -C addon/configgen" >> $DST fi echo "doxywizard:" >> $DST if test $f_wizard = YES; then @@ -404,7 +404,7 @@ EOF echo " Created $DST from $SRC..." done -f_inprofiles="src/doxygen.pro.in src/doxytag.pro.in src/doxysearch.pro.in addon/configgen/configgen.pro.in addon/doxywizard/doxywizard.pro.in" +f_inprofiles="src/doxygen.pro.in src/doxytag.pro.in src/doxysearch.pro.in addon/configgen/configgen.pro.in addon/doxywizard/doxywizard.pro.in addon/xmlread/xmlread.pro.in" for i in $f_inprofiles ; do SRC=$i diff --git a/doc/commands.doc b/doc/commands.doc index 7791c8b..37d4890 100644 --- a/doc/commands.doc +++ b/doc/commands.doc @@ -113,6 +113,7 @@ documentation: <li> \refitem cmdskipline \skipline <li> \refitem cmdstruct \struct <li> \refitem cmdsubsection \subsection +<li> \refitem cmdtest \test <li> \refitem cmdthrow \throw <li> \refitem cmdtodo \todo <li> \refitem cmdtypedef \typedef @@ -807,7 +808,7 @@ Public/Protected/Private/... section. Synonymous to \\see. - \sa section \ref autolink "\\autolink" for information on how to create links + \sa section \ref autolink "autolink" for information on how to create links to objects. <hr> @@ -821,6 +822,16 @@ Public/Protected/Private/... section. line or some other sectioning command is encountered. <hr> +\subsection cmdtest \test { paragraph describing a test case } + + \addindex \test + Starts a paragraph where a test case can be described. + The description will also add the test case to a separate test list. + The two instances of the description will be cross-referenced. + Each test case in the test list will be preceded by a header that + indicates the origin of the test case. + +<hr> \subsection cmdthrow \throw <exception-object> { exception description } \addindex \throw @@ -830,11 +841,14 @@ Public/Protected/Private/... section. the tag \\throws is a synonym for this tag. <hr> -\subsection cmdtodo \todo ( one line todo description ) +\subsection cmdtodo \todo { paragraph describing what is to be done } \addindex \todo - Adds a TODO item to the documentation. The item will also be added - to a TODO list. Both instances of the item will be cross-referenced. + Starts a paragraph where a TODO item is described. + The description will also add an item to a separate TODO list. + The two instances of the description will be cross-referenced. + Each item in the TODO list will be preceded by a header that + indicates the origin of the item. <hr> \subsection cmdversion \version { version number } @@ -907,7 +921,7 @@ Public/Protected/Private/... section. 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 "\\autolink" for more information on automatically + See section \ref autolink "autolink" for more information on automatically generated links and valid link-objects. \b Note: @@ -1150,7 +1164,7 @@ Public/Protected/Private/... section. \par Note: For nested lists, HTML commands should be used. - Equivalent to \ref cmdli "\\cmdli" + Equivalent to \ref cmdli "\\li" <hr> @@ -1176,7 +1190,7 @@ Public/Protected/Private/... section. will result in the following text:<br><br> ... This function returns \c void and not \c int ... - Equivalent to \ref cmdp "\\cmdp" + Equivalent to \ref cmdp "\\p" <hr> \subsection cmdcode \code @@ -1396,7 +1410,7 @@ Public/Protected/Private/... section. \par Note: For nested lists, HTML commands should be used. - Equivalent to \ref cmdarg "\\cmdarg" + Equivalent to \ref cmdarg "\\arg" <hr> \subsection cmdp \p <word> @@ -1413,7 +1427,7 @@ Public/Protected/Private/... section. This will result in the following text:<br><br> ... the \p x and \p y coordinates are used to ... - Equivalent to \ref cmdc "\\cmdc" + Equivalent to \ref cmdc "\\c" <hr> \subsection cmdverbatim \verbatim diff --git a/doc/doxygen_manual.tex b/doc/doxygen_manual.tex index 4a89d23..6bab05e 100644 --- a/doc/doxygen_manual.tex +++ b/doc/doxygen_manual.tex @@ -20,8 +20,7 @@ \usepackage{doxygen} \usepackage{multicol} \usepackage{times} -\usepackage[backref=true, - pagebackref=true, +\usepackage[pagebackref=true, colorlinks=true, linkcolor=blue ]{hyperref} diff --git a/src/classdef.cpp b/src/classdef.cpp index 8fd8d92..928860a 100644 --- a/src/classdef.cpp +++ b/src/classdef.cpp @@ -33,6 +33,7 @@ #include "example.h" #include "outputlist.h" #include "dot.h" +#include "xml.h" static QCString stripExtension(const char *fName) { @@ -1763,3 +1764,126 @@ void ClassDef::determineIntfUsageRelation() } } #endif + +void ClassDef::generateXMLSection(QTextStream &t,MemberList *ml,const char *type) +{ + if (ml->count()>0) + { + t << " <sectiondef type=\"" << type << "\">" << endl; + t << " <memberlist>" << endl; + MemberListIterator mli(*ml); + MemberDef *md; + for (mli.toFirst();(md=mli.current());++mli) + { + md->generateXML(t,this); + } + t << " </memberlist>" << endl; + t << " </sectiondef>" << endl; + } +} + +void ClassDef::generateXML(QTextStream &t) +{ + t << " <compounddef id=\"" + << getOutputFileBase() << "\" type=\""; + switch(compType) + { + case Class: t << "class"; break; + case Struct: t << "struct"; break; + case Union: t << "union"; break; + default: t << "interface"; break; + } + t << "\">" << endl; + t << " <compoundname>"; + writeXMLString(t,name()); + t << "</compoundname>" << endl; + if (inherits->count()>0) + { + t << " <basecompoundlist>" << endl; + BaseClassListIterator bcli(*inherits); + BaseClassDef *bcd; + for (bcli.toFirst();(bcd=bcli.current());++bcli) + { + t << " <basecompoundref idref=\"" + << bcd->classDef->getOutputFileBase() + << "\" prot=\""; + switch (bcd->prot) + { + case Public: t << "public"; break; + case Protected: t << "protected"; break; + case Private: t << "private"; break; + } + t << "\" virt=\""; + switch(bcd->virt) + { + case Normal: t << "non-virtual"; break; + case Virtual: t << "virtual"; break; + case Pure: t <<"pure-virtual"; break; + } + t << "\"/>" << endl; + } + t << " </basecompoundlist>" << endl; + } + if (inheritedBy->count()>0) + { + t << " <derivedcompoundlist>" << endl; + BaseClassListIterator bcli(*inheritedBy); + BaseClassDef *bcd; + for (bcli.toFirst();(bcd=bcli.current());++bcli) + { + t << " <derivedcompoundref idref=\"" + << bcd->classDef->getOutputFileBase() + << "\" prot=\""; + switch (bcd->prot) + { + case Public: t << "public"; break; + case Protected: t << "protected"; break; + case Private: t << "private"; break; + } + t << "\" virt=\""; + switch(bcd->virt) + { + case Normal: t << "non-virtual"; break; + case Virtual: t << "virtual"; break; + case Pure: t << "pure-virtual"; break; + } + t << "\"/>" << endl; + } + t << " </derivedcompoundlist>" << endl; + } + int numMembers = + pubTypes.count()+pubMembers.count()+pubAttribs.count()+ + pubSlots.count()+signals.count()+pubStaticMembers.count()+ + pubStaticAttribs.count()+proTypes.count()+proMembers.count()+ + proAttribs.count()+proSlots.count()+proStaticMembers.count()+ + proStaticAttribs.count()+priTypes.count()+priMembers.count()+ + priAttribs.count()+priSlots.count()+priStaticMembers.count()+ + priStaticAttribs.count()+friends.count()+related.count(); + if (numMembers>0) + { + t << " <sectionlist>" << endl; + generateXMLSection(t,&pubTypes,"public-type"); + generateXMLSection(t,&pubMembers,"public-func"); + generateXMLSection(t,&pubAttribs,"public-attrib"); + generateXMLSection(t,&pubSlots,"public-slot"); + generateXMLSection(t,&signals,"signal"); + generateXMLSection(t,&pubStaticMembers,"public-static-func"); + generateXMLSection(t,&pubStaticAttribs,"public-static-attrib"); + generateXMLSection(t,&proTypes,"protected-type"); + generateXMLSection(t,&proMembers,"protected-func"); + generateXMLSection(t,&proAttribs,"protected-attrib"); + generateXMLSection(t,&proSlots,"protected-slot"); + generateXMLSection(t,&proStaticMembers,"protected-static-func"); + generateXMLSection(t,&proStaticAttribs,"protected-static-attrib"); + generateXMLSection(t,&priTypes,"private-type"); + generateXMLSection(t,&priMembers,"private-func"); + generateXMLSection(t,&priAttribs,"private-attrib"); + generateXMLSection(t,&priSlots,"private-slot"); + generateXMLSection(t,&priStaticMembers,"private-static-func"); + generateXMLSection(t,&priStaticAttribs,"private-static-attrib"); + generateXMLSection(t,&friends,"signal"); + generateXMLSection(t,&related,"related"); + t << " </sectionlist>" << endl; + } + t << " </compounddef>" << endl; +} diff --git a/src/classdef.h b/src/classdef.h index a52173d..a0a494d 100644 --- a/src/classdef.h +++ b/src/classdef.h @@ -42,6 +42,7 @@ class MemberNameInfoDict; class UsesClassDict; class MemberGroupList; class MemberGroupDict; +class QTextStream; struct IncludeInfo; class ClassDef : public Definition @@ -126,6 +127,9 @@ class ClassDef : public Definition void addMembersToMemberGroup(); void distributeMemberGroupDocumentation(); + + void generateXML(QTextStream &t); + void generateXMLSection(QTextStream &t,MemberList *ml,const char *type); protected: void addUsedInterfaceClasses(MemberDef *md,const char *typeStr); @@ -1506,7 +1506,7 @@ void parseCode(OutputList &ol,const char *className,const QCString &s, g_searchingForBody = FALSE; g_insideBody = FALSE; g_bracketCount = 0; - g_exampleFile = convertSlashes(g_exampleName,TRUE)+"-example"; + g_exampleFile = convertFileName(g_exampleName)+"-example"; g_includeCodeFragment = inlineFragment; startCodeLine(*g_code); g_type.resize(0); diff --git a/src/config.h b/src/config.h index a7c220d..7bd72a7 100644 --- a/src/config.h +++ b/src/config.h @@ -1,4 +1,4 @@ -/* This file was generated by configgen on Fri Jul 14 20:01:34 2000 +/* This file was generated by configgen on Fri Jul 28 19:43:36 2000 * from config_templ.h * * DO NOT EDIT! @@ -67,6 +67,8 @@ struct Config static bool sortMembersFlag; // sort members alphabetically? static int tabSize; // number of spaces in a tab static QStrList sectionFilterList; // list of section filters that are enabled + static bool generateTodoList; // do we want a todo list? + static bool generateTestList; // do we want a test list? static bool quietFlag; // generate progress messages flag static bool warningFlag; // generate warnings flag static bool warningUndocFlag; // generate undocumented warnings @@ -97,6 +99,7 @@ struct Config static QStrList extraPackageList; // list of extra LaTeX packages. static QCString latexHeaderFile; // the name of the personal LaTeX header static bool pdfHyperFlag; // generate latex prepared creating hyperlinked pdfs. + static bool usePDFLatexFlag; // use pdflatex instead of plain latex static bool latexBatchModeFlag; // continue after latex errors? static bool generateRTF; // generate RTF flag static QCString rtfOutputDir; // the directory to put the RTF files @@ -106,6 +109,7 @@ struct Config static bool generateMan; // generate Man pages static QCString manOutputDir; // the directory to put the man pages static QCString manExtension; // extension the man page files + static bool generateXML; // generate XML output static bool preprocessingFlag; // enable preprocessing static bool macroExpansionFlag; // expand macros in the source. static bool onlyPredefinedFlag; // expand only predefined macros diff --git a/src/config.l b/src/config.l index 8c864ff..06521d3 100644 --- a/src/config.l +++ b/src/config.l @@ -1,4 +1,4 @@ -/* This file was generated by configgen on Fri Jul 14 20:01:34 2000 +/* This file was generated by configgen on Fri Jul 28 19:43:36 2000 * from config_templ.l * * DO NOT EDIT! @@ -102,6 +102,8 @@ bool Config::inlineInfoFlag = TRUE; bool Config::sortMembersFlag = TRUE; int Config::tabSize = 8; QStrList Config::sectionFilterList; +bool Config::generateTodoList = TRUE; +bool Config::generateTestList = TRUE; bool Config::quietFlag = FALSE; bool Config::warningFlag = TRUE; bool Config::warningUndocFlag = TRUE; @@ -132,6 +134,7 @@ QCString Config::paperType = "a4wide"; QStrList Config::extraPackageList; QCString Config::latexHeaderFile; bool Config::pdfHyperFlag = FALSE; +bool Config::usePDFLatexFlag = FALSE; bool Config::latexBatchModeFlag = FALSE; bool Config::generateRTF = TRUE; QCString Config::rtfOutputDir = "rtf"; @@ -141,6 +144,7 @@ QCString Config::rtfStylesheetFile; bool Config::generateMan = TRUE; QCString Config::manOutputDir = "man"; QCString Config::manExtension = ".3"; +bool Config::generateXML = FALSE; bool Config::preprocessingFlag = TRUE; bool Config::macroExpansionFlag = FALSE; bool Config::onlyPredefinedFlag = FALSE; @@ -251,6 +255,8 @@ static int yyread(char *buf,int max_size) <Start>"SORT_MEMBER_DOCS"[ \t]*"=" { BEGIN(GetBool); b=&Config::sortMembersFlag; } <Start>"TAB_SIZE"[ \t]*"=" { BEGIN(GetString); s=&tabSizeString; s->resize(0); } <Start>"ENABLED_SECTIONS"[ \t]*"=" { BEGIN(GetStrList); l=&Config::sectionFilterList; l->clear(); elemStr=""; } +<Start>"GENERATE_TODOLIST"[ \t]*"=" { BEGIN(GetBool); b=&Config::generateTodoList; } +<Start>"GENERATE_TESTLIST"[ \t]*"=" { BEGIN(GetBool); b=&Config::generateTestList; } <Start>"QUIET"[ \t]*"=" { BEGIN(GetBool); b=&Config::quietFlag; } <Start>"WARNINGS"[ \t]*"=" { BEGIN(GetBool); b=&Config::warningFlag; } <Start>"WARN_IF_UNDOCUMENTED"[ \t]*"=" { BEGIN(GetBool); b=&Config::warningUndocFlag; } @@ -281,6 +287,7 @@ static int yyread(char *buf,int max_size) <Start>"EXTRA_PACKAGES"[ \t]*"=" { BEGIN(GetStrList); l=&Config::extraPackageList; l->clear(); elemStr=""; } <Start>"LATEX_HEADER"[ \t]*"=" { BEGIN(GetString); s=&Config::latexHeaderFile; s->resize(0); } <Start>"PDF_HYPERLINKS"[ \t]*"=" { BEGIN(GetBool); b=&Config::pdfHyperFlag; } +<Start>"USE_PDFLATEX"[ \t]*"=" { BEGIN(GetBool); b=&Config::usePDFLatexFlag; } <Start>"LATEX_BATCHMODE"[ \t]*"=" { BEGIN(GetBool); b=&Config::latexBatchModeFlag; } <Start>"GENERATE_RTF"[ \t]*"=" { BEGIN(GetBool); b=&Config::generateRTF; } <Start>"RTF_OUTPUT"[ \t]*"=" { BEGIN(GetString); s=&Config::rtfOutputDir; s->resize(0); } @@ -290,6 +297,7 @@ static int yyread(char *buf,int max_size) <Start>"GENERATE_MAN"[ \t]*"=" { BEGIN(GetBool); b=&Config::generateMan; } <Start>"MAN_OUTPUT"[ \t]*"=" { BEGIN(GetString); s=&Config::manOutputDir; s->resize(0); } <Start>"MAN_EXTENSION"[ \t]*"=" { BEGIN(GetString); s=&Config::manExtension; s->resize(0); } +<Start>"GENERATE_XML"[ \t]*"=" { BEGIN(GetBool); b=&Config::generateXML; } <Start>"ENABLE_PREPROCESSING"[ \t]*"=" { BEGIN(GetBool); b=&Config::preprocessingFlag; } <Start>"MACRO_EXPANSION"[ \t]*"=" { BEGIN(GetBool); b=&Config::macroExpansionFlag; } <Start>"EXPAND_ONLY_PREDEF"[ \t]*"=" { BEGIN(GetBool); b=&Config::onlyPredefinedFlag; } @@ -452,6 +460,8 @@ void dumpConfig() is=Config::sectionFilterList.next(); } } + printf("generateTodoList=`%d'\n",Config::generateTodoList); + printf("generateTestList=`%d'\n",Config::generateTestList); printf("# configuration options related to warning and progress messages\n"); printf("quietFlag=`%d'\n",Config::quietFlag); printf("warningFlag=`%d'\n",Config::warningFlag); @@ -550,6 +560,7 @@ void dumpConfig() } printf("latexHeaderFile=`%s'\n",Config::latexHeaderFile.data()); printf("pdfHyperFlag=`%d'\n",Config::pdfHyperFlag); + printf("usePDFLatexFlag=`%d'\n",Config::usePDFLatexFlag); printf("latexBatchModeFlag=`%d'\n",Config::latexBatchModeFlag); printf("# configuration options related to the RTF output\n"); printf("generateRTF=`%d'\n",Config::generateRTF); @@ -561,6 +572,8 @@ void dumpConfig() printf("generateMan=`%d'\n",Config::generateMan); printf("manOutputDir=`%s'\n",Config::manOutputDir.data()); printf("manExtension=`%s'\n",Config::manExtension.data()); + printf("# configuration options related to the XML output\n"); + printf("generateXML=`%d'\n",Config::generateXML); printf("# Configuration options related to the preprocessor \n"); printf("preprocessingFlag=`%d'\n",Config::preprocessingFlag); printf("macroExpansionFlag=`%d'\n",Config::macroExpansionFlag); @@ -669,6 +682,8 @@ void Config::init() Config::sortMembersFlag = TRUE; Config::tabSize = 8; Config::sectionFilterList.clear(); + Config::generateTodoList = TRUE; + Config::generateTestList = TRUE; Config::quietFlag = FALSE; Config::warningFlag = TRUE; Config::warningUndocFlag = TRUE; @@ -699,6 +714,7 @@ void Config::init() Config::extraPackageList.clear(); Config::latexHeaderFile.resize(0); Config::pdfHyperFlag = FALSE; + Config::usePDFLatexFlag = FALSE; Config::latexBatchModeFlag = FALSE; Config::generateRTF = TRUE; Config::rtfOutputDir = "rtf"; @@ -708,6 +724,7 @@ void Config::init() Config::generateMan = TRUE; Config::manOutputDir = "man"; Config::manExtension = ".3"; + Config::generateXML = FALSE; Config::preprocessingFlag = TRUE; Config::macroExpansionFlag = FALSE; Config::onlyPredefinedFlag = FALSE; @@ -846,7 +863,7 @@ void writeTemplateConfig(QFile *f,bool sl) t << "# information to generate all constant output in the proper language. \n"; t << "# The default language is English, other supported languages are: \n"; t << "# Dutch, French, Italian, Czech, Swedish, German, Finnish, Japanese, \n"; - t << "# Spanish, Russian, Croatian and Polish.\n"; + t << "# Spanish, Russian, Croatian, Polish, and Portuguese.\n"; t << "\n"; } t << "OUTPUT_LANGUAGE = "; @@ -1146,6 +1163,28 @@ void writeTemplateConfig(QFile *f,bool sl) if (!sl) { t << "\n"; + t << "# The GENERATE_TODOLIST tag can be used to enable (YES) or \n"; + t << "# disable (NO) the todo list. This list is created by putting \\todo \n"; + t << "# commands in the documentation.\n"; + t << "\n"; + } + t << "GENERATE_TODOLIST = "; + writeBoolValue(t,Config::generateTodoList); + t << "\n"; + if (!sl) + { + t << "\n"; + t << "# The GENERATE_TESTLIST tag can be used to enable (YES) or \n"; + t << "# disable (NO) the test list. This list is created by putting \\test \n"; + t << "# commands in the documentation.\n"; + t << "\n"; + } + t << "GENERATE_TESTLIST = "; + writeBoolValue(t,Config::generateTestList); + t << "\n"; + if (!sl) + { + t << "\n"; } t << "#---------------------------------------------------------------------------\n"; t << "# configuration options related to warning and progress messages\n"; @@ -1519,6 +1558,17 @@ void writeTemplateConfig(QFile *f,bool sl) if (!sl) { t << "\n"; + t << "# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of \n"; + t << "# plain latex in the generated Makefile. Set this option to YES to get a \n"; + t << "# higher quality PDF documentation. \n"; + t << "\n"; + } + t << "USE_PDFLATEX = "; + writeBoolValue(t,Config::usePDFLatexFlag); + t << "\n"; + if (!sl) + { + t << "\n"; t << "# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\\\batchmode. \n"; t << "# command to the generated LaTeX files. This will instruct LaTeX to keep \n"; t << "# running if errors occur, instead of asking the user for help. \n"; @@ -1539,9 +1589,8 @@ void writeTemplateConfig(QFile *f,bool sl) { t << "\n"; t << "# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output \n"; - t << "# For now this is experimental and is disabled by default. The RTF output \n"; - t << "# is optimised for Word 97 and may not look too pretty with other readers \n"; - t << "# or editors.\n"; + t << "# The RTF output is optimised for Word 97 and may not look very pretty with \n"; + t << "# other RTF readers or editors.\n"; t << "\n"; } t << "GENERATE_RTF = "; @@ -1637,6 +1686,25 @@ void writeTemplateConfig(QFile *f,bool sl) t << "\n"; } t << "#---------------------------------------------------------------------------\n"; + t << "# configuration options related to the XML output\n"; + t << "#---------------------------------------------------------------------------\n"; + if (!sl) + { + t << "\n"; + t << "# If the GENERATE_XML tag is set to YES Doxygen will \n"; + t << "# generate an XML file that captures the structure of \n"; + t << "# the code including all documentation. Warning: This feature \n"; + t << "# is still experimental and very incomplete.\n"; + t << "\n"; + } + t << "GENERATE_XML = "; + writeBoolValue(t,Config::generateXML); + t << "\n"; + if (!sl) + { + t << "\n"; + } + t << "#---------------------------------------------------------------------------\n"; t << "# Configuration options related to the preprocessor \n"; t << "#---------------------------------------------------------------------------\n"; if (!sl) diff --git a/src/definition.cpp b/src/definition.cpp index 3ce5893..a28228f 100644 --- a/src/definition.cpp +++ b/src/definition.cpp @@ -48,9 +48,9 @@ Definition::~Definition() delete sourceRefDict; } -QCString Definition::nameToFile(const char *name) +QCString Definition::nameToFile(const char *name,bool allowDots) { - return convertNameToFile(name); + return convertNameToFile(name,allowDots); #if 0 QCString result; char c; diff --git a/src/definition.h b/src/definition.h index 701fd03..232e632 100644 --- a/src/definition.h +++ b/src/definition.h @@ -79,7 +79,7 @@ class Definition * The function getOutputFileBase() also uses this function in most cases. * \sa setName(),Definition() */ - QCString nameToFile(const char *name); + QCString nameToFile(const char *name,bool allowDot=FALSE); /*! Add the list of anchors that mark the sections that are found in the * documentation. diff --git a/src/diagram.cpp b/src/diagram.cpp index 80e6d10..3f6dd61 100644 --- a/src/diagram.cpp +++ b/src/diagram.cpp @@ -985,8 +985,6 @@ void ClassDiagram::writeFigure(QTextStream &output,const char *path, output << ":\\begin{figure}[H]\n" "\\begin{center}\n" "\\leavevmode\n"; - //output << "\\setlength{\\epsfysize}{" << realHeight << "cm}\n"; - //output << "\\epsfbox{" << fileName << ".eps}\n" output << "\\includegraphics[height=" << realHeight << "cm]{" << fileName << "}" << endl; output << "\\end{center}\n" @@ -994,7 +992,9 @@ void ClassDiagram::writeFigure(QTextStream &output,const char *path, //printf("writeFigure rows=%d cols=%d\n",rows,cols); - QFile f1((QCString)path+"/"+fileName+".eps"); + QCString epsBaseName=(QCString)path+"/"+fileName; + QCString epsName=epsBaseName+".eps"; + QFile f1(epsName.data()); if (!f1.open(IO_WriteOnly)) { err("Could not open file %s for writing\n",convertToQCString(f1.name()).data()); @@ -1227,6 +1227,19 @@ void ClassDiagram::writeFigure(QTextStream &output,const char *path, 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); + + f1.close(); + if (Config::usePDFLatexFlag) + { + QCString epstopdfCmd(4096); + epstopdfCmd.sprintf("epstopdf \"%s.eps\" -outfile=\"%s.pdf\"", + epsBaseName.data(),epsBaseName.data()); + if (iSystem(epstopdfCmd)!=0) + { + err("Error: Problems running epstopdf. Check your TeX installation!\n"); + return; + } + } } diff --git a/src/dot.cpp b/src/dot.cpp index 02a0b07..ccf991f 100644 --- a/src/dot.cpp +++ b/src/dot.cpp @@ -39,7 +39,7 @@ static const char *edgeColorMap[] = "darkgreen", // Protected "firebrick4", // Private "darkorchid3", // "use" relation - "grey50" // Undocumented + "grey75" // Undocumented }; static const char *edgeStyleMap[] = @@ -319,7 +319,7 @@ void DotNode::writeBox(QTextStream &t, bool hasNonReachableChildren) { const char *labCol = - m_url.isEmpty() ? "grey50" : // non link + m_url.isEmpty() ? "grey75" : // non link ( (hasNonReachableChildren) ? "red" : "black" ); @@ -1141,13 +1141,23 @@ void DotClassGraph::writeGraph(QTextStream &out, QDir::setCurrent(oldDir); return; } + if (Config::usePDFLatexFlag) + { + QCString epstopdfCmd(4096); + epstopdfCmd.sprintf("epstopdf \"%s.eps\" -outfile=\"%s.pdf\"", + baseName.data(),baseName.data()); + if (iSystem(epstopdfCmd)!=0) + { + err("Error: Problems running epstopdf. Check your TeX installation!\n"); + QDir::setCurrent(oldDir); + return; + } + } int maxWidth = 420; /* approx. page width in points */ out << "\\begin{figure}[H]\n" "\\begin{center}\n" "\\leavevmode\n" - //"\\setlength{\\epsfxsize}{" << QMIN(width/2,maxWidth) << "pt}\n" - //"\\epsfbox{" << baseName << ".eps}\n" "\\includegraphics[width=" << QMIN(width/2,maxWidth) << "pt]{" << baseName << "}\n" "\\end{center}\n" @@ -1321,6 +1331,18 @@ void DotInclDepGraph::writeGraph(QTextStream &out, QDir::setCurrent(oldDir); return; } + if (Config::usePDFLatexFlag) + { + QCString epstopdfCmd(4096); + epstopdfCmd.sprintf("epstopdf \"%s.eps\" -outfile=\"%s.pdf\"", + baseName.data(),baseName.data()); + if (iSystem(epstopdfCmd)!=0) + { + err("Error: Problems running epstopdf. Check your TeX installation!\n"); + QDir::setCurrent(oldDir); + return; + } + } int maxWidth = 420; /* approx. page width in points */ out << "\\begin{figure}[H]\n" @@ -1368,7 +1390,7 @@ void generateGraphLegend(const char *path) dotText << " Node12 -> Node7 [dir=back,color=\"firebrick4\",fontsize=10,style=\"solid\",fontname=\"doxfont\"];\n"; dotText << " Node12 [shape=\"box\",label=\"PrivateBase\",fontsize=10,height=0.2,width=0.4,fontname=\"doxfont\",color=\"black\",URL=\"$class_privatebase.html\"];\n"; dotText << " Node13 -> Node7 [dir=back,color=\"midnightblue\",fontsize=10,style=\"solid\",fontname=\"doxfont\"];\n"; - dotText << " Node13 [shape=\"box\",label=\"Undocumented\",fontsize=10,height=0.2,width=0.4,fontname=\"doxfont\",color=\"grey50\"];\n"; + dotText << " Node13 [shape=\"box\",label=\"Undocumented\",fontsize=10,height=0.2,width=0.4,fontname=\"doxfont\",color=\"grey75\"];\n"; dotText << " Node14 -> Node7 [dir=back,color=\"darkorchid3\",fontsize=10,style=\"dashed\",label=\"m_usedClass\",fontname=\"doxfont\"];\n"; dotText << " Node14 [shape=\"box\",label=\"Used\",fontsize=10,height=0.2,width=0.4,fontname=\"doxfont\",color=\"black\",URL=\"$class_used.html\"];\n"; dotText << "}\n"; diff --git a/src/doxygen.cpp b/src/doxygen.cpp index c756ba8..9c6f35c 100644 --- a/src/doxygen.cpp +++ b/src/doxygen.cpp @@ -52,6 +52,8 @@ #include "htmlhelp.h" #include "defargs.h" #include "rtfgen.h" +#include "xml.h" +#include "reflist.h" #if defined(_MSC_VER) || defined(__BORLANDC__) #define popen _popen @@ -170,6 +172,78 @@ const char *getOverloadDocs() //---------------------------------------------------------------------------- +static void addTodoItem(Entry *root,const char *prefix, + const char *name,const char *title=0) +{ + //printf("addTodoItem(%s) todoId=%d\n",name,root->todoId); + if (root->todoId==0 || !Config::generateTodoList) return; + RefItem *item = todoList.getRefItem(root->todoId); + ASSERT(item!=0); + if (item->written) return; + + Entry *page = new Entry; + page->section = Entry::PAGEDOC_SEC; + page->fileName = "generated"; + page->startLine = 1; + page->name = "todo"; + page->args = theTranslator->trTodoList(); + page->doc += "<dl><dt>\\anchor "; + page->doc += item->listAnchor; + page->doc += "\n"; + page->doc += prefix; + page->doc += " \\ref "; + page->doc += name; + page->doc += " \""; + if (title && title[0]!='\0') + page->doc += title; + else + page->doc += name; + page->doc += "\":</dt>\n<dd>"; + page->doc += item->text; + page->doc += "</dd></dl>\n"; + root->addSubEntry(page); + + item->written=TRUE; +} + +//---------------------------------------------------------------------------- + +static void addTestItem(Entry *root,const char *prefix, + const char *name,const char *title=0) +{ + //printf("addTestItem(%s) testId=%d\n",name,root->testId); + if (root->testId==0 || !Config::generateTestList) return; + RefItem *item = testList.getRefItem(root->testId); + ASSERT(item!=0); + if (item->written) return; + + Entry *page = new Entry; + page->section = Entry::PAGEDOC_SEC; + page->fileName = "generated"; + page->startLine = 1; + page->name = "test"; + page->args = theTranslator->trTestList(); + page->doc += "<dl><dt>\\anchor "; + page->doc += item->listAnchor; + page->doc += "\n"; + page->doc += prefix; + page->doc += " \\ref "; + page->doc += name; + page->doc += " \""; + if (title && title[0]!='\0') + page->doc += title; + else + page->doc += name; + page->doc += "\":</dt>\n<dd>"; + page->doc += item->text; + page->doc += "</dd></dl>\n"; + root->addSubEntry(page); + + item->written=TRUE; +} + +//---------------------------------------------------------------------------- + static void buildGroupList(Entry *root) { @@ -195,6 +269,8 @@ static void buildGroupList(Entry *root) groupList.append(gd); groupDict.insert(root->name,gd); addGroupToGroups(root,gd); + addTodoItem(root,"group",gd->name()); + addTestItem(root,"group",gd->name()); } } EntryListIterator eli(*root->sublist); @@ -278,6 +354,8 @@ static void buildFileList(Entry *root) //printf("File %s: in group %s\n",fd->name().data(),s->data()); } } + addTodoItem(root,"file",fd->name()); + addTestItem(root,"file",fd->name()); } } else @@ -507,6 +585,8 @@ static void buildClassList(Entry *root) fd->insertClass(cd); } addClassToGroups(root,cd); + addTodoItem(root,"class",cd->name()); + addTestItem(root,"class",cd->name()); if (!root->subGrouping) cd->setSubGrouping(FALSE); } else // new class @@ -547,6 +627,8 @@ static void buildClassList(Entry *root) if (!root->subGrouping) cd->setSubGrouping(FALSE); addClassToGroups(root,cd); + addTodoItem(root,"class",cd->name()); + addTestItem(root,"class",cd->name()); // see if the class is found inside a namespace bool found=addNamespace(root,cd); @@ -584,6 +666,8 @@ static void buildClassList(Entry *root) // 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()); @@ -656,6 +740,8 @@ static void buildNamespaceList(Entry *root) // insert the namespace in the file definition if (fd) fd->insertNamespace(nd); addNamespaceToGroups(root,nd); + addTodoItem(root,"namespace",nd->name()); + addTestItem(root,"namespace",nd->name()); } else /* if (!root->doc.isEmpty() || !root->brief.isEmpty() || @@ -670,6 +756,8 @@ static void buildNamespaceList(Entry *root) //printf("Adding namespace to group\n"); addNamespaceToGroups(root,nd); + addTodoItem(root,"namespace",nd->name()); + addTestItem(root,"namespace",nd->name()); bool ambig; // file definition containing the namespace nd @@ -792,6 +880,8 @@ static void findUsingDirectives(Entry *root) // add class to the list namespaceList.inSort(nd); namespaceDict.insert(root->name,nd); + addTodoItem(root,"namespace",nd->name()); + addTestItem(root,"namespace",nd->name()); } } } @@ -805,7 +895,7 @@ static void findUsingDirectives(Entry *root) //---------------------------------------------------------------------- -void findUsingDeclarations(Entry *root) +static void findUsingDeclarations(Entry *root) { if (root->section==Entry::USINGDECL_SEC) { @@ -1004,6 +1094,8 @@ static MemberDef *addVariableToClass( // add the member to the class } cd->insertMember(md); + addTodoItem(root,"member",cd->name()+"::"+md->name()); + addTestItem(root,"member",cd->name()+"::"+md->name()); //TODO: insert FileDef instead of filename strings. cd->insertUsedFile(root->fileName); @@ -1089,6 +1181,16 @@ static MemberDef *addVariableToFile( // variable already in the scope { addMemberDocs(root,md,def,0,FALSE); + if (nscope.isEmpty()) + { + addTodoItem(root,"member",md->name()); + addTestItem(root,"member",md->name()); + } + else + { + addTodoItem(root,"member",nscope+"::"+md->name()); + addTestItem(root,"member",nscope+"::"+md->name()); + } return md; } md=mn->next(); @@ -1125,6 +1227,8 @@ static MemberDef *addVariableToFile( { nd->insertMember(md); md->setNamespace(nd); + addTodoItem(root,"member",nd->name()+"::"+md->name()); + addTestItem(root,"member",nd->name()+"::"+md->name()); } else { @@ -1133,6 +1237,8 @@ static MemberDef *addVariableToFile( { fd->insertMember(md); md->setFileDef(fd); + addTodoItem(root,"member",md->name()); + addTestItem(root,"member",md->name()); } } @@ -1526,6 +1632,8 @@ static void buildMemberList(Entry *root) cd->insertMember(md); // add file to list of used files cd->insertUsedFile(root->fileName); + addTodoItem(root,"member",cd->name()+"::"+md->name()); + addTestItem(root,"member",cd->name()+"::"+md->name()); addMemberToGroups(root,md); } @@ -1682,6 +1790,8 @@ static void buildMemberList(Entry *root) { nd->insertMember(md); md->setNamespace(nd); + addTodoItem(root,"member",nd->name()+"::"+md->name()); + addTestItem(root,"member",nd->name()+"::"+md->name()); } else { @@ -1696,6 +1806,8 @@ static void buildMemberList(Entry *root) // add member to the file fd->insertMember(md); md->setFileDef(fd); + addTodoItem(root,"member",md->name()); + addTestItem(root,"member",md->name()); } } @@ -1921,11 +2033,12 @@ static bool findBaseClassRelation(Entry *root,ClassDef *cd, baseClassName.prepend(scopeName.left(scopeOffset)+"::"); } ClassDef *baseClass=getResolvedClass(baseClassName); + //printf("baseClassName=`%s' baseClass=%p\n",baseClassName.data(),baseClass); if (baseClassName!=root->name) // check for base class with the same name, // look in the outer scope for a match { Debug::print( - Debug::Classes,0,"baseClass %s of %s found (%s and %s)\n", + Debug::Classes,0," baseClass %s of %s found (%s and %s)\n", baseClassName.data(), root->name.data(), (bi->prot==Private)?"private":((bi->prot==Protected)?"protected":"public"), @@ -2183,6 +2296,11 @@ static void addMemberDocs(Entry *root, md->setDefinition(fDecl); ClassDef *cd=md->getClassDef(); NamespaceDef *nd=md->getNamespaceDef(); + QCString fullName; + if (cd) fullName = cd->name(); + else if (nd) fullName = nd->name(); + if (!fullName.isEmpty()) fullName+="::"; + fullName+=md->name(); if (al) { mergeArguments(md->argumentList(),al); @@ -2209,6 +2327,8 @@ static void addMemberDocs(Entry *root, doc+=root->doc; } md->setDocumentation(doc); + addTodoItem(root,"member",fullName); + addTestItem(root,"member",fullName); } else { @@ -2256,6 +2376,8 @@ static void addMemberDocs(Entry *root, md->setBodyDef(fd); } + addTodoItem(root,"member",fullName); + addTestItem(root,"member",fullName); } //md->setDefFile(root->fileName); @@ -3131,6 +3253,8 @@ static void findMember(Entry *root,QCString funcDecl,QCString related,bool overl mn->inSort(md); cd->insertMember(md); cd->insertUsedFile(root->fileName); + addTodoItem(root,"member",cd->name()+"::"+md->name()); + addTestItem(root,"member",cd->name()+"::"+md->name()); } } else // unrelated function with the same name as a member @@ -3247,6 +3371,8 @@ static void findMember(Entry *root,QCString funcDecl,QCString related,bool overl mn->inSort(md); cd->insertMember(md); cd->insertUsedFile(root->fileName); + addTodoItem(root,"member",cd->name()+"::"+md->name()); + addTestItem(root,"member",cd->name()+"::"+md->name()); if (newMemberName) { //printf("Adding memberName=%s\n",mn->memberName()); @@ -3482,11 +3608,15 @@ static void findEnums(Entry *root) } nd->insertMember(md); md->setNamespace(nd); + addTodoItem(root,"member",nd->name()+"::"+md->name()); + addTestItem(root,"member",nd->name()+"::"+md->name()); } else if (isGlobal) { md->setDefinition(name); fd->insertMember(md); + addTodoItem(root,"member",md->name()); + addTestItem(root,"member",md->name()); } else if (cd) { @@ -3500,6 +3630,8 @@ static void findEnums(Entry *root) } cd->insertMember(md); cd->insertUsedFile(root->fileName); + addTodoItem(root,"member",cd->name()+"::"+md->name()); + addTestItem(root,"member",cd->name()+"::"+md->name()); } md->setDocumentation(root->doc); md->setBriefDescription(root->brief); @@ -4252,15 +4384,18 @@ static void buildPageList(Entry *root) baseName=baseName.left(baseName.length()-4); else if (baseName.right(5)==".html") baseName=baseName.left(baseName.length()-5); + + QCString title=root->args.stripWhiteSpace(); pi=new PageInfo(root->fileName,root->startLine, - baseName, root->doc, - root->args.stripWhiteSpace()); + baseName, root->doc,title); QCString pageName; if (Config::caseSensitiveNames) pageName=pi->name.copy(); else pageName=pi->name.lower(); setFileNameForSections(root->anchors,pageName); + addTodoItem(root,"page",pageName,title); + addTestItem(root,"page",pageName,title); pageList.append(pi); pageDict.insert(baseName,pi); @@ -4271,7 +4406,7 @@ static void buildPageList(Entry *root) // a page name is a label as well! SectionInfo *si=new SectionInfo( pi->name,pi->title,SectionInfo::Section); - si->fileName=pageName+".html"; + si->fileName=pageName; //printf(" SectionInfo: sec=%p sec->fileName=%s\n",si,si->fileName.data()); //printf("Adding section info %s\n",pi->name.data()); sectionDict.insert(pageName,si); @@ -4279,6 +4414,13 @@ static void buildPageList(Entry *root) } } } + else if (root->section == Entry::MAINPAGEDOC_SEC) + { + QCString title=root->args.stripWhiteSpace(); + if (title.isEmpty()) title=theTranslator->trMainPage(); + addTodoItem(root,"page","index",title); + addTestItem(root,"page","index",title); + } EntryListIterator eli(*root->sublist); Entry *e; for (;(e=eli.current());++eli) @@ -4294,10 +4436,16 @@ static void findMainPage(Entry *root) if (mainPage==0) { //printf("Found main page! \n======\n%s\n=======\n",root->doc.data()); + QCString title=root->args.stripWhiteSpace(); mainPage = new PageInfo(root->fileName,root->startLine, - "index", root->doc, - root->args.stripWhiteSpace()); + "index", root->doc,title); setFileNameForSections(root->anchors,"index"); + + // a page name is a label as well! + SectionInfo *si=new SectionInfo( + mainPage->name,mainPage->title,SectionInfo::Section); + si->fileName="index"; + sectionDict.insert("index",si); } else { @@ -4331,6 +4479,14 @@ static void resolveUserReferences() // si->definition->getOutputFileBase().data()); si->fileName=si->definition->getOutputFileBase().copy(); } + // hack: the items of a todo/test list are all fragments from different files, + // so the resulting section's all have the wrong file name (not from the + // todo/test list, but from the file in which they are defined). We correct this + // here by looking at the generated section labels! + if (si->label.left(5)=="_todo" || si->label.left(5)=="_test") + { + si->fileName=si->label.mid(1,4); // extract "todo" or "test" + } } } @@ -4408,7 +4564,7 @@ static void buildExampleList(Entry *root) PageInfo *pi=new PageInfo(root->fileName,root->startLine, root->name,root->doc,root->args); setFileNameForSections(root->anchors, - convertSlashes(pi->name,TRUE)+"-example" + convertFileName(pi->name)+"-example" ); exampleList.inSort(pi); exampleDict.insert(root->name,pi); @@ -4440,7 +4596,7 @@ static void generateExampleDocs() while (pi) { msg("Generating docs for example %s...\n",pi->name.data()); - QCString n=convertSlashes(pi->name,TRUE)+"-example"; + QCString n=convertFileName(pi->name)+"-example"; startFile(*outputList,n,"Example Documentation"); startTitle(*outputList,n); outputList->docify(pi->name); @@ -5604,12 +5760,6 @@ int main(int argc,char **argv) msg("Building example list...\n"); buildExampleList(root); - msg("Building page list...\n"); - buildPageList(root); - - msg("Search for main page...\n"); - findMainPage(root); - msg("Searching for documented variables...\n"); buildVarList(root); @@ -5636,6 +5786,12 @@ int main(int argc,char **argv) findMemberDocumentation(root); // may introduce new members ! transferRelatedFunctionDocumentation(); + msg("Building page list...\n"); + buildPageList(root); + + msg("Search for main page...\n"); + findMainPage(root); + msg("Freeing entry tree\n"); delete root; @@ -5793,6 +5949,12 @@ int main(int argc,char **argv) writeGraphicalClassHierarchy(*outputList); } + if (Config::generateXML) + { + msg("Generating XML output\n"); + generateXML(); + } + if (formulaList.count()>0 && Config::generateHtml) { msg("Generating bitmaps for formulas in HTML...\n"); @@ -5812,9 +5974,11 @@ int main(int argc,char **argv) HtmlHelp::getInstance()->finalize(); } + if (Config::generateHtml) removeDoxFont(Config::htmlOutputDir); if (Config::generateRTF) removeDoxFont(Config::rtfOutputDir); delete tag; + return 0; } diff --git a/src/doxygen.dtd b/src/doxygen.dtd new file mode 100644 index 0000000..a479ee5 --- /dev/null +++ b/src/doxygen.dtd @@ -0,0 +1,115 @@ +<?xml encoding="ISO-8859-1"?> +<!-- DTD describing the grammar used in doxygen's XML output --> + +<!-- standard character entities --> +<!ENTITY lt "&#60;"> +<!ENTITY gt ">"> +<!ENTITY amp "&#38;"> +<!ENTITY apos "'"> +<!ENTITY quot """> + +<!-- required attributes for compounds --> +<!ENTITY % compound-req.att + 'id ID #REQUIRED + type (group|file|namespace| + class|struct|union| + interface|dispinterface| + valuetype|library) #REQUIRED' +> +<!-- required attributes for references --> +<!ENTITY % ref-req.att 'idref IDREF #REQUIRED' +> +<!-- required attributes for inheritance relations --> +<!ENTITY % inheritcompref-req.att + '%ref-req.att; + prot (public|protected|private) #REQUIRED + virt (non-virtual|virtual) #REQUIRED' +> + +<!-- required attributes for member sections --> +<!ENTITY % sec-req.att 'type (user + |public-type + |public-func + |public-attrib + |public-slot + |public-static-func + |public-static-attrib + |protected-type + |protected-func + |protected-attrib + |protected-slot + |protected-static-func + |protected-static-attrib + |private-type + |private-func + |private-attrib + |private-slot + |private-static-func + |private-static-attrib + |signal + |friend + |related + |define|prototype|typedef|enum|func|var + ) #REQUIRED + ' +> +<!-- required attributes for members --> +<!ENTITY % mem-req.att 'id ID #REQUIRED'> + +<!-- optional attributes for function --> +<!ENTITY % func-opt.att 'virt (virtual|pure-virtual) #IMPLIED'> + +<!-- elements --> +<!ELEMENT doxygen (compoundlist?)> +<!ELEMENT compoundlist (compounddef)+> +<!ELEMENT compounddef (compoundname, + basecompoundlist?, + derivedcompoundlist?, + sectionlist? + ) +> +<!ATTLIST compounddef %compound-req.att;> +<!ELEMENT basecompoundlist (basecompoundref)+> +<!ELEMENT derivedcompoundlist (derivedcompoundref)+> +<!ELEMENT compoundref (#PCDATA)> +<!ATTLIST compoundref %ref-req.att;> +<!ELEMENT memberref (#PCDATA)> +<!ATTLIST memberref %ref-req.att;> +<!ELEMENT basecompoundref EMPTY> +<!ATTLIST basecompoundref %inheritcompref-req.att;> +<!ELEMENT derivedcompoundref EMPTY> +<!ATTLIST derivedcompoundref %inheritcompref-req.att;> +<!ELEMENT sectionlist (sectiondef)+> +<!ELEMENT sectiondef (memberlist)> +<!ATTLIST sectiondef %sec-req.att;> +<!ELEMENT memberlist (functiondef|variabledef|typedef|definedef|enumdef)+> +<!ELEMENT functiondef (type?,name,paramlist)> +<!ATTLIST functiondef %mem-req.att; %func-opt.att;> +<!ELEMENT variabledef (type,name,array?,initializer?)> +<!ATTLIST variabledef %mem-req.att;> +<!ELEMENT typedef (type,name)> +<!ATTLIST typedef %mem-req.att;> +<!ELEMENT definedef (name,defparamlist?,initializer?)> +<!ATTLIST definedef %mem-req.att;> +<!ELEMENT enumdef (name,enumvaluelist)> +<!ATTLIST enumdef %mem-req.att;> +<!ELEMENT slotdef (type,name,paramlist)> +<!ATTLIST slotdef %mem-req.att;> +<!ELEMENT signaldef (type,name,paramlist)> +<!ATTLIST signaldef %mem-req.att;> +<!ELEMENT paramlist (param)*> +<!ELEMENT param (attributes?,type,declname?,defname?,array?,defval?)> +<!ELEMENT defparamlist (defarg)*> +<!ELEMENT defarg (#PCDATA)> +<!ELEMENT enumvaluelist (enumvalue)*> +<!ELEMENT enumvalue (name,initializer?)> +<!ELEMENT name (#PCDATA)> +<!ELEMENT compoundname (#PCDATA)> +<!ELEMENT declname (#PCDATA)> +<!ELEMENT defname (#PCDATA)> +<!ELEMENT type (#PCDATA|memberref|compoundref|compounddef)*> +<!ELEMENT defval (#PCDATA|memberref|compoundref)*> +<!ELEMENT initializer (#PCDATA|memberref|compoundref)*> +<!ELEMENT array (#PCDATA)> +<!ELEMENT attributes (#PCDATA)> + diff --git a/src/doxygen.pro.in b/src/doxygen.pro.in index 81d0817..0fb674e 100644 --- a/src/doxygen.pro.in +++ b/src/doxygen.pro.in @@ -25,7 +25,8 @@ HEADERS = doxygen.h scanner.h classdef.h classlist.h memberdef.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 membergroup.h htmlhelp.h \ - translator_ru.h translator_pl.h dot.h rtfgen.h + translator_ru.h translator_pl.h dot.h rtfgen.h xml.h xml_dtd.h \ + reflist.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 \ @@ -35,7 +36,9 @@ SOURCES = doxygen.cpp scanner.cpp classdef.cpp classlist.cpp memberdef.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 \ - membergroup.cpp htmlhelp.cpp dot.cpp rtfgen.cpp + membergroup.cpp htmlhelp.cpp dot.cpp rtfgen.cpp xml.cpp \ + reflist.cpp win32:INCLUDEPATH += . +win32:LIBS += shell32.lib TARGET = ../bin/doxygen OBJECTS_DIR = ../objects diff --git a/src/doxygen.t b/src/doxygen.t index f887a68..1d6fc2f 100644 --- a/src/doxygen.t +++ b/src/doxygen.t @@ -75,3 +75,5 @@ sub GenerateDep { $(YACC) -l -d -p cppExpYY constexp.y -o ce_parse.c -rm ce_parse.c +xml_dtd.h: doxygen.dtd + cat doxygen.dtd | sed -e "s/\"/\\\\\"/g" -e "s/^/\"/g" -e "s/$$/\\\\n\"/g" >xml_dtd.h diff --git a/src/entry.cpp b/src/entry.cpp index ceee6ca..1c4ef6d 100644 --- a/src/entry.cpp +++ b/src/entry.cpp @@ -73,6 +73,8 @@ Entry::Entry(const Entry &e) memSpec = e.memSpec; initializer = e.initializer; initLines = e.initLines; + todoId = e.todoId; + testId = e.testId; sublist = new QList<Entry>; sublist->setAutoDelete(TRUE); extends = new QList<BaseInfo>; @@ -214,6 +216,8 @@ void Entry::reset() bodyLine = -1; endBodyLine = -1; mGrpId = -1; + todoId = 0; + testId = 0; section = EMPTY_SEC; sig = FALSE; virt = Normal; diff --git a/src/entry.h b/src/entry.h index 5c98a8c..1494bae 100644 --- a/src/entry.h +++ b/src/entry.h @@ -197,6 +197,8 @@ class Entry QList<QCString> *anchors; // list of anchors defined in this entry QCString fileName; // file this entry was extracted from int startLine; // start line of entry in the source + int todoId; // id of the todo item of this entry + int testId; // id of the test item of this entry static int num; // counts the total number of entries private: Entry &operator=(const Entry &); diff --git a/src/filedef.cpp b/src/filedef.cpp index eefb1ad..e35875f 100644 --- a/src/filedef.cpp +++ b/src/filedef.cpp @@ -39,8 +39,8 @@ FileDef::FileDef(const char *p,const char *nm,const char *lref) { path=p; filepath=path+nm; - filename=nameToFile(nm); - diskname=filename.copy(); + filename=nameToFile(nm,TRUE); + diskname=nameToFile(nm,FALSE); setReference(lref); classList = new ClassList; includeList = new QList<IncludeInfo>; @@ -388,16 +388,6 @@ void FileDef::writeDocumentation(OutputList &ol) enumMembers.writeDocumentation(ol,name()); } - //enumValMembers.countDocMembers(); - //if (enumValMembers.totalCount()>0 ) - //{ - // ol.writeRuler(); - // ol.startGroupHeader(); - // parseText(ol,theTranslator->trEnumerationValueDocumentation()); - // ol.endGroupHeader(); - // enumValMembers.writeDocumentation(ol,name()); - //} - funcMembers.countDocMembers(); if (funcMembers.totalCount()>0 ) { @@ -532,10 +522,10 @@ void FileDef::insertMember(MemberDef *md) enumMembers.append(md); break; case MemberDef::EnumValue: - if (Config::sortMembersFlag) - enumValMembers.inSort(md); - else - enumValMembers.append(md); + //if (Config::sortMembersFlag) + // enumValMembers.inSort(md); + //else + // enumValMembers.append(md); break; case MemberDef::Prototype: if (Config::sortMembersFlag) @@ -658,33 +648,44 @@ void FileDef::addIncludedByDependency(FileDef *fd,const char *incName,bool local } } -//----------------------------------------------------------------------------- - -#if 0 -/*! Creates a file list. */ -FileList::FileList() : QList<FileDef>() -{ -} - -/*! Destroys a file list */ -FileList::~FileList() +void FileDef::generateXMLSection(QTextStream &t,MemberList *ml,const char *type) { + if (ml->count()>0) + { + t << " <sectiondef type=\"" << type << "\">" << endl; + t << " <memberlist>" << endl; + MemberListIterator mli(*ml); + MemberDef *md; + for (mli.toFirst();(md=mli.current());++mli) + { + md->generateXML(t,this); + } + t << " </memberlist>" << endl; + t << " </sectiondef>" << endl; + } } -/*! Compares two files by name. */ -int FileList::compareItems(GCI item1, GCI item2) +void FileDef::generateXML(QTextStream &t) { - FileDef *f1=(FileDef *)item1; - FileDef *f2=(FileDef *)item2; - ASSERT(f1!=0 && f2!=0); - return Config::fullPathNameFlag ? - stricmp(f1->absFilePath(),f2->absFilePath()) : - stricmp(f1->name(),f2->name()); + t << " <compounddef id=\"" + << getOutputFileBase() << "\" type=\"file\">" << endl; + t << " <compoundname>"; + writeXMLString(t,name()); + t << "</compoundname>" << endl; + int numMembers = defineMembers.count()+protoMembers.count()+ + typedefMembers.count()+enumMembers.count()+ + funcMembers.count()+varMembers.count(); + if (numMembers>0) + { + t << " <sectionlist>" << endl; + generateXMLSection(t,&defineMembers,"define"); + generateXMLSection(t,&protoMembers,"prototype"); + generateXMLSection(t,&typedefMembers,"typedef"); + generateXMLSection(t,&enumMembers,"enum"); + generateXMLSection(t,&funcMembers,"func"); + generateXMLSection(t,&varMembers,"var"); + t << " </sectionlist>" << endl; + } + t << " </compounddef>" << endl; } -/*! Create a file list iterator. */ -FileListIterator::FileListIterator(const FileList &cllist) : - QListIterator<FileDef>(cllist) -{ -} -#endif diff --git a/src/filedef.h b/src/filedef.h index 03bc919..ff9f5b5 100644 --- a/src/filedef.h +++ b/src/filedef.h @@ -131,6 +131,9 @@ class FileDef : public Definition void addMembersToMemberGroup(); void distributeMemberGroupDocumentation(); + void generateXML(QTextStream &t); + void generateXMLSection(QTextStream &t,MemberList *ml,const char *type); + protected: void addMemberListToGroup(MemberList *,bool (MemberDef::*)() const); @@ -140,7 +143,6 @@ class FileDef : public Definition MemberList protoMembers; MemberList typedefMembers; MemberList enumMembers; - MemberList enumValMembers; MemberList funcMembers; MemberList varMembers; diff --git a/src/filename.cpp b/src/filename.cpp index 86db34f..e5f224a 100644 --- a/src/filename.cpp +++ b/src/filename.cpp @@ -28,13 +28,6 @@ FileName::~FileName() { } -//static QCString convertSlashes(const char *s) -//{ -// QCString 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() { @@ -48,7 +41,7 @@ void FileName::generateDiskNames() // skip references while (fd && fd->isReference()) fd=next(); // name if unique, so diskname is simply the name - fd->diskname=name; + fd->diskname=convertFileName(name); } else if (count>1) // multiple occurrences of the same file name { @@ -90,7 +83,7 @@ void FileName::generateDiskNames() { QCString prefix = fd->path.right(fd->path.length()-j-1); fd->setName(prefix+name); - fd->diskname=convertSlashes(prefix+name); + fd->diskname=convertFileName(prefix+name); } fd=next(); } diff --git a/src/formula.cpp b/src/formula.cpp index d7e444c..f35fd47 100644 --- a/src/formula.cpp +++ b/src/formula.cpp @@ -17,6 +17,9 @@ #include <stdlib.h> #include <unistd.h> +#ifdef _WIN32 +#include <windows.h> +#endif #include "qtbc.h" #include <qfile.h> @@ -165,29 +168,58 @@ void FormulaList::generateBitmaps(const char *path) 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. #ifdef _WIN32 - sprintf(gsCmd,"gswin32 -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() + char gsArgs[256]; + sprintf(gsArgs,"-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() ); + // gswin32 is a GUI api which will pop up a window and run + // asynchronously. To prevent both, we use ShellExecuteEx and + // WaitForSingleObject (thanks to Robert Golias for the code) + SHELLEXECUTEINFO sInfo = { + sizeof(SHELLEXECUTEINFO), /* structure size */ + SEE_MASK_NOCLOSEPROCESS, /* leave the process running */ + NULL, /* window handle */ + NULL, /* action to perform: open */ + "gswin32.exe", /* file to execute */ + gsArgs, /* argument list */ + NULL, /* use current working dir */ + SW_HIDE /* minimize on start-up */ + 0, /* application instance handle */ + NULL, /* ignored: id list */ + NULL, /* ignored: class name */ + NULL, /* ignored: key class */ + 0, /* ignored: hot key */ + NULL, /* ignored: icon */ + NULL /* resulting application handle */ + }; + if (!ShellExecuteEx(&sInfo)) + { + err("Problem running ghostscript. Check your installation!\n"); + return; + } + else if (sInfo.hProcess) /* executable was launched, wait for it to finish */ + { + WaitForSingleObject(sInfo.hProcess,INFINITE); + } #else + char gsCmd[256]; 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() ); -#endif - //printf("Running ghostscript...\n"); if (iSystem(gsCmd)!=0) { err("Problem running ghostscript. Check your installation!\n"); return; } +#endif f.setName(formBase+".pnm"); uint imageX=0,imageY=0; // we read the generated image again, to obtain the pixel data. diff --git a/src/index.cpp b/src/index.cpp index 9e13091..c56d265 100644 --- a/src/index.cpp +++ b/src/index.cpp @@ -578,7 +578,7 @@ int countNamespaces() NamespaceDef *nd; for (;(nd=nli.current());++nli) { - if (nd->isLinkableInProject() && nd->countMembers()>0) count++; + if (nd->isLinkableInProject()) count++; } return count; } @@ -614,7 +614,7 @@ void writeNamespaceIndex(OutputList &ol) NamespaceDef *nd=namespaceList.first(); while (nd) { - if (nd->isLinkableInProject() && nd->countMembers()>0) + if (nd->isLinkableInProject()) { ol.writeStartAnnoItem("namespace",nd->getOutputFileBase(),0,nd->name()); ol.docify(" ("); @@ -1386,7 +1386,7 @@ void writeExampleIndex(OutputList &ol) while (pi) { ol.writeListItem(); - QCString n=convertSlashes(pi->name,TRUE)+"-example"; + QCString n=convertFileName(pi->name)+"-example"; if (!pi->title.isEmpty()) { ol.writeObjectLink(0,n,0,pi->title); @@ -1513,7 +1513,7 @@ void writeGroupList(OutputList &ol) void writeGraphInfo(OutputList &ol) { - if (!Config::haveDotFlag) return; + if (!Config::haveDotFlag || !Config::generateHtml) return; ol.pushGeneratorState(); ol.disableAllBut(OutputGenerator::Html); generateGraphLegend(Config::htmlOutputDir); diff --git a/src/latexgen.cpp b/src/latexgen.cpp index 1f2e1a2..721176c 100644 --- a/src/latexgen.cpp +++ b/src/latexgen.cpp @@ -157,10 +157,20 @@ void LatexGenerator::init() << "refman.ps: refman.dvi" << endl << "\tdvips -o refman.ps refman.dvi" << endl << endl - << "refman.pdf: refman.ps" << endl - << "\tps2pdf refman.ps refman.pdf" << endl - << endl - << "refman_2on1.ps: refman.ps" << endl + << "refman.pdf: refman.ps" << endl; + if (Config::usePDFLatexFlag) // use pdflatex instead of latex + { + t << "\tpdflatex refman.tex" << endl; + t << "\tmakeindex refman.idx" << endl; + t << "\tpdflatex refman.tex" << endl << endl; + } + else // otherwise use ps2pdf: not as nice :( + // especially from the font point of view + { + t << "\tps2pdf refman.ps refman.pdf" << endl << endl; + } + + t << "refman_2on1.ps: refman.ps" << endl << "\tpsnup -2 refman.ps >refman_2on1.ps" << endl << endl << "refman_2on1.pdf: refman_2on1.ps" << endl @@ -185,7 +195,7 @@ static void writeDefaultHeaderPart1(QTextStream &t) if (Config::latexBatchModeFlag) t << "\\batchmode" << endl; if (Config::paperType=="a4wide") paperName="a4"; else paperName=Config::paperType; t << "\\documentclass[" << paperName << "paper"; - if (Config::pdfHyperFlag) t << ",ps2pdf"; + //if (Config::pdfHyperFlag) t << ",ps2pdf"; t << "]{"; if (Config::compactLatexFlag) t << "article"; else t << "book"; t << "}\n"; @@ -197,12 +207,20 @@ static void writeDefaultHeaderPart1(QTextStream &t) "\\usepackage{doxygen}\n"; if (Config::pdfHyperFlag) { - t << "\\usepackage{times}" << endl - << "\\usepackage[backref=true," << endl + t << "\\usepackage{times}" << endl; + t << "\\ifx\\pdfoutput\\undefined" << endl + << "\\usepackage[ps2pdf," << endl + << " pagebackref=true," << endl + << " colorlinks=true," << endl + << " linkcolor=blue" << endl + << " ]{hyperref}" << endl + << "\\else" << endl + << "\\usepackage[pdftex," << endl << " pagebackref=true," << endl << " colorlinks=true," << endl << " linkcolor=blue" << endl - << " ]{hyperref}" << endl; + << " ]{hyperref}" << endl + << "\\fi" << endl; } // Try to get the command for switching on the language // support @@ -479,7 +497,7 @@ void LatexGenerator::startIndexSection(IndexSections is) bool found=FALSE; while (nd && !found) { - if (nd->isLinkableInProject() && nd->countMembers()>0) + if (nd->isLinkableInProject()) { if (Config::compactLatexFlag) t << "\\section"; else t << "\\chapter"; t << "{"; // Namespace Documentation}\n": @@ -560,7 +578,9 @@ void LatexGenerator::endIndexSection(IndexSections is) } break; case isMainPage: - t << "}\n\\input{index}\n"; + t << "}\n\\label{index}"; + if (Config::pdfHyperFlag) t << "\\hypertarget{index}{}"; + t << "\\input{index}\n"; break; case isModuleIndex: t << "}\n\\input{modules}\n"; @@ -610,7 +630,7 @@ void LatexGenerator::endIndexSection(IndexSections is) bool found=FALSE; while (nd && !found) { - if (nd->isLinkableInProject() && nd->countMembers()>0) + if (nd->isLinkableInProject()) { t << "}\n\\input{" << nd->getOutputFileBase() << "}\n"; found=TRUE; @@ -619,7 +639,7 @@ void LatexGenerator::endIndexSection(IndexSections is) } while (nd) { - if (nd->isLinkableInProject() && nd->countMembers()>0) + if (nd->isLinkableInProject()) { if (Config::compactLatexFlag) t << "\\input"; else t << "\\include"; t << "{" << nd->getOutputFileBase() << "}\n"; @@ -686,13 +706,13 @@ void LatexGenerator::endIndexSection(IndexSections is) PageInfo *pi=exampleList.first(); if (pi) { - t << "\\input{" << convertSlashes(pi->name,TRUE) << "-example}\n"; + t << "\\input{" << convertFileName(pi->name) << "-example}\n"; pi=exampleList.next(); } while (pi) { if (Config::compactLatexFlag) t << "\\input" ; else t << "\\include"; - t << "{" << convertSlashes(pi->name,TRUE) << "-example}\n"; + t << "{" << convertFileName(pi->name) << "-example}\n"; pi=exampleList.next(); } } @@ -1076,7 +1096,7 @@ void LatexGenerator::writeSectionRef(const char *,const char *lab, if (strcmp(lab,text)!=0) // lab!=text { // todo: don't hardcode p. here! - t << "{\\bf " << text << "} (p.\\,\\pageref{" << lab << "})"; + t << "{\\bf " << text << "} {\\rm (p.\\,\\pageref{" << lab << "})}"; } else { diff --git a/src/memberdef.cpp b/src/memberdef.cpp index 396692a..d64225c 100644 --- a/src/memberdef.cpp +++ b/src/memberdef.cpp @@ -29,6 +29,8 @@ #include "membergroup.h" #include "scanner.h" #include "groupdef.h" +#include "defargs.h" +#include "xml.h" //----------------------------------------------------------------------------- @@ -117,13 +119,13 @@ static void writeDefArgumentList(OutputList &ol,ClassDef *cd, { QCString n=a->type.left(vp); if (!cName.isEmpty()) n=addTemplateNames(n,cd->name(),cName); - linkifyText(ol,scopeName,md->name(),n); + linkifyText(TextGeneratorOLImpl(ol),scopeName,md->name(),n); } else // non-function pointer type { QCString n=a->type; if (!cName.isEmpty()) n=addTemplateNames(n,cd->name(),cName); - linkifyText(ol,scopeName,md->name(),n); + linkifyText(TextGeneratorOLImpl(ol),scopeName,md->name(),n); } if (!a->name.isEmpty()) // argument has a name { @@ -143,14 +145,14 @@ static void writeDefArgumentList(OutputList &ol,ClassDef *cd, 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)); + linkifyText(TextGeneratorOLImpl(ol),scopeName,md->name(),a->type.right(a->type.length()-vp)); } if (!a->defval.isEmpty()) // write the default value { QCString n=a->defval; if (!cName.isEmpty()) n=addTemplateNames(n,cd->name(),cName); ol.docify(" = "); - linkifyText(ol,scopeName,md->name(),n); + linkifyText(TextGeneratorOLImpl(ol),scopeName,md->name(),n); } a=argList->next(); if (a) @@ -639,20 +641,20 @@ void MemberDef::writeDeclaration(OutputList &ol, { if (getAnonymousEnumType()) // type is an anonymous enum { - linkifyText(ol,cname,name(),ltype.left(i),TRUE); + linkifyText(TextGeneratorOLImpl(ol),cname,name(),ltype.left(i),TRUE); ol+=*getAnonymousEnumType()->enumDecl(); - linkifyText(ol,cname,name(),ltype.right(ltype.length()-i-l),TRUE); + linkifyText(TextGeneratorOLImpl(ol),cname,name(),ltype.right(ltype.length()-i-l),TRUE); } else { ltype = ltype.left(i) + " { ... } " + ltype.right(ltype.length()-i-l); - linkifyText(ol,cname,name(),ltype,TRUE); + linkifyText(TextGeneratorOLImpl(ol),cname,name(),ltype,TRUE); } } } else { - linkifyText(ol,cname,name(),ltype,TRUE); + linkifyText(TextGeneratorOLImpl(ol),cname,name(),ltype,TRUE); } bool htmlOn = ol.isEnabled(OutputGenerator::Html); if (htmlOn && Config::htmlAlignMemberFlag && !ltype.isEmpty()) @@ -679,7 +681,9 @@ void MemberDef::writeDeclaration(OutputList &ol, //if (manOn) ol.enable(OutputGenerator::Man); } else + { ol.insertMemberAlign(); + } // write name if (!name().isEmpty() && name().at(0)!='@') @@ -734,7 +738,7 @@ void MemberDef::writeDeclaration(OutputList &ol, { if (!isDefine()) ol.writeString(" "); //ol.docify(argsString()); - linkifyText(ol,cname,name(),argsString()); + linkifyText(TextGeneratorOLImpl(ol),cname,name(),argsString()); } if (excpString()) @@ -748,12 +752,12 @@ void MemberDef::writeDeclaration(OutputList &ol, if (!isDefine()) { ol.writeString(" = "); - linkifyText(ol,cname,name(),init.simplifyWhiteSpace()); + linkifyText(TextGeneratorOLImpl(ol),cname,name(),init.simplifyWhiteSpace()); } else { ol.writeNonBreakableSpace(); - linkifyText(ol,cname,name(),init); + linkifyText(TextGeneratorOLImpl(ol),cname,name(),init); } } @@ -860,9 +864,9 @@ void MemberDef::writeDocumentation(MemberList *ml,OutputList &ol, { htmlHelp->addIndexItem(cname,name(),cfname,anchor()); } - linkifyText(ol,scopeName,name(),ldef.left(i)); + linkifyText(TextGeneratorOLImpl(ol),scopeName,name(),ldef.left(i)); ol+=*vmd->enumDecl(); - linkifyText(ol,scopeName,name(),ldef.right(ldef.length()-i-l)); + linkifyText(TextGeneratorOLImpl(ol),scopeName,name(),ldef.right(ldef.length()-i-l)); found=TRUE; } @@ -886,7 +890,7 @@ void MemberDef::writeDocumentation(MemberList *ml,OutputList &ol, // last ei characters of ldef contain pointer/reference specifiers int ni=ldef.find("::",si); if (ni>=ei) ei=ni+2; - linkifyText(ol,scopeName,name(),ldef.right(ldef.length()-ei)); + linkifyText(TextGeneratorOLImpl(ol),scopeName,name(),ldef.right(ldef.length()-ei)); } } else @@ -943,25 +947,25 @@ void MemberDef::writeDocumentation(MemberList *ml,OutputList &ol, } } ol.startMemberDocName(); - linkifyText(ol,scopeName,name(),ldef); + linkifyText(TextGeneratorOLImpl(ol),scopeName,name(),ldef); writeDefArgumentList(ol,cd,scopeName,this); if (!init.isEmpty() && initLines==0 && maxInitLines>0) // add initializer { if (!isDefine()) { ol.docify(" = "); - linkifyText(ol,scopeName,name(),init.simplifyWhiteSpace()); + linkifyText(TextGeneratorOLImpl(ol),scopeName,name(),init.simplifyWhiteSpace()); } else { ol.writeNonBreakableSpace(); - linkifyText(ol,scopeName,name(),init); + linkifyText(TextGeneratorOLImpl(ol),scopeName,name(),init); } } if (excpString()) // add exception list { ol.docify(" "); - linkifyText(ol,scopeName,name(),excpString()); + linkifyText(TextGeneratorOLImpl(ol),scopeName,name(),excpString()); } } @@ -1389,3 +1393,180 @@ QCString MemberDef::getScopeString() const else if (getNamespaceDef()) result=getNamespaceDef()->name(); return result; } + +void MemberDef::generateXML(QTextStream &t,Definition *def) +{ + if (mtype==EnumValue) return; + + QCString scopeName; + if (getClassDef()) + scopeName=getClassDef()->name(); + else if (getNamespaceDef()) + scopeName=getNamespaceDef()->name(); + + t << " <"; + enum { define_t,variable_t,typedef_t,enum_t,function_t } xmlType; + switch (mtype) + { + case Define: t << "definedef"; xmlType=define_t; break; + case EnumValue: // fall through + case Variable: t << "variabledef"; xmlType=variable_t; break; + case Typedef: t << "typedef"; xmlType=typedef_t; break; + case Enumeration: t << "enumdef"; xmlType=enum_t; break; + case Function: // fall through + case Signal: // fall through + case Prototype: // fall through + case Friend: // fall through + case Slot: t << "functiondef"; xmlType=function_t; break; + } + t << " id=\""; + t << def->getOutputFileBase() + << ":" + << anchor(); + t << "\""; + if (xmlType==function_t && virtualness()!=Normal) + // functions has an extra "virt" attribute + { + t << " virt=\""; + switch (virtualness()) + { + case Virtual: t << "virtual"; break; + case Pure: t << "pure-virtual"; break; + default: ASSERT(0); + } + t << "\""; + } + t << ">" << endl; + + if (xmlType!=define_t && xmlType!=enum_t && // These don't have types. + (xmlType!=function_t || !type.isEmpty()) // Type is optional here. + ) + { + t << " <type>"; + if (xmlType==typedef_t && type.left(8)=="typedef ") + linkifyText(TextGeneratorXMLImpl(t),scopeName,name(), + type.right(type.length()-8)); // strip "typedef " + else if (xmlType==function_t && type.left(8)=="virtual ") + linkifyText(TextGeneratorXMLImpl(t),scopeName,name(), + type.right(type.length()-8)); // strip "virtual " + else + linkifyText(TextGeneratorXMLImpl(t),scopeName,name(),type); + t << "</type>" << endl; + } + + t << " <name>"; + writeXMLString(t,name()); + t << "</name>" << endl; + if (xmlType==function_t) //function + { + t << " <paramlist>" << endl; + ArgumentList *declAl = new ArgumentList; + ArgumentList *defAl = argList; + stringToArgumentList(args,declAl); + if (declAl->count()>0) + { + ArgumentListIterator declAli(*declAl); + ArgumentListIterator defAli(*defAl); + Argument *a; + for (declAli.toFirst();(a=declAli.current());++declAli) + { + Argument *defArg = defAli.current(); + t << " <param>" << endl; + if (!a->attrib.isEmpty()) + { + t << " <attributes>"; + writeXMLString(t,a->attrib); + t << "</attributes>" << endl; + } + if (!a->type.isEmpty()) + { + t << " <type>"; + linkifyText(TextGeneratorXMLImpl(t),scopeName,name(),a->type); + t << "</type>" << endl; + } + if (!a->name.isEmpty()) + { + t << " <declname>"; + writeXMLString(t,a->name); + t << "</declname>" << endl; + } + if (defArg && !defArg->name.isEmpty() && defArg->name!=a->name) + { + t << " <defname>"; + writeXMLString(t,defArg->name); + t << "</defname>" << endl; + } + if (!a->array.isEmpty()) + { + t << " <array>"; + writeXMLString(t,a->array); + t << "</array>" << endl; + } + if (!a->defval.isEmpty()) + { + t << " <defval>"; + linkifyText(TextGeneratorXMLImpl(t),scopeName,name(),a->defval); + t << "</defval>" << endl; + } + t << " </param>" << endl; + if (defArg) ++defAli; + } + } + delete declAl; + t << " </paramlist>" << endl; + } + else if (xmlType==define_t && !args.isEmpty()) // define + { + t << " <defparamlist>" << endl; + ArgumentListIterator ali(*argList); + Argument *a; + for (ali.toFirst();(a=ali.current());++ali) + { + t << " <defarg>" << a->type << "</defarg>" << endl; + } + t << " </defparamlist>" << endl; + if (!init.isEmpty()) + { + t << " <initializer>"; + linkifyText(TextGeneratorXMLImpl(t),scopeName,name(),init); + t << "</initializer>" << endl; + } + } + else if (xmlType==enum_t) // enum + { + t << " <enumvaluelist>" << endl; + MemberListIterator emli(*enumFields); + MemberDef *emd; + for (emli.toFirst();(emd=emli.current());++emli) + { + t << " <enumvalue>" << endl; + t << " <name>"; + writeXMLString(t,emd->name()); + t << "</name>" << endl; + if (!emd->init.isEmpty()) + { + t << " <initializer>"; + writeXMLString(t,emd->init); + t << "</initializer>" << endl; + } + t << " </enumvalue>" << endl; + } + t << " </enumvaluelist>" << endl; + } + t << " </"; + switch (mtype) + { + case Define: t << "definedef"; break; + case EnumValue: // fall through + case Variable: t << "variabledef"; break; + case Typedef: t << "typedef"; break; + case Enumeration: t << "enumdef"; break; + case Function: // fall through + case Signal: // fall through + case Prototype: // fall through + case Friend: // fall through + case Slot: t << "functiondef"; break; + } + t << ">" << endl; +} + diff --git a/src/memberdef.h b/src/memberdef.h index c8cab13..0ea0877 100644 --- a/src/memberdef.h +++ b/src/memberdef.h @@ -35,6 +35,7 @@ class ExampleList; class ExampleDict; class OutputList; class GroupDef; +class QTextStream; struct SourceReference { @@ -209,6 +210,8 @@ class MemberDef : public Definition QCString getScopeString() const; + void generateXML(QTextStream &t,Definition *def); + private: ClassDef *classDef; // member of or related to FileDef *fileDef; // member of file definition diff --git a/src/outputgen.h b/src/outputgen.h index 5f351f0..5b309c7 100644 --- a/src/outputgen.h +++ b/src/outputgen.h @@ -33,13 +33,12 @@ class DotGfxHierarchyTable; class OutputGenerator { public: - enum OutputType { Html, Latex, Man, RTF }; + enum OutputType { Html, Latex, Man, RTF, XML }; 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; @@ -52,7 +51,6 @@ class OutputGenerator 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; @@ -130,7 +128,6 @@ class OutputGenerator virtual void startCodeAnchor(const char *label) = 0; virtual void endCodeAnchor() = 0; virtual void writeLatexSpacing() = 0; - //virtual void writeLatexLabel(const char *clName,const char *anchor) = 0; virtual void writeStartAnnoItem(const char *type,const char *file, const char *path,const char *name) = 0; virtual void writeEndAnnoItem(const char *name) = 0; @@ -180,7 +177,6 @@ class OutputGenerator 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; diff --git a/src/reflist.cpp b/src/reflist.cpp new file mode 100644 index 0000000..8bef347 --- /dev/null +++ b/src/reflist.cpp @@ -0,0 +1,86 @@ +/****************************************************************************** + * + * + * + * + * Copyright (C) 1997-2000 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. + * + * Documents produced by Doxygen are derivative works derived from the + * input used in their production; they are not affected by this license. + * + */ + +#include "reflist.h" + +/*! The one and only todo list */ +RefList todoList; +/*! The test criteria list */ +RefList testList; + + +/*! Create a todo list */ +RefList::RefList() +{ + m_dict = 0; + m_dictIterator = 0; + m_id = 0; +} + +/*! Destroy the todo list. Currently not called! */ +RefList::~RefList() +{ + delete m_dictIterator; + delete m_dict; +} + +/*! Adds a new item to the list. + * \param text The item text. + * \returns A unique id for this item. + */ +int RefList::addRefItem() +{ + if (m_dict==0) + { + m_dict = new QIntDict<RefItem>(1009); + m_dict->setAutoDelete(TRUE); + m_dictIterator = new QIntDictIterator<RefItem>(*m_dict); + } + RefItem *item = new RefItem; + m_id++; + m_dict->insert(m_id,item); + return m_id; +} + +/*! Returns an item given it's id that is obtained with addRefItem() + * \param itemId item's identifier. + * \returns A pointer to the todo item's structure. + */ +RefItem *RefList::getRefItem(int itemId) +{ + return m_dict->find(itemId); +} + +/*! Returns the first item in the dictionary or 0 if + * non is available. + * Items are not sorted. + */ +RefItem *RefList::getFirstRefItem() +{ + return m_dictIterator->toFirst(); +} + +/*! Returns the next item in the dictionary or 0 if + * we are at the end of the list. + * Items are not sorted. + */ +RefItem *RefList::getNextRefItem() +{ + return m_dictIterator->operator++(); +} + diff --git a/src/reflist.h b/src/reflist.h new file mode 100644 index 0000000..f0d9958 --- /dev/null +++ b/src/reflist.h @@ -0,0 +1,55 @@ +/****************************************************************************** + * + * + * + * + * Copyright (C) 1997-2000 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. + * + * Documents produced by Doxygen are derivative works derived from the + * input used in their production; they are not affected by this license. + * + */ + +#ifndef _REFLIST_H +#define _REFLIST_H + +#include "qtbc.h" +#include <qintdict.h> + +/*! This struct represents an item in the list of references. */ +struct RefItem +{ + RefItem() : written(FALSE) {} + QCString text; //!< text of the item. + QCString listAnchor; //!< anchor in the list + bool written; +}; + +/*! Singleton for the one and only RefList */ +class RefList +{ + public: + int addRefItem(); + RefItem *getRefItem(int todoItemId); + RefItem *getFirstRefItem(); + RefItem *getNextRefItem(); + + RefList(); + ~RefList(); + + private: + int m_id; + QIntDict<RefItem> *m_dict; + QIntDictIterator<RefItem> *m_dictIterator; +}; + +extern RefList todoList; +extern RefList testList; + +#endif diff --git a/src/rtfgen.cpp b/src/rtfgen.cpp index 5239ffd..8ea9fb0 100644 --- a/src/rtfgen.cpp +++ b/src/rtfgen.cpp @@ -666,7 +666,7 @@ void RTFGenerator::startIndexSection(IndexSections is) bool found=FALSE; while (nd && !found) { - if (nd->isLinkableInProject() && nd->countMembers()>0) + if (nd->isLinkableInProject()) { beginRTFChapter(); found=TRUE; @@ -840,7 +840,7 @@ void RTFGenerator::endIndexSection(IndexSections is) bool found=FALSE; while (nd && !found) { - if (nd->isLinkableInProject() && nd->countMembers()>0) + if (nd->isLinkableInProject()) { t << "\\par " << Rtf_Style["Reset"] << endl; t << "{\\field\\fldedit{\\*\\fldinst INCLUDETEXT \""; @@ -852,7 +852,7 @@ void RTFGenerator::endIndexSection(IndexSections is) } while (nd) { - if (nd->isLinkableInProject() && nd->countMembers()>0) + if (nd->isLinkableInProject()) { t << "\\par " << Rtf_Style["Reset"] << endl; beginRTFSection(); @@ -941,7 +941,7 @@ void RTFGenerator::endIndexSection(IndexSections is) { t << "\\par " << Rtf_Style["Reset"] << endl; t << "{\\field\\fldedit{\\*\\fldinst INCLUDETEXT \""; - t << convertSlashes(pi->name,TRUE); + t << convertFileName(pi->name); t << "-example.rtf\" \\\\*MERGEFORMAT}{\\fldrslt includedstuff}}\n"; pi=exampleList.next(); } @@ -950,7 +950,7 @@ void RTFGenerator::endIndexSection(IndexSections is) t << "\\par " << Rtf_Style["Reset"] << endl; beginRTFSection(); t << "{\\field\\fldedit{\\*\\fldinst INCLUDETEXT \""; - t << convertSlashes(pi->name,TRUE); + t << convertFileName(pi->name); t << "-example.rtf\" \\\\*MERGEFORMAT}{\\fldrslt includedstuff}}\n"; pi=exampleList.next(); } diff --git a/src/scanner.l b/src/scanner.l index ba99f5b..33a4f07 100644 --- a/src/scanner.l +++ b/src/scanner.l @@ -42,6 +42,7 @@ #include "language.h" #include "outputlist.h" #include "membergroup.h" +#include "reflist.h" #ifndef WIN32 #include <unistd.h> @@ -93,9 +94,10 @@ static int roundCount = 0 ; static int curlyCount = 0 ; static int squareCount = 0 ; static int ifCount = 0 ; -static int todoAnchor = 0 ; static int todoStartContext = 0; static QCString todoString = 0; +static int testStartContext = 0; +static QCString testString = 0; static Entry* current_root = 0 ; static Entry* global_root = 0 ; static Entry* current = 0 ; @@ -237,6 +239,7 @@ static void initParser() //----------------------------------------------------------------------------- void scanString(const char *s); +void internalParseDocument(const char *s); //----------------------------------------------------------------------------- @@ -897,11 +900,12 @@ static int yyread(char *buf,int max_size) %} CMD ("\\"|"@") +SECTIONCMD {CMD}("image"|"author"|"internal"|"version"|"date"|"deprecated"|"param"|"exception"|"return"[s]?|"retval"|"bug"|"warning"|"par"|"sa"|"see"|"pre"|"post"|"invariant"|"note"|"remark"[s]?|"todo"|"test"|"ingroup") BN [ \t\n\r] BL [ \t\r]*"\n" B [ \t] BS ^(({B}*"//")?)(({B}*"*"+)?){B}* -FILE ([a-z_A-Z0-9\.\\:\/\-\+]+)|("\""[^\n\"]+"\"") +FILE ([a-z_A-Z0-9\\:\/\-\+]+("."[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}?) @@ -1086,6 +1090,7 @@ DOCPARAM ([a-z_A-Z0-9:\<\>\=\.\-]+)|("\"".*"\"") %x DocLatexImageName %x DocLatexImageWidth %x TodoParam +%x TestParam %x SectionLabel %x SectionTitle %x SkipTemplate @@ -1278,7 +1283,7 @@ DOCPARAM ([a-z_A-Z0-9:\<\>\=\.\-]+)|("\"".*"\"") "in documentation." ); } -<DocScan>{CMD}"addindex"/{BN} { +<DocScan>{CMD}"addindex"{B}+ { BEGIN(DocIndexWord); } <DocScan>"\\form#"[0-9]+ { @@ -1529,6 +1534,46 @@ DOCPARAM ([a-z_A-Z0-9:\<\>\=\.\-]+)|("\"".*"\"") outDoc->writeDescItem(); } } +<DocScan>"\\todo "[0-9]+ { // this tag is generated in an earlier pass + if (Config::generateTodoList) + { + QCString numStr=yytext; + numStr=numStr.right(numStr.length()-6); + bool ok; int num = numStr.toUInt(&ok); + RefItem *item = todoList.getRefItem(num); + ASSERT(item!=0); + endArgumentList(); + if (inBlock()) endBlock(); + outDoc->startDescList(); + outDoc->startBold(); + outDoc->writeObjectLink(0,"todo",item->listAnchor,theTranslator->trTodo()+": "); + outDoc->endBold(); + outDoc->endDescTitle(); + outDoc->writeDescItem(); + internalParseDocument(item->text); + outDoc->endDescList(); + } + } +<DocScan>"\\test "[0-9]+ { // this tag is generated in an earlier pass + if (Config::generateTestList) + { + QCString numStr=yytext; + numStr=numStr.right(numStr.length()-6); + bool ok; int num = numStr.toUInt(&ok); + RefItem *item = testList.getRefItem(num); + ASSERT(item!=0); + endArgumentList(); + if (inBlock()) endBlock(); + outDoc->startDescList(); + outDoc->startBold(); + outDoc->writeObjectLink(0,"test",item->listAnchor,theTranslator->trTest()+": "); + outDoc->endBold(); + outDoc->endDescTitle(); + outDoc->writeDescItem(); + internalParseDocument(item->text); + outDoc->endDescList(); + } + } <DocScan>{CMD}"deprecated"/{BN} { endArgumentList(); if (!inDeprecatedBlock) @@ -1560,6 +1605,7 @@ DOCPARAM ([a-z_A-Z0-9:\<\>\=\.\-]+)|("\"".*"\"") scanString(tagName+": "); outDoc->endBold(); outDoc->endDescTitle(); + outDoc->writeDescItem(); scanString(tagText); outDoc->endDescList(); } @@ -1760,7 +1806,7 @@ DOCPARAM ([a-z_A-Z0-9:\<\>\=\.\-]+)|("\"".*"\"") } BEGIN(DocScan); } -<DocRefName>{SCOPENAME} { +<DocRefName>{SCOPENAME}|{FILE} { QCString ref=yytext; SectionInfo *sec; if ((sec=sectionDict[ref])) @@ -1789,7 +1835,7 @@ DOCPARAM ([a-z_A-Z0-9:\<\>\=\.\-]+)|("\"".*"\"") } BEGIN(DocScan); } -<DocRefName>{SCOPENAME}{B}+/"\"" { +<DocRefName>({SCOPENAME}|{FILE}){B}+/"\"" { sectionRef=yytext; sectionRef=sectionRef.stripWhiteSpace(); BEGIN(DocRefArgStart); @@ -1922,7 +1968,7 @@ DOCPARAM ([a-z_A-Z0-9:\<\>\=\.\-]+)|("\"".*"\"") generateRef(*outDoc,className,yytext,inSeeBlock); BEGIN(DocScan); } -<DocScan,DocRefName>{SCOPEMASK}("()")? { +<DocScan,DocRefName>{SCOPEMASK}("()")? { generateRef(*outDoc,className,yytext,inSeeBlock); BEGIN(DocScan); } @@ -2178,7 +2224,7 @@ DOCPARAM ([a-z_A-Z0-9:\<\>\=\.\-]+)|("\"".*"\"") } <DocEmphasis>{WORD} { outDoc->startEmphasis(); - linkifyText(*outDoc,className,0,yytext,FALSE,FALSE); + linkifyText(TextGeneratorOLImpl(*outDoc),className,0,yytext,FALSE,FALSE); outDoc->endEmphasis(); BEGIN( DocScan ); } @@ -2196,7 +2242,7 @@ DOCPARAM ([a-z_A-Z0-9:\<\>\=\.\-]+)|("\"".*"\"") } <DocBold>{WORD} { outDoc->startBold(); - linkifyText(*outDoc,className,0,yytext,FALSE,FALSE); + linkifyText(TextGeneratorOLImpl(*outDoc),className,0,yytext,FALSE,FALSE); outDoc->endBold(); BEGIN( DocScan ); } @@ -2208,7 +2254,7 @@ DOCPARAM ([a-z_A-Z0-9:\<\>\=\.\-]+)|("\"".*"\"") } <DocCode>{WORD} { outDoc->startTypewriter(); - linkifyText(*outDoc,className,0,yytext,FALSE,FALSE); + linkifyText(TextGeneratorOLImpl(*outDoc),className,0,yytext,FALSE,FALSE); outDoc->endTypewriter(); BEGIN( DocScan ); } @@ -4233,7 +4279,7 @@ DOCPARAM ([a-z_A-Z0-9:\<\>\=\.\-]+)|("\"".*"\"") current->brief+="."; BEGIN( tmpDocType ); } -<JavaDoc>{CMD}("image"|"author"|"internal"|"version"|"date"|"param"|"exception"|"return"[s]?|"retval"|"bug"|"warning"|"par"|"sa"|"see"|"pre"|"post"|"invariant"|"note") { +<JavaDoc>{B}*/{SECTIONCMD} { current->doc+=yytext; BEGIN( tmpDocType ); } @@ -4381,50 +4427,74 @@ DOCPARAM ([a-z_A-Z0-9:\<\>\=\.\-]+)|("\"".*"\"") } <SkipHtmlComment>"--"[!]?">" { BEGIN(lastSkipHtmlCommentContext); } <SkipHtmlComment>. -<LineDoc,Doc,JavaDoc,ClassDoc,PageDoc>{CMD}"todo"{B}+ { +<AfterDoc,AfterDocLine,LineDoc,Doc,JavaDoc,ClassDoc,PageDoc>{CMD}"todo"/[^a-z_A-Z0-9] { todoStartContext = YY_START; - todoString.resize(0); - BEGIN(TodoParam); + lastBriefContext = TodoParam; // this is where we will continue at the end of the argument + todoString = current->brief.copy(); // these will be swapped later on. + BEGIN(ClassDocBrief); } -<TodoParam>[^*/\n]+ { - todoString+=yytext; +<AfterDoc,AfterDocLine,LineDoc,Doc,JavaDoc,ClassDoc,PageDoc>{CMD}"test"/[^a-z_A-Z0-9] { + testStartContext = YY_START; + lastBriefContext = TestParam; // this is where we will continue at the end of the argument + testString = current->brief.copy(); // these will be swapped later on. + BEGIN(ClassDocBrief); } +<TodoParam>\n | <TodoParam>. { - todoString+=*yytext; - } -<TodoParam>"\n"|"*/" { - char anchorLabel[12]; - sprintf(anchorLabel,"_todo%06d",todoAnchor++); - QCString todoItemNum; - todoItemNum.sprintf("%d",todoAnchor); - sectionType=SectionInfo::Anchor; - sectionLabel=anchorLabel; - addSection(); - current->doc += "\\anchor "+sectionLabel+"\n"; - current->doc += "<p><b>\\link todo "; - current->doc += theTranslator->trTodo(); - current->doc += ":\\endlink </b>"; - current->doc += todoString + "<p>"; - Entry *page = new Entry; - page->section = Entry::PAGEDOC_SEC; - page->fileName = yyFileName; - page->startLine = yyLineNr; - page->name = "todo"; - page->args = theTranslator->trTodoList(); - page->doc += "\\ref "; - page->doc += anchorLabel; - page->doc += " \""+todoItemNum+"\"\n"+todoString+"<p>"; - global_root->addSubEntry(page); - if (*yytext=='*') - { - unput('/');unput('*'); + if (current->todoId!=0) + { + RefItem *item = todoList.getRefItem(current->todoId); + item->text += "<p>"; + item->text += current->brief; } else { - unput('\n'); + int todoItemId = todoList.addRefItem(); + char anchorLabel[12]; + sprintf(anchorLabel,"_todo%06d",todoItemId); + RefItem *item = todoList.getRefItem(todoItemId); + item->text = current->brief.copy(); + item->listAnchor = anchorLabel; + current->todoId = todoItemId; + QCString todoCmdString; + todoCmdString.sprintf("\\todo %d\n",todoItemId); + current->doc += todoCmdString; + sectionType=SectionInfo::Anchor; + sectionLabel=anchorLabel; + addSection(); } + unput(*yytext); + current->brief = todoString.copy(); // restore orginial brief desc. BEGIN(todoStartContext); - } + } +<TestParam>\n | +<TestParam>. { + if (current->testId!=0) + { + RefItem *item = testList.getRefItem(current->testId); + item->text += "<p>"; + item->text += current->brief; + } + else + { + int testItemId = testList.addRefItem(); + char anchorLabel[12]; + sprintf(anchorLabel,"_test%06d",testItemId); + RefItem *item = testList.getRefItem(testItemId); + item->text = current->brief.copy(); + item->listAnchor = anchorLabel; + current->testId = testItemId; + QCString testCmdString; + testCmdString.sprintf("\\test %d\n",testItemId); + current->doc += testCmdString; + sectionType=SectionInfo::Anchor; + sectionLabel=anchorLabel; + addSection(); + } + unput(*yytext); + current->brief = testString.copy(); // restore orginial brief desc. + BEGIN(testStartContext); + } <ExampleDocArg1>{FILE} { current->name = stripQuotes(yytext); BEGIN( ExampleDoc ); @@ -4715,7 +4785,7 @@ DOCPARAM ([a-z_A-Z0-9:\<\>\=\.\-]+)|("\"".*"\"") <Doc,JavaDoc,LineDoc,ExampleDoc,PageDoc,ClassDoc>^{B}*"//" <Doc,ExampleDoc,PageDoc,ClassDoc>"//" { current->doc += yytext; } <LineDoc,JavaDoc>"//" { current->brief += yytext; } -<Doc,JavaDoc,LineDoc,ExampleDoc,ClassDocBrief,PageDoc,ClassDoc>("\\\\"|"@@")"f"[$\[\]] { +<Doc,JavaDoc,LineDoc,ExampleDoc,ClassDocBrief,PageDoc,ClassDoc,AfterDoc,AfterDocLine,AfterDocBrief>("\\\\"|"@@")"f"[$\[\]] { current->doc += &yytext[1]; } <Doc,JavaDoc,LineDoc,ExampleDoc,ClassDocBrief,PageDoc,ClassDoc,AfterDoc,AfterDocLine,AfterDocBrief>{CMD}"f$" { @@ -4766,6 +4836,18 @@ DOCPARAM ([a-z_A-Z0-9:\<\>\=\.\-]+)|("\"".*"\"") BEGIN( lastDocContext ); } else if (YY_START==ClassDocBrief && + lastBriefContext==TodoParam) + { + unput('/');unput('*'); // make sure we have something to read + BEGIN( TodoParam ); + } + else if (YY_START==ClassDocBrief && + lastBriefContext==TestParam) + { + unput('/');unput('*'); // make sure we have something to read + BEGIN( TestParam ); + } + else if (YY_START==ClassDocBrief && lastBriefContext==Doc) { current->doc += "\n\n"; @@ -4799,18 +4881,18 @@ DOCPARAM ([a-z_A-Z0-9:\<\>\=\.\-]+)|("\"".*"\"") <PageDocTitle>\n { yyLineNr++; current->args+=" "; } <PageDocTitle>[^\n\<] { current->args+=yytext; } <PageDocTitle>"</"{TITLE}">" { BEGIN( PageDoc ); } -<ClassDoc,LineDoc,Doc,JavaDoc>{CMD}"ingroup"{B}+ { +<ClassDoc,LineDoc,Doc,JavaDoc,AfterDoc>{CMD}"ingroup"{B}+ { lastGroupContext = YY_START; lineCount(); BEGIN( GroupName ); } -<ClassDoc,LineDoc,Doc,JavaDoc>{CMD}"nosubgrouping"/[^a-z_A-Z0-9] { +<ClassDoc,LineDoc,Doc,JavaDoc,AfterDoc>{CMD}"nosubgrouping"/[^a-z_A-Z0-9] { current->subGrouping = FALSE; } -<ClassDoc,LineDoc,Doc,JavaDoc>{CMD}"showinitializer"/[^a-z_A-Z0-9] { +<ClassDoc,LineDoc,Doc,JavaDoc,AfterDoc>{CMD}"showinitializer"/[^a-z_A-Z0-9] { current->initLines = 100000; // ON } -<ClassDoc,LineDoc,Doc,JavaDoc>{CMD}"hideinitializer"/[^a-z_A-Z0-9] { +<ClassDoc,LineDoc,Doc,JavaDoc,AfterDoc>{CMD}"hideinitializer"/[^a-z_A-Z0-9] { current->initLines = 0; // OFF } <GroupName>{ID} { @@ -4837,16 +4919,46 @@ DOCPARAM ([a-z_A-Z0-9:\<\>\=\.\-]+)|("\"".*"\"") <ClassDocBrief>{BS}({BL}|"\\n\\n") { current->brief=current->brief.stripWhiteSpace(); if (!current->doc.isEmpty()) current->doc+="<p>"; - yyLineNr++; + if (lastBriefContext==TodoParam || lastBriefContext==TestParam) + { + unput('\n'); + } + else + { + yyLineNr++; + } BEGIN( lastBriefContext ); } -<ClassDocBrief>"\n" { yyLineNr++ ; current->brief += " "; } +<ClassDocBrief>"\n" { + // allow \todo in brief description + if (lastBriefContext==TodoParam && + (todoStartContext==LineDoc || + todoStartContext==AfterDocLine + ) + ) + { + unput('\n'); // make sure we have something to read + BEGIN( TodoParam ); + } + else if + (lastBriefContext==TestParam && + (testStartContext==LineDoc || + testStartContext==AfterDocLine + ) + ) + { + unput('\n'); // make sure we have something to read + BEGIN( TestParam ); + } + else + { + current->brief += " "; + yyLineNr++ ; + } + } <ClassDocBrief>"<"{BR}{ATTR}">" -<ClassDocBrief>{BS}/{CMD}"ingroup" { +<ClassDocBrief>{BS}/{SECTIONCMD} { current->brief=current->brief.stripWhiteSpace(); - BEGIN( lastBriefContext ); - } -<ClassDocBrief>{BS}/{CMD}("image"|"author"|"internal"|"version"|"date"|"deprecated"|"param"|"exception"|"return"[s]?|"retval"|"bug"|"warning"|"par"|"sa"|"see") { BEGIN( lastBriefContext ); } <ClassDocBrief>{BS}/{CMD}("brief"|"short"){BN}+ { @@ -4971,14 +5083,33 @@ DOCPARAM ([a-z_A-Z0-9:\<\>\=\.\-]+)|("\"".*"\"") BEGIN(AfterDoc); } <AfterDocLine>. { current->brief+=yytext; } +<AfterDocBrief>{BS}({BL}|"\\n\\n") { + current->brief=current->brief.stripWhiteSpace(); + yyLineNr++; + BEGIN( AfterDoc ); + } <AfterDocBrief>"/*"|"//" { current->brief+=yytext; } -<AfterDocBrief>^{B}*"*"+/[^/\n] +<AfterDocBrief>{B}*/{SECTIONCMD} { + current->brief=current->brief.stripWhiteSpace(); + BEGIN( AfterDoc ); + } <AfterDocBrief>\n { current->brief+=yytext; yyLineNr++; } <AfterDocBrief>. { current->brief+=*yytext; } -<AfterDocBrief>^{B}*"*"/[^/\n]{BL} { yyLineNr++; + + /* +<AfterDocBrief>"<"{BR}{ATTR}">" +<AfterDocBrief>{BS}/{CMD}"ingroup" { + current->brief=current->brief.stripWhiteSpace(); + BEGIN( lastBriefContext ); + } +<AfterDocBrief>{BS}/{SECTIONCMD} { + BEGIN( lastBriefContext ); + } +<AfterDocBrief>{BS}/[^/\n]{BL} { yyLineNr++; if (!current->brief.stripWhiteSpace().isEmpty()) BEGIN(AfterDoc); } + */ <AfterDocBrief>"*/" { if (afterDocTerminator!=0) unput(afterDocTerminator); @@ -5032,11 +5163,11 @@ DOCPARAM ([a-z_A-Z0-9:\<\>\=\.\-]+)|("\"".*"\"") unput('/');unput('*'); BEGIN( tmpDocType ); } -<Doc,JavaDoc,ClassDoc,PageDoc,ExampleDoc,ReadFormulaShort,ReadFormulaLong,ClassDocBrief>^{B}*(("//"{B}*)?)"*"+[ \t]*"-"{B}+ { +<Doc,JavaDoc,ClassDoc,PageDoc,ExampleDoc,ReadFormulaShort,ReadFormulaLong,ClassDocBrief,AfterDoc,AfterDocBrief>^{B}*(("//"{B}*)?)"*"+[ \t]*"-"{B}+ { current->doc += yytext; } -<Doc,JavaDoc,ClassDoc,PageDoc,ExampleDoc,ReadFormulaShort,ReadFormulaLong,ClassDocBrief>^{B}*(("//"{B}*)?)"*"+/[^/] -<Doc,JavaDoc,ClassDoc,PageDoc,ExampleDoc,ReadFormulaShort,ReadFormulaLong,ClassDocBrief>^{B}*(("//"{B}*)?)"*"+{B}+ { +<Doc,JavaDoc,ClassDoc,PageDoc,ExampleDoc,ReadFormulaShort,ReadFormulaLong,ClassDocBrief,AfterDoc,AfterDocBrief>^{B}*(("//"{B}*)?)"*"+/[^/] +<Doc,JavaDoc,ClassDoc,PageDoc,ExampleDoc,ReadFormulaShort,ReadFormulaLong,ClassDocBrief,AfterDoc,AfterDocBrief>^{B}*(("//"{B}*)?)"*"+{B}+ { current->doc+=' '; } <DefLineDoc,LineDoc,ClassDoc,Doc>"/*" { current->doc += yytext; } @@ -5097,6 +5228,25 @@ void scanString(const char *s) BEGIN( oldRule ); } +void internalParseDocument(const char *s) +{ + const char *oldInputString = inputString; + int oldInputPosition = inputPosition; + int oldRule = YY_START; + YY_BUFFER_STATE oldBuffer = YY_CURRENT_BUFFER; + yy_switch_to_buffer(yy_create_buffer(scanYYin, YY_BUF_SIZE)); + inputString = s; + inputPosition = 0; + BEGIN( DocScan ); + scanYYlex(); + yy_delete_buffer(YY_CURRENT_BUFFER); + yy_switch_to_buffer(oldBuffer); + inputString = oldInputString; + inputPosition = oldInputPosition; + BEGIN( oldRule ); +} + + //---------------------------------------------------------------------------- static void newDocState() diff --git a/src/translator.h b/src/translator.h index cb2e2ab..25d25d6 100644 --- a/src/translator.h +++ b/src/translator.h @@ -977,6 +977,22 @@ class Translator { return "legend"; } + +////////////////////////////////////////////////////////////////////////// +// new since 1.2.0 +////////////////////////////////////////////////////////////////////////// + + /*! Used as a marker that is put before a todo item */ + virtual QCString trTest() + { + return "Test"; + } + /*! Used as the header of the todo list */ + virtual QCString trTestList() + { + return "Test List"; + } + }; #endif diff --git a/src/translator_de.h b/src/translator_de.h index a48251b..44d2ec5 100644 --- a/src/translator_de.h +++ b/src/translator_de.h @@ -560,7 +560,7 @@ class TranslatorGerman : public Translator bool single) { // here s is one of " Class", " Struct" or " Union" // single is true implies a single file - QCString result=(QCString)"Die Dokumentation für diese"; + QCString result=(QCString)"Die Dokumentation für diese"; switch(compType) { case ClassDef::Class: result+=" Klasse"; break; @@ -634,10 +634,11 @@ class TranslatorGerman : public Translator { return (QCString)"Zusammengehörigkeiten von "+clName+":"; } + //RK: Apparently Jens missed the Umlaut here. Corrected that. /*! this text is put before an include dependency graph */ virtual QCString trInclDepGraph(const char *fName) { - return (QCString)"Include-Abhängikeitsdiagramm für "+fName+":"; + return (QCString)"Include-Abhängikeitsdiagramm für "+fName+":"; } /*! header that is put before the list of constructor/destructors. */ virtual QCString trConstructorDocumentation() @@ -700,9 +701,10 @@ class TranslatorGerman : public Translator // new since 1.1.0 ////////////////////////////////////////////////////////////////////////// + //RK: had to change here because of the new command \remark virtual QCString trNote() { - return "Bemerkung"; + return "Zu beachten"; } virtual QCString trPublicTypes() @@ -742,9 +744,123 @@ class TranslatorGerman : public Translator return "Statische private Attribute"; } - ////////////////////////////////////////////////////////////////////////// - // new since 1.1.1 - ////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////// +// new since 1.1.3 +////////////////////////////////////////////////////////////////////////// + +//RK: Started from here + /*! Used as a marker that is put before a todo item */ + virtual QCString trTodo() + { + return "Noch zu erledigen"; + } + /*! Used as the header of the todo list */ + virtual QCString trTodoList() + { + return "Liste der zu erledigenden Dinge"; + } + +////////////////////////////////////////////////////////////////////////// +// new since 1.1.4 +////////////////////////////////////////////////////////////////////////// + + virtual QCString trReferencedBy() + { + return "Wird benutzt von"; + } + virtual QCString trRemarks() + { + return "Bemerkungen"; + } + virtual QCString trAttention() + { + return "Achtung"; + } + virtual QCString trInclByDepGraph() + { + return "Dieser Graph zeigt, welche Datei direkt oder " + "indirekt diese Datei enthält:"; + } + virtual QCString trSince() + { + return "Seit"; + } + +////////////////////////////////////////////////////////////////////////// +// new since 1.1.5 +////////////////////////////////////////////////////////////////////////// + + /*! title of the graph legend page */ + virtual QCString trLegendTitle() + { + return "Erklärung des Graphen"; + } + /*! page explaining how the dot graph's should be interpreted */ + virtual QCString trLegendDocs() + { + return + "Diese Seite erklärt die Interpretation der von doxygen " + "erzeugten Graphen.<p>\n" + "Beispiel:\n" + "\\code\n" + "/*! Wegen Verkürzung unsichtbare Klasse */\n" + "class Invisible { };\n\n" + "/*! Klasse verkürzt dargestellt, Vererbunsbeziehung ist versteckt */\n" + "class Truncated : public Invisible { };\n\n" + "/* Nicht mit doxygen-Kommentaren dokumentierte Klasse */\n" + "class Undocumented { };\n\n" + "/*! Mithilfe öffentlicher Vererbung vererbte Klasse */\n" + "class PublicBase : public Truncated { };\n\n" + "/*! Mithilfe geschützter Vererbung vererbte Klasse */\n" + "class ProtectedBase { };\n\n" + "/*! Mithilfe privater Vererbung vererbte Klasse */\n" + "class PrivateBase { };\n\n" + "/*! Von der Klasse Inherited benutzte Klasse */\n" + "class Used { };\n\n" + "/*! Superklasse, die von mehreren anderen Klassen erbt */\n" + "class Inherited : public PublicBase,\n" + " protected ProtectedBase,\n" + " private PrivateBase,\n" + " public Undocumented\n" + "{\n" + " private:\n" + " Used *m_usedClass;\n" + "};\n" + "\\endcode\n" + "Setzen des Tags \\c MAX_DOT_GRAPH_HEIGHT in der Konfigurationsdatei " + "auf 200 liefert den folgenden Graphen:" + "<p><center><img src=\"graph_legend.gif\"></center>\n" + "<p>\n" + "Die Rechtecke in obigem Graphen bedeuten:\n" + "<ul>\n" + "<li>Ein schwarz gefülltes Rechteck stellt die Struktur oder " + "Klasse dar, füdie der Graph erzeug wurde.\n" + "<li>Ein Rechteck mit schwarzem Rahmen kennzeichnet eine dokumentierte " + " Struktur oder Klasse.\n" + "<li>Ein Rechteck mit grauem Rahmen kennzeichnet eine undokumentierte " + " Struktur oder Klasse.\n" + "<li>Ein Rechteck mit rotem Rahmen kennzeichnet eine dokumentierte " + " Struktur oder Klasse, für die nicht alle Vererbungs-/" + "Enthaltenseinsbeziehungen dargestellt werden. Ein Graph wird gekürzt, " + "wenn er nicht in die angegebenen Schranken passt." + "</ul>\n" + "Die Pfeile bedeuten:\n" + "<ul>\n" + "<li>Ein dunkelblauer Pfeil stellt eine öffentliche Vererbungsbeziehung " + "zwischen zwei Klassen dar.\n" + "<li>Ein dunkelgrüner Pfeil stellt geschützte Vererbung dar.\n" + "<li>Ein dunkelroter Pfeil stellt private Vererbung dar.\n" + "<li>Ein gestrichelter violetter Pfeil beutet, dass eine Klasse in einer " + "anderen enthalten ist oder von einer anderen benutzt wird. Am Pfeil " + "stehen die Variable(n), mit deren Hilfe auf die Struktur oder Klasse " + "an der Pfeilspize zugegriffen werden kann. \n" + "</ul>\n"; + } + /*! text for the link to the legend page */ + virtual QCString trLegend() + { + return "Legende"; + } }; diff --git a/src/translator_nl.h b/src/translator_nl.h index 1112ce8..d366cc5 100644 --- a/src/translator_nl.h +++ b/src/translator_nl.h @@ -696,6 +696,22 @@ class TranslatorDutch : public Translator { return "legenda"; } + +////////////////////////////////////////////////////////////////////////// +// new since 1.2.0 +////////////////////////////////////////////////////////////////////////// + + /*! Used as a marker that is put before a todo item */ + virtual QCString trTest() + { + return "Test"; + } + /*! Used as the header of the todo list */ + virtual QCString trTestList() + { + return "Test Lijst"; + } + }; #endif diff --git a/src/util.cpp b/src/util.cpp index 8d29fd4..1870400 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -282,7 +282,16 @@ ClassDef *getResolvedClass(const char *name) else { //printf("getClass: subst %s->%s\n",name,subst->data()); - return classDict[subst->data()]; + int i; + ClassDef *cd = classDict[subst->data()]; + if (cd==0 && (i=subst->find('<'))>0) // try unspecialized version as well + { + return classDict[subst->left(i)]; + } + else + { + return cd; + } } } else @@ -291,6 +300,20 @@ ClassDef *getResolvedClass(const char *name) } } +static bool findOperator(const QCString &s,int i) +{ + int b = s.findRev("operator",i); + if (b==-1) return FALSE; // not found + b+=8; + while (b<i) // check if there are only spaces inbetween + // the operator and the > + { + if (!isspace(s.at(b))) return FALSE; + b++; + } + return TRUE; +} + QCString removeRedundantWhiteSpace(const QCString &s) { if (s.isEmpty()) return s; @@ -301,15 +324,15 @@ QCString removeRedundantWhiteSpace(const QCString &s) { char c=s.at(i); if (i<l-2 && c=='<' && // current char is a < - (isId(s.at(i+1)) || isspace(s.at(i+1))) && // next char is a id char or space - (i<8 || s.mid(i-8,8)!="operator") // string in front is not "operator" + (isId(s.at(i+1)) || isspace(s.at(i+1))) && // next char is an id char or space + (i<8 || !findOperator(s,i)) // string in front is not "operator" ) { result+="< "; // insert extra space for layouting (nested) templates } else if (i>0 && c=='>' && // current char is a > - (isId(s.at(i-1)) || isspace(s.at(i-1))) && // prev char is a id char or space - (i<8 || s.mid(i-8,8)!="operator") // string in front is not "operator" + (isId(s.at(i-1)) || isspace(s.at(i-1))) && // prev char is an id char or space + (i<8 || !findOperator(s,i)) // string in front is not "operator" ) { result+=" >"; // insert extra space for layouting (nested) templates @@ -346,7 +369,8 @@ bool leftScopeMatch(const QCString &scope, const QCString &name) ); } -void linkifyText(OutputList &ol,const char *scName,const char *name,const char *text,bool autoBreak,bool external) + +void linkifyText(const TextGeneratorIntf &out,const char *scName,const char *name,const char *text,bool autoBreak,bool external) { //printf("scope=`%s' name=`%s' Text: `%s'\n",scName,name,text); static QRegExp regExp("[a-z_A-Z][a-z_A-Z0-9:]*"); @@ -373,18 +397,22 @@ void linkifyText(OutputList &ol,const char *scName,const char *name,const char * if (i==-1) i=splitText.find(' '); if (i!=-1) // add a link-break at i in case of Html output { - ol.docify(splitText.left(i+1)); - ol.pushGeneratorState(); - ol.disableAllBut(OutputGenerator::Html); - ol.lineBreak(); - ol.popGeneratorState(); - ol.docify(splitText.right(splitLength-i-1)); + //ol.docify(splitText.left(i+1)); + //ol.pushGeneratorState(); + //ol.disableAllBut(OutputGenerator::Html); + //ol.lineBreak(); + //ol.popGeneratorState(); + //ol.docify(splitText.right(splitLength-i-1)); + out.writeString(splitText.left(i+1)); + out.writeBreak(); + out.writeString(splitText.right(splitLength-i-1)); } floatingIndex=splitLength-i-1; } else { - ol.docify(txtStr.mid(skipIndex,newIndex-skipIndex)); + //ol.docify(txtStr.mid(skipIndex,newIndex-skipIndex)); + out.writeString(txtStr.mid(skipIndex,newIndex-skipIndex)); } // get word from string QCString word=txtStr.mid(newIndex,matchLen); @@ -422,7 +450,8 @@ void linkifyText(OutputList &ol,const char *scName,const char *name,const char * // add link to the result if (external ? cd->isLinkable() : cd->isLinkableInProject()) { - ol.writeObjectLink(cd->getReference(),cd->getOutputFileBase(),0,word); + //ol.writeObjectLink(cd->getReference(),cd->getOutputFileBase(),0,word); + out.writeLink(cd->getReference(),cd->getOutputFileBase(),0,word); found=TRUE; } } @@ -450,7 +479,9 @@ void linkifyText(OutputList &ol,const char *scName,const char *name,const char * if (cd) d=cd; else if (nd) d=nd; else if (fd) d=fd; else d=gd; if (d && (external ? d->isLinkable() : d->isLinkableInProject())) { - ol.writeObjectLink(d->getReference(),d->getOutputFileBase(), + //ol.writeObjectLink(d->getReference(),d->getOutputFileBase(), + // md->anchor(),word); + out.writeLink(d->getReference(),d->getOutputFileBase(), md->anchor(),word); found=TRUE; } @@ -458,19 +489,22 @@ void linkifyText(OutputList &ol,const char *scName,const char *name,const char * if (!found) // add word to the result { - ol.docify(word); + //ol.docify(word); + out.writeString(word); } } else { - ol.docify(word); + //ol.docify(word); + out.writeString(word); } // set next start point in the string skipIndex=index=newIndex+matchLen; floatingIndex+=matchLen; } // add last part of the string to the result. - ol.docify(txtStr.right(txtStr.length()-skipIndex)); + //ol.docify(txtStr.right(txtStr.length()-skipIndex)); + out.writeString(txtStr.right(txtStr.length()-skipIndex)); } @@ -2016,7 +2050,7 @@ bool generateLink(OutputList &ol,const char *clName, } else if ((pi=exampleDict[linkRef])) // link to an example { - ol.writeObjectLink(0,convertSlashes(pi->name,TRUE)+"-example",0,lt); + ol.writeObjectLink(0,convertFileName(pi->name)+"-example",0,lt); return TRUE; } else if ((gd=groupDict[linkRef])) // link to a group @@ -2034,6 +2068,7 @@ bool generateLink(OutputList &ol,const char *clName, { // link to documented input file ol.writeObjectLink(fd->getReference(),fd->getOutputFileBase(),0,lt); + writePageRef(ol,fd->getOutputFileBase(),0); return TRUE; } else // probably a class or member reference @@ -2084,13 +2119,13 @@ QCString substituteClassNames(const QCString &s) //---------------------------------------------------------------------- -QCString convertSlashes(const QCString &s,bool dots) +QCString convertFileName(const QCString &s) { QCString result; int i,l=s.length(); for (i=0;i<l;i++) { - if (s.at(i)!='/' && (!dots || s.at(i)!='.')) + if (s.at(i)!='/' && s.at(i)!='.') { if (Config::caseSensitiveNames) { @@ -2299,7 +2334,7 @@ bool hasVisibleRoot(BaseClassList *bcl) return FALSE; } -QCString convertNameToFile(const char *name) +QCString convertNameToFile(const char *name,bool allowDots) { QCString result; char c; @@ -2316,6 +2351,7 @@ QCString convertNameToFile(const char *name) case '|': result+="_p_"; break; case '!': result+="_e_"; break; case ',': result+="_x_"; break; + case '.': if (allowDots) result+="."; else result+="_"; break; case ' ': break; default: if (Config::caseSensitiveNames) @@ -2325,6 +2361,7 @@ QCString convertNameToFile(const char *name) break; } } + //printf("convertNameToFile(%s)=`%s'\n",name,result.data()); return result; } @@ -23,6 +23,9 @@ #include <qtextstream.h> #include <ctype.h> +#include "outputlist.h" +#include "xml.h" + class ClassDef; class FileDef; class MemberList; @@ -36,12 +39,69 @@ class ClassList; class BaseClassList; class GroupDef; class NamespaceList; +class OutputList; + +class TextGeneratorIntf +{ + public: + virtual void writeString(const char *) const = 0; + virtual void writeBreak() const = 0; + virtual void writeLink(const char *extRef,const char *file, + const char *anchor,const char *text + ) const = 0; +}; + +class TextGeneratorOLImpl : public TextGeneratorIntf +{ + public: + TextGeneratorOLImpl(OutputList &ol) : m_ol(ol) {} + void writeString(const char *s) const + { m_ol.docify(s); } + void writeBreak() const + { + m_ol.pushGeneratorState(); + m_ol.disableAllBut(OutputGenerator::Html); + m_ol.lineBreak(); + m_ol.popGeneratorState(); + } + void writeLink(const char *extRef,const char *file, + const char *anchor,const char *text + ) const + { + m_ol.writeObjectLink(extRef,file,anchor,text); + } + private: + OutputList &m_ol; +}; + +class TextGeneratorXMLImpl : public TextGeneratorIntf +{ + public: + TextGeneratorXMLImpl(QTextStream &t) : m_t(t) {} + void writeString(const char *s) const + { + writeXMLString(m_t,s); + } + void writeBreak() const {} + void writeLink(const char *extRef,const char *file, + const char *anchor,const char *text + ) const + { + if (extRef==0) + { writeXMLLink(m_t,file,anchor,text); } + else // external references are not supported for XML + { writeXMLString(m_t,text); } + } + private: + QTextStream &m_t; +}; + +extern void linkifyText(const TextGeneratorIntf &ol,const char *clName,const char *name, + const char *text,bool autoBreak=FALSE,bool external=TRUE); extern void setAnchors(char id,MemberList *ml,int groupId=-1); extern QCString fileToString(const char *name); extern QCString dateToString(bool); -extern void linkifyText(OutputList &ol,const char *clName,const char *name, - const char *text,bool autoBreak=FALSE,bool external=TRUE); extern bool getDefs(const QCString &scopeName,const QCString &memberName, const char *, MemberDef *&md, ClassDef *&cd,FileDef *&fd, @@ -58,7 +118,7 @@ extern bool matchArguments(ArgumentList *,ArgumentList *, NamespaceList *usingList=0); extern void mergeArguments(ArgumentList *,ArgumentList *); extern QCString substituteClassNames(const QCString &s); -extern QCString convertSlashes(const QCString &s,bool dots=FALSE); +extern QCString convertFileName(const QCString &s); extern QCString substitute(const char *s,const char *src,const char *dst); extern QCString resolveDefines(const char *n); extern ClassDef *getClass(const char *key); @@ -92,7 +152,7 @@ QCString removeAnnonymousScopes(const QCString &s); void initClassHierarchy(ClassList *cl); bool hasVisibleRoot(BaseClassList *bcl); int minClassDistance(ClassDef *cd,ClassDef *bcd,int level=0); -QCString convertNameToFile(const char *name); +QCString convertNameToFile(const char *name,bool allowDots=FALSE); void extractNamespaceName(const QCString &scopeName, QCString &className,QCString &namespaceName); QCString insertTemplateSpecifierInScope(const QCString &scope,const QCString &templ); diff --git a/src/xml.cpp b/src/xml.cpp new file mode 100644 index 0000000..fd2cf45 --- /dev/null +++ b/src/xml.cpp @@ -0,0 +1,139 @@ +/****************************************************************************** + * + * + * + * + * Copyright (C) 1997-2000 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. + * + * Documents produced by Doxygen are derivative works derived from the + * input used in their production; they are not affected by this license. + * + */ + +#include "qtbc.h" +#include "xml.h" +#include "doxygen.h" +#include "message.h" +#include "config.h" +#include "classlist.h" + +#include <qdir.h> +#include <qfile.h> +#include <qtextstream.h> + +const char dtd_data[]= +#include "xml_dtd.h" +; + +void generateDTD() +{ + QCString fileName=Config::outputDir+"/xml/doxygen.dtd"; + QFile f(fileName); + if (!f.open(IO_WriteOnly)) + { + err("Cannot open file %s for writing!\n",fileName.data()); + return; + } + QTextStream t(&f); + t << dtd_data; +} + +void writeXMLString(QTextStream &t,const char *s) +{ + if (s==0) return; + const char *p=s; + char c; + while ((c=*p++)) + { + switch (c) + { + case '<': t << "<"; break; + case '>': t << ">"; break; + case '&': t << "&"; break; + case '\'': t << "'"; break; + case '"': t << """; break; + default: t << c; break; + } + } +} + +void writeXMLLink(QTextStream &t,const char *compoundId,const char *memId, + const char *text) +{ + if (memId==0) + { + t << "<compoundref idref=\"" << compoundId << "\">"; + writeXMLString(t,text); + t << "</compoundref>"; + } + else + { + t << "<memberref idref=\"" << compoundId << ":" << memId << "\">"; + writeXMLString(t,text); + t << "</memberref>"; + } +} + +void generateXML() +{ + QDir dir(Config::outputDir); + if (!dir.exists()) + { + dir.setPath(QDir::currentDirPath()); + if (!dir.mkdir(Config::outputDir)) + { + err("Cannot create directory %s\n",Config::outputDir.data()); + return; + } + } + QDir xmlDir(Config::outputDir+"/xml"); + if (!xmlDir.exists() && !xmlDir.mkdir(Config::outputDir+"/xml")) + { + err("Could not create xml directory in %s\n",Config::outputDir.data()); + return; + } + generateDTD(); + + QCString fileName=Config::outputDir+"/xml/doxygen.xml"; + QFile f(fileName); + if (!f.open(IO_WriteOnly)) + { + err("Cannot open file %s for writing!\n",fileName.data()); + return; + } + QTextStream t(&f); + t << "<?xml version='1.0' encoding='ISO-8859-1' standalone='no'?>" << endl; + t << "<!DOCTYPE doxygen SYSTEM \"doxygen.dtd\">" << endl; + t << "<doxygen>" << endl; + if (classList.count()+inputNameList.count()>0) + { + t << " <compoundlist>" << endl; + ClassListIterator cli(classList); + ClassDef *cd; + for (cli.toFirst();(cd=cli.current());++cli) + { + cd->generateXML(t); + } + FileNameListIterator fnli(inputNameList); + FileName *fn; + for (;(fn=fnli.current());++fnli) + { + FileNameIterator fni(*fn); + FileDef *fd; + for (;(fd=fni.current());++fni) + { + fd->generateXML(t); + } + } + t << " </compoundlist>" << endl; + } + t << "</doxygen>" << endl; +} + + diff --git a/src/xml.h b/src/xml.h new file mode 100644 index 0000000..ee0f85f --- /dev/null +++ b/src/xml.h @@ -0,0 +1,25 @@ +/****************************************************************************** + * + * + * + * Copyright (C) 1997-2000 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. + * + */ + +#ifndef XML_H +#define XML_H + +class QTextStream; + +void generateXML(); +void writeXMLString(QTextStream &t,const char *s); +void writeXMLLink(QTextStream &t,const char *compoundRef,const char *memAnchor, + const char *text); + +#endif diff --git a/src/xml_dtd.h b/src/xml_dtd.h new file mode 100644 index 0000000..f43db77 --- /dev/null +++ b/src/xml_dtd.h @@ -0,0 +1,115 @@ +"<?xml encoding=\"ISO-8859-1\"?>\n" +"<!-- DTD describing the grammar used in doxygen's XML output -->\n" +"\n" +"<!-- standard character entities -->\n" +"<!ENTITY lt \"&#60;\"> \n" +"<!ENTITY gt \">\"> \n" +"<!ENTITY amp \"&#38;\"> \n" +"<!ENTITY apos \"'\"> \n" +"<!ENTITY quot \""\"> \n" +"\n" +"<!-- required attributes for compounds -->\n" +"<!ENTITY % compound-req.att \n" +" 'id ID #REQUIRED\n" +" type (group|file|namespace|\n" +" class|struct|union|\n" +" interface|dispinterface|\n" +" valuetype|library) #REQUIRED'\n" +">\n" +"<!-- required attributes for references -->\n" +"<!ENTITY % ref-req.att 'idref IDREF #REQUIRED'\n" +">\n" +"<!-- required attributes for inheritance relations -->\n" +"<!ENTITY % inheritcompref-req.att\n" +" '%ref-req.att;\n" +" prot (public|protected|private) #REQUIRED\n" +" virt (non-virtual|virtual) #REQUIRED'\n" +">\n" +"\n" +"<!-- required attributes for member sections -->\n" +"<!ENTITY % sec-req.att 'type (user\n" +" |public-type\n" +" |public-func\n" +" |public-attrib\n" +" |public-slot\n" +" |public-static-func\n" +" |public-static-attrib\n" +" |protected-type\n" +" |protected-func\n" +" |protected-attrib\n" +" |protected-slot\n" +" |protected-static-func\n" +" |protected-static-attrib\n" +" |private-type\n" +" |private-func\n" +" |private-attrib\n" +" |private-slot\n" +" |private-static-func\n" +" |private-static-attrib\n" +" |signal\n" +" |friend\n" +" |related\n" +" |define|prototype|typedef|enum|func|var\n" +" ) #REQUIRED\n" +" '\n" +">\n" +"<!-- required attributes for members -->\n" +"<!ENTITY % mem-req.att 'id ID #REQUIRED'>\n" +"\n" +"<!-- optional attributes for function -->\n" +"<!ENTITY % func-opt.att 'virt (virtual|pure-virtual) #IMPLIED'>\n" +"\n" +"<!-- elements -->\n" +"<!ELEMENT doxygen (compoundlist?)>\n" +"<!ELEMENT compoundlist (compounddef)+>\n" +"<!ELEMENT compounddef (compoundname,\n" +" basecompoundlist?, \n" +" derivedcompoundlist?, \n" +" sectionlist? \n" +" )\n" +">\n" +"<!ATTLIST compounddef %compound-req.att;>\n" +"<!ELEMENT basecompoundlist (basecompoundref)+>\n" +"<!ELEMENT derivedcompoundlist (derivedcompoundref)+>\n" +"<!ELEMENT compoundref (#PCDATA)>\n" +"<!ATTLIST compoundref %ref-req.att;>\n" +"<!ELEMENT memberref (#PCDATA)>\n" +"<!ATTLIST memberref %ref-req.att;>\n" +"<!ELEMENT basecompoundref EMPTY>\n" +"<!ATTLIST basecompoundref %inheritcompref-req.att;>\n" +"<!ELEMENT derivedcompoundref EMPTY>\n" +"<!ATTLIST derivedcompoundref %inheritcompref-req.att;>\n" +"<!ELEMENT sectionlist (sectiondef)+>\n" +"<!ELEMENT sectiondef (memberlist)>\n" +"<!ATTLIST sectiondef %sec-req.att;>\n" +"<!ELEMENT memberlist (functiondef|variabledef|typedef|definedef|enumdef)+>\n" +"<!ELEMENT functiondef (type?,name,paramlist)>\n" +"<!ATTLIST functiondef %mem-req.att; %func-opt.att;>\n" +"<!ELEMENT variabledef (type,name,array?,initializer?)>\n" +"<!ATTLIST variabledef %mem-req.att;>\n" +"<!ELEMENT typedef (type,name)>\n" +"<!ATTLIST typedef %mem-req.att;>\n" +"<!ELEMENT definedef (name,defparamlist?,initializer?)>\n" +"<!ATTLIST definedef %mem-req.att;>\n" +"<!ELEMENT enumdef (name,enumvaluelist)>\n" +"<!ATTLIST enumdef %mem-req.att;>\n" +"<!ELEMENT slotdef (type,name,paramlist)>\n" +"<!ATTLIST slotdef %mem-req.att;>\n" +"<!ELEMENT signaldef (type,name,paramlist)>\n" +"<!ATTLIST signaldef %mem-req.att;>\n" +"<!ELEMENT paramlist (param)*>\n" +"<!ELEMENT param (attributes?,type,declname?,defname?,array?,defval?)>\n" +"<!ELEMENT defparamlist (defarg)*>\n" +"<!ELEMENT defarg (#PCDATA)>\n" +"<!ELEMENT enumvaluelist (enumvalue)*>\n" +"<!ELEMENT enumvalue (name,initializer?)>\n" +"<!ELEMENT name (#PCDATA)>\n" +"<!ELEMENT compoundname (#PCDATA)>\n" +"<!ELEMENT declname (#PCDATA)>\n" +"<!ELEMENT defname (#PCDATA)>\n" +"<!ELEMENT type (#PCDATA|memberref|compoundref|compounddef)*>\n" +"<!ELEMENT defval (#PCDATA|memberref|compoundref)*>\n" +"<!ELEMENT initializer (#PCDATA|memberref|compoundref)*>\n" +"<!ELEMENT array (#PCDATA)>\n" +"<!ELEMENT attributes (#PCDATA)>\n" +"\n" |