00001 /****************************************************************************** 00002 * 00003 * $Id: tagreader.cpp,v 1.2 2001/03/19 19:27:41 root Exp $ 00004 * 00005 * 00006 * Copyright (C) 1997-2008 by Dimitri van Heesch. 00007 * 00008 * Permission to use, copy, modify, and distribute this software and its 00009 * documentation under the terms of the GNU General Public License is hereby 00010 * granted. No representations are made about the suitability of this software 00011 * for any purpose. It is provided "as is" without express or implied warranty. 00012 * See the GNU General Public License for more details. 00013 * 00014 * Documents produced by Doxygen are derivative works derived from the 00015 * input used in their production; they are not affected by this license. 00016 * 00017 */ 00018 00019 #include "tagreader.h" 00020 00021 #include <stdio.h> 00022 #include <stdarg.h> 00023 00024 #include <qxml.h> 00025 #include <qstack.h> 00026 #include <qdict.h> 00027 #include <qfileinfo.h> 00028 #include <qlist.h> 00029 #include <qstring.h> 00030 #include <qstringlist.h> 00031 00032 #include "entry.h" 00033 #include "classdef.h" 00034 #include "doxygen.h" 00035 #include "util.h" 00036 #include "message.h" 00037 #include "defargs.h" 00038 //#include "reflist.h" 00039 00041 class TagAnchorInfo 00042 { 00043 public: 00044 TagAnchorInfo(const QString &f,const QString &l) : label(l), fileName(f) {} 00045 QString label; 00046 QString fileName; 00047 }; 00048 00049 class TagAnchorInfoList : public QList<TagAnchorInfo> 00050 { 00051 public: 00052 TagAnchorInfoList() : QList<TagAnchorInfo>() { setAutoDelete(TRUE); } 00053 virtual ~TagAnchorInfoList() {} 00054 }; 00055 00057 class TagMemberInfo 00058 { 00059 public: 00060 TagMemberInfo() : prot(Public), virt(Normal), isStatic(FALSE) {} 00061 QString type; 00062 QString name; 00063 QString anchorFile; 00064 QString anchor; 00065 QString arglist; 00066 QString kind; 00067 TagAnchorInfoList docAnchors; 00068 Protection prot; 00069 Specifier virt; 00070 bool isStatic; 00071 }; 00072 00074 class TagClassInfo 00075 { 00076 public: 00077 enum Kind { Class, Struct, Union, Interface, Exception, Protocol, Category }; 00078 TagClassInfo() { bases=0, templateArguments=0; members.setAutoDelete(TRUE); isObjC=FALSE; } 00079 ~TagClassInfo() { delete bases; delete templateArguments; } 00080 QString name; 00081 QString filename; 00082 TagAnchorInfoList docAnchors; 00083 QList<BaseInfo> *bases; 00084 QList<TagMemberInfo> members; 00085 QList<QString> *templateArguments; 00086 QStringList classList; 00087 Kind kind; 00088 bool isObjC; 00089 }; 00090 00092 class TagNamespaceInfo 00093 { 00094 public: 00095 TagNamespaceInfo() { members.setAutoDelete(TRUE); } 00096 QString name; 00097 QString filename; 00098 QStringList classList; 00099 QStringList namespaceList; 00100 TagAnchorInfoList docAnchors; 00101 QList<TagMemberInfo> members; 00102 }; 00103 00105 class TagPackageInfo 00106 { 00107 public: 00108 TagPackageInfo() { members.setAutoDelete(TRUE); } 00109 QString name; 00110 QString filename; 00111 TagAnchorInfoList docAnchors; 00112 QList<TagMemberInfo> members; 00113 QStringList classList; 00114 }; 00115 00116 class TagIncludeInfo 00117 { 00118 public: 00119 QString id; 00120 QString name; 00121 QString text; 00122 bool isLocal; 00123 bool isImported; 00124 }; 00125 00127 class TagFileInfo 00128 { 00129 public: 00130 TagFileInfo() { members.setAutoDelete(TRUE); includes.setAutoDelete(TRUE); } 00131 QString name; 00132 QString path; 00133 QString filename; 00134 TagAnchorInfoList docAnchors; 00135 QList<TagMemberInfo> members; 00136 QStringList classList; 00137 QStringList namespaceList; 00138 QList<TagIncludeInfo> includes; 00139 }; 00140 00142 class TagGroupInfo 00143 { 00144 public: 00145 TagGroupInfo() { members.setAutoDelete(TRUE); } 00146 QString name; 00147 QString title; 00148 QString filename; 00149 TagAnchorInfoList docAnchors; 00150 QList<TagMemberInfo> members; 00151 QStringList subgroupList; 00152 QStringList classList; 00153 QStringList namespaceList; 00154 QStringList fileList; 00155 QStringList pageList; 00156 QStringList dirList; 00157 }; 00158 00160 class TagPageInfo 00161 { 00162 public: 00163 QString name; 00164 QString title; 00165 QString filename; 00166 TagAnchorInfoList docAnchors; 00167 }; 00168 00170 class TagDirInfo 00171 { 00172 public: 00173 QString name; 00174 QString filename; 00175 QString path; 00176 QStringList subdirList; 00177 QStringList fileList; 00178 TagAnchorInfoList docAnchors; 00179 }; 00180 00186 class TagFileParser : public QXmlDefaultHandler 00187 { 00188 enum State { Invalid, 00189 InClass, 00190 InFile, 00191 InNamespace, 00192 InGroup, 00193 InPage, 00194 InMember, 00195 InPackage, 00196 InDir, 00197 InTempArgList 00198 }; 00199 class StartElementHandler 00200 { 00201 typedef void (TagFileParser::*Handler)(const QXmlAttributes &attrib); 00202 public: 00203 StartElementHandler(TagFileParser *parent, Handler h) : m_parent(parent), m_handler(h) {} 00204 void operator()(const QXmlAttributes &attrib) { (m_parent->*m_handler)(attrib); } 00205 private: 00206 TagFileParser *m_parent; 00207 Handler m_handler; 00208 }; 00209 00210 class EndElementHandler 00211 { 00212 typedef void (TagFileParser::*Handler)(); 00213 public: 00214 EndElementHandler(TagFileParser *parent, Handler h) : m_parent(parent), m_handler(h) {} 00215 void operator()() { (m_parent->*m_handler)(); } 00216 private: 00217 TagFileParser *m_parent; 00218 Handler m_handler; 00219 }; 00220 00221 public: 00222 TagFileParser(const char *tagName) : m_startElementHandlers(17), 00223 m_endElementHandlers(17), 00224 m_tagName(tagName) 00225 { 00226 m_startElementHandlers.setAutoDelete(TRUE); 00227 m_endElementHandlers.setAutoDelete(TRUE); 00228 } 00229 00230 void setDocumentLocator ( QXmlLocator * locator ) 00231 { 00232 m_locator = locator; 00233 } 00234 00235 void setFileName( const QString &fileName ) 00236 { 00237 m_inputFileName = fileName; 00238 } 00239 00240 void warn(const char *fmt) 00241 { 00242 ::warn(m_inputFileName,m_locator->lineNumber(),fmt); 00243 } 00244 void warn(const char *fmt,const char *s) 00245 { 00246 ::warn(m_inputFileName,m_locator->lineNumber(),fmt,s); 00247 } 00248 00249 void startCompound( const QXmlAttributes& attrib ) 00250 { 00251 m_curString = ""; 00252 QString kind = attrib.value("kind"); 00253 QString isObjC = attrib.value("objc"); 00254 if (kind=="class") 00255 { 00256 m_curClass = new TagClassInfo; 00257 m_curClass->kind = TagClassInfo::Class; 00258 m_state = InClass; 00259 } 00260 else if (kind=="struct") 00261 { 00262 m_curClass = new TagClassInfo; 00263 m_curClass->kind = TagClassInfo::Struct; 00264 m_state = InClass; 00265 } 00266 else if (kind=="union") 00267 { 00268 m_curClass = new TagClassInfo; 00269 m_curClass->kind = TagClassInfo::Union; 00270 m_state = InClass; 00271 } 00272 else if (kind=="interface") 00273 { 00274 m_curClass = new TagClassInfo; 00275 m_curClass->kind = TagClassInfo::Interface; 00276 m_state = InClass; 00277 } 00278 else if (kind=="exception") 00279 { 00280 m_curClass = new TagClassInfo; 00281 m_curClass->kind = TagClassInfo::Exception; 00282 m_state = InClass; 00283 } 00284 else if (kind=="protocol") 00285 { 00286 m_curClass = new TagClassInfo; 00287 m_curClass->kind = TagClassInfo::Protocol; 00288 m_state = InClass; 00289 } 00290 else if (kind=="category") 00291 { 00292 m_curClass = new TagClassInfo; 00293 m_curClass->kind = TagClassInfo::Category; 00294 m_state = InClass; 00295 } 00296 else if (kind=="file") 00297 { 00298 m_curFile = new TagFileInfo; 00299 m_state = InFile; 00300 } 00301 else if (kind=="namespace") 00302 { 00303 m_curNamespace = new TagNamespaceInfo; 00304 m_state = InNamespace; 00305 } 00306 else if (kind=="group") 00307 { 00308 m_curGroup = new TagGroupInfo; 00309 m_state = InGroup; 00310 } 00311 else if (kind=="page") 00312 { 00313 m_curPage = new TagPageInfo; 00314 m_state = InPage; 00315 } 00316 else if (kind=="package") 00317 { 00318 m_curPackage = new TagPackageInfo; 00319 m_state = InPackage; 00320 } 00321 else if (kind=="dir") 00322 { 00323 m_curDir = new TagDirInfo; 00324 m_state = InDir; 00325 } 00326 else 00327 { 00328 warn("Warning: Unknown compound attribute `%s' found!\n",kind.data()); 00329 } 00330 if (isObjC=="yes" && m_curClass) 00331 { 00332 m_curClass->isObjC = TRUE; 00333 } 00334 } 00335 00336 void endCompound() 00337 { 00338 switch (m_state) 00339 { 00340 case InClass: m_tagFileClasses.append(m_curClass); 00341 m_curClass=0; break; 00342 case InFile: m_tagFileFiles.append(m_curFile); 00343 m_curFile=0; break; 00344 case InNamespace: m_tagFileNamespaces.append(m_curNamespace); 00345 m_curNamespace=0; break; 00346 case InGroup: m_tagFileGroups.append(m_curGroup); 00347 m_curGroup=0; break; 00348 case InPage: m_tagFilePages.append(m_curPage); 00349 m_curPage=0; break; 00350 case InDir: m_tagFileDirs.append(m_curDir); 00351 m_curDir=0; break; 00352 case InPackage: m_tagFilePackages.append(m_curPackage); 00353 m_curPackage=0; break; 00354 default: 00355 warn("Warning: tag `compound' was not expected!\n"); 00356 } 00357 } 00358 00359 void startMember( const QXmlAttributes& attrib) 00360 { 00361 m_curMember = new TagMemberInfo; 00362 m_curMember->kind = attrib.value("kind"); 00363 QString protStr = attrib.value("protection"); 00364 QString virtStr = attrib.value("virtualness"); 00365 QString staticStr = attrib.value("static"); 00366 if (protStr=="protected") 00367 { 00368 m_curMember->prot = Protected; 00369 } 00370 else if (protStr=="private") 00371 { 00372 m_curMember->prot = Private; 00373 } 00374 if (virtStr=="virtual") 00375 { 00376 m_curMember->virt = Virtual; 00377 } 00378 else if (virtStr=="pure") 00379 { 00380 m_curMember->virt = Pure; 00381 } 00382 if (staticStr=="yes") 00383 { 00384 m_curMember->isStatic = TRUE; 00385 } 00386 m_stateStack.push(new State(m_state)); 00387 m_state = InMember; 00388 } 00389 00390 void endMember() 00391 { 00392 m_state = *m_stateStack.top(); 00393 m_stateStack.remove(); 00394 switch(m_state) 00395 { 00396 case InClass: m_curClass->members.append(m_curMember); break; 00397 case InFile: m_curFile->members.append(m_curMember); break; 00398 case InNamespace: m_curNamespace->members.append(m_curMember); break; 00399 case InGroup: m_curGroup->members.append(m_curMember); break; 00400 case InPackage: m_curPackage->members.append(m_curMember); break; 00401 default: warn("Warning: Unexpected tag `member' found\n"); break; 00402 } 00403 } 00404 00405 void endDocAnchor() 00406 { 00407 switch(m_state) 00408 { 00409 case InClass: m_curClass->docAnchors.append(new TagAnchorInfo(m_fileName,m_curString)); break; 00410 case InFile: m_curFile->docAnchors.append(new TagAnchorInfo(m_fileName,m_curString)); break; 00411 case InNamespace: m_curNamespace->docAnchors.append(new TagAnchorInfo(m_fileName,m_curString)); break; 00412 case InGroup: m_curGroup->docAnchors.append(new TagAnchorInfo(m_fileName,m_curString)); break; 00413 case InPage: m_curPage->docAnchors.append(new TagAnchorInfo(m_fileName,m_curString)); break; 00414 case InMember: m_curMember->docAnchors.append(new TagAnchorInfo(m_fileName,m_curString)); break; 00415 case InPackage: m_curPackage->docAnchors.append(new TagAnchorInfo(m_fileName,m_curString)); break; 00416 case InDir: m_curDir->docAnchors.append(new TagAnchorInfo(m_fileName,m_curString)); break; 00417 default: warn("Warning: Unexpected tag `member' found\n"); break; 00418 } 00419 } 00420 00421 void endClass() 00422 { 00423 switch(m_state) 00424 { 00425 case InClass: m_curClass->classList.append(m_curString); break; 00426 case InFile: m_curFile->classList.append(m_curString); break; 00427 case InNamespace: m_curNamespace->classList.append(m_curString); break; 00428 case InGroup: m_curGroup->classList.append(m_curString); break; 00429 case InPackage: m_curPackage->classList.append(m_curString); break; 00430 default: warn("Warning: Unexpected tag `class' found\n"); break; 00431 } 00432 } 00433 00434 void endNamespace() 00435 { 00436 switch(m_state) 00437 { 00438 case InNamespace: m_curNamespace->classList.append(m_curString); break; 00439 case InFile: m_curFile->namespaceList.append(m_curString); break; 00440 case InGroup: m_curGroup->namespaceList.append(m_curString); break; 00441 default: warn("Warning: Unexpected tag `namespace' found\n"); break; 00442 } 00443 } 00444 00445 void endFile() 00446 { 00447 switch(m_state) 00448 { 00449 case InGroup: m_curGroup->fileList.append(m_curString); break; 00450 case InDir: m_curDir->fileList.append(m_curString); break; 00451 default: warn("Warning: Unexpected tag `file' found\n"); break; 00452 } 00453 } 00454 00455 void endPage() 00456 { 00457 switch(m_state) 00458 { 00459 case InGroup: m_curGroup->fileList.append(m_curString); break; 00460 default: warn("Warning: Unexpected tag `page' found\n"); break; 00461 } 00462 } 00463 00464 void endDir() 00465 { 00466 switch(m_state) 00467 { 00468 case InDir: m_curDir->subdirList.append(m_curString); break; 00469 default: warn("Warning: Unexpected tag `page' found\n"); break; 00470 } 00471 } 00472 00473 void startStringValue(const QXmlAttributes& ) 00474 { 00475 m_curString = ""; 00476 } 00477 00478 void startDocAnchor(const QXmlAttributes& attrib ) 00479 { 00480 m_fileName = attrib.value("file"); 00481 m_curString = ""; 00482 } 00483 00484 void endType() 00485 { 00486 if (m_state==InMember) 00487 { 00488 m_curMember->type = m_curString; 00489 } 00490 else 00491 { 00492 warn("Warning: Unexpected tag `type' found\n"); 00493 } 00494 } 00495 00496 void endName() 00497 { 00498 switch (m_state) 00499 { 00500 case InClass: m_curClass->name = m_curString; break; 00501 case InFile: m_curFile->name = m_curString; break; 00502 case InNamespace: m_curNamespace->name = m_curString; break; 00503 case InGroup: m_curGroup->name = m_curString; break; 00504 case InPage: m_curPage->name = m_curString; break; 00505 case InDir: m_curDir->name = m_curString; break; 00506 case InMember: m_curMember->name = m_curString; break; 00507 case InPackage: m_curPackage->name = m_curString; break; 00508 default: warn("Warning: Unexpected tag `name' found\n"); break; 00509 } 00510 } 00511 00512 void startBase(const QXmlAttributes& attrib ) 00513 { 00514 m_curString=""; 00515 if (m_state==InClass && m_curClass) 00516 { 00517 QString protStr = attrib.value("protection"); 00518 QString virtStr = attrib.value("virtualness"); 00519 Protection prot = Public; 00520 Specifier virt = Normal; 00521 if (protStr=="protected") 00522 { 00523 prot = Protected; 00524 } 00525 else if (protStr=="private") 00526 { 00527 prot = Private; 00528 } 00529 if (virtStr=="virtual") 00530 { 00531 virt = Virtual; 00532 } 00533 if (m_curClass->bases==0) 00534 { 00535 m_curClass->bases = new QList<BaseInfo>; 00536 m_curClass->bases->setAutoDelete(TRUE); 00537 } 00538 m_curClass->bases->append(new BaseInfo(m_curString,prot,virt)); 00539 } 00540 else 00541 { 00542 warn("Warning: Unexpected tag `base' found\n"); 00543 } 00544 } 00545 00546 void endBase() 00547 { 00548 if (m_state==InClass && m_curClass) 00549 { 00550 m_curClass->bases->getLast()->name = m_curString; 00551 } 00552 else 00553 { 00554 warn("Warning: Unexpected tag `base' found\n"); 00555 } 00556 } 00557 00558 void startIncludes(const QXmlAttributes& attrib ) 00559 { 00560 if (m_state==InFile && m_curFile) 00561 { 00562 m_curIncludes = new TagIncludeInfo; 00563 m_curIncludes->id = attrib.value("id"); 00564 m_curIncludes->name = attrib.value("name"); 00565 m_curIncludes->isLocal = attrib.value("local")=="yes" ? TRUE : FALSE; 00566 m_curIncludes->isImported = attrib.value("imported")=="yes" ? TRUE : FALSE; 00567 m_curFile->includes.append(m_curIncludes); 00568 } 00569 else 00570 { 00571 warn("Warning: Unexpected tag `includes' found\n"); 00572 } 00573 m_curString=""; 00574 } 00575 00576 void endIncludes() 00577 { 00578 m_curIncludes->text = m_curString; 00579 } 00580 00581 void endTemplateArg() 00582 { 00583 if (m_state==InClass && m_curClass) 00584 { 00585 if (m_curClass->templateArguments==0) 00586 { 00587 m_curClass->templateArguments = new QList<QString>; 00588 m_curClass->templateArguments->setAutoDelete(TRUE); 00589 } 00590 m_curClass->templateArguments->append(new QString(m_curString)); 00591 } 00592 else 00593 { 00594 warn("Warning: Unexpected tag `templarg' found\n"); 00595 } 00596 } 00597 00598 void endFilename() 00599 { 00600 switch (m_state) 00601 { 00602 case InClass: m_curClass->filename = m_curString; break; 00603 case InNamespace: m_curNamespace->filename = m_curString; break; 00604 case InFile: m_curFile->filename = m_curString; break; 00605 case InGroup: m_curGroup->filename = m_curString; break; 00606 case InPage: m_curPage->filename = m_curString; break; 00607 case InPackage: m_curPackage->filename = m_curString; break; 00608 case InDir: m_curDir->filename = m_curString; break; 00609 default: warn("Warning: Unexpected tag `filename' found\n"); break; 00610 } 00611 } 00612 00613 void endPath() 00614 { 00615 switch (m_state) 00616 { 00617 case InFile: m_curFile->path = m_curString; break; 00618 case InDir: m_curDir->path = m_curString; break; 00619 default: warn("Warning: Unexpected tag `path' found\n"); break; 00620 } 00621 } 00622 00623 void endAnchor() 00624 { 00625 if (m_state==InMember) 00626 { 00627 m_curMember->anchor = m_curString; 00628 } 00629 else 00630 { 00631 warn("Warning: Unexpected tag `anchor' found\n"); 00632 } 00633 } 00634 00635 void endAnchorFile() 00636 { 00637 if (m_state==InMember) 00638 { 00639 m_curMember->anchorFile = m_curString; 00640 } 00641 else 00642 { 00643 warn("Warning: Unexpected tag `anchorfile' found\n"); 00644 } 00645 } 00646 00647 void endArglist() 00648 { 00649 if (m_state==InMember) 00650 { 00651 m_curMember->arglist = m_curString; 00652 } 00653 else 00654 { 00655 warn("Warning: Unexpected tag `arglist' found\n"); 00656 } 00657 } 00658 void endTitle() 00659 { 00660 switch (m_state) 00661 { 00662 case InGroup: m_curGroup->title = m_curString; break; 00663 case InPage: m_curPage->title = m_curString; break; 00664 default: warn("Warning: Unexpected tag `title' found\n"); break; 00665 } 00666 } 00667 00668 void endSubgroup() 00669 { 00670 if (m_state==InGroup) 00671 { 00672 m_curGroup->subgroupList.append(m_curString); 00673 } 00674 else 00675 { 00676 warn("Warning: Unexpected tag `subgroup' found\n"); 00677 } 00678 } 00679 00680 void startIgnoreElement(const QXmlAttributes& ) 00681 { 00682 } 00683 00684 void endIgnoreElement() 00685 { 00686 } 00687 00688 bool startDocument() 00689 { 00690 m_state = Invalid; 00691 00692 m_curClass=0; 00693 m_curNamespace=0; 00694 m_curFile=0; 00695 m_curGroup=0; 00696 m_curPage=0; 00697 m_curPackage=0; 00698 m_curDir=0; 00699 00700 m_stateStack.setAutoDelete(TRUE); 00701 m_tagFileClasses.setAutoDelete(TRUE); 00702 m_tagFileFiles.setAutoDelete(TRUE); 00703 m_tagFileNamespaces.setAutoDelete(TRUE); 00704 m_tagFileGroups.setAutoDelete(TRUE); 00705 m_tagFilePages.setAutoDelete(TRUE); 00706 m_tagFilePackages.setAutoDelete(TRUE); 00707 m_tagFileDirs.setAutoDelete(TRUE); 00708 00709 m_startElementHandlers.insert("compound", new StartElementHandler(this,&TagFileParser::startCompound)); 00710 m_startElementHandlers.insert("member", new StartElementHandler(this,&TagFileParser::startMember)); 00711 m_startElementHandlers.insert("name", new StartElementHandler(this,&TagFileParser::startStringValue)); 00712 m_startElementHandlers.insert("base", new StartElementHandler(this,&TagFileParser::startBase)); 00713 m_startElementHandlers.insert("filename", new StartElementHandler(this,&TagFileParser::startStringValue)); 00714 m_startElementHandlers.insert("includes", new StartElementHandler(this,&TagFileParser::startIncludes)); 00715 m_startElementHandlers.insert("path", new StartElementHandler(this,&TagFileParser::startStringValue)); 00716 m_startElementHandlers.insert("anchorfile", new StartElementHandler(this,&TagFileParser::startStringValue)); 00717 m_startElementHandlers.insert("anchor", new StartElementHandler(this,&TagFileParser::startStringValue)); 00718 m_startElementHandlers.insert("arglist", new StartElementHandler(this,&TagFileParser::startStringValue)); 00719 m_startElementHandlers.insert("title", new StartElementHandler(this,&TagFileParser::startStringValue)); 00720 m_startElementHandlers.insert("subgroup", new StartElementHandler(this,&TagFileParser::startStringValue)); 00721 m_startElementHandlers.insert("class", new StartElementHandler(this,&TagFileParser::startStringValue)); 00722 m_startElementHandlers.insert("namespace", new StartElementHandler(this,&TagFileParser::startStringValue)); 00723 m_startElementHandlers.insert("file", new StartElementHandler(this,&TagFileParser::startStringValue)); 00724 m_startElementHandlers.insert("dir", new StartElementHandler(this,&TagFileParser::startStringValue)); 00725 m_startElementHandlers.insert("page", new StartElementHandler(this,&TagFileParser::startStringValue)); 00726 m_startElementHandlers.insert("docanchor", new StartElementHandler(this,&TagFileParser::startDocAnchor)); 00727 m_startElementHandlers.insert("tagfile", new StartElementHandler(this,&TagFileParser::startIgnoreElement)); 00728 m_startElementHandlers.insert("templarg", new StartElementHandler(this,&TagFileParser::startStringValue)); 00729 m_startElementHandlers.insert("type", new StartElementHandler(this,&TagFileParser::startStringValue)); 00730 00731 m_endElementHandlers.insert("compound", new EndElementHandler(this,&TagFileParser::endCompound)); 00732 m_endElementHandlers.insert("member", new EndElementHandler(this,&TagFileParser::endMember)); 00733 m_endElementHandlers.insert("name", new EndElementHandler(this,&TagFileParser::endName)); 00734 m_endElementHandlers.insert("base", new EndElementHandler(this,&TagFileParser::endBase)); 00735 m_endElementHandlers.insert("filename", new EndElementHandler(this,&TagFileParser::endFilename)); 00736 m_endElementHandlers.insert("includes", new EndElementHandler(this,&TagFileParser::endIncludes)); 00737 m_endElementHandlers.insert("path", new EndElementHandler(this,&TagFileParser::endPath)); 00738 m_endElementHandlers.insert("anchorfile", new EndElementHandler(this,&TagFileParser::endAnchorFile)); 00739 m_endElementHandlers.insert("anchor", new EndElementHandler(this,&TagFileParser::endAnchor)); 00740 m_endElementHandlers.insert("arglist", new EndElementHandler(this,&TagFileParser::endArglist)); 00741 m_endElementHandlers.insert("title", new EndElementHandler(this,&TagFileParser::endTitle)); 00742 m_endElementHandlers.insert("subgroup", new EndElementHandler(this,&TagFileParser::endSubgroup)); 00743 m_endElementHandlers.insert("class" , new EndElementHandler(this,&TagFileParser::endClass)); 00744 m_endElementHandlers.insert("namespace", new EndElementHandler(this,&TagFileParser::endNamespace)); 00745 m_endElementHandlers.insert("file", new EndElementHandler(this,&TagFileParser::endFile)); 00746 m_endElementHandlers.insert("dir", new EndElementHandler(this,&TagFileParser::endDir)); 00747 m_endElementHandlers.insert("page", new EndElementHandler(this,&TagFileParser::endPage)); 00748 m_endElementHandlers.insert("docanchor", new EndElementHandler(this,&TagFileParser::endDocAnchor)); 00749 m_endElementHandlers.insert("tagfile", new EndElementHandler(this,&TagFileParser::endIgnoreElement)); 00750 m_endElementHandlers.insert("templarg", new EndElementHandler(this,&TagFileParser::endTemplateArg)); 00751 m_endElementHandlers.insert("type", new EndElementHandler(this,&TagFileParser::endType)); 00752 00753 return TRUE; 00754 } 00755 00756 bool startElement( const QString&, const QString&, 00757 const QString&name, const QXmlAttributes& attrib ) 00758 { 00759 //printf("startElement `%s'\n",name.data()); 00760 StartElementHandler *handler = m_startElementHandlers[name]; 00761 if (handler) 00762 { 00763 (*handler)(attrib); 00764 } 00765 else 00766 { 00767 warn("Warning: Unknown tag `%s' found!\n",name.data()); 00768 } 00769 return TRUE; 00770 } 00771 00772 bool endElement( const QString&, const QString&, const QString& name ) 00773 { 00774 //printf("endElement `%s'\n",name.data()); 00775 EndElementHandler *handler = m_endElementHandlers[name]; 00776 if (handler) 00777 { 00778 (*handler)(); 00779 } 00780 else 00781 { 00782 warn("Warning: Unknown tag `%s' found!\n",name.data()); 00783 } 00784 return TRUE; 00785 } 00786 00787 bool characters ( const QString & ch ) 00788 { 00789 m_curString+=ch; 00790 return TRUE; 00791 } 00792 00793 void dump(); 00794 void buildLists(Entry *root); 00795 void addIncludes(); 00796 00797 private: 00798 void buildMemberList(Entry *ce,QList<TagMemberInfo> &members); 00799 void addDocAnchors(Entry *e,const TagAnchorInfoList &l); 00800 QList<TagClassInfo> m_tagFileClasses; 00801 QList<TagFileInfo> m_tagFileFiles; 00802 QList<TagNamespaceInfo> m_tagFileNamespaces; 00803 QList<TagGroupInfo> m_tagFileGroups; 00804 QList<TagPageInfo> m_tagFilePages; 00805 QList<TagPackageInfo> m_tagFilePackages; 00806 QList<TagDirInfo> m_tagFileDirs; 00807 QDict<StartElementHandler> m_startElementHandlers; 00808 QDict<EndElementHandler> m_endElementHandlers; 00809 TagClassInfo *m_curClass; 00810 TagFileInfo *m_curFile; 00811 TagNamespaceInfo *m_curNamespace; 00812 TagPackageInfo *m_curPackage; 00813 TagGroupInfo *m_curGroup; 00814 TagPageInfo *m_curPage; 00815 TagDirInfo *m_curDir; 00816 TagMemberInfo *m_curMember; 00817 TagIncludeInfo *m_curIncludes; 00818 QCString m_curString; 00819 QString m_tagName; 00820 QString m_fileName; 00821 State m_state; 00822 QStack<State> m_stateStack; 00823 QXmlLocator *m_locator; 00824 QString m_inputFileName; 00825 }; 00826 00830 class TagFileErrorHandler : public QXmlErrorHandler 00831 { 00832 public: 00833 virtual ~TagFileErrorHandler() {} 00834 bool warning( const QXmlParseException & ) 00835 { 00836 return FALSE; 00837 } 00838 bool error( const QXmlParseException & ) 00839 { 00840 return FALSE; 00841 } 00842 bool fatalError( const QXmlParseException &exception ) 00843 { 00844 err("Fatal error at line %d column %d: %s\n", 00845 exception.lineNumber(),exception.columnNumber(), 00846 exception.message().data()); 00847 return FALSE; 00848 } 00849 QString errorString() { return ""; } 00850 00851 private: 00852 QString errorMsg; 00853 }; 00854 00856 void TagFileParser::dump() 00857 { 00858 msg("Result:\n"); 00859 QListIterator<TagClassInfo> lci(m_tagFileClasses); 00860 00861 //============== CLASSES 00862 TagClassInfo *cd; 00863 for (;(cd=lci.current());++lci) 00864 { 00865 msg("class `%s'\n",cd->name.data()); 00866 msg(" filename `%s'\n",cd->filename.data()); 00867 if (cd->bases) 00868 { 00869 QListIterator<BaseInfo> bii(*cd->bases); 00870 BaseInfo *bi; 00871 for ( bii.toFirst() ; (bi=bii.current()) ; ++bii) 00872 { 00873 msg( " base: %s \n", bi->name.data() ); 00874 } 00875 } 00876 00877 QListIterator<TagMemberInfo> mci(cd->members); 00878 TagMemberInfo *md; 00879 for (;(md=mci.current());++mci) 00880 { 00881 msg(" member:\n"); 00882 msg(" kind: `%s'\n",md->kind.data()); 00883 msg(" name: `%s'\n",md->name.data()); 00884 msg(" anchor: `%s'\n",md->anchor.data()); 00885 msg(" arglist: `%s'\n",md->arglist.data()); 00886 } 00887 } 00888 //============== NAMESPACES 00889 QListIterator<TagNamespaceInfo> lni(m_tagFileNamespaces); 00890 TagNamespaceInfo *nd; 00891 for (;(nd=lni.current());++lni) 00892 { 00893 msg("namespace `%s'\n",nd->name.data()); 00894 msg(" filename `%s'\n",nd->filename.data()); 00895 QStringList::Iterator it; 00896 for ( it = nd->classList.begin(); 00897 it != nd->classList.end(); ++it ) 00898 { 00899 msg( " class: %s \n", (*it).latin1() ); 00900 } 00901 00902 QListIterator<TagMemberInfo> mci(nd->members); 00903 TagMemberInfo *md; 00904 for (;(md=mci.current());++mci) 00905 { 00906 msg(" member:\n"); 00907 msg(" kind: `%s'\n",md->kind.data()); 00908 msg(" name: `%s'\n",md->name.data()); 00909 msg(" anchor: `%s'\n",md->anchor.data()); 00910 msg(" arglist: `%s'\n",md->arglist.data()); 00911 } 00912 } 00913 //============== FILES 00914 QListIterator<TagFileInfo> lfi(m_tagFileFiles); 00915 TagFileInfo *fd; 00916 for (;(fd=lfi.current());++lfi) 00917 { 00918 msg("file `%s'\n",fd->name.data()); 00919 msg(" filename `%s'\n",fd->filename.data()); 00920 QStringList::Iterator it; 00921 for ( it = fd->namespaceList.begin(); 00922 it != fd->namespaceList.end(); ++it ) 00923 { 00924 msg( " namespace: %s \n", (*it).latin1() ); 00925 } 00926 for ( it = fd->classList.begin(); 00927 it != fd->classList.end(); ++it ) 00928 { 00929 msg( " class: %s \n", (*it).latin1() ); 00930 } 00931 00932 QListIterator<TagMemberInfo> mci(fd->members); 00933 TagMemberInfo *md; 00934 for (;(md=mci.current());++mci) 00935 { 00936 msg(" member:\n"); 00937 msg(" kind: `%s'\n",md->kind.data()); 00938 msg(" name: `%s'\n",md->name.data()); 00939 msg(" anchor: `%s'\n",md->anchor.data()); 00940 msg(" arglist: `%s'\n",md->arglist.data()); 00941 } 00942 00943 QListIterator<TagIncludeInfo> mii(fd->includes); 00944 TagIncludeInfo *ii; 00945 for (;(ii=mii.current());++mii) 00946 { 00947 msg(" includes id: %s name: %s\n",ii->id.data(),ii->name.data()); 00948 } 00949 } 00950 00951 //============== GROUPS 00952 QListIterator<TagGroupInfo> lgi(m_tagFileGroups); 00953 TagGroupInfo *gd; 00954 for (;(gd=lgi.current());++lgi) 00955 { 00956 msg("group `%s'\n",gd->name.data()); 00957 msg(" filename `%s'\n",gd->filename.data()); 00958 QStringList::Iterator it; 00959 for ( it = gd->namespaceList.begin(); 00960 it != gd->namespaceList.end(); ++it ) 00961 { 00962 msg( " namespace: %s \n", (*it).latin1() ); 00963 } 00964 for ( it = gd->classList.begin(); 00965 it != gd->classList.end(); ++it ) 00966 { 00967 msg( " class: %s \n", (*it).latin1() ); 00968 } 00969 for ( it = gd->fileList.begin(); 00970 it != gd->fileList.end(); ++it ) 00971 { 00972 msg( " file: %s \n", (*it).latin1() ); 00973 } 00974 for ( it = gd->subgroupList.begin(); 00975 it != gd->subgroupList.end(); ++it ) 00976 { 00977 msg( " subgroup: %s \n", (*it).latin1() ); 00978 } 00979 for ( it = gd->pageList.begin(); 00980 it != gd->pageList.end(); ++it ) 00981 { 00982 msg( " page: %s \n", (*it).latin1() ); 00983 } 00984 00985 QListIterator<TagMemberInfo> mci(gd->members); 00986 TagMemberInfo *md; 00987 for (;(md=mci.current());++mci) 00988 { 00989 msg(" member:\n"); 00990 msg(" kind: `%s'\n",md->kind.data()); 00991 msg(" name: `%s'\n",md->name.data()); 00992 msg(" anchor: `%s'\n",md->anchor.data()); 00993 msg(" arglist: `%s'\n",md->arglist.data()); 00994 } 00995 } 00996 //============== PAGES 00997 QListIterator<TagPageInfo> lpi(m_tagFilePages); 00998 TagPageInfo *pd; 00999 for (;(pd=lpi.current());++lpi) 01000 { 01001 msg("page `%s'\n",pd->name.data()); 01002 msg(" title `%s'\n",pd->title.data()); 01003 msg(" filename `%s'\n",pd->filename.data()); 01004 } 01005 //============== DIRS 01006 QListIterator<TagDirInfo> ldi(m_tagFileDirs); 01007 TagDirInfo *dd; 01008 for (;(dd=ldi.current());++ldi) 01009 { 01010 msg("dir `%s'\n",dd->name.data()); 01011 msg(" path `%s'\n",dd->path.data()); 01012 QStringList::Iterator it; 01013 for ( it = dd->fileList.begin(); 01014 it != dd->fileList.end(); ++it ) 01015 { 01016 msg( " file: %s \n", (*it).latin1() ); 01017 } 01018 for ( it = dd->subdirList.begin(); 01019 it != dd->subdirList.end(); ++it ) 01020 { 01021 msg( " subdir: %s \n", (*it).latin1() ); 01022 } 01023 } 01024 } 01025 01026 void TagFileParser::addDocAnchors(Entry *e,const TagAnchorInfoList &l) 01027 { 01028 QListIterator<TagAnchorInfo> tli(l); 01029 TagAnchorInfo *ta; 01030 for (tli.toFirst();(ta=tli.current());++tli) 01031 { 01032 if (Doxygen::sectionDict.find(ta->label)==0) 01033 { 01034 //printf("New sectionInfo file=%s anchor=%s\n", 01035 // ta->fileName.data(),ta->label.data()); 01036 SectionInfo *si=new SectionInfo(ta->fileName,ta->label,ta->label, 01037 SectionInfo::Anchor,m_tagName); 01038 Doxygen::sectionDict.insert(ta->label,si); 01039 e->anchors->append(si); 01040 } 01041 else 01042 { 01043 warn("Duplicate anchor %s found\n",ta->label.data()); 01044 } 01045 } 01046 } 01047 01048 void TagFileParser::buildMemberList(Entry *ce,QList<TagMemberInfo> &members) 01049 { 01050 QListIterator<TagMemberInfo> mii(members); 01051 TagMemberInfo *tmi; 01052 for (;(tmi=mii.current());++mii) 01053 { 01054 Entry *me = new Entry; 01055 me->type = tmi->type; 01056 me->name = tmi->name; 01057 me->args = tmi->arglist; 01058 if (!me->args.isEmpty()) 01059 { 01060 delete me->argList; 01061 me->argList = new ArgumentList; 01062 stringToArgumentList(me->args,me->argList); 01063 } 01064 me->protection = tmi->prot; 01065 me->virt = tmi->virt; 01066 me->stat = tmi->isStatic; 01067 me->fileName = ce->fileName; 01068 if (ce->section == Entry::GROUPDOC_SEC) 01069 { 01070 me->groups->append(new Grouping(ce->name,Grouping::GROUPING_INGROUP)); 01071 } 01072 addDocAnchors(me,tmi->docAnchors); 01073 TagInfo *ti = new TagInfo; 01074 ti->tagName = m_tagName; 01075 ti->anchor = tmi->anchor; 01076 ti->fileName = tmi->anchorFile; 01077 me->tagInfo = ti; 01078 if (tmi->kind=="define") 01079 { 01080 me->type="#define"; 01081 me->section = Entry::DEFINE_SEC; 01082 } 01083 else if (tmi->kind=="enumvalue") 01084 { 01085 me->section = Entry::VARIABLE_SEC; 01086 me->mtype = Method; 01087 } 01088 else if (tmi->kind=="property") 01089 { 01090 me->section = Entry::VARIABLE_SEC; 01091 me->mtype = Property; 01092 } 01093 else if (tmi->kind=="event") 01094 { 01095 me->section = Entry::VARIABLE_SEC; 01096 me->mtype = Event; 01097 } 01098 else if (tmi->kind=="variable") 01099 { 01100 me->section = Entry::VARIABLE_SEC; 01101 me->mtype = Method; 01102 } 01103 else if (tmi->kind=="typedef") 01104 { 01105 me->section = Entry::VARIABLE_SEC; //Entry::TYPEDEF_SEC; 01106 me->type.prepend("typedef "); 01107 me->mtype = Method; 01108 } 01109 else if (tmi->kind=="enumeration") 01110 { 01111 me->section = Entry::ENUM_SEC; 01112 me->mtype = Method; 01113 } 01114 else if (tmi->kind=="function") 01115 { 01116 me->section = Entry::FUNCTION_SEC; 01117 me->mtype = Method; 01118 } 01119 else if (tmi->kind=="signal") 01120 { 01121 me->section = Entry::FUNCTION_SEC; 01122 me->mtype = Signal; 01123 } 01124 else if (tmi->kind=="prototype") 01125 { 01126 me->section = Entry::FUNCTION_SEC; 01127 me->mtype = Method; 01128 } 01129 else if (tmi->kind=="friend") 01130 { 01131 me->section = Entry::FUNCTION_SEC; 01132 me->type.prepend("friend "); 01133 me->mtype = Method; 01134 } 01135 else if (tmi->kind=="dcop") 01136 { 01137 me->section = Entry::FUNCTION_SEC; 01138 me->mtype = DCOP; 01139 } 01140 else if (tmi->kind=="slot") 01141 { 01142 me->section = Entry::FUNCTION_SEC; 01143 me->mtype = Slot; 01144 } 01145 ce->addSubEntry(me); 01146 } 01147 } 01148 01149 static QString stripPath(const QString &s) 01150 { 01151 int i=s.findRev('/'); 01152 if (i!=-1) 01153 { 01154 return s.right(s.length()-i-1); 01155 } 01156 else 01157 { 01158 return s; 01159 } 01160 } 01161 01166 void TagFileParser::buildLists(Entry *root) 01167 { 01168 // build class list 01169 TagClassInfo *tci = m_tagFileClasses.first(); 01170 while (tci) 01171 { 01172 Entry *ce = new Entry; 01173 ce->section = Entry::CLASS_SEC; 01174 switch (tci->kind) 01175 { 01176 case TagClassInfo::Class: break; 01177 case TagClassInfo::Struct: ce->spec = Entry::Struct; break; 01178 case TagClassInfo::Union: ce->spec = Entry::Union; break; 01179 case TagClassInfo::Interface: ce->spec = Entry::Interface; break; 01180 case TagClassInfo::Exception: ce->spec = Entry::Exception; break; 01181 case TagClassInfo::Protocol: ce->spec = Entry::Protocol; break; 01182 case TagClassInfo::Category: ce->spec = Entry::Category; break; 01183 } 01184 ce->name = tci->name; 01185 addDocAnchors(ce,tci->docAnchors); 01186 TagInfo *ti = new TagInfo; 01187 ti->tagName = m_tagName; 01188 ti->fileName = tci->filename; 01189 ce->tagInfo = ti; 01190 ce->objc = tci->isObjC; 01191 // transfer base class list 01192 if (tci->bases) 01193 { 01194 delete ce->extends; 01195 ce->extends = tci->bases; tci->bases = 0; 01196 } 01197 if (tci->templateArguments) 01198 { 01199 if (ce->tArgLists==0) 01200 { 01201 ce->tArgLists = new QList<ArgumentList>; 01202 ce->tArgLists->setAutoDelete(TRUE); 01203 } 01204 ArgumentList *al = new ArgumentList; 01205 ce->tArgLists->append(al); 01206 01207 QListIterator<QString> sli(*tci->templateArguments); 01208 QString *argName; 01209 for (;(argName=sli.current());++sli) 01210 { 01211 Argument *a = new Argument; 01212 a->type = "class"; 01213 a->name = *argName; 01214 al->append(a); 01215 } 01216 } 01217 01218 buildMemberList(ce,tci->members); 01219 root->addSubEntry(ce); 01220 tci = m_tagFileClasses.next(); 01221 } 01222 01223 // build file list 01224 TagFileInfo *tfi = m_tagFileFiles.first(); 01225 while (tfi) 01226 { 01227 Entry *fe = new Entry; 01228 fe->section = guessSection(tfi->name); 01229 fe->name = tfi->name; 01230 addDocAnchors(fe,tfi->docAnchors); 01231 TagInfo *ti = new TagInfo; 01232 ti->tagName = m_tagName; 01233 ti->fileName = tfi->filename; 01234 fe->tagInfo = ti; 01235 01236 QString fullName = m_tagName+":"+tfi->path+stripPath(tfi->name); 01237 fe->fileName = fullName; 01238 //printf("new FileDef() filename=%s\n",tfi->filename.data()); 01239 FileDef *fd = new FileDef(m_tagName+":"+tfi->path, 01240 tfi->name,m_tagName, 01241 tfi->filename 01242 ); 01243 FileName *mn; 01244 if ((mn=Doxygen::inputNameDict->find(tfi->name))) 01245 { 01246 mn->append(fd); 01247 } 01248 else 01249 { 01250 mn = new FileName(fullName,tfi->name); 01251 mn->append(fd); 01252 Doxygen::inputNameList->inSort(mn); 01253 Doxygen::inputNameDict->insert(tfi->name,mn); 01254 } 01255 buildMemberList(fe,tfi->members); 01256 root->addSubEntry(fe); 01257 tfi = m_tagFileFiles.next(); 01258 } 01259 01260 // build namespace list 01261 TagNamespaceInfo *tni = m_tagFileNamespaces.first(); 01262 while (tni) 01263 { 01264 Entry *ne = new Entry; 01265 ne->section = Entry::NAMESPACE_SEC; 01266 ne->name = tni->name; 01267 addDocAnchors(ne,tni->docAnchors); 01268 TagInfo *ti = new TagInfo; 01269 ti->tagName = m_tagName; 01270 ti->fileName = tni->filename; 01271 ne->tagInfo = ti; 01272 01273 buildMemberList(ne,tni->members); 01274 root->addSubEntry(ne); 01275 tni = m_tagFileNamespaces.next(); 01276 } 01277 01278 // build package list 01279 TagPackageInfo *tpgi = m_tagFilePackages.first(); 01280 while (tpgi) 01281 { 01282 Entry *pe = new Entry; 01283 pe->section = Entry::PACKAGE_SEC; 01284 pe->name = tpgi->name; 01285 addDocAnchors(pe,tpgi->docAnchors); 01286 TagInfo *ti = new TagInfo; 01287 ti->tagName = m_tagName; 01288 ti->fileName = tpgi->filename; 01289 pe->tagInfo = ti; 01290 01291 buildMemberList(pe,tpgi->members); 01292 root->addSubEntry(pe); 01293 tpgi = m_tagFilePackages.next(); 01294 } 01295 01296 // build group list, but only if config file says to include it 01297 //if (Config_getBool("EXTERNAL_GROUPS")) 01298 //{ 01299 TagGroupInfo *tgi = m_tagFileGroups.first(); 01300 while (tgi) 01301 { 01302 Entry *ge = new Entry; 01303 ge->section = Entry::GROUPDOC_SEC; 01304 ge->name = tgi->name; 01305 ge->type = tgi->title; 01306 addDocAnchors(ge,tgi->docAnchors); 01307 TagInfo *ti = new TagInfo; 01308 ti->tagName = m_tagName; 01309 ti->fileName = tgi->filename; 01310 ge->tagInfo = ti; 01311 01312 buildMemberList(ge,tgi->members); 01313 root->addSubEntry(ge); 01314 tgi = m_tagFileGroups.next(); 01315 } 01316 //} 01317 01318 // build page list 01319 TagPageInfo *tpi = m_tagFilePages.first(); 01320 while (tpi) 01321 { 01322 Entry *pe = new Entry; 01323 pe->section = Entry::PAGEDOC_SEC; 01324 pe->name = tpi->name; 01325 pe->args = tpi->title; 01326 addDocAnchors(pe,tpi->docAnchors); 01327 TagInfo *ti = new TagInfo; 01328 ti->tagName = m_tagName; 01329 ti->fileName = tpi->filename; 01330 pe->tagInfo = ti; 01331 01332 root->addSubEntry(pe); 01333 tpi = m_tagFilePages.next(); 01334 } 01335 } 01336 01337 void TagFileParser::addIncludes() 01338 { 01339 TagFileInfo *tfi = m_tagFileFiles.first(); 01340 while (tfi) 01341 { 01342 //printf("tag file tagName=%s path=%s name=%s\n",m_tagName.data(),tfi->path.data(),tfi->name.data()); 01343 FileName *fn = Doxygen::inputNameDict->find(tfi->name); 01344 if (fn) 01345 { 01346 //printf("found\n"); 01347 FileNameIterator fni(*fn); 01348 FileDef *fd; 01349 for (;(fd=fni.current());++fni) 01350 { 01351 //printf("input file path=%s name=%s\n",fd->getPath().data(),fd->name().data()); 01352 if (fd->getPath()==QCString(m_tagName+":"+tfi->path)) 01353 { 01354 //printf("found\n"); 01355 QListIterator<TagIncludeInfo> mii(tfi->includes); 01356 TagIncludeInfo *ii; 01357 for (;(ii=mii.current());++mii) 01358 { 01359 //printf("ii->name=`%s'\n",ii->name.data()); 01360 FileName *ifn = Doxygen::inputNameDict->find(ii->name); 01361 ASSERT(ifn!=0); 01362 if (ifn) 01363 { 01364 FileNameIterator ifni(*ifn); 01365 FileDef *ifd; 01366 for (;(ifd=ifni.current());++ifni) 01367 { 01368 //printf("ifd->getOutputFileBase()=%s ii->id=%s\n", 01369 // ifd->getOutputFileBase().data(),ii->id.data()); 01370 if (ifd->getOutputFileBase()==QCString(ii->id)) 01371 { 01372 fd->addIncludeDependency(ifd,ii->text,ii->isLocal,ii->isImported); 01373 } 01374 } 01375 } 01376 } 01377 } 01378 } 01379 } 01380 tfi = m_tagFileFiles.next(); 01381 } 01382 } 01383 01384 void parseTagFile(Entry *root,const char *fullName,const char *tagName) 01385 { 01386 QFileInfo fi(fullName); 01387 if (!fi.exists()) return; 01388 TagFileParser handler( tagName ); 01389 handler.setFileName(fullName); 01390 TagFileErrorHandler errorHandler; 01391 QFile xmlFile( fullName ); 01392 QXmlInputSource source( xmlFile ); 01393 QXmlSimpleReader reader; 01394 reader.setContentHandler( &handler ); 01395 reader.setErrorHandler( &errorHandler ); 01396 reader.parse( source ); 01397 handler.buildLists(root); 01398 handler.addIncludes(); 01399 //handler.dump(); 01400 } 01401 01402