Chameleon

Chameleon Svn Source Tree

Root/branches/xZenu/src/util/doxygen/src/tagreader.cpp

Source at commit 1322 created 9 years 5 months ago.
By meklort, Add doxygen to utils folder
1/******************************************************************************
2 *
3 * $Id: tagreader.cpp,v 1.2 2001/03/19 19:27:41 root Exp $
4 *
5 *
6 * Copyright (C) 1997-2011 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 "tagreader.h"
20
21#include <stdio.h>
22#include <stdarg.h>
23
24#include <qxml.h>
25#include <qstack.h>
26#include <qdict.h>
27#include <qfileinfo.h>
28#include <qlist.h>
29#include <qstring.h>
30#include <qstringlist.h>
31
32#include "entry.h"
33#include "classdef.h"
34#include "doxygen.h"
35#include "util.h"
36#include "message.h"
37#include "defargs.h"
38//#include "reflist.h"
39
40/*! Information about an linkable anchor */
41class TagAnchorInfo
42{
43 public:
44 TagAnchorInfo(const QString &f,const QString &l) : label(l), fileName(f) {}
45 QString label;
46 QString fileName;
47};
48
49class TagAnchorInfoList : public QList<TagAnchorInfo>
50{
51 public:
52 TagAnchorInfoList() : QList<TagAnchorInfo>() { setAutoDelete(TRUE); }
53 virtual ~TagAnchorInfoList() {}
54};
55
56/*! Container for member specific info that can be read from a tagfile */
57class TagMemberInfo
58{
59 public:
60 TagMemberInfo() : prot(Public), virt(Normal), isStatic(FALSE) {}
61 QString type;
62 QString name;
63 QString anchorFile;
64 QString anchor;
65 QString arglist;
66 QString kind;
67 TagAnchorInfoList docAnchors;
68 Protection prot;
69 Specifier virt;
70 bool isStatic;
71};
72
73/*! Container for class specific info that can be read from a tagfile */
74class TagClassInfo
75{
76 public:
77 enum Kind { Class, Struct, Union, Interface, Exception, Protocol, Category };
78 TagClassInfo() { bases=0, templateArguments=0; members.setAutoDelete(TRUE); isObjC=FALSE; }
79 ~TagClassInfo() { delete bases; delete templateArguments; }
80 QString name;
81 QString filename;
82 TagAnchorInfoList docAnchors;
83 QList<BaseInfo> *bases;
84 QList<TagMemberInfo> members;
85 QList<QString> *templateArguments;
86 QStringList classList;
87 Kind kind;
88 bool isObjC;
89};
90
91/*! Container for namespace specific info that can be read from a tagfile */
92class TagNamespaceInfo
93{
94 public:
95 TagNamespaceInfo() { members.setAutoDelete(TRUE); }
96 QString name;
97 QString filename;
98 QStringList classList;
99 QStringList namespaceList;
100 TagAnchorInfoList docAnchors;
101 QList<TagMemberInfo> members;
102};
103
104/*! Container for package specific info that can be read from a tagfile */
105class TagPackageInfo
106{
107 public:
108 TagPackageInfo() { members.setAutoDelete(TRUE); }
109 QString name;
110 QString filename;
111 TagAnchorInfoList docAnchors;
112 QList<TagMemberInfo> members;
113 QStringList classList;
114};
115
116class TagIncludeInfo
117{
118 public:
119 QString id;
120 QString name;
121 QString text;
122 bool isLocal;
123 bool isImported;
124};
125
126/*! Container for file specific info that can be read from a tagfile */
127class TagFileInfo
128{
129 public:
130 TagFileInfo() { members.setAutoDelete(TRUE); includes.setAutoDelete(TRUE); }
131 QString name;
132 QString path;
133 QString filename;
134 TagAnchorInfoList docAnchors;
135 QList<TagMemberInfo> members;
136 QStringList classList;
137 QStringList namespaceList;
138 QList<TagIncludeInfo> includes;
139};
140
141/*! Container for group specific info that can be read from a tagfile */
142class TagGroupInfo
143{
144 public:
145 TagGroupInfo() { members.setAutoDelete(TRUE); }
146 QString name;
147 QString title;
148 QString filename;
149 TagAnchorInfoList docAnchors;
150 QList<TagMemberInfo> members;
151 QStringList subgroupList;
152 QStringList classList;
153 QStringList namespaceList;
154 QStringList fileList;
155 QStringList pageList;
156 QStringList dirList;
157};
158
159/*! Container for page specific info that can be read from a tagfile */
160class TagPageInfo
161{
162 public:
163 QString name;
164 QString title;
165 QString filename;
166 TagAnchorInfoList docAnchors;
167};
168
169/*! Container for directory specific info that can be read from a tagfile */
170class TagDirInfo
171{
172 public:
173 QString name;
174 QString filename;
175 QString path;
176 QStringList subdirList;
177 QStringList fileList;
178 TagAnchorInfoList docAnchors;
179};
180
181/*! Tag file parser.
182 * Reads an XML-structured tagfile and builds up the structure in
183 * memory. The method buildLists() is used to transfer/translate
184 * the structures to the doxygen engine.
185 */
186class TagFileParser : public QXmlDefaultHandler
187{
188 enum State { Invalid,
189 InClass,
190 InFile,
191 InNamespace,
192 InGroup,
193 InPage,
194 InMember,
195 InPackage,
196 InDir,
197 InTempArgList
198 };
199 class StartElementHandler
200 {
201 typedef void (TagFileParser::*Handler)(const QXmlAttributes &attrib);
202 public:
203 StartElementHandler(TagFileParser *parent, Handler h) : m_parent(parent), m_handler(h) {}
204 void operator()(const QXmlAttributes &attrib) { (m_parent->*m_handler)(attrib); }
205 private:
206 TagFileParser *m_parent;
207 Handler m_handler;
208 };
209
210 class EndElementHandler
211 {
212 typedef void (TagFileParser::*Handler)();
213 public:
214 EndElementHandler(TagFileParser *parent, Handler h) : m_parent(parent), m_handler(h) {}
215 void operator()() { (m_parent->*m_handler)(); }
216 private:
217 TagFileParser *m_parent;
218 Handler m_handler;
219 };
220
221 public:
222 TagFileParser(const char *tagName) : m_startElementHandlers(17),
223 m_endElementHandlers(17),
224 m_tagName(tagName)
225 {
226 m_startElementHandlers.setAutoDelete(TRUE);
227 m_endElementHandlers.setAutoDelete(TRUE);
228 }
229
230 void setDocumentLocator ( QXmlLocator * locator )
231 {
232 m_locator = locator;
233 }
234
235 void setFileName( const QString &fileName )
236 {
237 m_inputFileName = fileName;
238 }
239
240 void warn(const char *fmt)
241 {
242 ::warn(m_inputFileName,m_locator->lineNumber(),fmt);
243 }
244 void warn(const char *fmt,const char *s)
245 {
246 ::warn(m_inputFileName,m_locator->lineNumber(),fmt,s);
247 }
248
249 void startCompound( const QXmlAttributes& attrib )
250 {
251 m_curString = "";
252 QString kind = attrib.value("kind");
253 QString isObjC = attrib.value("objc");
254 if (kind=="class")
255 {
256 m_curClass = new TagClassInfo;
257 m_curClass->kind = TagClassInfo::Class;
258 m_state = InClass;
259 }
260 else if (kind=="struct")
261 {
262 m_curClass = new TagClassInfo;
263 m_curClass->kind = TagClassInfo::Struct;
264 m_state = InClass;
265 }
266 else if (kind=="union")
267 {
268 m_curClass = new TagClassInfo;
269 m_curClass->kind = TagClassInfo::Union;
270 m_state = InClass;
271 }
272 else if (kind=="interface")
273 {
274 m_curClass = new TagClassInfo;
275 m_curClass->kind = TagClassInfo::Interface;
276 m_state = InClass;
277 }
278 else if (kind=="exception")
279 {
280 m_curClass = new TagClassInfo;
281 m_curClass->kind = TagClassInfo::Exception;
282 m_state = InClass;
283 }
284 else if (kind=="protocol")
285 {
286 m_curClass = new TagClassInfo;
287 m_curClass->kind = TagClassInfo::Protocol;
288 m_state = InClass;
289 }
290 else if (kind=="category")
291 {
292 m_curClass = new TagClassInfo;
293 m_curClass->kind = TagClassInfo::Category;
294 m_state = InClass;
295 }
296 else if (kind=="file")
297 {
298 m_curFile = new TagFileInfo;
299 m_state = InFile;
300 }
301 else if (kind=="namespace")
302 {
303 m_curNamespace = new TagNamespaceInfo;
304 m_state = InNamespace;
305 }
306 else if (kind=="group")
307 {
308 m_curGroup = new TagGroupInfo;
309 m_state = InGroup;
310 }
311 else if (kind=="page")
312 {
313 m_curPage = new TagPageInfo;
314 m_state = InPage;
315 }
316 else if (kind=="package")
317 {
318 m_curPackage = new TagPackageInfo;
319 m_state = InPackage;
320 }
321 else if (kind=="dir")
322 {
323 m_curDir = new TagDirInfo;
324 m_state = InDir;
325 }
326 else
327 {
328 warn("warning: Unknown compound attribute `%s' found!\n",kind.data());
329 }
330 if (isObjC=="yes" && m_curClass)
331 {
332 m_curClass->isObjC = TRUE;
333 }
334 }
335
336 void endCompound()
337 {
338 switch (m_state)
339 {
340 case InClass: m_tagFileClasses.append(m_curClass);
341 m_curClass=0; break;
342 case InFile: m_tagFileFiles.append(m_curFile);
343 m_curFile=0; break;
344 case InNamespace: m_tagFileNamespaces.append(m_curNamespace);
345 m_curNamespace=0; break;
346 case InGroup: m_tagFileGroups.append(m_curGroup);
347 m_curGroup=0; break;
348 case InPage: m_tagFilePages.append(m_curPage);
349 m_curPage=0; break;
350 case InDir: m_tagFileDirs.append(m_curDir);
351 m_curDir=0; break;
352 case InPackage: m_tagFilePackages.append(m_curPackage);
353 m_curPackage=0; break;
354 default:
355 warn("warning: tag `compound' was not expected!\n");
356 }
357 }
358
359 void startMember( const QXmlAttributes& attrib)
360 {
361 m_curMember = new TagMemberInfo;
362 m_curMember->kind = attrib.value("kind");
363 QString protStr = attrib.value("protection");
364 QString virtStr = attrib.value("virtualness");
365 QString staticStr = attrib.value("static");
366 if (protStr=="protected")
367 {
368 m_curMember->prot = Protected;
369 }
370 else if (protStr=="private")
371 {
372 m_curMember->prot = Private;
373 }
374 if (virtStr=="virtual")
375 {
376 m_curMember->virt = Virtual;
377 }
378 else if (virtStr=="pure")
379 {
380 m_curMember->virt = Pure;
381 }
382 if (staticStr=="yes")
383 {
384 m_curMember->isStatic = TRUE;
385 }
386 m_stateStack.push(new State(m_state));
387 m_state = InMember;
388 }
389
390 void endMember()
391 {
392 m_state = *m_stateStack.top();
393 m_stateStack.remove();
394 switch(m_state)
395 {
396 case InClass: m_curClass->members.append(m_curMember); break;
397 case InFile: m_curFile->members.append(m_curMember); break;
398 case InNamespace: m_curNamespace->members.append(m_curMember); break;
399 case InGroup: m_curGroup->members.append(m_curMember); break;
400 case InPackage: m_curPackage->members.append(m_curMember); break;
401 default: warn("warning: Unexpected tag `member' found\n"); break;
402 }
403 }
404
405 void endDocAnchor()
406 {
407 switch(m_state)
408 {
409 case InClass: m_curClass->docAnchors.append(new TagAnchorInfo(m_fileName,m_curString)); break;
410 case InFile: m_curFile->docAnchors.append(new TagAnchorInfo(m_fileName,m_curString)); break;
411 case InNamespace: m_curNamespace->docAnchors.append(new TagAnchorInfo(m_fileName,m_curString)); break;
412 case InGroup: m_curGroup->docAnchors.append(new TagAnchorInfo(m_fileName,m_curString)); break;
413 case InPage: m_curPage->docAnchors.append(new TagAnchorInfo(m_fileName,m_curString)); break;
414 case InMember: m_curMember->docAnchors.append(new TagAnchorInfo(m_fileName,m_curString)); break;
415 case InPackage: m_curPackage->docAnchors.append(new TagAnchorInfo(m_fileName,m_curString)); break;
416 case InDir: m_curDir->docAnchors.append(new TagAnchorInfo(m_fileName,m_curString)); break;
417 default: warn("warning: Unexpected tag `member' found\n"); break;
418 }
419 }
420
421 void endClass()
422 {
423 switch(m_state)
424 {
425 case InClass: m_curClass->classList.append(m_curString); break;
426 case InFile: m_curFile->classList.append(m_curString); break;
427 case InNamespace: m_curNamespace->classList.append(m_curString); break;
428 case InGroup: m_curGroup->classList.append(m_curString); break;
429 case InPackage: m_curPackage->classList.append(m_curString); break;
430 default: warn("warning: Unexpected tag `class' found\n"); break;
431 }
432 }
433
434 void endNamespace()
435 {
436 switch(m_state)
437 {
438 case InNamespace: m_curNamespace->classList.append(m_curString); break;
439 case InFile: m_curFile->namespaceList.append(m_curString); break;
440 case InGroup: m_curGroup->namespaceList.append(m_curString); break;
441 default: warn("warning: Unexpected tag `namespace' found\n"); break;
442 }
443 }
444
445 void endFile()
446 {
447 switch(m_state)
448 {
449 case InGroup: m_curGroup->fileList.append(m_curString); break;
450 case InDir: m_curDir->fileList.append(m_curString); break;
451 default: warn("warning: Unexpected tag `file' found\n"); break;
452 }
453 }
454
455 void endPage()
456 {
457 switch(m_state)
458 {
459 case InGroup: m_curGroup->fileList.append(m_curString); break;
460 default: warn("warning: Unexpected tag `page' found\n"); break;
461 }
462 }
463
464 void endDir()
465 {
466 switch(m_state)
467 {
468 case InDir: m_curDir->subdirList.append(m_curString); break;
469 default: warn("warning: Unexpected tag `page' found\n"); break;
470 }
471 }
472
473 void startStringValue(const QXmlAttributes& )
474 {
475 m_curString = "";
476 }
477
478 void startDocAnchor(const QXmlAttributes& attrib )
479 {
480 m_fileName = attrib.value("file");
481 m_curString = "";
482 }
483
484 void endType()
485 {
486 if (m_state==InMember)
487 {
488 m_curMember->type = m_curString;
489 }
490 else
491 {
492 warn("warning: Unexpected tag `type' found\n");
493 }
494 }
495
496 void endName()
497 {
498 switch (m_state)
499 {
500 case InClass: m_curClass->name = m_curString; break;
501 case InFile: m_curFile->name = m_curString; break;
502 case InNamespace: m_curNamespace->name = m_curString; break;
503 case InGroup: m_curGroup->name = m_curString; break;
504 case InPage: m_curPage->name = m_curString; break;
505 case InDir: m_curDir->name = m_curString; break;
506 case InMember: m_curMember->name = m_curString; break;
507 case InPackage: m_curPackage->name = m_curString; break;
508 default: warn("warning: Unexpected tag `name' found\n"); break;
509 }
510 }
511
512 void startBase(const QXmlAttributes& attrib )
513 {
514 m_curString="";
515 if (m_state==InClass && m_curClass)
516 {
517 QString protStr = attrib.value("protection");
518 QString virtStr = attrib.value("virtualness");
519 Protection prot = Public;
520 Specifier virt = Normal;
521 if (protStr=="protected")
522 {
523 prot = Protected;
524 }
525 else if (protStr=="private")
526 {
527 prot = Private;
528 }
529 if (virtStr=="virtual")
530 {
531 virt = Virtual;
532 }
533 if (m_curClass->bases==0)
534 {
535 m_curClass->bases = new QList<BaseInfo>;
536 m_curClass->bases->setAutoDelete(TRUE);
537 }
538 m_curClass->bases->append(new BaseInfo(m_curString,prot,virt));
539 }
540 else
541 {
542 warn("warning: Unexpected tag `base' found\n");
543 }
544 }
545
546 void endBase()
547 {
548 if (m_state==InClass && m_curClass)
549 {
550 m_curClass->bases->getLast()->name = m_curString;
551 }
552 else
553 {
554 warn("warning: Unexpected tag `base' found\n");
555 }
556 }
557
558 void startIncludes(const QXmlAttributes& attrib )
559 {
560 if (m_state==InFile && m_curFile)
561 {
562 m_curIncludes = new TagIncludeInfo;
563 m_curIncludes->id = attrib.value("id");
564 m_curIncludes->name = attrib.value("name");
565 m_curIncludes->isLocal = attrib.value("local")=="yes" ? TRUE : FALSE;
566 m_curIncludes->isImported = attrib.value("imported")=="yes" ? TRUE : FALSE;
567 m_curFile->includes.append(m_curIncludes);
568 }
569 else
570 {
571 warn("warning: Unexpected tag `includes' found\n");
572 }
573 m_curString="";
574 }
575
576 void endIncludes()
577 {
578 m_curIncludes->text = m_curString;
579 }
580
581 void endTemplateArg()
582 {
583 if (m_state==InClass && m_curClass)
584 {
585 if (m_curClass->templateArguments==0)
586 {
587 m_curClass->templateArguments = new QList<QString>;
588 m_curClass->templateArguments->setAutoDelete(TRUE);
589 }
590 m_curClass->templateArguments->append(new QString(m_curString));
591 }
592 else
593 {
594 warn("warning: Unexpected tag `templarg' found\n");
595 }
596 }
597
598 void endFilename()
599 {
600 switch (m_state)
601 {
602 case InClass: m_curClass->filename = m_curString; break;
603 case InNamespace: m_curNamespace->filename = m_curString; break;
604 case InFile: m_curFile->filename = m_curString; break;
605 case InGroup: m_curGroup->filename = m_curString; break;
606 case InPage: m_curPage->filename = m_curString; break;
607 case InPackage: m_curPackage->filename = m_curString; break;
608 case InDir: m_curDir->filename = m_curString; break;
609 default: warn("warning: Unexpected tag `filename' found\n"); break;
610 }
611 }
612
613 void endPath()
614 {
615 switch (m_state)
616 {
617 case InFile: m_curFile->path = m_curString; break;
618 case InDir: m_curDir->path = m_curString; break;
619 default: warn("warning: Unexpected tag `path' found\n"); break;
620 }
621 }
622
623 void endAnchor()
624 {
625 if (m_state==InMember)
626 {
627 m_curMember->anchor = m_curString;
628 }
629 else
630 {
631 warn("warning: Unexpected tag `anchor' found\n");
632 }
633 }
634
635 void endAnchorFile()
636 {
637 if (m_state==InMember)
638 {
639 m_curMember->anchorFile = m_curString;
640 }
641 else
642 {
643 warn("warning: Unexpected tag `anchorfile' found\n");
644 }
645 }
646
647 void endArglist()
648 {
649 if (m_state==InMember)
650 {
651 m_curMember->arglist = m_curString;
652 }
653 else
654 {
655 warn("warning: Unexpected tag `arglist' found\n");
656 }
657 }
658 void endTitle()
659 {
660 switch (m_state)
661 {
662 case InGroup: m_curGroup->title = m_curString; break;
663 case InPage: m_curPage->title = m_curString; break;
664 default: warn("warning: Unexpected tag `title' found\n"); break;
665 }
666 }
667
668 void endSubgroup()
669 {
670 if (m_state==InGroup)
671 {
672 m_curGroup->subgroupList.append(m_curString);
673 }
674 else
675 {
676 warn("warning: Unexpected tag `subgroup' found\n");
677 }
678 }
679
680 void startIgnoreElement(const QXmlAttributes& )
681 {
682 }
683
684 void endIgnoreElement()
685 {
686 }
687
688 bool startDocument()
689 {
690 m_state = Invalid;
691
692 m_curClass=0;
693 m_curNamespace=0;
694 m_curFile=0;
695 m_curGroup=0;
696 m_curPage=0;
697 m_curPackage=0;
698 m_curDir=0;
699
700 m_stateStack.setAutoDelete(TRUE);
701 m_tagFileClasses.setAutoDelete(TRUE);
702 m_tagFileFiles.setAutoDelete(TRUE);
703 m_tagFileNamespaces.setAutoDelete(TRUE);
704 m_tagFileGroups.setAutoDelete(TRUE);
705 m_tagFilePages.setAutoDelete(TRUE);
706 m_tagFilePackages.setAutoDelete(TRUE);
707 m_tagFileDirs.setAutoDelete(TRUE);
708
709 m_startElementHandlers.insert("compound", new StartElementHandler(this,&TagFileParser::startCompound));
710 m_startElementHandlers.insert("member", new StartElementHandler(this,&TagFileParser::startMember));
711 m_startElementHandlers.insert("name", new StartElementHandler(this,&TagFileParser::startStringValue));
712 m_startElementHandlers.insert("base", new StartElementHandler(this,&TagFileParser::startBase));
713 m_startElementHandlers.insert("filename", new StartElementHandler(this,&TagFileParser::startStringValue));
714 m_startElementHandlers.insert("includes", new StartElementHandler(this,&TagFileParser::startIncludes));
715 m_startElementHandlers.insert("path", new StartElementHandler(this,&TagFileParser::startStringValue));
716 m_startElementHandlers.insert("anchorfile", new StartElementHandler(this,&TagFileParser::startStringValue));
717 m_startElementHandlers.insert("anchor", new StartElementHandler(this,&TagFileParser::startStringValue));
718 m_startElementHandlers.insert("arglist", new StartElementHandler(this,&TagFileParser::startStringValue));
719 m_startElementHandlers.insert("title", new StartElementHandler(this,&TagFileParser::startStringValue));
720 m_startElementHandlers.insert("subgroup", new StartElementHandler(this,&TagFileParser::startStringValue));
721 m_startElementHandlers.insert("class", new StartElementHandler(this,&TagFileParser::startStringValue));
722 m_startElementHandlers.insert("namespace", new StartElementHandler(this,&TagFileParser::startStringValue));
723 m_startElementHandlers.insert("file", new StartElementHandler(this,&TagFileParser::startStringValue));
724 m_startElementHandlers.insert("dir", new StartElementHandler(this,&TagFileParser::startStringValue));
725 m_startElementHandlers.insert("page", new StartElementHandler(this,&TagFileParser::startStringValue));
726 m_startElementHandlers.insert("docanchor", new StartElementHandler(this,&TagFileParser::startDocAnchor));
727 m_startElementHandlers.insert("tagfile", new StartElementHandler(this,&TagFileParser::startIgnoreElement));
728 m_startElementHandlers.insert("templarg", new StartElementHandler(this,&TagFileParser::startStringValue));
729 m_startElementHandlers.insert("type", new StartElementHandler(this,&TagFileParser::startStringValue));
730
731 m_endElementHandlers.insert("compound", new EndElementHandler(this,&TagFileParser::endCompound));
732 m_endElementHandlers.insert("member", new EndElementHandler(this,&TagFileParser::endMember));
733 m_endElementHandlers.insert("name", new EndElementHandler(this,&TagFileParser::endName));
734 m_endElementHandlers.insert("base", new EndElementHandler(this,&TagFileParser::endBase));
735 m_endElementHandlers.insert("filename", new EndElementHandler(this,&TagFileParser::endFilename));
736 m_endElementHandlers.insert("includes", new EndElementHandler(this,&TagFileParser::endIncludes));
737 m_endElementHandlers.insert("path", new EndElementHandler(this,&TagFileParser::endPath));
738 m_endElementHandlers.insert("anchorfile", new EndElementHandler(this,&TagFileParser::endAnchorFile));
739 m_endElementHandlers.insert("anchor", new EndElementHandler(this,&TagFileParser::endAnchor));
740 m_endElementHandlers.insert("arglist", new EndElementHandler(this,&TagFileParser::endArglist));
741 m_endElementHandlers.insert("title", new EndElementHandler(this,&TagFileParser::endTitle));
742 m_endElementHandlers.insert("subgroup", new EndElementHandler(this,&TagFileParser::endSubgroup));
743 m_endElementHandlers.insert("class" , new EndElementHandler(this,&TagFileParser::endClass));
744 m_endElementHandlers.insert("namespace", new EndElementHandler(this,&TagFileParser::endNamespace));
745 m_endElementHandlers.insert("file", new EndElementHandler(this,&TagFileParser::endFile));
746 m_endElementHandlers.insert("dir", new EndElementHandler(this,&TagFileParser::endDir));
747 m_endElementHandlers.insert("page", new EndElementHandler(this,&TagFileParser::endPage));
748 m_endElementHandlers.insert("docanchor", new EndElementHandler(this,&TagFileParser::endDocAnchor));
749 m_endElementHandlers.insert("tagfile", new EndElementHandler(this,&TagFileParser::endIgnoreElement));
750 m_endElementHandlers.insert("templarg", new EndElementHandler(this,&TagFileParser::endTemplateArg));
751 m_endElementHandlers.insert("type", new EndElementHandler(this,&TagFileParser::endType));
752
753 return TRUE;
754 }
755
756 bool startElement( const QString&, const QString&,
757 const QString&name, const QXmlAttributes& attrib )
758 {
759 //printf("startElement `%s'\n",name.data());
760 StartElementHandler *handler = m_startElementHandlers[name];
761 if (handler)
762 {
763 (*handler)(attrib);
764 }
765 else
766 {
767 warn("warning: Unknown tag `%s' found!\n",name.data());
768 }
769 return TRUE;
770 }
771
772 bool endElement( const QString&, const QString&, const QString& name )
773 {
774 //printf("endElement `%s'\n",name.data());
775 EndElementHandler *handler = m_endElementHandlers[name];
776 if (handler)
777 {
778 (*handler)();
779 }
780 else
781 {
782 warn("warning: Unknown tag `%s' found!\n",name.data());
783 }
784 return TRUE;
785 }
786
787 bool characters ( const QString & ch )
788 {
789 m_curString+=ch;
790 return TRUE;
791 }
792
793 void dump();
794 void buildLists(Entry *root);
795 void addIncludes();
796
797 private:
798 void buildMemberList(Entry *ce,QList<TagMemberInfo> &members);
799 void addDocAnchors(Entry *e,const TagAnchorInfoList &l);
800 QList<TagClassInfo> m_tagFileClasses;
801 QList<TagFileInfo> m_tagFileFiles;
802 QList<TagNamespaceInfo> m_tagFileNamespaces;
803 QList<TagGroupInfo> m_tagFileGroups;
804 QList<TagPageInfo> m_tagFilePages;
805 QList<TagPackageInfo> m_tagFilePackages;
806 QList<TagDirInfo> m_tagFileDirs;
807 QDict<StartElementHandler> m_startElementHandlers;
808 QDict<EndElementHandler> m_endElementHandlers;
809 TagClassInfo *m_curClass;
810 TagFileInfo *m_curFile;
811 TagNamespaceInfo *m_curNamespace;
812 TagPackageInfo *m_curPackage;
813 TagGroupInfo *m_curGroup;
814 TagPageInfo *m_curPage;
815 TagDirInfo *m_curDir;
816 TagMemberInfo *m_curMember;
817 TagIncludeInfo *m_curIncludes;
818 QCString m_curString;
819 QString m_tagName;
820 QString m_fileName;
821 State m_state;
822 QStack<State> m_stateStack;
823 QXmlLocator *m_locator;
824 QString m_inputFileName;
825};
826
827/*! Error handler for the XML tag file parser.
828 * Basically dumps all fatal error to stderr using err().
829 */
830class TagFileErrorHandler : public QXmlErrorHandler
831{
832 public:
833 virtual ~TagFileErrorHandler() {}
834 bool warning( const QXmlParseException & )
835 {
836 return FALSE;
837 }
838 bool error( const QXmlParseException & )
839 {
840 return FALSE;
841 }
842 bool fatalError( const QXmlParseException &exception )
843 {
844 err("Fatal error at line %d column %d: %s\n",
845 exception.lineNumber(),exception.columnNumber(),
846 exception.message().data());
847 return FALSE;
848 }
849 QString errorString() { return ""; }
850
851 private:
852 QString errorMsg;
853};
854
855/*! Dumps the internal structures. For debugging only! */
856void TagFileParser::dump()
857{
858 msg("Result:\n");
859 QListIterator<TagClassInfo> lci(m_tagFileClasses);
860
861 //============== CLASSES
862 TagClassInfo *cd;
863 for (;(cd=lci.current());++lci)
864 {
865 msg("class `%s'\n",cd->name.data());
866 msg(" filename `%s'\n",cd->filename.data());
867 if (cd->bases)
868 {
869 QListIterator<BaseInfo> bii(*cd->bases);
870 BaseInfo *bi;
871 for ( bii.toFirst() ; (bi=bii.current()) ; ++bii)
872 {
873 msg( " base: %s \n", bi->name.data() );
874 }
875 }
876
877 QListIterator<TagMemberInfo> mci(cd->members);
878 TagMemberInfo *md;
879 for (;(md=mci.current());++mci)
880 {
881 msg(" member:\n");
882 msg(" kind: `%s'\n",md->kind.data());
883 msg(" name: `%s'\n",md->name.data());
884 msg(" anchor: `%s'\n",md->anchor.data());
885 msg(" arglist: `%s'\n",md->arglist.data());
886 }
887 }
888 //============== NAMESPACES
889 QListIterator<TagNamespaceInfo> lni(m_tagFileNamespaces);
890 TagNamespaceInfo *nd;
891 for (;(nd=lni.current());++lni)
892 {
893 msg("namespace `%s'\n",nd->name.data());
894 msg(" filename `%s'\n",nd->filename.data());
895 QStringList::Iterator it;
896 for ( it = nd->classList.begin();
897 it != nd->classList.end(); ++it )
898 {
899 msg( " class: %s \n", (*it).latin1() );
900 }
901
902 QListIterator<TagMemberInfo> mci(nd->members);
903 TagMemberInfo *md;
904 for (;(md=mci.current());++mci)
905 {
906 msg(" member:\n");
907 msg(" kind: `%s'\n",md->kind.data());
908 msg(" name: `%s'\n",md->name.data());
909 msg(" anchor: `%s'\n",md->anchor.data());
910 msg(" arglist: `%s'\n",md->arglist.data());
911 }
912 }
913 //============== FILES
914 QListIterator<TagFileInfo> lfi(m_tagFileFiles);
915 TagFileInfo *fd;
916 for (;(fd=lfi.current());++lfi)
917 {
918 msg("file `%s'\n",fd->name.data());
919 msg(" filename `%s'\n",fd->filename.data());
920 QStringList::Iterator it;
921 for ( it = fd->namespaceList.begin();
922 it != fd->namespaceList.end(); ++it )
923 {
924 msg( " namespace: %s \n", (*it).latin1() );
925 }
926 for ( it = fd->classList.begin();
927 it != fd->classList.end(); ++it )
928 {
929 msg( " class: %s \n", (*it).latin1() );
930 }
931
932 QListIterator<TagMemberInfo> mci(fd->members);
933 TagMemberInfo *md;
934 for (;(md=mci.current());++mci)
935 {
936 msg(" member:\n");
937 msg(" kind: `%s'\n",md->kind.data());
938 msg(" name: `%s'\n",md->name.data());
939 msg(" anchor: `%s'\n",md->anchor.data());
940 msg(" arglist: `%s'\n",md->arglist.data());
941 }
942
943 QListIterator<TagIncludeInfo> mii(fd->includes);
944 TagIncludeInfo *ii;
945 for (;(ii=mii.current());++mii)
946 {
947 msg(" includes id: %s name: %s\n",ii->id.data(),ii->name.data());
948 }
949 }
950
951 //============== GROUPS
952 QListIterator<TagGroupInfo> lgi(m_tagFileGroups);
953 TagGroupInfo *gd;
954 for (;(gd=lgi.current());++lgi)
955 {
956 msg("group `%s'\n",gd->name.data());
957 msg(" filename `%s'\n",gd->filename.data());
958 QStringList::Iterator it;
959 for ( it = gd->namespaceList.begin();
960 it != gd->namespaceList.end(); ++it )
961 {
962 msg( " namespace: %s \n", (*it).latin1() );
963 }
964 for ( it = gd->classList.begin();
965 it != gd->classList.end(); ++it )
966 {
967 msg( " class: %s \n", (*it).latin1() );
968 }
969 for ( it = gd->fileList.begin();
970 it != gd->fileList.end(); ++it )
971 {
972 msg( " file: %s \n", (*it).latin1() );
973 }
974 for ( it = gd->subgroupList.begin();
975 it != gd->subgroupList.end(); ++it )
976 {
977 msg( " subgroup: %s \n", (*it).latin1() );
978 }
979 for ( it = gd->pageList.begin();
980 it != gd->pageList.end(); ++it )
981 {
982 msg( " page: %s \n", (*it).latin1() );
983 }
984
985 QListIterator<TagMemberInfo> mci(gd->members);
986 TagMemberInfo *md;
987 for (;(md=mci.current());++mci)
988 {
989 msg(" member:\n");
990 msg(" kind: `%s'\n",md->kind.data());
991 msg(" name: `%s'\n",md->name.data());
992 msg(" anchor: `%s'\n",md->anchor.data());
993 msg(" arglist: `%s'\n",md->arglist.data());
994 }
995 }
996 //============== PAGES
997 QListIterator<TagPageInfo> lpi(m_tagFilePages);
998 TagPageInfo *pd;
999 for (;(pd=lpi.current());++lpi)
1000 {
1001 msg("page `%s'\n",pd->name.data());
1002 msg(" title `%s'\n",pd->title.data());
1003 msg(" filename `%s'\n",pd->filename.data());
1004 }
1005 //============== DIRS
1006 QListIterator<TagDirInfo> ldi(m_tagFileDirs);
1007 TagDirInfo *dd;
1008 for (;(dd=ldi.current());++ldi)
1009 {
1010 msg("dir `%s'\n",dd->name.data());
1011 msg(" path `%s'\n",dd->path.data());
1012 QStringList::Iterator it;
1013 for ( it = dd->fileList.begin();
1014 it != dd->fileList.end(); ++it )
1015 {
1016 msg( " file: %s \n", (*it).latin1() );
1017 }
1018 for ( it = dd->subdirList.begin();
1019 it != dd->subdirList.end(); ++it )
1020 {
1021 msg( " subdir: %s \n", (*it).latin1() );
1022 }
1023 }
1024}
1025
1026void TagFileParser::addDocAnchors(Entry *e,const TagAnchorInfoList &l)
1027{
1028 QListIterator<TagAnchorInfo> tli(l);
1029 TagAnchorInfo *ta;
1030 for (tli.toFirst();(ta=tli.current());++tli)
1031 {
1032 if (Doxygen::sectionDict.find(ta->label)==0)
1033 {
1034 //printf("New sectionInfo file=%s anchor=%s\n",
1035 // ta->fileName.data(),ta->label.data());
1036 SectionInfo *si=new SectionInfo(ta->fileName,ta->label,ta->label,
1037 SectionInfo::Anchor,m_tagName);
1038 Doxygen::sectionDict.insert(ta->label,si);
1039 e->anchors->append(si);
1040 }
1041 else
1042 {
1043 warn("Duplicate anchor %s found\n",ta->label.data());
1044 }
1045 }
1046}
1047
1048void TagFileParser::buildMemberList(Entry *ce,QList<TagMemberInfo> &members)
1049{
1050 QListIterator<TagMemberInfo> mii(members);
1051 TagMemberInfo *tmi;
1052 for (;(tmi=mii.current());++mii)
1053 {
1054 Entry *me = new Entry;
1055 me->type = tmi->type;
1056 me->name = tmi->name;
1057 me->args = tmi->arglist;
1058 if (!me->args.isEmpty())
1059 {
1060 delete me->argList;
1061 me->argList = new ArgumentList;
1062 stringToArgumentList(me->args,me->argList);
1063 }
1064 me->protection = tmi->prot;
1065 me->virt = tmi->virt;
1066 me->stat = tmi->isStatic;
1067 me->fileName = ce->fileName;
1068 if (ce->section == Entry::GROUPDOC_SEC)
1069 {
1070 me->groups->append(new Grouping(ce->name,Grouping::GROUPING_INGROUP));
1071 }
1072 addDocAnchors(me,tmi->docAnchors);
1073 TagInfo *ti = new TagInfo;
1074 ti->tagName = m_tagName;
1075 ti->anchor = tmi->anchor;
1076 ti->fileName = tmi->anchorFile;
1077 me->tagInfo = ti;
1078 if (tmi->kind=="define")
1079 {
1080 me->type="#define";
1081 me->section = Entry::DEFINE_SEC;
1082 }
1083 else if (tmi->kind=="enumvalue")
1084 {
1085 me->section = Entry::VARIABLE_SEC;
1086 me->mtype = Method;
1087 }
1088 else if (tmi->kind=="property")
1089 {
1090 me->section = Entry::VARIABLE_SEC;
1091 me->mtype = Property;
1092 }
1093 else if (tmi->kind=="event")
1094 {
1095 me->section = Entry::VARIABLE_SEC;
1096 me->mtype = Event;
1097 }
1098 else if (tmi->kind=="variable")
1099 {
1100 me->section = Entry::VARIABLE_SEC;
1101 me->mtype = Method;
1102 }
1103 else if (tmi->kind=="typedef")
1104 {
1105 me->section = Entry::VARIABLE_SEC; //Entry::TYPEDEF_SEC;
1106 me->type.prepend("typedef ");
1107 me->mtype = Method;
1108 }
1109 else if (tmi->kind=="enumeration")
1110 {
1111 me->section = Entry::ENUM_SEC;
1112 me->mtype = Method;
1113 }
1114 else if (tmi->kind=="function")
1115 {
1116 me->section = Entry::FUNCTION_SEC;
1117 me->mtype = Method;
1118 }
1119 else if (tmi->kind=="signal")
1120 {
1121 me->section = Entry::FUNCTION_SEC;
1122 me->mtype = Signal;
1123 }
1124 else if (tmi->kind=="prototype")
1125 {
1126 me->section = Entry::FUNCTION_SEC;
1127 me->mtype = Method;
1128 }
1129 else if (tmi->kind=="friend")
1130 {
1131 me->section = Entry::FUNCTION_SEC;
1132 me->type.prepend("friend ");
1133 me->mtype = Method;
1134 }
1135 else if (tmi->kind=="dcop")
1136 {
1137 me->section = Entry::FUNCTION_SEC;
1138 me->mtype = DCOP;
1139 }
1140 else if (tmi->kind=="slot")
1141 {
1142 me->section = Entry::FUNCTION_SEC;
1143 me->mtype = Slot;
1144 }
1145 ce->addSubEntry(me);
1146 }
1147}
1148
1149static QString stripPath(const QString &s)
1150{
1151 int i=s.findRev('/');
1152 if (i!=-1)
1153 {
1154 return s.right(s.length()-i-1);
1155 }
1156 else
1157 {
1158 return s;
1159 }
1160}
1161
1162/*! Injects the info gathered by the XML parser into the Entry tree.
1163 * This tree contains the information extracted from the input in a
1164 * "unrelated" form.
1165 */
1166void TagFileParser::buildLists(Entry *root)
1167{
1168 // build class list
1169 TagClassInfo *tci = m_tagFileClasses.first();
1170 while (tci)
1171 {
1172 Entry *ce = new Entry;
1173 ce->section = Entry::CLASS_SEC;
1174 switch (tci->kind)
1175 {
1176 case TagClassInfo::Class: break;
1177 case TagClassInfo::Struct: ce->spec = Entry::Struct; break;
1178 case TagClassInfo::Union: ce->spec = Entry::Union; break;
1179 case TagClassInfo::Interface: ce->spec = Entry::Interface; break;
1180 case TagClassInfo::Exception: ce->spec = Entry::Exception; break;
1181 case TagClassInfo::Protocol: ce->spec = Entry::Protocol; break;
1182 case TagClassInfo::Category: ce->spec = Entry::Category; break;
1183 }
1184 ce->name = tci->name;
1185 if (tci->kind==TagClassInfo::Protocol)
1186 {
1187 ce->name+="-p";
1188 }
1189 addDocAnchors(ce,tci->docAnchors);
1190 TagInfo *ti = new TagInfo;
1191 ti->tagName = m_tagName;
1192 ti->fileName = tci->filename;
1193 ce->tagInfo = ti;
1194 ce->lang = tci->isObjC ? SrcLangExt_ObjC : SrcLangExt_Unknown;
1195 // transfer base class list
1196 if (tci->bases)
1197 {
1198 delete ce->extends;
1199 ce->extends = tci->bases; tci->bases = 0;
1200 }
1201 if (tci->templateArguments)
1202 {
1203 if (ce->tArgLists==0)
1204 {
1205 ce->tArgLists = new QList<ArgumentList>;
1206 ce->tArgLists->setAutoDelete(TRUE);
1207 }
1208 ArgumentList *al = new ArgumentList;
1209 ce->tArgLists->append(al);
1210
1211 QListIterator<QString> sli(*tci->templateArguments);
1212 QString *argName;
1213 for (;(argName=sli.current());++sli)
1214 {
1215 Argument *a = new Argument;
1216 a->type = "class";
1217 a->name = *argName;
1218 al->append(a);
1219 }
1220 }
1221
1222 buildMemberList(ce,tci->members);
1223 root->addSubEntry(ce);
1224 tci = m_tagFileClasses.next();
1225 }
1226
1227 // build file list
1228 TagFileInfo *tfi = m_tagFileFiles.first();
1229 while (tfi)
1230 {
1231 Entry *fe = new Entry;
1232 fe->section = guessSection(tfi->name);
1233 fe->name = tfi->name;
1234 addDocAnchors(fe,tfi->docAnchors);
1235 TagInfo *ti = new TagInfo;
1236 ti->tagName = m_tagName;
1237 ti->fileName = tfi->filename;
1238 fe->tagInfo = ti;
1239
1240 QString fullName = m_tagName+":"+tfi->path+stripPath(tfi->name);
1241 fe->fileName = fullName;
1242 //printf("new FileDef() filename=%s\n",tfi->filename.data());
1243 FileDef *fd = new FileDef(m_tagName+":"+tfi->path,
1244 tfi->name,m_tagName,
1245 tfi->filename
1246 );
1247 FileName *mn;
1248 if ((mn=Doxygen::inputNameDict->find(tfi->name)))
1249 {
1250 mn->append(fd);
1251 }
1252 else
1253 {
1254 mn = new FileName(fullName,tfi->name);
1255 mn->append(fd);
1256 Doxygen::inputNameList->inSort(mn);
1257 Doxygen::inputNameDict->insert(tfi->name,mn);
1258 }
1259 buildMemberList(fe,tfi->members);
1260 root->addSubEntry(fe);
1261 tfi = m_tagFileFiles.next();
1262 }
1263
1264 // build namespace list
1265 TagNamespaceInfo *tni = m_tagFileNamespaces.first();
1266 while (tni)
1267 {
1268 Entry *ne = new Entry;
1269 ne->section = Entry::NAMESPACE_SEC;
1270 ne->name = tni->name;
1271 addDocAnchors(ne,tni->docAnchors);
1272 TagInfo *ti = new TagInfo;
1273 ti->tagName = m_tagName;
1274 ti->fileName = tni->filename;
1275 ne->tagInfo = ti;
1276
1277 buildMemberList(ne,tni->members);
1278 root->addSubEntry(ne);
1279 tni = m_tagFileNamespaces.next();
1280 }
1281
1282 // build package list
1283 TagPackageInfo *tpgi = m_tagFilePackages.first();
1284 while (tpgi)
1285 {
1286 Entry *pe = new Entry;
1287 pe->section = Entry::PACKAGE_SEC;
1288 pe->name = tpgi->name;
1289 addDocAnchors(pe,tpgi->docAnchors);
1290 TagInfo *ti = new TagInfo;
1291 ti->tagName = m_tagName;
1292 ti->fileName = tpgi->filename;
1293 pe->tagInfo = ti;
1294
1295 buildMemberList(pe,tpgi->members);
1296 root->addSubEntry(pe);
1297 tpgi = m_tagFilePackages.next();
1298 }
1299
1300 // build group list, but only if config file says to include it
1301 //if (Config_getBool("EXTERNAL_GROUPS"))
1302 //{
1303 TagGroupInfo *tgi = m_tagFileGroups.first();
1304 while (tgi)
1305 {
1306 Entry *ge = new Entry;
1307 ge->section = Entry::GROUPDOC_SEC;
1308 ge->name = tgi->name;
1309 ge->type = tgi->title;
1310 addDocAnchors(ge,tgi->docAnchors);
1311 TagInfo *ti = new TagInfo;
1312 ti->tagName = m_tagName;
1313 ti->fileName = tgi->filename;
1314 ge->tagInfo = ti;
1315
1316 buildMemberList(ge,tgi->members);
1317 root->addSubEntry(ge);
1318 tgi = m_tagFileGroups.next();
1319 }
1320 //}
1321
1322 // build page list
1323 TagPageInfo *tpi = m_tagFilePages.first();
1324 while (tpi)
1325 {
1326 Entry *pe = new Entry;
1327 pe->section = Entry::PAGEDOC_SEC;
1328 pe->name = tpi->name;
1329 pe->args = tpi->title;
1330 addDocAnchors(pe,tpi->docAnchors);
1331 TagInfo *ti = new TagInfo;
1332 ti->tagName = m_tagName;
1333 ti->fileName = tpi->filename;
1334 pe->tagInfo = ti;
1335
1336 root->addSubEntry(pe);
1337 tpi = m_tagFilePages.next();
1338 }
1339}
1340
1341void TagFileParser::addIncludes()
1342{
1343 TagFileInfo *tfi = m_tagFileFiles.first();
1344 while (tfi)
1345 {
1346 //printf("tag file tagName=%s path=%s name=%s\n",m_tagName.data(),tfi->path.data(),tfi->name.data());
1347 FileName *fn = Doxygen::inputNameDict->find(tfi->name);
1348 if (fn)
1349 {
1350 //printf("found\n");
1351 FileNameIterator fni(*fn);
1352 FileDef *fd;
1353 for (;(fd=fni.current());++fni)
1354 {
1355 //printf("input file path=%s name=%s\n",fd->getPath().data(),fd->name().data());
1356 if (fd->getPath()==QCString(m_tagName+":"+tfi->path))
1357 {
1358 //printf("found\n");
1359 QListIterator<TagIncludeInfo> mii(tfi->includes);
1360 TagIncludeInfo *ii;
1361 for (;(ii=mii.current());++mii)
1362 {
1363 //printf("ii->name=`%s'\n",ii->name.data());
1364 FileName *ifn = Doxygen::inputNameDict->find(ii->name);
1365 ASSERT(ifn!=0);
1366 if (ifn)
1367 {
1368 FileNameIterator ifni(*ifn);
1369 FileDef *ifd;
1370 for (;(ifd=ifni.current());++ifni)
1371 {
1372 //printf("ifd->getOutputFileBase()=%s ii->id=%s\n",
1373 // ifd->getOutputFileBase().data(),ii->id.data());
1374 if (ifd->getOutputFileBase()==QCString(ii->id))
1375 {
1376 fd->addIncludeDependency(ifd,ii->text,ii->isLocal,ii->isImported);
1377 }
1378 }
1379 }
1380 }
1381 }
1382 }
1383 }
1384 tfi = m_tagFileFiles.next();
1385 }
1386}
1387
1388void parseTagFile(Entry *root,const char *fullName,const char *tagName)
1389{
1390 QFileInfo fi(fullName);
1391 if (!fi.exists()) return;
1392 TagFileParser handler( tagName );
1393 handler.setFileName(fullName);
1394 TagFileErrorHandler errorHandler;
1395 QFile xmlFile( fullName );
1396 QXmlInputSource source( xmlFile );
1397 QXmlSimpleReader reader;
1398 reader.setContentHandler( &handler );
1399 reader.setErrorHandler( &errorHandler );
1400 reader.parse( source );
1401 handler.buildLists(root);
1402 handler.addIncludes();
1403 //handler.dump();
1404}
1405
1406
1407

Archive Download this file

Revision: 1322