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