00001 /****************************************************************************** 00002 * 00003 * $Id: filedef.cpp,v 1.55 2001/03/19 19:27:40 root Exp $ 00004 * 00005 * Copyright (C) 1997-2008 by Dimitri van Heesch. 00006 * 00007 * Permission to use, copy, modify, and distribute this software and its 00008 * documentation under the terms of the GNU General Public License is hereby 00009 * granted. No representations are made about the suitability of this software 00010 * for any purpose. It is provided "as is" without express or implied warranty. 00011 * See the GNU General Public License for more details. 00012 * 00013 * Documents produced by Doxygen are derivative works derived from the 00014 * input used in their production; they are not affected by this license. 00015 * 00016 */ 00017 00018 #include "qtbc.h" 00019 #include "memberlist.h" 00020 #include "classlist.h" 00021 #include "filedef.h" 00022 #include "doxygen.h" 00023 #include "memberdef.h" 00024 #include "classdef.h" 00025 #include "namespacedef.h" 00026 #include "util.h" 00027 #include "language.h" 00028 #include "outputlist.h" 00029 #include "dot.h" 00030 #include "message.h" 00031 #include "docparser.h" 00032 #include "searchindex.h" 00033 #include "htags.h" 00034 #include "parserintf.h" 00035 #include "portable.h" 00036 #include "vhdldocgen.h" 00037 #include "debug.h" 00038 00039 class DevNullCodeDocInterface : public CodeOutputInterface 00040 { 00041 public: 00042 virtual void codify(const char *) {} 00043 virtual void writeCodeLink(const char *,const char *, 00044 const char *,const char *, 00045 const char *) {} 00046 virtual void writeLineNumber(const char *,const char *, 00047 const char *,int) {} 00048 virtual void startCodeLine() {} 00049 virtual void endCodeLine() {} 00050 virtual void startCodeAnchor(const char *) {} 00051 virtual void endCodeAnchor() {} 00052 virtual void startFontClass(const char *) {} 00053 virtual void endFontClass() {} 00054 virtual void writeCodeAnchor(const char *) {} 00055 virtual void linkableSymbol(int, const char *,Definition *,Definition *) {} 00056 }; 00057 00062 FileDef::FileDef(const char *p,const char *nm, 00063 const char *lref,const char *dn) 00064 : Definition((QCString)p+nm,1,nm) 00065 { 00066 path=p; 00067 filepath=path+nm; 00068 filename=nm; 00069 diskname=dn; 00070 if (diskname.isEmpty()) diskname=nm; 00071 setReference(lref); 00072 classSDict = 0; 00073 includeList = 0; 00074 includeDict = 0; 00075 includedByList = 0; 00076 includedByDict = 0; 00077 namespaceSDict = 0; 00078 srcDefDict = 0; 00079 srcMemberDict = 0; 00080 usingDirList = 0; 00081 usingDeclList = 0; 00082 package = 0; 00083 isSource = FALSE; 00084 docname = nm; 00085 dir = 0; 00086 if (Config_getBool("FULL_PATH_NAMES")) 00087 { 00088 docname.prepend(stripFromPath(path.copy())); 00089 } 00090 m_isJava = name().right(5)==".java"; 00091 memberGroupSDict = 0; 00092 acquireFileVersion(); 00093 m_subGrouping=Config_getBool("SUBGROUPING"); 00094 } 00095 00097 FileDef::~FileDef() 00098 { 00099 delete classSDict; 00100 delete includeDict; 00101 delete includeList; 00102 delete includedByDict; 00103 delete includedByList; 00104 delete namespaceSDict; 00105 delete srcDefDict; 00106 delete srcMemberDict; 00107 delete usingDirList; 00108 delete usingDeclList; 00109 delete memberGroupSDict; 00110 } 00111 00113 void FileDef::computeAnchors() 00114 { 00115 MemberList *ml = getMemberList(MemberList::allMembersList); 00116 if (ml) setAnchors(0,'a',ml); 00117 } 00118 00119 void FileDef::distributeMemberGroupDocumentation() 00120 { 00121 //printf("FileDef::distributeMemberGroupDocumentation()\n"); 00122 if (memberGroupSDict) 00123 { 00124 MemberGroupSDict::Iterator mgli(*memberGroupSDict); 00125 MemberGroup *mg; 00126 for (;(mg=mgli.current());++mgli) 00127 { 00128 mg->distributeMemberGroupDocumentation(); 00129 } 00130 } 00131 } 00132 00133 void FileDef::findSectionsInDocumentation() 00134 { 00135 docFindSections(documentation(),this,0,docFile()); 00136 if (memberGroupSDict) 00137 { 00138 MemberGroupSDict::Iterator mgli(*memberGroupSDict); 00139 MemberGroup *mg; 00140 for (;(mg=mgli.current());++mgli) 00141 { 00142 mg->findSectionsInDocumentation(); 00143 } 00144 } 00145 00146 QListIterator<MemberList> mli(m_memberLists); 00147 MemberList *ml; 00148 for (mli.toFirst();(ml=mli.current());++mli) 00149 { 00150 if (ml->listType()&MemberList::declarationLists) 00151 { 00152 ml->findSectionsInDocumentation(); 00153 } 00154 } 00155 } 00156 00157 void FileDef::writeDetailedDocumentation(OutputList &ol) 00158 { 00159 if ((!briefDescription().isEmpty() && Config_getBool("REPEAT_BRIEF")) || 00160 !documentation().isEmpty() 00161 ) 00162 { 00163 ol.writeRuler(); 00164 ol.pushGeneratorState(); 00165 ol.disable(OutputGenerator::Latex); 00166 ol.disable(OutputGenerator::RTF); 00167 ol.writeAnchor(0,"_details"); 00168 ol.popGeneratorState(); 00169 ol.startGroupHeader(); 00170 ol.parseText(theTranslator->trDetailedDescription()); 00171 ol.endGroupHeader(); 00172 ol.startTextBlock(); 00173 if (!briefDescription().isEmpty() && Config_getBool("REPEAT_BRIEF")) 00174 { 00175 ol.parseDoc(briefFile(),briefLine(),this,0,briefDescription(),FALSE,FALSE); 00176 } 00177 if (!briefDescription().isEmpty() && Config_getBool("REPEAT_BRIEF") && 00178 !documentation().isEmpty()) 00179 { 00180 ol.pushGeneratorState(); 00181 ol.disable(OutputGenerator::Man); 00182 ol.newParagraph(); 00183 ol.enableAll(); 00184 ol.disableAllBut(OutputGenerator::Man); 00185 ol.writeString("\n\n"); 00186 ol.popGeneratorState(); 00187 } 00188 if (!documentation().isEmpty()) 00189 { 00190 //if (doc.at(dl-1)!='.' && doc.at(dl-1)!='!' && doc.at(dl-1)!='?') 00191 // doc+='.'; 00192 ol.parseDoc(docFile(),docLine(),this,0,documentation()+"\n",TRUE,FALSE); 00193 } 00194 //printf("Writing source ref for file %s\n",name().data()); 00195 if (Config_getBool("SOURCE_BROWSER")) 00196 { 00197 ol.startParagraph(); 00198 QCString refText = theTranslator->trDefinedInSourceFile(); 00199 int fileMarkerPos = refText.find("@0"); 00200 if (fileMarkerPos!=-1) // should always pass this. 00201 { 00202 ol.parseText(refText.left(fileMarkerPos)); //text left from marker 1 00203 ol.writeObjectLink(0,getSourceFileBase(), 00204 0,name()); 00205 ol.parseText(refText.right( 00206 refText.length()-fileMarkerPos-2)); // text right from marker 2 00207 } 00208 ol.endParagraph(); 00209 } 00210 ol.endTextBlock(); 00211 } 00212 } 00213 00217 void FileDef::writeDocumentation(OutputList &ol) 00218 { 00219 bool fortranOpt = Config_getBool("OPTIMIZE_FOR_FORTRAN"); 00220 bool vhdlOpt = Config_getBool("OPTIMIZE_OUTPUT_VHDL"); 00221 //funcList->countDecMembers(); 00222 00223 //QCString fn = name(); 00224 //if (Config_getBool("FULL_PATH_NAMES")) 00225 //{ 00226 // fn.prepend(stripFromPath(getPath().copy())); 00227 //} 00228 00229 //printf("WriteDocumentation diskname=%s\n",diskname.data()); 00230 00231 QCString versionTitle; 00232 if (!fileVersion.isEmpty()) 00233 { 00234 versionTitle=("("+fileVersion+")"); 00235 } 00236 QCString title = docname+versionTitle; 00237 QCString pageTitle=theTranslator->trFileReference(docname); 00238 00239 if (Config_getBool("SHOW_DIRECTORIES") && getDirDef()) 00240 { 00241 startFile(ol,getOutputFileBase(),name(),pageTitle,HLI_FileVisible,TRUE); 00242 getDirDef()->writeNavigationPath(ol); 00243 ol.endQuickIndices(); 00244 ol.startContents(); 00245 QCString pageTitleShort=theTranslator->trFileReference(name()); 00246 startTitle(ol,getOutputFileBase()); 00247 ol.pushGeneratorState(); 00248 ol.disableAllBut(OutputGenerator::Html); 00249 ol.parseText(pageTitleShort); // Html only 00250 ol.enableAll(); 00251 ol.disable(OutputGenerator::Html); 00252 ol.parseText(pageTitle); // other output formats 00253 ol.popGeneratorState(); 00254 addGroupListToTitle(ol,this); 00255 endTitle(ol,getOutputFileBase(),title); 00256 } 00257 else 00258 { 00259 startFile(ol,getOutputFileBase(),name(),pageTitle,HLI_FileVisible); 00260 startTitle(ol,getOutputFileBase()); 00261 ol.parseText(pageTitle); 00262 addGroupListToTitle(ol,this); 00263 endTitle(ol,getOutputFileBase(),title); 00264 } 00265 if (!fileVersion.isEmpty()) 00266 { 00267 ol.disableAllBut(OutputGenerator::Html); 00268 ol.startProjectNumber(); 00269 ol.docify(versionTitle); 00270 ol.endProjectNumber(); 00271 ol.enableAll(); 00272 } 00273 00274 if (Config_getBool("SEARCHENGINE")) 00275 { 00276 Doxygen::searchIndex->setCurrentDoc(pageTitle,getOutputFileBase()); 00277 Doxygen::searchIndex->addWord(localName(),TRUE); 00278 } 00279 00280 if (!Config_getString("GENERATE_TAGFILE").isEmpty()) 00281 { 00282 Doxygen::tagFile << " <compound kind=\"file\">" << endl; 00283 Doxygen::tagFile << " <name>" << convertToXML(name()) << "</name>" << endl; 00284 Doxygen::tagFile << " <path>" << convertToXML(getPath()) << "</path>" << endl; 00285 Doxygen::tagFile << " <filename>" 00286 << convertToXML(getOutputFileBase()) 00287 << "</filename>" << endl; 00288 } 00289 00290 if (Config_getBool("DETAILS_AT_TOP")) 00291 { 00292 ol.startTextBlock(); 00293 writeDetailedDocumentation(ol); 00294 ol.endTextBlock(); 00295 00296 ol.pushGeneratorState(); 00297 ol.disable(OutputGenerator::Man); 00298 ol.disable(OutputGenerator::RTF); 00299 ol.newParagraph(); 00300 ol.popGeneratorState(); 00301 } 00302 else if (!briefDescription().isEmpty()) 00303 { 00304 ol.parseDoc(briefFile(),briefLine(),this,0,briefDescription(),TRUE,FALSE); 00305 //ol.writeString(" \n"); 00306 ol.disableAllBut(OutputGenerator::Html); 00307 ol.startTextLink(0,"_details"); 00308 ol.parseText(theTranslator->trMore()); 00309 ol.endTextLink(); 00310 ol.enableAll(); 00311 00312 ol.pushGeneratorState(); 00313 ol.disable(OutputGenerator::Man); 00314 ol.disable(OutputGenerator::RTF); 00315 ol.newParagraph(); 00316 ol.popGeneratorState(); 00317 } 00318 ol.writeSynopsis(); 00319 00320 if (Config_getBool("SHOW_INCLUDE_FILES") && includeList && 00321 includeList->count()>0) 00322 { 00323 ol.startTextBlock(TRUE); 00324 QListIterator<IncludeInfo> ili(*includeList); 00325 IncludeInfo *ii; 00326 for (;(ii=ili.current());++ili) 00327 { 00328 FileDef *fd=ii->fileDef; 00329 bool isIDLorJava = FALSE; 00330 if (fd) 00331 { 00332 isIDLorJava = fd->name().right(4)==".idl" || // M$ or Corba IDL 00333 fd->name().right(5)==".pidl" || 00334 fd->name().right(5)==".java" || // Sun's Java 00335 fd->name().right(4)==".jsl"; // M$ J# 00336 } 00337 ol.startTypewriter(); 00338 if (isIDLorJava) // IDL/Java include 00339 { 00340 ol.docify("import "); 00341 } 00342 else if (ii->imported) // Objective-C include 00343 { 00344 ol.docify("#import "); 00345 } 00346 else // C/C++ include 00347 { 00348 ol.docify("#include "); 00349 } 00350 if (ii->local || isIDLorJava) 00351 ol.docify("\""); 00352 else 00353 ol.docify("<"); 00354 ol.disable(OutputGenerator::Html); 00355 ol.docify(ii->includeName); 00356 ol.enableAll(); 00357 ol.disableAllBut(OutputGenerator::Html); 00358 00359 // Here we use the include file name as it appears in the file. 00360 // we could also we the name as it is used within doxygen, 00361 // then we should have used fd->docName() instead of ii->includeName 00362 if (fd && fd->isLinkable()) 00363 { 00364 ol.writeObjectLink(fd->getReference(), 00365 fd->generateSourceFile() ? fd->includeName() : fd->getOutputFileBase(), 00366 0,ii->includeName); 00367 if (!Config_getString("GENERATE_TAGFILE").isEmpty() && !fd->isReference()) 00368 { 00369 const char *locStr = (ii->local || isIDLorJava) ? "yes" : "no"; 00370 const char *impStr = (ii->imported || isIDLorJava) ? "yes" : "no"; 00371 Doxygen::tagFile << " <includes id=\"" 00372 << convertToXML(fd->getOutputFileBase()) << "\" " 00373 << "name=\"" << convertToXML(fd->name()) << "\" " 00374 << "local=\"" << locStr << "\" " 00375 << "imported=\"" << impStr << "\">" 00376 << convertToXML(ii->includeName) 00377 << "</includes>" 00378 << endl; 00379 } 00380 } 00381 else 00382 { 00383 ol.docify(ii->includeName); 00384 } 00385 00386 ol.enableAll(); 00387 if (ii->local || isIDLorJava) 00388 ol.docify("\""); 00389 else 00390 ol.docify(">"); 00391 if (isIDLorJava) 00392 ol.docify(";"); 00393 ol.endTypewriter(); 00394 ol.lineBreak(); 00395 } 00396 ol.endTextBlock(); 00397 } 00398 00399 if (Config_getBool("HAVE_DOT") && Config_getBool("INCLUDE_GRAPH")) 00400 { 00401 //printf("Graph for file %s\n",name().data()); 00402 DotInclDepGraph incDepGraph(this,FALSE); 00403 if (!incDepGraph.isTrivial() && !incDepGraph.isTooBig()) 00404 { 00405 ol.startTextBlock(); 00406 ol.disable(OutputGenerator::Man); 00407 ol.newParagraph(); 00408 ol.startInclDepGraph(); 00409 ol.parseText(theTranslator->trInclDepGraph(name())); 00410 ol.endInclDepGraph(incDepGraph); 00411 ol.enableAll(); 00412 ol.endTextBlock(TRUE); 00413 } 00414 //incDepGraph.writeGraph(Config_getString("HTML_OUTPUT"),fd->getOutputFileBase()); 00415 } 00416 00417 if (Config_getBool("HAVE_DOT") && Config_getBool("INCLUDED_BY_GRAPH")) 00418 { 00419 //printf("Graph for file %s\n",name().data()); 00420 DotInclDepGraph incDepGraph(this,TRUE); 00421 if (!incDepGraph.isTrivial() && !incDepGraph.isTooBig()) 00422 { 00423 ol.startTextBlock(); 00424 ol.disable(OutputGenerator::Man); 00425 ol.newParagraph(); 00426 ol.startInclDepGraph(); 00427 ol.parseText(theTranslator->trInclByDepGraph()); 00428 ol.endInclDepGraph(incDepGraph); 00429 ol.enableAll(); 00430 ol.endTextBlock(TRUE); 00431 } 00432 //incDepGraph.writeGraph(Config_getString("HTML_OUTPUT"),fd->getOutputFileBase()); 00433 } 00434 00435 //printf("%s: generateSourceFile()=%d\n",name().data(),generateSourceFile()); 00436 if (generateSourceFile()) 00437 { 00438 ol.disableAllBut(OutputGenerator::Html); 00439 ol.newParagraph(); 00440 ol.startTextLink(includeName(),0); 00441 ol.parseText(theTranslator->trGotoSourceCode()); 00442 ol.endTextLink(); 00443 ol.enableAll(); 00444 } 00445 00446 ol.startMemberSections(); 00447 00448 if (namespaceSDict && namespaceSDict->count()>0) 00449 { 00450 NamespaceSDict::Iterator ndi(*namespaceSDict); 00451 NamespaceDef *nd; 00452 bool found=FALSE; 00453 for (ndi.toFirst();(nd=ndi.current());++ndi) 00454 { 00455 if (nd->name().find('@')==-1 && !nd->isArtificial()) 00456 { 00457 if (!found) 00458 { 00459 ol.startMemberHeader(); 00460 if (fortranOpt) 00461 { 00462 ol.parseText(theTranslator->trModules()); 00463 } 00464 else 00465 { 00466 ol.parseText(theTranslator->trNamespaces()); 00467 } 00468 ol.endMemberHeader(); 00469 ol.startMemberList(); 00470 found=TRUE; 00471 } 00472 ol.startMemberItem(0); 00473 if (fortranOpt) 00474 { 00475 ol.writeString("module "); 00476 } 00477 else 00478 { 00479 ol.writeString("namespace "); 00480 } 00481 ol.insertMemberAlign(); 00482 if (nd->isLinkable()) 00483 { 00484 ol.writeObjectLink(nd->getReference(), 00485 nd->getOutputFileBase(), 00486 0, 00487 nd->displayName() 00488 ); 00489 if (!Config_getString("GENERATE_TAGFILE").isEmpty()) 00490 { 00491 Doxygen::tagFile << " <namespace>" << convertToXML(nd->name()) << "</namespace>" << endl; 00492 } 00493 } 00494 else 00495 { 00496 ol.startBold(); 00497 ol.docify(nd->displayName()); 00498 ol.endBold(); 00499 } 00500 ol.endMemberItem(); 00501 } 00502 } 00503 if (found) ol.endMemberList(); 00504 } 00505 00506 if (classSDict) classSDict->writeDeclaration(ol); 00507 00508 /* write user defined member groups */ 00509 if (memberGroupSDict) 00510 { 00511 MemberGroupSDict::Iterator mgli(*memberGroupSDict); 00512 MemberGroup *mg; 00513 for (;(mg=mgli.current());++mgli) 00514 { 00515 if ((!mg->allMembersInSameSection() || !m_subGrouping) 00516 && mg->header()!="[NOHEADER]") 00517 { 00518 mg->writeDeclarations(ol,0,0,this,0); 00519 } 00520 } 00521 } 00522 00523 //allMemberList.writeDeclarations(ol,0,0,this,0,0,0); 00524 writeMemberDeclarations(ol,MemberList::decDefineMembers,theTranslator->trDefines()); 00525 writeMemberDeclarations(ol,MemberList::decProtoMembers,theTranslator->trFuncProtos()); 00526 writeMemberDeclarations(ol,MemberList::decTypedefMembers,theTranslator->trTypedefs()); 00527 writeMemberDeclarations(ol,MemberList::decEnumMembers,theTranslator->trEnumerations()); 00528 writeMemberDeclarations(ol,MemberList::decFuncMembers, 00529 fortranOpt ? theTranslator->trSubprograms() : 00530 vhdlOpt ? VhdlDocGen::trFunctionAndProc() : 00531 theTranslator->trFunctions()) ; 00532 writeMemberDeclarations(ol,MemberList::decVarMembers,theTranslator->trVariables()); 00533 ol.endMemberSections(); 00534 00535 if (!Config_getBool("DETAILS_AT_TOP")) 00536 { 00537 writeDetailedDocumentation(ol); 00538 } 00539 00540 writeMemberDocumentation(ol); 00541 00542 // write Author section (Man only) 00543 ol.disableAllBut(OutputGenerator::Man); 00544 ol.startGroupHeader(); 00545 ol.parseText(theTranslator->trAuthor(TRUE,TRUE)); 00546 ol.endGroupHeader(); 00547 ol.parseText(theTranslator->trGeneratedAutomatically(Config_getString("PROJECT_NAME"))); 00548 ol.enableAll(); 00549 00550 if (!Config_getString("GENERATE_TAGFILE").isEmpty()) 00551 { 00552 writeDocAnchorsToTagFile(); 00553 Doxygen::tagFile << " </compound>" << endl; 00554 } 00555 00556 endFile(ol); 00557 00558 if (Config_getBool("SEPARATE_MEMBER_PAGES")) 00559 { 00560 MemberList *ml = getMemberList(MemberList::allMembersList); 00561 if (ml) ml->sort(); 00562 writeMemberPages(ol); 00563 } 00564 } 00565 00566 void FileDef::writeMemberDocumentation(OutputList &ol) 00567 { 00568 bool fortranOpt = Config_getBool("OPTIMIZE_FOR_FORTRAN"); 00569 if (Config_getBool("SEPARATE_MEMBER_PAGES")) 00570 { 00571 ol.disable(OutputGenerator::Html); 00572 } 00573 00574 writeMemberDocumentation(ol,MemberList::docDefineMembers,theTranslator->trDefineDocumentation()); 00575 writeMemberDocumentation(ol,MemberList::docProtoMembers,fortranOpt?theTranslator->trSubprogramDocumentation():theTranslator->trFunctionPrototypeDocumentation()); 00576 writeMemberDocumentation(ol,MemberList::docTypedefMembers,theTranslator->trTypedefDocumentation()); 00577 writeMemberDocumentation(ol,MemberList::docEnumMembers,theTranslator->trEnumerationTypeDocumentation()); 00578 writeMemberDocumentation(ol,MemberList::docFuncMembers,theTranslator->trFunctionDocumentation()); 00579 writeMemberDocumentation(ol,MemberList::docVarMembers,theTranslator->trVariableDocumentation()); 00580 00581 if (Config_getBool("SEPARATE_MEMBER_PAGES")) 00582 { 00583 ol.enable(OutputGenerator::Html); 00584 } 00585 } 00586 00587 void FileDef::writeMemberPages(OutputList &ol) 00588 { 00589 ol.pushGeneratorState(); 00590 ol.disableAllBut(OutputGenerator::Html); 00591 00592 QListIterator<MemberList> mli(m_memberLists); 00593 MemberList *ml; 00594 for (mli.toFirst();(ml=mli.current());++mli) 00595 { 00596 if (ml->listType()&MemberList::documentationLists) 00597 { 00598 ml->writeDocumentationPage(ol,name(),this); 00599 } 00600 } 00601 00602 ol.popGeneratorState(); 00603 } 00604 00605 void FileDef::writeQuickMemberLinks(OutputList &ol,MemberDef *currentMd) const 00606 { 00607 static bool createSubDirs=Config_getBool("CREATE_SUBDIRS"); 00608 00609 ol.writeString(" <div class=\"navtab\">\n"); 00610 ol.writeString(" <table>\n"); 00611 00612 MemberList *allMemberList = getMemberList(MemberList::allMembersList); 00613 if (allMemberList) 00614 { 00615 MemberListIterator mli(*allMemberList); 00616 MemberDef *md; 00617 for (mli.toFirst();(md=mli.current());++mli) 00618 { 00619 if (md->getFileDef()==this && md->getNamespaceDef()==0 && md->isLinkable()) 00620 { 00621 ol.writeString(" <tr><td class=\"navtab\">"); 00622 if (md->isLinkableInProject()) 00623 { 00624 if (md==currentMd) // selected item => highlight 00625 { 00626 ol.writeString("<a class=\"qindexHL\" "); 00627 } 00628 else 00629 { 00630 ol.writeString("<a class=\"qindex\" "); 00631 } 00632 ol.writeString("href=\""); 00633 if (createSubDirs) ol.writeString("../../"); 00634 ol.writeString(md->getOutputFileBase()+Doxygen::htmlFileExtension+"#"+md->anchor()); 00635 ol.writeString("\">"); 00636 ol.writeString(md->localName()); 00637 ol.writeString("</a>"); 00638 } 00639 ol.writeString("</td></tr>\n"); 00640 } 00641 } 00642 } 00643 00644 ol.writeString(" </table>\n"); 00645 ol.writeString(" </div>\n"); 00646 } 00647 00649 void FileDef::writeSource(OutputList &ol) 00650 { 00651 static bool filterSourceFiles = Config_getBool("FILTER_SOURCE_FILES"); 00652 QCString title = docname; 00653 if (!fileVersion.isEmpty()) 00654 { 00655 title+=(" ("+fileVersion+")"); 00656 } 00657 QCString pageTitle = theTranslator->trSourceFile(title); 00658 ol.disableAllBut(OutputGenerator::Html); 00659 00660 if (Config_getBool("SHOW_DIRECTORIES") && getDirDef()) 00661 { 00662 startFile(ol,getSourceFileBase(),0,pageTitle,HLI_FileVisible,TRUE); 00663 getDirDef()->writeNavigationPath(ol); 00664 ol.endQuickIndices(); 00665 ol.endContents(); 00666 startTitle(ol,getOutputFileBase()); 00667 ol.parseText(name()); 00668 endTitle(ol,getOutputFileBase(),title); 00669 } 00670 else 00671 { 00672 startFile(ol,getSourceFileBase(),0,pageTitle,HLI_FileVisible,TRUE); 00673 startTitle(ol,0); 00674 ol.parseText(title); 00675 endTitle(ol,0,0); 00676 } 00677 00678 if (isLinkable()) 00679 { 00680 ol.startTextLink(getOutputFileBase(),0); 00681 ol.parseText(theTranslator->trGotoDocumentation()); 00682 ol.endTextLink(); 00683 } 00684 00685 ParserInterface *pIntf = Doxygen::parserManager->getParser(getDefFileExtension()); 00686 pIntf->resetCodeParserState(); 00687 ol.startCodeFragment(); 00688 pIntf->parseCode(ol,0, 00689 fileToString(absFilePath(),filterSourceFiles), 00690 FALSE,0,this 00691 ); 00692 ol.endCodeFragment(); 00693 endFile(ol); 00694 ol.enableAll(); 00695 } 00696 00697 void FileDef::parseSource() 00698 { 00699 static bool filterSourceFiles = Config_getBool("FILTER_SOURCE_FILES"); 00700 DevNullCodeDocInterface devNullIntf; 00701 ParserInterface *pIntf = Doxygen::parserManager->getParser(getDefFileExtension()); 00702 pIntf->resetCodeParserState(); 00703 pIntf->parseCode( 00704 devNullIntf,0, 00705 fileToString(absFilePath(),filterSourceFiles), 00706 FALSE,0,this 00707 ); 00708 } 00709 00710 void FileDef::addMembersToMemberGroup() 00711 { 00712 QListIterator<MemberList> mli(m_memberLists); 00713 MemberList *ml; 00714 for (mli.toFirst();(ml=mli.current());++mli) 00715 { 00716 if (ml->listType()&MemberList::declarationLists) 00717 { 00718 ::addMembersToMemberGroup(ml,&memberGroupSDict,this); 00719 } 00720 } 00721 00722 // add members inside sections to their groups 00723 if (memberGroupSDict) 00724 { 00725 MemberGroupSDict::Iterator mgli(*memberGroupSDict); 00726 MemberGroup *mg; 00727 for (;(mg=mgli.current());++mgli) 00728 { 00729 if (mg->allMembersInSameSection() && m_subGrouping) 00730 { 00731 //printf("----> addToDeclarationSection(%s)\n",mg->header().data()); 00732 mg->addToDeclarationSection(); 00733 } 00734 } 00735 } 00736 } 00737 00739 void FileDef::insertMember(MemberDef *md) 00740 { 00741 if (md->isHidden()) return; 00742 //printf("%s:FileDef::insertMember(%s (=%p) list has %d elements)\n", 00743 // name().data(),md->name().data(),md,allMemberList.count()); 00744 MemberList *allMemberList = getMemberList(MemberList::allMembersList); 00745 if (allMemberList && allMemberList->findRef(md)!=-1) // TODO optimize the findRef! 00746 { 00747 return; 00748 } 00749 00750 if (allMemberList==0) 00751 { 00752 allMemberList = new MemberList(MemberList::allMembersList);; 00753 m_memberLists.append(allMemberList); 00754 } 00755 allMemberList->append(md); 00756 //::addFileMemberNameToIndex(md); 00757 switch (md->memberType()) 00758 { 00759 case MemberDef::Variable: 00760 case MemberDef::Property: 00761 addMemberToList(MemberList::decVarMembers,md); 00762 addMemberToList(MemberList::docVarMembers,md); 00763 break; 00764 case MemberDef::Function: 00765 addMemberToList(MemberList::decFuncMembers,md); 00766 addMemberToList(MemberList::docFuncMembers,md); 00767 break; 00768 case MemberDef::Typedef: 00769 addMemberToList(MemberList::decTypedefMembers,md); 00770 addMemberToList(MemberList::docTypedefMembers,md); 00771 break; 00772 case MemberDef::Enumeration: 00773 addMemberToList(MemberList::decEnumMembers,md); 00774 addMemberToList(MemberList::docEnumMembers,md); 00775 break; 00776 case MemberDef::EnumValue: // enum values are shown inside their enums 00777 break; 00778 case MemberDef::Prototype: 00779 addMemberToList(MemberList::decProtoMembers,md); 00780 addMemberToList(MemberList::docProtoMembers,md); 00781 break; 00782 case MemberDef::Define: 00783 addMemberToList(MemberList::decDefineMembers,md); 00784 addMemberToList(MemberList::docDefineMembers,md); 00785 break; 00786 default: 00787 err("FileDef::insertMembers(): " 00788 "member `%s' with class scope `%s' inserted in file scope `%s'!\n", 00789 md->name().data(), 00790 md->getClassDef() ? md->getClassDef()->name().data() : "<global>", 00791 name().data()); 00792 } 00793 //addMemberToGroup(md,groupId); 00794 } 00795 00797 void FileDef::insertClass(ClassDef *cd) 00798 { 00799 if (cd->isHidden()) return; 00800 if (classSDict==0) 00801 { 00802 classSDict = new ClassSDict(17); 00803 } 00804 if (Config_getBool("SORT_BRIEF_DOCS")) 00805 classSDict->inSort(cd->name(),cd); 00806 else 00807 classSDict->append(cd->name(),cd); 00808 } 00809 00811 void FileDef::insertNamespace(NamespaceDef *nd) 00812 { 00813 if (nd->isHidden()) return; 00814 if (!nd->name().isEmpty() && 00815 (namespaceSDict==0 || namespaceSDict->find(nd->name())==0)) 00816 { 00817 if (namespaceSDict==0) 00818 { 00819 namespaceSDict = new NamespaceSDict; 00820 } 00821 if (Config_getBool("SORT_BRIEF_DOCS")) 00822 namespaceSDict->inSort(nd->name(),nd); 00823 else 00824 namespaceSDict->append(nd->name(),nd); 00825 } 00826 } 00827 00828 void FileDef::addSourceRef(int line,Definition *d,MemberDef *md) 00829 { 00830 //printf("FileDef::addSourceDef(%d,%p,%p)\n",line,d,md); 00831 if (d) 00832 { 00833 if (srcDefDict==0) srcDefDict = new QIntDict<Definition>(257); 00834 if (srcMemberDict==0) srcMemberDict = new QIntDict<MemberDef>(257); 00835 srcDefDict->insert(line,d); 00836 if (md) srcMemberDict->insert(line,md); 00837 //printf("Adding member %s with anchor %s at line %d to file %s\n", 00838 // md->name().data(),md->anchor().data(),line,name().data()); 00839 } 00840 } 00841 00842 Definition *FileDef::getSourceDefinition(int lineNr) 00843 { 00844 Definition *result=0; 00845 if (srcDefDict) 00846 { 00847 result = srcDefDict->find(lineNr); 00848 } 00849 return result; 00850 } 00851 00852 MemberDef *FileDef::getSourceMember(int lineNr) 00853 { 00854 MemberDef *result=0; 00855 if (srcMemberDict) 00856 { 00857 result = srcMemberDict->find(lineNr); 00858 } 00859 return result; 00860 } 00861 00862 00863 void FileDef::addUsingDirective(NamespaceDef *nd) 00864 { 00865 if (usingDirList==0) 00866 { 00867 usingDirList = new NamespaceSDict; 00868 } 00869 if (usingDirList->find(nd->qualifiedName())==0) 00870 { 00871 usingDirList->append(nd->qualifiedName(),nd); 00872 } 00873 //printf("%p: FileDef::addUsingDirective: %s:%d\n",this,name().data(),usingDirList->count()); 00874 } 00875 00876 NamespaceSDict *FileDef::getUsedNamespaces() const 00877 { 00878 //printf("%p: FileDef::getUsedNamespace: %s:%d\n",this,name().data(),usingDirList?usingDirList->count():0); 00879 return usingDirList; 00880 } 00881 00882 void FileDef::addUsingDeclaration(Definition *d) 00883 { 00884 if (usingDeclList==0) 00885 { 00886 usingDeclList = new SDict<Definition>(17); 00887 } 00888 if (usingDeclList->find(d->qualifiedName())==0) 00889 { 00890 usingDeclList->append(d->qualifiedName(),d); 00891 } 00892 } 00893 00894 void FileDef::addIncludeDependency(FileDef *fd,const char *incName,bool local, 00895 bool imported) 00896 { 00897 //printf("FileDef::addIncludeDependency(%p,%s,%d)\n",fd,incName,local); 00898 QCString iName = fd ? fd->absFilePath().data() : incName; 00899 if (!iName.isEmpty() && (!includeDict || includeDict->find(iName)==0)) 00900 { 00901 if (includeDict==0) 00902 { 00903 includeDict = new QDict<IncludeInfo>(61); 00904 includeList = new QList<IncludeInfo>; 00905 includeList->setAutoDelete(TRUE); 00906 } 00907 IncludeInfo *ii = new IncludeInfo; 00908 ii->fileDef = fd; 00909 ii->includeName = incName; 00910 ii->local = local; 00911 ii->imported = imported; 00912 includeList->append(ii); 00913 includeDict->insert(iName,ii); 00914 } 00915 } 00916 00917 void FileDef::addIncludedUsingDirectives() 00918 { 00919 if (visited) return; 00920 visited=TRUE; 00921 //printf("( FileDef::addIncludedUsingDirectives for file %s\n",name().data()); 00922 00923 NamespaceList nl; 00924 if (includeList) // file contains #includes 00925 { 00926 { 00927 QListIterator<IncludeInfo> iii(*includeList); 00928 IncludeInfo *ii; 00929 for (iii.toFirst();(ii=iii.current());++iii) // foreach #include... 00930 { 00931 if (ii->fileDef && !ii->fileDef->visited) // ...that is a known file 00932 { 00933 // recurse into this file 00934 ii->fileDef->addIncludedUsingDirectives(); 00935 } 00936 } 00937 } 00938 { 00939 QListIterator<IncludeInfo> iii(*includeList); 00940 IncludeInfo *ii; 00941 // iterate through list from last to first 00942 for (iii.toLast();(ii=iii.current());--iii) 00943 { 00944 if (ii->fileDef && ii->fileDef!=this) 00945 { 00946 NamespaceSDict *unl = ii->fileDef->usingDirList; 00947 if (unl) 00948 { 00949 NamespaceSDict::Iterator nli(*unl); 00950 NamespaceDef *nd; 00951 for (nli.toLast();(nd=nli.current());--nli) 00952 { 00953 // append each using directive found in a #include file 00954 if (usingDirList==0) usingDirList = new NamespaceSDict; 00955 //printf("Prepending used namespace %s to the list of file %s\n", 00956 // nd->name().data(),name().data()); 00957 if (usingDirList->find(nd->qualifiedName())==0) // not yet added 00958 { 00959 usingDirList->prepend(nd->qualifiedName(),nd); 00960 } 00961 } 00962 } 00963 } 00964 } 00965 } 00966 } 00967 //printf(") end FileDef::addIncludedUsingDirectives for file %s\n",name().data()); 00968 } 00969 00970 00971 void FileDef::addIncludedByDependency(FileDef *fd,const char *incName, 00972 bool local,bool imported) 00973 { 00974 //printf("FileDef::addIncludedByDependency(%p,%s,%d)\n",fd,incName,local); 00975 QCString iName = fd ? fd->absFilePath().data() : incName; 00976 if (!iName.isEmpty() && (includedByDict==0 || includedByDict->find(iName)==0)) 00977 { 00978 if (includedByDict==0) 00979 { 00980 includedByDict = new QDict<IncludeInfo>(61); 00981 includedByList = new QList<IncludeInfo>; 00982 includedByList->setAutoDelete(TRUE); 00983 } 00984 IncludeInfo *ii = new IncludeInfo; 00985 ii->fileDef = fd; 00986 ii->includeName = incName; 00987 ii->local = local; 00988 ii->imported = imported; 00989 includedByList->append(ii); 00990 includedByDict->insert(iName,ii); 00991 } 00992 } 00993 00994 bool FileDef::isIncluded(const QCString &name) const 00995 { 00996 if (name.isEmpty()) return FALSE; 00997 return includeDict!=0 && includeDict->find(name)!=0; 00998 } 00999 01000 bool FileDef::generateSourceFile() const 01001 { 01002 QCString extension = name().right(4); 01003 return !isReference() && 01004 (Config_getBool("SOURCE_BROWSER") || 01005 (Config_getBool("VERBATIM_HEADERS") && guessSection(name())==Entry::HEADER_SEC) 01006 ) && 01007 extension!=".doc" && extension!=".txt" && extension!=".dox"; 01008 } 01009 01010 01011 void FileDef::addListReferences() 01012 { 01013 { 01014 LockingPtr< QList<ListItemInfo> > xrefItems = xrefListItems(); 01015 addRefItem(xrefItems.pointer(), 01016 theTranslator->trFile(TRUE,TRUE), 01017 getOutputFileBase(),name() 01018 ); 01019 } 01020 if (memberGroupSDict) 01021 { 01022 MemberGroupSDict::Iterator mgli(*memberGroupSDict); 01023 MemberGroup *mg; 01024 for (;(mg=mgli.current());++mgli) 01025 { 01026 mg->addListReferences(this); 01027 } 01028 } 01029 QListIterator<MemberList> mli(m_memberLists); 01030 MemberList *ml; 01031 for (mli.toFirst();(ml=mli.current());++mli) 01032 { 01033 if (ml->listType()&MemberList::documentationLists) 01034 { 01035 ml->addListReferences(this); 01036 } 01037 } 01038 } 01039 01040 //------------------------------------------------------------------- 01041 01042 static int findMatchingPart(const QCString &path,const QCString dir) 01043 { 01044 int si1; 01045 int pos1=0,pos2=0; 01046 while ((si1=path.find('/',pos1))!=-1) 01047 { 01048 int si2=dir.find('/',pos2); 01049 //printf(" found slash at pos %d in path %d: %s<->%s\n",si1,si2, 01050 // path.mid(pos1,si1-pos2).data(),dir.mid(pos2).data()); 01051 if (si2==-1 && path.mid(pos1,si1-pos2)==dir.mid(pos2)) // match at end 01052 { 01053 return dir.length(); 01054 } 01055 if (si1!=si2 || path.mid(pos1,si1-pos2)!=dir.mid(pos2,si2-pos2)) // no match in middle 01056 { 01057 return QMAX(pos1-1,0); 01058 } 01059 pos1=si1+1; 01060 pos2=si2+1; 01061 } 01062 return 0; 01063 } 01064 01065 static Directory *findDirNode(Directory *root,const QCString &name) 01066 { 01067 QListIterator<DirEntry> dli(root->children()); 01068 DirEntry *de; 01069 for (dli.toFirst();(de=dli.current());++dli) 01070 { 01071 if (de->kind()==DirEntry::Dir) 01072 { 01073 Directory *dir = (Directory *)de; 01074 QCString dirName=dir->name(); 01075 int sp=findMatchingPart(name,dirName); 01076 //printf("findMatchingPart(%s,%s)=%d\n",name.data(),dirName.data(),sp); 01077 if (sp>0) // match found 01078 { 01079 if ((uint)sp==dirName.length()) // whole directory matches 01080 { 01081 // recurse into the directory 01082 return findDirNode(dir,name.mid(dirName.length()+1)); 01083 } 01084 else // partial match => we need to split the path into three parts 01085 { 01086 QCString baseName =dirName.left(sp); 01087 QCString oldBranchName=dirName.mid(sp+1); 01088 QCString newBranchName=name.mid(sp+1); 01089 // strip file name from path 01090 int newIndex=newBranchName.findRev('/'); 01091 if (newIndex>0) newBranchName=newBranchName.left(newIndex); 01092 01093 //printf("Splitting off part in new branch \n" 01094 // "base=%s old=%s new=%s\n", 01095 // baseName.data(), 01096 // oldBranchName.data(), 01097 // newBranchName.data() 01098 // ); 01099 Directory *base = new Directory(root,baseName); 01100 Directory *newBranch = new Directory(base,newBranchName); 01101 dir->reParent(base); 01102 dir->rename(oldBranchName); 01103 base->addChild(dir); 01104 base->addChild(newBranch); 01105 dir->setLast(FALSE); 01106 // remove DirEntry container from list (without deleting it) 01107 root->children().setAutoDelete(FALSE); 01108 root->children().removeRef(dir); 01109 root->children().setAutoDelete(TRUE); 01110 // add new branch to the root 01111 if (!root->children().isEmpty()) 01112 { 01113 root->children().last()->setLast(FALSE); 01114 } 01115 root->addChild(base); 01116 return newBranch; 01117 } 01118 } 01119 } 01120 } 01121 int si=name.findRev('/'); 01122 if (si==-1) // no subdir 01123 { 01124 return root; // put the file under the root node. 01125 } 01126 else // need to create a subdir 01127 { 01128 QCString baseName = name.left(si); 01129 //printf("new subdir %s\n",baseName.data()); 01130 Directory *newBranch = new Directory(root,baseName); 01131 if (!root->children().isEmpty()) 01132 { 01133 root->children().last()->setLast(FALSE); 01134 } 01135 root->addChild(newBranch); 01136 return newBranch; 01137 } 01138 } 01139 01140 static void mergeFileDef(Directory *root,FileDef *fd) 01141 { 01142 QCString rootPath = root->name(); 01143 QCString filePath = fd->absFilePath(); 01144 //printf("merging %s\n",filePath.data()); 01145 Directory *dirNode = findDirNode(root,filePath); 01146 if (!dirNode->children().isEmpty()) 01147 { 01148 dirNode->children().last()->setLast(FALSE); 01149 } 01150 DirEntry *e=new DirEntry(dirNode,fd); 01151 dirNode->addChild(e); 01152 } 01153 01154 #if 0 01155 static void generateIndent(QTextStream &t,DirEntry *de,int level) 01156 { 01157 if (de->parent()) 01158 { 01159 generateIndent(t,de->parent(),level+1); 01160 } 01161 // from the root up to node n do... 01162 if (level==0) // item before a dir or document 01163 { 01164 if (de->isLast()) 01165 { 01166 if (de->kind()==DirEntry::Dir) 01167 { 01168 t << "<img " << FTV_IMGATTRIBS(plastnode) << "/>"; 01169 } 01170 else 01171 { 01172 t << "<img " << FTV_IMGATTRIBS(lastnode) << "/>"; 01173 } 01174 } 01175 else 01176 { 01177 if (de->kind()==DirEntry::Dir) 01178 { 01179 t << "<img " << FTV_IMGATTRIBS(pnode) << "/>"; 01180 } 01181 else 01182 { 01183 t << "<img " << FTV_IMGATTRIBS(node) << "/>"; 01184 } 01185 } 01186 } 01187 else // item at another level 01188 { 01189 if (de->isLast()) 01190 { 01191 t << "<img " << FTV_IMGATTRIBS(blank) << "/>"; 01192 } 01193 else 01194 { 01195 t << "<img " << FTV_IMGATTRIBS(vertline) << "/>"; 01196 } 01197 } 01198 } 01199 01200 static void writeDirTreeNode(QTextStream &t,Directory *root,int level) 01201 { 01202 QCString indent; 01203 indent.fill(' ',level*2); 01204 QListIterator<DirEntry> dli(root->children()); 01205 DirEntry *de; 01206 for (dli.toFirst();(de=dli.current());++dli) 01207 { 01208 t << indent << "<p>"; 01209 generateIndent(t,de,0); 01210 if (de->kind()==DirEntry::Dir) 01211 { 01212 Directory *dir=(Directory *)de; 01213 //printf("%s [dir]: %s (last=%d,dir=%d)\n",indent.data(),dir->name().data(),dir->isLast(),dir->kind()==DirEntry::Dir); 01214 t << "<img " << FTV_IMGATTRIBS(folderclosed) << "/>"; 01215 t << dir->name(); 01216 t << "</p>\n"; 01217 t << indent << "<div>\n"; 01218 writeDirTreeNode(t,dir,level+1); 01219 t << indent << "</div>\n"; 01220 } 01221 else 01222 { 01223 //printf("%s [file]: %s (last=%d,dir=%d)\n",indent.data(),de->file()->name().data(),de->isLast(),de->kind()==DirEntry::Dir); 01224 t << "<img " << FTV_IMGATTRIBS(doc) << "/>"; 01225 t << de->file()->name(); 01226 t << "</p>\n"; 01227 } 01228 } 01229 } 01230 #endif 01231 01232 static void addDirsAsGroups(Directory *root,GroupDef *parent,int level) 01233 { 01234 GroupDef *gd=0; 01235 if (root->kind()==DirEntry::Dir) 01236 { 01237 gd = new GroupDef("[generated]", 01238 1, 01239 root->path(), // name 01240 root->name() // title 01241 ); 01242 if (parent) 01243 { 01244 parent->addGroup(gd); 01245 gd->makePartOfGroup(parent); 01246 } 01247 else 01248 { 01249 Doxygen::groupSDict->append(root->path(),gd); 01250 } 01251 } 01252 QListIterator<DirEntry> dli(root->children()); 01253 DirEntry *de; 01254 for (dli.toFirst();(de=dli.current());++dli) 01255 { 01256 if (de->kind()==DirEntry::Dir) 01257 { 01258 addDirsAsGroups((Directory *)de,gd,level+1); 01259 } 01260 } 01261 } 01262 01263 void generateFileTree() 01264 { 01265 Directory *root=new Directory(0,"root"); 01266 root->setLast(TRUE); 01267 FileNameListIterator fnli(*Doxygen::inputNameList); 01268 FileName *fn; 01269 for (fnli.toFirst();(fn=fnli.current());++fnli) 01270 { 01271 FileNameIterator fni(*fn); 01272 FileDef *fd; 01273 for (;(fd=fni.current());++fni) 01274 { 01275 mergeFileDef(root,fd); 01276 } 01277 } 01278 //t << "<div class=\"directory\">\n"; 01279 //writeDirTreeNode(t,root,0); 01280 //t << "</div>\n"; 01281 addDirsAsGroups(root,0,0); 01282 delete root; 01283 } 01284 01285 //------------------------------------------------------------------- 01286 01287 void FileDef::combineUsingRelations() 01288 { 01289 if (visited) return; // already done 01290 visited=TRUE; 01291 if (usingDirList) 01292 { 01293 NamespaceSDict::Iterator nli(*usingDirList); 01294 NamespaceDef *nd; 01295 for (nli.toFirst();(nd=nli.current());++nli) 01296 { 01297 nd->combineUsingRelations(); 01298 } 01299 for (nli.toFirst();(nd=nli.current());++nli) 01300 { 01301 // add used namespaces of namespace nd to this namespace 01302 if (nd->getUsedNamespaces()) 01303 { 01304 NamespaceSDict::Iterator unli(*nd->getUsedNamespaces()); 01305 NamespaceDef *und; 01306 for (unli.toFirst();(und=unli.current());++unli) 01307 { 01308 //printf("Adding namespace %s to the using list of %s\n",und->qualifiedName().data(),qualifiedName().data()); 01309 addUsingDirective(und); 01310 } 01311 } 01312 // add used classes of namespace nd to this namespace 01313 if (nd->getUsedClasses()) 01314 { 01315 SDict<Definition>::Iterator cli(*nd->getUsedClasses()); 01316 Definition *ucd; 01317 for (cli.toFirst();(ucd=cli.current());++cli) 01318 { 01319 //printf("Adding class %s to the using list of %s\n",cd->qualifiedName().data(),qualifiedName().data()); 01320 addUsingDeclaration(ucd); 01321 } 01322 } 01323 } 01324 } 01325 } 01326 01327 bool FileDef::isDocumentationFile() const 01328 { 01329 return name().right(4)==".doc" || 01330 name().right(4)==".txt" || 01331 name().right(4)==".dox"; 01332 } 01333 01334 void FileDef::acquireFileVersion() 01335 { 01336 QCString vercmd = Config_getString("FILE_VERSION_FILTER"); 01337 if (!vercmd.isEmpty()) 01338 { 01339 msg("Version of %s : ",filepath.data()); 01340 QCString cmd = vercmd+" \""+filepath+"\""; 01341 Debug::print(Debug::ExtCmd,0,"Executing popen(`%s`)\n",cmd.data()); 01342 FILE *f=portable_popen(cmd,"r"); 01343 if (!f) 01344 { 01345 err("Error: could not execute %s\n",vercmd.data()); 01346 return; 01347 } 01348 const int bufSize=1024; 01349 char buf[bufSize]; 01350 int numRead = fread(buf,1,bufSize,f); 01351 portable_pclose(f); 01352 if (numRead > 0) 01353 { 01354 fileVersion = QCString(buf,numRead).stripWhiteSpace(); 01355 msg("%s\n",fileVersion.data()); 01356 } 01357 else 01358 { 01359 msg("no version available\n"); 01360 } 01361 } 01362 } 01363 01364 01365 QCString FileDef::getSourceFileBase() const 01366 { 01367 if (Htags::useHtags) 01368 { 01369 return Htags::path2URL(filepath); 01370 } 01371 else 01372 { 01373 return convertNameToFile(diskname+"-source"); 01374 } 01375 } 01376 01378 QCString FileDef::includeName() const 01379 { 01380 if (Htags::useHtags) 01381 { 01382 return Htags::path2URL(filepath); 01383 } 01384 else 01385 { 01386 return convertNameToFile(diskname+"-source"); 01387 } 01388 } 01389 01390 MemberList *FileDef::createMemberList(MemberList::ListType lt) 01391 { 01392 m_memberLists.setAutoDelete(TRUE); 01393 QListIterator<MemberList> mli(m_memberLists); 01394 MemberList *ml; 01395 for (mli.toFirst();(ml=mli.current());++mli) 01396 { 01397 if (ml->listType()==lt) 01398 { 01399 return ml; 01400 } 01401 } 01402 // not found, create a new member list 01403 ml = new MemberList(lt); 01404 m_memberLists.append(ml); 01405 return ml; 01406 } 01407 01408 void FileDef::addMemberToList(MemberList::ListType lt,MemberDef *md) 01409 { 01410 static bool sortBriefDocs = Config_getBool("SORT_BRIEF_DOCS"); 01411 static bool sortMemberDocs = Config_getBool("SORT_MEMBER_DOCS"); 01412 MemberList *ml = createMemberList(lt); 01413 if (((ml->listType()&MemberList::declarationLists) && sortBriefDocs) || 01414 ((ml->listType()&MemberList::documentationLists) && sortMemberDocs) 01415 ) 01416 ml->inSort(md); 01417 else 01418 ml->append(md); 01419 if (lt&MemberList::documentationLists) 01420 { 01421 ml->setInFile(TRUE); 01422 } 01423 if (ml->listType()&MemberList::declarationLists) md->setSectionList(this,ml); 01424 } 01425 01426 MemberList *FileDef::getMemberList(MemberList::ListType lt) const 01427 { 01428 FileDef *that = (FileDef*)this; 01429 MemberList *ml = that->m_memberLists.first(); 01430 while (ml) 01431 { 01432 if (ml->listType()==lt) 01433 { 01434 return ml; 01435 } 01436 ml = that->m_memberLists.next(); 01437 } 01438 return 0; 01439 } 01440 01441 void FileDef::writeMemberDeclarations(OutputList &ol,MemberList::ListType lt,const QCString &title) 01442 { 01443 MemberList * ml = getMemberList(lt); 01444 if (ml) ml->writeDeclarations(ol,0,0,this,0,title,0); 01445 } 01446 01447 void FileDef::writeMemberDocumentation(OutputList &ol,MemberList::ListType lt,const QCString &title) 01448 { 01449 MemberList * ml = getMemberList(lt); 01450 if (ml) ml->writeDocumentation(ol,name(),this,title); 01451 }