diff options
author | Anas Nashif <anas.nashif@intel.com> | 2012-11-08 06:36:54 -0800 |
---|---|---|
committer | Anas Nashif <anas.nashif@intel.com> | 2012-11-08 06:36:54 -0800 |
commit | cccf3a7c7888ce7bd7a8f8d48a34c5474ad9feeb (patch) | |
tree | 7f31b77ace4359e85dc3d3f66c853858c0bca7a4 /src/xmlgen.cpp | |
download | doxygen-cccf3a7c7888ce7bd7a8f8d48a34c5474ad9feeb.tar.gz doxygen-cccf3a7c7888ce7bd7a8f8d48a34c5474ad9feeb.tar.bz2 doxygen-cccf3a7c7888ce7bd7a8f8d48a34c5474ad9feeb.zip |
Imported Upstream version 1.8.2upstream/1.8.2
Diffstat (limited to 'src/xmlgen.cpp')
-rw-r--r-- | src/xmlgen.cpp | 2024 |
1 files changed, 2024 insertions, 0 deletions
diff --git a/src/xmlgen.cpp b/src/xmlgen.cpp new file mode 100644 index 0000000..5c71cd6 --- /dev/null +++ b/src/xmlgen.cpp @@ -0,0 +1,2024 @@ +/****************************************************************************** + * + * Copyright (C) 1997-2012 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 <stdlib.h> + +#include "qtbc.h" +#include "xmlgen.h" +#include "doxygen.h" +#include "message.h" +#include "config.h" +#include "classlist.h" +#include "util.h" +#include "defargs.h" +#include "outputgen.h" +#include "dot.h" +#include "pagedef.h" +#include "filename.h" +#include "version.h" +#include "xmldocvisitor.h" +#include "docparser.h" +#include "language.h" +#include "parserintf.h" +#include "arguments.h" + +#include <qdir.h> +#include <qfile.h> +#include <qtextstream.h> +#include <qintdict.h> + +// no debug info +#define XML_DB(x) do {} while(0) +// debug to stdout +//#define XML_DB(x) printf x +// debug inside output +//#define XML_DB(x) QCString __t;__t.sprintf x;m_t << __t + +//------------------ + +static const char index_xsd[] = +#include "index_xsd.h" +; + +//------------------ +// +static const char compound_xsd[] = +#include "compound_xsd.h" +; + +//------------------ + +/** Helper class mapping MemberList::ListType to a string representing */ +class XmlSectionMapper : public QIntDict<char> +{ + public: + XmlSectionMapper() : QIntDict<char>(47) + { + insert(MemberList::pubTypes,"public-type"); + insert(MemberList::pubMethods,"public-func"); + insert(MemberList::pubAttribs,"public-attrib"); + insert(MemberList::pubSlots,"public-slot"); + insert(MemberList::signals,"signal"); + insert(MemberList::dcopMethods,"dcop-func"); + insert(MemberList::properties,"property"); + insert(MemberList::events,"event"); + insert(MemberList::pubStaticMethods,"public-static-func"); + insert(MemberList::pubStaticAttribs,"public-static-attrib"); + insert(MemberList::proTypes,"protected-type"); + insert(MemberList::proMethods,"protected-func"); + insert(MemberList::proAttribs,"protected-attrib"); + insert(MemberList::proSlots,"protected-slot"); + insert(MemberList::proStaticMethods,"protected-static-func"); + insert(MemberList::proStaticAttribs,"protected-static-attrib"); + insert(MemberList::pacTypes,"package-type"); + insert(MemberList::pacMethods,"package-func"); + insert(MemberList::pacAttribs,"package-attrib"); + insert(MemberList::pacStaticMethods,"package-static-func"); + insert(MemberList::pacStaticAttribs,"package-static-attrib"); + insert(MemberList::priTypes,"private-type"); + insert(MemberList::priMethods,"private-func"); + insert(MemberList::priAttribs,"private-attrib"); + insert(MemberList::priSlots,"private-slot"); + insert(MemberList::priStaticMethods,"private-static-func"); + insert(MemberList::priStaticAttribs,"private-static-attrib"); + insert(MemberList::friends,"friend"); + insert(MemberList::related,"related"); + insert(MemberList::decDefineMembers,"define"); + insert(MemberList::decProtoMembers,"prototype"); + insert(MemberList::decTypedefMembers,"typedef"); + insert(MemberList::decEnumMembers,"enum"); + insert(MemberList::decFuncMembers,"func"); + insert(MemberList::decVarMembers,"var"); + } +}; + +static XmlSectionMapper g_xmlSectionMapper; + + +inline void writeXMLString(FTextStream &t,const char *s) +{ + t << convertToXML(s); +} + +inline void writeXMLCodeString(FTextStream &t,const char *s, int &col) +{ + char c; + while ((c=*s++)) + { + switch(c) + { + case '\t': + { + static int tabSize = Config_getInt("TAB_SIZE"); + int spacesToNextTabStop = tabSize - (col%tabSize); + col+=spacesToNextTabStop; + while (spacesToNextTabStop--) t << "<sp/>"; + break; + } + case ' ': t << "<sp/>"; col++; break; + case '<': t << "<"; col++; break; + case '>': t << ">"; col++; break; + case '&': t << "&"; col++; break; + case '\'': t << "'"; col++; break; + case '"': t << """; col++; break; + default: t << c; col++; break; + } + } +} + + +static void writeXMLHeader(FTextStream &t) +{ + t << "<?xml version='1.0' encoding='UTF-8' standalone='no'?>" << endl;; + t << "<doxygen xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" "; + t << "xsi:noNamespaceSchemaLocation=\"compound.xsd\" "; + t << "version=\"" << versionString << "\">" << endl; +} + +static void writeCombineScript() +{ + QCString outputDirectory = Config_getString("XML_OUTPUT"); + QCString fileName=outputDirectory+"/combine.xslt"; + QFile f(fileName); + if (!f.open(IO_WriteOnly)) + { + err("Cannot open file %s for writing!\n",fileName.data()); + return; + } + FTextStream t(&f); + //t.setEncoding(FTextStream::UnicodeUTF8); + + t << + "<!-- XSLT script to combine the generated output into a single file. \n" + " If you have xsltproc you could use:\n" + " xsltproc combine.xslt index.xml >all.xml\n" + "-->\n" + "<xsl:stylesheet xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" version=\"1.0\">\n" + " <xsl:output method=\"xml\" version=\"1.0\" indent=\"no\" standalone=\"yes\" />\n" + " <xsl:template match=\"/\">\n" + " <doxygen version=\"{doxygenindex/@version}\">\n" + " <!-- Load all doxgen generated xml files -->\n" + " <xsl:for-each select=\"doxygenindex/compound\">\n" + " <xsl:copy-of select=\"document( concat( @refid, '.xml' ) )/doxygen/*\" />\n" + " </xsl:for-each>\n" + " </doxygen>\n" + " </xsl:template>\n" + "</xsl:stylesheet>\n"; + +} + +void writeXMLLink(FTextStream &t,const char *extRef,const char *compoundId, + const char *anchorId,const char *text,const char *tooltip) +{ + t << "<ref refid=\"" << compoundId; + if (anchorId) t << "_1" << anchorId; + t << "\" kindref=\""; + if (anchorId) t << "member"; else t << "compound"; + t << "\""; + if (extRef) t << " external=\"" << extRef << "\""; + if (tooltip) t << " tooltip=\"" << convertToXML(tooltip) << "\""; + t << ">"; + writeXMLString(t,text); + t << "</ref>"; +} + +/** Implements TextGeneratorIntf for an XML stream. */ +class TextGeneratorXMLImpl : public TextGeneratorIntf +{ + public: + TextGeneratorXMLImpl(FTextStream &t): m_t(t) {} + void writeString(const char *s,bool /*keepSpaces*/) const + { + writeXMLString(m_t,s); + } + void writeBreak(int) const {} + void writeLink(const char *extRef,const char *file, + const char *anchor,const char *text + ) const + { + writeXMLLink(m_t,extRef,file,anchor,text,0); + } + private: + FTextStream &m_t; +}; + +/** Helper class representing a stack of objects stored by value */ +template<class T> class ValStack +{ + public: + ValStack() : m_values(10), m_sp(0), m_size(10) {} + virtual ~ValStack() {} + ValStack(const ValStack<T> &s) + { + m_values=s.m_values.copy(); + m_sp=s.m_sp; + m_size=s.m_size; + } + ValStack &operator=(const ValStack<T> &s) + { + m_values=s.m_values.copy(); + m_sp=s.m_sp; + m_size=s.m_size; + return *this; + } + void push(T v) + { + m_sp++; + if (m_sp>=m_size) + { + m_size+=10; + m_values.resize(m_size); + } + m_values[m_sp]=v; + } + T pop() + { + ASSERT(m_sp!=0); + return m_values[m_sp--]; + } + T& top() + { + ASSERT(m_sp!=0); + return m_values[m_sp]; + } + bool isEmpty() + { + return m_sp==0; + } + uint count() const + { + return m_sp; + } + + private: + QArray<T> m_values; + int m_sp; + int m_size; +}; + +/** Generator for producing XML formatted source code. */ +class XMLCodeGenerator : public CodeOutputInterface +{ + public: + + XMLCodeGenerator(FTextStream &t) : m_t(t), m_lineNumber(-1), + m_insideCodeLine(FALSE), m_normalHLNeedStartTag(TRUE), + m_insideSpecialHL(FALSE) {} + virtual ~XMLCodeGenerator() { } + + void codify(const char *text) + { + XML_DB(("(codify \"%s\")\n",text)); + if (m_insideCodeLine && !m_insideSpecialHL && m_normalHLNeedStartTag) + { + m_t << "<highlight class=\"normal\">"; + m_normalHLNeedStartTag=FALSE; + } + writeXMLCodeString(m_t,text,col); + } + void writeCodeLink(const char *ref,const char *file, + const char *anchor,const char *name, + const char *tooltip) + { + XML_DB(("(writeCodeLink)\n")); + if (m_insideCodeLine && !m_insideSpecialHL && m_normalHLNeedStartTag) + { + m_t << "<highlight class=\"normal\">"; + m_normalHLNeedStartTag=FALSE; + } + writeXMLLink(m_t,ref,file,anchor,name,tooltip); + col+=strlen(name); + } + void startCodeLine(bool) + { + XML_DB(("(startCodeLine)\n")); + m_t << "<codeline"; + if (m_lineNumber!=-1) + { + m_t << " lineno=\"" << m_lineNumber << "\""; + if (!m_refId.isEmpty()) + { + m_t << " refid=\"" << m_refId << "\""; + if (m_isMemberRef) + { + m_t << " refkind=\"member\""; + } + else + { + m_t << " refkind=\"compound\""; + } + } + if (!m_external.isEmpty()) + { + m_t << " external=\"" << m_external << "\""; + } + } + m_t << ">"; + m_insideCodeLine=TRUE; + col=0; + } + void endCodeLine() + { + XML_DB(("(endCodeLine)\n")); + if (!m_insideSpecialHL && !m_normalHLNeedStartTag) + { + m_t << "</highlight>"; + m_normalHLNeedStartTag=TRUE; + } + m_t << "</codeline>" << endl; // non DocBook + m_lineNumber = -1; + m_refId.resize(0); + m_external.resize(0); + m_insideCodeLine=FALSE; + } + void startCodeAnchor(const char *id) + { + XML_DB(("(startCodeAnchor)\n")); + if (m_insideCodeLine && !m_insideSpecialHL && m_normalHLNeedStartTag) + { + m_t << "<highlight class=\"normal\">"; + m_normalHLNeedStartTag=FALSE; + } + m_t << "<anchor id=\"" << id << "\">"; + } + void endCodeAnchor() + { + XML_DB(("(endCodeAnchor)\n")); + m_t << "</anchor>"; + } + void startFontClass(const char *colorClass) + { + XML_DB(("(startFontClass)\n")); + if (m_insideCodeLine && !m_insideSpecialHL && !m_normalHLNeedStartTag) + { + m_t << "</highlight>"; + m_normalHLNeedStartTag=TRUE; + } + m_t << "<highlight class=\"" << colorClass << "\">"; // non DocBook + m_insideSpecialHL=TRUE; + } + void endFontClass() + { + XML_DB(("(endFontClass)\n")); + m_t << "</highlight>"; // non DocBook + m_insideSpecialHL=FALSE; + } + void writeCodeAnchor(const char *) + { + XML_DB(("(writeCodeAnchor)\n")); + } + void writeLineNumber(const char *extRef,const char *compId, + const char *anchorId,int l) + { + XML_DB(("(writeLineNumber)\n")); + // we remember the information provided here to use it + // at the <codeline> start tag. + m_lineNumber = l; + if (compId) + { + m_refId=compId; + if (anchorId) m_refId+=(QCString)"_1"+anchorId; + m_isMemberRef = anchorId!=0; + if (extRef) m_external=extRef; + } + } + void linkableSymbol(int, const char *,Definition *,Definition *) + { + } + + void finish() + { + if (m_insideCodeLine) endCodeLine(); + } + + private: + FTextStream &m_t; + QCString m_refId; + QCString m_external; + int m_lineNumber; + bool m_isMemberRef; + int col; + + bool m_insideCodeLine; + bool m_normalHLNeedStartTag; + bool m_insideSpecialHL; +}; + + +static void writeTemplateArgumentList(ArgumentList *al, + FTextStream &t, + Definition *scope, + FileDef *fileScope, + int indent) +{ + QCString indentStr; + indentStr.fill(' ',indent); + if (al) + { + t << indentStr << "<templateparamlist>" << endl; + ArgumentListIterator ali(*al); + Argument *a; + for (ali.toFirst();(a=ali.current());++ali) + { + t << indentStr << " <param>" << endl; + if (!a->type.isEmpty()) + { + t << indentStr << " <type>"; + linkifyText(TextGeneratorXMLImpl(t),scope,fileScope,0,a->type); + t << "</type>" << endl; + } + if (!a->name.isEmpty()) + { + t << indentStr << " <declname>" << a->name << "</declname>" << endl; + t << indentStr << " <defname>" << a->name << "</defname>" << endl; + } + if (!a->defval.isEmpty()) + { + t << indentStr << " <defval>"; + linkifyText(TextGeneratorXMLImpl(t),scope,fileScope,0,a->defval); + t << "</defval>" << endl; + } + t << indentStr << " </param>" << endl; + } + t << indentStr << "</templateparamlist>" << endl; + } +} + +static void writeMemberTemplateLists(MemberDef *md,FTextStream &t) +{ + LockingPtr<ArgumentList> templMd = md->templateArguments(); + if (templMd!=0) // function template prefix + { + writeTemplateArgumentList(templMd.pointer(),t,md->getClassDef(),md->getFileDef(),8); + } +} + +static void writeTemplateList(ClassDef *cd,FTextStream &t) +{ + writeTemplateArgumentList(cd->templateArguments(),t,cd,0,4); +} + +static void writeXMLDocBlock(FTextStream &t, + const QCString &fileName, + int lineNr, + Definition *scope, + MemberDef * md, + const QCString &text) +{ + QCString stext = text.stripWhiteSpace(); + if (stext.isEmpty()) return; + // convert the documentation string into an abstract syntax tree + DocNode *root = validatingParseDoc(fileName,lineNr,scope,md,text+"\n",FALSE,FALSE); + // create a code generator + XMLCodeGenerator *xmlCodeGen = new XMLCodeGenerator(t); + // create a parse tree visitor for XML + XmlDocVisitor *visitor = new XmlDocVisitor(t,*xmlCodeGen); + // visit all nodes + root->accept(visitor); + // clean up + delete visitor; + delete xmlCodeGen; + delete root; + +} + +void writeXMLCodeBlock(FTextStream &t,FileDef *fd) +{ + ParserInterface *pIntf=Doxygen::parserManager->getParser(fd->getDefFileExtension()); + pIntf->resetCodeParserState(); + XMLCodeGenerator *xmlGen = new XMLCodeGenerator(t); + pIntf->parseCode(*xmlGen, // codeOutIntf + 0, // scopeName + fileToString(fd->absFilePath(),Config_getBool("FILTER_SOURCE_FILES")), + FALSE, // isExampleBlock + 0, // exampleName + fd, // fileDef + -1, // startLine + -1, // endLine + FALSE, // inlineFragement + 0, // memberDef + TRUE // showLineNumbers + ); + xmlGen->finish(); + delete xmlGen; +} + +static void writeMemberReference(FTextStream &t,Definition *def,MemberDef *rmd,const char *tagName) +{ + QCString scope = rmd->getScopeString(); + QCString name = rmd->name(); + if (!scope.isEmpty() && scope!=def->name()) + { + name.prepend(scope+getLanguageSpecificSeparator(rmd->getLanguage())); + } + t << " <" << tagName << " refid=\""; + t << rmd->getOutputFileBase() << "_1" << rmd->anchor() << "\""; + if (rmd->getStartBodyLine()!=-1 && rmd->getBodyDef()) + { + t << " compoundref=\"" << rmd->getBodyDef()->getOutputFileBase() << "\""; + t << " startline=\"" << rmd->getStartBodyLine() << "\""; + if (rmd->getEndBodyLine()!=-1) + { + t << " endline=\"" << rmd->getEndBodyLine() << "\""; + } + } + t << ">" << convertToXML(name) << "</" << tagName << ">" << endl; + +} + +static void stripQualifiers(QCString &typeStr) +{ + bool done=FALSE; + while (!done) + { + if (typeStr.stripPrefix("static ")); + else if (typeStr.stripPrefix("virtual ")); + else if (typeStr.stripPrefix("volatile ")); + else if (typeStr=="virtual") typeStr=""; + else done=TRUE; + } +} + +static QCString classOutputFileBase(ClassDef *cd) +{ + //static bool inlineGroupedClasses = Config_getBool("INLINE_GROUPED_CLASSES"); + //if (inlineGroupedClasses && cd->partOfGroups()!=0) + return cd->getOutputFileBase(); + //else + // return cd->getOutputFileBase(); +} + +static QCString memberOutputFileBase(MemberDef *md) +{ + //static bool inlineGroupedClasses = Config_getBool("INLINE_GROUPED_CLASSES"); + //if (inlineGroupedClasses && md->getClassDef() && md->getClassDef()->partOfGroups()!=0) + // return md->getClassDef()->getXmlOutputFileBase(); + //else + // return md->getOutputFileBase(); + return md->getOutputFileBase(); +} + + +static void generateXMLForMember(MemberDef *md,FTextStream &ti,FTextStream &t,Definition *def) +{ + + // + declaration/definition arg lists + // + reimplements + // + reimplementedBy + // + exceptions + // + const/volatile specifiers + // - examples + // + source definition + // + source references + // + source referenced by + // - body code + // + template arguments + // (templateArguments(), definitionTemplateParameterLists()) + // - call graph + + // enum values are written as part of the enum + if (md->memberType()==MemberDef::EnumValue) return; + if (md->isHidden()) return; + //if (md->name().at(0)=='@') return; // anonymous member + + // group members are only visible in their group + //if (def->definitionType()!=Definition::TypeGroup && md->getGroupDef()) return; + + QCString memType; + bool isFunc=FALSE; + switch (md->memberType()) + { + case MemberDef::Define: memType="define"; break; + case MemberDef::EnumValue: ASSERT(0); break; + case MemberDef::Property: memType="property"; break; + case MemberDef::Event: memType="event"; break; + case MemberDef::Variable: memType="variable"; break; + case MemberDef::Typedef: memType="typedef"; break; + case MemberDef::Enumeration: memType="enum"; break; + case MemberDef::Function: memType="function"; isFunc=TRUE; break; + case MemberDef::Signal: memType="signal"; isFunc=TRUE; break; + case MemberDef::Friend: memType="friend"; isFunc=TRUE; break; + case MemberDef::DCOP: memType="dcop"; isFunc=TRUE; break; + case MemberDef::Slot: memType="slot"; isFunc=TRUE; break; + } + + ti << " <member refid=\"" << memberOutputFileBase(md) + << "_1" << md->anchor() << "\" kind=\"" << memType << "\"><name>" + << convertToXML(md->name()) << "</name></member>" << endl; + + QCString scopeName; + if (md->getClassDef()) + scopeName=md->getClassDef()->name(); + else if (md->getNamespaceDef()) + scopeName=md->getNamespaceDef()->name(); + + t << " <memberdef kind=\""; + //enum { define_t,variable_t,typedef_t,enum_t,function_t } xmlType = function_t; + t << memType << "\" id=\""; + if (md->getGroupDef() && def->definitionType()==Definition::TypeGroup) + { + t << md->getGroupDef()->getOutputFileBase(); + } + else + { + t << memberOutputFileBase(md); + } + t << "_1" // encoded `:' character (see util.cpp:convertNameToFile) + << md->anchor(); + t << "\" prot=\""; + switch(md->protection()) + { + case Public: t << "public"; break; + case Protected: t << "protected"; break; + case Private: t << "private"; break; + case Package: t << "package"; break; + } + t << "\""; + + t << " static=\""; + if (md->isStatic()) t << "yes"; else t << "no"; + t << "\""; + + if (isFunc) + { + LockingPtr<ArgumentList> al = md->argumentList(); + t << " const=\""; + if (al!=0 && al->constSpecifier) t << "yes"; else t << "no"; + t << "\""; + + t << " explicit=\""; + if (md->isExplicit()) t << "yes"; else t << "no"; + t << "\""; + + t << " inline=\""; + if (md->isInline()) t << "yes"; else t << "no"; + t << "\""; + + if (md->isFinal()) + { + t << " final=\"yes\""; + } + + if (md->isSealed()) + { + t << " sealed=\"yes\""; + } + + if (md->isNew()) + { + t << " new=\"yes\""; + } + + if (md->isOptional()) + { + t << " optional=\"yes\""; + } + + if (md->isRequired()) + { + t << " required=\"yes\""; + } + + t << " virt=\""; + switch (md->virtualness()) + { + case Normal: t << "non-virtual"; break; + case Virtual: t << "virtual"; break; + case Pure: t << "pure-virtual"; break; + default: ASSERT(0); + } + t << "\""; + } + + if (md->memberType() == MemberDef::Variable) + { + //ArgumentList *al = md->argumentList(); + //t << " volatile=\""; + //if (al && al->volatileSpecifier) t << "yes"; else t << "no"; + + t << " mutable=\""; + if (md->isMutable()) t << "yes"; else t << "no"; + t << "\""; + + if (md->isInitonly()) + { + t << " initonly=\"yes\""; + } + + } + else if (md->memberType() == MemberDef::Property) + { + t << " readable=\""; + if (md->isReadable()) t << "yes"; else t << "no"; + t << "\""; + + t << " writable=\""; + if (md->isWritable()) t << "yes"; else t << "no"; + t << "\""; + + t << " gettable=\""; + if (md->isGettable()) t << "yes"; else t << "no"; + t << "\""; + + t << " settable=\""; + if (md->isSettable()) t << "yes"; else t << "no"; + t << "\""; + + if (md->isAssign() || md->isCopy() || md->isRetain() || md->isStrong() || md->isWeak()) + { + t << " accessor=\""; + if (md->isAssign()) t << "assign"; + else if (md->isCopy()) t << "copy"; + else if (md->isRetain()) t << "retain"; + else if (md->isStrong()) t << "strong"; + else if (md->isWeak()) t << "weak"; + t << "\""; + } + } + else if (md->memberType() == MemberDef::Event) + { + t << " add=\""; + if (md->isAddable()) t << "yes"; else t << "no"; + t << "\""; + + t << " remove=\""; + if (md->isRemovable()) t << "yes"; else t << "no"; + t << "\""; + + t << " raise=\""; + if (md->isRaisable()) t << "yes"; else t << "no"; + t << "\""; + } + + t << ">" << endl; + + if (md->memberType()!=MemberDef::Define && + md->memberType()!=MemberDef::Enumeration + ) + { + if (md->memberType()!=MemberDef::Typedef) + { + writeMemberTemplateLists(md,t); + } + QCString typeStr = md->typeString(); //replaceAnonymousScopes(md->typeString()); + stripQualifiers(typeStr); + t << " <type>"; + linkifyText(TextGeneratorXMLImpl(t),def,md->getBodyDef(),md,typeStr); + t << "</type>" << endl; + t << " <definition>" << convertToXML(md->definition()) << "</definition>" << endl; + t << " <argsstring>" << convertToXML(md->argsString()) << "</argsstring>" << endl; + } + + t << " <name>" << convertToXML(md->name()) << "</name>" << endl; + + if (md->memberType() == MemberDef::Property) + { + if (md->isReadable()) + t << " <read>" << convertToXML(md->getReadAccessor()) << "</read>" << endl; + if (md->isWritable()) + t << " <write>" << convertToXML(md->getWriteAccessor()) << "</write>" << endl; + } + if (md->memberType()==MemberDef::Variable && md->bitfieldString()) + { + QCString bitfield = md->bitfieldString(); + if (bitfield.at(0)==':') bitfield=bitfield.mid(1); + t << " <bitfield>" << bitfield << "</bitfield>" << endl; + } + + MemberDef *rmd = md->reimplements(); + if (rmd) + { + t << " <reimplements refid=\"" + << memberOutputFileBase(rmd) << "_1" << rmd->anchor() << "\">" + << convertToXML(rmd->name()) << "</reimplements>" << endl; + } + LockingPtr<MemberList> rbml = md->reimplementedBy(); + if (rbml!=0) + { + MemberListIterator mli(*rbml); + for (mli.toFirst();(rmd=mli.current());++mli) + { + t << " <reimplementedby refid=\"" + << memberOutputFileBase(rmd) << "_1" << rmd->anchor() << "\">" + << convertToXML(rmd->name()) << "</reimplementedby>" << endl; + } + } + + if (isFunc) //function + { + LockingPtr<ArgumentList> declAl = md->declArgumentList(); + LockingPtr<ArgumentList> defAl = md->argumentList(); + if (declAl!=0 && 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),def,md->getBodyDef(),md,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),def,md->getBodyDef(),md,a->defval); + t << "</defval>" << endl; + } + if (defArg && defArg->hasDocumentation()) + { + t << " <briefdescription>"; + writeXMLDocBlock(t,md->getDefFileName(),md->getDefLine(), + md->getOuterScope(),md,defArg->docs); + t << "</briefdescription>" << endl; + } + t << " </param>" << endl; + if (defArg) ++defAli; + } + } + } + else if (md->memberType()==MemberDef::Define && + md->argsString()) // define + { + if (md->argumentList()->count()==0) // special case for "foo()" to + // disguish it from "foo". + { + t << " <param></param>" << endl; + } + else + { + ArgumentListIterator ali(*md->argumentList()); + Argument *a; + for (ali.toFirst();(a=ali.current());++ali) + { + t << " <param><defname>" << a->type << "</defname></param>" << endl; + } + } + } + // avoid that extremely large tables are written to the output. + // todo: it's better to adhere to MAX_INITIALIZER_LINES. + if (!md->initializer().isEmpty() && md->initializer().length()<2000) + { + t << " <initializer>"; + linkifyText(TextGeneratorXMLImpl(t),def,md->getBodyDef(),md,md->initializer()); + t << "</initializer>" << endl; + } + + if (md->excpString()) + { + t << " <exceptions>"; + linkifyText(TextGeneratorXMLImpl(t),def,md->getBodyDef(),md,md->excpString()); + t << "</exceptions>" << endl; + } + + if (md->memberType()==MemberDef::Enumeration) // enum + { + LockingPtr<MemberList> enumFields = md->enumFieldList(); + if (enumFields!=0) + { + MemberListIterator emli(*enumFields); + MemberDef *emd; + for (emli.toFirst();(emd=emli.current());++emli) + { + ti << " <member refid=\"" << memberOutputFileBase(emd) + << "_1" << emd->anchor() << "\" kind=\"enumvalue\"><name>" + << convertToXML(emd->name()) << "</name></member>" << endl; + + t << " <enumvalue id=\"" << memberOutputFileBase(emd) << "_1" + << emd->anchor() << "\" prot=\""; + switch (emd->protection()) + { + case Public: t << "public"; break; + case Protected: t << "protected"; break; + case Private: t << "private"; break; + case Package: t << "package"; break; + } + t << "\">" << endl; + t << " <name>"; + writeXMLString(t,emd->name()); + t << "</name>" << endl; + if (!emd->initializer().isEmpty()) + { + t << " <initializer>"; + writeXMLString(t,emd->initializer()); + t << "</initializer>" << endl; + } + t << " <briefdescription>" << endl; + writeXMLDocBlock(t,emd->briefFile(),emd->briefLine(),emd->getOuterScope(),emd,emd->briefDescription()); + t << " </briefdescription>" << endl; + t << " <detaileddescription>" << endl; + writeXMLDocBlock(t,emd->docFile(),emd->docLine(),emd->getOuterScope(),emd,emd->documentation()); + t << " </detaileddescription>" << endl; + t << " </enumvalue>" << endl; + } + } + } + t << " <briefdescription>" << endl; + writeXMLDocBlock(t,md->briefFile(),md->briefLine(),md->getOuterScope(),md,md->briefDescription()); + t << " </briefdescription>" << endl; + t << " <detaileddescription>" << endl; + writeXMLDocBlock(t,md->docFile(),md->docLine(),md->getOuterScope(),md,md->documentation()); + t << " </detaileddescription>" << endl; + t << " <inbodydescription>" << endl; + writeXMLDocBlock(t,md->docFile(),md->inbodyLine(),md->getOuterScope(),md,md->inbodyDocumentation()); + t << " </inbodydescription>" << endl; + if (md->getDefLine()!=-1) + { + t << " <location file=\"" + << md->getDefFileName() << "\" line=\"" + << md->getDefLine() << "\""; + if (md->getStartBodyLine()!=-1) + { + FileDef *bodyDef = md->getBodyDef(); + if (bodyDef) + { + t << " bodyfile=\"" << bodyDef->absFilePath() << "\""; + } + t << " bodystart=\"" << md->getStartBodyLine() << "\" bodyend=\"" + << md->getEndBodyLine() << "\""; + } + t << "/>" << endl; + } + + //printf("md->getReferencesMembers()=%p\n",md->getReferencesMembers()); + LockingPtr<MemberSDict> mdict = md->getReferencesMembers(); + if (mdict!=0) + { + MemberSDict::Iterator mdi(*mdict); + MemberDef *rmd; + for (mdi.toFirst();(rmd=mdi.current());++mdi) + { + writeMemberReference(t,def,rmd,"references"); + } + } + mdict = md->getReferencedByMembers(); + if (mdict!=0) + { + MemberSDict::Iterator mdi(*mdict); + MemberDef *rmd; + for (mdi.toFirst();(rmd=mdi.current());++mdi) + { + writeMemberReference(t,def,rmd,"referencedby"); + } + } + + t << " </memberdef>" << endl; +} + +static void generateXMLSection(Definition *d,FTextStream &ti,FTextStream &t, + MemberList *ml,const char *kind,const char *header=0, + const char *documentation=0) +{ + if (ml==0) return; + MemberListIterator mli(*ml); + MemberDef *md; + int count=0; + for (mli.toFirst();(md=mli.current());++mli) + { + // namespace members are also inserted in the file scope, but + // to prevent this duplication in the XML output, we filter those here. + if (d->definitionType()!=Definition::TypeFile || md->getNamespaceDef()==0) + { + count++; + } + } + if (count==0) return; // empty list + + t << " <sectiondef kind=\"" << kind << "\">" << endl; + if (header) + { + t << " <header>" << convertToXML(header) << "</header>" << endl; + } + if (documentation) + { + t << " <description>"; + writeXMLDocBlock(t,d->docFile(),d->docLine(),d,0,documentation); + t << "</description>" << endl; + } + for (mli.toFirst();(md=mli.current());++mli) + { + // namespace members are also inserted in the file scope, but + // to prevent this duplication in the XML output, we filter those here. + if (d->definitionType()!=Definition::TypeFile || md->getNamespaceDef()==0) + { + generateXMLForMember(md,ti,t,d); + } + } + t << " </sectiondef>" << endl; +} + +static void writeListOfAllMembers(ClassDef *cd,FTextStream &t) +{ + t << " <listofallmembers>" << endl; + if (cd->memberNameInfoSDict()) + { + MemberNameInfoSDict::Iterator mnii(*cd->memberNameInfoSDict()); + MemberNameInfo *mni; + for (mnii.toFirst();(mni=mnii.current());++mnii) + { + MemberNameInfoIterator mii(*mni); + MemberInfo *mi; + for (mii.toFirst();(mi=mii.current());++mii) + { + MemberDef *md=mi->memberDef; + if (md->name().at(0)!='@') // skip anonymous members + { + Protection prot = mi->prot; + Specifier virt=md->virtualness(); + t << " <member refid=\"" << memberOutputFileBase(md) << "_1" << + md->anchor() << "\" prot=\""; + switch (prot) + { + case Public: t << "public"; break; + case Protected: t << "protected"; break; + case Private: t << "private"; break; + case Package: t << "package"; break; + } + t << "\" virt=\""; + switch(virt) + { + case Normal: t << "non-virtual"; break; + case Virtual: t << "virtual"; break; + case Pure: t << "pure-virtual"; break; + } + t << "\""; + if (!mi->ambiguityResolutionScope.isEmpty()) + { + t << " ambiguityscope=\"" << convertToXML(mi->ambiguityResolutionScope) << "\""; + } + t << "><scope>" << convertToXML(cd->name()) << "</scope><name>" << + convertToXML(md->name()) << "</name></member>" << endl; + } + } + } + } + t << " </listofallmembers>" << endl; +} + +static void writeInnerClasses(const ClassSDict *cl,FTextStream &t) +{ + if (cl) + { + ClassSDict::Iterator cli(*cl); + ClassDef *cd; + for (cli.toFirst();(cd=cli.current());++cli) + { + if (!cd->isHidden() && cd->name().find('@')==-1) // skip anonymous scopes + { + t << " <innerclass refid=\"" << classOutputFileBase(cd) + << "\" prot=\""; + switch(cd->protection()) + { + case Public: t << "public"; break; + case Protected: t << "protected"; break; + case Private: t << "private"; break; + case Package: t << "package"; break; + } + t << "\">" << convertToXML(cd->name()) << "</innerclass>" << endl; + } + } + } +} + +static void writeInnerNamespaces(const NamespaceSDict *nl,FTextStream &t) +{ + if (nl) + { + NamespaceSDict::Iterator nli(*nl); + NamespaceDef *nd; + for (nli.toFirst();(nd=nli.current());++nli) + { + if (!nd->isHidden() && nd->name().find('@')==-1) // skip anonymouse scopes + { + t << " <innernamespace refid=\"" << nd->getOutputFileBase() + << "\">" << convertToXML(nd->name()) << "</innernamespace>" << endl; + } + } + } +} + +static void writeInnerFiles(const FileList *fl,FTextStream &t) +{ + if (fl) + { + QListIterator<FileDef> fli(*fl); + FileDef *fd; + for (fli.toFirst();(fd=fli.current());++fli) + { + t << " <innerfile refid=\"" << fd->getOutputFileBase() + << "\">" << convertToXML(fd->name()) << "</innerfile>" << endl; + } + } +} + +static void writeInnerPages(const PageSDict *pl,FTextStream &t) +{ + if (pl) + { + PageSDict::Iterator pli(*pl); + PageDef *pd; + for (pli.toFirst();(pd=pli.current());++pli) + { + t << " <innerpage refid=\"" << pd->getOutputFileBase(); + if (pd->getGroupDef()) + { + t << "_" << pd->name(); + } + t << "\">" << convertToXML(pd->title()) << "</innerpage>" << endl; + } + } +} + +static void writeInnerGroups(const GroupList *gl,FTextStream &t) +{ + if (gl) + { + GroupListIterator gli(*gl); + GroupDef *sgd; + for (gli.toFirst();(sgd=gli.current());++gli) + { + t << " <innergroup refid=\"" << sgd->getOutputFileBase() + << "\">" << convertToXML(sgd->groupTitle()) + << "</innergroup>" << endl; + } + } +} + +static void writeInnerDirs(const DirList *dl,FTextStream &t) +{ + if (dl) + { + QListIterator<DirDef> subdirs(*dl); + DirDef *subdir; + for (subdirs.toFirst();(subdir=subdirs.current());++subdirs) + { + t << " <innerdir refid=\"" << subdir->getOutputFileBase() + << "\">" << convertToXML(subdir->displayName()) << "</innerdir>" << endl; + } + } +} + +static void generateXMLForClass(ClassDef *cd,FTextStream &ti) +{ + // + brief description + // + detailed description + // + template argument list(s) + // - include file + // + member groups + // + inheritance diagram + // + list of direct super classes + // + list of direct sub classes + // + list of inner classes + // + collaboration diagram + // + list of all members + // + user defined member sections + // + standard member sections + // + detailed member documentation + // - examples using the class + + if (cd->isReference()) return; // skip external references. + if (cd->isHidden()) return; // skip hidden classes. + if (cd->name().find('@')!=-1) return; // skip anonymous compounds. + if (cd->templateMaster()!=0) return; // skip generated template instances. + if (cd->isArtificial()) return; // skip artificially created classes + + msg("Generating XML output for class %s\n",cd->name().data()); + + ti << " <compound refid=\"" << classOutputFileBase(cd) + << "\" kind=\"" << cd->compoundTypeString() + << "\"><name>" << convertToXML(cd->name()) << "</name>" << endl; + + QCString outputDirectory = Config_getString("XML_OUTPUT"); + QCString fileName=outputDirectory+"/"+ classOutputFileBase(cd)+".xml"; + QFile f(fileName); + if (!f.open(IO_WriteOnly)) + { + err("Cannot open file %s for writing!\n",fileName.data()); + return; + } + FTextStream t(&f); + //t.setEncoding(FTextStream::UnicodeUTF8); + + writeXMLHeader(t); + t << " <compounddef id=\"" + << classOutputFileBase(cd) << "\" kind=\"" + << cd->compoundTypeString() << "\" prot=\""; + switch (cd->protection()) + { + case Public: t << "public"; break; + case Protected: t << "protected"; break; + case Private: t << "private"; break; + case Package: t << "package"; break; + } + if (cd->isFinal()) t << "\" final=\"yes"; + if (cd->isSealed()) t << "\" sealed=\"yes"; + if (cd->isAbstract()) t << "\" abstract=\"yes"; + t << "\">" << endl; + t << " <compoundname>"; + writeXMLString(t,cd->name()); + t << "</compoundname>" << endl; + if (cd->baseClasses()) + { + BaseClassListIterator bcli(*cd->baseClasses()); + BaseClassDef *bcd; + for (bcli.toFirst();(bcd=bcli.current());++bcli) + { + t << " <basecompoundref "; + if (bcd->classDef->isLinkable()) + { + t << "refid=\"" << classOutputFileBase(bcd->classDef) << "\" "; + } + t << "prot=\""; + switch (bcd->prot) + { + case Public: t << "public"; break; + case Protected: t << "protected"; break; + case Private: t << "private"; break; + case Package: ASSERT(0); break; + } + t << "\" virt=\""; + switch(bcd->virt) + { + case Normal: t << "non-virtual"; break; + case Virtual: t << "virtual"; break; + case Pure: t <<"pure-virtual"; break; + } + t << "\">"; + if (!bcd->templSpecifiers.isEmpty()) + { + t << convertToXML( + insertTemplateSpecifierInScope( + bcd->classDef->name(),bcd->templSpecifiers) + ); + } + else + { + t << convertToXML(bcd->classDef->displayName()); + } + t << "</basecompoundref>" << endl; + } + } + if (cd->subClasses()) + { + BaseClassListIterator bcli(*cd->subClasses()); + BaseClassDef *bcd; + for (bcli.toFirst();(bcd=bcli.current());++bcli) + { + t << " <derivedcompoundref refid=\"" + << classOutputFileBase(bcd->classDef) + << "\" prot=\""; + switch (bcd->prot) + { + case Public: t << "public"; break; + case Protected: t << "protected"; break; + case Private: t << "private"; break; + case Package: ASSERT(0); break; + } + t << "\" virt=\""; + switch(bcd->virt) + { + case Normal: t << "non-virtual"; break; + case Virtual: t << "virtual"; break; + case Pure: t << "pure-virtual"; break; + } + t << "\">" << convertToXML(bcd->classDef->displayName()) + << "</derivedcompoundref>" << endl; + } + } + + IncludeInfo *ii=cd->includeInfo(); + if (ii) + { + QCString nm = ii->includeName; + if (nm.isEmpty() && ii->fileDef) nm = ii->fileDef->docName(); + if (!nm.isEmpty()) + { + t << " <includes"; + if (ii->fileDef && !ii->fileDef->isReference()) // TODO: support external references + { + t << " refid=\"" << ii->fileDef->getOutputFileBase() << "\""; + } + t << " local=\"" << (ii->local ? "yes" : "no") << "\">"; + t << nm; + t << "</includes>" << endl; + } + } + + writeInnerClasses(cd->getClassSDict(),t); + + writeTemplateList(cd,t); + if (cd->getMemberGroupSDict()) + { + MemberGroupSDict::Iterator mgli(*cd->getMemberGroupSDict()); + MemberGroup *mg; + for (;(mg=mgli.current());++mgli) + { + generateXMLSection(cd,ti,t,mg->members(),"user-defined",mg->header(), + mg->documentation()); + } + } + + QListIterator<MemberList> mli(cd->getMemberLists()); + MemberList *ml; + for (mli.toFirst();(ml=mli.current());++mli) + { + if ((ml->listType()&MemberList::detailedLists)==0) + { + generateXMLSection(cd,ti,t,ml,g_xmlSectionMapper.find(ml->listType())); + } + } +#if 0 + generateXMLSection(cd,ti,t,cd->pubTypes,"public-type"); + generateXMLSection(cd,ti,t,cd->pubMethods,"public-func"); + generateXMLSection(cd,ti,t,cd->pubAttribs,"public-attrib"); + generateXMLSection(cd,ti,t,cd->pubSlots,"public-slot"); + generateXMLSection(cd,ti,t,cd->signals,"signal"); + generateXMLSection(cd,ti,t,cd->dcopMethods,"dcop-func"); + generateXMLSection(cd,ti,t,cd->properties,"property"); + generateXMLSection(cd,ti,t,cd->events,"event"); + generateXMLSection(cd,ti,t,cd->pubStaticMethods,"public-static-func"); + generateXMLSection(cd,ti,t,cd->pubStaticAttribs,"public-static-attrib"); + generateXMLSection(cd,ti,t,cd->proTypes,"protected-type"); + generateXMLSection(cd,ti,t,cd->proMethods,"protected-func"); + generateXMLSection(cd,ti,t,cd->proAttribs,"protected-attrib"); + generateXMLSection(cd,ti,t,cd->proSlots,"protected-slot"); + generateXMLSection(cd,ti,t,cd->proStaticMethods,"protected-static-func"); + generateXMLSection(cd,ti,t,cd->proStaticAttribs,"protected-static-attrib"); + generateXMLSection(cd,ti,t,cd->pacTypes,"package-type"); + generateXMLSection(cd,ti,t,cd->pacMethods,"package-func"); + generateXMLSection(cd,ti,t,cd->pacAttribs,"package-attrib"); + generateXMLSection(cd,ti,t,cd->pacStaticMethods,"package-static-func"); + generateXMLSection(cd,ti,t,cd->pacStaticAttribs,"package-static-attrib"); + generateXMLSection(cd,ti,t,cd->priTypes,"private-type"); + generateXMLSection(cd,ti,t,cd->priMethods,"private-func"); + generateXMLSection(cd,ti,t,cd->priAttribs,"private-attrib"); + generateXMLSection(cd,ti,t,cd->priSlots,"private-slot"); + generateXMLSection(cd,ti,t,cd->priStaticMethods,"private-static-func"); + generateXMLSection(cd,ti,t,cd->priStaticAttribs,"private-static-attrib"); + generateXMLSection(cd,ti,t,cd->friends,"friend"); + generateXMLSection(cd,ti,t,cd->related,"related"); +#endif + + t << " <briefdescription>" << endl; + writeXMLDocBlock(t,cd->briefFile(),cd->briefLine(),cd,0,cd->briefDescription()); + t << " </briefdescription>" << endl; + t << " <detaileddescription>" << endl; + writeXMLDocBlock(t,cd->docFile(),cd->docLine(),cd,0,cd->documentation()); + t << " </detaileddescription>" << endl; + DotClassGraph inheritanceGraph(cd,DotNode::Inheritance); + if (!inheritanceGraph.isTrivial()) + { + t << " <inheritancegraph>" << endl; + inheritanceGraph.writeXML(t); + t << " </inheritancegraph>" << endl; + } + DotClassGraph collaborationGraph(cd,DotNode::Collaboration); + if (!collaborationGraph.isTrivial()) + { + t << " <collaborationgraph>" << endl; + collaborationGraph.writeXML(t); + t << " </collaborationgraph>" << endl; + } + t << " <location file=\"" + << cd->getDefFileName() << "\" line=\"" + << cd->getDefLine() << "\""; + if (cd->getStartBodyLine()!=-1) + { + FileDef *bodyDef = cd->getBodyDef(); + if (bodyDef) + { + t << " bodyfile=\"" << bodyDef->absFilePath() << "\""; + } + t << " bodystart=\"" << cd->getStartBodyLine() << "\" bodyend=\"" + << cd->getEndBodyLine() << "\""; + } + t << "/>" << endl; + writeListOfAllMembers(cd,t); + t << " </compounddef>" << endl; + t << "</doxygen>" << endl; + + ti << " </compound>" << endl; +} + +static void generateXMLForNamespace(NamespaceDef *nd,FTextStream &ti) +{ + // + contained class definitions + // + contained namespace definitions + // + member groups + // + normal members + // + brief desc + // + detailed desc + // + location + // - files containing (parts of) the namespace definition + + if (nd->isReference() || nd->isHidden()) return; // skip external references + + ti << " <compound refid=\"" << nd->getOutputFileBase() + << "\" kind=\"namespace\"" << "><name>" + << convertToXML(nd->name()) << "</name>" << endl; + + QCString outputDirectory = Config_getString("XML_OUTPUT"); + QCString fileName=outputDirectory+"/"+nd->getOutputFileBase()+".xml"; + QFile f(fileName); + if (!f.open(IO_WriteOnly)) + { + err("Cannot open file %s for writing!\n",fileName.data()); + return; + } + FTextStream t(&f); + //t.setEncoding(FTextStream::UnicodeUTF8); + + writeXMLHeader(t); + t << " <compounddef id=\"" + << nd->getOutputFileBase() << "\" kind=\"namespace\">" << endl; + t << " <compoundname>"; + writeXMLString(t,nd->name()); + t << "</compoundname>" << endl; + + writeInnerClasses(nd->getClassSDict(),t); + writeInnerNamespaces(nd->getNamespaceSDict(),t); + + if (nd->getMemberGroupSDict()) + { + MemberGroupSDict::Iterator mgli(*nd->getMemberGroupSDict()); + MemberGroup *mg; + for (;(mg=mgli.current());++mgli) + { + generateXMLSection(nd,ti,t,mg->members(),"user-defined",mg->header(), + mg->documentation()); + } + } + + QListIterator<MemberList> mli(nd->getMemberLists()); + MemberList *ml; + for (mli.toFirst();(ml=mli.current());++mli) + { + if ((ml->listType()&MemberList::declarationLists)!=0) + { + generateXMLSection(nd,ti,t,ml,g_xmlSectionMapper.find(ml->listType())); + } + } +#if 0 + generateXMLSection(nd,ti,t,&nd->decDefineMembers,"define"); + generateXMLSection(nd,ti,t,&nd->decProtoMembers,"prototype"); + generateXMLSection(nd,ti,t,&nd->decTypedefMembers,"typedef"); + generateXMLSection(nd,ti,t,&nd->decEnumMembers,"enum"); + generateXMLSection(nd,ti,t,&nd->decFuncMembers,"func"); + generateXMLSection(nd,ti,t,&nd->decVarMembers,"var"); +#endif + + t << " <briefdescription>" << endl; + writeXMLDocBlock(t,nd->briefFile(),nd->briefLine(),nd,0,nd->briefDescription()); + t << " </briefdescription>" << endl; + t << " <detaileddescription>" << endl; + writeXMLDocBlock(t,nd->docFile(),nd->docLine(),nd,0,nd->documentation()); + t << " </detaileddescription>" << endl; + t << " <location file=\"" + << nd->getDefFileName() << "\" line=\"" + << nd->getDefLine() << "\"/>" << endl; + t << " </compounddef>" << endl; + t << "</doxygen>" << endl; + + ti << " </compound>" << endl; +} + +static void generateXMLForFile(FileDef *fd,FTextStream &ti) +{ + // + includes files + // + includedby files + // + include graph + // + included by graph + // + contained class definitions + // + contained namespace definitions + // + member groups + // + normal members + // + brief desc + // + detailed desc + // + source code + // + location + // - number of lines + + if (fd->isReference()) return; // skip external references + + ti << " <compound refid=\"" << fd->getOutputFileBase() + << "\" kind=\"file\"><name>" << convertToXML(fd->name()) + << "</name>" << endl; + + QCString outputDirectory = Config_getString("XML_OUTPUT"); + QCString fileName=outputDirectory+"/"+fd->getOutputFileBase()+".xml"; + QFile f(fileName); + if (!f.open(IO_WriteOnly)) + { + err("Cannot open file %s for writing!\n",fileName.data()); + return; + } + FTextStream t(&f); + //t.setEncoding(FTextStream::UnicodeUTF8); + + writeXMLHeader(t); + t << " <compounddef id=\"" + << fd->getOutputFileBase() << "\" kind=\"file\">" << endl; + t << " <compoundname>"; + writeXMLString(t,fd->name()); + t << "</compoundname>" << endl; + + IncludeInfo *inc; + + if (fd->includeFileList()) + { + QListIterator<IncludeInfo> ili1(*fd->includeFileList()); + for (ili1.toFirst();(inc=ili1.current());++ili1) + { + t << " <includes"; + if (inc->fileDef && !inc->fileDef->isReference()) // TODO: support external references + { + t << " refid=\"" << inc->fileDef->getOutputFileBase() << "\""; + } + t << " local=\"" << (inc->local ? "yes" : "no") << "\">"; + t << inc->includeName; + t << "</includes>" << endl; + } + } + + if (fd->includedByFileList()) + { + QListIterator<IncludeInfo> ili2(*fd->includedByFileList()); + for (ili2.toFirst();(inc=ili2.current());++ili2) + { + t << " <includedby"; + if (inc->fileDef && !inc->fileDef->isReference()) // TODO: support external references + { + t << " refid=\"" << inc->fileDef->getOutputFileBase() << "\""; + } + t << " local=\"" << (inc->local ? "yes" : "no") << "\">"; + t << inc->includeName; + t << "</includedby>" << endl; + } + } + + DotInclDepGraph incDepGraph(fd,FALSE); + if (!incDepGraph.isTrivial()) + { + t << " <incdepgraph>" << endl; + incDepGraph.writeXML(t); + t << " </incdepgraph>" << endl; + } + + DotInclDepGraph invIncDepGraph(fd,TRUE); + if (!invIncDepGraph.isTrivial()) + { + t << " <invincdepgraph>" << endl; + invIncDepGraph.writeXML(t); + t << " </invincdepgraph>" << endl; + } + + if (fd->getClassSDict()) + { + writeInnerClasses(fd->getClassSDict(),t); + } + if (fd->getNamespaceSDict()) + { + writeInnerNamespaces(fd->getNamespaceSDict(),t); + } + + if (fd->getMemberGroupSDict()) + { + MemberGroupSDict::Iterator mgli(*fd->getMemberGroupSDict()); + MemberGroup *mg; + for (;(mg=mgli.current());++mgli) + { + generateXMLSection(fd,ti,t,mg->members(),"user-defined",mg->header(), + mg->documentation()); + } + } + + QListIterator<MemberList> mli(fd->getMemberLists()); + MemberList *ml; + for (mli.toFirst();(ml=mli.current());++mli) + { + if ((ml->listType()&MemberList::declarationLists)!=0) + { + generateXMLSection(fd,ti,t,ml,g_xmlSectionMapper.find(ml->listType())); + } + } +#if 0 + generateXMLSection(fd,ti,t,fd->decDefineMembers,"define"); + generateXMLSection(fd,ti,t,fd->decProtoMembers,"prototype"); + generateXMLSection(fd,ti,t,fd->decTypedefMembers,"typedef"); + generateXMLSection(fd,ti,t,fd->decEnumMembers,"enum"); + generateXMLSection(fd,ti,t,fd->decFuncMembers,"func"); + generateXMLSection(fd,ti,t,fd->decVarMembers,"var"); +#endif + + t << " <briefdescription>" << endl; + writeXMLDocBlock(t,fd->briefFile(),fd->briefLine(),fd,0,fd->briefDescription()); + t << " </briefdescription>" << endl; + t << " <detaileddescription>" << endl; + writeXMLDocBlock(t,fd->docFile(),fd->docLine(),fd,0,fd->documentation()); + t << " </detaileddescription>" << endl; + if (Config_getBool("XML_PROGRAMLISTING")) + { + t << " <programlisting>" << endl; + writeXMLCodeBlock(t,fd); + t << " </programlisting>" << endl; + } + t << " <location file=\"" << fd->getDefFileName() << "\"/>" << endl; + t << " </compounddef>" << endl; + t << "</doxygen>" << endl; + + ti << " </compound>" << endl; +} + +static void generateXMLForGroup(GroupDef *gd,FTextStream &ti) +{ + // + members + // + member groups + // + files + // + classes + // + namespaces + // - packages + // + pages + // + child groups + // - examples + // + brief description + // + detailed description + + if (gd->isReference()) return; // skip external references + + ti << " <compound refid=\"" << gd->getOutputFileBase() + << "\" kind=\"group\"><name>" << convertToXML(gd->name()) << "</name>" << endl; + + QCString outputDirectory = Config_getString("XML_OUTPUT"); + QCString fileName=outputDirectory+"/"+gd->getOutputFileBase()+".xml"; + QFile f(fileName); + if (!f.open(IO_WriteOnly)) + { + err("Cannot open file %s for writing!\n",fileName.data()); + return; + } + + FTextStream t(&f); + //t.setEncoding(FTextStream::UnicodeUTF8); + writeXMLHeader(t); + t << " <compounddef id=\"" + << gd->getOutputFileBase() << "\" kind=\"group\">" << endl; + t << " <compoundname>" << convertToXML(gd->name()) << "</compoundname>" << endl; + t << " <title>" << convertToXML(gd->groupTitle()) << "</title>" << endl; + + writeInnerFiles(gd->getFiles(),t); + writeInnerClasses(gd->getClasses(),t); + writeInnerNamespaces(gd->getNamespaces(),t); + writeInnerPages(gd->getPages(),t); + writeInnerGroups(gd->getSubGroups(),t); + + if (gd->getMemberGroupSDict()) + { + MemberGroupSDict::Iterator mgli(*gd->getMemberGroupSDict()); + MemberGroup *mg; + for (;(mg=mgli.current());++mgli) + { + generateXMLSection(gd,ti,t,mg->members(),"user-defined",mg->header(), + mg->documentation()); + } + } + + QListIterator<MemberList> mli(gd->getMemberLists()); + MemberList *ml; + for (mli.toFirst();(ml=mli.current());++mli) + { + if ((ml->listType()&MemberList::declarationLists)!=0) + { + generateXMLSection(gd,ti,t,ml,g_xmlSectionMapper.find(ml->listType())); + } + } +#if 0 + generateXMLSection(gd,ti,t,&gd->decDefineMembers,"define"); + generateXMLSection(gd,ti,t,&gd->decProtoMembers,"prototype"); + generateXMLSection(gd,ti,t,&gd->decTypedefMembers,"typedef"); + generateXMLSection(gd,ti,t,&gd->decEnumMembers,"enum"); + generateXMLSection(gd,ti,t,&gd->decFuncMembers,"func"); + generateXMLSection(gd,ti,t,&gd->decVarMembers,"var"); +#endif + + t << " <briefdescription>" << endl; + writeXMLDocBlock(t,gd->briefFile(),gd->briefLine(),gd,0,gd->briefDescription()); + t << " </briefdescription>" << endl; + t << " <detaileddescription>" << endl; + writeXMLDocBlock(t,gd->docFile(),gd->docLine(),gd,0,gd->documentation()); + t << " </detaileddescription>" << endl; + t << " </compounddef>" << endl; + t << "</doxygen>" << endl; + + ti << " </compound>" << endl; +} + +static void generateXMLForDir(DirDef *dd,FTextStream &ti) +{ + if (dd->isReference()) return; // skip external references + ti << " <compound refid=\"" << dd->getOutputFileBase() + << "\" kind=\"dir\"><name>" << convertToXML(dd->displayName()) + << "</name>" << endl; + + QCString outputDirectory = Config_getString("XML_OUTPUT"); + QCString fileName=outputDirectory+"/"+dd->getOutputFileBase()+".xml"; + QFile f(fileName); + if (!f.open(IO_WriteOnly)) + { + err("Cannot open file %s for writing!\n",fileName.data()); + return; + } + + FTextStream t(&f); + //t.setEncoding(FTextStream::UnicodeUTF8); + writeXMLHeader(t); + t << " <compounddef id=\"" + << dd->getOutputFileBase() << "\" kind=\"dir\">" << endl; + t << " <compoundname>" << convertToXML(dd->displayName()) << "</compoundname>" << endl; + + writeInnerDirs(&dd->subDirs(),t); + writeInnerFiles(dd->getFiles(),t); + + t << " <briefdescription>" << endl; + writeXMLDocBlock(t,dd->briefFile(),dd->briefLine(),dd,0,dd->briefDescription()); + t << " </briefdescription>" << endl; + t << " <detaileddescription>" << endl; + writeXMLDocBlock(t,dd->docFile(),dd->docLine(),dd,0,dd->documentation()); + t << " </detaileddescription>" << endl; + t << " <location file=\"" << dd->name() << "\"/>" << endl; + t << " </compounddef>" << endl; + t << "</doxygen>" << endl; + + ti << " </compound>" << endl; +} + +static void generateXMLForPage(PageDef *pd,FTextStream &ti,bool isExample) +{ + // + name + // + title + // + documentation + + const char *kindName = isExample ? "example" : "page"; + + if (pd->isReference()) return; + + QCString pageName = pd->getOutputFileBase(); + if (pd->getGroupDef()) + { + pageName+=(QCString)"_"+pd->name(); + } + if (pageName=="index") pageName="indexpage"; // to prevent overwriting the generated index page. + + ti << " <compound refid=\"" << pageName + << "\" kind=\"" << kindName << "\"><name>" << convertToXML(pd->name()) + << "</name>" << endl; + + QCString outputDirectory = Config_getString("XML_OUTPUT"); + QCString fileName=outputDirectory+"/"+pageName+".xml"; + QFile f(fileName); + if (!f.open(IO_WriteOnly)) + { + err("Cannot open file %s for writing!\n",fileName.data()); + return; + } + + FTextStream t(&f); + //t.setEncoding(FTextStream::UnicodeUTF8); + writeXMLHeader(t); + t << " <compounddef id=\"" << pageName; + t << "\" kind=\"" << kindName << "\">" << endl; + t << " <compoundname>" << convertToXML(pd->name()) + << "</compoundname>" << endl; + + SectionInfo *si = Doxygen::sectionDict.find(pd->name()); + if (si) + { + t << " <title>" << convertToXML(si->title) << "</title>" << endl; + } + writeInnerPages(pd->getSubPages(),t); + t << " <detaileddescription>" << endl; + if (isExample) + { + writeXMLDocBlock(t,pd->docFile(),pd->docLine(),pd,0, + pd->documentation()+"\n\\include "+pd->name()); + } + else + { + writeXMLDocBlock(t,pd->docFile(),pd->docLine(),pd,0, + pd->documentation()); + } + t << " </detaileddescription>" << endl; + + t << " </compounddef>" << endl; + t << "</doxygen>" << endl; + + ti << " </compound>" << endl; +} + +void generateXML() +{ + + // + classes + // + namespaces + // + files + // + groups + // + related pages + // - examples + + QCString outputDirectory = Config_getString("XML_OUTPUT"); + if (outputDirectory.isEmpty()) + { + outputDirectory=QDir::currentDirPath().utf8(); + } + else + { + QDir dir(outputDirectory); + if (!dir.exists()) + { + dir.setPath(QDir::currentDirPath()); + if (!dir.mkdir(outputDirectory)) + { + err("error: tag XML_OUTPUT: Output directory `%s' does not " + "exist and cannot be created\n",outputDirectory.data()); + exit(1); + } + else if (!Config_getBool("QUIET")) + { + err("notice: Output directory `%s' does not exist. " + "I have created it for you.\n", outputDirectory.data()); + } + dir.cd(outputDirectory); + } + outputDirectory=dir.absPath().utf8(); + } + + QDir dir(outputDirectory); + if (!dir.exists()) + { + dir.setPath(QDir::currentDirPath()); + if (!dir.mkdir(outputDirectory)) + { + err("Cannot create directory %s\n",outputDirectory.data()); + return; + } + } + QDir xmlDir(outputDirectory); + createSubDirs(xmlDir); + QCString fileName=outputDirectory+"/index.xsd"; + QFile f(fileName); + if (!f.open(IO_WriteOnly)) + { + err("Cannot open file %s for writing!\n",fileName.data()); + return; + } + f.writeBlock(index_xsd,strlen(index_xsd)); + f.close(); + + fileName=outputDirectory+"/compound.xsd"; + f.setName(fileName); + if (!f.open(IO_WriteOnly)) + { + err("Cannot open file %s for writing!\n",fileName.data()); + return; + } + f.writeBlock(compound_xsd,strlen(compound_xsd)); + f.close(); + + fileName=outputDirectory+"/index.xml"; + f.setName(fileName); + if (!f.open(IO_WriteOnly)) + { + err("Cannot open file %s for writing!\n",fileName.data()); + return; + } + FTextStream t(&f); + //t.setEncoding(FTextStream::UnicodeUTF8); + + // write index header + t << "<?xml version='1.0' encoding='UTF-8' standalone='no'?>" << endl;; + t << "<doxygenindex xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" "; + t << "xsi:noNamespaceSchemaLocation=\"index.xsd\" "; + t << "version=\"" << versionString << "\">" << endl; + + { + ClassSDict::Iterator cli(*Doxygen::classSDict); + ClassDef *cd; + for (cli.toFirst();(cd=cli.current());++cli) + { + generateXMLForClass(cd,t); + } + } + //{ + // ClassSDict::Iterator cli(Doxygen::hiddenClasses); + // ClassDef *cd; + // for (cli.toFirst();(cd=cli.current());++cli) + // { + // msg("Generating XML output for class %s\n",cd->name().data()); + // generateXMLForClass(cd,t); + // } + //} + NamespaceSDict::Iterator nli(*Doxygen::namespaceSDict); + NamespaceDef *nd; + for (nli.toFirst();(nd=nli.current());++nli) + { + msg("Generating XML output for namespace %s\n",nd->name().data()); + generateXMLForNamespace(nd,t); + } + FileNameListIterator fnli(*Doxygen::inputNameList); + FileName *fn; + for (;(fn=fnli.current());++fnli) + { + FileNameIterator fni(*fn); + FileDef *fd; + for (;(fd=fni.current());++fni) + { + msg("Generating XML output for file %s\n",fd->name().data()); + generateXMLForFile(fd,t); + } + } + GroupSDict::Iterator gli(*Doxygen::groupSDict); + GroupDef *gd; + for (;(gd=gli.current());++gli) + { + msg("Generating XML output for group %s\n",gd->name().data()); + generateXMLForGroup(gd,t); + } + { + PageSDict::Iterator pdi(*Doxygen::pageSDict); + PageDef *pd=0; + for (pdi.toFirst();(pd=pdi.current());++pdi) + { + msg("Generating XML output for page %s\n",pd->name().data()); + generateXMLForPage(pd,t,FALSE); + } + } + { + DirDef *dir; + DirSDict::Iterator sdi(*Doxygen::directories); + for (sdi.toFirst();(dir=sdi.current());++sdi) + { + msg("Generate XML output for dir %s\n",dir->name().data()); + generateXMLForDir(dir,t); + } + } + { + PageSDict::Iterator pdi(*Doxygen::exampleSDict); + PageDef *pd=0; + for (pdi.toFirst();(pd=pdi.current());++pdi) + { + msg("Generating XML output for example %s\n",pd->name().data()); + generateXMLForPage(pd,t,TRUE); + } + } + if (Doxygen::mainPage) + { + msg("Generating XML output for the main page\n"); + generateXMLForPage(Doxygen::mainPage,t,FALSE); + } + + //t << " </compoundlist>" << endl; + t << "</doxygenindex>" << endl; + + writeCombineScript(); +} + + |