diff options
author | mueller <mueller@afe2bf4a-e733-0410-8a33-86f594647bc7> | 1999-12-15 19:25:10 (GMT) |
---|---|---|
committer | mueller <mueller@afe2bf4a-e733-0410-8a33-86f594647bc7> | 1999-12-15 19:25:10 (GMT) |
commit | 719f0a35063be88eddcc4ed8fe7a940de47ef20c (patch) | |
tree | cc1cd70cf5761ddf72ff114c0b65576c3f4c1d2a /src | |
parent | bd30c025c4651ddda467f1af09d4c7ccab397bde (diff) | |
download | Doxygen-719f0a35063be88eddcc4ed8fe7a940de47ef20c.zip Doxygen-719f0a35063be88eddcc4ed8fe7a940de47ef20c.tar.gz Doxygen-719f0a35063be88eddcc4ed8fe7a940de47ef20c.tar.bz2 |
initial version
Diffstat (limited to 'src')
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=¯oExpansionFlag; } +<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> "); + + if (page>0) + { + printf("<a href=\"%s?page=%d&which=%s&what=%s&query=%s\">" + "<font color=\"ffffff\">prev</font></a> ", + 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> ", + cgiBin, i, + wordOnly?"word":"doc", + nameOnly?"name":"string", + encQueryInput, i+1); + } + else + { + printf("<b><font color=\"ffffff\">%d</font></b></a> ",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(" </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 "<b>the</b>" for example, will find " + " documents containing the words "<b>the</b>", " + " "<b>the</b>re", and "fea<b>the</b>r".<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 "<b>the</b>" for example, will look " + " for documents containing the word "<b>the</b>" and not for" + " documents containing the word "<b>the</b>re".<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 "<b>set</b>" for example, will " + " result in a list of links to the documentation of all functions and classes " + " that contain the word "<b>set</b>" 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 "<b>+</b>" to the beginning of " + " the word. You can quickly reject results by adding a word that appears only " + " in unwanted documents with a "<b>-</b>" 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,"&",5)==0) { result+='&'; p+=5; } + else if (strncmp(p,"<",4)==0) { result+='<'; p+=4; } + else if (strncmp(p,">",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"|("&"("&"|"=")*)|(">"(">"|"=")*)|("<"("<"|"=")*)|("->"[*]*)|[+\-*%/|~!=,\^]|[+\-*%/\^!|~=\[(][=|+\-\])]) { // 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>"<" { memberName+="<"; } +<ReadOperator>">" { 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>"&" { memberArgs+="&"; } +<ReadArgs>"<" { memberArgs+="<"; } +<ReadArgs>">" { 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> "; +// if (hierarchyClasses>0) +// tt << "<a doxygen=\"_doc:\" href=\"/hierarchy.html\">Class hierarchy</a> "; +// if (annotatedClasses>0) +// tt << "<a doxygen=\"_doc:\" href=\"/annotated.html\">Compound list</a> "; +// if (documentedFiles>0) +// tt << "<a doxygen=\"_doc:\" href=\"/files.html\">File list</a> "; +// if (includeFiles.count()>0) +// tt << "<a doxygen=\"_doc:\" href=\"/headers.html\">Header files</a> "; +// if (documentedMembers>0) +// tt << "<a doxygen=\"_doc:\" href=\"/functions.html\">Compound Members</a> "; +// if (documentedFunctions>0) +// tt << "<a doxygen=\"_doc:\" href=\"/globals.html\">File Members</a> "; +// if (pageList.count()>0) +// tt << "<a doxygen=\"_doc:\" href=\"/pages.html\">Related Pages</a> "; +// if (exampleList.count()>0) +// tt << "<a doxygen=\"_doc:\" href=\"/examples.html\">Examples</a> "; +// 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> written by <a href=" +// "\"mailto:dimitri@stack.nl\">Dimitri van Heesch</a>, © " +// "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> "; +// if (hierarchyClasses>0) +// t << "<a href=\"hierarchy.html\">Class hierarchy</a> "; +// if (annotatedClasses>0) +// t << "<a href=\"annotated.html\">Compound list</a> "; +// if (documentedFiles>0) +// t << "<a href=\"files.html\">File list</a> "; +// if (includeFiles.count()>0) +// t << "<a href=\"headers.html\">Header files</a> "; +// if (documentedMembers>0) +// t << "<a href=\"functions.html\">Compound Members</a> "; +// if (documentedFunctions>0) +// t << "<a href=\"globals.html\">File Members</a> "; +// if (pageList.count()>0) +// t << "<a href=\"pages.html\">Related Pages</a> "; +// if (exampleList.count()>0) +// t << "<a href=\"examples.html\">Examples</a> "; +// 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> "; +} + +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> "; + } + break; + default: + if (footer.length()==0) + t << " <a href=\"mailto:dimitri@stack.nl\">Dimitri van Heesch</a>, © " + "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> written by <a href=" +// "\"mailto:dimitri@stack.nl\">Dimitri van Heesch</a>, © " +// "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 << ""<a href=\"" << refName << "#" << lab << "\">"; + docify(title); + t << "</a>""; +} + +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 << "<"; break; + case '>': t << ">"; break; + case '&': t << "&"; break; + case '\\': + if (*p=='<') + { t << "<"; p++; } + else if (*p=='>') + { t << ">"; 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 << "©"; } + void writeQuote() { t << """; } + 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>"©" { outDoc->writeCopyright(); } +<DocScan>""" { 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=¤t->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=¤t->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 = ¤t->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=¤t->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ë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ï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ïmplemented; " + "de API wordt er niet door beï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ë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ë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ë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ë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ï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ïmplemented; " + "de API wordt er niet door beï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 |