Doxygen
Loading...
Searching...
No Matches
dirdef.cpp
Go to the documentation of this file.
1/******************************************************************************
2 *
3 * Copyright (C) 1997-2020 by Dimitri van Heesch.
4 *
5 * Permission to use, copy, modify, and distribute this software and its
6 * documentation under the terms of the GNU General Public License is hereby
7 * granted. No representations are made about the suitability of this software
8 * for any purpose. It is provided "as is" without express or implied warranty.
9 * See the GNU General Public License for more details.
10 *
11 * Documents produced by Doxygen are derivative works derived from the
12 * input used in their production; they are not affected by this license.
13 *
14 */
15
16#include <algorithm>
17
18#include "dirdef.h"
19#include "md5.h"
20#include "filename.h"
21#include "doxygen.h"
22#include "util.h"
23#include "outputlist.h"
24#include "language.h"
25#include "message.h"
26#include "dot.h"
27#include "dotdirdeps.h"
28#include "layout.h"
29#include "config.h"
30#include "docparser.h"
31#include "definitionimpl.h"
32#include "filedef.h"
33#include "trace.h"
34
35//----------------------------------------------------------------------
36
37class DirDefImpl : public DefinitionMixin<DirDef>
38{
39 public:
40 DirDefImpl(const QCString &path);
41 ~DirDefImpl() override;
43
44 DefType definitionType() const override { return TypeDir; }
46 QCString getOutputFileBase() const override;
47 QCString anchor() const override { return QCString(); }
48 bool isLinkableInProject() const override;
49 bool isLinkable() const override;
50 QCString displayName(bool=TRUE) const override { return m_dispName; }
51 const QCString shortName() const override { return m_shortName; }
52 void addSubDir(DirDef *subdir) override;
53 const FileList &getFiles() const override { return m_fileList; }
54 void addFile(FileDef *fd) override;
55 const DirList &subDirs() const override { return m_subdirs; }
56 bool hasSubdirs() const override { return !m_subdirs.empty(); }
57 int level() const override { return m_level; }
58 DirDef *parent() const override { return m_parent; }
59 int dirIndex() const override { return m_dirIndex; }
60 const UsedDirLinkedMap &usedDirs() const override { return m_usedDirs; }
61 bool isParentOf(const DirDef *dir) const override;
62 bool depGraphIsTrivial() const override;
63 QCString shortTitle() const override;
64 bool hasDetailedDescription() const override;
65 void writeDocumentation(OutputList &ol) override;
66 void writeTagFile(TextStream &t) override;
67 void setDiskName(const QCString &name) override { m_diskName = name; }
68 void sort() override;
69 void setParent(DirDef *parent) override;
70 void setDirIndex(int index) override;
71 void setLevel() override;
72 void addUsesDependency(const DirDef *usedDir,const FileDef *srcFd,
73 const FileDef *dstFd,bool srcDirect, bool dstDirect) override;
74 void computeDependencies() override;
75
76 bool hasDirectoryGraph() const override;
77 void overrideDirectoryGraph(bool e) override;
78
79 public:
80 static DirDef *mergeDirectoryInTree(const QCString &path);
81
82 private:
83
84 void writeDetailedDescription(OutputList &ol,const QCString &title);
85 void writeBriefDescription(OutputList &ol);
86 void writeDirectoryGraph(OutputList &ol);
87 void writeSubDirList(OutputList &ol);
88 void writeFileList(OutputList &ol);
89 void startMemberDeclarations(OutputList &ol);
90 void endMemberDeclarations(OutputList &ol);
91
92 static DirDef *createNewDir(const QCString &path);
93 static bool matchPath(const QCString &path,const StringVector &l);
94
95 DirList m_subdirs;
96 QCString m_dispName;
97 QCString m_shortName;
98 QCString m_diskName;
99 FileList m_fileList; // list of files in the group
100 int m_dirIndex = -1;
102 DirDef *m_parent;
105};
106
108{
109 return new DirDefImpl(path);
110}
111
112
113//----------------------------------------------------------------------
114// method implementation
115
117{
118 bool fullPathNames = Config_getBool(FULL_PATH_NAMES);
119 // get display name (stripping the paths mentioned in STRIP_FROM_PATH)
120 // get short name (last part of path)
121 m_shortName = path;
122 m_diskName = path;
123 if (m_shortName.at(m_shortName.length()-1)=='/')
124 { // strip trailing /
125 m_shortName = m_shortName.left(m_shortName.length()-1);
126 }
127 int pi=m_shortName.findRev('/');
128 if (pi!=-1)
129 { // remove everything till the last /
130 m_shortName = m_shortName.mid(pi+1);
131 }
133 m_dispName = fullPathNames ? stripFromPath(path) : m_shortName;
134 if (m_dispName.length()>0 && m_dispName.at(m_dispName.length()-1)=='/')
135 { // strip trailing /
136 m_dispName = m_dispName.left(m_dispName.length()-1);
137 }
138
139 m_level=-1;
140 m_parent=nullptr;
141 m_hasDirectoryGraph=Config_getBool(DIRECTORY_GRAPH);
142
143}
144
148
150{
151 return !isReference();
152}
153
155{
156 return isReference() || isLinkableInProject();
157}
158
160{
161 m_subdirs.push_back(subdir);
162 subdir->setOuterScope(this);
163 subdir->setParent(this);
164}
165
167{
168 m_parent=p;
169}
170
172{
173 m_dirIndex=index;
174}
175
177{
178 m_fileList.push_back(fd);
179 fd->setDirDef(this);
180}
181
183{
184 std::stable_sort(m_subdirs.begin(), m_subdirs.end(), compareDirDefs);
185 std::stable_sort(m_fileList.begin(), m_fileList.end(), compareFileDefs);
186}
187
188static QCString encodeDirName(const QCString &anchor)
189{
190 AUTO_TRACE();
191 // convert to md5 hash
192 uint8_t md5_sig[16];
193 char sigStr[33];
194 MD5Buffer(anchor.data(),static_cast<unsigned int>(anchor.length()),md5_sig);
195 MD5SigToString(md5_sig,sigStr);
196 AUTO_TRACE_EXIT("result={}",sigStr);
197 return sigStr;
198
199 // old algorithm
200// QCString result;
201
202// int l = anchor.length(),i;
203// for (i=0;i<l;i++)
204// {
205// char c = anchor.at(i);
206// if ((c>='a' && c<='z') || (c>='A' && c<='Z') || (c>='0' && c<='9'))
207// {
208// result+=c;
209// }
210// else
211// {
212// static char hexStr[]="0123456789ABCDEF";
213// char escChar[]={ '_', 0, 0, 0 };
214// escChar[1]=hexStr[c>>4];
215// escChar[2]=hexStr[c&0xf];
216// result+=escChar;
217// }
218// }
219// return result;
220}
221
223{
224 QCString dir = "dir_"+encodeDirName(m_diskName);
225 AUTO_TRACE("diskName={} result={}",m_diskName,dir);
226 return dir;
227}
228
230{
231 AUTO_TRACE();
232 if ((!briefDescription().isEmpty() && Config_getBool(REPEAT_BRIEF)) ||
233 !documentation().isEmpty())
234 {
237 ol.writeRuler();
241 ol.writeAnchor(QCString(),"details");
243 ol.startGroupHeader();
244 ol.parseText(title);
245 ol.endGroupHeader();
246
247 // repeat brief description
248 if (!briefDescription().isEmpty() && Config_getBool(REPEAT_BRIEF))
249 {
251 QCString(),FALSE,FALSE,Config_getBool(MARKDOWN_SUPPORT));
252 }
253 // separator between brief and details
254 if (!briefDescription().isEmpty() && Config_getBool(REPEAT_BRIEF) &&
255 !documentation().isEmpty())
256 {
260 ol.enableAll();
263 ol.writeString("\n\n");
265 }
266
267 // write documentation
268 if (!documentation().isEmpty())
269 {
270 ol.generateDoc(docFile(),docLine(),this,nullptr,documentation()+"\n",TRUE,FALSE,
271 QCString(),FALSE,FALSE,Config_getBool(MARKDOWN_SUPPORT));
272 }
273 }
274}
275
277{
278 AUTO_TRACE();
280 {
281 auto parser { createDocParser() };
282 auto ast { validatingParseDoc(
283 *parser.get(), briefFile(),briefLine(),this,nullptr,briefDescription(),TRUE,FALSE,
284 QCString(),FALSE,FALSE,Config_getBool(MARKDOWN_SUPPORT)) };
285 if (!ast->isEmpty())
286 {
287 ol.startParagraph();
290 ol.writeString(" - ");
292 ol.writeDoc(ast.get(),this,nullptr);
295 ol.writeString(" \n");
297
298 if (Config_getBool(REPEAT_BRIEF) ||
299 !documentation().isEmpty()
300 )
301 {
303 ol.startTextLink(QCString(),"details");
305 ol.endTextLink();
306 }
308
309 ol.endParagraph();
310 }
311 }
312 ol.writeSynopsis();
313}
314
316{
317 // write graph dependency graph
318 if (Config_getBool(HAVE_DOT) && m_hasDirectoryGraph /*&& Config_getBool(DIRECTORY_GRAPH)*/)
319 {
320 DotDirDeps dirDep(this);
321 if (!dirDep.isTrivial())
322 {
323 msg("Generating dependency graph for directory %s\n",qPrint(displayName()));
325 //ol.startParagraph();
326 ol.startDirDepGraph();
328 ol.endDirDepGraph(dirDep);
329 //ol.endParagraph();
330 ol.enableAll();
331 }
332 }
333}
334
336{
337 AUTO_TRACE();
338 int numSubdirs = 0;
339 for(const auto dd : m_subdirs)
340 {
341 if (dd->hasDocumentation() || !dd->getFiles().empty())
342 {
343 numSubdirs++;
344 }
345 }
346
347 AUTO_TRACE_ADD("numSubdirs={}",numSubdirs);
348 // write subdir list
349 if (numSubdirs>0)
350 {
351 ol.startMemberHeader("subdirs");
353 ol.endMemberHeader();
354 ol.startMemberList();
355 for(const auto dd : m_subdirs)
356 {
357 if (dd->hasDocumentation() || !dd->getFiles().empty())
358 {
361 {
364 ol.writeString("<span class=\"iconfclosed\"></span>");
365 ol.enableAll();
369 }
371 ol.writeObjectLink(dd->getReference(),dd->getOutputFileBase(),QCString(),dd->shortName());
373 if (!dd->briefDescription().isEmpty() && Config_getBool(BRIEF_MEMBER_DESC))
374 {
375 ol.startMemberDescription(dd->getOutputFileBase());
376 ol.generateDoc(briefFile(),briefLine(),dd,nullptr,dd->briefDescription(),
377 FALSE, // indexWords
378 FALSE, // isExample
379 QCString(), // exampleName
380 TRUE, // single line
381 TRUE, // link from index
382 Config_getBool(MARKDOWN_SUPPORT)
383 );
385 }
386 ol.endMemberDeclaration(dd->anchor(),QCString());
387 }
388 }
389
390 ol.endMemberList();
391 }
392}
393
395{
396 AUTO_TRACE();
397 int numFiles = 0;
398 for (const auto &fd : m_fileList)
399 {
400 bool genSourceFile=false;
401 if (fileVisibleInIndex(fd,genSourceFile))
402 {
403 numFiles++;
404 }
405 else if (genSourceFile)
406 {
407 numFiles++;
408 }
409 }
410
411 AUTO_TRACE_ADD("numFiles={}",numFiles);
412 // write file list
413 if (numFiles>0)
414 {
415 ol.startMemberHeader("files");
417 ol.endMemberHeader();
418 ol.startMemberList();
419 for (const auto &fd : m_fileList)
420 {
421 bool src = false;
422 bool doc = fileVisibleInIndex(fd,src);
423 if (doc || src)
424 {
427 {
430 bool genSrc = fd->generateSourceFile();
431 if (genSrc)
432 {
433 ol.startTextLink(fd->includeName(),QCString());
434 }
435 ol.writeString("<span class=\"icondoc\"></span>");
436 if (genSrc)
437 {
438 ol.endTextLink();
439 }
440 ol.enableAll();
444 }
446 if (fd->isLinkable())
447 {
448 ol.writeObjectLink(fd->getReference(),fd->getOutputFileBase(),QCString(),fd->displayName());
449 }
450 else
451 {
452 ol.startBold();
453 ol.docify(fd->displayName());
454 ol.endBold();
455 }
457 if (!fd->briefDescription().isEmpty() && Config_getBool(BRIEF_MEMBER_DESC))
458 {
459 ol.startMemberDescription(fd->getOutputFileBase());
460 ol.generateDoc(briefFile(),briefLine(),fd,nullptr,fd->briefDescription(),
461 FALSE, // indexWords
462 FALSE, // isExample
463 QCString(), // exampleName
464 TRUE, // single line
465 TRUE, // link from index
466 Config_getBool(MARKDOWN_SUPPORT)
467 );
469 }
470 ol.endMemberDeclaration(fd->anchor(),QCString());
471 }
472 }
473 ol.endMemberList();
474 }
475}
476
481
486
491
493{
494 bool repeatBrief = Config_getBool(REPEAT_BRIEF);
495 return (!briefDescription().isEmpty() && repeatBrief) || !documentation().isEmpty();
496}
497
499{
500 tagFile << " <compound kind=\"dir\">\n";
501 tagFile << " <name>" << convertToXML(displayName()) << "</name>\n";
502 tagFile << " <path>" << convertToXML(stripFromPath(name())) << "</path>\n";
503 QCString fn=getOutputFileBase();
505 tagFile << " <filename>" << fn << "</filename>\n";
506 for (const auto &lde : LayoutDocManager::instance().docEntries(LayoutDocManager::Directory))
507 {
508 switch (lde->kind())
509 {
510 case LayoutDocEntry::DirSubDirs:
511 {
512 if (m_subdirs.size()>0)
513 {
514 for(const auto dd : m_subdirs)
515 {
516 tagFile << " <dir>" << convertToXML(dd->displayName()) << "</dir>\n";
517 }
518 }
519 }
520 break;
521 case LayoutDocEntry::DirFiles:
522 {
523 for (const auto &fd : m_fileList)
524 {
525 tagFile << " <file>" << convertToXML(fd->name()) << "</file>\n";
526 }
527 }
528 break;
529 default:
530 break;
531 }
532 }
534 tagFile << " </compound>\n";
535}
536
538{
539 bool generateTreeView = Config_getBool(GENERATE_TREEVIEW);
541
542 QCString title=theTranslator->trDirReference(m_dispName);
543 AUTO_TRACE("title={}",title);
544 startFile(ol,getOutputFileBase(),name(),title,HighlightedItem::Files,!generateTreeView);
545
546 if (!generateTreeView)
547 {
548 // write navigation path
550 ol.endQuickIndices();
551 }
552
556 ol.parseText(shortTitle());
557 ol.enableAll();
559 ol.parseText(title);
561 endTitle(ol,getOutputFileBase(),title);
562 ol.startContents();
563
564 //---------------------------------------- start flexible part -------------------------------
565
566 SrcLangExt lang = getLanguage();
567 for (const auto &lde : LayoutDocManager::instance().docEntries(LayoutDocManager::Directory))
568 {
569 switch (lde->kind())
570 {
571 case LayoutDocEntry::BriefDesc:
573 break;
574 case LayoutDocEntry::DirGraph:
576 break;
577 case LayoutDocEntry::MemberDeclStart:
579 break;
580 case LayoutDocEntry::DirSubDirs:
581 writeSubDirList(ol);
582 break;
583 case LayoutDocEntry::DirFiles:
584 writeFileList(ol);
585 break;
586 case LayoutDocEntry::MemberDeclEnd:
588 break;
589 case LayoutDocEntry::DetailedDesc:
590 {
591 const LayoutDocEntrySection *ls = dynamic_cast<const LayoutDocEntrySection*>(lde.get());
592 if (ls)
593 {
594 writeDetailedDescription(ol,ls->title(lang));
595 }
596 }
597 break;
598 case LayoutDocEntry::ClassIncludes:
599 case LayoutDocEntry::ClassInlineClasses:
600 case LayoutDocEntry::ClassInheritanceGraph:
601 case LayoutDocEntry::ClassNestedClasses:
602 case LayoutDocEntry::ClassCollaborationGraph:
603 case LayoutDocEntry::ClassAllMembersLink:
604 case LayoutDocEntry::ClassUsedFiles:
605 case LayoutDocEntry::NamespaceNestedNamespaces:
606 case LayoutDocEntry::NamespaceNestedConstantGroups:
607 case LayoutDocEntry::NamespaceClasses:
608 case LayoutDocEntry::NamespaceConcepts:
609 case LayoutDocEntry::NamespaceInterfaces:
610 case LayoutDocEntry::NamespaceStructs:
611 case LayoutDocEntry::NamespaceExceptions:
612 case LayoutDocEntry::NamespaceInlineClasses:
613 case LayoutDocEntry::ConceptDefinition:
614 case LayoutDocEntry::FileClasses:
615 case LayoutDocEntry::FileConcepts:
616 case LayoutDocEntry::FileInterfaces:
617 case LayoutDocEntry::FileStructs:
618 case LayoutDocEntry::FileExceptions:
619 case LayoutDocEntry::FileNamespaces:
620 case LayoutDocEntry::FileConstantGroups:
621 case LayoutDocEntry::FileIncludes:
622 case LayoutDocEntry::FileIncludeGraph:
623 case LayoutDocEntry::FileIncludedByGraph:
624 case LayoutDocEntry::FileSourceLink:
625 case LayoutDocEntry::FileInlineClasses:
626 case LayoutDocEntry::GroupClasses:
627 case LayoutDocEntry::GroupConcepts:
628 case LayoutDocEntry::GroupModules:
629 case LayoutDocEntry::GroupInlineClasses:
630 case LayoutDocEntry::GroupNamespaces:
631 case LayoutDocEntry::GroupDirs:
632 case LayoutDocEntry::GroupNestedGroups:
633 case LayoutDocEntry::GroupFiles:
634 case LayoutDocEntry::GroupGraph:
635 case LayoutDocEntry::GroupPageDocs:
636 case LayoutDocEntry::ModuleExports:
637 case LayoutDocEntry::ModuleClasses:
638 case LayoutDocEntry::ModuleConcepts:
639 case LayoutDocEntry::ModuleUsedFiles:
640 case LayoutDocEntry::AuthorSection:
641 case LayoutDocEntry::MemberGroups:
642 case LayoutDocEntry::MemberDecl:
643 case LayoutDocEntry::MemberDef:
644 case LayoutDocEntry::MemberDefStart:
645 case LayoutDocEntry::MemberDefEnd:
646 err("Internal inconsistency: member %d should not be part of "
647 "LayoutDocManager::Directory entry list\n",lde->kind());
648 break;
649 }
650 }
651
652 //---------------------------------------- end flexible part -------------------------------
653
654 ol.endContents();
655
656 endFileWithNavPath(ol,this);
657
659}
660
662{
663 if (m_level==-1) // level not set before
664 {
665 DirDef *p = parent();
666 if (p)
667 {
668 p->setLevel();
669 m_level = p->level()+1;
670 }
671 else
672 {
673 m_level = 0;
674 }
675 }
676}
677
678/** Add as "uses" dependency between \a this dir and \a dir,
679 * that was caused by a dependency on file \a fd.
680 * srcDirect and dstDirect indicate if it is a direct dependencies (true) or if
681 * the dependencies was indirect (e.g. a parent dir that has a child dir that has the dependencies)
682 */
683void DirDefImpl::addUsesDependency(const DirDef *dir,const FileDef *srcFd,
684 const FileDef *dstFd,bool srcDirect, bool dstDirect)
685{
686 if (this==dir) return; // do not add self-dependencies
687 AUTO_TRACE("add dependency {}->{} due to {}->{}",
688 qPrint(shortName()),
689 qPrint(dir->shortName()),
690 qPrint(srcFd->name()),
691 qPrint(dstFd->name()));
692
693 // levels match => add direct dependency
694 bool added=FALSE;
695 UsedDir *usedDir = m_usedDirs.find(dir->getOutputFileBase());
696 if (usedDir) // dir dependency already present
697 {
698 const FilePair *usedPair = usedDir->findFilePair(FilePair::key(srcFd,dstFd));
699 if (usedPair==nullptr) // new file dependency
700 {
701 AUTO_TRACE_ADD("{} => {} new file dependency",srcFd->name(),dstFd->name());
702 usedDir->addFileDep(srcFd,dstFd, srcDirect, dstDirect);
703 added=TRUE;
704 }
705 else
706 {
707 // dir & file dependency already added
708 }
709 }
710 else // new directory dependency
711 {
712 AUTO_TRACE_ADD("{} => {} new file dependency",srcFd->name(),dstFd->name());
713 auto newUsedDir = std::make_unique<UsedDir>(dir);
714 newUsedDir->addFileDep(srcFd,dstFd, srcDirect, dstDirect);
715 m_usedDirs.add(dir->getOutputFileBase(),std::move(newUsedDir));
716 added=TRUE;
717 }
718 if (added)
719 {
720 if (dir->parent())
721 {
722 // add relation to parent of used dir
724 srcFd,
725 dstFd,
726 srcDirect,
727 false); // indirect dependency on dest dir
728 }
729 if (parent())
730 {
731 // add relation for the parent of this dir as well
733 srcFd,
734 dstFd,
735 false, // indirect dependency from source dir
736 dstDirect);
737 }
738 }
739}
740
741/** Computes the dependencies between directories
742 */
744{
745 AUTO_TRACE();
746 for (const auto &fd : m_fileList)
747 {
748 AUTO_TRACE_ADD("dir={} file={}",shortName(),fd->name());
749 for (const auto &ii : fd->includeFileList())
750 {
751 AUTO_TRACE_ADD("#include {}",ii.includeName);
752 if (ii.fileDef && ii.fileDef->isLinkable()) // linkable file
753 {
754 DirDef *usedDir = ii.fileDef->getDirDef();
755 if (usedDir)
756 {
757 // add dependency: thisDir->usedDir
758 AUTO_TRACE_ADD("add dependency {}->{}",name(),usedDir->name());
759 addUsesDependency(usedDir,fd,ii.fileDef,true,true);
760 }
761 }
762 }
763 }
764
765 std::stable_sort(m_usedDirs.begin(),m_usedDirs.end(),
766 [](const auto &u1,const auto &u2)
767 { return qstricmp_sort(u1->dir()->getOutputFileBase(),u2->dir()->getOutputFileBase())<0; });
768
769 for (const auto& usedDirectory : m_usedDirs)
770 {
771 usedDirectory->sort();
772 }
773}
774
775bool DirDefImpl::isParentOf(const DirDef *dir) const
776{
777 if (dir->parent()==this) // this is a parent of dir
778 return TRUE;
779 else if (dir->parent()) // repeat for the parent of dir
780 return isParentOf(dir->parent());
781 else
782 return FALSE;
783}
784
786{
787 return m_usedDirs.empty() && m_parent==nullptr;
788}
789
790//----------------------------------------------------------------------
791
793 m_dir(dir)
794{
795}
796
797void UsedDir::addFileDep(const FileDef *srcFd,const FileDef *dstFd, bool srcDirect, bool dstDirect)
798{
799 m_filePairs.add(FilePair::key(srcFd,dstFd),std::make_unique<FilePair>(srcFd,dstFd));
800 m_hasDirectDeps = m_hasDirectDeps || (srcDirect && dstDirect);
803}
804
806{
807 std::stable_sort(m_filePairs.begin(),
808 m_filePairs.end(),
809 [](const auto &left,const auto &right)
810 {
811 int orderHi = qstricmp_sort(left->source()->name(),right->source()->name());
812 if (orderHi!=0) return orderHi<0;
813 int orderLo = qstricmp_sort(left->destination()->name(),right->destination()->name());
814 return orderLo<0;
815 });
816}
817
819{
820 return m_filePairs.find(name);
821}
822
824{
825 AUTO_TRACE();
826 ASSERT(path!=nullptr);
827 DirDef *dir = Doxygen::dirLinkedMap->find(path);
828 if (dir==nullptr) // new dir
829 {
830 dir = Doxygen::dirLinkedMap->add(path,
831 std::unique_ptr<DirDef>(
832 createDirDef(path)));
833 AUTO_TRACE_ADD("Adding new dir {} shortName {}",path,dir->shortName());
834 }
835 return dir;
836}
837
839{
840 for (const auto &s : l)
841 {
842 std::string prefix = s.substr(0,path.length());
843 if (qstricmp_sort(prefix.c_str(),path)==0) // case insensitive compare
844 {
845 return TRUE;
846 }
847 }
848 return FALSE;
849}
850
851/*! strip part of \a path if it matches
852 * one of the paths in the Config_getList(STRIP_FROM_PATH) list
853 */
855{
856 AUTO_TRACE("path={}",path);
857 int p=0,i=0;
858 DirDef *dir=nullptr;
859 while ((i=path.find('/',p))!=-1)
860 {
861 QCString part=path.left(i+1);
862 if (!matchPath(part,Config_getList(STRIP_FROM_PATH)) && (part!="/" && part!="//" && part!="//?/"))
863 {
865 }
866 p=i+1;
867 }
868 return dir;
869}
870
875
877{
878 return m_hasDirectoryGraph;
879}
880
881//----------------------------------------------------------------------
882
883QCString FilePair::key(const FileDef *srcFd,const FileDef *dstFd)
884{
885 return srcFd->getOutputFileBase()+";"+dstFd->getOutputFileBase();
886}
887
888//----------------------------------------------------------------------
889
890static void writePartialDirPath(OutputList &ol,const DirDef *root,const DirDef *target)
891{
892 if (target->parent()!=root)
893 {
894 writePartialDirPath(ol,root,target->parent());
895 ol.writeString("&#160;/&#160;");
896 }
897 ol.writeObjectLink(target->getReference(),target->getOutputFileBase(),QCString(),target->shortName());
898}
899
900static void writePartialFilePath(OutputList &ol,const DirDef *root,const FileDef *fd)
901{
902 if (fd->getDirDef() && fd->getDirDef()!=root)
903 {
904 writePartialDirPath(ol,root,fd->getDirDef());
905 ol.writeString("&#160;/&#160;");
906 }
907 if (fd->isLinkable())
908 {
910 }
911 else
912 {
913 ol.startBold();
914 ol.docify(fd->name());
915 ol.endBold();
916 }
917}
918
920{
921 bool generateTreeView = Config_getBool(GENERATE_TREEVIEW);
924
925 QCString shortTitle=theTranslator->trDirRelation(
926 (m_src->shortName()+" &rarr; "+m_dst->dir()->shortName()));
927 QCString title=theTranslator->trDirRelation(
928 (m_src->displayName()+" -> "+m_dst->dir()->shortName()));
929 AUTO_TRACE("title={}",title);
931 title,HighlightedItem::None,!generateTreeView,m_src->getOutputFileBase());
932
933 if (!generateTreeView)
934 {
935 // write navigation path
936 m_src->writeNavigationPath(ol);
937 ol.endQuickIndices();
938 }
939 ol.startContents();
940
941 ol.writeString("<h3>"+shortTitle+"</h3>");
942 ol.writeString("<table class=\"dirtab\">");
943 ol.writeString("<tr class=\"dirtab\">");
944 ol.writeString("<th class=\"dirtab\">");
945 ol.parseText(theTranslator->trFileIn(m_src->pathFragment()));
946 ol.writeString("</th>");
947 ol.writeString("<th class=\"dirtab\">");
948 ol.parseText(theTranslator->trIncludesFileIn(m_dst->dir()->pathFragment()));
949 ol.writeString("</th>");
950 ol.writeString("</tr>");
951
952 for (const auto &fp : m_dst->filePairs())
953 {
954 ol.writeString("<tr class=\"dirtab\">");
955 ol.writeString("<td class=\"dirtab\">");
956 writePartialFilePath(ol,m_src,fp->source());
957 ol.writeString("</td>");
958 ol.writeString("<td class=\"dirtab\">");
959 writePartialFilePath(ol,m_dst->dir(),fp->destination());
960 ol.writeString("</td>");
961 ol.writeString("</tr>");
962 }
963 ol.writeString("</table>");
964
965 ol.endContents();
966
968
970}
971
972//----------------------------------------------------------------------
973// external functions
974
975/** In order to create stable, but unique directory names,
976 * we compute the common part of the path shared by all directories.
977 */
979{
980 AUTO_TRACE();
981 QCString path;
982 auto it = Doxygen::dirLinkedMap->begin();
983 if (!Doxygen::dirLinkedMap->empty()) // we have at least one dir
984 {
985 // start will full path of first dir
986 path=removeLongPathMarker((*it)->name());
987 int i=path.findRev('/',static_cast<int>(path.length())-2);
988 path=path.left(i+1);
989 bool done=FALSE;
990 if (i==-1)
991 {
992 path="";
993 }
994 else
995 {
996 while (!done)
997 {
998 int l = static_cast<int>(path.length());
999 size_t count=0;
1000 for (const auto &dir : *Doxygen::dirLinkedMap)
1001 {
1002 QCString dirName = removeLongPathMarker(dir->name());
1003 //printf("dirName='%s' (l=%d) path='%s' (l=%d)\n",qPrint(dirName),dirName.length(),qPrint(path),path.length());
1004 if (dirName.length()>path.length())
1005 {
1006 if (dirName.left(l)!=path) // dirName does not start with path
1007 {
1008 i = l>=2 ? path.findRev('/',l-2) : -1;
1009 if (i==-1) // no unique prefix -> stop
1010 {
1011 path="";
1012 done=TRUE;
1013 }
1014 else // restart with shorter path
1015 {
1016 path=path.left(i+1);
1017 break;
1018 }
1019 }
1020 }
1021 else // dir is shorter than path -> take path of dir as new start
1022 {
1023 path=dir->name();
1024 l=static_cast<int>(path.length());
1025 i=path.findRev('/',l-2);
1026 if (i==-1) // no unique prefix -> stop
1027 {
1028 path="";
1029 done=TRUE;
1030 }
1031 else // restart with shorter path
1032 {
1033 path=path.left(i+1);
1034 }
1035 break;
1036 }
1037 count++;
1038 }
1039 if (count==Doxygen::dirLinkedMap->size())
1040 // path matches for all directories -> found the common prefix
1041 {
1042 done=TRUE;
1043 }
1044 }
1045 }
1046 }
1047 for (const auto &dir : *Doxygen::dirLinkedMap)
1048 {
1049 QCString diskName = dir->name().right(dir->name().length()-path.length());
1050 dir->setDiskName(diskName);
1051 AUTO_TRACE_ADD("set disk name: {} -> {}",dir->name(),diskName);
1052 }
1053}
1054
1056{
1057 AUTO_TRACE();
1058 // for each input file
1059 for (const auto &fn : *Doxygen::inputNameLinkedMap)
1060 {
1061 for (const auto &fd : *fn)
1062 {
1063 if (fd->getReference().isEmpty())
1064 {
1065 DirDef *dir=Doxygen::dirLinkedMap->find(fd->getPath());
1066 if (dir==nullptr) // new directory
1067 {
1068 dir = DirDefImpl::mergeDirectoryInTree(fd->getPath());
1069 }
1070 if (dir && !fd->isDocumentationFile()) dir->addFile(fd.get());
1071 }
1072 else
1073 {
1074 // do something for file imported via tag files.
1075 }
1076 }
1077 }
1078
1079 // compute relations between directories => introduce container dirs.
1080 for (const auto &dir : *Doxygen::dirLinkedMap)
1081 {
1082 QCString name = dir->name();
1083 int i=name.findRev('/',static_cast<int>(name.length())-2);
1084 if (i>0)
1085 {
1086 DirDef *parent = Doxygen::dirLinkedMap->find(name.left(i+1));
1087 //if (parent==0) parent=root;
1088 if (parent)
1089 {
1090 parent->addSubDir(dir.get());
1091 AUTO_TRACE_ADD("DirDefImpl::addSubdir(): Adding subdir {} to {}",
1092 dir->displayName(), parent->displayName());
1093 }
1094 }
1095 }
1096
1097 // sort the directory contents
1098 for (const auto &dir : *Doxygen::dirLinkedMap)
1099 {
1100 dir->sort();
1101 }
1102
1103 // short the directories themselves
1104 std::stable_sort(Doxygen::dirLinkedMap->begin(),
1106 [](const auto &d1,const auto &d2)
1107 {
1108 QCString s1 = d1->shortName(), s2 = d2->shortName();
1109 int i = qstricmp_sort(s1,s2);
1110 if (i==0) // if sort name are equal, sort on full path
1111 {
1112 QCString n1 = d1->name(), n2 = d2->name();
1113 int n = qstricmp_sort(n1,n2);
1114 return n < 0;
1115 }
1116 return i < 0;
1117 });
1118
1119 // set the directory index identifier
1120 int dirIndex=0;
1121 for (const auto &dir : *Doxygen::dirLinkedMap)
1122 {
1123 dir->setDirIndex(dirIndex++);
1124 }
1125
1127}
1128
1130{
1131 AUTO_TRACE();
1132 // compute nesting level for each directory
1133 for (const auto &dir : *Doxygen::dirLinkedMap)
1134 {
1135 dir->setLevel();
1136 }
1137
1138 // compute uses dependencies between directories
1139 for (const auto &dir : *Doxygen::dirLinkedMap)
1140 {
1141 AUTO_TRACE_ADD("computeDependencies for {}: #dirs={}",dir->name(),Doxygen::dirLinkedMap->size());
1142 dir->computeDependencies();
1143 }
1144}
1145
1147{
1148 AUTO_TRACE();
1149 for (const auto &dir : *Doxygen::dirLinkedMap)
1150 {
1151 ol.pushGeneratorState();
1152 if (!dir->hasDocumentation())
1153 {
1155 }
1156 dir->writeDocumentation(ol);
1157 ol.popGeneratorState();
1158 }
1159 //if (Config_getBool(DIRECTORY_GRAPH))
1160 {
1161 for (const auto &dr : Doxygen::dirRelations)
1162 {
1163 dr->writeDocumentation(ol);
1164 }
1165 }
1166}
1167
1168bool compareDirDefs(const DirDef *item1, const DirDef *item2)
1169{
1170 return qstricmp_sort(item1->shortName(),item2->shortName()) < 0;
1171}
1172
1173// --- Cast functions
1174
1176{
1177 if (d==nullptr) return nullptr;
1178 if (d && typeid(*d)==typeid(DirDefImpl))
1179 {
1180 return static_cast<DirDef*>(d);
1181 }
1182 else
1183 {
1184 return nullptr;
1185 }
1186}
1187
1189{
1190 if (d==nullptr) return nullptr;
1191 if (d && typeid(*d)==typeid(DirDefImpl))
1192 {
1193 return static_cast<const DirDef*>(d);
1194 }
1195 else
1196 {
1197 return nullptr;
1198 }
1199}
1200
constexpr auto prefix
Definition anchor.cpp:44
The common base class of all entity definitions found in the sources.
Definition definition.h:76
virtual bool isLinkable() const =0
virtual QCString getReference() const =0
virtual QCString briefFile() const =0
virtual QCString getOutputFileBase() const =0
virtual const QCString & name() const =0
bool isReference() const override
const QCString & name() const override
void writeNavigationPath(OutputList &ol) const override
bool hasBriefDescription() const override
QCString docFile() const override
QCString briefFile() const override
QCString briefDescription(bool abbreviate=FALSE) const override
DefinitionMixin(const QCString &defFileName, int defLine, int defColumn, const QCString &name, const char *b=nullptr, const char *d=nullptr, bool isSymbol=TRUE)
void setLocalName(const QCString &name) override
int docLine() const override
int briefLine() const override
QCString documentation() const override
void writeDocAnchorsToTagFile(TextStream &fs) const override
SrcLangExt getLanguage() const override
virtual void setOuterScope(Definition *d)=0
A model of a directory symbol.
Definition dirdef.h:110
virtual int level() const =0
virtual void setLevel()=0
virtual void addFile(FileDef *fd)=0
virtual DirDef * parent() const =0
virtual void addUsesDependency(const DirDef *usedDir, const FileDef *srcFd, const FileDef *dstFd, bool srcDirect, bool dstDirect)=0
virtual void setParent(DirDef *parent)=0
virtual const QCString shortName() const =0
void writeDocumentation(OutputList &ol) override
Definition dirdef.cpp:537
int m_dirIndex
Definition dirdef.cpp:100
void writeSubDirList(OutputList &ol)
Definition dirdef.cpp:335
void setLevel() override
Definition dirdef.cpp:661
static DirDef * createNewDir(const QCString &path)
Definition dirdef.cpp:823
DirDef * m_parent
Definition dirdef.cpp:102
static bool matchPath(const QCString &path, const StringVector &l)
Definition dirdef.cpp:838
QCString m_diskName
Definition dirdef.cpp:98
bool hasSubdirs() const override
Definition dirdef.cpp:56
QCString m_shortName
Definition dirdef.cpp:97
void writeTagFile(TextStream &t) override
Definition dirdef.cpp:498
const FileList & getFiles() const override
Definition dirdef.cpp:53
const QCString shortName() const override
Definition dirdef.cpp:51
bool isLinkable() const override
Definition dirdef.cpp:154
const UsedDirLinkedMap & usedDirs() const override
Definition dirdef.cpp:60
void addSubDir(DirDef *subdir) override
Definition dirdef.cpp:159
bool hasDetailedDescription() const override
Definition dirdef.cpp:492
DirDef * parent() const override
Definition dirdef.cpp:58
void startMemberDeclarations(OutputList &ol)
Definition dirdef.cpp:477
int level() const override
Definition dirdef.cpp:57
bool isLinkableInProject() const override
Definition dirdef.cpp:149
void writeDetailedDescription(OutputList &ol, const QCString &title)
Definition dirdef.cpp:229
DirList m_subdirs
Definition dirdef.cpp:95
DefType definitionType() const override
Definition dirdef.cpp:44
bool isParentOf(const DirDef *dir) const override
Definition dirdef.cpp:775
QCString getOutputFileBase() const override
Definition dirdef.cpp:222
int dirIndex() const override
Definition dirdef.cpp:59
QCString m_dispName
Definition dirdef.cpp:96
QCString anchor() const override
Definition dirdef.cpp:47
CodeSymbolType codeSymbolType() const override
Definition dirdef.cpp:45
void addFile(FileDef *fd) override
Definition dirdef.cpp:176
bool depGraphIsTrivial() const override
Definition dirdef.cpp:785
void overrideDirectoryGraph(bool e) override
Definition dirdef.cpp:871
void addUsesDependency(const DirDef *usedDir, const FileDef *srcFd, const FileDef *dstFd, bool srcDirect, bool dstDirect) override
Add as "uses" dependency between this dir and dir, that was caused by a dependency on file fd.
Definition dirdef.cpp:683
void writeDirectoryGraph(OutputList &ol)
Definition dirdef.cpp:315
const DirList & subDirs() const override
Definition dirdef.cpp:55
UsedDirLinkedMap m_usedDirs
Definition dirdef.cpp:103
void setDiskName(const QCString &name) override
Definition dirdef.cpp:67
static DirDef * mergeDirectoryInTree(const QCString &path)
Definition dirdef.cpp:854
void writeFileList(OutputList &ol)
Definition dirdef.cpp:394
QCString shortTitle() const override
Definition dirdef.cpp:487
DirDefImpl(const QCString &path)
Definition dirdef.cpp:116
void setDirIndex(int index) override
Definition dirdef.cpp:171
void endMemberDeclarations(OutputList &ol)
Definition dirdef.cpp:482
int m_level
Definition dirdef.cpp:101
FileList m_fileList
Definition dirdef.cpp:99
void sort() override
Definition dirdef.cpp:182
~DirDefImpl() override
Definition dirdef.cpp:145
void writeBriefDescription(OutputList &ol)
Definition dirdef.cpp:276
void computeDependencies() override
Computes the dependencies between directories.
Definition dirdef.cpp:743
QCString displayName(bool=TRUE) const override
Definition dirdef.cpp:50
void setParent(DirDef *parent) override
Definition dirdef.cpp:166
bool m_hasDirectoryGraph
Definition dirdef.cpp:104
bool hasDirectoryGraph() const override
Definition dirdef.cpp:876
const DirDef * m_src
Definition dirdef.h:166
UsedDir * m_dst
Definition dirdef.h:167
void writeDocumentation(OutputList &ol)
Definition dirdef.cpp:919
QCString getOutputFileBase() const
Definition dirdef.h:162
bool isTrivial() const
static FileNameLinkedMap * inputNameLinkedMap
Definition doxygen.h:105
static DirLinkedMap * dirLinkedMap
Definition doxygen.h:129
static DirRelationLinkedMap dirRelations
Definition doxygen.h:130
A model of a file symbol.
Definition filedef.h:99
virtual void setDirDef(DirDef *dd)=0
virtual DirDef * getDirDef() const =0
Class representing a pair of FileDef objects.
Definition dirdef.h:42
static QCString key(const FileDef *srcFd, const FileDef *dstFd)
Definition dirdef.cpp:883
static LayoutDocManager & instance()
Returns a reference to this singleton.
Definition layout.cpp:1423
T * add(const char *k, Args &&... args)
Adds a new object to the ordered vector if it was not added already.
Definition linkedmap.h:90
const T * find(const std::string &key) const
Find an object given the key.
Definition linkedmap.h:47
Class representing a list of output generators that are written to in parallel.
Definition outputlist.h:314
void writeString(const QCString &text)
Definition outputlist.h:412
void startGroupHeader(int extraLevels=0)
Definition outputlist.h:454
void startMemberDeclaration()
Definition outputlist.h:570
void disable(OutputType o)
void endDirDepGraph(DotDirDeps &g)
Definition outputlist.h:661
void writeRuler()
Definition outputlist.h:522
void enable(OutputType o)
void endContents()
Definition outputlist.h:619
void endMemberDescription()
Definition outputlist.h:568
void writeObjectLink(const QCString &ref, const QCString &file, const QCString &anchor, const QCString &name)
Definition outputlist.h:440
void writeDoc(const IDocNodeAST *ast, const Definition *ctx, const MemberDef *md)
Definition outputlist.h:384
void startMemberDescription(const QCString &anchor, const QCString &inheritId=QCString(), bool typ=false)
Definition outputlist.h:566
void docify(const QCString &s)
Definition outputlist.h:438
void startParagraph(const QCString &classDef=QCString())
Definition outputlist.h:408
void endParagraph()
Definition outputlist.h:410
void startDirDepGraph()
Definition outputlist.h:659
void startMemberSections()
Definition outputlist.h:462
void startMemberList()
Definition outputlist.h:482
void endTextLink()
Definition outputlist.h:445
void startBold()
Definition outputlist.h:562
void endMemberItem(OutputGenerator::MemberItemType type)
Definition outputlist.h:496
void endMemberList()
Definition outputlist.h:484
void writeSynopsis()
Definition outputlist.h:593
void generateDoc(const QCString &fileName, int startLine, const Definition *ctx, const MemberDef *md, const QCString &docStr, bool indexWords, bool isExample, const QCString &exampleName, bool singleLine, bool linkFromIndex, bool markdownSupport)
void pushGeneratorState()
void insertMemberAlign(bool templ=FALSE)
Definition outputlist.h:518
void disableAllBut(OutputType o)
void popGeneratorState()
void writeAnchor(const QCString &fileName, const QCString &name)
Definition outputlist.h:524
void endBold()
Definition outputlist.h:564
void endGroupHeader(int extraLevels=0)
Definition outputlist.h:456
void endQuickIndices()
Definition outputlist.h:605
void startContents()
Definition outputlist.h:617
void endMemberDeclaration(const QCString &anchor, const QCString &inheritId)
Definition outputlist.h:572
void enableAll()
void endMemberHeader()
Definition outputlist.h:472
void startMemberItem(const QCString &anchor, OutputGenerator::MemberItemType type, const QCString &id=QCString())
Definition outputlist.h:494
void parseText(const QCString &textStr)
void startTextLink(const QCString &file, const QCString &anchor)
Definition outputlist.h:443
void startMemberHeader(const QCString &anchor, int typ=2)
Definition outputlist.h:470
void endMemberSections()
Definition outputlist.h:464
This is an alternative implementation of QCString.
Definition qcstring.h:101
int find(char c, int index=0, bool cs=TRUE) const
Definition qcstring.cpp:43
size_t length() const
Returns the length of the string, not counting the 0-terminator.
Definition qcstring.h:153
bool isEmpty() const
Returns TRUE iff the string is empty.
Definition qcstring.h:150
QCString right(size_t len) const
Definition qcstring.h:219
int findRev(char c, int index=-1, bool cs=TRUE) const
Definition qcstring.cpp:91
const char * data() const
Returns a pointer to the contents of the string in the form of a 0-terminated C string.
Definition qcstring.h:159
QCString left(size_t len) const
Definition qcstring.h:214
Text streaming class that buffers data.
Definition textstream.h:36
virtual QCString trIncludesFileIn(const QCString &name)=0
virtual QCString trDirDepGraph(const QCString &name)=0
virtual QCString trDir(bool first_capital, bool singular)=0
virtual QCString trMore()=0
virtual QCString trDirRelation(const QCString &name)=0
virtual QCString trFile(bool first_capital, bool singular)=0
virtual QCString trFileIn(const QCString &name)=0
virtual QCString trDirReference(const QCString &dirName)=0
bool m_hasDirectDstDeps
Definition dirdef.h:103
void sort()
Definition dirdef.cpp:805
FilePairLinkedMap m_filePairs
Definition dirdef.h:99
bool m_hasDirectDeps
Definition dirdef.h:101
void addFileDep(const FileDef *srcFd, const FileDef *dstFd, bool srcDirect, bool dstDirect)
Take up dependency between files.
Definition dirdef.cpp:797
const DirDef * dir() const
Definition dirdef.h:78
UsedDir(const DirDef *dir)
Definition dirdef.cpp:792
FilePair * findFilePair(const QCString &name)
Definition dirdef.cpp:818
bool m_hasDirectSrcDeps
Definition dirdef.h:102
const DirDef * m_dir
Definition dirdef.h:98
#define Config_getList(name)
Definition config.h:38
#define Config_getBool(name)
Definition config.h:33
#define NON_COPYABLE(cls)
Macro to help implementing the rule of 5 for a non-copyable & movable class.
Definition construct.h:37
std::vector< std::string > StringVector
Definition containers.h:33
DirIterator begin(DirIterator it) noexcept
Definition dir.cpp:170
DirIterator end(const DirIterator &) noexcept
Definition dir.cpp:175
DirDef * createDirDef(const QCString &path)
Definition dirdef.cpp:107
static void writePartialFilePath(OutputList &ol, const DirDef *root, const FileDef *fd)
Definition dirdef.cpp:900
bool compareDirDefs(const DirDef *item1, const DirDef *item2)
Definition dirdef.cpp:1168
static void writePartialDirPath(OutputList &ol, const DirDef *root, const DirDef *target)
Definition dirdef.cpp:890
static QCString encodeDirName(const QCString &anchor)
Definition dirdef.cpp:188
void buildDirectories()
Definition dirdef.cpp:1055
void computeDirDependencies()
Definition dirdef.cpp:1129
DirDef * toDirDef(Definition *d)
Definition dirdef.cpp:1175
static void computeCommonDirPrefix()
In order to create stable, but unique directory names, we compute the common part of the path shared ...
Definition dirdef.cpp:978
void generateDirDocs(OutputList &ol)
Definition dirdef.cpp:1146
#define AUTO_TRACE_ADD(...)
Definition docnode.cpp:47
#define AUTO_TRACE(...)
Definition docnode.cpp:46
#define AUTO_TRACE_EXIT(...)
Definition docnode.cpp:48
constexpr DocNodeVariant * parent(DocNodeVariant *n)
returns the parent node of a given node n or nullptr if the node has no parent.
Definition docnode.h:1310
IDocParserPtr createDocParser()
factory function to create a parser
Definition docparser.cpp:54
IDocNodeASTPtr validatingParseDoc(IDocParser &parserIntf, const QCString &fileName, int startLine, const Definition *ctx, const MemberDef *md, const QCString &input, bool indexWords, bool isExample, const QCString &exampleName, bool singleLine, bool linkFromIndex, bool markdownSupport)
static void writeTagFile()
bool compareFileDefs(const FileDef *fd1, const FileDef *fd2)
Definition filedef.cpp:1885
void startTitle(OutputList &ol, const QCString &fileName, const DefinitionMutable *def)
Definition index.cpp:386
void endTitle(OutputList &ol, const QCString &fileName, const QCString &name)
Definition index.cpp:395
void startFile(OutputList &ol, const QCString &name, const QCString &manName, const QCString &title, HighlightedItem hli, bool additionalIndices, const QCString &altSidebarName, int hierarchyLevel)
Definition index.cpp:402
void endFileWithNavPath(OutputList &ol, const Definition *d)
Definition index.cpp:441
Translator * theTranslator
Definition language.cpp:71
void msg(const char *fmt,...)
Definition message.cpp:98
#define err(fmt,...)
Definition message.h:84
int qstricmp_sort(const char *str1, const char *str2)
Definition qcstring.h:86
const char * qPrint(const char *s)
Definition qcstring.h:661
#define TRUE
Definition qcstring.h:37
#define FALSE
Definition qcstring.h:34
#define ASSERT(x)
Definition qcstring.h:39
QCString title(SrcLangExt lang) const
Definition layout.cpp:1526
CodeSymbolType
Definition types.h:319
SrcLangExt
Language as given by extension.
Definition types.h:42
bool fileVisibleInIndex(const FileDef *fd, bool &genSourceFile)
Definition util.cpp:6416
static QCString stripFromPath(const QCString &p, const StringVector &l)
Definition util.cpp:309
QCString convertToXML(const QCString &s, bool keepEntities)
Definition util.cpp:4266
QCString removeLongPathMarker(QCString path)
Definition util.cpp:298
void addHtmlExtensionIfMissing(QCString &fName)
Definition util.cpp:5243
A bunch of utility functions.