My Project
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
filedef.cpp
Go to the documentation of this file.
1 /******************************************************************************
2  *
3  *
4  *
5  * Copyright (C) 1997-2015 by Dimitri van Heesch.
6  *
7  * Permission to use, copy, modify, and distribute this software and its
8  * documentation under the terms of the GNU General Public License is hereby
9  * granted. No representations are made about the suitability of this software
10  * for any purpose. It is provided "as is" without express or implied warranty.
11  * See the GNU General Public License for more details.
12  *
13  * Documents produced by Doxygen are derivative works derived from the
14  * input used in their production; they are not affected by this license.
15  *
16  */
17 
18 #include "memberlist.h"
19 #include "classlist.h"
20 #include "filedef.h"
21 #include "doxygen.h"
22 #include "memberdef.h"
23 #include "classdef.h"
24 #include "namespacedef.h"
25 #include "util.h"
26 #include "language.h"
27 #include "outputlist.h"
28 #include "dot.h"
29 #include "message.h"
30 #include "docparser.h"
31 #include "searchindex.h"
32 #include "htags.h"
33 #include "parserintf.h"
34 #include "portable.h"
35 #include "vhdldocgen.h"
36 #include "debug.h"
37 #include "layout.h"
38 #include "entry.h"
39 #include "groupdef.h"
40 #include "filename.h"
41 #include "membergroup.h"
42 #include "dirdef.h"
43 #include "config.h"
44 #include "clangparser.h"
45 #include "settings.h"
46 
47 //---------------------------------------------------------------------------
48 
51 {
52  public:
53  virtual void codify(const char *) {}
54  virtual void writeCodeLink(const char *,const char *,
55  const char *,const char *,
56  const char *) {}
57  virtual void writeTooltip(const char *, const DocLinkInfo &, const char *,
58  const char *, const SourceLinkInfo &, const SourceLinkInfo &
59  ) {}
60  virtual void writeLineNumber(const char *,const char *,
61  const char *,int) {}
62  virtual void startCodeLine(bool) {}
63  virtual void endCodeLine() {}
64  virtual void startFontClass(const char *) {}
65  virtual void endFontClass() {}
66  virtual void writeCodeAnchor(const char *) {}
67  virtual void linkableSymbol(int, const char *,Definition *,Definition *) {}
68  virtual void setCurrentDoc(Definition *,const char *,bool) {}
69  virtual void addWord(const char *,bool) {}
70 };
71 
72 //---------------------------------------------------------------------------
73 
78 FileDef::FileDef(const char *p,const char *nm,
79  const char *lref,const char *dn)
80  : Definition((QCString)p+nm,1,1,nm)
81 {
82  m_path=p;
83  m_filePath=m_path+nm;
84  m_fileName=nm;
85  setDiskName(dn?dn:nm);
86  setReference(lref);
87  m_classSDict = 0;
88  m_includeList = 0;
89  m_includeDict = 0;
90  m_includedByList = 0;
91  m_includedByDict = 0;
92  m_namespaceSDict = 0;
93  m_srcDefDict = 0;
94  m_srcMemberDict = 0;
95  m_usingDirList = 0;
96  m_usingDeclList = 0;
97  m_package = 0;
99  m_docname = nm;
100  m_dir = 0;
101  if (Config_getBool(FULL_PATH_NAMES))
102  {
103  m_docname.prepend(stripFromPath(m_path.copy()));
104  }
106  m_memberGroupSDict = 0;
108  m_subGrouping=Config_getBool(SUBGROUPING);
109 }
110 
113 {
114  delete m_classSDict;
115  delete m_includeDict;
116  delete m_includeList;
117  delete m_includedByDict;
118  delete m_includedByList;
119  delete m_namespaceSDict;
120  delete m_srcDefDict;
121  delete m_srcMemberDict;
122  delete m_usingDirList;
123  delete m_usingDeclList;
124  delete m_memberGroupSDict;
125 }
126 
127 void FileDef::setDiskName(const QCString &name)
128 {
130  m_inclDepFileName = convertNameToFile(name+"_incl");
131  m_inclByDepFileName = convertNameToFile(name+"_dep_incl");
132 }
133 
136 {
138  if (ml) setAnchors(ml);
139 }
140 
142 {
143  //printf("FileDef::distributeMemberGroupDocumentation()\n");
144  if (m_memberGroupSDict)
145  {
147  MemberGroup *mg;
148  for (;(mg=mgli.current());++mgli)
149  {
151  }
152  }
153 }
154 
156 {
158  if (m_memberGroupSDict)
159  {
161  MemberGroup *mg;
162  for (;(mg=mgli.current());++mgli)
163  {
165  }
166  }
167 
168  QListIterator<MemberList> mli(m_memberLists);
169  MemberList *ml;
170  for (mli.toFirst();(ml=mli.current());++mli)
171  {
173  {
175  }
176  }
177 }
178 
180 {
181  static bool repeatBrief = Config_getBool(REPEAT_BRIEF);
182  static bool sourceBrowser = Config_getBool(SOURCE_BROWSER);
183  return ((!briefDescription().isEmpty() && repeatBrief) ||
184  !documentation().stripWhiteSpace().isEmpty() || // avail empty section
185  (sourceBrowser && getStartBodyLine()!=-1 && getBodyDef())
186  );
187 }
188 
190 {
191  tagFile << " <compound kind=\"file\">" << endl;
192  tagFile << " <name>" << convertToXML(name()) << "</name>" << endl;
193  tagFile << " <path>" << convertToXML(getPath()) << "</path>" << endl;
194  tagFile << " <filename>" << convertToXML(getOutputFileBase()) << "</filename>" << endl;
195  if (m_includeList && m_includeList->count()>0)
196  {
197  QListIterator<IncludeInfo> ili(*m_includeList);
198  IncludeInfo *ii;
199  for (;(ii=ili.current());++ili)
200  {
201  if (!ii->indirect)
202  {
203  FileDef *fd=ii->fileDef;
204  if (fd && fd->isLinkable() && !fd->isReference())
205  {
206  bool isIDLorJava = FALSE;
207  SrcLangExt lang = fd->getLanguage();
208  isIDLorJava = lang==SrcLangExt_IDL || lang==SrcLangExt_Java;
209  const char *locStr = (ii->local || isIDLorJava) ? "yes" : "no";
210  const char *impStr = (ii->imported || isIDLorJava) ? "yes" : "no";
211  tagFile << " <includes id=\""
212  << convertToXML(fd->getOutputFileBase()) << "\" "
213  << "name=\"" << convertToXML(fd->name()) << "\" "
214  << "local=\"" << locStr << "\" "
215  << "imported=\"" << impStr << "\">"
216  << convertToXML(ii->includeName)
217  << "</includes>"
218  << endl;
219  }
220  }
221  }
222  }
223  QListIterator<LayoutDocEntry> eli(
225  LayoutDocEntry *lde;
226  for (eli.toFirst();(lde=eli.current());++eli)
227  {
228  switch (lde->kind())
229  {
231  {
232  if (m_classSDict)
233  {
235  ClassDef *cd;
236  for (ci.toFirst();(cd=ci.current());++ci)
237  {
238  if (cd->isLinkableInProject())
239  {
240  tagFile << " <class kind=\"" << cd->compoundTypeString() <<
241  "\">" << convertToXML(cd->name()) << "</class>" << endl;
242  }
243  }
244  }
245  }
246  break;
248  {
249  if (m_namespaceSDict)
250  {
252  NamespaceDef *nd;
253  for (ni.toFirst();(nd=ni.current());++ni)
254  {
255  if (nd->isLinkableInProject())
256  {
257  tagFile << " <namespace>" << convertToXML(nd->name()) << "</namespace>" << endl;
258  }
259  }
260  }
261  }
262  break;
264  {
266  MemberList * ml = getMemberList(lmd->type);
267  if (ml)
268  {
269  ml->writeTagFile(tagFile);
270  }
271  }
272  break;
274  {
275  if (m_memberGroupSDict)
276  {
278  MemberGroup *mg;
279  for (;(mg=mgli.current());++mgli)
280  {
281  mg->writeTagFile(tagFile);
282  }
283  }
284  }
285  break;
286  default:
287  break;
288  }
289  }
290 
291  writeDocAnchorsToTagFile(tagFile);
292  tagFile << " </compound>" << endl;
293 }
294 
295 void FileDef::writeDetailedDescription(OutputList &ol,const QCString &title)
296 {
298  {
299  ol.pushGeneratorState();
301  ol.writeRuler();
302  ol.popGeneratorState();
303  ol.pushGeneratorState();
305  ol.writeAnchor(0,"details");
306  ol.popGeneratorState();
307  ol.startGroupHeader();
308  ol.parseText(title);
309  ol.endGroupHeader();
310 
311  ol.startTextBlock();
312  if (!briefDescription().isEmpty() && Config_getBool(REPEAT_BRIEF))
313  {
314  ol.generateDoc(briefFile(),briefLine(),this,0,briefDescription(),FALSE,FALSE);
315  }
316  if (!briefDescription().isEmpty() && Config_getBool(REPEAT_BRIEF) &&
317  !documentation().isEmpty())
318  {
319  ol.pushGeneratorState();
322  // ol.newParagraph(); // FIXME:PARA
323  ol.enableAll();
326  ol.writeString("\n\n");
327  ol.popGeneratorState();
328  }
329  if (!documentation().isEmpty())
330  {
331  ol.generateDoc(docFile(),docLine(),this,0,documentation()+"\n",TRUE,FALSE);
332  }
333  //printf("Writing source ref for file %s\n",name().data());
334  if (Config_getBool(SOURCE_BROWSER))
335  {
336  //if Latex enabled and LATEX_SOURCE_CODE isn't -> skip, bug_738548
337  ol.pushGeneratorState();
338  if (ol.isEnabled(OutputGenerator::Latex) && !Config_getBool(LATEX_SOURCE_CODE))
339  {
341  }
342  if (ol.isEnabled(OutputGenerator::RTF) && !Config_getBool(RTF_SOURCE_CODE))
343  {
345  }
346 
347  ol.startParagraph();
348  QCString refText = theTranslator->trDefinedInSourceFile();
349  int fileMarkerPos = refText.find("@0");
350  if (fileMarkerPos!=-1) // should always pass this.
351  {
352  ol.parseText(refText.left(fileMarkerPos)); //text left from marker 1
354  0,name());
355  ol.parseText(refText.right(
356  refText.length()-fileMarkerPos-2)); // text right from marker 2
357  }
358  ol.endParagraph();
359  //Restore settings, bug_738548
360  ol.popGeneratorState();
361  }
362  ol.endTextBlock();
363  }
364 }
365 
367 {
368  if (!briefDescription().isEmpty() && Config_getBool(BRIEF_MEMBER_DESC))
369  {
370  DocRoot *rootNode = validatingParseDoc(briefFile(),briefLine(),this,0,
371  briefDescription(),TRUE,FALSE,0,TRUE,FALSE);
372 
373  if (rootNode && !rootNode->isEmpty())
374  {
375  ol.startParagraph();
376  ol.writeDoc(rootNode,this,0);
377  ol.pushGeneratorState();
379  ol.writeString(" \n");
381 
382  if (Config_getBool(REPEAT_BRIEF) ||
383  !documentation().isEmpty()
384  )
385  {
387  ol.startTextLink(0,"details");
389  ol.endTextLink();
390  }
391  ol.popGeneratorState();
392  ol.endParagraph();
393  }
394  delete rootNode;
395  }
396  ol.writeSynopsis();
397 }
398 
400 {
401  if (m_includeList && m_includeList->count()>0)
402  {
403  ol.startTextBlock(TRUE);
404  QListIterator<IncludeInfo> ili(*m_includeList);
405  IncludeInfo *ii;
406  for (;(ii=ili.current());++ili)
407  {
408  if (!ii->indirect)
409  {
410  FileDef *fd=ii->fileDef;
411  bool isIDLorJava = FALSE;
412  if (fd)
413  {
414  SrcLangExt lang = fd->getLanguage();
415  isIDLorJava = lang==SrcLangExt_IDL || lang==SrcLangExt_Java;
416  }
417  ol.startTypewriter();
418  if (isIDLorJava) // IDL/Java include
419  {
420  ol.docify("import ");
421  }
422  else if (ii->imported) // Objective-C include
423  {
424  ol.docify("#import ");
425  }
426  else // C/C++ include
427  {
428  ol.docify("#include ");
429  }
430  if (ii->local || isIDLorJava)
431  ol.docify("\"");
432  else
433  ol.docify("<");
435  ol.docify(ii->includeName);
436  ol.enableAll();
438 
439  // Here we use the include file name as it appears in the file.
440  // we could also we the name as it is used within doxygen,
441  // then we should have used fd->docName() instead of ii->includeName
442  if (fd && fd->isLinkable())
443  {
444  ol.writeObjectLink(fd->getReference(),
445  fd->generateSourceFile() ? fd->includeName() : fd->getOutputFileBase(),
446  0,ii->includeName);
447  }
448  else
449  {
450  ol.docify(ii->includeName);
451  }
452 
453  ol.enableAll();
454  if (ii->local || isIDLorJava)
455  ol.docify("\"");
456  else
457  ol.docify(">");
458  if (isIDLorJava)
459  ol.docify(";");
460  ol.endTypewriter();
461  ol.lineBreak();
462  }
463  }
464  ol.endTextBlock();
465  }
466 }
467 
469 {
470  if (Config_getBool(HAVE_DOT) /*&& Config_getBool(INCLUDE_GRAPH)*/)
471  {
472  //printf("Graph for file %s\n",name().data());
473  DotInclDepGraph incDepGraph(this,FALSE);
474  if (incDepGraph.isTooBig())
475  {
476  warn_uncond("Include graph for '%s' not generated, too many nodes. Consider increasing DOT_GRAPH_MAX_NODES.\n",name().data());
477  }
478  else if (!incDepGraph.isTrivial())
479  {
480  ol.startTextBlock();
482  ol.startInclDepGraph();
484  ol.endInclDepGraph(incDepGraph);
485  ol.enableAll();
486  ol.endTextBlock(TRUE);
487  }
488  //incDepGraph.writeGraph(Config_getString(HTML_OUTPUT),fd->getOutputFileBase());
489  }
490 }
491 
493 {
494  if (Config_getBool(HAVE_DOT) /*&& Config_getBool(INCLUDED_BY_GRAPH)*/)
495  {
496  //printf("Graph for file %s\n",name().data());
497  DotInclDepGraph incDepGraph(this,TRUE);
498  if (incDepGraph.isTooBig())
499  {
500  warn_uncond("Included by graph for '%s' not generated, too many nodes. Consider increasing DOT_GRAPH_MAX_NODES.\n",name().data());
501  }
502  else if (!incDepGraph.isTrivial())
503  {
504  ol.startTextBlock();
506  ol.startInclDepGraph();
508  ol.endInclDepGraph(incDepGraph);
509  ol.enableAll();
510  ol.endTextBlock(TRUE);
511  }
512  //incDepGraph.writeGraph(Config_getString(HTML_OUTPUT),fd->getOutputFileBase());
513  }
514 }
515 
516 
518 {
519  //printf("%s: generateSourceFile()=%d\n",name().data(),generateSourceFile());
520  if (generateSourceFile())
521  {
523  ol.startParagraph();
524  ol.startTextLink(includeName(),0);
526  ol.endTextLink();
527  ol.endParagraph();
528  ol.enableAll();
529  }
530 }
531 
532 void FileDef::writeNamespaceDeclarations(OutputList &ol,const QCString &title,
533  bool const isConstantGroup)
534 {
535  // write list of namespaces
536  if (m_namespaceSDict) m_namespaceSDict->writeDeclaration(ol,title,isConstantGroup);
537 }
538 
539 void FileDef::writeClassDeclarations(OutputList &ol,const QCString &title)
540 {
541  // write list of classes
542  if (m_classSDict) m_classSDict->writeDeclaration(ol,0,title,FALSE);
543 }
544 
546 {
547  // temporarily undo the disbling could be done by startMemberDocumentation()
548  // as a result of setting SEPARATE_MEMBER_PAGES to YES; see bug730512
549  bool isEnabled = ol.isEnabled(OutputGenerator::Html);
551 
553 
554  // restore the initial state if needed
555  if (!isEnabled) ol.disable(OutputGenerator::Html);
556 }
557 
559 {
560  ol.startMemberSections();
561 }
562 
564 {
565  ol.endMemberSections();
566 }
567 
569 {
570  if (Config_getBool(SEPARATE_MEMBER_PAGES))
571  {
574  }
575 }
576 
578 {
579  if (Config_getBool(SEPARATE_MEMBER_PAGES))
580  {
583  }
584 }
585 
587 {
588  /* write user defined member groups */
589  if (m_memberGroupSDict)
590  {
593  MemberGroup *mg;
594  for (;(mg=mgli.current());++mgli)
595  {
596  if ((!mg->allMembersInSameSection() || !m_subGrouping)
597  && mg->header()!="[NOHEADER]")
598  {
599  mg->writeDeclarations(ol,0,0,this,0);
600  }
601  }
602  }
603 }
604 
606 {
607  // write Author section (Man only)
608  ol.pushGeneratorState();
610  ol.startGroupHeader();
611  ol.parseText(theTranslator->trAuthor(TRUE,TRUE));
612  ol.endGroupHeader();
614  ol.popGeneratorState();
615 }
616 
618 {
619  ol.pushGeneratorState();
621  QListIterator<LayoutDocEntry> eli(
623  LayoutDocEntry *lde;
624  bool first=TRUE;
625  SrcLangExt lang=getLanguage();
626  for (eli.toFirst();(lde=eli.current());++eli)
627  {
628  if ((lde->kind()==LayoutDocEntry::FileClasses &&
632  )
633  {
635  QCString label = lde->kind()==LayoutDocEntry::FileClasses ? "nested-classes" : "namespaces";
636  ol.writeSummaryLink(0,label,ls->title(lang),first);
637  first=FALSE;
638  }
639  else if (lde->kind()==LayoutDocEntry::MemberDecl)
640  {
642  MemberList * ml = getMemberList(lmd->type);
643  if (ml && ml->declVisible())
644  {
645  ol.writeSummaryLink(0,MemberList::listTypeAsString(ml->listType()),lmd->title(lang),first);
646  first=FALSE;
647  }
648  }
649  }
650  if (!first)
651  {
652  ol.writeString(" </div>\n");
653  }
654  ol.popGeneratorState();
655 }
656 
661 {
662  static bool generateTreeView = Config_getBool(GENERATE_TREEVIEW);
663  //funcList->countDecMembers();
664 
665  //QCString fn = name();
666  //if (Config_getBool(FULL_PATH_NAMES))
667  //{
668  // fn.prepend(stripFromPath(getPath().copy()));
669  //}
670 
671  //printf("WriteDocumentation diskname=%s\n",diskname.data());
672 
673  QCString versionTitle;
674  if (!m_fileVersion.isEmpty())
675  {
676  versionTitle=("("+m_fileVersion+")");
677  }
678  QCString title = m_docname+versionTitle;
679  QCString pageTitle=theTranslator->trFileReference(m_docname);
680 
681  if (getDirDef())
682  {
683  startFile(ol,getOutputFileBase(),name(),pageTitle,HLI_FileVisible,!generateTreeView);
684  if (!generateTreeView)
685  {
687  ol.endQuickIndices();
688  }
689  QCString pageTitleShort=theTranslator->trFileReference(name());
690  startTitle(ol,getOutputFileBase(),this);
691  ol.pushGeneratorState();
693  ol.parseText(pageTitleShort); // Html only
694  ol.enableAll();
696  ol.parseText(pageTitle); // other output formats
697  ol.popGeneratorState();
698  addGroupListToTitle(ol,this);
699  endTitle(ol,getOutputFileBase(),title);
700  }
701  else
702  {
703  startFile(ol,getOutputFileBase(),name(),pageTitle,HLI_FileVisible,!generateTreeView);
704  if (!generateTreeView)
705  {
706  ol.endQuickIndices();
707  }
708  startTitle(ol,getOutputFileBase(),this);
709  ol.parseText(pageTitle);
710  addGroupListToTitle(ol,this);
711  endTitle(ol,getOutputFileBase(),title);
712  }
713 
714  ol.startContents();
715 
716  if (!m_fileVersion.isEmpty())
717  {
719  ol.startProjectNumber();
720  ol.docify(versionTitle);
721  ol.endProjectNumber();
722  ol.enableAll();
723  }
724 
726  {
729  }
730 
731 
732  //---------------------------------------- start flexible part -------------------------------
733 
734  SrcLangExt lang = getLanguage();
735  QListIterator<LayoutDocEntry> eli(
737  LayoutDocEntry *lde;
738  for (eli.toFirst();(lde=eli.current());++eli)
739  {
740  switch (lde->kind())
741  {
744  break;
747  break;
749  writeIncludeFiles(ol);
750  break;
752  writeIncludeGraph(ol);
753  break;
756  break;
758  writeSourceLink(ol);
759  break;
761  {
763  writeClassDeclarations(ol,ls->title(lang));
764  }
765  break;
767  {
769  writeNamespaceDeclarations(ol,ls->title(lang),false);
770  }
771  break;
773  {
775  writeNamespaceDeclarations(ol,ls->title(lang),true);
776  }
777  break;
779  writeMemberGroups(ol);
780  break;
782  {
784  writeMemberDeclarations(ol,lmd->type,lmd->title(lang));
785  }
786  break;
789  break;
791  {
793  writeDetailedDescription(ol,ls->title(lang));
794  }
795  break;
798  break;
800  writeInlineClasses(ol);
801  break;
803  {
805  writeMemberDocumentation(ol,lmd->type,lmd->title(lang));
806  }
807  break;
810  break;
812  writeAuthorSection(ol);
813  break;
836  err("Internal inconsistency: member %d should not be part of "
837  "LayoutDocManager::File entry list\n",lde->kind());
838  break;
839  }
840  }
841 
842  //---------------------------------------- end flexible part -------------------------------
843 
844  ol.endContents();
845 
846  endFileWithNavPath(this,ol);
847 
848  if (Config_getBool(SEPARATE_MEMBER_PAGES))
849  {
851  if (ml) ml->sort();
852  writeMemberPages(ol);
853  }
854 }
855 
857 {
858  ol.pushGeneratorState();
860 
861  QListIterator<MemberList> mli(m_memberLists);
862  MemberList *ml;
863  for (mli.toFirst();(ml=mli.current());++mli)
864  {
866  {
867  ml->writeDocumentationPage(ol,name(),this);
868  }
869  }
870 
871  ol.popGeneratorState();
872 }
873 
875 {
876  static bool createSubDirs=Config_getBool(CREATE_SUBDIRS);
877 
878  ol.writeString(" <div class=\"navtab\">\n");
879  ol.writeString(" <table>\n");
880 
882  if (allMemberList)
883  {
884  MemberListIterator mli(*allMemberList);
885  MemberDef *md;
886  for (mli.toFirst();(md=mli.current());++mli)
887  {
888  if (md->getFileDef()==this && md->getNamespaceDef()==0 && md->isLinkable() && !md->isEnumValue())
889  {
890  ol.writeString(" <tr><td class=\"navtab\">");
891  if (md->isLinkableInProject())
892  {
893  if (md==currentMd) // selected item => highlight
894  {
895  ol.writeString("<a class=\"qindexHL\" ");
896  }
897  else
898  {
899  ol.writeString("<a class=\"qindex\" ");
900  }
901  ol.writeString("href=\"");
902  if (createSubDirs) ol.writeString("../../");
904  ol.writeString("\">");
906  ol.writeString("</a>");
907  }
908  ol.writeString("</td></tr>\n");
909  }
910  }
911  }
912 
913  ol.writeString(" </table>\n");
914  ol.writeString(" </div>\n");
915 }
916 
918 void FileDef::writeSource(OutputList &ol,bool sameTu,QStrList &filesInSameTu)
919 {
920  static bool generateTreeView = Config_getBool(GENERATE_TREEVIEW);
921  static bool filterSourceFiles = Config_getBool(FILTER_SOURCE_FILES);
922  static bool latexSourceCode = Config_getBool(LATEX_SOURCE_CODE);
923  static bool rtfSourceCode = Config_getBool(RTF_SOURCE_CODE);
924  DevNullCodeDocInterface devNullIntf;
925  QCString title = m_docname;
926  if (!m_fileVersion.isEmpty())
927  {
928  title+=(" ("+m_fileVersion+")");
929  }
930  QCString pageTitle = theTranslator->trSourceFile(title);
932  if (!latexSourceCode) ol.disable(OutputGenerator::Latex);
933  if (!rtfSourceCode) ol.disable(OutputGenerator::RTF);
934 
935  bool isDocFile = isDocumentationFile();
936  bool genSourceFile = !isDocFile && generateSourceFile();
937  if (getDirDef())
938  {
940  !generateTreeView,
941  !isDocFile && genSourceFile ? QCString() : getOutputFileBase());
942  if (!generateTreeView)
943  {
945  ol.endQuickIndices();
946  }
948  ol.parseText(name());
949  endTitle(ol,getSourceFileBase(),title);
950  }
951  else
952  {
953  startFile(ol,getSourceFileBase(),0,pageTitle,HLI_FileVisible,FALSE,
954  !isDocFile && genSourceFile ? QCString() : getOutputFileBase());
956  ol.parseText(title);
957  endTitle(ol,getSourceFileBase(),0);
958  }
959 
960  ol.startContents();
961 
962  if (isLinkable())
963  {
964  if (latexSourceCode) ol.disable(OutputGenerator::Latex);
965  if (rtfSourceCode) ol.disable(OutputGenerator::RTF);
968  ol.endTextLink();
969  if (latexSourceCode) ol.enable(OutputGenerator::Latex);
970  if (rtfSourceCode) ol.enable(OutputGenerator::RTF);
971  }
972 
973  (void)sameTu;
974  (void)filesInSameTu;
975 #if USE_LIBCLANG
976  static bool clangAssistedParsing = Config_getBool(CLANG_ASSISTED_PARSING);
977  if (clangAssistedParsing &&
979  {
980  ol.startCodeFragment();
981  if (!sameTu)
982  {
983  ClangParser::instance()->start(absFilePath(),filesInSameTu);
984  }
985  else
986  {
988  }
990  ol.endCodeFragment();
991  }
992  else
993 #endif
994  {
996  pIntf->resetCodeParserState();
997  ol.startCodeFragment();
998  bool needs2PassParsing =
999  Doxygen::parseSourcesNeeded && // we need to parse (filtered) sources for cross-references
1000  !filterSourceFiles && // but user wants to show sources as-is
1001  !getFileFilter(absFilePath(),TRUE).isEmpty(); // and there is a filter used while parsing
1002 
1003  if (needs2PassParsing)
1004  {
1005  // parse code for cross-references only (see bug707641)
1006  pIntf->parseCode(devNullIntf,0,
1007  fileToString(absFilePath(),TRUE,TRUE),
1008  getLanguage(),
1009  FALSE,0,this
1010  );
1011  }
1012  pIntf->parseCode(ol,0,
1013  fileToString(absFilePath(),filterSourceFiles,TRUE),
1014  getLanguage(), // lang
1015  FALSE, // isExampleBlock
1016  0, // exampleName
1017  this, // fileDef
1018  -1, // startLine
1019  -1, // endLine
1020  FALSE, // inlineFragment
1021  0, // memberDef
1022  TRUE, // showLineNumbers
1023  0, // searchCtx
1024  !needs2PassParsing // collectXRefs
1025  );
1026  ol.endCodeFragment();
1027  }
1028  ol.endContents();
1029  endFileWithNavPath(this,ol);
1030  ol.enableAll();
1031 }
1032 
1033 void FileDef::parseSource(bool sameTu,QStrList &filesInSameTu)
1034 {
1035  static bool filterSourceFiles = Config_getBool(FILTER_SOURCE_FILES);
1036  DevNullCodeDocInterface devNullIntf;
1037  (void)sameTu;
1038  (void)filesInSameTu;
1039 #if USE_LIBCLANG
1040  static bool clangAssistedParsing = Config_getBool(CLANG_ASSISTED_PARSING);
1041  if (clangAssistedParsing &&
1043  {
1044  if (!sameTu)
1045  {
1046  ClangParser::instance()->start(absFilePath(),filesInSameTu);
1047  }
1048  else
1049  {
1051  }
1052  ClangParser::instance()->writeSources(devNullIntf,this);
1053  }
1054  else
1055 #endif
1056  {
1058  pIntf->resetCodeParserState();
1059  pIntf->parseCode(
1060  devNullIntf,0,
1061  fileToString(absFilePath(),filterSourceFiles,TRUE),
1062  getLanguage(),
1063  FALSE,0,this
1064  );
1065  }
1066 }
1067 
1069 {
1070 }
1071 
1073 {
1075 }
1076 
1078 {
1079  QListIterator<MemberList> mli(m_memberLists);
1080  MemberList *ml;
1081  for (mli.toFirst();(ml=mli.current());++mli)
1082  {
1084  {
1086  }
1087  }
1088 
1089  // add members inside sections to their groups
1090  if (m_memberGroupSDict)
1091  {
1093  MemberGroup *mg;
1094  for (;(mg=mgli.current());++mgli)
1095  {
1097  {
1098  //printf("----> addToDeclarationSection(%s)\n",mg->header().data());
1100  }
1101  }
1102  }
1103 }
1104 
1107 {
1108  if (md->isHidden()) return;
1109  //printf("%s:FileDef::insertMember(%s (=%p) list has %d elements)\n",
1110  // name().data(),md->name().data(),md,allMemberList.count());
1112  if (allMemberList && allMemberList->findRef(md)!=-1) // TODO optimize the findRef!
1113  {
1114  return;
1115  }
1116 
1117  if (allMemberList==0)
1118  {
1119  allMemberList = new MemberList(MemberListType_allMembersList);
1120  m_memberLists.append(allMemberList);
1121  }
1122  allMemberList->append(md);
1123  //::addFileMemberNameToIndex(md);
1124  switch (md->memberType())
1125  {
1126  case MemberType_Variable:
1127  case MemberType_Property:
1130  break;
1131  case MemberType_Function:
1134  break;
1135  case MemberType_Typedef:
1138  break;
1139  case MemberType_Enumeration:
1142  break;
1143  case MemberType_EnumValue: // enum values are shown inside their enums
1144  break;
1145  case MemberType_Define:
1148  break;
1149  default:
1150  err("FileDef::insertMembers(): "
1151  "member `%s' with class scope `%s' inserted in file scope `%s'!\n",
1152  md->name().data(),
1153  md->getClassDef() ? md->getClassDef()->name().data() : "<global>",
1154  name().data());
1155  }
1156  //addMemberToGroup(md,groupId);
1157 }
1158 
1161 {
1162  if (cd->isHidden()) return;
1163  if (m_classSDict==0)
1164  {
1165  m_classSDict = new ClassSDict(17);
1166  }
1167  if (Config_getBool(SORT_BRIEF_DOCS))
1168  {
1169  m_classSDict->inSort(cd->name(),cd);
1170  }
1171  else
1172  {
1173  m_classSDict->append(cd->name(),cd);
1174  }
1175 }
1176 
1179 {
1180  if (nd->isHidden()) return;
1181  if (!nd->name().isEmpty() &&
1182  (m_namespaceSDict==0 || m_namespaceSDict->find(nd->name())==0))
1183  {
1184  if (m_namespaceSDict==0)
1185  {
1187  }
1188  if (Config_getBool(SORT_BRIEF_DOCS))
1189  {
1190  m_namespaceSDict->inSort(nd->name(),nd);
1191  }
1192  else
1193  {
1194  m_namespaceSDict->append(nd->name(),nd);
1195  }
1196  }
1197 }
1198 
1199 QCString FileDef::name() const
1200 {
1201  if (Config_getBool(FULL_PATH_NAMES))
1202  return m_fileName;
1203  else
1204  return Definition::name();
1205 }
1206 
1208 {
1209  //printf("FileDef::addSourceDef(%d,%p,%p)\n",line,d,md);
1210  if (d)
1211  {
1212  if (m_srcDefDict==0) m_srcDefDict = new QIntDict<Definition>(257);
1213  if (m_srcMemberDict==0) m_srcMemberDict = new QIntDict<MemberDef>(257);
1214  m_srcDefDict->insert(line,d);
1215  if (md) m_srcMemberDict->insert(line,md);
1216  //printf("Adding member %s with anchor %s at line %d to file %s\n",
1217  // md?md->name().data():"<none>",md?md->anchor().data():"<none>",line,name().data());
1218  }
1219 }
1220 
1222 {
1223  Definition *result=0;
1224  if (m_srcDefDict)
1225  {
1226  result = m_srcDefDict->find(lineNr);
1227  }
1228  //printf("%s::getSourceDefinition(%d)=%s\n",name().data(),lineNr,result?result->name().data():"none");
1229  return result;
1230 }
1231 
1233 {
1234  MemberDef *result=0;
1235  if (m_srcMemberDict)
1236  {
1237  result = m_srcMemberDict->find(lineNr);
1238  }
1239  //printf("%s::getSourceMember(%d)=%s\n",name().data(),lineNr,result?result->name().data():"none");
1240  return result;
1241 }
1242 
1243 
1245 {
1246  if (m_usingDirList==0)
1247  {
1249  }
1250  if (m_usingDirList->find(nd->qualifiedName())==0)
1251  {
1252  m_usingDirList->append(nd->qualifiedName(),nd);
1253  }
1254  //printf("%p: FileDef::addUsingDirective: %s:%d\n",this,name().data(),usingDirList->count());
1255 }
1256 
1258 {
1259  //printf("%p: FileDef::getUsedNamespace: %s:%d\n",this,name().data(),usingDirList?usingDirList->count():0);
1260  return m_usingDirList;
1261 }
1262 
1264 {
1265  if (m_usingDeclList==0)
1266  {
1268  }
1269  if (m_usingDeclList->find(d->qualifiedName())==0)
1270  {
1272  }
1273 }
1274 
1275 void FileDef::addIncludeDependency(FileDef *fd,const char *incName,bool local,
1276  bool imported,bool indirect)
1277 {
1278  //printf("FileDef::addIncludeDependency(%p,%s,%d)\n",fd,incName,local);
1279  QCString iName = fd ? fd->absFilePath().data() : incName;
1280  if (!iName.isEmpty() && (!m_includeDict || m_includeDict->find(iName)==0))
1281  {
1282  if (m_includeDict==0)
1283  {
1284  m_includeDict = new QDict<IncludeInfo>(61);
1285  m_includeList = new QList<IncludeInfo>;
1286  m_includeList->setAutoDelete(TRUE);
1287  }
1288  IncludeInfo *ii = new IncludeInfo;
1289  ii->fileDef = fd;
1290  ii->includeName = incName;
1291  ii->local = local;
1292  ii->imported = imported;
1293  ii->indirect = indirect;
1294  m_includeList->append(ii);
1295  m_includeDict->insert(iName,ii);
1296  }
1297 }
1298 
1300 {
1301  if (visited) return;
1302  visited=TRUE;
1303  //printf("( FileDef::addIncludedUsingDirectives for file %s\n",name().data());
1304 
1305  if (m_includeList) // file contains #includes
1306  {
1307  {
1308  QListIterator<IncludeInfo> iii(*m_includeList);
1309  IncludeInfo *ii;
1310  for (iii.toFirst();(ii=iii.current());++iii) // foreach #include...
1311  {
1312  if (ii->fileDef && !ii->fileDef->visited) // ...that is a known file
1313  {
1314  // recurse into this file
1316  }
1317  }
1318  }
1319  {
1320  QListIterator<IncludeInfo> iii(*m_includeList);
1321  IncludeInfo *ii;
1322  // iterate through list from last to first
1323  for (iii.toLast();(ii=iii.current());--iii)
1324  {
1325  if (ii->fileDef && ii->fileDef!=this)
1326  {
1327  // add using directives
1329  if (unl)
1330  {
1331  NamespaceSDict::Iterator nli(*unl);
1332  NamespaceDef *nd;
1333  for (nli.toLast();(nd=nli.current());--nli)
1334  {
1335  // append each using directive found in a #include file
1337  //printf("Prepending used namespace %s to the list of file %s\n",
1338  // nd->name().data(),name().data());
1339  if (m_usingDirList->find(nd->qualifiedName())==0) // not yet added
1340  {
1342  }
1343  }
1344  }
1345  // add using declarations
1347  if (udl)
1348  {
1349  SDict<Definition>::Iterator udi(*udl);
1350  Definition *d;
1351  for (udi.toLast();(d=udi.current());--udi)
1352  {
1353  //printf("Adding using declaration %s\n",d->name().data());
1354  if (m_usingDeclList==0)
1355  {
1357  }
1358  if (m_usingDeclList->find(d->qualifiedName())==0)
1359  {
1361  }
1362  }
1363  }
1364  }
1365  }
1366  }
1367  }
1368  //printf(") end FileDef::addIncludedUsingDirectives for file %s\n",name().data());
1369 }
1370 
1371 
1372 void FileDef::addIncludedByDependency(FileDef *fd,const char *incName,
1373  bool local,bool imported)
1374 {
1375  //printf("FileDef::addIncludedByDependency(%p,%s,%d)\n",fd,incName,local);
1376  QCString iName = fd ? fd->absFilePath().data() : incName;
1377  if (!iName.isEmpty() && (m_includedByDict==0 || m_includedByDict->find(iName)==0))
1378  {
1379  if (m_includedByDict==0)
1380  {
1381  m_includedByDict = new QDict<IncludeInfo>(61);
1382  m_includedByList = new QList<IncludeInfo>;
1383  m_includedByList->setAutoDelete(TRUE);
1384  }
1385  IncludeInfo *ii = new IncludeInfo;
1386  ii->fileDef = fd;
1387  ii->includeName = incName;
1388  ii->local = local;
1389  ii->imported = imported;
1390  ii->indirect = FALSE;
1391  m_includedByList->append(ii);
1392  m_includedByDict->insert(iName,ii);
1393  }
1394 }
1395 
1396 bool FileDef::isIncluded(const QCString &name) const
1397 {
1398  if (name.isEmpty()) return FALSE;
1399  return m_includeDict!=0 && m_includeDict->find(name)!=0;
1400 }
1401 
1403 {
1404  static bool sourceBrowser = Config_getBool(SOURCE_BROWSER);
1405  static bool verbatimHeaders = Config_getBool(VERBATIM_HEADERS);
1406  QCString extension = name().right(4);
1407  return !isReference() &&
1408  (sourceBrowser ||
1409  (verbatimHeaders && guessSection(name())==Entry::HEADER_SEC)
1410  ) &&
1411  extension!=".doc" && extension!=".txt" && extension!=".dox" &&
1412  extension!=".md" && name().right(9)!=".markdown";
1413 }
1414 
1415 
1417 {
1418  {
1419  QList<ListItemInfo> *xrefItems = xrefListItems();
1420  addRefItem(xrefItems,
1422  theTranslator->trFile(TRUE,TRUE),
1423  getOutputFileBase(),name(),
1424  0,
1425  0
1426  );
1427  }
1428  if (m_memberGroupSDict)
1429  {
1431  MemberGroup *mg;
1432  for (;(mg=mgli.current());++mgli)
1433  {
1434  mg->addListReferences(this);
1435  }
1436  }
1437  QListIterator<MemberList> mli(m_memberLists);
1438  MemberList *ml;
1439  for (mli.toFirst();(ml=mli.current());++mli)
1440  {
1442  {
1443  ml->addListReferences(this);
1444  }
1445  }
1446 }
1447 
1448 //-------------------------------------------------------------------
1449 
1450 static int findMatchingPart(const QCString &path,const QCString dir)
1451 {
1452  int si1;
1453  int pos1=0,pos2=0;
1454  while ((si1=path.find('/',pos1))!=-1)
1455  {
1456  int si2=dir.find('/',pos2);
1457  //printf(" found slash at pos %d in path %d: %s<->%s\n",si1,si2,
1458  // path.mid(pos1,si1-pos2).data(),dir.mid(pos2).data());
1459  if (si2==-1 && path.mid(pos1,si1-pos2)==dir.mid(pos2)) // match at end
1460  {
1461  return dir.length();
1462  }
1463  if (si1!=si2 || path.mid(pos1,si1-pos2)!=dir.mid(pos2,si2-pos2)) // no match in middle
1464  {
1465  return QMAX(pos1-1,0);
1466  }
1467  pos1=si1+1;
1468  pos2=si2+1;
1469  }
1470  return 0;
1471 }
1472 
1473 static Directory *findDirNode(Directory *root,const QCString &name)
1474 {
1475  QListIterator<DirEntry> dli(root->children());
1476  DirEntry *de;
1477  for (dli.toFirst();(de=dli.current());++dli)
1478  {
1479  if (de->kind()==DirEntry::Dir)
1480  {
1481  Directory *dir = (Directory *)de;
1482  QCString dirName=dir->name();
1483  int sp=findMatchingPart(name,dirName);
1484  //printf("findMatchingPart(%s,%s)=%d\n",name.data(),dirName.data(),sp);
1485  if (sp>0) // match found
1486  {
1487  if ((uint)sp==dirName.length()) // whole directory matches
1488  {
1489  // recurse into the directory
1490  return findDirNode(dir,name.mid(dirName.length()+1));
1491  }
1492  else // partial match => we need to split the path into three parts
1493  {
1494  QCString baseName =dirName.left(sp);
1495  QCString oldBranchName=dirName.mid(sp+1);
1496  QCString newBranchName=name.mid(sp+1);
1497  // strip file name from path
1498  int newIndex=newBranchName.findRev('/');
1499  if (newIndex>0) newBranchName=newBranchName.left(newIndex);
1500 
1501  //printf("Splitting off part in new branch \n"
1502  // "base=%s old=%s new=%s\n",
1503  // baseName.data(),
1504  // oldBranchName.data(),
1505  // newBranchName.data()
1506  // );
1507  Directory *base = new Directory(root,baseName);
1508  Directory *newBranch = new Directory(base,newBranchName);
1509  dir->reParent(base);
1510  dir->rename(oldBranchName);
1511  base->addChild(dir);
1512  base->addChild(newBranch);
1513  dir->setLast(FALSE);
1514  // remove DirEntry container from list (without deleting it)
1515  root->children().setAutoDelete(FALSE);
1516  root->children().removeRef(dir);
1517  root->children().setAutoDelete(TRUE);
1518  // add new branch to the root
1519  if (!root->children().isEmpty())
1520  {
1521  root->children().getLast()->setLast(FALSE);
1522  }
1523  root->addChild(base);
1524  return newBranch;
1525  }
1526  }
1527  }
1528  }
1529  int si=name.findRev('/');
1530  if (si==-1) // no subdir
1531  {
1532  return root; // put the file under the root node.
1533  }
1534  else // need to create a subdir
1535  {
1536  QCString baseName = name.left(si);
1537  //printf("new subdir %s\n",baseName.data());
1538  Directory *newBranch = new Directory(root,baseName);
1539  if (!root->children().isEmpty())
1540  {
1541  root->children().getLast()->setLast(FALSE);
1542  }
1543  root->addChild(newBranch);
1544  return newBranch;
1545  }
1546 }
1547 
1548 static void mergeFileDef(Directory *root,FileDef *fd)
1549 {
1550  QCString filePath = fd->absFilePath();
1551  //printf("merging %s\n",filePath.data());
1552  Directory *dirNode = findDirNode(root,filePath);
1553  if (!dirNode->children().isEmpty())
1554  {
1555  dirNode->children().getLast()->setLast(FALSE);
1556  }
1557  DirEntry *e=new DirEntry(dirNode,fd);
1558  dirNode->addChild(e);
1559 }
1560 
1561 #if 0
1562 static void generateIndent(QTextStream &t,DirEntry *de,int level)
1563 {
1564  if (de->parent())
1565  {
1566  generateIndent(t,de->parent(),level+1);
1567  }
1568  // from the root up to node n do...
1569  if (level==0) // item before a dir or document
1570  {
1571  if (de->isLast())
1572  {
1573  if (de->kind()==DirEntry::Dir)
1574  {
1575  t << "<img " << FTV_IMGATTRIBS(plastnode) << "/>";
1576  }
1577  else
1578  {
1579  t << "<img " << FTV_IMGATTRIBS(lastnode) << "/>";
1580  }
1581  }
1582  else
1583  {
1584  if (de->kind()==DirEntry::Dir)
1585  {
1586  t << "<img " << FTV_IMGATTRIBS(pnode) << "/>";
1587  }
1588  else
1589  {
1590  t << "<img " << FTV_IMGATTRIBS(node) << "/>";
1591  }
1592  }
1593  }
1594  else // item at another level
1595  {
1596  if (de->isLast())
1597  {
1598  t << "<img " << FTV_IMGATTRIBS(blank) << "/>";
1599  }
1600  else
1601  {
1602  t << "<img " << FTV_IMGATTRIBS(vertline) << "/>";
1603  }
1604  }
1605 }
1606 
1607 static void writeDirTreeNode(QTextStream &t,Directory *root,int level)
1608 {
1609  QCString indent;
1610  indent.fill(' ',level*2);
1611  QListIterator<DirEntry> dli(root->children());
1612  DirEntry *de;
1613  for (dli.toFirst();(de=dli.current());++dli)
1614  {
1615  t << indent << "<p>";
1616  generateIndent(t,de,0);
1617  if (de->kind()==DirEntry::Dir)
1618  {
1619  Directory *dir=(Directory *)de;
1620  //printf("%s [dir]: %s (last=%d,dir=%d)\n",indent.data(),dir->name().data(),dir->isLast(),dir->kind()==DirEntry::Dir);
1621  t << "<img " << FTV_IMGATTRIBS(folderclosed) << "/>";
1622  t << dir->name();
1623  t << "</p>\n";
1624  t << indent << "<div>\n";
1625  writeDirTreeNode(t,dir,level+1);
1626  t << indent << "</div>\n";
1627  }
1628  else
1629  {
1630  //printf("%s [file]: %s (last=%d,dir=%d)\n",indent.data(),de->file()->name().data(),de->isLast(),de->kind()==DirEntry::Dir);
1631  t << "<img " << FTV_IMGATTRIBS(doc) << "/>";
1632  t << de->file()->name();
1633  t << "</p>\n";
1634  }
1635  }
1636 }
1637 #endif
1638 
1639 static void addDirsAsGroups(Directory *root,GroupDef *parent,int level)
1640 {
1641  GroupDef *gd=0;
1642  if (root->kind()==DirEntry::Dir)
1643  {
1644  gd = new GroupDef("[generated]",
1645  1,
1646  root->path(), // name
1647  root->name() // title
1648  );
1649  if (parent)
1650  {
1651  parent->addGroup(gd);
1652  gd->makePartOfGroup(parent);
1653  }
1654  else
1655  {
1656  Doxygen::groupSDict->append(root->path(),gd);
1657  }
1658  }
1659  QListIterator<DirEntry> dli(root->children());
1660  DirEntry *de;
1661  for (dli.toFirst();(de=dli.current());++dli)
1662  {
1663  if (de->kind()==DirEntry::Dir)
1664  {
1665  addDirsAsGroups((Directory *)de,gd,level+1);
1666  }
1667  }
1668 }
1669 
1671 {
1672  Directory *root=new Directory(0,"root");
1673  root->setLast(TRUE);
1675  FileName *fn;
1676  for (fnli.toFirst();(fn=fnli.current());++fnli)
1677  {
1678  FileNameIterator fni(*fn);
1679  FileDef *fd;
1680  for (;(fd=fni.current());++fni)
1681  {
1682  mergeFileDef(root,fd);
1683  }
1684  }
1685  //t << "<div class=\"directory\">\n";
1686  //writeDirTreeNode(t,root,0);
1687  //t << "</div>\n";
1688  addDirsAsGroups(root,0,0);
1689  delete root;
1690 }
1691 
1692 //-------------------------------------------------------------------
1693 
1695 {
1696  if (visited) return; // already done
1697  visited=TRUE;
1698  if (m_usingDirList)
1699  {
1701  NamespaceDef *nd;
1702  for (nli.toFirst();(nd=nli.current());++nli)
1703  {
1704  nd->combineUsingRelations();
1705  }
1706  for (nli.toFirst();(nd=nli.current());++nli)
1707  {
1708  // add used namespaces of namespace nd to this namespace
1709  if (nd->getUsedNamespaces())
1710  {
1712  NamespaceDef *und;
1713  for (unli.toFirst();(und=unli.current());++unli)
1714  {
1715  //printf("Adding namespace %s to the using list of %s\n",und->qualifiedName().data(),qualifiedName().data());
1716  addUsingDirective(und);
1717  }
1718  }
1719  // add used classes of namespace nd to this namespace
1720  if (nd->getUsedClasses())
1721  {
1723  Definition *ucd;
1724  for (cli.toFirst();(ucd=cli.current());++cli)
1725  {
1726  //printf("Adding class %s to the using list of %s\n",cd->qualifiedName().data(),qualifiedName().data());
1727  addUsingDeclaration(ucd);
1728  }
1729  }
1730  }
1731  }
1732 }
1733 
1735 {
1736  return name().right(4)==".doc" ||
1737  name().right(4)==".txt" ||
1738  name().right(4)==".dox" ||
1739  name().right(3)==".md" ||
1740  name().right(9)==".markdown";
1741 }
1742 
1744 {
1745  QCString vercmd = Config_getString(FILE_VERSION_FILTER);
1746  if (!vercmd.isEmpty() && !m_filePath.isEmpty() &&
1747  m_filePath!="generated" && m_filePath!="graph_legend")
1748  {
1749  msg("Version of %s : ",m_filePath.data());
1750  QCString cmd = vercmd+" \""+m_filePath+"\"";
1751  Debug::print(Debug::ExtCmd,0,"Executing popen(`%s`)\n",qPrint(cmd));
1752  FILE *f=portable_popen(cmd,"r");
1753  if (!f)
1754  {
1755  err("could not execute %s\n",vercmd.data());
1756  return;
1757  }
1758  const int bufSize=1024;
1759  char buf[bufSize];
1760  int numRead = (int)fread(buf,1,bufSize-1,f);
1761  portable_pclose(f);
1762  if (numRead>0 && numRead<bufSize)
1763  {
1764  buf[numRead]='\0';
1765  m_fileVersion=QCString(buf,numRead).stripWhiteSpace();
1766  if (!m_fileVersion.isEmpty())
1767  {
1768  msg("%s\n",m_fileVersion.data());
1769  return;
1770  }
1771  }
1772  msg("no version available\n");
1773  }
1774 }
1775 
1776 
1778 {
1779  if (Htags::useHtags)
1780  {
1781  return Htags::path2URL(m_filePath);
1782  }
1783  else
1784  {
1785  return m_outputDiskName+"_source";
1786  }
1787 }
1788 
1790 {
1791  return m_outputDiskName;
1792 }
1793 
1795 QCString FileDef::includeName() const
1796 {
1797  return getSourceFileBase();
1798 }
1799 
1801 {
1802  m_memberLists.setAutoDelete(TRUE);
1803  QListIterator<MemberList> mli(m_memberLists);
1804  MemberList *ml;
1805  for (mli.toFirst();(ml=mli.current());++mli)
1806  {
1807  if (ml->listType()==lt)
1808  {
1809  return ml;
1810  }
1811  }
1812  // not found, create a new member list
1813  ml = new MemberList(lt);
1814  m_memberLists.append(ml);
1815  return ml;
1816 }
1817 
1819 {
1820  static bool sortBriefDocs = Config_getBool(SORT_BRIEF_DOCS);
1821  static bool sortMemberDocs = Config_getBool(SORT_MEMBER_DOCS);
1822  MemberList *ml = createMemberList(lt);
1823  ml->setNeedsSorting(
1824  ((ml->listType()&MemberListType_declarationLists) && sortBriefDocs) ||
1825  ((ml->listType()&MemberListType_documentationLists) && sortMemberDocs));
1826  ml->append(md);
1827 #if 0
1828  if (ml->needsSorting())
1829  ml->inSort(md);
1830  else
1831  ml->append(md);
1832 #endif
1834  {
1835  ml->setInFile(TRUE);
1836  }
1838 }
1839 
1841 {
1842  QListIterator<MemberList> mli(m_memberLists);
1843  MemberList *ml;
1844  for (;(ml=mli.current());++mli)
1845  {
1846  if (ml->needsSorting()) { ml->sort(); ml->setNeedsSorting(FALSE); }
1847  }
1848 }
1849 
1851 {
1852  QListIterator<MemberList> mli(m_memberLists);
1853  MemberList *ml;
1854  for (;(ml=mli.current());++mli)
1855  {
1856  if (ml->listType()==lt)
1857  {
1858  return ml;
1859  }
1860  }
1861  return 0;
1862 }
1863 
1865 {
1866  static bool optVhdl = Config_getBool(OPTIMIZE_OUTPUT_VHDL);
1867  MemberList * ml = getMemberList(lt);
1868  if (ml)
1869  {
1870  if (optVhdl) // use specific declarations function
1871  {
1872 
1873  VhdlDocGen::writeVhdlDeclarations(ml,ol,0,0,this,0);
1874  }
1875  else
1876  {
1877  ml->writeDeclarations(ol,0,0,this,0,title,0);
1878  }
1879  }
1880 }
1881 
1883 {
1884  MemberList * ml = getMemberList(lt);
1885  if (ml) ml->writeDocumentation(ol,name(),this,title);
1886 }
1887 
1889 {
1890  static bool showFiles = Config_getBool(SHOW_FILES);
1891  return hasDocumentation() && !isReference() && (showFiles || isLinkableViaGroup());
1892 }
1893 
1895  QDict<void> *filesVisited,const FileDef *fd,QStrList &incFiles)
1896 {
1897  if (fd->includeFileList())
1898  {
1899  QListIterator<IncludeInfo> iii(*fd->includeFileList());
1900  IncludeInfo *ii;
1901  for (iii.toFirst();(ii=iii.current());++iii)
1902  {
1903  if (ii->fileDef && !ii->fileDef->isReference() &&
1904  !filesVisited->find(ii->fileDef->absFilePath()))
1905  {
1906  //printf("FileDef::addIncludeDependency(%s)\n",ii->fileDef->absFilePath().data());
1907  incFiles.append(ii->fileDef->absFilePath());
1908  filesVisited->insert(ii->fileDef->absFilePath(),(void*)0x8);
1909  getAllIncludeFilesRecursively(filesVisited,ii->fileDef,incFiles);
1910  }
1911  }
1912  }
1913 }
1914 
1915 void FileDef::getAllIncludeFilesRecursively(QStrList &incFiles) const
1916 {
1917  QDict<void> includes(257);
1918  ::getAllIncludeFilesRecursively(&includes,this,incFiles);
1919 }
1920 
1921 QCString FileDef::title() const
1922 {
1923  return theTranslator->trFileReference(name());
1924 }
1925 
1926 QCString FileDef::fileVersion() const
1927 {
1928  return m_fileVersion;
1929 }
1930 
1932 {
1933  return m_inclDepFileName;
1934 }
1935 
1937 {
1938  return m_inclByDepFileName;
1939 }
1940