doxygen.cpp
Go to the documentation of this file.
1 /******************************************************************************
2  *
3  * Copyright (C) 1997-2015 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 <locale.h>
17 
18 #include <qfileinfo.h>
19 #include <qfile.h>
20 #include <qdir.h>
21 #include <qdict.h>
22 #include <qregexp.h>
23 #include <qstrlist.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <sys/stat.h>
27 #include <qtextcodec.h>
28 #include <errno.h>
29 #include <qptrdict.h>
30 #include <qtextstream.h>
31 
32 #include "version.h"
33 #include "doxygen.h"
34 #include "scanner.h"
35 #include "entry.h"
36 #include "index.h"
37 #include "logos.h"
38 #include "message.h"
39 #include "config.h"
40 #include "util.h"
41 #include "pre.h"
42 #include "tagreader.h"
43 #include "dot.h"
44 #include "msc.h"
45 #include "docparser.h"
46 #include "dirdef.h"
47 #include "outputlist.h"
48 #include "declinfo.h"
49 #include "htmlgen.h"
50 #include "latexgen.h"
51 #include "mangen.h"
52 #include "language.h"
53 #include "debug.h"
54 #include "htmlhelp.h"
55 #include "qhp.h"
56 #include "ftvhelp.h"
57 #include "defargs.h"
58 #include "rtfgen.h"
59 #include "sqlite3gen.h"
60 #include "xmlgen.h"
61 #include "docbookgen.h"
62 #include "defgen.h"
63 #include "perlmodgen.h"
64 #include "reflist.h"
65 #include "pagedef.h"
66 #include "bufstr.h"
67 #include "commentcnv.h"
68 #include "cmdmapper.h"
69 #include "searchindex.h"
70 #include "parserintf.h"
71 #include "htags.h"
72 #include "pyscanner.h"
73 #include "fortranscanner.h"
74 #include "xmlscanner.h"
75 #include "tclscanner.h"
76 #include "code.h"
77 #include "objcache.h"
78 #include "store.h"
79 #include "marshal.h"
80 #include "portable.h"
81 #include "vhdljjparser.h"
82 #include "vhdldocgen.h"
83 #include "eclipsehelp.h"
84 #include "cite.h"
85 #include "filestorage.h"
86 #include "markdown.h"
87 #include "arguments.h"
88 #include "memberlist.h"
89 #include "layout.h"
90 #include "groupdef.h"
91 #include "classlist.h"
92 #include "namespacedef.h"
93 #include "filename.h"
94 #include "membername.h"
95 #include "membergroup.h"
96 #include "docsets.h"
97 #include "formula.h"
98 #include "settings.h"
99 #include "context.h"
100 #include "fileparser.h"
101 
102 // provided by the generated file resources.cpp
103 extern void initResources();
104 
105 #define RECURSE_ENTRYTREE(func,var) \
106  do { if (var->children()) { \
107  EntryNavListIterator eli(*var->children()); \
108  for (;eli.current();++eli) func(eli.current()); \
109  } } while(0)
110 
111 
112 #if !defined(_WIN32) || defined(__CYGWIN__)
113 #include <signal.h>
114 #define HAS_SIGNALS
115 #endif
116 
117 // globally accessible variables
123 FileNameList *Doxygen::inputNameList = 0; // all input files
126 FormulaList *Doxygen::formulaList = 0; // all formulas
127 FormulaDict *Doxygen::formulaDict = 0; // all formulas
128 FormulaDict *Doxygen::formulaNameDict = 0; // the label name of all formulas
131 SectionDict *Doxygen::sectionDict = 0; // all page sections
132 CiteDict *Doxygen::citeDict=0; // database of bibliographic references
133 StringDict Doxygen::aliasDict(257); // aliases
134 QDict<void> Doxygen::inputPaths(1009);
135 FileNameDict *Doxygen::includeNameDict = 0; // include names
136 FileNameDict *Doxygen::exampleNameDict = 0; // examples
137 FileNameDict *Doxygen::imageNameDict = 0; // images
138 FileNameDict *Doxygen::dotFileNameDict = 0; // dot files
139 FileNameDict *Doxygen::mscFileNameDict = 0; // msc files
140 FileNameDict *Doxygen::diaFileNameDict = 0; // dia files
141 StringDict Doxygen::namespaceAliasDict(257); // all namespace aliases
142 StringDict Doxygen::tagDestinationDict(257); // all tag locations
143 QDict<void> Doxygen::expandAsDefinedDict(257); // all macros that should be expanded
144 QIntDict<MemberGroupInfo> Doxygen::memGrpInfoDict(1009); // dictionary of the member groups heading
146 bool Doxygen::insideMainPage = FALSE; // are we generating docs for the main page?
148 QDict<RefList> *Doxygen::xrefLists = new QDict<RefList>; // dictionary of cross-referenced item lists
152 QDict<DefinitionIntf> *Doxygen::symbolMap = 0;
153 QDict<Definition> *Doxygen::clangUsrMap = 0;
155 QDict<int> * Doxygen::htmlDirMap = 0;
173 
174 // locally accessible globals
175 static QDict<EntryNav> g_classEntries(1009);
177 static QDict<void> g_compoundKeywordDict(7); // keywords recognised as compounds
178 static OutputList *g_outputList = 0; // list of output generating objects
179 static QDict<FileDef> g_usingDeclarations(1009); // used classes
180 static FileStorage *g_storage = 0;
181 static bool g_successfulRun = FALSE;
182 static bool g_dumpSymbolMap = FALSE;
184 
185 void clearAll()
186 {
187  g_inputFiles.clear();
188  //g_excludeNameDict.clear();
189  //delete g_outputList; g_outputList=0;
190 
191  Doxygen::classSDict->clear();
192  Doxygen::namespaceSDict->clear();
193  Doxygen::pageSDict->clear();
194  Doxygen::exampleSDict->clear();
195  Doxygen::inputNameList->clear();
196  Doxygen::formulaList->clear();
197  Doxygen::sectionDict->clear();
198  Doxygen::inputNameDict->clear();
199  Doxygen::includeNameDict->clear();
200  Doxygen::exampleNameDict->clear();
201  Doxygen::imageNameDict->clear();
202  Doxygen::dotFileNameDict->clear();
203  Doxygen::mscFileNameDict->clear();
204  Doxygen::diaFileNameDict->clear();
205  Doxygen::formulaDict->clear();
206  Doxygen::formulaNameDict->clear();
208  delete Doxygen::citeDict;
209  delete Doxygen::mainPage; Doxygen::mainPage=0;
210 }
211 
213 {
214  public:
215  Statistics() { stats.setAutoDelete(TRUE); }
216  void begin(const char *name)
217  {
218  msg(name);
219  stat *entry= new stat(name,0);
220  stats.append(entry);
221  time.restart();
222  }
223  void end()
224  {
225  stats.getLast()->elapsed=((double)time.elapsed())/1000.0;
226  }
227  void print()
228  {
229  bool restore=FALSE;
231  {
232  Debug::clearFlag("time");
233  restore=TRUE;
234  }
235  msg("----------------------\n");
237  stat *s;
238  for ( sli.toFirst(); (s=sli.current()); ++sli )
239  {
240  msg("Spent %.3f seconds in %s",s->elapsed,s->name);
241  }
242  if (restore) Debug::setFlag("time");
243  }
244  private:
245  struct stat
246  {
247  const char *name;
248  double elapsed;
249  stat() : name(NULL),elapsed(0) {}
250  stat(const char *n, double el) : name(n),elapsed(el) {}
251  };
254 } g_s;
255 
256 
258 {
259  fprintf(stderr,"--- inputNameDict stats ----\n");
260  Doxygen::inputNameDict->statistics();
261  fprintf(stderr,"--- includeNameDict stats ----\n");
262  Doxygen::includeNameDict->statistics();
263  fprintf(stderr,"--- exampleNameDict stats ----\n");
264  Doxygen::exampleNameDict->statistics();
265  fprintf(stderr,"--- imageNameDict stats ----\n");
266  Doxygen::imageNameDict->statistics();
267  fprintf(stderr,"--- dotFileNameDict stats ----\n");
268  Doxygen::dotFileNameDict->statistics();
269  fprintf(stderr,"--- mscFileNameDict stats ----\n");
270  Doxygen::mscFileNameDict->statistics();
271  fprintf(stderr,"--- diaFileNameDict stats ----\n");
272  Doxygen::diaFileNameDict->statistics();
273  //fprintf(stderr,"--- g_excludeNameDict stats ----\n");
274  //g_excludeNameDict.statistics();
275  fprintf(stderr,"--- aliasDict stats ----\n");
276  Doxygen::aliasDict.statistics();
277  fprintf(stderr,"--- typedefDict stats ----\n");
278  fprintf(stderr,"--- namespaceAliasDict stats ----\n");
279  Doxygen::namespaceAliasDict.statistics();
280  fprintf(stderr,"--- formulaDict stats ----\n");
281  Doxygen::formulaDict->statistics();
282  fprintf(stderr,"--- formulaNameDict stats ----\n");
283  Doxygen::formulaNameDict->statistics();
284  fprintf(stderr,"--- tagDestinationDict stats ----\n");
285  Doxygen::tagDestinationDict.statistics();
286  fprintf(stderr,"--- g_compoundKeywordDict stats ----\n");
287  g_compoundKeywordDict.statistics();
288  fprintf(stderr,"--- expandAsDefinedDict stats ----\n");
289  Doxygen::expandAsDefinedDict.statistics();
290  fprintf(stderr,"--- memGrpInfoDict stats ----\n");
292 }
293 
294 
295 
296 static void addMemberDocs(EntryNav *rootNav,MemberDef *md, const char *funcDecl,
297  ArgumentList *al,bool over_load,NamespaceSDict *nl=0);
298 static void findMember(EntryNav *rootNav,
299  QCString funcDecl,
300  bool overloaded,
301  bool isFunc
302  );
303 
305 {
309 };
310 
311 static bool findClassRelation(
312  EntryNav *rootNav,
313  Definition *context,
314  ClassDef *cd,
315  BaseInfo *bi,
316  QDict<int> *templateNames,
317  /*bool insertUndocumented*/
319  bool isArtificial
320  );
321 
322 /** A struct contained the data for an STL class */
323 struct STLInfo
324 {
325  const char *className;
326  const char *baseClass1;
327  const char *baseClass2;
328  const char *templType1;
329  const char *templName1;
330  const char *templType2;
331  const char *templName2;
333  bool iterators;
334 };
335 
336 static STLInfo g_stlinfo[] =
337 {
338  // className baseClass1 baseClass2 templType1 templName1 templType2 templName2 virtInheritance // iterators
339  { "allocator", 0, 0, "T", "elements", 0, 0, FALSE, FALSE },
340  { "array", 0, 0, "T", "elements", 0, 0, FALSE, FALSE }, // C++11
341  { "auto_ptr", 0, 0, "T", "ptr", 0, 0, FALSE, FALSE }, // deprecated
342  { "smart_ptr", 0, 0, "T", "ptr", 0, 0, FALSE, FALSE }, // C++11
343  { "unique_ptr", 0, 0, "T", "ptr", 0, 0, FALSE, FALSE }, // C++11
344  { "weak_ptr", 0, 0, "T", "ptr", 0, 0, FALSE, FALSE }, // C++11
345  { "ios_base", 0, 0, 0, 0, 0, 0, FALSE, FALSE }, // C++11
346  { "error_code", 0, 0, 0, 0, 0, 0, FALSE, FALSE }, // C++11
347  { "error_category", 0, 0, 0, 0, 0, 0, FALSE, FALSE }, // C++11
348  { "system_error", 0, 0, 0, 0, 0, 0, FALSE, FALSE }, // C++11
349  { "error_condition", 0, 0, 0, 0, 0, 0, FALSE, FALSE }, // C++11
350  { "thread", 0, 0, 0, 0, 0, 0, FALSE, FALSE }, // C++11
351  { "basic_ios", "ios_base", 0, "Char", 0, 0, 0, FALSE, FALSE },
352  { "basic_istream", "basic_ios<Char>", 0, "Char", 0, 0, 0, TRUE, FALSE },
353  { "basic_ostream", "basic_ios<Char>", 0, "Char", 0, 0, 0, TRUE, FALSE },
354  { "basic_iostream", "basic_istream<Char>", "basic_ostream<Char>", "Char", 0, 0, 0, FALSE, FALSE },
355  { "basic_ifstream", "basic_istream<Char>", 0, "Char", 0, 0, 0, FALSE, FALSE },
356  { "basic_ofstream", "basic_ostream<Char>", 0, "Char", 0, 0, 0, FALSE, FALSE },
357  { "basic_fstream", "basic_iostream<Char>", 0, "Char", 0, 0, 0, FALSE, FALSE },
358  { "basic_istringstream", "basic_istream<Char>", 0, "Char", 0, 0, 0, FALSE, FALSE },
359  { "basic_ostringstream", "basic_ostream<Char>", 0, "Char", 0, 0, 0, FALSE, FALSE },
360  { "basic_stringstream", "basic_iostream<Char>", 0, "Char", 0, 0, 0, FALSE, FALSE },
361  { "ios", "basic_ios<char>", 0, 0, 0, 0, 0, FALSE, FALSE },
362  { "wios", "basic_ios<wchar_t>", 0, 0, 0, 0, 0, FALSE, FALSE },
363  { "istream", "basic_istream<char>", 0, 0, 0, 0, 0, FALSE, FALSE },
364  { "wistream", "basic_istream<wchar_t>", 0, 0, 0, 0, 0, FALSE, FALSE },
365  { "ostream", "basic_ostream<char>", 0, 0, 0, 0, 0, FALSE, FALSE },
366  { "wostream", "basic_ostream<wchar_t>", 0, 0, 0, 0, 0, FALSE, FALSE },
367  { "ifstream", "basic_ifstream<char>", 0, 0, 0, 0, 0, FALSE, FALSE },
368  { "wifstream", "basic_ifstream<wchar_t>", 0, 0, 0, 0, 0, FALSE, FALSE },
369  { "ofstream", "basic_ofstream<char>", 0, 0, 0, 0, 0, FALSE, FALSE },
370  { "wofstream", "basic_ofstream<wchar_t>", 0, 0, 0, 0, 0, FALSE, FALSE },
371  { "fstream", "basic_fstream<char>", 0, 0, 0, 0, 0, FALSE, FALSE },
372  { "wfstream", "basic_fstream<wchar_t>", 0, 0, 0, 0, 0, FALSE, FALSE },
373  { "istringstream", "basic_istringstream<char>", 0, 0, 0, 0, 0, FALSE, FALSE },
374  { "wistringstream", "basic_istringstream<wchar_t>", 0, 0, 0, 0, 0, FALSE, FALSE },
375  { "ostringstream", "basic_ostringstream<char>", 0, 0, 0, 0, 0, FALSE, FALSE },
376  { "wostringstream", "basic_ostringstream<wchar_t>", 0, 0, 0, 0, 0, FALSE, FALSE },
377  { "stringstream", "basic_stringstream<char>", 0, 0, 0, 0, 0, FALSE, FALSE },
378  { "wstringstream", "basic_stringstream<wchar_t>", 0, 0, 0, 0, 0, FALSE, FALSE },
379  { "basic_string", 0, 0, "Char", 0, 0, 0, FALSE, TRUE },
380  { "string", "basic_string<char>", 0, 0, 0, 0, 0, FALSE, TRUE },
381  { "wstring", "basic_string<wchar_t>", 0, 0, 0, 0, 0, FALSE, TRUE },
382  { "complex", 0, 0, 0, 0, 0, 0, FALSE, FALSE },
383  { "bitset", 0, 0, "Bits", 0, 0, 0, FALSE, FALSE },
384  { "deque", 0, 0, "T", "elements", 0, 0, FALSE, TRUE },
385  { "list", 0, 0, "T", "elements", 0, 0, FALSE, TRUE },
386  { "forward_list", 0, 0, "T", "elements", 0, 0, FALSE, TRUE }, // C++11
387  { "map", 0, 0, "K", "keys", "T", "elements", FALSE, TRUE },
388  { "unordered_map", 0, 0, "K", "keys", "T", "elements", FALSE, TRUE }, // C++11
389  { "multimap", 0, 0, "K", "keys", "T", "elements", FALSE, TRUE },
390  { "unordered_multimap", 0, 0, "K", "keys", "T", "elements", FALSE, TRUE }, // C++11
391  { "set", 0, 0, "K", "keys", 0, 0, FALSE, TRUE },
392  { "unordered_set", 0, 0, "K", "keys", 0, 0, FALSE, TRUE }, // C++11
393  { "multiset", 0, 0, "K", "keys", 0, 0, FALSE, TRUE },
394  { "unordered_multiset", 0, 0, "K", "keys", 0, 0, FALSE, TRUE }, // C++11
395  { "vector", 0, 0, "T", "elements", 0, 0, FALSE, TRUE },
396  { "queue", 0, 0, "T", "elements", 0, 0, FALSE, FALSE },
397  { "priority_queue", 0, 0, "T", "elements", 0, 0, FALSE, FALSE },
398  { "stack", 0, 0, "T", "elements", 0, 0, FALSE, FALSE },
399  { "valarray", 0, 0, "T", "elements", 0, 0, FALSE, FALSE },
400  { "exception", 0, 0, 0, 0, 0, 0, FALSE, FALSE },
401  { "bad_alloc", "exception", 0, 0, 0, 0, 0, FALSE, FALSE },
402  { "bad_cast", "exception", 0, 0, 0, 0, 0, FALSE, FALSE },
403  { "bad_typeid", "exception", 0, 0, 0, 0, 0, FALSE, FALSE },
404  { "logic_error", "exception", 0, 0, 0, 0, 0, FALSE, FALSE },
405  { "ios_base::failure", "exception", 0, 0, 0, 0, 0, FALSE, FALSE },
406  { "runtime_error", "exception", 0, 0, 0, 0, 0, FALSE, FALSE },
407  { "bad_exception", "exception", 0, 0, 0, 0, 0, FALSE, FALSE },
408  { "domain_error", "logic_error", 0, 0, 0, 0, 0, FALSE, FALSE },
409  { "invalid_argument", "logic_error", 0, 0, 0, 0, 0, FALSE, FALSE },
410  { "length_error", "logic_error", 0, 0, 0, 0, 0, FALSE, FALSE },
411  { "out_of_range", "logic_error", 0, 0, 0, 0, 0, FALSE, FALSE },
412  { "range_error", "runtime_error", 0, 0, 0, 0, 0, FALSE, FALSE },
413  { "overflow_error", "runtime_error", 0, 0, 0, 0, 0, FALSE, FALSE },
414  { "underflow_error", "runtime_error", 0, 0, 0, 0, 0, FALSE, FALSE },
415  { 0, 0, 0, 0, 0, 0, 0, FALSE, FALSE }
416 };
417 
418 static void addSTLMember(EntryNav *rootNav,const char *type,const char *name)
419 {
420  Entry *memEntry = new Entry;
421  memEntry->name = name;
422  memEntry->type = type;
423  memEntry->protection = Public;
424  memEntry->section = Entry::VARIABLE_SEC;
425  memEntry->brief = "STL member";
426  memEntry->hidden = FALSE;
427  memEntry->artificial = TRUE;
428  //memEntry->parent = root;
429  //root->addSubEntry(memEntry);
430  EntryNav *memEntryNav = new EntryNav(rootNav,memEntry);
431  memEntryNav->setEntry(memEntry);
432  rootNav->addChild(memEntryNav);
433 }
434 
435 static void addSTLIterator(EntryNav *classEntryNav,const char *name)
436 {
437  Entry *iteratorClassEntry = new Entry;
438  iteratorClassEntry->fileName = "[STL]";
439  iteratorClassEntry->startLine = 1;
440  iteratorClassEntry->name = name;
441  iteratorClassEntry->section = Entry::CLASS_SEC;
442  iteratorClassEntry->brief = "STL iterator class";
443  iteratorClassEntry->hidden = FALSE;
444  iteratorClassEntry->artificial= TRUE;
445  EntryNav *iteratorClassEntryNav = new EntryNav(classEntryNav,iteratorClassEntry);
446  iteratorClassEntryNav->setEntry(iteratorClassEntry);
447  classEntryNav->addChild(iteratorClassEntryNav);
448 }
449 
450 
451 static void addSTLClasses(EntryNav *rootNav)
452 {
453  Entry *namespaceEntry = new Entry;
454  namespaceEntry->fileName = "[STL]";
455  namespaceEntry->startLine = 1;
456  //namespaceEntry->parent = rootNav->entry();
457  namespaceEntry->name = "std";
458  namespaceEntry->section = Entry::NAMESPACE_SEC;
459  namespaceEntry->brief = "STL namespace";
460  namespaceEntry->hidden = FALSE;
461  namespaceEntry->artificial= TRUE;
462  //root->addSubEntry(namespaceEntry);
463  EntryNav *namespaceEntryNav = new EntryNav(rootNav,namespaceEntry);
464  namespaceEntryNav->setEntry(namespaceEntry);
465  rootNav->addChild(namespaceEntryNav);
466 
468  while (info->className)
469  {
470  //printf("Adding STL class %s\n",info->className);
471  QCString fullName = info->className;
472  fullName.prepend("std::");
473 
474  // add fake Entry for the class
475  Entry *classEntry = new Entry;
476  classEntry->fileName = "[STL]";
477  classEntry->startLine = 1;
478  classEntry->name = fullName;
479  //classEntry->parent = namespaceEntry;
480  classEntry->section = Entry::CLASS_SEC;
481  classEntry->brief = "STL class";
482  classEntry->hidden = FALSE;
483  classEntry->artificial= TRUE;
484  //namespaceEntry->addSubEntry(classEntry);
485  EntryNav *classEntryNav = new EntryNav(namespaceEntryNav,classEntry);
486  classEntryNav->setEntry(classEntry);
487  namespaceEntryNav->addChild(classEntryNav);
488 
489  // add template arguments to class
490  if (info->templType1)
491  {
492  ArgumentList *al = new ArgumentList;
493  Argument *a=new Argument;
494  a->type="typename";
495  a->name=info->templType1;
496  al->append(a);
497  if (info->templType2) // another template argument
498  {
499  a=new Argument;
500  a->type="typename";
501  a->name=info->templType2;
502  al->append(a);
503  }
504  classEntry->tArgLists = new QList<ArgumentList>;
505  classEntry->tArgLists->setAutoDelete(TRUE);
506  classEntry->tArgLists->append(al);
507  }
508  // add member variables
509  if (info->templName1)
510  {
511  addSTLMember(classEntryNav,info->templType1,info->templName1);
512  }
513  if (info->templName2)
514  {
515  addSTLMember(classEntryNav,info->templType2,info->templName2);
516  }
517  if (fullName=="std::auto_ptr" || fullName=="std::smart_ptr" ||
518  fullName=="std::unique_ptr" || fullName=="std::weak_ptr")
519  {
520  Entry *memEntry = new Entry;
521  memEntry->name = "operator->";
522  memEntry->args = "()";
523  memEntry->type = "T*";
524  memEntry->protection = Public;
525  memEntry->section = Entry::FUNCTION_SEC;
526  memEntry->brief = "STL member";
527  memEntry->hidden = FALSE;
528  memEntry->artificial = FALSE;
529  EntryNav *memEntryNav = new EntryNav(classEntryNav,memEntry);
530  memEntryNav->setEntry(memEntry);
531  classEntryNav->addChild(memEntryNav);
532  }
533  if (info->baseClass1)
534  {
535  classEntry->extends->append(new BaseInfo(info->baseClass1,Public,info->virtualInheritance?Virtual:Normal));
536  }
537  if (info->baseClass2)
538  {
539  classEntry->extends->append(new BaseInfo(info->baseClass2,Public,info->virtualInheritance?Virtual:Normal));
540  }
541  if (info->iterators)
542  {
543  // add iterator class
544  addSTLIterator(classEntryNav,fullName+"::iterator");
545  addSTLIterator(classEntryNav,fullName+"::const_iterator");
546  addSTLIterator(classEntryNav,fullName+"::reverse_iterator");
547  addSTLIterator(classEntryNav,fullName+"::const_reverse_iterator");
548  }
549  info++;
550  }
551 }
552 
553 //----------------------------------------------------------------------------
554 
556  FileDef *fileScope,TagInfo *tagInfo);
557 
558 static void addPageToContext(PageDef *pd,EntryNav *rootNav)
559 {
560  if (rootNav->parent()) // add the page to it's scope
561  {
562  QCString scope = rootNav->parent()->name();
563  if (rootNav->parent()->section()==Entry::PACKAGEDOC_SEC)
564  {
565  scope=substitute(scope,".","::");
566  }
567  scope = stripAnonymousNamespaceScope(scope);
568  scope+="::"+pd->name();
569  Definition *d = findScopeFromQualifiedName(Doxygen::globalScope,scope,0,rootNav->tagInfo());
570  if (d)
571  {
572  pd->setPageScope(d);
573  }
574  }
575 }
576 
577 static void addRelatedPage(EntryNav *rootNav)
578 {
579  Entry *root = rootNav->entry();
580  GroupDef *gd=0;
581  QListIterator<Grouping> gli(*root->groups);
582  Grouping *g;
583  for (;(g=gli.current());++gli)
584  {
585  if (!g->groupname.isEmpty() && (gd=Doxygen::groupSDict->find(g->groupname))) break;
586  }
587  //printf("---> addRelatedPage() %s gd=%p\n",root->name.data(),gd);
588  QCString doc;
589  if (root->brief.isEmpty())
590  {
591  doc=root->doc+root->inbodyDocs;
592  }
593  else
594  {
595  doc=root->brief+"\n\n"+root->doc+root->inbodyDocs;
596  }
597  PageDef *pd = addRelatedPage(root->name,root->args,doc,root->anchors,
598  root->docFile,root->docLine,
599  root->sli,
600  gd,rootNav->tagInfo(),
601  root->lang
602  );
603  if (pd)
604  {
605  pd->setBriefDescription(root->brief,root->briefFile,root->briefLine);
606  pd->addSectionsToDefinition(root->anchors);
607  pd->setShowToc(root->stat);
608  addPageToContext(pd,rootNav);
609  }
610 }
611 
612 static void buildGroupListFiltered(EntryNav *rootNav,bool additional, bool includeExternal)
613 {
614  if (rootNav->section()==Entry::GROUPDOC_SEC && !rootNav->name().isEmpty() &&
615  ((!includeExternal && rootNav->tagInfo()==0) ||
616  ( includeExternal && rootNav->tagInfo()!=0))
617  )
618  {
619  rootNav->loadEntry(g_storage);
620  Entry *root = rootNav->entry();
621 
622  if ((root->groupDocType==Entry::GROUPDOC_NORMAL && !additional) ||
623  (root->groupDocType!=Entry::GROUPDOC_NORMAL && additional))
624  {
625  GroupDef *gd = Doxygen::groupSDict->find(root->name);
626  //printf("Processing group '%s':'%s' add=%d ext=%d gd=%p\n",
627  // root->type.data(),root->name.data(),additional,includeExternal,gd);
628 
629  if (gd)
630  {
631  if ( !gd->hasGroupTitle() )
632  {
633  gd->setGroupTitle( root->type );
634  }
635  else if ( root->type.length() > 0 && root->name != root->type && gd->groupTitle() != root->type )
636  {
637  warn( root->fileName,root->startLine,
638  "group %s: ignoring title \"%s\" that does not match old title \"%s\"\n",
639  qPrint(root->name), qPrint(root->type), qPrint(gd->groupTitle()) );
640  }
641  gd->setBriefDescription(root->brief,root->briefFile,root->briefLine);
642  gd->setDocumentation( root->doc, root->docFile, root->docLine );
643  gd->setInbodyDocumentation( root->inbodyDocs, root->inbodyFile, root->inbodyLine );
644  gd->addSectionsToDefinition(root->anchors);
645  gd->setRefItems(root->sli);
646  gd->setLanguage(root->lang);
647  }
648  else
649  {
650  if (rootNav->tagInfo())
651  {
652  gd = new GroupDef(root->fileName,root->startLine,root->name,root->type,rootNav->tagInfo()->fileName);
653  gd->setReference(rootNav->tagInfo()->tagName);
654  }
655  else
656  {
657  gd = new GroupDef(root->fileName,root->startLine,root->name,root->type);
658  }
659  gd->setBriefDescription(root->brief,root->briefFile,root->briefLine);
660  // allow empty docs for group
661  gd->setDocumentation(!root->doc.isEmpty() ? root->doc : QCString(" "),root->docFile,root->docLine,FALSE);
662  gd->setInbodyDocumentation( root->inbodyDocs, root->inbodyFile, root->inbodyLine );
663  gd->addSectionsToDefinition(root->anchors);
664  Doxygen::groupSDict->append(root->name,gd);
665  gd->setRefItems(root->sli);
666  gd->setLanguage(root->lang);
667  }
668  }
669 
670  rootNav->releaseEntry();
671  }
672  if (rootNav->children())
673  {
674  EntryNavListIterator eli(*rootNav->children());
675  EntryNav *e;
676  for (;(e=eli.current());++eli)
677  {
678  buildGroupListFiltered(e,additional,includeExternal);
679  }
680  }
681 }
682 
683 static void buildGroupList(EntryNav *rootNav)
684 {
685  // --- first process only local groups
686  // first process the @defgroups blocks
688  // then process the @addtogroup, @weakgroup blocks
690 
691  // --- then also process external groups
692  // first process the @defgroups blocks
694  // then process the @addtogroup, @weakgroup blocks
696 }
697 
698 static void findGroupScope(EntryNav *rootNav)
699 {
700  if (rootNav->section()==Entry::GROUPDOC_SEC && !rootNav->name().isEmpty() &&
701  rootNav->parent() && !rootNav->parent()->name().isEmpty())
702  {
703  GroupDef *gd;
704  if ((gd=Doxygen::groupSDict->find(rootNav->name())))
705  {
706  QCString scope = rootNav->parent()->name();
707  if (rootNav->parent()->section()==Entry::PACKAGEDOC_SEC)
708  {
709  scope=substitute(scope,".","::");
710  }
711  scope = stripAnonymousNamespaceScope(scope);
712  scope+="::"+gd->name();
713  Definition *d = findScopeFromQualifiedName(Doxygen::globalScope,scope,0,rootNav->tagInfo());
714  if (d)
715  {
716  gd->setGroupScope(d);
717  }
718  }
719  }
721 }
722 
723 static void organizeSubGroupsFiltered(EntryNav *rootNav,bool additional)
724 {
725  if (rootNav->section()==Entry::GROUPDOC_SEC && !rootNav->name().isEmpty())
726  {
727  rootNav->loadEntry(g_storage);
728  Entry *root = rootNav->entry();
729 
730  if ((root->groupDocType==Entry::GROUPDOC_NORMAL && !additional) ||
731  (root->groupDocType!=Entry::GROUPDOC_NORMAL && additional))
732  {
733  GroupDef *gd;
734  if ((gd=Doxygen::groupSDict->find(root->name)))
735  {
736  //printf("adding %s to group %s\n",root->name.data(),gd->name().data());
737  addGroupToGroups(root,gd);
738  }
739  }
740 
741  rootNav->releaseEntry();
742  }
743  if (rootNav->children())
744  {
745  EntryNavListIterator eli(*rootNav->children());
746  EntryNav *e;
747  for (;(e=eli.current());++eli)
748  {
749  organizeSubGroupsFiltered(e,additional);
750  }
751  }
752 }
753 
754 static void organizeSubGroups(EntryNav *rootNav)
755 {
756  //printf("Defining groups\n");
757  // first process the @defgroups blocks
759  //printf("Additional groups\n");
760  // then process the @addtogroup, @weakgroup blocks
762 }
763 
764 //----------------------------------------------------------------------
765 
766 static void buildFileList(EntryNav *rootNav)
767 {
768  if (((rootNav->section()==Entry::FILEDOC_SEC) ||
769  ((rootNav->section() & Entry::FILE_MASK) && Config_getBool("EXTRACT_ALL"))) &&
770  !rootNav->name().isEmpty() && !rootNav->tagInfo() // skip any file coming from tag files
771  )
772  {
773  rootNav->loadEntry(g_storage);
774  Entry *root = rootNav->entry();
775 
776  bool ambig;
777  FileDef *fd=findFileDef(Doxygen::inputNameDict,root->name,ambig);
778  //printf("**************** root->name=%s fd=%p\n",root->name.data(),fd);
779  if (fd && !ambig)
780  {
781 #if 0
782  if ((!root->doc.isEmpty() && !fd->documentation().isEmpty()) ||
783  (!root->brief.isEmpty() && !fd->briefDescription().isEmpty()))
784  {
785  warn(
786  root->fileName,root->startLine,
787  "file %s already documented. "
788  "Skipping documentation.",
789  root->name.data()
790  );
791  }
792  else
793 #endif
794  {
795  //printf("Adding documentation!\n");
796  // using FALSE in setDocumentation is small hack to make sure a file
797  // is documented even if a \file command is used without further
798  // documentation
799  fd->setDocumentation(root->doc,root->docFile,root->docLine,FALSE);
800  fd->setBriefDescription(root->brief,root->briefFile,root->briefLine);
801  fd->addSectionsToDefinition(root->anchors);
802  fd->setRefItems(root->sli);
803  QListIterator<Grouping> gli(*root->groups);
804  Grouping *g;
805  for (;(g=gli.current());++gli)
806  {
807  GroupDef *gd=0;
808  if (!g->groupname.isEmpty() && (gd=Doxygen::groupSDict->find(g->groupname)))
809  {
810  gd->addFile(fd);
811  fd->makePartOfGroup(gd);
812  //printf("File %s: in group %s\n",fd->name().data(),s->data());
813  }
814  }
815  }
816  }
817  else
818  {
819  const char *fn = root->fileName.data();
820  QCString text(4096);
821  text.sprintf("the name `%s' supplied as "
822  "the second argument in the \\file statement ",
823  qPrint(root->name));
824  if (ambig) // name is ambiguous
825  {
826  text+="matches the following input files:\n";
827  text+=showFileDefMatches(Doxygen::inputNameDict,root->name);
828  text+="Please use a more specific name by "
829  "including a (larger) part of the path!";
830  }
831  else // name is not an input file
832  {
833  text+="is not an input file";
834  }
835  warn(fn,root->startLine,text);
836  }
837 
838  rootNav->releaseEntry();
839  }
841 }
842 
843 static void addIncludeFile(ClassDef *cd,FileDef *ifd,Entry *root)
844 {
845  if (
846  (!root->doc.stripWhiteSpace().isEmpty() ||
847  !root->brief.stripWhiteSpace().isEmpty() ||
848  Config_getBool("EXTRACT_ALL")
849  ) && root->protection!=Private
850  )
851  {
852  //printf(">>>>>> includeFile=%s\n",root->includeFile.data());
853 
854  bool local=Config_getBool("FORCE_LOCAL_INCLUDES");
855  QCString includeFile = root->includeFile;
856  if (!includeFile.isEmpty() && includeFile.at(0)=='"')
857  {
858  local = TRUE;
859  includeFile=includeFile.mid(1,includeFile.length()-2);
860  }
861  else if (!includeFile.isEmpty() && includeFile.at(0)=='<')
862  {
863  local = FALSE;
864  includeFile=includeFile.mid(1,includeFile.length()-2);
865  }
866 
867  bool ambig;
868  FileDef *fd=0;
869  // see if we need to include a verbatim copy of the header file
870  //printf("root->includeFile=%s\n",root->includeFile.data());
871  if (!includeFile.isEmpty() &&
872  (fd=findFileDef(Doxygen::inputNameDict,includeFile,ambig))==0
873  )
874  { // explicit request
875  QCString text;
876  text.sprintf("the name `%s' supplied as "
877  "the argument of the \\class, \\struct, \\union, or \\include command ",
878  qPrint(includeFile)
879  );
880  if (ambig) // name is ambiguous
881  {
882  text+="matches the following input files:\n";
883  text+=showFileDefMatches(Doxygen::inputNameDict,root->includeFile);
884  text+="Please use a more specific name by "
885  "including a (larger) part of the path!";
886  }
887  else // name is not an input file
888  {
889  text+="is not an input file";
890  }
891  warn(root->fileName,root->startLine,text);
892  }
893  else if (includeFile.isEmpty() && ifd &&
894  // see if the file extension makes sense
896  { // implicit assumption
897  fd=ifd;
898  }
899 
900  // if a file is found, we mark it as a source file.
901  if (fd)
902  {
903  QCString iName = !root->includeName.isEmpty() ?
904  root->includeName : includeFile;
905  if (!iName.isEmpty()) // user specified include file
906  {
907  if (iName.at(0)=='<') local=FALSE; // explicit override
908  else if (iName.at(0)=='"') local=TRUE;
909  if (iName.at(0)=='"' || iName.at(0)=='<')
910  {
911  iName=iName.mid(1,iName.length()-2); // strip quotes or brackets
912  }
913  if (iName.isEmpty())
914  {
915  iName=fd->name();
916  }
917  }
918  else if (!Config_getList("STRIP_FROM_INC_PATH").isEmpty())
919  {
920  iName=stripFromIncludePath(fd->absFilePath());
921  }
922  else // use name of the file containing the class definition
923  {
924  iName=fd->name();
925  }
926  if (fd->generateSourceFile()) // generate code for header
927  {
928  cd->setIncludeFile(fd,iName,local,!root->includeName.isEmpty());
929  }
930  else // put #include in the class documentation without link
931  {
932  cd->setIncludeFile(0,iName,local,TRUE);
933  }
934  }
935  }
936 }
937 
938 #if 0
939 static bool addNamespace(Entry *root,ClassDef *cd)
940 {
941  // see if this class is defined inside a namespace
942  if (root->section & Entry::COMPOUND_MASK)
943  {
944  Entry *e = root->parent;
945  while (e)
946  {
948  {
949  NamespaceDef *nd=0;
951  //printf("addNameSpace() trying: %s\n",nsName.data());
952  if (!nsName.isEmpty() && nsName.at(0)!='@' &&
953  (nd=getResolvedNamespace(nsName))
954  )
955  {
956  cd->setNamespace(nd);
957  cd->setOuterScope(nd);
958  nd->insertClass(cd);
959  return TRUE;
960  }
961  }
962  e=e->parent;
963  }
964  }
965  return FALSE;
966 }
967 #endif
968 
969 #if 0
970 static Definition *findScope(Entry *root,int level=0)
971 {
972  if (root==0) return 0;
973  //printf("start findScope name=%s\n",root->name.data());
974  Definition *result=0;
975  if (root->section&Entry::SCOPE_MASK)
976  {
977  result = findScope(root->parent,level+1); // traverse to the root of the tree
978  if (result)
979  {
980  //printf("Found %s inside %s at level %d\n",root->name.data(),result->name().data(),level);
981  // TODO: look at template arguments
982  result = result->findInnerCompound(root->name);
983  }
984  else // reached the global scope
985  {
986  // TODO: look at template arguments
987  result = Doxygen::globalScope->findInnerCompound(root->name);
988  //printf("Found in globalScope %s at level %d\n",result->name().data(),level);
989  }
990  }
991  //printf("end findScope(%s,%d)=%s\n",root->name.data(),
992  // level,result==0 ? "<none>" : result->name().data());
993  return result;
994 }
995 #endif
996 
997 /*! returns the Definition object belonging to the first \a level levels of
998  * full qualified name \a name. Creates an artificial scope if the scope is
999  * not found and set the parent/child scope relation if the scope is found.
1000  */
1002  int level,SrcLangExt lang,TagInfo *tagInfo)
1003 {
1004  //printf("buildScopeFromQualifiedName(%s) level=%d\n",name.data(),level);
1005  int i=0;
1006  int p=0,l;
1007  Definition *prevScope=Doxygen::globalScope;
1008  QCString fullScope;
1009  while (i<level)
1010  {
1011  int idx=getScopeFragment(name,p,&l);
1012  if (idx==-1) return prevScope;
1013  QCString nsName = name.mid(idx,l);
1014  if (nsName.isEmpty()) return prevScope;
1015  if (!fullScope.isEmpty()) fullScope+="::";
1016  fullScope+=nsName;
1017  NamespaceDef *nd=Doxygen::namespaceSDict->find(fullScope);
1018  Definition *innerScope = nd;
1019  ClassDef *cd=0;
1020  if (nd==0) cd = getClass(fullScope);
1021  if (nd==0 && cd) // scope is a class
1022  {
1023  innerScope = cd;
1024  }
1025  else if (nd==0 && cd==0 && fullScope.find('<')==-1) // scope is not known and could be a namespace!
1026  {
1027  // introduce bogus namespace
1028  //printf("++ adding dummy namespace %s to %s tagInfo=%p\n",nsName.data(),prevScope->name().data(),tagInfo);
1029  nd=new NamespaceDef(
1030  "[generated]",1,1,fullScope,
1031  tagInfo?tagInfo->tagName:QCString(),
1032  tagInfo?tagInfo->fileName:QCString());
1033  nd->setLanguage(lang);
1034 
1035  // add namespace to the list
1036  Doxygen::namespaceSDict->inSort(fullScope,nd);
1037  innerScope = nd;
1038  }
1039  else // scope is a namespace
1040  {
1041  }
1042  if (innerScope)
1043  {
1044  // make the parent/child scope relation
1045  prevScope->addInnerCompound(innerScope);
1046  innerScope->setOuterScope(prevScope);
1047  }
1048  else // current scope is a class, so return only the namespace part...
1049  {
1050  return prevScope;
1051  }
1052  // proceed to the next scope fragment
1053  p=idx+l+2;
1054  prevScope=innerScope;
1055  i++;
1056  }
1057  return prevScope;
1058 }
1059 
1061  FileDef *fileScope,TagInfo *tagInfo)
1062 {
1063  //printf("<findScopeFromQualifiedName(%s,%s)\n",startScope ? startScope->name().data() : 0, n.data());
1064  Definition *resultScope=startScope;
1065  if (resultScope==0) resultScope=Doxygen::globalScope;
1067  int l1=0,i1;
1068  i1=getScopeFragment(scope,0,&l1);
1069  if (i1==-1)
1070  {
1071  //printf(">no fragments!\n");
1072  return resultScope;
1073  }
1074  int p=i1+l1,l2=0,i2;
1075  while ((i2=getScopeFragment(scope,p,&l2))!=-1)
1076  {
1077  QCString nestedNameSpecifier = scope.mid(i1,l1);
1078  Definition *orgScope = resultScope;
1079  //printf(" nestedNameSpecifier=%s\n",nestedNameSpecifier.data());
1080  resultScope = resultScope->findInnerCompound(nestedNameSpecifier);
1081  //printf(" resultScope=%p\n",resultScope);
1082  if (resultScope==0)
1083  {
1084  NamespaceSDict *usedNamespaces;
1085  if (orgScope==Doxygen::globalScope && fileScope &&
1086  (usedNamespaces = fileScope->getUsedNamespaces()))
1087  // also search for used namespaces
1088  {
1089  NamespaceSDict::Iterator ni(*usedNamespaces);
1090  NamespaceDef *nd;
1091  for (ni.toFirst();((nd=ni.current()) && resultScope==0);++ni)
1092  {
1093  // restart search within the used namespace
1094  resultScope = findScopeFromQualifiedName(nd,n,fileScope,tagInfo);
1095  }
1096  if (resultScope)
1097  {
1098  // for a nested class A::I in used namespace N, we get
1099  // N::A::I while looking for A, so we should compare
1100  // resultScope->name() against scope.left(i2+l2)
1101  //printf(" -> result=%s scope=%s\n",resultScope->name().data(),scope.data());
1102  if (rightScopeMatch(resultScope->name(),scope.left(i2+l2)))
1103  {
1104  break;
1105  }
1106  goto nextFragment;
1107  }
1108  }
1109 
1110  // also search for used classes. Complication: we haven't been able
1111  // to put them in the right scope yet, because we are still resolving
1112  // the scope relations!
1113  // Therefore loop through all used classes and see if there is a right
1114  // scope match between the used class and nestedNameSpecifier.
1115  QDictIterator<FileDef> ui(g_usingDeclarations);
1116  FileDef *usedFd;
1117  for (ui.toFirst();(usedFd=ui.current());++ui)
1118  {
1119  //printf("Checking using class %s\n",ui.currentKey());
1120  if (rightScopeMatch(ui.currentKey(),nestedNameSpecifier))
1121  {
1122  // ui.currentKey() is the fully qualified name of nestedNameSpecifier
1123  // so use this instead.
1124  QCString fqn = QCString(ui.currentKey())+
1125  scope.right(scope.length()-p);
1126  resultScope = buildScopeFromQualifiedName(fqn,fqn.contains("::"),
1127  startScope->getLanguage(),0);
1128  //printf("Creating scope from fqn=%s result %p\n",fqn.data(),resultScope);
1129  if (resultScope)
1130  {
1131  //printf("> Match! resultScope=%s\n",resultScope->name().data());
1132  return resultScope;
1133  }
1134  }
1135  }
1136 
1137  //printf("> name %s not found in scope %s\n",nestedNameSpecifier.data(),orgScope->name().data());
1138  return 0;
1139  }
1140  nextFragment:
1141  i1=i2;
1142  l1=l2;
1143  p=i2+l2;
1144  }
1145  //printf(">findScopeFromQualifiedName scope %s\n",resultScope->name().data());
1146  return resultScope;
1147 }
1148 
1150  const QCString &name,
1151  const QList<ArgumentList> *tArgLists)
1152 {
1153  if (tArgLists==0) return 0;
1154 
1155  QListIterator<ArgumentList> ali(*tArgLists);
1156  // for each scope fragment, check if it is a template and advance through
1157  // the list if so.
1158  int i,p=0;
1159  while ((i=name.find("::",p))!=-1)
1160  {
1161  NamespaceDef *nd = Doxygen::namespaceSDict->find(name.left(i));
1162  if (nd==0)
1163  {
1164  ClassDef *cd = getClass(name.left(i));
1165  if (cd)
1166  {
1167  if (cd->templateArguments())
1168  {
1169  ++ali;
1170  }
1171  }
1172  }
1173  p=i+2;
1174  }
1175  return ali.current();
1176 }
1177 
1178 static
1180 {
1182  if (specifier&Entry::Struct)
1183  sec=ClassDef::Struct;
1184  else if (specifier&Entry::Union)
1185  sec=ClassDef::Union;
1186  else if (specifier&Entry::Category)
1187  sec=ClassDef::Category;
1188  else if (specifier&Entry::Interface)
1189  sec=ClassDef::Interface;
1190  else if (specifier&Entry::Protocol)
1191  sec=ClassDef::Protocol;
1192  else if (specifier&Entry::Exception)
1193  sec=ClassDef::Exception;
1194  else if (specifier&Entry::Service)
1195  sec=ClassDef::Service;
1196  else if (specifier&Entry::Singleton)
1197  sec=ClassDef::Singleton;
1198 
1199  switch(section)
1200  {
1201  //case Entry::UNION_SEC:
1202  case Entry::UNIONDOC_SEC:
1203  sec=ClassDef::Union;
1204  break;
1205  //case Entry::STRUCT_SEC:
1206  case Entry::STRUCTDOC_SEC:
1207  sec=ClassDef::Struct;
1208  break;
1209  //case Entry::INTERFACE_SEC:
1211  sec=ClassDef::Interface;
1212  break;
1213  //case Entry::PROTOCOL_SEC:
1215  sec=ClassDef::Protocol;
1216  break;
1217  //case Entry::CATEGORY_SEC:
1219  sec=ClassDef::Category;
1220  break;
1221  //case Entry::EXCEPTION_SEC:
1223  sec=ClassDef::Exception;
1224  break;
1225  case Entry::SERVICEDOC_SEC:
1226  sec=ClassDef::Service;
1227  break;
1229  sec=ClassDef::Singleton;
1230  break;
1231  }
1232  return sec;
1233 }
1234 
1235 
1236 static void addClassToContext(EntryNav *rootNav)
1237 {
1238  //printf("Loading entry for rootNav=%p name=%s\n",rootNav,rootNav->name().data());
1239  rootNav->loadEntry(g_storage);
1240  Entry *root = rootNav->entry();
1241 
1242  //NamespaceDef *nd = 0;
1243  FileDef *fd = rootNav->fileDef();
1244 
1245  QCString scName;
1246  if (rootNav->parent()->section()&Entry::SCOPE_MASK)
1247  {
1248  scName=rootNav->parent()->name();
1249  }
1250  // name without parent's scope
1251  QCString fullName = root->name;
1252 
1253  // strip off any template parameters (but not those for specializations)
1254  fullName=stripTemplateSpecifiersFromScope(fullName);
1255 
1256  // name with scope (if not present already)
1257  QCString qualifiedName = fullName;
1258  if (!scName.isEmpty() && !leftScopeMatch(fullName,scName))
1259  {
1260  qualifiedName.prepend(scName+"::");
1261  }
1262 
1263  // see if we already found the class before
1264  ClassDef *cd = getClass(qualifiedName);
1265 
1266  Debug::print(Debug::Classes,0, " Found class with name %s (qualifiedName=%s -> cd=%p)\n",
1267  cd ? qPrint(cd->name()) : qPrint(root->name), qPrint(qualifiedName),cd);
1268 
1269  if (cd)
1270  {
1271  fullName=cd->name();
1272  Debug::print(Debug::Classes,0," Existing class %s!\n",qPrint(cd->name()));
1273  //if (cd->templateArguments()==0)
1274  //{
1275  // //printf("existing ClassDef tempArgList=%p specScope=%s\n",root->tArgList,root->scopeSpec.data());
1276  // cd->setTemplateArguments(tArgList);
1277  //}
1278 
1279  cd->setDocumentation(root->doc,root->docFile,root->docLine);
1280  cd->setBriefDescription(root->brief,root->briefFile,root->briefLine);
1281 
1282  if (root->bodyLine!=-1 && cd->getStartBodyLine()==-1)
1283  {
1284  cd->setBodySegment(root->bodyLine,root->endBodyLine);
1285  cd->setBodyDef(fd);
1286  }
1287  //cd->setName(fullName); // change name to match docs
1288 
1289  if (cd->templateArguments()==0 || (cd->isForwardDeclared() && (root->spec&Entry::ForwardDecl)==0))
1290  {
1291  // this happens if a template class declared with @class is found
1292  // before the actual definition or if a forward declaration has different template
1293  // parameter names.
1294  ArgumentList *tArgList =
1296  cd->setTemplateArguments(tArgList);
1297  }
1298 
1300  }
1301  else // new class
1302  {
1304 
1306  QCString namespaceName;
1307  extractNamespaceName(fullName,className,namespaceName);
1308 
1309  //printf("New class: fullname %s namespace `%s' name=`%s' brief=`%s' docs=`%s'\n",
1310  // fullName.data(),namespaceName.data(),className.data(),root->brief.data(),root->doc.data());
1311 
1312  QCString tagName;
1313  QCString refFileName;
1314  TagInfo *tagInfo = rootNav->tagInfo();
1315  int i;
1316  if (tagInfo)
1317  {
1318  tagName = tagInfo->tagName;
1319  refFileName = tagInfo->fileName;
1320  if (fullName.find("::")!=-1)
1321  // symbols imported via tag files may come without the parent scope,
1322  // so we artificially create it here
1323  {
1324  buildScopeFromQualifiedName(fullName,fullName.contains("::"),root->lang,tagInfo);
1325  }
1326  }
1327  ArgumentList *tArgList = 0;
1328  if ((root->lang==SrcLangExt_CSharp || root->lang==SrcLangExt_Java) && (i=fullName.find('<'))!=-1)
1329  {
1330  // a Java/C# generic class looks like a C++ specialization, so we need to split the
1331  // name and template arguments here
1332  tArgList = new ArgumentList;
1333  stringToArgumentList(fullName.mid(i),tArgList);
1334  fullName=fullName.left(i);
1335  }
1336  else
1337  {
1338  tArgList = getTemplateArgumentsFromName(fullName,root->tArgLists);
1339  }
1340  cd=new ClassDef(tagInfo?tagName:root->fileName,root->startLine,root->startColumn,
1341  fullName,sec,tagName,refFileName,TRUE,root->spec&Entry::Enum);
1342  Debug::print(Debug::Classes,0," New class `%s' (sec=0x%08x)! #tArgLists=%d tagInfo=%p\n",
1343  qPrint(fullName),sec,root->tArgLists ? (int)root->tArgLists->count() : -1, tagInfo);
1344  cd->setDocumentation(root->doc,root->docFile,root->docLine); // copy docs to definition
1345  cd->setBriefDescription(root->brief,root->briefFile,root->briefLine);
1346  cd->setLanguage(root->lang);
1347  cd->setId(root->id);
1348  cd->setHidden(root->hidden);
1349  cd->setArtificial(root->artificial);
1350  cd->setClassSpecifier(root->spec);
1351  cd->setTypeConstraints(root->typeConstr);
1352  //printf("new ClassDef %s tempArgList=%p specScope=%s\n",fullName.data(),root->tArgList,root->scopeSpec.data());
1353 
1354  //printf("class %s template args=%s\n",fullName.data(),
1355  // tArgList ? tempArgListToString(tArgList,root->lang).data() : "<none>");
1356  cd->setTemplateArguments(tArgList);
1357  cd->setProtection(root->protection);
1358  cd->setIsStatic(root->stat);
1359 
1360  // file definition containing the class cd
1361  cd->setBodySegment(root->bodyLine,root->endBodyLine);
1362  cd->setBodyDef(fd);
1363 
1364  // see if the class is found inside a namespace
1365  //bool found=addNamespace(root,cd);
1366 
1367  cd->insertUsedFile(fd);
1368 
1369  // add class to the list
1370  //printf("ClassDict.insert(%s)\n",fullName.data());
1371  Doxygen::classSDict->append(fullName,cd);
1372 
1373  if (cd->isGeneric()) // generics are also stored in a separate dictionary for fast lookup of instantions
1374  {
1375  //printf("inserting generic '%s' cd=%p\n",fullName.data(),cd);
1376  Doxygen::genericsDict->insert(fullName,cd);
1377  }
1378  }
1379 
1380  cd->addSectionsToDefinition(root->anchors);
1381  if (!root->subGrouping) cd->setSubGrouping(FALSE);
1382  if (cd->hasDocumentation())
1383  {
1384  addIncludeFile(cd,fd,root);
1385  }
1386  if (fd && (root->section & Entry::COMPOUND_MASK))
1387  {
1388  //printf(">> Inserting class `%s' in file `%s' (root->fileName=`%s')\n",
1389  // cd->name().data(),
1390  // fd->name().data(),
1391  // root->fileName.data()
1392  // );
1393  cd->setFileDef(fd);
1394  fd->insertClass(cd);
1395  }
1396  addClassToGroups(root,cd);
1397  cd->setRefItems(root->sli);
1398 
1399  rootNav->releaseEntry();
1400 }
1401 
1402 //----------------------------------------------------------------------
1403 // build a list of all classes mentioned in the documentation
1404 // and all classes that have a documentation block before their definition.
1405 static void buildClassList(EntryNav *rootNav)
1406 {
1407  if (
1408  ((rootNav->section() & Entry::COMPOUND_MASK) ||
1409  rootNav->section()==Entry::OBJCIMPL_SEC) && !rootNav->name().isEmpty()
1410  )
1411  {
1412  addClassToContext(rootNav);
1413  }
1415 }
1416 
1417 static void buildClassDocList(EntryNav *rootNav)
1418 {
1419  if (
1420  (rootNav->section() & Entry::COMPOUNDDOC_MASK) && !rootNav->name().isEmpty()
1421  )
1422  {
1423  addClassToContext(rootNav);
1424  }
1426 }
1427 
1429 {
1430  ClassSDict::Iterator cli(*Doxygen::classSDict);
1431  for (cli.toFirst();cli.current();++cli) cli.current()->visited=FALSE;
1432 
1433  bool done=FALSE;
1434  int iteration=0;
1435  while (!done)
1436  {
1437  done=TRUE;
1438  ++iteration;
1439  ClassDef *cd=0;
1440  for (cli.toFirst();(cd=cli.current());++cli)
1441  {
1442  if (!cd->visited)
1443  {
1445  //printf("processing=%s, iteration=%d\n",cd->name().data(),iteration);
1446  // also add class to the correct structural context
1447  Definition *d = findScopeFromQualifiedName(Doxygen::globalScope,
1448  name,cd->getFileDef(),0);
1449  if (d)
1450  {
1451  //printf("****** adding %s to scope %s in iteration %d\n",cd->name().data(),d->name().data(),iteration);
1452  d->addInnerCompound(cd);
1453  cd->setOuterScope(d);
1454  cd->visited=TRUE;
1455  done=FALSE;
1456  }
1457  //else
1458  //{
1459  // printf("****** ignoring %s: scope not (yet) found in iteration %d\n",cd->name().data(),iteration);
1460  //}
1461  }
1462  }
1463  }
1464 
1465  //give warnings for unresolved compounds
1466  ClassDef *cd=0;
1467  for (cli.toFirst();(cd=cli.current());++cli)
1468  {
1469  if (!cd->visited)
1470  {
1472  //printf("processing unresolved=%s, iteration=%d\n",cd->name().data(),iteration);
1473  /// create the scope artificially
1474  // anyway, so we can at least relate scopes properly.
1475  Definition *d = buildScopeFromQualifiedName(name,name.contains("::"),cd->getLanguage(),0);
1476  if (d!=cd && !cd->getDefFileName().isEmpty())
1477  // avoid recursion in case of redundant scopes, i.e: namespace N { class N::C {}; }
1478  // for this case doxygen assumes the exitance of a namespace N::N in which C is to be found!
1479  // also avoid warning for stuff imported via a tagfile.
1480  {
1481  d->addInnerCompound(cd);
1482  cd->setOuterScope(d);
1483  warn(cd->getDefFileName(),cd->getDefLine(),
1484  "Internal inconsistency: scope for class %s not "
1485  "found!",name.data()
1486  );
1487  }
1488  }
1489  }
1490 }
1491 
1493 {
1494  //static bool inlineGroupedClasses = Config_getBool("INLINE_GROUPED_CLASSES");
1495  //if (!inlineGroupedClasses) return;
1496  //printf("** distributeClassGroupRelations()\n");
1497 
1498  ClassSDict::Iterator cli(*Doxygen::classSDict);
1499  for (cli.toFirst();cli.current();++cli) cli.current()->visited=FALSE;
1500 
1501  ClassDef *cd;
1502  for (cli.toFirst();(cd=cli.current());++cli)
1503  {
1504  //printf("Checking %s\n",cd->name().data());
1505  // distribute the group to nested classes as well
1506  if (!cd->visited && cd->partOfGroups()!=0 && cd->getClassSDict())
1507  {
1508  //printf(" Candidate for merging\n");
1509  ClassSDict::Iterator ncli(*cd->getClassSDict());
1510  ClassDef *ncd;
1511  GroupDef *gd = cd->partOfGroups()->at(0);
1512  for (ncli.toFirst();(ncd=ncli.current());++ncli)
1513  {
1514  if (ncd->partOfGroups()==0)
1515  {
1516  //printf(" Adding %s to group '%s'\n",ncd->name().data(),
1517  // gd->groupTitle());
1518  ncd->makePartOfGroup(gd);
1519  gd->addClass(ncd);
1520  }
1521  }
1522  cd->visited=TRUE; // only visit every class once
1523  }
1524  }
1525 }
1526 
1527 //----------------------------
1528 
1529 static ClassDef *createTagLessInstance(ClassDef *rootCd,ClassDef *templ,const QCString &fieldName)
1530 {
1531  QCString fullName = removeAnonymousScopes(templ->name());
1532  if (fullName.right(2)=="::") fullName=fullName.left(fullName.length()-2);
1533  fullName+="."+fieldName;
1534  ClassDef *cd = new ClassDef(templ->getDefFileName(),
1535  templ->getDefLine(),
1536  templ->getDefColumn(),
1537  fullName,
1538  templ->compoundType());
1539  cd->setDocumentation(templ->documentation(),templ->docFile(),templ->docLine()); // copy docs to definition
1540  cd->setBriefDescription(templ->briefDescription(),templ->briefFile(),templ->briefLine());
1541  cd->setLanguage(templ->getLanguage());
1542  cd->setBodySegment(templ->getStartBodyLine(),templ->getEndBodyLine());
1543  cd->setBodyDef(templ->getBodyDef());
1544 
1545  cd->setOuterScope(rootCd->getOuterScope());
1546  if (rootCd->getOuterScope()!=Doxygen::globalScope)
1547  {
1548  rootCd->getOuterScope()->addInnerCompound(cd);
1549  }
1550 
1551  FileDef *fd = templ->getFileDef();
1552  if (fd)
1553  {
1554  cd->setFileDef(fd);
1555  fd->insertClass(cd);
1556  }
1557  GroupList *groups = rootCd->partOfGroups();
1558  if ( groups!=0 )
1559  {
1560  GroupListIterator gli(*groups);
1561  GroupDef *gd;
1562  for (gli.toFirst();(gd=gli.current());++gli)
1563  {
1564  cd->makePartOfGroup(gd);
1565  gd->addClass(cd);
1566  }
1567  }
1568  //printf("** adding class %s based on %s\n",fullName.data(),templ->name().data());
1569  Doxygen::classSDict->append(fullName,cd);
1570 
1572  if (ml)
1573  {
1574  MemberListIterator li(*ml);
1575  MemberDef *md;
1576  for (li.toFirst();(md=li.current());++li)
1577  {
1578  //printf(" Member %s type=%s\n",md->name().data(),md->typeString());
1579  MemberDef *imd = new MemberDef(md->getDefFileName(),md->getDefLine(),md->getDefColumn(),
1580  md->typeString(),md->name(),md->argsString(),md->excpString(),
1581  md->protection(),md->virtualness(),md->isStatic(),Member,
1582  md->memberType(),
1583  0,0);
1584  imd->setMemberClass(cd);
1585  imd->setDocumentation(md->documentation(),md->docFile(),md->docLine());
1586  imd->setBriefDescription(md->briefDescription(),md->briefFile(),md->briefLine());
1589  imd->setMemberGroupId(md->getMemberGroupId());
1590  imd->setInitializer(md->initializer());
1591  imd->setMaxInitLines(md->initializerLines());
1592  imd->setBitfields(md->bitfieldString());
1593  imd->setLanguage(md->getLanguage());
1594  cd->insertMember(imd);
1595  }
1596  }
1597  return cd;
1598 }
1599 
1600 /** Look through the members of class \a cd and its public members.
1601  * If there is a member m of a tag less struct/union,
1602  * then we create a duplicate of the struct/union with the name of the
1603  * member to identify it.
1604  * So if cd has name S, then the tag less struct/union will get name S.m
1605  * Since tag less structs can be nested we need to call this function
1606  * recursively. Later on we need to patch the member types so we keep
1607  * track of the hierarchy of classes we create.
1608  */
1609 static void processTagLessClasses(ClassDef *rootCd,
1610  ClassDef *cd,
1611  ClassDef *tagParentCd,
1612  const QCString &prefix,int count)
1613 {
1614  //printf("%d: processTagLessClasses %s\n",count,cd->name().data());
1615  //printf("checking members for %s\n",cd->name().data());
1616  if (cd->getClassSDict())
1617  {
1619  if (ml)
1620  {
1621  MemberListIterator li(*ml);
1622  MemberDef *md;
1623  for (li.toFirst();(md=li.current());++li)
1624  {
1625  QCString type = md->typeString();
1626  if (type.find("::@")!=-1) // member of tag less struct/union
1627  {
1629  ClassDef *icd;
1630  for (it.toFirst();(icd=it.current());++it)
1631  {
1632  //printf(" member %s: type='%s'\n",md->name().data(),type.data());
1633  //printf(" comparing '%s'<->'%s'\n",type.data(),icd->name().data());
1634  if (type.find(icd->name())!=-1) // matching tag less struct/union
1635  {
1636  QCString name = md->name();
1637  if (name.at(0)=='@') name = "__unnamed__";
1638  if (!prefix.isEmpty()) name.prepend(prefix+".");
1639  //printf(" found %s for class %s\n",name.data(),cd->name().data());
1640  ClassDef *ncd = createTagLessInstance(rootCd,icd,name);
1641  processTagLessClasses(rootCd,icd,ncd,name,count+1);
1642  //printf(" addTagged %s to %s\n",ncd->name().data(),tagParentCd->name().data());
1643  tagParentCd->addTaggedInnerClass(ncd);
1644  ncd->setTagLessReference(icd);
1645 
1646  // replace tag-less type for generated/original member
1647  // by newly created class name.
1648  // note the difference between changing cd and tagParentCd.
1649  // for the initial call this is the same pointer, but for
1650  // recursive calls cd is the original tag-less struct (of which
1651  // there is only one instance) and tagParentCd is the newly
1652  // generated tagged struct of which there can be multiple instances!
1653  MemberList *pml = tagParentCd->getMemberList(MemberListType_pubAttribs);
1654  if (pml)
1655  {
1656  MemberListIterator pli(*pml);
1657  MemberDef *pmd;
1658  for (pli.toFirst();(pmd=pli.current());++pli)
1659  {
1660  if (pmd->name()==md->name())
1661  {
1662  pmd->setAccessorType(ncd,substitute(pmd->typeString(),icd->name(),ncd->name()));
1663  //pmd->setType(substitute(pmd->typeString(),icd->name(),ncd->name()));
1664  }
1665  }
1666  }
1667  }
1668  }
1669  }
1670  }
1671  }
1672  }
1673 }
1674 
1676 {
1677  if (cd->getClassSDict())
1678  {
1680  ClassDef *icd;
1681  for (it.toFirst();(icd=it.current());++it)
1682  {
1683  if (icd->name().find("@")==-1) // process all non-anonymous inner classes
1684  {
1685  findTagLessClasses(icd);
1686  }
1687  }
1688  }
1689 
1690  processTagLessClasses(cd,cd,cd,"",0); // process tag less inner struct/classes (if any)
1691 }
1692 
1693 static void findTagLessClasses()
1694 {
1695  ClassSDict::Iterator cli(*Doxygen::classSDict);
1696  ClassDef *cd;
1697  for (cli.toFirst();(cd=cli.current());++cli) // for each class
1698  {
1699  Definition *scope = cd->getOuterScope();
1700  if (scope && scope->definitionType()!=Definition::TypeClass) // that is not nested
1701  {
1702  findTagLessClasses(cd);
1703  }
1704  }
1705 }
1706 
1707 
1708 //----------------------------------------------------------------------
1709 // build a list of all namespaces mentioned in the documentation
1710 // and all namespaces that have a documentation block before their definition.
1711 static void buildNamespaceList(EntryNav *rootNav)
1712 {
1713  if (
1714  (rootNav->section()==Entry::NAMESPACE_SEC ||
1715  rootNav->section()==Entry::NAMESPACEDOC_SEC ||
1716  rootNav->section()==Entry::PACKAGEDOC_SEC
1717  ) &&
1718  !rootNav->name().isEmpty()
1719  )
1720  {
1721  rootNav->loadEntry(g_storage);
1722  Entry *root = rootNav->entry();
1723 
1724  //printf("** buildNamespaceList(%s)\n",root->name.data());
1725 
1726  QCString fName = root->name;
1727  if (root->section==Entry::PACKAGEDOC_SEC)
1728  {
1729  fName=substitute(fName,".","::");
1730  }
1731 
1732  QCString fullName = stripAnonymousNamespaceScope(fName);
1733  if (!fullName.isEmpty())
1734  {
1735  //printf("Found namespace %s in %s at line %d\n",root->name.data(),
1736  // root->fileName.data(), root->startLine);
1737  NamespaceDef *nd;
1738  if ((nd=Doxygen::namespaceSDict->find(fullName))) // existing namespace
1739  {
1740  nd->setDocumentation(root->doc,root->docFile,root->docLine);
1741  nd->setName(fullName); // change name to match docs
1742  nd->addSectionsToDefinition(root->anchors);
1743  nd->setBriefDescription(root->brief,root->briefFile,root->briefLine);
1744  if (nd->getLanguage()==SrcLangExt_Unknown)
1745  {
1746  nd->setLanguage(root->lang);
1747  }
1748  if (rootNav->tagInfo()==0) // if we found the namespace in a tag file
1749  // and also in a project file, then remove
1750  // the tag file reference
1751  {
1752  nd->setReference("");
1753  nd->setFileName(fullName);
1754  }
1755 
1756  // file definition containing the namespace nd
1757  FileDef *fd=rootNav->fileDef();
1758  // insert the namespace in the file definition
1759  if (fd) fd->insertNamespace(nd);
1760  addNamespaceToGroups(root,nd);
1761  nd->setRefItems(root->sli);
1762  }
1763  else // fresh namespace
1764  {
1765  QCString tagName;
1766  QCString tagFileName;
1767  TagInfo *tagInfo = rootNav->tagInfo();
1768  if (tagInfo)
1769  {
1770  tagName = tagInfo->tagName;
1771  tagFileName = tagInfo->fileName;
1772  }
1773  //printf("++ new namespace %s lang=%s tagName=%s\n",fullName.data(),langToString(root->lang).data(),tagName.data());
1774  NamespaceDef *nd=new NamespaceDef(tagInfo?tagName:root->fileName,root->startLine,
1775  root->startColumn,fullName,tagName,tagFileName,
1776  root->type,root->spec&Entry::Published);
1777  nd->setDocumentation(root->doc,root->docFile,root->docLine); // copy docs to definition
1778  nd->setBriefDescription(root->brief,root->briefFile,root->briefLine);
1779  nd->addSectionsToDefinition(root->anchors);
1780  nd->setHidden(root->hidden);
1781  nd->setArtificial(root->artificial);
1782  nd->setLanguage(root->lang);
1783  nd->setId(root->id);
1784 
1785  //printf("Adding namespace to group\n");
1786  addNamespaceToGroups(root,nd);
1787  nd->setRefItems(root->sli);
1788 
1789  // file definition containing the namespace nd
1790  FileDef *fd=rootNav->fileDef();
1791  // insert the namespace in the file definition
1792  if (fd) fd->insertNamespace(nd);
1793 
1794  // the empty string test is needed for extract all case
1795  nd->setBriefDescription(root->brief,root->briefFile,root->briefLine);
1796  nd->insertUsedFile(fd);
1797  nd->setBodySegment(root->bodyLine,root->endBodyLine);
1798  nd->setBodyDef(fd);
1799  // add class to the list
1800  Doxygen::namespaceSDict->inSort(fullName,nd);
1801 
1802  // also add namespace to the correct structural context
1803  Definition *d = findScopeFromQualifiedName(Doxygen::globalScope,fullName,0,tagInfo);
1804  //printf("adding namespace %s to context %s\n",nd->name().data(),d?d->name().data():"<none>");
1805  if (d==0) // we didn't find anything, create the scope artificially
1806  // anyway, so we can at least relate scopes properly.
1807  {
1808  Definition *d = buildScopeFromQualifiedName(fullName,fullName.contains("::"),nd->getLanguage(),tagInfo);
1809  d->addInnerCompound(nd);
1810  nd->setOuterScope(d);
1811  // TODO: Due to the order in which the tag file is written
1812  // a nested class can be found before its parent!
1813  }
1814  else
1815  {
1816  d->addInnerCompound(nd);
1817  nd->setOuterScope(d);
1818  }
1819  }
1820  }
1821 
1822  rootNav->releaseEntry();
1823  }
1825 }
1826 
1827 //----------------------------------------------------------------------
1828 
1830  const QCString &name)
1831 {
1832  NamespaceDef *usingNd =0;
1833  if (unl)
1834  {
1835  //printf("Found namespace dict %d\n",unl->count());
1836  NamespaceSDict::Iterator unli(*unl);
1837  NamespaceDef *und;
1838  for (unli.toFirst();(und=unli.current());++unli)
1839  {
1840  QCString uScope=und->name()+"::";
1841  usingNd = getResolvedNamespace(uScope+name);
1842  //printf("Also trying with scope=`%s' usingNd=%p\n",(uScope+name).data(),usingNd);
1843  }
1844  }
1845  return usingNd;
1846 }
1847 
1848 static void findUsingDirectives(EntryNav *rootNav)
1849 {
1850  if (rootNav->section()==Entry::USINGDIR_SEC)
1851  {
1852  rootNav->loadEntry(g_storage);
1853  Entry *root = rootNav->entry();
1854 
1855  //printf("Found using directive %s at line %d of %s\n",
1856  // root->name.data(),root->startLine,root->fileName.data());
1857  QCString name=substitute(root->name,".","::");
1858  if (name.right(2)=="::")
1859  {
1860  name=name.left(name.length()-2);
1861  }
1862  if (!name.isEmpty())
1863  {
1864  NamespaceDef *usingNd = 0;
1865  NamespaceDef *nd = 0;
1866  FileDef *fd = rootNav->fileDef();
1867  QCString nsName;
1868 
1869  // see if the using statement was found inside a namespace or inside
1870  // the global file scope.
1871  if (rootNav->parent() && rootNav->parent()->section()==Entry::NAMESPACE_SEC &&
1872  (fd==0 || fd->getLanguage()!=SrcLangExt_Java) // not a .java file
1873  )
1874  {
1875  nsName=stripAnonymousNamespaceScope(rootNav->parent()->name());
1876  if (!nsName.isEmpty())
1877  {
1878  nd = getResolvedNamespace(nsName);
1879  }
1880  }
1881 
1882  // find the scope in which the `using' namespace is defined by prepending
1883  // the possible scopes in which the using statement was found, starting
1884  // with the most inner scope and going to the most outer scope (i.e.
1885  // file scope).
1886  int scopeOffset = nsName.length();
1887  do
1888  {
1889  QCString scope=scopeOffset>0 ?
1890  nsName.left(scopeOffset)+"::" : QCString();
1891  usingNd = getResolvedNamespace(scope+name);
1892  //printf("Trying with scope=`%s' usingNd=%p\n",(scope+name).data(),usingNd);
1893  if (scopeOffset==0)
1894  {
1895  scopeOffset=-1;
1896  }
1897  else if ((scopeOffset=nsName.findRev("::",scopeOffset-1))==-1)
1898  {
1899  scopeOffset=0;
1900  }
1901  } while (scopeOffset>=0 && usingNd==0);
1902 
1903  if (usingNd==0 && nd) // not found, try used namespaces in this scope
1904  // or in one of the parent namespace scopes
1905  {
1906  NamespaceDef *pnd = nd;
1907  while (pnd && usingNd==0)
1908  {
1909  // also try with one of the used namespaces found earlier
1910  usingNd = findUsedNamespace(pnd->getUsedNamespaces(),name);
1911 
1912  // goto the parent
1913  Definition *s = pnd->getOuterScope();
1914  if (s && s->definitionType()==Definition::TypeNamespace)
1915  {
1916  pnd = (NamespaceDef*)s;
1917  }
1918  else
1919  {
1920  pnd = 0;
1921  }
1922  }
1923  }
1924  if (usingNd==0 && fd) // still nothing, also try used namespace in the
1925  // global scope
1926  {
1927  usingNd = findUsedNamespace(fd->getUsedNamespaces(),name);
1928  }
1929 
1930  //printf("%s -> %s\n",name.data(),usingNd?usingNd->name().data():"<none>");
1931 
1932  // add the namespace the correct scope
1933  if (usingNd)
1934  {
1935  //printf("using fd=%p nd=%p\n",fd,nd);
1936  if (nd)
1937  {
1938  //printf("Inside namespace %s\n",nd->name().data());
1939  nd->addUsingDirective(usingNd);
1940  }
1941  else if (fd)
1942  {
1943  //printf("Inside file %s\n",fd->name().data());
1944  fd->addUsingDirective(usingNd);
1945  }
1946  }
1947  else // unknown namespace, but add it anyway.
1948  {
1949  //printf("++ new unknown namespace %s lang=%s\n",name.data(),langToString(root->lang).data());
1950  NamespaceDef *nd=new NamespaceDef(root->fileName,root->startLine,root->startColumn,name);
1951  nd->setDocumentation(root->doc,root->docFile,root->docLine); // copy docs to definition
1952  nd->setBriefDescription(root->brief,root->briefFile,root->briefLine);
1953  nd->addSectionsToDefinition(root->anchors);
1954  //printf("** Adding namespace %s hidden=%d\n",name.data(),root->hidden);
1955  nd->setHidden(root->hidden);
1956  nd->setArtificial(TRUE);
1957  nd->setLanguage(root->lang);
1958  nd->setId(root->id);
1959 
1960  QListIterator<Grouping> gli(*root->groups);
1961  Grouping *g;
1962  for (;(g=gli.current());++gli)
1963  {
1964  GroupDef *gd=0;
1965  if (!g->groupname.isEmpty() && (gd=Doxygen::groupSDict->find(g->groupname)))
1966  gd->addNamespace(nd);
1967  }
1968 
1969  // insert the namespace in the file definition
1970  if (fd)
1971  {
1972  fd->insertNamespace(nd);
1973  fd->addUsingDirective(nd);
1974  }
1975 
1976  // the empty string test is needed for extract all case
1977  nd->setBriefDescription(root->brief,root->briefFile,root->briefLine);
1978  nd->insertUsedFile(fd);
1979  // add class to the list
1980  Doxygen::namespaceSDict->inSort(name,nd);
1981  nd->setRefItems(root->sli);
1982  }
1983  }
1984 
1985  rootNav->releaseEntry();
1986  }
1988 }
1989 
1990 //----------------------------------------------------------------------
1991 
1992 static void buildListOfUsingDecls(EntryNav *rootNav)
1993 {
1994  if (rootNav->section()==Entry::USINGDECL_SEC &&
1995  !(rootNav->parent()->section()&Entry::COMPOUND_MASK) // not a class/struct member
1996  )
1997  {
1998  rootNav->loadEntry(g_storage);
1999  Entry *root = rootNav->entry();
2000 
2001  QCString name = substitute(root->name,".","::");
2002 
2003  if (g_usingDeclarations.find(name)==0)
2004  {
2005  FileDef *fd = rootNav->fileDef();
2006  if (fd)
2007  {
2008  g_usingDeclarations.insert(name,fd);
2009  }
2010  }
2011 
2012  rootNav->releaseEntry();
2013  }
2015 }
2016 
2017 
2018 static void findUsingDeclarations(EntryNav *rootNav)
2019 {
2020  if (rootNav->section()==Entry::USINGDECL_SEC &&
2021  !(rootNav->parent()->section()&Entry::COMPOUND_MASK) // not a class/struct member
2022  )
2023  {
2024  rootNav->loadEntry(g_storage);
2025  Entry *root = rootNav->entry();
2026 
2027  //printf("Found using declaration %s at line %d of %s inside section %x\n",
2028  // root->name.data(),root->startLine,root->fileName.data(),
2029  // rootNav->parent()->section());
2030  if (!root->name.isEmpty())
2031  {
2032  ClassDef *usingCd = 0;
2033  NamespaceDef *nd = 0;
2034  FileDef *fd = rootNav->fileDef();
2035  QCString scName;
2036 
2037  // see if the using statement was found inside a namespace or inside
2038  // the global file scope.
2039  if (rootNav->parent()->section() == Entry::NAMESPACE_SEC)
2040  {
2041  scName=rootNav->parent()->name();
2042  if (!scName.isEmpty())
2043  {
2044  nd = getResolvedNamespace(scName);
2045  }
2046  }
2047 
2048  // Assume the using statement was used to import a class.
2049  // Find the scope in which the `using' namespace is defined by prepending
2050  // the possible scopes in which the using statement was found, starting
2051  // with the most inner scope and going to the most outer scope (i.e.
2052  // file scope).
2053 
2054  QCString name = substitute(root->name,".","::"); //Java/C# scope->internal
2055  usingCd = getClass(name);
2056  if (usingCd==0)
2057  {
2058  usingCd = Doxygen::hiddenClasses->find(name);
2059  }
2060 
2061  //printf("%s -> %p\n",root->name.data(),usingCd);
2062  if (usingCd==0) // definition not in the input => add an artificial class
2063  {
2064  Debug::print(Debug::Classes,0," New using class `%s' (sec=0x%08x)! #tArgLists=%d\n",
2065  qPrint(name),root->section,root->tArgLists ? (int)root->tArgLists->count() : -1);
2066  usingCd = new ClassDef(
2067  "<using>",1,1,
2068  name,
2069  ClassDef::Class);
2070  Doxygen::hiddenClasses->append(root->name,usingCd);
2071  usingCd->setArtificial(TRUE);
2072  usingCd->setLanguage(root->lang);
2073  }
2074  else
2075  {
2076  Debug::print(Debug::Classes,0," Found used class %s in scope=%s\n",
2077  qPrint(usingCd->name()),
2078  nd?qPrint(nd->name()):
2079  fd?qPrint(fd->name()):
2080  "<unknown>");
2081  }
2082 
2083  if (nd)
2084  {
2085  //printf("Inside namespace %s\n",nd->name().data());
2086  nd->addUsingDeclaration(usingCd);
2087  }
2088  else if (fd)
2089  {
2090  //printf("Inside file %s\n",fd->name().data());
2091  fd->addUsingDeclaration(usingCd);
2092  }
2093  }
2094 
2095  rootNav->releaseEntry();
2096  }
2098 }
2099 
2100 //----------------------------------------------------------------------
2101 
2102 static void findUsingDeclImports(EntryNav *rootNav)
2103 {
2104  if (rootNav->section()==Entry::USINGDECL_SEC &&
2105  (rootNav->parent()->section()&Entry::COMPOUND_MASK) // in a class/struct member
2106  )
2107  {
2108  //printf("Found using declaration %s at line %d of %s inside section %x\n",
2109  // root->name.data(),root->startLine,root->fileName.data(),
2110  // root->parent->section);
2111  QCString fullName=removeRedundantWhiteSpace(rootNav->parent()->name());
2112  fullName=stripAnonymousNamespaceScope(fullName);
2113  fullName=stripTemplateSpecifiersFromScope(fullName);
2114  ClassDef *cd = getClass(fullName);
2115  if (cd)
2116  {
2117  //printf("found class %s\n",cd->name().data());
2118  int i=rootNav->name().find("::");
2119  if (i!=-1)
2120  {
2121  QCString scope=rootNav->name().left(i);
2122  QCString memName=rootNav->name().right(rootNav->name().length()-i-2);
2123  ClassDef *bcd = getResolvedClass(cd,0,scope); // todo: file in fileScope parameter
2124  if (bcd)
2125  {
2126  //printf("found class %s\n",bcd->name().data());
2128  if (mndict)
2129  {
2130  MemberNameInfo *mni = mndict->find(memName);
2131  if (mni)
2132  {
2133  MemberNameInfoIterator mnii(*mni);
2134  MemberInfo *mi;
2135  for ( ; (mi=mnii.current()) ; ++mnii )
2136  {
2137  MemberDef *md = mi->memberDef;
2138  if (md && md->protection()!=Private)
2139  {
2140 
2141  rootNav->loadEntry(g_storage);
2142  Entry *root = rootNav->entry();
2143 
2144  //printf("found member %s\n",mni->memberName());
2145  MemberDef *newMd = 0;
2146  {
2147  QCString fileName = root->fileName;
2148  if (fileName.isEmpty() && rootNav->tagInfo())
2149  {
2150  fileName = rootNav->tagInfo()->tagName;
2151  }
2152  ArgumentList *templAl = md->templateArguments();
2153  ArgumentList *al = md->templateArguments();
2154  newMd = new MemberDef(
2155  fileName,root->startLine,root->startColumn,
2156  md->typeString(),memName,md->argsString(),
2157  md->excpString(),root->protection,root->virt,
2158  md->isStatic(),Member,md->memberType(),
2159  templAl,al
2160  );
2161  }
2162  newMd->setMemberClass(cd);
2163  cd->insertMember(newMd);
2164  if (!root->doc.isEmpty() || !root->brief.isEmpty())
2165  {
2166  newMd->setDocumentation(root->doc,root->docFile,root->docLine);
2167  newMd->setBriefDescription(root->brief,root->briefFile,root->briefLine);
2168  newMd->setInbodyDocumentation(root->inbodyDocs,root->inbodyFile,root->inbodyLine);
2169  }
2170  else
2171  {
2172  newMd->setDocumentation(md->documentation(),md->docFile(),md->docLine());
2173  newMd->setBriefDescription(md->briefDescription(),md->briefFile(),md->briefLine());
2175  }
2176  newMd->setDefinition(md->definition());
2177  newMd->enableCallGraph(root->callGraph);
2178  newMd->enableCallerGraph(root->callerGraph);
2179  newMd->setBitfields(md->bitfieldString());
2180  newMd->addSectionsToDefinition(root->anchors);
2181  newMd->setBodySegment(md->getStartBodyLine(),md->getEndBodyLine());
2182  newMd->setBodyDef(md->getBodyDef());
2183  newMd->setInitializer(md->initializer());
2184  newMd->setMaxInitLines(md->initializerLines());
2185  newMd->setMemberGroupId(root->mGrpId);
2187  newMd->setLanguage(root->lang);
2188  newMd->setId(root->id);
2189 
2190  rootNav->releaseEntry();
2191  }
2192  }
2193  }
2194  }
2195  }
2196  }
2197  }
2198 
2199  }
2201 }
2202 
2203 //----------------------------------------------------------------------
2204 
2206 {
2207  // first mark all files as not visited
2208  FileNameListIterator fnli(*Doxygen::inputNameList);
2209  FileName *fn;
2210  for (fnli.toFirst();(fn=fnli.current());++fnli)
2211  {
2212  FileNameIterator fni(*fn);
2213  FileDef *fd;
2214  for (;(fd=fni.current());++fni)
2215  {
2216  fd->visited=FALSE;
2217  }
2218  }
2219  // then recursively add using directives found in #include files
2220  // to files that have not been visited.
2221  for (fnli.toFirst();(fn=fnli.current());++fnli)
2222  {
2223  FileNameIterator fni(*fn);
2224  FileDef *fd;
2225  for (fni.toFirst();(fd=fni.current());++fni)
2226  {
2227  if (!fd->visited)
2228  {
2229  //printf("----- adding using directives for file %s\n",fd->name().data());
2231  }
2232  }
2233  }
2234 }
2235 
2236 //----------------------------------------------------------------------
2237 
2239  EntryNav *rootNav,
2240  ClassDef *cd,
2241  MemberType mtype,
2242  const QCString &name,
2243  bool fromAnnScope,
2244  MemberDef *fromAnnMemb,
2245  Protection prot,
2246  Relationship related)
2247 {
2248  Entry *root = rootNav->entry();
2249 
2251  QCString scopeSeparator="::";
2252  SrcLangExt lang = cd->getLanguage();
2253  if (lang==SrcLangExt_Java || lang==SrcLangExt_CSharp)
2254  {
2255  qualScope = substitute(qualScope,"::",".");
2256  scopeSeparator=".";
2257  }
2259  " class variable:\n"
2260  " `%s' `%s'::`%s' `%s' prot=`%d ann=%d init=`%s'\n",
2261  qPrint(root->type),
2262  qPrint(qualScope),
2263  qPrint(name),
2264  qPrint(root->args),
2265  root->protection,
2266  fromAnnScope,
2267  qPrint(root->initializer)
2268  );
2269 
2270  QCString def;
2271  if (!root->type.isEmpty())
2272  {
2273  if (related || mtype==MemberType_Friend || Config_getBool("HIDE_SCOPE_NAMES"))
2274  {
2275  if (root->spec&Entry::Alias) // turn 'typedef B A' into 'using A = B'
2276  {
2277  def="using "+name+" = "+root->type.mid(7);
2278  }
2279  else
2280  {
2281  def=root->type+" "+name+root->args;
2282  }
2283  }
2284  else
2285  {
2286  if (root->spec&Entry::Alias) // turn 'typedef B C::A' into 'using C::A = B'
2287  {
2288  def="using "+qualScope+scopeSeparator+name+" = "+root->type.mid(7);
2289  }
2290  else
2291  {
2292  def=root->type+" "+qualScope+scopeSeparator+name+root->args;
2293  }
2294  }
2295  }
2296  else
2297  {
2298  if (Config_getBool("HIDE_SCOPE_NAMES"))
2299  {
2300  def=name+root->args;
2301  }
2302  else
2303  {
2304  def=qualScope+scopeSeparator+name+root->args;
2305  }
2306  }
2307  def.stripPrefix("static ");
2308 
2309  // see if the member is already found in the same scope
2310  // (this may be the case for a static member that is initialized
2311  // outside the class)
2312  MemberName *mn=Doxygen::memberNameSDict->find(name);
2313  if (mn)
2314  {
2315  MemberNameIterator mni(*mn);
2316  MemberDef *md;
2317  for (mni.toFirst();(md=mni.current());++mni)
2318  {
2319  //printf("md->getClassDef()=%p cd=%p type=[%s] md->typeString()=[%s]\n",
2320  // md->getClassDef(),cd,root->type.data(),md->typeString());
2321  if (md->getClassDef()==cd &&
2323  // member already in the scope
2324  {
2325 
2326  if (root->lang==SrcLangExt_ObjC &&
2327  root->mtype==Property &&
2329  { // Objective-C 2.0 property
2330  // turn variable into a property
2331  md->setProtection(root->protection);
2333  }
2334  addMemberDocs(rootNav,md,def,0,FALSE);
2335  //printf(" Member already found!\n");
2336  return md;
2337  }
2338  }
2339  }
2340 
2341  QCString fileName = root->fileName;
2342  if (fileName.isEmpty() && rootNav->tagInfo())
2343  {
2344  fileName = rootNav->tagInfo()->tagName;
2345  }
2346 
2347  // new member variable, typedef or enum value
2348  MemberDef *md=new MemberDef(
2349  fileName,root->startLine,root->startColumn,
2350  root->type,name,root->args,root->exception,
2351  prot,Normal,root->stat,related,
2352  mtype,root->tArgLists ? root->tArgLists->getLast() : 0,0);
2353  md->setTagInfo(rootNav->tagInfo());
2354  md->setMemberClass(cd); // also sets outer scope (i.e. getOuterScope())
2355  //md->setDefFile(root->fileName);
2356  //md->setDefLine(root->startLine);
2357  md->setDocumentation(root->doc,root->docFile,root->docLine);
2358  md->setBriefDescription(root->brief,root->briefFile,root->briefLine);
2359  md->setInbodyDocumentation(root->inbodyDocs,root->inbodyFile,root->inbodyLine);
2360  md->setDefinition(def);
2361  md->setBitfields(root->bitfields);
2362  md->addSectionsToDefinition(root->anchors);
2363  md->setFromAnonymousScope(fromAnnScope);
2364  md->setFromAnonymousMember(fromAnnMemb);
2365  //md->setIndentDepth(indentDepth);
2366  md->setBodySegment(root->bodyLine,root->endBodyLine);
2367  md->setInitializer(root->initializer);
2368  md->setMaxInitLines(root->initLines);
2369  md->setMemberGroupId(root->mGrpId);
2370  md->setMemberSpecifiers(root->spec);
2371  md->setReadAccessor(root->read);
2372  md->setWriteAccessor(root->write);
2373  md->enableCallGraph(root->callGraph);
2374  md->enableCallerGraph(root->callerGraph);
2375  md->setHidden(root->hidden);
2376  md->setArtificial(root->artificial);
2377  md->setLanguage(root->lang);
2378  md->setId(root->id);
2379  addMemberToGroups(root,md);
2380  //if (root->mGrpId!=-1)
2381  //{
2382  // printf("memberdef %s in memberGroup %d\n",name.data(),root->mGrpId);
2383  // md->setMemberGroup(memberGroupDict[root->mGrpId]);
2384  //
2385  md->setBodyDef(rootNav->fileDef());
2386 
2387  //printf(" Adding member=%s\n",md->name().data());
2388  // add the member to the global list
2389  if (mn)
2390  {
2391  mn->append(md);
2392  }
2393  else // new variable name
2394  {
2395  mn = new MemberName(name);
2396  mn->append(md);
2397  //printf("Adding memberName=%s\n",mn->memberName());
2398  //Doxygen::memberNameDict.insert(name,mn);
2399  //Doxygen::memberNameList.append(mn);
2400  Doxygen::memberNameSDict->append(name,mn);
2401  // add the member to the class
2402  }
2403  //printf(" New member adding to %s (%p)!\n",cd->name().data(),cd);
2404  cd->insertMember(md);
2405  md->setRefItems(root->sli);
2406 
2407  //TODO: insert FileDef instead of filename strings.
2408  cd->insertUsedFile(rootNav->fileDef());
2409  rootNav->changeSection(Entry::EMPTY_SEC);
2410  return md;
2411 }
2412 
2413 //----------------------------------------------------------------------
2414 
2416  EntryNav *rootNav,
2417  MemberType mtype,
2418  const QCString &scope,
2419  const QCString &name,
2420  bool fromAnnScope,
2421  /*int indentDepth,*/
2422  MemberDef *fromAnnMemb)
2423 {
2424  Entry *root = rootNav->entry();
2426  " global variable:\n"
2427  " type=`%s' scope=`%s' name=`%s' args=`%s' prot=`%d mtype=%d lang=%d\n",
2428  qPrint(root->type),
2429  qPrint(scope),
2430  qPrint(name),
2431  qPrint(root->args),
2432  root->protection,
2433  mtype,
2434  root->lang
2435  );
2436 
2437  FileDef *fd = rootNav->fileDef();
2438 
2439  // see if we have a typedef that should hide a struct or union
2440  if (mtype==MemberType_Typedef && Config_getBool("TYPEDEF_HIDES_STRUCT"))
2441  {
2442  QCString type = root->type;
2443  type.stripPrefix("typedef ");
2444  if (type.left(7)=="struct " || type.left(6)=="union ")
2445  {
2446  type.stripPrefix("struct ");
2447  type.stripPrefix("union ");
2448  static QRegExp re("[a-z_A-Z][a-z_A-Z0-9]*");
2449  int l,s;
2450  s = re.match(type,0,&l);
2451  if (s>=0)
2452  {
2453  QCString typeValue = type.mid(s,l);
2454  ClassDef *cd = getClass(typeValue);
2455  if (cd)
2456  {
2457  // this typedef should hide compound name cd, so we
2458  // change the name that is displayed from cd.
2459  cd->setClassName(name);
2460  cd->setDocumentation(root->doc,root->docFile,root->docLine);
2461  cd->setBriefDescription(root->brief,root->briefFile,root->briefLine);
2462  return 0;
2463  }
2464  }
2465  }
2466  }
2467 
2468  // see if the function is inside a namespace
2469  NamespaceDef *nd = 0;
2470  if (!scope.isEmpty())
2471  {
2472  if (scope.find('@')!=-1) return 0; // anonymous scope!
2473  //nscope=removeAnonymousScopes(scope);
2474  //if (!nscope.isEmpty())
2475  //{
2476  nd = getResolvedNamespace(scope);
2477  //}
2478  }
2479  QCString def;
2480 
2481  // determine the definition of the global variable
2482  if (nd && !nd->name().isEmpty() && nd->name().at(0)!='@' &&
2483  !Config_getBool("HIDE_SCOPE_NAMES")
2484  )
2485  // variable is inside a namespace, so put the scope before the name
2486  {
2487  SrcLangExt lang = nd->getLanguage();
2489 
2490  if (!root->type.isEmpty())
2491  {
2492  if (root->spec&Entry::Alias) // turn 'typedef B NS::A' into 'using NS::A = B'
2493  {
2494  def="using "+nd->name()+sep+name+" = "+root->type;
2495  }
2496  else // normal member
2497  {
2498  def=root->type+" "+nd->name()+sep+name+root->args;
2499  }
2500  }
2501  else
2502  {
2503  def=nd->name()+sep+name+root->args;
2504  }
2505  }
2506  else
2507  {
2508  if (!root->type.isEmpty() && !root->name.isEmpty())
2509  {
2510  if (name.at(0)=='@') // dummy variable representing anonymous union
2511  {
2512  def=root->type;
2513  }
2514  else
2515  {
2516  if (root->spec&Entry::Alias) // turn 'typedef B A' into 'using A = B'
2517  {
2518  def="using "+root->name+" = "+root->type.mid(7);
2519  }
2520  else // normal member
2521  {
2522  def=root->type+" "+name+root->args;
2523  }
2524  }
2525  }
2526  else
2527  {
2528  def=name+root->args;
2529  }
2530  }
2531  def.stripPrefix("static ");
2532 
2533  MemberName *mn=Doxygen::functionNameSDict->find(name);
2534  if (mn)
2535  {
2536  //QCString nscope=removeAnonymousScopes(scope);
2537  //NamespaceDef *nd=0;
2538  //if (!nscope.isEmpty())
2539  if (!scope.isEmpty())
2540  {
2541  nd = getResolvedNamespace(scope);
2542  }
2543  MemberNameIterator mni(*mn);
2544  MemberDef *md;
2545  for (mni.toFirst();(md=mni.current());++mni)
2546  {
2547  if (
2548  ((nd==0 && md->getNamespaceDef()==0 && md->getFileDef() &&
2549  root->fileName==md->getFileDef()->absFilePath()
2550  ) // both variable names in the same file
2551  || (nd!=0 && md->getNamespaceDef()==nd) // both in same namespace
2552  )
2553  && !md->isDefine() // function style #define's can be "overloaded" by typedefs or variables
2554  && !md->isEnumerate() // in C# an enum value and enum can have the same name
2555  )
2556  // variable already in the scope
2557  {
2558  bool isPHPArray = md->getLanguage()==SrcLangExt_PHP &&
2559  md->argsString()!=root->args &&
2560  root->args.find('[')!=-1;
2561  bool staticsInDifferentFiles =
2562  root->stat && md->isStatic() &&
2563  root->fileName!=md->getDefFileName();
2564 
2565  if (md->getFileDef() &&
2566  !isPHPArray && // not a php array
2567  !staticsInDifferentFiles
2568  )
2569  // not a php array variable
2570  {
2571 
2573  " variable already found: scope=%s\n",qPrint(md->getOuterScope()->name()));
2574  addMemberDocs(rootNav,md,def,0,FALSE);
2575  md->setRefItems(root->sli);
2576  return md;
2577  }
2578  }
2579  }
2580  }
2581 
2582  QCString fileName = root->fileName;
2583  if (fileName.isEmpty() && rootNav->tagInfo())
2584  {
2585  fileName = rootNav->tagInfo()->tagName;
2586  }
2587 
2589  " new variable, nd=%s!\n",nd?qPrint(nd->name()):"<global>");
2590  // new global variable, enum value or typedef
2591  MemberDef *md=new MemberDef(
2592  fileName,root->startLine,root->startColumn,
2593  root->type,name,root->args,0,
2594  root->protection, Normal,root->stat,Member,
2595  mtype,root->tArgLists ? root->tArgLists->getLast() : 0,0);
2596  md->setTagInfo(rootNav->tagInfo());
2597  md->setMemberSpecifiers(root->spec);
2598  md->setDocumentation(root->doc,root->docFile,root->docLine);
2599  md->setBriefDescription(root->brief,root->briefFile,root->briefLine);
2600  md->setInbodyDocumentation(root->inbodyDocs,root->inbodyFile,root->inbodyLine);
2601  md->addSectionsToDefinition(root->anchors);
2602  md->setFromAnonymousScope(fromAnnScope);
2603  md->setFromAnonymousMember(fromAnnMemb);
2604  md->setInitializer(root->initializer);
2605  md->setMaxInitLines(root->initLines);
2606  md->setMemberGroupId(root->mGrpId);
2607  md->setDefinition(def);
2608  md->setLanguage(root->lang);
2609  md->setId(root->id);
2610  md->enableCallGraph(root->callGraph);
2611  md->enableCallerGraph(root->callerGraph);
2613  //md->setOuterScope(fd);
2614  if (!root->explicitExternal)
2615  {
2616  md->setBodySegment(root->bodyLine,root->endBodyLine);
2617  md->setBodyDef(fd);
2618  }
2619  addMemberToGroups(root,md);
2620 
2621  md->setRefItems(root->sli);
2622  if (nd && !nd->name().isEmpty() && nd->name().at(0)!='@')
2623  {
2624  md->setNamespace(nd);
2625  nd->insertMember(md);
2626  }
2627 
2628  // add member to the file (we do this even if we have already inserted
2629  // it into the namespace.
2630  if (fd)
2631  {
2632  md->setFileDef(fd);
2633  fd->insertMember(md);
2634  }
2635 
2636  // add member definition to the list of globals
2637  if (mn)
2638  {
2639  mn->append(md);
2640  }
2641  else
2642  {
2643  mn = new MemberName(name);
2644  mn->append(md);
2645  Doxygen::functionNameSDict->append(name,mn);
2646  }
2647  rootNav->changeSection(Entry::EMPTY_SEC);
2648  return md;
2649 }
2650 
2651 /*! See if the return type string \a type is that of a function pointer
2652  * \returns -1 if this is not a function pointer variable or
2653  * the index at which the closing brace of (...*name) was found.
2654  */
2655 static int findFunctionPtr(const QCString &type,int lang, int *pLength=0)
2656 {
2657  if (lang == SrcLangExt_Fortran) return -1; // Fortran does not have function pointers
2658  static const QRegExp re("([^)]*[\\*\\^][^)]*)");
2659  int i=-1,l;
2660  int bb=type.find('<');
2661  int be=type.findRev('>');
2662  if (!type.isEmpty() && // return type is non-empty
2663  (i=re.match(type,0,&l))!=-1 && // contains (...*...)
2664  type.find("operator")==-1 && // not an operator
2665  (type.find(")(")==-1 || type.find("typedef ")!=-1) &&
2666  // not a function pointer return type
2667  !(bb<i && i<be) // bug665855: avoid treating "typedef A<void (T*)> type" as a function pointer
2668  )
2669  {
2670  if (pLength) *pLength=l;
2671  //printf("findFunctionPtr=%d\n",i);
2672  return i;
2673  }
2674  else
2675  {
2676  //printf("findFunctionPtr=%d\n",-1);
2677  return -1;
2678  }
2679 }
2680 
2681 
2682 /*! Returns TRUE iff \a type is a class within scope \a context.
2683  * Used to detect variable declarations that look like function prototypes.
2684  */
2685 static bool isVarWithConstructor(EntryNav *rootNav)
2686 {
2687  static QRegExp initChars("[0-9\"'&*!^]+");
2688  static QRegExp idChars("[a-z_A-Z][a-z_A-Z0-9]*");
2689  bool result=FALSE;
2690  bool typeIsClass;
2691  QCString type;
2692  Definition *ctx = 0;
2693  FileDef *fd = 0;
2694  int ti;
2695 
2696  //printf("isVarWithConstructor(%s)\n",rootNav->name().data());
2697  rootNav->loadEntry(g_storage);
2698  Entry *root = rootNav->entry();
2699 
2700  if (rootNav->parent()->section() & Entry::COMPOUND_MASK)
2701  { // inside a class
2702  result=FALSE;
2703  goto done;
2704  }
2705  else if ((fd = rootNav->fileDef()) &&
2706  (fd->name().right(2)==".c" || fd->name().right(2)==".h")
2707  )
2708  { // inside a .c file
2709  result=FALSE;
2710  goto done;
2711  }
2712  if (root->type.isEmpty())
2713  {
2714  result=FALSE;
2715  goto done;
2716  }
2717  if (!rootNav->parent()->name().isEmpty())
2718  {
2719  ctx=Doxygen::namespaceSDict->find(rootNav->parent()->name());
2720  }
2721  type = root->type;
2722  // remove qualifiers
2723  findAndRemoveWord(type,"const");
2724  findAndRemoveWord(type,"static");
2725  findAndRemoveWord(type,"volatile");
2726  //if (type.left(6)=="const ") type=type.right(type.length()-6);
2727  typeIsClass=getResolvedClass(ctx,fd,type)!=0;
2728  if (!typeIsClass && (ti=type.find('<'))!=-1)
2729  {
2730  typeIsClass=getResolvedClass(ctx,fd,type.left(ti))!=0;
2731  }
2732  if (typeIsClass) // now we still have to check if the arguments are
2733  // types or values. Since we do not have complete type info
2734  // we need to rely on heuristics :-(
2735  {
2736  //printf("typeIsClass\n");
2737  ArgumentList *al = root->argList;
2738  if (al==0 || al->isEmpty())
2739  {
2740  result=FALSE; // empty arg list -> function prototype.
2741  goto done;
2742  }
2743  ArgumentListIterator ali(*al);
2744  Argument *a;
2745  for (ali.toFirst();(a=ali.current());++ali)
2746  {
2747  if (!a->name.isEmpty() || !a->defval.isEmpty())
2748  {
2749  if (a->name.find(initChars)==0)
2750  {
2751  result=TRUE;
2752  }
2753  else
2754  {
2755  result=FALSE; // arg has (type,name) pair -> function prototype
2756  }
2757  goto done;
2758  }
2759  if (a->type.isEmpty() || getResolvedClass(ctx,fd,a->type)!=0)
2760  {
2761  result=FALSE; // arg type is a known type
2762  goto done;
2763  }
2764  if (checkIfTypedef(ctx,fd,a->type))
2765  {
2766  //printf("%s:%d: false (arg is typedef)\n",__FILE__,__LINE__);
2767  result=FALSE; // argument is a typedef
2768  goto done;
2769  }
2770  if (a->type.at(a->type.length()-1)=='*' ||
2771  a->type.at(a->type.length()-1)=='&')
2772  // type ends with * or & => pointer or reference
2773  {
2774  result=FALSE;
2775  goto done;
2776  }
2777  if (a->type.find(initChars)==0)
2778  {
2779  result=TRUE; // argument type starts with typical initializer char
2780  goto done;
2781  }
2782  QCString resType=resolveTypeDef(ctx,a->type);
2783  if (resType.isEmpty()) resType=a->type;
2784  int len;
2785  if (idChars.match(resType,0,&len)==0) // resType starts with identifier
2786  {
2787  resType=resType.left(len);
2788  //printf("resType=%s\n",resType.data());
2789  if (resType=="int" || resType=="long" || resType=="float" ||
2790  resType=="double" || resType=="char" || resType=="signed" ||
2791  resType=="const" || resType=="unsigned" || resType=="void")
2792  {
2793  result=FALSE; // type keyword -> function prototype
2794  goto done;
2795  }
2796  }
2797  }
2798  result=TRUE;
2799  }
2800 
2801 done:
2802  //printf("isVarWithConstructor(%s,%s)=%d\n",rootNav->parent()->name().data(),
2803  // root->type.data(),result);
2804  rootNav->releaseEntry();
2805  return result;
2806 }
2807 
2808 static void addVariable(EntryNav *rootNav,int isFuncPtr=-1)
2809 {
2810  rootNav->loadEntry(g_storage);
2811  Entry *root = rootNav->entry();
2812 
2814  "VARIABLE_SEC: \n"
2815  " type=`%s' name=`%s' args=`%s' bodyLine=`%d' mGrpId=%d relates=%s\n",
2816  qPrint(root->type),
2817  qPrint(root->name),
2818  qPrint(root->args),
2819  root->bodyLine,
2820  root->mGrpId,
2821  qPrint(root->relates)
2822  );
2823  //printf("root->parent->name=%s\n",root->parent->name.data());
2824 
2825  if (root->type.isEmpty() && root->name.find("operator")==-1 &&
2826  (root->name.find('*')!=-1 || root->name.find('&')!=-1))
2827  {
2828  // recover from parse error caused by redundant braces
2829  // like in "int *(var[10]);", which is parsed as
2830  // type="" name="int *" args="(var[10])"
2831 
2832  root->type=root->name;
2833  static const QRegExp reName("[a-z_A-Z][a-z_A-Z0-9]*");
2834  int l=0;
2835  int i=root->args.isEmpty() ? -1 : reName.match(root->args,0,&l);
2836  if (i!=-1)
2837  {
2838  root->name=root->args.mid(i,l);
2839  root->args=root->args.mid(i+l,root->args.find(')',i+l)-i-l);
2840  }
2841  //printf("new: type=`%s' name=`%s' args=`%s'\n",
2842  // root->type.data(),root->name.data(),root->args.data());
2843  }
2844  else
2845  {
2846  int i=isFuncPtr;
2847  if (i==-1 && (root->spec&Entry::Alias)==0) i=findFunctionPtr(root->type,root->lang); // for typedefs isFuncPtr is not yet set
2848  Debug::print(Debug::Variables,0," functionPtr? %s\n",i!=-1?"yes":"no");
2849  if (i!=-1) // function pointer
2850  {
2851  int ai = root->type.find('[',i);
2852  if (ai>i) // function pointer array
2853  {
2854  root->args.prepend(root->type.right(root->type.length()-ai));
2855  root->type=root->type.left(ai);
2856  }
2857  else if (root->type.find(')',i)!=-1) // function ptr, not variable like "int (*bla)[10]"
2858  {
2859  root->type=root->type.left(root->type.length()-1);
2860  root->args.prepend(") ");
2861  //printf("root->type=%s root->args=%s\n",root->type.data(),root->args.data());
2862  }
2863  }
2864  else if (root->type.find("typedef ")!=-1 && root->type.right(2)=="()") // typedef void (func)(int)
2865  {
2866  root->type=root->type.left(root->type.length()-1);
2867  root->args.prepend(") ");
2868  }
2869  }
2870 
2872 
2873  // find the scope of this variable
2874  EntryNav *p = rootNav->parent();
2875  while ((p->section() & Entry::SCOPE_MASK))
2876  {
2877  QCString scopeName = p->name();
2878  if (!scopeName.isEmpty())
2879  {
2880  scope.prepend(scopeName);
2881  break;
2882  }
2883  p=p->parent();
2884  }
2885 
2886  MemberType mtype;
2888  ClassDef *cd=0;
2889  bool isRelated=FALSE;
2890  bool isMemberOf=FALSE;
2891 
2892  QCString classScope=stripAnonymousNamespaceScope(scope);
2893  classScope=stripTemplateSpecifiersFromScope(classScope,FALSE);
2894  QCString annScopePrefix=scope.left(scope.length()-classScope.length());
2895 
2896  if (root->name.findRev("::")!=-1)
2897  {
2898  if (root->type=="friend class" || root->type=="friend struct" ||
2899  root->type=="friend union")
2900  {
2901  cd=getClass(scope);
2902  if (cd)
2903  {
2904  addVariableToClass(rootNav, // entry
2905  cd, // class to add member to
2906  MemberType_Friend, // type of member
2907  name, // name of the member
2908  FALSE, // from Anonymous scope
2909  0, // anonymous member
2910  Public, // protection
2911  Member // related to a class
2912  );
2913  }
2914  }
2915  goto nextMember;
2916  /* skip this member, because it is a
2917  * static variable definition (always?), which will be
2918  * found in a class scope as well, but then we know the
2919  * correct protection level, so only then it will be
2920  * inserted in the correct list!
2921  */
2922  }
2923 
2924  if (type=="@")
2925  mtype=MemberType_EnumValue;
2926  else if (type.left(8)=="typedef ")
2927  mtype=MemberType_Typedef;
2928  else if (type.left(7)=="friend ")
2929  mtype=MemberType_Friend;
2930  else if (root->mtype==Property)
2931  mtype=MemberType_Property;
2932  else if (root->mtype==Event)
2933  mtype=MemberType_Event;
2934  else
2935  mtype=MemberType_Variable;
2936 
2937  if (!root->relates.isEmpty()) // related variable
2938  {
2939  isRelated=TRUE;
2940  isMemberOf=(root->relatesType == MemberOf);
2941  if (getClass(root->relates)==0 && !scope.isEmpty())
2942  scope=mergeScopes(scope,root->relates);
2943  else
2944  scope=root->relates;
2945  }
2946 
2947  cd=getClass(scope);
2948  if (cd==0 && classScope!=scope) cd=getClass(classScope);
2949  if (cd)
2950  {
2951  MemberDef *md=0;
2952 
2953  // if cd is an anonymous (=tag less) scope we insert the member
2954  // into a non-anonymous parent scope as well. This is needed to
2955  // be able to refer to it using \var or \fn
2956 
2957  //int indentDepth=0;
2958  int si=scope.find('@');
2959  //int anonyScopes = 0;
2960  //bool added=FALSE;
2961 
2962  static bool inlineSimpleStructs = Config_getBool("INLINE_SIMPLE_STRUCTS");
2963  if (si!=-1 && !inlineSimpleStructs) // anonymous scope or type
2964  {
2965  QCString pScope;
2966  ClassDef *pcd=0;
2967  pScope = scope.left(QMAX(si-2,0)); // scope without tag less parts
2968  if (!pScope.isEmpty())
2969  pScope.prepend(annScopePrefix);
2970  else if (annScopePrefix.length()>2)
2971  pScope=annScopePrefix.left(annScopePrefix.length()-2);
2972  if (name.at(0)!='@')
2973  {
2974  if (!pScope.isEmpty() && (pcd=getClass(pScope)))
2975  {
2976  md=addVariableToClass(rootNav, // entry
2977  pcd, // class to add member to
2978  mtype, // member type
2979  name, // member name
2980  TRUE, // from anonymous scope
2981  0, // from anonymous member
2982  root->protection,
2983  isMemberOf ? Foreign : isRelated ? Related : Member
2984  );
2985  //added=TRUE;
2986  }
2987  else // anonymous scope inside namespace or file => put variable in the global scope
2988  {
2989  if (mtype==MemberType_Variable)
2990  {
2991  md=addVariableToFile(rootNav,mtype,pScope,name,TRUE,0);
2992  }
2993  //added=TRUE;
2994  }
2995  }
2996  }
2997 
2998  //printf("name=`%s' scope=%s scope.right=%s\n",
2999  // name.data(),scope.data(),
3000  // scope.right(scope.length()-si).data());
3001  addVariableToClass(rootNav, // entry
3002  cd, // class to add member to
3003  mtype, // member type
3004  name, // name of the member
3005  FALSE, // from anonymous scope
3006  md, // from anonymous member
3007  root->protection,
3008  isMemberOf ? Foreign : isRelated ? Related : Member);
3009  }
3010  else if (!name.isEmpty()) // global variable
3011  {
3012  //printf("Inserting member in global scope %s!\n",scope.data());
3013  addVariableToFile(rootNav,mtype,scope,name,FALSE,/*0,*/0);
3014  }
3015 
3016 nextMember:
3017  rootNav->releaseEntry();
3018 }
3019 
3020 //----------------------------------------------------------------------
3021 // Searches the Entry tree for typedef documentation sections.
3022 // If found they are stored in their class or in the global list.
3023 static void buildTypedefList(EntryNav *rootNav)
3024 {
3025  //printf("buildVarList(%s)\n",rootNav->name().data());
3026  if (!rootNav->name().isEmpty() &&
3027  rootNav->section()==Entry::VARIABLE_SEC &&
3028  rootNav->type().find("typedef ")!=-1 // its a typedef
3029  )
3030  {
3031  addVariable(rootNav);
3032  }
3033  if (rootNav->children())
3034  {
3035  EntryNavListIterator eli(*rootNav->children());
3036  EntryNav *e;
3037  for (;(e=eli.current());++eli)
3038  {
3039  if (e->section()!=Entry::ENUM_SEC)
3040  {
3041  buildTypedefList(e);
3042  }
3043  }
3044  }
3045 }
3046 
3047 //----------------------------------------------------------------------
3048 // Searches the Entry tree for Variable documentation sections.
3049 // If found they are stored in their class or in the global list.
3050 
3051 static void buildVarList(EntryNav *rootNav)
3052 {
3053  //printf("buildVarList(%s) section=%08x\n",rootNav->name().data(),rootNav->section());
3054  int isFuncPtr=-1;
3055  if (!rootNav->name().isEmpty() &&
3056  (rootNav->type().isEmpty() || g_compoundKeywordDict.find(rootNav->type())==0) &&
3057  (
3058  (rootNav->section()==Entry::VARIABLE_SEC // it's a variable
3059  ) ||
3060  (rootNav->section()==Entry::FUNCTION_SEC && // or maybe a function pointer variable
3061  (isFuncPtr=findFunctionPtr(rootNav->type(),rootNav->lang()))!=-1
3062  ) ||
3063  (rootNav->section()==Entry::FUNCTION_SEC && // class variable initialized by constructor
3064  isVarWithConstructor(rootNav)
3065  )
3066  )
3067  ) // documented variable
3068  {
3069  addVariable(rootNav,isFuncPtr);
3070  }
3071  if (rootNav->children())
3072  {
3073  EntryNavListIterator eli(*rootNav->children());
3074  EntryNav *e;
3075  for (;(e=eli.current());++eli)
3076  {
3077  if (e->section()!=Entry::ENUM_SEC)
3078  {
3079  buildVarList(e);
3080  }
3081  }
3082  }
3083 }
3084 
3085 //----------------------------------------------------------------------
3086 // Searches the Entry tree for Interface sections (UNO IDL only).
3087 // If found they are stored in their service or in the global list.
3088 //
3089 
3091  EntryNav *const rootNav,
3092  ClassDef *const cd,
3093  QCString const& rname)
3094 {
3095  Entry *const root = rootNav->entry();
3096  FileDef *const fd = rootNav->fileDef();
3097  enum MemberType const type = (rootNav->section()==Entry::EXPORTED_INTERFACE_SEC)
3100  QCString fileName = root->fileName;
3101  if (fileName.isEmpty() && rootNav->tagInfo())
3102  {
3103  fileName = rootNav->tagInfo()->tagName;
3104  }
3105  MemberDef *const md = new MemberDef(
3106  fileName, root->startLine, root->startColumn, root->type, rname,
3107  "", "", root->protection, root->virt, root->stat, Member,
3108  type, 0, root->argList);
3109  md->setTagInfo(rootNav->tagInfo());
3110  md->setMemberClass(cd);
3111  md->setDocumentation(root->doc,root->docFile,root->docLine);
3112  md->setDocsForDefinition(false);
3113  md->setBriefDescription(root->brief,root->briefFile,root->briefLine);
3114  md->setInbodyDocumentation(root->inbodyDocs,root->inbodyFile,root->inbodyLine);
3115  md->setBodySegment(root->bodyLine,root->endBodyLine);
3116  md->setMemberSpecifiers(root->spec);
3117  md->setMemberGroupId(root->mGrpId);
3118  md->setTypeConstraints(root->typeConstr);
3119  md->setLanguage(root->lang);
3120  md->setBodyDef(fd);
3121  md->setFileDef(fd);
3122  md->addSectionsToDefinition(root->anchors);
3123  QCString const def = root->type + " " + rname;
3124  md->setDefinition(def);
3125  md->enableCallGraph(root->callGraph);
3126  md->enableCallerGraph(root->callerGraph);
3127 
3129  " Interface Member:\n"
3130  " `%s' `%s' proto=%d\n"
3131  " def=`%s'\n",
3132  qPrint(root->type),
3133  qPrint(rname),
3134  root->proto,
3135  qPrint(def)
3136  );
3137 
3138  // add member to the global list of all members
3139  MemberName *mn;
3140  if ((mn=Doxygen::memberNameSDict->find(rname)))
3141  {
3142  mn->append(md);
3143  }
3144  else
3145  {
3146  mn = new MemberName(rname);
3147  mn->append(md);
3148  Doxygen::memberNameSDict->append(rname,mn);
3149  }
3150 
3151  // add member to the class cd
3152  cd->insertMember(md);
3153  // also add the member as a "base" (to get nicer diagrams)
3154  // "optional" interface/service get Protected which turns into dashed line
3155  BaseInfo base(rname,
3156  (root->spec & (Entry::Optional)) ? Protected : Public,Normal);
3157  findClassRelation(rootNav,cd,cd,&base,0,DocumentedOnly,true)
3158  || findClassRelation(rootNav,cd,cd,&base,0,Undocumented,true);
3159  // add file to list of used files
3160  cd->insertUsedFile(fd);
3161 
3162  addMemberToGroups(root,md);
3163  rootNav->changeSection(Entry::EMPTY_SEC);
3164  md->setRefItems(root->sli);
3165 }
3166 
3167 static void buildInterfaceAndServiceList(EntryNav *const rootNav)
3168 {
3169  if (rootNav->section()==Entry::EXPORTED_INTERFACE_SEC ||
3171  {
3172  rootNav->loadEntry(g_storage);
3173  Entry *const root = rootNav->entry();
3174 
3176  "EXPORTED_INTERFACE_SEC:\n"
3177  " `%s' `%s'::`%s' `%s' relates=`%s' relatesType=`%d' file=`%s' line=`%d' bodyLine=`%d' #tArgLists=%d mGrpId=%d spec=%lld proto=%d docFile=%s\n",
3178  qPrint(root->type),
3179  qPrint(rootNav->parent()->name()),
3180  qPrint(root->name),
3181  qPrint(root->args),
3182  qPrint(root->relates),
3183  root->relatesType,
3184  qPrint(root->fileName),
3185  root->startLine,
3186  root->bodyLine,
3187  root->tArgLists ? (int)root->tArgLists->count() : -1,
3188  root->mGrpId,
3189  root->spec,
3190  root->proto,
3191  qPrint(root->docFile)
3192  );
3193 
3194  QCString const rname = removeRedundantWhiteSpace(root->name);
3195 
3196  if (!rname.isEmpty())
3197  {
3198  QCString const scope = rootNav->parent()->name();
3199  ClassDef *const cd = getClass(scope);
3200  assert(cd);
3201  if (cd && ((ClassDef::Interface == cd->compoundType()) ||
3202  (ClassDef::Service == cd->compoundType()) ||
3203  (ClassDef::Singleton == cd->compoundType())))
3204  {
3206  }
3207  else
3208  {
3209  assert(false); // was checked by scanner.l
3210  }
3211  }
3212  else if (rname.isEmpty())
3213  {
3214  warn(root->fileName,root->startLine,
3215  "Illegal member name found.");
3216  }
3217 
3218  rootNav->releaseEntry();
3219  }
3220  // can only have these in IDL anyway
3221  switch (rootNav->lang())
3222  {
3223  case SrcLangExt_Unknown: // fall through (root node always is Unknown)
3224  case SrcLangExt_IDL:
3226  break;
3227  default:
3228  return; // nothing to do here
3229  }
3230 }
3231 
3232 
3233 //----------------------------------------------------------------------
3234 // Searches the Entry tree for Function sections.
3235 // If found they are stored in their class or in the global list.
3236 
3237 static void addMethodToClass(EntryNav *rootNav,ClassDef *cd,
3238  const QCString &rname,bool isFriend)
3239 {
3240  Entry *root = rootNav->entry();
3241  FileDef *fd=rootNav->fileDef();
3242 
3243  int l;
3244  static QRegExp re("([a-z_A-Z0-9: ]*[ &*]+[ ]*");
3245  int ts=root->type.find('<');
3246  int te=root->type.findRev('>');
3247  int i=re.match(root->type,0,&l);
3248  if (i!=-1 && ts!=-1 && ts<te && ts<i && i<te) // avoid changing A<int(int*)>, see bug 677315
3249  {
3250  i=-1;
3251  }
3252 
3253  if (cd->getLanguage()==SrcLangExt_Cpp && // only C has pointers
3254  !root->type.isEmpty() && (root->spec&Entry::Alias)==0 && i!=-1) // function variable
3255  {
3256  root->args+=root->type.right(root->type.length()-i-l);
3257  root->type=root->type.left(i+l);
3258  }
3259 
3261  if (name.left(2)=="::") name=name.right(name.length()-2);
3262 
3263  MemberType mtype;
3264  if (isFriend) mtype=MemberType_Friend;
3265  else if (root->mtype==Signal) mtype=MemberType_Signal;
3266  else if (root->mtype==Slot) mtype=MemberType_Slot;
3267  else if (root->mtype==DCOP) mtype=MemberType_DCOP;
3268  else mtype=MemberType_Function;
3269 
3270  // strip redundant template specifier for constructors
3271  if ((fd==0 || fd->getLanguage()==SrcLangExt_Cpp) &&
3272  name.left(9)!="operator " && (i=name.find('<'))!=-1 && name.find('>')!=-1)
3273  {
3274  name=name.left(i);
3275  }
3276 
3277  QCString fileName = root->fileName;
3278  if (fileName.isEmpty() && rootNav->tagInfo())
3279  {
3280  fileName = rootNav->tagInfo()->tagName;
3281  }
3282 
3283  //printf("root->name=`%s; root->args=`%s' root->argList=`%s'\n",
3284  // root->name.data(),root->args.data(),argListToString(root->argList).data()
3285  // );
3286 
3287  // adding class member
3288  MemberDef *md=new MemberDef(
3289  fileName,root->startLine,root->startColumn,
3290  root->type,name,root->args,root->exception,
3291  root->protection,root->virt,
3292  root->stat && root->relatesType != MemberOf,
3293  root->relates.isEmpty() ? Member :
3294  root->relatesType == MemberOf ? Foreign : Related,
3295  mtype,root->tArgLists ? root->tArgLists->getLast() : 0,root->argList);
3296  md->setTagInfo(rootNav->tagInfo());
3297  md->setMemberClass(cd);
3298  md->setDocumentation(root->doc,root->docFile,root->docLine);
3299  md->setDocsForDefinition(!root->proto);
3300  md->setBriefDescription(root->brief,root->briefFile,root->briefLine);
3301  md->setInbodyDocumentation(root->inbodyDocs,root->inbodyFile,root->inbodyLine);
3302  md->setBodySegment(root->bodyLine,root->endBodyLine);
3303  md->setMemberSpecifiers(root->spec);
3304  md->setMemberGroupId(root->mGrpId);
3305  md->setTypeConstraints(root->typeConstr);
3306  md->setLanguage(root->lang);
3307  md->setId(root->id);
3308  md->setBodyDef(fd);
3309  md->setFileDef(fd);
3310  //md->setScopeTemplateArguments(root->tArgList);
3311  md->addSectionsToDefinition(root->anchors);
3312  QCString def;
3314  SrcLangExt lang = cd->getLanguage();
3315  QCString scopeSeparator=getLanguageSpecificSeparator(lang);
3316  if (scopeSeparator!="::")
3317  {
3318  qualScope = substitute(qualScope,"::",scopeSeparator);
3319  }
3320  if (lang==SrcLangExt_PHP)
3321  {
3322  // for PHP we use Class::method and Namespace\method
3323  scopeSeparator="::";
3324  }
3325  if (!root->relates.isEmpty() || isFriend || Config_getBool("HIDE_SCOPE_NAMES"))
3326  {
3327  if (!root->type.isEmpty())
3328  {
3329  if (root->argList)
3330  {
3331  def=root->type+" "+name;
3332  }
3333  else
3334  {
3335  def=root->type+" "+name+root->args;
3336  }
3337  }
3338  else
3339  {
3340  if (root->argList)
3341  {
3342  def=name;
3343  }
3344  else
3345  {
3346  def=name+root->args;
3347  }
3348  }
3349  }
3350  else
3351  {
3352  if (!root->type.isEmpty())
3353  {
3354  if (root->argList)
3355  {
3356  def=root->type+" "+qualScope+scopeSeparator+name;
3357  }
3358  else
3359  {
3360  def=root->type+" "+qualScope+scopeSeparator+name+root->args;
3361  }
3362  }
3363  else
3364  {
3365  if (root->argList)
3366  {
3367  def=qualScope+scopeSeparator+name;
3368  }
3369  else
3370  {
3371  def=qualScope+scopeSeparator+name+root->args;
3372  }
3373  }
3374  }
3375  if (def.left(7)=="friend ") def=def.right(def.length()-7);
3376  md->setDefinition(def);
3377  md->enableCallGraph(root->callGraph);
3378  md->enableCallerGraph(root->callerGraph);
3379 
3381  " Func Member:\n"
3382  " `%s' `%s'::`%s' `%s' proto=%d\n"
3383  " def=`%s'\n",
3384  qPrint(root->type),
3385  qPrint(qualScope),
3386  qPrint(rname),
3387  qPrint(root->args),
3388  root->proto,
3389  qPrint(def)
3390  );
3391 
3392  // add member to the global list of all members
3393  //printf("Adding member=%s class=%s\n",md->name().data(),cd->name().data());
3394  MemberName *mn;
3395  if ((mn=Doxygen::memberNameSDict->find(name)))
3396  {
3397  mn->append(md);
3398  }
3399  else
3400  {
3401  mn = new MemberName(name);
3402  mn->append(md);
3403  Doxygen::memberNameSDict->append(name,mn);
3404  }
3405 
3406  // add member to the class cd
3407  cd->insertMember(md);
3408  // add file to list of used files
3409  cd->insertUsedFile(fd);
3410 
3411  addMemberToGroups(root,md);
3412  rootNav->changeSection(Entry::EMPTY_SEC);
3413  md->setRefItems(root->sli);
3414 }
3415 
3416 
3417 static void buildFunctionList(EntryNav *rootNav)
3418 {
3419  if (rootNav->section()==Entry::FUNCTION_SEC)
3420  {
3421  rootNav->loadEntry(g_storage);
3422  Entry *root = rootNav->entry();
3423 
3425  "FUNCTION_SEC:\n"
3426  " `%s' `%s'::`%s' `%s' relates=`%s' relatesType=`%d' file=`%s' line=`%d' bodyLine=`%d' #tArgLists=%d mGrpId=%d spec=%lld proto=%d docFile=%s\n",
3427  qPrint(root->type),
3428  qPrint(rootNav->parent()->name()),
3429  qPrint(root->name),
3430  qPrint(root->args),
3431  qPrint(root->relates),
3432  root->relatesType,
3433  qPrint(root->fileName),
3434  root->startLine,
3435  root->bodyLine,
3436  root->tArgLists ? (int)root->tArgLists->count() : -1,
3437  root->mGrpId,
3438  root->spec,
3439  root->proto,
3440  qPrint(root->docFile)
3441  );
3442 
3443  bool isFriend=root->type.find("friend ")!=-1;
3444  QCString rname = removeRedundantWhiteSpace(root->name);
3445  //printf("rname=%s\n",rname.data());
3446 
3447  QCString scope=rootNav->parent()->name(); //stripAnonymousNamespaceScope(root->parent->name);
3448  if (!rname.isEmpty() && scope.find('@')==-1)
3449  {
3450  ClassDef *cd=0;
3451  // check if this function's parent is a class
3453 
3454  FileDef *rfd=rootNav->fileDef();
3455 
3456  int memIndex=rname.findRev("::");
3457 
3458  cd=getClass(scope);
3459  if (cd && scope+"::"==rname.left(scope.length()+2)) // found A::f inside A
3460  {
3461  // strip scope from name
3462  rname=rname.right(rname.length()-rootNav->parent()->name().length()-2);
3463  }
3464 
3465  NamespaceDef *nd = 0;
3466  bool isMember=FALSE;
3467  if (memIndex!=-1)
3468  {
3469  int ts=rname.find('<');
3470  int te=rname.find('>');
3471  if (memIndex>0 && (ts==-1 || te==-1))
3472  {
3473  // note: the following code was replaced by inMember=TRUE to deal with a
3474  // function rname='X::foo' of class X inside a namespace also called X...
3475  // bug id 548175
3476  //nd = Doxygen::namespaceSDict->find(rname.left(memIndex));
3477  //isMember = nd==0;
3478  //if (nd)
3479  //{
3480  // // strip namespace scope from name
3481  // scope=rname.left(memIndex);
3482  // rname=rname.right(rname.length()-memIndex-2);
3483  //}
3484  isMember = TRUE;
3485  }
3486  else
3487  {
3488  isMember=memIndex<ts || memIndex>te;
3489  }
3490  }
3491 
3492  static QRegExp re("([a-z_A-Z0-9: ]*[ &*]+[ ]*");
3493  int ts=root->type.find('<');
3494  int te=root->type.findRev('>');
3495  int ti;
3496  if (!rootNav->parent()->name().isEmpty() &&
3497  (rootNav->parent()->section() & Entry::COMPOUND_MASK) &&
3498  cd &&
3499  // do some fuzzy things to exclude function pointers
3500  (root->type.isEmpty() ||
3501  ((ti=root->type.find(re,0))==-1 || // type does not contain ..(..*
3502  (ts!=-1 && ts<te && ts<ti && ti<te) || // outside of < ... >
3503  root->args.find(")[")!=-1) || // and args not )[.. -> function pointer
3504  root->type.find(")(")!=-1 || root->type.find("operator")!=-1 || // type contains ..)(.. and not "operator"
3505  cd->getLanguage()!=SrcLangExt_Cpp // language other than C
3506  )
3507  )
3508  {
3509  Debug::print(Debug::Functions,0," --> member %s of class %s!\n",
3510  qPrint(rname),qPrint(cd->name()));
3511  addMethodToClass(rootNav,cd,rname,isFriend);
3512  }
3513  else if (!((rootNav->parent()->section() & Entry::COMPOUND_MASK)
3514  || rootNav->parent()->section()==Entry::OBJCIMPL_SEC
3515  ) &&
3516  !isMember &&
3517  (root->relates.isEmpty() || root->relatesType == Duplicate) &&
3518  root->type.left(7)!="extern " && root->type.left(8)!="typedef "
3519  )
3520  // no member => unrelated function
3521  {
3522  /* check the uniqueness of the function name in the file.
3523  * A file could contain a function prototype and a function definition
3524  * or even multiple function prototypes.
3525  */
3526  bool found=FALSE;
3527  MemberName *mn;
3528  MemberDef *md=0;
3529  if ((mn=Doxygen::functionNameSDict->find(rname)))
3530  {
3531  Debug::print(Debug::Functions,0," --> function %s already found!\n",qPrint(rname));
3532  MemberNameIterator mni(*mn);
3533  for (mni.toFirst();(!found && (md=mni.current()));++mni)
3534  {
3535  NamespaceDef *mnd = md->getNamespaceDef();
3536  NamespaceDef *rnd = 0;
3537  //printf("root namespace=%s\n",rootNav->parent()->name().data());
3538  QCString fullScope = scope;
3539  QCString parentScope = rootNav->parent()->name();
3540  if (!parentScope.isEmpty() && !leftScopeMatch(parentScope,scope))
3541  {
3542  if (!scope.isEmpty()) fullScope.prepend("::");
3543  fullScope.prepend(parentScope);
3544  }
3545  //printf("fullScope=%s\n",fullScope.data());
3546  rnd = getResolvedNamespace(fullScope);
3547  FileDef *mfd = md->getFileDef();
3548  QCString nsName,rnsName;
3549  if (mnd) nsName = mnd->name().copy();
3550  if (rnd) rnsName = rnd->name().copy();
3551  //printf("matching arguments for %s%s %s%s\n",
3552  // md->name().data(),md->argsString(),rname.data(),argListToString(root->argList).data());
3553  ArgumentList *mdAl = md->argumentList();
3554  ArgumentList *mdTempl = md->templateArguments();
3555 
3556  // in case of template functions, we need to check if the
3557  // functions have the same number of template parameters
3558  bool sameNumTemplateArgs = TRUE;
3559  bool matchingReturnTypes = TRUE;
3560  if (mdTempl!=0 && root->tArgLists)
3561  {
3562  if (mdTempl->count()!=root->tArgLists->getLast()->count())
3563  {
3564  sameNumTemplateArgs = FALSE;
3565  }
3566  if (md->typeString()!=removeRedundantWhiteSpace(root->type))
3567  {
3568  matchingReturnTypes = FALSE;
3569  }
3570  }
3571 
3572  bool staticsInDifferentFiles =
3573  root->stat && md->isStatic() && root->fileName!=md->getDefFileName();
3574 
3575  if (
3576  matchArguments2(md->getOuterScope(),mfd,mdAl,
3577  rnd ? rnd : Doxygen::globalScope,rfd,root->argList,
3578  FALSE) &&
3579  sameNumTemplateArgs &&
3580  matchingReturnTypes &&
3581  !staticsInDifferentFiles
3582  )
3583  {
3584  GroupDef *gd=0;
3585  if (root->groups->getFirst()!=0)
3586  {
3587  gd = Doxygen::groupSDict->find(root->groups->getFirst()->groupname.data());
3588  }
3589  //printf("match!\n");
3590  //printf("mnd=%p rnd=%p nsName=%s rnsName=%s\n",mnd,rnd,nsName.data(),rnsName.data());
3591  // see if we need to create a new member
3592  found=(mnd && rnd && nsName==rnsName) || // members are in the same namespace
3593  ((mnd==0 && rnd==0 && mfd!=0 && // no external reference and
3594  mfd->absFilePath()==root->fileName // prototype in the same file
3595  )
3596  );
3597  // otherwise, allow a duplicate global member with the same argument list
3598  if (!found && gd && gd==md->getGroupDef() && nsName==rnsName)
3599  {
3600  // member is already in the group, so we don't want to add it again.
3601  found=TRUE;
3602  }
3603 
3604  //printf("combining function with prototype found=%d in namespace %s\n",
3605  // found,nsName.data());
3606 
3607  if (found)
3608  {
3609  // merge argument lists
3610  mergeArguments(mdAl,root->argList,!root->doc.isEmpty());
3611  // merge documentation
3612  if (md->documentation().isEmpty() && !root->doc.isEmpty())
3613  {
3614  ArgumentList *argList = new ArgumentList;
3615  stringToArgumentList(root->args,argList);
3616  if (root->proto)
3617  {
3618  //printf("setDeclArgumentList to %p\n",argList);
3619  md->setDeclArgumentList(argList);
3620  }
3621  else
3622  {
3623  md->setArgumentList(argList);
3624  }
3625  }
3626 
3627  md->setDocumentation(root->doc,root->docFile,root->docLine);
3628  md->setInbodyDocumentation(root->inbodyDocs,root->inbodyFile,root->inbodyLine);
3629  md->setDocsForDefinition(!root->proto);
3630  if (md->getStartBodyLine()==-1 && root->bodyLine!=-1)
3631  {
3632  md->setBodySegment(root->bodyLine,root->endBodyLine);
3633  md->setBodyDef(rfd);
3634  }
3635 
3636  if (md->briefDescription().isEmpty() && !root->brief.isEmpty())
3637  {
3638  md->setArgsString(root->args);
3639  }
3640  md->setBriefDescription(root->brief,root->briefFile,root->briefLine);
3641 
3642  md->addSectionsToDefinition(root->anchors);
3643 
3644  md->enableCallGraph(md->hasCallGraph() || root->callGraph);
3645  md->enableCallerGraph(md->hasCallerGraph() || root->callerGraph);
3646 
3647  // merge ingroup specifiers
3648  if (md->getGroupDef()==0 && root->groups->getFirst()!=0)
3649  {
3650  addMemberToGroups(root,md);
3651  }
3652  else if (md->getGroupDef()!=0 && root->groups->count()==0)
3653  {
3654  //printf("existing member is grouped, new member not\n");
3655  root->groups->append(new Grouping(md->getGroupDef()->name(), md->getGroupPri()));
3656  }
3657  else if (md->getGroupDef()!=0 && root->groups->getFirst()!=0)
3658  {
3659  //printf("both members are grouped\n");
3660  }
3661 
3662  // if md is a declaration and root is the corresponding
3663  // definition, then turn md into a definition.
3664  if (md->isPrototype() && !root->proto)
3665  {
3666  md->setPrototype(FALSE);
3667  }
3668  }
3669  }
3670  }
3671  }
3672  if (!found) /* global function is unique with respect to the file */
3673  {
3674  Debug::print(Debug::Functions,0," --> new function %s found!\n",qPrint(rname));
3675  //printf("New function type=`%s' name=`%s' args=`%s' bodyLine=%d\n",
3676  // root->type.data(),rname.data(),root->args.data(),root->bodyLine);
3677 
3678  // new global function
3679  ArgumentList *tArgList = root->tArgLists ? root->tArgLists->getLast() : 0;
3681  md=new MemberDef(
3682  root->fileName,root->startLine,root->startColumn,
3683  root->type,name,root->args,root->exception,
3684  root->protection,root->virt,root->stat,Member,
3685  MemberType_Function,tArgList,root->argList);
3686 
3687  md->setTagInfo(rootNav->tagInfo());
3688  md->setLanguage(root->lang);
3689  md->setId(root->id);
3690  //md->setDefFile(root->fileName);
3691  //md->setDefLine(root->startLine);
3692  md->setDocumentation(root->doc,root->docFile,root->docLine);
3693  md->setBriefDescription(root->brief,root->briefFile,root->briefLine);
3694  md->setInbodyDocumentation(root->inbodyDocs,root->inbodyFile,root->inbodyLine);
3695  md->setPrototype(root->proto);
3696  md->setDocsForDefinition(!root->proto);
3697  md->setTypeConstraints(root->typeConstr);
3698  //md->setBody(root->body);
3699  md->setBodySegment(root->bodyLine,root->endBodyLine);
3700  FileDef *fd=rootNav->fileDef();
3701  md->setBodyDef(fd);
3702  md->addSectionsToDefinition(root->anchors);
3703  md->setMemberSpecifiers(root->spec);
3704  md->setMemberGroupId(root->mGrpId);
3705 
3706  // see if the function is inside a namespace that was not part of
3707  // the name already (in that case nd should be non-zero already)
3708  if (nd==0 && rootNav->parent()->section() == Entry::NAMESPACE_SEC )
3709  {
3710  //QCString nscope=removeAnonymousScopes(rootNav->parent()->name());
3711  QCString nscope=rootNav->parent()->name();
3712  if (!nscope.isEmpty())
3713  {
3714  nd = getResolvedNamespace(nscope);
3715  }
3716  }
3717 
3718  if (!scope.isEmpty())
3719  {
3721  if (sep!="::")
3722  {
3723  scope = substitute(scope,"::",sep);
3724  }
3725  scope+=sep;
3726  }
3727 
3728  QCString def;
3729  if (!root->type.isEmpty())
3730  {
3731  if (root->argList)
3732  {
3733  def=root->type+" "+scope+name;
3734  }
3735  else
3736  {
3737  def=root->type+" "+scope+name+root->args;
3738  }
3739  }
3740  else
3741  {
3742  if (root->argList)
3743  {
3744  def=scope+name.copy();
3745  }
3746  else
3747  {
3748  def=scope+name+root->args;
3749  }
3750  }
3752  " Global Function:\n"
3753  " `%s' `%s'::`%s' `%s' proto=%d\n"
3754  " def=`%s'\n",
3755  qPrint(root->type),
3756  qPrint(rootNav->parent()->name()),
3757  qPrint(rname),
3758  qPrint(root->args),
3759  root->proto,
3760  qPrint(def)
3761  );
3762  md->setDefinition(def);
3763  md->enableCallGraph(root->callGraph);
3764  md->enableCallerGraph(root->callerGraph);
3765  //if (root->mGrpId!=-1)
3766  //{
3767  // md->setMemberGroup(memberGroupDict[root->mGrpId]);
3768  //}
3769 
3770  md->setRefItems(root->sli);
3771  if (nd && !nd->name().isEmpty() && nd->name().at(0)!='@')
3772  {
3773  // add member to namespace
3774  md->setNamespace(nd);
3775  nd->insertMember(md);
3776  }
3777  if (fd)
3778  {
3779  // add member to the file (we do this even if we have already
3780  // inserted it into the namespace)
3781  md->setFileDef(fd);
3782  fd->insertMember(md);
3783  }
3784 
3785  // add member to the list of file members
3786  //printf("Adding member=%s\n",md->name().data());
3787  MemberName *mn;
3788  if ((mn=Doxygen::functionNameSDict->find(name)))
3789  {
3790  mn->append(md);
3791  }
3792  else
3793  {
3794  mn = new MemberName(name);
3795  mn->append(md);
3796  Doxygen::functionNameSDict->append(name,mn);
3797  }
3798  addMemberToGroups(root,md);
3799  if (root->relatesType == Simple) // if this is a relatesalso command,
3800  // allow find Member to pick it up
3801  {
3802  rootNav->changeSection(Entry::EMPTY_SEC); // Otherwise we have finished
3803  // with this entry.
3804 
3805  }
3806  }
3807  else
3808  {
3809  FileDef *fd=rootNav->fileDef();
3810  if (fd)
3811  {
3812  // add member to the file (we do this even if we have already
3813  // inserted it into the namespace)
3814  fd->insertMember(md);
3815  }
3816  }
3817 
3818  //printf("unrelated function %d `%s' `%s' `%s'\n",
3819  // root->parent->section,root->type.data(),rname.data(),root->args.data());
3820  }
3821  else
3822  {
3823  Debug::print(Debug::Functions,0," --> %s not processed!\n",qPrint(rname));
3824  }
3825  }
3826  else if (rname.isEmpty())
3827  {
3828  warn(root->fileName,root->startLine,
3829  "Illegal member name found."
3830  );
3831  }
3832 
3833  rootNav->releaseEntry();
3834  }
3836 }
3837 
3838 //----------------------------------------------------------------------
3839 
3840 static void findFriends()
3841 {
3842  //printf("findFriends()\n");
3843  MemberNameSDict::Iterator fnli(*Doxygen::functionNameSDict);
3844  MemberName *fn;
3845  for (;(fn=fnli.current());++fnli) // for each global function name
3846  {
3847  //printf("Function name=`%s'\n",fn->memberName());
3848  MemberName *mn;
3849  if ((mn=Doxygen::memberNameSDict->find(fn->memberName())))
3850  { // there are members with the same name
3851  //printf("Function name is also a member name\n");
3852  MemberNameIterator fni(*fn);
3853  MemberDef *fmd;
3854  for (;(fmd=fni.current());++fni) // for each function with that name
3855  {
3856  MemberNameIterator mni(*mn);
3857  MemberDef *mmd;
3858  for (;(mmd=mni.current());++mni) // for each member with that name
3859  {
3860  //printf("Checking for matching arguments
3861  // mmd->isRelated()=%d mmd->isFriend()=%d mmd->isFunction()=%d\n",
3862  // mmd->isRelated(),mmd->isFriend(),mmd->isFunction());
3863  ArgumentList *mmdAl = mmd->argumentList();
3864  ArgumentList *fmdAl = fmd->argumentList();
3865  if ((mmd->isFriend() || (mmd->isRelated() && mmd->isFunction())) &&
3866  matchArguments2(mmd->getOuterScope(), mmd->getFileDef(), mmdAl,
3867  fmd->getOuterScope(), fmd->getFileDef(), fmdAl,
3868  TRUE
3869  )
3870 
3871  ) // if the member is related and the arguments match then the
3872  // function is actually a friend.
3873  {
3874  mergeArguments(mmdAl,fmdAl);
3875  if (!fmd->documentation().isEmpty())
3876  {
3877  mmd->setDocumentation(fmd->documentation(),fmd->docFile(),fmd->docLine());
3878  }
3879  else if (!mmd->documentation().isEmpty())
3880  {
3881  fmd->setDocumentation(mmd->documentation(),mmd->docFile(),mmd->docLine());
3882  }
3883  if (mmd->briefDescription().isEmpty() && !fmd->briefDescription().isEmpty())
3884  {
3885  mmd->setBriefDescription(fmd->briefDescription(),fmd->briefFile(),fmd->briefLine());
3886  }
3887  else if (!mmd->briefDescription().isEmpty() && !fmd->briefDescription().isEmpty())
3888  {
3889  fmd->setBriefDescription(mmd->briefDescription(),mmd->briefFile(),mmd->briefLine());
3890  }
3891  if (!fmd->inbodyDocumentation().isEmpty())
3892  {
3894  }
3895  else if (!mmd->inbodyDocumentation().isEmpty())
3896  {
3898  }
3899  //printf("body mmd %d fmd %d\n",mmd->getStartBodyLine(),fmd->getStartBodyLine());
3900  if (mmd->getStartBodyLine()==-1 && fmd->getStartBodyLine()!=-1)
3901  {
3902  mmd->setBodySegment(fmd->getStartBodyLine(),fmd->getEndBodyLine());
3903  mmd->setBodyDef(fmd->getBodyDef());
3904  //mmd->setBodyMember(fmd);
3905  }
3906  else if (mmd->getStartBodyLine()!=-1 && fmd->getStartBodyLine()==-1)
3907  {
3908  fmd->setBodySegment(mmd->getStartBodyLine(),mmd->getEndBodyLine());
3909  fmd->setBodyDef(mmd->getBodyDef());
3910  //fmd->setBodyMember(mmd);
3911  }
3913 
3914  mmd->enableCallGraph(mmd->hasCallGraph() || fmd->hasCallGraph());
3915  mmd->enableCallerGraph(mmd->hasCallerGraph() || fmd->hasCallerGraph());
3916  fmd->enableCallGraph(mmd->hasCallGraph() || fmd->hasCallGraph());
3917  fmd->enableCallerGraph(mmd->hasCallerGraph() || fmd->hasCallerGraph());
3918  }
3919  }
3920  }
3921  }
3922  }
3923 }
3924 
3925 //----------------------------------------------------------------------
3926 
3928 {
3929  //printf("---- transferFunctionDocumentation()\n");
3930 
3931  // find matching function declaration and definitions.
3932  MemberNameSDict::Iterator mnli(*Doxygen::functionNameSDict);
3933  MemberName *mn;
3934  for (;(mn=mnli.current());++mnli)
3935  {
3936  //printf("memberName=%s count=%d\n",mn->memberName(),mn->count());
3937  MemberDef *mdef=0,*mdec=0;
3938  MemberNameIterator mni1(*mn);
3939  /* find a matching function declaration and definition for this function */
3940  for (;(mdec=mni1.current());++mni1)
3941  {
3942  if (mdec->isPrototype() ||
3943  (mdec->isVariable() && mdec->isExternal())
3944  )
3945  {
3946  MemberNameIterator mni2(*mn);
3947  for (;(mdef=mni2.current());++mni2)
3948  {
3950  }
3951  }
3952  }
3953  }
3954 }
3955 
3956 //----------------------------------------------------------------------
3957 
3959 {
3960  MemberNameSDict::Iterator mnli(*Doxygen::functionNameSDict);
3961  MemberName *mn;
3962  for (;(mn=mnli.current());++mnli)
3963  {
3964  MemberDef *md,*mdef=0,*mdec=0;
3965  MemberNameIterator mni(*mn);
3966  /* find a matching function declaration and definition for this function */
3967  for (;(md=mni.current());++mni)
3968  {
3969  if (md->isPrototype())
3970  mdec=md;
3971  else if (md->isVariable() && md->isExternal())
3972  mdec=md;
3973 
3974  if (md->isFunction() && !md->isStatic() && !md->isPrototype())
3975  mdef=md;
3976  else if (md->isVariable() && !md->isExternal() && !md->isStatic())
3977  mdef=md;
3978  }
3979  if (mdef && mdec)
3980  {
3981  ArgumentList *mdefAl = mdef->argumentList();
3982  ArgumentList *mdecAl = mdec->argumentList();
3983  if (
3984  matchArguments2(mdef->getOuterScope(),mdef->getFileDef(),mdefAl,
3985  mdec->getOuterScope(),mdec->getFileDef(),mdecAl,
3986  TRUE
3987  )
3988  ) /* match found */
3989  {
3990  MemberSDict *defDict = mdef->getReferencesMembers();
3991  MemberSDict *decDict = mdec->getReferencesMembers();
3992  if (defDict!=0)
3993  {
3994  MemberSDict::IteratorDict msdi(*defDict);
3995  MemberDef *rmd;
3996  for (msdi.toFirst();(rmd=msdi.current());++msdi)
3997  {
3998  if (decDict==0 || decDict->find(rmd->name())==0)
3999  {
4000  mdec->addSourceReferences(rmd);
4001  }
4002  }
4003  }
4004  if (decDict!=0)
4005  {
4006  MemberSDict::IteratorDict msdi(*decDict);
4007  MemberDef *rmd;
4008  for (msdi.toFirst();(rmd=msdi.current());++msdi)
4009  {
4010  if (defDict==0 || defDict->find(rmd->name())==0)
4011  {
4012  mdef->addSourceReferences(rmd);
4013  }
4014  }
4015  }
4016 
4017  defDict = mdef->getReferencedByMembers();
4018  decDict = mdec->getReferencedByMembers();
4019  if (defDict!=0)
4020  {
4021  MemberSDict::IteratorDict msdi(*defDict);
4022  MemberDef *rmd;
4023  for (msdi.toFirst();(rmd=msdi.current());++msdi)
4024  {
4025  if (decDict==0 || decDict->find(rmd->name())==0)
4026  {
4027  mdec->addSourceReferencedBy(rmd);
4028  }
4029  }
4030  }
4031  if (decDict!=0)
4032  {
4033  MemberSDict::IteratorDict msdi(*decDict);
4034  MemberDef *rmd;
4035  for (msdi.toFirst();(rmd=msdi.current());++msdi)
4036  {
4037  if (defDict==0 || defDict->find(rmd->name())==0)
4038  {
4039  mdef->addSourceReferencedBy(rmd);
4040  }
4041  }
4042  }
4043  }
4044  }
4045  }
4046 }
4047 
4048 //----------------------------------------------------------------------
4049 
4051 {
4052  // find match between function declaration and definition for
4053  // related functions
4054  MemberNameSDict::Iterator mnli(*Doxygen::functionNameSDict);
4055  MemberName *mn;
4056  for (mnli.toFirst();(mn=mnli.current());++mnli)
4057  {
4058  MemberDef *md;
4059  MemberNameIterator mni(*mn);
4060  /* find a matching function declaration and definition for this function */
4061  for (mni.toFirst();(md=mni.current());++mni) // for each global function
4062  {
4063  //printf(" Function `%s'\n",md->name().data());
4064  MemberName *rmn;
4065  if ((rmn=Doxygen::memberNameSDict->find(md->name()))) // check if there is a member with the same name
4066  {
4067  //printf(" Member name found\n");
4068  MemberDef *rmd;
4069  MemberNameIterator rmni(*rmn);
4070  for (rmni.toFirst();(rmd=rmni.current());++rmni) // for each member with the same name
4071  {
4072  ArgumentList *mdAl = md->argumentList();
4073  ArgumentList *rmdAl = rmd->argumentList();
4074  //printf(" Member found: related=`%d'\n",rmd->isRelated());
4075  if ((rmd->isRelated() || rmd->isForeign()) && // related function
4076  matchArguments2( md->getOuterScope(), md->getFileDef(), mdAl,
4077  rmd->getOuterScope(),rmd->getFileDef(),rmdAl,
4078  TRUE
4079  )
4080  )
4081  {
4082  //printf(" Found related member `%s'\n",md->name().data());
4083  if (rmd->relatedAlso())
4084  md->setRelatedAlso(rmd->relatedAlso());
4085  else if (rmd->isForeign())
4086  md->makeForeign();
4087  else
4088  md->makeRelated();
4089  }
4090  }
4091  }
4092  }
4093  }
4094 }
4095 
4096 //----------------------------------------------------------------------
4097 
4098 /*! make a dictionary of all template arguments of class cd
4099  * that are part of the base class name.
4100  * Example: A template class A with template arguments <R,S,T>
4101  * that inherits from B<T,T,S> will have T and S in the dictionary.
4102  */
4103 static QDict<int> *getTemplateArgumentsInName(ArgumentList *templateArguments,const QCString &name)
4104 {
4105  QDict<int> *templateNames = new QDict<int>(17);
4106  templateNames->setAutoDelete(TRUE);
4107  static QRegExp re("[a-z_A-Z][a-z_A-Z0-9:]*");
4108  if (templateArguments)
4109  {
4110  ArgumentListIterator ali(*templateArguments);
4111  Argument *arg;
4112  int count=0;
4113  for (ali.toFirst();(arg=ali.current());++ali,count++)
4114  {
4115  int i,p=0,l;
4116  while ((i=re.match(name,p,&l))!=-1)
4117  {
4118  QCString n = name.mid(i,l);
4119  if (n==arg->name)
4120  {
4121  if (templateNames->find(n)==0)
4122  {
4123  templateNames->insert(n,new int(count));
4124  }
4125  }
4126  p=i+l;
4127  }
4128  }
4129  }
4130  return templateNames;
4131 }
4132 
4133 /*! Searches a class from within \a context and \a cd and returns its
4134  * definition if found (otherwise 0 is returned).
4135  */
4137 {
4138  ClassDef *result=0;
4139  if (cd==0)
4140  {
4141  return result;
4142  }
4143  FileDef *fd=cd->getFileDef();
4144  if (context && cd!=context)
4145  {
4146  result = getResolvedClass(context,0,name,0,0,TRUE,TRUE);
4147  }
4148  if (result==0)
4149  {
4150  result = getResolvedClass(cd,fd,name,0,0,TRUE,TRUE);
4151  }
4152  if (result==0) // try direct class, needed for namespaced classes imported via tag files (see bug624095)
4153  {
4154  result = getClass(name);
4155  }
4156  if (result==0 &&
4158  name.find('<')!=-1)
4159  {
4160  result = Doxygen::genericsDict->find(name);
4161  }
4162  //printf("** Trying to find %s within context %s class %s result=%s lookup=%p\n",
4163  // name.data(),
4164  // context ? context->name().data() : "<none>",
4165  // cd ? cd->name().data() : "<none>",
4166  // result ? result->name().data() : "<none>",
4167  // Doxygen::classSDict->find(name)
4168  // );
4169  return result;
4170 }
4171 
4172 
4173 static void findUsedClassesForClass(EntryNav *rootNav,
4174  Definition *context,
4175  ClassDef *masterCd,
4176  ClassDef *instanceCd,
4177  bool isArtificial,
4178  ArgumentList *actualArgs=0,
4179  QDict<int> *templateNames=0
4180  )
4181 {
4182  masterCd->visited=TRUE;
4183  ArgumentList *formalArgs = masterCd->templateArguments();
4184  if (masterCd->memberNameInfoSDict())
4185  {
4187  MemberNameInfo *mni;
4188  for (;(mni=mnili.current());++mnili)
4189  {
4190  MemberNameInfoIterator mnii(*mni);
4191  MemberInfo *mi;
4192  for (mnii.toFirst();(mi=mnii.current());++mnii)
4193  {
4194  MemberDef *md=mi->memberDef;
4195  if (md->isVariable() || md->isObjCProperty()) // for each member variable in this class
4196  {
4197  //printf(" Found variable %s in class %s\n",md->name().data(),masterCd->name().data());
4198  QCString type = normalizeNonTemplateArgumentsInString(md->typeString(),masterCd,formalArgs);
4199  QCString typedefValue = resolveTypeDef(masterCd,type);
4200  if (!typedefValue.isEmpty())
4201  {
4202  type = typedefValue;
4203  }
4204  int pos=0;
4205  QCString usedClassName;
4206  QCString templSpec;
4207  bool found=FALSE;
4208  // the type can contain template variables, replace them if present
4209  if (actualArgs)
4210  {
4211  type = substituteTemplateArgumentsInString(type,formalArgs,actualArgs);
4212  }
4213 
4214  //printf(" template substitution gives=%s\n",type.data());
4215  while (!found && extractClassNameFromType(type,pos,usedClassName,templSpec,rootNav->lang())!=-1)
4216  {
4217  // find the type (if any) that matches usedClassName
4218  ClassDef *typeCd = getResolvedClass(masterCd,
4219  masterCd->getFileDef(),
4220  usedClassName,
4221  0,0,
4222  FALSE,TRUE
4223  );
4224  //printf("====> usedClassName=%s -> typeCd=%s\n",
4225  // usedClassName.data(),typeCd?typeCd->name().data():"<none>");
4226  if (typeCd)
4227  {
4228  usedClassName = typeCd->name();
4229  }
4230 
4231  int sp=usedClassName.find('<');
4232  if (sp==-1) sp=0;
4233  int si=usedClassName.findRev("::",sp);
4234  if (si!=-1)
4235  {
4236  // replace any namespace aliases
4237  replaceNamespaceAliases(usedClassName,si);
4238  }
4239  // add any template arguments to the class
4240  QCString usedName = removeRedundantWhiteSpace(usedClassName+templSpec);
4241  //printf(" usedName=%s\n",usedName.data());
4242 
4243  bool delTempNames=FALSE;
4244  if (templateNames==0)
4245  {
4246  templateNames = getTemplateArgumentsInName(formalArgs,usedName);
4247  delTempNames=TRUE;
4248  }
4249  BaseInfo bi(usedName,Public,Normal);
4250  findClassRelation(rootNav,context,instanceCd,&bi,templateNames,TemplateInstances,isArtificial);
4251 
4252  if (masterCd->templateArguments())
4253  {
4254  ArgumentListIterator ali(*masterCd->templateArguments());
4255  Argument *arg;
4256  int count=0;
4257  for (ali.toFirst();(arg=ali.current());++ali,++count)
4258  {
4259  if (arg->name==usedName) // type is a template argument
4260  {
4261  found=TRUE;
4262  Debug::print(Debug::Classes,0," New used class `%s'\n", qPrint(usedName));
4263 
4264  ClassDef *usedCd = Doxygen::hiddenClasses->find(usedName);
4265  if (usedCd==0)
4266  {
4267  usedCd = new ClassDef(
4268  masterCd->getDefFileName(),masterCd->getDefLine(),
4269  masterCd->getDefColumn(),
4270  usedName,
4271  ClassDef::Class);
4272  //printf("making %s a template argument!!!\n",usedCd->name().data());
4273  usedCd->makeTemplateArgument();
4274  usedCd->setUsedOnly(TRUE);
4275  usedCd->setLanguage(masterCd->getLanguage());
4276  Doxygen::hiddenClasses->append(usedName,usedCd);
4277  }
4278  if (isArtificial) usedCd->setArtificial(TRUE);
4279  Debug::print(Debug::Classes,0," Adding used class `%s' (1)\n", qPrint(usedCd->name()));
4280  instanceCd->addUsedClass(usedCd,md->name(),md->protection());
4281  usedCd->addUsedByClass(instanceCd,md->name(),md->protection());
4282  }
4283  }
4284  }
4285 
4286  if (!found)
4287  {
4288  ClassDef *usedCd=findClassWithinClassContext(context,masterCd,usedName);
4289  //printf("Looking for used class %s: result=%s master=%s\n",
4290  // usedName.data(),usedCd?usedCd->name().data():"<none>",masterCd?masterCd->name().data():"<none>");
4291 
4292  if (usedCd)
4293  {
4294  found=TRUE;
4295  Debug::print(Debug::Classes,0," Adding used class `%s' (2)\n", qPrint(usedCd->name()));
4296  instanceCd->addUsedClass(usedCd,md->name(),md->protection()); // class exists
4297  usedCd->addUsedByClass(instanceCd,md->name(),md->protection());
4298  }
4299  }
4300  if (delTempNames)
4301  {
4302  delete templateNames;
4303  templateNames=0;
4304  }
4305  }
4306  if (!found && !type.isEmpty()) // used class is not documented in any scope
4307  {
4308  ClassDef *usedCd = Doxygen::hiddenClasses->find(type);
4309  if (usedCd==0 && !Config_getBool("HIDE_UNDOC_RELATIONS"))
4310  {
4311  if (type.right(2)=="(*" || type.right(2)=="(^") // type is a function pointer
4312  {
4313  type+=md->argsString();
4314  }
4315  Debug::print(Debug::Classes,0," New undocumented used class `%s'\n", qPrint(type));
4316  usedCd = new ClassDef(
4317  masterCd->getDefFileName(),masterCd->getDefLine(),
4318  masterCd->getDefColumn(),
4320  usedCd->setUsedOnly(TRUE);
4321  usedCd->setLanguage(masterCd->getLanguage());
4322  Doxygen::hiddenClasses->append(type,usedCd);
4323  }
4324  if (usedCd)
4325  {
4326  if (isArtificial) usedCd->setArtificial(TRUE);
4327  Debug::print(Debug::Classes,0," Adding used class `%s' (3)\n", qPrint(usedCd->name()));
4328  instanceCd->addUsedClass(usedCd,md->name(),md->protection());
4329  usedCd->addUsedByClass(instanceCd,md->name(),md->protection());
4330  }
4331  }
4332  }
4333  }
4334  }
4335  }
4336  else
4337  {
4338  //printf("no members for class %s (%p)\n",masterCd->name().data(),masterCd);
4339  }
4340 }
4341 
4343  EntryNav *rootNav,
4344  Definition *context,
4345  ClassDef *masterCd,
4346  ClassDef *instanceCd,
4348  bool isArtificial,
4349  ArgumentList *actualArgs=0,
4350  QDict<int> *templateNames=0
4351  )
4352 {
4353  Entry *root = rootNav->entry();
4354  //if (masterCd->visited) return;
4355  masterCd->visited=TRUE;
4356  // The base class could ofcouse also be a non-nested class
4357  ArgumentList *formalArgs = masterCd->templateArguments();
4358  QListIterator<BaseInfo> bii(*root->extends);
4359  BaseInfo *bi=0;
4360  for (bii.toFirst();(bi=bii.current());++bii)
4361  {
4362  //printf("masterCd=%s bi->name='%s' #actualArgs=%d\n",
4363  // masterCd->localName().data(),bi->name.data(),actualArgs?(int)actualArgs->count():-1);
4364  bool delTempNames=FALSE;
4365  if (templateNames==0)
4366  {
4367  templateNames = getTemplateArgumentsInName(formalArgs,bi->name);
4368  delTempNames=TRUE;
4369  }
4370  BaseInfo tbi(bi->name,bi->prot,bi->virt);
4371  if (actualArgs) // substitute the formal template arguments of the base class
4372  {
4373  tbi.name = substituteTemplateArgumentsInString(bi->name,formalArgs,actualArgs);
4374  }
4375  //printf("bi->name=%s tbi.name=%s\n",bi->name.data(),tbi.name.data());
4376 
4377  if (mode==DocumentedOnly)
4378  {
4379  // find a documented base class in the correct scope
4380  if (!findClassRelation(rootNav,context,instanceCd,&tbi,templateNames,DocumentedOnly,isArtificial))
4381  {
4382  // 1.8.2: decided to show inheritance relations even if not documented,
4383  // we do make them artificial, so they do not appear in the index
4384  //if (!Config_getBool("HIDE_UNDOC_RELATIONS"))
4385  bool b = Config_getBool("HIDE_UNDOC_RELATIONS") ? TRUE : isArtificial;
4386  //{
4387  // no documented base class -> try to find an undocumented one
4388  findClassRelation(rootNav,context,instanceCd,&tbi,templateNames,Undocumented,b);
4389  //}
4390  }
4391  }
4392  else if (mode==TemplateInstances)
4393  {
4394  findClassRelation(rootNav,context,instanceCd,&tbi,templateNames,TemplateInstances,isArtificial);
4395  }
4396  if (delTempNames)
4397  {
4398  delete templateNames;
4399  templateNames=0;
4400  }
4401  }
4402 }
4403 
4404 //----------------------------------------------------------------------
4405 
4407  Definition *context,
4408  ClassDef *templateClass,const QCString &templSpec,
4409  QDict<int> *templateNames,
4410  bool isArtificial)
4411 {
4412  Debug::print(Debug::Classes,0," derived from template %s with parameters %s\n",
4413  qPrint(templateClass->name()),qPrint(templSpec));
4414  //printf("findTemplateInstanceRelation(base=%s templSpec=%s templateNames=",
4415  // templateClass->name().data(),templSpec.data());
4416  //if (templateNames)
4417  //{
4418  // QDictIterator<int> qdi(*templateNames);
4419  // int *tempArgIndex;
4420  // for (;(tempArgIndex=qdi.current());++qdi)
4421  // {
4422  // printf("(%s->%d) ",qdi.currentKey(),*tempArgIndex);
4423  // }
4424  //}
4425  //printf("\n");
4426 
4427  bool existingClass = (templSpec ==
4428  tempArgListToString(templateClass->templateArguments(),root->lang)
4429  );
4430  if (existingClass) return TRUE;
4431 
4432  bool freshInstance=FALSE;
4433  ClassDef *instanceClass = templateClass->insertTemplateInstance(
4434  root->fileName,root->startLine,root->startColumn,templSpec,freshInstance);
4435  if (isArtificial) instanceClass->setArtificial(TRUE);
4436  instanceClass->setLanguage(root->lang);
4437 
4438  if (freshInstance)
4439  {
4440  Debug::print(Debug::Classes,0," found fresh instance '%s'!\n",qPrint(instanceClass->name()));
4441  Doxygen::classSDict->append(instanceClass->name(),instanceClass);
4442  instanceClass->setTemplateBaseClassNames(templateNames);
4443 
4444  // search for new template instances caused by base classes of
4445  // instanceClass
4446  EntryNav *templateRootNav = g_classEntries.find(templateClass->name());
4447  if (templateRootNav)
4448  {
4449  bool unloadNeeded=FALSE;
4450  Entry *templateRoot = templateRootNav->entry();
4451  if (templateRoot==0) // not yet loaded
4452  {
4453  templateRootNav->loadEntry(g_storage);
4454  templateRoot = templateRootNav->entry();
4455  ASSERT(templateRoot!=0); // now it should really be loaded
4456  unloadNeeded=TRUE;
4457  }
4458 
4459  Debug::print(Debug::Classes,0," template root found %s templSpec=%s!\n",
4460  qPrint(templateRoot->name),qPrint(templSpec));
4461  ArgumentList *templArgs = new ArgumentList;
4462  stringToArgumentList(templSpec,templArgs);
4463  findBaseClassesForClass(templateRootNav,context,templateClass,instanceClass,
4464  TemplateInstances,isArtificial,templArgs,templateNames);
4465 
4466  findUsedClassesForClass(templateRootNav,context,templateClass,instanceClass,
4467  isArtificial,templArgs,templateNames);
4468  delete templArgs;
4469 
4470  if (unloadNeeded) // still cleanup to do
4471  {
4472  templateRootNav->releaseEntry();
4473  }
4474  }
4475  else
4476  {
4477  Debug::print(Debug::Classes,0," no template root entry found!\n");
4478  // TODO: what happened if we get here?
4479  }
4480 
4481  //Debug::print(Debug::Classes,0," Template instance %s : \n",instanceClass->name().data());
4482  //ArgumentList *tl = templateClass->templateArguments();
4483  }
4484  else
4485  {
4486  Debug::print(Debug::Classes,0," instance already exists!\n");
4487  }
4488  return TRUE;
4489 }
4490 
4492 {
4493  QCString n=name;
4494  int index=n.find('<');
4495  if (index!=-1)
4496  {
4497  n=n.left(index);
4498  }
4499  bool result = rightScopeMatch(scope,n);
4500  return result;
4501 }
4502 
4503 /*! Searches for the end of a template in prototype \a s starting from
4504  * character position \a startPos. If the end was found the position
4505  * of the closing > is returned, otherwise -1 is returned.
4506  *
4507  * Handles exotic cases such as
4508  * \code
4509  * Class<(id<0)>
4510  * Class<bits<<2>
4511  * Class<"<">
4512  * Class<'<'>
4513  * Class<(")<")>
4514  * \endcode
4515  */
4516 static int findEndOfTemplate(const QCString &s,int startPos)
4517 {
4518  // locate end of template
4519  int e=startPos;
4520  int brCount=1;
4521  int roundCount=0;
4522  int len = s.length();
4523  bool insideString=FALSE;
4524  bool insideChar=FALSE;
4525  char pc = 0;
4526  while (e<len && brCount!=0)
4527  {
4528  char c=s.at(e);
4529  switch(c)
4530  {
4531  case '<':
4532  if (!insideString && !insideChar)
4533  {
4534  if (e<len-1 && s.at(e+1)=='<')
4535  e++;
4536  else if (roundCount==0)
4537  brCount++;
4538  }
4539  break;
4540  case '>':
4541  if (!insideString && !insideChar)
4542  {
4543  if (e<len-1 && s.at(e+1)=='>')
4544  e++;
4545  else if (roundCount==0)
4546  brCount--;
4547  }
4548  break;
4549  case '(':
4550  if (!insideString && !insideChar)
4551  roundCount++;
4552  break;
4553  case ')':
4554  if (!insideString && !insideChar)
4555  roundCount--;
4556  break;
4557  case '"':
4558  if (!insideChar)
4559  {
4560  if (insideString && pc!='\\')
4561  insideString=FALSE;
4562  else
4563  insideString=TRUE;
4564  }
4565  break;
4566  case '\'':
4567  if (!insideString)
4568  {
4569  if (insideChar && pc!='\\')
4570  insideChar=FALSE;
4571  else
4572  insideChar=TRUE;
4573  }
4574  break;
4575  }
4576  pc = c;
4577  e++;
4578  }
4579  return brCount==0 ? e : -1;
4580 }
4581 
4582 static bool findClassRelation(
4583  EntryNav *rootNav,
4584  Definition *context,
4585  ClassDef *cd,
4586  BaseInfo *bi,
4587  QDict<int> *templateNames,
4589  bool isArtificial
4590  )
4591 {
4592  //printf("findClassRelation(class=%s base=%s templateNames=",
4593  // cd->name().data(),bi->name.data());
4594  //if (templateNames)
4595  //{
4596  // QDictIterator<int> qdi(*templateNames);
4597  // int *tempArgIndex;
4598  // for (;(tempArgIndex=qdi.current());++qdi)
4599  // {
4600  // printf("(%s->%d) ",qdi.currentKey(),*tempArgIndex);
4601  // }
4602  //}
4603  //printf("\n");
4604 
4605  Entry *root = rootNav->entry();
4606 
4607  QCString biName=bi->name;
4608  bool explicitGlobalScope=FALSE;
4609  //printf("findClassRelation: biName=`%s'\n",biName.data());
4610  if (biName.left(2)=="::") // explicit global scope
4611  {
4612  biName=biName.right(biName.length()-2);
4613  explicitGlobalScope=TRUE;
4614  }
4615 
4616  EntryNav *parentNode=rootNav->parent();
4617  bool lastParent=FALSE;
4618  do // for each parent scope, starting with the largest scope
4619  // (in case of nested classes)
4620  {
4621  QCString scopeName= parentNode ? parentNode->name().data() : "";
4622  int scopeOffset=explicitGlobalScope ? 0 : scopeName.length();
4623  do // try all parent scope prefixes, starting with the largest scope
4624  {
4625  //printf("scopePrefix=`%s' biName=`%s'\n",
4626  // scopeName.left(scopeOffset).data(),biName.data());
4627 
4628  QCString baseClassName=biName;
4629  if (scopeOffset>0)
4630  {
4631  baseClassName.prepend(scopeName.left(scopeOffset)+"::");
4632  }
4633  //QCString stripped;
4634  //baseClassName=stripTemplateSpecifiersFromScope
4635  // (removeRedundantWhiteSpace(baseClassName),TRUE,
4636  // &stripped);
4637  MemberDef *baseClassTypeDef=0;
4638  QCString templSpec;
4639  ClassDef *baseClass=getResolvedClass(explicitGlobalScope ? Doxygen::globalScope : context,
4640  cd->getFileDef(),
4641  baseClassName,
4642  &baseClassTypeDef,
4643  &templSpec,
4644  mode==Undocumented,
4645  TRUE
4646  );
4647  //printf("baseClassName=%s baseClass=%p cd=%p explicitGlobalScope=%d\n",
4648  // baseClassName.data(),baseClass,cd,explicitGlobalScope);
4649  //printf(" scope=`%s' baseClassName=`%s' baseClass=%s templSpec=%s\n",
4650  // cd ? cd->name().data():"<none>",
4651  // baseClassName.data(),
4652  // baseClass?baseClass->name().data():"<none>",
4653  // templSpec.data()
4654  // );
4655  //if (baseClassName.left(root->name.length())!=root->name ||
4656  // baseClassName.at(root->name.length())!='<'
4657  // ) // Check for base class with the same name.
4658  // // If found then look in the outer scope for a match
4659  // // and prevent recursion.
4660  if (!isRecursiveBaseClass(rootNav->name(),baseClassName)
4661  || explicitGlobalScope
4662  // sadly isRecursiveBaseClass always true for UNO IDL ifc/svc members
4663  // (i.e. this is needed for addInterfaceOrServiceToServiceOrSingleton)
4664  || (rootNav->lang()==SrcLangExt_IDL &&
4665  (rootNav->section()==Entry::EXPORTED_INTERFACE_SEC ||
4666  rootNav->section()==Entry::INCLUDED_SERVICE_SEC)))
4667  {
4668  Debug::print(
4669  Debug::Classes,0," class relation %s inherited/used by %s found (%s and %s) templSpec='%s'\n",
4670  qPrint(baseClassName),
4671  qPrint(rootNav->name()),
4672  (bi->prot==Private)?"private":((bi->prot==Protected)?"protected":"public"),
4673  (bi->virt==Normal)?"normal":"virtual",
4674  qPrint(templSpec)
4675  );
4676 
4677  int i=baseClassName.find('<');
4678  int si=baseClassName.findRev("::",i==-1 ? baseClassName.length() : i);
4679  if (si==-1) si=0;
4680  if (baseClass==0 && (root->lang==SrcLangExt_CSharp || root->lang==SrcLangExt_Java))
4681  {
4682  // for Java/C# strip the template part before looking for matching
4683  baseClass = Doxygen::genericsDict->find(baseClassName.left(i));
4684  //printf("looking for '%s' result=%p\n",baseClassName.data(),baseClass);
4685  }
4686  if (baseClass==0 && i!=-1)
4687  // base class has template specifiers
4688  {
4689  // TODO: here we should try to find the correct template specialization
4690  // but for now, we only look for the unspecializated base class.
4691  int e=findEndOfTemplate(baseClassName,i+1);
4692  //printf("baseClass==0 i=%d e=%d\n",i,e);
4693  if (e!=-1) // end of template was found at e
4694  {
4695  templSpec=removeRedundantWhiteSpace(baseClassName.mid(i,e-i));
4696  baseClassName=baseClassName.left(i)+baseClassName.right(baseClassName.length()-e);
4697  baseClass=getResolvedClass(explicitGlobalScope ? Doxygen::globalScope : context,
4698  cd->getFileDef(),
4699  baseClassName,
4700  &baseClassTypeDef,
4701  0, //&templSpec,
4702  mode==Undocumented,
4703  TRUE
4704  );
4705  //printf("baseClass=%p -> baseClass=%s templSpec=%s\n",
4706  // baseClass,baseClassName.data(),templSpec.data());
4707  }
4708  }
4709  else if (baseClass && !templSpec.isEmpty()) // we have a known class, but also
4710  // know it is a template, so see if
4711  // we can also link to the explicit
4712  // instance (for instance if a class
4713  // derived from a template argument)
4714  {
4715  //printf("baseClass=%p templSpec=%s\n",baseClass,templSpec.data());
4716  ClassDef *templClass=getClass(baseClass->name()+templSpec);
4717  if (templClass)
4718  {
4719  // use the template instance instead of the template base.
4720  baseClass = templClass;
4721  templSpec.resize(0);
4722  }
4723  }
4724 
4725  //printf("cd=%p baseClass=%p\n",cd,baseClass);
4726  bool found=baseClass!=0 && (baseClass!=cd || mode==TemplateInstances);
4727  //printf("1. found=%d\n",found);
4728  if (!found && si!=-1)
4729  {
4730  QCString tmpTemplSpec;
4731  // replace any namespace aliases
4732  replaceNamespaceAliases(baseClassName,si);
4733  baseClass=getResolvedClass(explicitGlobalScope ? Doxygen::globalScope : context,
4734  cd->getFileDef(),
4735  baseClassName,
4736  &baseClassTypeDef,
4737  &tmpTemplSpec,
4738  mode==Undocumented,
4739  TRUE
4740  );
4741  found=baseClass!=0 && baseClass!=cd;
4742  if (found) templSpec = tmpTemplSpec;
4743  }
4744  //printf("2. found=%d\n",found);
4745 
4746  //printf("root->name=%s biName=%s baseClassName=%s\n",
4747  // root->name.data(),biName.data(),baseClassName.data());
4748  //if (cd->isCSharp() && i!=-1) // C# generic -> add internal -g postfix
4749  //{
4750  // baseClassName+="-g";
4751  //}
4752 
4753  if (!found)
4754  {
4755  baseClass=findClassWithinClassContext(context,cd,baseClassName);
4756  //printf("findClassWithinClassContext(%s,%s)=%p\n",
4757  // cd->name().data(),baseClassName.data(),baseClass);
4758  found = baseClass!=0 && baseClass!=cd;
4759 
4760  }
4761  if (!found)
4762  {
4763  // for PHP the "use A\B as C" construct map class C to A::B, so we lookup
4764  // the class name also in the alias mapping.
4766  if (aliasName) // see if it is indeed a class.
4767  {
4768  baseClass=getClass(*aliasName);
4769  found = baseClass!=0 && baseClass!=cd;
4770  }
4771  }
4772  bool isATemplateArgument = templateNames!=0 && templateNames->find(biName)!=0;
4773  // make templSpec canonical
4774  // warning: the following line doesn't work for Mixin classes (see bug 560623)
4775  // templSpec = getCanonicalTemplateSpec(cd, cd->getFileDef(), templSpec);
4776 
4777  //printf("3. found=%d\n",found);
4778  if (found)
4779  {
4780  Debug::print(Debug::Classes,0," Documented base class `%s' templSpec=%s\n",qPrint(biName),qPrint(templSpec));
4781  // add base class to this class
4782 
4783  // if templSpec is not empty then we should "instantiate"
4784  // the template baseClass. A new ClassDef should be created
4785  // to represent the instance. To be able to add the (instantiated)
4786  // members and documentation of a template class
4787  // (inserted in that template class at a later stage),
4788  // the template should know about its instances.
4789  // the instantiation process, should be done in a recursive way,
4790  // since instantiating a template may introduce new inheritance
4791  // relations.
4792  if (!templSpec.isEmpty() && mode==TemplateInstances)
4793  {
4794  // if baseClass is actually a typedef then we should not
4795  // instantiate it, since typedefs are in a different namespace
4796  // see bug531637 for an example where this would otherwise hang
4797  // doxygen
4798  if (baseClassTypeDef==0)
4799  {
4800  //printf(" => findTemplateInstanceRelation: %p\n",baseClassTypeDef);
4801  findTemplateInstanceRelation(root,context,baseClass,templSpec,templateNames,isArtificial);
4802  }
4803  }
4804  else if (mode==DocumentedOnly || mode==Undocumented)
4805  {
4806  //printf(" => insert base class\n");
4807  QCString usedName;
4808  if (baseClassTypeDef || cd->isCSharp())
4809  {
4810  usedName=biName;
4811  //printf("***** usedName=%s templSpec=%s\n",usedName.data(),templSpec.data());
4812  }
4813  static bool sipSupport = Config_getBool("SIP_SUPPORT");
4814  if (sipSupport) bi->prot=Public;
4815  if (!cd->isSubClass(baseClass)) // check for recursion, see bug690787
4816  {
4817  cd->insertBaseClass(baseClass,usedName,bi->prot,bi->virt,templSpec);
4818  // add this class as super class to the base class
4819  baseClass->insertSubClass(cd,bi->prot,bi->virt,templSpec);
4820  }
4821  else
4822  {
4823  warn(root->fileName,root->startLine,
4824  "Detected potential recursive class relation "
4825  "between class %s and base class %s!",
4826  cd->name().data(),baseClass->name().data()
4827  );
4828  }
4829  }
4830  return TRUE;
4831  }
4832  else if (mode==Undocumented && (scopeOffset==0 || isATemplateArgument))
4833  {
4835  " New undocumented base class `%s' baseClassName=%s templSpec=%s isArtificial=%d\n",
4836  qPrint(biName),qPrint(baseClassName),qPrint(templSpec),isArtificial
4837  );
4838  baseClass=0;
4839  if (isATemplateArgument)
4840  {
4841  baseClass=Doxygen::hiddenClasses->find(baseClassName);
4842  if (baseClass==0)
4843  {
4844  baseClass=new ClassDef(root->fileName,root->startLine,root->startColumn,
4845  baseClassName,
4846  ClassDef::Class);
4847  Doxygen::hiddenClasses->append(baseClassName,baseClass);
4848  if (isArtificial) baseClass->setArtificial(TRUE);
4849  baseClass->setLanguage(root->lang);
4850  }
4851  }
4852  else
4853  {
4854  baseClass=Doxygen::classSDict->find(baseClassName);
4855  //printf("*** classDDict->find(%s)=%p biName=%s templSpec=%s\n",
4856  // baseClassName.data(),baseClass,biName.data(),templSpec.data());
4857  if (baseClass==0)
4858  {
4859  baseClass=new ClassDef(root->fileName,root->startLine,root->startColumn,
4860  baseClassName,
4861  ClassDef::Class);
4862  Doxygen::classSDict->append(baseClassName,baseClass);
4863  if (isArtificial) baseClass->setArtificial(TRUE);
4864  baseClass->setLanguage(root->lang);
4865  int si = baseClassName.findRev("::");
4866  if (si!=-1) // class is nested
4867  {
4868  Definition *sd = findScopeFromQualifiedName(Doxygen::globalScope,baseClassName.left(si),0,rootNav->tagInfo());
4869  if (sd==0 || sd==Doxygen::globalScope) // outer scope not found
4870  {
4871  baseClass->setArtificial(TRUE); // see bug678139
4872  }
4873  }
4874  }
4875  }
4876  if (biName.right(2)=="-p")
4877  {
4878  biName="<"+biName.left(biName.length()-2)+">";
4879  }
4880  // add base class to this class
4881  cd->insertBaseClass(baseClass,biName,bi->prot,bi->virt,templSpec);
4882  // add this class as super class to the base class
4883  baseClass->insertSubClass(cd,bi->prot,bi->virt,templSpec);
4884  // the undocumented base was found in this file
4885  baseClass->insertUsedFile(rootNav->fileDef());
4886  baseClass->setOuterScope(Doxygen::globalScope);
4887  if (baseClassName.right(2)=="-p")
4888  {
4889  baseClass->setCompoundType(ClassDef::Protocol);
4890  }
4891  return TRUE;
4892  }
4893  else
4894  {
4895  Debug::print(Debug::Classes,0," Base class `%s' not found\n",qPrint(biName));
4896  }
4897  }
4898  else
4899  {
4900  if (mode!=TemplateInstances)
4901  {
4902  warn(root->fileName,root->startLine,
4903  "Detected potential recursive class relation "
4904  "between class %s and base class %s!\n",
4905  root->name.data(),baseClassName.data()
4906  );
4907  }
4908  // for mode==TemplateInstance this case is quite common and
4909  // indicates a relation between a template class and a template
4910  // instance with the same name.
4911  }
4912  if (scopeOffset==0)
4913  {
4914  scopeOffset=-1;
4915  }
4916  else if ((scopeOffset=scopeName.findRev("::",scopeOffset-1))==-1)
4917  {
4918  scopeOffset=0;
4919  }
4920  //printf("new scopeOffset=`%d'",scopeOffset);
4921  } while (scopeOffset>=0);
4922 
4923  if (parentNode==0)
4924  {
4925  lastParent=TRUE;
4926  }
4927  else
4928  {
4929  parentNode=parentNode->parent();
4930  }
4931  } while (lastParent);
4932 
4933  return FALSE;
4934 }
4935 
4936 //----------------------------------------------------------------------
4937 // Computes the base and super classes for each class in the tree
4938 
4939 static bool isClassSection(EntryNav *rootNav)
4940 {
4941  if ( !rootNav->name().isEmpty() )
4942  {
4943  if (rootNav->section() & Entry::COMPOUND_MASK)
4944  // is it a compound (class, struct, union, interface ...)
4945  {
4946  return TRUE;
4947  }
4948  else if (rootNav->section() & Entry::COMPOUNDDOC_MASK)
4949  // is it a documentation block with inheritance info.
4950  {
4951  rootNav->loadEntry(g_storage);
4952  Entry *root = rootNav->entry();
4953  bool extends = root->extends->count()>0;
4954  rootNav->releaseEntry();
4955  if (extends) return TRUE;
4956  }
4957  }
4958  return FALSE;
4959 }
4960 
4961 
4962 /*! Builds a dictionary of all entry nodes in the tree starting with \a root
4963  */
4964 static void findClassEntries(EntryNav *rootNav)
4965 {
4966  if (isClassSection(rootNav))
4967  {
4968  g_classEntries.insert(rootNav->name(),rootNav);
4969  }
4971 }
4972 
4974 {
4975  // strip any anonymous scopes first
4976  QCString bName=stripAnonymousNamespaceScope(rootNav->name());
4977  bName=stripTemplateSpecifiersFromScope(bName);
4978  int i;
4979  if ((rootNav->lang()==SrcLangExt_CSharp || rootNav->lang()==SrcLangExt_Java) &&
4980  (i=bName.find('<'))!=-1)
4981  {
4982  // a Java/C# generic class looks like a C++ specialization, so we need to strip the
4983  // template part before looking for matches
4984  bName=bName.left(i);
4985  }
4986  return bName;
4987 }
4988 
4989 /*! Using the dictionary build by findClassEntries(), this
4990  * function will look for additional template specialization that
4991  * exists as inheritance relations only. These instances will be
4992  * added to the template they are derived from.
4993  */
4995 {
4996  ClassSDict::Iterator cli(*Doxygen::classSDict);
4997  for (cli.toFirst();cli.current();++cli) cli.current()->visited=FALSE;
4998  QDictIterator<EntryNav> edi(g_classEntries);
4999  EntryNav *rootNav;
5000  for (;(rootNav=edi.current());++edi)
5001  {
5002  ClassDef *cd;
5003  QCString bName = extractClassName(rootNav);
5004  Debug::print(Debug::Classes,0," Inheritance: Class %s : \n",qPrint(bName));
5005  if ((cd=getClass(bName)))
5006  {
5007  rootNav->loadEntry(g_storage);
5008  //printf("Class %s %d\n",cd->name().data(),root->extends->count());
5010  rootNav->releaseEntry();
5011  }
5012  }
5013 }
5014 
5016 {
5017  ClassSDict::Iterator cli(*Doxygen::classSDict);
5018  for (cli.toFirst();cli.current();++cli) cli.current()->visited=FALSE;
5019  QDictIterator<EntryNav> edi(g_classEntries);
5020  EntryNav *rootNav;
5021  for (;(rootNav=edi.current());++edi)
5022  {
5023  ClassDef *cd;
5024  QCString bName = extractClassName(rootNav);
5025  Debug::print(Debug::Classes,0," Usage: Class %s : \n",qPrint(bName));
5026  if ((cd=getClass(bName)))
5027  {
5028  rootNav->loadEntry(g_storage);
5029  findUsedClassesForClass(rootNav,cd,cd,cd,TRUE);
5030  cd->addTypeConstraints();
5031  rootNav->releaseEntry();
5032  }
5033  }
5034 }
5035 
5037 {
5038  ClassSDict::Iterator cli(*Doxygen::classSDict);
5039  for (cli.toFirst();cli.current();++cli) cli.current()->visited=FALSE;
5040  QDictIterator<EntryNav> edi(g_classEntries);
5041  EntryNav *rootNav;
5042  for (;(rootNav=edi.current());++edi)
5043  {
5044  ClassDef *cd;
5045 
5046  rootNav->loadEntry(g_storage);
5047  Entry *root = rootNav->entry();
5048  QCString bName = extractClassName(rootNav);
5049  Debug::print(Debug::Classes,0," Relations: Class %s : \n",qPrint(bName));
5050  if ((cd=getClass(bName)))
5051  {
5052  findBaseClassesForClass(rootNav,cd,cd,cd,DocumentedOnly,FALSE);
5053  }
5054  int numMembers = cd && cd->memberNameInfoSDict() ? cd->memberNameInfoSDict()->count() : 0;
5055  if ((cd==0 || (!cd->hasDocumentation() && !cd->isReference())) && numMembers>0 &&
5056  bName.right(2)!="::")
5057  {
5058  if (!root->name.isEmpty() && root->name.find('@')==-1 && // normal name
5060  Config_getBool("EXTRACT_LOCAL_CLASSES")) && // not defined in source file
5061  protectionLevelVisible(root->protection) && // hidden by protection
5062  !Config_getBool("HIDE_UNDOC_CLASSES") // undocumented class are visible
5063  )
5064  warn_undoc(
5065  root->fileName,root->startLine,
5066  "Compound %s is not documented.",
5067  root->name.data()
5068  );
5069  }
5070 
5071  rootNav->releaseEntry();
5072  }
5073 }
5074 
5076 {
5077  QDictIterator<EntryNav> edi(g_classEntries);
5078  EntryNav *rootNav;
5079  for (;(rootNav=edi.current());++edi)
5080  {
5081  rootNav->loadEntry(g_storage);
5082  Entry *root = rootNav->entry();
5083 
5085  bName=stripTemplateSpecifiersFromScope(bName);
5086  ClassDef *cd=getClass(bName);
5087  // strip any anonymous scopes first
5088  QDict<ClassDef> *templInstances = 0;
5089  if (cd && (templInstances=cd->getTemplateInstances()))
5090  {
5091  Debug::print(Debug::Classes,0," Template class %s : \n",qPrint(cd->name()));
5092  QDictIterator<ClassDef> tdi(*templInstances);
5093  ClassDef *tcd;
5094  for (tdi.toFirst();(tcd=tdi.current());++tdi) // for each template instance
5095  {
5096  Debug::print(Debug::Classes,0," Template instance %s : \n",qPrint(tcd->name()));
5097  QCString templSpec = tdi.currentKey();
5098  ArgumentList *templArgs = new ArgumentList;
5099  stringToArgumentList(templSpec,templArgs);
5100  QList<BaseInfo> *baseList=root->extends;
5101  QListIterator<BaseInfo> it(*baseList);
5102  BaseInfo *bi;
5103  for (;(bi=it.current());++it) // for each base class of the template
5104  {
5105  // check if the base class is a template argument
5106  BaseInfo tbi(bi->name,bi->prot,bi->virt);
5107  ArgumentList *tl = cd->templateArguments();
5108  if (tl)
5109  {
5110  QDict<int> *baseClassNames = tcd->getTemplateBaseClassNames();
5111  QDict<int> *templateNames = getTemplateArgumentsInName(tl,bi->name);
5112  // for each template name that we inherit from we need to
5113  // substitute the formal with the actual arguments
5114  QDict<int> *actualTemplateNames = new QDict<int>(17);
5115  actualTemplateNames->setAutoDelete(TRUE);
5116  QDictIterator<int> qdi(*templateNames);
5117  for (qdi.toFirst();qdi.current();++qdi)
5118  {
5119  int templIndex = *qdi.current();
5120  Argument *actArg = 0;
5121  if (templIndex<(int)templArgs->count())
5122  {
5123  actArg=templArgs->at(templIndex);
5124  }
5125  if (actArg!=0 &&
5126  baseClassNames!=0 &&
5127  baseClassNames->find(actArg->type)!=0 &&
5128  actualTemplateNames->find(actArg->type)==0
5129  )
5130  {
5131  actualTemplateNames->insert(actArg->type,new int(templIndex));
5132  }
5133  }
5134  delete templateNames;
5135 
5136  tbi.name = substituteTemplateArgumentsInString(bi->name,tl,templArgs);
5137  // find a documented base class in the correct scope
5138  if (!findClassRelation(rootNav,cd,tcd,&tbi,actualTemplateNames,DocumentedOnly,FALSE))
5139  {
5140  // no documented base class -> try to find an undocumented one
5141  findClassRelation(rootNav,cd,tcd,&tbi,actualTemplateNames,Undocumented,TRUE);
5142  }
5143  delete actualTemplateNames;
5144  }
5145  }
5146  delete templArgs;
5147  } // class has no base classes
5148  }
5149 
5150  rootNav->releaseEntry();
5151  }
5152 }
5153 
5154 //-----------------------------------------------------------------------
5155 // compute the references (anchors in HTML) for each function in the file
5156 
5158 {
5159  ClassSDict::Iterator cli(*Doxygen::classSDict);
5160  ClassDef *cd=0;
5161  for (cli.toFirst();(cd=cli.current());++cli)
5162  {
5163  cd->computeAnchors();
5164  }
5165  FileNameListIterator fnli(*Doxygen::inputNameList);
5166  FileName *fn;
5167  for (fnli.toFirst();(fn=fnli.current());++fnli)
5168  {
5169  FileNameIterator fni(*fn);
5170  FileDef *fd;
5171  for (;(fd=fni.current());++fni)
5172  {
5173  fd->computeAnchors();
5174  }
5175  }
5176  NamespaceSDict::Iterator nli(*Doxygen::namespaceSDict);
5177  NamespaceDef *nd=0;
5178  for (nli.toFirst();(nd=nli.current());++nli)
5179  {
5180  nd->computeAnchors();
5181  }
5182  GroupSDict::Iterator gli(*Doxygen::groupSDict);
5183  GroupDef *gd;
5184  for (gli.toFirst();(gd=gli.current());++gli)
5185  {
5186  gd->computeAnchors();
5187  }
5188 }
5189 
5190 //----------------------------------------------------------------------
5191 
5192 static void addListReferences()
5193 {
5194  MemberNameSDict::Iterator mnli(*Doxygen::memberNameSDict);
5195  MemberName *mn=0;
5196  for (mnli.toFirst();(mn=mnli.current());++mnli)
5197  {
5198  MemberNameIterator mni(*mn);
5199  MemberDef *md=0;
5200  for (mni.toFirst();(md=mni.current());++mni)
5201  {
5202  md->visited=FALSE;
5203  }
5204  }
5205  MemberNameSDict::Iterator fmnli(*Doxygen::functionNameSDict);
5206  for (fmnli.toFirst();(mn=fmnli.current());++fmnli)
5207  {
5208  MemberNameIterator mni(*mn);
5209  MemberDef *md=0;
5210  for (mni.toFirst();(md=mni.current());++mni)
5211  {
5212  md->visited=FALSE;
5213  }
5214  }
5215 
5216  ClassSDict::Iterator cli(*Doxygen::classSDict);
5217  ClassDef *cd=0;
5218  for (cli.toFirst();(cd=cli.current());++cli)
5219  {
5220  cd->addListReferences();
5221  }
5222 
5223  FileNameListIterator fnli(*Doxygen::inputNameList);
5224  FileName *fn;
5225  for (fnli.toFirst();(fn=fnli.current());++fnli)
5226  {
5227  FileNameIterator fni(*fn);
5228  FileDef *fd;
5229  for (;(fd=fni.current());++fni)
5230  {
5231  fd->addListReferences();
5232  }
5233  }
5234 
5235  NamespaceSDict::Iterator nli(*Doxygen::namespaceSDict);
5236  NamespaceDef *nd=0;
5237  for (nli.toFirst();(nd=nli.current());++nli)
5238  {
5239  nd->addListReferences();
5240  }
5241 
5242  GroupSDict::Iterator gli(*Doxygen::groupSDict);
5243  GroupDef *gd;
5244  for (gli.toFirst();(gd=gli.current());++gli)
5245  {
5246  gd->addListReferences();
5247  }
5248 
5249  PageSDict::Iterator pdi(*Doxygen::pageSDict);
5250  PageDef *pd=0;
5251  for (pdi.toFirst();(pd=pdi.current());++pdi)
5252  {
5254  if (pd->getGroupDef())
5255  {
5256  name = pd->getGroupDef()->getOutputFileBase();
5257  }
5258  {
5259  QList<ListItemInfo> *xrefItems = pd->xrefListItems();
5260  addRefItem(xrefItems,
5261  name,
5263  name,pd->title(),0,0);
5264  }
5265  }
5266 
5267  DirSDict::Iterator ddi(*Doxygen::directories);
5268  DirDef *dd = 0;
5269  for (ddi.toFirst();(dd=ddi.current());++ddi)
5270  {
5272  //if (dd->getGroupDef())
5273  //{
5274  // name = dd->getGroupDef()->getOutputFileBase();
5275  //}
5276  QList<ListItemInfo> *xrefItems = dd->xrefListItems();
5277  addRefItem(xrefItems,
5278  name,
5280  name,dd->displayName(),0,0);
5281  }
5282 }
5283 
5284 //----------------------------------------------------------------------
5285 
5286 static void generateXRefPages()
5287 {
5288  QDictIterator<RefList> di(*Doxygen::xrefLists);
5289  RefList *rl;
5290  for (di.toFirst();(rl=di.current());++di)
5291  {
5292  rl->generatePage();
5293  }
5294 }
5295 
5296 //----------------------------------------------------------------------
5297 // Copy the documentation in entry `root' to member definition `md' and
5298 // set the function declaration of the member to `funcDecl'. If the boolean
5299 // over_load is set the standard overload text is added.
5300 
5301 static void addMemberDocs(EntryNav *rootNav,
5302  MemberDef *md, const char *funcDecl,
5303  ArgumentList *al,
5304  bool over_load,
5305  NamespaceSDict *
5306  )
5307 {
5308  Entry *root = rootNav->entry();
5309  //printf("addMemberDocs: `%s'::`%s' `%s' funcDecl=`%s' mSpec=%d\n",
5310  // root->parent->name.data(),md->name().data(),md->argsString(),funcDecl,root->spec);
5311  QCString fDecl=funcDecl;
5312  // strip extern specifier
5313  fDecl.stripPrefix("extern ");
5314  md->setDefinition(fDecl);
5315  md->enableCallGraph(root->callGraph);
5316  md->enableCallerGraph(root->callerGraph);
5317  ClassDef *cd=md->getClassDef();
5318  NamespaceDef *nd=md->getNamespaceDef();
5319  QCString fullName;
5320  if (cd)
5321  fullName = cd->name();
5322  else if (nd)
5323  fullName = nd->name();
5324 
5325  if (!fullName.isEmpty()) fullName+="::";
5326  fullName+=md->name();
5327  FileDef *rfd=rootNav->fileDef();
5328 
5329  // TODO determine scope based on root not md
5330  Definition *rscope = md->getOuterScope();
5331 
5332  ArgumentList *mdAl = md->argumentList();
5333  if (al)
5334  {
5335  //printf("merging arguments (1) docs=%d\n",root->doc.isEmpty());
5336  mergeArguments(mdAl,al,!root->doc.isEmpty());
5337  }
5338  else
5339  {
5340  if (
5341  matchArguments2( md->getOuterScope(), md->getFileDef(), mdAl,
5342  rscope,rfd,root->argList,
5343  TRUE
5344  )
5345  )
5346  {
5347  //printf("merging arguments (2)\n");
5348  mergeArguments(mdAl,root->argList,!root->doc.isEmpty());
5349  }
5350  }
5351  if (over_load) // the \overload keyword was used
5352  {
5354  if (!root->doc.isEmpty())
5355  {
5356  doc+="<p>";
5357  doc+=root->doc;
5358  }
5359  md->setDocumentation(doc,root->docFile,root->docLine);
5360  md->setInbodyDocumentation(root->inbodyDocs,root->inbodyFile,root->inbodyLine);
5361  md->setDocsForDefinition(!root->proto);
5362  }
5363  else
5364  {
5365  //printf("overwrite!\n");
5366  md->setDocumentation(root->doc,root->docFile,root->docLine);
5367  md->setDocsForDefinition(!root->proto);
5368 
5369  //printf("overwrite!\n");
5370  md->setBriefDescription(root->brief,root->briefFile,root->briefLine);
5371 
5372  if (
5373  (md->inbodyDocumentation().isEmpty() ||
5374  !rootNav->parent()->name().isEmpty()
5375  ) && !root->inbodyDocs.isEmpty()
5376  )
5377  {
5378  md->setInbodyDocumentation(root->inbodyDocs,root->inbodyFile,root->inbodyLine);
5379  }
5380  }
5381 
5382  //printf("initializer: '%s'(isEmpty=%d) '%s'(isEmpty=%d)\n",
5383  // md->initializer().data(),md->initializer().isEmpty(),
5384  // root->initializer.data(),root->initializer.isEmpty()
5385  // );
5386  if (md->initializer().isEmpty() && !root->initializer.isEmpty())
5387  {
5388  //printf("setInitializer\n");
5389  md->setInitializer(root->initializer);
5390  }
5391 
5392  md->setMaxInitLines(root->initLines);
5393 
5394  if (rfd)
5395  {
5396  if ((md->getStartBodyLine()==-1 && root->bodyLine!=-1)
5397  )
5398  {
5399  //printf("Setting new body segment [%d,%d]\n",root->bodyLine,root->endBodyLine);
5400  md->setBodySegment(root->bodyLine,root->endBodyLine);
5401  md->setBodyDef(rfd);
5402  }
5403 
5404  md->setRefItems(root->sli);
5405  }
5406 
5407  md->enableCallGraph(md->hasCallGraph() || root->callGraph);
5408  md->enableCallerGraph(md->hasCallerGraph() || root->callerGraph);
5409 
5410  md->mergeMemberSpecifiers(root->spec);
5411  md->addSectionsToDefinition(root->anchors);
5412  addMemberToGroups(root,md);
5413  if (cd) cd->insertUsedFile(rfd);
5414  //printf("root->mGrpId=%d\n",root->mGrpId);
5415  if (root->mGrpId!=-1)
5416  {
5417  if (md->getMemberGroupId()!=-1)
5418  {
5419  if (md->getMemberGroupId()!=root->mGrpId)
5420  {
5421  warn(
5422  root->fileName,root->startLine,
5423  "member %s belongs to two different groups. The second "
5424  "one found here will be ignored.",
5425  md->name().data()
5426  );
5427  }
5428  }
5429  else // set group id
5430  {
5431  //printf("setMemberGroupId=%d md=%s\n",root->mGrpId,md->name().data());
5432  md->setMemberGroupId(root->mGrpId);
5433  }
5434  }
5435 }
5436 
5437 //----------------------------------------------------------------------
5438 // find a class definition given the scope name and (optionally) a
5439 // template list specifier
5440 
5442  const char *scopeName)
5443 {
5444  ClassDef *tcd = getResolvedClass(nd,fd,scopeName,0,0,TRUE,TRUE);
5445  return tcd;
5446 }
5447 
5448 
5449 //----------------------------------------------------------------------
5450 // Adds the documentation contained in `root' to a global function
5451 // with name `name' and argument list `args' (for overloading) and
5452 // function declaration `decl' to the corresponding member definition.
5453 
5454 static bool findGlobalMember(EntryNav *rootNav,
5455  const QCString &namespaceName,
5456  const char *type,
5457  const char *name,
5458  const char *tempArg,
5459  const char *,
5460  const char *decl)
5461 {
5462  Entry *root = rootNav->entry();
5464  "2. findGlobalMember(namespace=%s,type=%s,name=%s,tempArg=%s,decl=%s)\n",
5465  qPrint(namespaceName),qPrint(type),qPrint(name),qPrint(tempArg),qPrint(decl));
5466  QCString n=name;
5467  if (n.isEmpty()) return FALSE;
5468  if (n.find("::")!=-1) return FALSE; // skip undefined class members
5469  MemberName *mn=Doxygen::functionNameSDict->find(n+tempArg); // look in function dictionary
5470  if (mn==0)
5471  {
5472  mn=Doxygen::functionNameSDict->find(n); // try without template arguments
5473  }
5474  if (mn) // function name defined
5475  {
5476  Debug::print(Debug::FindMembers,0,"3. Found symbol scope\n");
5477  //int count=0;
5478  MemberNameIterator mni(*mn);
5479  MemberDef *md;
5480  bool found=FALSE;
5481  for (mni.toFirst();(md=mni.current()) && !found;++mni)
5482  {
5483  NamespaceDef *nd=md->getNamespaceDef();
5484 
5485  //printf("Namespace namespaceName=%s nd=%s\n",
5486  // namespaceName.data(),nd ? nd->name().data() : "<none>");
5487 
5488  FileDef *fd=rootNav->fileDef();
5489  //printf("File %s\n",fd ? fd->name().data() : "<none>");
5490  NamespaceSDict *nl = fd ? fd->getUsedNamespaces() : 0;
5491  //SDict<Definition> *cl = fd ? fd->getUsedClasses() : 0;
5492  //printf("NamespaceList %p\n",nl);
5493 
5494  // search in the list of namespaces that are imported via a
5495  // using declaration
5496  bool viaUsingDirective = nl && nd && nl->find(nd->qualifiedName())!=0;
5497 
5498  if ((namespaceName.isEmpty() && nd==0) || // not in a namespace
5499  (nd && nd->name()==namespaceName) || // or in the same namespace
5500  viaUsingDirective // member in `using' namespace
5501  )
5502  {
5503  Debug::print(Debug::FindMembers,0,"4. Try to add member `%s' to scope `%s'\n",
5504  qPrint(md->name()),qPrint(namespaceName));
5505 
5506  NamespaceDef *rnd = 0;
5507  if (!namespaceName.isEmpty()) rnd = Doxygen::namespaceSDict->find(namespaceName);
5508 
5509  ArgumentList *mdAl = md->argumentList();
5510  bool matching=
5511  (mdAl==0 && root->argList->count()==0) ||
5512  md->isVariable() || md->isTypedef() || /* in case of function pointers */
5513  matchArguments2(md->getOuterScope(),md->getFileDef(),mdAl,
5514  rnd ? rnd : Doxygen::globalScope,fd,root->argList,
5515  FALSE);
5516 
5517  // for template members we need to check if the number of
5518  // template arguments is the same, otherwise we are dealing with
5519  // different functions.
5520  if (matching && root->tArgLists)
5521  {
5522  ArgumentList *mdTempl = md->templateArguments();
5523  if (mdTempl)
5524  {
5525  if (root->tArgLists->getLast()->count()!=mdTempl->count())
5526  {
5527  matching=FALSE;
5528  }
5529  }
5530  }
5531 
5532  //printf("%s<->%s\n",
5533  // argListToString(md->argumentList()).data(),
5534  // argListToString(root->argList).data());
5535 
5536  // for static members we also check if the comment block was found in
5537  // the same file. This is needed because static members with the same
5538  // name can be in different files. Thus it would be wrong to just
5539  // put the comment block at the first syntactically matching member.
5540  if (matching && md->isStatic() &&
5541  md->getDefFileName()!=root->fileName &&
5542  mn->count()>1)
5543  {
5544  matching = FALSE;
5545  }
5546 
5547  // for template member we also need to check the return type
5548  if (md->templateArguments()!=0 && root->tArgLists!=0)
5549  {
5550  //printf("Comparing return types '%s'<->'%s'\n",
5551  // md->typeString(),type);
5552  if (md->templateArguments()->count()!=root->tArgLists->getLast()->count() ||
5553  qstrcmp(md->typeString(),type)!=0)
5554  {
5555  //printf(" ---> no matching\n");
5556  matching = FALSE;
5557  }
5558  }
5559 
5560  if (matching) // add docs to the member
5561  {
5562  Debug::print(Debug::FindMembers,0,"5. Match found\n");
5563  addMemberDocs(rootNav,md,decl,root->argList,FALSE);
5564  found=TRUE;
5565  }
5566  }
5567  }
5568  if (!found && root->relatesType != Duplicate && root->section==Entry::FUNCTION_SEC) // no match
5569  {
5570  QCString fullFuncDecl=decl;
5571  if (root->argList) fullFuncDecl+=argListToString(root->argList,TRUE);
5572  QCString warnMsg =
5573  QCString("no matching file member found for \n")+substitute(fullFuncDecl,"%","%%");
5574  if (mn->count()>0)
5575  {
5576  warnMsg+="\nPossible candidates:\n";
5577  for (mni.toFirst();(md=mni.current());++mni)
5578  {
5579  warnMsg+=" '";
5580  warnMsg+=substitute(md->declaration(),"%","%%");
5581  warnMsg+="' at line "+QCString().setNum(md->getDefLine())+
5582  " of file"+md->getDefFileName()+"\n";
5583  }
5584  }
5585  warn(root->fileName,root->startLine,warnMsg);
5586  }
5587  }
5588  else // got docs for an undefined member!
5589  {
5590  if (root->type!="friend class" &&
5591  root->type!="friend struct" &&
5592  root->type!="friend union" &&
5593  (!Config_getBool("TYPEDEF_HIDES_STRUCT") ||
5594  root->type.find("typedef ")==-1)
5595  )
5596  {
5597  warn(root->fileName,root->startLine,
5598  "documented symbol `%s' was not declared or defined.",decl
5599  );
5600  }
5601  }
5602  return TRUE;
5603 }
5604 
5605 static bool isSpecialization(
5606  const QList<ArgumentList> &srcTempArgLists,
5607  const QList<ArgumentList> &dstTempArgLists
5608  )
5609 {
5610  QListIterator<ArgumentList> srclali(srcTempArgLists);
5611  QListIterator<ArgumentList> dstlali(dstTempArgLists);
5612  for (;srclali.current();++srclali,++dstlali)
5613  {
5614  ArgumentList *sal = srclali.current();
5615  ArgumentList *dal = dstlali.current();
5616  if (!(sal && dal && sal->count()==dal->count())) return TRUE;
5617  }
5618  return FALSE;
5619 }
5620 
5622 {
5623  bool result=FALSE;
5624  if (d && d->definitionType()==Definition::TypeClass)
5625  {
5626  result = ((ClassDef*)d)->templateArguments() || scopeIsTemplate(d->getOuterScope());
5627  }
5628  return result;
5629 }
5630 
5632  const QList<ArgumentList> &srcTempArgLists,
5633  const QList<ArgumentList> &dstTempArgLists,
5634  ArgumentList *funcTempArgList, // can be used to match template specializations
5635  const QCString &src
5636  )
5637 {
5638  QCString dst;
5639  QRegExp re( "[A-Za-z_][A-Za-z_0-9]*");
5640  //printf("type=%s\n",sa->type.data());
5641  int i,p=0,l;
5642  while ((i=re.match(src,p,&l))!=-1) // for each word in srcType
5643  {
5644  bool found=FALSE;
5645  dst+=src.mid(p,i-p);
5646  QCString name=src.mid(i,l);
5647 
5648  QListIterator<ArgumentList> srclali(srcTempArgLists);
5649  QListIterator<ArgumentList> dstlali(dstTempArgLists);
5650  for (;srclali.current() && !found;++srclali,++dstlali)
5651  {
5652  ArgumentListIterator tsali(*srclali.current());
5653  ArgumentListIterator tdali(*dstlali.current());
5654  ArgumentListIterator *fali=0;
5655  Argument *tsa =0,*tda=0, *fa=0;
5656  if (funcTempArgList)
5657  {
5658  fali = new ArgumentListIterator(*funcTempArgList);
5659  fa = fali->current();
5660  }
5661 
5662  for (tsali.toFirst();(tsa=tsali.current()) && !found;++tsali)
5663  {
5664  tda = tdali.current();
5665  //if (tda) printf("tsa=%s|%s tda=%s|%s\n",
5666  // tsa->type.data(),tsa->name.data(),
5667  // tda->type.data(),tda->name.data());
5668  if (name==tsa->name)
5669  {
5670  if (tda && tda->name.isEmpty())
5671  {
5672  int vc=0;
5673  if (tda->type.left(6)=="class ") vc=6;
5674  else if (tda->type.left(9)=="typename ") vc=9;
5675  if (vc>0) // convert type=="class T" to type=="class" name=="T"
5676  {
5677  tda->name = tda->type.mid(vc);
5678  tda->type = tda->type.left(vc-1);
5679  }
5680  }
5681  if (tda && !tda->name.isEmpty())
5682  {
5683  name=tda->name; // substitute
5684  found=TRUE;
5685  }
5686  else if (fa)
5687  {
5688  name=fa->type;
5689  found=TRUE;
5690  }
5691  }
5692  if (tda)
5693  ++tdali;
5694  else if (fali)
5695  { ++(*fali); fa=fali->current(); }
5696  }
5697 
5698  delete fali;
5699  //printf(" srcList='%s' dstList='%s faList='%s'\n",
5700  // argListToString(srclali.current()).data(),
5701  // argListToString(dstlali.current()).data(),
5702  // funcTempArgList ? argListToString(funcTempArgList).data() : "<none>");
5703  }
5704  dst+=name;
5705  p=i+l;
5706  }
5707  dst+=src.right(src.length()-p);
5708  //printf(" substituteTemplatesInString(%s)=%s\n",
5709  // src.data(),dst.data());
5710  return dst;
5711 }
5712 
5714  const QList<ArgumentList> &srcTempArgLists,
5715  const QList<ArgumentList> &dstTempArgLists,
5716  ArgumentList *src,
5717  ArgumentList *dst,
5718  ArgumentList *funcTempArgs = 0
5719  )
5720 {
5721  ArgumentListIterator sali(*src);
5722  ArgumentListIterator dali(*dst);
5723  Argument *sa=0;
5724  Argument *da=dali.current();
5725 
5726  for (sali.toFirst();(sa=sali.current());++sali) // for each member argument
5727  {
5729  srcTempArgLists,dstTempArgLists,funcTempArgs,
5730  sa->type);
5732  srcTempArgLists,dstTempArgLists,funcTempArgs,
5733  sa->array);
5734  if (da==0)
5735  {
5736  da=new Argument(*sa);
5737  dst->append(da);
5738  da->type=dstType;
5739  da->array=dstArray;
5740  da=0;
5741  }
5742  else
5743  {
5744  da->type=dstType;
5745  da->type=dstArray;
5746  ++dali;
5747  da=dali.current();
5748  }
5749  }
5750  dst->constSpecifier = src->constSpecifier;
5752  dst->pureSpecifier = src->pureSpecifier;
5754  srcTempArgLists,dstTempArgLists,
5755  funcTempArgs,src->trailingReturnType);
5756  //printf("substituteTemplatesInArgList: replacing %s with %s\n",
5757  // argListToString(src).data(),argListToString(dst).data()
5758  // );
5759 }
5760 
5761 
5762 
5763 /*! This function tries to find a member (in a documented class/file/namespace)
5764  * that corresponds to the function/variable declaration given in \a funcDecl.
5765  *
5766  * The boolean \a overloaded is used to specify whether or not a standard
5767  * overload documentation line should be generated.
5768  *
5769  * The boolean \a isFunc is a hint that indicates that this is a function
5770  * instead of a variable or typedef.
5771  */
5772 static void findMember(EntryNav *rootNav,
5773  QCString funcDecl,
5774  bool overloaded,
5775  bool isFunc
5776  )
5777 {
5778  Entry *root = rootNav->entry();
5779 
5781  "findMember(root=%p,funcDecl=`%s',related=`%s',overload=%d,"
5782  "isFunc=%d mGrpId=%d tArgList=%p (#=%d) "
5783  "spec=%lld lang=%x\n",
5784  root,qPrint(funcDecl),qPrint(root->relates),overloaded,isFunc,root->mGrpId,
5785  root->tArgLists,root->tArgLists ? root->tArgLists->count() : 0,
5786  root->spec,root->lang
5787  );
5788 
5789  QCString scopeName;
5791  QCString namespaceName;
5792  QCString funcType;
5793  QCString funcName;
5794  QCString funcArgs;
5796  QCString exceptions;
5797  QCString funcSpec;
5798  bool isRelated=FALSE;
5799  bool isMemberOf=FALSE;
5800  bool isFriend=FALSE;
5801  bool done;
5802  do
5803  {
5804  done=TRUE;
5805  if (funcDecl.stripPrefix("friend ")) // treat friends as related members
5806  {
5807  isFriend=TRUE;
5808  done=FALSE;
5809  }
5810  if (funcDecl.stripPrefix("inline "))
5811  {
5812  root->spec|=Entry::Inline;
5813  done=FALSE;
5814  }
5815  if (funcDecl.stripPrefix("explicit "))
5816  {
5817  root->spec|=Entry::Explicit;
5818  done=FALSE;
5819  }
5820  if (funcDecl.stripPrefix("mutable "))
5821  {
5822  root->spec|=Entry::Mutable;
5823  done=FALSE;
5824  }
5825  if (funcDecl.stripPrefix("virtual "))
5826  {
5827  done=FALSE;
5828  }
5829  } while (!done);
5830 
5831  // delete any ; from the function declaration
5832  int sep;
5833  while ((sep=funcDecl.find(';'))!=-1)
5834  {
5835  funcDecl=(funcDecl.left(sep)+funcDecl.right(funcDecl.length()-sep-1)).stripWhiteSpace();
5836  }
5837 
5838  // make sure the first character is a space to simplify searching.
5839  if (!funcDecl.isEmpty() && funcDecl[0]!=' ') funcDecl.prepend(" ");
5840 
5841  // remove some superfluous spaces
5842  funcDecl= substitute(
5843  substitute(
5844  substitute(funcDecl,"~ ","~"),
5845  ":: ","::"
5846  ),
5847  " ::","::"
5848  ).stripWhiteSpace();
5849 
5850  //printf("funcDecl=`%s'\n",funcDecl.data());
5851  if (isFriend && funcDecl.left(6)=="class ")
5852  {
5853  //printf("friend class\n");
5854  funcDecl=funcDecl.right(funcDecl.length()-6);
5855  funcName = funcDecl.copy();
5856  }
5857  else if (isFriend && funcDecl.left(7)=="struct ")
5858  {
5859  funcDecl=funcDecl.right(funcDecl.length()-7);
5860  funcName = funcDecl.copy();
5861  }
5862  else
5863  {
5864  // extract information from the declarations
5865  parseFuncDecl(funcDecl,root->lang==SrcLangExt_ObjC,scopeName,funcType,funcName,
5866  funcArgs,funcTempList,exceptions
5867  );
5868  }
5869  //printf("scopeName=`%s' funcType=`%s' funcName=`%s' funcArgs=`%s'\n",
5870  // scopeName.data(),funcType.data(),funcName.data(),funcArgs.data());
5871 
5872  // the class name can also be a namespace name, we decide this later.
5873  // if a related class name is specified and the class name could
5874  // not be derived from the function declaration, then use the
5875  // related field.
5876  //printf("scopeName=`%s' className=`%s' namespaceName=`%s'\n",
5877  // scopeName.data(),className.data(),namespaceName.data());
5878  if (!root->relates.isEmpty())
5879  { // related member, prefix user specified scope
5880  isRelated=TRUE;
5881  isMemberOf=(root->relatesType == MemberOf);
5882  if (getClass(root->relates)==0 && !scopeName.isEmpty())
5883  {
5884  scopeName= mergeScopes(scopeName,root->relates);
5885  }
5886  else
5887  {
5888  scopeName = root->relates;
5889  }
5890  }
5891 
5892  if (root->relates.isEmpty() && rootNav->parent() &&
5893  ((rootNav->parent()->section()&Entry::SCOPE_MASK) ||
5894  (rootNav->parent()->section()==Entry::OBJCIMPL_SEC)
5895  ) &&
5896  !rootNav->parent()->name().isEmpty()) // see if we can combine scopeName
5897  // with the scope in which it was found
5898  {
5899  QCString joinedName = rootNav->parent()->name()+"::"+scopeName;
5900  if (!scopeName.isEmpty() &&
5901  (getClass(joinedName) || Doxygen::namespaceSDict->find(joinedName)))
5902  {
5903  scopeName = joinedName;
5904  }
5905  else
5906  {
5907  scopeName = mergeScopes(rootNav->parent()->name(),scopeName);
5908  }
5909  }
5910  else // see if we can prefix a namespace or class that is used from the file
5911  {
5912  FileDef *fd=rootNav->fileDef();
5913  if (fd)
5914  {
5915  NamespaceSDict *fnl = fd->getUsedNamespaces();
5916  if (fnl)
5917  {
5918  QCString joinedName;
5919  NamespaceDef *fnd;
5920  NamespaceSDict::Iterator nsdi(*fnl);
5921  for (nsdi.toFirst();(fnd=nsdi.current());++nsdi)
5922  {
5923  joinedName = fnd->name()+"::"+scopeName;
5924  if (Doxygen::namespaceSDict->find(joinedName))
5925  {
5926  scopeName=joinedName;
5927  break;
5928  }
5929  }
5930  }
5931  }
5932  }
5934  removeRedundantWhiteSpace(scopeName),FALSE,&funcSpec);
5935 
5936  // funcSpec contains the last template specifiers of the given scope.
5937  // If this method does not have any template arguments or they are
5938  // empty while funcSpec is not empty we assume this is a
5939  // specialization of a method. If not, we clear the funcSpec and treat
5940  // this as a normal method of a template class.
5941  if (!(root->tArgLists &&
5942  root->tArgLists->count()>0 &&
5943  root->tArgLists->getFirst()->count()==0
5944  )
5945  )
5946  {
5947  funcSpec.resize(0);
5948  }
5949 
5950  // split scope into a namespace and a class part
5951  extractNamespaceName(scopeName,className,namespaceName,TRUE);
5952  //printf("scopeName=`%s' className=`%s' namespaceName=`%s'\n",
5953  // scopeName.data(),className.data(),namespaceName.data());
5954 
5955  //namespaceName=removeAnonymousScopes(namespaceName);
5956  if (namespaceName.find('@')!=-1) return; // skip stuff in anonymous namespace...
5957 
5958  //printf("namespaceName=`%s' className=`%s'\n",namespaceName.data(),className.data());
5959  // merge class and namespace scopes again
5960  scopeName.resize(0);
5961  if (!namespaceName.isEmpty())
5962  {
5963  if (className.isEmpty())
5964  {
5965  scopeName=namespaceName;
5966  }
5967  else if (!root->relates.isEmpty() || // relates command with explicit scope
5968  !getClass(className)) // class name only exists in a namespace
5969  {
5970  scopeName=namespaceName+"::"+className;
5971  }
5972  else
5973  {
5974  scopeName=className;
5975  }
5976  }
5977  else if (!className.isEmpty())
5978  {
5979  scopeName=className;
5980  }
5981  //printf("new scope=`%s'\n",scopeName.data());
5982 
5983  QCString tempScopeName=scopeName;
5984  ClassDef *cd=getClass(scopeName);
5985  if (cd)
5986  {
5987  if (funcSpec.isEmpty())
5988  {
5989  int argListIndex=0;
5990  tempScopeName=cd->qualifiedNameWithTemplateParameters(root->tArgLists,&argListIndex);
5991  }
5992  else
5993  {
5994  tempScopeName=scopeName+funcSpec;
5995  }
5996  }
5997  //printf("scopeName=%s cd=%p root->tArgLists=%p result=%s\n",
5998  // scopeName.data(),cd,root->tArgLists,tempScopeName.data());
5999 
6000  //printf("scopeName=`%s' className=`%s'\n",scopeName.data(),className.data());
6001  // rebuild the function declaration (needed to get the scope right).
6002  if (!scopeName.isEmpty() && !isRelated && !isFriend && !Config_getBool("HIDE_SCOPE_NAMES"))
6003  {
6004  if (!funcType.isEmpty())
6005  {
6006  if (isFunc) // a function -> we use argList for the arguments
6007  {
6008  funcDecl=funcType+" "+tempScopeName+"::"+funcName+funcTempList;
6009  }
6010  else
6011  {
6012  funcDecl=funcType+" "+tempScopeName+"::"+funcName+funcArgs;
6013  }
6014  }
6015  else
6016  {
6017  if (isFunc) // a function => we use argList for the arguments
6018  {
6019  funcDecl=tempScopeName+"::"+funcName+funcTempList;
6020  }
6021  else // variable => add `argument' list
6022  {
6023  funcDecl=tempScopeName+"::"+funcName+funcArgs;
6024  }
6025  }
6026  }
6027  else // build declaration without scope
6028  {
6029  if (!funcType.isEmpty()) // but with a type
6030  {
6031  if (isFunc) // function => omit argument list
6032  {
6033  funcDecl=funcType+" "+funcName+funcTempList;
6034  }
6035  else // variable => add `argument' list
6036  {
6037  funcDecl=funcType+" "+funcName+funcArgs;
6038  }
6039  }
6040  else // no type
6041  {
6042  if (isFunc)
6043  {
6044  funcDecl=funcName+funcTempList;
6045  }
6046  else
6047  {
6048  funcDecl=funcName+funcArgs;
6049  }
6050  }
6051  }
6052 
6053  if (funcType=="template class" && !funcTempList.isEmpty())
6054  return; // ignore explicit template instantiations
6055 
6057  "findMember() Parse results:\n"
6058  " namespaceName=`%s'\n"
6059  " className=`%s`\n"
6060  " funcType=`%s'\n"
6061  " funcSpec=`%s'\n"
6062  " funcName=`%s'\n"
6063  " funcArgs=`%s'\n"
6064  " funcTempList=`%s'\n"
6065  " funcDecl=`%s'\n"
6066  " related=`%s'\n"
6067  " exceptions=`%s'\n"
6068  " isRelated=%d\n"
6069  " isMemberOf=%d\n"
6070  " isFriend=%d\n"
6071  " isFunc=%d\n\n",
6072  qPrint(namespaceName),qPrint(className),
6073  qPrint(funcType),qPrint(funcSpec),qPrint(funcName),qPrint(funcArgs),qPrint(funcTempList),
6074  qPrint(funcDecl),qPrint(root->relates),qPrint(exceptions),isRelated,isMemberOf,isFriend,
6075  isFunc
6076  );
6077 
6078  MemberName *mn=0;
6079  if (!funcName.isEmpty()) // function name is valid
6080  {
6082  "1. funcName=`%s'\n",funcName.data());
6083  if (funcName.left(9)=="operator ") // strip class scope from cast operator
6084  {
6085  funcName = substitute(funcName,className+"::","");
6086  }
6087  if (!funcTempList.isEmpty()) // try with member specialization
6088  {
6089  mn=Doxygen::memberNameSDict->find(funcName+funcTempList);
6090  }
6091  if (mn==0) // try without specialization
6092  {
6093  mn=Doxygen::memberNameSDict->find(funcName);
6094  }
6095  if (!isRelated && mn) // function name already found
6096  {
6098  "2. member name exists (%d members with this name)\n",mn->count());
6099  if (!className.isEmpty()) // class name is valid
6100  {
6101  if (funcSpec.isEmpty()) // not a member specialization
6102  {
6103  int count=0;
6104  int noMatchCount=0;
6105  MemberNameIterator mni(*mn);
6106  MemberDef *md;
6107  bool memFound=FALSE;
6108  for (mni.toFirst();!memFound && (md=mni.current());++mni)
6109  {
6110  ClassDef *cd=md->getClassDef();
6112  "3. member definition found, "
6113  "scope needed=`%s' scope=`%s' args=`%s' fileName=%s\n",
6114  qPrint(scopeName),cd ? qPrint(cd->name()) : "<none>",
6115  qPrint(md->argsString()),
6116  qPrint(root->fileName));
6117  //printf("Member %s (member scopeName=%s) (this scopeName=%s) classTempList=%s\n",md->name().data(),cd->name().data(),scopeName.data(),classTempList.data());
6118  FileDef *fd=rootNav->fileDef();
6119  NamespaceDef *nd=0;
6120  if (!namespaceName.isEmpty()) nd=getResolvedNamespace(namespaceName);
6121 
6122  //printf("scopeName %s->%s\n",scopeName.data(),
6123  // stripTemplateSpecifiersFromScope(scopeName,FALSE).data());
6124 
6125  ClassDef *tcd=findClassDefinition(fd,nd,scopeName);
6126  if (tcd==0 && cd && stripAnonymousNamespaceScope(cd->name())==scopeName)
6127  {
6128  // don't be fooled by anonymous scopes
6129  tcd=cd;
6130  }
6131  //printf("Looking for %s inside nd=%s result=%p (%s) cd=%p\n",
6132  // scopeName.data(),nd?nd->name().data():"<none>",tcd,tcd?tcd->name().data():"",cd);
6133 
6134  if (cd && tcd==cd) // member's classes match
6135  {
6137  "4. class definition %s found\n",cd->name().data());
6138 
6139  // get the template parameter lists found at the member declaration
6140  QList<ArgumentList> declTemplArgs;
6141  cd->getTemplateParameterLists(declTemplArgs);
6142  ArgumentList *templAl = md->templateArguments();
6143  if (templAl)
6144  {
6145  declTemplArgs.append(templAl);
6146  }
6147 
6148  // get the template parameter lists found at the member definition
6149  QList<ArgumentList> *defTemplArgs = root->tArgLists;
6150  //printf("defTemplArgs=%p\n",defTemplArgs);
6151 
6152  // do we replace the decl argument lists with the def argument lists?
6153  bool substDone=FALSE;
6154  ArgumentList *argList=0;
6155 
6156  /* substitute the occurrences of class template names in the
6157  * argument list before matching
6158  */
6159  ArgumentList *mdAl = md->argumentList();
6160  if (declTemplArgs.count()>0 && defTemplArgs &&
6161  declTemplArgs.count()==defTemplArgs->count() &&
6162  mdAl
6163  )
6164  {
6165  /* the function definition has template arguments
6166  * and the class definition also has template arguments, so
6167  * we must substitute the template names of the class by that
6168  * of the function definition before matching.
6169  */
6170  argList = new ArgumentList;
6171  substituteTemplatesInArgList(declTemplArgs,*defTemplArgs,
6172  mdAl,argList);
6173 
6174  substDone=TRUE;
6175  }
6176  else /* no template arguments, compare argument lists directly */
6177  {
6178  argList = mdAl;
6179  }
6180 
6182  "5. matching `%s'<=>`%s' className=%s namespaceName=%s\n",
6184  qPrint(className),qPrint(namespaceName)
6185  );
6186 
6187  bool matching=
6188  md->isVariable() || md->isTypedef() || // needed for function pointers
6189  (mdAl==0 && root->argList->count()==0) ||
6191  md->getClassDef(),md->getFileDef(),argList,
6192  cd,fd,root->argList,
6193  TRUE);
6194 
6195  if (md->getLanguage()==SrcLangExt_ObjC && md->isVariable() && (root->section&Entry::FUNCTION_SEC))
6196  {
6197  matching = FALSE; // don't match methods and attributes with the same name
6198  }
6199 
6200  // for template member we also need to check the return type
6201  if (md->templateArguments()!=0 && root->tArgLists!=0)
6202  {
6203  QCString memType = md->typeString();
6204  memType.stripPrefix("static "); // see bug700696
6206  className+"::",""); // see bug700693 & bug732594
6208  className+"::",""); // see bug758900
6210  "5b. Comparing return types '%s'<->'%s' #args %d<->%d\n",
6211  qPrint(md->typeString()),qPrint(funcType),
6212  md->templateArguments()->count(),root->tArgLists->getLast()->count());
6213  if (md->templateArguments()->count()!=root->tArgLists->getLast()->count() ||
6214  qstrcmp(memType,funcType))
6215  {
6216  //printf(" ---> no matching\n");
6217  matching = FALSE;
6218  }
6219  }
6220  bool rootIsUserDoc = (root->section&Entry::MEMBERDOC_SEC)!=0;
6221  bool classIsTemplate = scopeIsTemplate(md->getClassDef());
6222  bool mdIsTemplate = md->templateArguments()!=0;
6223  bool classOrMdIsTemplate = mdIsTemplate || classIsTemplate;
6224  bool rootIsTemplate = root->tArgLists!=0;
6225  //printf("classIsTemplate=%d mdIsTemplate=%d rootIsTemplate=%d\n",classIsTemplate,mdIsTemplate,rootIsTemplate);
6226  if (!rootIsUserDoc && // don't check out-of-line @fn references, see bug722457
6227  (mdIsTemplate || rootIsTemplate) && // either md or root is a template
6228  ((classOrMdIsTemplate && !rootIsTemplate) || (!classOrMdIsTemplate && rootIsTemplate))
6229  )
6230  {
6231  // Method with template return type does not match method without return type
6232  // even if the parameters are the same. See also bug709052
6234  "5b. Comparing return types: template v.s. non-template\n");
6235  matching = FALSE;
6236  }
6237 
6238 
6240  "6. match results of matchArguments2 = %d\n",matching);
6241 
6242  if (substDone) // found a new argument list
6243  {
6244  if (matching) // replace member's argument list
6245  {
6246  md->setDefinitionTemplateParameterLists(root->tArgLists);
6247  md->setArgumentList(argList); // new owner of the list => no delete
6248  }
6249  else // no match
6250  {
6251  if (!funcTempList.isEmpty() &&
6252  isSpecialization(declTemplArgs,*defTemplArgs))
6253  {
6254  // check if we are dealing with a partial template
6255  // specialization. In this case we add it to the class
6256  // even though the member arguments do not match.
6257 
6258  // TODO: copy other aspects?
6259  root->protection=md->protection(); // copy protection level
6260  addMethodToClass(rootNav,cd,md->name(),isFriend);
6261  return;
6262  }
6263  delete argList;
6264  }
6265  }
6266  if (matching)
6267  {
6268  addMemberDocs(rootNav,md,funcDecl,0,overloaded,0/* TODO */);
6269  count++;
6270  memFound=TRUE;
6271  }
6272  }
6273  else if (cd && cd!=tcd) // we did find a class with the same name as cd
6274  // but in a different namespace
6275  {
6276  noMatchCount++;
6277  }
6278  }
6279  if (count==0 && rootNav->parent() &&
6280  rootNav->parent()->section()==Entry::OBJCIMPL_SEC)
6281  {
6282  goto localObjCMethod;
6283  }
6284  if (count==0 && !(isFriend && funcType=="class"))
6285  {
6286  int candidates=0;
6287  ClassDef *ecd = 0, *ucd = 0;
6288  MemberDef *emd = 0, *umd = 0;
6289  if (mn->count()>0)
6290  {
6291  //printf("Assume template class\n");
6292  for (mni.toFirst();(md=mni.current());++mni)
6293  {
6294  ClassDef *ccd=md->getClassDef();
6295  MemberDef *cmd=md;
6296  //printf("ccd->name()==%s className=%s\n",ccd->name().data(),className.data());
6297  if (ccd!=0 && rightScopeMatch(ccd->name(),className))
6298  {
6299  ArgumentList *templAl = md->templateArguments();
6300  if (root->tArgLists && templAl!=0 &&
6301  root->tArgLists->getLast()->count()<=templAl->count())
6302  {
6303  addMethodToClass(rootNav,ccd,md->name(),isFriend);
6304  return;
6305  }
6306  if (md->argsString()==argListToString(root->argList,TRUE,FALSE))
6307  { // exact argument list match -> remember
6308  ucd = ecd = ccd;
6309  umd = emd = cmd;
6311  "7. new candidate className=%s scope=%s args=%s exact match\n",
6312  qPrint(className),qPrint(ccd->name()),qPrint(md->argsString()));
6313  }
6314  else // arguments do not match, but member name and scope do -> remember
6315  {
6316  ucd = ccd;
6317  umd = cmd;
6319  "7. new candidate className=%s scope=%s args=%s no match\n",
6320  qPrint(className),qPrint(ccd->name()),qPrint(md->argsString()));
6321  }
6322  candidates++;
6323  }
6324  }
6325  }
6326  static bool strictProtoMatching = Config_getBool("STRICT_PROTO_MATCHING");
6327  if (!strictProtoMatching)
6328  {
6329  if (candidates==1 && ucd && umd)
6330  {
6331  // we didn't find an actual match on argument lists, but there is only 1 member with this
6332  // name in the same scope, so that has to be the one.
6333  addMemberDocs(rootNav,umd,funcDecl,0,overloaded,0);
6334  return;
6335  }
6336  else if (candidates>1 && ecd && emd)
6337  {
6338  // we didn't find a unique match using type resolution,
6339  // but one of the matches has the exact same signature so
6340  // we take that one.
6341  addMemberDocs(rootNav,emd,funcDecl,0,overloaded,0);
6342  return;
6343  }
6344  }
6345 
6346  QCString warnMsg = "no ";
6347  if (noMatchCount>1) warnMsg+="uniquely ";
6348  warnMsg+="matching class member found for \n";
6349 
6350  if (root->tArgLists)
6351  {
6353  ArgumentList *al;
6354  for (;(al=alli.current());++alli)
6355  {
6356  warnMsg+=" template ";
6357  warnMsg+=tempArgListToString(al,root->lang);
6358  warnMsg+='\n';
6359  }
6360  }
6361  QCString fullFuncDecl=funcDecl.copy();
6362  if (isFunc) fullFuncDecl+=argListToString(root->argList,TRUE);
6363 
6364  warnMsg+=" ";
6365  warnMsg+=fullFuncDecl;
6366  warnMsg+='\n';
6367 
6368  if (candidates>0)
6369  {
6370  warnMsg+="Possible candidates:\n";
6371  for (mni.toFirst();(md=mni.current());++mni)
6372  {
6373  ClassDef *cd=md->getClassDef();
6374  if (cd!=0 && rightScopeMatch(cd->name(),className))
6375  {
6376  ArgumentList *templAl = md->templateArguments();
6377  if (templAl!=0)
6378  {
6379  warnMsg+=" 'template ";
6380  warnMsg+=tempArgListToString(templAl,root->lang);
6381  warnMsg+='\n';
6382  }
6383  warnMsg+=" ";
6384  if (md->typeString())
6385  {
6386  warnMsg+=md->typeString();
6387  warnMsg+=' ';
6388  }
6390  if (!qScope.isEmpty())
6391  warnMsg+=qScope+"::"+md->name();
6392  if (md->argsString())
6393  warnMsg+=md->argsString();
6394  if (noMatchCount>1)
6395  {
6396  warnMsg+="' at line "+QCString().setNum(md->getDefLine()) +
6397  " of file "+md->getDefFileName();
6398  }
6399 
6400  warnMsg+='\n';
6401  }
6402  }
6403  }
6404  warn_simple(root->fileName,root->startLine,warnMsg);
6405  }
6406  }
6407  else if (cd) // member specialization
6408  {
6409  MemberNameIterator mni(*mn);
6410  MemberDef *declMd=0;
6411  MemberDef *md=0;
6412  for (mni.toFirst();(md=mni.current());++mni)
6413  {
6414  if (md->getClassDef()==cd)
6415  {
6416  // TODO: we should probably also check for matching arguments
6417  declMd = md;
6418  break;
6419  }
6420  }
6422  ArgumentList *tArgList = new ArgumentList;
6423  // getTemplateArgumentsFromName(cd->name()+"::"+funcName,root->tArgLists);
6424  md=new MemberDef(
6425  root->fileName,root->startLine,root->startColumn,
6426  funcType,funcName,funcArgs,exceptions,
6427  declMd ? declMd->protection() : root->protection,
6428  root->virt,root->stat,Member,
6429  mtype,tArgList,root->argList);
6430  //printf("new specialized member %s args=`%s'\n",md->name().data(),funcArgs.data());
6431  md->setTagInfo(rootNav->tagInfo());
6432  md->setLanguage(root->lang);
6433  md->setId(root->id);
6434  md->setMemberClass(cd);
6436  md->setTypeConstraints(root->typeConstr);
6437  md->setDefinition(funcDecl);
6438  md->enableCallGraph(root->callGraph);
6439  md->enableCallerGraph(root->callerGraph);
6440  md->setDocumentation(root->doc,root->docFile,root->docLine);
6441  md->setBriefDescription(root->brief,root->briefFile,root->briefLine);
6442  md->setInbodyDocumentation(root->inbodyDocs,root->inbodyFile,root->inbodyLine);
6443  md->setDocsForDefinition(!root->proto);
6444  md->setPrototype(root->proto);
6445  md->addSectionsToDefinition(root->anchors);
6446  md->setBodySegment(root->bodyLine,root->endBodyLine);
6447  FileDef *fd=rootNav->fileDef();
6448  md->setBodyDef(fd);
6449  md->setMemberSpecifiers(root->spec);
6450  md->setMemberGroupId(root->mGrpId);
6451  mn->append(md);
6452  cd->insertMember(md);
6453  md->setRefItems(root->sli);
6454  delete tArgList;
6455  }
6456  else
6457  {
6458  //printf("*** Specialized member %s of unknown scope %s%s found!\n",
6459  // scopeName.data(),funcName.data(),funcArgs.data());
6460  }
6461  }
6462  else if (overloaded) // check if the function belongs to only one class
6463  {
6464  // for unique overloaded member we allow the class to be
6465  // omitted, this is to be Qt compatible. Using this should
6466  // however be avoided, because it is error prone
6467  MemberNameIterator mni(*mn);
6468  MemberDef *md=mni.toFirst();
6469  ASSERT(md);
6470  ClassDef *cd=md->getClassDef();
6471  ASSERT(cd);
6472  QCString className=cd->name().copy();
6473  ++mni;
6474  bool unique=TRUE;
6475  for (;(md=mni.current());++mni)
6476  {
6477  ClassDef *cd=md->getClassDef();
6478  if (className!=cd->name()) unique=FALSE;
6479  }
6480  if (unique)
6481  {
6482  MemberType mtype;
6483  if (root->mtype==Signal) mtype=MemberType_Signal;
6484  else if (root->mtype==Slot) mtype=MemberType_Slot;
6485  else if (root->mtype==DCOP) mtype=MemberType_DCOP;
6486  else mtype=MemberType_Function;
6487 
6488  // new overloaded member function
6489  ArgumentList *tArgList =
6490  getTemplateArgumentsFromName(cd->name()+"::"+funcName,root->tArgLists);
6491  //printf("new related member %s args=`%s'\n",md->name().data(),funcArgs.data());
6492  MemberDef *md=new MemberDef(
6493  root->fileName,root->startLine,root->startColumn,
6494  funcType,funcName,funcArgs,exceptions,
6495  root->protection,root->virt,root->stat,Related,
6496  mtype,tArgList,root->argList);
6497  md->setTagInfo(rootNav->tagInfo());
6498  md->setLanguage(root->lang);
6499  md->setId(root->id);
6500  md->setTypeConstraints(root->typeConstr);
6501  md->setMemberClass(cd);
6502  md->setDefinition(funcDecl);
6503  md->enableCallGraph(root->callGraph);
6504  md->enableCallerGraph(root->callerGraph);
6506  doc+="<p>";
6507  doc+=root->doc;
6508  md->setDocumentation(doc,root->docFile,root->docLine);
6509  md->setBriefDescription(root->brief,root->briefFile,root->briefLine);
6510  md->setInbodyDocumentation(root->inbodyDocs,root->inbodyFile,root->inbodyLine);
6511  md->setDocsForDefinition(!root->proto);
6512  md->setPrototype(root->proto);
6513  md->addSectionsToDefinition(root->anchors);
6514  md->setBodySegment(root->bodyLine,root->endBodyLine);
6515  FileDef *fd=rootNav->fileDef();
6516  md->setBodyDef(fd);
6517  md->setMemberSpecifiers(root->spec);
6518  md->setMemberGroupId(root->mGrpId);
6519  mn->append(md);
6520  cd->insertMember(md);
6521  cd->insertUsedFile(fd);
6522  md->setRefItems(root->sli);
6523  }
6524  }
6525  else // unrelated function with the same name as a member
6526  {
6527  if (!findGlobalMember(rootNav,namespaceName,funcType,funcName,funcTempList,funcArgs,funcDecl))
6528  {
6529  QCString fullFuncDecl=funcDecl.copy();
6530  if (isFunc) fullFuncDecl+=argListToString(root->argList,TRUE);
6531  warn(root->fileName,root->startLine,
6532  "Cannot determine class for function\n%s",
6533  fullFuncDecl.data()
6534  );
6535  }
6536  }
6537  }
6538  else if (isRelated && !root->relates.isEmpty())
6539  {
6540  Debug::print(Debug::FindMembers,0,"2. related function\n"
6541  " scopeName=%s className=%s\n",qPrint(scopeName),qPrint(className));
6542  if (className.isEmpty()) className=root->relates;
6543  ClassDef *cd;
6544  //printf("scopeName=`%s' className=`%s'\n",scopeName.data(),className.data());
6545  if ((cd=getClass(scopeName)))
6546  {
6547  bool newMember=TRUE; // assume we have a new member
6548  bool newMemberName=FALSE;
6549  MemberDef *mdDefine=0;
6550  bool isDefine=FALSE;
6551  {
6552  MemberName *mn = Doxygen::functionNameSDict->find(funcName);
6553  if (mn)
6554  {
6555  MemberNameIterator mni(*mn);
6556  mdDefine = mni.current();
6557  while (mdDefine && !isDefine)
6558  {
6559  isDefine = isDefine || mdDefine->isDefine();
6560  if (!isDefine) { ++mni; mdDefine=mni.current(); }
6561  }
6562  }
6563  }
6564 
6565  FileDef *fd=rootNav->fileDef();
6566 
6567  if ((mn=Doxygen::memberNameSDict->find(funcName))==0)
6568  {
6569  mn=new MemberName(funcName);
6570  newMemberName=TRUE; // we create a new member name
6571  }
6572  else
6573  {
6574  MemberNameIterator mni(*mn);
6575  MemberDef *rmd;
6576  while ((rmd=mni.current()) && newMember) // see if we got another member with matching arguments
6577  {
6578  ArgumentList *rmdAl = rmd->argumentList();
6579 
6580  newMember=
6581  className!=rmd->getOuterScope()->name() ||
6582  !matchArguments2(rmd->getOuterScope(),rmd->getFileDef(),rmdAl,
6583  cd,fd,root->argList,
6584  TRUE);
6585  if (newMember) ++mni;
6586  }
6587  if (!newMember && rmd) // member already exists as rmd -> add docs
6588  {
6589  //printf("addMemberDocs for related member %s\n",root->name.data());
6590  //rmd->setMemberDefTemplateArguments(root->mtArgList);
6591  addMemberDocs(rootNav,rmd,funcDecl,0,overloaded);
6592  }
6593  }
6594 
6595  if (newMember) // need to create a new member
6596  {
6597  MemberType mtype;
6598  if (isDefine)
6599  mtype=MemberType_Define;
6600  else if (root->mtype==Signal)
6601  mtype=MemberType_Signal;
6602  else if (root->mtype==Slot)
6603  mtype=MemberType_Slot;
6604  else if (root->mtype==DCOP)
6605  mtype=MemberType_DCOP;
6606  else
6607  mtype=MemberType_Function;
6608 
6609  if (isDefine && mdDefine)
6610  {
6611  mdDefine->setHidden(TRUE);
6612  funcType="#define";
6613  funcArgs=mdDefine->argsString();
6614  funcDecl=funcType + " " + funcName;
6615  }
6616 
6617  //printf("New related name `%s' `%d'\n",funcName.data(),
6618  // root->argList ? (int)root->argList->count() : -1);
6619 
6620  // first note that we pass:
6621  // (root->tArgLists ? root->tArgLists->last() : 0)
6622  // for the template arguments fo the new "member."
6623  // this accurately reflects the template arguments of
6624  // the related function, which don't have to do with
6625  // those of the related class.
6626  MemberDef *md=new MemberDef(
6627  root->fileName,root->startLine,root->startColumn,
6628  funcType,funcName,funcArgs,exceptions,
6629  root->protection,root->virt,
6630  root->stat && !isMemberOf,
6631  isMemberOf ? Foreign : Related,
6632  mtype,
6633  (root->tArgLists ? root->tArgLists->getLast() : 0),
6634  funcArgs.isEmpty() ? 0 : root->argList);
6635 
6636  if (isDefine && mdDefine)
6637  {
6638  md->setInitializer(mdDefine->initializer());
6639  }
6640 
6641  //
6642  // we still have the problem that
6643  // MemberDef::writeDocumentation() in memberdef.cpp
6644  // writes the template argument list for the class,
6645  // as if this member is a member of the class.
6646  // fortunately, MemberDef::writeDocumentation() has
6647  // a special mechanism that allows us to totally
6648  // override the set of template argument lists that
6649  // are printed. We use that and set it to the
6650  // template argument lists of the related function.
6651  //
6653 
6654  md->setTagInfo(rootNav->tagInfo());
6655 
6656 
6657 
6658  //printf("Related member name=`%s' decl=`%s' bodyLine=`%d'\n",
6659  // funcName.data(),funcDecl.data(),root->bodyLine);
6660 
6661  // try to find the matching line number of the body from the
6662  // global function list
6663  bool found=FALSE;
6664  if (root->bodyLine==-1)
6665  {
6666  MemberName *rmn=Doxygen::functionNameSDict->find(funcName);
6667  if (rmn)
6668  {
6669  MemberNameIterator rmni(*rmn);
6670  MemberDef *rmd;
6671  while ((rmd=rmni.current()) && !found) // see if we got another member with matching arguments
6672  {
6673  ArgumentList *rmdAl = rmd->argumentList();
6674  // check for matching argument lists
6675  if (
6676  matchArguments2(rmd->getOuterScope(),rmd->getFileDef(),rmdAl,
6677  cd,fd,root->argList,
6678  TRUE)
6679  )
6680  {
6681  found=TRUE;
6682  }
6683  if (!found) ++rmni;
6684  }
6685  if (rmd) // member found -> copy line number info
6686  {
6687  md->setBodySegment(rmd->getStartBodyLine(),rmd->getEndBodyLine());
6688  md->setBodyDef(rmd->getBodyDef());
6689  //md->setBodyMember(rmd);
6690  }
6691  }
6692  }
6693  if (!found) // line number could not be found or is available in this
6694  // entry
6695  {
6696  md->setBodySegment(root->bodyLine,root->endBodyLine);
6697  md->setBodyDef(fd);
6698  }
6699 
6700  //if (root->mGrpId!=-1)
6701  //{
6702  // md->setMemberGroup(memberGroupDict[root->mGrpId]);
6703  //}
6704  md->setMemberClass(cd);
6705  md->setMemberSpecifiers(root->spec);
6706  md->setDefinition(funcDecl);
6707  md->enableCallGraph(root->callGraph);
6708  md->enableCallerGraph(root->callerGraph);
6709  md->setDocumentation(root->doc,root->docFile,root->docLine);
6710  md->setInbodyDocumentation(root->inbodyDocs,root->inbodyFile,root->inbodyLine);
6711  md->setDocsForDefinition(!root->proto);
6712  md->setPrototype(root->proto);
6713  md->setBriefDescription(root->brief,root->briefFile,root->briefLine);
6714  md->addSectionsToDefinition(root->anchors);
6715  md->setMemberGroupId(root->mGrpId);
6716  md->setLanguage(root->lang);
6717  md->setId(root->id);
6718  //md->setMemberDefTemplateArguments(root->mtArgList);
6719  mn->append(md);
6720  cd->insertMember(md);
6721  cd->insertUsedFile(fd);
6722  md->setRefItems(root->sli);
6723  if (root->relatesType == Duplicate) md->setRelatedAlso(cd);
6724  if (!isDefine)
6725  {
6726  addMemberToGroups(root,md);
6727  }
6728  //printf("Adding member=%s\n",md->name().data());
6729  if (newMemberName)
6730  {
6731  //Doxygen::memberNameList.append(mn);
6732  //Doxygen::memberNameDict.insert(funcName,mn);
6733  Doxygen::memberNameSDict->append(funcName,mn);
6734  }
6735  }
6736  if (root->relatesType == Duplicate)
6737  {
6738  if (!findGlobalMember(rootNav,namespaceName,funcType,funcName,funcTempList,funcArgs,funcDecl))
6739  {
6740  QCString fullFuncDecl=funcDecl.copy();
6741  if (isFunc) fullFuncDecl+=argListToString(root->argList,TRUE);
6742  warn(root->fileName,root->startLine,
6743  "Cannot determine file/namespace for relatedalso function\n%s",
6744  fullFuncDecl.data()
6745  );
6746  }
6747  }
6748  }
6749  else
6750  {
6751  warn_undoc(root->fileName,root->startLine,
6752  "class `%s' for related function `%s' is not "
6753  "documented.",
6754  className.data(),funcName.data()
6755  );
6756  }
6757  }
6758  else if (rootNav->parent() && rootNav->parent()->section()==Entry::OBJCIMPL_SEC)
6759  {
6760 localObjCMethod:
6761  ClassDef *cd;
6762  //printf("scopeName=`%s' className=`%s'\n",scopeName.data(),className.data());
6763  if (Config_getBool("EXTRACT_LOCAL_METHODS") && (cd=getClass(scopeName)))
6764  {
6765  Debug::print(Debug::FindMembers,0,"4. Local objective C method %s\n"
6766  " scopeName=%s className=%s\n",qPrint(root->name),qPrint(scopeName),qPrint(className));
6767  //printf("Local objective C method `%s' of class `%s' found\n",root->name.data(),cd->name().data());
6768  MemberDef *md=new MemberDef(
6769  root->fileName,root->startLine,root->startColumn,
6770  funcType,funcName,funcArgs,exceptions,
6771  root->protection,root->virt,root->stat,Member,
6772  MemberType_Function,0,root->argList);
6773  md->setTagInfo(rootNav->tagInfo());
6774  md->setLanguage(root->lang);
6775  md->setId(root->id);
6777  md->setMemberClass(cd);
6778  md->setDefinition(funcDecl);
6779  md->enableCallGraph(root->callGraph);
6780  md->enableCallerGraph(root->callerGraph);
6781  md->setDocumentation(root->doc,root->docFile,root->docLine);
6782  md->setBriefDescription(root->brief,root->briefFile,root->briefLine);
6783  md->setInbodyDocumentation(root->inbodyDocs,root->inbodyFile,root->inbodyLine);
6784  md->setDocsForDefinition(!root->proto);
6785  md->setPrototype(root->proto);
6786  md->addSectionsToDefinition(root->anchors);
6787  md->setBodySegment(root->bodyLine,root->endBodyLine);
6788  FileDef *fd=rootNav->fileDef();
6789  md->setBodyDef(fd);
6790  md->setMemberSpecifiers(root->spec);
6791  md->setMemberGroupId(root->mGrpId);
6792  cd->insertMember(md);
6793  cd->insertUsedFile(fd);
6794  md->setRefItems(root->sli);
6795  if ((mn=Doxygen::memberNameSDict->find(root->name)))
6796  {
6797  mn->append(md);
6798  }
6799  else
6800  {
6801  mn = new MemberName(root->name);
6802  mn->append(md);
6803  Doxygen::memberNameSDict->append(root->name,mn);
6804  }
6805  }
6806  else
6807  {
6808  // local objective C method found for class without interface
6809  }
6810  }
6811  else // unrelated not overloaded member found
6812  {
6813  bool globMem = findGlobalMember(rootNav,namespaceName,funcType,funcName,funcTempList,funcArgs,funcDecl);
6814  if (className.isEmpty() && !globMem)
6815  {
6816  warn(root->fileName,root->startLine,
6817  "class for member `%s' cannot "
6818  "be found.", funcName.data()
6819  );
6820  }
6821  else if (!className.isEmpty() && !globMem)
6822  {
6823  warn(root->fileName,root->startLine,
6824  "member `%s' of class `%s' cannot be found",
6825  funcName.data(),className.data());
6826  }
6827  }
6828  }
6829  else
6830  {
6831  // this should not be called
6832  warn(root->fileName,root->startLine,
6833  "member with no name found.");
6834  }
6835  return;
6836 }
6837 
6838 //----------------------------------------------------------------------
6839 // find the members corresponding to the different documentation blocks
6840 // that are extracted from the sources.
6841 
6843 {
6844  Entry *root = rootNav->entry();
6845  int i=-1,l;
6847  "findMemberDocumentation(): root->type=`%s' root->inside=`%s' root->name=`%s' root->args=`%s' section=%x root->spec=%lld root->mGrpId=%d\n",
6848  qPrint(root->type),qPrint(root->inside),qPrint(root->name),qPrint(root->args),root->section,root->spec,root->mGrpId
6849  );
6850  //printf("rootNav->parent()->name()=%s\n",rootNav->parent()->name().data());
6851  bool isFunc=TRUE;
6852 
6853  if (root->relatesType == Duplicate && !root->relates.isEmpty())
6854  {
6855  QCString tmp = root->relates;
6856  root->relates.resize(0);
6857  filterMemberDocumentation(rootNav);
6858  root->relates = tmp;
6859  }
6860 
6861  if ( // detect func variable/typedef to func ptr
6862  (i=findFunctionPtr(root->type,root->lang,&l))!=-1
6863  )
6864  {
6865  //printf("Fixing function pointer!\n");
6866  // fix type and argument
6867  root->args.prepend(root->type.right(root->type.length()-i-l));
6868  root->type=root->type.left(i+l);
6869  //printf("Results type=%s,name=%s,args=%s\n",root->type.data(),root->name.data(),root->args.data());
6870  isFunc=FALSE;
6871  }
6872  else if ((root->type.left(8)=="typedef " && root->args.find('(')!=-1))
6873  // detect function types marked as functions
6874  {
6875  isFunc=FALSE;
6876  }
6877 
6878  //printf("Member %s isFunc=%d\n",root->name.data(),isFunc);
6879  if (root->section==Entry::MEMBERDOC_SEC)
6880  {
6881  //printf("Documentation for inline member `%s' found args=`%s'\n",
6882  // root->name.data(),root->args.data());
6883  //if (root->relates.length()) printf(" Relates %s\n",root->relates.data());
6884  if (root->type.isEmpty())
6885  {
6886  findMember(rootNav,root->name+root->args+root->exception,FALSE,isFunc);
6887  }
6888  else
6889  {
6890  findMember(rootNav,root->type+" "+root->name+root->args+root->exception,FALSE,isFunc);
6891  }
6892  }
6893  else if (root->section==Entry::OVERLOADDOC_SEC)
6894  {
6895  //printf("Overloaded member %s found\n",root->name.data());
6896  findMember(rootNav,root->name,TRUE,isFunc);
6897  }
6898  else if
6899  ((root->section==Entry::FUNCTION_SEC // function
6900  ||
6901  (root->section==Entry::VARIABLE_SEC && // variable
6902  !root->type.isEmpty() && // with a type
6903  g_compoundKeywordDict.find(root->type)==0 // that is not a keyword
6904  // (to skip forward declaration of class etc.)
6905  )
6906  )
6907  )
6908  {
6909  //printf("Documentation for member `%s' found args=`%s' excp=`%s'\n",
6910  // root->name.data(),root->args.data(),root->exception.data());
6911  //if (root->relates.length()) printf(" Relates %s\n",root->relates.data());
6912  //printf("Inside=%s\n Relates=%s\n",root->inside.data(),root->relates.data());
6913  if (root->type=="friend class" || root->type=="friend struct" ||
6914  root->type=="friend union")
6915  {
6916  findMember(rootNav,
6917  root->type+" "+
6918  root->name,
6919  FALSE,FALSE);
6920 
6921  }
6922  else if (!root->type.isEmpty())
6923  {
6924  findMember(rootNav,
6925  root->type+" "+
6926  root->inside+
6927  root->name+
6928  root->args+
6929  root->exception,
6930  FALSE,isFunc);
6931  }
6932  else
6933  {
6934  findMember(rootNav,
6935  root->inside+
6936  root->name+
6937  root->args+
6938  root->exception,
6939  FALSE,isFunc);
6940  }
6941  }
6942  else if (root->section==Entry::DEFINE_SEC && !root->relates.isEmpty())
6943  {
6944  findMember(rootNav,root->name+root->args,FALSE,!root->args.isEmpty());
6945  }
6946  else if (root->section==Entry::VARIABLEDOC_SEC)
6947  {
6948  //printf("Documentation for variable %s found\n",root->name.data());
6949  //if (!root->relates.isEmpty()) printf(" Relates %s\n",root->relates.data());
6950  findMember(rootNav,root->name,FALSE,FALSE);
6951  }
6952  else if (root->section==Entry::EXPORTED_INTERFACE_SEC ||
6954  {
6955  findMember(rootNav,root->type + " " + root->name,FALSE,FALSE);
6956  }
6957  else
6958  {
6959  // skip section
6960  //printf("skip section\n");
6961  }
6962 }
6963 
6964 static void findMemberDocumentation(EntryNav *rootNav)
6965 {
6966  if (rootNav->section()==Entry::MEMBERDOC_SEC ||
6967  rootNav->section()==Entry::OVERLOADDOC_SEC ||
6968  rootNav->section()==Entry::FUNCTION_SEC ||
6969  rootNav->section()==Entry::VARIABLE_SEC ||
6970  rootNav->section()==Entry::VARIABLEDOC_SEC ||
6971  rootNav->section()==Entry::DEFINE_SEC ||
6972  rootNav->section()==Entry::INCLUDED_SERVICE_SEC ||
6974  )
6975  {
6976  rootNav->loadEntry(g_storage);
6977 
6978  filterMemberDocumentation(rootNav);
6979 
6980  rootNav->releaseEntry();
6981  }
6982  if (rootNav->children())
6983  {
6984  EntryNavListIterator eli(*rootNav->children());
6985  EntryNav *e;
6986  for (;(e=eli.current());++eli)
6987  {
6988  if (e->section()!=Entry::ENUM_SEC) findMemberDocumentation(e);
6989  }
6990  }
6991 }
6992 
6993 //----------------------------------------------------------------------
6994 
6996 {
6997  if (rootNav->children())
6998  {
6999  EntryNavListIterator eli(*rootNav->children());
7000  EntryNav *objCImplNav;
7001  for (;(objCImplNav=eli.current());++eli)
7002  {
7003  if (objCImplNav->section()==Entry::OBJCIMPL_SEC && objCImplNav->children())
7004  {
7005  EntryNavListIterator seli(*objCImplNav->children());
7006  EntryNav *objCMethodNav;
7007  for (;(objCMethodNav=seli.current());++seli)
7008  {
7009  if (objCMethodNav->section()==Entry::FUNCTION_SEC)
7010  {
7011  objCMethodNav->loadEntry(g_storage);
7012  Entry *objCMethod = objCMethodNav->entry();
7013 
7014  //Printf(" Found ObjC method definition %s\n",objCMethod->name.data());
7015  findMember(objCMethodNav, objCMethod->type+" "+objCImplNav->name()+"::"+
7016  objCMethod->name+" "+objCMethod->args, FALSE,TRUE);
7017  objCMethod->section=Entry::EMPTY_SEC;
7018 
7019  objCMethodNav->releaseEntry();
7020  }
7021  }
7022  }
7023  }
7024  }
7025 }
7026 
7027 //----------------------------------------------------------------------
7028 // find and add the enumeration to their classes, namespaces or files
7029 
7030 static void findEnums(EntryNav *rootNav)
7031 {
7032  if (rootNav->section()==Entry::ENUM_SEC)
7033  {
7034  rootNav->loadEntry(g_storage);
7035  Entry *root = rootNav->entry();
7036 
7037  MemberDef *md=0;
7038  ClassDef *cd=0;
7039  FileDef *fd=0;
7040  NamespaceDef *nd=0;
7041  MemberNameSDict *mnsd=0;
7042  bool isGlobal;
7043  bool isRelated=FALSE;
7044  bool isMemberOf=FALSE;
7045  //printf("Found enum with name `%s' relates=%s\n",root->name.data(),root->relates.data());
7046  int i;
7047 
7048  QCString name;
7049  QCString scope;
7050 
7051  if ((i=root->name.findRev("::"))!=-1) // scope is specified
7052  {
7053  scope=root->name.left(i); // extract scope
7054  name=root->name.right(root->name.length()-i-2); // extract name
7055  if ((cd=getClass(scope))==0) nd=getResolvedNamespace(scope);
7056  }
7057  else // no scope, check the scope in which the docs where found
7058  {
7059  if (( rootNav->parent()->section() & Entry::SCOPE_MASK )
7060  && !rootNav->parent()->name().isEmpty()
7061  ) // found enum docs inside a compound
7062  {
7063  scope=rootNav->parent()->name();
7064  if ((cd=getClass(scope))==0) nd=getResolvedNamespace(scope);
7065  }
7066  name=root->name;
7067  }
7068 
7069  if (!root->relates.isEmpty())
7070  { // related member, prefix user specified scope
7071  isRelated=TRUE;
7072  isMemberOf=(root->relatesType == MemberOf);
7073  if (getClass(root->relates)==0 && !scope.isEmpty())
7074  scope=mergeScopes(scope,root->relates);
7075  else
7076  scope=root->relates.copy();
7077  if ((cd=getClass(scope))==0) nd=getResolvedNamespace(scope);
7078  }
7079 
7080  if (cd && !name.isEmpty()) // found a enum inside a compound
7081  {
7082  //printf("Enum `%s'::`%s'\n",cd->name().data(),name.data());
7083  fd=0;
7085  isGlobal=FALSE;
7086  }
7087  else if (nd && !nd->name().isEmpty() && nd->name().at(0)!='@') // found enum inside namespace
7088  {
7090  isGlobal=TRUE;
7091  }
7092  else // found a global enum
7093  {
7094  fd=rootNav->fileDef();
7096  isGlobal=TRUE;
7097  }
7098 
7099  if (!name.isEmpty())
7100  {
7101  // new enum type
7102  md = new MemberDef(
7103  root->fileName,root->startLine,root->startColumn,
7104  0,name,0,0,
7105  root->protection,Normal,FALSE,
7106  isMemberOf ? Foreign : isRelated ? Related : Member,
7108  0,0);
7109  md->setTagInfo(rootNav->tagInfo());
7110  md->setLanguage(root->lang);
7111  md->setId(root->id);
7112  if (!isGlobal) md->setMemberClass(cd); else md->setFileDef(fd);
7113  md->setBodySegment(root->bodyLine,root->endBodyLine);
7114  md->setBodyDef(rootNav->fileDef());
7115  md->setMemberSpecifiers(root->spec);
7116  md->setEnumBaseType(root->args);
7117  //printf("Enum %s definition at line %d of %s: protection=%d scope=%s\n",
7118  // root->name.data(),root->bodyLine,root->fileName.data(),root->protection,cd?cd->name().data():"<none>");
7119  md->addSectionsToDefinition(root->anchors);
7120  md->setMemberGroupId(root->mGrpId);
7121  md->enableCallGraph(root->callGraph);
7122  md->enableCallerGraph(root->callerGraph);
7123  //printf("%s::setRefItems(%d)\n",md->name().data(),root->sli?root->sli->count():-1);
7124  md->setRefItems(root->sli);
7125  //printf("found enum %s nd=%p\n",md->name().data(),nd);
7126  bool defSet=FALSE;
7127 
7128  QCString baseType = root->args;
7129  if (!baseType.isEmpty())
7130  {
7131  baseType.prepend(" : ");
7132  }
7133 
7134  if (nd && !nd->name().isEmpty() && nd->name().at(0)!='@')
7135  {
7136  if (isRelated || Config_getBool("HIDE_SCOPE_NAMES"))
7137  {
7138  md->setDefinition(name+baseType);
7139  }
7140  else
7141  {
7142  md->setDefinition(nd->name()+"::"+name+baseType);
7143  }
7144  //printf("definition=%s\n",md->definition());
7145  defSet=TRUE;
7146  md->setNamespace(nd);
7147  nd->insertMember(md);
7148  }
7149 
7150  // even if we have already added the enum to a namespace, we still
7151  // also want to add it to other appropriate places such as file
7152  // or class.
7153  if (isGlobal)
7154  {
7155  if (!defSet) md->setDefinition(name+baseType);
7156  if (fd==0 && rootNav->parent())
7157  {
7158  fd=rootNav->parent()->fileDef();
7159  }
7160  if (fd)
7161  {
7162  md->setFileDef(fd);
7163  fd->insertMember(md);
7164  }
7165  }
7166  else if (cd)
7167  {
7168  if (isRelated || Config_getBool("HIDE_SCOPE_NAMES"))
7169  {
7170  md->setDefinition(name+baseType);
7171  }
7172  else
7173  {
7174  md->setDefinition(cd->name()+"::"+name+baseType);
7175  }
7176  cd->insertMember(md);
7177  cd->insertUsedFile(fd);
7178  }
7179  md->setDocumentation(root->doc,root->docFile,root->docLine);
7180  md->setDocsForDefinition(!root->proto);
7181  md->setBriefDescription(root->brief,root->briefFile,root->briefLine);
7182  md->setInbodyDocumentation(root->inbodyDocs,root->inbodyFile,root->inbodyLine);
7183 
7184  //printf("Adding member=%s\n",md->name().data());
7185  MemberName *mn;
7186  if ((mn=(*mnsd)[name]))
7187  {
7188  // this is used if the same enum is in multiple namespaces/classes
7189  mn->append(md);
7190  }
7191  else // new enum name
7192  {
7193  mn = new MemberName(name);
7194  mn->append(md);
7195  mnsd->append(name,mn);
7196  //printf("add %s to new memberName. Now %d members\n",
7197  // name.data(),mn->count());
7198  }
7199  addMemberToGroups(root,md);
7200  }
7201  rootNav->releaseEntry();
7202  }
7203  else
7204  {
7205  RECURSE_ENTRYTREE(findEnums,rootNav);
7206  }
7207 }
7208 
7209 //----------------------------------------------------------------------
7210 
7211 static void addEnumValuesToEnums(EntryNav *rootNav)
7212 {
7213  if (rootNav->section()==Entry::ENUM_SEC)
7214  // non anonymous enumeration
7215  {
7216  rootNav->loadEntry(g_storage);
7217  Entry *root = rootNav->entry();
7218 
7219  ClassDef *cd=0;
7220  FileDef *fd=0;
7221  NamespaceDef *nd=0;
7222  MemberNameSDict *mnsd=0;
7223  bool isGlobal;
7224  bool isRelated=FALSE;
7225  //printf("Found enum with name `%s' relates=%s\n",root->name.data(),root->relates.data());
7226  int i;
7227 
7228  QCString name;
7229  QCString scope;
7230 
7231  if ((i=root->name.findRev("::"))!=-1) // scope is specified
7232  {
7233  scope=root->name.left(i); // extract scope
7234  name=root->name.right(root->name.length()-i-2); // extract name
7235  if ((cd=getClass(scope))==0) nd=getResolvedNamespace(scope);
7236  }
7237  else // no scope, check the scope in which the docs where found
7238  {
7239  if (( rootNav->parent()->section() & Entry::SCOPE_MASK )
7240  && !rootNav->parent()->name().isEmpty()
7241  ) // found enum docs inside a compound
7242  {
7243  scope=rootNav->parent()->name();
7244  if ((cd=getClass(scope))==0) nd=getResolvedNamespace(scope);
7245  }
7246  name=root->name;
7247  }
7248 
7249  if (!root->relates.isEmpty())
7250  { // related member, prefix user specified scope
7251  isRelated=TRUE;
7252  if (getClass(root->relates)==0 && !scope.isEmpty())
7253  scope=mergeScopes(scope,root->relates);
7254  else
7255  scope=root->relates.copy();
7256  if ((cd=getClass(scope))==0) nd=getResolvedNamespace(scope);
7257  }
7258 
7259  if (cd && !name.isEmpty()) // found a enum inside a compound
7260  {
7261  //printf("Enum in class `%s'::`%s'\n",cd->name().data(),name.data());
7262  fd=0;
7264  isGlobal=FALSE;
7265  }
7266  else if (nd && !nd->name().isEmpty() && nd->name().at(0)!='@') // found enum inside namespace
7267  {
7268  //printf("Enum in namespace `%s'::`%s'\n",nd->name().data(),name.data());
7270  isGlobal=TRUE;
7271  }
7272  else // found a global enum
7273  {
7274  fd=rootNav->fileDef();
7275  //printf("Enum in file `%s': `%s'\n",fd->name().data(),name.data());
7277  isGlobal=TRUE;
7278  }
7279 
7280  if (!name.isEmpty())
7281  {
7282  //printf("** name=%s\n",name.data());
7283  MemberName *mn = mnsd->find(name); // for all members with this name
7284  if (mn)
7285  {
7286  MemberNameIterator mni(*mn);
7287  MemberDef *md;
7288  for (mni.toFirst(); (md=mni.current()) ; ++mni) // for each enum in this list
7289  {
7290  if (md->isEnumerate() && rootNav->children())
7291  {
7292  //printf(" enum with %d children\n",rootNav->children()->count());
7293  EntryNavListIterator eli(*rootNav->children()); // for each enum value
7294  EntryNav *e;
7295  for (;(e=eli.current());++eli)
7296  {
7297  SrcLangExt sle;
7298  if (
7299  (sle=rootNav->lang())==SrcLangExt_CSharp ||
7300  sle==SrcLangExt_Java ||
7301  sle==SrcLangExt_XML ||
7302  (root->spec&Entry::Strong)
7303  )
7304  {
7305  // Unlike classic C/C++ enums, for C++11, C# & Java enum
7306  // values are only visible inside the enum scope, so we must create
7307  // them here and only add them to the enum
7308  e->loadEntry(g_storage);
7309  Entry *root = e->entry();
7310  //printf("md->qualifiedName()=%s rootNav->name()=%s tagInfo=%p name=%s\n",
7311  // md->qualifiedName().data(),rootNav->name().data(),rootNav->tagInfo(),root->name.data());
7312  QCString qualifiedName = substitute(rootNav->name(),"::",".");
7313  if (!scope.isEmpty() && rootNav->tagInfo())
7314  {
7315  qualifiedName=substitute(scope,"::",".")+"."+qualifiedName;
7316  }
7317  if (substitute(md->qualifiedName(),"::",".")== // TODO: add function to get canonical representation
7318  qualifiedName // enum value scope matches that of the enum
7319  )
7320  {
7321  QCString fileName = root->fileName;
7322  if (fileName.isEmpty() && rootNav->tagInfo())
7323  {
7324  fileName = rootNav->tagInfo()->tagName;
7325  }
7326  MemberDef *fmd=new MemberDef(
7327  fileName,root->startLine,root->startColumn,
7328  root->type,root->name,root->args,0,
7329  root->protection, Normal,root->stat,Member,
7330  MemberType_EnumValue,0,0);
7331  if (md->getClassDef()) fmd->setMemberClass(md->getClassDef());
7332  else if (md->getNamespaceDef()) fmd->setNamespace(md->getNamespaceDef());
7333  else if (md->getFileDef()) fmd->setFileDef(md->getFileDef());
7334  fmd->setOuterScope(md->getOuterScope());
7335  fmd->setTagInfo(e->tagInfo());
7336  fmd->setLanguage(root->lang);
7337  fmd->setId(root->id);
7338  fmd->setDocumentation(root->doc,root->docFile,root->docLine);
7339  fmd->setBriefDescription(root->brief,root->briefFile,root->briefLine);
7340  fmd->addSectionsToDefinition(root->anchors);
7341  fmd->setInitializer(root->initializer);
7342  fmd->setMaxInitLines(root->initLines);
7343  fmd->setMemberGroupId(root->mGrpId);
7345  fmd->setRefItems(root->sli);
7346  fmd->setAnchor();
7347  md->insertEnumField(fmd);
7348  fmd->setEnumScope(md,TRUE);
7349  MemberName *mn=mnsd->find(root->name);
7350  if (mn)
7351  {
7352  mn->append(fmd);
7353  }
7354  else
7355  {
7356  mn = new MemberName(root->name);
7357  mn->append(fmd);
7358  mnsd->append(root->name,mn);
7359  }
7360  }
7361  e->releaseEntry();
7362  }
7363  else
7364  {
7365  //printf("e->name=%s isRelated=%d\n",e->name().data(),isRelated);
7366  MemberName *fmn=0;
7367  MemberNameSDict *emnsd = isRelated ? Doxygen::functionNameSDict : mnsd;
7368  if (!e->name().isEmpty() && (fmn=(*emnsd)[e->name()]))
7369  // get list of members with the same name as the field
7370  {
7371  MemberNameIterator fmni(*fmn);
7372  MemberDef *fmd;
7373  for (fmni.toFirst(); (fmd=fmni.current()) ; ++fmni)
7374  {
7375  if (fmd->isEnumValue() && fmd->getOuterScope()==md->getOuterScope()) // in same scope
7376  {
7377  //printf("found enum value with same name %s in scope %s\n",
7378  // fmd->name().data(),fmd->getOuterScope()->name().data());
7379  if (nd && !nd->name().isEmpty() && nd->name().at(0)!='@')
7380  {
7381  NamespaceDef *fnd=fmd->getNamespaceDef();
7382  if (fnd==nd) // enum value is inside a namespace
7383  {
7384  md->insertEnumField(fmd);
7385  fmd->setEnumScope(md);
7386  }
7387  }
7388  else if (isGlobal)
7389  {
7390  FileDef *ffd=fmd->getFileDef();
7391  if (ffd==fd) // enum value has file scope
7392  {
7393  md->insertEnumField(fmd);
7394  fmd->setEnumScope(md);
7395  }
7396  }
7397  else if (isRelated && cd) // reparent enum value to
7398  // match the enum's scope
7399  {
7400  md->insertEnumField(fmd); // add field def to list
7401  fmd->setEnumScope(md); // cross ref with enum name
7402  fmd->setEnumClassScope(cd); // cross ref with enum name
7403  fmd->setOuterScope(cd);
7404  fmd->makeRelated();
7405  cd->insertMember(fmd);
7406  }
7407  else
7408  {
7409  ClassDef *fcd=fmd->getClassDef();
7410  if (fcd==cd) // enum value is inside a class
7411  {
7412  //printf("Inserting enum field %s in enum scope %s\n",
7413  // fmd->name().data(),md->name().data());
7414  md->insertEnumField(fmd); // add field def to list
7415  fmd->setEnumScope(md); // cross ref with enum name
7416  }
7417  }
7418  }
7419  }
7420  }
7421  }
7422  }
7423  }
7424  }
7425  }
7426  }
7427 
7428  rootNav->releaseEntry();
7429  }
7430  else
7431  {
7433  }
7434 }
7435 
7436 
7437 //----------------------------------------------------------------------
7438 // find the documentation blocks for the enumerations
7439 
7440 static void findEnumDocumentation(EntryNav *rootNav)
7441 {
7442  if (rootNav->section()==Entry::ENUMDOC_SEC
7443  && !rootNav->name().isEmpty()
7444  && rootNav->name().at(0)!='@' // skip anonymous enums
7445  )
7446  {
7447  rootNav->loadEntry(g_storage);
7448  Entry *root = rootNav->entry();
7449 
7450  //printf("Found docs for enum with name `%s' in context %s\n",
7451  // root->name.data(),root->parent->name.data());
7452  int i;
7453  QCString name;
7454  QCString scope;
7455  if ((i=root->name.findRev("::"))!=-1) // scope is specified as part of the name
7456  {
7457  name=root->name.right(root->name.length()-i-2); // extract name
7458  scope=root->name.left(i); // extract scope
7459  //printf("Scope=`%s' Name=`%s'\n",scope.data(),name.data());
7460  }
7461  else // just the name
7462  {
7463  name=root->name;
7464  }
7465  if (( rootNav->parent()->section() & Entry::SCOPE_MASK )
7466  && !rootNav->parent()->name().isEmpty()
7467  ) // found enum docs inside a compound
7468  {
7469  if (!scope.isEmpty()) scope.prepend("::");
7470  scope.prepend(rootNav->parent()->name());
7471  }
7472  ClassDef *cd=getClass(scope);
7473 
7474  if (!name.isEmpty())
7475  {
7476  bool found=FALSE;
7477  if (cd)
7478  {
7479  //printf("Enum: scope=`%s' name=`%s'\n",cd->name(),name.data());
7480  QCString className=cd->name().copy();
7481  MemberName *mn=Doxygen::memberNameSDict->find(name);
7482  if (mn)
7483  {
7484  MemberNameIterator mni(*mn);
7485  MemberDef *md;
7486  for (mni.toFirst();(md=mni.current()) && !found;++mni)
7487  {
7488  ClassDef *cd=md->getClassDef();
7489  if (cd && cd->name()==className && md->isEnumerate())
7490  {
7491  // documentation outside a compound overrides the documentation inside it
7492 #if 0
7493  if (!md->documentation() || rootNav->parent()->name().isEmpty())
7494 #endif
7495  {
7496  md->setDocumentation(root->doc,root->docFile,root->docLine);
7497  md->setDocsForDefinition(!root->proto);
7498  }
7499 
7500  // brief descriptions inside a compound override the documentation
7501  // outside it
7502 #if 0
7503  if (!md->briefDescription() || !rootNav->parent()->name().isEmpty())
7504 #endif
7505  {
7506  md->setBriefDescription(root->brief,root->briefFile,root->briefLine);
7507  }
7508 
7509  if (!md->inbodyDocumentation() || !rootNav->parent()->name().isEmpty())
7510  {
7511  md->setInbodyDocumentation(root->inbodyDocs,root->inbodyFile,root->inbodyLine);
7512  }
7513 
7514  if (root->mGrpId!=-1 && md->getMemberGroupId()==-1)
7515  {
7516  md->setMemberGroupId(root->mGrpId);
7517  }
7518 
7519  md->addSectionsToDefinition(root->anchors);
7520  md->setRefItems(root->sli);
7521 
7522  GroupDef *gd=md->getGroupDef();
7523  if (gd==0 &&root->groups->getFirst()!=0) // member not grouped but out-of-line documentation is
7524  {
7525  addMemberToGroups(root,md);
7526  }
7527 
7528  found=TRUE;
7529  }
7530  }
7531  }
7532  else
7533  {
7534  //printf("MemberName %s not found!\n",name.data());
7535  }
7536  }
7537  else // enum outside class
7538  {
7539  //printf("Enum outside class: %s grpId=%d\n",name.data(),root->mGrpId);
7540  MemberName *mn=Doxygen::functionNameSDict->find(name);
7541  if (mn)
7542  {
7543  MemberNameIterator mni(*mn);
7544  MemberDef *md;
7545  for (mni.toFirst();(md=mni.current()) && !found;++mni)
7546  {
7547  if (md->isEnumerate())
7548  {
7549  md->setDocumentation(root->doc,root->docFile,root->docLine);
7550  md->setDocsForDefinition(!root->proto);
7551  md->setBriefDescription(root->brief,root->briefFile,root->briefLine);
7552  md->setInbodyDocumentation(root->inbodyDocs,root->inbodyFile,root->inbodyLine);
7553  md->addSectionsToDefinition(root->anchors);
7554  md->setMemberGroupId(root->mGrpId);
7555 
7556  GroupDef *gd=md->getGroupDef();
7557  if (gd==0 && root->groups->getFirst()!=0) // member not grouped but out-of-line documentation is
7558  {
7559  addMemberToGroups(root,md);
7560  }
7561 
7562  found=TRUE;
7563  }
7564  }
7565  }
7566  }
7567  if (!found)
7568  {
7569  warn(root->fileName,root->startLine,
7570  "Documentation for undefined enum `%s' found.",
7571  name.data()
7572  );
7573  }
7574  }
7575 
7576  rootNav->releaseEntry();
7577  }
7579 }
7580 
7581 // search for each enum (member or function) in mnl if it has documented
7582 // enum values.
7583 static void findDEV(const MemberNameSDict &mnsd)
7584 {
7585  MemberName *mn;
7586  MemberNameSDict::Iterator mnli(mnsd);
7587  // for each member name
7588  for (mnli.toFirst();(mn=mnli.current());++mnli)
7589  {
7590  MemberDef *md;
7591  MemberNameIterator mni(*mn);
7592  // for each member definition
7593  for (mni.toFirst();(md=mni.current());++mni)
7594  {
7595  if (md->isEnumerate()) // member is an enum
7596  {
7597  MemberList *fmdl = md->enumFieldList();
7598  int documentedEnumValues=0;
7599  if (fmdl) // enum has values
7600  {
7601  MemberListIterator fmni(*fmdl);
7602  MemberDef *fmd;
7603  // for each enum value
7604  for (fmni.toFirst();(fmd=fmni.current());++fmni)
7605  {
7606  if (fmd->isLinkableInProject()) documentedEnumValues++;
7607  }
7608  }
7609  // at least one enum value is documented
7610  if (documentedEnumValues>0) md->setDocumentedEnumValues(TRUE);
7611  }
7612  }
7613  }
7614 }
7615 
7616 // search for each enum (member or function) if it has documented enum
7617 // values.
7619 {
7620  findDEV(*Doxygen::memberNameSDict);
7621  findDEV(*Doxygen::functionNameSDict);
7622 }
7623 
7624 //----------------------------------------------------------------------
7625 
7626 static void addMembersToIndex()
7627 {
7628  MemberName *mn;
7629  MemberNameSDict::Iterator mnli(*Doxygen::memberNameSDict);
7630  // for each member name
7631  for (mnli.toFirst();(mn=mnli.current());++mnli)
7632  {
7633  MemberDef *md;
7634  MemberNameIterator mni(*mn);
7635  // for each member definition
7636  for (mni.toFirst();(md=mni.current());++mni)
7637  {
7639  }
7640  }
7641  MemberNameSDict::Iterator fnli(*Doxygen::functionNameSDict);
7642  // for each member name
7643  for (fnli.toFirst();(mn=fnli.current());++fnli)
7644  {
7645  MemberDef *md;
7646  MemberNameIterator mni(*mn);
7647  // for each member definition
7648  for (mni.toFirst();(md=mni.current());++mni)
7649  {
7650  if (md->getNamespaceDef())
7651  {
7653  }
7654  else
7655  {
7657  }
7658  }
7659  }
7660 }
7661 
7662 //----------------------------------------------------------------------
7663 // computes the relation between all members. For each member `m'
7664 // the members that override the implementation of `m' are searched and
7665 // the member that `m' overrides is searched.
7666 
7668 {
7669  MemberNameSDict::Iterator mnli(*Doxygen::memberNameSDict);
7670  MemberName *mn;
7671  for ( ; (mn=mnli.current()) ; ++mnli ) // for each member name
7672  {
7673  MemberNameIterator mdi(*mn);
7674  MemberNameIterator bmdi(*mn);
7675  MemberDef *md;
7676  MemberDef *bmd;
7677  for ( ; (md=mdi.current()) ; ++mdi ) // for each member with a specific name
7678  {
7679  for ( bmdi.toFirst() ; (bmd=bmdi.current()); ++bmdi ) // for each other member with the same name
7680  {
7681  ClassDef *mcd = md->getClassDef();
7682  if (mcd && mcd->baseClasses())
7683  {
7684  ClassDef *bmcd = bmd->getClassDef();
7685  //printf("Check relation between `%s'::`%s' (%p) and `%s'::`%s' (%p)\n",
7686  // mcd->name().data(),md->name().data(),md,
7687  // bmcd->name().data(),bmd->name().data(),bmd
7688  // );
7689  if (md!=bmd && bmcd && mcd && bmcd!=mcd &&
7690  (bmd->virtualness()!=Normal ||
7691  bmcd->compoundType()==ClassDef::Interface ||
7693  ) &&
7694  md->isFunction() &&
7695  mcd->isLinkable() &&
7696  bmcd->isLinkable() &&
7697  mcd->isBaseClass(bmcd,TRUE))
7698  {
7699  //printf(" derived scope\n");
7700  ArgumentList *bmdAl = bmd->argumentList();
7701  ArgumentList *mdAl = md->argumentList();
7702  //printf(" Base argList=`%s'\n Super argList=`%s'\n",
7703  // argListToString(bmdAl.pointer()).data(),
7704  // argListToString(mdAl.pointer()).data()
7705  // );
7706  if (
7707  matchArguments2(bmd->getOuterScope(),bmd->getFileDef(),bmdAl,
7708  md->getOuterScope(), md->getFileDef(), mdAl,
7709  TRUE
7710  )
7711  )
7712  {
7713  MemberDef *rmd;
7714  if ((rmd=md->reimplements())==0 ||
7715  minClassDistance(mcd,bmcd)<minClassDistance(mcd,rmd->getClassDef())
7716  )
7717  {
7718  //printf("setting (new) reimplements member\n");
7719  md->setReimplements(bmd);
7720  }
7721  //printf("%s: add reimplementedBy member %s\n",bmcd->name().data(),mcd->name().data());
7722  bmd->insertReimplementedBy(md);
7723  }
7724  }
7725  }
7726  }
7727  }
7728  }
7729 }
7730 
7731 
7732 //----------------------------------------------------------------------------
7733 //static void computeClassImplUsageRelations()
7734 //{
7735 // ClassDef *cd;
7736 // ClassSDict::Iterator cli(*Doxygen::classSDict);
7737 // for (;(cd=cli.current());++cli)
7738 // {
7739 // cd->determineImplUsageRelation();
7740 // }
7741 //}
7742 
7743 //----------------------------------------------------------------------------
7744 
7746 {
7747  ClassSDict::Iterator cli(*Doxygen::classSDict);
7748  ClassDef *cd;
7749  // for each class
7750  for (cli.toFirst();(cd=cli.current());++cli)
7751  {
7752  // that is a template
7753  QDict<ClassDef> *templInstances = cd->getTemplateInstances();
7754  if (templInstances)
7755  {
7756  QDictIterator<ClassDef> qdi(*templInstances);
7757  ClassDef *tcd=0;
7758  // for each instance of the template
7759  for (qdi.toFirst();(tcd=qdi.current());++qdi)
7760  {
7761  tcd->addMembersToTemplateInstance(cd,qdi.currentKey());
7762  }
7763  }
7764  }
7765 }
7766 
7767 //----------------------------------------------------------------------------
7768 
7769 static void mergeCategories()
7770 {
7771  ClassDef *cd;
7772  ClassSDict::Iterator cli(*Doxygen::classSDict);
7773  // merge members of categories into the class they extend
7774  for (cli.toFirst();(cd=cli.current());++cli)
7775  {
7776  int i=cd->name().find('(');
7777  if (i!=-1) // it is an Objective-C category
7778  {
7779  QCString baseName=cd->name().left(i);
7780  ClassDef *baseClass=Doxygen::classSDict->find(baseName);
7781  if (baseClass)
7782  {
7783  //printf("*** merging members of category %s into %s\n",
7784  // cd->name().data(),baseClass->name().data());
7785  baseClass->mergeCategory(cd);
7786  }
7787  }
7788  }
7789 }
7790 
7791 // builds the list of all members for each class
7792 
7794 {
7795  ClassDef *cd;
7796  ClassSDict::Iterator cli(*Doxygen::classSDict);
7797  // merge the member list of base classes into the inherited classes.
7798  for (cli.toFirst();(cd=cli.current());++cli)
7799  {
7800  if (// !cd->isReference() && // not an external class
7801  cd->subClasses()==0 && // is a root of the hierarchy
7802  cd->baseClasses()) // and has at least one base class
7803  {
7804  //printf("*** merging members for %s\n",cd->name().data());
7805  cd->mergeMembers();
7806  }
7807  }
7808  // now sort the member list of all classes.
7809  for (cli.toFirst();(cd=cli.current());++cli)
7810  {
7811  if (cd->memberNameInfoSDict()) cd->memberNameInfoSDict()->sort();
7812  }
7813 }
7814 
7815 //----------------------------------------------------------------------------
7816 
7817 static void generateFileSources()
7818 {
7819  if (Doxygen::inputNameList->count()>0)
7820  {
7821 #if USE_LIBCLANG
7822  static bool clangAssistedParsing = Config_getBool("CLANG_ASSISTED_PARSING");
7823  if (clangAssistedParsing)
7824  {
7825  QDict<void> g_processedFiles(10007);
7826 
7827  // create a dictionary with files to process
7828  QDict<void> g_filesToProcess(10007);
7829  FileNameListIterator fnli(*Doxygen::inputNameList);
7830  FileName *fn;
7831  for (fnli.toFirst();(fn=fnli.current());++fnli)
7832  {
7833  FileNameIterator fni(*fn);
7834  FileDef *fd;
7835  for (;(fd=fni.current());++fni)
7836  {
7837  g_filesToProcess.insert(fd->absFilePath(),(void*)0x8);
7838  }
7839  }
7840  // process source files (and their include dependencies)
7841  for (fnli.toFirst();(fn=fnli.current());++fnli)
7842  {
7843  FileNameIterator fni(*fn);
7844  FileDef *fd;
7845  for (;(fd=fni.current());++fni)
7846  {
7847  if (fd->isSource() && !fd->isReference())
7848  {
7849  QStrList filesInSameTu;
7850  fd->getAllIncludeFilesRecursively(filesInSameTu);
7851  fd->startParsing();
7852  if (fd->generateSourceFile() && !g_useOutputTemplate) // sources need to be shown in the output
7853  {
7854  msg("Generating code for file %s...\n",fd->docName().data());
7855  fd->writeSource(*g_outputList,FALSE,filesInSameTu);
7856 
7857  }
7858  else if (!fd->isReference() && Doxygen::parseSourcesNeeded)
7859  // we needed to parse the sources even if we do not show them
7860  {
7861  msg("Parsing code for file %s...\n",fd->docName().data());
7862  fd->parseSource(FALSE,filesInSameTu);
7863  }
7864 
7865  char *incFile = filesInSameTu.first();
7866  while (incFile && g_filesToProcess.find(incFile))
7867  {
7868  if (fd->absFilePath()!=incFile && !g_processedFiles.find(incFile))
7869  {
7870  QStrList moreFiles;
7871  bool ambig;
7872  FileDef *ifd=findFileDef(Doxygen::inputNameDict,incFile,ambig);
7873  if (ifd && !ifd->isReference())
7874  {
7875  if (ifd->generateSourceFile() && !g_useOutputTemplate) // sources need to be shown in the output
7876  {
7877  msg(" Generating code for file %s...\n",ifd->docName().data());
7878  ifd->writeSource(*g_outputList,TRUE,moreFiles);
7879 
7880  }
7881  else if (!ifd->isReference() && Doxygen::parseSourcesNeeded)
7882  // we needed to parse the sources even if we do not show them
7883  {
7884  msg(" Parsing code for file %s...\n",ifd->docName().data());
7885  ifd->parseSource(TRUE,moreFiles);
7886  }
7887  g_processedFiles.insert(incFile,(void*)0x8);
7888  }
7889  }
7890  incFile = filesInSameTu.next();
7891  }
7892  fd->finishParsing();
7893  g_processedFiles.insert(fd->absFilePath(),(void*)0x8);
7894  }
7895  }
7896  }
7897  // process remaining files
7898  for (fnli.toFirst();(fn=fnli.current());++fnli)
7899  {
7900  FileNameIterator fni(*fn);
7901  FileDef *fd;
7902  for (;(fd=fni.current());++fni)
7903  {
7904  if (!g_processedFiles.find(fd->absFilePath())) // not yet processed
7905  {
7906  QStrList filesInSameTu;
7907  fd->startParsing();
7908  if (fd->generateSourceFile() && !g_useOutputTemplate) // sources need to be shown in the output
7909  {
7910  msg("Generating code for file %s...\n",fd->docName().data());
7911  fd->writeSource(*g_outputList,FALSE,filesInSameTu);
7912 
7913  }
7914  else if (!fd->isReference() && Doxygen::parseSourcesNeeded)
7915  // we needed to parse the sources even if we do not show them
7916  {
7917  msg("Parsing code for file %s...\n",fd->docName().data());
7918  fd->parseSource(FALSE,filesInSameTu);
7919  }
7920  fd->finishParsing();
7921  }
7922  }
7923  }
7924  }
7925  else
7926 #endif
7927  {
7928  FileNameListIterator fnli(*Doxygen::inputNameList);
7929  FileName *fn;
7930  for (;(fn=fnli.current());++fnli)
7931  {
7932  FileNameIterator fni(*fn);
7933  FileDef *fd;
7934  for (;(fd=fni.current());++fni)
7935  {
7936  QStrList filesInSameTu;
7937  fd->startParsing();
7938  if (fd->generateSourceFile() && !g_useOutputTemplate) // sources need to be shown in the output
7939  {
7940  msg("Generating code for file %s...\n",fd->docName().data());
7941  fd->writeSource(*g_outputList,FALSE,filesInSameTu);
7942 
7943  }
7944  else if (!fd->isReference() && Doxygen::parseSourcesNeeded)
7945  // we needed to parse the sources even if we do not show them
7946  {
7947  msg("Parsing code for file %s...\n",fd->docName().data());
7948  fd->parseSource(FALSE,filesInSameTu);
7949  }
7950  fd->finishParsing();
7951  }
7952  }
7953  }
7954  }
7955 }
7956 
7957 //----------------------------------------------------------------------------
7958 
7959 static void generateFileDocs()
7960 {
7961  if (documentedHtmlFiles==0) return;
7962 
7963  if (Doxygen::inputNameList->count()>0)
7964  {
7965  FileNameListIterator fnli(*Doxygen::inputNameList);
7966  FileName *fn;
7967  for (fnli.toFirst();(fn=fnli.current());++fnli)
7968  {
7969  FileNameIterator fni(*fn);
7970  FileDef *fd;
7971  for (fni.toFirst();(fd=fni.current());++fni)
7972  {
7973  bool doc = fd->isLinkableInProject();
7974  if (doc)
7975  {
7976  msg("Generating docs for file %s...\n",fd->docName().data());
7977  fd->writeDocumentation(*g_outputList);
7978  }
7979  }
7980  }
7981  }
7982 }
7983 
7984 //----------------------------------------------------------------------------
7985 
7986 static void addSourceReferences()
7987 {
7988  // add source references for class definitions
7989  ClassSDict::Iterator cli(*Doxygen::classSDict);
7990  ClassDef *cd=0;
7991  for (cli.toFirst();(cd=cli.current());++cli)
7992  {
7993  FileDef *fd=cd->getBodyDef();
7994  if (fd && cd->isLinkableInProject() && cd->getStartBodyLine()!=-1)
7995  {
7996  fd->addSourceRef(cd->getStartBodyLine(),cd,0);
7997  }
7998  }
7999  // add source references for namespace definitions
8000  NamespaceSDict::Iterator nli(*Doxygen::namespaceSDict);
8001  NamespaceDef *nd=0;
8002  for (nli.toFirst();(nd=nli.current());++nli)
8003  {
8004  FileDef *fd=nd->getBodyDef();
8005  if (fd && nd->isLinkableInProject() && nd->getStartBodyLine()!=-1)
8006  {
8007  fd->addSourceRef(nd->getStartBodyLine(),nd,0);
8008  }
8009  }
8010 
8011  // add source references for member names
8012  MemberNameSDict::Iterator mnli(*Doxygen::memberNameSDict);
8013  MemberName *mn=0;
8014  for (mnli.toFirst();(mn=mnli.current());++mnli)
8015  {
8016  MemberNameIterator mni(*mn);
8017  MemberDef *md=0;
8018  for (mni.toFirst();(md=mni.current());++mni)
8019  {
8020  //printf("class member %s: def=%s body=%d link?=%d\n",
8021  // md->name().data(),
8022  // md->getBodyDef()?md->getBodyDef()->name().data():"<none>",
8023  // md->getStartBodyLine(),md->isLinkableInProject());
8024  FileDef *fd=md->getBodyDef();
8025  if (fd &&
8026  md->getStartBodyLine()!=-1 &&
8027  md->isLinkableInProject() &&
8029  )
8030  {
8031  //printf("Found member `%s' in file `%s' at line `%d' def=%s\n",
8032  // md->name().data(),fd->name().data(),md->getStartBodyLine(),md->getOuterScope()->name().data());
8033  fd->addSourceRef(md->getStartBodyLine(),md->getOuterScope(),md);
8034  }
8035  }
8036  }
8037  MemberNameSDict::Iterator fnli(*Doxygen::functionNameSDict);
8038  for (fnli.toFirst();(mn=fnli.current());++fnli)
8039  {
8040  MemberNameIterator mni(*mn);
8041  MemberDef *md=0;
8042  for (mni.toFirst();(md=mni.current());++mni)
8043  {
8044  FileDef *fd=md->getBodyDef();
8045  //printf("member %s body=[%d,%d] fd=%p link=%d parseSources=%d\n",
8046  // md->name().data(),
8047  // md->getStartBodyLine(),md->getEndBodyLine(),fd,
8048  // md->isLinkableInProject(),
8049  // Doxygen::parseSourcesNeeded);
8050  if (fd &&
8051  md->getStartBodyLine()!=-1 &&
8052  md->isLinkableInProject() &&
8054  )
8055  {
8056  //printf("Found member `%s' in file `%s' at line `%d' def=%s\n",
8057  // md->name().data(),fd->name().data(),md->getStartBodyLine(),md->getOuterScope()->name().data());
8058  fd->addSourceRef(md->getStartBodyLine(),md->getOuterScope(),md);
8059  }
8060  }
8061  }
8062 }
8063 
8064 //----------------------------------------------------------------------------
8065 
8066 static void sortMemberLists()
8067 {
8068  // sort class member lists
8069  ClassSDict::Iterator cli(*Doxygen::classSDict);
8070  ClassDef *cd=0;
8071  for (cli.toFirst();(cd=cli.current());++cli)
8072  {
8073  cd->sortMemberLists();
8074  }
8075 
8076  // sort namespace member lists
8077  NamespaceSDict::Iterator nli(*Doxygen::namespaceSDict);
8078  NamespaceDef *nd=0;
8079  for (nli.toFirst();(nd=nli.current());++nli)
8080  {
8081  nd->sortMemberLists();
8082  }
8083 
8084  // sort file member lists
8085  FileNameListIterator fnli(*Doxygen::inputNameList);
8086  FileName *fn;
8087  for (;(fn=fnli.current());++fnli)
8088  {
8089  FileNameIterator fni(*fn);
8090  FileDef *fd;
8091  for (;(fd=fni.current());++fni)
8092  {
8093  fd->sortMemberLists();
8094  }
8095  }
8096 
8097  // sort group member lists
8098  GroupSDict::Iterator gli(*Doxygen::groupSDict);
8099  GroupDef *gd;
8100  for (gli.toFirst();(gd=gli.current());++gli)
8101  {
8102  gd->sortMemberLists();
8103  }
8104 }
8105 
8106 //----------------------------------------------------------------------------
8107 // generate the documentation of all classes
8108 
8109 static void generateClassList(ClassSDict &classSDict)
8110 {
8111  ClassSDict::Iterator cli(classSDict);
8112  for ( ; cli.current() ; ++cli )
8113  {
8114  ClassDef *cd=cli.current();
8115 
8116  //printf("cd=%s getOuterScope=%p global=%p\n",cd->name().data(),cd->getOuterScope(),Doxygen::globalScope);
8117  if (cd &&
8118  (cd->getOuterScope()==0 || // <-- should not happen, but can if we read an old tag file
8119  cd->getOuterScope()==Doxygen::globalScope // only look at global classes
8120  ) && !cd->isHidden() && !cd->isEmbeddedInOuterScope()
8121  )
8122  {
8123  // skip external references, anonymous compounds and
8124  // template instances
8125  if ( cd->isLinkableInProject() && cd->templateMaster()==0)
8126  {
8127  msg("Generating docs for compound %s...\n",cd->name().data());
8128 
8129  cd->writeDocumentation(*g_outputList);
8130  cd->writeMemberList(*g_outputList);
8131  }
8132  // even for undocumented classes, the inner classes can be documented.
8133  cd->writeDocumentationForInnerClasses(*g_outputList);
8134  }
8135  }
8136 }
8137 
8138 static void generateClassDocs()
8139 {
8140  generateClassList(*Doxygen::classSDict);
8141  generateClassList(*Doxygen::hiddenClasses);
8142 }
8143 
8144 //----------------------------------------------------------------------------
8145 
8147 {
8148  MemberNameSDict::Iterator mnli(*Doxygen::memberNameSDict);
8149  MemberName *mn;
8150  //int count=0;
8151  for (;(mn=mnli.current());++mnli)
8152  {
8153  MemberNameIterator mni(*mn);
8154  MemberDef *md;
8155  for (;(md=mni.current());++mni)
8156  {
8157  //printf("%04d Member `%s'\n",count++,md->name().data());
8158  if (md->documentation().isEmpty() && md->briefDescription().isEmpty())
8159  { // no documentation yet
8160  MemberDef *bmd = md->reimplements();
8161  while (bmd && bmd->documentation().isEmpty() &&
8162  bmd->briefDescription().isEmpty()
8163  )
8164  { // search up the inheritance tree for a documentation member
8165  //printf("bmd=%s class=%s\n",bmd->name().data(),bmd->getClassDef()->name().data());
8166  bmd = bmd->reimplements();
8167  }
8168  if (bmd) // copy the documentation from the reimplemented member
8169  {
8170  md->setInheritsDocsFrom(bmd);
8171  md->setDocumentation(bmd->documentation(),bmd->docFile(),bmd->docLine());
8173  md->setBriefDescription(bmd->briefDescription(),bmd->briefFile(),bmd->briefLine());
8174  md->copyArgumentNames(bmd);
8176  }
8177  }
8178  }
8179  }
8180 }
8181 
8182 //----------------------------------------------------------------------------
8183 
8185 {
8186  // for each file
8187  FileNameListIterator fnli(*Doxygen::inputNameList);
8188  FileName *fn;
8189  for (fnli.toFirst();(fn=fnli.current());++fnli)
8190  {
8191  FileNameIterator fni(*fn);
8192  FileDef *fd;
8193  for (fni.toFirst();(fd=fni.current());++fni)
8194  {
8195  fd->visited=FALSE;
8196  }
8197  }
8198  for (fnli.toFirst();(fn=fnli.current());++fnli)
8199  {
8200  FileNameIterator fni(*fn);
8201  FileDef *fd;
8202  for (fni.toFirst();(fd=fni.current());++fni)
8203  {
8204  fd->combineUsingRelations();
8205  }
8206  }
8207 
8208  // for each namespace
8209  NamespaceSDict::Iterator nli(*Doxygen::namespaceSDict);
8210  NamespaceDef *nd;
8211  for (nli.toFirst() ; (nd=nli.current()) ; ++nli )
8212  {
8213  nd->visited=FALSE;
8214  }
8215  for (nli.toFirst() ; (nd=nli.current()) ; ++nli )
8216  {
8217  nd->combineUsingRelations();
8218  }
8219 }
8220 
8221 //----------------------------------------------------------------------------
8222 
8224 {
8225  // for each class
8226  ClassSDict::Iterator cli(*Doxygen::classSDict);
8227  ClassDef *cd;
8228  for ( ; (cd=cli.current()) ; ++cli )
8229  {
8231  }
8232  // for each file
8233  FileNameListIterator fnli(*Doxygen::inputNameList);
8234  FileName *fn;
8235  for (fnli.toFirst();(fn=fnli.current());++fnli)
8236  {
8237  FileNameIterator fni(*fn);
8238  FileDef *fd;
8239  for (fni.toFirst();(fd=fni.current());++fni)
8240  {
8242  }
8243  }
8244  // for each namespace
8245  NamespaceSDict::Iterator nli(*Doxygen::namespaceSDict);
8246  NamespaceDef *nd;
8247  for ( ; (nd=nli.current()) ; ++nli )
8248  {
8250  }
8251  // for each group
8252  GroupSDict::Iterator gli(*Doxygen::groupSDict);
8253  GroupDef *gd;
8254  for (gli.toFirst();(gd=gli.current());++gli)
8255  {
8257  }
8258 }
8259 
8260 //----------------------------------------------------------------------------
8261 
8263 {
8264  // for each class
8265  ClassSDict::Iterator cli(*Doxygen::classSDict);
8266  ClassDef *cd;
8267  for ( ; (cd=cli.current()) ; ++cli )
8268  {
8270  }
8271  // for each file
8272  FileNameListIterator fnli(*Doxygen::inputNameList);
8273  FileName *fn;
8274  for (fnli.toFirst();(fn=fnli.current());++fnli)
8275  {
8276  FileNameIterator fni(*fn);
8277  FileDef *fd;
8278  for (fni.toFirst();(fd=fni.current());++fni)
8279  {
8281  }
8282  }
8283  // for each namespace
8284  NamespaceSDict::Iterator nli(*Doxygen::namespaceSDict);
8285  NamespaceDef *nd;
8286  for ( ; (nd=nli.current()) ; ++nli )
8287  {
8289  }
8290  // for each group
8291  GroupSDict::Iterator gli(*Doxygen::groupSDict);
8292  GroupDef *gd;
8293  for (gli.toFirst();(gd=gli.current());++gli)
8294  {
8296  }
8297 }
8298 
8299 //----------------------------------------------------------------------------
8300 
8302 {
8303  // for each class
8304  ClassSDict::Iterator cli(*Doxygen::classSDict);
8305  ClassDef *cd;
8306  for ( ; (cd=cli.current()) ; ++cli )
8307  {
8309  }
8310  // for each file
8311  FileNameListIterator fnli(*Doxygen::inputNameList);
8312  FileName *fn;
8313  for (fnli.toFirst();(fn=fnli.current());++fnli)
8314  {
8315  FileNameIterator fni(*fn);
8316  FileDef *fd;
8317  for (fni.toFirst();(fd=fni.current());++fni)
8318  {
8320  }
8321  }
8322  // for each namespace
8323  NamespaceSDict::Iterator nli(*Doxygen::namespaceSDict);
8324  NamespaceDef *nd;
8325  for ( ; (nd=nli.current()) ; ++nli )
8326  {
8328  }
8329  // for each group
8330  GroupSDict::Iterator gli(*Doxygen::groupSDict);
8331  GroupDef *gd;
8332  for (gli.toFirst();(gd=gli.current());++gli)
8333  {
8335  }
8336  // for each page
8337  PageSDict::Iterator pdi(*Doxygen::pageSDict);
8338  PageDef *pd=0;
8339  for (pdi.toFirst();(pd=pdi.current());++pdi)
8340  {
8342  }
8343  if (Doxygen::mainPage) Doxygen::mainPage->findSectionsInDocumentation();
8344 }
8345 
8347 {
8348  // remove all references to classes from the cache
8349  // as there can be new template instances in the inheritance path
8350  // to this class. Optimization: only remove those classes that
8351  // have inheritance instances as direct or indirect sub classes.
8352  QCacheIterator<LookupInfo> ci(*Doxygen::lookupCache);
8353  LookupInfo *li=0;
8354  for (ci.toFirst();(li=ci.current());++ci)
8355  {
8356  if (li->classDef)
8357  {
8358  Doxygen::lookupCache->remove(ci.currentKey());
8359  }
8360  }
8361  // remove all cached typedef resolutions whose target is a
8362  // template class as this may now be a template instance
8363  MemberNameSDict::Iterator fnli(*Doxygen::functionNameSDict);
8364  MemberName *fn;
8365  for (;(fn=fnli.current());++fnli) // for each global function name
8366  {
8367  MemberNameIterator fni(*fn);
8368  MemberDef *fmd;
8369  for (;(fmd=fni.current());++fni) // for each function with that name
8370  {
8371  if (fmd->isTypedefValCached())
8372  {
8373  ClassDef *cd = fmd->getCachedTypedefVal();
8374  if (cd->isTemplate()) fmd->invalidateTypedefValCache();
8375  }
8376  }
8377  }
8378  MemberNameSDict::Iterator mnli(*Doxygen::memberNameSDict);
8379  for (;(fn=mnli.current());++mnli) // for each class method name
8380  {
8381  MemberNameIterator mni(*fn);
8382  MemberDef *fmd;
8383  for (;(fmd=mni.current());++mni) // for each function with that name
8384  {
8385  if (fmd->isTypedefValCached())
8386  {
8387  ClassDef *cd = fmd->getCachedTypedefVal();
8388  if (cd->isTemplate()) fmd->invalidateTypedefValCache();
8389  }
8390  }
8391  }
8392 }
8393 
8394 //----------------------------------------------------------------------------
8395 
8397 {
8398  // Remove all unresolved references to classes from the cache.
8399  // This is needed before resolving the inheritance relations, since
8400  // it would otherwise not find the inheritance relation
8401  // for C in the example below, as B::I was already found to be unresolvable
8402  // (which is correct if you igore the inheritance relation between A and B).
8403  //
8404  // class A { class I {} };
8405  // class B : public A {};
8406  // class C : public B::I {};
8407  //
8408  QCacheIterator<LookupInfo> ci(*Doxygen::lookupCache);
8409  LookupInfo *li=0;
8410  for (ci.toFirst();(li=ci.current());++ci)
8411  {
8412  if (li->classDef==0 && li->typeDef==0)
8413  {
8414  Doxygen::lookupCache->remove(ci.currentKey());
8415  }
8416  }
8417 
8418  MemberNameSDict::Iterator fnli(*Doxygen::functionNameSDict);
8419  MemberName *fn;
8420  for (;(fn=fnli.current());++fnli) // for each global function name
8421  {
8422  MemberNameIterator fni(*fn);
8423  MemberDef *fmd;
8424  for (;(fmd=fni.current());++fni) // for each function with that name
8425  {
8427  }
8428  }
8429  MemberNameSDict::Iterator mnli(*Doxygen::memberNameSDict);
8430  for (;(fn=mnli.current());++mnli) // for each class method name
8431  {
8432  MemberNameIterator mni(*fn);
8433  MemberDef *fmd;
8434  for (;(fmd=mni.current());++mni) // for each function with that name
8435  {
8437  }
8438  }
8439 
8440 }
8441 
8442 //----------------------------------------------------------------------------
8443 
8444 static void findDefineDocumentation(EntryNav *rootNav)
8445 {
8446  if ((rootNav->section()==Entry::DEFINEDOC_SEC ||
8447  rootNav->section()==Entry::DEFINE_SEC) && !rootNav->name().isEmpty()
8448  )
8449  {
8450  rootNav->loadEntry(g_storage);
8451  Entry *root = rootNav->entry();
8452 
8453  //printf("found define `%s' `%s' brief=`%s' doc=`%s'\n",
8454  // root->name.data(),root->args.data(),root->brief.data(),root->doc.data());
8455 
8456  if (rootNav->tagInfo() && !root->name.isEmpty()) // define read from a tag file
8457  {
8458  MemberDef *md=new MemberDef(rootNav->tagInfo()->tagName,1,1,
8459  "#define",root->name,root->args,0,
8461  md->setTagInfo(rootNav->tagInfo());
8462  md->setLanguage(root->lang);
8463  //printf("Searching for `%s' fd=%p\n",filePathName.data(),fd);
8464  md->setFileDef(rootNav->parent()->fileDef());
8465  //printf("Adding member=%s\n",md->name().data());
8466  MemberName *mn;
8467  if ((mn=Doxygen::functionNameSDict->find(root->name)))
8468  {
8469  mn->append(md);
8470  }
8471  else
8472  {
8473  mn = new MemberName(root->name);
8474  mn->append(md);
8475  Doxygen::functionNameSDict->append(root->name,mn);
8476  }
8477  }
8478  MemberName *mn=Doxygen::functionNameSDict->find(root->name);
8479  if (mn)
8480  {
8481  MemberNameIterator mni(*mn);
8482  MemberDef *md;
8483  int count=0;
8484  for (;(md=mni.current());++mni)
8485  {
8486  if (md->memberType()==MemberType_Define) count++;
8487  }
8488  if (count==1)
8489  {
8490  for (mni.toFirst();(md=mni.current());++mni)
8491  {
8492  if (md->memberType()==MemberType_Define)
8493  {
8494  md->setDocumentation(root->doc,root->docFile,root->docLine);
8495  md->setDocsForDefinition(!root->proto);
8496  md->setBriefDescription(root->brief,root->briefFile,root->briefLine);
8497  if (md->inbodyDocumentation().isEmpty())
8498  {
8499  md->setInbodyDocumentation(root->inbodyDocs,root->inbodyFile,root->inbodyLine);
8500  }
8501  md->setBodySegment(root->bodyLine,root->endBodyLine);
8502  md->setBodyDef(rootNav->fileDef());
8503  md->addSectionsToDefinition(root->anchors);
8504  md->setMaxInitLines(root->initLines);
8505  md->setRefItems(root->sli);
8506  if (root->mGrpId!=-1) md->setMemberGroupId(root->mGrpId);
8507  addMemberToGroups(root,md);
8508  }
8509  }
8510  }
8511  else if (count>1 &&
8512  (!root->doc.isEmpty() ||
8513  !root->brief.isEmpty() ||
8514  root->bodyLine!=-1
8515  )
8516  )
8517  // multiple defines don't know where to add docs
8518  // but maybe they are in different files together with their documentation
8519  {
8520  for (mni.toFirst();(md=mni.current());++mni)
8521  {
8522  if (md->memberType()==MemberType_Define)
8523  {
8524  FileDef *fd=md->getFileDef();
8525  if (fd && fd->absFilePath()==root->fileName)
8526  // doc and define in the same file assume they belong together.
8527  {
8528 #if 0
8529  if (md->documentation().isEmpty())
8530 #endif
8531  {
8532  md->setDocumentation(root->doc,root->docFile,root->docLine);
8533  md->setDocsForDefinition(!root->proto);
8534  }
8535 #if 0
8536  if (md->briefDescription().isEmpty())
8537 #endif
8538  {
8539  md->setBriefDescription(root->brief,root->briefFile,root->briefLine);
8540  }
8541  if (md->inbodyDocumentation().isEmpty())
8542  {
8543  md->setInbodyDocumentation(root->inbodyDocs,root->inbodyFile,root->inbodyLine);
8544  }
8545  md->setBodySegment(root->bodyLine,root->endBodyLine);
8546  md->setBodyDef(rootNav->fileDef());
8547  md->addSectionsToDefinition(root->anchors);
8548  md->setRefItems(root->sli);
8549  md->setLanguage(root->lang);
8550  if (root->mGrpId!=-1) md->setMemberGroupId(root->mGrpId);
8551  addMemberToGroups(root,md);
8552  }
8553  }
8554  }
8555  //warn("define %s found in the following files:\n",root->name.data());
8556  //warn("Cannot determine where to add the documentation found "
8557  // "at line %d of file %s. \n",
8558  // root->startLine,root->fileName.data());
8559  }
8560  }
8561  else if (!root->doc.isEmpty() || !root->brief.isEmpty()) // define not found
8562  {
8563  static bool preEnabled = Config_getBool("ENABLE_PREPROCESSING");
8564  if (preEnabled)
8565  {
8566  warn(root->fileName,root->startLine,
8567  "documentation for unknown define %s found.\n",
8568  root->name.data()
8569  );
8570  }
8571  else
8572  {
8573  warn(root->fileName,root->startLine,
8574  "found documented #define but ignoring it because "
8575  "ENABLE_PREPROCESSING is NO.\n",
8576  root->name.data()
8577  );
8578  }
8579  }
8580 
8581  rootNav->releaseEntry();
8582  }
8584 }
8585 
8586 //----------------------------------------------------------------------------
8587 
8588 static void findDirDocumentation(EntryNav *rootNav)
8589 {
8590  if (rootNav->section() == Entry::DIRDOC_SEC)
8591  {
8592  rootNav->loadEntry(g_storage);
8593  Entry *root = rootNav->entry();
8594 
8595  QCString normalizedName = root->name;
8596  normalizedName = substitute(normalizedName,"\\","/");
8597  //printf("root->docFile=%s normalizedName=%s\n",
8598  // root->docFile.data(),normalizedName.data());
8599  if (root->docFile==normalizedName) // current dir?
8600  {
8601  int lastSlashPos=normalizedName.findRev('/');
8602  if (lastSlashPos!=-1) // strip file name
8603  {
8604  normalizedName=normalizedName.left(lastSlashPos);
8605  }
8606  }
8607  if (normalizedName.at(normalizedName.length()-1)!='/')
8608  {
8609  normalizedName+='/';
8610  }
8611  DirDef *dir,*matchingDir=0;
8612  SDict<DirDef>::Iterator sdi(*Doxygen::directories);
8613  for (sdi.toFirst();(dir=sdi.current());++sdi)
8614  {
8615  //printf("Dir: %s<->%s\n",dir->name().data(),normalizedName.data());
8616  if (dir->name().right(normalizedName.length())==normalizedName)
8617  {
8618  if (matchingDir)
8619  {
8620  warn(root->fileName,root->startLine,
8621  "\\dir command matches multiple directories.\n"
8622  " Applying the command for directory %s\n"
8623  " Ignoring the command for directory %s\n",
8624  matchingDir->name().data(),dir->name().data()
8625  );
8626  }
8627  else
8628  {
8629  matchingDir=dir;
8630  }
8631  }
8632  }
8633  if (matchingDir)
8634  {
8635  //printf("Match for with dir %s\n",matchingDir->name().data());
8636  matchingDir->setBriefDescription(root->brief,root->briefFile,root->briefLine);
8637  matchingDir->setDocumentation(root->doc,root->docFile,root->docLine);
8638  matchingDir->setRefItems(root->sli);
8639  addDirToGroups(root,matchingDir);
8640  }
8641  else
8642  {
8643  warn(root->fileName,root->startLine,"No matching "
8644  "directory found for command \\dir %s\n",normalizedName.data());
8645  }
8646  rootNav->releaseEntry();
8647  }
8649 }
8650 
8651 
8652 //----------------------------------------------------------------------------
8653 // create a (sorted) list of separate documentation pages
8654 
8655 static void buildPageList(EntryNav *rootNav)
8656 {
8657  if (rootNav->section() == Entry::PAGEDOC_SEC)
8658  {
8659  rootNav->loadEntry(g_storage);
8660  Entry *root = rootNav->entry();
8661 
8662  if (!root->name.isEmpty())
8663  {
8664  addRelatedPage(rootNav);
8665  }
8666 
8667  rootNav->releaseEntry();
8668  }
8669  else if (rootNav->section() == Entry::MAINPAGEDOC_SEC)
8670  {
8671  rootNav->loadEntry(g_storage);
8672  Entry *root = rootNav->entry();
8673 
8675  if (title.isEmpty()) title=theTranslator->trMainPage();
8676  //QCString name = Config_getBool("GENERATE_TREEVIEW")?"main":"index";
8677  QCString name = "index";
8678  addRefItem(root->sli,
8679  name,
8680  "page",
8681  name,
8682  title,
8683  0,0
8684  );
8685 
8686  rootNav->releaseEntry();
8687  }
8689 }
8690 
8691 // search for the main page defined in this project
8692 static void findMainPage(EntryNav *rootNav)
8693 {
8694  if (rootNav->section() == Entry::MAINPAGEDOC_SEC)
8695  {
8696  rootNav->loadEntry(g_storage);
8697 
8698  if (Doxygen::mainPage==0 && rootNav->tagInfo()==0)
8699  {
8700  Entry *root = rootNav->entry();
8701  //printf("Found main page! \n======\n%s\n=======\n",root->doc.data());
8703  //QCString indexName=Config_getBool("GENERATE_TREEVIEW")?"main":"index";
8704  QCString indexName="index";
8705  Doxygen::mainPage = new PageDef(root->docFile,root->docLine,
8706  indexName, root->brief+root->doc+root->inbodyDocs,title);
8707  //setFileNameForSections(root->anchors,"index",Doxygen::mainPage);
8708  Doxygen::mainPage->setBriefDescription(root->brief,root->briefFile,root->briefLine);
8709  Doxygen::mainPage->setFileName(indexName);
8710  Doxygen::mainPage->setShowToc(root->stat);
8711  addPageToContext(Doxygen::mainPage,rootNav);
8712 
8713  SectionInfo *si = Doxygen::sectionDict->find(Doxygen::mainPage->name());
8714  if (si)
8715  {
8716  if (si->lineNr != -1)
8717  {
8718  warn(root->fileName,root->startLine,"multiple use of section label '%s' for main page, (first occurrence: %s, line %d)",Doxygen::mainPage->name().data(),si->fileName.data(),si->lineNr);
8719  }
8720  else
8721  {
8722  warn(root->fileName,root->startLine,"multiple use of section label '%s' for main page, (first occurrence: %s)",Doxygen::mainPage->name().data(),si->fileName.data());
8723  }
8724  }
8725  else
8726  {
8727  // a page name is a label as well! but should no be double either
8728  si=new SectionInfo(
8729  indexName, root->startLine,
8730  Doxygen::mainPage->name(),
8731  Doxygen::mainPage->title(),
8733  0); // level 0
8734  Doxygen::sectionDict->append(indexName,si);
8735  Doxygen::mainPage->addSectionsToDefinition(root->anchors);
8736  }
8737  }
8738  else if (rootNav->tagInfo()==0)
8739  {
8740  Entry *root = rootNav->entry();
8741  warn(root->fileName,root->startLine,
8742  "found more than one \\mainpage comment block! (first occurrence: %s, line %d), Skipping current block!",
8743  Doxygen::mainPage->docFile().data(),Doxygen::mainPage->docLine());
8744  }
8745 
8746  rootNav->releaseEntry();
8747  }
8749 }
8750 
8751 // search for the main page imported via tag files and add only the section labels
8752 static void findMainPageTagFiles(EntryNav *rootNav)
8753 {
8754  if (rootNav->section() == Entry::MAINPAGEDOC_SEC)
8755  {
8756  rootNav->loadEntry(g_storage);
8757 
8758  if (Doxygen::mainPage && rootNav->tagInfo())
8759  {
8760  Entry *root = rootNav->entry();
8761  Doxygen::mainPage->addSectionsToDefinition(root->anchors);
8762  }
8763  }
8765 }
8766 
8767 static void computePageRelations(EntryNav *rootNav)
8768 {
8769  if ((rootNav->section()==Entry::PAGEDOC_SEC ||
8770  rootNav->section()==Entry::MAINPAGEDOC_SEC
8771  )
8772  && !rootNav->name().isEmpty()
8773  )
8774  {
8775  rootNav->loadEntry(g_storage);
8776  Entry *root = rootNav->entry();
8777 
8778  PageDef *pd = root->section==Entry::PAGEDOC_SEC ?
8779  Doxygen::pageSDict->find(root->name) :
8781  if (pd)
8782  {
8783  QListIterator<BaseInfo> bii(*root->extends);
8784  BaseInfo *bi;
8785  for (bii.toFirst();(bi=bii.current());++bii)
8786  {
8787  PageDef *subPd = Doxygen::pageSDict->find(bi->name);
8788  if (subPd)
8789  {
8790  pd->addInnerCompound(subPd);
8791  //printf("*** Added subpage relation: %s->%s\n",
8792  // pd->name().data(),subPd->name().data());
8793  }
8794  }
8795  }
8796 
8797  rootNav->releaseEntry();
8798  }
8800 }
8801 
8802 static void checkPageRelations()
8803 {
8804  PageSDict::Iterator pdi(*Doxygen::pageSDict);
8805  PageDef *pd=0;
8806  for (pdi.toFirst();(pd=pdi.current());++pdi)
8807  {
8808  Definition *ppd = pd->getOuterScope();
8809  while (ppd)
8810  {
8811  if (ppd==pd)
8812  {
8813  err("page defined at line %d of file %s with label %s is a subpage "
8814  "of itself! Please remove this cyclic dependency.\n",
8815  pd->docLine(),pd->docFile().data(),pd->name().data());
8816  exit(1);
8817  }
8818  ppd=ppd->getOuterScope();
8819  }
8820  }
8821 }
8822 
8823 //----------------------------------------------------------------------------
8824 
8826 {
8827  SDict<SectionInfo>::Iterator sdi(*Doxygen::sectionDict);
8828  SectionInfo *si;
8829  for (;(si=sdi.current());++sdi)
8830  {
8831  //printf("si->label=`%s' si->definition=%s si->fileName=`%s'\n",
8832  // si->label.data(),si->definition?si->definition->name().data():"<none>",
8833  // si->fileName.data());
8834  PageDef *pd=0;
8835 
8836  // hack: the items of a todo/test/bug/deprecated list are all fragments from
8837  // different files, so the resulting section's all have the wrong file
8838  // name (not from the todo/test/bug/deprecated list, but from the file in
8839  // which they are defined). We correct this here by looking at the
8840  // generated section labels!
8841  QDictIterator<RefList> rli(*Doxygen::xrefLists);
8842  RefList *rl;
8843  for (rli.toFirst();(rl=rli.current());++rli)
8844  {
8845  QCString label="_"+rl->listName(); // "_todo", "_test", ...
8846  if (si->label.left(label.length())==label)
8847  {
8848  si->fileName=rl->listName();
8849  si->generated=TRUE;
8850  break;
8851  }
8852  }
8853 
8854  //printf("start: si->label=%s si->fileName=%s\n",si->label.data(),si->fileName.data());
8855  if (!si->generated)
8856  {
8857  // if this section is in a page and the page is in a group, then we
8858  // have to adjust the link file name to point to the group.
8859  if (!si->fileName.isEmpty() &&
8860  (pd=Doxygen::pageSDict->find(si->fileName)) &&
8861  pd->getGroupDef())
8862  {
8863  si->fileName=pd->getGroupDef()->getOutputFileBase().copy();
8864  }
8865 
8866  if (si->definition)
8867  {
8868  // TODO: there should be one function in Definition that returns
8869  // the file to link to, so we can avoid the following tests.
8870  GroupDef *gd=0;
8872  {
8873  gd = ((MemberDef *)si->definition)->getGroupDef();
8874  }
8875 
8876  if (gd)
8877  {
8878  si->fileName=gd->getOutputFileBase().copy();
8879  }
8880  else
8881  {
8882  //si->fileName=si->definition->getOutputFileBase().copy();
8883  //printf("Setting si->fileName to %s\n",si->fileName.data());
8884  }
8885  }
8886  }
8887  //printf("end: si->label=%s si->fileName=%s\n",si->label.data(),si->fileName.data());
8888  }
8889 }
8890 
8891 
8892 
8893 //----------------------------------------------------------------------------
8894 // generate all separate documentation pages
8895 
8896 
8897 static void generatePageDocs()
8898 {
8899  //printf("documentedPages=%d real=%d\n",documentedPages,Doxygen::pageSDict->count());
8900  if (documentedPages==0) return;
8901  PageSDict::Iterator pdi(*Doxygen::pageSDict);
8902  PageDef *pd=0;
8903  for (pdi.toFirst();(pd=pdi.current());++pdi)
8904  {
8905  if (!pd->getGroupDef() && !pd->isReference())
8906  {
8907  msg("Generating docs for page %s...\n",pd->name().data());
8909  pd->writeDocumentation(*g_outputList);
8910  Doxygen::insideMainPage=FALSE;
8911  }
8912  }
8913 }
8914 
8915 //----------------------------------------------------------------------------
8916 // create a (sorted) list & dictionary of example pages
8917 
8918 static void buildExampleList(EntryNav *rootNav)
8919 {
8920  if (rootNav->section()==Entry::EXAMPLE_SEC && !rootNav->name().isEmpty())
8921  {
8922  rootNav->loadEntry(g_storage);
8923  Entry *root = rootNav->entry();
8924 
8925  if (Doxygen::exampleSDict->find(root->name))
8926  {
8927  warn(root->fileName,root->startLine,
8928  "Example %s was already documented. Ignoring "
8929  "documentation found here.",
8930  root->name.data()
8931  );
8932  }
8933  else
8934  {
8935  PageDef *pd=new PageDef(root->fileName,root->startLine,
8936  root->name,root->brief+root->doc+root->inbodyDocs,root->args);
8937  pd->setBriefDescription(root->brief,root->briefFile,root->briefLine);
8938  pd->setFileName(convertNameToFile(pd->name()+"-example",FALSE,TRUE));
8939  pd->addSectionsToDefinition(root->anchors);
8940  pd->setLanguage(root->lang);
8941  //pi->addSections(root->anchors);
8942 
8943  Doxygen::exampleSDict->inSort(root->name,pd);
8944  //we don't add example to groups
8945  //addExampleToGroups(root,pd);
8946  }
8947 
8948  rootNav->releaseEntry();
8949  }
8951 }
8952 
8953 //----------------------------------------------------------------------------
8954 // prints the Entry tree (for debugging)
8955 
8956 void printNavTree(EntryNav *rootNav,int indent)
8957 {
8958  QCString indentStr;
8959  indentStr.fill(' ',indent);
8960  msg("%s%s (sec=0x%x)\n",
8961  indentStr.isEmpty()?"":indentStr.data(),
8962  rootNav->name().isEmpty()?"<empty>":rootNav->name().data(),
8963  rootNav->section());
8964  if (rootNav->children())
8965  {
8966  EntryNavListIterator eli(*rootNav->children());
8967  for (;eli.current();++eli) printNavTree(eli.current(),indent+2);
8968  }
8969 }
8970 
8971 
8972 //----------------------------------------------------------------------------
8973 // generate the example documentation
8974 
8975 static void generateExampleDocs()
8976 {
8977  g_outputList->disable(OutputGenerator::Man);
8978  PageSDict::Iterator pdi(*Doxygen::exampleSDict);
8979  PageDef *pd=0;
8980  for (pdi.toFirst();(pd=pdi.current());++pdi)
8981  {
8982  msg("Generating docs for example %s...\n",pd->name().data());
8984  QCString n=pd->getOutputFileBase();
8985  startFile(*g_outputList,n,n,pd->name());
8986  startTitle(*g_outputList,n);
8987  g_outputList->docify(pd->name());
8988  endTitle(*g_outputList,n,0);
8989  g_outputList->startContents();
8990  g_outputList->generateDoc(pd->docFile(), // file
8991  pd->docLine(), // startLine
8992  pd, // context
8993  0, // memberDef
8994  pd->documentation()+"\n\n\\include "+pd->name(), // docs
8995  TRUE, // index words
8996  TRUE, // is example
8997  pd->name()
8998  );
8999  endFile(*g_outputList); // contains g_outputList->endContents()
9000  }
9001  g_outputList->enable(OutputGenerator::Man);
9002 }
9003 
9004 //----------------------------------------------------------------------------
9005 // generate module pages
9006 
9007 static void generateGroupDocs()
9008 {
9009  GroupSDict::Iterator gli(*Doxygen::groupSDict);
9010  GroupDef *gd;
9011  for (gli.toFirst();(gd=gli.current());++gli)
9012  {
9013  if (!gd->isReference())
9014  {
9015  gd->writeDocumentation(*g_outputList);
9016  }
9017  }
9018 }
9019 
9020 //----------------------------------------------------------------------------
9021 
9022 //static void generatePackageDocs()
9023 //{
9024 // writePackageIndex(*g_outputList);
9025 //
9026 // if (Doxygen::packageDict.count()>0)
9027 // {
9028 // PackageSDict::Iterator pdi(Doxygen::packageDict);
9029 // PackageDef *pd;
9030 // for (pdi.toFirst();(pd=pdi.current());++pdi)
9031 // {
9032 // pd->writeDocumentation(*g_outputList);
9033 // }
9034 // }
9035 //}
9036 
9037 //----------------------------------------------------------------------------
9038 // generate module pages
9039 
9041 {
9042  //writeNamespaceIndex(*g_outputList);
9043 
9044  NamespaceSDict::Iterator nli(*Doxygen::namespaceSDict);
9045  NamespaceDef *nd;
9046  // for each namespace...
9047  for (;(nd=nli.current());++nli)
9048  {
9049 
9050  if (nd->isLinkableInProject())
9051  {
9052  msg("Generating docs for namespace %s\n",nd->name().data());
9053  nd->writeDocumentation(*g_outputList);
9054  }
9055 
9056  // for each class in the namespace...
9058  ClassDef *cd;
9059  for ( ; (cd=cli.current()) ; ++cli )
9060  {
9061  if ( ( cd->isLinkableInProject() &&
9062  cd->templateMaster()==0
9063  ) // skip external references, anonymous compounds and
9064  // template instances and nested classes
9065  && !cd->isHidden() && !cd->isEmbeddedInOuterScope()
9066  )
9067  {
9068  msg("Generating docs for compound %s...\n",cd->name().data());
9069 
9070  cd->writeDocumentation(*g_outputList);
9071  cd->writeMemberList(*g_outputList);
9072  }
9073  cd->writeDocumentationForInnerClasses(*g_outputList);
9074  }
9075  }
9076 }
9077 
9078 #if defined(_WIN32)
9079 static QCString fixSlashes(QCString &s)
9080 {
9081  QCString result;
9082  uint i;
9083  for (i=0;i<s.length();i++)
9084  {
9085  switch(s.at(i))
9086  {
9087  case '/':
9088  case '\\':
9089  result+="\\\\";
9090  break;
9091  default:
9092  result+=s.at(i);
9093  }
9094  }
9095  return result;
9096 }
9097 #endif
9098 
9099 
9100 //----------------------------------------------------------------------------
9101 
9102 /*! Generate a template version of the configuration file.
9103  * If the \a shortList parameter is TRUE a configuration file without
9104  * comments will be generated.
9105  */
9106 static void generateConfigFile(const char *configFile,bool shortList,
9107  bool updateOnly=FALSE)
9108 {
9109  QFile f;
9110  bool fileOpened=openOutputFile(configFile,f);
9111  bool writeToStdout=(configFile[0]=='-' && configFile[1]=='\0');
9112  if (fileOpened)
9113  {
9114  FTextStream t(&f);
9115  Config::instance()->writeTemplate(t,shortList,updateOnly);
9116  if (!writeToStdout)
9117  {
9118  if (!updateOnly)
9119  {
9120  msg("\n\nConfiguration file `%s' created.\n\n",configFile);
9121  msg("Now edit the configuration file and enter\n\n");
9122  if (qstrcmp(configFile,"Doxyfile") || qstrcmp(configFile,"doxyfile"))
9123  msg(" doxygen %s\n\n",configFile);
9124  else
9125  msg(" doxygen\n\n");
9126  msg("to generate the documentation for your project\n\n");
9127  }
9128  else
9129  {
9130  msg("\n\nConfiguration file `%s' updated.\n\n",configFile);
9131  }
9132  }
9133  }
9134  else
9135  {
9136  err("Cannot open file %s for writing\n",configFile);
9137  exit(1);
9138  }
9139 }
9140 
9141 //----------------------------------------------------------------------------
9142 // read and parse a tag file
9143 
9144 //static bool readLineFromFile(QFile &f,QCString &s)
9145 //{
9146 // char c=0;
9147 // s.resize(0);
9148 // while (!f.atEnd() && (c=f.getch())!='\n') s+=c;
9149 // return f.atEnd();
9150 //}
9151 
9152 //----------------------------------------------------------------------------
9153 
9154 static void readTagFile(Entry *root,const char *tl)
9155 {
9156  QCString tagLine = tl;
9158  QCString destName;
9159  int eqPos = tagLine.find('=');
9160  if (eqPos!=-1) // tag command contains a destination
9161  {
9162  fileName = tagLine.left(eqPos).stripWhiteSpace();
9163  destName = tagLine.right(tagLine.length()-eqPos-1).stripWhiteSpace();
9164  QFileInfo fi(fileName);
9165  Doxygen::tagDestinationDict.insert(fi.absFilePath().utf8(),new QCString(destName));
9166  //printf("insert tagDestination %s->%s\n",fi.fileName().data(),destName.data());
9167  }
9168  else
9169  {
9170  fileName = tagLine;
9171  }
9172 
9173  QFileInfo fi(fileName);
9174  if (!fi.exists() || !fi.isFile())
9175  {
9176  err("Tag file `%s' does not exist or is not a file. Skipping it...\n",
9177  fileName.data());
9178  return;
9179  }
9180 
9181  if (!destName.isEmpty())
9182  msg("Reading tag file `%s', location `%s'...\n",fileName.data(),destName.data());
9183  else
9184  msg("Reading tag file `%s'...\n",fileName.data());
9185 
9186  parseTagFile(root,fi.absFilePath().utf8());
9187 }
9188 
9189 //----------------------------------------------------------------------------
9190 static void copyLatexStyleSheet()
9191 {
9192  QStrList latexExtraStyleSheet = Config_getList("LATEX_EXTRA_STYLESHEET");
9193  for (uint i=0; i<latexExtraStyleSheet.count(); ++i)
9194  {
9195  QCString fileName(latexExtraStyleSheet.at(i));
9196  if (!fileName.isEmpty())
9197  {
9198  QFileInfo fi(fileName);
9199  if (!fi.exists())
9200  {
9201  err("Style sheet '%s' specified by LATEX_EXTRA_STYLESHEET does not exist!\n",fileName.data());
9202  }
9203  else
9204  {
9205  QCString destFileName = Config_getString("LATEX_OUTPUT")+"/"+fi.fileName().data();
9207  {
9208  destFileName += latexStyleExtension;
9209  }
9210  copyFile(fileName, destFileName);
9211  }
9212  }
9213  }
9214 }
9215 
9216 //----------------------------------------------------------------------------
9217 static void copyStyleSheet()
9218 {
9219  QCString &htmlStyleSheet = Config_getString("HTML_STYLESHEET");
9220  if (!htmlStyleSheet.isEmpty())
9221  {
9222  QFileInfo fi(htmlStyleSheet);
9223  if (!fi.exists())
9224  {
9225  err("Style sheet '%s' specified by HTML_STYLESHEET does not exist!\n",htmlStyleSheet.data());
9226  htmlStyleSheet.resize(0); // revert to the default
9227  }
9228  else
9229  {
9230  QCString destFileName = Config_getString("HTML_OUTPUT")+"/"+fi.fileName().data();
9231  copyFile(htmlStyleSheet,destFileName);
9232  }
9233  }
9234  QStrList htmlExtraStyleSheet = Config_getList("HTML_EXTRA_STYLESHEET");
9235  for (uint i=0; i<htmlExtraStyleSheet.count(); ++i)
9236  {
9237  QCString fileName(htmlExtraStyleSheet.at(i));
9238  if (!fileName.isEmpty())
9239  {
9240  QFileInfo fi(fileName);
9241  if (!fi.exists())
9242  {
9243  err("Style sheet '%s' specified by HTML_EXTRA_STYLESHEET does not exist!\n",fileName.data());
9244  }
9245  else if (fi.fileName()=="doxygen.css" || fi.fileName()=="tabs.css" || fi.fileName()=="navtree.css")
9246  {
9247  err("Style sheet %s specified by HTML_EXTRA_STYLESHEET is already a built-in stylesheet. Please use a different name\n",fi.fileName().data());
9248  }
9249  else
9250  {
9251  QCString destFileName = Config_getString("HTML_OUTPUT")+"/"+fi.fileName().data();
9252  copyFile(fileName, destFileName);
9253  }
9254  }
9255  }
9256 }
9257 
9258 static void copyLogo()
9259 {
9260  QCString &projectLogo = Config_getString("PROJECT_LOGO");
9261  if (!projectLogo.isEmpty())
9262  {
9263  QFileInfo fi(projectLogo);
9264  if (!fi.exists())
9265  {
9266  err("Project logo '%s' specified by PROJECT_LOGO does not exist!\n",projectLogo.data());
9267  projectLogo.resize(0); // revert to the default
9268  }
9269  else
9270  {
9271  QCString destFileName = Config_getString("HTML_OUTPUT")+"/"+fi.fileName().data();
9272  copyFile(projectLogo,destFileName);
9273  Doxygen::indexList->addImageFile(fi.fileName().data());
9274  }
9275  }
9276 }
9277 
9278 static void copyExtraFiles(const QCString& filesOption,const QCString &outputOption)
9279 {
9280  QStrList files = Config_getList(filesOption);
9281  uint i;
9282  for (i=0; i<files.count(); ++i)
9283  {
9284  QCString fileName(files.at(i));
9285 
9286  if (!fileName.isEmpty())
9287  {
9288  QFileInfo fi(fileName);
9289  if (!fi.exists())
9290  {
9291  err("Extra file '%s' specified in " + filesOption + " does not exist!\n", fileName.data());
9292  }
9293  else
9294  {
9295  QCString destFileName = Config_getString(outputOption)+"/"+fi.fileName().data();
9296  Doxygen::indexList->addImageFile(fi.fileName().utf8());
9297  copyFile(fileName, destFileName);
9298  }
9299  }
9300  }
9301 }
9302 
9303 //----------------------------------------------------------------------------
9304 
9306 {
9308  QCString extension;
9309  int sep = fileName.findRev('/');
9310  int ei = fileName.findRev('.');
9311  if (ei!=-1 && (sep==-1 || ei>sep)) // matches dir/file.ext but not dir.1/file
9312  {
9313  extension=fileName.right(fileName.length()-ei);
9314  }
9315  else
9316  {
9317  extension = ".no_extension";
9318  }
9319 
9320  return Doxygen::parserManager->getParser(extension);
9321 }
9322 
9324  Entry *root,EntryNav *rootNav,FileDef *fd,const char *fn,
9325  bool sameTu,QStrList &filesInSameTu)
9326 {
9327 #if USE_LIBCLANG
9328  static bool clangAssistedParsing = Config_getBool("CLANG_ASSISTED_PARSING");
9329 #else
9330  static bool clangAssistedParsing = FALSE;
9331 #endif
9333  QCString extension;
9334  int ei = fileName.findRev('.');
9335  if (ei!=-1)
9336  {
9337  extension=fileName.right(fileName.length()-ei);
9338  }
9339  else
9340  {
9341  extension = ".no_extension";
9342  }
9343 
9344  QFileInfo fi(fileName);
9345  BufStr preBuf(fi.size()+4096);
9346 
9347  if (Config_getBool("ENABLE_PREPROCESSING") &&
9348  parser->needsPreprocessing(extension))
9349  {
9350  BufStr inBuf(fi.size()+4096);
9351  msg("Preprocessing %s...\n",fn);
9352  readInputFile(fileName,inBuf);
9353  preprocessFile(fileName,inBuf,preBuf);
9354  }
9355  else // no preprocessing
9356  {
9357  msg("Reading %s...\n",fn);
9358  readInputFile(fileName,preBuf);
9359  }
9360  if (preBuf.data() && preBuf.curPos()>0 && *(preBuf.data()+preBuf.curPos()-1)!='\n')
9361  {
9362  preBuf.addChar('\n'); // add extra newline to help parser
9363  }
9364 
9365  BufStr convBuf(preBuf.curPos()+1024);
9366 
9367  // convert multi-line C++ comments to C style comments
9368  convertCppComments(&preBuf,&convBuf,fileName);
9369 
9370  convBuf.addChar('\0');
9371 
9372  if (clangAssistedParsing && !sameTu)
9373  {
9374  fd->getAllIncludeFilesRecursively(filesInSameTu);
9375  }
9376 
9377  // use language parse to parse the file
9378  parser->parseInput(fileName,convBuf.data(),root,sameTu,filesInSameTu);
9379 
9380  // store the Entry tree in a file and create an index to
9381  // navigate/load entries
9382  //printf("root->createNavigationIndex for %s\n",fd->name().data());
9383  root->createNavigationIndex(rootNav,g_storage,fd);
9384 }
9385 
9386 //! parse the list of input files
9387 static void parseFiles(Entry *root,EntryNav *rootNav)
9388 {
9389 #if USE_LIBCLANG
9390  static bool clangAssistedParsing = Config_getBool("CLANG_ASSISTED_PARSING");
9391  if (clangAssistedParsing)
9392  {
9393  QDict<void> g_processedFiles(10007);
9394 
9395  // create a dictionary with files to process
9396  QDict<void> g_filesToProcess(10007);
9397  StringListIterator it(g_inputFiles);
9398  QCString *s;
9399  for (;(s=it.current());++it)
9400  {
9401  g_filesToProcess.insert(*s,(void*)0x8);
9402  }
9403 
9404  // process source files (and their include dependencies)
9405  for (it.toFirst();(s=it.current());++it)
9406  {
9407  bool ambig;
9408  FileDef *fd=findFileDef(Doxygen::inputNameDict,s->data(),ambig);
9409  ASSERT(fd!=0);
9410  if (fd->isSource() && !fd->isReference()) // this is a source file
9411  {
9412  QStrList filesInSameTu;
9414  parser->startTranslationUnit(s->data());
9415  parseFile(parser,root,rootNav,fd,s->data(),FALSE,filesInSameTu);
9416  //printf(" got %d extra files in tu\n",filesInSameTu.count());
9417 
9418  // Now process any include files in the same translation unit
9419  // first. When libclang is used this is much more efficient.
9420  char *incFile = filesInSameTu.first();
9421  while (incFile && g_filesToProcess.find(incFile))
9422  {
9423  if (qstrcmp(incFile,s->data()) && !g_processedFiles.find(incFile))
9424  {
9425  FileDef *ifd=findFileDef(Doxygen::inputNameDict,incFile,ambig);
9426  if (ifd && !ifd->isReference())
9427  {
9428  QStrList moreFiles;
9429  //printf(" Processing %s in same translation unit as %s\n",incFile,s->data());
9430  parseFile(parser,root,rootNav,ifd,incFile,TRUE,moreFiles);
9431  g_processedFiles.insert(incFile,(void*)0x8);
9432  }
9433  }
9434  incFile = filesInSameTu.next();
9435  }
9436  parser->finishTranslationUnit();
9437  g_processedFiles.insert(*s,(void*)0x8);
9438  }
9439  }
9440  // process remaining files
9441  for (it.toFirst();(s=it.current());++it)
9442  {
9443  if (!g_processedFiles.find(*s)) // not yet processed
9444  {
9445  bool ambig;
9446  QStrList filesInSameTu;
9447  FileDef *fd=findFileDef(Doxygen::inputNameDict,s->data(),ambig);
9448  ASSERT(fd!=0);
9450  parser->startTranslationUnit(s->data());
9451  parseFile(parser,root,rootNav,fd,s->data(),FALSE,filesInSameTu);
9452  parser->finishTranslationUnit();
9453  g_processedFiles.insert(*s,(void*)0x8);
9454  }
9455  }
9456  }
9457  else // normal pocessing
9458 #endif
9459  {
9460  StringListIterator it(g_inputFiles);
9461  QCString *s;
9462  for (;(s=it.current());++it)
9463  {
9464  bool ambig;
9465  QStrList filesInSameTu;
9466  FileDef *fd=findFileDef(Doxygen::inputNameDict,s->data(),ambig);
9467  ASSERT(fd!=0);
9469  parser->startTranslationUnit(s->data());
9470  parseFile(parser,root,rootNav,fd,s->data(),FALSE,filesInSameTu);
9471  }
9472  }
9473 }
9474 
9475 // resolves a path that may include symlinks, if a recursive symlink is
9476 // found an empty string is returned.
9478 {
9479  int sepPos=0;
9480  int oldPos=0;
9481  QFileInfo fi;
9482  QDict<void> nonSymlinks;
9483  QDict<void> known;
9484  QCString result = path;
9485  QCString oldPrefix = "/";
9486  do
9487  {
9488 #ifdef WIN32
9489  // UNC path, skip server and share name
9490  if (sepPos==0 && (result.left(2)=="//" || result.left(2)=="\\\\"))
9491  sepPos = result.find('/',2);
9492  if (sepPos!=-1)
9493  sepPos = result.find('/',sepPos+1);
9494 #else
9495  sepPos = result.find('/',sepPos+1);
9496 #endif
9497  QCString prefix = sepPos==-1 ? result : result.left(sepPos);
9498  if (nonSymlinks.find(prefix)==0)
9499  {
9500  fi.setFile(prefix);
9501  if (fi.isSymLink())
9502  {
9503  QString target = fi.readLink();
9504  bool isRelative = QFileInfo(target).isRelative();
9505  if (isRelative)
9506  {
9507  target = QDir::cleanDirPath(oldPrefix+"/"+target.data());
9508  }
9509  if (sepPos!=-1)
9510  {
9511  if (fi.isDir() && target.length()>0 && target.at(target.length()-1)!='/')
9512  {
9513  target+='/';
9514  }
9515  target+=result.mid(sepPos);
9516  }
9517  result = QDir::cleanDirPath(target).data();
9518  sepPos = 0;
9519  if (known.find(result)) return QCString(); // recursive symlink!
9520  known.insert(result,(void*)0x8);
9521  if (isRelative)
9522  {
9523  sepPos = oldPos;
9524  }
9525  else // link to absolute path
9526  {
9527  sepPos = 0;
9528  oldPrefix = "/";
9529  }
9530  }
9531  else
9532  {
9533  nonSymlinks.insert(prefix,(void*)0x8);
9534  oldPrefix = prefix;
9535  }
9536  oldPos = sepPos;
9537  }
9538  }
9539  while (sepPos!=-1);
9540  return QDir::cleanDirPath(result).data();
9541 }
9542 
9543 static QDict<void> g_pathsVisited(1009);
9544 
9545 //----------------------------------------------------------------------------
9546 // Read all files matching at least one pattern in `patList' in the
9547 // directory represented by `fi'.
9548 // The directory is read iff the recusiveFlag is set.
9549 // The contents of all files is append to the input string
9550 
9552  FileNameList *fnList,
9553  FileNameDict *fnDict,
9554  StringDict *exclDict,
9555  QStrList *patList,
9556  QStrList *exclPatList,
9557  StringList *resultList,
9558  StringDict *resultDict,
9559  bool errorIfNotExist,
9560  bool recursive,
9561  QDict<void> *killDict,
9562  QDict<void> *paths
9563  )
9564 {
9565  QCString dirName = fi->absFilePath().utf8();
9566  if (paths && paths->find(dirName)==0)
9567  {
9568  paths->insert(dirName,(void*)0x8);
9569  }
9570  if (fi->isSymLink())
9571  {
9572  dirName = resolveSymlink(dirName.data());
9573  if (dirName.isEmpty()) return 0; // recusive symlink
9574  if (g_pathsVisited.find(dirName)) return 0; // already visited path
9575  g_pathsVisited.insert(dirName,(void*)0x8);
9576  }
9577  QDir dir(dirName);
9579  int totalSize=0;
9580  msg("Searching for files in directory %s\n", fi->absFilePath().data());
9581  //printf("killDict=%p count=%d\n",killDict,killDict->count());
9582 
9583  const QFileInfoList *list = dir.entryInfoList();
9584  if (list)
9585  {
9586  QFileInfoListIterator it( *list );
9587  QFileInfo *cfi;
9588 
9589  while ((cfi=it.current()))
9590  {
9591  if (exclDict==0 || exclDict->find(cfi->absFilePath().utf8())==0)
9592  { // file should not be excluded
9593  //printf("killDict->find(%s)\n",cfi->absFilePath().data());
9594  if (!cfi->exists() || !cfi->isReadable())
9595  {
9596  if (errorIfNotExist)
9597  {
9598  warn_uncond("source %s is not a readable file or directory... skipping.\n",cfi->absFilePath().data());
9599  }
9600  }
9601  else if (cfi->isFile() &&
9602  (!Config_getBool("EXCLUDE_SYMLINKS") || !cfi->isSymLink()) &&
9603  (patList==0 || patternMatch(*cfi,patList)) &&
9604  !patternMatch(*cfi,exclPatList) &&
9605  (killDict==0 || killDict->find(cfi->absFilePath().utf8())==0)
9606  )
9607  {
9608  totalSize+=cfi->size()+cfi->absFilePath().length()+4;
9609  QCString name=cfi->fileName().utf8();
9610  //printf("New file %s\n",name.data());
9611  if (fnDict)
9612  {
9613  FileDef *fd=new FileDef(cfi->dirPath().utf8()+"/",name);
9614  FileName *fn=0;
9615  if (!name.isEmpty() && (fn=(*fnDict)[name]))
9616  {
9617  fn->append(fd);
9618  }
9619  else
9620  {
9621  fn = new FileName(cfi->absFilePath().utf8(),name);
9622  fn->append(fd);
9623  if (fnList) fnList->inSort(fn);
9624  fnDict->insert(name,fn);
9625  }
9626  }
9627  QCString *rs=0;
9628  if (resultList || resultDict)
9629  {
9630  rs=new QCString(cfi->absFilePath().utf8());
9631  }
9632  if (resultList) resultList->append(rs);
9633  if (resultDict) resultDict->insert(cfi->absFilePath().utf8(),rs);
9634  if (killDict) killDict->insert(cfi->absFilePath().utf8(),(void *)0x8);
9635  }
9636  else if (recursive &&
9637  (!Config_getBool("EXCLUDE_SYMLINKS") || !cfi->isSymLink()) &&
9638  cfi->isDir() &&
9639  !patternMatch(*cfi,exclPatList) &&
9640  cfi->fileName().at(0)!='.') // skip "." ".." and ".dir"
9641  {
9642  cfi->setFile(cfi->absFilePath());
9643  totalSize+=readDir(cfi,fnList,fnDict,exclDict,
9644  patList,exclPatList,resultList,resultDict,errorIfNotExist,
9645  recursive,killDict,paths);
9646  }
9647  }
9648  ++it;
9649  }
9650  }
9651  return totalSize;
9652 }
9653 
9654 
9655 //----------------------------------------------------------------------------
9656 // read a file or all files in a directory and append their contents to the
9657 // input string. The names of the files are appended to the `fiList' list.
9658 
9659 int readFileOrDirectory(const char *s,
9660  FileNameList *fnList,
9661  FileNameDict *fnDict,
9662  StringDict *exclDict,
9663  QStrList *patList,
9664  QStrList *exclPatList,
9665  StringList *resultList,
9666  StringDict *resultDict,
9667  bool recursive,
9668  bool errorIfNotExist,
9669  QDict<void> *killDict,
9670  QDict<void> *paths
9671  )
9672 {
9673  //printf("killDict=%p count=%d\n",killDict,killDict->count());
9674  // strip trailing slashes
9675  if (s==0) return 0;
9676  QCString fs = s;
9677  char lc = fs.at(fs.length()-1);
9678  if (lc=='/' || lc=='\\') fs = fs.left(fs.length()-1);
9679 
9680  QFileInfo fi(fs);
9681  //printf("readFileOrDirectory(%s)\n",s);
9682  int totalSize=0;
9683  {
9684  if (exclDict==0 || exclDict->find(fi.absFilePath().utf8())==0)
9685  {
9686  if (!fi.exists() || !fi.isReadable())
9687  {
9688  if (errorIfNotExist)
9689  {
9690  warn_uncond("source %s is not a readable file or directory... skipping.\n",s);
9691  }
9692  }
9693  else if (!Config_getBool("EXCLUDE_SYMLINKS") || !fi.isSymLink())
9694  {
9695  if (fi.isFile())
9696  {
9697  QCString dirPath = fi.dirPath(TRUE).utf8();
9698  QCString filePath = fi.absFilePath().utf8();
9699  if (paths && paths->find(dirPath))
9700  {
9701  paths->insert(dirPath,(void*)0x8);
9702  }
9703  //printf("killDict->find(%s)\n",fi.absFilePath().data());
9704  if (killDict==0 || killDict->find(filePath)==0)
9705  {
9706  totalSize+=fi.size()+fi.absFilePath().length()+4; //readFile(&fi,fiList,input);
9707  //fiList->inSort(new FileInfo(fi));
9708  QCString name=fi.fileName().utf8();
9709  //printf("New file %s\n",name.data());
9710  if (fnDict)
9711  {
9712  FileDef *fd=new FileDef(dirPath+"/",name);
9713  FileName *fn=0;
9714  if (!name.isEmpty() && (fn=(*fnDict)[name]))
9715  {
9716  fn->append(fd);
9717  }
9718  else
9719  {
9720  fn = new FileName(filePath,name);
9721  fn->append(fd);
9722  if (fnList) fnList->inSort(fn);
9723  fnDict->insert(name,fn);
9724  }
9725  }
9726  QCString *rs=0;
9727  if (resultList || resultDict)
9728  {
9729  rs=new QCString(filePath);
9730  if (resultList) resultList->append(rs);
9731  if (resultDict) resultDict->insert(filePath,rs);
9732  }
9733 
9734  if (killDict) killDict->insert(fi.absFilePath().utf8(),(void *)0x8);
9735  }
9736  }
9737  else if (fi.isDir()) // readable dir
9738  {
9739  totalSize+=readDir(&fi,fnList,fnDict,exclDict,patList,
9740  exclPatList,resultList,resultDict,errorIfNotExist,
9741  recursive,killDict,paths);
9742  }
9743  }
9744  }
9745  }
9746  return totalSize;
9747 }
9748 
9749 //----------------------------------------------------------------------------
9750 
9752 {
9753  QFile f(Config_getString("HTML_OUTPUT")+"/formula.repository");
9754  if (f.open(IO_ReadOnly)) // open repository
9755  {
9756  msg("Reading formula repository...\n");
9757  QTextStream t(&f);
9758  QCString line;
9759  while (!t.eof())
9760  {
9761  line=t.readLine().utf8();
9762  int se=line.find(':'); // find name and text separator.
9763  if (se==-1)
9764  {
9765  warn_uncond("formula.repository is corrupted!\n");
9766  break;
9767  }
9768  else
9769  {
9770  QCString formName = line.left(se);
9771  QCString formText = line.right(line.length()-se-1);
9772  Formula *f=new Formula(formText);
9773  Doxygen::formulaList->setAutoDelete(TRUE);
9774  Doxygen::formulaList->append(f);
9775  Doxygen::formulaDict->insert(formText,f);
9776  Doxygen::formulaNameDict->insert(formName,f);
9777  }
9778  }
9779  }
9780 }
9781 
9782 //----------------------------------------------------------------------------
9783 
9784 static void expandAliases()
9785 {
9786  QDictIterator<QCString> adi(Doxygen::aliasDict);
9787  QCString *s;
9788  for (adi.toFirst();(s=adi.current());++adi)
9789  {
9790  *s = expandAlias(adi.currentKey(),*s);
9791  }
9792 }
9793 
9794 //----------------------------------------------------------------------------
9795 
9796 static void escapeAliases()
9797 {
9798  QDictIterator<QCString> adi(Doxygen::aliasDict);
9799  QCString *s;
9800  for (adi.toFirst();(s=adi.current());++adi)
9801  {
9802  QCString value=*s,newValue;
9803  int in,p=0;
9804  // for each \n in the alias command value
9805  while ((in=value.find("\\n",p))!=-1)
9806  {
9807  newValue+=value.mid(p,in-p);
9808  // expand \n's except if \n is part of a built-in command.
9809  if (value.mid(in,5)!="\\note" &&
9810  value.mid(in,5)!="\\name" &&
9811  value.mid(in,10)!="\\namespace" &&
9812  value.mid(in,14)!="\\nosubgrouping"
9813  )
9814  {
9815  newValue+="\\_linebr ";
9816  }
9817  else
9818  {
9819  newValue+="\\n";
9820  }
9821  p=in+2;
9822  }
9823  newValue+=value.mid(p,value.length()-p);
9824  *s=newValue;
9825  //printf("Alias %s has value %s\n",adi.currentKey().data(),s->data());
9826  }
9827 }
9828 
9829 //----------------------------------------------------------------------------
9830 
9832 {
9833  // add aliases to a dictionary
9834  Doxygen::aliasDict.setAutoDelete(TRUE);
9835  QStrList &aliasList = Config_getList("ALIASES");
9836  const char *s=aliasList.first();
9837  while (s)
9838  {
9839  if (Doxygen::aliasDict[s]==0)
9840  {
9841  QCString alias=s;
9842  int i=alias.find('=');
9843  if (i>0)
9844  {
9845  QCString name=alias.left(i).stripWhiteSpace();
9846  QCString value=alias.right(alias.length()-i-1);
9847  //printf("Alias: found name=`%s' value=`%s'\n",name.data(),value.data());
9848  if (!name.isEmpty())
9849  {
9851  if (dn==0) // insert new alias
9852  {
9853  Doxygen::aliasDict.insert(name,new QCString(value));
9854  }
9855  else // overwrite previous alias
9856  {
9857  *dn=value;
9858  }
9859  }
9860  }
9861  }
9862  s=aliasList.next();
9863  }
9864  expandAliases();
9865  escapeAliases();
9866 }
9867 
9868 //----------------------------------------------------------------------------
9869 
9871 {
9872  QCString anchor;
9874  {
9875  MemberDef *md = (MemberDef *)d;
9876  anchor=":"+md->anchor();
9877  }
9878  QCString scope;
9880  {
9882  }
9883  t << "REPLACE INTO symbols (symbol_id,scope_id,name,file,line) VALUES('"
9884  << d->getOutputFileBase()+Doxygen::htmlFileExtension+anchor << "','"
9885  << scope << "','"
9886  << d->name() << "','"
9887  << d->getDefFileName() << "','"
9888  << d->getDefLine()
9889  << "');" << endl;
9890 }
9891 
9892 static void dumpSymbolMap()
9893 {
9894  QFile f("symbols.sql");
9895  if (f.open(IO_WriteOnly))
9896  {
9897  FTextStream t(&f);
9898  QDictIterator<DefinitionIntf> di(*Doxygen::symbolMap);
9899  DefinitionIntf *intf;
9900  for (;(intf=di.current());++di)
9901  {
9902  if (intf->definitionType()==DefinitionIntf::TypeSymbolList) // list of symbols
9903  {
9905  Definition *d;
9906  // for each symbol
9907  for (dli.toFirst();(d=dli.current());++dli)
9908  {
9909  dumpSymbol(t,d);
9910  }
9911  }
9912  else // single symbol
9913  {
9914  Definition *d = (Definition *)intf;
9915  if (d!=Doxygen::globalScope) dumpSymbol(t,d);
9916  }
9917  }
9918  }
9919 }
9920 
9921 // print developer options of doxygen
9922 static void devUsage()
9923 {
9924  msg("Developer parameters:\n");
9925  msg(" -m dump symbol map\n");
9926  msg(" -b output to wizard\n");
9927  msg(" -T activates output generation via Django like template\n");
9928  msg(" -d <level> enable a debug level, such as (multiple invocations of -d are possible):\n");
9930 }
9931 
9932 
9933 //----------------------------------------------------------------------------
9934 // print the usage of doxygen
9935 
9936 static void usage(const char *name)
9937 {
9938  msg("Doxygen version %s\nCopyright Dimitri van Heesch 1997-2015\n\n",versionString);
9939  msg("You can use doxygen in a number of ways:\n\n");
9940  msg("1) Use doxygen to generate a template configuration file:\n");
9941  msg(" %s [-s] -g [configName]\n\n",name);
9942  msg(" If - is used for configName doxygen will write to standard output.\n\n");
9943  msg("2) Use doxygen to update an old configuration file:\n");
9944  msg(" %s [-s] -u [configName]\n\n",name);
9945  msg("3) Use doxygen to generate documentation using an existing ");
9946  msg("configuration file:\n");
9947  msg(" %s [configName]\n\n",name);
9948  msg(" If - is used for configName doxygen will read from standard input.\n\n");
9949  msg("4) Use doxygen to generate a template file controlling the layout of the\n");
9950  msg(" generated documentation:\n");
9951  msg(" %s -l [layoutFileName.xml]\n\n",name);
9952  msg("5) Use doxygen to generate a template style sheet file for RTF, HTML or Latex.\n");
9953  msg(" RTF: %s -w rtf styleSheetFile\n",name);
9954  msg(" HTML: %s -w html headerFile footerFile styleSheetFile [configFile]\n",name);
9955  msg(" LaTeX: %s -w latex headerFile footerFile styleSheetFile [configFile]\n\n",name);
9956  msg("6) Use doxygen to generate a rtf extensions file\n");
9957  msg(" RTF: %s -e rtf extensionsFile\n\n",name);
9958  msg("If -s is specified the comments of the configuration items in the config file will be omitted.\n");
9959  msg("If configName is omitted `Doxyfile' will be used as a default.\n\n");
9960  msg("-v print version string\n");
9961 }
9962 
9963 //----------------------------------------------------------------------------
9964 // read the argument of option `c' from the comment argument list and
9965 // update the option index `optind'.
9966 
9967 static const char *getArg(int argc,char **argv,int &optind)
9968 {
9969  char *s=0;
9970  if (qstrlen(&argv[optind][2])>0)
9971  s=&argv[optind][2];
9972  else if (optind+1<argc && argv[optind+1][0]!='-')
9973  s=argv[++optind];
9974  return s;
9975 }
9976 
9977 //----------------------------------------------------------------------------
9978 
9980 {
9981  initResources();
9982  const char *lang = portable_getenv("LC_ALL");
9983  if (lang) portable_setenv("LANG",lang);
9984  setlocale(LC_ALL,"");
9985  setlocale(LC_CTYPE,"C"); // to get isspace(0xA0)==0, needed for UTF-8
9986  setlocale(LC_NUMERIC,"C");
9987 
9988  Doxygen::runningTime.start();
9989  initPreprocessor();
9990 
9991  Doxygen::parserManager = new ParserManager;
9992  Doxygen::parserManager->registerDefaultParser( new FileParser);
9993  Doxygen::parserManager->registerParser("c", new CLanguageScanner);
9994  Doxygen::parserManager->registerParser("python", new PythonLanguageScanner);
9995  Doxygen::parserManager->registerParser("fortran", new FortranLanguageScanner);
9996  Doxygen::parserManager->registerParser("fortranfree", new FortranLanguageScannerFree);
9997  Doxygen::parserManager->registerParser("fortranfixed", new FortranLanguageScannerFixed);
9998  Doxygen::parserManager->registerParser("vhdl", new VHDLLanguageScanner);
9999  Doxygen::parserManager->registerParser("xml", new XMLScanner);
10000  Doxygen::parserManager->registerParser("tcl", new TclLanguageScanner);
10001  Doxygen::parserManager->registerParser("md", new MarkdownFileParser);
10002 
10003  // register any additional parsers here...
10004 
10009 
10010  Doxygen::symbolMap = new QDict<DefinitionIntf>(50177);
10011 #ifdef USE_LIBCLANG
10012  Doxygen::clangUsrMap = new QDict<Definition>(50177);
10013 #endif
10014  Doxygen::inputNameList = new FileNameList;
10015  Doxygen::inputNameList->setAutoDelete(TRUE);
10016  Doxygen::memberNameSDict = new MemberNameSDict(10000);
10017  Doxygen::memberNameSDict->setAutoDelete(TRUE);
10018  Doxygen::functionNameSDict = new MemberNameSDict(10000);
10019  Doxygen::functionNameSDict->setAutoDelete(TRUE);
10020  Doxygen::groupSDict = new GroupSDict(17);
10021  Doxygen::groupSDict->setAutoDelete(TRUE);
10022  Doxygen::globalScope = new NamespaceDef("<globalScope>",1,1,"<globalScope>");
10023  Doxygen::namespaceSDict = new NamespaceSDict(20);
10024  Doxygen::namespaceSDict->setAutoDelete(TRUE);
10025  Doxygen::classSDict = new ClassSDict(1009);
10026  Doxygen::classSDict->setAutoDelete(TRUE);
10027  Doxygen::hiddenClasses = new ClassSDict(257);
10028  Doxygen::hiddenClasses->setAutoDelete(TRUE);
10029  Doxygen::directories = new DirSDict(17);
10030  Doxygen::directories->setAutoDelete(TRUE);
10031  Doxygen::pageSDict = new PageSDict(1009); // all doc pages
10032  Doxygen::pageSDict->setAutoDelete(TRUE);
10033  Doxygen::exampleSDict = new PageSDict(1009); // all examples
10034  Doxygen::exampleSDict->setAutoDelete(TRUE);
10035  Doxygen::inputNameDict = new FileNameDict(10007);
10036  Doxygen::includeNameDict = new FileNameDict(10007);
10037  Doxygen::exampleNameDict = new FileNameDict(1009);
10038  Doxygen::exampleNameDict->setAutoDelete(TRUE);
10039  Doxygen::imageNameDict = new FileNameDict(257);
10040  Doxygen::imageNameDict->setAutoDelete(TRUE);
10041  Doxygen::dotFileNameDict = new FileNameDict(257);
10042  Doxygen::mscFileNameDict = new FileNameDict(257);
10043  Doxygen::diaFileNameDict = new FileNameDict(257);
10045  Doxygen::tagDestinationDict.setAutoDelete(TRUE);
10047  Doxygen::citeDict = new CiteDict(257);
10048  Doxygen::genericsDict = new GenericsSDict;
10049  Doxygen::indexList = new IndexList;
10050  Doxygen::formulaList = new FormulaList;
10051  Doxygen::formulaDict = new FormulaDict(1009);
10052  Doxygen::formulaNameDict = new FormulaDict(1009);
10053  Doxygen::sectionDict = new SectionDict(257);
10054  Doxygen::sectionDict->setAutoDelete(TRUE);
10055 
10056  /**************************************************************************
10057  * Initialize some global constants
10058  **************************************************************************/
10059 
10060  g_compoundKeywordDict.insert("template class",(void *)8);
10061  g_compoundKeywordDict.insert("template struct",(void *)8);
10062  g_compoundKeywordDict.insert("class",(void *)8);
10063  g_compoundKeywordDict.insert("struct",(void *)8);
10064  g_compoundKeywordDict.insert("union",(void *)8);
10065  g_compoundKeywordDict.insert("interface",(void *)8);
10066  g_compoundKeywordDict.insert("exception",(void *)8);
10067 
10068 }
10069 
10071 {
10072  delete Doxygen::sectionDict;
10073  delete Doxygen::formulaNameDict;
10074  delete Doxygen::formulaDict;
10075  delete Doxygen::formulaList;
10076  delete Doxygen::indexList;
10077  delete Doxygen::genericsDict;
10078  delete Doxygen::inputNameDict;
10079  delete Doxygen::includeNameDict;
10080  delete Doxygen::exampleNameDict;
10081  delete Doxygen::imageNameDict;
10082  delete Doxygen::dotFileNameDict;
10083  delete Doxygen::mscFileNameDict;
10084  delete Doxygen::diaFileNameDict;
10085  delete Doxygen::mainPage;
10086  delete Doxygen::pageSDict;
10087  delete Doxygen::exampleSDict;
10088  delete Doxygen::globalScope;
10089  delete Doxygen::xrefLists;
10090  delete Doxygen::parserManager;
10092  delete theTranslator;
10093  delete g_outputList;
10095  codeFreeScanner();
10096 
10097  if (Doxygen::symbolMap)
10098  {
10099  // iterate through Doxygen::symbolMap and delete all
10100  // DefinitionList objects, since they have no owner
10101  QDictIterator<DefinitionIntf> dli(*Doxygen::symbolMap);
10102  DefinitionIntf *di;
10103  for (dli.toFirst();(di=dli.current());)
10104  {
10106  {
10107  DefinitionIntf *tmp = Doxygen::symbolMap->take(dli.currentKey());
10108  delete (DefinitionList *)tmp;
10109  }
10110  else
10111  {
10112  ++dli;
10113  }
10114  }
10115  }
10116 
10117  delete Doxygen::inputNameList;
10118  delete Doxygen::memberNameSDict;
10120  delete Doxygen::groupSDict;
10121  delete Doxygen::classSDict;
10122  delete Doxygen::hiddenClasses;
10123  delete Doxygen::namespaceSDict;
10124  delete Doxygen::directories;
10125 
10126  //delete Doxygen::symbolMap; <- we cannot do this unless all static lists
10127  // (such as Doxygen::namespaceSDict)
10128  // with objects based on Definition are made
10129  // dynamic first
10130 }
10131 
10133 {
10134  //printf("computeIdealCacheParam(v=%u)\n",v);
10135 
10136  int r=0;
10137  while (v!=0) v>>=1,r++;
10138  // r = log2(v)
10139 
10140  // convert to a valid cache size value
10141  return QMAX(0,QMIN(r-16,9));
10142 }
10143 
10144 void readConfiguration(int argc, char **argv)
10145 {
10146  /**************************************************************************
10147  * Handle arguments *
10148  **************************************************************************/
10149 
10150  int optind=1;
10151  const char *configName=0;
10152  const char *layoutName=0;
10153  const char *debugLabel;
10154  const char *formatName;
10155  bool genConfig=FALSE;
10156  bool shortList=FALSE;
10157  bool updateConfig=FALSE;
10158  bool genLayout=FALSE;
10159  int retVal;
10160  while (optind<argc && argv[optind][0]=='-' &&
10161  (isalpha(argv[optind][1]) || argv[optind][1]=='?' ||
10162  argv[optind][1]=='-')
10163  )
10164  {
10165  switch(argv[optind][1])
10166  {
10167  case 'g':
10168  genConfig=TRUE;
10169  configName=getArg(argc,argv,optind);
10170  if (optind+1<argc && qstrcmp(argv[optind+1],"-")==0)
10171  { configName="-"; optind++; }
10172  if (!configName)
10173  { configName="Doxyfile"; }
10174  break;
10175  case 'l':
10176  genLayout=TRUE;
10177  layoutName=getArg(argc,argv,optind);
10178  if (!layoutName)
10179  { layoutName="DoxygenLayout.xml"; }
10180  break;
10181  case 'd':
10182  debugLabel=getArg(argc,argv,optind);
10183  if (!debugLabel)
10184  {
10185  err("option \"-d\" is missing debug specifier.\n");
10186  devUsage();
10187  cleanUpDoxygen();
10188  exit(1);
10189  }
10190  retVal = Debug::setFlag(debugLabel);
10191  if (!retVal)
10192  {
10193  err("option \"-d\" has unknown debug specifier: \"%s\".\n",debugLabel);
10194  cleanUpDoxygen();
10195  exit(1);
10196  }
10197  break;
10198  case 's':
10199  shortList=TRUE;
10200  break;
10201  case 'u':
10202  updateConfig=TRUE;
10203  break;
10204  case 'e':
10205  formatName=getArg(argc,argv,optind);
10206  if (!formatName)
10207  {
10208  err("option \"-e\" is missing format specifier rtf.\n");
10209  cleanUpDoxygen();
10210  exit(1);
10211  }
10212  if (qstricmp(formatName,"rtf")==0)
10213  {
10214  if (optind+1>=argc)
10215  {
10216  err("option \"-e rtf\" is missing an extensions file name\n");
10217  cleanUpDoxygen();
10218  exit(1);
10219  }
10220  QFile f;
10221  if (openOutputFile(argv[optind+1],f))
10222  {
10224  }
10225  cleanUpDoxygen();
10226  exit(0);
10227  }
10228  err("option \"-e\" has invalid format specifier.\n");
10229  cleanUpDoxygen();
10230  exit(1);
10231  break;
10232  case 'w':
10233  formatName=getArg(argc,argv,optind);
10234  if (!formatName)
10235  {
10236  err("option \"-w\" is missing format specifier rtf, html or latex\n");
10237  cleanUpDoxygen();
10238  exit(1);
10239  }
10240  if (qstricmp(formatName,"rtf")==0)
10241  {
10242  if (optind+1>=argc)
10243  {
10244  err("option \"-w rtf\" is missing a style sheet file name\n");
10245  cleanUpDoxygen();
10246  exit(1);
10247  }
10248  QFile f;
10249  if (openOutputFile(argv[optind+1],f))
10250  {
10252  }
10253  cleanUpDoxygen();
10254  exit(1);
10255  }
10256  else if (qstricmp(formatName,"html")==0)
10257  {
10258  if (optind+4<argc || QFileInfo("Doxyfile").exists())
10259  {
10260  QCString df = optind+4<argc ? argv[optind+4] : QCString("Doxyfile");
10261  if (!Config::instance()->parse(df))
10262  {
10263  err("error opening or reading configuration file %s!\n",argv[optind+4]);
10264  cleanUpDoxygen();
10265  exit(1);
10266  }
10267  Config::instance()->substituteEnvironmentVars();
10268  Config::instance()->convertStrToVal();
10269  // avoid bootstrapping issues when the config file already
10270  // refers to the files that we are supposed to parse.
10271  Config_getString("HTML_HEADER")="";
10272  Config_getString("HTML_FOOTER")="";
10273  Config::instance()->check();
10274  }
10275  else
10276  {
10277  Config::instance()->init();
10278  }
10279  if (optind+3>=argc)
10280  {
10281  err("option \"-w html\" does not have enough arguments\n");
10282  cleanUpDoxygen();
10283  exit(1);
10284  }
10285 
10286  QCString outputLanguage=Config_getEnum("OUTPUT_LANGUAGE");
10287  if (!setTranslator(outputLanguage))
10288  {
10289  warn_uncond("Output language %s not supported! Using English instead.\n", outputLanguage.data());
10290  }
10291 
10292  QFile f;
10293  if (openOutputFile(argv[optind+1],f))
10294  {
10295  HtmlGenerator::writeHeaderFile(f, argv[optind+3]);
10296  }
10297  f.close();
10298  if (openOutputFile(argv[optind+2],f))
10299  {
10301  }
10302  f.close();
10303  if (openOutputFile(argv[optind+3],f))
10304  {
10306  }
10307  cleanUpDoxygen();
10308  exit(0);
10309  }
10310  else if (qstricmp(formatName,"latex")==0)
10311  {
10312  if (optind+4<argc || QFileInfo("Doxyfile").exists())
10313  {
10314  QCString df = optind+4<argc ? argv[optind+4] : QCString("Doxyfile");
10315  if (!Config::instance()->parse(df))
10316  {
10317  err("error opening or reading configuration file %s!\n",argv[optind+4]);
10318  cleanUpDoxygen();
10319  exit(1);
10320  }
10321  Config::instance()->substituteEnvironmentVars();
10322  Config::instance()->convertStrToVal();
10323  Config_getString("LATEX_HEADER")="";
10324  Config_getString("LATEX_FOOTER")="";
10325  Config::instance()->check();
10326  }
10327  else // use default config
10328  {
10329  Config::instance()->init();
10330  }
10331  if (optind+3>=argc)
10332  {
10333  err("option \"-w latex\" does not have enough arguments\n");
10334  cleanUpDoxygen();
10335  exit(1);
10336  }
10337 
10338  QCString outputLanguage=Config_getEnum("OUTPUT_LANGUAGE");
10339  if (!setTranslator(outputLanguage))
10340  {
10341  warn_uncond("Output language %s not supported! Using English instead.\n", outputLanguage.data());
10342  }
10343 
10344  QFile f;
10345  if (openOutputFile(argv[optind+1],f))
10346  {
10348  }
10349  f.close();
10350  if (openOutputFile(argv[optind+2],f))
10351  {
10353  }
10354  f.close();
10355  if (openOutputFile(argv[optind+3],f))
10356  {
10358  }
10359  cleanUpDoxygen();
10360  exit(0);
10361  }
10362  else
10363  {
10364  err("Illegal format specifier \"%s\": should be one of rtf, html or latex\n",formatName);
10365  cleanUpDoxygen();
10366  exit(1);
10367  }
10368  break;
10369  case 'm':
10371  break;
10372  case 'v':
10373  msg("%s\n",versionString);
10374  cleanUpDoxygen();
10375  exit(0);
10376  break;
10377  case '-':
10378  if (qstrcmp(&argv[optind][2],"help")==0)
10379  {
10380  usage(argv[0]);
10381  exit(0);
10382  }
10383  else if (qstrcmp(&argv[optind][2],"version")==0)
10384  {
10385  msg("%s\n",versionString);
10386  cleanUpDoxygen();
10387  exit(0);
10388  }
10389  else
10390  {
10391  err("Unknown option \"-%s\"\n",&argv[optind][1]);
10392  usage(argv[0]);
10393  exit(1);
10394  }
10395  break;
10396  case 'b':
10397  setvbuf(stdout,NULL,_IONBF,0);
10399  break;
10400  case 'T':
10401  msg("Warning: this option activates output generation via Django like template files. "
10402  "This option is scheduled for doxygen 2.0, is currently incomplete and highly experimental! "
10403  "Only use if you are a doxygen developer\n");
10405  break;
10406  case 'h':
10407  case '?':
10408  usage(argv[0]);
10409  exit(0);
10410  break;
10411  default:
10412  err("Unknown option \"-%c\"\n",argv[optind][1]);
10413  usage(argv[0]);
10414  exit(1);
10415  }
10416  optind++;
10417  }
10418 
10419  /**************************************************************************
10420  * Parse or generate the config file *
10421  **************************************************************************/
10422 
10423  Config::instance()->init();
10424 
10425  if (genConfig)
10426  {
10427  generateConfigFile(configName,shortList);
10428  cleanUpDoxygen();
10429  exit(0);
10430  }
10431  if (genLayout)
10432  {
10433  writeDefaultLayoutFile(layoutName);
10434  cleanUpDoxygen();
10435  exit(0);
10436  }
10437 
10438  QFileInfo configFileInfo1("Doxyfile"),configFileInfo2("doxyfile");
10439  if (optind>=argc)
10440  {
10441  if (configFileInfo1.exists())
10442  {
10443  configName="Doxyfile";
10444  }
10445  else if (configFileInfo2.exists())
10446  {
10447  configName="doxyfile";
10448  }
10449  else
10450  {
10451  err("Doxyfile not found and no input file specified!\n");
10452  usage(argv[0]);
10453  exit(1);
10454  }
10455  }
10456  else
10457  {
10458  QFileInfo fi(argv[optind]);
10459  if (fi.exists() || qstrcmp(argv[optind],"-")==0)
10460  {
10461  configName=argv[optind];
10462  }
10463  else
10464  {
10465  err("configuration file %s not found!\n",argv[optind]);
10466  usage(argv[0]);
10467  exit(1);
10468  }
10469  }
10470 
10471 
10472  if (!Config::instance()->parse(configName,updateConfig))
10473  {
10474  err("could not open or read configuration file %s!\n",configName);
10475  cleanUpDoxygen();
10476  exit(1);
10477  }
10478 
10479  if (updateConfig)
10480  {
10481  generateConfigFile(configName,shortList,TRUE);
10482  cleanUpDoxygen();
10483  exit(0);
10484  }
10485 
10486  /* Perlmod wants to know the path to the config file.*/
10487  QFileInfo configFileInfo(configName);
10488  setPerlModDoxyfile(configFileInfo.absFilePath().data());
10489 
10490 }
10491 
10492 /** check and resolve config options */
10494 {
10495 
10496  Config::instance()->substituteEnvironmentVars();
10497  Config::instance()->convertStrToVal();
10498  Config::instance()->check();
10499 
10501 }
10502 
10503 /** adjust globals that depend on configuration settings. */
10505 {
10506  QCString outputLanguage=Config_getEnum("OUTPUT_LANGUAGE");
10507  if (!setTranslator(outputLanguage))
10508  {
10509  warn_uncond("Output language %s not supported! Using English instead.\n",
10510  outputLanguage.data());
10511  }
10512  QStrList &includePath = Config_getList("INCLUDE_PATH");
10513  char *s=includePath.first();
10514  while (s)
10515  {
10516  QFileInfo fi(s);
10517  addSearchDir(fi.absFilePath().utf8());
10518  s=includePath.next();
10519  }
10520 
10521  /* Set the global html file extension. */
10522  Doxygen::htmlFileExtension = Config_getString("HTML_FILE_EXTENSION");
10523 
10524 
10525  Doxygen::xrefLists->setAutoDelete(TRUE);
10526 
10527  Doxygen::parseSourcesNeeded = Config_getBool("CALL_GRAPH") ||
10528  Config_getBool("CALLER_GRAPH") ||
10529  Config_getBool("REFERENCES_RELATION") ||
10530  Config_getBool("REFERENCED_BY_RELATION");
10531 
10532  Doxygen::markdownSupport = Config_getBool("MARKDOWN_SUPPORT");
10533 
10534  /**************************************************************************
10535  * Add custom extension mappings
10536  **************************************************************************/
10537 
10538  QStrList &extMaps = Config_getList("EXTENSION_MAPPING");
10539  char *mapping = extMaps.first();
10540  while (mapping)
10541  {
10542  QCString mapStr = mapping;
10543  int i;
10544  if ((i=mapStr.find('='))!=-1)
10545  {
10546  QCString ext=mapStr.left(i).stripWhiteSpace().lower();
10547  QCString language=mapStr.mid(i+1).stripWhiteSpace().lower();
10548  if (!updateLanguageMapping(ext,language))
10549  {
10550  err("Failed to map file extension '%s' to unsupported language '%s'.\n"
10551  "Check the EXTENSION_MAPPING setting in the config file.\n",
10552  ext.data(),language.data());
10553  }
10554  else
10555  {
10556  msg("Adding custom extension mapping: .%s will be treated as language %s\n",
10557  ext.data(),language.data());
10558  }
10559  }
10560  mapping = extMaps.next();
10561  }
10562 
10563 
10564  // add predefined macro name to a dictionary
10565  QStrList &expandAsDefinedList =Config_getList("EXPAND_AS_DEFINED");
10566  s=expandAsDefinedList.first();
10567  while (s)
10568  {
10569  if (Doxygen::expandAsDefinedDict[s]==0)
10570  {
10571  Doxygen::expandAsDefinedDict.insert(s,(void *)666);
10572  }
10573  s=expandAsDefinedList.next();
10574  }
10575 
10576  // read aliases and store them in a dictionary
10577  readAliases();
10578 
10579  // store number of spaces in a tab into Doxygen::spaces
10580  int &tabSize = Config_getInt("TAB_SIZE");
10581  Doxygen::spaces.resize(tabSize+1);
10582  int sp;for (sp=0;sp<tabSize;sp++) Doxygen::spaces.at(sp)=' ';
10583  Doxygen::spaces.at(tabSize)='\0';
10584 }
10585 
10586 #ifdef HAS_SIGNALS
10587 static void stopDoxygen(int)
10588 {
10589  QDir thisDir;
10590  msg("Cleaning up...\n");
10591  if (!Doxygen::entryDBFileName.isEmpty())
10592  {
10593  thisDir.remove(Doxygen::entryDBFileName);
10594  }
10595  if (!Doxygen::objDBFileName.isEmpty())
10596  {
10597  thisDir.remove(Doxygen::objDBFileName);
10598  }
10599  killpg(0,SIGINT);
10600  exit(1);
10601 }
10602 #endif
10603 
10604 static void writeTagFile()
10605 {
10606  QCString &generateTagFile = Config_getString("GENERATE_TAGFILE");
10607  if (generateTagFile.isEmpty()) return;
10608 
10609  QFile tag(generateTagFile);
10610  if (!tag.open(IO_WriteOnly))
10611  {
10612  err("cannot open tag file %s for writing\n",
10613  generateTagFile.data()
10614  );
10615  return;
10616  }
10617  FTextStream tagFile(&tag);
10618  tagFile << "<?xml version='1.0' encoding='UTF-8' standalone='yes' ?>" << endl;
10619  tagFile << "<tagfile>" << endl;
10620 
10621  // for each file
10622  FileNameListIterator fnli(*Doxygen::inputNameList);
10623  FileName *fn;
10624  for (fnli.toFirst();(fn=fnli.current());++fnli)
10625  {
10626  FileNameIterator fni(*fn);
10627  FileDef *fd;
10628  for (fni.toFirst();(fd=fni.current());++fni)
10629  {
10630  if (fd->isLinkableInProject()) fd->writeTagFile(tagFile);
10631  }
10632  }
10633  // for each class
10634  ClassSDict::Iterator cli(*Doxygen::classSDict);
10635  ClassDef *cd;
10636  for ( ; (cd=cli.current()) ; ++cli )
10637  {
10638  if (cd->isLinkableInProject()) cd->writeTagFile(tagFile);
10639  }
10640  // for each namespace
10641  NamespaceSDict::Iterator nli(*Doxygen::namespaceSDict);
10642  NamespaceDef *nd;
10643  for ( ; (nd=nli.current()) ; ++nli )
10644  {
10645  if (nd->isLinkableInProject()) nd->writeTagFile(tagFile);
10646  }
10647  // for each group
10648  GroupSDict::Iterator gli(*Doxygen::groupSDict);
10649  GroupDef *gd;
10650  for (gli.toFirst();(gd=gli.current());++gli)
10651  {
10652  if (gd->isLinkableInProject()) gd->writeTagFile(tagFile);
10653  }
10654  // for each page
10655  PageSDict::Iterator pdi(*Doxygen::pageSDict);
10656  PageDef *pd=0;
10657  for (pdi.toFirst();(pd=pdi.current());++pdi)
10658  {
10659  if (pd->isLinkableInProject()) pd->writeTagFile(tagFile);
10660  }
10661  if (Doxygen::mainPage) Doxygen::mainPage->writeTagFile(tagFile);
10662 
10663  /*
10664  if (Doxygen::mainPage && !Config_getString("GENERATE_TAGFILE").isEmpty())
10665  {
10666  tagFile << " <compound kind=\"page\">" << endl
10667  << " <name>"
10668  << convertToXML(Doxygen::mainPage->name())
10669  << "</name>" << endl
10670  << " <title>"
10671  << convertToXML(Doxygen::mainPage->title())
10672  << "</title>" << endl
10673  << " <filename>"
10674  << convertToXML(Doxygen::mainPage->getOutputFileBase())
10675  << "</filename>" << endl;
10676 
10677  mainPage->writeDocAnchorsToTagFile();
10678  tagFile << " </compound>" << endl;
10679  }
10680  */
10681 
10682  tagFile << "</tagfile>" << endl;
10683 }
10684 
10685 static void exitDoxygen()
10686 {
10687  if (!g_successfulRun) // premature exit
10688  {
10689  QDir thisDir;
10690  msg("Exiting...\n");
10691  if (!Doxygen::entryDBFileName.isEmpty())
10692  {
10693  thisDir.remove(Doxygen::entryDBFileName);
10694  }
10695  if (!Doxygen::objDBFileName.isEmpty())
10696  {
10697  thisDir.remove(Doxygen::objDBFileName);
10698  }
10699  }
10700 }
10701 
10702 static QCString createOutputDirectory(const QCString &baseDirName,
10703  const char *formatDirOption,
10704  const char *defaultDirName)
10705 {
10706  // Note the & on the next line, we modify the formatDirOption!
10707  QCString &formatDirName = Config_getString(formatDirOption);
10708  if (formatDirName.isEmpty())
10709  {
10710  formatDirName = baseDirName + defaultDirName;
10711  }
10712  else if (formatDirName[0]!='/' && (formatDirName.length()==1 || formatDirName[1]!=':'))
10713  {
10714  formatDirName.prepend(baseDirName+'/');
10715  }
10716  QDir formatDir(formatDirName);
10717  if (!formatDir.exists() && !formatDir.mkdir(formatDirName))
10718  {
10719  err("Could not create output directory %s\n", formatDirName.data());
10720  cleanUpDoxygen();
10721  exit(1);
10722  }
10723  return formatDirName;
10724 }
10725 
10727 {
10728  QCString const & qchFile = Config_getString("QCH_FILE");
10729  if (!qchFile.isEmpty())
10730  {
10731  return qchFile;
10732  }
10733 
10734  QCString const & projectName = Config_getString("PROJECT_NAME");
10735  QCString const & versionText = Config_getString("PROJECT_NUMBER");
10736 
10737  return QCString("../qch/")
10738  + (projectName.isEmpty() ? QCString("index") : projectName)
10739  + (versionText.isEmpty() ? QCString("") : QCString("-") + versionText)
10740  + QCString(".qch");
10741 }
10742 
10744 {
10745  QStrList &exclPatterns = Config_getList("EXCLUDE_PATTERNS");
10746  bool alwaysRecursive = Config_getBool("RECURSIVE");
10747  StringDict excludeNameDict(1009);
10748  excludeNameDict.setAutoDelete(TRUE);
10749 
10750  // gather names of all files in the include path
10751  g_s.begin("Searching for include files...\n");
10752  QStrList &includePathList = Config_getList("INCLUDE_PATH");
10753  char *s=includePathList.first();
10754  while (s)
10755  {
10756  QStrList &pl = Config_getList("INCLUDE_FILE_PATTERNS");
10757  if (pl.count()==0)
10758  {
10759  pl = Config_getList("FILE_PATTERNS");
10760  }
10761  readFileOrDirectory(s,0,Doxygen::includeNameDict,0,&pl,
10762  &exclPatterns,0,0,
10763  alwaysRecursive);
10764  s=includePathList.next();
10765  }
10766  g_s.end();
10767 
10768  g_s.begin("Searching for example files...\n");
10769  QStrList &examplePathList = Config_getList("EXAMPLE_PATH");
10770  s=examplePathList.first();
10771  while (s)
10772  {
10773  readFileOrDirectory(s,0,Doxygen::exampleNameDict,0,
10774  &Config_getList("EXAMPLE_PATTERNS"),
10775  0,0,0,
10776  (alwaysRecursive || Config_getBool("EXAMPLE_RECURSIVE")));
10777  s=examplePathList.next();
10778  }
10779  g_s.end();
10780 
10781  g_s.begin("Searching for images...\n");
10782  QStrList &imagePathList=Config_getList("IMAGE_PATH");
10783  s=imagePathList.first();
10784  while (s)
10785  {
10786  readFileOrDirectory(s,0,Doxygen::imageNameDict,0,0,
10787  0,0,0,
10788  alwaysRecursive);
10789  s=imagePathList.next();
10790  }
10791  g_s.end();
10792 
10793  g_s.begin("Searching for dot files...\n");
10794  QStrList &dotFileList=Config_getList("DOTFILE_DIRS");
10795  s=dotFileList.first();
10796  while (s)
10797  {
10798  readFileOrDirectory(s,0,Doxygen::dotFileNameDict,0,0,
10799  0,0,0,
10800  alwaysRecursive);
10801  s=dotFileList.next();
10802  }
10803  g_s.end();
10804 
10805  g_s.begin("Searching for msc files...\n");
10806  QStrList &mscFileList=Config_getList("MSCFILE_DIRS");
10807  s=mscFileList.first();
10808  while (s)
10809  {
10810  readFileOrDirectory(s,0,Doxygen::mscFileNameDict,0,0,
10811  0,0,0,
10812  alwaysRecursive);
10813  s=mscFileList.next();
10814  }
10815  g_s.end();
10816 
10817  g_s.begin("Searching for dia files...\n");
10818  QStrList &diaFileList=Config_getList("DIAFILE_DIRS");
10819  s=diaFileList.first();
10820  while (s)
10821  {
10822  readFileOrDirectory(s,0,Doxygen::diaFileNameDict,0,0,
10823  0,0,0,
10824  alwaysRecursive);
10825  s=diaFileList.next();
10826  }
10827  g_s.end();
10828 
10829  g_s.begin("Searching for files to exclude\n");
10830  QStrList &excludeList = Config_getList("EXCLUDE");
10831  s=excludeList.first();
10832  while (s)
10833  {
10834  readFileOrDirectory(s,0,0,0,&Config_getList("FILE_PATTERNS"),
10835  0,0,&excludeNameDict,
10836  alwaysRecursive,
10837  FALSE);
10838  s=excludeList.next();
10839  }
10840  g_s.end();
10841 
10842  /**************************************************************************
10843  * Determine Input Files *
10844  **************************************************************************/
10845 
10846  g_s.begin("Searching INPUT for files to process...\n");
10847  QDict<void> *killDict = new QDict<void>(10007);
10848  QStrList &inputList=Config_getList("INPUT");
10849  g_inputFiles.setAutoDelete(TRUE);
10850  s=inputList.first();
10851  while (s)
10852  {
10853  QCString path=s;
10854  uint l = path.length();
10855  if (l>0)
10856  {
10857  // strip trailing slashes
10858  if (path.at(l-1)=='\\' || path.at(l-1)=='/') path=path.left(l-1);
10859 
10861  path,
10862  Doxygen::inputNameList,
10863  Doxygen::inputNameDict,
10864  &excludeNameDict,
10865  &Config_getList("FILE_PATTERNS"),
10866  &exclPatterns,
10867  &g_inputFiles,0,
10868  alwaysRecursive,
10869  TRUE,
10870  killDict,
10872  }
10873  s=inputList.next();
10874  }
10875  delete killDict;
10876  g_s.end();
10877 }
10878 
10879 
10881 {
10882  atexit(exitDoxygen);
10883 
10884 
10885  /**************************************************************************
10886  * Make sure the output directory exists
10887  **************************************************************************/
10888  QCString &outputDirectory = Config_getString("OUTPUT_DIRECTORY");
10889  if (outputDirectory.isEmpty())
10890  {
10891  outputDirectory=QDir::currentDirPath().utf8();
10892  }
10893  else
10894  {
10895  QDir dir(outputDirectory);
10896  if (!dir.exists())
10897  {
10899  if (!dir.mkdir(outputDirectory))
10900  {
10901  err("tag OUTPUT_DIRECTORY: Output directory `%s' does not "
10902  "exist and cannot be created\n",outputDirectory.data());
10903  cleanUpDoxygen();
10904  exit(1);
10905  }
10906  else
10907  {
10908  msg("Notice: Output directory `%s' does not exist. "
10909  "I have created it for you.\n", outputDirectory.data());
10910  }
10911  dir.cd(outputDirectory);
10912  }
10913  outputDirectory=dir.absPath().utf8();
10914  }
10915 
10916  /**************************************************************************
10917  * Initialize global lists and dictionaries
10918  **************************************************************************/
10919 
10920  Doxygen::symbolStorage = new Store;
10921 
10922  // also scale lookup cache with SYMBOL_CACHE_SIZE
10923  int cacheSize = Config_getInt("LOOKUP_CACHE_SIZE");
10924  if (cacheSize<0) cacheSize=0;
10925  if (cacheSize>9) cacheSize=9;
10926  uint lookupSize = 65536 << cacheSize;
10927  Doxygen::lookupCache = new QCache<LookupInfo>(lookupSize,lookupSize);
10928  Doxygen::lookupCache->setAutoDelete(TRUE);
10929 
10930 #ifdef HAS_SIGNALS
10931  signal(SIGINT, stopDoxygen);
10932 #endif
10933 
10934  uint pid = portable_pid();
10935  Doxygen::objDBFileName.sprintf("doxygen_objdb_%d.tmp",pid);
10936  Doxygen::objDBFileName.prepend(outputDirectory+"/");
10937  Doxygen::entryDBFileName.sprintf("doxygen_entrydb_%d.tmp",pid);
10938  Doxygen::entryDBFileName.prepend(outputDirectory+"/");
10939 
10940  if (Doxygen::symbolStorage->open(Doxygen::objDBFileName)==-1)
10941  {
10942  err("Failed to open temporary file %s\n",Doxygen::objDBFileName.data());
10943  exit(1);
10944  }
10945 
10946 
10947 
10948  /**************************************************************************
10949  * Check/create output directorties *
10950  **************************************************************************/
10951 
10952  QCString htmlOutput;
10953  bool &generateHtml = Config_getBool("GENERATE_HTML");
10954  if (generateHtml || g_useOutputTemplate /* TODO: temp hack */)
10955  htmlOutput = createOutputDirectory(outputDirectory,"HTML_OUTPUT","/html");
10956 
10957  QCString docbookOutput;
10958  bool &generateDocbook = Config_getBool("GENERATE_DOCBOOK");
10959  if (generateDocbook)
10960  docbookOutput = createOutputDirectory(outputDirectory,"DOCBOOK_OUTPUT","/docbook");
10961 
10962  QCString xmlOutput;
10963  bool &generateXml = Config_getBool("GENERATE_XML");
10964  if (generateXml)
10965  xmlOutput = createOutputDirectory(outputDirectory,"XML_OUTPUT","/xml");
10966 
10967  QCString latexOutput;
10968  bool &generateLatex = Config_getBool("GENERATE_LATEX");
10969  if (generateLatex)
10970  latexOutput = createOutputDirectory(outputDirectory,"LATEX_OUTPUT","/latex");
10971 
10972  QCString rtfOutput;
10973  bool &generateRtf = Config_getBool("GENERATE_RTF");
10974  if (generateRtf)
10975  rtfOutput = createOutputDirectory(outputDirectory,"RTF_OUTPUT","/rtf");
10976 
10977  QCString manOutput;
10978  bool &generateMan = Config_getBool("GENERATE_MAN");
10979  if (generateMan)
10980  manOutput = createOutputDirectory(outputDirectory,"MAN_OUTPUT","/man");
10981 
10982  //QCString sqlOutput;
10983  //bool &generateSql = Config_getBool("GENERATE_SQLITE3");
10984  //if (generateSql)
10985  // sqlOutput = createOutputDirectory(outputDirectory,"SQLITE3_OUTPUT","/sqlite3");
10986 
10987  if (Config_getBool("HAVE_DOT"))
10988  {
10989  QCString curFontPath = Config_getString("DOT_FONTPATH");
10990  if (curFontPath.isEmpty())
10991  {
10992  portable_getenv("DOTFONTPATH");
10993  QCString newFontPath = ".";
10994  if (!curFontPath.isEmpty())
10995  {
10996  newFontPath+=portable_pathListSeparator();
10997  newFontPath+=curFontPath;
10998  }
10999  portable_setenv("DOTFONTPATH",newFontPath);
11000  }
11001  else
11002  {
11003  portable_setenv("DOTFONTPATH",curFontPath);
11004  }
11005  }
11006 
11007 
11008 
11009  /**************************************************************************
11010  * Handle layout file *
11011  **************************************************************************/
11012 
11014  QCString &layoutFileName = Config_getString("LAYOUT_FILE");
11015  bool defaultLayoutUsed = FALSE;
11016  if (layoutFileName.isEmpty())
11017  {
11018  layoutFileName = "DoxygenLayout.xml";
11019  defaultLayoutUsed = TRUE;
11020  }
11021 
11022  QFile layoutFile(layoutFileName);
11023  if (layoutFile.open(IO_ReadOnly))
11024  {
11025  msg("Parsing layout file %s...\n",layoutFileName.data());
11026  QTextStream t(&layoutFile);
11027  t.setEncoding(QTextStream::Latin1);
11028  LayoutDocManager::instance().parse(t,layoutFileName);
11029  }
11030  else if (!defaultLayoutUsed)
11031  {
11032  warn_uncond("failed to open layout file '%s' for reading!\n",layoutFileName.data());
11033  }
11034 
11035  /**************************************************************************
11036  * Read and preprocess input *
11037  **************************************************************************/
11038 
11039  // prevent search in the output directories
11040  QStrList &exclPatterns = Config_getList("EXCLUDE_PATTERNS");
11041  if (generateHtml) exclPatterns.append(htmlOutput);
11042  if (generateDocbook) exclPatterns.append(docbookOutput);
11043  if (generateXml) exclPatterns.append(xmlOutput);
11044  if (generateLatex) exclPatterns.append(latexOutput);
11045  if (generateRtf) exclPatterns.append(rtfOutput);
11046  if (generateMan) exclPatterns.append(manOutput);
11047 
11048  searchInputFiles();
11049 
11050  // Notice: the order of the function calls below is very important!
11051 
11052  if (Config_getBool("GENERATE_HTML"))
11053  {
11055  }
11056 
11057  /**************************************************************************
11058  * Handle Tag Files *
11059  **************************************************************************/
11060 
11061  g_storage = new FileStorage;
11062  g_storage->setName(Doxygen::entryDBFileName);
11063  if (!g_storage->open(IO_WriteOnly))
11064  {
11065  err("Failed to create temporary storage file %s\n",
11066  Doxygen::entryDBFileName.data());
11067  exit(1);
11068  }
11069  Entry *root=new Entry;
11070  EntryNav *rootNav = new EntryNav(0,root);
11071  rootNav->setEntry(root);
11072  msg("Reading and parsing tag files\n");
11073 
11074  QStrList &tagFileList = Config_getList("TAGFILES");
11075  char *s=tagFileList.first();
11076  while (s)
11077  {
11078  readTagFile(root,s);
11079  root->createNavigationIndex(rootNav,g_storage,0);
11080  s=tagFileList.next();
11081  }
11082 
11083  /**************************************************************************
11084  * Parse source files *
11085  **************************************************************************/
11086 
11087  if (Config_getBool("BUILTIN_STL_SUPPORT"))
11088  {
11089  addSTLClasses(rootNav);
11090  }
11091 
11092  g_s.begin("Parsing files\n");
11093  parseFiles(root,rootNav);
11094  g_storage->close();
11095  g_s.end();
11096 
11097  // we are done with input scanning now, so free up the buffers used by flex
11098  // (can be around 4MB)
11099  preFreeScanner();
11100  scanFreeScanner();
11102 
11103  if (!g_storage->open(IO_ReadOnly))
11104  {
11105  err("Failed to open temporary storage file %s for reading",
11106  Doxygen::entryDBFileName.data());
11107  exit(1);
11108  }
11109 
11110  /**************************************************************************
11111  * Gather information *
11112  **************************************************************************/
11113 
11114  g_s.begin("Building group list...\n");
11115  buildGroupList(rootNav);
11116  organizeSubGroups(rootNav);
11117  g_s.end();
11118 
11119  g_s.begin("Building directory list...\n");
11120  buildDirectories();
11121  findDirDocumentation(rootNav);
11122  g_s.end();
11123 
11124  g_s.begin("Building namespace list...\n");
11125  buildNamespaceList(rootNav);
11126  findUsingDirectives(rootNav);
11127  g_s.end();
11128 
11129  g_s.begin("Building file list...\n");
11130  buildFileList(rootNav);
11131  g_s.end();
11132  //generateFileTree();
11133 
11134  g_s.begin("Building class list...\n");
11135  buildClassList(rootNav);
11136  g_s.end();
11137 
11138  g_s.begin("Associating documentation with classes...\n");
11139  buildClassDocList(rootNav);
11140 
11141  // build list of using declarations here (global list)
11142  buildListOfUsingDecls(rootNav);
11143  g_s.end();
11144 
11145  g_s.begin("Computing nesting relations for classes...\n");
11147  g_s.end();
11148  // 1.8.2-20121111: no longer add nested classes to the group as well
11149  //distributeClassGroupRelations();
11150 
11151  // calling buildClassList may result in cached relations that
11152  // become invalid after resolveClassNestingRelations(), that's why
11153  // we need to clear the cache here
11154  Doxygen::lookupCache->clear();
11155  // we don't need the list of using declaration anymore
11156  g_usingDeclarations.clear();
11157 
11158  g_s.begin("Building example list...\n");
11159  buildExampleList(rootNav);
11160  g_s.end();
11161 
11162  g_s.begin("Searching for enumerations...\n");
11163  findEnums(rootNav);
11164  g_s.end();
11165 
11166  // Since buildVarList calls isVarWithConstructor
11167  // and this calls getResolvedClass we need to process
11168  // typedefs first so the relations between classes via typedefs
11169  // are properly resolved. See bug 536385 for an example.
11170  g_s.begin("Searching for documented typedefs...\n");
11171  buildTypedefList(rootNav);
11172  g_s.end();
11173 
11174  g_s.begin("Searching for members imported via using declarations...\n");
11175  findUsingDeclImports(rootNav);
11176  // this should be after buildTypedefList in order to properly import
11177  // used typedefs
11178  findUsingDeclarations(rootNav);
11179  g_s.end();
11180 
11181  g_s.begin("Searching for included using directives...\n");
11183  g_s.end();
11184 
11185  g_s.begin("Searching for documented variables...\n");
11186  buildVarList(rootNav);
11187  g_s.end();
11188 
11189  g_s.begin("Building interface member list...\n");
11190  buildInterfaceAndServiceList(rootNav); // UNO IDL
11191 
11192  g_s.begin("Building member list...\n"); // using class info only !
11193  buildFunctionList(rootNav);
11194  g_s.end();
11195 
11196  g_s.begin("Searching for friends...\n");
11197  findFriends();
11198  g_s.end();
11199 
11200  g_s.begin("Searching for documented defines...\n");
11201  findDefineDocumentation(rootNav);
11202  g_s.end();
11203 
11204  g_s.begin("Computing class inheritance relations...\n");
11205  findClassEntries(rootNav);
11207  g_s.end();
11208 
11209  g_s.begin("Computing class usage relations...\n");
11211  g_s.end();
11212 
11213  if (Config_getBool("INLINE_SIMPLE_STRUCTS"))
11214  {
11215  g_s.begin("Searching for tag less structs...\n");
11217  g_s.end();
11218  }
11219 
11220  g_s.begin("Flushing cached template relations that have become invalid...\n");
11222  g_s.end();
11223 
11224  g_s.begin("Creating members for template instances...\n");
11226  g_s.end();
11227 
11228  g_s.begin("Computing class relations...\n");
11231  if (Config_getBool("OPTIMIZE_OUTPUT_VHDL"))
11232  {
11234  }
11236  g_classEntries.clear();
11237  g_s.end();
11238 
11239  g_s.begin("Add enum values to enums...\n");
11240  addEnumValuesToEnums(rootNav);
11241  findEnumDocumentation(rootNav);
11242  g_s.end();
11243 
11244  g_s.begin("Searching for member function documentation...\n");
11245  findObjCMethodDefinitions(rootNav);
11246  findMemberDocumentation(rootNav); // may introduce new members !
11247 
11250  g_s.end();
11251 
11252  g_s.begin("Building page list...\n");
11253  buildPageList(rootNav);
11254  g_s.end();
11255 
11256  g_s.begin("Search for main page...\n");
11257  findMainPage(rootNav);
11258  findMainPageTagFiles(rootNav);
11259  g_s.end();
11260 
11261  g_s.begin("Computing page relations...\n");
11262  computePageRelations(rootNav);
11264  g_s.end();
11265 
11266  g_s.begin("Determining the scope of groups...\n");
11267  findGroupScope(rootNav);
11268  g_s.end();
11269 
11270  g_s.begin("Sorting lists...\n");
11271  Doxygen::memberNameSDict->sort();
11272  Doxygen::functionNameSDict->sort();
11273  Doxygen::hiddenClasses->sort();
11274  Doxygen::classSDict->sort();
11275  g_s.end();
11276 
11277  msg("Freeing entry tree\n");
11278  delete rootNav;
11279  g_storage->close();
11280  delete g_storage;
11281  g_storage=0;
11282 
11283  QDir thisDir;
11284  thisDir.remove(Doxygen::entryDBFileName);
11285 
11286  g_s.begin("Determining which enums are documented\n");
11288  g_s.end();
11289 
11290  g_s.begin("Computing member relations...\n");
11291  mergeCategories();
11293  g_s.end();
11294 
11295  g_s.begin("Building full member lists recursively...\n");
11297  g_s.end();
11298 
11299  g_s.begin("Adding members to member groups.\n");
11301  g_s.end();
11302 
11303  if (Config_getBool("DISTRIBUTE_GROUP_DOC"))
11304  {
11305  g_s.begin("Distributing member group documentation.\n");
11307  g_s.end();
11308  }
11309 
11310  g_s.begin("Computing member references...\n");
11312  g_s.end();
11313 
11314  if (Config_getBool("INHERIT_DOCS"))
11315  {
11316  g_s.begin("Inheriting documentation...\n");
11318  g_s.end();
11319  }
11320 
11321  // compute the shortest possible names of all files
11322  // without losing the uniqueness of the file names.
11323  g_s.begin("Generating disk names...\n");
11324  Doxygen::inputNameList->generateDiskNames();
11325  g_s.end();
11326 
11327  g_s.begin("Adding source references...\n");
11329  g_s.end();
11330 
11331  g_s.begin("Adding xrefitems...\n");
11334  g_s.end();
11335 
11336  g_s.begin("Sorting member lists...\n");
11337  sortMemberLists();
11338  g_s.end();
11339 
11340  if (Config_getBool("DIRECTORY_GRAPH"))
11341  {
11342  g_s.begin("Computing dependencies between directories...\n");
11344  g_s.end();
11345  }
11346 
11347  //g_s.begin("Resolving citations...\n");
11348  //Doxygen::citeDict->resolve();
11349 
11350  g_s.begin("Generating citations page...\n");
11351  Doxygen::citeDict->generatePage();
11352  g_s.end();
11353 
11354  g_s.begin("Counting data structures...\n");
11356  g_s.end();
11357 
11358  g_s.begin("Resolving user defined references...\n");
11360  g_s.end();
11361 
11362  g_s.begin("Finding anchors and sections in the documentation...\n");
11364  g_s.end();
11365 
11366  g_s.begin("Transferring function references...\n");
11368  g_s.end();
11369 
11370  g_s.begin("Combining using relations...\n");
11372  g_s.end();
11373 
11374  g_s.begin("Adding members to index pages...\n");
11376  g_s.end();
11377 }
11378 
11380 {
11381  /**************************************************************************
11382  * Initialize output generators *
11383  **************************************************************************/
11384 
11385  /// add extra languages for which we can only produce syntax highlighted code
11387 
11388  //// dump all symbols
11389  if (g_dumpSymbolMap)
11390  {
11391  dumpSymbolMap();
11392  exit(0);
11393  }
11394 
11396 
11397  bool generateHtml = Config_getBool("GENERATE_HTML");
11398  bool generateLatex = Config_getBool("GENERATE_LATEX");
11399  bool generateMan = Config_getBool("GENERATE_MAN");
11400  bool generateRtf = Config_getBool("GENERATE_RTF");
11401 
11402 
11403  g_outputList = new OutputList(TRUE);
11404  if (generateHtml)
11405  {
11406  g_outputList->add(new HtmlGenerator);
11408 
11409  // add HTML indexers that are enabled
11410  bool generateHtmlHelp = Config_getBool("GENERATE_HTMLHELP");
11411  bool generateEclipseHelp = Config_getBool("GENERATE_ECLIPSEHELP");
11412  bool generateQhp = Config_getBool("GENERATE_QHP");
11413  bool generateTreeView = Config_getBool("GENERATE_TREEVIEW");
11414  bool generateDocSet = Config_getBool("GENERATE_DOCSET");
11415  if (generateEclipseHelp) Doxygen::indexList->addIndex(new EclipseHelp);
11416  if (generateHtmlHelp) Doxygen::indexList->addIndex(new HtmlHelp);
11417  if (generateQhp) Doxygen::indexList->addIndex(new Qhp);
11418  if (generateTreeView) Doxygen::indexList->addIndex(new FTVHelp(TRUE));
11419  if (generateDocSet) Doxygen::indexList->addIndex(new DocSets);
11420  Doxygen::indexList->initialize();
11422  }
11423  if (generateLatex)
11424  {
11425  g_outputList->add(new LatexGenerator);
11427  }
11428  if (generateMan)
11429  {
11430  g_outputList->add(new ManGenerator);
11432  }
11433  if (generateRtf)
11434  {
11435  g_outputList->add(new RTFGenerator);
11437  }
11438  if (Config_getBool("USE_HTAGS"))
11439  {
11441  QCString htmldir = Config_getString("HTML_OUTPUT");
11442  if (!Htags::execute(htmldir))
11443  err("USE_HTAGS is YES but htags(1) failed. \n");
11444  if (!Htags::loadFilemap(htmldir))
11445  err("htags(1) ended normally but failed to load the filemap. \n");
11446  }
11447 
11448  /**************************************************************************
11449  * Generate documentation *
11450  **************************************************************************/
11451 
11452  if (generateHtml) writeDoxFont(Config_getString("HTML_OUTPUT"));
11453  if (generateLatex) writeDoxFont(Config_getString("LATEX_OUTPUT"));
11454  if (generateRtf) writeDoxFont(Config_getString("RTF_OUTPUT"));
11455 
11456  g_s.begin("Generating style sheet...\n");
11457  //printf("writing style info\n");
11458  g_outputList->writeStyleInfo(0); // write first part
11459  g_s.end();
11460 
11461  static bool searchEngine = Config_getBool("SEARCHENGINE");
11462  static bool serverBasedSearch = Config_getBool("SERVER_BASED_SEARCH");
11463 
11464  g_s.begin("Generating search indices...\n");
11465  if (searchEngine && !serverBasedSearch && (generateHtml || g_useOutputTemplate))
11466  {
11468  }
11469 
11470  // generate search indices (need to do this before writing other HTML
11471  // pages as these contain a drop down menu with options depending on
11472  // what categories we find in this function.
11473  if (generateHtml && searchEngine)
11474  {
11475  QCString searchDirName = Config_getString("HTML_OUTPUT")+"/search";
11476  QDir searchDir(searchDirName);
11477  if (!searchDir.exists() && !searchDir.mkdir(searchDirName))
11478  {
11479  err("Could not create search results directory '%s' $PWD='%s'\n",
11480  searchDirName.data(),QDir::currentDirPath().data());
11481  exit(1);
11482  }
11483  HtmlGenerator::writeSearchData(searchDirName);
11484  if (!serverBasedSearch) // client side search index
11485  {
11487  }
11488  }
11489  g_s.end();
11490 
11491  g_s.begin("Generating example documentation...\n");
11493  g_s.end();
11494 
11495  if (!Htags::useHtags)
11496  {
11497  g_s.begin("Generating file sources...\n");
11499  g_s.end();
11500  }
11501 
11502  g_s.begin("Generating file documentation...\n");
11503  generateFileDocs();
11504  g_s.end();
11505 
11506  g_s.begin("Generating page documentation...\n");
11507  generatePageDocs();
11508  g_s.end();
11509 
11510  g_s.begin("Generating group documentation...\n");
11512  g_s.end();
11513 
11514  g_s.begin("Generating class documentation...\n");
11516  g_s.end();
11517 
11518  g_s.begin("Generating namespace index...\n");
11520  g_s.end();
11521 
11522  if (Config_getBool("GENERATE_LEGEND"))
11523  {
11524  g_s.begin("Generating graph info page...\n");
11525  writeGraphInfo(*g_outputList);
11526  g_s.end();
11527  }
11528 
11529  g_s.begin("Generating directory documentation...\n");
11530  generateDirDocs(*g_outputList);
11531  g_s.end();
11532 
11533  if (Doxygen::formulaList->count()>0 && generateHtml
11534  && !Config_getBool("USE_MATHJAX"))
11535  {
11536  g_s.begin("Generating bitmaps for formulas in HTML...\n");
11537  Doxygen::formulaList->generateBitmaps(Config_getString("HTML_OUTPUT"));
11538  g_s.end();
11539  }
11540 
11541  if (Config_getBool("SORT_GROUP_NAMES"))
11542  {
11543  Doxygen::groupSDict->sort();
11544  GroupSDict::Iterator gli(*Doxygen::groupSDict);
11545  GroupDef *gd;
11546  for (gli.toFirst();(gd=gli.current());++gli)
11547  {
11548  gd->sortSubGroups();
11549  }
11550  }
11551 
11552  if (g_outputList->count()>0)
11553  {
11554  writeIndexHierarchy(*g_outputList);
11555  }
11556 
11557  g_s.begin("finalizing index lists...\n");
11558  Doxygen::indexList->finalize();
11559  g_s.end();
11560 
11561  g_s.begin("writing tag file...\n");
11562  writeTagFile();
11563  g_s.end();
11564 
11565  if (Config_getBool("DOT_CLEANUP"))
11566  {
11567  if (generateHtml)
11568  removeDoxFont(Config_getString("HTML_OUTPUT"));
11569  if (generateRtf)
11570  removeDoxFont(Config_getString("RTF_OUTPUT"));
11571  if (generateLatex)
11572  removeDoxFont(Config_getString("LATEX_OUTPUT"));
11573  }
11574 
11575  if (Config_getBool("GENERATE_XML"))
11576  {
11577  g_s.begin("Generating XML output...\n");
11579  generateXML();
11581  g_s.end();
11582  }
11583  if (USE_SQLITE3)
11584  {
11585  g_s.begin("Generating SQLITE3 output...\n");
11586  generateSqlite3();
11587  g_s.end();
11588  }
11589 
11590  if (Config_getBool("GENERATE_DOCBOOK"))
11591  {
11592  g_s.begin("Generating Docbook output...\n");
11593  generateDocbook();
11594  g_s.end();
11595  }
11596 
11597  if (Config_getBool("GENERATE_AUTOGEN_DEF"))
11598  {
11599  g_s.begin("Generating AutoGen DEF output...\n");
11600  generateDEF();
11601  g_s.end();
11602  }
11603  if (Config_getBool("GENERATE_PERLMOD"))
11604  {
11605  g_s.begin("Generating Perl module output...\n");
11606  generatePerlMod();
11607  g_s.end();
11608  }
11609  if (generateHtml && searchEngine && serverBasedSearch)
11610  {
11611  g_s.begin("Generating search index\n");
11612  if (Doxygen::searchIndex->kind()==SearchIndexIntf::Internal) // write own search index
11613  {
11615  Doxygen::searchIndex->write(Config_getString("HTML_OUTPUT")+"/search/search.idx");
11616  }
11617  else // write data for external search index
11618  {
11620  QCString searchDataFile = Config_getString("SEARCHDATA_FILE");
11621  if (searchDataFile.isEmpty())
11622  {
11623  searchDataFile="searchdata.xml";
11624  }
11625  if (!portable_isAbsolutePath(searchDataFile))
11626  {
11627  searchDataFile.prepend(Config_getString("OUTPUT_DIRECTORY")+"/");
11628  }
11629  Doxygen::searchIndex->write(searchDataFile);
11630  }
11631  g_s.end();
11632  }
11633 
11635 
11636  if (generateRtf)
11637  {
11638  g_s.begin("Combining RTF output...\n");
11639  if (!RTFGenerator::preProcessFileInplace(Config_getString("RTF_OUTPUT"),"refman.rtf"))
11640  {
11641  err("An error occurred during post-processing the RTF files!\n");
11642  }
11643  g_s.end();
11644  }
11645 
11646  if (Config_getBool("HAVE_DOT"))
11647  {
11648  g_s.begin("Running dot...\n");
11650  g_s.end();
11651  }
11652 
11653  // copy static stuff
11654  if (generateHtml)
11655  {
11657  copyStyleSheet();
11658  copyLogo();
11659  copyExtraFiles("HTML_EXTRA_FILES","HTML_OUTPUT");
11660  }
11661  if (generateLatex)
11662  {
11664  copyExtraFiles("LATEX_EXTRA_FILES","LATEX_OUTPUT");
11665  }
11666 
11667  if (generateHtml &&
11668  Config_getBool("GENERATE_HTMLHELP") &&
11669  !Config_getString("HHC_LOCATION").isEmpty())
11670  {
11671  g_s.begin("Running html help compiler...\n");
11672  QString oldDir = QDir::currentDirPath();
11673  QDir::setCurrent(Config_getString("HTML_OUTPUT"));
11675  if (portable_system(Config_getString("HHC_LOCATION"), "index.hhp", Debug::isFlagSet(Debug::ExtCmd)))
11676  {
11677  err("failed to run html help compiler on index.hhp\n");
11678  }
11680  QDir::setCurrent(oldDir);
11681  g_s.end();
11682  }
11683  if ( generateHtml &&
11684  Config_getBool("GENERATE_QHP") &&
11685  !Config_getString("QHG_LOCATION").isEmpty())
11686  {
11687  g_s.begin("Running qhelpgenerator...\n");
11688  QCString const qhpFileName = Qhp::getQhpFileName();
11689  QCString const qchFileName = getQchFileName();
11690 
11691  QCString const args = QCString().sprintf("%s -o \"%s\"", qhpFileName.data(), qchFileName.data());
11692  QString const oldDir = QDir::currentDirPath();
11693  QDir::setCurrent(Config_getString("HTML_OUTPUT"));
11695  if (portable_system(Config_getString("QHG_LOCATION"), args.data(), FALSE))
11696  {
11697  err("failed to run qhelpgenerator on index.qhp\n");
11698  }
11700  QDir::setCurrent(oldDir);
11701  g_s.end();
11702  }
11703 
11704  int cacheParam;
11705  msg("lookup cache used %d/%d hits=%d misses=%d\n",
11706  Doxygen::lookupCache->count(),
11707  Doxygen::lookupCache->size(),
11708  Doxygen::lookupCache->hits(),
11709  Doxygen::lookupCache->misses());
11710  cacheParam = computeIdealCacheParam(Doxygen::lookupCache->misses()*2/3); // part of the cache is flushed, hence the 2/3 correction factor
11711  if (cacheParam>Config_getInt("LOOKUP_CACHE_SIZE"))
11712  {
11713  msg("Note: based on cache misses the ideal setting for LOOKUP_CACHE_SIZE is %d at the cost of higher memory usage.\n",cacheParam);
11714  }
11715 
11717  {
11718  msg("Total elapsed time: %.3f seconds\n(of which %.3f seconds waiting for external tools to finish)\n",
11719  ((double)Doxygen::runningTime.elapsed())/1000.0,
11721  );
11722  g_s.print();
11723  }
11724  else
11725  {
11726  msg("finished...\n");
11727  }
11728 
11729 
11730  /**************************************************************************
11731  * Start cleaning up *
11732  **************************************************************************/
11733 
11734  cleanUpDoxygen();
11735 
11737  Doxygen::symbolStorage->close();
11738  QDir thisDir;
11739  thisDir.remove(Doxygen::objDBFileName);
11740  Config::deleteInstance();
11742  delete Doxygen::symbolMap;
11743  delete Doxygen::clangUsrMap;
11744  delete Doxygen::symbolStorage;
11746 }
11747 
SrcLangExt lang() const
Definition: entry.h:348
static QCString name
Definition: declinfo.cpp:673
bool callGraph
do we need to draw the call graph?
Definition: entry.h:249
static QDict< RefList > * xrefLists
Definition: doxygen.h:129
static bool markdownSupport
Definition: doxygen.h:153
Traverses directory structures and contents in a platform-independent way.
Definition: qdir.h:52
Definition: types.h:61
CompoundType compoundType() const
Definition: classdef.cpp:4394
QCString type
Definition: arguments.h:67
static void findGroupScope(EntryNav *rootNav)
Definition: doxygen.cpp:698
static QString cleanDirPath(const QString &dirPath)
Definition: qdir.cpp:1077
static CiteDict * citeDict
Definition: doxygen.h:146
type * toFirst()
Definition: qcache.h:135
bool resize(uint newlen)
Definition: qcstring.h:225
void addMembersToTemplateInstance(ClassDef *cd, const char *templSpec)
Definition: classdef.cpp:3771
static GroupSDict * groupSDict
Definition: doxygen.h:119
static MemberNameSDict * functionNameSDict
Definition: doxygen.h:116
static SDict< DirRelation > dirRelations
Definition: doxygen.h:140
QCString includeName
include name (3 arg of \class)
Definition: entry.h:259
QCString docFile() const
Definition: types.h:38
static void addVariable(EntryNav *rootNav, int isFuncPtr=-1)
Definition: doxygen.cpp:2808
bool portable_isAbsolutePath(const char *fileName)
Definition: portable.cpp:434
void portable_sysTimerStop()
Definition: portable.cpp:415
uint count() const
Definition: outputlist.h:61
void preprocessFile(const char *fileName, BufStr &input, BufStr &output)
bool isDocsForDefinition() const
Definition: memberdef.cpp:4482
static void expandAliases()
Definition: doxygen.cpp:9784
ParserInterface * getParser(const char *extension)
Definition: parserintf.h:191
void clear()
Definition: sortdict.h:276
static void transferFunctionReferences()
Definition: doxygen.cpp:3958
void begin(const char *name)
Definition: doxygen.cpp:216
void setRelatedAlso(ClassDef *cd)
Definition: memberdef.cpp:4713
static QStrList includePathList
Definition: config.cpp:1047
void writeTagFile(FTextStream &)
FileDef * getFileDef() const
Definition: classdef.cpp:4429
void endFile(OutputList &ol, bool skipNavIndex, bool skipEndContents, const QCString &navPath)
Definition: index.cpp:263
EntryNav * parent() const
Definition: entry.h:353
static ClassDef::CompoundType convertToCompoundType(int section, uint64 specifier)
Definition: doxygen.cpp:1179
virtual void startTranslationUnit(const char *fileName)=0
static const uint64 Published
Definition: entry.h:182
static void addSourceReferences()
Definition: doxygen.cpp:7986
void setDefinition(const char *d)
Definition: memberdef.cpp:4619
void insertEnumField(MemberDef *md)
Definition: memberdef.cpp:909
This class represents an function or template argument list.
Definition: arguments.h:82
void generateOutputViaTemplate()
Definition: context.cpp:10068
type * current() const
Definition: qcache.h:138
bool isTypedefValCached() const
Definition: memberdef.cpp:4572
static void init()
Definition: mangen.cpp:108
const char * baseClass1
Definition: doxygen.cpp:326
QCString stripWhiteSpace() const
Definition: qcstring.cpp:295
bool isLinkableInProject() const
Definition: classdef.cpp:2707
int readFileOrDirectory(const char *s, FileNameList *fnList, FileNameDict *fnDict, StringDict *exclDict, QStrList *patList, QStrList *exclPatList, StringList *resultList, StringDict *resultDict, bool recursive, bool errorIfNotExist, QDict< void > *killDict, QDict< void > *paths)
Definition: doxygen.cpp:9659
static QCString scope
Definition: declinfo.cpp:668
bool proto
prototype ?
Definition: entry.h:247
static QCString aliasName
Definition: scanner.cpp:10889
void setFromAnonymousMember(MemberDef *m)
Definition: memberdef.cpp:4755
void setEnumBaseType(const QCString &type)
Definition: memberdef.cpp:4816
void setReimplements(MemberDef *md)
Definition: memberdef.cpp:860
MemberDef * reimplements() const
Definition: memberdef.cpp:878
bool matchArguments2(Definition *srcScope, FileDef *srcFileScope, ArgumentList *srcAl, Definition *dstScope, FileDef *dstFileScope, ArgumentList *dstAl, bool checkCV)
Definition: util.cpp:3647
Definition: types.h:38
uint64 spec
class/member specifiers
Definition: entry.h:243
static bool gatherDefines
Definition: doxygen.h:147
void insertMember(MemberDef *md)
Definition: filedef.cpp:1100
QList< Entry > entry
void combineDeclarationAndDefinition(MemberDef *mdec, MemberDef *mdef)
Definition: memberdef.cpp:4946
bool stat
static ?
Definition: entry.h:245
static void generateGroupDocs()
Definition: doxygen.cpp:9007
void statistics() const
Definition: qintdict.h:69
static void writeStyleSheetFile(QFile &f)
Definition: latexgen.cpp:788
bool iterators
Definition: doxygen.cpp:333
static void createTemplateInstanceMembers()
Definition: doxygen.cpp:7745
BaseClassList * subClasses() const
Definition: classdef.cpp:4404
void addDirToGroups(Entry *root, DirDef *dd)
Definition: groupdef.cpp:1341
Definition: types.h:32
bool readInputFile(const char *fileName, BufStr &inBuf, bool filter, bool isSourceCode)
read a file name fileName and optionally filter and transcode it
Definition: util.cpp:7673
Definition: types.h:29
bool openOutputFile(const char *outFile, QFile &f)
Definition: util.cpp:8588
void setFromAnonymousScope(bool b)
Definition: memberdef.cpp:4750
void inSort(const char *key, const T *d)
Definition: sortdict.h:197
void setName(const char *name)
Definition: filestorage.h:40
static constexpr double g
Definition: Units.h:144
static PageSDict * exampleSDict
Definition: doxygen.h:101
static QCString result
bool isEmpty() const
Definition: qcstring.h:189
virtual bool remove(const QString &fileName, bool acceptAbsPath=TRUE)
Definition: qdir.cpp:915
static void writeFooterFile(QFile &f)
Definition: htmlgen.cpp:836
void initFileMemberIndices()
Definition: index.cpp:2396
static void mergeCategories()
Definition: doxygen.cpp:7769
void setTagInfo(TagInfo *i)
Definition: memberdef.cpp:3992
static void computeMemberReferences()
Definition: doxygen.cpp:5157
int documentedHtmlFiles
Definition: index.cpp:65
The QRegExp class provides pattern matching using regular expressions or wildcards.
Definition: qregexp.h:46
void generatePage()
Definition: reflist.cpp:140
void startFile(OutputList &ol, const char *name, const char *manName, const char *title, HighlightedItem hli, bool additionalIndices, const char *altSidebarName)
Definition: index.cpp:244
void addFileMemberNameToIndex(MemberDef *md)
Definition: index.cpp:2406
bool isFriend() const
Definition: memberdef.cpp:4175
void addUsedByClass(ClassDef *cd, const char *accessName, Protection prot)
Definition: classdef.cpp:3267
static void buildExampleList(EntryNav *rootNav)
Definition: doxygen.cpp:8918
void msg(const char *fmt,...)
Definition: message.cpp:107
static void writeExtensionsFile(QFile &file)
Definition: rtfgen.cpp:113
QCString title() const
Definition: pagedef.h:54
static const uint64 Mutable
Definition: entry.h:145
static void writeHeaderFile(QFile &f, const char *cssname)
Definition: htmlgen.cpp:829
static bool loadFilemap(const QCString &htmldir)
Definition: htags.cpp:105
void writeTagFile(FTextStream &)
Definition: classdef.cpp:1560
static void writeExternalSearchPage()
Definition: htmlgen.cpp:2281
class Statistics g_s
uint length() const
Definition: qcstring.h:195
static bool scopeIsTemplate(Definition *d)
Definition: doxygen.cpp:5621
static FileNameDict * includeNameDict
Definition: doxygen.h:105
void setBodyDef(FileDef *fd)
static void sortMemberLists()
Definition: doxygen.cpp:8066
void makeRelated()
Definition: memberdef.cpp:4681
void clear()
Definition: qcache.h:100
static ClassSDict * hiddenClasses
Definition: doxygen.h:100
int contains(char c, bool cs=TRUE) const
Definition: qcstring.cpp:153
void start()
Definition: qdatetime.cpp:949
void insertReimplementedBy(MemberDef *md)
Definition: memberdef.cpp:865
void append(const type *d)
Definition: qlist.h:73
void buildDirectories()
Definition: dirdef.cpp:872
static void parseFiles(Entry *root, EntryNav *rootNav)
parse the list of input files
Definition: doxygen.cpp:9387
void mergeArguments(ArgumentList *srcAl, ArgumentList *dstAl, bool forceNameOverwrite)
Definition: util.cpp:3732
static void organizeSubGroupsFiltered(EntryNav *rootNav, bool additional)
Definition: doxygen.cpp:723
virtual void setPath(const QString &path)
Definition: qdir.cpp:248
const char * portable_getenv(const char *variable)
Definition: portable.cpp:317
#define IO_WriteOnly
Definition: qiodevice.h:62
bool generateSourceFile() const
Definition: filedef.cpp:1396
static void writeStyleSheetFile(QFile &f)
Definition: htmlgen.cpp:823
void addMemberToGroups(Entry *root, MemberDef *md)
Definition: groupdef.cpp:1390
static void init()
Definition: latexgen.cpp:437
Definition: entry.h:63
Abstract interface for programming language parsers.
Definition: parserintf.h:38
int guessSection(const char *name)
Definition: util.cpp:315
virtual void setName(const char *name)
Definition: definition.cpp:396
Protection protection() const
Definition: memberdef.cpp:4120
QCString read
property read accessor
Definition: entry.h:271
QList< ListItemInfo > * xrefListItems() const
Definition: types.h:26
static void buildFileList(EntryNav *rootNav)
Definition: doxygen.cpp:766
static QCString htmlFileExtension
Definition: doxygen.h:130
static void writeTabData()
Additional initialization after indices have been created.
Definition: htmlgen.cpp:752
bool isPrototype() const
Definition: memberdef.cpp:4507
const char * baseClass2
Definition: doxygen.cpp:327
bool generateDoc(const char *fileName, int startLine, Definition *ctx, MemberDef *md, const QCString &docStr, bool indexWords, bool isExample, const char *exampleName=0, bool singleLine=FALSE, bool linkFromIndex=FALSE)
Definition: outputlist.cpp:131
static const uint64 ForwardDecl
Definition: entry.h:136
bool isForwardDeclared() const
Definition: classdef.cpp:4499
static Store * symbolStorage
Definition: doxygen.h:143
Python Language parser using state-based lexical scanning.
Definition: pyscanner.h:34
double portable_getSysElapsedTime()
Definition: portable.cpp:420
QCString inbodyDocumentation() const
bool visited
Definition: memberdef.h:398
void setLanguage(SrcLangExt lang)
void addClassMemberNameToIndex(MemberDef *md)
Definition: index.cpp:2264
type * first()
Definition: qinternallist.h:87
static void buildClassList(EntryNav *rootNav)
Definition: doxygen.cpp:1405
ArgumentList * templateArguments() const
Definition: classdef.cpp:4419
static FormulaDict * formulaDict
Definition: doxygen.h:122
void initDoxygen()
Definition: doxygen.cpp:9979
static const uint64 Exception
Definition: entry.h:128
bool generated
Definition: section.h:63
QCString defval
Definition: arguments.h:71
const char * bitfieldString() const
Definition: memberdef.cpp:4050
virtual void addInnerCompound(Definition *d)
void setAnchor()
Definition: memberdef.cpp:3334
char & at(uint i) const
Definition: qcstring.h:326
void setPageScope(Definition *d)
Definition: pagedef.h:63
void generateDiskNames()
Definition: filename.cpp:121
FileDef * getBodyDef() const
void convertCppComments(BufStr *inBuf, BufStr *outBuf, const char *fileName)
QCString listName() const
Definition: reflist.cpp:98
void setArtificial(bool b)
Tcl language parser using state-based lexical scanning.
Definition: tclscanner.h:28
QCString argListToString(ArgumentList *al, bool useCanonicalType, bool showDefVals)
Definition: util.cpp:2151
static bool execute(const QCString &htmldir)
Definition: htags.cpp:37
void setTemplateSpecialization(bool b)
Definition: memberdef.cpp:4676
static void printFlags(void)
Definition: debug.cpp:124
MemberNameInfoSDict * memberNameInfoSDict() const
Definition: classdef.cpp:4409
int briefLine
line number at which the brief desc. was found
Definition: entry.h:264
static int roundCount
Definition: scanner.cpp:10859
void addNamespaceToGroups(Entry *root, NamespaceDef *nd)
Definition: groupdef.cpp:1324
int open(const char *, int)
Opens a file descriptor.
Definition: types.h:35
virtual void setOuterScope(Definition *d)
void setTemplateBaseClassNames(QDict< int > *templateNames)
Definition: classdef.cpp:3747
void writeTagFile(FTextStream &t)
Definition: filedef.cpp:183
void readFormulaRepository()
Definition: doxygen.cpp:9751
void computeAnchors()
static DotManager * instance()
Definition: dot.cpp:1221
void findSectionsInDocumentation()
Definition: groupdef.cpp:117
bool isSource() const
Definition: filedef.h:102
C-like language parser using state-based lexical scanning.
Definition: scanner.h:29
const QCString & name() const
Definition: entry.h:350
void enableCallGraph(bool e)
Definition: memberdef.cpp:3923
QCString stripAnonymousNamespaceScope(const QCString &s)
Definition: util.cpp:218
bool isLinkableInProject() const
Definition: groupdef.cpp:1640
bool visited
Definition: filedef.h:184
NamespaceSDict * getUsedNamespaces() const
Definition: filedef.cpp:1251
static void resolveUserReferences()
Definition: doxygen.cpp:8825
int docLine
line number at which the documentation was found
Definition: entry.h:261
const bool FALSE
Definition: qglobal.h:370
static FileNameList * inputNameList
Definition: doxygen.h:109
bool isReference() const
Definition: classdef.cpp:3826
static void transferFunctionDocumentation()
Definition: doxygen.cpp:3927
void findSectionsInDocumentation()
void registerDefaultParser(ParserInterface *parser)
Definition: parserintf.h:155
static LayoutDocManager & instance()
Definition: layout.cpp:1359
Definition: types.h:26
ArgumentList * argList
member arguments as a list
Definition: entry.h:254
static OutputList * g_outputList
Definition: doxygen.cpp:178
static constexpr double fs
Definition: Units.h:100
static FormulaDict * formulaNameDict
Definition: doxygen.h:123
const char * name
Definition: doxygen.cpp:247
QCString label
Definition: section.h:56
void addSearchDir(const char *dir)
bool leftScopeMatch(const QCString &scope, const QCString &name)
Definition: util.cpp:1904
MemberList * enumFieldList() const
Definition: memberdef.cpp:4497
bool isLinkableInProject() const
Definition: memberdef.cpp:1150
static bool preProcessFileInplace(const char *path, const char *name)
Definition: rtfgen.cpp:2587
void setUsedOnly(bool b)
Definition: classdef.cpp:4574
static void buildVarList(EntryNav *rootNav)
Definition: doxygen.cpp:3051
QCString name
member name
Definition: entry.h:237
void setMemberGroupId(int id)
Definition: memberdef.cpp:4740
const std::string instance
static void dumpSymbol(FTextStream &t, Definition *d)
Definition: doxygen.cpp:9870
void writeSource(OutputList &ol, bool sameTu, QStrList &filesInSameTu)
Definition: filedef.cpp:912
int initLines
define/variable initializer lines to show
Definition: entry.h:244
void distributeMemberGroupDocumentation()
Definition: groupdef.cpp:107
static void flushCachedTemplateRelations()
Definition: doxygen.cpp:8346
type * at(uint i) const
Definition: qlist.h:94
void statistics()
Definition: doxygen.cpp:257
Store implementation based on a file. Writing is linear, after that the file is re-opened for reading...
Definition: filestorage.h:28
void parseSource(bool sameTu, QStrList &filesInSameTu)
Definition: filedef.cpp:1027
bool copyFile(const QCString &src, const QCString &dest)
Definition: util.cpp:7966
static QCString className
Definition: declinfo.cpp:669
void checkConfiguration()
Definition: doxygen.cpp:10493
void setNamespace(NamespaceDef *nd)
Definition: memberdef.cpp:3400
#define Config_getList(val)
Definition: config.cpp:662
void enableCallerGraph(bool e)
Definition: memberdef.cpp:3929
Definition: entry.h:50
static FileNameDict * inputNameDict
Definition: doxygen.h:108
static int subpageNestingLevel
Definition: doxygen.h:150
MemberType
Definition: types.h:195
static void findDirDocumentation(EntryNav *rootNav)
Definition: doxygen.cpp:8588
QCString left(uint len) const
Definition: qcstring.cpp:213
bool isDefine() const
Definition: memberdef.cpp:4170
static Definition * findScopeFromQualifiedName(Definition *startScope, const QCString &n, FileDef *fileScope, TagInfo *tagInfo)
Definition: doxygen.cpp:1060
bool stripPrefix(const char *prefix)
Definition: qcstring.cpp:201
const char * templType1
Definition: doxygen.cpp:328
MemberDef * memberDef
Definition: membername.h:62
The QString class provides an abstraction of Unicode text and the classic C null-terminated char arra...
Definition: qstring.h:350
void registerParser(const char *name, ParserInterface *parser)
Definition: parserintf.h:166
static const char * getArg(int argc, char **argv, int &optind)
Definition: doxygen.cpp:9967
static void parseFile(ParserInterface *parser, Entry *root, EntryNav *rootNav, FileDef *fd, const char *fn, bool sameTu, QStrList &filesInSameTu)
Definition: doxygen.cpp:9323
int briefLine() const
static bool suppressDocWarnings
Definition: doxygen.h:142
ClassDef * insertTemplateInstance(const QCString &fileName, int startLine, int startColumn, const QCString &templSpec, bool &freshInstance)
Definition: classdef.cpp:3702
void setGroupScope(Definition *d)
Definition: groupdef.h:91
void setPrototype(bool p)
Definition: memberdef.cpp:4735
virtual bool isReference() const
QCString getOverloadDocs()
Definition: util.cpp:5859
bool protectionLevelVisible(Protection prot)
Definition: util.cpp:8098
bool addClass(const ClassDef *def)
Definition: groupdef.cpp:149
Definition: qhp.h:23
Simplified and optimized version of QTextStream.
Definition: ftextstream.h:11
ClassDef * classDef
Definition: doxygen.h:84
static void resolveClassNestingRelations()
Definition: doxygen.cpp:1428
string dir
int find(char c, int index=0, bool cs=TRUE) const
Definition: qcstring.cpp:41
void generateDEF()
Definition: defgen.cpp:558
int count() const
Definition: sortdict.h:284
NamespaceSDict * getUsedNamespaces() const
bool isCSharp() const
Definition: classdef.cpp:4509
bool isVariable() const
Definition: memberdef.cpp:4140
void setGroupTitle(const char *newtitle)
Definition: groupdef.cpp:91
void setClassName(const char *name)
Definition: classdef.cpp:3926
QCString id
libclang id
Definition: entry.h:290
void setReadAccessor(const char *r)
Definition: memberdef.cpp:4666
void findSectionsInDocumentation()
Definition: pagedef.cpp:47
static void stopDoxygen(int)
Definition: doxygen.cpp:10587
void findSectionsInDocumentation()
Definition: classdef.cpp:758
static bool findTemplateInstanceRelation(Entry *root, Definition *context, ClassDef *templateClass, const QCString &templSpec, QDict< int > *templateNames, bool isArtificial)
Definition: doxygen.cpp:4406
static void combineUsingRelations()
Definition: doxygen.cpp:8184
virtual QCString getOutputFileBase() const =0
const char * groupTitle() const
Definition: groupdef.h:54
virtual void finishTranslationUnit()=0
void warn_undoc(const char *file, int line, const char *fmt,...)
Definition: message.cpp:202
void getAllIncludeFilesRecursively(QStrList &incFiles) const
Definition: filedef.cpp:1904
#define RECURSE_ENTRYTREE(func, var)
Definition: doxygen.cpp:105
bool hasCallerGraph() const
Definition: memberdef.cpp:4562
GroupList * partOfGroups() const
void append(const char *key, const T *d)
Definition: sortdict.h:135
Fortran language parser using state-based lexical scanning.
const char * templName2
Definition: doxygen.cpp:331
static QCString args
Definition: declinfo.cpp:674
void mergeCategory(ClassDef *category)
Definition: classdef.cpp:3095
bool isObjCProperty() const
Definition: memberdef.cpp:3962
SrcLangExt
Definition: types.h:41
static QStrList * l
Definition: config.cpp:1044
static FileNameDict * exampleNameDict
Definition: doxygen.h:106
bool hidden
does this represent an entity that is hidden from the output
Definition: entry.h:287
void setInheritsDocsFrom(MemberDef *md)
Definition: memberdef.cpp:4703
void resetCCodeParserState()
Definition: code.cpp:16382
virtual QString absPath() const
Definition: qdir.cpp:276
void setEntry(Entry *e)
Definition: entry.cpp:425
TagInfo * tagInfo() const
Definition: entry.h:351
void parse(QTextStream &t, const char *fileName)
Definition: layout.cpp:1385
Definition: types.h:32
int findRev(char c, int index=-1, bool cs=TRUE) const
Definition: qcstring.cpp:95
Entry * parent() const
Definition: entry.h:205
void cleanUpPreprocessor()
void finishParsing()
Definition: filedef.cpp:1066
static void copyLatexStyleSheet()
Definition: doxygen.cpp:9190
Definition: types.h:29
bool isBaseClass(ClassDef *bcd, bool followInstances, int level=0)
Definition: classdef.cpp:2777
void removeDoxFont(const char *dir)
Definition: logos.cpp:1981
virtual void setInbodyDocumentation(const char *d, const char *docFile, int docLine)
Definition: definition.cpp:711
int mGrpId
member group id
Definition: entry.h:278
ClassSDict * getClassSDict()
Definition: classdef.cpp:4389
int section() const
Definition: entry.h:347
QCString removeAnonymousScopes(const QCString &s)
Definition: util.cpp:164
void addMembersToMemberGroup()
Definition: filedef.cpp:1071
void setExplicitExternal(bool b)
Definition: memberdef.cpp:4661
static void generateExampleDocs()
Definition: doxygen.cpp:8975
static int computeIdealCacheParam(uint v)
Definition: doxygen.cpp:10132
void writeDoxFont(const char *dir)
Definition: logos.cpp:1968
void initDefaultExtensionMapping()
Definition: util.cpp:6999
static QDict< EntryNav > g_classEntries(1009)
void sortSubGroups()
Definition: groupdef.cpp:1635
void clearAll()
Definition: doxygen.cpp:185
void setFileName(const char *name)
Definition: pagedef.cpp:66
static StringDict aliasDict
Definition: doxygen.h:125
static void devUsage()
Definition: doxygen.cpp:9922
MemberSDict * getReferencesMembers() const
QCString getDefFileName() const
QListIterator< Argument > ArgumentListIterator
Definition: arguments.h:113
void writeMemberList(OutputList &ol)
Definition: classdef.cpp:2250
QList< ArgumentList > * tArgLists
template argument declarations
Definition: entry.h:255
void computeAnchors()
Definition: classdef.cpp:719
QCString copy() const
Definition: qcstring.h:250
static void inheritDocumentation()
Definition: doxygen.cpp:8146
static QDict< void > inputPaths
Definition: doxygen.h:107
static void buildTypedefList(EntryNav *rootNav)
Definition: doxygen.cpp:3023
int startColumn
start column of entry in the source
Definition: entry.h:284
void portable_sysTimerStart()
Definition: portable.cpp:410
ClassDef * getClass(const char *n)
Definition: util.cpp:472
const QList< EntryNav > * children() const
Definition: entry.h:352
void invalidateTypedefValCache()
Definition: memberdef.cpp:4781
QCString displayName(bool=TRUE) const
Definition: dirdef.h:56
bool constSpecifier
Definition: arguments.h:99
void adjustConfiguration()
Definition: doxygen.cpp:10504
bool isFile() const
void sortMemberLists()
Definition: classdef.cpp:4047
const char * memberName() const
Definition: membername.h:31
#define IO_ReadOnly
Definition: qiodevice.h:61
int getDefColumn() const
Definition: definition.h:191
void setAutoDelete(bool val)
Definition: sortdict.h:222
void releaseEntry()
Definition: entry.cpp:415
static const uint64 Explicit
Definition: entry.h:144
static const uint64 Optional
Definition: entry.h:159
static bool insideMainPage
Definition: doxygen.h:104
QString readLink() const
static bool parseSourcesNeeded
Definition: doxygen.h:131
#define Config_getEnum(val)
Definition: config.cpp:663
QString absFilePath() const
#define QMIN(a, b)
Definition: qglobal.h:391
bool hasCallGraph() const
Definition: memberdef.cpp:4557
void writeDocumentation(OutputList &ol)
Definition: groupdef.cpp:1073
static void transferRelatedFunctionDocumentation()
Definition: doxygen.cpp:4050
void mergeMemberSpecifiers(uint64 s)
Definition: memberdef.cpp:4643
bool exists(std::string path)
#define Config_getInt(val)
Definition: config.cpp:661
FileDef * getFileDef() const
Definition: memberdef.cpp:4075
decltype(auto) constexpr size(T &&obj)
ADL-aware version of std::size.
Definition: StdUtils.h:92
Relationship
Definition: types.h:38
static NamespaceSDict * namespaceSDict
Definition: doxygen.h:120
static void copyExtraFiles(const QCString &filesOption, const QCString &outputOption)
Definition: doxygen.cpp:9278
void distributeMemberGroupDocumentation()
Definition: filedef.cpp:135
QCString substituteTemplateArgumentsInString(const QCString &name, ArgumentList *formalArgs, ArgumentList *actualArgs)
Definition: util.cpp:6099
The QTime class provides clock time functions.
Definition: qdatetime.h:108
static NamespaceDef * globalScope
Definition: doxygen.h:128
bool rightScopeMatch(const QCString &scope, const QCString &name)
Definition: util.cpp:1893
static const uint64 Inline
Definition: entry.h:143
static void buildNamespaceList(EntryNav *rootNav)
Definition: doxygen.cpp:1711
void computeDirDependencies()
Definition: dirdef.cpp:924
const char * templType2
Definition: doxygen.cpp:330
static ParserManager * parserManager
Definition: doxygen.h:141
void setBitfields(const char *s)
Definition: memberdef.cpp:4648
QCString stripTemplateSpecifiersFromScope(const QCString &fullName, bool parentOnly, QCString *pLastScopeStripped)
Definition: util.cpp:6226
list files
Definition: languages.py:9
ClassDef * templateMaster() const
Definition: classdef.cpp:4439
virtual DefType definitionType() const =0
void addNamespaceMemberNameToIndex(MemberDef *md)
Definition: index.cpp:2349
QCString showFileDefMatches(const FileNameDict *fnDict, const char *n)
Definition: util.cpp:5058
Specifier virtualness(int count=0) const
Definition: memberdef.cpp:3560
void writeDocumentation(OutputList &ol)
Definition: filedef.cpp:654
def cli(ctx)
Definition: main.py:7
static const uint64 Strong
Definition: entry.h:165
This class contains the information about the argument of a function or template. ...
Definition: arguments.h:28
const char * typeString() const
Definition: memberdef.cpp:4035
QCString getLanguageSpecificSeparator(SrcLangExt lang, bool classScope)
Definition: util.cpp:8065
static void deleteAllCodecs()
Definition: qtextcodec.cpp:81
QCString tagName
Definition: entry.h:52
static void readTagFile(Entry *root, const char *tl)
Definition: doxygen.cpp:9154
bool isSymLink() const
uint count() const
Definition: qlist.h:66
static SrcLangExt language
Definition: scanner.cpp:10895
static StringDict tagDestinationDict
Definition: doxygen.h:124
static void writeHeaderFile(QFile &f)
Definition: latexgen.cpp:770
void setDefinitionTemplateParameterLists(QList< ArgumentList > *lists)
Definition: memberdef.cpp:1174
void makeImplementationDetail()
Definition: memberdef.cpp:4745
static void findMainPage(EntryNav *rootNav)
Definition: doxygen.cpp:8692
void distributeClassGroupRelations()
Definition: doxygen.cpp:1492
MemberSDict * getReferencedByMembers() const
bool findAndRemoveWord(QCString &s, const QCString &word)
Definition: util.cpp:6848
const char * data() const
Definition: qstring.h:542
void copyArgumentNames(MemberDef *bmd)
Definition: memberdef.cpp:4836
bool volatileSpecifier
Definition: arguments.h:101
virtual bool mkdir(const QString &dirName, bool acceptAbsPath=TRUE) const
Definition: qdir_unix.cpp:98
virtual QCString trMainPage()=0
static void copyLogo()
Definition: doxygen.cpp:9258
QAsciiDict< Entry > fn
virtual bool needsPreprocessing(const QCString &extension)=0
type * getLast() const
Definition: qlist.h:96
static SearchIndexIntf * searchIndex
Definition: doxygen.h:133
static void addSTLClasses(EntryNav *rootNav)
Definition: doxygen.cpp:451
stat(const char *n, double el)
Definition: doxygen.cpp:250
void insert(const QCString &key, ClassDef *cd)
Definition: classlist.cpp:163
static QCString funcTempList
Definition: declinfo.cpp:671
void setClassSpecifier(uint64 spec)
Definition: classdef.cpp:4704
Q_EXPORT uint qstrlen(const char *str)
Definition: qcstring.h:81
static FormulaList * formulaList
Definition: doxygen.h:121
static void findDefineDocumentation(EntryNav *rootNav)
Definition: doxygen.cpp:8444
static void findInheritedTemplateInstances()
Definition: doxygen.cpp:4994
static void addMembersToMemberGroup()
Definition: doxygen.cpp:8223
QCString includeFile
include file (2 arg of \class, must be unique)
Definition: entry.h:258
void insertMember(MemberDef *)
Definition: classdef.cpp:713
type * current() const
#define QMAX(a, b)
Definition: qglobal.h:390
bool subGrouping
automatically group class members?
Definition: entry.h:248
Definition: types.h:32
static void findIncludedUsingDirectives()
Definition: doxygen.cpp:2205
const QCString & name() const
Definition: definition.h:114
static QCString getQhpFileName()
Definition: qhp.cpp:280
static void computeClassRelations()
Definition: doxygen.cpp:5036
const double e
void readConfiguration(int argc, char **argv)
Definition: doxygen.cpp:10144
int getDefLine() const
Definition: definition.h:188
bool callerGraph
do we need to draw the caller graph?
Definition: entry.h:250
void end()
Definition: doxygen.cpp:223
void addMembersToMemberGroup()
bool isEnumValue() const
Definition: memberdef.cpp:4150
static bool isRecursiveBaseClass(const QCString &scope, const QCString &name)
Definition: doxygen.cpp:4491
int qstricmp(const char *str1, const char *str2)
Definition: qcstring.cpp:567
static void findEnumDocumentation(EntryNav *rootNav)
Definition: doxygen.cpp:7440
QList< Grouping > * groups
list of groups this entry belongs to
Definition: entry.h:280
FileDef * fileDef() const
Definition: entry.h:354
QGString initializer
initial value (for variables)
Definition: entry.h:257
void combineUsingRelations()
Definition: filedef.cpp:1688
void inSort(const type *d)
Definition: qlist.h:71
QCString inbodyFile
file in which the body doc was found
Definition: entry.h:268
QCString inbodyFile() const
static void processTagLessClasses(ClassDef *rootCd, ClassDef *cd, ClassDef *tagParentCd, const QCString &prefix, int count)
Definition: doxygen.cpp:1609
static void findSectionsInDocumentation()
Definition: doxygen.cpp:8301
fileName
Definition: dumpTree.py:9
QChar at(uint i) const
Definition: qstring.h:492
Definition: types.h:35
void createJavascriptSearchIndex()
QCString brief
brief description (doc block)
Definition: entry.h:263
int endBodyLine
line number where the definition ends
Definition: entry.h:277
QString dirPath(bool absPath=FALSE) const
void changeSection(int section)
Definition: entry.h:343
void addMembersToMemberGroup()
Definition: groupdef.cpp:237
ArgumentList * typeConstr
where clause (C#) for type constraints
Definition: entry.h:275
static ClassDef * findClassWithinClassContext(Definition *context, ClassDef *cd, const QCString &name)
Definition: doxygen.cpp:4136
static void findMember(EntryNav *rootNav, QCString funcDecl, bool overloaded, bool isFunc)
Definition: doxygen.cpp:5772
static void writeSearchData(const char *dir)
Definition: htmlgen.cpp:781
static void findDocumentedEnumValues()
Definition: doxygen.cpp:7618
virtual void setFilter(int filterSpec)
Definition: qdir.cpp:538
bool isLinkableInProject() const
Definition: filedef.cpp:1877
void setDocumentation(const char *d, const char *docFile, int docLine, bool stripWhiteSpace=TRUE)
Definition: memberdef.cpp:1126
The Store is a file based memory manager.
Definition: store.h:52
QCString name() const
Definition: filedef.cpp:1193
void setInbodyDocumentation(const char *d, const char *inbodyFile, int inbodyLine)
Definition: memberdef.cpp:1138
void insertNamespace(NamespaceDef *nd)
Definition: filedef.cpp:1172
static ParserInterface * getParserForFile(const char *fn)
Definition: doxygen.cpp:9305
void generateDirDocs(OutputList &ol)
Definition: dirdef.cpp:942
void setMemberClass(ClassDef *cd)
Definition: memberdef.cpp:3392
QCString briefDescription(bool abbr=FALSE) const
Definition: memberdef.cpp:5073
static MemberDef * addVariableToClass(EntryNav *rootNav, ClassDef *cd, MemberType mtype, const QCString &name, bool fromAnnScope, MemberDef *fromAnnMemb, Protection prot, Relationship related)
Definition: doxygen.cpp:2238
bool hasDocumentation() const
Definition: classdef.cpp:2767
void generatePerlMod()
void setFile(const QString &file)
Definition: qfileinfo.cpp:219
bool isEmpty() const
Definition: qlist.h:67
static QCString extractClassName(EntryNav *rootNav)
Definition: doxygen.cpp:4973
bool isTemplate() const
Definition: classdef.cpp:4444
static void escapeAliases()
Definition: doxygen.cpp:9796
static void freeMappers()
Definition: cmdmapper.cpp:254
ClassDef * relatedAlso() const
Definition: memberdef.cpp:4467
QCString right(uint len) const
Definition: qcstring.cpp:231
QCString name
the name of the base class
Definition: entry.h:42
void finializeSearchIndexer()
uint length() const
Definition: qstring.h:679
void initResources()
static const uint64 Interface
Definition: entry.h:125
SrcLangExt getLanguage() const
std::void_t< T > n
void setProtection(Protection p)
Definition: classdef.cpp:4544
const char * className
Definition: doxygen.cpp:325
Specifier virt
virtualness
Definition: entry.h:44
const double a
void addListReferences()
static QCString objDBFileName
Definition: doxygen.h:144
bool open(int)
Definition: qfile_unix.cpp:134
void writeTagFile(FTextStream &)
Definition: pagedef.cpp:95
General file parser.
Definition: fileparser.h:22
static const uint64 Alias
Definition: entry.h:168
static void addListReferences()
Definition: doxygen.cpp:5192
static const uint64 Protocol
Definition: entry.h:129
static const uint64 Enum
Definition: entry.h:133
static int setFlag(const char *label)
Definition: debug.cpp:102
static DirSDict * directories
Definition: doxygen.h:139
void generateDocbook()
static QString currentDirPath()
Definition: qdir_unix.cpp:141
char versionString[]
Definition: version.cpp:1
static void findUsedClassesForClass(EntryNav *rootNav, Definition *context, ClassDef *masterCd, ClassDef *instanceCd, bool isArtificial, ArgumentList *actualArgs=0, QDict< int > *templateNames=0)
Definition: doxygen.cpp:4173
virtual void write(const char *file)=0
FileDef * findFileDef(const FileNameDict *fnDict, const char *n, bool &ambig)
Definition: util.cpp:4963
bool isForeign() const
Definition: memberdef.cpp:4200
QList< SectionInfo > * anchors
list of anchors defined in this entry
Definition: entry.h:281
static void findClassEntries(EntryNav *rootNav)
Definition: doxygen.cpp:4964
static void distributeMemberGroupDocumentation()
Definition: doxygen.cpp:8262
FindBaseClassRelation_Mode
Definition: doxygen.cpp:304
bool setTranslator(const char *langName)
Definition: language.cpp:159
ArgumentList * getTemplateArgumentsFromName(const QCString &name, const QList< ArgumentList > *tArgLists)
Definition: doxygen.cpp:1149
void writeStyleInfo(int part)
Definition: outputlist.h:95
QCString fileName
Definition: section.h:61
void setTemplateArguments(ArgumentList *al)
Definition: classdef.cpp:2603
void addListReferences()
Definition: groupdef.cpp:1524
QCString exception
throw specification
Definition: entry.h:274
static void print(DebugMask mask, int prio, const char *fmt,...)
Definition: debug.cpp:84
static QDict< DefinitionIntf > * symbolMap
Definition: doxygen.h:134
int startLine
start line of entry in the source
Definition: entry.h:283
static void generateFileDocs()
Definition: doxygen.cpp:7959
void stringToArgumentList(const char *argsString, ArgumentList *al, QCString *extraTypeChars)
Definition: defargs.cpp:2922
QCString & prepend(const char *s)
Definition: qcstring.cpp:387
virtual Definition * findInnerCompound(const char *name)
int documentedPages
Definition: index.cpp:66
const char * currentKey() const
Definition: qcache.h:142
static QCString substituteTemplatesInString(const QList< ArgumentList > &srcTempArgLists, const QList< ArgumentList > &dstTempArgLists, ArgumentList *funcTempArgList, const QCString &src)
Definition: doxygen.cpp:5631
p
Definition: test.py:223
static void addSTLMember(EntryNav *rootNav, const char *type, const char *name)
Definition: doxygen.cpp:418
void setTagLessReference(ClassDef *cd)
Definition: classdef.cpp:4679
void disable(OutputGenerator::OutputType o)
Definition: outputlist.cpp:79
QCString args
member argument string
Definition: entry.h:252
static void generateFileSources()
Definition: doxygen.cpp:7817
void makePartOfGroup(GroupDef *gd)
QCString write
property write accessor
Definition: entry.h:272
static SectionDict * sectionDict
Definition: doxygen.h:117
void setProtection(Protection p)
Definition: memberdef.cpp:4632
void setFileName(const QCString &fn)
void addGroupToGroups(Entry *root, GroupDef *subGroup)
Definition: groupdef.cpp:1359
void addMembersToMemberGroup()
Definition: classdef.cpp:388
static bool generatingXmlOutput
Definition: doxygen.h:152
bool updateLanguageMapping(const QCString &extension, const QCString &language)
Definition: util.cpp:6964
Manages programming language parsers.
Definition: parserintf.h:143
A bunch of utility functions.
static PageSDict * pageSDict
Definition: doxygen.h:102
static void writeFooterFile(QFile &f)
Definition: latexgen.cpp:781
void clear()
Definition: qlist.h:82
QDict< int > * getTemplateBaseClassNames() const
Definition: classdef.cpp:3766
void addSectionsToDefinition(QList< SectionInfo > *anchorList)
Definition: definition.cpp:418
static QDict< void > g_pathsVisited(1009)
void writeDocumentation(OutputList &ol)
Definition: classdef.cpp:2120
const char * data() const
Definition: qcstring.h:207
bool isEmbeddedInOuterScope() const
Definition: classdef.cpp:4630
static void generateXRefPages()
Definition: doxygen.cpp:5286
Definition: dirdef.h:44
static void addInterfaceOrServiceToServiceOrSingleton(EntryNav *const rootNav, ClassDef *const cd, QCString const &rname)
Definition: doxygen.cpp:3090
char portable_pathListSeparator()
Definition: portable.cpp:364
static void buildClassDocList(EntryNav *rootNav)
Definition: doxygen.cpp:1417
bool isLinkable() const
Definition: classdef.cpp:2729
QCString anchor() const
Definition: memberdef.cpp:1031
void addImageFile(const char *name)
Definition: index.h:147
static void copyStyleSheet()
Definition: doxygen.cpp:9217
#define Config_getString(val)
Definition: config.cpp:660
void setAccessorType(ClassDef *cd, const char *t)
Definition: memberdef.cpp:3907
static Definition * buildScopeFromQualifiedName(const QCString name, int level, SrcLangExt lang, TagInfo *tagInfo)
Definition: doxygen.cpp:1001
static StringList g_inputFiles
Definition: doxygen.cpp:176
void initialize()
Definition: index.h:129
type * current() const
Definition: qlist.h:146
void addListReferences()
Definition: classdef.cpp:3931
string tmp
Definition: languages.py:63
Protection protection
class protection
Definition: entry.h:241
static QIntDict< MemberGroupInfo > memGrpInfoDict
Definition: doxygen.h:126
void searchInputFiles()
Definition: doxygen.cpp:10743
void enable(OutputGenerator::OutputType o)
Definition: outputlist.cpp:89
int lineNr
Definition: section.h:62
#define Config_getBool(val)
Definition: config.cpp:664
void setReference(const char *r)
void parseTagFile(Entry *root, const char *fullName)
Definition: tagreader.cpp:1527
const char * definition() const
Definition: memberdef.cpp:4025
ClassDef * getClassDef() const
Definition: memberdef.cpp:4070
void preFreeScanner()
static void generateClassList(ClassSDict &classSDict)
Definition: doxygen.cpp:8109
void initPreprocessor()
static bool isVarWithConstructor(EntryNav *rootNav)
Definition: doxygen.cpp:2685
static void usage(const char *name)
Definition: doxygen.cpp:9936
static void writeSearchPage()
Definition: htmlgen.cpp:2193
static void writeTagFile()
Definition: doxygen.cpp:10604
QCString briefFile() const
static void addIncludeFile(ClassDef *cd, FileDef *ifd, Entry *root)
Definition: doxygen.cpp:843
static FileNameDict * diaFileNameDict
Definition: doxygen.h:113
type * getFirst() const
Definition: qlist.h:95
void sortMemberLists()
Definition: filedef.cpp:1829
void addListReferences()
Definition: filedef.cpp:1410
void generatePage() const
Definition: cite.cpp:114
void countDataStructures()
Definition: index.cpp:77
void printNavTree(EntryNav *rootNav, int indent)
Definition: doxygen.cpp:8956
uint64 getMemberSpecifiers() const
Definition: memberdef.cpp:4065
virtual QCString qualifiedName() const
QCString & insert(uint index, const char *s)
Definition: qcstring.cpp:355
void distributeMemberGroupDocumentation()
Definition: classdef.cpp:745
void initSearchIndexer()
static void init()
Definition: rtfgen.cpp:166
type * next()
Definition: qinternallist.h:89
void warn(const char *file, int line, const char *fmt,...)
Definition: message.cpp:183
void makeForeign()
Definition: memberdef.cpp:4687
static QCString getQchFileName()
Definition: doxygen.cpp:10726
void addUsingDeclaration(Definition *def)
Definition: filedef.cpp:1257
ClassDef * getCachedTypedefVal() const
Definition: memberdef.cpp:4577
Protection prot
inheritance type
Definition: entry.h:43
QCString groupname
name of the group
Definition: types.h:93
friend class IteratorDict
Definition: sortdict.h:353
static void clearFlag(const char *label)
Definition: debug.cpp:109
void pyscanFreeScanner()
Definition: pyscanner.cpp:5007
void err(const char *fmt,...)
Definition: message.cpp:226
bool visited
Definition: classdef.h:402
void print()
Definition: doxygen.cpp:227
static void buildPageList(EntryNav *rootNav)
Definition: doxygen.cpp:8655
static QDict< Definition > * clangUsrMap
Definition: doxygen.h:135
static bool g_dumpSymbolMap
Definition: doxygen.cpp:182
static FileNameDict * imageNameDict
Definition: doxygen.h:110
void insertClass(ClassDef *cd)
static bool findClassRelation(EntryNav *rootNav, Definition *context, ClassDef *cd, BaseInfo *bi, QDict< int > *templateNames, FindBaseClassRelation_Mode mode, bool isArtificial)
Definition: doxygen.cpp:4582
void sortMemberLists()
void finalize()
Definition: index.h:131
MemberType memberType() const
Definition: memberdef.cpp:4125
static void computeMemberRelations()
Definition: doxygen.cpp:7667
virtual bool cd(const QString &dirName, bool acceptAbsPath=TRUE)
Definition: qdir.cpp:429
static void computeTemplateClassRelations()
Definition: doxygen.cpp:5075
static void addRelatedPage(EntryNav *rootNav)
Definition: doxygen.cpp:577
QCString absFilePath() const
Definition: filedef.h:96
const char * templName1
Definition: doxygen.cpp:329
int inbodyLine() const
static FileStorage * g_storage
Definition: doxygen.cpp:180
virtual QCString briefDescription(bool abbreviate=FALSE) const
void extractNamespaceName(const QCString &scopeName, QCString &className, QCString &namespaceName, bool allowEmptyClass)
Definition: util.cpp:5478
QCString qualifiedNameWithTemplateParameters(QList< ArgumentList > *actualParams=0, int *actualParamIndex=0) const
Definition: classdef.cpp:3855
void addUsedClass(ClassDef *cd, const char *accessName, Protection prot)
Definition: classdef.cpp:3233
void addClassToGroups(Entry *root, ClassDef *cd)
Definition: groupdef.cpp:1306
void setCompoundType(CompoundType t)
Definition: classdef.cpp:4554
static void exitDoxygen()
Definition: doxygen.cpp:10685
const char * declaration() const
Definition: memberdef.cpp:4020
void setTypeConstraints(ArgumentList *al)
Definition: memberdef.cpp:3888
static void generateTreeViewImages()
Definition: ftvhelp.cpp:690
QCString removeRedundantWhiteSpace(const QCString &s)
Definition: util.cpp:1655
int extractClassNameFromType(const QCString &type, int &pos, QCString &name, QCString &templSpec, SrcLangExt lang)
Definition: util.cpp:5963
Buffer used to store strings.
Definition: bufstr.h:30
static bool g_successfulRun
Definition: doxygen.cpp:181
QCString mid(uint index, uint len=0xffffffff) const
Definition: qcstring.cpp:246
static void substituteTemplatesInArgList(const QList< ArgumentList > &srcTempArgLists, const QList< ArgumentList > &dstTempArgLists, ArgumentList *src, ArgumentList *dst, ArgumentList *funcTempArgs=0)
Definition: doxygen.cpp:5713
static void buildGroupList(EntryNav *rootNav)
Definition: doxygen.cpp:683
bool loadEntry(FileStorage *storage)
Definition: entry.cpp:374
RelatesType relatesType
how relates is handled
Definition: entry.h:270
static void organizeSubGroups(EntryNav *rootNav)
Definition: doxygen.cpp:754
int match(const QCString &str, int index=0, int *len=0, bool indexIsStart=TRUE) const
Definition: qregexp.cpp:649
The QFile class is an I/O device that operates on files.
Definition: qfile.h:50
virtual QCString trPage(bool first_capital, bool singular)=0
void setDocumentedEnumValues(bool value)
Definition: memberdef.cpp:4725
void setAutoDelete(bool enable)
Definition: qcollection.h:55
void setDocsForDefinition(bool b)
Definition: memberdef.cpp:4771
static QCString resolveSymlink(QCString path)
Definition: doxygen.cpp:9477
void distributeMemberGroupDocumentation()
QCString & sprintf(const char *format,...)
Definition: qcstring.cpp:27
static void findMemberDocumentation(EntryNav *rootNav)
Definition: doxygen.cpp:6964
bool checkIfTypedef(Definition *scope, FileDef *fileScope, const char *n)
Definition: util.cpp:7155
static void buildInterfaceAndServiceList(EntryNav *const rootNav)
Definition: doxygen.cpp:3167
bool isRelative() const
Definition: qfileinfo.cpp:439
void setMemberSpecifiers(uint64 s)
Definition: memberdef.cpp:4638
bool run()
Definition: dot.cpp:1317
void sortMemberLists()
Definition: groupdef.cpp:1583
void writeDefaultLayoutFile(const char *fileName)
Definition: layout.cpp:1397
static void findFriends()
Definition: doxygen.cpp:3840
static void filterMemberDocumentation(EntryNav *rootNav)
Definition: doxygen.cpp:6842
static void generateClassDocs()
Definition: doxygen.cpp:8138
static void buildListOfUsingDecls(EntryNav *rootNav)
Definition: doxygen.cpp:1992
void findSectionsInDocumentation()
Definition: filedef.cpp:149
void writeTagFile(FTextStream &)
Definition: groupdef.cpp:565
QCString inbodyDocs
documentation inside the body of a function
Definition: entry.h:266
void insertBaseClass(ClassDef *, const char *name, Protection p, Specifier s, const char *t=0)
Definition: classdef.cpp:358
The QTextStream class provides basic functions for reading and writing text using a QIODevice...
Definition: qtextstream.h:53
QCString doc
documentation block (partly parsed)
Definition: entry.h:260
void initNamespaceMemberIndices()
Definition: index.cpp:2339
QCString & setNum(short n)
Definition: qcstring.cpp:469
void parseFuncDecl(const QCString &decl, bool objC, QCString &cl, QCString &t, QCString &n, QCString &a, QCString &ftl, QCString &exc)
Definition: declinfo.cpp:2213
bool isLinkableInProject() const
Definition: pagedef.h:41
static void addClassToContext(EntryNav *rootNav)
Definition: doxygen.cpp:1236
void addFile(const FileDef *def)
Definition: groupdef.cpp:138
uint size() const
static void addMemberDocs(EntryNav *rootNav, MemberDef *md, const char *funcDecl, ArgumentList *al, bool over_load, NamespaceSDict *nl=0)
Definition: doxygen.cpp:5301
Specifier virt
virtualness of the entry
Definition: entry.h:251
bool pureSpecifier
Definition: arguments.h:103
static STLInfo g_stlinfo[]
Definition: doxygen.cpp:336
static void init()
Definition: htmlgen.cpp:683
void portable_setenv(const char *name, const char *value)
Definition: portable.cpp:202
bool addNamespace(const NamespaceDef *def)
Definition: groupdef.cpp:197
static ClassDef * findClassDefinition(FileDef *fd, NamespaceDef *nd, const char *scopeName)
Definition: doxygen.cpp:5441
virtual Definition * getOuterScope() const
void setRefItems(const QList< ListItemInfo > *sli)
QCString documentation() const
Definition: memberdef.cpp:5085
void generateOutput()
Definition: doxygen.cpp:11379
bool isHidden() const
int getEndBodyLine() const
GroupDef * getGroupDef() const
Definition: memberdef.cpp:4095
void writeGraphInfo(OutputList &ol)
Definition: index.cpp:3245
static bool userComments
Definition: doxygen.h:148
QCString getOutputFileBase() const
Definition: dirdef.cpp:113
void sort()
Definition: sortdict.h:188
static void findMainPageTagFiles(EntryNav *rootNav)
Definition: doxygen.cpp:8752
Definition: types.h:38
void insertClass(ClassDef *cd)
Definition: filedef.cpp:1154
void startTitle(OutputList &ol, const char *fileName, Definition *def)
Definition: index.cpp:228
static bool useHtags
Definition: htags.h:23
static void addSTLIterator(EntryNav *classEntryNav, const char *name)
Definition: doxygen.cpp:435
void insertSubClass(ClassDef *, Protection p, Specifier s, const char *t=0)
Definition: classdef.cpp:373
void cleanUpDoxygen()
Definition: doxygen.cpp:10070
ArgumentList * argumentList() const
Definition: memberdef.cpp:4512
static void findUsingDeclarations(EntryNav *rootNav)
Definition: doxygen.cpp:2018
static void findTagLessClasses(ClassDef *cd)
Definition: doxygen.cpp:1675
static FileNameDict * dotFileNameDict
Definition: doxygen.h:111
virtual Definition * findInnerCompound(const char *name)
NamespaceDef * getResolvedNamespace(const char *name)
Definition: util.cpp:489
void addCodeOnlyMappings()
Definition: util.cpp:7056
Entry * entry() const
Definition: entry.h:346
void generateXML()
Definition: xmlgen.cpp:1839
static GenericsSDict * genericsDict
Definition: doxygen.h:154
void setMaxInitLines(int lines)
Definition: memberdef.cpp:4653
QCString qualifiedName() const
Definition: memberdef.cpp:3968
int getStartBodyLine() const
static void findUsingDirectives(EntryNav *rootNav)
Definition: doxygen.cpp:1848
static QCString entryDBFileName
Definition: doxygen.h:145
void addInnerCompound(Definition *d)
Definition: pagedef.cpp:71
int initializerLines() const
Definition: memberdef.cpp:4060
static MemberNameSDict * memberNameSDict
Definition: doxygen.h:115
QCString tempArgListToString(ArgumentList *al, SrcLangExt lang)
Definition: util.cpp:2197
bool isSubClass(ClassDef *bcd, int level=0)
Definition: classdef.cpp:2807
void addSourceReferences(MemberDef *d)
QDict< ClassDef > * getTemplateInstances() const
Definition: classdef.cpp:4434
const QCString & type() const
Definition: entry.h:349
bool artificial
Artificially introduced item.
Definition: entry.h:288
GroupDocType groupDocType
Definition: entry.h:289
static NamespaceDef * findUsedNamespace(NamespaceSDict *unl, const QCString &name)
Definition: doxygen.cpp:1829
static void buildGroupListFiltered(EntryNav *rootNav, bool additional, bool includeExternal)
Definition: doxygen.cpp:612
static void findUsedTemplateInstances()
Definition: doxygen.cpp:5015
MemberDef * typeDef
Definition: doxygen.h:85
void codeFreeScanner()
Definition: code.cpp:16505
QCString resolveTypeDef(Definition *context, const QCString &qualifiedName, Definition **typedefContext)
Definition: util.cpp:346
int getMemberGroupId() const
Definition: memberdef.cpp:4532
static int findEndOfTemplate(const QCString &s, int startPos)
Definition: doxygen.cpp:4516
static void addMembersToIndex()
Definition: doxygen.cpp:7626
QCString expandAlias(const QCString &aliasName, const QCString &aliasValue)
Definition: util.cpp:7572
void computeAnchors()
Definition: filedef.cpp:129
void addSourceReferencedBy(MemberDef *d)
bool isGeneric() const
Definition: classdef.cpp:4699
void writeDocumentation(OutputList &ol)
const QCString & initializer() const
Definition: memberdef.cpp:4055
void warn_simple(const char *file, int line, const char *text)
Definition: message.cpp:196
static void buildCompleteMemberLists()
Definition: doxygen.cpp:7793
void setId(const char *name)
Definition: definition.cpp:402
void add(const OutputGenerator *)
Definition: outputlist.cpp:44
void insertMember(MemberDef *md)
const char * excpString() const
Definition: memberdef.cpp:4045
static const uint64 Category
Definition: entry.h:130
void setIsStatic(bool b)
Definition: classdef.cpp:4549
A model of a page symbol.
Definition: pagedef.h:29
static bool isClassSection(EntryNav *rootNav)
Definition: doxygen.cpp:4939
Definition: types.h:32
virtual const QFileInfoList * entryInfoList(int filterSpec=DefaultFilter, int sortSpec=DefaultSort) const
Definition: qdir.cpp:772
static bool g_useOutputTemplate
Definition: doxygen.cpp:183
void setEnumScope(MemberDef *md, bool livesInsideEnum=FALSE)
Definition: memberdef.cpp:3377
void setInitializer(const char *i)
Definition: memberdef.cpp:3470
QCString name
Definition: arguments.h:69
void line(double t, double *p, double &x, double &y, double &z)
Cite database access class.
Definition: cite.h:56
static void writeStyleSheetFile(QFile &f)
Definition: rtfgen.cpp:96
void replaceNamespaceAliases(QCString &scope, int i)
Definition: util.cpp:6804
static QCString createOutputDirectory(const QCString &baseDirName, const char *formatDirOption, const char *defaultDirName)
Definition: doxygen.cpp:10702
virtual void setBriefDescription(const char *b, const char *briefFile, int briefLine)
Definition: definition.cpp:687
static StringDict namespaceAliasDict
Definition: doxygen.h:118
QCString convertNameToFile(const char *name, bool allowDots, bool allowUnderscore)
Definition: util.cpp:5354
void initClassMemberIndices()
Definition: index.cpp:2254
QCString fileName
Definition: entry.h:53
static QCString type
Definition: declinfo.cpp:672
bool fill(char c, int len=-1)
Definition: qcstring.h:243
QCString fileName
file this entry was extracted from
Definition: entry.h:282
static void findBaseClassesForClass(EntryNav *rootNav, Definition *context, ClassDef *masterCd, ClassDef *instanceCd, FindBaseClassRelation_Mode mode, bool isArtificial, ArgumentList *actualArgs=0, QDict< int > *templateNames=0)
Definition: doxygen.cpp:4342
CompoundType
Definition: classdef.h:63
bool explicitExternal
explicitly defined as external?
Definition: entry.h:246
QString fileName() const
QCString doc
static const char * latexStyleExtension
Definition: latexgen.h:25
void generateBitmaps(const char *path)
Definition: formula.cpp:49
static MemberDef * addVariableToFile(EntryNav *rootNav, MemberType mtype, const QCString &scope, const QCString &name, bool fromAnnScope, MemberDef *fromAnnMemb)
Definition: doxygen.cpp:2415
static QDict< FileDef > g_usingDeclarations(1009)
void setShowToc(bool b)
Definition: pagedef.cpp:310
#define USE_SQLITE3
Definition: settings.h:3
ClassDef * find(const QCString &key)
Definition: classlist.cpp:183
void computeAnchors()
Definition: groupdef.cpp:559
bool virtualInheritance
Definition: doxygen.cpp:332
bool isEmpty() const
Definition: qgstring.h:39
QCString bitfields
member&#39;s bit fields
Definition: entry.h:253
QCString inside
name of the class in which documents are found
Definition: entry.h:273
static bool findGlobalMember(EntryNav *rootNav, const QCString &namespaceName, const char *type, const char *name, const char *tempArg, const char *, const char *decl)
Definition: doxygen.cpp:5454
void setEnumClassScope(ClassDef *cd)
Definition: memberdef.cpp:4718
QCString trailingReturnType
Definition: arguments.h:105
void writeDocumentation(OutputList &ol)
Definition: pagedef.cpp:119
static bool * b
Definition: config.cpp:1043
static QDict< int > * getTemplateArgumentsInName(ArgumentList *templateArguments, const QCString &name)
Definition: doxygen.cpp:4103
void invalidateCachedArgumentTypes()
Definition: memberdef.cpp:4879
NamespaceDef * getNamespaceDef() const
Definition: memberdef.cpp:4080
void addRefItem(const QList< ListItemInfo > *sli, const char *key, const char *prefix, const char *name, const char *title, const char *args, Definition *scope)
Definition: util.cpp:6456
Protection
Definition: types.h:26
Translator * theTranslator
Definition: language.cpp:157
static void computeVhdlComponentRelations()
void setTypeConstraints(ArgumentList *al)
Definition: classdef.cpp:2590
virtual QCString trDir(bool first_capital, bool singular)=0
void mergeMembers()
Definition: classdef.cpp:2844
QCString docFile
file in which the documentation was found
Definition: entry.h:262
void insertUsedFile(FileDef *fd)
virtual void setDocumentation(const char *d, const char *docFile, int docLine, bool stripWhiteSpace=TRUE)
Definition: definition.cpp:612
bool checkExtension(const char *fName, const char *ext)
Definition: util.cpp:6784
static void generatePageDocs()
Definition: doxygen.cpp:8897
void endTitle(OutputList &ol, const char *fileName, const char *name)
Definition: index.cpp:237
void writeIndexHierarchy(OutputList &ol)
Definition: index.cpp:4279
MethodTypes mtype
signal, slot, (dcop) method, or property?
Definition: entry.h:242
virtual void parseInput(const char *fileName, const char *fileBuf, Entry *root, bool sameTranslationUnit, QStrList &filesInSameTranslationUnit)=0
static void generateConfigFile(const char *configFile, bool shortList, bool updateOnly=FALSE)
Definition: doxygen.cpp:9106
QCString normalizeNonTemplateArgumentsInString(const QCString &name, Definition *context, const ArgumentList *formalArgs)
Definition: util.cpp:6037
void reclassifyMember(MemberDef *md, MemberType t)
Definition: classdef.cpp:4594
bool isFunction() const
Definition: memberdef.cpp:4160
void setIncludeFile(FileDef *fd, const char *incName, bool local, bool force)
Definition: classdef.cpp:820
static ClassDef * createTagLessInstance(ClassDef *rootCd, ClassDef *templ, const QCString &fieldName)
Definition: doxygen.cpp:1529
bool open(int m)
Definition: filestorage.h:36
void getTemplateParameterLists(QList< ArgumentList > &lists) const
Definition: classdef.cpp:3838
type * at(uint i)
Definition: qinternallist.h:81
void parseInput()
Definition: doxygen.cpp:10880
friend class Iterator
Definition: sortdict.h:289
QList< stat > stats
Definition: doxygen.cpp:252
int readDir(QFileInfo *fi, FileNameList *fnList, FileNameDict *fnDict, StringDict *exclDict, QStrList *patList, QStrList *exclPatList, StringList *resultList, StringDict *resultDict, bool errorIfNotExist, bool recursive, QDict< void > *killDict, QDict< void > *paths)
Definition: doxygen.cpp:9551
void writeJavascriptSearchIndex()
void initWarningFormat()
Definition: message.cpp:38
int getScopeFragment(const QCString &s, int p, int *l)
Definition: util.cpp:6322
void addUsingDeclaration(Definition *def)
static QCache< LookupInfo > * lookupCache
Definition: doxygen.h:138
list cmd
Definition: getreco.py:22
void generateSqlite3()
static QDict< void > expandAsDefinedDict
Definition: doxygen.h:127
QCString relates
related class (doc block)
Definition: entry.h:269
void readAliases()
Definition: doxygen.cpp:9831
static const uint64 Struct
Definition: entry.h:126
void setHidden(bool b)
Definition: memberdef.cpp:1144
void addUsingDirective(NamespaceDef *nd)
static void startScope()
static QCString baseName
Definition: scanner.cpp:10890
bool isRelated() const
Definition: memberdef.cpp:4195
void addIncludedUsingDirectives()
Definition: filedef.cpp:1293
static QCString spaces
Definition: doxygen.h:151
ClassSDict * getClassSDict() const
Definition: namespacedef.h:98
static void findObjCMethodDefinitions(EntryNav *rootNav)
Definition: doxygen.cpp:6995
void makeTemplateArgument(bool b=TRUE)
Definition: classdef.cpp:4564
int docLine() const
void setWriteAccessor(const char *w)
Definition: memberdef.cpp:4671
const char * argsString() const
Definition: memberdef.cpp:4040
bool isLinkableInProject() const
void insertUsedFile(FileDef *)
Definition: classdef.cpp:783
static bool isFlagSet(DebugMask mask)
Definition: debug.cpp:119
static QDict< int > * htmlDirMap
Definition: doxygen.h:137
void addSourceRef(int line, Definition *d, MemberDef *md)
Definition: filedef.cpp:1201
static bool outputToWizard
Definition: doxygen.h:136
The QFileInfo class provides system-independent file information.
Definition: qfileinfo.h:51
static int findFunctionPtr(const QCString &type, int lang, int *pLength=0)
Definition: doxygen.cpp:2655
QCString getOutputFileBase() const
Definition: groupdef.cpp:1512
void close()
Definition: filestorage.h:39
QCString lower() const
Definition: qcstring.cpp:263
void createNavigationIndex(EntryNav *rootNav, FileStorage *storage, FileDef *fd)
Definition: entry.cpp:304
bool isStatic() const
Definition: memberdef.cpp:4205
void setFileDef(FileDef *fd)
Definition: memberdef.cpp:4624
Definition * definition
Definition: section.h:60
QString readLine()
void docify(const char *s)
Definition: outputlist.h:145
unsigned long long uint64
Definition: qglobal.h:361
uint count() const
Definition: qinternallist.h:56
bool remove(const char *k)
Definition: qcache.h:103
static const uint64 Union
Definition: entry.h:127
Q_EXPORT int qstrcmp(const char *str1, const char *str2)
Definition: qcstring.h:95
VHDL parser using state-based lexical scanning.
Definition: vhdljjparser.h:41
bool isTypedef() const
Definition: memberdef.cpp:4155
SrcLangExt lang
programming language in which this entry was found
Definition: entry.h:286
static void findUsingDeclImports(EntryNav *rootNav)
Definition: doxygen.cpp:2102
static const uint64 Service
Definition: entry.h:134
T * find(const char *key)
Definition: sortdict.h:232
static bool isSpecialization(const QList< ArgumentList > &srcTempArgLists, const QList< ArgumentList > &dstTempArgLists)
Definition: doxygen.cpp:5605
QCString utf8() const
Definition: qstring.cpp:14507
virtual QCString documentation() const
bool patternMatch(const QFileInfo &fi, const QStrList *patList)
Definition: util.cpp:7784
if(!yymsg) yymsg
int inbodyLine
line number at which the body doc was found
Definition: entry.h:267
Definition: entry.h:37
ClassDef * getResolvedClass(Definition *scope, FileDef *fileScope, const char *n, MemberDef **pTypeDef, QCString *pTemplSpec, bool mayBeUnlinkable, bool mayBeHidden, QCString *pResolvedType)
Definition: util.cpp:1563
void setSubGrouping(bool enabled)
Definition: classdef.cpp:4539
void setNamespace(NamespaceDef *nd)
Definition: classdef.cpp:4529
bool isExternal() const
Definition: memberdef.cpp:4438
void startParsing()
Definition: filedef.cpp:1062
static void generateNamespaceDocs()
Definition: doxygen.cpp:9040
static void checkPageRelations()
Definition: doxygen.cpp:8802
static void addPageToContext(PageDef *pd, EntryNav *rootNav)
Definition: doxygen.cpp:558
static void findDEV(const MemberNameSDict &mnsd)
Definition: doxygen.cpp:7583
static void findEnums(EntryNav *rootNav)
Definition: doxygen.cpp:7030
unsigned uint
Definition: qglobal.h:351
void setAutoDelete(bool enable)
Definition: qlist.h:99
static ClassSDict * classSDict
Definition: doxygen.h:99
QCString getOutputFileBase() const
Definition: pagedef.cpp:58
QCString mergeScopes(const QCString &leftScope, const QCString &rightScope)
Definition: util.cpp:6287
void addIndex(IndexIntf *intf)
Definition: index.h:119
QCString stripFromIncludePath(const QCString &path)
Definition: util.cpp:306
void addTaggedInnerClass(ClassDef *cd)
Definition: classdef.cpp:4665
void addTypeConstraints()
Definition: classdef.cpp:2564
static PageDef * mainPage
Definition: doxygen.h:103
static void addEnumValuesToEnums(EntryNav *rootNav)
Definition: doxygen.cpp:7211
void setBriefDescription(const char *b, const char *briefFile, int briefLine)
Definition: memberdef.cpp:1132
void addChild(EntryNav *)
Definition: entry.cpp:364
std::string nl(std::size_t i=1)
bool hasGroupTitle() const
Definition: groupdef.h:56
const QCString & docName() const
Definition: filedef.h:99
A list of index interfaces.
Definition: index.h:53
Definition: types.h:32
static MethodTypes mtype
static void buildFunctionList(EntryNav *rootNav)
Definition: doxygen.cpp:3417
MemberList * getMemberList(MemberListType lt)
Definition: classdef.cpp:4021
static void dumpSymbolMap()
Definition: doxygen.cpp:9892
QTime time
Definition: doxygen.cpp:253
void setFileDef(FileDef *fd)
Definition: classdef.cpp:4534
uint portable_pid()
Definition: portable.cpp:186
static QCString * s
Definition: config.cpp:1042
bool isDir() const
virtual bool exists() const
Definition: qdir.cpp:820
const char * qPrint(const char *s)
Definition: qcstring.h:797
void scanFreeScanner()
Definition: scanner.cpp:22510
const bool TRUE
Definition: qglobal.h:371
static QTime runningTime
Definition: doxygen.h:132
QList< BaseInfo > * extends
list of base classes
Definition: entry.h:279
static IndexList * indexList
Definition: doxygen.h:149
static void addMethodToClass(EntryNav *rootNav, ClassDef *cd, const QCString &rname, bool isFriend)
Definition: doxygen.cpp:3237
Portable versions of functions that are platform dependent.
QCString substitute(const QCString &s, const QCString &src, const QCString &dst)
substitute all occurrences of src in s by dst
Definition: util.cpp:5088
static void flushUnresolvedRelations()
Definition: doxygen.cpp:8396
Definition: se.py:1
static bool setCurrent(const QString &path)
Definition: qdir_unix.cpp:134
void setPerlModDoxyfile(const QCString &qs)
static FileNameDict * mscFileNameDict
Definition: doxygen.h:112
static QDict< void > g_compoundKeywordDict(7)
void combineUsingRelations()
QTextStream & endl(QTextStream &s)
bool isEnumerate() const
Definition: memberdef.cpp:4145
static void computePageRelations(EntryNav *rootNav)
Definition: doxygen.cpp:8767
BaseClassList * baseClasses() const
Definition: classdef.cpp:4399
GroupDef * getGroupDef() const
Definition: pagedef.cpp:52
ArgumentList * templateArguments() const
Definition: memberdef.cpp:4522
int minClassDistance(const ClassDef *cd, const ClassDef *bcd, int level)
Definition: util.cpp:2527
QCString type
member type
Definition: entry.h:236
void startContents()
Definition: outputlist.h:364
bool eof() const
Definition: qtextstream.h:229
Definition: qlist.h:54
QCString array
Definition: arguments.h:70
bool exists() const
Definition: qfileinfo.cpp:265
void close()
Definition: store.cpp:101
static const uint64 Singleton
Definition: entry.h:135
#define ASSERT(x)
Definition: qglobal.h:590
int section
entry type (see Sections);
Definition: entry.h:235
void warn_uncond(const char *fmt,...)
Definition: message.cpp:218
int portable_system(const char *command, const char *args, bool commandHasConsole)
Definition: portable.cpp:33
int bodyLine
line number of the definition in the source
Definition: entry.h:276
QCString briefFile
file in which the brief desc. was found
Definition: entry.h:265
QList< ListItemInfo > * sli
special lists (test/todo/bug/deprecated/..) this entry is in
Definition: entry.h:285
virtual void setHidden(bool b)
bool isReadable() const
Definition: qfileinfo.cpp:405
void writeDocumentationForInnerClasses(OutputList &ol)
Definition: classdef.cpp:2225
type * toFirst()
Definition: qlist.h:135
void setBodySegment(int bls, int ble)