1 /******************************************************************************
6 * Copyright (C) 1997-2015 by Dimitri van Heesch.
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.
14 * Documents produced by Doxygen are derivative works derived from the
15 * input used in their production; they are not affected by this license.
25 #include "classlist.h"
28 #include "outputgen.h"
30 #include "arguments.h"
31 #include "memberlist.h"
32 #include "namespacedef.h"
38 #include <qtextstream.h>
42 inline void writeDEFString(FTextStream &t,const char *s)
57 void generateDEFForMember(MemberDef *md,
68 // - const/volatile specifiers
70 // + source definition
71 // - source references
72 // - source referenced by
75 if (md->memberType()==MemberType_EnumValue) return;
78 if (md->getClassDef())
79 scopeName=md->getClassDef()->name();
80 else if (md->getNamespaceDef())
81 scopeName=md->getNamespaceDef()->name();
83 t << " " << Prefix << "-member = {" << endl;
85 memPrefix.append( Prefix );
86 memPrefix.append( "-mem-" );
90 switch (md->memberType())
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;
108 t << memPrefix << "kind = '" << memType << "';" << endl;
109 t << memPrefix << "id = '"
110 << md->getOutputFileBase() << "_1" << md->anchor()
113 t << memPrefix << "virt = ";
114 switch (md->virtualness())
116 case Normal: t << "normal;" << endl; break;
117 case Virtual: t << "virtual;" << endl; break;
118 case Pure: t << "pure-virtual;" << endl; break;
122 t << memPrefix << "prot = ";
123 switch(md->protection())
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;
131 if (md->memberType()!=MemberType_Define &&
132 md->memberType()!=MemberType_Enumeration
135 QCString typeStr = replaceAnonymousScopes(md->typeString());
136 t << memPrefix << "type = <<_EnD_oF_dEf_TeXt_" << endl << typeStr << endl
137 << "_EnD_oF_dEf_TeXt_;" << endl;
140 t << memPrefix << "name = '" << md->name() << "';" << endl;
142 if (isFunc) //function
144 ArgumentList *declAl = new ArgumentList;
145 ArgumentList *defAl = md->argumentList();
146 stringToArgumentList(md->argsString(),declAl);
147 QCString fcnPrefix = " " + memPrefix + "param-";
149 if (declAl->count()>0)
151 ArgumentListIterator declAli(*declAl);
152 ArgumentListIterator defAli(*defAl);
154 for (declAli.toFirst();(a=declAli.current());++declAli)
156 Argument *defArg = defAli.current();
157 t << memPrefix << "param = {" << endl;
158 if (!a->attrib.isEmpty())
160 t << fcnPrefix << "attributes = ";
161 writeDEFString(t,a->attrib);
164 if (!a->type.isEmpty())
166 t << fcnPrefix << "type = <<_EnD_oF_dEf_TeXt_" << endl
167 << a->type << endl << "_EnD_oF_dEf_TeXt_;" << endl;
169 if (!a->name.isEmpty())
171 t << fcnPrefix << "declname = ";
172 writeDEFString(t,a->name);
175 if (defArg && !defArg->name.isEmpty() && defArg->name!=a->name)
177 t << fcnPrefix << "defname = ";
178 writeDEFString(t,defArg->name);
181 if (!a->array.isEmpty())
183 t << fcnPrefix << "array = ";
184 writeDEFString(t,a->array);
187 if (!a->defval.isEmpty())
189 t << fcnPrefix << "defval = <<_EnD_oF_dEf_TeXt_" << endl
190 << a->defval << endl << "_EnD_oF_dEf_TeXt_;" << endl;
192 if (defArg) ++defAli;
193 t << " }; /*" << fcnPrefix << "-param */" << endl;
198 else if ( md->memberType()==MemberType_Define
199 && md->argsString()!=0)
201 ArgumentListIterator ali(*md->argumentList());
203 QCString defPrefix = " " + memPrefix + "def-";
205 for (ali.toFirst();(a=ali.current());++ali)
207 t << memPrefix << "param = {" << endl;
208 t << defPrefix << "name = '" << a->type << "';" << endl;
209 t << " }; /*" << defPrefix << "-param */" << endl;
213 if (!md->initializer().isEmpty())
215 t << memPrefix << "initializer = <<_EnD_oF_dEf_TeXt_" << endl
216 << md->initializer() << endl << "_EnD_oF_dEf_TeXt_;" << endl;
218 // TODO: exceptions, const volatile
219 if (md->memberType()==MemberType_Enumeration) // enum
221 MemberList *enumList = md->enumFieldList();
224 MemberListIterator emli(*enumList);
226 for (emli.toFirst();(emd=emli.current());++emli)
228 t << memPrefix << "enum = { enum-name = " << emd->name() << ';';
229 if (!emd->initializer().isEmpty())
231 t << " enum-value = ";
232 writeDEFString(t,emd->initializer());
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;
247 //printf("md->getReferencesMembers()=%p\n",md->getReferencesMembers());
249 MemberSDict *mdict = md->getReferencesMembers();
252 MemberSDict::Iterator mdi(*mdict);
254 QCString refPrefix = " " + memPrefix + "ref-";
256 for (mdi.toFirst();(rmd=mdi.current());++mdi)
258 if (rmd->getStartBodyLine()!=-1 && rmd->getBodyDef())
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;
266 t << refPrefix << "line = '"
267 << rmd->getStartBodyLine() << "';" << endl;
269 QCString scope = rmd->getScopeString();
270 QCString name = rmd->name();
271 if (!scope.isEmpty() && scope!=def->name())
273 name.prepend(scope+"::");
276 t << refPrefix << "name = ";
277 writeDEFString(t,name);
278 t << ';' << endl << " };" << endl;
280 } /* for (mdi.toFirst...) */
282 mdict = md->getReferencedByMembers();
285 MemberSDict::Iterator mdi(*mdict);
287 QCString refPrefix = " " + memPrefix + "ref-";
289 for (mdi.toFirst();(rmd=mdi.current());++mdi)
291 if (rmd->getStartBodyLine()!=-1 && rmd->getBodyDef())
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;
299 t << refPrefix << "line = '"
300 << rmd->getStartBodyLine() << "';" << endl;
302 QCString scope = rmd->getScopeString();
303 QCString name = rmd->name();
304 if (!scope.isEmpty() && scope!=def->name())
306 name.prepend(scope+"::");
309 t << refPrefix << "name = ";
310 writeDEFString(t,name);
311 t << ';' << endl << " };" << endl;
313 } /* for (mdi.toFirst...) */
316 t << " }; /* " << Prefix << "-member */" << endl;
320 void generateDEFClassSection(ClassDef *cd,
325 if (cd && ml && ml->count()>0)
327 t << " cp-section = {" << endl;
328 t << " sec-kind = '" << kind << "';" << endl;
330 MemberListIterator mli(*ml);
332 for (mli.toFirst();(md=mli.current());++mli)
334 generateDEFForMember(md,t,cd,"sec");
336 t << " }; /* cp-section */" << endl;
340 void generateDEFForClass(ClassDef *cd,FTextStream &t)
342 // + brief description
343 // + detailed description
344 // - template arguments
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
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.
360 t << cd->compoundTypeString() << " = {" << endl;
361 t << " cp-id = '" << cd->getOutputFileBase() << "';" << endl;
362 t << " cp-name = '" << cd->name() << "';" << endl;
364 if (cd->baseClasses())
366 BaseClassListIterator bcli(*cd->baseClasses());
368 for (bcli.toFirst();(bcd=bcli.current());++bcli)
370 t << " cp-ref = {" << endl << " ref-type = base;" << endl;
372 << bcd->classDef->getOutputFileBase() << "';" << endl;
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;
384 case Normal: t << "non-virtual;"; break;
385 case Virtual: t << "virtual;"; break;
386 case Pure: t << "pure-virtual;"; break;
388 t << endl << " };" << endl;
392 if (cd->subClasses())
394 BaseClassListIterator bcli(*cd->subClasses());
396 for (bcli.toFirst();(bcd=bcli.current());++bcli)
398 t << " cp-ref = {" << endl << " ref-type = derived;" << endl;
400 << bcd->classDef->getOutputFileBase() << "';" << endl;
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;
412 case Normal: t << "non-virtual;"; break;
413 case Virtual: t << "virtual;"; break;
414 case Pure: t << "pure-virtual;"; break;
416 t << endl << " };" << endl;
421 QListIterator<MemberList> mli(cd->getMemberLists());
423 for (mli.toFirst();(ml=mli.current());++mli)
425 if ((ml->listType()&MemberListType_detailedLists)==0)
427 numMembers+=ml->count();
432 generateDEFClassSection(cd,t,cd->getMemberList(MemberListType_pubTypes),"public-type");
433 generateDEFClassSection(cd,t,cd->getMemberList(MemberListType_interfaces),"interfaces");
434 generateDEFClassSection(cd,t,cd->getMemberList(MemberListType_services),"services");
435 generateDEFClassSection(cd,t,cd->getMemberList(MemberListType_pubMethods),"public-func");
436 generateDEFClassSection(cd,t,cd->getMemberList(MemberListType_pubAttribs),"public-attrib");
437 generateDEFClassSection(cd,t,cd->getMemberList(MemberListType_pubSlots),"public-slot");
438 generateDEFClassSection(cd,t,cd->getMemberList(MemberListType_signals),"signal");
439 generateDEFClassSection(cd,t,cd->getMemberList(MemberListType_dcopMethods),"dcop-func");
440 generateDEFClassSection(cd,t,cd->getMemberList(MemberListType_properties),"property");
441 generateDEFClassSection(cd,t,cd->getMemberList(MemberListType_pubStaticMethods),"public-static-func");
442 generateDEFClassSection(cd,t,cd->getMemberList(MemberListType_pubStaticAttribs),"public-static-attrib");
443 generateDEFClassSection(cd,t,cd->getMemberList(MemberListType_proTypes),"protected-type");
444 generateDEFClassSection(cd,t,cd->getMemberList(MemberListType_proMethods),"protected-func");
445 generateDEFClassSection(cd,t,cd->getMemberList(MemberListType_proAttribs),"protected-attrib");
446 generateDEFClassSection(cd,t,cd->getMemberList(MemberListType_proSlots),"protected-slot");
447 generateDEFClassSection(cd,t,cd->getMemberList(MemberListType_proStaticMethods),"protected-static-func");
448 generateDEFClassSection(cd,t,cd->getMemberList(MemberListType_proStaticAttribs),"protected-static-attrib");
449 generateDEFClassSection(cd,t,cd->getMemberList(MemberListType_priTypes),"private-type");
450 generateDEFClassSection(cd,t,cd->getMemberList(MemberListType_priMethods),"private-func");
451 generateDEFClassSection(cd,t,cd->getMemberList(MemberListType_priAttribs),"private-attrib");
452 generateDEFClassSection(cd,t,cd->getMemberList(MemberListType_priSlots),"private-slot");
453 generateDEFClassSection(cd,t,cd->getMemberList(MemberListType_priStaticMethods),"private-static-func");
454 generateDEFClassSection(cd,t,cd->getMemberList(MemberListType_priStaticAttribs),"private-static-attrib");
455 generateDEFClassSection(cd,t,cd->getMemberList(MemberListType_friends),"signal");
456 generateDEFClassSection(cd,t,cd->getMemberList(MemberListType_related),"related");
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;
464 t << " cp-documentation = <<_EnD_oF_dEf_TeXt_" << endl
465 << cd->documentation() << endl << "_EnD_oF_dEf_TeXt_;" << endl;
467 DotClassGraph inheritanceGraph(cd,DotNode::Inheritance);
468 if (!inheritanceGraph.isTrivial())
470 t << " cp-inheritancegraph = <<_EnD_oF_dEf_TeXt_" << endl;
471 inheritanceGraph.writeDEF(t);
472 t << endl << "_EnD_oF_dEf_TeXt_;" << endl;
474 DotClassGraph collaborationGraph(cd,DotNode::Collaboration);
475 if (!collaborationGraph.isTrivial())
477 t << " cp-collaborationgraph = <<_EnD_oF_dEf_TeXt_" << endl;
478 collaborationGraph.writeDEF(t);
479 t << endl << "_EnD_oF_dEf_TeXt_;" << endl;
481 t << "}; /* " << cd->compoundTypeString() << " */" << endl;
484 void generateDEFSection(Definition *d,
489 if (ml && ml->count()>0)
491 t << " " << kind << " = {" << endl;
492 MemberListIterator mli(*ml);
494 for (mli.toFirst();(md=mli.current());++mli)
496 generateDEFForMember(md,t,d,kind);
502 void generateDEFForNamespace(NamespaceDef *nd,FTextStream &t)
504 if (nd->isReference()) return; // skip external references
505 t << " namespace = {" << endl;
506 t << " ns-id = '" << nd->getOutputFileBase() << "';" << endl;
508 writeDEFString(t,nd->name());
511 generateDEFSection(nd,t,nd->getMemberList(MemberListType_decDefineMembers),"define");
512 generateDEFSection(nd,t,nd->getMemberList(MemberListType_decProtoMembers),"prototype");
513 generateDEFSection(nd,t,nd->getMemberList(MemberListType_decTypedefMembers),"typedef");
514 generateDEFSection(nd,t,nd->getMemberList(MemberListType_decEnumMembers),"enum");
515 generateDEFSection(nd,t,nd->getMemberList(MemberListType_decFuncMembers),"func");
516 generateDEFSection(nd,t,nd->getMemberList(MemberListType_decVarMembers),"var");
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;
523 t << " ns-documentation = <<_EnD_oF_dEf_TeXt_" << endl
524 << nd->documentation() << endl << "_EnD_oF_dEf_TeXt_;" << endl;
528 void generateDEFForFile(FileDef *fd,FTextStream &t)
530 if (fd->isReference()) return; // skip external references
532 t << "file = {" << endl;
533 t << " file-id = '" << fd->getOutputFileBase() << "';" << endl;
534 t << " file-name = ";
535 writeDEFString(t,fd->name());
538 generateDEFSection(fd,t,fd->getMemberList(MemberListType_decDefineMembers),"define");
539 generateDEFSection(fd,t,fd->getMemberList(MemberListType_decProtoMembers),"prototype");
540 generateDEFSection(fd,t,fd->getMemberList(MemberListType_decTypedefMembers),"typedef");
541 generateDEFSection(fd,t,fd->getMemberList(MemberListType_decEnumMembers),"enum");
542 generateDEFSection(fd,t,fd->getMemberList(MemberListType_decFuncMembers),"func");
543 generateDEFSection(fd,t,fd->getMemberList(MemberListType_decVarMembers),"var");
545 t << " file-full-name = '" << fd->getDefFileName() << "';" << endl;
546 t << " file-first-line = '" << fd->getDefLine() << "';" << endl;
548 t << " file-briefdesc = <<_EnD_oF_dEf_TeXt_" << endl
549 << fd->briefDescription() << endl << "_EnD_oF_dEf_TeXt_;" << endl;
551 t << " file-documentation = <<_EnD_oF_dEf_TeXt_" << endl
552 << fd->documentation() << endl << "_EnD_oF_dEf_TeXt_;" << endl;
554 t << "}; /* file */" << endl;
560 QCString outputDirectory = Config_getString(OUTPUT_DIRECTORY);
561 if (outputDirectory.isEmpty())
563 outputDirectory=QDir::currentDirPath().utf8();
567 QDir dir(outputDirectory);
570 dir.setPath(QDir::currentDirPath());
571 if (!dir.mkdir(outputDirectory))
573 err("tag OUTPUT_DIRECTORY: Output directory `%s' does not "
574 "exist and cannot be created\n",outputDirectory.data());
579 msg("Notice: Output directory `%s' does not exist. "
580 "I have created it for you.\n", outputDirectory.data());
582 dir.cd(outputDirectory);
584 outputDirectory=dir.absPath().utf8();
587 QDir dir(outputDirectory);
590 dir.setPath(QDir::currentDirPath());
591 if (!dir.mkdir(outputDirectory))
593 err("Cannot create directory %s\n",outputDirectory.data());
597 QDir defDir(outputDirectory+"/def");
598 if (!defDir.exists() && !defDir.mkdir(outputDirectory+"/def"))
600 err("Could not create def directory in %s\n",outputDirectory.data());
604 QCString fileName=outputDirectory+"/def/doxygen.def";
606 if (!f.open(IO_WriteOnly))
608 err("Cannot open file %s for writing!\n",fileName.data());
612 t << "AutoGen Definitions dummy;" << endl;
614 if (Doxygen::classSDict->count()+Doxygen::inputNameList->count()>0)
616 ClassSDict::Iterator cli(*Doxygen::classSDict);
618 for (cli.toFirst();(cd=cli.current());++cli)
620 generateDEFForClass(cd,t);
622 FileNameListIterator fnli(*Doxygen::inputNameList);
624 for (;(fn=fnli.current());++fnli)
626 FileNameIterator fni(*fn);
628 for (;(fd=fni.current());++fni)
630 generateDEFForFile(fd,t);
636 t << "dummy_value = true;" << endl;