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"
28 #include <qfileinfo.h>
31 #include <qcstringlist.h>
39 #include "arguments.h"
45 /** Information about an linkable anchor */
49 TagAnchorInfo(const QCString &f,
51 const QCString &t=QCString())
52 : label(l), fileName(f), title(t) {}
58 /** List of TagAnchorInfo objects. */
59 class TagAnchorInfoList : public QList<TagAnchorInfo>
62 TagAnchorInfoList() : QList<TagAnchorInfo>() { setAutoDelete(TRUE); }
63 virtual ~TagAnchorInfoList() {}
66 /** Container for enum values that are scoped within an enum */
67 class TagEnumValueInfo
76 /** Container for member specific info that can be read from a tagfile */
80 TagMemberInfo() : prot(Public), virt(Normal), isStatic(FALSE)
81 { enumValues.setAutoDelete(TRUE); }
89 TagAnchorInfoList docAnchors;
93 QList<TagEnumValueInfo> enumValues;
96 /** Container for class specific info that can be read from a tagfile */
100 enum Kind { None=-1, Class, Struct, Union, Interface, Exception, Protocol, Category, Enum, Service, Singleton };
101 TagClassInfo() { bases=0, templateArguments=0; members.setAutoDelete(TRUE); isObjC=FALSE; kind = None; }
102 ~TagClassInfo() { delete bases; delete templateArguments; }
107 TagAnchorInfoList docAnchors;
108 QList<BaseInfo> *bases;
109 QList<TagMemberInfo> members;
110 QList<QCString> *templateArguments;
111 QCStringList classList;
116 /** Container for namespace specific info that can be read from a tagfile */
117 class TagNamespaceInfo
120 TagNamespaceInfo() { members.setAutoDelete(TRUE); }
124 QCStringList classList;
125 QCStringList namespaceList;
126 TagAnchorInfoList docAnchors;
127 QList<TagMemberInfo> members;
130 /** Container for package specific info that can be read from a tagfile */
134 TagPackageInfo() { members.setAutoDelete(TRUE); }
137 TagAnchorInfoList docAnchors;
138 QList<TagMemberInfo> members;
139 QCStringList classList;
142 /** Container for include info that can be read from a tagfile */
153 /** Container for file specific info that can be read from a tagfile */
157 TagFileInfo() { members.setAutoDelete(TRUE); includes.setAutoDelete(TRUE); }
161 TagAnchorInfoList docAnchors;
162 QList<TagMemberInfo> members;
163 QCStringList classList;
164 QCStringList namespaceList;
165 QList<TagIncludeInfo> includes;
168 /** Container for group specific info that can be read from a tagfile */
172 TagGroupInfo() { members.setAutoDelete(TRUE); }
176 TagAnchorInfoList docAnchors;
177 QList<TagMemberInfo> members;
178 QCStringList subgroupList;
179 QCStringList classList;
180 QCStringList namespaceList;
181 QCStringList fileList;
182 QCStringList pageList;
183 QCStringList dirList;
186 /** Container for page specific info that can be read from a tagfile */
193 TagAnchorInfoList docAnchors;
196 /** Container for directory specific info that can be read from a tagfile */
203 QCStringList subdirList;
204 QCStringList fileList;
205 TagAnchorInfoList docAnchors;
210 * Reads an XML-structured tagfile and builds up the structure in
211 * memory. The method buildLists() is used to transfer/translate
212 * the structures to the doxygen engine.
214 class TagFileParser : public QXmlDefaultHandler
216 enum State { Invalid,
228 class StartElementHandler
230 typedef void (TagFileParser::*Handler)(const QXmlAttributes &attrib);
232 StartElementHandler(TagFileParser *parent, Handler h) : m_parent(parent), m_handler(h) {}
233 void operator()(const QXmlAttributes &attrib) { (m_parent->*m_handler)(attrib); }
235 TagFileParser *m_parent;
239 class EndElementHandler
241 typedef void (TagFileParser::*Handler)();
243 EndElementHandler(TagFileParser *parent, Handler h) : m_parent(parent), m_handler(h) {}
244 void operator()() { (m_parent->*m_handler)(); }
246 TagFileParser *m_parent;
251 TagFileParser(const char *tagName) : m_startElementHandlers(17),
252 m_endElementHandlers(17),
255 m_startElementHandlers.setAutoDelete(TRUE);
256 m_endElementHandlers.setAutoDelete(TRUE);
271 void setDocumentLocator ( QXmlLocator * locator )
276 void setFileName( const QString &fileName )
278 m_inputFileName = fileName.utf8();
281 void warn(const char *fmt)
283 ::warn(m_inputFileName,m_locator->lineNumber(),fmt);
285 void warn(const char *fmt,const char *s)
287 ::warn(m_inputFileName,m_locator->lineNumber(),fmt,s);
290 void startCompound( const QXmlAttributes& attrib )
293 QString kind = attrib.value("kind");
294 QString isObjC = attrib.value("objc");
297 m_curClass = new TagClassInfo;
298 m_curClass->kind = TagClassInfo::Class;
301 else if (kind=="struct")
303 m_curClass = new TagClassInfo;
304 m_curClass->kind = TagClassInfo::Struct;
307 else if (kind=="union")
309 m_curClass = new TagClassInfo;
310 m_curClass->kind = TagClassInfo::Union;
313 else if (kind=="interface")
315 m_curClass = new TagClassInfo;
316 m_curClass->kind = TagClassInfo::Interface;
319 else if (kind=="enum")
321 m_curClass = new TagClassInfo;
322 m_curClass->kind = TagClassInfo::Enum;
325 else if (kind=="exception")
327 m_curClass = new TagClassInfo;
328 m_curClass->kind = TagClassInfo::Exception;
331 else if (kind=="protocol")
333 m_curClass = new TagClassInfo;
334 m_curClass->kind = TagClassInfo::Protocol;
337 else if (kind=="category")
339 m_curClass = new TagClassInfo;
340 m_curClass->kind = TagClassInfo::Category;
343 else if (kind=="service")
345 m_curClass = new TagClassInfo;
346 m_curClass->kind = TagClassInfo::Service;
349 else if (kind=="singleton")
351 m_curClass = new TagClassInfo;
352 m_curClass->kind = TagClassInfo::Singleton;
355 else if (kind=="file")
357 m_curFile = new TagFileInfo;
360 else if (kind=="namespace")
362 m_curNamespace = new TagNamespaceInfo;
363 m_state = InNamespace;
365 else if (kind=="group")
367 m_curGroup = new TagGroupInfo;
370 else if (kind=="page")
372 m_curPage = new TagPageInfo;
375 else if (kind=="package")
377 m_curPackage = new TagPackageInfo;
380 else if (kind=="dir")
382 m_curDir = new TagDirInfo;
387 warn("Unknown compound attribute `%s' found!",kind.data());
390 if (isObjC=="yes" && m_curClass)
392 m_curClass->isObjC = TRUE;
400 case InClass: m_tagFileClasses.append(m_curClass);
402 case InFile: m_tagFileFiles.append(m_curFile);
404 case InNamespace: m_tagFileNamespaces.append(m_curNamespace);
405 m_curNamespace=0; break;
406 case InGroup: m_tagFileGroups.append(m_curGroup);
408 case InPage: m_tagFilePages.append(m_curPage);
410 case InDir: m_tagFileDirs.append(m_curDir);
412 case InPackage: m_tagFilePackages.append(m_curPackage);
413 m_curPackage=0; break;
415 warn("tag `compound' was not expected!");
419 void startMember( const QXmlAttributes& attrib)
421 m_curMember = new TagMemberInfo;
422 m_curMember->kind = attrib.value("kind").utf8();
423 QCString protStr = attrib.value("protection").utf8();
424 QCString virtStr = attrib.value("virtualness").utf8();
425 QCString staticStr = attrib.value("static").utf8();
426 if (protStr=="protected")
428 m_curMember->prot = Protected;
430 else if (protStr=="private")
432 m_curMember->prot = Private;
434 if (virtStr=="virtual")
436 m_curMember->virt = Virtual;
438 else if (virtStr=="pure")
440 m_curMember->virt = Pure;
442 if (staticStr=="yes")
444 m_curMember->isStatic = TRUE;
446 m_stateStack.push(new State(m_state));
452 m_state = *m_stateStack.top();
453 m_stateStack.remove();
456 case InClass: m_curClass->members.append(m_curMember); break;
457 case InFile: m_curFile->members.append(m_curMember); break;
458 case InNamespace: m_curNamespace->members.append(m_curMember); break;
459 case InGroup: m_curGroup->members.append(m_curMember); break;
460 case InPackage: m_curPackage->members.append(m_curMember); break;
461 default: warn("Unexpected tag `member' found"); break;
465 void startEnumValue( const QXmlAttributes& attrib)
467 if (m_state==InMember)
470 m_curEnumValue = new TagEnumValueInfo;
471 m_curEnumValue->file = attrib.value("file").utf8();
472 m_curEnumValue->anchor = attrib.value("anchor").utf8();
473 m_curEnumValue->clangid = attrib.value("clangid").utf8();
474 m_stateStack.push(new State(m_state));
475 m_state = InEnumValue;
479 warn("Found `enumvalue' tag outside of member tag");
485 m_curEnumValue->name = m_curString.stripWhiteSpace();
486 m_state = *m_stateStack.top();
487 m_stateStack.remove();
488 if (m_state==InMember)
490 m_curMember->enumValues.append(m_curEnumValue);
499 case InClass: m_curClass->docAnchors.append(new TagAnchorInfo(m_fileName,m_curString,m_title)); break;
500 case InFile: m_curFile->docAnchors.append(new TagAnchorInfo(m_fileName,m_curString,m_title)); break;
501 case InNamespace: m_curNamespace->docAnchors.append(new TagAnchorInfo(m_fileName,m_curString,m_title)); break;
502 case InGroup: m_curGroup->docAnchors.append(new TagAnchorInfo(m_fileName,m_curString,m_title)); break;
503 case InPage: m_curPage->docAnchors.append(new TagAnchorInfo(m_fileName,m_curString,m_title)); break;
504 case InMember: m_curMember->docAnchors.append(new TagAnchorInfo(m_fileName,m_curString,m_title)); break;
505 case InPackage: m_curPackage->docAnchors.append(new TagAnchorInfo(m_fileName,m_curString,m_title)); break;
506 case InDir: m_curDir->docAnchors.append(new TagAnchorInfo(m_fileName,m_curString,m_title)); break;
507 default: warn("Unexpected tag `docanchor' found"); break;
515 case InClass: m_curClass->classList.append(m_curString); break;
516 case InFile: m_curFile->classList.append(m_curString); break;
517 case InNamespace: m_curNamespace->classList.append(m_curString); break;
518 case InGroup: m_curGroup->classList.append(m_curString); break;
519 case InPackage: m_curPackage->classList.append(m_curString); break;
520 default: warn("Unexpected tag `class' found"); break;
528 case InNamespace: m_curNamespace->classList.append(m_curString); break;
529 case InFile: m_curFile->namespaceList.append(m_curString); break;
530 case InGroup: m_curGroup->namespaceList.append(m_curString); break;
531 default: warn("Unexpected tag `namespace' found"); break;
539 case InGroup: m_curGroup->fileList.append(m_curString); break;
540 case InDir: m_curDir->fileList.append(m_curString); break;
541 default: warn("Unexpected tag `file' found"); break;
549 case InGroup: m_curGroup->fileList.append(m_curString); break;
550 default: warn("Unexpected tag `page' found"); break;
558 case InDir: m_curDir->subdirList.append(m_curString); break;
559 default: warn("Unexpected tag `dir' found"); break;
563 void startStringValue(const QXmlAttributes& )
568 void startDocAnchor(const QXmlAttributes& attrib )
570 m_fileName = attrib.value("file").utf8();
571 m_title = attrib.value("title").utf8();
577 if (m_state==InMember)
579 m_curMember->type = m_curString;
583 warn("Unexpected tag `type' found");
591 case InClass: m_curClass->name = m_curString; break;
592 case InFile: m_curFile->name = m_curString; break;
593 case InNamespace: m_curNamespace->name = m_curString; break;
594 case InGroup: m_curGroup->name = m_curString; break;
595 case InPage: m_curPage->name = m_curString; break;
596 case InDir: m_curDir->name = m_curString; break;
597 case InMember: m_curMember->name = m_curString; break;
598 case InPackage: m_curPackage->name = m_curString; break;
599 default: warn("Unexpected tag `name' found"); break;
603 void startBase(const QXmlAttributes& attrib )
606 if (m_state==InClass && m_curClass)
608 QString protStr = attrib.value("protection");
609 QString virtStr = attrib.value("virtualness");
610 Protection prot = Public;
611 Specifier virt = Normal;
612 if (protStr=="protected")
616 else if (protStr=="private")
620 if (virtStr=="virtual")
624 if (m_curClass->bases==0)
626 m_curClass->bases = new QList<BaseInfo>;
627 m_curClass->bases->setAutoDelete(TRUE);
629 m_curClass->bases->append(new BaseInfo(m_curString,prot,virt));
633 warn("Unexpected tag `base' found");
639 if (m_state==InClass && m_curClass)
641 m_curClass->bases->getLast()->name = m_curString;
645 warn("Unexpected tag `base' found");
649 void startIncludes(const QXmlAttributes& attrib )
651 if (m_state==InFile && m_curFile)
653 m_curIncludes = new TagIncludeInfo;
654 m_curIncludes->id = attrib.value("id").utf8();
655 m_curIncludes->name = attrib.value("name").utf8();
656 m_curIncludes->isLocal = attrib.value("local").utf8()=="yes" ? TRUE : FALSE;
657 m_curIncludes->isImported = attrib.value("imported").utf8()=="yes" ? TRUE : FALSE;
658 m_curFile->includes.append(m_curIncludes);
662 warn("Unexpected tag `includes' found");
669 m_curIncludes->text = m_curString;
672 void endTemplateArg()
674 if (m_state==InClass && m_curClass)
676 if (m_curClass->templateArguments==0)
678 m_curClass->templateArguments = new QList<QCString>;
679 m_curClass->templateArguments->setAutoDelete(TRUE);
681 m_curClass->templateArguments->append(new QCString(m_curString));
685 warn("Unexpected tag `templarg' found");
693 case InClass: m_curClass->filename = m_curString; break;
694 case InNamespace: m_curNamespace->filename = m_curString; break;
695 case InFile: m_curFile->filename = m_curString; break;
696 case InGroup: m_curGroup->filename = m_curString; break;
697 case InPage: m_curPage->filename = m_curString; break;
698 case InPackage: m_curPackage->filename = m_curString; break;
699 case InDir: m_curDir->filename = m_curString; break;
700 default: warn("Unexpected tag `filename' found"); break;
708 case InFile: m_curFile->path = m_curString; break;
709 case InDir: m_curDir->path = m_curString; break;
710 default: warn("Unexpected tag `path' found"); break;
716 if (m_state==InMember)
718 m_curMember->anchor = m_curString;
720 else if (m_state==InClass)
722 m_curClass->anchor = m_curString;
726 warn("Unexpected tag `anchor' found");
732 if (m_state==InMember)
734 m_curMember->clangId = m_curString;
736 else if (m_state==InClass)
738 m_curClass->clangId = m_curString;
740 else if (m_state==InNamespace)
742 m_curNamespace->clangId = m_curString;
746 warn("Unexpected tag `clangid' found");
754 if (m_state==InMember)
756 m_curMember->anchorFile = m_curString;
760 warn("Unexpected tag `anchorfile' found");
766 if (m_state==InMember)
768 m_curMember->arglist = m_curString;
772 warn("Unexpected tag `arglist' found");
779 case InGroup: m_curGroup->title = m_curString; break;
780 case InPage: m_curPage->title = m_curString; break;
781 default: warn("Unexpected tag `title' found"); break;
787 if (m_state==InGroup)
789 m_curGroup->subgroupList.append(m_curString);
793 warn("Unexpected tag `subgroup' found");
797 void startIgnoreElement(const QXmlAttributes& )
801 void endIgnoreElement()
817 m_stateStack.setAutoDelete(TRUE);
818 m_tagFileClasses.setAutoDelete(TRUE);
819 m_tagFileFiles.setAutoDelete(TRUE);
820 m_tagFileNamespaces.setAutoDelete(TRUE);
821 m_tagFileGroups.setAutoDelete(TRUE);
822 m_tagFilePages.setAutoDelete(TRUE);
823 m_tagFilePackages.setAutoDelete(TRUE);
824 m_tagFileDirs.setAutoDelete(TRUE);
826 m_startElementHandlers.insert("compound", new StartElementHandler(this,&TagFileParser::startCompound));
827 m_startElementHandlers.insert("member", new StartElementHandler(this,&TagFileParser::startMember));
828 m_startElementHandlers.insert("enumvalue", new StartElementHandler(this,&TagFileParser::startEnumValue));
829 m_startElementHandlers.insert("name", new StartElementHandler(this,&TagFileParser::startStringValue));
830 m_startElementHandlers.insert("base", new StartElementHandler(this,&TagFileParser::startBase));
831 m_startElementHandlers.insert("filename", new StartElementHandler(this,&TagFileParser::startStringValue));
832 m_startElementHandlers.insert("includes", new StartElementHandler(this,&TagFileParser::startIncludes));
833 m_startElementHandlers.insert("path", new StartElementHandler(this,&TagFileParser::startStringValue));
834 m_startElementHandlers.insert("anchorfile", new StartElementHandler(this,&TagFileParser::startStringValue));
835 m_startElementHandlers.insert("anchor", new StartElementHandler(this,&TagFileParser::startStringValue));
836 m_startElementHandlers.insert("clangid", new StartElementHandler(this,&TagFileParser::startStringValue));
837 m_startElementHandlers.insert("arglist", new StartElementHandler(this,&TagFileParser::startStringValue));
838 m_startElementHandlers.insert("title", new StartElementHandler(this,&TagFileParser::startStringValue));
839 m_startElementHandlers.insert("subgroup", new StartElementHandler(this,&TagFileParser::startStringValue));
840 m_startElementHandlers.insert("class", new StartElementHandler(this,&TagFileParser::startStringValue));
841 m_startElementHandlers.insert("namespace", new StartElementHandler(this,&TagFileParser::startStringValue));
842 m_startElementHandlers.insert("file", new StartElementHandler(this,&TagFileParser::startStringValue));
843 m_startElementHandlers.insert("dir", new StartElementHandler(this,&TagFileParser::startStringValue));
844 m_startElementHandlers.insert("page", new StartElementHandler(this,&TagFileParser::startStringValue));
845 m_startElementHandlers.insert("docanchor", new StartElementHandler(this,&TagFileParser::startDocAnchor));
846 m_startElementHandlers.insert("tagfile", new StartElementHandler(this,&TagFileParser::startIgnoreElement));
847 m_startElementHandlers.insert("templarg", new StartElementHandler(this,&TagFileParser::startStringValue));
848 m_startElementHandlers.insert("type", new StartElementHandler(this,&TagFileParser::startStringValue));
850 m_endElementHandlers.insert("compound", new EndElementHandler(this,&TagFileParser::endCompound));
851 m_endElementHandlers.insert("member", new EndElementHandler(this,&TagFileParser::endMember));
852 m_endElementHandlers.insert("enumvalue", new EndElementHandler(this,&TagFileParser::endEnumValue));
853 m_endElementHandlers.insert("name", new EndElementHandler(this,&TagFileParser::endName));
854 m_endElementHandlers.insert("base", new EndElementHandler(this,&TagFileParser::endBase));
855 m_endElementHandlers.insert("filename", new EndElementHandler(this,&TagFileParser::endFilename));
856 m_endElementHandlers.insert("includes", new EndElementHandler(this,&TagFileParser::endIncludes));
857 m_endElementHandlers.insert("path", new EndElementHandler(this,&TagFileParser::endPath));
858 m_endElementHandlers.insert("anchorfile", new EndElementHandler(this,&TagFileParser::endAnchorFile));
859 m_endElementHandlers.insert("anchor", new EndElementHandler(this,&TagFileParser::endAnchor));
860 m_endElementHandlers.insert("clangid", new EndElementHandler(this,&TagFileParser::endClangId));
861 m_endElementHandlers.insert("arglist", new EndElementHandler(this,&TagFileParser::endArglist));
862 m_endElementHandlers.insert("title", new EndElementHandler(this,&TagFileParser::endTitle));
863 m_endElementHandlers.insert("subgroup", new EndElementHandler(this,&TagFileParser::endSubgroup));
864 m_endElementHandlers.insert("class" , new EndElementHandler(this,&TagFileParser::endClass));
865 m_endElementHandlers.insert("namespace", new EndElementHandler(this,&TagFileParser::endNamespace));
866 m_endElementHandlers.insert("file", new EndElementHandler(this,&TagFileParser::endFile));
867 m_endElementHandlers.insert("dir", new EndElementHandler(this,&TagFileParser::endDir));
868 m_endElementHandlers.insert("page", new EndElementHandler(this,&TagFileParser::endPage));
869 m_endElementHandlers.insert("docanchor", new EndElementHandler(this,&TagFileParser::endDocAnchor));
870 m_endElementHandlers.insert("tagfile", new EndElementHandler(this,&TagFileParser::endIgnoreElement));
871 m_endElementHandlers.insert("templarg", new EndElementHandler(this,&TagFileParser::endTemplateArg));
872 m_endElementHandlers.insert("type", new EndElementHandler(this,&TagFileParser::endType));
877 bool startElement( const QString&, const QString&,
878 const QString&name, const QXmlAttributes& attrib )
880 //printf("startElement `%s'\n",name.data());
881 StartElementHandler *handler = m_startElementHandlers[name.utf8()];
888 warn("Unknown tag `%s' found!",name.data());
893 bool endElement( const QString&, const QString&, const QString& name )
895 //printf("endElement `%s'\n",name.data());
896 EndElementHandler *handler = m_endElementHandlers[name.utf8()];
903 warn("Unknown tag `%s' found!",name.data());
908 bool characters ( const QString & ch )
910 m_curString+=ch.utf8();
915 void buildLists(Entry *root);
919 void buildMemberList(Entry *ce,QList<TagMemberInfo> &members);
920 void addDocAnchors(Entry *e,const TagAnchorInfoList &l);
921 QList<TagClassInfo> m_tagFileClasses;
922 QList<TagFileInfo> m_tagFileFiles;
923 QList<TagNamespaceInfo> m_tagFileNamespaces;
924 QList<TagGroupInfo> m_tagFileGroups;
925 QList<TagPageInfo> m_tagFilePages;
926 QList<TagPackageInfo> m_tagFilePackages;
927 QList<TagDirInfo> m_tagFileDirs;
928 QDict<StartElementHandler> m_startElementHandlers;
929 QDict<EndElementHandler> m_endElementHandlers;
930 TagClassInfo *m_curClass;
931 TagFileInfo *m_curFile;
932 TagNamespaceInfo *m_curNamespace;
933 TagPackageInfo *m_curPackage;
934 TagGroupInfo *m_curGroup;
935 TagPageInfo *m_curPage;
936 TagDirInfo *m_curDir;
937 TagMemberInfo *m_curMember;
938 TagEnumValueInfo *m_curEnumValue;
939 TagIncludeInfo *m_curIncludes;
940 QCString m_curString;
945 QStack<State> m_stateStack;
946 QXmlLocator *m_locator;
947 QCString m_inputFileName;
950 /** Error handler for the XML tag file parser.
952 * Basically dumps all fatal error to stderr using err().
954 class TagFileErrorHandler : public QXmlErrorHandler
957 virtual ~TagFileErrorHandler() {}
958 bool warning( const QXmlParseException & )
962 bool error( const QXmlParseException & )
966 bool fatalError( const QXmlParseException &exception )
968 err("Fatal error at line %d column %d: %s\n",
969 exception.lineNumber(),exception.columnNumber(),
970 exception.message().data());
973 QString errorString() { return ""; }
979 /*! Dumps the internal structures. For debugging only! */
980 void TagFileParser::dump()
983 QListIterator<TagClassInfo> lci(m_tagFileClasses);
985 //============== CLASSES
987 for (;(cd=lci.current());++lci)
989 msg("class `%s'\n",cd->name.data());
990 msg(" filename `%s'\n",cd->filename.data());
993 QListIterator<BaseInfo> bii(*cd->bases);
995 for ( bii.toFirst() ; (bi=bii.current()) ; ++bii)
997 msg( " base: %s \n", bi->name.data() );
1001 QListIterator<TagMemberInfo> mci(cd->members);
1003 for (;(md=mci.current());++mci)
1006 msg(" kind: `%s'\n",md->kind.data());
1007 msg(" name: `%s'\n",md->name.data());
1008 msg(" anchor: `%s'\n",md->anchor.data());
1009 msg(" arglist: `%s'\n",md->arglist.data());
1012 //============== NAMESPACES
1013 QListIterator<TagNamespaceInfo> lni(m_tagFileNamespaces);
1014 TagNamespaceInfo *nd;
1015 for (;(nd=lni.current());++lni)
1017 msg("namespace `%s'\n",nd->name.data());
1018 msg(" filename `%s'\n",nd->filename.data());
1019 QCStringList::Iterator it;
1020 for ( it = nd->classList.begin();
1021 it != nd->classList.end(); ++it )
1023 msg( " class: %s \n", (*it).data() );
1026 QListIterator<TagMemberInfo> mci(nd->members);
1028 for (;(md=mci.current());++mci)
1031 msg(" kind: `%s'\n",md->kind.data());
1032 msg(" name: `%s'\n",md->name.data());
1033 msg(" anchor: `%s'\n",md->anchor.data());
1034 msg(" arglist: `%s'\n",md->arglist.data());
1037 //============== FILES
1038 QListIterator<TagFileInfo> lfi(m_tagFileFiles);
1040 for (;(fd=lfi.current());++lfi)
1042 msg("file `%s'\n",fd->name.data());
1043 msg(" filename `%s'\n",fd->filename.data());
1044 QCStringList::Iterator it;
1045 for ( it = fd->namespaceList.begin();
1046 it != fd->namespaceList.end(); ++it )
1048 msg( " namespace: %s \n", (*it).data() );
1050 for ( it = fd->classList.begin();
1051 it != fd->classList.end(); ++it )
1053 msg( " class: %s \n", (*it).data() );
1056 QListIterator<TagMemberInfo> mci(fd->members);
1058 for (;(md=mci.current());++mci)
1061 msg(" kind: `%s'\n",md->kind.data());
1062 msg(" name: `%s'\n",md->name.data());
1063 msg(" anchor: `%s'\n",md->anchor.data());
1064 msg(" arglist: `%s'\n",md->arglist.data());
1067 QListIterator<TagIncludeInfo> mii(fd->includes);
1069 for (;(ii=mii.current());++mii)
1071 msg(" includes id: %s name: %s\n",ii->id.data(),ii->name.data());
1075 //============== GROUPS
1076 QListIterator<TagGroupInfo> lgi(m_tagFileGroups);
1078 for (;(gd=lgi.current());++lgi)
1080 msg("group `%s'\n",gd->name.data());
1081 msg(" filename `%s'\n",gd->filename.data());
1082 QCStringList::Iterator it;
1083 for ( it = gd->namespaceList.begin();
1084 it != gd->namespaceList.end(); ++it )
1086 msg( " namespace: %s \n", (*it).data() );
1088 for ( it = gd->classList.begin();
1089 it != gd->classList.end(); ++it )
1091 msg( " class: %s \n", (*it).data() );
1093 for ( it = gd->fileList.begin();
1094 it != gd->fileList.end(); ++it )
1096 msg( " file: %s \n", (*it).data() );
1098 for ( it = gd->subgroupList.begin();
1099 it != gd->subgroupList.end(); ++it )
1101 msg( " subgroup: %s \n", (*it).data() );
1103 for ( it = gd->pageList.begin();
1104 it != gd->pageList.end(); ++it )
1106 msg( " page: %s \n", (*it).data() );
1109 QListIterator<TagMemberInfo> mci(gd->members);
1111 for (;(md=mci.current());++mci)
1114 msg(" kind: `%s'\n",md->kind.data());
1115 msg(" name: `%s'\n",md->name.data());
1116 msg(" anchor: `%s'\n",md->anchor.data());
1117 msg(" arglist: `%s'\n",md->arglist.data());
1120 //============== PAGES
1121 QListIterator<TagPageInfo> lpi(m_tagFilePages);
1123 for (;(pd=lpi.current());++lpi)
1125 msg("page `%s'\n",pd->name.data());
1126 msg(" title `%s'\n",pd->title.data());
1127 msg(" filename `%s'\n",pd->filename.data());
1129 //============== DIRS
1130 QListIterator<TagDirInfo> ldi(m_tagFileDirs);
1132 for (;(dd=ldi.current());++ldi)
1134 msg("dir `%s'\n",dd->name.data());
1135 msg(" path `%s'\n",dd->path.data());
1136 QCStringList::Iterator it;
1137 for ( it = dd->fileList.begin();
1138 it != dd->fileList.end(); ++it )
1140 msg( " file: %s \n", (*it).data() );
1142 for ( it = dd->subdirList.begin();
1143 it != dd->subdirList.end(); ++it )
1145 msg( " subdir: %s \n", (*it).data() );
1150 void TagFileParser::addDocAnchors(Entry *e,const TagAnchorInfoList &l)
1152 QListIterator<TagAnchorInfo> tli(l);
1154 for (tli.toFirst();(ta=tli.current());++tli)
1156 if (Doxygen::sectionDict->find(ta->label)==0)
1158 //printf("New sectionInfo file=%s anchor=%s\n",
1159 // ta->fileName.data(),ta->label.data());
1160 SectionInfo *si=new SectionInfo(ta->fileName,-1,ta->label,ta->title,
1161 SectionInfo::Anchor,0,m_tagName);
1162 Doxygen::sectionDict->append(ta->label,si);
1163 e->anchors->append(si);
1167 warn("Duplicate anchor %s found",ta->label.data());
1172 void TagFileParser::buildMemberList(Entry *ce,QList<TagMemberInfo> &members)
1174 QListIterator<TagMemberInfo> mii(members);
1176 for (;(tmi=mii.current());++mii)
1178 Entry *me = new Entry;
1179 me->type = tmi->type;
1180 me->name = tmi->name;
1181 me->args = tmi->arglist;
1182 if (!me->args.isEmpty())
1185 me->argList = new ArgumentList;
1186 stringToArgumentList(me->args,me->argList);
1188 if (tmi->enumValues.count()>0)
1190 me->spec |= Entry::Strong;
1191 QListIterator<TagEnumValueInfo> evii(tmi->enumValues);
1192 TagEnumValueInfo *evi;
1193 for (evii.toFirst();(evi=evii.current());++evii)
1195 Entry *ev = new Entry;
1197 ev->name = evi->name;
1198 ev->id = evi->clangid;
1199 ev->section = Entry::VARIABLE_SEC;
1200 TagInfo *ti = new TagInfo;
1201 ti->tagName = m_tagName;
1202 ti->anchor = evi->anchor;
1203 ti->fileName = evi->file;
1205 me->addSubEntry(ev);
1208 me->protection = tmi->prot;
1209 me->virt = tmi->virt;
1210 me->stat = tmi->isStatic;
1211 me->fileName = ce->fileName;
1212 me->id = tmi->clangId;
1213 if (ce->section == Entry::GROUPDOC_SEC)
1215 me->groups->append(new Grouping(ce->name,Grouping::GROUPING_INGROUP));
1217 addDocAnchors(me,tmi->docAnchors);
1218 TagInfo *ti = new TagInfo;
1219 ti->tagName = m_tagName;
1220 ti->anchor = tmi->anchor;
1221 ti->fileName = tmi->anchorFile;
1223 if (tmi->kind=="define")
1226 me->section = Entry::DEFINE_SEC;
1228 else if (tmi->kind=="enumvalue")
1230 me->section = Entry::VARIABLE_SEC;
1233 else if (tmi->kind=="property")
1235 me->section = Entry::VARIABLE_SEC;
1236 me->mtype = Property;
1238 else if (tmi->kind=="event")
1240 me->section = Entry::VARIABLE_SEC;
1243 else if (tmi->kind=="variable")
1245 me->section = Entry::VARIABLE_SEC;
1248 else if (tmi->kind=="typedef")
1250 me->section = Entry::VARIABLE_SEC; //Entry::TYPEDEF_SEC;
1251 me->type.prepend("typedef ");
1254 else if (tmi->kind=="enumeration")
1256 me->section = Entry::ENUM_SEC;
1259 else if (tmi->kind=="function")
1261 me->section = Entry::FUNCTION_SEC;
1264 else if (tmi->kind=="signal")
1266 me->section = Entry::FUNCTION_SEC;
1269 else if (tmi->kind=="prototype")
1271 me->section = Entry::FUNCTION_SEC;
1274 else if (tmi->kind=="friend")
1276 me->section = Entry::FUNCTION_SEC;
1277 me->type.prepend("friend ");
1280 else if (tmi->kind=="dcop")
1282 me->section = Entry::FUNCTION_SEC;
1285 else if (tmi->kind=="slot")
1287 me->section = Entry::FUNCTION_SEC;
1290 ce->addSubEntry(me);
1294 static QCString stripPath(const QCString &s)
1296 int i=s.findRev('/');
1299 return s.right(s.length()-i-1);
1307 /*! Injects the info gathered by the XML parser into the Entry tree.
1308 * This tree contains the information extracted from the input in a
1311 void TagFileParser::buildLists(Entry *root)
1314 QListIterator<TagClassInfo> cit(m_tagFileClasses);
1316 for (cit.toFirst();(tci=cit.current());++cit)
1318 Entry *ce = new Entry;
1319 ce->section = Entry::CLASS_SEC;
1322 case TagClassInfo::Class: break;
1323 case TagClassInfo::Struct: ce->spec = Entry::Struct; break;
1324 case TagClassInfo::Union: ce->spec = Entry::Union; break;
1325 case TagClassInfo::Interface: ce->spec = Entry::Interface; break;
1326 case TagClassInfo::Enum: ce->spec = Entry::Enum; break;
1327 case TagClassInfo::Exception: ce->spec = Entry::Exception; break;
1328 case TagClassInfo::Protocol: ce->spec = Entry::Protocol; break;
1329 case TagClassInfo::Category: ce->spec = Entry::Category; break;
1330 case TagClassInfo::Service: ce->spec = Entry::Service; break;
1331 case TagClassInfo::Singleton: ce->spec = Entry::Singleton; break;
1332 case TagClassInfo::None: // should never happen, means not properly initialized
1333 assert(tci->kind != TagClassInfo::None);
1336 ce->name = tci->name;
1337 if (tci->kind==TagClassInfo::Protocol)
1341 addDocAnchors(ce,tci->docAnchors);
1342 TagInfo *ti = new TagInfo;
1343 ti->tagName = m_tagName;
1344 ti->anchor = tci->anchor;
1345 ti->fileName = tci->filename;
1346 ce->id = tci->clangId;
1348 ce->lang = tci->isObjC ? SrcLangExt_ObjC : SrcLangExt_Unknown;
1349 // transfer base class list
1353 ce->extends = tci->bases; tci->bases = 0;
1355 if (tci->templateArguments)
1357 if (ce->tArgLists==0)
1359 ce->tArgLists = new QList<ArgumentList>;
1360 ce->tArgLists->setAutoDelete(TRUE);
1362 ArgumentList *al = new ArgumentList;
1363 ce->tArgLists->append(al);
1365 QListIterator<QCString> sli(*tci->templateArguments);
1367 for (;(argName=sli.current());++sli)
1369 Argument *a = new Argument;
1376 buildMemberList(ce,tci->members);
1377 root->addSubEntry(ce);
1381 QListIterator<TagFileInfo> fit(m_tagFileFiles);
1383 for (fit.toFirst();(tfi=fit.current());++fit)
1385 Entry *fe = new Entry;
1386 fe->section = guessSection(tfi->name);
1387 fe->name = tfi->name;
1388 addDocAnchors(fe,tfi->docAnchors);
1389 TagInfo *ti = new TagInfo;
1390 ti->tagName = m_tagName;
1391 ti->fileName = tfi->filename;
1394 QCString fullName = m_tagName+":"+tfi->path+stripPath(tfi->name);
1395 fe->fileName = fullName;
1396 //printf("new FileDef() filename=%s\n",tfi->filename.data());
1397 FileDef *fd = new FileDef(m_tagName+":"+tfi->path,
1398 tfi->name,m_tagName,
1402 if ((mn=Doxygen::inputNameDict->find(tfi->name)))
1408 mn = new FileName(fullName,tfi->name);
1410 Doxygen::inputNameList->inSort(mn);
1411 Doxygen::inputNameDict->insert(tfi->name,mn);
1413 buildMemberList(fe,tfi->members);
1414 root->addSubEntry(fe);
1417 // build namespace list
1418 QListIterator<TagNamespaceInfo> nit(m_tagFileNamespaces);
1419 TagNamespaceInfo *tni;
1420 for (nit.toFirst();(tni=nit.current());++nit)
1422 Entry *ne = new Entry;
1423 ne->section = Entry::NAMESPACE_SEC;
1424 ne->name = tni->name;
1425 addDocAnchors(ne,tni->docAnchors);
1426 TagInfo *ti = new TagInfo;
1427 ti->tagName = m_tagName;
1428 ti->fileName = tni->filename;
1429 ne->id = tni->clangId;
1432 buildMemberList(ne,tni->members);
1433 root->addSubEntry(ne);
1436 // build package list
1437 QListIterator<TagPackageInfo> pit(m_tagFilePackages);
1438 TagPackageInfo *tpgi;
1439 for (pit.toFirst();(tpgi=pit.current());++pit)
1441 Entry *pe = new Entry;
1442 pe->section = Entry::PACKAGE_SEC;
1443 pe->name = tpgi->name;
1444 addDocAnchors(pe,tpgi->docAnchors);
1445 TagInfo *ti = new TagInfo;
1446 ti->tagName = m_tagName;
1447 ti->fileName = tpgi->filename;
1450 buildMemberList(pe,tpgi->members);
1451 root->addSubEntry(pe);
1455 QListIterator<TagGroupInfo> git(m_tagFileGroups);
1457 for (git.toFirst();(tgi=git.current());++git)
1459 Entry *ge = new Entry;
1460 ge->section = Entry::GROUPDOC_SEC;
1461 ge->name = tgi->name;
1462 ge->type = tgi->title;
1463 addDocAnchors(ge,tgi->docAnchors);
1464 TagInfo *ti = new TagInfo;
1465 ti->tagName = m_tagName;
1466 ti->fileName = tgi->filename;
1469 buildMemberList(ge,tgi->members);
1470 root->addSubEntry(ge);
1473 // set subgroup relations bug_774118
1474 for (git.toFirst();(tgi=git.current());++git)
1476 QCStringList::Iterator it;
1477 for ( it = tgi->subgroupList.begin(); it != tgi->subgroupList.end(); ++it )
1479 QListIterator<Entry> eli(*(root->children()));
1481 for (eli.toFirst();(childNode=eli.current());++eli)
1483 if (childNode->name == (*it)) break;
1485 childNode->groups->append(new Grouping(tgi->name,Grouping::GROUPING_INGROUP));
1490 QListIterator<TagPageInfo> pgit(m_tagFilePages);
1492 for (pgit.toFirst();(tpi=pgit.current());++pgit)
1494 Entry *pe = new Entry;
1495 pe->section = tpi->filename=="index" ? Entry::MAINPAGEDOC_SEC : Entry::PAGEDOC_SEC;
1496 pe->name = tpi->name;
1497 pe->args = tpi->title;
1498 addDocAnchors(pe,tpi->docAnchors);
1499 TagInfo *ti = new TagInfo;
1500 ti->tagName = m_tagName;
1501 ti->fileName = tpi->filename;
1503 root->addSubEntry(pe);
1507 void TagFileParser::addIncludes()
1509 QListIterator<TagFileInfo> fit(m_tagFileFiles);
1511 for (fit.toFirst();(tfi=fit.current());++fit)
1513 //printf("tag file tagName=%s path=%s name=%s\n",m_tagName.data(),tfi->path.data(),tfi->name.data());
1514 FileName *fn = Doxygen::inputNameDict->find(tfi->name);
1517 //printf("found\n");
1518 FileNameIterator fni(*fn);
1520 for (;(fd=fni.current());++fni)
1522 //printf("input file path=%s name=%s\n",fd->getPath().data(),fd->name().data());
1523 if (fd->getPath()==QCString(m_tagName+":"+tfi->path))
1525 //printf("found\n");
1526 QListIterator<TagIncludeInfo> mii(tfi->includes);
1528 for (;(ii=mii.current());++mii)
1530 //printf("ii->name=`%s'\n",ii->name.data());
1531 FileName *ifn = Doxygen::inputNameDict->find(ii->name);
1535 FileNameIterator ifni(*ifn);
1537 for (;(ifd=ifni.current());++ifni)
1539 //printf("ifd->getOutputFileBase()=%s ii->id=%s\n",
1540 // ifd->getOutputFileBase().data(),ii->id.data());
1541 if (ifd->getOutputFileBase()==QCString(ii->id))
1543 fd->addIncludeDependency(ifd,ii->text,ii->isLocal,ii->isImported,FALSE);
1554 void parseTagFile(Entry *root,const char *fullName)
1556 QFileInfo fi(fullName);
1557 if (!fi.exists()) return;
1558 TagFileParser handler( fullName ); // tagName
1559 handler.setFileName(fullName);
1560 TagFileErrorHandler errorHandler;
1561 QFile xmlFile( fullName );
1562 QXmlInputSource source( xmlFile );
1563 QXmlSimpleReader reader;
1564 reader.setContentHandler( &handler );
1565 reader.setErrorHandler( &errorHandler );
1566 reader.parse( source );
1567 handler.buildLists(root);
1568 handler.addIncludes();