Root/
Source at commit 1322 created 12 years 8 months ago. By meklort, Add doxygen to utils folder | |
---|---|
1 | #include "md5.h"␊ |
2 | ␊ |
3 | #include "dirdef.h"␊ |
4 | #include "filename.h"␊ |
5 | #include "doxygen.h"␊ |
6 | #include "util.h"␊ |
7 | #include "outputlist.h"␊ |
8 | #include "language.h"␊ |
9 | #include "message.h"␊ |
10 | #include "dot.h"␊ |
11 | #include "layout.h"␊ |
12 | #include "ftextstream.h"␊ |
13 | ␊ |
14 | //----------------------------------------------------------------------␊ |
15 | // method implementation␊ |
16 | ␊ |
17 | static int g_dirCount=0;␊ |
18 | ␊ |
19 | DirDef::DirDef(const char *path) : Definition(path,1,path)␊ |
20 | {␊ |
21 | // get display name (stipping the paths mentioned in STRIP_FROM_PATH)␊ |
22 | m_dispName = stripFromPath(path);␊ |
23 | // get short name (last part of path)␊ |
24 | m_shortName = path;␊ |
25 | if (m_shortName.at(m_shortName.length()-1)=='/')␊ |
26 | { // strip trailing /␊ |
27 | m_shortName = m_shortName.left(m_shortName.length()-1);␊ |
28 | }␊ |
29 | int pi=m_shortName.findRev('/');␊ |
30 | if (pi!=-1) ␊ |
31 | { // remove everything till the last /␊ |
32 | m_shortName = m_shortName.mid(pi+1);␊ |
33 | }␊ |
34 | setLocalName(m_shortName);␊ |
35 | ␊ |
36 | m_fileList = new FileList;␊ |
37 | m_usedDirs = new QDict<UsedDir>(257);␊ |
38 | m_usedDirs->setAutoDelete(TRUE);␊ |
39 | m_dirCount = g_dirCount++;␊ |
40 | m_level=-1;␊ |
41 | m_parent=0;␊ |
42 | }␊ |
43 | ␊ |
44 | DirDef::~DirDef()␊ |
45 | {␊ |
46 | delete m_fileList;␊ |
47 | delete m_usedDirs;␊ |
48 | }␊ |
49 | ␊ |
50 | bool DirDef::isLinkableInProject() const ␊ |
51 | { ␊ |
52 | return !isReference() && Config_getBool("SHOW_DIRECTORIES"); ␊ |
53 | }␊ |
54 | ␊ |
55 | bool DirDef::isLinkable() const ␊ |
56 | { ␊ |
57 | return isReference() || isLinkableInProject(); ␊ |
58 | }␊ |
59 | ␊ |
60 | void DirDef::addSubDir(DirDef *subdir)␊ |
61 | {␊ |
62 | m_subdirs.inSort(subdir);␊ |
63 | subdir->setOuterScope(this);␊ |
64 | subdir->m_parent=this;␊ |
65 | }␊ |
66 | ␊ |
67 | void DirDef::addFile(FileDef *fd)␊ |
68 | {␊ |
69 | m_fileList->inSort(fd);␊ |
70 | fd->setDirDef(this);␊ |
71 | }␊ |
72 | ␊ |
73 | static QCString encodeDirName(const QCString &anchor)␊ |
74 | {␊ |
75 | QCString result;␊ |
76 | ␊ |
77 | // convert to md5 hash␊ |
78 | uchar md5_sig[16];␊ |
79 | QCString sigStr(33);␊ |
80 | MD5Buffer((const unsigned char *)anchor.data(),anchor.length(),md5_sig);␊ |
81 | MD5SigToString(md5_sig,sigStr.data(),33);␊ |
82 | return sigStr;␊ |
83 | ␊ |
84 | // old algorithm␊ |
85 | ␊ |
86 | // int l = anchor.length(),i;␊ |
87 | // for (i=0;i<l;i++)␊ |
88 | // {␊ |
89 | // char c = anchor.at(i);␊ |
90 | // if ((c>='a' && c<='z') || (c>='A' && c<='Z') || (c>='0' && c<='9'))␊ |
91 | // {␊ |
92 | // result+=c;␊ |
93 | // }␊ |
94 | // else␊ |
95 | // {␊ |
96 | // static char hexStr[]="0123456789ABCDEF";␊ |
97 | // char escChar[]={ '_', 0, 0, 0 };␊ |
98 | // escChar[1]=hexStr[c>>4];␊ |
99 | // escChar[2]=hexStr[c&0xf];␊ |
100 | // result+=escChar;␊ |
101 | // }␊ |
102 | // }␊ |
103 | // return result;␊ |
104 | }␊ |
105 | ␊ |
106 | QCString DirDef::getOutputFileBase() const␊ |
107 | {␊ |
108 | return "dir_"+encodeDirName(name());␊ |
109 | //return QCString().sprintf("dir_%06d",m_dirCount);␊ |
110 | }␊ |
111 | ␊ |
112 | void DirDef::writeDetailedDescription(OutputList &ol,const QCString &title)␊ |
113 | {␊ |
114 | if ((!briefDescription().isEmpty() && Config_getBool("REPEAT_BRIEF")) || ␊ |
115 | !documentation().isEmpty())␊ |
116 | {␊ |
117 | ol.writeRuler();␊ |
118 | ol.pushGeneratorState();␊ |
119 | ol.disableAllBut(OutputGenerator::Html);␊ |
120 | ol.writeAnchor(0,"details");␊ |
121 | ol.popGeneratorState();␊ |
122 | ol.startGroupHeader();␊ |
123 | ol.parseText(title);␊ |
124 | ol.endGroupHeader();␊ |
125 | ␊ |
126 | // repeat brief description␊ |
127 | if (!briefDescription().isEmpty() && Config_getBool("REPEAT_BRIEF"))␊ |
128 | {␊ |
129 | ol.parseDoc(briefFile(),briefLine(),this,0,briefDescription(),FALSE,FALSE);␊ |
130 | }␊ |
131 | // separator between brief and details␊ |
132 | if (!briefDescription().isEmpty() && Config_getBool("REPEAT_BRIEF") && ␊ |
133 | !documentation().isEmpty())␊ |
134 | {␊ |
135 | ol.pushGeneratorState();␊ |
136 | ol.disable(OutputGenerator::Man);␊ |
137 | ol.disable(OutputGenerator::RTF);␊ |
138 | // ol.newParagraph(); // FIXME:PARA␊ |
139 | ol.enableAll();␊ |
140 | ol.disableAllBut(OutputGenerator::Man);␊ |
141 | ol.writeString("\n\n");␊ |
142 | ol.popGeneratorState();␊ |
143 | }␊ |
144 | ␊ |
145 | // write documentation␊ |
146 | if (!documentation().isEmpty())␊ |
147 | {␊ |
148 | ol.parseDoc(docFile(),docLine(),this,0,documentation()+"\n",TRUE,FALSE);␊ |
149 | }␊ |
150 | }␊ |
151 | }␊ |
152 | ␊ |
153 | void DirDef::writeBriefDescription(OutputList &ol)␊ |
154 | {␊ |
155 | if (!briefDescription().isEmpty()) ␊ |
156 | {␊ |
157 | ol.startParagraph();␊ |
158 | ol.parseDoc(briefFile(),briefLine(),this,0,briefDescription(),TRUE,FALSE);␊ |
159 | ol.pushGeneratorState();␊ |
160 | ol.disable(OutputGenerator::RTF);␊ |
161 | ol.writeString(" \n");␊ |
162 | ol.enable(OutputGenerator::RTF);␊ |
163 | ␊ |
164 | if (Config_getBool("REPEAT_BRIEF") ||␊ |
165 | !documentation().isEmpty()␊ |
166 | )␊ |
167 | {␊ |
168 | ol.disableAllBut(OutputGenerator::Html);␊ |
169 | ol.startTextLink(0,"details");␊ |
170 | ol.parseText(theTranslator->trMore());␊ |
171 | ol.endTextLink();␊ |
172 | }␊ |
173 | ol.popGeneratorState();␊ |
174 | ␊ |
175 | //ol.pushGeneratorState();␊ |
176 | //ol.disable(OutputGenerator::RTF);␊ |
177 | //ol.newParagraph();␊ |
178 | //ol.popGeneratorState();␊ |
179 | ol.endParagraph();␊ |
180 | }␊ |
181 | ol.writeSynopsis();␊ |
182 | }␊ |
183 | ␊ |
184 | void DirDef::writeDirectoryGraph(OutputList &ol)␊ |
185 | {␊ |
186 | // write graph dependency graph␊ |
187 | if (/*Config_getBool("DIRECTORY_GRAPH") &&*/ Config_getBool("HAVE_DOT"))␊ |
188 | {␊ |
189 | DotDirDeps dirDep(this);␊ |
190 | if (!dirDep.isTrivial())␊ |
191 | {␊ |
192 | msg("Generating dependency graph for directory %s\n",displayName().data());␊ |
193 | ol.disable(OutputGenerator::Man);␊ |
194 | //ol.startParagraph();␊ |
195 | ol.startDirDepGraph();␊ |
196 | //TODO: ol.parseText(theTranslator->trDirDepGraph());␊ |
197 | ol.parseText((QCString)"Directory dependency graph for "+displayName()+":");␊ |
198 | ol.endDirDepGraph(dirDep);␊ |
199 | //ol.endParagraph();␊ |
200 | ol.enableAll();␊ |
201 | }␊ |
202 | }␊ |
203 | }␊ |
204 | ␊ |
205 | void DirDef::writeSubDirList(OutputList &ol)␊ |
206 | {␊ |
207 | // write subdir list␊ |
208 | if (m_subdirs.count()>0)␊ |
209 | {␊ |
210 | ol.startMemberHeader("subdirs");␊ |
211 | ol.parseText(theTranslator->trDir(TRUE,FALSE));␊ |
212 | ol.endMemberHeader();␊ |
213 | ol.startMemberList();␊ |
214 | DirDef *dd=m_subdirs.first();␊ |
215 | while (dd)␊ |
216 | {␊ |
217 | ol.startMemberItem(0);␊ |
218 | ol.parseText(theTranslator->trDir(FALSE,TRUE)+" ");␊ |
219 | ol.insertMemberAlign();␊ |
220 | ol.writeObjectLink(dd->getReference(),dd->getOutputFileBase(),0,dd->shortName());␊ |
221 | ol.endMemberItem();␊ |
222 | if (!Config_getString("GENERATE_TAGFILE").isEmpty()) ␊ |
223 | {␊ |
224 | Doxygen::tagFile << " <dir>" << convertToXML(dd->displayName()) << "</dir>" << endl;␊ |
225 | }␊ |
226 | if (!dd->briefDescription().isEmpty() && Config_getBool("BRIEF_MEMBER_DESC"))␊ |
227 | {␊ |
228 | ol.startParagraph();␊ |
229 | ol.startMemberDescription();␊ |
230 | ol.parseDoc(briefFile(),briefLine(),dd,0,dd->briefDescription(),␊ |
231 | FALSE, // indexWords␊ |
232 | FALSE, // isExample␊ |
233 | 0, // exampleName␊ |
234 | FALSE, // single line␊ |
235 | TRUE // link from index␊ |
236 | );␊ |
237 | ol.endMemberDescription();␊ |
238 | ol.endParagraph();␊ |
239 | }␊ |
240 | dd=m_subdirs.next();␊ |
241 | }␊ |
242 | ␊ |
243 | ol.endMemberList();␊ |
244 | }␊ |
245 | }␊ |
246 | ␊ |
247 | void DirDef::writeFileList(OutputList &ol)␊ |
248 | {␊ |
249 | // write file list␊ |
250 | if (m_fileList->count()>0)␊ |
251 | {␊ |
252 | ol.startMemberHeader("files");␊ |
253 | ol.parseText(theTranslator->trFile(TRUE,FALSE));␊ |
254 | ol.endMemberHeader();␊ |
255 | ol.startMemberList();␊ |
256 | FileDef *fd=m_fileList->first();␊ |
257 | while (fd)␊ |
258 | {␊ |
259 | ol.startMemberItem(0);␊ |
260 | ol.docify(theTranslator->trFile(FALSE,TRUE)+" ");␊ |
261 | ol.insertMemberAlign();␊ |
262 | if (fd->isLinkable())␊ |
263 | {␊ |
264 | ol.writeObjectLink(fd->getReference(),fd->getOutputFileBase(),0,fd->name());␊ |
265 | }␊ |
266 | else␊ |
267 | {␊ |
268 | ol.startBold();␊ |
269 | ol.docify(fd->name()); ␊ |
270 | ol.endBold();␊ |
271 | }␊ |
272 | if (fd->generateSourceFile())␊ |
273 | {␊ |
274 | ol.pushGeneratorState();␊ |
275 | ol.disableAllBut(OutputGenerator::Html);␊ |
276 | ol.docify(" ");␊ |
277 | ol.startTextLink(fd->includeName(),0);␊ |
278 | ol.docify("[");␊ |
279 | ol.parseText(theTranslator->trCode());␊ |
280 | ol.docify("]");␊ |
281 | ol.endTextLink();␊ |
282 | ol.popGeneratorState();␊ |
283 | }␊ |
284 | if (!Config_getString("GENERATE_TAGFILE").isEmpty()) ␊ |
285 | {␊ |
286 | Doxygen::tagFile << " <file>" << convertToXML(fd->name()) << "</file>" << endl;␊ |
287 | }␊ |
288 | ol.endMemberItem();␊ |
289 | if (!fd->briefDescription().isEmpty() && Config_getBool("BRIEF_MEMBER_DESC"))␊ |
290 | {␊ |
291 | ol.startParagraph();␊ |
292 | ol.startMemberDescription();␊ |
293 | ol.parseDoc(briefFile(),briefLine(),fd,0,fd->briefDescription(),␊ |
294 | FALSE, // indexWords␊ |
295 | FALSE, // isExample␊ |
296 | 0, // exampleName␊ |
297 | FALSE, // single line␊ |
298 | TRUE // link from index␊ |
299 | );␊ |
300 | ol.endMemberDescription();␊ |
301 | ol.endParagraph();␊ |
302 | }␊ |
303 | fd=m_fileList->next();␊ |
304 | }␊ |
305 | ol.endMemberList();␊ |
306 | }␊ |
307 | }␊ |
308 | ␊ |
309 | void DirDef::startMemberDeclarations(OutputList &ol)␊ |
310 | {␊ |
311 | ol.startMemberSections();␊ |
312 | }␊ |
313 | ␊ |
314 | void DirDef::endMemberDeclarations(OutputList &ol)␊ |
315 | {␊ |
316 | ol.endMemberSections();␊ |
317 | }␊ |
318 | ␊ |
319 | void DirDef::writeDocumentation(OutputList &ol)␊ |
320 | {␊ |
321 | static bool generateTreeView = Config_getBool("GENERATE_TREEVIEW");␊ |
322 | ol.pushGeneratorState();␊ |
323 | ␊ |
324 | QCString shortTitle=theTranslator->trDirReference(m_shortName);␊ |
325 | QCString title=theTranslator->trDirReference(m_dispName);␊ |
326 | startFile(ol,getOutputFileBase(),name(),title,HLI_None,!generateTreeView);␊ |
327 | ␊ |
328 | if (!generateTreeView)␊ |
329 | {␊ |
330 | // write navigation path␊ |
331 | writeNavigationPath(ol);␊ |
332 | ol.endQuickIndices();␊ |
333 | }␊ |
334 | ␊ |
335 | startTitle(ol,getOutputFileBase());␊ |
336 | ol.pushGeneratorState();␊ |
337 | ol.disableAllBut(OutputGenerator::Html);␊ |
338 | ol.parseText(shortTitle);␊ |
339 | ol.enableAll();␊ |
340 | ol.disable(OutputGenerator::Html);␊ |
341 | ol.parseText(title);␊ |
342 | ol.popGeneratorState();␊ |
343 | endTitle(ol,getOutputFileBase(),title);␊ |
344 | ol.startContents();␊ |
345 | ␊ |
346 | if (!Config_getString("GENERATE_TAGFILE").isEmpty()) ␊ |
347 | {␊ |
348 | Doxygen::tagFile << " <compound kind=\"dir\">" << endl;␊ |
349 | Doxygen::tagFile << " <name>" << convertToXML(displayName()) << "</name>" << endl;␊ |
350 | Doxygen::tagFile << " <path>" << convertToXML(name()) << "</path>" << endl;␊ |
351 | Doxygen::tagFile << " <filename>" << convertToXML(getOutputFileBase()) << Doxygen::htmlFileExtension << "</filename>" << endl;␊ |
352 | }␊ |
353 | ␊ |
354 | //---------------------------------------- start flexible part -------------------------------␊ |
355 | ␊ |
356 | QListIterator<LayoutDocEntry> eli(␊ |
357 | LayoutDocManager::instance().docEntries(LayoutDocManager::Directory));␊ |
358 | LayoutDocEntry *lde;␊ |
359 | for (eli.toFirst();(lde=eli.current());++eli)␊ |
360 | {␊ |
361 | switch (lde->kind())␊ |
362 | {␊ |
363 | case LayoutDocEntry::BriefDesc: ␊ |
364 | writeBriefDescription(ol);␊ |
365 | break; ␊ |
366 | case LayoutDocEntry::DirGraph: ␊ |
367 | writeDirectoryGraph(ol);␊ |
368 | break; ␊ |
369 | case LayoutDocEntry::MemberDeclStart: ␊ |
370 | startMemberDeclarations(ol);␊ |
371 | break; ␊ |
372 | case LayoutDocEntry::DirSubDirs: ␊ |
373 | writeSubDirList(ol);␊ |
374 | break; ␊ |
375 | case LayoutDocEntry::DirFiles: ␊ |
376 | writeFileList(ol);␊ |
377 | break; ␊ |
378 | case LayoutDocEntry::MemberDeclEnd: ␊ |
379 | endMemberDeclarations(ol);␊ |
380 | break;␊ |
381 | case LayoutDocEntry::DetailedDesc: ␊ |
382 | {␊ |
383 | LayoutDocEntrySection *ls = (LayoutDocEntrySection*)lde;␊ |
384 | writeDetailedDescription(ol,ls->title);␊ |
385 | }␊ |
386 | break;␊ |
387 | case LayoutDocEntry::ClassIncludes:␊ |
388 | case LayoutDocEntry::ClassInheritanceGraph:␊ |
389 | case LayoutDocEntry::ClassNestedClasses:␊ |
390 | case LayoutDocEntry::ClassCollaborationGraph:␊ |
391 | case LayoutDocEntry::ClassAllMembersLink:␊ |
392 | case LayoutDocEntry::ClassUsedFiles:␊ |
393 | case LayoutDocEntry::NamespaceNestedNamespaces:␊ |
394 | case LayoutDocEntry::NamespaceClasses:␊ |
395 | case LayoutDocEntry::FileClasses:␊ |
396 | case LayoutDocEntry::FileNamespaces:␊ |
397 | case LayoutDocEntry::FileIncludes:␊ |
398 | case LayoutDocEntry::FileIncludeGraph:␊ |
399 | case LayoutDocEntry::FileIncludedByGraph: ␊ |
400 | case LayoutDocEntry::FileSourceLink:␊ |
401 | case LayoutDocEntry::GroupClasses: ␊ |
402 | case LayoutDocEntry::GroupInlineClasses: ␊ |
403 | case LayoutDocEntry::GroupNamespaces:␊ |
404 | case LayoutDocEntry::GroupDirs: ␊ |
405 | case LayoutDocEntry::GroupNestedGroups: ␊ |
406 | case LayoutDocEntry::GroupFiles:␊ |
407 | case LayoutDocEntry::GroupGraph: ␊ |
408 | case LayoutDocEntry::GroupPageDocs:␊ |
409 | case LayoutDocEntry::AuthorSection:␊ |
410 | case LayoutDocEntry::MemberGroups:␊ |
411 | case LayoutDocEntry::MemberDecl:␊ |
412 | case LayoutDocEntry::MemberDef:␊ |
413 | case LayoutDocEntry::MemberDefStart:␊ |
414 | case LayoutDocEntry::MemberDefEnd:␊ |
415 | err("Internal inconsistency: member %d should not be part of "␊ |
416 | "LayoutDocManager::Directory entry list\n",lde->kind());␊ |
417 | break;␊ |
418 | }␊ |
419 | }␊ |
420 | ␊ |
421 | //---------------------------------------- end flexible part -------------------------------␊ |
422 | ␊ |
423 | if (!Config_getString("GENERATE_TAGFILE").isEmpty()) ␊ |
424 | {␊ |
425 | writeDocAnchorsToTagFile();␊ |
426 | Doxygen::tagFile << " </compound>" << endl;␊ |
427 | }␊ |
428 | ␊ |
429 | ol.endContents();␊ |
430 | ␊ |
431 | if (generateTreeView)␊ |
432 | {␊ |
433 | writeNavigationPath(ol);␊ |
434 | }␊ |
435 | ␊ |
436 | endFile(ol,TRUE); ␊ |
437 | ol.popGeneratorState();␊ |
438 | ␊ |
439 | ␊ |
440 | }␊ |
441 | ␊ |
442 | void DirDef::setLevel()␊ |
443 | {␊ |
444 | if (m_level==-1) // level not set before␊ |
445 | {␊ |
446 | DirDef *p = parent();␊ |
447 | if (p)␊ |
448 | {␊ |
449 | p->setLevel();␊ |
450 | m_level = p->level()+1;␊ |
451 | }␊ |
452 | else␊ |
453 | {␊ |
454 | m_level = 0;␊ |
455 | }␊ |
456 | }␊ |
457 | }␊ |
458 | ␊ |
459 | /** Add as "uses" dependency between \a this dir and \a dir,␊ |
460 | * that was caused by a dependency on file \a fd.␊ |
461 | */ ␊ |
462 | void DirDef::addUsesDependency(DirDef *dir,FileDef *srcFd,␊ |
463 | FileDef *dstFd,bool inherited)␊ |
464 | {␊ |
465 | if (this==dir) return; // do not add self-dependencies␊ |
466 | //static int count=0;␊ |
467 | //printf(" %d add dependency %s->%s due to %s->%s\n",␊ |
468 | // count++,shortName().data(),␊ |
469 | // dir->shortName().data(),␊ |
470 | // srcFd->name().data(),␊ |
471 | // dstFd->name().data());␊ |
472 | ␊ |
473 | // levels match => add direct dependency␊ |
474 | bool added=FALSE;␊ |
475 | UsedDir *usedDir = m_usedDirs->find(dir->getOutputFileBase());␊ |
476 | if (usedDir) // dir dependency already present␊ |
477 | {␊ |
478 | FilePair *usedPair = usedDir->findFilePair(␊ |
479 | srcFd->getOutputFileBase()+dstFd->getOutputFileBase());␊ |
480 | if (usedPair==0) // new file dependency␊ |
481 | {␊ |
482 | //printf(" => new file\n");␊ |
483 | usedDir->addFileDep(srcFd,dstFd); ␊ |
484 | added=TRUE;␊ |
485 | }␊ |
486 | else␊ |
487 | {␊ |
488 | // dir & file dependency already added␊ |
489 | }␊ |
490 | }␊ |
491 | else // new directory dependency␊ |
492 | {␊ |
493 | //printf(" => new file\n");␊ |
494 | usedDir = new UsedDir(dir,inherited);␊ |
495 | usedDir->addFileDep(srcFd,dstFd); ␊ |
496 | m_usedDirs->insert(dir->getOutputFileBase(),usedDir);␊ |
497 | added=TRUE;␊ |
498 | }␊ |
499 | if (added)␊ |
500 | {␊ |
501 | if (dir->parent())␊ |
502 | {␊ |
503 | // add relation to parent of used dir␊ |
504 | addUsesDependency(dir->parent(),srcFd,dstFd,inherited);␊ |
505 | }␊ |
506 | if (parent())␊ |
507 | {␊ |
508 | // add relation for the parent of this dir as well␊ |
509 | parent()->addUsesDependency(dir,srcFd,dstFd,TRUE);␊ |
510 | }␊ |
511 | }␊ |
512 | }␊ |
513 | ␊ |
514 | /** Computes the dependencies between directories␊ |
515 | */␊ |
516 | void DirDef::computeDependencies()␊ |
517 | {␊ |
518 | FileList *fl = m_fileList;␊ |
519 | if (fl) ␊ |
520 | {␊ |
521 | QListIterator<FileDef> fli(*fl);␊ |
522 | FileDef *fd;␊ |
523 | for (fli.toFirst();(fd=fli.current());++fli) // foreach file in dir dd␊ |
524 | {␊ |
525 | //printf(" File %s\n",fd->name().data());␊ |
526 | //printf("** dir=%s file=%s\n",shortName().data(),fd->name().data());␊ |
527 | QList<IncludeInfo> *ifl = fd->includeFileList();␊ |
528 | if (ifl)␊ |
529 | {␊ |
530 | QListIterator<IncludeInfo> ifli(*ifl); ␊ |
531 | IncludeInfo *ii;␊ |
532 | for (ifli.toFirst();(ii=ifli.current());++ifli) // foreach include file␊ |
533 | {␊ |
534 | //printf(" > %s\n",ii->includeName.data());␊ |
535 | //printf(" #include %s\n",ii->includeName.data());␊ |
536 | if (ii->fileDef && ii->fileDef->isLinkable()) // linkable file␊ |
537 | {␊ |
538 | DirDef *usedDir = ii->fileDef->getDirDef();␊ |
539 | if (usedDir)␊ |
540 | {␊ |
541 | // add dependency: thisDir->usedDir␊ |
542 | //static int count=0;␊ |
543 | //printf(" %d: add dependency %s->%s\n",count++,name().data(),usedDir->name().data());␊ |
544 | addUsesDependency(usedDir,fd,ii->fileDef,FALSE);␊ |
545 | }␊ |
546 | } ␊ |
547 | }␊ |
548 | }␊ |
549 | }␊ |
550 | }␊ |
551 | }␊ |
552 | ␊ |
553 | bool DirDef::isParentOf(DirDef *dir) const␊ |
554 | {␊ |
555 | if (dir->parent()==this) // this is a parent of dir ␊ |
556 | return TRUE;␊ |
557 | else if (dir->parent()) // repeat for the parent of dir␊ |
558 | return isParentOf(dir->parent()); ␊ |
559 | else␊ |
560 | return FALSE;␊ |
561 | }␊ |
562 | ␊ |
563 | bool DirDef::depGraphIsTrivial() const␊ |
564 | {␊ |
565 | return FALSE;␊ |
566 | }␊ |
567 | ␊ |
568 | //----------------------------------------------------------------------␊ |
569 | ␊ |
570 | int FilePairDict::compareItems(GCI item1,GCI item2)␊ |
571 | {␊ |
572 | FilePair *left = (FilePair*)item1;␊ |
573 | FilePair *right = (FilePair*)item2;␊ |
574 | int orderHi = stricmp(left->source()->name(),right->source()->name());␊ |
575 | int orderLo = stricmp(left->destination()->name(),right->destination()->name());␊ |
576 | return orderHi==0 ? orderLo : orderHi;␊ |
577 | }␊ |
578 | ␊ |
579 | //----------------------------------------------------------------------␊ |
580 | ␊ |
581 | UsedDir::UsedDir(DirDef *dir,bool inherited) :␊ |
582 | m_dir(dir), m_filePairs(7), m_inherited(inherited)␊ |
583 | {␊ |
584 | m_filePairs.setAutoDelete(TRUE);␊ |
585 | }␊ |
586 | ␊ |
587 | UsedDir::~UsedDir()␊ |
588 | {␊ |
589 | }␊ |
590 | ␊ |
591 | ␊ |
592 | void UsedDir::addFileDep(FileDef *srcFd,FileDef *dstFd)␊ |
593 | {␊ |
594 | m_filePairs.inSort(srcFd->getOutputFileBase()+dstFd->getOutputFileBase(),␊ |
595 | new FilePair(srcFd,dstFd));␊ |
596 | }␊ |
597 | ␊ |
598 | FilePair *UsedDir::findFilePair(const char *name)␊ |
599 | {␊ |
600 | QCString n=name;␊ |
601 | return n.isEmpty() ? 0 : m_filePairs.find(n);␊ |
602 | }␊ |
603 | ␊ |
604 | DirDef *DirDef::createNewDir(const char *path)␊ |
605 | {␊ |
606 | ASSERT(path!=0);␊ |
607 | DirDef *dir = Doxygen::directories->find(path);␊ |
608 | if (dir==0) // new dir␊ |
609 | {␊ |
610 | //printf("Adding new dir %s\n",path);␊ |
611 | dir = new DirDef(path);␊ |
612 | //printf("createNewDir %s short=%s\n",path,dir->shortName().data());␊ |
613 | Doxygen::directories->inSort(path,dir);␊ |
614 | }␊ |
615 | return dir;␊ |
616 | }␊ |
617 | ␊ |
618 | bool DirDef::matchPath(const QCString &path,QStrList &l)␊ |
619 | {␊ |
620 | const char *s=l.first();␊ |
621 | while (s)␊ |
622 | {␊ |
623 | QCString prefix = s;␊ |
624 | if (stricmp(prefix.left(path.length()),path)==0) // case insensitive compare␊ |
625 | {␊ |
626 | return TRUE;␊ |
627 | }␊ |
628 | s = l.next();␊ |
629 | }␊ |
630 | return FALSE;␊ |
631 | }␊ |
632 | ␊ |
633 | /*! strip part of \a path if it matches␊ |
634 | * one of the paths in the Config_getList("STRIP_FROM_PATH") list␊ |
635 | */␊ |
636 | DirDef *DirDef::mergeDirectoryInTree(const QCString &path)␊ |
637 | {␊ |
638 | //printf("DirDef::mergeDirectoryInTree(%s)\n",path.data());␊ |
639 | int p=0,i=0;␊ |
640 | DirDef *dir=0;␊ |
641 | while ((i=path.find('/',p))!=-1)␊ |
642 | {␊ |
643 | QCString part=path.left(i+1);␊ |
644 | if (!matchPath(part,Config_getList("STRIP_FROM_PATH")) && part!="/")␊ |
645 | {␊ |
646 | dir=createNewDir(part); ␊ |
647 | }␊ |
648 | p=i+1;␊ |
649 | }␊ |
650 | return dir;␊ |
651 | }␊ |
652 | ␊ |
653 | void DirDef::writeDepGraph(FTextStream &t)␊ |
654 | {␊ |
655 | writeDotDirDepGraph(t,this);␊ |
656 | }␊ |
657 | ␊ |
658 | //----------------------------------------------------------------------␊ |
659 | ␊ |
660 | static void writePartialDirPath(OutputList &ol,const DirDef *root,const DirDef *target)␊ |
661 | {␊ |
662 | if (target->parent()!=root) ␊ |
663 | {␊ |
664 | writePartialDirPath(ol,root,target->parent());␊ |
665 | ol.writeString(" / ");␊ |
666 | }␊ |
667 | ol.writeObjectLink(target->getReference(),target->getOutputFileBase(),0,target->shortName());␊ |
668 | }␊ |
669 | ␊ |
670 | static void writePartialFilePath(OutputList &ol,const DirDef *root,const FileDef *fd)␊ |
671 | {␊ |
672 | if (fd->getDirDef() && fd->getDirDef()!=root)␊ |
673 | {␊ |
674 | writePartialDirPath(ol,root,fd->getDirDef());␊ |
675 | ol.writeString(" / ");␊ |
676 | }␊ |
677 | if (fd->isLinkable())␊ |
678 | {␊ |
679 | ol.writeObjectLink(fd->getReference(),fd->getOutputFileBase(),0,fd->name());␊ |
680 | }␊ |
681 | else␊ |
682 | {␊ |
683 | ol.startBold();␊ |
684 | ol.docify(fd->name());␊ |
685 | ol.endBold();␊ |
686 | }␊ |
687 | }␊ |
688 | ␊ |
689 | void DirRelation::writeDocumentation(OutputList &ol)␊ |
690 | {␊ |
691 | static bool generateTreeView = Config_getBool("GENERATE_TREEVIEW");␊ |
692 | ol.pushGeneratorState();␊ |
693 | ol.disableAllBut(OutputGenerator::Html);␊ |
694 | ␊ |
695 | QCString shortTitle=theTranslator->trDirRelation(␊ |
696 | m_src->shortName()+" → "+␊ |
697 | m_dst->dir()->shortName());␊ |
698 | QCString title=theTranslator->trDirRelation(␊ |
699 | m_src->displayName()+" -> "+␊ |
700 | m_dst->dir()->shortName());␊ |
701 | startFile(ol,getOutputFileBase(),getOutputFileBase(),␊ |
702 | title,HLI_None,!generateTreeView,m_src->getOutputFileBase());␊ |
703 | ␊ |
704 | if (!generateTreeView)␊ |
705 | {␊ |
706 | // write navigation path␊ |
707 | m_src->writeNavigationPath(ol);␊ |
708 | ol.endQuickIndices();␊ |
709 | }␊ |
710 | ol.startContents();␊ |
711 | ␊ |
712 | ol.writeString("<h3>"+shortTitle+"</h3>");␊ |
713 | ol.writeString("<table class=\"dirtab\">");␊ |
714 | ol.writeString("<tr class=\"dirtab\">");␊ |
715 | ol.writeString("<th class=\"dirtab\">");␊ |
716 | ol.parseText(theTranslator->trFileIn(m_src->pathFragment()));␊ |
717 | ol.writeString("</th>");␊ |
718 | ol.writeString("<th class=\"dirtab\">");␊ |
719 | ol.parseText(theTranslator->trIncludesFileIn(m_dst->dir()->pathFragment()));␊ |
720 | ol.writeString("</th>");␊ |
721 | ol.writeString("</tr>");␊ |
722 | ␊ |
723 | SDict<FilePair>::Iterator fpi(m_dst->filePairs());␊ |
724 | FilePair *fp;␊ |
725 | for (fpi.toFirst();(fp=fpi.current());++fpi)␊ |
726 | {␊ |
727 | ol.writeString("<tr class=\"dirtab\">");␊ |
728 | ol.writeString("<td class=\"dirtab\">");␊ |
729 | writePartialFilePath(ol,m_src,fp->source());␊ |
730 | ol.writeString("</td>");␊ |
731 | ol.writeString("<td class=\"dirtab\">");␊ |
732 | writePartialFilePath(ol,m_dst->dir(),fp->destination());␊ |
733 | ol.writeString("</td>");␊ |
734 | ol.writeString("</tr>");␊ |
735 | }␊ |
736 | ol.writeString("</table>");␊ |
737 | ␊ |
738 | ol.endContents();␊ |
739 | ␊ |
740 | if (generateTreeView)␊ |
741 | {␊ |
742 | m_src->writeNavigationPath(ol);␊ |
743 | }␊ |
744 | ␊ |
745 | endFile(ol,TRUE); ␊ |
746 | ol.popGeneratorState();␊ |
747 | }␊ |
748 | ␊ |
749 | //----------------------------------------------------------------------␊ |
750 | // external functions␊ |
751 | ␊ |
752 | void buildDirectories()␊ |
753 | {␊ |
754 | // for each input file␊ |
755 | FileNameListIterator fnli(*Doxygen::inputNameList); ␊ |
756 | FileName *fn;␊ |
757 | for (fnli.toFirst();(fn=fnli.current());++fnli)␊ |
758 | {␊ |
759 | FileNameIterator fni(*fn);␊ |
760 | FileDef *fd;␊ |
761 | for (;(fd=fni.current());++fni)␊ |
762 | {␊ |
763 | //printf("buildDirectories %s\n",fd->name().data());␊ |
764 | if (fd->getReference().isEmpty() && !fd->isDocumentationFile())␊ |
765 | {␊ |
766 | DirDef *dir;␊ |
767 | if ((dir=Doxygen::directories->find(fd->getPath()))==0) // new directory␊ |
768 | {␊ |
769 | dir = DirDef::mergeDirectoryInTree(fd->getPath());␊ |
770 | }␊ |
771 | if (dir) dir->addFile(fd);␊ |
772 | }␊ |
773 | else␊ |
774 | {␊ |
775 | // do something for file imported via tag files.␊ |
776 | }␊ |
777 | }␊ |
778 | }␊ |
779 | ␊ |
780 | //DirDef *root = new DirDef("root:");␊ |
781 | // compute relations between directories => introduce container dirs.␊ |
782 | DirDef *dir;␊ |
783 | DirSDict::Iterator sdi(*Doxygen::directories);␊ |
784 | for (sdi.toFirst();(dir=sdi.current());++sdi)␊ |
785 | {␊ |
786 | //printf("New dir %s\n",dir->displayName().data());␊ |
787 | QCString name = dir->name();␊ |
788 | int i=name.findRev('/',name.length()-2);␊ |
789 | if (i>0)␊ |
790 | {␊ |
791 | DirDef *parent = Doxygen::directories->find(name.left(i+1));␊ |
792 | //if (parent==0) parent=root;␊ |
793 | if (parent) ␊ |
794 | {␊ |
795 | parent->addSubDir(dir); ␊ |
796 | //printf("DirDef::addSubdir(): Adding subdir\n%s to\n%s\n",␊ |
797 | // dir->displayName().data(), parent->displayName().data());␊ |
798 | }␊ |
799 | }␊ |
800 | }␊ |
801 | }␊ |
802 | ␊ |
803 | void computeDirDependencies()␊ |
804 | {␊ |
805 | DirDef *dir;␊ |
806 | DirSDict::Iterator sdi(*Doxygen::directories);␊ |
807 | // compute nesting level for each directory␊ |
808 | for (sdi.toFirst();(dir=sdi.current());++sdi)␊ |
809 | {␊ |
810 | dir->setLevel();␊ |
811 | }␊ |
812 | // compute uses dependencies between directories␊ |
813 | for (sdi.toFirst();(dir=sdi.current());++sdi)␊ |
814 | {␊ |
815 | //printf("computeDependencies for %s: #dirs=%d\n",dir->name().data(),Doxygen::directories.count());␊ |
816 | dir->computeDependencies();␊ |
817 | }␊ |
818 | ␊ |
819 | #if 0␊ |
820 | printf("-------------------------------------------------------------\n");␊ |
821 | // print dependencies (for debugging)␊ |
822 | for (sdi.toFirst();(dir=sdi.current());++sdi)␊ |
823 | {␊ |
824 | if (dir->usedDirs())␊ |
825 | {␊ |
826 | QDictIterator<UsedDir> udi(*dir->usedDirs());␊ |
827 | UsedDir *usedDir;␊ |
828 | for (udi.toFirst();(usedDir=udi.current());++udi)␊ |
829 | {␊ |
830 | printf("%s depends on %s due to ",␊ |
831 | dir->shortName().data(),usedDir->dir()->shortName().data());␊ |
832 | QDictIterator<FileDef> fdi(usedDir->files());␊ |
833 | FileDef *fd;␊ |
834 | for (fdi.toFirst();(fd=fdi.current());++fdi)␊ |
835 | {␊ |
836 | printf("%s ",fd->name().data());␊ |
837 | }␊ |
838 | printf("\n");␊ |
839 | }␊ |
840 | }␊ |
841 | }␊ |
842 | printf("^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^\n");␊ |
843 | #endif␊ |
844 | }␊ |
845 | ␊ |
846 | #if 0␊ |
847 | void writeDirDependencyGraph(const char *dirName)␊ |
848 | {␊ |
849 | QString path;␊ |
850 | DirDef *dir;␊ |
851 | DirSDict::Iterator sdi(*Doxygen::directories);␊ |
852 | QFile htmlPage(QCString(dirName)+"/dirdeps.html");␊ |
853 | if (htmlPage.open(IO_WriteOnly))␊ |
854 | {␊ |
855 | QTextStream out(&htmlPage);␊ |
856 | out << "<html><body>";␊ |
857 | for (sdi.toFirst();(dir=sdi.current());++sdi)␊ |
858 | {␊ |
859 | path=dirName;␊ |
860 | path+="/";␊ |
861 | path+=dir->getOutputFileBase();␊ |
862 | path+="_dep.dot";␊ |
863 | out << "<h4>" << dir->displayName() << "</h4>" << endl;␊ |
864 | out << "<img src=\"" << dir->getOutputFileBase() << "_dep.gif\">" << endl;␊ |
865 | QFile f(path);␊ |
866 | if (f.open(IO_WriteOnly))␊ |
867 | {␊ |
868 | QTextStream t(&f);␊ |
869 | dir->writeDepGraph(t);␊ |
870 | }␊ |
871 | f.close();␊ |
872 | ␊ |
873 | QCString imgExt = Config_getEnum("DOT_IMAGE_FORMAT");␊ |
874 | QCString outFile = QCString(dirName)+"/"+␊ |
875 | dir->getOutputFileBase()+"_dep."+imgExt; ␊ |
876 | DotRunner dotRun(path);␊ |
877 | dotRun.addJob(imgExt,outFile);␊ |
878 | dotRun.run();␊ |
879 | ␊ |
880 | //QCString dotArgs(4096);␊ |
881 | //dotArgs.sprintf("%s -Tgif -o %s",path.data(),outFile.data());␊ |
882 | //if (portable_system(Config_getString("DOT_PATH")+"dot",dotArgs,FALSE)!=0)␊ |
883 | //{␊ |
884 | // err("Problems running dot. Check your installation!\n");␊ |
885 | //}␊ |
886 | }␊ |
887 | out << "</body></html>";␊ |
888 | }␊ |
889 | htmlPage.close();␊ |
890 | }␊ |
891 | #endif␊ |
892 | ␊ |
893 | void generateDirDocs(OutputList &ol)␊ |
894 | {␊ |
895 | DirDef *dir;␊ |
896 | DirSDict::Iterator sdi(*Doxygen::directories);␊ |
897 | for (sdi.toFirst();(dir=sdi.current());++sdi)␊ |
898 | {␊ |
899 | dir->writeDocumentation(ol);␊ |
900 | }␊ |
901 | if (Config_getBool("DIRECTORY_GRAPH"))␊ |
902 | {␊ |
903 | SDict<DirRelation>::Iterator rdi(Doxygen::dirRelations);␊ |
904 | DirRelation *dr;␊ |
905 | for (rdi.toFirst();(dr=rdi.current());++rdi)␊ |
906 | {␊ |
907 | dr->writeDocumentation(ol);␊ |
908 | }␊ |
909 | }␊ |
910 | }␊ |
911 | ␊ |
912 |