2222e46428d58ecdb040e31af903a2a12e303538
[platform/upstream/doxygen.git] / src / xmlgen.cpp
1 /******************************************************************************
2  *
3  * Copyright (C) 1997-2015 by Dimitri van Heesch.
4  *
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.
10  *
11  * Documents produced by Doxygen are derivative works derived from the
12  * input used in their production; they are not affected by this license.
13  *
14  */
15
16 #include <stdlib.h>
17
18 #include <qdir.h>
19 #include <qfile.h>
20 #include <qtextstream.h>
21 #include <qintdict.h>
22
23 #include "xmlgen.h"
24 #include "doxygen.h"
25 #include "message.h"
26 #include "config.h"
27 #include "classlist.h"
28 #include "util.h"
29 #include "defargs.h"
30 #include "outputgen.h"
31 #include "dot.h"
32 #include "pagedef.h"
33 #include "filename.h"
34 #include "version.h"
35 #include "xmldocvisitor.h"
36 #include "docparser.h"
37 #include "language.h"
38 #include "parserintf.h"
39 #include "arguments.h"
40 #include "memberlist.h"
41 #include "groupdef.h"
42 #include "memberdef.h"
43 #include "namespacedef.h"
44 #include "membername.h"
45 #include "membergroup.h"
46 #include "dirdef.h"
47 #include "section.h"
48 #include "htmlentity.h"
49 #include "resourcemgr.h"
50
51 // no debug info
52 #define XML_DB(x) do {} while(0)
53 // debug to stdout
54 //#define XML_DB(x) printf x
55 // debug inside output
56 //#define XML_DB(x) QCString __t;__t.sprintf x;m_t << __t
57
58 //------------------
59
60 /** Helper class mapping MemberList::ListType to a string representing */
61 class XmlSectionMapper : public QIntDict<char>
62 {
63   public:
64     XmlSectionMapper() : QIntDict<char>(47)
65     {
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_decEnumMembers,"enum");
101       insert(MemberListType_decFuncMembers,"func");
102       insert(MemberListType_decVarMembers,"var");
103     }
104 };
105
106 static XmlSectionMapper g_xmlSectionMapper;
107
108
109 inline void writeXMLString(FTextStream &t,const char *s)
110 {
111   t << convertToXML(s);
112 }
113
114 inline void writeXMLCodeString(FTextStream &t,const char *s, int &col)
115 {
116   char c;
117   while ((c=*s++))
118   {
119     switch(c)
120     {
121       case '\t':
122       {
123         static int tabSize = Config_getInt(TAB_SIZE);
124         int spacesToNextTabStop = tabSize - (col%tabSize);
125         col+=spacesToNextTabStop;
126         while (spacesToNextTabStop--) t << "<sp/>";
127         break;
128         }
129       case ' ':  t << "<sp/>"; col++;  break;
130       case '<':  t << "&lt;"; col++;   break;
131       case '>':  t << "&gt;"; col++;   break;
132       case '&':  t << "&amp;"; col++;  break;
133       case '\'': t << "&apos;"; col++; break;
134       case '"':  t << "&quot;"; col++; break;
135       case  1: case  2: case  3: case  4: case  5: case  6: case  7: case  8:
136       case 11: case 12: case 13: case 14: case 15: case 16: case 17: case 18:
137       case 19: case 20: case 21: case 22: case 23: case 24: case 25: case 26:
138       case 27: case 28: case 29: case 30: case 31:
139         // encode invalid XML characters (see http://www.w3.org/TR/2000/REC-xml-20001006#NT-Char)
140         t << "<sp value=\"" << int(c) << "\"/>";
141         break;
142       default:   s=writeUtf8Char(t,s-1); col++; break;
143     }
144   }
145 }
146
147
148 static void writeXMLHeader(FTextStream &t)
149 {
150   t << "<?xml version='1.0' encoding='UTF-8' standalone='no'?>" << endl;;
151   t << "<doxygen xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" ";
152   t << "xsi:noNamespaceSchemaLocation=\"compound.xsd\" ";
153   t << "version=\"" << versionString << "\">" << endl;
154 }
155
156 static void writeCombineScript()
157 {
158   QCString outputDirectory = Config_getString(XML_OUTPUT);
159   QCString fileName=outputDirectory+"/combine.xslt";
160   QFile f(fileName);
161   if (!f.open(IO_WriteOnly))
162   {
163     err("Cannot open file %s for writing!\n",fileName.data());
164     return;
165   }
166   FTextStream t(&f);
167   //t.setEncoding(FTextStream::UnicodeUTF8);
168
169   t <<
170   "<!-- XSLT script to combine the generated output into a single file. \n"
171   "     If you have xsltproc you could use:\n"
172   "     xsltproc combine.xslt index.xml >all.xml\n"
173   "-->\n"
174   "<xsl:stylesheet xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" version=\"1.0\">\n"
175   "  <xsl:output method=\"xml\" version=\"1.0\" indent=\"no\" standalone=\"yes\" />\n"
176   "  <xsl:template match=\"/\">\n"
177   "    <doxygen version=\"{doxygenindex/@version}\">\n"
178   "      <!-- Load all doxgen generated xml files -->\n"
179   "      <xsl:for-each select=\"doxygenindex/compound\">\n"
180   "        <xsl:copy-of select=\"document( concat( @refid, '.xml' ) )/doxygen/*\" />\n"
181   "      </xsl:for-each>\n"
182   "    </doxygen>\n"
183   "  </xsl:template>\n"
184   "</xsl:stylesheet>\n";
185
186 }
187
188 void writeXMLLink(FTextStream &t,const char *extRef,const char *compoundId,
189                   const char *anchorId,const char *text,const char *tooltip)
190 {
191   t << "<ref refid=\"" << compoundId;
192   if (anchorId) t << "_1" << anchorId;
193   t << "\" kindref=\"";
194   if (anchorId) t << "member"; else t << "compound"; 
195   t << "\"";
196   if (extRef) t << " external=\"" << extRef << "\"";
197   if (tooltip) t << " tooltip=\"" << convertToXML(tooltip) << "\"";
198   t << ">";
199   writeXMLString(t,text);
200   t << "</ref>";
201 }
202
203 /** Implements TextGeneratorIntf for an XML stream. */
204 class TextGeneratorXMLImpl : public TextGeneratorIntf
205 {
206   public:
207     TextGeneratorXMLImpl(FTextStream &t): m_t(t) {}
208     void writeString(const char *s,bool /*keepSpaces*/) const
209     {
210       writeXMLString(m_t,s); 
211     }
212     void writeBreak(int) const {}
213     void writeLink(const char *extRef,const char *file,
214                    const char *anchor,const char *text
215                   ) const
216     {
217       writeXMLLink(m_t,extRef,file,anchor,text,0);
218     }
219   private:
220     FTextStream &m_t;
221 };
222
223
224 /** Generator for producing XML formatted source code. */
225 class XMLCodeGenerator : public CodeOutputInterface
226 {
227   public:
228
229     XMLCodeGenerator(FTextStream &t) : m_t(t), m_lineNumber(-1), m_isMemberRef(FALSE), m_col(0),
230       m_insideCodeLine(FALSE), m_normalHLNeedStartTag(TRUE), m_insideSpecialHL(FALSE) {}
231     virtual ~XMLCodeGenerator() { }
232
233     void codify(const char *text)
234     {
235       XML_DB(("(codify \"%s\")\n",text));
236       if (m_insideCodeLine && !m_insideSpecialHL && m_normalHLNeedStartTag)
237       {
238         m_t << "<highlight class=\"normal\">";
239         m_normalHLNeedStartTag=FALSE;
240       }
241       writeXMLCodeString(m_t,text,m_col);
242     }
243     void writeCodeLink(const char *ref,const char *file,
244                        const char *anchor,const char *name,
245                        const char *tooltip)
246     {
247       XML_DB(("(writeCodeLink)\n"));
248       if (m_insideCodeLine && !m_insideSpecialHL && m_normalHLNeedStartTag)
249       {
250         m_t << "<highlight class=\"normal\">";
251         m_normalHLNeedStartTag=FALSE;
252       }
253       writeXMLLink(m_t,ref,file,anchor,name,tooltip);
254       m_col+=qstrlen(name);
255     }
256     void writeTooltip(const char *, const DocLinkInfo &, const char *,
257                       const char *, const SourceLinkInfo &, const SourceLinkInfo &
258                      )
259     {
260       XML_DB(("(writeToolTip)\n"));
261     }
262     void startCodeLine(bool)
263     {
264       XML_DB(("(startCodeLine)\n"));
265       m_t << "<codeline";
266       if (m_lineNumber!=-1)
267       {
268         m_t << " lineno=\"" << m_lineNumber << "\"";
269         if (!m_refId.isEmpty())
270         {
271           m_t << " refid=\"" << m_refId << "\"";
272           if (m_isMemberRef)
273           {
274             m_t << " refkind=\"member\"";
275           }
276           else
277           {
278             m_t << " refkind=\"compound\"";
279           }
280         }
281         if (!m_external.isEmpty())
282         {
283           m_t << " external=\"" << m_external << "\"";
284         }
285       }
286       m_t << ">";
287       m_insideCodeLine=TRUE;
288       m_col=0;
289     }
290     void endCodeLine()
291     {
292       XML_DB(("(endCodeLine)\n"));
293       if (!m_insideSpecialHL && !m_normalHLNeedStartTag)
294       {
295         m_t << "</highlight>";
296         m_normalHLNeedStartTag=TRUE;
297       }
298       m_t << "</codeline>" << endl; // non DocBook
299       m_lineNumber = -1;
300       m_refId.resize(0);
301       m_external.resize(0);
302       m_insideCodeLine=FALSE;
303     }
304     void startFontClass(const char *colorClass)
305     {
306       XML_DB(("(startFontClass)\n"));
307       if (m_insideCodeLine && !m_insideSpecialHL && !m_normalHLNeedStartTag)
308       {
309         m_t << "</highlight>";
310         m_normalHLNeedStartTag=TRUE;
311       }
312       m_t << "<highlight class=\"" << colorClass << "\">"; // non DocBook
313       m_insideSpecialHL=TRUE;
314     }
315     void endFontClass()
316     {
317       XML_DB(("(endFontClass)\n"));
318       m_t << "</highlight>"; // non DocBook
319       m_insideSpecialHL=FALSE;
320     }
321     void writeCodeAnchor(const char *)
322     {
323       XML_DB(("(writeCodeAnchor)\n"));
324     }
325     void writeLineNumber(const char *extRef,const char *compId,
326                          const char *anchorId,int l)
327     {
328       XML_DB(("(writeLineNumber)\n"));
329       // we remember the information provided here to use it
330       // at the <codeline> start tag.
331       m_lineNumber = l;
332       if (compId)
333       {
334         m_refId=compId;
335         if (anchorId) m_refId+=(QCString)"_1"+anchorId;
336         m_isMemberRef = anchorId!=0;
337         if (extRef) m_external=extRef;
338       }
339     }
340     void setCurrentDoc(Definition *,const char *,bool)
341     {
342     }
343     void addWord(const char *,bool)
344     {
345     }
346
347     void finish()
348     {
349       if (m_insideCodeLine) endCodeLine();
350     }
351
352   private:
353     FTextStream &m_t;
354     QCString m_refId;
355     QCString m_external;
356     int m_lineNumber;
357     bool m_isMemberRef;
358     int m_col;
359
360     bool m_insideCodeLine;
361     bool m_normalHLNeedStartTag;
362     bool m_insideSpecialHL;
363 };
364
365
366 static void writeTemplateArgumentList(ArgumentList *al,
367                                       FTextStream &t,
368                                       Definition *scope,
369                                       FileDef *fileScope,
370                                       int indent)
371 {
372   QCString indentStr;
373   indentStr.fill(' ',indent);
374   if (al)
375   {
376     t << indentStr << "<templateparamlist>" << endl;
377     ArgumentListIterator ali(*al);
378     Argument *a;
379     for (ali.toFirst();(a=ali.current());++ali)
380     {
381       t << indentStr << "  <param>" << endl;
382       if (!a->type.isEmpty())
383       {
384         t << indentStr <<  "    <type>";
385         linkifyText(TextGeneratorXMLImpl(t),scope,fileScope,0,a->type);
386         t << "</type>" << endl;
387       }
388       if (!a->name.isEmpty())
389       {
390         t << indentStr <<  "    <declname>" << a->name << "</declname>" << endl;
391         t << indentStr <<  "    <defname>" << a->name << "</defname>" << endl;
392       }
393       if (!a->defval.isEmpty())
394       {
395         t << indentStr << "    <defval>";
396         linkifyText(TextGeneratorXMLImpl(t),scope,fileScope,0,a->defval);
397         t << "</defval>" << endl;
398       }
399       if (!a->typeConstraint.isEmpty())
400       {
401         t << indentStr << "    <typeconstraint>";
402         linkifyText(TextGeneratorXMLImpl(t),scope,fileScope,0,a->typeConstraint);
403         t << "</typeconstraint>" << endl;
404       }
405       t << indentStr << "  </param>" << endl;
406     }
407     t << indentStr << "</templateparamlist>" << endl;
408   }
409 }
410
411 static void writeMemberTemplateLists(MemberDef *md,FTextStream &t)
412 {
413   ArgumentList *templMd = md->templateArguments();
414   if (templMd) // function template prefix
415   {
416     writeTemplateArgumentList(templMd,t,md->getClassDef(),md->getFileDef(),8);
417   }
418 }
419
420 static void writeTemplateList(ClassDef *cd,FTextStream &t)
421 {
422   writeTemplateArgumentList(cd->templateArguments(),t,cd,0,4);
423 }
424
425 static void writeXMLDocBlock(FTextStream &t,
426                       const QCString &fileName,
427                       int lineNr,
428                       Definition *scope,
429                       MemberDef * md,
430                       const QCString &text)
431 {
432   QCString stext = text.stripWhiteSpace();
433   if (stext.isEmpty()) return;
434   // convert the documentation string into an abstract syntax tree
435   DocNode *root = validatingParseDoc(fileName,lineNr,scope,md,text,FALSE,FALSE);
436   // create a code generator
437   XMLCodeGenerator *xmlCodeGen = new XMLCodeGenerator(t);
438   // create a parse tree visitor for XML
439   XmlDocVisitor *visitor = new XmlDocVisitor(t,*xmlCodeGen);
440   // visit all nodes
441   root->accept(visitor);
442   // clean up
443   delete visitor;
444   delete xmlCodeGen;
445   delete root;
446   
447 }
448
449 void writeXMLCodeBlock(FTextStream &t,FileDef *fd)
450 {
451   ParserInterface *pIntf=Doxygen::parserManager->getParser(fd->getDefFileExtension());
452   SrcLangExt langExt = getLanguageFromFileName(fd->getDefFileExtension());
453   pIntf->resetCodeParserState();
454   XMLCodeGenerator *xmlGen = new XMLCodeGenerator(t);
455   pIntf->parseCode(*xmlGen,  // codeOutIntf
456                 0,           // scopeName
457                 fileToString(fd->absFilePath(),Config_getBool(FILTER_SOURCE_FILES)),
458                 langExt,     // lang
459                 FALSE,       // isExampleBlock
460                 0,           // exampleName
461                 fd,          // fileDef
462                 -1,          // startLine
463                 -1,          // endLine
464                 FALSE,       // inlineFragement
465                 0,           // memberDef
466                 TRUE         // showLineNumbers
467                 );
468   xmlGen->finish();
469   delete xmlGen;
470 }
471
472 static void writeMemberReference(FTextStream &t,Definition *def,MemberDef *rmd,const char *tagName)
473 {
474   QCString scope = rmd->getScopeString();
475   QCString name = rmd->name();
476   if (!scope.isEmpty() && scope!=def->name())
477   {
478     name.prepend(scope+getLanguageSpecificSeparator(rmd->getLanguage()));
479   }
480   t << "        <" << tagName << " refid=\"";
481   t << rmd->getOutputFileBase() << "_1" << rmd->anchor() << "\"";
482   if (rmd->getStartBodyLine()!=-1 && rmd->getBodyDef()) 
483   {
484     t << " compoundref=\"" << rmd->getBodyDef()->getOutputFileBase() << "\"";
485     t << " startline=\"" << rmd->getStartBodyLine() << "\"";
486     if (rmd->getEndBodyLine()!=-1)
487     {
488       t << " endline=\"" << rmd->getEndBodyLine() << "\"";
489     }
490   }
491   t << ">" << convertToXML(name) << "</" << tagName << ">" << endl;
492   
493 }
494
495 static void stripQualifiers(QCString &typeStr)
496 {
497   bool done=FALSE;
498   while (!done)
499   {
500     if (typeStr.stripPrefix("static "));
501     else if (typeStr.stripPrefix("virtual "));
502     else if (typeStr.stripPrefix("volatile "));
503     else if (typeStr=="virtual") typeStr="";
504     else done=TRUE;
505   }
506 }
507
508 static QCString classOutputFileBase(ClassDef *cd)
509 {
510   //static bool inlineGroupedClasses = Config_getBool(INLINE_GROUPED_CLASSES);
511   //if (inlineGroupedClasses && cd->partOfGroups()!=0) 
512   return cd->getOutputFileBase();
513   //else 
514   //  return cd->getOutputFileBase();
515 }
516
517 static QCString memberOutputFileBase(MemberDef *md)
518 {
519   //static bool inlineGroupedClasses = Config_getBool(INLINE_GROUPED_CLASSES);
520   //if (inlineGroupedClasses && md->getClassDef() && md->getClassDef()->partOfGroups()!=0) 
521   //  return md->getClassDef()->getXmlOutputFileBase();
522   //else 
523   //  return md->getOutputFileBase();
524   return md->getOutputFileBase();
525 }
526
527
528 static void generateXMLForMember(MemberDef *md,FTextStream &ti,FTextStream &t,Definition *def)
529 {
530
531   // + declaration/definition arg lists
532   // + reimplements
533   // + reimplementedBy
534   // + exceptions
535   // + const/volatile specifiers
536   // - examples
537   // + source definition
538   // + source references
539   // + source referenced by
540   // - body code 
541   // + template arguments 
542   //     (templateArguments(), definitionTemplateParameterLists())
543   // - call graph
544   
545   // enum values are written as part of the enum
546   if (md->memberType()==MemberType_EnumValue) return;
547   if (md->isHidden()) return;
548   //if (md->name().at(0)=='@') return; // anonymous member
549
550   // group members are only visible in their group
551   //if (def->definitionType()!=Definition::TypeGroup && md->getGroupDef()) return;
552
553   QCString memType;
554   bool isFunc=FALSE;
555   switch (md->memberType())
556   {
557     case MemberType_Define:      memType="define";    break;
558     case MemberType_Function:    memType="function";  isFunc=TRUE; break;
559     case MemberType_Variable:    memType="variable";  break;
560     case MemberType_Typedef:     memType="typedef";   break;
561     case MemberType_Enumeration: memType="enum";      break;
562     case MemberType_EnumValue:   ASSERT(0);           break;
563     case MemberType_Signal:      memType="signal";    isFunc=TRUE; break;
564     case MemberType_Slot:        memType="slot";      isFunc=TRUE; break;
565     case MemberType_Friend:      memType="friend";    isFunc=TRUE; break;
566     case MemberType_DCOP:        memType="dcop";      isFunc=TRUE; break;
567     case MemberType_Property:    memType="property";  break;
568     case MemberType_Event:       memType="event";     break;
569     case MemberType_Interface:   memType="interface"; break;
570     case MemberType_Service:     memType="service";   break;
571   }
572
573   ti << "    <member refid=\"" << memberOutputFileBase(md) 
574      << "_1" << md->anchor() << "\" kind=\"" << memType << "\"><name>" 
575      << convertToXML(md->name()) << "</name></member>" << endl;
576   
577   QCString scopeName;
578   if (md->getClassDef()) 
579     scopeName=md->getClassDef()->name();
580   else if (md->getNamespaceDef()) 
581     scopeName=md->getNamespaceDef()->name();
582     
583   t << "      <memberdef kind=\"";
584   //enum { define_t,variable_t,typedef_t,enum_t,function_t } xmlType = function_t;
585   t << memType << "\" id=\"";
586   if (md->getGroupDef() && def->definitionType()==Definition::TypeGroup)
587   {
588     t << md->getGroupDef()->getOutputFileBase();
589   }
590   else
591   {
592     t << memberOutputFileBase(md);
593   }
594   t << "_1"      // encoded `:' character (see util.cpp:convertNameToFile)
595     << md->anchor();
596   t << "\" prot=\"";
597   switch(md->protection())
598   {
599     case Public:    t << "public";     break;
600     case Protected: t << "protected";  break;
601     case Private:   t << "private";    break;
602     case Package:   t << "package";    break;
603   }
604   t << "\"";
605
606   t << " static=\"";
607   if (md->isStatic()) t << "yes"; else t << "no";
608   t << "\"";
609
610   if (isFunc)
611   {
612     ArgumentList *al = md->argumentList();
613     t << " const=\"";
614     if (al!=0 && al->constSpecifier)    t << "yes"; else t << "no"; 
615     t << "\"";
616
617     t << " explicit=\"";
618     if (md->isExplicit()) t << "yes"; else t << "no";
619     t << "\"";
620
621     t << " inline=\"";
622     if (md->isInline()) t << "yes"; else t << "no";
623     t << "\"";
624
625     if (al!=0 && al->refQualifier!=RefQualifierNone)
626     {
627       t << " refqual=\"";
628       if (al->refQualifier==RefQualifierLValue) t << "lvalue"; else t << "rvalue";
629       t << "\"";
630     }
631
632     if (md->isFinal())
633     {
634       t << " final=\"yes\"";
635     }
636
637     if (md->isSealed())
638     {
639       t << " sealed=\"yes\"";
640     }
641
642     if (md->isNew())
643     {
644       t << " new=\"yes\"";
645     }
646
647     if (md->isOptional())
648     {
649       t << " optional=\"yes\"";
650     }
651
652     if (md->isRequired())
653     {
654       t << " required=\"yes\"";
655     }
656
657     if (al && al->volatileSpecifier)
658     {
659       t << " volatile=\"yes\"";
660     }
661
662     t << " virt=\"";
663     switch (md->virtualness())
664     {
665       case Normal:  t << "non-virtual";  break;
666       case Virtual: t << "virtual";      break;
667       case Pure:    t << "pure-virtual"; break;
668       default: ASSERT(0);
669     }
670     t << "\"";
671   }
672
673   if (md->memberType() == MemberType_Enumeration)
674   {
675     t << " strong=\"";
676     if (md->isStrong()) t << "yes"; else t << "no";
677     t << "\"";
678   }
679
680   if (md->memberType() == MemberType_Variable)
681   {
682     //ArgumentList *al = md->argumentList();
683     //t << " volatile=\"";
684     //if (al && al->volatileSpecifier) t << "yes"; else t << "no"; 
685
686     t << " mutable=\"";
687     if (md->isMutable()) t << "yes"; else t << "no";
688     t << "\"";
689     
690     if (md->isInitonly())
691     {
692       t << " initonly=\"yes\"";
693     }
694     if (md->isAttribute())
695     {
696       t << " attribute=\"yes\"";
697     }
698     if (md->isUNOProperty())
699     {
700       t << " property=\"yes\"";
701     }
702     if (md->isReadonly())
703     {
704       t << " readonly=\"yes\"";
705     }
706     if (md->isBound())
707     {
708       t << " bound=\"yes\"";
709     }
710     if (md->isRemovable())
711     {
712       t << " removable=\"yes\"";
713     }
714     if (md->isConstrained())
715     {
716       t << " constrained=\"yes\"";
717     }
718     if (md->isTransient())
719     {
720       t << " transient=\"yes\"";
721     }
722     if (md->isMaybeVoid())
723     {
724       t << " maybevoid=\"yes\"";
725     }
726     if (md->isMaybeDefault())
727     {
728       t << " maybedefault=\"yes\"";
729     }
730     if (md->isMaybeAmbiguous())
731     {
732       t << " maybeambiguous=\"yes\"";
733     }
734   }
735   else if (md->memberType() == MemberType_Property)
736   {
737     t << " readable=\"";
738     if (md->isReadable()) t << "yes"; else t << "no";
739     t << "\"";
740
741     t << " writable=\"";
742     if (md->isWritable()) t << "yes"; else t << "no";
743     t << "\"";
744
745     t << " gettable=\"";
746     if (md->isGettable()) t << "yes"; else t << "no";
747     t << "\"";
748
749     t << " privategettable=\"";
750     if (md->isPrivateGettable()) t << "yes"; else t << "no";
751     t << "\"";
752
753     t << " protectedgettable=\"";
754     if (md->isProtectedGettable()) t << "yes"; else t << "no";
755     t << "\"";
756
757     t << " settable=\"";
758     if (md->isSettable()) t << "yes"; else t << "no";
759     t << "\"";
760
761     t << " privatesettable=\"";
762     if (md->isPrivateSettable()) t << "yes"; else t << "no";
763     t << "\"";
764
765     t << " protectedsettable=\"";
766     if (md->isProtectedSettable()) t << "yes"; else t << "no";
767     t << "\"";
768
769     if (md->isAssign() || md->isCopy() || md->isRetain() || md->isStrong() || md->isWeak())
770     {
771       t << " accessor=\"";
772       if (md->isAssign())      t << "assign";
773       else if (md->isCopy())   t << "copy";
774       else if (md->isRetain()) t << "retain";
775       else if (md->isStrong()) t << "strong";
776       else if (md->isWeak())   t << "weak";
777       t << "\"";
778     }
779   }
780   else if (md->memberType() == MemberType_Event)
781   {
782     t << " add=\"";
783     if (md->isAddable()) t << "yes"; else t << "no";
784     t << "\"";
785
786     t << " remove=\"";
787     if (md->isRemovable()) t << "yes"; else t << "no";
788     t << "\"";
789
790     t << " raise=\"";
791     if (md->isRaisable()) t << "yes"; else t << "no";
792     t << "\"";
793   }
794
795   t << ">" << endl;
796
797   if (md->memberType()!=MemberType_Define &&
798       md->memberType()!=MemberType_Enumeration
799      )
800   {
801     writeMemberTemplateLists(md,t);
802     QCString typeStr = md->typeString(); //replaceAnonymousScopes(md->typeString());
803     stripQualifiers(typeStr);
804     t << "        <type>";
805     linkifyText(TextGeneratorXMLImpl(t),def,md->getBodyDef(),md,typeStr);
806     t << "</type>" << endl;
807     t << "        <definition>" << convertToXML(md->definition()) << "</definition>" << endl;
808     t << "        <argsstring>" << convertToXML(md->argsString()) << "</argsstring>" << endl;
809   }
810
811   if (md->memberType() == MemberType_Enumeration)
812   {
813     t << "        <type>";
814     linkifyText(TextGeneratorXMLImpl(t),def,md->getBodyDef(),md,md->enumBaseType());
815     t << "</type>" << endl;
816   }
817
818   t << "        <name>" << convertToXML(md->name()) << "</name>" << endl;
819   
820   if (md->memberType() == MemberType_Property)
821   {
822     if (md->isReadable())
823       t << "        <read>" << convertToXML(md->getReadAccessor()) << "</read>" << endl;
824     if (md->isWritable())
825       t << "        <write>" << convertToXML(md->getWriteAccessor()) << "</write>" << endl;
826   }
827
828   if (md->memberType()==MemberType_Variable && md->bitfieldString())
829   {
830     QCString bitfield = md->bitfieldString();
831     if (bitfield.at(0)==':') bitfield=bitfield.mid(1);
832     t << "        <bitfield>" << convertToXML(bitfield) << "</bitfield>" << endl;
833   }
834   
835   MemberDef *rmd = md->reimplements();
836   if (rmd)
837   {
838     t << "        <reimplements refid=\"" 
839       << memberOutputFileBase(rmd) << "_1" << rmd->anchor() << "\">"
840       << convertToXML(rmd->name()) << "</reimplements>" << endl;
841   }
842   MemberList *rbml = md->reimplementedBy();
843   if (rbml)
844   {
845     MemberListIterator mli(*rbml);
846     for (mli.toFirst();(rmd=mli.current());++mli)
847     {
848       t << "        <reimplementedby refid=\"" 
849         << memberOutputFileBase(rmd) << "_1" << rmd->anchor() << "\">"
850         << convertToXML(rmd->name()) << "</reimplementedby>" << endl;
851     }
852   }
853
854   if (isFunc) //function
855   {
856     ArgumentList *declAl = md->declArgumentList();
857     ArgumentList *defAl = md->argumentList();
858     if (declAl && defAl && declAl->count()>0)
859     {
860       ArgumentListIterator declAli(*declAl);
861       ArgumentListIterator defAli(*defAl);
862       Argument *a;
863       for (declAli.toFirst();(a=declAli.current());++declAli)
864       {
865         Argument *defArg = defAli.current();
866         t << "        <param>" << endl;
867         if (!a->attrib.isEmpty())
868         {
869           t << "          <attributes>";
870           writeXMLString(t,a->attrib);
871           t << "</attributes>" << endl;
872         }
873         if (!a->type.isEmpty())
874         {
875           t << "          <type>";
876           linkifyText(TextGeneratorXMLImpl(t),def,md->getBodyDef(),md,a->type);
877           t << "</type>" << endl;
878         }
879         if (!a->name.isEmpty())
880         {
881           t << "          <declname>";
882           writeXMLString(t,a->name); 
883           t << "</declname>" << endl;
884         }
885         if (defArg && !defArg->name.isEmpty() && defArg->name!=a->name)
886         {
887           t << "          <defname>";
888           writeXMLString(t,defArg->name);
889           t << "</defname>" << endl;
890         }
891         if (!a->array.isEmpty())
892         {
893           t << "          <array>"; 
894           writeXMLString(t,a->array); 
895           t << "</array>" << endl;
896         }
897         if (!a->defval.isEmpty())
898         {
899           t << "          <defval>";
900           linkifyText(TextGeneratorXMLImpl(t),def,md->getBodyDef(),md,a->defval);
901           t << "</defval>" << endl;
902         }
903         if (defArg && defArg->hasDocumentation())
904         {
905           t << "          <briefdescription>";
906           writeXMLDocBlock(t,md->getDefFileName(),md->getDefLine(),
907                            md->getOuterScope(),md,defArg->docs);
908           t << "</briefdescription>" << endl;
909         }
910         t << "        </param>" << endl;
911         if (defArg) ++defAli;
912       }
913     }
914   }
915   else if (md->memberType()==MemberType_Define && 
916           md->argsString()) // define
917   {
918     if (md->argumentList()->count()==0) // special case for "foo()" to
919                                         // disguish it from "foo".
920     {
921       t << "        <param></param>" << endl;
922     }
923     else
924     {
925       ArgumentListIterator ali(*md->argumentList());
926       Argument *a;
927       for (ali.toFirst();(a=ali.current());++ali)
928       {
929         t << "        <param><defname>" << a->type << "</defname></param>" << endl;
930       }
931     }
932   }
933
934   if (md->hasOneLineInitializer() || md->hasMultiLineInitializer())
935   {
936     t << "        <initializer>";
937     linkifyText(TextGeneratorXMLImpl(t),def,md->getBodyDef(),md,md->initializer());
938     t << "</initializer>" << endl;
939   }
940
941   if (md->excpString())
942   {
943     t << "        <exceptions>";
944     linkifyText(TextGeneratorXMLImpl(t),def,md->getBodyDef(),md,md->excpString());
945     t << "</exceptions>" << endl;
946   }
947   
948   if (md->memberType()==MemberType_Enumeration) // enum
949   {
950     MemberList *enumFields = md->enumFieldList();
951     if (enumFields)
952     {
953       MemberListIterator emli(*enumFields);
954       MemberDef *emd;
955       for (emli.toFirst();(emd=emli.current());++emli)
956       {
957         ti << "    <member refid=\"" << memberOutputFileBase(emd) 
958            << "_1" << emd->anchor() << "\" kind=\"enumvalue\"><name>" 
959            << convertToXML(emd->name()) << "</name></member>" << endl;
960
961         t << "        <enumvalue id=\"" << memberOutputFileBase(emd) << "_1" 
962           << emd->anchor() << "\" prot=\"";
963         switch (emd->protection())
964         {
965           case Public:    t << "public";    break;
966           case Protected: t << "protected"; break;
967           case Private:   t << "private";   break;
968           case Package:   t << "package";   break;
969         }
970         t << "\">" << endl;
971         t << "          <name>";
972         writeXMLString(t,emd->name());
973         t << "</name>" << endl;
974         if (!emd->initializer().isEmpty())
975         {
976           t << "          <initializer>";
977           writeXMLString(t,emd->initializer());
978           t << "</initializer>" << endl;
979         }
980         t << "          <briefdescription>" << endl;
981         writeXMLDocBlock(t,emd->briefFile(),emd->briefLine(),emd->getOuterScope(),emd,emd->briefDescription());
982         t << "          </briefdescription>" << endl;
983         t << "          <detaileddescription>" << endl;
984         writeXMLDocBlock(t,emd->docFile(),emd->docLine(),emd->getOuterScope(),emd,emd->documentation());
985         t << "          </detaileddescription>" << endl;
986         t << "        </enumvalue>" << endl;
987       }
988     }
989   }
990   t << "        <briefdescription>" << endl;
991   writeXMLDocBlock(t,md->briefFile(),md->briefLine(),md->getOuterScope(),md,md->briefDescription());
992   t << "        </briefdescription>" << endl;
993   t << "        <detaileddescription>" << endl;
994   writeXMLDocBlock(t,md->docFile(),md->docLine(),md->getOuterScope(),md,md->documentation());
995   t << "        </detaileddescription>" << endl;
996   t << "        <inbodydescription>" << endl;
997   writeXMLDocBlock(t,md->docFile(),md->inbodyLine(),md->getOuterScope(),md,md->inbodyDocumentation());
998   t << "        </inbodydescription>" << endl;
999   if (md->getDefLine()!=-1)
1000   {
1001     t << "        <location file=\"" 
1002       << stripFromPath(md->getDefFileName()) << "\" line=\"" 
1003       << md->getDefLine() << "\"" << " column=\"" 
1004       << md->getDefColumn() << "\"" ;
1005     if (md->getStartBodyLine()!=-1)
1006     {
1007       FileDef *bodyDef = md->getBodyDef();
1008       if (bodyDef)
1009       {
1010         t << " bodyfile=\"" << stripFromPath(bodyDef->absFilePath()) << "\"";
1011       }
1012       t << " bodystart=\"" << md->getStartBodyLine() << "\" bodyend=\"" 
1013         << md->getEndBodyLine() << "\"";
1014     }
1015     t << "/>" << endl;
1016   }
1017
1018   //printf("md->getReferencesMembers()=%p\n",md->getReferencesMembers());
1019   MemberSDict *mdict = md->getReferencesMembers();
1020   if (mdict)
1021   {
1022     MemberSDict::Iterator mdi(*mdict);
1023     MemberDef *rmd;
1024     for (mdi.toFirst();(rmd=mdi.current());++mdi)
1025     {
1026       writeMemberReference(t,def,rmd,"references");
1027     }
1028   }
1029   mdict = md->getReferencedByMembers();
1030   if (mdict)
1031   {
1032     MemberSDict::Iterator mdi(*mdict);
1033     MemberDef *rmd;
1034     for (mdi.toFirst();(rmd=mdi.current());++mdi)
1035     {
1036       writeMemberReference(t,def,rmd,"referencedby");
1037     }
1038   }
1039   
1040   t << "      </memberdef>" << endl;
1041 }
1042
1043 static void generateXMLSection(Definition *d,FTextStream &ti,FTextStream &t,
1044                       MemberList *ml,const char *kind,const char *header=0,
1045                       const char *documentation=0)
1046 {
1047   if (ml==0) return;
1048   MemberListIterator mli(*ml);
1049   MemberDef *md;
1050   int count=0;
1051   for (mli.toFirst();(md=mli.current());++mli)
1052   {
1053     // namespace members are also inserted in the file scope, but 
1054     // to prevent this duplication in the XML output, we filter those here.
1055     if (d->definitionType()!=Definition::TypeFile || md->getNamespaceDef()==0)
1056     {
1057       count++;
1058     }
1059   }
1060   if (count==0) return; // empty list
1061
1062   t << "      <sectiondef kind=\"" << kind << "\">" << endl;
1063   if (header)
1064   {
1065     t << "      <header>" << convertToXML(header) << "</header>" << endl;
1066   }
1067   if (documentation)
1068   {
1069     t << "      <description>";
1070     writeXMLDocBlock(t,d->docFile(),d->docLine(),d,0,documentation);
1071     t << "</description>" << endl;
1072   }
1073   for (mli.toFirst();(md=mli.current());++mli)
1074   {
1075     // namespace members are also inserted in the file scope, but 
1076     // to prevent this duplication in the XML output, we filter those here.
1077     if (d->definitionType()!=Definition::TypeFile || md->getNamespaceDef()==0)
1078     {
1079       generateXMLForMember(md,ti,t,d);
1080     }
1081   }
1082   t << "      </sectiondef>" << endl;
1083 }
1084
1085 static void writeListOfAllMembers(ClassDef *cd,FTextStream &t)
1086 {
1087   t << "    <listofallmembers>" << endl;
1088   if (cd->memberNameInfoSDict())
1089   {
1090     MemberNameInfoSDict::Iterator mnii(*cd->memberNameInfoSDict());
1091     MemberNameInfo *mni;
1092     for (mnii.toFirst();(mni=mnii.current());++mnii)
1093     {
1094       MemberNameInfoIterator mii(*mni);
1095       MemberInfo *mi;
1096       for (mii.toFirst();(mi=mii.current());++mii)
1097       {
1098         MemberDef *md=mi->memberDef;
1099         if (md->name().at(0)!='@') // skip anonymous members
1100         {
1101           Protection prot = mi->prot;
1102           Specifier virt=md->virtualness();
1103           t << "      <member refid=\"" << memberOutputFileBase(md) << "_1" <<
1104             md->anchor() << "\" prot=\"";
1105           switch (prot)
1106           {
1107             case Public:    t << "public";    break;
1108             case Protected: t << "protected"; break;
1109             case Private:   t << "private";   break;
1110             case Package:   t << "package";   break;
1111           }
1112           t << "\" virt=\"";
1113           switch(virt)
1114           {
1115             case Normal:  t << "non-virtual";  break;
1116             case Virtual: t << "virtual";      break;
1117             case Pure:    t << "pure-virtual"; break;
1118           }
1119           t << "\"";
1120           if (!mi->ambiguityResolutionScope.isEmpty())
1121           {
1122             t << " ambiguityscope=\"" << convertToXML(mi->ambiguityResolutionScope) << "\"";
1123           }
1124           t << "><scope>" << convertToXML(cd->name()) << "</scope><name>" << 
1125             convertToXML(md->name()) << "</name></member>" << endl;
1126         }
1127       }
1128     }
1129   }
1130   t << "    </listofallmembers>" << endl;
1131 }
1132
1133 static void writeInnerClasses(const ClassSDict *cl,FTextStream &t)
1134 {
1135   if (cl)
1136   {
1137     ClassSDict::Iterator cli(*cl);
1138     ClassDef *cd;
1139     for (cli.toFirst();(cd=cli.current());++cli)
1140     {
1141       if (!cd->isHidden() && cd->name().find('@')==-1) // skip anonymous scopes
1142       {
1143         t << "    <innerclass refid=\"" << classOutputFileBase(cd)
1144           << "\" prot=\"";
1145         switch(cd->protection())
1146         {
1147            case Public:    t << "public";     break;
1148            case Protected: t << "protected";  break;
1149            case Private:   t << "private";    break;
1150            case Package:   t << "package";    break;
1151         }
1152         t << "\">" << convertToXML(cd->name()) << "</innerclass>" << endl;
1153       }
1154     }
1155   }
1156 }
1157
1158 static void writeInnerNamespaces(const NamespaceSDict *nl,FTextStream &t)
1159 {
1160   if (nl)
1161   {
1162     NamespaceSDict::Iterator nli(*nl);
1163     NamespaceDef *nd;
1164     for (nli.toFirst();(nd=nli.current());++nli)
1165     {
1166       if (!nd->isHidden() && nd->name().find('@')==-1) // skip anonymouse scopes
1167       {
1168         t << "    <innernamespace refid=\"" << nd->getOutputFileBase()
1169           << "\">" << convertToXML(nd->name()) << "</innernamespace>" << endl;
1170       }
1171     }
1172   }
1173 }
1174
1175 static void writeInnerFiles(const FileList *fl,FTextStream &t)
1176 {
1177   if (fl)
1178   {
1179     QListIterator<FileDef> fli(*fl);
1180     FileDef *fd;
1181     for (fli.toFirst();(fd=fli.current());++fli)
1182     {
1183       t << "    <innerfile refid=\"" << fd->getOutputFileBase() 
1184         << "\">" << convertToXML(fd->name()) << "</innerfile>" << endl;
1185     }
1186   }
1187 }
1188
1189 static void writeInnerPages(const PageSDict *pl,FTextStream &t)
1190 {
1191   if (pl)
1192   {
1193     PageSDict::Iterator pli(*pl);
1194     PageDef *pd;
1195     for (pli.toFirst();(pd=pli.current());++pli)
1196     {
1197       t << "    <innerpage refid=\"" << pd->getOutputFileBase();
1198       if (pd->getGroupDef())
1199       {
1200         t << "_" << pd->name();
1201       }
1202       t << "\">" << convertToXML(pd->title()) << "</innerpage>" << endl;
1203     }
1204   }
1205 }
1206
1207 static void writeInnerGroups(const GroupList *gl,FTextStream &t)
1208 {
1209   if (gl)
1210   {
1211     GroupListIterator gli(*gl);
1212     GroupDef *sgd;
1213     for (gli.toFirst();(sgd=gli.current());++gli)
1214     {
1215       t << "    <innergroup refid=\"" << sgd->getOutputFileBase()
1216         << "\">" << convertToXML(sgd->groupTitle()) 
1217         << "</innergroup>" << endl;
1218     }
1219   }
1220 }
1221
1222 static void writeInnerDirs(const DirList *dl,FTextStream &t)
1223 {
1224   if (dl)
1225   {
1226     QListIterator<DirDef> subdirs(*dl);
1227     DirDef *subdir;
1228     for (subdirs.toFirst();(subdir=subdirs.current());++subdirs)
1229     {
1230       t << "    <innerdir refid=\"" << subdir->getOutputFileBase() 
1231         << "\">" << convertToXML(subdir->displayName()) << "</innerdir>" << endl;
1232     }
1233   }
1234 }
1235   
1236 static void generateXMLForClass(ClassDef *cd,FTextStream &ti)
1237 {
1238   // + brief description
1239   // + detailed description
1240   // + template argument list(s)
1241   // - include file
1242   // + member groups
1243   // + inheritance diagram
1244   // + list of direct super classes
1245   // + list of direct sub classes
1246   // + list of inner classes
1247   // + collaboration diagram
1248   // + list of all members
1249   // + user defined member sections
1250   // + standard member sections
1251   // + detailed member documentation
1252   // - examples using the class
1253
1254   if (cd->isReference())        return; // skip external references.
1255   if (cd->isHidden())           return; // skip hidden classes.
1256   if (cd->name().find('@')!=-1) return; // skip anonymous compounds.
1257   if (cd->templateMaster()!=0)  return; // skip generated template instances.
1258   if (cd->isArtificial())       return; // skip artificially created classes
1259
1260   msg("Generating XML output for class %s\n",cd->name().data());
1261
1262   ti << "  <compound refid=\"" << classOutputFileBase(cd) 
1263      << "\" kind=\"" << cd->compoundTypeString()
1264      << "\"><name>" << convertToXML(cd->name()) << "</name>" << endl;
1265   
1266   QCString outputDirectory = Config_getString(XML_OUTPUT);
1267   QCString fileName=outputDirectory+"/"+ classOutputFileBase(cd)+".xml";
1268   QFile f(fileName);
1269   if (!f.open(IO_WriteOnly))
1270   {
1271     err("Cannot open file %s for writing!\n",fileName.data());
1272     return;
1273   }
1274   FTextStream t(&f);
1275   //t.setEncoding(FTextStream::UnicodeUTF8);
1276
1277   writeXMLHeader(t);
1278   t << "  <compounddef id=\"" 
1279     << classOutputFileBase(cd) << "\" kind=\"" 
1280     << cd->compoundTypeString() << "\" language=\""
1281     << langToString(cd->getLanguage()) << "\" prot=\"";
1282   switch (cd->protection())
1283   {
1284     case Public:    t << "public";    break;
1285     case Protected: t << "protected"; break;
1286     case Private:   t << "private";   break;
1287     case Package:   t << "package";   break;
1288   }
1289   if (cd->isFinal()) t << "\" final=\"yes";
1290   if (cd->isSealed()) t << "\" sealed=\"yes";
1291   if (cd->isAbstract()) t << "\" abstract=\"yes";
1292   t << "\">" << endl;
1293   t << "    <compoundname>"; 
1294   writeXMLString(t,cd->name()); 
1295   t << "</compoundname>" << endl;
1296   if (cd->baseClasses())
1297   {
1298     BaseClassListIterator bcli(*cd->baseClasses());
1299     BaseClassDef *bcd;
1300     for (bcli.toFirst();(bcd=bcli.current());++bcli)
1301     {
1302       t << "    <basecompoundref ";
1303       if (bcd->classDef->isLinkable())
1304       {
1305         t << "refid=\"" << classOutputFileBase(bcd->classDef) << "\" ";
1306       }
1307       t << "prot=\"";
1308       switch (bcd->prot)
1309       {
1310         case Public:    t << "public";    break;
1311         case Protected: t << "protected"; break;
1312         case Private:   t << "private";   break;
1313         case Package: ASSERT(0); break;
1314       }
1315       t << "\" virt=\"";
1316       switch(bcd->virt)
1317       {
1318         case Normal:  t << "non-virtual";  break;
1319         case Virtual: t << "virtual";      break;
1320         case Pure:    t <<"pure-virtual"; break;
1321       }
1322       t << "\">";
1323       if (!bcd->templSpecifiers.isEmpty())
1324       {
1325         t << convertToXML(
1326               insertTemplateSpecifierInScope(
1327               bcd->classDef->name(),bcd->templSpecifiers)
1328            );
1329       }
1330       else
1331       {
1332         t << convertToXML(bcd->classDef->displayName());
1333       }
1334       t  << "</basecompoundref>" << endl;
1335     }
1336   }
1337   if (cd->subClasses())
1338   {
1339     BaseClassListIterator bcli(*cd->subClasses());
1340     BaseClassDef *bcd;
1341     for (bcli.toFirst();(bcd=bcli.current());++bcli)
1342     {
1343       t << "    <derivedcompoundref refid=\"" 
1344         << classOutputFileBase(bcd->classDef)
1345         << "\" prot=\"";
1346       switch (bcd->prot)
1347       {
1348         case Public:    t << "public";    break;
1349         case Protected: t << "protected"; break;
1350         case Private:   t << "private";   break;
1351         case Package: ASSERT(0); break;
1352       }
1353       t << "\" virt=\"";
1354       switch(bcd->virt)
1355       {
1356         case Normal:  t << "non-virtual";  break;
1357         case Virtual: t << "virtual";      break;
1358         case Pure:    t << "pure-virtual"; break;
1359       }
1360       t << "\">" << convertToXML(bcd->classDef->displayName()) 
1361         << "</derivedcompoundref>" << endl;
1362     }
1363   }
1364
1365   IncludeInfo *ii=cd->includeInfo();
1366   if (ii)
1367   {
1368     QCString nm = ii->includeName;
1369     if (nm.isEmpty() && ii->fileDef) nm = ii->fileDef->docName();
1370     if (!nm.isEmpty())
1371     {
1372       t << "    <includes";
1373       if (ii->fileDef && !ii->fileDef->isReference()) // TODO: support external references
1374       {
1375         t << " refid=\"" << ii->fileDef->getOutputFileBase() << "\"";
1376       }
1377       t << " local=\"" << (ii->local ? "yes" : "no") << "\">";
1378       t << nm;
1379       t << "</includes>" << endl;
1380     }
1381   }
1382
1383   writeInnerClasses(cd->getClassSDict(),t);
1384
1385   writeTemplateList(cd,t);
1386   if (cd->getMemberGroupSDict())
1387   {
1388     MemberGroupSDict::Iterator mgli(*cd->getMemberGroupSDict());
1389     MemberGroup *mg;
1390     for (;(mg=mgli.current());++mgli)
1391     {
1392       generateXMLSection(cd,ti,t,mg->members(),"user-defined",mg->header(),
1393           mg->documentation());
1394     }
1395   }
1396
1397   QListIterator<MemberList> mli(cd->getMemberLists());
1398   MemberList *ml;
1399   for (mli.toFirst();(ml=mli.current());++mli)
1400   {
1401     if ((ml->listType()&MemberListType_detailedLists)==0)
1402     {
1403       generateXMLSection(cd,ti,t,ml,g_xmlSectionMapper.find(ml->listType()));
1404     }
1405   }
1406
1407   t << "    <briefdescription>" << endl;
1408   writeXMLDocBlock(t,cd->briefFile(),cd->briefLine(),cd,0,cd->briefDescription());
1409   t << "    </briefdescription>" << endl;
1410   t << "    <detaileddescription>" << endl;
1411   writeXMLDocBlock(t,cd->docFile(),cd->docLine(),cd,0,cd->documentation());
1412   t << "    </detaileddescription>" << endl;
1413   DotClassGraph inheritanceGraph(cd,DotNode::Inheritance);
1414   if (!inheritanceGraph.isTrivial())
1415   {
1416     t << "    <inheritancegraph>" << endl;
1417     inheritanceGraph.writeXML(t);
1418     t << "    </inheritancegraph>" << endl;
1419   }
1420   DotClassGraph collaborationGraph(cd,DotNode::Collaboration);
1421   if (!collaborationGraph.isTrivial())
1422   {
1423     t << "    <collaborationgraph>" << endl;
1424     collaborationGraph.writeXML(t);
1425     t << "    </collaborationgraph>" << endl;
1426   }
1427   t << "    <location file=\"" 
1428     << stripFromPath(cd->getDefFileName()) << "\" line=\"" 
1429     << cd->getDefLine() << "\"" << " column=\"" 
1430     << cd->getDefColumn() << "\"" ;
1431     if (cd->getStartBodyLine()!=-1)
1432     {
1433       FileDef *bodyDef = cd->getBodyDef();
1434       if (bodyDef)
1435       {
1436         t << " bodyfile=\"" << stripFromPath(bodyDef->absFilePath()) << "\"";
1437       }
1438       t << " bodystart=\"" << cd->getStartBodyLine() << "\" bodyend=\"" 
1439         << cd->getEndBodyLine() << "\"";
1440     }
1441   t << "/>" << endl;
1442   writeListOfAllMembers(cd,t);
1443   t << "  </compounddef>" << endl;
1444   t << "</doxygen>" << endl;
1445
1446   ti << "  </compound>" << endl;
1447 }
1448
1449 static void generateXMLForNamespace(NamespaceDef *nd,FTextStream &ti)
1450 {
1451   // + contained class definitions
1452   // + contained namespace definitions
1453   // + member groups
1454   // + normal members
1455   // + brief desc
1456   // + detailed desc
1457   // + location
1458   // - files containing (parts of) the namespace definition
1459
1460   if (nd->isReference() || nd->isHidden()) return; // skip external references
1461
1462   ti << "  <compound refid=\"" << nd->getOutputFileBase() 
1463      << "\" kind=\"namespace\"" << "><name>" 
1464      << convertToXML(nd->name()) << "</name>" << endl;
1465   
1466   QCString outputDirectory = Config_getString(XML_OUTPUT);
1467   QCString fileName=outputDirectory+"/"+nd->getOutputFileBase()+".xml";
1468   QFile f(fileName);
1469   if (!f.open(IO_WriteOnly))
1470   {
1471     err("Cannot open file %s for writing!\n",fileName.data());
1472     return;
1473   }
1474   FTextStream t(&f);
1475   //t.setEncoding(FTextStream::UnicodeUTF8);
1476   
1477   writeXMLHeader(t);
1478   t << "  <compounddef id=\"" << nd->getOutputFileBase() 
1479     << "\" kind=\"namespace\" language=\"" 
1480     << langToString(nd->getLanguage()) << "\">" << endl;
1481   t << "    <compoundname>";
1482   writeXMLString(t,nd->name());
1483   t << "</compoundname>" << endl;
1484
1485   writeInnerClasses(nd->getClassSDict(),t);
1486   writeInnerNamespaces(nd->getNamespaceSDict(),t);
1487
1488   if (nd->getMemberGroupSDict())
1489   {
1490     MemberGroupSDict::Iterator mgli(*nd->getMemberGroupSDict());
1491     MemberGroup *mg;
1492     for (;(mg=mgli.current());++mgli)
1493     {
1494       generateXMLSection(nd,ti,t,mg->members(),"user-defined",mg->header(),
1495           mg->documentation());
1496     }
1497   }
1498
1499   QListIterator<MemberList> mli(nd->getMemberLists());
1500   MemberList *ml;
1501   for (mli.toFirst();(ml=mli.current());++mli)
1502   {
1503     if ((ml->listType()&MemberListType_declarationLists)!=0)
1504     {
1505       generateXMLSection(nd,ti,t,ml,g_xmlSectionMapper.find(ml->listType()));
1506     }
1507   }
1508
1509   t << "    <briefdescription>" << endl;
1510   writeXMLDocBlock(t,nd->briefFile(),nd->briefLine(),nd,0,nd->briefDescription());
1511   t << "    </briefdescription>" << endl;
1512   t << "    <detaileddescription>" << endl;
1513   writeXMLDocBlock(t,nd->docFile(),nd->docLine(),nd,0,nd->documentation());
1514   t << "    </detaileddescription>" << endl;
1515   t << "    <location file=\""
1516     << stripFromPath(nd->getDefFileName()) << "\" line=\""
1517     << nd->getDefLine() << "\"" << " column=\""
1518     << nd->getDefColumn() << "\"/>" << endl ;
1519   t << "  </compounddef>" << endl;
1520   t << "</doxygen>" << endl;
1521
1522   ti << "  </compound>" << endl;
1523 }
1524
1525 static void generateXMLForFile(FileDef *fd,FTextStream &ti)
1526 {
1527   // + includes files
1528   // + includedby files
1529   // + include graph
1530   // + included by graph
1531   // + contained class definitions
1532   // + contained namespace definitions
1533   // + member groups
1534   // + normal members
1535   // + brief desc
1536   // + detailed desc
1537   // + source code
1538   // + location
1539   // - number of lines
1540   
1541   if (fd->isReference()) return; // skip external references
1542   
1543   ti << "  <compound refid=\"" << fd->getOutputFileBase() 
1544      << "\" kind=\"file\"><name>" << convertToXML(fd->name()) 
1545      << "</name>" << endl;
1546   
1547   QCString outputDirectory = Config_getString(XML_OUTPUT);
1548   QCString fileName=outputDirectory+"/"+fd->getOutputFileBase()+".xml";
1549   QFile f(fileName);
1550   if (!f.open(IO_WriteOnly))
1551   {
1552     err("Cannot open file %s for writing!\n",fileName.data());
1553     return;
1554   }
1555   FTextStream t(&f);
1556   //t.setEncoding(FTextStream::UnicodeUTF8);
1557
1558   writeXMLHeader(t);
1559   t << "  <compounddef id=\"" << fd->getOutputFileBase()
1560     << "\" kind=\"file\" language=\"" 
1561     << langToString(fd->getLanguage()) << "\">" << endl;
1562   t << "    <compoundname>";
1563   writeXMLString(t,fd->name());
1564   t << "</compoundname>" << endl;
1565
1566   IncludeInfo *inc;
1567
1568   if (fd->includeFileList())
1569   {
1570     QListIterator<IncludeInfo> ili1(*fd->includeFileList());
1571     for (ili1.toFirst();(inc=ili1.current());++ili1)
1572     {
1573       t << "    <includes";
1574       if (inc->fileDef && !inc->fileDef->isReference()) // TODO: support external references
1575       {
1576         t << " refid=\"" << inc->fileDef->getOutputFileBase() << "\"";
1577       }
1578       t << " local=\"" << (inc->local ? "yes" : "no") << "\">";
1579       t << inc->includeName;
1580       t << "</includes>" << endl;
1581     }
1582   }
1583
1584   if (fd->includedByFileList())
1585   {
1586     QListIterator<IncludeInfo> ili2(*fd->includedByFileList());
1587     for (ili2.toFirst();(inc=ili2.current());++ili2)
1588     {
1589       t << "    <includedby";
1590       if (inc->fileDef && !inc->fileDef->isReference()) // TODO: support external references
1591       {
1592         t << " refid=\"" << inc->fileDef->getOutputFileBase() << "\"";
1593       }
1594       t << " local=\"" << (inc->local ? "yes" : "no") << "\">";
1595       t << inc->includeName;
1596       t << "</includedby>" << endl;
1597     }
1598   }
1599
1600   DotInclDepGraph incDepGraph(fd,FALSE);
1601   if (!incDepGraph.isTrivial())
1602   {
1603     t << "    <incdepgraph>" << endl;
1604     incDepGraph.writeXML(t);
1605     t << "    </incdepgraph>" << endl;
1606   }
1607
1608   DotInclDepGraph invIncDepGraph(fd,TRUE);
1609   if (!invIncDepGraph.isTrivial())
1610   {
1611     t << "    <invincdepgraph>" << endl;
1612     invIncDepGraph.writeXML(t);
1613     t << "    </invincdepgraph>" << endl;
1614   }
1615
1616   if (fd->getClassSDict())
1617   {
1618     writeInnerClasses(fd->getClassSDict(),t);
1619   }
1620   if (fd->getNamespaceSDict())
1621   {
1622     writeInnerNamespaces(fd->getNamespaceSDict(),t);
1623   }
1624
1625   if (fd->getMemberGroupSDict())
1626   {
1627     MemberGroupSDict::Iterator mgli(*fd->getMemberGroupSDict());
1628     MemberGroup *mg;
1629     for (;(mg=mgli.current());++mgli)
1630     {
1631       generateXMLSection(fd,ti,t,mg->members(),"user-defined",mg->header(),
1632           mg->documentation());
1633     }
1634   }
1635
1636   QListIterator<MemberList> mli(fd->getMemberLists());
1637   MemberList *ml;
1638   for (mli.toFirst();(ml=mli.current());++mli)
1639   {
1640     if ((ml->listType()&MemberListType_declarationLists)!=0)
1641     {
1642       generateXMLSection(fd,ti,t,ml,g_xmlSectionMapper.find(ml->listType()));
1643     }
1644   }
1645
1646   t << "    <briefdescription>" << endl;
1647   writeXMLDocBlock(t,fd->briefFile(),fd->briefLine(),fd,0,fd->briefDescription());
1648   t << "    </briefdescription>" << endl;
1649   t << "    <detaileddescription>" << endl;
1650   writeXMLDocBlock(t,fd->docFile(),fd->docLine(),fd,0,fd->documentation());
1651   t << "    </detaileddescription>" << endl;
1652   if (Config_getBool(XML_PROGRAMLISTING))
1653   {
1654     t << "    <programlisting>" << endl;
1655     writeXMLCodeBlock(t,fd);
1656     t << "    </programlisting>" << endl;
1657   }
1658   t << "    <location file=\"" << stripFromPath(fd->getDefFileName()) << "\"/>" << endl;
1659   t << "  </compounddef>" << endl;
1660   t << "</doxygen>" << endl;
1661
1662   ti << "  </compound>" << endl;
1663 }
1664
1665 static void generateXMLForGroup(GroupDef *gd,FTextStream &ti)
1666 {
1667   // + members
1668   // + member groups
1669   // + files
1670   // + classes
1671   // + namespaces
1672   // - packages
1673   // + pages
1674   // + child groups
1675   // - examples
1676   // + brief description
1677   // + detailed description
1678
1679   if (gd->isReference()) return; // skip external references
1680
1681   ti << "  <compound refid=\"" << gd->getOutputFileBase() 
1682      << "\" kind=\"group\"><name>" << convertToXML(gd->name()) << "</name>" << endl;
1683   
1684   QCString outputDirectory = Config_getString(XML_OUTPUT);
1685   QCString fileName=outputDirectory+"/"+gd->getOutputFileBase()+".xml";
1686   QFile f(fileName);
1687   if (!f.open(IO_WriteOnly))
1688   {
1689     err("Cannot open file %s for writing!\n",fileName.data());
1690     return;
1691   }
1692
1693   FTextStream t(&f);
1694   //t.setEncoding(FTextStream::UnicodeUTF8);
1695   writeXMLHeader(t);
1696   t << "  <compounddef id=\"" 
1697     << gd->getOutputFileBase() << "\" kind=\"group\">" << endl;
1698   t << "    <compoundname>" << convertToXML(gd->name()) << "</compoundname>" << endl;
1699   t << "    <title>" << convertToXML(gd->groupTitle()) << "</title>" << endl;
1700
1701   writeInnerFiles(gd->getFiles(),t);
1702   writeInnerClasses(gd->getClasses(),t);
1703   writeInnerNamespaces(gd->getNamespaces(),t);
1704   writeInnerPages(gd->getPages(),t);
1705   writeInnerGroups(gd->getSubGroups(),t);
1706
1707   if (gd->getMemberGroupSDict())
1708   {
1709     MemberGroupSDict::Iterator mgli(*gd->getMemberGroupSDict());
1710     MemberGroup *mg;
1711     for (;(mg=mgli.current());++mgli)
1712     {
1713       generateXMLSection(gd,ti,t,mg->members(),"user-defined",mg->header(),
1714           mg->documentation());
1715     }
1716   }
1717
1718   QListIterator<MemberList> mli(gd->getMemberLists());
1719   MemberList *ml;
1720   for (mli.toFirst();(ml=mli.current());++mli)
1721   {
1722     if ((ml->listType()&MemberListType_declarationLists)!=0)
1723     {
1724       generateXMLSection(gd,ti,t,ml,g_xmlSectionMapper.find(ml->listType()));
1725     }
1726   }
1727
1728   t << "    <briefdescription>" << endl;
1729   writeXMLDocBlock(t,gd->briefFile(),gd->briefLine(),gd,0,gd->briefDescription());
1730   t << "    </briefdescription>" << endl;
1731   t << "    <detaileddescription>" << endl;
1732   writeXMLDocBlock(t,gd->docFile(),gd->docLine(),gd,0,gd->documentation());
1733   t << "    </detaileddescription>" << endl;
1734   t << "  </compounddef>" << endl;
1735   t << "</doxygen>" << endl;
1736
1737   ti << "  </compound>" << endl;
1738 }
1739
1740 static void generateXMLForDir(DirDef *dd,FTextStream &ti)
1741 {
1742   if (dd->isReference()) return; // skip external references
1743   ti << "  <compound refid=\"" << dd->getOutputFileBase() 
1744      << "\" kind=\"dir\"><name>" << convertToXML(dd->displayName()) 
1745      << "</name>" << endl;
1746
1747   QCString outputDirectory = Config_getString(XML_OUTPUT);
1748   QCString fileName=outputDirectory+"/"+dd->getOutputFileBase()+".xml";
1749   QFile f(fileName);
1750   if (!f.open(IO_WriteOnly))
1751   {
1752     err("Cannot open file %s for writing!\n",fileName.data());
1753     return;
1754   }
1755
1756   FTextStream t(&f);
1757   //t.setEncoding(FTextStream::UnicodeUTF8);
1758   writeXMLHeader(t);
1759   t << "  <compounddef id=\"" 
1760     << dd->getOutputFileBase() << "\" kind=\"dir\">" << endl;
1761   t << "    <compoundname>" << convertToXML(dd->displayName()) << "</compoundname>" << endl;
1762
1763   writeInnerDirs(&dd->subDirs(),t);
1764   writeInnerFiles(dd->getFiles(),t);
1765
1766   t << "    <briefdescription>" << endl;
1767   writeXMLDocBlock(t,dd->briefFile(),dd->briefLine(),dd,0,dd->briefDescription());
1768   t << "    </briefdescription>" << endl;
1769   t << "    <detaileddescription>" << endl;
1770   writeXMLDocBlock(t,dd->docFile(),dd->docLine(),dd,0,dd->documentation());
1771   t << "    </detaileddescription>" << endl;
1772   t << "    <location file=\"" << stripFromPath(dd->name()) << "\"/>" << endl; 
1773   t << "  </compounddef>" << endl;
1774   t << "</doxygen>" << endl;
1775
1776   ti << "  </compound>" << endl;
1777 }
1778
1779 static void generateXMLForPage(PageDef *pd,FTextStream &ti,bool isExample)
1780 {
1781   // + name
1782   // + title
1783   // + documentation
1784
1785   const char *kindName = isExample ? "example" : "page";
1786
1787   if (pd->isReference()) return;
1788   
1789   QCString pageName = pd->getOutputFileBase();
1790   if (pd->getGroupDef())
1791   {
1792     pageName+=(QCString)"_"+pd->name();
1793   }
1794   if (pageName=="index") pageName="indexpage"; // to prevent overwriting the generated index page.
1795   
1796   ti << "  <compound refid=\"" << pageName
1797      << "\" kind=\"" << kindName << "\"><name>" << convertToXML(pd->name()) 
1798      << "</name>" << endl;
1799   
1800   QCString outputDirectory = Config_getString(XML_OUTPUT);
1801   QCString fileName=outputDirectory+"/"+pageName+".xml";
1802   QFile f(fileName);
1803   if (!f.open(IO_WriteOnly))
1804   {
1805     err("Cannot open file %s for writing!\n",fileName.data());
1806     return;
1807   }
1808
1809   FTextStream t(&f);
1810   //t.setEncoding(FTextStream::UnicodeUTF8);
1811   writeXMLHeader(t);
1812   t << "  <compounddef id=\"" << pageName;
1813   t << "\" kind=\"" << kindName << "\">" << endl;
1814   t << "    <compoundname>" << convertToXML(pd->name()) 
1815     << "</compoundname>" << endl;
1816
1817   if (pd==Doxygen::mainPage) // main page is special
1818   {
1819     QCString title;
1820     if (!pd->title().isEmpty() && pd->title().lower()!="notitle")
1821     {
1822       title = filterTitle(convertCharEntitiesToUTF8(Doxygen::mainPage->title()));
1823     }
1824     else 
1825     {
1826       title = Config_getString(PROJECT_NAME);
1827     }
1828     t << "    <title>" << convertToXML(convertCharEntitiesToUTF8(title)) 
1829       << "</title>" << endl;
1830   }
1831   else
1832   {
1833     SectionInfo *si = Doxygen::sectionDict->find(pd->name());
1834     if (si)
1835     {
1836       t << "    <title>" << convertToXML(convertCharEntitiesToUTF8(filterTitle(si->title))) 
1837         << "</title>" << endl;
1838     }
1839   }
1840   writeInnerPages(pd->getSubPages(),t);
1841   if(pd->showToc())
1842   {
1843     t << "    <tableofcontents/>" << endl;
1844   }
1845   t << "    <briefdescription>" << endl;
1846   writeXMLDocBlock(t,pd->briefFile(),pd->briefLine(),pd,0,pd->briefDescription());
1847   t << "    </briefdescription>" << endl;
1848   t << "    <detaileddescription>" << endl;
1849   if (isExample)
1850   {
1851     writeXMLDocBlock(t,pd->docFile(),pd->docLine(),pd,0,
1852         pd->documentation()+"\n\\include "+pd->name());
1853   }
1854   else
1855   {
1856     writeXMLDocBlock(t,pd->docFile(),pd->docLine(),pd,0,
1857         pd->documentation());
1858   }
1859   t << "    </detaileddescription>" << endl;
1860
1861   t << "  </compounddef>" << endl;
1862   t << "</doxygen>" << endl;
1863
1864   ti << "  </compound>" << endl;
1865 }
1866
1867 void generateXML()
1868 {
1869   // + classes
1870   // + namespaces
1871   // + files
1872   // + groups
1873   // + related pages
1874   // - examples
1875   
1876   QCString outputDirectory = Config_getString(XML_OUTPUT);
1877   QDir xmlDir(outputDirectory);
1878   createSubDirs(xmlDir);
1879
1880   ResourceMgr::instance().copyResource("index.xsd",outputDirectory);
1881
1882   QCString fileName=outputDirectory+"/compound.xsd";
1883   QFile f(fileName);
1884   if (!f.open(IO_WriteOnly))
1885   {
1886     err("Cannot open file %s for writing!\n",fileName.data());
1887     return;
1888   }
1889
1890   // write compound.xsd, but replace special marker with the entities
1891   QCString compound_xsd = ResourceMgr::instance().getAsString("compound.xsd");
1892   const char *startLine = compound_xsd.data();
1893   while (*startLine)
1894   {
1895     // find end of the line
1896     const char *endLine = startLine+1;
1897     while (*endLine && *(endLine-1)!='\n') endLine++; // skip to end of the line including \n
1898     int len=endLine-startLine;
1899     if (len>0)
1900     {
1901       QCString s(len+1);
1902       qstrncpy(s.rawData(),startLine,len);
1903       s[len]='\0';
1904       if (s.find("<!-- Automatically insert here the HTML entities -->")!=-1)
1905       {
1906         FTextStream t(&f);
1907         HtmlEntityMapper::instance()->writeXMLSchema(t);
1908       }
1909       else
1910       {
1911         f.writeBlock(startLine,len);
1912       }
1913     }
1914     startLine=endLine;
1915   }
1916   f.close();
1917
1918   fileName=outputDirectory+"/index.xml";
1919   f.setName(fileName);
1920   if (!f.open(IO_WriteOnly))
1921   {
1922     err("Cannot open file %s for writing!\n",fileName.data());
1923     return;
1924   }
1925   FTextStream t(&f);
1926   //t.setEncoding(FTextStream::UnicodeUTF8);
1927
1928   // write index header
1929   t << "<?xml version='1.0' encoding='UTF-8' standalone='no'?>" << endl;;
1930   t << "<doxygenindex xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" ";
1931   t << "xsi:noNamespaceSchemaLocation=\"index.xsd\" ";
1932   t << "version=\"" << versionString << "\">" << endl;
1933
1934   {
1935     ClassSDict::Iterator cli(*Doxygen::classSDict);
1936     ClassDef *cd;
1937     for (cli.toFirst();(cd=cli.current());++cli)
1938     {
1939       generateXMLForClass(cd,t);
1940     }
1941   }
1942   //{
1943   //  ClassSDict::Iterator cli(Doxygen::hiddenClasses);
1944   //  ClassDef *cd;
1945   //  for (cli.toFirst();(cd=cli.current());++cli)
1946   //  {
1947   //    msg("Generating XML output for class %s\n",cd->name().data());
1948   //    generateXMLForClass(cd,t);
1949   //  }
1950   //}
1951   NamespaceSDict::Iterator nli(*Doxygen::namespaceSDict);
1952   NamespaceDef *nd;
1953   for (nli.toFirst();(nd=nli.current());++nli)
1954   {
1955     msg("Generating XML output for namespace %s\n",nd->name().data());
1956     generateXMLForNamespace(nd,t);
1957   }
1958   FileNameListIterator fnli(*Doxygen::inputNameList);
1959   FileName *fn;
1960   for (;(fn=fnli.current());++fnli)
1961   {
1962     FileNameIterator fni(*fn);
1963     FileDef *fd;
1964     for (;(fd=fni.current());++fni)
1965     {
1966       msg("Generating XML output for file %s\n",fd->name().data());
1967       generateXMLForFile(fd,t);
1968     }
1969   }
1970   GroupSDict::Iterator gli(*Doxygen::groupSDict);
1971   GroupDef *gd;
1972   for (;(gd=gli.current());++gli)
1973   {
1974     msg("Generating XML output for group %s\n",gd->name().data());
1975     generateXMLForGroup(gd,t);
1976   }
1977   {
1978     PageSDict::Iterator pdi(*Doxygen::pageSDict);
1979     PageDef *pd=0;
1980     for (pdi.toFirst();(pd=pdi.current());++pdi)
1981     {
1982       msg("Generating XML output for page %s\n",pd->name().data());
1983       generateXMLForPage(pd,t,FALSE);
1984     }
1985   }
1986   {
1987     DirDef *dir;
1988     DirSDict::Iterator sdi(*Doxygen::directories);
1989     for (sdi.toFirst();(dir=sdi.current());++sdi)
1990     {
1991       msg("Generate XML output for dir %s\n",dir->name().data());
1992       generateXMLForDir(dir,t);
1993     }
1994   }
1995   {
1996     PageSDict::Iterator pdi(*Doxygen::exampleSDict);
1997     PageDef *pd=0;
1998     for (pdi.toFirst();(pd=pdi.current());++pdi)
1999     {
2000       msg("Generating XML output for example %s\n",pd->name().data());
2001       generateXMLForPage(pd,t,TRUE);
2002     }
2003   }
2004   if (Doxygen::mainPage)
2005   {
2006     msg("Generating XML output for the main page\n");
2007     generateXMLForPage(Doxygen::mainPage,t,FALSE);
2008   }
2009
2010   //t << "  </compoundlist>" << endl;
2011   t << "</doxygenindex>" << endl;
2012
2013   writeCombineScript();
2014 }
2015
2016