1 /******************************************************************************
3 * Copyright (C) 1997-2015 by Dimitri van Heesch.
5 * Permission to use, copy, modify, and distribute this software and its
6 * documentation under the terms of the GNU General Public License is hereby
7 * granted. No representations are made about the suitability of this software
8 * for any purpose. It is provided "as is" without express or implied warranty.
9 * See the GNU General Public License for more details.
11 * Documents produced by Doxygen are derivative works derived from the
12 * input used in their production; they are not affected by this license.
20 #include <qtextstream.h>
27 #include "classlist.h"
30 #include "outputgen.h"
35 #include "xmldocvisitor.h"
36 #include "docparser.h"
38 #include "parserintf.h"
39 #include "arguments.h"
40 #include "memberlist.h"
42 #include "memberdef.h"
43 #include "namespacedef.h"
44 #include "membername.h"
45 #include "membergroup.h"
48 #include "htmlentity.h"
49 #include "resourcemgr.h"
52 #define XML_DB(x) do {} while(0)
54 //#define XML_DB(x) printf x
55 // debug inside output
56 //#define XML_DB(x) QCString __t;__t.sprintf x;m_t << __t
60 /** Helper class mapping MemberList::ListType to a string representing */
61 class XmlSectionMapper : public QIntDict<char>
64 XmlSectionMapper() : QIntDict<char>(47)
66 insert(MemberListType_pubTypes,"public-type");
67 insert(MemberListType_pubMethods,"public-func");
68 insert(MemberListType_pubAttribs,"public-attrib");
69 insert(MemberListType_pubSlots,"public-slot");
70 insert(MemberListType_signals,"signal");
71 insert(MemberListType_dcopMethods,"dcop-func");
72 insert(MemberListType_properties,"property");
73 insert(MemberListType_events,"event");
74 insert(MemberListType_interfaces,"interfaces");
75 insert(MemberListType_services,"services");
76 insert(MemberListType_pubStaticMethods,"public-static-func");
77 insert(MemberListType_pubStaticAttribs,"public-static-attrib");
78 insert(MemberListType_proTypes,"protected-type");
79 insert(MemberListType_proMethods,"protected-func");
80 insert(MemberListType_proAttribs,"protected-attrib");
81 insert(MemberListType_proSlots,"protected-slot");
82 insert(MemberListType_proStaticMethods,"protected-static-func");
83 insert(MemberListType_proStaticAttribs,"protected-static-attrib");
84 insert(MemberListType_pacTypes,"package-type");
85 insert(MemberListType_pacMethods,"package-func");
86 insert(MemberListType_pacAttribs,"package-attrib");
87 insert(MemberListType_pacStaticMethods,"package-static-func");
88 insert(MemberListType_pacStaticAttribs,"package-static-attrib");
89 insert(MemberListType_priTypes,"private-type");
90 insert(MemberListType_priMethods,"private-func");
91 insert(MemberListType_priAttribs,"private-attrib");
92 insert(MemberListType_priSlots,"private-slot");
93 insert(MemberListType_priStaticMethods,"private-static-func");
94 insert(MemberListType_priStaticAttribs,"private-static-attrib");
95 insert(MemberListType_friends,"friend");
96 insert(MemberListType_related,"related");
97 insert(MemberListType_decDefineMembers,"define");
98 insert(MemberListType_decProtoMembers,"prototype");
99 insert(MemberListType_decTypedefMembers,"typedef");
100 insert(MemberListType_decSequenceMembers,"sequence");
101 insert(MemberListType_decDictionaryMembers,"dictionary");
102 insert(MemberListType_decEnumMembers,"enum");
103 insert(MemberListType_decFuncMembers,"func");
104 insert(MemberListType_decVarMembers,"var");
108 static XmlSectionMapper g_xmlSectionMapper;
111 inline void writeXMLString(FTextStream &t,const char *s)
113 t << convertToXML(s);
116 inline void writeXMLCodeString(FTextStream &t,const char *s, int &col)
125 static int tabSize = Config_getInt(TAB_SIZE);
126 int spacesToNextTabStop = tabSize - (col%tabSize);
127 col+=spacesToNextTabStop;
128 while (spacesToNextTabStop--) t << "<sp/>";
131 case ' ': t << "<sp/>"; col++; break;
132 case '<': t << "<"; col++; break;
133 case '>': t << ">"; col++; break;
134 case '&': t << "&"; col++; break;
135 case '\'': t << "'"; col++; break;
136 case '"': t << """; col++; break;
137 case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8:
138 case 11: case 12: case 13: case 14: case 15: case 16: case 17: case 18:
139 case 19: case 20: case 21: case 22: case 23: case 24: case 25: case 26:
140 case 27: case 28: case 29: case 30: case 31:
141 // encode invalid XML characters (see http://www.w3.org/TR/2000/REC-xml-20001006#NT-Char)
142 t << "<sp value=\"" << int(c) << "\"/>";
144 default: s=writeUtf8Char(t,s-1); col++; break;
150 static void writeXMLHeader(FTextStream &t)
152 t << "<?xml version='1.0' encoding='UTF-8' standalone='no'?>" << endl;;
153 t << "<doxygen xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" ";
154 t << "xsi:noNamespaceSchemaLocation=\"compound.xsd\" ";
155 t << "version=\"" << versionString << "\">" << endl;
158 static void writeCombineScript()
160 QCString outputDirectory = Config_getString(XML_OUTPUT);
161 QCString fileName=outputDirectory+"/combine.xslt";
163 if (!f.open(IO_WriteOnly))
165 err("Cannot open file %s for writing!\n",fileName.data());
169 //t.setEncoding(FTextStream::UnicodeUTF8);
172 "<!-- XSLT script to combine the generated output into a single file. \n"
173 " If you have xsltproc you could use:\n"
174 " xsltproc combine.xslt index.xml >all.xml\n"
176 "<xsl:stylesheet xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" version=\"1.0\">\n"
177 " <xsl:output method=\"xml\" version=\"1.0\" indent=\"no\" standalone=\"yes\" />\n"
178 " <xsl:template match=\"/\">\n"
179 " <doxygen version=\"{doxygenindex/@version}\">\n"
180 " <!-- Load all doxygen generated xml files -->\n"
181 " <xsl:for-each select=\"doxygenindex/compound\">\n"
182 " <xsl:copy-of select=\"document( concat( @refid, '.xml' ) )/doxygen/*\" />\n"
186 "</xsl:stylesheet>\n";
190 void writeXMLLink(FTextStream &t,const char *extRef,const char *compoundId,
191 const char *anchorId,const char *text,const char *tooltip)
193 t << "<ref refid=\"" << compoundId;
194 if (anchorId) t << "_1" << anchorId;
195 t << "\" kindref=\"";
196 if (anchorId) t << "member"; else t << "compound";
198 if (extRef) t << " external=\"" << extRef << "\"";
199 if (tooltip) t << " tooltip=\"" << convertToXML(tooltip) << "\"";
201 writeXMLString(t,text);
205 /** Implements TextGeneratorIntf for an XML stream. */
206 class TextGeneratorXMLImpl : public TextGeneratorIntf
209 TextGeneratorXMLImpl(FTextStream &t): m_t(t) {}
210 void writeString(const char *s,bool /*keepSpaces*/) const
212 writeXMLString(m_t,s);
214 void writeBreak(int) const {}
215 void writeLink(const char *extRef,const char *file,
216 const char *anchor,const char *text
219 writeXMLLink(m_t,extRef,file,anchor,text,0);
226 /** Generator for producing XML formatted source code. */
227 void XMLCodeGenerator::codify(const char *text)
229 XML_DB(("(codify \"%s\")\n",text));
230 if (m_insideCodeLine && !m_insideSpecialHL && m_normalHLNeedStartTag)
232 m_t << "<highlight class=\"normal\">";
233 m_normalHLNeedStartTag=FALSE;
235 writeXMLCodeString(m_t,text,m_col);
237 void XMLCodeGenerator::writeCodeLink(const char *ref,const char *file,
238 const char *anchor,const char *name,
241 XML_DB(("(writeCodeLink)\n"));
242 if (m_insideCodeLine && !m_insideSpecialHL && m_normalHLNeedStartTag)
244 m_t << "<highlight class=\"normal\">";
245 m_normalHLNeedStartTag=FALSE;
247 writeXMLLink(m_t,ref,file,anchor,name,tooltip);
248 m_col+=qstrlen(name);
250 void XMLCodeGenerator::writeTooltip(const char *, const DocLinkInfo &, const char *,
251 const char *, const SourceLinkInfo &, const SourceLinkInfo &
254 XML_DB(("(writeToolTip)\n"));
256 void XMLCodeGenerator::startCodeLine(bool)
258 XML_DB(("(startCodeLine)\n"));
260 if (m_lineNumber!=-1)
262 m_t << " lineno=\"" << m_lineNumber << "\"";
263 if (!m_refId.isEmpty())
265 m_t << " refid=\"" << m_refId << "\"";
268 m_t << " refkind=\"member\"";
272 m_t << " refkind=\"compound\"";
275 if (!m_external.isEmpty())
277 m_t << " external=\"" << m_external << "\"";
281 m_insideCodeLine=TRUE;
284 void XMLCodeGenerator::endCodeLine()
286 XML_DB(("(endCodeLine)\n"));
287 if (!m_insideSpecialHL && !m_normalHLNeedStartTag)
289 m_t << "</highlight>";
290 m_normalHLNeedStartTag=TRUE;
292 m_t << "</codeline>" << endl; // non DocBook
295 m_external.resize(0);
296 m_insideCodeLine=FALSE;
298 void XMLCodeGenerator::startFontClass(const char *colorClass)
300 XML_DB(("(startFontClass)\n"));
301 if (m_insideCodeLine && !m_insideSpecialHL && !m_normalHLNeedStartTag)
303 m_t << "</highlight>";
304 m_normalHLNeedStartTag=TRUE;
306 m_t << "<highlight class=\"" << colorClass << "\">"; // non DocBook
307 m_insideSpecialHL=TRUE;
309 void XMLCodeGenerator::endFontClass()
311 XML_DB(("(endFontClass)\n"));
312 m_t << "</highlight>"; // non DocBook
313 m_insideSpecialHL=FALSE;
315 void XMLCodeGenerator::writeCodeAnchor(const char *)
317 XML_DB(("(writeCodeAnchor)\n"));
319 void XMLCodeGenerator::writeLineNumber(const char *extRef,const char *compId,
320 const char *anchorId,int l)
322 XML_DB(("(writeLineNumber)\n"));
323 // we remember the information provided here to use it
324 // at the <codeline> start tag.
329 if (anchorId) m_refId+=(QCString)"_1"+anchorId;
330 m_isMemberRef = anchorId!=0;
331 if (extRef) m_external=extRef;
334 void XMLCodeGenerator::finish()
336 if (m_insideCodeLine) endCodeLine();
339 static void writeTemplateArgumentList(ArgumentList *al,
346 indentStr.fill(' ',indent);
349 t << indentStr << "<templateparamlist>" << endl;
350 ArgumentListIterator ali(*al);
352 for (ali.toFirst();(a=ali.current());++ali)
354 t << indentStr << " <param>" << endl;
355 if (!a->type.isEmpty())
357 t << indentStr << " <type>";
358 linkifyText(TextGeneratorXMLImpl(t),scope,fileScope,0,a->type);
359 t << "</type>" << endl;
361 if (!a->name.isEmpty())
363 t << indentStr << " <declname>" << a->name << "</declname>" << endl;
364 t << indentStr << " <defname>" << a->name << "</defname>" << endl;
366 if (!a->defval.isEmpty())
368 t << indentStr << " <defval>";
369 linkifyText(TextGeneratorXMLImpl(t),scope,fileScope,0,a->defval);
370 t << "</defval>" << endl;
372 if (!a->typeConstraint.isEmpty())
374 t << indentStr << " <typeconstraint>";
375 linkifyText(TextGeneratorXMLImpl(t),scope,fileScope,0,a->typeConstraint);
376 t << "</typeconstraint>" << endl;
378 t << indentStr << " </param>" << endl;
380 t << indentStr << "</templateparamlist>" << endl;
384 static void writeMemberTemplateLists(MemberDef *md,FTextStream &t)
386 ArgumentList *templMd = md->templateArguments();
387 if (templMd) // function template prefix
389 writeTemplateArgumentList(templMd,t,md->getClassDef(),md->getFileDef(),8);
393 static void writeTemplateList(ClassDef *cd,FTextStream &t)
395 writeTemplateArgumentList(cd->templateArguments(),t,cd,0,4);
398 static void writeXMLDocBlock(FTextStream &t,
399 const QCString &fileName,
403 const QCString &text)
405 QCString stext = text.stripWhiteSpace();
406 if (stext.isEmpty()) return;
407 // convert the documentation string into an abstract syntax tree
408 DocNode *root = validatingParseDoc(fileName,lineNr,scope,md,text,FALSE,FALSE);
409 // create a code generator
410 XMLCodeGenerator *xmlCodeGen = new XMLCodeGenerator(t);
411 // create a parse tree visitor for XML
412 XmlDocVisitor *visitor = new XmlDocVisitor(t,*xmlCodeGen);
414 root->accept(visitor);
422 void writeXMLCodeBlock(FTextStream &t,FileDef *fd)
424 ParserInterface *pIntf=Doxygen::parserManager->getParser(fd->getDefFileExtension());
425 SrcLangExt langExt = getLanguageFromFileName(fd->getDefFileExtension());
426 pIntf->resetCodeParserState();
427 XMLCodeGenerator *xmlGen = new XMLCodeGenerator(t);
428 pIntf->parseCode(*xmlGen, // codeOutIntf
430 fileToString(fd->absFilePath(),Config_getBool(FILTER_SOURCE_FILES)),
432 FALSE, // isExampleBlock
437 FALSE, // inlineFragement
439 TRUE // showLineNumbers
445 static void writeMemberReference(FTextStream &t,Definition *def,MemberDef *rmd,const char *tagName)
447 QCString scope = rmd->getScopeString();
448 QCString name = rmd->name();
449 if (!scope.isEmpty() && scope!=def->name())
451 name.prepend(scope+getLanguageSpecificSeparator(rmd->getLanguage()));
453 t << " <" << tagName << " refid=\"";
454 t << rmd->getOutputFileBase() << "_1" << rmd->anchor() << "\"";
455 if (rmd->getStartBodyLine()!=-1 && rmd->getBodyDef())
457 t << " compoundref=\"" << rmd->getBodyDef()->getOutputFileBase() << "\"";
458 t << " startline=\"" << rmd->getStartBodyLine() << "\"";
459 if (rmd->getEndBodyLine()!=-1)
461 t << " endline=\"" << rmd->getEndBodyLine() << "\"";
464 t << ">" << convertToXML(name) << "</" << tagName << ">" << endl;
468 static void stripQualifiers(QCString &typeStr)
473 if (typeStr.stripPrefix("static "));
474 else if (typeStr.stripPrefix("virtual "));
475 else if (typeStr.stripPrefix("volatile "));
476 else if (typeStr=="virtual") typeStr="";
481 static QCString classOutputFileBase(ClassDef *cd)
483 //static bool inlineGroupedClasses = Config_getBool(INLINE_GROUPED_CLASSES);
484 //if (inlineGroupedClasses && cd->partOfGroups()!=0)
485 return cd->getOutputFileBase();
487 // return cd->getOutputFileBase();
490 static QCString memberOutputFileBase(MemberDef *md)
492 //static bool inlineGroupedClasses = Config_getBool(INLINE_GROUPED_CLASSES);
493 //if (inlineGroupedClasses && md->getClassDef() && md->getClassDef()->partOfGroups()!=0)
494 // return md->getClassDef()->getXmlOutputFileBase();
496 // return md->getOutputFileBase();
497 return md->getOutputFileBase();
501 static void generateXMLForMember(MemberDef *md,FTextStream &ti,FTextStream &t,Definition *def)
504 // + declaration/definition arg lists
508 // + const/volatile specifiers
510 // + source definition
511 // + source references
512 // + source referenced by
514 // + template arguments
515 // (templateArguments(), definitionTemplateParameterLists())
518 // enum values are written as part of the enum
519 if (md->memberType()==MemberType_EnumValue) return;
520 if (md->isHidden()) return;
521 //if (md->name().at(0)=='@') return; // anonymous member
523 // group members are only visible in their group
524 //if (def->definitionType()!=Definition::TypeGroup && md->getGroupDef()) return;
528 switch (md->memberType())
530 case MemberType_Define: memType="define"; break;
531 case MemberType_Function: memType="function"; isFunc=TRUE; break;
532 case MemberType_Variable: memType="variable"; break;
533 case MemberType_Typedef: memType="typedef"; break;
534 case MemberType_Enumeration: memType="enum"; break;
535 case MemberType_EnumValue: ASSERT(0); break;
536 case MemberType_Signal: memType="signal"; isFunc=TRUE; break;
537 case MemberType_Slot: memType="slot"; isFunc=TRUE; break;
538 case MemberType_Friend: memType="friend"; isFunc=TRUE; break;
539 case MemberType_DCOP: memType="dcop"; isFunc=TRUE; break;
540 case MemberType_Property: memType="property"; break;
541 case MemberType_Event: memType="event"; break;
542 case MemberType_Interface: memType="interface"; break;
543 case MemberType_Service: memType="service"; break;
544 case MemberType_Sequence: memType="sequence"; break;
545 case MemberType_Dictionary: memType="dictionary"; break;
548 ti << " <member refid=\"" << memberOutputFileBase(md)
549 << "_1" << md->anchor() << "\" kind=\"" << memType << "\"><name>"
550 << convertToXML(md->name()) << "</name></member>" << endl;
553 if (md->getClassDef())
554 scopeName=md->getClassDef()->name();
555 else if (md->getNamespaceDef())
556 scopeName=md->getNamespaceDef()->name();
558 t << " <memberdef kind=\"";
559 //enum { define_t,variable_t,typedef_t,enum_t,function_t } xmlType = function_t;
560 t << memType << "\" id=\"";
561 if (md->getGroupDef() && def->definitionType()==Definition::TypeGroup)
563 t << md->getGroupDef()->getOutputFileBase();
567 t << memberOutputFileBase(md);
569 t << "_1" // encoded `:' character (see util.cpp:convertNameToFile)
572 switch(md->protection())
574 case Public: t << "public"; break;
575 case Protected: t << "protected"; break;
576 case Private: t << "private"; break;
577 case Package: t << "package"; break;
582 if (md->isStatic()) t << "yes"; else t << "no";
587 ArgumentList *al = md->argumentList();
589 if (al!=0 && al->constSpecifier) t << "yes"; else t << "no";
593 if (md->isExplicit()) t << "yes"; else t << "no";
597 if (md->isInline()) t << "yes"; else t << "no";
600 if (al!=0 && al->refQualifier!=RefQualifierNone)
603 if (al->refQualifier==RefQualifierLValue) t << "lvalue"; else t << "rvalue";
609 t << " final=\"yes\"";
614 t << " sealed=\"yes\"";
622 if (md->isOptional())
624 t << " optional=\"yes\"";
627 if (md->isRequired())
629 t << " required=\"yes\"";
632 if (al && al->volatileSpecifier)
634 t << " volatile=\"yes\"";
638 switch (md->virtualness())
640 case Normal: t << "non-virtual"; break;
641 case Virtual: t << "virtual"; break;
642 case Pure: t << "pure-virtual"; break;
648 if (md->memberType() == MemberType_Enumeration)
651 if (md->isStrong()) t << "yes"; else t << "no";
655 if (md->memberType() == MemberType_Variable)
657 //ArgumentList *al = md->argumentList();
658 //t << " volatile=\"";
659 //if (al && al->volatileSpecifier) t << "yes"; else t << "no";
662 if (md->isMutable()) t << "yes"; else t << "no";
665 if (md->isInitonly())
667 t << " initonly=\"yes\"";
669 if (md->isAttribute())
671 t << " attribute=\"yes\"";
673 if (md->isUNOProperty())
675 t << " property=\"yes\"";
677 if (md->isReadonly())
679 t << " readonly=\"yes\"";
683 t << " bound=\"yes\"";
685 if (md->isRemovable())
687 t << " removable=\"yes\"";
689 if (md->isConstrained())
691 t << " constrained=\"yes\"";
693 if (md->isTransient())
695 t << " transient=\"yes\"";
697 if (md->isMaybeVoid())
699 t << " maybevoid=\"yes\"";
701 if (md->isMaybeDefault())
703 t << " maybedefault=\"yes\"";
705 if (md->isMaybeAmbiguous())
707 t << " maybeambiguous=\"yes\"";
710 else if (md->memberType() == MemberType_Property)
713 if (md->isReadable()) t << "yes"; else t << "no";
717 if (md->isWritable()) t << "yes"; else t << "no";
721 if (md->isGettable()) t << "yes"; else t << "no";
724 t << " privategettable=\"";
725 if (md->isPrivateGettable()) t << "yes"; else t << "no";
728 t << " protectedgettable=\"";
729 if (md->isProtectedGettable()) t << "yes"; else t << "no";
733 if (md->isSettable()) t << "yes"; else t << "no";
736 t << " privatesettable=\"";
737 if (md->isPrivateSettable()) t << "yes"; else t << "no";
740 t << " protectedsettable=\"";
741 if (md->isProtectedSettable()) t << "yes"; else t << "no";
744 if (md->isAssign() || md->isCopy() || md->isRetain() || md->isStrong() || md->isWeak())
747 if (md->isAssign()) t << "assign";
748 else if (md->isCopy()) t << "copy";
749 else if (md->isRetain()) t << "retain";
750 else if (md->isStrong()) t << "strong";
751 else if (md->isWeak()) t << "weak";
755 else if (md->memberType() == MemberType_Event)
758 if (md->isAddable()) t << "yes"; else t << "no";
762 if (md->isRemovable()) t << "yes"; else t << "no";
766 if (md->isRaisable()) t << "yes"; else t << "no";
772 if (md->memberType()!=MemberType_Define &&
773 md->memberType()!=MemberType_Enumeration
776 writeMemberTemplateLists(md,t);
777 QCString typeStr = md->typeString(); //replaceAnonymousScopes(md->typeString());
778 stripQualifiers(typeStr);
780 linkifyText(TextGeneratorXMLImpl(t),def,md->getBodyDef(),md,typeStr);
781 t << "</type>" << endl;
782 t << " <definition>" << convertToXML(md->definition()) << "</definition>" << endl;
783 t << " <argsstring>" << convertToXML(md->argsString()) << "</argsstring>" << endl;
786 if (md->memberType() == MemberType_Enumeration)
789 linkifyText(TextGeneratorXMLImpl(t),def,md->getBodyDef(),md,md->enumBaseType());
790 t << "</type>" << endl;
793 t << " <name>" << convertToXML(md->name()) << "</name>" << endl;
795 if (md->memberType() == MemberType_Property)
797 if (md->isReadable())
798 t << " <read>" << convertToXML(md->getReadAccessor()) << "</read>" << endl;
799 if (md->isWritable())
800 t << " <write>" << convertToXML(md->getWriteAccessor()) << "</write>" << endl;
803 if (md->memberType()==MemberType_Variable && md->bitfieldString())
805 QCString bitfield = md->bitfieldString();
806 if (bitfield.at(0)==':') bitfield=bitfield.mid(1);
807 t << " <bitfield>" << convertToXML(bitfield) << "</bitfield>" << endl;
810 MemberDef *rmd = md->reimplements();
813 t << " <reimplements refid=\""
814 << memberOutputFileBase(rmd) << "_1" << rmd->anchor() << "\">"
815 << convertToXML(rmd->name()) << "</reimplements>" << endl;
817 MemberList *rbml = md->reimplementedBy();
820 MemberListIterator mli(*rbml);
821 for (mli.toFirst();(rmd=mli.current());++mli)
823 t << " <reimplementedby refid=\""
824 << memberOutputFileBase(rmd) << "_1" << rmd->anchor() << "\">"
825 << convertToXML(rmd->name()) << "</reimplementedby>" << endl;
829 if (isFunc) //function
831 ArgumentList *declAl = md->declArgumentList();
832 ArgumentList *defAl = md->argumentList();
833 if (declAl && defAl && declAl->count()>0)
835 ArgumentListIterator declAli(*declAl);
836 ArgumentListIterator defAli(*defAl);
838 for (declAli.toFirst();(a=declAli.current());++declAli)
840 Argument *defArg = defAli.current();
841 t << " <param>" << endl;
842 if (!a->attrib.isEmpty())
844 t << " <attributes>";
845 writeXMLString(t,a->attrib);
846 t << "</attributes>" << endl;
848 if (!a->type.isEmpty())
851 linkifyText(TextGeneratorXMLImpl(t),def,md->getBodyDef(),md,a->type);
852 t << "</type>" << endl;
854 if (!a->name.isEmpty())
857 writeXMLString(t,a->name);
858 t << "</declname>" << endl;
860 if (defArg && !defArg->name.isEmpty() && defArg->name!=a->name)
863 writeXMLString(t,defArg->name);
864 t << "</defname>" << endl;
866 if (!a->array.isEmpty())
869 writeXMLString(t,a->array);
870 t << "</array>" << endl;
872 if (!a->defval.isEmpty())
875 linkifyText(TextGeneratorXMLImpl(t),def,md->getBodyDef(),md,a->defval);
876 t << "</defval>" << endl;
878 if (defArg && defArg->hasDocumentation())
880 t << " <briefdescription>";
881 writeXMLDocBlock(t,md->getDefFileName(),md->getDefLine(),
882 md->getOuterScope(),md,defArg->docs);
883 t << "</briefdescription>" << endl;
885 t << " </param>" << endl;
886 if (defArg) ++defAli;
890 else if (md->memberType()==MemberType_Define &&
891 md->argsString()) // define
893 if (md->argumentList()->count()==0) // special case for "foo()" to
894 // disguish it from "foo".
896 t << " <param></param>" << endl;
900 ArgumentListIterator ali(*md->argumentList());
902 for (ali.toFirst();(a=ali.current());++ali)
904 t << " <param><defname>" << a->type << "</defname></param>" << endl;
909 if (md->hasOneLineInitializer() || md->hasMultiLineInitializer())
911 t << " <initializer>";
912 linkifyText(TextGeneratorXMLImpl(t),def,md->getBodyDef(),md,md->initializer());
913 t << "</initializer>" << endl;
916 if (md->excpString())
918 t << " <exceptions>";
919 linkifyText(TextGeneratorXMLImpl(t),def,md->getBodyDef(),md,md->excpString());
920 t << "</exceptions>" << endl;
923 if (md->memberType()==MemberType_Enumeration) // enum
925 MemberList *enumFields = md->enumFieldList();
928 MemberListIterator emli(*enumFields);
930 for (emli.toFirst();(emd=emli.current());++emli)
932 ti << " <member refid=\"" << memberOutputFileBase(md)
933 << "_1" << emd->anchor() << "\" kind=\"enumvalue\"><name>"
934 << convertToXML(emd->name()) << "</name></member>" << endl;
936 t << " <enumvalue id=\"" << memberOutputFileBase(md) << "_1"
937 << emd->anchor() << "\" prot=\"";
938 switch (emd->protection())
940 case Public: t << "public"; break;
941 case Protected: t << "protected"; break;
942 case Private: t << "private"; break;
943 case Package: t << "package"; break;
947 writeXMLString(t,emd->name());
948 t << "</name>" << endl;
949 if (!emd->initializer().isEmpty())
951 t << " <initializer>";
952 writeXMLString(t,emd->initializer());
953 t << "</initializer>" << endl;
955 t << " <briefdescription>" << endl;
956 writeXMLDocBlock(t,emd->briefFile(),emd->briefLine(),emd->getOuterScope(),emd,emd->briefDescription());
957 t << " </briefdescription>" << endl;
958 t << " <detaileddescription>" << endl;
959 writeXMLDocBlock(t,emd->docFile(),emd->docLine(),emd->getOuterScope(),emd,emd->documentation());
960 t << " </detaileddescription>" << endl;
961 t << " </enumvalue>" << endl;
965 t << " <briefdescription>" << endl;
966 writeXMLDocBlock(t,md->briefFile(),md->briefLine(),md->getOuterScope(),md,md->briefDescription());
967 t << " </briefdescription>" << endl;
968 t << " <detaileddescription>" << endl;
969 writeXMLDocBlock(t,md->docFile(),md->docLine(),md->getOuterScope(),md,md->documentation());
970 t << " </detaileddescription>" << endl;
971 t << " <inbodydescription>" << endl;
972 writeXMLDocBlock(t,md->docFile(),md->inbodyLine(),md->getOuterScope(),md,md->inbodyDocumentation());
973 t << " </inbodydescription>" << endl;
974 if (md->getDefLine()!=-1)
976 t << " <location file=\""
977 << stripFromPath(md->getDefFileName()) << "\" line=\""
978 << md->getDefLine() << "\"" << " column=\""
979 << md->getDefColumn() << "\"" ;
980 if (md->getStartBodyLine()!=-1)
982 FileDef *bodyDef = md->getBodyDef();
985 t << " bodyfile=\"" << stripFromPath(bodyDef->absFilePath()) << "\"";
987 t << " bodystart=\"" << md->getStartBodyLine() << "\" bodyend=\""
988 << md->getEndBodyLine() << "\"";
993 //printf("md->getReferencesMembers()=%p\n",md->getReferencesMembers());
994 MemberSDict *mdict = md->getReferencesMembers();
997 MemberSDict::Iterator mdi(*mdict);
999 for (mdi.toFirst();(rmd=mdi.current());++mdi)
1001 writeMemberReference(t,def,rmd,"references");
1004 mdict = md->getReferencedByMembers();
1007 MemberSDict::Iterator mdi(*mdict);
1009 for (mdi.toFirst();(rmd=mdi.current());++mdi)
1011 writeMemberReference(t,def,rmd,"referencedby");
1015 t << " </memberdef>" << endl;
1018 // namespace members are also inserted in the file scope, but
1019 // to prevent this duplication in the XML output, we optionally filter those here.
1020 static bool memberVisible(Definition *d,MemberDef *md)
1022 return Config_getBool(XML_NS_MEMB_FILE_SCOPE) ||
1023 d->definitionType()!=Definition::TypeFile ||
1024 md->getNamespaceDef()==0;
1027 static void generateXMLSection(Definition *d,FTextStream &ti,FTextStream &t,
1028 MemberList *ml,const char *kind,const char *header=0,
1029 const char *documentation=0)
1032 MemberListIterator mli(*ml);
1035 for (mli.toFirst();(md=mli.current());++mli)
1037 if (memberVisible(d,md))
1042 if (count==0) return; // empty list
1044 t << " <sectiondef kind=\"" << kind << "\">" << endl;
1047 t << " <header>" << convertToXML(header) << "</header>" << endl;
1051 t << " <description>";
1052 writeXMLDocBlock(t,d->docFile(),d->docLine(),d,0,documentation);
1053 t << "</description>" << endl;
1055 for (mli.toFirst();(md=mli.current());++mli)
1057 if (memberVisible(d,md))
1059 generateXMLForMember(md,ti,t,d);
1062 t << " </sectiondef>" << endl;
1065 static void writeListOfAllMembers(ClassDef *cd,FTextStream &t)
1067 t << " <listofallmembers>" << endl;
1068 if (cd->memberNameInfoSDict())
1070 MemberNameInfoSDict::Iterator mnii(*cd->memberNameInfoSDict());
1071 MemberNameInfo *mni;
1072 for (mnii.toFirst();(mni=mnii.current());++mnii)
1074 MemberNameInfoIterator mii(*mni);
1076 for (mii.toFirst();(mi=mii.current());++mii)
1078 MemberDef *md=mi->memberDef;
1079 if (md->name().at(0)!='@') // skip anonymous members
1081 Protection prot = mi->prot;
1082 Specifier virt=md->virtualness();
1083 t << " <member refid=\"" << memberOutputFileBase(md) << "_1" <<
1084 md->anchor() << "\" prot=\"";
1087 case Public: t << "public"; break;
1088 case Protected: t << "protected"; break;
1089 case Private: t << "private"; break;
1090 case Package: t << "package"; break;
1095 case Normal: t << "non-virtual"; break;
1096 case Virtual: t << "virtual"; break;
1097 case Pure: t << "pure-virtual"; break;
1100 if (!mi->ambiguityResolutionScope.isEmpty())
1102 t << " ambiguityscope=\"" << convertToXML(mi->ambiguityResolutionScope) << "\"";
1104 t << "><scope>" << convertToXML(cd->name()) << "</scope><name>" <<
1105 convertToXML(md->name()) << "</name></member>" << endl;
1110 t << " </listofallmembers>" << endl;
1113 static void writeInnerClasses(const ClassSDict *cl,FTextStream &t)
1117 ClassSDict::Iterator cli(*cl);
1119 for (cli.toFirst();(cd=cli.current());++cli)
1121 if (!cd->isHidden() && cd->name().find('@')==-1) // skip anonymous scopes
1123 t << " <innerclass refid=\"" << classOutputFileBase(cd)
1125 switch(cd->protection())
1127 case Public: t << "public"; break;
1128 case Protected: t << "protected"; break;
1129 case Private: t << "private"; break;
1130 case Package: t << "package"; break;
1132 t << "\">" << convertToXML(cd->name()) << "</innerclass>" << endl;
1138 static void writeInnerNamespaces(const NamespaceSDict *nl,FTextStream &t)
1142 NamespaceSDict::Iterator nli(*nl);
1144 for (nli.toFirst();(nd=nli.current());++nli)
1146 if (!nd->isHidden() && nd->name().find('@')==-1) // skip anonymous scopes
1148 t << " <innernamespace refid=\"" << nd->getOutputFileBase()
1149 << "\">" << convertToXML(nd->name()) << "</innernamespace>" << endl;
1155 static void writeInnerFiles(const FileList *fl,FTextStream &t)
1159 QListIterator<FileDef> fli(*fl);
1161 for (fli.toFirst();(fd=fli.current());++fli)
1163 t << " <innerfile refid=\"" << fd->getOutputFileBase()
1164 << "\">" << convertToXML(fd->name()) << "</innerfile>" << endl;
1169 static void writeInnerPages(const PageSDict *pl,FTextStream &t)
1173 PageSDict::Iterator pli(*pl);
1175 for (pli.toFirst();(pd=pli.current());++pli)
1177 t << " <innerpage refid=\"" << pd->getOutputFileBase();
1178 if (pd->getGroupDef())
1180 t << "_" << pd->name();
1182 t << "\">" << convertToXML(pd->title()) << "</innerpage>" << endl;
1187 static void writeInnerGroups(const GroupList *gl,FTextStream &t)
1191 GroupListIterator gli(*gl);
1193 for (gli.toFirst();(sgd=gli.current());++gli)
1195 t << " <innergroup refid=\"" << sgd->getOutputFileBase()
1196 << "\">" << convertToXML(sgd->groupTitle())
1197 << "</innergroup>" << endl;
1202 static void writeInnerDirs(const DirList *dl,FTextStream &t)
1206 QListIterator<DirDef> subdirs(*dl);
1208 for (subdirs.toFirst();(subdir=subdirs.current());++subdirs)
1210 t << " <innerdir refid=\"" << subdir->getOutputFileBase()
1211 << "\">" << convertToXML(subdir->displayName()) << "</innerdir>" << endl;
1216 static void generateXMLForClass(ClassDef *cd,FTextStream &ti)
1218 // + brief description
1219 // + detailed description
1220 // + template argument list(s)
1223 // + inheritance diagram
1224 // + list of direct super classes
1225 // + list of direct sub classes
1226 // + list of inner classes
1227 // + collaboration diagram
1228 // + list of all members
1229 // + user defined member sections
1230 // + standard member sections
1231 // + detailed member documentation
1232 // - examples using the class
1234 if (cd->isReference()) return; // skip external references.
1235 if (cd->isHidden()) return; // skip hidden classes.
1236 if (cd->name().find('@')!=-1) return; // skip anonymous compounds.
1237 if (cd->templateMaster()!=0) return; // skip generated template instances.
1238 if (cd->isArtificial()) return; // skip artificially created classes
1240 msg("Generating XML output for class %s\n",cd->name().data());
1242 ti << " <compound refid=\"" << classOutputFileBase(cd)
1243 << "\" kind=\"" << cd->compoundTypeString()
1244 << "\"><name>" << convertToXML(cd->name()) << "</name>" << endl;
1246 QCString outputDirectory = Config_getString(XML_OUTPUT);
1247 QCString fileName=outputDirectory+"/"+ classOutputFileBase(cd)+".xml";
1249 if (!f.open(IO_WriteOnly))
1251 err("Cannot open file %s for writing!\n",fileName.data());
1255 //t.setEncoding(FTextStream::UnicodeUTF8);
1258 t << " <compounddef id=\""
1259 << classOutputFileBase(cd) << "\" kind=\""
1260 << cd->compoundTypeString() << "\" language=\""
1261 << langToString(cd->getLanguage()) << "\" prot=\"";
1262 switch (cd->protection())
1264 case Public: t << "public"; break;
1265 case Protected: t << "protected"; break;
1266 case Private: t << "private"; break;
1267 case Package: t << "package"; break;
1269 if (cd->isFinal()) t << "\" final=\"yes";
1270 if (cd->isSealed()) t << "\" sealed=\"yes";
1271 if (cd->isAbstract()) t << "\" abstract=\"yes";
1273 t << " <compoundname>";
1274 writeXMLString(t,cd->name());
1275 t << "</compoundname>" << endl;
1276 if (cd->baseClasses())
1278 BaseClassListIterator bcli(*cd->baseClasses());
1280 for (bcli.toFirst();(bcd=bcli.current());++bcli)
1282 t << " <basecompoundref ";
1283 if (bcd->classDef->isLinkable())
1285 t << "refid=\"" << classOutputFileBase(bcd->classDef) << "\" ";
1290 case Public: t << "public"; break;
1291 case Protected: t << "protected"; break;
1292 case Private: t << "private"; break;
1293 case Package: ASSERT(0); break;
1298 case Normal: t << "non-virtual"; break;
1299 case Virtual: t << "virtual"; break;
1300 case Pure: t <<"pure-virtual"; break;
1303 if (!bcd->templSpecifiers.isEmpty())
1306 insertTemplateSpecifierInScope(
1307 bcd->classDef->name(),bcd->templSpecifiers)
1312 t << convertToXML(bcd->classDef->displayName());
1314 t << "</basecompoundref>" << endl;
1317 if (cd->subClasses())
1319 BaseClassListIterator bcli(*cd->subClasses());
1321 for (bcli.toFirst();(bcd=bcli.current());++bcli)
1323 t << " <derivedcompoundref refid=\""
1324 << classOutputFileBase(bcd->classDef)
1328 case Public: t << "public"; break;
1329 case Protected: t << "protected"; break;
1330 case Private: t << "private"; break;
1331 case Package: ASSERT(0); break;
1336 case Normal: t << "non-virtual"; break;
1337 case Virtual: t << "virtual"; break;
1338 case Pure: t << "pure-virtual"; break;
1340 t << "\">" << convertToXML(bcd->classDef->displayName())
1341 << "</derivedcompoundref>" << endl;
1345 IncludeInfo *ii=cd->includeInfo();
1348 QCString nm = ii->includeName;
1349 if (nm.isEmpty() && ii->fileDef) nm = ii->fileDef->docName();
1353 if (ii->fileDef && !ii->fileDef->isReference()) // TODO: support external references
1355 t << " refid=\"" << ii->fileDef->getOutputFileBase() << "\"";
1357 t << " local=\"" << (ii->local ? "yes" : "no") << "\">";
1359 t << "</includes>" << endl;
1363 writeInnerClasses(cd->getClassSDict(),t);
1365 writeTemplateList(cd,t);
1366 if (cd->getMemberGroupSDict())
1368 MemberGroupSDict::Iterator mgli(*cd->getMemberGroupSDict());
1370 for (;(mg=mgli.current());++mgli)
1372 generateXMLSection(cd,ti,t,mg->members(),"user-defined",mg->header(),
1373 mg->documentation());
1377 QListIterator<MemberList> mli(cd->getMemberLists());
1379 for (mli.toFirst();(ml=mli.current());++mli)
1381 if ((ml->listType()&MemberListType_detailedLists)==0)
1383 generateXMLSection(cd,ti,t,ml,g_xmlSectionMapper.find(ml->listType()));
1387 t << " <briefdescription>" << endl;
1388 writeXMLDocBlock(t,cd->briefFile(),cd->briefLine(),cd,0,cd->briefDescription());
1389 t << " </briefdescription>" << endl;
1390 t << " <detaileddescription>" << endl;
1391 writeXMLDocBlock(t,cd->docFile(),cd->docLine(),cd,0,cd->documentation());
1392 t << " </detaileddescription>" << endl;
1393 DotClassGraph inheritanceGraph(cd,DotNode::Inheritance);
1394 if (!inheritanceGraph.isTrivial())
1396 t << " <inheritancegraph>" << endl;
1397 inheritanceGraph.writeXML(t);
1398 t << " </inheritancegraph>" << endl;
1400 DotClassGraph collaborationGraph(cd,DotNode::Collaboration);
1401 if (!collaborationGraph.isTrivial())
1403 t << " <collaborationgraph>" << endl;
1404 collaborationGraph.writeXML(t);
1405 t << " </collaborationgraph>" << endl;
1407 t << " <location file=\""
1408 << stripFromPath(cd->getDefFileName()) << "\" line=\""
1409 << cd->getDefLine() << "\"" << " column=\""
1410 << cd->getDefColumn() << "\"" ;
1411 if (cd->getStartBodyLine()!=-1)
1413 FileDef *bodyDef = cd->getBodyDef();
1416 t << " bodyfile=\"" << stripFromPath(bodyDef->absFilePath()) << "\"";
1418 t << " bodystart=\"" << cd->getStartBodyLine() << "\" bodyend=\""
1419 << cd->getEndBodyLine() << "\"";
1422 writeListOfAllMembers(cd,t);
1423 t << " </compounddef>" << endl;
1424 t << "</doxygen>" << endl;
1426 ti << " </compound>" << endl;
1429 static void generateXMLForNamespace(NamespaceDef *nd,FTextStream &ti)
1431 // + contained class definitions
1432 // + contained namespace definitions
1438 // - files containing (parts of) the namespace definition
1440 if (nd->isReference() || nd->isHidden()) return; // skip external references
1442 ti << " <compound refid=\"" << nd->getOutputFileBase()
1443 << "\" kind=\"namespace\"" << "><name>"
1444 << convertToXML(nd->name()) << "</name>" << endl;
1446 QCString outputDirectory = Config_getString(XML_OUTPUT);
1447 QCString fileName=outputDirectory+"/"+nd->getOutputFileBase()+".xml";
1449 if (!f.open(IO_WriteOnly))
1451 err("Cannot open file %s for writing!\n",fileName.data());
1455 //t.setEncoding(FTextStream::UnicodeUTF8);
1458 t << " <compounddef id=\"" << nd->getOutputFileBase()
1459 << "\" kind=\"namespace\" language=\""
1460 << langToString(nd->getLanguage()) << "\">" << endl;
1461 t << " <compoundname>";
1462 writeXMLString(t,nd->name());
1463 t << "</compoundname>" << endl;
1465 writeInnerClasses(nd->getClassSDict(),t);
1466 writeInnerNamespaces(nd->getNamespaceSDict(),t);
1468 if (nd->getMemberGroupSDict())
1470 MemberGroupSDict::Iterator mgli(*nd->getMemberGroupSDict());
1472 for (;(mg=mgli.current());++mgli)
1474 generateXMLSection(nd,ti,t,mg->members(),"user-defined",mg->header(),
1475 mg->documentation());
1479 QListIterator<MemberList> mli(nd->getMemberLists());
1481 for (mli.toFirst();(ml=mli.current());++mli)
1483 if ((ml->listType()&MemberListType_declarationLists)!=0)
1485 generateXMLSection(nd,ti,t,ml,g_xmlSectionMapper.find(ml->listType()));
1489 t << " <briefdescription>" << endl;
1490 writeXMLDocBlock(t,nd->briefFile(),nd->briefLine(),nd,0,nd->briefDescription());
1491 t << " </briefdescription>" << endl;
1492 t << " <detaileddescription>" << endl;
1493 writeXMLDocBlock(t,nd->docFile(),nd->docLine(),nd,0,nd->documentation());
1494 t << " </detaileddescription>" << endl;
1495 t << " <location file=\""
1496 << stripFromPath(nd->getDefFileName()) << "\" line=\""
1497 << nd->getDefLine() << "\"" << " column=\""
1498 << nd->getDefColumn() << "\"/>" << endl ;
1499 t << " </compounddef>" << endl;
1500 t << "</doxygen>" << endl;
1502 ti << " </compound>" << endl;
1505 static void generateXMLForFile(FileDef *fd,FTextStream &ti)
1508 // + includedby files
1510 // + included by graph
1511 // + contained class definitions
1512 // + contained namespace definitions
1519 // - number of lines
1521 if (fd->isReference()) return; // skip external references
1523 ti << " <compound refid=\"" << fd->getOutputFileBase()
1524 << "\" kind=\"file\"><name>" << convertToXML(fd->name())
1525 << "</name>" << endl;
1527 QCString outputDirectory = Config_getString(XML_OUTPUT);
1528 QCString fileName=outputDirectory+"/"+fd->getOutputFileBase()+".xml";
1530 if (!f.open(IO_WriteOnly))
1532 err("Cannot open file %s for writing!\n",fileName.data());
1536 //t.setEncoding(FTextStream::UnicodeUTF8);
1539 t << " <compounddef id=\"" << fd->getOutputFileBase()
1540 << "\" kind=\"file\" language=\""
1541 << langToString(fd->getLanguage()) << "\">" << endl;
1542 t << " <compoundname>";
1543 writeXMLString(t,fd->name());
1544 t << "</compoundname>" << endl;
1548 if (fd->includeFileList())
1550 QListIterator<IncludeInfo> ili1(*fd->includeFileList());
1551 for (ili1.toFirst();(inc=ili1.current());++ili1)
1554 if (inc->fileDef && !inc->fileDef->isReference()) // TODO: support external references
1556 t << " refid=\"" << inc->fileDef->getOutputFileBase() << "\"";
1558 t << " local=\"" << (inc->local ? "yes" : "no") << "\">";
1559 t << inc->includeName;
1560 t << "</includes>" << endl;
1564 if (fd->includedByFileList())
1566 QListIterator<IncludeInfo> ili2(*fd->includedByFileList());
1567 for (ili2.toFirst();(inc=ili2.current());++ili2)
1569 t << " <includedby";
1570 if (inc->fileDef && !inc->fileDef->isReference()) // TODO: support external references
1572 t << " refid=\"" << inc->fileDef->getOutputFileBase() << "\"";
1574 t << " local=\"" << (inc->local ? "yes" : "no") << "\">";
1575 t << inc->includeName;
1576 t << "</includedby>" << endl;
1580 DotInclDepGraph incDepGraph(fd,FALSE);
1581 if (!incDepGraph.isTrivial())
1583 t << " <incdepgraph>" << endl;
1584 incDepGraph.writeXML(t);
1585 t << " </incdepgraph>" << endl;
1588 DotInclDepGraph invIncDepGraph(fd,TRUE);
1589 if (!invIncDepGraph.isTrivial())
1591 t << " <invincdepgraph>" << endl;
1592 invIncDepGraph.writeXML(t);
1593 t << " </invincdepgraph>" << endl;
1596 if (fd->getClassSDict())
1598 writeInnerClasses(fd->getClassSDict(),t);
1600 if (fd->getNamespaceSDict())
1602 writeInnerNamespaces(fd->getNamespaceSDict(),t);
1605 if (fd->getMemberGroupSDict())
1607 MemberGroupSDict::Iterator mgli(*fd->getMemberGroupSDict());
1609 for (;(mg=mgli.current());++mgli)
1611 generateXMLSection(fd,ti,t,mg->members(),"user-defined",mg->header(),
1612 mg->documentation());
1616 QListIterator<MemberList> mli(fd->getMemberLists());
1618 for (mli.toFirst();(ml=mli.current());++mli)
1620 if ((ml->listType()&MemberListType_declarationLists)!=0)
1622 generateXMLSection(fd,ti,t,ml,g_xmlSectionMapper.find(ml->listType()));
1626 t << " <briefdescription>" << endl;
1627 writeXMLDocBlock(t,fd->briefFile(),fd->briefLine(),fd,0,fd->briefDescription());
1628 t << " </briefdescription>" << endl;
1629 t << " <detaileddescription>" << endl;
1630 writeXMLDocBlock(t,fd->docFile(),fd->docLine(),fd,0,fd->documentation());
1631 t << " </detaileddescription>" << endl;
1632 if (Config_getBool(XML_PROGRAMLISTING))
1634 t << " <programlisting>" << endl;
1635 writeXMLCodeBlock(t,fd);
1636 t << " </programlisting>" << endl;
1638 t << " <location file=\"" << stripFromPath(fd->getDefFileName()) << "\"/>" << endl;
1639 t << " </compounddef>" << endl;
1640 t << "</doxygen>" << endl;
1642 ti << " </compound>" << endl;
1645 static void generateXMLForGroup(GroupDef *gd,FTextStream &ti)
1656 // + brief description
1657 // + detailed description
1659 if (gd->isReference()) return; // skip external references
1661 ti << " <compound refid=\"" << gd->getOutputFileBase()
1662 << "\" kind=\"group\"><name>" << convertToXML(gd->name()) << "</name>" << endl;
1664 QCString outputDirectory = Config_getString(XML_OUTPUT);
1665 QCString fileName=outputDirectory+"/"+gd->getOutputFileBase()+".xml";
1667 if (!f.open(IO_WriteOnly))
1669 err("Cannot open file %s for writing!\n",fileName.data());
1674 //t.setEncoding(FTextStream::UnicodeUTF8);
1676 t << " <compounddef id=\""
1677 << gd->getOutputFileBase() << "\" kind=\"group\">" << endl;
1678 t << " <compoundname>" << convertToXML(gd->name()) << "</compoundname>" << endl;
1679 t << " <title>" << convertToXML(gd->groupTitle()) << "</title>" << endl;
1681 writeInnerFiles(gd->getFiles(),t);
1682 writeInnerClasses(gd->getClasses(),t);
1683 writeInnerNamespaces(gd->getNamespaces(),t);
1684 writeInnerPages(gd->getPages(),t);
1685 writeInnerGroups(gd->getSubGroups(),t);
1687 if (gd->getMemberGroupSDict())
1689 MemberGroupSDict::Iterator mgli(*gd->getMemberGroupSDict());
1691 for (;(mg=mgli.current());++mgli)
1693 generateXMLSection(gd,ti,t,mg->members(),"user-defined",mg->header(),
1694 mg->documentation());
1698 QListIterator<MemberList> mli(gd->getMemberLists());
1700 for (mli.toFirst();(ml=mli.current());++mli)
1702 if ((ml->listType()&MemberListType_declarationLists)!=0)
1704 generateXMLSection(gd,ti,t,ml,g_xmlSectionMapper.find(ml->listType()));
1708 t << " <briefdescription>" << endl;
1709 writeXMLDocBlock(t,gd->briefFile(),gd->briefLine(),gd,0,gd->briefDescription());
1710 t << " </briefdescription>" << endl;
1711 t << " <detaileddescription>" << endl;
1712 writeXMLDocBlock(t,gd->docFile(),gd->docLine(),gd,0,gd->documentation());
1713 t << " </detaileddescription>" << endl;
1714 t << " </compounddef>" << endl;
1715 t << "</doxygen>" << endl;
1717 ti << " </compound>" << endl;
1720 static void generateXMLForDir(DirDef *dd,FTextStream &ti)
1722 if (dd->isReference()) return; // skip external references
1723 ti << " <compound refid=\"" << dd->getOutputFileBase()
1724 << "\" kind=\"dir\"><name>" << convertToXML(dd->displayName())
1725 << "</name>" << endl;
1727 QCString outputDirectory = Config_getString(XML_OUTPUT);
1728 QCString fileName=outputDirectory+"/"+dd->getOutputFileBase()+".xml";
1730 if (!f.open(IO_WriteOnly))
1732 err("Cannot open file %s for writing!\n",fileName.data());
1737 //t.setEncoding(FTextStream::UnicodeUTF8);
1739 t << " <compounddef id=\""
1740 << dd->getOutputFileBase() << "\" kind=\"dir\">" << endl;
1741 t << " <compoundname>" << convertToXML(dd->displayName()) << "</compoundname>" << endl;
1743 writeInnerDirs(&dd->subDirs(),t);
1744 writeInnerFiles(dd->getFiles(),t);
1746 t << " <briefdescription>" << endl;
1747 writeXMLDocBlock(t,dd->briefFile(),dd->briefLine(),dd,0,dd->briefDescription());
1748 t << " </briefdescription>" << endl;
1749 t << " <detaileddescription>" << endl;
1750 writeXMLDocBlock(t,dd->docFile(),dd->docLine(),dd,0,dd->documentation());
1751 t << " </detaileddescription>" << endl;
1752 t << " <location file=\"" << stripFromPath(dd->name()) << "\"/>" << endl;
1753 t << " </compounddef>" << endl;
1754 t << "</doxygen>" << endl;
1756 ti << " </compound>" << endl;
1759 static void generateXMLForPage(PageDef *pd,FTextStream &ti,bool isExample)
1765 const char *kindName = isExample ? "example" : "page";
1767 if (pd->isReference()) return;
1769 QCString pageName = pd->getOutputFileBase();
1770 if (pd->getGroupDef())
1772 pageName+=(QCString)"_"+pd->name();
1774 if (pageName=="index") pageName="indexpage"; // to prevent overwriting the generated index page.
1776 ti << " <compound refid=\"" << pageName
1777 << "\" kind=\"" << kindName << "\"><name>" << convertToXML(pd->name())
1778 << "</name>" << endl;
1780 QCString outputDirectory = Config_getString(XML_OUTPUT);
1781 QCString fileName=outputDirectory+"/"+pageName+".xml";
1783 if (!f.open(IO_WriteOnly))
1785 err("Cannot open file %s for writing!\n",fileName.data());
1790 //t.setEncoding(FTextStream::UnicodeUTF8);
1792 t << " <compounddef id=\"" << pageName;
1793 t << "\" kind=\"" << kindName << "\">" << endl;
1794 t << " <compoundname>" << convertToXML(pd->name())
1795 << "</compoundname>" << endl;
1797 if (pd==Doxygen::mainPage) // main page is special
1800 if (!pd->title().isEmpty() && pd->title().lower()!="notitle")
1802 title = filterTitle(convertCharEntitiesToUTF8(Doxygen::mainPage->title()));
1806 title = Config_getString(PROJECT_NAME);
1808 t << " <title>" << convertToXML(convertCharEntitiesToUTF8(title))
1809 << "</title>" << endl;
1813 SectionInfo *si = Doxygen::sectionDict->find(pd->name());
1816 t << " <title>" << convertToXML(convertCharEntitiesToUTF8(filterTitle(si->title)))
1817 << "</title>" << endl;
1820 writeInnerPages(pd->getSubPages(),t);
1821 if (pd->localToc().isXmlEnabled())
1823 t << " <tableofcontents>" << endl;
1824 SectionDict *sectionDict = pd->getSectionDict();
1825 SDict<SectionInfo>::Iterator li(*sectionDict);
1828 bool inLi[5]={ FALSE, FALSE, FALSE, FALSE, FALSE };
1829 int maxLevel = pd->localToc().xmlLevel();
1830 for (li.toFirst();(si=li.current());++li)
1832 if (si->type==SectionInfo::Section ||
1833 si->type==SectionInfo::Subsection ||
1834 si->type==SectionInfo::Subsubsection ||
1835 si->type==SectionInfo::Paragraph)
1837 //printf(" level=%d title=%s\n",level,si->title.data());
1838 int nextLevel = (int)si->type;
1839 if (nextLevel>level)
1841 for (l=level;l<nextLevel;l++)
1843 if (l < maxLevel) t << " <tableofcontents>" << endl;
1846 else if (nextLevel<level)
1848 for (l=level;l>nextLevel;l--)
1850 if (l <= maxLevel && inLi[l]) t << " </tocsect>" << endl;
1852 if (l <= maxLevel) t << " </tableofcontents>" << endl;
1855 if (nextLevel <= maxLevel)
1857 if (inLi[nextLevel]) t << " </tocsect>" << endl;
1858 QCString titleDoc = convertToXML(si->title);
1859 t << " <tocsect>" << endl;
1860 t << " <name>" << (si->title.isEmpty()?si->label:titleDoc) << "</name>" << endl;
1861 t << " <reference>" << convertToXML(pageName) << "_1" << convertToXML(si -> label) << "</reference>" << endl;
1862 inLi[nextLevel]=TRUE;
1867 while (level>1 && level <= maxLevel)
1869 if (inLi[level]) t << " </tocsect>" << endl;
1871 t << " </tableofcontents>" << endl;
1874 if (level <= maxLevel && inLi[level]) t << " </tocsect>" << endl;
1876 t << " </tableofcontents>" << endl;
1878 t << " <briefdescription>" << endl;
1879 writeXMLDocBlock(t,pd->briefFile(),pd->briefLine(),pd,0,pd->briefDescription());
1880 t << " </briefdescription>" << endl;
1881 t << " <detaileddescription>" << endl;
1884 writeXMLDocBlock(t,pd->docFile(),pd->docLine(),pd,0,
1885 pd->documentation()+"\n\\include "+pd->name());
1889 writeXMLDocBlock(t,pd->docFile(),pd->docLine(),pd,0,
1890 pd->documentation());
1892 t << " </detaileddescription>" << endl;
1894 t << " </compounddef>" << endl;
1895 t << "</doxygen>" << endl;
1897 ti << " </compound>" << endl;
1909 QCString outputDirectory = Config_getString(XML_OUTPUT);
1910 QDir xmlDir(outputDirectory);
1911 createSubDirs(xmlDir);
1913 ResourceMgr::instance().copyResource("index.xsd",outputDirectory);
1915 QCString fileName=outputDirectory+"/compound.xsd";
1917 if (!f.open(IO_WriteOnly))
1919 err("Cannot open file %s for writing!\n",fileName.data());
1923 // write compound.xsd, but replace special marker with the entities
1924 QCString compound_xsd = ResourceMgr::instance().getAsString("compound.xsd");
1925 const char *startLine = compound_xsd.data();
1928 // find end of the line
1929 const char *endLine = startLine+1;
1930 while (*endLine && *(endLine-1)!='\n') endLine++; // skip to end of the line including \n
1931 int len=endLine-startLine;
1935 qstrncpy(s.rawData(),startLine,len);
1937 if (s.find("<!-- Automatically insert here the HTML entities -->")!=-1)
1940 HtmlEntityMapper::instance()->writeXMLSchema(t);
1944 f.writeBlock(startLine,len);
1951 fileName=outputDirectory+"/index.xml";
1952 f.setName(fileName);
1953 if (!f.open(IO_WriteOnly))
1955 err("Cannot open file %s for writing!\n",fileName.data());
1959 //t.setEncoding(FTextStream::UnicodeUTF8);
1961 // write index header
1962 t << "<?xml version='1.0' encoding='UTF-8' standalone='no'?>" << endl;;
1963 t << "<doxygenindex xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" ";
1964 t << "xsi:noNamespaceSchemaLocation=\"index.xsd\" ";
1965 t << "version=\"" << versionString << "\">" << endl;
1968 ClassSDict::Iterator cli(*Doxygen::classSDict);
1970 for (cli.toFirst();(cd=cli.current());++cli)
1972 generateXMLForClass(cd,t);
1976 // ClassSDict::Iterator cli(Doxygen::hiddenClasses);
1978 // for (cli.toFirst();(cd=cli.current());++cli)
1980 // msg("Generating XML output for class %s\n",cd->name().data());
1981 // generateXMLForClass(cd,t);
1984 NamespaceSDict::Iterator nli(*Doxygen::namespaceSDict);
1986 for (nli.toFirst();(nd=nli.current());++nli)
1988 msg("Generating XML output for namespace %s\n",nd->name().data());
1989 generateXMLForNamespace(nd,t);
1991 FileNameListIterator fnli(*Doxygen::inputNameList);
1993 for (;(fn=fnli.current());++fnli)
1995 FileNameIterator fni(*fn);
1997 for (;(fd=fni.current());++fni)
1999 msg("Generating XML output for file %s\n",fd->name().data());
2000 generateXMLForFile(fd,t);
2003 GroupSDict::Iterator gli(*Doxygen::groupSDict);
2005 for (;(gd=gli.current());++gli)
2007 msg("Generating XML output for group %s\n",gd->name().data());
2008 generateXMLForGroup(gd,t);
2011 PageSDict::Iterator pdi(*Doxygen::pageSDict);
2013 for (pdi.toFirst();(pd=pdi.current());++pdi)
2015 msg("Generating XML output for page %s\n",pd->name().data());
2016 generateXMLForPage(pd,t,FALSE);
2021 DirSDict::Iterator sdi(*Doxygen::directories);
2022 for (sdi.toFirst();(dir=sdi.current());++sdi)
2024 msg("Generate XML output for dir %s\n",dir->name().data());
2025 generateXMLForDir(dir,t);
2029 PageSDict::Iterator pdi(*Doxygen::exampleSDict);
2031 for (pdi.toFirst();(pd=pdi.current());++pdi)
2033 msg("Generating XML output for example %s\n",pd->name().data());
2034 generateXMLForPage(pd,t,TRUE);
2037 if (Doxygen::mainPage)
2039 msg("Generating XML output for the main page\n");
2040 generateXMLForPage(Doxygen::mainPage,t,FALSE);
2043 //t << " </compoundlist>" << endl;
2044 t << "</doxygenindex>" << endl;
2046 writeCombineScript();