My Project
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
defgen.cpp
Go to the documentation of this file.
1 /******************************************************************************
2  *
3  *
4  *
5  *
6  * Copyright (C) 1997-2015 by Dimitri van Heesch.
7  *
8  * Permission to use, copy, modify, and distribute this software and its
9  * documentation under the terms of the GNU General Public License is hereby
10  * granted. No representations are made about the suitability of this software
11  * for any purpose. It is provided "as is" without express or implied warranty.
12  * See the GNU General Public License for more details.
13  *
14  * Documents produced by Doxygen are derivative works derived from the
15  * input used in their production; they are not affected by this license.
16  *
17  */
18 
19 #include <stdlib.h>
20 
21 #include "defgen.h"
22 #include "doxygen.h"
23 #include "message.h"
24 #include "config.h"
25 #include "classlist.h"
26 #include "util.h"
27 #include "defargs.h"
28 #include "outputgen.h"
29 #include "dot.h"
30 #include "arguments.h"
31 #include "memberlist.h"
32 #include "namespacedef.h"
33 #include "filedef.h"
34 #include "filename.h"
35 
36 #include <qdir.h>
37 #include <qfile.h>
38 #include <qtextstream.h>
39 
40 #define DEF_DB(x)
41 
42 inline void writeDEFString(FTextStream &t,const char *s)
43 {
44  const char* p=s;
45  char c;
46 
47  t << '\'';
48  while ((c = *(p++)))
49  {
50  if (c == '\'')
51  t << '\\';
52  t << c;
53  }
54  t << '\'';
55 }
56 
58  FTextStream &t,
59  Definition *def,
60  const char* Prefix)
61 {
62  QCString memPrefix;
63 
64  // + declaration
65  // - reimplements
66  // - reimplementedBy
67  // - exceptions
68  // - const/volatile specifiers
69  // - examples
70  // + source definition
71  // - source references
72  // - source referenced by
73  // - include code
74 
75  if (md->memberType()==MemberType_EnumValue) return;
76 
77  QCString scopeName;
78  if (md->getClassDef())
79  scopeName=md->getClassDef()->name();
80  else if (md->getNamespaceDef())
81  scopeName=md->getNamespaceDef()->name();
82 
83  t << " " << Prefix << "-member = {" << endl;
84  memPrefix = " ";
85  memPrefix.append( Prefix );
86  memPrefix.append( "-mem-" );
87 
88  QCString memType;
89  bool isFunc=FALSE;
90  switch (md->memberType())
91  {
92  case MemberType_Define: memType="define"; break;
93  case MemberType_EnumValue: ASSERT(0); break;
94  case MemberType_Property: memType="property"; break;
95  case MemberType_Event: memType="event"; break;
96  case MemberType_Variable: memType="variable"; break;
97  case MemberType_Typedef: memType="typedef"; break;
98  case MemberType_Enumeration: memType="enum"; break;
99  case MemberType_Interface: memType="interface"; break;
100  case MemberType_Service: memType="service"; break;
101  case MemberType_Function: memType="function"; isFunc=TRUE; break;
102  case MemberType_Signal: memType="signal"; isFunc=TRUE; break;
103  case MemberType_Friend: memType="friend"; isFunc=TRUE; break;
104  case MemberType_DCOP: memType="dcop"; isFunc=TRUE; break;
105  case MemberType_Slot: memType="slot"; isFunc=TRUE; break;
106  }
107 
108  t << memPrefix << "kind = '" << memType << "';" << endl;
109  t << memPrefix << "id = '"
110  << md->getOutputFileBase() << "_1" << md->anchor()
111  << "';" << endl;
112 
113  t << memPrefix << "virt = ";
114  switch (md->virtualness())
115  {
116  case Normal: t << "normal;" << endl; break;
117  case Virtual: t << "virtual;" << endl; break;
118  case Pure: t << "pure-virtual;" << endl; break;
119  default: ASSERT(0);
120  }
121 
122  t << memPrefix << "prot = ";
123  switch(md->protection())
124  {
125  case Public: t << "public;" << endl; break;
126  case Protected: t << "protected;" << endl; break;
127  case Private: t << "private;" << endl; break;
128  case Package: t << "package;" << endl; break;
129  }
130 
131  if (md->memberType()!=MemberType_Define &&
133  )
134  {
135  QCString typeStr = replaceAnonymousScopes(md->typeString());
136  t << memPrefix << "type = <<_EnD_oF_dEf_TeXt_" << endl << typeStr << endl
137  << "_EnD_oF_dEf_TeXt_;" << endl;
138  }
139 
140  t << memPrefix << "name = '" << md->name() << "';" << endl;
141 
142  if (isFunc) //function
143  {
144  ArgumentList *declAl = new ArgumentList;
145  ArgumentList *defAl = md->argumentList();
146  stringToArgumentList(md->argsString(),declAl);
147  QCString fcnPrefix = " " + memPrefix + "param-";
148 
149  if (declAl->count()>0)
150  {
151  ArgumentListIterator declAli(*declAl);
152  ArgumentListIterator defAli(*defAl);
153  Argument *a;
154  for (declAli.toFirst();(a=declAli.current());++declAli)
155  {
156  Argument *defArg = defAli.current();
157  t << memPrefix << "param = {" << endl;
158  if (!a->attrib.isEmpty())
159  {
160  t << fcnPrefix << "attributes = ";
161  writeDEFString(t,a->attrib);
162  t << ';' << endl;
163  }
164  if (!a->type.isEmpty())
165  {
166  t << fcnPrefix << "type = <<_EnD_oF_dEf_TeXt_" << endl
167  << a->type << endl << "_EnD_oF_dEf_TeXt_;" << endl;
168  }
169  if (!a->name.isEmpty())
170  {
171  t << fcnPrefix << "declname = ";
172  writeDEFString(t,a->name);
173  t << ';' << endl;
174  }
175  if (defArg && !defArg->name.isEmpty() && defArg->name!=a->name)
176  {
177  t << fcnPrefix << "defname = ";
178  writeDEFString(t,defArg->name);
179  t << ';' << endl;
180  }
181  if (!a->array.isEmpty())
182  {
183  t << fcnPrefix << "array = ";
184  writeDEFString(t,a->array);
185  t << ';' << endl;
186  }
187  if (!a->defval.isEmpty())
188  {
189  t << fcnPrefix << "defval = <<_EnD_oF_dEf_TeXt_" << endl
190  << a->defval << endl << "_EnD_oF_dEf_TeXt_;" << endl;
191  }
192  if (defArg) ++defAli;
193  t << " }; /*" << fcnPrefix << "-param */" << endl;
194  }
195  }
196  delete declAl;
197  }
198  else if ( md->memberType()==MemberType_Define
199  && md->argsString()!=0)
200  {
202  Argument *a;
203  QCString defPrefix = " " + memPrefix + "def-";
204 
205  for (ali.toFirst();(a=ali.current());++ali)
206  {
207  t << memPrefix << "param = {" << endl;
208  t << defPrefix << "name = '" << a->type << "';" << endl;
209  t << " }; /*" << defPrefix << "-param */" << endl;
210  }
211  }
212 
213  if (!md->initializer().isEmpty())
214  {
215  t << memPrefix << "initializer = <<_EnD_oF_dEf_TeXt_" << endl
216  << md->initializer() << endl << "_EnD_oF_dEf_TeXt_;" << endl;
217  }
218  // TODO: exceptions, const volatile
219  if (md->memberType()==MemberType_Enumeration) // enum
220  {
221  MemberList *enumList = md->enumFieldList();
222  if (enumList!=0)
223  {
224  MemberListIterator emli(*enumList);
225  MemberDef *emd;
226  for (emli.toFirst();(emd=emli.current());++emli)
227  {
228  t << memPrefix << "enum = { enum-name = " << emd->name() << ';';
229  if (!emd->initializer().isEmpty())
230  {
231  t << " enum-value = ";
232  writeDEFString(t,emd->initializer());
233  t << ';';
234  }
235  t << " };" << endl;
236  }
237  }
238  }
239 
240  t << memPrefix << "desc-file = '" << md->getDefFileName() << "';" << endl;
241  t << memPrefix << "desc-line = '" << md->getDefLine() << "';" << endl;
242  t << memPrefix << "briefdesc = <<_EnD_oF_dEf_TeXt_" << endl
243  << md->briefDescription() << endl << "_EnD_oF_dEf_TeXt_;" << endl;
244  t << memPrefix << "documentation = <<_EnD_oF_dEf_TeXt_" << endl
245  << md->documentation() << endl << "_EnD_oF_dEf_TeXt_;" << endl;
246 
247  //printf("md->getReferencesMembers()=%p\n",md->getReferencesMembers());
248 
249  MemberSDict *mdict = md->getReferencesMembers();
250  if (mdict)
251  {
252  MemberSDict::Iterator mdi(*mdict);
253  MemberDef *rmd;
254  QCString refPrefix = " " + memPrefix + "ref-";
255 
256  for (mdi.toFirst();(rmd=mdi.current());++mdi)
257  {
258  if (rmd->getStartBodyLine()!=-1 && rmd->getBodyDef())
259  {
260  t << memPrefix << "referenceto = {" << endl;
261  t << refPrefix << "id = '"
262  << rmd->getBodyDef()->getOutputFileBase()
263  << "_1" // encoded `:' character (see util.cpp:convertNameToFile)
264  << rmd->anchor() << "';" << endl;
265 
266  t << refPrefix << "line = '"
267  << rmd->getStartBodyLine() << "';" << endl;
268 
269  QCString scope = rmd->getScopeString();
270  QCString name = rmd->name();
271  if (!scope.isEmpty() && scope!=def->name())
272  {
273  name.prepend(scope+"::");
274  }
275 
276  t << refPrefix << "name = ";
277  writeDEFString(t,name);
278  t << ';' << endl << " };" << endl;
279  }
280  } /* for (mdi.toFirst...) */
281  }
282  mdict = md->getReferencedByMembers();
283  if (mdict)
284  {
285  MemberSDict::Iterator mdi(*mdict);
286  MemberDef *rmd;
287  QCString refPrefix = " " + memPrefix + "ref-";
288 
289  for (mdi.toFirst();(rmd=mdi.current());++mdi)
290  {
291  if (rmd->getStartBodyLine()!=-1 && rmd->getBodyDef())
292  {
293  t << memPrefix << "referenceby = {" << endl;
294  t << refPrefix << "id = '"
295  << rmd->getBodyDef()->getOutputFileBase()
296  << "_1" // encoded `:' character (see util.cpp:convertNameToFile)
297  << rmd->anchor() << "';" << endl;
298 
299  t << refPrefix << "line = '"
300  << rmd->getStartBodyLine() << "';" << endl;
301 
302  QCString scope = rmd->getScopeString();
303  QCString name = rmd->name();
304  if (!scope.isEmpty() && scope!=def->name())
305  {
306  name.prepend(scope+"::");
307  }
308 
309  t << refPrefix << "name = ";
310  writeDEFString(t,name);
311  t << ';' << endl << " };" << endl;
312  }
313  } /* for (mdi.toFirst...) */
314  }
315 
316  t << " }; /* " << Prefix << "-member */" << endl;
317 }
318 
319 
321  FTextStream &t,
322  MemberList *ml,
323  const char *kind)
324 {
325  if (cd && ml && ml->count()>0)
326  {
327  t << " cp-section = {" << endl;
328  t << " sec-kind = '" << kind << "';" << endl;
329 
330  MemberListIterator mli(*ml);
331  MemberDef *md;
332  for (mli.toFirst();(md=mli.current());++mli)
333  {
334  generateDEFForMember(md,t,cd,"sec");
335  }
336  t << " }; /* cp-section */" << endl;
337  }
338 }
339 
341 {
342  // + brief description
343  // + detailed description
344  // - template arguments
345  // - include files
346  // + inheritance diagram
347  // + list of direct super classes
348  // + list of direct sub classes
349  // + collaboration diagram
350  // - list of all members
351  // + user defined member sections
352  // + standard member sections
353  // + detailed member documentation
354  // - examples
355 
356  if (cd->isReference()) return; // skip external references.
357  if (cd->name().find('@')!=-1) return; // skip anonymous compounds.
358  if (cd->templateMaster()!=0) return; // skip generated template instances.
359 
360  t << cd->compoundTypeString() << " = {" << endl;
361  t << " cp-id = '" << cd->getOutputFileBase() << "';" << endl;
362  t << " cp-name = '" << cd->name() << "';" << endl;
363 
364  if (cd->baseClasses())
365  {
366  BaseClassListIterator bcli(*cd->baseClasses());
367  BaseClassDef *bcd;
368  for (bcli.toFirst();(bcd=bcli.current());++bcli)
369  {
370  t << " cp-ref = {" << endl << " ref-type = base;" << endl;
371  t << " ref-id = '"
372  << bcd->classDef->getOutputFileBase() << "';" << endl;
373  t << " ref-prot = ";
374  switch (bcd->prot)
375  {
376  case Public: t << "public;" << endl; break;
377  case Package: // package scope is not possible
378  case Protected: t << "protected;" << endl; break;
379  case Private: t << "private;" << endl; break;
380  }
381  t << " ref-virt = ";
382  switch(bcd->virt)
383  {
384  case Normal: t << "non-virtual;"; break;
385  case Virtual: t << "virtual;"; break;
386  case Pure: t << "pure-virtual;"; break;
387  }
388  t << endl << " };" << endl;
389  }
390  }
391 
392  if (cd->subClasses())
393  {
394  BaseClassListIterator bcli(*cd->subClasses());
395  BaseClassDef *bcd;
396  for (bcli.toFirst();(bcd=bcli.current());++bcli)
397  {
398  t << " cp-ref = {" << endl << " ref-type = derived;" << endl;
399  t << " ref-id = '"
400  << bcd->classDef->getOutputFileBase() << "';" << endl;
401  t << " ref-prot = ";
402  switch (bcd->prot)
403  {
404  case Public: t << "public;" << endl; break;
405  case Package: // packet scope is not possible!
406  case Protected: t << "protected;" << endl; break;
407  case Private: t << "private;" << endl; break;
408  }
409  t << " ref-virt = ";
410  switch(bcd->virt)
411  {
412  case Normal: t << "non-virtual;"; break;
413  case Virtual: t << "virtual;"; break;
414  case Pure: t << "pure-virtual;"; break;
415  }
416  t << endl << " };" << endl;
417  }
418  }
419 
420  int numMembers = 0;
421  QListIterator<MemberList> mli(cd->getMemberLists());
422  MemberList *ml;
423  for (mli.toFirst();(ml=mli.current());++mli)
424  {
425  if ((ml->listType()&MemberListType_detailedLists)==0)
426  {
427  numMembers+=ml->count();
428  }
429  }
430  if (numMembers>0)
431  {
447  generateDEFClassSection(cd,t,cd->getMemberList(MemberListType_proStaticMethods),"protected-static-func");
448  generateDEFClassSection(cd,t,cd->getMemberList(MemberListType_proStaticAttribs),"protected-static-attrib");
454  generateDEFClassSection(cd,t,cd->getMemberList(MemberListType_priStaticAttribs),"private-static-attrib");
457  }
458 
459  t << " cp-filename = '" << cd->getDefFileName() << "';" << endl;
460  t << " cp-fileline = '" << cd->getDefLine() << "';" << endl;
461  t << " cp-briefdesc = <<_EnD_oF_dEf_TeXt_" << endl
462  << cd->briefDescription() << endl << "_EnD_oF_dEf_TeXt_;" << endl;
463 
464  t << " cp-documentation = <<_EnD_oF_dEf_TeXt_" << endl
465  << cd->documentation() << endl << "_EnD_oF_dEf_TeXt_;" << endl;
466 
467  DotClassGraph inheritanceGraph(cd,DotNode::Inheritance);
468  if (!inheritanceGraph.isTrivial())
469  {
470  t << " cp-inheritancegraph = <<_EnD_oF_dEf_TeXt_" << endl;
471  inheritanceGraph.writeDEF(t);
472  t << endl << "_EnD_oF_dEf_TeXt_;" << endl;
473  }
474  DotClassGraph collaborationGraph(cd,DotNode::Collaboration);
475  if (!collaborationGraph.isTrivial())
476  {
477  t << " cp-collaborationgraph = <<_EnD_oF_dEf_TeXt_" << endl;
478  collaborationGraph.writeDEF(t);
479  t << endl << "_EnD_oF_dEf_TeXt_;" << endl;
480  }
481  t << "}; /* " << cd->compoundTypeString() << " */" << endl;
482 }
483 
485  FTextStream &t,
486  MemberList *ml,
487  const char *kind)
488 {
489  if (ml && ml->count()>0)
490  {
491  t << " " << kind << " = {" << endl;
492  MemberListIterator mli(*ml);
493  MemberDef *md;
494  for (mli.toFirst();(md=mli.current());++mli)
495  {
496  generateDEFForMember(md,t,d,kind);
497  }
498  t << " };" << endl;
499  }
500 }
501 
503 {
504  if (nd->isReference()) return; // skip external references
505  t << " namespace = {" << endl;
506  t << " ns-id = '" << nd->getOutputFileBase() << "';" << endl;
507  t << " ns-name = ";
508  writeDEFString(t,nd->name());
509  t << ';' << endl;
510 
517 
518  t << " ns-filename = '" << nd->getDefFileName() << "';" << endl;
519  t << " ns-fileline = '" << nd->getDefLine() << "';" << endl;
520  t << " ns-briefdesc = <<_EnD_oF_dEf_TeXt_" << endl
521  << nd->briefDescription() << endl << "_EnD_oF_dEf_TeXt_;" << endl;
522 
523  t << " ns-documentation = <<_EnD_oF_dEf_TeXt_" << endl
524  << nd->documentation() << endl << "_EnD_oF_dEf_TeXt_;" << endl;
525  t << " };" << endl;
526 }
527 
529 {
530  if (fd->isReference()) return; // skip external references
531 
532  t << "file = {" << endl;
533  t << " file-id = '" << fd->getOutputFileBase() << "';" << endl;
534  t << " file-name = ";
535  writeDEFString(t,fd->name());
536  t << ';' << endl;
537 
544 
545  t << " file-full-name = '" << fd->getDefFileName() << "';" << endl;
546  t << " file-first-line = '" << fd->getDefLine() << "';" << endl;
547 
548  t << " file-briefdesc = <<_EnD_oF_dEf_TeXt_" << endl
549  << fd->briefDescription() << endl << "_EnD_oF_dEf_TeXt_;" << endl;
550 
551  t << " file-documentation = <<_EnD_oF_dEf_TeXt_" << endl
552  << fd->documentation() << endl << "_EnD_oF_dEf_TeXt_;" << endl;
553 
554  t << "}; /* file */" << endl;
555 }
556 
557 
559 {
560  QCString outputDirectory = Config_getString(OUTPUT_DIRECTORY);
561  if (outputDirectory.isEmpty())
562  {
563  outputDirectory=QDir::currentDirPath().utf8();
564  }
565  else
566  {
567  QDir dir(outputDirectory);
568  if (!dir.exists())
569  {
570  dir.setPath(QDir::currentDirPath());
571  if (!dir.mkdir(outputDirectory))
572  {
573  err("tag OUTPUT_DIRECTORY: Output directory `%s' does not "
574  "exist and cannot be created\n",outputDirectory.data());
575  exit(1);
576  }
577  else
578  {
579  msg("Notice: Output directory `%s' does not exist. "
580  "I have created it for you.\n", outputDirectory.data());
581  }
582  dir.cd(outputDirectory);
583  }
584  outputDirectory=dir.absPath().utf8();
585  }
586 
587  QDir dir(outputDirectory);
588  if (!dir.exists())
589  {
590  dir.setPath(QDir::currentDirPath());
591  if (!dir.mkdir(outputDirectory))
592  {
593  err("Cannot create directory %s\n",outputDirectory.data());
594  return;
595  }
596  }
597  QDir defDir(outputDirectory+"/def");
598  if (!defDir.exists() && !defDir.mkdir(outputDirectory+"/def"))
599  {
600  err("Could not create def directory in %s\n",outputDirectory.data());
601  return;
602  }
603 
604  QCString fileName=outputDirectory+"/def/doxygen.def";
605  QFile f(fileName);
606  if (!f.open(IO_WriteOnly))
607  {
608  err("Cannot open file %s for writing!\n",fileName.data());
609  return;
610  }
611  FTextStream t(&f);
612  t << "AutoGen Definitions dummy;" << endl;
613 
614  if (Doxygen::classSDict->count()+Doxygen::inputNameList->count()>0)
615  {
617  ClassDef *cd;
618  for (cli.toFirst();(cd=cli.current());++cli)
619  {
620  generateDEFForClass(cd,t);
621  }
623  FileName *fn;
624  for (;(fn=fnli.current());++fnli)
625  {
626  FileNameIterator fni(*fn);
627  FileDef *fd;
628  for (;(fd=fni.current());++fni)
629  {
630  generateDEFForFile(fd,t);
631  }
632  }
633  }
634  else
635  {
636  t << "dummy_value = true;" << endl;
637  }
638 }