1 /******************************************************************************
6 * Copyright (C) 1997-2015 by Dimitri van Heesch.
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.
14 * Documents produced by Doxygen are derivative works derived from the
15 * input used in their production; they are not affected by this license.
19 #include "tagreader.h"
27 #include <qfileinfo.h>
30 #include <qstringlist.h>
38 #include "arguments.h"
43 /** Information about an linkable anchor */
47 TagAnchorInfo(const QCString &f,
49 const QCString &t=QCString())
50 : label(l), fileName(f), title(t) {}
56 /** List of TagAnchorInfo objects. */
57 class TagAnchorInfoList : public QList<TagAnchorInfo>
60 TagAnchorInfoList() : QList<TagAnchorInfo>() { setAutoDelete(TRUE); }
61 virtual ~TagAnchorInfoList() {}
64 /** Container for enum values that are scoped within an enum */
65 class TagEnumValueInfo
74 /** Container for member specific info that can be read from a tagfile */
78 TagMemberInfo() : prot(Public), virt(Normal), isStatic(FALSE)
79 { enumValues.setAutoDelete(TRUE); }
87 TagAnchorInfoList docAnchors;
91 QList<TagEnumValueInfo> enumValues;
94 /** Container for class specific info that can be read from a tagfile */
98 enum Kind { Class, Struct, Union, Interface, Exception, Protocol, Category, Enum, Service, Singleton };
99 TagClassInfo() { bases=0, templateArguments=0; members.setAutoDelete(TRUE); isObjC=FALSE; }
100 ~TagClassInfo() { delete bases; delete templateArguments; }
104 TagAnchorInfoList docAnchors;
105 QList<BaseInfo> *bases;
106 QList<TagMemberInfo> members;
107 QList<QCString> *templateArguments;
108 QStringList classList;
113 /** Container for namespace specific info that can be read from a tagfile */
114 class TagNamespaceInfo
117 TagNamespaceInfo() { members.setAutoDelete(TRUE); }
121 QStringList classList;
122 QStringList namespaceList;
123 TagAnchorInfoList docAnchors;
124 QList<TagMemberInfo> members;
127 /** Container for package specific info that can be read from a tagfile */
131 TagPackageInfo() { members.setAutoDelete(TRUE); }
134 TagAnchorInfoList docAnchors;
135 QList<TagMemberInfo> members;
136 QStringList classList;
139 /** Container for include info that can be read from a tagfile */
150 /** Container for file specific info that can be read from a tagfile */
154 TagFileInfo() { members.setAutoDelete(TRUE); includes.setAutoDelete(TRUE); }
158 TagAnchorInfoList docAnchors;
159 QList<TagMemberInfo> members;
160 QStringList classList;
161 QStringList namespaceList;
162 QList<TagIncludeInfo> includes;
165 /** Container for group specific info that can be read from a tagfile */
169 TagGroupInfo() { members.setAutoDelete(TRUE); }
173 TagAnchorInfoList docAnchors;
174 QList<TagMemberInfo> members;
175 QStringList subgroupList;
176 QStringList classList;
177 QStringList namespaceList;
178 QStringList fileList;
179 QStringList pageList;
183 /** Container for page specific info that can be read from a tagfile */
190 TagAnchorInfoList docAnchors;
193 /** Container for directory specific info that can be read from a tagfile */
200 QStringList subdirList;
201 QStringList fileList;
202 TagAnchorInfoList docAnchors;
207 * Reads an XML-structured tagfile and builds up the structure in
208 * memory. The method buildLists() is used to transfer/translate
209 * the structures to the doxygen engine.
211 class TagFileParser : public QXmlDefaultHandler
213 enum State { Invalid,
225 class StartElementHandler
227 typedef void (TagFileParser::*Handler)(const QXmlAttributes &attrib);
229 StartElementHandler(TagFileParser *parent, Handler h) : m_parent(parent), m_handler(h) {}
230 void operator()(const QXmlAttributes &attrib) { (m_parent->*m_handler)(attrib); }
232 TagFileParser *m_parent;
236 class EndElementHandler
238 typedef void (TagFileParser::*Handler)();
240 EndElementHandler(TagFileParser *parent, Handler h) : m_parent(parent), m_handler(h) {}
241 void operator()() { (m_parent->*m_handler)(); }
243 TagFileParser *m_parent;
248 TagFileParser(const char *tagName) : m_startElementHandlers(17),
249 m_endElementHandlers(17),
252 m_startElementHandlers.setAutoDelete(TRUE);
253 m_endElementHandlers.setAutoDelete(TRUE);
268 void setDocumentLocator ( QXmlLocator * locator )
273 void setFileName( const QString &fileName )
275 m_inputFileName = fileName.utf8();
278 void warn(const char *fmt)
280 ::warn(m_inputFileName,m_locator->lineNumber(),fmt);
282 void warn(const char *fmt,const char *s)
284 ::warn(m_inputFileName,m_locator->lineNumber(),fmt,s);
287 void startCompound( const QXmlAttributes& attrib )
290 QString kind = attrib.value("kind");
291 QString isObjC = attrib.value("objc");
294 m_curClass = new TagClassInfo;
295 m_curClass->kind = TagClassInfo::Class;
298 else if (kind=="struct")
300 m_curClass = new TagClassInfo;
301 m_curClass->kind = TagClassInfo::Struct;
304 else if (kind=="union")
306 m_curClass = new TagClassInfo;
307 m_curClass->kind = TagClassInfo::Union;
310 else if (kind=="interface")
312 m_curClass = new TagClassInfo;
313 m_curClass->kind = TagClassInfo::Interface;
316 else if (kind=="enum")
318 m_curClass = new TagClassInfo;
319 m_curClass->kind = TagClassInfo::Enum;
322 else if (kind=="exception")
324 m_curClass = new TagClassInfo;
325 m_curClass->kind = TagClassInfo::Exception;
328 else if (kind=="protocol")
330 m_curClass = new TagClassInfo;
331 m_curClass->kind = TagClassInfo::Protocol;
334 else if (kind=="category")
336 m_curClass = new TagClassInfo;
337 m_curClass->kind = TagClassInfo::Category;
340 else if (kind=="service")
342 m_curClass = new TagClassInfo;
343 m_curClass->kind = TagClassInfo::Service;
346 else if (kind=="singleton")
348 m_curClass = new TagClassInfo;
349 m_curClass->kind = TagClassInfo::Singleton;
352 else if (kind=="file")
354 m_curFile = new TagFileInfo;
357 else if (kind=="namespace")
359 m_curNamespace = new TagNamespaceInfo;
360 m_state = InNamespace;
362 else if (kind=="group")
364 m_curGroup = new TagGroupInfo;
367 else if (kind=="page")
369 m_curPage = new TagPageInfo;
372 else if (kind=="package")
374 m_curPackage = new TagPackageInfo;
377 else if (kind=="dir")
379 m_curDir = new TagDirInfo;
384 warn("Unknown compound attribute `%s' found!\n",kind.data());
387 if (isObjC=="yes" && m_curClass)
389 m_curClass->isObjC = TRUE;
397 case InClass: m_tagFileClasses.append(m_curClass);
399 case InFile: m_tagFileFiles.append(m_curFile);
401 case InNamespace: m_tagFileNamespaces.append(m_curNamespace);
402 m_curNamespace=0; break;
403 case InGroup: m_tagFileGroups.append(m_curGroup);
405 case InPage: m_tagFilePages.append(m_curPage);
407 case InDir: m_tagFileDirs.append(m_curDir);
409 case InPackage: m_tagFilePackages.append(m_curPackage);
410 m_curPackage=0; break;
412 warn("tag `compound' was not expected!\n");
416 void startMember( const QXmlAttributes& attrib)
418 m_curMember = new TagMemberInfo;
419 m_curMember->kind = attrib.value("kind").utf8();
420 QCString protStr = attrib.value("protection").utf8();
421 QCString virtStr = attrib.value("virtualness").utf8();
422 QCString staticStr = attrib.value("static").utf8();
423 if (protStr=="protected")
425 m_curMember->prot = Protected;
427 else if (protStr=="private")
429 m_curMember->prot = Private;
431 if (virtStr=="virtual")
433 m_curMember->virt = Virtual;
435 else if (virtStr=="pure")
437 m_curMember->virt = Pure;
439 if (staticStr=="yes")
441 m_curMember->isStatic = TRUE;
443 m_stateStack.push(new State(m_state));
449 m_state = *m_stateStack.top();
450 m_stateStack.remove();
453 case InClass: m_curClass->members.append(m_curMember); break;
454 case InFile: m_curFile->members.append(m_curMember); break;
455 case InNamespace: m_curNamespace->members.append(m_curMember); break;
456 case InGroup: m_curGroup->members.append(m_curMember); break;
457 case InPackage: m_curPackage->members.append(m_curMember); break;
458 default: warn("Unexpected tag `member' found\n"); break;
462 void startEnumValue( const QXmlAttributes& attrib)
464 if (m_state==InMember)
467 m_curEnumValue = new TagEnumValueInfo;
468 m_curEnumValue->file = attrib.value("file").utf8();
469 m_curEnumValue->anchor = attrib.value("anchor").utf8();
470 m_curEnumValue->clangid = attrib.value("clangid").utf8();
471 m_stateStack.push(new State(m_state));
472 m_state = InEnumValue;
476 warn("Found enumvalue tag outside of member tag\n");
482 m_curEnumValue->name = m_curString.stripWhiteSpace();
483 m_state = *m_stateStack.top();
484 m_stateStack.remove();
485 if (m_state==InMember)
487 m_curMember->enumValues.append(m_curEnumValue);
496 case InClass: m_curClass->docAnchors.append(new TagAnchorInfo(m_fileName,m_curString,m_title)); break;
497 case InFile: m_curFile->docAnchors.append(new TagAnchorInfo(m_fileName,m_curString,m_title)); break;
498 case InNamespace: m_curNamespace->docAnchors.append(new TagAnchorInfo(m_fileName,m_curString,m_title)); break;
499 case InGroup: m_curGroup->docAnchors.append(new TagAnchorInfo(m_fileName,m_curString,m_title)); break;
500 case InPage: m_curPage->docAnchors.append(new TagAnchorInfo(m_fileName,m_curString,m_title)); break;
501 case InMember: m_curMember->docAnchors.append(new TagAnchorInfo(m_fileName,m_curString,m_title)); break;
502 case InPackage: m_curPackage->docAnchors.append(new TagAnchorInfo(m_fileName,m_curString,m_title)); break;
503 case InDir: m_curDir->docAnchors.append(new TagAnchorInfo(m_fileName,m_curString,m_title)); break;
504 default: warn("Unexpected tag `member' found\n"); break;
512 case InClass: m_curClass->classList.append(m_curString); break;
513 case InFile: m_curFile->classList.append(m_curString); break;
514 case InNamespace: m_curNamespace->classList.append(m_curString); break;
515 case InGroup: m_curGroup->classList.append(m_curString); break;
516 case InPackage: m_curPackage->classList.append(m_curString); break;
517 default: warn("Unexpected tag `class' found\n"); break;
525 case InNamespace: m_curNamespace->classList.append(m_curString); break;
526 case InFile: m_curFile->namespaceList.append(m_curString); break;
527 case InGroup: m_curGroup->namespaceList.append(m_curString); break;
528 default: warn("Unexpected tag `namespace' found\n"); break;
536 case InGroup: m_curGroup->fileList.append(m_curString); break;
537 case InDir: m_curDir->fileList.append(m_curString); break;
538 default: warn("Unexpected tag `file' found\n"); break;
546 case InGroup: m_curGroup->fileList.append(m_curString); break;
547 default: warn("Unexpected tag `page' found\n"); break;
555 case InDir: m_curDir->subdirList.append(m_curString); break;
556 default: warn("Unexpected tag `page' found\n"); break;
560 void startStringValue(const QXmlAttributes& )
565 void startDocAnchor(const QXmlAttributes& attrib )
567 m_fileName = attrib.value("file").utf8();
568 m_title = attrib.value("title").utf8();
574 if (m_state==InMember)
576 m_curMember->type = m_curString;
580 warn("Unexpected tag `type' found\n");
588 case InClass: m_curClass->name = m_curString; break;
589 case InFile: m_curFile->name = m_curString; break;
590 case InNamespace: m_curNamespace->name = m_curString; break;
591 case InGroup: m_curGroup->name = m_curString; break;
592 case InPage: m_curPage->name = m_curString; break;
593 case InDir: m_curDir->name = m_curString; break;
594 case InMember: m_curMember->name = m_curString; break;
595 case InPackage: m_curPackage->name = m_curString; break;
596 default: warn("Unexpected tag `name' found\n"); break;
600 void startBase(const QXmlAttributes& attrib )
603 if (m_state==InClass && m_curClass)
605 QString protStr = attrib.value("protection");
606 QString virtStr = attrib.value("virtualness");
607 Protection prot = Public;
608 Specifier virt = Normal;
609 if (protStr=="protected")
613 else if (protStr=="private")
617 if (virtStr=="virtual")
621 if (m_curClass->bases==0)
623 m_curClass->bases = new QList<BaseInfo>;
624 m_curClass->bases->setAutoDelete(TRUE);
626 m_curClass->bases->append(new BaseInfo(m_curString,prot,virt));
630 warn("Unexpected tag `base' found\n");
636 if (m_state==InClass && m_curClass)
638 m_curClass->bases->getLast()->name = m_curString;
642 warn("Unexpected tag `base' found\n");
646 void startIncludes(const QXmlAttributes& attrib )
648 if (m_state==InFile && m_curFile)
650 m_curIncludes = new TagIncludeInfo;
651 m_curIncludes->id = attrib.value("id").utf8();
652 m_curIncludes->name = attrib.value("name").utf8();
653 m_curIncludes->isLocal = attrib.value("local").utf8()=="yes" ? TRUE : FALSE;
654 m_curIncludes->isImported = attrib.value("imported").utf8()=="yes" ? TRUE : FALSE;
655 m_curFile->includes.append(m_curIncludes);
659 warn("Unexpected tag `includes' found\n");
666 m_curIncludes->text = m_curString;
669 void endTemplateArg()
671 if (m_state==InClass && m_curClass)
673 if (m_curClass->templateArguments==0)
675 m_curClass->templateArguments = new QList<QCString>;
676 m_curClass->templateArguments->setAutoDelete(TRUE);
678 m_curClass->templateArguments->append(new QCString(m_curString));
682 warn("Unexpected tag `templarg' found\n");
690 case InClass: m_curClass->filename = m_curString; break;
691 case InNamespace: m_curNamespace->filename = m_curString; break;
692 case InFile: m_curFile->filename = m_curString; break;
693 case InGroup: m_curGroup->filename = m_curString; break;
694 case InPage: m_curPage->filename = m_curString; break;
695 case InPackage: m_curPackage->filename = m_curString; break;
696 case InDir: m_curDir->filename = m_curString; break;
697 default: warn("Unexpected tag `filename' found\n"); break;
705 case InFile: m_curFile->path = m_curString; break;
706 case InDir: m_curDir->path = m_curString; break;
707 default: warn("Unexpected tag `path' found\n"); break;
713 if (m_state==InMember)
715 m_curMember->anchor = m_curString;
719 warn("Unexpected tag `anchor' found\n");
725 if (m_state==InMember)
727 m_curMember->clangId = m_curString;
729 else if (m_state==InClass)
731 m_curClass->clangId = m_curString;
733 else if (m_state==InNamespace)
735 m_curNamespace->clangId = m_curString;
739 warn("warning: Unexpected tag `anchor' found\n");
747 if (m_state==InMember)
749 m_curMember->anchorFile = m_curString;
753 warn("Unexpected tag `anchorfile' found\n");
759 if (m_state==InMember)
761 m_curMember->arglist = m_curString;
765 warn("Unexpected tag `arglist' found\n");
772 case InGroup: m_curGroup->title = m_curString; break;
773 case InPage: m_curPage->title = m_curString; break;
774 default: warn("Unexpected tag `title' found\n"); break;
780 if (m_state==InGroup)
782 m_curGroup->subgroupList.append(m_curString);
786 warn("Unexpected tag `subgroup' found\n");
790 void startIgnoreElement(const QXmlAttributes& )
794 void endIgnoreElement()
810 m_stateStack.setAutoDelete(TRUE);
811 m_tagFileClasses.setAutoDelete(TRUE);
812 m_tagFileFiles.setAutoDelete(TRUE);
813 m_tagFileNamespaces.setAutoDelete(TRUE);
814 m_tagFileGroups.setAutoDelete(TRUE);
815 m_tagFilePages.setAutoDelete(TRUE);
816 m_tagFilePackages.setAutoDelete(TRUE);
817 m_tagFileDirs.setAutoDelete(TRUE);
819 m_startElementHandlers.insert("compound", new StartElementHandler(this,&TagFileParser::startCompound));
820 m_startElementHandlers.insert("member", new StartElementHandler(this,&TagFileParser::startMember));
821 m_startElementHandlers.insert("enumvalue", new StartElementHandler(this,&TagFileParser::startEnumValue));
822 m_startElementHandlers.insert("name", new StartElementHandler(this,&TagFileParser::startStringValue));
823 m_startElementHandlers.insert("base", new StartElementHandler(this,&TagFileParser::startBase));
824 m_startElementHandlers.insert("filename", new StartElementHandler(this,&TagFileParser::startStringValue));
825 m_startElementHandlers.insert("includes", new StartElementHandler(this,&TagFileParser::startIncludes));
826 m_startElementHandlers.insert("path", new StartElementHandler(this,&TagFileParser::startStringValue));
827 m_startElementHandlers.insert("anchorfile", new StartElementHandler(this,&TagFileParser::startStringValue));
828 m_startElementHandlers.insert("anchor", new StartElementHandler(this,&TagFileParser::startStringValue));
829 m_startElementHandlers.insert("clangid", new StartElementHandler(this,&TagFileParser::startStringValue));
830 m_startElementHandlers.insert("arglist", new StartElementHandler(this,&TagFileParser::startStringValue));
831 m_startElementHandlers.insert("title", new StartElementHandler(this,&TagFileParser::startStringValue));
832 m_startElementHandlers.insert("subgroup", new StartElementHandler(this,&TagFileParser::startStringValue));
833 m_startElementHandlers.insert("class", new StartElementHandler(this,&TagFileParser::startStringValue));
834 m_startElementHandlers.insert("namespace", new StartElementHandler(this,&TagFileParser::startStringValue));
835 m_startElementHandlers.insert("file", new StartElementHandler(this,&TagFileParser::startStringValue));
836 m_startElementHandlers.insert("dir", new StartElementHandler(this,&TagFileParser::startStringValue));
837 m_startElementHandlers.insert("page", new StartElementHandler(this,&TagFileParser::startStringValue));
838 m_startElementHandlers.insert("docanchor", new StartElementHandler(this,&TagFileParser::startDocAnchor));
839 m_startElementHandlers.insert("tagfile", new StartElementHandler(this,&TagFileParser::startIgnoreElement));
840 m_startElementHandlers.insert("templarg", new StartElementHandler(this,&TagFileParser::startStringValue));
841 m_startElementHandlers.insert("type", new StartElementHandler(this,&TagFileParser::startStringValue));
843 m_endElementHandlers.insert("compound", new EndElementHandler(this,&TagFileParser::endCompound));
844 m_endElementHandlers.insert("member", new EndElementHandler(this,&TagFileParser::endMember));
845 m_endElementHandlers.insert("enumvalue", new EndElementHandler(this,&TagFileParser::endEnumValue));
846 m_endElementHandlers.insert("name", new EndElementHandler(this,&TagFileParser::endName));
847 m_endElementHandlers.insert("base", new EndElementHandler(this,&TagFileParser::endBase));
848 m_endElementHandlers.insert("filename", new EndElementHandler(this,&TagFileParser::endFilename));
849 m_endElementHandlers.insert("includes", new EndElementHandler(this,&TagFileParser::endIncludes));
850 m_endElementHandlers.insert("path", new EndElementHandler(this,&TagFileParser::endPath));
851 m_endElementHandlers.insert("anchorfile", new EndElementHandler(this,&TagFileParser::endAnchorFile));
852 m_endElementHandlers.insert("anchor", new EndElementHandler(this,&TagFileParser::endAnchor));
853 m_endElementHandlers.insert("clangid", new EndElementHandler(this,&TagFileParser::endClangId));
854 m_endElementHandlers.insert("arglist", new EndElementHandler(this,&TagFileParser::endArglist));
855 m_endElementHandlers.insert("title", new EndElementHandler(this,&TagFileParser::endTitle));
856 m_endElementHandlers.insert("subgroup", new EndElementHandler(this,&TagFileParser::endSubgroup));
857 m_endElementHandlers.insert("class" , new EndElementHandler(this,&TagFileParser::endClass));
858 m_endElementHandlers.insert("namespace", new EndElementHandler(this,&TagFileParser::endNamespace));
859 m_endElementHandlers.insert("file", new EndElementHandler(this,&TagFileParser::endFile));
860 m_endElementHandlers.insert("dir", new EndElementHandler(this,&TagFileParser::endDir));
861 m_endElementHandlers.insert("page", new EndElementHandler(this,&TagFileParser::endPage));
862 m_endElementHandlers.insert("docanchor", new EndElementHandler(this,&TagFileParser::endDocAnchor));
863 m_endElementHandlers.insert("tagfile", new EndElementHandler(this,&TagFileParser::endIgnoreElement));
864 m_endElementHandlers.insert("templarg", new EndElementHandler(this,&TagFileParser::endTemplateArg));
865 m_endElementHandlers.insert("type", new EndElementHandler(this,&TagFileParser::endType));
870 bool startElement( const QString&, const QString&,
871 const QString&name, const QXmlAttributes& attrib )
873 //printf("startElement `%s'\n",name.data());
874 StartElementHandler *handler = m_startElementHandlers[name.utf8()];
881 warn("Unknown tag `%s' found!\n",name.data());
886 bool endElement( const QString&, const QString&, const QString& name )
888 //printf("endElement `%s'\n",name.data());
889 EndElementHandler *handler = m_endElementHandlers[name.utf8()];
896 warn("Unknown tag `%s' found!\n",name.data());
901 bool characters ( const QString & ch )
903 m_curString+=ch.utf8();
908 void buildLists(Entry *root);
912 void buildMemberList(Entry *ce,QList<TagMemberInfo> &members);
913 void addDocAnchors(Entry *e,const TagAnchorInfoList &l);
914 QList<TagClassInfo> m_tagFileClasses;
915 QList<TagFileInfo> m_tagFileFiles;
916 QList<TagNamespaceInfo> m_tagFileNamespaces;
917 QList<TagGroupInfo> m_tagFileGroups;
918 QList<TagPageInfo> m_tagFilePages;
919 QList<TagPackageInfo> m_tagFilePackages;
920 QList<TagDirInfo> m_tagFileDirs;
921 QDict<StartElementHandler> m_startElementHandlers;
922 QDict<EndElementHandler> m_endElementHandlers;
923 TagClassInfo *m_curClass;
924 TagFileInfo *m_curFile;
925 TagNamespaceInfo *m_curNamespace;
926 TagPackageInfo *m_curPackage;
927 TagGroupInfo *m_curGroup;
928 TagPageInfo *m_curPage;
929 TagDirInfo *m_curDir;
930 TagMemberInfo *m_curMember;
931 TagEnumValueInfo *m_curEnumValue;
932 TagIncludeInfo *m_curIncludes;
933 QCString m_curString;
938 QStack<State> m_stateStack;
939 QXmlLocator *m_locator;
940 QCString m_inputFileName;
943 /** Error handler for the XML tag file parser.
945 * Basically dumps all fatal error to stderr using err().
947 class TagFileErrorHandler : public QXmlErrorHandler
950 virtual ~TagFileErrorHandler() {}
951 bool warning( const QXmlParseException & )
955 bool error( const QXmlParseException & )
959 bool fatalError( const QXmlParseException &exception )
961 err("Fatal error at line %d column %d: %s\n",
962 exception.lineNumber(),exception.columnNumber(),
963 exception.message().data());
966 QString errorString() { return ""; }
972 /*! Dumps the internal structures. For debugging only! */
973 void TagFileParser::dump()
976 QListIterator<TagClassInfo> lci(m_tagFileClasses);
978 //============== CLASSES
980 for (;(cd=lci.current());++lci)
982 msg("class `%s'\n",cd->name.data());
983 msg(" filename `%s'\n",cd->filename.data());
986 QListIterator<BaseInfo> bii(*cd->bases);
988 for ( bii.toFirst() ; (bi=bii.current()) ; ++bii)
990 msg( " base: %s \n", bi->name.data() );
994 QListIterator<TagMemberInfo> mci(cd->members);
996 for (;(md=mci.current());++mci)
999 msg(" kind: `%s'\n",md->kind.data());
1000 msg(" name: `%s'\n",md->name.data());
1001 msg(" anchor: `%s'\n",md->anchor.data());
1002 msg(" arglist: `%s'\n",md->arglist.data());
1005 //============== NAMESPACES
1006 QListIterator<TagNamespaceInfo> lni(m_tagFileNamespaces);
1007 TagNamespaceInfo *nd;
1008 for (;(nd=lni.current());++lni)
1010 msg("namespace `%s'\n",nd->name.data());
1011 msg(" filename `%s'\n",nd->filename.data());
1012 QStringList::Iterator it;
1013 for ( it = nd->classList.begin();
1014 it != nd->classList.end(); ++it )
1016 msg( " class: %s \n", (*it).latin1() );
1019 QListIterator<TagMemberInfo> mci(nd->members);
1021 for (;(md=mci.current());++mci)
1024 msg(" kind: `%s'\n",md->kind.data());
1025 msg(" name: `%s'\n",md->name.data());
1026 msg(" anchor: `%s'\n",md->anchor.data());
1027 msg(" arglist: `%s'\n",md->arglist.data());
1030 //============== FILES
1031 QListIterator<TagFileInfo> lfi(m_tagFileFiles);
1033 for (;(fd=lfi.current());++lfi)
1035 msg("file `%s'\n",fd->name.data());
1036 msg(" filename `%s'\n",fd->filename.data());
1037 QStringList::Iterator it;
1038 for ( it = fd->namespaceList.begin();
1039 it != fd->namespaceList.end(); ++it )
1041 msg( " namespace: %s \n", (*it).latin1() );
1043 for ( it = fd->classList.begin();
1044 it != fd->classList.end(); ++it )
1046 msg( " class: %s \n", (*it).latin1() );
1049 QListIterator<TagMemberInfo> mci(fd->members);
1051 for (;(md=mci.current());++mci)
1054 msg(" kind: `%s'\n",md->kind.data());
1055 msg(" name: `%s'\n",md->name.data());
1056 msg(" anchor: `%s'\n",md->anchor.data());
1057 msg(" arglist: `%s'\n",md->arglist.data());
1060 QListIterator<TagIncludeInfo> mii(fd->includes);
1062 for (;(ii=mii.current());++mii)
1064 msg(" includes id: %s name: %s\n",ii->id.data(),ii->name.data());
1068 //============== GROUPS
1069 QListIterator<TagGroupInfo> lgi(m_tagFileGroups);
1071 for (;(gd=lgi.current());++lgi)
1073 msg("group `%s'\n",gd->name.data());
1074 msg(" filename `%s'\n",gd->filename.data());
1075 QStringList::Iterator it;
1076 for ( it = gd->namespaceList.begin();
1077 it != gd->namespaceList.end(); ++it )
1079 msg( " namespace: %s \n", (*it).latin1() );
1081 for ( it = gd->classList.begin();
1082 it != gd->classList.end(); ++it )
1084 msg( " class: %s \n", (*it).latin1() );
1086 for ( it = gd->fileList.begin();
1087 it != gd->fileList.end(); ++it )
1089 msg( " file: %s \n", (*it).latin1() );
1091 for ( it = gd->subgroupList.begin();
1092 it != gd->subgroupList.end(); ++it )
1094 msg( " subgroup: %s \n", (*it).latin1() );
1096 for ( it = gd->pageList.begin();
1097 it != gd->pageList.end(); ++it )
1099 msg( " page: %s \n", (*it).latin1() );
1102 QListIterator<TagMemberInfo> mci(gd->members);
1104 for (;(md=mci.current());++mci)
1107 msg(" kind: `%s'\n",md->kind.data());
1108 msg(" name: `%s'\n",md->name.data());
1109 msg(" anchor: `%s'\n",md->anchor.data());
1110 msg(" arglist: `%s'\n",md->arglist.data());
1113 //============== PAGES
1114 QListIterator<TagPageInfo> lpi(m_tagFilePages);
1116 for (;(pd=lpi.current());++lpi)
1118 msg("page `%s'\n",pd->name.data());
1119 msg(" title `%s'\n",pd->title.data());
1120 msg(" filename `%s'\n",pd->filename.data());
1122 //============== DIRS
1123 QListIterator<TagDirInfo> ldi(m_tagFileDirs);
1125 for (;(dd=ldi.current());++ldi)
1127 msg("dir `%s'\n",dd->name.data());
1128 msg(" path `%s'\n",dd->path.data());
1129 QStringList::Iterator it;
1130 for ( it = dd->fileList.begin();
1131 it != dd->fileList.end(); ++it )
1133 msg( " file: %s \n", (*it).latin1() );
1135 for ( it = dd->subdirList.begin();
1136 it != dd->subdirList.end(); ++it )
1138 msg( " subdir: %s \n", (*it).latin1() );
1143 void TagFileParser::addDocAnchors(Entry *e,const TagAnchorInfoList &l)
1145 QListIterator<TagAnchorInfo> tli(l);
1147 for (tli.toFirst();(ta=tli.current());++tli)
1149 if (Doxygen::sectionDict->find(ta->label)==0)
1151 //printf("New sectionInfo file=%s anchor=%s\n",
1152 // ta->fileName.data(),ta->label.data());
1153 SectionInfo *si=new SectionInfo(ta->fileName,-1,ta->label,ta->title,
1154 SectionInfo::Anchor,0,m_tagName);
1155 Doxygen::sectionDict->append(ta->label,si);
1156 e->anchors->append(si);
1160 warn("Duplicate anchor %s found\n",ta->label.data());
1165 void TagFileParser::buildMemberList(Entry *ce,QList<TagMemberInfo> &members)
1167 QListIterator<TagMemberInfo> mii(members);
1169 for (;(tmi=mii.current());++mii)
1171 Entry *me = new Entry;
1172 me->type = tmi->type;
1173 me->name = tmi->name;
1174 me->args = tmi->arglist;
1175 if (!me->args.isEmpty())
1178 me->argList = new ArgumentList;
1179 stringToArgumentList(me->args,me->argList);
1181 if (tmi->enumValues.count()>0)
1183 me->spec |= Entry::Strong;
1184 QListIterator<TagEnumValueInfo> evii(tmi->enumValues);
1185 TagEnumValueInfo *evi;
1186 for (evii.toFirst();(evi=evii.current());++evii)
1188 Entry *ev = new Entry;
1190 ev->name = evi->name;
1191 ev->id = evi->clangid;
1192 ev->section = Entry::VARIABLE_SEC;
1193 TagInfo *ti = new TagInfo;
1194 ti->tagName = m_tagName;
1195 ti->anchor = evi->anchor;
1196 ti->fileName = evi->file;
1198 me->addSubEntry(ev);
1201 me->protection = tmi->prot;
1202 me->virt = tmi->virt;
1203 me->stat = tmi->isStatic;
1204 me->fileName = ce->fileName;
1205 me->id = tmi->clangId;
1206 if (ce->section == Entry::GROUPDOC_SEC)
1208 me->groups->append(new Grouping(ce->name,Grouping::GROUPING_INGROUP));
1210 addDocAnchors(me,tmi->docAnchors);
1211 TagInfo *ti = new TagInfo;
1212 ti->tagName = m_tagName;
1213 ti->anchor = tmi->anchor;
1214 ti->fileName = tmi->anchorFile;
1216 if (tmi->kind=="define")
1219 me->section = Entry::DEFINE_SEC;
1221 else if (tmi->kind=="enumvalue")
1223 me->section = Entry::VARIABLE_SEC;
1226 else if (tmi->kind=="property")
1228 me->section = Entry::VARIABLE_SEC;
1229 me->mtype = Property;
1231 else if (tmi->kind=="event")
1233 me->section = Entry::VARIABLE_SEC;
1236 else if (tmi->kind=="variable")
1238 me->section = Entry::VARIABLE_SEC;
1241 else if (tmi->kind=="typedef")
1243 me->section = Entry::VARIABLE_SEC; //Entry::TYPEDEF_SEC;
1244 me->type.prepend("typedef ");
1247 else if (tmi->kind=="enumeration")
1249 me->section = Entry::ENUM_SEC;
1252 else if (tmi->kind=="function")
1254 me->section = Entry::FUNCTION_SEC;
1257 else if (tmi->kind=="signal")
1259 me->section = Entry::FUNCTION_SEC;
1262 else if (tmi->kind=="prototype")
1264 me->section = Entry::FUNCTION_SEC;
1267 else if (tmi->kind=="friend")
1269 me->section = Entry::FUNCTION_SEC;
1270 me->type.prepend("friend ");
1273 else if (tmi->kind=="dcop")
1275 me->section = Entry::FUNCTION_SEC;
1278 else if (tmi->kind=="slot")
1280 me->section = Entry::FUNCTION_SEC;
1283 ce->addSubEntry(me);
1287 static QCString stripPath(const QCString &s)
1289 int i=s.findRev('/');
1292 return s.right(s.length()-i-1);
1300 /*! Injects the info gathered by the XML parser into the Entry tree.
1301 * This tree contains the information extracted from the input in a
1304 void TagFileParser::buildLists(Entry *root)
1307 QListIterator<TagClassInfo> cit(m_tagFileClasses);
1309 for (cit.toFirst();(tci=cit.current());++cit)
1311 Entry *ce = new Entry;
1312 ce->section = Entry::CLASS_SEC;
1315 case TagClassInfo::Class: break;
1316 case TagClassInfo::Struct: ce->spec = Entry::Struct; break;
1317 case TagClassInfo::Union: ce->spec = Entry::Union; break;
1318 case TagClassInfo::Interface: ce->spec = Entry::Interface; break;
1319 case TagClassInfo::Enum: ce->spec = Entry::Enum; break;
1320 case TagClassInfo::Exception: ce->spec = Entry::Exception; break;
1321 case TagClassInfo::Protocol: ce->spec = Entry::Protocol; break;
1322 case TagClassInfo::Category: ce->spec = Entry::Category; break;
1323 case TagClassInfo::Service: ce->spec = Entry::Service; break;
1324 case TagClassInfo::Singleton: ce->spec = Entry::Singleton; break;
1326 ce->name = tci->name;
1327 if (tci->kind==TagClassInfo::Protocol)
1331 addDocAnchors(ce,tci->docAnchors);
1332 TagInfo *ti = new TagInfo;
1333 ti->tagName = m_tagName;
1334 ti->fileName = tci->filename;
1335 ce->id = tci->clangId;
1337 ce->lang = tci->isObjC ? SrcLangExt_ObjC : SrcLangExt_Unknown;
1338 // transfer base class list
1342 ce->extends = tci->bases; tci->bases = 0;
1344 if (tci->templateArguments)
1346 if (ce->tArgLists==0)
1348 ce->tArgLists = new QList<ArgumentList>;
1349 ce->tArgLists->setAutoDelete(TRUE);
1351 ArgumentList *al = new ArgumentList;
1352 ce->tArgLists->append(al);
1354 QListIterator<QCString> sli(*tci->templateArguments);
1356 for (;(argName=sli.current());++sli)
1358 Argument *a = new Argument;
1365 buildMemberList(ce,tci->members);
1366 root->addSubEntry(ce);
1370 QListIterator<TagFileInfo> fit(m_tagFileFiles);
1372 for (fit.toFirst();(tfi=fit.current());++fit)
1374 Entry *fe = new Entry;
1375 fe->section = guessSection(tfi->name);
1376 fe->name = tfi->name;
1377 addDocAnchors(fe,tfi->docAnchors);
1378 TagInfo *ti = new TagInfo;
1379 ti->tagName = m_tagName;
1380 ti->fileName = tfi->filename;
1383 QCString fullName = m_tagName+":"+tfi->path+stripPath(tfi->name);
1384 fe->fileName = fullName;
1385 //printf("new FileDef() filename=%s\n",tfi->filename.data());
1386 FileDef *fd = new FileDef(m_tagName+":"+tfi->path,
1387 tfi->name,m_tagName,
1391 if ((mn=Doxygen::inputNameDict->find(tfi->name)))
1397 mn = new FileName(fullName,tfi->name);
1399 Doxygen::inputNameList->inSort(mn);
1400 Doxygen::inputNameDict->insert(tfi->name,mn);
1402 buildMemberList(fe,tfi->members);
1403 root->addSubEntry(fe);
1406 // build namespace list
1407 QListIterator<TagNamespaceInfo> nit(m_tagFileNamespaces);
1408 TagNamespaceInfo *tni;
1409 for (nit.toFirst();(tni=nit.current());++nit)
1411 Entry *ne = new Entry;
1412 ne->section = Entry::NAMESPACE_SEC;
1413 ne->name = tni->name;
1414 addDocAnchors(ne,tni->docAnchors);
1415 TagInfo *ti = new TagInfo;
1416 ti->tagName = m_tagName;
1417 ti->fileName = tni->filename;
1418 ne->id = tni->clangId;
1421 buildMemberList(ne,tni->members);
1422 root->addSubEntry(ne);
1425 // build package list
1426 QListIterator<TagPackageInfo> pit(m_tagFilePackages);
1427 TagPackageInfo *tpgi;
1428 for (pit.toFirst();(tpgi=pit.current());++pit)
1430 Entry *pe = new Entry;
1431 pe->section = Entry::PACKAGE_SEC;
1432 pe->name = tpgi->name;
1433 addDocAnchors(pe,tpgi->docAnchors);
1434 TagInfo *ti = new TagInfo;
1435 ti->tagName = m_tagName;
1436 ti->fileName = tpgi->filename;
1439 buildMemberList(pe,tpgi->members);
1440 root->addSubEntry(pe);
1444 QListIterator<TagGroupInfo> git(m_tagFileGroups);
1446 for (git.toFirst();(tgi=git.current());++git)
1448 Entry *ge = new Entry;
1449 ge->section = Entry::GROUPDOC_SEC;
1450 ge->name = tgi->name;
1451 ge->type = tgi->title;
1452 addDocAnchors(ge,tgi->docAnchors);
1453 TagInfo *ti = new TagInfo;
1454 ti->tagName = m_tagName;
1455 ti->fileName = tgi->filename;
1458 buildMemberList(ge,tgi->members);
1459 root->addSubEntry(ge);
1463 QListIterator<TagPageInfo> pgit(m_tagFilePages);
1465 for (pgit.toFirst();(tpi=pgit.current());++pgit)
1467 Entry *pe = new Entry;
1468 pe->section = tpi->filename=="index" ? Entry::MAINPAGEDOC_SEC : Entry::PAGEDOC_SEC;
1469 pe->name = tpi->name;
1470 pe->args = tpi->title;
1471 addDocAnchors(pe,tpi->docAnchors);
1472 TagInfo *ti = new TagInfo;
1473 ti->tagName = m_tagName;
1474 ti->fileName = tpi->filename;
1476 root->addSubEntry(pe);
1480 void TagFileParser::addIncludes()
1482 QListIterator<TagFileInfo> fit(m_tagFileFiles);
1484 for (fit.toFirst();(tfi=fit.current());++fit)
1486 //printf("tag file tagName=%s path=%s name=%s\n",m_tagName.data(),tfi->path.data(),tfi->name.data());
1487 FileName *fn = Doxygen::inputNameDict->find(tfi->name);
1490 //printf("found\n");
1491 FileNameIterator fni(*fn);
1493 for (;(fd=fni.current());++fni)
1495 //printf("input file path=%s name=%s\n",fd->getPath().data(),fd->name().data());
1496 if (fd->getPath()==QCString(m_tagName+":"+tfi->path))
1498 //printf("found\n");
1499 QListIterator<TagIncludeInfo> mii(tfi->includes);
1501 for (;(ii=mii.current());++mii)
1503 //printf("ii->name=`%s'\n",ii->name.data());
1504 FileName *ifn = Doxygen::inputNameDict->find(ii->name);
1508 FileNameIterator ifni(*ifn);
1510 for (;(ifd=ifni.current());++ifni)
1512 //printf("ifd->getOutputFileBase()=%s ii->id=%s\n",
1513 // ifd->getOutputFileBase().data(),ii->id.data());
1514 if (ifd->getOutputFileBase()==QCString(ii->id))
1516 fd->addIncludeDependency(ifd,ii->text,ii->isLocal,ii->isImported,FALSE);
1527 void parseTagFile(Entry *root,const char *fullName)
1529 QFileInfo fi(fullName);
1530 if (!fi.exists()) return;
1531 TagFileParser handler( fullName ); // tagName
1532 handler.setFileName(fullName);
1533 TagFileErrorHandler errorHandler;
1534 QFile xmlFile( fullName );
1535 QXmlInputSource source( xmlFile );
1536 QXmlSimpleReader reader;
1537 reader.setContentHandler( &handler );
1538 reader.setErrorHandler( &errorHandler );
1539 reader.parse( source );
1540 handler.buildLists(root);
1541 handler.addIncludes();