1 /******************************************************************************
3 * $Id: tagreader.cpp,v 1.2 2001/03/19 19:27:41 root Exp $
6 * Copyright (C) 1997-2012 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"
39 //#include "reflist.h"
41 /** Information about an linkable anchor */
45 TagAnchorInfo(const QCString &f,const QCString &l) : label(l), fileName(f) {}
50 /** List of TagAnchorInfo objects. */
51 class TagAnchorInfoList : public QList<TagAnchorInfo>
54 TagAnchorInfoList() : QList<TagAnchorInfo>() { setAutoDelete(TRUE); }
55 virtual ~TagAnchorInfoList() {}
58 /** Container for member specific info that can be read from a tagfile */
62 TagMemberInfo() : prot(Public), virt(Normal), isStatic(FALSE) {}
69 TagAnchorInfoList docAnchors;
75 /** Container for class specific info that can be read from a tagfile */
79 enum Kind { Class, Struct, Union, Interface, Exception, Protocol, Category };
80 TagClassInfo() { bases=0, templateArguments=0; members.setAutoDelete(TRUE); isObjC=FALSE; }
81 ~TagClassInfo() { delete bases; delete templateArguments; }
84 TagAnchorInfoList docAnchors;
85 QList<BaseInfo> *bases;
86 QList<TagMemberInfo> members;
87 QList<QCString> *templateArguments;
88 QStringList classList;
93 /** Container for namespace specific info that can be read from a tagfile */
94 class TagNamespaceInfo
97 TagNamespaceInfo() { members.setAutoDelete(TRUE); }
100 QStringList classList;
101 QStringList namespaceList;
102 TagAnchorInfoList docAnchors;
103 QList<TagMemberInfo> members;
106 /** Container for package specific info that can be read from a tagfile */
110 TagPackageInfo() { members.setAutoDelete(TRUE); }
113 TagAnchorInfoList docAnchors;
114 QList<TagMemberInfo> members;
115 QStringList classList;
118 /** Container for include info that can be read from a tagfile */
129 /** Container for file specific info that can be read from a tagfile */
133 TagFileInfo() { members.setAutoDelete(TRUE); includes.setAutoDelete(TRUE); }
137 TagAnchorInfoList docAnchors;
138 QList<TagMemberInfo> members;
139 QStringList classList;
140 QStringList namespaceList;
141 QList<TagIncludeInfo> includes;
144 /** Container for group specific info that can be read from a tagfile */
148 TagGroupInfo() { members.setAutoDelete(TRUE); }
152 TagAnchorInfoList docAnchors;
153 QList<TagMemberInfo> members;
154 QStringList subgroupList;
155 QStringList classList;
156 QStringList namespaceList;
157 QStringList fileList;
158 QStringList pageList;
162 /** Container for page specific info that can be read from a tagfile */
169 TagAnchorInfoList docAnchors;
172 /** Container for directory specific info that can be read from a tagfile */
179 QStringList subdirList;
180 QStringList fileList;
181 TagAnchorInfoList docAnchors;
186 * Reads an XML-structured tagfile and builds up the structure in
187 * memory. The method buildLists() is used to transfer/translate
188 * the structures to the doxygen engine.
190 class TagFileParser : public QXmlDefaultHandler
192 enum State { Invalid,
203 class StartElementHandler
205 typedef void (TagFileParser::*Handler)(const QXmlAttributes &attrib);
207 StartElementHandler(TagFileParser *parent, Handler h) : m_parent(parent), m_handler(h) {}
208 void operator()(const QXmlAttributes &attrib) { (m_parent->*m_handler)(attrib); }
210 TagFileParser *m_parent;
214 class EndElementHandler
216 typedef void (TagFileParser::*Handler)();
218 EndElementHandler(TagFileParser *parent, Handler h) : m_parent(parent), m_handler(h) {}
219 void operator()() { (m_parent->*m_handler)(); }
221 TagFileParser *m_parent;
226 TagFileParser(const char *tagName) : m_startElementHandlers(17),
227 m_endElementHandlers(17),
230 m_startElementHandlers.setAutoDelete(TRUE);
231 m_endElementHandlers.setAutoDelete(TRUE);
234 void setDocumentLocator ( QXmlLocator * locator )
239 void setFileName( const QString &fileName )
241 m_inputFileName = fileName.utf8();
244 void warn(const char *fmt)
246 ::warn(m_inputFileName,m_locator->lineNumber(),fmt);
248 void warn(const char *fmt,const char *s)
250 ::warn(m_inputFileName,m_locator->lineNumber(),fmt,s);
253 void startCompound( const QXmlAttributes& attrib )
256 QString kind = attrib.value("kind");
257 QString isObjC = attrib.value("objc");
260 m_curClass = new TagClassInfo;
261 m_curClass->kind = TagClassInfo::Class;
264 else if (kind=="struct")
266 m_curClass = new TagClassInfo;
267 m_curClass->kind = TagClassInfo::Struct;
270 else if (kind=="union")
272 m_curClass = new TagClassInfo;
273 m_curClass->kind = TagClassInfo::Union;
276 else if (kind=="interface")
278 m_curClass = new TagClassInfo;
279 m_curClass->kind = TagClassInfo::Interface;
282 else if (kind=="exception")
284 m_curClass = new TagClassInfo;
285 m_curClass->kind = TagClassInfo::Exception;
288 else if (kind=="protocol")
290 m_curClass = new TagClassInfo;
291 m_curClass->kind = TagClassInfo::Protocol;
294 else if (kind=="category")
296 m_curClass = new TagClassInfo;
297 m_curClass->kind = TagClassInfo::Category;
300 else if (kind=="file")
302 m_curFile = new TagFileInfo;
305 else if (kind=="namespace")
307 m_curNamespace = new TagNamespaceInfo;
308 m_state = InNamespace;
310 else if (kind=="group")
312 m_curGroup = new TagGroupInfo;
315 else if (kind=="page")
317 m_curPage = new TagPageInfo;
320 else if (kind=="package")
322 m_curPackage = new TagPackageInfo;
325 else if (kind=="dir")
327 m_curDir = new TagDirInfo;
332 warn("warning: Unknown compound attribute `%s' found!\n",kind.data());
335 if (isObjC=="yes" && m_curClass)
337 m_curClass->isObjC = TRUE;
345 case InClass: m_tagFileClasses.append(m_curClass);
347 case InFile: m_tagFileFiles.append(m_curFile);
349 case InNamespace: m_tagFileNamespaces.append(m_curNamespace);
350 m_curNamespace=0; break;
351 case InGroup: m_tagFileGroups.append(m_curGroup);
353 case InPage: m_tagFilePages.append(m_curPage);
355 case InDir: m_tagFileDirs.append(m_curDir);
357 case InPackage: m_tagFilePackages.append(m_curPackage);
358 m_curPackage=0; break;
360 warn("warning: tag `compound' was not expected!\n");
364 void startMember( const QXmlAttributes& attrib)
366 m_curMember = new TagMemberInfo;
367 m_curMember->kind = attrib.value("kind").utf8();
368 QCString protStr = attrib.value("protection").utf8();
369 QCString virtStr = attrib.value("virtualness").utf8();
370 QCString staticStr = attrib.value("static").utf8();
371 if (protStr=="protected")
373 m_curMember->prot = Protected;
375 else if (protStr=="private")
377 m_curMember->prot = Private;
379 if (virtStr=="virtual")
381 m_curMember->virt = Virtual;
383 else if (virtStr=="pure")
385 m_curMember->virt = Pure;
387 if (staticStr=="yes")
389 m_curMember->isStatic = TRUE;
391 m_stateStack.push(new State(m_state));
397 m_state = *m_stateStack.top();
398 m_stateStack.remove();
401 case InClass: m_curClass->members.append(m_curMember); break;
402 case InFile: m_curFile->members.append(m_curMember); break;
403 case InNamespace: m_curNamespace->members.append(m_curMember); break;
404 case InGroup: m_curGroup->members.append(m_curMember); break;
405 case InPackage: m_curPackage->members.append(m_curMember); break;
406 default: warn("warning: Unexpected tag `member' found\n"); break;
414 case InClass: m_curClass->docAnchors.append(new TagAnchorInfo(m_fileName,m_curString)); break;
415 case InFile: m_curFile->docAnchors.append(new TagAnchorInfo(m_fileName,m_curString)); break;
416 case InNamespace: m_curNamespace->docAnchors.append(new TagAnchorInfo(m_fileName,m_curString)); break;
417 case InGroup: m_curGroup->docAnchors.append(new TagAnchorInfo(m_fileName,m_curString)); break;
418 case InPage: m_curPage->docAnchors.append(new TagAnchorInfo(m_fileName,m_curString)); break;
419 case InMember: m_curMember->docAnchors.append(new TagAnchorInfo(m_fileName,m_curString)); break;
420 case InPackage: m_curPackage->docAnchors.append(new TagAnchorInfo(m_fileName,m_curString)); break;
421 case InDir: m_curDir->docAnchors.append(new TagAnchorInfo(m_fileName,m_curString)); break;
422 default: warn("warning: Unexpected tag `member' found\n"); break;
430 case InClass: m_curClass->classList.append(m_curString); break;
431 case InFile: m_curFile->classList.append(m_curString); break;
432 case InNamespace: m_curNamespace->classList.append(m_curString); break;
433 case InGroup: m_curGroup->classList.append(m_curString); break;
434 case InPackage: m_curPackage->classList.append(m_curString); break;
435 default: warn("warning: Unexpected tag `class' found\n"); break;
443 case InNamespace: m_curNamespace->classList.append(m_curString); break;
444 case InFile: m_curFile->namespaceList.append(m_curString); break;
445 case InGroup: m_curGroup->namespaceList.append(m_curString); break;
446 default: warn("warning: Unexpected tag `namespace' found\n"); break;
454 case InGroup: m_curGroup->fileList.append(m_curString); break;
455 case InDir: m_curDir->fileList.append(m_curString); break;
456 default: warn("warning: Unexpected tag `file' found\n"); break;
464 case InGroup: m_curGroup->fileList.append(m_curString); break;
465 default: warn("warning: Unexpected tag `page' found\n"); break;
473 case InDir: m_curDir->subdirList.append(m_curString); break;
474 default: warn("warning: Unexpected tag `page' found\n"); break;
478 void startStringValue(const QXmlAttributes& )
483 void startDocAnchor(const QXmlAttributes& attrib )
485 m_fileName = attrib.value("file").utf8();
491 if (m_state==InMember)
493 m_curMember->type = m_curString;
497 warn("warning: Unexpected tag `type' found\n");
505 case InClass: m_curClass->name = m_curString; break;
506 case InFile: m_curFile->name = m_curString; break;
507 case InNamespace: m_curNamespace->name = m_curString; break;
508 case InGroup: m_curGroup->name = m_curString; break;
509 case InPage: m_curPage->name = m_curString; break;
510 case InDir: m_curDir->name = m_curString; break;
511 case InMember: m_curMember->name = m_curString; break;
512 case InPackage: m_curPackage->name = m_curString; break;
513 default: warn("warning: Unexpected tag `name' found\n"); break;
517 void startBase(const QXmlAttributes& attrib )
520 if (m_state==InClass && m_curClass)
522 QString protStr = attrib.value("protection");
523 QString virtStr = attrib.value("virtualness");
524 Protection prot = Public;
525 Specifier virt = Normal;
526 if (protStr=="protected")
530 else if (protStr=="private")
534 if (virtStr=="virtual")
538 if (m_curClass->bases==0)
540 m_curClass->bases = new QList<BaseInfo>;
541 m_curClass->bases->setAutoDelete(TRUE);
543 m_curClass->bases->append(new BaseInfo(m_curString,prot,virt));
547 warn("warning: Unexpected tag `base' found\n");
553 if (m_state==InClass && m_curClass)
555 m_curClass->bases->getLast()->name = m_curString;
559 warn("warning: Unexpected tag `base' found\n");
563 void startIncludes(const QXmlAttributes& attrib )
565 if (m_state==InFile && m_curFile)
567 m_curIncludes = new TagIncludeInfo;
568 m_curIncludes->id = attrib.value("id").utf8();
569 m_curIncludes->name = attrib.value("name").utf8();
570 m_curIncludes->isLocal = attrib.value("local").utf8()=="yes" ? TRUE : FALSE;
571 m_curIncludes->isImported = attrib.value("imported").utf8()=="yes" ? TRUE : FALSE;
572 m_curFile->includes.append(m_curIncludes);
576 warn("warning: Unexpected tag `includes' found\n");
583 m_curIncludes->text = m_curString;
586 void endTemplateArg()
588 if (m_state==InClass && m_curClass)
590 if (m_curClass->templateArguments==0)
592 m_curClass->templateArguments = new QList<QCString>;
593 m_curClass->templateArguments->setAutoDelete(TRUE);
595 m_curClass->templateArguments->append(new QCString(m_curString));
599 warn("warning: Unexpected tag `templarg' found\n");
607 case InClass: m_curClass->filename = m_curString; break;
608 case InNamespace: m_curNamespace->filename = m_curString; break;
609 case InFile: m_curFile->filename = m_curString; break;
610 case InGroup: m_curGroup->filename = m_curString; break;
611 case InPage: m_curPage->filename = m_curString; break;
612 case InPackage: m_curPackage->filename = m_curString; break;
613 case InDir: m_curDir->filename = m_curString; break;
614 default: warn("warning: Unexpected tag `filename' found\n"); break;
622 case InFile: m_curFile->path = m_curString; break;
623 case InDir: m_curDir->path = m_curString; break;
624 default: warn("warning: Unexpected tag `path' found\n"); break;
630 if (m_state==InMember)
632 m_curMember->anchor = m_curString;
636 warn("warning: Unexpected tag `anchor' found\n");
642 if (m_state==InMember)
644 m_curMember->anchorFile = m_curString;
648 warn("warning: Unexpected tag `anchorfile' found\n");
654 if (m_state==InMember)
656 m_curMember->arglist = m_curString;
660 warn("warning: Unexpected tag `arglist' found\n");
667 case InGroup: m_curGroup->title = m_curString; break;
668 case InPage: m_curPage->title = m_curString; break;
669 default: warn("warning: Unexpected tag `title' found\n"); break;
675 if (m_state==InGroup)
677 m_curGroup->subgroupList.append(m_curString);
681 warn("warning: Unexpected tag `subgroup' found\n");
685 void startIgnoreElement(const QXmlAttributes& )
689 void endIgnoreElement()
705 m_stateStack.setAutoDelete(TRUE);
706 m_tagFileClasses.setAutoDelete(TRUE);
707 m_tagFileFiles.setAutoDelete(TRUE);
708 m_tagFileNamespaces.setAutoDelete(TRUE);
709 m_tagFileGroups.setAutoDelete(TRUE);
710 m_tagFilePages.setAutoDelete(TRUE);
711 m_tagFilePackages.setAutoDelete(TRUE);
712 m_tagFileDirs.setAutoDelete(TRUE);
714 m_startElementHandlers.insert("compound", new StartElementHandler(this,&TagFileParser::startCompound));
715 m_startElementHandlers.insert("member", new StartElementHandler(this,&TagFileParser::startMember));
716 m_startElementHandlers.insert("name", new StartElementHandler(this,&TagFileParser::startStringValue));
717 m_startElementHandlers.insert("base", new StartElementHandler(this,&TagFileParser::startBase));
718 m_startElementHandlers.insert("filename", new StartElementHandler(this,&TagFileParser::startStringValue));
719 m_startElementHandlers.insert("includes", new StartElementHandler(this,&TagFileParser::startIncludes));
720 m_startElementHandlers.insert("path", new StartElementHandler(this,&TagFileParser::startStringValue));
721 m_startElementHandlers.insert("anchorfile", new StartElementHandler(this,&TagFileParser::startStringValue));
722 m_startElementHandlers.insert("anchor", new StartElementHandler(this,&TagFileParser::startStringValue));
723 m_startElementHandlers.insert("arglist", new StartElementHandler(this,&TagFileParser::startStringValue));
724 m_startElementHandlers.insert("title", new StartElementHandler(this,&TagFileParser::startStringValue));
725 m_startElementHandlers.insert("subgroup", new StartElementHandler(this,&TagFileParser::startStringValue));
726 m_startElementHandlers.insert("class", new StartElementHandler(this,&TagFileParser::startStringValue));
727 m_startElementHandlers.insert("namespace", new StartElementHandler(this,&TagFileParser::startStringValue));
728 m_startElementHandlers.insert("file", new StartElementHandler(this,&TagFileParser::startStringValue));
729 m_startElementHandlers.insert("dir", new StartElementHandler(this,&TagFileParser::startStringValue));
730 m_startElementHandlers.insert("page", new StartElementHandler(this,&TagFileParser::startStringValue));
731 m_startElementHandlers.insert("docanchor", new StartElementHandler(this,&TagFileParser::startDocAnchor));
732 m_startElementHandlers.insert("tagfile", new StartElementHandler(this,&TagFileParser::startIgnoreElement));
733 m_startElementHandlers.insert("templarg", new StartElementHandler(this,&TagFileParser::startStringValue));
734 m_startElementHandlers.insert("type", new StartElementHandler(this,&TagFileParser::startStringValue));
736 m_endElementHandlers.insert("compound", new EndElementHandler(this,&TagFileParser::endCompound));
737 m_endElementHandlers.insert("member", new EndElementHandler(this,&TagFileParser::endMember));
738 m_endElementHandlers.insert("name", new EndElementHandler(this,&TagFileParser::endName));
739 m_endElementHandlers.insert("base", new EndElementHandler(this,&TagFileParser::endBase));
740 m_endElementHandlers.insert("filename", new EndElementHandler(this,&TagFileParser::endFilename));
741 m_endElementHandlers.insert("includes", new EndElementHandler(this,&TagFileParser::endIncludes));
742 m_endElementHandlers.insert("path", new EndElementHandler(this,&TagFileParser::endPath));
743 m_endElementHandlers.insert("anchorfile", new EndElementHandler(this,&TagFileParser::endAnchorFile));
744 m_endElementHandlers.insert("anchor", new EndElementHandler(this,&TagFileParser::endAnchor));
745 m_endElementHandlers.insert("arglist", new EndElementHandler(this,&TagFileParser::endArglist));
746 m_endElementHandlers.insert("title", new EndElementHandler(this,&TagFileParser::endTitle));
747 m_endElementHandlers.insert("subgroup", new EndElementHandler(this,&TagFileParser::endSubgroup));
748 m_endElementHandlers.insert("class" , new EndElementHandler(this,&TagFileParser::endClass));
749 m_endElementHandlers.insert("namespace", new EndElementHandler(this,&TagFileParser::endNamespace));
750 m_endElementHandlers.insert("file", new EndElementHandler(this,&TagFileParser::endFile));
751 m_endElementHandlers.insert("dir", new EndElementHandler(this,&TagFileParser::endDir));
752 m_endElementHandlers.insert("page", new EndElementHandler(this,&TagFileParser::endPage));
753 m_endElementHandlers.insert("docanchor", new EndElementHandler(this,&TagFileParser::endDocAnchor));
754 m_endElementHandlers.insert("tagfile", new EndElementHandler(this,&TagFileParser::endIgnoreElement));
755 m_endElementHandlers.insert("templarg", new EndElementHandler(this,&TagFileParser::endTemplateArg));
756 m_endElementHandlers.insert("type", new EndElementHandler(this,&TagFileParser::endType));
761 bool startElement( const QString&, const QString&,
762 const QString&name, const QXmlAttributes& attrib )
764 //printf("startElement `%s'\n",name.data());
765 StartElementHandler *handler = m_startElementHandlers[name.utf8()];
772 warn("warning: Unknown tag `%s' found!\n",name.data());
777 bool endElement( const QString&, const QString&, const QString& name )
779 //printf("endElement `%s'\n",name.data());
780 EndElementHandler *handler = m_endElementHandlers[name.utf8()];
787 warn("warning: Unknown tag `%s' found!\n",name.data());
792 bool characters ( const QString & ch )
794 m_curString+=ch.utf8();
799 void buildLists(Entry *root);
803 void buildMemberList(Entry *ce,QList<TagMemberInfo> &members);
804 void addDocAnchors(Entry *e,const TagAnchorInfoList &l);
805 QList<TagClassInfo> m_tagFileClasses;
806 QList<TagFileInfo> m_tagFileFiles;
807 QList<TagNamespaceInfo> m_tagFileNamespaces;
808 QList<TagGroupInfo> m_tagFileGroups;
809 QList<TagPageInfo> m_tagFilePages;
810 QList<TagPackageInfo> m_tagFilePackages;
811 QList<TagDirInfo> m_tagFileDirs;
812 QDict<StartElementHandler> m_startElementHandlers;
813 QDict<EndElementHandler> m_endElementHandlers;
814 TagClassInfo *m_curClass;
815 TagFileInfo *m_curFile;
816 TagNamespaceInfo *m_curNamespace;
817 TagPackageInfo *m_curPackage;
818 TagGroupInfo *m_curGroup;
819 TagPageInfo *m_curPage;
820 TagDirInfo *m_curDir;
821 TagMemberInfo *m_curMember;
822 TagIncludeInfo *m_curIncludes;
823 QCString m_curString;
827 QStack<State> m_stateStack;
828 QXmlLocator *m_locator;
829 QCString m_inputFileName;
832 /** Error handler for the XML tag file parser.
834 * Basically dumps all fatal error to stderr using err().
836 class TagFileErrorHandler : public QXmlErrorHandler
839 virtual ~TagFileErrorHandler() {}
840 bool warning( const QXmlParseException & )
844 bool error( const QXmlParseException & )
848 bool fatalError( const QXmlParseException &exception )
850 err("Fatal error at line %d column %d: %s\n",
851 exception.lineNumber(),exception.columnNumber(),
852 exception.message().data());
855 QString errorString() { return ""; }
861 /*! Dumps the internal structures. For debugging only! */
862 void TagFileParser::dump()
865 QListIterator<TagClassInfo> lci(m_tagFileClasses);
867 //============== CLASSES
869 for (;(cd=lci.current());++lci)
871 msg("class `%s'\n",cd->name.data());
872 msg(" filename `%s'\n",cd->filename.data());
875 QListIterator<BaseInfo> bii(*cd->bases);
877 for ( bii.toFirst() ; (bi=bii.current()) ; ++bii)
879 msg( " base: %s \n", bi->name.data() );
883 QListIterator<TagMemberInfo> mci(cd->members);
885 for (;(md=mci.current());++mci)
888 msg(" kind: `%s'\n",md->kind.data());
889 msg(" name: `%s'\n",md->name.data());
890 msg(" anchor: `%s'\n",md->anchor.data());
891 msg(" arglist: `%s'\n",md->arglist.data());
894 //============== NAMESPACES
895 QListIterator<TagNamespaceInfo> lni(m_tagFileNamespaces);
896 TagNamespaceInfo *nd;
897 for (;(nd=lni.current());++lni)
899 msg("namespace `%s'\n",nd->name.data());
900 msg(" filename `%s'\n",nd->filename.data());
901 QStringList::Iterator it;
902 for ( it = nd->classList.begin();
903 it != nd->classList.end(); ++it )
905 msg( " class: %s \n", (*it).latin1() );
908 QListIterator<TagMemberInfo> mci(nd->members);
910 for (;(md=mci.current());++mci)
913 msg(" kind: `%s'\n",md->kind.data());
914 msg(" name: `%s'\n",md->name.data());
915 msg(" anchor: `%s'\n",md->anchor.data());
916 msg(" arglist: `%s'\n",md->arglist.data());
919 //============== FILES
920 QListIterator<TagFileInfo> lfi(m_tagFileFiles);
922 for (;(fd=lfi.current());++lfi)
924 msg("file `%s'\n",fd->name.data());
925 msg(" filename `%s'\n",fd->filename.data());
926 QStringList::Iterator it;
927 for ( it = fd->namespaceList.begin();
928 it != fd->namespaceList.end(); ++it )
930 msg( " namespace: %s \n", (*it).latin1() );
932 for ( it = fd->classList.begin();
933 it != fd->classList.end(); ++it )
935 msg( " class: %s \n", (*it).latin1() );
938 QListIterator<TagMemberInfo> mci(fd->members);
940 for (;(md=mci.current());++mci)
943 msg(" kind: `%s'\n",md->kind.data());
944 msg(" name: `%s'\n",md->name.data());
945 msg(" anchor: `%s'\n",md->anchor.data());
946 msg(" arglist: `%s'\n",md->arglist.data());
949 QListIterator<TagIncludeInfo> mii(fd->includes);
951 for (;(ii=mii.current());++mii)
953 msg(" includes id: %s name: %s\n",ii->id.data(),ii->name.data());
957 //============== GROUPS
958 QListIterator<TagGroupInfo> lgi(m_tagFileGroups);
960 for (;(gd=lgi.current());++lgi)
962 msg("group `%s'\n",gd->name.data());
963 msg(" filename `%s'\n",gd->filename.data());
964 QStringList::Iterator it;
965 for ( it = gd->namespaceList.begin();
966 it != gd->namespaceList.end(); ++it )
968 msg( " namespace: %s \n", (*it).latin1() );
970 for ( it = gd->classList.begin();
971 it != gd->classList.end(); ++it )
973 msg( " class: %s \n", (*it).latin1() );
975 for ( it = gd->fileList.begin();
976 it != gd->fileList.end(); ++it )
978 msg( " file: %s \n", (*it).latin1() );
980 for ( it = gd->subgroupList.begin();
981 it != gd->subgroupList.end(); ++it )
983 msg( " subgroup: %s \n", (*it).latin1() );
985 for ( it = gd->pageList.begin();
986 it != gd->pageList.end(); ++it )
988 msg( " page: %s \n", (*it).latin1() );
991 QListIterator<TagMemberInfo> mci(gd->members);
993 for (;(md=mci.current());++mci)
996 msg(" kind: `%s'\n",md->kind.data());
997 msg(" name: `%s'\n",md->name.data());
998 msg(" anchor: `%s'\n",md->anchor.data());
999 msg(" arglist: `%s'\n",md->arglist.data());
1002 //============== PAGES
1003 QListIterator<TagPageInfo> lpi(m_tagFilePages);
1005 for (;(pd=lpi.current());++lpi)
1007 msg("page `%s'\n",pd->name.data());
1008 msg(" title `%s'\n",pd->title.data());
1009 msg(" filename `%s'\n",pd->filename.data());
1011 //============== DIRS
1012 QListIterator<TagDirInfo> ldi(m_tagFileDirs);
1014 for (;(dd=ldi.current());++ldi)
1016 msg("dir `%s'\n",dd->name.data());
1017 msg(" path `%s'\n",dd->path.data());
1018 QStringList::Iterator it;
1019 for ( it = dd->fileList.begin();
1020 it != dd->fileList.end(); ++it )
1022 msg( " file: %s \n", (*it).latin1() );
1024 for ( it = dd->subdirList.begin();
1025 it != dd->subdirList.end(); ++it )
1027 msg( " subdir: %s \n", (*it).latin1() );
1032 void TagFileParser::addDocAnchors(Entry *e,const TagAnchorInfoList &l)
1034 QListIterator<TagAnchorInfo> tli(l);
1036 for (tli.toFirst();(ta=tli.current());++tli)
1038 if (Doxygen::sectionDict.find(ta->label)==0)
1040 //printf("New sectionInfo file=%s anchor=%s\n",
1041 // ta->fileName.data(),ta->label.data());
1042 SectionInfo *si=new SectionInfo(ta->fileName,ta->label,ta->label,
1043 SectionInfo::Anchor,0,m_tagName);
1044 Doxygen::sectionDict.append(ta->label,si);
1045 e->anchors->append(si);
1049 warn("Duplicate anchor %s found\n",ta->label.data());
1054 void TagFileParser::buildMemberList(Entry *ce,QList<TagMemberInfo> &members)
1056 QListIterator<TagMemberInfo> mii(members);
1058 for (;(tmi=mii.current());++mii)
1060 Entry *me = new Entry;
1061 me->type = tmi->type;
1062 me->name = tmi->name;
1063 me->args = tmi->arglist;
1064 if (!me->args.isEmpty())
1067 me->argList = new ArgumentList;
1068 stringToArgumentList(me->args,me->argList);
1070 me->protection = tmi->prot;
1071 me->virt = tmi->virt;
1072 me->stat = tmi->isStatic;
1073 me->fileName = ce->fileName;
1074 if (ce->section == Entry::GROUPDOC_SEC)
1076 me->groups->append(new Grouping(ce->name,Grouping::GROUPING_INGROUP));
1078 addDocAnchors(me,tmi->docAnchors);
1079 TagInfo *ti = new TagInfo;
1080 ti->tagName = m_tagName;
1081 ti->anchor = tmi->anchor;
1082 ti->fileName = tmi->anchorFile;
1084 if (tmi->kind=="define")
1087 me->section = Entry::DEFINE_SEC;
1089 else if (tmi->kind=="enumvalue")
1091 me->section = Entry::VARIABLE_SEC;
1094 else if (tmi->kind=="property")
1096 me->section = Entry::VARIABLE_SEC;
1097 me->mtype = Property;
1099 else if (tmi->kind=="event")
1101 me->section = Entry::VARIABLE_SEC;
1104 else if (tmi->kind=="variable")
1106 me->section = Entry::VARIABLE_SEC;
1109 else if (tmi->kind=="typedef")
1111 me->section = Entry::VARIABLE_SEC; //Entry::TYPEDEF_SEC;
1112 me->type.prepend("typedef ");
1115 else if (tmi->kind=="enumeration")
1117 me->section = Entry::ENUM_SEC;
1120 else if (tmi->kind=="function")
1122 me->section = Entry::FUNCTION_SEC;
1125 else if (tmi->kind=="signal")
1127 me->section = Entry::FUNCTION_SEC;
1130 else if (tmi->kind=="prototype")
1132 me->section = Entry::FUNCTION_SEC;
1135 else if (tmi->kind=="friend")
1137 me->section = Entry::FUNCTION_SEC;
1138 me->type.prepend("friend ");
1141 else if (tmi->kind=="dcop")
1143 me->section = Entry::FUNCTION_SEC;
1146 else if (tmi->kind=="slot")
1148 me->section = Entry::FUNCTION_SEC;
1151 ce->addSubEntry(me);
1155 static QCString stripPath(const QCString &s)
1157 int i=s.findRev('/');
1160 return s.right(s.length()-i-1);
1168 /*! Injects the info gathered by the XML parser into the Entry tree.
1169 * This tree contains the information extracted from the input in a
1172 void TagFileParser::buildLists(Entry *root)
1175 TagClassInfo *tci = m_tagFileClasses.first();
1178 Entry *ce = new Entry;
1179 ce->section = Entry::CLASS_SEC;
1182 case TagClassInfo::Class: break;
1183 case TagClassInfo::Struct: ce->spec = Entry::Struct; break;
1184 case TagClassInfo::Union: ce->spec = Entry::Union; break;
1185 case TagClassInfo::Interface: ce->spec = Entry::Interface; break;
1186 case TagClassInfo::Exception: ce->spec = Entry::Exception; break;
1187 case TagClassInfo::Protocol: ce->spec = Entry::Protocol; break;
1188 case TagClassInfo::Category: ce->spec = Entry::Category; break;
1190 ce->name = tci->name;
1191 if (tci->kind==TagClassInfo::Protocol)
1195 addDocAnchors(ce,tci->docAnchors);
1196 TagInfo *ti = new TagInfo;
1197 ti->tagName = m_tagName;
1198 ti->fileName = tci->filename;
1200 ce->lang = tci->isObjC ? SrcLangExt_ObjC : SrcLangExt_Unknown;
1201 // transfer base class list
1205 ce->extends = tci->bases; tci->bases = 0;
1207 if (tci->templateArguments)
1209 if (ce->tArgLists==0)
1211 ce->tArgLists = new QList<ArgumentList>;
1212 ce->tArgLists->setAutoDelete(TRUE);
1214 ArgumentList *al = new ArgumentList;
1215 ce->tArgLists->append(al);
1217 QListIterator<QCString> sli(*tci->templateArguments);
1219 for (;(argName=sli.current());++sli)
1221 Argument *a = new Argument;
1228 buildMemberList(ce,tci->members);
1229 root->addSubEntry(ce);
1230 tci = m_tagFileClasses.next();
1234 TagFileInfo *tfi = m_tagFileFiles.first();
1237 Entry *fe = new Entry;
1238 fe->section = guessSection(tfi->name);
1239 fe->name = tfi->name;
1240 addDocAnchors(fe,tfi->docAnchors);
1241 TagInfo *ti = new TagInfo;
1242 ti->tagName = m_tagName;
1243 ti->fileName = tfi->filename;
1246 QCString fullName = m_tagName+":"+tfi->path+stripPath(tfi->name);
1247 fe->fileName = fullName;
1248 //printf("new FileDef() filename=%s\n",tfi->filename.data());
1249 FileDef *fd = new FileDef(m_tagName+":"+tfi->path,
1250 tfi->name,m_tagName,
1254 if ((mn=Doxygen::inputNameDict->find(tfi->name)))
1260 mn = new FileName(fullName,tfi->name);
1262 Doxygen::inputNameList->inSort(mn);
1263 Doxygen::inputNameDict->insert(tfi->name,mn);
1265 buildMemberList(fe,tfi->members);
1266 root->addSubEntry(fe);
1267 tfi = m_tagFileFiles.next();
1270 // build namespace list
1271 TagNamespaceInfo *tni = m_tagFileNamespaces.first();
1274 Entry *ne = new Entry;
1275 ne->section = Entry::NAMESPACE_SEC;
1276 ne->name = tni->name;
1277 addDocAnchors(ne,tni->docAnchors);
1278 TagInfo *ti = new TagInfo;
1279 ti->tagName = m_tagName;
1280 ti->fileName = tni->filename;
1283 buildMemberList(ne,tni->members);
1284 root->addSubEntry(ne);
1285 tni = m_tagFileNamespaces.next();
1288 // build package list
1289 TagPackageInfo *tpgi = m_tagFilePackages.first();
1292 Entry *pe = new Entry;
1293 pe->section = Entry::PACKAGE_SEC;
1294 pe->name = tpgi->name;
1295 addDocAnchors(pe,tpgi->docAnchors);
1296 TagInfo *ti = new TagInfo;
1297 ti->tagName = m_tagName;
1298 ti->fileName = tpgi->filename;
1301 buildMemberList(pe,tpgi->members);
1302 root->addSubEntry(pe);
1303 tpgi = m_tagFilePackages.next();
1306 // build group list, but only if config file says to include it
1307 //if (Config_getBool("EXTERNAL_GROUPS"))
1309 TagGroupInfo *tgi = m_tagFileGroups.first();
1312 Entry *ge = new Entry;
1313 ge->section = Entry::GROUPDOC_SEC;
1314 ge->name = tgi->name;
1315 ge->type = tgi->title;
1316 addDocAnchors(ge,tgi->docAnchors);
1317 TagInfo *ti = new TagInfo;
1318 ti->tagName = m_tagName;
1319 ti->fileName = tgi->filename;
1322 buildMemberList(ge,tgi->members);
1323 root->addSubEntry(ge);
1324 tgi = m_tagFileGroups.next();
1329 TagPageInfo *tpi = m_tagFilePages.first();
1332 Entry *pe = new Entry;
1333 pe->section = Entry::PAGEDOC_SEC;
1334 pe->name = tpi->name;
1335 pe->args = tpi->title;
1336 addDocAnchors(pe,tpi->docAnchors);
1337 TagInfo *ti = new TagInfo;
1338 ti->tagName = m_tagName;
1339 ti->fileName = tpi->filename;
1342 root->addSubEntry(pe);
1343 tpi = m_tagFilePages.next();
1347 void TagFileParser::addIncludes()
1349 TagFileInfo *tfi = m_tagFileFiles.first();
1352 //printf("tag file tagName=%s path=%s name=%s\n",m_tagName.data(),tfi->path.data(),tfi->name.data());
1353 FileName *fn = Doxygen::inputNameDict->find(tfi->name);
1356 //printf("found\n");
1357 FileNameIterator fni(*fn);
1359 for (;(fd=fni.current());++fni)
1361 //printf("input file path=%s name=%s\n",fd->getPath().data(),fd->name().data());
1362 if (fd->getPath()==QCString(m_tagName+":"+tfi->path))
1364 //printf("found\n");
1365 QListIterator<TagIncludeInfo> mii(tfi->includes);
1367 for (;(ii=mii.current());++mii)
1369 //printf("ii->name=`%s'\n",ii->name.data());
1370 FileName *ifn = Doxygen::inputNameDict->find(ii->name);
1374 FileNameIterator ifni(*ifn);
1376 for (;(ifd=ifni.current());++ifni)
1378 //printf("ifd->getOutputFileBase()=%s ii->id=%s\n",
1379 // ifd->getOutputFileBase().data(),ii->id.data());
1380 if (ifd->getOutputFileBase()==QCString(ii->id))
1382 fd->addIncludeDependency(ifd,ii->text,ii->isLocal,ii->isImported,FALSE);
1390 tfi = m_tagFileFiles.next();
1394 void parseTagFile(Entry *root,const char *fullName,const char *tagName)
1396 QFileInfo fi(fullName);
1397 if (!fi.exists()) return;
1398 TagFileParser handler( tagName );
1399 handler.setFileName(fullName);
1400 TagFileErrorHandler errorHandler;
1401 QFile xmlFile( fullName );
1402 QXmlInputSource source( xmlFile );
1403 QXmlSimpleReader reader;
1404 reader.setContentHandler( &handler );
1405 reader.setErrorHandler( &errorHandler );
1406 reader.parse( source );
1407 handler.buildLists(root);
1408 handler.addIncludes();