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_Sequence: memType="sequence"; break;
102 case MemberType_Dictionary: memType="dictionary"; break;
103 case MemberType_Function: memType="function"; isFunc=TRUE; break;
104 case MemberType_Signal: memType="signal"; isFunc=TRUE; break;
105 case MemberType_Friend: memType="friend"; isFunc=TRUE; break;
106 case MemberType_DCOP: memType="dcop"; isFunc=TRUE; break;
107 case MemberType_Slot: memType="slot"; isFunc=TRUE; break;
110 t << memPrefix << "kind = '" << memType << "';" << endl;
111 t << memPrefix << "id = '"
112 << md->getOutputFileBase() << "_1" << md->anchor()
115 t << memPrefix << "virt = ";
116 switch (md->virtualness())
118 case Normal: t << "normal;" << endl; break;
119 case Virtual: t << "virtual;" << endl; break;
120 case Pure: t << "pure-virtual;" << endl; break;
124 t << memPrefix << "prot = ";
125 switch(md->protection())
127 case Public: t << "public;" << endl; break;
128 case Protected: t << "protected;" << endl; break;
129 case Private: t << "private;" << endl; break;
130 case Package: t << "package;" << endl; break;
133 if (md->memberType()!=MemberType_Define &&
134 md->memberType()!=MemberType_Enumeration
137 QCString typeStr = replaceAnonymousScopes(md->typeString());
138 t << memPrefix << "type = <<_EnD_oF_dEf_TeXt_" << endl << typeStr << endl
139 << "_EnD_oF_dEf_TeXt_;" << endl;
142 t << memPrefix << "name = '" << md->name() << "';" << endl;
144 if (isFunc) //function
146 ArgumentList *declAl = new ArgumentList;
147 ArgumentList *defAl = md->argumentList();
148 stringToArgumentList(md->argsString(),declAl);
149 QCString fcnPrefix = " " + memPrefix + "param-";
151 if (defAl && declAl->count()>0)
153 ArgumentListIterator declAli(*declAl);
154 ArgumentListIterator defAli(*defAl);
156 for (declAli.toFirst();(a=declAli.current());++declAli)
158 Argument *defArg = defAli.current();
159 t << memPrefix << "param = {" << endl;
160 if (!a->attrib.isEmpty())
162 t << fcnPrefix << "attributes = ";
163 writeDEFString(t,a->attrib);
166 if (!a->type.isEmpty())
168 t << fcnPrefix << "type = <<_EnD_oF_dEf_TeXt_" << endl
169 << a->type << endl << "_EnD_oF_dEf_TeXt_;" << endl;
171 if (!a->name.isEmpty())
173 t << fcnPrefix << "declname = ";
174 writeDEFString(t,a->name);
177 if (defArg && !defArg->name.isEmpty() && defArg->name!=a->name)
179 t << fcnPrefix << "defname = ";
180 writeDEFString(t,defArg->name);
183 if (!a->array.isEmpty())
185 t << fcnPrefix << "array = ";
186 writeDEFString(t,a->array);
189 if (!a->defval.isEmpty())
191 t << fcnPrefix << "defval = <<_EnD_oF_dEf_TeXt_" << endl
192 << a->defval << endl << "_EnD_oF_dEf_TeXt_;" << endl;
194 if (defArg) ++defAli;
195 t << " }; /*" << fcnPrefix << "-param */" << endl;
200 else if ( md->memberType()==MemberType_Define
201 && md->argsString()!=0)
203 ArgumentListIterator ali(*md->argumentList());
205 QCString defPrefix = " " + memPrefix + "def-";
207 for (ali.toFirst();(a=ali.current());++ali)
209 t << memPrefix << "param = {" << endl;
210 t << defPrefix << "name = '" << a->type << "';" << endl;
211 t << " }; /*" << defPrefix << "-param */" << endl;
215 if (!md->initializer().isEmpty())
217 t << memPrefix << "initializer = <<_EnD_oF_dEf_TeXt_" << endl
218 << md->initializer() << endl << "_EnD_oF_dEf_TeXt_;" << endl;
220 // TODO: exceptions, const volatile
221 if (md->memberType()==MemberType_Enumeration) // enum
223 MemberList *enumList = md->enumFieldList();
226 MemberListIterator emli(*enumList);
228 for (emli.toFirst();(emd=emli.current());++emli)
230 t << memPrefix << "enum = { enum-name = " << emd->name() << ';';
231 if (!emd->initializer().isEmpty())
233 t << " enum-value = ";
234 writeDEFString(t,emd->initializer());
242 t << memPrefix << "desc-file = '" << md->getDefFileName() << "';" << endl;
243 t << memPrefix << "desc-line = '" << md->getDefLine() << "';" << endl;
244 t << memPrefix << "briefdesc = <<_EnD_oF_dEf_TeXt_" << endl
245 << md->briefDescription() << endl << "_EnD_oF_dEf_TeXt_;" << endl;
246 t << memPrefix << "documentation = <<_EnD_oF_dEf_TeXt_" << endl
247 << md->documentation() << endl << "_EnD_oF_dEf_TeXt_;" << endl;
249 //printf("md->getReferencesMembers()=%p\n",md->getReferencesMembers());
251 MemberSDict *mdict = md->getReferencesMembers();
254 MemberSDict::Iterator mdi(*mdict);
256 QCString refPrefix = " " + memPrefix + "ref-";
258 for (mdi.toFirst();(rmd=mdi.current());++mdi)
260 if (rmd->getStartBodyLine()!=-1 && rmd->getBodyDef())
262 t << memPrefix << "referenceto = {" << endl;
263 t << refPrefix << "id = '"
264 << rmd->getBodyDef()->getOutputFileBase()
265 << "_1" // encoded `:' character (see util.cpp:convertNameToFile)
266 << rmd->anchor() << "';" << endl;
268 t << refPrefix << "line = '"
269 << rmd->getStartBodyLine() << "';" << endl;
271 QCString scope = rmd->getScopeString();
272 QCString name = rmd->name();
273 if (!scope.isEmpty() && scope!=def->name())
275 name.prepend(scope+"::");
278 t << refPrefix << "name = ";
279 writeDEFString(t,name);
280 t << ';' << endl << " };" << endl;
282 } /* for (mdi.toFirst...) */
284 mdict = md->getReferencedByMembers();
287 MemberSDict::Iterator mdi(*mdict);
289 QCString refPrefix = " " + memPrefix + "ref-";
291 for (mdi.toFirst();(rmd=mdi.current());++mdi)
293 if (rmd->getStartBodyLine()!=-1 && rmd->getBodyDef())
295 t << memPrefix << "referenceby = {" << endl;
296 t << refPrefix << "id = '"
297 << rmd->getBodyDef()->getOutputFileBase()
298 << "_1" // encoded `:' character (see util.cpp:convertNameToFile)
299 << rmd->anchor() << "';" << endl;
301 t << refPrefix << "line = '"
302 << rmd->getStartBodyLine() << "';" << endl;
304 QCString scope = rmd->getScopeString();
305 QCString name = rmd->name();
306 if (!scope.isEmpty() && scope!=def->name())
308 name.prepend(scope+"::");
311 t << refPrefix << "name = ";
312 writeDEFString(t,name);
313 t << ';' << endl << " };" << endl;
315 } /* for (mdi.toFirst...) */
318 t << " }; /* " << Prefix << "-member */" << endl;
322 void generateDEFClassSection(ClassDef *cd,
327 if (cd && ml && ml->count()>0)
329 t << " cp-section = {" << endl;
330 t << " sec-kind = '" << kind << "';" << endl;
332 MemberListIterator mli(*ml);
334 for (mli.toFirst();(md=mli.current());++mli)
336 generateDEFForMember(md,t,cd,"sec");
338 t << " }; /* cp-section */" << endl;
342 void generateDEFForClass(ClassDef *cd,FTextStream &t)
344 // + brief description
345 // + detailed description
346 // - template arguments
348 // + inheritance diagram
349 // + list of direct super classes
350 // + list of direct sub classes
351 // + collaboration diagram
352 // - list of all members
353 // + user defined member sections
354 // + standard member sections
355 // + detailed member documentation
358 if (cd->isReference()) return; // skip external references.
359 if (cd->name().find('@')!=-1) return; // skip anonymous compounds.
360 if (cd->templateMaster()!=0) return; // skip generated template instances.
362 t << cd->compoundTypeString() << " = {" << endl;
363 t << " cp-id = '" << cd->getOutputFileBase() << "';" << endl;
364 t << " cp-name = '" << cd->name() << "';" << endl;
366 if (cd->baseClasses())
368 BaseClassListIterator bcli(*cd->baseClasses());
370 for (bcli.toFirst();(bcd=bcli.current());++bcli)
372 t << " cp-ref = {" << endl << " ref-type = base;" << endl;
374 << bcd->classDef->getOutputFileBase() << "';" << endl;
378 case Public: t << "public;" << endl; break;
379 case Package: // package scope is not possible
380 case Protected: t << "protected;" << endl; break;
381 case Private: t << "private;" << endl; break;
386 case Normal: t << "non-virtual;"; break;
387 case Virtual: t << "virtual;"; break;
388 case Pure: t << "pure-virtual;"; break;
390 t << endl << " };" << endl;
394 if (cd->subClasses())
396 BaseClassListIterator bcli(*cd->subClasses());
398 for (bcli.toFirst();(bcd=bcli.current());++bcli)
400 t << " cp-ref = {" << endl << " ref-type = derived;" << endl;
402 << bcd->classDef->getOutputFileBase() << "';" << endl;
406 case Public: t << "public;" << endl; break;
407 case Package: // packet scope is not possible!
408 case Protected: t << "protected;" << endl; break;
409 case Private: t << "private;" << endl; break;
414 case Normal: t << "non-virtual;"; break;
415 case Virtual: t << "virtual;"; break;
416 case Pure: t << "pure-virtual;"; break;
418 t << endl << " };" << endl;
423 QListIterator<MemberList> mli(cd->getMemberLists());
425 for (mli.toFirst();(ml=mli.current());++mli)
427 if ((ml->listType()&MemberListType_detailedLists)==0)
429 numMembers+=ml->count();
434 generateDEFClassSection(cd,t,cd->getMemberList(MemberListType_pubTypes),"public-type");
435 generateDEFClassSection(cd,t,cd->getMemberList(MemberListType_interfaces),"interfaces");
436 generateDEFClassSection(cd,t,cd->getMemberList(MemberListType_services),"services");
437 generateDEFClassSection(cd,t,cd->getMemberList(MemberListType_pubMethods),"public-func");
438 generateDEFClassSection(cd,t,cd->getMemberList(MemberListType_pubAttribs),"public-attrib");
439 generateDEFClassSection(cd,t,cd->getMemberList(MemberListType_pubSlots),"public-slot");
440 generateDEFClassSection(cd,t,cd->getMemberList(MemberListType_signals),"signal");
441 generateDEFClassSection(cd,t,cd->getMemberList(MemberListType_dcopMethods),"dcop-func");
442 generateDEFClassSection(cd,t,cd->getMemberList(MemberListType_properties),"property");
443 generateDEFClassSection(cd,t,cd->getMemberList(MemberListType_pubStaticMethods),"public-static-func");
444 generateDEFClassSection(cd,t,cd->getMemberList(MemberListType_pubStaticAttribs),"public-static-attrib");
445 generateDEFClassSection(cd,t,cd->getMemberList(MemberListType_proTypes),"protected-type");
446 generateDEFClassSection(cd,t,cd->getMemberList(MemberListType_proMethods),"protected-func");
447 generateDEFClassSection(cd,t,cd->getMemberList(MemberListType_proAttribs),"protected-attrib");
448 generateDEFClassSection(cd,t,cd->getMemberList(MemberListType_proSlots),"protected-slot");
449 generateDEFClassSection(cd,t,cd->getMemberList(MemberListType_proStaticMethods),"protected-static-func");
450 generateDEFClassSection(cd,t,cd->getMemberList(MemberListType_proStaticAttribs),"protected-static-attrib");
451 generateDEFClassSection(cd,t,cd->getMemberList(MemberListType_priTypes),"private-type");
452 generateDEFClassSection(cd,t,cd->getMemberList(MemberListType_priMethods),"private-func");
453 generateDEFClassSection(cd,t,cd->getMemberList(MemberListType_priAttribs),"private-attrib");
454 generateDEFClassSection(cd,t,cd->getMemberList(MemberListType_priSlots),"private-slot");
455 generateDEFClassSection(cd,t,cd->getMemberList(MemberListType_priStaticMethods),"private-static-func");
456 generateDEFClassSection(cd,t,cd->getMemberList(MemberListType_priStaticAttribs),"private-static-attrib");
457 generateDEFClassSection(cd,t,cd->getMemberList(MemberListType_friends),"signal");
458 generateDEFClassSection(cd,t,cd->getMemberList(MemberListType_related),"related");
461 t << " cp-filename = '" << cd->getDefFileName() << "';" << endl;
462 t << " cp-fileline = '" << cd->getDefLine() << "';" << endl;
463 t << " cp-briefdesc = <<_EnD_oF_dEf_TeXt_" << endl
464 << cd->briefDescription() << endl << "_EnD_oF_dEf_TeXt_;" << endl;
466 t << " cp-documentation = <<_EnD_oF_dEf_TeXt_" << endl
467 << cd->documentation() << endl << "_EnD_oF_dEf_TeXt_;" << endl;
469 DotClassGraph inheritanceGraph(cd,DotNode::Inheritance);
470 if (!inheritanceGraph.isTrivial())
472 t << " cp-inheritancegraph = <<_EnD_oF_dEf_TeXt_" << endl;
473 inheritanceGraph.writeDEF(t);
474 t << endl << "_EnD_oF_dEf_TeXt_;" << endl;
476 DotClassGraph collaborationGraph(cd,DotNode::Collaboration);
477 if (!collaborationGraph.isTrivial())
479 t << " cp-collaborationgraph = <<_EnD_oF_dEf_TeXt_" << endl;
480 collaborationGraph.writeDEF(t);
481 t << endl << "_EnD_oF_dEf_TeXt_;" << endl;
483 t << "}; /* " << cd->compoundTypeString() << " */" << endl;
486 void generateDEFSection(Definition *d,
491 if (ml && ml->count()>0)
493 t << " " << kind << " = {" << endl;
494 MemberListIterator mli(*ml);
496 for (mli.toFirst();(md=mli.current());++mli)
498 generateDEFForMember(md,t,d,kind);
504 void generateDEFForNamespace(NamespaceDef *nd,FTextStream &t)
506 if (nd->isReference()) return; // skip external references
507 t << " namespace = {" << endl;
508 t << " ns-id = '" << nd->getOutputFileBase() << "';" << endl;
510 writeDEFString(t,nd->name());
513 generateDEFSection(nd,t,nd->getMemberList(MemberListType_decDefineMembers),"define");
514 generateDEFSection(nd,t,nd->getMemberList(MemberListType_decProtoMembers),"prototype");
515 generateDEFSection(nd,t,nd->getMemberList(MemberListType_decTypedefMembers),"typedef");
516 generateDEFSection(nd,t,nd->getMemberList(MemberListType_decSequenceMembers),"sequence");
517 generateDEFSection(nd,t,nd->getMemberList(MemberListType_decDictionaryMembers),"dictionary");
518 generateDEFSection(nd,t,nd->getMemberList(MemberListType_decEnumMembers),"enum");
519 generateDEFSection(nd,t,nd->getMemberList(MemberListType_decFuncMembers),"func");
520 generateDEFSection(nd,t,nd->getMemberList(MemberListType_decVarMembers),"var");
522 t << " ns-filename = '" << nd->getDefFileName() << "';" << endl;
523 t << " ns-fileline = '" << nd->getDefLine() << "';" << endl;
524 t << " ns-briefdesc = <<_EnD_oF_dEf_TeXt_" << endl
525 << nd->briefDescription() << endl << "_EnD_oF_dEf_TeXt_;" << endl;
527 t << " ns-documentation = <<_EnD_oF_dEf_TeXt_" << endl
528 << nd->documentation() << endl << "_EnD_oF_dEf_TeXt_;" << endl;
532 void generateDEFForFile(FileDef *fd,FTextStream &t)
534 if (fd->isReference()) return; // skip external references
536 t << "file = {" << endl;
537 t << " file-id = '" << fd->getOutputFileBase() << "';" << endl;
538 t << " file-name = ";
539 writeDEFString(t,fd->name());
542 generateDEFSection(fd,t,fd->getMemberList(MemberListType_decDefineMembers),"define");
543 generateDEFSection(fd,t,fd->getMemberList(MemberListType_decProtoMembers),"prototype");
544 generateDEFSection(fd,t,fd->getMemberList(MemberListType_decTypedefMembers),"typedef");
545 generateDEFSection(fd,t,fd->getMemberList(MemberListType_decSequenceMembers),"sequence");
546 generateDEFSection(fd,t,fd->getMemberList(MemberListType_decDictionaryMembers),"dictionary");
547 generateDEFSection(fd,t,fd->getMemberList(MemberListType_decEnumMembers),"enum");
548 generateDEFSection(fd,t,fd->getMemberList(MemberListType_decFuncMembers),"func");
549 generateDEFSection(fd,t,fd->getMemberList(MemberListType_decVarMembers),"var");
551 t << " file-full-name = '" << fd->getDefFileName() << "';" << endl;
552 t << " file-first-line = '" << fd->getDefLine() << "';" << endl;
554 t << " file-briefdesc = <<_EnD_oF_dEf_TeXt_" << endl
555 << fd->briefDescription() << endl << "_EnD_oF_dEf_TeXt_;" << endl;
557 t << " file-documentation = <<_EnD_oF_dEf_TeXt_" << endl
558 << fd->documentation() << endl << "_EnD_oF_dEf_TeXt_;" << endl;
560 t << "}; /* file */" << endl;
566 QCString outputDirectory = Config_getString(OUTPUT_DIRECTORY);
567 if (outputDirectory.isEmpty())
569 outputDirectory=QDir::currentDirPath().utf8();
573 QDir dir(outputDirectory);
576 dir.setPath(QDir::currentDirPath());
577 if (!dir.mkdir(outputDirectory))
579 err("tag OUTPUT_DIRECTORY: Output directory `%s' does not "
580 "exist and cannot be created\n",outputDirectory.data());
585 msg("Notice: Output directory `%s' does not exist. "
586 "I have created it for you.\n", outputDirectory.data());
588 dir.cd(outputDirectory);
590 outputDirectory=dir.absPath().utf8();
593 QDir dir(outputDirectory);
596 dir.setPath(QDir::currentDirPath());
597 if (!dir.mkdir(outputDirectory))
599 err("Cannot create directory %s\n",outputDirectory.data());
603 QDir defDir(outputDirectory+"/def");
604 if (!defDir.exists() && !defDir.mkdir(outputDirectory+"/def"))
606 err("Could not create def directory in %s\n",outputDirectory.data());
610 QCString fileName=outputDirectory+"/def/doxygen.def";
612 if (!f.open(IO_WriteOnly))
614 err("Cannot open file %s for writing!\n",fileName.data());
618 t << "AutoGen Definitions dummy;" << endl;
620 if (Doxygen::classSDict->count()+Doxygen::inputNameList->count()>0)
622 ClassSDict::Iterator cli(*Doxygen::classSDict);
624 for (cli.toFirst();(cd=cli.current());++cli)
626 generateDEFForClass(cd,t);
628 FileNameListIterator fnli(*Doxygen::inputNameList);
630 for (;(fn=fnli.current());++fnli)
632 FileNameIterator fni(*fn);
634 for (;(fd=fni.current());++fni)
636 generateDEFForFile(fd,t);
642 t << "dummy_value = true;" << endl;