summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile44
-rw-r--r--src/classdef.cpp900
-rw-r--r--src/classdef.h169
-rw-r--r--src/classlist.cpp37
-rw-r--r--src/classlist.h37
-rw-r--r--src/code.h28
-rw-r--r--src/code.l747
-rw-r--r--src/config.h80
-rw-r--r--src/config.l1112
-rw-r--r--src/constexp.h30
-rw-r--r--src/constexp.l110
-rw-r--r--src/constexp.y275
-rw-r--r--src/cppvalue.cpp85
-rw-r--r--src/cppvalue.h59
-rw-r--r--src/debug.cpp62
-rw-r--r--src/debug.h39
-rw-r--r--src/declinfo.h32
-rw-r--r--src/declinfo.l292
-rw-r--r--src/defargs.h27
-rw-r--r--src/defargs.l298
-rw-r--r--src/define.cpp43
-rw-r--r--src/define.h88
-rw-r--r--src/definition.cpp44
-rw-r--r--src/definition.h64
-rw-r--r--src/diagram.cpp1236
-rw-r--r--src/diagram.h128
-rw-r--r--src/doxygen.cpp3763
-rw-r--r--src/doxygen.h134
-rw-r--r--src/doxygen.pro38
-rw-r--r--src/doxygen.t76
-rw-r--r--src/doxysearch.cpp1022
-rw-r--r--src/doxysearch.pro18
-rw-r--r--src/doxytag.l634
-rw-r--r--src/doxytag.pro24
-rw-r--r--src/doxytag.t49
-rw-r--r--src/entry.cpp242
-rw-r--r--src/entry.h153
-rw-r--r--src/example.h45
-rw-r--r--src/filedef.cpp291
-rw-r--r--src/filedef.h158
-rw-r--r--src/filename.cpp133
-rw-r--r--src/filename.h63
-rw-r--r--src/formula.cpp286
-rw-r--r--src/formula.h57
-rw-r--r--src/gifenc.cpp293
-rw-r--r--src/gifenc.h85
-rw-r--r--src/groupdef.cpp158
-rw-r--r--src/groupdef.h64
-rw-r--r--src/htmlgen.cpp512
-rw-r--r--src/htmlgen.h174
-rw-r--r--src/image.cpp443
-rw-r--r--src/image.h50
-rw-r--r--src/index.cpp975
-rw-r--r--src/index.h65
-rw-r--r--src/instdox.cpp164
-rw-r--r--src/instdox.h22
-rw-r--r--src/language.cpp61
-rw-r--r--src/language.h25
-rw-r--r--src/latexgen.cpp876
-rw-r--r--src/latexgen.h178
-rw-r--r--src/logos.cpp519
-rw-r--r--src/logos.h23
-rw-r--r--src/mangen.cpp341
-rw-r--r--src/mangen.h171
-rw-r--r--src/memberdef.cpp180
-rw-r--r--src/memberdef.h186
-rw-r--r--src/memberlist.cpp148
-rw-r--r--src/memberlist.h56
-rw-r--r--src/membername.cpp96
-rw-r--r--src/membername.h111
-rw-r--r--src/message.cpp49
-rw-r--r--src/message.h24
-rw-r--r--src/namespacedef.cpp220
-rw-r--r--src/namespacedef.h70
-rw-r--r--src/outputgen.cpp77
-rw-r--r--src/outputgen.h182
-rw-r--r--src/outputlist.cpp239
-rw-r--r--src/outputlist.h298
-rw-r--r--src/pre.h41
-rw-r--r--src/pre.l1636
-rw-r--r--src/scanner.h34
-rw-r--r--src/scanner.l3386
-rw-r--r--src/searchindex.cpp124
-rw-r--r--src/searchindex.h71
-rw-r--r--src/suffixtree.cpp355
-rw-r--r--src/suffixtree.h93
-rw-r--r--src/tag.h22
-rw-r--r--src/tag.l243
-rw-r--r--src/translator.h280
-rw-r--r--src/translator_cz.h278
-rw-r--r--src/translator_fr.h270
-rw-r--r--src/translator_it.h266
-rw-r--r--src/translator_nl.h266
-rw-r--r--src/translator_se.h250
-rw-r--r--src/unistd.h7
-rw-r--r--src/util.cpp2174
-rw-r--r--src/util.h82
-rw-r--r--src/version.h22
98 files changed, 30287 insertions, 0 deletions
diff --git a/src/Makefile b/src/Makefile
new file mode 100644
index 0000000..e57994c
--- /dev/null
+++ b/src/Makefile
@@ -0,0 +1,44 @@
+#
+# $Id$
+#
+# Copyright (C) 1997-1999 by Dimitri van Heesch.
+#
+# Permission to use, copy, modify, and distribute this software and its
+# documentation under the terms of the GNU General Public License is hereby
+# granted. No representations are made about the suitability of this software
+# for any purpose. It is provided "as is" without express or implied warranty.
+# See the GNU General Public License for more details.
+#
+# All output generated with Doxygen is not covered by this license.
+#
+
+include ../Makefile.config
+
+all: Makefile.doxygen Makefile.doxytag Makefile.doxysearch Makefile
+ $(MAKE) -f Makefile.doxygen $@
+ $(MAKE) -f Makefile.doxytag $@
+ $(MAKE) -f Makefile.doxysearch $@
+
+Makefile.doxygen: doxygen.pro doxygen.t
+ $(PERL) $(TMAKE) doxygen.pro >Makefile.doxygen
+
+Makefile.doxytag: doxytag.pro doxytag.t
+ $(PERL) $(TMAKE) doxytag.pro >Makefile.doxytag
+
+Makefile.doxysearch: doxysearch.pro
+ $(PERL) $(TMAKE) doxysearch.pro >Makefile.doxysearch
+
+tmake:
+ $(PERL) $(TMAKE) doxygen.pro >Makefile.doxygen
+ $(PERL) $(TMAKE) doxytag.pro >Makefile.doxytag
+ $(PERL) $(TMAKE) doxysearch.pro >Makefile.doxysearch
+
+clean:
+ $(MAKE) -f Makefile.doxygen clean
+ $(MAKE) -f Makefile.doxytag clean
+ $(MAKE) -f Makefile.doxysearch clean
+ -rm -f scanner.cpp code.cpp config.cpp pre.cpp ce_lex.cpp \
+ ce_parse.cpp ce_parse.h doxytag.cpp tag.cpp \
+ declinfo.cpp defargs.cpp version.cpp
+
+FORCE:
diff --git a/src/classdef.cpp b/src/classdef.cpp
new file mode 100644
index 0000000..079252d
--- /dev/null
+++ b/src/classdef.cpp
@@ -0,0 +1,900 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#include <stdio.h>
+#include <qfile.h>
+#include <qregexp.h>
+#include "classdef.h"
+#include "classlist.h"
+#include "entry.h"
+#include "scanner.h"
+#include "doxygen.h"
+#include "membername.h"
+#include "message.h"
+#include "config.h"
+#include "util.h"
+#include "diagram.h"
+#include "language.h"
+
+static QString stripExtension(const char *fName)
+{
+ QString result=fName;
+ if (result.right(5)==".html") result=result.left(result.length()-5);
+ return result;
+}
+
+// constructs a new class definition
+ClassDef::ClassDef(const char *nm,int ct,const char *ref,const char *fName)
+ : Definition(removeRedundantWhiteSpace(nm))
+{
+ //name=n;
+ if (fName)
+ fileName=stripExtension(fName);
+ else
+ fileName="class_"+nameToFile(nm);
+ if (ref)
+ {
+ //url=(QString)"doxygen=\""+ref+":\" href=\""+fileName;
+ exampleList = 0;
+ exampleDict = 0;
+ }
+ else
+ {
+ //url="href=\""+fileName;
+ exampleList = new ExampleList;
+ exampleDict = new ExampleDict(29);
+ }
+ memListFileName="class_"+nameToFile(nm)+"-members";
+ inherits = new BaseClassList;
+ inherits->setAutoDelete(TRUE);
+ inheritedBy = new BaseClassList;
+ inheritedBy->setAutoDelete(TRUE);
+ allMemberNameInfoList = new MemberNameInfoList;
+ allMemberNameInfoList->setAutoDelete(TRUE);
+ allMemberNameInfoDict = new MemberNameInfoDict(1009);
+ visited=FALSE;
+ reference=ref;
+ compType=ct;
+ incFile=0;
+ tempArgs=0;
+ prot=Public;
+ nspace=0;
+}
+
+// destroy the class definition
+ClassDef::~ClassDef()
+{
+ delete inherits;
+ delete inheritedBy;
+ delete allMemberNameInfoList;
+ delete allMemberNameInfoDict;
+ delete exampleList;
+ delete exampleDict;
+}
+
+// inserts a base class in the inheritance list
+void ClassDef::insertBaseClass(ClassDef *cd,Protection p,
+ Specifier s,const char *t)
+{
+ inherits->inSort(new BaseClassDef(cd,p,s,t));
+}
+
+// inserts a super class in the inherited list
+void ClassDef::insertSuperClass(ClassDef *cd,Protection p,
+ Specifier s,const char *t)
+{
+ inheritedBy->inSort(new BaseClassDef(cd,p,s,t));
+}
+
+// adds new member definition to the class
+void ClassDef::insertMember(const MemberDef *md)
+{
+ //printf("adding %s::%s\n",name(),md->name());
+ if (!reference)
+ {
+ if (md->isRelated() && (extractPrivateFlag || md->protection()!=Private))
+ {
+ related.append(md);
+ }
+ else if (md->isFriend())
+ {
+ friends.append(md);
+ }
+ else
+ {
+ switch (md->memberType())
+ {
+ case MemberDef::Signal:
+ signals.append(md);
+ break;
+ case MemberDef::Slot:
+ switch (md->protection())
+ {
+ case Protected: proSlots.append(md); break;
+ case Public: pubSlots.append(md); break;
+ case Private: priSlots.append(md); break;
+ }
+ break;
+ default: // any of the other members
+ if (md->isStatic())
+ {
+ switch (md->protection())
+ {
+ case Protected: proStaticMembers.append(md); break;
+ case Public: pubStaticMembers.append(md); break;
+ case Private: priStaticMembers.append(md); break;
+ }
+ }
+ else
+ {
+ switch (md->protection())
+ {
+ case Protected: proMembers.append(md); break;
+ case Public: pubMembers.append(md); break;
+ case Private: priMembers.append(md); break;
+ }
+ }
+ break;
+ }
+ }
+ }
+ // check if we should add this member in the `all members' list
+ if (md->isFriend() || md->protection()!=Private || extractPrivateFlag)
+ {
+ MemberInfo *mi = new MemberInfo((MemberDef *)md,Public,Normal);
+ MemberNameInfo *mni;
+ if ((mni=(*allMemberNameInfoDict)[md->name()]))
+ {
+ mni->append(mi);
+ }
+ else
+ {
+ mni = new MemberNameInfo(md->name());
+ mni->append(mi);
+ allMemberNameInfoList->inSort(mni);
+ allMemberNameInfoDict->insert(mni->memberName(),mni);
+ }
+ }
+}
+
+
+// compute the anchors for all members
+void ClassDef::computeAnchors()
+{
+ setAnchors('a',&pubMembers);
+ setAnchors('b',&proMembers);
+ setAnchors('c',&priMembers);
+ setAnchors('d',&pubStaticMembers);
+ setAnchors('e',&proStaticMembers);
+ setAnchors('f',&priStaticMembers);
+ setAnchors('g',&pubSlots);
+ setAnchors('h',&proSlots);
+ setAnchors('i',&priSlots);
+ setAnchors('j',&signals);
+ setAnchors('k',&related);
+ setAnchors('l',&friends);
+}
+
+// add a file name to the used files set
+void ClassDef::insertUsedFile(const char *f)
+{
+ if (files.find(f)==-1) files.append(f);
+}
+
+static void writeInheritanceSpecifier(OutputList &ol,BaseClassDef *bcd)
+{
+ if (bcd->prot!=Public || bcd->virt!=Normal)
+ {
+ ol.startTypewriter();
+ ol.docify(" [");
+ QStrList sl;
+ if (bcd->prot==Protected) sl.append("protected");
+ else if (bcd->prot==Private) sl.append("private");
+ if (bcd->virt==Virtual) sl.append("virtual");
+ const char *s=sl.first();
+ while (s)
+ {
+ ol.docify(s);
+ s=sl.next();
+ if (s) ol.docify(", ");
+ }
+ ol.docify("]");
+ ol.endTypewriter();
+ }
+}
+
+// write all documentation for this class
+void ClassDef::writeDocumentation(OutputList &ol)
+{
+ // write title
+ QString pageTitle=name().copy();
+ QString pageType;
+ switch(compType)
+ {
+ case Class: pageType=" Class"; break;
+ case Struct: pageType=" Struct"; break;
+ case Union: pageType=" Union"; break;
+ default: pageType+=compType; break; // an error
+ }
+ pageTitle+=pageType+" Reference";
+ startFile(ol,fileName,pageTitle);
+ startTitle(ol);
+ ol.docify(name()+" "+pageType.right(pageType.length()-1)+" ");
+ parseDoc(ol,0,0,theTranslator->trReference());
+ endTitle(ol,name());
+
+ // write brief description
+ OutputList briefOutput(&ol);
+ if (!briefDescription().isEmpty())
+ {
+ parseDoc(briefOutput,name(),0,briefDescription());
+ ol+=briefOutput;
+ ol.writeString(" \n");
+ ol.disableAllBut(OutputGenerator::Html);
+ ol.startTextLink(0,"details");
+ parseDoc(ol,0,0,theTranslator->trMore());
+ ol.endTextLink();
+ ol.enableAll();
+ }
+ ol.disable(OutputGenerator::Man);
+ ol.newParagraph();
+ ol.enable(OutputGenerator::Man);
+ ol.writeSynopsis();
+
+ if (incFile)
+ {
+ QString nm=incName.copy();
+ if (incName.isNull()) nm=incFile->name();
+ ol.startTypewriter();
+ ol.docify("#include <");
+ ol.disable(OutputGenerator::Man);
+ if (verbatimHeaderFlag)
+ {
+ ol.writeObjectLink(0,fileName+"-include",0,nm);
+ }
+ else
+ {
+ ol.docify(nm);
+ }
+ ol.enable(OutputGenerator::Man);
+ ol.disableAllBut(OutputGenerator::Man);
+ ol.docify(nm);
+ ol.enableAll();
+ ol.docify(">");
+ ol.endTypewriter();
+ ol.newParagraph();
+ }
+
+ if (genTagFile.length()>0) tagFile << ">" << name() << ":";
+
+ if (classDiagramFlag) ol.disableAllBut(OutputGenerator::Man);
+
+ // write superclasses
+ int count;
+ if ((count=inherits->count())>0)
+ {
+ parseDoc(ol,0,0,theTranslator->trInherits()+" ");
+ BaseClassDef *bcd=inherits->first();
+ while (bcd)
+ {
+ ClassDef *cd=bcd->classDef;
+ if (cd->hasDocumentation() || cd->isReference())
+ {
+ if (genTagFile.length()>0) tagFile << cd->classFile() << "?";
+ ol.writeObjectLink(cd->getReference(),cd->classFile(),0,cd->name()+bcd->templSpecifiers);
+ }
+ else
+ {
+ ol.docify(cd->name());
+ }
+ writeInheritanceSpecifier(ol,bcd);
+ bcd=inherits->next();
+ if (bcd)
+ {
+ if (inherits->at()==count-1)
+ parseDoc(ol,0,0," "+theTranslator->trAnd()+" ");
+ else
+ ol.writeString(", ");
+ }
+ }
+ ol.writeString(".");
+ ol.newParagraph();
+ }
+
+ if (genTagFile.length()>0) tagFile << " \"" << fileName << ".html\"\n";
+
+ // write subclasses
+ if ((count=inheritedBy->count())>0)
+ {
+ parseDoc(ol,0,0,theTranslator->trInheritedBy()+" ");
+ BaseClassDef *bcd=inheritedBy->first();
+ while (bcd)
+ {
+ ClassDef *cd=bcd->classDef;
+ if (cd->hasDocumentation() || cd->isReference())
+ {
+ ol.writeObjectLink(cd->getReference(),cd->classFile(),0,cd->name());
+ }
+ else
+ {
+ ol.docify(cd->name());
+ }
+ writeInheritanceSpecifier(ol,bcd);
+ bcd=inheritedBy->next();
+ if (bcd)
+ {
+ if (inheritedBy->at()==count-1)
+ parseDoc(ol,0,0," "+theTranslator->trAnd()+" ");
+ else
+ ol.writeString(", ");
+ }
+ }
+ ol.writeString(".");
+ ol.newParagraph();
+ }
+
+ if (classDiagramFlag) ol.enableAll();
+
+ count=0;
+ BaseClassDef *ibcd;
+ ibcd=inheritedBy->first();
+ while (ibcd)
+ {
+ ClassDef *icd=ibcd->classDef;
+ if (//(icd->protection()!=Private || extractPrivateFlag) &&
+ //(icd->hasDocumentation() || !hideClassFlag || icd->isReference())
+ icd->isVisibleExt()
+ ) count++;
+ ibcd=inheritedBy->next();
+ }
+ ibcd=inherits->first();
+ while (ibcd)
+ {
+ ClassDef *icd=ibcd->classDef;
+ if (//(icd->protection()!=Private || extractPrivateFlag) &&
+ //(icd->hasDocumentation() || !hideClassFlag | icd->isReference())
+ icd->isVisibleExt()
+ ) count++;
+ ibcd=inherits->next();
+ }
+ if (classDiagramFlag && count>0)
+ // write class diagram
+ {
+ ClassDiagram diagram(this); // create a diagram of this class.
+ ol.startClassDiagram();
+ ol.disable(OutputGenerator::Man);
+ parseDoc(ol,name(),0,theTranslator->trClassDiagram(name()));
+ ol.enable(OutputGenerator::Man);
+ ol.endClassDiagram(diagram,fileName,name());
+ }
+
+ // write link to list of all members (HTML only)
+ if (allMemberNameInfoList->count()>0 && compType==Class)
+ {
+ ol.disableAllBut(OutputGenerator::Html);
+ ol.startTextLink(memListFileName,0);
+ parseDoc(ol,0,0,theTranslator->trListOfAllMembers());
+ ol.endTextLink();
+ ol.enableAll();
+ }
+
+ // write member groups
+ writeMemberDecs(ol,this,0,0,"Public Members",0,&pubMembers);
+ writeMemberDecs(ol,this,0,0,"Public Slots",0,&pubSlots);
+ writeMemberDecs(ol,this,0,0,"Signals",0,&signals);
+ writeMemberDecs(ol,this,0,0,"Static Public Members",0,&pubStaticMembers);
+ writeMemberDecs(ol,this,0,0,"Protected Members",0,&proMembers);
+ writeMemberDecs(ol,this,0,0,"Protected Slots",0,&proSlots);
+ writeMemberDecs(ol,this,0,0,"Static Protected Members",0,&proStaticMembers);
+ if (extractPrivateFlag)
+ {
+ writeMemberDecs(ol,this,0,0,"Private Members",0,&priMembers);
+ writeMemberDecs(ol,this,0,0,"Private Slots",0,&priSlots);
+ writeMemberDecs(ol,this,0,0,"Static Private Members",0,&priStaticMembers);
+ }
+ writeMemberDecs(ol,this,0,0,"Friends",0,&friends);
+ writeMemberDecs(ol,this,0,0,
+ theTranslator->trRelatedFunctions(),
+ theTranslator->trRelatedSubscript(),
+ &related
+ );
+
+ // write detailed description
+ bool exampleFlag=hasExamples();
+ if (!briefDescription().isEmpty() || !documentation().isEmpty() || exampleFlag)
+ {
+ ol.writeRuler();
+ ol.writeAnchor("details");
+ ol.startGroupHeader();
+ parseDoc(ol,0,0,theTranslator->trDetailedDescription());
+ ol.endGroupHeader();
+ if (tempArgs) // class is a template
+ {
+ ol.startSubsubsection();
+ ArgumentList *al=tempArgs;
+ ol.docify("template<");
+ Argument *a=al->first();
+ while (a)
+ {
+ ol.docify(a->type);
+ ol.docify(a->name);
+ if (a->defval.length()!=0)
+ {
+ ol.docify(" = ");
+ ol.docify(a->defval);
+ }
+ a=al->next();
+ if (a) ol.docify(", ");
+ }
+ ol.docify("> "+pageType.lower()+" "+name());
+ ol.endSubsubsection();
+ ol.writeString("\n");
+ }
+
+ // repeat brief description
+ if (!briefDescription().isEmpty())
+ {
+ ol+=briefOutput;
+ ol.newParagraph();
+ }
+ // write documentation
+ if (!documentation().isEmpty())
+ {
+ parseDoc(ol,name(),0,documentation()+"\n");
+ }
+ // write examples
+ if (exampleFlag)
+ {
+ ol.startDescList();
+ ol.startBold();
+ parseDoc(ol,0,0,theTranslator->trExamples()+": ");
+ ol.endBold();
+ ol.endDescTitle();
+ ol.writeDescItem();
+ writeExample(ol);
+ //ol.endDescItem();
+ ol.endDescList();
+ }
+ }
+
+ pubMembers.countDocMembers();
+ proMembers.countDocMembers();
+ priMembers.countDocMembers();
+ pubStaticMembers.countDocMembers();
+ proStaticMembers.countDocMembers();
+ priStaticMembers.countDocMembers();
+ pubSlots.countDocMembers();
+ proSlots.countDocMembers();
+ priSlots.countDocMembers();
+ related.countDocMembers();
+ friends.countDocMembers();
+ signals.countDocMembers();
+
+ if ( pubMembers.typedefCount() + proMembers.typedefCount() +
+ (extractPrivateFlag ? priMembers.typedefCount() : 0 )
+ )
+ {
+ ol.writeRuler();
+ ol.startGroupHeader();
+ parseDoc(ol,0,0,theTranslator->trMemberTypedefDocumentation());
+ ol.endGroupHeader();
+
+ writeMemberDocs(ol,&pubMembers,name(),MemberDef::Typedef);
+ writeMemberDocs(ol,&proMembers,name(),MemberDef::Typedef);
+ if (extractPrivateFlag)
+ {
+ writeMemberDocs(ol,&priMembers,name(),MemberDef::Typedef);
+ }
+ }
+
+ if (pubMembers.enumCount() +
+ proMembers.enumCount() +
+ ( extractPrivateFlag ? priMembers.enumCount() : 0 )
+ )
+ {
+ ol.writeRuler();
+ ol.startGroupHeader();
+ parseDoc(ol,0,0,theTranslator->trMemberEnumerationDocumentation());
+ ol.endGroupHeader();
+
+ writeMemberDocs(ol,&pubMembers,name(),MemberDef::Enumeration);
+ writeMemberDocs(ol,&proMembers,name(),MemberDef::Enumeration);
+ if (extractPrivateFlag)
+ {
+ writeMemberDocs(ol,&priMembers,name(),MemberDef::Enumeration);
+ }
+ }
+
+ if (pubMembers.enumValueCount() +
+ proMembers.enumValueCount() +
+ ( extractPrivateFlag ? priMembers.enumValueCount() : 0 )
+ )
+ {
+ ol.writeRuler();
+ ol.startGroupHeader();
+ parseDoc(ol,0,0,theTranslator->trEnumerationValueDocumentation());
+ ol.endGroupHeader();
+
+ writeMemberDocs(ol,&pubMembers,name(),MemberDef::EnumValue);
+ writeMemberDocs(ol,&proMembers,name(),MemberDef::EnumValue);
+ if (extractPrivateFlag)
+ {
+ writeMemberDocs(ol,&priMembers,name(),MemberDef::EnumValue);
+ }
+ }
+
+ if ( pubMembers.funcCount() + pubSlots.funcCount() +
+ pubStaticMembers.funcCount() +
+ proMembers.funcCount() + proSlots.funcCount() +
+ proStaticMembers.funcCount() +
+ (extractPrivateFlag ?
+ priMembers.funcCount() + priSlots.funcCount() +
+ priStaticMembers.funcCount() : 0
+ )
+ )
+ {
+ ol.writeRuler();
+ ol.startGroupHeader();
+ parseDoc(ol,0,0,theTranslator->trMemberFunctionDocumentation());
+ ol.endGroupHeader();
+
+ writeMemberDocs(ol,&pubMembers,name(),MemberDef::Function);
+ writeMemberDocs(ol,&pubSlots,name(),MemberDef::Slot);
+ writeMemberDocs(ol,&signals,name(),MemberDef::Signal);
+ writeMemberDocs(ol,&pubStaticMembers,name(),MemberDef::Function);
+ writeMemberDocs(ol,&proMembers,name(),MemberDef::Function);
+ writeMemberDocs(ol,&proSlots,name(),MemberDef::Slot);
+ writeMemberDocs(ol,&proStaticMembers,name(),MemberDef::Function);
+ if (extractPrivateFlag)
+ {
+ writeMemberDocs(ol,&priMembers,name(),MemberDef::Function);
+ writeMemberDocs(ol,&priSlots,name(),MemberDef::Slot);
+ writeMemberDocs(ol,&priStaticMembers,name(),MemberDef::Function);
+ }
+ }
+
+ if ( friends.count() + related.count() )
+ {
+ ol.writeRuler();
+ ol.startGroupHeader();
+ parseDoc(ol,0,0,theTranslator->trRelatedFunctionDocumentation());
+ ol.endGroupHeader();
+ writeMemberDocs(ol,&friends,name(),MemberDef::Friend);
+ writeMemberDocs(ol,&related,name(),MemberDef::Function);
+ }
+
+
+ if ( pubMembers.varCount() + pubStaticMembers.varCount() +
+ proMembers.varCount() + proStaticMembers.varCount() +
+ (extractPrivateFlag ?
+ priMembers.varCount() + priStaticMembers.varCount() : 0
+ )
+ )
+ {
+ ol.writeRuler();
+ ol.startGroupHeader();
+ parseDoc(ol,0,0,theTranslator->trMemberDataDocumentation());
+ ol.endGroupHeader();
+
+ writeMemberDocs(ol,&pubMembers,name(),MemberDef::Variable);
+ writeMemberDocs(ol,&pubStaticMembers,name(),MemberDef::Variable);
+ writeMemberDocs(ol,&proMembers,name(),MemberDef::Variable);
+ writeMemberDocs(ol,&proStaticMembers,name(),MemberDef::Variable);
+ if (extractPrivateFlag)
+ {
+ writeMemberDocs(ol,&priMembers,name(),MemberDef::Variable);
+ writeMemberDocs(ol,&priStaticMembers,name(),MemberDef::Variable);
+ }
+ }
+
+ // write the list of used files (Html and LaTeX only)
+ ol.disable(OutputGenerator::Man);
+ ol.writeRuler();
+ parseDoc(ol,0,0,
+ theTranslator->trGeneratedFrom(pageType.lower(),
+ files.count()==1));
+ ol.startItemList();
+
+ const char *file = files.first();
+ while (file)
+ {
+ QFileInfo fi(file);
+ ol.writeListItem();
+ FileDef *fd;
+ bool ambig;
+ if ((fd=findFileDef(&inputNameDict,fi.absFilePath(),ambig))
+ && fd->hasDocumentation())
+ {
+ ol.writeObjectLink(fd->getReference(),fd->diskName(),0,
+ fi.fileName());
+ }
+ else
+ {
+ ol.docify(fi.fileName());
+ }
+ file=files.next();
+ }
+
+ ol.endItemList();
+ ol.enable(OutputGenerator::Man);
+
+ // write Author section (Man only)
+ ol.disableAllBut(OutputGenerator::Man);
+ ol.writeString("\n");
+ ol.startGroupHeader();
+ parseDoc(ol,0,0,theTranslator->trAuthor());
+ ol.endGroupHeader();
+ parseDoc(ol,0,0,theTranslator->trGeneratedAutomatically(projectName));
+ ol.enableAll();
+
+ endFile(ol);
+}
+
+// write the list of all (inherited) members for this class
+void ClassDef::writeMemberList(OutputList &ol)
+{
+ if (allMemberNameInfoList->count()==0) return;
+ // do not generate Latex output
+ ol.disableAllBut(OutputGenerator::Html);
+ startFile(ol,memListFileName,theTranslator->trMemberList());
+ startTitle(ol);
+ parseDoc(ol,name(),0,name()+" "+theTranslator->trMemberList());
+ endTitle(ol,0);
+ parseDoc(ol,0,0,theTranslator->trThisIsTheListOfAllMembers());
+ ol.writeString(" ");
+ ol.writeObjectLink(reference,fileName,0,name());
+ ol.writeString(", ");
+ parseDoc(ol,0,0,theTranslator->trIncludingInheritedMembers());
+
+ ol.startItemList();
+
+ MemberNameInfo *mni=allMemberNameInfoList->first();
+ while (mni)
+ {
+ MemberInfo *mi=mni->first();
+ while (mi)
+ {
+ MemberDef *md=mi->memberDef;
+ ClassDef *cd=md->memberClass();
+
+ // compute the protection level for this member
+ Protection protect=md->protection();
+ if (mi->prot==Protected) // inherited protection
+ {
+ if (protect==Public) protect=Protected;
+ else if (protect==Protected) protect=Private;
+ }
+
+ //printf("Member %s of class %s mi->prot=%d prot=%d\n",
+ // md->name().data(),cd->name().data(),mi->prot,protect);
+
+ Specifier virt=md->virtualness();
+ MemberDef *rmd=md->reimplements();
+ while (rmd && virt==Normal)
+ {
+ virt = rmd->virtualness()==Normal ? Normal : Virtual;
+ rmd = rmd->reimplements();
+ }
+
+ if (cd && !md->name().isEmpty() && md->name()[0]!='@' &&
+ (
+ md->isFriend() ||
+ (mi->prot!=Private && (protect!=Private || extractPrivateFlag))
+ )
+ )
+ {
+ bool memberWritten=FALSE;
+ if (cd->isVisible() && (md->hasDocumentation() || md->isReference()))
+ // create a link to the documentation
+ {
+ QString name=mi->ambiguityResolutionScope+md->name();
+ ol.writeListItem();
+ ol.writeObjectLink(cd->getReference(),cd->classFile(),
+ md->anchor(),name);
+ if ( md->isFunction() || md->isSignal() || md->isSlot() )
+ ol.docify(md->argsString());
+ else if (md->isEnumerate())
+ parseDoc(ol,0,0," "+theTranslator->trEnumName());
+ else if (md->isEnumValue())
+ parseDoc(ol,0,0," "+theTranslator->trEnumValue());
+ else if (md->isTypedef())
+ ol.docify(" typedef");
+ else if (md->isFriend() && !strcmp(md->typeString(),"friend class"))
+ ol.docify(" class");
+ ol.writeString("\n");
+ memberWritten=TRUE;
+ }
+ else if (!hideMemberFlag) // no documentation,
+ // generate link to the class instead.
+ {
+ ol.writeListItem();
+ ol.writeBoldString(md->name());
+ if ( md->isFunction() || md->isSignal() || md->isSlot() )
+ ol.docify(md->argsString());
+ else if (md->isEnumerate())
+ parseDoc(ol,0,0," "+theTranslator->trEnumName());
+ else if (md->isEnumValue())
+ parseDoc(ol,0,0," "+theTranslator->trEnumValue());
+ else if (md->isTypedef())
+ ol.docify(" typedef");
+ ol.writeString(" (");
+ parseDoc(ol,0,0,theTranslator->trDefinedIn()+" ");
+ if (cd->isVisible())
+ {
+ ol.writeObjectLink(cd->getReference(),cd->classFile(),0,cd->name());
+ }
+ else
+ {
+ ol.writeBoldString(cd->name());
+ }
+ ol.writeString(")");
+ memberWritten=TRUE;
+ }
+ if ((protect!=Public || md->isStatic() || virt!=Normal ||
+ md->isFriend() || md->isRelated()
+ )
+ && memberWritten)
+ {
+ ol.startTypewriter();
+ ol.docify(" [");
+ QStrList sl;
+ if (md->isFriend()) sl.append("friend");
+ else if (md->isRelated()) sl.append("related");
+ else
+ {
+ if (protect==Protected) sl.append("protected");
+ else if (protect==Private) sl.append("private");
+ if (virt==Virtual) sl.append("virtual");
+ else if (virt==Pure) sl.append("pure virtual");
+ if (md->isStatic()) sl.append("static");
+ if (md->isSignal()) sl.append("signal");
+ if (md->isSlot()) sl.append("slot");
+ }
+ const char *s=sl.first();
+ while (s)
+ {
+ ol.docify(s);
+ s=sl.next();
+ if (s) ol.docify(", ");
+ }
+ ol.docify("]");
+ ol.endTypewriter();
+ }
+ }
+ mi=mni->next();
+ }
+ mni=allMemberNameInfoList->next();
+ }
+ ol.endItemList();
+ endFile(ol);
+ ol.enableAll();
+}
+
+void ClassDef::writeIncludeFile(OutputList &ol)
+{
+ if (!incFile) return;
+ //printf("incFile=%s\n",incFile->absFilePath().data());
+ ol.disableAllBut(OutputGenerator::Html);
+ startFile(ol,fileName+"-include",name()+" Include File");
+ startTitle(ol);
+ QString n=incName.copy();
+ if (incName.isNull()) n=incFile->name();
+ parseDoc(ol,0,0,n);
+ endTitle(ol,0);
+ parseDoc(ol,0,0,theTranslator->trVerbatimText(incFile->name()));
+ ol.writeRuler();
+ ol.startCodeFragment();
+ parseCode(ol,n,fileToString(incFile->absFilePath()),FALSE,0);
+ ol.endCodeFragment();
+ endFile(ol);
+ ol.enableAll();
+}
+
+// add a reference to an example
+bool ClassDef::addExample(const char *anchor,const char *nameStr,
+ const char *file)
+{
+ if (exampleDict && !exampleDict->find(nameStr))
+ {
+ Example *e=new Example;
+ e->anchor=anchor;
+ e->name=nameStr;
+ e->file=file;
+ exampleDict->insert(nameStr,e);
+ exampleList->inSort(e);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+// returns TRUE if this class is used in an example
+bool ClassDef::hasExamples()
+{
+ if (exampleList==0)
+ return FALSE;
+ else
+ return exampleList->count()>0;
+}
+
+// write the list of all examples that are use this class.
+void ClassDef::writeExample(OutputList &ol)
+{
+ Example *e=exampleList->first();
+ while (e)
+ {
+ ol.writeObjectLink(0,e->file,e->anchor,e->name);
+ e=exampleList->next();
+ if (e)
+ {
+ if (exampleList->at()==(int)exampleList->count()-1)
+ parseDoc(ol,0,0," "+theTranslator->trAnd()+" ");
+ else
+ ol.writeString(", ");
+ }
+ }
+ ol.writeString(".");
+}
+
+void ClassDef::setTemplateArguments(ArgumentList *al)
+{
+ if (al==0) return;
+ if (!tempArgs) delete tempArgs; // delete old list if needed
+ tempArgs=new ArgumentList;
+ tempArgs->setAutoDelete(TRUE);
+ ArgumentListIterator ali(*al);
+ Argument *a;
+ for (;(a=ali.current());++ali)
+ {
+ tempArgs->append(new Argument(*a));
+ }
+}
+
+QString ClassDef::getTemplateNameString()
+{
+ QString result;
+ if (!tempArgs || tempArgs->count()==0) return result;
+ result="<";
+ Argument *a=tempArgs->first();
+ while (a)
+ {
+ if (a->name.length()>0) // add template argument name
+ {
+ result+=a->name;
+ }
+ else // extract name from type
+ {
+ int i=a->type.length()-1;
+ while (i>=0 && isId(a->type.at(i))) i--;
+ if (i>0)
+ {
+ result+=a->type.right(a->type.length()-i-1);
+ }
+ }
+ a=tempArgs->next();
+ if (a) result+=", ";
+ }
+ result+=">";
+ return result;
+}
+
+bool ClassDef::hasNonReferenceSuperClass()
+{
+ bool found=!isReference();
+ BaseClassListIterator bcli(*inheritedBy);
+ for ( ; bcli.current() && !found ; ++bcli )
+ found=found || bcli.current()->classDef->hasNonReferenceSuperClass();
+ return found;
+}
diff --git a/src/classdef.h b/src/classdef.h
new file mode 100644
index 0000000..8fe0f21
--- /dev/null
+++ b/src/classdef.h
@@ -0,0 +1,169 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#ifndef CLASSDEF_H
+#define CLASSDEF_H
+
+#include <qstring.h>
+#include <qfileinf.h>
+#include <qlist.h>
+#include <qdict.h>
+#include <qtstream.h>
+#include <qstrlist.h>
+
+#include "membername.h"
+#include "memberlist.h"
+#include "memberdef.h"
+#include "example.h"
+#include "entry.h"
+#include "definition.h"
+
+typedef QDict<MemberDef> MemberDict;
+class ClassList;
+class OutputList;
+class FileDef;
+class BaseClassList;
+class MemberInfoList;
+class MemberInfoDict;
+class NamespaceDef;
+
+class ClassDef : public Definition
+{
+ public:
+
+ enum CompoundType { Class=Entry::CLASS_SEC,
+ Struct=Entry::STRUCT_SEC,
+ Union=Entry::UNION_SEC
+ };
+
+ ClassDef(const char *name,int ct,const char *ref=0,const char *fName=0);
+ ~ClassDef();
+ QString classFile() const { return fileName; }
+ int compoundType() const { return compType; }
+ const char *memberListFileName() const { return memListFileName; }
+ void insertBaseClass(ClassDef *,Protection p,Specifier s,const char *t=0);
+ BaseClassList *baseClasses() { return inherits; }
+ void insertSuperClass(ClassDef *,Protection p,Specifier s,const char *t=0);
+ BaseClassList *superClasses() { return inheritedBy; }
+ void setIncludeFile(FileDef *fd) { incFile=fd; }
+ FileDef *includeFile() const { return incFile; }
+ void setIncludeName(const char *n_) { incName=n_; }
+ MemberNameInfoList *memberNameInfoList() { return allMemberNameInfoList; }
+ MemberNameInfoDict *memberNameInfoDict() { return allMemberNameInfoDict; }
+ bool isReference() { return !reference.isNull(); }
+ const char *getReference() const { return reference; }
+ void insertMember(const MemberDef *);
+ void insertUsedFile(const char *);
+ void computeAnchors();
+ void setAnchor(MemberDef *);
+ void dumpMembers();
+ void writeDocumentation(OutputList &ol);
+ void writeMemberList(OutputList &ol);
+ void writeIncludeFile(OutputList &ol);
+ bool addExample(const char *anchor,const char *name, const char *file);
+ bool hasExamples();
+ void writeExample(OutputList &ol);
+ void setProtection(Protection p) { prot=p; }
+ Protection protection() const { return prot; }
+ bool isVisible()
+ { return !name().isEmpty() && name().at(0)!='@' &&
+ (prot!=Private || extractPrivateFlag) &&
+ hasDocumentation();
+ }
+ bool hasNonReferenceSuperClass();
+ bool isVisibleExt()
+ { return (allExtFlag || hasNonReferenceSuperClass()) &&
+ !name().isEmpty() && name().at(0)!='@' &&
+ (prot!=Private || extractPrivateFlag) &&
+ (hasDocumentation() || !hideClassFlag || !reference.isNull());
+ }
+
+ // template argument functions
+ ArgumentList *templateArguments() const { return tempArgs; }
+ void setTemplateArguments(ArgumentList *al);
+ QString getTemplateNameString();
+ void setNamespace(NamespaceDef *nd) { nspace = nd; }
+ NamespaceDef *getNamespace() { return nspace; }
+
+ bool visited;
+
+ private:
+ //QString name; // name of the class
+ QString fileName; // HTML containing the class docs
+ //QString doc; // general class documentation
+ FileDef *incFile; // header file to refer to
+ QString incName; // alternative include file name
+ //QString brief; // brief class discription
+ QString memListFileName;
+ BaseClassList *inherits;
+ BaseClassList *inheritedBy;
+ NamespaceDef *nspace; // the namespace this class is in
+ MemberList pubMembers;
+ MemberList proMembers;
+ MemberList priMembers;
+ MemberList pubStaticMembers;
+ MemberList proStaticMembers;
+ MemberList priStaticMembers;
+ MemberList pubSlots;
+ MemberList proSlots;
+ MemberList priSlots;
+ MemberList related;
+ MemberList signals;
+ MemberList friends;
+ MemberNameInfoList *allMemberNameInfoList;
+ MemberNameInfoDict *allMemberNameInfoDict;
+ ArgumentList *tempArgs;
+ QStrList files;
+ QString reference;
+ ExampleList *exampleList;
+ ExampleDict *exampleDict;
+ int compType;
+ Protection prot;
+};
+
+
+struct BaseClassDef
+{
+ BaseClassDef(ClassDef *cd,Protection p,Specifier v,const char *t) :
+ classDef(cd), prot(p), virt(v), templSpecifiers(t) {}
+ ClassDef *classDef;
+ Protection prot;
+ Specifier virt;
+ QString templSpecifiers;
+};
+
+class BaseClassList : public QList<BaseClassDef>
+{
+ public:
+ int compareItems(GCI item1,GCI item2)
+ {
+ ClassDef *c1=((BaseClassDef *)item1)->classDef;
+ ClassDef *c2=((BaseClassDef *)item2)->classDef;
+ if (c1==0 || c2==0)
+ return FALSE;
+ else
+ return strcmp(c1->name(),c2->name());
+ }
+};
+
+class BaseClassListIterator : public QListIterator<BaseClassDef>
+{
+ public:
+ BaseClassListIterator(const BaseClassList &bcl) :
+ QListIterator<BaseClassDef>(bcl) {}
+};
+
+#endif
diff --git a/src/classlist.cpp b/src/classlist.cpp
new file mode 100644
index 0000000..518f757
--- /dev/null
+++ b/src/classlist.cpp
@@ -0,0 +1,37 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#include "classlist.h"
+
+ClassList::ClassList() : QList<ClassDef>()
+{
+}
+
+ClassList::~ClassList()
+{
+}
+
+int ClassList::compareItems(GCI item1, GCI item2)
+{
+ ClassDef *c1=(ClassDef *)item1;
+ ClassDef *c2=(ClassDef *)item2;
+ return strcmp(c1->name(),c2->name());
+}
+
+ClassListIterator::ClassListIterator(const ClassList &cllist) :
+ QListIterator<ClassDef>(cllist)
+{
+}
diff --git a/src/classlist.h b/src/classlist.h
new file mode 100644
index 0000000..28d8454
--- /dev/null
+++ b/src/classlist.h
@@ -0,0 +1,37 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#ifndef CLASSLIST_H
+#define CLASSLIST_H
+
+#include "classdef.h"
+
+class ClassList : public QList<ClassDef>
+{
+ public:
+ ClassList();
+ ~ClassList();
+
+ int compareItems(GCI item1,GCI item2);
+};
+
+class ClassListIterator : public QListIterator<ClassDef>
+{
+ public:
+ ClassListIterator(const ClassList &list);
+};
+
+#endif
diff --git a/src/code.h b/src/code.h
new file mode 100644
index 0000000..4b781fb
--- /dev/null
+++ b/src/code.h
@@ -0,0 +1,28 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#ifndef CODE_H
+#define CODE_H
+
+#include <stdio.h>
+#include <qstring.h>
+
+class OutputList;
+
+extern void parseCode(OutputList &,const char *,const QString &,
+ bool ,const char *);
+extern void initParseCodeContext();
+#endif
diff --git a/src/code.l b/src/code.l
new file mode 100644
index 0000000..8bff410
--- /dev/null
+++ b/src/code.l
@@ -0,0 +1,747 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+%{
+
+/*
+ * includes
+ */
+#include <stdio.h>
+#include <iostream.h>
+#include <assert.h>
+#include <ctype.h>
+
+#include <qstring.h>
+
+#include "scanner.h"
+#include "entry.h"
+#include "doxygen.h"
+#include "message.h"
+#include "outputlist.h"
+#include "util.h"
+
+#define YY_NO_UNPUT
+#define YY_NEVER_INTERACTIVE 1
+
+class CodeClassDef
+{
+ public:
+ CodeClassDef() {}
+ CodeClassDef(const CodeClassDef &d)
+ {
+ name = d.name;
+ bases = d.bases;
+ }
+ ~CodeClassDef() {}
+
+ QString name;
+ QStrList bases;
+};
+
+class CodeVarDef
+{
+ public:
+ CodeVarDef() {}
+ CodeVarDef(const CodeVarDef &d)
+ {
+ name = d.name;
+ type = d.type;
+ classScope = d.classScope;
+ }
+ ~CodeVarDef() {}
+
+ QString name;
+ QString type;
+ QString classScope;
+};
+
+typedef QList<CodeClassDef> CodeClassList;
+typedef QDict<CodeClassDef> CodeClassDict;
+typedef QList<CodeVarDef> CodeVarList;
+
+static CodeClassList codeClassList;
+static CodeClassDict codeClassDict(17);
+static CodeVarList codeVarList;
+static CodeVarList codeParmList;
+
+/* -----------------------------------------------------------------
+ *
+ * statics
+ */
+
+static const char * inputString;
+static int inputPosition;
+static int lastCContext;
+static int lastDContext;
+static int lastStringContext;
+static int bracketCount = 0;
+static int curlyCount = 0;
+static int sharpCount = 0;
+static int yyLineNr = 0;
+static QString type;
+static QString name;
+static QString args;
+static QString parmType;
+static QString parmName;
+static bool inClass;
+static QString classScope;
+static OutputList *code;
+static CodeClassDef ccd;
+static CodeVarDef cvd;
+static bool exampleBlock;
+static QString exampleName;
+static QString exampleFile;
+static int anchorCount;
+
+static void addType()
+{
+ if (name=="const") { name.resize(0); return; }
+ if (type.length()) type += ' ' ;
+ type += name ;
+ name.resize(0) ;
+ if (type.length()) type += ' ' ;
+ type += args ;
+ args.resize(0) ;
+}
+
+static void addParmType()
+{
+ if (parmName=="const") { parmName.resize(0); return; }
+ if (parmType.length()) parmType += ' ' ;
+ parmType += parmName ;
+ parmName.resize(0) ;
+}
+
+static void setClassScope(const QString &name)
+{
+ QString n=name;
+ n=n.simplifyWhiteSpace();
+ int index;
+ if ((index=n.find("::"))!=-1)
+ classScope=n.left(index);
+ else
+ classScope.resize(0);
+ //printf("--->New class scope `%s'\n",classScope.data());
+}
+
+static void addVariable()
+{
+ cvd.name=name.copy().simplifyWhiteSpace();
+ cvd.type=type.copy().simplifyWhiteSpace();
+ if (type.length()==0)
+ return;
+ else if ((getClass(cvd.type)) || (codeClassDict[cvd.type]))
+ {
+ cvd.classScope=classScope;
+ codeVarList.append(new CodeVarDef(cvd)); // add it to a list
+ }
+}
+
+static void addParameter()
+{
+ cvd.name=parmName.copy().simplifyWhiteSpace();
+ cvd.type=parmType.copy().simplifyWhiteSpace();
+ if (cvd.type.length()==0)
+ return;
+ else if ((getClass(cvd.type)) || (codeClassDict[cvd.type]))
+ {
+ cvd.classScope=classScope;
+ codeParmList.append(new CodeVarDef(cvd)); // add it to a list
+ }
+}
+
+static void generateClassLink(OutputList &ol,const char *clName)
+{
+ QString className=clName;
+ if (className.length()==0) return;
+ ClassDef *cd;
+ if ((cd=getClass(className)) && cd->isVisible())
+ {
+ if (exampleBlock)
+ {
+ QString anchor;
+ anchor.sprintf("a%d",anchorCount);
+ //printf("addExampleClass(%s,%s,%s)\n",anchor.data(),exampleName.data(),
+ // exampleFile.data());
+ if (cd->addExample(anchor,exampleName,exampleFile))
+ {
+ ol.writeAnchor(anchor);
+ anchorCount++;
+ }
+ }
+ ol.writeCodeLink(cd->getReference(),cd->classFile(),0,className);
+ }
+ else
+ {
+ ol.codify(clName);
+ }
+}
+
+static bool getLink(const char *className,
+ const char *memberName,OutputList &result)
+{
+ MemberDef *md;
+ ClassDef *cd;
+ FileDef *fd;
+ QString m=memberName;
+ QString c=className;
+ //printf("Trying `%s'::`%s'\n",c.data(),m.data());
+ if (getDefs(m,c,"()",md,cd,fd) &&
+ (md->hasDocumentation() || md->isReference()))
+ {
+ //printf("Found!\n");
+ if (exampleBlock)
+ {
+ QString anchor;
+ anchor.sprintf("a%d",anchorCount);
+ //printf("addExampleFile(%s,%s,%s)\n",anchor.data(),exampleName.data(),
+ // exampleFile.data());
+ if (md->addExample(anchor,exampleName,exampleFile))
+ {
+ result.writeAnchor(anchor);
+ anchorCount++;
+ }
+ }
+ if (cd)
+ {
+ result.writeCodeLink(cd->getReference(),cd->classFile(),
+ md->anchor(),memberName);
+ return TRUE;
+ }
+ else if (fd)
+ {
+ result.writeCodeLink(fd->getReference(),fd->diskName(),
+ md->anchor(),memberName);
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+static void generateMemberLink(OutputList &ol,const char *varName,
+ const char *memName)
+{
+ //printf("generateMemberLink(object=%s,mem=%s) classScope=%s\n",
+ // varName,memName,classScope.data());
+ CodeVarDef *cvd=codeParmList.last();
+ while (cvd && cvd->name!=varName) cvd=codeParmList.prev();
+ if (!cvd)
+ {
+ cvd=codeVarList.last();
+ while (cvd && cvd->name!=varName) cvd=codeVarList.prev();
+ }
+ if (cvd) // variable found
+ {
+ CodeClassDef *ccd=codeClassDict[cvd->type];
+ if (ccd)
+ {
+ char *s=ccd->bases.first();
+ while (s)
+ {
+ OutputList result(&ol);
+ if (getLink(s,memName,result))
+ {
+ ol+=result;
+ return;
+ }
+ s=ccd->bases.next();
+ }
+ }
+ else
+ {
+ OutputList result(&ol);
+ if (getLink(cvd->type,memName,result))
+ {
+ ol+=result;
+ }
+ else
+ {
+ ol.codify(memName);
+ }
+ return;
+ }
+ }
+ ol.codify(memName);
+ return;
+}
+
+static void generateFunctionLink(OutputList &ol,const char *funcName)
+{
+ //printf("generateFunctionLink(%s) classScope=%s\n",funcName,classScope.data());
+ OutputList result(&ol);
+ CodeClassDef *ccd=0;
+ if (classScope.length()>0 && (ccd=codeClassDict[classScope]))
+ {
+ //printf("using classScope %s\n",classScope.data());
+ char *s=ccd->bases.first();
+ while (s)
+ {
+ if (getLink(s,funcName,result))
+ {
+ ol+=result;
+ return;
+ }
+ s=ccd->bases.next();
+ }
+ }
+ if (getLink(classScope,funcName,result))
+ {
+ ol+=result;
+ }
+ else
+ {
+ ol.codify(funcName);
+ }
+ return;
+}
+
+/* -----------------------------------------------------------------
+ */
+#undef YY_INPUT
+#define YY_INPUT(buf,result,max_size) result=yyread(buf,max_size);
+
+static int yyread(char *buf,int max_size)
+{
+ int c=0;
+ while( c < max_size && inputString[inputPosition] )
+ {
+ *buf = inputString[inputPosition++] ;
+ c++; buf++;
+ }
+ return c;
+}
+
+%}
+
+ID [a-z_A-Z][a-z_A-Z0-9]*
+
+%x SkipString
+%x SkipCPP
+%x SkipComment
+%x SkipSpecialComment
+%x SkipCxxComment
+%x SkipSpecialCxxComment
+%x Body
+%x FuncCall
+%x MemberCall
+%x MemberCall2
+%x SkipInits
+%x ClassName
+%x Bases
+%x SkipSharp
+%x ReadInclude
+
+%%
+
+<*>\x0d
+<Body>^([ \t]*"#include"[ \t]*)("<"|"\"") {
+ code->codify(yytext);
+ BEGIN( ReadInclude );
+ }
+<Body>("class"|"struct"|"union")[ \t\n]+ {
+ code->codify(yytext);
+ BEGIN( ClassName );
+ }
+<ReadInclude>[a-z_A-Z0-9.]+(("/"[a-z_A-Z0-9.]+)*)/(">"|"\"") {
+ //FileInfo *f;
+ bool ambig;
+ FileDef *fd;
+ if ((fd=findFileDef(&inputNameDict,yytext,ambig)) &&
+ fd->hasDocumentation())
+ {
+ code->writeCodeLink(0,fd->diskName(),0,yytext);
+ }
+ else
+ {
+ code->codify(yytext);
+ }
+ char c=yyinput();
+ QString text;
+ text+=c;
+ code->codify(text);
+ BEGIN( Body );
+ }
+<Body>^[ \t]*"#" {
+ code->codify(yytext);
+ BEGIN( SkipCPP ) ;
+ }
+<SkipCPP>. {
+ code->codify(yytext);
+ }
+<SkipCPP>\\\n {
+ code->codify(yytext);
+ yyLineNr++ ;
+ }
+<SkipCPP>\n {
+ yyLineNr++ ;
+ code->codify(yytext);
+ BEGIN( Body ) ;
+ }
+<SkipCPP>"//" {
+ code->codify(yytext);
+ }
+<Body>"{" {
+ code->codify(yytext);
+ curlyCount++;
+ type.resize(0); name.resize(0);
+ }
+<Body>"}" {
+ code->codify(yytext);
+ inClass=FALSE;
+ if (--curlyCount<=0)
+ {
+ classScope.resize(0);
+ codeParmList.clear();
+ }
+ }
+<ClassName>";" {
+ code->codify(yytext);
+ BEGIN( Body );
+ }
+<ClassName>[*&]+ {
+ addType();
+ code->codify(yytext);
+ }
+<ClassName>{ID} {
+ ccd.name=yytext;
+ addType();
+ generateClassLink(*code,yytext);
+ }
+<ClassName>[ \t\n]*":"[ \t\n]* {
+ code->codify(yytext);
+ BEGIN( Bases );
+ }
+<Bases,ClassName>[ \t]*"{"[ \t]* {
+ code->codify(yytext);
+ curlyCount++;
+ inClass=TRUE;
+ if (ccd.name.length()>0)
+ {
+ classScope=ccd.name.copy();
+ CodeClassDef *cd=new CodeClassDef(ccd);
+ codeClassList.append(cd);
+ codeClassDict.insert(cd->name,cd);
+ }
+ BEGIN( Body );
+ }
+<Bases>"virtual" {
+ code->codify(yytext);
+ }
+<Bases>"public" {
+ code->codify(yytext);
+ }
+<Bases>"protected" {
+ code->codify(yytext);
+ }
+<Bases>"private" {
+ code->codify(yytext);
+ }
+<Bases>{ID} {
+ //printf("%s:addBase(%s)\n",ccd.name.data(),yytext);
+ ccd.bases.inSort(yytext);
+ generateClassLink(*code,yytext);
+ }
+<Bases>"<" {
+ code->codify(yytext);
+ sharpCount=1;
+ BEGIN ( SkipSharp );
+ }
+<SkipSharp>"<" {
+ code->codify(yytext);
+ ++sharpCount;
+ }
+<SkipSharp>">" {
+ code->codify(yytext);
+ if (--sharpCount<=0)
+ BEGIN ( Bases );
+ }
+<Bases>"," {
+ code->codify(yytext);
+ }
+
+
+<Body>("asm"|"auto"|"break"|"case"|"catch"|"continue"|"default"|"delete"|"do"|"else"|"for"|"goto"|"if"|"new"|"return"|"switch"|"this"|"throw"|"try"|"typedef"|"while")([ \t\n]*)/"(" {
+ code->codify(yytext);
+ name.resize(0);type.resize(0);
+ }
+<Body>("asm"|"auto"|"break"|"case"|"catch"|"continue"|"default"|"delete"|"do"|"else"|"for"|"goto"|"if"|"new"|"return"|"switch"|"this"|"throw"|"try"|"typedef"|"while")([ \t\n]*) {
+ code->codify(yytext);
+ name.resize(0);type.resize(0);
+ }
+<Body>([a-z_A-Z~][a-z_A-Z0-9]*)/([ \t]*) {
+ generateClassLink(*code,yytext);
+ addType();
+ name+=yytext;
+ }
+<Body>[a-z_A-Z~]([a-z_A-Z0-9]*[ \t\n]*"::")+[ \t\n]*[~a-z_A-Z][a-z_A-Z0-9]*[ \t\n]* {
+ code->codify(yytext);
+ addType();
+ name+=yytext;
+ }
+<Body>([a-z_A-Z~][a-z_A-Z0-9:]*)/([ \t]*"(") {
+ addType();
+ if (type.length()==0)
+ generateFunctionLink(*code,yytext);
+ else
+ code->codify(yytext);
+ bracketCount=1;
+ args.resize(0);
+ name+=yytext;
+ BEGIN( FuncCall );
+ }
+<FuncCall,Body,MemberCall>\" {
+ code->codify(yytext);
+ lastStringContext=YY_START;
+ BEGIN( SkipString );
+ }
+<SkipString>[^\"\\]* {
+ code->codify(yytext);
+ }
+<SkipString>\" {
+ code->codify(yytext);
+ BEGIN( lastStringContext );
+ }
+<SkipString>\\\" {
+ code->codify(yytext);
+ }
+<Body>":" {
+ code->codify(yytext);
+ name.resize(0);type.resize(0);
+ }
+<Body>"'"."'" {
+ code->codify(yytext);
+ }
+<Body>"."|"->" {
+ code->codify(yytext);
+ BEGIN( MemberCall );
+ }
+<MemberCall>([a-z_A-Z~][a-z_A-Z0-9]*)/([ \t\n]*"(") {
+ if (name.length()>0)
+ generateMemberLink(*code,name,yytext);
+ else
+ code->codify(yytext);
+ name.resize(0);type.resize(0);
+ bracketCount=0;
+ BEGIN(FuncCall);
+ }
+<MemberCall>[^a-z_A-Z0-9(] {
+ code->codify(yytext);
+ type.resize(0);
+ name.resize(0);
+ BEGIN(Body);
+ }
+<Body>[,=;\[] {
+ code->codify(yytext);
+ if (type.length()>0)
+ addVariable();
+ name.resize(0);
+ if (*yytext!=',') type.resize(0);
+ args.resize(0);
+ }
+<Body>[0-9]+ {
+ code->codify(yytext);
+ }
+<MemberCall2,FuncCall>[a-z_A-Z][:a-z_A-Z0-9]* {
+ addParmType();
+ parmName=yytext;
+ generateClassLink(*code,yytext);
+ }
+<MemberCall2,FuncCall>, {
+ code->codify(yytext);
+ addParameter();
+ parmType.resize(0);parmName.resize(0);
+ }
+<MemberCall2,FuncCall>"(" {
+ code->codify(yytext);
+ bracketCount++;
+ }
+<MemberCall2,FuncCall>")" {
+ code->codify(yytext);
+ if (--bracketCount<=0)
+ name.resize(0);args.resize(0);
+ parmType.resize(0);parmName.resize(0);
+ BEGIN( Body );
+ }
+<MemberCall2,FuncCall>")"[ \t\n]*";" {
+ code->codify(yytext);
+ bracketCount=0;
+ if (!inClass && type.length()>0)
+ addVariable();
+ name.resize(0);type.resize(0);
+ parmType.resize(0);parmName.resize(0);
+ BEGIN( Body );
+ }
+<MemberCall2,FuncCall>")"[ \t\n]*"{" {
+ addParameter();
+ parmType.resize(0);parmName.resize(0);
+ if (name.length()>0) setClassScope(name);
+ code->codify(yytext);
+ curlyCount++;
+ type.resize(0); name.resize(0);
+ BEGIN( Body );
+ }
+<MemberCall2,FuncCall>")"[ \t\n]*":" {
+ addParameter();
+ parmType.resize(0);parmName.resize(0);
+ if (name.length()>0) setClassScope(name);
+ code->codify(yytext);
+ type.resize(0); name.resize(0);
+ BEGIN( SkipInits );
+ }
+<SkipInits>"{" {
+ code->codify(yytext);
+ curlyCount++;
+ BEGIN( Body );
+ }
+<SkipInits>{ID} {
+ generateClassLink(*code,yytext);
+ }
+<FuncCall>([a-z_A-Z][a-z_A-Z0-9]*)/"(" {
+ generateFunctionLink(*code,yytext);
+ }
+<FuncCall>([a-z_A-Z][a-z_A-Z0-9]*)/("."|"->") {
+ code->codify(yytext);
+ args=yytext;
+ BEGIN( MemberCall2 );
+ }
+<MemberCall2>([a-z_A-Z][a-z_A-Z0-9]*)/([ \t\n]*"(") {
+ if (args.length()>0)
+ generateMemberLink(*code,args,yytext);
+ else
+ code->codify(yytext);
+ args.resize(0);
+ BEGIN( FuncCall );
+ }
+<MemberCall2>([a-z_A-Z][a-z_A-Z0-9]*)/([ \t\n]*("."|"->")) {
+ code->codify(yytext);
+ args=yytext;
+ }
+<SkipComment>"//" {
+ code->codify(yytext);
+ }
+<SkipComment>[ \t]*"*/" {
+ code->codify(yytext);
+ BEGIN( lastCContext ) ;
+ }
+<SkipCxxComment>.*\n {
+ code->codify(yytext);
+ yyLineNr++ ;
+ BEGIN( lastCContext ) ;
+ }
+<SkipSpecialComment>"//"
+ /*!
+<SkipSpecialComment>[ \t]*"* /"[ \t]* /"\n" {
+ BEGIN( lastDContext ) ;
+ }
+ */
+<SkipSpecialComment>[ \t]*"*/" {
+ BEGIN( lastDContext ) ;
+ }
+<SkipSpecialComment>[ \t]*"*/"[ \t\n]*"\n"/"/*" {
+ //code->codify("\n");
+ QString lineText=yytext;
+ yyLineNr+=lineText.contains('\n');
+ BEGIN( lastDContext ) ;
+ }
+<SkipSpecialComment>.
+<SkipSpecialComment>\n { yyLineNr++; }
+<SkipSpecialCxxComment>.*/\n {
+ yyLineNr++ ;
+ BEGIN( lastDContext ) ;
+ }
+<SkipSpecialCxxComment>.
+<SkipSpecialCxxComment>\n { yyLineNr++; }
+<*>[ \t]*"/*!"|"/**" {
+ lastDContext = YY_START ;
+ BEGIN( SkipSpecialComment );
+ }
+<*>"/*" {
+ code->codify(yytext);
+ lastCContext = YY_START ;
+ BEGIN( SkipComment ) ;
+ }
+<*>[ \t]*"//!" {
+ lastDContext = YY_START ;
+ BEGIN( SkipSpecialCxxComment );
+ }
+<*>"//" {
+ code->codify(yytext);
+ lastCContext = YY_START ;
+ BEGIN( SkipCxxComment ) ;
+ }
+<*>. {
+ code->codify(yytext);
+ }
+<*>\n {
+ code->codify(yytext);
+ }
+<*>([ \t\n]*"\n"){2,} { // combine multiple blank lines
+ QString sepLine=yytext;
+ code->codify("\n\n");
+ yyLineNr+=sepLine.contains('\n');
+ }
+
+%%
+
+/*@ ----------------------------------------------------------------------------
+ */
+
+void initParseCodeContext()
+{
+ codeClassList.setAutoDelete(TRUE);
+ codeVarList.setAutoDelete(TRUE);
+ codeParmList.setAutoDelete(TRUE);
+ codeClassDict.clear();
+ codeClassList.clear();
+ codeVarList.clear();
+ codeParmList.clear();
+ ccd.bases.clear();
+ anchorCount = 0;
+}
+
+void parseCode(OutputList &ol,const char *className,const QString &s,
+ bool e, const char *exName)
+{
+ code = new OutputList(&ol);
+ if (s.length()==0) return;
+ inputString = s;
+ inputPosition = 0;
+ yyLineNr = 0;
+ curlyCount = 0;
+ bracketCount = 0;
+ sharpCount = 0;
+ classScope = className;
+ exampleBlock = e;
+ exampleName = exName;
+ exampleFile = convertSlashes(exampleName,TRUE)+"-example";
+ type.resize(0);
+ name.resize(0);
+ args.resize(0);
+ parmName.resize(0);
+ parmType.resize(0);
+ codeYYrestart( codeYYin );
+ BEGIN( Body );
+ codeYYlex();
+ ol+=*code;
+ delete code;
+ return;
+}
+
+extern "C" { // some bogus code to keep the compiler happy
+ int codeYYwrap() { return 1 ; }
+ void codeYYdummy() { yy_flex_realloc(0,0); }
+}
diff --git a/src/config.h b/src/config.h
new file mode 100644
index 0000000..6269e85
--- /dev/null
+++ b/src/config.h
@@ -0,0 +1,80 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#ifndef CONFIG_H
+#define CONFIG_H
+
+#include <qstring.h>
+#include <qstrlist.h>
+#include <qfile.h>
+
+extern void parseConfig(const QString &config);
+extern void writeTemplateConfig(QFile *f,bool shortList);
+
+extern QString projectName; // the name of the project
+extern QString projectNumber; // the number of the project
+extern QString htmlOutputDir; // the directory to put the HTML files
+extern QString latexOutputDir; // the directory to put the Latex files
+extern QString manOutputDir; // the directory to put the man pages
+extern QString headerFile; // the name of the personal HTML header
+extern QString footerFile; // the name of the personal HTML footer
+extern QString cgiName; // the name of the CGI binary
+extern QString cgiURL; // the absolute URL to the CGI binary
+extern QString docURL; // the absolute URL to the documentation
+extern QString binAbsPath; // the absolute path to the doxysearch
+extern QString docAbsPath; // the absolute path to the documentation
+extern QString perlPath; // the absolute path to perl
+extern QString genTagFile; // the tag file to generate
+extern QString inputFilter; // a filter command that is applied to input files
+extern QString paperType; // the page type to generate docs for
+extern QString stripFromPath; // the string to strip from the file path
+extern QStrList includePath; // list of include paths
+extern QStrList examplePath; // list of example paths
+extern QStrList inputSources; // list of input files
+extern QStrList excludeSources; // list of files to exclude from the input
+extern QStrList filePatternList; // list of file patterns
+extern QStrList excludePatternList; // list of patterns to exclude from input
+extern QStrList tagFileList; // list of tag files
+extern QStrList extDocPathList; // list of external doc. directories.
+extern QStrList predefined; // list of predefined macro names.
+extern QStrList extraPackageList; // list of extra LaTeX packages.
+extern bool quietFlag; // generate progress messages flag
+extern bool warningFlag; // generate warnings flag
+extern bool recursiveFlag; // scan directories recursively
+extern bool allExtFlag; // include all external classes flag
+extern bool searchEngineFlag; // generate search engine flag
+extern bool extractAllFlag; // gererate docs for all classes flag
+extern bool extractPrivateFlag; // generate docs for private members flag
+extern bool noIndexFlag; // generate condensed index flag
+extern bool generateHtml; // generate HTML output
+extern bool generateLatex; // generate Latex output
+extern bool generateMan; // generate Man pages
+extern bool preprocessingFlag; // enable preprocessing
+extern bool briefMemDescFlag; // enable `inline' brief member descr.
+extern bool hideMemberFlag; // hide undocumented members.
+extern bool hideClassFlag; // hide undocumented members.
+extern bool searchIncludeFlag; // search for included files
+extern bool macroExpansionFlag; // expand macros in the source.
+extern bool onlyPredefinedFlag; // expand only predefined macros
+extern bool fullPathNameFlag; // using full path name in output
+extern bool classDiagramFlag; // enable the generation of class diagrams.
+extern bool compactLatexFlag; // generate compact LaTeX documentation.
+extern bool repeatBriefFlag; // repeat brief descriptions.
+extern bool internalDocsFlag; // determines what happens to internal docs.
+extern bool caseSensitiveNames; // determines if output can be mixed case.
+extern bool verbatimHeaderFlag; // enable/disable generation of verb headers.
+
+#endif
diff --git a/src/config.l b/src/config.l
new file mode 100644
index 0000000..232f531
--- /dev/null
+++ b/src/config.l
@@ -0,0 +1,1112 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+%{
+
+/*
+ * includes
+ */
+#include <stdio.h>
+#include <iostream.h>
+#include <assert.h>
+#include <ctype.h>
+
+#include <qstring.h>
+#include <qfileinf.h>
+#include <qdir.h>
+#include <qtstream.h>
+
+#include "doxygen.h"
+#include "config.h"
+#include "message.h"
+#include "pre.h"
+#include "version.h"
+#include "language.h"
+
+#define YY_NEVER_INTERACTIVE 1
+
+/* -----------------------------------------------------------------
+ *
+ * exported variables
+ */
+
+QString projectName;
+QString projectNumber;
+QString outputDir;
+QString htmlOutputDir;
+QString latexOutputDir;
+QString manOutputDir;
+QString headerFile;
+QString footerFile;
+QString cgiName;
+QString cgiURL;
+QString docURL;
+QString binAbsPath;
+QString docAbsPath;
+QString perlPath;
+QString genTagFile;
+QString inputFilter;
+QString paperType;
+QString outputLanguage;
+QString stripFromPath;
+QStrList includePath;
+QStrList examplePath;
+QStrList inputSources;
+QStrList excludeSources;
+QStrList filePatternList;
+QStrList excludePatternList;
+QStrList tagFileList;
+QStrList extDocPathList;
+QStrList predefined;
+QStrList extraPackageList;
+bool quietFlag = FALSE;
+bool warningFlag = FALSE;
+bool recursiveFlag = FALSE;
+bool allExtFlag = FALSE;
+bool searchEngineFlag = FALSE;
+bool extractAllFlag = FALSE;
+bool extractPrivateFlag = FALSE;
+bool noIndexFlag = FALSE;
+bool hideMemberFlag = FALSE;
+bool hideClassFlag = FALSE;
+bool macroExpansionFlag = FALSE;
+bool onlyPredefinedFlag = FALSE;
+bool fullPathNameFlag = FALSE;
+bool compactLatexFlag = FALSE;
+bool internalDocsFlag = FALSE;
+bool caseSensitiveNames = FALSE;
+bool generateHtml = TRUE;
+bool generateLatex = TRUE;
+bool generateMan = TRUE;
+bool preprocessingFlag = TRUE;
+bool briefMemDescFlag = TRUE;
+bool searchIncludeFlag = TRUE;
+bool classDiagramFlag = TRUE;
+bool repeatBriefFlag = TRUE;
+bool verbatimHeaderFlag = TRUE;
+
+/* -----------------------------------------------------------------
+ *
+ * static variables
+ */
+
+static const char * inputString;
+static int inputPosition;
+static int yyLineNr;
+static QString tmpString;
+static QString * s=0;
+static bool * b=0;
+static QStrList * l=0;
+static int lastState;
+static int lastEnvState;
+static QString elemStr;
+
+/* -----------------------------------------------------------------
+ */
+#undef YY_INPUT
+#define YY_INPUT(buf,result,max_size) result=yyread(buf,max_size);
+
+static int yyread(char *buf,int max_size)
+{
+ int c=0;
+ while( c < max_size && inputString[inputPosition] )
+ {
+ *buf = inputString[inputPosition++] ;
+ c++; buf++;
+ }
+ return c;
+}
+
+%}
+
+%x Start
+%x SkipComment
+%x GetString
+%x GetBool
+%x GetStrList
+%x GetQuotedString
+%x GetEnvVar
+
+%%
+
+<*>\0x0d
+<Start,GetString,GetStrList,GetBool>"#" { BEGIN(SkipComment); }
+<Start>"PROJECT_NAME"[ \t]*"=" { BEGIN(GetString); s=&projectName; }
+<Start>"PROJECT_NUMBER"[ \t]*"=" { BEGIN(GetString); s=&projectNumber; }
+<Start>"OUTPUT_DIRECTORY"[ \t]*"=" { BEGIN(GetString); s=&outputDir; }
+<Start>"HTML_OUTPUT"[ \t]*"=" { BEGIN(GetString); s=&htmlOutputDir; }
+<Start>"MAN_OUTPUT"[ \t]*"=" { BEGIN(GetString); s=&manOutputDir; }
+<Start>"LATEX_OUTPUT"[ \t]*"=" { BEGIN(GetString); s=&latexOutputDir; }
+<Start>"HTML_HEADER"[ \t]*"=" { BEGIN(GetString); s=&headerFile; }
+<Start>"HTML_FOOTER"[ \t]*"=" { BEGIN(GetString); s=&footerFile; }
+<Start>"CGI_NAME"[ \t]*"=" { BEGIN(GetString); s=&cgiName; }
+<Start>"CGI_URL"[ \t]*"=" { BEGIN(GetString); s=&cgiURL; }
+<Start>"DOC_URL"[ \t]*"=" { BEGIN(GetString); s=&docURL; }
+<Start>"BIN_ABSPATH"[ \t]*"=" { BEGIN(GetString); s=&binAbsPath; }
+<Start>"DOC_ABSPATH"[ \t]*"=" { BEGIN(GetString); s=&docAbsPath; }
+<Start>"PERL_PATH"[ \t]*"=" { BEGIN(GetString); s=&perlPath; }
+<Start>"GENERATE_TAGFILE"[ \t]*"=" { BEGIN(GetString); s=&genTagFile; }
+<Start>"INPUT_FILTER"[ \t]*"=" { BEGIN(GetString); s=&inputFilter; }
+<Start>"PAPER_TYPE"[ \t]*"=" { BEGIN(GetString); s=&paperType; }
+<Start>"OUTPUT_LANGUAGE"[ \t]*"=" { BEGIN(GetString); s=&outputLanguage; }
+<Start>"STRIP_FROM_PATH"[ \t]*"=" { BEGIN(GetString); s=&stripFromPath; }
+<Start>"INCLUDE_PATH"[ \t]*"=" { BEGIN(GetStrList); l=&includePath; elemStr=""; }
+<Start>"EXAMPLE_PATH"[ \t]*"=" { BEGIN(GetStrList); l=&examplePath; elemStr=""; }
+<Start>"INPUT"[ \t]*"=" { BEGIN(GetStrList); l=&inputSources; elemStr=""; }
+<Start>"EXCLUDE"[ \t]*"=" { BEGIN(GetStrList); l=&excludeSources; elemStr=""; }
+<Start>"FILE_PATTERNS"[ \t]*"=" { BEGIN(GetStrList); l=&filePatternList; elemStr=""; }
+<Start>"EXCLUDE_PATTERNS"[ \t]*"=" { BEGIN(GetStrList); l=&excludePatternList; elemStr=""; }
+<Start>"TAGFILES"[ \t]*"=" { BEGIN(GetStrList); l=&tagFileList; elemStr=""; }
+<Start>"EXT_DOC_PATHS"[ \t]*"=" { BEGIN(GetStrList); l=&extDocPathList; elemStr=""; }
+<Start>"PREDEFINED"[ \t]*"=" { BEGIN(GetStrList); l=&predefined; elemStr=""; }
+<Start>"EXTRA_PACKAGES"[ \t]*"=" { BEGIN(GetStrList); l=&extraPackageList; elemStr=""; }
+<Start>"QUIET"[ \t]*"=" { BEGIN(GetBool); b=&quietFlag; }
+<Start>"WARNINGS"[ \t]*"=" { BEGIN(GetBool); b=&warningFlag; }
+<Start>"RECURSIVE"[ \t]*"=" { BEGIN(GetBool); b=&recursiveFlag; }
+<Start>"ALLEXTERNALS"[ \t]*"=" { BEGIN(GetBool); b=&allExtFlag; }
+<Start>"SEARCHENGINE"[ \t]*"=" { BEGIN(GetBool); b=&searchEngineFlag; }
+<Start>"EXTRACT_ALL"[ \t]*"=" { BEGIN(GetBool); b=&extractAllFlag; }
+<Start>"EXTRACT_PRIVATE"[ \t]*"=" { BEGIN(GetBool); b=&extractPrivateFlag; }
+<Start>"DISABLE_INDEX"[ \t]*"=" { BEGIN(GetBool); b=&noIndexFlag; }
+<Start>"GENERATE_LATEX"[ \t]*"=" { BEGIN(GetBool); b=&generateLatex; }
+<Start>"GENERATE_HTML"[ \t]*"=" { BEGIN(GetBool); b=&generateHtml; }
+<Start>"GENERATE_MAN"[ \t]*"=" { BEGIN(GetBool); b=&generateMan; }
+<Start>"ENABLE_PREPROCESSING"[ \t]*"=" { BEGIN(GetBool); b=&preprocessingFlag; }
+<Start>"MACRO_EXPANSION"[ \t]*"=" { BEGIN(GetBool); b=&macroExpansionFlag; }
+<Start>"SEARCH_INCLUDES"[ \t]*"=" { BEGIN(GetBool); b=&searchIncludeFlag; }
+<Start>"BRIEF_MEMBER_DESC"[ \t]*"=" { BEGIN(GetBool); b=&briefMemDescFlag; }
+<Start>"HIDE_UNDOC_MEMBERS"[ \t]*"=" { BEGIN(GetBool); b=&hideMemberFlag; }
+<Start>"HIDE_UNDOC_CLASSES"[ \t]*"=" { BEGIN(GetBool); b=&hideClassFlag; }
+<Start>"EXPAND_ONLY_PREDEF"[ \t]*"=" { BEGIN(GetBool); b=&onlyPredefinedFlag; }
+<Start>"FULL_PATH_NAMES"[ \t]*"=" { BEGIN(GetBool); b=&fullPathNameFlag; }
+<Start>"CLASS_DIAGRAMS"[ \t]*"=" { BEGIN(GetBool); b=&classDiagramFlag; }
+<Start>"COMPACT_LATEX"[ \t]*"=" { BEGIN(GetBool); b=&compactLatexFlag; }
+<Start>"REPEAT_BRIEF"[ \t]*"=" { BEGIN(GetBool); b=&repeatBriefFlag; }
+<Start>"INTERNAL_DOCS"[ \t]*"=" { BEGIN(GetBool); b=&internalDocsFlag; }
+<Start>"CASE_SENSE_NAMES"[ \t]*"=" { BEGIN(GetBool); b=&caseSensitiveNames; }
+<Start>"VERBATIM_HEADERS"[ \t]*"=" { BEGIN(GetBool); b=&verbatimHeaderFlag; }
+<Start>[a-z_A-Z0-9]+ { err("Warning: ignoring unknown tag `%s' at line %d\n",yytext,yyLineNr); }
+<GetString,GetBool>\n { yyLineNr++; BEGIN(Start); }
+<GetStrList>\n {
+ yyLineNr++;
+ if (elemStr.length()>0)
+ {
+ //printf("elemStr1=`%s'\n",elemStr.data());
+ l->append(elemStr);
+ }
+ BEGIN(Start);
+ }
+<GetStrList>[ \t]+ {
+ if (elemStr.length()>0)
+ {
+ //printf("elemStr2=`%s'\n",elemStr.data());
+ l->append(elemStr);
+ }
+ elemStr.resize(0);
+ }
+<GetString>[^ \"\$\t\r\n]+ { (*s)+=yytext; }
+<GetString,GetStrList>"\"" { lastState=YY_START;
+ BEGIN(GetQuotedString);
+ tmpString.resize(0);
+ }
+<GetString,GetStrList,GetQuotedString>"\$\(" {
+ //printf(">> Enter env\n");
+ lastEnvState=YY_START;
+ BEGIN(GetEnvVar);
+ }
+<GetEnvVar>[a-z_A-Z0-9]+")" {
+ yytext[yyleng-1]='\0';
+ const char *env=getenv(yytext);
+ int i;
+ int l=strlen(env);
+ //printf("env name=`%s' text=`%s'\n",yytext,env);
+ for (i=l-1;i>=0;i--) unput(env[i]);
+ BEGIN(lastEnvState);
+ }
+<GetQuotedString>"\""|"\n" {
+ //printf("Quoted String = `%s'\n",tmpString.data());
+ if (lastState==GetString)
+ (*s)+=tmpString;
+ else
+ elemStr+=tmpString;
+ if (*yytext=='\n')
+ {
+ err("Warning: Missing end quote (\") on line %d\n",yyLineNr);
+ yyLineNr++;
+ }
+ BEGIN(lastState);
+ }
+<GetQuotedString>"\\\"" {
+ tmpString+='"';
+ }
+<GetQuotedString>. { tmpString+=*yytext; }
+<GetBool>[a-zA-Z]+ {
+ QString bs=yytext;
+ bs=bs.upper();
+ if (bs=="YES")
+ *b=TRUE;
+ else if (bs=="NO")
+ *b=FALSE;
+ else
+ {
+ *b=FALSE;
+ warn("Warning: Invalid value `%s' for "
+ "boolean tag in line %d; use YES or NO\n",
+ bs.data(),yyLineNr);
+ }
+ }
+ /*
+<GetStrList>[a-z_A-Z.*:?~0-9/\\\-]+ {
+ elemStr+=yytext;
+ }
+ */
+<GetStrList>[^ \#\"\$\t\r\n]+ {
+ elemStr+=yytext;
+ }
+<SkipComment>\n { yyLineNr++; BEGIN(Start); }
+<SkipComment>\\[ \r\t]*\n { yyLineNr++; BEGIN(Start); }
+<*>\\[ \r\t]*\n { yyLineNr++; }
+<*>.
+<*>\n { yyLineNr++ ; }
+
+%%
+
+/*@ ----------------------------------------------------------------------------
+ */
+
+
+void dumpConfig()
+{
+ printf("projectName=`%s'\n",projectName.data());
+ printf("outputDir=`%s'\n", outputDir.data());
+ printf("headerFile=`%s'\n", headerFile.data());
+ printf("footerFile=`%s'\n", footerFile.data());
+ char *ip=includePath.first();
+ while (ip)
+ {
+ printf("includePath=`%s'\n",ip);
+ ip=includePath.next();
+ }
+ printf("quiet=`%d'\n", quietFlag);
+ printf("warnings=`%d'\n", warningFlag);
+ char *is=inputSources.first();
+ while (is)
+ {
+ printf("inputSources=`%s'\n",is);
+ is=inputSources.next();
+ }
+ char *fp=filePatternList.first();
+ while (fp)
+ {
+ printf("filePattern=`%s'\n",fp);
+ fp=filePatternList.next();
+ }
+ printf("recusive=`%d'\n",recursiveFlag);
+ printf("inputFilter=`%s'\n",inputFilter.data());
+ char *tf=tagFileList.first();
+ while (tf)
+ {
+ printf("tagFile=`%s'\n",tf);
+ tf=tagFileList.next();
+ }
+ printf("allExternals=`%d'\n",allExtFlag);
+ printf("searchEngine=`%d'\n",searchEngineFlag);
+ printf("cgiName=`%s'\n",cgiName.data());
+ printf("cgiURL=`%s'\n",cgiURL.data());
+ printf("docURL=`%s'\n",docURL.data());
+ printf("binAbsPath=`%s'\n",binAbsPath.data());
+ char *ed=extDocPathList.first();
+ while (ed)
+ {
+ printf("binAbsPathFile=`%s'\n",ed);
+ ed=extDocPathList.next();
+ }
+}
+
+void writeTemplateConfig(QFile *f,bool sl)
+{
+ QTextStream t(f);
+ t << "# Doxyfile " << versionString << endl;
+ if (!sl)
+ {
+ t << "# This file describes the settings to be used by doxygen for a project\n";
+ t << "#\n";
+ t << "# All text after a hash (#) is considered a comment and will be ignored\n";
+ t << "# The format is:\n";
+ t << "# TAG = value [value, ...]\n";
+ t << "# Values that contain spaces should be placed between quotes (\" \")\n";
+ t << "\n";
+ t << "#---------------------------------------------------------------------------\n";
+ t << "# General configuration options\n";
+ t << "#---------------------------------------------------------------------------\n";
+ t << "\n";
+ t << "# The PROJECT_NAME tag is a single word (or a sequence of word surrounded\n";
+ t << "# by quotes) that should identify the project. \n";
+ t << "\n";
+ }
+ t << "PROJECT_NAME =\n";
+ if (!sl)
+ {
+ t << "\n";
+ t << "# The PROJECT_NUMBER tag can be used to enter a project or revision number.\n" ;
+ t << "# This could be handy for archiving the generated documentation or \n";
+ t << "# if some version control system is used.\n";
+ t << "\n";
+ }
+ t << "PROJECT_NUMBER =\n";
+ if (!sl)
+ {
+ t << "\n";
+ t << "# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) \n";
+ t << "# base path where the generated documentation will be put. \n";
+ t << "# If a relative path is entered, it will be relative to the location \n";
+ t << "# where doxygen was started. If left blank the current directory will be used.\n";
+ t << "\n";
+ }
+ t << "OUTPUT_DIRECTORY =\n";
+ if (!sl)
+ {
+ t << "\n";
+ t << "# The OUTPUT_LANGUAGE tag is used to specify the language in which all\n";
+ t << "# documentation generated by doxygen is written. Doxygen will use this\n";
+ t << "# information to generate all constant output in the proper language.\n";
+ t << "# The default language is English, other supported languages are: Dutch\n";
+ t << "\n";
+ }
+ t << "OUTPUT_LANGUAGE = English\n";
+ if (!sl)
+ {
+ t << "\n";
+ t << "# The QUIET tag can be used to turn on/off the messages that are generated\n";
+ t << "# by doxygen. Possible values are YES and NO. If left blank NO is used.\n";
+ t << "\n";
+ }
+ t << "QUIET = NO\n";
+ if (!sl)
+ {
+ t << "\n";
+ t << "# The WARNINGS tag can be used to turn on/off the warning messages that are\n";
+ t << "# generated by doxygen. Possible values are YES and NO. If left blank\n";
+ t << "# NO is used.\n";
+ t << "\n";
+ }
+ t << "WARNINGS = YES\n";
+ if (!sl)
+ {
+ t << "\n";
+ t << "# The DISABLE_INDEX tag can be used to turn on/off the condensed index at\n";
+ t << "# top of each HTML page. The value NO (the default) enables the index and\n";
+ t << "# the value YES disables it.\n";
+ t << "\n";
+ }
+ t << "DISABLE_INDEX = NO\n";
+ if (!sl)
+ {
+ t << "\n";
+ t << "# If the EXTRACT_ALL tag is set to YES all classes and functions will be\n";
+ t << "# included in the documentation, even if no documentation was available.\n";
+ t << "\n";
+ }
+ t << "EXTRACT_ALL = NO\n";
+ if (!sl)
+ {
+ t << "\n";
+ t << "# If the EXTRACT_PRIVATE tag is set to YES all private members of a class\n";
+ t << "# will be included in the documentation.\n";
+ t << "\n";
+ }
+ t << "EXTRACT_PRIVATE = NO\n";
+ if (!sl)
+ {
+ t << "\n";
+ t << "# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all\n";
+ t << "# undocumented members inside documented classes or files.\n";
+ t << "\n";
+ }
+ t << "HIDE_UNDOC_MEMBERS = NO\n";
+ if (!sl)
+ {
+ t << "\n";
+ t << "# If the HIDE_UNDOC_CLASSESS tag is set to YES, Doxygen will hide all\n";
+ t << "# undocumented classes.\n";
+ t << "\n";
+ }
+ t << "HIDE_UNDOC_CLASSES = NO\n";
+ if (!sl)
+ {
+ t << "\n";
+ t << "# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will\n";
+ t << "# include brief member descriptions after the members that are listed in \n";
+ t << "# the file and class documentation (similar to JavaDoc).\n";
+ t << "# Set to NO to disable this.\n";
+ t << "\n";
+ }
+ t << "BRIEF_MEMBER_DESC = YES\n";
+ if (!sl)
+ {
+ t << "\n";
+ t << "# The INTERNAL_DOCS tag determines if documentation\n";
+ t << "# that is typed after a \\internal command is included. If the tag is set \n";
+ t << "# to NO (the default) then the documentation will be excluded.\n";
+ t << "# Set it to YES to include the internal documentation.\n";
+ t << "\n";
+ }
+ t << "INTERNAL_DOCS = NO\n";
+ if (!sl)
+ {
+ t << "\n";
+ t << "# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend\n";
+ t << "# the brief description of a member or function before the detailed description.\n";
+ t << "# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the \n";
+ t << "# brief descriptions will be completely suppressed.\n";
+ t << "\n";
+ }
+ t << "REPEAT_BRIEF = YES\n";
+ if (!sl)
+ {
+ t << "\n";
+ t << "# If the FULL_PATH_NAMES tag is set to YES Doxygen will prepend the full\n";
+ t << "# path before files name in the file list and in the header files. If set\n" ;
+ t << "# to NO the shortest path that makes the file name unique will be used.\n";
+ t << "\n";
+ }
+ t << "FULL_PATH_NAMES = NO\n";
+ if (!sl)
+ {
+ t << "\n";
+ t << "# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag\n";
+ t << "# can be used to strip a user defined part of the path. Stripping is\n" ;
+ t << "# only done if the specified string matches the left-hand part of the path.\n";
+ t << "\n";
+ }
+ t << "STRIP_FROM_PATH =\n";
+ if (!sl)
+ {
+ t << "\n";
+ t << "# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will\n";
+ t << "# generate a class diagram (in Html and LaTeX) for classes with base or\n";
+ t << "# super classes. Setting the tag to NO turns the diagrams off.\n";
+ t << "\n";
+ }
+ t << "CLASS_DIAGRAMS = YES\n";
+ if (!sl)
+ {
+ t << "\n";
+ t << "# If the CASE_SENSE_NAMES tag is set to NO (the default) then Doxygen\n";
+ t << "# will only generate file names in lower case letters. If set to\n";
+ t << "# YES upper case letters are also allowed. This is useful if you have\n";
+ t << "# classes or files whose names only differ in case and if your file system\n";
+ t << "# supports case sensitive file names.\n";
+ t << "\n";
+ }
+ t << "CASE_SENSE_NAMES = NO\n";
+ if (!sl)
+ {
+ t << "\n";
+ t << "# If the VERBATIM_HEADERS tag is set the YES (the default) then Doxygen\n";
+ t << "# will generate a verbatim copy of the header file for each class for\n";
+ t << "# which an include is specified. Set to NO to disable this.\n";
+ t << "\n";
+ }
+ t << "VERBATIM_HEADERS = YES\n";
+ if (!sl)
+ {
+ t << "\n";
+ t << "#---------------------------------------------------------------------------\n";
+ t << "# configuration options related to the input files\n";
+ t << "#---------------------------------------------------------------------------\n";
+ t << "\n";
+ t << "# The INPUT tag can be used to specify the files and/or directories that contain \n";
+ t << "# documented source files. You may enter file names like \"myfile.cpp\" or \n";
+ t << "# directories like \"/usr/src/myproject\". Separate the files or directories \n";
+ t << "# with spaces.\n";
+ t << "\n";
+ }
+ t << "INPUT =\n";
+ if (!sl)
+ {
+ t << "\n";
+ t << "# If the value of the INPUT tag contains directories, you can use the \n";
+ t << "# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp \n";
+ t << "# and *.h) to filter out the source-files in the directories. If left \n";
+ t << "# blank all files are included.\n";
+ t << "\n";
+ }
+ t << "FILE_PATTERNS =\n";
+ if (!sl)
+ {
+ t << "\n";
+ t << "# The RECURSIVE tag can be used to turn specify whether or not subdirectories\n";
+ t << "# should be searched for input files as well. Possible values are YES and NO.\n";
+ t << "# If left blank NO is used.\n";
+ t << "\n";
+ }
+ t << "RECURSIVE = NO\n";
+ if (!sl)
+ {
+ t << "\n";
+ t << "# The EXCLUDE tag can be used to specify files and/or directories that should\n";
+ t << "# excluded from the INPUT source files. This way you can easily exclude a \n";
+ t << "# subdirectory from a directory tree whose root is specified with the INPUT tag.\n";
+ t << "\n";
+ }
+ t << "EXCLUDE =\n";
+ if (!sl)
+ {
+ t << "\n";
+ t << "# If the value of the INPUT tag contains directories, you can use the\n";
+ t << "# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude\n";
+ t << "# certain files from those directories.\n";
+ t << "\n";
+ }
+ t << "EXCLUDE_PATTERNS =\n";
+ if (!sl)
+ {
+ t << "\n";
+ t << "# The EXAMPLE_PATH tag can be used to specify one or more files or \n";
+ t << "# directories that contain example code fragments that are included (see \n";
+ t << "# the \\include command).\n";
+ t << "\n";
+ }
+ t << "EXAMPLE_PATH =\n";
+ if (!sl)
+ {
+ t << "\n";
+ t << "# The INPUT_FILTER tag can be used to specify a program that doxygen should\n";
+ t << "# invoke to filter for each input file. Doxygen will invoke the filter program \n";
+ t << "# by executing (via popen()) the command <filter> <input-file>, where <filter>\n";
+ t << "# is the value of the INPUT_FILTER tag, and <input-file> is the name of an\n";
+ t << "# input file. Doxygen will then use the output that the filter program writes\n";
+ t << "# to standard output.\n";
+ t << "\n";
+ }
+ t << "INPUT_FILTER =\n";
+ if (!sl)
+ {
+ t << "\n";
+ t << "#---------------------------------------------------------------------------\n";
+ t << "# configuration options related to the HTML output\n";
+ t << "#---------------------------------------------------------------------------\n";
+ t << "\n";
+ t << "# If the GENERATE_HTML tag is set to YES (the default) Doxygen will\n";
+ t << "# generate HTML output\n";
+ t << "\n";
+ }
+ t << "GENERATE_HTML = YES\n";
+ if (!sl)
+ {
+ t << "\n";
+ t << "# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.\n";
+ t << "# If a relative path is entered the value of OUTPUT_DIRECTORY will be\n";
+ t << "# put in front of it. If left blank `html' will be used as the default path.\n";
+ t << "\n";
+ }
+ t << "HTML_OUTPUT =\n";
+ if (!sl)
+ {
+ t << "\n";
+ t << "# The HTML_HEADER tag can be used to specify a personal HTML header for \n";
+ t << "# each generated HTML page. If it is left blank doxygen will generate a \n";
+ t << "# standard header.\n";
+ t << "\n";
+ }
+ t << "HTML_HEADER =\n";
+ if (!sl)
+ {
+ t << "\n";
+ t << "# The HTML_FOOTER tag can be used to specify a personal HTML footer for \n";
+ t << "# each generated HTML page. If it is left blank doxygen will generate a \n";
+ t << "# standard footer.\n";
+ t << "\n";
+ }
+ t << "HTML_FOOTER =\n";
+ if (!sl)
+ {
+ t << "\n";
+ t << "#---------------------------------------------------------------------------\n";
+ t << "# configuration options related to the LaTeX output\n";
+ t << "#---------------------------------------------------------------------------\n";
+ t << "\n";
+ t << "# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will\n";
+ t << "# generate Latex output.\n";
+ t << "\n";
+ }
+ t << "GENERATE_LATEX = YES\n";
+ if (!sl)
+ {
+ t << "\n";
+ t << "# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.\n";
+ t << "# If a relative path is entered the value of OUTPUT_DIRECTORY will be\n";
+ t << "# put in front of it. If left blank `latex' will be used as the default path.\n";
+ t << "\n";
+ }
+ t << "LATEX_OUTPUT =\n";
+ if (!sl)
+ {
+ t << "\n";
+ t << "# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact\n";
+ t << "# LaTeX documents. This may be useful for small projects and may help to\n";
+ t << "# save some trees in general.\n";
+ t << "\n";
+ }
+ t << "COMPACT_LATEX = NO\n";
+ if (!sl)
+ {
+ t << "\n";
+ t << "# The PAPER_TYPE tag can be used to set the paper type that is used\n";
+ t << "# by the printer. Possible values are: a4, a4wide, letter, legal and \n";
+ t << "# executive. If left blank a4wide will be used.\n";
+ t << "\n";
+ }
+ t << "PAPER_TYPE = a4wide\n";
+ if (!sl)
+ {
+ t << "\n";
+ t << "# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX\n";
+ t << "# packages that should be included in the LaTeX output.\n";
+ t << "\n";
+ }
+ t << "EXTRA_PACKAGES =\n";
+ if (!sl)
+ {
+ t << "\n";
+ t << "#---------------------------------------------------------------------------\n";
+ t << "# configuration options related to the man page output\n";
+ t << "#---------------------------------------------------------------------------\n";
+ t << "\n";
+ t << "# If the GENERATE_MAN tag is set to YES (the default) Doxygen will\n";
+ t << "# generate man pages\n";
+ t << "\n";
+ }
+ t << "GENERATE_MAN = YES\n";
+ if (!sl)
+ {
+ t << "\n";
+ t << "# The MAN_OUTPUT tag is used to specify where the man pages will be put.\n";
+ t << "# If a relative path is entered the value of OUTPUT_DIRECTORY will be\n";
+ t << "# put in front of it. If left blank `man' will be used as the default path.\n";
+ t << "\n";
+ }
+ t << "MAN_OUTPUT =\n";
+ if (!sl)
+ {
+ t << "\n";
+ t << "#---------------------------------------------------------------------------\n";
+ t << "# Configuration options related to the preprocessor \n";
+ t << "#---------------------------------------------------------------------------\n";
+ t << "\n";
+ t << "# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will\n";
+ t << "# evaluate all C-preprocessor directives found in the sources and include\n";
+ t << "# files.\n";
+ t << "\n";
+ }
+ t << "ENABLE_PREPROCESSING = YES\n";
+ if (!sl)
+ {
+ t << "\n";
+ t << "# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro\n";
+ t << "# names in the source code. If set to NO (the default) only conditional \n";
+ t << "# compilation will be performed.\n";
+ t << "\n";
+ }
+ t << "MACRO_EXPANSION = NO\n";
+ if (!sl)
+ {
+ t << "\n";
+ t << "# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files\n";
+ t << "# in the INCLUDE_PATH (see below) will be search if a #include is found.\n";
+ t << "\n";
+ }
+ t << "SEARCH_INCLUDES = YES\n";
+ if (!sl)
+ {
+ t << "\n";
+ t << "# The INCLUDE_PATH tag can be used to specify one or more directories that\n";
+ t << "# contain include files that are not input files but should be processed by\n";
+ t << "# the preprocessor.\n" ;
+ t << "\n";
+ }
+ t << "INCLUDE_PATH =\n";
+ if (!sl)
+ {
+ t << "\n";
+ t << "# The PREDEFINED tag can be used to specify one or more macro names that\n";
+ t << "# are defined before the preprocessor is started (similar to the -D option of\n";
+ t << "# gcc). The argument of the tag is a list of macros of the form: name\n";
+ t << "# or name=definition (no spaces). If the definition and the = are \n";
+ t << "# omitted =1 is assumed.\n";
+ t << "\n";
+ }
+ t << "PREDEFINED =\n";
+ if (!sl)
+ {
+ t << "\n";
+ t << "# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES\n";
+ t << "# then the macro expansion is limited to the macros specified with the\n";
+ t << "# PREDEFINED tag.\n";
+ t << "\n";
+ }
+ t << "EXPAND_ONLY_PREDEF = NO\n";
+ if (!sl)
+ {
+ t << "\n";
+ t << "#---------------------------------------------------------------------------\n";
+ t << "# Configuration options related to external references \n";
+ t << "#---------------------------------------------------------------------------\n";
+ t << "\n";
+ t << "# The TAGFILES tag can be used to specify one or more tagfiles. \n";
+ t << "\n";
+ }
+ t << "TAGFILES =\n";
+ if (!sl)
+ {
+ t << "\n";
+ t << "# When a file name is specified after GENERATE_TAGFILE, doxygen will create\n";
+ t << "# a tag file that is based on the input files it reads.\n";
+ t << "\n";
+ }
+ t << "GENERATE_TAGFILE =\n";
+ if (!sl)
+ {
+ t << "\n";
+ t << "# If the ALLEXTERNALS tag is set to YES all external classes will be listed\n";
+ t << "# in the class index. If set to NO only the inherited external classes\n";
+ t << "# will be listed.\n";
+ t << "\n";
+ }
+ t << "ALLEXTERNALS = NO\n";
+ if (!sl)
+ {
+ t << "\n";
+ t << "# The PERL_PATH should be the absolute path and name of the perl script\n";
+ t << "# interpreter (i.e. the result of `which perl').\n";
+ t << "\n";
+ }
+ t << "PERL_PATH = /usr/local/bin/perl\n";
+ if (!sl)
+ {
+ t << "\n";
+ t << "#---------------------------------------------------------------------------\n";
+ t << "# Configuration options related to the search engine \n";
+ t << "#---------------------------------------------------------------------------\n";
+ t << "\n";
+ t << "# The SEARCHENGINE tag specifies whether or not a search engine should be \n";
+ t << "# used. If set to NO the values of all tags below this one will be ignored.\n";
+ t << "\n";
+ }
+ t << "SEARCHENGINE = NO\n";
+ if (!sl)
+ {
+ t << "\n";
+ t << "# The CGI_NAME tag should be the name of the CGI script that\n";
+ t << "# starts the search engine (doxysearch) with the correct parameters.\n";
+ t << "# A script with this name will be generated by doxygen.\n";
+ t << "\n";
+ }
+ t << "CGI_NAME = search.cgi\n";
+ if (!sl)
+ {
+ t << "\n";
+ t << "# The CGI_URL tag should be the absolute URL to the directory where the\n";
+ t << "# cgi binaries are located. See the documentation of your http daemon for \n";
+ t << "# details.\n";
+ t << "\n";
+ }
+ t << "CGI_URL =\n";
+ if (!sl)
+ {
+ t << "\n";
+ t << "# The DOC_URL tag should be the absolute URL to the directory where the\n";
+ t << "# documentation is located. If left blank the absolute path to the \n";
+ t << "# documentation, with file:// prepended to it, will be used.\n";
+ t << "\n";
+ }
+ t << "DOC_URL =\n";
+ if (!sl)
+ {
+ t << "\n";
+ t << "# The DOC_ABSPATH tag should be the absolute path to the directory where the\n";
+ t << "# documentation is located. If left blank the directory on the local machine\n";
+ t << "# will be used.\n";
+ t << "\n";
+ }
+ t << "DOC_ABSPATH =\n";
+ if (!sl)
+ {
+ t << "\n";
+ t << "# The BIN_ABSPATH tag must point to the directory where the doxysearch binary\n";
+ t << "# is installed.\n";
+ t << "\n";
+ }
+ t << "BIN_ABSPATH = /usr/local/bin/\n";
+ if (!sl)
+ {
+ t << "\n";
+ t << "# The EXT_DOC_PATHS tag can be used to specify one or more paths to \n";
+ t << "# documentation generated for other projects. This allows doxysearch to search\n";
+ t << "# the documentation for these projects as well.\n";
+ t << "\n";
+ }
+ t << "EXT_DOC_PATHS =\n";
+}
+
+void checkConfig()
+{
+ //if (projectName.length()>0)
+ //{
+ // projectName[0]=toupper(projectName[0]);
+ //}
+
+ paperType = paperType.lower().stripWhiteSpace();
+ if (paperType.isEmpty())
+ {
+ paperType = "a4wide";
+ }
+ if (paperType!="a4" && paperType!="a4wide" && paperType!="letter" &&
+ paperType!="legal" && paperType!="executive")
+ {
+ err("Error: Unknown page type specified");
+ }
+
+ outputLanguage=outputLanguage.stripWhiteSpace();
+ if (outputLanguage.isEmpty())
+ {
+ setTranslator("English");
+ }
+ else
+ {
+ if (!setTranslator(outputLanguage))
+ {
+ err("Error: Output language %s not supported! Using english instead.\n",
+ outputLanguage.data());
+ }
+ }
+
+ // Test to see if output directory is valid
+ if (outputDir.isEmpty())
+ outputDir=QDir::currentDirPath();
+ else
+ {
+ QDir dir(outputDir);
+ if (!dir.exists())
+ {
+ dir.setPath(QDir::currentDirPath());
+ if (!dir.mkdir(outputDir))
+ {
+ err("Error: tag OUTPUT_DIRECTORY: Output directory `%s' does not "
+ "exist and cannot be created\n",outputDir.data());
+ exit(1);
+ }
+ else if (!quietFlag)
+ {
+ err("Notice: Output directory `%s' does not exist. "
+ "I have created it for you.\n", outputDir.data());
+ }
+ dir.cd(outputDir);
+ }
+ outputDir=dir.absPath();
+ }
+
+ if (htmlOutputDir.isEmpty() && generateHtml)
+ {
+ htmlOutputDir=outputDir+"/html";
+ }
+ else if (htmlOutputDir && htmlOutputDir[0]!='/')
+ {
+ htmlOutputDir.prepend(outputDir+'/');
+ }
+ QDir htmlDir(htmlOutputDir);
+ if (!htmlDir.exists() && !htmlDir.mkdir(htmlOutputDir))
+ {
+ err("Could not create output directory %s\n",htmlOutputDir.data());
+ exit(1);
+ }
+
+ if (latexOutputDir.isEmpty() && generateLatex)
+ {
+ latexOutputDir=outputDir+"/latex";
+ }
+ else if (latexOutputDir && latexOutputDir[0]!='/')
+ {
+ latexOutputDir.prepend(outputDir+'/');
+ }
+ QDir latexDir(latexOutputDir);
+ if (!latexDir.exists() && !latexDir.mkdir(latexOutputDir))
+ {
+ err("Could not create output directory %s\n",latexOutputDir.data());
+ exit(1);
+ }
+
+ if (manOutputDir.isEmpty() && generateMan)
+ {
+ manOutputDir=outputDir+"/man";
+ }
+ else if (manOutputDir && manOutputDir[0]!='/')
+ {
+ manOutputDir.prepend(outputDir+'/');
+ }
+ QDir manDir(manOutputDir);
+ if (!manDir.exists() && !manDir.mkdir(manOutputDir))
+ {
+ err("Could not create output directory %s\n",manOutputDir.data());
+ exit(1);
+ }
+
+ // Test to see if HTML header is valid
+ if (headerFile.length()>0)
+ {
+ QFileInfo fi(headerFile);
+ if (!fi.exists())
+ {
+ err("Error: tag HTML_HEADER: header file `%s' "
+ "does not exist\n",headerFile.data());
+ exit(1);
+ }
+ }
+ // Test to see if HTML footer is valid
+ if (footerFile.length()>0)
+ {
+ QFileInfo fi(footerFile);
+ if (!fi.exists())
+ {
+ err("Error: tag HTML_FOOTER: footer file `%s' "
+ "does not exist\n",footerFile.data());
+ exit(1);
+ }
+ }
+ // check include path
+ char *s=includePath.first();
+ while (s)
+ {
+ QFileInfo fi(s);
+ if (!fi.exists()) err("Warning: tag INCLUDE_PATH: include path `%s' "
+ "does not exist\n",s);
+ addSearchDir(fi.absFilePath());
+ s=includePath.next();
+ }
+ // check input
+ if (inputSources.count()==0)
+ {
+ err("Error: tag INPUT: no input files specified after the INPUT tag.\n");
+ exit(1);
+ }
+ else
+ {
+ s=inputSources.first();
+ while (s)
+ {
+ QFileInfo fi(s);
+ if (!fi.exists())
+ {
+ err("Error: tag INPUT: input source `%s' does not exist\n",s);
+ exit(1);
+ }
+ s=inputSources.next();
+ }
+ }
+ // add default pattern if needed
+ if (filePatternList.count()==0)
+ {
+ filePatternList.append("*");
+ }
+
+ // more checks needed if and only if the search engine is enabled.
+ if (searchEngineFlag)
+ {
+ // check cgi name
+ if (cgiName.length()==0)
+ {
+ err("Error: tag CGI_NAME: no cgi script name after the CGI_NAME tag.\n");
+ exit(1);
+ }
+ // check cgi URL
+ if (cgiURL.length()==0)
+ {
+ err("Error: tag CGI_URL: no URL to cgi directory specified.\n");
+ exit(1);
+ }
+ else if (cgiURL.left(7)!="http://")
+ {
+ err("Error: tag CGI_URL: URL to cgi directory is invalid (must "
+ "start with http://).\n");
+ exit(1);
+ }
+ // check documentation URL
+ if (docURL.length()==0)
+ {
+ docURL = outputDir.copy().prepend("file://").append("html");
+ }
+ else if (docURL.left(7)!="http://" && docURL.left(7)!="file://")
+ {
+ err("Error: tag DOC_URL: URL to documentation is invalid or "
+ "not absolute.\n");
+ exit(1);
+ }
+ // check absolute documentation path
+ if (docAbsPath.length()==0)
+ {
+ docAbsPath = outputDir+"/html";
+ }
+ else if (docAbsPath && docAbsPath[0]!='/')
+ {
+ err("Error: tag DOC_ABSPATH: path is not absolute\n");
+ exit(1);
+ }
+ // check path to doxysearch
+ if (binAbsPath.length()==0)
+ {
+ err("Error: tag BIN_ABSPATH: no absolute path to doxysearch "
+ "specified.\n");
+ exit(1);
+ }
+ else
+ {
+ if (binAbsPath && binAbsPath[0]!='/')
+ {
+ err("Error: tag BIN_ABSPATH: path is not absolute "
+ "(must start with /).\n");
+ exit(1);
+ }
+ }
+ // check perl path
+ if (perlPath.length()==0)
+ {
+ perlPath="/usr/local/bin/perl";
+ }
+ QFileInfo fi(perlPath);
+ if (!fi.exists())
+ {
+ err("Error: tag PERL_PATH: perl interpreter not found at `%s'\n",
+ perlPath.data());
+ exit(1);
+ }
+ }
+}
+
+void parseConfig(const QString &s)
+{
+ inputString = s;
+ inputPosition = 0;
+ yyLineNr = 1;
+ configYYrestart( configYYin );
+ BEGIN( Start );
+ configYYlex();
+ checkConfig();
+}
+
+extern "C" { // some bogus code to keep the compiler happy
+ int configYYwrap() { return 1 ; }
+}
diff --git a/src/constexp.h b/src/constexp.h
new file mode 100644
index 0000000..9979bfd
--- /dev/null
+++ b/src/constexp.h
@@ -0,0 +1,30 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#ifndef _CONSTEXP_H
+#define _CONSTEXP_H
+
+#include <qstring.h>
+#include "cppvalue.h"
+
+extern bool parseCppExpression(const QString &s);
+extern int cppExpYYparse();
+extern int cppExpYYdebug;
+extern QString strToken;
+extern CPPValue resultValue;
+
+#endif
diff --git a/src/constexp.l b/src/constexp.l
new file mode 100644
index 0000000..f023507
--- /dev/null
+++ b/src/constexp.l
@@ -0,0 +1,110 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+%{
+
+#include "constexp.h"
+#include "cppvalue.h"
+#include "ce_parse.h" // generated header file
+
+#define YY_NO_UNPUT
+#define YY_NEVER_INTERACTIVE 1
+
+QString strToken;
+
+static const char *inputString;
+static int inputPosition;
+CPPValue resultValue;
+
+#undef YY_INPUT
+#define YY_INPUT(buf,result,max_size) result=yyread(buf,max_size);
+
+static int yyread(char *buf,int max_size)
+{
+ int c=0;
+ while( c < max_size && inputString[inputPosition] )
+ {
+ *buf = inputString[inputPosition++] ;
+ c++; buf++;
+ }
+ return c;
+}
+
+%}
+
+%%
+
+"?" { return TOK_QUESTIONMARK; }
+":" { return TOK_COLON; }
+"||" { return TOK_OR; }
+"&&" { return TOK_AND; }
+"|" { return TOK_BITWISEOR; }
+"^" { return TOK_BITWISEXOR; }
+"&" { return TOK_AMPERSAND; }
+"!=" { return TOK_NOTEQUAL; }
+"==" { return TOK_EQUAL; }
+"<" { return TOK_LESSTHAN; }
+">" { return TOK_GREATERTHAN; }
+"<=" { return TOK_LESSTHANOREQUALTO; }
+">=" { return TOK_GREATERTHANOREQUALTO; }
+"<<" { return TOK_SHIFTLEFT; }
+">>" { return TOK_SHIFTRIGHT; }
+"+" { return TOK_PLUS; }
+"-" { return TOK_MINUS; }
+"*" { return TOK_STAR; }
+"/" { return TOK_DIVIDE; }
+"%" { return TOK_MOD; }
+"~" { return TOK_TILDE; }
+"!" { return TOK_NOT; }
+"(" { return TOK_LPAREN; }
+")" { return TOK_RPAREN; }
+"'"(([^\'\n\r\\]+)|(\\(([ntvbrfa\\?'\"])|([0-9]+)|([xX][0-9a-fA-F]+))))"'" {
+ strToken=yytext;
+ return TOK_CHARACTER;
+ }
+0[0-7]*[uUlL]* { strToken=yytext;
+ return TOK_OCTALINT;
+ }
+[1-9][0-9]*[uUlL]* { strToken=yytext;
+ return TOK_DECIMALINT;
+ }
+(0x|0X)[0-9a-fA-F]+[uUlL]* { strToken=yytext; return TOK_HEXADECIMALINT; }
+(([0-9]+\.[0-9]*)|([0-9]*\.[0-9]+))([eE]([\-\+])?[0-9]+)?([fFlL])? {
+ strToken=yytext; return TOK_FLOAT;
+ }
+([0-9]+[eE])([\-\+])?[0-9]+([fFlL])? {
+ strToken=yytext; return TOK_FLOAT;
+ }
+.
+\n
+
+%%
+
+bool parseCppExpression(const QString &s)
+{
+ //printf("Expression: `%s'\n",s.data());
+ inputString = s;
+ inputPosition = 0;
+ cppExpYYrestart( cppExpYYin );
+ cppExpYYparse();
+ //printf("Result: %ld\n",(long)resultValue);
+ return (long)resultValue!=0;
+}
+
+extern "C" {
+ int cppExpYYwrap() { return 1; }
+}
diff --git a/src/constexp.y b/src/constexp.y
new file mode 100644
index 0000000..fa13d6e
--- /dev/null
+++ b/src/constexp.y
@@ -0,0 +1,275 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+%{
+
+#include "cppvalue.h"
+#include "constexp.h"
+
+#if defined(_MSC_VER)
+#define MSDOS
+#endif
+
+#define YYSTYPE CPPValue
+
+#include <stdio.h>
+#include <stdlib.h>
+
+int cppExpYYerror(const char *s)
+{
+ printf("ERROR: %s\n",s);
+ return 0;
+}
+
+int cppExpYYlex();
+
+%}
+
+%token TOK_QUESTIONMARK
+%token TOK_COLON
+%token TOK_OR
+%token TOK_AND
+%token TOK_BITWISEOR
+%token TOK_BITWISEXOR
+%token TOK_AMPERSAND
+%token TOK_NOTEQUAL
+%token TOK_EQUAL
+%token TOK_LESSTHAN
+%token TOK_GREATERTHAN
+%token TOK_LESSTHANOREQUALTO
+%token TOK_GREATERTHANOREQUALTO
+%token TOK_SHIFTLEFT
+%token TOK_SHIFTRIGHT
+%token TOK_PLUS
+%token TOK_MINUS
+%token TOK_STAR
+%token TOK_DIVIDE
+%token TOK_MOD
+%token TOK_TILDE
+%token TOK_NOT
+%token TOK_LPAREN
+%token TOK_RPAREN
+%token TOK_OCTALINT
+%token TOK_DECIMALINT
+%token TOK_HEXADECIMALINT
+%token TOK_CHARACTER
+%token TOK_FLOAT
+
+%%
+
+start: constant_expression
+ { resultValue = $1; return 0; }
+;
+
+constant_expression: logical_or_expression
+ { $$ = $1; }
+ | logical_or_expression
+ TOK_QUESTIONMARK logical_or_expression
+ TOK_COLON logical_or_expression
+ {
+ bool c = ($1.isInt() ? ((long)$1 != 0) : ((double)$1 != 0.0));
+ $$ = c ? $3 : $5;
+ }
+;
+
+logical_or_expression: logical_and_expression
+ { $$ = $1; }
+ | logical_or_expression TOK_OR logical_and_expression
+ {
+ $$ = CPPValue( (long)((long)$1 || (long)$3) );
+ }
+;
+
+logical_and_expression: inclusive_or_expression
+ { $$ = $1; }
+ | logical_and_expression TOK_AND inclusive_or_expression
+ {
+ $$ = CPPValue( (long)((long)$1 && (long)$3) );
+ }
+;
+
+inclusive_or_expression: exclusive_or_expression
+ { $$ = $1; }
+ | inclusive_or_expression TOK_BITWISEOR
+ exclusive_or_expression
+ {
+ $$ = CPPValue( (long)$1 | (long)$3 );
+ }
+;
+
+exclusive_or_expression: and_expression
+ { $$ = $1; }
+ | exclusive_or_expression TOK_BITWISEXOR and_expression
+ {
+ $$ = CPPValue( (long)$1 ^ (long)$3 );
+ }
+;
+
+and_expression: equality_expression
+ { $$ = $1; }
+ | and_expression TOK_AMPERSAND equality_expression
+ {
+ $$ = CPPValue( (long)$1 & (long)$3 );
+ }
+;
+
+equality_expression: relational_expression
+ { $$ = $1; }
+ | equality_expression TOK_EQUAL relational_expression
+ {
+ $$ = CPPValue( (long)((double)$1 == (double)$3) );
+ }
+ | equality_expression TOK_NOTEQUAL relational_expression
+ {
+ $$ = CPPValue( (long)((double)$1 != (double)$3) );
+ }
+;
+
+relational_expression: shift_expression
+ { $$ = $1; }
+ | relational_expression TOK_LESSTHAN shift_expression
+ {
+ $$ = CPPValue( (long)((double)$1 < (double)$3) );
+ }
+ | relational_expression TOK_GREATERTHAN shift_expression
+ {
+ $$ = CPPValue( (long)((double)$1 > (double)$3) );
+ }
+ | relational_expression TOK_LESSTHANOREQUALTO
+ shift_expression
+ {
+ $$ = CPPValue( (long)((double)$1 <= (double)$3) );
+ }
+ | relational_expression TOK_GREATERTHANOREQUALTO
+ shift_expression
+ {
+ $$ = CPPValue( (long)((double)$1 >= (double)$3) );
+ }
+;
+
+shift_expression: additive_expression
+ { $$ = $1; }
+ | shift_expression TOK_SHIFTLEFT additive_expression
+ {
+ $$ = CPPValue( (long)$1 << (long)$3 );
+ }
+ | shift_expression TOK_SHIFTRIGHT additive_expression
+ {
+ $$ = CPPValue( (long)$1 >> (long)$3 );
+ }
+;
+
+additive_expression: multiplicative_expression
+ { $$ = $1; }
+ | additive_expression TOK_PLUS multiplicative_expression
+ {
+ if (!$1.isInt() || !$3.isInt())
+ {
+ $$ = CPPValue( (double)$1 + (double)$3 );
+ }
+ else
+ {
+ $$ = CPPValue( (long)$1 + (long)$3 );
+ }
+ }
+ | additive_expression TOK_MINUS multiplicative_expression
+ {
+ if (!$1.isInt() || !$3.isInt())
+ {
+ $$ = CPPValue( (double)$1 - (double)$3 );
+ }
+ else
+ {
+ $$ = CPPValue( (long)$1 - (long)$3 );
+ }
+ }
+;
+
+multiplicative_expression: unary_expression
+ { $$ = $1; }
+ | multiplicative_expression TOK_STAR unary_expression
+ {
+ if (!$1.isInt() || !$3.isInt())
+ {
+ $$ = CPPValue( (double)$1 * (double)$3 );
+ }
+ else
+ {
+ $$ = CPPValue( (long)$1 * (long)$3 );
+ }
+ }
+ | multiplicative_expression TOK_DIVIDE unary_expression
+ {
+ if (!$1.isInt() || !$3.isInt())
+ {
+ $$ = CPPValue( (double)$1 / (double)$3 );
+ }
+ else
+ {
+ long value = $3;
+ if (value==0) value=1;
+ $$ = CPPValue( (long)$1 / value );
+ }
+ }
+ | multiplicative_expression TOK_MOD unary_expression
+ {
+ long value = $3;
+ if (value==0) value=1;
+ $$ = CPPValue( (long)$1 % value );
+ }
+;
+
+unary_expression: primary_expression
+ { $$ = $1; }
+ | TOK_PLUS unary_expression
+ { $$ = $1; }
+ | TOK_MINUS unary_expression
+ {
+ if ($2.isInt())
+ $$ = CPPValue(-(long)$2);
+ else
+ $$ = CPPValue(-(double)$2);
+ }
+ | TOK_TILDE unary_expression
+ {
+ $$ = CPPValue(~(long)$2);
+ }
+ | TOK_NOT unary_expression
+ {
+ $$ = CPPValue((long)!(long)$2);
+ }
+;
+
+primary_expression: constant
+ { $$ = $1; }
+ | TOK_LPAREN constant_expression TOK_RPAREN
+ { $$ = $2; }
+;
+
+constant: TOK_OCTALINT
+ { $$ = parseOctal(); }
+ | TOK_DECIMALINT
+ { $$ = parseDecimal(); }
+ | TOK_HEXADECIMALINT
+ { $$ = parseHexadecimal(); }
+ | TOK_CHARACTER
+ { $$ = parseCharacter(); }
+ | TOK_FLOAT
+ { $$ = parseFloat(); }
+;
+
+%%
diff --git a/src/cppvalue.cpp b/src/cppvalue.cpp
new file mode 100644
index 0000000..ab2a1d4
--- /dev/null
+++ b/src/cppvalue.cpp
@@ -0,0 +1,85 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#include <stdlib.h>
+
+#include "cppvalue.h"
+#include "constexp.h"
+
+CPPValue parseOctal()
+{
+ long val = 0;
+ for (const char *p = strToken.data(); *p != 0; p++)
+ {
+ if (*p >= '0' && *p <= '7') val = val * 8 + *p - '0';
+ }
+ return CPPValue(val);
+}
+
+CPPValue parseDecimal()
+{
+ long val = 0;
+ for (const char *p = strToken.data(); *p != 0; p++)
+ {
+ if (*p >= '0' && *p <= '9') val = val * 10 + *p - '0';
+ }
+ return CPPValue(val);
+}
+
+CPPValue parseHexadecimal()
+{
+ long val = 0;
+ for (const char *p = strToken.data(); *p != 0; p++)
+ {
+ if (*p >= '0' && *p <= '9') val = val * 16 + *p - '0';
+ else if (*p >= 'a' && *p <= 'f') val = val * 16 + *p - 'a' + 10;
+ else if (*p >= 'A' && *p <= 'F') val = val * 16 + *p - 'A' + 10;
+ }
+ return CPPValue(val);
+}
+
+CPPValue parseCharacter() // does not work for '\n' and the alike
+{
+ if (strToken[1]=='\\')
+ {
+ switch(strToken[2])
+ {
+ case 'n': return CPPValue((long)'\n');
+ case 't': return CPPValue((long)'\t');
+ case 'v': return CPPValue((long)'\v');
+ case 'b': return CPPValue((long)'\b');
+ case 'r': return CPPValue((long)'\r');
+ case 'f': return CPPValue((long)'\f');
+ case 'a': return CPPValue((long)'\a');
+ case '\\': return CPPValue((long)'\\');
+ case '?': return CPPValue((long)'\?');
+ case '\'': return CPPValue((long)'\'');
+ case '"': return CPPValue((long)'"');
+ case '0': return parseOctal();
+ case 'x':
+ case 'X': return parseHexadecimal();
+ default: printf("Invalid escape sequence %s found!\n",strToken.data());
+ return CPPValue(0L);
+ }
+ }
+ return CPPValue((long)strToken[1]);
+}
+
+CPPValue parseFloat()
+{
+ return CPPValue(atof(strToken));
+}
diff --git a/src/cppvalue.h b/src/cppvalue.h
new file mode 100644
index 0000000..d3751b2
--- /dev/null
+++ b/src/cppvalue.h
@@ -0,0 +1,59 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#ifndef _CPPVALUE_H
+#define _CPPVALUE_H
+
+#include <stdio.h>
+#include <qglobal.h>
+
+class CPPValue
+{
+ friend CPPValue parseOctal();
+ friend CPPValue parseDecimal();
+ friend CPPValue parseHexadecimal();
+ friend CPPValue parseCharacter();
+ friend CPPValue parseFloat();
+
+ public:
+ enum Type { Int, Float };
+
+ CPPValue(long val=0) : type(Int) { v.l = val; }
+ CPPValue(double val) : type(Float) { v.d = val; }
+
+ operator double () const { return type==Int ? (double)v.l : v.d; }
+ operator long () const { return type==Int ? v.l : (long)v.d; }
+
+ bool isInt() const { return type == Int; }
+
+ void print() const
+ {
+ if (type==Int)
+ printf("(%ld)\n",v.l);
+ else
+ printf("(%f)\n",v.d);
+ }
+
+ private:
+ Type type;
+ union {
+ double d;
+ long l;
+ } v;
+};
+
+#endif
diff --git a/src/debug.cpp b/src/debug.cpp
new file mode 100644
index 0000000..fc2731d
--- /dev/null
+++ b/src/debug.cpp
@@ -0,0 +1,62 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#include "debug.h"
+#include <stdarg.h>
+#include <stdio.h>
+#include <qstring.h>
+
+Debug::DebugMask Debug::curMask = Debug::Quiet;
+int Debug::curPrio = 0;
+
+void Debug::print(DebugMask mask,int prio,const char *fmt,...)
+{
+ if ((curMask&mask) && prio<=curPrio)
+ {
+ va_list args;
+ va_start(args,fmt);
+ vfprintf(stdout, fmt, args);
+ va_end(args);
+ }
+}
+
+static int labelToEnumValue(const char *l)
+{
+ QString label=l;
+ if (label=="FindMembers")
+ return Debug::FindMembers;
+ else if (label=="Functions")
+ return Debug::Functions;
+ else if (label=="Variables")
+ return Debug::Variables;
+ else
+ return 0;
+}
+
+void Debug::setFlag(const char *lab)
+{
+ curMask = (DebugMask)(curMask | labelToEnumValue(lab));
+}
+
+void Debug::clearFlag(const char *lab)
+{
+ curMask = (DebugMask)(curMask & ~labelToEnumValue(lab));
+}
+
+void Debug::setPriority(int p)
+{
+ curPrio = p;
+}
diff --git a/src/debug.h b/src/debug.h
new file mode 100644
index 0000000..b2b389f
--- /dev/null
+++ b/src/debug.h
@@ -0,0 +1,39 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#ifndef _DEBUG_H
+#define _DEBUG_H
+
+class Debug
+{
+ public:
+ enum DebugMask { Quiet = 0x00000000,
+ FindMembers = 0x00000001,
+ Functions = 0x00000002,
+ Variables = 0x00000004
+ };
+ static void print(DebugMask mask,int prio,const char *fmt,...);
+ static void setFlag(const char *label);
+ static void clearFlag(const char *label);
+ static void setPriority(int p);
+
+ private:
+ static DebugMask curMask;
+ static int curPrio;
+};
+
+#endif
diff --git a/src/declinfo.h b/src/declinfo.h
new file mode 100644
index 0000000..4ec3ec5
--- /dev/null
+++ b/src/declinfo.h
@@ -0,0 +1,32 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#ifndef DECLINFO_H
+#define DECLINFO_H
+
+#include <stdio.h>
+#include <qstring.h>
+
+extern void parseFuncDecl(const QString &decl,
+ QString &clName,
+ QString &classTempList,
+ QString &type,
+ QString &name,
+ QString &args,
+ QString &funcTempList,
+ QString &exceptions
+ );
+#endif
diff --git a/src/declinfo.l b/src/declinfo.l
new file mode 100644
index 0000000..0f0505d
--- /dev/null
+++ b/src/declinfo.l
@@ -0,0 +1,292 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+%{
+
+/*
+ * includes
+ */
+#include <stdio.h>
+#include <iostream.h>
+#include <assert.h>
+#include <ctype.h>
+
+#include "declinfo.h"
+#include "util.h"
+
+
+#define YY_NO_UNPUT
+
+/* -----------------------------------------------------------------
+ *
+ * statics
+ */
+
+static const char * inputString;
+static int inputPosition;
+static QString scope;
+static QString className;
+static QString classTempList;
+static QString funcTempList;
+static QString type;
+static QString name;
+static QString args;
+static QString tmpType;
+static int sharpCount;
+static bool classTempListFound;
+static bool funcTempListFound;
+static QString exceptionString;
+
+static void addType()
+{
+ //printf("addType() type=`%s' scope=`%s' name=`%s'\n",
+ // type.data(),scope.data(),name.data());
+ if (name.isEmpty() && scope.isEmpty()) return;
+ if (!type.isNull()) type+=' ';
+ if (!scope.isEmpty()) type+=scope+"::";
+ type+=name;
+ scope.resize(0);
+ name.resize(0);
+}
+
+static void addTypeName()
+{
+ //printf("addTypeName() type=`%s' scope=`%s' name=`%s'\n",
+ // type.data(),scope.data(),name.data());
+ if (name.isEmpty()) return;
+ if (!type.isNull()) type+=' ';
+ type+=name;
+ name.resize(0);
+}
+
+#define YY_NEVER_INTERACTIVE 1
+
+/* -----------------------------------------------------------------
+ */
+#undef YY_INPUT
+#define YY_INPUT(buf,result,max_size) result=yyread(buf,max_size);
+
+static int yyread(char *buf,int max_size)
+{
+ int c=0;
+ while( c < max_size && inputString[inputPosition] )
+ {
+ *buf = inputString[inputPosition++] ;
+ c++; buf++;
+ }
+ return c;
+}
+
+%}
+
+B [ \t]
+ID [a-z_A-Z][a-z_A-Z0-9]*
+
+%x Start
+%x Template
+%x ReadArgs
+%x Operator
+%x FuncPtr
+%x EndTemplate
+%x StripTempArgs
+%x SkipSharp
+%x ReadExceptions
+
+%%
+
+<Start>"operator" { // operator rule must be before {ID} rule
+ name += yytext;
+ BEGIN(Operator);
+ }
+<Start>(~{B}*)?{ID} {
+ addTypeName();
+ name += yytext;
+ }
+<Start>{B}*"::"{B}* { // found a scope specifier
+ if (!scope.isEmpty())
+ {
+ scope+="::"+name; // add name to scope
+ }
+ else
+ {
+ scope = name.copy(); // scope becomes name
+ }
+ name.resize(0);
+ }
+<Start>[*&]+ {
+ addType();
+ type+=yytext;
+ }
+<Start>{B}+ {
+ addType();
+ }
+<Start>{B}*"("{B}*"*" {
+ addType();
+ type+="(*";
+ }
+<Start>{B}*")" {
+ type+=")";
+ }
+<Start>{B}*"(" { // TODO: function pointers
+ args+="(";
+ BEGIN(ReadArgs);
+ }
+<Start>{B}*"[" {
+ args+="[";
+ BEGIN(ReadArgs);
+ }
+<Start>{B}*"<" {
+ name+="<";
+ sharpCount=0;
+ BEGIN(Template);
+ }
+<Template>"<" {
+ name+="<";
+ sharpCount++;
+ }
+<Template>">" {
+ name+=">";
+ if (sharpCount)
+ --sharpCount;
+ else
+ {
+ BEGIN(Start);
+ }
+ }
+<Template>. {
+ name+=*yytext;
+ }
+<Operator>{B}*"()"{B}*"<>"{B}*/"(" {
+ name+="() <>";
+ BEGIN(ReadArgs);
+ }
+<Operator>{B}*"()"{B}*/"(" {
+ name+="()";
+ BEGIN(ReadArgs);
+ }
+<Operator>[^(]*{B}*("<>"{B}*)?/"(" {
+ name+=yytext;
+ BEGIN(ReadArgs);
+ }
+<ReadArgs>"throw"{B}*"(" {
+ exceptionString="throw(";
+ BEGIN(ReadExceptions);
+ }
+<ReadArgs>. {
+ args+=*yytext;
+ }
+<ReadExceptions>. {
+ exceptionString+=*yytext;
+ }
+<*>.
+
+%%
+
+/*@ ----------------------------------------------------------------------------
+ */
+
+void parseFuncDecl(const QString &decl,QString &cl,QString &ctl,QString &t,
+ QString &n,QString &a,QString &ftl,QString &exc)
+{
+ inputString = decl;
+ //printf("Input=`%s'\n",inputString);
+ if (inputString==0) return;
+ inputPosition = 0;
+ classTempListFound = FALSE;
+ funcTempListFound = FALSE;
+ scope.resize(0);
+ className.resize(0);
+ classTempList.resize(0);
+ funcTempList.resize(0);
+ name.resize(0);
+ type.resize(0);
+ args.resize(0);
+ exceptionString.resize(0);
+ // first we try to find the type, scope, name and arguments
+ declinfoYYrestart( declinfoYYin );
+ BEGIN( Start );
+ declinfoYYlex();
+
+ cl=scope.copy();
+ int i;
+ if ((i=cl.find('<'))!=-1) // split up scope and template arguments
+ {
+ ctl=removeRedundantWhiteSpace(cl.right(cl.length()-i));
+ cl=cl.left(i);
+ }
+ n=removeRedundantWhiteSpace(name);
+ if ((i=n.find('<'))!=-1 && n.left(8)!="operator")
+ {
+ ftl=removeRedundantWhiteSpace(n.right(n.length()-i));
+ n=n.left(i);
+ }
+
+ //ctl=classTempList.copy();
+ //ftl=funcTempList.copy();
+ t=removeRedundantWhiteSpace(type);
+ a=removeRedundantWhiteSpace(args);
+ exc=removeRedundantWhiteSpace(exceptionString);
+
+ if (t.length()>0 && t.at(t.length()-1)==')')
+ {
+ a.prepend(")");
+ t=t.left(t.length()-1);
+ }
+ //printf("type=`%s' class=`%s' name=`%s' args=`%s'\n",
+ // t.data(),cl.data(),n.data(),a.data());
+
+ return;
+
+
+}
+
+extern "C" { // some bogus code to keep the compiler happy
+ int declinfoYYwrap() { return 1 ; }
+ void declinfoYYdummy() { yy_flex_realloc(0,0); }
+}
+
+#if 0
+void dumpDecl(const char *s)
+{
+ QString className;
+ QString classTNames;
+ QString type;
+ QString name;
+ QString args;
+ QString funcTNames;
+ printf("-----------------------------------------\n");
+ parseFuncDecl(s,className,classTNames,type,name,args,funcTNames);
+ printf("type=`%s' class=`%s' classTempl=`%s' name=`%s' "
+ "funcTemplateNames=`%s' args=`%s'\n",
+ type.data(),className.data(),classTNames.data(),
+ name.data(),funcTNames.data(),args.data()
+ );
+}
+
+// some test code
+int main()
+{
+ dumpDecl("A < T > :: Value * A < T > :: getValue < S > ( const A < T > & a )");
+ dumpDecl("const A<T>::Value* A<T>::getValue<S>(const A<T>&a)");
+ dumpDecl("func()");
+ dumpDecl("friend void bla<>()");
+ dumpDecl("name< T > :: operator () (int bla)");
+ dumpDecl("name< T > :: operator << (int bla)");
+ dumpDecl("name< T > :: operator << <> (int bla)");
+ dumpDecl("className::func()");
+ dumpDecl("void ( * Name < T > :: bla ) ( int, char * )");
+}
+#endif
diff --git a/src/defargs.h b/src/defargs.h
new file mode 100644
index 0000000..d2cd8f2
--- /dev/null
+++ b/src/defargs.h
@@ -0,0 +1,27 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#ifndef DEFARGS_H
+#define DEFARGS_H
+
+#include <stdio.h>
+#include <qstring.h>
+
+class ArgumentList;
+
+extern void stringToArgumentList(const char *argsString,ArgumentList* &argList);
+
+#endif
diff --git a/src/defargs.l b/src/defargs.l
new file mode 100644
index 0000000..b7dfd57
--- /dev/null
+++ b/src/defargs.l
@@ -0,0 +1,298 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+%{
+
+/*
+ * includes
+ */
+#include <stdio.h>
+#include <iostream.h>
+#include <assert.h>
+#include <ctype.h>
+#include <qregexp.h>
+
+#include "defargs.h"
+#include "entry.h"
+#include "util.h"
+
+#define YY_NO_UNPUT
+#define YY_NEVER_INTERACTIVE 1
+
+/* -----------------------------------------------------------------
+ *
+ * statics
+ */
+
+static const char *inputString;
+static int inputPosition;
+static ArgumentList *argList;
+static QString *copyArgValue;
+static QString curArgTypeName;
+static QString curArgDefValue;
+static QString curArgName;
+static int argRoundCount;
+static int argSharpCount;
+static int argCurlyCount;
+static int readArgContext;
+
+
+
+/* -----------------------------------------------------------------
+ */
+#undef YY_INPUT
+#define YY_INPUT(buf,result,max_size) result=yyread(buf,max_size);
+
+static int yyread(char *buf,int max_size)
+{
+ int c=0;
+ while( c < max_size && inputString[inputPosition] )
+ {
+ *buf = inputString[inputPosition++] ;
+ c++; buf++;
+ }
+ return c;
+}
+
+%}
+
+B [ \t]
+ID [a-z_A-Z][a-z_A-Z0-9]*
+
+%x Start
+%x CopyArgString
+%x CopyArgRound
+%x CopyArgRound2
+%x CopyArgSharp
+%x CopyArgCurly
+%x ReadFuncArgType
+%x ReadFuncArgDef
+%x ReadFuncArgPtr
+%x FuncQual
+
+
+%%
+
+<Start>[<(] { BEGIN(ReadFuncArgType); }
+
+<ReadFuncArgType>{B}* {
+ curArgTypeName+=" ";
+ }
+<ReadFuncArgDef>"'"\\[0-7]{1,3}"'" { curArgDefValue+=yytext; }
+<ReadFuncArgDef>"'"\\."'" { curArgDefValue+=yytext; }
+<ReadFuncArgDef>"'"."'" { curArgDefValue+=yytext; }
+<ReadFuncArgDef>\" {
+ curArgDefValue+=*yytext;
+ BEGIN( CopyArgString );
+ }
+<ReadFuncArgType>"("([^:)]+{B}*"::")*{B}*[&*]+{B}*/{ID} {
+ // function pointer as argument
+ curArgTypeName+=yytext;
+ //curArgTypeName=curArgTypeName.simplifyWhiteSpace();
+ BEGIN( ReadFuncArgPtr );
+ }
+<ReadFuncArgPtr>{ID} {
+ curArgName=yytext;
+ }
+<ReadFuncArgPtr>")"{B}*"(" {
+ curArgTypeName+=yytext;
+ //curArgTypeName=curArgTypeName.simplifyWhiteSpace();
+ readArgContext = ReadFuncArgType;
+ copyArgValue=&curArgTypeName;
+ argRoundCount=0;
+ BEGIN( CopyArgRound2 );
+ }
+<ReadFuncArgPtr>")" { // redundant braces detected / remove them
+ int i=curArgTypeName.findRev('('),l=curArgTypeName.length();
+ if (i!=-1)
+ curArgTypeName=curArgTypeName.left(i)+
+ curArgTypeName.right(l-i-1);
+ curArgTypeName+=curArgName;
+ BEGIN( ReadFuncArgType );
+ }
+<ReadFuncArgType,ReadFuncArgDef>[({<] {
+ if (YY_START==ReadFuncArgType)
+ {
+ curArgTypeName+=*yytext;
+ copyArgValue=&curArgTypeName;
+ }
+ else // YY_START==ReadFuncArgDef
+ {
+ curArgDefValue+=*yytext;
+ copyArgValue=&curArgDefValue;
+ }
+ readArgContext = YY_START;
+ if (*yytext=='(')
+ {
+ argRoundCount=0;
+ BEGIN( CopyArgRound );
+ }
+ else if (*yytext=='{')
+ {
+ argCurlyCount=0;
+ BEGIN( CopyArgCurly );
+ }
+ else // yytext=='<'
+ {
+ argSharpCount=0;
+ BEGIN( CopyArgSharp );
+ }
+ }
+<CopyArgRound,CopyArgRound2>"(" {
+ argRoundCount++;
+ *copyArgValue += *yytext;
+ }
+<CopyArgRound,CopyArgRound2>")" {
+ *copyArgValue += *yytext;
+ if (argRoundCount>0)
+ {
+ argRoundCount--;
+ }
+ else
+ {
+ if (YY_START==CopyArgRound2)
+ {
+ *copyArgValue+=" "+curArgName;
+ }
+ BEGIN( readArgContext );
+ }
+ }
+<CopyArgSharp>"<" {
+ argSharpCount++;
+ *copyArgValue += *yytext;
+ }
+<CopyArgSharp>">" {
+ *copyArgValue += *yytext;
+ if (argSharpCount>0) argSharpCount--;
+ else BEGIN( readArgContext );
+ }
+<CopyArgCurly>"{" {
+ argCurlyCount++;
+ *copyArgValue += *yytext;
+ }
+<CopyArgSharp>"}" {
+ *copyArgValue += *yytext;
+ if (argCurlyCount>0) argCurlyCount--;
+ else BEGIN( readArgContext );
+ }
+<CopyArgString>\\. {
+ curArgDefValue+=yytext;
+ }
+<CopyArgString>\" {
+ curArgDefValue+=*yytext;
+ BEGIN( ReadFuncArgDef );
+ }
+<ReadFuncArgType>"=" {
+ BEGIN( ReadFuncArgDef );
+ }
+<ReadFuncArgType,ReadFuncArgDef>[,)>] {
+ curArgTypeName=removeRedundantWhiteSpace(
+ curArgTypeName.simplifyWhiteSpace());
+ curArgDefValue=curArgDefValue.stripWhiteSpace();
+ int l=curArgTypeName.length();
+ if (l>0)
+ {
+ int i=l-1;
+ while (i>=0 &&
+ (
+ isspace(curArgTypeName.at(i)) ||
+ isId(curArgTypeName.at(i))
+ )
+ ) i--;
+ Argument *a = new Argument;
+ if (i>=0 && curArgTypeName.at(i)!=':')
+ { // type contains a name
+ a->type = curArgTypeName.left(i+1).stripWhiteSpace();
+ a->name = curArgTypeName.right(curArgTypeName.length()-i-1);
+ }
+ else // assume only the type was specified, try to determine name later
+ {
+ a->type = curArgTypeName.stripWhiteSpace();
+ }
+ a->defval = curArgDefValue.copy();
+ //printf("----> Adding argument `%s' `%s' `%s'\n",a->type.data(),a->name.data(),a->defval.data());
+ argList->append(a);
+ }
+ curArgTypeName.resize(0);
+ curArgDefValue.resize(0);
+ if (*yytext==')')
+ {
+ BEGIN(FuncQual);
+ //printf(">>> end of argument list\n");
+ }
+ else
+ {
+ BEGIN( ReadFuncArgType );
+ }
+ }
+<ReadFuncArgType,ReadFuncArgPtr>{ID} {
+ QString name=yytext; //resolveDefines(yytext);
+ //printf("resolveName `%s'->`%s'\n",yytext,name.data());
+ curArgTypeName+=name;
+ }
+<ReadFuncArgType,ReadFuncArgPtr>. {
+ curArgTypeName+=*yytext;
+ }
+<ReadFuncArgDef,CopyArgString>. {
+ curArgDefValue+=*yytext;
+ }
+<CopyArgRound,CopyArgRound2,CopyArgSharp,CopyArgCurly>{ID} {
+ QString name=yytext; //resolveDefines(yytext);
+ *copyArgValue+=name;
+ }
+<CopyArgRound,CopyArgRound2,CopyArgSharp,CopyArgCurly>. {
+ *copyArgValue += *yytext;
+ }
+<FuncQual>"const" {
+ argList->constSpecifier=TRUE;
+ }
+<FuncQual>"volatile" {
+ argList->volatileSpecifier=TRUE;
+ }
+<FuncQual>"="{B}*"0" {
+ argList->pureSpecifier=TRUE;
+ }
+<*>.
+
+%%
+
+/* ----------------------------------------------------------------------------
+ */
+
+// converts an argument string into a list of Arguments.
+// an Argument consists of a type, an optional name, and an optional
+// default initializer.
+
+void stringToArgumentList(const char *argsString,ArgumentList* &al)
+{
+ //if (al==0) al=new ArgumentList; // allocate new list if needed.
+ if (al==0) return;
+ if (!argsString) return;
+ inputString = argsString;
+ inputPosition = 0;
+ curArgTypeName.resize(0);
+ curArgDefValue.resize(0);
+ curArgName.resize(0);
+ argList = al;
+ defargsYYrestart( defargsYYin );
+ BEGIN( Start );
+ defargsYYlex();
+}
+
+extern "C" { // some bogus code to keep the compiler happy
+ int defargsYYwrap() { return 1 ; }
+ void defargsYYdummy() { yy_flex_realloc(0,0); }
+}
diff --git a/src/define.cpp b/src/define.cpp
new file mode 100644
index 0000000..2fa7fa4
--- /dev/null
+++ b/src/define.cpp
@@ -0,0 +1,43 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#include "define.h"
+#include "config.h"
+
+Define::Define()
+{
+ undef=FALSE;
+ fileDef=0;
+}
+
+Define::Define(const Define &d)
+ : name(d.name),definition(d.definition),fileName(d.fileName)
+{
+ //name=d.name; definition=d.definition; fileName=d.fileName;
+ lineNr=d.lineNr;
+ nargs=d.nargs;
+ undef=d.undef;
+ fileDef=0;
+}
+
+Define::~Define()
+{
+}
+
+bool Define::hasDocumentation()
+{
+ return definition && (doc || extractAllFlag);
+}
diff --git a/src/define.h b/src/define.h
new file mode 100644
index 0000000..14ac008
--- /dev/null
+++ b/src/define.h
@@ -0,0 +1,88 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#ifndef DEFINE_H
+#define DEFINE_H
+
+#include <qdict.h>
+#include <qstring.h>
+#include "util.h"
+
+class FileDef;
+
+class Define
+{
+ public:
+ Define();
+ Define(const Define &d);
+ ~Define();
+ bool hasDocumentation();
+ QString name;
+ QString definition;
+ QString fileName;
+ QString doc;
+ QString brief;
+ QString args;
+ QString anchor;
+ FileDef *fileDef;
+ int lineNr;
+ int nargs;
+ bool undef;
+ bool varArgs;
+};
+
+class DefineList : public QList<Define>
+{
+ public:
+ DefineList() : QList<Define>() {}
+ ~DefineList() {}
+ int compareItems(GCI i1,GCI i2)
+ {
+ return strcmp(((Define *)i1)->name,((Define *)i2)->name);
+ }
+};
+
+class DefineName : public QList<Define>
+{
+ public:
+ DefineName(const char *n) : QList<Define>() { name=n; }
+ ~DefineName() {}
+ const char *nameString() const { return name; }
+ int compareItems(GCI i1,GCI i2)
+ {
+ return strcmp(((Define *)i1)->name,((Define *)i2)->name);
+ }
+
+ private:
+ QString name;
+};
+
+class DefineNameList : public QList<DefineName>
+{
+ public:
+ DefineNameList() : QList<DefineName>() {}
+ ~DefineNameList() {}
+ int compareItems(GCI i1,GCI i2)
+ {
+ return stricmp(((DefineName *)i1)->nameString(),
+ ((DefineName *)i2)->nameString());
+ }
+};
+
+typedef QDict<Define> DefineDict;
+typedef QDict<DefineName> DefineNameDict;
+
+#endif
diff --git a/src/definition.cpp b/src/definition.cpp
new file mode 100644
index 0000000..535612b
--- /dev/null
+++ b/src/definition.cpp
@@ -0,0 +1,44 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#include <ctype.h>
+#include "definition.h"
+
+QString Definition::nameToFile(const char *name)
+{
+ QString result;
+ char c;
+ const char *p=name;
+ while ((c=*p++)!=0)
+ {
+ switch(c)
+ {
+ case ':': break;
+ case '<': result+="_lt"; break;
+ case '>': result+="_gt"; break;
+ case '*': result+="_ast"; break;
+ case '&': result+="_amp"; break;
+ case ' ': break;
+ default:
+ if (caseSensitiveNames)
+ result+=c;
+ else
+ result+=tolower(c);
+ break;
+ }
+ }
+ return result;
+}
diff --git a/src/definition.h b/src/definition.h
new file mode 100644
index 0000000..2dbee89
--- /dev/null
+++ b/src/definition.h
@@ -0,0 +1,64 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#ifndef DEFINITION_H
+#define DEFINITION_H
+
+#include <qstring.h>
+#include "config.h"
+
+/*! The common base class of all definitions. */
+class Definition
+{
+ public:
+ //! create a new definition
+ Definition(const char *name,const char *b=0,const char *d=0)
+ { n=name; brief=b; doc=d; }
+ //! destroys the definition
+ virtual ~Definition() {}
+ //! returns the name of the definition
+ QString name() const { return n; }
+ //! returns the detailed description of this definition
+ QString documentation() const { return doc; }
+ //! returns the brief description of this definition
+ QString briefDescription() const { return brief; }
+ //! sets a new name for the definition
+ void setName(const char *name) { n=name; }
+ //! sets the documentation of this definition
+ void setDocumentation(const char *d)
+ {
+ doc=d; doc=doc.stripWhiteSpace();
+ }
+ //! sets the brief description of this definition
+ void setBriefDescription(const char *b)
+ {
+ brief=b; brief=brief.stripWhiteSpace();
+ int bl=brief.length();
+ if (bl>0 && brief.at(bl-1)!='.' && brief.at(bl-1)!='!' &&
+ brief.at(bl-1)!='?') brief+='.';
+ }
+ //! returns TRUE iff the definition is documented
+ bool hasDocumentation()
+ { return !doc.isNull() || !brief.isNull() || extractAllFlag; }
+ QString nameToFile(const char *name);
+
+ private:
+ QString n; // name of the definition
+ QString brief; // brief description
+ QString doc; // detailed description
+};
+
+#endif
diff --git a/src/diagram.cpp b/src/diagram.cpp
new file mode 100644
index 0000000..0fd30a5
--- /dev/null
+++ b/src/diagram.cpp
@@ -0,0 +1,1236 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <qlist.h>
+#include <qstring.h>
+#include <qarray.h>
+#include <qtstream.h>
+#include <qfile.h>
+
+#include "diagram.h"
+#include "image.h"
+#include "classdef.h"
+#include "config.h"
+#include "message.h"
+#include "util.h"
+#include "latexgen.h"
+#include "htmlgen.h"
+
+//-----------------------------------------------------------------------------
+
+const uint maxTreeWidth = 8;
+const int gridWidth = 100;
+const int gridHeight = 100;
+
+const uint labelHorSpacing = 10; // horizontal distance between labels
+const uint labelVertSpacing = 32; // vertical distance between labels
+const uint labelHorMargin = 6; // horiz. spacing between label and box
+const uint fontHeight = 12; // height of a character
+
+//static QString escapeLatex(const char *s)
+//{
+// QString result;
+// char c;
+// while ((c=*s++))
+// {
+// if (c=='_') result+="\\_";
+// else result+=c;
+// }
+// return result;
+//}
+
+static uint protToMask(Protection p)
+{
+ switch(p)
+ {
+ case Public: return 0xffffffff;
+ case Protected: return 0xcccccccc;
+ case Private: return 0xaaaaaaaa;
+ }
+ return 0;
+}
+
+static uint protToColor(Protection p)
+{
+ switch(p)
+ {
+ case Public: return 6;
+ case Protected: return 5;
+ case Private: return 4;
+ }
+ return 0;
+}
+
+static QString protToString(Protection p)
+{
+ switch(p)
+ {
+ case Public: return "solid";
+ case Protected: return "dashed";
+ case Private: return "dotted";
+ }
+ return 0;
+}
+
+static uint virtToMask(Specifier p)
+{
+ switch(p)
+ {
+ case Normal: return 0xffffffff;
+ case Virtual: return 0xf0f0f0f0;
+ default: return 0;
+ }
+ return 0;
+}
+
+// pre: dil is not empty
+static Protection getMinProtectionLevel(DiagramItemList *dil)
+{
+ DiagramItem *di=dil->first();
+ Protection result=di->protection();
+ di=dil->next();
+ while (di)
+ {
+ Protection p=di->protection();
+ if (p!=result)
+ {
+ if (result==Protected && p==Public) result=p;
+ else if (result==Private) result=p;
+ }
+ di=dil->next();
+ }
+ return result;
+}
+
+static void writeBitmapBox(DiagramItem *di,Image *image,
+ int x,int y,int w,int h,bool firstRow,
+ bool hasDocs,bool children=FALSE)
+{
+ int colFill = hasDocs ? (firstRow ? 0 : 2) : 7;
+ int colBorder = (firstRow || !hasDocs) ? 1 : 3;
+ int l = stringLength(di->label());
+ uint mask=virtToMask(di->virtualness());
+ image->fillRect(x+1,y+1,w-2,h-2,colFill,mask);
+ image->drawRect(x,y,w,h,colBorder,mask);
+ image->writeString(x+(w-l)/2, y+(h-fontHeight)/2, di->label(),1);
+ if (children)
+ {
+ int i;
+ for (i=0;i<5;i++)
+ image->drawHorzLine(y+h+i-6,x+w-2-i,x+w-2,firstRow?1:3,0xffffffff);
+ }
+}
+
+static void writeVectorBox(QTextStream &t,DiagramItem *di,
+ float x,float y,bool children=FALSE)
+{
+ if (di->virtualness()==Virtual) t << "dashed\n";
+ t << " (" << di->label() << ") " << x << " " << y << " box\n";
+ if (children) t << x << " " << y << " mark\n";
+ if (di->virtualness()==Virtual) t << "solid\n";
+}
+
+static void writeMapArea(QTextStream &t,ClassDef *cd,int x,int y,int w,int h)
+{
+ if (cd->hasDocumentation() || cd->isReference())
+ {
+ t << "<area ";
+ if (cd->getReference()) t << "doxygen=\"" << cd->getReference() << ":\" ";
+ t << "href=\"" << cd->classFile() << ".html\" ";
+ t << "ALT=\"" << cd->name();
+ t << "\" shape=\"rect\" coords=\"" << x << "," << y << ",";
+ t << x+w << "," << y+h << "\">" << endl;
+ }
+}
+//-----------------------------------------------------------------------------
+
+DiagramItem::DiagramItem(DiagramItem *p,int number,ClassDef *cd,
+ Protection pr,Specifier vi,const char *ts)
+{
+ parent=p;
+ x=y=0;
+ //name=n;
+ num=number;
+ children = new DiagramItemList;
+ prot=pr;
+ virt=vi;
+ inList=FALSE;
+ classDef=cd;
+ templSpec=ts;
+}
+
+DiagramItem::~DiagramItem()
+{
+ delete children;
+}
+
+QString DiagramItem::label() const
+{
+ return classDef->name()+templSpec;
+}
+
+QString DiagramItem::fileName() const
+{
+ return classDef->classFile();
+}
+
+int DiagramItem::avgChildPos() const
+{
+ DiagramItem *di;
+ int c=children->count();
+ if (c==0) // no children -> don't move
+ return xPos();
+ if ((di=children->getFirst())->isInList()) // children should be in a list
+ return di->xPos();
+ if (c&1) // odd number of children -> get pos of middle child
+ return children->at(c/2)->xPos();
+ else // even number of children -> get middle of most middle children
+ return (children->at(c/2-1)->xPos()+children->at(c/2)->xPos())/2;
+}
+
+int DiagramItem::numChildren() const
+{
+ return children->count();
+}
+
+void DiagramItem::addChild(DiagramItem *di)
+{
+ children->append(di);
+}
+
+void DiagramRow::insertClass(DiagramItem *parent,ClassDef *cd,bool doBases,
+ Protection prot,Specifier virt,const char *ts)
+{
+ DiagramItem *di=new DiagramItem(parent, diagram->at(level)->count(),
+ cd,prot,virt,ts);
+ if (parent) parent->addChild(di);
+ di->move(count()*gridWidth,level*gridHeight);
+ append(di);
+ BaseClassList *bcl=doBases ? cd->baseClasses() : cd->superClasses();
+ /* there are base/super classes */
+ int count=0;
+ BaseClassDef *bcd=bcl->first();
+ while (bcd)
+ {
+ ClassDef *ccd=bcd->classDef;
+ if (ccd && ccd->isVisibleExt()
+ //(ccd->protection()!=Private || extractPrivateFlag) &&
+ //(ccd->hasDocumentation() || !hideClassFlag)
+ ) count++;
+ bcd=bcl->next();
+ }
+ if (count>0 && (prot!=Private || !doBases))
+ {
+ DiagramRow *row=0;
+ if (diagram->count()<=level+1) /* add new row */
+ {
+ row = new DiagramRow(diagram,level+1);
+ diagram->append(row);
+ }
+ else /* get next row */
+ {
+ row=diagram->at(level+1);
+ }
+ /* insert base classes in the next row */
+ BaseClassDef *bcd=bcl->last();
+ while (bcd)
+ {
+ ClassDef *ccd=bcd->classDef;
+ if (ccd && ccd->isVisibleExt()
+ //(ccd->protection()!=Private || extractPrivateFlag) &&
+ //(ccd->hasDocumentation() || !hideClassFlag)
+ )
+ {
+ row->insertClass(di,ccd,doBases,bcd->prot,
+ doBases?bcd->virt:Normal,
+ doBases?bcd->templSpecifiers.data():"");
+ }
+ bcd=bcl->prev();
+ }
+ }
+}
+
+TreeDiagram::TreeDiagram(ClassDef *root,bool doBases)
+{
+ setAutoDelete(TRUE);
+ DiagramRow *row=new DiagramRow(this,0);
+ append(row);
+ row->insertClass(0,root,doBases,Public,Normal,0);
+}
+
+TreeDiagram::~TreeDiagram()
+{
+}
+
+
+void TreeDiagram::moveChildren(DiagramItem *root,int dx)
+{
+ DiagramItemList *dil=root->getChildren();
+ DiagramItem *di=dil->first();
+ while (di)
+ {
+ di->move(dx,0);
+ moveChildren(di,dx);
+ di=dil->next();
+ }
+}
+
+bool TreeDiagram::layoutTree(DiagramItem *root,int r)
+{
+ bool moved=FALSE;
+ //printf("layoutTree(%s,%d)\n",root->label().data(),r);
+
+ DiagramItemList *dil=root->getChildren();
+ if (dil->count()>0)
+ {
+ uint k;
+ int pPos=root->xPos();
+ int cPos=root->avgChildPos();
+ if (pPos>cPos) // move children
+ {
+ DiagramRow *row=at(r+1);
+ //printf("Moving children %d-%d in row %d\n",
+ // dil->getFirst()->number(),row->count()-1,r+1);
+ for (k=dil->getFirst()->number();k<row->count();k++)
+ row->at(k)->move(pPos-cPos,0);
+ moved=TRUE;
+ }
+ else if (pPos<cPos) // move parent
+ {
+ DiagramRow *row=at(r);
+ //printf("Moving parents %d-%d in row %d\n",
+ // root->number(),row->count()-1,r);
+ for (k=root->number();k<row->count();k++)
+ row->at(k)->move(cPos-pPos,0);
+ moved=TRUE;
+ }
+
+ // recurse to children
+ DiagramItem *di=dil->first();
+ while (di && !moved && !di->isInList())
+ {
+ moved = moved || layoutTree(di,r+1);
+ di=dil->next();
+ }
+ }
+ return moved;
+}
+
+void TreeDiagram::computeLayout()
+{
+ DiagramRow *row=first();
+ while (row && row->count()<maxTreeWidth) row=next();
+ if (row)
+ {
+ //printf("computeLayout() list row at %d\n",row->number());
+ DiagramItem *di=row->first();
+ DiagramItem *opi=0;
+ int delta=0;
+ bool first=TRUE;
+ while (di)
+ {
+ DiagramItem *pi=di->parentItem();
+ if (pi==opi && !first) { delta-=gridWidth; }
+ first = pi!=opi;
+ opi=pi;
+ di->move(delta,0); // collapse all items in the same
+ // list (except the first)
+ di->putInList();
+ di=row->next();
+ }
+ }
+
+ // re-organize the diagram items
+ DiagramItem *root=getFirst()->getFirst();
+ while (layoutTree(root,0));
+
+ // move first items of the lists
+ if (row)
+ {
+ DiagramItem *di=row->first();
+ while (di)
+ {
+ DiagramItem *pi=di->parentItem();
+ if (pi->getChildren()->count()>1)
+ {
+ di->move(gridWidth,0);
+ while (di && di->parentItem()==pi) di=row->next();
+ }
+ else
+ {
+ di=row->next();
+ }
+ }
+ }
+}
+
+uint TreeDiagram::computeRows()
+{
+ //printf("TreeDiagram::computeRows()=%d\n",count());
+ int count=0;
+ DiagramRow *row=first();
+ while (row && !row->getFirst()->isInList())
+ {
+ count++;
+ row=next();
+ }
+ //printf("count=%d row=%p\n",count,row);
+ if (row)
+ {
+ int maxListLen=0;
+ int curListLen=0;
+ DiagramItem *di=row->first(),*opi=0;
+ while (di)
+ {
+ if (di->parentItem()!=opi) curListLen=1; else curListLen++;
+ if (curListLen>maxListLen) maxListLen=curListLen;
+ opi=di->parentItem();
+ di=row->next();
+ }
+ //printf("maxListLen=%d\n",maxListLen);
+ count+=maxListLen;
+ }
+ return count;
+}
+
+#if 0
+uint TreeDiagram::computeCols()
+{
+ uint count=0;
+ DiagramRow *row=first();
+ while (row && !row->getFirst()->isInList())
+ {
+ if (row->count()>count) count=row->count();
+ row=next();
+ }
+ if (row)
+ {
+ row=prev();
+ uint cols=row->count();
+ if (row->getLast()->getChildren()->count()>1) cols++;
+ if (cols>count) count=cols;
+ }
+ return count;
+};
+#endif
+
+void TreeDiagram::computeExtremes(uint *maxLabelLen,uint *maxXPos)
+{
+ uint ml=0,mx=0;
+ DiagramRow *dr=first();
+ bool done=FALSE;
+ while (dr && !done)
+ {
+ DiagramItem *di=dr->first();
+ while (di)
+ {
+ if (di->isInList()) done=TRUE;
+ if (maxXPos) mx=QMAX(mx,(uint)di->xPos());
+ if (maxLabelLen) ml=QMAX(ml,stringLength(di->label()));
+ di=dr->next();
+ }
+ dr=next();
+ }
+ if (maxLabelLen) *maxLabelLen=ml;
+ if (maxXPos) *maxXPos=mx;
+}
+
+void TreeDiagram::drawBoxes(QTextStream &t,Image *image,
+ bool doBase,bool bitmap,
+ uint baseRows,uint superRows,
+ uint cellWidth,uint cellHeight)
+{
+ DiagramRow *dr=first();
+ if (!doBase) dr=next();
+ bool done=FALSE;
+ bool firstRow = doBase;
+ while (dr && !done)
+ {
+ int x=0,y=0;
+ float xf=0.0,yf=0.0;
+ DiagramItem *di=dr->first();
+ if (di->isInList()) // put boxes in a list
+ {
+ DiagramItem *opi=0;
+ if (doBase) di=dr->last();
+ while (di)
+ {
+ if (di->parentItem()==opi)
+ {
+ if (bitmap)
+ {
+ if (doBase) y -= cellHeight+labelVertSpacing;
+ else y += cellHeight+labelVertSpacing;
+ }
+ else
+ {
+ if (doBase) yf += 1.0;
+ else yf -= 1.0;
+ }
+ }
+ else
+ {
+ if (bitmap)
+ {
+ x = di->xPos()*(cellWidth+labelHorSpacing)/gridWidth;
+ if (doBase)
+ {
+ y = image->getHeight()-
+ superRows*cellHeight-
+ (superRows-1)*labelVertSpacing-
+ di->yPos()*(cellHeight+labelVertSpacing)/gridHeight;
+ }
+ else
+ {
+ y = (baseRows-1)*(cellHeight+labelVertSpacing)+
+ di->yPos()*(cellHeight+labelVertSpacing)/gridHeight;
+ }
+ }
+ else
+ {
+ xf = di->xPos()/(float)gridWidth;
+ if (doBase)
+ {
+ yf = di->yPos()/(float)gridHeight+superRows-1;
+ }
+ else
+ {
+ yf = superRows-1-di->yPos()/(float)gridHeight;
+ }
+ }
+ }
+ opi=di->parentItem();
+
+ if (bitmap)
+ {
+ bool hasDocs=di->getClassDef()->hasDocumentation() ||
+ di->getClassDef()->isReference();
+ writeBitmapBox(di,image,x,y,cellWidth,cellHeight,firstRow,
+ hasDocs,di->getChildren()->count()>0);
+ if (!firstRow) writeMapArea(t,di->getClassDef(),x,y,cellWidth,cellHeight);
+ }
+ else
+ {
+ writeVectorBox(t,di,xf,yf,di->getChildren()->count()>0);
+ }
+
+ if (doBase) di=dr->prev(); else di=dr->next();
+ }
+ done=TRUE;
+ }
+ else // draw a tree of boxes
+ {
+ while (di)
+ {
+ if (bitmap)
+ {
+ x = di->xPos()*(cellWidth+labelHorSpacing)/gridWidth;
+ if (doBase)
+ {
+ y = image->getHeight()-
+ superRows*cellHeight-
+ (superRows-1)*labelVertSpacing-
+ di->yPos()*(cellHeight+labelVertSpacing)/gridHeight;
+ }
+ else
+ {
+ y = (baseRows-1)*(cellHeight+labelVertSpacing)+
+ di->yPos()*(cellHeight+labelVertSpacing)/gridHeight;
+ }
+ bool hasDocs=di->getClassDef()->hasDocumentation() ||
+ di->getClassDef()->isReference();
+ writeBitmapBox(di,image,x,y,cellWidth,cellHeight,firstRow,hasDocs);
+ if (!firstRow) writeMapArea(t,di->getClassDef(),x,y,cellWidth,cellHeight);
+ }
+ else
+ {
+ xf=di->xPos()/(float)gridWidth;
+ if (doBase)
+ {
+ yf = di->yPos()/(float)gridHeight+superRows-1;
+ }
+ else
+ {
+ yf = superRows-1-di->yPos()/(float)gridHeight;
+ }
+ writeVectorBox(t,di,xf,yf);
+ }
+
+ di=dr->next();
+ }
+ }
+ dr=next();
+ firstRow=FALSE;
+ }
+}
+
+void TreeDiagram::drawConnectors(QTextStream &t,Image *image,
+ bool doBase,bool bitmap,
+ uint baseRows,uint superRows,
+ uint cellWidth,uint cellHeight)
+{
+ DiagramRow *dr=first();
+ bool done=FALSE;
+ while (dr && !done) // for each row
+ {
+ DiagramItem *di=dr->first();
+ if (di->isInList()) // row consists of list connectors
+ {
+ int x=0,y=0,ys=0;
+ float xf=0.0,yf=0.0,ysf=0.0;
+ while (di)
+ {
+ DiagramItem *pi=di->parentItem();
+ DiagramItemList *dil=pi->getChildren();
+ DiagramItem *last=dil->getLast();
+ if (di==last) // single child
+ {
+ if (bitmap) // draw pixels
+ {
+ x = di->xPos()*(cellWidth+labelHorSpacing)/gridWidth + cellWidth/2;
+ if (doBase) // base classes
+ {
+ y = image->getHeight()-
+ (superRows-1)*(cellHeight+labelVertSpacing)-
+ di->yPos()*(cellHeight+labelVertSpacing)/gridHeight;
+ image->drawVertArrow(x,y,y+labelVertSpacing/2,
+ protToColor(di->protection()),
+ protToMask(di->protection()));
+ }
+ else // super classes
+ {
+ y = (baseRows-1)*(cellHeight+labelVertSpacing)-
+ labelVertSpacing/2+
+ di->yPos()*(cellHeight+labelVertSpacing)/gridHeight;
+ image->drawVertLine(x,y,y+labelVertSpacing/2,
+ protToColor(di->protection()),
+ protToMask(di->protection()));
+ }
+ }
+ else // draw vectors
+ {
+ t << protToString(di->protection()) << endl;
+ if (doBase)
+ {
+ t << "1 " << di->xPos()/(float)gridWidth << " "
+ << di->yPos()/(float)gridHeight+superRows-1 << " in\n";
+ }
+ else
+ {
+ t << "0 " << di->xPos()/(float)gridWidth << " "
+ << (float)superRows-0.25-di->yPos()/(float)gridHeight
+ << " in\n";
+ }
+ }
+ }
+ else // multiple children, put them in a vertical list
+ {
+ if (bitmap)
+ {
+ x = di->parentItem()->xPos()*
+ (cellWidth+labelHorSpacing)/gridWidth+cellWidth/2;
+ if (doBase) // base classes
+ {
+ ys = image->getHeight()-
+ (superRows-1)*(cellHeight+labelVertSpacing)-
+ di->yPos()*(cellHeight+labelVertSpacing)/gridHeight;
+ y = ys - cellHeight/2;
+ }
+ else // super classes
+ {
+ ys = (baseRows-1)*(cellHeight+labelVertSpacing)+
+ di->yPos()*(cellHeight+labelVertSpacing)/gridHeight;
+ y = ys + cellHeight/2;
+ }
+ }
+ else
+ {
+ xf = di->parentItem()->xPos()/(float)gridWidth;
+ if (doBase)
+ {
+ ysf = di->yPos()/(float)gridHeight+superRows-1;
+ yf = ysf + 0.5;
+ }
+ else
+ {
+ ysf = (float)superRows-0.25-di->yPos()/(float)gridHeight;
+ yf = ysf - 0.25;
+ }
+ }
+ while (di!=last) // more children to add
+ {
+ if (bitmap)
+ {
+ if (doBase) // base classes
+ {
+ image->drawHorzArrow(y,x,x+cellWidth/2+labelHorSpacing,
+ protToColor(di->protection()),
+ protToMask(di->protection()));
+ y -= cellHeight+labelVertSpacing;
+ }
+ else // super classes
+ {
+ image->drawHorzLine(y,x,x+cellWidth/2+labelHorSpacing,
+ protToColor(di->protection()),
+ protToMask(di->protection()));
+ y += cellHeight+labelVertSpacing;
+ }
+ }
+ else
+ {
+ t << protToString(di->protection()) << endl;
+ if (doBase)
+ {
+ t << "1 " << xf << " " << yf << " hedge\n";
+ yf += 1.0;
+ }
+ else
+ {
+ t << "0 " << xf << " " << yf << " hedge\n";
+ yf -= 1.0;
+ }
+ }
+ di=dr->next();
+ }
+ // add last horizonal line and a vertical connection line
+ if (bitmap)
+ {
+ if (doBase) // base classes
+ {
+ image->drawHorzArrow(y,x,x+cellWidth/2+labelHorSpacing,
+ protToColor(di->protection()),
+ protToMask(di->protection()));
+ image->drawVertLine(x,y,ys+labelVertSpacing/2,
+ protToColor(getMinProtectionLevel(dil)),
+ protToMask(getMinProtectionLevel(dil)));
+ }
+ else // super classes
+ {
+ image->drawHorzLine(y,x,x+cellWidth/2+labelHorSpacing,
+ protToColor(di->protection()),
+ protToMask(di->protection()));
+ image->drawVertLine(x,ys-labelVertSpacing/2,y,
+ protToColor(getMinProtectionLevel(dil)),
+ protToMask(getMinProtectionLevel(dil)));
+ }
+ }
+ else
+ {
+ t << protToString(di->protection()) << endl;
+ if (doBase)
+ {
+ t << "1 " << xf << " " << yf << " hedge\n";
+ }
+ else
+ {
+ t << "0 " << xf << " " << yf << " hedge\n";
+ }
+ t << protToString(getMinProtectionLevel(dil)) << endl;
+ if (doBase)
+ {
+ t << xf << " " << ysf << " " << yf << " vedge\n";
+ }
+ else
+ {
+ t << xf << " " << ysf + 0.25 << " " << yf << " vedge\n";
+ }
+ }
+ }
+ di=dr->next();
+ }
+ done=TRUE; // the tree is drawn now
+ }
+ else // normal tree connector
+ {
+ while (di)
+ {
+ int x=0,y=0;
+ DiagramItemList *dil = di->getChildren();
+ DiagramItem *parent = di->parentItem();
+ if (parent) // item has a parent -> connect to it
+ {
+ if (bitmap) // draw pixels
+ {
+ x = di->xPos()*(cellWidth+labelHorSpacing)/gridWidth + cellWidth/2;
+ if (doBase) // base classes
+ {
+ y = image->getHeight()-
+ (superRows-1)*(cellHeight+labelVertSpacing)-
+ di->yPos()*(cellHeight+labelVertSpacing)/gridHeight;
+ /* write input line */
+ image->drawVertArrow(x,y,y+labelVertSpacing/2,
+ protToColor(di->protection()),
+ protToMask(di->protection()));
+ }
+ else // super classes
+ {
+ y = (baseRows-1)*(cellHeight+labelVertSpacing)-
+ labelVertSpacing/2+
+ di->yPos()*(cellHeight+labelVertSpacing)/gridHeight;
+ /* write output line */
+ image->drawVertLine(x,y,y+labelVertSpacing/2,
+ protToColor(di->protection()),
+ protToMask(di->protection()));
+ }
+ }
+ else // draw pixels
+ {
+ t << protToString(di->protection()) << endl;
+ if (doBase)
+ {
+ t << "1 " << di->xPos()/(float)gridWidth << " "
+ << di->yPos()/(float)gridHeight+superRows-1 << " in\n";
+ }
+ else
+ {
+ t << "0 " << di->xPos()/(float)gridWidth << " "
+ << (float)superRows-0.25-di->yPos()/(float)gridHeight
+ << " in\n";
+ }
+ }
+ }
+ if (dil->count()>0)
+ {
+ Protection p=getMinProtectionLevel(dil);
+ uint mask=protToMask(p);
+ uint col=protToColor(p);
+ if (bitmap)
+ {
+ x = di->xPos()*(cellWidth+labelHorSpacing)/gridWidth + cellWidth/2;
+ if (doBase) // base classes
+ {
+ y = image->getHeight()-
+ (superRows-1)*(cellHeight+labelVertSpacing)-
+ cellHeight-labelVertSpacing/2-
+ di->yPos()*(cellHeight+labelVertSpacing)/gridHeight;
+ image->drawVertLine(x,y,y+labelVertSpacing/2-1,col,mask);
+ }
+ else // super classes
+ {
+ y = (baseRows-1)*(cellHeight+labelVertSpacing)+
+ cellHeight+
+ di->yPos()*(cellHeight+labelVertSpacing)/gridHeight;
+ image->drawVertArrow(x,y,y+labelVertSpacing/2-1,col,mask);
+ }
+ }
+ else
+ {
+ t << protToString(p) << endl;
+ if (doBase)
+ {
+ t << "0 " << di->xPos()/(float)gridWidth << " "
+ << di->yPos()/(float)gridHeight+superRows-1 << " out\n";
+ }
+ else
+ {
+ t << "1 " << di->xPos()/(float)gridWidth << " "
+ << (float)superRows-1.75-di->yPos()/(float)gridHeight
+ << " out\n";
+ }
+ }
+ /* write input line */
+ DiagramItem *first = dil->first();
+ DiagramItem *last = dil->last();
+ if (first!=last && !first->isInList()) /* connect with all base classes */
+ {
+ if (bitmap)
+ {
+ int xs = first->xPos()*(cellWidth+labelHorSpacing)/gridWidth
+ + cellWidth/2;
+ int xe = last->xPos()*(cellWidth+labelHorSpacing)/gridWidth
+ + cellWidth/2;
+ if (doBase) // base classes
+ {
+ image->drawHorzLine(y,xs,xe,col,mask);
+ }
+ else // super classes
+ {
+ image->drawHorzLine(y+labelVertSpacing/2,xs,xe,col,mask);
+ }
+ }
+ else
+ {
+ t << protToString(p) << endl;
+ if (doBase)
+ {
+ t << first->xPos()/(float)gridWidth << " "
+ << last->xPos()/(float)gridWidth << " "
+ << first->yPos()/(float)gridHeight+superRows-1
+ << " conn\n";
+ }
+ else
+ {
+ t << first->xPos()/(float)gridWidth << " "
+ << last->xPos()/(float)gridWidth << " "
+ << (float)superRows-first->yPos()/(float)gridHeight
+ << " conn\n";
+ }
+ }
+ }
+ }
+ di=dr->next();
+ }
+ dr=next();
+ }
+ }
+}
+
+ClassDiagram::ClassDiagram(ClassDef *root)
+{
+ base = new TreeDiagram(root,TRUE);
+ base->computeLayout();
+ super = new TreeDiagram(root,FALSE);
+ super->computeLayout();
+ DiagramItem *baseItem = base->first()->first();
+ DiagramItem *superItem = super->first()->first();
+ int xbase = baseItem->xPos();
+ int xsuper = superItem->xPos();
+ if (xbase>xsuper)
+ {
+ superItem->move(xbase-xsuper,0);
+ super->moveChildren(superItem,xbase-xsuper);
+ }
+ else if (xbase<xsuper)
+ {
+ baseItem->move(xsuper-xbase,0);
+ base->moveChildren(baseItem,xsuper-xbase);
+ }
+}
+
+ClassDiagram::~ClassDiagram()
+{
+ delete base;
+ delete super;
+}
+
+void ClassDiagram::writeFigure(QTextStream &output,const char *path,
+ const char *fileName)
+{
+ uint baseRows=base->computeRows();
+ uint superRows=super->computeRows();
+ uint baseMaxX, baseMaxLabelWidth, superMaxX, superMaxLabelWidth;
+ base->computeExtremes(&baseMaxLabelWidth,&baseMaxX);
+ super->computeExtremes(&superMaxLabelWidth,&superMaxX);
+
+ uint rows=baseRows+superRows-1;
+ uint cols=(QMAX(baseMaxX,superMaxX)+gridWidth*2-1)/gridWidth;
+
+ // Estimate the image aspect width and height in pixels.
+ uint estHeight = rows*40;
+ uint estWidth = cols*(20+QMAX(baseMaxLabelWidth,superMaxLabelWidth));
+ //printf("Estimated size %d x %d\n",estWidth,estHeight);
+
+ const float pageWidth = 14.0; // estimated page width in cm.
+ // Somewhat lower to deal with estimation
+ // errors.
+
+ // compute the image height in centimeters based on the estimates
+ float realHeight = QMIN(rows,12); // real height in cm
+ float realWidth = realHeight * estWidth/(float)estHeight;
+ if (realWidth>pageWidth) // assume that the page width is about 15 cm
+ {
+ realHeight*=pageWidth/realWidth;
+ realWidth=pageWidth;
+ }
+
+ output << "}\n"
+ "\\begin{figure}[H]\n"
+ "\\begin{center}\n"
+ "\\leavevmode\n";
+ output << "\\setlength{\\epsfysize}{" << realHeight << "cm}\n";
+ output << "\\epsfbox{" << fileName << ".eps}\n"
+ "\\end{center}\n"
+ "\\end{figure}\n";
+
+ //printf("writeFigure rows=%d cols=%d\n",rows,cols);
+
+ QFile f1((QString)path+"/"+fileName+".eps");
+ if (!f1.open(IO_WriteOnly))
+ {
+ err("Could not open file %s for writing\n",f1.name());
+ exit(1);
+ }
+ QTextStream t(&f1);
+
+ //printf("writeEPS() rows=%d cols=%d\n",rows,cols);
+
+ // generate EPS header and postscipt variables and procedures
+
+ t << "%!PS-Adobe-2.0 EPSF-2.0\n";
+ t << "%%Title: ClassName\n";
+ t << "%%Creator: Doxygen\n";
+ t << "%%CreationDate: Time\n";
+ t << "%%For: \n";
+ t << "%Magnification: 1.00\n";
+ t << "%%Orientation: Portrait\n";
+ t << "%%BoundingBox: 0 0 500 " << estHeight*500.0/(float)estWidth << "\n";
+ t << "%%Pages: 0\n";
+ t << "%%BeginSetup\n";
+ t << "%%EndSetup\n";
+ t << "%%EndComments\n";
+ t << "\n";
+ t << "% ----- variables -----\n";
+ t << "\n";
+ t << "/boxwidth 0 def\n";
+ t << "/boxheight 40 def\n";
+ t << "/fontheight 24 def\n";
+ t << "/marginwidth 10 def\n";
+ t << "/distx 20 def\n";
+ t << "/disty 40 def\n";
+ t << "/boundaspect " << estWidth/(float)estHeight << " def % aspect ratio of the BoundingBox (width/height)\n";
+ t << "/boundx 500 def\n";
+ t << "/boundy boundx boundaspect div def\n";
+ t << "/xspacing 0 def\n";
+ t << "/yspacing 0 def\n";
+ t << "/rows " << rows << " def\n";
+ t << "/cols " << cols << " def\n";
+ t << "/scalefactor 0 def\n";
+ t << "/boxfont /Times-Roman findfont fontheight scalefont def\n";
+ t << "\n";
+ t << "% ----- procedures -----\n";
+ t << "\n";
+ t << "/dotted { [1 4] 0 setdash } def\n";
+ t << "/dashed { [5] 0 setdash } def\n";
+ t << "/solid { [] 0 setdash } def\n";
+ t << "\n";
+ t << "/max % result = MAX(arg1,arg2)\n";
+ t << "{\n";
+ t << " /a exch def\n";
+ t << " /b exch def\n";
+ t << " a b gt {a} {b} ifelse\n";
+ t << "} def\n";
+ t << "\n";
+ t << "/xoffset % result = MAX(0,(scalefactor-(boxwidth*cols+distx*(cols-1)))/2)\n";
+ t << "{\n";
+ t << " 0 scalefactor boxwidth cols mul distx cols 1 sub mul add sub 2 div max\n";
+ t << "} def\n";
+ t << "\n";
+ t << "/cw % boxwidth = MAX(boxwidth, stringwidth(arg1))\n";
+ t << "{\n";
+ t << " /str exch def\n";
+ t << " /boxwidth boxwidth str stringwidth pop max def\n";
+ t << "} def\n";
+ t << "\n";
+ t << "/box % draws a box with text `arg1' at grid pos (arg2,arg3)\n";
+ t << "{ gsave\n";
+ t << " 2 setlinewidth\n";
+ t << " newpath\n";
+ t << " exch xspacing mul xoffset add\n";
+ t << " exch yspacing mul\n";
+ t << " moveto\n";
+ t << " boxwidth 0 rlineto \n";
+ t << " 0 boxheight rlineto \n";
+ t << " boxwidth neg 0 rlineto \n";
+ t << " 0 boxheight neg rlineto \n";
+ t << " closepath\n";
+ t << " dup stringwidth pop neg boxwidth add 2 div\n";
+ t << " boxheight fontheight 2 div sub 2 div\n";
+ t << " rmoveto show stroke\n";
+ t << " grestore\n";
+ t << "} def \n";
+ t << "\n";
+ t << "/mark\n";
+ t << "{ newpath\n";
+ t << " exch xspacing mul xoffset add boxwidth add\n";
+ t << " exch yspacing mul\n";
+ t << " moveto\n";
+ t << " 0 boxheight 4 div rlineto\n";
+ t << " boxheight neg 4 div boxheight neg 4 div rlineto\n";
+ t << " closepath\n";
+ t << " eofill\n";
+ t << " stroke\n";
+ t << "} def\n";
+ t << "\n";
+ t << "/arrow\n";
+ t << "{ newpath\n";
+ t << " moveto\n";
+ t << " 3 -8 rlineto\n";
+ t << " -6 0 rlineto\n";
+ t << " 3 8 rlineto\n";
+ t << " closepath\n";
+ t << " eofill\n";
+ t << " stroke\n";
+ t << "} def\n";
+ t << "\n";
+ t << "/out % draws an output connector for the block at (arg1,arg2)\n";
+ t << "{\n";
+ t << " newpath\n";
+ t << " exch xspacing mul xoffset add boxwidth 2 div add\n";
+ t << " exch yspacing mul boxheight add\n";
+ t << " /y exch def\n";
+ t << " /x exch def\n";
+ t << " x y moveto\n";
+ t << " 0 disty 2 div rlineto \n";
+ t << " stroke\n";
+ t << " 1 eq { x y disty 2 div add arrow } if\n";
+ t << "} def\n";
+ t << "\n";
+ t << "/in % draws an input connector for the block at (arg1,arg2)\n";
+ t << "{\n";
+ t << " newpath\n";
+ t << " exch xspacing mul xoffset add boxwidth 2 div add\n";
+ t << " exch yspacing mul disty 2 div sub\n";
+ t << " /y exch def\n";
+ t << " /x exch def\n";
+ t << " x y moveto\n";
+ t << " 0 disty 2 div rlineto\n";
+ t << " stroke\n";
+ t << " 1 eq { x y disty 2 div add arrow } if\n";
+ t << "} def\n";
+ t << "\n";
+ t << "/hedge\n";
+ t << "{\n";
+ t << " exch xspacing mul xoffset add boxwidth 2 div add\n";
+ t << " exch yspacing mul boxheight 2 div sub\n";
+ t << " /y exch def\n";
+ t << " /x exch def\n";
+ t << " newpath\n";
+ t << " x y moveto\n";
+ t << " boxwidth 2 div distx add 0 rlineto\n";
+ t << " stroke\n";
+ t << " 1 eq\n";
+ t << " { newpath x boxwidth 2 div distx add add y moveto\n";
+ t << " -8 3 rlineto\n";
+ t << " 0 -6 rlineto\n";
+ t << " 8 3 rlineto\n";
+ t << " closepath\n";
+ t << " eofill\n";
+ t << " stroke\n";
+ t << " } if\n";
+ t << "} def\n";
+ t << "\n";
+ t << "/vedge\n";
+ t << "{\n";
+ t << " /ye exch def\n";
+ t << " /ys exch def\n";
+ t << " /xs exch def\n";
+ t << " newpath\n";
+ t << " xs xspacing mul xoffset add boxwidth 2 div add dup\n";
+ t << " ys yspacing mul boxheight 2 div sub\n";
+ t << " moveto\n";
+ t << " ye yspacing mul boxheight 2 div sub\n";
+ t << " lineto\n";
+ t << " stroke\n";
+ t << "} def\n";
+ t << "\n";
+ t << "/conn % connections the blocks from col `arg1' to `arg2' of row `arg3'\n";
+ t << "{\n";
+ t << " /ys exch def\n";
+ t << " /xe exch def\n";
+ t << " /xs exch def\n";
+ t << " newpath\n";
+ t << " xs xspacing mul xoffset add boxwidth 2 div add\n";
+ t << " ys yspacing mul disty 2 div sub\n";
+ t << " moveto\n";
+ t << " xspacing xe xs sub mul 0\n";
+ t << " rlineto\n";
+ t << " stroke\n";
+ t << "} def\n";
+ t << "\n";
+ t << "% ----- main ------\n";
+ t << "\n";
+ t << "boxfont setfont\n";
+ t << "1 boundaspect scale\n";
+
+
+ bool done=FALSE;
+ DiagramRow *dr=base->first();
+ while (dr && !done)
+ {
+ DiagramItem *di=dr->first();
+ while (di)
+ {
+ done=di->isInList();
+ t << "(" << di->label() << ") cw\n";
+ di=dr->next();
+ }
+ dr=base->next();
+ }
+ dr=super->first();
+ dr=super->next();
+ done=FALSE;
+ while (dr && !done)
+ {
+ DiagramItem *di=dr->first();
+ while (di)
+ {
+ done=di->isInList();
+ t << "(" << di->label() << ") cw\n";
+ di=dr->next();
+ }
+ dr=super->next();
+ }
+
+ t << "/boxwidth boxwidth marginwidth 2 mul add def\n"
+ << "/xspacing boxwidth distx add def\n"
+ << "/yspacing boxheight disty add def\n"
+ << "/scalefactor \n"
+ << " boxwidth cols mul distx cols 1 sub mul add\n"
+ << " boxheight rows mul disty rows 1 sub mul add boundaspect mul \n"
+ << " max def\n"
+ << "boundx scalefactor div boundy scalefactor div scale\n";
+
+ t << "\n% ----- classes -----\n\n";
+ base->drawBoxes(t,0,TRUE,FALSE,baseRows,superRows,0,0);
+ super->drawBoxes(t,0,FALSE,FALSE,baseRows,superRows,0,0);
+
+ t << "\n% ----- relations -----\n\n";
+ base->drawConnectors(t,0,TRUE,FALSE,baseRows,superRows,0,0);
+ super->drawConnectors(t,0,FALSE,FALSE,baseRows,superRows,0,0);
+}
+
+
+void ClassDiagram::writeImageMap(QTextStream &t,const char *path,
+ const char *fileName)
+{
+ uint baseRows=base->computeRows();
+ uint superRows=super->computeRows();
+ uint rows=baseRows+superRows-1;
+
+// t << "<p>Class diagram for ";
+// HtmlGenerator::docifyStatic(t,name);
+// t << ".\n<p><center><img src=\""
+// << fileName << ".gif\" usemap=\"#" << name << "_map\""
+// << " border=\"0\"></center>" << endl
+// << "<map name=\"" << name << "_map\"><p>" << endl;
+
+ uint lb,ls,xb,xs;
+ base->computeExtremes(&lb,&xb);
+ super->computeExtremes(&ls,&xs);
+
+ uint cellWidth = QMAX(lb,ls)+labelHorMargin*2;
+ uint maxXPos = QMAX(xb,xs);
+ uint labelVertMargin = 6; //QMAX(6,(cellWidth-fontHeight)/6); // aspect at least 1:3
+ uint cellHeight = labelVertMargin*2+fontHeight;
+ uint imageWidth = (maxXPos+gridWidth)*cellWidth/gridWidth+
+ (maxXPos*labelHorSpacing)/gridWidth;
+ uint imageHeight = rows*cellHeight+(rows-1)*labelVertSpacing;
+
+ Image image(imageWidth,imageHeight);
+
+ base->drawBoxes(t,&image,TRUE,TRUE,baseRows,superRows,cellWidth,cellHeight);
+ super->drawBoxes(t,&image,FALSE,TRUE,baseRows,superRows,cellWidth,cellHeight);
+ base->drawConnectors(t,&image,TRUE,TRUE,baseRows,superRows,cellWidth,cellHeight);
+ super->drawConnectors(t,&image,FALSE,TRUE,baseRows,superRows,cellWidth,cellHeight);
+
+ image.save((QString)path+"/"+fileName+".gif");
+
+ t << "</MAP></P>" << endl;
+}
+
diff --git a/src/diagram.h b/src/diagram.h
new file mode 100644
index 0000000..5bc30f8
--- /dev/null
+++ b/src/diagram.h
@@ -0,0 +1,128 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#include "entry.h"
+
+class ClassDef;
+class DiagramRow;
+class TreeDiagram;
+class ClassDiagram;
+class DiagramItemList;
+class Image;
+
+class DiagramItem
+{
+ public:
+ DiagramItem(DiagramItem *p,int number,ClassDef *cd,
+ Protection prot,Specifier virt,const char *ts);
+ ~DiagramItem();
+ QString label() const;
+ QString fileName() const;
+ DiagramItem *parentItem() { return parent; }
+ DiagramItemList *getChildren() { return children; }
+ void move(int dx,int dy) { x+=dx; y+=dy; }
+ int xPos() const { return x; }
+ int yPos() const { return y; }
+ int avgChildPos() const;
+ int numChildren() const;
+ void addChild(DiagramItem *di);
+ int number() const { return num; }
+ Protection protection() const { return prot; }
+ Specifier virtualness() const { return virt; }
+ void putInList() { inList=TRUE; }
+ bool isInList() const { return inList; }
+ ClassDef *getClassDef() const { return classDef; }
+ private:
+ DiagramItemList *children;
+ DiagramItem *parent;
+ int x,y;
+ int num;
+ Protection prot;
+ Specifier virt;
+ QString templSpec;
+ bool inList;
+ ClassDef *classDef;
+};
+
+class DiagramItemList : public QList<DiagramItem>
+{
+ public:
+ DiagramItemList() : QList<DiagramItem>() {}
+ ~DiagramItemList() {}
+};
+
+class DiagramRow : public QList<DiagramItem>
+{
+ public:
+ DiagramRow(TreeDiagram *d,int l) : QList<DiagramItem>()
+ {
+ diagram=d;
+ level=l;
+ setAutoDelete(TRUE);
+ }
+ void insertClass(DiagramItem *parent,ClassDef *cd,bool doBases,
+ Protection prot,Specifier virt,const char *ts);
+ uint number() { return level; }
+ private:
+ TreeDiagram *diagram;
+ uint level;
+};
+
+class DiagramRowIterator : public QListIterator<DiagramRow>
+{
+ public:
+ DiagramRowIterator(const QList<DiagramRow> &d)
+ : QListIterator<DiagramRow>(d) {}
+};
+
+class TreeDiagram : public QList<DiagramRow>
+{
+ public:
+ TreeDiagram(ClassDef *root,bool doBases);
+ ~TreeDiagram();
+ void computeLayout();
+ uint computeRows();
+ //uint computeCols();
+ void moveChildren(DiagramItem *root,int dx);
+ void computeExtremes(uint *labelWidth,uint *xpos);
+ void drawBoxes(QTextStream &t,Image *image,
+ bool doBase,bool bitmap,
+ uint baseRows,uint superRows,
+ uint cellWidth,uint cellHeight);
+ void drawConnectors(QTextStream &t,Image *image,
+ bool doBase,bool bitmap,
+ uint baseRows,uint superRows,
+ uint cellWidth,uint cellheight);
+ private:
+ bool layoutTree(DiagramItem *root,int row);
+ TreeDiagram &operator=(const TreeDiagram &);
+ TreeDiagram(const TreeDiagram &);
+};
+
+class ClassDiagram
+{
+ public:
+ ClassDiagram(ClassDef *root);
+ ~ClassDiagram();
+ void writeFigure(QTextStream &t,const char *path,
+ const char *file);
+ void writeImageMap(QTextStream &t,const char *path,
+ const char *file);
+ private:
+ TreeDiagram *base;
+ TreeDiagram *super;
+};
diff --git a/src/doxygen.cpp b/src/doxygen.cpp
new file mode 100644
index 0000000..3d641ef
--- /dev/null
+++ b/src/doxygen.cpp
@@ -0,0 +1,3763 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#include <qstring.h>
+#include <qfileinf.h>
+#include <qfile.h>
+#include <qdir.h>
+#include <qdict.h>
+#include <qregexp.h>
+#include <qstrlist.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+
+#include "version.h"
+#include "doxygen.h"
+#include "scanner.h"
+#include "entry.h"
+#include "index.h"
+#include "logos.h"
+#include "instdox.h"
+#include "message.h"
+#include "code.h"
+#include "config.h"
+#include "util.h"
+#include "pre.h"
+#include "tag.h"
+
+#include "outputlist.h"
+#include "declinfo.h"
+#include "htmlgen.h"
+#include "latexgen.h"
+#include "mangen.h"
+#include "language.h"
+#include "debug.h"
+
+#if defined(_MSC_VER)
+#define popen _popen
+#endif
+
+
+// lists
+ClassList classList; // list of all documented classes
+NamespaceList namespaceList; // list of all namespaces
+PageList exampleList; // list of all example files
+PageList pageList; // list of all related documentation pages
+MemberNameList memberNameList; // list of class member + related functions
+MemberNameList functionNameList; // list of all unrelated functions
+FileNameList inputNameList; // list of all input files
+StringList inputFiles;
+FileList includeFiles;
+GroupList groupList; // list of all groups
+FormulaList formulaList; // list of all formulas
+
+// dictionaries
+PageDict pageDict(1009); // dictionary of all doc pages
+PageDict exampleDict(1009); // dictionary of all examples
+ClassDict classDict(1009); // dictionary of all documented classes
+NamespaceDict namespaceDict(257); // dictionary of all documented namespaces
+MemberNameDict memberNameDict(10007); // dictionary of all member names
+MemberNameDict functionNameDict(10007); // dictionary of all functions
+StringDict substituteDict(1009); // dictionary of class name substitutes
+SectionDict sectionDict(257); // dictionary of all page sections
+FileNameDict inputNameDict(1009); // dictionary of sections
+StringDict excludeNameDict(1009); // dictionary of sections
+FileNameDict includeNameDict(1009); // dictionary of include names
+FileNameDict exampleNameDict(1009); // dictionary of examples
+FileDict includeDict(1009); // dictionary of include files
+DefineDict defineDict(10007); // dictionary of all defines
+StringDict typedefDict(1009); // dictionary of all typedefs
+GroupDict groupDict(257); // dictionary of all groups
+FormulaDict formulaDict(1009); // dictionary of all formulas
+FormulaDict formulaNameDict(1009); // dictionary of the label name of all formulas
+
+OutputList *outputList; // list of output generating objects
+
+//bool unrelatedFunctionsUsed;
+
+//ClassDef unrelatedClass("nothing",ClassDef::Class);
+ // dummy class for unrelated functions
+
+int annotatedClasses;
+int hierarchyClasses;
+int documentedFunctions;
+int documentedMembers;
+int documentedFiles;
+int documentedGroups;
+int documentedNamespaces;
+
+QTextStream tagFile;
+
+void addMemberDocs(Entry *root,MemberDef *md, const char *funcDecl,
+ bool over_load);
+
+
+//----------------------------------------------------------------------
+// Returns the standard string that is generated when the \overload
+// command is used.
+
+const char *getOverloadDocs()
+{
+ return "This is an overloaded member function, "
+ "provided for convenience. It differs from the above "
+ "function only in what argument(s) it accepts.";
+}
+
+//----------------------------------------------------------------------------
+
+
+void buildGroupList(Entry *root)
+{
+ if (root->section==Entry::GROUPDOC_SEC && root->name.length()>0)
+ {
+ //printf("Found group %s title=`%s'\n",root->name.data(),root->type.data());
+
+ GroupDef *gd;
+
+ if ((gd=groupDict[root->name]))
+ {
+ warn("Warning: group %s already documented\n"
+ " skipping documentation in file %s at line %d\n",
+ root->name.data(),root->fileName.data(),root->startLine);
+ }
+ else
+ {
+ gd = new GroupDef(root->name,root->type);
+ gd->setBriefDescription(root->brief);
+ gd->setDocumentation(root->doc);
+ groupList.inSort(gd);
+ groupDict.insert(root->name,gd);
+ }
+ }
+ EntryListIterator eli(*root->sublist);
+ Entry *e;
+ for (;(e=eli.current());++eli)
+ {
+ buildGroupList(e);
+ }
+}
+
+//----------------------------------------------------------------------
+
+//void computeGroupRelations(Entry *root)
+//{
+// if (root->section==Entry::GROUPDOC_SEC && root->name.length()>0)
+// {
+// GroupDef *gd;
+//
+// if ((gd=groupDict[root->name]))
+// {
+// QListIterator<QString> sli(*root->groups);
+// QString *s;
+// for (;(s=sli.current());++sli)
+// {
+// GroupDef *pgd;
+// if (s->length()>0 && (pgd=groupDict[*s]))
+// {
+// pgd->addGroup(gd);
+// printf("Group %s: in group %s\n",gd->groupName(),s->data());
+// }
+// }
+// }
+// }
+// EntryListIterator eli(*root->sublist);
+// Entry *e;
+// for (;(e=eli.current());++eli)
+// {
+// computeGroupRelations(e);
+// }
+//}
+
+//----------------------------------------------------------------------
+
+void buildFileList(Entry *root)
+{
+ if (((root->section==Entry::FILEDOC_SEC) ||
+ ((root->section & Entry::FILE_MASK) && extractAllFlag)) &&
+ root->name.length()>0
+ )
+ {
+ bool ambig;
+ FileDef *fd=findFileDef(&inputNameDict,root->name,ambig);
+ if (fd && !ambig)
+ {
+ if ((root->doc.length()>0 && fd->documentation()) ||
+ (root->brief.length()>0 && fd->briefDescription()))
+ {
+ warn("Warning: file %s already documented\n"
+ " skipping documentation in file %s at line %d\n",
+ root->name.data(),root->fileName.data(),root->startLine);
+ }
+ else
+ {
+ fd->setDocumentation(root->doc);
+ fd->setBriefDescription(root->brief);
+ QListIterator<QString> sli(*root->groups);
+ QString *s;
+ for (;(s=sli.current());++sli)
+ {
+ GroupDef *gd=0;
+ if (s->length()>0 && (gd=groupDict[*s]))
+ {
+ gd->addFile(fd);
+ //printf("File %s: in group %s\n",fd->name().data(),s->data());
+ }
+ }
+ }
+ }
+ else
+ {
+ warn("Warning: the name `%s' supplied as "
+ "the second argument in the \\file statement in file "
+ "%s at line %d ",
+ root->name.data(),
+ root->fileName.data(),
+ root->startLine);
+ if (ambig) // name is ambigious
+ {
+ warn("matches the following input files:\n");
+ showFileDefMatches(&inputNameDict,root->name);
+ warn("Please use a more specific name by "
+ "including a (larger) part of the path!\n");
+ }
+ else // name is not an input file
+ warn("is not an input file\n");
+ }
+ }
+ EntryListIterator eli(*root->sublist);
+ Entry *e;
+ for (;(e=eli.current());++eli)
+ {
+ buildFileList(e);
+ }
+}
+
+void addIncludeFile(ClassDef *cd,FileDef *ifd,Entry *root)
+{
+ //printf(">>>>>> includeFile=%s\n",root->includeFile.data());
+
+ bool ambig;
+ FileDef *fd=0;
+ // see if we need to include a verbatim copy of the header file
+ if (!root->includeFile.isNull() &&
+ (fd=findFileDef(&inputNameDict,root->includeFile,ambig))==0
+ )
+ { // explicit request
+ warn("Warning: the name `%s' supplied as "
+ "the second argument in the \\class statement in file "
+ "%s at line %d ",
+ root->includeFile.data(),
+ root->fileName.data(),
+ root->startLine);
+ if (ambig) // name is ambigious
+ {
+ warn("matches the following input files:\n");
+ showFileDefMatches(&inputNameDict,root->includeFile);
+ warn("Please use a more specific name by "
+ "including a (larger) part of the path!\n");
+ }
+ else // name is not an input file
+ warn("is not an input file\n");
+ }
+ else if (root->includeFile.length()==0 &&
+ // see if the file extension makes sense
+ guessSection(root->includeFile)==Entry::HEADER_SEC)
+ { // implicit assumption
+ fd=ifd;
+ }
+
+ // if a file is found, we mark it for verbatim inclusion.
+ if (fd)
+ {
+ //printf("fd->name()=%s fd->absFilePath()=%s\n",fd->name().data(),
+ // fd->absFilePath().data());
+ // set include file definition
+ cd->setIncludeFile(fd);
+ // set include supplied name
+ cd->setIncludeName(root->includeName);
+ fd->setIncludeName((QString)cd->classFile()+"-include");
+ if (includeDict[fd->absFilePath()]==0) // include not inserted earlier
+ {
+ includeFiles.inSort(fd);
+ includeDict.insert(fd->absFilePath(),fd);
+ }
+ }
+}
+
+/*! Input is a scopeName, output is the scopename split into a
+ * namespace part (as large as possible) and a classname part.
+ */
+void extractNamespaceName(const QString &scopeName,
+ QString &className,QString &namespaceName)
+{
+ QString clName=scopeName.copy();
+ QString nsName;
+ if (clName.length()>0 && namespaceDict[clName])
+ { // the whole name is a namespace
+ namespaceName=clName.copy();
+ className.resize(0);
+ return;
+ }
+ int i,p=clName.length()-2;
+ while (p>=0 && (i=clName.findRev("::",p))!=-1)
+ // see if the first part is a namespace
+ {
+ if (i>0 && namespaceDict[clName.left(i)])
+ {
+ namespaceName=clName.left(i);
+ className=clName.right(clName.length()-i-2);
+ return;
+ }
+ p=i-2; // try a smaller piece of the scope
+ }
+ className=scopeName.copy();
+ namespaceName.resize(0);
+ return;
+}
+
+static bool addNamespace(Entry *root,ClassDef *cd)
+{
+ // see if this class is defined inside a namespace
+ if (root->section & Entry::COMPOUND_MASK)
+ {
+ Entry *e = root->parent;
+ while (e)
+ {
+ if (e->section==Entry::NAMESPACE_SEC)
+ {
+ NamespaceDef *nd=0;
+ if (!e->name.isEmpty() && (nd=namespaceDict[e->name]))
+ {
+ cd->setNamespace(nd);
+ nd->insertClass(cd);
+ return TRUE;
+ }
+ }
+ e=e->parent;
+ }
+ }
+ return FALSE;
+}
+
+//----------------------------------------------------------------------
+// build a list of all classes mentioned in the documentation
+// and all classes that have a documentation block before their definition.
+void buildClassList(Entry *root)
+{
+ if (
+ ((root->section & Entry::COMPOUNDDOC_MASK) ||
+ ((root->section & Entry::COMPOUND_MASK))) &&
+ root->name.length()>0
+ )
+ {
+ QString fullName=root->name.copy();
+ if (fullName.length()==0)
+ {
+ // this should not be called
+ warn("Warning: invalid class found in file %s at %d\n",
+ root->fileName.data(),root->startLine);
+ }
+ else
+ {
+ //QString className;
+ //QString namespaceName;
+ //extractNamespaceName(fullName,className,namespaceName);
+
+ //printf("Found class %s in %s at line %d\n",fullName.data(),
+ // root->fileName.data(),root->startLine);
+ // add class name substitution entry iff the class name is alterned by a
+ // define. This is needed to properly document Qt's template classes
+ // (although, it's quite general)
+ //if (resolveDefines(fullName)!=fullName)
+ //{
+ // substituteDict.insert(resolveDefines(fullName),new QString(fullName));
+ //}
+
+ bool ambig;
+ ClassDef *cd;
+ if ((cd=getClass(fullName)))
+ {
+ if (cd->templateArguments()==0)
+ {
+ //printf("existing ClassDef tempArgList=%p\n",root->tArgList);
+ cd->setTemplateArguments(root->tArgList);
+ }
+ if (root->doc.length()>0 || root->brief.length()>0) // block contains docs
+ {
+ if (cd->documentation()) // class already documented
+ {
+ warn("Warning: class %s already documented\n"
+ " skipping documentation in file %s at line %d\n",
+ fullName.data(),root->fileName.data(),root->startLine);
+ }
+ else // class not documented, use docs in block
+ {
+ cd->setDocumentation(root->doc);
+ cd->setBriefDescription(root->brief);
+ cd->setName(fullName); // change name to match docs
+ }
+ }
+ if (cd->includeFile()==0)
+ {
+ addIncludeFile(cd,
+ findFileDef(&inputNameDict,root->fileName,ambig),
+ root
+ );
+ }
+ addNamespace(root,cd);
+ }
+ else if (fullName[0]!='@' /* &&
+ (root->doc.length()>0 ||
+ root->brief.length()>0 ||
+ extractAllFlag
+ )*/
+ )
+ // new class
+ {
+ int sec=ClassDef::Class;
+ switch(root->section)
+ {
+ case Entry::UNION_SEC:
+ case Entry::UNIONDOC_SEC:
+ sec=ClassDef::Union; break;
+ case Entry::STRUCT_SEC:
+ case Entry::STRUCTDOC_SEC:
+ sec=ClassDef::Struct; break;
+ }
+ ClassDef *cd=new ClassDef(fullName,sec);
+ cd->setDocumentation(root->doc); // copy docs to definition
+ cd->setBriefDescription(root->brief);
+ //printf("new ClassDef tempArgList=%p\n",root->tArgList);
+ cd->setTemplateArguments(root->tArgList);
+ cd->setProtection(root->protection);
+
+ QListIterator<QString> sli(*root->groups);
+ QString *s;
+ for (;(s=sli.current());++sli)
+ {
+ GroupDef *gd=0;
+ if (s->length()>0 && (gd=groupDict[*s]))
+ {
+ gd->addClass(cd);
+ //printf("Compound %s: in group %s\n",cd->name().data(),s->data());
+ }
+ }
+
+ bool found=addNamespace(root,cd);
+
+ // file definition containing the class cd
+ FileDef *ifd=findFileDef(&inputNameDict,root->fileName,ambig);
+
+ addIncludeFile(cd,ifd,root);
+
+ // if the class is not in a namespace then we insert
+ // it in the file definition
+ if (!found && ifd) ifd->insertClass(cd);
+
+ // the empty string test is needed for extract all case
+ cd->setBriefDescription(root->brief);
+ cd->insertUsedFile(root->fileName);
+ // add class to the list
+ classList.inSort(cd);
+ //printf("ClassDict.insert(%s)\n",resolveDefines(fullName).data());
+ //classDict.insert(resolveDefines(fullName),cd);
+ classDict.insert(fullName,cd);
+ }
+ }
+ }
+ EntryListIterator eli(*root->sublist);
+ Entry *e;
+ for (;(e=eli.current());++eli)
+ {
+ buildClassList(e);
+ }
+}
+
+//----------------------------------------------------------------------
+// build a list of all namespaces mentioned in the documentation
+// and all namespaces that have a documentation block before their definition.
+void buildNamespaceList(Entry *root)
+{
+ if (
+ (root->section==Entry::NAMESPACE_SEC) ||
+ (root->section==Entry::NAMESPACEDOC_SEC) &&
+ root->name.length()>0
+ )
+ {
+ QString fullName=root->name.copy();
+ if (fullName.length()==0)
+ {
+ // this should not be called
+ warn("Warning: invalid namespace found in file %s at %d\n",
+ root->fileName.data(),root->startLine);
+ }
+ else
+ {
+ //printf("Found namespace %s in %s at line %d\n",root->name.data(),
+ // root->fileName.data(), root->startLine);
+ NamespaceDef *nd;
+ if ((nd=namespaceDict[fullName]))
+ {
+ if (root->doc.length()>0 || root->brief.length()>0) // block contains docs
+ {
+ if (nd->documentation().isEmpty() && root->doc.length()>0)
+ {
+ nd->setDocumentation(root->doc);
+ nd->setName(fullName); // change name to match docs
+ }
+ else if (!nd->documentation().isEmpty() && root->doc.length()>0)
+ {
+ warn("Warning: namespace %s already has a detailed description,\n"
+ " skipping documentation in file %s at line %d\n",
+ fullName.data(),root->fileName.data(),root->startLine);
+ }
+ if (nd->briefDescription().isEmpty() && root->brief.length()>0)
+ {
+ nd->setBriefDescription(root->brief);
+ nd->setName(fullName); // change name to match docs
+ }
+ else if (!nd->briefDescription().isEmpty() && root->brief.length()>0)
+ {
+ warn("Warning: namespace %s already has a brief description,\n"
+ " skipping documentation in file %s at line %d\n",
+ fullName.data(),root->fileName.data(),root->startLine);
+ }
+ }
+ }
+ else if (root->doc.length()>0 ||
+ root->brief.length()>0 ||
+ extractAllFlag
+ )
+ {
+ NamespaceDef *nd=new NamespaceDef(fullName);
+ nd->setDocumentation(root->doc); // copy docs to definition
+ nd->setBriefDescription(root->brief);
+
+ QListIterator<QString> sli(*root->groups);
+ QString *s;
+ for (;(s=sli.current());++sli)
+ {
+ GroupDef *gd=0;
+ if (s->length()>0 && (gd=groupDict[*s]))
+ gd->addNamespace(nd);
+ }
+
+ bool ambig;
+ // file definition containing the class cd
+ FileDef *fd=findFileDef(&inputNameDict,root->fileName,ambig);
+ // insert the namespace in the file definition
+ if (fd) fd->insertNamespace(nd);
+
+ // the empty string test is needed for extract all case
+ nd->setBriefDescription(root->brief);
+ nd->insertUsedFile(root->fileName);
+ // add class to the list
+ namespaceList.inSort(nd);
+ namespaceDict.insert(fullName,nd);
+ }
+ }
+ }
+ EntryListIterator eli(*root->sublist);
+ Entry *e;
+ for (;(e=eli.current());++eli)
+ {
+ buildNamespaceList(e);
+ }
+}
+
+
+//----------------------------------------------------------------------
+// Searches the Entry tree for Variable documentation sections.
+// If found they are stored in their class or in the global list.
+
+void buildVarList(Entry *root)
+{
+ QRegExp re("([^)]*)");
+ int i=-1;
+ if (root->name.length()>0 &&
+ root->type!="class" &&
+ (
+ (root->section==Entry::VARIABLE_SEC
+ ) ||
+ (root->section==Entry::FUNCTION_SEC && // function variable
+ !root->type.isNull() && root->type.find(re,0)!=-1 &&
+ root->type.find("operator")==-1 && root->type.find(")(")==-1
+ )
+ )
+ ) // documented variable
+ {
+ Debug::print(Debug::Variables,0,
+ "VARIABLE_SEC: \n"
+ " type=`%s' name=`%s' args=`%s'\n",
+ root->type.data(),
+ root->name.data(),
+ root->args.data()
+ );
+ //printf("root->parent->name=%s\n",root->parent->name.data());
+
+ if (root->type.isNull() && root->name.find("operator")==-1 &&
+ (root->name.find('*')!=-1 || root->name.find('&')!=-1))
+ {
+ // recover from parse error caused by redundant braces
+ root->type=root->name;
+ QRegExp re("[a-z_A-Z][a-z_A-Z0-9]*");
+ int i,l;
+ i=re.match(root->args,0,&l);
+ root->name=root->args.mid(i,l);
+ root->args=root->args.mid(i+l,
+ root->args.find(')',i+l)-i-l);
+ //printf("new: type=`%s' name=`%s' args=`%s'\n",
+ // root->type.data(),root->name.data(),root->args.data());
+ }
+ else
+ {
+ QRegExp re("([^)]*)");
+ i=root->type.find(re,0);
+ if (i!=-1) // function variable
+ {
+ root->type=root->type.left(root->type.length()-1);
+ root->args.prepend(")");
+ }
+ }
+
+ QString scope,name=root->name.copy();
+ bool stat=root->stat;
+ ClassDef *cd=0;
+ Entry *p = root->parent;
+ while ((p->section & Entry::COMPOUND_MASK))
+ {
+ if (p->name.length()>0 && p->name[0]!='@')
+ {
+ if (!scope.isEmpty()) scope.prepend("::");
+ scope.prepend(p->name);
+ }
+ p=p->parent;
+ }
+
+ //printf("scope=%s\n",scope.data());
+
+ int ni;
+ if ((ni=root->name.findRev("::"))!=-1)
+ {
+ if (scope.length()>0) scope+="::";
+ scope+=root->name.left(ni);
+ name=root->name.right(root->name.length()-ni-2);
+ stat=TRUE;
+ }
+
+ MemberDef::MemberType mtype;
+ QString type=root->type.stripWhiteSpace();
+ if (type=="@")
+ mtype=MemberDef::EnumValue;
+ else if (type.left(8)=="typedef ")
+ mtype=MemberDef::Typedef;
+ else if (type.left(7)=="friend ")
+ mtype=MemberDef::Friend;
+ else
+ mtype=MemberDef::Variable;
+
+ if (scope.length()>0 && name.length()>0 && (cd=getClass(scope)))
+ {
+
+ Debug::print(Debug::Variables,0,
+ " class variable:\n"
+ " %s' %s'::`%s' `%s' prot=`%d\n",
+ root->type.data(),
+ scope.data(),
+ name.data(),
+ root->args.data(),
+ root->protection
+ );
+ // add template names, if the class is a non-specialized template
+ //if (scope.find('<')==-1 && cd->templateArguments())
+ //{
+ // scope+=cd->getTemplateNameString();
+ //}
+ // generate member definition.
+ QString def;
+ if (root->type.length()>0)
+ {
+ if (mtype==MemberDef::Friend)
+ {
+ def=root->type+" "+name+root->args;
+ }
+ else
+ {
+ def=root->type+" "+scope+"::"+name+root->args;
+ }
+ }
+ else
+ {
+ def=scope+"::"+name+root->args;
+ }
+ if (def.left(7)=="static ") def=def.right(def.length()-7);
+
+ // see if the member is already found in the same scope
+ // (this may be the case for a static member that is initialized
+ // outside the class)
+ bool found=FALSE;
+ MemberName *mn=memberNameDict[name];
+ if (mn)
+ {
+ MemberDef *md=mn->first();
+ while (md)
+ {
+ if (md->memberClass()==cd) // member already in the scope
+ {
+ addMemberDocs(root,md,def,FALSE);
+ found=TRUE;
+ }
+ md=mn->next();
+ }
+ }
+ if (!found) // found a fresh variable
+ {
+ // new member variable, typedef or enum value
+ MemberDef *md=new MemberDef(root->type,name,root->args,0,
+ root->protection,Normal,stat,FALSE,
+ mtype,0,0);
+ md->setMemberClass(cd);
+ md->setDefFile(root->fileName);
+ md->setDefLine(root->startLine);
+ md->setDocumentation(root->doc);
+ md->setBriefDescription(root->brief);
+ md->setDefinition(def);
+
+ // add the member to the global list
+ if (mn)
+ {
+ //printf("Member already found! %s\n",md->name());
+ //addMemberDocs(root,mn->first(),def,FALSE);
+ //delete md;
+ mn->inSort(md);
+ }
+ else // new variable name
+ {
+ mn = new MemberName(name);
+ mn->inSort(md);
+ //printf("Adding memberName=%s\n",mn->memberName());
+ memberNameDict.insert(name,mn);
+ memberNameList.inSort(mn);
+ // add the member to the class
+ }
+ cd->insertMember(md);
+
+ //TODO: insert FileDef instead of filename strings.
+ cd->insertUsedFile(root->fileName);
+ }
+ }
+ else if (name.length()>0) // global variable
+ {
+ Debug::print(Debug::Variables,0,
+ " global variable:\n"
+ " type=`%s' scope=`%s' name=`%s' args=`%s' prot=`%d\n",
+ root->type.data(),
+ scope.data(),
+ name.data(),
+ root->args.data(),
+ root->protection
+ );
+
+ // new global variable, enum value or typedef
+ MemberDef *md=new MemberDef(root->type,name,root->args,0,
+ Public, Normal,root->stat,FALSE,
+ mtype,0,0);
+ md->setDefFile(root->fileName);
+ md->setDefLine(root->startLine);
+ md->setDocumentation(root->doc);
+ md->setBriefDescription(root->brief);
+ QString def;
+
+ // see if the function is inside a namespace
+ NamespaceDef *nd = 0;
+ if (root->parent->section == Entry::NAMESPACE_SEC )
+ {
+ nd = namespaceDict[root->parent->name];
+ }
+ if (nd)
+ {
+ nd->insertMember(md);
+ md->setNamespace(nd);
+ }
+ else
+ {
+ // find file definition
+ FileDef *fd=0;
+ bool ambig;
+ if (root->fileName.length()>0 &&
+ (fd=findFileDef(&inputNameDict,root->fileName,ambig))
+ )
+ {
+ fd->insertMember(md);
+ md->setFileDef(fd);
+ }
+ }
+
+ // determine the definition of the global variable
+ if (nd) // variable is inside a namespace, so put the scope
+ // before the name
+ {
+ if (root->type.length()>0)
+ {
+ def=root->type+" "+nd->name()+"::"+name+root->args;
+ }
+ else
+ {
+ def=nd->name()+"::"+name+root->args;
+ }
+ }
+ else
+ {
+ if (root->type.length()>0)
+ {
+ def=root->type+" "+name+root->args;
+ }
+ else
+ {
+ def=name+root->args;
+ }
+ }
+ if (def.left(7)=="static ") def=def.right(def.length()-7);
+ md->setDefinition(def);
+
+ MemberName *mn;
+ // add member definition to the list of globals
+ if ((mn=functionNameDict[name]))
+ {
+ mn->inSort(md);
+ }
+ else
+ {
+ mn = new MemberName(name);
+ mn->inSort(md);
+ functionNameDict.insert(name,mn);
+ functionNameList.inSort(mn);
+ }
+ }
+ }
+ EntryListIterator eli(*root->sublist);
+ Entry *e;
+ for (;(e=eli.current());++eli)
+ {
+ if (e->section!=Entry::ENUM_SEC) buildVarList(e);
+ }
+}
+
+//----------------------------------------------------------------------
+// Searches the Entry tree for Function sections.
+// If found they are stored in their class or in the global list.
+
+void buildMemberList(Entry *root)
+{
+ if (root->section==Entry::FUNCTION_SEC)
+ {
+ Debug::print(Debug::Functions,0,
+ "FUNCTION_SEC:\n"
+ " `%s' `%s'::`%s' `%s' relates=`%s' file=`%s' #targs=%d\n",
+ root->type.data(),
+ root->parent->name.data(),
+ root->name.data(),
+ root->args.data(),
+ root->relates.data(),
+ root->fileName.data(),
+ root->tArgList ? (int)root->tArgList->count() : -1
+ );
+
+ bool isFriend=root->type.find("friend ")!=-1;
+ //if (isFriend && root->relates.length()==0)
+ // root->relates=root->parent->name.copy();
+ if (root->name.length()>0 /* && !isFriend */)
+ {
+
+ ClassDef *cd=0;
+ // check if this function's parent is a class
+ QRegExp re("([a-zA-Z0-9: ]*[ *]*[ ]*");
+ //printf("root->parent=`%s' cd=%p root->type.find(re,0)=%d\n",
+ // root->parent->name.data(),getClass(root->parent->name),
+ // root->type.find(re,0));
+ int i;
+ if (root->parent &&
+ root->parent->name.length()>0 &&
+ (root->parent->section & Entry::COMPOUND_MASK) &&
+ (cd=getClass(root->parent->name)) &&
+ // do some fuzzy things to exclude function pointers
+ (root->type.isNull() || root->type.find(re,0)==-1 ||
+ root->type.find(")(")!=-1 || root->type.find("operator")!=-1
+ )
+ )
+ {
+ int l;
+ if ((i=re.match(root->type,0,&l))!=-1) // function variable
+ {
+ root->args+=root->type.right(root->type.length()-i-l);
+ root->type=root->type.left(i+l);
+ }
+
+ QString name=removeRedundantWhiteSpace(root->name);
+ if (name.left(2)=="::") name=name.right(name.length()-2);
+
+ MemberDef::MemberType mtype;
+ if (isFriend) mtype=MemberDef::Friend;
+ else if (root->sig) mtype=MemberDef::Signal;
+ else if (root->slot) mtype=MemberDef::Slot;
+ else mtype=MemberDef::Function;
+ // new member of function, signal or slot.
+ MemberDef *md=new MemberDef(root->type,name,root->args,root->exception,
+ root->protection,root->virt,root->stat,root->relates.length()>0,
+ mtype,root->tArgList,root->argList);
+ md->setMemberClass(cd);
+ md->setDefFile(root->fileName);
+ md->setDefLine(root->startLine);
+ md->setDocumentation(root->doc);
+ md->setBriefDescription(root->brief);
+ QString def;
+ if (root->relates.length()>0 || isFriend)
+ {
+ if (root->type.length()>0)
+ {
+ if (root->argList)
+ {
+ def=root->type+" "+name;
+ }
+ else
+ {
+ def=root->type+" "+name+root->args;
+ }
+ }
+ else
+ {
+ if (root->argList)
+ {
+ def=name;
+ }
+ else
+ {
+ def=name+root->args;
+ }
+ }
+ }
+ else
+ {
+ QString scope=root->parent->name.copy();
+ if (root->type.length()>0)
+ {
+ if (root->argList)
+ {
+ def=root->type+" "+scope+"::"+name;
+ }
+ else
+ {
+ def=root->type+" "+scope+"::"+name+root->args;
+ }
+ }
+ else
+ {
+ if (root->argList)
+ {
+ def=scope+"::"+name;
+ }
+ else
+ {
+ def=scope+"::"+name+root->args;
+ }
+ }
+ }
+ if (def.left(7)=="friend ") def=def.right(def.length()-7);
+ md->setDefinition(def);
+
+ Debug::print(Debug::Functions,0,
+ " Func Member:\n"
+ " `%s' `%s'::`%s' `%s' proto=%d\n"
+ " def=`%s'\n",
+ root->type.data(),
+ root->parent->name.data(),
+ root->name.data(),
+ root->args.data(),
+ root->proto,
+ def.data()
+ );
+
+ // add member to the global list of all members
+ MemberName *mn;
+ if ((mn=memberNameDict[name]))
+ {
+ mn->inSort(md);
+ }
+ else
+ {
+ mn = new MemberName(name);
+ mn->inSort(md);
+ //printf("Adding memberName=%s\n",mn->memberName());
+ memberNameDict.insert(name,mn);
+ memberNameList.inSort(mn);
+ }
+
+ // add member to the class cd
+ cd->insertMember(md);
+ // add file to list of used files
+ cd->insertUsedFile(root->fileName);
+ }
+ else if (root->parent &&
+ !(root->parent->section & Entry::COMPOUND_MASK) &&
+ root->name.find("::")==-1 &&
+ root->relates.length()==0 &&
+ root->type.left(7)!="extern ")
+ // no member => unrelated function
+ {
+ /* check the uniqueness of the function name in the file.
+ * A file could contain a function prototype and a function definition
+ * or even multiple function prototypes.
+ */
+ bool found=FALSE;
+ MemberName *mn;
+ //MemberDef *fmd;
+ if ((mn=functionNameDict[root->name]))
+ {
+ MemberDef *md=mn->first();
+ while (md && !found)
+ {
+ if (md->getFileDef() &&
+ md->getFileDef()->absFilePath()==root->fileName &&
+ /*matchArguments(md->argsString(),root->args)*/
+ matchArguments(md->argumentList(),root->argList)
+ )
+ {
+ // function already found in the same file, one is probably
+ // a prototype.
+ found=TRUE;
+ if (!md->documentation() && !root->doc.isEmpty())
+ {
+ md->setDocumentation(root->doc);
+ }
+ if (!md->briefDescription() && !root->brief.isEmpty())
+ {
+ md->setBriefDescription(root->brief);
+ }
+ }
+ md=mn->next();
+ }
+ }
+ if (!found) /* global function is unique with respect to the file */
+ {
+ //printf("New function type=`%s' name=`%s' args=`%s'\n",
+ // root->type.data(),root->name.data(),root->args.data());
+
+ // new global function
+ QString name=removeRedundantWhiteSpace(root->name);
+ MemberDef *md=new MemberDef(root->type,name,root->args,root->exception,
+ root->protection,root->virt,root->stat,FALSE,
+ MemberDef::Function,root->tArgList,root->argList);
+ md->setDefFile(root->fileName);
+ md->setDefLine(root->startLine);
+ md->setDocumentation(root->doc);
+ md->setBriefDescription(root->brief);
+ md->setPrototype(root->proto);
+ QString def;
+ if (root->type.length()>0)
+ {
+ if (root->argList)
+ {
+ def=root->type+" "+name;
+ }
+ else
+ {
+ def=root->type+" "+name+root->args;
+ }
+ }
+ else
+ {
+ if (root->argList)
+ {
+ def=name.copy();
+ }
+ else
+ {
+ def=name+root->args;
+ }
+ }
+ Debug::print(Debug::Functions,0,
+ " Global Function:\n"
+ " `%s' `%s'::`%s' `%s' proto=%d\n"
+ " def=`%s'\n",
+ root->type.data(),
+ root->parent->name.data(),
+ root->name.data(),
+ root->args.data(),
+ root->proto,
+ def.data()
+ );
+ md->setDefinition(def);
+
+ // see if the function is inside a namespace
+ NamespaceDef *nd = 0;
+ if (root->parent->section == Entry::NAMESPACE_SEC )
+ {
+ nd = namespaceDict[root->parent->name];
+ }
+ if (nd)
+ {
+ nd->insertMember(md);
+ md->setNamespace(nd);
+ }
+ else
+ {
+ // find file definition
+ FileDef *fd=0;
+ bool ambig;
+ if (root->fileName.length()>0 &&
+ (fd=findFileDef(&inputNameDict,root->fileName,ambig))
+ )
+ {
+ // add member to the file
+ fd->insertMember(md);
+ md->setFileDef(fd);
+ }
+ }
+
+ // add member to the list of file members
+ MemberName *mn;
+ if ((mn=functionNameDict[name]))
+ {
+ mn->inSort(md);
+ }
+ else
+ {
+ mn = new MemberName(name);
+ mn->inSort(md);
+ functionNameDict.insert(name,mn);
+ functionNameList.inSort(mn);
+ }
+ }
+ else
+ {
+ //printf("Function already found!\n");
+ }
+
+ //printf("unrelated function %d `%s' `%s' `%s'\n",
+ // root->parent->section,root->type.data(),root->name.data(),root->args.data());
+ }
+ }
+ else if (root->name.length()==0)
+ {
+ warn("Warning: Illegal member name found in file %s at line %d\n",
+ root->fileName.data(),root->startLine);
+ }
+ }
+ EntryListIterator eli(*root->sublist);
+ Entry *e;
+ for (;(e=eli.current());++eli)
+ {
+ buildMemberList(e);
+ }
+}
+
+//----------------------------------------------------------------------
+
+void findFriends()
+{
+ //printf("findFriends()\n");
+ MemberNameListIterator fnli(functionNameList);
+ MemberName *fn;
+ for (;(fn=fnli.current());++fnli) // for each global function name
+ {
+ //printf("Function name=`%s'\n",fn->memberName());
+ MemberName *mn;
+ if ((mn=memberNameDict[fn->memberName()]))
+ { // there are members with the same name
+ //printf("Function name is also a member name\n");
+ MemberNameIterator fni(*fn);
+ MemberDef *fmd;
+ for (;(fmd=fni.current());++fni) // for each function with that name
+ {
+ MemberNameIterator mni(*mn);
+ MemberDef *mmd;
+ for (;(mmd=mni.current());++mni) // for each member with that name
+ {
+ //printf("Checking for matching arguments
+ // mmd->isRelated()=%d mmd->isFriend()=%d mmd->isFunction()=%d\n",
+ // mmd->isRelated(),mmd->isFriend(),mmd->isFunction());
+ NamespaceDef *nd=mmd->getNamespace();
+ if ((mmd->isFriend() || (mmd->isRelated() && mmd->isFunction())) &&
+ matchArguments(mmd->argumentList(),
+ fmd->argumentList(),
+ mmd->memberClass()->name(),
+ nd ? nd->name().data() : 0
+ )
+ ) // if the member is related and the arguments match then the
+ // function is actually a friend.
+ {
+ //printf("Found friend function\n");
+ mergeArguments(mmd->argumentList(),fmd->argumentList());
+ if (fmd->documentation())
+ mmd->setDocumentation(fmd->documentation());
+ else if (mmd->documentation())
+ fmd->setDocumentation(mmd->documentation());
+ if (!mmd->briefDescription() && fmd->briefDescription())
+ mmd->setBriefDescription(fmd->briefDescription());
+ else if (mmd->briefDescription() && !fmd->briefDescription())
+ fmd->setBriefDescription(mmd->briefDescription());
+ }
+ }
+ }
+ }
+ }
+}
+
+//----------------------------------------------------------------------
+
+void transferFunctionDocumentation()
+{
+ //printf("transferFunctionDocumentation()\n");
+ MemberNameListIterator mnli(functionNameList);
+ MemberName *mn;
+ for (;(mn=mnli.current());++mnli)
+ {
+ MemberDef *md,*mdef=0,*mdec=0;
+ MemberNameIterator mni(*mn);
+ /* find a matching function declaration and definition for this function */
+ for (;(md=mni.current());++mni)
+ {
+ if (md->isPrototype()) mdec=md;
+ if (md->isFunction() && !md->isStatic() && !md->isPrototype()) mdef=md;
+ }
+ if (mdef && mdec &&
+ matchArguments(mdef->argumentList(),mdec->argumentList())
+ ) /* match found */
+ {
+ //printf("Found member %s: def in %s and dec in %s\n",
+ // mn->memberName(),mdef->getFileDef()->name(),mdec->getFileDef()->name());
+
+ /* copy documentation between function definition and declaration */
+ if (mdec->briefDescription())
+ {
+ mdef->setBriefDescription(mdec->briefDescription());
+ }
+ else if (mdef->briefDescription())
+ {
+ mdec->setBriefDescription(mdef->briefDescription());
+ }
+ if (mdef->documentation())
+ {
+ mdec->setDocumentation(mdef->documentation());
+ }
+ else if (mdec->documentation())
+ {
+ mdef->setDocumentation(mdec->documentation());
+ }
+ }
+ }
+}
+
+
+//----------------------------------------------------------------------
+// Computes the base and super classes for each class in the tree
+
+void computeClassRelations(Entry *root)
+{
+ if (
+ (
+ (
+ root->section & Entry::COMPOUND_MASK
+ )
+ ||
+ (
+ (root->section & Entry::COMPOUNDDOC_MASK) && root->extends->count()>0
+ )
+ )
+ &&
+ root->name.length()>0
+ )
+ {
+ ClassDef *cd;
+ if ((cd=getClass(root->name)))
+ {
+ //printf("Class %s %d\n",cd->name().data(),root->extends->count());
+ if (!cd->visited)
+ {
+ cd->visited=TRUE; // mark class as used (in case the are multiple classes
+ // with the same name!)
+ if (root->extends->count()>0) // there are base classes
+ {
+ QString scopePrefix;
+ Entry *p=root->parent;
+ // For nested classes the base class could also be nested!
+ // To find the correct scope, we try to prepend the scope to the base
+ // name, starting with the largest, most inner scope.
+ while (p->section&Entry::COMPOUND_MASK)
+ {
+ scopePrefix=p->name+"::";
+ QList<BaseInfo> *baseList=root->extends;
+ BaseInfo *bi=baseList->first();
+ while (bi) // for each base class
+ {
+ QString cName=scopePrefix+bi->name;
+ //printf("Base class %s\n",cName.data());
+ ClassDef *baseClass=getClass(cName);
+ if (baseClass) // base class is documented
+ {
+ //printf("Adding!\n");
+ // add base class to this class
+ cd->insertBaseClass(baseClass,bi->prot,bi->virt);
+ // add this class as super class to the base class
+ baseClass->insertSuperClass(cd,bi->prot,bi->virt);
+ }
+ //else // base class not documented
+ //{
+ // warn("Warning: Base class %s referred to in file %s at line %d is not "
+ // "documented\n",s->data(),root->fileName.data(),root->startLine);
+ //}
+ bi=baseList->next();
+ }
+ p=p->parent;
+ }
+ // The base class could ofcouse also be a non-nested class
+ QList<BaseInfo> *baseList=root->extends;
+ BaseInfo *bi=baseList->first();
+ while (bi) // for each base class
+ {
+ ClassDef *baseClass=getClass(bi->name);
+ //printf("baseClass %s of %s found (%s and %s)\n",
+ // bi->name.data(),
+ // root->name.data(),
+ // (bi->prot==Private)?"private":((bi->prot==Protected)?"protected":"public"),
+ // (bi->virt==Normal)?"normal":"virtual"
+ // );
+ int i;
+ QString templSpec,baseClassName=bi->name.copy();
+ if (!baseClass && (i=bi->name.find('<'))!=-1)
+ // base class has template specifiers
+ {
+ // TODO: here we should try to find the correct template specialization
+ // but for now, we only look for the unspecializated base class.
+ baseClassName=bi->name.left(i);
+ baseClass=getClass(baseClassName);
+ templSpec=bi->name.right(bi->name.length()-i);
+ }
+ if (baseClass) // base class is documented
+ {
+ // add base class to this class
+ cd->insertBaseClass(baseClass,bi->prot,bi->virt,templSpec);
+ // add this class as super class to the base class
+ baseClass->insertSuperClass(cd,bi->prot,bi->virt,templSpec);
+ }
+ else // base class not documented
+ {
+ //printf("Found undocumented base class %s\n",bi->name.data());
+ NamespaceDef *nd=cd->getNamespace();
+ if (nd && (baseClass=getClass(nd->name()+"::"+baseClassName)))
+ // class is defined inside namespace
+ {
+ // add base class to this class
+ cd->insertBaseClass(baseClass,bi->prot,bi->virt,templSpec);
+ // add this class as super class to the base class
+ baseClass->insertSuperClass(cd,bi->prot,bi->virt,templSpec);
+ }
+ else // undocumented base class
+ {
+ baseClass=new ClassDef(bi->name,Entry::CLASS_SEC);
+ // add base class to this class
+ cd->insertBaseClass(baseClass,bi->prot,bi->virt,templSpec);
+ // add this class as super class to the base class
+ baseClass->insertSuperClass(cd,bi->prot,bi->virt,templSpec);
+ // the undocumented base was found in this file
+ baseClass->insertUsedFile(root->fileName);
+ // add class to the list
+ classList.inSort(baseClass);
+ //printf("ClassDict.insert(%s)\n",resolveDefines(fullName).data());
+ //classDict.insert(resolveDefines(bi->name),baseClass);
+ classDict.insert(bi->name,baseClass);
+ }
+ }
+ bi=baseList->next();
+ }
+ }
+// else // class has no base classes
+// {
+// QString resName=resolveDefines(root->name);
+// int i;
+// // Check if this class is a template instance of another class.
+// // If this is the case, we act as if this class `inherits' from the
+// // template class.
+// if ((i=resName.find('<'))!=-1)
+// {
+// ClassDef *baseClass=getClass(resName.left(i));
+// if (baseClass)
+// {
+// // add base class to this class
+// cd->insertBaseClass(baseClass,Public,Normal);
+// // add this class as super class to the base class
+// baseClass->insertSuperClass(cd,Public,Normal);
+// }
+// }
+// }
+ } // else class is already found
+ }
+ else if (root->name.right(2)!="::")
+ {
+ if (root->name.length()>0 && root->name[0]!='@')
+ warn("Warning: Compound %s\n"
+ " defined in file %s at line %d\n"
+ " is not documented\n",
+ root->name.data(),root->fileName.data(),root->startLine);
+ }
+ }
+ EntryListIterator eli(*root->sublist);
+ Entry *e;
+ for (;(e=eli.current());++eli)
+ {
+ computeClassRelations(e);
+ }
+}
+
+//-----------------------------------------------------------------------
+// compute the references (anchors in HTML) for each member in the class
+
+void computeMemberReferences()
+{
+ ClassDef *cd=classList.first();
+ while (cd)
+ {
+ cd->computeAnchors();
+ cd=classList.next();
+ }
+}
+
+//-----------------------------------------------------------------------
+// compute the references (anchors in HTML) for each function in the file
+
+void computeFunctionReferences()
+{
+ FileName *fn=inputNameList.first();
+ while (fn)
+ {
+ FileDef *fd=fn->first();
+ while (fd)
+ {
+ fd->computeAnchors();
+ fd=fn->next();
+ }
+ fn=inputNameList.next();
+ }
+ NamespaceDef *nd=namespaceList.first();
+ while (nd)
+ {
+ nd->computeAnchors();
+ nd=namespaceList.next();
+ }
+}
+
+
+
+//----------------------------------------------------------------------
+// Copy the documentation in entry `root' to member definition `md' and
+// set the function declaration of the member to `funcDecl'. If the boolean
+// over_load is set the standard overload text is added.
+
+void addMemberDocs(Entry *root,MemberDef *md, const char *funcDecl,
+ bool over_load)
+{
+ //printf("addMemberDocs: `%s'::`%s' `%s' funcDecl=`%s'\n",
+ // root->parent->name.data(),md->name().data(),md->argsString(),funcDecl);
+ QString fDecl=funcDecl;
+ // strip extern specifier
+ if (fDecl.left(7)=="extern ") fDecl=fDecl.right(fDecl.length()-7);
+ md->setDefinition(fDecl);
+ ClassDef *cd=md->memberClass();
+ NamespaceDef *nd=md->getNamespace();
+ if (matchArguments(md->argumentList(),root->argList,
+ cd ? cd->name().data() : 0,
+ nd ? nd->name().data() : 0
+ )
+ ) mergeArguments(md->argumentList(),root->argList);
+ if (over_load) // the \overload keyword was used
+ {
+ QString doc=getOverloadDocs();
+ if (!root->doc.isNull())
+ {
+ doc+="<p>";
+ doc+=root->doc;
+ }
+ md->setDocumentation(doc);
+ }
+ else
+ {
+ // documentation outside a compound overrides the documentation inside it
+ if ( /* !md->isStatic() && !root->stat && do not replace doc of a static */
+ (
+ !md->documentation() || /* no docs yet */
+ (root->parent->name.isNull() && /* or overwrite prototype docs */
+ !root->proto && md->isPrototype() /* with member definition docs */
+ )
+ ) && root->doc.length()>0
+ )
+ {
+ md->setDocumentation(root->doc);
+ }
+
+ // brief descriptions inside a compound override the documentation
+ // outside it
+ if ( /* !md->isStatic() && !root->stat && do not replace doc of static */
+ (
+ !md->briefDescription() || /* no docs yet */
+ !root->parent->name.isNull() /* member of a class */
+ ) && root->brief.length()>0
+ )
+ {
+ md->setBriefDescription(root->brief);
+ }
+ }
+ md->setDefFile(root->fileName);
+ md->setDefLine(root->startLine);
+ if (cd) cd->insertUsedFile(root->fileName);
+}
+
+//----------------------------------------------------------------------
+// Adds the documentation contained in `root' to a global function
+// with name `name' and argument list `args' (for overloading) and
+// function declaration `decl' to the corresponding member definition.
+
+bool findUnrelatedFunction(Entry *root,
+ const QString &namespaceName,
+ const char *name,
+ const char *,
+ const char *decl)
+{
+ MemberName *mn=0;
+ QString n=name;
+ if (n.find("::")!=-1) return FALSE; // skip undefined class members
+ //printf("findUnrelatedFunction(%s)\n",name);
+ if (n.length()>0 && (mn=functionNameDict[n])) // function name defined
+ {
+ int count=0;
+ MemberDef *md=mn->first();
+ while (md)
+ {
+ NamespaceDef *nd=md->getNamespace();
+ QString nsName = nd ? nd->name().data() : "";
+ if (namespaceName.length()==0 ||
+ nsName==namespaceName)
+ {
+ //printf("Searching for match between %s and %s\n",
+ // argListToString(md->argumentList()).data(),
+ // argListToString(root->argList).data());
+ bool matching=
+ /*matchArguments(md->argsString(),args);*/
+ (md->argumentList()==0 && root->argList->count()==0) ||
+ matchArguments(md->argumentList(),root->argList,0,nsName);
+ if (matching) // add docs to the member
+ {
+ //printf("Match found\n");
+ addMemberDocs(root,md,decl,FALSE);
+ count++;
+ }
+ }
+ md=mn->next();
+ }
+ if (count==0) // more than one match (each member will get the same docs)!
+ {
+ warn("Warning: no matching members found for \n%s\n"
+ "in file %s at line %d\n",
+ decl,root->fileName.data(),root->startLine);
+ }
+#if 0
+ else if (count>1) // no match!
+ {
+ warn("Warning: multiple matching members for\n%s\n",decl);
+ if (mn->count()>0) // there is a member with that name
+ {
+ warn("Possible candidates are:\n");
+ MemberDef *md=mn->first();
+ while (md) // list all possible members with the same name
+ {
+ warn(" %s%s\n",md->name(),md->argsString());
+ md=mn->next();
+ }
+ }
+ }
+#endif
+ }
+ else // got docs for an undefined member!
+ {
+ warn("Warning: documented function `%s' in file %s at line %d "
+ "was not defined \n",decl,
+ root->fileName.data(),root->startLine);
+ }
+ return TRUE;
+}
+
+
+//----------------------------------------------------------------------
+// This function tries to find a member (in a documented class/file/namespace)
+// that corresponds to the function declaration given in `funcDecl'.
+//
+// The related field may be used to specify a related class name.
+// It is only used if the class name cannot be extracted from the function
+// declaration.
+//
+// The boolean overloaded is used to specify whether or not a standard
+// overload documentation line should be generated.
+
+void findMember(Entry *root,QString funcDecl,QString related,bool overloaded,
+ bool isFunc)
+{
+ Debug::print(Debug::FindMembers,0,
+ "findMember(root=%p,funcDecl=`%s',related=`%s',overload=%d,isFunc=%d)\n",
+ root,funcDecl.data(),related.data(),overloaded,isFunc
+ );
+
+ QString scopeName;
+ QString className;
+ QString namespaceName;
+ QString classTempList;
+ QString funcType;
+ QString funcName;
+ QString funcArgs;
+ QString funcTempList;
+ QString exceptions;
+ bool isRelated=FALSE;
+ bool isFriend=FALSE;
+
+ if (funcDecl.left(7)=="friend ") // treat friends as related members
+ {
+ funcDecl=funcDecl.right(funcDecl.length()-7);
+ isFriend=TRUE;
+ }
+
+ // delete any ; from the function declaration
+ int sep;
+ while ((sep=funcDecl.find(';'))!=-1)
+ {
+ funcDecl=(funcDecl.left(sep)+funcDecl.right(funcDecl.length()-sep-1)).stripWhiteSpace();
+ }
+
+ // make sure the first character is a space to simplify searching.
+ if (funcDecl.length()>0 && funcDecl[0]!=' ') funcDecl.prepend(" ");
+
+ // remove some superfluous spaces
+ funcDecl=substitute(
+ substitute(
+ substitute(funcDecl,"~ ","~"),
+ ":: ","::"
+ ),
+ " ::","::"
+ );
+
+ // extract information from the declarations
+ parseFuncDecl(funcDecl,scopeName,classTempList,funcType,funcName,
+ funcArgs,funcTempList,exceptions
+ );
+
+ // the class name can also be a namespace name, we decide this later.
+ // if a related class name is specified and the class name could
+ // not be derived from the function declaration, then use the
+ // related field.
+ //printf("scopeName=`%s' className=`%s'\n",scopeName.data(),className.data());
+ if (/*scopeName.isEmpty() &&*/ !related.isEmpty() && !isRelated)
+ {
+ isRelated=TRUE;
+ //scopeName=resolveDefines(related);
+ if (!scopeName.isEmpty() && scopeName!=related)
+ scopeName+="::"+related;
+ else
+ scopeName=related.copy();
+ }
+ else if (scopeName.isEmpty() && related.isEmpty() && root->parent &&
+ !root->parent->name.isNull())
+ {
+ Entry *p=root->parent;
+ while (p) // get full scope as class name
+ {
+ if (((p->section & Entry::COMPOUND_MASK) ||
+ p->section == Entry::NAMESPACE_SEC
+ ) && !p->name.isEmpty() && p->name[0]!='@'
+ )
+ {
+ if (!scopeName.isEmpty()) scopeName.prepend("::");
+ scopeName.prepend(p->name);
+ break; // stop here because the class name already contains
+ // the whole scope!
+ }
+ p=p->parent;
+ }
+ }
+
+ if (scopeName.length()>0 && scopeName.find('<')==-1 && classTempList.length()==0 )
+ { // class is a template, but no template name list found
+ ClassDef *cd=getClass(scopeName);
+ if (cd) // class exists
+ {
+ classTempList = cd->getTemplateNameString();
+ }
+ }
+
+ //printf("scopeName=`%s' className=`%s'\n",scopeName.data(),className.data());
+ // rebuild the function declaration (needed to get the scope right).
+ if (scopeName.length()>0 && !isRelated && !isFriend)
+ {
+ if (funcType.length()>0)
+ {
+ if (isFunc) // a function -> we use argList for the arguments
+ {
+ funcDecl=funcType+" "+scopeName+classTempList+"::"+funcName+funcTempList;
+ }
+ else
+ {
+ funcDecl=funcType+" "+scopeName+classTempList+"::"+funcName+funcArgs;
+ }
+ }
+ else
+ {
+ if (isFunc) // a function => we use argList for the arguments
+ {
+ funcDecl=scopeName+classTempList+"::"+funcName+funcTempList;
+ }
+ else // variable => add `argument' list
+ {
+ funcDecl=scopeName+classTempList+"::"+funcName+funcArgs;
+ }
+ }
+ }
+ else // build declaration without scope
+ {
+ if (funcType.length()>0) // but with a type
+ {
+ if (isFunc) // function => omit argument list
+ {
+ funcDecl=funcType+" "+funcName+funcTempList;
+ }
+ else // variable => add `argument' list
+ {
+ funcDecl=funcType+" "+funcName+funcArgs;
+ }
+ }
+ else // no type
+ {
+ if (isFunc)
+ {
+ funcDecl=funcName+funcTempList;
+ }
+ else
+ {
+ funcDecl=funcName+funcArgs;
+ }
+ }
+ }
+
+ QString fullFuncDecl=funcDecl.copy();
+ if (isFunc) fullFuncDecl+=argListToString(root->argList);
+
+ //printf("scopeName=`%s' className=`%s'\n",scopeName.data(),className.data());
+ // see if (part of) the scope name is a namespace name
+ extractNamespaceName(scopeName,className,namespaceName);
+ //printf("scopeName=`%s' className=`%s'\n",scopeName.data(),className.data());
+
+ // destructor => do backward class name substitution if needed
+ //if (funcName.length()>0 && funcName[0]=='~')
+ // funcName="~"+resolveDefines(className);
+ // constructor => do backward class name substitution if needed
+ //if (funcName==className) funcName=resolveDefines(className);
+ //if (funcDecl.left(7)=="inline ") funcDecl=funcDecl.right(funcDecl.length()-7);
+
+ Debug::print(Debug::FindMembers,0,
+ "findMember() Parse results:\n"
+ " namespaceName=`%s'\n"
+ " className=`%s`\n"
+ " classTempList=`%s'\n"
+ " funcType=`%s'\n"
+ " funcName=`%s'\n"
+ " funcArgs=`%s'\n"
+ " funcTempList=`%s'\n"
+ " funcDecl=`%s'\n"
+ " related=`%s'\n"
+ " exceptions=`%s'\n"
+ " isRelated=%d\n"
+ " isFiend=%d\n"
+ " isFunc=%d\n\n",
+ namespaceName.data(),className.data(),classTempList.data(),
+ funcType.data(),funcName.data(),funcArgs.data(),funcTempList.data(),
+ funcDecl.data(),related.data(),exceptions.data(),isRelated,isFriend,
+ isFunc
+ );
+
+ MemberName *mn;
+ if (funcName.length()>0) // function name is valid
+ {
+ if (!isRelated && (mn=memberNameDict[funcName])) // function name already found
+ {
+ if (className.length()>0) // class name is valid
+ {
+ int count=0;
+ MemberDef *md=mn->first();
+ while (md)
+ {
+ ClassDef *cd=md->memberClass();
+ //printf("Member %s member className=%s this className=%s\n",md->name().data(),cd->name().data(),className.data());
+ ClassDef *tcd=0;
+ if (classTempList.length()>0) // try to find the correct specialization
+ {
+ tcd=getClass(scopeName+classTempList);
+ if (!tcd) tcd=getClass(scopeName); // try general class
+ }
+ else
+ {
+ tcd=getClass(scopeName);
+ }
+ //printf("tcd=%p\n",tcd);
+ if (cd && tcd==cd)
+ {
+ //printf("Class %s\n",cd->name().data());
+ bool matching=
+ md->isVariable() || md->isTypedef() || // needed for function pointers
+ (md->argumentList()==0 && root->argList->count()==0) ||
+ matchArguments(md->argumentList(), root->argList,
+ className,namespaceName);
+ if (matching)
+ {
+ addMemberDocs(root,md,funcDecl,overloaded);
+ count++;
+ }
+ }
+ md=mn->next();
+ }
+ if (count==0)
+ warn("Warning: no matching member found for \n%s\n"
+ "in file %s at line %d\n",
+ fullFuncDecl.data(),root->fileName.data(),root->startLine);
+#if 0
+ else if (count>1)
+ {
+ warn("Warning: multiple matching members for\n%s\n",funcDecl.data());
+ int matchCount=0;
+ MemberDef *md=mn->first();
+ while (md)
+ {
+ if (md->memberClass() && className==md->memberClass()->name())
+ matchCount++;
+ md=mn->next();
+ }
+ if (matchCount>0)
+ {
+ warn("Possible candidates are:\n");
+ md=mn->first();
+ while (md)
+ {
+ ClassDef *cd=md->memberClass();
+ if (cd && className==cd->name())
+ warn(" %s::%s%s\n",md->memberClass()->name(),
+ md->name(),md->argsString());
+ md=mn->next();
+ }
+ }
+ }
+#endif
+ }
+ else if (overloaded) // check if the function belongs to only one class
+ {
+ // for unique overloaded member we allow the class to be
+ // omitted, this is to be Qt compatable. Using this should
+ // however be avoided, because it is error prone
+ MemberDef *md=mn->first();
+ ASSERT(md);
+ ClassDef *cd=md->memberClass();
+ ASSERT(cd);
+ QString className=cd->name().copy();
+ md=mn->next();
+ bool unique=TRUE;
+ while (md)
+ {
+ ClassDef *cd=md->memberClass();
+ if (className!=cd->name()) unique=FALSE;
+ md=mn->next();
+ }
+ if (unique)
+ {
+ MemberDef::MemberType mtype;
+ if (root->sig) mtype=MemberDef::Signal;
+ else if (root->slot) mtype=MemberDef::Slot;
+ else mtype=MemberDef::Function;
+
+ // new overloaded member function
+ MemberDef *md=new MemberDef(funcType,funcName,funcArgs,exceptions,
+ root->protection,root->virt,root->stat,TRUE,
+ mtype,root->tArgList,root->argList);
+ md->setMemberClass(cd);
+ md->setDefinition(funcDecl);
+ QString doc=getOverloadDocs();
+ doc+="<p>";
+ doc+=root->doc;
+ md->setDocumentation(doc);
+ //md->setDecFile(root->fileName);
+ //md->setDecLine(root->startLine);
+ md->setDefFile(root->fileName);
+ md->setDefLine(root->startLine);
+ md->setPrototype(root->proto);
+ mn->inSort(md);
+ cd->insertMember(md);
+ cd->insertUsedFile(root->fileName);
+ }
+ }
+ else // unrelated function with the same name as a member
+ {
+ if (!findUnrelatedFunction(root,namespaceName,funcName+funcTempList,funcArgs,funcDecl))
+ {
+ warn("Warning: Cannot determine class for function\n%s\n"
+ "in file %s at line %d\n",fullFuncDecl.data(),
+ root->fileName.data(),root->startLine);
+ }
+ }
+ }
+ else if (isRelated && related.length()>0)
+ {
+ if (className.isEmpty()) className=related.copy();
+ ClassDef *cd;
+ if ((cd=getClass(scopeName)))
+ {
+ bool newMember=TRUE; // assume we have a new member
+ bool newMemberName=FALSE;
+ if ((mn=memberNameDict[funcName])==0)
+ {
+ mn=new MemberName(funcName);
+ newMemberName=TRUE; // we create a new member name
+ }
+ else
+ {
+ MemberDef *rmd=mn->first();
+ while (rmd && newMember) // see if we got another member with matching arguments
+ {
+ newMember=newMember &&
+ !matchArguments(rmd->argumentList(),root->argList,className,namespaceName);
+ if (newMember) rmd=mn->next();
+ }
+ if (!newMember && rmd) // member already exists as rmd -> add docs
+ {
+ addMemberDocs(root,rmd,funcDecl,overloaded);
+ }
+ }
+ if (newMember) // need to create a new member
+ {
+ MemberDef::MemberType mtype;
+ if (root->sig)
+ mtype=MemberDef::Signal;
+ else if (root->slot)
+ mtype=MemberDef::Slot;
+ else
+ mtype=MemberDef::Function;
+
+ // new related (member) function
+ MemberDef *md=new MemberDef(funcType,funcName,funcArgs,exceptions,
+ root->protection,root->virt,root->stat,TRUE,
+ mtype,root->tArgList,root->argList);
+ //printf("Related member name=`%s' decl=`%s'\n",funcName.data(),funcDecl.data());
+ md->setMemberClass(cd);
+ md->setDefinition(funcDecl);
+ md->setDocumentation(root->doc);
+ md->setBriefDescription(root->brief);
+ md->setDefFile(root->fileName);
+ md->setDefLine(root->startLine);
+ md->setPrototype(root->proto);
+ mn->inSort(md);
+ cd->insertMember(md);
+ cd->insertUsedFile(root->fileName);
+ if (newMemberName)
+ {
+ //printf("Adding memberName=%s\n",mn->memberName());
+ memberNameList.inSort(mn);
+ memberNameDict.insert(funcName,mn);
+ }
+ }
+ }
+ else
+ {
+ warn("Warning: class `%s' for related function `%s' is not "
+ "documented\n", className.data(),funcName.data());
+ }
+ }
+ else // unrelated not overloaded member found
+ {
+ if (className.length()==0 &&
+ !findUnrelatedFunction(root,namespaceName,funcName+funcTempList,funcArgs,funcDecl))
+ {
+ warn("Warning: class for member %s (file %s at line %d) cannot "
+ "be found\n", funcName.data(),root->fileName.data(),
+ root->startLine);
+ }
+ }
+ }
+ else
+ {
+ // this should not be called
+ warn("Warning: member with no name found in %s at line %d\n",
+ root->fileName.data(),root->startLine);
+ }
+ return;
+}
+
+//----------------------------------------------------------------------
+// find the members corresponding to the different documentation blocks
+// that are extracted from the sources.
+
+void findMemberDocumentation(Entry *root)
+{
+ int i,l;
+ QRegExp re("([a-zA-Z0-9: ]*[ *]+[ ]*");
+ Debug::print(Debug::FindMembers,0,
+ "root->type=`%s' root->name=`%s' root->args=`%s'\n",
+ root->type.data(),root->name.data(),root->args.data()
+ );
+ bool isFunc=TRUE;
+ if ((i=re.match(root->type,0,&l))!=-1) // func variable/typedef to func ptr
+ {
+ root->args+=root->type.right(root->type.length()-i-l);
+ root->type=root->type.left(i+l);
+ isFunc=FALSE;
+ }
+ else if (root->name.find(re)!=-1 && root->name.find("operator")!=-1)
+ // func ptr entered with \fn, \var or \typedef
+ {
+ isFunc=FALSE;
+ }
+ else if ((root->type.isEmpty() && root->name.left(8)=="typedef ")
+ || root->args.find('(')==-1)
+ {
+ isFunc=FALSE;
+ }
+ //printf("Member %s isFunc=%d\n",root->name.data(),isFunc);
+ if (root->section==Entry::MEMBERDOC_SEC)
+ {
+ //printf("Documentation for inline member `%s' found args=`%s'\n",
+ // root->name.data(),root->args.data());
+ //if (root->relates.length()) printf(" Relates %s\n",root->relates.data());
+ findMember(root,root->name+root->args+root->exception,root->relates,FALSE,isFunc);
+ }
+ else if (root->section==Entry::OVERLOADDOC_SEC)
+ {
+ //printf("Overloaded member %s found\n",root->name.data());
+ findMember(root,root->name,root->relates,TRUE,isFunc);
+ }
+ else if (root->section==Entry::FUNCTION_SEC &&
+ (root->doc.length()>0 || root->brief.length()>0 || extractAllFlag))
+ {
+ //printf("Documentation for member `%s' found args=`%s' excp=`%s'\n",
+ // root->name.data(),root->args.data(),root->exception.data());
+ //if (root->relates.length()) printf(" Relates %s\n",root->relates.data());
+ //printf("Inside=%s\n Relates=%s\n",root->inside.data(),root->relates.data());
+ if (root->type.length()>0)
+ {
+ findMember(root,
+ root->type+" "+root->inside+root->name+root->args+root->exception,
+ root->relates,
+ FALSE,isFunc);
+ }
+ else
+ {
+ findMember(root,
+ root->inside+root->name+root->args+root->exception,
+ root->relates,
+ FALSE,isFunc);
+ }
+ }
+ else if (root->section==Entry::VARIABLEDOC_SEC)
+ {
+ //printf("Documentation for variable %s found\n",root->name.data());
+ //if (root->relates.length()>0) printf(" Relates %s\n",root->relates.data());
+ findMember(root,root->name,root->relates,FALSE,FALSE);
+ }
+ EntryListIterator eli(*root->sublist);
+ Entry *e;
+ for (;(e=eli.current());++eli)
+ {
+ if (e->section!=Entry::ENUM_SEC) findMemberDocumentation(e);
+ }
+}
+
+//----------------------------------------------------------------------
+// find and add the enumeration to their classes, namespaces or files
+
+void findEnums(Entry *root)
+{
+ if (root->section==Entry::ENUM_SEC)
+ // non anonymous enumeration
+ {
+ MemberDef *md=0;
+ ClassDef *cd=0;
+ FileDef *fd=0;
+ NamespaceDef *nd=0;
+ MemberNameDict *mnd=0;
+ MemberNameList *mnl=0;
+ bool isGlobal;
+ //printf("Found enum with name `%s'\n",root->name.data());
+ int i;
+
+ QString name;
+ if ((i=root->name.findRev("::"))!=-1) // scope is specified
+ {
+ QString scope=root->name.left(i); // extract scope
+ name=root->name.right(root->name.length()-i-2); // extract name
+ cd=getClass(scope);
+ if (!cd) nd=namespaceDict[scope];
+ }
+ else // no scope, check the scope in which the docs where found
+ {
+ if (( root->parent->section & Entry::COMPOUND_MASK )
+ && root->parent->name.length()>0
+ ) // found enum docs inside a compound
+ {
+ cd=getClass(root->parent->name);
+ }
+ name=root->name.copy();
+ }
+ if (cd && name.length()>0) // found a enum inside a compound
+ {
+ //printf("Enum `%s'::`%s'\n",cd->name(),name.data());
+ fd=0;
+ mnd=&memberNameDict;
+ mnl=&memberNameList;
+ isGlobal=FALSE;
+ }
+ else if (nd) // found enum inside namespace
+ {
+ mnd=&functionNameDict;
+ mnl=&functionNameList;
+ isGlobal=TRUE;
+ }
+ else // found a global enum
+ {
+ bool ambig;
+ fd=findFileDef(&inputNameDict,root->fileName,ambig);
+ mnd=&functionNameDict;
+ mnl=&functionNameList;
+ isGlobal=TRUE;
+ }
+ if (name.length()>0)
+ {
+ // new enum type
+ md = new MemberDef(0,name,0,0,root->protection,Normal,FALSE,FALSE,
+ MemberDef::Enumeration,0,0);
+ if (!isGlobal) md->setMemberClass(cd); else md->setFileDef(fd);
+ md->setDefFile(root->fileName);
+ md->setDefLine(root->startLine);
+ if (nd)
+ {
+ md->setDefinition(nd->name()+"::"+name);
+ nd->insertMember(md);
+ md->setNamespace(nd);
+ }
+ else if (isGlobal)
+ {
+ md->setDefinition(name);
+ fd->insertMember(md);
+ }
+ else if (cd)
+ {
+ md->setDefinition(cd->name()+"::"+name);
+ cd->insertMember(md);
+ cd->insertUsedFile(root->fileName);
+ }
+ md->setDocumentation(root->doc);
+ md->setBriefDescription(root->brief);
+
+ MemberName *mn;
+ if ((mn=(*mnd)[name]))
+ {
+ // this is used if the same enum is in multiple namespaces/classes
+ mn->inSort(md);
+ }
+ else // new enum name
+ {
+ mn = new MemberName(name);
+ mn->inSort(md);
+ mnd->insert(name,mn);
+ mnl->inSort(mn);
+ //printf("add %s to new memberName. Now %d members\n",
+ // name.data(),mn->count());
+ }
+
+ EntryListIterator eli(*root->sublist);
+ Entry *e;
+ for (;(e=eli.current());++eli)
+ {
+ MemberName *fmn=0;
+ if (e->name.length()>0 && (fmn=(*mnd)[e->name]))
+ // get list of members with the same name as the field
+ {
+ MemberDef *fmd=fmn->first();
+ while (fmd) // search for the class with the right name
+ {
+ if (nd)
+ {
+ NamespaceDef *fnd=fmd->getNamespace();
+ if (fnd==nd)
+ {
+ md->insertEnumField(fmd);
+ fmd->setEnumScope(md);
+ }
+ }
+ else if (isGlobal)
+ {
+ FileDef *ffd=fmd->getFileDef();
+ if (ffd==fd)
+ {
+ md->insertEnumField(fmd);
+ fmd->setEnumScope(md);
+ }
+ }
+ else
+ {
+ ClassDef *fcd=fmd->memberClass();
+ if (fcd==cd)
+ {
+ md->insertEnumField(fmd); // add field def to list
+ fmd->setEnumScope(md); // cross ref with enum name
+ }
+ }
+ fmd=fmn->next();
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ EntryListIterator eli(*root->sublist);
+ Entry *e;
+ for (;(e=eli.current());++eli)
+ {
+ findEnums(e);
+ }
+ }
+}
+
+//----------------------------------------------------------------------
+// find the documentation blocks for the enumerations
+
+void findEnumDocumentation(Entry *root)
+{
+ if (root->section==Entry::ENUMDOC_SEC
+ && root->name.length()>0
+ && root->name[0]!='@' // skip anonymous enums
+ )
+ {
+ //printf("Found docs for enum with name `%s'\n",root->name.data());
+ int i;
+ ClassDef *cd=0;
+ QString name;
+ if ((i=root->name.findRev("::"))!=-1) // scope is specified
+ {
+ QString scope=root->name.left(i); // extract scope
+ name=root->name.right(root->name.length()-i-2); // extract name
+ cd=getClass(scope);
+ //printf("Scope=`%s' Name=`%s'\n",scope.data(),name.data());
+ }
+ else // no scope, check the scope in which the docs where found
+ {
+ if (( root->parent->section & Entry::COMPOUND_MASK )
+ && root->parent->name.length()>0
+ ) // found enum docs inside a compound
+ {
+ cd=getClass(root->parent->name);
+ }
+ name=root->name.copy();
+ }
+ if (name.length()>0)
+ {
+ bool found=FALSE;
+ if (cd)
+ {
+ //printf("Enum: scope=`%s' name=`%s'\n",cd->name(),name.data());
+ QString className=cd->name().copy();
+ MemberName *mn=memberNameDict[name];
+ if (mn)
+ {
+ MemberDef *md=mn->first();
+ while (md && !found)
+ {
+ ClassDef *cd=md->memberClass();
+ if (cd && cd->name()==className)
+ {
+ // documentation outside a compound overrides the documentation inside it
+ if (!md->documentation() || root->parent->name.length()==0)
+ {
+ md->setDocumentation(root->doc);
+ }
+
+ // brief descriptions inside a compound override the documentation
+ // outside it
+ if (!md->briefDescription() || root->parent->name.length()>0)
+ {
+ md->setBriefDescription(root->brief);
+ }
+ found=TRUE;
+ }
+ md=mn->next();
+ }
+ }
+ else
+ {
+ //printf("MemberName %s not found!\n",name.data());
+ }
+ }
+ else // enum outside class
+ {
+ MemberDef *md;
+ MemberName *mn=functionNameDict[name];
+ if (mn && (md=mn->first()))
+ {
+ md->setDocumentation(root->doc);
+ md->setBriefDescription(root->brief);
+ found=TRUE;
+ }
+ }
+ if (!found)
+ {
+ warn("Warning: Documentation for undefined enum `%s' found at"
+ " line %d of file %s\n",name.data(),
+ root->startLine,root->fileName.data());
+ }
+ }
+ }
+ EntryListIterator eli(*root->sublist);
+ Entry *e;
+ for (;(e=eli.current());++eli)
+ {
+ findEnumDocumentation(e);
+ }
+}
+
+//----------------------------------------------------------------------
+// recursive function:
+// returns TRUE iff class definition `bcd' represents an (in)direct base
+// class of class definition `cd'.
+
+bool isBaseClass(ClassDef *bcd,ClassDef *cd)
+{
+ bool found=FALSE;
+ //printf("isBaseClass(cd=%s) looking for %s\n",cd->name().data(),bcd->name().data());
+ BaseClassListIterator bcli(*cd->baseClasses());
+ for ( ; bcli.current() && !found ; ++bcli)
+ {
+ ClassDef *ccd=bcli.current()->classDef;
+ //printf("isBaseClass() baseclass %s\n",ccd->name().data());
+ if (ccd==bcd)
+ found=TRUE;
+ else
+ found=isBaseClass(bcd,ccd);
+ }
+ return found;
+}
+
+//----------------------------------------------------------------------
+// computes the relation between all members. For each member `m'
+// the members that override the implementation of `m' are searched and
+// the member that `m' overrides is searched.
+
+void computeMemberRelations()
+{
+ MemberName *mn=memberNameList.first();
+ while (mn) // for each member name
+ {
+ MemberNameIterator mdi(*mn);
+ for ( ; mdi.current() ; ++mdi) // for each function with a specific name
+ {
+ MemberDef *md=mdi.current();
+ MemberNameIterator bmdi(*mn);
+ for ( ; bmdi.current() ; ++bmdi) // for each other function with that name
+ {
+ MemberDef *bmd=bmdi.current();
+ if (md!=bmd && bmd->memberClass() && md->memberClass() &&
+ isBaseClass(bmd->memberClass(),md->memberClass()))
+ {
+ //printf("Checking Base: %s\nWith normal : %s\n",bmd->definition(),md->definition());
+ if (/*matchArguments(bmd->argsString(),md->argsString())*/
+ matchArguments(bmd->argumentList(),md->argumentList())
+ )
+ {
+ //printf("Base: %s\nNorm: %s\n",bmd->definition(),md->definition());
+ ClassDef *bmcd = bmd->memberClass();
+ ClassDef *mcd = md->memberClass();
+ if (mcd && bmcd &&
+ (bmcd->protection()!=Private || extractPrivateFlag) &&
+ (bmcd->hasDocumentation() || !hideClassFlag) &&
+ (mcd->protection()!=Private || extractPrivateFlag) &&
+ (mcd->hasDocumentation() || !hideClassFlag)
+ )
+ {
+ md->setReimplements(bmd);
+ bmd->insertReimplementedBy(md);
+ }
+ }
+ }
+ }
+ }
+ mn=memberNameList.next();
+ }
+}
+
+//----------------------------------------------------------------------------
+// recusively merges the `all members' lists of class cd's base classes
+// with that of class `cd' itself.
+
+void mergeMembers(ClassDef *cd,BaseClassList *bcl)
+{
+ //if (mcd->flag==TRUE)
+ //{
+ // err("Error: Cyclic inhertance dependency found for class %s\n",mcd->name());
+ // return;
+ //}
+ //mcd->flag=TRUE;
+
+ BaseClassListIterator bcli(*bcl);
+ BaseClassDef *bcd;
+ for ( ; (bcd=bcli.current()) ; ++bcli )
+ {
+ ClassDef *bClass=bcd->classDef;
+ // merge the members of bClass with the onces from cd
+
+ mergeMembers(bClass,bClass->baseClasses());
+ // the all member list of the branch until bClass is now complete
+ // so we can merge it with cd
+
+ MemberNameInfoList *srcMnl = bClass->memberNameInfoList();
+ MemberNameInfoDict *dstMnd = cd->memberNameInfoDict();
+ MemberNameInfoList *dstMnl = cd->memberNameInfoList();
+
+ MemberNameInfoListIterator srcMnili(*srcMnl);
+ MemberNameInfo *srcMni;
+ for ( ; (srcMni=srcMnili.current()) ; ++srcMnili)
+ {
+ //printf("Base member name %s\n",srcMni->memberName());
+ MemberNameInfo *dstMni;
+ if ((dstMni=dstMnd->find(srcMni->memberName())))
+ // a member with that name is already in the class.
+ // the member may hide or reimplement the one in the super class
+ // or there may be another path to the base class that is already
+ // visited via another branch in the class hierarchy.
+ {
+ MemberNameInfoIterator srcMnii(*srcMni);
+ MemberInfo *srcMi;
+ for ( ; (srcMi=srcMnii.current()) ; ++srcMnii )
+ {
+ MemberDef *srcMd = srcMi->memberDef;
+ bool found=FALSE;
+ bool ambigue=FALSE;
+ MemberNameInfoIterator dstMnii(*dstMni);
+ MemberInfo *dstMi;
+ for ( ; (dstMi=dstMnii.current()) && !found; ++dstMnii )
+ {
+ MemberDef *dstMd = dstMi->memberDef;
+ if (srcMd!=dstMd) // different members
+ {
+ ClassDef *srcCd = srcMd->memberClass();
+ ClassDef *dstCd = dstMd->memberClass();
+ //printf("Is %s a base class of %s?\n",srcCd->name(),dstCd->name());
+ if (srcCd==dstCd || isBaseClass(srcCd,dstCd))
+ // member is in the same or a base class
+ {
+ found =
+ /*matchArguments(srcMd->argsString(),dstMd->argsString());*/
+ matchArguments(srcMd->argumentList(),dstMd->argumentList());
+ }
+ else // member is in a non base class => multiple inheritance
+ // using the same base class.
+ {
+ //printf("$$ Existing member %s %s add scope %s\n",
+ // dstMi->ambiguityResolutionScope.data(),
+ // dstMd->name().data(),
+ // dstMi->scopePath.left(dstMi->scopePath.find("::")+2).data());
+
+ QString scope=dstMi->scopePath.left(dstMi->scopePath.find("::")+2);
+ if (scope!=dstMi->ambiguityResolutionScope.left(scope.length()))
+ dstMi->ambiguityResolutionScope.prepend(scope);
+ ambigue=TRUE;
+ }
+ }
+ else // same members
+ {
+ // do not add if base class is virtual or
+ // if scope paths are equal
+ if ((srcMi->virt==Virtual && dstMi->virt==Virtual) ||
+ bClass->name()+"::"+srcMi->scopePath == dstMi->scopePath
+ ) found=TRUE;
+ else // member can be reached via multiple paths in the
+ // inheritance tree
+ {
+ //printf("$$ Existing member %s %s add scope %s\n",
+ // dstMi->ambiguityResolutionScope.data(),
+ // dstMd->name().data(),
+ // dstMi->scopePath.left(dstMi->scopePath.find("::")+2).data());
+
+ QString scope=dstMi->scopePath.left(dstMi->scopePath.find("::")+2);
+ if (scope!=dstMi->ambiguityResolutionScope.left(scope.length()))
+ dstMi->ambiguityResolutionScope.prepend(scope);
+ ambigue=TRUE;
+ }
+ }
+ }
+ if (!found && srcMd->protection()!=Private)
+ {
+ Specifier virt=srcMi->virt;
+ if (srcMi->virt==Normal && bcd->virt!=Normal) virt=bcd->virt;
+ MemberInfo *newMi = new MemberInfo(srcMd,bcd->prot,virt);
+ //if (srcMi->memberDef->memberClass()!=bClass)
+ newMi->scopePath=bClass->name()+"::"+srcMi->scopePath;
+ if (ambigue)
+ {
+ //printf("$$ New member %s %s add scope %s::\n",
+ // srcMi->ambiguityResolutionScope.data(),
+ // srcMd->name().data(),
+ // bClass->name().data());
+
+ QString scope=bClass->name().copy(); scope+="::";
+ if (scope!=srcMi->ambiguityResolutionScope.left(scope.length()))
+ newMi->ambiguityResolutionScope=
+ scope+srcMi->ambiguityResolutionScope;
+ }
+ dstMni->append(newMi);
+ }
+ }
+ }
+ else // base class has a member that is not in the super class => copy
+ {
+ // create a deep copy of the list (only the MemberInfo's will be
+ // copied, not the actual MemberDef's)
+ MemberNameInfo *newMni = new MemberNameInfo(srcMni->memberName());
+
+ // copy the member(s) from the base to the super class
+ MemberNameInfoIterator mnii(*srcMni);
+ MemberInfo *mi;
+ for (;(mi=mnii.current());++mnii)
+ {
+ if (mi->memberDef->protection()!=Private)
+ {
+ Specifier virt=mi->virt;
+ if (mi->virt==Normal && bcd->virt!=Normal) virt=bcd->virt;
+ MemberInfo *newMi=new MemberInfo(mi->memberDef,bcd->prot,virt);
+ //if (mi->memberDef->memberClass()!=bClass)
+ newMi->scopePath=bClass->name()+"::"+mi->scopePath;
+ newMi->ambiguityResolutionScope=mi->ambiguityResolutionScope.copy();
+ newMni->append(newMi);
+ }
+ }
+
+ // add it to the list and dictionary
+ dstMnl->inSort(newMni);
+ dstMnd->insert(newMni->memberName(),newMni);
+ }
+ }
+ }
+}
+
+//----------------------------------------------------------------------------
+// builds the list of all members for each class
+
+void buildCompleteMemberLists()
+{
+ ClassDef *cd;
+ ClassListIterator cli(classList);
+ for (;(cd=cli.current());++cli)
+ {
+ //if (!cd->isReference()) printf("Building member for class %s\n",cd->name());
+ //ClassListIterator vcli(classList);
+ //for (;(vcd=vcli.current());++vcli) vcd->flag = FALSE;
+ if (!cd->isReference() && // not an external class
+ cd->superClasses()->count()==0 && // is a root of the hierarchy
+ cd->baseClasses()->count()>0) // and has at least one base class
+ {
+ //printf("merging members for class %s\n",cd->name());
+ mergeMembers(cd,cd->baseClasses());
+ }
+ }
+}
+
+//----------------------------------------------------------------------------
+
+void generateFileDocs()
+{
+ if (documentedFiles==0) return;
+ writeFileIndex(*outputList);
+
+ if (inputNameList.count()>0)
+ {
+ FileName *fn=inputNameList.first();
+ while (fn)
+ {
+ FileDef *fd=fn->first();
+ while (fd)
+ {
+ if (!fd->isReference() && fd->hasDocumentation())
+ {
+ msg("Generating docs for file %s...\n",fd->name().data());
+ fd->writeDocumentation(*outputList);
+ }
+ fd=fn->next();
+ }
+ fn=inputNameList.next();
+ }
+ }
+}
+
+//----------------------------------------------------------------------------
+// generate the documentation of all classes
+
+void generateClassDocs()
+{
+ // write the installdox script if necessary
+ if (generateHtml && (tagFileList.count()>0 || searchEngineFlag))
+ writeInstallScript();
+
+ msg("Generating index page...\n");
+ writeIndex(*outputList);
+
+ msg("Generating compound index...\n");
+ writeAnnotatedIndex(*outputList);
+
+ msg("Generating hierarchical class index...\n");
+ writeHierarchicalIndex(*outputList);
+
+ if (includeFiles.count()>0)
+ {
+ msg("Generating header index...\n");
+ writeHeaderIndex(*outputList);
+ }
+
+ msg("Generating member index...\n");
+ writeMemberIndex(*outputList);
+
+ if (exampleList.count()>0)
+ {
+ msg("Generating example index...\n");
+ }
+
+ ClassListIterator cli(classList);
+ for ( ; cli.current() ; ++cli )
+ {
+ ClassDef *cd=cli.current();
+ if (!cd->isReference() &&
+ //!cd->name().isEmpty() &&
+ //cd->name().at(0)!='@' &&
+ //(cd->protection()!=Private || extractPrivateFlag) &&
+ //(cd->hasDocumentation() || !hideClassFlag)
+ cd->isVisible()
+ )
+ // skip external references and anonymous compounds
+ {
+ msg("Generating docs for compound %s...\n",cd->name().data());
+
+ cd->writeDocumentation(*outputList);
+ cd->writeMemberList(*outputList);
+ if (verbatimHeaderFlag) cd->writeIncludeFile(*outputList);
+ }
+ }
+}
+
+//----------------------------------------------------------------------------
+
+void findDefineDocumentation(Entry *root)
+{
+ if ((root->section==Entry::DEFINEDOC_SEC ||
+ root->section==Entry::DEFINE_SEC) && root->name.length()>0
+ )
+ {
+ //printf("found define `%s' `%s' brief=`%s' doc=`%s'\n",
+ // root->name.data(),root->args.data(),root->brief.data(),root->doc.data());
+ MemberName *mn=functionNameDict[root->name];
+ if (mn)
+ {
+ int count=0;
+ MemberDef *md=mn->first();
+ while (md)
+ {
+ if (md->memberType()==MemberDef::Define) count++;
+ md=mn->next();
+ }
+ if (count==1)
+ {
+ md=mn->first();
+ while (md)
+ {
+ if (md->memberType()==MemberDef::Define)
+ {
+ if (md->documentation().isEmpty())
+ md->setDocumentation(root->doc);
+ if (md->briefDescription().isEmpty())
+ md->setBriefDescription(root->brief);
+ }
+ md=mn->next();
+ }
+ }
+ else if (count>1 && (root->doc.length()>0 || root->brief.length()>0))
+ // multiple defines don't know where to add docs
+ {
+ md=mn->first();
+ while (md)
+ {
+ if (md->memberType()==MemberDef::Define)
+ {
+ FileDef *fd=md->getFileDef();
+ if (fd && fd->absFilePath()==root->fileName)
+ // doc and define in the same file assume they belong together.
+ {
+ if (md->documentation().isEmpty())
+ md->setDocumentation(root->doc);
+ if (md->briefDescription().isEmpty())
+ md->setBriefDescription(root->brief);
+ }
+ }
+ md=mn->next();
+ }
+ //warn("Warning: define %s found in the following files:\n",root->name.data());
+ //warn("Cannot determine where to add the documentation found "
+ // "at line %d of file %s. \n",
+ // root->startLine,root->fileName.data());
+ }
+ }
+ else // define not found
+ {
+ warn("Warning: documentation for unknown define %s found at line %d of "
+ "file %s\n",root->name.data(),root->startLine,root->fileName.data());
+ }
+ }
+ EntryListIterator eli(*root->sublist);
+ Entry *e;
+ for (;(e=eli.current());++eli)
+ {
+ findDefineDocumentation(e);
+ }
+}
+
+//----------------------------------------------------------------------------
+
+//----------------------------------------------------------------------------
+// create a (sorted) list of separate documentation pages
+
+void buildPageList(Entry *root)
+{
+ if (root->section == Entry::PAGEDOC_SEC)
+ {
+ if (root->name.length()>0)
+ {
+ PageInfo *pi=0;
+ if ((pi=pageDict[root->name]))
+ {
+ //warn("Warning: Page %s was already documented. Ignoring documentation "
+ // "at line %d of %s\n",root->name.data(),root->startLine,
+ // root->fileName.data());
+
+ // append documentation block to the page.
+ pi->doc+="\n\n"+root->doc;
+ }
+ else
+ {
+ QString baseName=root->name.copy();
+ if (baseName.right(4)==".tex")
+ baseName=baseName.left(baseName.length()-4);
+ else if (baseName.right(5)==".html")
+ baseName=baseName.left(baseName.length()-5);
+ pi=new PageInfo(baseName, root->doc,
+ root->args.stripWhiteSpace());
+ pageList.append(pi);
+ pageDict.insert(baseName,pi);
+ if (pi->title.length()>0)
+ {
+ QString pageName;
+ if (caseSensitiveNames)
+ pageName=pi->name.copy();
+ else
+ pageName=pi->name.lower();
+ //outputList->writeTitle(pi->name,pi->title);
+ SectionInfo *si=new SectionInfo(pageName+".html",
+ pi->name,pi->title,FALSE);
+ //printf("Adding section info %s\n",pi->name.data());
+ sectionDict.insert(pi->name,si);
+ }
+ }
+ }
+ }
+ EntryListIterator eli(*root->sublist);
+ Entry *e;
+ for (;(e=eli.current());++eli)
+ {
+ buildPageList(e);
+ }
+}
+
+//----------------------------------------------------------------------------
+// generate all separate documentation pages
+
+void generatePageDocs()
+{
+ PageInfo *pi=pageList.first();
+ while (pi)
+ {
+ if (!pi->title.isEmpty())
+ {
+ msg("Generating docs for page %s...\n",pi->title.data());
+ }
+ else
+ {
+ msg("Generating docs for page %s...\n",pi->name.data());
+ }
+ outputList->disable(OutputGenerator::Man);
+ QString pageName;
+ if (caseSensitiveNames)
+ pageName=pi->name.copy();
+ else
+ pageName=pi->name.lower();
+
+ startFile(*outputList,pageName,pi->title);
+ SectionInfo *si=0;
+ if (pi->title.length()>0 && pi->name.length()>0 &&
+ (si=sectionDict[pi->name])!=0)
+ {
+ outputList->writeSection(si->label,si->title,FALSE);
+ }
+ parseDoc(*outputList,0,0,pi->doc);
+ endFile(*outputList);
+ outputList->enable(OutputGenerator::Man);
+ pi=pageList.next();
+ }
+}
+
+//----------------------------------------------------------------------------
+// create a (sorted) list & dictionary of example pages
+
+void buildExampleList(Entry *root)
+{
+ if (root->section == Entry::EXAMPLE_SEC)
+ {
+ if (root->name.length()>0)
+ {
+ if (exampleDict[root->name])
+ {
+ warn("Warning: Example %s was already documented. Ignoring "
+ "documentation at line %d of %s\n",root->name.data(),
+ root->startLine,root->fileName.data());
+ }
+ else
+ {
+ PageInfo *pi=new PageInfo(root->name,root->doc,root->args);
+ exampleList.inSort(pi);
+ exampleDict.insert(root->name,pi);
+ }
+ }
+ }
+ //EntryList *entryList=root->sublist;
+ //Entry *e = entryList->first();
+ //while (e)
+ //{
+ // buildExampleList(e);
+ // e=entryList->next();
+ //}
+ EntryListIterator eli(*root->sublist);
+ Entry *e;
+ for (;(e=eli.current());++eli)
+ {
+ buildExampleList(e);
+ }
+}
+
+//----------------------------------------------------------------------------
+// generate the example documentation
+
+void generateExampleDocs()
+{
+ PageInfo *pi=exampleList.first();
+ while (pi)
+ {
+ msg("Generating docs for example %s...\n",pi->name.data());
+ QString n=convertSlashes(pi->name,TRUE)+"-example";
+ startFile(*outputList,n,"Example Documentation");
+ //outputList->writeTitle(pi->name,pi->name);
+ parseExample(*outputList,pi->doc+"\n\\include "+pi->name,pi->name);
+ endFile(*outputList);
+ pi=exampleList.next();
+ }
+}
+
+//----------------------------------------------------------------------------
+// generate module pages
+
+void generateGroupDocs()
+{
+ GroupListIterator gli(groupList);
+ GroupDef *gd;
+ for (;(gd=gli.current());++gli)
+ {
+ //printf("group %s #members=%d\n",gd->name().data(),gd->countMembers());
+ if (gd->countMembers()>0) gd->writeDocumentation(*outputList);
+ }
+}
+
+//----------------------------------------------------------------------------
+// generate module pages
+
+void generateNamespaceDocs()
+{
+ writeNamespaceIndex(*outputList);
+
+ NamespaceListIterator nli(namespaceList);
+ NamespaceDef *nd;
+ for (;(nd=nli.current());++nli)
+ {
+ msg("Generating docs for namespace %s\n",nd->name().data());
+ nd->writeDocumentation(*outputList);
+ }
+}
+
+//----------------------------------------------------------------------------
+// generate files for the search engine
+
+void generateSearchIndex()
+{
+ if (searchEngineFlag && generateHtml)
+ {
+ // create search index
+ QString fileName;
+ writeSearchButton(htmlOutputDir);
+
+ // create cgi script
+ fileName = htmlOutputDir+"/"+cgiName;
+ QFile f(fileName);
+ if (f.open(IO_WriteOnly))
+ {
+ QTextStream t(&f);
+ t << "#!/bin/sh" << endl
+ << "DOXYSEARCH=" << binAbsPath << "/doxysearch" << endl
+ << "DOXYPATH=" << docAbsPath << " ";
+
+ char *s=extDocPathList.first();
+ while (s)
+ {
+ t << s << " ";
+ s=extDocPathList.next();
+ }
+
+ t << endl
+ << "if [ -f $DOXYSEARCH ]" << endl
+ << "then" << endl
+ << " $DOXYSEARCH $DOXYPATH" << endl
+ << "else" << endl
+ << " echo \"Content-Type: text/html\"" << endl
+ << " echo \"\"" << endl
+ << " echo \"<H1>Error: $DOXYSEARCH not found. Check cgi script!\"" << endl
+ << "fi" << endl;
+
+ f.close();
+ struct stat stat_struct;
+ stat(fileName,&stat_struct);
+#if !defined(_WIN32)
+ chmod(fileName,stat_struct.st_mode|S_IXUSR|S_IXGRP|S_IXOTH);
+#endif
+ }
+ else
+ {
+ err("Error: Cannot open file %s for writing\n",fileName.data());
+ }
+
+ // create config file
+ fileName = htmlOutputDir+"/search.cfg";
+ f.setName(fileName);
+ if (f.open(IO_WriteOnly))
+ {
+ QTextStream t(&f);
+ t << docURL << endl << cgiURL << "/" << cgiName << endl;
+ f.close();
+ }
+ else
+ {
+ err("Error: Cannot open file %s for writing\n",fileName.data());
+ }
+ //outputList->generateExternalIndex();
+ outputList->disableAllBut(OutputGenerator::Html);
+ startFile(*outputList,"header.html","Search Engine",TRUE);
+ outputList->endPlainFile();
+ outputList->startPlainFile("footer.html");
+ endFile(*outputList,TRUE);
+ outputList->enableAll();
+ }
+}
+
+//----------------------------------------------------------------------------
+// generate the configuration file
+
+void generateConfigFile(const char *configFile,bool shortList)
+{
+ QFileInfo fi(configFile);
+ QFile f(configFile);
+
+ if (fi.exists()) // create a backup
+ {
+ QDir dir=fi.dir();
+ dir.rename(fi.fileName(),fi.fileName()+".bak");
+ }
+ if (f.open(IO_WriteOnly))
+ {
+ writeTemplateConfig(&f,shortList);
+ f.close();
+ msg("\n\nConfiguration file `%s' created.\n\n",configFile);
+ msg("Now edit the configuration file and enter\n\n");
+ if (strcmp(configFile,"Doxyfile") || strcmp(configFile,"doxyfile"))
+ msg(" doxygen %s\n\n",configFile);
+ else
+ msg(" doxygen\n\n");
+ msg("to generate the documentation for your project\n\n");
+ }
+ else
+ {
+ err("Error: Cannot open file %s for writing\n");
+ exit(1);
+ }
+}
+
+//----------------------------------------------------------------------------
+// read and parse a tag file
+
+bool readLineFromFile(QFile &f,QString &s)
+{
+ char c=0;
+ s.resize(0);
+ while (!f.atEnd() && (c=f.getch())!='\n') s+=c;
+ return f.atEnd();
+}
+
+void readTagFile(const char *file)
+{
+ QFileInfo fi(file);
+ if (!fi.exists() || !fi.isFile())
+ {
+ err("Error: Tag file `%s' does not exist or is not a file\n",file);
+ exit(1);
+ }
+ msg("Reading tag file %s...\n",file);
+ parseTagFile(file);
+}
+
+//----------------------------------------------------------------------------
+// returns TRUE if the name of the file represented by `fi' matches
+// one of the file patterns in the `patList' list.
+
+bool patternMatch(QFileInfo *fi,QStrList *patList)
+{
+ bool found=FALSE;
+ if (patList)
+ {
+ char *pattern=patList->first();
+ while (pattern && !found)
+ {
+ found = found || QDir::match(pattern,fi->fileName());
+ pattern=patList->next();
+ }
+ }
+ return found;
+}
+
+//----------------------------------------------------------------------------
+// reads a file into an array and filters out any 0x00 and 0x06 bytes,
+// because these are special for the parser.
+
+void copyAndFilterFile(const char *fileName,BufStr &dest)
+{
+ // try to open file
+ int size=0;
+ uint oldPos = dest.curPos();
+
+ QFileInfo fi(fileName);
+ if (!fi.exists()) return;
+ if (inputFilter.isEmpty())
+ {
+ QFile f(fileName);
+ if (!f.open(IO_ReadOnly))
+ {
+ err("Error: could not open file %s\n",fileName);
+ return;
+ }
+ size=fi.size();
+ // read the file
+ dest.skip(size);
+ if (f.readBlock(dest.data()+oldPos,size)!=size)
+ {
+ err("Error while reading file %s\n",fileName);
+ return;
+ }
+ }
+ else
+ {
+ int c;
+// char *p=dest;
+ QString cmd=inputFilter+" "+fileName;
+ FILE *f=popen(cmd,"r");
+ if (!f)
+ {
+ err("Error: could not execute filter %s\n",inputFilter.data());
+ return;
+ }
+ while ((c=fgetc(f))!=EOF) dest.addChar(c),size++;
+ }
+ // filter unwanted bytes from the resulting data
+ uchar *p=(uchar *)dest.data()+oldPos;
+ uchar conv[256];
+ int i;
+ for (i=0;i<256;i++) conv[i]=i;
+ conv[0x06]=0x20; // replace the offending characters with spaces
+ conv[0x00]=0x20;
+ // remove any special markers from the input
+ for (i=0;i<size;i++,p++) *p=conv[*p];
+ // adjust pointer
+}
+
+//----------------------------------------------------------------------------
+// Reads a file to a string.
+// The name of the file is written in front of the file's contents and
+// between 0x06 markers
+
+
+void readFiles(BufStr &output)
+{
+ QString *s=inputFiles.first();
+// char *p=output.data();
+ while (s)
+ {
+ QString fileName=*s;
+
+ //int fileSize=fi->fileInfo()->size();
+ int fileNameSize=fileName.length();
+ //int streamLength=fileSize+fileNameSize+4;
+
+ //QString fileText(streamLength);
+
+ // add begin filename marker
+// *p++=0x06;
+ output.addChar(0x06);
+ // copy filename
+// memcpy(p,fileName.data(),fileNameSize);
+// p+=fileNameSize;
+ output.addArray(fileName.data(),fileNameSize);
+
+ // add end filename marker
+// *p++=0x06;
+ output.addChar(0x06);
+// *p++='\n'; // to make ^ work while scanning the first line of a file!
+ output.addChar('\n');
+ if (preprocessingFlag)
+ {
+ msg("Preprocessing %s...\n",s->data());
+ preprocessFile(fileName,output);
+ }
+ else
+ {
+ msg("Reading %s...\n",s->data());
+ copyAndFilterFile(fileName,output);
+ }
+
+ s=inputFiles.next();
+ }
+// *p++='\0';
+ output.addChar(0);
+ //printf("Output after preprocessing:\n---------\n%s\n----------\n",output.data());
+ //printf("Final length = %d\n",p-output.data());
+}
+
+//----------------------------------------------------------------------------
+// Read all files matching at least one pattern in `patList' in the
+// directory represented by `fi'.
+// The directory is read iff the recusiveFlag is set.
+// The contents of all files is append to the input string
+
+int readDir(QFileInfo *fi,
+ FileNameList *fnList,
+ FileNameDict *fnDict,
+ StringDict *exclDict,
+ QStrList *patList,
+ QStrList *exclPatList,
+ StringList *resultList,
+ StringDict *resultDict
+ )
+{
+ QDir dir((const char *)fi->absFilePath());
+ dir.setFilter( QDir::Files | QDir::Dirs );
+ int totalSize=0;
+
+ const QFileInfoList *list = dir.entryInfoList();
+ QFileInfoListIterator it( *list );
+ QFileInfo *cfi;
+
+ while ((cfi=it.current()))
+ {
+ if (exclDict==0 || exclDict->find(cfi->absFilePath())==0)
+ { // file should not be excluded
+ if (!cfi->exists() || !cfi->isReadable())
+ {
+ err("Error: source %s is not a readable file or directory... skipping.\n",cfi->absFilePath().data());
+ }
+ else if (cfi->isFile() &&
+ patternMatch(cfi,patList) && !patternMatch(cfi,exclPatList))
+ {
+ totalSize+=cfi->size()+cfi->absFilePath().length()+3;
+ QString name=cfi->fileName();
+ if (fnDict)
+ {
+ FileDef *fd=new FileDef(cfi->dirPath()+"/",name);
+ FileName *fn=0;
+ if (name.length()>0 && (fn=(*fnDict)[name]))
+ {
+ fn->append(fd);
+ }
+ else
+ {
+ fn = new FileName(name);
+ fn->append(fd);
+ if (fnList) fnList->inSort(fn);
+ fnDict->insert(name,fn);
+ }
+ }
+ QString *rs=0;
+ if (resultList || resultDict)
+ {
+ rs=new QString(cfi->absFilePath());
+ }
+ if (resultList) resultList->append(rs);
+ if (resultDict) resultDict->insert(cfi->absFilePath(),rs);
+ }
+ else if (recursiveFlag && cfi->isDir() && cfi->fileName()!="." &&
+ cfi->fileName()!="..")
+ {
+ cfi->setFile(cfi->absFilePath());
+ totalSize+=readDir(cfi,fnList,fnDict,exclDict,
+ patList,exclPatList,resultList,resultDict);
+ }
+ }
+ ++it;
+ }
+ return totalSize;
+}
+
+//----------------------------------------------------------------------------
+// read the file with name `name' into a string.
+
+QString readExampleFile(const char *name)
+{
+ QString example;
+ QFileInfo fi(name);
+ if (fi.exists())
+ {
+ QFile f((const char *)fi.absFilePath());
+ if (f.open(IO_ReadOnly))
+ {
+ example.resize(fi.size()+1);
+ if ((int)fi.size()!=f.readBlock(example.data(),fi.size()))
+ {
+ err("Error while reading file %s\n",fi.absFilePath().data());
+ //exit(1);
+ return "";
+ }
+ example.at(fi.size())='\0';
+ }
+ else
+ {
+ err("Error opening file %s\n",fi.absFilePath().data());
+ //exit(1);
+ return "";
+ }
+ }
+ else
+ {
+ err("Error: example file %s does not exist\n",name);
+ exit(1);
+ }
+ return example;
+}
+
+//----------------------------------------------------------------------------
+// read a file or all files in a directory and append their contents to the
+// input string. The names of the files are appended to the `fiList' list.
+
+int readFileOrDirectory(const char *s,
+ FileNameList *fnList,
+ FileNameDict *fnDict,
+ StringDict *exclDict,
+ QStrList *patList,
+ QStrList *exclPatList,
+ StringList *resultList,
+ StringDict *resultDict
+ )
+{
+ QFileInfo fi(s);
+ int totalSize=0;
+ {
+ if (exclDict==0 || exclDict->find(fi.absFilePath())==0)
+ {
+ if (!fi.exists() || !fi.isReadable())
+ {
+ err("Error: source %s is not a readable file or directory... skipping.\n",s);
+ }
+ else if (fi.isFile())
+ {
+ totalSize+=fi.size()+fi.absFilePath().length()+3; //readFile(&fi,fiList,input);
+ //fiList->inSort(new FileInfo(fi));
+ QString name=fi.fileName();
+ if (fnDict)
+ {
+ FileDef *fd=new FileDef(fi.dirPath(TRUE)+"/",name);
+ FileName *fn=0;
+ if (name.length()>0 && (fn=(*fnDict)[name]))
+ {
+ fn->append(fd);
+ }
+ else
+ {
+ fn = new FileName(name);
+ fn->append(fd);
+ if (fnList) fnList->inSort(fn);
+ fnDict->insert(name,fn);
+ }
+ }
+ QString *rs=0;
+ if (resultList || resultDict)
+ {
+ rs=new QString(fi.absFilePath());
+ }
+ if (resultList) resultList->append(rs);
+ if (resultDict) resultDict->insert(fi.absFilePath(),rs);
+ }
+ else if (fi.isDir()) // readable dir
+ totalSize+=readDir(&fi,fnList,fnDict,exclDict,patList,
+ exclPatList,resultList,resultDict);
+ }
+ }
+ return totalSize;
+}
+
+//----------------------------------------------------------------------------
+
+void readFormulaRepository()
+{
+ QFile f(htmlOutputDir+"/formula.repository");
+ if (f.open(IO_ReadOnly)) // open repository
+ {
+ QTextStream t(&f);
+ QString line;
+ while (!t.eof())
+ {
+ line=t.readLine();
+ int se=line.find(':'); // find name and text separator.
+ if (se==-1)
+ {
+ warn("Warning: formula.repository is corrupted!\n");
+ break;
+ }
+ else
+ {
+ QString formName = line.left(se);
+ QString formText = line.right(line.length()-se-1);
+ Formula *f=new Formula(formText);
+ formulaList.append(f);
+ formulaDict.insert(formText,f);
+ formulaNameDict.insert(formName,f);
+ }
+ }
+ }
+}
+
+//----------------------------------------------------------------------------
+// print the usage of doxygen
+
+void usage(const char *name)
+{
+ msg("Doxygen version %s\nCopyright Dimitri van Heesch 1997-1999\n\n",versionString);
+ msg("You can use doxygen in two ways:\n\n");
+ msg("1) Use doxygen to generate a template configuration file:\n");
+ msg(" %s [-s] -g [configName]\n\n",name);
+ msg(" if -s is specified the comments in the config file will be omitted.\n\n");
+ msg("2) Use doxygen to generate documentation using an existing ");
+ msg("configuration file:\n");
+ msg(" %s [configName]\n\n",name);
+ msg("If configName is omitted `Doxyfile' will be used as a default.\n\n");
+ exit(1);
+}
+
+//----------------------------------------------------------------------------
+// read the argument of option `c' from the comment argument list and
+// update the option index `optind'.
+
+const char *getArg(int argc,char **argv,int &optind)
+{
+ char *s=0;
+ if (strlen(&argv[optind][2])>0)
+ s=&argv[optind][2];
+ else if (optind+1<argc)
+ s=argv[++optind];
+ return s;
+}
+
+//----------------------------------------------------------------------------
+
+int main(int argc,char **argv)
+{
+
+ initPreprocessor();
+
+ /**************************************************************************
+ * Handle arguments *
+ **************************************************************************/
+
+ char *s;
+ int optind=1;
+ const char *configName=0;
+ const char *debugLabel;
+ bool genConfig=FALSE;
+ bool shortList=FALSE;
+ while (optind<argc && argv[optind][0]=='-')
+ {
+ switch(argv[optind][1])
+ {
+ case 'g':
+ genConfig=TRUE;
+ configName=getArg(argc,argv,optind);
+ if (!configName) configName="Doxyfile";
+ break;
+ case 'd':
+ debugLabel=getArg(argc,argv,optind);
+ Debug::setFlag(debugLabel);
+ break;
+ case 's':
+ shortList=TRUE;
+ break;
+ case 'h':
+ case '?':
+ usage(argv[0]);
+ break;
+ default:
+ err("Unknown option -%c\n",argv[optind][1]);
+ usage(argv[0]);
+ }
+ optind++;
+ }
+
+ /**************************************************************************
+ * Parse or generate the config file *
+ **************************************************************************/
+
+ if (genConfig)
+ {
+ generateConfigFile(configName,shortList);
+ exit(1);
+ }
+
+ QFileInfo configFileInfo1("Doxyfile"),configFileInfo2("doxyfile");
+ QString config;
+ if (optind>=argc)
+ {
+ if (configFileInfo1.exists())
+ config=fileToString("Doxyfile");
+ else if (configFileInfo2.exists())
+ {
+ config=fileToString("doxyfile");
+ }
+ else
+ {
+ err("Doxyfile not found and no input file specified!\n");
+ usage(argv[0]);
+ }
+ }
+ else
+ config=fileToString(argv[1]);
+
+ parseConfig(config);
+
+ /**************************************************************************
+ * Initialize output generators *
+ **************************************************************************/
+
+ outputList = new OutputList(TRUE);
+ if (generateHtml)
+ {
+ outputList->add(new HtmlGenerator);
+ HtmlGenerator::init();
+ }
+ if (generateLatex)
+ {
+ outputList->add(new LatexGenerator);
+ LatexGenerator::init();
+ }
+ if (generateMan)
+ {
+ outputList->add(new ManGenerator);
+ ManGenerator::init();
+ }
+
+ /**************************************************************************
+ * Read and preprocess input *
+ **************************************************************************/
+
+ // gather names of all files in the include path
+ msg("Searching for include files...\n");
+ s=includePath.first();
+ while (s)
+ {
+ readFileOrDirectory(s,0,&includeNameDict,0,&filePatternList,
+ &excludePatternList,0,0);
+ s=includePath.next();
+ }
+
+ msg("Searching for example files...\n");
+ s=examplePath.first();
+ while (s)
+ {
+ readFileOrDirectory(s,0,&exampleNameDict,0,&filePatternList,
+ &excludePatternList,0,0);
+ s=examplePath.next();
+ }
+
+ msg("Searching for files to exclude\n");
+ s=excludeSources.first();
+ while (s)
+ {
+ readFileOrDirectory(s,0,0,0,&filePatternList,
+ 0,0,&excludeNameDict);
+ s=excludeSources.next();
+ }
+
+ msg("Reading input files...\n");
+ int inputSize=0;
+ s=inputSources.first();
+ while (s)
+ {
+ inputSize+=readFileOrDirectory(s,&inputNameList,
+ &inputNameDict,&excludeNameDict,
+ &filePatternList,&excludePatternList,
+ &inputFiles,0);
+ s=inputSources.next();
+ }
+ //msg("Input size %d bytes\n",inputSize);
+
+ BufStr input(inputSize+1); // Add one byte extra for \0 termination
+ readFiles(input);
+
+ if (input.length()==0)
+ {
+ warn("No input read, no output generated!\n");
+ exit(1);
+ }
+ else
+ {
+ msg("Read %d bytes\n",input.length());
+ }
+
+ /**************************************************************************
+ * Handle Tag Files *
+ **************************************************************************/
+
+ msg("Reading tag files\n");
+
+ s=tagFileList.first();
+ while (s)
+ {
+ readTagFile(s);
+ s=tagFileList.next();
+ }
+
+ QFile *tag =new QFile(genTagFile);
+ if (genTagFile.length()>0)
+ {
+ if (!tag->open(IO_WriteOnly))
+ {
+ err("Error: cannot open tag file %s for writing\n",genTagFile.data());
+ exit(1);
+ }
+ tagFile.setDevice(tag);
+ }
+
+ /**************************************************************************
+ * Gather information *
+ **************************************************************************/
+
+ // Notice: the order of the function calls below is very important!
+
+ if (generateHtml)
+ {
+ msg("Reading formula repository...\n");
+ readFormulaRepository();
+ }
+
+ Entry *root=new Entry;
+ root->program=input;
+
+ msg("Parsing input...\n");
+ parseMain(root); // build a tree of entries
+
+ msg("Freeing input...\n");
+ input.resize(0);
+
+ msg("Building namespace list...\n");
+ buildNamespaceList(root);
+
+ msg("Building group list...\n");
+ buildGroupList(root);
+
+ //msg("Computing group relations...\n");
+ //computeGroupRelations(root);
+
+ msg("Building file list...\n");
+ buildFileList(root);
+
+ msg("Building class list...\n");
+ buildClassList(root);
+
+ msg("Building example list...\n");
+ buildExampleList(root);
+
+ msg("Building page list...\n");
+ buildPageList(root);
+
+// msg("Adding compounds to file pages...\n");
+// findClassDefsInFiles(root);
+
+ msg("Building member list...\n"); // using class info only !
+ buildMemberList(root);
+ transferFunctionDocumentation();
+
+ msg("Searching for friends...\n");
+ findFriends();
+
+
+ msg("Searching for documented variables...\n");
+ buildVarList(root);
+
+ msg("Searching for documented defines...\n");
+ findDefineDocumentation(root);
+
+ msg("Computing class relations...\n");
+ computeClassRelations(root);
+
+ msg("Searching for enumerations...\n");
+ findEnums(root);
+ findEnumDocumentation(root);
+
+// msg("Searching for function prototypes...\n");
+// findPrototypes(root); // may introduce new members !
+
+ msg("Searching for member function documentation...\n");
+ findMemberDocumentation(root); // may introduce new members !
+
+ msg("Freeing entry tree\n");
+ delete root;
+
+ msg("Computing member references...\n");
+ computeMemberReferences();
+
+ msg("Computing function references...\n");
+ computeFunctionReferences();
+
+ msg("Computing member relations...\n");
+ computeMemberRelations();
+
+ msg("Building full member lists recursively...\n");
+ buildCompleteMemberLists();
+
+ //unrelatedFunctionsUsed=hasUnrelatedFunctions();
+
+ /**************************************************************************
+ * Generate documentation *
+ **************************************************************************/
+
+ // count the number of documented elements in the lists we have built.
+ // If the result is 0 we do not generate the lists and omit the
+ // corresponding links in the index.
+ msg("Counting data structures...\n");
+ annotatedClasses = countAnnotatedClasses();
+ hierarchyClasses = countClassHierarchy();
+ documentedMembers = countMemberList();
+ documentedFunctions = countFunctionList();
+ documentedFiles = countFileList();
+ documentedGroups = countGroupList();
+ documentedNamespaces = countNamespaceList();
+
+ // compute the shortest possible names of all files
+ // without loosing the uniqueness of the file names.
+ msg("Generating disk names...\n");
+ inputNameList.generateDiskNames();
+
+ msg("Generating example documentation...\n");
+ generateExampleDocs();
+
+ msg("Generating file documentation...\n");
+ generateFileDocs();
+
+ msg("Generating class documentation...\n");
+ generateClassDocs();
+
+ msg("Generating page documentation...\n");
+ generatePageDocs();
+
+ msg("Generating group documentation...\n");
+ generateGroupDocs();
+
+ msg("Generating namespace index...\n");
+ generateNamespaceDocs();
+
+ msg("Generating group index...\n");
+ writeGroupIndex(*outputList);
+
+ msg("Generating example index...\n");
+ writeExampleIndex(*outputList);
+
+ msg("Generating function index...\n");
+ writeFunctionIndex(*outputList);
+
+// msg("Generating define index...\n");
+// writeDefineIndex(*outputList);
+
+ msg("Generating page index...\n");
+ writePageIndex(*outputList);
+
+ msg("Generating search index...\n");
+ generateSearchIndex();
+
+ msg("Generating style sheet...\n");
+ outputList->writeStyleInfo(0); // write first part
+ outputList->disableAllBut(OutputGenerator::Latex);
+ parseDoc(*outputList,0,0,
+ theTranslator->trGeneratedAt(dateToString(TRUE),projectName)
+ );
+ outputList->writeStyleInfo(1); // write second part
+ parseDoc(*outputList,0,0, theTranslator->trWrittenBy());
+ outputList->writeStyleInfo(2); // write third part
+ parseDoc(*outputList,0,0,
+ theTranslator->trGeneratedAt(dateToString(TRUE),projectName)
+ );
+ outputList->writeStyleInfo(3); // write fourth part
+ parseDoc(*outputList,0,0, theTranslator->trWrittenBy());
+ outputList->writeStyleInfo(4); // write last part
+ outputList->enableAll();
+
+ if (formulaList.count()>0 && generateHtml)
+ {
+ msg("Generating bitmaps for formulas in HTML...\n");
+ formulaList.generateBitmaps(htmlOutputDir);
+ }
+
+ if (searchEngineFlag || tagFileList.count()>0)
+ {
+ msg("\nNow copy the file\n\n %s\n\nto the directory where the CGI binaries are "
+ "located and don't forget to run\n\n",(htmlOutputDir+"/"+cgiName).data());
+ msg(" %s/installdox\n\nto replace any dummy links.\n\n",
+ htmlOutputDir.data());
+ }
+
+ delete tag;
+ return 0;
+}
diff --git a/src/doxygen.h b/src/doxygen.h
new file mode 100644
index 0000000..05ca854
--- /dev/null
+++ b/src/doxygen.h
@@ -0,0 +1,134 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#ifndef DOXYGEN_H
+#define DOXYGEN_H
+
+#include "groupdef.h"
+#include "filedef.h"
+#include "classdef.h"
+#include "memberdef.h"
+#include "classlist.h"
+#include "membername.h"
+#include "filename.h"
+#include "define.h"
+#include "namespacedef.h"
+#include "formula.h"
+
+struct PageInfo
+{
+ PageInfo(const char *n,const char *d,const char *t)
+ { name=n; doc=d; title=t; }
+ QString name;
+ QString doc;
+ QString title;
+};
+
+class PageList : public QList<PageInfo>
+{
+ int compareItems(GCI i1,GCI i2)
+ {
+ return stricmp(((PageInfo *)i1)->name,((PageInfo *)i2)->name);
+ }
+};
+
+class BufStr : public QString
+{
+ public:
+ BufStr(int size) : QString(size), offset(0), spareRoom(10240) {}
+ void addChar(char c)
+ {
+ if (offset>=size()) resize(size()+spareRoom);
+ data()[offset++]=c;
+ }
+ void addArray(const char *a,int len)
+ {
+ if (offset+len>=size()) resize(size()+len+spareRoom);
+ memcpy(data()+offset,a,len);
+ offset+=len;
+ }
+ uint curPos() { return offset; }
+ void skip(uint s)
+ {
+ if (offset+s>=size()) resize(size()+s+spareRoom);
+ offset+=s;
+ }
+ private:
+ uint offset;
+ const int spareRoom; // 10Kb extra room to avoid frequent resizing
+};
+
+struct SectionInfo
+{
+ SectionInfo(const char *n,const char *l,const char *t,bool sub)
+ { pageName=n; label=l; title=t; isSubsection=sub; }
+ QString pageName;
+ QString label;
+ QString title;
+ bool isSubsection;
+};
+
+typedef QList<QString> StringList;
+typedef QDict<MemberDef> MemberDict;
+typedef QDict<ClassDef> ClassDict;
+typedef QDict<FileDef> FileDict;
+typedef QDict<QString> StringDict;
+typedef QDict<PageInfo> PageDict;
+typedef QDict<SectionInfo> SectionDict;
+typedef QDict<GroupDef> GroupDict;
+
+extern const char * getOverloadDocs();
+extern ClassList classList;
+extern ClassDict classDict;
+extern QStrList tagfileList;
+extern PageList exampleList;
+extern PageDict exampleDict;
+extern PageList pageList;
+extern PageDict pageDict;
+extern MemberNameList memberNameList;
+extern MemberNameList functionNameList;
+extern MemberNameDict memberNameDict;
+extern MemberNameDict functionNameDict;
+extern StringDict substituteDict;
+extern FileList fileList;
+extern FileDict fileDict;
+extern DefineDict defineDict;
+extern ClassDef unrelatedClass;
+extern QTextStream tagFile;
+extern SectionDict sectionDict;
+extern FileNameList inputNameList;
+extern FileNameDict includeNameDict;
+extern FileNameDict exampleNameDict;
+extern FileNameDict inputNameDict;
+extern FileList includeFiles;
+extern StringDict typedefDict;
+extern GroupList groupList;
+extern NamespaceList namespaceList;
+extern FormulaList formulaList;
+extern FormulaDict formulaDict;
+extern FormulaDict formulaNameDict;
+
+extern int annotatedClasses;
+extern int hierarchyClasses;
+extern int documentedFunctions;
+extern int documentedMembers;
+extern int documentedDefines;
+extern int documentedFiles;
+extern int documentedGroups;
+extern int documentedNamespaces;
+
+#endif
diff --git a/src/doxygen.pro b/src/doxygen.pro
new file mode 100644
index 0000000..e6dd3c0
--- /dev/null
+++ b/src/doxygen.pro
@@ -0,0 +1,38 @@
+#
+# $Id$
+#
+# Copyright (C) 1997-1999 by Dimitri van Heesch.
+#
+# Permission to use, copy, modify, and distribute this software and its
+# documentation under the terms of the GNU General Public License is hereby
+# granted. No representations are made about the suitability of this software
+# for any purpose. It is provided "as is" without express or implied warranty.
+# See the GNU General Public License for more details.
+#
+# All output generated with Doxygen is not covered by this license.
+#
+# TMake project file for doxygen
+
+TEMPLATE = doxygen.t
+CONFIG = console qt warn_on release #debug
+HEADERS = doxygen.h scanner.h classdef.h classlist.h memberdef.h \
+ membername.h index.h memberlist.h definition.h \
+ entry.h logos.h instdox.h message.h code.h \
+ filedef.h util.h cppvalue.h constexp.h \
+ outputgen.h outputlist.h htmlgen.h latexgen.h tag.h \
+ filename.h defargs.h groupdef.h gifenc.h diagram.h image.h \
+ namespacedef.h version.h language.h translator.h \
+ translator_nl.h translator_se.h translator_cz.h translator_fr.h \
+ translator_it.h formula.h debug.h
+SOURCES = doxygen.cpp scanner.cpp classdef.cpp classlist.cpp memberdef.cpp \
+ membername.cpp index.cpp memberlist.cpp \
+ entry.cpp logos.cpp instdox.cpp message.cpp code.cpp \
+ config.cpp filedef.cpp util.cpp groupdef.cpp \
+ outputgen.cpp outputlist.cpp htmlgen.cpp latexgen.cpp mangen.cpp \
+ cppvalue.cpp ce_lex.cpp ce_parse.cpp pre.cpp \
+ tag.cpp filename.cpp declinfo.cpp defargs.cpp define.cpp \
+ diagram.cpp gifenc.cpp image.cpp namespacedef.cpp \
+ version.cpp language.cpp definition.cpp formula.cpp debug.cpp
+win32:INCLUDEPATH += .
+TARGET = ../bin/doxygen
+OBJECTS_DIR = ../objects
diff --git a/src/doxygen.t b/src/doxygen.t
new file mode 100644
index 0000000..badf33e
--- /dev/null
+++ b/src/doxygen.t
@@ -0,0 +1,76 @@
+#
+# $Id$
+#
+# Copyright (C) 1997-1999 by Dimitri van Heesch.
+#
+# Permission to use, copy, modify, and distribute this software and its
+# documentation under the terms of the GNU General Public License is hereby
+# granted. No representations are made about the suitability of this software
+# for any purpose. It is provided "as is" without express or implied warranty.
+# See the GNU General Public License for more details.
+#
+# All output generated with Doxygen is not covered by this license.
+#!
+#! doxygen.t: This is a custom template for building Doxygen
+#!
+#$ IncludeTemplate("app.t");
+
+LEX = flex
+YACC = bison
+
+#${
+sub GenerateDep {
+ my($obj,$src,$dep) = @_;
+ my(@objv,$srcv,$i,$s,$o,$d,$c);
+ @objv = split(/\s+/,$obj);
+ @srcv = split(/\s+/,$src);
+ for $i ( 0..$#objv ) {
+ $s = $srcv[$i];
+ $o = $objv[$i];
+ next if $s eq "";
+ $text .= $o . ": " . $s;
+ $text .= " ${linebreak}\n\t\t" . $dep if $dep ne "";
+ if ( $moc_output{$s} ne "" ) {
+ $text .= " ${linebreak}\n\t\t" . $moc_output{$s};
+ }
+ $d = &make_depend($s);
+ $text .= " ${linebreak}\n\t\t" . $d if $d ne "";
+ $text .= "\n";
+ }
+ chop $text;
+}
+#$}
+
+####################
+
+#$ GenerateDep("scanner.cpp","scanner.l");
+ $(LEX) -PscanYY -t scanner.l >scanner.cpp
+
+#$ GenerateDep("code.cpp","code.l");
+ $(LEX) -PcodeYY -t code.l >code.cpp
+
+#$ GenerateDep("pre.cpp","pre.l");
+ $(LEX) -PpreYY -t pre.l >pre.cpp
+
+#$ GenerateDep("tag.cpp","tag.l");
+ $(LEX) -PtagYY -t tag.l >tag.cpp
+
+#$ GenerateDep("config.cpp","config.l");
+ $(LEX) -PconfigYY -t config.l >config.cpp
+
+#$ GenerateDep("declinfo.cpp","declinfo.l");
+ $(LEX) -PdeclinfoYY -t declinfo.l >declinfo.cpp
+
+#$ GenerateDep("defargs.cpp","defargs.l");
+ $(LEX) -PdefargsYY -t defargs.l >defargs.cpp
+
+#$ GenerateDep("ce_lex.cpp","constexp.l","ce_parse.h");
+ $(LEX) -PcppExpYY -t constexp.l >ce_lex.cpp
+
+#$ GenerateDep("ce_parse.cpp","constexp.y");
+ $(YACC) -l -p cppExpYY constexp.y -o ce_parse.cpp
+
+#$ GenerateDep("ce_parse.h","constexp.y");
+ $(YACC) -l -d -p cppExpYY constexp.y -o ce_parse.c
+ -rm ce_parse.c
+
diff --git a/src/doxysearch.cpp b/src/doxysearch.cpp
new file mode 100644
index 0000000..cd59d02
--- /dev/null
+++ b/src/doxysearch.cpp
@@ -0,0 +1,1022 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+// includes
+
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <sys/stat.h>
+#ifdef PROFILING
+#include <sys/time.h>
+#include <unistd.h>
+#endif
+
+// defines
+
+#ifndef bool
+#define bool int
+#endif
+
+#define MAXSTRLEN 1024
+#ifndef TRUE
+#define TRUE 1
+#endif
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#define NORMAL 1 // OR search results
+#define INCLUDE 2 // AND search results
+#define EXCLUDE 3 // AND NOT search results
+
+#define TERMMASK (1<<31)
+#define OFFSETMASK (~TERMMASK)
+
+// structs
+
+//----------------------------------------------------------------------------
+
+struct FileInfo
+{
+ FileInfo() { f=0; url=0; }
+ ~FileInfo() { if (f) fclose(f);
+ delete[] url;
+ }
+ FILE *f;
+ int index;
+ int refOffset;
+ char *url;
+ FileInfo *next;
+};
+
+//----------------------------------------------------------------------------
+
+struct FileList
+{
+ FileList() { first=0; last=0; index=0; }
+ ~FileList() { FileInfo *fi=first;
+ while (fi) { FileInfo *ofi=fi; fi=fi->next; delete ofi; }
+ }
+ FileInfo *add()
+ {
+ FileInfo *nf=new FileInfo;
+ nf->next=0;
+ nf->index=index++;
+ if (last) { last->next=nf; last=nf; } else { first=nf; last=nf; }
+ return nf;
+ }
+ FileInfo *first;
+ FileInfo *last;
+ int index;
+};
+
+//----------------------------------------------------------------------------
+
+struct WordInfo
+{
+ WordInfo() { word=0; }
+ ~WordInfo() { delete[] word; }
+ char *word;
+ int freq;
+ WordInfo *next;
+};
+
+//----------------------------------------------------------------------------
+
+struct WordList
+{
+ WordList() { first=0; last=0; }
+ ~WordList() { WordInfo *wi=first;
+ while (wi) { WordInfo *owi=wi; wi=wi->next; delete owi; }
+ }
+ void add(const char *word,int freq)
+ {
+ WordInfo *nw=new WordInfo;
+ nw->word = new char[strlen(word)+1];
+ strcpy(nw->word,word);
+ nw->freq=freq;
+ nw->next=0;
+ if (last) { last->next=nw; last=nw; } else { first=nw; last=nw; }
+ }
+ WordInfo *first;
+ WordInfo *last;
+};
+
+//----------------------------------------------------------------------------
+
+struct SearchDoc
+{
+ FileInfo *fileInfo;
+ int index;
+ int freq;
+ double rank;
+ SearchDoc *next;
+};
+
+//----------------------------------------------------------------------------
+
+struct SearchResults
+{
+ SearchResults() { totalFreq=0; docList=0; last=0; }
+ ~SearchResults() { SearchDoc *d=docList;
+ while (d) { SearchDoc *od=d; d=d->next; delete od; }
+ }
+ void add(FileInfo *fi,int index,int freq)
+ {
+ SearchDoc *nd=new SearchDoc;
+ nd->fileInfo=fi;
+ nd->index=index;
+ nd->freq=freq;
+ nd->next=0;
+ if (last) { last->next=nd; last=nd; } else { docList=nd; last=nd; }
+ }
+ SearchDoc *docList;
+ SearchDoc *last;
+ int totalFreq;
+};
+
+//----------------------------------------------------------------------------
+
+// global vars
+
+static WordList wordList;
+static FileList fileList;
+static char cgiBin[MAXSTRLEN];
+static char queryInput[MAXSTRLEN];
+static char encQueryInput[MAXSTRLEN];
+static char firstDocUrl[MAXSTRLEN];
+static bool nameOnly;
+static bool wordOnly;
+static bool helpOnly;
+static int page;
+static char *headerBuf=0;
+static char *footerBuf=0;
+
+//----------------------------------------------------------------------------
+
+// functions
+
+void printHeader()
+{
+ if (headerBuf)
+ {
+ printf("Content-Type: text/html\r\n\r\n%s",headerBuf);
+ }
+ else
+ {
+ printf("Content-Type: text/html\r\n\r\n");
+ printf("<html><head><title>Search the documentation</title></head>\n"
+ "<body bgcolor=\"#ffffff\" text=\"#000000\" link=\"#0000ee\" \n"
+ "vlink=\"#551a8b\" alink=\"#ff0000\">\n");
+ }
+}
+
+//----------------------------------------------------------------------------
+
+void printFooter()
+{
+ if (footerBuf)
+ {
+ printf("%s",footerBuf);
+ }
+ else
+ {
+ printf("</body></html>\n");
+ }
+}
+
+//----------------------------------------------------------------------------
+
+void message(char *fmt,...)
+{
+ printHeader();
+ printf("<h2>");
+ va_list args;
+ va_start(args, fmt);
+ vfprintf(stdout, fmt, args);
+ va_end(args);
+ printf("</h2>");
+ printFooter();
+}
+
+//----------------------------------------------------------------------------
+
+void printSearchPage(bool open=FALSE)
+{
+ printf("<form name=doxyform method=GET action=\"%s\">\n"
+ "<center>\n"
+ "<input type=hidden name=page value=0>\n"
+ "<table border=0 bgcolor=\"#ffffcc\" cellspacing=0 cellpadding=4>\n"
+ " <tr>\n"
+ " <td valign=top><font size=-1 face=\"arial, helvetica\"><b>"
+ " Search for\n"
+ " <select name=which>\n"
+ " <option value=string %s>strings\n"
+ " <option value=word %s>words\n"
+ " </select>\n"
+ " in function and class\n"
+ " <select name=what>\n"
+ " <option value=doc %s>documentation\n"
+ " <option value=name %s>names</select></b></font>\n"
+ " </td>\n"
+ " <td valign=top align=right>\n"
+ " <a href=\"%s?help=on\"><font size=-1>Help</font></a>\n"
+ " </td>\n"
+ " </tr>\n"
+ " <tr>\n"
+ " <td><input name=query size=44 wrap=virtual maxlength=1000 value=\"%s\">\n"
+ " </td>\n"
+ " <td><input type=image src=\"%s/search.gif\" height=26 width=120 border=0 name=\"search\">\n"
+ " </td>\n"
+ " </tr>\n",
+ cgiBin,
+ (wordOnly?"":"selected"),(wordOnly?"selected":""),
+ (nameOnly?"":"selected"),(nameOnly?"selected":""),
+ cgiBin,queryInput,firstDocUrl);
+ if (!open)
+ {
+ printf("</table>\n</center></form>\n");
+ }
+}
+
+//----------------------------------------------------------------------------
+
+int readInt(FILE *f)
+{
+ return (fgetc(f)<<24)+(fgetc(f)<<16)+(fgetc(f)<<8)+fgetc(f);
+}
+
+//----------------------------------------------------------------------------
+
+int readEncodedNumber(FILE *f)
+{
+ int n=0,b,s=0;
+ do { b=fgetc(f); n|=(b&0x7f)<<s; s+=7; } while (b&0x80);
+ return n;
+}
+
+void readString(FILE *f,char *s,int n)
+{
+ int i=0,b;
+ if (n<=0) return;
+ while (i<n-1 && (b=fgetc(f))!=0) s[i++]=b;
+ s[i]='\0';
+}
+
+//----------------------------------------------------------------------------
+
+bool searchRecursive(SearchResults *sr,FileInfo *fi,const char *word)
+{
+ char entry[MAXSTRLEN];
+ readString(fi->f,entry,MAXSTRLEN);
+ while (entry[0]!='\0')
+ {
+ //printf("Found entry `%s'\n",entry);
+ int i=0, w=word[0], e=entry[0];
+ while (w!=0 && e!=0 && w==e) { i++; w=word[i]; e=entry[i]; }
+ if (w==0 && e!=0) // word is a substring of entry
+ {
+ if (wordOnly) return FALSE; // no full word match
+ //printf("Word found as substring of `%s%s'\n",&word[-index],&entry[i]);
+ int offset=readInt(fi->f); // <= follow for extensions
+ if (!(offset&TERMMASK)) // extra info available
+ {
+ int tfreq=readEncodedNumber(fi->f);
+ sr->totalFreq+=tfreq;
+ //printf("Total frequency %d\n",tfreq);
+ int s=-1,k;
+ while ((k=readEncodedNumber(fi->f))!=0)
+ {
+ bool inName = (k&2)==2;
+ s+=(k>>3);
+ int freq=readEncodedNumber(fi->f);
+ //printf("Doc index %d frequency %d\n",s,freq);
+ if (!nameOnly || inName)
+ //addResult(fi,sr,s,freq);
+ sr->add(fi,s,freq);
+ }
+ }
+ return TRUE;
+ }
+ else if (e==0) // entry is a substring of word
+ {
+ if (w==0) // word is equal to entry => exact match found
+ {
+ int offset=readInt(fi->f); // <= follow for extensions
+ if (!(offset&TERMMASK)) // extra info available
+ {
+ //printf("Match found\n");
+ int tfreq=readEncodedNumber(fi->f);
+ sr->totalFreq+=tfreq;
+ //printf("Total frequency %d\n",tfreq);
+ int s=-1,k;
+ while ((k=readEncodedNumber(fi->f))!=0)
+ {
+ bool fullWord = (k&1)==1;
+ bool inName = (k&2)==2;
+ bool wordInName = (k&4)==4;
+ s+=(k>>3);
+ int freq=readEncodedNumber(fi->f);
+ if (nameOnly && wordOnly)
+ {
+ if (wordInName) sr->add(fi,s,freq);
+ }
+ else if (!nameOnly && wordOnly)
+ {
+ if (fullWord) sr->add(fi,s,freq);
+ }
+ else if (nameOnly && !wordOnly)
+ {
+ if (inName) sr->add(fi,s,freq);
+ }
+ else // !nameOnly && !wordOnly
+ {
+ sr->add(fi,s,freq);
+ }
+ }
+ }
+ return TRUE;
+ }
+ else // follow branch to next entry
+ {
+ int offset=readInt(fi->f);
+ if ((offset&OFFSETMASK)==0) // no next entry (leaf node)
+ {
+ return FALSE;
+ }
+ else // follow branch
+ {
+ fseek(fi->f,offset&OFFSETMASK,SEEK_SET);
+ //printf("Recursive call; jump to %lx\n",ftell(f));
+ return searchRecursive(sr,fi,&word[i]);
+ }
+ }
+ }
+ else // skip rest of the entry
+ {
+ int offset=readInt(fi->f);
+ if (!(offset&TERMMASK)) while (readEncodedNumber(fi->f)!=0);
+ }
+ readString(fi->f,entry,MAXSTRLEN);
+ }
+ //printf("Sorry no match found\n");
+ return FALSE;
+}
+
+//----------------------------------------------------------------------------
+
+
+void searchIndex(const char *word,SearchResults *results)
+{
+ FileInfo *fi=fileList.first;
+ while (fi)
+ {
+ fseek(fi->f,8,SEEK_SET);
+ searchRecursive(results,fi,word);
+ fi=fi->next;
+ }
+
+ SearchDoc *ds = results->docList;
+ while (ds)
+ {
+ ds->rank = ds->freq/(double)results->totalFreq;
+ ds = ds->next;
+ }
+
+ wordList.add(word,results->totalFreq);
+}
+
+//----------------------------------------------------------------------------
+
+int sortResults(const void *a1,const void *a2)
+{
+ SearchDoc **d1=(SearchDoc **)a1;
+ SearchDoc **d2=(SearchDoc **)a2;
+ if ((*d1)->rank > (*d2)->rank)
+ return -1;
+ else if ((*d1)->rank == (*d2)->rank)
+ return 0;
+ else
+ return 1;
+}
+
+//----------------------------------------------------------------------------
+
+void generateResults(SearchResults *sr)
+{
+ // compute the maximum rank
+ SearchDoc *ds = sr->docList;
+ double maxRank = 0.00000001;
+ int resultCount=0;
+ if (ds)
+ {
+ while (ds)
+ {
+ if (ds->rank>maxRank) maxRank = ds->rank;
+ ds = ds->next;
+ }
+
+ // scale ranks, so the highest is 1 and count the number of links
+ double oneOverMaxRank = 1.0/maxRank;
+ ds = sr->docList;
+ while (ds)
+ {
+ ds->rank *= oneOverMaxRank;
+ resultCount++;
+ ds = ds->next;
+ }
+ }
+ SearchDoc **docPtrArray=0;
+ if (resultCount>0)
+ {
+ docPtrArray=(SearchDoc **)calloc(resultCount,sizeof(SearchDoc *));
+ int offset=0;
+ ds = sr->docList;
+ while (ds)
+ {
+ docPtrArray[offset++]=ds;
+ ds = ds->next;
+ }
+ qsort(docPtrArray,resultCount,sizeof(SearchDoc *),sortResults);
+ }
+
+ // start generating output
+ printHeader();
+ printSearchPage(TRUE);
+
+ printf(" <tr bgcolor=#ffffff>\n"
+ " <td colspan=2>"
+ "<br><h3>Search results</h3>\n"
+ " </td>\n"
+ " </tr>\n");
+ if (resultCount==0) // nothing found
+ {
+ printf(" <tr bgcolor=#ffffff>\n"
+ " <td colspan=2>Sorry, no documents matching your query.\n"
+ " </td>\n"
+ " </tr>\n");
+ }
+ else // something found
+ {
+ printf(" <tr bgcolor=#ffffff>\n"
+ " <td colspan=2>"
+ "Found <b>%d</b> document%s matching your query. ",
+ resultCount,resultCount==1?"":"s");
+
+ if (resultCount>1)
+ printf("Showing best matches first.\n");
+
+ printf(" <br><br>\n");
+ printf(" </td>\n"
+ " </tr>\n");
+
+ const int lpp=20;
+ int numPages = (resultCount+lpp-1)/lpp;
+
+ // clip page
+ if (page<0) page=0;
+ if (page>=numPages) page=numPages-1;
+ int skipEntries = page * lpp;
+ int pageEntries = lpp;
+
+ printf(" <tr><td colspan=2 bgcolor=\"#4040c0\">"
+ "<center><b><font color=\"#ffffff\">Page %d / %d</font></b>"
+ "</center></td></tr>\n",page+1,numPages);
+ printf(" <tr bgcolor=#ffffff>\n"
+ " <td colspan=2>\n"
+ " <dl compact>\n");
+ int i;
+ for (i=0 ; i < resultCount && pageEntries > 0; i++)
+ {
+ if (skipEntries == 0)
+ {
+ SearchDoc *d=docPtrArray[i];
+ FILE *f=d->fileInfo->f;
+ fseek(f,d->fileInfo->refOffset+d->index*4,SEEK_SET);
+ int offset=readInt(f);
+ fseek(f,offset,SEEK_SET);
+ char linkName[MAXSTRLEN];
+ char htmlName[MAXSTRLEN];
+ readString(f,linkName,MAXSTRLEN);
+ readString(f,htmlName,MAXSTRLEN);
+ int rank=(int)(d->rank*100+0.5);
+ if (rank==0) rank++;
+ printf(" <dt><b><font color=#%2x00%2x>%d</font></b>"
+ "<dd><a href=\"%s/%s\">%s</a>\n",
+ rank*2+55, 255-rank*2, rank,
+ d->fileInfo->url, htmlName, linkName);
+ pageEntries--;
+ }
+ else
+ {
+ skipEntries--;
+ }
+ }
+ printf(" </dl>\n"
+ " </td>\n"
+ " </tr>\n"
+ " <tr><td colspan=2 bgcolor=\"#4040c0\"><center>&nbsp;");
+
+ if (page>0)
+ {
+ printf("<a href=\"%s?page=%d&which=%s&what=%s&query=%s\">"
+ "<font color=\"ffffff\">prev</font></a>&nbsp;",
+ cgiBin, page-1,
+ wordOnly?"word":"doc",
+ nameOnly?"name":"string",
+ encQueryInput);
+ }
+ int startPage = page-5 < 0 ? 0 : page-5;
+ int endPage = page+6 > numPages ? numPages : page+5;
+ if (endPage-startPage>1)
+ {
+ for (i=startPage;i<endPage;i++)
+ {
+ if (i!=page)
+ {
+ printf("<a href=\"%s?page=%d&which=%s&what=%s&query=%s\">"
+ "<font color=\"ffffff\">%d</font></a>&nbsp;",
+ cgiBin, i,
+ wordOnly?"word":"doc",
+ nameOnly?"name":"string",
+ encQueryInput, i+1);
+ }
+ else
+ {
+ printf("<b><font color=\"ffffff\">%d</font></b></a>&nbsp;",i+1);
+ }
+ }
+ }
+ if (page<numPages-1)
+ {
+ printf("<a href=\"%s?page=%d&which=%s&what=%s&query=%s\">"
+ "<font color=\"ffffff\">next</font></a>",
+ cgiBin, page+1,
+ wordOnly?"word":"doc",
+ nameOnly?"name":"string",
+ encQueryInput);
+ }
+ printf(" &nbsp;</center></td></tr>\n"
+ " <tr bgcolor=#ffffff>\n"
+ " <td colspan=2><p>\n"
+ " Occurrence count: ");
+ WordInfo *wi=wordList.first;
+ while (wi)
+ {
+ printf("<b><font color=#ff0000>%s</font></b> ",wi->word);
+ if (wi->freq>0) printf("(%d)",wi->freq); else printf("(ignored)");
+ wi=wi->next;
+ if (wi)
+ {
+ if (wi->next) printf(", "); else printf(" and ");
+ }
+ }
+ printf("\n"
+ " </td>\n"
+ " </tr>\n");
+ }
+ printf("</table>\n</center>\n</form>\n");
+ printFooter();
+ free(docPtrArray);
+}
+
+//----------------------------------------------------------------------------
+
+void generateHelpPage()
+{
+ printHeader();
+ printf("<h3>Doxysearch help page</h3>\n"
+ "<b>Basic search instructions</b>\n"
+ "<ul>\n"
+ "Just type in one or more words or fragments of words and press the "
+ "search button. Doxysearch will return a list of functions and class names, "
+ "whose documentation or name matches one or more of the words. "
+ "Documents containing more matches will appear earlier in the list. "
+ "\n"
+ "</ul>\n"
+ "<b>Search modes</b>\n"
+ "<ul>\n"
+ "Doxysearch has four search modes. From least restrictive to most "
+ "restrictive they are:\n"
+ " <ul><p>\n"
+ " <li><em>Search for strings in the documentation:</em>\n"
+ " The words you type will be searched in the documentation as substrings."
+ " Typing the word &quot;<b>the</b>&quot; for example, will find "
+ " documents containing the words &quot;<b>the</b>&quot;, "
+ " &quot;<b>the</b>re&quot;, and &quot;fea<b>the</b>r&quot;.<p>\n"
+ " <li><em>Search for words in the documentation:</em>\n"
+ " The words you type will be searched in the documentation as words."
+ " Typing the word &quot;<b>the</b>&quot; for example, will look "
+ " for documents containing the word &quot;<b>the</b>&quot; and not for"
+ " documents containing the word &quot;<b>the</b>re&quot;.<p>\n"
+ " <li><em>Search for strings in the function and class names:</em>\n"
+ " The words you type will be searched in the function and class names "
+ " as substrings. Typing the word &quot;<b>set</b>&quot; for example, will "
+ " result in a list of links to the documentation of all functions and classes "
+ " that contain the word &quot;<b>set</b>&quot; in the name, such as the function "
+ " <code><b>set</b>Cursor</code>.<p>\n"
+ " <li><em>Search for words in the function and class names:</em>\n"
+ " The words you type will be matched against the function and class names."
+ " The result will be a list of links to the documentation of all function "
+ " and class names that are equal to one of the words.\n"
+ " </ul>\n"
+ "</ul>\n"
+ "<b>Requiring/Excluding words</b>\n"
+ "<ul>\n"
+ " Often you will know a word that will be guaranteed to appear in a document "
+ " for which you are searching. If this is the case, require that the word appears "
+ " in all of the results by attaching a &quot;<b>+</b>&quot; to the beginning of "
+ " the word. You can quickly reject results by adding a word that appears only "
+ " in unwanted documents with a &quot;<b>-</b>&quot; before it."
+ "</ul>\n"
+ );
+
+ printFooter();
+}
+
+//----------------------------------------------------------------------------
+
+void mergeSearchResults(SearchResults *totalResults,
+ SearchResults *sr,int mode)
+{
+ SearchDoc *otd = 0,
+ *td = totalResults->docList,
+ *d = sr->docList;
+ totalResults->totalFreq += sr->totalFreq;
+ if (!d) return; // nothing to add
+ while (td && d)
+ {
+ int otdih = otd ? otd->fileInfo->index : -1,
+ otdil = otd ? otd->index : -1,
+ tdih = td->fileInfo->index,
+ tdil = td->index,
+ dih = d->fileInfo->index,
+ dil = d->index;
+ if (tdih==dih && tdil==dil) // combine results
+ {
+ if (mode != EXCLUDE)
+ {
+ td->rank += d->rank;
+ td->rank *= 2; // put extra emphasis on multiple word matches
+ td->freq += d->freq;
+ d = d->next;
+ otd = td; td = td->next;
+ }
+ else // mode == EXCLUDE => remove entry from results
+ {
+ SearchDoc *tmp=td;
+ td=td->next;
+ if (otd) otd->next=td; else totalResults->docList = td;
+ delete tmp;
+ }
+ }
+ else if ((otdih<dih || (otdih==dih && otdil<dil)) &&
+ (tdih>dih || (tdih==dih && tdil>dil))) // insert
+ {
+ if (mode == NORMAL)
+ {
+ SearchDoc *nd = new SearchDoc(*d);
+ if (otd) otd->next = nd; else totalResults->docList = nd;
+ nd->next = td;
+ td = nd;
+ }
+ d = d->next;
+ }
+ else if (tdih<dih || (tdih==dih && tdil<dil)) // remove or skip
+ {
+ if (mode == INCLUDE)
+ {
+ SearchDoc *tmp=td;
+ td=td->next;
+ if (otd) otd->next=td; else totalResults->docList = td;
+ delete tmp;
+ }
+ else // mode == EXCLUDE or mode == NORMAL
+ {
+ otd = td; td = td->next;
+ }
+ }
+ }
+ if (td==0 && d && mode==NORMAL) // append rest of sr to totalResults
+ {
+ while (d)
+ {
+ SearchDoc *nd = new SearchDoc(*d);
+ if (otd) otd->next = nd; else totalResults->docList = nd;
+ nd->next = 0;
+ d = d->next;
+ otd = nd;
+ }
+ }
+ if (td && d==0 && mode==INCLUDE) // delete the rest of the results
+ {
+ while (td)
+ {
+ SearchDoc *tmp=td;
+ td=td->next;
+ if (otd) otd->next = td; else totalResults->docList = td;
+ delete tmp;
+ }
+ }
+}
+
+//----------------------------------------------------------------------------
+
+int asciiToHex(char c)
+{
+ char l=tolower(c);
+ if (l>='0' && l<='9')
+ return l-'0';
+ else if (l>='a' && l<='f')
+ return l+10-'a';
+ else // invalid hex char
+ return 0;
+}
+
+//----------------------------------------------------------------------------
+
+void fileToBuf(const char *name, char **buf)
+{
+ FILE *f;
+ struct stat file_stats;
+ if ((f=fopen(name,"r"))==NULL) return;
+ if (stat(name,&file_stats)==-1)
+ {
+ message("Error: could not fstat header file %s\n",name);
+ exit(1);
+ }
+ unsigned int len=file_stats.st_size;
+ if ((*buf=(char *)malloc(len+1))==NULL)
+ {
+ message("Error: out of memory\n");
+ exit(1);
+ }
+ if (fread(*buf,1,len,f)!=len)
+ {
+ message("Error: could not read header file %s\n",name);
+ exit(1);
+ }
+ (*buf)[len]='\0';
+ fclose(f);
+}
+
+//----------------------------------------------------------------------------
+
+void getConfig(const char *s)
+{
+ int l;
+ char configFile[MAXSTRLEN];
+ strcpy(configFile,s);
+ strcat(configFile,"/search.cfg");
+
+ FILE *f;
+ if ((f=fopen(configFile,"r"))==NULL)
+ {
+ message("Error: could not open config file %s\n",configFile);
+ exit(1);
+ }
+
+ // get the URL to the documentation
+ fgets(firstDocUrl,MAXSTRLEN,f);
+ l=strlen(firstDocUrl)-1;
+ if (firstDocUrl[l]=='\n') firstDocUrl[l]='\0';
+ l=strlen(firstDocUrl);
+ if (firstDocUrl[l]=='/') firstDocUrl[l]='\0';
+
+ // get the URL to the cgi script
+ fgets(cgiBin,MAXSTRLEN,f);
+ l=strlen(cgiBin)-1;
+ if (cgiBin[l]=='\n') cgiBin[l]='\0';
+
+ fclose(f);
+
+ char headerFile[MAXSTRLEN];
+ strcpy(headerFile,s);
+ strcat(headerFile,"/header.html");
+ fileToBuf(headerFile,&headerBuf);
+
+ char footerFile[MAXSTRLEN];
+ strcpy(footerFile,s);
+ strcat(footerFile,"/footer.html");
+ fileToBuf(footerFile,&footerBuf);
+
+}
+
+//----------------------------------------------------------------------------
+// copy and convert string to lower case
+
+void strlowercpy(char *d,const char *s)
+{
+ while (*s!='\0') *d++=tolower(*s++); *d='\0';
+}
+
+//----------------------------------------------------------------------------
+
+int main(int argc,char **argv)
+{
+#ifdef PROFILING
+ struct timeval tv_start,tv_end;
+ gettimeofday(&tv_start,0);
+#endif
+ char *argString=getenv("QUERY_STRING");
+ if (argc==1)
+ {
+ message("Error: invalid number of arguments. "
+ "Usage: %s doc_path [doc_path ...]",argv[0]);
+ exit(1);
+ }
+ // read the configuration file for this instance of the search engine
+ getConfig(argv[1]);
+
+ if (!argString)
+ {
+ printHeader();
+ printSearchPage();
+ printFooter();
+ exit(1);
+ }
+
+ SearchResults tsr;
+
+ // parse cgi arguments
+ char *arg=strtok(argString,"&");
+ char *query = 0;
+ char *what = 0;
+ char *which = 0;
+ char *help = 0;
+ page = 0;
+ while (arg)
+ {
+ int namelen=strcspn(arg,"=");
+ if (!strncmp(arg,"query", namelen)) query = &arg[namelen+1];
+ else if (!strncmp(arg,"what", namelen)) what = &arg[namelen+1];
+ else if (!strncmp(arg,"which", namelen)) which = &arg[namelen+1];
+ else if (!strncmp(arg,"help", namelen)) help = &arg[namelen+1];
+ else if (!strncmp(arg,"page", namelen)) page = atoi(&arg[namelen+1]);
+ arg=strtok(0,"&");
+ }
+
+ wordOnly=which ? strcmp(which,"word")==0 : FALSE;
+ nameOnly=what ? strcmp(what, "name")==0 : FALSE;
+ helpOnly=help ? strcmp(help, "on" )==0 : FALSE;
+
+ // store encoded query string
+ if (query) strcpy(encQueryInput,query); else encQueryInput[0]='\0';
+
+ // convert query string to original input
+ char *s=query,*d=queryInput;
+ if (s)
+ {
+ while (*s!='\0')
+ {
+ char c=*s++;
+ if (c=='+')
+ *d++=' ';
+ else if (c=='%')
+ *d++=asciiToHex(*s++)*16+asciiToHex(*s++);
+ else
+ *d++=c;
+ }
+ }
+ *d='\0';
+
+ if (helpOnly)
+ {
+ generateHelpPage();
+ exit(1);
+ }
+
+ // read search index files
+ int argIndex=0;
+ for (argIndex=1;argIndex<argc;argIndex++)
+ {
+ char configFile[MAXSTRLEN];
+ strcpy(configFile,argv[argIndex]);
+ strcat(configFile,"/search.cfg");
+
+ char indexFile[MAXSTRLEN];
+ strcpy(indexFile,argv[argIndex]);
+ strcat(indexFile,"/search.idx");
+
+ FileInfo *fi=fileList.add();
+ FILE *g;
+
+ if ((fi->f=fopen(indexFile,"r"))==NULL)
+ {
+ message("Error: could not open index file %s\n",indexFile);
+ exit(1);
+ }
+ if ((g=fopen(configFile,"r"))==NULL)
+ {
+ message("Error: could not open config file %s\n",configFile);
+ exit(1);
+ }
+
+ // get URL to the documentation
+ char tmp[MAXSTRLEN];
+ fgets(tmp,MAXSTRLEN,g);
+ if (tmp[strlen(tmp)-1]=='\n') tmp[strlen(tmp)-1]='\0';
+ if (tmp[strlen(tmp)-1]=='/') tmp[strlen(tmp)-1]='\0';
+ fi->url = new char[strlen(tmp)+1];
+ strcpy(fi->url,tmp);
+ fclose(g);
+
+ // read & check the format of the search index file
+ fseek(fi->f,0,SEEK_SET);
+ char header[5];
+ if (fread(header,1,4,fi->f)!=4)
+ {
+ message("Error: Couldn't read header of the index file %s\n",indexFile);
+ exit(1);
+ }
+ header[4]='\0';
+ if (strcmp(header,"DOXI"))
+ {
+ message("Error: Index file %s has an unknown format\n",indexFile);
+ exit(1);
+ }
+ // read and store the offset to the link index
+ fi->refOffset=readInt(fi->f);
+ }
+
+ char *word;
+ char wordString[MAXSTRLEN];
+
+ // search for included words
+ strlowercpy(wordString,queryInput);
+ word=strtok(wordString," ");
+ bool first=TRUE;
+ while (word)
+ {
+ if (word[0]=='+') // + character => include
+ {
+ SearchResults sr;
+ searchIndex(&word[1],&sr);
+ if (first)
+ mergeSearchResults(&tsr,&sr,NORMAL);
+ else
+ mergeSearchResults(&tsr,&sr,INCLUDE);
+ first=FALSE;
+ }
+ word=strtok(0," ");
+ }
+
+ // search for normal words
+ strlowercpy(wordString,queryInput);
+ word=strtok(wordString," ");
+ while (word)
+ {
+ if (word[0]!='-' && word[0]!='+') // normal word
+ {
+ SearchResults sr;
+ searchIndex(word,&sr);
+ mergeSearchResults(&tsr,&sr,NORMAL);
+ }
+ word=strtok(0," ");
+ }
+
+ // search for excluded words
+ strlowercpy(wordString,queryInput);
+ word=strtok(wordString," ");
+ while (word)
+ {
+ if (word[0]=='-') // - character => exclude
+ {
+ SearchResults sr;
+ searchIndex(&word[1],&sr);
+ mergeSearchResults(&tsr,&sr,EXCLUDE);
+ }
+ word=strtok(0," ");
+ }
+
+ // write results to HTML page
+ generateResults(&tsr);
+
+ free(headerBuf);
+ free(footerBuf);
+
+#ifdef PROFILING
+ gettimeofday(&tv_end,0);
+ printf("processing time %3.3f msec\n",
+ ((tv_end.tv_sec-tv_start.tv_sec)*1000000+
+ tv_end.tv_usec-tv_start.tv_usec)/1000.0
+ );
+#endif
+ return 0;
+}
diff --git a/src/doxysearch.pro b/src/doxysearch.pro
new file mode 100644
index 0000000..ab34adc
--- /dev/null
+++ b/src/doxysearch.pro
@@ -0,0 +1,18 @@
+#
+# $Id$
+#
+# Copyright (C) 1997-1999 by Dimitri van Heesch.
+#
+# Permission to use, copy, modify, and distribute this software and its
+# documentation under the terms of the GNU General Public License is hereby
+# granted. No representations are made about the suitability of this software
+# for any purpose. It is provided "as is" without express or implied warranty.
+# See the GNU General Public License for more details.
+#
+# All output generated with Doxygen is not covered by this license.
+
+TEMPLATE = app.t
+CONFIG = console warn_on release
+SOURCES = doxysearch.cpp
+TARGET = ../bin/doxysearch
+OBJECTS_DIR = ../objects
diff --git a/src/doxytag.l b/src/doxytag.l
new file mode 100644
index 0000000..4f9fac1
--- /dev/null
+++ b/src/doxytag.l
@@ -0,0 +1,634 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+%{
+/*
+ * includes
+ */
+#include <stdio.h>
+#include <iostream.h>
+#include <assert.h>
+#include <ctype.h>
+
+#include <qstring.h>
+#include <qstrlist.h>
+#include <qfileinf.h>
+#include <qfile.h>
+#include <qdict.h>
+#include <qtstream.h>
+#include <qdir.h>
+
+#include "version.h"
+#include "suffixtree.h"
+#include "searchindex.h"
+#include "logos.h"
+
+struct MemberDef
+{
+ QString name;
+ QString anchor;
+ QString args;
+};
+
+struct ClassDef
+{
+ QString name;
+ QStrList bases;
+ QString fileName;
+ bool isFile;
+ QList<MemberDef> memberList;
+};
+
+QList<ClassDef> classList;
+QDict<ClassDef> classDict(1009);
+QList<ClassDef> fileList;
+QDict<ClassDef> fileDict(1009);
+
+static bool genTag;
+static bool genIndex;
+
+static QStrList bases;
+static QString inputString;
+static int inputPosition;
+static QString yyFileName;
+static int yyLineNr;
+static QString classFile;
+static QString memberRef;
+static QString memberName;
+static QString memberArgs;
+static QString className;
+//static bool newClass;
+static QString docBaseLink;
+static QString docAnchor;
+static QString docRefName;
+static bool nameBug;
+static SearchIndex searchIndex;
+
+#define YY_NEVER_INTERACTIVE 1
+
+/* -----------------------------------------------------------------
+ */
+#undef YY_INPUT
+#define YY_INPUT(buf,result,max_size) result=yyread(buf,max_size);
+
+static int yyread(char *buf,int max_size)
+{
+ int c=0;
+ while( c < max_size && inputString[inputPosition] )
+ {
+ *buf = inputString[inputPosition++] ;
+ c++; buf++;
+ }
+ return c;
+}
+
+static void addClass(const char *clName)
+{
+ if (classDict[clName]==0)
+ {
+ ClassDef *cd=new ClassDef;
+ cd->name=clName;
+ cd->fileName=yyFileName;
+ cd->isFile=FALSE;
+ classList.append(cd);
+ classDict.insert(clName,cd);
+ }
+}
+
+static void addFile(const char *fName)
+{
+ if (classDict[fName]==0)
+ {
+ ClassDef *fd=new ClassDef;
+ fd->name=fName;
+ fd->fileName=yyFileName;
+ fd->isFile=TRUE;
+ classList.append(fd);
+ classDict.insert(fName,fd);
+ }
+}
+
+static void addBases(const char *clName)
+{
+ ClassDef *cd=0;
+ if (clName && (cd=classDict[clName])) cd->bases=bases;
+}
+
+static void addMember(const char *memName,const char *memRef,const char *memArgs)
+{
+ ClassDef *cd=classList.last();
+ MemberDef *md;
+ md=new MemberDef;
+ md->name=memName;
+ md->anchor=memRef;
+ md->args=memArgs;
+ cd->memberList.append(md);
+}
+
+static void addReference()
+{
+ //printf("addReference() key: %s ref:%s\n",
+ // docRefName.data(),(docBaseLink+"#"+docAnchor).data());
+ if (genIndex && docRefName.length()>0 && docBaseLink.length()>0)
+ {
+ if (docAnchor.length()==0)
+ searchIndex.addReference(docRefName,docBaseLink);
+ else
+ searchIndex.addReference(docRefName,docBaseLink+"#"+docAnchor);
+ searchIndex.addWord(docRefName,docRefName,TRUE);
+ }
+}
+
+QString unhtmlify(const char *str)
+{
+ QString result;
+ const char *p=str;
+ char c;
+ while ((c=*p)!='\0')
+ {
+ if (c!='&') { result+=c; p++; }
+ else
+ {
+ if (strncmp(p,"&amp;",5)==0) { result+='&'; p+=5; }
+ else if (strncmp(p,"&lt;",4)==0) { result+='<'; p+=4; }
+ else if (strncmp(p,"&gt;",4)==0) { result+='>'; p+=4; }
+ else /* should not happen */ { result+='&'; p++; }
+ }
+ }
+ return result;
+}
+
+%}
+
+%x Start
+%x SearchClassFile
+%x ReadClassFile
+%x CheckClassName
+%x ReadClassName
+%x SearchMemberRef
+%x ReadMemberRef
+%x SearchMemberName
+%x ReadMemberName
+%x ReadOperator
+%x SearchBaseClasses
+%x ReadBaseClass
+%x SearchRefName
+%x ReadRefName
+%x SearchArgs
+%x ReadArgs
+%x SearchWords
+%x SkipHTMLTag
+%x CheckConstructor
+%x SkipPreformated
+
+%%
+
+<Start>^"<li>" {
+ BEGIN( SearchClassFile );
+ }
+<Start>^"<h1 align=center>" { // Qt variant
+ BEGIN( ReadClassName );
+ }
+<Start>^"<h1>" { // Doxygen variant
+ BEGIN( ReadClassName );
+ }
+<Start>^"Inherits " {
+ //printf("Inherits found\n");
+ BEGIN( SearchBaseClasses );
+ }
+<Start>^"<h3 class=\"fn\">"/[a-z_A-Z0-9] { // needed due to inconsistency in the Qt docs
+ BEGIN( CheckConstructor );
+ }
+<Start>"<pre>" {
+ BEGIN( SkipPreformated );
+ }
+<Start>"<a name=\"" {
+ BEGIN( SearchWords );
+ }
+<Start>"<" {
+ BEGIN( SkipHTMLTag );
+ }
+<Start>"&"[a-zA-Z]+";"
+<Start>[a-z_A-Z][a-z_A-Z0-9]* {
+ //printf("tag: %s#%s ref: %s word: `%s'\n",
+ // docBaseLink.data(),docAnchor.data(),
+ // docRefName.data(),yytext);
+ if (genIndex && docRefName.length()>0 && yyleng>2)
+ searchIndex.addWord(docRefName,
+ yytext,FALSE
+ );
+ }
+<SkipPreformated>"</pre>" {
+ BEGIN( Start );
+ }
+<SkipPreformated>[^\<]+
+<CheckConstructor>[a-z_A-Z0-9~:]+ {
+ QString s=yytext;
+ if (s.find("::")!=-1)
+ {
+ docRefName=yytext;
+ addReference();
+ nameBug=TRUE;
+ }
+ else
+ {
+ nameBug=FALSE;
+ }
+ BEGIN( Start );
+ }
+<SearchWords>[a-z_A-Z0-9]+ {
+ docAnchor = yytext;
+ if (docAnchor=="details")
+ {
+ docRefName=className.copy();
+ addReference();
+ BEGIN( Start );
+ }
+ else
+ {
+ BEGIN( SearchRefName );
+ }
+ }
+<SearchRefName>"\" doxytag=\"" {
+ BEGIN( ReadRefName );
+ }
+<SearchRefName>"\"></a>" {
+ if (nameBug)
+ BEGIN( Start );
+ else
+ BEGIN( ReadRefName );
+ }
+
+<ReadRefName>[a-z_A-Z0-9:\.\+\-]*"operator"[ \t]*("new"|"delete"|("&amp;"("&amp"|"=")*)|("&gt;"("&gt;"|"=")*)|("&lt;"("&lt;"|"=")*)|("-&gt;"[*]*)|[+\-*%/|~!=,\^]|[+\-*%/\^!|~=\[(][=|+\-\])]) { // hmm, looks impressive :-)
+ docRefName=unhtmlify(yytext);
+ addReference();
+ BEGIN( Start );
+ }
+<ReadRefName>[a-z_A-Z0-9~:\.\+\-]+ {
+ //printf("ReadRef=%s\n",yytext);
+ docRefName=yytext;
+ addReference();
+ BEGIN( Start );
+ }
+<SearchBaseClasses>"<a "[a-z_A-Z0-9 .:\=\"\-\+\/\@]+">" {
+ //printf("Search %s\n",yytext);
+ BEGIN( ReadBaseClass );
+ }
+<SearchBaseClasses>\n {
+ addBases(className);
+ BEGIN( Start );
+ }
+<ReadBaseClass>[a-z_A-Z0-9]+ {
+ bases.append(yytext);
+ BEGIN( SearchBaseClasses );
+ }
+<SearchClassFile>"<a class=\"el\" href=\"" {
+ BEGIN( ReadClassFile );
+ }
+<SearchClassFile>"<a href=\"" {
+ BEGIN( ReadClassFile );
+ }
+<ReadClassName>[a-z_A-Z0-9:\.\-\+]+ {
+ className=yytext;
+ BEGIN( CheckClassName);
+ }
+<CheckClassName>"Class Reference" {
+ //printf("className=%s\n",className.data());
+ addClass(className);
+ BEGIN( Start );
+ }
+<CheckClassName>"File Reference" {
+ //printf("className=%s\n",className.data());
+ addFile(className);
+ BEGIN( Start );
+ }
+<CheckClassName>[a-z_A-Z0-9]+ { // not a class file
+ className.resize(0);
+ BEGIN( Start );
+ }
+<ReadClassFile>[a-z_A-Z0-9.\-\+]+ {
+ classFile=yytext;
+ BEGIN( SearchMemberRef );
+ }
+<SearchMemberRef>"#" {
+ BEGIN( ReadMemberRef );
+ }
+<ReadMemberRef>[a-z_A-Z0-9]+ {
+ memberRef=yytext;
+ BEGIN( SearchMemberName );
+ }
+<SearchMemberName>"<strong>" {
+ BEGIN( ReadMemberName );
+ }
+<SearchMemberName>[a-z_A-Z~] {
+ unput(*yytext);
+ BEGIN( ReadMemberName );
+ }
+<ReadMemberName>"operator" {
+ memberName="operator";
+ BEGIN( ReadOperator );
+ }
+<ReadOperator>[+\-*/%\^&|~!=()\[\]] { memberName+=*yytext; }
+<ReadOperator>"&lt;" { memberName+="<"; }
+<ReadOperator>"&gt;" { memberName+=">"; }
+<ReadOperator>"new" { memberName+=" new"; }
+<ReadOperator>"delete" { memberName+=" delete"; }
+<ReadOperator>"<" { BEGIN( SearchArgs ); }
+<ReadMemberName>[a-z_A-Z0-9]+ {
+ memberName=yytext;
+ BEGIN( SearchArgs );
+ }
+<SearchArgs>"</a>" {
+ //printf("SearchArg className=%s memberName=%s\n",className.data(),memberName.data());
+ if (className.length()>0 && memberName.length()>0)
+ BEGIN( ReadArgs );
+ else
+ BEGIN( Start );
+ }
+<ReadArgs>"&amp;" { memberArgs+="&"; }
+<ReadArgs>"&lt;" { memberArgs+="<"; }
+<ReadArgs>"&gt;" { memberArgs+=">"; }
+ /*
+<ReadArgs>[{}] { // handle enums
+ memberArgs.resize(0);
+ addMember(memberName,memberRef,memberArgs);
+ if (*yytext=='}')
+ BEGIN( Start );
+ else
+ BEGIN( SearchClassFile );
+ }
+ */
+<ReadArgs>"<"|"\n" {
+ //printf("adding member %s\n",memberName.data());
+ memberArgs=memberArgs.stripWhiteSpace();
+ //if (newClass)
+ //{
+ // newClass=FALSE;
+ // addClass(className);
+ //}
+ addMember(memberName,memberRef,memberArgs);
+ memberArgs.resize(0);
+ if (*yytext=='<')
+ BEGIN( SkipHTMLTag);
+ else
+ BEGIN( Start );
+ }
+<ReadArgs>. { memberArgs+=(*yytext)&0x7f; }
+<SkipHTMLTag>">" { BEGIN( Start ); }
+<SkipHTMLTag>[a-zA-Z]+
+<*>.
+<*>\n { yyLineNr++;
+ if (YY_START!=SkipHTMLTag) BEGIN( Start );
+ }
+
+%%
+
+/*@ ----------------------------------------------------------------------------
+ */
+
+
+void parse(QString &s)
+{
+ bases.clear();
+ nameBug = FALSE;
+ //newClass = TRUE;
+ inputString = s;
+ inputPosition = 0;
+ yyLineNr = 0;
+ tagYYrestart( tagYYin );
+ BEGIN( Start );
+ tagYYlex();
+ //printf("Number of lines scanned: %d\n",yyLineNr);
+}
+
+void parseFile(QFileInfo &fi)
+{
+ fprintf(stderr,"Parsing file %s...\n",fi.fileName().data());
+ QFile f(fi.absFilePath());
+ if (f.open(IO_ReadOnly))
+ {
+ yyFileName = fi.fileName();
+ className.resize(0);
+ memberName.resize(0);
+ //printf("Parsing file %s...\n",fi.fileName().data());
+ QString input(fi.size()+1);
+ docBaseLink=fi.fileName();
+ docRefName=fi.fileName().copy();
+ searchIndex.addReference(docRefName,docBaseLink);
+ searchIndex.addWord(docRefName,docRefName,TRUE);
+ f.readBlock(input.data(),fi.size());
+ input.at(fi.size())='\0';
+ parse(input);
+ }
+ else
+ {
+ fprintf(stderr,"Warning: Cannot open file %s\n",fi.fileName().data());
+ }
+}
+
+void parseFileOrDir(const char *fileName)
+{
+ QFileInfo fi(fileName);
+ if (fi.exists())
+ {
+ if (fi.isFile())
+ {
+ parseFile(fi);
+ }
+ else if (fi.isDir())
+ {
+ QDir dir(fileName);
+ dir.setFilter( QDir::Files );
+ dir.setNameFilter( "*.html" );
+ const QFileInfoList *list = dir.entryInfoList();
+ QFileInfoListIterator it( *list );
+ QFileInfo *cfi;
+ for ( it.toFirst() ; (cfi=it.current()) ; ++it)
+ {
+ if (cfi->isFile())
+ {
+ parseFile(*cfi);
+ }
+ }
+ }
+ }
+ else
+ {
+ fprintf(stderr,"Warning: File %s does not exist\n",fileName);
+ }
+}
+
+void usage(const char *name)
+{
+ fprintf(stderr,"Doxytag version %s\nCopyright Dimitri van Heesch 1997-1999\n\n",
+ versionString);
+ fprintf(stderr," Generates a tag file and/or a search index for a set of HTML files\n\n");
+ fprintf(stderr,"Usage: %s [-t tag_file] [-s index_file] [ html_file [html_file...] ]\n",name);
+ fprintf(stderr,"Options:\n");
+ fprintf(stderr," -t <tag_file> Generate tag file <tag_file>.\n");
+ fprintf(stderr," -s <index_file> Generate search index <index_file>.\n\n");
+ fprintf(stderr,"If no HTML files are given all files in the current dir that\n"
+ "have a .html extension are parsed.\n\n");
+ exit(1);
+}
+
+const char *getArg(int argc,char **argv,int &optind,const char c)
+{
+ char *s=0;
+ if (strlen(&argv[optind][2])>0)
+ s=&argv[optind][2];
+ else if (optind+1<argc)
+ s=argv[++optind];
+ else
+ {
+ fprintf(stderr,"option -%c requires an argument\n",c);
+ exit(1);
+ }
+ return s;
+}
+
+int main(int argc,char **argv)
+{
+ QString tagName;
+ QString indexName;
+
+ int optind=1;
+ const char *arg;
+ while (optind<argc && argv[optind][0]=='-')
+ {
+ switch(argv[optind][1])
+ {
+ case 't':
+ arg=getArg(argc,argv,optind,'t');
+ tagName=arg;
+ break;
+ case 's':
+ arg=getArg(argc,argv,optind,'s');
+ indexName=arg;
+ break;
+ case 'h':
+ case '?':
+ usage(argv[0]);
+ break;
+ default:
+ fprintf(stderr,"Unknown option -%c\n",argv[optind][1]);
+ usage(argv[0]);
+ }
+ optind++;
+ }
+
+ genTag = tagName.length()>0;
+ genIndex = indexName.length()>0;
+
+ if (!genTag && !genIndex)
+ {
+ fprintf(stderr,"Nothing to do !\n\n");
+ usage(argv[0]);
+ }
+
+ int i;
+ if (optind>=argc)
+ {
+ parseFileOrDir(".");
+ }
+ else
+ {
+ for (i=optind;i<argc;i++)
+ {
+ parseFileOrDir(argv[i]);
+ }
+ }
+ if (genIndex)
+ {
+ printf("Writing search index\n");
+ if (!searchIndex.saveIndex(indexName))
+ {
+ fprintf(stderr,"Error: Could not write search index\n");
+ }
+ QFileInfo fi(indexName);
+ if (fi.exists())
+ {
+ QString dir=fi.dir().absPath();
+ fi.setFile(dir+"/search.gif");
+ if (!fi.exists()) writeSearchButton(dir);
+ fi.setFile(dir+"/doxygen.gif");
+ if (!fi.exists()) writeLogo(dir);
+ fi.setFile(dir+"/search.cgi");
+ if (!fi.exists())
+ {
+ QFile f(dir+"/search.cgi");
+ if (f.open(IO_WriteOnly))
+ {
+ QTextStream t(&f);
+ t << "#!/bin/sh" << endl
+ << "DOXYSEARCH=" << endl
+ << "DOXYPATH=" << endl
+ << "if [ -f $DOXYSEARCH ]" << endl
+ << "then" << endl
+ << " $DOXYSEARCH $DOXYPATH" << endl
+ << "else" << endl
+ << " echo \"Content-Type: text/html\"" << endl
+ << " echo \"\"" << endl
+ << " echo \"<H1>Error: $DOXYSEARCH not found. Check cgi script!\"" << endl
+ << "fi" << endl;
+ f.close();
+ }
+ else
+ {
+ fprintf(stderr,"Error: could not open file %s for writing\n",(dir+"/search.cgi").data());
+ }
+ }
+ }
+ }
+ if (genTag)
+ {
+ QFile f(tagName);
+ if (f.open(IO_WriteOnly))
+ {
+ QTextStream t(&f);
+ ClassDef *cd=classList.first();
+ while (cd)
+ {
+ if (cd->isFile) t << "&"; else t << ">";
+ t << cd->name << ":";
+ char *base=cd->bases.first();
+ while (base)
+ {
+ t << base << "?";
+ base=cd->bases.next();
+ }
+ if (!cd->isFile) t << " \"" << cd->fileName << "\"";
+ t << endl;
+ MemberDef *md=cd->memberList.first();
+ while (md)
+ {
+ t << md->name << " " << md->anchor << " \"" << md->args << "\"" << endl;
+ md=cd->memberList.next();
+ }
+ cd=classList.next();
+ }
+ }
+ else
+ {
+ fprintf(stderr,"Error: Could not write tag file %s\n",tagName.data());
+ }
+ }
+ return 0;
+}
+
+extern "C" {
+int tagYYwrap() { return 1 ; }
+};
diff --git a/src/doxytag.pro b/src/doxytag.pro
new file mode 100644
index 0000000..3389c00
--- /dev/null
+++ b/src/doxytag.pro
@@ -0,0 +1,24 @@
+#
+# $Id$
+#
+# Copyright (C) 1997-1999 by Dimitri van Heesch.
+#
+# Permission to use, copy, modify, and distribute this software and its
+# documentation under the terms of the GNU General Public License is hereby
+# granted. No representations are made about the suitability of this software
+# for any purpose. It is provided "as is" without express or implied warranty.
+# See the GNU General Public License for more details.
+#
+# All output generated with Doxygen is not covered by this license.
+#
+# TMake project file for doxytag
+
+TEMPLATE = doxytag.t
+CONFIG = console warn_on qt release
+HEADERS = suffixtree.h searchindex.h logos.h version.h
+SOURCES = doxytag.cpp suffixtree.cpp searchindex.cpp \
+ logos.cpp version.cpp
+TARGET = ../bin/doxytag
+win32:INCLUDEPATH += .
+#unix:INCLUDEPATH += /usr/include
+OBJECTS_DIR = ../objects
diff --git a/src/doxytag.t b/src/doxytag.t
new file mode 100644
index 0000000..1ee8ec5
--- /dev/null
+++ b/src/doxytag.t
@@ -0,0 +1,49 @@
+#
+# $Id$
+#
+# Copyright (C) 1997-1999 by Dimitri van Heesch.
+#
+# Permission to use, copy, modify, and distribute this software and its
+# documentation under the terms of the GNU General Public License is hereby
+# granted. No representations are made about the suitability of this software
+# for any purpose. It is provided "as is" without express or implied warranty.
+# See the GNU General Public License for more details.
+#
+# All output generated with Doxygen is not covered by this license.
+#
+#!
+#! doxytag.t: This is a custom template for building Doxytag
+#!
+#$ IncludeTemplate("app.t");
+
+LEX = flex
+
+#${
+sub GenerateDep {
+ my($obj,$src,$dep) = @_;
+ my(@objv,$srcv,$i,$s,$o,$d,$c);
+ @objv = split(/\s+/,$obj);
+ @srcv = split(/\s+/,$src);
+ for $i ( 0..$#objv ) {
+ $s = $srcv[$i];
+ $o = $objv[$i];
+ next if $s eq "";
+ $text .= $o . ": " . $s;
+ $text .= " ${linebreak}\n\t\t" . $dep if $dep ne "";
+ if ( $moc_output{$s} ne "" ) {
+ $text .= " ${linebreak}\n\t\t" . $moc_output{$s};
+ }
+ $d = &make_depend($s);
+ $text .= " ${linebreak}\n\t\t" . $d if $d ne "";
+ $text .= "\n";
+ }
+ chop $text;
+}
+#$}
+
+#####################
+
+#$ GenerateDep("doxytag.cpp","doxytag.l");
+ $(LEX) -PtagYY -t doxytag.l >doxytag.cpp
+
+
diff --git a/src/entry.cpp b/src/entry.cpp
new file mode 100644
index 0000000..2520fa3
--- /dev/null
+++ b/src/entry.cpp
@@ -0,0 +1,242 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#include "entry.h"
+
+static int newCount=0;
+
+Entry::Entry()
+{
+ num=newCount++;
+ //printf("New Entry %d\n",num);
+ parent=0;
+ sublist = new QList<Entry>;
+ sublist->setAutoDelete(TRUE);
+ extends = new QList<BaseInfo>;
+ extends->setAutoDelete(TRUE);
+ groups = new QList<QString>;
+ groups->setAutoDelete(TRUE);
+ argList = new ArgumentList;
+ argList->setAutoDelete(TRUE);
+ //printf("Entry::Entry() tArgList=0\n");
+ tArgList = 0;
+ reset();
+}
+
+Entry::Entry(const Entry &e)
+{
+ num=newCount++;
+ //printf("Copy New Entry %d\n",num);
+ section = e.section;
+ protection = e.protection;
+ sig = e.sig;
+ slot = e.slot;
+ stat = e.stat;
+ virt = e.virt;
+ parent = e.parent;
+ type = e.type.copy();
+ name = e.name.copy();
+ args = e.args.copy();
+ exception = e.exception.copy();
+ program = e.program.copy();
+ includeFile = e.includeFile.copy();
+ includeName = e.includeFile.copy();
+ doc = e.doc.copy();
+ relates = e.relates.copy();
+ brief = e.brief.copy();
+ inside = e.inside.copy();
+ fileName = e.fileName.copy();
+ startLine = e.startLine;
+ sublist = new QList<Entry>;
+ sublist->setAutoDelete(TRUE);
+ extends = new QList<BaseInfo>;
+ extends->setAutoDelete(TRUE);
+ groups = new QList<QString>;
+ groups->setAutoDelete(TRUE);
+ argList = new ArgumentList;
+ argList->setAutoDelete(TRUE);
+ //printf("Entry::Entry(copy) tArgList=0\n");
+ tArgList = 0;
+
+ // deep copy of the child entry list
+ QListIterator<Entry> eli(*e.sublist);
+ Entry *cur;
+ for (;(cur=eli.current());++eli)
+ {
+ sublist->append(new Entry(*cur));
+ }
+
+ // deep copy base class list
+ QListIterator<BaseInfo> bli(*e.extends);
+ BaseInfo *bi;
+ for (;(bi=bli.current());++bli)
+ {
+ extends->append(new BaseInfo(*bi));
+ }
+
+ // deep copy group list
+ QListIterator<QString> sli(*e.groups);
+ QString *s;
+ for (;(s=sli.current());++sli)
+ {
+ groups->append(new QString(*s));
+ }
+
+ // deep copy argument list
+ QListIterator<Argument> ali(*e.argList);
+ Argument *a;
+ for (;(a=ali.current());++ali)
+ {
+ argList->append(new Argument(*a));
+ }
+ argList->constSpecifier = e.argList->constSpecifier;
+ argList->volatileSpecifier = e.argList->volatileSpecifier;
+ argList->pureSpecifier = e.argList->pureSpecifier;
+
+ // deep copy template argument list
+ if (e.tArgList)
+ {
+ tArgList = new ArgumentList;
+ tArgList->setAutoDelete(TRUE);
+ //printf("Entry::Entry(copy) new tArgList=%p\n",tArgList);
+ QListIterator<Argument> tali(*e.tArgList);
+ for (;(a=tali.current());++tali)
+ {
+ tArgList->append(new Argument(*a));
+ //printf("appending argument %s %s\n",a->type.data(),a->name.data());
+ }
+ }
+}
+
+Entry::~Entry()
+{
+ //printf("Deleting entry %d name %s type %x chilren %d\n",
+ // num,name.data(),section,sublist->count());
+ delete sublist;
+ delete extends;
+ delete groups;
+ delete argList;
+ //printf("Entry::~Entry() tArgList=%p\n",tArgList);
+ delete tArgList;
+}
+
+void Entry::addSubEntry(Entry *current)
+{
+ //printf("Entry %d with name %s type 0x%x added\n",
+ // current->num,current->name.data(),current->section);
+ //printf("Entry::addSubEntry(%s) %p\n",current->name.data(),current->tArgList);
+ current->parent=this;
+ sublist->append(current);
+
+ //if (current->tArgList)
+ //{
+ // Argument * a=current->tArgList->first();
+ // while (a)
+ // {
+ // printf("type=%s name=%s\n",a->type.data(),a->name.data());
+ // a=current->tArgList->next();
+ // }
+ //}
+
+}
+
+void Entry::reset()
+{
+ name.resize(0);
+ type.resize(0);
+ args.resize(0);
+ exception.resize(0);
+ program.resize(0);
+ includeFile.resize(0);
+ includeName.resize(0);
+ doc.resize(0);
+ relates.resize(0);
+ brief.resize(0);
+ inside.resize(0);
+ fileName.resize(0);
+ section = EMPTY_SEC;
+ sig = FALSE;
+ virt = Normal;
+ slot = FALSE;
+ stat = FALSE;
+ proto = FALSE;
+ protection = Public;
+ sublist->clear();
+ extends->clear();
+ groups->clear();
+ argList->clear();
+ if (tArgList) { delete tArgList; tArgList=0; }
+}
+
+
+int Entry::getSize()
+{
+ int size=sizeof(Entry);
+ size+=type.length()+1;
+ size+=name.length()+1;
+ size+=args.length()+1;
+ size+=exception.length()+1;
+ size+=program.length()+1;
+ size+=includeFile.length()+1;
+ size+=includeName.length()+1;
+ size+=doc.length()+1;
+ size+=relates.length()+1;
+ size+=brief.length()+1;
+ size+=inside.length()+1;
+ size+=fileName.length()+1;
+ BaseInfo *bi=extends->first();
+ while (bi)
+ {
+ size+=sizeof(QLNode);
+ size+=bi->name.length()+1+sizeof(bi->prot)+sizeof(bi->virt);
+ bi=extends->next();
+ }
+ QString *s=groups->first();
+ while (s)
+ {
+ size+=sizeof(QLNode);
+ size+=s->length()+1;
+ s=groups->next();
+ }
+ Entry *e=sublist->first();
+ while (e)
+ {
+ size+=e->getSize();
+ e=sublist->next();
+ }
+ Argument *a=argList->first();
+ while (e)
+ {
+ size+=sizeof(Argument);
+ size+=a->type.length()+1
+ +a->name.length()+1
+ +a->defval.length()+1;
+ a=argList->next();
+ }
+ if (tArgList)
+ {
+ a=tArgList->first();
+ while (e)
+ {
+ size+=sizeof(Argument);
+ size+=a->type.length()+1
+ +a->name.length()+1
+ +a->defval.length()+1;
+ a=tArgList->next();
+ }
+ }
+ return size;
+}
diff --git a/src/entry.h b/src/entry.h
new file mode 100644
index 0000000..40624d8
--- /dev/null
+++ b/src/entry.h
@@ -0,0 +1,153 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#ifndef ENTRY_H
+#define ENTRY_H
+
+#include <qstring.h>
+#include <qlist.h>
+
+enum Protection { Public, Protected, Private } ;
+enum Specifier { Normal, Virtual, Pure } ;
+
+struct BaseInfo
+{
+ BaseInfo(const char *n,Protection p,Specifier v) : name(n),prot(p),virt(v) {}
+ QString name; // the name of the base class
+ Protection prot; // inheritance type
+ Specifier virt; // virtualness
+};
+
+struct Argument
+{
+ Argument() {}
+ Argument(const Argument &a)
+ {
+ type=a.type.copy();
+ name=a.name.copy();
+ defval=a.defval.copy();
+ }
+ Argument &operator=(const Argument &a)
+ {
+ if (this!=&a)
+ {
+ type=a.type.copy();
+ name=a.name.copy();
+ defval=a.defval.copy();
+ }
+ return *this;
+ }
+
+ QString type; // argument type
+ QString name; // argument name (if any)
+ QString defval; // argument default value (if any)
+};
+
+class ArgumentList : public QList<Argument>
+{
+ public:
+ ArgumentList() : QList<Argument>(),
+ constSpecifier(FALSE),
+ volatileSpecifier(FALSE),
+ pureSpecifier(FALSE) {}
+ bool constSpecifier;
+ bool volatileSpecifier;
+ bool pureSpecifier;
+};
+
+typedef QListIterator<Argument> ArgumentListIterator;
+
+class Entry
+{
+ public:
+
+ enum Sections {
+ CLASS_SEC = 0x00000001,
+ STRUCT_SEC = 0x00000002,
+ UNION_SEC = 0x00000004,
+ ENUM_SEC = 0x00000008,
+ EMPTY_SEC = 0x00000010,
+ PAGEDOC_SEC = 0x00000020,
+ VARIABLE_SEC = 0x00000040,
+ FUNCTION_SEC = 0x00000080,
+ TYPEDEF_SEC = 0x00000100,
+ CLASSDOC_SEC = 0x00000200,
+ MEMBERDOC_SEC = 0x00000400,
+ OVERLOADDOC_SEC = 0x00000800,
+ EXAMPLE_SEC = 0x00001000,
+ VARIABLEDOC_SEC = 0x00002000,
+ ENUMDOC_SEC = 0x00004000,
+ UNIONDOC_SEC = 0x00008000,
+ STRUCTDOC_SEC = 0x00010000,
+ SOURCE_SEC = 0x00020000,
+ HEADER_SEC = 0x00040000,
+ FILEDOC_SEC = 0x00080000,
+ DEFINEDOC_SEC = 0x00100000,
+ INCLUDE_SEC = 0x00200000,
+ DEFINE_SEC = 0x00400000,
+ GROUPDOC_SEC = 0x00800000,
+ NAMESPACE_SEC = 0x01000000,
+ NAMESPACEDOC_SEC = 0x02000000,
+ COMPOUND_MASK = CLASS_SEC | STRUCT_SEC | UNION_SEC,
+ COMPOUNDDOC_MASK = CLASSDOC_SEC | STRUCTDOC_SEC | UNIONDOC_SEC,
+ SCOPE_MASK = COMPOUND_MASK | NAMESPACE_SEC,
+ FILE_MASK = SOURCE_SEC | HEADER_SEC
+ };
+
+ Entry();
+ Entry(const Entry &);
+ ~Entry();
+ int getSize();
+
+ void addSubEntry (Entry* e) ;
+ void reset();
+
+ int section; // entry type;
+ Protection protection; // class protection
+ bool sig; // a Qt signal ?
+ bool slot; // a Qt slot ?
+ bool stat; // static ?
+ bool proto; // prototype ?
+ Specifier virt; // virtualness of the entry
+ Entry *parent; // parent node in the tree
+ QString type; // member type
+ QString name; // member name
+ QString args; // member argument string
+ ArgumentList *argList; // member arguments as a list
+ ArgumentList *tArgList; // template argument list
+ ArgumentList *tNameList; // template name list
+ QString program; // the program text
+ QString includeFile; // include file (2 arg of \class, must be unique)
+ QString includeName; // include name (3 arg of \class)
+ QString doc; // documentation block (partly parsed)
+ QString relates; // related class (doc block)
+ QString brief; // brief description (doc block)
+ QString inside; // name of the class in which documents are found
+ QString exception; // throw specification
+ QList<Entry> *sublist; // entries that are children of this one
+ QList<BaseInfo> *extends; // list of base classes
+ QList<QString> *groups; // list of groups this entry belongs to
+ QString fileName; // file this entry was extracted from
+ int startLine; // start line of entry in the source
+ int num;
+ private:
+ Entry &operator=(const Entry &);
+} ;
+
+typedef QList<Entry> EntryList;
+typedef QListIterator<Entry> EntryListIterator;
+
+#endif
diff --git a/src/example.h b/src/example.h
new file mode 100644
index 0000000..eef33ce
--- /dev/null
+++ b/src/example.h
@@ -0,0 +1,45 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#ifndef EXAMPLE_H
+#define EXAMPLE_H
+
+#include <qstring.h>
+
+class ClassDef;
+class MemberName;
+
+struct Example
+{
+ QString anchor;
+ QString name;
+ QString file;
+};
+
+class ExampleList : public QList<Example>
+{
+ public:
+ ExampleList() : QList<Example>() {}
+ ~ExampleList() {}
+ int compareItems(GCI item1,GCI item2)
+ {
+ return stricmp(((Example *)item1)->name,((Example *)item2)->name);
+ }
+};
+
+typedef QDict<Example> ExampleDict;
+
+#endif
diff --git a/src/filedef.cpp b/src/filedef.cpp
new file mode 100644
index 0000000..54266a5
--- /dev/null
+++ b/src/filedef.cpp
@@ -0,0 +1,291 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#include "memberlist.h"
+#include "classlist.h"
+#include "define.h"
+#include "filedef.h"
+#include "scanner.h"
+#include "doxygen.h"
+#include "memberdef.h"
+#include "classdef.h"
+#include "namespacedef.h"
+#include "util.h"
+#include "language.h"
+
+/*! create a new file definition, where \a p is the file path,
+ \a the file name, and \a ref is an HTML anchor name if the
+ file was read from a tag file or 0 otherwise
+*/
+FileDef::FileDef(const char *p,const char *nm,const char *ref)
+ : Definition(nm)
+{
+ path=p;
+ filepath=path+nm;
+ filename=nameToFile(nm);
+ reference=ref;
+ memList = new MemberList;
+ classList = new ClassList;
+ includeList = new FileList;
+ defineList = new DefineList;
+ namespaceList = new NamespaceList;
+}
+
+/*! destroy the file definition */
+FileDef::~FileDef()
+{
+ delete memList;
+ delete classList;
+ delete includeList;
+ delete defineList;
+}
+
+/*! Compute the HTML anchor names for all members in the class */
+void FileDef::computeAnchors()
+{
+ setAnchors('a',memList);
+}
+
+/*! Write the documentation page for this file to the file of output
+ generators \a ol.
+*/
+void FileDef::writeDocumentation(OutputList &ol)
+{
+ //funcList->countDecMembers();
+
+ QString pageTitle=name()+" File Reference";
+ startFile(ol,diskname,pageTitle);
+ startTitle(ol);
+ ol.docify(pageTitle);
+ endTitle(ol,name());
+ //ol.newParagraph();
+
+ if (genTagFile.length()>0) tagFile << "&" << name() << ":\n";
+
+ //brief=brief.stripWhiteSpace();
+ //int bl=brief.length();
+ OutputList briefOutput(&ol);
+ if (briefDescription())
+ {
+ //if (brief.at(bl-1)!='.' && brief.at(bl-1)!='!' && brief.at(bl!='?'))
+ // brief+='.';
+ parseDoc(briefOutput,0,0,briefDescription());
+ ol+=briefOutput;
+ ol.writeString(" \n");
+ ol.disableAllBut(OutputGenerator::Html);
+ ol.startTextLink(0,"details");
+ parseDoc(ol,0,0,theTranslator->trMore());
+ ol.endTextLink();
+ ol.enableAll();
+ }
+ ol.disable(OutputGenerator::Man);
+ ol.newParagraph();
+ ol.enable(OutputGenerator::Man);
+ ol.writeSynopsis();
+
+ if (classList->count()>0)
+ {
+ ClassDef *cd=classList->first();
+ bool found=FALSE;
+ while (cd)
+ {
+ if (//cd->name()[0]!='@' &&
+ //(cd->protection()!=Private || extractPrivateFlag) &&
+ //(cd->hasDocumentation() || !hideClassFlag))
+ cd->isVisibleExt()
+ )
+ {
+ if (!found)
+ {
+ ol.startMemberHeader();
+ parseDoc(ol,0,0,theTranslator->trCompounds());
+ ol.endMemberHeader();
+ ol.startMemberList();
+ found=TRUE;
+ }
+ ol.startMemberItem();
+ switch (cd->compoundType())
+ {
+ case ClassDef::Class: ol.writeString("class"); break;
+ case ClassDef::Struct: ol.writeString("struct"); break;
+ case ClassDef::Union: ol.writeString("union"); break;
+ }
+ ol.writeString(" ");
+ if (cd->hasDocumentation())
+ {
+ ol.writeObjectLink(cd->getReference(),
+ cd->classFile(),
+ 0,
+ cd->name()
+ );
+ }
+ else
+ {
+ ol.startBold();
+ ol.docify(cd->name());
+ ol.endBold();
+ }
+ ol.endMemberItem();
+ }
+ cd=classList->next();
+ }
+ if (found) ol.endMemberList();
+ }
+
+ writeMemberDecs(ol,0,0,this,0,0,memList);
+
+ //doc=doc.stripWhiteSpace();
+ //int bl=brief.length();
+ //int dl=doc.length();
+ if (!briefDescription().isEmpty() || !documentation().isEmpty())
+ {
+ ol.writeRuler();
+ ol.writeAnchor("details");
+ ol.startGroupHeader();
+ parseDoc(ol,0,0,theTranslator->trDetailedDescription());
+ ol.endGroupHeader();
+ if (!briefDescription().isEmpty())
+ {
+ ol+=briefOutput;
+ ol.newParagraph();
+ }
+ if (!documentation().isEmpty())
+ {
+ //if (doc.at(dl-1)!='.' && doc.at(dl-1)!='!' && doc.at(dl-1)!='?')
+ // doc+='.';
+ parseDoc(ol,0,0,documentation()+"\n");
+ ol.newParagraph();
+ }
+ }
+
+ memList->countDocMembers();
+
+ if ( memList->defineCount()>0 )
+ {
+ ol.writeRuler();
+ ol.startGroupHeader();
+ parseDoc(ol,0,0,theTranslator->trDefineDocumentation());
+ ol.endGroupHeader();
+ writeMemberDocs(ol,memList,name(),MemberDef::Define);
+ }
+
+ if ( memList->protoCount()>0 )
+ {
+ ol.writeRuler();
+ ol.startGroupHeader();
+ parseDoc(ol,0,0,theTranslator->trFunctionPrototypeDocumentation());
+ ol.endGroupHeader();
+ writeMemberDocs(ol,memList,name(),MemberDef::Prototype);
+ }
+
+ if ( memList->typedefCount()>0 )
+ {
+ ol.writeRuler();
+ ol.startGroupHeader();
+ parseDoc(ol,0,0,theTranslator->trTypedefDocumentation());
+ ol.endGroupHeader();
+ writeMemberDocs(ol,memList,name(),MemberDef::Typedef);
+ }
+
+ if ( memList->enumCount()>0 )
+ {
+ ol.writeRuler();
+ ol.startGroupHeader();
+ parseDoc(ol,0,0,theTranslator->trEnumerationTypeDocumentation());
+ ol.endGroupHeader();
+ writeMemberDocs(ol,memList,name(),MemberDef::Enumeration);
+ }
+
+ if ( memList->enumValueCount()>0 )
+ {
+ ol.writeRuler();
+ ol.startGroupHeader();
+ parseDoc(ol,0,0,theTranslator->trEnumerationValueDocumentation());
+ ol.endGroupHeader();
+ writeMemberDocs(ol,memList,name(),MemberDef::EnumValue);
+ }
+
+ if ( memList->funcCount()>0 )
+ {
+ ol.writeRuler();
+ ol.startGroupHeader();
+ parseDoc(ol,0,0,theTranslator->trFunctionDocumentation());
+ ol.endGroupHeader();
+ writeMemberDocs(ol,memList,name(),MemberDef::Function);
+ }
+
+ if ( memList->varCount()>0 )
+ {
+ ol.writeRuler();
+ ol.startGroupHeader();
+ parseDoc(ol,0,0,theTranslator->trVariableDocumentation());
+ ol.endGroupHeader();
+ writeMemberDocs(ol,memList,name(),MemberDef::Variable);
+ }
+
+ // write Author section (Man only)
+ ol.disableAllBut(OutputGenerator::Man);
+ ol.startGroupHeader();
+ parseDoc(ol,0,0,theTranslator->trAuthor());
+ ol.endGroupHeader();
+ parseDoc(ol,0,0,theTranslator->trGeneratedAutomatically(projectName));
+ ol.enableAll();
+ endFile(ol);
+}
+
+/*! Adds member definition \a md to the list of all members of this file */
+void FileDef::insertMember(MemberDef *md)
+{
+ memList->append(md);
+}
+
+/*! Adds compound definition \a cd to the list of all compounds of this file */
+void FileDef::insertClass(ClassDef *cd)
+{
+ classList->append(cd);
+}
+
+/*! Adds namespace definition \a nd to the list of all compounds of this file */
+void FileDef::insertNamespace(NamespaceDef *nd)
+{
+ namespaceList->append(nd);
+}
+
+//-----------------------------------------------------------------------------
+
+/*! Creates a file list. */
+FileList::FileList() : QList<FileDef>()
+{
+}
+
+/*! Destroys a file list */
+FileList::~FileList()
+{
+}
+
+/*! Compares two files by name. */
+int FileList::compareItems(GCI item1, GCI item2)
+{
+ FileDef *c1=(FileDef *)item1;
+ FileDef *c2=(FileDef *)item2;
+ return strcmp(c1->name(),c2->name());
+}
+
+/*! Create a file list iterator. */
+FileListIterator::FileListIterator(const FileList &cllist) :
+ QListIterator<FileDef>(cllist)
+{
+}
diff --git a/src/filedef.h b/src/filedef.h
new file mode 100644
index 0000000..36ce9cb
--- /dev/null
+++ b/src/filedef.h
@@ -0,0 +1,158 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#ifndef FILEDEF_H
+#define FILEDEF_H
+
+#include <qlist.h>
+#include "index.h"
+#include "config.h"
+#include "definition.h"
+
+class MemberList;
+class FileList;
+class ClassList;
+class MemberDef;
+class ClassDef;
+class OutputList;
+class DefineList;
+class NamespaceDef;
+class NamespaceList;
+
+/*! \class FileDef filedef.h
+ \brief A File definition.
+
+ An object of this class contains all file information that is gathered.
+ This includes the members and compounds defined in the file.
+
+ The member writeDocumentation() can be used to generate the page of
+ documentation to HTML and LaTeX.
+*/
+
+class FileDef : public Definition
+{
+ friend class FileName;
+
+ public:
+ //enum FileType { Source, Header, Unknown };
+
+ FileDef(const char *p,const char *n,const char *ref=0);
+ ~FileDef();
+
+ /*! Returns the unique file name (this may include part of the path). */
+ QString name() const
+ {
+ if (fullPathNameFlag)
+ return filename;
+ else
+ return Definition::name();
+ }
+
+ /*! Returns nameString with all slashes replaced by underscores. */
+ const char *diskName() const { return diskname; }
+
+ /*! Returns the absolute path including the file name. */
+ QString absFilePath() const { return filepath; }
+
+ /*! Returns the name of the verbatim copy of this file (if any). */
+ const char *includeName() const { return incName; }
+
+ /*! Returns the documentation that was available for this file. */
+ //const char *documentation() const { return doc; }
+
+ /*! Returns the brief description that was given for this file. */
+ //const char *briefDescription() const { return brief; }
+
+ /*! Sets the name of the include file to \a n. */
+ void setIncludeName(const char *n_) { incName=n_; }
+
+ /*! Sets the name of the include file to \a n. */
+ //void setBriefDescription(const char *b) { brief=b; }
+
+ /*! Sets the documentaton of this file to \a d. */
+ //void setDocumentation(const char *d) { doc=d; }
+
+ /*! Returns the absolute path of this file. */
+ QString getPath() const { return path; }
+
+ /*! Returns true iff any documentation for this file is found. */
+ //bool hasDocumentation()
+ // { return extractAllFlag || !doc.isNull() || !brief.isNull(); }
+
+ /*! Returns true iff this file was externally defined
+ (i.e. read from a tag file) */
+ bool isReference() { return !reference.isNull(); }
+
+ /*! Returns the reference name of the external file, if any or 0
+ if the file is not defined. */
+ const char *getReference() { return reference; }
+
+ //void setFileType(FileType ft) { ftype = ft; }
+ //FileType fileType() const { return ftype; }
+
+ void writeDocumentation(OutputList &ol);
+ friend void generatedFileNames();
+ void insertMember(MemberDef *fd);
+ void insertClass(ClassDef *cd);
+ void insertNamespace(NamespaceDef *nd);
+ void computeAnchors();
+
+ private:
+ MemberList *memList;
+ ClassList *classList;
+ FileList *includeList;
+ NamespaceList *namespaceList;
+ DefineList *defineList;
+ //QString n;
+ //QString doc;
+ //QString brief;
+ QString reference;
+ QString path;
+ QString filepath;
+ QString diskname;
+ QString filename;
+ QString incName;
+ //FileType ftype;
+};
+
+/*! \class FileList filedef.h
+ \brief This class is list of file definitions.
+
+ It is based on QList.
+*/
+
+class FileList : public QList<FileDef>
+{
+ public:
+ FileList();
+ ~FileList();
+
+ int compareItems(GCI item1,GCI item2);
+};
+
+/*! \class FileListIterator filedef.h
+ \brief This class represents a file list iterator.
+
+ It is based on QListIterator.
+*/
+
+class FileListIterator : public QListIterator<FileDef>
+{
+ public:
+ FileListIterator(const FileList &list);
+};
+
+#endif
diff --git a/src/filename.cpp b/src/filename.cpp
new file mode 100644
index 0000000..60367dc
--- /dev/null
+++ b/src/filename.cpp
@@ -0,0 +1,133 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#include "filename.h"
+#include "util.h"
+
+FileName::FileName(const char *n) : QList<FileDef>()
+{
+ name=n;
+}
+
+FileName::~FileName()
+{
+}
+
+//static QString convertSlashes(const char *s)
+//{
+// QString result=s;
+// int i,l=result.length();
+// for (i=0;i<l;i++) if (result.at(i)=='/') result.at(i)='_';
+// return result;
+//}
+
+void FileName::generateDiskNames()
+{
+ QString commonPrefix;
+ FileDef *fd=first();
+ int count=0;
+ while (fd) { if (!fd->isReference()) count++; fd=next(); }
+ if (count==1)
+ {
+ fd=first();
+ // skip references
+ while (fd && fd->isReference()) fd=next();
+ // name if unique, so diskname is simply the name
+ fd->diskname=name;
+ }
+ else if (count>1) // multiple occurrences of the same file name
+ {
+ //printf("Multiple occurrences of %s\n",name.data());
+ int i=0,j=0;
+ bool found=FALSE;
+ while (!found)
+ {
+ fd=first();
+ while (fd && fd->isReference()) fd=next();
+ char c=fd->path.at(i);
+ if (c=='/') j=i; // remember last position of dirname
+ while (fd && !found)
+ {
+ if (!fd->isReference())
+ {
+ //printf("i=%d fd->path=`%s' fd->name=`%s'\n",i,fd->path.data(),fd->name().data());
+ if (i==(int)fd->path.length())
+ {
+ warning("Warning: Input file found multiple times!\n"
+ " The generated documentation for this file may not be correct!\n");
+ found=TRUE;
+ }
+ else if (fd->path[i]!=c)
+ {
+ found=TRUE;
+ }
+ }
+ fd=next();
+ }
+ i++;
+ }
+ fd=first();
+ while (fd)
+ {
+ //printf("fd->setName(%s)\n",(fd->path.right(fd->path.length()-j-1)+name).data());
+ fd->setName(fd->path.right(fd->path.length()-j-1)+name);
+ fd->diskname=convertSlashes(fd->name());
+ fd=next();
+ }
+ }
+}
+
+int FileName::compareItems(GCI item1, GCI item2)
+{
+ FileName *f1=(FileName *)item1;
+ FileName *f2=(FileName *)item2;
+ return stricmp(f1->fileName(),f2->fileName());
+}
+
+FileNameIterator::FileNameIterator(const FileName &fname) :
+ QListIterator<FileDef>(fname)
+{
+}
+
+FileNameList::FileNameList() : QList<FileName>()
+{
+}
+
+FileNameList::~FileNameList()
+{
+}
+
+void FileNameList::generateDiskNames()
+{
+ FileName *fn=first();
+ while (fn)
+ {
+ fn->generateDiskNames();
+ fn=next();
+ }
+}
+
+int FileNameList::compareItems(GCI item1, GCI item2)
+{
+ FileName *f1=(FileName *)item1;
+ FileName *f2=(FileName *)item2;
+ return stricmp(f1->fileName(),f2->fileName());
+}
+
+FileNameListIterator::FileNameListIterator(const FileNameList &fnlist) :
+ QListIterator<FileName>(fnlist)
+{
+}
diff --git a/src/filename.h b/src/filename.h
new file mode 100644
index 0000000..2932d18
--- /dev/null
+++ b/src/filename.h
@@ -0,0 +1,63 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#ifndef FILENAME_H
+#define FILENAME_H
+
+#include <qdict.h>
+#include "filedef.h"
+
+class FileName : public QList<FileDef>
+{
+ public:
+ FileName(const char *name);
+ ~FileName();
+ const char *fileName() const { return name; }
+ void generateDiskNames();
+ int compareItems(GCI item1,GCI item2);
+
+ private:
+ QString name;
+};
+
+class FileNameIterator : public QListIterator<FileDef>
+{
+ public:
+ FileNameIterator(const FileName &list);
+};
+
+class FileNameList : public QList<FileName>
+{
+ public:
+ FileNameList();
+ ~FileNameList();
+ void generateDiskNames();
+ int compareItems(GCI item1,GCI item2);
+};
+
+class FileNameListIterator : public QListIterator<FileName>
+{
+ public:
+ FileNameListIterator( const FileNameList &list );
+};
+
+class FileNameDict : public QDict<FileName>
+{
+ public:
+ FileNameDict(uint size) : QDict<FileName>(size) {}
+};
+
+#endif
diff --git a/src/formula.cpp b/src/formula.cpp
new file mode 100644
index 0000000..53e8b38
--- /dev/null
+++ b/src/formula.cpp
@@ -0,0 +1,286 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <qfile.h>
+#include <qtstream.h>
+#include <qfileinf.h>
+#include <qdir.h>
+
+#include "formula.h"
+#include "image.h"
+#include "util.h"
+#include "message.h"
+
+Formula::Formula(const char *text)
+{
+ static int count=0;
+ number = count++;
+ form=text;
+}
+
+Formula::~Formula()
+{
+}
+
+int Formula::getId()
+{
+ return number;
+}
+
+void FormulaList::generateBitmaps(const char *path)
+{
+ int x1,y1,x2,y2;
+ QDir d(path);
+ // store the original directory
+ if (!d.exists()) { err("Error: Output dir %s does not exist!\n",path); exit(1); }
+ QString oldDir = QDir::currentDirPath().copy();
+ // goto the html output directory (i.e. path)
+ QDir::setCurrent(d.absPath());
+ QDir thisDir;
+ // generate a latex file containing one formula per page.
+ QString texName="_formulas.tex";
+ QList<int> pagesToGenerate;
+ pagesToGenerate.setAutoDelete(TRUE);
+ FormulaListIterator fli(*this);
+ Formula *formula;
+ QFile f(texName);
+ if (f.open(IO_WriteOnly))
+ {
+ QTextStream t(&f);
+ t << "\\documentclass{article}" << endl;
+ t << "\\usepackage{epsf}" << endl; // for those who want to include images
+ t << "\\pagestyle{empty}" << endl;
+ t << "\\begin{document}" << endl;
+ int page=0;
+ for (fli.toFirst();(formula=fli.current());++fli)
+ {
+ QString resultName;
+ resultName.sprintf("form-%d.gif",formula->getId());
+ // only formulas for which no image exists are generated
+ QFileInfo fi(resultName);
+ if (!fi.exists())
+ {
+ // we force a pagebreak after each formula
+ t << formula->getFormulaText() << endl << "\\pagebreak\n\n";
+ pagesToGenerate.append(new int(page));
+ }
+ page++;
+ }
+ t << "\\end{document}" << endl;
+ f.close();
+ }
+ if (pagesToGenerate.count()>0) // there are new formulas
+ {
+ //printf("Running latex...\n");
+ //system("latex _formulas.tex </dev/null >/dev/null");
+ system("latex _formulas.tex");
+ //printf("Running dvips...\n");
+ QListIterator<int> pli(pagesToGenerate);
+ int *pagePtr;
+ int pageIndex=1;
+ for (;(pagePtr=pli.current());++pli,++pageIndex)
+ {
+ int pageNum=*pagePtr;
+ msg("Generating image form-%d.gif for formula\n",pageNum);
+ char dviCmd[256];
+ QString formBase;
+ formBase.sprintf("_form%d",pageNum);
+ // run dvips to convert the page with number pageIndex to an
+ // encapsulated postscript.
+ sprintf(dviCmd,"dvips -q -D 600 -E -n 1 -p %d -o %s.eps _formulas.dvi",
+ pageIndex,formBase.data());
+ system(dviCmd);
+ // now we read the generated postscript file to extract the bounding box
+ QFileInfo fi(formBase+".eps");
+ if (fi.exists())
+ {
+ QString eps = fileToString(formBase+".eps");
+ int i=eps.find("%%BoundingBox:");
+ if (i!=-1)
+ {
+ sscanf(eps.data()+i,"%%%%BoundingBox:%d %d %d %d",&x1,&y1,&x2,&y2);
+ }
+ else
+ {
+ err("Error: Couldn't extract bounding box!\n");
+ }
+ }
+ // next we generate a postscript file which contains the eps
+ // and displays it in the right colors and the right bounding box
+ f.setName(formBase+".ps");
+ if (f.open(IO_WriteOnly))
+ {
+ QTextStream t(&f);
+ t << "1 1 1 setrgbcolor" << endl; // anti-alias to white background
+ t << "newpath" << endl;
+ t << "-1 -1 moveto" << endl;
+ t << x2-x1+2 << " -1 lineto" << endl;
+ t << x2-x1+2 << " " << y2-y1+2 << " lineto" << endl;
+ t << "-1 " << y2-y1+2 << " lineto" <<endl;
+ t << "closepath" << endl;
+ t << "fill" << endl;
+ t << -x1 << " " << -y1 << " translate" << endl;
+ t << "0 0 0 setrgbcolor" << endl;
+ t << "(" << formBase << ".eps) run" << endl;
+ f.close();
+ }
+ // scale the image so that it is four times larger than needed.
+ // and the sizes are a multiple of four.
+ const double scaleFactor = 16.0/3.0;
+ int gx = (((int)((x2-x1)*scaleFactor))+3)&~2;
+ int gy = (((int)((y2-y1)*scaleFactor))+3)&~2;
+ char gsCmd[256];
+ // Then we run ghostscript to convert the postscript to a pixmap
+ // The pixmap is a truecolor image, where only black and white are
+ // used.
+ sprintf(gsCmd,"gs -q -g%dx%d -r%dx%dx -sDEVICE=ppmraw "
+ "-sOutputFile=%s.pnm -DNOPAUSE -- %s.ps",
+ gx,gy,(int)(scaleFactor*72),(int)(scaleFactor*72),
+ formBase.data(),formBase.data()
+ );
+ //printf("Running ghostscript...\n");
+ system(gsCmd);
+ f.setName(formBase+".pnm");
+ uint imageX=0,imageY=0;
+ // we read the generated image again, to obtain the pixel data.
+ if (f.open(IO_ReadOnly))
+ {
+ QTextStream t(&f);
+ QString s;
+ if (!t.eof())
+ s=t.readLine();
+ if (s.length()<2 || s.left(2)!="P6")
+ err("Error: ghostscript produced an illegal image format!");
+ else
+ {
+ // assume the size if after the first line that does not start with
+ // # excluding the first line of the file.
+ while (!t.eof() && (s=t.readLine()) && !s.isEmpty() && s.at(0)=='#');
+ sscanf(s,"%d %d",&imageX,&imageY);
+ }
+ if (imageX>0 && imageY>0)
+ {
+ //printf("Converting image...\n");
+ char *data = new char[imageX*imageY*3]; // rgb 8:8:8 format
+ uint i,x,y,ix,iy;
+ f.readBlock(data,imageX*imageY*3);
+ Image srcImage(imageX,imageY),
+ filteredImage(imageX,imageY),
+ dstImage(imageX/4,imageY/4);
+ uchar *ps=srcImage.getData();
+ // convert image to black (1) and white (0) index.
+ for (i=0;i<imageX*imageY;i++) *ps++= (data[i*3]==0 ? 1 : 0);
+ // apply a simple box filter to the image
+ static int filterMask[]={1,2,1,2,8,2,1,2,1};
+ for (y=0;y<srcImage.getHeight();y++)
+ {
+ for (x=0;x<srcImage.getWidth();x++)
+ {
+ int s=0;
+ for (iy=0;iy<2;iy++)
+ {
+ for (ix=0;ix<2;ix++)
+ {
+ s+=srcImage.getPixel(x+ix-1,y+iy-1)*filterMask[iy*3+ix];
+ }
+ }
+ filteredImage.setPixel(x,y,s);
+ }
+ }
+ // down-sample the image to 1/16th of the area using 16 gray scale
+ // colors.
+ for (y=0;y<dstImage.getHeight();y++)
+ {
+ for (x=0;x<dstImage.getWidth();x++)
+ {
+ int xp=x<<2;
+ int yp=y<<2;
+ int c=filteredImage.getPixel(xp+0,yp+0)+
+ filteredImage.getPixel(xp+1,yp+0)+
+ filteredImage.getPixel(xp+2,yp+0)+
+ filteredImage.getPixel(xp+3,yp+0)+
+ filteredImage.getPixel(xp+0,yp+1)+
+ filteredImage.getPixel(xp+1,yp+1)+
+ filteredImage.getPixel(xp+2,yp+1)+
+ filteredImage.getPixel(xp+3,yp+1)+
+ filteredImage.getPixel(xp+0,yp+2)+
+ filteredImage.getPixel(xp+1,yp+2)+
+ filteredImage.getPixel(xp+2,yp+2)+
+ filteredImage.getPixel(xp+3,yp+2)+
+ filteredImage.getPixel(xp+0,yp+3)+
+ filteredImage.getPixel(xp+1,yp+3)+
+ filteredImage.getPixel(xp+2,yp+3)+
+ filteredImage.getPixel(xp+3,yp+3);
+ // here we scale and clip the color value so the
+ // resulting image has a reasonable contrast
+ dstImage.setPixel(x,y,QMIN(15,(c*15)/(16*10)));
+ }
+ }
+ // save the result as a gif
+ QString resultName;
+ resultName.sprintf("form-%d.gif",pageNum);
+ // the option parameter 1 is used here as a temporary hack
+ // to select the right color palette!
+ dstImage.save(resultName,1);
+ delete[] data;
+ }
+ f.close();
+ }
+ // remove intermediate image files
+ thisDir.remove(formBase+".eps");
+ thisDir.remove(formBase+".pnm");
+ thisDir.remove(formBase+".ps");
+ }
+ // remove intermediate files produced by latex
+ thisDir.remove("_formulas.dvi");
+ thisDir.remove("_formulas.log");
+ thisDir.remove("_formulas.aux");
+ }
+ // remove the latex file itself
+ thisDir.remove("_formulas.tex");
+ // write/update the formula repository so we know what text the
+ // generated gifs represent (we use this next time to avoid regeneration
+ // of the gifs, and to avoid forcing the user to delete all gifs in order
+ // to let a browser refresh the images).
+ f.setName("formula.repository");
+ if (f.open(IO_WriteOnly))
+ {
+ QTextStream t(&f);
+ for (fli.toFirst();(formula=fli.current());++fli)
+ {
+ t << "\\form#" << formula->getId() << ":" << formula->getFormulaText() << endl;
+ }
+ f.close();
+ }
+ // reset the directory to the original location.
+ QDir::setCurrent(oldDir);
+}
+
+
+#ifdef FORMULA_TEST
+int main()
+{
+ FormulaList fl;
+ fl.append(new Formula("$x^2$"));
+ fl.append(new Formula("$y^2$"));
+ fl.append(new Formula("$\\sqrt{x_0^2+x_1^2+x_2^2}$"));
+ fl.generateBitmaps("dest");
+ return 0;
+}
+#endif
diff --git a/src/formula.h b/src/formula.h
new file mode 100644
index 0000000..977ccfe
--- /dev/null
+++ b/src/formula.h
@@ -0,0 +1,57 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#ifndef FORMULA_H
+#define FORMULA_H
+
+#include <qstring.h>
+#include <qlist.h>
+#include <qdict.h>
+
+class Formula
+{
+ public:
+ Formula(const char *text);
+ ~Formula();
+ int getId();
+ QString getFormulaText() const { return form; }
+
+ private:
+ int number;
+ QString form;
+};
+
+class FormulaList : public QList<Formula>
+{
+ public:
+ void generateBitmaps(const char *path);
+};
+
+class FormulaListIterator : public QListIterator<Formula>
+{
+ public:
+ FormulaListIterator(const FormulaList &l) :
+ QListIterator<Formula>(l) {}
+};
+
+class FormulaDict : public QDict<Formula>
+{
+ public:
+ FormulaDict(uint size) :
+ QDict<Formula>(size) {}
+};
+
+#endif
diff --git a/src/gifenc.cpp b/src/gifenc.cpp
new file mode 100644
index 0000000..1160531
--- /dev/null
+++ b/src/gifenc.cpp
@@ -0,0 +1,293 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ * The GIF compression code below is based on the file ppmtogif.c of the
+ * netpbm package. The original copyright message follows:
+ *
+ * ---------------------------------------------------------------------------
+ *
+ * Copyright (C) 1989 by Jef Poskanzer.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose and without fee is hereby granted, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation. This software is provided "as is" without express or
+ * implied warranty.
+ *
+ * ---------------------------------------------------------------------------
+ *
+ * The Graphics Interchange Format(c) is the Copyright property of
+ * CompuServe Incorporated. GIF(sm) is a Service Mark property of
+ * CompuServe Incorporated.
+ */
+
+#include "gifenc.h"
+
+static const unsigned int masks[] = { 0x0000, 0x0001, 0x0003, 0x0007, 0x000F,
+ 0x001F, 0x003F, 0x007F, 0x00FF,
+ 0x01FF, 0x03FF, 0x07FF, 0x0FFF,
+ 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF };
+
+GifEncoder::GifEncoder(Byte *rawBytes,Color *p,int w,int h, Byte d,
+ int t)
+ : colorResolution(8),globalPaletteFlag(0x80),bits(12),
+ maxMaxCode(1<<bits)
+{
+ width = w;
+ height = h;
+ depth = d;
+ transIndex = t;
+ palette = p;
+ data = rawBytes;
+ dataPtr = data;
+}
+
+GifEncoder::~GifEncoder()
+{
+}
+
+void GifEncoder::writeGIF(QFile &fp)
+{
+ // Write the Magic header
+ fp.writeBlock( transIndex < 0 ? "GIF87a" : "GIF89a", 6 );
+
+ // Write the logical screen descriptor
+ putWord( width, fp );
+ putWord( height, fp );
+ Byte pack = globalPaletteFlag | ((colorResolution-1)<<4) | (depth-1);
+ putByte( pack, fp );
+ putByte( 0, fp ); // the background color
+ putByte( 0, fp ); // no aspect ration defined
+
+ // Write global color table
+ int i; for ( i=0 ; i< (1<<depth) ; i++)
+ {
+ putByte(palette[i].red, fp);
+ putByte(palette[i].green,fp);
+ putByte(palette[i].blue, fp);
+ }
+
+ if ( transIndex >= 0)
+ {
+ // Write graphic control extension (needed for GIF transparancy)
+ putByte( 0x21, fp); // extension introducer
+ putByte( 0xf9, fp); // graphic control label
+ putByte( 4, fp); // block size
+ putByte( 1, fp); // announce transparacy value
+ putWord( 0, fp); // zero delay time
+ putByte( transIndex, fp); // write transparant index
+ putByte( 0, fp); // end block
+ }
+
+ // Write the image descriptor
+ putByte( 0x2c, fp); // image separator
+ putWord( 0, fp); // image left position
+ putWord( 0, fp); // image top position
+ putWord( width, fp); // image width
+ putWord( height, fp); // image height
+ putByte( 0, fp); // no local color table, no interlacing
+
+ // Write table based image data
+ Byte initCodeSize = depth<=1 ? 2 : depth;
+ putByte( initCodeSize, fp); // LZW Minimum Code Size
+ compress( initCodeSize+1, fp);
+ putByte( 0, fp); // end of blocks
+
+ // Write GIF Trailer
+ putByte( 0x3b, fp);
+}
+
+void GifEncoder::compress( int ibits, QFile &outfile )
+{
+ int i;
+ int entry;
+
+ initBits = ibits;
+ numPixels = width*height;
+ dataPtr = data;
+ clearFlag = FALSE;
+ nBits = initBits;
+ maxCode = (1<<nBits) -1;
+ ClearCode = (1 << (initBits - 1));
+ EOFCode = ClearCode + 1;
+ freeEntry = ClearCode + 2;
+ aCount = 0;
+ curAccum = 0;
+ curBits = 0;
+
+ entry = nextPixel();
+
+ int hshift = 0;
+ int fcode;
+ for ( fcode = hashTableSize; fcode < 65536L; fcode *= 2L ) ++hshift;
+ hshift = 8 - hshift; /* set hash code range bound */
+
+ clearHashTable(); /* clear hash table */
+
+ writeCode( ClearCode,outfile );
+
+ int c;
+ while ( (c = nextPixel()) != EOF )
+ {
+ fcode = (c << bits) + entry;
+ i = (c << hshift) ^ entry; /* xor hashing */
+
+ bool found=FALSE;
+ if (htab[i]==fcode)
+ {
+ entry = codetab[i];
+ found=TRUE;
+ }
+ else if (htab[i]>=0)
+ {
+ int disp = hashTableSize - i;
+ if (i==0) disp=1;
+ do
+ {
+ if ((i-=disp)<0) i+=hashTableSize;
+ if (htab[i]==fcode)
+ {
+ entry=codetab[i];
+ found=TRUE;
+ }
+ } while (htab[i]>0 && !found);
+ }
+ if (!found)
+ {
+ writeCode( entry, outfile );
+ entry = c;
+ if ( freeEntry < maxMaxCode )
+ {
+ codetab[i] = freeEntry++; /* code -> hashtable */
+ htab[i] = fcode;
+ }
+ else
+ {
+ clearHashTable();
+ freeEntry = ClearCode + 2;
+ clearFlag = TRUE;
+ writeCode( ClearCode, outfile );
+ }
+ }
+ }
+ writeCode( entry, outfile );
+ writeCode( EOFCode, outfile );
+}
+
+void GifEncoder::putWord( Word w, QFile &fp )
+{
+ fp.putch( w & 0xff );
+ fp.putch( (w>>8) & 0xff );
+}
+
+void GifEncoder::putByte( Byte b, QFile &fp )
+{
+ fp.putch( b );
+}
+
+int GifEncoder::nextPixel()
+{
+ if ( --numPixels < 0) return EOF;
+ return *dataPtr++;
+}
+
+void GifEncoder::writeCode( int code, QFile &outfile )
+{
+ curAccum &= masks[ curBits ];
+
+ if ( curBits > 0 )
+ {
+ curAccum |= (code << curBits);
+ }
+ else
+ {
+ curAccum = code;
+ }
+
+ curBits += nBits;
+
+ while( curBits >= 8 )
+ {
+ writeChar( (Byte)(curAccum & 0xff),outfile );
+ curAccum >>= 8;
+ curBits -= 8;
+ }
+
+ /*
+ * If the next entry is going to be too big for the code size,
+ * then increase it, if possible.
+ */
+ if ( freeEntry > maxCode || clearFlag )
+ {
+ if( clearFlag )
+ {
+ nBits = initBits;
+ maxCode = (1<<nBits)-1;
+ clearFlag = FALSE;
+ }
+ else
+ {
+ ++nBits;
+ if ( nBits == bits )
+ maxCode = maxMaxCode;
+ else
+ maxCode = (1<<nBits)-1;
+ }
+ }
+
+ if ( code == EOFCode )
+ {
+ /* At EOF, write the rest of the buffer. */
+ while( curBits > 0 )
+ {
+ writeChar( (Byte)(curAccum & 0xff), outfile );
+ curAccum >>= 8;
+ curBits -= 8;
+ }
+
+ writePacket(outfile);
+ }
+}
+
+/*
+ * Add a character to the end of the current packet, and if it is 254
+ * characters, flush the packet to disk.
+ */
+void GifEncoder::writeChar( Byte c, QFile &fp )
+{
+ accum[ aCount++ ] = c;
+ if( aCount >= 254 ) writePacket(fp);
+}
+
+/*
+ * Flush the packet to disk, and reset the accumulator
+ */
+void GifEncoder::writePacket(QFile &fp)
+{
+ if ( aCount > 0 )
+ {
+ fp.putch( aCount );
+ fp.writeBlock( (const char *)accum, aCount );
+ aCount = 0;
+ }
+}
+
+void GifEncoder::clearHashTable() /* reset code table */
+{
+ int *htab_p = htab;
+ int i; for (i=0;i<hashTableSize;i++) *htab_p++ = -1;
+}
+
diff --git a/src/gifenc.h b/src/gifenc.h
new file mode 100644
index 0000000..161e032
--- /dev/null
+++ b/src/gifenc.h
@@ -0,0 +1,85 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#ifndef _GIFENC_H
+#define _GIFENC_H
+#include <qfile.h>
+
+typedef unsigned char Byte;
+typedef unsigned short Word;
+
+struct Color
+{
+ Byte red;
+ Byte green;
+ Byte blue;
+};
+
+const int hashTableSize=5003; // size of the hash table
+
+class GifEncoder
+{
+ public:
+ GifEncoder(Byte *rawBytes,Color *p,int w,int h,Byte d,int t);
+ ~GifEncoder();
+ void writeGIF(QFile &fp);
+
+ protected:
+ void putWord( Word w, QFile &fp );
+ void putByte( Byte b, QFile &fp );
+ void compress(int csize, QFile &fp);
+ void writeCode(int code, QFile &fp);
+ void writeChar( Byte c, QFile &fp );
+ void writePacket(QFile &fp);
+ int nextPixel();
+ void clearHashTable();
+
+ private:
+ const int colorResolution; // 8 bit for Red, Green and Blue;
+ const int globalPaletteFlag;
+ const int bits;
+ const int maxMaxCode;
+
+ // image variables
+ int width; // image width
+ int height; // image height
+ Byte depth; // bits per CLUT entry
+ int transIndex; // index of the transparant color; -1 = none
+ Color *palette; // pointer to the color palette
+ int numPixels; // total number of pixel (i.e. width * height)
+ Byte *data; // pointer to the image data (one byte per pixel)
+ Byte *dataPtr; // pointer located at the current pixel.
+
+ // compression variables
+ bool clearFlag; // clear hash table flag
+ int freeEntry; // first free entry in the hash table
+ unsigned int curAccum; // encoded bit accumulator
+ int curBits; // number of bits in curAccum
+ Byte accum[256]; // Buffer for a packet
+ int aCount; // Number of characters so far in this 'packet'
+ int nBits; // number of bits/code
+ int maxCode; // maximum code, given n_bits
+ int initBits; // initial number of bits
+ int EOFCode; // code for signaling the end of the file
+ int ClearCode; // the clear code for the decompressor
+
+ // tables
+ int htab[hashTableSize]; // the hash table
+ Word codetab[hashTableSize]; // the code table
+};
+
+#endif
diff --git a/src/groupdef.cpp b/src/groupdef.cpp
new file mode 100644
index 0000000..6a2d79b
--- /dev/null
+++ b/src/groupdef.cpp
@@ -0,0 +1,158 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#include <ctype.h>
+#include "groupdef.h"
+#include "classdef.h"
+#include "filedef.h"
+#include "classlist.h"
+#include "outputlist.h"
+#include "scanner.h"
+#include "namespacedef.h"
+#include "language.h"
+#include "util.h"
+
+GroupDef::GroupDef(const char *na,const char *t) : Definition(na)
+{
+ fileList = new FileList;
+ classList = new ClassList;
+// groupList = new GroupList;
+// name = n;
+ if (t)
+ title = t;
+ else
+ {
+ title = na;
+ title.at(0)=toupper(title.at(0));
+ }
+ fileName = "group_"+nameToFile(na);
+}
+
+GroupDef::~GroupDef()
+{
+ delete fileList;
+ delete classList;
+// delete groupList;
+}
+
+void GroupDef::addFile(const FileDef *def)
+{
+ fileList->append(def);
+}
+
+void GroupDef::addClass(const ClassDef *def)
+{
+ classList->append(def);
+}
+
+void GroupDef::addNamespace(const NamespaceDef *def)
+{
+ namespaceList->append(def);
+}
+
+//void GroupDef::addGroup(const GroupDef *def)
+//{
+// groupList->append(def);
+//}
+
+int GroupDef::countMembers() const
+{
+ return fileList->count()+classList->count();
+}
+
+void GroupDef::writeDocumentation(OutputList &ol)
+{
+ ol.disable(OutputGenerator::Man);
+ startFile(ol,fileName,title);
+ startTitle(ol);
+ ol.docify(title);
+ endTitle(ol,name());
+
+ //brief=brief.stripWhiteSpace();
+ //int bl=brief.length();
+ OutputList briefOutput(&ol);
+ if (!briefDescription().isEmpty())
+ {
+ parseDoc(briefOutput,name(),0,briefDescription());
+ ol+=briefOutput;
+ ol.writeString(" \n");
+ ol.disable(OutputGenerator::Latex);
+ ol.startTextLink(0,"details");
+ parseDoc(ol,0,0,theTranslator->trMore());
+ ol.enable(OutputGenerator::Latex);
+ }
+ if (fileList->count()>0)
+ {
+ ol.startMemberHeader();
+ parseDoc(ol,0,0,theTranslator->trFiles());
+ ol.endMemberHeader();
+ ol.startIndexList();
+ FileDef *fd=fileList->first();
+ while (fd)
+ {
+ ol.writeStartAnnoItem("file ",fd->diskName(),0,fd->name());
+ ol.writeEndAnnoItem(fd->name());
+ fd=fileList->next();
+ }
+ ol.endIndexList();
+ }
+ if (classList->count()>0)
+ {
+ ol.startMemberHeader();
+ parseDoc(ol,0,0,theTranslator->trCompounds());
+ ol.endMemberHeader();
+ ol.startIndexList();
+ ClassDef *cd=classList->first();
+ while (cd)
+ {
+ QString type;
+ switch (cd->compoundType())
+ {
+ case ClassDef::Class: type="class"; break;
+ case ClassDef::Struct: type="struct"; break;
+ case ClassDef::Union: type="union"; break;
+ }
+ ol.writeStartAnnoItem(type,cd->classFile(),0,cd->name());
+ ol.writeEndAnnoItem(cd->name());
+ cd=classList->next();
+ }
+ ol.endIndexList();
+ }
+ //int dl=doc.length();
+ //doc=doc.stripWhiteSpace();
+ if (!briefDescription().isEmpty() || !documentation().isEmpty())
+ {
+ ol.writeRuler();
+ ol.writeAnchor("details");
+ ol.startGroupHeader();
+ parseDoc(ol,0,0,theTranslator->trDetailedDescription());
+ ol.endGroupHeader();
+ // repeat brief description
+ if (!briefDescription().isEmpty())
+ {
+ ol+=briefOutput;
+ ol.newParagraph();
+ }
+ // write documentation
+ if (!documentation().isEmpty())
+ {
+ parseDoc(ol,name(),0,documentation()+"\n");
+ }
+ }
+
+ endFile(ol);
+ ol.enable(OutputGenerator::Man);
+}
diff --git a/src/groupdef.h b/src/groupdef.h
new file mode 100644
index 0000000..421b701
--- /dev/null
+++ b/src/groupdef.h
@@ -0,0 +1,64 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#ifndef GROUPDEF_H
+#define GROUPDEF_H
+
+#include <qstring.h>
+#include <qlist.h>
+#include "definition.h"
+
+class FileList;
+class ClassList;
+class FileDef;
+class ClassDef;
+class NamespaceDef;
+class GroupList;
+class OutputList;
+class NamespaceList;
+
+class GroupDef : public Definition
+{
+ public:
+ GroupDef(const char *name,const char *title);
+ ~GroupDef();
+ const char *groupFile() const { return fileName; }
+ const char *groupTitle() const { return title; }
+ void addFile(const FileDef *def);
+ void addClass(const ClassDef *def);
+ void addNamespace(const NamespaceDef *def);
+ void writeDocumentation(OutputList &ol);
+ int countMembers() const;
+
+ private:
+ QString title; // title of the group
+ QString fileName; // base name of the generated file
+ FileList *fileList; // list of all files in the group
+ ClassList *classList; // list of all classes in the group
+ NamespaceList *namespaceList; // list of all namespace in the group
+};
+
+class GroupList : public QList<GroupDef>
+{
+};
+
+class GroupListIterator : public QListIterator<GroupDef>
+{
+ public:
+ GroupListIterator(const GroupList &l) : QListIterator<GroupDef>(l) {}
+};
+
+#endif
diff --git a/src/htmlgen.cpp b/src/htmlgen.cpp
new file mode 100644
index 0000000..4ab337f
--- /dev/null
+++ b/src/htmlgen.cpp
@@ -0,0 +1,512 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#include <qdir.h>
+#include <stdlib.h>
+#include "message.h"
+#include "htmlgen.h"
+#include "config.h"
+#include "util.h"
+#include "doxygen.h"
+#include "logos.h"
+#include "diagram.h"
+
+HtmlGenerator::HtmlGenerator() : OutputGenerator()
+{
+ if (headerFile.length()>0) header=fileToString(headerFile);
+ if (footerFile.length()>0) footer=fileToString(footerFile);
+ dir=htmlOutputDir;
+}
+
+HtmlGenerator::~HtmlGenerator()
+{
+}
+
+void HtmlGenerator::append(const OutputGenerator *g)
+{
+ t << g->getContents();
+}
+
+void HtmlGenerator::init()
+{
+ QDir d(htmlOutputDir);
+ if (!d.exists() && !d.mkdir(htmlOutputDir))
+ {
+ err("Could not create output directory %s\n",htmlOutputDir.data());
+ exit(1);
+ }
+ writeLogo(htmlOutputDir);
+}
+
+//void HtmlGenerator::generateExternalIndex()
+//{
+// //printf("Generating external index...\n");
+// QFile f;
+// f.setName(htmlOutputDir+"/header.html");
+// if (f.open(IO_WriteOnly))
+// {
+// QTextStream tt(&f);
+// if (header.length()==0)
+// {
+// tt << "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\">\n"
+// "<html><head><meta name=\"robots\" content=\"noindex\">\n"
+// "<title>Doxysearch</title>\n"
+// "</head><body bgcolor=\"#ffffff\">\n";
+// }
+// else
+// {
+// tt << header;
+// }
+// if (!noIndexFlag)
+// {
+// tt << "<center>";
+// if (documentedGroups>0)
+// tt << "<a doxygen=\"_doc:\" href=\"/modules.html\">Modules</a> &nbsp; ";
+// if (hierarchyClasses>0)
+// tt << "<a doxygen=\"_doc:\" href=\"/hierarchy.html\">Class hierarchy</a> &nbsp; ";
+// if (annotatedClasses>0)
+// tt << "<a doxygen=\"_doc:\" href=\"/annotated.html\">Compound list</a> &nbsp; ";
+// if (documentedFiles>0)
+// tt << "<a doxygen=\"_doc:\" href=\"/files.html\">File list</a> &nbsp; ";
+// if (includeFiles.count()>0)
+// tt << "<a doxygen=\"_doc:\" href=\"/headers.html\">Header files</a> &nbsp; ";
+// if (documentedMembers>0)
+// tt << "<a doxygen=\"_doc:\" href=\"/functions.html\">Compound Members</a> &nbsp; ";
+// if (documentedFunctions>0)
+// tt << "<a doxygen=\"_doc:\" href=\"/globals.html\">File Members</a> &nbsp; ";
+// if (pageList.count()>0)
+// tt << "<a doxygen=\"_doc:\" href=\"/pages.html\">Related Pages</a> &nbsp; ";
+// if (exampleList.count()>0)
+// tt << "<a doxygen=\"_doc:\" href=\"/examples.html\">Examples</a> &nbsp; ";
+// if (searchEngineFlag)
+// tt << "<a doxygen=\"_cgi:\" href=\"\">Search</a>";
+// tt << endl << "</center><hr>" << endl;
+// }
+// }
+// f.close();
+//
+// f.setName(htmlOutputDir+"/footer.html");
+// if (f.open(IO_WriteOnly))
+// {
+// QTextStream tt(&f);
+// if (footer.length()==0)
+// {
+// tt << "<hr><address><small>Generated at " << dateToString(TRUE);
+// if (projectName.length()>0) tt << " for " << projectName;
+// tt << " by <a href=\"http://www.stack.nl/~dimitri/doxygen/index.html\">"
+// "doxygen</a>&nbsp; written by <a href="
+// "\"mailto:dimitri@stack.nl\">Dimitri van Heesch</a>, &copy; "
+// "1997-1999</small></address>\n</body>\n</html>\n";
+// }
+// else
+// {
+// tt << footer;
+// }
+// }
+// f.close();
+//}
+
+void HtmlGenerator::startFile(const char *name,const char *title,bool external)
+{
+ QString fileName=name;
+ if (fileName.right(5)!=".html") fileName+=".html";
+ startPlainFile(fileName);
+ if (header.length()==0)
+ {
+ t << "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\">\n"
+ "<html><head><meta name=\"robots\" content=\"noindex\">\n"
+ "<title>" << title << "</title>\n";
+ t << "<link ";
+ if (external)
+ t << "doxygen=\"_doc:\" href=\"/";
+ else
+ t << "href=\"";
+ t << "doxygen.css\" rel=\"stylesheet\" type=\"text/css\">\n"
+ "</head><body bgcolor=\"#ffffff\">\n";
+ }
+ else
+ {
+ t << header;
+ }
+
+// if (!noIndexFlag)
+// {
+// t << "<center>";
+// if (documentedGroups>0)
+// t << "<a href=\"modules.html\">Modules</a> &nbsp; ";
+// if (hierarchyClasses>0)
+// t << "<a href=\"hierarchy.html\">Class hierarchy</a> &nbsp; ";
+// if (annotatedClasses>0)
+// t << "<a href=\"annotated.html\">Compound list</a> &nbsp; ";
+// if (documentedFiles>0)
+// t << "<a href=\"files.html\">File list</a> &nbsp; ";
+// if (includeFiles.count()>0)
+// t << "<a href=\"headers.html\">Header files</a> &nbsp; ";
+// if (documentedMembers>0)
+// t << "<a href=\"functions.html\">Compound Members</a> &nbsp; ";
+// if (documentedFunctions>0)
+// t << "<a href=\"globals.html\">File Members</a> &nbsp; ";
+// if (pageList.count()>0)
+// t << "<a href=\"pages.html\">Related Pages</a> &nbsp; ";
+// if (exampleList.count()>0)
+// t << "<a href=\"examples.html\">Examples</a> &nbsp; ";
+// if (searchEngineFlag)
+// t << "<a doxygen=\"_cgi:\" href=\"\">Search</a>";
+// t << endl << "</center><hr>" << endl;
+// }
+}
+
+void HtmlGenerator::startQuickIndexItem(const char *s,const char *l)
+{
+ t << "<a ";
+ if (s) t << "doxygen=\"" << s << "\" ";
+ t << "href=\"" << l << "\">";
+}
+
+void HtmlGenerator::endQuickIndexItem()
+{
+ t << "</a> &nbsp; ";
+}
+
+void HtmlGenerator::writeFooter(int part,bool external)
+{
+ switch (part)
+ {
+ case 0:
+ if (footer.length()==0)
+ t << "<hr><address><small>";
+ else
+ t << footer;
+ break;
+ case 1:
+ if (footer.length()==0)
+ {
+ t << " <a href=\"http://www.stack.nl/~dimitri/doxygen/index.html\">";
+ t << "<img ";
+ if (external)
+ {
+ t << "doxygen=\"_doc:\" src=\"/";
+ }
+ else
+ {
+ t << "src=\"";
+ }
+ t << "doxygen.gif\" alt=\"doxygen\" align=center border=0 "
+ "width=118 height=53></a>&nbsp; ";
+ }
+ break;
+ default:
+ if (footer.length()==0)
+ t << " <a href=\"mailto:dimitri@stack.nl\">Dimitri van Heesch</a>, &copy; "
+ "1997-1999</small></address>\n</body>\n</html>\n";
+ break;
+
+ }
+}
+
+void HtmlGenerator::endFile()
+{
+// if (footer.length()==0)
+// {
+// t << "<hr><address><small>Generated at " << dateToString(TRUE);
+// if (projectName.length()>0)
+// {
+// t << " for ";
+// docify(projectName);
+// }
+// t << " by <a href=\"http://www.stack.nl/~dimitri/doxygen/index.html\">"
+// "<img src=\"doxygen.gif\" alt=\"doxygen\" align=center border=0 "
+// "width=118 height=53></a>&nbsp; written by <a href="
+// "\"mailto:dimitri@stack.nl\">Dimitri van Heesch</a>, &copy; "
+// "1997-1999</small></address>\n</body>\n</html>\n";
+// }
+// else
+// {
+// t << footer;
+// }
+ endPlainFile();
+}
+
+void HtmlGenerator::startProjectNumber()
+{
+ t << "<h3 align=center>";
+}
+
+void HtmlGenerator::endProjectNumber()
+{
+ t << "</h3>";
+}
+
+//void HtmlGenerator::writeIndex()
+//{
+// startFile("index.html","Main Index");
+// t << "<h1 align=center>";
+// docify(projectName);
+// t << " Documentation</h1>"
+// << "<p>" << endl << "<p>" << endl;
+// if (!projectNumber.isEmpty())
+// {
+// t << "<h3 align=center>";
+// docify(projectNumber);
+// t << "</h3>\n<p>\n<p>\n";
+// }
+// if (noIndexFlag)
+// {
+// t << "<ul>" << endl;
+// if (hierarchyClasses>0)
+// t << "<li><a href=\"hierarchy.html\">Class hierarchy</a>" << endl;
+// if (annotatedClasses>0)
+// t << "<li><a href=\"annotated.html\">Compound list</a>" << endl;
+// if (documentedFiles>0)
+// t << "<li><a href=\"files.html\">File list</a>" << endl;
+// if (includeFiles.count()>0)
+// t << "<li><a href=\"headers.html\">Header files</a>" << endl;
+// if (documentedMembers>0)
+// t << "<li><a href=\"functions.html\">Compound Members</a>" << endl;
+// if (documentedFunctions>0)
+// t << "<li><a href=\"globals.html\">File Members</a>" << endl;
+// if (pageList.count()>0)
+// t << "<li><a href=\"pageList.html\">Related Pages</a>" << endl;
+// if (exampleList.count()>0)
+// t << "<li><a href=\"examples.html\">Examples</a>" << endl;
+// if (searchEngineFlag)
+// t << "<li><a doxygen=\"_cgi:\" href=\"\">Search</a>" << endl;
+// t << "</ul>" << endl;
+// }
+// endFile();
+//}
+
+void HtmlGenerator::writeStyleInfo(int part)
+{
+ if (part==0)
+ {
+ startPlainFile("doxygen.css");
+ t << "H1 { border-width: thin; border: solid; text-align: center }" << endl
+ << "A.el { text-decoration: none; font-weight: bold }" << endl
+ << "DL.el { margin-left: -1cm }" << endl
+ << "DIV.fragment { width: 100%; border: none; background-color: #eeeeee }" << endl
+ << "DIV.in { margin-left: 16 }" << endl
+ << endl;
+ endPlainFile();
+ }
+}
+
+void HtmlGenerator::writeDoxyAnchor(const char *,const char *anchor, const char *name)
+{
+ t << "<a name=\"" << anchor << "\" doxytag=\"" << name << "\"></a>";
+}
+
+void HtmlGenerator::newParagraph()
+{
+ t << endl << "<p>" << endl;
+}
+
+void HtmlGenerator::writeString(const char *text)
+{
+ t << text;
+}
+
+void HtmlGenerator::writeIndexItem(const char *ref,const char *f,
+ const char *name)
+{
+ t << "<li>";
+ if (ref || f)
+ {
+ t << "<a class=\"el\" ";
+ if (ref) t << "doxygen=\"" << ref << ":\" ";
+ t << "href=\"";
+ if (f) t << f << ".html\">";
+ }
+ else
+ {
+ t << "<b>";
+ }
+ docify(name);
+ if (ref || f)
+ {
+ t << "</a>" << endl;
+ }
+ else
+ {
+ t << "</b>";
+ }
+}
+
+void HtmlGenerator::writeStartAnnoItem(const char *,const char *f,
+ const char *path,const char *name)
+{
+ t << "<li>";
+ if (path) docify(path);
+ t << "<a class=\"el\" href=\"" << f << ".html\">";
+ docify(name);
+ t << "</a> ";
+}
+
+void HtmlGenerator::writeObjectLink(const char *ref,const char *f,
+ const char *anchor, const char *name)
+{
+ t << "<a class=\"el\" ";
+ if (ref) t << "doxygen=\"" << ref << ":\" ";
+ t << "href=\"";
+ if (f) t << f << ".html";
+ if (anchor) t << "#" << anchor;
+ t << "\">";
+ docify(name);
+ t << "</a>";
+}
+
+void HtmlGenerator::startTextLink(const char *f,const char *anchor)
+{
+ t << "<a href=\"";
+ if (f) t << f << ".html";
+ if (anchor) t << "#" << anchor;
+ t << "\">";
+}
+
+void HtmlGenerator::endTextLink()
+{
+ t << "</a>";
+}
+
+void HtmlGenerator::writeHtmlLink(const char *url,const char *text)
+{
+ t << "<a href=\"";
+ if (url) t << url;
+ t << "\">";
+ docify(text);
+ t << "</a>";
+}
+
+void HtmlGenerator::startGroupHeader()
+{
+ t << "<h2>";
+}
+
+void HtmlGenerator::endGroupHeader()
+{
+ t << "</h2>" << endl;
+}
+
+void HtmlGenerator::writeSection(const char *lab,const char *title,bool sub)
+{
+ t << "<a name=\"" << lab << "\">";
+ if (sub) t << "<h3>"; else t << "<h2>";
+ docify(title);
+ if (sub) t << "</h3>"; else t << "</h2>";
+ t << "</a>" << endl;
+}
+
+void HtmlGenerator::writeSectionRef(const char *name,const char *lab,
+ const char *title)
+{
+ QString refName=name;
+ if (refName.right(5)!=".html") refName+=".html";
+ t << "&quot;<a href=\"" << refName << "#" << lab << "\">";
+ docify(title);
+ t << "</a>&quot;";
+}
+
+void HtmlGenerator::writeSectionRefItem(const char *name,const char *lab,
+ const char *title)
+{
+ QString refName=name;
+ if (refName.right(5)!=".html") refName+=".html";
+ t << "<a href=\"" << refName << "#" << lab << "\">";
+ docify(title);
+ t << "</a>";
+}
+
+//void HtmlGenerator::docify(const char *str)
+//{
+// docifyStatic(t,str);
+//}
+
+//void HtmlGenerator::docifyStatic(QTextStream &t,const char *str)
+void HtmlGenerator::docify(const char *str)
+{
+ if (str)
+ {
+ const char *p=str;
+ char c;
+ while (*p)
+ {
+ c=*p++;
+ switch(c)
+ {
+ case '<': t << "&lt;"; break;
+ case '>': t << "&gt;"; break;
+ case '&': t << "&amp;"; break;
+ case '\\':
+ if (*p=='<')
+ { t << "&lt;"; p++; }
+ else if (*p=='>')
+ { t << "&gt;"; p++; }
+ else
+ t << "\\";
+ break;
+ default: t << c;
+ }
+ }
+ }
+}
+
+void HtmlGenerator::codify(const char *str)
+{
+ docify(str);
+}
+
+void HtmlGenerator::writeChar(char c)
+{
+ char cs[2];
+ cs[0]=c;
+ cs[1]=0;
+ docify(cs);
+}
+
+void HtmlGenerator::startClassDiagram()
+{
+ t << "<p>";
+}
+
+void HtmlGenerator::endClassDiagram(ClassDiagram &d,
+ const char *fileName,const char *name)
+{
+ t << ":\n<p><center><img src=\""
+ << fileName << ".gif\" usemap=\"#" << name << "_map\""
+ << " border=\"0\"></center>" << endl
+ << "<map name=\"" << name << "_map\"><p>" << endl;
+
+ d.writeImageMap(t,dir,fileName);
+}
+
+void HtmlGenerator::startColorFont(uchar red,uchar green,uchar blue)
+{
+ QString colorString;
+ colorString.sprintf("%02x%02x%02x",red,green,blue);
+ t << "<font color=\"#" << colorString << "\">";
+}
+
+void HtmlGenerator::endColorFont()
+{
+ t << "</font>";
+}
+
+void HtmlGenerator::writeFormula(const char *n,const char *text)
+{
+ if (text && text[0]=='\\') t << "<p><center>" << endl;
+ t << "<img align=\"top\" src=\"" << n << "\">" << endl;
+ if (text && text[0]=='\\') t << "</center></p>" << endl;
+}
diff --git a/src/htmlgen.h b/src/htmlgen.h
new file mode 100644
index 0000000..c8a5223
--- /dev/null
+++ b/src/htmlgen.h
@@ -0,0 +1,174 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#ifndef HTMLGEN_H
+#define HTMLGEN_H
+
+#include "outputgen.h"
+
+class QFile;
+
+class HtmlGenerator : public OutputGenerator
+{
+ public:
+ HtmlGenerator();
+ ~HtmlGenerator();
+
+ OutputGenerator *copy() { return new HtmlGenerator; }
+ //OutputGenerator *clone() { return new HtmlGenerator(*this); }
+ void append(const OutputGenerator *o);
+ void enable() { active=TRUE; }
+ void disable() { active=FALSE; }
+ void enableIf(OutputType o) { if (o==Html) active=TRUE; }
+ void disableIf(OutputType o) { if (o==Html) active=FALSE; }
+ void disableIfNot(OutputType o) { if (o!=Html) active=FALSE; }
+ bool isEnabled(OutputType o) { return (o==Html && active); }
+ OutputGenerator *get(OutputType o) { return (o==Html) ? this : 0; }
+
+ static void init();
+ //void generateExternalIndex();
+ void startFile(const char *name,const char *title,bool external);
+ void writeFooter(int,bool);
+ void endFile();
+ void clearBuffer();
+
+ //void writeIndex();
+ void startIndexSection(IndexSections) {}
+ void endIndexSection(IndexSections) {}
+ void startProjectNumber();
+ void endProjectNumber();
+ void writeStyleInfo(int part);
+ void startTitleHead() { startTitle(); }
+ void endTitleHead(const char *) { endTitle(); }
+ void startTitle() { t << "<h1>"; }
+ void endTitle() { t << "</h1>"; }
+
+ void newParagraph();
+ void writeString(const char *text);
+ void startIndexList() { t << "<ul>" << endl; }
+ void endIndexList() { t << "</ul>" << endl; }
+ void startItemList() { t << "<ul>" << endl; }
+ void endItemList() { t << "</ul>" << endl; }
+ void startEnumList() { t << "<ol>" << endl; }
+ void endEnumList() { t << "</ol>" << endl; }
+ void writeIndexItem(const char *ref,const char *file,const char *name);
+ void docify(const char *text);
+ void codify(const char *text);
+ void writeObjectLink(const char *ref,const char *file,
+ const char *anchor,const char *name);
+ void writeCodeLink(const char *ref,const char *f,
+ const char *anchor,const char *name)
+ { writeObjectLink(ref,f,anchor,name); }
+ void startTextLink(const char *file,const char *anchor);
+ void endTextLink();
+ void writeHtmlLink(const char *url,const char *text);
+ void startTypewriter() { t << "<code>"; }
+ void endTypewriter() { t << "</code>"; }
+ void startGroupHeader();
+ void endGroupHeader();
+ void writeListItem() { t << "<li>"; }
+
+ void startMemberHeader() { startGroupHeader(); }
+ void endMemberHeader() { endGroupHeader(); }
+ void startMemberList() { t << "<ul>" << endl; }
+ void endMemberList() { t << "</ul>" << endl; }
+ void startMemberItem() { t << "<li>"; }
+ void endMemberItem() { t << endl; }
+
+ void writeRuler() { t << "<hr>"; }
+ void writeAnchor(const char *name)
+ { t << "<a name=\"" << name <<"\"></a>"; }
+ void startCodeFragment() { t << "<div class=\"fragment\"><pre>"; }
+ void endCodeFragment() { t << "</div></pre>"; }
+ void writeBoldString(const char *text)
+ { t << "<b>"; docify(text); t << "</b>"; }
+ void startEmphasis() { t << "<em>"; }
+ void endEmphasis() { t << "</em>"; }
+ void startBold() { t << "<b>"; }
+ void endBold() { t << "</b>"; }
+ void startDescription() { t << endl << "<dl compact>" << endl; }
+ void endDescription() { t << endl << "</dl>" << endl; }
+ void startDescItem() { t << "<dt>"; }
+ void endDescItem() { t << "<dd>"; }
+ void lineBreak() { t << "<br>" << endl; }
+ void writeChar(char c);
+ void startMemberDoc(const char *,const char *,const char *)
+ { t << endl << "<h3>"; }
+ void endMemberDoc() { t << "</h3>" << endl; }
+ void writeDoxyAnchor(const char *clName,const char *anchor,
+ const char *name);
+ void writeLatexSpacing() {}
+ void writeStartAnnoItem(const char *type,const char *file,
+ const char *path,const char *name);
+ void writeEndAnnoItem(const char *) { t << endl; }
+ void startSubsection() { t << "<h2>"; }
+ void endSubsection() { t << "</h2>" << endl; }
+ void startSubsubsection() { t << "<h3>"; }
+ void endSubsubsection() { t << "</h3>" << endl; }
+ void startCenter() { t << "<center>" << endl; }
+ void endCenter() { t << "</center>" << endl; }
+ void startSmall() { t << "<small>" << endl; }
+ void endSmall() { t << "</small>" << endl; }
+ void startSubscript() { t << "<sub>"; }
+ void endSubscript() { t << "</sub>"; }
+ void startSuperscript() { t << "<sup>"; }
+ void endSuperscript() { t << "</sup>"; }
+ void startTable(int) { t << "<table border=1 cellspacing=3 cellpadding=3>"; }
+ void endTable() { t << "</table>" << endl; }
+ void nextTableRow() { t << endl << "<tr><td>"; }
+ void endTableRow() { t << "</tr>" << endl; }
+ void nextTableColumn() { t << "<td>"; }
+ void endTableColumn() { t << "</td>"; }
+ void writeCopyright() { t << "&copy;"; }
+ void writeQuote() { t << "&quot;"; }
+ void writeUmlaut(char c) { t << "&" << c << "uml;"; }
+ void writeAcute(char c) { t << "&" << c << "acute;"; }
+ void writeGrave(char c) { t << "&" << c << "grave;"; }
+ void writeCirc(char c) { t << "&" << c << "circ;"; }
+ void writeTilde(char c) { t << "&" << c << "tilde;"; }
+ void startMemberDescription() { t << "<dl class=\"el\"><dd><font size=-1><em>"; }
+ void endMemberDescription() { t << "</em></font></dl>"; }
+ void startDescList() { t << "<dl compact><dt>" << endl; }
+ void endDescTitle() {}
+ void writeDescItem() { t << "<dd>" << endl; }
+ void endDescList() { t << "</dl>"; }
+ void writeSection(const char *,const char *,bool);
+ void writeSectionRef(const char *,const char *,const char *);
+ void writeSectionRefItem(const char *,const char *,const char *);
+ void addToIndex(const char *,const char *) {}
+ void startIndent() { t << "<div class=\"in\">" << endl; }
+ void endIndent() { t << "</div>" << endl; }
+ void writeSynopsis() {}
+ void startClassDiagram();
+ void endClassDiagram(ClassDiagram &,const char *,const char *);
+ void startColorFont(uchar r,uchar g,uchar b);
+ void endColorFont();
+ void writePageRef(const char *,const char *) {}
+ void startQuickIndexItem(const char *,const char *);
+ void endQuickIndexItem();
+ void writeFormula(const char *,const char *);
+
+ //static void docifyStatic(QTextStream &t,const char *str);
+
+ private:
+ QString header;
+ QString footer;
+
+ HtmlGenerator &operator=(const HtmlGenerator &g);
+ HtmlGenerator(const HtmlGenerator &g);
+};
+
+#endif
diff --git a/src/image.cpp b/src/image.cpp
new file mode 100644
index 0000000..853d4ea
--- /dev/null
+++ b/src/image.cpp
@@ -0,0 +1,443 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#include "image.h"
+#include "gifenc.h"
+#include <qglobal.h>
+#include <qstring.h>
+
+const int charSetWidth=80;
+const int charHeight=12;
+const int numChars=96;
+
+unsigned short charPos[numChars] =
+ {
+ 0, 5, 8, 13, 20, 27, 38, 47,
+ 50, 54, 58, 65, 72, 76, 83, 87,
+ 91, 98,105,112,119,126,133,140,
+ 147,154,161,164,167,174,181,188,
+ 195,207,216,224,233,242,250,258,
+ 267,276,279,286,294,301,312,321,
+ 331,339,349,357,365,372,380,389,
+ 400,409,418,427,430,434,437,443,
+ 450,453,460,467,474,481,488,492,
+ 499,506,509,512,518,521,530,537,
+ 544,551,557,562,568,571,578,585,
+ 594,600,607,613,617,620,624,631
+ };
+
+unsigned char charWidth[numChars] =
+ {
+ 5, 3, 5, 7, 7,11, 9, 3,
+ 4, 4, 7, 7, 4, 7, 4, 4,
+
+ 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 3, 3, 7, 7, 7, 7,
+ 12, 9, 8, 9, 9, 8, 8, 9,
+ 9, 3, 7, 8, 7,11, 9,10,
+ 8,10, 8, 8, 7, 8, 9,11,
+ 9, 9, 9, 3, 4, 3, 6, 7,
+ 3, 7, 7, 7, 7, 7, 4, 7,
+ 7, 3, 3, 6, 3, 9, 7, 7,
+ 7, 6, 5, 6, 3, 7, 7, 9,
+ 6, 7, 6, 4, 3, 4, 7, 5
+ };
+
+unsigned char fontRaw[charSetWidth*charHeight] = {
+ 0x02, 0x50, 0x01, 0x06, 0x20, 0x60, 0xc6, 0x04, 0x00, 0x00, 0x00, 0x27,
+ 0x04, 0x1c, 0x38, 0x11, 0xf1, 0xc7, 0xc7, 0x0e, 0x00, 0x00, 0x00, 0x03,
+ 0x81, 0xf0, 0x10, 0x7c, 0x1e, 0x3e, 0x1f, 0x9f, 0x87, 0x88, 0x24, 0x09,
+ 0x09, 0x02, 0x02, 0x41, 0x0f, 0x0f, 0x83, 0xc3, 0xe1, 0xe7, 0xf4, 0x24,
+ 0x12, 0x22, 0x41, 0x20, 0x9f, 0xce, 0x30, 0x00, 0x10, 0x04, 0x00, 0x01,
+ 0x00, 0x30, 0x08, 0x12, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0xac, 0x00, 0x00, 0x02, 0x51, 0x43, 0x89,
+ 0x40, 0x90, 0x49, 0x15, 0x00, 0x00, 0x00, 0x28, 0x9c, 0x22, 0x44, 0x31,
+ 0x02, 0x20, 0x48, 0x91, 0x00, 0x00, 0x00, 0x04, 0x46, 0x08, 0x28, 0x42,
+ 0x21, 0x21, 0x10, 0x10, 0x08, 0x48, 0x24, 0x09, 0x11, 0x03, 0x06, 0x61,
+ 0x10, 0x88, 0x44, 0x22, 0x12, 0x10, 0x84, 0x24, 0x12, 0x22, 0x22, 0x20,
+ 0x80, 0x4a, 0x11, 0x00, 0x20, 0x04, 0x00, 0x01, 0x00, 0x40, 0x08, 0x00,
+ 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00,
+ 0x02, 0x22, 0x00, 0x00, 0x02, 0x51, 0x45, 0x49, 0x40, 0x90, 0x89, 0x0a,
+ 0x00, 0x00, 0x00, 0x48, 0x84, 0x02, 0x04, 0x51, 0x02, 0x00, 0x88, 0x91,
+ 0x00, 0x00, 0x00, 0x04, 0x44, 0xd4, 0x28, 0x42, 0x40, 0x20, 0x90, 0x10,
+ 0x10, 0x08, 0x24, 0x09, 0x21, 0x03, 0x06, 0x51, 0x20, 0x48, 0x48, 0x12,
+ 0x12, 0x00, 0x84, 0x22, 0x22, 0x22, 0x22, 0x11, 0x00, 0x89, 0x12, 0x80,
+ 0x31, 0xc5, 0x87, 0x0d, 0x1c, 0xe3, 0x4b, 0x12, 0x49, 0x29, 0x16, 0x1c,
+ 0x58, 0x69, 0x4c, 0xe8, 0x91, 0x44, 0x61, 0x44, 0xf2, 0x22, 0x00, 0x00,
+ 0x02, 0x07, 0xe5, 0x06, 0x80, 0x60, 0x10, 0x95, 0x08, 0x00, 0x00, 0x48,
+ 0x84, 0x04, 0x18, 0x51, 0xe2, 0xc0, 0x87, 0x11, 0x24, 0x18, 0x03, 0x00,
+ 0x89, 0x24, 0x44, 0x42, 0x40, 0x20, 0x90, 0x10, 0x10, 0x08, 0x24, 0x09,
+ 0x41, 0x02, 0x8a, 0x51, 0x20, 0x48, 0x48, 0x12, 0x11, 0x80, 0x84, 0x22,
+ 0x21, 0x24, 0x14, 0x11, 0x01, 0x09, 0x14, 0x40, 0x02, 0x26, 0x48, 0x93,
+ 0x22, 0x44, 0xcc, 0x92, 0x51, 0x36, 0x99, 0x22, 0x64, 0x99, 0x92, 0x48,
+ 0x91, 0x44, 0x52, 0x44, 0x12, 0x22, 0x00, 0x00, 0x02, 0x01, 0x43, 0x80,
+ 0x80, 0xa0, 0x10, 0x84, 0x08, 0x00, 0x00, 0x88, 0x84, 0x08, 0x04, 0x90,
+ 0x13, 0x21, 0x08, 0x8f, 0x00, 0x61, 0xf0, 0xc0, 0x8a, 0x24, 0x44, 0x7c,
+ 0x40, 0x20, 0x9f, 0x9f, 0x11, 0xcf, 0xe4, 0x09, 0xc1, 0x02, 0x8a, 0x49,
+ 0x20, 0x4f, 0x88, 0x13, 0xe0, 0x60, 0x84, 0x22, 0x21, 0x54, 0x08, 0x0a,
+ 0x02, 0x08, 0x90, 0x00, 0x00, 0x24, 0x48, 0x11, 0x22, 0x44, 0x48, 0x92,
+ 0x61, 0x24, 0x91, 0x22, 0x44, 0x89, 0x10, 0x48, 0x91, 0x24, 0x8c, 0x44,
+ 0x22, 0x22, 0x64, 0x00, 0x02, 0x07, 0xe1, 0x41, 0x31, 0x14, 0x10, 0x80,
+ 0x3e, 0x07, 0xc0, 0x88, 0x84, 0x10, 0x05, 0x10, 0x12, 0x21, 0x08, 0x81,
+ 0x01, 0x80, 0x00, 0x31, 0x0a, 0x24, 0x7c, 0x42, 0x40, 0x20, 0x90, 0x10,
+ 0x10, 0x48, 0x24, 0x09, 0x21, 0x02, 0x52, 0x45, 0x20, 0x48, 0x08, 0x92,
+ 0x20, 0x10, 0x84, 0x21, 0x41, 0x54, 0x14, 0x04, 0x04, 0x08, 0x90, 0x00,
+ 0x01, 0xe4, 0x48, 0x11, 0x3e, 0x44, 0x48, 0x92, 0x61, 0x24, 0x91, 0x22,
+ 0x44, 0x89, 0x0c, 0x48, 0x8a, 0x24, 0x8c, 0x48, 0x44, 0x21, 0x98, 0x00,
+ 0x02, 0x02, 0x85, 0x41, 0x49, 0x08, 0x10, 0x80, 0x08, 0x00, 0x00, 0x88,
+ 0x84, 0x20, 0x45, 0xf9, 0x12, 0x21, 0x08, 0x81, 0x00, 0x61, 0xf0, 0xc1,
+ 0x0a, 0x68, 0x82, 0x42, 0x40, 0x20, 0x90, 0x10, 0x10, 0x48, 0x24, 0x89,
+ 0x11, 0x02, 0x52, 0x45, 0x20, 0x48, 0x08, 0x52, 0x12, 0x10, 0x84, 0x21,
+ 0x40, 0x88, 0x22, 0x04, 0x08, 0x08, 0x90, 0x00, 0x02, 0x24, 0x48, 0x11,
+ 0x20, 0x44, 0x48, 0x92, 0x51, 0x24, 0x91, 0x22, 0x44, 0x89, 0x02, 0x48,
+ 0x8a, 0x2a, 0x92, 0x28, 0x42, 0x22, 0x00, 0x00, 0x00, 0x02, 0x85, 0x41,
+ 0x49, 0x18, 0x10, 0x80, 0x08, 0x00, 0x01, 0x08, 0x84, 0x20, 0x44, 0x11,
+ 0x12, 0x22, 0x08, 0x91, 0x00, 0x18, 0x03, 0x00, 0x09, 0xb0, 0x82, 0x42,
+ 0x21, 0x21, 0x10, 0x10, 0x08, 0xc8, 0x24, 0x89, 0x09, 0x02, 0x22, 0x43,
+ 0x10, 0x88, 0x04, 0x22, 0x12, 0x10, 0x84, 0x20, 0x80, 0x88, 0x22, 0x04,
+ 0x10, 0x08, 0x50, 0x00, 0x02, 0x26, 0x48, 0x93, 0x22, 0x44, 0xc8, 0x92,
+ 0x49, 0x24, 0x91, 0x22, 0x64, 0x99, 0x12, 0x49, 0x84, 0x11, 0x21, 0x28,
+ 0x82, 0x22, 0x00, 0x00, 0x02, 0x02, 0x83, 0x82, 0x30, 0xe4, 0x10, 0x80,
+ 0x00, 0x20, 0x05, 0x07, 0x04, 0x3e, 0x38, 0x10, 0xe1, 0xc2, 0x07, 0x0e,
+ 0x24, 0x00, 0x00, 0x01, 0x04, 0x00, 0x82, 0x7c, 0x1e, 0x3e, 0x1f, 0x90,
+ 0x07, 0x48, 0x24, 0x71, 0x05, 0xf2, 0x22, 0x41, 0x0f, 0x08, 0x03, 0xd2,
+ 0x11, 0xe0, 0x83, 0xc0, 0x80, 0x88, 0x41, 0x04, 0x1f, 0xc8, 0x50, 0x00,
+ 0x01, 0xd5, 0x87, 0x0d, 0x1c, 0x43, 0x48, 0x92, 0x45, 0x24, 0x91, 0x1c,
+ 0x58, 0x69, 0x0c, 0x66, 0x84, 0x11, 0x21, 0x10, 0xf2, 0x22, 0x00, 0x00,
+ 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x20, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+ 0x03, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x40, 0x02, 0x00, 0x00, 0x00, 0x00, 0x40, 0x08, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x10, 0x02, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x09, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x08, 0x10, 0x1f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x04, 0x40, 0x02,
+ 0x00, 0x00, 0x00, 0x00, 0x40, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20,
+ 0x02, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x30, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x80, 0x04, 0x00, 0x00, 0x00, 0x00,
+ 0x40, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x01, 0xac, 0x00, 0x00
+};
+
+
+#if 0
+const int charSetWidth=68;
+const int charHeight=12;
+const int numChars=80;
+
+unsigned short charPos[numChars] =
+ { 0, 7, 14, 21, 28, 35, 42, 49,
+ 56, 63, 70, 73, 76, 83, 90, 97,
+ 104,116,125,133,142,151,159,167,
+ 176,185,188,195,203,210,221,230,
+ 240,248,258,266,274,281,289,298,
+ 309,318,327,336,339,343,346,352,
+ 359,362,369,376,383,390,397,401,
+ 407,414,417,420,426,429,438,445,
+ 452,459,465,470,476,479,486,493,
+ 502,508,515,521,525,528,532,539
+ };
+
+unsigned char charWidth[numChars] =
+ {
+ 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 3, 3, 7, 7, 7, 7,
+ 12, 9, 8, 9, 9, 8, 8, 9,
+ 9, 3, 7, 8, 7,11, 9,10,
+ 8,10, 8, 8, 7, 8, 9,11,
+ 9, 9, 9, 3, 4, 3, 6, 7,
+ 3, 7, 7, 7, 7, 7, 4, 6,
+ 7, 3, 3, 6, 3, 9, 7, 7,
+ 7, 6, 5, 6, 3, 7, 7, 9,
+ 6, 7, 6, 4, 3, 4, 7, 5
+ };
+
+unsigned char fontRaw[charSetWidth*charHeight] = {
+ 0x38, 0x20, 0xe1, 0xc0, 0x8f, 0x8e, 0x3e, 0x38, 0x70, 0x00, 0x00, 0x00,
+ 0x1c, 0x0f, 0x80, 0x83, 0xe0, 0xf1, 0xf0, 0xfc, 0xfc, 0x3c, 0x41, 0x20,
+ 0x48, 0x48, 0x10, 0x12, 0x08, 0x78, 0x7c, 0x1e, 0x1f, 0x0f, 0x3f, 0xa1,
+ 0x20, 0x91, 0x12, 0x09, 0x04, 0xfe, 0x71, 0x80, 0x00, 0x80, 0x20, 0x00,
+ 0x08, 0x01, 0x80, 0x81, 0x24, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x1a, 0xc0, 0x00, 0x44, 0xe1, 0x12, 0x21,
+ 0x88, 0x11, 0x02, 0x44, 0x88, 0x00, 0x00, 0x00, 0x22, 0x30, 0x41, 0x42,
+ 0x11, 0x09, 0x08, 0x80, 0x80, 0x42, 0x41, 0x20, 0x48, 0x88, 0x18, 0x33,
+ 0x08, 0x84, 0x42, 0x21, 0x10, 0x90, 0x84, 0x21, 0x20, 0x91, 0x11, 0x11,
+ 0x04, 0x02, 0x50, 0x88, 0x01, 0x00, 0x20, 0x00, 0x08, 0x02, 0x00, 0x80,
+ 0x04, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x22, 0x20, 0x00, 0x44, 0x20, 0x10, 0x22, 0x88, 0x10, 0x04, 0x44,
+ 0x88, 0x00, 0x00, 0x00, 0x22, 0x26, 0xa1, 0x42, 0x12, 0x01, 0x04, 0x80,
+ 0x80, 0x80, 0x41, 0x20, 0x49, 0x08, 0x18, 0x32, 0x89, 0x02, 0x42, 0x40,
+ 0x90, 0x90, 0x04, 0x21, 0x11, 0x11, 0x11, 0x10, 0x88, 0x04, 0x48, 0x94,
+ 0x01, 0x8e, 0x2c, 0x38, 0x68, 0xe7, 0x34, 0xb1, 0x24, 0x92, 0x91, 0x61,
+ 0xc5, 0x86, 0x94, 0xce, 0x89, 0x14, 0x46, 0x14, 0x4f, 0x22, 0x20, 0x00,
+ 0x44, 0x20, 0x20, 0xc2, 0x8f, 0x16, 0x04, 0x38, 0x89, 0x20, 0xc0, 0x18,
+ 0x04, 0x49, 0x22, 0x22, 0x12, 0x01, 0x04, 0x80, 0x80, 0x80, 0x41, 0x20,
+ 0x4a, 0x08, 0x14, 0x52, 0x89, 0x02, 0x42, 0x40, 0x90, 0x8c, 0x04, 0x21,
+ 0x11, 0x09, 0x20, 0xa0, 0x88, 0x08, 0x48, 0xa2, 0x00, 0x11, 0x32, 0x44,
+ 0x99, 0x12, 0x4c, 0xc9, 0x25, 0x13, 0x69, 0x92, 0x26, 0x49, 0x99, 0x24,
+ 0x89, 0x14, 0x45, 0x24, 0x41, 0x22, 0x20, 0x00, 0x44, 0x20, 0x40, 0x24,
+ 0x80, 0x99, 0x08, 0x44, 0x78, 0x03, 0x0f, 0x86, 0x04, 0x51, 0x22, 0x23,
+ 0xe2, 0x01, 0x04, 0xfc, 0xf8, 0x8e, 0x7f, 0x20, 0x4e, 0x08, 0x14, 0x52,
+ 0x49, 0x02, 0x7c, 0x40, 0x9f, 0x03, 0x04, 0x21, 0x11, 0x0a, 0xa0, 0x40,
+ 0x50, 0x10, 0x44, 0x80, 0x00, 0x01, 0x22, 0x40, 0x89, 0x12, 0x44, 0x89,
+ 0x26, 0x12, 0x49, 0x12, 0x24, 0x48, 0x91, 0x04, 0x89, 0x12, 0x48, 0xc4,
+ 0x42, 0x22, 0x26, 0x40, 0x44, 0x20, 0x80, 0x28, 0x80, 0x91, 0x08, 0x44,
+ 0x08, 0x0c, 0x00, 0x01, 0x88, 0x51, 0x23, 0xe2, 0x12, 0x01, 0x04, 0x80,
+ 0x80, 0x82, 0x41, 0x20, 0x49, 0x08, 0x12, 0x92, 0x29, 0x02, 0x40, 0x44,
+ 0x91, 0x00, 0x84, 0x21, 0x0a, 0x0a, 0xa0, 0xa0, 0x20, 0x20, 0x44, 0x80,
+ 0x00, 0x0f, 0x22, 0x40, 0x89, 0xf2, 0x44, 0x89, 0x26, 0x12, 0x49, 0x12,
+ 0x24, 0x48, 0x90, 0xc4, 0x88, 0xa2, 0x48, 0xc4, 0x84, 0x42, 0x19, 0x80,
+ 0x44, 0x21, 0x02, 0x2f, 0xc8, 0x91, 0x08, 0x44, 0x08, 0x03, 0x0f, 0x86,
+ 0x08, 0x53, 0x44, 0x12, 0x12, 0x01, 0x04, 0x80, 0x80, 0x82, 0x41, 0x24,
+ 0x48, 0x88, 0x12, 0x92, 0x29, 0x02, 0x40, 0x42, 0x90, 0x90, 0x84, 0x21,
+ 0x0a, 0x04, 0x41, 0x10, 0x20, 0x40, 0x44, 0x80, 0x00, 0x11, 0x22, 0x40,
+ 0x89, 0x02, 0x44, 0x89, 0x25, 0x12, 0x49, 0x12, 0x24, 0x48, 0x90, 0x24,
+ 0x88, 0xa2, 0xa9, 0x22, 0x84, 0x22, 0x20, 0x00, 0x44, 0x21, 0x02, 0x20,
+ 0x88, 0x91, 0x10, 0x44, 0x88, 0x00, 0xc0, 0x18, 0x00, 0x4d, 0x84, 0x12,
+ 0x11, 0x09, 0x08, 0x80, 0x80, 0x46, 0x41, 0x24, 0x48, 0x48, 0x11, 0x12,
+ 0x18, 0x84, 0x40, 0x21, 0x10, 0x90, 0x84, 0x21, 0x04, 0x04, 0x41, 0x10,
+ 0x20, 0x80, 0x42, 0x80, 0x00, 0x11, 0x32, 0x44, 0x99, 0x12, 0x4c, 0x89,
+ 0x24, 0x92, 0x49, 0x12, 0x26, 0x49, 0x91, 0x24, 0x98, 0x41, 0x12, 0x12,
+ 0x88, 0x22, 0x20, 0x00, 0x38, 0x21, 0xf1, 0xc0, 0x87, 0x0e, 0x10, 0x38,
+ 0x71, 0x20, 0x00, 0x00, 0x08, 0x20, 0x04, 0x13, 0xe0, 0xf1, 0xf0, 0xfc,
+ 0x80, 0x3a, 0x41, 0x23, 0x88, 0x2f, 0x91, 0x12, 0x08, 0x78, 0x40, 0x1e,
+ 0x90, 0x8f, 0x04, 0x1e, 0x04, 0x04, 0x42, 0x08, 0x20, 0xfe, 0x42, 0x80,
+ 0x00, 0x0e, 0xac, 0x38, 0x68, 0xe2, 0x34, 0x89, 0x24, 0x52, 0x49, 0x11,
+ 0xc5, 0x86, 0x90, 0xc6, 0x68, 0x41, 0x12, 0x11, 0x0f, 0x22, 0x20, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
+ 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x80, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x04, 0x00, 0x20, 0x00, 0x00, 0x00, 0x04, 0x00, 0x80, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x22, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x40, 0x80, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x00,
+ 0x20, 0x00, 0x00, 0x00, 0x04, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x02,
+ 0x00, 0x22, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x61, 0x80,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x40, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x1a, 0xc0, 0x00
+};
+#endif
+
+static Color palette[] =
+{
+ { 0xff, 0xff, 0xff },
+ { 0x00, 0x00, 0x00 },
+ { 0xff, 0xff, 0xc0 },
+ { 0x9f, 0x9f, 0x60 },
+ { 0x90, 0x00, 0x00 },
+ { 0x00, 0x90, 0x00 },
+ { 0x00, 0x00, 0x90 },
+ { 0xc0, 0xc0, 0xc0 }
+};
+
+static Color palette2[] =
+{
+ { 0xff, 0xff, 0xff },
+ { 0xe0, 0xe0, 0xe0 },
+ { 0xd0, 0xd0, 0xd0 },
+ { 0xc0, 0xc0, 0xc0 },
+ { 0xb0, 0xb0, 0xb0 },
+ { 0xa0, 0xa0, 0xa0 },
+ { 0x90, 0x90, 0x90 },
+ { 0x80, 0x80, 0x80 },
+ { 0x70, 0x70, 0x70 },
+ { 0x60, 0x60, 0x60 },
+ { 0x50, 0x50, 0x50 },
+ { 0x40, 0x40, 0x40 },
+ { 0x30, 0x30, 0x30 },
+ { 0x20, 0x20, 0x20 },
+ { 0x10, 0x10, 0x10 },
+ { 0x00, 0x00, 0x00 }
+};
+
+Image::Image(int w,int h)
+{
+ data = new uchar[w*h];
+ memset(data,0,w*h);
+ width = w;
+ height = h;
+}
+
+Image::~Image()
+{
+ delete[] data;
+}
+
+void Image::setPixel(int x,int y,uchar val)
+{
+ if (x>=0 && x<width && y>=0 && y<height)
+ data[y*width+x] = val;
+}
+
+uchar Image::getPixel(int x,int y) const
+{
+ if (x>=0 && x<width && y>=0 && y<height)
+ return data[y*width+x];
+ else
+ return 0;
+}
+
+void Image::writeChar(int x,int y,char c,uchar fg)
+{
+ if (c>=' ')
+ {
+ int xf,yf,ci=c-' ';
+ int rowOffset=0;
+ int cw = charWidth[ci];
+ int cp = charPos[ci];
+ for (yf=0;yf<charHeight;yf++)
+ {
+ unsigned short bitPattern=0;
+ int bitsLeft=cw;
+ int byteOffset = rowOffset+(cp>>3);
+ int bitOffset = cp&7;
+ // get the bit pattern for row yf of the character from the font data
+ while (bitsLeft>0)
+ {
+ int bits=8-bitOffset;
+ if (bits>bitsLeft) bits=bitsLeft;
+ bitPattern<<=bits;
+ bitPattern|=((fontRaw[byteOffset]<<bitOffset)&0xff)>>(8-bits);
+ bitsLeft-=bits;
+ bitOffset=0;
+ byteOffset++;
+ }
+ int mask=1<<(cw-1);
+ // draw character row yf
+ for (xf=0;xf<cw;xf++)
+ {
+ setPixel(x+xf,y+yf,(bitPattern&mask) ? fg : getPixel(x+xf,y+yf));
+ mask>>=1;
+ }
+ rowOffset+=charSetWidth;
+ }
+ }
+}
+
+void Image::writeString(int x,int y,const char *s,uchar fg)
+{
+ if (s)
+ {
+ char c;
+ while ((c=*s++))
+ {
+ writeChar(x,y,c,fg);
+ x+=charWidth[c-' '];
+ }
+ }
+}
+
+uint stringLength(const char *s)
+{
+ int w=0;
+ if (s)
+ {
+ char c;
+ while ((c=*s++)) w+=charWidth[c-' '];
+ }
+ return w;
+}
+
+void Image::drawHorzLine(int y,int xs,int xe,uchar colIndex,uint mask)
+{
+ int x,i=0,j=0;
+ for (x=xs;x<=xe;x++,j++)
+ {
+ if (j&1) i++;
+ if (mask&(1<<(i&0x1f))) setPixel(x,y,colIndex);
+ }
+}
+
+void Image::drawHorzArrow(int y,int xs,int xe,uchar colIndex,uint mask)
+{
+ drawHorzLine(y,xs,xe,colIndex,mask);
+ int i;
+ for (i=0;i<6;i++)
+ {
+ int h=i>>1;
+ drawVertLine(xe-i,y-h,y+h,colIndex,0xffffffff);
+ }
+}
+
+void Image::drawVertLine(int x,int ys,int ye,uchar colIndex,uint mask)
+{
+ int y,i=0;
+ for (y=ys;y<=ye;y++,i++)
+ {
+ if (mask&(1<<(i&0x1f))) setPixel(x,y,colIndex);
+ }
+}
+
+void Image::drawVertArrow(int x,int ys,int ye,uchar colIndex,uint mask)
+{
+ drawVertLine(x,ys,ye,colIndex,mask);
+ int i;
+ for (i=0;i<6;i++)
+ {
+ int h=i>>1;
+ drawHorzLine(ys+i,x-h,x+h,colIndex,0xffffffff);
+ }
+}
+
+void Image::drawRect(int x,int y,int w,int h,uchar colIndex,uint mask)
+{
+ drawHorzLine(y,x,x+w-1,colIndex,mask);
+ drawHorzLine(y+h-1,x,x+w-1,colIndex,mask);
+ drawVertLine(x,y,y+h-1,colIndex,mask);
+ drawVertLine(x+w-1,y,y+h-1,colIndex,mask);
+}
+
+void Image::fillRect(int x,int y,int width,int height,uchar colIndex,uint mask)
+{
+ int xp,yp,xi,yi;
+ for (yp=y,yi=0;yp<y+height;yp++,yi++)
+ for (xp=x,xi=0;xp<x+width;xp++,xi++)
+ if (mask&(1<<((xi+yi)&0x1f)))
+ setPixel(xp,yp,colIndex);
+}
+
+bool Image::save(const char *fileName,int mode)
+{
+ GifEncoder gifenc(data,
+ mode==0 ? palette : palette2,
+ width,height,
+ mode==0 ? 3 : 4,
+ 0);
+ QFile file(fileName);
+ if (file.open(IO_WriteOnly))
+ {
+ gifenc.writeGIF(file);
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+}
diff --git a/src/image.h b/src/image.h
new file mode 100644
index 0000000..a48a1f8
--- /dev/null
+++ b/src/image.h
@@ -0,0 +1,50 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#ifndef _IMAGE_H
+#define _IMAGE_H
+#include <qglobal.h>
+
+class Image
+{
+ public:
+ Image(int w,int h);
+ ~Image();
+
+ void setPixel(int x,int y,uchar val);
+ uchar getPixel(int x,int y) const;
+ void writeChar(int x,int y,char c,uchar fg);
+ void writeString(int x,int y,const char *s,uchar fg);
+ void drawHorzLine(int y,int xs,int xe,uchar colIndex,uint mask);
+ void drawHorzArrow(int y,int xs,int xe,uchar colIndex,uint mask);
+ void drawVertLine(int x,int ys,int ye,uchar colIndex,uint mask);
+ void drawVertArrow(int x,int ys,int ye,uchar colIndex,uint mask);
+ void drawRect(int x,int y,int width,int height,uchar colIndex,uint mask);
+ void fillRect(int x,int y,int width,int height,uchar colIndex,uint mask);
+ bool save(const char *fileName,int mode=0);
+ friend uint stringLength(const char *s);
+ uint getWidth() const { return width; }
+ uint getHeight() const { return height; }
+ uchar *getData() const { return data; }
+
+ private:
+ int width;
+ int height;
+ uchar *data;
+};
+
+#endif
diff --git a/src/index.cpp b/src/index.cpp
new file mode 100644
index 0000000..d472542
--- /dev/null
+++ b/src/index.cpp
@@ -0,0 +1,975 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#include <qtstream.h>
+#include <qdatetm.h>
+#include <qdir.h>
+#include <stdlib.h>
+
+#include "message.h"
+#include "index.h"
+#include "doxygen.h"
+#include "scanner.h"
+#include "code.h"
+#include "config.h"
+#include "filedef.h"
+#include "outputlist.h"
+#include "util.h"
+#include "groupdef.h"
+#include "language.h"
+
+//----------------------------------------------------------------------------
+
+// strips w from s iff s starts with w
+bool stripWord(QString &s,QString w)
+{
+ bool success=FALSE;
+ if (s.left(w.length())==w)
+ {
+ success=TRUE;
+ s=s.right(s.length()-w.length());
+ }
+ return success;
+}
+
+//----------------------------------------------------------------------------
+// some quasi intelligent brief description abbreviator :^)
+QString abbreviate(const char *s,const char *name)
+{
+ QString result=s;
+ QString start1=(QString)"The "+name+" class ";
+ QString start2=(QString)"The "+name+" widget ";
+ QString start3=(QString)"The "+name+" file ";
+ result=result.simplifyWhiteSpace();
+ // strip trailing .
+ if (result.length()>0 && result.at(result.length()-1)=='.')
+ result=result.left(result.length()-1);
+ bool found=FALSE;
+ found = found || stripWord(result,start1);
+ found = found || stripWord(result,start2);
+ found = found || stripWord(result,start3);
+ if (found)
+ {
+ bool found=FALSE;
+ found = found || stripWord(result,"is ");
+ found = found || stripWord(result,"provides ");
+ found = found || stripWord(result,"specifies ");
+ found = found || stripWord(result,"contains ");
+ found = found || stripWord(result,"represents ");
+ if (found)
+ {
+ stripWord(result,"a ");
+ stripWord(result,"an ");
+ stripWord(result,"the ");
+ }
+ }
+ if (result.length()>0)
+ {
+ int c=result[0];
+ if (c>='a' && c<='z') c+='A'-'a';
+ result[0]=c;
+ }
+ return result;
+}
+
+//----------------------------------------------------------------------------
+
+void initBaseClassHierarchy(BaseClassList *bcl)
+{
+ BaseClassListIterator bcli(*bcl);
+ for ( ; bcli.current(); ++bcli)
+ {
+ ClassDef *cd=bcli.current()->classDef;
+ if (cd->baseClasses()->count()==0) // no base classes => new root
+ {
+ initBaseClassHierarchy(cd->baseClasses());
+ }
+ cd->visited=FALSE;
+ }
+}
+
+//----------------------------------------------------------------------------
+
+void initClassHierarchy(ClassList *cl)
+{
+ ClassListIterator cli(*cl);
+ ClassDef *cd;
+ for ( ; (cd=cli.current()); ++cli)
+ {
+ cd->visited=FALSE;
+ initBaseClassHierarchy(cd->baseClasses());
+ }
+}
+
+//----------------------------------------------------------------------------
+
+bool hasVisibleRoot(BaseClassList *bcl)
+{
+ BaseClassListIterator bcli(*bcl);
+ for ( ; bcli.current(); ++bcli)
+ {
+ ClassDef *cd=bcli.current()->classDef;
+ if (cd->isVisibleExt()) return TRUE;
+ hasVisibleRoot(cd->baseClasses());
+ }
+ return FALSE;
+}
+
+//----------------------------------------------------------------------------
+
+void writeClassTree(OutputList &ol,BaseClassList *bcl,bool hideSuper)
+{
+ BaseClassListIterator bcli(*bcl);
+ bool started=FALSE;
+ for ( ; bcli.current() ; ++bcli)
+ {
+ ClassDef *cd=bcli.current()->classDef;
+ if (cd->isVisibleExt() && hasVisibleRoot(cd->baseClasses()))
+ {
+ if (!started)
+ {
+ ol.startIndexList();
+ started=TRUE;
+ }
+ //printf("Passed...\n");
+ if (cd->hasDocumentation() || cd->isReference())
+ {
+ ol.writeIndexItem(cd->getReference(),cd->classFile(),cd->name());
+ if (cd->isReference())
+ {
+ ol.startTypewriter();
+ ol.docify(" [external]");
+ ol.endTypewriter();
+ }
+ }
+ else
+ {
+ ol.writeIndexItem(0,0,cd->name());
+ }
+ if (!cd->visited && !hideSuper && cd->superClasses()->count()>0)
+ {
+ writeClassTree(ol,cd->superClasses(),cd->visited);
+ cd->visited=TRUE;
+ }
+ }
+ }
+ if (started) ol.endIndexList();
+}
+
+//----------------------------------------------------------------------------
+
+void writeClassHierarchy(OutputList &ol)
+{
+ initClassHierarchy(&classList);
+
+ bool started=FALSE;
+ ClassListIterator cli(classList);
+ for (;cli.current(); ++cli)
+ {
+ ClassDef *cd=cli.current();
+ if (!hasVisibleRoot(cd->baseClasses()))
+ {
+ if (cd->isVisibleExt())
+ {
+ if (!started)
+ {
+ ol.startIndexList();
+ started=TRUE;
+ }
+ if (cd->hasDocumentation() || cd->isReference())
+ {
+ ol.writeIndexItem(cd->getReference(),cd->classFile(),cd->name());
+ if (cd->isReference())
+ {
+ ol.startTypewriter();
+ ol.docify(" [external]");
+ ol.endTypewriter();
+ }
+ }
+ else
+ {
+ ol.writeIndexItem(0,0,cd->name());
+ }
+ }
+ if (!cd->visited && cd->superClasses()->count()>0)
+ {
+ writeClassTree(ol,cd->superClasses(),cd->visited);
+ cd->visited=TRUE;
+ }
+ }
+ }
+ if (started) ol.endIndexList();
+}
+
+//----------------------------------------------------------------------------
+
+int countClassHierarchy()
+{
+ initClassHierarchy(&classList);
+ int count=0;
+ ClassListIterator cli(classList);
+ for ( ; cli.current(); ++cli)
+ {
+ if (cli.current()->superClasses()->count()>0) count++;
+ }
+ return count;
+}
+
+//----------------------------------------------------------------------------
+
+void writeHierarchicalIndex(OutputList &ol)
+{
+ if (hierarchyClasses==0) return;
+ ol.disable(OutputGenerator::Man);
+ startFile(ol,"hierarchy","Hierarchical Index");
+ startTitle(ol);
+ parseDoc(ol,0,0,projectName+" "+theTranslator->trClassHierarchy());
+ endTitle(ol,0);
+ parseDoc(ol,0,0,theTranslator->trClassHierarchyDescription());
+ ol.newParagraph();
+ writeClassHierarchy(ol);
+ endFile(ol);
+ ol.enable(OutputGenerator::Man);
+}
+
+//----------------------------------------------------------------------------
+
+int countFileList()
+{
+ int count=0;
+ FileNameListIterator fnli(inputNameList);
+ FileName *fn;
+ for (;(fn=fnli.current());++fnli)
+ {
+ FileNameIterator fni(*fn);
+ FileDef *fd;
+ for (;(fd=fni.current());++fni)
+ {
+ if (fd->hasDocumentation()) count++;
+ }
+ }
+ return count;
+}
+
+//----------------------------------------------------------------------------
+
+void writeFileIndex(OutputList &ol)
+{
+ if (documentedFiles==0) return;
+ ol.disable(OutputGenerator::Man);
+ startFile(ol,"files","File Index");
+ startTitle(ol);
+ parseDoc(ol,0,0,projectName+" "+theTranslator->trFileList());
+ endTitle(ol,0);
+ ol.newParagraph();
+ parseDoc(ol,0,0,theTranslator->trFileListDescription(extractAllFlag));
+ ol.newParagraph();
+
+ ol.startIndexList();
+ FileName *fn=inputNameList.first();
+ while (fn)
+ {
+ FileDef *fd=fn->first();
+ while (fd)
+ {
+ if (fd->hasDocumentation() && !fd->isReference())
+ {
+ //ol.writeIndexItem(fd->getReference(),fd->diskName(),
+ // fd->name());
+ QString path;
+ if (fullPathNameFlag)
+ {
+ path=fd->getPath().copy();
+ // strip part of the path
+ if (path.left(stripFromPath.length())==stripFromPath)
+ path=path.right(path.length()-stripFromPath.length());
+ }
+
+ ol.writeStartAnnoItem("file",
+ fd->diskName(),
+ path,
+ fd->name()
+ );
+ ol.docify(" (");
+ if (fd->briefDescription())
+ {
+ OutputList briefOutput(&ol);
+ parseDoc(briefOutput,0,0,
+ abbreviate(fd->briefDescription(),fd->name()));
+ ol+=briefOutput;
+ }
+ else
+ {
+ ol.startEmphasis();
+ parseDoc(ol,0,0,theTranslator->trNoDescriptionAvailable());
+ ol.endEmphasis();
+ }
+ ol.docify(")");
+ ol.writeEndAnnoItem(fd->name());
+ }
+ fd=fn->next();
+ }
+ fn=inputNameList.next();
+ }
+ ol.endIndexList();
+ endFile(ol);
+ ol.enable(OutputGenerator::Man);
+}
+
+//----------------------------------------------------------------------------
+
+int countNamespaceList()
+{
+ int count=0;
+ NamespaceListIterator nli(namespaceList);
+ NamespaceDef *nd;
+ for (;(nd=nli.current());++nli)
+ {
+ if (nd->hasDocumentation()) count++;
+ }
+ return count;
+}
+
+//----------------------------------------------------------------------------
+
+void writeNamespaceIndex(OutputList &ol)
+{
+ if (documentedNamespaces==0) return;
+ ol.disable(OutputGenerator::Man);
+ startFile(ol,"namespaces","Namespace Index");
+ startTitle(ol);
+ parseDoc(ol,0,0,projectName+" "+theTranslator->trNamespaceList());
+ endTitle(ol,0);
+ ol.newParagraph();
+ parseDoc(ol,0,0,theTranslator->trNamespaceListDescription(extractAllFlag));
+ ol.newParagraph();
+
+ ol.startIndexList();
+ NamespaceDef *nd=namespaceList.first();
+ while (nd)
+ {
+ if (nd->hasDocumentation())
+ {
+ ol.writeStartAnnoItem("namespace",nd->namespaceFile(),0,nd->name());
+ ol.docify(" (");
+ if (nd->briefDescription())
+ {
+ OutputList briefOutput(&ol);
+ parseDoc(briefOutput,nd->name(),0,
+ abbreviate(nd->briefDescription(),nd->name()));
+ ol+=briefOutput;
+ }
+ else
+ {
+ ol.startEmphasis();
+ parseDoc(ol,0,0,theTranslator->trNoDescriptionAvailable());
+ ol.endEmphasis();
+ }
+ ol.docify(")");
+ ol.writeEndAnnoItem(nd->name());
+ }
+ nd=namespaceList.next();
+ }
+ ol.endIndexList();
+ endFile(ol);
+ ol.enable(OutputGenerator::Man);
+}
+
+//----------------------------------------------------------------------------
+
+int countAnnotatedClasses()
+{
+ int count=0;
+ //ClassDef *cd=classList.first();
+ ClassListIterator cli(classList);
+ ClassDef *cd;
+ for (;(cd=cli.current());++cli)
+ {
+ if (!cd->isReference() && cd->isVisible())
+ {
+ //printf("Annotated class %s\n",cd->name().data());
+ count++;
+ }
+ }
+ return count;
+}
+
+//----------------------------------------------------------------------
+
+void writeAnnotatedClassList(OutputList &ol)
+{
+ ol.startIndexList();
+ //ClassDef *cd=classList.first();
+ //while (cd)
+ ClassListIterator cli(classList);
+ ClassDef *cd;
+ for (;(cd=cli.current());++cli)
+ {
+ if (!cd->isReference() &&
+ //!cd->name().isEmpty() && cd->name()[0]!='@' &&
+ //(cd->protection()!=Private || extractPrivateFlag) &&
+ //(cd->hasDocumentation() || !hideClassFlag)
+ cd->isVisible()
+ )
+ {
+ QString type;
+ switch (cd->compoundType())
+ {
+ case ClassDef::Class: type="class"; break;
+ case ClassDef::Struct: type="struct"; break;
+ case ClassDef::Union: type="union"; break;
+ default: type="unknown"; break; // an error
+ }
+ ol.writeStartAnnoItem(type,cd->classFile(),0,cd->name());
+ ol.docify(" (");
+ if (cd->briefDescription())
+ {
+ OutputList briefOutput(&ol);
+ parseDoc(briefOutput,cd->name(),0,
+ abbreviate(cd->briefDescription(),cd->name()));
+ ol+=briefOutput;
+ }
+ else
+ {
+ ol.startEmphasis();
+ parseDoc(ol,0,0,theTranslator->trNoDescriptionAvailable());
+ ol.endEmphasis();
+ }
+ ol.docify(")");
+ ol.writeEndAnnoItem(cd->name());
+ }
+ cd=classList.next();
+ }
+ ol.endIndexList();
+}
+
+//----------------------------------------------------------------------------
+
+void writeAnnotatedIndex(OutputList &ol)
+{
+ if (annotatedClasses==0) return;
+
+ //if (classList.count()==0) return;
+ ol.disable(OutputGenerator::Man);
+ startFile(ol,"annotated","Annotated Index");
+ startTitle(ol);
+ parseDoc(ol,0,0,projectName+" "+theTranslator->trCompoundList());
+ endTitle(ol,0);
+ parseDoc(ol,0,0,theTranslator->trCompoundListDescription());
+ writeAnnotatedClassList(ol);
+ endFile(ol);
+ ol.enable(OutputGenerator::Man);
+}
+
+//----------------------------------------------------------------------------
+
+void writeMemberList(OutputList &ol)
+{
+ ol.startItemList();
+ MemberName *mn=memberNameList.first();
+ while (mn)
+ {
+ MemberDef *md=mn->first();
+ bool found=FALSE;
+ bool isFunc=FALSE;
+ while (md && !found)
+ {
+ ClassDef *cd;
+ if ((md->isFriend() || md->protection()!=Private || extractPrivateFlag) &&
+ !md->isReference() && md->hasDocumentation() &&
+ md->name()[0]!='@' && (cd=md->memberClass()) &&
+ cd->isVisible()
+ )
+ {
+ found=TRUE;
+ isFunc=md->isFunction();
+ }
+ md=mn->next();
+ }
+ if (found)
+ {
+ ol.writeListItem();
+ ol.docify(substituteClassNames(mn->memberName()));
+ if (isFunc) ol.docify("()");
+ ol.writeString("\n");
+
+ int count=0;
+ md=mn->first();
+ QString prevName;
+ while (md)
+ {
+ ClassDef *cd=md->memberClass();
+ if (cd && (md->isFriend() || md->protection()!=Private || extractPrivateFlag) &&
+ !md->isReference() && md->hasDocumentation() &&
+ prevName!=cd->name() &&
+ cd->isVisible()
+ )
+ {
+ if (count==0)
+ ol.docify(": ");
+ else
+ ol.docify(", ");
+ ol.writeObjectLink(cd->getReference(),cd->classFile(),md->anchor(),
+ cd->name());
+ count++;
+ prevName=cd->name();
+ }
+ md=mn->next();
+ }
+ }
+ mn=memberNameList.next();
+ }
+ ol.endItemList();
+}
+
+//----------------------------------------------------------------------------
+
+int countMemberList()
+{
+ int count=0;
+ MemberName *mn=memberNameList.first();
+ while (mn)
+ {
+ MemberDef *md=mn->first();
+ bool found=FALSE;
+ MemberDef *otherMd=0;
+ ClassDef *cd;
+ while (md && !found)
+ {
+ if ((md->isFriend() || md->protection()!=Private || extractPrivateFlag) &&
+ !md->isReference() && !md->isRelated() && md->hasDocumentation() &&
+ md->name()[0]!='@' && (cd=md->memberClass()) && cd->isVisible())
+ otherMd=md;
+ if ((md->isFriend() || md->protection()!=Private || extractPrivateFlag) &&
+ !md->isReference() && md->isRelated() && md->hasDocumentation() &&
+ md->name()[0]!='@' && (cd=md->memberClass()) && cd->isVisible())
+ found=TRUE;
+ else
+ md=mn->next();
+ }
+ if (found || otherMd) count++;
+ mn=memberNameList.next();
+ }
+ return count;
+}
+
+//----------------------------------------------------------------------------
+
+void writeMemberIndex(OutputList &ol)
+{
+ if (memberNameList.count()==0) return;
+ ol.disable(OutputGenerator::Man);
+ ol.disable(OutputGenerator::Latex);
+ startFile(ol,"functions","Compound Member Index");
+ startTitle(ol);
+ parseDoc(ol,0,0,projectName+" "+theTranslator->trCompoundMembers());
+ endTitle(ol,0);
+ parseDoc(ol,0,0,theTranslator->trCompoundMembersDescription(extractAllFlag));
+ writeMemberList(ol);
+ endFile(ol);
+ ol.enable(OutputGenerator::Latex);
+ ol.enable(OutputGenerator::Man);
+}
+
+//----------------------------------------------------------------------------
+
+void writeFunctionList(OutputList &ol)
+{
+ ol.startItemList();
+ MemberName *mn=functionNameList.first();
+ while (mn)
+ {
+ MemberDef *md=mn->first();
+ bool found=FALSE;
+ while (md && !found)
+ {
+ FileDef *fd=md->getFileDef() ? md->getFileDef() : md->getFileDec();
+ bool hasDocs =
+ (md->getFileDef() && md->getFileDef()->hasDocumentation()) ||
+ (md->getFileDec() && md->getFileDec()->hasDocumentation());
+
+ if (fd && hasDocs &&
+ !md->isReference() &&
+ md->hasDocumentation() &&
+ md->name()[0]!='@') found=TRUE;
+ else
+ md=mn->next();
+ }
+ if (found) // function is documented
+ {
+ ol.writeListItem();
+ ol.docify(md->name());
+ if (md->isFunction()) ol.docify("()");
+ ol.writeString("\n");
+
+ int count=0;
+ md=mn->first();
+ QString prevName;
+ while (md)
+ {
+ FileDef *fd=md->getFileDef() ? md->getFileDef() : md->getFileDec();
+ bool hasDocs =
+ (md->getFileDef() && md->getFileDef()->hasDocumentation()) ||
+ (md->getFileDec() && md->getFileDec()->hasDocumentation());
+ if (fd && hasDocs &&
+ !md->isReference() &&
+ md->hasDocumentation() &&
+ md->name()[0]!='@' &&
+ prevName!=fd->name())
+ {
+ if (count==0)
+ ol.docify(": ");
+ else
+ ol.docify(", ");
+ QString baseName=fd->name().copy();
+ //int s;
+ //if ((s=baseName.findRev("/"))!=-1)
+ // baseName=baseName.right(baseName.length()-s-1);
+ ol.writeObjectLink(fd->getReference(),
+ fd->diskName(),md->anchor(), baseName);
+ count++;
+ prevName=fd->name();
+ }
+ md=mn->next();
+ }
+ }
+ mn=functionNameList.next();
+ }
+ ol.endItemList();
+}
+
+//----------------------------------------------------------------------------
+
+int countFunctionList()
+{
+ int count=0;
+ MemberName *mn=functionNameList.first();
+ while (mn)
+ {
+ MemberDef *md=mn->first();
+ FileDef *fd;
+ bool found=FALSE;
+ while (md && !found)
+ {
+ if (!md->isReference() && md->hasDocumentation() &&
+ md->name()[0]!='@' &&
+ (((fd=md->getFileDef()) && fd->hasDocumentation())
+ ||
+ ((fd=md->getFileDec()) && fd->hasDocumentation())
+ )
+ )
+ found=TRUE;
+ else
+ md=mn->next();
+ }
+ if (found) count++;
+ mn=functionNameList.next();
+ }
+ return count;
+}
+
+//----------------------------------------------------------------------------
+
+void writeFunctionIndex(OutputList &ol)
+{
+ if (documentedFunctions==0) return;
+ ol.disable(OutputGenerator::Man);
+ ol.disable(OutputGenerator::Latex);
+ startFile(ol,"globals","File Member Index");
+ startTitle(ol);
+ parseDoc(ol,0,0,projectName+" "+theTranslator->trFileMembers());
+ endTitle(ol,0);
+ parseDoc(ol,0,0,theTranslator->trFileMembersDescription(extractAllFlag));
+ writeFunctionList(ol);
+ endFile(ol);
+ ol.enable(OutputGenerator::Latex);
+ ol.enable(OutputGenerator::Man);
+}
+
+//----------------------------------------------------------------------------
+
+void writeHeaderFileList(OutputList &ol)
+{
+ if (includeFiles.count()>0)
+ {
+ ol.startItemList();
+ FileDef *fd=includeFiles.first();
+ while (fd)
+ {
+ ol.writeListItem();
+ QString path;
+ if (fullPathNameFlag)
+ {
+ path=fd->getPath().copy();
+ // strip part of the path
+ if (path.left(stripFromPath.length())==stripFromPath)
+ path=path.right(path.length()-stripFromPath.length());
+ }
+ if (!path.isEmpty()) ol.docify(path);
+ ol.writeObjectLink(0,fd->includeName(),0,fd->name());
+ ol.writeString("\n");
+ fd=includeFiles.next();
+ }
+ ol.endItemList();
+ }
+}
+
+//----------------------------------------------------------------------------
+
+void writeHeaderIndex(OutputList &ol)
+{
+ if (includeFiles.count()==0) return;
+ ol.disable(OutputGenerator::Man);
+ ol.disable(OutputGenerator::Latex);
+ startFile(ol,"headers","Header File Index");
+ startTitle(ol);
+ parseDoc(ol,0,0,projectName+" "+theTranslator->trHeaderFiles());
+ endTitle(ol,0);
+ parseDoc(ol,0,0,theTranslator->trHeaderFilesDescription());
+ writeHeaderFileList(ol);
+ endFile(ol);
+ ol.enable(OutputGenerator::Latex);
+ ol.enable(OutputGenerator::Man);
+}
+
+//----------------------------------------------------------------------------
+
+void writeExampleIndex(OutputList &ol)
+{
+ if (exampleList.count()==0) return;
+ ol.disable(OutputGenerator::Man);
+ startFile(ol,"examples","Example Index");
+ startTitle(ol);
+ parseDoc(ol,0,0,projectName+" "+theTranslator->trExamples());
+ endTitle(ol,0);
+ parseDoc(ol,0,0,theTranslator->trExamplesDescription());
+ ol.startIndexList();
+ PageInfo *pi=exampleList.first();
+ while (pi)
+ {
+ ol.writeListItem();
+ QString n=convertSlashes(pi->name,TRUE)+"-example";
+ if (!pi->title.isEmpty())
+ {
+ ol.writeObjectLink(0,n,0,pi->title);
+ }
+ else
+ {
+ ol.writeObjectLink(0,n,0,pi->name);
+ }
+ ol.writeString("\n");
+ pi=exampleList.next();
+ }
+ ol.endIndexList();
+ endFile(ol);
+ ol.enable(OutputGenerator::Man);
+}
+
+//----------------------------------------------------------------------------
+
+void writePageIndex(OutputList &ol)
+{
+ if (pageList.count()==0) return;
+ ol.disable(OutputGenerator::Man);
+ startFile(ol,"pages","Page Index");
+ startTitle(ol);
+ ol.docify(projectName+" "+theTranslator->trRelatedPages());
+ endTitle(ol,0);
+ parseDoc(ol,0,0,theTranslator->trRelatedPagesDescription());
+ ol.startIndexList();
+ PageInfo *pi=pageList.first();
+ while (pi)
+ {
+ QString pageName;
+ if (caseSensitiveNames)
+ pageName=pi->name.copy();
+ else
+ pageName=pi->name.lower();
+ ol.writeListItem();
+ ol.writeObjectLink(0,pageName,0,pi->name);
+ ol.writeString("\n");
+ pi=pageList.next();
+ }
+ ol.endIndexList();
+ endFile(ol);
+ ol.enable(OutputGenerator::Man);
+}
+
+//----------------------------------------------------------------------------
+
+int countGroupList()
+{
+ int count=0;
+ GroupListIterator gli(groupList);
+ GroupDef *gd;
+ for (;(gd=gli.current());++gli)
+ {
+ if (gd->countMembers()>0) count++;
+ gd=groupList.next();
+ }
+ return count;
+}
+
+//----------------------------------------------------------------------------
+
+void writeGroupList(OutputList &ol)
+{
+ ol.startDescription();
+ GroupListIterator gli(groupList);
+ GroupDef *gd;
+ for (;(gd=gli.current());++gli)
+ {
+ if (gd->countMembers()>0)
+ {
+ ol.startDescItem();
+ ol.startTextLink(gd->groupFile(),0);
+ parseDoc(ol,0,0,gd->groupTitle());
+ ol.endTextLink();
+ ol.endDescItem();
+ parseDoc(ol,0,0,gd->briefDescription());
+ ol.newParagraph();
+ }
+ }
+ ol.endDescription();
+}
+
+//----------------------------------------------------------------------------
+
+void writeGroupIndex(OutputList &ol)
+{
+ if (documentedGroups==0) return;
+ ol.disable(OutputGenerator::Man);
+ startFile(ol,"modules","Module Index");
+ startTitle(ol);
+ parseDoc(ol,0,0,projectName+" "+theTranslator->trModules());
+ endTitle(ol,0);
+ parseDoc(ol,0,0,theTranslator->trModulesDescription());
+ writeGroupList(ol);
+ endFile(ol);
+ ol.enable(OutputGenerator::Man);
+}
+
+void writeIndex(OutputList &ol)
+{
+ // save old generator state
+ bool manEnabled = ol.isEnabled(OutputGenerator::Man);
+ bool texEnabled = ol.isEnabled(OutputGenerator::Latex);
+ bool htmEnabled = ol.isEnabled(OutputGenerator::Html);
+
+ QString projPrefix;
+ if (!projectName.isEmpty())
+ {
+ projPrefix=projectName+" ";
+ }
+ // write HTML index
+ ol.disable(OutputGenerator::Man);
+ ol.disable(OutputGenerator::Latex);
+ ol.startFile("index","Main Index",FALSE);
+ if (!noIndexFlag) writeQuickLinks(ol,TRUE);
+ ol.startTitleHead();
+ parseDoc(ol,0,0,projPrefix+theTranslator->trDocumentation());
+ ol.endTitleHead(0);
+ ol.newParagraph();
+ if (!projectNumber.isEmpty())
+ {
+ ol.startProjectNumber();
+ parseDoc(ol,0,0,projectNumber);
+ ol.endProjectNumber();
+ }
+ if (noIndexFlag) writeQuickLinks(ol,FALSE);
+ endFile(ol);
+ ol.disable(OutputGenerator::Html);
+
+ // write LaTeX index
+ ol.enable(OutputGenerator::Latex);
+ ol.startFile("refman",0,FALSE);
+ ol.startIndexSection(isTitlePageStart);
+ parseDoc(ol,0,0,projPrefix+theTranslator->trReferenceManual());
+ if (!projectNumber.isEmpty())
+ {
+ ol.startProjectNumber();
+ parseDoc(ol,0,0,projectNumber);
+ ol.endProjectNumber();
+ }
+ ol.endIndexSection(isTitlePageStart);
+ ol.startIndexSection(isTitlePageAuthor);
+ parseDoc(ol,0,0,theTranslator->trGeneratedBy());
+ ol.endIndexSection(isTitlePageAuthor);
+ if (documentedGroups>0)
+ {
+ ol.startIndexSection(isModuleIndex);
+ parseDoc(ol,0,0,projPrefix+theTranslator->trModuleIndex());
+ ol.endIndexSection(isModuleIndex);
+ }
+ if (hierarchyClasses>0)
+ {
+ ol.startIndexSection(isClassHierarchyIndex);
+ parseDoc(ol,0,0,projPrefix+theTranslator->trHierarchicalIndex());
+ ol.endIndexSection(isClassHierarchyIndex);
+ }
+ if (annotatedClasses>0)
+ {
+ ol.startIndexSection(isCompoundIndex);
+ parseDoc(ol,0,0,projPrefix+theTranslator->trCompoundIndex());
+ ol.endIndexSection(isCompoundIndex);
+ }
+ if (documentedFiles>0)
+ {
+ ol.startIndexSection(isFileIndex);
+ parseDoc(ol,0,0,projPrefix+theTranslator->trFileIndex());
+ ol.endIndexSection(isFileIndex);
+ }
+ if (documentedGroups>0)
+ {
+ ol.startIndexSection(isModuleDocumentation);
+ parseDoc(ol,0,0,projPrefix+theTranslator->trModuleDocumentation());
+ ol.endIndexSection(isModuleDocumentation);
+ }
+ if (annotatedClasses>0)
+ {
+ ol.startIndexSection(isClassDocumentation);
+ parseDoc(ol,0,0,projPrefix+theTranslator->trClassDocumentation());
+ ol.endIndexSection(isClassDocumentation);
+ }
+ if (documentedFiles>0)
+ {
+ ol.startIndexSection(isFileDocumentation);
+ parseDoc(ol,0,0,projPrefix+theTranslator->trFileDocumentation());
+ ol.endIndexSection(isFileDocumentation);
+ }
+ if (exampleList.count()>0)
+ {
+ ol.startIndexSection(isExampleDocumentation);
+ parseDoc(ol,0,0,projPrefix+theTranslator->trExampleDocumentation());
+ ol.endIndexSection(isExampleDocumentation);
+ }
+ if (pageList.count()>0)
+ {
+ ol.startIndexSection(isPageDocumentation);
+ parseDoc(ol,0,0,projPrefix+theTranslator->trPageDocumentation());
+ ol.endIndexSection(isPageDocumentation);
+ }
+ ol.endIndexSection(isEndIndex);
+ endFile(ol);
+
+ // restore generator state
+ if (manEnabled) ol.enable(OutputGenerator::Man);
+ else ol.disable(OutputGenerator::Man);
+ if (texEnabled) ol.enable(OutputGenerator::Latex);
+ else ol.disable(OutputGenerator::Latex);
+ if (htmEnabled) ol.enable(OutputGenerator::Html);
+ else ol.disable(OutputGenerator::Html);
+}
diff --git a/src/index.h b/src/index.h
new file mode 100644
index 0000000..5b3cc67
--- /dev/null
+++ b/src/index.h
@@ -0,0 +1,65 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#ifndef INDEX_H
+#define INDEX_H
+
+#include <qfile.h>
+#include <qtstream.h>
+
+enum IndexSections
+{
+ isTitlePageStart,
+ isTitlePageAuthor,
+ isModuleIndex,
+ isClassHierarchyIndex,
+ isCompoundIndex,
+ isFileIndex,
+ isModuleDocumentation,
+ isClassDocumentation,
+ isFileDocumentation,
+ isExampleDocumentation,
+ isPageDocumentation,
+ isEndIndex
+};
+
+class OutputList;
+
+void writeIndex(OutputList &ol);
+void writeHierarchicalIndex(OutputList &ol);
+void writeClassHierarchy(OutputList &ol);
+void writeFileIndex(OutputList &ol);
+void writeAnnotatedIndex(OutputList &ol);
+void writeAnnotatedClassList(OutputList &ol);
+void writeMemberIndex(OutputList &ol);
+void writeMemberList(OutputList &ol);
+void writeHeaderIndex(OutputList &ol);
+void writeHeaderFileList(OutputList &ol);
+void writeExampleIndex(OutputList &ol);
+void writePageIndex(OutputList &ol);
+void writeFunctionIndex(OutputList &ol);
+void writeGroupIndex(OutputList &ol);
+void writeNamespaceIndex(OutputList &ol);
+
+int countClassHierarchy();
+int countMemberList();
+int countFunctionList();
+int countFileList();
+int countGroupList();
+int countNamespaceList();
+int countAnnotatedClasses();
+
+#endif
diff --git a/src/instdox.cpp b/src/instdox.cpp
new file mode 100644
index 0000000..ad22c89
--- /dev/null
+++ b/src/instdox.cpp
@@ -0,0 +1,164 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <qstring.h>
+#include <qfile.h>
+#include <qfileinf.h>
+#include <qtstream.h>
+
+#include "instdox.h"
+#include "doxygen.h"
+#include "config.h"
+#include "message.h"
+
+void writeInstallScript()
+{
+ QString fileName=htmlOutputDir+"/installdox";
+ QFile f(fileName);
+ if (f.open(IO_WriteOnly))
+ {
+ QTextStream t(&f);
+ t << "#!" << perlPath << endl << endl << "%subst = ( ";
+
+ char *s=tagFileList.first();
+ while (s)
+ {
+ QFileInfo fi(s);
+ t << "\"" << fi.fileName() << "\", \"\"";
+ s=tagFileList.next();
+ if (s) t << ", ";
+ }
+
+ t << ");\n";
+ t << "$quiet = 0;\n";
+ t << "\n";
+ t << "if (open(F,\"search.cfg\"))\n";
+ t << "{\n";
+ t << " $_=<F> ; s/[ \\t\\n]*$//g ; $subst{\"_doc\"} = $_;\n";
+ t << " $_=<F> ; s/[ \\t\\n]*$//g ; $subst{\"_cgi\"} = $_;\n";
+ t << "}\n";
+ t << "\n";
+ t << "while ( @ARGV ) {\n";
+ t << " $_ = shift @ARGV;\n";
+ t << " if ( s/^-// ) {\n";
+ t << " if ( /^l(.*)/ ) {\n";
+ t << " $v = ($1 eq \"\") ? shift @ARGV : $1;\n";
+ t << " ($v =~ /\\/$/) || ($v .= \"/\");\n";
+ t << " $_ = $v;\n";
+ t << " if ( /(.+)\\@(.+)/ ) {\n";
+ t << " if ( exists $subst{$1} ) {\n";
+ t << " $subst{$1} = $2;\n";
+ t << " } else {\n";
+ t << " print STDERR \"Unknown tag file $1 given with option -l\\n\";\n";
+ t << " &usage();\n";
+ t << " }\n";
+ t << " } else {\n";
+ t << " print STDERR \"Argument $_ is invalid for option -l\\n\";\n";
+ t << " &usage();\n";
+ t << " }\n";
+ t << " }\n";
+ t << " elsif ( /^q/ ) {\n";
+ t << " $quiet = 1;\n";
+ t << " }\n";
+ t << " elsif ( /^\\?|^h/ ) {\n";
+ t << " &usage();\n";
+ t << " }\n";
+ t << " else {\n";
+ t << " print STDERR \"Illegal option -$_\\n\";\n";
+ t << " &usage();\n";
+ t << " }\n";
+ t << " }\n";
+ t << " else {\n";
+ t << " push (@files, $_ );\n";
+ t << " }\n";
+ t << "}\n";
+ t << "\n";
+ t << "foreach $sub (keys %subst)\n";
+ t << "{\n";
+ t << " if ( $subst{$sub} eq \"\" ) \n";
+ t << " {\n";
+ t << " print STDERR \"No substitute given for tag file `$sub'\\n\";\n";
+ t << " &usage();\n";
+ t << " }\n";
+ t << " elsif ( ! $quiet && $sub!=\"_doc\" && $sub!=\"_cgi\" )\n";
+ t << " {\n";
+ t << " print \"Substituting $subst{$sub} for each occurence of tag file $sub\\n\"; \n";
+ t << " }\n";
+ t << "}\n";
+ t << "\n";
+ t << "if ( ! @files ) {\n";
+ t << " if (opendir(D,\".\")) {\n";
+ t << " foreach $file ( readdir(D) ) {\n";
+ t << " $match = \".html\";\n";
+ t << " next if ( $file =~ /^\\.\\.?$/ );\n";
+ t << " ($file =~ /$match/) && (push @files, $file);\n";
+ t << " }\n";
+ t << " closedir(D);\n";
+ t << " }\n";
+ t << "}\n";
+ t << "\n";
+ t << "if ( ! @files ) {\n";
+ t << " print STDERR \"Warning: No input files given and non found!\\n\";\n";
+ t << "}\n";
+ t << "\n";
+ t << "foreach $f (@files)\n";
+ t << "{\n";
+ t << " if ( ! $quiet ) {\n";
+ t << " print \"Editing: $f...\\n\";\n";
+ t << " }\n";
+ t << " $oldf = $f;\n";
+ t << " $f .= \".bak\";\n";
+ t << " unless (rename $oldf,$f) {\n";
+ t << " print STDERR \"Error: cannot rename file $oldf\\n\";\n";
+ t << " exit 1;\n";
+ t << " }\n";
+ t << " if (open(F,\"<$f\")) {\n";
+ t << " unless (open(G,\">$oldf\")) {\n";
+ t << " print STDERR \"Error: opening file $oldf for writing\\n\";\n";
+ t << " exit 1;\n";
+ t << " }\n";
+ t << " while (<F>) {\n";
+ t << " s/doxygen\\=\\\"([^ \\\"\\:\\t\\>\\<]*)\\:([^ \\\"\\t\\>\\<]*)\\\" (href|src)=\\\"\\2/doxygen\\=\\\"$1:$subst{$1}\\\" \\3=\\\"$subst{$1}/g;\n";
+ t << " print G \"$_\";\n";
+ t << " }\n";
+ t << " } \n";
+ t << " else {\n";
+ t << " print STDERR \"Warning file $f does not exist\\n\";\n";
+ t << " }\n";
+ t << " unlink $f;\n";
+ t << "}\n";
+ t << "\n";
+ t << "sub usage {\n";
+ t << " print STDERR \"Usage: installdox [options] [html-file [html-file ...]]\\n\";\n";
+ t << " print STDERR \"Options:\\n\";\n";
+ t << " print STDERR \" -l tagfile\\@linkName tag file + URL or directory \\n\";\n";
+ t << " print STDERR \" -q Quiet mode\\n\\n\";\n";
+ t << " exit 1;\n";
+ t << "}\n";
+ }
+ else
+ {
+ err("Error: Cannot open file %s for writing\n",fileName.data());
+ }
+ f.close();
+ struct stat stat_struct;
+ stat(fileName,&stat_struct);
+#if !defined(_WIN32)
+ chmod(fileName,stat_struct.st_mode|S_IXUSR|S_IXGRP|S_IXOTH);
+#endif
+}
diff --git a/src/instdox.h b/src/instdox.h
new file mode 100644
index 0000000..a149310
--- /dev/null
+++ b/src/instdox.h
@@ -0,0 +1,22 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#ifndef INSTDOX_H
+#define INSTDOX_H
+
+extern void writeInstallScript();
+
+#endif
diff --git a/src/language.cpp b/src/language.cpp
new file mode 100644
index 0000000..f5e2dde
--- /dev/null
+++ b/src/language.cpp
@@ -0,0 +1,61 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#include "language.h"
+#include "translator_nl.h"
+#include "translator_se.h"
+#include "translator_cz.h"
+#include "translator_fr.h"
+#include "translator_it.h"
+#include <qstring.h>
+
+#define L_EQUAL(a) !stricmp(langName,a)
+
+Translator *theTranslator=0;
+
+bool setTranslator(const char *langName)
+{
+ if (L_EQUAL("english"))
+ {
+ theTranslator=new Translator;
+ }
+ else if (L_EQUAL("dutch"))
+ {
+ theTranslator=new TranslatorDutch;
+ }
+ else if (L_EQUAL("swedish"))
+ {
+ theTranslator=new TranslatorSwedish;
+ }
+ else if (L_EQUAL("czech"))
+ {
+ theTranslator=new TranslatorCzech;
+ }
+ else if (L_EQUAL("french"))
+ {
+ theTranslator=new TranslatorFrench;
+ }
+ else if (L_EQUAL("italian"))
+ {
+ theTranslator=new TranslatorItalian;
+ }
+ else // use the default language (i.e. english)
+ {
+ theTranslator=new Translator;
+ return FALSE;
+ }
+ return TRUE;
+}
diff --git a/src/language.h b/src/language.h
new file mode 100644
index 0000000..c18eaed
--- /dev/null
+++ b/src/language.h
@@ -0,0 +1,25 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#ifndef LANGUAGE_H
+#define LANGUAGE_H
+
+#include "translator.h"
+
+extern Translator *theTranslator;
+extern bool setTranslator(const char *languageName);
+
+#endif
diff --git a/src/latexgen.cpp b/src/latexgen.cpp
new file mode 100644
index 0000000..50ec496
--- /dev/null
+++ b/src/latexgen.cpp
@@ -0,0 +1,876 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#include <stdlib.h>
+#include <qdir.h>
+#include "latexgen.h"
+#include "config.h"
+#include "message.h"
+#include "doxygen.h"
+#include "util.h"
+#include "diagram.h"
+#include "language.h"
+
+//static QString escapeLabelName(const QString &s)
+//{
+// QString result;
+// uint i;
+// for (i=0;i<s.length();i++)
+// {
+// char c=s.at(i);
+// switch (c)
+// {
+// case '~': result+=".1"; break;
+// case '%': result+=".2"; break;
+// default: result+=c;
+// }
+// }
+// return result;
+//}
+
+
+LatexGenerator::LatexGenerator()
+ : OutputGenerator()
+{
+ dir=latexOutputDir;
+ col=0;
+}
+
+LatexGenerator::~LatexGenerator()
+{
+}
+
+//LatexGenerator::LatexGenerator(const LatexGenerator &g)
+// : OutputGenerator(g)
+//{
+// col=g.col;
+//}
+
+void LatexGenerator::append(const OutputGenerator *g)
+{
+ t << g->getContents();
+ col+=((LatexGenerator *)g)->col;
+}
+
+
+void LatexGenerator::init()
+{
+ QString dir=latexOutputDir;
+ QDir d(dir);
+ if (!d.exists() && !d.mkdir(dir))
+ {
+ err("Could not create output directory %s\n",dir.data());
+ exit(1);
+ }
+
+ QString fileName=dir+"/Makefile";
+ QFile file(fileName);
+ if (!file.open(IO_WriteOnly))
+ {
+ err("Could not open file %s for writing\n",fileName.data());
+ exit(1);
+ }
+ QTextStream t(&file);
+ t << "all: refman.dvi" << endl
+ << endl
+ << "ps: refman.ps" << endl
+ << endl
+ << "refman.ps: refman.dvi" << endl
+ << "\tdvips -o refman.ps refman.dvi" << endl
+ << endl
+ << "refman.dvi: refman.tex doxygen.sty" << endl
+ << "\techo \"Running latex...\"" << endl
+ << "\tlatex refman.tex" << endl
+ << "\techo \"Running makeindex...\"" << endl
+ << "\tmakeindex refman.idx" << endl
+ << "\techo \"Rerunning latex....\"" << endl
+ << "\tlatex refman.tex" << endl
+ << "clean:" << endl
+ << "\trm -f *.ps *.dvi *.aux *.toc *.idx *.ind *.ilg *.log" << endl;
+}
+
+void LatexGenerator::startFile(const char *name,const char *,bool)
+{
+ QString fileName=name;
+ if (fileName.right(4)!=".tex" && fileName.right(4)!=".sty") fileName+=".tex";
+ startPlainFile(fileName);
+}
+
+void LatexGenerator::endFile()
+{
+ endPlainFile();
+}
+
+//void LatexGenerator::writeIndex()
+//{
+// startFile("refman.tex");
+//}
+
+void LatexGenerator::startProjectNumber()
+{
+ t << "\\\\[1ex]\\large ";
+}
+
+void LatexGenerator::startIndexSection(IndexSections is)
+{
+ QString paperName;
+ switch (is)
+ {
+ case isTitlePageStart:
+ {
+ if (paperType=="a4wide") paperName="a4"; else paperName=paperType;
+ t << "\\documentclass[" << paperName << "paper]{";
+ if (compactLatexFlag) t << "article"; else t << "book";
+ t << "}\n";
+ if (paperType=="a4wide") t << "\\usepackage{a4wide}\n";
+ t << "\\usepackage{makeidx}\n"
+ "\\usepackage{fancyheadings}\n"
+ "\\usepackage{epsf}\n"
+ "\\usepackage{float}\n"
+ "\\usepackage{doxygen}\n";
+ if (!theTranslator->latexBabelPackage().isEmpty())
+ {
+ t << "\\usepackage{" << theTranslator->latexBabelPackage() << "}\n";
+ }
+ const char *s=extraPackageList.first();
+ while (s)
+ {
+ t << "\\usepackage{" << s << "}\n";
+ s=extraPackageList.next();
+ }
+ t << "\\makeindex\n"
+ "\\setcounter{tocdepth}{1}\n"
+ "\\setlength{\\footrulewidth}{0.4pt}\n"
+ "\\begin{document}\n"
+ "\\title{";
+ //docify(projectName);
+ //t << " Reference Manual";
+ //if (!projectNumber.isEmpty())
+ //{
+ // t << "\\\\[1ex]\\large ";
+ // docify(projectNumber);
+ //}
+ }
+ break;
+ case isTitlePageAuthor:
+ t << "}\n\\author{";
+ break;
+ case isModuleIndex:
+ if (compactLatexFlag) t << "\\section"; else t << "\\chapter";
+ t << "{"; //Module Index}\n"
+ break;
+ case isClassHierarchyIndex:
+ if (compactLatexFlag) t << "\\section"; else t << "\\chapter";
+ t << "{"; //Hierarchical Index}\n"
+ break;
+ case isCompoundIndex:
+ if (compactLatexFlag) t << "\\section"; else t << "\\chapter";
+ t << "{"; //Annotated Compound Index}\n"
+ break;
+ case isFileIndex:
+ if (compactLatexFlag) t << "\\section"; else t << "\\chapter";
+ t << "{"; //Annotated File Index}\n"
+ break;
+ case isModuleDocumentation:
+ {
+ GroupDef *gd=groupList.first();
+ bool found=FALSE;
+ while (gd && !found)
+ {
+ if (gd->hasDocumentation() || gd->countMembers()>0)
+ {
+ if (compactLatexFlag) t << "\\section"; else t << "\\chapter";
+ t << "{"; //Module Documentation}\n";
+ found=TRUE;
+ }
+ gd=groupList.next();
+ }
+ }
+ break;
+ case isClassDocumentation:
+ {
+ ClassDef *cd=classList.first();
+ bool found=FALSE;
+ while (cd && !found)
+ {
+ //if (cd->classFile()[0]!='@' && !cd->getReference() &&
+ // (cd->hasDocumentation() || !hideClassFlag) &&
+ // (cd->protection()!=Private || extractPrivateFlag)
+ // )
+
+ if (!cd->isReference() && cd->isVisible())
+ {
+ if (compactLatexFlag) t << "\\section"; else t << "\\chapter";
+ t << "{"; //Compound Documentation}\n";
+ found=TRUE;
+ }
+ cd=classList.next();
+ }
+ }
+ break;
+ case isFileDocumentation:
+ {
+ bool isFirst=TRUE;
+ FileName *fn=inputNameList.first();
+ while (fn)
+ {
+ FileDef *fd=fn->first();
+ while (fd)
+ {
+ if (fd->hasDocumentation() && !fd->isReference())
+ {
+ if (isFirst)
+ {
+ if (compactLatexFlag) t << "\\section"; else t << "\\chapter";
+ t << "{"; //File Documentation}\n";
+ isFirst=FALSE;
+ break;
+ }
+ }
+ fd=fn->next();
+ }
+ fn=inputNameList.next();
+ }
+ }
+ break;
+ case isExampleDocumentation:
+ {
+ if (compactLatexFlag) t << "\\section"; else t << "\\chapter";
+ t << "{"; //Example Documentation}\n";
+ }
+ break;
+ case isPageDocumentation:
+ {
+ if (compactLatexFlag) t << "\\section"; else t << "\\chapter";
+ t << "{"; //Page Documentation}\n";
+ }
+ break;
+ case isEndIndex:
+ break;
+ }
+}
+
+void LatexGenerator::endIndexSection(IndexSections is)
+{
+ switch (is)
+ {
+ case isTitlePageStart:
+ break;
+ case isTitlePageAuthor:
+ t << " Doxygen}\n"
+ "\\date{" << dateToString(TRUE) << "}\n"
+ "\\maketitle\n"
+ "\\pagenumbering{roman}\n";
+ if (!compactLatexFlag) t << "\\clearemptydoublepage\n";
+ t << "\\tableofcontents\n";
+ if (!compactLatexFlag) t << "\\clearemptydoublepage\n";
+ t << "\\pagenumbering{arabic}\n";
+ break;
+ case isModuleIndex:
+ t << "}\n\\input{modules}\n";
+ break;
+ case isClassHierarchyIndex:
+ t << "}\n\\input{hierarchy}\n";
+ break;
+ case isCompoundIndex:
+ t << "}\n\\input{annotated}\n";
+ break;
+ case isFileIndex:
+ t << "}\n\\input{files}\n";
+ break;
+ case isModuleDocumentation:
+ {
+ GroupDef *gd=groupList.first();
+ bool found=FALSE;
+ while (gd && !found)
+ {
+ if (gd->hasDocumentation() || gd->countMembers()>0)
+ {
+ t << "}\n\\input{" << gd->groupFile() << "}\n";
+ found=TRUE;
+ }
+ gd=groupList.next();
+ }
+ while (gd)
+ {
+ if (gd->hasDocumentation() || gd->countMembers()>0)
+ {
+ if (compactLatexFlag) t << "\\input"; else t << "\\include";
+ t << "{" << gd->groupFile() << "}\n";
+ }
+ gd=groupList.next();
+ }
+ }
+ break;
+ case isClassDocumentation:
+ {
+ ClassDef *cd=classList.first();
+ bool found=FALSE;
+ while (cd && !found)
+ {
+ //if (cd->classFile()[0]!='@' && !cd->getReference() &&
+ // (cd->hasDocumentation() || !hideClassFlag) &&
+ // (cd->protection()!=Private || extractPrivateFlag)
+ // )
+ if (!cd->isReference() && cd->isVisible())
+ {
+ t << "}\n\\input{" << cd->classFile() << "}\n";
+ found=TRUE;
+ }
+ cd=classList.next();
+ }
+ while (cd)
+ {
+ //if (cd->classFile()[0]!='@' && !cd->getReference() &&
+ // (cd->hasDocumentation() || !hideClassFlag) &&
+ // (cd->protection()!=Private || extractPrivateFlag)
+ // )
+ if (!cd->isReference() && cd->isVisible())
+ {
+ if (compactLatexFlag) t << "\\input"; else t << "\\include";
+ t << "{" << cd->classFile() << "}\n";
+ }
+ cd=classList.next();
+ }
+ }
+ break;
+ case isFileDocumentation:
+ {
+ bool isFirst=TRUE;
+ FileName *fn=inputNameList.first();
+ while (fn)
+ {
+ FileDef *fd=fn->first();
+ while (fd)
+ {
+ if (fd->hasDocumentation() && !fd->isReference())
+ {
+ if (isFirst)
+ {
+ t << "}\n\\input{" << fd->diskName() << "}\n";
+ isFirst=FALSE;
+ }
+ else
+ {
+ if (compactLatexFlag) t << "\\input" ; else t << "\\include";
+ t << "{" << fd->diskName() << "}\n";
+ }
+ }
+ fd=fn->next();
+ }
+ fn=inputNameList.next();
+ }
+ }
+ break;
+ case isExampleDocumentation:
+ {
+ t << "}\n";
+ PageInfo *pi=exampleList.first();
+ if (pi)
+ {
+ t << "\\input{" << convertSlashes(pi->name,TRUE) << "-example}\n";
+ pi=exampleList.next();
+ }
+ while (pi)
+ {
+ if (compactLatexFlag) t << "\\input" ; else t << "\\include";
+ t << "{" << convertSlashes(pi->name,TRUE) << "-example}\n";
+ pi=exampleList.next();
+ }
+ }
+ break;
+ case isPageDocumentation:
+ {
+ t << "}\n";
+ PageInfo *pi=pageList.first();
+ if (pi)
+ {
+ QString pageName;
+ if (caseSensitiveNames)
+ pageName=pi->name.copy();
+ else
+ pageName=pi->name.lower();
+ t << "\\input{" << pageName << "}\n";
+ pi=pageList.next();
+ }
+ while (pi)
+ {
+ if (compactLatexFlag) t << "\\input" ; else t << "\\include";
+ QString pageName;
+ if (caseSensitiveNames)
+ pageName=pi->name.copy();
+ else
+ pageName=pi->name.lower();
+ t << "{" << pageName << "}\n";
+ pi=pageList.next();
+ }
+ }
+ break;
+ case isEndIndex:
+ t << "\\printindex\n";
+ t << "\\end{document}\n";
+ break;
+ }
+}
+void LatexGenerator::writeStyleInfo(int part)
+{
+ switch(part)
+ {
+ case 0:
+ {
+ QString pname=projectName.stripWhiteSpace();
+ startPlainFile("doxygen.sty");
+ t << "\\NeedsTeXFormat{LaTeX2e}\n";
+ t << "\\ProvidesPackage{doxygen}\n";
+ t << "\\RequirePackage{calc}\n";
+ t << "\\RequirePackage{array}\n";
+ t << "\\pagestyle{fancyplain}\n";
+ t << "\\addtolength{\\headwidth}{\\marginparsep}\n";
+ t << "\\addtolength{\\headwidth}{\\marginparwidth}\n";
+ t << "\\newcommand{\\clearemptydoublepage}{\\newpage{\\pagestyle{empty}";
+ t << "\\cleardoublepage}}\n";
+ if (!compactLatexFlag)
+ t << "\\renewcommand{\\chaptermark}[1]{\\markboth{#1}{}}\n";
+ t << "\\renewcommand{\\sectionmark}[1]{\\markright{\\thesection\\ #1}}\n";
+ t << "\\lhead[\\fancyplain{}{\\bfseries\\thepage}]\n";
+ t << " {\\fancyplain{}{\\bfseries\\rightmark}}\n";
+ t << "\\rhead[\\fancyplain{}{\\bfseries\\leftmark}]\n";
+ t << " {\\fancyplain{}{\\bfseries\\thepage}}\n";
+ t << "\\rfoot[\\fancyplain{}{\\bfseries\\scriptsize ";
+ }
+ break;
+ case 1:
+ case 3:
+ t << " Doxygen ";
+ break;
+ case 2:
+ {
+ t << " Dimitri van Heesch \\copyright 1997-1999}]{}\n";
+ //QString dtString=dateToString(FALSE);
+ t << "\\lfoot[]{\\fancyplain{}{\\bfseries\\scriptsize ";
+ }
+ break;
+ case 4:
+ {
+ t << " Dimitri van Heesch \\copyright 1997-1999}}\n";
+ t << "\\cfoot{}\n";
+ t << "\\newenvironment{CompactList}\n";
+ t << "{\\begin{list}{}{\n";
+ t << " \\setlength{\\leftmargin}{0.5cm}\n";
+ t << " \\setlength{\\itemsep}{0pt}\n";
+ t << " \\setlength{\\parsep}{0pt}\n";
+ t << " \\setlength{\\topsep}{0pt}\n";
+ t << " \\renewcommand{\\makelabel}{}}}\n";
+ t << "{\\end{list}}\n";
+ t << "\\newenvironment{CompactItemize}\n";
+ t << "{\n";
+ t << " \\begin{itemize}\n";
+ t << " \\setlength{\\itemsep}{-4pt}\n";
+ t << " \\setlength{\\parsep}{0pt}\n";
+ t << " \\setlength{\\topsep}{0pt}\n";
+ t << " \\setlength{\\partopsep}{0pt}\n";
+ t << "}\n";
+ t << "{\\end{itemize}}\n";
+ t << "\\newcommand{\\PBS}[1]{\\let\\temp=\\\\#1\\let\\\\=\\temp}\n";
+ t << "\\newlength{\\tmplength}\n";
+ t << "\\newenvironment{TabularC}[1]\n";
+ t << "{\n";
+ t << "\\setlength{\\tmplength}\n";
+ t << " {\\linewidth/(#1)-\\tabcolsep*2-\\arrayrulewidth*(#1+1)/(#1)}\n";
+ t << " \\par\\begin{tabular*}{\\linewidth}\n";
+ t << " {*{#1}{|>{\\PBS\\raggedright\\hspace{0pt}}p{\\the\\tmplength}}|}\n";
+ t << "}\n";
+ t << "{\\end{tabular*}\\par}\n";
+ t << "\\newcommand{\\entrylabel}[1]{\n";
+ t << " {\\parbox[b]{\\labelwidth-4pt}{\\makebox[0pt][l]{\\textbf{#1}}\\\\}}}\n";
+ t << "\\newenvironment{Desc}\n";
+ t << "{\\begin{list}{}\n";
+ t << " {\n";
+ t << " \\settowidth{\\labelwidth}{40pt}\n";
+ t << " \\setlength{\\leftmargin}{\\labelwidth}\n";
+ t << " \\setlength{\\parsep}{0pt}\n";
+ t << " \\setlength{\\itemsep}{-4pt}\n";
+ t << " \\renewcommand{\\makelabel}{\\entrylabel}\n";
+ t << " }\n";
+ t << "}\n";
+ t << "{\\end{list}}\n";
+ t << "\\setlength{\\parindent}{0cm}\n";
+ t << "\\setlength{\\parskip}{0.2cm}\n";
+ t << "\\sloppy\n";
+ endPlainFile();
+ }
+ break;
+ }
+}
+
+void LatexGenerator::endTitleHead(const char *name)
+{
+ t << "}" << endl;
+ if (name)
+ {
+ t << "\\label{" << name << "}\\index{"
+ << name << "@{";
+ docify(name);
+ t << "}}";
+ }
+ t << endl;
+}
+
+void LatexGenerator::newParagraph()
+{
+ t << endl << endl;
+}
+
+void LatexGenerator::writeString(const char *text)
+{
+ t << text;
+}
+
+void LatexGenerator::writeIndexItem(const char *ref,const char *fn,
+ const char *name)
+{
+ t << "\\item ";
+ if (!ref && fn)
+ {
+ t << "\\contentsline{section}{";
+ docify(name);
+ t << "}{\\pageref{" << name << "}}" << endl;
+ }
+ else
+ docify(name);
+}
+
+//void LatexGenerator::writeIndexFileItem(const char *,const char *text)
+//{
+// t << "\\item\\contentsline{section}{";
+// docify(text);
+// t << "}{\\pageref{" << text << "}}" << endl;
+//}
+
+
+void LatexGenerator::writeHtmlLink(const char *url,const char *text)
+{
+ docify(text);
+ if (url)
+ {
+ // t << " {\\tt (";
+ // docify(url);
+ // t << ")}";
+ }
+}
+
+void LatexGenerator::writeStartAnnoItem(const char *,const char *,
+ const char *path,const char *name)
+{
+ t << "\\item\\contentsline{section}{{\\bf ";
+ if (path) docify(path);
+ docify(name);
+ t << "} ";
+}
+
+void LatexGenerator::writeEndAnnoItem(const char *name)
+{
+ t << "}{\\pageref{" << name << "}}" << endl;
+}
+
+//void LatexGenerator::writeClassLink(const char *,const char *,
+// const char *,const char *name)
+//{
+// t << "{\\bf ";
+// docify(name);
+// t << "}";
+//}
+
+void LatexGenerator::writeObjectLink(const char *, const char *,
+ const char *, const char *text)
+{
+ t << "{\\bf ";
+ docify(text);
+ t << "}";
+}
+
+void LatexGenerator::writePageRef(const char *clname, const char *anchor)
+{
+ t << " {\\rm (p. \\pageref{";
+ if (clname) t << clname;
+ if (anchor) t << "_" << anchor;
+ t << "})}";
+}
+
+void LatexGenerator::writeCodeLink(const char *,const char *,
+ const char *,const char *name)
+{
+ t << name;
+ col+=strlen(name);
+}
+
+
+void LatexGenerator::startTitle()
+{
+ if (compactLatexFlag) t << "\\subsection{"; else t << "\\section{";
+}
+
+void LatexGenerator::startGroupHeader()
+{
+ if (compactLatexFlag) t << "\\subsubsection*{"; else t << "\\subsection*{";
+}
+
+void LatexGenerator::endGroupHeader()
+{
+ t << "}" << endl;
+}
+
+void LatexGenerator::startMemberDoc(const char *clname,
+ const char *memname,const char *)
+{
+ t << "\\index{";
+ if (clname)
+ {
+ t << clname << "@{";
+ docify(clname);
+ t << "}!";
+ }
+ t << memname << "@{";
+ docify(memname);
+ t << "}}" << endl;
+
+ t << "\\index{" << memname << "@{";
+ docify(memname);
+ t << "}";
+ if (clname)
+ {
+ t << "!" << clname << "@{";
+ docify(clname);
+ t << "}";
+ }
+ t << "}" << endl;
+ //
+ if (compactLatexFlag) t << "\\subsubsection{"; else t << "\\subsection{";
+ t << "\\setlength{\\rightskip}{0pt plus 5cm}";
+}
+
+void LatexGenerator::writeDoxyAnchor(const char *clname,const char *anchor,const char *)
+{
+ t << "\\label{";
+ if (clname) t << clname;
+ if (anchor) t << "_" << anchor;
+ t << "}" << endl;
+}
+
+void LatexGenerator::addToIndex(const char *s1,const char *s2)
+{
+ if (s1)
+ {
+ t << "\\index{" << s1 << "@{";
+ docify(s1);
+ t << "}";
+ if (s2)
+ {
+ t << "!" << s2 << "@{";
+ docify(s2);
+ t << "}";
+ }
+ t << "}";
+ }
+}
+
+void LatexGenerator::writeSection(const char *lab,const char *title,bool sub)
+{
+ t << "\\";
+ if (sub) t << "subsection{"; else t << "section{";
+ docify(title);
+ t << "}\\label{" << lab << "}" << endl;
+}
+
+void LatexGenerator::writeSectionRef(const char *,const char *lab,
+ const char *)
+{
+ t << "\\ref{" << lab << "}";
+}
+
+void LatexGenerator::writeSectionRefItem(const char *,const char *lab,
+ const char *title)
+{
+ t << "\\contentsline{section}{";
+ docify(title);
+ t << "}{\\ref{" << lab << "}}" << endl;
+}
+
+//void LatexGenerator::docify(const char *str)
+//{
+// docifyStatic(t,str);
+//}
+
+//void LatexGenerator::docifyStatic(QTextStream &t,const char *str)
+void LatexGenerator::docify(const char *str)
+{
+ if (str)
+ {
+ const unsigned char *p=(const unsigned char *)str;
+ unsigned char c;
+ unsigned char pc='\0';
+ while (*p)
+ {
+ c=*p++;
+ switch(c)
+ {
+ case '#': t << "\\#"; break;
+ case '$': t << "\\$"; break;
+ case '%': t << "\\%"; break;
+ case '^': t << "$^\\wedge$"; break;
+ case '&': t << "\\&"; break;
+ case '*': t << "$\\ast$"; break;
+ case '_': t << "\\_\\-"; break;
+ case '{': t << "\\{"; break;
+ case '}': t << "\\}"; break;
+ case '<': t << "$<$"; break;
+ case '>': t << "$>$"; break;
+ case '|': t << "$|$"; break;
+ case '~': t << "$\\sim$"; break;
+ case '-': if (*p=='>')
+ { t << " $\\rightarrow$ "; p++; }
+ else
+ { t << (char)c; }
+ break;
+ case '\\': if (*p=='<')
+ { t << "$<$"; p++; }
+ else if (*p=='>')
+ { t << "$>$"; p++; }
+ else
+ { t << "$\\backslash$"; }
+ break;
+ // the Latin-1 characters
+ case 161: t << "!`"; break;
+ case 181: t << "$\\mu$"; break;
+ case 191: t << "?`"; break;
+ case 192: t << "\\`{A}"; break;
+ case 193: t << "\\'{A}"; break;
+ case 194: t << "\\^{A}"; break;
+ case 195: t << "\\~{A}"; break;
+ case 196: t << "\\\"{A}"; break;
+ case 197: t << "\\AA "; break;
+ case 198: t << "\\AE "; break;
+ case 199: t << "\\c{C}"; break;
+ case 200: t << "\\`{E}"; break;
+ case 201: t << "\\'{E}"; break;
+ case 202: t << "\\^{E}"; break;
+ case 203: t << "\\\"{E}"; break;
+ case 204: t << "\\`{I}"; break;
+ case 205: t << "\\'{I}"; break;
+ case 206: t << "\\^{I}"; break;
+ case 207: t << "\\\"{I}"; break;
+ case 208: t << "D "; break; // anyone know the real code?
+ case 209: t << "\\~{N}"; break;
+ case 210: t << "\\`{O}"; break;
+ case 211: t << "\\'{O}"; break;
+ case 212: t << "\\^{O}"; break;
+ case 213: t << "\\~{O}"; break;
+ case 214: t << "\\\"{O}"; break;
+ case 215: t << "$\\times$"; break;
+ case 216: t << "\\O"; break;
+ case 217: t << "\\`{U}"; break;
+ case 218: t << "\\'{U}"; break;
+ case 219: t << "\\^{U}"; break;
+ case 220: t << "\\\"{U}"; break;
+ case 221: t << "\\'{Y}"; break;
+ case 223: t << "\"s "; break; // assumes german package
+ case 224: t << "\\`{a}"; break;
+ case 225: t << "\\'{a}"; break;
+ case 226: t << "\\^{a}"; break;
+ case 227: t << "\\~{a}"; break;
+ case 228: t << "\\\"{a}"; break;
+ case 229: t << "\\aa "; break;
+ case 230: t << "\\ae "; break;
+ case 231: t << "\\c{c}"; break;
+ case 232: t << "\\`{e}"; break;
+ case 233: t << "\\'{e}"; break;
+ case 234: t << "\\^{e}"; break;
+ case 235: t << "\\\"{e}"; break;
+ case 236: t << "\\`{\\i}"; break;
+ case 237: t << "\\'{\\i}"; break;
+ case 238: t << "\\^{\\i}"; break;
+ case 239: t << "\\\"{\\i}"; break;
+ case 241: t << "\\~{n}"; break;
+ case 242: t << "\\`{o}"; break;
+ case 243: t << "\\'{o}"; break;
+ case 244: t << "\\^{o}"; break;
+ case 245: t << "\\~{o}"; break;
+ case 246: t << "\\\"{o}"; break;
+ case 248: t << "\\o "; break;
+ case 249: t << "\\`{u}"; break;
+ case 250: t << "\\'{u}"; break;
+ case 251: t << "\\^{u}"; break;
+ case 252: t << "\\\"{u}"; break;
+ case 253: t << "\\'{y}"; break;
+ case 255: t << "\\\"{y}"; break;
+
+ default:
+ if ((isupper(c) && islower(pc))
+ // ||
+ // (pc!=':' && c==':') ||
+ // (pc==':' && c!=':')
+ ) t << "\\-";
+ t << (char)c;
+ }
+ pc = c;
+ }
+ }
+}
+
+void LatexGenerator::codify(const char *str)
+{
+ static char spaces[]=" ";
+ if (str)
+ {
+ const char *p=str;
+ char c;
+ while (*p)
+ {
+ c=*p++;
+ switch(c)
+ {
+ case '\t': t << &spaces[col&7]; col+=8-(col&7); break;
+ case '\n': t << '\n'; col=0; break;
+ default: t << c; col++; break;
+ }
+ }
+ }
+}
+
+void LatexGenerator::writeChar(char c)
+{
+ char cs[2];
+ cs[0]=c;
+ cs[1]=0;
+ docify(cs);
+}
+
+void LatexGenerator::startClassDiagram()
+{
+ if (compactLatexFlag) t << "\\subsubsection*"; else t << "\\subsection*";
+ t << "{";
+}
+
+void LatexGenerator::endClassDiagram(ClassDiagram &d,
+ const char *fileName,const char *)
+{
+ d.writeFigure(t,dir,fileName);
+}
+
+void LatexGenerator::writeFormula(const char *,const char *text)
+{
+ t << text;
+}
diff --git a/src/latexgen.h b/src/latexgen.h
new file mode 100644
index 0000000..5a3dd1c
--- /dev/null
+++ b/src/latexgen.h
@@ -0,0 +1,178 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#ifndef OUTPUT_H
+#define OUTPUT_H
+
+#include "outputgen.h"
+
+class QFile;
+
+class LatexGenerator : public OutputGenerator
+{
+ public:
+ LatexGenerator();
+ ~LatexGenerator();
+
+ OutputGenerator *copy() { return new LatexGenerator; }
+ //OutputGenerator *clone() { return new LatexGenerator(*this); }
+ void append(const OutputGenerator *o);
+ void enable() { active=TRUE; }
+ void disable() { active=FALSE; }
+ void enableIf(OutputType o) { if (o==Latex) active=TRUE; }
+ void disableIf(OutputType o) { if (o==Latex) active=FALSE; }
+ void disableIfNot(OutputType o) { if (o!=Latex) active=FALSE; }
+ bool isEnabled(OutputType o) { return (o==Latex && active); }
+ OutputGenerator *get(OutputType o) { return (o==Latex) ? this : 0; }
+
+ static void init();
+ void startFile(const char *name,const char *title, bool external);
+ void writeFooter(int,bool) {}
+ void endFile();
+ void clearBuffer();
+
+ //void writeIndex();
+ void startIndexSection(IndexSections);
+ void endIndexSection(IndexSections);
+ void startProjectNumber();
+ void endProjectNumber() {}
+ void writeStyleInfo(int part);
+ void startTitleHead() { startTitle(); }
+ void startTitle();
+ void endTitleHead(const char *name);
+ void endTitle() { t << "}"; }
+
+ void newParagraph();
+ void writeString(const char *text);
+ void startIndexList() { t << "\\begin{CompactList}" << endl; }
+ void endIndexList() { t << "\\end{CompactList}" << endl; }
+ void startItemList() { t << "\\begin{CompactItemize}" << endl; }
+ void endItemList() { t << "\\end{CompactItemize}" << endl; }
+ void startEnumList() { t << "\\begin{enumerate}" << endl; }
+ void endEnumList() { t << "\\end{enumerate}" << endl; }
+ void writeIndexItem(const char *ref,const char *file,const char *name);
+ void docify(const char *text);
+ void codify(const char *text);
+ void writeObjectLink(const char *ref,const char *file,
+ const char *anchor,const char *text);
+ void writeCodeLink(const char *ref, const char *file,
+ const char *anchor,const char *text);
+ void startTextLink(const char *,const char *) {}
+ void endTextLink() {}
+ void writeHtmlLink(const char *,const char *);
+ void startTypewriter() { t << "{\\tt "; }
+ void endTypewriter() { t << "}"; }
+ void startGroupHeader();
+ void endGroupHeader();
+ void writeListItem() { t << "\\item " << endl; }
+
+ void startMemberHeader() { startGroupHeader(); }
+ void endMemberHeader() { endGroupHeader(); }
+ void startMemberList() { t << "\\begin{CompactItemize}" << endl; }
+ void endMemberList() { t << "\\end{CompactItemize}" << endl; }
+ void startMemberItem() { t << "\\item " << endl; }
+ void endMemberItem() { t << endl; }
+
+ void writeRuler() { t << "\\vspace{0.4cm}\\hrule\\vspace{0.2cm}"; }
+ void writeAnchor(const char *) {}
+ void startCodeFragment() { t << "\\small\\begin{verbatim}"; }
+ void endCodeFragment() { t << "\\end{verbatim}\\normalsize "; }
+ void writeBoldString(const char *text)
+ { t << "{\\bf "; docify(text); t << "}"; }
+ void startEmphasis() { t << "{\\em "; }
+ void endEmphasis() { t << "}"; }
+ void startBold() { t << "{\\bf "; }
+ void endBold() { t << "}"; }
+ void startDescription() { t << "\\begin{description}" << endl; }
+ void endDescription() { t << "\\end{description}" << endl; }
+ void startDescItem() { t << "\\item["; }
+ void endDescItem() { t << "]"; }
+ void lineBreak() { t << "\\par\n"; }
+ void startMemberDoc(const char *,const char *,const char *);
+ void endMemberDoc() { t << "}"; }
+ void writeDoxyAnchor(const char *,const char *,const char *);
+ void writeChar(char c);
+ void writeLatexSpacing() { t << "\\hspace{0.3cm}"; }
+ void writeStartAnnoItem(const char *type,const char *file,
+ const char *path,const char *name);
+ void writeEndAnnoItem(const char *name);
+ void startSubsection() { t << "\\subsection*{"; }
+ void endSubsection() { t << "}" << endl; }
+ void startSubsubsection() { t << "\\subsubsection*{"; }
+ void endSubsubsection() { t << "}" << endl; }
+ void startCenter() { t << "\\begin{center}" << endl; }
+ void endCenter() { t << "\\end{center}" << endl; }
+ void startSmall() { t << "\\footnotesize "; }
+ void endSmall() { t << "\\normalsize "; }
+ void startSubscript() { t << "$_{\\mbox{"; }
+ void endSubscript() { t << "}}$"; }
+ void startSuperscript() { t << "$^{\\mbox{"; }
+ void endSuperscript() { t << "}}$"; }
+ void startTable(int c) { t << "\\begin{TabularC}{" << c
+ << "}\n\\hline\n";
+ }
+ void endTable() { t << "\\\\\\hline\n\\end{TabularC}\n"; }
+ void nextTableRow() {}
+ void endTableRow() { t << "\\\\\\hline\n"; }
+ void nextTableColumn() { t << "&"; }
+ void endTableColumn() {}
+ void writeCopyright() { t << "\\copyright"; }
+ void writeQuote() { t << "''"; }
+ void writeUmlaut(char c) { if (c=='i') t << "\\\"{\\i}"; else
+ t << "\\\"{" << c << "}";
+ }
+ void writeAcute(char c) { if (c=='i') t << "\\'{\\i}"; else
+ t << "\\'{" << c << "}";
+ }
+ void writeGrave(char c) { if (c=='i') t << "\\`{\\i}"; else
+ t << "\\`{" << c << "}";
+ }
+ void writeCirc(char c) { if (c=='i') t << "\\^{\\i}"; else
+ t << "\\^{" << c << "}";
+ }
+ void writeTilde(char c) { t << "\\~{" << c << "}"; }
+ void startMemberDescription() { t << "\\begin{CompactList}\\small\\item\\em "; }
+ void endMemberDescription() { t << "\\item\\end{CompactList}"; }
+ void startDescList() { t << "\\begin{Desc}\\item["; }
+ void endDescTitle() { t << "]"; }
+ void writeDescItem() { t << "\\par "; }
+ void endDescList() { t << "\\end{Desc}"; }
+ void writeSection(const char *,const char *,bool);
+ void writeSectionRef(const char *,const char *,const char *);
+ void writeSectionRefItem(const char *,const char *,const char *);
+ void addToIndex(const char *,const char *);
+ void startIndent() {}
+ void endIndent() {}
+ void writeSynopsis() {}
+ //void generateExternalIndex() {}
+ void startClassDiagram();
+ void endClassDiagram(ClassDiagram &,const char *,const char *);
+ void startColorFont(uchar,uchar,uchar) {}
+ void endColorFont() {}
+ void writePageRef(const char *,const char *);
+ void startQuickIndexItem(const char *,const char *) {}
+ void endQuickIndexItem() {}
+ void writeFormula(const char *,const char *);
+
+ //static void docifyStatic(QTextStream &t,const char *str);
+
+ private:
+ LatexGenerator(const LatexGenerator &);
+ LatexGenerator &operator=(const LatexGenerator &);
+ int col;
+};
+
+#endif
diff --git a/src/logos.cpp b/src/logos.cpp
new file mode 100644
index 0000000..090309a
--- /dev/null
+++ b/src/logos.cpp
@@ -0,0 +1,519 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#include <qstring.h>
+#include <qfile.h>
+#include <stdio.h>
+
+unsigned char logo_data[] = {
+ 0x47, 0x49, 0x46, 0x38, 0x37, 0x61, 0x76, 0x00, 0x35, 0x00, 0xf7, 0x00,
+ 0x00, 0x31, 0x7b, 0x6b, 0x31, 0x7b, 0x73, 0x31, 0x84, 0x7b, 0x31, 0x84,
+ 0x84, 0x31, 0x8c, 0x7b, 0x31, 0x8c, 0x84, 0x31, 0x8c, 0x8c, 0x39, 0x7b,
+ 0x7b, 0x39, 0x84, 0x7b, 0x39, 0x84, 0x84, 0x39, 0x8c, 0x84, 0x39, 0x94,
+ 0x8c, 0x39, 0x94, 0x94, 0x39, 0x9c, 0x94, 0x42, 0x7b, 0x73, 0x42, 0x8c,
+ 0x84, 0x42, 0x94, 0x8c, 0x42, 0x9c, 0x8c, 0x42, 0x9c, 0x94, 0x42, 0xa5,
+ 0x9c, 0x4a, 0x5a, 0x5a, 0x4a, 0x84, 0x84, 0x4a, 0x8c, 0x84, 0x4a, 0x94,
+ 0x8c, 0x4a, 0x94, 0x94, 0x4a, 0x9c, 0x94, 0x4a, 0xa5, 0x94, 0x4a, 0xa5,
+ 0x9c, 0x4a, 0xa5, 0xa5, 0x52, 0x52, 0x52, 0x52, 0x73, 0x73, 0x52, 0x7b,
+ 0x7b, 0x52, 0x84, 0x84, 0x52, 0x94, 0x8c, 0x52, 0x9c, 0x94, 0x52, 0xa5,
+ 0x9c, 0x52, 0xad, 0xa5, 0x52, 0xb5, 0xad, 0x5a, 0x5a, 0x5a, 0x5a, 0x63,
+ 0x63, 0x5a, 0x6b, 0x6b, 0x5a, 0x7b, 0x7b, 0x5a, 0x8c, 0x84, 0x5a, 0x8c,
+ 0x8c, 0x5a, 0x94, 0x8c, 0x5a, 0x94, 0x94, 0x5a, 0x9c, 0x94, 0x5a, 0xa5,
+ 0x9c, 0x5a, 0xa5, 0xa5, 0x5a, 0xad, 0xa5, 0x5a, 0xb5, 0xad, 0x5a, 0xbd,
+ 0xb5, 0x63, 0x63, 0x63, 0x63, 0x6b, 0x6b, 0x63, 0x73, 0x73, 0x63, 0x7b,
+ 0x7b, 0x63, 0x84, 0x84, 0x63, 0x8c, 0x8c, 0x63, 0x94, 0x94, 0x63, 0xa5,
+ 0x9c, 0x63, 0xa5, 0xa5, 0x63, 0xad, 0xa5, 0x63, 0xb5, 0xad, 0x63, 0xb5,
+ 0xb5, 0x63, 0xbd, 0xbd, 0x6b, 0x6b, 0x6b, 0x6b, 0x73, 0x73, 0x6b, 0x7b,
+ 0x7b, 0x6b, 0x8c, 0x8c, 0x6b, 0x9c, 0x94, 0x6b, 0xa5, 0x9c, 0x6b, 0xad,
+ 0xa5, 0x6b, 0xb5, 0xad, 0x6b, 0xb5, 0xb5, 0x6b, 0xbd, 0xb5, 0x6b, 0xbd,
+ 0xbd, 0x6b, 0xc6, 0xbd, 0x6b, 0xc6, 0xc6, 0x6b, 0xce, 0xc6, 0x73, 0x73,
+ 0x73, 0x73, 0x7b, 0x7b, 0x73, 0x84, 0x84, 0x73, 0x8c, 0x8c, 0x73, 0x94,
+ 0x8c, 0x73, 0x94, 0x94, 0x73, 0x9c, 0x94, 0x73, 0x9c, 0x9c, 0x73, 0xa5,
+ 0x9c, 0x73, 0xa5, 0xa5, 0x73, 0xad, 0xad, 0x73, 0xb5, 0xad, 0x73, 0xb5,
+ 0xb5, 0x73, 0xbd, 0xbd, 0x73, 0xce, 0xce, 0x7b, 0x7b, 0x7b, 0x7b, 0x8c,
+ 0x8c, 0x7b, 0x94, 0x94, 0x7b, 0x9c, 0x9c, 0x7b, 0xa5, 0xa5, 0x7b, 0xb5,
+ 0xb5, 0x7b, 0xbd, 0xb5, 0x7b, 0xbd, 0xbd, 0x7b, 0xc6, 0xc6, 0x7b, 0xce,
+ 0xc6, 0x7b, 0xce, 0xce, 0x7b, 0xd6, 0xce, 0x7b, 0xd6, 0xd6, 0x7b, 0xde,
+ 0xd6, 0x84, 0x84, 0x84, 0x84, 0x8c, 0x8c, 0x84, 0x9c, 0x94, 0x84, 0x9c,
+ 0x9c, 0x84, 0xa5, 0x9c, 0x84, 0xad, 0xad, 0x84, 0xb5, 0xb5, 0x84, 0xc6,
+ 0xc6, 0x84, 0xce, 0xce, 0x84, 0xd6, 0xd6, 0x8c, 0x7b, 0x7b, 0x8c, 0x84,
+ 0x84, 0x8c, 0x8c, 0x8c, 0x8c, 0xa5, 0xa5, 0x8c, 0xad, 0xad, 0x8c, 0xb5,
+ 0xb5, 0x8c, 0xbd, 0xb5, 0x8c, 0xbd, 0xbd, 0x8c, 0xc6, 0xc6, 0x8c, 0xce,
+ 0xce, 0x8c, 0xde, 0xde, 0x94, 0x7b, 0x7b, 0x94, 0x94, 0x94, 0x94, 0x9c,
+ 0x9c, 0x94, 0xa5, 0xa5, 0x94, 0xad, 0xad, 0x94, 0xbd, 0xb5, 0x94, 0xc6,
+ 0xbd, 0x9c, 0x9c, 0x9c, 0x9c, 0xa5, 0xa5, 0x9c, 0xb5, 0xb5, 0x9c, 0xbd,
+ 0xbd, 0x9c, 0xc6, 0xbd, 0x9c, 0xc6, 0xc6, 0x9c, 0xce, 0xc6, 0x9c, 0xce,
+ 0xce, 0x9c, 0xd6, 0xd6, 0xa5, 0x5a, 0x5a, 0xa5, 0x63, 0x63, 0xa5, 0x84,
+ 0x84, 0xa5, 0x94, 0x94, 0xa5, 0xa5, 0xa5, 0xa5, 0xad, 0xa5, 0xa5, 0xbd,
+ 0xbd, 0xa5, 0xc6, 0xc6, 0xa5, 0xce, 0xce, 0xa5, 0xd6, 0xd6, 0xa5, 0xde,
+ 0xde, 0xa5, 0xe7, 0xde, 0xad, 0x21, 0x18, 0xad, 0x21, 0x21, 0xad, 0x52,
+ 0x52, 0xad, 0x63, 0x63, 0xad, 0x7b, 0x7b, 0xad, 0xad, 0xad, 0xad, 0xb5,
+ 0xb5, 0xad, 0xbd, 0xbd, 0xad, 0xce, 0xc6, 0xad, 0xce, 0xce, 0xad, 0xd6,
+ 0xce, 0xad, 0xd6, 0xd6, 0xb5, 0x21, 0x21, 0xb5, 0x52, 0x52, 0xb5, 0x5a,
+ 0x5a, 0xb5, 0x63, 0x63, 0xb5, 0x6b, 0x6b, 0xb5, 0xb5, 0xb5, 0xb5, 0xc6,
+ 0xc6, 0xb5, 0xce, 0xce, 0xb5, 0xd6, 0xce, 0xb5, 0xd6, 0xd6, 0xb5, 0xde,
+ 0xd6, 0xb5, 0xde, 0xde, 0xb5, 0xe7, 0xe7, 0xbd, 0x21, 0x21, 0xbd, 0x29,
+ 0x29, 0xbd, 0x42, 0x42, 0xbd, 0x52, 0x52, 0xbd, 0x73, 0x73, 0xbd, 0x7b,
+ 0x7b, 0xbd, 0x84, 0x84, 0xbd, 0xbd, 0xbd, 0xbd, 0xc6, 0xc6, 0xbd, 0xce,
+ 0xce, 0xbd, 0xd6, 0xd6, 0xbd, 0xde, 0xde, 0xc6, 0x39, 0x39, 0xc6, 0x73,
+ 0x73, 0xc6, 0x7b, 0x7b, 0xc6, 0x84, 0x84, 0xc6, 0x8c, 0x8c, 0xc6, 0x94,
+ 0x94, 0xc6, 0xc6, 0xc6, 0xc6, 0xce, 0xce, 0xc6, 0xd6, 0xd6, 0xc6, 0xde,
+ 0xde, 0xc6, 0xef, 0xe7, 0xce, 0x7b, 0x7b, 0xce, 0x8c, 0x8c, 0xce, 0x94,
+ 0x94, 0xce, 0xce, 0xce, 0xce, 0xd6, 0xd6, 0xce, 0xde, 0xde, 0xce, 0xe7,
+ 0xe7, 0xd6, 0x84, 0x84, 0xd6, 0x94, 0x8c, 0xd6, 0x94, 0x94, 0xd6, 0x9c,
+ 0x9c, 0xd6, 0xad, 0xad, 0xd6, 0xd6, 0xd6, 0xd6, 0xe7, 0xde, 0xd6, 0xef,
+ 0xef, 0xde, 0xa5, 0xa5, 0xde, 0xbd, 0xbd, 0xde, 0xce, 0xce, 0xde, 0xde,
+ 0xde, 0xde, 0xe7, 0xe7, 0xde, 0xef, 0xe7, 0xde, 0xef, 0xef, 0xe7, 0xbd,
+ 0xbd, 0xe7, 0xe7, 0xe7, 0xe7, 0xef, 0xef, 0xe7, 0xf7, 0xf7, 0xef, 0xd6,
+ 0xd6, 0xef, 0xef, 0xef, 0xef, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xff,
+ 0xf7, 0xf7, 0xff, 0xff, 0xff, 0xf7, 0xf7, 0xff, 0xff, 0xff, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x76, 0x00, 0x35, 0x00, 0x00, 0x08,
+ 0xfe, 0x00, 0xdd, 0x09, 0x1c, 0x48, 0xb0, 0xa0, 0xba, 0x45, 0x71, 0x76,
+ 0xc8, 0x29, 0xc8, 0xb0, 0xa1, 0xc3, 0x87, 0x10, 0x23, 0x4a, 0x9c, 0x48,
+ 0xb1, 0xa2, 0x3a, 0x74, 0xe4, 0xb4, 0x05, 0x10, 0x10, 0xa0, 0x48, 0xc5,
+ 0x8f, 0x20, 0x43, 0x8a, 0x1c, 0x59, 0x10, 0x5d, 0xb6, 0x5e, 0xae, 0x14,
+ 0x08, 0x10, 0xe0, 0x91, 0xa4, 0xcb, 0x97, 0x30, 0x43, 0xaa, 0xfb, 0xd6,
+ 0x4b, 0x50, 0x1b, 0x08, 0x1c, 0x8d, 0xc4, 0xdc, 0xc9, 0xb3, 0xe7, 0x40,
+ 0x75, 0xd9, 0x2a, 0x3d, 0x09, 0xb2, 0x40, 0xa5, 0x4e, 0x9f, 0x48, 0x93,
+ 0xca, 0x84, 0x86, 0xe8, 0x09, 0x8d, 0x05, 0x0b, 0x04, 0x1c, 0x55, 0x4a,
+ 0xb5, 0xaa, 0x43, 0x93, 0x88, 0x82, 0xd0, 0xb8, 0xb0, 0x60, 0xc0, 0x54,
+ 0xab, 0x60, 0xad, 0x02, 0xcd, 0x4a, 0x43, 0x42, 0xd4, 0x23, 0x61, 0xd3,
+ 0x56, 0x55, 0xc7, 0x34, 0x48, 0x8d, 0x0d, 0x10, 0x14, 0x60, 0x51, 0x4b,
+ 0x17, 0x29, 0x5b, 0xb2, 0x19, 0x24, 0x14, 0xf8, 0x5a, 0xb7, 0xaf, 0xcb,
+ 0xb1, 0x41, 0x4e, 0x60, 0x90, 0xa0, 0x00, 0xad, 0xdf, 0xc3, 0x24, 0xef,
+ 0x6a, 0xcd, 0xab, 0x80, 0x2f, 0xe2, 0xc7, 0x13, 0xd1, 0xb5, 0xad, 0x31,
+ 0xc2, 0xac, 0x61, 0xc8, 0x98, 0x1d, 0x5e, 0x64, 0xa6, 0xe9, 0x8f, 0x9f,
+ 0x38, 0x42, 0x68, 0x90, 0x20, 0x7c, 0x59, 0xa0, 0x3a, 0x75, 0xe0, 0x64,
+ 0x39, 0xfa, 0x03, 0xa9, 0x96, 0x39, 0x87, 0xe6, 0x82, 0x31, 0x04, 0x06,
+ 0xcc, 0xdd, 0xe9, 0x69, 0xb3, 0x50, 0x35, 0x54, 0x17, 0x2c, 0xd8, 0xeb,
+ 0x9f, 0xea, 0xd2, 0x2d, 0xcb, 0xc4, 0xa8, 0x14, 0x30, 0x69, 0xe1, 0xc0,
+ 0x81, 0x33, 0xa8, 0x4e, 0x1a, 0x26, 0x39, 0x87, 0x62, 0x95, 0x2b, 0xb8,
+ 0xae, 0x9c, 0xb4, 0x5f, 0xda, 0xd4, 0x4d, 0x3b, 0xe5, 0xa7, 0xd1, 0x34,
+ 0xcd, 0xe8, 0xc0, 0xfe, 0xbd, 0xda, 0xf2, 0x03, 0xc8, 0x92, 0x25, 0x40,
+ 0x62, 0xdc, 0xa8, 0xbc, 0xe0, 0xb2, 0x3a, 0x72, 0xdf, 0x0c, 0xbd, 0x28,
+ 0xf1, 0xc3, 0x89, 0x13, 0x26, 0x4d, 0x38, 0xa5, 0x13, 0x88, 0x51, 0x9b,
+ 0x26, 0x34, 0x4e, 0x7c, 0xf7, 0x1e, 0x39, 0xd2, 0x2c, 0x50, 0x00, 0x16,
+ 0xc9, 0x64, 0xb1, 0x80, 0x04, 0x1b, 0xfc, 0xe6, 0x0e, 0x46, 0x19, 0x95,
+ 0xc0, 0xe0, 0x21, 0x0f, 0x96, 0x13, 0x1f, 0x09, 0x25, 0x4c, 0x30, 0xc0,
+ 0x4a, 0x01, 0x74, 0x88, 0xc0, 0x7e, 0x17, 0x81, 0xe3, 0x0b, 0x16, 0x12,
+ 0x44, 0x10, 0x41, 0x89, 0x0f, 0x30, 0x72, 0x1a, 0x39, 0xe4, 0x44, 0xd3,
+ 0x61, 0x00, 0x71, 0x5c, 0x02, 0x01, 0x07, 0x24, 0x28, 0x70, 0x00, 0x85,
+ 0x25, 0x7d, 0x03, 0x4d, 0x1c, 0x1b, 0xc8, 0xf0, 0x43, 0x79, 0x33, 0xfc,
+ 0x20, 0x03, 0x09, 0x70, 0xb5, 0x67, 0x9b, 0x49, 0xbe, 0xec, 0x30, 0x01,
+ 0x09, 0x32, 0xe0, 0x77, 0x46, 0x13, 0x4d, 0x74, 0x51, 0xc7, 0x36, 0x26,
+ 0x21, 0x83, 0x49, 0x13, 0xf6, 0x9d, 0x61, 0x21, 0x32, 0xbd, 0xbc, 0xd0,
+ 0xd5, 0x02, 0x7a, 0xc4, 0xb1, 0xe0, 0x06, 0x8f, 0x98, 0xf6, 0x0d, 0x32,
+ 0xae, 0xf0, 0xc1, 0xc1, 0x06, 0x0b, 0x98, 0x42, 0xce, 0x49, 0x2e, 0x18,
+ 0xc0, 0xc1, 0x0c, 0x1c, 0x14, 0xc5, 0x51, 0x87, 0x56, 0xb4, 0x83, 0xce,
+ 0x99, 0x70, 0x44, 0xa0, 0x81, 0x06, 0x7e, 0x6a, 0xf0, 0x80, 0x02, 0x04,
+ 0x60, 0x71, 0x66, 0x2f, 0x89, 0x00, 0xb0, 0xd1, 0x03, 0x03, 0x48, 0x20,
+ 0x43, 0x09, 0x06, 0x0a, 0xb0, 0x0c, 0x41, 0x26, 0xf5, 0xf2, 0x06, 0x04,
+ 0x1b, 0x8c, 0x50, 0x82, 0x0c, 0x48, 0xf8, 0x30, 0xe4, 0x06, 0x66, 0xb5,
+ 0x77, 0x11, 0x34, 0xa2, 0xe4, 0xc0, 0xa0, 0x0c, 0x3e, 0x70, 0x91, 0x05,
+ 0x19, 0x67, 0x38, 0x81, 0x46, 0x17, 0xfe, 0x74, 0x64, 0xe3, 0x8a, 0x20,
+ 0x82, 0xf8, 0xe1, 0x04, 0x94, 0x87, 0xf4, 0x82, 0x88, 0x11, 0x05, 0x30,
+ 0x50, 0xc0, 0x0e, 0x6c, 0xe0, 0x01, 0x41, 0x03, 0x1b, 0xc4, 0x90, 0xce,
+ 0x7b, 0xba, 0xe2, 0x11, 0x03, 0xa8, 0x30, 0x9c, 0x59, 0x89, 0x0e, 0x0b,
+ 0xd2, 0x07, 0x43, 0x06, 0x76, 0x06, 0x70, 0x85, 0x36, 0xe5, 0x40, 0xe3,
+ 0x8a, 0x1b, 0x10, 0x44, 0x30, 0xc2, 0x08, 0x2c, 0x54, 0x91, 0x50, 0x04,
+ 0x0a, 0x04, 0x20, 0x46, 0x25, 0x6c, 0x44, 0xd1, 0xa1, 0x00, 0x0a, 0x2c,
+ 0xb0, 0xc1, 0x0c, 0x30, 0xb0, 0xa9, 0x40, 0x1c, 0x03, 0xed, 0xe9, 0x0a,
+ 0x1e, 0x17, 0x40, 0xc0, 0xe0, 0x0e, 0x37, 0xd0, 0x40, 0x03, 0x0a, 0x21,
+ 0x80, 0x6a, 0x99, 0x64, 0x95, 0x7c, 0xc1, 0xe0, 0x06, 0x24, 0x10, 0xa1,
+ 0x55, 0x10, 0x6e, 0xcc, 0xe1, 0x44, 0x1a, 0x6a, 0x68, 0x52, 0x89, 0x17,
+ 0x41, 0xb0, 0xe1, 0x47, 0x13, 0x3f, 0x94, 0xf0, 0x46, 0x14, 0x02, 0x8b,
+ 0xd0, 0x46, 0x10, 0x4f, 0x5c, 0x21, 0xc1, 0x04, 0x1b, 0xa0, 0x02, 0xd4,
+ 0xc4, 0x39, 0xac, 0x29, 0xc1, 0x22, 0x35, 0xe1, 0xa0, 0x2f, 0x07, 0x3f,
+ 0xe0, 0x70, 0xc2, 0x09, 0x29, 0xe0, 0x24, 0x40, 0x08, 0x6f, 0x8a, 0xc2,
+ 0x46, 0x08, 0x7e, 0xee, 0x30, 0x44, 0x10, 0x41, 0x78, 0x41, 0xc8, 0x05,
+ 0xe4, 0x12, 0x10, 0x45, 0x60, 0x2b, 0x25, 0x00, 0x81, 0x05, 0x28, 0x0c,
+ 0x91, 0xc5, 0x68, 0x0b, 0xbc, 0x60, 0x1a, 0x39, 0x35, 0xd9, 0xb0, 0xa0,
+ 0x04, 0x2d, 0xe0, 0xc1, 0x86, 0x53, 0x1d, 0x74, 0x10, 0x82, 0x04, 0x10,
+ 0xb4, 0xf7, 0x8d, 0x2b, 0x6c, 0x7c, 0x50, 0x02, 0x93, 0x57, 0x08, 0xb2,
+ 0x35, 0x0d, 0x41, 0xb4, 0x71, 0x46, 0x17, 0x69, 0xd0, 0x31, 0xca, 0x1d,
+ 0x40, 0xbf, 0x01, 0xa5, 0x0f, 0x9e, 0x62, 0x28, 0x81, 0xfe, 0x22, 0x78,
+ 0x68, 0x15, 0x85, 0x04, 0x19, 0x4c, 0xe0, 0x03, 0x39, 0xc8, 0xf4, 0xfd,
+ 0x02, 0xa8, 0x23, 0xf8, 0x32, 0xb1, 0x07, 0x0c, 0x6c, 0x50, 0x42, 0x18,
+ 0x5c, 0x9b, 0x90, 0x83, 0x4a, 0x01, 0x5c, 0x42, 0xb6, 0x10, 0x19, 0x8c,
+ 0x10, 0x43, 0x1e, 0x78, 0x38, 0x45, 0x44, 0x0f, 0x23, 0x68, 0x00, 0x41,
+ 0x11, 0x50, 0x98, 0x40, 0x41, 0x00, 0x08, 0x14, 0x80, 0x41, 0x10, 0x26,
+ 0x98, 0xf0, 0x84, 0x0f, 0xa0, 0x2a, 0xa0, 0x8e, 0x6d, 0x41, 0x3d, 0xe1,
+ 0xc0, 0x02, 0x79, 0x29, 0x82, 0x12, 0x22, 0x5e, 0xd0, 0xd0, 0x81, 0x07,
+ 0x70, 0x0d, 0xb0, 0x03, 0x32, 0x82, 0x04, 0x81, 0x00, 0x91, 0x89, 0xa3,
+ 0x29, 0x88, 0x53, 0x41, 0xf4, 0x01, 0xb7, 0x1a, 0xb0, 0x4c, 0xcc, 0x36,
+ 0x1c, 0x4c, 0x64, 0xbc, 0xc1, 0x06, 0x1c, 0x18, 0x02, 0x8d, 0xf4, 0x4f,
+ 0xe8, 0xc0, 0x01, 0x83, 0xa6, 0x4c, 0x7c, 0x03, 0x09, 0x13, 0x48, 0xd0,
+ 0x47, 0x2f, 0x77, 0xd0, 0x80, 0x40, 0x04, 0x24, 0xfc, 0x30, 0x0a, 0xef,
+ 0xfe, 0x46, 0xa1, 0x92, 0x00, 0x71, 0x2c, 0x9f, 0x02, 0x93, 0x5b, 0xb8,
+ 0x82, 0xc8, 0x17, 0x58, 0x54, 0x2f, 0xc3, 0x16, 0x97, 0x10, 0x85, 0x17,
+ 0x4c, 0x87, 0x00, 0x01, 0xec, 0xa5, 0x6f, 0x26, 0x08, 0xc2, 0xd3, 0x30,
+ 0x00, 0x81, 0xd9, 0xa1, 0xa3, 0x17, 0x7d, 0x4b, 0x80, 0x02, 0x24, 0xf0,
+ 0x82, 0x6f, 0xec, 0x09, 0x19, 0x4d, 0x31, 0xc1, 0x09, 0x44, 0x50, 0x94,
+ 0x1d, 0xb8, 0xc2, 0x0b, 0x6f, 0x81, 0x00, 0x04, 0xc6, 0x80, 0x11, 0x9a,
+ 0x14, 0x8f, 0x06, 0x60, 0x80, 0x58, 0x1a, 0x68, 0x41, 0x3c, 0xe6, 0x59,
+ 0x01, 0x08, 0x32, 0x00, 0xd5, 0x1e, 0x30, 0x02, 0x41, 0x7f, 0x49, 0x01,
+ 0x54, 0x13, 0xc8, 0x42, 0xf1, 0x0e, 0x27, 0x81, 0x11, 0x28, 0x43, 0x7a,
+ 0xfe, 0x15, 0x90, 0x40, 0xfb, 0xb4, 0x41, 0x3c, 0xad, 0x40, 0x61, 0x7e,
+ 0x55, 0x60, 0x43, 0x10, 0x58, 0x10, 0x03, 0x19, 0x2c, 0x42, 0x14, 0x79,
+ 0x50, 0xc2, 0x7d, 0x96, 0xc0, 0x07, 0x68, 0x64, 0x43, 0x80, 0x1a, 0x2c,
+ 0xe0, 0x02, 0xf6, 0x20, 0x40, 0x7f, 0x61, 0x01, 0x06, 0x60, 0x63, 0x87,
+ 0x3b, 0xc6, 0xd6, 0x3b, 0x05, 0xe8, 0x8b, 0x07, 0xb3, 0x7b, 0x0f, 0xd9,
+ 0x68, 0x70, 0x82, 0x10, 0x84, 0xad, 0x05, 0x42, 0x41, 0xc1, 0x02, 0x18,
+ 0x20, 0x81, 0x32, 0x3d, 0xa8, 0x76, 0x34, 0x88, 0x42, 0x17, 0xd6, 0xa0,
+ 0x06, 0x5a, 0x8c, 0x0d, 0x0f, 0xbe, 0xb3, 0xc1, 0xa3, 0x24, 0xa4, 0x8c,
+ 0x8b, 0xe0, 0xf1, 0x09, 0x2f, 0x20, 0x01, 0x09, 0x38, 0x10, 0x85, 0x1a,
+ 0x70, 0x80, 0x03, 0x25, 0xe8, 0x43, 0xed, 0x4c, 0x80, 0x03, 0x21, 0xce,
+ 0x20, 0x18, 0x57, 0x74, 0x0a, 0x0e, 0x0a, 0x50, 0x00, 0x01, 0x80, 0x81,
+ 0x62, 0x22, 0x68, 0x52, 0x19, 0xe4, 0x70, 0x2b, 0x27, 0x94, 0xe1, 0x12,
+ 0xd9, 0xb0, 0x50, 0x17, 0x6b, 0xa0, 0x12, 0x08, 0x1c, 0xc2, 0x17, 0x80,
+ 0xa4, 0x01, 0x16, 0x48, 0x90, 0x81, 0x06, 0x8e, 0x51, 0x14, 0x4e, 0x79,
+ 0x00, 0xe0, 0x46, 0xb0, 0x9f, 0x07, 0x15, 0x91, 0x06, 0x1b, 0xa8, 0xa5,
+ 0x0b, 0xb2, 0x72, 0x82, 0xca, 0x48, 0x00, 0x09, 0x53, 0x5b, 0x23, 0x15,
+ 0xba, 0xc0, 0x4c, 0x66, 0x48, 0x86, 0x98, 0x48, 0x80, 0xe1, 0x06, 0x1a,
+ 0xd0, 0x83, 0x63, 0x51, 0x2d, 0x96, 0x37, 0xc4, 0xde, 0x0a, 0x54, 0x80,
+ 0xbd, 0x0d, 0x48, 0x03, 0x8f, 0x43, 0x10, 0xe2, 0x0f, 0xcc, 0x10, 0xbd,
+ 0x27, 0xdc, 0x20, 0x03, 0x0a, 0x28, 0xc0, 0x02, 0x06, 0xe1, 0x94, 0x22,
+ 0xd4, 0x87, 0x0b, 0x50, 0x72, 0xc2, 0x2b, 0xc9, 0x71, 0x1a, 0x32, 0xd2,
+ 0xc0, 0x06, 0xe9, 0xfe, 0x5c, 0xc0, 0x22, 0x7e, 0x39, 0x4b, 0xb8, 0xcc,
+ 0xee, 0x1b, 0x42, 0xa1, 0x41, 0x0a, 0x32, 0x40, 0xd0, 0x49, 0xb1, 0x43,
+ 0x32, 0x82, 0x10, 0x68, 0x06, 0xd8, 0xb4, 0x03, 0xb2, 0xb8, 0x80, 0x41,
+ 0x24, 0xd8, 0x86, 0x40, 0xec, 0xb9, 0x05, 0x66, 0xa2, 0xc1, 0x1c, 0xcf,
+ 0x7c, 0x82, 0x11, 0x96, 0x10, 0xa4, 0x35, 0x4d, 0x80, 0x0c, 0x0f, 0x62,
+ 0x8a, 0x53, 0x9e, 0x30, 0x82, 0x0d, 0x2c, 0x09, 0x7b, 0x13, 0x18, 0xc3,
+ 0x4c, 0xd6, 0x18, 0x04, 0x2b, 0x38, 0x6e, 0x06, 0x40, 0x40, 0xc2, 0xe1,
+ 0x20, 0x60, 0x00, 0x05, 0x5c, 0x22, 0x2b, 0x94, 0xc4, 0x8f, 0x7d, 0xe6,
+ 0xf0, 0x8a, 0x6c, 0xd0, 0xb3, 0x9e, 0x1f, 0xa4, 0x81, 0x10, 0xbe, 0xc4,
+ 0x08, 0x68, 0x9c, 0xd0, 0x08, 0x23, 0x10, 0xa1, 0x18, 0xc9, 0xd1, 0x45,
+ 0x1b, 0x2c, 0x74, 0x03, 0x3d, 0x28, 0x07, 0xb2, 0xda, 0x60, 0x83, 0x92,
+ 0xc2, 0x65, 0x07, 0x01, 0xc5, 0x81, 0x22, 0x65, 0x50, 0x86, 0x72, 0x98,
+ 0x44, 0x28, 0x56, 0xc0, 0x92, 0x1a, 0x38, 0xb1, 0x52, 0x3c, 0x50, 0xe1,
+ 0x56, 0x4b, 0x38, 0xc2, 0x16, 0x1c, 0xc7, 0x81, 0x4c, 0xb0, 0x83, 0x26,
+ 0x6c, 0x60, 0x23, 0x0e, 0x48, 0x36, 0x01, 0x92, 0x6d, 0x60, 0x19, 0xed,
+ 0x28, 0x47, 0x0b, 0x69, 0xf0, 0x84, 0x22, 0xf4, 0xe8, 0x51, 0xdf, 0x33,
+ 0x4b, 0x29, 0x26, 0x79, 0x82, 0x24, 0x70, 0xe1, 0x0c, 0x65, 0x80, 0xc6,
+ 0x37, 0xc8, 0x81, 0x8e, 0xd3, 0xa0, 0x02, 0x13, 0x4d, 0x2d, 0xca, 0x02,
+ 0x1a, 0x61, 0x54, 0xad, 0xe8, 0x40, 0x60, 0xb3, 0x23, 0x5c, 0x2c, 0x5d,
+ 0x60, 0x55, 0x1f, 0x98, 0xc2, 0x17, 0x89, 0x98, 0x02, 0x06, 0xbe, 0x75,
+ 0xbd, 0x23, 0x04, 0x55, 0x08, 0x89, 0x64, 0x92, 0x19, 0x50, 0x71, 0x89,
+ 0x37, 0x64, 0x81, 0x09, 0xae, 0x4a, 0xfe, 0xc3, 0x34, 0x08, 0x27, 0x88,
+ 0x2f, 0x38, 0x81, 0x99, 0x4b, 0x10, 0x42, 0x1b, 0x62, 0x18, 0x03, 0x0e,
+ 0x48, 0xe3, 0x99, 0xac, 0x3b, 0x41, 0x8f, 0x38, 0x30, 0x81, 0x12, 0x24,
+ 0xc1, 0x4c, 0x64, 0x5b, 0x18, 0xc2, 0xce, 0x26, 0xb0, 0x01, 0xf0, 0x81,
+ 0x8c, 0xad, 0x33, 0x02, 0x96, 0x9a, 0xa0, 0x09, 0x6d, 0x64, 0x23, 0x1a,
+ 0xca, 0x80, 0x04, 0x13, 0xb8, 0x30, 0x8a, 0xde, 0x0d, 0x75, 0x00, 0x05,
+ 0xa0, 0xec, 0x09, 0x75, 0x20, 0x01, 0xb0, 0x39, 0x50, 0xa4, 0x34, 0xc0,
+ 0xc1, 0x08, 0x14, 0xb9, 0x5e, 0x84, 0x2d, 0x52, 0x91, 0x24, 0x88, 0x81,
+ 0x16, 0x7e, 0x29, 0x05, 0x12, 0xc0, 0x94, 0x09, 0x5d, 0x40, 0x03, 0x80,
+ 0xcc, 0x80, 0xa5, 0x4d, 0x90, 0x63, 0x7b, 0x51, 0xe0, 0x82, 0x7e, 0xbb,
+ 0x10, 0x06, 0xb6, 0x89, 0x01, 0x08, 0x68, 0x90, 0x41, 0x0c, 0xc4, 0x31,
+ 0x36, 0x36, 0x98, 0xa0, 0x03, 0x20, 0x60, 0x6e, 0x09, 0x64, 0x51, 0xaf,
+ 0xed, 0xf5, 0x2e, 0x05, 0x23, 0x58, 0x81, 0x07, 0x50, 0xa0, 0x82, 0x5a,
+ 0x72, 0xb2, 0x14, 0x45, 0x34, 0x81, 0x10, 0xe0, 0xc9, 0x85, 0x2e, 0xa8,
+ 0x81, 0x0e, 0x5c, 0x60, 0xc2, 0x76, 0x65, 0x50, 0x08, 0xef, 0xa6, 0x53,
+ 0x01, 0x45, 0x1d, 0x6f, 0x2d, 0x6d, 0x39, 0x13, 0x08, 0xfa, 0x0d, 0x06,
+ 0xf0, 0x25, 0x99, 0x22, 0x79, 0x80, 0x63, 0x12, 0x6c, 0xa1, 0xc1, 0x5a,
+ 0xc1, 0x41, 0x12, 0x96, 0x60, 0xd1, 0x34, 0xa0, 0x01, 0x4b, 0x9a, 0xc8,
+ 0x19, 0x1b, 0xb4, 0x90, 0x86, 0x34, 0x74, 0xc1, 0x11, 0xcb, 0xe3, 0xeb,
+ 0x0e, 0x0e, 0x56, 0x06, 0x74, 0x14, 0xb1, 0x03, 0x27, 0x28, 0x01, 0x07,
+ 0x30, 0xe0, 0x83, 0xd9, 0x99, 0xa9, 0x26, 0x78, 0xf8, 0x42, 0x1b, 0x28,
+ 0x66, 0x02, 0x1a, 0x7c, 0x61, 0x04, 0x45, 0xe1, 0xc1, 0xfe, 0x15, 0x7b,
+ 0x87, 0xc2, 0x2d, 0x60, 0x09, 0x40, 0x4e, 0x48, 0x31, 0x13, 0xca, 0xa0,
+ 0x08, 0xef, 0x1a, 0x08, 0x02, 0xe2, 0xd5, 0x0a, 0x0b, 0x82, 0x89, 0x81,
+ 0x75, 0xf0, 0xe7, 0x8a, 0x4a, 0xbc, 0xe7, 0x0a, 0x60, 0xf0, 0x3d, 0x0c,
+ 0x94, 0x60, 0x05, 0x35, 0x90, 0x81, 0xa2, 0xfd, 0x40, 0x30, 0x25, 0x02,
+ 0xad, 0x08, 0x5c, 0x00, 0x44, 0x1d, 0xd2, 0xd0, 0x84, 0x3e, 0x00, 0x83,
+ 0x45, 0x2d, 0x94, 0x42, 0x16, 0xd4, 0x00, 0x88, 0x68, 0xd4, 0x64, 0x28,
+ 0x82, 0x50, 0xf4, 0x23, 0xc4, 0x71, 0x32, 0xd6, 0xa5, 0x40, 0xcb, 0x13,
+ 0xd0, 0x04, 0x41, 0x46, 0xd5, 0x0b, 0x52, 0xf4, 0xa2, 0x17, 0xa2, 0x88,
+ 0xf2, 0x13, 0xc2, 0x00, 0x95, 0x0d, 0x80, 0x83, 0x29, 0x14, 0x0b, 0xc2,
+ 0x10, 0xb0, 0xe0, 0x2a, 0xb4, 0x72, 0x21, 0x13, 0xda, 0x58, 0xe3, 0x10,
+ 0x8a, 0x22, 0x01, 0xf1, 0x0a, 0x21, 0x08, 0x3a, 0x58, 0x68, 0x06, 0xbc,
+ 0x1c, 0xd2, 0x59, 0x79, 0x61, 0x28, 0x42, 0xc0, 0x01, 0x11, 0xa8, 0xf0,
+ 0x05, 0x2f, 0xb0, 0x81, 0x10, 0xaf, 0x20, 0x47, 0x3b, 0x46, 0xe5, 0x6c,
+ 0x68, 0x4f, 0x21, 0x0e, 0x7a, 0x18, 0x85, 0x4f, 0xdf, 0xb3, 0x3d, 0x3c,
+ 0xdc, 0xa1, 0x12, 0xbf, 0xa0, 0x92, 0xac, 0xd4, 0x36, 0x08, 0x52, 0x44,
+ 0x23, 0x8d, 0x93, 0xe4, 0xc1, 0x90, 0x48, 0x30, 0x1d, 0x4a, 0xc1, 0x67,
+ 0xb1, 0x6f, 0xba, 0x17, 0xd0, 0xc0, 0x90, 0x97, 0x11, 0x6c, 0x83, 0x70,
+ 0x95, 0xc0, 0x43, 0xae, 0xa1, 0x60, 0x85, 0x2c, 0xc4, 0x81, 0x11, 0xd1,
+ 0xc0, 0x88, 0xb3, 0xdb, 0x10, 0x07, 0x4c, 0x28, 0x23, 0x1c, 0x41, 0x61,
+ 0x83, 0x17, 0xc4, 0xb0, 0x08, 0x60, 0x7c, 0xe7, 0x27, 0x55, 0x12, 0x05,
+ 0x22, 0x68, 0x85, 0x08, 0x51, 0xb8, 0x42, 0x14, 0x95, 0x10, 0x45, 0x2f,
+ 0xfe, 0xb2, 0xd1, 0xd8, 0x15, 0x65, 0x03, 0x4d, 0x88, 0xd8, 0x78, 0xc7,
+ 0x91, 0x31, 0x6e, 0x43, 0xc2, 0xda, 0x15, 0xc8, 0xb0, 0xe0, 0x7b, 0x64,
+ 0xe5, 0x0a, 0x57, 0x44, 0xe3, 0xa7, 0x19, 0xbd, 0x81, 0x0c, 0x66, 0x50,
+ 0x02, 0x48, 0xb0, 0xa3, 0x1d, 0x18, 0xc7, 0x88, 0x3a, 0x32, 0x31, 0x0d,
+ 0xe0, 0xd2, 0xa0, 0x08, 0xc8, 0x13, 0x07, 0x46, 0xb4, 0x55, 0x09, 0x41,
+ 0xe0, 0x01, 0x0f, 0x82, 0xb0, 0xc4, 0xc8, 0x19, 0xfb, 0x5f, 0x8d, 0x8b,
+ 0x02, 0x19, 0xf4, 0xb4, 0x57, 0x25, 0x2a, 0xe1, 0x8a, 0x6f, 0x30, 0xfb,
+ 0x48, 0xe4, 0xf0, 0x86, 0x31, 0x8a, 0xc1, 0x0b, 0x5e, 0xec, 0x82, 0x17,
+ 0xc5, 0x28, 0xc6, 0xd8, 0x8b, 0xe1, 0x8c, 0x67, 0x5c, 0xe3, 0xed, 0x6f,
+ 0x7f, 0x86, 0x31, 0x8c, 0x61, 0xf6, 0x5d, 0xa4, 0xdd, 0x19, 0xd6, 0xb8,
+ 0x46, 0xde, 0xad, 0xf1, 0x8c, 0x63, 0xa8, 0x1d, 0xef, 0x7b, 0x97, 0xfb,
+ 0xdc, 0xf1, 0x0e, 0x77, 0x5e, 0xd0, 0x8d, 0x07, 0x40, 0xf8, 0xc1, 0x0c,
+ 0xa4, 0x41, 0x0e, 0xbd, 0x57, 0xe3, 0xf1, 0xdd, 0xb0, 0xa2, 0x29, 0x8c,
+ 0x2b, 0x8d, 0x22, 0xde, 0xc0, 0x53, 0x25, 0x58, 0x02, 0x39, 0xb0, 0x41,
+ 0x0c, 0x62, 0xe8, 0xa2, 0x15, 0xac, 0x08, 0x3d, 0x2b, 0x5a, 0x31, 0x8c,
+ 0xce, 0x37, 0xc3, 0xf3, 0xad, 0x48, 0x7d, 0xe9, 0x4f, 0xaf, 0x8b, 0xcf,
+ 0x93, 0xbe, 0x19, 0xd4, 0xb0, 0x06, 0xd0, 0x6d, 0xf3, 0xa6, 0x5e, 0xe8,
+ 0xe2, 0x16, 0xb7, 0x48, 0x05, 0xee, 0x77, 0xbf, 0x7b, 0xdd, 0xf3, 0x1e,
+ 0xf7, 0xb6, 0xe0, 0x7d, 0xf0, 0x6d, 0x11, 0xfc, 0xdd, 0x0f, 0xdf, 0xf8,
+ 0xb7, 0x20, 0xfe, 0xf1, 0x81, 0x8f, 0x8b, 0x27, 0x0c, 0x01, 0x08, 0x30,
+ 0x2d, 0x03, 0x32, 0x8c, 0x41, 0xfc, 0x54, 0xd8, 0x22, 0x15, 0xc2, 0xa8,
+ 0x44, 0x21, 0x7e, 0xfe, 0x34, 0x03, 0x19, 0x64, 0x21, 0x0c, 0x3a, 0xe0,
+ 0xfe, 0x0f, 0x58, 0x76, 0xfd, 0x54, 0x98, 0xff, 0xfc, 0xe8, 0x37, 0xbf,
+ 0x27, 0xd0, 0xef, 0x89, 0xf6, 0xbb, 0xff, 0xfd, 0x9e, 0xe8, 0x44, 0x2e,
+ 0xce, 0xf1, 0x20, 0x9a, 0x80, 0x7c, 0x12, 0x91, 0xf8, 0x84, 0xfe, 0xf3,
+ 0xff, 0x89, 0xfc, 0x47, 0x42, 0x15, 0xfd, 0x07, 0x80, 0xfe, 0x07, 0x80,
+ 0xfb, 0xb7, 0x0a, 0x91, 0x60, 0x80, 0xab, 0x00, 0x0a, 0x0a, 0xb8, 0x80,
+ 0x0c, 0xd8, 0x80, 0xa0, 0xc0, 0x0a, 0xad, 0xd7, 0x0a, 0x81, 0xa0, 0x40,
+ 0x5d, 0x00, 0x25, 0x8a, 0x50, 0x09, 0xa1, 0x00, 0x0a, 0xad, 0xa0, 0x0b,
+ 0x9e, 0x07, 0x0a, 0x76, 0xc0, 0x06, 0x5c, 0x90, 0x78, 0x42, 0x12, 0x24,
+ 0xe6, 0x01, 0x04, 0x5c, 0x60, 0x09, 0x94, 0x10, 0x09, 0x0a, 0x28, 0x09,
+ 0xa0, 0x10, 0x09, 0x91, 0x20, 0x09, 0x2a, 0xf8, 0x82, 0x32, 0x08, 0x83,
+ 0x30, 0x38, 0x83, 0x92, 0x70, 0x83, 0x1a, 0xc8, 0x0b, 0xcf, 0xc0, 0x0d,
+ 0xd7, 0x30, 0x0e, 0xb6, 0xa1, 0x23, 0xae, 0x50, 0x09, 0x88, 0xb0, 0x75,
+ 0x89, 0xb0, 0x75, 0x5b, 0x37, 0x84, 0x46, 0x58, 0x09, 0x45, 0x68, 0x84,
+ 0x4b, 0x98, 0x84, 0x44, 0x28, 0x84, 0x50, 0x58, 0x84, 0x43, 0x38, 0x84,
+ 0x52, 0x58, 0x84, 0x22, 0xd7, 0x0b, 0x13, 0x33, 0x04, 0x50, 0xd2, 0x04,
+ 0x73, 0x00, 0x6b, 0x56, 0xd8, 0x0b, 0xd0, 0x80, 0x0c, 0x13, 0x13, 0x04,
+ 0x42, 0x90, 0x05, 0x4d, 0x00, 0x7d, 0x4b, 0xb0, 0x85, 0x3c, 0x05, 0x72,
+ 0x4e, 0xd8, 0x86, 0x6e, 0xc8, 0x86, 0x4e, 0xe8, 0x71, 0x31, 0xd7, 0x4b,
+ 0xfc, 0xf1, 0x26, 0xd0, 0x10, 0x86, 0xc8, 0x90, 0x87, 0x7a, 0x88, 0x87,
+ 0x7a, 0xd8, 0x87, 0x79, 0x18, 0x86, 0x80, 0x88, 0x0c, 0x81, 0x18, 0x86,
+ 0xc9, 0x80, 0x87, 0x84, 0x68, 0x88, 0xbf, 0x82, 0x78, 0x87, 0xba, 0xf2,
+ 0x04, 0x60, 0x50, 0x06, 0x73, 0xd0, 0x05, 0xc0, 0x90, 0x0d, 0x77, 0x78,
+ 0x87, 0xda, 0xf0, 0x0d, 0x27, 0x21, 0x08, 0xb9, 0x86, 0x03, 0x47, 0x90,
+ 0x86, 0x4d, 0xe0, 0x07, 0xb2, 0x60, 0x89, 0x92, 0x38, 0x89, 0xa2, 0x38,
+ 0x8a, 0xa4, 0x58, 0x8a, 0x77, 0x98, 0x0d, 0x8b, 0xf5, 0x75, 0x47, 0x82,
+ 0x0e, 0xac, 0xd8, 0x8a, 0xae, 0xf8, 0x8a, 0xb0, 0x18, 0x8b, 0xb2, 0x38,
+ 0x8b, 0xac, 0x58, 0x75, 0xb4, 0x22, 0x0a, 0x24, 0x77, 0x1a, 0xaf, 0x78,
+ 0x11, 0x34, 0xd1, 0x74, 0x12, 0x17, 0x2c, 0x95, 0x30, 0x72, 0xac, 0x78,
+ 0x11, 0xb0, 0x48, 0x8c, 0xc6, 0x38, 0x8c, 0x8d, 0x95, 0x8c, 0xe9, 0x90,
+ 0x8c, 0x17, 0xd1, 0x8c, 0xaa, 0xb8, 0x6a, 0x03, 0xd1, 0x0e, 0x62, 0x34,
+ 0x7b, 0x11, 0xf1, 0x8c, 0x32, 0xf1, 0x5f, 0x79, 0x38, 0x6e, 0x9a, 0x31,
+ 0x73, 0x68, 0x52, 0x73, 0x82, 0xc8, 0x58, 0xd4, 0x98, 0x19, 0x69, 0x71,
+ 0x11, 0x2c, 0x82, 0x0e, 0xe1, 0xb8, 0x1b, 0xb5, 0x58, 0x8e, 0x8d, 0x25,
+ 0x8e, 0xec, 0xd8, 0x8e, 0xee, 0xf8, 0x8e, 0xf0, 0x18, 0x8f, 0xf2, 0x38,
+ 0x8f, 0xf4, 0x58, 0x8f, 0xf6, 0x78, 0x8f, 0xf8, 0x98, 0x8f, 0xfa, 0xb8,
+ 0x8f, 0xfc, 0xd8, 0x8f, 0xfe, 0xf8, 0x8f, 0x00, 0x19, 0x90, 0x02, 0x39,
+ 0x90, 0x04, 0xb9, 0x8f, 0x01, 0x01, 0x00, 0x3b
+};
+const unsigned int logo_len = 3536;
+
+unsigned char search_data[] = {
+ 0x47, 0x49, 0x46, 0x38, 0x39, 0x61, 0x78, 0x00, 0x1a, 0x00, 0xe7, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x01, 0x4c, 0x01, 0x01, 0x4c, 0x00,
+ 0x02, 0x4c, 0x01, 0x02, 0x4c, 0x02, 0x01, 0x63, 0x01, 0x02, 0x63, 0x02,
+ 0x02, 0x63, 0x01, 0x04, 0x63, 0x02, 0x04, 0x63, 0x04, 0x04, 0x63, 0x04,
+ 0x07, 0x72, 0x02, 0x04, 0x72, 0x04, 0x04, 0x72, 0x04, 0x07, 0x72, 0x07,
+ 0x07, 0x72, 0x04, 0x09, 0x72, 0x07, 0x09, 0x7d, 0x07, 0x09, 0x7d, 0x09,
+ 0x09, 0x7d, 0x09, 0x0d, 0x87, 0x09, 0x0d, 0x87, 0x09, 0x11, 0x87, 0x0d,
+ 0x11, 0x90, 0x0d, 0x11, 0x90, 0x0d, 0x15, 0x90, 0x11, 0x15, 0x9a, 0x11,
+ 0x15, 0x9a, 0x11, 0x1a, 0x9a, 0x15, 0x1a, 0xa2, 0x15, 0x1a, 0xa2, 0x15,
+ 0x20, 0xa2, 0x1a, 0x20, 0xa9, 0x1a, 0x20, 0xa9, 0x1a, 0x26, 0xa0, 0x20,
+ 0x28, 0xa0, 0x24, 0x28, 0xa7, 0x2f, 0x37, 0xa7, 0x32, 0x37, 0xb0, 0x20,
+ 0x26, 0xb0, 0x20, 0x2d, 0xb7, 0x26, 0x2d, 0xbd, 0x2d, 0x2d, 0xb7, 0x26,
+ 0x34, 0xb2, 0x29, 0x36, 0xb7, 0x2d, 0x34, 0xbd, 0x2d, 0x34, 0xb5, 0x32,
+ 0x3c, 0xad, 0x3e, 0x45, 0x8e, 0x43, 0x3b, 0xad, 0x41, 0x45, 0xbf, 0x43,
+ 0x4e, 0xb3, 0x4d, 0x53, 0xb3, 0x53, 0x4f, 0xb3, 0x50, 0x53, 0xba, 0x5e,
+ 0x62, 0xb8, 0x71, 0x5f, 0xc3, 0x34, 0x3b, 0xc9, 0x3b, 0x44, 0xc9, 0x3b,
+ 0x4d, 0xc9, 0x44, 0x4d, 0xcf, 0x44, 0x56, 0xcf, 0x4d, 0x56, 0xd5, 0x4d,
+ 0x5f, 0xd5, 0x56, 0x5f, 0xcc, 0x54, 0x61, 0xda, 0x56, 0x6b, 0xda, 0x5f,
+ 0x6b, 0xdf, 0x5f, 0x6b, 0xc0, 0x6b, 0x70, 0xc0, 0x6d, 0x70, 0xcd, 0x7f,
+ 0x6a, 0xc6, 0x7a, 0x7f, 0xc6, 0x7c, 0x7f, 0xd7, 0x64, 0x72, 0xd6, 0x66,
+ 0x72, 0xd7, 0x6f, 0x72, 0xd7, 0x6d, 0x79, 0xd6, 0x71, 0x71, 0xe5, 0x6b,
+ 0x75, 0xe5, 0x75, 0x75, 0xe9, 0x75, 0x8c, 0xcd, 0x81, 0x6e, 0xcd, 0x85,
+ 0x72, 0xcd, 0x88, 0x8d, 0xcd, 0x8a, 0x8d, 0xd3, 0x98, 0x9a, 0xd9, 0xa7,
+ 0xa9, 0xdc, 0xaa, 0xa0, 0xdf, 0xb6, 0xb7, 0xee, 0x80, 0x8c, 0xe5, 0x8b,
+ 0x92, 0xee, 0x8c, 0x9a, 0xf2, 0x8c, 0x9a, 0xea, 0x8c, 0xa0, 0xec, 0x99,
+ 0xa3, 0xf7, 0x9a, 0xb4, 0xe1, 0xac, 0xa3, 0xea, 0xae, 0xa0, 0xef, 0xae,
+ 0xb1, 0xe6, 0xb5, 0xac, 0xf7, 0xa6, 0xb4, 0xfc, 0xa6, 0xc1, 0xfa, 0xaf,
+ 0xc0, 0xf3, 0xc1, 0xb3, 0xf2, 0xd6, 0xac, 0xff, 0xff, 0xa3, 0xe6, 0xc4,
+ 0xc6, 0xec, 0xd2, 0xd0, 0xec, 0xd3, 0xd4, 0xf6, 0xcd, 0xc9, 0xfb, 0xc5,
+ 0xd1, 0xfb, 0xc9, 0xd4, 0xf2, 0xd6, 0xd3, 0xf7, 0xd3, 0xd2, 0xf5, 0xd0,
+ 0xd7, 0xf3, 0xdc, 0xdc, 0xf9, 0xd4, 0xd7, 0xfa, 0xd1, 0xd8, 0xfa, 0xd6,
+ 0xda, 0xf9, 0xda, 0xd5, 0xf9, 0xdf, 0xe1, 0xfc, 0xde, 0xe0, 0xff, 0xff,
+ 0xcb, 0xff, 0xff, 0xcc, 0xf2, 0xe2, 0xe2, 0xfa, 0xe5, 0xe8, 0xfe, 0xed,
+ 0xe9, 0xfe, 0xef, 0xf0, 0xf9, 0xf0, 0xf1, 0xfd, 0xf0, 0xf1, 0xff, 0xf4,
+ 0xf0, 0xff, 0xf6, 0xf2, 0xff, 0xf8, 0xf8, 0xff, 0xfa, 0xf8, 0xff, 0xfb,
+ 0xfa, 0xff, 0xfb, 0xfb, 0xff, 0xfd, 0xfa, 0xff, 0xfd, 0xfd, 0xff, 0xff,
+ 0xfd, 0xff, 0xff, 0xff, 0x00, 0xcc, 0x22, 0x00, 0xcc, 0x55, 0x00, 0xcc,
+ 0x99, 0x00, 0xcc, 0xcc, 0x00, 0xaa, 0xcc, 0x00, 0x66, 0xcc, 0x00, 0x33,
+ 0xcc, 0x00, 0x00, 0xcc, 0x11, 0x00, 0xcc, 0x44, 0x00, 0xcc, 0x55, 0x00,
+ 0xcc, 0x88, 0x00, 0xcc, 0xbb, 0x00, 0xcc, 0xcc, 0x00, 0xcc, 0xcc, 0x00,
+ 0xbb, 0xcc, 0x00, 0x88, 0xcc, 0x00, 0x66, 0xcc, 0x00, 0x44, 0xcc, 0x00,
+ 0x22, 0x99, 0x00, 0x00, 0x99, 0x11, 0x00, 0x99, 0x33, 0x00, 0x99, 0x44,
+ 0x00, 0x99, 0x66, 0x00, 0x99, 0x88, 0x00, 0x99, 0x99, 0x00, 0x88, 0x99,
+ 0x00, 0x66, 0x99, 0x00, 0x55, 0x99, 0x00, 0x33, 0x99, 0x00, 0x11, 0x99,
+ 0x00, 0x00, 0x99, 0x00, 0x00, 0x99, 0x11, 0x00, 0x99, 0x44, 0x00, 0x99,
+ 0x77, 0x00, 0x99, 0x99, 0x00, 0x77, 0x99, 0x00, 0x55, 0x99, 0x00, 0x22,
+ 0x99, 0x00, 0x00, 0x99, 0x11, 0x00, 0x99, 0x33, 0x00, 0x99, 0x44, 0x00,
+ 0x99, 0x66, 0x00, 0x99, 0x88, 0x00, 0x99, 0x99, 0x00, 0x99, 0x99, 0x00,
+ 0x88, 0x99, 0x00, 0x66, 0x99, 0x00, 0x55, 0x99, 0x00, 0x33, 0x99, 0x00,
+ 0x11, 0x66, 0x00, 0x00, 0x66, 0x11, 0x00, 0x66, 0x22, 0x00, 0x66, 0x33,
+ 0x00, 0x66, 0x44, 0x00, 0x66, 0x55, 0x00, 0x66, 0x66, 0x00, 0x55, 0x66,
+ 0x00, 0x44, 0x66, 0x00, 0x33, 0x66, 0x00, 0x22, 0x66, 0x00, 0x11, 0x66,
+ 0x00, 0x00, 0x66, 0x00, 0x00, 0x66, 0x11, 0x00, 0x66, 0x22, 0x00, 0x66,
+ 0x44, 0x00, 0x66, 0x66, 0x00, 0x55, 0x66, 0x00, 0x33, 0x66, 0x00, 0x11,
+ 0x66, 0x00, 0x00, 0x66, 0x11, 0x00, 0x66, 0x22, 0x00, 0x66, 0x33, 0x00,
+ 0x66, 0x44, 0x00, 0x66, 0x55, 0x00, 0x66, 0x66, 0x00, 0x66, 0x66, 0x00,
+ 0x55, 0x66, 0x00, 0x44, 0x66, 0x00, 0x33, 0x66, 0x00, 0x22, 0x66, 0x00,
+ 0x11, 0x33, 0x00, 0x00, 0x33, 0x00, 0x00, 0x33, 0x11, 0x00, 0x33, 0x11,
+ 0x00, 0x33, 0x22, 0x00, 0x33, 0x22, 0x00, 0x33, 0x33, 0x00, 0x33, 0x33,
+ 0x00, 0x22, 0x33, 0x00, 0x11, 0x33, 0x00, 0x11, 0x33, 0x00, 0x00, 0x33,
+ 0x00, 0x00, 0x33, 0x00, 0x00, 0x33, 0x00, 0x00, 0x33, 0x11, 0x00, 0x33,
+ 0x22, 0x00, 0x33, 0x33, 0x00, 0x22, 0x33, 0x00, 0x11, 0x33, 0x00, 0x00,
+ 0x33, 0x00, 0x00, 0x33, 0x00, 0x00, 0x33, 0x11, 0x00, 0x33, 0x11, 0x00,
+ 0x33, 0x22, 0x00, 0x33, 0x22, 0x00, 0x33, 0x33, 0x00, 0x33, 0x33, 0x00,
+ 0x22, 0x33, 0x00, 0x22, 0x33, 0x00, 0x11, 0x33, 0x00, 0x11, 0x33, 0x00,
+ 0x00, 0x21, 0xf9, 0x04, 0x09, 0x01, 0x00, 0x7c, 0x00, 0x2c, 0x00, 0x00,
+ 0x00, 0x00, 0x78, 0x00, 0x1a, 0x00, 0x00, 0x08, 0xff, 0x00, 0xf9, 0x08,
+ 0x1c, 0x48, 0xb0, 0xa0, 0xc1, 0x83, 0x08, 0x13, 0x2a, 0x5c, 0xc8, 0xb0,
+ 0xa1, 0xc3, 0x87, 0x08, 0xd3, 0xa0, 0x21, 0x43, 0xe6, 0xcb, 0x17, 0x22,
+ 0x42, 0x80, 0x68, 0xdc, 0xc8, 0xb1, 0xa3, 0xc7, 0x8f, 0x20, 0x43, 0x8a,
+ 0x1c, 0x49, 0x52, 0xa4, 0x8f, 0x1d, 0x2e, 0x50, 0x70, 0x90, 0x20, 0x01,
+ 0x07, 0x96, 0x34, 0x0c, 0x25, 0xa2, 0x59, 0x43, 0x73, 0xcc, 0x17, 0x33,
+ 0x5d, 0xb4, 0x68, 0xe1, 0xc2, 0xb3, 0xa7, 0xcf, 0x9f, 0x40, 0x83, 0x0a,
+ 0x1d, 0x4a, 0xb4, 0xa8, 0x51, 0xa1, 0x51, 0x9e, 0xf8, 0x70, 0x71, 0x02,
+ 0xc4, 0x06, 0x96, 0x37, 0xb0, 0x28, 0x9c, 0xc8, 0xa6, 0x8f, 0x9f, 0x3c,
+ 0x6e, 0xc6, 0x68, 0x11, 0xf2, 0xc3, 0x87, 0xd7, 0xaf, 0x60, 0xc3, 0x8a,
+ 0x1d, 0x4b, 0xb6, 0xac, 0xd9, 0xb3, 0x68, 0xcd, 0xf6, 0xe0, 0x91, 0x23,
+ 0x85, 0x08, 0x0f, 0x1b, 0x34, 0x48, 0x70, 0x50, 0x43, 0xea, 0x1e, 0x83,
+ 0x13, 0xf1, 0xf8, 0xa1, 0xb3, 0xe6, 0x8b, 0x93, 0x20, 0x30, 0x3e, 0x08,
+ 0x1e, 0x4c, 0xb8, 0xb0, 0xe1, 0xc3, 0x88, 0x13, 0x2b, 0x5e, 0xcc, 0xb8,
+ 0xf1, 0x60, 0x10, 0x70, 0x33, 0x5c, 0x90, 0xc0, 0xa0, 0x2e, 0x5e, 0x32,
+ 0x74, 0xfc, 0xac, 0xd9, 0xb2, 0x64, 0x06, 0x8b, 0x11, 0x20, 0x3a, 0x88,
+ 0x1e, 0xdd, 0x81, 0x84, 0x8d, 0xd3, 0x36, 0x48, 0xab, 0x5e, 0xcd, 0xba,
+ 0xb5, 0xeb, 0xd7, 0xac, 0x4d, 0xa0, 0x36, 0x01, 0xbb, 0x36, 0x07, 0x0d,
+ 0x18, 0x2a, 0xb0, 0xac, 0x41, 0x86, 0xa0, 0xc4, 0x3c, 0x7e, 0xd0, 0x38,
+ 0x81, 0x41, 0x22, 0x34, 0x6b, 0x23, 0x6d, 0x18, 0x29, 0x57, 0x1e, 0xc8,
+ 0x0a, 0xe9, 0x2b, 0xcb, 0xa3, 0x47, 0x97, 0xa1, 0x3a, 0x49, 0xf4, 0x35,
+ 0xab, 0xa1, 0x4b, 0x5f, 0xde, 0x27, 0x89, 0x6a, 0x12, 0x55, 0xfa, 0x48,
+ 0xff, 0xef, 0x43, 0x7d, 0xb4, 0x78, 0xe5, 0xce, 0x47, 0x6b, 0x67, 0xd4,
+ 0x86, 0xf4, 0xed, 0x0a, 0x13, 0x24, 0x20, 0xb8, 0x71, 0x97, 0x4f, 0x1a,
+ 0x32, 0x68, 0x34, 0x3b, 0x79, 0x61, 0x7c, 0x35, 0x89, 0xe4, 0xdb, 0x29,
+ 0x67, 0xc4, 0x68, 0x81, 0x04, 0xc8, 0x9d, 0x6a, 0x32, 0x14, 0xb8, 0x5c,
+ 0x7b, 0xaa, 0x29, 0x68, 0x20, 0x23, 0xa9, 0x89, 0x76, 0x83, 0x83, 0xd2,
+ 0x05, 0x42, 0x5b, 0x07, 0x32, 0x4c, 0x47, 0x9a, 0x83, 0xde, 0xb9, 0x97,
+ 0x01, 0x05, 0x12, 0x34, 0x80, 0x80, 0x13, 0x02, 0x89, 0xf1, 0xc5, 0x1b,
+ 0x77, 0x78, 0x01, 0x43, 0x7f, 0xab, 0xad, 0xb1, 0xdc, 0x15, 0x37, 0x58,
+ 0x11, 0x5d, 0x15, 0x12, 0x3e, 0x88, 0x9e, 0x6a, 0x00, 0x46, 0xa7, 0xda,
+ 0x0d, 0xd7, 0xad, 0x91, 0xa3, 0x72, 0x34, 0x76, 0x60, 0x84, 0x8d, 0x8c,
+ 0x74, 0x28, 0xa3, 0x72, 0x7d, 0x90, 0xc6, 0xe3, 0x72, 0x17, 0x92, 0xb6,
+ 0xc1, 0x64, 0x10, 0x34, 0x40, 0x82, 0x40, 0x5b, 0x6c, 0x71, 0xc6, 0x19,
+ 0x4b, 0xa0, 0xe0, 0xda, 0x90, 0xca, 0x31, 0xd8, 0x81, 0x8b, 0x40, 0x8a,
+ 0xb6, 0x9e, 0x97, 0xae, 0x1d, 0x29, 0x9d, 0x6a, 0xeb, 0x25, 0x59, 0xe3,
+ 0x72, 0x37, 0x74, 0xb0, 0xa4, 0x72, 0x59, 0x50, 0x97, 0xe0, 0x8b, 0xa2,
+ 0x9d, 0xc7, 0x48, 0x7a, 0x62, 0x2e, 0xc8, 0x1a, 0x07, 0x93, 0x3d, 0x20,
+ 0x22, 0x4c, 0x38, 0x00, 0xc1, 0xc5, 0x16, 0x33, 0xb0, 0xa8, 0x5a, 0x16,
+ 0xcb, 0x35, 0x77, 0x03, 0x09, 0x32, 0x34, 0x59, 0x5a, 0x74, 0x1d, 0xba,
+ 0x66, 0xc3, 0x72, 0x55, 0xe8, 0xb8, 0xe1, 0x72, 0x78, 0x56, 0xca, 0x5c,
+ 0x69, 0x0e, 0x5e, 0x41, 0x9a, 0x15, 0x6b, 0x58, 0x61, 0x84, 0x9c, 0x1a,
+ 0x12, 0xb8, 0x5c, 0xa4, 0xaa, 0x65, 0x30, 0x81, 0x9f, 0x06, 0x48, 0x25,
+ 0x83, 0x0e, 0x43, 0x00, 0xff, 0xc1, 0xc2, 0x6b, 0x88, 0x6e, 0x97, 0x45,
+ 0x84, 0xa2, 0x71, 0xd9, 0x25, 0x4d, 0xbc, 0x66, 0x41, 0x1a, 0x09, 0x0a,
+ 0xf6, 0x41, 0x82, 0xa5, 0x6b, 0x2a, 0x97, 0x84, 0x0d, 0x31, 0x46, 0xd7,
+ 0xa6, 0xa6, 0x8c, 0x04, 0x42, 0xc2, 0x6b, 0x66, 0xda, 0xe8, 0xa8, 0x93,
+ 0x14, 0x38, 0xd0, 0x40, 0xab, 0x7c, 0x68, 0xc0, 0x82, 0x0e, 0x39, 0x88,
+ 0xf0, 0xda, 0x9b, 0xdb, 0x79, 0x2a, 0x5a, 0xad, 0x06, 0x8a, 0x3b, 0xee,
+ 0x72, 0xa9, 0x11, 0xdb, 0xc1, 0x7a, 0x06, 0x0e, 0xd8, 0x81, 0x9d, 0x41,
+ 0xba, 0x66, 0xe7, 0x83, 0x64, 0xaa, 0xb6, 0x41, 0x05, 0xd6, 0x62, 0x7b,
+ 0x01, 0x08, 0x29, 0xa4, 0x60, 0xe8, 0x6a, 0x36, 0x80, 0xb9, 0x1d, 0x6d,
+ 0xc3, 0xda, 0xd8, 0xa6, 0x68, 0xd6, 0xdd, 0xd8, 0x81, 0xba, 0x14, 0x46,
+ 0xd7, 0xc7, 0x15, 0x17, 0x4e, 0xba, 0x5c, 0x79, 0xad, 0x65, 0x48, 0x64,
+ 0x91, 0xae, 0xdd, 0xeb, 0xc0, 0x02, 0xd8, 0x52, 0xa0, 0x01, 0x08, 0x21,
+ 0x78, 0xc0, 0x9a, 0xa1, 0x26, 0x24, 0x41, 0xae, 0x72, 0xa9, 0xe9, 0x0a,
+ 0x21, 0x6a, 0xa8, 0x8d, 0x36, 0xa7, 0x72, 0x37, 0x9c, 0x56, 0x2a, 0xb8,
+ 0x55, 0x08, 0x1c, 0x88, 0xbb, 0x1d, 0x30, 0x1b, 0x88, 0x6a, 0x46, 0x1c,
+ 0x2c, 0x9a, 0x99, 0x7d, 0x54, 0x21, 0x74, 0x15, 0x27, 0x4f, 0x4b, 0x9a,
+ 0x06, 0x13, 0x6c, 0x4c, 0x80, 0x54, 0x11, 0x5c, 0xa0, 0x81, 0x6b, 0x26,
+ 0x08, 0x9d, 0xc5, 0x1a, 0x14, 0x47, 0xfb, 0x2c, 0xb9, 0xbe, 0xba, 0xf6,
+ 0x63, 0x80, 0x11, 0x8e, 0xd9, 0x81, 0x09, 0xd1, 0xed, 0x2c, 0x9a, 0xc0,
+ 0xd8, 0x8d, 0x26, 0x71, 0x20, 0x41, 0xda, 0x89, 0xe7, 0xba, 0x7a, 0xb6,
+ 0xc6, 0x41, 0x06, 0x12, 0x28, 0x40, 0xc0, 0xd2, 0x7c, 0xd4, 0x40, 0x81,
+ 0xd3, 0x1c, 0x70, 0xa0, 0x1a, 0x08, 0x34, 0x28, 0xff, 0x3b, 0x1a, 0xb9,
+ 0x9e, 0x16, 0x2c, 0x60, 0x99, 0x17, 0x47, 0xc8, 0xa1, 0x68, 0x14, 0x46,
+ 0x68, 0x73, 0x79, 0x13, 0xb2, 0xd9, 0x81, 0xc4, 0xca, 0x51, 0xdc, 0xc1,
+ 0xe1, 0xad, 0x3d, 0xe9, 0x80, 0xdc, 0xc3, 0xc0, 0x84, 0x45, 0x04, 0x77,
+ 0x67, 0x90, 0x37, 0x69, 0x20, 0x40, 0xce, 0x5e, 0xcf, 0xe4, 0x0a, 0x2b,
+ 0x24, 0x91, 0xbe, 0x8a, 0xfe, 0x60, 0x6a, 0xe0, 0x5e, 0x28, 0x30, 0x23,
+ 0xee, 0x32, 0xab, 0xdc, 0x1a, 0x14, 0x8a, 0x9b, 0xa6, 0x92, 0xd1, 0x19,
+ 0x2d, 0x1a, 0x07, 0xf7, 0x36, 0x90, 0x00, 0x01, 0x38, 0xc0, 0x94, 0x46,
+ 0x0d, 0x11, 0x48, 0x50, 0x01, 0x06, 0x9f, 0x8f, 0x06, 0xc3, 0xbc, 0xd2,
+ 0xb5, 0x51, 0xde, 0xc9, 0x01, 0x1a, 0x01, 0xec, 0xa9, 0xa4, 0x89, 0x9e,
+ 0x9a, 0xd7, 0xa2, 0xc9, 0x1e, 0xa4, 0x09, 0x0d, 0x47, 0x87, 0xa7, 0x83,
+ 0xf1, 0xb2, 0xdd, 0x65, 0xc6, 0x17, 0x3c, 0x90, 0x40, 0x00, 0x31, 0x4c,
+ 0x31, 0x10, 0x16, 0x31, 0x14, 0x7f, 0xfc, 0x06, 0x79, 0xe7, 0x3d, 0xc2,
+ 0xcb, 0x61, 0x57, 0xf1, 0xec, 0xa3, 0x44, 0x92, 0x40, 0x6e, 0xd9, 0x66,
+ 0x47, 0x97, 0x1a, 0xe5, 0x8f, 0xbb, 0xce, 0x68, 0x1a, 0xd7, 0x3c, 0x5c,
+ 0xb5, 0x6e, 0x34, 0x82, 0xc3, 0xd8, 0x6a, 0x78, 0x77, 0x81, 0x08, 0x28,
+ 0xe0, 0x00, 0x01, 0xa8, 0x41, 0x7d, 0x04, 0xc2, 0x3e, 0xf7, 0x61, 0x00,
+ 0x03, 0x19, 0x80, 0x5f, 0xfc, 0x68, 0x80, 0x04, 0x2a, 0x50, 0x01, 0x09,
+ 0x34, 0x88, 0x9f, 0xfc, 0x68, 0x40, 0xc2, 0x12, 0x9a, 0x90, 0x06, 0x30,
+ 0x18, 0x81, 0x09, 0x47, 0x20, 0x42, 0x0e, 0xa8, 0xb0, 0x84, 0x23, 0x78,
+ 0x21, 0x09, 0x59, 0x38, 0xc2, 0x12, 0xc2, 0xa0, 0x85, 0x34, 0xf0, 0x20,
+ 0x15, 0x8a, 0x70, 0x43, 0x11, 0x96, 0xc0, 0x84, 0x22, 0x94, 0x21, 0x0d,
+ 0xb7, 0x68, 0x18, 0xbf, 0x0d, 0x6c, 0x00, 0x03, 0x16, 0x78, 0xc0, 0x03,
+ 0xd1, 0x67, 0x05, 0x83, 0x54, 0xd0, 0x01, 0x2c, 0xa9, 0x40, 0x05, 0x2e,
+ 0x70, 0x81, 0x0c, 0x58, 0xf1, 0x8a, 0x58, 0xcc, 0xa2, 0x16, 0xb7, 0xc8,
+ 0xc5, 0x2e, 0x7a, 0xf1, 0x8b, 0x60, 0x0c, 0xa3, 0x15, 0x31, 0x70, 0x81,
+ 0x0a, 0x3c, 0xe0, 0x72, 0x07, 0x10, 0x40, 0x30, 0xd4, 0x77, 0x10, 0xf6,
+ 0x0d, 0x23, 0x18, 0x0d, 0x70, 0xc0, 0x03, 0x1e, 0x10, 0x81, 0x3a, 0xda,
+ 0xf1, 0x8e, 0x78, 0xcc, 0xa3, 0x1e, 0xf7, 0xc8, 0xc7, 0x3e, 0xfa, 0xf1,
+ 0x8f, 0x80, 0xb4, 0xe3, 0x03, 0x16, 0xa0, 0x80, 0x04, 0x1c, 0x20, 0x8d,
+ 0xc2, 0xc0, 0x81, 0x42, 0xd2, 0xe0, 0xc6, 0x60, 0x1c, 0xc0, 0x90, 0x09,
+ 0x50, 0x80, 0x24, 0x27, 0x49, 0xc9, 0x4a, 0x5a, 0xf2, 0x92, 0x98, 0xcc,
+ 0xa4, 0x26, 0x37, 0xc9, 0xc9, 0x4e, 0x4a, 0xd2, 0x90, 0x06, 0x20, 0x80,
+ 0x30, 0x6a, 0x50, 0x85, 0x86, 0x30, 0xb2, 0x7d, 0x02, 0x48, 0xa5, 0x00,
+ 0x02, 0x10, 0x80, 0x01, 0xb0, 0xf2, 0x95, 0xb0, 0x8c, 0xa5, 0x2c, 0x67,
+ 0x49, 0xcb, 0x5a, 0xda, 0xf2, 0x96, 0xb8, 0xbc, 0x25, 0x01, 0x58, 0x39,
+ 0x8c, 0x18, 0x58, 0x01, 0x26, 0x10, 0x09, 0xa6, 0x30, 0x87, 0x49, 0xcc,
+ 0x62, 0x3a, 0x24, 0x20, 0x00, 0x3b
+};
+unsigned int search_len = 2010;
+
+
+void writeLogo(const char *dir)
+{
+ QString fileName=(QString)dir+"/doxygen.gif";
+ QFile f(fileName);
+ if (f.open(IO_WriteOnly))
+ f.writeBlock((char *)logo_data,logo_len);
+ else
+ {
+ fprintf(stderr,"Warning: Cannot open file %s for writing\n",fileName.data());
+ }
+ f.close();
+}
+
+void writeSearchButton(const char *dir)
+{
+ QString fileName=(QString)dir+"/search.gif";
+ QFile f(fileName);
+ if (f.open(IO_WriteOnly))
+ f.writeBlock((char *)search_data,search_len);
+ else
+ {
+ fprintf(stderr,"Warning: Cannot open file %s for writing\n",fileName.data());
+ }
+ f.close();
+}
+
+
diff --git a/src/logos.h b/src/logos.h
new file mode 100644
index 0000000..1054fdb
--- /dev/null
+++ b/src/logos.h
@@ -0,0 +1,23 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#ifndef LOGOS_H
+#define LOGOS_H
+
+extern void writeLogo(const char *dir);
+extern void writeSearchButton(const char *dir);
+
+#endif
diff --git a/src/mangen.cpp b/src/mangen.cpp
new file mode 100644
index 0000000..55bf8c7
--- /dev/null
+++ b/src/mangen.cpp
@@ -0,0 +1,341 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#include <qdir.h>
+#include <stdlib.h>
+#include "message.h"
+#include "mangen.h"
+#include "config.h"
+#include "util.h"
+#include "doxygen.h"
+
+ManGenerator::ManGenerator() : OutputGenerator()
+{
+ dir=manOutputDir+"/man3";
+ firstCol=TRUE;
+ paragraph=FALSE;
+ col=0;
+ upperCase=FALSE;
+}
+
+ManGenerator::~ManGenerator()
+{
+}
+
+void ManGenerator::append(const OutputGenerator *g)
+{
+ QString r=g->getContents();
+ if (upperCase)
+ t << r.upper();
+ else
+ t << r;
+ if (r.length()>0)
+ firstCol = r.at(r.length()-1)=='\n';
+ else
+ firstCol = ((ManGenerator *)g)->firstCol;
+ col+=((ManGenerator *)g)->col;
+ paragraph=FALSE;
+}
+
+void ManGenerator::init()
+{
+ QDir d(manOutputDir);
+ if (!d.exists() && !d.mkdir(manOutputDir))
+ {
+ err("Could not create output directory %s\n",manOutputDir.data());
+ exit(1);
+ }
+ d.setPath(manOutputDir+"/man3");
+ if (!d.exists() && !d.mkdir(manOutputDir+"/man3"))
+ {
+ err("Could not create output directory %s/man3\n",manOutputDir.data());
+ exit(1);
+ }
+}
+
+void ManGenerator::startFile(const char *name,const char *,bool)
+{
+ QString fileName=name;
+ if (fileName.left(6)=="class_")
+ {
+ fileName=fileName.right(fileName.length()-6);
+ }
+ int i;
+ if ((i=fileName.findRev('.'))!=-1)
+ {
+ fileName=fileName.left(i);
+ }
+ if (fileName.right(2)!=".3") fileName+=".3";
+ startPlainFile(fileName);
+ firstCol=TRUE;
+}
+
+void ManGenerator::endFile()
+{
+ endPlainFile();
+}
+
+void ManGenerator::writeDoxyAnchor(const char *, const char *,const char *)
+{
+}
+
+void ManGenerator::endTitleHead(const char *name)
+{
+ t << ".TH " << name << " 3 \"" << dateToString(FALSE) << "\" \"";
+ if (projectName.isEmpty())
+ t << "Doxygen";
+ else
+ t << projectName;
+ t << "\" \\\" -*- nroff -*-" << endl;
+ t << ".ad l" << endl;
+ t << ".nh" << endl;
+ t << ".SH NAME" << endl;
+ t << name << " \\- ";
+ firstCol=FALSE;
+}
+
+void ManGenerator::newParagraph()
+{
+ if (!paragraph)
+ {
+ if (!firstCol) t << endl;
+ t << ".PP" << endl;
+ firstCol=TRUE;
+ }
+ paragraph=TRUE;
+}
+
+void ManGenerator::writeString(const char *text)
+{
+ docify(text);
+}
+
+void ManGenerator::writeIndexItem(const char *,const char *,
+ const char *)
+{
+}
+
+void ManGenerator::writeStartAnnoItem(const char *,const char *,
+ const char *,const char *)
+{
+}
+
+void ManGenerator::writeObjectLink(const char *,const char *,
+ const char *, const char *name)
+{
+ startBold(); docify(name); endBold();
+}
+
+void ManGenerator::writeCodeLink(const char *,const char *,
+ const char *, const char *name)
+{
+ docify(name);
+}
+
+void ManGenerator::writeHtmlLink(const char *,const char *text)
+{
+ docify(text);
+}
+
+void ManGenerator::startGroupHeader()
+{
+ if (!firstCol) t << endl;
+ t << ".SH ";
+ upperCase=TRUE;
+ firstCol=FALSE;
+}
+
+void ManGenerator::endGroupHeader()
+{
+ t << "\n.PP " << endl;
+ firstCol=TRUE;
+ paragraph=TRUE;
+ upperCase=FALSE;
+}
+
+void ManGenerator::startMemberHeader()
+{
+ if (!firstCol) t << endl;
+ t << ".SS ";
+}
+
+void ManGenerator::endMemberHeader()
+{
+ t << "\n";
+ firstCol=TRUE;
+ paragraph=FALSE;
+}
+
+void ManGenerator::docify(const char *str)
+{
+ if (str)
+ {
+ const char *p=str;
+ char c=0;
+ while ((c=*p++))
+ {
+ switch(c)
+ {
+ case '\\': t << "\\\\"; col++; break;
+ case '\n': t << "\n"; col=0; break;
+ default: t << c; col++; break;
+ }
+ }
+ firstCol=(c=='\n');
+ //printf("%s",str);fflush(stdout);
+ }
+ paragraph=FALSE;
+}
+
+void ManGenerator::codify(const char *str)
+{
+ static char spaces[]=" ";
+ if (str)
+ {
+ const char *p=str;
+ char c;
+ while (*p)
+ {
+ c=*p++;
+ switch(c)
+ {
+ case '\t': t << &spaces[col&7]; col+=8-(col&7); break;
+ case '\n': t << "\n.br\n"; firstCol=TRUE; col=0; break;
+ case '\\': t << "\\\\"; col++; break;
+ default: t << c; firstCol=FALSE; col++; break;
+ }
+ }
+ //printf("%s",str);fflush(stdout);
+ }
+ paragraph=FALSE;
+}
+
+void ManGenerator::writeChar(char c)
+{
+ firstCol=(c=='\n');
+ if (firstCol) col=0; else col++;
+ switch (c)
+ {
+ case '\\': t << "\\\\"; break;
+ default: t << c; break;
+ }
+ //printf("%c",c);fflush(stdout);
+ paragraph=FALSE;
+}
+
+void ManGenerator::startDescList()
+{
+ if (!firstCol)
+ { t << endl << ".PP" << endl;
+ firstCol=TRUE; paragraph=TRUE;
+ col=0;
+ }
+ paragraph=FALSE;
+}
+
+void ManGenerator::startTitle()
+{
+ if (!firstCol) t << endl;
+ t << ".SH ";
+ firstCol=FALSE;
+ paragraph=FALSE;
+}
+
+void ManGenerator::writeListItem()
+{
+ if (!firstCol) t << endl;
+ t << ".TP" << endl;
+ firstCol=TRUE;
+ paragraph=FALSE;
+ col=0;
+}
+
+void ManGenerator::startCodeFragment()
+{
+ newParagraph();
+ t << ".nf";
+ firstCol=FALSE;
+ paragraph=FALSE;
+}
+
+void ManGenerator::endCodeFragment()
+{
+ if (!firstCol) t << endl;
+ t << ".fi" << endl;
+ firstCol=TRUE;
+ paragraph=FALSE;
+ col=0;
+}
+
+void ManGenerator::startMemberDoc(const char *,const char *,const char *)
+{
+ if (!firstCol) t << endl;
+ t << ".SS ";
+ firstCol=FALSE;
+ paragraph=FALSE;
+}
+
+void ManGenerator::startSubsection()
+{
+ if (!firstCol) t << endl;
+ t << ".SS ";
+ firstCol=FALSE;
+ paragraph=FALSE;
+}
+
+void ManGenerator::startSubsubsection()
+{
+ if (!firstCol) t << endl;
+ t << "\n.SS ";
+ firstCol=FALSE;
+ paragraph=FALSE;
+}
+
+void ManGenerator::writeSynopsis()
+{
+ if (!firstCol) t << endl;
+ t << ".SH SYNOPSIS\n.br\n.PP\n";
+ firstCol=TRUE;
+ paragraph=FALSE;
+}
+
+void ManGenerator::startDescItem()
+{
+ if (!firstCol) t << endl;
+ t << ".IP \"";
+ firstCol=FALSE;
+}
+
+void ManGenerator::endDescTitle()
+{
+ paragraph=TRUE;
+}
+
+void ManGenerator::writeDescItem()
+{
+ if (!firstCol) t << endl;
+ if (!paragraph) t << ".in -1c" << endl;
+ t << ".in +1c" << endl;
+ firstCol=TRUE;
+ paragraph=FALSE;
+ col=0;
+}
+
+void ManGenerator::endDescItem()
+{
+ t << "\" 1c" << endl;
+ firstCol=TRUE;
+}
diff --git a/src/mangen.h b/src/mangen.h
new file mode 100644
index 0000000..d091782
--- /dev/null
+++ b/src/mangen.h
@@ -0,0 +1,171 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#ifndef MANGEN_H
+#define MANGEN_H
+
+#include "outputgen.h"
+
+class QFile;
+
+class ManGenerator : public OutputGenerator
+{
+ public:
+ ManGenerator();
+ ~ManGenerator();
+
+ OutputGenerator *copy() { return new ManGenerator; }
+ //OutputGenerator *clone() { return new ManGenerator(*this); }
+ void append(const OutputGenerator *o);
+ void enable() { active=TRUE; }
+ void disable() { active=FALSE; }
+ void enableIf(OutputType o) { if (o==Man) active=TRUE; }
+ void disableIf(OutputType o) { if (o==Man) active=FALSE; }
+ void disableIfNot(OutputType o) { if (o!=Man) active=FALSE; }
+ bool isEnabled(OutputType o) { return (o==Man && active); }
+ OutputGenerator *get(OutputType o) { return (o==Man) ? this : 0; }
+
+ static void init();
+ void startFile(const char *name,const char *title,bool external);
+ void writeFooter(int,bool) {}
+ void endFile();
+ void clearBuffer();
+
+ //void writeIndex();
+ void startIndexSection(IndexSections) {}
+ void endIndexSection(IndexSections) {}
+ void startProjectNumber() {}
+ void endProjectNumber() {}
+ void writeStyleInfo(int) {}
+ void startTitleHead() {}
+ void endTitleHead(const char *);
+ void startTitle();
+ void endTitle() {}
+
+ void newParagraph();
+ void writeString(const char *text);
+ void startIndexList() {}
+ void endIndexList() {}
+ void startItemList() {}
+ void endItemList() {}
+ void startEnumList() {}
+ void endEnumList() {}
+ void writeIndexItem(const char *ref,const char *file,const char *name);
+ void docify(const char *text);
+ void codify(const char *text);
+ void writeObjectLink(const char *ref,const char *file,
+ const char *anchor,const char *name);
+ void writeCodeLink(const char *ref,const char *f,
+ const char *anchor,const char *name);
+ void startTextLink(const char *,const char *) {}
+ void endTextLink() {}
+ void writeHtmlLink(const char *url,const char *text);
+ void startTypewriter() { t << "\\fC"; firstCol=FALSE; }
+ void endTypewriter() { t << "\\fR"; firstCol=FALSE; }
+ void startGroupHeader();
+ void endGroupHeader();
+ void startMemberHeader();
+ void endMemberHeader();
+ void writeListItem();
+ void startMemberList() { t << "\n.in +1c"; firstCol=FALSE; }
+ void endMemberList() { t << "\n.in -1c"; firstCol=FALSE; }
+ void startMemberItem() { if (firstCol) t << ".in +1c";
+ t << "\n.ti -1c\n.RI \"";
+ firstCol=FALSE;
+ }
+ void endMemberItem() { t << "\"\n.br"; }
+ void writeRuler() {}
+ void writeAnchor(const char *) {}
+ void startCodeFragment();
+ void endCodeFragment();
+ void writeBoldString(const char *text)
+ { t << "\\fB"; docify(text); t << "\\fR"; firstCol=FALSE; }
+ void startEmphasis() { t << "\\fI"; firstCol=FALSE; }
+ void endEmphasis() { t << "\\fR"; firstCol=FALSE; }
+ void startBold() { t << "\\fB"; firstCol=FALSE; }
+ void endBold() { t << "\\fR"; firstCol=FALSE; }
+ void startDescription() {}
+ void endDescription() {}
+ void startDescItem();
+ void endDescItem();
+ void lineBreak() { t << "\n.br" << endl; }
+ void writeChar(char c);
+ void startMemberDoc(const char *,const char *,const char *);
+ void endMemberDoc() {}
+ void writeDoxyAnchor(const char *clName,const char *anchor,const char *name);
+ void writeLatexSpacing() {}
+ void writeStartAnnoItem(const char *type,const char *file,
+ const char *path,const char *name);
+ void writeEndAnnoItem(const char *) { t << endl; firstCol=TRUE; }
+ void startSubsection();
+ void endSubsection() {}
+ void startSubsubsection();
+ void endSubsubsection() {}
+ void startCenter() {}
+ void endCenter() {}
+ void startSmall() {}
+ void endSmall() {}
+ void startSubscript() { t << "\\*<"; firstCol=FALSE; }
+ void endSubscript() { t << "\\*>"; firstCol=FALSE; }
+ void startSuperscript() { t << "\\*{"; firstCol=FALSE; }
+ void endSuperscript() { t << "\\*}"; firstCol=FALSE; }
+ void startTable(int) {}
+ void endTable() {}
+ void nextTableRow() {}
+ void endTableRow() {}
+ void nextTableColumn() {}
+ void endTableColumn() {}
+ void writeCopyright() { t << "(c)"; firstCol=FALSE; }
+ void writeQuote() { t << "\""; firstCol=FALSE; }
+ void writeUmlaut(char c) { t << c << "\\*'"; firstCol=FALSE; }
+ void writeAcute(char c) { t << c << "\\*`"; firstCol=FALSE; }
+ void writeGrave(char c) { t << c << "\\*:"; firstCol=FALSE; }
+ void writeCirc(char c) { t << c << "\\*^"; firstCol=FALSE; }
+ void writeTilde(char c) { t << c << "\\*~"; firstCol=FALSE; }
+ void startMemberDescription() { t << "\n.RI \"\\fI"; firstCol=FALSE; }
+ void endMemberDescription() { t << "\\fR\""; firstCol=FALSE; }
+ void startDescList();
+ void endDescTitle();
+ void writeDescItem();
+ void endDescList() {}
+ void writeSection(const char *,const char *,bool) {}
+ void writeSectionRef(const char *,const char *,const char *) {}
+ void writeSectionRefItem(const char *,const char *,const char *) {}
+ void addToIndex(const char *,const char *) {}
+ void startIndent() {}
+ void endIndent() {}
+ void writeSynopsis();
+ //void generateExternalIndex() {}
+ void startClassDiagram() {}
+ void endClassDiagram(ClassDiagram &,const char *,const char *) {}
+ void startColorFont(uchar,uchar,uchar) {}
+ void endColorFont() {}
+ void writePageRef(const char *,const char *) {}
+ void startQuickIndexItem(const char *,const char *) {}
+ void endQuickIndexItem() {}
+ void writeFormula(const char *,const char *) {}
+
+ private:
+ bool firstCol;
+ bool paragraph;
+ int col;
+ bool upperCase;
+
+ ManGenerator(const ManGenerator &g);
+ ManGenerator &operator=(const ManGenerator &g);
+};
+
+#endif
diff --git a/src/memberdef.cpp b/src/memberdef.cpp
new file mode 100644
index 0000000..f96a2d6
--- /dev/null
+++ b/src/memberdef.cpp
@@ -0,0 +1,180 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#include <stdio.h>
+#include <qregexp.h>
+#include "memberdef.h"
+#include "membername.h"
+#include "doxygen.h"
+#include "util.h"
+
+/*! Creates a new member definition.
+ * Members can be function/variables/enums/etc. inside a class or inside a
+ * file.
+ *
+ * \param t A string representing the type of the member.
+ * \param n A string representing the name of the member.
+ * \param a A string representing the arguments of the member.
+ * \param p The type of protection of the member, possible values are:
+ * \c Public, \c Protected, \c Private.
+ * \param v The `virtualness' of the member, possible values are:
+ * \c Normal, \c Virtual, \c Pure.
+ * \param s A boolean that is true if the member is static.
+ * \param r A boolean that is true if the member is only related.
+ * \param mt The kind of member. See #MemberDef::MemberType for a list of
+ * all types.
+ */
+
+MemberDef::MemberDef(const char *t,const char *na,const char *a,const char *e,
+ Protection p,Specifier v,bool s,bool r,MemberType mt,
+ const ArgumentList *tal,const ArgumentList *al
+ ) : Definition(substituteClassNames(na))
+{
+ //printf("++++++ MemberDef(%s,%s,%s) ++++++ \n",t,na,a);
+ classDef=0;
+ fileDef=0;
+ fileDec=0;
+ redefines=0;
+ redefinedBy=0;
+ nspace=0;
+ memDef=0;
+ memDec=0;
+ exampleList=0;
+ exampleDict=0;
+ enumFields=0;
+ enumScope=0;
+ enumDeclList=0;
+ type=substituteClassNames(t);
+ args=substituteClassNames(a);
+ if (type.isNull()) decl=name()+args; else decl=type+" "+name()+args;
+ declLine=0;
+ defLine=0;
+ virt=v;
+ prot=p;
+ related=r;
+ stat=s;
+ mtype=mt;
+ exception=e;
+ eUsed=FALSE;
+ proto=FALSE;
+ docEnumValues=FALSE;
+ // copy function template arguments (if any)
+ if (tal)
+ {
+ tArgList = new ArgumentList;
+ tArgList->setAutoDelete(TRUE);
+ ArgumentListIterator ali(*tal);
+ Argument *a;
+ for (;(a=ali.current());++ali)
+ {
+ tArgList->append(new Argument(*a));
+ }
+ }
+ else
+ {
+ tArgList=0;
+ }
+ // copy function arguments (if any)
+ if (al)
+ {
+ argList = new ArgumentList;
+ argList->setAutoDelete(TRUE);
+ ArgumentListIterator ali(*al);
+ Argument *a;
+ for (;(a=ali.current());++ali)
+ {
+ argList->append(new Argument(*a));
+ }
+ argList->constSpecifier = al->constSpecifier;
+ argList->volatileSpecifier = al->volatileSpecifier;
+ argList->pureSpecifier = al->pureSpecifier;
+ }
+ else
+ {
+ argList=0;
+ }
+
+}
+
+MemberDef::~MemberDef()
+{
+ delete redefinedBy;
+ delete exampleList;
+ delete exampleDict;
+ delete enumFields;
+ delete argList;
+ delete tArgList;
+}
+
+void MemberDef::insertReimplementedBy(MemberDef *md)
+{
+ if (redefinedBy==0) redefinedBy = new MemberList;
+ redefinedBy->inSort(md);
+}
+
+void MemberDef::insertEnumField(MemberDef *md)
+{
+ if (enumFields==0) enumFields=new MemberList;
+ enumFields->append(md);
+}
+
+bool MemberDef::addExample(const char *anchor,const char *nameStr,
+ const char *file)
+{
+ //printf("%s::addExample(%s,%s,%s)\n",name.data(),anchor,nameStr,file);
+ if (exampleDict==0) exampleDict = new ExampleDict;
+ if (exampleList==0) exampleList = new ExampleList;
+ if (exampleDict->find(nameStr)==0)
+ {
+ //printf("Add reference to example %s to member %s\n",nameStr,name.data());
+ Example *e=new Example;
+ e->anchor=anchor;
+ e->name=nameStr;
+ e->file=file;
+ exampleDict->insert(nameStr,e);
+ exampleList->inSort(e);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+bool MemberDef::hasExamples()
+{
+ if (exampleList==0)
+ return FALSE;
+ else
+ return exampleList->count()>0;
+}
+
+
+void MemberDef::writeExample(OutputList &ol)
+{
+ Example *e=exampleList->first();
+ while (e)
+ {
+ ol.writeObjectLink(0,e->file,e->anchor,e->name);
+ e=exampleList->next();
+ if (e)
+ {
+ if (exampleList->at()==(int)exampleList->count()-1)
+ ol.writeString(" and ");
+ else
+ ol.writeString(", ");
+ }
+ }
+ ol.writeString(".");
+}
+
diff --git a/src/memberdef.h b/src/memberdef.h
new file mode 100644
index 0000000..fba76f8
--- /dev/null
+++ b/src/memberdef.h
@@ -0,0 +1,186 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#ifndef MEMBERDEF_H
+#define MEMBERDEF_H
+
+#include <qstring.h>
+#include <qlist.h>
+#include <qdict.h>
+
+#include "entry.h"
+#include "example.h"
+#include "config.h"
+#include "outputlist.h"
+#include "definition.h"
+#include "config.h"
+
+class FileDef;
+class MemberList;
+class NamespaceDef;
+
+class MemberDef : public Definition
+{
+ public:
+
+ enum MemberType {
+ Define,
+ Function,
+ Variable,
+ Typedef,
+ Enumeration,
+ EnumValue,
+ Prototype,
+ Signal,
+ Slot,
+ Friend
+ };
+
+ MemberDef(const char *type,const char *name,const char *args,
+ const char *excp,Protection prot,Specifier virt,bool stat,
+ bool related,MemberType t,const ArgumentList *tal,
+ const ArgumentList *al);
+ ~MemberDef();
+
+ const char *declaration() const { return decl; }
+ const char *definition() const { return def; }
+ const char *typeString() const { return type; }
+ const char *argsString() const { return args; }
+ const char *excpString() const { return exception; }
+ const char *anchor() const { return ref; }
+ ClassDef *memberClass() { return classDef; }
+ Protection protection() const { return prot; }
+ Specifier virtualness() const { return virt; }
+ MemberType memberType() const { return mtype; }
+ void setMemberType(MemberType t) { mtype=t; }
+ void setDefinition(const char *d) { def=d; }
+ void setDefFile(const char *f) { defFile=f; }
+ void setDefLine(int l) { defLine=l; }
+ void setFileDef(FileDef *fd) { fileDef=fd; }
+ void setFileDec(FileDef *fd) { fileDec=fd; }
+ void setAnchor(const char *a) { ref=a; }
+ FileDef *getFileDef() { return fileDef; }
+ FileDef *getFileDec() { return fileDec; }
+ void setMemberClass(ClassDef *cd) { classDef=cd; }
+ bool isRelated() const { return related; }
+ bool isStatic() const { return stat; }
+ bool detailsAreVisible() const
+ { return !documentation().isEmpty() ||
+ (mtype==Enumeration && docEnumValues) ||
+ (mtype==EnumValue && !briefDescription().isEmpty()) ||
+ (!briefDescription().isEmpty() &&
+ !briefMemDescFlag && repeatBriefFlag);
+ }
+
+ // relation to other members
+ void setReimplements(MemberDef *md) { redefines=md; }
+ void insertReimplementedBy(MemberDef *md);
+ MemberDef *reimplements() { return redefines; }
+ MemberList *reimplementedBy() { return redefinedBy; }
+
+ // enumeration specific members
+ void insertEnumField(MemberDef *md);
+ void setEnumScope(MemberDef *md) { enumScope=md; }
+ MemberDef *getEnumScope() const { return enumScope; }
+ void setEnumDecl(OutputList &ed) { enumDeclList=new OutputList(&ed); }
+ void setEnumUsed() { eUsed=TRUE; }
+ bool enumUsed() const { return eUsed; }
+ OutputList *enumDecl() const { return enumDeclList; }
+ MemberList *enumFieldList() { return enumFields; }
+ void setDocumentedEnumValues(bool value) { docEnumValues=value; }
+ bool hasDocumentedEnumValues() const { return docEnumValues; }
+
+ // example related members
+ bool addExample(const char *anchor,const char *name,const char *file);
+ void writeExample(OutputList &ol);
+ bool hasExamples();
+
+ // prototype related members
+ const char *getDefFile() { return defFile; }
+ int getDefLine() { return defLine; }
+ void setDecFile(const char *f) { declFile=f; }
+ void setDecLine(int l) { defLine=l; }
+
+ // convenience members
+ bool isSignal() const { return mtype==Signal; }
+ bool isSlot() const { return mtype==Slot; }
+ bool isVariable() const { return mtype==Variable; }
+ bool isEnumerate() const { return mtype==Enumeration; }
+ bool isEnumValue() const { return mtype==EnumValue; }
+ bool isTypedef() const { return mtype==Typedef; }
+ bool isFunction() const { return mtype==Function; }
+ bool isDefine() const { return mtype==Define; }
+ bool isFriend() const { return mtype==Friend; }
+
+ // prototype related members
+ void setPrototype(bool p) { proto=p; }
+ bool isPrototype() const { return proto; }
+
+ // tag file related members
+ void setReference(const char *r) { external=r; }
+ bool isReference() { return !external.isNull(); }
+
+ // argument related members
+ ArgumentList *argumentList() const { return argList; }
+ ArgumentList *templateArguments() const { return tArgList; }
+
+ // namespace related members
+ NamespaceDef *getNamespace() { return nspace; }
+ void setNamespace(NamespaceDef *nd) { nspace=nd; }
+
+ private:
+ ClassDef *classDef; // member of or related to
+ FileDef *fileDef; // member of file definition
+ FileDef *fileDec; // member of file declaration
+ MemberDef *redefines; // the member that is redefined by this one
+ MemberDef *enumScope; // the enclosing scope, if this is an enum field
+ MemberList *redefinedBy; // the list of members that redefine this one
+ MemberDef *memDef; // member definition for this declaration
+ MemberDef *memDec; // member declaration for this definition
+ ExampleList *exampleList; // a list of all examples using this member
+ ExampleDict *exampleDict; // a dictionary of all examples for quick access
+ MemberList *enumFields; // enumeration fields
+ OutputList *enumDeclList; // stored piece of documentation for enumeration.
+ NamespaceDef *nspace; // the namespace this member is in.
+ QString type; // return type
+ QString args; // function arguments/variable array specifiers
+ QString exception; // exceptions that can be thrown
+ QString decl; // member declaration in class
+ QString declFile; // file where the declaration was found
+ int declLine; // line where the declaration was found
+ QString def; // member definition in code (fully qualified name)
+ QString defFile; // file where the definition was found
+ int defLine; // line where the definition was found
+ QString ref; // HTML anchor name
+ Specifier virt; // normal/virtual/pure virtual
+ Protection prot; // protection type [Public/Protected/Private]
+ bool related; // is this a member that is only related to a class
+ QString external; // anchor of a member if extracted from a tag file
+ bool stat; // is it a static function?
+ MemberType mtype; // returns the kind of member
+ bool eUsed; // is the enumerate already placed in a list
+ bool proto; // is it a prototype;
+ bool docEnumValues; // is an enum with documented enum values.
+ ArgumentList *argList; // argument list of this member
+ ArgumentList *tArgList; // template argument list of function template
+
+ // disable copying of member defs
+ MemberDef(const MemberDef &);
+ MemberDef &operator=(const MemberDef &);
+};
+
+
+#endif
diff --git a/src/memberlist.cpp b/src/memberlist.cpp
new file mode 100644
index 0000000..4d7cc73
--- /dev/null
+++ b/src/memberlist.cpp
@@ -0,0 +1,148 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#include "memberlist.h"
+#include "classdef.h"
+#include "message.h"
+#include <qregexp.h>
+
+MemberList::MemberList() : QList<MemberDef>()
+{
+}
+
+MemberList::~MemberList()
+{
+}
+
+int MemberList::compareItems(GCI item1, GCI item2)
+{
+ MemberDef *c1=(MemberDef *)item1;
+ MemberDef *c2=(MemberDef *)item2;
+ return strcmp(c1->name(),c2->name());
+}
+
+void MemberList::countDecMembers()
+{
+ varCnt=funcCnt=enumCnt=enumValCnt=typeCnt=protoCnt=defCnt=friendCnt=0;
+ MemberDef *md=first();
+ while (md)
+ {
+ if ((!hideMemberFlag || md->hasDocumentation()) &&
+ (!hideMemberFlag || !md->documentation().isEmpty() ||
+ briefMemDescFlag || repeatBriefFlag
+ ) || extractAllFlag
+ )
+ {
+ switch(md->memberType())
+ {
+ case MemberDef::Variable: varCnt++; break;
+ case MemberDef::Function: // fall through
+ case MemberDef::Signal: // fall through
+ case MemberDef::Slot: funcCnt++; break;
+ case MemberDef::Enumeration: enumCnt++; break;
+ case MemberDef::EnumValue: enumValCnt++; break;
+ case MemberDef::Typedef: typeCnt++; break;
+ case MemberDef::Prototype: protoCnt++; break;
+ case MemberDef::Define: if (extractAllFlag || md->argsString() || md->hasDocumentation() )
+ defCnt++;
+ break;
+ case MemberDef::Friend: friendCnt++; break;
+ default:
+ err("Error: Unknown member type found!");
+ }
+ }
+ md=next();
+ }
+}
+
+void MemberList::countDocMembers()
+{
+ varCnt=funcCnt=enumCnt=enumValCnt=typeCnt=protoCnt=defCnt=friendCnt;
+ MemberDef *md=first();
+ while (md)
+ {
+ //if (extractAllFlag || /*md->hasDocumentation()*/
+ // !md->documentation().isEmpty() ||
+ // (!md->briefDescription().isEmpty() &&
+ // !briefMemDescFlag &&
+ // repeatBriefFlag
+ // )
+ // )
+ if (extractAllFlag || md->detailsAreVisible())
+ {
+ QRegExp r("@[0-9]+");
+ int dummy;
+ switch(md->memberType())
+ {
+ case MemberDef::Variable:
+ varCnt++;
+ break;
+ case MemberDef::Function:
+ case MemberDef::Signal:
+ case MemberDef::Slot:
+ funcCnt++;
+ break;
+ case MemberDef::Enumeration:
+ if (r.match(md->name(),0,&dummy)==-1)
+ {
+ enumCnt++;
+ }
+ break;
+ case MemberDef::EnumValue:
+ {
+ MemberDef *scope;
+ scope=md->getEnumScope();
+ if (scope && r.match(scope->name(),0,&dummy)!=-1)
+ enumValCnt++;
+ }
+ break;
+ case MemberDef::Typedef:
+ typeCnt++;
+ break;
+ case MemberDef::Prototype:
+ protoCnt++;
+ break;
+ case MemberDef::Define:
+ defCnt++;
+ break;
+ case MemberDef::Friend:
+ friendCnt++;
+ }
+ }
+ md=next();
+ }
+}
+
+bool MemberList::insert(uint index,const MemberDef *md)
+{
+ return QList<MemberDef>::insert(index,md);
+}
+
+void MemberList::inSort(const MemberDef *md)
+{
+ QList<MemberDef>::inSort(md);
+}
+
+void MemberList::append(const MemberDef *md)
+{
+ QList<MemberDef>::append(md);
+}
+
+MemberListIterator::MemberListIterator(const QList<MemberDef> &l) :
+ QListIterator<MemberDef>(l)
+{
+}
+
diff --git a/src/memberlist.h b/src/memberlist.h
new file mode 100644
index 0000000..c26f055
--- /dev/null
+++ b/src/memberlist.h
@@ -0,0 +1,56 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#ifndef MEMBERLIST_H
+#define MEMBERLIST_H
+
+#include <qlist.h>
+#include "memberdef.h"
+
+class MemberList : public QList<MemberDef>
+{
+ public:
+ MemberList();
+ ~MemberList();
+ bool insert(uint index,const MemberDef *md);
+ void inSort(const MemberDef *md);
+ void append(const MemberDef *md);
+ int compareItems(GCI item1,GCI item2);
+ int varCount() const { return varCnt; }
+ int funcCount() const { return funcCnt; }
+ int enumCount() const { return enumCnt; }
+ int enumValueCount() const { return enumValCnt; }
+ int typedefCount() const { return typeCnt; }
+ int protoCount() const { return protoCnt; }
+ int defineCount() const { return defCnt; }
+ int friendCount() const { return friendCnt; }
+ void countDecMembers();
+ void countDocMembers();
+ int totalCount() const
+ { return varCnt+funcCnt+enumCnt+enumValCnt+typeCnt+
+ protoCnt+defCnt+friendCnt; }
+
+ private:
+ int varCnt,funcCnt,enumCnt,enumValCnt,typeCnt,protoCnt,defCnt,friendCnt;
+};
+
+class MemberListIterator : public QListIterator<MemberDef>
+{
+ public:
+ MemberListIterator(const QList<MemberDef> &list);
+};
+
+#endif
diff --git a/src/membername.cpp b/src/membername.cpp
new file mode 100644
index 0000000..2605f86
--- /dev/null
+++ b/src/membername.cpp
@@ -0,0 +1,96 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#include "membername.h"
+#include "classdef.h"
+#include "util.h"
+#include "filedef.h"
+
+MemberName::MemberName(const char *n) : QList<MemberDef>()
+{
+ name=n;
+}
+
+MemberName::~MemberName()
+{
+}
+
+int MemberName::compareItems(GCI item1, GCI item2)
+{
+ MemberDef *m1=(MemberDef *)item1;
+ MemberDef *m2=(MemberDef *)item2;
+ ClassDef *c1=m1->memberClass();
+ ClassDef *c2=m2->memberClass();
+ FileDef *f1=m1->getFileDef();
+ FileDef *f2=m2->getFileDef();
+ if (c1 && c2)
+ return stricmp(c1->name(),c2->name());
+ else if (f1 && f2)
+ return stricmp(f1->name(),f2->name());
+ else
+ return 0;
+}
+
+MemberNameInfo::MemberNameInfo(const char *n) : QList<MemberInfo>()
+{
+ name=n;
+ setAutoDelete(TRUE);
+}
+
+MemberNameInfo::~MemberNameInfo()
+{
+}
+
+int MemberNameInfo::compareItems(GCI item1, GCI item2)
+{
+ MemberInfo *m1=(MemberInfo *)item1;
+ MemberInfo *m2=(MemberInfo *)item2;
+ ClassDef *c1=m1->memberDef->memberClass();
+ ClassDef *c2=m2->memberDef->memberClass();
+ FileDef *f1=m1->memberDef->getFileDef();
+ FileDef *f2=m2->memberDef->getFileDef();
+ if (c1 && c2)
+ return stricmp(c1->name(),c2->name());
+ else if (f1 && f2)
+ return stricmp(f1->name(),f2->name());
+ else
+ return 0;
+}
+MemberNameIterator::MemberNameIterator(const MemberName &mnlist) :
+ QListIterator<MemberDef>(mnlist)
+{
+}
+
+MemberNameList::MemberNameList() : QList<MemberName>()
+{
+}
+
+MemberNameList::~MemberNameList()
+{
+}
+
+int MemberNameList::compareItems(GCI item1, GCI item2)
+{
+ MemberName *n1=(MemberName *)item1;
+ MemberName *n2=(MemberName *)item2;
+ return stricmp(n1->memberName(),n2->memberName());
+}
+
+MemberNameListIterator::MemberNameListIterator(const MemberNameList &mnlist) :
+ QListIterator<MemberName>(mnlist)
+{
+}
+
diff --git a/src/membername.h b/src/membername.h
new file mode 100644
index 0000000..4754fa7
--- /dev/null
+++ b/src/membername.h
@@ -0,0 +1,111 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#ifndef MEMBERNAME_H
+#define MEMBERNAME_H
+
+#include <qlist.h>
+#include "memberdef.h"
+
+class MemberName : public QList<MemberDef>
+{
+ public:
+ MemberName(const char *name);
+ ~MemberName();
+ const char *memberName() const { return name; }
+
+ int compareItems(GCI item1,GCI item2);
+ private:
+ QString name;
+};
+
+class MemberNameIterator : public QListIterator<MemberDef>
+{
+ public:
+ MemberNameIterator( const MemberName &list);
+};
+
+class MemberNameList : public QList<MemberName>
+{
+ public:
+ MemberNameList();
+ ~MemberNameList();
+
+ int compareItems(GCI item1,GCI item2);
+};
+
+class MemberNameListIterator : public QListIterator<MemberName>
+{
+ public:
+ MemberNameListIterator( const MemberNameList &list );
+};
+
+typedef QDict<MemberName> MemberNameDict;
+
+struct MemberInfo
+{
+ MemberInfo(MemberDef *md,Protection p,Specifier v) :
+ memberDef(md), prot(p), virt(v) {}
+ MemberDef *memberDef;
+ Protection prot;
+ Specifier virt;
+ QString scopePath;
+ QString ambiguityResolutionScope;
+};
+
+class MemberNameInfo : public QList<MemberInfo>
+{
+ public:
+ MemberNameInfo(const char *name);
+ ~MemberNameInfo();
+ const char *memberName() const { return name; }
+ int compareItems(GCI item1,GCI item2);
+ private:
+ QString name;
+};
+
+class MemberNameInfoIterator : public QListIterator<MemberInfo>
+{
+ public:
+ MemberNameInfoIterator(const MemberNameInfo &mnii)
+ : QListIterator<MemberInfo>(mnii) {}
+};
+
+class MemberNameInfoList : public QList<MemberNameInfo>
+{
+ public:
+ int compareItems(GCI item1,GCI item2)
+ { return stricmp(
+ ((MemberNameInfo *)item1)->memberName(),
+ ((MemberNameInfo *)item2)->memberName()
+ );
+ }
+};
+
+class MemberNameInfoDict : public QDict<MemberNameInfo>
+{
+ public:
+ MemberNameInfoDict(int size) : QDict<MemberNameInfo>(size) {}
+};
+
+class MemberNameInfoListIterator : public QListIterator<MemberNameInfo>
+{
+ public:
+ MemberNameInfoListIterator(const MemberNameInfoList &mil) :
+ QListIterator<MemberNameInfo>(mil) {}
+};
+
+#endif
diff --git a/src/message.cpp b/src/message.cpp
new file mode 100644
index 0000000..9f98107
--- /dev/null
+++ b/src/message.cpp
@@ -0,0 +1,49 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#include <stdarg.h>
+#include <stdio.h>
+#include "config.h"
+
+void msg(const char *fmt, ...)
+{
+ if (!quietFlag)
+ {
+ va_list args;
+ va_start(args, fmt);
+ vfprintf(stdout, fmt, args);
+ va_end(args);
+ }
+}
+
+void warn(const char *fmt, ...)
+{
+ if (warningFlag)
+ {
+ va_list args;
+ va_start(args, fmt);
+ vfprintf(stderr, fmt, args);
+ va_end(args);
+ }
+}
+
+void err(const char *fmt, ...)
+{
+ va_list args;
+ va_start(args, fmt);
+ vfprintf(stderr, fmt, args);
+ va_end(args);
+}
diff --git a/src/message.h b/src/message.h
new file mode 100644
index 0000000..f7586ca
--- /dev/null
+++ b/src/message.h
@@ -0,0 +1,24 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#ifndef MESSAGE_H
+#define MESSAGE_H
+
+extern void msg(const char *fmt, ...);
+extern void warn(const char *fmt, ...);
+extern void err(const char *fmt, ...);
+
+#endif
diff --git a/src/namespacedef.cpp b/src/namespacedef.cpp
new file mode 100644
index 0000000..9d055b2
--- /dev/null
+++ b/src/namespacedef.cpp
@@ -0,0 +1,220 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#include "namespacedef.h"
+#include "outputlist.h"
+#include "util.h"
+#include "scanner.h"
+#include "language.h"
+#include "classdef.h"
+#include "classlist.h"
+#include "memberlist.h"
+
+NamespaceDef::NamespaceDef(const char *name) : Definition(name)
+{
+ fileName="namespace_"+nameToFile(name);
+ classList = new ClassList;
+ memList = new MemberList;
+}
+
+NamespaceDef::~NamespaceDef()
+{
+ delete classList;
+ delete memList;
+}
+
+void NamespaceDef::insertUsedFile(const char *f)
+{
+ if (files.find(f)==-1) files.append(f);
+}
+
+void NamespaceDef::insertClass(ClassDef *cd)
+{
+ classList->append(cd);
+}
+
+void NamespaceDef::insertMember(MemberDef *md)
+{
+ memList->append(md);
+}
+
+void NamespaceDef::computeAnchors()
+{
+ setAnchors('a',memList);
+}
+
+void NamespaceDef::writeDocumentation(OutputList &ol)
+{
+ QString pageTitle=name()+" Namespace Reference";
+ startFile(ol,fileName,pageTitle);
+ startTitle(ol);
+ ol.docify(pageTitle);
+ endTitle(ol,name());
+
+ OutputList briefOutput(&ol);
+ if (briefDescription())
+ {
+ parseDoc(briefOutput,0,0,briefDescription());
+ ol+=briefOutput;
+ ol.writeString(" \n");
+ ol.disableAllBut(OutputGenerator::Html);
+ ol.startTextLink(0,"details");
+ parseDoc(ol,0,0,theTranslator->trMore());
+ ol.endTextLink();
+ ol.enableAll();
+ }
+ ol.disable(OutputGenerator::Man);
+ ol.newParagraph();
+ ol.enable(OutputGenerator::Man);
+ ol.writeSynopsis();
+
+ if (classList->count()>0)
+ {
+ ClassDef *cd=classList->first();
+ bool found=FALSE;
+ while (cd)
+ {
+ if (cd->isVisibleExt())
+ {
+ if (!found)
+ {
+ ol.startMemberHeader();
+ parseDoc(ol,0,0,theTranslator->trCompounds());
+ ol.endMemberHeader();
+ ol.startMemberList();
+ found=TRUE;
+ }
+ QString clName=cd->name().copy();
+ if (clName.left(name().length()+2)==name()+"::")
+ {
+ clName = clName.right(clName.length()-name().length()-2);
+ }
+
+ ol.startMemberItem();
+ switch (cd->compoundType())
+ {
+ case ClassDef::Class: ol.writeString("class"); break;
+ case ClassDef::Struct: ol.writeString("struct"); break;
+ case ClassDef::Union: ol.writeString("union"); break;
+ }
+ ol.writeString(" ");
+ if (cd->hasDocumentation())
+ {
+ ol.writeObjectLink(cd->getReference(),
+ cd->classFile(),
+ 0,
+ clName
+ );
+ }
+ else
+ {
+ ol.startBold();
+ ol.docify(clName);
+ ol.endBold();
+ }
+ ol.endMemberItem();
+ }
+ cd=classList->next();
+ }
+ if (found) ol.endMemberList();
+ }
+
+ writeMemberDecs(ol,0,this,0,0,0,memList);
+
+ if (!briefDescription().isEmpty() || !documentation().isEmpty())
+ {
+ ol.writeRuler();
+ ol.writeAnchor("details");
+ ol.startGroupHeader();
+ parseDoc(ol,0,0,theTranslator->trDetailedDescription());
+ ol.endGroupHeader();
+ if (!briefDescription().isEmpty())
+ {
+ ol+=briefOutput;
+ ol.newParagraph();
+ }
+ if (!documentation().isEmpty())
+ {
+ parseDoc(ol,0,0,documentation()+"\n");
+ ol.newParagraph();
+ }
+ }
+
+ memList->countDocMembers();
+
+ if ( memList->protoCount()>0 )
+ {
+ ol.writeRuler();
+ ol.startGroupHeader();
+ parseDoc(ol,0,0,theTranslator->trFunctionPrototypeDocumentation());
+ ol.endGroupHeader();
+ writeMemberDocs(ol,memList,name(),MemberDef::Prototype);
+ }
+
+ if ( memList->typedefCount()>0 )
+ {
+ ol.writeRuler();
+ ol.startGroupHeader();
+ parseDoc(ol,0,0,theTranslator->trTypedefDocumentation());
+ ol.endGroupHeader();
+ writeMemberDocs(ol,memList,name(),MemberDef::Typedef);
+ }
+
+ if ( memList->enumCount()>0 )
+ {
+ ol.writeRuler();
+ ol.startGroupHeader();
+ parseDoc(ol,0,0,theTranslator->trEnumerationTypeDocumentation());
+ ol.endGroupHeader();
+ writeMemberDocs(ol,memList,name(),MemberDef::Enumeration);
+ }
+
+ if ( memList->enumValueCount()>0 )
+ {
+ ol.writeRuler();
+ ol.startGroupHeader();
+ parseDoc(ol,0,0,theTranslator->trEnumerationValueDocumentation());
+ ol.endGroupHeader();
+ writeMemberDocs(ol,memList,name(),MemberDef::EnumValue);
+ }
+
+ if ( memList->funcCount()>0 )
+ {
+ ol.writeRuler();
+ ol.startGroupHeader();
+ parseDoc(ol,0,0,theTranslator->trFunctionDocumentation());
+ ol.endGroupHeader();
+ writeMemberDocs(ol,memList,name(),MemberDef::Function);
+ }
+
+ if ( memList->varCount()>0 )
+ {
+ ol.writeRuler();
+ ol.startGroupHeader();
+ parseDoc(ol,0,0,theTranslator->trVariableDocumentation());
+ ol.endGroupHeader();
+ writeMemberDocs(ol,memList,name(),MemberDef::Variable);
+ }
+
+ // write Author section (Man only)
+ ol.disableAllBut(OutputGenerator::Man);
+ ol.startGroupHeader();
+ parseDoc(ol,0,0,theTranslator->trAuthor());
+ ol.endGroupHeader();
+ parseDoc(ol,0,0,theTranslator->trGeneratedAutomatically(projectName));
+ ol.enableAll();
+ endFile(ol);
+}
diff --git a/src/namespacedef.h b/src/namespacedef.h
new file mode 100644
index 0000000..9da6b2c
--- /dev/null
+++ b/src/namespacedef.h
@@ -0,0 +1,70 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#ifndef NAMESPACEDEF_H
+#define NAMESPACEDEF_H
+
+#include <qstring.h>
+#include <qstrlist.h>
+#include <qdict.h>
+#include "definition.h"
+
+class ClassDef;
+class OutputList;
+class ClassList;
+class MemberList;
+class MemberDef;
+
+class NamespaceDef : public Definition
+{
+ public:
+ NamespaceDef(const char *name);
+ ~NamespaceDef();
+ QString namespaceFile() const { return fileName; }
+ void insertUsedFile(const char *fname);
+ void writeDocumentation(OutputList &ol);
+ void insertClass(ClassDef *cd);
+ void insertMember(MemberDef *md);
+ void computeAnchors();
+
+ private:
+ QString fileName;
+ QStrList files;
+ ClassList *classList;
+ MemberList *memList;
+};
+
+class NamespaceList : public QList<NamespaceDef>
+{
+ public:
+ int compareItems(GCI item1,GCI item2)
+ {
+ return strcmp(((NamespaceDef *)item1)->name(),
+ ((NamespaceDef *)item2)->name()
+ );
+ }
+};
+
+class NamespaceListIterator : public QListIterator<NamespaceDef>
+{
+ public:
+ NamespaceListIterator(const NamespaceList &l) :
+ QListIterator<NamespaceDef>(l) {}
+};
+
+typedef QDict<NamespaceDef> NamespaceDict;
+
+#endif
diff --git a/src/outputgen.cpp b/src/outputgen.cpp
new file mode 100644
index 0000000..ca07302
--- /dev/null
+++ b/src/outputgen.cpp
@@ -0,0 +1,77 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#include <stdlib.h>
+#include "outputgen.h"
+#include <qstring.h>
+#include "message.h"
+
+OutputGenerator::OutputGenerator()
+{
+ //printf("OutputGenerator::OutputGenerator()\n");
+ file=0;
+ b.setBuffer(a);
+ b.open( IO_WriteOnly );
+ t.setDevice(&b);
+ active=TRUE;
+}
+
+OutputGenerator::~OutputGenerator()
+{
+ //printf("OutputGenerator::~OutputGenerator()\n");
+ delete file;
+}
+
+void OutputGenerator::startPlainFile(const char *name)
+{
+ //printf("startPlainFile(%s)\n",name);
+ QString fileName=dir+"/"+name;
+ file = new QFile(fileName);
+ if (!file)
+ {
+ err("Could not create file object for %s\n",fileName.data());
+ exit(1);
+ }
+ if (!file->open(IO_WriteOnly))
+ {
+ err("Could not open file %s for writing\n",fileName.data());
+ exit(1);
+ }
+ fs.setDevice(file);
+}
+
+void OutputGenerator::endPlainFile()
+{
+ //printf("endPlainFile(%s)\n",file->name());
+ fs.writeRawBytes(a.data(),a.size()) ; // write string buffer to file
+ delete file;
+ file=0;
+ b.close();
+ a.resize(0);
+ b.setBuffer(a);
+ b.open(IO_WriteOnly);
+ t.setDevice(&b);
+}
+
+QString OutputGenerator::getContents() const
+{
+ QString s;
+ s.resize(a.size()+1);
+ memcpy(s.data(),a.data(),a.size());
+ s.at(a.size())='\0';
+ return s;
+}
+
diff --git a/src/outputgen.h b/src/outputgen.h
new file mode 100644
index 0000000..457dd80
--- /dev/null
+++ b/src/outputgen.h
@@ -0,0 +1,182 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#ifndef OUTPUTGEN_H
+#define OUTPUTGEN_H
+
+#include <qstring.h>
+#include <qtstream.h>
+#include <qbuffer.h>
+#include <qfile.h>
+#include "index.h"
+
+class ClassDiagram;
+
+class OutputGenerator
+{
+ public:
+ enum OutputType { Html, Latex, Man };
+
+ OutputGenerator();
+ virtual ~OutputGenerator();
+
+ virtual OutputGenerator *copy() = 0;
+ //virtual OutputGenerator *clone() = 0;
+ virtual void append(const OutputGenerator *) = 0;
+ virtual void enable() = 0;
+ virtual void disable() = 0;
+ virtual void enableIf(OutputType o) = 0;
+ virtual void disableIf(OutputType o) = 0;
+ virtual void disableIfNot(OutputType o) = 0;
+ virtual bool isEnabled(OutputType o) = 0;
+ virtual OutputGenerator *get(OutputType o) = 0;
+
+ virtual void startFile(const char *name,const char *title,bool ext) = 0;
+ virtual void writeFooter(int,bool) = 0;
+ virtual void endFile() = 0;
+ //virtual void writeIndex() = 0;
+ virtual void startIndexSection(IndexSections) = 0;
+ virtual void endIndexSection(IndexSections) = 0;
+ virtual void startProjectNumber() = 0;
+ virtual void endProjectNumber() = 0;
+ virtual void writeStyleInfo(int part) = 0;
+ virtual void startTitleHead() = 0;
+ virtual void endTitleHead(const char *name) = 0;
+ virtual void startTitle() = 0;
+ virtual void endTitle() = 0;
+ virtual void newParagraph() = 0;
+ virtual void writeString(const char *text) = 0;
+ virtual void startIndexList() = 0;
+ virtual void endIndexList() = 0;
+ virtual void startItemList() = 0;
+ virtual void endItemList() = 0;
+ virtual void startEnumList() = 0;
+ virtual void endEnumList() = 0;
+ virtual void startBold() = 0;
+ virtual void endBold() = 0;
+ virtual void writeIndexItem(const char *ref,const char *file,
+ const char *text) = 0;
+ virtual void docify(const char *s) = 0;
+ virtual void codify(const char *s) = 0;
+ virtual void writeObjectLink(const char *ref,const char *file,
+ const char *anchor, const char *text) = 0;
+ virtual void writeCodeLink(const char *ref,const char *file,
+ const char *anchor,const char *text) = 0;
+ virtual void startTextLink(const char *file,const char *anchor) = 0;
+ virtual void endTextLink() = 0;
+ virtual void writeHtmlLink(const char *url,const char *text) = 0;
+ virtual void startTypewriter() = 0;
+ virtual void endTypewriter() = 0;
+ virtual void startGroupHeader() = 0;
+ virtual void endGroupHeader() = 0;
+ virtual void writeListItem() = 0;
+
+ virtual void startMemberHeader() = 0;
+ virtual void endMemberHeader() = 0;
+ virtual void startMemberList() = 0;
+ virtual void endMemberList() = 0;
+ virtual void startMemberItem() = 0;
+ virtual void endMemberItem() = 0;
+
+ virtual void writeRuler() = 0;
+ virtual void writeAnchor(const char *name) = 0;
+ virtual void startCodeFragment() = 0;
+ virtual void endCodeFragment() = 0;
+ virtual void writeBoldString(const char *text) = 0;
+ virtual void startEmphasis() = 0;
+ virtual void endEmphasis() = 0;
+ virtual void writeChar(char c) = 0;
+ virtual void startMemberDoc(const char *,const char *,const char *) = 0;
+ virtual void endMemberDoc() = 0;
+ virtual void writeDoxyAnchor(const char *clName,const char *anchor,const char *name) = 0;
+ virtual void writeLatexSpacing() = 0;
+ virtual void writeStartAnnoItem(const char *type,const char *file,
+ const char *path,const char *name) = 0;
+ virtual void writeEndAnnoItem(const char *name) = 0;
+ virtual void startDescription() = 0;
+ virtual void endDescription() = 0;
+ virtual void startDescItem() = 0;
+ virtual void endDescItem() = 0;
+ virtual void startSubsection() = 0;
+ virtual void endSubsection() = 0;
+ virtual void startSubsubsection() = 0;
+ virtual void endSubsubsection() = 0;
+ virtual void startCenter() = 0;
+ virtual void endCenter() = 0;
+ virtual void startSmall() = 0;
+ virtual void endSmall() = 0;
+ virtual void startSubscript() = 0;
+ virtual void endSubscript() = 0;
+ virtual void startSuperscript() = 0;
+ virtual void endSuperscript() = 0;
+ virtual void startTable(int cols) = 0;
+ virtual void endTable() = 0;
+ virtual void nextTableRow() = 0;
+ virtual void endTableRow() = 0;
+ virtual void nextTableColumn() = 0;
+ virtual void endTableColumn() = 0;
+ virtual void writeQuote() = 0;
+ virtual void writeCopyright() = 0;
+ virtual void writeUmlaut(char) = 0;
+ virtual void writeAcute(char) = 0;
+ virtual void writeGrave(char) = 0;
+ virtual void writeCirc(char) = 0;
+ virtual void writeTilde(char) = 0;
+ virtual void startMemberDescription() = 0;
+ virtual void endMemberDescription() = 0;
+ virtual void startDescList() = 0;
+ virtual void endDescTitle() = 0;
+ virtual void writeDescItem() = 0;
+ virtual void endDescList() = 0;
+ virtual void writeSection(const char *,const char *,bool) = 0;
+ virtual void writeSectionRef(const char *,const char *,const char *) = 0;
+ virtual void writeSectionRefItem(const char *,const char *,const char *) = 0;
+ virtual void lineBreak() = 0;
+ virtual void addToIndex(const char *s1,const char *s2) = 0;
+ virtual void startIndent() = 0;
+ virtual void endIndent() = 0;
+ virtual void writeSynopsis() = 0;
+ //virtual void generateExternalIndex() = 0;
+ virtual void startClassDiagram() = 0;
+ virtual void endClassDiagram(ClassDiagram &,const char *,const char *) = 0;
+ virtual void startColorFont(uchar r,uchar g,uchar b) = 0;
+ virtual void endColorFont() = 0;
+ virtual void writePageRef(const char *,const char *) = 0;
+ virtual void startQuickIndexItem(const char *s,const char *l) = 0;
+ virtual void endQuickIndexItem() = 0;
+ virtual void writeFormula(const char *,const char *) = 0;
+
+ void clear() { b.close(); a.resize(0); b.setBuffer(a);
+ b.open(IO_WriteOnly); t.setDevice(&b); }
+ void startPlainFile(const char *name);
+ void endPlainFile();
+ QString getContents() const;
+ bool isEnabled() const { return active; }
+ protected:
+ QTextStream fs;
+ QByteArray a;
+ QBuffer b;
+ QTextStream t;
+ QFile *file;
+ QString dir;
+ bool active;
+
+ private:
+ OutputGenerator(const OutputGenerator &o);
+ OutputGenerator &operator=(const OutputGenerator &o);
+};
+
+#endif
diff --git a/src/outputlist.cpp b/src/outputlist.cpp
new file mode 100644
index 0000000..daa83ed
--- /dev/null
+++ b/src/outputlist.cpp
@@ -0,0 +1,239 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+/*! \file
+ * This class represents a list of output generators that work in "parallel".
+ * The class only knows about the abstract base class OutputGenerators.
+ * All output is produced by calling a method of this class, which forwards
+ * the call to all output generators.
+ */
+
+#include "outputlist.h"
+#include "outputgen.h"
+#include "config.h"
+#include "message.h"
+
+OutputList::OutputList(bool)
+{
+ //printf("OutputList::OutputList()\n");
+ outputs = new QList<OutputGenerator>;
+ outputs->setAutoDelete(TRUE);
+}
+
+OutputList::OutputList(const OutputList *olist)
+{
+ //printf("OutputList::OutputList() deep copy\n");
+ outputs = new QList<OutputGenerator>;
+ outputs->setAutoDelete(TRUE);
+
+ QList<OutputGenerator> *ol=olist->outputs;
+ OutputGenerator *og=ol->first();
+ while (og)
+ {
+ OutputGenerator *ogc=og->copy();
+ outputs->append(ogc);
+ if (og->isEnabled()) ogc->enable(); else ogc->disable();
+ og=ol->next();
+ }
+ //printf("OutputList::OutputList dst=%d res=%d\n",ol->count(),outputs->count());
+}
+
+OutputList::~OutputList()
+{
+ delete outputs;
+}
+
+OutputList &OutputList::operator=(const OutputList &olist)
+{
+ if (this!=&olist)
+ {
+ QList<OutputGenerator> *ol=olist.outputs;
+ OutputGenerator *ogsrc=ol->first();
+ OutputGenerator *ogdst=outputs->first();
+ //printf("OutputList::operator= src=%d dst=%d\n",outputs->count(),ol->count());
+ while (ogdst)
+ {
+ ogdst=ogsrc->copy();
+ ogsrc=ol->next();
+ ogdst=outputs->next();
+ }
+ }
+ return *this;
+}
+
+void OutputList::add(const OutputGenerator *og)
+{
+ if (og) outputs->append(og);
+}
+
+//HtmlGenerator *OutputList::getHtmlGenerator()
+//{
+// OutputGenerator *og=outputs->first();
+// while (og)
+// {
+// if (og->get(OutputGenerator::Html)) return (HtmlGenerator *)og;
+// og=outputs->next();
+// }
+// return 0; // should not happen!
+//}
+
+void OutputList::disableAllBut(OutputGenerator::OutputType o)
+{
+ OutputGenerator *og=outputs->first();
+ while (og)
+ {
+ og->disableIfNot(o);
+ og=outputs->next();
+ }
+}
+
+void OutputList::enableAll()
+{
+ OutputGenerator *og=outputs->first();
+ while (og)
+ {
+ og->enable();
+ og=outputs->next();
+ }
+}
+
+void OutputList::disable(OutputGenerator::OutputType o)
+{
+ OutputGenerator *og=outputs->first();
+ while (og)
+ {
+ og->disableIf(o);
+ og=outputs->next();
+ }
+}
+
+void OutputList::enable(OutputGenerator::OutputType o)
+{
+ OutputGenerator *og=outputs->first();
+ while (og)
+ {
+ og->enableIf(o);
+ og=outputs->next();
+ }
+}
+
+bool OutputList::isEnabled(OutputGenerator::OutputType o)
+{
+ bool result=FALSE;
+ OutputGenerator *og=outputs->first();
+ while (og)
+ {
+ result=result || og->isEnabled(o);
+ og=outputs->next();
+ }
+ return result;
+}
+
+OutputList &OutputList::operator+=(const OutputList &outputList)
+{
+ OutputList *ol=(OutputList *)&outputList;
+ OutputGenerator *ogsrc=ol->outputs->first();
+ OutputGenerator *ogdst=outputs->first();
+ //printf("OutputList::operator+= src=%d dst=%d\n",outputs->count(),ol->outputs->count());
+ while (ogdst && ogsrc)
+ {
+ ogdst->append(ogsrc);
+ ogsrc=ol->outputs->next();
+ ogdst=outputs->next();
+ }
+ return *this;
+}
+
+//--------------------------------------------------------------------------
+// Create some overloaded definitions of the forall function.
+// Using template functions here would have made it a little less
+// portable (I guess).
+
+// zero arguments
+void OutputList::forall(void (OutputGenerator::*func)())
+{
+ OutputGenerator *og=outputs->first();
+ while (og)
+ {
+ if (og->isEnabled()) (og->*func)();
+ og=outputs->next();
+ }
+}
+
+// one argument
+#define FORALL1(a1,p1) \
+void OutputList::forall(void (OutputGenerator::*func)(a1),a1) \
+{ \
+ OutputGenerator *og=outputs->first(); \
+ while (og) \
+ { \
+ if (og->isEnabled()) (og->*func)(p1); \
+ og=outputs->next(); \
+ } \
+}
+
+// two arguments
+#define FORALL2(a1,a2,p1,p2) \
+void OutputList::forall(void (OutputGenerator::*func)(a1,a2),a1,a2) \
+{ \
+ OutputGenerator *og=outputs->first(); \
+ while (og) \
+ { \
+ if (og->isEnabled()) (og->*func)(p1,p2); \
+ og=outputs->next(); \
+ } \
+}
+
+// three arguments
+#define FORALL3(a1,a2,a3,p1,p2,p3) \
+void OutputList::forall(void (OutputGenerator::*func)(a1,a2,a3),a1,a2,a3) \
+{ \
+ OutputGenerator *og=outputs->first(); \
+ while (og) \
+ { \
+ if (og->isEnabled()) (og->*func)(p1,p2,p3); \
+ og=outputs->next(); \
+ } \
+}
+
+// four arguments
+#define FORALL4(a1,a2,a3,a4,p1,p2,p3,p4) \
+void OutputList::forall(void (OutputGenerator::*func)(a1,a2,a3,a4),a1,a2,a3,a4) \
+{ \
+ OutputGenerator *og=outputs->first(); \
+ while (og) \
+ { \
+ if (og->isEnabled()) (og->*func)(p1,p2,p3,p4); \
+ og=outputs->next(); \
+ } \
+}
+
+// now instantiate only the ones we need.
+
+FORALL1(const char *a1,a1)
+FORALL1(char a1,a1)
+FORALL1(int a1,a1)
+FORALL1(IndexSections a1,a1)
+FORALL2(const char *a1,const char *a2,a1,a2)
+FORALL2(int a1,bool a2,a1,a2)
+FORALL3(ClassDiagram &a1,const char *a2,const char *a3,a1,a2,a3)
+FORALL3(const char *a1,const char *a2,const char *a3,a1,a2,a3)
+FORALL3(const char *a1,const char *a2,bool a3,a1,a2,a3)
+FORALL3(uchar a1,uchar a2,uchar a3,a1,a2,a3)
+FORALL4(const char *a1,const char *a2,const char *a3,const char *a4,a1,a2,a3,a4)
+
+
+//--------------------------------------------------------------------------
diff --git a/src/outputlist.h b/src/outputlist.h
new file mode 100644
index 0000000..2c57dad
--- /dev/null
+++ b/src/outputlist.h
@@ -0,0 +1,298 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#ifndef OUTPUTLIST_H
+#define OUTPUTLIST_H
+
+#include <qlist.h>
+#include <qstring.h>
+#include "index.h" // for IndexSections
+#include "outputgen.h"
+
+#define FORALLPROTO1(arg1) \
+ void forall(void (OutputGenerator::*func)(arg1),arg1)
+#define FORALLPROTO2(arg1,arg2) \
+ void forall(void (OutputGenerator::*func)(arg1,arg2),arg1,arg2)
+#define FORALLPROTO3(arg1,arg2,arg3) \
+ void forall(void (OutputGenerator::*func)(arg1,arg2,arg3),arg1,arg2,arg3)
+#define FORALLPROTO4(arg1,arg2,arg3,arg4) \
+ void forall(void (OutputGenerator::*func)(arg1,arg2,arg3,arg4),arg1,arg2,arg3,arg4)
+
+class ClassDiagram;
+
+class OutputList
+{
+ public:
+ OutputList(bool);
+ ~OutputList();
+ OutputList(const OutputList *ol);
+ OutputList &operator=(const OutputList &ol);
+ OutputList &operator+=(const OutputList &ol);
+
+ void add(const OutputGenerator *);
+
+ void disableAllBut(OutputGenerator::OutputType o);
+ void enableAll();
+ void disable(OutputGenerator::OutputType o);
+ void enable(OutputGenerator::OutputType o);
+ bool isEnabled(OutputGenerator::OutputType o);
+
+ //void writeIndex()
+ //{ forall(&OutputGenerator::writeIndex); }
+ void startIndexSection(IndexSections is)
+ { forall(&OutputGenerator::startIndexSection,is); }
+ void endIndexSection(IndexSections is)
+ { forall(&OutputGenerator::endIndexSection,is); }
+ void startProjectNumber()
+ { forall(&OutputGenerator::startProjectNumber); }
+ void endProjectNumber()
+ { forall(&OutputGenerator::endProjectNumber); }
+ void writeStyleInfo(int part)
+ { forall(&OutputGenerator::writeStyleInfo,part); }
+ void startFile(const char *name,const char *title,bool external)
+ { forall(&OutputGenerator::startFile,name,title,external); }
+ void startPlainFile(const char *name)
+ { forall(&OutputGenerator::startPlainFile,name); }
+ void writeFooter(int fase,bool external)
+ { forall(&OutputGenerator::writeFooter,fase,external); }
+ void endFile()
+ { forall(&OutputGenerator::endFile); }
+ void endPlainFile()
+ { forall(&OutputGenerator::endPlainFile); }
+ void startTitleHead()
+ { forall(&OutputGenerator::startTitleHead); }
+ void endTitleHead(const char *name)
+ { forall(&OutputGenerator::endTitleHead,name); }
+ void startTitle()
+ { forall(&OutputGenerator::startTitle); }
+ void endTitle()
+ { forall(&OutputGenerator::endTitle); }
+ void newParagraph()
+ { forall(&OutputGenerator::newParagraph); }
+ void writeString(const char *text)
+ { forall(&OutputGenerator::writeString,text); }
+ void startIndexList()
+ { forall(&OutputGenerator::startIndexList); }
+ void endIndexList()
+ { forall(&OutputGenerator::endIndexList); }
+ void startItemList()
+ { forall(&OutputGenerator::startItemList); }
+ void endItemList()
+ { forall(&OutputGenerator::endItemList); }
+ void startEnumList()
+ { forall(&OutputGenerator::startEnumList); }
+ void endEnumList()
+ { forall(&OutputGenerator::endEnumList); }
+ void writeIndexItem(const char *ref,const char *file,const char *text)
+ { forall(&OutputGenerator::writeIndexItem,ref,file,text); }
+ void docify(const char *s)
+ { forall(&OutputGenerator::docify,s); }
+ void codify(const char *s)
+ { forall(&OutputGenerator::codify,s); }
+ void writeObjectLink(const char *ref,const char *file,
+ const char *anchor, const char *text)
+ { forall(&OutputGenerator::writeObjectLink,ref,file,anchor,text); }
+ void writeCodeLink(const char *ref,const char *file,
+ const char *anchor,const char *text)
+ { forall(&OutputGenerator::writeCodeLink,ref,file,anchor,text); }
+ void startTextLink(const char *file,const char *anchor)
+ { forall(&OutputGenerator::startTextLink,file,anchor); }
+ void endTextLink()
+ { forall(&OutputGenerator::endTextLink); }
+ void writeHtmlLink(const char *url,const char *text)
+ { forall(&OutputGenerator::writeHtmlLink,url,text); }
+ void writeStartAnnoItem(const char *type,const char *file,
+ const char *path,const char *name)
+ { forall(&OutputGenerator::writeStartAnnoItem,type,file,path,name); }
+ void writeEndAnnoItem(const char *name)
+ { forall(&OutputGenerator::writeEndAnnoItem,name); }
+ void startTypewriter()
+ { forall(&OutputGenerator::startTypewriter); }
+ void endTypewriter()
+ { forall(&OutputGenerator::endTypewriter); }
+ void startGroupHeader()
+ { forall(&OutputGenerator::startGroupHeader); }
+ void endGroupHeader()
+ { forall(&OutputGenerator::endGroupHeader); }
+ void writeListItem()
+ { forall(&OutputGenerator::writeListItem); }
+ void startMemberHeader()
+ { forall(&OutputGenerator::startMemberHeader); }
+ void endMemberHeader()
+ { forall(&OutputGenerator::endMemberHeader); }
+ void startMemberList()
+ { forall(&OutputGenerator::startMemberList); }
+ void endMemberList()
+ { forall(&OutputGenerator::endMemberList); }
+ void startMemberItem()
+ { forall(&OutputGenerator::startMemberItem); }
+ void endMemberItem()
+ { forall(&OutputGenerator::endMemberItem); }
+ void writeRuler()
+ { forall(&OutputGenerator::writeRuler); }
+ void writeAnchor(const char *name)
+ { forall(&OutputGenerator::writeAnchor,name); }
+ void startCodeFragment()
+ { forall(&OutputGenerator::startCodeFragment); }
+ void endCodeFragment()
+ { forall(&OutputGenerator::endCodeFragment); }
+ void writeBoldString(const char *text)
+ { forall(&OutputGenerator::writeBoldString,text); }
+ void startEmphasis()
+ { forall(&OutputGenerator::startEmphasis); }
+ void endEmphasis()
+ { forall(&OutputGenerator::endEmphasis); }
+ void writeChar(char c)
+ { forall(&OutputGenerator::writeChar,c); }
+ void startMemberDoc(const char *clName,const char *memName,const char *anchor)
+ { forall(&OutputGenerator::startMemberDoc,clName,memName,anchor); }
+ void endMemberDoc()
+ { forall(&OutputGenerator::endMemberDoc); }
+ void writeDoxyAnchor(const char *clName,const char *anchor,const char *name)
+ { forall(&OutputGenerator::writeDoxyAnchor,clName,anchor,name); }
+ void writeLatexSpacing()
+ { forall(&OutputGenerator::writeLatexSpacing); }
+ void startDescription()
+ { forall(&OutputGenerator::startDescription); }
+ void endDescription()
+ { forall(&OutputGenerator::endDescription); }
+ void startDescItem()
+ { forall(&OutputGenerator::startDescItem); }
+ void endDescItem()
+ { forall(&OutputGenerator::endDescItem); }
+ void startSubsection()
+ { forall(&OutputGenerator::startSubsection); }
+ void endSubsection()
+ { forall(&OutputGenerator::endSubsection); }
+ void startSubsubsection()
+ { forall(&OutputGenerator::startSubsubsection); }
+ void endSubsubsection()
+ { forall(&OutputGenerator::endSubsubsection); }
+ void startCenter()
+ { forall(&OutputGenerator::startCenter); }
+ void endCenter()
+ { forall(&OutputGenerator::endCenter); }
+ void startSmall()
+ { forall(&OutputGenerator::startSmall); }
+ void endSmall()
+ { forall(&OutputGenerator::endSmall); }
+ void startSubscript()
+ { forall(&OutputGenerator::startSubscript); }
+ void endSubscript()
+ { forall(&OutputGenerator::endSubscript); }
+ void startSuperscript()
+ { forall(&OutputGenerator::startSuperscript); }
+ void endSuperscript()
+ { forall(&OutputGenerator::endSuperscript); }
+ void startTable(int cols)
+ { forall(&OutputGenerator::startTable,cols); }
+ void endTable()
+ { forall(&OutputGenerator::endTable); }
+ void nextTableRow()
+ { forall(&OutputGenerator::nextTableRow); }
+ void endTableRow()
+ { forall(&OutputGenerator::endTableRow); }
+ void nextTableColumn()
+ { forall(&OutputGenerator::nextTableColumn); }
+ void endTableColumn()
+ { forall(&OutputGenerator::endTableColumn); }
+ void lineBreak()
+ { forall(&OutputGenerator::lineBreak); }
+ void startBold()
+ { forall(&OutputGenerator::startBold); }
+ void endBold()
+ { forall(&OutputGenerator::endBold); }
+ void writeCopyright()
+ { forall(&OutputGenerator::writeCopyright); }
+ void writeQuote()
+ { forall(&OutputGenerator::writeQuote); }
+ void writeUmlaut(char c)
+ { forall(&OutputGenerator::writeUmlaut,c); }
+ void writeAcute(char c)
+ { forall(&OutputGenerator::writeAcute,c); }
+ void writeGrave(char c)
+ { forall(&OutputGenerator::writeGrave,c); }
+ void writeCirc(char c)
+ { forall(&OutputGenerator::writeCirc,c); }
+ void writeTilde(char c)
+ { forall(&OutputGenerator::writeTilde,c); }
+ void startMemberDescription()
+ { forall(&OutputGenerator::startMemberDescription); }
+ void endMemberDescription()
+ { forall(&OutputGenerator::endMemberDescription); }
+ void startDescList()
+ { forall(&OutputGenerator::startDescList); }
+ void endDescTitle()
+ { forall(&OutputGenerator::endDescTitle); }
+ void writeDescItem()
+ { forall(&OutputGenerator::writeDescItem); }
+ void endDescList()
+ { forall(&OutputGenerator::endDescList); }
+ void startIndent()
+ { forall(&OutputGenerator::startIndent); }
+ void endIndent()
+ { forall(&OutputGenerator::endIndent); }
+ void writeSection(const char *lab,const char *title,bool sub)
+ { forall(&OutputGenerator::writeSection,lab,title,sub); }
+ void writeSectionRef(const char *page,const char *lab, const char *title)
+ { forall(&OutputGenerator::writeSectionRef,page,lab,title); }
+ void writeSectionRefItem(const char *page,const char *lab, const char *title)
+ { forall(&OutputGenerator::writeSectionRefItem,page,lab,title); }
+ void addToIndex(const char *s1,const char *s2)
+ { forall(&OutputGenerator::addToIndex,s1,s2); }
+ void writeSynopsis()
+ { forall(&OutputGenerator::writeSynopsis); }
+ //void generateExternalIndex()
+ //{ forall(&OutputGenerator::generateExternalIndex); }
+ void startClassDiagram()
+ { forall(&OutputGenerator::startClassDiagram); }
+ void endClassDiagram(ClassDiagram &d,const char *f,const char *n)
+ { forall(&OutputGenerator::endClassDiagram,d,f,n); }
+ void startColorFont(uchar r,uchar g,uchar b)
+ { forall(&OutputGenerator::startColorFont,r,g,b); }
+ void endColorFont()
+ { forall(&OutputGenerator::endColorFont); }
+ void writePageRef(const char *c,const char *a)
+ { forall(&OutputGenerator::writePageRef,c,a); }
+ void startQuickIndexItem(const char *s,const char *l)
+ { forall(&OutputGenerator::startQuickIndexItem,s,l); }
+ void endQuickIndexItem()
+ { forall(&OutputGenerator::endQuickIndexItem); }
+ void writeFormula(const char *n,const char *t)
+ { forall(&OutputGenerator::writeFormula,n,t); }
+
+ private:
+ void debug();
+ void clear();
+
+ void forall(void (OutputGenerator::*func)());
+ FORALLPROTO1(const char *);
+ FORALLPROTO1(char);
+ FORALLPROTO1(int);
+ FORALLPROTO1(IndexSections);
+ FORALLPROTO2(const char *,const char *);
+ FORALLPROTO2(int,bool);
+ FORALLPROTO3(const char *,const char *,bool);
+ FORALLPROTO3(uchar,uchar,uchar);
+ FORALLPROTO3(const char *,const char *,const char *);
+ FORALLPROTO3(ClassDiagram &,const char *,const char *);
+ FORALLPROTO4(const char *,const char *,const char *,const char *);
+
+ OutputList(const OutputList &ol);
+ QList<OutputGenerator> *outputs;
+};
+
+#endif
diff --git a/src/pre.h b/src/pre.h
new file mode 100644
index 0000000..5028929
--- /dev/null
+++ b/src/pre.h
@@ -0,0 +1,41 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#ifndef PRE_H
+#define PRE_H
+
+#include <stdio.h>
+#include <qstring.h>
+#include <qfile.h>
+
+#if 0
+class Define
+{
+ public:
+ Define(const char *n) { name=n; }
+ ~Define();
+
+ private:
+ QString name;
+ QStrList args;
+};
+#endif
+
+void initPreprocessor();
+void addSearchDir(const char *dir);
+void preprocessFile(const char *fileName,BufStr &output);
+
+#endif
diff --git a/src/pre.l b/src/pre.l
new file mode 100644
index 0000000..92f7553
--- /dev/null
+++ b/src/pre.l
@@ -0,0 +1,1636 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+%{
+
+/*
+ * includes
+ */
+
+#include <stdio.h>
+#include <iostream.h>
+#include <assert.h>
+#include <ctype.h>
+
+#include <qarray.h>
+#include <qstring.h>
+#include <qstack.h>
+#include <qfile.h>
+#include <qstrlist.h>
+#include <qdict.h>
+#include <qregexp.h>
+
+#include "constexp.h"
+#include "define.h"
+#include "doxygen.h"
+#include "message.h"
+#include "util.h"
+
+#if defined(_MSC_VER)
+#define popen _popen
+#define pclose _pclose
+#endif
+
+#define YY_NEVER_INTERACTIVE 1
+
+#define DUMP_OUTPUT 0 // set this to one to see what the preprocessor
+ // produces.
+#define SHOW_INCLUDES 0 // set this to one to list all parsed include files
+
+struct FileState
+{
+ int lineNr;
+ FILE *filePtr;
+ YY_BUFFER_STATE bufState;
+ QString fileName;
+};
+
+/* -----------------------------------------------------------------
+ *
+ * statics
+ */
+
+static int yyLineNr = 1;
+static QString yyFileName;
+static int ifcount = 0;
+static QStrList *pathList = 0;
+static QStack<FileState> includeStack;
+static QDict<int> *argDict;
+static int defArgs = 0;
+static QString defName;
+static QString defText;
+static QString defArgsStr;
+static bool defVarArgs;
+static int level;
+static int lastCContext;
+static int lastCPPContext;
+static QArray<int> levelGuard;
+static QString guardExpr;
+static BufStr *outputBuf;
+//static DefineCache *fileDefineCache;
+static int roundCount;
+//static const Define *expandDefine;
+static bool quoteArg;
+static DefineDict *fileDefineDict;
+static DefineDict *expandedDict;
+static int findDefArgContext;
+
+
+static void incrLevel()
+{
+ level++;
+ levelGuard.resize(level);
+ levelGuard[level-1]=FALSE;
+ //printf("%s line %d: incrLevel %d\n",yyFileName.data(),yyLineNr,level);
+}
+
+static void decrLevel()
+{
+ //printf("%s line %d: decrLevel %d\n",yyFileName.data(),yyLineNr,level);
+ if (level > 0)
+ {
+ level--;
+ levelGuard.resize(level);
+ }
+ else
+ {
+ err("Error: More #endif's than #if's found.\n");
+ }
+}
+
+static bool otherCaseDone()
+{
+ return levelGuard[level-1];
+}
+
+static void setCaseDone(bool value)
+{
+ levelGuard[level-1]=value;
+}
+
+static Define *isDefined(const char *name)
+{
+ if (name)
+ {
+ Define *def;
+ //if ((def=fileDefineCache->findDefine(yyFileName,name)) && !def->undef)
+ // return def;
+ if ((def=fileDefineDict->find(name)) && !def->undef) return def;
+ }
+ return 0;
+}
+
+static FILE *findFile(const char *fileName)
+{
+ if (pathList==0)
+ {
+ return 0;
+ }
+ char *s=pathList->first();
+ while (s)
+ {
+ QString absName=(QString)s+"/"+fileName;
+ QFileInfo fi(absName);
+ if (fi.exists())
+ {
+ FILE *f;
+ if (!inputFilter.isEmpty())
+ {
+ QString cmd = inputFilter+" "+absName;
+ f=popen(cmd,"r");
+ if (!f) warn("Warning: could not execute filter %s\n",cmd.data());
+ }
+ else
+ {
+ f=fopen(absName,"r");
+ if (!f) warn("Warning: could not open file %s for reading\n",absName.data());
+ }
+ if (f)
+ {
+ yyFileName=absName;
+ yyLineNr=1;
+ return f;
+ }
+ }
+ s=pathList->next();
+ }
+ return 0;
+}
+
+
+static int getNextChar(const QString &expr,QString *rest,uint &pos);
+static int getCurrentChar(const QString &expr,QString *rest,uint pos);
+static void unputChar(const QString &expr,QString *rest,uint &pos,char c);
+static void expandExpression(QString &expr,QString *rest,int pos);
+
+static QString stringize(const QString &s)
+{
+ QString result;
+ uint i=0;
+ bool inString=FALSE;
+ bool inChar=FALSE;
+ char c,pc;
+ while (i<s.length())
+ {
+ if (!inString && !inChar)
+ {
+ while (i<s.length() && !inString && !inChar)
+ {
+ c=s.at(i++);
+ if (c=='"')
+ {
+ result+="\\\"";
+ inString=TRUE;
+ }
+ else if (c=='\'')
+ {
+ result+=c;
+ inChar=TRUE;
+ }
+ else
+ {
+ result+=c;
+ }
+ }
+ }
+ else if (inChar)
+ {
+ while (i<s.length() && inChar)
+ {
+ c=s.at(i++);
+ if (c=='\'')
+ {
+ result+='\'';
+ inChar=FALSE;
+ }
+ else if (c=='\\')
+ {
+ result+="\\\\";
+ }
+ else
+ {
+ result+=c;
+ }
+ }
+ }
+ else
+ {
+ pc=0;
+ while (i<s.length() && inString)
+ {
+ char c=s.at(i++);
+ if (c=='"')
+ {
+ result+="\\\"";
+ inString= pc=='\\';
+ }
+ else if (c=='\\')
+ result+="\\\\";
+ else
+ result+=c;
+ pc=c;
+ }
+ }
+ }
+ //printf("stringize `%s'->`%s'\n",s.data(),result.data());
+ return result;
+}
+
+/*! Execute all ## operators in expr.
+ * If the macro name before or after the operator contains a no-rescan
+ * marker (@-) then this is removed (before the concatenated macro name
+ * may be expanded again.
+ */
+static void processConcatOperators(QString &expr)
+{
+ QRegExp r("[ \\t\\n]*##[ \\t\\n]*");
+ int l,n,i=0;
+ while ((n=r.match(expr,i,&l))!=-1)
+ {
+ if (n+l+1<(int)expr.length() && expr.at(n+l)=='@' && expr.at(n+l+1)=='-')
+ {
+ // remove no-rescan marker after ID
+ l+=2;
+ }
+ // remove the ## operator and the surrounding whitespace
+ expr=expr.left(n)+expr.right(expr.length()-n-l);
+ int k=n-1;
+ while (k>=0 && isId(expr.at(k))) k--;
+ if (k>0 && expr.at(k)=='-' && expr.at(k-1)=='@')
+ {
+ // remove no-rescan marker before ID
+ expr=expr.left(k-1)+expr.right(expr.length()-k-1);
+ n-=2;
+ }
+ i=n+l;
+ }
+}
+
+/*! replaces the function macro \a def whose argument list starts at
+ * \a pos in expression \a expr.
+ * Notice that this routine may scan beyond the \a expr string if needed.
+ * The characters from the input file will be read.
+ * The replacement string will be returned in \a result and the
+ * length of the (unexpanded) argument list is stored in \a len.
+ */
+static bool replaceFunctionMacro(const QString &expr,QString *rest,int pos,int &len,const Define *def,QString &result)
+{
+ //printf("replaceFunctionMacro(expr=%s,rest=%s,pos=%d,def=%s) level=%d\n",expr.data(),rest ? rest->data() : 0,pos,def->name.data(),level);
+ //bool replaced=FALSE;
+ uint j=pos;
+ len=0;
+ result.resize(0);
+ int cc;
+ // TODO: use a checkNextChar function.
+ //while ((cc=getNextChar(expr,rest,j))!=EOF && cc==' ') len++;
+ //if (cc!='(') return FALSE;
+ while ((cc=getCurrentChar(expr,rest,j))!=EOF && cc==' ')
+ {
+ len++;
+ getNextChar(expr,rest,j);
+ }
+ if (cc!='(')
+ {
+ unputChar(expr,rest,j,' ');
+ return FALSE;
+ }
+ getNextChar(expr,rest,j); // eat the `(' character
+
+ //while (j<expr.length() && expr.at(j)!='(') j++;
+ //j++; // skip opening paren
+
+ QDict<QString> argTable; // list of arguments
+ argTable.setAutoDelete(TRUE);
+ QString arg;
+ int argCount=0;
+ bool done=FALSE;
+ // FASE 1: read the macro arguments
+ while ((argCount<def->nargs || def->varArgs) &&
+ ((cc=getNextChar(expr,rest,j))!=EOF) && !done
+ )
+ {
+ char c=(char)cc;
+ if (c=='(') // argument is a function => search for matching )
+ {
+ int level=1;
+ arg+=c;
+ char term='\0';
+ while ((cc=getNextChar(expr,rest,j))!=EOF)
+ {
+ char c=(char)cc;
+ if (c=='\'' || c=='\"') // skip ('s and )'s inside strings
+ {
+ if (term!='\0')
+ {
+ if (c==term && expr.at(j-2)!='\\') term='\0';
+ }
+ else
+ {
+ term=c;
+ }
+ }
+ if (term=='\0' && c==')')
+ {
+ level--;
+ arg+=c;
+ if (level==0) break;
+ }
+ else if (term=='\0' && c=='(')
+ {
+ level++;
+ arg+=c;
+ }
+ else
+ arg+=c;
+ }
+ }
+ else if (c==')' || c==',') // last or next argument found
+ {
+ if (c==',' && argCount==def->nargs-1 && def->varArgs)
+ {
+ arg=arg.stripWhiteSpace();
+ arg+=',';
+ }
+ else
+ {
+ QString argKey;
+ argKey.sprintf("@%d",argCount++); // key name
+ arg=arg.stripWhiteSpace();
+ // add argument to the lookup table
+ argTable.insert(argKey, new QString(arg));
+ arg.resize(0);
+ if (c==')') // end of the argument list
+ {
+ done=TRUE;
+ }
+ }
+ }
+ else if (c=='\"') // append literal strings
+ {
+ arg+=c;
+ char pc=c;
+ bool found=FALSE;
+ while (!found && (cc=getNextChar(expr,rest,j))!=EOF)
+ {
+ found = pc!='\\' && cc=='"';
+ c=(char)cc;
+ pc=c;
+ arg+=c;
+ }
+ }
+ else if (c=='\'') // append literal characters
+ {
+ arg+=c;
+ char pc=c;
+ bool found=FALSE;
+ while (!found && (cc=getNextChar(expr,rest,j))!=EOF)
+ {
+ found = pc!='\\' && cc=='\'';
+ c=(char)cc;
+ pc=c;
+ arg+=c;
+ }
+ }
+ else // append other characters
+ {
+ arg+=c;
+ }
+ }
+
+ // FASE 2: apply the macro function
+ if (argCount==def->nargs ||
+ (argCount>def->nargs && def->varArgs)) // matching parameters lists
+ {
+ uint k=0;
+ // substitution of all formal arguments
+ QString resExpr;
+ const QString d=def->definition.stripWhiteSpace();
+ bool inString=FALSE;
+ while (k<d.length())
+ {
+ if (d.at(k)=='@') // maybe a marker, otherwise an escaped @
+ {
+ if (d.at(k+1)=='@') // escaped @ => copy it (is unescaped later)
+ {
+ k+=2;
+ resExpr+="@@"; // we unescape these later
+ }
+ else if (d.at(k+1)=='-') // no-rescan marker
+ {
+ k+=2;
+ resExpr+="@-";
+ }
+ else // argument marker => read the argument number
+ {
+ QString key="@";
+ QString *subst=0;
+ bool hash=FALSE;
+ int l=k-1;
+ // search for ## backward
+ if (l>=0 && d.at(l)=='"') l--;
+ while (l>=0 && d.at(l)==' ') l--;
+ if (l>0 && d.at(l)=='#' && d.at(l-1)=='#') hash=TRUE;
+ k++;
+ // scan the number
+ while (k<d.length() && d.at(k)>='0' && d.at(k)<='9') key+=d.at(k++);
+ if (!hash)
+ {
+ // search for ## forward
+ l=k;
+ if (l<(int)d.length() && d.at(l)=='"') l++;
+ while (l<(int)d.length() && d.at(l)==' ') l++;
+ if (l<(int)d.length()-1 && d.at(l)=='#' && d.at(l+1)=='#') hash=TRUE;
+ }
+ //printf("request key %s result %s\n",key.data(),args[key]->data());
+ if (key.length()>1 && (subst=argTable[key]))
+ {
+ QString substArg=*subst;
+ // only if no ## operator is before or after the argument
+ // marker we do macro expansion.
+ if (!hash) expandExpression(substArg,0,0);
+ if (inString)
+ {
+ //printf("`%s'=stringize(`%s')\n",stringize(*subst).data(),subst->data());
+
+ // if the marker is inside a string (because a # was put
+ // before the macro name) we must escape " and \ characters
+ resExpr+=stringize(substArg);
+ }
+ else
+ {
+ resExpr+=substArg;
+ }
+ }
+ }
+ }
+ else // no marker, just copy
+ {
+ if (!inString && d.at(k)=='\"')
+ {
+ inString=TRUE; // entering a literal string
+ }
+ else if (inString && d.at(k)=='\"' && d.at(k-1)!='\\')
+ {
+ inString=FALSE; // leaving a literal string
+ }
+ resExpr+=d.at(k++);
+ }
+ }
+ len=j-pos;
+ result=resExpr;
+ //printf("result after substitution `%s' expr=`%s'\n",
+ // result.data(),expr.mid(pos,len).data());
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+}
+
+
+/*! returns the next identifier in string \a expr by starting at position \a p.
+ * The position of the identifier is returned (or -1 if nothing is found)
+ * and \a l is its length. Any quoted strings are skipping during the search.
+ */
+static int getNextId(const QString &expr,int p,int *l)
+{
+ int n;
+ while (p<(int)expr.length())
+ {
+ char c=expr.at(p++);
+ if (isalpha(c) || c=='_') // read id
+ {
+ n=p-1;
+ while (p<(int)expr.length() && isId(expr.at(p))
+ ) p++;
+ *l=p-n;
+ return n;
+ }
+ else if (c=='"') // skip string
+ {
+ char pc=c;
+ if (p<(int)expr.length()) c=expr.at(p);
+ while (p<(int)expr.length() && (c!='"' || pc=='\\'))
+ {
+ pc=c;
+ c=expr.at(p);
+ p++;
+ }
+ }
+ }
+ return -1;
+}
+
+/*! preforms recursive macro expansion on the string \a expr
+ * starting at position \a pos.
+ * May read additional characters from the input while re-scanning!
+ * If \a expandAll is \c TRUE then all macros in the expression are
+ * expanded, otherwise only the first is expanded.
+ */
+static void expandExpression(QString &expr,QString *rest,int pos)
+{
+ //printf("expandExpression(%s,%s)\n",expr.data(),rest ? rest->data() : 0);
+ QString macroName;
+ QString expMacro;
+ int i=pos,l,p,len;
+ while ((p=getNextId(expr,i,&l))!=-1) // search for an macro name
+ {
+ bool replaced=FALSE;
+ macroName=expr.mid(p,l);
+ //printf("macroName %s found\n",macroName.data());
+ if (p<2 || !(expr.at(p-2)=='@' && expr.at(p-1)=='-')) // no-rescan marker?
+ {
+ if (expandedDict->find(macroName)==0) // expand macro
+ {
+ Define *def=isDefined(macroName);
+ //printf("name is not an expanded macro def=%s\n",def ? def->name.data() : 0);
+ if (def && def->nargs==0) // simple macro
+ {
+ // substitute the definition of the macro
+ expMacro=def->definition.stripWhiteSpace();
+ replaced=TRUE;
+ len=l;
+ //printf("simple macro expansion=`%s'->`%s'\n",macroName.data(),expMacro.data());
+ }
+ else if (def && def->nargs>0) // function macro
+ {
+ replaced=replaceFunctionMacro(expr,rest,p+l,len,def,expMacro);
+ len+=l;
+ }
+
+ if (replaced) // expand the macro and rescan the expression
+ {
+ //printf("replacing `%s'->`%s'\n",expr.mid(p,len).data(),expMacro.data());
+ QString resultExpr=expMacro;
+ QString restExpr=expr.right(expr.length()-len-p);
+ processConcatOperators(resultExpr);
+ expandedDict->insert(macroName,def);
+ expandExpression(resultExpr,&restExpr,0);
+ expandedDict->remove(macroName);
+ expr=expr.left(p)+resultExpr+restExpr;
+ i=p;
+ //printf("new expression: %s\n",expr.data());
+ }
+ else // move to the next macro name
+ {
+ //printf("moving to the next macro old=%d new=%d\n",i,p+l);
+ i=p+l;
+ }
+ }
+ else // move to the next macro name
+ {
+ expr=expr.left(p)+"@-"+expr.right(expr.length()-p);
+ //printf("macro already expanded, moving to the next macro expr=%s\n",expr.data());
+ i=p+l+2;
+ //i=p+l;
+ }
+ }
+ else // no re-scan marker found, skip the macro name
+ {
+ //printf("skipping marked macro\n");
+ i=p+l;
+ }
+ }
+}
+
+/*! replaces all occurrences of @@ in \a s by @
+ * All identifiers found are replaced by 0L
+ * \par assumption:
+ * \a s only contains pairs of @@'s.
+ */
+QString removeIdsAndMarkers(const char *s)
+{
+ //printf("removeIdsAndMarkers(%s)\n",s);
+ const char *p=s;
+ char c;
+ bool inNum=FALSE;
+ QString result;
+ if (p)
+ {
+ while ((c=*p))
+ {
+ if (c=='@') // replace @@ with @
+ {
+ if (*(p+1)=='@')
+ {
+ result+=c;
+ }
+ p+=2;
+ }
+ else if (isdigit(c))
+ {
+ result+=c;
+ p++;
+ inNum=TRUE;
+ }
+ else if ((isalpha(c) || c=='_') && !inNum) // replace identifier with 0L
+ {
+ result+="0L";
+ p++;
+ while ((c=*p) && isId(c)) p++;
+ }
+ else
+ {
+ result+=c;
+ char lc=tolower(c);
+ if (lc!='l' && lc!='u') inNum=FALSE;
+ p++;
+ }
+ }
+ }
+ return result;
+}
+
+/*! replaces all occurrences of @@ in \a s by @
+ * \par assumption:
+ * \a s only contains pairs of @@'s
+ */
+QString removeMarkers(const char *s)
+{
+ const char *p=s;
+ char c;
+ QString result;
+ if (p)
+ {
+ while ((c=*p))
+ {
+ if (c=='@') // replace @@ with @
+ {
+ if (*(p+1)=='@')
+ {
+ result+=c;
+ }
+ p+=2;
+ }
+ else
+ {
+ result+=c;
+ p++;
+ }
+ }
+ }
+ return result;
+}
+
+/*! compute the value of the expression in string \a expr.
+ * If needed the function may read additional characters from the input.
+ */
+
+bool computeExpression(const QString &expr)
+{
+ QString e=expr;
+ expandExpression(e,0,0);
+ e = removeIdsAndMarkers(e);
+ if (e.length()==0) return FALSE;
+ //printf("computeExpession(%s)\n",e.data());
+ return parseCppExpression(e);
+}
+
+/*! expands the macro definition in \a name
+ * If needed the function may read additional characters from the input
+ */
+
+QString expandMacro(const QString &name)
+{
+ QString n=name;
+ expandExpression(n,0,0);
+ n=removeMarkers(n);
+ //printf("expandMacro `%s'->`%s'\n",name.data(),n.data());
+ return n;
+}
+
+Define *newDefine()
+{
+ Define *def=new Define;
+ def->name = defName;
+ def->definition = defText.stripWhiteSpace();
+ def->nargs = defArgs;
+ def->fileName = yyFileName;
+ def->lineNr = yyLineNr;
+ def->varArgs = defVarArgs;
+ return def;
+}
+
+void addDefine()
+{
+ bool ambig;
+ FileDef *fd=findFileDef(&inputNameDict,yyFileName,ambig);
+ MemberDef *md=new MemberDef("#define",defName,defArgsStr,0,
+ Public,Normal,FALSE,FALSE,MemberDef::Define,0,0);
+ md->setDefFile(yyFileName);
+ md->setDefLine(yyLineNr);
+ md->setFileDef(fd);
+ md->setDefinition("#define "+defName+defArgsStr);
+
+ MemberName *mn=functionNameDict[defName];
+ if (mn==0)
+ {
+ mn = new MemberName(defName);
+ functionNameList.inSort(mn);
+ functionNameDict.insert(defName,mn);
+ }
+ mn->append(md);
+ if (fd) fd->insertMember(md);
+
+ Define *d;
+ if ((d=defineDict[defName])==0) defineDict.insert(defName,newDefine());
+
+}
+
+static void outputChar(char c)
+{
+ if (includeStack.isEmpty()) outputBuf->addChar(c);
+}
+
+static void outputArray(const char *a,int len)
+{
+ if (includeStack.isEmpty()) outputBuf->addArray(a,len);
+}
+
+static void readIncludeFile(const QString &inc)
+{
+ if (!searchIncludeFlag) return; // do not read include files
+ uint i=0;
+ // find the start of the include file name
+ while (i<inc.length() &&
+ (inc.at(i)==' ' || inc.at(i)=='"' || inc.at(i)=='<')
+ ) i++;
+ uint s=i;
+ // find the end of the include file name
+ while (i<inc.length() &&
+ inc.at(i)!='"' && inc.at(i)!='>') i++;
+ if (s<inc.length() && i>s) // valid include file name found
+ {
+ QString incFileName=inc.mid(s,i-s).stripWhiteSpace();
+
+ FILE *f;
+ QString oldFileName=yyFileName.copy();
+ if ((f=findFile(incFileName))) // see if the include file can be found
+ {
+#if SHOW_INCLUDES
+ for (i=0;i<includeStack.count();i++) msg(" ");
+ msg("#include %s: parsing...\n",incFileName.data());
+#endif
+ // store the state of the old file
+ FileState *fs=new FileState;
+ fs->bufState=YY_CURRENT_BUFFER;
+ fs->lineNr=yyLineNr;
+ fs->fileName=oldFileName;
+ fs->filePtr=f;
+ // push the state on the stack
+ includeStack.push(fs);
+ // set the scanner to the include file
+ preYYin=f;
+ yy_switch_to_buffer(yy_create_buffer(preYYin, YY_BUF_SIZE));
+ }
+ else
+ {
+#if SHOW_INCLUDES
+ msg("#include %s: not found! skipping...\n",incFileName.data());
+ //printf("Error: include file %s not found\n",yytext);
+#endif
+ }
+ }
+}
+
+/* ----------------------------------------------------------------- */
+
+%}
+
+ID [a-z_A-Z][a-z_A-Z0-9]*
+B [ \t]
+BN [ \t\r\n]
+
+%x Start
+%x Command
+%x SkipCommand
+%x SkipLine
+%x CopyLine
+%x Include
+%x IncludeID
+%x DefineName
+%x DefineArg
+%x DefineText
+%x SkipCPPBlock
+%x Ifdef
+%x Ifndef
+%x SkipCComment
+%x SkipCPPComment
+%x RemoveCComment
+%x RemoveCPPComment
+%x Guard
+%x DefinedExpr1
+%x DefinedExpr2
+%x SkipDoubleQuote
+%x SkipSingleQuote
+%x UndefName
+%x IgnoreLine
+%x FindDefineArgs
+%x ReadString
+
+%%
+
+<*>\x06
+<*>\x00
+<*>\r
+ /*
+<Start>^{B}*([^ \t#\n\/][^\n]*)?"\n" {
+ //printf("%s line %d: %s",yyFileName.data(),yyLineNr,yytext);
+ if (includeStack.isEmpty())
+ {
+ //preprocessedFile+=yytext;
+ //char *s=yytext,c;
+ //if (s) while ((c=*s++)) *dataPtr++=c;
+ outputBuf->addArray(yytext,yyleng);
+ }
+ yyLineNr++;
+ }
+ */
+<Start>^{B}*"#" { BEGIN(Command); }
+<Start>^{B}*/[^#] {
+ outputArray(yytext,yyleng);
+ BEGIN(CopyLine);
+ }
+ /*
+<CopyLine>[^\n/]+ {
+ outputArray(yytext,yyleng);
+ }
+ */
+<CopyLine>{ID}/{BN}*"(" {
+ if (includeStack.isEmpty() &&
+ macroExpansionFlag &&
+ /* (expandDefine=fileDefineCache->findDefine(yyFileName,yytext)) */
+ fileDefineDict->find(yytext)
+ )
+ {
+ roundCount=0;
+ defArgsStr=yytext;
+ findDefArgContext = CopyLine;
+ BEGIN(FindDefineArgs);
+ }
+ else
+ {
+ outputArray(yytext,yyleng);
+ }
+ }
+<CopyLine>{ID} {
+ Define *def=0;
+ if (includeStack.isEmpty() &&
+ macroExpansionFlag &&
+ (def=fileDefineDict->find(yytext)) &&
+ def->nargs==0
+ )
+ {
+ QString name=yytext;
+ QString result=expandMacro(name);
+ outputArray(result,result.length());
+ }
+ else
+ {
+ outputArray(yytext,yyleng);
+ }
+ }
+<CopyLine>. {
+ outputChar(*yytext);
+ }
+<CopyLine>\n {
+ outputChar('\n');
+ BEGIN(Start);
+ yyLineNr++;
+ }
+<FindDefineArgs>"(" {
+ defArgsStr+='(';
+ roundCount++;
+ }
+<FindDefineArgs>")" {
+ defArgsStr+=')';
+ roundCount--;
+ if (roundCount==0)
+ {
+ QString result=expandMacro(defArgsStr);
+ if (findDefArgContext==CopyLine)
+ {
+ outputArray(result,result.length());
+ BEGIN(findDefArgContext);
+ }
+ else // findDefArgContext==IncludeID
+ {
+ readIncludeFile(result);
+ BEGIN(Start);
+ }
+ }
+ }
+ /*
+<FindDefineArgs>")"{B}*"(" {
+ defArgsStr+=yytext;
+ }
+ */
+<FindDefineArgs>"\"" {
+ defArgsStr+=*yytext;
+ BEGIN(ReadString);
+ }
+<FindDefineArgs>\n {
+ yyLineNr++;
+ outputChar('\n');
+ }
+<FindDefineArgs>"@" {
+ defArgsStr+="@@";
+ }
+<FindDefineArgs>. {
+ defArgsStr+=*yytext;
+ }
+<ReadString>"\\\"" {
+ defArgsStr+=yytext;
+ }
+<ReadString>"\"" {
+ defArgsStr+=*yytext;
+ BEGIN(FindDefineArgs);
+ }
+<ReadString>. {
+ defArgsStr+=*yytext;
+ }
+<Command>"include"{B}*/{ID} {
+ if (macroExpansionFlag)
+ BEGIN(IncludeID);
+ }
+<Command>"include"{B}*[<"] {
+ BEGIN(Include);
+ }
+<Command>"define"{B}+ {
+ //printf("!!!DefineName\n");
+ BEGIN(DefineName);
+ }
+<Command>"ifdef"/{B}*"(" {
+ incrLevel();
+ guardExpr.resize(0);
+ BEGIN(DefinedExpr2);
+ }
+<Command>"ifdef"/{B}+ {
+ //printf("Pre.l: ifdef\n");
+ incrLevel();
+ guardExpr.resize(0);
+ BEGIN(DefinedExpr1);
+ }
+<Command>"ifndef"/{B}*"(" {
+ incrLevel();
+ guardExpr="! ";
+ BEGIN(DefinedExpr2);
+ }
+<Command>"ifndef"/{B}+ {
+ incrLevel();
+ guardExpr="! ";
+ BEGIN(DefinedExpr1);
+ }
+<Command>"if"/[ \t(] {
+ incrLevel();
+ guardExpr.resize(0);
+ BEGIN(Guard);
+ }
+<Command>"elif"/[ \t(] {
+ if (!otherCaseDone())
+ {
+ guardExpr.resize(0);
+ BEGIN(Guard);
+ }
+ else
+ {
+ ifcount=0;
+ BEGIN(SkipCPPBlock);
+ }
+ }
+<Command>"else"/[^a-z_A-Z0-9] {
+ //printf("else levelGuard[%d]=%d\n",level-1,levelGuard[level-1]);
+ if (otherCaseDone())
+ {
+ ifcount=0;
+ BEGIN(SkipCPPBlock);
+ }
+ else
+ {
+ setCaseDone(TRUE);
+ //levelGuard[level-1]=TRUE;
+ }
+ }
+<Command>"undef"{B}+ {
+ BEGIN(UndefName);
+ }
+<Command>"elif"/[ \t(] {
+ if (!otherCaseDone())
+ {
+ guardExpr.resize(0);
+ BEGIN(Guard);
+ }
+ }
+<Command>"endif"/[^a-z_A-Z0-9] {
+ //printf("Pre.l: #endif\n");
+ decrLevel();
+ }
+<Command,IgnoreLine>\n {
+ outputChar('\n');
+ BEGIN(Start);
+ yyLineNr++;
+ }
+<Command>{ID} { // unknown directive
+ BEGIN(IgnoreLine);
+ }
+<IgnoreLine>.
+<Command>.
+<UndefName>{ID} {
+ Define *def;
+ if ((def=isDefined(yytext)))
+ {
+ //printf("undefining %s\n",yytext);
+ def->undef=TRUE;
+ }
+ BEGIN(Start);
+ }
+<Guard>\\\n {
+ outputChar('\n');
+ guardExpr+=' ';
+ yyLineNr++;
+ }
+<Guard>"defined"/{B}*"(" {
+ BEGIN(DefinedExpr2);
+ }
+<Guard>"defined"/{B}+ {
+ BEGIN(DefinedExpr1);
+ }
+<Guard>. { guardExpr+=*yytext; }
+<Guard>\n {
+ outputChar('\n');
+ yyLineNr++;
+ //printf("Guard: `%s'\n",
+ // guardExpr.data());
+ bool guard=computeExpression(guardExpr);
+ setCaseDone(guard);
+ //printf("if levelGuard[%d]=%d\n",level-1,levelGuard[level-1]);
+ if (guard)
+ {
+ BEGIN(Start);
+ }
+ else
+ {
+ ifcount=0;
+ BEGIN(SkipCPPBlock);
+ }
+ }
+<DefinedExpr1,DefinedExpr2>\\\n { yyLineNr++; outputChar('\n'); }
+<DefinedExpr1>{ID} {
+ if (isDefined(yytext))
+ guardExpr+=" 1L ";
+ else
+ guardExpr+=" 0L ";
+ BEGIN(Guard);
+ }
+<DefinedExpr2>{ID} {
+ if (isDefined(yytext))
+ guardExpr+=" 1L ";
+ else
+ guardExpr+=" 0L ";
+ }
+<DefinedExpr1,DefinedExpr2>\n { // should not happen, handle anyway
+ ifcount=0;
+ BEGIN(SkipCPPBlock);
+ }
+<DefinedExpr2>")" {
+ BEGIN(Guard);
+ }
+<DefinedExpr1,DefinedExpr2>.
+<SkipCPPBlock>^{B}*"#" { BEGIN(SkipCommand); }
+<SkipCPPBlock>^{B}*/[^#] { BEGIN(SkipLine); }
+<SkipCPPBlock>.
+<SkipCommand>"if"(("n")?("def"))?/[ \t(] {
+ incrLevel();
+ ifcount++;
+ //printf("#if... depth=%d\n",ifcount);
+ }
+<SkipCommand>"else"/[^a-z_A-Z0-9] {
+ //printf("Else! ifcount=%d otherCaseDone=%d\n",ifcount,otherCaseDone());
+ if (ifcount==0 && !otherCaseDone())
+ {
+ setCaseDone(TRUE);
+ //outputChar('\n');
+ BEGIN(Start);
+ }
+ }
+<SkipCommand>"elif"/[ \t(] {
+ if (ifcount==0)
+ {
+ if (!otherCaseDone())
+ {
+ guardExpr.resize(0);
+ BEGIN(Guard);
+ }
+ else
+ {
+ BEGIN(Start);
+ }
+ }
+ }
+<SkipCommand>"endif"/[^a-z_A-Z0-9] {
+ decrLevel();
+ if (--ifcount<0)
+ {
+ //outputChar('\n');
+ BEGIN(Start);
+ }
+ }
+<SkipCommand>\n {
+ outputChar('\n');
+ yyLineNr++;
+ BEGIN(SkipCPPBlock);
+ }
+<SkipCommand>{ID} { // unknown directive
+ BEGIN(SkipLine);
+ }
+<SkipCommand>.
+<SkipLine>[^/\n]+
+<SkipLine>.
+<SkipLine>"//" {
+ lastCPPContext=YY_START;
+ BEGIN(RemoveCPPComment);
+ }
+<SkipLine>"/*" {
+ lastCContext=YY_START;
+ BEGIN(RemoveCComment);
+ }
+<SkipLine>\n {
+ outputChar('\n');
+ yyLineNr++;
+ BEGIN(SkipCPPBlock);
+ }
+<IncludeID>{ID}{B}*/"(" {
+ roundCount=0;
+ defArgsStr=yytext;
+ findDefArgContext = IncludeID;
+ BEGIN(FindDefineArgs);
+ }
+<IncludeID>{ID} {
+ readIncludeFile(expandMacro(yytext));
+ BEGIN(Start);
+ }
+<Include>[^\">\n]+[\">] {
+ QString incName=yytext;
+ //int l=incName.length();
+ //QString incFileName=incName.left(l-1);
+ //if (fileDefineCache->fileCached(incFileName))
+ //{
+ // printf("file already cached!\n");
+ // fileDefineCache->merge(incFileName,yyFileName);
+ //}
+ //else if ((f=findFile(incFileName)))
+ readIncludeFile(incName);
+
+ BEGIN(Start);
+ }
+<DefineName>{ID}/"(" {
+ //printf("Define() `%s'\n",yytext);
+ argDict = new QDict<int>(31);
+ argDict->setAutoDelete(TRUE);
+ defArgs = 0;
+ defArgsStr.resize(0);
+ defText.resize(0);
+ defName = yytext;
+ defVarArgs = FALSE;
+ BEGIN(DefineArg);
+ }
+<DefineName>{ID}/{B}* {
+ //printf("Define `%s'\n",yytext);
+ argDict = 0;
+ defArgs = 0;
+ defArgsStr.resize(0);
+ defText.resize(0);
+ defName = yytext;
+ defVarArgs = FALSE;
+ QString tmp=(QString)"#define "+defName+defArgsStr;
+ outputArray(tmp.data(),tmp.length());
+ quoteArg=FALSE;
+ BEGIN(DefineText);
+ }
+<DefineArg>","{B}* { defArgsStr+=yytext; }
+<DefineArg>"("{B}* { defArgsStr+=yytext; }
+<DefineArg>")"{B}* {
+ defArgsStr+=yytext;
+ QString tmp=(QString)"#define "+defName+defArgsStr;
+ outputArray(tmp.data(),tmp.length());
+ quoteArg=FALSE;
+ BEGIN(DefineText);
+ }
+<DefineArg>{ID}("..."?) {
+ //printf("Define addArg(%s)\n",yytext);
+ QString argName=yytext;
+ defVarArgs = yytext[yyleng-1]=='.';
+ if (defVarArgs)
+ argName=argName.left(argName.length()-3);
+ defArgsStr+=yytext;
+ argDict->insert(argName,new int(defArgs));
+ defArgs++;
+ }
+<DefineText>"/*" {
+ outputChar('/');outputChar('*');
+ defText+=' ';
+ lastCContext=YY_START;
+ BEGIN(SkipCComment);
+ }
+<DefineText>"//" {
+ outputChar('/');outputChar('/');
+ lastCPPContext=YY_START;
+ BEGIN(SkipCPPComment);
+ }
+<SkipCComment>"*/" {
+ outputChar('*');outputChar('/');
+ BEGIN(lastCContext);
+ }
+<SkipCComment>"//" {
+ outputChar('/');outputChar('/');
+ }
+<SkipCComment>"/*" {
+ outputChar('/');outputChar('*');
+ }
+<SkipCComment>[^*\n]+ {
+ outputArray(yytext,yyleng);
+ }
+<SkipCComment>\n {
+ yyLineNr++;
+ outputChar('\n');
+ }
+<SkipCComment>. {
+ outputChar(*yytext);
+ }
+<RemoveCComment>"*/" { BEGIN(lastCContext); }
+<RemoveCComment>"//"
+<RemoveCComment>"/*"
+<RemoveCComment>[^*\n]+
+<RemoveCComment>\n { yyLineNr++; outputChar('\n'); }
+<RemoveCComment>.
+<SkipCPPComment,RemoveCPPComment>\n {
+ unput(*yytext);
+ BEGIN(lastCPPContext);
+ }
+<SkipCPPComment>"/*" {
+ outputChar('/');outputChar('*');
+ }
+<SkipCPPComment>"//" {
+ outputChar('/');outputChar('/');
+ }
+<SkipCPPComment>[^\n]+ {
+ outputArray(yytext,yyleng);
+ }
+<SkipCPPComment>. {
+ outputChar(*yytext);
+ }
+<RemoveCPPComment>"/*"
+<RemoveCPPComment>"//"
+<RemoveCPPComment>[^\n]+
+<RemoveCPPComment>.
+<DefineText>"#" {
+ quoteArg=TRUE;
+ }
+<DefineText>{ID} {
+ //bool quote=FALSE;
+ //char *p=yytext;
+ //if (p[0]=='#')
+ //{
+ // p++;
+ // quote=TRUE;
+ // defText+="\"";
+ //}
+ if (quoteArg)
+ {
+ defText+="\"";
+ }
+ if (defArgs>0)
+ {
+ int *n;
+ if ((n=(*argDict)[yytext]))
+ {
+ if (!quoteArg) defText+=' ';
+ defText+='@';
+ QString numStr;
+ numStr.setNum(*n);
+ defText+=numStr;
+ if (!quoteArg) defText+=' ';
+ }
+ else
+ {
+ defText+=yytext;
+ }
+ }
+ else
+ {
+ defText+=yytext;
+ }
+ if (quoteArg)
+ {
+ defText+="\"";
+ }
+ quoteArg=FALSE;
+ }
+<DefineText>\\\n {
+ outputChar('\n');
+ defText += ' '; yyLineNr++;
+ }
+<DefineText>\n {
+ outputChar('\n');
+ Define *def=0;
+ //printf("Define name=`%s' text=`%s'\n",defName.data(),defText.data());
+ if (includeStack.isEmpty()) addDefine();
+ if (!onlyPredefinedFlag && (def=fileDefineDict->find(defName))==0)
+ {
+ fileDefineDict->insert(defName,newDefine());
+ }
+ //if ((def=fileDefineCache->findDefine(yyFileName,defName))==0)
+ //{
+ // printf("define is not found\n");
+ // fileDefineCache->insertDefine(yyFileName,defName,newDefine());
+ //}
+ else if (def)// name already exists
+ {
+ //printf("define found\n");
+ if (def->undef) // undefined name
+ {
+ def->undef = FALSE;
+ def->name = defName;
+ def->definition = defText.stripWhiteSpace();
+ def->nargs = defArgs;
+ def->fileName = yyFileName;
+ def->lineNr = yyLineNr;
+ }
+ else
+ {
+ //printf("Error: define %s is defined more than once!\n",defName.data());
+ }
+ }
+ delete argDict;
+ yyLineNr++;
+ BEGIN(Start);
+ }
+<DefineText>{B}* { defText += ' '; }
+<DefineText>{B}*"##"{B}* { defText += "##"; }
+<DefineText>"@" { defText += "@@"; }
+<DefineText>\" { defText += *yytext;
+ BEGIN(SkipDoubleQuote);
+ }
+<DefineText>\' { defText += *yytext;
+ BEGIN(SkipSingleQuote);
+ }
+<SkipDoubleQuote>\" {
+ defText += *yytext;
+ BEGIN(DefineText);
+ }
+<SkipSingleQuote>\' {
+ defText += *yytext;
+ BEGIN(DefineText);
+ }
+<SkipDoubleQuote>. { defText += *yytext; }
+<SkipSingleQuote>. { defText += *yytext; }
+<DefineText>. { defText += *yytext; }
+<<EOF>> {
+ //printf("End of include file\n");
+ //printf("Include stack depth=%d\n",includeStack.count());
+ if (includeStack.isEmpty())
+ {
+ //printf("Terminating scanner!\n");
+ yyterminate();
+ }
+ else
+ {
+ FileState *fs=includeStack.pop();
+ //fileDefineCache->merge(yyFileName,fs->fileName);
+ if (inputFilter.isEmpty())
+ fclose(fs->filePtr);
+ else
+ pclose(fs->filePtr);
+ YY_BUFFER_STATE oldBuf = YY_CURRENT_BUFFER;
+ yy_switch_to_buffer( fs->bufState );
+ yy_delete_buffer( oldBuf );
+ yyLineNr=fs->lineNr;
+ yyFileName=fs->fileName.copy();
+ //printf("######## FileName %s\n",yyFileName.data());
+ delete fs;
+ }
+ }
+<*>"/*" {
+ outputChar('/');outputChar('*');
+ lastCContext=YY_START;
+ BEGIN(SkipCComment);
+ }
+<*>"//" {
+ outputChar('/');outputChar('/');
+ lastCPPContext=YY_START;
+ BEGIN(SkipCPPComment);
+ }
+<*>\n {
+ outputChar('\n');
+ yyLineNr++;
+ }
+<*>. {
+ outputChar(*yytext);
+ }
+
+%%
+
+/*@ ----------------------------------------------------------------------------
+ */
+
+static int getNextChar(const QString &expr,QString *rest,uint &pos)
+{
+ //printf("getNextChar(%s,%s,%d)\n",expr.data(),rest ? rest->data() : 0,pos);
+ if (pos<expr.length())
+ {
+ //printf("%c=expr()\n",expr.at(pos));
+ return expr.at(pos++);
+ }
+ else if (rest && rest->length()>0)
+ {
+ int cc=rest->at(0);
+ *rest=rest->right(rest->length()-1);
+ //printf("%c=rest\n",cc);
+ return cc;
+ }
+ else
+ {
+ int cc=yyinput();
+ //printf("%c=yyinput()\n",cc);
+ return cc;
+ }
+}
+
+static int getCurrentChar(const QString &expr,QString *rest,uint pos)
+{
+ //printf("getCurrentChar(%s,%s,%d)\n",expr.data(),rest ? rest->data() : 0,pos);
+ if (pos<expr.length())
+ {
+ //printf("%c=expr()\n",expr.at(pos));
+ return expr.at(pos);
+ }
+ else if (rest && rest->length()>0)
+ {
+ int cc=rest->at(0);
+ //printf("%c=rest\n",cc);
+ return cc;
+ }
+ else
+ {
+ int cc=yyinput();unput(cc);
+ //printf("%c=yyinput()\n",cc);
+ return cc;
+ }
+}
+
+static void unputChar(const QString &expr,QString *rest,uint &pos,char c)
+{
+ //printf("unputChar(%s,%s,%d,%c)\n",expr.data(),rest ? rest->data() : 0,pos,c);
+ if (pos<expr.length())
+ {
+ pos++;
+ }
+ else if (rest)
+ {
+ //printf("Prepending to rest!\n");
+ char cs[2];cs[0]=c;cs[1]='\0';
+ rest->prepend(cs);
+ }
+ else
+ {
+ unput(c);
+ }
+ //printf("result: unputChar(%s,%s,%d,%c)\n",expr.data(),rest ? rest->data() : 0,pos,c);
+}
+
+void addSearchDir(const char *dir)
+{
+ QFileInfo fi(dir);
+ if (fi.isDir()) pathList->append(fi.absFilePath());
+}
+
+void initPreprocessor()
+{
+ pathList = new QStrList;
+ addSearchDir(".");
+ //defineNameList.setAutoDelete(TRUE);
+ //defineNameList.clear();
+ defineDict.clear();
+ //fileDefineCache = new DefineCache(1009);
+ expandedDict = new DefineDict(17);
+ fileDefineDict = new DefineDict(1009);
+}
+
+void cleanupPreprocessor()
+{
+ //delete fileDefineCache;
+ delete fileDefineDict;
+ delete expandedDict;
+ delete pathList;
+}
+
+
+void preprocessFile(const char *fileName,BufStr &output)
+{
+#if DUMP_OUTPUT
+ uint orgOffset=output.curPos();
+#endif
+
+ outputBuf=&output;
+ includeStack.setAutoDelete(TRUE);
+ includeStack.clear();
+ fileDefineDict->setAutoDelete(TRUE);
+ fileDefineDict->clear();
+ expandedDict->setAutoDelete(FALSE);
+ expandedDict->clear();
+
+ // add predefined macros
+ char *defStr = predefined.first();
+ while (defStr)
+ {
+ QString ds = defStr;
+ int i;
+ if ((i=ds.find('='))==-1)
+ {
+ if (ds.length()>0)
+ {
+ Define *def = new Define;
+ def->name = ds;
+ def->definition = "1";
+ def->nargs = 0;
+ fileDefineDict->insert(ds,def);
+ }
+ }
+ else
+ {
+ if (i>0 && (int)ds.length()>i)
+ {
+ Define *def = new Define;
+ def->name = ds.left(i);
+ def->definition = ds.right(ds.length()-i-1);
+ def->nargs = 0;
+ fileDefineDict->insert(ds.left(i),def);
+ }
+ }
+ defStr=predefined.next();
+ }
+
+ if (inputFilter.isEmpty())
+ {
+ preYYin = fopen(fileName,"r");
+ if (!preYYin)
+ {
+ err("Error: could not open file %s\n",fileName);
+ return;
+ }
+ }
+ else
+ {
+ QString cmd = inputFilter+" "+fileName;
+ preYYin = popen(cmd,"r");
+ if (!preYYin)
+ {
+ err("Error: could not execute filter %s\n",cmd.data());
+ return;
+ }
+ }
+ yyLineNr = 1;
+ level = 0;
+ yyFileName = fileName;
+ BEGIN( Start );
+ preYYlex();
+ if (inputFilter.isEmpty())
+ fclose(preYYin);
+ else
+ pclose(preYYin);
+
+#if DUMP_OUTPUT
+ char *orgPos=output.data()+orgOffset;
+ char *newPos=output.data()+output.curPos();
+ printf("Resulting size: %d bytes\n",newPos-orgPos);
+ int line=1;
+ printf("---------\n00001 ");
+ while (orgPos<newPos)
+ {
+ putchar(*orgPos);
+ if (*orgPos=='\n') printf("%05d ",++line);
+ orgPos++;
+ }
+ printf("\n---------\n");
+#endif
+}
+
+
+extern "C" { // some bogus code to keep the compiler happy
+ int preYYwrap() { return 1 ; }
+ void preYYdummy() { yy_flex_realloc(0,0); }
+}
diff --git a/src/scanner.h b/src/scanner.h
new file mode 100644
index 0000000..59d5966
--- /dev/null
+++ b/src/scanner.h
@@ -0,0 +1,34 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#ifndef SCANNER_H
+#define SCANNER_H
+
+#include <stdio.h>
+#include <qlist.h>
+#include <qstring.h>
+
+#include "entry.h"
+#include "code.h"
+
+class OutputList;
+
+extern void parseMain(Entry *);
+extern void parseDoc(OutputList &ol,const char *clName, const char *memName,
+ const QString &docString);
+extern void parseExample(OutputList &ol,const QString &docString,
+ const char *fileName);
+#endif
diff --git a/src/scanner.l b/src/scanner.l
new file mode 100644
index 0000000..0beadae
--- /dev/null
+++ b/src/scanner.l
@@ -0,0 +1,3386 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+%{
+
+/*
+ * includes
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <iostream.h>
+#include <assert.h>
+#include <ctype.h>
+
+#include <qarray.h>
+#include <qstring.h>
+#include <qstack.h>
+#include <qregexp.h>
+
+#include "scanner.h"
+#include "entry.h"
+#include "doxygen.h"
+#include "message.h"
+#include "config.h"
+#include "util.h"
+#include "index.h"
+#include "defargs.h"
+#include "language.h"
+
+#ifndef WIN32
+#include <unistd.h>
+#endif
+
+#define YY_NEVER_INTERACTIVE 1
+
+/* -----------------------------------------------------------------
+ *
+ * statics
+ */
+static bool insideArgumentList;
+static QString className;
+static QString memberName;
+static QString refName;
+static OutputList * outDoc;
+static QString code;
+static QString linkRef;
+static QString linkText;
+static QString codeBlock;
+static const char * inputString;
+static int inputPosition;
+static int lastContext;
+static int lastCContext;
+static int lastDocContext;
+static int lastDocRelContext;
+static int lastCPPContext;
+static int lastSkipSharpContext;
+static int lastSkipRoundContext;
+static int lastBriefContext;
+static int lastVerbState;
+static int lastStringContext;
+static int lastCurlyContext;
+static int lastCodeState;
+static int lastAfterDocContext;
+static int lastGroupContext;
+static int lastFormulaContext;
+static int nextDefContext;
+static Protection protection;
+static Protection baseProt;
+static int bracketCount = 0 ;
+static int sharpCount = 0 ;
+static int roundCount = 0 ;
+static int ifCount = 0 ;
+static Entry* current_root = 0 ;
+static Entry* global_root = 0 ;
+static Entry* current = 0 ;
+static int yyLineNr = 0 ;
+static int anonCount = 0 ;
+static char yyFileName[2048] ;
+static bool sig;
+static bool slot;
+static bool gstat;
+static bool removeSlashes;
+static Specifier virt;
+static Specifier baseVirt;
+static bool exampleDoc;
+static QString exampleName;
+static QString htmlUrl,htmlText;
+static QString currentIncludeFile;
+static QString msType,msName,msArgs;
+static int includeFileOffset = 0;
+static int includeFileLength = 0;
+static bool firstLine;
+static bool isTypedef;
+static bool inParamBlock;
+static bool inExceptionBlock;
+static bool inSeeBlock;
+static bool inReturnBlock;
+static bool inAuthorBlock;
+static bool inVersionBlock;
+static bool inDateBlock;
+static bool inBugBlock;
+static bool inWarningBlock;
+static bool inParBlock;
+static bool firstSeeArg;
+static bool javaDocSee;
+static char afterDocTerminator;
+static int tmpDocType;
+static QString sectionLabel;
+static QString sectionTitle;
+static bool isSubsection;
+static QString funcPtrType;
+static QString templateStr;
+static QString baseName;
+static QString *specName;
+static QString formulaText;
+static QString sectionRef;
+
+// state variable for reading the argument list of a function
+static int argRoundCount;
+static int argSharpCount;
+static int currentArgumentContext;
+static int lastCopyArgStringContext;
+static int lastCopyArgContext;
+static QString *copyArgString;
+
+
+
+//-----------------------------------------------------------------------------
+
+static void initParser()
+{
+ insideArgumentList=FALSE;
+ className.resize(0);
+ memberName.resize(0);
+ refName.resize(0);
+ code.resize(0);
+ linkRef.resize(0);
+ linkText.resize(0);
+ codeBlock.resize(0);
+ htmlUrl.resize(0);
+ htmlText.resize(0);
+ currentIncludeFile.resize(0);
+ sectionLabel.resize(0);
+ sectionTitle.resize(0);
+ baseName.resize(0);
+ formulaText.resize(0);
+ protection = Public;
+ baseProt = Public;
+ bracketCount = 0;
+ sharpCount = 0;
+ roundCount = 0;
+ ifCount = 0;
+ sig = FALSE;
+ slot = FALSE;
+ gstat = FALSE;
+ virt = Normal;
+ baseVirt = Normal;
+ includeFileOffset = 0;
+ includeFileLength = 0;
+ firstLine = TRUE;
+ isTypedef = FALSE;
+ inParamBlock = FALSE;
+ inExceptionBlock = FALSE;
+ inSeeBlock = FALSE;
+ inReturnBlock = FALSE;
+ inAuthorBlock = FALSE;
+ inVersionBlock = FALSE;
+ inDateBlock = FALSE;
+ inBugBlock = FALSE;
+ inWarningBlock = FALSE;
+ inParBlock = FALSE;
+ firstSeeArg = FALSE;
+ javaDocSee = FALSE;
+ isSubsection = FALSE;
+}
+
+//-----------------------------------------------------------------------------
+
+void scanString(const char *s);
+
+//-----------------------------------------------------------------------------
+
+class TableElem
+{
+ public:
+ TableElem(int r,int c);
+ ~TableElem();
+ int getRow() { return row; }
+ int getCol() { return col; }
+ OutputList *outputList() { return ol; }
+
+ private:
+ OutputList *ol;
+ int row;
+ int col;
+};
+
+TableElem::TableElem(int r,int c)
+{
+ //printf("TableElem::TableElem(%d,%d)\n",r,c);
+ ol=new OutputList(outDoc);
+ outDoc=ol;
+ row=r;
+ col=c;
+}
+
+TableElem::~TableElem()
+{
+ //printf("TableElem::~TableElem(%d,%d)\n",row,col);
+ delete ol;
+}
+
+class Table
+{
+ public:
+ Table();
+ ~Table();
+ void newRow();
+ void newElem();
+
+ private:
+ OutputList *parentDoc;
+ QList<TableElem> *elemList;
+ int curRow;
+ int curCol;
+ int rows;
+ int cols;
+};
+
+Table::Table()
+{
+ parentDoc=outDoc;
+ elemList=new QList<TableElem>;
+ elemList->setAutoDelete(TRUE);
+ curRow=curCol=rows=cols=0;
+}
+
+Table::~Table()
+{
+ //printf("Table::~Table()\n");
+ // use elemList & cols & rows
+ if (cols>0 && rows>0)
+ {
+ parentDoc->startTable(cols);
+ TableElem *e=elemList->first();
+ while (e)
+ {
+ if (e->getRow()>0)
+ {
+ if (e->getCol()==0)
+ {
+ if (e->getRow()>1) parentDoc->endTableRow();
+ parentDoc->nextTableRow();
+ }
+ else
+ {
+ parentDoc->nextTableColumn();
+ }
+ *parentDoc+=*e->outputList();
+ parentDoc->endTableColumn();
+ }
+ e=elemList->next();
+ }
+ parentDoc->endTable();
+ }
+ delete elemList;
+ outDoc=parentDoc;
+}
+
+void Table::newRow()
+{
+ //printf("Table::newRow()\n");
+ curRow++;
+ if (curRow>rows) rows=curRow;
+ curCol=0;
+}
+
+void Table::newElem()
+{
+ //printf("Table::newElem(%d,%d)\n",curRow,curCol);
+ TableElem *te = new TableElem(curRow,curCol);
+ elemList->append(te);
+
+ curCol++;
+ if (curCol>cols) cols=curCol;
+}
+
+static QStack<Table> tableStack;
+static Table *curTable;
+
+static void startTable()
+{
+ //printf("startTable()\n");
+ curTable=new Table;
+ tableStack.push(curTable);
+}
+
+static void endTable()
+{
+ //printf("endTable()\n");
+ delete tableStack.pop(); // the destructor adds the table to the stream!
+ curTable=tableStack.top();
+}
+
+//-----------------------------------------------------------------------------
+
+static void lineCount()
+{
+ for( const char* c = yytext ; *c ; ++c )
+ yyLineNr += (*c == '\n') ;
+}
+
+static void endArgumentList()
+{
+ if (insideArgumentList)
+ {
+ insideArgumentList=FALSE;
+ outDoc->endItemList();
+ }
+}
+
+static void addType( Entry* current )
+{
+ if( current->type.length() )
+ current->type += ' ' ;
+ current->type += current->name ;
+ current->name.resize(0) ;
+ if( current->type.length() )
+ current->type += ' ' ;
+ current->type += current->args ;
+ current->args.resize(0) ;
+ current->argList->clear();
+}
+
+static void includeFile(OutputList &ol,const char *fileName,bool quiet)
+{
+ //FileInfo *f;
+ bool ambig;
+ FileDef *fd;
+ if ((fd=findFileDef(&exampleNameDict,fileName,ambig)))
+ {
+ currentIncludeFile=fileToString(fd->absFilePath());
+ includeFileOffset=0;
+ includeFileLength=currentIncludeFile.length();
+ OutputList codeFrag(&ol);
+ parseCode(codeFrag,0,currentIncludeFile,exampleDoc,exampleName);
+ if (!quiet)
+ {
+ ol.startCodeFragment();
+ ol+=codeFrag;
+ ol.endCodeFragment();
+ }
+ }
+ else if (ambig)
+ {
+ warn("Include file name %s is ambigious.\n",fileName);
+ warn("Possible candidates:\n");
+ //includeFileList.writeMatches(fileName);
+ showFileDefMatches(&exampleNameDict,fileName);
+ }
+ else
+ {
+ warn("Warning: example file %s is not found. ",fileName);
+ warn("Check your EXAMPLE_PATH\n");
+ }
+}
+
+static void verbIncludeFile(OutputList &ol,const char *name)
+{
+ //FileInfo *f;
+ bool ambig;
+ FileDef *fd;
+ if ((fd=findFileDef(&exampleNameDict,name,ambig)))
+ {
+ ol.startCodeFragment();
+ ol.codify(fileToString(fd->absFilePath()));
+ ol.endCodeFragment();
+ }
+ else if (ambig)
+ {
+ warn("Include file name %s is ambigious.\n",name);
+ warn("Possible candidates:\n");
+ showFileDefMatches(&exampleNameDict,name);
+ }
+ else
+ {
+ warn("Warning: example file %s is not found. ",name);
+ warn("Check your EXAMPLE_PATH\n");
+ }
+}
+
+
+static QString stripQuotes(const char *s)
+{
+ QString name;
+ if (s==0 || *s==0) return name;
+ name=s;
+ if (name.at(0)=='"' && name.at(name.length()-1)=='"')
+ {
+ name=name.mid(1,name.length()-2);
+ }
+ return name;
+}
+
+static QString stripKnownExtensions(const char *text)
+{
+ QString result=text;
+ if (result.right(4)==".tex") result=result.left(result.length()-4);
+ else if (result.right(5)==".html") result=result.left(result.length()-5);
+ //printf("%s stripKnowExtensions(%s)\n",result.data(),text);
+ return result;
+}
+
+static void skipLine(OutputList &ol,const char *key)
+{
+ bool found=FALSE;
+ while (!found)
+ {
+ QString s;
+ char c;
+ while ( includeFileOffset<includeFileLength &&
+ (c=currentIncludeFile[includeFileOffset++])!='\n' && c!=0
+ ) s+=c;
+ if (s.find(key)!=-1)
+ {
+ found=TRUE;
+ ol.writeString(" ");
+ parseCode(ol,className,s,exampleDoc,exampleName);
+ ol.writeString("\n");
+ }
+ else if (includeFileOffset==includeFileLength) found=TRUE;
+ }
+}
+
+static void skipUntil(const char *key)
+{
+ bool found=FALSE;
+ while (!found)
+ {
+ QString s;
+ int i=includeFileOffset;
+ char c;
+ while ( i<includeFileLength &&
+ (c=currentIncludeFile[i++])!='\n' && c!=0
+ ) s+=c;
+ if (s.find(key)!=-1 || i==includeFileLength)
+ {
+ found=TRUE;
+ }
+ else
+ {
+ includeFileOffset=i;
+ }
+ }
+}
+
+static void showLine(OutputList &ol,const char *key)
+{
+ QString s;
+ char c;
+ bool found=FALSE;
+ while (!found)
+ {
+ while ( includeFileOffset<includeFileLength &&
+ (c=currentIncludeFile[includeFileOffset++])!='\n' && c!=0
+ ) s+=c;
+ if (s.stripWhiteSpace().length()>0 ||
+ includeFileOffset==includeFileLength) found=TRUE;
+ }
+ if (s.find(key)!=-1)
+ {
+ ol.writeString(" ");
+ parseCode(ol,className,s,exampleDoc,exampleName);
+ ol.writeString("\n");
+ }
+}
+
+static void showUntil(OutputList &ol,const char *key)
+{
+ bool found=FALSE;
+ while (!found)
+ {
+ QString s;
+ char c;
+ while ( includeFileOffset<includeFileLength &&
+ (c=currentIncludeFile[includeFileOffset++])!='\n' && c!=0
+ ) s+=c;
+ if (s.stripWhiteSpace().length()>0)
+ {
+ ol.writeString(" ");
+ parseCode(ol,className,s,exampleDoc,exampleName);
+ ol.writeString("\n");
+ if (s.find(key)!=-1) found=TRUE;
+ }
+ if (includeFileOffset==includeFileLength) found=TRUE;
+ }
+}
+
+static void newDocState();
+
+//-----------------------------------------------------------------
+
+static bool inBlock()
+{
+ return inParamBlock || inSeeBlock || inReturnBlock || inAuthorBlock ||
+ inVersionBlock || inDateBlock || inWarningBlock || inBugBlock ||
+ inParBlock || inExceptionBlock;
+}
+
+static void endBlock()
+{
+ outDoc->endDescList();
+ inParamBlock=inSeeBlock=inReturnBlock=inAuthorBlock=
+ inVersionBlock=inDateBlock=inBugBlock=inWarningBlock=
+ inParBlock=inExceptionBlock=FALSE;
+}
+
+static void addSection()
+{
+ //printf("New section pageName=%s label=%s title=%s\n",
+ // current->name.data(),sectionLabel.data(),sectionTitle.data());
+ SectionInfo *si=new SectionInfo(current->name,
+ sectionLabel,sectionTitle,isSubsection);
+ sectionDict.insert(sectionLabel,si);
+}
+
+
+// Adds a formula text to the list/dictionary of formulas if it was
+// not already added. Returns the label of the formula.
+static QString addFormula()
+{
+ QString formLabel;
+ QString fText=formulaText.simplifyWhiteSpace();
+ Formula *f=0;
+ if ((f=formulaDict[fText])==0)
+ {
+ f = new Formula(fText);
+ formulaList.append(f);
+ formulaDict.insert(fText,f);
+ formLabel.sprintf("\\form#%d",f->getId());
+ formulaNameDict.insert(formLabel,f);
+ }
+ else
+ {
+ formLabel.sprintf("\\form#%d",f->getId());
+ }
+ return formLabel;
+}
+
+/* -----------------------------------------------------------------
+ */
+#undef YY_INPUT
+#define YY_INPUT(buf,result,max_size) result=yyread(buf,max_size);
+
+static int yyread(char *buf,int max_size)
+{
+ int c=0;
+ while( c < max_size && inputString[inputPosition] )
+ {
+ *buf = inputString[inputPosition++] ;
+ //printf("%d (%c)\n",*buf,*buf);
+ c++; buf++;
+ }
+ return c;
+}
+
+//ATTR ((({BN}+[^\>]+)/">")?)
+%}
+
+BN [ \t\n\r]
+BL [ \t\r]*"\n"
+B [ \t]
+BS ^(({B}*"//")?)(({B}*"*"+)?){B}*
+FILE ([a-z_A-Z0-9\.\\:\/\-\+]+)|("\""[^\n\"]+"\"")
+FILEMASK [a-z_A-Z0-9\.\\:\/\-\+]+"."[a-z_A-Z0-9\.\-\+]*[a-z_A-Z0-9\-\+]
+ID [a-z_A-Z][a-z_A-Z0-9]*
+SCOPEID {ID}({ID}*{BN}*"::"{BN}*)*({ID}?)
+SCOPENAME (({ID}?{BN}*"::"{BN}*)*)((~{BN}*)?{ID})
+SCOPEMASK {ID}?(("::"|"#")?(~)?{ID})+
+URLMASK [a-z_A-Z0-9\~\:\@\#\.\-\+\/]+
+ATTR ({B}+[^>\n]*)?
+A [aA]
+BOLD [bB]
+BODY [bB][oO][dD][yY]
+BR [bB][rR]
+EM [eE][mM]
+CENTER [cC][eE][nN][tT][eE][rR]
+CODE [cC][oO][dD][eE]
+DL [dD][lL]
+DD [dD][dD]
+DT [dD][tT]
+DFN [dD][fF][nN]
+FORM [fF][oO][rR][mM]
+H1 [hH]1
+H2 [hH]2
+H3 [hH][3-6]
+HEAD [hH][eE][aA][dD]
+HR [hH][rR]
+HREF [hH][rR][eE][fF]
+I [iI]
+IMG [iI][mM][gG]
+INPUT [iI][nN][pP][uU][tT]
+LI [lL][iI]
+META [mM][eE][tT][aA]
+MULTICOL [mM][uU][lL][tT][iI][cC][oO][lL]
+NAME [nN][aA][mM][eE]
+OL [oO][lL]
+P [pP]
+PRE [pP][rR][eE]
+SMALL [sS][mM][aA][lL][lL]
+STRONG [sS][tT][rR][oO][nN][gG]
+SUB [sS][uU][bB]
+SUP [sS][uU][pP]
+SRC [sS][rR][cC]
+TABLE [tT][aA][bB][lL][eE]
+TITLE [tT][iI][tT][lL][eE]
+TD [tT][dD]
+TR [tT][rR]
+TT [tT][tT]
+UL [uU][lL]
+VAR [vV][aA][rR]
+
+%x Define
+%x DefineArg
+%x DefineEnd
+%x Include
+%x ClassName
+%x ClassVar
+%x Bases
+%x NextSemi
+%x FindMembers
+%x FindMemberName
+%x FindFields
+%x FindFieldArg
+%x Function
+%x FuncRound
+%x ExcpRound
+%x FuncQual
+%x Operator
+%x Array
+%x Curly
+%x Using
+%x NameSpaceDocArg1
+%x SkipCurly
+%x SkipCurlyCpp
+%x SkipString
+%x SkipInits
+%x SkipCPP
+%x SkipCPPBlock
+%x SkipComment
+%x SkipCxxComment
+%x SkipBlock
+%x SkipCode
+%x Sharp
+%x SkipSharp
+%x SkipRound
+%x TypedefName
+%x Comment
+%x Doc
+%x JavaDoc
+%x ClassDoc
+%x LineDoc
+%x DefLineDoc
+%x ClassDocArg1
+%x ClassDocArg2
+%x ClassDocArg3
+%x ClassDocFunc
+%x ClassDocFuncPtr
+%x ClassDocFuncQual
+%x ClassDocFuncExc
+%x ClassDocDefine
+%x ClassDocRelates
+%x ClassDocBrief
+%x ClassDocOverload
+%x ClassDefineArgs
+%x GroupDocArg1
+%x GroupDocArg2
+%x GroupName
+%x AfterDoc
+%x AfterDocBrief
+%x AfterDocLine
+%x PageDoc
+%x PageDocTitle
+%x PageDocArg1
+%x PageDocArg2
+%x FileDocArg1
+%x FileDocArg2
+%x ExampleDoc
+%x ExampleDocArg1
+%x EnumDoc
+%x EnumDocArg1
+%x FuncPtr
+%x EndFuncPtr
+%x FuncFunc
+%x FuncFuncEnd
+%x FuncFuncType
+%x MemberSpec
+%x MemberSpecSkip
+%x SkipVerbatim
+%x DocScan
+%x DocParam
+%x DocException
+%x DocHtmlScan
+%x DocLatexScan
+%x DocEmphasis
+%x DocBold
+%x DocCode
+%x DocCodeBlock
+%x DocInternal
+%x DocLink
+%x DocLinkText
+%x DocSkipWord
+%x DocInclude
+%x DocDontInclude
+%x DocDescItem
+%x DocHtmlLink
+%x DocHtmlAnchor
+%x DocHtmlHref1
+%x DocHtmlHref2
+%x DocBaseClass
+%x DocSkiplineKey
+%x DocSkipKey
+%x DocLineKey
+%x DocUntilKey
+%x DocKeyEnd
+%x DocPar
+%x DocRefName
+%x DocVerbatim
+%x DocVerbInc
+%x DocIndexWord
+%x DocRef
+%x DocRefItem
+%x DocRefItemName
+%x SectionLabel
+%x SectionTitle
+%x EndTemplate
+%x CopyArgString
+%x CopyArgRound
+%x CopyArgSharp
+%x ReadFuncArgType
+%x ReadTempArgs
+%x Specialization
+%x DocSkipHtmlComment
+%x ReadFormulaShort
+%x ReadFormulaLong
+
+%%
+
+<*>\x06[^\x06]*\x06 { // new file
+ yyLineNr= 1 ;
+ int i;
+ for( i = 0 ; yytext[i+1] != 6 ; i++ )
+ yyFileName[i] = yytext[i+1] ;
+ yyFileName[i] = 0 ;
+ msg("Parsing file %s...\n",yyFileName);
+ current_root = global_root ;
+ initParser();
+ current->reset();
+ int sec=guessSection(yyFileName);
+ if (sec)
+ {
+ current->name = yyFileName;
+ current->name = current->name;
+ current->section = sec;
+ current_root->addSubEntry(current);
+ current = new Entry;
+ }
+ BEGIN( FindMembers );
+ }
+<*>\x0d
+ /*
+<DocScan>^{BL} {
+ if (insideArgumentList)
+ {
+ insideArgumentList=FALSE;
+ outDoc->endItemList();
+ }
+ else
+ {
+ outDoc->newParagraph();
+ }
+ if (inBlock()) endBlock();
+ }
+ */
+<DocScan>"<!--" { BEGIN(DocSkipHtmlComment); }
+<DocSkipHtmlComment>"--"[!]?">" { BEGIN(DocScan); }
+<DocSkipHtmlComment>.
+<DocScan>"&copy;" { outDoc->writeCopyright(); }
+<DocScan>"&quot;" { outDoc->writeQuote(); }
+<DocScan>"&"[AEIOUYaeiouy]"uml;" { outDoc->writeUmlaut(yytext[1]); }
+<DocScan>"&"[AEIOUYaeiouy]"acute;" { outDoc->writeAcute(yytext[1]); }
+<DocScan>"&"[AEIOUaeiou]"grave;" { outDoc->writeGrave(yytext[1]); }
+<DocScan>"&"[AEIOUaeiou]"circ;" { outDoc->writeCirc(yytext[1]); }
+<DocScan>"&"[ANOano]"tilde;" { outDoc->writeTilde(yytext[1]); }
+<DocScan,DocHtmlScan,DocLatexScan>"$("[a-z_A-Z]+")" {
+ QString envvar=&yytext[2];
+ envvar=envvar.left(envvar.length()-1);
+ outDoc->docify(getenv(envvar));
+ }
+<DocScan>("\\"|"@")"htmlonly"/[^a-z_A-Z0-9] {
+ outDoc->disableAllBut(OutputGenerator::Html);
+ BEGIN(DocHtmlScan);
+ }
+<DocHtmlScan>("\\"|"@")"endhtmlonly"/[^a-z_A-Z0-9] {
+ outDoc->enableAll();
+ BEGIN(DocScan);
+ }
+<DocScan>("\\"|"@")"latexonly"/[^a-z_A-Z0-9] {
+ outDoc->disableAllBut(OutputGenerator::Latex);
+ BEGIN(DocLatexScan);
+ }
+<DocHtmlScan,DocLatexScan>"//"|"/*"|"*/" {
+ outDoc->writeString(yytext);
+ }
+<DocHtmlScan,DocLatexScan>. {
+ char c[2];
+ c[0]=*yytext;c[1]='\0';
+ outDoc->writeString(c);
+ }
+<DocLatexScan>("\\"|"@")"endlatexonly"/[^a-z_A-Z0-9] {
+ outDoc->enableAll();
+ BEGIN(DocScan);
+ }
+<DocScan>"\\postheader"/{BN}
+<DocScan>"\\functionindex"/{BN} { writeMemberList(*outDoc); }
+<DocScan>"\\classhierarchy"/{BN} { writeClassHierarchy(*outDoc); }
+<DocScan>"\\annotatedclasslist"/{BN} { writeAnnotatedClassList(*outDoc); }
+<DocScan>"\\headerfilelist"/{BN} { /*TODO: fix this writeHeaderFileList(*outDoc); */ }
+<DocScan>"\\header"/{BN} { BEGIN( DocSkipWord ); }
+<DocScan>"\\define"/{BN} { BEGIN( DocSkipWord ); }
+<DocScan>("\\"|"@")"verbinclude"/{BN} { BEGIN( DocVerbInc ); }
+<DocVerbInc>{FILE} {
+ verbIncludeFile(*outDoc,stripQuotes(yytext));
+ BEGIN( DocScan );
+ }
+<DocScan>("\\"|"@")"verbatim"/[^a-z_A-Z0-9] {
+ outDoc->startCodeFragment();
+ BEGIN(DocVerbatim);
+ }
+<DocVerbatim>("\\"|"@")"endverbatim"/[^a-z_A-Z0-9] {
+ outDoc->endCodeFragment();
+ BEGIN(DocScan);
+ }
+<DocVerbatim>[^\n\\]*"\n" {
+ //printf("docifying: %s\n",yytext);
+ outDoc->codify(yytext);
+ }
+<DocVerbatim>"\n"|"//"|"/*"|"*/" {
+ outDoc->codify(yytext);
+ }
+<DocVerbatim>. {
+ //printf("char %c\n",*yytext);
+ char c[2];c[0]=*yytext;c[1]='\0';
+ outDoc->codify(c);
+ }
+<DocScan>("\\"|"@")"internal"/{BN} {
+ if (!internalDocsFlag)
+ {
+ outDoc->newParagraph();
+ scanString(theTranslator->trForInternalUseOnly()+"\n");
+ //outDoc->writeString("For internal use only.\n");
+ BEGIN( DocInternal );
+ }
+ }
+<DocScan>"\\reimp"/{BN} {
+ outDoc->newParagraph();
+ scanString(theTranslator->trReimplementedForInternalReasons()+"\n");
+ }
+<DocScan>("\\"|"@")"link"/{BN} { BEGIN( DocLink ); }
+<DocSkipWord>[a-z_A-Z0-9.:()]+ { BEGIN( DocScan ); }
+<DocLink>[a-z_A-Z0-9:#.~/()\-\+]+ {
+ linkRef = stripKnownExtensions(yytext);
+ linkText = "";
+ BEGIN( DocLinkText );
+ }
+<DocLinkText>. { linkText += *yytext; }
+<DocLinkText>"\n" { linkText += " "; }
+<DocLink,DocLinkText>("\\"|"@")"endlink"/[^a-z_A-Z0-9] { // <- needed for things like \endlink.
+ generateLink(*outDoc,className,linkRef,inSeeBlock,linkText);
+ BEGIN( DocScan );
+ }
+<DocScan>"@ref"{B}+ {
+ BEGIN(DocRef);
+ }
+<DocRef>{SCOPENAME} {
+ generateLink(*outDoc,className,yytext,TRUE,0);
+ BEGIN( DocScan );
+ }
+<DocScan>("\\"|"@")"endlink"/[^a-z_A-Z0-9] { warn("Warning: \\endlink without \\link "
+ "in documentation of %s\n", refName.data());
+ }
+<DocScan>("\\"|"@")"addindex"/{BN} {
+ BEGIN(DocIndexWord);
+ }
+<DocScan>"\\form#"[0-9]+ {
+ Formula *formula=formulaNameDict[yytext];
+ if (formula)
+ {
+ QString formName;
+ formName.sprintf("form-%d.gif",formula->getId());
+ outDoc->writeFormula(formName,formula->getFormulaText());
+ }
+ }
+<DocIndexWord>[^\n\t ]+ {
+ //printf("Adding %s to index\n",yytext);
+ outDoc->addToIndex(yytext,0);
+ BEGIN(DocScan);
+ }
+<DocScan>("\\"|"@")"arg"{BN}+ {
+ if (insideArgumentList)
+ {
+ outDoc->writeListItem();
+ }
+ else
+ {
+ outDoc->startItemList();
+ outDoc->writeListItem();
+ insideArgumentList=TRUE;
+ }
+ }
+<DocScan>("\\"|"@")"par"{B}+ {
+ BEGIN(DocPar);
+ }
+<DocPar>[^\n]*{BN}+ {
+ endArgumentList();
+ if (inBlock()) endBlock();
+ inParBlock=TRUE;
+ outDoc->startDescList();
+ outDoc->startBold();
+ outDoc->docify(((QString)yytext).stripWhiteSpace());
+ outDoc->endBold();
+ outDoc->endDescTitle();
+ outDoc->writeDescItem();
+ BEGIN(DocScan);
+ }
+<DocScan>("\\"|"@")"warning"{BN}+ {
+ endArgumentList();
+ if (!inWarningBlock)
+ {
+ if (inBlock()) endBlock();
+ inWarningBlock=TRUE;
+ outDoc->startDescList();
+ //outDoc->writeBoldString("Warning: ");
+ outDoc->startBold();
+ scanString(theTranslator->trWarning()+": ");
+ outDoc->endBold();
+ outDoc->endDescTitle();
+ outDoc->writeDescItem();
+ }
+ else
+ {
+ outDoc->writeDescItem();
+ }
+ }
+<DocScan>("\\"|"@")"bug"{BN}+ {
+ endArgumentList();
+ if (!inBugBlock)
+ {
+ if (inBlock()) endBlock();
+ inBugBlock=TRUE;
+ outDoc->startDescList();
+ //outDoc->writeBoldString("Bugs and limitations: ");
+ outDoc->startBold();
+ scanString(theTranslator->trBugsAndLimitations()+": ");
+ outDoc->endBold();
+ outDoc->endDescTitle();
+ outDoc->writeDescItem();
+ }
+ else
+ {
+ outDoc->writeDescItem();
+ }
+ }
+<DocScan>("\\"|"@")"version"{BN}+ {
+ endArgumentList();
+ if (!inVersionBlock)
+ {
+ if (inBlock()) endBlock();
+ inVersionBlock=TRUE;
+ outDoc->startDescList();
+ //outDoc->writeBoldString("Version: ");
+ outDoc->startBold();
+ scanString(theTranslator->trVersion()+": ");
+ outDoc->endBold();
+ outDoc->endDescTitle();
+ outDoc->writeDescItem();
+ }
+ else
+ {
+ outDoc->writeDescItem();
+ }
+ }
+<DocScan>("\\"|"@")"date"{BN}+ {
+ endArgumentList();
+ if (!inDateBlock)
+ {
+ if (inBlock()) endBlock();
+ inDateBlock=TRUE;
+ outDoc->startDescList();
+ //outDoc->writeBoldString("Date: ");
+ outDoc->startBold();
+ scanString(theTranslator->trDate()+": ");
+ outDoc->endBold();
+ outDoc->endDescTitle();
+ outDoc->writeDescItem();
+ }
+ else
+ {
+ outDoc->writeDescItem();
+ }
+ }
+<DocScan>("\\"|"@")"author"{BN}+ {
+ endArgumentList();
+ if (!inAuthorBlock)
+ {
+ if (inBlock()) endBlock();
+ inAuthorBlock=TRUE;
+ outDoc->startDescList();
+ //outDoc->writeBoldString("Author(s): ");
+ outDoc->startBold();
+ scanString(theTranslator->trAuthors()+": ");
+ outDoc->endBold();
+ outDoc->endDescTitle();
+ outDoc->writeDescItem();
+ }
+ else
+ {
+ outDoc->docify(", ");
+ }
+ }
+<DocScan>("\\"|"@")"return"{BN}+ {
+ endArgumentList();
+ if (!inReturnBlock)
+ {
+ if (inBlock()) endBlock();
+ inReturnBlock=TRUE;
+ outDoc->startDescList();
+ //outDoc->writeBoldString("Returns: ");
+ outDoc->startBold();
+ scanString(theTranslator->trReturns()+": ");
+ outDoc->endBold();
+ outDoc->endDescTitle();
+ outDoc->writeDescItem();
+ }
+ }
+<DocScan>("\\sa"|"@see"){BN}+ {
+ endArgumentList();
+ if (!inSeeBlock)
+ {
+ if (inBlock()) endBlock();
+ inSeeBlock=TRUE;
+ //firstSeeArg=TRUE;
+ //javaDocSee=!strcmp(yytext,"@see");
+ outDoc->startDescList();
+ //outDoc->writeBoldString("See also: ");
+ outDoc->startBold();
+ scanString(theTranslator->trSeeAlso()+": ");
+ outDoc->endBold();
+ outDoc->endDescTitle();
+ outDoc->writeDescItem();
+ }
+ else
+ {
+ outDoc->docify(", ");
+ }
+ }
+<DocScan>("\\"|"@")"param"{BN}+ {
+ endArgumentList();
+ if (!inParamBlock)
+ {
+ if (inBlock()) endBlock();
+ inParamBlock=TRUE;
+ outDoc->startDescList();
+ //outDoc->writeBoldString("Parameters: ");
+ outDoc->startBold();
+ scanString(theTranslator->trParameters()+": ");
+ outDoc->endBold();
+ outDoc->endDescTitle();
+ }
+ BEGIN(DocParam);
+ }
+<DocScan>("\\"|"@")"exception"{BN}+ {
+ endArgumentList();
+ if (!inExceptionBlock)
+ {
+ if (inBlock()) endBlock();
+ inExceptionBlock=TRUE;
+ outDoc->startDescList();
+ //outDoc->writeBoldString("Exceptions: ");
+ outDoc->startBold();
+ scanString(theTranslator->trExceptions()+": ");
+ outDoc->endBold();
+ outDoc->endDescTitle();
+ }
+ BEGIN(DocException);
+ }
+<DocScan>"\\capt".*
+<DocParam>{SCOPENAME} {
+ outDoc->writeDescItem();
+ outDoc->startEmphasis();
+ outDoc->docify(yytext);
+ outDoc->endEmphasis();
+ outDoc->docify(" - ");
+ BEGIN(DocScan);
+ }
+<DocException>{SCOPENAME} {
+ outDoc->writeDescItem();
+ outDoc->startEmphasis();
+ outDoc->docify(yytext);
+ outDoc->endEmphasis();
+ outDoc->docify(" - ");
+ BEGIN(DocScan);
+ }
+<DocScan>("\\"|"@")"section "{ID}"\n" {
+ QString secName=&yytext[9]; // skip "\section "
+ secName=secName.left(secName.length()-1); // remove \n
+ //printf("SectionName %s found\n",secName.data());
+ SectionInfo *sec;
+ if ((sec=sectionDict[secName]))
+ {
+ //printf("Title %s\n",sec->title.data());
+ outDoc->writeSection(sec->label,sec->title,sec->isSubsection);
+ }
+ }
+<DocScan>"\\ref" {
+ BEGIN(DocRefName);
+ }
+<DocScan>"\\refitem" {
+ BEGIN(DocRefItem);
+ }
+<DocRefName>{ID} {
+ QString ref=yytext;
+ SectionInfo *sec;
+ if ((sec=sectionDict[ref]))
+ {
+ outDoc->writeSectionRef(sec->pageName,sec->label,sec->title);
+ }
+ else
+ {
+ warn("Warning: reference to unknown section %s!\n",yytext);
+ outDoc->writeBoldString("unknown reference!");
+ }
+ BEGIN(DocScan);
+ }
+<DocRefItem>{ID} {
+ sectionRef=yytext;
+ BEGIN(DocRefItemName);
+ }
+<DocRefItemName>.*/"\n" {
+ SectionInfo *sec;
+ if ((sec=sectionDict[sectionRef]))
+ {
+ outDoc->writeSectionRefItem(sec->pageName,sec->label,yytext);
+ }
+ else
+ {
+ warn("Warning: reference to unknown section %s!\n",sectionRef.data());
+ outDoc->writeBoldString("unknown reference!");
+ }
+ BEGIN(DocScan);
+ }
+<DocScan>("\\"|"@")"code"/{BN}+ {
+ outDoc->startCodeFragment();
+ codeBlock.resize(0);
+ BEGIN( DocCodeBlock );
+ }
+<DocScan>("\\"|"@")"endcode"/[^a-z_A-Z0-9] {
+ warn("Warning: \\endcode without <PRE> or \\code "
+ "in the documentation of %s\n",refName.data());
+ }
+<DocScan>{SCOPEMASK}"("[a-z_A-Z,\<\> \t\*\&]+")" {
+ generateRef(*outDoc,className,yytext,inSeeBlock);
+ }
+<DocScan>{SCOPEMASK}(("()")?) {
+ generateRef(*outDoc,className,yytext,inSeeBlock);
+ }
+<DocScan>({SCOPEMASK}"::")?"operator"[^(\r\n.,]*"("[a-z_A-Z,\<\> \t\*\&]*")" {
+ QString oName=yytext;
+ generateRef(*outDoc,className,
+ removeRedundantWhiteSpace(oName),inSeeBlock);
+ }
+<DocScan>({SCOPEMASK}"::")?"operator()("[a-z_A-Z,\<\> \t\*\&]*")" {
+ QString oName=yytext;
+ generateRef(*outDoc,className,
+ removeRedundantWhiteSpace(oName),inSeeBlock);
+ }
+<DocScan>{FILEMASK} {
+ generateFileRef(*outDoc,yytext);
+ }
+<DocCodeBlock>{BN}*("\\"|"@")"endcode"/[^a-z_A-Z0-9] { // needed to match things like \endcode. (note the dot)
+ parseCode(*outDoc,className,codeBlock,exampleDoc,exampleName);
+ //printf("Code block\n-------------\n%s\n--------------\n",codeBlock.data());
+ outDoc->endCodeFragment();
+ BEGIN( DocScan );
+ }
+<DocCodeBlock>"</"{PRE}{ATTR}">" {
+ parseCode(*outDoc,className,codeBlock,exampleDoc,exampleName);
+ //printf("Code block\n-------------\n%s\n--------------\n",codeBlock.data());
+ outDoc->endCodeFragment();
+ BEGIN( DocScan );
+ }
+<DocScan>("\\"|"@")"e"{BN}+ { BEGIN( DocEmphasis ); }
+<DocScan>("\\"|"@")"a"{BN}+ { BEGIN( DocEmphasis ); }
+<DocScan>("\\"|"@")"b"{BN}+ { BEGIN( DocBold ); }
+<DocScan>("\\"|"@")"c"{BN}+ { BEGIN( DocCode ); }
+<DocScan>("\\"|"@")"l"{BN}+
+<DocScan>("\\"|"@")"include"{BN}+ { BEGIN( DocInclude ); }
+<DocScan>("\\"|"@")"dontinclude"{BN}+ { BEGIN( DocDontInclude ); }
+<DocScan>("\\"|"@")"skip"{BN}+ { BEGIN( DocSkipKey ); }
+<DocScan>("\\"|"@")"skipline"{BN}+ { BEGIN( DocSkiplineKey ); firstLine=TRUE; }
+<DocScan>("\\"|"@")"line"{BN}+ { BEGIN( DocLineKey ); firstLine=TRUE; }
+<DocScan>("\\"|"@")"until"{BN}+ { BEGIN( DocUntilKey ); firstLine=TRUE; }
+<DocSkipKey>[^ \t\r\n]+ {
+ if (includeFileLength>0)
+ skipUntil(yytext);
+ BEGIN( DocScan );
+ }
+<DocLineKey>[^ \t\r\n]+ {
+ if (includeFileLength>0)
+ {
+ if (firstLine) outDoc->startCodeFragment();
+ firstLine=FALSE;
+ showLine(*outDoc,yytext);
+ BEGIN( DocKeyEnd );
+ }
+ else
+ {
+ BEGIN( DocScan );
+ }
+ }
+<DocSkiplineKey>[^ \t\r\n]+ {
+ if (includeFileLength>0)
+ {
+ if (firstLine) outDoc->startCodeFragment();
+ firstLine=FALSE;
+ skipLine(*outDoc,yytext);
+ BEGIN( DocKeyEnd );
+ }
+ else
+ {
+ BEGIN( DocScan );
+ }
+ }
+<DocUntilKey>[^ \t\r\n]+ {
+ if (includeFileLength>0)
+ {
+ if (firstLine) outDoc->startCodeFragment();
+ firstLine=FALSE;
+ showUntil(*outDoc,yytext);
+ BEGIN( DocKeyEnd );
+ }
+ else
+ {
+ BEGIN( DocScan );
+ }
+ }
+<DocKeyEnd>("\\"|"@")"line"{BN}+ { BEGIN(DocLineKey); }
+<DocKeyEnd>("\\"|"@")"until"{BN}+ { BEGIN(DocUntilKey); }
+<DocKeyEnd>("\\"|"@")"skipline"{BN}+ { BEGIN(DocSkiplineKey); }
+<DocKeyEnd>\n
+<DocKeyEnd>. {
+ unput(*yytext);
+ if (!firstLine) outDoc->endCodeFragment();
+ BEGIN( DocScan );
+ }
+<DocScan>"<"{MULTICOL}{ATTR}">"
+<DocScan>"</"{MULTICOL}{ATTR}">"
+<DocScan>"<"{STRONG}{ATTR}">" { outDoc->startBold(); }
+<DocScan>"</"{STRONG}{ATTR}">" { outDoc->endBold(); }
+<DocScan>"<"{CENTER}{ATTR}">" { outDoc->startCenter(); }
+<DocScan>"</"{CENTER}{ATTR}">" { outDoc->endCenter(); }
+<DocScan>"<"{TABLE}{ATTR}">" {
+ startTable();
+ /*outDoc->startTable();*/ }
+<DocScan>"</"{TABLE}{ATTR}">" {
+ endTable();
+ /*outDoc->endTable();*/
+ }
+<DocScan>"<"{INPUT}{ATTR}">"
+<DocScan>"<"{SMALL}{ATTR}">" { outDoc->startSmall(); }
+<DocScan>"</"{SMALL}{ATTR}">" { outDoc->endSmall(); }
+<DocScan>"<"{META}{ATTR}">"
+<DocScan>"<"{FORM}{ATTR}">"
+<DocScan>"</"{FORM}{ATTR}">"
+<DocScan>"<"{HEAD}{ATTR}">"
+<DocScan>"</"{HEAD}{ATTR}">"
+<DocScan>"<"{BODY}{ATTR}">"
+<DocScan>"</"{BODY}{ATTR}">"
+<DocScan>"<"{CODE}{ATTR}">" { outDoc->startTypewriter(); }
+<DocScan>"</"{CODE}{ATTR}">" { outDoc->endTypewriter(); }
+<DocScan>"<"{DFN}{ATTR}">" { outDoc->startTypewriter(); }
+<DocScan>"</"{DFN}{ATTR}">" { outDoc->endTypewriter(); }
+<DocScan>"<"{VAR}{ATTR}">" { outDoc->startEmphasis(); }
+<DocScan>"</"{VAR}{ATTR}">" { outDoc->endEmphasis(); }
+<DocScan>"<"{IMG}{ATTR}">" { outDoc->disableAllBut(OutputGenerator::Html);
+ outDoc->writeString(yytext);
+ outDoc->enableAll();
+ }
+<DocScan>"<"{PRE}{ATTR}">" {
+ outDoc->startCodeFragment();
+ codeBlock.resize(0);
+ BEGIN( DocCodeBlock );
+ }
+<DocScan>"</"{PRE}{ATTR}">" {
+ warn("Warning: </PRE> without <PRE> or \\code"
+ "in the documentation of %s\n",refName.data());
+ }
+<DocScan>"<"{SUB}{ATTR}">" { outDoc->startSubscript(); }
+<DocScan>"</"{SUB}{ATTR}">" { outDoc->endSubscript(); }
+<DocScan>"<"{SUP}{ATTR}">" { outDoc->startSuperscript(); }
+<DocScan>"</"{SUP}{ATTR}">" { outDoc->endSuperscript(); }
+<DocScan>"<"{TR}{ATTR}">" { if (curTable) curTable->newRow(); }
+<DocScan>"</"{TR}{ATTR}">"
+<DocScan>"<"{TD}{ATTR}">" { if (curTable) curTable->newElem(); }
+<DocScan>"</"{TD}{ATTR}">"
+<DocScan>"<"{OL}{ATTR}">" { outDoc->startEnumList(); }
+<DocScan>"</"{OL}{ATTR}">" { outDoc->endEnumList(); }
+<DocScan>"<"{UL}{ATTR}">" { outDoc->startItemList(); }
+<DocScan>"</"{UL}{ATTR}">" { outDoc->endItemList(); }
+<DocScan>"<"{LI}{ATTR}">" { outDoc->writeListItem(); }
+<DocScan>"</"{LI}{ATTR}">"
+<DocScan>"<"{TT}{ATTR}">" { outDoc->startTypewriter(); }
+<DocScan>"</"{TT}{ATTR}">" { outDoc->endTypewriter(); }
+<DocScan>"<"{EM}{ATTR}">" { outDoc->startEmphasis(); }
+<DocScan>"</"{EM}{ATTR}">" { outDoc->endEmphasis(); }
+<DocScan>"<"{HR}{ATTR}">" { outDoc->writeRuler(); }
+<DocScan>"<"{DL}{ATTR}">" { outDoc->startDescription(); }
+<DocScan>"</"{DL}{ATTR}">" { outDoc->endDescription(); }
+<DocScan>"<"{DT}{ATTR}">" { outDoc->startDescItem(); }
+<DocScan>"</"{DT}{ATTR}">"
+<DocScan>"<"{DD}{ATTR}">" { outDoc->endDescItem(); }
+<DocScan>"</"{DD}{ATTR}">"
+<DocScan>"<"{BR}{ATTR}">" { outDoc->lineBreak(); }
+<DocScan>"<"{I}{ATTR}">" { outDoc->startEmphasis(); }
+<DocScan>"</"{I}{ATTR}">" { outDoc->endEmphasis(); }
+<DocScan>"</"{A}{ATTR}">"
+<DocScan>"<"{A} { BEGIN(DocHtmlLink); }
+<DocScan>"<"{BOLD}{ATTR}">" { outDoc->startBold(); }
+<DocScan>"</"{BOLD}{ATTR}">" { outDoc->endBold(); }
+<DocScan>"<"{P}{ATTR}">" {
+ if (inBlock()) endBlock();
+ outDoc->newParagraph(); }
+<DocScan>"</"{P}{ATTR}">"
+<DocScan>"<"{H1}{ATTR}">" { outDoc->startTitle(); }
+<DocScan>"</"{H1}{ATTR}">" { outDoc->endTitle(); }
+<DocScan>"<"{H2}{ATTR}">" { outDoc->startSubsection(); }
+<DocScan>"</"{H2}{ATTR}">" { outDoc->endSubsection(); }
+<DocScan>"<"{H3}{ATTR}">" { outDoc->startSubsubsection(); }
+<DocScan>"</"{H3}{ATTR}">" { outDoc->endSubsubsection(); }
+<DocHtmlLink>{NAME}{BN}*"="{BN}*("\""?) { BEGIN(DocHtmlAnchor); }
+<DocHtmlAnchor>[a-z_A-Z0-9.\-\+\/]+ { outDoc->writeAnchor(yytext); }
+<DocHtmlLink>{HREF}{BN}*"="{BN}*("\""?) {
+ htmlUrl.resize(0);
+ htmlText.resize(0);
+ BEGIN(DocHtmlHref1); }
+<DocHtmlHref1>{URLMASK}+ {
+ htmlUrl=yytext;
+ }
+<DocHtmlHref1>">" { BEGIN(DocHtmlHref2); }
+<DocHtmlHref2>[^<]* { htmlText+=yytext; }
+ /*
+<DocHtmlHref2>\n { htmlText+='\n'; }
+ */
+<DocHtmlHref2>"<" {
+ outDoc->writeHtmlLink(htmlUrl,htmlText);
+ unput(*yytext);
+ BEGIN(DocScan);
+ }
+<DocHtmlLink,DocHtmlAnchor>">" { BEGIN(DocScan); }
+
+<DocScan>"\\\\" {
+ outDoc->docify("\\");
+ }
+<DocScan>"\\@" {
+ outDoc->docify("@");
+ }
+<DocScan>"\\<" {
+ outDoc->docify("<");
+ }
+<DocScan>"\\>" {
+ outDoc->docify(">");
+ }
+<DocScan>"\\&" {
+ outDoc->docify("&");
+ }
+<DocScan>"\\$" {
+ outDoc->docify("$");
+ }
+<DocScan>"\\#" {
+ outDoc->docify("#");
+ }
+<DocScan>"\\%" {
+ outDoc->docify("%");
+ }
+<DocScan>"%"[a-zA-Z_0-9\-]+ {
+ outDoc->docify(yytext+1);
+ }
+<DocEmphasis>[^ \t\n\r]+ {
+ outDoc->startEmphasis();
+ generateRef(*outDoc,className,yytext,inSeeBlock);
+ outDoc->endEmphasis();
+ BEGIN( DocScan );
+ //addToIndex(yytext);
+ }
+<DocBold>[^ \t\n\r]+ {
+ outDoc->startBold();
+ generateRef(*outDoc,className,yytext,inSeeBlock);
+ outDoc->endBold();
+ BEGIN( DocScan );
+ }
+<DocCode>[^ \t\n\r]+ {
+ outDoc->startTypewriter();
+ generateRef(*outDoc,className,yytext,inSeeBlock);
+ outDoc->endTypewriter();
+ BEGIN( DocScan );
+ }
+<DocInclude>{FILE} {
+ includeFile(*outDoc,stripQuotes(yytext),FALSE);
+ BEGIN( DocScan );
+ }
+<DocDontInclude>{FILE} {
+ includeFile(*outDoc,stripQuotes(yytext),TRUE);
+ BEGIN( DocScan );
+ }
+<DocCodeBlock>"//" { codeBlock += yytext; }
+<DocCodeBlock>"/*" { codeBlock += yytext; }
+<DocCodeBlock>\n { codeBlock += '\n'; }
+<DocCodeBlock>[^\/\\\<\n]* { codeBlock += yytext; }
+<DocCodeBlock>. { codeBlock += *yytext; }
+<DocCode,DocEmphasis,DocScan,DocBold>"//" {
+ outDoc->docify(yytext);
+ }
+<DocCode,DocEmphasis,DocScan,DocBold>"/*" {
+ outDoc->docify(yytext);
+ }
+<DocCode,DocEmphasis,DocBold>"\n" { outDoc->writeChar('\n'); }
+<DocScan>({B}*"\n"{B}*){2,} {
+ if (insideArgumentList)
+ {
+ insideArgumentList=FALSE;
+ outDoc->endItemList();
+ }
+ else
+ {
+ outDoc->newParagraph();
+ }
+ if (inBlock()) endBlock();
+ }
+<DocScan>{BN}+ {
+ outDoc->writeChar(' ');
+ }
+<DocCode,DocEmphasis,DocBold,DocScan>. {
+ outDoc->writeChar(*yytext);
+ }
+<NextSemi>"{" { BEGIN(SkipBlock); }
+<SkipBlock>"{" { ++bracketCount ; }
+<SkipBlock>"}" { if( bracketCount )
+ --bracketCount ;
+ else
+ BEGIN( NextSemi ) ;
+ }
+<NextSemi>\" {
+ lastStringContext=NextSemi;
+ BEGIN(SkipString);
+ }
+<NextSemi>[;,] {
+ unput(*yytext);
+ BEGIN( FindMembers ) ;
+ }
+<FindMembers>{B}*"signals"{BN}*":"{BN}* { current->sig = sig = TRUE;
+ current->slot = slot = FALSE;
+ current->protection = protection = Public ;
+ current->type.resize(0);
+ current->name.resize(0);
+ current->args.resize(0);
+ current->argList->clear();
+ lineCount() ;
+ }
+
+<FindMembers>{B}*"public"{BN}*"slots"{BN}*":"{BN}* {
+ current->protection = protection = Public ;
+ current->slot = slot = TRUE;
+ current->sig = sig = FALSE;
+ current->type.resize(0);
+ current->name.resize(0);
+ current->args.resize(0);
+ current->argList->clear();
+ lineCount();
+ }
+
+<FindMembers>{B}*"protected"{BN}*"slots"{BN}*":"{BN}* {
+ current->protection = protection = Protected ;
+ current->slot = slot = TRUE;
+ current->sig = sig = FALSE;
+ current->type.resize(0);
+ current->name.resize(0);
+ current->args.resize(0);
+ current->argList->clear();
+ lineCount();
+ }
+
+<FindMembers>{B}*"private"{BN}*"slots"{BN}*":"{BN}* {
+ current->protection = protection = Private ;
+ current->slot = slot = TRUE;
+ current->sig = sig = FALSE;
+ current->type.resize(0);
+ current->name.resize(0);
+ current->args.resize(0);
+ current->argList->clear();
+ lineCount();
+ }
+
+<FindMembers>{B}*"public"{BN}*":"{BN}* {
+ current->protection = protection = Public ;
+ current->slot = slot = FALSE;
+ current->sig = sig = FALSE;
+ current->type.resize(0);
+ current->name.resize(0);
+ current->args.resize(0);
+ current->argList->clear();
+ lineCount() ;
+ }
+<FindMembers>{B}*"protected"{BN}*":"{BN}* {
+ current->protection = protection = Protected ;
+ current->slot = slot = FALSE;
+ current->sig = sig = FALSE;
+ current->type.resize(0);
+ current->name.resize(0);
+ current->args.resize(0);
+ current->argList->clear();
+ lineCount() ;
+ }
+<FindMembers>{B}*"private"{BN}*":"{BN}* {
+ current->protection = protection = Private ;
+ current->slot = slot = FALSE;
+ current->sig = sig = FALSE;
+ current->type.resize(0);
+ current->name.resize(0);
+ current->args.resize(0);
+ current->argList->clear();
+ lineCount() ;
+ }
+ /*
+<FindMembers>"inline"
+ */
+<FindMembers>{B}*"static"{BN}+ { //current->type += " static ";
+ current->stat = TRUE;
+ lineCount();
+ }
+<FindMembers>{B}*"extern"{BN}+ {
+ current->stat = FALSE;
+ lineCount();
+ }
+<FindMembers>{B}*"virtual"{BN}+ { current->type += " virtual ";
+ current->virt = Virtual;
+ lineCount();
+ }
+<FindMembers>{B}*"inline"{BN}+ { lineCount(); }
+<FindMembers>{B}*"typename"{BN}+ { lineCount(); }
+<FindMembers>{B}*"namespace"{BN}+ {
+ isTypedef=FALSE;
+ current->section = Entry::NAMESPACE_SEC;
+ current->type = "namespace" ;
+ current->fileName = yyFileName;
+ current->startLine = yyLineNr;
+ lineCount();
+ BEGIN( ClassName );
+ }
+<FindMembers>{B}*(("typedef"{BN}+)?)"class"{BN}+ {
+ isTypedef=((QString)yytext).find("typedef")!=-1;
+ current->section = Entry::CLASS_SEC ;
+ addType( current ) ;
+ current->type += " class" ;
+ current->fileName = yyFileName;
+ current->startLine = yyLineNr;
+ lineCount() ;
+ BEGIN( ClassName ) ;
+ }
+<FindMembers>{B}*(("typedef"{BN}+)?)"struct"{BN}+ {
+ isTypedef=((QString)yytext).find("typedef")!=-1;
+ current->section = Entry::STRUCT_SEC ;
+ addType( current ) ;
+ current->type += " struct" ;
+ current->fileName = yyFileName;
+ current->startLine = yyLineNr;
+ lineCount() ;
+ BEGIN( ClassName ) ;
+ }
+<FindMembers>{B}*(("typedef"{BN}+)?)"union"{BN}+ {
+ isTypedef=((QString)yytext).find("typedef")!=-1;
+ current->section = Entry::UNION_SEC ;
+ addType( current ) ;
+ current->type += " union" ;
+ current->fileName = yyFileName;
+ current->startLine = yyLineNr;
+ lineCount() ;
+ BEGIN( ClassName ) ;
+ }
+<FindMembers>{B}*(("typedef"{BN}+)?)"enum"{BN}+ {
+ isTypedef=((QString)yytext).find("typedef")!=-1;
+ current->section = Entry::ENUM_SEC ;
+ addType( current ) ;
+ current->type += " enum" ;
+ current->fileName = yyFileName;
+ current->startLine = yyLineNr;
+ lineCount() ;
+ BEGIN( ClassName ) ;
+ }
+<Operator>"("{BN}*")"{BN}*/"(" {
+ lineCount();
+ current->name += yytext ;
+ current->name = current->name.simplifyWhiteSpace();
+ BEGIN( FindMembers ) ;
+ }
+<Operator>[^(] {
+ current->name += *yytext ;
+ }
+<Operator>"<>" { /* skip guided templ specifiers */ }
+<Operator>"(" {
+ current->name = current->name.simplifyWhiteSpace();
+ unput(*yytext);
+ BEGIN( FindMembers ) ;
+ }
+<FindMembers>"template"({BN}*)"<"/[>]? {
+ lineCount();
+ if (current->tArgList)
+ {
+ //printf("scanner.l current->tArgList->clear() %p\n",current->tArgList);
+ current->tArgList->clear();
+ }
+ else
+ {
+ current->tArgList = new ArgumentList;
+ current->tArgList->setAutoDelete(TRUE);
+ //printf("scanner.l new tArgList %p\n",current->tArgList);
+ }
+ templateStr="<";
+ copyArgString=&templateStr;
+ currentArgumentContext = FindMembers;
+ //printf("Start template list\n");
+ BEGIN( ReadTempArgs );
+ }
+ /*
+<FindMembers>({ID}{BN}*"::")*{BN}*"operator"{BN}*[<=]+ {
+ lineCount();
+ addType( current );
+ current->name = yytext;
+ }
+<FindMembers>"operator"{BN}*"/"[=]?/[^/ *] { space added!
+ lineCount();
+ addType( current );
+ current->name = yytext;
+ }
+<FindMembers>"operator"{BN}*"({B}*)"{BN}* /"(" { space added!
+ lineCount();
+ addType( current );
+ current->name = yytext;
+ }
+<FindMembers>"operator"{BN}*[^(/]+ {
+ lineCount();
+ addType( current ) ;
+ current->name = yytext ;
+ }
+ */
+<FindMembers>"using"{BN}+ { lineCount(); BEGIN(Using); }
+<Using>";" { BEGIN(FindMembers); }
+<FindMembers>{SCOPENAME}{BN}*"<>" { // guided template decl
+ QString n=yytext;
+ addType( current );
+ current->name=n.left(n.length()-2);
+ }
+<FindMembers>{SCOPENAME}{BN}*/"<" {
+ sharpCount=0;
+ lineCount();
+ addType( current );
+ current->name=yytext;
+ current->name=current->name.stripWhiteSpace();
+ if (current->name.right(8)=="operator")
+ BEGIN( Operator );
+ else
+ BEGIN( EndTemplate );
+ }
+<EndTemplate>"<" {
+ current->name+='<';
+ sharpCount++;
+ }
+ /*
+<EndTemplate>">"({BN}*"::"{SCOPENAME})? {
+ */
+<EndTemplate>">" {
+ current->name+=*yytext;
+ if (--sharpCount<=0)
+ {
+ //printf("Found %s\n",current->name.data());
+ BEGIN(FindMembers);
+ }
+ }
+<EndTemplate>">"{BN}*"(" {
+ lineCount();
+ current->name+='>';
+ if (--sharpCount<=0)
+ {
+ current->args = "(";
+ currentArgumentContext = FuncQual;
+ copyArgString=&current->args;
+ //printf("Found %s\n",current->name.data());
+ BEGIN( ReadFuncArgType ) ;
+ }
+ }
+<EndTemplate>">"{BN}*/"::" {
+ lineCount();
+ current->name+='>';
+ if (--sharpCount<=0)
+ {
+ BEGIN(FindMemberName);
+ }
+ }
+<EndTemplate>. { current->name+=*yytext; }
+<FindMembers,FindMemberName>{SCOPENAME} {
+ lineCount();
+ if (YY_START==FindMembers)
+ {
+ addType( current ) ;
+ current->name = yytext;
+ }
+ else
+ {
+ current->name += yytext;
+ }
+ QString tmp=yytext;
+ if (tmp.right(8)=="operator")
+ BEGIN( Operator );
+ else
+ BEGIN(FindMembers);
+ }
+<FindMembers>^{B}*"#" { lastCPPContext = YY_START;
+ BEGIN( SkipCPP ) ;
+ }
+<FindMembers>^{B}*"#define" {
+ BEGIN( Define );
+ }
+<SkipCPP>.
+<SkipCPP>\\[\r]*"\n"[\r]* { yyLineNr++ ; }
+<SkipCPP>[\r]*\n[\r]* { yyLineNr++ ;
+ BEGIN( lastCPPContext) ;
+ }
+<Define>{ID}/"(" {
+ current->name = yytext;
+ BEGIN( DefineArg );
+ }
+<DefineArg>")" {
+ //printf("Define with args\n");
+ current->args += ')';
+ BEGIN( DefineEnd );
+ }
+<DefineArg>. {
+ current->args += *yytext;
+ }
+<Define>{ID} {
+ //printf("Define `%s' without args\n",yytext);
+ current->name = yytext;
+ BEGIN(DefineEnd);
+ }
+<DefineEnd>\n {
+ //printf("End define\n");
+ current->fileName = yyFileName;
+ current->startLine = yyLineNr;
+ current->type.resize(0);
+ current->args = current->args.simplifyWhiteSpace();
+ current->name = current->name.stripWhiteSpace();
+ current->section = Entry::DEFINE_SEC;
+ current_root->addSubEntry(current);
+ current = new Entry ;
+ current->protection = protection ;
+ current->sig = sig;
+ current->virt = virt;
+ current->stat = gstat;
+ current->slot = slot;
+ BEGIN(FindMembers);
+ }
+<DefineEnd>\\\n
+<DefineEnd>.
+
+<FindMembers>[*&]+ { current->name += yytext ; }
+<FindMembers,MemberSpec,Function,NextSemi>";"{BN}*("/**"|"//!"|"/*!")"<" {
+ lineCount();
+ current->doc.resize(0);
+ current->brief.resize(0);
+ lastAfterDocContext = YY_START;
+ afterDocTerminator = ';';
+ if (yytext[yyleng-3]=='/')
+ BEGIN(AfterDocLine);
+ else if (yytext[yyleng-2]=='*')
+ BEGIN(AfterDocBrief);
+ else
+ BEGIN(AfterDoc);
+ }
+<MemberSpec,FindFields,FindMembers,NextSemi>","{BN}*("/**"|"//!"|"/*!")"<" {
+ lineCount();
+ current->doc.resize(0);
+ current->brief.resize(0);
+ lastAfterDocContext = YY_START;
+ afterDocTerminator = ',';
+ if (yytext[yyleng-3]=='/')
+ BEGIN(AfterDocLine);
+ else if (yytext[yyleng-2]=='*')
+ BEGIN(AfterDocBrief);
+ else
+ BEGIN(AfterDoc);
+ }
+<DefineEnd,FindFields,FindFieldArg>{BN}*("/**"|"//!"|"/*!")"<" {
+ lineCount();
+ current->doc.resize(0);
+ current->brief.resize(0);
+ lastAfterDocContext = YY_START;
+ if (YY_START==DefineEnd)
+ afterDocTerminator = '\n';
+ else
+ afterDocTerminator = 0;
+ if (yytext[yyleng-3]=='/')
+ BEGIN(AfterDocLine);
+ else if (yytext[yyleng-2]=='*')
+ BEGIN(AfterDocBrief);
+ else
+ BEGIN(AfterDoc);
+ }
+<FindMembers>"=" {
+ BEGIN(NextSemi);
+ }
+<FindMembers>[:;,] {
+ QString oldType = current->type.copy();
+ QString oldDocs = current->doc.copy();
+ current->type=current->type.simplifyWhiteSpace();
+ current->args=current->args.simplifyWhiteSpace();
+ current->name=current->name.stripWhiteSpace();
+ current->section = Entry::VARIABLE_SEC ;
+ current->fileName = yyFileName;
+ current->startLine = yyLineNr;
+ current_root->addSubEntry( current ) ;
+ current = new Entry ;
+ // variable found
+ current->section = Entry::EMPTY_SEC ;
+ current->protection = protection;
+ current->slot = slot = FALSE;
+ current->sig = sig = FALSE;
+ current->virt = Normal;
+ current->stat = gstat;
+ // skip expression or bitfield if needed
+ if ( *yytext == ':')
+ BEGIN( NextSemi );
+ else
+ {
+ if ( *yytext == ',' )
+ {
+ int i=oldType.length();
+ while (i>0 && (oldType[i-1]=='*' || oldType[i-1]==' ')) i--;
+ current->type = oldType.left(i);
+ current->doc = oldDocs;
+ }
+ BEGIN( FindMembers ) ;
+ }
+ }
+
+<FindMembers>"[" { current->args += yytext ;
+ sharpCount=1;
+ BEGIN( Array ) ;
+ }
+<Array>"]" { current->args += *yytext ;
+ if (--sharpCount<=0)
+ BEGIN( FindMembers ) ;
+ }
+<Array>"[" { current->args += *yytext ;
+ sharpCount++;
+ }
+<Array>. { current->args += *yytext ; }
+
+<FindMembers>"<" { addType( current ) ;
+ current->type += yytext ;
+ BEGIN( Sharp ) ;
+ }
+<Sharp>">" { current->type += *yytext ;
+ if (--sharpCount<=0)
+ BEGIN( FindMembers ) ;
+ }
+<Sharp>"<" { current->type += *yytext ;
+ sharpCount++;
+ }
+<Sharp>{BN}+ {
+ lineCount();
+ }
+<Sharp>. { current->type += *yytext ; }
+<FindFields>{ID} {
+ current->name = yytext;
+ }
+<FindFields>"=" {
+ BEGIN(FindFieldArg);
+ }
+<FindFields>"," {
+ //printf("adding `%s' `%s' `%s' to enum `%s'\n",
+ // current->type.data(), current->name.data(),
+ // current->args.data(), current_root->name.data());
+ current->fileName = yyFileName;
+ current->startLine = yyLineNr;
+ current->type = "@"; // enum marker
+ current->args = current->args.simplifyWhiteSpace();
+ current->name = current->name.stripWhiteSpace();
+ current->section = Entry::VARIABLE_SEC;
+ // add to the scope of the enum
+ current_root->addSubEntry(current);
+ current = new Entry(*current);
+ // add to the scope surrounding the enum (copy!)
+ current_root->parent->addSubEntry(current);
+ current = new Entry ;
+ current->protection = protection ;
+ current->sig = sig;
+ current->virt = virt;
+ current->stat = gstat;
+ current->slot = slot;
+ }
+<FindFieldArg>"," { unput(*yytext); BEGIN(FindFields); }
+<Curly>[^\r\n{}"/]* { current->program += yytext ; }
+<Curly>"//".* { current->program += yytext ; }
+<Curly>\"[^\r\n"]*\" { current->program += yytext ; }
+<Curly>"/*"{B}* { current->program += yytext ;
+ lastContext = Curly ;
+ BEGIN( Comment ) ;
+ }
+<Curly>"/*"{BL} { current->program += yytext ;
+ ++yyLineNr ;
+ lastContext = Curly ;
+ BEGIN( Comment ) ;
+ }
+<Curly>"{" { current->program += yytext ;
+ ++bracketCount ;
+ }
+<Curly>"}" { if ( bracketCount )
+ {
+ current->program += yytext ;
+ --bracketCount ;
+ }
+ else
+ {
+ QString &cn = current->name;
+ QString &rn = current_root->name;
+ //printf("current->name=`%s' current_root->name=`%s'\n",
+ // cn.data(),rn.data());
+ if (cn && cn[0]!='@' &&
+ (current_root->section & Entry::SCOPE_MASK))
+ {
+ cn.prepend(rn+"::");
+ }
+ if (isTypedef && cn.length()==0)
+ {
+ //printf("Typedef Name\n");
+ BEGIN( TypedefName );
+ }
+ else
+ {
+ if (current->section == Entry::ENUM_SEC)
+ {
+ current->program+=','; // add field terminator
+ }
+ // add compound definition to the tree
+ current->args = current->args.simplifyWhiteSpace();
+ current->type = current->type.simplifyWhiteSpace();
+ current->name = current->name.stripWhiteSpace();
+ //printf("adding `%s' `%s' `%s' brief=%s\n",current->type.data(),current->name.data(),current->args.data(),current->brief.data());
+ current_root->addSubEntry( current ) ;
+ current = new Entry(*current);
+ if (current->section == Entry::NAMESPACE_SEC)
+ { // a namespace ends with a closing bracket
+ current->reset();
+ current->protection = protection ;
+ current->sig = sig;
+ current->virt = virt;
+ current->stat = gstat;
+ current->slot = slot;
+ BEGIN( FindMembers ) ;
+ }
+ else
+ BEGIN( MemberSpec ) ;
+ }
+ }
+ }
+<TypedefName>{ID} {
+ if (current->section == Entry::ENUM_SEC)
+ {
+ current->program+=","; // add field terminator
+ }
+ current->name=yytext;
+ if (current_root->section & Entry::SCOPE_MASK)
+ {
+ current->name.prepend(current_root->name+"::");
+ }
+ current->args = current->args.simplifyWhiteSpace();
+ current->type = current->type.simplifyWhiteSpace();
+ //printf("Adding compound %s %s %s\n",current->type.data(),current->name.data(),current->args.data());
+ current_root->addSubEntry( current ) ;
+ current = new Entry;
+ current->protection = protection ;
+ current->sig = sig;
+ current->virt = virt;
+ current->stat = gstat;
+ current->slot = slot;
+ BEGIN(MemberSpecSkip);
+ }
+<MemberSpec>([*&]*{BN}*)*{ID}("["[a-z_A-Z0-9]*"]")* { // the [] part could be improved.
+ lineCount();
+ int i=0,l=yyleng,j;
+ while (i<l && (!isalpha(yytext[i]))) i++;
+ msName = yytext;
+ msName = msName.right(msName.length()-i);
+ j=msName.find("[");
+ if (j!=-1)
+ {
+ msArgs=msName.right(msName.length()-j);
+ msName=msName.left(j);
+ }
+ msType = yytext; msType=msType.left(i);
+ }
+<MemberSpec>[,;] {
+ if (msName.length()>0)
+ {
+ Entry *varEntry=new Entry;
+ varEntry->protection = current->protection ;
+ varEntry->sig = current->sig;
+ varEntry->virt = current->virt;
+ varEntry->stat = current->stat;
+ varEntry->slot = current->slot;
+ varEntry->section = Entry::VARIABLE_SEC;
+ varEntry->name = msName.stripWhiteSpace();
+ varEntry->type = current->type.simplifyWhiteSpace()+" ";
+ varEntry->args = msArgs; //current->args.simplifyWhiteSpace();
+ //if (current->name.length()>0 && current->name[0]!='@' &&
+ // current->parent->section & Entry::COMPOUND_MASK)
+ // varEntry->type+=current->parent->name+"::";
+ if (isTypedef)
+ varEntry->type.prepend("typedef ");
+ varEntry->type+=current->name+msType;
+ varEntry->fileName = yyFileName;
+ varEntry->startLine = yyLineNr;
+ varEntry->doc = current->doc.copy();
+ varEntry->brief = current->brief.copy();
+ //printf("Add: type=`%s',name=`%s',args=`%s'\n",
+ // varEntry->type.data(),varEntry->name.data(),varEntry->args.data());
+ current_root->addSubEntry(varEntry);
+ }
+ if (*yytext==';')
+ {
+ msType.resize(0);
+ msName.resize(0);
+ msArgs.resize(0);
+ isTypedef=FALSE;
+ current->reset();
+ current->protection = protection ;
+ current->sig = sig;
+ current->virt = virt;
+ current->stat = gstat;
+ current->slot = slot;
+ BEGIN( FindMembers );
+ }
+ }
+<MemberSpec>"=" { BEGIN(MemberSpecSkip); }
+<MemberSpecSkip>"{" {
+ bracketCount=0;
+ lastCurlyContext = MemberSpecSkip;
+ BEGIN(SkipCurly);
+ }
+<MemberSpecSkip>"," { BEGIN(MemberSpec); }
+<MemberSpecSkip>";" { unput(';'); BEGIN(MemberSpec); }
+<Curly>\n { current->program += yytext ;
+ yyLineNr++ ;
+ }
+<Curly>. { current->program += yytext ; }
+
+<FindMembers>"("({ID}{BN}*"::"{BN}*)*("*"{BN}*)+ {
+ lineCount();
+ addType(current);
+ funcPtrType=yytext;
+ //current->type += yytext;
+ BEGIN( FuncPtr );
+ }
+<FuncPtr>{SCOPENAME} {
+ current->name = yytext;
+ BEGIN( EndFuncPtr );
+ }
+<FuncPtr>. {
+ //printf("Error: FuncPtr `%c' unexpected at line %d of %s\n",*yytext,yyLineNr,yyFileName);
+ }
+<EndFuncPtr>")"{BN}*/";" { // a variable with extra braces
+ lineCount();
+ current->type+=funcPtrType.data()+1;
+ BEGIN(FindMembers);
+ }
+<EndFuncPtr>")"{BN}*/"(" { // a variable function
+ lineCount();
+ current->type+=funcPtrType+")";
+ BEGIN(FindMembers);
+ }
+<EndFuncPtr>"(" { // a function returning a function
+ current->args += *yytext ;
+ bracketCount=0;
+ BEGIN( FuncFunc );
+ }
+<EndFuncPtr>")" {
+ BEGIN(FindMembers);
+ }
+<FuncFunc>"(" {
+ current->args += *yytext ;
+ ++bracketCount;
+ }
+<FuncFunc>")" {
+ current->args += *yytext ;
+ if ( bracketCount )
+ --bracketCount;
+ else
+ {
+ BEGIN(FuncFuncEnd);
+ }
+ }
+<FuncFuncEnd>")"{BN}*"(" {
+ lineCount();
+ current->type+=funcPtrType+")(";
+ BEGIN(FuncFuncType);
+ }
+<FuncFuncEnd>")"{BN}*/[;{] {
+ lineCount();
+ current->type+=funcPtrType.data()+1;
+ BEGIN(Function);
+ }
+<FuncFuncEnd>. {
+ current->args += *yytext;
+ }
+<FuncFuncType>"(" {
+ current->type += *yytext;
+ bracketCount++;
+ }
+<FuncFuncType>")" {
+ current->type += *yytext;
+ if (bracketCount)
+ --bracketCount;
+ else
+ BEGIN(Function);
+ }
+<FuncFuncType>{BN}*","{BN}* { lineCount() ; current->type += ", " ; }
+<FuncFuncType>{BN}+ { lineCount() ; current->type += ' ' ; }
+<FuncFuncType>. {
+ current->type += *yytext;
+ }
+<FindMembers>"(" { current->args = yytext;
+ currentArgumentContext = FuncQual;
+ copyArgString=&current->args;
+ BEGIN( ReadFuncArgType ) ;
+ //printf(">>> Read function arguments!\n");
+ }
+ /*
+<FindMembers>"("{BN}*("void"{BN}*)?")" {
+ lineCount();
+ current->args = "()";
+ BEGIN( FuncQual );
+ }
+ */
+
+ /*- Function argument reading rules ---------------------------------------*/
+
+<ReadFuncArgType>[^ \/\r\t\n\)\(\"\']+ { *copyArgString+=yytext; }
+<CopyArgString>[^\n\\\"\']+ { *copyArgString+=yytext; }
+<CopyArgRound>[^\/\n\)\(\"\']+ { *copyArgString+=yytext; }
+<ReadFuncArgType,ReadTempArgs>{BN}* {
+ *copyArgString+=" ";
+ lineCount();
+ }
+<ReadFuncArgType,CopyArgRound,CopyArgSharp,ReadTempArgs>\" {
+ *copyArgString+=*yytext;
+ lastCopyArgStringContext = YY_START;
+ BEGIN( CopyArgString );
+ }
+<ReadFuncArgType,ReadTempArgs>"(" {
+ *copyArgString+=*yytext;
+ argRoundCount=0;
+ lastCopyArgContext = YY_START;
+ BEGIN( CopyArgRound );
+ }
+<ReadFuncArgType>")" {
+ *copyArgString+=*yytext;
+ stringToArgumentList(*copyArgString,current->argList);
+ BEGIN( currentArgumentContext );
+ }
+<ReadTempArgs>"<" {
+ *copyArgString+=*yytext;
+ argSharpCount=0;
+ BEGIN( CopyArgSharp );
+ }
+<ReadTempArgs>">" {
+ *copyArgString+=*yytext;
+ //printf("end template list %s\n",copyArgString->data());
+ stringToArgumentList(*copyArgString,current->tArgList);
+ BEGIN( currentArgumentContext );
+ }
+<CopyArgRound>"(" {
+ argRoundCount++;
+ *copyArgString+=*yytext;
+ }
+<CopyArgRound>")" {
+ *copyArgString+=*yytext;
+ if (argRoundCount>0)
+ argRoundCount--;
+ else
+ BEGIN( lastCopyArgContext );
+ }
+<CopyArgSharp>"<" {
+ argSharpCount++;
+ *copyArgString+=*yytext;
+ }
+<CopyArgSharp>">" {
+ *copyArgString+=*yytext;
+ if (argRoundCount>0)
+ argRoundCount--;
+ else
+ BEGIN( ReadTempArgs );
+ }
+<CopyArgString>\\. {
+ *copyArgString+=yytext;
+ }
+<CopyArgString>\" {
+ *copyArgString+=*yytext;
+ BEGIN( lastCopyArgStringContext );
+ }
+<ReadFuncArgType,ReadTempArgs,CopyArgRound,CopyArgSharp>"'"\\[0-7]{1,3}"'" { *copyArgString+=yytext; }
+<ReadFuncArgType,ReadTempArgs,CopyArgRound,CopyArgSharp>"'"\\."'" { *copyArgString+=yytext; }
+<ReadFuncArgType,ReadTempArgs,CopyArgRound,CopyArgSharp>"'"."'" { *copyArgString+=yytext; }
+<ReadFuncArgType,ReadTempArgs,CopyArgString,CopyArgRound,CopyArgSharp>\n { yyLineNr++; *copyArgString+=*yytext; }
+<ReadFuncArgType,ReadTempArgs,CopyArgString,CopyArgRound,CopyArgSharp>. { *copyArgString+=*yytext; }
+
+
+
+ /*------------------------------------------------------------------------*/
+
+
+<FuncRound>"(" { current->args += *yytext ;
+ ++bracketCount ;
+ }
+<FuncRound>")" { current->args += *yytext ;
+ if ( bracketCount )
+ --bracketCount ;
+ else
+ BEGIN( FuncQual ) ;
+ }
+ /*
+<FuncQual>"#" { lastCPPContext = YY_START;
+ BEGIN(SkipCPP);
+ }
+ */
+<FuncQual>[{:;] { unput(*yytext); BEGIN( Function ); }
+<FuncQual>{BN}*"const"{BN}* {
+ lineCount() ;
+ current->args += " const ";
+ current->argList->constSpecifier=TRUE;
+ }
+<FuncQual>{BN}*"volatile"{BN}* {
+ lineCount() ;
+ current->args += " volatile ";
+ current->argList->volatileSpecifier=TRUE;
+ }
+<FuncQual>{BN}*"="{BN}*"0"{BN}* {
+ lineCount() ;
+ current->args += " = 0";
+ current->virt = Pure;
+ current->argList->pureSpecifier=TRUE;
+ }
+<FuncRound,FuncFunc>{BN}*","{BN}* {
+ lineCount() ;
+ current->args += ", " ;
+ }
+<FuncQual,FuncRound,FuncFunc>{BN}+ {
+ lineCount() ;
+ current->args += ' ' ;
+ }
+<FuncQual,FuncRound,FuncFunc>. { current->args += *yytext; }
+<FuncQual>{BN}*"throw"{BN}*"(" {
+ current->exception = " throw(" ;
+ lineCount() ;
+ BEGIN( ExcpRound ) ;
+ }
+<ExcpRound>"(" { current->exception += *yytext ;
+ ++bracketCount ;
+ }
+<ExcpRound>")" { current->exception += *yytext ;
+ if ( bracketCount )
+ --bracketCount ;
+ else
+ BEGIN( FuncQual ) ;
+ }
+<ExcpRound>. {
+ current->exception += yytext;
+ }
+<Function>"(" { current->type += current->name ;
+ current->name = current->args ;
+ current->args = yytext ;
+ BEGIN( FuncRound ) ;
+ }
+<Function>"#" { lastCPPContext = YY_START;
+ BEGIN(SkipCPP);
+ }
+<Function>[:;{] {
+ current->name=current->name.simplifyWhiteSpace();
+ current->type=current->type.simplifyWhiteSpace();
+ current->args=current->args.simplifyWhiteSpace();
+ QString &cn=current->name;
+ QString &rn=current_root->name;
+ //printf("current_root->name=`%s'\n",rn.data());
+ //printf("Function: `%s' `%s' `%s'\n",current->type.data(),cn.data(),current->args.data());
+ int i;
+ if ((i=cn.findRev("::"))!=-1) // name contains scope
+ {
+ if (cn.left(i)==rn.right(i)) // scope name is redundant
+ {
+ cn=cn.right(cn.length()-i-2); // strip scope
+ //printf("new name=`%s'\n",cn.data());
+ }
+ }
+ //if (cname.left(current_root->name.length()+2)==current_root->name+"::")
+ //{ // strip redundant scope
+ // current->name=current->name.right(current->name.length()-current_root->name.length()-2);
+ // printf("new name=`%s'\n",current->name.data());
+ //}
+ current->fileName = yyFileName;
+ current->startLine = yyLineNr;
+ if (*yytext!=';' || (current_root->section&Entry::SCOPE_MASK) )
+ {
+ int tempArg=current->name.find('<');
+ QString tempName;
+ if (tempArg==-1)
+ tempName=current->name;
+ else
+ tempName=current->name.left(tempArg);
+ if (current->type.isNull() && tempName.find("operator")==-1 &&
+ (tempName.find('*')!=-1 || tempName.find('&')!=-1))
+ {
+ //printf("Scanner.l: found in class variable: `%s' `%s' `%s'\n",
+ // current->type.data(),current->name.data(),current->args.data());
+ current->section = Entry::VARIABLE_SEC ;
+ }
+ else
+ {
+ //printf("Scanner.l: found in class function: `%s' `%s' `%s'\n",
+ // current->type.data(),current->name.data(),current->args.data());
+ current->section = Entry::FUNCTION_SEC ;
+ }
+ }
+ else // a global function prototype or function variable
+ {
+ //printf("Scanner.l: prototype? type=`%s' name=`%s' args=`%s'\n",current->type.data(),current->name.data(),current->args.data());
+ QRegExp re("([^)])");
+ if (!current->type.isNull() && current->type.find(re,0)!=-1)
+ {
+ //printf("Scanner.l: found function variable!\n");
+ current->section = Entry::VARIABLE_SEC;
+ }
+ else
+ {
+ //printf("Scanner.l: found prototype\n");
+ current->section = Entry::FUNCTION_SEC;
+ current->proto = TRUE;
+ }
+ }
+ current_root->addSubEntry(current);
+ current = new Entry ;
+ current->protection = protection;
+ current->sig = sig;
+ current->virt = virt;
+ current->stat = gstat;
+ current->slot = slot;
+ lastCurlyContext = FindMembers;
+ if( *yytext == '{' )
+ BEGIN( SkipCurly ) ;
+ else if( *yytext == ':' )
+ BEGIN( SkipInits ) ;
+ else
+ BEGIN( FindMembers ) ;
+ }
+
+<SkipInits>"{" {
+ lastCurlyContext = FindMembers;
+ BEGIN( SkipCurly ) ;
+ }
+<SkipCurly,SkipCurlyCpp>"{" { ++bracketCount ; }
+<SkipCurly,SkipCurlyCpp>"}" { if( bracketCount )
+ --bracketCount ;
+ else
+ //BEGIN( FindMembers ) ;
+ BEGIN( lastCurlyContext ) ;
+ }
+<SkipCurly>\'.\'
+<SkipCurly>\" {
+ lastStringContext=SkipCurly;
+ BEGIN( SkipString );
+ }
+<SkipCurly>^{B}*"#" { BEGIN( SkipCurlyCpp ); }
+<SkipCurlyCpp>\n { yyLineNr++;
+ lastCurlyContext = FindMembers;
+ BEGIN( SkipCurly );
+ }
+<SkipCurlyCpp>\\[\r]*"\n"[\r]* { yyLineNr++; }
+<SkipCurlyCpp>"/*"
+<SkipCurlyCpp>"*/"
+<SkipCurlyCpp>"//"
+<SkipString>\\.
+<SkipString>\" { BEGIN( lastStringContext ); }
+<SkipString>"/*"
+<SkipString>"*/"
+<SkipString>"//"
+
+<Bases,ClassName>";" {
+ current->section = Entry::EMPTY_SEC ;
+ current->type.resize(0) ;
+ current->name.resize(0) ;
+ current->args.resize(0) ;
+ current->argList->clear();
+ BEGIN( FindMembers ) ;
+ }
+<ClassName>{ID} {
+ current->name = yytext ;
+ BEGIN( ClassVar );
+ }
+ /*
+<ClassVar>{ID}/{BN}*"{" { // we probably got some M$ extension
+ current->name = yytext ;
+ }
+<ClassVar>{ID}/{BN}*":" { // we probably got some M$ extension
+ current->name = yytext ;
+ }
+ */
+<ClassVar>{ID} {
+ if (isTypedef)
+ {
+ typedefDict.insert(yytext,new QString(current->name));
+ current->type.prepend("typedef ");
+ }
+ current->type += ' ' ;
+ current->type += current->name ;
+ current->name = yytext ;
+ //BEGIN( FindMembers );
+ }
+<ClassVar>"(" {
+ roundCount=1;
+ lastSkipRoundContext=YY_START;
+ BEGIN(SkipRound);
+ }
+<ClassVar>":" {
+ current->type.resize(0);
+ baseProt=Private;
+ baseVirt=Normal;
+ baseName.resize(0);
+ BEGIN( Bases ) ;
+ }
+<ClassVar>[;=*&] {
+ unput(*yytext);
+ BEGIN( FindMembers );
+ }
+<ClassName,ClassVar>{B}*"{"{B}* { current->fileName = yyFileName ;
+ current->startLine = yyLineNr ;
+ if (current->name.length()==0 && !isTypedef) // anonymous compound
+ current->name.sprintf("@%d",anonCount++);
+ BEGIN( Curly ) ;
+ }
+<Bases>"virtual" { baseVirt = Virtual; }
+<Bases>"public" { baseProt = Public; }
+<Bases>"protected" { baseProt = Protected; }
+<Bases>"private" { baseProt = Private; }
+<Bases>({ID}{BN}*"::"{BN}*)*{ID} {
+ //current->extends->append(
+ // new BaseInfo(yytext,baseProt,baseVirt)
+ //) ;
+ baseName += yytext;
+ current->args += ' ' ;
+ current->args += yytext ;
+ }
+<ClassVar>"<" { current->name += *yytext;
+ sharpCount=1;
+ lastSkipSharpContext = YY_START;
+ specName = &current->name;
+ BEGIN ( Specialization );
+ }
+<Bases>"<" { baseName += *yytext;
+ sharpCount=1;
+ lastSkipSharpContext = YY_START;
+ specName = &baseName;
+ BEGIN ( Specialization );
+ }
+<Specialization>"<" { *specName += *yytext;
+ sharpCount++;
+ }
+<Specialization>">" {
+ *specName += *yytext;
+ if (--sharpCount<=0)
+ BEGIN(lastSkipSharpContext);
+ }
+<Specialization>{BN}+ { lineCount(); *specName +=' '; }
+<Specialization>. {
+ *specName += *yytext;
+ }
+<SkipSharp>"<" { ++sharpCount; }
+<SkipSharp>">" { if (--sharpCount<=0)
+ BEGIN ( lastSkipSharpContext );
+ }
+<SkipRound>"(" { ++roundCount; }
+<SkipRound>")" { if (--roundCount<=0)
+ BEGIN ( lastSkipRoundContext );
+ }
+<Bases>"," { current->args += ',' ;
+ if (baseName.length()>0)
+ current->extends->append(
+ new BaseInfo(baseName,baseProt,baseVirt)
+ );
+ baseProt=Private;
+ baseVirt=Normal;
+ baseName.resize(0);
+ }
+<Bases>{B}*"{"{B}* { current->fileName = yyFileName ;
+ current->startLine = yyLineNr ;
+ if (baseName.length()>0)
+ current->extends->append(
+ new BaseInfo(baseName,baseProt,baseVirt)
+ );
+ BEGIN( Curly ) ;
+ }
+<Comment>\n { current->program += yytext ;
+ yyLineNr++ ;
+ }
+<Comment>"/*" { current->program += yytext ; }
+<Comment>"//" { current->program += yytext ; }
+<Comment>. { current->program += *yytext ; }
+<Comment>.*"*/" { current->program += yytext ;
+ BEGIN( Curly ) ;
+ }
+
+<FindMembers,FindFields,MemberSpec,FuncQual,SkipCurly,Operator>("//"{B}*)?"/*!" {
+ removeSlashes=(yytext[1]=='/');
+ tmpDocType=-1;
+ if (YY_START==Curly)
+ current->doc+="\n\n";
+ else
+ current->doc.resize(0);
+ lastDocContext = YY_START;
+ if (current_root->section & Entry::SCOPE_MASK)
+ current->inside = current_root->name+"::";
+ BEGIN( Doc );
+ }
+<FindMembers,FindFields,MemberSpec,FuncQual,SkipCurly,Operator>("//"{B}*)?"/**"/[^/*] {
+ removeSlashes=(yytext[1]=='/');
+ if (current_root->section & Entry::SCOPE_MASK)
+ current->inside = current_root->name+"::";
+ if (YY_START==Curly)
+ {
+ tmpDocType=-1;
+ current->doc+="\n\n";
+ lastDocContext = Curly;
+ BEGIN( Doc );
+ }
+ else
+ {
+ tmpDocType=Doc;
+ current->doc.resize(0);
+ current->brief.resize(0);
+ lastDocContext = YY_START;
+ BEGIN( JavaDoc );
+ }
+ }
+<FindMembers,FindFields,MemberSpec,FuncQual,Operator>"//!" {
+ current->brief.resize(0);
+ tmpDocType=-1;
+ lastDocContext = YY_START;
+ if (current_root->section & Entry::SCOPE_MASK)
+ current->inside = current_root->name+"::";
+ BEGIN( LineDoc );
+ }
+<FindMembers,FindFields,MemberSpec,FuncQual,Operator>"///"/[^/] {
+ current->brief.resize(0);
+ tmpDocType=-1;
+ lastDocContext = YY_START;
+ if (current_root->section & Entry::SCOPE_MASK)
+ current->inside = current_root->name+"::";
+ BEGIN( LineDoc );
+ }
+<FindMembers>"extern"{BN}+"\"C"("++")?"\""{BN}+("{")?
+<FindMembers>"{" {
+ current->type.resize(0);
+ current->name.resize(0);
+ current->args.resize(0);
+ current->argList->clear();
+ bracketCount=0;
+ BEGIN( SkipBlock );
+
+ }
+<JavaDoc>"@short"{B}+ {
+ lastBriefContext=Doc;
+ BEGIN( ClassDocBrief );
+ }
+<JavaDoc>^(({B}*"*"+)?){BL} {
+ lineCount();
+ if (!current->brief.stripWhiteSpace().isEmpty())
+ {
+ BEGIN( tmpDocType );
+ }
+ }
+<JavaDoc>"@" {
+ unput(*yytext);
+ BEGIN(Doc);
+ }
+<JavaDoc>^{B}*"*"+/[^/] {
+ //printf("---> removing %s\n",yytext);
+ }
+ /*
+<JavaDoc>[^\n\@\*\.\\]+ {
+ current->brief+=yytext;
+ }
+ */
+<JavaDoc>. {
+ //printf("---> copy %c\n",*yytext);
+ current->brief+=*yytext;
+ }
+<JavaDoc>\n {
+ current->brief+=' ';
+ lineCount();
+ }
+<JavaDoc>"."[ \t\r\n] {
+ lineCount();
+ current->brief+=".";
+ BEGIN( tmpDocType );
+ }
+<JavaDoc>("\\"|"@")"internal" {
+ current->doc+="\\internal";
+ BEGIN( tmpDocType );
+ }
+<Doc,JavaDoc>{B}*("\\"|"@")("fn"|"var"|"typedef"){B}* {
+ current->section = Entry::MEMBERDOC_SEC;
+ current->fileName = yyFileName;
+ current->startLine = yyLineNr;
+ BEGIN( ClassDocFunc );
+ }
+<LineDoc,Doc,JavaDoc>{B}*("\\"|"@")"def"{B}* {
+ nextDefContext = YY_START==LineDoc ? DefLineDoc : ClassDoc;
+ current->section = Entry::DEFINEDOC_SEC;
+ current->fileName = yyFileName;
+ current->startLine = yyLineNr;
+ BEGIN( ClassDocDefine );
+ }
+<Doc,JavaDoc>{B}*("\\"|"@")"overload"{B}* {
+ BEGIN( ClassDocOverload );
+ }
+<ClassDocOverload>{B}*"\n" {
+ QString orgDoc = current->doc;
+ current->doc = getOverloadDocs();
+ current->doc += "\n\n";
+ current->doc += orgDoc;
+ yyLineNr++;
+ BEGIN( Doc );
+ }
+<ClassDocOverload>. { unput(*yytext);
+ current->section = Entry::OVERLOADDOC_SEC;
+ current->fileName = yyFileName;
+ current->startLine = yyLineNr;
+ BEGIN( ClassDocFunc );
+ }
+<Doc,JavaDoc>{B}*("\\"|"@")"enum"{B}* {
+ current->section = Entry::ENUMDOC_SEC;
+ current->fileName = yyFileName;
+ current->startLine = yyLineNr;
+ BEGIN( EnumDocArg1 );
+ }
+<Doc,JavaDoc>{B}*("\\"|"@")"defgroup"{B}* {
+ current->section = Entry::GROUPDOC_SEC;
+ current->fileName = yyFileName;
+ current->startLine = yyLineNr;
+ BEGIN( GroupDocArg1 );
+ }
+<Doc,JavaDoc>{B}*("\\"|"@")"namespace"{B}* {
+ current->section = Entry::NAMESPACEDOC_SEC;
+ current->fileName = yyFileName;
+ current->startLine = yyLineNr;
+ BEGIN( NameSpaceDocArg1 );
+ }
+<Doc,JavaDoc>{B}*("\\"|"@")"class"{B}* {
+ current->section = Entry::CLASSDOC_SEC;
+ current->fileName = yyFileName;
+ current->startLine = yyLineNr;
+ BEGIN( ClassDocArg1 );
+ }
+<Doc,JavaDoc>{B}*("\\"|"@")"union"{B}* {
+ current->section = Entry::UNIONDOC_SEC;
+ current->fileName = yyFileName;
+ current->startLine = yyLineNr;
+ BEGIN( ClassDocArg1 );
+ }
+<Doc,JavaDoc>{B}*("\\"|"@")"struct"{B}* {
+ current->section = Entry::STRUCTDOC_SEC;
+ current->fileName = yyFileName;
+ current->startLine = yyLineNr;
+ BEGIN( ClassDocArg1 );
+ }
+<Doc,JavaDoc>{B}*("\\"|"@")"page"{B}* {
+ current->section = Entry::PAGEDOC_SEC;
+ current->fileName = yyFileName;
+ current->startLine = yyLineNr;
+ BEGIN( PageDocArg1 );
+ }
+<Doc,JavaDoc>{B}*("\\"|"@")"file"{B}* {
+ current->section = Entry::FILEDOC_SEC;
+ current->fileName = yyFileName;
+ current->startLine = yyLineNr;
+ BEGIN( FileDocArg1 );
+ }
+<Doc,JavaDoc>{B}*("\\"|"@")"example"{B}* {
+ current->section = Entry::EXAMPLE_SEC;
+ current->fileName = yyFileName;
+ current->startLine = yyLineNr;
+ BEGIN( ExampleDocArg1 );
+ }
+<ExampleDocArg1>{FILE} {
+ current->name = stripQuotes(yytext);
+ BEGIN( ExampleDoc );
+ }
+<ClassDoc,Doc,JavaDoc>{B}*("\\"|"@")"relate"[sd]{B}* {
+ lastDocRelContext = YY_START;
+ BEGIN( ClassDocRelates );
+ }
+<ClassDocRelates>{ID} {
+ current->relates = yytext;
+ BEGIN( lastDocRelContext );
+ }
+<NameSpaceDocArg1>{SCOPENAME} {
+ current->name = yytext;
+ newDocState();
+ }
+<NameSpaceDocArg1>"\n" {
+ warn("Warning: missing argument after "
+ "\\namespace at line %d of %s.\n",yyLineNr,yyFileName);
+ yyLineNr++;
+ }
+<ClassDocArg1>{SCOPENAME} {
+ current->name = yytext;
+ // prepend outer scope name
+ if (current_root->section & Entry::SCOPE_MASK)
+ {
+ current->name.prepend(current_root->name+"::");
+ }
+ BEGIN( ClassDocArg2 );
+ }
+<ClassDocArg1>"\n" {
+ warn("Warning: missing argument after "
+ "\\class at line %d of %s.\n",yyLineNr,yyFileName);
+ yyLineNr++;
+
+ }
+<GroupDocArg1>{ID}(".html"?) {
+ current->name = yytext;
+ if (current->name.right(5)==".html")
+ current->name=current->name.left(current->name.length()-5);
+ BEGIN(GroupDocArg2);
+ }
+<GroupDocArg1>"\n" {
+ warn("Warning: missing argument after "
+ "\\defgroup at line %d of %s.\n",yyLineNr,yyFileName);
+ yyLineNr++;
+ BEGIN( Doc );
+ }
+<GroupDocArg2>.* {
+ current->type = yytext;
+ current->type = current->type.stripWhiteSpace();
+ newDocState();
+ }
+<GroupDocArg2>"\n" {
+ newDocState();
+ }
+<ClassDocArg2>{FILE} {
+ //printf("ClassDocArg2=%s\n",yytext);
+ current->includeFile = stripQuotes(yytext);
+ BEGIN( ClassDocArg3 );
+ }
+<ClassDocArg2>{BL} { yyLineNr++;
+ newDocState();
+ }
+<ClassDocArg3>{FILE} {
+ //printf("ClassDocArg3=%s\n",yytext);
+ current->includeName = stripQuotes(yytext);
+ newDocState();
+ }
+<ClassDocArg3>{BL} { yyLineNr++;
+ newDocState();
+ }
+<FileDocArg1>{FILE} {
+ current->name = stripQuotes(yytext);
+ newDocState();
+ }
+<FileDocArg1>"\n" {
+ //warn("Warning: missing argument after "
+ // "\\file at line %d of %s.\n",yyLineNr,yyFileName);
+ current->name = yyFileName;
+ yyLineNr++;
+ newDocState();
+ }
+<PageDocArg1>{FILE} {
+ current->name = stripQuotes(yytext);
+ BEGIN( PageDocArg2 );
+ }
+<PageDocArg1>"\n" {
+ warn("Warning: missing argument after "
+ "\\page at line %d of %s.\n",yyLineNr,yyFileName);
+ yyLineNr++;
+ BEGIN( Doc );
+ }
+<PageDocArg2>.*"\n" {
+ yyLineNr++;
+ current->args = yytext;
+ BEGIN( PageDoc );
+ }
+<EnumDocArg1>{SCOPEID} {
+ current->name = yytext;
+ if (current_root->section & Entry::SCOPE_MASK)
+ {
+ current->name.prepend(current_root->name+"::");
+ }
+ newDocState();
+ }
+<EnumDocArg1>"\n" {
+ warn("Warning: missing argument after "
+ "\\enum at line %d of %s.\n",yyLineNr,yyFileName);
+ yyLineNr++;
+ BEGIN( Doc );
+ }
+<PageDoc>"\\refitem".*"\n" {
+ current->doc+=yytext;
+ }
+<PageDoc>("\\"|"@")"section"{B}+ {
+ isSubsection=FALSE;
+ BEGIN(SectionLabel);
+ }
+<PageDoc>("\\"|"@")"subsection"{B}+ {
+ isSubsection=TRUE;
+ BEGIN(SectionLabel);
+ }
+<Doc,PageDoc,JavaDoc,ClassDoc>"\\\\verbatim"/[^a-z_A-Z0-9] {
+ current->doc+="\\\\verbatim";
+ }
+<Doc,PageDoc,JavaDoc,ClassDoc>("\\"|"@")"verbatim"/[^a-z_A-Z0-9] {
+ lastVerbState=YY_START;
+ current->doc+="\\verbatim";
+ BEGIN(SkipVerbatim);
+ }
+<Doc,PageDoc,JavaDoc,ClassDoc>"\\\\code"/[^a-z_A-Z0-9] {
+ current->doc+="\\\\code";
+ }
+<Doc,PageDoc,JavaDoc,ClassDoc>("\\"|"@")"code"/[^a-z_A-Z0-9] {
+ lastCodeState=YY_START;
+ current->doc+="\\code";
+ BEGIN(SkipCode);
+ }
+<Doc,PageDoc,JavaDoc,ClassDoc>"<"{PRE}{ATTR}">" {
+ lastCodeState=YY_START;
+ current->doc+="<PRE>";
+ BEGIN(SkipCode);
+ }
+<SkipVerbatim>("\\"|"@")"endverbatim"/[^a-z_A-Z0-9] {
+ current->doc+=yytext;
+ BEGIN(lastVerbState);
+ }
+<SkipVerbatim>[^ \t\/\\\n]* {
+ current->doc+=yytext;
+ }
+<SkipVerbatim>^"//" {
+ if (!removeSlashes)
+ current->doc+=yytext;
+ }
+ /*
+<SkipVerbatim>^"//"({B}*"*"+)? {
+ if (!removeSlashes)
+ current->doc+=yytext;
+ }
+<SkipVerbatim>^{B}*"*"+
+ */
+<SkipVerbatim>"//"|"/*" {
+ current->doc+=yytext;
+ }
+<SkipVerbatim>"\n" {
+ yyLineNr++;
+ current->doc+=*yytext;
+ }
+<SkipVerbatim>. {
+ current->doc+=*yytext;
+ }
+<SkipCode>("\\"|"@")"endcode" {
+ current->doc+="\\endcode";
+ BEGIN(lastCodeState);
+ }
+<SkipCode>"</"{PRE}{ATTR}">" {
+ current->doc+="</PRE>";
+ BEGIN(lastCodeState);
+ }
+<SkipCode>^"//"({B}*"*"+)? {
+ if (!removeSlashes)
+ current->doc+=yytext;
+ }
+<SkipCode>^{B}*"*"+
+<SkipCode>"//" {
+ current->doc+=yytext;
+ }
+<SkipCode>[^ \*\t\/\\\n]+ {
+ current->doc+=yytext;
+ }
+<SkipCode>\n {
+ yyLineNr++;
+ current->doc+=*yytext;
+ }
+<SkipCode>. {
+ current->doc+=*yytext;
+ }
+<SectionLabel>[a-z_A-Z0-9]+ {
+ sectionLabel=yytext;
+ sectionTitle.resize(0);
+ BEGIN(SectionTitle);
+ }
+<SectionTitle>[^\n*]*/"\n" {
+ sectionTitle+=yytext;
+ sectionTitle=sectionTitle.stripWhiteSpace();
+ addSection();
+ current->doc += "\\section "+sectionLabel+"\n";
+ BEGIN(PageDoc);
+ }
+<SectionTitle>"*" {
+ sectionTitle+=yytext;
+ }
+<ExampleDoc,PageDoc,ClassDoc>"\n" { yyLineNr++ ; current->doc+=yytext; }
+<ExampleDoc,PageDoc,ClassDoc>[a-z_A-Z0-9 \t]+ { current->doc += yytext; }
+<ExampleDoc,PageDoc,ClassDoc>. { current->doc += yytext; }
+<Doc,JavaDoc,LineDoc,ExampleDoc,PageDoc,ClassDoc>^{B}*"//"
+<Doc,JavaDoc,LineDoc,ExampleDoc,PageDoc,ClassDoc>"//" { current->doc += yytext; }
+<Doc,JavaDoc,LineDoc,ExampleDoc,ClassDocBrief,PageDoc,ClassDoc>"\\\\f"[$\[\]] {
+ current->doc += &yytext[1];
+ }
+<Doc,JavaDoc,LineDoc,ExampleDoc,ClassDocBrief,PageDoc,ClassDoc>"\\f$" {
+ lastFormulaContext = YY_START;
+ formulaText="$";
+ BEGIN(ReadFormulaShort);
+ }
+<Doc,JavaDoc,LineDoc,ExampleDoc,ClassDocBrief,PageDoc,ClassDoc>"\\f[" {
+ lastFormulaContext = YY_START;
+ formulaText="\\[";
+ BEGIN(ReadFormulaLong);
+ }
+<ReadFormulaShort>"\\f$" {
+ formulaText+="$";
+ if (lastFormulaContext==ClassDocBrief)
+ current->brief += addFormula();
+ else
+ current->doc += addFormula();
+ BEGIN(lastFormulaContext);
+ }
+<ReadFormulaLong>"\\f]" {
+ formulaText+="\\]";
+ if (lastFormulaContext==ClassDocBrief)
+ current->brief += addFormula();
+ else
+ current->doc += addFormula();
+ BEGIN(lastFormulaContext);
+ }
+<ReadFormulaLong,ReadFormulaShort>. { formulaText+=*yytext; }
+<ExampleDoc,PageDoc,ClassDocBrief,ClassDoc>"*/" {
+ if (YY_START==ClassDocBrief &&
+ lastBriefContext==Doc)
+ {
+ current->doc += "\n\n";
+ BEGIN( lastDocContext );
+ }
+ else
+ {
+ current->doc += "\n\n";
+ //printf("Add docs for class %s\n",current->name.data());
+ current_root->addSubEntry(current);
+ current = new Entry ;
+ current->protection = protection ;
+ current->sig = sig;
+ current->virt = virt;
+ current->stat = gstat;
+ current->slot = slot;
+ }
+ BEGIN( FindMembers );
+ }
+<PageDoc>"<"{TITLE}">" {
+ current->args.resize(0);
+ current->argList->clear();
+ BEGIN( PageDocTitle);
+ }
+<PageDocTitle>\n { yyLineNr++; current->args+=" "; }
+<PageDocTitle>[^\n\<] { current->args+=yytext; }
+<PageDocTitle>"</"{TITLE}">" { BEGIN( PageDoc ); }
+<ClassDoc,Doc,JavaDoc>("\\"|"@")"ingroup"{B}+ {
+ lastGroupContext = YY_START;
+ lineCount();
+ BEGIN( GroupName );
+ }
+<GroupName>{ID} {
+ current->groups->append(
+ new QString(yytext)
+ );
+ }
+<GroupName>\n {
+ yyLineNr++; BEGIN( lastGroupContext );
+ }
+<ClassDoc,Doc>{B}*("\\brief"|"@short") {
+ lastBriefContext=YY_START;
+ BEGIN( ClassDocBrief );
+ }
+<ClassDoc>{B}*"\\inherit"{B}+ { BEGIN( DocBaseClass ); }
+<DocBaseClass>{ID} {
+ //printf("Adding base class %s\n",yytext);
+ current->extends->append(
+ new BaseInfo(yytext,Public,Normal)
+ );
+ }
+<DocBaseClass>\n { yyLineNr++; BEGIN( ClassDoc ); }
+<ClassDocBrief>{BS}{BL} {
+ current->brief=current->brief.stripWhiteSpace();
+ yyLineNr++;
+ BEGIN( lastBriefContext );
+ }
+<ClassDocBrief>"\n" { yyLineNr++ ; current->brief += " "; }
+<ClassDocBrief>"<"{BR}{ATTR}">"
+<ClassDocBrief>{BS}/("\\"|"@")"ingroup" {
+ current->brief=current->brief.stripWhiteSpace();
+ BEGIN( lastBriefContext );
+ }
+<ClassDocBrief>{BS}/("\\"|"@")"author" { BEGIN( lastBriefContext ); }
+<ClassDocBrief>{BS}/("\\"|"@")"internal" { BEGIN( lastBriefContext ); }
+<ClassDocBrief>{BS}/("\\"|"@")"version" { BEGIN( lastBriefContext ); }
+<ClassDocBrief>{BS}/"\\date" { BEGIN( lastBriefContext ); }
+<ClassDocBrief>{BS}/("\\"|"@")"param" { BEGIN( lastBriefContext ); }
+<ClassDocBrief>{BS}/("\\"|"@")"exception" { BEGIN( lastBriefContext ); }
+<ClassDocBrief>{BS}/("\\"|"@")"return" { BEGIN( lastBriefContext ); }
+<ClassDocBrief>{BS}/("\\sa"|"@see") { BEGIN( lastBriefContext ); }
+<ClassDocBrief>{BS}/("\\"|"@")"bug" { BEGIN( lastBriefContext ); }
+<ClassDocBrief>{BS}/("\\"|"@")"warning" { BEGIN( lastBriefContext ); }
+<ClassDocBrief>{BS}/("\\"|"@")"par"{BN}+ { BEGIN( lastBriefContext ); }
+<ClassDocBrief>{BS}/("\\brief"|"@short"){BN}+ {
+ lastBriefContext=YY_START;
+ BEGIN( ClassDocBrief );
+ }
+<ClassDocBrief>. { current->brief += *yytext; }
+<ClassDocDefine>{ID}/"(" {
+ current->name = yytext;
+ BEGIN( ClassDefineArgs );
+ }
+<ClassDocDefine>{ID} {
+ current->name = yytext;
+ if (nextDefContext==ClassDoc)
+ newDocState();
+ else
+ BEGIN( nextDefContext );
+ }
+<ClassDefineArgs>")" {
+ current->args+=")";
+ if (nextDefContext==ClassDoc)
+ newDocState();
+ else
+ BEGIN( nextDefContext );
+ }
+<ClassDefineArgs>. {
+ current->args+= yytext;
+ }
+<ClassDocFunc>"\n" {
+ yyLineNr++;
+ current->name = current->name.stripWhiteSpace();
+ if (current->section == Entry::MEMBERDOC_SEC && current->args.length()==0)
+ current->section = Entry::VARIABLEDOC_SEC;
+ newDocState();
+ }
+<ClassDocFunc>"(" {
+ current->args+=*yytext;
+ currentArgumentContext = ClassDocFuncQual;
+ copyArgString=&current->args;
+ BEGIN( ReadFuncArgType ) ;
+ }
+<ClassDocFunc>"("({B}*"*")+ {
+ current->name+="(*";
+ BEGIN( ClassDocFuncPtr );
+ }
+<ClassDocFuncPtr>{SCOPENAME} {
+ current->name+=yytext;
+ }
+<ClassDocFuncPtr>")" {
+ current->name+=')';
+ BEGIN( ClassDocFunc );
+ }
+<ClassDocFuncQual>{B}*"const"{B}* {
+ current->args += " const ";
+ current->argList->constSpecifier=TRUE;
+ }
+<ClassDocFuncQual>{B}*"volatile"{B}* {
+ current->args += " volatile ";
+ current->argList->volatileSpecifier=TRUE;
+ }
+<ClassDocFuncQual>{B}*"="{B}*"0"{B}* {
+ current->args += " = 0";
+ current->virt = Pure;
+ current->argList->pureSpecifier=TRUE;
+ }
+<ClassDocFuncQual>"throw"{B}*"(" {
+ current->exception = "throw(";
+ BEGIN(ClassDocFuncExc);
+ }
+<ClassDocFuncExc>")" {
+ current->exception += ')';
+ BEGIN(ClassDocFuncQual);
+ }
+<ClassDocFuncExc>. {
+ current->exception += *yytext;
+ }
+<ClassDocFunc,ClassDocFuncQual>. {
+ current->name += *yytext;
+ }
+<ClassDocFuncQual>"\n" {
+ yyLineNr++;
+ current->name = current->name.stripWhiteSpace();
+ newDocState();
+ }
+<Doc>. { current->doc += *yytext; }
+<DefLineDoc,LineDoc>. { current->brief += *yytext; }
+<Doc>\n { yyLineNr++; current->doc += *yytext; }
+<LineDoc>\n {
+ yyLineNr++;
+ BEGIN( lastDocContext );
+ }
+<DefLineDoc>\n {
+ yyLineNr++;
+ unput('/');unput('*');
+ BEGIN( ClassDoc );
+ }
+
+<AfterDocLine>"/*"|"//" { current->brief+=yytext; }
+<AfterDocLine>\n {
+ if (afterDocTerminator!=0)
+ unput(afterDocTerminator);
+ BEGIN(lastAfterDocContext);
+ }
+<AfterDocLine>. { current->brief+=yytext; }
+<AfterDocBrief>"/*"|"//" { current->brief+=yytext; }
+<AfterDocBrief>^{B}*"*"+/[^/\n]
+<AfterDocBrief>\n { current->brief+=yytext; yyLineNr++; }
+<AfterDocBrief>. { current->brief+=*yytext; }
+<AfterDocBrief>^{B}*"*"/[^/\n]{BL} { yyLineNr++;
+ if (!current->brief.stripWhiteSpace().isEmpty())
+ BEGIN(AfterDoc);
+ }
+<AfterDocBrief>"*/" {
+ if (afterDocTerminator!=0)
+ unput(afterDocTerminator);
+ BEGIN(lastAfterDocContext);
+ }
+<AfterDocBrief>"."/{BN} { BEGIN(AfterDoc); }
+<AfterDoc>("\\"|"@")"brief" { BEGIN(AfterDocBrief); }
+<AfterDoc>"/*"|"//" { current->doc+=yytext; }
+<AfterDoc>^{B}*"*"+/[^/]
+<AfterDoc>\n { current->doc+=yytext; yyLineNr++; }
+<AfterDoc>. { current->doc+=*yytext; }
+<AfterDoc>"*/" {
+ if (afterDocTerminator!=0)
+ unput(afterDocTerminator);
+ BEGIN(lastAfterDocContext);
+ }
+<ClassDocRelates,ClassDocFunc,ClassDocDefine,GroupDocArg1,ClassDocArg1,SectionTitle,EnumDocArg1,FileDocArg1,PageDocArg1,ExampleDocArg1,ClassDefineArgs>"*/" {
+ current->doc += "\n\n";
+ err("Warning: unexpected end of "
+ "documentation block found in "
+ "file %s at line %d\n",yyFileName,yyLineNr);
+ BEGIN( lastDocContext );
+ }
+<Doc>"*/" {
+ current->doc += "\n\n";
+ BEGIN( lastDocContext );
+ }
+<JavaDoc>"*/" {
+ unput('/');unput('*');
+ BEGIN( tmpDocType );
+ }
+<Doc,JavaDoc,ClassDoc,PageDoc,ExampleDoc,ReadFormulaShort,ReadFormulaLong,ClassDocBrief>^{B}*(("//"{B}*)?)"*"+/[^/]
+<DefLineDoc,LineDoc,ClassDoc,Doc>"/*" { current->doc += yytext; }
+
+<SkipCxxComment>.*\n { yyLineNr++ ;
+ BEGIN( lastCContext ) ;
+ }
+<*>.
+<*>\n { yyLineNr++ ; }
+<SkipComment>"//"|"/*"
+<*>"/*" { lastCContext = YY_START ;
+ BEGIN( SkipComment ) ;
+ }
+<SkipComment>{B}*"*/" { BEGIN( lastCContext ) ; }
+<*>"//" {
+ lastCContext = YY_START ;
+ BEGIN( SkipCxxComment ) ;
+ }
+%%
+
+//----------------------------------------------------------------------------
+
+void scanString(const char *s)
+{
+ const char *oldInputString = inputString;
+ int oldInputPosition = inputPosition;
+ YY_BUFFER_STATE oldBuffer = YY_CURRENT_BUFFER;
+ yy_switch_to_buffer(yy_create_buffer(scanYYin, YY_BUF_SIZE));
+ inputString = s;
+ inputPosition = 0;
+ scanYYlex();
+ yy_delete_buffer(YY_CURRENT_BUFFER);
+ yy_switch_to_buffer(oldBuffer);
+ inputString = oldInputString;
+ inputPosition = oldInputPosition;
+}
+
+//----------------------------------------------------------------------------
+
+static void newDocState()
+{
+ if (tmpDocType!=-1)
+ {
+ tmpDocType=ClassDoc;
+ BEGIN(JavaDoc);
+ }
+ else
+ {
+ BEGIN(ClassDoc);
+ }
+}
+
+//----------------------------------------------------------------------------
+
+void parseCompounds(Entry *rt)
+{
+ //printf("parseCompounds(%s)\n",rt->name.data());
+ EntryListIterator eli(*rt->sublist);
+ Entry *ce;
+ for (;(ce=eli.current());++eli)
+ {
+ if (ce->program.length()>0)
+ {
+ //printf("-- %s ---------\n%s\n---------------\n",
+ // ce->name.data(),ce->program.data());
+ // init scanner state
+ inputString = ce->program;
+ inputPosition = 0;
+ scanYYrestart( scanYYin ) ;
+ if (ce->section==Entry::ENUM_SEC)
+ BEGIN( FindFields ) ;
+ else
+ BEGIN( FindMembers ) ;
+ current_root = ce ;
+ strcpy( yyFileName, ce->fileName ) ;
+ yyLineNr = ce->startLine ;
+ //current->reset();
+ current = new Entry;
+ // set default protection based on the compound type
+ if( ce->section==Entry::CLASS_SEC ) // class
+ current->protection = protection = Private ;
+ else if (ce->section == Entry::ENUM_SEC ) // enum
+ current->protection = protection = ce->protection;
+ else if (ce->name.length()>0 && ce->name.at(0)=='@') // anonymous union
+ current->protection = protection = ce->protection;
+ else // named struct or union
+ current->protection = protection = Public ;
+ sig = FALSE;
+ slot = FALSE;
+ gstat = FALSE;
+ virt = Normal;
+ scanYYlex() ;
+ delete current;
+ ce->program.resize(0);
+ }
+ parseCompounds(ce);
+ }
+}
+
+//----------------------------------------------------------------------------
+
+void parseMain(Entry *rt)
+{
+ initParser();
+ anonCount = 0;
+ protection = Public;
+ sig = FALSE;
+ slot = FALSE;
+ gstat = FALSE;
+ virt = Normal;
+ current_root = rt;
+ global_root = rt;
+ current = new Entry;
+ inputString = rt->program;
+ inputPosition = 0;
+ ifCount=0;
+ scanYYrestart( scanYYin );
+ BEGIN( FindMembers );
+ scanYYlex();
+ rt->program.resize(0);
+ delete current;
+ parseCompounds(rt);
+}
+
+//----------------------------------------------------------------------------
+
+void parseDocument(OutputList &ol,const QString &docString)
+{
+ //inParamBlock=inSeeBlock=inReturnBlock=FALSE;
+ curTable = 0;
+ outDoc = new OutputList(&ol);
+ currentIncludeFile.resize(0);
+ includeFileOffset=0;
+ includeFileLength=0;
+ if (!docString) return;
+ linkRef = "";
+ linkText = "";
+ inputString = docString;
+ inputPosition = 0;
+ scanYYrestart( scanYYin );
+ BEGIN( DocScan );
+ insideArgumentList = FALSE;
+ scanYYlex();
+ if (insideArgumentList) { insideArgumentList=FALSE; outDoc->endItemList(); }
+ if (inBlock()) endBlock();
+ ol+=*outDoc;
+ delete outDoc;
+ return;
+}
+
+//----------------------------------------------------------------------------
+
+void parseDoc(OutputList &ol,const char *clName,
+ const char *memName,const QString &docString)
+{
+ initParser();
+ initParseCodeContext();
+ exampleDoc=FALSE; // do not cross reference with member docs
+ className=clName;
+ memberName=memName;
+ if (memName)
+ {
+ refName=className+"::"+memberName;
+ }
+ else
+ {
+ refName=className;
+ }
+ parseDocument(ol,docString);
+}
+
+//----------------------------------------------------------------------------
+
+void parseExample(OutputList &ol,const QString &docString,
+ const char *fileName)
+{
+ initParser();
+ initParseCodeContext();
+ exampleDoc=TRUE; // cross reference with member docs
+ exampleName=fileName;
+ parseDocument(ol,docString);
+}
+
+//----------------------------------------------------------------------------
+
+extern "C" { // some sillyness to keep the compiler happy
+int scanYYwrap() { return 1 ; }
+void bogus() { yy_flex_realloc(0,0); }
+}
+
diff --git a/src/searchindex.cpp b/src/searchindex.cpp
new file mode 100644
index 0000000..241d0a8
--- /dev/null
+++ b/src/searchindex.cpp
@@ -0,0 +1,124 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#include "searchindex.h"
+#include "suffixtree.h"
+
+SearchIndex::SearchIndex() : refDict(10007), nameIndex(10007)
+{
+ indexCount=1;
+ //indexTree = new IndexTree;
+ suffixTree = new SuffixTree;
+}
+
+SearchIndex::~SearchIndex()
+{
+ //delete indexTree;
+ delete suffixTree;
+}
+
+void SearchIndex::addReference(const char *key,const char *ref)
+{
+ DocRef *dr=new DocRef(indexCount,key,ref);
+ nameIndex.insert(indexCount,dr);
+ refList.append(dr);
+ refDict.insert(key,dr);
+ indexCount++;
+}
+
+bool SearchIndex::addWord(const char *key,const char *word,bool special)
+{
+ DocRef *dr=0;
+ if (word && key && strlen(key)>0 && (dr=refDict[key]))
+ {
+ suffixTree->insertWord(((QString)word).lower(),dr->index(),special);
+ return TRUE;
+ }
+ else if (word)
+ {
+ printf("SearchIndex::addWord() key `%s' not found!\n",key);
+ return FALSE;
+ }
+ else
+ {
+ printf("SearchIndex::addWord() trying to insert word with length 0\n");
+ return FALSE;
+ }
+}
+
+bool SearchIndex::saveIndex(const char *fileName)
+{
+ QFile f(fileName);
+ if (!f.open(IO_WriteOnly)) return FALSE;
+
+ // write header
+ if (f.writeBlock("DOXI",4)!=4) return FALSE; // write header
+
+ // compute forward offsets for all children of each node.
+ suffixTree->resolveForwardReferences();
+
+ // compute offset to the reference index table
+ int offset=suffixTree->size()+9;
+
+ // write the offset
+ if (writeNumber(f,offset)) return FALSE;
+
+ // write the suffix tree
+ if (!suffixTree->write(f)) return FALSE;
+
+ f.putch(0);
+
+ // write the index reference table
+ DocRef *dr=refList.first();
+ offset+=refList.count()*4;
+ while (dr)
+ {
+ writeNumber(f,offset);
+ offset+=strlen(dr->name())+strlen(dr->url())+2;
+ dr=refList.next();
+ }
+
+ // write the references
+ dr=refList.first();
+ while (dr)
+ {
+ writeString(f,dr->name());
+ writeString(f,dr->url());
+ dr=refList.next();
+ }
+
+ //printf("Building index tree\n");
+ printf("Size of the suffix tree is %d bytes\n",suffixTree->size());
+ printf("Number of tree nodes is %d\n",suffixTree->numberOfNodes());
+ printf("Number of links %d\n",indexCount);
+ //suffixTree->buildIndex();
+ //printf("Computing reference offsets\n");
+ //int offset=suffixTree->size()+8;
+ //indexTree->setOffsets(&nameIndex);
+ //printf("Saving suffix tree\n");
+ //printf("Saving index tree\n");
+ //result&=indexTree->write(f);
+ //printf("Saving reference list\n");
+ //dr=refList.first();
+ //while (dr)
+ //{
+ // result&=!writeString(f,dr->name());
+ // result&=!writeString(f,dr->url());
+ // dr=refList.next();
+ //}
+ //suffixTree->dump();
+ return TRUE;
+}
diff --git a/src/searchindex.h b/src/searchindex.h
new file mode 100644
index 0000000..64071fb
--- /dev/null
+++ b/src/searchindex.h
@@ -0,0 +1,71 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#ifndef _SEARCHINDEX_H
+#define _SEARCHINDEX_H
+
+#include <qintdict.h>
+#include <qstring.h>
+#include <qlist.h>
+#include <qdict.h>
+
+#include "suffixtree.h"
+
+//class IndexTree;
+class SuffixTree;
+
+class DocRef
+{
+ public:
+ DocRef(int index,const char *name,const char *url)
+ { i=index; n=name; u=url; }
+ ~DocRef() {}
+ void setOffset(int offset) { o=offset; }
+ const char *name() const { return n; }
+ const char *url() const { return u; }
+ int index() const { return i; }
+ int offset() const { return o; }
+
+ private:
+ QString n;
+ QString u;
+ int i;
+ int o;
+};
+
+typedef QList<DocRef> DocRefList;
+typedef QDict<DocRef> DocRefDict;
+
+class SearchIndex
+{
+ public:
+ SearchIndex();
+ ~SearchIndex();
+ void addReference(const char *key,const char *ref);
+ bool addWord(const char *key,const char *word,bool special);
+ bool saveIndex(const char *fileName);
+ void dump() { suffixTree->dump(); }
+
+ private:
+ //IndexTree *indexTree;
+ SuffixTree *suffixTree;
+ DocRefList refList;
+ DocRefDict refDict;
+ QIntDict<DocRef> nameIndex;
+ int indexCount;
+};
+
+#endif
diff --git a/src/suffixtree.cpp b/src/suffixtree.cpp
new file mode 100644
index 0000000..604531f
--- /dev/null
+++ b/src/suffixtree.cpp
@@ -0,0 +1,355 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#include <stdio.h>
+#include "suffixtree.h"
+
+#define MAXWORDLEN 1024
+
+//----------------------------------------------------------------------------
+
+bool writeString(QFile &f,const char *s)
+{
+ int len=strlen(s)+1;
+ return (f.writeBlock(s,len)!=len);
+}
+
+bool writeNumber(QFile &f,int num)
+{
+ return (f.putch((num>>24)&0xff)==-1) ||
+ (f.putch((num>>16)&0xff)==-1) ||
+ (f.putch((num>>8)&0xff)==-1) ||
+ (f.putch(num&0xff)==-1);
+}
+
+bool writeEncodedNumber(QFile &f,uint number)
+{
+ bool error=FALSE;
+ uint n=number;
+ while (n>=128)
+ {
+ int frac=n&0x7f;
+ error = error || (f.putch(frac|0x80)==-1);
+ n>>=7;
+ }
+ error = error || (f.putch(n)==-1);
+ return error;
+}
+
+int encodedNumberSize(uint number)
+{
+ uint n=number;
+ int size=1;
+ while (n>=128) { size++; n>>=7; }
+ return size;
+}
+
+//----------------------------------------------------------------------------
+
+int SuffixNodeList::compareItems(GCI item1,GCI item2)
+{
+ SuffixNode *n1=(SuffixNode *)item1;
+ SuffixNode *n2=(SuffixNode *)item2;
+ return strcmp(n1->label,n2->label);
+}
+
+SuffixNode::SuffixNode(const char *lab) : references(0)
+{
+ children = new SuffixNodeList;
+ children->setAutoDelete(TRUE);
+ label=lab;
+ totalFreq=0;
+ branchOffset=0;
+}
+
+SuffixNode::~SuffixNode()
+{
+ delete children;
+}
+
+void SuffixNode::addReference(int refId,int inName,int fullWord)
+{
+ totalFreq++;
+ uint s=references.size();
+ if (s>0 && references.at(s-1).id==refId) // word occured in the same document
+ {
+ references.at(s-1).freq++; // increase word's frequency
+ references.at(s-1).flags=((references.at(s-1).flags & INNAME_MASK)
+ | (inName<<INNAME_BIT))
+ +((references.at(s-1).flags & FULLWORD_MASK)
+ | (fullWord<<FULLWORD_BIT))
+ +((references.at(s-1).flags & WORDINNAME_MASK)
+ | ((inName & fullWord)<<WORDINNAME_BIT));
+ }
+ else
+ {
+ references.resize(s+1);
+ references.at(s).id=refId;
+ references.at(s).freq=1;
+ references.at(s).flags=(inName<<INNAME_BIT)
+ +(fullWord<<FULLWORD_BIT)
+ +((inName && fullWord)<<WORDINNAME_BIT);
+ }
+}
+
+int SuffixNode::insert(const char *word,int refId,int inName,int fullWord)
+{
+ int numNewNodes=0;
+ //printf("SuffixNode::insert(%s,%d)\n",word,refId);
+ SuffixNode *sn=children->first();
+ while (sn)
+ {
+ char *lab=sn->label.data();
+ char w=word[0],l=lab[0],i=0;
+ while (w!=0 && l!=0 && w==l) { i++; w=word[i]; l=lab[i]; }
+ if (w==0 && l==0) // match found
+ {
+ sn->addReference(refId,inName,fullWord);
+ return numNewNodes;
+ }
+ if (i>0) // w and l contain a common prefix of length i
+ {
+ if (l==0) // w!=0 => follow this branch
+ {
+ sn->addReference(refId,inName,FALSE);
+ numNewNodes+=sn->insert(&word[i],refId,inName,fullWord);
+ }
+ else // l!=0 => split branch
+ {
+ char leftlab[MAXWORDLEN];
+ memcpy(leftlab,lab,i);
+ leftlab[i]='\0';
+ SuffixNode *r = new SuffixNode(leftlab);
+ numNewNodes++;
+ SuffixNode *n2 = children->take();
+ // copy reference info
+ r->references = n2->references.copy();
+ int j,refSize = r->references.size();
+ for (j=0;j<refSize;j++)
+ {
+ //r->references[j].fullWord=FALSE;
+ //r->references[j].wordInName=FALSE;
+ r->references[j].flags &= ~(FULLWORD_MASK|WORDINNAME_MASK);
+ }
+ r->totalFreq = n2->totalFreq;
+ //printf("root branch `%s'\n",leftlab);
+ if (w!=0) // two sub branches
+ {
+ SuffixNode *n1 = new SuffixNode(&word[i]);
+ numNewNodes++;
+ n1->addReference(refId,inName,fullWord);
+ r->addReference(refId,inName,FALSE);
+ r->children->append(n1);
+ //printf("Right branch `%s'\n",&word[i]);
+ }
+ else // one sub branch
+ {
+ r->addReference(refId,inName,fullWord);
+ }
+ //printf("Left branch `%s'\n",&lab[i]);
+ n2->label=&lab[i];
+ r->children->append(n2);
+ children->append(r);
+ }
+ return numNewNodes;
+ }
+ sn=children->next();
+ }
+ //printf("new branch `%s'\n",word);
+ SuffixNode *n=new SuffixNode(word);
+ numNewNodes++;
+ n->addReference(refId,inName,fullWord);
+ children->append(n);
+ return numNewNodes;
+}
+
+void SuffixNode::dump(int level,const char *prefix)
+{
+ uint i;
+ if (references.size()>0)
+ {
+ printf("%s (level=%d offset=%d freq=%d) ",
+ prefix,level,branchOffset,totalFreq);
+ for (i=0;i<references.size();i++)
+ printf("%d->%d ",references.at(i).id,references.at(i).freq);
+ printf("\n");
+ }
+ SuffixNode *sn=children->first();
+ while (sn)
+ {
+ sn->dump(level+1,prefix+("-"+sn->label));
+ sn=children->next();
+ }
+}
+
+void SuffixNode::resolveForwardReferences(int &offset)
+{
+ if (children->count()>0)
+ {
+ if (label.length()>0) offset++; // terminator for the previous level
+ branchOffset=offset;
+ }
+ else
+ branchOffset=0;
+ SuffixNode *sn=children->first();
+ while (sn)
+ {
+ offset+=sn->label.length()+5;
+ uint i,refs=sn->references.size();
+ if (refs>0)
+ {
+ offset+=encodedNumberSize(sn->totalFreq);
+ offset+=encodedNumberSize((sn->references[0].id<<3)+
+ sn->references[0].flags);
+ offset+=encodedNumberSize(sn->references[0].freq);
+ for (i=1;i<refs;i++)
+ {
+ offset+=encodedNumberSize(
+ ((sn->references.at(i).id - sn->references.at(i-1).id)<<3)+
+ sn->references.at(i).flags);
+ offset+=encodedNumberSize(sn->references.at(i).freq);
+ }
+ offset+=encodedNumberSize(0);
+ }
+ //printf("Lab=%s offset=%d\n",sn->lab.data(),offset);
+ sn=children->next();
+ }
+ sn=children->first();
+ while (sn)
+ {
+ //printf("Lab=%s offset=%d\n",sn->lab.data(),offset);
+ sn->resolveForwardReferences(offset);
+ sn=children->next();
+ }
+}
+
+int SuffixNode::size()
+{
+ int s=0;
+ if (label.length()>0 && children->count()>0) s++; // for the terminator
+ SuffixNode *sn=children->first();
+ while (sn)
+ {
+ uint i,refs=sn->references.size();
+ s+=sn->size()+sn->label.length()+5;
+ if (refs>0)
+ {
+ s+=encodedNumberSize(sn->totalFreq);
+ s+=encodedNumberSize(
+ (sn->references[0].id<<3)+
+ sn->references[0].flags);
+ s+=encodedNumberSize(sn->references[0].freq);
+ for (i=1;i<refs;i++)
+ {
+ s+=encodedNumberSize(
+ ((sn->references.at(i).id - sn->references.at(i-1).id)<<3)+
+ sn->references.at(i).flags);
+ s+=encodedNumberSize(sn->references.at(i).freq);
+ }
+ s+=encodedNumberSize(0);
+ }
+ sn=children->next();
+ }
+ return s;
+}
+
+bool SuffixNode::write(QFile &f)
+{
+ bool error=FALSE;
+ if (children->count()>0 && label.length()>0) error=error || (f.putch(0)==-1);
+ SuffixNode *sn=children->first();
+ while (sn)
+ {
+ //offset+=sn->lab.length()+1+2*sizeof(int);
+ int i,refs=sn->references.size();
+ error=error || writeString(f,sn->label);
+ error=error || writeNumber(f,sn->branchOffset|((refs==0)?0x80000000:0));
+ if (refs>0)
+ {
+ error=error || writeEncodedNumber(f,sn->totalFreq);
+ error=error || writeEncodedNumber(f,
+ (sn->references[0].id<<3)+
+ sn->references[0].flags);
+ error=error || writeEncodedNumber(f,sn->references[0].freq);
+ for (i=1;i<refs;i++)
+ {
+ error=error || writeEncodedNumber(f,
+ ((sn->references[i].id - sn->references[i-1].id)<<3)+
+ sn->references[i].flags);
+ error=error || writeEncodedNumber(f,sn->references[i].freq);
+ }
+ error=error || writeEncodedNumber(f,0);
+ }
+ //printf("Lab=%s offset=%d\n",sn->lab.data(),offset);
+ sn=children->next();
+ }
+ sn=children->first();
+ while (sn)
+ {
+ error=error || sn->write(f);
+ sn=children->next();
+ }
+ return error;
+}
+
+//----------------------------------------------------------------------------
+
+SuffixTree::SuffixTree()
+{
+ root=new SuffixNode("");
+ nodes=1;
+}
+
+SuffixTree::~SuffixTree()
+{
+ delete root;
+}
+
+void SuffixTree::insertWord(const char *word,int index,bool inName)
+{
+ QString suffix=word;
+ uint i;
+ for (i=2;i<suffix.length()-1;i++)
+ {
+ //printf("Inserting suffix %s\n",suffix.right(i).data());
+ nodes+=root->insert(suffix.right(i),index,inName?1:0,FALSE);
+ }
+ nodes+=root->insert(word,index,inName?1:0,TRUE);
+}
+
+void SuffixTree::dump()
+{
+ root->dump(0,"");
+}
+
+void SuffixTree::resolveForwardReferences()
+{
+ int offset=8;
+ root->resolveForwardReferences(offset);
+}
+
+int SuffixTree::size()
+{
+ return root->size();
+}
+
+bool SuffixTree::write(QFile &f)
+{
+ if (!f.isOpen()) { printf("File not open\n"); return FALSE; }
+ bool error=FALSE;
+ error = error || root->write(f);
+ return !error;
+}
diff --git a/src/suffixtree.h b/src/suffixtree.h
new file mode 100644
index 0000000..381253c
--- /dev/null
+++ b/src/suffixtree.h
@@ -0,0 +1,93 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#ifndef SUFFIXTREE_H
+#define SUFFIXTREE_H
+
+#include <qlist.h>
+#include <qarray.h>
+#include <qstring.h>
+#include <qfile.h>
+
+class SuffixNodeList;
+class IndexTree;
+
+enum WordRefMasks { WORDINNAME_MASK=4, INNAME_MASK=2, FULLWORD_MASK=1 };
+enum WordRefBits { WORDINNAME_BIT=2, INNAME_BIT=1, FULLWORD_BIT=0 };
+
+// bool inName;
+// bool fullWord;
+// bool wordInName;
+
+struct WordRef
+{
+ int id;
+ short freq;
+ char flags;
+};
+
+class SuffixNode
+{
+ friend class SuffixTree;
+ friend class IndexNode;
+ friend class SuffixNodeList;
+ public:
+ SuffixNode(const char *);
+ ~SuffixNode();
+ int insert(const char *word,int refId,int inName,int full);
+ void addReference(int refId,int inName,int fullWord);
+ void dump(int,const char *);
+ void resolveForwardReferences(int &offset);
+ int size(); // return the size of the tree whose root is this node
+ bool write(QFile &f);
+ private:
+ SuffixNodeList *children;
+ QArray<WordRef> references;
+ QString label;
+ int branchOffset;
+ int totalFreq;
+};
+
+class SuffixNodeList : public QList<SuffixNode>
+{
+ public:
+ SuffixNodeList() : QList<SuffixNode>() {}
+ ~SuffixNodeList() {}
+ int compareItems(GCI item1,GCI item2);
+};
+
+class SuffixTree
+{
+ friend class SuffixNode;
+ public:
+ SuffixTree();
+ ~SuffixTree();
+ void insertWord(const char *word,int index,bool inName);
+ //void buildIndex();
+ void resolveForwardReferences();
+ void dump();
+ int size(); // return the size of the (flat) tree in bytes
+ bool write(QFile &f);
+ int numberOfNodes() { return nodes; }
+ private:
+ int nodes;
+ SuffixNode *root;
+};
+
+extern bool writeNumber(QFile &f,int);
+extern bool writeString(QFile &f,const char *s);
+
+#endif
diff --git a/src/tag.h b/src/tag.h
new file mode 100644
index 0000000..d301f4d
--- /dev/null
+++ b/src/tag.h
@@ -0,0 +1,22 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#ifndef TAG_H
+#define TAG_H
+
+extern void parseTagFile(const char *fileName);
+
+#endif
diff --git a/src/tag.l b/src/tag.l
new file mode 100644
index 0000000..edc5cf1
--- /dev/null
+++ b/src/tag.l
@@ -0,0 +1,243 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+%{
+
+/*
+ * includes
+ */
+#include <stdio.h>
+#include <qstring.h>
+#include <qfileinf.h>
+
+#include "classdef.h"
+#include "filedef.h"
+#include "memberdef.h"
+#include "doxygen.h"
+#include "util.h"
+#include "message.h"
+
+#define YY_NO_UNPUT
+#define YY_NEVER_INTERACTIVE 1
+
+static int yyLineNr;
+static QString className;
+static QString fileName;
+static QString tagName;
+static QString memberName;
+static QString anchorName;
+static QString argString;
+static ClassDef *cd;
+static FileDef *fd;
+
+static void addClass(const char *name,const char *fileName)
+{
+ //printf("adding class %s\n",name);
+ if (name!=0 && strlen(name)>0 && classDict[name]==0)
+ {
+ cd = new ClassDef(name,ClassDef::Class,tagName,fileName);
+ fd = 0;
+ classList.inSort(cd);
+ classDict.insert(className,cd);
+ }
+}
+
+static void addFile(const char *name)
+{
+ //printf("adding file %s\n",name);
+ fd = new FileDef(0,name,tagName);
+ FileName *mn;
+ if ((mn=inputNameDict[name]))
+ {
+ mn->append(fd);
+ }
+ else
+ {
+ mn = new FileName(name);
+ mn->append(fd);
+ inputNameList.inSort(mn);
+ inputNameDict.insert(name,mn);
+ }
+ cd = 0;
+ //fileList.inSort(fd);
+ //fileDict.insert(fileName,fd);
+}
+
+static void addMember(const char *name,const char *anchor,const char *args)
+{
+ //printf("adding member %s\n",name);
+ if (cd || fd)
+ {
+ MemberNameDict *mnd=0;
+ MemberNameList *mnl=0;
+ MemberDef *md;
+ md=new MemberDef(0,name,args,0,Public,Normal,FALSE,FALSE,
+ MemberDef::Function,0,0);
+ md->setReference(anchor);
+ if (cd)
+ {
+ //md=new MemberDef(cd,name,args,anchor,tagName);
+ md->setMemberClass(cd);
+ cd->insertMember(md);
+ //printf("Adding member %s %s to class\n",name,args);
+ mnd=&memberNameDict;
+ mnl=&memberNameList;
+ }
+ else
+ {
+ //md=new MemberDef(&unrelatedClass,name,args,anchor,tagName);
+ md->setFileDef(fd);
+ fd->insertMember(md);
+ //printf("Adding global member %s %s\n",name,args);
+ mnd=&functionNameDict;
+ mnl=&functionNameList;
+ }
+ MemberName *mn;
+ if ((mn=(*mnd)[memberName]))
+ {
+ //printf("mn->inSort()\n");
+ mn->append(md);
+ }
+ else
+ {
+ //printf("mn->append()\n");
+ mn=new MemberName(memberName);
+ mn->append(md);
+ //printf("Adding memberName=%s\n",mn->memberName());
+ mnl->inSort(mn);
+ mnd->insert(memberName,mn);
+ }
+ }
+}
+
+/* -----------------------------------------------------------------
+ */
+
+%}
+
+ID [a-z_A-Z][a-z_A-Z0-9]*
+FILE [a-z_A-Z0-9\.\-\+\:\\\/]+
+
+%x Pass1
+%x Pass2
+%x AnchorName
+%x ArgString1
+%x ArgString2
+%x ClassName1
+%x ClassName2
+%x FileName
+%x BaseClasses
+%x ClassFile1
+%x ClassFile2
+
+%%
+
+<Pass1>^">" {
+ BEGIN(ClassName1);
+ }
+<Pass1>^"&" {
+ BEGIN(FileName);
+ }
+<Pass1>^[~a-z_A-Z][^ \n]*/" " {
+ memberName=yytext;
+ BEGIN(AnchorName);
+ }
+<Pass2>^">" {
+ BEGIN(ClassName2);
+ }
+<AnchorName>{ID} {
+ anchorName=yytext;
+ BEGIN(ArgString1);
+ }
+<ArgString1>"\"" {
+ BEGIN(ArgString2);
+ }
+<ArgString2>[^\"\n]*/"\"" {
+ argString=yytext;
+ addMember(memberName,anchorName,argString);
+ BEGIN(Pass1);
+ }
+<FileName>{FILE}/":" {
+ fileName=yytext;
+ addFile(yytext);
+ BEGIN(Pass1);
+ }
+<ClassName1>{ID}/":" {
+ className=yytext;
+ BEGIN(ClassFile1);
+ }
+<ClassFile1>\" {
+ BEGIN(ClassFile2);
+ }
+<ClassFile2>[^\"]*/\" {
+ addClass(className,yytext);
+ BEGIN(Pass1);
+ }
+<ClassFile2>\n {
+ yyLineNr++;
+ BEGIN(Pass1);
+ }
+<ClassName2>{ID}/":" {
+ cd=getClass(yytext);
+ BEGIN(BaseClasses);
+ }
+<BaseClasses>{ID}/"?" {
+ ClassDef *bcd=getClass(yytext);
+ if (cd && bcd)
+ {
+ cd->insertBaseClass(bcd,Public,Normal);
+ bcd->insertSuperClass(cd,Public,Normal);
+ }
+ }
+<BaseClasses>\n {
+ yyLineNr++;
+ BEGIN(Pass2);
+ }
+<*>.
+<*>\n { yyLineNr++ ; }
+
+%%
+
+/*@ ----------------------------------------------------------------------------
+ */
+
+void parseTagFile(const char *fileName)
+{
+ FILE *f=fopen(fileName,"r");
+ QFileInfo fi(fileName);
+ if (!f || !fi.exists());
+ tagName = fi.fileName();
+ tagYYin = f;
+
+ cd=0;
+ yyLineNr = 1;
+ tagYYrestart( tagYYin );
+ BEGIN(Pass1);
+ tagYYlex();
+
+ rewind(f);
+ cd=0;
+ yyLineNr = 1;
+ tagYYrestart( tagYYin );
+ BEGIN(Pass2);
+ tagYYlex();
+
+ fclose(f);
+}
+
+extern "C" { // some bogus code to keep the compiler happy
+ int tagYYwrap() { return 1 ; }
+}
diff --git a/src/translator.h b/src/translator.h
new file mode 100644
index 0000000..55b6eaf
--- /dev/null
+++ b/src/translator.h
@@ -0,0 +1,280 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#ifndef TRANSLATOR_H
+#define TRANSLATOR_H
+
+#include <qstring.h>
+
+class Translator
+{
+ public:
+ virtual QString latexBabelPackage()
+ { return ""; }
+ virtual QString trInherits()
+ { return "Inherits"; }
+ virtual QString trAnd()
+ { return "and"; }
+ virtual QString trInheritedBy()
+ { return "Inherited By"; }
+ virtual QString trRelatedFunctions()
+ { return "Related Functions"; }
+ virtual QString trRelatedSubscript()
+ { return "(Note that these are not member functions.)"; }
+ virtual QString trDetailedDescription()
+ { return "Detailed Description"; }
+ virtual QString trMemberTypedefDocumentation()
+ { return "Member Typedef Documentation"; }
+ virtual QString trMemberEnumerationDocumentation()
+ { return "Member Enumeration Documentation"; }
+ virtual QString trMemberFunctionDocumentation()
+ { return "Member Function Documentation"; }
+ virtual QString trMemberDataDocumentation()
+ { return "Member Data Documentation"; }
+ virtual QString trGeneratedFrom(const char *s,bool single)
+ { // here s is one of " Class", " Struct" or " Union"
+ // single is true implies a single file
+ QString result=(QString)"The documentation for this"+s+
+ " was generated from the following file";
+ if (single) result+=":"; else result+="s:";
+ return result;
+ }
+ virtual QString trMore()
+ { return "More..."; }
+ virtual QString trReference()
+ { return "Reference"; }
+ virtual QString trListOfAllMembers()
+ { return "List of all members."; }
+ virtual QString trMemberList()
+ { return "Member List"; }
+ virtual QString trThisIsTheListOfAllMembers()
+ { return "This is the complete list of members for"; }
+ virtual QString trIncludingInheritedMembers()
+ { return "including all inherited members."; }
+ virtual QString trGeneratedAutomatically(const char *s)
+ { QString result="Generated automatically by Doxygen";
+ if (s) result+=(QString)" for "+s;
+ result+=" from the source code.";
+ return result;
+ }
+ virtual QString trEnumName()
+ { return "enum name"; }
+ virtual QString trEnumValue()
+ { return "enum value"; }
+ virtual QString trDefinedIn()
+ { return "defined in"; }
+ virtual QString trIncludeFile()
+ { return "Include File"; }
+ virtual QString trVerbatimText(const char *f)
+ { return (QString)"This is the verbatim text of the "+f+" include file."; }
+
+
+ virtual QString trModules()
+ { return "Modules"; }
+ virtual QString trClassHierarchy()
+ { return "Class Hierarchy"; }
+ virtual QString trCompoundList()
+ { return "Compound List"; }
+ virtual QString trFileList()
+ { return "File List"; }
+ virtual QString trHeaderFiles()
+ { return "Header Files"; }
+ virtual QString trCompoundMembers()
+ { return "Compound Members"; }
+ virtual QString trFileMembers()
+ { return "File Members"; }
+ virtual QString trRelatedPages()
+ { return "Related Pages"; }
+ virtual QString trExamples()
+ { return "Examples"; }
+ virtual QString trSearch()
+ { return "Search"; }
+
+ virtual QString trClassHierarchyDescription()
+ { return "This inheritance list is sorted roughly, "
+ "but not completely, alphabetically:";
+ }
+ virtual QString trFileListDescription(bool extractAll)
+ {
+ QString result="Here is a list of all ";
+ if (!extractAll) result+="documented ";
+ result+="files with brief descriptions:";
+ return result;
+ }
+ virtual QString trCompoundListDescription()
+ { return "Here are the classes, structs and "
+ "unions with brief descriptions:";
+ }
+ virtual QString trCompoundMembersDescription(bool extractAll)
+ {
+ QString result="Here is a list of all ";
+ if (!extractAll) result+="documented ";
+ result+="class members with links to ";
+ if (extractAll)
+ result+="the class documentation for each member:";
+ else
+ result+="the classes they belong to:";
+ return result;
+ }
+ virtual QString trFileMembersDescription(bool extractAll)
+ {
+ QString result="Here is a list of all ";
+ if (!extractAll) result+="documented ";
+ result+="file members with links to ";
+ if (extractAll)
+ result+="the file documentation for each member:";
+ else
+ result+="the files they belong to:";
+ return result;
+ }
+ virtual QString trHeaderFilesDescription()
+ { return "Here are the header files that make up the API:"; }
+ virtual QString trExamplesDescription()
+ { return "Here is a list of all examples:"; }
+ virtual QString trRelatedPagesDescription()
+ { return "Here is a list of all related documentation pages:"; }
+ virtual QString trModulesDescription()
+ { return "Here is a list of all modules:"; }
+ virtual QString trNoDescriptionAvailable()
+ { return "No description available"; }
+
+ virtual QString trDocumentation()
+ { return "Documentation"; }
+ virtual QString trModuleIndex()
+ { return "Module Index"; }
+ virtual QString trHierarchicalIndex()
+ { return "Hierarchical Index"; }
+ virtual QString trCompoundIndex()
+ { return "Compound Index"; }
+ virtual QString trFileIndex()
+ { return "File Index"; }
+ virtual QString trModuleDocumentation()
+ { return "Module Documentation"; }
+ virtual QString trClassDocumentation()
+ { return "Class Documentation"; }
+ virtual QString trFileDocumentation()
+ { return "File Documentation"; }
+ virtual QString trExampleDocumentation()
+ { return "Example Documentation"; }
+ virtual QString trPageDocumentation()
+ { return "Page Documentation"; }
+ virtual QString trReferenceManual()
+ { return "Reference Manual"; }
+
+ virtual QString trDefines()
+ { return "Defines"; }
+ virtual QString trFuncProtos()
+ { return "Function Prototypes"; }
+ virtual QString trTypedefs()
+ { return "Typedefs"; }
+ virtual QString trEnumerations()
+ { return "Enumerations"; }
+ virtual QString trFunctions()
+ { return "Functions"; }
+ virtual QString trVariables()
+ { return "Variables"; }
+ virtual QString trEnumerationValues()
+ { return "Enumeration values"; }
+ virtual QString trReimplementedFrom()
+ { return "Reimplemented from"; }
+ virtual QString trReimplementedIn()
+ { return "Reimplemented in"; }
+ virtual QString trAuthor()
+ { return "Author"; }
+ virtual QString trDefineDocumentation()
+ { return "Define Documentation"; }
+ virtual QString trFunctionPrototypeDocumentation()
+ { return "Function Prototype Documentation"; }
+ virtual QString trTypedefDocumentation()
+ { return "Typedef Documentation"; }
+ virtual QString trEnumerationTypeDocumentation()
+ { return "Enumeration Type Documentation"; }
+ virtual QString trEnumerationValueDocumentation()
+ { return "Enumeration Value Documentation"; }
+ virtual QString trFunctionDocumentation()
+ { return "Function Documentation"; }
+ virtual QString trVariableDocumentation()
+ { return "Variable Documentation"; }
+ virtual QString trCompounds()
+ { return "Compounds"; }
+ virtual QString trFiles()
+ { return "Files"; }
+
+ virtual QString trGeneratedAt(const char *date,const char *projName)
+ {
+ QString result=(QString)"Generated at "+date;
+ if (projName) result+=(QString)" for "+projName;
+ result+=(QString)" by";
+ return result;
+ }
+ virtual QString trWrittenBy()
+ {
+ return "written by";
+ }
+
+ virtual QString trClassDiagram(const char *clName)
+ {
+ return (QString)"Class diagram for "+clName;
+ }
+
+ virtual QString trForInternalUseOnly()
+ { return "For internal use only."; }
+ virtual QString trReimplementedForInternalReasons()
+ { return "Reimplemented for internal reasons; the API is not affected."; }
+ virtual QString trWarning()
+ { return "Warning"; }
+ virtual QString trBugsAndLimitations()
+ { return "Bugs and limitations"; }
+ virtual QString trVersion()
+ { return "Version"; }
+ virtual QString trDate()
+ { return "Date"; }
+ virtual QString trAuthors()
+ { return "Author(s)"; }
+ virtual QString trReturns()
+ { return "Returns"; }
+ virtual QString trSeeAlso()
+ { return "See also"; }
+ virtual QString trParameters()
+ { return "Parameters"; }
+ virtual QString trExceptions()
+ { return "Exceptions"; }
+ virtual QString trGeneratedBy()
+ { return "Generated by"; }
+
+ // new since 0.49-990307
+
+ virtual QString trNamespaces()
+ { return "Namespaces"; }
+ virtual QString trNamespaceList()
+ { return "Namespace List"; }
+ virtual QString trNamespaceListDescription(bool extractAll)
+ {
+ QString result="Here is a list of all ";
+ if (!extractAll) result+="documented ";
+ result+="namespaces with brief descriptions:";
+ return result;
+ }
+ virtual QString trFriends()
+ { return "Friends"; }
+
+ // new since 0.49-990405
+
+ virtual QString trRelatedFunctionDocumentation()
+ { return "Friends And Related Function Documentation"; }
+};
+
+#endif
diff --git a/src/translator_cz.h b/src/translator_cz.h
new file mode 100644
index 0000000..9a0656e
--- /dev/null
+++ b/src/translator_cz.h
@@ -0,0 +1,278 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#ifndef TRANSLATOR_CZ_H
+#define TRANSLATOR_CZ_H
+
+#include <qstring.h>
+
+// The translation from English to Czech by Vlastimil Havran.
+// In the cases where are more translations possible I hope
+// that I have selected the most reasonable text. If not, please,
+// mail the comments and text proposals to
+//
+// havran@fel.cvut.cz, 1999/04/11
+
+class TranslatorCzech : public Translator
+{
+ public:
+ QString latexBabelPackage()
+ { return "czech"; }
+ QString trInherits()
+ { return "Dedi"; }
+ QString trAnd()
+ { return "a"; }
+ QString trInheritedBy()
+ { return "Je Potomkem"; }
+ QString trRelatedFunctions()
+ { return "Pribuzne Metody"; }
+ QString trRelatedSubscript()
+ { return "(Tyto funkce nejsou metody.)"; }
+ QString trDetailedDescription()
+ { return "Podrobna Dokumentace"; }
+ QString trMemberTypedefDocumentation()
+ { return "Dokumentace pro Deklaraci Typu (typedef) ve Tride";}
+ QString trMemberEnumerationDocumentation()
+ { return "Dokumentace Vyctovych Typu"; }
+ QString trEnumerationValueDocumentation()
+ { return "Dokumentace Hodnot Vyctovych Typu"; }
+ QString trMemberFunctionDocumentation()
+ { return "Dokumentace Metod"; }
+ QString trMemberDataDocumentation()
+ { return "Dokumentace Datovych Slozek Tridy"; }
+ QString trGeneratedFrom(const char *s,bool single)
+ {
+ QString result=(QString)"Dokumentace pro tento"+s+
+ " byla generovana z nasledujiciho souboru";
+ if (single) result+=":"; else result+="s:";
+ return result;
+ }
+ QString trMore()
+ { return "Detaily"; }
+ QString trReference()
+ { return "Reference"; }
+ QString trListOfAllMembers()
+ { return "Seznam vsech datovych slozek a metod tridy."; }
+ QString trMemberList()
+ { return "Seznam datovych polozek a metod tridy"; }
+ QString trThisIsTheListOfAllMembers()
+ { return "Toto je uplny seznam datovych slozek a metod tridy pro"; }
+ QString trIncludingInheritedMembers()
+ { return "zahrnuje vsechny nasledujici zdedene datove slozky a metody."; }
+ QString trGeneratedAutomatically(const char *s)
+ { QString result="Automaticky vygenerovany pomoci programu Doxygen";
+ if (s) result+=(QString)" pro "+s;
+ result+=" ze zdrojoveho souboru.";
+ return result;
+ }
+ QString trEnumName()
+ { return "pojmenovani vyctoveho typu"; }
+ QString trEnumValue()
+ { return "hodnota vyctoveho typu"; }
+ QString trDefinedIn()
+ { return "definovany v"; }
+ QString trIncludeFile()
+ { return "Vklada soubor"; }
+ QString trVerbatimText(const char *f)
+ { return (QString)"Toto je presny text z vlozeneho souboru "+f+""; }
+ QString trModules()
+ { return "Moduly"; }
+ QString trClassHierarchy()
+ { return "Hierarchie trid"; }
+ QString trCompoundList()
+ { return "Seznam objektovych typu"; }
+ QString trFileList()
+ { return "Seznam souboru"; }
+ QString trHeaderFiles()
+ { return "Hlavickove soubory"; }
+ QString trCompoundMembers()
+ { return "Datove slozky a metody objektovych typu"; }
+ QString trFileMembers()
+ { return "Globalni deklarace"; }
+ QString trRelatedPages()
+ { return "Souvisejici stranky"; }
+ QString trExamples()
+ { return "Priklady:"; }
+ QString trSearch()
+ { return "Hledej"; }
+ QString trClassHierarchyDescription()
+ { return "Tento seznam dedicnych zavislosti je temer setriden"
+ " podle abecedy:";
+ }
+ QString trFileListDescription(bool extractAll)
+ {
+ QString result="A toto je seznam vsech ";
+ if (!extractAll) result+="dokumentovanych ";
+ result+="souboru s kratkymi popisy:";
+ return result;
+ }
+ QString trCompoundListDescription()
+ { return "Zde jsou tridy, struktury a "
+ "unie s kratkymi popisy:";
+ }
+ QString trCompoundMembersDescription(bool extractAll)
+ {
+ QString result="Zde je seznam vsech ";
+ if (!extractAll) result+="dokumentovanych ";
+ result+="clenu tridy (metod a datovych slozek) s odkazy na ";
+ if (extractAll) result+="dokumentaci tridy pro kazdo polozku:";
+ else result+="tridy, kam patri:";
+ return result;
+ }
+ QString trFileMembersDescription(bool extractAll)
+ {
+ QString result="Zde je seznam vsech ";
+ if (!extractAll) result+="zdokumentovanych ";
+ result+="globalnich deklaraci s odkazy ";
+ if (extractAll) result+="na dokumentaci k souboru pro kazdou deklaraci:";
+ else result+="na soubory, kde jsou umisteny:";
+ return result;
+ }
+ QString trHeaderFilesDescription()
+ {return "Zde jsou hlavickove soubory ktere tvori programove"
+ " rozhrani aplikace(API):";
+ }
+ QString trExamplesDescription()
+ { return "Zde je seznam vsech prikladu:"; }
+ QString trRelatedPagesDescription()
+ { return "Zde je seznam vsech souvisejicich stranek dokumentace:"; }
+ QString trModulesDescription()
+ { return "Zde je seznam vsech modulu:"; }
+ QString trNoDescriptionAvailable()
+ { return "Zadny popis neni k dispozici."; }
+
+ QString trDocumentation()
+ { return "Dokumentace"; }
+ QString trModuleIndex()
+ { return "Index modulu"; }
+ QString trHierarchicalIndex()
+ { return "Index Hierarchie"; }
+ QString trCompoundIndex()
+ { return "Index objektovych typu"; }
+ QString trFileIndex()
+ { return "Index souboru"; }
+ QString trModuleDocumentation()
+ { return "Dokumentace modulu"; }
+ QString trClassDocumentation()
+ { return "Dokumentace tridy"; }
+ QString trFileDocumentation()
+ { return "Dokumentace souboru"; }
+ QString trExampleDocumentation()
+ { return "Dokumentace prikladu"; }
+ QString trPageDocumentation()
+ { return "Dokumentace stranek"; }
+ QString trReferenceManual()
+ { return "Referencni manual"; }
+
+ QString trDefines()
+ { return "Definice"; }
+ QString trFuncProtos()
+ { return "Prototypy funkci"; }
+ QString trTypedefs()
+ { return "Deklarace datovych typu(typedefs)"; }
+ QString trEnumerations()
+ { return "Vyctove typy (enumerations)"; }
+ QString trFunctions()
+ { return "Funkce"; }
+ QString trVariables()
+ { return "Promenne"; }
+ QString trEnumerationValues()
+ { return "Hodnoty vyctovych typu"; }
+ QString trReimplementedFrom()
+ { return "Je znovu implementovan z"; }
+ QString trReimplementedIn()
+ { return "Je znovu implementovan v"; }
+ QString trAuthor()
+ { return "Autor"; }
+ QString trDefineDocumentation()
+ { return "Dokumentace definic pomoci maker"; }
+ QString trFunctionPrototypeDocumentation()
+ { return "Dokumentace prototypu funkci"; }
+ QString trTypedefDocumentation()
+ { return "Dokumentace deklaraci datovych typu(typedefs)"; }
+ QString trEnumerationTypeDocumentation()
+ { return "Dokumentace vyctovych typu"; }
+ QString trFunctionDocumentation()
+ { return "Dokumentace funkci"; }
+ QString trVariableDocumentation()
+ { return "Dokumentace promennych"; }
+ QString trCompounds()
+ { return "Polozky objektovych typu"; }
+ QString trFiles()
+ { return "Soubory:"; }
+ QString trGeneratedAt(const char *date,const char *projName)
+ {
+ QString result=(QString)"Gegenerovany v "+date;
+ if (projName) result+=(QString)" pro "+projName;
+ result+=(QString)" ";
+ return result;
+ }
+ QString trWrittenBy()
+ {
+ return "napsany ";
+ }
+ QString trClassDiagram(const char *clName)
+ {
+ return (QString)"Diagram trid pro "+clName;
+ }
+ QString trForInternalUseOnly()
+ { return "Jen pro interni pouziti."; }
+ QString trReimplementedForInternalReasons()
+ {
+ return "Znovu implementovany z internich duvodu; programove rozhrani"
+ " aplikace(API) neni zmeneno.";
+ }
+ QString trWarning()
+ { return "Upozorneni"; }
+ QString trBugsAndLimitations()
+ { return "Chyby a omezeni"; }
+ QString trVersion()
+ { return "Verze"; }
+ QString trDate()
+ { return "Datum"; }
+ QString trAuthors()
+ { return "Autor(i)"; }
+ QString trReturns()
+ { return "ma navratovou hodnotu"; }
+ QString trSeeAlso()
+ { return "Podivej se take na"; }
+ QString trParameters()
+ { return "Parametry"; }
+ QString trExceptions()
+ { return "Vyjimky"; }
+ QString trGeneratedBy()
+ { return "Gegenerovan podle"; }
+
+ // new since 0.49-990307
+
+ QString trNamespaces()
+ { return "Prostory jmen"; }
+ QString trNamespaceList()
+ { return "Seznam prostoru jmen"; }
+ QString trNamespaceListDescription(bool extractAll)
+ {
+ QString result="Zde jsou vsechny ";
+ if (!extractAll) result+="dokumentovane ";
+ result+="prostory jem s kratkymi popisy:";
+ return result;
+ }
+ QString trFriends()
+ { return "Spratelene tridy, funkce a metody"; }
+};
+
+#endif // TRANSLATOR_CZ_H
+
+
diff --git a/src/translator_fr.h b/src/translator_fr.h
new file mode 100644
index 0000000..cd78053
--- /dev/null
+++ b/src/translator_fr.h
@@ -0,0 +1,270 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#ifndef TRANSLATOR_FR_H
+#define TRANSLATOR_FR_H
+
+#include <qstring.h>
+
+class TranslatorFrench : public Translator
+{
+ public:
+ QString latexBabelPackage()
+ { return "french"; }
+ QString trInherits()
+ { return "Hérite de"; }
+ QString trAnd()
+ { return "et"; }
+ QString trInheritedBy()
+ { return "Dérivée par"; }
+ QString trRelatedFunctions()
+ { return "Fonctions associées"; }
+ QString trRelatedSubscript()
+ { return "(Noter que ces fonctions ne sont pas des méthodes de la classe)"; }
+ QString trDetailedDescription()
+ { return "Description détaillée"; }
+ QString trMemberTypedefDocumentation()
+ { return "Documentation des types imbriqués"; }
+ QString trMemberEnumerationDocumentation()
+ { return "Documentation des énumérations imbriqués"; }
+ QString trMemberFunctionDocumentation()
+ { return "Documentation des méthodes"; }
+ QString trMemberDataDocumentation()
+ { return "Documentation des données imbriqués"; }
+ QString trGeneratedFrom(const char *s,bool single)
+ {
+ QString result=(QString)"La documentation pour cette"+s+
+ " a été générée à partir ";
+ if (single) result+="du fichier suivant:";
+ else result+="des fichiers suivants:";
+ return result;
+ }
+ QString trMore()
+ { return "Plus de détails..."; }
+ QString trReference()
+ { return "Référence"; }
+ QString trListOfAllMembers()
+ { return "Liste de tous les membres"; }
+ QString trMemberList()
+ { return "Liste des membres"; }
+ QString trThisIsTheListOfAllMembers()
+ { return "Ceci est la liste complète des membres de"; }
+ QString trIncludingInheritedMembers()
+ { return "y compris des membres des classes héritées."; }
+ QString trGeneratedAutomatically(const char *s)
+ { QString result="Généré automatiquement par Doxygen";
+ if (s) result+=(QString)" pour "+s;
+ result+=" à partir du code source.";
+ return result;
+ }
+ QString trEnumName()
+ { return "énumération"; }
+ QString trEnumValue()
+ { return "élément d'une énumération"; }
+ QString trDefinedIn()
+ { return "défini dans"; }
+ QString trIncludeFile()
+ { return "Fichier inclu"; }
+ QString trVerbatimText(const char *f)
+ { return (QString)"Ce texte provient du fichier inclu "+f+"."; }
+
+
+ QString trModules()
+ { return "Modules"; }
+ QString trClassHierarchy()
+ { return "Hiérarchie des classes"; }
+ QString trCompoundList()
+ { return "Liste des composants"; }
+ QString trFileList()
+ { return "Liste des fichiers"; }
+ QString trHeaderFiles()
+ { return "Fichiers d'entête"; }
+ QString trCompoundMembers()
+ { return "Composants"; }
+ QString trFileMembers()
+ { return "Déclarations"; }
+ QString trRelatedPages()
+ { return "Pages associées"; }
+ QString trExamples()
+ { return "Exemples"; }
+ QString trSearch()
+ { return "Recherche"; }
+ QString trClassHierarchyDescription()
+ { return "Cette liste d'héritage est, autant que possible, "
+ "classée par ordre alphabétique"; }
+ QString trFileListDescription(bool extractAll)
+ {
+ QString result="Liste de tous les fichiers ";
+ if (!extractAll) result+="documentés ";
+ result+="avec une brève description :";
+ return result;
+ }
+ QString trCompoundListDescription()
+ { return "Liste des classes, des strutures et des unions "
+ "avec une brève description :";
+ }
+ QString trCompoundMembersDescription(bool extractAll)
+ {
+ QString result="Liste de tous les membres de classe ";
+ if (!extractAll) result+="documentés ";
+ result+="avec les liens vers ";
+ if (extractAll) result+="la documentation de la classe correspondante :";
+ else result+="les classes auxquelles ils appartiennent :";
+ return result;
+ }
+ QString trFileMembersDescription(bool extractAll)
+ {
+ QString result="Liste de toutes les déclarations";
+ if (!extractAll) result+="documentées ";
+ result+="avec liens sur ";
+ if (extractAll) result+="la documentation du fichier correspondant "
+ "pour chacune :";
+ else result+="les fichiers dans lesquels elles sont définies :";
+ return result;
+ }
+ QString trHeaderFilesDescription()
+ { return "Liste de tous les fichiers d'entête constituant "
+ "l'interface de programmation :"; }
+ QString trExamplesDescription()
+ { return "Liste de tous les exemples :"; }
+ QString trRelatedPagesDescription()
+ { return "Liste de toutes les pages de documentation associées :"; }
+ QString trModulesDescription()
+ { return "Liste de tous les modules"; }
+ QString trNoDescriptionAvailable()
+ { return "Aucune description n'est disponible"; }
+
+ QString trDocumentation()
+ { return "Documentation"; }
+ QString trModuleIndex()
+ { return "Index des modules"; }
+ QString trHierarchicalIndex()
+ { return "Index hiérarchique"; }
+ QString trCompoundIndex()
+ { return "Index des composants"; }
+ QString trFileIndex()
+ { return "Index des fichiers"; }
+ QString trModuleDocumentation()
+ { return "Documentation du module"; }
+ QString trClassDocumentation()
+ { return "Documentation de la classe"; }
+ QString trFileDocumentation()
+ { return "Documentation du fichier"; }
+ QString trExampleDocumentation()
+ { return "Documentation de l'exemple"; }
+ QString trPageDocumentation()
+ { return "Documentation de la page"; }
+ QString trReferenceManual()
+ { return "Manuel de référence"; }
+
+ QString trDefines()
+ { return "Définitions des macros"; }
+ QString trFuncProtos()
+ { return "Prototypes des fonctions"; }
+ QString trTypedefs()
+ { return "Définitions des types"; }
+ QString trEnumerations()
+ { return "Enumérations"; }
+ QString trFunctions()
+ { return "Fonctions"; }
+ QString trVariables()
+ { return "Variables"; }
+ QString trEnumerationValues()
+ { return "Eléments énumérés"; }
+ QString trReimplementedFrom()
+ { return "Redéfini à partir de"; }
+ QString trReimplementedIn()
+ { return "Redéfini dans"; }
+ QString trAuthor()
+ { return "Auteur"; }
+ QString trDefineDocumentation()
+ { return "Documentation de la macro"; }
+ QString trFunctionPrototypeDocumentation()
+ { return "Documentation du prototype de la fonction"; }
+ QString trTypedefDocumentation()
+ { return "Documentation du type"; }
+ QString trEnumerationTypeDocumentation()
+ { return "Documentation du type de l'énumeration"; }
+ QString trEnumerationValueDocumentation()
+ { return "Documentation de l'élément de l'énumeration"; }
+ QString trFunctionDocumentation()
+ { return "Documentation de la fonction"; }
+ QString trVariableDocumentation()
+ { return "Documentation de la variable"; }
+ QString trCompounds()
+ { return "Composants"; }
+ QString trFiles()
+ { return "Fichiers"; }
+ QString trGeneratedAt(const char *date,const char *projName)
+ {
+ QString result=(QString)"Généré le "+date;
+ if (projName) result+=(QString)" pour "+projName;
+ result+=(QString)" par ";
+ return result;
+ }
+ QString trWrittenBy()
+ {
+ return "écrit par";
+ }
+ QString trClassDiagram(const char *clName)
+ {
+ return (QString)"Graphe d'héritage de la classe "+clName;
+ }
+ QString trForInternalUseOnly()
+ { return "A usage interne uniquement."; }
+ QString trReimplementedForInternalReasons()
+ { return "Redéfini pour des raisons internes; "
+ "l'interface n'est pas modifiée";
+ }
+ QString trWarning()
+ { return "Avertissement"; }
+ QString trBugsAndLimitations()
+ { return "Bogues et limitations"; }
+ QString trVersion()
+ { return "Version"; }
+ QString trDate()
+ { return "Date"; }
+ QString trAuthors()
+ { return "Auteur(s)"; }
+ QString trReturns()
+ { return "Renvoie"; }
+ QString trSeeAlso()
+ { return "Voir également"; }
+ QString trParameters()
+ { return "Paramètres"; }
+ QString trExceptions()
+ { return "Exceptions"; }
+ QString trGeneratedBy()
+ { return "Généré par"; }
+
+ // new since 0.49-990307
+
+ virtual QString trNamespaces()
+ { return "Namespaces"; }
+ virtual QString trNamespaceList()
+ { return "List des Namespaces"; }
+ virtual QString trNamespaceListDescription(bool extractAll)
+ {
+ QString result="Liste de tous les namespaces ";
+ if (!extractAll) result+="documentés ";
+ result+="avec une brève description :";
+ return result;
+ }
+ virtual QString trFriends()
+ { return "Friends"; }
+};
+
+#endif
diff --git a/src/translator_it.h b/src/translator_it.h
new file mode 100644
index 0000000..316f43a
--- /dev/null
+++ b/src/translator_it.h
@@ -0,0 +1,266 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#ifndef TRANSLATOR_IT_H
+#define TRANSLATOR_IT_H
+
+#include <qstring.h>
+
+class TranslatorItalian : public Translator
+{
+ public:
+ QString latexBabelPackage()
+ { return "italian"; }
+ QString trInherits()
+ { return "eredita"; }
+ QString trAnd()
+ { return "e"; }
+ QString trInheritedBy()
+ { return "Ereditato da"; }
+ QString trRelatedFunctions()
+ { return "Funzioni relative"; }
+ QString trRelatedSubscript()
+ { return "(Nota che questo no sono funzioni membro)"; }
+ QString trDetailedDescription()
+ { return "Descrizione dettagliata"; }
+ QString trMemberTypedefDocumentation()
+ { return "Documentazione dei membri Typedef"; }
+ QString trMemberEnumerationDocumentation()
+ { return "Documentazione dei membri enumerati"; }
+ QString trEnumerationValueDocumentation()
+ { return "Documentazione dei tipi enumerati"; }
+ QString trMemberFunctionDocumentation()
+ { return "Documentazione delle funzioni membro"; }
+ QString trMemberDataDocumentation()
+ { return "Documentazione dei dati membro"; }
+ QString trGeneratedFrom(const char *s,bool single)
+ {
+ QString result=(QString)"La documentazione di questa "+s+
+ " e stata generata dal seguente file";
+ if (single) result+=":"; else result+=":";
+ return result;
+ }
+ QString trMore()
+ { return "Continua..."; }
+ QString trReference()
+ { return "Riferimento"; }
+ QString trListOfAllMembers()
+ { return "Lista di tuti i memberi."; }
+ QString trMemberList()
+ { return "Lista membri"; }
+ QString trThisIsTheListOfAllMembers()
+ { return "Questa e la lista completa di tutti i membri"; }
+ QString trIncludingInheritedMembers()
+ { return "includendo tutti i membri ereditati."; }
+ QString trGeneratedAutomatically(const char *s)
+ { QString result="Generato automaticalmenta da Doxygen";
+ if (s) result+=(QString)" per "+s;
+ result+=" dall codice.";
+ return result;
+ }
+ QString trEnumName()
+ { return "nome dell enum"; }
+ QString trEnumValue()
+ { return "valore dell enum"; }
+ QString trDefinedIn()
+ { return "definito in"; }
+ QString trIncludeFile()
+ { return "Include il file"; }
+ QString trVerbatimText(const char *f)
+ { return (QString)"Questo e il contenuto verbatim dell file "+f+"."; }
+ QString trModules()
+ { return "Moduli"; }
+ QString trClassHierarchy()
+ { return "gerarchia delle classi"; }
+ QString trCompoundList()
+ { return "Lista dei tipi composti"; }
+ QString trFileList()
+ { return "Lista dei file"; }
+ QString trHeaderFiles()
+ { return "List dei fei file header"; }
+ QString trCompoundMembers()
+ { return "Membri composti"; }
+ QString trFileMembers()
+ { return "Membri dell file"; }
+ QString trRelatedPages()
+ { return "Relativo a pagina"; }
+ QString trExamples()
+ { return "Esempio"; }
+ QString trSearch()
+ { return "Ricerca"; }
+ QString trClassHierarchyDescription()
+ { return "Qua sono la lista delle classi, structs e unions"
+ "gesorte:";
+ }
+ QString trFileListDescription(bool extractAll)
+ {
+ QString result="Hieronder volgt de lijst met alle ";
+ if (!extractAll) result+="gedocumenteerde ";
+ result+="files, elk met een korte beschrijving:";
+ return result;
+ }
+ QString trCompoundListDescription()
+ { return "Hieronder volgen de klassen, structs en "
+ "unions met voor elk een korte beschrijving:";
+ }
+ QString trCompoundMembersDescription(bool extractAll)
+ {
+ QString result="Hieronder volgt de lijst met alle ";
+ if (!extractAll) result+="gedocumenteerde ";
+ result+="klasse members met links naar ";
+ if (extractAll) result+="de klasse Documentazione voor elke member:";
+ else result+="de klassen waartoe ze behoren:";
+ return result;
+ }
+ QString trFileMembersDescription(bool extractAll)
+ {
+ QString result="Hieronder volgt de lijst met alle ";
+ if (!extractAll) result+="gedocumenteerde ";
+ result+="file members met links naar ";
+ if (extractAll) result+="de file Documentazione voor elke member:";
+ else result+="de files waartoe ze behoren:";
+ return result;
+ }
+ QString trHeaderFilesDescription()
+ { return "Hieronder volgen de header files die de API vormen:"; }
+ QString trExamplesDescription()
+ { return "Hieronder volgt de lijst met alle voorbeelden:"; }
+ QString trRelatedPagesDescription()
+ { return "Hieronder volgt de lijst met alle pagina's die gerelateerde Documentazione bevatten:"; }
+ QString trModulesDescription()
+ { return "Hieronder volgt de lijst met alle modules:"; }
+ QString trNoDescriptionAvailable()
+ { return "Geen korte beschrijving beschikbaar"; }
+
+ QString trDocumentation()
+ { return "Documentazione"; }
+ QString trModuleIndex()
+ { return "Module Index"; }
+ QString trHierarchicalIndex()
+ { return "Hi&euml;rarchische Index"; }
+ QString trCompoundIndex()
+ { return "Compound Index"; }
+ QString trFileIndex()
+ { return "File Index"; }
+ QString trModuleDocumentation()
+ { return "Module Documentazione"; }
+ QString trClassDocumentation()
+ { return "Klasse Documentazione"; }
+ QString trFileDocumentation()
+ { return "File Documentazione"; }
+ QString trExampleDocumentation()
+ { return "Documentazione di voorbeelden"; }
+ QString trPageDocumentation()
+ { return "Documentazione di gerelateerde pagina's"; }
+ QString trReferenceManual()
+ { return "Naslagwerk"; }
+
+ QString trDefines()
+ { return "Defines"; }
+ QString trFuncProtos()
+ { return "Functie Prototypes"; }
+ QString trTypedefs()
+ { return "Typedefs"; }
+ QString trEnumerations()
+ { return "Enumeraties"; }
+ QString trFunctions()
+ { return "Functies"; }
+ QString trVariables()
+ { return "Variabelen"; }
+ QString trEnumerationValues()
+ { return "Enumeratie waarden"; }
+ QString trReimplementedFrom()
+ { return "Nieuwe implementatie di"; }
+ QString trReimplementedIn()
+ { return "Opnieuw ge&iuml;mplementeerd in"; }
+ QString trAuthor()
+ { return "auteur"; }
+ QString trDefineDocumentation()
+ { return "Lista "; }
+ QString trFunctionPrototypeDocumentation()
+ { return "Documentazione di functie Prototypes"; }
+ QString trTypedefDocumentation()
+ { return "Documentazione di typedefs"; }
+ QString trEnumerationTypeDocumentation()
+ { return "Documentazione di enumeratie types"; }
+ QString trFunctionDocumentation()
+ { return "Documentazione di functies"; }
+ QString trVariableDocumentation()
+ { return "Lista variabelen"; }
+ QString trCompounds()
+ { return "Compounds"; }
+ QString trFiles()
+ { return "Files"; }
+ QString trGeneratedAt(const char *date,const char *projName)
+ {
+ QString result=(QString)"Gegenereerd op "+date;
+ if (projName) result+=(QString)" voor "+projName;
+ result+=(QString)" door";
+ return result;
+ }
+ QString trWrittenBy()
+ {
+ return "geschreven door";
+ }
+ QString trClassDiagram(const char *clName)
+ {
+ return (QString)"Klasse diagram voor "+clName;
+ }
+ QString trForInternalUseOnly()
+ { return "Alleen voor intern gebruik."; }
+ QString trReimplementedForInternalReasons()
+ { return "Om interne rederene opnieuwd ge&iuml;mplemented; "
+ "de API wordt er niet door be&iuml;nvloed.";
+ }
+ QString trWarning()
+ { return "Waarschuwing"; }
+ QString trBugsAndLimitations()
+ { return "Fouten en beperkingen"; }
+ QString trVersion()
+ { return "Versie"; }
+ QString trDate()
+ { return "Datum"; }
+ QString trAuthors()
+ { return "Auteur(s)"; }
+ QString trReturns()
+ { return "Retourneerd"; }
+ QString trSeeAlso()
+ { return "Zie ook"; }
+ QString trParameters()
+ { return "Parameters"; }
+ QString trExceptions()
+ { return "Excepties"; }
+ QString trGeneratedBy()
+ { return "Gegenereerd door"; }
+
+ // new since 0.49-990307
+
+ QString trNamespaces()
+ { return "Namespaces"; }
+ QString trNamespaceList()
+ { return "Namespace Lijst"; }
+ QString trNamespaceListDescription(bool extractAll)
+ {
+ QString result="Hier is een lijst met alle ";
+ if (!extractAll) result+="gedocumenteerde ";
+ result+="namespaces met voor elk een korte beschrijving:";
+ return result;
+ }
+ QString trFriends()
+ { return "Friends"; }
+};
+
+#endif
diff --git a/src/translator_nl.h b/src/translator_nl.h
new file mode 100644
index 0000000..25e7ed4
--- /dev/null
+++ b/src/translator_nl.h
@@ -0,0 +1,266 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#ifndef TRANSLATOR_NL_H
+#define TRANSLATOR_NL_H
+
+#include <qstring.h>
+
+class TranslatorDutch : public Translator
+{
+ public:
+ QString latexBabelPackage()
+ { return "dutch"; }
+ QString trInherits()
+ { return "Erft over van"; }
+ QString trAnd()
+ { return "en"; }
+ QString trInheritedBy()
+ { return "Wordt overge&euml;rfd door"; }
+ QString trRelatedFunctions()
+ { return "Gerelateerde functies"; }
+ QString trRelatedSubscript()
+ { return "(Merk op dat dit geen member functies zijn.)"; }
+ QString trDetailedDescription()
+ { return "Gedetaileerde Beschrijving"; }
+ QString trMemberTypedefDocumentation()
+ { return "Documentatie van type definitie members"; }
+ QString trMemberEnumerationDocumentation()
+ { return "Documentatie van enumeratie members"; }
+ QString trEnumerationValueDocumentation()
+ { return "Documentatie van enumeratie waarden"; }
+ QString trMemberFunctionDocumentation()
+ { return "Documentatie van functie members"; }
+ QString trMemberDataDocumentation()
+ { return "Documentatie van data members"; }
+ QString trGeneratedFrom(const char *s,bool single)
+ {
+ QString result=(QString)"De documentatie voor deze"+s+
+ " is gegenereerd op grond van de volgende file";
+ if (single) result+=":"; else result+="s:";
+ return result;
+ }
+ QString trMore()
+ { return "Meer..."; }
+ QString trReference()
+ { return "Referentie"; }
+ QString trListOfAllMembers()
+ { return "Lijst van alle members."; }
+ QString trMemberList()
+ { return "Member Lijst"; }
+ QString trThisIsTheListOfAllMembers()
+ { return "Dit is de complete lijst van alle members voor"; }
+ QString trIncludingInheritedMembers()
+ { return "inclusief alle overge&euml;rfde members."; }
+ QString trGeneratedAutomatically(const char *s)
+ { QString result="Automatisch gegenereerd door Doxygen";
+ if (s) result+=(QString)" voor "+s;
+ result+=" uit de programmacode.";
+ return result;
+ }
+ QString trEnumName()
+ { return "enum naam"; }
+ QString trEnumValue()
+ { return "enum waarde"; }
+ QString trDefinedIn()
+ { return "gedefinieerd in"; }
+ QString trIncludeFile()
+ { return "Include File"; }
+ QString trVerbatimText(const char *f)
+ { return (QString)"Dit is de letterlijke tekst van de include file "+f+"."; }
+ QString trModules()
+ { return "Modules"; }
+ QString trClassHierarchy()
+ { return "Klasse Hi&euml;rarchie"; }
+ QString trCompoundList()
+ { return "Compound Lijst"; }
+ QString trFileList()
+ { return "File Lijst"; }
+ QString trHeaderFiles()
+ { return "Header Lijst"; }
+ QString trCompoundMembers()
+ { return "Compound Members"; }
+ QString trFileMembers()
+ { return "File members"; }
+ QString trRelatedPages()
+ { return "Gerelateerde pagina's"; }
+ QString trExamples()
+ { return "Voorbeelden"; }
+ QString trSearch()
+ { return "Zoeken"; }
+ QString trClassHierarchyDescription()
+ { return "Deze inheritance lijst is min of meer alfabetisch "
+ "gesorteerd:";
+ }
+ QString trFileListDescription(bool extractAll)
+ {
+ QString result="Hieronder volgt de lijst met alle ";
+ if (!extractAll) result+="gedocumenteerde ";
+ result+="files, elk met een korte beschrijving:";
+ return result;
+ }
+ QString trCompoundListDescription()
+ { return "Hieronder volgen de klassen, structs en "
+ "unions met voor elk een korte beschrijving:";
+ }
+ QString trCompoundMembersDescription(bool extractAll)
+ {
+ QString result="Hieronder volgt de lijst met alle ";
+ if (!extractAll) result+="gedocumenteerde ";
+ result+="klasse members met links naar ";
+ if (extractAll) result+="de klasse documentatie voor elke member:";
+ else result+="de klassen waartoe ze behoren:";
+ return result;
+ }
+ QString trFileMembersDescription(bool extractAll)
+ {
+ QString result="Hieronder volgt de lijst met alle ";
+ if (!extractAll) result+="gedocumenteerde ";
+ result+="file members met links naar ";
+ if (extractAll) result+="de file documentatie voor elke member:";
+ else result+="de files waartoe ze behoren:";
+ return result;
+ }
+ QString trHeaderFilesDescription()
+ { return "Hieronder volgen de header files die de API vormen:"; }
+ QString trExamplesDescription()
+ { return "Hieronder volgt de lijst met alle voorbeelden:"; }
+ QString trRelatedPagesDescription()
+ { return "Hieronder volgt de lijst met alle pagina's die gerelateerde documentatie bevatten:"; }
+ QString trModulesDescription()
+ { return "Hieronder volgt de lijst met alle modules:"; }
+ QString trNoDescriptionAvailable()
+ { return "Geen korte beschrijving beschikbaar"; }
+
+ QString trDocumentation()
+ { return "Documentatie"; }
+ QString trModuleIndex()
+ { return "Module Index"; }
+ QString trHierarchicalIndex()
+ { return "Hi&euml;rarchische Index"; }
+ QString trCompoundIndex()
+ { return "Compound Index"; }
+ QString trFileIndex()
+ { return "File Index"; }
+ QString trModuleDocumentation()
+ { return "Module Documentatie"; }
+ QString trClassDocumentation()
+ { return "Klasse Documentatie"; }
+ QString trFileDocumentation()
+ { return "File Documentatie"; }
+ QString trExampleDocumentation()
+ { return "Documentatie van voorbeelden"; }
+ QString trPageDocumentation()
+ { return "Documentatie van gerelateerde pagina's"; }
+ QString trReferenceManual()
+ { return "Naslagwerk"; }
+
+ QString trDefines()
+ { return "Defines"; }
+ QString trFuncProtos()
+ { return "Functie Prototypes"; }
+ QString trTypedefs()
+ { return "Typedefs"; }
+ QString trEnumerations()
+ { return "Enumeraties"; }
+ QString trFunctions()
+ { return "Functies"; }
+ QString trVariables()
+ { return "Variabelen"; }
+ QString trEnumerationValues()
+ { return "Enumeratie waarden"; }
+ QString trReimplementedFrom()
+ { return "Nieuwe implementatie van"; }
+ QString trReimplementedIn()
+ { return "Opnieuw ge&iuml;mplementeerd in"; }
+ QString trAuthor()
+ { return "auteur"; }
+ QString trDefineDocumentation()
+ { return "Documentatie van defines"; }
+ QString trFunctionPrototypeDocumentation()
+ { return "Documentatie van functie Prototypes"; }
+ QString trTypedefDocumentation()
+ { return "Documentatie van typedefs"; }
+ QString trEnumerationTypeDocumentation()
+ { return "Documentatie van enumeratie types"; }
+ QString trFunctionDocumentation()
+ { return "Documentatie van functies"; }
+ QString trVariableDocumentation()
+ { return "Documentatie van variabelen"; }
+ QString trCompounds()
+ { return "Compounds"; }
+ QString trFiles()
+ { return "Files"; }
+ QString trGeneratedAt(const char *date,const char *projName)
+ {
+ QString result=(QString)"Gegenereerd op "+date;
+ if (projName) result+=(QString)" voor "+projName;
+ result+=(QString)" door";
+ return result;
+ }
+ QString trWrittenBy()
+ {
+ return "geschreven door";
+ }
+ QString trClassDiagram(const char *clName)
+ {
+ return (QString)"Klasse diagram voor "+clName;
+ }
+ QString trForInternalUseOnly()
+ { return "Alleen voor intern gebruik."; }
+ QString trReimplementedForInternalReasons()
+ { return "Om interne rederene opnieuwd ge&iuml;mplemented; "
+ "de API wordt er niet door be&iuml;nvloed.";
+ }
+ QString trWarning()
+ { return "Waarschuwing"; }
+ QString trBugsAndLimitations()
+ { return "Fouten en beperkingen"; }
+ QString trVersion()
+ { return "Versie"; }
+ QString trDate()
+ { return "Datum"; }
+ QString trAuthors()
+ { return "Auteur(s)"; }
+ QString trReturns()
+ { return "Retourneerd"; }
+ QString trSeeAlso()
+ { return "Zie ook"; }
+ QString trParameters()
+ { return "Parameters"; }
+ QString trExceptions()
+ { return "Excepties"; }
+ QString trGeneratedBy()
+ { return "Gegenereerd door"; }
+
+ // new since 0.49-990307
+
+ QString trNamespaces()
+ { return "Namespaces"; }
+ QString trNamespaceList()
+ { return "Namespace Lijst"; }
+ QString trNamespaceListDescription(bool extractAll)
+ {
+ QString result="Hier is een lijst met alle ";
+ if (!extractAll) result+="gedocumenteerde ";
+ result+="namespaces met voor elk een korte beschrijving:";
+ return result;
+ }
+ QString trFriends()
+ { return "Friends"; }
+};
+
+#endif
diff --git a/src/translator_se.h b/src/translator_se.h
new file mode 100644
index 0000000..15b6c18
--- /dev/null
+++ b/src/translator_se.h
@@ -0,0 +1,250 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#ifndef TRANSLATOR_SE_H
+#define TRANSLATOR_SE_H
+
+#include <qstring.h>
+
+class TranslatorSwedish : public Translator
+{
+ public:
+ QString latexBabelPackage()
+ { return "swedish"; }
+ QString trInherits()
+ { return "Ärver"; }
+ QString trAnd()
+ { return "och"; }
+ QString trInheritedBy()
+ { return "Ärvd av"; }
+ QString trRelatedFunctions()
+ { return "Besläktade funktioner"; }
+ QString trRelatedSubscript()
+ { return "(Observera att dessa inte är medlemsfunktioner)"; }
+ QString trDetailedDescription()
+ { return "Utökad beskrivning"; }
+ QString trMemberTypedefDocumentation()
+ { return "Har inte en aning..."; }
+ QString trMemberEnumerationDocumentation()
+ { return "Uppräknad dokumentation???"; }
+ QString trEnumerationValueDocumentation()
+ { return "Documentatie van enumeratie waarden"; }
+ QString trMemberFunctionDocumentation()
+ { return "Dokumentation av medlemsfunktioner"; }
+ QString trMemberDataDocumentation()
+ { return "Dokumentation av datamedlemmar"; }
+ QString trGeneratedFrom(const char *s,bool single)
+ {
+ QString result=(QString)"Dokumentationen för detta"+s+
+ " är skapad ur följande fil";
+ if (single) result+=":"; else result+="s:";
+ return result;
+ }
+ QString trMore()
+ { return "Fler..."; }
+ QString trReference()
+ { return "Hänvisning?"; }
+ QString trListOfAllMembers()
+ { return "Lista över alla medlemmar."; }
+ QString trMemberList()
+ { return "Medlemslista"; }
+ QString trThisIsTheListOfAllMembers()
+ { return "Det här är en fullständig lista av medlemmar för?"; }
+ QString trIncludingInheritedMembers()
+ { return "med alla ärvda medlemmar."; }
+ QString trGeneratedAutomatically(const char *s)
+ { QString result="Automatiskt skapad av Doxygen";
+ if (s) result+=(QString)" för "+s;
+ result+=" från källkoden.";
+ return result;
+ }
+ QString trEnumName()
+ { return "enum namn?"; }
+ QString trEnumValue()
+ { return "enum värde?"; }
+ QString trDefinedIn()
+ { return "deklarerad i"; }
+ QString trIncludeFile()
+ { return "Include Fil"; }
+ QString trVerbatimText(const char *f)
+ { return (QString)"Detta är den ordagranna texten av "+f+" include fil."; }
+ QString trModules()
+ { return "Moduler?"; }
+ QString trClassHierarchy()
+ { return "Klasshierarki?"; }
+ QString trCompoundList()
+ { return "Inhägnad lista???"; }
+ QString trFileList()
+ { return "Fillista"; }
+ QString trHeaderFiles()
+ { return "Headerfiler"; }
+ QString trCompoundMembers()
+ { return "Inhägnade medlemmar??"; }
+ QString trFileMembers()
+ { return "Filmedlemmar???"; }
+ QString trRelatedPages()
+ { return "Besläktade sidor"; }
+ QString trExamples()
+ { return "Exempel"; }
+ QString trSearch()
+ { return "Sök"; }
+ QString trClassHierarchyDescription()
+ { return "Denna lista över arv är grovsorterad, men inte helt "
+ "i alfabetisk ordning:";
+ }
+ QString trFileListDescription(bool extractAll)
+ {
+ QString result="Här följer en lista över alla ";
+ if (!extractAll) result+="dokumenterade ";
+ result+="filer, med en kort beskrivning:";
+ return result;
+ }
+ QString trCompoundListDescription()
+ { return "Här följer klasserna, structs och "
+ "unions? med en kort beskrivning:";
+ }
+ QString trCompoundMembersDescription(bool extractAll)
+ {
+ QString result="Här följer en lista över alla ";
+ if (!extractAll) result+="dokumenterade ";
+ result+="klassmedlemmar med länkar till ";
+ if (extractAll) result+="klassdokumentationen för varje medlem:";
+ else result+="klasserna som de tillhör:";
+ return result;
+ }
+ QString trFileMembersDescription(bool extractAll)
+ {
+ QString result="Här följer en lista över alla ";
+ if (!extractAll) result+="dokumenterade ";
+ result+="filmedlemmar? med länkar till ";
+ if (extractAll) result+="dokumentationsfilen för varje medlem:";
+ else result+="filerna som de tillhör:";
+ return result;
+ }
+ QString trHeaderFilesDescription()
+ { return "Här följer headerfilerna som API:n består av???:"; }
+ QString trExamplesDescription()
+ { return "Här följer en lista med alla exempel:"; }
+ QString trRelatedPagesDescription()
+ { return "Här följer en lista med alla relevanta? dokumentationssidor:"; }
+ QString trModulesDescription()
+ { return "Här följer en lista över alla moduler:"; }
+ QString trNoDescriptionAvailable()
+ { return "Beskrivning saknas"; }
+
+ QString trDocumentation()
+ { return "Dokumentation"; }
+ QString trModuleIndex()
+ { return "Module Index"; }
+ QString trHierarchicalIndex()
+ { return "Hierarkiskt Index"; }
+ QString trCompoundIndex()
+ { return "Compound Index"; }
+ QString trFileIndex()
+ { return "Fil Index"; }
+ QString trModuleDocumentation()
+ { return "Dokumentation över moduler"; }
+ QString trClassDocumentation()
+ { return "Dokumentation över klasser"; }
+ QString trFileDocumentation()
+ { return "Dokumentation över filer"; }
+ QString trExampleDocumentation()
+ { return "Dokumentation över exempel"; }
+ QString trPageDocumentation()
+ { return "Dokumentation av sidor"; }
+ QString trReferenceManual()
+ { return "Uppslagsbok"; }
+
+ QString trDefines()
+ { return "Definerar"; }
+ QString trFuncProtos()
+ { return "Funktionsprototyper"; }
+ QString trTypedefs()
+ { return "Typedefs"; }
+ QString trEnumerations()
+ { return "Uppräkning???"; }
+ QString trFunctions()
+ { return "Funktioner"; }
+ QString trVariables()
+ { return "Variabler"; }
+ QString trEnumerationValues()
+ { return "Enum värden??"; }
+ QString trReimplementedFrom()
+ { return "Återanvänd från???"; }
+ QString trReimplementedIn()
+ { return "Återanvänd i??"; }
+ QString trAuthor()
+ { return "Författare"; }
+ QString trDefineDocumentation()
+ { return "Definiera dokumentation"; }
+ QString trFunctionPrototypeDocumentation()
+ { return "Dokumentation över funktionsprototyper"; }
+ QString trTypedefDocumentation()
+ { return "Dokumentation över typedefs"; }
+ QString trEnumerationTypeDocumentation()
+ { return "Dokumentation över enum typer"; }
+ QString trFunctionDocumentation()
+ { return "Dokumentation över funktioner"; }
+ QString trVariableDocumentation()
+ { return "Dokumentation över variabler"; }
+ QString trCompounds()
+ { return "Compounds??"; }
+ QString trFiles()
+ { return "Filer"; }
+ QString trGeneratedAt(const char *date,const char *projName)
+ {
+ QString result=(QString)"Skapad "+date;
+ if (projName) result+=(QString)" för "+projName;
+ result+=(QString)" av";
+ return result;
+ }
+ QString trWrittenBy()
+ {
+ return "skriven av";
+ }
+ QString trClassDiagram(const char *clName)
+ {
+ return (QString)"Klass diagram för "+clName;
+ }
+ QString trForInternalUseOnly()
+ { return "Endast för internt bruk."; }
+ QString trReimplementedForInternalReasons()
+ { return "Omskriven av interna orsaker???; "
+ "API:n påverkas inte.";
+ }
+ QString trWarning()
+ { return "Varning"; }
+ QString trBugsAndLimitations()
+ { return "Fel och begränsningar"; }
+ QString trVersion()
+ { return "Version"; }
+ QString trDate()
+ { return "Datum"; }
+ QString trAuthors()
+ { return "Författare"; }
+ QString trReturns()
+ { return "Returnerar"; }
+ QString trSeeAlso()
+ { return "Se även"; }
+ QString trParameters()
+ { return "Parametrar"; }
+ QString trExceptions()
+ { return "Undantag"; }
+ QString trGeneratedBy()
+ { return "Skapad av"; }
+};
+
+#endif
diff --git a/src/unistd.h b/src/unistd.h
new file mode 100644
index 0000000..46a5fbc
--- /dev/null
+++ b/src/unistd.h
@@ -0,0 +1,7 @@
+/* this is a dummy file, that is needed for compiling files that are
+ * generated with flex under Windows 95/NT.
+ */
+#if defined(_MSC_VER)
+#include <io.h>
+#endif
+
diff --git a/src/util.cpp b/src/util.cpp
new file mode 100644
index 0000000..6b4578d
--- /dev/null
+++ b/src/util.cpp
@@ -0,0 +1,2174 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#include <stdlib.h>
+#include <qregexp.h>
+#include <qstring.h>
+#include <ctype.h>
+#include "util.h"
+#include "message.h"
+#include "classdef.h"
+#include "filedef.h"
+#include "doxygen.h"
+#include "scanner.h"
+#include "outputlist.h"
+#include "defargs.h"
+#include "language.h"
+#include "config.h"
+
+// an inheritance tree of depth of 100000 should be enough for everyone :-)
+const int maxInheritanceDepth = 100000;
+
+bool isId(char c)
+{
+ return c=='_' || isalnum(c);
+}
+
+
+// try to determine if this files is a source or a header file by looking
+// at the extension (5 variations are allowed in both upper and lower case)
+// If anyone knows or uses another extension please let me know :-)
+int guessSection(const char *name)
+{
+ QString n=((QString)name).lower();
+ if (n.right(2)==".c" ||
+ n.right(3)==".cc" ||
+ n.right(4)==".cxx" ||
+ n.right(4)==".cpp" ||
+ n.right(4)==".c++"
+ ) return Entry::SOURCE_SEC;
+ if (n.right(2)==".h" ||
+ n.right(3)==".hh" ||
+ n.right(4)==".hxx" ||
+ n.right(4)==".hpp" ||
+ n.right(4)==".h++"
+ ) return Entry::HEADER_SEC;
+ return 0;
+}
+
+
+//QString resolveDefines(const char *n)
+//{
+// return n;
+// if (n)
+// {
+// Define *def=defineDict[n];
+// if (def && def->nargs==0 && !def->definition.isNull())
+// {
+// return def->definition;
+// }
+// return n;
+// }
+// return 0;
+//}
+
+QString resolveTypedefs(const QString &n)
+{
+ QString *subst=typedefDict[n];
+ if (subst && !subst->isNull())
+ {
+ return *subst;
+ }
+ else
+ {
+ return n;
+ }
+}
+
+ClassDef *getClass(const char *name)
+{
+ if (!name) return 0;
+ //QString key=resolveTypedefs(resolveDefines(name));
+ //Define *def=defineDict[key];
+ //if (def && def->nargs==0 && def->definition.length()>0) // normal define
+ // key=def->definition; // use substitution
+
+ return classDict[resolveTypedefs(name)];
+}
+
+QString removeRedundantWhiteSpace(const QString &s)
+{
+ if (s.length()==0) return s;
+ QString result;
+ uint i;
+ for (i=0;i<s.length();i++)
+ {
+ char c=s.at(i);
+ if (c!=' ' ||
+ (i!=0 && i!=s.length()-1 && isId(s.at(i-1)) && isId(s.at(i+1)))
+ )
+ {
+ if ((c=='*' || c=='&') &&
+ result.length()>0 && isId(result.at(result.length()-1))
+ ) result+=' ';
+ result+=c;
+ }
+ }
+ return result;
+}
+
+void writeTemplatePrefix(OutputList &ol,ArgumentList *al)
+{
+ ol.docify("template<");
+ Argument *a=al->first();
+ while (a)
+ {
+ ol.docify(a->type);
+ ol.docify(a->name);
+ if (a->defval.length()!=0)
+ {
+ ol.docify(" = ");
+ ol.docify(a->defval);
+ }
+ a=al->next();
+ if (a) ol.docify(", ");
+ }
+ ol.docify("> ");
+ bool latexEnabled = ol.isEnabled(OutputGenerator::Latex);
+ bool manEnabled = ol.isEnabled(OutputGenerator::Man);
+ if (latexEnabled) ol.disable(OutputGenerator::Latex);
+ if (manEnabled) ol.disable(OutputGenerator::Man);
+ ol.lineBreak();
+ if (latexEnabled) ol.enable(OutputGenerator::Latex);
+ if (manEnabled) ol.enable(OutputGenerator::Man);
+}
+
+QString addTemplateNames(const QString &s,const QString &n,const QString &t)
+{
+ //printf("addTemplateNames(%s)\n",s.data());
+ QString result;
+ QString clRealName=n;
+ int p=0,i;
+ if ((i=clRealName.find('<'))!=-1)
+ {
+ clRealName=clRealName.left(i); // strip template specialization
+ }
+ while ((i=s.find(clRealName,p))!=-1)
+ {
+ result+=s.mid(p,i-p);
+ uint j=clRealName.length()+i;
+ if (s.length()==j || (s.at(j)!='<' && !isId(s.at(j))))
+ { // add template names
+ //printf("Adding %s+%s\n",clRealName.data(),t.data());
+ result+=clRealName+t;
+ }
+ else
+ { // template names already present
+ //printf("Adding %s\n",clRealName.data());
+ result+=clRealName;
+ }
+ p=i+clRealName.length();
+ }
+ result+=s.right(s.length()-p);
+ //printf("result=%s\n",result.data());
+ return result;
+}
+
+static void linkifyText(OutputList &ol,const char *clName,const char *name,const char *text)
+{
+ //printf("class %s name %s Text: %s\n",clName,name,text);
+ QRegExp regExp("[a-z_A-Z0-9:<>]+");
+ QString txtStr=text;
+ OutputList result(&ol);
+ int matchLen;
+ int index=0;
+ int newIndex;
+ int skipIndex=0;
+ // read a word from the text string
+ while ((newIndex=regExp.match(txtStr,index,&matchLen))!=-1)
+ {
+ // add non-word part to the result
+ result.docify(txtStr.mid(skipIndex,newIndex-skipIndex));
+ // get word from string
+ QString word=txtStr.mid(newIndex,matchLen);
+ ClassDef *cd=0;
+ FileDef *fd=0;
+ MemberDef *md=0;
+
+ // check if `word' is a documented class name
+ if (word.length()>0 && word!=name && word!=clName)
+ {
+ if ((cd=getClass(word)))
+ {
+ // add link to the result
+ if (cd->isVisible())
+ {
+ result.writeObjectLink(cd->getReference(),cd->classFile(),0,word);
+ }
+ else
+ {
+ result.docify(word);
+ }
+ }
+ else if (getDefs(word,clName,0,md,cd,fd) && md->hasDocumentation())
+ {
+ if (cd && cd->isVisible() && !md->isFunction()) // word is a member of cd
+ {
+ result.writeObjectLink(cd->getReference(),
+ cd->classFile(),md->anchor(),word);
+ }
+ else if (fd && fd->hasDocumentation()) // word is a global in file fd
+ {
+ result.writeObjectLink(fd->getReference(),
+ fd->diskName(),md->anchor(),word);
+ }
+ else // add word to the result
+ {
+ result.docify(word);
+ }
+ }
+ else // add word to the result
+ {
+ result.docify(word);
+ }
+ }
+ else // add word to the result
+ {
+ result.docify(word);
+ }
+ // set next start point in the string
+ skipIndex=index=newIndex+matchLen;
+ }
+ // add last part of the string to the result.
+ result.docify(txtStr.right(txtStr.length()-skipIndex));
+ //printf("linkify: %s\n",result.data());
+ ol+=result;
+}
+
+static void writeDefArgumentList(OutputList &ol,ClassDef *cd,
+ const QString &scopeName,MemberDef *md)
+{
+ ArgumentList *argList=md->argumentList();
+ if (argList==0) return; // member has no function like argument list
+ ol.docify(" ("); // start argument list
+ Argument *a=argList->first();
+ QString cName;
+ if (cd && cd->templateArguments())
+ {
+ cName=cd->getTemplateNameString();
+ }
+ while (a)
+ {
+ QRegExp re(")(");
+ int vp;
+ if ((vp=a->type.find(re))!=-1) // argument type is a function pointer
+ {
+ QString n=a->type.left(vp);
+ if (cName.length()>0) n=addTemplateNames(n,cd->name(),cName);
+ linkifyText(ol,scopeName,md->name(),n);
+ }
+ else // non-function pointer type
+ {
+ QString n=a->type;
+ if (cName.length()>0) n=addTemplateNames(n,cd->name(),cName);
+ linkifyText(ol,scopeName,md->name(),n);
+ }
+ if (a->name.length()>0) // argument has a name
+ {
+ ol.docify(" ");
+ ol.disable(OutputGenerator::Man);
+ ol.startEmphasis();
+ ol.enable(OutputGenerator::Man);
+ ol.docify(a->name);
+ ol.disable(OutputGenerator::Man);
+ ol.endEmphasis();
+ ol.enable(OutputGenerator::Man);
+ }
+ if (vp!=-1) // write the part of the argument type
+ // that comes after the name
+ {
+ linkifyText(ol,scopeName,md->name(),a->type.right(a->type.length()-vp));
+ }
+ if (a->defval.length()>0) // write the default value
+ {
+ QString n=a->defval;
+ if (cName.length()>0) n=addTemplateNames(n,cd->name(),cName);
+ ol.docify(" = ");
+ linkifyText(ol,scopeName,md->name(),n);
+ }
+ a=argList->next();
+ if (a) ol.docify(", "); // there are more arguments
+ }
+ ol.docify(")"); // end argument list
+ if (argList->constSpecifier)
+ {
+ ol.docify(" const");
+ }
+ if (argList->volatileSpecifier)
+ {
+ ol.docify(" volatile");
+ }
+}
+
+QString argListToString(ArgumentList *al)
+{
+ QString result;
+ if (al==0) return result;
+ Argument *a=al->first();
+ result+="(";
+ while (a)
+ {
+ result+= a->type+" "+a->name;
+ a = al->next();
+ if (a) result+=",";
+ }
+ result+=")";
+ if (al->constSpecifier) result+=" const";
+ if (al->volatileSpecifier) result+=" volatile";
+ return result;
+}
+
+static void writeLink(OutputList &ol,ClassDef *cd,NamespaceDef *nd,
+ FileDef *fd,MemberDef *md,const char *name)
+{
+ if (nd)
+ ol.writeObjectLink(0 /*TODO: references */,nd->namespaceFile(),md->anchor(),name);
+ else if (fd)
+ ol.writeObjectLink(fd->getReference(),fd->diskName(),md->anchor(),name);
+ else
+ ol.writeObjectLink(cd->getReference(),cd->classFile(),md->anchor(),name);
+}
+
+static void warnForUndocumentedMember(MemberDef *md)
+{
+ ClassDef *cd=md->memberClass();
+ FileDef *fd=md->getFileDef();
+ if (cd)
+ {
+ if (!md->hasDocumentation() && md->name() && md->name()[0]!='@')
+ warn("Warning: Member %s of class %s is not documented\n",
+ md->name().data(),cd->name().data());
+ }
+ else if (fd)
+ {
+ if (!md->hasDocumentation() && md->name() && md->name()[0]!='@')
+ warn("Warning: Member %s of file %s is not documented\n",
+ md->name().data(),fd->name().data());
+ }
+}
+
+static bool manIsEnabled;
+
+void startTitle(OutputList &ol)
+{
+ ol.startTitleHead();
+ manIsEnabled=ol.isEnabled(OutputGenerator::Man);
+ if (manIsEnabled) ol.disable(OutputGenerator::Man);
+}
+
+void endTitle(OutputList &ol,const char *name)
+{
+ if (manIsEnabled) ol.enable(OutputGenerator::Man);
+ ol.endTitleHead(name);
+}
+
+void writeQuickLinks(OutputList &ol,bool compact,bool ext)
+{
+ bool manEnabled = ol.isEnabled(OutputGenerator::Man);
+ bool texEnabled = ol.isEnabled(OutputGenerator::Latex);
+ QString extLink,absPath;
+ if (ext) { extLink="_doc:"; absPath="/"; }
+ if (manEnabled) ol.disable(OutputGenerator::Man);
+ if (texEnabled) ol.disable(OutputGenerator::Latex);
+ if (compact) ol.startCenter(); else ol.startItemList();
+ if (documentedGroups>0)
+ {
+ if (!compact) ol.writeListItem();
+ ol.startQuickIndexItem(extLink,absPath+"modules.html");
+ parseDoc(ol,0,0,theTranslator->trModules());
+ ol.endQuickIndexItem();
+ }
+ if (documentedNamespaces>0)
+ {
+ if (!compact) ol.writeListItem();
+ ol.startQuickIndexItem(extLink,absPath+"namespaces.html");
+ parseDoc(ol,0,0,theTranslator->trNamespaces());
+ ol.endQuickIndexItem();
+ }
+ if (hierarchyClasses>0)
+ {
+ if (!compact) ol.writeListItem();
+ ol.startQuickIndexItem(extLink,absPath+"hierarchy.html");
+ parseDoc(ol,0,0,theTranslator->trClassHierarchy());
+ ol.endQuickIndexItem();
+ }
+ if (annotatedClasses>0)
+ {
+ if (!compact) ol.writeListItem();
+ ol.startQuickIndexItem(extLink,absPath+"annotated.html");
+ parseDoc(ol,0,0,theTranslator->trCompoundList());
+ ol.endQuickIndexItem();
+ }
+ if (documentedFiles>0)
+ {
+ if (!compact) ol.writeListItem();
+ ol.startQuickIndexItem(extLink,absPath+"files.html");
+ parseDoc(ol,0,0,theTranslator->trFileList());
+ ol.endQuickIndexItem();
+ }
+ if (includeFiles.count()>0 && verbatimHeaderFlag)
+ {
+ if (!compact) ol.writeListItem();
+ ol.startQuickIndexItem(extLink,absPath+"headers.html");
+ parseDoc(ol,0,0,theTranslator->trHeaderFiles());
+ ol.endQuickIndexItem();
+ }
+ if (documentedMembers>0)
+ {
+ if (!compact) ol.writeListItem();
+ ol.startQuickIndexItem(extLink,absPath+"functions.html");
+ parseDoc(ol,0,0,theTranslator->trCompoundMembers());
+ ol.endQuickIndexItem();
+ }
+ if (documentedFunctions>0)
+ {
+ if (!compact) ol.writeListItem();
+ ol.startQuickIndexItem(extLink,absPath+"globals.html");
+ parseDoc(ol,0,0,theTranslator->trFileMembers());
+ ol.endQuickIndexItem();
+ }
+ if (pageList.count()>0)
+ {
+ if (!compact) ol.writeListItem();
+ ol.startQuickIndexItem(extLink,absPath+"pages.html");
+ parseDoc(ol,0,0,theTranslator->trRelatedPages());
+ ol.endQuickIndexItem();
+ }
+ if (exampleList.count()>0)
+ {
+ if (!compact) ol.writeListItem();
+ ol.startQuickIndexItem(extLink,absPath+"examples.html");
+ parseDoc(ol,0,0,theTranslator->trExamples());
+ ol.endQuickIndexItem();
+ }
+ if (searchEngineFlag)
+ {
+ if (!compact) ol.writeListItem();
+ ol.startQuickIndexItem("_cgi:","");
+ parseDoc(ol,0,0,theTranslator->trSearch());
+ ol.endQuickIndexItem();
+ }
+ if (compact)
+ {
+ ol.endCenter();
+ ol.writeRuler();
+ }
+ else
+ {
+ ol.endItemList();
+ }
+ if (manEnabled) ol.enable(OutputGenerator::Man);
+ if (texEnabled) ol.enable(OutputGenerator::Latex);
+}
+
+void startFile(OutputList &ol,const char *name,const char *title,bool external)
+{
+ ol.startFile(name,title,external);
+ if (!noIndexFlag) writeQuickLinks(ol,TRUE,external);
+}
+
+void endFile(OutputList &ol,bool external)
+{
+ bool latexEnabled = ol.isEnabled(OutputGenerator::Latex);
+ bool manEnabled = ol.isEnabled(OutputGenerator::Man);
+ if (latexEnabled) ol.disable(OutputGenerator::Latex);
+ if (manEnabled) ol.disable(OutputGenerator::Man);
+ ol.writeFooter(0,external); // write the footer
+ if (footerFile.length()==0)
+ {
+ parseDoc(ol,0,0,theTranslator->trGeneratedAt(
+ dateToString(TRUE),
+ projectName
+ ));
+ }
+ ol.writeFooter(1,external); // write the link to the picture
+ if (footerFile.length()==0)
+ {
+ parseDoc(ol,0,0,theTranslator->trWrittenBy());
+ }
+ ol.writeFooter(2,external); // end the footer
+ if (latexEnabled) ol.enable(OutputGenerator::Latex);
+ if (manEnabled) ol.enable(OutputGenerator::Man);
+ ol.endFile();
+}
+
+
+static void writeMemberDef(OutputList &ol, ClassDef *cd, NamespaceDef *nd,
+ FileDef *fd, MemberDef *md)
+{
+ int i,l;
+ bool hasDocs=md->hasDocumentation();
+ if ((!hasDocs && hideMemberFlag) ||
+ (hideMemberFlag &&
+ md->documentation().isEmpty() &&
+ !briefMemDescFlag &&
+ !repeatBriefFlag
+ )
+ ) return;
+ QString type=md->typeString();
+ QRegExp r("@[0-9]+");
+ if ((i=r.match(type,0,&l))==-1 || !md->enumUsed())
+ {
+ // strip `static' keyword from type
+ if (type.left(7)=="static ") type=type.right(type.length()-7);
+ // strip `friend' keyword from type
+ if (type.left(7)=="friend ") type=type.right(type.length()-7);
+
+ if (genTagFile.length()>0)
+ {
+ tagFile << md->name() << " " << md->anchor() << " \""
+ << md->argsString() << "\"\n";
+ }
+
+ QString cname;
+ if (cd) cname=cd->name();
+ else if (nd) cname=nd->name();
+ else if (fd) cname=fd->name();
+
+ // If there is no detailed description we need to write the anchor here.
+ if (!md->detailsAreVisible() && !extractAllFlag)
+ {
+ ol.writeDoxyAnchor(cname,md->anchor(),md->name());
+ ol.addToIndex(md->name(),cname);
+ ol.addToIndex(cname,md->name());
+ ol.docify("\n");
+ }
+
+ ol.startMemberItem();
+
+ // write type
+ if (i!=-1)
+ {
+ QString newType = type.left(i) + " { ... } " +
+ type.right(type.length()-i-l);
+ type = newType;
+ ol.docify(type);
+ }
+ else
+ {
+ ol.docify(type);
+ }
+ QString name=md->name().copy();
+ if (type.length()>0) ol.writeString(" ");
+
+ // write name
+ if ( extractAllFlag ||
+ (md->briefDescription().isEmpty() || !briefMemDescFlag) &&
+ (!md->documentation().isEmpty() ||
+ (!md->briefDescription().isEmpty() &&
+ !briefMemDescFlag &&
+ repeatBriefFlag
+ )
+ )
+ )
+ {
+ //printf("writeLink %s->%d\n",name.data(),md->hasDocumentation());
+ writeLink(ol,cd,nd,fd,md,name);
+ }
+ else // there is a brief member description and brief member
+ // descriptions are enabled or there is no detailed description.
+ {
+ ol.writeBoldString(name);
+ }
+
+ if (md->argsString())
+ {
+ ol.writeString(" ");
+ ol.docify(md->argsString());
+ }
+
+ if (md->excpString())
+ {
+ ol.writeString(" ");
+ ol.docify(md->excpString());
+ }
+
+ ol.endMemberItem();
+
+ // write brief description
+ if (!md->briefDescription().isEmpty() && briefMemDescFlag)
+ {
+ ol.startMemberDescription();
+ parseDoc(ol,cname,md->name(),md->briefDescription());
+ if (!md->documentation().isEmpty())
+ {
+ ol.disableAllBut(OutputGenerator::Html);
+ ol.endEmphasis();
+ ol.docify(" ");
+ ol.startTextLink(0,md->anchor());
+ //ol.writeObjectLink(0,0,md->anchor()," More...");
+ parseDoc(ol,0,0,theTranslator->trMore());
+ ol.endTextLink();
+ ol.startEmphasis();
+ ol.enableAll();
+ }
+ ol.endMemberDescription();
+ ol.newParagraph();
+ }
+ }
+ warnForUndocumentedMember(md);
+}
+
+
+// write a list in HTML of all members of a certain category
+// cd!=0 => ml is a list of class members
+// fd!=0 => ml is a list of file `members'
+void writeMemberDecs(OutputList &ol,ClassDef *cd,NamespaceDef *nd, FileDef *fd,
+ const char *title, const char *subtitle,MemberList *ml)
+{
+ ml->countDecMembers();
+ if (ml->totalCount()==0) return;
+ if (title)
+ {
+ ol.startMemberHeader();
+ parseDoc(ol,0,0,title);
+ ol.endMemberHeader();
+ }
+ if (subtitle) ol.writeString(subtitle);
+
+
+ if (!fd && !nd) ol.startMemberList();
+ MemberDef *md;
+
+ if (fd && ml->defineCount()>0)
+ {
+ ol.startMemberHeader();
+ parseDoc(ol,0,0,theTranslator->trDefines());
+ ol.endMemberHeader();
+ ol.startMemberList();
+ MemberListIterator mli(*ml);
+ for ( ; (md=mli.current()); ++mli )
+ {
+ if (md->isDefine() &&
+ (md->argsString() || md->hasDocumentation() || extractAllFlag)
+ )
+ writeMemberDef(ol,cd,nd,fd,md);
+ }
+ ol.endMemberList();
+ }
+
+ if ((fd || nd) && ml->protoCount()>0)
+ {
+ ol.startMemberHeader();
+ parseDoc(ol,0,0,theTranslator->trFuncProtos());
+ ol.startMemberList();
+ MemberListIterator mli(*ml);
+ for ( ; (md=mli.current()); ++mli )
+ {
+ if (md->isPrototype()) writeMemberDef(ol,cd,nd,fd,md);
+ }
+ ol.endMemberList();
+ }
+
+ if (ml->typedefCount()>0)
+ {
+ if (fd || nd)
+ {
+ ol.startMemberHeader();
+ parseDoc(ol,0,0,theTranslator->trTypedefs());
+ ol.endMemberHeader();
+ //ol.writeMemberHeader("Typedefs");
+ ol.startMemberList();
+ }
+ MemberListIterator mli(*ml);
+ for ( ; (md=mli.current()) ; ++mli )
+ {
+ if (md->isTypedef()) writeMemberDef(ol,cd,nd,fd,md);
+ }
+ if (fd || nd) ol.endMemberList();
+ }
+
+ // write enums
+ if (ml->enumCount()>0)
+ {
+ if (fd || nd)
+ {
+ ol.startMemberHeader();
+ parseDoc(ol,0,0,theTranslator->trEnumerations());
+ ol.endMemberHeader();
+ ol.startMemberList();
+ }
+ MemberListIterator mli(*ml);
+ for ( ; (md=mli.current()) ; ++mli )
+ {
+ bool hasDocs=md->hasDocumentation();
+ QString type=md->typeString();
+ type=type.stripWhiteSpace();
+ if (md->isEnumerate() && (hasDocs || !hideMemberFlag))
+ {
+ // see if there are any documented enum values
+ // we need this info to decide if we need to generate a link.
+ QList<MemberDef> *fmdl=md->enumFieldList();
+ int documentedEnumValues=0;
+ if (fmdl)
+ {
+ MemberDef *fmd=fmdl->first();
+ while (fmd)
+ {
+ if (fmd->hasDocumentation()) documentedEnumValues++;
+ fmd=fmdl->next();
+ }
+ }
+ if (documentedEnumValues>0) md->setDocumentedEnumValues(TRUE);
+
+ if (!hideMemberFlag || // do not hide undocumented members or
+ !md->documentation().isEmpty() || // member has detailed descr. or
+ documentedEnumValues>0 || // member has documented enum vales.
+ briefMemDescFlag || // brief descr. is shown or
+ repeatBriefFlag // brief descr. is repeated.
+ )
+ {
+ OutputList typeDecl(&ol);
+ QString name=md->name().copy();
+ int i=name.findRev("::");
+ if (i!=-1) name=name.right(name.length()-i-2); // strip scope
+ if (name[0]!='@') // not an anonymous enum
+ {
+ if (extractAllFlag ||
+ (md->briefDescription().isEmpty() || !briefMemDescFlag) &&
+ (!md->documentation().isEmpty() || documentedEnumValues>0 ||
+ (!md->briefDescription().isEmpty() &&
+ !briefMemDescFlag &&
+ repeatBriefFlag
+ )
+ )
+ )
+ {
+ if (genTagFile.length()>0)
+ tagFile << md->name() << " " << md->anchor()
+ << " \"" << md->argsString() << "\"";
+ writeLink(typeDecl,cd,nd,fd,md,name);
+ }
+ else
+ {
+ typeDecl.writeBoldString(name);
+ }
+ typeDecl.writeChar(' ');
+ }
+
+ typeDecl.docify("{ ");
+ if (fmdl)
+ {
+ MemberDef *fmd=fmdl->first();
+ while (fmd)
+ {
+ if (fmd->hasDocumentation())
+ {
+ if (genTagFile.length()>0)
+ tagFile << fmd->name() << " " << fmd->anchor()
+ << " \"" << fmd->argsString() << "\"";
+ writeLink(typeDecl,cd,nd,fd,fmd,fmd->name());
+ }
+ else
+ typeDecl.writeBoldString(fmd->name());
+ fmd=fmdl->next();
+ if (fmd) typeDecl.writeString(", ");
+ typeDecl.disable(OutputGenerator::Man);
+ typeDecl.writeString("\n"); // to prevent too long lines in LaTeX
+ typeDecl.enable(OutputGenerator::Man);
+ }
+ }
+ typeDecl.docify(" }");
+ md->setEnumDecl(typeDecl);
+ int enumVars=0;
+ MemberListIterator vmli(*ml);
+ MemberDef *vmd;
+ if (name[0]=='@') // anonymous enum => append variables
+ {
+ for ( ; (vmd=vmli.current()) ; ++vmli)
+ {
+ QString vtype=vmd->typeString();
+ if ((vtype.find(name))!=-1) enumVars++;
+ }
+ }
+ if (enumVars==0) // no variable of this enum type
+ {
+ ol.startMemberItem();
+ ol.writeString("enum ");
+ ol+=typeDecl;
+ ol.endMemberItem();
+ //QString brief=md->briefDescription();
+ //brief=brief.stripWhiteSpace();
+ if (!md->briefDescription().isEmpty() && briefMemDescFlag)
+ {
+ ol.startMemberDescription();
+ parseDoc(ol,cd?cd->name().data():0,
+ md->name().data(),md->briefDescription());
+ if (!md->documentation().isEmpty() || documentedEnumValues>0)
+ {
+ ol.disableAllBut(OutputGenerator::Html);
+ ol.endEmphasis();
+ ol.docify(" ");
+ ol.startTextLink(0,md->anchor());
+ //ol.writeObjectLink(0,0,md->anchor()," More...");
+ parseDoc(ol,0,0,theTranslator->trMore());
+ ol.endTextLink();
+ ol.startEmphasis();
+ ol.enableAll();
+ }
+ ol.endMemberDescription();
+ ol.disable(OutputGenerator::Man);
+ ol.newParagraph();
+ ol.enable(OutputGenerator::Man);
+ }
+ }
+ warnForUndocumentedMember(md);
+ }
+ } // md->isEnumerate()
+ } // enum loop
+ if (fd || nd) ol.endMemberList();
+ } // write enums
+
+ // write functions
+ if (ml->funcCount()>0)
+ {
+ if (fd || nd)
+ {
+ ol.startMemberHeader();
+ parseDoc(ol,0,0,theTranslator->trFunctions());
+ ol.endMemberHeader();
+ ol.startMemberList();
+ }
+ MemberListIterator mli(*ml);
+ for ( ; (md=mli.current()) ; ++mli )
+ {
+ if ( md->isFunction() || md->isSignal() ||
+ md->isSlot())
+ writeMemberDef(ol,cd,nd,fd,md);
+ }
+ if (fd || nd) ol.endMemberList();
+ }
+
+ if (ml->friendCount()>0)
+ {
+ MemberListIterator mli(*ml);
+ for ( ; (md=mli.current()) ; ++mli )
+ {
+ if ( md->isFriend())
+ {
+ QString type=md->typeString();
+ //printf("Friend: type=%s name=%s\n",type.data(),md->name().data());
+ if (md->hasDocumentation() && type!="friend class")
+ {
+ writeMemberDef(ol,cd,nd,fd,md);
+ }
+ else // friend is undocumented as a member but it is a class,
+ // so generate a link to the class if that is documented.
+ {
+ ClassDef *cd=getClass(md->name());
+ if (md->hasDocumentation()) // friend is documented
+ {
+ ol.startMemberItem();
+ ol.docify("class ");
+ ol.writeObjectLink(0,0,md->anchor(),md->name());
+ ol.endMemberItem();
+ }
+ else if (cd && cd->isVisibleExt()) // class is documented
+ {
+ ol.startMemberItem();
+ ol.docify("class ");
+ ol.writeObjectLink(cd->getReference(),cd->classFile(),0,cd->name());
+ ol.endMemberItem();
+ }
+ else if (!hideMemberFlag) // no documentation
+ {
+ ol.startMemberItem();
+ ol.docify("class ");
+ ol.writeBoldString(md->name());
+ ol.endMemberItem();
+ }
+ }
+ }
+ }
+ }
+
+ // write variables
+ if (ml->varCount()>0)
+ {
+ if (fd || nd)
+ {
+ ol.startMemberHeader();
+ parseDoc(ol,0,0,theTranslator->trVariables());
+ ol.endMemberHeader();
+ ol.startMemberList();
+ }
+ MemberListIterator mli(*ml);
+ for ( ; (md=mli.current()) ; ++mli )
+ {
+ if (md->isVariable()) writeMemberDef(ol,cd,nd,fd,md);
+ }
+ if (fd || nd) ol.endMemberList();
+ }
+
+ if (!fd && !nd) { ol.endMemberList(); ol.writeChar('\n'); }
+}
+
+// compute the HTML anchors for a list of members
+void setAnchors(char id,MemberList *ml)
+{
+ int count=0;
+ MemberDef *md=ml->first();
+ while (md)
+ {
+ QString anchor;
+ anchor.sprintf("%c%d",id,count++);
+ //printf("Member %s anchor %s\n",md->name(),anchor.data());
+ md->setAnchor(anchor);
+ md=ml->next();
+ }
+}
+
+void writeMemberDocs(OutputList &ol,MemberList *ml,const char *scopeName,
+ MemberDef::MemberType m)
+{
+ MemberListIterator mli(*ml);
+ MemberDef *md;
+ for ( ; (md=mli.current()) ; ++mli)
+ {
+ bool hasDocs = md->detailsAreVisible();
+ // !md->documentation().isEmpty() || // member has a detailed description
+ // (md->memberType()==MemberDef::Enumeration && // or member is an enum and
+ // md->hasDocumentedEnumValues() // one of its values is documented
+ // ) || // or
+ // (!md->briefDescription().isEmpty() && // member has brief description and
+ // !briefMemDescFlag && // brief description not shown earlier and
+ // repeatBriefFlag // brief description should be repeated.
+ // );
+ if (md->memberType()==m && // filter member type
+ (extractAllFlag || hasDocs)
+ )
+ {
+ if (extractAllFlag && !hasDocs)
+ {
+ ol.disable(OutputGenerator::Latex); // Latex cannot insert a pagebreak
+ // if there are a lot of empty sections,
+ // so we disable LaTeX for all empty
+ // sections even if extractAllFlag is enabled
+ }
+ QString cname;
+ NamespaceDef *nd=md->getNamespace();
+ ClassDef *cd=md->memberClass();
+ FileDef *fd=md->getFileDef();
+ if (cd) cname=cd->name();
+ else if (nd) cname=nd->name();
+ else if (fd) cname=fd->name();
+ // get member name
+ QString doxyName=md->name().copy();
+ // prepend scope if there is any (TODO: prepend namespace scope as well)
+ if (scopeName) doxyName.prepend((QString)scopeName+"::");
+
+ QString def = md->definition();
+ if (md->isEnumerate()) def.prepend("enum ");
+ MemberDef *smd;
+ if (md->isEnumValue() && def[0]=='@') def = def.right(def.length()-2);
+ int i=0,l,dummy;
+ QRegExp r("@[0-9]+");
+ if (md->isEnumerate() && r.match(def,0,&l)!=-1) continue;
+ if (md->isEnumValue() && (smd = md->getEnumScope())
+ && r.match(smd->name(),0,&dummy)==-1) continue;
+ if ((md->isVariable() || md->isTypedef()) && (i=r.match(def,0,&l))!=-1)
+ {
+ // find enum type an insert it in the definition
+ MemberListIterator vmli(*ml);
+ MemberDef *vmd;
+ bool found=FALSE;
+ for ( ; (vmd=vmli.current()) && !found ; ++vmli)
+ {
+ if (vmd->isEnumerate() && def.mid(i,l)==vmd->name())
+ {
+ ol.startMemberDoc(cname,md->name(),md->anchor());
+ ol.writeDoxyAnchor(cname,md->anchor(),doxyName);
+ linkifyText(ol,scopeName,md->name(),def.left(i));
+ ol+=*vmd->enumDecl();
+ linkifyText(ol,scopeName,md->name(),def.right(def.length()-i-l));
+ found=TRUE;
+ }
+ }
+ if (!found) // anonymous compound
+ {
+ ol.startMemberDoc(cname,md->name(),md->anchor());
+ ol.writeDoxyAnchor(cname,md->anchor(),doxyName);
+ linkifyText(ol,scopeName,md->name(),def.left(i));
+ ol.docify(" { ... } ");
+ linkifyText(ol,scopeName,md->name(),def.right(def.length()-i-l));
+ }
+ }
+ else
+ {
+ ol.startMemberDoc(cname,md->name(),md->anchor());
+ ol.writeDoxyAnchor(cname,md->anchor(),doxyName);
+ ArgumentList *al=0;
+ if (cd && (!md->isRelated() || !md->templateArguments()) &&
+ (al=cd->templateArguments())) // class template prefix
+ {
+ writeTemplatePrefix(ol,al);
+ }
+ if (al && md->templateArguments()) ol.docify(" ");
+ al=md->templateArguments();
+ if (al) // function template prefix
+ {
+ writeTemplatePrefix(ol,al);
+ }
+ if (cd && cd->templateArguments())
+ {
+ // add template name lists to all occurrences of the class name.
+ def=addTemplateNames(def,cd->name(),cd->getTemplateNameString());
+ }
+ linkifyText(ol,scopeName,md->name(),def);
+ writeDefArgumentList(ol,cd,scopeName,md);
+ if (md->excpString())
+ {
+ ol.docify(" ");
+ linkifyText(ol,scopeName,md->name(),md->excpString());
+ }
+ }
+
+ Specifier virt=md->virtualness();
+ MemberDef *rmd=md->reimplements();
+ while (rmd && virt==Normal)
+ {
+ virt = rmd->virtualness()==Normal ? Normal : Virtual;
+ rmd = rmd->reimplements();
+ }
+
+ if (md->isStatic() || md->protection()!=Public ||
+ virt!=Normal || md->isSignal() || md->isFriend() ||
+ md->isRelated() || md->isSlot()
+ )
+ {
+ // write the member specifier list
+ ol.writeLatexSpacing();
+ ol.startTypewriter();
+ ol.docify(" [");
+ QStrList sl;
+ if (md->isFriend()) sl.append("friend");
+ else if (md->isRelated()) sl.append("related");
+ else
+ {
+ if (md->isStatic()) sl.append("static");
+ if (md->protection()==Protected) sl.append("protected");
+ else if (md->protection()==Private) sl.append("private");
+ if (virt==Virtual) sl.append("virtual");
+ else if (virt==Pure) sl.append("pure virtual");
+ if (md->isSignal()) sl.append("signal");
+ if (md->isSlot()) sl.append("slot");
+ }
+ const char *s=sl.first();
+ while (s)
+ {
+ ol.docify(s);
+ s=sl.next();
+ if (s) ol.docify(", ");
+ }
+ ol.docify("]");
+ ol.endTypewriter();
+ }
+ ol.endMemberDoc();
+ ol.startIndent();
+ ol.newParagraph();
+
+ if (!md->briefDescription().isEmpty() &&
+ (repeatBriefFlag ||
+ (!briefMemDescFlag && md->documentation().isEmpty())
+ )
+ )
+ {
+ parseDoc(ol,scopeName,md->name(),md->briefDescription());
+ ol.newParagraph();
+ }
+ if (!md->documentation().isEmpty())
+ {
+ parseDoc(ol,scopeName,md->name(),md->documentation()+"\n");
+ }
+
+ if (md->isEnumerate())
+ {
+ bool first=TRUE;
+ MemberList *fmdl=md->enumFieldList();
+ if (fmdl)
+ {
+ MemberDef *fmd=fmdl->first();
+ while (fmd)
+ {
+ if (fmd->hasDocumentation())
+ {
+ if (first)
+ {
+ ol.newParagraph();
+ ol.startBold();
+ parseDoc(ol,0,0,theTranslator->trEnumerationValues());
+ //ol.writeBoldString("Enumeration values:");
+ ol.docify(":");
+ ol.endBold();
+ ol.startMemberList();
+ }
+ ol.writeDoxyAnchor(cname,fmd->anchor(),fmd->name());
+ ol.addToIndex(fmd->name(),cname);
+ ol.addToIndex(cname,fmd->name());
+ ol.writeListItem();
+ first=FALSE;
+ ol.startBold();
+ ol.docify(fmd->name());
+ ol.endBold();
+ ol.newParagraph();
+
+ if (!fmd->briefDescription().isEmpty())
+ {
+ parseDoc(ol,scopeName,fmd->name(),fmd->briefDescription());
+ ol.newParagraph();
+ }
+ if (!fmd->documentation().isEmpty())
+ {
+ parseDoc(ol,scopeName,fmd->name(),fmd->documentation()+"\n");
+ }
+ ol.disable(OutputGenerator::Man);
+ ol.newParagraph();
+ ol.enable(OutputGenerator::Man);
+ }
+ fmd=fmdl->next();
+ }
+ }
+ if (!first) { ol.endMemberList(); ol.writeChar('\n'); }
+ }
+
+ MemberDef *bmd=md->reimplements();
+ if (bmd)
+ {
+ if (virt!=Normal) // search for virtual member of the deepest base class
+ {
+ MemberDef *lastBmd=bmd;
+ while (lastBmd)
+ {
+ if (lastBmd->virtualness()!=Normal) bmd=lastBmd;
+ lastBmd=lastBmd->reimplements();
+ }
+ }
+ // write class that contains a member that is reimplemented by this one
+ ClassDef *bcd = bmd->memberClass();
+ ol.newParagraph();
+ parseDoc(ol,0,0,theTranslator->trReimplementedFrom());
+ //ol.writeString("Reimplemented from ");
+ ol.docify(" ");
+ if (bmd->hasDocumentation())
+ {
+ ol.writeObjectLink(bcd->getReference(),bcd->classFile(),
+ bmd->anchor(),bcd->name());
+ if (
+ !bcd->isReference() &&
+ //(bcd->hasDocumentation() || !hideClassFlag) &&
+ //(bcd->protection()!=Private || extractPrivateFlag)
+ bcd->isVisible()
+ /*&& bmd->detailsAreVisible()*/
+ ) ol.writePageRef(bcd->name(),bmd->anchor());
+ }
+ else
+ {
+ ol.writeObjectLink(bcd->getReference(),bcd->classFile(),
+ 0,bcd->name());
+ if (
+ !bcd->isReference() &&
+ //(bcd->hasDocumentation() || !hideClassFlag) &&
+ //(bcd->protection()!=Private || extractPrivateFlag)
+ bcd->isVisible()
+ ) ol.writePageRef(bcd->name(),0);
+ }
+ ol.writeString(".");
+ }
+ MemberList *bml=md->reimplementedBy();
+ int count;
+ if (bml && (count=bml->count())>0)
+ {
+ // write the list of classes that overwrite this member
+ ol.newParagraph();
+ parseDoc(ol,0,0,theTranslator->trReimplementedIn());
+ //ol.writeString("Reimplemented in ");
+ ol.docify(" ");
+ bmd=bml->first();
+ while (bmd)
+ {
+ ClassDef *bcd = bmd->memberClass();
+ if (bmd->hasDocumentation())
+ {
+ ol.writeObjectLink(bcd->getReference(),bcd->classFile(),
+ bmd->anchor(),bcd->name());
+ if (
+ !bcd->isReference() &&
+ //(bcd->hasDocumentation() || !hideClassFlag) &&
+ //(bcd->protection()!=Private || extractPrivateFlag)
+ bcd->isVisible()
+ /*&& bmd->detailsAreVisible()*/
+ ) ol.writePageRef(bcd->name(),bmd->anchor());
+ }
+ else
+ {
+ ol.writeObjectLink(bcd->getReference(),bcd->classFile(),
+ 0,bcd->name());
+ if (
+ !bcd->isReference() &&
+ //(bcd->hasDocumentation() || !hideClassFlag) &&
+ //(bcd->protection()!=Private || extractPrivateFlag)
+ bcd->isVisible()
+ ) ol.writePageRef(bcd->name(),0);
+ }
+ bmd=bml->next();
+ if (bmd)
+ {
+ if (bml->at()==count-1)
+ //ol.writeString(" and ");
+ parseDoc(ol,0,0," "+theTranslator->trAnd()+" ");
+ else
+ ol.writeString(", ");
+ }
+ }
+ ol.writeString(".");
+ }
+ // write the list of examples that use this member
+ if (md->hasExamples())
+ {
+ ol.startDescList();
+ ol.startBold();
+ parseDoc(ol,0,0,theTranslator->trExamples()+": ");
+ //ol.writeBoldString("Examples: ");
+ ol.endBold();
+ ol.endDescTitle();
+ ol.writeDescItem();
+ md->writeExample(ol);
+ //ol.endDescItem();
+ ol.endDescList();
+ }
+ ol.endIndent();
+ // enable LaTeX again
+ if (extractAllFlag && !hasDocs) ol.enable(OutputGenerator::Latex);
+
+ }
+ }
+}
+
+//----------------------------------------------------------------------------
+// read a file with `name' to a string.
+
+QString fileToString(const char *name)
+{
+ if (name==0 || name[0]==0) return 0;
+ QFileInfo fi(name);
+ if (!fi.exists() || !fi.isFile())
+ {
+ err("Error: file `%s' not found\n",name);
+ exit(1);
+ }
+ QFile f(name);
+ if (!f.open(IO_ReadOnly))
+ {
+ err("Error: cannot open file `%s'\n",name);
+ exit(1);
+ }
+ int fsize=fi.size();
+ QString contents(fsize+1);
+ f.readBlock(contents.data(),fsize);
+ contents[fsize]='\0';
+ f.close();
+ return contents;
+}
+
+QString dateToString(bool includeTime)
+{
+ if (includeTime)
+ {
+ return QDateTime::currentDateTime().toString();
+ }
+ else
+ {
+ const QDate &d=QDate::currentDate();
+ QString result;
+ result.sprintf("%d %s %d",
+ d.day(),
+ d.monthName(d.month()),
+ d.year());
+ return result;
+ }
+ //QDate date=dt.date();
+ //QTime time=dt.time();
+ //QString dtString;
+ //dtString.sprintf("%02d:%02d, %04d/%02d/%02d",
+ // time.hour(),time.minute(),date.year(),date.month(),date.day());
+ //return dtString;
+}
+
+
+//----------------------------------------------------------------------
+// recursive function that returns the number of branches in the
+// inheritance tree that the base class `bcd' is below the class `cd'
+
+static int minClassDistance(ClassDef *cd,ClassDef *bcd,int level=0)
+{
+ if (cd==bcd) return level;
+ BaseClassListIterator bcli(*cd->baseClasses());
+ int m=maxInheritanceDepth;
+ for ( ; bcli.current() ; ++bcli)
+ {
+ m=QMIN(minClassDistance(bcli.current()->classDef,bcd,level+1),m);
+ }
+ return m;
+}
+
+//static void printArgList(ArgumentList *al)
+//{
+// if (al==0) return;
+// ArgumentListIterator ali(*al);
+// Argument *a;
+// printf("(");
+// for (;(a=ali.current());++ali)
+// {
+// printf("t=`%s' n=`%s' v=`%s' ",a->type.data(),a->name.length()>0?a->name.data():"",a->defval.length()>0?a->defval.data():"");
+// }
+// printf(")");
+//}
+
+// strip any template specifiers that follow className in string s
+static QString trimTemplateSpecifiers(const QString &className,const QString &s)
+{
+ // first we resolve any defines
+ //int i=0,p,l;
+ //QString result;
+ //QRegExp r("[A-Z_a-z][A-Z_a-z0-9]*");
+ //while ((p=r.match(s,i,&l))!=-1)
+ //{
+ // if (p>i) result+=s.mid(i,p-i);
+ // result+=resolveDefines(s.mid(p,l));
+ // i=p+l;
+ //}
+ //if (i<(int)s.length()) result+=s.mid(i,s.length()-i);
+
+ // We strip the template arguments following className (if any)
+ QString result=s.copy();
+ int l=className.length();
+ if (l>0) // there is a class name
+ {
+ int i,p=0;
+ while ((i=result.find(className,p))!=-1) // class name is in the argument type
+ {
+ uint s=i+l;
+ if (s<result.length() && result.at(s)=='<') // class has template args
+ {
+ int b=1;
+ uint e=s+1;
+ while (b>0 && e<result.length()) // find matching >
+ {
+ if (result.at(e)=='<') b++;
+ else if (result.at(e)=='>') b--;
+ e++;
+ }
+ // remove template argument
+ result=result.left(s)+result.right(result.length()-e);
+ if (result.length()>s && (result.at(s)=='*' || result.at(s)=='&'))
+ {
+ // insert a space to keep the argument in the canonical form
+ result=result.left(s)+" "+result.right(result.length()-s);
+ }
+ }
+ p=i+l;
+ }
+ }
+ return result;
+}
+
+// removes the (one and only) occurrence of name:: from s.
+static QString trimScope(const QString &name,const QString &s)
+{
+ int spos;
+ spos=s.find(name+"::");
+ if (spos!=-1)
+ {
+ return s.left(spos)+s.right(s.length()-spos-name.length()-2);
+ }
+ return s;
+}
+
+static QString trimBaseClassScope(BaseClassList *bcl,const QString &s)
+{
+ BaseClassListIterator bcli(*bcl);
+ BaseClassDef *bcd;
+ for (;(bcd=bcli.current());++bcli)
+ {
+ ClassDef *cd=bcd->classDef;
+ int spos=s.find(cd->name());
+ if (spos!=-1)
+ {
+ return s.left(spos)+s.right(
+ s.length()-spos-cd->name().length()-2
+ );
+ }
+ if (cd->baseClasses()->count()>0)
+ trimBaseClassScope(cd->baseClasses(),s);
+ }
+ return s;
+}
+
+//----------------------------------------------------------------------
+// Matches the arguments list srcAl with the argument list dstAl
+// Returns TRUE if the argument lists are equal. Two argument list are
+// considered equal if the number of arguments is equal and the types of all
+// arguments are equal. Furthermore the const and volatile specifiers
+// stored in the list should be equal.
+
+bool matchArguments(ArgumentList *srcAl,ArgumentList *dstAl,
+ const char *cl,const char *ns)
+{
+ QString className=cl;
+ QString namespaceName=ns;
+ //printf("matchArguments(%s,%s) className=%s namespaceName=%s\n",
+ // srcAl ? argListToString(srcAl).data() : "",
+ // dstAl ? argListToString(dstAl).data() : "",
+ // cl,ns);
+ if (srcAl==0 || dstAl==0)
+ {
+ return srcAl==dstAl; // at least one of the members is not a function
+ }
+ if ( srcAl->count()==0 && dstAl->count()==1 &&
+ dstAl->getFirst()->type=="void" )
+ { // special case for finding match between func() and func(void)
+ Argument *a=new Argument;
+ a->type = "void";
+ srcAl->append(a);
+ }
+ if ( dstAl->count()==0 && srcAl->count()==1 &&
+ srcAl->getFirst()->type=="void" )
+ { // special case for finding match between func(void) and func()
+ Argument *a=new Argument;
+ a->type = "void";
+ dstAl->append(a);
+ return TRUE;
+ }
+ if (srcAl->count() != dstAl->count())
+ {
+ return FALSE; // different number of arguments -> no match
+ }
+ if (srcAl->constSpecifier != dstAl->constSpecifier)
+ {
+ return FALSE; // one member is const, the other not -> no match
+ }
+ if (srcAl->volatileSpecifier != dstAl->volatileSpecifier)
+ {
+ return FALSE; // one member is volatile, the other not -> no match
+ }
+
+ // so far the argument list could match, so we need to compare the types of
+ // all arguments.
+ ArgumentListIterator srcAli(*srcAl),dstAli(*dstAl);
+ Argument *srcA,*dstA;
+ for (;(srcA=srcAli.current(),dstA=dstAli.current());++srcAli,++dstAli)
+ {
+ QString srcAType=trimTemplateSpecifiers(className,srcA->type);
+ QString dstAType=trimTemplateSpecifiers(className,dstA->type);
+
+ if (srcAType!=dstAType) // check if the argument only differs on name
+ {
+ //printf("`%s' <=> `%s'\n",srcAType.data(),dstAType.data());
+
+ QString srcScope;
+ QString dstScope;
+
+ // strip redundant scope specifiers
+ if (!className.isEmpty())
+ {
+ srcAType=trimScope(className,srcAType);
+ dstAType=trimScope(className,dstAType);
+ ClassDef *cd=getClass(className);
+ if (cd->baseClasses()->count()>0)
+ {
+ srcAType=trimBaseClassScope(cd->baseClasses(),srcAType);
+ dstAType=trimBaseClassScope(cd->baseClasses(),dstAType);
+ }
+ }
+ if (!namespaceName.isEmpty())
+ {
+ srcAType=trimScope(namespaceName,srcAType);
+ dstAType=trimScope(namespaceName,dstAType);
+ }
+
+ //printf("`%s' <=> `%s'\n",srcAType.data(),dstAType.data());
+ uint srcPos=0,dstPos=0;
+ bool equal=TRUE;
+ while (srcPos<srcAType.length() && dstPos<dstAType.length() && equal)
+ {
+ equal=srcAType.at(srcPos)==dstAType.at(dstPos);
+ if (equal) srcPos++,dstPos++;
+ }
+ if (srcPos<srcAType.length() && dstPos<dstAType.length())
+ {
+ // if nothing matches or the match ends in the middle or at the
+ // end of a string then there is no match
+ //if (srcPos==0 || isalnum(srcAType.at(srcPos-1)) ||
+ // dstPos==0 || isalnum(dstAType.at(dstPos-1))) { printf("No match1\n"); return FALSE; }
+ int srcStart=srcPos;
+ int dstStart=dstPos;
+ if (srcPos==0 || dstPos==0) return FALSE;
+ if (isId(srcAType.at(srcPos)) && isId(dstAType.at(dstPos)))
+ {
+ // check if a name if already found -> if no then there is no match
+ if (srcA->name.length()>0 || dstA->name.length()>0) return FALSE;
+ while (srcPos<srcAType.length() && isId(srcAType.at(srcPos))) srcPos++;
+ while (dstPos<dstAType.length() && isId(dstAType.at(dstPos))) dstPos++;
+ if (srcPos<srcAType.length() || dstPos<dstAType.length()) return FALSE;
+ // find the start of the name
+ while (srcStart>=0 && isId(srcAType.at(srcStart))) srcStart--;
+ while (dstStart>=0 && isId(dstAType.at(dstStart))) dstStart--;
+ if (srcStart>0) // move the name from the type to the name field
+ {
+ srcA->name=srcAType.right(srcAType.length()-srcStart-1);
+ srcA->type=srcAType.left(srcStart+1).stripWhiteSpace();
+ }
+ if (dstStart>0) // move the name from the type to the name field
+ {
+ dstA->name=dstAType.right(dstAType.length()-dstStart-1);
+ dstA->type=dstAType.left(dstStart+1).stripWhiteSpace();
+ }
+ }
+ else
+ {
+ // otherwise we assume that a name starts at the current position.
+ while (srcPos<srcAType.length() && isId(srcAType.at(srcPos))) srcPos++;
+ while (dstPos<dstAType.length() && isId(dstAType.at(dstPos))) dstPos++;
+ // if nothing more follows for both types then we assume we have
+ // found a match. Note that now `signed int' and `signed' match, but
+ // seeing that int is not a name can only be done by looking at the
+ // semantics.
+
+ if (srcPos!=srcAType.length() || dstPos!=dstAType.length()) { return FALSE; }
+ dstA->name=dstAType.right(dstAType.length()-dstStart);
+ dstA->type=dstAType.left(dstStart).stripWhiteSpace();
+ srcA->name=srcAType.right(dstAType.length()-srcStart);
+ srcA->type=srcAType.left(srcStart).stripWhiteSpace();
+ }
+ }
+ else if (dstPos<dstAType.length())
+ {
+ if (!isspace(dstAType.at(dstPos))) // maybe the names differ
+ {
+ int startPos=dstPos;
+ while (dstPos<dstAType.length() && isId(dstAType.at(dstPos))) dstPos++;
+ if (dstPos!=dstAType.length()) return FALSE; // more than a difference in name -> no match
+ while (startPos>=0 && isId(dstAType.at(startPos))) startPos--;
+ if (startPos>0)
+ {
+ dstA->name=dstAType.right(dstAType.length()-startPos-1);
+ dstA->type=dstAType.left(startPos+1).stripWhiteSpace();
+ }
+ }
+ else // maybe dst has a name while src has not
+ {
+ dstPos++;
+ int startPos=dstPos;
+ while (dstPos<dstAType.length() && isId(dstAType.at(dstPos))) dstPos++;
+ if (dstPos!=dstAType.length()) return FALSE; // nope not a name -> no match
+ else // its a name (most probably) so move it
+ {
+ dstA->name=dstAType.right(dstAType.length()-startPos);
+ dstA->type=dstAType.left(startPos).stripWhiteSpace();
+ }
+ }
+ }
+ else if (srcPos<srcAType.length())
+ {
+ if (!isspace(srcAType.at(srcPos))) // maybe the names differ
+ {
+ int startPos=srcPos;
+ while (srcPos<srcAType.length() && isId(srcAType.at(srcPos))) srcPos++;
+ if (srcPos!=srcAType.length()) return FALSE; // more than a difference in name -> no match
+ while (startPos>=0 && isId(srcAType.at(startPos))) startPos--;
+ if (startPos>0)
+ {
+ srcA->name=srcAType.right(srcAType.length()-startPos-1);
+ srcA->type=srcAType.left(startPos+1).stripWhiteSpace();
+ }
+ }
+ else // maybe src has a name while dst has not
+ {
+ srcPos++;
+ int startPos=srcPos;
+ while (srcPos<srcAType.length() && isId(srcAType.at(srcPos))) srcPos++;
+ if (srcPos!=srcAType.length()) return FALSE; // nope not a name -> no match
+ else // its a name (most probably) so move it
+ {
+ srcA->name=srcAType.right(srcAType.length()-startPos);
+ srcA->type=srcAType.left(startPos).stripWhiteSpace();
+ }
+ }
+ }
+ else // without scopes the names match exactly
+ {
+ }
+ }
+ else if (srcA->name.length()==0 && dstA->name.length()==0)
+ // arguments match exactly but no name ->
+ // see if we can find the name
+ {
+ int i=srcAType.length()-1;
+ while (i>=0 && isId(srcAType.at(i))) i--;
+ if (i>0 && i<(int)srcAType.length()-1 && srcAType.at(i)!=':')
+ // there is (probably) a name
+ {
+ srcA->name=srcAType.right(srcAType.length()-i-1);
+ srcA->type=srcAType.left(i+1).stripWhiteSpace();
+ dstA->name=dstAType.right(dstAType.length()-i-1);
+ dstA->type=dstAType.left(i+1).stripWhiteSpace();
+ }
+ }
+ }
+ //printf("Match found!\n");
+ return TRUE; // all arguments match
+}
+
+// merges the initializer of two argument lists
+// pre: the types of the arguments in the list should match.
+void mergeArguments(ArgumentList *srcAl,ArgumentList *dstAl)
+{
+ //printf("mergeArguments `%s', `%s'\n",
+ // argListToString(srcAl).data(),argListToString(dstAl).data());
+ //printArgList(srcAl);printf(" <=> ");
+ //printArgList(dstAl);printf("\n");
+ if (srcAl==0 || dstAl==0 || srcAl->count()!=dstAl->count())
+ {
+ return; // invalid argument lists -> do not merge
+ }
+
+ ArgumentListIterator srcAli(*srcAl),dstAli(*dstAl);
+ Argument *srcA,*dstA;
+ for (;(srcA=srcAli.current(),dstA=dstAli.current());++srcAli,++dstAli)
+ {
+ if (srcA->defval.length()==0 && dstA->defval.length()>0)
+ {
+ //printf("Defval changing `%s'->`%s'\n",srcA->defval.data(),dstA->defval.data());
+ srcA->defval=dstA->defval.copy();
+ }
+ else if (srcA->defval.length()>0 && dstA->defval.length()==0)
+ {
+ //printf("Defval changing `%s'->`%s'\n",dstA->defval.data(),srcA->defval.data());
+ dstA->defval=srcA->defval.copy();
+ }
+ if (srcA->name.isEmpty() && !dstA->name.isEmpty())
+ {
+ //printf("type: `%s':=`%s'\n",srcA->type.data(),dstA->type.data());
+ //printf("name: `%s':=`%s'\n",srcA->name.data(),dstA->name.data());
+ srcA->type = dstA->type.copy();
+ srcA->name = dstA->name.copy();
+ }
+ else if (!srcA->name.isEmpty() && dstA->name.isEmpty())
+ {
+ //printf("type: `%s':=`%s'\n",dstA->type.data(),srcA->type.data());
+ //printf("name: `%s':=`%s'\n",dstA->name.data(),srcA->name.data());
+ dstA->type = srcA->type.copy();
+ dstA->name = dstA->name.copy();
+ }
+ int i1=srcA->type.find("::"),
+ i2=dstA->type.find("::"),
+ j1=srcA->type.length()-i1-2,
+ j2=dstA->type.length()-i2-2;
+ if (i1!=-1 && i2==-1 && srcA->type.right(j1)==dstA->type)
+ {
+ //printf("type: `%s':=`%s'\n",dstA->type.data(),srcA->type.data());
+ //printf("name: `%s':=`%s'\n",dstA->name.data(),srcA->name.data());
+ dstA->type = srcA->type.left(i1+2)+dstA->type;
+ dstA->name = dstA->name.copy();
+ }
+ else if (i1==-1 && i2!=-1 && dstA->type.right(j2)==srcA->type)
+ {
+ //printf("type: `%s':=`%s'\n",srcA->type.data(),dstA->type.data());
+ //printf("name: `%s':=`%s'\n",dstA->name.data(),srcA->name.data());
+ srcA->type = dstA->type.left(i2+2)+srcA->type;
+ srcA->name = dstA->name.copy();
+ }
+ }
+ //printf("result mergeArguments `%s', `%s'\n",
+ // argListToString(srcAl).data(),argListToString(dstAl).data());
+}
+
+//----------------------------------------------------------------------
+// searches for the class and member definitions corresponding with
+// memberName and className.
+// These classes are returned using `md' and `cd'.
+// returns TRUE if the class and member both could be found
+
+bool getDefs(const QString &memberName,const QString &className,
+ const char *args,MemberDef *&md, ClassDef *&cd, FileDef *&fd)
+{
+ //printf("Search for %s::%s %s\n",className.data(),memberName.data(),args);
+ fd=0; md=0; cd=0;
+ if (memberName.length()==0) return FALSE;
+ MemberName *mn;
+ if ((mn=memberNameDict[memberName]) && className.length()>0)
+ {
+ //printf(" >member name found\n");
+ ClassDef *fcd=0;
+ if ((fcd=getClass(className)))
+ {
+ //printf(" >member class found\n");
+ MemberDef *mmd=mn->first();
+ int mdist=maxInheritanceDepth;
+ while (mmd)
+ {
+ if ((mmd->protection()!=Private || extractPrivateFlag) &&
+ mmd->hasDocumentation()
+ /*mmd->detailsAreVisible()*/
+ /* && (args==0 || matchArgumentsOld(mmd->argsString(),args)) */
+ )
+ {
+ bool match=TRUE;
+ ArgumentList *argList=0;
+ if (args)
+ {
+ match=FALSE;
+ argList=new ArgumentList;
+ stringToArgumentList(args,argList);
+ match=matchArguments(mmd->argumentList(),argList);
+ }
+ if (match)
+ {
+ ClassDef *mcd=mmd->memberClass();
+ int m=minClassDistance(fcd,mcd);
+ if (m<mdist && mcd->isVisible())
+ {
+ mdist=m;
+ cd=mcd;
+ md=mmd;
+ fd=0;
+ }
+ }
+ if (argList)
+ {
+ delete argList;
+ }
+ }
+ mmd=mn->next();
+ }
+ if (mdist==maxInheritanceDepth && !strcmp(args,"()"))
+ // no exact match found, but if args="()" an arbitrary member will do
+ {
+ //printf(" >Searching for arbitrary member\n");
+ mmd=mn->first();
+ while (mmd)
+ {
+ if ((mmd->protection()!=Private || extractPrivateFlag) &&
+ (
+ mmd->hasDocumentation()
+ /*mmd->detailsAreVisible()*/
+ || mmd->isReference()
+ )
+ )
+ {
+ ClassDef *mcd=mmd->memberClass();
+ //printf(" >Class %s found\n",mcd->name().data());
+ int m=minClassDistance(fcd,mcd);
+ if (m<mdist && mcd->isVisible())
+ {
+ //printf("Class distance %d\n",m);
+ mdist=m;
+ cd=mcd;
+ md=mmd;
+ fd=0;
+ }
+ }
+ mmd=mn->next();
+ }
+ }
+ //printf(" >Succes=%d\n",mdist<maxInheritanceDepth);
+ return mdist<maxInheritanceDepth;
+ }
+ }
+ else // maybe an unrelated member ?
+ {
+ MemberName *mn;
+ if ((mn=functionNameDict[memberName]))
+ {
+ md=mn->first();
+ while (md)
+ {
+ if (/*md->detailsAreVisible()*/ md->hasDocumentation())
+ {
+ fd=md->getFileDef();
+ if (fd && fd->hasDocumentation())
+ {
+ cd=0;
+ return TRUE;
+ }
+ }
+ md=mn->next();
+ }
+ }
+ }
+ return FALSE;
+}
+
+//----------------------------------------------------------------------
+// Generate a hypertext link to the class with name `clName'.
+// If linkTxt is not null this text is used as the link, otherwise
+// the name of the class will be used. If the class could be found a
+// hypertext link (in HTML) is written, otherwise the text of the link will
+// be written.
+
+void generateClassRef(OutputList &ol,const char *clName,const char *linkTxt)
+{
+ QString className=clName;
+ QString linkText=linkTxt ? linkTxt : (const char *)className;
+ if (className.length()==0)
+ {
+ ol.docify(linkText);
+ return;
+ }
+ ClassDef *cd;
+ if ((cd=getClass(className)) && cd->isVisible())
+ {
+ ol.writeObjectLink(cd->getReference(),cd->classFile(),0,linkText);
+ if (!cd->isReference()) ol.writePageRef(cd->name(),0);
+ }
+ else
+ ol.docify(linkText);
+}
+
+//----------------------------------------------------------------------
+// generate a reference to a class or member.
+// `clName' is the name of the class that contains the documentation
+// string that is returned.
+// `name' is the name of the member or class that we want to link to.
+// `name' may have five formats:
+// 1) "ClassName"
+// 2) "memberName()" one of the (overloaded) function or define
+// with name memberName.
+// 3) "memberName(...)" a specific (overloaded) function or define
+// with name memberName
+// 4) "::memberName a non-function member or define
+// 5) ("ClassName::")+"memberName()"
+// 6) ("ClassName::")+"memberName(...)"
+// 7) ("ClassName::")+"memberName"
+
+void generateRef(OutputList &ol,const char *clName,
+ const char *name,bool inSeeBlock,const char *rt)
+{
+ //printf("generateRef(clName=%s,name=%s,rt=%s)\n",clName,name,rt);
+
+ // check if we have a plane name
+ QString tmpName = substitute(name,"#","::");
+ QString linkText = rt;
+ int scopePos=tmpName.findRev("::");
+ int bracePos=tmpName.find('(');
+ if (scopePos==-1 && bracePos==-1)
+ {
+ if (!inSeeBlock) /* check for class link */
+ {
+ if (linkText.isNull()) linkText=tmpName;
+ // check if this is a class reference
+ if (clName!=tmpName)
+ generateClassRef(ol,name,linkText);
+ else
+ ol.docify(linkText);
+ return;
+ }
+ else /* check if it is a class, if not continue to search */
+ {
+ if (clName!=tmpName && getClass(tmpName)!=0)
+ {
+ generateClassRef(ol,tmpName,linkText);
+ return;
+ }
+ }
+ }
+
+ // extract scope
+ QString scopeStr;
+ if (scopePos>0) scopeStr=tmpName.left(scopePos); else scopeStr=clName;
+
+ // extract name
+ int startNamePos=scopePos!=-1 ? scopePos+2 : 0;
+ int endNamePos=bracePos!=-1 ? bracePos : tmpName.length();
+ QString nameStr=tmpName.mid(startNamePos,endNamePos-startNamePos);
+
+ // extract arguments
+ QString argsStr;
+ if (bracePos!=-1) argsStr=tmpName.right(tmpName.length()-bracePos);
+
+ bool explicitLink=TRUE;
+ // create a default link text if none was explicitly given
+ if (linkText.isNull())
+ {
+ if (!scopeStr.isNull() && scopePos>0) linkText=scopeStr+"::";
+ linkText+=nameStr;
+ explicitLink=FALSE;
+ }
+
+ //printf("scope=`%s' name=`%s' arg=`%s' linkText=`%s'\n",
+ // scopeStr.data(),nameStr.data(),argsStr.data(),linkText.data());
+
+ //Define *d=0;
+ MemberDef *md;
+ ClassDef *cd;
+ FileDef *fd;
+ // check if nameStr is a member or global.
+ if (getDefs(nameStr,scopeStr,argsStr,md,cd,fd))
+ {
+ QString anchor = md->hasDocumentation() ? md->anchor() : 0;
+ QString cName,aName;
+ if (cd) // nameStr is a member of cd
+ {
+ //printf("addObjectLink(%s,%s,%s,%s)\n",cd->getReference(),
+ // cd->classFile(),anchor.data(),resultName.stripWhiteSpace().data());
+ ol.writeObjectLink(cd->getReference(),
+ cd->classFile(),anchor,
+ linkText.stripWhiteSpace());
+ cName=cd->name();
+ aName=md->anchor();
+ }
+ else if (fd) // nameStr is a global in file fd
+ {
+ //printf("addFileLink(%s,%s,%s)\n",fd->diskName(),anchor.data(),
+ // resultName.stripWhiteSpace().data());
+ ol.writeObjectLink(fd->getReference(),fd->diskName(),
+ anchor, linkText.stripWhiteSpace());
+ cName=fd->name();
+ aName=md->anchor();
+ }
+ else // should not be reached
+ {
+ //printf("add no link fd=cd=0\n");
+ ol.docify(linkText);
+ }
+
+ // for functions we add the arguments if explicitly specified or else "()"
+ if (!rt && (md->isFunction() || md->isPrototype() || md->isSignal() || md->isSlot()))
+ {
+ if (argsStr.isNull())
+ ol.writeString("()");
+ else
+ ol.docify(argsStr);
+ }
+
+ // generate the page reference (for LaTeX)
+ if (cName.length()>0 || aName.length()>0)
+ {
+ if (/*md->detailsAreVisible() &&*/
+ (
+ (cd && !cd->isReference() &&
+ // (cd->hasDocumentation() || !hideClassFlag) &&
+ // (cd->protection()!=Private || extractPrivateFlag)
+ cd->isVisible()
+ ) ||
+ (fd && !fd->isReference())
+ )
+ ) ol.writePageRef(cName,aName);
+ }
+ }
+// else if (!nameStr.isNull() && (d=defineDict[nameStr]))
+// // check if nameStr is perhaps a define
+// {
+// if (d->hasDocumentation() && d->fileDef)
+// {
+// ol.writeObjectLink(0,d->fileDef->diskName(),d->anchor,
+// linkText.stripWhiteSpace());
+// if (!explicitLink) ol.docify(argsStr);
+// }
+// }
+ else // nameStr is a false alarm or a typo.
+ {
+ if (rt)
+ ol.docify(rt);
+ else
+ {
+ ol.docify(linkText);
+ if (!argsStr.isNull()) ol.docify(argsStr);
+ }
+ }
+ return;
+}
+
+//----------------------------------------------------------------------
+// General function that generates the HTML code for a reference to some
+// file, class or member from text `lr' within the context of class `clName'.
+// This link has the text 'lt' (if not 0), otherwise `lr' is used as a
+// basis for the link's text.
+
+void generateLink(OutputList &ol,const char *clName,
+ const char *lr,bool inSeeBlock,const char *lt)
+{
+ QString linkRef=lr;
+ //PageInfo *pi=0;
+ //printf("generateLink(%s,%s)\n",lr,lt);
+ //FileInfo *fi=0;
+ FileDef *fd;
+ bool ambig;
+ if (linkRef.length()==0) // no reference name!
+ ol.docify(lt);
+ else if ((pageDict[linkRef])) // link to a page
+ ol.writeObjectLink(0,linkRef,0,lt);
+ else if ((exampleDict[linkRef])) // link to an example
+ ol.writeObjectLink(0,linkRef+"-example",0,lt);
+ else if ((fd=findFileDef(&inputNameDict,linkRef,ambig))
+ && fd->hasDocumentation())
+ // link to documented input file
+ ol.writeObjectLink(fd->getReference(),fd->diskName(),0,lt);
+ else // probably a class or member reference
+ generateRef(ol,clName,lr,inSeeBlock,lt);
+}
+
+void generateFileRef(OutputList &ol,const char *name,const char *text)
+{
+ QString linkText = text ? text : name;
+ //FileInfo *fi;
+ FileDef *fd;
+ bool ambig;
+ if ((fd=findFileDef(&inputNameDict,name,ambig)) &&
+ fd->hasDocumentation())
+ // link to documented input file
+ ol.writeObjectLink(fd->getReference(),fd->diskName(),0,linkText);
+ else
+ ol.docify(linkText);
+}
+
+//----------------------------------------------------------------------
+
+QString substituteClassNames(const QString &s)
+{
+ int i=0,l,p;
+ QString result;
+ QRegExp r("[a-z_A-Z][a-z_A-Z0-9]*");
+ while ((p=r.match(s,i,&l))!=-1)
+ {
+ QString *subst;
+ if (p>i) result+=s.mid(i,p-i);
+ if ((subst=substituteDict[s.mid(p,l)]))
+ {
+ result+=*subst;
+ }
+ else
+ {
+ result+=s.mid(p,l);
+ }
+ i=p+l;
+ }
+ result+=s.mid(i,s.length()-i);
+ return result;
+}
+
+//----------------------------------------------------------------------
+
+QString convertSlashes(const QString &s,bool dots)
+{
+ QString result;
+ int i,l=s.length();
+ for (i=0;i<l;i++)
+ if (s.at(i)!='/' && (!dots || s.at(i)!='.'))
+ {
+ if (caseSensitiveNames)
+ {
+ result+=s[i];
+ }
+ else
+ {
+ result+=tolower(s[i]);
+ }
+ }
+ else
+ result+="_";
+ return result;
+}
+
+//----------------------------------------------------------------------
+// substitute all occurences of `src' in `s' by `dst'
+
+QString substitute(const char *s,const char *src,const char *dst)
+{
+ QString input=s;
+ QString output;
+ int i=0,p;
+ while ((p=input.find(src,i))!=-1)
+ {
+ output+=input.mid(i,p-i);
+ output+=dst;
+ i=p+strlen(src);
+ }
+ output+=input.mid(i,input.length()-i);
+ return output;
+}
+
+//----------------------------------------------------------------------
+
+FileDef *findFileDef(const FileNameDict *fnDict,const char *n,bool &ambig)
+{
+ ambig=FALSE;
+ QString name=n;
+ QString path;
+ if (name.isNull()) return 0;
+ int slashPos=QMAX(name.findRev('/'),name.findRev('\\'));
+ if (slashPos!=-1)
+ {
+ path=name.left(slashPos+1);
+ name=name.right(name.length()-slashPos-1);
+ }
+ //printf("findFileDef path=`%s' name=`%s'\n",path.data(),name.data());
+ if (name.isNull()) return 0;
+ FileName *fn;
+ if ((fn=(*fnDict)[name]))
+ {
+ if (fn->count()==1)
+ {
+ return fn->first();
+ }
+ else // file name alone is ambigious
+ {
+ int count=0;
+ FileDef *fd=fn->first();
+ FileDef *lastMatch=0;
+ while (fd)
+ {
+ if (path.isNull() || fd->getPath().right(path.length())==path)
+ {
+ count++;
+ lastMatch=fd;
+ }
+ fd=fn->next();
+ }
+ ambig=(count>1);
+ return lastMatch;
+ }
+ }
+ return 0;
+}
+
+//----------------------------------------------------------------------
+
+void showFileDefMatches(const FileNameDict *fnDict,const char *n)
+{
+ QString name=n;
+ QString path;
+ int slashPos=QMAX(name.findRev('/'),name.findRev('\\'));
+ if (slashPos!=-1)
+ {
+ path=name.left(slashPos+1);
+ name=name.right(name.length()-slashPos-1);
+ }
+ FileName *fn;
+ if ((fn=(*fnDict)[name]))
+ {
+ FileDef *fd=fn->first();
+ while (fd)
+ {
+ if (path.isNull() || fd->getPath().right(path.length())==path)
+ {
+ msg(" %s\n",fd->absFilePath().data());
+ }
+ fd=fn->next();
+ }
+ }
+}
+
diff --git a/src/util.h b/src/util.h
new file mode 100644
index 0000000..9dfd097
--- /dev/null
+++ b/src/util.h
@@ -0,0 +1,82 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#ifndef UTIL_H
+#define UTIL_H
+
+#include <qlist.h>
+#include <qtstream.h>
+#include <ctype.h>
+//#include "filedef.h"
+//#include "filename.h"
+#include "memberdef.h"
+//#include "outputlist.h"
+
+
+class ClassDef;
+class FileDef;
+class MemberList;
+class NamespaceDef;
+class FileNameDict;
+class ArgumentList;
+class OutputList;
+
+extern void writeMemberDecs(OutputList &ol, ClassDef *cd, NamespaceDef *nd,
+ FileDef *fd, const char *title, const char *subtitle,
+ MemberList *ml);
+extern void writeMemberDocs(OutputList &ol,
+ MemberList *ml,const char *scopeName,MemberDef::MemberType m);
+extern void setAnchors(char id,MemberList *ml);
+//extern int countMemberDocs(MemberList *ml,MemberDef::MemberType m);
+extern QString fileToString(const char *name);
+extern QString dateToString(bool);
+//extern OutputList linkifyText(const char *clName,const char *name,
+// const char *text);
+extern bool getDefs(const QString &memberName,const QString &className,
+ const char *, MemberDef *&md, ClassDef *&cd,FileDef *&fd);
+extern void generateRef(OutputList &ol,const char *,
+ const char *,bool inSeeBlock,const char * =0);
+extern void generateLink(OutputList &ol,const char *,
+ const char *,bool inSeeBlock,const char *);
+extern void generateClassRef(OutputList &ol,const char *clName,
+ const char *linkTxt=0);
+extern void generateFileRef(OutputList &ol,const char *,
+ const char *linkTxt=0);
+extern bool matchArguments(ArgumentList *,ArgumentList *,
+ const char *cl=0,const char *ns=0);
+extern void mergeArguments(ArgumentList *,ArgumentList *);
+extern QString substituteClassNames(const QString &s);
+extern QString convertSlashes(const QString &s,bool dots=FALSE);
+extern QString substitute(const char *s,const char *src,const char *dst);
+extern QString resolveDefines(const char *n);
+extern ClassDef *getClass(const char *key);
+//extern int strcscmp(const char *s1,const char *s2);
+extern FileDef *findFileDef(const FileNameDict *fnDict,const char *n,
+ bool &ambig);
+extern void showFileDefMatches(const FileNameDict *fnDict,const char *n);
+extern int guessSection(const char *name);
+//extern QString nameToFile(const char *name);
+extern bool isId(char c);
+extern QString removeRedundantWhiteSpace(const QString &s);
+extern void startTitle(OutputList &ol);
+extern void endTitle(OutputList &ol,const char *name);
+void startFile(OutputList &ol,const char *name,
+ const char *title,bool external=FALSE);
+void endFile(OutputList &ol,bool external=FALSE);
+void writeQuickLinks(OutputList &ol,bool compact,bool external=FALSE);
+QString argListToString(ArgumentList *al);
+
+#endif
diff --git a/src/version.h b/src/version.h
new file mode 100644
index 0000000..c148ab7
--- /dev/null
+++ b/src/version.h
@@ -0,0 +1,22 @@
+/******************************************************************************
+ *
+ * $Id$
+ *
+ * Copyright (C) 1997-1999 by Dimitri van Heesch.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
+ * for any purpose. It is provided "as is" without express or implied warranty.
+ * See the GNU General Public License for more details.
+ *
+ * All output generated with Doxygen is not covered by this license.
+ *
+ */
+
+#ifndef VERSION_H
+#define VERSION_H
+
+extern char versionString[];
+
+#endif