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