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