|
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 << "<"; col++; break; |
|
133 case '>': t << ">"; col++; break; |
|
134 case '&': t << "&"; col++; break; |
|
135 case '\'': t << "'"; col++; break; |
|
136 case '"': t << """; 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 |