diff options
Diffstat (limited to 'src')
164 files changed, 10262 insertions, 10899 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index f4e1231..06e0e44 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -3,8 +3,10 @@ include_directories( ${CMAKE_SOURCE_DIR}/qtools ${CMAKE_SOURCE_DIR}/libmd5 + ${CMAKE_SOURCE_DIR}/liblodepng + ${CMAKE_SOURCE_DIR}/libmscgen ${CMAKE_SOURCE_DIR}/libversion - ${CMAKE_SOURCE_DIR}/vhdlparser/ + ${CMAKE_SOURCE_DIR}/vhdlparser ${CMAKE_SOURCE_DIR}/src ${CLANG_INCLUDEDIR} ${GENERATED_SRC} @@ -15,7 +17,7 @@ file(MAKE_DIRECTORY ${GENERATED_SRC}) file(GLOB LANGUAGE_FILES "${CMAKE_SOURCE_DIR}/src/translator_??.h") # instead of increasebuffer.py -add_definitions(-DYY_BUF_SIZE=262144 -DYY_READ_BUF_SIZE=262144) +add_definitions(-DYY_BUF_SIZE=${enlarge_lex_buffers} -DYY_READ_BUF_SIZE=${enlarge_lex_buffers}) # generate settings.h file(GENERATE OUTPUT ${GENERATED_SRC}/settings.h @@ -38,6 +40,10 @@ add_custom_command( OUTPUT ${GENERATED_SRC}/configvalues.h ) set_source_files_properties(${GENERATED_SRC}/configvalues.h PROPERTIES GENERATED 1) +add_custom_target( + generate_configvalues_header + DEPENDS ${GENERATED_SRC}/configvalues.h +) # configvalues.cpp add_custom_command( @@ -175,6 +181,16 @@ add_library(_doxygen STATIC docparser.cpp docsets.cpp dot.cpp + dotcallgraph.cpp + dotclassgraph.cpp + dotdirdeps.cpp + dotfilepatcher.cpp + dotgfxhierarchytable.cpp + dotgraph.cpp + dotgroupcollaboration.cpp + dotincldepgraph.cpp + dotnode.cpp + dotrunner.cpp doxygen.cpp eclipsehelp.cpp emoji.cpp @@ -197,7 +213,6 @@ add_library(_doxygen STATIC latexdocvisitor.cpp latexgen.cpp layout.cpp - lodepng.cpp mandocvisitor.cpp mangen.cpp sqlite3gen.cpp @@ -233,6 +248,7 @@ add_library(_doxygen STATIC xmlgen.cpp docbookvisitor.cpp docbookgen.cpp + docgroup.cpp ) add_executable(doxygen main.cpp) @@ -262,6 +278,8 @@ target_link_libraries(doxygen doxycfg qtools md5 + lodepng + mscgen version vhdlparser ${SQLITE3_LIBRARIES} diff --git a/src/clangparser.cpp b/src/clangparser.cpp index f24ec0a..271b99f 100644 --- a/src/clangparser.cpp +++ b/src/clangparser.cpp @@ -782,7 +782,7 @@ void ClangParser::linkIdentifier(CodeOutputInterface &ol,FileDef *fd, g_currentMemberDef && d->definitionType()==Definition::TypeMember && (g_currentMemberDef!=d || g_currentLine<line)) // avoid self-reference { - addDocCrossReference(g_currentMemberDef,(MemberDef*)d); + addDocCrossReference(g_currentMemberDef,dynamic_cast<MemberDef *>(d)); } writeMultiLineCodeLink(ol,fd,line,column,d,text); } diff --git a/src/classdef.cpp b/src/classdef.cpp index 5ea8cea..a7b59c1 100644 --- a/src/classdef.cpp +++ b/src/classdef.cpp @@ -33,6 +33,8 @@ #include "example.h" #include "outputlist.h" #include "dot.h" +#include "dotclassgraph.h" +#include "dotrunner.h" #include "defargs.h" #include "debug.h" #include "docparser.h" @@ -61,6 +63,7 @@ class ClassDefImpl : public DefinitionImpl, public ClassDef /** Destroys a compound definition. */ ~ClassDefImpl(); + virtual ClassDef *resolveAlias() { return this; } virtual DefType definitionType() const { return TypeClass; } virtual QCString getOutputFileBase() const; virtual QCString getInstanceOutputFileBase() const; @@ -92,7 +95,7 @@ class ClassDefImpl : public DefinitionImpl, public ClassDef virtual bool isSubClass(ClassDef *bcd,int level=0) const; virtual bool isAccessibleMember(const MemberDef *md) const; virtual QDict<ClassDef> *getTemplateInstances() const; - virtual ClassDef *templateMaster() const; + virtual const ClassDef *templateMaster() const; virtual bool isTemplate() const; virtual IncludeInfo *includeInfo() const; virtual UsesClassDict *usedImplementationClasses() const; @@ -120,7 +123,7 @@ class ClassDefImpl : public DefinitionImpl, public ClassDef virtual const QList<MemberList> &getMemberLists() const; virtual MemberGroupSDict *getMemberGroupSDict() const; virtual QDict<int> *getTemplateBaseClassNames() const; - virtual ClassDef *getVariableInstance(const char *templSpec); + virtual ClassDef *getVariableInstance(const char *templSpec) const; virtual bool isUsedOnly() const; virtual QCString anchor() const; virtual bool isEmbeddedInOuterScope() const; @@ -141,6 +144,10 @@ class ClassDefImpl : public DefinitionImpl, public ClassDef virtual QCString getMemberListFileName() const; virtual bool subGrouping() const; virtual bool isSliceLocal() const; + virtual bool hasNonReferenceSuperClass() const; + virtual ClassDef *insertTemplateInstance(const QCString &fileName,int startLine,int startColumn, + const QCString &templSpec,bool &freshInstance) const; + virtual void insertBaseClass(ClassDef *,const char *name,Protection p,Specifier s,const char *t=0); virtual void insertSubClass(ClassDef *,Protection p,Specifier s,const char *t=0); virtual void setIncludeFile(FileDef *fd,const char *incName,bool local,bool force); @@ -153,9 +160,7 @@ class ClassDefImpl : public DefinitionImpl, public ClassDef virtual void setSubGrouping(bool enabled); virtual void setProtection(Protection p); virtual void setGroupDefForAllMembers(GroupDef *g,Grouping::GroupPri_t pri,const QCString &fileName,int startLine,bool hasDocs); - virtual void addInnerCompound(Definition *d); - virtual ClassDef *insertTemplateInstance(const QCString &fileName,int startLine,int startColumn, - const QCString &templSpec,bool &freshInstance); + virtual void addInnerCompound(const Definition *d); virtual void addUsedClass(ClassDef *cd,const char *accessName,Protection prot); virtual void addUsedByClass(ClassDef *cd,const char *accessName,Protection prot); virtual void setIsStatic(bool b); @@ -164,9 +169,9 @@ class ClassDefImpl : public DefinitionImpl, public ClassDef virtual void setClassSpecifier(uint64 spec); virtual void setTemplateArguments(ArgumentList *al); virtual void setTemplateBaseClassNames(QDict<int> *templateNames); - virtual void setTemplateMaster(ClassDef *tm); + virtual void setTemplateMaster(const ClassDef *tm); virtual void setTypeConstraints(ArgumentList *al); - virtual void addMembersToTemplateInstance(ClassDef *cd,const char *templSpec); + virtual void addMembersToTemplateInstance(const ClassDef *cd,const char *templSpec); virtual void makeTemplateArgument(bool b=TRUE); virtual void setCategoryOf(ClassDef *cd); virtual void setUsedOnly(bool b); @@ -182,75 +187,79 @@ class ClassDefImpl : public DefinitionImpl, public ClassDef virtual void mergeMembers(); virtual void sortMemberLists(); virtual void distributeMemberGroupDocumentation(); - virtual void writeDocumentation(OutputList &ol); - virtual void writeDocumentationForInnerClasses(OutputList &ol); - virtual void writeMemberPages(OutputList &ol); - virtual void writeMemberList(OutputList &ol); - virtual void writeDeclaration(OutputList &ol,MemberDef *md,bool inGroup, - ClassDef *inheritedFrom,const char *inheritId); - virtual void writeQuickMemberLinks(OutputList &ol,MemberDef *md) const; - virtual void writeSummaryLinks(OutputList &ol); + virtual void writeDocumentation(OutputList &ol) const; + virtual void writeDocumentationForInnerClasses(OutputList &ol) const; + virtual void writeMemberPages(OutputList &ol) const; + virtual void writeMemberList(OutputList &ol) const; + virtual void writeDeclaration(OutputList &ol,const MemberDef *md,bool inGroup, + const ClassDef *inheritedFrom,const char *inheritId) const; + virtual void writeQuickMemberLinks(OutputList &ol,const MemberDef *md) const; + virtual void writeSummaryLinks(OutputList &ol) const; virtual void reclassifyMember(MemberDef *md,MemberType t); - virtual void writeInlineDocumentation(OutputList &ol); + virtual void writeInlineDocumentation(OutputList &ol) const; virtual void writeDeclarationLink(OutputList &ol,bool &found, - const char *header,bool localNames); + const char *header,bool localNames) const; virtual void removeMemberFromLists(MemberDef *md); + virtual void setAnonymousEnumType(); + virtual void countMembers(); + virtual void addGroupedInheritedMembers(OutputList &ol,MemberListType lt, - ClassDef *inheritedFrom,const QCString &inheritId); - virtual int countMembersIncludingGrouped(MemberListType lt,ClassDef *inheritedFrom,bool additional); - virtual int countInheritanceNodes(); + const ClassDef *inheritedFrom,const QCString &inheritId) const; virtual void writeTagFile(FTextStream &); - virtual void setVisited(bool visited) { m_visited = visited; } + virtual void setVisited(bool visited) const { m_visited = visited; } virtual bool isVisited() const { return m_visited; } - virtual bool hasNonReferenceSuperClass() const; - virtual int countMemberDeclarations(MemberListType lt,ClassDef *inheritedFrom, - int lt2,bool invert,bool showAlways,QPtrDict<void> *visitedClasses); + virtual int countMembersIncludingGrouped(MemberListType lt,const ClassDef *inheritedFrom,bool additional) const; + virtual int countInheritanceNodes() const; + virtual int countMemberDeclarations(MemberListType lt,const ClassDef *inheritedFrom, + int lt2,bool invert,bool showAlways,QPtrDict<void> *visitedClasses) const; virtual void writeMemberDeclarations(OutputList &ol,MemberListType lt,const QCString &title, - const char *subTitle=0,bool showInline=FALSE,ClassDef *inheritedFrom=0, + const char *subTitle=0,bool showInline=FALSE,const ClassDef *inheritedFrom=0, int lt2=-1,bool invert=FALSE,bool showAlways=FALSE, - QPtrDict<void> *visitedClasses=0); + QPtrDict<void> *visitedClasses=0) const; private: - bool m_visited; + mutable bool m_visited; void addUsedInterfaceClasses(MemberDef *md,const char *typeStr); - void showUsedFiles(OutputList &ol); + void showUsedFiles(OutputList &ol) const; - void writeDocumentationContents(OutputList &ol,const QCString &pageTitle); + void writeDocumentationContents(OutputList &ol,const QCString &pageTitle) const; void internalInsertMember(MemberDef *md,Protection prot,bool addToAllList); void addMemberToList(MemberListType lt,MemberDef *md,bool isBrief); MemberList *createMemberList(MemberListType lt); - void writeInheritedMemberDeclarations(OutputList &ol,MemberListType lt,int lt2,const QCString &title,ClassDef *inheritedFrom,bool invert,bool showAlways,QPtrDict<void> *visitedClasses); - void writeMemberDocumentation(OutputList &ol,MemberListType lt,const QCString &title,bool showInline=FALSE); - void writeSimpleMemberDocumentation(OutputList &ol,MemberListType lt); - void writePlainMemberDeclaration(OutputList &ol,MemberListType lt,bool inGroup,ClassDef *inheritedFrom,const char *inheritId); - void writeBriefDescription(OutputList &ol,bool exampleFlag); + void writeInheritedMemberDeclarations(OutputList &ol,MemberListType lt,int lt2,const QCString &title, + const ClassDef *inheritedFrom,bool invert, + bool showAlways,QPtrDict<void> *visitedClasses) const; + void writeMemberDocumentation(OutputList &ol,MemberListType lt,const QCString &title,bool showInline=FALSE) const; + void writeSimpleMemberDocumentation(OutputList &ol,MemberListType lt) const; + void writePlainMemberDeclaration(OutputList &ol,MemberListType lt,bool inGroup,const ClassDef *inheritedFrom,const char *inheritId) const; + void writeBriefDescription(OutputList &ol,bool exampleFlag) const; void writeDetailedDescription(OutputList &ol,const QCString &pageType,bool exampleFlag, - const QCString &title,const QCString &anchor=QCString()); - void writeIncludeFiles(OutputList &ol); - void writeIncludeFilesForSlice(OutputList &ol); + const QCString &title,const QCString &anchor=QCString()) const; + void writeIncludeFiles(OutputList &ol) const; + void writeIncludeFilesForSlice(OutputList &ol) const; //void writeAllMembersLink(OutputList &ol); - void writeInheritanceGraph(OutputList &ol); - void writeCollaborationGraph(OutputList &ol); - void writeMemberGroups(OutputList &ol,bool showInline=FALSE); - void writeNestedClasses(OutputList &ol,const QCString &title); - void writeInlineClasses(OutputList &ol); - void startMemberDeclarations(OutputList &ol); - void endMemberDeclarations(OutputList &ol); - void startMemberDocumentation(OutputList &ol); - void endMemberDocumentation(OutputList &ol); - void writeAuthorSection(OutputList &ol); - void writeMoreLink(OutputList &ol,const QCString &anchor); - void writeDetailedDocumentationBody(OutputList &ol); - - int countAdditionalInheritedMembers(); - void writeAdditionalInheritedMembers(OutputList &ol); - void addClassAttributes(OutputList &ol); + void writeInheritanceGraph(OutputList &ol) const; + void writeCollaborationGraph(OutputList &ol) const; + void writeMemberGroups(OutputList &ol,bool showInline=FALSE) const; + void writeNestedClasses(OutputList &ol,const QCString &title) const; + void writeInlineClasses(OutputList &ol) const; + void startMemberDeclarations(OutputList &ol) const; + void endMemberDeclarations(OutputList &ol) const; + void startMemberDocumentation(OutputList &ol) const; + void endMemberDocumentation(OutputList &ol) const; + void writeAuthorSection(OutputList &ol) const; + void writeMoreLink(OutputList &ol,const QCString &anchor) const; + void writeDetailedDocumentationBody(OutputList &ol) const; + + int countAdditionalInheritedMembers() const; + void writeAdditionalInheritedMembers(OutputList &ol) const; + void addClassAttributes(OutputList &ol) const; int countInheritedDecMembers(MemberListType lt, - ClassDef *inheritedFrom,bool invert,bool showAlways, - QPtrDict<void> *visitedClasses); + const ClassDef *inheritedFrom,bool invert,bool showAlways, + QPtrDict<void> *visitedClasses) const; void getTitleForMemberListType(MemberListType type, - QCString &title,QCString &subtitle); + QCString &title,QCString &subtitle) const; QCString includeStatement() const; void addTypeConstraint(const QCString &typeConstraint,const QCString &type); @@ -267,6 +276,265 @@ ClassDef *createClassDef( { return new ClassDefImpl(fileName,startLine,startColumn,name,ct,ref,fName,isSymbol,isJavaEnum); } +//----------------------------------------------------------------------------- + +class ClassDefAliasImpl : public DefinitionAliasImpl, public ClassDef +{ + public: + ClassDefAliasImpl(const Definition *newScope,const ClassDef *cd) : DefinitionAliasImpl(newScope,cd) {} + virtual ~ClassDefAliasImpl() {} + virtual DefType definitionType() const { return TypeClass; } + + const ClassDef *getCdAlias() const { return dynamic_cast<const ClassDef*>(getAlias()); } + virtual ClassDef *resolveAlias() { return const_cast<ClassDef*>(getCdAlias()); } + + virtual QCString getOutputFileBase() const + { return getCdAlias()->getOutputFileBase(); } + virtual QCString getInstanceOutputFileBase() const + { return getCdAlias()->getInstanceOutputFileBase(); } + virtual QCString getSourceFileBase() const + { return getCdAlias()->getSourceFileBase(); } + virtual QCString getReference() const + { return getCdAlias()->getReference(); } + virtual bool isReference() const + { return getCdAlias()->isReference(); } + virtual bool isLocal() const + { return getCdAlias()->isLocal(); } + virtual ClassSDict *getClassSDict() const + { return getCdAlias()->getClassSDict(); } + virtual bool hasDocumentation() const + { return getCdAlias()->hasDocumentation(); } + virtual bool hasDetailedDescription() const + { return getCdAlias()->hasDetailedDescription(); } + virtual QCString collaborationGraphFileName() const + { return getCdAlias()->collaborationGraphFileName(); } + virtual QCString inheritanceGraphFileName() const + { return getCdAlias()->inheritanceGraphFileName(); } + virtual QCString displayName(bool includeScope=TRUE) const + { return getCdAlias()->displayName(includeScope); } + virtual CompoundType compoundType() const + { return getCdAlias()->compoundType(); } + virtual QCString compoundTypeString() const + { return getCdAlias()->compoundTypeString(); } + virtual BaseClassList *baseClasses() const + { return getCdAlias()->baseClasses(); } + virtual BaseClassList *subClasses() const + { return getCdAlias()->subClasses(); } + virtual MemberNameInfoSDict *memberNameInfoSDict() const + { return getCdAlias()->memberNameInfoSDict(); } + virtual Protection protection() const + { return getCdAlias()->protection(); } + virtual bool isLinkableInProject() const + { return getCdAlias()->isLinkableInProject(); } + virtual bool isLinkable() const + { return getCdAlias()->isLinkable(); } + virtual bool isVisibleInHierarchy() const + { return getCdAlias()->isVisibleInHierarchy(); } + virtual bool visibleInParentsDeclList() const + { return getCdAlias()->visibleInParentsDeclList(); } + virtual ArgumentList *templateArguments() const + { return getCdAlias()->templateArguments(); } + virtual NamespaceDef *getNamespaceDef() const + { return getCdAlias()->getNamespaceDef(); } + virtual FileDef *getFileDef() const + { return getCdAlias()->getFileDef(); } + virtual MemberDef *getMemberByName(const QCString &s) const + { return getCdAlias()->getMemberByName(s); } + virtual bool isBaseClass(const ClassDef *bcd,bool followInstances,int level=0) const + { return getCdAlias()->isBaseClass(bcd,followInstances,level); } + virtual bool isSubClass(ClassDef *bcd,int level=0) const + { return getCdAlias()->isSubClass(bcd,level); } + virtual bool isAccessibleMember(const MemberDef *md) const + { return getCdAlias()->isAccessibleMember(md); } + virtual QDict<ClassDef> *getTemplateInstances() const + { return getCdAlias()->getTemplateInstances(); } + virtual const ClassDef *templateMaster() const + { return getCdAlias()->templateMaster(); } + virtual bool isTemplate() const + { return getCdAlias()->isTemplate(); } + virtual IncludeInfo *includeInfo() const + { return getCdAlias()->includeInfo(); } + virtual UsesClassDict *usedImplementationClasses() const + { return getCdAlias()->usedImplementationClasses(); } + virtual UsesClassDict *usedByImplementationClasses() const + { return getCdAlias()->usedByImplementationClasses(); } + virtual UsesClassDict *usedInterfaceClasses() const + { return getCdAlias()->usedInterfaceClasses(); } + virtual ConstraintClassDict *templateTypeConstraints() const + { return getCdAlias()->templateTypeConstraints(); } + virtual bool isTemplateArgument() const + { return getCdAlias()->isTemplateArgument(); } + virtual Definition *findInnerCompound(const char *name) const + { return getCdAlias()->findInnerCompound(name); } + virtual void getTemplateParameterLists(QList<ArgumentList> &lists) const + { return getCdAlias()->getTemplateParameterLists(lists); } + virtual QCString qualifiedNameWithTemplateParameters( + QList<ArgumentList> *actualParams=0,int *actualParamIndex=0) const + { return getCdAlias()->qualifiedNameWithTemplateParameters(actualParams,actualParamIndex); } + virtual bool isAbstract() const + { return getCdAlias()->isAbstract(); } + virtual bool isObjectiveC() const + { return getCdAlias()->isObjectiveC(); } + virtual bool isFortran() const + { return getCdAlias()->isFortran(); } + virtual bool isCSharp() const + { return getCdAlias()->isCSharp(); } + virtual bool isFinal() const + { return getCdAlias()->isFinal(); } + virtual bool isSealed() const + { return getCdAlias()->isSealed(); } + virtual bool isPublished() const + { return getCdAlias()->isPublished(); } + virtual bool isExtension() const + { return getCdAlias()->isExtension(); } + virtual bool isForwardDeclared() const + { return getCdAlias()->isForwardDeclared(); } + virtual bool isInterface() const + { return getCdAlias()->isInterface(); } + virtual ClassDef *categoryOf() const + { return getCdAlias()->categoryOf(); } + virtual QCString className() const + { return getCdAlias()->className(); } + virtual MemberList *getMemberList(MemberListType lt) const + { return getCdAlias()->getMemberList(lt); } + virtual const QList<MemberList> &getMemberLists() const + { return getCdAlias()->getMemberLists(); } + virtual MemberGroupSDict *getMemberGroupSDict() const + { return getCdAlias()->getMemberGroupSDict(); } + virtual QDict<int> *getTemplateBaseClassNames() const + { return getCdAlias()->getTemplateBaseClassNames(); } + virtual ClassDef *getVariableInstance(const char *templSpec) const + { return getCdAlias()->getVariableInstance(templSpec); } + virtual bool isUsedOnly() const + { return getCdAlias()->isUsedOnly(); } + virtual QCString anchor() const + { return getCdAlias()->anchor(); } + virtual bool isEmbeddedInOuterScope() const + { return getCdAlias()->isEmbeddedInOuterScope(); } + virtual bool isSimple() const + { return getCdAlias()->isSimple(); } + virtual const ClassList *taggedInnerClasses() const + { return getCdAlias()->taggedInnerClasses(); } + virtual ClassDef *tagLessReference() const + { return getCdAlias()->tagLessReference(); } + virtual MemberDef *isSmartPointer() const + { return getCdAlias()->isSmartPointer(); } + virtual bool isJavaEnum() const + { return getCdAlias()->isJavaEnum(); } + virtual bool isGeneric() const + { return getCdAlias()->isGeneric(); } + virtual bool isAnonymous() const + { return getCdAlias()->isAnonymous(); } + virtual const ClassSDict *innerClasses() const + { return getCdAlias()->innerClasses(); } + virtual QCString title() const + { return getCdAlias()->title(); } + virtual QCString generatedFromFiles() const + { return getCdAlias()->generatedFromFiles(); } + virtual const FileList &usedFiles() const + { return getCdAlias()->usedFiles(); } + virtual const ArgumentList *typeConstraints() const + { return getCdAlias()->typeConstraints(); } + virtual const ExampleSDict *exampleList() const + { return getCdAlias()->exampleList(); } + virtual bool hasExamples() const + { return getCdAlias()->hasExamples(); } + virtual QCString getMemberListFileName() const + { return getCdAlias()->getMemberListFileName(); } + virtual bool subGrouping() const + { return getCdAlias()->subGrouping(); } + virtual bool isSliceLocal() const + { return getCdAlias()->isSliceLocal(); } + virtual bool hasNonReferenceSuperClass() const + { return getCdAlias()->hasNonReferenceSuperClass(); } + virtual ClassDef *insertTemplateInstance(const QCString &fileName,int startLine,int startColumn, + const QCString &templSpec,bool &freshInstance) const + { return getCdAlias()->insertTemplateInstance(fileName,startLine,startColumn,templSpec,freshInstance); } + + virtual void insertBaseClass(ClassDef *,const char *name,Protection p,Specifier s,const char *t=0) { } + virtual void insertSubClass(ClassDef *,Protection p,Specifier s,const char *t=0) { } + virtual void setIncludeFile(FileDef *fd,const char *incName,bool local,bool force) {} + virtual void insertMember(MemberDef *) {} + virtual void insertUsedFile(FileDef *) {} + virtual bool addExample(const char *anchor,const char *name, const char *file) { return FALSE; } + virtual void mergeCategory(ClassDef *category) {} + virtual void setNamespace(NamespaceDef *nd) {} + virtual void setFileDef(FileDef *fd) {} + virtual void setSubGrouping(bool enabled) {} + virtual void setProtection(Protection p) {} + virtual void setGroupDefForAllMembers(GroupDef *g,Grouping::GroupPri_t pri,const QCString &fileName,int startLine,bool hasDocs) {} + virtual void addInnerCompound(const Definition *d) {} + virtual void addUsedClass(ClassDef *cd,const char *accessName,Protection prot) {} + virtual void addUsedByClass(ClassDef *cd,const char *accessName,Protection prot) {} + virtual void setIsStatic(bool b) {} + virtual void setCompoundType(CompoundType t) {} + virtual void setClassName(const char *name) {} + virtual void setClassSpecifier(uint64 spec) {} + virtual void setTemplateArguments(ArgumentList *al) {} + virtual void setTemplateBaseClassNames(QDict<int> *templateNames) {} + virtual void setTemplateMaster(const ClassDef *tm) {} + virtual void setTypeConstraints(ArgumentList *al) {} + virtual void addMembersToTemplateInstance(const ClassDef *cd,const char *templSpec) {} + virtual void makeTemplateArgument(bool b=TRUE) {} + virtual void setCategoryOf(ClassDef *cd) {} + virtual void setUsedOnly(bool b) {} + virtual void addTaggedInnerClass(ClassDef *cd) {} + virtual void setTagLessReference(ClassDef *cd) {} + virtual void setName(const char *name) {} + virtual void setMetaData(const char *md) {} + virtual void findSectionsInDocumentation() {} + virtual void addMembersToMemberGroup() {} + virtual void addListReferences() {} + virtual void addTypeConstraints() {} + virtual void computeAnchors() {} + virtual void mergeMembers() {} + virtual void sortMemberLists() {} + virtual void distributeMemberGroupDocumentation() {} + virtual void writeDocumentation(OutputList &ol) const {} + virtual void writeDocumentationForInnerClasses(OutputList &ol) const {} + virtual void writeMemberPages(OutputList &ol) const {} + virtual void writeMemberList(OutputList &ol) const {} + virtual void writeDeclaration(OutputList &ol,const MemberDef *md,bool inGroup, + const ClassDef *inheritedFrom,const char *inheritId) const {} + virtual void writeQuickMemberLinks(OutputList &ol,const MemberDef *md) const {} + virtual void writeSummaryLinks(OutputList &ol) const {} + virtual void reclassifyMember(MemberDef *md,MemberType t) {} + virtual void writeInlineDocumentation(OutputList &ol) const {} + virtual void writeDeclarationLink(OutputList &ol,bool &found, + const char *header,bool localNames) const + { getCdAlias()->writeDeclarationLink(ol,found,header,localNames); } + virtual void removeMemberFromLists(MemberDef *md) {} + virtual void setAnonymousEnumType() {} + virtual void countMembers() {} + virtual void addGroupedInheritedMembers(OutputList &ol,MemberListType lt, + const ClassDef *inheritedFrom,const QCString &inheritId) const {} + virtual void writeTagFile(FTextStream &) {} + + virtual void setVisited(bool visited) const { m_visited = visited; } + virtual bool isVisited() const { return m_visited; } + virtual int countMembersIncludingGrouped(MemberListType lt,const ClassDef *inheritedFrom,bool additional) const + { return getCdAlias()->countMembersIncludingGrouped(lt,inheritedFrom,additional); } + virtual int countInheritanceNodes() const + { return getCdAlias()->countInheritanceNodes(); } + virtual int countMemberDeclarations(MemberListType lt,const ClassDef *inheritedFrom, + int lt2,bool invert,bool showAlways,QPtrDict<void> *visitedClasses) const + { return getCdAlias()->countMemberDeclarations(lt,inheritedFrom,lt2,invert,showAlways,visitedClasses); } + virtual void writeMemberDeclarations(OutputList &ol,MemberListType lt,const QCString &title, + const char *subTitle=0,bool showInline=FALSE,const ClassDef *inheritedFrom=0, + int lt2=-1,bool invert=FALSE,bool showAlways=FALSE, + QPtrDict<void> *visitedClasses=0) const {} + + private: + mutable bool m_visited; +}; + + +ClassDef *createClassDefAlias(const Definition *newScope,const ClassDef *cd) +{ + return new ClassDefAliasImpl(newScope,cd); +} + +//----------------------------------------------------------------------------- /** Private data associated with a ClassDef object. */ class ClassDefImpl::IMPL @@ -353,18 +621,18 @@ class ClassDefImpl::IMPL /*! Template instances that exists of this class, the key in the * dictionary is the template argument list. */ - QDict<ClassDef> *templateInstances; + mutable QDict<ClassDef> *templateInstances; /*! Template instances that exists of this class, as defined by variables. * We do NOT want to document these individually. The key in the * dictionary is the template argument list. */ - QDict<ClassDef> *variableInstances; + mutable QDict<ClassDef> *variableInstances; QDict<int> *templBaseClassNames; /*! The class this class is an instance of. */ - ClassDef *templateMaster; + const ClassDef *templateMaster; /*! local class name which could be a typedef'ed alias name. */ QCString className; @@ -1107,7 +1375,7 @@ void ClassDefImpl::setIncludeFile(FileDef *fd, // return 0; //} -static void searchTemplateSpecs(/*in*/ Definition *d, +static void searchTemplateSpecs(/*in*/ const Definition *d, /*out*/ QList<ArgumentList> &result, /*out*/ QCString &name, /*in*/ SrcLangExt lang) @@ -1118,7 +1386,7 @@ static void searchTemplateSpecs(/*in*/ Definition *d, { searchTemplateSpecs(d->getOuterScope(),result,name,lang); } - ClassDef *cd=dynamic_cast<ClassDef *>(d); + const ClassDef *cd=dynamic_cast<const ClassDef *>(d); if (!name.isEmpty()) name+="::"; QCString clName = d->localName(); if (/*clName.right(2)=="-g" ||*/ clName.right(2)=="-p") @@ -1142,7 +1410,7 @@ static void searchTemplateSpecs(/*in*/ Definition *d, } } -static void writeTemplateSpec(OutputList &ol,Definition *d, +static void writeTemplateSpec(OutputList &ol,const Definition *d, const QCString &type,SrcLangExt lang) { QList<ArgumentList> specs; @@ -1184,7 +1452,7 @@ static void writeTemplateSpec(OutputList &ol,Definition *d, } } -void ClassDefImpl::writeBriefDescription(OutputList &ol,bool exampleFlag) +void ClassDefImpl::writeBriefDescription(OutputList &ol,bool exampleFlag) const { if (hasBriefDescription()) { @@ -1211,7 +1479,7 @@ void ClassDefImpl::writeBriefDescription(OutputList &ol,bool exampleFlag) ol.writeSynopsis(); } -void ClassDefImpl::writeDetailedDocumentationBody(OutputList &ol) +void ClassDefImpl::writeDetailedDocumentationBody(OutputList &ol) const { static bool repeatBrief = Config_getBool(REPEAT_BRIEF); @@ -1270,7 +1538,7 @@ bool ClassDefImpl::hasDetailedDescription() const // write the detailed description for this class void ClassDefImpl::writeDetailedDescription(OutputList &ol, const QCString &/*pageType*/, bool exampleFlag, - const QCString &title,const QCString &anchor) + const QCString &title,const QCString &anchor) const { if (hasDetailedDescription() || exampleFlag) { @@ -1336,7 +1604,7 @@ QCString ClassDefImpl::generatedFromFiles() const return result; } -void ClassDefImpl::showUsedFiles(OutputList &ol) +void ClassDefImpl::showUsedFiles(OutputList &ol) const { ol.pushGeneratorState(); ol.disable(OutputGenerator::Man); @@ -1416,7 +1684,7 @@ void ClassDefImpl::showUsedFiles(OutputList &ol) ol.popGeneratorState(); } -int ClassDefImpl::countInheritanceNodes() +int ClassDefImpl::countInheritanceNodes() const { int count=0; BaseClassDef *ibcd; @@ -1441,7 +1709,7 @@ int ClassDefImpl::countInheritanceNodes() return count; } -void ClassDefImpl::writeInheritanceGraph(OutputList &ol) +void ClassDefImpl::writeInheritanceGraph(OutputList &ol) const { // count direct inheritance relations const int count=countInheritanceNodes(); @@ -1451,8 +1719,12 @@ void ClassDefImpl::writeInheritanceGraph(OutputList &ol) (Config_getBool(CLASS_DIAGRAMS) || Config_getBool(CLASS_GRAPH))) // write class diagram using dot { - DotClassGraph inheritanceGraph(this,DotNode::Inheritance); - if (!inheritanceGraph.isTrivial() && !inheritanceGraph.isTooBig()) + DotClassGraph inheritanceGraph(this,Inheritance); + if (inheritanceGraph.isTooBig()) + { + warn_uncond("Inheritance graph for '%s' not generated, too many nodes. Consider increasing DOT_GRAPH_MAX_NODES.\n",name().data()); + } + else if (!inheritanceGraph.isTrivial()) { ol.pushGeneratorState(); ol.disable(OutputGenerator::Man); @@ -1566,11 +1838,11 @@ void ClassDefImpl::writeInheritanceGraph(OutputList &ol) } } -void ClassDefImpl::writeCollaborationGraph(OutputList &ol) +void ClassDefImpl::writeCollaborationGraph(OutputList &ol) const { if (Config_getBool(HAVE_DOT) /*&& Config_getBool(COLLABORATION_GRAPH)*/) { - DotClassGraph usageImplGraph(this,DotNode::Collaboration); + DotClassGraph usageImplGraph(this,Collaboration); if (!usageImplGraph.isTrivial()) { ol.pushGeneratorState(); @@ -1601,7 +1873,7 @@ QCString ClassDefImpl::includeStatement() const } } -void ClassDefImpl::writeIncludeFilesForSlice(OutputList &ol) +void ClassDefImpl::writeIncludeFilesForSlice(OutputList &ol) const { if (m_impl->incInfo) { @@ -1755,7 +2027,7 @@ void ClassDefImpl::writeIncludeFilesForSlice(OutputList &ol) ol.endParagraph(); } -void ClassDefImpl::writeIncludeFiles(OutputList &ol) +void ClassDefImpl::writeIncludeFiles(OutputList &ol) const { if (m_impl->incInfo /*&& Config_getBool(SHOW_INCLUDE_FILES)*/) { @@ -1822,7 +2094,7 @@ void ClassDefImpl::writeAllMembersLink(OutputList &ol) } #endif -void ClassDefImpl::writeMemberGroups(OutputList &ol,bool showInline) +void ClassDefImpl::writeMemberGroups(OutputList &ol,bool showInline) const { // write user defined member groups if (m_impl->memberGroupSDict) @@ -1845,7 +2117,7 @@ void ClassDefImpl::writeMemberGroups(OutputList &ol,bool showInline) } } -void ClassDefImpl::writeNestedClasses(OutputList &ol,const QCString &title) +void ClassDefImpl::writeNestedClasses(OutputList &ol,const QCString &title) const { // nested classes if (m_impl->innerClasses) @@ -1854,7 +2126,7 @@ void ClassDefImpl::writeNestedClasses(OutputList &ol,const QCString &title) } } -void ClassDefImpl::writeInlineClasses(OutputList &ol) +void ClassDefImpl::writeInlineClasses(OutputList &ol) const { if (m_impl->innerClasses) { @@ -1862,7 +2134,7 @@ void ClassDefImpl::writeInlineClasses(OutputList &ol) } } -void ClassDefImpl::startMemberDocumentation(OutputList &ol) +void ClassDefImpl::startMemberDocumentation(OutputList &ol) const { //printf("%s: ClassDefImpl::startMemberDocumentation()\n",name().data()); if (Config_getBool(SEPARATE_MEMBER_PAGES)) @@ -1872,7 +2144,7 @@ void ClassDefImpl::startMemberDocumentation(OutputList &ol) } } -void ClassDefImpl::endMemberDocumentation(OutputList &ol) +void ClassDefImpl::endMemberDocumentation(OutputList &ol) const { //printf("%s: ClassDefImpl::endMemberDocumentation()\n",name().data()); if (Config_getBool(SEPARATE_MEMBER_PAGES)) @@ -1882,13 +2154,13 @@ void ClassDefImpl::endMemberDocumentation(OutputList &ol) } } -void ClassDefImpl::startMemberDeclarations(OutputList &ol) +void ClassDefImpl::startMemberDeclarations(OutputList &ol) const { //printf("%s: ClassDefImpl::startMemberDeclarations()\n",name().data()); ol.startMemberSections(); } -void ClassDefImpl::endMemberDeclarations(OutputList &ol) +void ClassDefImpl::endMemberDeclarations(OutputList &ol) const { //printf("%s: ClassDefImpl::endMemberDeclarations()\n",name().data()); static bool inlineInheritedMembers = Config_getBool(INLINE_INHERITED_MEMB); @@ -1902,7 +2174,7 @@ void ClassDefImpl::endMemberDeclarations(OutputList &ol) ol.endMemberSections(); } -void ClassDefImpl::writeAuthorSection(OutputList &ol) +void ClassDefImpl::writeAuthorSection(OutputList &ol) const { ol.pushGeneratorState(); ol.disableAllBut(OutputGenerator::Man); @@ -1915,7 +2187,7 @@ void ClassDefImpl::writeAuthorSection(OutputList &ol) } -void ClassDefImpl::writeSummaryLinks(OutputList &ol) +void ClassDefImpl::writeSummaryLinks(OutputList &ol) const { ol.pushGeneratorState(); ol.disableAllBut(OutputGenerator::Html); @@ -2093,7 +2365,7 @@ void ClassDefImpl::writeTagFile(FTextStream &tagFile) } /** Write class documentation inside another container (i.e. a group) */ -void ClassDefImpl::writeInlineDocumentation(OutputList &ol) +void ClassDefImpl::writeInlineDocumentation(OutputList &ol) const { bool isSimple = m_impl->isSimple; @@ -2210,7 +2482,7 @@ void ClassDefImpl::writeInlineDocumentation(OutputList &ol) ol.popGeneratorState(); } -void ClassDefImpl::writeMoreLink(OutputList &ol,const QCString &anchor) +void ClassDefImpl::writeMoreLink(OutputList &ol,const QCString &anchor) const { // TODO: clean up this mess by moving it to // the output generators... @@ -2266,7 +2538,7 @@ bool ClassDefImpl::visibleInParentsDeclList() const ); } -void ClassDefImpl::writeDeclarationLink(OutputList &ol,bool &found,const char *header,bool localNames) +void ClassDefImpl::writeDeclarationLink(OutputList &ol,bool &found,const char *header,bool localNames) const { //static bool fortranOpt = Config_getBool(OPTIMIZE_FOR_FORTRAN); //static bool vhdlOpt = Config_getBool(OPTIMIZE_OUTPUT_VHDL); @@ -2375,7 +2647,7 @@ void ClassDefImpl::writeDeclarationLink(OutputList &ol,bool &found,const char *h } } -void ClassDefImpl::addClassAttributes(OutputList &ol) +void ClassDefImpl::addClassAttributes(OutputList &ol) const { QStrList sl; if (isFinal()) sl.append("final"); @@ -2400,7 +2672,7 @@ void ClassDefImpl::addClassAttributes(OutputList &ol) ol.popGeneratorState(); } -void ClassDefImpl::writeDocumentationContents(OutputList &ol,const QCString & /*pageTitle*/) +void ClassDefImpl::writeDocumentationContents(OutputList &ol,const QCString & /*pageTitle*/) const { ol.startContents(); @@ -2585,7 +2857,7 @@ QCString ClassDefImpl::title() const } // write all documentation for this class -void ClassDefImpl::writeDocumentation(OutputList &ol) +void ClassDefImpl::writeDocumentation(OutputList &ol) const { static bool generateTreeView = Config_getBool(GENERATE_TREEVIEW); //static bool fortranOpt = Config_getBool(OPTIMIZE_FOR_FORTRAN); @@ -2643,7 +2915,7 @@ void ClassDefImpl::writeDocumentation(OutputList &ol) } } -void ClassDefImpl::writeMemberPages(OutputList &ol) +void ClassDefImpl::writeMemberPages(OutputList &ol) const { /////////////////////////////////////////////////////////////////////////// //// Member definitions on separate pages @@ -2656,8 +2928,7 @@ void ClassDefImpl::writeMemberPages(OutputList &ol) MemberList *ml; for (mli.toFirst();(ml=mli.current());++mli) { - ml->countDocMembers(); - if (ml->numDocMembers()>0 && (ml->listType()&MemberListType_detailedLists)) + if (ml->numDocMembers()>ml->numDocEnumValues() && (ml->listType()&MemberListType_detailedLists)) { ml->writeDocumentationPage(ol,displayName(),this); } @@ -2666,7 +2937,7 @@ void ClassDefImpl::writeMemberPages(OutputList &ol) ol.popGeneratorState(); } -void ClassDefImpl::writeQuickMemberLinks(OutputList &ol,MemberDef *currentMd) const +void ClassDefImpl::writeQuickMemberLinks(OutputList &ol,const MemberDef *currentMd) const { static bool createSubDirs=Config_getBool(CREATE_SUBDIRS); @@ -2716,7 +2987,7 @@ void ClassDefImpl::writeQuickMemberLinks(OutputList &ol,MemberDef *currentMd) co -void ClassDefImpl::writeDocumentationForInnerClasses(OutputList &ol) +void ClassDefImpl::writeDocumentationForInnerClasses(OutputList &ol) const { // write inner classes after the parent, so the tag files contain // the definition in proper order! @@ -2741,7 +3012,7 @@ void ClassDefImpl::writeDocumentationForInnerClasses(OutputList &ol) } // write the list of all (inherited) members for this class -void ClassDefImpl::writeMemberList(OutputList &ol) +void ClassDefImpl::writeMemberList(OutputList &ol) const { static bool cOpt = Config_getBool(OPTIMIZE_OUTPUT_FOR_C); //static bool vhdlOpt = Config_getBool(OPTIMIZE_OUTPUT_VHDL); @@ -2811,7 +3082,7 @@ void ClassDefImpl::writeMemberList(OutputList &ol) for (;(mi=it.current());++it) { MemberDef *md=mi->memberDef; - ClassDef *cd=md->getClassDef(); + const ClassDef *cd=md->getClassDef(); Protection prot = mi->prot; Specifier virt=md->virtualness(); @@ -3024,7 +3295,6 @@ void ClassDefImpl::writeMemberList(OutputList &ol) ol.popGeneratorState(); } - // add a reference to an example bool ClassDefImpl::addExample(const char *anchor,const char *nameStr, const char *file) @@ -3060,7 +3330,7 @@ void ClassDefImpl::addTypeConstraint(const QCString &typeConstraint,const QCStri //printf("addTypeContraint(%s,%s)\n",type.data(),typeConstraint.data()); static bool hideUndocRelation = Config_getBool(HIDE_UNDOC_RELATIONS); if (typeConstraint.isEmpty() || type.isEmpty()) return; - ClassDef *cd = getResolvedClass(this,getFileDef(),typeConstraint); + ClassDef *cd = const_cast<ClassDef*>(getResolvedClass(this,getFileDef(),typeConstraint)); if (cd==0 && !hideUndocRelation) { cd = new ClassDefImpl(getDefFileName(),getDefLine(),getDefColumn(),typeConstraint,ClassDef::Class); @@ -3183,8 +3453,8 @@ bool ClassDefImpl::hasNonReferenceSuperClass() const /*! called from MemberDef::writeDeclaration() to (recursively) write the * definition of an anonymous struct, union or class. */ -void ClassDefImpl::writeDeclaration(OutputList &ol,MemberDef *md,bool inGroup, - ClassDef *inheritedFrom,const char *inheritId) +void ClassDefImpl::writeDeclaration(OutputList &ol,const MemberDef *md,bool inGroup, + const ClassDef *inheritedFrom,const char *inheritId) const { //printf("ClassName=`%s' inGroup=%d\n",name().data(),inGroup); @@ -3319,7 +3589,7 @@ bool ClassDefImpl::isBaseClass(const ClassDef *bcd, bool followInstances,int lev BaseClassListIterator bcli(*baseClasses()); for ( ; bcli.current() && !found ; ++bcli) { - ClassDef *ccd=bcli.current()->classDef; + const ClassDef *ccd=bcli.current()->classDef; if (!followInstances && ccd->templateMaster()) ccd=ccd->templateMaster(); //printf("isBaseClass() baseclass %s\n",ccd->name().data()); if (ccd==bcd) @@ -3382,7 +3652,8 @@ void ClassDefImpl::mergeMembers() m_impl->membersMerged=TRUE; //printf(" mergeMembers for %s\n",name().data()); - bool inlineInheritedMembers = Config_getBool(INLINE_INHERITED_MEMB); + static bool inlineInheritedMembers = Config_getBool(INLINE_INHERITED_MEMB); + static bool extractPrivate = Config_getBool(EXTRACT_PRIVATE); if (baseClasses()) { //printf(" => has base classes!\n"); @@ -3422,19 +3693,19 @@ void ClassDefImpl::mergeMembers() bool hidden=FALSE; MemberNameInfoIterator dstMnii(*dstMni); MemberInfo *dstMi; - ClassDef *srcCd = srcMd->getClassDef(); + const ClassDef *srcCd = srcMd->getClassDef(); for ( ; (dstMi=dstMnii.current()) && !found; ++dstMnii ) { MemberDef *dstMd = dstMi->memberDef; if (srcMd!=dstMd) // different members { - ClassDef *dstCd = dstMd->getClassDef(); + const ClassDef *dstCd = dstMd->getClassDef(); //printf(" Is %s a base class of %s?\n",srcCd->name().data(),dstCd->name().data()); if (srcCd==dstCd || dstCd->isBaseClass(srcCd,TRUE)) // member is in the same or a base class { - ArgumentList *srcAl = srcMd->argumentList(); - ArgumentList *dstAl = dstMd->argumentList(); + const ArgumentList *srcAl = srcMd->argumentList(); + const ArgumentList *dstAl = dstMd->argumentList(); found=matchArguments2( srcMd->getOuterScope(),srcMd->getFileDef(),srcAl, dstMd->getOuterScope(),dstMd->getFileDef(),dstAl, @@ -3578,7 +3849,7 @@ void ClassDefImpl::mergeMembers() // name().data(),mi->memberDef->name().data(),mi->prot, // bcd->prot,prot); - if (mi->prot!=Private) + if (prot!=Private || extractPrivate) { Specifier virt=mi->virt; if (mi->virt==Normal && bcd->virt!=Normal) virt=bcd->virt; @@ -4135,7 +4406,7 @@ void ClassDefImpl::setGroupDefForAllMembers(GroupDef *gd,Grouping::GroupPri_t pr } } -void ClassDefImpl::addInnerCompound(Definition *d) +void ClassDefImpl::addInnerCompound(const Definition *d) { //printf("**** %s::addInnerCompound(%s)\n",name().data(),d->name().data()); if (d->definitionType()==Definition::TypeClass) // only classes can be @@ -4145,7 +4416,7 @@ void ClassDefImpl::addInnerCompound(Definition *d) { m_impl->innerClasses = new ClassSDict(17); } - m_impl->innerClasses->inSort(d->localName(),dynamic_cast<ClassDef *>(d)); + m_impl->innerClasses->inSort(d->localName(),dynamic_cast<const ClassDef *>(d)); } } @@ -4201,7 +4472,7 @@ Definition *ClassDefImpl::findInnerCompound(const char *name) const //} ClassDef *ClassDefImpl::insertTemplateInstance(const QCString &fileName, - int startLine, int startColumn, const QCString &templSpec,bool &freshInstance) + int startLine, int startColumn, const QCString &templSpec,bool &freshInstance) const { freshInstance = FALSE; if (m_impl->templateInstances==0) @@ -4224,7 +4495,7 @@ ClassDef *ClassDefImpl::insertTemplateInstance(const QCString &fileName, return templateClass; } -ClassDef *ClassDefImpl::getVariableInstance(const char *templSpec) +ClassDef *ClassDefImpl::getVariableInstance(const char *templSpec) const { if (m_impl->variableInstances==0) { @@ -4269,7 +4540,7 @@ QDict<int> *ClassDefImpl::getTemplateBaseClassNames() const return m_impl->templBaseClassNames; } -void ClassDefImpl::addMembersToTemplateInstance(ClassDef *cd,const char *templSpec) +void ClassDefImpl::addMembersToTemplateInstance(const ClassDef *cd,const char *templSpec) { //printf("%s::addMembersToTemplateInstance(%s,%s)\n",name().data(),cd->name().data(),templSpec); if (cd->memberNameInfoSDict()==0) return; @@ -4480,7 +4751,7 @@ MemberDef *ClassDefImpl::getMemberByName(const QCString &name) const MemberInfo *mi; for (mnii.toFirst();(mi=mnii.current());++mnii) { - ClassDef *mcd=mi->memberDef->getClassDef(); + const ClassDef *mcd=mi->memberDef->getClassDef(); int m=minClassDistance(this,mcd); //printf("found member in %s linkable=%d m=%d\n", // mcd->name().data(),mcd->isLinkable(),m); @@ -4559,8 +4830,8 @@ void ClassDefImpl::sortMemberLists() } } -int ClassDefImpl::countMemberDeclarations(MemberListType lt,ClassDef *inheritedFrom, - int lt2,bool invert,bool showAlways,QPtrDict<void> *visitedClasses) +int ClassDefImpl::countMemberDeclarations(MemberListType lt,const ClassDef *inheritedFrom, + int lt2,bool invert,bool showAlways,QPtrDict<void> *visitedClasses) const { //printf("%s: countMemberDeclarations for %d and %d\n",name().data(),lt,lt2); int count=0; @@ -4570,13 +4841,11 @@ int ClassDefImpl::countMemberDeclarations(MemberListType lt,ClassDef *inheritedF { if (ml) { - ml->countDecMembers(); count+=ml->numDecMembers(); //printf("-> ml=%d\n",ml->numDecMembers()); } if (ml2) { - ml2->countDecMembers(); count+=ml2->numDecMembers(); //printf("-> ml2=%d\n",ml2->numDecMembers()); } @@ -4601,10 +4870,61 @@ int ClassDefImpl::countMemberDeclarations(MemberListType lt,ClassDef *inheritedF return count; } +void ClassDefImpl::setAnonymousEnumType() +{ + QListIterator<LayoutDocEntry> eli( + LayoutDocManager::instance().docEntries(LayoutDocManager::Class)); + LayoutDocEntry *lde; + for (eli.toFirst();(lde=eli.current());++eli) + { + if (lde->kind()==LayoutDocEntry::MemberDecl) + { + LayoutDocEntryMemberDecl *lmd = (LayoutDocEntryMemberDecl*)lde; + MemberList * ml = getMemberList(lmd->type); + if (ml) + { + ml->setAnonymousEnumType(); + } + } + else if (lde->kind()==LayoutDocEntry::MemberGroups) + { + if (m_impl->memberGroupSDict) + { + MemberGroupSDict::Iterator mgli(*m_impl->memberGroupSDict); + MemberGroup *mg; + for (;(mg=mgli.current());++mgli) + { + mg->setAnonymousEnumType(); + } + } + } + } +} + +void ClassDefImpl::countMembers() +{ + QListIterator<MemberList> mli(m_impl->memberLists); + MemberList *ml; + for (mli.toFirst();(ml=mli.current());++mli) + { + ml->countDecMembers(); + ml->countDocMembers(); + } + if (m_impl->memberGroupSDict) + { + MemberGroupSDict::Iterator mgli(*m_impl->memberGroupSDict); + MemberGroup *mg; + for (;(mg=mgli.current());++mgli) + { + mg->countDecMembers(); + mg->countDocMembers(); + } + } +} int ClassDefImpl::countInheritedDecMembers(MemberListType lt, - ClassDef *inheritedFrom,bool invert,bool showAlways, - QPtrDict<void> *visitedClasses) + const ClassDef *inheritedFrom,bool invert,bool showAlways, + QPtrDict<void> *visitedClasses) const { int inhCount = 0; int count = countMembersIncludingGrouped(lt,inheritedFrom,FALSE); @@ -4642,7 +4962,7 @@ int ClassDefImpl::countInheritedDecMembers(MemberListType lt, } void ClassDefImpl::getTitleForMemberListType(MemberListType type, - QCString &title,QCString &subtitle) + QCString &title,QCString &subtitle) const { SrcLangExt lang = getLanguage(); QListIterator<LayoutDocEntry> eli( @@ -4665,7 +4985,7 @@ void ClassDefImpl::getTitleForMemberListType(MemberListType type, subtitle=""; } -int ClassDefImpl::countAdditionalInheritedMembers() +int ClassDefImpl::countAdditionalInheritedMembers() const { int totalCount=0; QListIterator<LayoutDocEntry> eli( @@ -4691,7 +5011,7 @@ int ClassDefImpl::countAdditionalInheritedMembers() return totalCount; } -void ClassDefImpl::writeAdditionalInheritedMembers(OutputList &ol) +void ClassDefImpl::writeAdditionalInheritedMembers(OutputList &ol) const { //printf("**** writeAdditionalInheritedMembers()\n"); QListIterator<LayoutDocEntry> eli( @@ -4712,7 +5032,7 @@ void ClassDefImpl::writeAdditionalInheritedMembers(OutputList &ol) } int ClassDefImpl::countMembersIncludingGrouped(MemberListType lt, - ClassDef *inheritedFrom,bool additional) + const ClassDef *inheritedFrom,bool additional) const { int count=0; MemberList *ml = getMemberList(lt); @@ -4740,10 +5060,11 @@ int ClassDefImpl::countMembersIncludingGrouped(MemberListType lt, return count; } + void ClassDefImpl::writeInheritedMemberDeclarations(OutputList &ol, MemberListType lt,int lt2,const QCString &title, - ClassDef *inheritedFrom,bool invert,bool showAlways, - QPtrDict<void> *visitedClasses) + const ClassDef *inheritedFrom,bool invert,bool showAlways, + QPtrDict<void> *visitedClasses) const { ol.pushGeneratorState(); ol.disableAllBut(OutputGenerator::Html); @@ -4790,15 +5111,15 @@ void ClassDefImpl::writeInheritedMemberDeclarations(OutputList &ol, } void ClassDefImpl::writeMemberDeclarations(OutputList &ol,MemberListType lt,const QCString &title, - const char *subTitle,bool showInline,ClassDef *inheritedFrom,int lt2, - bool invert,bool showAlways,QPtrDict<void> *visitedClasses) + const char *subTitle,bool showInline,const ClassDef *inheritedFrom,int lt2, + bool invert,bool showAlways,QPtrDict<void> *visitedClasses) const { //printf("%s: ClassDefImpl::writeMemberDeclarations lt=%d lt2=%d\n",name().data(),lt,lt2); MemberList * ml = getMemberList(lt); MemberList * ml2 = getMemberList((MemberListType)lt2); if (getLanguage()==SrcLangExt_VHDL) // use specific declarations function { - static ClassDef *cdef; + static const ClassDef *cdef; if (cdef!=this) { // only one inline link VhdlDocGen::writeInlineClassLink(this,ol); @@ -4838,7 +5159,7 @@ void ClassDefImpl::writeMemberDeclarations(OutputList &ol,MemberListType lt,cons } void ClassDefImpl::addGroupedInheritedMembers(OutputList &ol,MemberListType lt, - ClassDef *inheritedFrom,const QCString &inheritId) + const ClassDef *inheritedFrom,const QCString &inheritId) const { //printf("** %s::addGroupedInheritedMembers(%p) inheritId=%s\n",name().data(),m_impl->memberGroupSDict,inheritId.data()); if (m_impl->memberGroupSDict) @@ -4855,14 +5176,14 @@ void ClassDefImpl::addGroupedInheritedMembers(OutputList &ol,MemberListType lt, } } -void ClassDefImpl::writeMemberDocumentation(OutputList &ol,MemberListType lt,const QCString &title,bool showInline) +void ClassDefImpl::writeMemberDocumentation(OutputList &ol,MemberListType lt,const QCString &title,bool showInline) const { //printf("%s: ClassDefImpl::writeMemberDocumentation()\n",name().data()); MemberList * ml = getMemberList(lt); if (ml) ml->writeDocumentation(ol,displayName(),this,title,FALSE,showInline); } -void ClassDefImpl::writeSimpleMemberDocumentation(OutputList &ol,MemberListType lt) +void ClassDefImpl::writeSimpleMemberDocumentation(OutputList &ol,MemberListType lt) const { //printf("%s: ClassDefImpl::writeSimpleMemberDocumentation()\n",name().data()); MemberList * ml = getMemberList(lt); @@ -4871,7 +5192,7 @@ void ClassDefImpl::writeSimpleMemberDocumentation(OutputList &ol,MemberListType void ClassDefImpl::writePlainMemberDeclaration(OutputList &ol, MemberListType lt,bool inGroup, - ClassDef *inheritedFrom,const char *inheritId) + const ClassDef *inheritedFrom,const char *inheritId) const { //printf("%s: ClassDefImpl::writePlainMemberDeclaration()\n",name().data()); MemberList * ml = getMemberList(lt); @@ -4937,7 +5258,7 @@ QDict<ClassDef> *ClassDefImpl::getTemplateInstances() const return m_impl->templateInstances; } -ClassDef *ClassDefImpl::templateMaster() const +const ClassDef *ClassDefImpl::templateMaster() const { return m_impl->templateMaster; } @@ -5067,7 +5388,7 @@ void ClassDefImpl::setCompoundType(CompoundType t) m_impl->compType = t; } -void ClassDefImpl::setTemplateMaster(ClassDef *tm) +void ClassDefImpl::setTemplateMaster(const ClassDef *tm) { m_impl->templateMaster=tm; } diff --git a/src/classdef.h b/src/classdef.h index 58a3dee..a442ace 100644 --- a/src/classdef.h +++ b/src/classdef.h @@ -72,6 +72,8 @@ class ClassDef : virtual public Definition virtual ~ClassDef() {} + virtual ClassDef *resolveAlias() = 0; + //----------------------------------------------------------------------------------- // --- getters //----------------------------------------------------------------------------------- @@ -197,7 +199,7 @@ class ClassDef : virtual public Definition /** Returns the template master of which this class is an instance. * Returns 0 if not applicable. */ - virtual ClassDef *templateMaster() const = 0; + virtual const ClassDef *templateMaster() const = 0; /** Returns TRUE if this class is a template */ virtual bool isTemplate() const = 0; @@ -283,7 +285,7 @@ class ClassDef : virtual public Definition virtual QDict<int> *getTemplateBaseClassNames() const = 0; - virtual ClassDef *getVariableInstance(const char *templSpec) = 0; + virtual ClassDef *getVariableInstance(const char *templSpec) const = 0; virtual bool isUsedOnly() const = 0; @@ -314,52 +316,50 @@ class ClassDef : virtual public Definition virtual bool subGrouping() const = 0; virtual bool isSliceLocal() const = 0; + virtual bool hasNonReferenceSuperClass() const = 0; //----------------------------------------------------------------------------------- // --- setters ---- //----------------------------------------------------------------------------------- - virtual void insertBaseClass(ClassDef *,const char *name,Protection p,Specifier s,const char *t=0) = 0; - virtual void insertSubClass(ClassDef *,Protection p,Specifier s,const char *t=0) = 0; virtual void setIncludeFile(FileDef *fd,const char *incName,bool local,bool force) = 0; - virtual void insertMember(MemberDef *) = 0; - virtual void insertUsedFile(FileDef *) = 0; - virtual bool addExample(const char *anchor,const char *name, const char *file) = 0; - virtual void mergeCategory(ClassDef *category) = 0; virtual void setNamespace(NamespaceDef *nd) = 0; virtual void setFileDef(FileDef *fd) = 0; virtual void setSubGrouping(bool enabled) = 0; virtual void setProtection(Protection p) = 0; virtual void setGroupDefForAllMembers(GroupDef *g,Grouping::GroupPri_t pri,const QCString &fileName,int startLine,bool hasDocs) = 0; - virtual void addInnerCompound(Definition *d) = 0; - virtual ClassDef *insertTemplateInstance(const QCString &fileName,int startLine,int startColumn, - const QCString &templSpec,bool &freshInstance) = 0; - virtual void addUsedClass(ClassDef *cd,const char *accessName,Protection prot) = 0; - virtual void addUsedByClass(ClassDef *cd,const char *accessName,Protection prot) = 0; virtual void setIsStatic(bool b) = 0; virtual void setCompoundType(CompoundType t) = 0; virtual void setClassName(const char *name) = 0; virtual void setClassSpecifier(uint64 spec) = 0; - virtual void setTemplateArguments(ArgumentList *al) = 0; virtual void setTemplateBaseClassNames(QDict<int> *templateNames) = 0; - virtual void setTemplateMaster(ClassDef *tm) = 0; + virtual void setTemplateMaster(const ClassDef *tm) = 0; virtual void setTypeConstraints(ArgumentList *al) = 0; - virtual void addMembersToTemplateInstance(ClassDef *cd,const char *templSpec) = 0; - virtual void makeTemplateArgument(bool b=TRUE) = 0; virtual void setCategoryOf(ClassDef *cd) = 0; virtual void setUsedOnly(bool b) = 0; - - virtual void addTaggedInnerClass(ClassDef *cd) = 0; virtual void setTagLessReference(ClassDef *cd) = 0; virtual void setName(const char *name) = 0; - virtual void setMetaData(const char *md) = 0; //----------------------------------------------------------------------------------- // --- actions ---- //----------------------------------------------------------------------------------- + virtual void insertBaseClass(ClassDef *,const char *name,Protection p,Specifier s,const char *t=0) = 0; + virtual void insertSubClass(ClassDef *,Protection p,Specifier s,const char *t=0) = 0; + virtual void insertMember(MemberDef *) = 0; + virtual void insertUsedFile(FileDef *) = 0; + virtual void addMembersToTemplateInstance(const ClassDef *cd,const char *templSpec) = 0; + virtual void addTaggedInnerClass(ClassDef *cd) = 0; + virtual void addInnerCompound(const Definition *d) = 0; + virtual bool addExample(const char *anchor,const char *name, const char *file) = 0; + virtual ClassDef *insertTemplateInstance(const QCString &fileName,int startLine,int startColumn, + const QCString &templSpec,bool &freshInstance) const = 0; + virtual void addUsedClass(ClassDef *cd,const char *accessName,Protection prot) = 0; + virtual void addUsedByClass(ClassDef *cd,const char *accessName,Protection prot) = 0; + virtual void makeTemplateArgument(bool b=TRUE) = 0; + virtual void mergeCategory(ClassDef *category) = 0; virtual void findSectionsInDocumentation() = 0; virtual void addMembersToMemberGroup() = 0; virtual void addListReferences() = 0; @@ -368,34 +368,51 @@ class ClassDef : virtual public Definition virtual void mergeMembers() = 0; virtual void sortMemberLists() = 0; virtual void distributeMemberGroupDocumentation() = 0; - virtual void writeDocumentation(OutputList &ol) = 0; - virtual void writeDocumentationForInnerClasses(OutputList &ol) = 0; - virtual void writeMemberPages(OutputList &ol) = 0; - virtual void writeMemberList(OutputList &ol) = 0; - virtual void writeDeclaration(OutputList &ol,MemberDef *md,bool inGroup, - ClassDef *inheritedFrom,const char *inheritId) = 0; - virtual void writeQuickMemberLinks(OutputList &ol,MemberDef *md) const = 0; - virtual void writeSummaryLinks(OutputList &ol) = 0; virtual void reclassifyMember(MemberDef *md,MemberType t) = 0; - virtual void writeInlineDocumentation(OutputList &ol) = 0; - virtual void writeDeclarationLink(OutputList &ol,bool &found, - const char *header,bool localNames) = 0; virtual void removeMemberFromLists(MemberDef *md) = 0; - virtual void addGroupedInheritedMembers(OutputList &ol,MemberListType lt, - ClassDef *inheritedFrom,const QCString &inheritId) = 0; - virtual int countMembersIncludingGrouped(MemberListType lt,ClassDef *inheritedFrom,bool additional) = 0; - virtual int countInheritanceNodes() = 0; - virtual void writeTagFile(FTextStream &) = 0; + virtual void setAnonymousEnumType() = 0; + virtual void countMembers() = 0; - virtual void setVisited(bool visited) = 0; - virtual bool isVisited() const = 0; - virtual bool hasNonReferenceSuperClass() const = 0; - virtual int countMemberDeclarations(MemberListType lt,ClassDef *inheritedFrom, - int lt2,bool invert,bool showAlways,QPtrDict<void> *visitedClasses) = 0; + //----------------------------------------------------------------------------------- + // --- write output ---- + //----------------------------------------------------------------------------------- + + virtual void writeDocumentation(OutputList &ol) const = 0; + virtual void writeDocumentationForInnerClasses(OutputList &ol) const = 0; + virtual void writeMemberPages(OutputList &ol) const = 0; + virtual void writeMemberList(OutputList &ol) const = 0; + virtual void writeDeclaration(OutputList &ol,const MemberDef *md,bool inGroup, + const ClassDef *inheritedFrom,const char *inheritId) const = 0; + virtual void writeQuickMemberLinks(OutputList &ol,const MemberDef *md) const = 0; + virtual void writeSummaryLinks(OutputList &ol) const = 0; + virtual void writeInlineDocumentation(OutputList &ol) const = 0; + virtual void writeDeclarationLink(OutputList &ol,bool &found, + const char *header,bool localNames) const = 0; + virtual void writeTagFile(FTextStream &) = 0; virtual void writeMemberDeclarations(OutputList &ol,MemberListType lt,const QCString &title, - const char *subTitle=0,bool showInline=FALSE,ClassDef *inheritedFrom=0, + const char *subTitle=0,bool showInline=FALSE,const ClassDef *inheritedFrom=0, int lt2=-1,bool invert=FALSE,bool showAlways=FALSE, - QPtrDict<void> *visitedClasses=0) = 0; + QPtrDict<void> *visitedClasses=0) const = 0; + virtual void addGroupedInheritedMembers(OutputList &ol,MemberListType lt, + const ClassDef *inheritedFrom,const QCString &inheritId) const = 0; + + //----------------------------------------------------------------------------------- + // --- count members ---- + //----------------------------------------------------------------------------------- + + virtual int countMembersIncludingGrouped(MemberListType lt, + const ClassDef *inheritedFrom,bool additional) const = 0; + virtual int countInheritanceNodes() const = 0; + virtual int countMemberDeclarations(MemberListType lt,const ClassDef *inheritedFrom, + int lt2,bool invert,bool showAlways,QPtrDict<void> *visitedClasses) const = 0; + + + //----------------------------------------------------------------------------------- + // --- visiting administration ---- + //----------------------------------------------------------------------------------- + + virtual void setVisited(bool visited) const = 0; + virtual bool isVisited() const = 0; }; /** Factory method to create a new ClassDef object */ @@ -405,6 +422,9 @@ ClassDef *createClassDef( const char *ref=0,const char *fName=0, bool isSymbol=TRUE,bool isJavaEnum=FALSE); +ClassDef *createClassDefAlias(const Definition *newScope,const ClassDef *cd); + + //------------------------------------------------------------------------ /** Class that contains information about a usage relation. diff --git a/src/classlist.cpp b/src/classlist.cpp index c752fd3..93ae8aa 100644 --- a/src/classlist.cpp +++ b/src/classlist.cpp @@ -92,7 +92,7 @@ bool ClassSDict::declVisible(const ClassDef::CompoundType *filter) const } void ClassSDict::writeDeclaration(OutputList &ol,const ClassDef::CompoundType *filter, - const char *header,bool localNames) + const char *header,bool localNames) const { static bool extractPrivate = Config_getBool(EXTRACT_PRIVATE); if (count()>0) @@ -109,6 +109,7 @@ void ClassSDict::writeDeclaration(OutputList &ol,const ClassDef::CompoundType *f (filter==0 || *filter==cd->compoundType()) ) { + //printf("writeDeclarationLink()\n"); cd->writeDeclarationLink(ol,found,header,localNames); } } @@ -116,7 +117,7 @@ void ClassSDict::writeDeclaration(OutputList &ol,const ClassDef::CompoundType *f } } -void ClassSDict::writeDocumentation(OutputList &ol,Definition * container) +void ClassSDict::writeDocumentation(OutputList &ol,const Definition * container) const { static bool fortranOpt = Config_getBool(OPTIMIZE_FOR_FORTRAN); @@ -139,6 +140,7 @@ void ClassSDict::writeDocumentation(OutputList &ol,Definition * container) if (cd->name().find('@')==-1 && cd->isLinkableInProject() && cd->isEmbeddedInOuterScope() && + !cd->isAlias() && (container==0 || cd->partOfGroups()==0) // if container==0 -> show as part of the group docs, otherwise only show if not part of a group ) { diff --git a/src/classlist.h b/src/classlist.h index 2ae7de8..11c8305 100644 --- a/src/classlist.h +++ b/src/classlist.h @@ -59,8 +59,8 @@ class ClassSDict : public SDict<ClassDef> ClassSDict(int size=17) : SDict<ClassDef>(size) {} ~ClassSDict() {} void writeDeclaration(OutputList &ol,const ClassDef::CompoundType *filter=0, - const char *header=0,bool localNames=FALSE); - void writeDocumentation(OutputList &ol,Definition *container=0); + const char *header=0,bool localNames=FALSE) const; + void writeDocumentation(OutputList &ol,const Definition *container=0) const; bool declVisible(const ClassDef::CompoundType *filter=0) const; private: int compareValues(const ClassDef *item1,const ClassDef *item2) const; @@ -29,7 +29,7 @@ class Definition; void parseCCode(CodeOutputInterface &,const char *,const QCString &, SrcLangExt lang, bool isExample, const char *exName,FileDef *fd, int startLine,int endLine,bool inlineFragment, - MemberDef *memberDef,bool showLineNumbers,Definition *searchCtx, + const MemberDef *memberDef,bool showLineNumbers,const Definition *searchCtx, bool collectXRefs); void resetCCodeParserState(); void codeFreeScanner(); @@ -129,7 +129,7 @@ static bool g_lexInit = FALSE; static QStack<int> g_classScopeLengthStack; static int g_prefixed_with_this_keyword = FALSE; -static Definition *g_searchCtx; +static const Definition *g_searchCtx; static bool g_collectXRefs; // context for an Objective-C method call @@ -139,9 +139,9 @@ struct ObjCCallCtx QCString methodName; QCString objectTypeOrName; QGString comment; - ClassDef *objectType; - MemberDef *objectVar; - MemberDef *method; + const ClassDef *objectType; + const MemberDef *objectVar; + const MemberDef *method; QCString format; int lexState; int braceCount; @@ -252,7 +252,7 @@ void VariableContext::addVariable(const QCString &type,const QCString &name) DBG_CTX((stderr,"** addVariable trying: type='%s' name='%s' g_currentDefinition=%s\n", ltype.data(),lname.data(),g_currentDefinition?g_currentDefinition->name().data():"<none>")); Scope *scope = m_scopes.count()==0 ? &m_globalScope : m_scopes.getLast(); - ClassDef *varType; + const ClassDef *varType; int i=0; if ( (varType=g_codeClassSDict->find(ltype)) || // look for class definitions inside the code block @@ -338,19 +338,19 @@ class CallContext public: struct Ctx { - Ctx() : name(g_name), type(g_type), d(0) {} + Ctx(QCString _name, QCString _type) : name(_name), type(_type), d(0) {} QCString name; QCString type; - Definition *d; + const Definition *d; }; - CallContext() + CallContext() { - m_defList.append(new Ctx); + m_defList.append(new Ctx("","")); m_defList.setAutoDelete(TRUE); } virtual ~CallContext() {} - void setScope(Definition *d) + void setScope(const Definition *d) { Ctx *ctx = m_defList.getLast(); if (ctx) @@ -359,12 +359,12 @@ class CallContext ctx->d=d; } } - void pushScope() + void pushScope(QCString _name, QCString _type) { - m_defList.append(new Ctx); + m_defList.append(new Ctx(_name,_type)); DBG_CTX((stderr,"** Push call context %d\n",m_defList.count())); } - void popScope() + void popScope(QCString &_name, QCString &_type) { if (m_defList.count()>1) { @@ -372,8 +372,8 @@ class CallContext Ctx *ctx = m_defList.getLast(); if (ctx) { - g_name = ctx->name; - g_type = ctx->type; + _name = ctx->name; + _type = ctx->type; } m_defList.removeLast(); } @@ -386,9 +386,9 @@ class CallContext { DBG_CTX((stderr,"** Clear call context\n")); m_defList.clear(); - m_defList.append(new Ctx); + m_defList.append(new Ctx("","")); } - Definition *getScope() const + const Definition *getScope() const { Ctx *ctx = m_defList.getLast(); if (ctx) return ctx->d; else return 0; @@ -606,7 +606,7 @@ static void codifyLines(const char *text) * split into multiple links with the same destination, one for each line. */ static void writeMultiLineCodeLink(CodeOutputInterface &ol, - Definition *d, + const Definition *d, const char *text) { static bool sourceTooltips = Config_getBool(SOURCE_TOOLTIPS); @@ -674,13 +674,13 @@ static void addUsingDirective(const char *name) } } -static void setParameterList(MemberDef *md) +static void setParameterList(const MemberDef *md) { g_classScope = md->getClassDef() ? md->getClassDef()->name().data() : ""; - ArgumentList *al = md->argumentList(); + const ArgumentList *al = md->argumentList(); if (al==0) return; ArgumentListIterator it(*al); - Argument *a; + const Argument *a; for (;(a=it.current());++it) { g_parmName = a->name.copy(); @@ -695,7 +695,7 @@ static void setParameterList(MemberDef *md) } } -static ClassDef *stripClassName(const char *s,Definition *d=g_currentDefinition) +static const ClassDef *stripClassName(const char *s,Definition *d=g_currentDefinition) { int pos=0; QCString type = s; @@ -704,7 +704,7 @@ static ClassDef *stripClassName(const char *s,Definition *d=g_currentDefinition) while (extractClassNameFromType(type,pos,className,templSpec)!=-1) { QCString clName=className+templSpec; - ClassDef *cd=0; + const ClassDef *cd=0; if (!g_classScope.isEmpty()) { cd=getResolvedClass(d,g_sourceFileDef,g_classScope+"::"+clName); @@ -747,7 +747,7 @@ static MemberDef *setCallContextForVar(const QCString &name) } else // check namespace as well { - NamespaceDef *mnd = getResolvedNamespace(scope); + const NamespaceDef *mnd = getResolvedNamespace(scope); if (mnd && !locName.isEmpty()) { MemberDef *md=mnd->getMemberByName(locName); @@ -838,12 +838,12 @@ static MemberDef *setCallContextForVar(const QCString &name) static void updateCallContextForSmartPointer() { - Definition *d = g_theCallContext.getScope(); + const Definition *d = g_theCallContext.getScope(); //printf("updateCallContextForSmartPointer() cd=%s\n",cd ? d->name().data() : "<none>"); MemberDef *md; - if (d && d->definitionType()==Definition::TypeClass && (md=(dynamic_cast<ClassDef*>(d))->isSmartPointer())) + if (d && d->definitionType()==Definition::TypeClass && (md=(dynamic_cast<const ClassDef*>(d))->isSmartPointer())) { - ClassDef *ncd = stripClassName(md->typeString(),md->getOuterScope()); + const ClassDef *ncd = stripClassName(md->typeString(),md->getOuterScope()); if (ncd) { g_theCallContext.setScope(ncd); @@ -860,11 +860,11 @@ static bool getLinkInScope(const QCString &c, // scope bool varOnly=FALSE ) { - MemberDef *md; - ClassDef *cd; - FileDef *fd; - NamespaceDef *nd; - GroupDef *gd; + const MemberDef *md = 0; + const ClassDef *cd = 0; + const FileDef *fd = 0; + const NamespaceDef *nd = 0; + const GroupDef *gd = 0; DBG_CTX((stderr,"getLinkInScope: trying `%s'::`%s' varOnly=%d\n",c.data(),m.data(),varOnly)); if (getDefs(c,m,"()",md,cd,fd,nd,gd,FALSE,g_sourceFileDef,FALSE,g_forceTagReference) && (!varOnly || md->isVariable())) @@ -878,16 +878,16 @@ static bool getLinkInScope(const QCString &c, // scope anchor.sprintf("a%d",g_anchorCount); //printf("addExampleFile(%s,%s,%s)\n",anchor.data(),g_exampleName.data(), // g_exampleFile.data()); - if (md->addExample(anchor,g_exampleName,g_exampleFile)) + if (const_cast<MemberDef*>(md)->addExample(anchor,g_exampleName,g_exampleFile)) { ol.writeCodeAnchor(anchor); g_anchorCount++; } } - Definition *d = md->getOuterScope()==Doxygen::globalScope ? - md->getFileDef() : md->getOuterScope(); - if (md->getGroupDef()) d = md->getGroupDef(); + const Definition *d = md->getOuterScope()==Doxygen::globalScope ? + md->resolveAlias()->getFileDef() : md->getOuterScope(); + if (md->resolveAlias()->getGroupDef()) d = md->resolveAlias()->getGroupDef(); if (d && d->isLinkable()) { g_theCallContext.setScope(stripClassName(md->typeString(),md->getOuterScope())); @@ -897,7 +897,7 @@ static bool getLinkInScope(const QCString &c, // scope if (g_currentDefinition && g_currentMemberDef && md!=g_currentMemberDef && g_insideBody && g_collectXRefs) { - addDocCrossReference(g_currentMemberDef,md); + addDocCrossReference(g_currentMemberDef,const_cast<MemberDef*>(md)); } //printf("d->getReference()=`%s' d->getOutputBase()=`%s' name=`%s' member name=`%s'\n",d->getReference().data(),d->getOutputFileBase().data(),d->name().data(),md->name().data()); @@ -961,8 +961,8 @@ static void generateClassOrGlobalLink(CodeOutputInterface &ol,const char *clName { className = substitute(className,".","::"); // for PHP namespaces } - ClassDef *cd=0,*lcd=0; - MemberDef *md=0; + const ClassDef *cd=0,*lcd=0; + const MemberDef *md=0; bool isLocal=FALSE; //printf("generateClassOrGlobalLink(className=%s)\n",className.data()); @@ -983,7 +983,7 @@ static void generateClassOrGlobalLink(CodeOutputInterface &ol,const char *clName cd=getResolvedClass(d,g_sourceFileDef,bareName,&md); // try unspecialized version } } - NamespaceDef *nd = getResolvedNamespace(className); + const NamespaceDef *nd = getResolvedNamespace(className); if (nd && nd->isLinkableInProject()) { g_theCallContext.setScope(nd); @@ -1033,7 +1033,7 @@ static void generateClassOrGlobalLink(CodeOutputInterface &ol,const char *clName anchor.sprintf("_a%d",g_anchorCount); //printf("addExampleClass(%s,%s,%s)\n",anchor.data(),g_exampleName.data(), // g_exampleFile.data()); - if (cd->addExample(anchor,g_exampleName,g_exampleFile)) + if (const_cast<ClassDef*>(cd)->addExample(anchor,g_exampleName,g_exampleFile)) { ol.writeCodeAnchor(anchor); g_anchorCount++; @@ -1044,13 +1044,13 @@ static void generateClassOrGlobalLink(CodeOutputInterface &ol,const char *clName g_theCallContext.setScope(cd); if (md) { - Definition *d = md->getOuterScope()==Doxygen::globalScope ? + const Definition *d = md->getOuterScope()==Doxygen::globalScope ? md->getFileDef() : md->getOuterScope(); if (md->getGroupDef()) d = md->getGroupDef(); if (d && d->isLinkable() && md->isLinkable() && g_currentMemberDef && g_collectXRefs) { - addDocCrossReference(g_currentMemberDef,md); + addDocCrossReference(g_currentMemberDef,const_cast<MemberDef*>(md)); } } } @@ -1092,8 +1092,8 @@ static void generateClassOrGlobalLink(CodeOutputInterface &ol,const char *clName } text+=getLanguageSpecificSeparator(md->getLanguage()); text+=clName; - md->setName(text); - md->setLocalName(text); + const_cast<MemberDef*>(md)->setName(text); + const_cast<MemberDef*>(md)->setLocalName(text); } else // normal reference { @@ -1103,7 +1103,7 @@ static void generateClassOrGlobalLink(CodeOutputInterface &ol,const char *clName addToSearchIndex(clName); if (g_currentMemberDef && g_collectXRefs) { - addDocCrossReference(g_currentMemberDef,md); + addDocCrossReference(g_currentMemberDef,const_cast<MemberDef*>(md)); } return; } @@ -1139,11 +1139,11 @@ static bool generateClassMemberLink(CodeOutputInterface &ol,MemberDef *xmd,const } } - ClassDef *typeClass = stripClassName(removeAnonymousScopes(xmd->typeString()),xmd->getOuterScope()); + const ClassDef *typeClass = stripClassName(removeAnonymousScopes(xmd->typeString()),xmd->getOuterScope()); DBG_CTX((stderr,"%s -> typeName=%p\n",xmd->typeString(),typeClass)); g_theCallContext.setScope(typeClass); - Definition *xd = xmd->getOuterScope()==Doxygen::globalScope ? + const Definition *xd = xmd->getOuterScope()==Doxygen::globalScope ? xmd->getFileDef() : xmd->getOuterScope(); if (xmd->getGroupDef()) xd = xmd->getGroupDef(); if (xd && xd->isLinkable()) @@ -1172,11 +1172,11 @@ static bool generateClassMemberLink(CodeOutputInterface &ol,MemberDef *xmd,const return FALSE; } -static bool generateClassMemberLink(CodeOutputInterface &ol,Definition *def,const char *memName) +static bool generateClassMemberLink(CodeOutputInterface &ol,const Definition *def,const char *memName) { if (def && def->definitionType()==Definition::TypeClass) { - ClassDef *cd = dynamic_cast<ClassDef*>(def); + const ClassDef *cd = dynamic_cast<const ClassDef*>(def); MemberDef *xmd = cd->getMemberByName(memName); //printf("generateClassMemberLink(class=%s,member=%s)=%p\n",def->name().data(),memName,xmd); if (xmd) @@ -1197,7 +1197,7 @@ static bool generateClassMemberLink(CodeOutputInterface &ol,Definition *def,cons } else if (def && def->definitionType()==Definition::TypeNamespace) { - NamespaceDef *nd = dynamic_cast<NamespaceDef*>(def); + const NamespaceDef *nd = dynamic_cast<const NamespaceDef*>(def); //printf("Looking for %s inside namespace %s\n",memName,nd->name().data()); Definition *innerDef = nd->findInnerCompound(memName); if (innerDef) @@ -1220,7 +1220,7 @@ static void generateMemberLink(CodeOutputInterface &ol,const QCString &varName, if (varName.isEmpty()) return; // look for the variable in the current context - ClassDef *vcd = g_theVarContext.findVariable(varName); + const ClassDef *vcd = g_theVarContext.findVariable(varName); if (vcd) { if (vcd!=VariableContext::dummyContext) @@ -1265,14 +1265,14 @@ static void generateMemberLink(CodeOutputInterface &ol,const QCString &varName, if (vmn) { MemberNameIterator vmni(*vmn); - MemberDef *vmd; + const MemberDef *vmd; for (;(vmd=vmni.current());++vmni) { if (/*(vmd->isVariable() || vmd->isFunction()) && */ vmd->getClassDef()==jcd) { //printf("Found variable type=%s\n",vmd->typeString()); - ClassDef *mcd=stripClassName(vmd->typeString(),vmd->getOuterScope()); + const ClassDef *mcd=stripClassName(vmd->typeString(),vmd->getOuterScope()); if (mcd && mcd->isLinkable()) { if (generateClassMemberLink(ol,mcd,memName)) return; @@ -1286,14 +1286,14 @@ static void generateMemberLink(CodeOutputInterface &ol,const QCString &varName, { //printf("There is a variable with name `%s'\n",varName); MemberNameIterator vmni(*vmn); - MemberDef *vmd; + const MemberDef *vmd; for (;(vmd=vmni.current());++vmni) { if (/*(vmd->isVariable() || vmd->isFunction()) && */ vmd->getClassDef()==vcd) { //printf("Found variable type=%s\n",vmd->typeString()); - ClassDef *mcd=stripClassName(vmd->typeString(),vmd->getOuterScope()); + const ClassDef *mcd=stripClassName(vmd->typeString(),vmd->getOuterScope()); if (mcd && mcd->isLinkable()) { if (generateClassMemberLink(ol,mcd,memName)) return; @@ -1335,7 +1335,7 @@ static void generateFunctionLink(CodeOutputInterface &ol,const char *funcName) DBG_CTX((stdout,"*** locScope=%s locFunc=%s\n",locScope.data(),locFunc.data())); int len=2; int i=locFunc.findRev("::"); - if (g_currentMemberDef && g_currentMemberDef->getClassDef() && + if (g_currentMemberDef && g_currentMemberDef->resolveAlias()->getClassDef() && funcName==g_currentMemberDef->localName() && g_currentMemberDef->getDefLine()==g_yyLineNr && generateClassMemberLink(ol,g_currentMemberDef,funcName) @@ -1561,7 +1561,7 @@ static void writeObjCMethodCall(ObjCCallCtx *ctx) writeMultiLineCodeLink(*g_code,ctx->method,pName->data()); if (g_currentMemberDef && g_collectXRefs) { - addDocCrossReference(g_currentMemberDef,ctx->method); + addDocCrossReference(g_currentMemberDef,const_cast<MemberDef*>(ctx->method)); } } else @@ -1640,7 +1640,7 @@ static void writeObjCMethodCall(ObjCCallCtx *ctx) writeMultiLineCodeLink(*g_code,ctx->objectVar,pObject->data()); if (g_currentMemberDef && g_collectXRefs) { - addDocCrossReference(g_currentMemberDef,ctx->objectVar); + addDocCrossReference(g_currentMemberDef,const_cast<MemberDef*>(ctx->objectVar)); } } else if (ctx->objectType && @@ -1648,12 +1648,12 @@ static void writeObjCMethodCall(ObjCCallCtx *ctx) ctx->objectType->isLinkable() ) // object is class name { - ClassDef *cd = ctx->objectType; + const ClassDef *cd = ctx->objectType; writeMultiLineCodeLink(*g_code,cd,pObject->data()); } else // object still needs to be resolved { - ClassDef *cd = getResolvedClass(g_currentDefinition, + const ClassDef *cd = getResolvedClass(g_currentDefinition, g_sourceFileDef, *pObject); if (cd && cd->isLinkable()) { @@ -2302,12 +2302,11 @@ RAWEND ")"[^ \t\(\)\\]{0,16}\" char *s=g_curClassBases.first(); while (s) { - ClassDef *bcd; - bcd=g_codeClassSDict->find(s); + const ClassDef *bcd=g_codeClassSDict->find(s); if (bcd==0) bcd=getResolvedClass(g_currentDefinition,g_sourceFileDef,s); if (bcd && bcd!=ncd) { - ncd->insertBaseClass(bcd,s,Public,Normal); + ncd->insertBaseClass(const_cast<ClassDef*>(bcd),s,Public,Normal); } s=g_curClassBases.next(); } @@ -2510,7 +2509,7 @@ RAWEND ")"[^ \t\(\)\\]{0,16}\" } <Body>"*"{B}*")" { // end of cast? g_code->codify(yytext); - g_theCallContext.popScope(); + g_theCallContext.popScope(g_name, g_type); g_bracketCount--; g_parmType = g_name; BEGIN(FuncCall); @@ -2520,7 +2519,7 @@ RAWEND ")"[^ \t\(\)\\]{0,16}\" g_name.resize(0);g_type.resize(0); if (*yytext==')') { - g_theCallContext.popScope(); + g_theCallContext.popScope(g_name, g_type); g_bracketCount--; BEGIN(FuncCall); } @@ -2852,7 +2851,7 @@ RAWEND ")"[^ \t\(\)\\]{0,16}\" } else if (*yytext=='[') { - g_theCallContext.pushScope(); + g_theCallContext.pushScope(g_name, g_type); } g_args.resize(0); g_parmType.resize(0); @@ -2878,7 +2877,7 @@ RAWEND ")"[^ \t\(\)\\]{0,16}\" } <ObjCMemberCall>"[" { g_code->codify(yytext); - g_theCallContext.pushScope(); + g_theCallContext.pushScope(g_name, g_type); } <ObjCMemberCall2>{ID}":"? { g_name+=yytext; @@ -2900,7 +2899,7 @@ RAWEND ")"[^ \t\(\)\\]{0,16}\" BEGIN(ObjCMemberCall3); } <ObjCMemberCall2,ObjCMemberCall3>"]" { - g_theCallContext.popScope(); + g_theCallContext.popScope(g_name, g_type); g_code->codify(yytext); BEGIN(Body); } @@ -2990,7 +2989,7 @@ RAWEND ")"[^ \t\(\)\\]{0,16}\" <ObjCCall,ObjCMName,ObjCSkipStr>\n { g_currentCtx->format+=*yytext; } <Body>"]" { - g_theCallContext.popScope(); + g_theCallContext.popScope(g_name, g_type); g_code->codify(yytext); // TODO: nested arrays like: a[b[0]->func()]->func() g_name = g_saveName.copy(); @@ -3093,7 +3092,7 @@ RAWEND ")"[^ \t\(\)\\]{0,16}\" g_parmType.resize(0);g_parmName.resize(0); g_code->codify(yytext); g_bracketCount++; - g_theCallContext.pushScope(); + g_theCallContext.pushScope(g_name, g_type); if (YY_START==FuncCall && !g_insideBody) { g_theVarContext.pushScope(); @@ -3127,7 +3126,7 @@ RAWEND ")"[^ \t\(\)\\]{0,16}\" g_parmName.resize(0); g_theVarContext.addVariable(g_parmType,g_parmName); } - g_theCallContext.popScope(); + g_theCallContext.popScope(g_name, g_type); g_inForEachExpression = FALSE; //g_theCallContext.setClass(0); // commented out, otherwise a()->b() does not work for b(). g_code->codify(yytext); @@ -3184,7 +3183,7 @@ RAWEND ")"[^ \t\(\)\\]{0,16}\" g_theVarContext.pushScope(); } g_theVarContext.addVariable(g_parmType,g_parmName); - //g_theCallContext.popScope(); + //g_theCallContext.popScope(g_name, g_type); g_parmType.resize(0);g_parmName.resize(0); int index = g_name.findRev("::"); DBG_CTX((stderr,"g_name=%s\n",g_name.data())); @@ -3192,7 +3191,7 @@ RAWEND ")"[^ \t\(\)\\]{0,16}\" { QCString scope = g_name.left(index); if (!g_classScope.isEmpty()) scope.prepend(g_classScope+"::"); - ClassDef *cd=getResolvedClass(Doxygen::globalScope,g_sourceFileDef,scope); + const ClassDef *cd=getResolvedClass(Doxygen::globalScope,g_sourceFileDef,scope); if (cd) { setClassScope(cd->name()); @@ -3553,6 +3552,24 @@ RAWEND ")"[^ \t\(\)\\]{0,16}\" BEGIN(SkipComment); } } +<*>^{B}*"/**"[*]+/[^/] { // special C "banner" comment block at a new line + if (Config_getBool(JAVADOC_BANNER) && Config_getBool(STRIP_CODE_COMMENTS)) + { + g_lastSpecialCContext = YY_START; + BEGIN(RemoveSpecialCComment); + } + else + { + // check is to prevent getting stuck in skipping C++ comments + if (YY_START != SkipCxxComment) + { + g_lastCContext = YY_START ; + } + startFontClass("comment"); + g_code->codify(yytext); + BEGIN(SkipComment); + } + } <*>^{B}*"/*"[!*]/[^/*] { // special C comment block at a new line if (Config_getBool(STRIP_CODE_COMMENTS)) { @@ -3626,11 +3643,11 @@ RAWEND ")"[^ \t\(\)\\]{0,16}\" } <*>"("|"[" { g_code->codify(yytext); - g_theCallContext.pushScope(); + g_theCallContext.pushScope(g_name, g_type); } <*>")"|"]" { g_code->codify(yytext); - g_theCallContext.popScope(); + g_theCallContext.popScope(g_name, g_type); } <*>\n { g_yyColNr++; @@ -3719,7 +3736,7 @@ void resetCCodeParserState() void parseCCode(CodeOutputInterface &od,const char *className,const QCString &s, SrcLangExt lang,bool exBlock, const char *exName,FileDef *fd, int startLine,int endLine,bool inlineFragment, - MemberDef *memberDef,bool showLineNumbers,Definition *searchCtx, + const MemberDef *memberDef,bool showLineNumbers,const Definition *searchCtx, bool collectXRefs) { //printf("***parseCode() exBlock=%d exName=%s fd=%p className=%s searchCtx=%s\n", diff --git a/src/commentcnv.l b/src/commentcnv.l index 6b08d74..031b6f5 100644 --- a/src/commentcnv.l +++ b/src/commentcnv.l @@ -266,7 +266,7 @@ void replaceComment(int offset); else { g_pythonDocString = TRUE; - g_nestingCount=0; + g_nestingCount=1; g_commentStack.clear(); /* to be on the save side */ copyToOutput(yytext,(int)yyleng); BEGIN(CComment); @@ -281,7 +281,7 @@ void replaceComment(int offset); else { copyToOutput(yytext,(int)yyleng); - g_nestingCount=0; + g_nestingCount=0; // Fortran doesn't have an end comment g_commentStack.clear(); /* to be on the save side */ BEGIN(CComment); g_commentStack.push(new CommentCtx(g_lineNr)); @@ -298,7 +298,7 @@ void replaceComment(int offset); if (isFixedForm && (g_col == 0)) { copyToOutput(yytext,(int)yyleng); - g_nestingCount=0; + g_nestingCount=0; // Fortran doesn't have an end comment g_commentStack.clear(); /* to be on the safe side */ BEGIN(CComment); g_commentStack.push(new CommentCtx(g_lineNr)); @@ -399,8 +399,12 @@ void replaceComment(int offset); copyToOutput(yytext,(int)yyleng); } <Scan>"/*"[*!]? { /* start of a C comment */ + if ((g_lang==SrcLangExt_Python) || (g_lang==SrcLangExt_Tcl)) + { + REJECT; + } g_specialComment=(int)yyleng==3; - g_nestingCount=0; + g_nestingCount=1; g_commentStack.clear(); /* to be on the save side */ copyToOutput(yytext,(int)yyleng); BEGIN(CComment); @@ -414,7 +418,7 @@ void replaceComment(int offset); else { copyToOutput(yytext,(int)yyleng); - g_nestingCount=0; + g_nestingCount=0; // Python doesn't have an end comment for # g_commentStack.clear(); /* to be on the save side */ BEGIN(CComment); g_commentStack.push(new CommentCtx(g_lineNr)); @@ -429,7 +433,7 @@ void replaceComment(int offset); { g_vhdl = TRUE; copyToOutput(yytext,(int)yyleng); - g_nestingCount=0; + g_nestingCount=0; // VHDL doesn't have an end comment g_commentStack.clear(); /* to be on the save side */ BEGIN(CComment); g_commentStack.push(new CommentCtx(g_lineNr)); @@ -443,7 +447,7 @@ void replaceComment(int offset); else { copyToOutput(yytext,(int)yyleng); - g_nestingCount=0; + g_nestingCount=0; // Fortran doesn't have an end comment g_commentStack.clear(); /* to be on the save side */ BEGIN(CComment); g_commentStack.push(new CommentCtx(g_lineNr)); @@ -660,25 +664,30 @@ void replaceComment(int offset); } } <CComment>"/"+"*" { /* nested C comment */ + if ((g_lang==SrcLangExt_Python) || (g_lang==SrcLangExt_Tcl)) + { + REJECT; + } g_nestingCount++; g_commentStack.push(new CommentCtx(g_lineNr)); copyToOutput(yytext,(int)yyleng); } <CComment>"*"+"/" { /* end of C comment */ - if (g_lang==SrcLangExt_Python) + if ((g_lang==SrcLangExt_Python) || (g_lang==SrcLangExt_Tcl)) { REJECT; } else { copyToOutput(yytext,(int)yyleng); + g_nestingCount--; if (g_nestingCount<=0) { BEGIN(Scan); } else { - g_nestingCount--; + //g_nestingCount--; delete g_commentStack.pop(); } } @@ -1111,7 +1120,7 @@ void convertCppComments(BufStr *inBuf,BufStr *outBuf,const char *fileName) } tmp += ")"; warn(g_fileName,g_lineNr,"Reached end of file while still inside a (nested) comment. " - "Nesting level %d %s",g_nestingCount+1,tmp.data()); // add one for "normal" expected end of comment + "Nesting level %d %s",g_nestingCount,tmp.data()); } g_commentStack.clear(); g_nestingCount = 0; diff --git a/src/commentscan.h b/src/commentscan.h index 75cd99f..7d2189f 100644 --- a/src/commentscan.h +++ b/src/commentscan.h @@ -85,13 +85,5 @@ bool parseCommentBlock(ParserInterface *parser, bool &newEntryNeeded ); -void groupEnterFile(const char *file,int line); -void groupLeaveFile(const char *file,int line); -void groupLeaveCompound(const char *file,int line,const char *name); -void groupEnterCompound(const char *file,int line,const char *name); -void openGroup(Entry *e,const char *file,int line); -void closeGroup(Entry *,const char *file,int line,bool foundInline=FALSE); -void initGroupInfo(Entry *e); - #endif diff --git a/src/commentscan.l b/src/commentscan.l index 0ca293c..a52821c 100644 --- a/src/commentscan.l +++ b/src/commentscan.l @@ -147,30 +147,30 @@ static DocCmdMap docCmdMap[] = // command name handler function ends brief description { "brief", &handleBrief, FALSE }, { "short", &handleBrief, FALSE }, - { "fn", &handleFn, FALSE }, - { "var", &handleFn, FALSE }, - { "typedef", &handleFn, FALSE }, - { "property", &handleFn, FALSE }, - { "def", &handleDef, FALSE }, + { "fn", &handleFn, TRUE }, + { "var", &handleFn, TRUE }, + { "typedef", &handleFn, TRUE }, + { "property", &handleFn, TRUE }, + { "def", &handleDef, TRUE }, { "overload", &handleOverload, FALSE }, - { "enum", &handleEnum, FALSE }, - { "defgroup", &handleDefGroup, FALSE }, - { "addtogroup", &handleAddToGroup, FALSE }, - { "weakgroup", &handleWeakGroup, FALSE }, - { "namespace", &handleNamespace, FALSE }, - { "package", &handlePackage, FALSE }, - { "class", &handleClass, FALSE }, + { "enum", &handleEnum, TRUE }, + { "defgroup", &handleDefGroup, TRUE }, + { "addtogroup", &handleAddToGroup, TRUE }, + { "weakgroup", &handleWeakGroup, TRUE }, + { "namespace", &handleNamespace, TRUE }, + { "package", &handlePackage, TRUE }, + { "class", &handleClass, TRUE }, { "headerfile", &handleHeaderFile, FALSE }, - { "protocol", &handleProtocol, FALSE }, - { "category", &handleCategory, FALSE }, - { "union", &handleUnion, FALSE }, - { "struct", &handleStruct, FALSE }, - { "interface", &handleInterface, FALSE }, - { "idlexcept", &handleIdlException, FALSE }, - { "page", &handlePage, FALSE }, - { "mainpage", &handleMainpage, FALSE }, - { "file", &handleFile, FALSE }, - { "dir", &handleDir, FALSE }, + { "protocol", &handleProtocol, TRUE }, + { "category", &handleCategory, TRUE }, + { "union", &handleUnion, TRUE }, + { "struct", &handleStruct, TRUE }, + { "interface", &handleInterface, TRUE }, + { "idlexcept", &handleIdlException, TRUE }, + { "page", &handlePage, TRUE }, + { "mainpage", &handleMainpage, TRUE }, + { "file", &handleFile, TRUE }, + { "dir", &handleDir, TRUE }, { "example", &handleExample, FALSE }, { "details", &handleDetails, TRUE }, { "name", &handleName, FALSE }, @@ -210,7 +210,7 @@ static DocCmdMap docCmdMap[] = { "elseif", &handleElseIf, FALSE }, { "else", &handleElse, FALSE }, { "endif", &handleEndIf, FALSE }, - { "ingroup", &handleIngroup, FALSE }, + { "ingroup", &handleIngroup, TRUE }, { "nosubgrouping", &handleNoSubGrouping, FALSE }, { "showinitializer", &handleShowInitializer, FALSE }, { "hideinitializer", &handleHideInitializer, FALSE }, @@ -386,11 +386,6 @@ class GuardedSection bool m_parentVisible; }; -void openGroup(Entry *e,const char *file,int line); -void closeGroup(Entry *e,const char *file,int line,bool foundInline=FALSE); -void initGroupInfo(Entry *e); -static void groupAddDocs(Entry *e); - /* ----------------------------------------------------------------- * * statics @@ -451,20 +446,11 @@ static bool g_insideParBlock; //----------------------------------------------------------------------------- -static QStack<Grouping> g_autoGroupStack; -static int g_memberGroupId = DOX_NOGROUP; -static QCString g_memberGroupHeader; -static QCString g_memberGroupDocs; -static QCString g_memberGroupRelates; -static QCString g_compoundName; - -//----------------------------------------------------------------------------- - static void initParser() { g_sectionLabel.resize(0); g_sectionTitle.resize(0); - g_memberGroupHeader.resize(0); + Doxygen::docGroup.clearHeader(); g_insideParBlock = FALSE; } @@ -1218,12 +1204,12 @@ RCSTAG "$"{ID}":"[^\n$]+"$" } <Comment>{B}*{CMD}"{" { // begin of a group //langParser->handleGroupStartCommand(g_memberGroupHeader); - openGroup(current,yyFileName,yyLineNr); + Doxygen::docGroup.open(current,yyFileName,yyLineNr); } <Comment>{B}*{CMD}"}" { // end of a group //langParser->handleGroupEndCommand(); - closeGroup(current,yyFileName,yyLineNr,TRUE); - g_memberGroupHeader.resize(0); + Doxygen::docGroup.close(current,yyFileName,yyLineNr,TRUE); + Doxygen::docGroup.clearHeader(); parseMore=TRUE; needNewEntry = TRUE; #if YY_FLEX_MAJOR_VERSION>=2 && (YY_FLEX_MINOR_VERSION>5 || (YY_FLEX_MINOR_VERSION==5 && YY_FLEX_SUBMINOR_VERSION>=33)) @@ -1576,7 +1562,7 @@ RCSTAG "$"{ID}":"[^\n$]+"$" yyLineNr++; addOutput('\n'); } -<GroupDocArg2>[^\n\*]+ { // title (stored in type) +<GroupDocArg2>[^\n\\]+ { // title (stored in type) current->type += yytext; current->type = current->type.stripWhiteSpace(); } @@ -1594,11 +1580,16 @@ RCSTAG "$"{ID}":"[^\n$]+"$" addOutput('\n'); BEGIN( Comment ); } +<GroupDocArg2>. { // title (stored in type) + current->type += yytext; + current->type = current->type.stripWhiteSpace(); + } /* --------- handle arguments of page/mainpage command ------------------- */ <PageDocArg1>{FILE} { // first argument; page name current->name = stripQuotes(yytext); + current->args = ""; BEGIN( PageDocArg2 ); } <PageDocArg1>{LC} { yyLineNr++; @@ -1615,17 +1606,21 @@ RCSTAG "$"{ID}":"[^\n$]+"$" } <PageDocArg1>. { // ignore other stuff } -<PageDocArg2>.*"\n" { // second argument; page title - yyLineNr++; +<PageDocArg2>{DOCNL} { // second argument; page title + if (*yytext=='\n') yyLineNr++; + addOutput('\n'); + BEGIN( Comment ); + } +<PageDocArg2>{CMD}[<>] { // bug 748927 QCString tmp = yytext; tmp = substitute(substitute(tmp,"@<","<"),"@>",">"); tmp = substitute(substitute(tmp,"\\<","<"),"\\>",">"); - current->args = tmp; - addOutput('\n'); - BEGIN( Comment ); + current->args += tmp; } - +<PageDocArg2>. { + current->args += yytext; + } /* --------- handle arguments of the param command ------------ */ <ParamArg1>{ID}/{B}*"," { addOutput(yytext); @@ -1895,17 +1890,20 @@ RCSTAG "$"{ID}":"[^\n$]+"$" addOutput('\n'); } <FormatBlock>"/*" { // start of a C-comment - g_commentCount++; + if (!(blockName=="code" || blockName=="verbatim")) g_commentCount++; addOutput(yytext); } <FormatBlock>"*/" { // end of a C-comment addOutput(yytext); - g_commentCount--; - if (g_commentCount<0 && blockName!="verbatim") - { - warn(yyFileName,yyLineNr, + if (!(blockName=="code" || blockName=="verbatim")) + { + g_commentCount--; + if (g_commentCount<0) + { + warn(yyFileName,yyLineNr, "found */ without matching /* while inside a \\%s block! Perhaps a missing \\end%s?\n",blockName.data(),blockName.data()); - } + } + } } <FormatBlock>. { addOutput(*yytext); @@ -1965,6 +1963,7 @@ RCSTAG "$"{ID}":"[^\n$]+"$" addOutput(*yytext); } <GuardParamEnd>{B}*{DOCNL} { + lineCount(); g_spaceBeforeIf.resize(0); BEGIN(Comment); } @@ -2119,10 +2118,10 @@ RCSTAG "$"{ID}":"[^\n$]+"$" <NameParam>{LC} { // line continuation yyLineNr++; addOutput('\n'); - g_memberGroupHeader+=' '; + Doxygen::docGroup.appendHeader(' '); } <NameParam>. { // ignore other stuff - g_memberGroupHeader+=*yytext; + Doxygen::docGroup.appendHeader(*yytext); current->name+=*yytext; } @@ -2298,7 +2297,7 @@ RCSTAG "$"{ID}":"[^\n$]+"$" if (*yytext=='\n') yyLineNr++; addOutput('\n'); setOutput(OutputDoc); - addOutput("\\copydetails "); + addOutput(" \\copydetails "); addOutput(g_copyDocArg); addOutput("\n"); BEGIN(Comment); @@ -2359,6 +2358,7 @@ static bool handleDefGroup(const QCString &, const QCStringList &) { bool stop=makeStructuralIndicator(Entry::GROUPDOC_SEC); current->groupDocType = Entry::GROUPDOC_NORMAL; + setOutput(OutputBrief); BEGIN( GroupDocArg1 ); return stop; } @@ -2462,6 +2462,7 @@ static bool handleMainpage(const QCString &, const QCStringList &) { current->name = "mainpage"; } + current->name = ""; BEGIN( PageDocArg2 ); return stop; } @@ -2540,11 +2541,11 @@ static bool handleName(const QCString &, const QCStringList &) bool stop=makeStructuralIndicator(Entry::MEMBERGRP_SEC); if (!stop) { - g_memberGroupHeader.resize(0); + Doxygen::docGroup.clearHeader(); BEGIN( NameParam ); - if (g_memberGroupId!=DOX_NOGROUP) // end of previous member group + if (!Doxygen::docGroup.isEmpty()) // end of previous member group { - closeGroup(current,yyFileName,yyLineNr,TRUE); + Doxygen::docGroup.close(current,yyFileName,yyLineNr,TRUE); } } return stop; @@ -3192,9 +3193,9 @@ bool parseCommentBlock(/* in */ ParserInterface *parser, } if (current->section==Entry::MEMBERGRP_SEC && - g_memberGroupId==DOX_NOGROUP) // @name section but no group started yet + Doxygen::docGroup.isEmpty()) // @name section but no group started yet { - openGroup(current,yyFileName,yyLineNr); + Doxygen::docGroup.open(current,yyFileName,yyLineNr,true); } Debug::print(Debug::CommentScan,0,"-----------\nCommentScanner: %s:%d\noutput=[\n" @@ -3208,7 +3209,7 @@ bool parseCommentBlock(/* in */ ParserInterface *parser, checkFormula(); prot = protection; - groupAddDocs(curEntry); + Doxygen::docGroup.addDocs(curEntry); newEntryNeeded = needNewEntry; @@ -3227,185 +3228,6 @@ bool parseCommentBlock(/* in */ ParserInterface *parser, return parseMore; } -//--------------------------------------------------------------------------- - -void groupEnterFile(const char *fileName,int) -{ - g_autoGroupStack.setAutoDelete(TRUE); - g_autoGroupStack.clear(); - g_memberGroupId = DOX_NOGROUP; - g_memberGroupDocs.resize(0); - g_memberGroupRelates.resize(0); - g_compoundName=fileName; -} - -void groupLeaveFile(const char *fileName,int line) -{ - //if (g_memberGroupId!=DOX_NOGROUP) - //{ - // warn(fileName,line,"end of file while inside a member group\n"); - //} - g_memberGroupId=DOX_NOGROUP; - g_memberGroupRelates.resize(0); - g_memberGroupDocs.resize(0); - if (!g_autoGroupStack.isEmpty()) - { - warn(fileName,line,"end of file while inside a group\n"); - } -} - -void groupEnterCompound(const char *fileName,int line,const char *name) -{ - if (g_memberGroupId!=DOX_NOGROUP) - { - warn(fileName,line,"try to put compound %s inside a member group\n",name); - } - g_memberGroupId=DOX_NOGROUP; - g_memberGroupRelates.resize(0); - g_memberGroupDocs.resize(0); - g_compoundName = name; - int i = g_compoundName.find('('); - if (i!=-1) - { - g_compoundName=g_compoundName.left(i); // strip category (Obj-C) - } - if (g_compoundName.isEmpty()) - { - g_compoundName=fileName; - } - //printf("groupEnterCompound(%s)\n",name); -} - -void groupLeaveCompound(const char *,int,const char * /*name*/) -{ - //printf("groupLeaveCompound(%s)\n",name); - //if (g_memberGroupId!=DOX_NOGROUP) - //{ - // warn(fileName,line,"end of compound %s while inside a member group\n",name); - //} - g_memberGroupId=DOX_NOGROUP; - g_memberGroupRelates.resize(0); - g_memberGroupDocs.resize(0); - g_compoundName.resize(0); -} - -static int findExistingGroup(int &groupId,const MemberGroupInfo *info) -{ - //printf("findExistingGroup %s:%s\n",info->header.data(),info->compoundName.data()); - QIntDictIterator<MemberGroupInfo> di(Doxygen::memGrpInfoDict); - MemberGroupInfo *mi; - for (di.toFirst();(mi=di.current());++di) - { - if (g_compoundName==mi->compoundName && // same file or scope - !mi->header.isEmpty() && // not a nameless group - qstricmp(mi->header,info->header)==0 // same header name - ) - { - //printf("Found it!\n"); - return (int)di.currentKey(); // put the item in this group - } - } - groupId++; // start new group - return groupId; -} - -void openGroup(Entry *e,const char *,int) -{ - //printf("==> openGroup(name=%s,sec=%x) g_autoGroupStack=%d\n", - // e->name.data(),e->section,g_autoGroupStack.count()); - if (e->section==Entry::GROUPDOC_SEC) // auto group - { - g_autoGroupStack.push(new Grouping(e->name,e->groupingPri())); - } - else // start of a member group - { - //printf(" membergroup id=%d %s\n",g_memberGroupId,g_memberGroupHeader.data()); - if (g_memberGroupId==DOX_NOGROUP) // no group started yet - { - static int curGroupId=0; - - MemberGroupInfo *info = new MemberGroupInfo; - info->header = g_memberGroupHeader.stripWhiteSpace(); - info->compoundName = g_compoundName; - g_memberGroupId = findExistingGroup(curGroupId,info); - //printf(" use membergroup %d\n",g_memberGroupId); - Doxygen::memGrpInfoDict.insert(g_memberGroupId,info); - - g_memberGroupRelates = e->relates; - e->mGrpId = g_memberGroupId; - } - } -} - -void closeGroup(Entry *e,const char *fileName,int line,bool foundInline) -{ - //printf("==> closeGroup(name=%s,sec=%x,file=%s,line=%d) g_autoGroupStack=%d\n", - // e->name.data(),e->section,fileName,line,g_autoGroupStack.count()); - if (g_memberGroupId!=DOX_NOGROUP) // end of member group - { - MemberGroupInfo *info=Doxygen::memGrpInfoDict.find(g_memberGroupId); - if (info) // known group - { - info->doc = g_memberGroupDocs; - info->docFile = fileName; - info->docLine = line; - } - g_memberGroupId=DOX_NOGROUP; - g_memberGroupRelates.resize(0); - g_memberGroupDocs.resize(0); - if (!foundInline) e->mGrpId=DOX_NOGROUP; - //printf("new group id=%d\n",g_memberGroupId); - } - else if (!g_autoGroupStack.isEmpty()) // end of auto group - { - Grouping *grp = g_autoGroupStack.pop(); - // see bug577005: we should not remove the last group for e - if (!foundInline) e->groups->removeLast(); - //printf("Removing %s e=%p\n",grp->groupname.data(),e); - delete grp; - if (!foundInline) initGroupInfo(e); - } -} - -void initGroupInfo(Entry *e) -{ - //printf("==> initGroup(id=%d,related=%s,e=%p)\n",g_memberGroupId, - // g_memberGroupRelates.data(),e); - e->mGrpId = g_memberGroupId; - e->relates = g_memberGroupRelates; - if (!g_autoGroupStack.isEmpty()) - { - //printf("Appending group %s to %s: count=%d entry=%p\n", - // g_autoGroupStack.top()->groupname.data(), - // e->name.data(),e->groups->count(),e); - e->groups->append(new Grouping(*g_autoGroupStack.top())); - } -} - -static void groupAddDocs(Entry *e) -{ - if (e->section==Entry::MEMBERGRP_SEC) - { - g_memberGroupDocs=e->brief.stripWhiteSpace(); - e->doc = stripLeadingAndTrailingEmptyLines(e->doc,e->docLine); - if (!g_memberGroupDocs.isEmpty() && !e->doc.isEmpty()) - { - g_memberGroupDocs+="\n\n"; - } - g_memberGroupDocs+=e->doc; - MemberGroupInfo *info=Doxygen::memGrpInfoDict.find(g_memberGroupId); - if (info) - { - info->doc = g_memberGroupDocs; - info->docFile = e->docFile; - info->docLine = e->docLine; - info->setRefItems(e->sli); - } - e->doc.resize(0); - e->brief.resize(0); - } -} - static void handleGuard(const QCString &expr) { CondParser prs; diff --git a/src/config.xml b/src/config.xml index 8820fe7..8e19d67 100644 --- a/src/config.xml +++ b/src/config.xml @@ -105,7 +105,6 @@ PROJECT_NAME = Example INPUT = example.cc example.h WARNINGS = YES TAGFILES = qt.tag -PERL_PATH = /usr/local/bin/perl SEARCHENGINE = NO \endverbatim @@ -120,7 +119,6 @@ INPUT = examples/examples.doc src FILE_PATTERNS = *.cc *.h INCLUDE_PATH = examples TAGFILES = qt.tag -PERL_PATH = /usr/bin/perl SEARCHENGINE = YES \endverbatim @@ -480,6 +478,17 @@ Go to the <a href="commands.html">next</a> section or return to the ]]> </docs> </option> + <option type='bool' id='JAVADOC_BANNER' defval='0'> + <docs> +<![CDATA[ + If the \c JAVADOC_BANNER tag is set to \c YES then doxygen + will interpret a line such as "/***************" as being the + beginning of a Javadoc-style comment "banner". If set to \c NO, the + Javadoc-style will behave just like regular comments and it will + not be interpreted by doxygen. +]]> + </docs> + </option> <option type='bool' id='QT_AUTOBRIEF' defval='0'> <docs> <![CDATA[ @@ -951,8 +960,8 @@ Go to the <a href="commands.html">next</a> section or return to the will only generate file names in lower-case letters. If set to \c YES, upper-case letters are also allowed. This is useful if you have classes or files whose names only differ in case and if your file system - supports case sensitive file names. Windows and Mac users are advised to set this - option to \c NO. + supports case sensitive file names. Windows (including Cygwin) ands + Mac users are advised to set this option to \c NO. ]]> </docs> </option> @@ -3229,14 +3238,6 @@ where `loc1` and `loc2` can be relative or absolute paths or URLs. ]]> </docs> </option> - <option type='string' id='PERL_PATH' format='file' defval='/usr/bin/perl' abspath='1'> - <docs> -<![CDATA[ - The \c PERL_PATH should be the absolute path and name of the perl script - interpreter (i.e. the result of `'which perl'`). -]]> - </docs> - </option> </group> <group name='Dot' docs='Configuration options related to the dot tool'> <option type='bool' id='CLASS_DIAGRAMS' defval='1'> @@ -3250,17 +3251,6 @@ where `loc1` and `loc2` can be relative or absolute paths or URLs. ]]> </docs> </option> - <option type='string' id='MSCGEN_PATH' format='dir' defval=''> - <docs> -<![CDATA[ - You can define message sequence charts within doxygen comments using the \ref cmdmsc "\\msc" - command. Doxygen will then run the <a href="http://www.mcternan.me.uk/mscgen/">mscgen tool</a>) to - produce the chart and insert it in the documentation. The <code>MSCGEN_PATH</code> tag allows you to - specify the directory where the \c mscgen tool resides. If left empty the tool is assumed to - be found in the default search path. -]]> - </docs> - </option> <option type='string' id='DIA_PATH' format='dir' defval=''> <docs> <![CDATA[ @@ -3639,5 +3629,7 @@ remove the intermediate dot files that are used to generate the various graphs. <option type='obsolete' id='SYMBOL_CACHE_SIZE'/> <option type='obsolete' id='XML_SCHEMA'/> <option type='obsolete' id='XML_DTD'/> + <option type='obsolete' id='PERL_PATH'/> + <option type='obsolete' id='MSCGEN_PATH'/> </group> </doxygenconfig> diff --git a/src/configimpl.l b/src/configimpl.l index f07509a..72c826d 100644 --- a/src/configimpl.l +++ b/src/configimpl.l @@ -699,12 +699,12 @@ static void readIncludeFile(const char *incName) %% <*>\0x0d -<PreStart>"##".*"\n" { config->appendStartComment(yytext);} +<PreStart>"##".*"\n" { config->appendStartComment(yytext);yyLineNr++;} <PreStart>. { BEGIN(Start); unput(*yytext); } -<Start,GetString,GetStrList,GetBool,SkipInvalid>"##".*"\n" { config->appendUserComment(yytext);} +<Start,GetString,GetStrList,GetBool,SkipInvalid>"##".*"\n" { config->appendUserComment(yytext);yyLineNr++;} <Start,GetString,GetStrList,GetBool,SkipInvalid>"#" { BEGIN(SkipComment); } <Start>[a-z_A-Z][a-z_A-Z0-9]*[ \t]*"=" { QCString cmd=yytext; cmd=cmd.left(cmd.length()-1).stripWhiteSpace(); @@ -1570,30 +1570,6 @@ void Config::checkAndCorrect() dotPath=""; } - // check mscgen path - QCString &mscgenPath = ConfigImpl_getString("MSCGEN_PATH"); - if (!mscgenPath.isEmpty()) - { - QFileInfo dp(mscgenPath+"/mscgen"+portable_commandExtension()); - if (!dp.exists() || !dp.isFile()) - { - warn_uncond("the mscgen tool could not be found at %s\n",mscgenPath.data()); - mscgenPath=""; - } - else - { - mscgenPath=dp.dirPath(TRUE).utf8()+"/"; -#if defined(_WIN32) // convert slashes - uint i=0,l=mscgenPath.length(); - for (i=0;i<l;i++) if (mscgenPath.at(i)=='/') mscgenPath.at(i)='\\'; -#endif - } - } - else // make sure the string is empty but not null! - { - mscgenPath=""; - } - // check plantuml path QCString &plantumlJarPath = ConfigImpl_getString("PLANTUML_JAR_PATH"); if (!plantumlJarPath.isEmpty()) diff --git a/src/constexp.h b/src/constexp.h index d84e94e..8bf582e 100644 --- a/src/constexp.h +++ b/src/constexp.h @@ -22,12 +22,21 @@ #include "cppvalue.h" #include <qcstring.h> -extern bool parseconstexp(const char *fileName,int line,const QCString &s); -extern int constexpYYparse(); -extern int constexpYYdebug; -extern QCString g_strToken; -extern CPPValue g_resultValue; -extern QCString g_constExpFileName; -extern int g_constExpLineNr; +#define YYSTYPE CPPValue +typedef void* yyscan_t; +struct constexpYY_state +{ + QCString g_strToken; + CPPValue g_resultValue; + int g_constExpLineNr; + QCString g_constExpFileName; + + const char *g_inputString; + int g_inputPosition; +}; +extern bool parseconstexp(const char *fileName,int line,const QCString &s); +extern int constexpYYparse(yyscan_t); +extern int constexpYYlex(YYSTYPE *lvalp, yyscan_t); +struct constexpYY_state* constexpYYget_extra (yyscan_t yyscanner ); #endif diff --git a/src/constexp.l b/src/constexp.l index 8a7db04..bd42104 100644 --- a/src/constexp.l +++ b/src/constexp.l @@ -17,44 +17,30 @@ */ %option never-interactive %option prefix="constexpYY" +%option nounput +%option reentrant bison-bridge +%option extra-type="struct constexpYY_state *" %{ #include "constexp.h" #include "cppvalue.h" -#include "ce_parse.h" // generated header file +#include "ce_parse.hpp" // generated header file #include "message.h" #define YY_NO_INPUT 1 #define YY_NO_UNISTD_H 1 - -QCString g_strToken; -CPPValue g_resultValue; -int g_constExpLineNr; -QCString g_constExpFileName; -static const char *g_inputString; -static int g_inputPosition; -#undef YY_INPUT -#define YY_INPUT(buf,result,max_size) result=yyread(buf,max_size); +static int yyread(char *buf,int max_size,yyscan_t yyscanner); -static int yyread(char *buf,int max_size) -{ - int c=0; - while( c < max_size && g_inputString[g_inputPosition] ) - { - *buf = g_inputString[g_inputPosition++] ; - c++; buf++; - } - return c; -} +#undef YY_INPUT +#define YY_INPUT(buf,result,max_size) result=yyread(buf,max_size,yyscanner); %} CONSTSUFFIX ([uU][lL]?[lL]?)|([lL][lL]?[uU]?) -%option nounput %% @@ -83,44 +69,73 @@ CONSTSUFFIX ([uU][lL]?[lL]?)|([lL][lL]?[uU]?) "(" { return TOK_LPAREN; } ")" { return TOK_RPAREN; } "'"(([^\'\n\r\\]+)|(\\(([ntvbrfa\\?'\"])|([0-9]+)|([xX][0-9a-fA-F]+))))"'" { - g_strToken=yytext; + yyextra->g_strToken=yytext; return TOK_CHARACTER; } -0[0-7]*{CONSTSUFFIX}? { g_strToken=yytext; +0[0-7]*{CONSTSUFFIX}? { yyextra->g_strToken=yytext; return TOK_OCTALINT; } -[1-9][0-9]*{CONSTSUFFIX}? { g_strToken=yytext; +[1-9][0-9]*{CONSTSUFFIX}? { yyextra->g_strToken=yytext; return TOK_DECIMALINT; } -(0x|0X)[0-9a-fA-F]+{CONSTSUFFIX}? { g_strToken=yytext+2; +(0x|0X)[0-9a-fA-F]+{CONSTSUFFIX}? { yyextra->g_strToken=yytext+2; return TOK_HEXADECIMALINT; } (([0-9]+\.[0-9]*)|([0-9]*\.[0-9]+))([eE]([\-\+])?[0-9]+)?([fFlL])? { - g_strToken=yytext; return TOK_FLOAT; + yyextra->g_strToken=yytext; return TOK_FLOAT; } ([0-9]+[eE])([\-\+])?[0-9]+([fFlL])? { - g_strToken=yytext; return TOK_FLOAT; + yyextra->g_strToken=yytext; return TOK_FLOAT; } . \n %% +static int yyread(char *buf,int max_size,yyscan_t yyscanner) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + int c=0; + while( c < max_size && yyextra->g_inputString[yyextra->g_inputPosition] ) + { + *buf = yyextra->g_inputString[yyextra->g_inputPosition++] ; + c++; buf++; + } + return c; +} + + +static yyscan_t yyscanner; +static struct constexpYY_state constexpYY_extra; + bool parseconstexp(const char *fileName,int lineNr,const QCString &s) { + constexpYYlex_init_extra(&constexpYY_extra, &yyscanner); + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + +#ifdef FLEX_DEBUG + yyset_debug(1,yyscanner); +#endif + + yyextra->g_constExpFileName = fileName; + yyextra->g_constExpLineNr = lineNr; + yyextra->g_inputString = s; + yyextra->g_inputPosition = 0; + constexpYYrestart( yyin, yyscanner ); + printlex(yy_flex_debug, TRUE, __FILE__, fileName); //printf("Expression: `%s'\n",s.data()); - g_constExpFileName = fileName; - g_constExpLineNr = lineNr; - g_inputString = s; - g_inputPosition = 0; - constexpYYrestart( constexpYYin ); - constexpYYparse(); + + constexpYYparse(yyscanner); + //printf("Result: %ld\n",(long)g_resultValue); printlex(yy_flex_debug, FALSE, __FILE__, fileName); - return (long)g_resultValue!=0; + bool result = (long)yyextra->g_resultValue!=0; + + constexpYYlex_destroy(yyscanner); + return result; } extern "C" { - int constexpYYwrap() { return 1; } + int constexpYYwrap(yyscan_t yyscanner) { return 1; } } diff --git a/src/constexp.y b/src/constexp.y index f87ebf3..62a51f3 100644 --- a/src/constexp.y +++ b/src/constexp.y @@ -26,24 +26,24 @@ #define MSDOS #endif -#define YYSTYPE CPPValue #include <stdio.h> #include <stdlib.h> -int constexpYYerror(const char *s) +int constexpYYerror(yyscan_t yyscanner, const char *s) { - warn(g_constExpFileName,g_constExpLineNr, + struct constexpYY_state* yyextra = constexpYYget_extra(yyscanner); + warn(yyextra->g_constExpFileName, yyextra->g_constExpLineNr, "preprocessing issue while doing constant expression evaluation: %s",s); return 0; } -int constexpYYlex(); - %} -%no-lines -%name-prefix="constexpYY" +%name-prefix "constexpYY" +%define api.pure full +%lex-param {yyscan_t yyscanner} +%parse-param {yyscan_t yyscanner} %token TOK_QUESTIONMARK %token TOK_COLON @@ -78,7 +78,10 @@ int constexpYYlex(); %% start: constant_expression - { g_resultValue = $1; return 0; } + { + struct constexpYY_state* yyextra = constexpYYget_extra(yyscanner); + yyextra->g_resultValue = $1; return 0; + } ; constant_expression: logical_or_expression @@ -267,15 +270,30 @@ primary_expression: constant ; constant: TOK_OCTALINT - { $$ = parseOctal(); } + { + struct constexpYY_state* yyextra = constexpYYget_extra(yyscanner); + $$ = parseOctal(yyextra->g_strToken); + } | TOK_DECIMALINT - { $$ = parseDecimal(); } + { + struct constexpYY_state* yyextra = constexpYYget_extra(yyscanner); + $$ = parseDecimal(yyextra->g_strToken); + } | TOK_HEXADECIMALINT - { $$ = parseHexadecimal(); } + { + struct constexpYY_state* yyextra = constexpYYget_extra(yyscanner); + $$ = parseHexadecimal(yyextra->g_strToken); + } | TOK_CHARACTER - { $$ = parseCharacter(); } + { + struct constexpYY_state* yyextra = constexpYYget_extra(yyscanner); + $$ = parseCharacter(yyextra->g_strToken); + } | TOK_FLOAT - { $$ = parseFloat(); } + { + struct constexpYY_state* yyextra = constexpYYget_extra(yyscanner); + $$ = parseFloat(yyextra->g_strToken); + } ; %% diff --git a/src/context.cpp b/src/context.cpp index e14907f..49c9afa 100644 --- a/src/context.cpp +++ b/src/context.cpp @@ -39,6 +39,12 @@ #include "latexgen.h" #include "latexdocvisitor.h" #include "dot.h" +#include "dotcallgraph.h" +#include "dotclassgraph.h" +#include "dotdirdeps.h" +#include "dotgfxhierarchytable.h" +#include "dotgroupcollaboration.h" +#include "dotincldepgraph.h" #include "diagram.h" #include "example.h" #include "membername.h" @@ -1254,7 +1260,7 @@ TemplateVariant TranslateContext::get(const char *n) const return p->get(n); } -static TemplateVariant parseDoc(Definition *def,const QCString &file,int line, +static TemplateVariant parseDoc(const Definition *def,const QCString &file,int line, const QCString &relPath,const QCString &docStr,bool isBrief) { TemplateVariant result; @@ -1324,7 +1330,7 @@ static TemplateVariant parseCode(MemberDef *md,const QCString &scopeName,const Q return TemplateVariant(s.data(),TRUE); } -static TemplateVariant parseCode(FileDef *fd,const QCString &relPath) +static TemplateVariant parseCode(const FileDef *fd,const QCString &relPath) { static bool filterSourceFiles = Config_getBool(FILTER_SOURCE_FILES); ParserInterface *pIntf = Doxygen::parserManager->getParser(fd->getDefFileExtension()); @@ -1341,7 +1347,7 @@ static TemplateVariant parseCode(FileDef *fd,const QCString &relPath) fd->getLanguage(), // lang FALSE, // isExampleBlock 0, // exampleName - fd, // fileDef + const_cast<FileDef*>(fd), // fileDef, TODO: should be const -1, // startLine -1, // endLine FALSE, // inlineFragment @@ -1360,7 +1366,7 @@ static TemplateVariant parseCode(FileDef *fd,const QCString &relPath) fd->getLanguage(), // lang FALSE, // isExampleBlock 0, // exampleName - fd, // fileDef + const_cast<FileDef*>(fd), // fileDef, TODO: should be const -1, // startLine -1, // endLine FALSE, // inlineFragment @@ -1387,7 +1393,7 @@ template<typename T> class DefinitionContext { public: - DefinitionContext(Definition *d) : m_def(d) + DefinitionContext(const Definition *d) : m_def(d) { assert(d!=0); } @@ -1574,9 +1580,9 @@ class DefinitionContext return FALSE; } } - void fillPath(Definition *def,TemplateList *list) const + void fillPath(const Definition *def,TemplateList *list) const { - Definition *outerScope = def->getOuterScope(); + const Definition *outerScope = def->getOuterScope(); Definition::DefType type = def->definitionType(); if (outerScope && outerScope!=Doxygen::globalScope) { @@ -1618,7 +1624,7 @@ class DefinitionContext protected: struct Cachable : public Definition::Cookie { - Cachable(Definition *def) : detailsOutputFormat(ContextOutputFormat_Unspecified), + Cachable(const Definition *def) : detailsOutputFormat(ContextOutputFormat_Unspecified), briefOutputFormat(ContextOutputFormat_Unspecified), inbodyDocsOutputFormat(ContextOutputFormat_Unspecified) { @@ -1675,7 +1681,7 @@ class DefinitionContext assert(c!=0); return *c; } - Definition *m_def; + const Definition *m_def; }; //%% } @@ -1810,7 +1816,7 @@ TemplateListIntf::ConstIterator *IncludeInfoListContext::createIterator() const class ClassContext::Private : public DefinitionContext<ClassContext::Private> { public: - Private(ClassDef *cd) : DefinitionContext<ClassContext::Private>(cd), + Private(const ClassDef *cd) : DefinitionContext<ClassContext::Private>(cd), m_classDef(cd) { static bool init=FALSE; @@ -1926,7 +1932,7 @@ class ClassContext::Private : public DefinitionContext<ClassContext::Private> Cachable &cache = getCache(); if (!cache.classGraph) { - cache.classGraph.reset(new DotClassGraph(m_classDef,DotNode::Inheritance)); + cache.classGraph.reset(new DotClassGraph(m_classDef,Inheritance)); } return cache.classGraph.get(); } @@ -2048,7 +2054,7 @@ class ClassContext::Private : public DefinitionContext<ClassContext::Private> Cachable &cache = getCache(); if (!cache.collaborationGraph) { - cache.collaborationGraph.reset(new DotClassGraph(m_classDef,DotNode::Collaboration)); + cache.collaborationGraph.reset(new DotClassGraph(m_classDef,Collaboration)); } return cache.collaborationGraph.get(); } @@ -2322,7 +2328,7 @@ class ClassContext::Private : public DefinitionContext<ClassContext::Private> if (m_classDef->getClassSDict()) { ClassSDict::Iterator sdi(*m_classDef->getClassSDict()); - ClassDef *cd; + const ClassDef *cd; for (sdi.toFirst();(cd=sdi.current());++sdi) { if (cd->visibleInParentsDeclList()) @@ -2344,7 +2350,7 @@ class ClassContext::Private : public DefinitionContext<ClassContext::Private> if (m_classDef->getClassSDict()) { ClassSDict::Iterator sdi(*m_classDef->getClassSDict()); - ClassDef *cd; + const ClassDef *cd; for (sdi.toFirst();(cd=sdi.current());++sdi) { if (cd->name().find('@')==-1 && @@ -2365,16 +2371,16 @@ class ClassContext::Private : public DefinitionContext<ClassContext::Private> { return m_classDef->compoundTypeString(); } - void addTemplateDecls(Definition *d,TemplateList *tl) const + void addTemplateDecls(const Definition *d,TemplateList *tl) const { if (d->definitionType()==Definition::TypeClass) { - Definition *parent = d->getOuterScope(); + const Definition *parent = d->getOuterScope(); if (parent) { addTemplateDecls(parent,tl); } - ClassDef *cd=dynamic_cast<ClassDef *>(d); + const ClassDef *cd=dynamic_cast<const ClassDef *>(d); if (cd->templateArguments()) { ArgumentListContext *al = ArgumentListContext::alloc(cd->templateArguments(),cd,relPathAsString()); @@ -2438,7 +2444,7 @@ class ClassContext::Private : public DefinitionContext<ClassContext::Private> } return cache.examples.get(); } - void addMembers(ClassDef *cd,MemberListType lt) const + void addMembers(const ClassDef *cd,MemberListType lt) const { MemberList *ml = cd->getMemberList(lt); if (ml) @@ -2595,10 +2601,10 @@ class ClassContext::Private : public DefinitionContext<ClassContext::Private> } private: - ClassDef *m_classDef; + const ClassDef *m_classDef; struct Cachable : public DefinitionContext<ClassContext::Private>::Cachable { - Cachable(ClassDef *cd) : DefinitionContext<ClassContext::Private>::Cachable(cd), + Cachable(const ClassDef *cd) : DefinitionContext<ClassContext::Private>::Cachable(cd), inheritanceNodes(-1) { } SharedPtr<IncludeInfoContext> includeInfo; SharedPtr<InheritanceListContext> inheritsList; @@ -2672,7 +2678,7 @@ class ClassContext::Private : public DefinitionContext<ClassContext::Private> PropertyMapper<ClassContext::Private> ClassContext::Private::s_inst; -ClassContext::ClassContext(ClassDef *cd) : RefCountedContext("ClassContext") +ClassContext::ClassContext(const ClassDef *cd) : RefCountedContext("ClassContext") { //printf("ClassContext::ClassContext(%s)\n",cd?cd->name().data():"<none>"); p = new Private(cd); @@ -2695,7 +2701,7 @@ TemplateVariant ClassContext::get(const char *n) const class NamespaceContext::Private : public DefinitionContext<NamespaceContext::Private> { public: - Private(NamespaceDef *nd) : DefinitionContext<NamespaceContext::Private>(nd), + Private(const NamespaceDef *nd) : DefinitionContext<NamespaceContext::Private>(nd), m_namespaceDef(nd) { static bool init=FALSE; @@ -2764,7 +2770,7 @@ class NamespaceContext::Private : public DefinitionContext<NamespaceContext::Pri if (m_namespaceDef->getClassSDict()) { ClassSDict::Iterator sdi(*m_namespaceDef->getClassSDict()); - ClassDef *cd; + const ClassDef *cd; for (sdi.toFirst();(cd=sdi.current());++sdi) { if (sliceOpt && (cd->compoundType()==ClassDef::Struct || @@ -2792,7 +2798,7 @@ class NamespaceContext::Private : public DefinitionContext<NamespaceContext::Pri if (m_namespaceDef->getNamespaceSDict()) { NamespaceSDict::Iterator sdi(*m_namespaceDef->getNamespaceSDict()); - NamespaceDef *nd; + const NamespaceDef *nd; for (sdi.toFirst();(nd=sdi.current());++sdi) { if (nd->isLinkable() && !nd->isConstantGroup()) @@ -2814,7 +2820,7 @@ class NamespaceContext::Private : public DefinitionContext<NamespaceContext::Pri if (m_namespaceDef->getNamespaceSDict()) { NamespaceSDict::Iterator sdi(*m_namespaceDef->getNamespaceSDict()); - NamespaceDef *nd; + const NamespaceDef *nd; for (sdi.toFirst();(nd=sdi.current());++sdi) { if (nd->isLinkable() && nd->isConstantGroup()) @@ -2932,7 +2938,7 @@ class NamespaceContext::Private : public DefinitionContext<NamespaceContext::Pri if (m_namespaceDef->getClassSDict()) { ClassSDict::Iterator sdi(*m_namespaceDef->getClassSDict()); - ClassDef *cd; + const ClassDef *cd; for (sdi.toFirst();(cd=sdi.current());++sdi) { if (cd->name().find('@')==-1 && @@ -2949,10 +2955,10 @@ class NamespaceContext::Private : public DefinitionContext<NamespaceContext::Pri return cache.inlineClasses.get(); } private: - NamespaceDef *m_namespaceDef; + const NamespaceDef *m_namespaceDef; struct Cachable : public DefinitionContext<NamespaceContext::Private>::Cachable { - Cachable(NamespaceDef *nd) : DefinitionContext<NamespaceContext::Private>::Cachable(nd) {} + Cachable(const NamespaceDef *nd) : DefinitionContext<NamespaceContext::Private>::Cachable(nd) {} SharedPtr<TemplateList> classes; SharedPtr<TemplateList> interfaces; SharedPtr<TemplateList> namespaces; @@ -2984,7 +2990,7 @@ class NamespaceContext::Private : public DefinitionContext<NamespaceContext::Pri PropertyMapper<NamespaceContext::Private> NamespaceContext::Private::s_inst; -NamespaceContext::NamespaceContext(NamespaceDef *nd) : RefCountedContext("NamespaceContext") +NamespaceContext::NamespaceContext(const NamespaceDef *nd) : RefCountedContext("NamespaceContext") { p = new Private(nd); } @@ -3006,7 +3012,7 @@ TemplateVariant NamespaceContext::get(const char *n) const class FileContext::Private : public DefinitionContext<FileContext::Private> { public: - Private(FileDef *fd) : DefinitionContext<FileContext::Private>(fd) , m_fileDef(fd) + Private(const FileDef *fd) : DefinitionContext<FileContext::Private>(fd) , m_fileDef(fd) { if (fd==0) abort(); static bool init=FALSE; @@ -3229,7 +3235,7 @@ class FileContext::Private : public DefinitionContext<FileContext::Private> if (m_fileDef->getClassSDict()) { ClassSDict::Iterator sdi(*m_fileDef->getClassSDict()); - ClassDef *cd; + const ClassDef *cd; for (sdi.toFirst();(cd=sdi.current());++sdi) { if (cd->visibleInParentsDeclList()) @@ -3251,7 +3257,7 @@ class FileContext::Private : public DefinitionContext<FileContext::Private> if (m_fileDef->getNamespaceSDict()) { NamespaceSDict::Iterator sdi(*m_fileDef->getNamespaceSDict()); - NamespaceDef *nd; + const NamespaceDef *nd; for (sdi.toFirst();(nd=sdi.current());++sdi) { if (nd->isLinkable() && !nd->isConstantGroup()) @@ -3396,7 +3402,7 @@ class FileContext::Private : public DefinitionContext<FileContext::Private> if (m_fileDef->getClassSDict()) { ClassSDict::Iterator sdi(*m_fileDef->getClassSDict()); - ClassDef *cd; + const ClassDef *cd; for (sdi.toFirst();(cd=sdi.current());++sdi) { if (cd->name().find('@')==-1 && @@ -3418,10 +3424,10 @@ class FileContext::Private : public DefinitionContext<FileContext::Private> } private: - FileDef *m_fileDef; + const FileDef *m_fileDef; struct Cachable : public DefinitionContext<FileContext::Private>::Cachable { - Cachable(FileDef *fd) : DefinitionContext<FileContext::Private>::Cachable(fd) {} + Cachable(const FileDef *fd) : DefinitionContext<FileContext::Private>::Cachable(fd) {} SharedPtr<IncludeInfoListContext> includeInfoList; ScopedPtr<DotInclDepGraph> includeGraph; ScopedPtr<DotInclDepGraph> includedByGraph; @@ -3458,7 +3464,7 @@ class FileContext::Private : public DefinitionContext<FileContext::Private> PropertyMapper<FileContext::Private> FileContext::Private::s_inst; -FileContext::FileContext(FileDef *fd) : RefCountedContext("FileContext") +FileContext::FileContext(const FileDef *fd) : RefCountedContext("FileContext") { p = new Private(fd); } @@ -3480,7 +3486,7 @@ TemplateVariant FileContext::get(const char *n) const class DirContext::Private : public DefinitionContext<DirContext::Private> { public: - Private(DirDef *dd) : DefinitionContext<DirContext::Private>(dd) , m_dirDef(dd) + Private(const DirDef *dd) : DefinitionContext<DirContext::Private>(dd) , m_dirDef(dd) { static bool init=FALSE; if (!init) @@ -3529,7 +3535,7 @@ class DirContext::Private : public DefinitionContext<DirContext::Private> cache.dirs.reset(TemplateList::alloc()); const DirList &subDirs = m_dirDef->subDirs(); QListIterator<DirDef> it(subDirs); - DirDef *dd; + const DirDef *dd; for (it.toFirst();(dd=it.current());++it) { DirContext *dc = new DirContext(dd); @@ -3548,7 +3554,7 @@ class DirContext::Private : public DefinitionContext<DirContext::Private> if (files) { QListIterator<FileDef> it(*files); - FileDef *fd; + const FileDef *fd; for (it.toFirst();(fd=it.current());++it) { FileContext *fc = FileContext::alloc(fd); @@ -3637,10 +3643,10 @@ class DirContext::Private : public DefinitionContext<DirContext::Private> } private: - DirDef *m_dirDef; + const DirDef *m_dirDef; struct Cachable : public DefinitionContext<DirContext::Private>::Cachable { - Cachable(DirDef *dd) : DefinitionContext<DirContext::Private>::Cachable(dd) {} + Cachable(const DirDef *dd) : DefinitionContext<DirContext::Private>::Cachable(dd) {} SharedPtr<TemplateList> dirs; SharedPtr<TemplateList> files; ScopedPtr<DotDirDeps> dirDepsGraph; @@ -3657,7 +3663,7 @@ class DirContext::Private : public DefinitionContext<DirContext::Private> PropertyMapper<DirContext::Private> DirContext::Private::s_inst; -DirContext::DirContext(DirDef *fd) : RefCountedContext("DirContext") +DirContext::DirContext(const DirDef *fd) : RefCountedContext("DirContext") { p = new Private(fd); } @@ -3679,7 +3685,7 @@ TemplateVariant DirContext::get(const char *n) const class PageContext::Private : public DefinitionContext<PageContext::Private> { public: - Private(PageDef *pd,bool isMainPage,bool isExample) + Private(const PageDef *pd,bool isMainPage,bool isExample) : DefinitionContext<PageContext::Private>(pd) , m_pageDef(pd), m_isMainPage(isMainPage), m_isExample(isExample) { @@ -3768,10 +3774,10 @@ class PageContext::Private : public DefinitionContext<PageContext::Private> } } private: - PageDef *m_pageDef; + const PageDef *m_pageDef; struct Cachable : public DefinitionContext<PageContext::Private>::Cachable { - Cachable(PageDef *pd) : DefinitionContext<PageContext::Private>::Cachable(pd), + Cachable(const PageDef *pd) : DefinitionContext<PageContext::Private>::Cachable(pd), exampleOutputFormat(ContextOutputFormat_Unspecified) { } ScopedPtr<TemplateVariant> example; ContextOutputFormat exampleOutputFormat; @@ -3790,7 +3796,7 @@ class PageContext::Private : public DefinitionContext<PageContext::Private> PropertyMapper<PageContext::Private> PageContext::Private::s_inst; -PageContext::PageContext(PageDef *pd,bool isMainPage,bool isExample) : RefCountedContext("PageContext") +PageContext::PageContext(const PageDef *pd,bool isMainPage,bool isExample) : RefCountedContext("PageContext") { p = new Private(pd,isMainPage,isExample); } @@ -3949,7 +3955,7 @@ class TextGeneratorFactory virtual ~TextGeneratorFactory() {} }; -TemplateVariant createLinkedText(Definition *def,const QCString &relPath,const QCString &text) +TemplateVariant createLinkedText(const Definition *def,const QCString &relPath,const QCString &text) { QGString s; FTextStream ts(&s); @@ -4023,7 +4029,7 @@ class MemberContext::Private : public DefinitionContext<MemberContext::Private> s_inst.addProperty("isSealed", &Private::isSealed); s_inst.addProperty("isImplementation", &Private::isImplementation); s_inst.addProperty("isExternal", &Private::isExternal); - s_inst.addProperty("isAlias", &Private::isAlias); + s_inst.addProperty("isTypeAlias", &Private::isTypeAlias); s_inst.addProperty("isDefault", &Private::isDefault); s_inst.addProperty("isDelete", &Private::isDelete); s_inst.addProperty("isNoExcept", &Private::isNoExcept); @@ -4334,9 +4340,9 @@ class MemberContext::Private : public DefinitionContext<MemberContext::Private> { return m_memberDef->isExternal(); } - TemplateVariant isAlias() const + TemplateVariant isTypeAlias() const { - return m_memberDef->isAlias(); + return m_memberDef->isTypeAlias(); } TemplateVariant isDefault() const { @@ -4452,7 +4458,7 @@ class MemberContext::Private : public DefinitionContext<MemberContext::Private> Cachable &cache = getCache(); if (!cache.anonymousType) { - ClassDef *cd = m_memberDef->getClassDefOfAnonymousType(); + const ClassDef *cd = m_memberDef->getClassDefOfAnonymousType(); if (cd) { cache.anonymousType.reset(ClassContext::alloc(cd)); @@ -4508,7 +4514,7 @@ class MemberContext::Private : public DefinitionContext<MemberContext::Private> Cachable &cache = getCache(); if (!cache.enumValues) { - MemberList *ml = m_memberDef->enumFieldList(); + const MemberList *ml = m_memberDef->enumFieldList(); if (ml) { cache.enumValues.reset(MemberListContext::alloc(ml)); @@ -4538,7 +4544,7 @@ class MemberContext::Private : public DefinitionContext<MemberContext::Private> } TemplateVariant templateAlias() const { - if (m_memberDef->isAlias()) + if (m_memberDef->isTypeAlias()) { return createLinkedText(m_memberDef,relPathAsString(), QCString(" = ")+m_memberDef->typeString()); @@ -4638,7 +4644,7 @@ class MemberContext::Private : public DefinitionContext<MemberContext::Private> return createLinkedText(m_memberDef,relPathAsString(), m_memberDef->displayDefinition()); } - ArgumentList *getDefArgList() const + const ArgumentList *getDefArgList() const { return (m_memberDef->isDocsForDefinition()) ? m_memberDef->argumentList() : m_memberDef->declArgumentList(); @@ -4648,7 +4654,7 @@ class MemberContext::Private : public DefinitionContext<MemberContext::Private> Cachable &cache = getCache(); if (!cache.arguments) { - ArgumentList *defArgList = getDefArgList(); + const ArgumentList *defArgList = getDefArgList(); if (defArgList && !m_memberDef->isProperty()) { cache.arguments.reset(ArgumentListContext::alloc(defArgList,m_memberDef,relPathAsString())); @@ -4666,27 +4672,27 @@ class MemberContext::Private : public DefinitionContext<MemberContext::Private> } TemplateVariant hasConstQualifier() const { - ArgumentList *al = getDefArgList(); + const ArgumentList *al = getDefArgList(); return al ? al->constSpecifier : FALSE; } TemplateVariant hasVolatileQualifier() const { - ArgumentList *al = getDefArgList(); + const ArgumentList *al = getDefArgList(); return al ? al->volatileSpecifier : FALSE; } TemplateVariant hasRefQualifierLValue() const { - ArgumentList *al = getDefArgList(); + const ArgumentList *al = getDefArgList(); return al ? al->refQualifier==RefQualifierLValue : FALSE; } TemplateVariant hasRefQualifierRValue() const { - ArgumentList *al = getDefArgList(); + const ArgumentList *al = getDefArgList(); return al ? al->refQualifier==RefQualifierRValue : FALSE; } TemplateVariant trailingReturnType() const { - ArgumentList *al = getDefArgList(); + const ArgumentList *al = getDefArgList(); if (al && !al->trailingReturnType.isEmpty()) { return createLinkedText(m_memberDef,relPathAsString(), @@ -4703,7 +4709,7 @@ class MemberContext::Private : public DefinitionContext<MemberContext::Private> } void addTemplateDecls(TemplateList *tl) const { - ClassDef *cd=m_memberDef->getClassDef(); + const ClassDef *cd=m_memberDef->getClassDef(); if (m_memberDef->definitionTemplateParameterLists()) { QListIterator<ArgumentList> ali(*m_memberDef->definitionTemplateParameterLists()); @@ -4813,7 +4819,7 @@ class MemberContext::Private : public DefinitionContext<MemberContext::Private> cache.implements.reset(TemplateList::alloc()); if (md) { - ClassDef *cd = md->getClassDef(); + const ClassDef *cd = md->getClassDef(); if (cd && (md->virtualness()==Pure || cd->compoundType()==ClassDef::Interface)) { MemberContext *mc = MemberContext::alloc(md); @@ -4832,7 +4838,7 @@ class MemberContext::Private : public DefinitionContext<MemberContext::Private> cache.reimplements.reset(TemplateList::alloc()); if (md) { - ClassDef *cd = md->getClassDef(); + const ClassDef *cd = md->getClassDef(); if (cd && md->virtualness()!=Pure && cd->compoundType()!=ClassDef::Interface) { MemberContext *mc = MemberContext::alloc(md); @@ -4855,7 +4861,7 @@ class MemberContext::Private : public DefinitionContext<MemberContext::Private> MemberDef *md=0; for (mli.toFirst();(md=mli.current());++mli) { - ClassDef *cd = md->getClassDef(); + const ClassDef *cd = md->getClassDef(); if (cd && (md->virtualness()==Pure || cd->compoundType()==ClassDef::Interface)) { MemberContext *mc = new MemberContext(md); @@ -4879,7 +4885,7 @@ class MemberContext::Private : public DefinitionContext<MemberContext::Private> MemberDef *md=0; for (mli.toFirst();(md=mli.current());++mli) { - ClassDef *cd = md->getClassDef(); + const ClassDef *cd = md->getClassDef(); if (cd && md->virtualness()!=Pure && cd->compoundType()!=ClassDef::Interface) { MemberContext *mc = new MemberContext(md); @@ -4976,7 +4982,7 @@ class MemberContext::Private : public DefinitionContext<MemberContext::Private> if (!cache.sourceCodeParsed) { QCString codeFragment; - FileDef *fd = m_memberDef->getBodyDef(); + const FileDef *fd = m_memberDef->getBodyDef(); int startLine = m_memberDef->getStartBodyLine(); int endLine = m_memberDef->getEndBodyLine(); if (fd && readCodeFragment(fd->absFilePath(), @@ -5271,7 +5277,7 @@ TemplateVariant MemberContext::get(const char *n) const class ModuleContext::Private : public DefinitionContext<ModuleContext::Private> { public: - Private(GroupDef *gd) : DefinitionContext<ModuleContext::Private>(gd) , m_groupDef(gd) + Private(const GroupDef *gd) : DefinitionContext<ModuleContext::Private>(gd) , m_groupDef(gd) { static bool init=FALSE; if (!init) @@ -5416,7 +5422,7 @@ class ModuleContext::Private : public DefinitionContext<ModuleContext::Private> if (m_groupDef->getSubGroups()) { GroupListIterator gli(*m_groupDef->getSubGroups()); - GroupDef *gd; + const GroupDef *gd; for (gli.toFirst();(gd=gli.current());++gli) { if (gd->isVisible()) @@ -5438,7 +5444,7 @@ class ModuleContext::Private : public DefinitionContext<ModuleContext::Private> if (m_groupDef->getExamples()) { PageSDict::Iterator eli(*m_groupDef->getExamples()); - PageDef *ex; + const PageDef *ex; for (eli.toFirst();(ex=eli.current());++eli) { exampleList->append(PageContext::alloc(ex,FALSE,TRUE)); @@ -5457,7 +5463,7 @@ class ModuleContext::Private : public DefinitionContext<ModuleContext::Private> if (m_groupDef->getExamples()) { PageSDict::Iterator eli(*m_groupDef->getPages()); - PageDef *ex; + const PageDef *ex; for (eli.toFirst();(ex=eli.current());++eli) { pageList->append(PageContext::alloc(ex,FALSE,TRUE)); @@ -5476,7 +5482,7 @@ class ModuleContext::Private : public DefinitionContext<ModuleContext::Private> if (m_groupDef->getDirs()) { QListIterator<DirDef> it(*m_groupDef->getDirs()); - DirDef *dd; + const DirDef *dd; for (it.toFirst();(dd=it.current());++it) { dirList->append(DirContext::alloc(dd)); @@ -5495,7 +5501,7 @@ class ModuleContext::Private : public DefinitionContext<ModuleContext::Private> if (m_groupDef->getFiles()) { QListIterator<FileDef> it(*m_groupDef->getFiles()); - FileDef *fd; + const FileDef *fd; for (it.toFirst();(fd=it.current());++it) { fileList->append(FileContext::alloc(fd)); @@ -5514,7 +5520,7 @@ class ModuleContext::Private : public DefinitionContext<ModuleContext::Private> if (m_groupDef->getClasses()) { ClassSDict::Iterator sdi(*m_groupDef->getClasses()); - ClassDef *cd; + const ClassDef *cd; for (sdi.toFirst();(cd=sdi.current());++sdi) { if (cd->visibleInParentsDeclList()) @@ -5536,7 +5542,7 @@ class ModuleContext::Private : public DefinitionContext<ModuleContext::Private> if (m_groupDef->getNamespaces()) { NamespaceSDict::Iterator sdi(*m_groupDef->getNamespaces()); - NamespaceDef *nd; + const NamespaceDef *nd; for (sdi.toFirst();(nd=sdi.current());++sdi) { if (nd->isLinkable() && !nd->isConstantGroup()) @@ -5730,7 +5736,7 @@ class ModuleContext::Private : public DefinitionContext<ModuleContext::Private> if (m_groupDef->getClasses()) { ClassSDict::Iterator sdi(*m_groupDef->getClasses()); - ClassDef *cd; + const ClassDef *cd; for (sdi.toFirst();(cd=sdi.current());++sdi) { if (cd->name().find('@')==-1 && @@ -5751,10 +5757,10 @@ class ModuleContext::Private : public DefinitionContext<ModuleContext::Private> return "module"; //theTranslator->trGroup(FALSE,TRUE); } private: - GroupDef *m_groupDef; + const GroupDef *m_groupDef; struct Cachable : public DefinitionContext<ModuleContext::Private>::Cachable { - Cachable(GroupDef *gd) : DefinitionContext<ModuleContext::Private>::Cachable(gd) {} + Cachable(const GroupDef *gd) : DefinitionContext<ModuleContext::Private>::Cachable(gd) {} SharedPtr<TemplateList> modules; SharedPtr<TemplateList> dirs; SharedPtr<TemplateList> files; @@ -5805,7 +5811,7 @@ class ModuleContext::Private : public DefinitionContext<ModuleContext::Private> PropertyMapper<ModuleContext::Private> ModuleContext::Private::s_inst; -ModuleContext::ModuleContext(GroupDef *gd) : RefCountedContext("ModuleContext") +ModuleContext::ModuleContext(const GroupDef *gd) : RefCountedContext("ModuleContext") { p = new Private(gd); } @@ -5829,7 +5835,7 @@ class ClassListContext::Private : public GenericNodeListContext void addClasses(const ClassSDict &classSDict) { ClassSDict::Iterator cli(classSDict); - ClassDef *cd; + const ClassDef *cd; for (cli.toFirst() ; (cd=cli.current()) ; ++cli ) { if (cd->getLanguage()==SrcLangExt_VHDL && @@ -5908,7 +5914,7 @@ class ClassIndexContext::Private if (Doxygen::classSDict) { ClassSDict::Iterator cli(*Doxygen::classSDict); - ClassDef *cd; + const ClassDef *cd; for (cli.toFirst() ; (cd=cli.current()) ; ++cli ) { if (cd->getLanguage()==SrcLangExt_VHDL && @@ -6216,7 +6222,7 @@ class NestingNodeContext::Private { public: Private(const NestingNodeContext *parent,const NestingNodeContext *thisNode, - Definition *d,int index,int level,bool addCls,bool inherit, bool hideSuper) + const Definition *d,int index,int level,bool addCls,bool inherit, bool hideSuper) : m_parent(parent), m_def(d), m_level(level), m_index(index) { m_children.reset(NestingContext::alloc(thisNode,level+1)); @@ -6278,7 +6284,7 @@ class NestingNodeContext::Private { if (!m_cache.classContext && m_def->definitionType()==Definition::TypeClass) { - m_cache.classContext.reset(ClassContext::alloc(dynamic_cast<ClassDef*>(m_def))); + m_cache.classContext.reset(ClassContext::alloc(dynamic_cast<const ClassDef*>(m_def))); } if (m_cache.classContext) { @@ -6293,7 +6299,7 @@ class NestingNodeContext::Private { if (!m_cache.namespaceContext && m_def->definitionType()==Definition::TypeNamespace) { - m_cache.namespaceContext.reset(NamespaceContext::alloc(dynamic_cast<NamespaceDef*>(m_def))); + m_cache.namespaceContext.reset(NamespaceContext::alloc(dynamic_cast<const NamespaceDef*>(m_def))); } if (m_cache.namespaceContext) { @@ -6308,7 +6314,7 @@ class NestingNodeContext::Private { if (!m_cache.dirContext && m_def->definitionType()==Definition::TypeDir) { - m_cache.dirContext.reset(DirContext::alloc(dynamic_cast<DirDef*>(m_def))); + m_cache.dirContext.reset(DirContext::alloc(dynamic_cast<const DirDef*>(m_def))); } if (m_cache.dirContext) { @@ -6323,7 +6329,7 @@ class NestingNodeContext::Private { if (!m_cache.fileContext && m_def->definitionType()==Definition::TypeFile) { - m_cache.fileContext.reset(FileContext::alloc(dynamic_cast<FileDef*>(m_def))); + m_cache.fileContext.reset(FileContext::alloc(dynamic_cast<const FileDef*>(m_def))); } if (m_cache.fileContext) { @@ -6338,7 +6344,7 @@ class NestingNodeContext::Private { if (!m_cache.pageContext && m_def->definitionType()==Definition::TypePage) { - m_cache.pageContext.reset(PageContext::alloc(dynamic_cast<PageDef*>(m_def),FALSE,FALSE)); + m_cache.pageContext.reset(PageContext::alloc(dynamic_cast<const PageDef*>(m_def),FALSE,FALSE)); } if (m_cache.pageContext) { @@ -6353,7 +6359,7 @@ class NestingNodeContext::Private { if (!m_cache.moduleContext && m_def->definitionType()==Definition::TypeGroup) { - m_cache.moduleContext.reset(ModuleContext::alloc(dynamic_cast<GroupDef*>(m_def))); + m_cache.moduleContext.reset(ModuleContext::alloc(dynamic_cast<const GroupDef*>(m_def))); } if (m_cache.moduleContext) { @@ -6425,7 +6431,7 @@ class NestingNodeContext::Private void addClasses(bool inherit, bool hideSuper) { - ClassDef *cd = dynamic_cast<ClassDef*>(m_def); + const ClassDef *cd = dynamic_cast<const ClassDef*>(m_def); if (cd && inherit) { bool hasChildren = !cd->isVisited() && !hideSuper && classHasVisibleChildren(cd); @@ -6453,7 +6459,7 @@ class NestingNodeContext::Private } void addNamespaces(bool addClasses) { - NamespaceDef *nd = dynamic_cast<NamespaceDef*>(m_def); + const NamespaceDef *nd = dynamic_cast<const NamespaceDef*>(m_def); if (nd && nd->getNamespaceSDict()) { m_children->addNamespaces(*nd->getNamespaceSDict(),FALSE,addClasses); @@ -6465,7 +6471,7 @@ class NestingNodeContext::Private } void addDirFiles() { - DirDef *dd = dynamic_cast<DirDef*>(m_def); + const DirDef *dd = dynamic_cast<const DirDef*>(m_def); if (dd) { m_children->addDirs(dd->subDirs()); @@ -6477,7 +6483,7 @@ class NestingNodeContext::Private } void addPages() { - PageDef *pd = dynamic_cast<PageDef*>(m_def); + const PageDef *pd = dynamic_cast<const PageDef*>(m_def); if (pd && pd->getSubPages()) { m_children->addPages(*pd->getSubPages(),FALSE); @@ -6485,7 +6491,7 @@ class NestingNodeContext::Private } void addModules() { - GroupDef *gd = dynamic_cast<GroupDef*>(m_def); + const GroupDef *gd = dynamic_cast<const GroupDef*>(m_def); if (gd && gd->getSubGroups()) { m_children->addModules(*gd->getSubGroups()); @@ -6493,7 +6499,7 @@ class NestingNodeContext::Private } private: const NestingNodeContext *m_parent; - Definition *m_def; + const Definition *m_def; SharedPtr<NestingContext> m_children; int m_level; int m_index; @@ -6515,7 +6521,7 @@ class NestingNodeContext::Private PropertyMapper<NestingNodeContext::Private> NestingNodeContext::Private::s_inst; NestingNodeContext::NestingNodeContext(const NestingNodeContext *parent, - Definition *d,int index,int level,bool addClass,bool inherit,bool hideSuper) + const Definition *d,int index,int level,bool addClass,bool inherit,bool hideSuper) : RefCountedContext("NestingNodeContext") { p = new Private(parent,this,d,index,level,addClass,inherit,hideSuper); @@ -6548,7 +6554,7 @@ class NestingContext::Private : public GenericNodeListContext void addNamespaces(const NamespaceSDict &nsDict,bool rootOnly,bool addClasses) { NamespaceSDict::Iterator nli(nsDict); - NamespaceDef *nd; + const NamespaceDef *nd; for (nli.toFirst();(nd=nli.current());++nli) { if (nd->localName().find('@')==-1 && @@ -6568,7 +6574,7 @@ class NestingContext::Private : public GenericNodeListContext void addClasses(const ClassSDict &clDict,bool rootOnly) { ClassSDict::Iterator cli(clDict); - ClassDef *cd; + const ClassDef *cd; for (;(cd=cli.current());++cli) { if (cd->getLanguage()==SrcLangExt_VHDL) @@ -6597,7 +6603,7 @@ class NestingContext::Private : public GenericNodeListContext void addDirs(const DirSDict &dirDict) { SDict<DirDef>::Iterator dli(dirDict); - DirDef *dd; + const DirDef *dd; for (dli.toFirst();(dd=dli.current());++dli) { if (dd->getOuterScope()==Doxygen::globalScope) @@ -6610,7 +6616,7 @@ class NestingContext::Private : public GenericNodeListContext void addDirs(const DirList &dirList) { QListIterator<DirDef> li(dirList); - DirDef *dd; + const DirDef *dd; for (li.toFirst();(dd=li.current());++li) { append(NestingNodeContext::alloc(m_parent,dd,m_index,m_level,FALSE,FALSE,FALSE)); @@ -6624,7 +6630,7 @@ class NestingContext::Private : public GenericNodeListContext for (fnli.toFirst();(fn=fnli.current());++fnli) { FileNameIterator fni(*fn); - FileDef *fd; + const FileDef *fd; for (;(fd=fni.current());++fni) { if (fd->getDirDef()==0) // top level file @@ -6638,7 +6644,7 @@ class NestingContext::Private : public GenericNodeListContext void addFiles(const FileList &fList) { QListIterator<FileDef> li(fList); - FileDef *fd; + const FileDef *fd; for (li.toFirst();(fd=li.current());++li) { append(NestingNodeContext::alloc(m_parent,fd,m_index,m_level,FALSE,FALSE,FALSE)); @@ -6648,7 +6654,7 @@ class NestingContext::Private : public GenericNodeListContext void addPages(const PageSDict &pages,bool rootOnly) { SDict<PageDef>::Iterator pli(pages); - PageDef *pd; + const PageDef *pd; for (pli.toFirst();(pd=pli.current());++pli) { if (!rootOnly || @@ -6663,7 +6669,7 @@ class NestingContext::Private : public GenericNodeListContext void addModules(const GroupSDict &groups) { GroupSDict::Iterator gli(groups); - GroupDef *gd; + const GroupDef *gd; for (gli.toFirst();(gd=gli.current());++gli) { static bool externalGroups = Config_getBool(EXTERNAL_GROUPS); @@ -6679,7 +6685,7 @@ class NestingContext::Private : public GenericNodeListContext void addModules(const GroupList &list) { GroupListIterator gli(list); - GroupDef *gd; + const GroupDef *gd; for (gli.toFirst();(gd=gli.current());++gli) { if (gd->isVisible()) @@ -6696,7 +6702,7 @@ class NestingContext::Private : public GenericNodeListContext BaseClassDef *bcd; for (bcli.toFirst() ; (bcd=bcli.current()) ; ++bcli) { - ClassDef *cd=bcd->classDef; + const ClassDef *cd=bcd->classDef; if (cd->getLanguage()==SrcLangExt_VHDL && (VhdlDocGen::VhdlClasses)cd->protection()!=VhdlDocGen::ENTITYCLASS) { continue; @@ -6723,7 +6729,7 @@ class NestingContext::Private : public GenericNodeListContext void addClassHierarchy(const ClassSDict &classSDict,bool) { ClassSDict::Iterator cli(classSDict); - ClassDef *cd; + const ClassDef *cd; for (cli.toFirst();(cd=cli.current());++cli) { bool b; @@ -6973,7 +6979,7 @@ class NamespaceListContext::Private : public GenericNodeListContext void addNamespaces(const NamespaceSDict &nsDict) { NamespaceSDict::Iterator nli(nsDict); - NamespaceDef *nd; + const NamespaceDef *nd; for (nli.toFirst();(nd=nli.current());++nli) { if (nd->isLinkableInProject()) @@ -7148,7 +7154,7 @@ class FileListContext::Private : public GenericNodeListContext for (fnli.toFirst();(fn=fnli.current());++fnli) { FileNameIterator fni(*fn); - FileDef *fd; + const FileDef *fd; for (fni.toFirst();(fd=fni.current());++fni) { bool doc = fd->isLinkableInProject(); @@ -7198,7 +7204,7 @@ class DirListContext::Private : public GenericNodeListContext public: Private() { - DirDef *dir; + const DirDef *dir; DirSDict::Iterator sdi(*Doxygen::directories); for (sdi.toFirst();(dir=sdi.current());++sdi) { @@ -7240,19 +7246,19 @@ TemplateListIntf::ConstIterator *DirListContext::createIterator() const class UsedFilesContext::Private : public GenericNodeListContext { public: - void addFile(FileDef *fd) + void addFile(const FileDef *fd) { append(FileContext::alloc(fd)); } }; -UsedFilesContext::UsedFilesContext(ClassDef *cd) : RefCountedContext("UsedFilesContext") +UsedFilesContext::UsedFilesContext(const ClassDef *cd) : RefCountedContext("UsedFilesContext") { p = new Private; if (cd) { QListIterator<FileDef> li(cd->usedFiles()); - FileDef *fd; + const FileDef *fd; for (li.toFirst();(fd=li.current());++li) { p->addFile(fd); @@ -7281,7 +7287,7 @@ TemplateListIntf::ConstIterator *UsedFilesContext::createIterator() const return p->createIterator(); } -void UsedFilesContext::addFile(FileDef *fd) +void UsedFilesContext::addFile(const FileDef *fd) { p->addFile(fd); } @@ -7518,7 +7524,7 @@ class PageListContext::Private : public GenericNodeListContext void addPages(const PageSDict &pages) { PageSDict::Iterator pdi(pages); - PageDef *pd=0; + const PageDef *pd=0; for (pdi.toFirst();(pd=pdi.current());++pdi) { if (!pd->getGroupDef() && !pd->isReference()) @@ -7567,7 +7573,7 @@ class ExampleListContext::Private : public GenericNodeListContext if (Doxygen::exampleSDict) { PageSDict::Iterator pdi(*Doxygen::exampleSDict); - PageDef *pd=0; + const PageDef *pd=0; for (pdi.toFirst();(pd=pdi.current());++pdi) { if (!pd->getGroupDef() && !pd->isReference()) @@ -7614,7 +7620,7 @@ class ModuleListContext::Private : public GenericNodeListContext void addModules() { GroupSDict::Iterator gli(*Doxygen::groupSDict); - GroupDef *gd; + const GroupDef *gd; for (gli.toFirst();(gd=gli.current());++gli) { if (!gd->isReference()) @@ -7769,7 +7775,7 @@ TemplateVariant ModuleTreeContext::get(const char *name) const class NavPathElemContext::Private { public: - Private(Definition *def) : m_def(def) + Private(const Definition *def) : m_def(def) { static bool init=FALSE; if (!init) @@ -7834,14 +7840,14 @@ class NavPathElemContext::Private return m_def->externalReference(relPathAsString()); } private: - Definition *m_def; + const Definition *m_def; static PropertyMapper<NavPathElemContext::Private> s_inst; }; //%% } PropertyMapper<NavPathElemContext::Private> NavPathElemContext::Private::s_inst; -NavPathElemContext::NavPathElemContext(Definition *def) : RefCountedContext("NavPathElemContext") +NavPathElemContext::NavPathElemContext(const Definition *def) : RefCountedContext("NavPathElemContext") { p = new Private(def); } @@ -8014,7 +8020,7 @@ class GlobalsIndexContext::Private MemberNameIterator mni(*mn); for (mni.toFirst();(md=mni.current());++mni) { - FileDef *fd=md->getFileDef(); + const FileDef *fd=md->getFileDef(); if (fd && fd->isLinkableInProject() && !md->name().isEmpty() && !md->getNamespaceDef() && md->isLinkableInProject()) { @@ -8171,7 +8177,7 @@ class ClassMembersIndexContext::Private MemberNameIterator mni(*mn); for (mni.toFirst();(md=mni.current());++mni) { - ClassDef *cd = md->getClassDef(); + const ClassDef *cd = md->getClassDef(); if (cd && cd->isLinkableInProject() && cd->templateMaster()==0 && md->isLinkableInProject() && !md->name().isEmpty()) { @@ -8330,7 +8336,7 @@ class NamespaceMembersIndexContext::Private MemberNameIterator mni(*mn); for (mni.toFirst();(md=mni.current());++mni) { - NamespaceDef *nd=md->getNamespaceDef(); + const NamespaceDef *nd=md->getNamespaceDef(); if (nd && nd->isLinkableInProject() && !md->name().isEmpty() && md->isLinkableInProject()) { @@ -8508,7 +8514,7 @@ TemplateVariant InheritanceGraphContext::get(const char *name) const class InheritanceNodeContext::Private { public: - Private(ClassDef *cd,const QCString &name) : m_classDef(cd), m_name(name) + Private(const ClassDef *cd,const QCString &name) : m_classDef(cd), m_name(name) { static bool init=FALSE; if (!init) @@ -8535,7 +8541,7 @@ class InheritanceNodeContext::Private return m_name; } private: - ClassDef *m_classDef; + const ClassDef *m_classDef; mutable SharedPtr<ClassContext> m_classContext; QCString m_name; static PropertyMapper<InheritanceNodeContext::Private> s_inst; @@ -8544,7 +8550,7 @@ class InheritanceNodeContext::Private PropertyMapper<InheritanceNodeContext::Private> InheritanceNodeContext::Private::s_inst; -InheritanceNodeContext::InheritanceNodeContext(ClassDef *cd,const QCString &name) : RefCountedContext("InheritanceNodeContext") +InheritanceNodeContext::InheritanceNodeContext(const ClassDef *cd,const QCString &name) : RefCountedContext("InheritanceNodeContext") { p = new Private(cd,name); } @@ -8565,7 +8571,7 @@ TemplateVariant InheritanceNodeContext::get(const char *name) const class InheritanceListContext::Private : public GenericNodeListContext { public: - void addClass(ClassDef *cd,const QCString &name) + void addClass(const ClassDef *cd,const QCString &name) { append(InheritanceNodeContext::alloc(cd,name)); } @@ -8580,7 +8586,7 @@ InheritanceListContext::InheritanceListContext(const BaseClassList *list, bool b BaseClassDef *bcd; for (li.toFirst();(bcd=li.current());++li) { - ClassDef *cd=bcd->classDef; + const ClassDef *cd=bcd->classDef; QCString name; if (baseClasses) { @@ -8806,7 +8812,7 @@ class AllMembersListContext::Private : public GenericNodeListContext for (mnii2.toFirst();(mi=mnii2.current());++mnii2) { MemberDef *md=mi->memberDef; - ClassDef *cd=md->getClassDef(); + const ClassDef *cd=md->getClassDef(); if (cd && !md->name().isEmpty() && md->name()[0]!='@') { if ((cd->isLinkable() && md->isLinkable()) || @@ -8862,7 +8868,7 @@ TemplateListIntf::ConstIterator *AllMembersListContext::createIterator() const class MemberGroupInfoContext::Private { public: - Private(Definition *def,const QCString &relPath,const MemberGroup *mg) : + Private(const Definition *def,const QCString &relPath,const MemberGroup *mg) : m_def(def), m_relPath(relPath), m_memberGroup(mg) @@ -8936,7 +8942,7 @@ class MemberGroupInfoContext::Private return FALSE; } private: - Definition *m_def; + const Definition *m_def; QCString m_relPath; const MemberGroup *m_memberGroup; struct Cachable @@ -8952,7 +8958,7 @@ class MemberGroupInfoContext::Private PropertyMapper<MemberGroupInfoContext::Private> MemberGroupInfoContext::Private::s_inst; -MemberGroupInfoContext::MemberGroupInfoContext(Definition *def, +MemberGroupInfoContext::MemberGroupInfoContext(const Definition *def, const QCString &relPath,const MemberGroup *mg) : RefCountedContext("MemberGroupInfoContext") { p = new Private(def,relPath,mg); @@ -8974,7 +8980,7 @@ TemplateVariant MemberGroupInfoContext::get(const char *name) const class MemberGroupListContext::Private : public GenericNodeListContext { public: - void addMemberGroup(Definition *def,const QCString &relPath,const MemberGroup *mg) + void addMemberGroup(const Definition *def,const QCString &relPath,const MemberGroup *mg) { append(MemberGroupInfoContext::alloc(def,relPath,mg)); } @@ -8985,7 +8991,7 @@ MemberGroupListContext::MemberGroupListContext() : RefCountedContext("MemberGrou p = new Private; } -MemberGroupListContext::MemberGroupListContext(Definition *def,const QCString &relPath,const MemberGroupList *list) : RefCountedContext("MemberGroupListContext") +MemberGroupListContext::MemberGroupListContext(const Definition *def,const QCString &relPath,const MemberGroupList *list) : RefCountedContext("MemberGroupListContext") { p = new Private; if (list) @@ -8999,7 +9005,7 @@ MemberGroupListContext::MemberGroupListContext(Definition *def,const QCString &r } } -MemberGroupListContext::MemberGroupListContext(Definition *def,const QCString &relPath,const MemberGroupSDict *dict,bool subGrouping) : RefCountedContext("MemberGroupListContext") +MemberGroupListContext::MemberGroupListContext(const Definition *def,const QCString &relPath,const MemberGroupSDict *dict,bool subGrouping) : RefCountedContext("MemberGroupListContext") { p = new Private; if (dict) @@ -9045,7 +9051,7 @@ TemplateListIntf::ConstIterator *MemberGroupListContext::createIterator() const class MemberListInfoContext::Private { public: - Private(Definition *def,const QCString &relPath,const MemberList *ml,const QCString &title,const QCString &subtitle) : + Private(const Definition *def,const QCString &relPath,const MemberList *ml,const QCString &title,const QCString &subtitle) : m_def(def), m_memberList(ml), m_relPath(relPath), @@ -9102,7 +9108,7 @@ class MemberListInfoContext::Private m_def->definitionType()==Definition::TypeClass) { InheritedMemberInfoListContext *ctx = InheritedMemberInfoListContext::alloc(); - ctx->addMemberList(dynamic_cast<ClassDef*>(m_def),m_memberList->listType(),m_title,FALSE); + ctx->addMemberList(dynamic_cast<const ClassDef*>(m_def),m_memberList->listType(),m_title,FALSE); m_cache.inherited.reset(ctx); } if (m_cache.inherited) @@ -9115,7 +9121,7 @@ class MemberListInfoContext::Private } } private: - Definition *m_def; + const Definition *m_def; const MemberList *m_memberList; QCString m_relPath; QCString m_title; @@ -9134,7 +9140,7 @@ class MemberListInfoContext::Private PropertyMapper<MemberListInfoContext::Private> MemberListInfoContext::Private::s_inst; MemberListInfoContext::MemberListInfoContext( - Definition *def,const QCString &relPath,const MemberList *ml, + const Definition *def,const QCString &relPath,const MemberList *ml, const QCString &title,const QCString &subtitle) : RefCountedContext("MemberListInfoContext") { p = new Private(def,relPath,ml,title,subtitle); @@ -9157,7 +9163,7 @@ TemplateVariant MemberListInfoContext::get(const char *name) const class InheritedMemberInfoContext::Private { public: - Private(ClassDef *cd,MemberList *ml,const QCString &title) + Private(const ClassDef *cd,MemberList *ml,const QCString &title) : m_class(cd), m_memberList(ml), m_title(title) { static bool init=FALSE; @@ -9216,7 +9222,7 @@ class InheritedMemberInfoContext::Private } private: - ClassDef * m_class; + const ClassDef * m_class; MemberList *m_memberList; QCString m_title; mutable SharedPtr<ClassContext> m_classCtx; @@ -9228,7 +9234,7 @@ class InheritedMemberInfoContext::Private PropertyMapper<InheritedMemberInfoContext::Private> InheritedMemberInfoContext::Private::s_inst; -InheritedMemberInfoContext::InheritedMemberInfoContext(ClassDef *cd,MemberList *ml, +InheritedMemberInfoContext::InheritedMemberInfoContext(const ClassDef *cd,MemberList *ml, const QCString &title) : RefCountedContext("InheritedMemberInfoContext") { p = new Private(cd,ml,title); @@ -9250,7 +9256,7 @@ TemplateVariant InheritedMemberInfoContext::get(const char *name) const class InheritedMemberInfoListContext::Private : public GenericNodeListContext { public: - void addMemberList(ClassDef *inheritedFrom,MemberList *ml,MemberList *combinedList) + void addMemberList(const ClassDef *inheritedFrom,MemberList *ml,MemberList *combinedList) { if (ml) { @@ -9265,7 +9271,7 @@ class InheritedMemberInfoListContext::Private : public GenericNodeListContext } } } - void addMemberListIncludingGrouped(ClassDef *inheritedFrom,MemberList *ml,MemberList *combinedList) + void addMemberListIncludingGrouped(const ClassDef *inheritedFrom,MemberList *ml,MemberList *combinedList) { if (ml) { @@ -9281,8 +9287,8 @@ class InheritedMemberInfoListContext::Private : public GenericNodeListContext } } } - void addMemberGroupsOfClass(ClassDef *inheritedFrom, - ClassDef *cd,MemberListType lt,MemberList *combinedList) + void addMemberGroupsOfClass(const ClassDef *inheritedFrom, + const ClassDef *cd,MemberListType lt,MemberList *combinedList) { if (cd->getMemberGroupSDict()) { @@ -9307,7 +9313,7 @@ class InheritedMemberInfoListContext::Private : public GenericNodeListContext } } } - void addInheritedMembers(ClassDef *inheritedFrom,ClassDef *cd,MemberListType lt, + void addInheritedMembers(const ClassDef *inheritedFrom,const ClassDef *cd,MemberListType lt, MemberListType lt1,int lt2,const QCString &title,bool additionalList) { int count = cd->countMembersIncludingGrouped(lt1,inheritedFrom,additionalList); @@ -9324,7 +9330,7 @@ class InheritedMemberInfoListContext::Private : public GenericNodeListContext append(InheritedMemberInfoContext::alloc(cd,combinedList,title)); } } - void findInheritedMembers(ClassDef *inheritedFrom,ClassDef *cd,MemberListType lt, + void findInheritedMembers(const ClassDef *inheritedFrom,const ClassDef *cd,MemberListType lt, int lt2, const QCString &title,bool additionalList, QPtrDict<void> *visitedClasses) { @@ -9366,7 +9372,7 @@ InheritedMemberInfoListContext::InheritedMemberInfoListContext() : RefCountedCon } void InheritedMemberInfoListContext::addMemberList( - ClassDef *cd,MemberListType lt,const QCString &title,bool additionalList) + const ClassDef *cd,MemberListType lt,const QCString &title,bool additionalList) { QPtrDict<void> visited(17); bool memberInSection = cd->countMembersIncludingGrouped(lt,cd,FALSE)>0; @@ -9407,7 +9413,7 @@ TemplateListIntf::ConstIterator *InheritedMemberInfoListContext::createIterator( class ArgumentContext::Private { public: - Private(const Argument *arg,Definition *def,const QCString &relPath) : + Private(const Argument *arg,const Definition *def,const QCString &relPath) : m_argument(arg), m_def(def), m_relPath(relPath) { static bool init=FALSE; @@ -9477,7 +9483,7 @@ class ArgumentContext::Private } private: const Argument *m_argument; - Definition *m_def; + const Definition *m_def; QCString m_relPath; struct Cachable { @@ -9490,7 +9496,7 @@ class ArgumentContext::Private PropertyMapper<ArgumentContext::Private> ArgumentContext::Private::s_inst; -ArgumentContext::ArgumentContext(const Argument *al,Definition *def,const QCString &relPath) : RefCountedContext("ArgumentContext") +ArgumentContext::ArgumentContext(const Argument *al,const Definition *def,const QCString &relPath) : RefCountedContext("ArgumentContext") { p = new Private(al,def,relPath); } @@ -9511,7 +9517,7 @@ TemplateVariant ArgumentContext::get(const char *name) const class ArgumentListContext::Private : public GenericNodeListContext { public: - void addArgument(const Argument *arg,Definition *def,const QCString &relPath) + void addArgument(const Argument *arg,const Definition *def,const QCString &relPath) { append(ArgumentContext::alloc(arg,def,relPath)); } @@ -9523,7 +9529,7 @@ ArgumentListContext::ArgumentListContext() : RefCountedContext("ArgumentListCont } ArgumentListContext::ArgumentListContext(const ArgumentList *list, - Definition *def,const QCString &relPath) : RefCountedContext("ArgumentListContext") + const Definition *def,const QCString &relPath) : RefCountedContext("ArgumentListContext") { p = new Private; if (list) @@ -9645,7 +9651,7 @@ class SymbolContext::Private { if (md) { - FileDef *fd = md->getBodyDef(); + const FileDef *fd = md->getBodyDef(); if (fd==0) fd = md->getFileDef(); if (fd) { @@ -9713,8 +9719,8 @@ class SymbolListContext::Private : public GenericNodeListContext Private(const SearchDefinitionList *sdl) { QListIterator<Definition> li(*sdl); - Definition *def; - Definition *prev = 0; + const Definition *def; + const Definition *prev = 0; for (li.toFirst();(def=li.current());) { ++li; @@ -10364,13 +10370,13 @@ void generateOutputViaTemplate() // clear all cached data in Definition objects. QDictIterator<DefinitionIntf> di(*Doxygen::symbolMap); - DefinitionIntf *intf; + const DefinitionIntf *intf; for (;(intf=di.current());++di) { if (intf->definitionType()==DefinitionIntf::TypeSymbolList) // list of symbols { - DefinitionListIterator dli(*(DefinitionList*)intf); - Definition *d; + DefinitionListIterator dli(*dynamic_cast<const DefinitionList*>(intf)); + const Definition *d; // for each symbol for (dli.toFirst();(d=dli.current());++dli) { @@ -10379,7 +10385,7 @@ void generateOutputViaTemplate() } else // single symbol { - Definition *d = (Definition *)intf; + const Definition *d = dynamic_cast<const Definition *>(intf); d->setCookie(0); } } diff --git a/src/context.h b/src/context.h index e082c4b..ecd1227 100644 --- a/src/context.h +++ b/src/context.h @@ -186,7 +186,7 @@ class TranslateContext : public RefCountedContext, public TemplateStructIntf class UsedFilesContext : public RefCountedContext, public TemplateListIntf { public: - static UsedFilesContext *alloc(ClassDef *cd) { return new UsedFilesContext(cd); } + static UsedFilesContext *alloc(const ClassDef *cd) { return new UsedFilesContext(cd); } // TemplateListIntf virtual int count() const; @@ -195,10 +195,10 @@ class UsedFilesContext : public RefCountedContext, public TemplateListIntf virtual int addRef() { return RefCountedContext::addRef(); } virtual int release() { return RefCountedContext::release(); } - void addFile(FileDef *fd); + void addFile(const FileDef *fd); private: - UsedFilesContext(ClassDef *cd); + UsedFilesContext(const ClassDef *cd); ~UsedFilesContext(); class Private; @@ -253,7 +253,7 @@ class IncludeInfoListContext : public RefCountedContext, public TemplateListIntf class ClassContext : public RefCountedContext, public TemplateStructIntf { public: - static ClassContext *alloc(ClassDef *cd) { return new ClassContext(cd); } + static ClassContext *alloc(const ClassDef *cd) { return new ClassContext(cd); } // TemplateStructIntf methods virtual TemplateVariant get(const char *name) const; @@ -261,7 +261,7 @@ class ClassContext : public RefCountedContext, public TemplateStructIntf virtual int release() { return RefCountedContext::release(); } private: - ClassContext(ClassDef *); + ClassContext(const ClassDef *); ~ClassContext(); class Private; Private *p; @@ -272,7 +272,7 @@ class ClassContext : public RefCountedContext, public TemplateStructIntf class NamespaceContext : public RefCountedContext, public TemplateStructIntf { public: - static NamespaceContext *alloc(NamespaceDef *nd) { return new NamespaceContext(nd); } + static NamespaceContext *alloc(const NamespaceDef *nd) { return new NamespaceContext(nd); } // TemplateStructIntf methods virtual TemplateVariant get(const char *name) const; @@ -280,7 +280,7 @@ class NamespaceContext : public RefCountedContext, public TemplateStructIntf virtual int release() { return RefCountedContext::release(); } private: - NamespaceContext(NamespaceDef *); + NamespaceContext(const NamespaceDef *); ~NamespaceContext(); class Private; Private *p; @@ -291,7 +291,7 @@ class NamespaceContext : public RefCountedContext, public TemplateStructIntf class FileContext : public RefCountedContext, public TemplateStructIntf { public: - static FileContext *alloc(FileDef *fd) { return new FileContext(fd); } + static FileContext *alloc(const FileDef *fd) { return new FileContext(fd); } // TemplateStructIntf methods virtual TemplateVariant get(const char *name) const; @@ -299,7 +299,7 @@ class FileContext : public RefCountedContext, public TemplateStructIntf virtual int release() { return RefCountedContext::release(); } private: - FileContext(FileDef *); + FileContext(const FileDef *); ~FileContext(); class Private; Private *p; @@ -309,7 +309,7 @@ class FileContext : public RefCountedContext, public TemplateStructIntf class DirContext : public RefCountedContext, public TemplateStructIntf { public: - static DirContext *alloc(DirDef *dd) { return new DirContext(dd); } + static DirContext *alloc(const DirDef *dd) { return new DirContext(dd); } // TemplateStructIntf methods virtual TemplateVariant get(const char *name) const; @@ -317,7 +317,7 @@ class DirContext : public RefCountedContext, public TemplateStructIntf virtual int release() { return RefCountedContext::release(); } private: - DirContext(DirDef *); + DirContext(const DirDef *); ~DirContext(); class Private; Private *p; @@ -329,7 +329,7 @@ class DirContext : public RefCountedContext, public TemplateStructIntf class PageContext : public RefCountedContext, public TemplateStructIntf { public: - static PageContext *alloc(PageDef *pd,bool isMainPage,bool isExample) { return new PageContext(pd,isMainPage,isExample); } + static PageContext *alloc(const PageDef *pd,bool isMainPage,bool isExample) { return new PageContext(pd,isMainPage,isExample); } // TemplateStructIntf methods virtual TemplateVariant get(const char *name) const; @@ -337,7 +337,7 @@ class PageContext : public RefCountedContext, public TemplateStructIntf virtual int release() { return RefCountedContext::release(); } private: - PageContext(PageDef *,bool isMainPage,bool isExample); + PageContext(const PageDef *,bool isMainPage,bool isExample); ~PageContext(); class Private; Private *p; @@ -368,7 +368,7 @@ class MemberContext : public RefCountedContext, public TemplateStructIntf class ModuleContext : public RefCountedContext, public TemplateStructIntf { public: - static ModuleContext *alloc(GroupDef *gd) { return new ModuleContext(gd); } + static ModuleContext *alloc(const GroupDef *gd) { return new ModuleContext(gd); } // TemplateStructIntf methods virtual TemplateVariant get(const char *name) const; @@ -376,7 +376,7 @@ class ModuleContext : public RefCountedContext, public TemplateStructIntf virtual int release() { return RefCountedContext::release(); } private: - ModuleContext(GroupDef *); + ModuleContext(const GroupDef *); ~ModuleContext(); class Private; Private *p; @@ -447,7 +447,7 @@ class InheritanceGraphContext : public RefCountedContext, public TemplateStructI class ClassInheritanceNodeContext : public RefCountedContext, public TemplateStructIntf { public: - static ClassInheritanceNodeContext *alloc(ClassDef *cd) + static ClassInheritanceNodeContext *alloc(const ClassDef *cd) { return new ClassInheritanceNodeContext(cd); } // TemplateStructIntf methods @@ -458,7 +458,7 @@ class ClassInheritanceNodeContext : public RefCountedContext, public TemplateStr void addChildren(const BaseClassList *bcl,bool hideSuper); private: - ClassInheritanceNodeContext(ClassDef *); + ClassInheritanceNodeContext(const ClassDef *); ~ClassInheritanceNodeContext(); class Private; Private *p; @@ -509,7 +509,7 @@ class ClassHierarchyContext : public RefCountedContext, public TemplateStructInt class NestingNodeContext : public RefCountedContext, public TemplateStructIntf { public: - static NestingNodeContext *alloc(const NestingNodeContext *parent,Definition *def, + static NestingNodeContext *alloc(const NestingNodeContext *parent,const Definition *def, int index,int level,bool addClasses,bool inherit,bool hideSuper) { return new NestingNodeContext(parent,def,index,level,addClasses,inherit,hideSuper); } @@ -522,7 +522,7 @@ class NestingNodeContext : public RefCountedContext, public TemplateStructIntf private: NestingNodeContext(const NestingNodeContext *parent, - Definition *,int index,int level,bool addClasses,bool inherit,bool hideSuper); + const Definition *,int index,int level,bool addClasses,bool inherit,bool hideSuper); ~NestingNodeContext(); class Private; Private *p; @@ -729,7 +729,7 @@ class PageTreeContext : public RefCountedContext, public TemplateStructIntf class ModuleNodeContext : public RefCountedContext, public TemplateStructIntf { public: - static ModuleNodeContext *alloc(GroupDef *gd) { return new ModuleNodeContext(gd); } + static ModuleNodeContext *alloc(const GroupDef *gd) { return new ModuleNodeContext(gd); } // TemplateStructIntf methods virtual TemplateVariant get(const char *name) const; @@ -737,7 +737,7 @@ class ModuleNodeContext : public RefCountedContext, public TemplateStructIntf virtual int release() { return RefCountedContext::release(); } private: - ModuleNodeContext(GroupDef *); + ModuleNodeContext(const GroupDef *); ~ModuleNodeContext(); class Private; Private *p; @@ -889,7 +889,7 @@ class NamespaceMembersIndexContext : public RefCountedContext, public TemplateSt class NavPathElemContext : public RefCountedContext, public TemplateStructIntf { public: - static NavPathElemContext *alloc(Definition *def) { return new NavPathElemContext(def); } + static NavPathElemContext *alloc(const Definition *def) { return new NavPathElemContext(def); } // TemplateStructIntf methods virtual TemplateVariant get(const char *name) const; @@ -897,7 +897,7 @@ class NavPathElemContext : public RefCountedContext, public TemplateStructIntf virtual int release() { return RefCountedContext::release(); } private: - NavPathElemContext(Definition *def); + NavPathElemContext(const Definition *def); ~NavPathElemContext(); class Private; Private *p; @@ -909,7 +909,7 @@ class NavPathElemContext : public RefCountedContext, public TemplateStructIntf class InheritanceNodeContext : public RefCountedContext, public TemplateStructIntf { public: - static InheritanceNodeContext *alloc(ClassDef *cd,const QCString &name) + static InheritanceNodeContext *alloc(const ClassDef *cd,const QCString &name) { return new InheritanceNodeContext(cd,name); } // TemplateStructIntf methods @@ -918,7 +918,7 @@ class InheritanceNodeContext : public RefCountedContext, public TemplateStructIn virtual int release() { return RefCountedContext::release(); } private: - InheritanceNodeContext(ClassDef *cd,const QCString &name); + InheritanceNodeContext(const ClassDef *cd,const QCString &name); ~InheritanceNodeContext(); class Private; Private *p; @@ -979,7 +979,7 @@ class MemberListContext : public RefCountedContext, public TemplateListIntf class MemberGroupInfoContext : public RefCountedContext, public TemplateStructIntf { public: - static MemberGroupInfoContext *alloc(Definition *def,const QCString &relPath,const MemberGroup *mg) + static MemberGroupInfoContext *alloc(const Definition *def,const QCString &relPath,const MemberGroup *mg) { return new MemberGroupInfoContext(def,relPath,mg); } // TemplateStructIntf methods @@ -988,7 +988,7 @@ class MemberGroupInfoContext : public RefCountedContext, public TemplateStructIn virtual int release() { return RefCountedContext::release(); } private: - MemberGroupInfoContext(Definition *def,const QCString &relPath,const MemberGroup *mg); + MemberGroupInfoContext(const Definition *def,const QCString &relPath,const MemberGroup *mg); ~MemberGroupInfoContext(); class Private; Private *p; @@ -1001,9 +1001,9 @@ class MemberGroupListContext : public RefCountedContext, public TemplateListIntf public: static MemberGroupListContext *alloc() { return new MemberGroupListContext; } - static MemberGroupListContext *alloc(Definition *def,const QCString &relPath,const MemberGroupList *list) + static MemberGroupListContext *alloc(const Definition *def,const QCString &relPath,const MemberGroupList *list) { return new MemberGroupListContext(def,relPath,list); } - static MemberGroupListContext *alloc(Definition *def,const QCString &relPath,const MemberGroupSDict *dict,bool subGrouping) + static MemberGroupListContext *alloc(const Definition *def,const QCString &relPath,const MemberGroupSDict *dict,bool subGrouping) { return new MemberGroupListContext(def,relPath,dict,subGrouping); } // TemplateListIntf @@ -1015,8 +1015,8 @@ class MemberGroupListContext : public RefCountedContext, public TemplateListIntf private: MemberGroupListContext(); - MemberGroupListContext(Definition *def,const QCString &relPath,const MemberGroupList *list); - MemberGroupListContext(Definition *def,const QCString &relPath,const MemberGroupSDict *mgDict,bool subGrouping); + MemberGroupListContext(const Definition *def,const QCString &relPath,const MemberGroupList *list); + MemberGroupListContext(const Definition *def,const QCString &relPath,const MemberGroupSDict *mgDict,bool subGrouping); ~MemberGroupListContext(); class Private; Private *p; @@ -1028,7 +1028,7 @@ class MemberGroupListContext : public RefCountedContext, public TemplateListIntf class MemberListInfoContext : public RefCountedContext, public TemplateStructIntf { public: - static MemberListInfoContext *alloc(Definition *def,const QCString &relPath, + static MemberListInfoContext *alloc(const Definition *def,const QCString &relPath, const MemberList *ml,const QCString &title, const QCString &subtitle=QCString()) { return new MemberListInfoContext(def,relPath,ml,title,subtitle); } @@ -1039,7 +1039,7 @@ class MemberListInfoContext : public RefCountedContext, public TemplateStructInt virtual int release() { return RefCountedContext::release(); } private: - MemberListInfoContext(Definition *def,const QCString &relPath, + MemberListInfoContext(const Definition *def,const QCString &relPath, const MemberList *ml,const QCString &title, const QCString &subtitle=QCString()); ~MemberListInfoContext(); @@ -1071,7 +1071,7 @@ class MemberInfoContext : public RefCountedContext, public TemplateStructIntf class InheritedMemberInfoContext : public RefCountedContext, public TemplateStructIntf { public: - static InheritedMemberInfoContext *alloc(ClassDef *cd,MemberList *ml,const QCString &title) + static InheritedMemberInfoContext *alloc(const ClassDef *cd,MemberList *ml,const QCString &title) { return new InheritedMemberInfoContext(cd,ml,title); } // TemplateStructIntf methods @@ -1080,7 +1080,7 @@ class InheritedMemberInfoContext : public RefCountedContext, public TemplateStru virtual int release() { return RefCountedContext::release(); } private: - InheritedMemberInfoContext(ClassDef *cd,MemberList *ml,const QCString &title); + InheritedMemberInfoContext(const ClassDef *cd,MemberList *ml,const QCString &title); ~InheritedMemberInfoContext(); class Private; Private *p; @@ -1092,7 +1092,7 @@ class InheritedMemberInfoListContext : public RefCountedContext, public Template { public: static InheritedMemberInfoListContext *alloc() { return new InheritedMemberInfoListContext; } - void addMemberList(ClassDef *cd,MemberListType lt,const QCString &title,bool additionalList=TRUE); + void addMemberList(const ClassDef *cd,MemberListType lt,const QCString &title,bool additionalList=TRUE); // TemplateListIntf virtual int count() const; @@ -1138,7 +1138,7 @@ class AllMembersListContext : public RefCountedContext, public TemplateListIntf class ArgumentContext : public RefCountedContext, public TemplateStructIntf { public: - static ArgumentContext *alloc(const Argument *arg,Definition *def,const QCString &relPath) + static ArgumentContext *alloc(const Argument *arg,const Definition *def,const QCString &relPath) { return new ArgumentContext(arg,def,relPath); } // TemplateStructIntf methods @@ -1147,7 +1147,7 @@ class ArgumentContext : public RefCountedContext, public TemplateStructIntf virtual int release() { return RefCountedContext::release(); } private: - ArgumentContext(const Argument *arg,Definition *def,const QCString &relPath); + ArgumentContext(const Argument *arg,const Definition *def,const QCString &relPath); ~ArgumentContext(); class Private; Private *p; @@ -1159,7 +1159,7 @@ class ArgumentListContext : public RefCountedContext, public TemplateListIntf { public: static ArgumentListContext *alloc() { return new ArgumentListContext; } - static ArgumentListContext *alloc(const ArgumentList *al,Definition *def,const QCString &relPath) + static ArgumentListContext *alloc(const ArgumentList *al,const Definition *def,const QCString &relPath) { return new ArgumentListContext(al,def,relPath); } // TemplateListIntf @@ -1171,7 +1171,7 @@ class ArgumentListContext : public RefCountedContext, public TemplateListIntf private: ArgumentListContext(); - ArgumentListContext(const ArgumentList *al,Definition *def,const QCString &relPath); + ArgumentListContext(const ArgumentList *al,const Definition *def,const QCString &relPath); ~ArgumentListContext(); class Private; Private *p; diff --git a/src/cppvalue.cpp b/src/cppvalue.cpp index 176931d..1543498 100644 --- a/src/cppvalue.cpp +++ b/src/cppvalue.cpp @@ -21,44 +21,44 @@ #include "cppvalue.h" #include "constexp.h" -CPPValue parseOctal() +CPPValue parseOctal(const QCString& token) { long val = 0; - for (const char *p = g_strToken.data(); *p != 0; p++) + for (const char *p = token.data(); *p != 0; p++) { if (*p >= '0' && *p <= '7') val = val * 8 + *p - '0'; } return CPPValue(val); } -CPPValue parseDecimal() +CPPValue parseDecimal(const QCString& token) { long val = 0; - for (const char *p = g_strToken.data(); *p != 0; p++) + for (const char *p = token.data(); *p != 0; p++) { if (*p >= '0' && *p <= '9') val = val * 10 + *p - '0'; } return CPPValue(val); } -CPPValue parseHexadecimal() +CPPValue parseHexadecimal(const QCString& token) { long val = 0; - for (const char *p = g_strToken.data(); *p != 0; p++) + for (const char *p = token.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; } - //printf("parseHexadecimal %s->%x\n",g_strToken.data(),val); + //printf("parseHexadecimal %s->%x\n",token.data(),val); return CPPValue(val); } -CPPValue parseCharacter() // does not work for '\n' and the alike +CPPValue parseCharacter(const QCString& token) // does not work for '\n' and the alike { - if (g_strToken[1]=='\\') + if (token[1]=='\\') { - switch(g_strToken[2]) + switch(token[2]) { case 'n': return CPPValue((long)'\n'); case 't': return CPPValue((long)'\t'); @@ -79,17 +79,17 @@ CPPValue parseCharacter() // does not work for '\n' and the alike case '5': // fall through case '6': // fall through case '7': // fall through - return parseOctal(); + return parseOctal(token); case 'x': - case 'X': return parseHexadecimal(); - default: printf("Invalid escape sequence %s found!\n",g_strToken.data()); + case 'X': return parseHexadecimal(token); + default: printf("Invalid escape sequence %s found!\n",token.data()); return CPPValue(0L); } } - return CPPValue((long)g_strToken[1]); + return CPPValue((long)token[1]); } -CPPValue parseFloat() +CPPValue parseFloat(const QCString& token) { - return CPPValue(atof(g_strToken)); + return CPPValue(atof(token)); } diff --git a/src/cppvalue.h b/src/cppvalue.h index 59dd594..cde033d 100644 --- a/src/cppvalue.h +++ b/src/cppvalue.h @@ -21,6 +21,7 @@ #include <stdio.h> #include <qglobal.h> +#include <qcstring.h> /** A class representing a C-preprocessor value. */ class CPPValue @@ -52,10 +53,10 @@ class CPPValue } v; }; -extern CPPValue parseOctal(); -extern CPPValue parseDecimal(); -extern CPPValue parseHexadecimal(); -extern CPPValue parseCharacter(); -extern CPPValue parseFloat(); +extern CPPValue parseOctal(const QCString& token); +extern CPPValue parseDecimal(const QCString& token); +extern CPPValue parseHexadecimal(const QCString& token); +extern CPPValue parseCharacter(const QCString& token); +extern CPPValue parseFloat(const QCString& token); #endif diff --git a/src/declinfo.l b/src/declinfo.l index a91f832..d7f8743 100644 --- a/src/declinfo.l +++ b/src/declinfo.l @@ -16,6 +16,10 @@ */ %option never-interactive %option prefix="declinfoYY" +%option nounput +%option noyywrap +%option reentrant +%option extra-type="struct declinfoYY_state *" %{ @@ -33,79 +37,43 @@ #define YY_NO_INPUT 1 #define YY_NO_UNISTD_H 1 +#define YY_NEVER_INTERACTIVE 1 /* ----------------------------------------------------------------- * * statics */ - -static const char * inputString; -static int inputPosition; -static QCString scope; -static QCString className; -static QCString classTempList; -static QCString funcTempList; -static QCString type; -static QCString name; -static QCString args; -static int sharpCount; -static bool classTempListFound; -static bool funcTempListFound; -static QCString exceptionString; -static bool insideObjC; - -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.isEmpty()) type+=" "; - if (!scope.isEmpty()) type+=scope+"::"; - type+=name; - scope.resize(0); - name.resize(0); -} - -static void addTypeName() +struct declinfoYY_state { - //printf("addTypeName() type=`%s' scope=`%s' name=`%s'\n", - // type.data(),scope.data(),name.data()); - if (name.isEmpty() || - name.at(name.length()-1)==':') // end of Objective-C keyword => append to name not type - { - return; - } - if (!type.isEmpty()) type+=' '; - type+=name; - name.resize(0); -} - -#define YY_NEVER_INTERACTIVE 1 - + const char *inputString; + int inputPosition; + QCString scope; + QCString className; + QCString classTempList; + QCString funcTempList; + QCString type; + QCString name; + QCString args; + int sharpCount; + bool classTempListFound; + bool funcTempListFound; + QCString exceptionString; + bool insideObjC; +}; + +static void addType(yyscan_t yyscanner); +static void addTypeName(yyscan_t yyscanner); +static int yyread(char *buf,int max_size, yyscan_t yyscanner); + /* ----------------------------------------------------------------- */ #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; -} - +#define YY_INPUT(buf,result,max_size) result=yyread(buf,max_size,yyscanner); %} B [ \t] ID "$"?([a-z_A-Z\x80-\xFF][a-z_A-Z0-9\x80-\xFF]*)|(@[0-9]+) -%option nounput -%option noyywrap - %x Start %x Template %x ReadArgs @@ -119,17 +87,17 @@ ID "$"?([a-z_A-Z\x80-\xFF][a-z_A-Z0-9\x80-\xFF]*)|(@[0-9]+) %% <Start>"operator"/({B}*"["{B}*"]")* { // operator rule must be before {ID} rule - name += yytext; + yyextra->name += yytext; BEGIN(Operator); } <Start>{ID}{B}*"("{B}*{ID}{B}*")" { // Objective-C class categories - if (!insideObjC) + if (!yyextra->insideObjC) { REJECT; } else { - name += yytext; + yyextra->name += yytext; } } <Start>([~!]{B}*)?{ID}/({B}*"["{B}*"]")* { // the []'s are for Java, @@ -137,143 +105,195 @@ ID "$"?([a-z_A-Z\x80-\xFF][a-z_A-Z0-9\x80-\xFF]*)|(@[0-9]+) // dimensional C++ arrays like A[][15] // the leading ~ is for a destructor // the leading ! is for a C++/CLI finalizer (see bug 456475 and 635198) - addTypeName(); - name += yytext; + addTypeName(yyscanner); + yyextra->name += yytext; } -<Start>{B}*"::"{B}* { // found a scope specifier - if (!scope.isEmpty()) +<Start>{B}*"::"{B}* { // found a yyextra->scope specifier + if (!yyextra->scope.isEmpty()) { - scope+="::"+name; // add name to scope + yyextra->scope+="::"+yyextra->name; // add yyextra->name to yyextra->scope } else { - scope = name.copy(); // scope becomes name + yyextra->scope = yyextra->name.copy(); // yyextra->scope becomes yyextra->name } - name.resize(0); + yyextra->name.resize(0); } <Start>{B}*":" { // Objective-C argument separator - name+=yytext; + yyextra->name+=yytext; } <Start>[*&]+ { - addType(); - type+=yytext; + addType(yyscanner); + yyextra->type+=yytext; } <Start>{B}+ { - addType(); + addType(yyscanner); } <Start>{B}*"("({ID}"::")*{B}*[&*]({B}*("const"|"volatile"){B}+)? { - addType(); + addType(yyscanner); QCString text=yytext; - type+=text.stripWhiteSpace(); + yyextra->type+=text.stripWhiteSpace(); } <Start>{B}*")" { - type+=")"; + yyextra->type+=")"; } <Start>{B}*"(" { // TODO: function pointers - args+="("; + yyextra->args+="("; BEGIN(ReadArgs); } <Start>{B}*"[" { - args+="["; + yyextra->args+="["; BEGIN(ReadArgs); } <Start>{B}*"<" { - name+="<"; - sharpCount=0; + yyextra->name+="<"; + yyextra->sharpCount=0; BEGIN(Template); } -<Template>"<<" { name+="<<"; } -<Template>">>" { name+=">>"; } +<Template>"<<" { yyextra->name+="<<"; } +<Template>">>" { yyextra->name+=">>"; } <Template>"<" { - name+="<"; - sharpCount++; + yyextra->name+="<"; + yyextra->sharpCount++; } <Template>">" { - name+=">"; - if (sharpCount) - --sharpCount; + yyextra->name+=">"; + if (yyextra->sharpCount) + --yyextra->sharpCount; else { BEGIN(Start); } } <Template>. { - name+=*yytext; + yyextra->name+=*yytext; } <Operator>{B}*"("{B}*")"{B}*"<>"{B}*/"(" { - name+="() <>"; + yyextra->name+="() <>"; BEGIN(ReadArgs); } <Operator>{B}*"("{B}*")"{B}*/"(" { - name+="()"; + yyextra->name+="()"; BEGIN(ReadArgs); } <Operator>[^(]*{B}*("<>"{B}*)?/"(" { - name+=yytext; + yyextra->name+=yytext; BEGIN(ReadArgs); } <ReadArgs>"throw"{B}*"(" { - exceptionString="throw("; + yyextra->exceptionString="throw("; BEGIN(ReadExceptions); } <ReadArgs>. { - args+=*yytext; + yyextra->args+=*yytext; } <ReadExceptions>. { - exceptionString+=*yytext; + yyextra->exceptionString+=*yytext; } <*>. <*>\n %% -/*@ ---------------------------------------------------------------------------- +static void addType(yyscan_t yyscanner) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + //printf("addType() yyextra->type=`%s' yyextra->scope=`%s' yyextra->name=`%s'\n", + // yyextra->type.data(),yyextra->scope.data(),yyextra->name.data()); + if (yyextra->name.isEmpty() && yyextra->scope.isEmpty()) return; + if (!yyextra->type.isEmpty()) yyextra->type+=" "; + if (!yyextra->scope.isEmpty()) yyextra->type+=yyextra->scope+"::"; + yyextra->type+=yyextra->name; + yyextra->scope.resize(0); + yyextra->name.resize(0); +} + +static void addTypeName(yyscan_t yyscanner) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + //printf("addTypeName() yyextra->type=`%s' yyextra->scope=`%s' yyextra->name=`%s'\n", + // yyextra->type.data(),yyextra->scope.data(),yyextra->name.data()); + if (yyextra->name.isEmpty() || + yyextra->name.at(yyextra->name.length()-1)==':') // end of Objective-C keyword => append to yyextra->name not yyextra->type + { + return; + } + if (!yyextra->type.isEmpty()) yyextra->type+=' '; + yyextra->type+=yyextra->name; + yyextra->name.resize(0); +} + +static int yyread(char *buf,int max_size, yyscan_t yyscanner) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + int c=0; + while( c < max_size && yyextra->inputString[yyextra->inputPosition] ) + { + *buf = yyextra->inputString[yyextra->inputPosition++] ; + c++; buf++; + } + return c; +} + +/*@ public interface------------------------------------------------------------ */ +static yyscan_t g_yyscanner; +static struct declinfoYY_state g_declinfo_extra; void parseFuncDecl(const QCString &decl,bool objC,QCString &cl,QCString &t, QCString &n,QCString &a,QCString &ftl,QCString &exc) { + if (decl.isEmpty()) + { + return; + } + declinfoYYlex_init_extra(&g_declinfo_extra, &g_yyscanner); + struct yyguts_t *yyg = (struct yyguts_t*)g_yyscanner; + +#ifdef FLEX_DEBUG + yyset_debug(1,g_yyscanner); +#endif + printlex(yy_flex_debug, TRUE, __FILE__, NULL); - inputString = decl; - //printf("Input=`%s'\n",inputString); - if (inputString==0) return; - inputPosition = 0; - classTempListFound = FALSE; - funcTempListFound = FALSE; - insideObjC = objC; - 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 ); + yyextra->inputString = decl; + //printf("Input=`%s'\n",yyextra->inputString); + yyextra->inputPosition = 0; + yyextra->classTempListFound = FALSE; + yyextra->funcTempListFound = FALSE; + yyextra->insideObjC = objC; + yyextra->scope.resize(0); + yyextra->className.resize(0); + yyextra->classTempList.resize(0); + yyextra->funcTempList.resize(0); + yyextra->name.resize(0); + yyextra->type.resize(0); + yyextra->args.resize(0); + yyextra->exceptionString.resize(0); + // first we try to find the yyextra->type, yyextra->scope, yyextra->name and arguments + declinfoYYrestart( yyin, g_yyscanner ); BEGIN( Start ); - declinfoYYlex(); + declinfoYYlex(g_yyscanner); - //printf("type=`%s' class=`%s' name=`%s' args=`%s'\n", - // type.data(),scope.data(),name.data(),args.data()); + //printf("yyextra->type=`%s' class=`%s' yyextra->name=`%s' yyextra->args=`%s'\n", + // yyextra->type.data(),yyextra->scope.data(),yyextra->name.data(),yyextra->args.data()); - int nb = name.findRev('['); - if (nb!=-1 && args.isEmpty()) // correct for [] in name ambigity (due to Java return type allowing []) + int nb = yyextra->name.findRev('['); + if (nb!=-1 && yyextra->args.isEmpty()) // correct for [] in yyextra->name ambigity (due to Java return yyextra->type allowing []) { - args.prepend(name.right(name.length()-nb)); - name=name.left(nb); + yyextra->args.prepend(yyextra->name.right(yyextra->name.length()-nb)); + yyextra->name=yyextra->name.left(nb); } #if 0 { - int l=scope.length(); + int l=yyextra->scope.length(); int i=0; int skipCount=0; cl.resize(0); ctl.resize(0); for (i=0;i<l;i++) { - char c=scope.at(i); + char c=yyextra->scope.at(i); if (c=='<') skipCount++; else if (c=='>') @@ -282,12 +302,12 @@ void parseFuncDecl(const QCString &decl,bool objC,QCString &cl,QCString &t, cl+=c; } } - cl=stripTemplateSpecifiersFromScope(removeRedundantWhiteSpace(scope),FALSE); + cl=stripTemplateSpecifiersFromScope(removeRedundantWhiteSpace(yyextra->scope),FALSE); ctl.resize(0); #endif - cl=scope; - n=removeRedundantWhiteSpace(name); + cl=yyextra->scope; + n=removeRedundantWhiteSpace(yyextra->name); int il,ir; if ((il=n.find('<'))!=-1 && (ir=n.findRev('>'))!=-1) // TODO: handle cases like where n="operator<< <T>" @@ -296,24 +316,23 @@ void parseFuncDecl(const QCString &decl,bool objC,QCString &cl,QCString &t, n=n.left(il); } - //ctl=classTempList.copy(); - //ftl=funcTempList.copy(); - t=removeRedundantWhiteSpace(type); - a=removeRedundantWhiteSpace(args); - exc=removeRedundantWhiteSpace(exceptionString); + //ctl=yyextra->classTempList.copy(); + //ftl=yyextra->funcTempList.copy(); + t=removeRedundantWhiteSpace(yyextra->type); + a=removeRedundantWhiteSpace(yyextra->args); + exc=removeRedundantWhiteSpace(yyextra->exceptionString); if (!t.isEmpty() && t.at(t.length()-1)==')') // for function pointers { a.prepend(")"); t=t.left(t.length()-1); } - //printf("type=`%s' class=`%s' name=`%s' args=`%s'\n", + //printf("yyextra->type=`%s' class=`%s' yyextra->name=`%s' yyextra->args=`%s'\n", // t.data(),cl.data(),n.data(),a.data()); printlex(yy_flex_debug, FALSE, __FILE__, NULL); + declinfoYYlex_destroy(g_yyscanner); return; - - } //extern "C" { // some bogus code to keep the compiler happy @@ -324,18 +343,18 @@ void parseFuncDecl(const QCString &decl,bool objC,QCString &cl,QCString &t, #if 0 void dumpDecl(const char *s) { - QCString className; + QCString yyextra->className; QCString classTNames; - QCString type; - QCString name; - QCString args; + QCString yyextra->type; + QCString yyextra->name; + QCString yyextra->args; QCString funcTNames; msg("-----------------------------------------\n"); - parseFuncDecl(s,className,classTNames,type,name,args,funcTNames); - msg("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() + parseFuncDecl(s,yyextra->className,classTNames,yyextra->type,yyextra->name,yyextra->args,funcTNames); + msg("yyextra->type=`%s' class=`%s' classTempl=`%s' yyextra->name=`%s' " + "funcTemplateNames=`%s' yyextra->args=`%s'\n", + yyextra->type.data(),yyextra->className.data(),classTNames.data(), + yyextra->name.data(),funcTNames.data(),yyextra->args.data() ); } @@ -346,11 +365,11 @@ int main() 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 * )"); + dumpDecl("yyextra->name< T > :: operator () (int bla)"); + dumpDecl("yyextra->name< T > :: operator << (int bla)"); + dumpDecl("yyextra->name< T > :: operator << <> (int bla)"); + dumpDecl("yyextra->className::func()"); + dumpDecl("void ( * yyextra->Name < T > :: bla ) ( int, char * )"); } #endif diff --git a/src/defgen.cpp b/src/defgen.cpp index a8f89c5..ab19c2a 100644 --- a/src/defgen.cpp +++ b/src/defgen.cpp @@ -27,6 +27,7 @@ #include "defargs.h" #include "outputgen.h" #include "dot.h" +#include "dotclassgraph.h" #include "arguments.h" #include "memberlist.h" #include "namespacedef.h" @@ -144,7 +145,7 @@ void generateDEFForMember(MemberDef *md, if (isFunc) //function { ArgumentList *declAl = new ArgumentList; - ArgumentList *defAl = md->argumentList(); + const ArgumentList *defAl = md->argumentList(); stringToArgumentList(md->argsString(),declAl); QCString fcnPrefix = " " + memPrefix + "param-"; @@ -220,7 +221,7 @@ void generateDEFForMember(MemberDef *md, // TODO: exceptions, const volatile if (md->memberType()==MemberType_Enumeration) // enum { - MemberList *enumList = md->enumFieldList(); + const MemberList *enumList = md->enumFieldList(); if (enumList!=0) { MemberListIterator emli(*enumList); @@ -466,14 +467,14 @@ void generateDEFForClass(ClassDef *cd,FTextStream &t) t << " cp-documentation = <<_EnD_oF_dEf_TeXt_" << endl << cd->documentation() << endl << "_EnD_oF_dEf_TeXt_;" << endl; - DotClassGraph inheritanceGraph(cd,DotNode::Inheritance); + DotClassGraph inheritanceGraph(cd,Inheritance); if (!inheritanceGraph.isTrivial()) { t << " cp-inheritancegraph = <<_EnD_oF_dEf_TeXt_" << endl; inheritanceGraph.writeDEF(t); t << endl << "_EnD_oF_dEf_TeXt_;" << endl; } - DotClassGraph collaborationGraph(cd,DotNode::Collaboration); + DotClassGraph collaborationGraph(cd,Collaboration); if (!collaborationGraph.isTrivial()) { t << " cp-collaborationgraph = <<_EnD_oF_dEf_TeXt_" << endl; diff --git a/src/definition.cpp b/src/definition.cpp index 1233add..b9c40f6 100644 --- a/src/definition.cpp +++ b/src/definition.cpp @@ -223,7 +223,7 @@ static bool matchExcludedSymbols(const char *name) return FALSE; } -void DefinitionImpl::addToMap(const char *name,Definition *d) +static void addToMap(const char *name,Definition *d) { bool vhdlOpt = Config_getBool(OPTIMIZE_OUTPUT_VHDL); QCString symbolName = name; @@ -270,7 +270,7 @@ void DefinitionImpl::addToMap(const char *name,Definition *d) } } -void DefinitionImpl::removeFromMap(Definition *d) +static void removeFromMap(Definition *d) { QCString symbolName = d->_symbolName(); if (!symbolName.isEmpty()) @@ -532,7 +532,7 @@ void DefinitionImpl::addSectionsToIndex() } } -void DefinitionImpl::writeDocAnchorsToTagFile(FTextStream &tagFile) +void DefinitionImpl::writeDocAnchorsToTagFile(FTextStream &tagFile) const { if (m_impl->sectionDict) { @@ -1047,7 +1047,7 @@ QCString DefinitionImpl::getSourceAnchor() const } /*! Write a reference to the source code defining this definition */ -void DefinitionImpl::writeSourceDef(OutputList &ol,const char *) +void DefinitionImpl::writeSourceDef(OutputList &ol,const char *) const { static bool latexSourceCode = Config_getBool(LATEX_SOURCE_CODE); static bool rtfSourceCode = Config_getBool(RTF_SOURCE_CODE); @@ -1259,7 +1259,7 @@ bool DefinitionImpl::hasSources() const } /*! Write code of this definition into the documentation */ -void DefinitionImpl::writeInlineCode(OutputList &ol,const char *scopeName) +void DefinitionImpl::writeInlineCode(OutputList &ol,const char *scopeName) const { static bool inlineSources = Config_getBool(INLINE_SOURCES); ol.pushGeneratorState(); @@ -1278,8 +1278,8 @@ void DefinitionImpl::writeInlineCode(OutputList &ol,const char *scopeName) ParserInterface *pIntf = Doxygen::parserManager->getParser(m_impl->defFileExt); pIntf->resetCodeParserState(); //printf("Read:\n`%s'\n\n",codeFragment.data()); - MemberDef *thisMd = 0; - if (definitionType()==TypeMember) thisMd = dynamic_cast <MemberDef*>(this); + const MemberDef *thisMd = 0; + if (definitionType()==TypeMember) thisMd = dynamic_cast <const MemberDef*>(this); ol.startCodeFragment(); pIntf->parseCode(ol, // codeOutIntf @@ -1305,7 +1305,7 @@ void DefinitionImpl::writeInlineCode(OutputList &ol,const char *scopeName) * definition is used. */ void DefinitionImpl::_writeSourceRefList(OutputList &ol,const char *scopeName, - const QCString &text,MemberSDict *members,bool /*funcOnly*/) + const QCString &text,MemberSDict *members,bool /*funcOnly*/) const { static bool latexSourceCode = Config_getBool(LATEX_SOURCE_CODE); static bool docbookSourceCode = Config_getBool(DOCBOOK_PROGRAMLISTING); @@ -1456,12 +1456,12 @@ void DefinitionImpl::_writeSourceRefList(OutputList &ol,const char *scopeName, ol.popGeneratorState(); } -void DefinitionImpl::writeSourceReffedBy(OutputList &ol,const char *scopeName) +void DefinitionImpl::writeSourceReffedBy(OutputList &ol,const char *scopeName) const { _writeSourceRefList(ol,scopeName,theTranslator->trReferencedBy(),m_impl->sourceRefByDict,FALSE); } -void DefinitionImpl::writeSourceRefs(OutputList &ol,const char *scopeName) +void DefinitionImpl::writeSourceRefs(OutputList &ol,const char *scopeName) const { _writeSourceRefList(ol,scopeName,theTranslator->trReferences(),m_impl->sourceRefsDict,TRUE); } @@ -1491,7 +1491,7 @@ bool DefinitionImpl::hasUserDocumentation() const } -void DefinitionImpl::addSourceReferencedBy(MemberDef *md) +void DefinitionImpl::addSourceReferencedBy(const MemberDef *md) { if (md) { @@ -1514,7 +1514,7 @@ void DefinitionImpl::addSourceReferencedBy(MemberDef *md) } } -void DefinitionImpl::addSourceReferences(MemberDef *md) +void DefinitionImpl::addSourceReferences(const MemberDef *md) { if (md) { @@ -1542,7 +1542,7 @@ Definition *DefinitionImpl::findInnerCompound(const char *) const return 0; } -void DefinitionImpl::addInnerCompound(Definition *) +void DefinitionImpl::addInnerCompound(const Definition *) { err("DefinitionImpl::addInnerCompound() called\n"); } @@ -1796,7 +1796,7 @@ void DefinitionImpl::writeNavigationPath(OutputList &ol) const } // TODO: move to htmlgen -void DefinitionImpl::writeToc(OutputList &ol, const LocalToc &localToc) +void DefinitionImpl::writeToc(OutputList &ol, const LocalToc &localToc) const { SectionDict *sectionDict = m_impl->sectionDict; if (sectionDict==0) return; @@ -1936,7 +1936,7 @@ void DefinitionImpl::writeToc(OutputList &ol, const LocalToc &localToc) //---------------------------------------------------------------------------------------- -SectionDict * DefinitionImpl::getSectionDict(void) +SectionDict * DefinitionImpl::getSectionDict() const { return m_impl->sectionDict; } @@ -2251,7 +2251,7 @@ int DefinitionImpl::getDefColumn() const return m_impl->defColumn; } -void DefinitionImpl::setCookie(Cookie *cookie) +void DefinitionImpl::setCookie(Cookie *cookie) const { delete m_impl->cookie; m_impl->cookie = cookie; @@ -2262,11 +2262,26 @@ Definition::Cookie *DefinitionImpl::cookie() const return m_impl->cookie; } -void DefinitionImpl::writeQuickMemberLinks(OutputList &,MemberDef *) const +void DefinitionImpl::writeQuickMemberLinks(OutputList &,const MemberDef *) const { } -void DefinitionImpl::writeSummaryLinks(OutputList &) +void DefinitionImpl::writeSummaryLinks(OutputList &) const { } +//--------------------------------------------------------------------------------- + +DefinitionAliasImpl::DefinitionAliasImpl(const Definition *scope,const Definition *alias) + : m_scope(scope), m_def(alias), m_cookie(0) +{ + //printf("%s::addToMap(%s)\n",qPrint(name()),qPrint(alias->name())); + addToMap(alias->name(),this); +} + +DefinitionAliasImpl::~DefinitionAliasImpl() +{ + //printf("~DefinitionAliasImpl()\n"); + removeFromMap(this); +} + diff --git a/src/definition.h b/src/definition.h index a2307f7..db9bbbc 100644 --- a/src/definition.h +++ b/src/definition.h @@ -105,6 +105,8 @@ class Definition : public DefinitionIntf //----------------------------------------------------------------------------------- // ---- getters ----- //----------------------------------------------------------------------------------- + /*! Returns TRUE if this is an alias of another definition */ + virtual bool isAlias() const = 0; /*! Returns the name of the definition */ virtual QCString name() const = 0; @@ -272,7 +274,10 @@ class Definition : public DefinitionIntf virtual QCString id() const = 0; /** returns the section dictionary, only of importance for pagedef */ - virtual SectionDict * getSectionDict(void) = 0; + virtual SectionDict * getSectionDict() const = 0; + + virtual QCString navigationPathAsString() const = 0; + virtual QCString pathFragment() const = 0; //----------------------------------------------------------------------------------- // ---- setters ----- @@ -304,54 +309,57 @@ class Definition : public DefinitionIntf /*! Sets the tag file id via which this definition was imported. */ virtual void setReference(const char *r) = 0; - /*! Add the list of anchors that mark the sections that are found in the - * documentation. - */ - virtual void addSectionsToDefinition(QList<SectionInfo> *anchorList) = 0; - // source references virtual void setBodySegment(int bls,int ble) = 0; virtual void setBodyDef(FileDef *fd) = 0; - virtual void addSourceReferencedBy(MemberDef *d) = 0; - virtual void addSourceReferences(MemberDef *d) = 0; virtual void setRefItems(const QList<ListItemInfo> *sli) = 0; - virtual void mergeRefItems(Definition *d) = 0; - virtual void addInnerCompound(Definition *d) = 0; virtual void setOuterScope(Definition *d) = 0; virtual void setHidden(bool b) = 0; virtual void setArtificial(bool b) = 0; virtual void setLanguage(SrcLangExt lang) = 0; + virtual void setLocalName(const QCString name) = 0; //----------------------------------------------------------------------------------- // --- actions ---- //----------------------------------------------------------------------------------- - virtual void writeSourceDef(OutputList &ol,const char *scopeName) = 0; - virtual void writeInlineCode(OutputList &ol,const char *scopeName) = 0; - virtual void writeSourceRefs(OutputList &ol,const char *scopeName) = 0; - virtual void writeSourceReffedBy(OutputList &ol,const char *scopeName) = 0; virtual void makePartOfGroup(GroupDef *gd) = 0; - virtual void writeNavigationPath(OutputList &ol) const = 0; - virtual QCString navigationPathAsString() const = 0; - virtual void writeQuickMemberLinks(OutputList &,MemberDef *) const = 0; - virtual void writeSummaryLinks(OutputList &) = 0; - virtual QCString pathFragment() const = 0; - /*! Writes the documentation anchors of the definition to - * the Doxygen::tagFile stream. + /*! Add the list of anchors that mark the sections that are found in the + * documentation. */ - virtual void writeDocAnchorsToTagFile(FTextStream &) = 0; - virtual void setLocalName(const QCString name) = 0; - + virtual void addSectionsToDefinition(QList<SectionInfo> *anchorList) = 0; + virtual void addSourceReferencedBy(const MemberDef *d) = 0; + virtual void addSourceReferences(const MemberDef *d) = 0; + virtual void mergeRefItems(Definition *d) = 0; + virtual void addInnerCompound(const Definition *d) = 0; virtual void addSectionsToIndex() = 0; - virtual void writeToc(OutputList &ol, const LocalToc <) = 0; - virtual void setCookie(Cookie *cookie) = 0; + //----------------------------------------------------------------------------------- + // --- writing output ---- + //----------------------------------------------------------------------------------- + virtual void writeSourceDef(OutputList &ol,const char *scopeName) const = 0; + virtual void writeInlineCode(OutputList &ol,const char *scopeName) const = 0; + virtual void writeSourceRefs(OutputList &ol,const char *scopeName) const = 0; + virtual void writeSourceReffedBy(OutputList &ol,const char *scopeName) const = 0; + virtual void writeNavigationPath(OutputList &ol) const = 0; + virtual void writeQuickMemberLinks(OutputList &,const MemberDef *) const = 0; + virtual void writeSummaryLinks(OutputList &) const = 0; + virtual void writeDocAnchorsToTagFile(FTextStream &) const = 0; + virtual void writeToc(OutputList &ol, const LocalToc <) const = 0; + + //----------------------------------------------------------------------------------- + // --- cookie storage ---- + //----------------------------------------------------------------------------------- + virtual void setCookie(Cookie *cookie) const = 0; virtual Cookie *cookie() const = 0; + //----------------------------------------------------------------------------------- + // --- symbol name ---- + //----------------------------------------------------------------------------------- virtual void _setSymbolName(const QCString &name) = 0; virtual QCString _symbolName() const = 0; }; diff --git a/src/definitionimpl.h b/src/definitionimpl.h index 864d35b..4dd324b 100644 --- a/src/definitionimpl.h +++ b/src/definitionimpl.h @@ -30,13 +30,11 @@ class DefinitionImpl : virtual public Definition bool isSymbol=TRUE); virtual ~DefinitionImpl(); + virtual bool isAlias() const { return FALSE; } virtual QCString name() const; - virtual QCString displayName(bool includeScope=TRUE) const = 0; virtual QCString localName() const; virtual QCString qualifiedName() const; virtual QCString symbolName() const; - virtual QCString getOutputFileBase() const = 0; - virtual QCString anchor() const = 0; virtual QCString getSourceFileBase() const; virtual QCString getSourceAnchor() const; virtual QCString documentation() const; @@ -55,8 +53,6 @@ class DefinitionImpl : virtual public Definition virtual int getDefColumn() const; virtual bool hasDocumentation() const; virtual bool hasUserDocumentation() const; - virtual bool isLinkableInProject() const = 0; - virtual bool isLinkable() const = 0; virtual bool isVisibleInProject() const; virtual bool isVisible() const; virtual bool isHidden() const; @@ -79,7 +75,7 @@ class DefinitionImpl : virtual public Definition virtual bool hasSources() const; virtual bool hasBriefDescription() const; virtual QCString id() const; - virtual SectionDict * getSectionDict(void); + virtual SectionDict * getSectionDict() const; virtual void setName(const char *name); virtual void setId(const char *name); virtual void setDefFile(const QCString& df,int defLine,int defColumn); @@ -90,30 +86,30 @@ class DefinitionImpl : virtual public Definition virtual void addSectionsToDefinition(QList<SectionInfo> *anchorList); virtual void setBodySegment(int bls,int ble); virtual void setBodyDef(FileDef *fd); - virtual void addSourceReferencedBy(MemberDef *d); - virtual void addSourceReferences(MemberDef *d); + virtual void addSourceReferencedBy(const MemberDef *d); + virtual void addSourceReferences(const MemberDef *d); virtual void setRefItems(const QList<ListItemInfo> *sli); virtual void mergeRefItems(Definition *d); - virtual void addInnerCompound(Definition *d); + virtual void addInnerCompound(const Definition *d); virtual void setOuterScope(Definition *d); virtual void setHidden(bool b); virtual void setArtificial(bool b); virtual void setLanguage(SrcLangExt lang); - virtual void writeSourceDef(OutputList &ol,const char *scopeName); - virtual void writeInlineCode(OutputList &ol,const char *scopeName); - virtual void writeSourceRefs(OutputList &ol,const char *scopeName); - virtual void writeSourceReffedBy(OutputList &ol,const char *scopeName); + virtual void writeSourceDef(OutputList &ol,const char *scopeName) const; + virtual void writeInlineCode(OutputList &ol,const char *scopeName) const; + virtual void writeSourceRefs(OutputList &ol,const char *scopeName) const; + virtual void writeSourceReffedBy(OutputList &ol,const char *scopeName) const; virtual void makePartOfGroup(GroupDef *gd); virtual void writeNavigationPath(OutputList &ol) const; virtual QCString navigationPathAsString() const; - virtual void writeQuickMemberLinks(OutputList &,MemberDef *) const; - virtual void writeSummaryLinks(OutputList &); + virtual void writeQuickMemberLinks(OutputList &,const MemberDef *) const; + virtual void writeSummaryLinks(OutputList &) const; virtual QCString pathFragment() const; - virtual void writeDocAnchorsToTagFile(FTextStream &); + virtual void writeDocAnchorsToTagFile(FTextStream &) const; virtual void setLocalName(const QCString name); virtual void addSectionsToIndex(); - virtual void writeToc(OutputList &ol, const LocalToc <); - virtual void setCookie(Cookie *cookie); + virtual void writeToc(OutputList &ol, const LocalToc <) const; + virtual void setCookie(Cookie *cookie) const; virtual Cookie *cookie() const; protected: @@ -121,15 +117,12 @@ class DefinitionImpl : virtual public Definition DefinitionImpl(const DefinitionImpl &d); private: - static void addToMap(const char *name,Definition *d); - static void removeFromMap(Definition *d); - virtual void _setSymbolName(const QCString &name); virtual QCString _symbolName() const ; int _getXRefListId(const char *listName) const; void _writeSourceRefList(OutputList &ol,const char *scopeName, - const QCString &text,MemberSDict *members,bool); + const QCString &text,MemberSDict *members,bool) const; void _setBriefDescription(const char *b,const char *briefFile,int briefLine); void _setDocumentation(const char *d,const char *docFile,int docLine,bool stripWhiteSpace,bool atTop); void _setInbodyDocumentation(const char *d,const char *docFile,int docLine); @@ -140,5 +133,152 @@ class DefinitionImpl : virtual public Definition IMPL *m_impl; // internal structure holding all private data }; +class DefinitionAliasImpl : virtual public Definition +{ + public: + DefinitionAliasImpl(const Definition *scope,const Definition *alias); + virtual ~DefinitionAliasImpl(); + + virtual bool isAlias() const { return TRUE; } + virtual QCString name() const + { return m_def->name(); } + virtual QCString localName() const + { return m_def->localName(); } + virtual QCString qualifiedName() const + { return m_def->qualifiedName(); } + virtual QCString symbolName() const + { return m_def->symbolName(); } + virtual QCString getSourceFileBase() const + { return m_def->getSourceFileBase(); } + virtual QCString getSourceAnchor() const + { return m_def->getSourceAnchor(); } + virtual QCString documentation() const + { return m_def->documentation(); } + virtual int docLine() const + { return m_def->docLine(); } + virtual QCString docFile() const + { return m_def->docFile(); } + virtual QCString briefDescription(bool abbreviate=FALSE) const + { return m_def->briefDescription(abbreviate); } + virtual QCString briefDescriptionAsTooltip() const + { return m_def->briefDescriptionAsTooltip(); } + virtual int briefLine() const + { return m_def->briefLine(); } + virtual QCString inbodyDocumentation() const + { return m_def->inbodyDocumentation(); } + virtual QCString inbodyFile() const + { return m_def->inbodyFile(); } + virtual int inbodyLine() const + { return m_def->inbodyLine(); } + virtual QCString briefFile() const + { return m_def->briefFile(); } + virtual QCString getDefFileName() const + { return m_def->getDefFileName(); } + virtual QCString getDefFileExtension() const + { return m_def->getDefFileExtension(); } + virtual int getDefLine() const + { return m_def->getDefLine(); } + virtual int getDefColumn() const + { return m_def->getDefColumn(); } + virtual bool hasDocumentation() const + { return m_def->hasDocumentation(); } + virtual bool hasUserDocumentation() const + { return m_def->hasUserDocumentation(); } + virtual bool isVisibleInProject() const + { return m_def->isVisibleInProject(); } + virtual bool isVisible() const + { return m_def->isVisible(); } + virtual bool isHidden() const + { return m_def->isHidden(); } + virtual bool isArtificial() const + { return m_def->isArtificial(); } + virtual QCString getReference() const + { return m_def->getReference(); } + virtual bool isReference() const + { return m_def->isReference(); } + virtual QCString externalReference(const QCString &relPath) const + { return m_def->externalReference(relPath); } + virtual int getStartBodyLine() const + { return m_def->getStartBodyLine(); } + virtual int getEndBodyLine() const + { return m_def->getEndBodyLine(); } + virtual FileDef *getBodyDef() const + { return m_def->getBodyDef(); } + virtual SrcLangExt getLanguage() const + { return m_def->getLanguage(); } + virtual GroupList *partOfGroups() const + { return m_def->partOfGroups(); } + virtual bool isLinkableViaGroup() const + { return m_def->isLinkableViaGroup(); } + virtual QList<ListItemInfo> *xrefListItems() const + { return m_def->xrefListItems(); } + virtual Definition *findInnerCompound(const char *name) const + { return m_def->findInnerCompound(name); } + virtual Definition *getOuterScope() const + { return const_cast<Definition*>(m_scope); } + virtual MemberSDict *getReferencesMembers() const + { return m_def->getReferencesMembers(); } + virtual MemberSDict *getReferencedByMembers() const + { return m_def->getReferencedByMembers(); } + virtual bool hasSections() const + { return m_def->hasSections(); } + virtual bool hasSources() const + { return m_def->hasSources(); } + virtual bool hasBriefDescription() const + { return m_def->hasBriefDescription(); } + virtual QCString id() const + { return m_def->id(); } + virtual SectionDict * getSectionDict() const + { return m_def->getSectionDict(); } + virtual QCString navigationPathAsString() const + { return m_def->navigationPathAsString(); } + virtual QCString pathFragment() const + { return m_def->pathFragment(); } + virtual void setName(const char *name) { } + virtual void setId(const char *name) { } + virtual void setDefFile(const QCString& df,int defLine,int defColumn) {} + virtual void setDocumentation(const char *d,const char *docFile,int docLine,bool stripWhiteSpace=TRUE) {} + virtual void setBriefDescription(const char *b,const char *briefFile,int briefLine) {} + virtual void setInbodyDocumentation(const char *d,const char *docFile,int docLine) {} + virtual void setReference(const char *r) {} + virtual void addSectionsToDefinition(QList<SectionInfo> *anchorList) {} + virtual void setBodySegment(int bls,int ble) {} + virtual void setBodyDef(FileDef *fd) {} + virtual void addSourceReferencedBy(const MemberDef *d) {} + virtual void addSourceReferences(const MemberDef *d) {} + virtual void setRefItems(const QList<ListItemInfo> *sli) {} + virtual void mergeRefItems(Definition *d) {} + virtual void addInnerCompound(const Definition *d) {} + virtual void setOuterScope(Definition *d) {} + virtual void setHidden(bool b) {} + virtual void setArtificial(bool b) {} + virtual void setLanguage(SrcLangExt lang) {} + virtual void writeSourceDef(OutputList &ol,const char *scopeName) const {} + virtual void writeInlineCode(OutputList &ol,const char *scopeName) const {} + virtual void writeSourceRefs(OutputList &ol,const char *scopeName) const {} + virtual void writeSourceReffedBy(OutputList &ol,const char *scopeName) const {} + virtual void makePartOfGroup(GroupDef *gd) {} + virtual void writeNavigationPath(OutputList &ol) const {} + virtual void writeQuickMemberLinks(OutputList &,const MemberDef *) const {} + virtual void writeSummaryLinks(OutputList &) const {} + virtual void writeDocAnchorsToTagFile(FTextStream &) const {} + virtual void setLocalName(const QCString name) {} + virtual void addSectionsToIndex() {} + virtual void writeToc(OutputList &ol, const LocalToc <) const {} + virtual void setCookie(Cookie *cookie) const { delete m_cookie; m_cookie = cookie; } + virtual Cookie *cookie() const { return m_cookie; } + protected: + const Definition *getAlias() const { return m_def; } + const Definition *getScope() const { return m_scope; } + + private: + virtual void _setSymbolName(const QCString &name) { m_symbolName = name; } + virtual QCString _symbolName() const { return m_symbolName; } + const Definition *m_scope; + const Definition *m_def; + mutable Cookie *m_cookie; + QCString m_symbolName; +}; + #endif diff --git a/src/dia.cpp b/src/dia.cpp index 5adbc7c..8dab5b0 100644 --- a/src/dia.cpp +++ b/src/dia.cpp @@ -65,6 +65,8 @@ void writeDiaGraphFromFile(const char *inFile,const char *outDir, portable_sysTimerStart(); if ((exitCode=portable_system(diaExe,diaArgs,FALSE))!=0) { + err("Problems running %s. Check your installation or look typos in you dia file %s\n", + diaExe.data(),inFile); portable_sysTimerStop(); goto error; } diff --git a/src/diagram.cpp b/src/diagram.cpp index 808191e..06480fc 100644 --- a/src/diagram.cpp +++ b/src/diagram.cpp @@ -42,7 +42,7 @@ class DiagramItemList; class DiagramItem { public: - DiagramItem(DiagramItem *p,int number,ClassDef *cd, + DiagramItem(DiagramItem *p,int number,const ClassDef *cd, Protection prot,Specifier virt,const char *ts); ~DiagramItem(); QCString label() const; @@ -60,7 +60,7 @@ class DiagramItem Specifier virtualness() const { return virt; } void putInList() { inList=TRUE; } bool isInList() const { return inList; } - ClassDef *getClassDef() const { return classDef; } + const ClassDef *getClassDef() const { return classDef; } private: DiagramItemList *children; DiagramItem *parent; @@ -70,7 +70,7 @@ class DiagramItem Specifier virt; QCString templSpec; bool inList; - ClassDef *classDef; + const ClassDef *classDef; }; /** Class representing a list of DiagramItem object. */ @@ -91,7 +91,7 @@ class DiagramRow : public QList<DiagramItem> level=l; setAutoDelete(TRUE); } - void insertClass(DiagramItem *parent,ClassDef *cd,bool doBases, + void insertClass(DiagramItem *parent,const ClassDef *cd,bool doBases, Protection prot,Specifier virt,const char *ts); uint number() { return level; } private: @@ -111,7 +111,7 @@ class DiagramRowIterator : public QListIterator<DiagramRow> class TreeDiagram : public QList<DiagramRow> { public: - TreeDiagram(ClassDef *root,bool doBases); + TreeDiagram(const ClassDef *root,bool doBases); ~TreeDiagram(); void computeLayout(); uint computeRows(); @@ -252,7 +252,7 @@ static void writeVectorBox(FTextStream &t,DiagramItem *di, if (di->virtualness()==Virtual) t << "solid\n"; } -static void writeMapArea(FTextStream &t,ClassDef *cd,QCString relPath, +static void writeMapArea(FTextStream &t,const ClassDef *cd,QCString relPath, int x,int y,int w,int h) { if (cd->isLinkable()) @@ -283,7 +283,7 @@ static void writeMapArea(FTextStream &t,ClassDef *cd,QCString relPath, } //----------------------------------------------------------------------------- -DiagramItem::DiagramItem(DiagramItem *p,int number,ClassDef *cd, +DiagramItem::DiagramItem(DiagramItem *p,int number,const ClassDef *cd, Protection pr,Specifier vi,const char *ts) { parent=p; @@ -354,7 +354,7 @@ void DiagramItem::addChild(DiagramItem *di) children->append(di); } -void DiagramRow::insertClass(DiagramItem *parent,ClassDef *cd,bool doBases, +void DiagramRow::insertClass(DiagramItem *parent,const ClassDef *cd,bool doBases, Protection prot,Specifier virt,const char *ts) { //if (cd->visited) return; // the visit check does not work in case of @@ -406,7 +406,7 @@ void DiagramRow::insertClass(DiagramItem *parent,ClassDef *cd,bool doBases, } } -TreeDiagram::TreeDiagram(ClassDef *root,bool doBases) +TreeDiagram::TreeDiagram(const ClassDef *root,bool doBases) { setAutoDelete(TRUE); DiagramRow *row=new DiagramRow(this,0); @@ -1024,7 +1024,7 @@ void clearVisitFlags() } } -ClassDiagram::ClassDiagram(ClassDef *root) +ClassDiagram::ClassDiagram(const ClassDef *root) { clearVisitFlags(); base = new TreeDiagram(root,TRUE); diff --git a/src/diagram.h b/src/diagram.h index 2922657..05af28e 100644 --- a/src/diagram.h +++ b/src/diagram.h @@ -29,7 +29,7 @@ class FTextStream; class ClassDiagram { public: - ClassDiagram(ClassDef *root); + ClassDiagram(const ClassDef *root); ~ClassDiagram(); void writeFigure(FTextStream &t,const char *path, const char *file) const; diff --git a/src/dirdef.cpp b/src/dirdef.cpp index ae3a6a3..5db8b99 100644 --- a/src/dirdef.cpp +++ b/src/dirdef.cpp @@ -8,6 +8,7 @@ #include "language.h" #include "message.h" #include "dot.h" +#include "dotdirdeps.h" #include "layout.h" #include "ftextstream.h" #include "config.h" @@ -38,7 +39,7 @@ class DirDefImpl : public DefinitionImpl, public DirDef virtual DirDef *parent() const { return m_parent; } virtual int dirCount() const { return m_dirCount; } virtual const QDict<UsedDir> *usedDirs() const { return m_usedDirs; } - virtual bool isParentOf(DirDef *dir) const; + virtual bool isParentOf(const DirDef *dir) const; virtual bool depGraphIsTrivial() const; virtual QCString shortTitle() const; virtual bool hasDetailedDescription() const; @@ -726,7 +727,7 @@ void DirDefImpl::computeDependencies() } } -bool DirDefImpl::isParentOf(DirDef *dir) const +bool DirDefImpl::isParentOf(const DirDef *dir) const { if (dir->parent()==this) // this is a parent of dir return TRUE; diff --git a/src/dirdef.h b/src/dirdef.h index 2bca93e..2ea54af 100644 --- a/src/dirdef.h +++ b/src/dirdef.h @@ -63,7 +63,7 @@ class DirDef : virtual public Definition virtual DirDef *parent() const = 0; virtual int dirCount() const = 0; virtual const QDict<UsedDir> *usedDirs() const = 0; - virtual bool isParentOf(DirDef *dir) const = 0; + virtual bool isParentOf(const DirDef *dir) const = 0; virtual bool depGraphIsTrivial() const = 0; virtual QCString shortTitle() const = 0; virtual bool hasDetailedDescription() const = 0; @@ -125,16 +125,16 @@ class UsedDir class DirRelation { public: - DirRelation(const QCString &name,DirDef *src,UsedDir *dst) + DirRelation(const QCString &name,const DirDef *src,UsedDir *dst) : m_name(name), m_src(src), m_dst(dst) {} - DirDef *source() const { return m_src; } + const DirDef *source() const { return m_src; } UsedDir *destination() const { return m_dst; } void writeDocumentation(OutputList &ol); QCString getOutputFileBase() const { return m_name; } private: QCString m_name; - DirDef *m_src; + const DirDef *m_src; UsedDir *m_dst; }; diff --git a/src/docbookgen.cpp b/src/docbookgen.cpp index adf36b0..7fe849a 100644 --- a/src/docbookgen.cpp +++ b/src/docbookgen.cpp @@ -33,6 +33,11 @@ #include "defargs.h" #include "outputgen.h" #include "dot.h" +#include "dotcallgraph.h" +#include "dotclassgraph.h" +#include "dotdirdeps.h" +#include "dotgroupcollaboration.h" +#include "dotincldepgraph.h" #include "pagedef.h" #include "filename.h" #include "version.h" @@ -180,7 +185,7 @@ void DocbookCodeGenerator::startCodeLine(bool) } void DocbookCodeGenerator::endCodeLine() { - m_t << endl; + if (m_insideCodeLine) m_t << endl; Docbook_DB(("(endCodeLine)\n")); m_lineNumber = -1; m_refId.resize(0); @@ -230,7 +235,7 @@ void DocbookCodeGenerator::writeLineNumber(const char *ref,const char *fileName, } } -void DocbookCodeGenerator::setCurrentDoc(Definition *,const char *,bool) +void DocbookCodeGenerator::setCurrentDoc(const Definition *,const char *,bool) { } void DocbookCodeGenerator::addWord(const char *,bool) @@ -238,7 +243,7 @@ void DocbookCodeGenerator::addWord(const char *,bool) } void DocbookCodeGenerator::finish() { - if (m_insideCodeLine) endCodeLine(); + endCodeLine(); } void DocbookCodeGenerator::startCodeFragment() { @@ -246,6 +251,9 @@ void DocbookCodeGenerator::startCodeFragment() } void DocbookCodeGenerator::endCodeFragment() { + //endCodeLine checks is there is still an open code line, if so closes it. + endCodeLine(); + m_t << "</computeroutput></literallayout>" << endl; } @@ -537,7 +545,7 @@ DB_GEN_C2("IndexSections " << is) { t << "</title>" << endl; ClassSDict::Iterator cli(*Doxygen::classSDict); - ClassDef *cd=0; + const ClassDef *cd=0; bool found=FALSE; for (cli.toFirst();(cd=cli.current()) && !found;++cli) { @@ -572,7 +580,7 @@ DB_GEN_C2("IndexSections " << is) for (fnli.toFirst();(fn=fnli.current());++fnli) { FileNameIterator fni(*fn); - FileDef *fd; + const FileDef *fd; for (;(fd=fni.current());++fni) { if (fd->isLinkableInProject()) @@ -648,7 +656,7 @@ DB_GEN_C } } } -void DocbookGenerator::writeDoc(DocNode *n,Definition *ctx,MemberDef *) +void DocbookGenerator::writeDoc(DocNode *n,const Definition *ctx,const MemberDef *) { DB_GEN_C DocbookDocVisitor *visitor = @@ -1002,6 +1010,9 @@ DB_GEN_C void DocbookGenerator::endCodeFragment() { DB_GEN_C + //endCodeLine checks is there is still an open code line, if so closes it. + endCodeLine(); + t << "</programlisting>"; } void DocbookGenerator::startMemberTemplateParams() @@ -1095,7 +1106,7 @@ void DocbookGenerator::startGroupCollaboration() { DB_GEN_C } -void DocbookGenerator::endGroupCollaboration(const DotGroupCollaboration &g) +void DocbookGenerator::endGroupCollaboration(DotGroupCollaboration &g) { DB_GEN_C g.writeGraph(t,GOF_BITMAP,EOF_DocBook,Config_getString(DOCBOOK_OUTPUT),fileName,relPath,FALSE); @@ -1104,7 +1115,7 @@ void DocbookGenerator::startDotGraph() { DB_GEN_C } -void DocbookGenerator::endDotGraph(const DotClassGraph &g) +void DocbookGenerator::endDotGraph(DotClassGraph &g) { DB_GEN_C g.writeGraph(t,GOF_BITMAP,EOF_DocBook,Config_getString(DOCBOOK_OUTPUT),fileName,relPath,TRUE,FALSE); @@ -1113,7 +1124,7 @@ void DocbookGenerator::startInclDepGraph() { DB_GEN_C } -void DocbookGenerator::endInclDepGraph(const DotInclDepGraph &g) +void DocbookGenerator::endInclDepGraph(DotInclDepGraph &g) { DB_GEN_C QCString fn = g.writeGraph(t,GOF_BITMAP,EOF_DocBook,Config_getString(DOCBOOK_OUTPUT), fileName,relPath,FALSE); @@ -1122,7 +1133,7 @@ void DocbookGenerator::startCallGraph() { DB_GEN_C } -void DocbookGenerator::endCallGraph(const DotCallGraph &g) +void DocbookGenerator::endCallGraph(DotCallGraph &g) { DB_GEN_C QCString fn = g.writeGraph(t,GOF_BITMAP,EOF_DocBook,Config_getString(DOCBOOK_OUTPUT), fileName,relPath,FALSE); @@ -1131,7 +1142,7 @@ void DocbookGenerator::startDirDepGraph() { DB_GEN_C } -void DocbookGenerator::endDirDepGraph(const DotDirDeps &g) +void DocbookGenerator::endDirDepGraph(DotDirDeps &g) { DB_GEN_C QCString fn = g.writeGraph(t,GOF_BITMAP,EOF_DocBook,Config_getString(DOCBOOK_OUTPUT), fileName,relPath,FALSE); diff --git a/src/docbookgen.h b/src/docbookgen.h index 08255a1..8f71722 100644 --- a/src/docbookgen.h +++ b/src/docbookgen.h @@ -49,7 +49,7 @@ class DocbookCodeGenerator : public CodeOutputInterface void writeCodeAnchor(const char *); void writeLineNumber(const char *extRef,const char *compId, const char *anchorId,int l); - void setCurrentDoc(Definition *,const char *,bool); + void setCurrentDoc(const Definition *,const char *,bool); void addWord(const char *,bool); void finish(); void startCodeFragment(); @@ -137,7 +137,7 @@ class DocbookGenerator : public OutputGenerator { m_codeGen.writeCodeAnchor(anchor); } // --------------------------- - void writeDoc(DocNode *,Definition *ctx,MemberDef *md); + void writeDoc(DocNode *,const Definition *ctx,const MemberDef *md); /////////////////////////////////////////////////////////////// // structural output interface @@ -281,16 +281,16 @@ class DocbookGenerator : public OutputGenerator void startClassDiagram(); void endClassDiagram(const ClassDiagram &,const char *,const char *); void startDotGraph(); - void endDotGraph(const DotClassGraph &g); + void endDotGraph(DotClassGraph &g); void startInclDepGraph(); - void endInclDepGraph(const DotInclDepGraph &g); + void endInclDepGraph(DotInclDepGraph &g); void startGroupCollaboration(); - void endGroupCollaboration(const DotGroupCollaboration &g); + void endGroupCollaboration(DotGroupCollaboration &g); void startCallGraph(); - void endCallGraph(const DotCallGraph &g); + void endCallGraph(DotCallGraph &g); void startDirDepGraph(); - void endDirDepGraph(const DotDirDeps &g); - void writeGraphicalHierarchy(const DotGfxHierarchyTable &g){DB_GEN_NEW}; + void endDirDepGraph(DotDirDeps &g); + void writeGraphicalHierarchy(DotGfxHierarchyTable &g){DB_GEN_NEW}; void startQuickIndices(){DB_GEN_EMPTY}; void endQuickIndices(){DB_GEN_EMPTY}; void writeSplitBar(const char *){DB_GEN_EMPTY}; @@ -339,7 +339,7 @@ class DocbookGenerator : public OutputGenerator void writeLabel(const char *,bool); void endLabels(); - void setCurrentDoc(Definition *,const char *,bool) {DB_GEN_EMPTY} + void setCurrentDoc(const Definition *,const char *,bool) {DB_GEN_EMPTY} void addWord(const char *,bool) {DB_GEN_EMPTY} private: diff --git a/src/docbookvisitor.cpp b/src/docbookvisitor.cpp index 64425c6..1901454 100644 --- a/src/docbookvisitor.cpp +++ b/src/docbookvisitor.cpp @@ -472,20 +472,22 @@ DB_VIS_C pushEnabled(); m_hide = TRUE; } - SrcLangExt langExt = getLanguageFromFileName(m_langExt); + QCString locLangExt = getFileNameExtension(op->includeFileName()); + if (locLangExt.isEmpty()) locLangExt = m_langExt; + SrcLangExt langExt = getLanguageFromFileName(locLangExt); if (op->type()!=DocIncOperator::Skip) { popEnabled(); if (!m_hide) { - FileDef *fd; + FileDef *fd = 0; if (!op->includeFileName().isEmpty()) { QFileInfo cfi( op->includeFileName() ); fd = createFileDef( cfi.dirPath().utf8(), cfi.fileName().utf8() ); } - Doxygen::parserManager->getParser(m_langExt) + Doxygen::parserManager->getParser(locLangExt) ->parseCode(m_ci,op->context(), op->text(),langExt,op->isExample(), op->exampleFile(), @@ -634,152 +636,152 @@ DB_VIS_C case DocSimpleSect::See: if (m_insidePre) { - m_t << "<formalpara><title>" << theTranslator->trSeeAlso() << ": </title>" << endl; + m_t << "<formalpara><title>" << theTranslator->trSeeAlso() << "</title>" << endl; } else { - m_t << "<formalpara><title>" << convertToDocBook(theTranslator->trSeeAlso()) << ": </title>" << endl; + m_t << "<formalpara><title>" << convertToDocBook(theTranslator->trSeeAlso()) << "</title>" << endl; } break; case DocSimpleSect::Return: if (m_insidePre) { - m_t << "<formalpara><title>" << theTranslator->trReturns()<< ": </title>" << endl; + m_t << "<formalpara><title>" << theTranslator->trReturns()<< "</title>" << endl; } else { - m_t << "<formalpara><title>" << convertToDocBook(theTranslator->trReturns()) << ": </title>" << endl; + m_t << "<formalpara><title>" << convertToDocBook(theTranslator->trReturns()) << "</title>" << endl; } break; case DocSimpleSect::Author: if (m_insidePre) { - m_t << "<formalpara><title>" << theTranslator->trAuthor(TRUE, TRUE) << ": </title>" << endl; + m_t << "<formalpara><title>" << theTranslator->trAuthor(TRUE, TRUE) << "</title>" << endl; } else { - m_t << "<formalpara><title>" << convertToDocBook(theTranslator->trAuthor(TRUE, TRUE)) << ": </title>" << endl; + m_t << "<formalpara><title>" << convertToDocBook(theTranslator->trAuthor(TRUE, TRUE)) << "</title>" << endl; } break; case DocSimpleSect::Authors: if (m_insidePre) { - m_t << "<formalpara><title>" << theTranslator->trAuthor(TRUE, FALSE) << ": </title>" << endl; + m_t << "<formalpara><title>" << theTranslator->trAuthor(TRUE, FALSE) << "</title>" << endl; } else { - m_t << "<formalpara><title>" << convertToDocBook(theTranslator->trAuthor(TRUE, FALSE)) << ": </title>" << endl; + m_t << "<formalpara><title>" << convertToDocBook(theTranslator->trAuthor(TRUE, FALSE)) << "</title>" << endl; } break; case DocSimpleSect::Version: if (m_insidePre) { - m_t << "<formalpara><title>" << theTranslator->trVersion() << ": </title>" << endl; + m_t << "<formalpara><title>" << theTranslator->trVersion() << "</title>" << endl; } else { - m_t << "<formalpara><title>" << convertToDocBook(theTranslator->trVersion()) << ": </title>" << endl; + m_t << "<formalpara><title>" << convertToDocBook(theTranslator->trVersion()) << "</title>" << endl; } break; case DocSimpleSect::Since: if (m_insidePre) { - m_t << "<formalpara><title>" << theTranslator->trSince() << ": </title>" << endl; + m_t << "<formalpara><title>" << theTranslator->trSince() << "</title>" << endl; } else { - m_t << "<formalpara><title>" << convertToDocBook(theTranslator->trSince()) << ": </title>" << endl; + m_t << "<formalpara><title>" << convertToDocBook(theTranslator->trSince()) << "</title>" << endl; } break; case DocSimpleSect::Date: if (m_insidePre) { - m_t << "<formalpara><title>" << theTranslator->trDate() << ": </title>" << endl; + m_t << "<formalpara><title>" << theTranslator->trDate() << "</title>" << endl; } else { - m_t << "<formalpara><title>" << convertToDocBook(theTranslator->trDate()) << ": </title>" << endl; + m_t << "<formalpara><title>" << convertToDocBook(theTranslator->trDate()) << "</title>" << endl; } break; case DocSimpleSect::Note: if (m_insidePre) { - m_t << "<note><title>" << theTranslator->trNote() << ": </title>" << endl; + m_t << "<note><title>" << theTranslator->trNote() << "</title>" << endl; } else { - m_t << "<note><title>" << convertToDocBook(theTranslator->trNote()) << ": </title>" << endl; + m_t << "<note><title>" << convertToDocBook(theTranslator->trNote()) << "</title>" << endl; } break; case DocSimpleSect::Warning: if (m_insidePre) { - m_t << "<warning><title>" << theTranslator->trWarning() << ": </title>" << endl; + m_t << "<warning><title>" << theTranslator->trWarning() << "</title>" << endl; } else { - m_t << "<warning><title>" << convertToDocBook(theTranslator->trWarning()) << ": </title>" << endl; + m_t << "<warning><title>" << convertToDocBook(theTranslator->trWarning()) << "</title>" << endl; } break; case DocSimpleSect::Pre: if (m_insidePre) { - m_t << "<formalpara><title>" << theTranslator->trPrecondition() << ": </title>" << endl; + m_t << "<formalpara><title>" << theTranslator->trPrecondition() << "</title>" << endl; } else { - m_t << "<formalpara><title>" << convertToDocBook(theTranslator->trPrecondition()) << ": </title>" << endl; + m_t << "<formalpara><title>" << convertToDocBook(theTranslator->trPrecondition()) << "</title>" << endl; } break; case DocSimpleSect::Post: if (m_insidePre) { - m_t << "<formalpara><title>" << theTranslator->trPostcondition() << ": </title>" << endl; + m_t << "<formalpara><title>" << theTranslator->trPostcondition() << "</title>" << endl; } else { - m_t << "<formalpara><title>" << convertToDocBook(theTranslator->trPostcondition()) << ": </title>" << endl; + m_t << "<formalpara><title>" << convertToDocBook(theTranslator->trPostcondition()) << "</title>" << endl; } break; case DocSimpleSect::Copyright: if (m_insidePre) { - m_t << "<formalpara><title>" << theTranslator->trCopyright() << ": </title>" << endl; + m_t << "<formalpara><title>" << theTranslator->trCopyright() << "</title>" << endl; } else { - m_t << "<formalpara><title>" << convertToDocBook(theTranslator->trCopyright()) << ": </title>" << endl; + m_t << "<formalpara><title>" << convertToDocBook(theTranslator->trCopyright()) << "</title>" << endl; } break; case DocSimpleSect::Invar: if (m_insidePre) { - m_t << "<formalpara><title>" << theTranslator->trInvariant() << ": </title>" << endl; + m_t << "<formalpara><title>" << theTranslator->trInvariant() << "</title>" << endl; } else { - m_t << "<formalpara><title>" << convertToDocBook(theTranslator->trInvariant()) << ": </title>" << endl; + m_t << "<formalpara><title>" << convertToDocBook(theTranslator->trInvariant()) << "</title>" << endl; } break; case DocSimpleSect::Remark: // <remark> is miising the <title> possibility if (m_insidePre) { - m_t << "<formalpara><title>" << theTranslator->trRemarks() << ": </title>" << endl; + m_t << "<formalpara><title>" << theTranslator->trRemarks() << "</title>" << endl; } else { - m_t << "<formalpara><title>" << convertToDocBook(theTranslator->trRemarks()) << ": </title>" << endl; + m_t << "<formalpara><title>" << convertToDocBook(theTranslator->trRemarks()) << "</title>" << endl; } break; case DocSimpleSect::Attention: if (m_insidePre) { - m_t << "<caution><title>" << theTranslator->trAttention() << ": </title>" << endl; + m_t << "<caution><title>" << theTranslator->trAttention() << "</title>" << endl; } else { - m_t << "<caution><title>" << convertToDocBook(theTranslator->trAttention()) << ": </title>" << endl; + m_t << "<caution><title>" << convertToDocBook(theTranslator->trAttention()) << "</title>" << endl; } break; case DocSimpleSect::User: @@ -1521,22 +1523,6 @@ DB_VIS_C m_t << " "; } -void DocbookDocVisitor::visitPre(DocCopy *) -{ -DB_VIS_C - if (m_hide) return; - // TODO: to be implemented -} - - -void DocbookDocVisitor::visitPost(DocCopy *) -{ -DB_VIS_C - if (m_hide) return; - // TODO: to be implemented -} - - void DocbookDocVisitor::visitPre(DocText *) { DB_VIS_C diff --git a/src/docbookvisitor.h b/src/docbookvisitor.h index 24b1fbb..47275f7 100644 --- a/src/docbookvisitor.h +++ b/src/docbookvisitor.h @@ -127,8 +127,6 @@ class DocbookDocVisitor : public DocVisitor void visitPost(DocXRefItem *); void visitPre(DocInternalRef *); void visitPost(DocInternalRef *); - void visitPre(DocCopy *); - void visitPost(DocCopy *); void visitPre(DocText *); void visitPost(DocText *); void visitPre(DocHtmlBlockQuote *); diff --git a/src/docgroup.cpp b/src/docgroup.cpp new file mode 100644 index 0000000..2dcca70 --- /dev/null +++ b/src/docgroup.cpp @@ -0,0 +1,212 @@ +#include "doxygen.h" +#include "util.h" +#include "entry.h" +#include "message.h" +#include "docgroup.h" + + +void DocGroup::enterFile(const char *fileName,int) +{ + m_openCount = 0; + m_autoGroupStack.setAutoDelete(TRUE); + m_autoGroupStack.clear(); + m_memberGroupId = DOX_NOGROUP; + m_memberGroupDocs.resize(0); + m_memberGroupRelates.resize(0); + m_compoundName=fileName; +} + +void DocGroup::leaveFile(const char *fileName,int line) +{ + //if (m_memberGroupId!=DOX_NOGROUP) + //{ + // warn(fileName,line,"end of file while inside a member group\n"); + //} + m_memberGroupId=DOX_NOGROUP; + m_memberGroupRelates.resize(0); + m_memberGroupDocs.resize(0); + if (!m_autoGroupStack.isEmpty()) + { + warn(fileName,line,"end of file while inside a group"); + } + else if (m_openCount > 0) // < 0 is already handled on close call + { + warn(fileName,line,"end of file with unbalanced grouping commands"); + } +} + +void DocGroup::enterCompound(const char *fileName,int line,const char *name) +{ + if (m_memberGroupId!=DOX_NOGROUP) + { + warn(fileName,line,"try to put compound %s inside a member group\n",name); + } + m_memberGroupId=DOX_NOGROUP; + m_memberGroupRelates.resize(0); + m_memberGroupDocs.resize(0); + m_compoundName = name; + int i = m_compoundName.find('('); + if (i!=-1) + { + m_compoundName=m_compoundName.left(i); // strip category (Obj-C) + } + if (m_compoundName.isEmpty()) + { + m_compoundName=fileName; + } + //printf("groupEnterCompound(%s)\n",name); +} + +void DocGroup::leaveCompound(const char *,int,const char * /*name*/) +{ + //printf("groupLeaveCompound(%s)\n",name); + //if (m_memberGroupId!=DOX_NOGROUP) + //{ + // warn(fileName,line,"end of compound %s while inside a member group\n",name); + //} + m_memberGroupId=DOX_NOGROUP; + m_memberGroupRelates.resize(0); + m_memberGroupDocs.resize(0); + m_compoundName.resize(0); +} + +int DocGroup::findExistingGroup(int &groupId,const MemberGroupInfo *info) +{ + //printf("findExistingGroup %s:%s\n",info->header.data(),info->compoundName.data()); + QIntDictIterator<MemberGroupInfo> di(Doxygen::memGrpInfoDict); + MemberGroupInfo *mi; + for (di.toFirst();(mi=di.current());++di) + { + if (m_compoundName==mi->compoundName && // same file or scope + !mi->header.isEmpty() && // not a nameless group + qstricmp(mi->header,info->header)==0 // same header name + ) + { + //printf("Found it!\n"); + return (int)di.currentKey(); // put the item in this group + } + } + groupId++; // start new group + return groupId; +} + +void DocGroup::open(Entry *e,const char *,int, bool implicit) +{ + if (!implicit) m_openCount++; + //printf("==> openGroup(name=%s,sec=%x) m_autoGroupStack=%d\n", + // e->name.data(),e->section,m_autoGroupStack.count()); + if (e->section==Entry::GROUPDOC_SEC) // auto group + { + m_autoGroupStack.push(new Grouping(e->name,e->groupingPri())); + } + else // start of a member group + { + //printf(" membergroup id=%d %s\n",m_memberGroupId,m_memberGroupHeader.data()); + if (m_memberGroupId==DOX_NOGROUP) // no group started yet + { + static int curGroupId=0; + + MemberGroupInfo *info = new MemberGroupInfo; + info->header = m_memberGroupHeader.stripWhiteSpace(); + info->compoundName = m_compoundName; + m_memberGroupId = findExistingGroup(curGroupId,info); + //printf(" use membergroup %d\n",m_memberGroupId); + Doxygen::memGrpInfoDict.insert(m_memberGroupId,info); + + m_memberGroupRelates = e->relates; + e->mGrpId = m_memberGroupId; + } + } +} + +void DocGroup::close(Entry *e,const char *fileName,int line,bool foundInline) +{ + if (m_openCount < 1) + { + warn(fileName,line,"unbalanced grouping commands"); + } + else + { + m_openCount--; + } + //printf("==> closeGroup(name=%s,sec=%x,file=%s,line=%d) m_autoGroupStack=%d\n", + // e->name.data(),e->section,fileName,line,m_autoGroupStack.count()); + if (m_memberGroupId!=DOX_NOGROUP) // end of member group + { + MemberGroupInfo *info=Doxygen::memGrpInfoDict.find(m_memberGroupId); + if (info) // known group + { + info->doc = m_memberGroupDocs; + info->docFile = fileName; + info->docLine = line; + } + m_memberGroupId=DOX_NOGROUP; + m_memberGroupRelates.resize(0); + m_memberGroupDocs.resize(0); + if (!foundInline) e->mGrpId=DOX_NOGROUP; + //printf("new group id=%d\n",m_memberGroupId); + } + else if (!m_autoGroupStack.isEmpty()) // end of auto group + { + Grouping *grp = m_autoGroupStack.pop(); + // see bug577005: we should not remove the last group for e + if (!foundInline) e->groups->removeLast(); + //printf("Removing %s e=%p\n",grp->groupname.data(),e); + delete grp; + if (!foundInline) initGroupInfo(e); + } +} + +void DocGroup::initGroupInfo(Entry *e) +{ + //printf("==> initGroup(id=%d,related=%s,e=%p)\n",m_memberGroupId, + // m_memberGroupRelates.data(),e); + e->mGrpId = m_memberGroupId; + e->relates = m_memberGroupRelates; + if (!m_autoGroupStack.isEmpty()) + { + //printf("Appending group %s to %s: count=%d entry=%p\n", + // m_autoGroupStack.top()->groupname.data(), + // e->name.data(),e->groups->count(),e); + e->groups->append(new Grouping(*m_autoGroupStack.top())); + } +} + +void DocGroup::addDocs(Entry *e) +{ + if (e->section==Entry::MEMBERGRP_SEC) + { + m_memberGroupDocs=e->brief.stripWhiteSpace(); + e->doc = stripLeadingAndTrailingEmptyLines(e->doc,e->docLine); + if (!m_memberGroupDocs.isEmpty() && !e->doc.isEmpty()) + { + m_memberGroupDocs+="\n\n"; + } + m_memberGroupDocs+=e->doc; + MemberGroupInfo *info=Doxygen::memGrpInfoDict.find(m_memberGroupId); + if (info) + { + info->doc = m_memberGroupDocs; + info->docFile = e->docFile; + info->docLine = e->docLine; + info->setRefItems(e->sli); + } + e->doc.resize(0); + e->brief.resize(0); + } +} + +bool DocGroup::isEmpty() const +{ + return (m_memberGroupId==DOX_NOGROUP); +} + +void DocGroup::clearHeader() +{ + m_memberGroupHeader.resize(0); +} + +void DocGroup::appendHeader(const char text) +{ + m_memberGroupHeader += text; +} diff --git a/src/docgroup.h b/src/docgroup.h new file mode 100644 index 0000000..4ce9af9 --- /dev/null +++ b/src/docgroup.h @@ -0,0 +1,54 @@ +/****************************************************************************** + * + * Copyright (C) 1997-2019 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. + * + * Documents produced by Doxygen are derivative works derived from the + * input used in their production; they are not affected by this license. + * + */ + +#ifndef DOCGROUP_H +#define DOCGROUP_H + +#include <qstack.h> +#include <qstring.h> +#include "membergroup.h" + +class Entry; + +class DocGroup +{ + public: + DocGroup() {}; + + public: + void enterFile(const char *fileName,int); + void leaveFile(const char *fileName,int line); + void enterCompound(const char *fileName,int line,const char *name); + void leaveCompound(const char *,int,const char * /*name*/); + void open(Entry *e,const char *,int,bool implicit=false); + void close(Entry *e,const char *fileName,int line,bool foundInline); + void initGroupInfo(Entry *e); + bool isEmpty() const; + void clearHeader(); + void appendHeader(const char); + void addDocs(Entry *e); + + private: + int findExistingGroup(int &groupId,const MemberGroupInfo *info); + int m_openCount; + QCString m_memberGroupHeader; + int m_memberGroupId; + QCString m_memberGroupRelates; + QCString m_memberGroupDocs; + QStack<Grouping> m_autoGroupStack; + QCString m_compoundName; +}; + +#endif diff --git a/src/docparser.cpp b/src/docparser.cpp index 1c8479b..be0d60b 100644 --- a/src/docparser.cpp +++ b/src/docparser.cpp @@ -87,7 +87,7 @@ static const char *sectionLevelToName[] = //--------------------------------------------------------------------------- // Parser state: global variables during a call to validatingParseDoc -static Definition * g_scope; +static const Definition * g_scope; static QCString g_context; static bool g_inSeeBlock; static bool g_xmlComment; @@ -102,7 +102,7 @@ static QCString g_relPath; static bool g_hasParamCommand; static bool g_hasReturnCommand; static QDict<void> g_paramsFound; -static MemberDef * g_memberDef; +static const MemberDef * g_memberDef; static bool g_isExample; static QCString g_exampleName; static SectionDict * g_sectionDict; @@ -120,7 +120,7 @@ static bool g_includeFileShowLineNo; */ struct DocParserContext { - Definition *scope; + const Definition *scope; QCString context; bool inSeeBlock; bool xmlComment; @@ -135,7 +135,7 @@ struct DocParserContext bool hasParamCommand; bool hasReturnCommand; - MemberDef * memberDef; + const MemberDef * memberDef; QDict<void> paramsFound; bool isExample; QCString exampleName; @@ -406,9 +406,9 @@ static void checkArgumentName(const QCString &name,bool isParam) { if (!Config_getBool(WARN_IF_DOC_ERROR)) return; if (g_memberDef==0) return; // not a member - ArgumentList *al=g_memberDef->isDocsForDefinition() ? - g_memberDef->argumentList() : - g_memberDef->declArgumentList(); + const ArgumentList *al=g_memberDef->isDocsForDefinition() ? + g_memberDef->argumentList() : + g_memberDef->declArgumentList(); SrcLangExt lang = g_memberDef->getLanguage(); //printf("isDocsForDefinition()=%d\n",g_memberDef->isDocsForDefinition()); if (al==0) return; // no argument list @@ -421,7 +421,7 @@ static void checkArgumentName(const QCString &name,bool isParam) if (lang==SrcLangExt_Fortran) aName=aName.lower(); //printf("aName=`%s'\n",aName.data()); ArgumentListIterator ali(*al); - Argument *a; + const Argument *a; bool found=FALSE; for (ali.toFirst();(a=ali.current());++ali) { @@ -476,14 +476,14 @@ static void checkUnOrMultipleDocumentedParams() { if (g_memberDef && g_hasParamCommand && Config_getBool(WARN_IF_DOC_ERROR)) { - ArgumentList *al=g_memberDef->isDocsForDefinition() ? + const ArgumentList *al=g_memberDef->isDocsForDefinition() ? g_memberDef->argumentList() : g_memberDef->declArgumentList(); SrcLangExt lang = g_memberDef->getLanguage(); if (al!=0) { ArgumentListIterator ali(*al); - Argument *a; + const Argument *a; bool found=FALSE; for (ali.toFirst();(a=ali.current());++ali) { @@ -558,106 +558,6 @@ static void checkUnOrMultipleDocumentedParams() } } -/*! Check if a member has documentation for its parameter and or return - * type, if applicable. If found this will be stored in the member, this - * is needed as a member can have brief and detailed documentation, while - * only one of these needs to document the parameters. - */ -static void detectNoDocumentedParams() -{ - if (g_memberDef && Config_getBool(WARN_NO_PARAMDOC)) - { - ArgumentList *al = g_memberDef->argumentList(); - ArgumentList *declAl = g_memberDef->declArgumentList(); - QCString returnType = g_memberDef->typeString(); - bool isPython = g_memberDef->getLanguage()==SrcLangExt_Python; - - if (!g_memberDef->hasDocumentedParams() && - g_hasParamCommand) - { - //printf("%s->setHasDocumentedParams(TRUE);\n",g_memberDef->name().data()); - g_memberDef->setHasDocumentedParams(TRUE); - } - else if (!g_memberDef->hasDocumentedParams()) - { - bool allDoc=TRUE; // no parameter => all parameters are documented - if ( // member has parameters - al!=0 && // but the member has a parameter list - al->count()>0 // with at least one parameter (that is not void) - ) - { - ArgumentListIterator ali(*al); - Argument *a; - - // see if all parameters have documentation - for (ali.toFirst();(a=ali.current()) && allDoc;++ali) - { - if (!a->name.isEmpty() && a->type!="void" && - !(isPython && (a->name=="self" || a->name=="cls")) - ) - { - allDoc = !a->docs.isEmpty(); - } - //printf("a->type=%s a->name=%s doc=%s\n", - // a->type.data(),a->name.data(),a->docs.data()); - } - if (!allDoc && declAl!=0) // try declaration arguments as well - { - allDoc=TRUE; - ArgumentListIterator ali(*declAl); - Argument *a; - for (ali.toFirst();(a=ali.current()) && allDoc;++ali) - { - if (!a->name.isEmpty() && a->type!="void" && - !(isPython && (a->name=="self" || a->name=="cls")) - ) - { - allDoc = !a->docs.isEmpty(); - } - //printf("a->name=%s doc=%s\n",a->name.data(),a->docs.data()); - } - } - } - if (allDoc) - { - //printf("%s->setHasDocumentedParams(TRUE);\n",g_memberDef->name().data()); - g_memberDef->setHasDocumentedParams(TRUE); - } - } - //printf("Member %s hasDocumentedReturnType()=%d hasReturnCommand=%d\n", - // g_memberDef->name().data(),g_memberDef->hasDocumentedReturnType(),g_hasReturnCommand); - if (!g_memberDef->hasDocumentedReturnType() && // docs not yet found - g_hasReturnCommand) - { - g_memberDef->setHasDocumentedReturnType(TRUE); - } - else if ( // see if return type is documented in a function w/o return type - g_hasReturnCommand && - (//returnType.isEmpty() || // empty return type - returnType.find("void")!=-1 || // void return type - returnType.find("subroutine")!=-1 || // fortran subroutine - g_memberDef->isConstructor() || // a constructor - g_memberDef->isDestructor() // or destructor - ) - ) - { - warn_doc_error(g_fileName,doctokenizerYYlineno,"documented empty return type of %s",g_memberDef->qualifiedName().data()); - } - else if ( // see if return needs to documented - g_memberDef->hasDocumentedReturnType() || - //returnType.isEmpty() || // empty return type - returnType.find("void")!=-1 || // void return type - returnType.find("subroutine")!=-1 || // fortran subroutine - g_memberDef->isConstructor() || // a constructor - g_memberDef->isDestructor() // or destructor - ) - { - g_memberDef->setHasDocumentedReturnType(TRUE); - } - } -} - - //--------------------------------------------------------------------------- /*! Strips known html and tex extensions from \a text. */ @@ -755,7 +655,7 @@ static bool insideTable(DocNode *n) static bool findDocsForMemberOrCompound(const char *commandName, QCString *pDoc, QCString *pBrief, - Definition **pDef) + const Definition **pDef) { //printf("findDocsForMemberOrCompound(%s)\n",commandName); *pDoc=""; @@ -789,12 +689,12 @@ static bool findDocsForMemberOrCompound(const char *commandName, QCString args=cmdArg.right(l-funcStart); // try if the link is to a member - MemberDef *md=0; - ClassDef *cd=0; - FileDef *fd=0; - NamespaceDef *nd=0; - GroupDef *gd=0; - PageDef *pd=0; + const MemberDef *md=0; + const ClassDef *cd=0; + const FileDef *fd=0; + const NamespaceDef *nd=0; + const GroupDef *gd=0; + const PageDef *pd=0; bool found = getDefs( g_context.find('.')==-1?g_context.data():"", // `find('.') is a hack to detect files name, @@ -916,8 +816,8 @@ static int handleStyleArgument(DocNode *parent,QList<DocNode> &children, int tok=doctokenizerYYlex(); if (tok!=TK_WHITESPACE) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after %s command", - qPrint(cmdName)); + warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after \\%s command", + qPrint(saveCmdName)); return tok; } while ((tok=doctokenizerYYlex()) && @@ -952,7 +852,7 @@ static int handleStyleArgument(DocNode *parent,QList<DocNode> &children, break; } } - DBG(("handleStyleArgument(%s) end tok=%x\n",qPrint(cmdName),tok)); + DBG(("handleStyleArgument(%s) end tok=%x\n",qPrint(saveCmdName),tok)); return (tok==TK_NEWPARA || tok==TK_LISTITEM || tok==TK_ENDLIST ) ? tok : RetVal_OK; } @@ -1125,8 +1025,8 @@ static void handleLinkedWord(DocNode *parent,QList<DocNode> &children,bool ignor // ------- try to turn the word 'name' into a link - Definition *compound=0; - MemberDef *member=0; + const Definition *compound=0; + const MemberDef *member=0; int len = g_token->name.length(); ClassDef *cd=0; bool ambig; @@ -1165,7 +1065,7 @@ static void handleLinkedWord(DocNode *parent,QList<DocNode> &children,bool ignor } else if (compound->definitionType()==Definition::TypeGroup) { - name=(dynamic_cast<GroupDef*>(compound))->groupTitle(); + name=(dynamic_cast<const GroupDef*>(compound))->groupTitle(); } children.append(new DocLinkedWord(parent,name, @@ -1177,7 +1077,7 @@ static void handleLinkedWord(DocNode *parent,QList<DocNode> &children,bool ignor ); } else if (compound->definitionType()==Definition::TypeFile && - (dynamic_cast<FileDef*>(compound))->generateSourceFile() + (dynamic_cast<const FileDef*>(compound))->generateSourceFile() ) // undocumented file that has source code we can link to { children.append(new @@ -1262,7 +1162,7 @@ static DocInternalRef *handleInternalRef(DocNode *parent) QCString tokenName = g_token->name; if (tok!=TK_WHITESPACE) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after %s command", + warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after \\%s command", qPrint(tokenName)); return 0; } @@ -1282,7 +1182,7 @@ static DocAnchor *handleAnchor(DocNode *parent) int tok=doctokenizerYYlex(); if (tok!=TK_WHITESPACE) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after %s command", + warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after \\%s command", qPrint(g_token->name)); return 0; } @@ -2063,7 +1963,7 @@ void DocIncOperator::parse() if (g_includeFileName.isEmpty()) { warn_doc_error(g_fileName,doctokenizerYYlineno, - "No previous '\\include' or \\dontinclude' command for '\\%s' present", + "No previous '\\include' or '\\dontinclude' command for '\\%s' present", typeAsString()); } @@ -2198,100 +2098,6 @@ void DocIncOperator::parse() //--------------------------------------------------------------------------- -void DocCopy::parse(QList<DocNode> &children) -{ - QCString doc,brief; - Definition *def; - if (findDocsForMemberOrCompound(m_link,&doc,&brief,&def)) - { - if (g_copyStack.findRef(def)==-1) // definition not parsed earlier - { - bool hasParamCommand = g_hasParamCommand; - bool hasReturnCommand = g_hasReturnCommand; - QDict<void> paramsFound = g_paramsFound; - //printf("..1 hasParamCommand=%d hasReturnCommand=%d paramsFound=%d\n", - // g_hasParamCommand,g_hasReturnCommand,g_paramsFound.count()); - - docParserPushContext(FALSE); - g_scope = def; - if (def->definitionType()==Definition::TypeMember && def->getOuterScope()) - { - if (def->getOuterScope()!=Doxygen::globalScope) - { - g_context=def->getOuterScope()->name(); - } - } - else if (def!=Doxygen::globalScope) - { - g_context=def->name(); - } - g_styleStack.clear(); - g_nodeStack.clear(); - g_paramsFound.clear(); - g_copyStack.append(def); - // make sure the descriptions end with a newline, so the parser will correctly - // handle them in all cases. - //printf("doc='%s'\n",doc.data()); - //printf("brief='%s'\n",brief.data()); - if (m_copyBrief) - { - brief+='\n'; - internalValidatingParseDoc(m_parent,children,brief); - - //printf("..2 hasParamCommand=%d hasReturnCommand=%d paramsFound=%d\n", - // g_hasParamCommand,g_hasReturnCommand,g_paramsFound.count()); - hasParamCommand = hasParamCommand || g_hasParamCommand; - hasReturnCommand = hasReturnCommand || g_hasReturnCommand; - QDictIterator<void> it(g_paramsFound); - void *item; - for (;(item=it.current());++it) - { - paramsFound.insert(it.currentKey(),it.current()); - } - } - if (m_copyDetails) - { - doc+='\n'; - internalValidatingParseDoc(m_parent,children,doc); - - //printf("..3 hasParamCommand=%d hasReturnCommand=%d paramsFound=%d\n", - // g_hasParamCommand,g_hasReturnCommand,g_paramsFound.count()); - hasParamCommand = hasParamCommand || g_hasParamCommand; - hasReturnCommand = hasReturnCommand || g_hasReturnCommand; - QDictIterator<void> it(g_paramsFound); - void *item; - for (;(item=it.current());++it) - { - paramsFound.insert(it.currentKey(),it.current()); - } - } - g_copyStack.remove(def); - ASSERT(g_styleStack.isEmpty()); - ASSERT(g_nodeStack.isEmpty()); - docParserPopContext(TRUE); - - g_hasParamCommand = hasParamCommand; - g_hasReturnCommand = hasReturnCommand; - g_paramsFound = paramsFound; - - //printf("..4 hasParamCommand=%d hasReturnCommand=%d paramsFound=%d\n", - // g_hasParamCommand,g_hasReturnCommand,g_paramsFound.count()); - } - else // oops, recursion - { - warn_doc_error(g_fileName,doctokenizerYYlineno,"recursive call chain of \\copydoc commands detected at %d\n", - doctokenizerYYlineno); - } - } - else - { - warn_doc_error(g_fileName,doctokenizerYYlineno,"target %s of \\copydoc command not found", - qPrint(m_link)); - } -} - -//--------------------------------------------------------------------------- - DocXRefItem::DocXRefItem(DocNode *parent,int id,const char *key) : m_id(id), m_key(key), m_relPath(g_relPath) { @@ -2547,7 +2353,7 @@ DocRef::DocRef(DocNode *parent,const QCString &target,const QCString &context) : m_refType(Unknown), m_isSubPage(FALSE) { m_parent = parent; - Definition *compound = 0; + const Definition *compound = 0; QCString anchor; //printf("DocRef::DocRef(target=%s,context=%s)\n",target.data(),context.data()); ASSERT(!target.isEmpty()); @@ -2600,16 +2406,16 @@ DocRef::DocRef(DocNode *parent,const QCString &target,const QCString &context) : { if (anchor.isEmpty() && /* compound link */ compound->definitionType()==Definition::TypeGroup && /* is group */ - (dynamic_cast<GroupDef *>(compound))->groupTitle() /* with title */ + (dynamic_cast<const GroupDef *>(compound))->groupTitle() /* with title */ ) { - m_text=(dynamic_cast<GroupDef *>(compound))->groupTitle(); // use group's title as link + m_text=(dynamic_cast<const GroupDef *>(compound))->groupTitle(); // use group's title as link } else if (compound->definitionType()==Definition::TypeMember && - (dynamic_cast<MemberDef*>(compound))->isObjCMethod()) + (dynamic_cast<const MemberDef*>(compound))->isObjCMethod()) { // Objective C Method - MemberDef *member = dynamic_cast<MemberDef*>(compound); + const MemberDef *member = dynamic_cast<const MemberDef*>(compound); bool localLink = g_memberDef ? member->getClassDef()==g_memberDef->getClassDef() : FALSE; m_text = member->objCMethodName(localLink,g_inSeeBlock); } @@ -2621,7 +2427,7 @@ DocRef::DocRef(DocNode *parent,const QCString &target,const QCString &context) : return; } else if (compound && compound->definitionType()==Definition::TypeFile && - (dynamic_cast<FileDef*>(compound))->generateSourceFile() + (dynamic_cast<const FileDef*>(compound))->generateSourceFile() ) // undocumented file that has source code we can link to { m_file = compound->getSourceFileBase(); @@ -2743,7 +2549,7 @@ DocCite::DocCite(DocNode *parent,const QCString &target,const QCString &) //cont DocLink::DocLink(DocNode *parent,const QCString &target) { m_parent = parent; - Definition *compound = 0; + const Definition *compound = 0; QCString anchor; m_refText = target; m_relPath = g_relPath; @@ -2761,7 +2567,7 @@ DocLink::DocLink(DocNode *parent,const QCString &target) m_ref = compound->getReference(); } else if (compound && compound->definitionType()==Definition::TypeFile && - (dynamic_cast<FileDef*>(compound))->generateSourceFile() + (dynamic_cast<const FileDef*>(compound))->generateSourceFile() ) // undocumented file that has source code we can link to { m_file = compound->getSourceFileBase(); @@ -2875,8 +2681,9 @@ DocDotFile::DocDotFile(DocNode *parent,const QCString &name,const QCString &cont m_parent = parent; } -void DocDotFile::parse() +bool DocDotFile::parse() { + bool ok = false; defaultHandleTitleAndSize(CMD_DOTFILE,this,m_children,m_width,m_height); bool ambig; @@ -2888,6 +2695,7 @@ void DocDotFile::parse() if (fd) { m_file = fd->absFilePath(); + ok = true; } else if (ambig) { @@ -2901,6 +2709,7 @@ void DocDotFile::parse() warn_doc_error(g_fileName,doctokenizerYYlineno,"included dot file %s is not found " "in any of the paths specified via DOTFILE_DIRS!",qPrint(m_name)); } + return ok; } DocMscFile::DocMscFile(DocNode *parent,const QCString &name,const QCString &context) : @@ -2909,8 +2718,9 @@ DocMscFile::DocMscFile(DocNode *parent,const QCString &name,const QCString &cont m_parent = parent; } -void DocMscFile::parse() +bool DocMscFile::parse() { + bool ok = false; defaultHandleTitleAndSize(CMD_MSCFILE,this,m_children,m_width,m_height); bool ambig; @@ -2922,6 +2732,7 @@ void DocMscFile::parse() if (fd) { m_file = fd->absFilePath(); + ok = true; } else if (ambig) { @@ -2935,6 +2746,7 @@ void DocMscFile::parse() warn_doc_error(g_fileName,doctokenizerYYlineno,"included msc file %s is not found " "in any of the paths specified via MSCFILE_DIRS!",qPrint(m_name)); } + return ok; } //--------------------------------------------------------------------------- @@ -2945,8 +2757,9 @@ DocDiaFile::DocDiaFile(DocNode *parent,const QCString &name,const QCString &cont m_parent = parent; } -void DocDiaFile::parse() +bool DocDiaFile::parse() { + bool ok = false; defaultHandleTitleAndSize(CMD_DIAFILE,this,m_children,m_width,m_height); bool ambig; @@ -2958,6 +2771,7 @@ void DocDiaFile::parse() if (fd) { m_file = fd->absFilePath(); + ok = true; } else if (ambig) { @@ -2971,6 +2785,7 @@ void DocDiaFile::parse() warn_doc_error(g_fileName,doctokenizerYYlineno,"included dia file %s is not found " "in any of the paths specified via DIAFILE_DIRS!",qPrint(m_name)); } + return ok; } //--------------------------------------------------------------------------- @@ -3019,7 +2834,11 @@ DocImage::DocImage(DocNode *parent,const HtmlAttribList &attribs,const QCString bool DocImage::isSVG() const { - return m_url.isEmpty() ? m_name.right(4)==".svg" : m_url.right(4)==".svg"; + QCString locName = m_url.isEmpty() ? m_name : m_url; + int len = locName.length(); + int fnd = locName.find('?'); // ignore part from ? until end + if (fnd!=-1) fnd=len; + return fnd>=4 && locName.mid(fnd-4,4)==".svg"; } void DocImage::parse() @@ -4739,8 +4558,8 @@ int DocParamList::parse(const QCString &cmdName) int tok=doctokenizerYYlex(); if (tok!=TK_WHITESPACE) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after %s command", - qPrint(cmdName)); + warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after \\%s command", + qPrint(saveCmdName)); retval=0; goto endparamlist; } @@ -4778,7 +4597,7 @@ int DocParamList::parse(const QCString &cmdName) if (tok==0) /* premature end of comment block */ { warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected end of comment block while parsing the " - "argument of command %s",qPrint(cmdName)); + "argument of command %s",qPrint(saveCmdName)); retval=0; goto endparamlist; } @@ -4976,7 +4795,7 @@ void DocPara::handleCite() int tok=doctokenizerYYlex(); if (tok!=TK_WHITESPACE) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after %s command", + warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after \\%s command", qPrint("cite")); return; } @@ -5008,7 +4827,7 @@ void DocPara::handleEmoji() int tok=doctokenizerYYlex(); if (tok!=TK_WHITESPACE) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after %s command", + warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after \\%s command", qPrint("emoji")); return; } @@ -5055,12 +4874,13 @@ int DocPara::handleXRefItem() void DocPara::handleIncludeOperator(const QCString &cmdName,DocIncOperator::Type t) { - DBG(("handleIncludeOperator(%s)\n",qPrint(cmdName))); + QCString saveCmdName = cmdName; + DBG(("handleIncludeOperator(%s)\n",qPrint(saveCmdName))); int tok=doctokenizerYYlex(); if (tok!=TK_WHITESPACE) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after %s command", - qPrint(cmdName)); + warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after \\%s command", + qPrint(saveCmdName)); return; } doctokenizerYYsetStatePattern(); @@ -5069,13 +4889,13 @@ void DocPara::handleIncludeOperator(const QCString &cmdName,DocIncOperator::Type if (tok==0) { warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected end of comment block while parsing the " - "argument of command %s", qPrint(cmdName)); + "argument of command %s", qPrint(saveCmdName)); return; } else if (tok!=TK_WORD) { warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected token %s as the argument of %s", - tokToString(tok),qPrint(cmdName)); + tokToString(tok),qPrint(saveCmdName)); return; } DocIncOperator *op = new DocIncOperator(this,t,g_token->name,g_context,g_isExample,g_exampleName); @@ -5141,7 +4961,7 @@ void DocPara::handleImage(const QCString &cmdName) tok=doctokenizerYYlex(); if (tok!=TK_WHITESPACE) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after %s command with option", + warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after \\%s command with option", qPrint(saveCmdName)); return; } @@ -5149,7 +4969,7 @@ void DocPara::handleImage(const QCString &cmdName) } else { - warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after %s command", + warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after \\%s command", qPrint(saveCmdName)); return; } @@ -5164,7 +4984,7 @@ void DocPara::handleImage(const QCString &cmdName) tok=doctokenizerYYlex(); if (tok!=TK_WHITESPACE) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after %s command", + warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after \\%s command", qPrint(saveCmdName)); return; } @@ -5199,11 +5019,12 @@ void DocPara::handleImage(const QCString &cmdName) template<class T> void DocPara::handleFile(const QCString &cmdName) { + QCString saveCmdName = cmdName; int tok=doctokenizerYYlex(); if (tok!=TK_WHITESPACE) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after %s command", - qPrint(cmdName)); + warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after \\%s command", + qPrint(saveCmdName)); return; } doctokenizerYYsetStateFile(); @@ -5212,13 +5033,19 @@ void DocPara::handleFile(const QCString &cmdName) if (tok!=TK_WORD) { warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected token %s as the argument of %s", - tokToString(tok),qPrint(cmdName)); + tokToString(tok),qPrint(saveCmdName)); return; } QCString name = g_token->name; T *df = new T(this,name,g_context); - m_children.append(df); - df->parse(); + if (df->parse()) + { + m_children.append(df); + } + else + { + delete df; + } } void DocPara::handleVhdlFlow() @@ -5230,11 +5057,12 @@ void DocPara::handleVhdlFlow() void DocPara::handleLink(const QCString &cmdName,bool isJavaLink) { + QCString saveCmdName = cmdName; int tok=doctokenizerYYlex(); if (tok!=TK_WHITESPACE) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after %s command", - qPrint(cmdName)); + warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after \\%s command", + qPrint(saveCmdName)); return; } doctokenizerYYsetStateLink(); @@ -5242,7 +5070,7 @@ void DocPara::handleLink(const QCString &cmdName,bool isJavaLink) if (tok!=TK_WORD) { warn_doc_error(g_fileName,doctokenizerYYlineno,"%s as the argument of %s", - tokToString(tok),qPrint(cmdName)); + tokToString(tok),qPrint(saveCmdName)); return; } doctokenizerYYsetStatePara(); @@ -5257,12 +5085,13 @@ void DocPara::handleLink(const QCString &cmdName,bool isJavaLink) void DocPara::handleRef(const QCString &cmdName) { - DBG(("handleRef(%s)\n",qPrint(cmdName))); + QCString saveCmdName = cmdName; + DBG(("handleRef(%s)\n",qPrint(saveCmdName))); int tok=doctokenizerYYlex(); if (tok!=TK_WHITESPACE) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after %s command", - qPrint(cmdName)); + warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after \\%s command", + qPrint(saveCmdName)); return; } doctokenizerYYsetStateRef(); @@ -5271,7 +5100,7 @@ void DocPara::handleRef(const QCString &cmdName) if (tok!=TK_WORD) { warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected token %s as the argument of %s", - tokToString(tok),qPrint(cmdName)); + tokToString(tok),qPrint(saveCmdName)); goto endref; } ref = new DocRef(this,g_token->name,g_context); @@ -5284,6 +5113,7 @@ endref: void DocPara::handleInclude(const QCString &cmdName,DocInclude::Type t) { DBG(("handleInclude(%s)\n",qPrint(cmdName))); + QCString saveCmdName = cmdName; int tok=doctokenizerYYlex(); bool isBlock = false; if (tok==TK_WORD && g_token->name=="{") @@ -5324,8 +5154,8 @@ void DocPara::handleInclude(const QCString &cmdName,DocInclude::Type t) } else if (tok!=TK_WHITESPACE) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after %s command", - qPrint(cmdName)); + warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after \\%s command", + qPrint(saveCmdName)); return; } doctokenizerYYsetStateFile(); @@ -5334,13 +5164,13 @@ void DocPara::handleInclude(const QCString &cmdName,DocInclude::Type t) if (tok==0) { warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected end of comment block while parsing the " - "argument of command %s",qPrint(cmdName)); + "argument of command %s",qPrint(saveCmdName)); return; } else if (tok!=TK_WORD) { warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected token %s as the argument of %s", - tokToString(tok),qPrint(cmdName)); + tokToString(tok),qPrint(saveCmdName)); return; } QCString fileName = g_token->name; @@ -5354,7 +5184,7 @@ void DocPara::handleInclude(const QCString &cmdName,DocInclude::Type t) if (tok!=TK_WORD) { warn_doc_error(g_fileName,doctokenizerYYlineno,"expected block identifier, but found token %s instead while parsing the %s command", - tokToString(tok),qPrint(cmdName)); + tokToString(tok),qPrint(saveCmdName)); return; } blockId = "["+g_token->name+"]"; @@ -5388,25 +5218,26 @@ void DocPara::handleInclude(const QCString &cmdName,DocInclude::Type t) void DocPara::handleSection(const QCString &cmdName) { + QCString saveCmdName = cmdName; // get the argument of the section command. int tok=doctokenizerYYlex(); if (tok!=TK_WHITESPACE) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after %s command", - qPrint(cmdName)); + warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after \\%s command", + qPrint(saveCmdName)); return; } tok=doctokenizerYYlex(); if (tok==0) { warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected end of comment block while parsing the " - "argument of command %s\n", qPrint(cmdName)); + "argument of command %s\n", qPrint(saveCmdName)); return; } else if (tok!=TK_WORD && tok!=TK_LNKWORD) { warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected token %s as the argument of %s", - tokToString(tok),qPrint(cmdName)); + tokToString(tok),qPrint(saveCmdName)); return; } g_token->sectionId = g_token->name; @@ -5464,7 +5295,7 @@ void DocPara::handleInheritDoc() MemberDef *reMd = g_memberDef->reimplements(); if (reMd) // member from which was inherited. { - MemberDef *thisMd = g_memberDef; + const MemberDef *thisMd = g_memberDef; //printf("{InheritDocs:%s=>%s}\n",g_memberDef->qualifiedName().data(),reMd->qualifiedName().data()); docParserPushContext(); g_scope=reMd->getOuterScope(); @@ -6981,54 +6812,55 @@ int DocSection::parse() //printf("m_level=%d <-> %d\n",m_level,Doxygen::subpageNestingLevel); - if (retval==RetVal_Subsection && m_level==Doxygen::subpageNestingLevel+1) + while (true) { - // then parse any number of nested sections - while (retval==RetVal_Subsection) // more sections follow + if (retval==RetVal_Subsection && m_level<=Doxygen::subpageNestingLevel+1) { - //SectionInfo *sec=Doxygen::sectionDict[g_token->sectionId]; - DocSection *s=new DocSection(this, - QMIN(2+Doxygen::subpageNestingLevel,5),g_token->sectionId); - m_children.append(s); - retval = s->parse(); + // then parse any number of nested sections + while (retval==RetVal_Subsection) // more sections follow + { + //SectionInfo *sec=Doxygen::sectionDict[g_token->sectionId]; + DocSection *s=new DocSection(this, + QMIN(2+Doxygen::subpageNestingLevel,5),g_token->sectionId); + m_children.append(s); + retval = s->parse(); + } + break; } - } - else if (retval==RetVal_Subsubsection && m_level==Doxygen::subpageNestingLevel+2) - { - // then parse any number of nested sections - while (retval==RetVal_Subsubsection) // more sections follow + else if (retval==RetVal_Subsubsection && m_level<=Doxygen::subpageNestingLevel+2) { - //SectionInfo *sec=Doxygen::sectionDict[g_token->sectionId]; - DocSection *s=new DocSection(this, - QMIN(3+Doxygen::subpageNestingLevel,5),g_token->sectionId); - m_children.append(s); - retval = s->parse(); + if ((m_level<=1+Doxygen::subpageNestingLevel) && !QString(g_token->sectionId).startsWith("autotoc_md")) + warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected subsubsection command found inside %s!",sectionLevelToName[m_level]); + // then parse any number of nested sections + while (retval==RetVal_Subsubsection) // more sections follow + { + //SectionInfo *sec=Doxygen::sectionDict[g_token->sectionId]; + DocSection *s=new DocSection(this, + QMIN(3+Doxygen::subpageNestingLevel,5),g_token->sectionId); + m_children.append(s); + retval = s->parse(); + } + if (!(m_level<Doxygen::subpageNestingLevel+2 && retval == RetVal_Subsection)) break; } - } - else if (retval==RetVal_Paragraph && m_level==QMIN(5,Doxygen::subpageNestingLevel+3)) - { - // then parse any number of nested sections - while (retval==RetVal_Paragraph) // more sections follow + else if (retval==RetVal_Paragraph && m_level<=QMIN(5,Doxygen::subpageNestingLevel+3)) { - //SectionInfo *sec=Doxygen::sectionDict[g_token->sectionId]; - DocSection *s=new DocSection(this, - QMIN(4+Doxygen::subpageNestingLevel,5),g_token->sectionId); - m_children.append(s); - retval = s->parse(); + if ((m_level<=2+Doxygen::subpageNestingLevel) && !QString(g_token->sectionId).startsWith("autotoc_md")) + warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected paragraph command found inside %s!",sectionLevelToName[m_level]); + // then parse any number of nested sections + while (retval==RetVal_Paragraph) // more sections follow + { + //SectionInfo *sec=Doxygen::sectionDict[g_token->sectionId]; + DocSection *s=new DocSection(this, + QMIN(4+Doxygen::subpageNestingLevel,5),g_token->sectionId); + m_children.append(s); + retval = s->parse(); + } + if (!(m_level<Doxygen::subpageNestingLevel+3 && (retval == RetVal_Subsection || retval == RetVal_Subsubsection))) break; + } + else + { + break; } - } - else if ((m_level<=1+Doxygen::subpageNestingLevel && retval==RetVal_Subsubsection) || - (m_level<=2+Doxygen::subpageNestingLevel && retval==RetVal_Paragraph) - ) - { - int level = (retval==RetVal_Subsubsection) ? 3 : 4; - warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected %s " - "command found inside %s!", - sectionLevelToName[level],sectionLevelToName[m_level]); - retval=0; // stop parsing - } - else - { } INTERNAL_ASSERT(retval==0 || @@ -7182,21 +7014,72 @@ void DocRoot::parse() { delete par; } - if (retval==TK_LISTITEM) + if (retval==RetVal_Paragraph) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"Invalid list item found"); + if (!QString(g_token->sectionId).startsWith("autotoc_md")) + warn_doc_error(g_fileName,doctokenizerYYlineno,"found paragraph command outside of subsubsection context!"); + while (retval==RetVal_Paragraph) + { + SectionInfo *sec=Doxygen::sectionDict->find(g_token->sectionId); + if (sec) + { + DocSection *s=new DocSection(this, + QMIN(4+Doxygen::subpageNestingLevel,5),g_token->sectionId); + m_children.append(s); + retval = s->parse(); + } + else + { + warn_doc_error(g_fileName,doctokenizerYYlineno,"Invalid paragraph id `%s'; ignoring paragraph",qPrint(g_token->sectionId)); + retval = 0; + } + } } - else if (retval==RetVal_Subsection) + if (retval==RetVal_Subsubsection) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"found subsection command outside of section context!"); + if (!(QString(g_token->sectionId).startsWith("autotoc_md"))) + warn_doc_error(g_fileName,doctokenizerYYlineno,"found subsubsection command outside of subsection context!"); + while (retval==RetVal_Subsubsection) + { + SectionInfo *sec=Doxygen::sectionDict->find(g_token->sectionId); + if (sec) + { + DocSection *s=new DocSection(this, + QMIN(3+Doxygen::subpageNestingLevel,5),g_token->sectionId); + m_children.append(s); + retval = s->parse(); + } + else + { + warn_doc_error(g_fileName,doctokenizerYYlineno,"Invalid subsubsection id `%s'; ignoring subsubsection",qPrint(g_token->sectionId)); + retval = 0; + } + } } - else if (retval==RetVal_Subsubsection) + if (retval==RetVal_Subsection) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"found subsubsection command outside of subsection context!"); + if (!(QString(g_token->sectionId).startsWith("autotoc_md"))) + warn_doc_error(g_fileName,doctokenizerYYlineno,"found subsection command outside of section context!"); + while (retval==RetVal_Subsection) + { + SectionInfo *sec=Doxygen::sectionDict->find(g_token->sectionId); + if (sec) + { + DocSection *s=new DocSection(this, + QMIN(2+Doxygen::subpageNestingLevel,5),g_token->sectionId); + m_children.append(s); + retval = s->parse(); + } + else + { + warn_doc_error(g_fileName,doctokenizerYYlineno,"Invalid subsection id `%s'; ignoring subsection",qPrint(g_token->sectionId)); + retval = 0; + } + } } - else if (retval==RetVal_Paragraph) + if (retval==TK_LISTITEM) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"found paragraph command outside of subsubsection context!"); + warn_doc_error(g_fileName,doctokenizerYYlineno,"Invalid list item found"); } if (retval==RetVal_Internal) { @@ -7366,7 +7249,7 @@ static QCString processCopyDoc(const char *data,uint &len) while (j<len && (data[j]==' ' || data[j]=='\t')) j++; // extract the argument QCString id = extractCopyDocId(data,j,len); - Definition *def; + const Definition *def = 0; QCString doc,brief; //printf("resolving docs='%s'\n",id.data()); if (findDocsForMemberOrCompound(id,&doc,&brief,&def)) @@ -7555,7 +7438,7 @@ QCString getJsDirEmbedingChar(QString::Direction textDir) //--------------------------------------------------------------------------- DocRoot *validatingParseDoc(const char *fileName,int startLine, - Definition *ctx,MemberDef *md, + const Definition *ctx,const MemberDef *md, const char *input,bool indexWords, bool isExample, const char *exampleName, bool singleLine, bool linkFromIndex) @@ -7581,12 +7464,12 @@ DocRoot *validatingParseDoc(const char *fileName,int startLine, } else if (ctx && ctx->definitionType()==Definition::TypePage) { - Definition *scope = (dynamic_cast<PageDef*>(ctx))->getPageScope(); + const Definition *scope = (dynamic_cast<const PageDef*>(ctx))->getPageScope(); if (scope && scope!=Doxygen::globalScope) g_context = scope->name(); } else if (ctx && ctx->definitionType()==Definition::TypeGroup) { - Definition *scope = (dynamic_cast<GroupDef*>(ctx))->getGroupScope(); + const Definition *scope = (dynamic_cast<const GroupDef*>(ctx))->getGroupScope(); if (scope && scope!=Doxygen::globalScope) g_context = scope->name(); } else @@ -7740,7 +7623,7 @@ DocRoot *validatingParseDoc(const char *fileName,int startLine, } checkUnOrMultipleDocumentedParams(); - detectNoDocumentedParams(); + if (g_memberDef) g_memberDef->detectUndocumentedParams(g_hasParamCommand,g_hasReturnCommand); // TODO: These should be called at the end of the program. //doctokenizerYYcleanup(); diff --git a/src/docparser.h b/src/docparser.h index 15180f9..cab1589 100644 --- a/src/docparser.h +++ b/src/docparser.h @@ -65,7 +65,7 @@ QCString getJsDirEmbedingChar(QString::Direction textDir); * pointer is handed over to the caller. */ DocRoot *validatingParseDoc(const char *fileName,int startLine, - Definition *context, MemberDef *md, + const Definition *context, const MemberDef *md, const char *input,bool indexWords, bool isExample,const char *exampleName=0, bool singleLine=FALSE,bool linkFromIndex=FALSE); @@ -677,41 +677,23 @@ class DocFormula : public DocNode class DocIndexEntry : public DocNode { public: - DocIndexEntry(DocNode *parent,Definition *scope,MemberDef *md) + DocIndexEntry(DocNode *parent,const Definition *scope,const MemberDef *md) : m_scope(scope), m_member(md){ m_parent = parent; } Kind kind() const { return Kind_IndexEntry; } int parse(); - Definition *scope() const { return m_scope; } - MemberDef *member() const { return m_member; } + const Definition *scope() const { return m_scope; } + const MemberDef *member() const { return m_member; } QCString entry() const { return m_entry; } void accept(DocVisitor *v) { v->visit(this); } private: QCString m_entry; - Definition *m_scope; - MemberDef *m_member; + const Definition *m_scope; + const MemberDef *m_member; }; //----------------------------------------------------------------------- -/** Node representing a copy of documentation block. */ -class DocCopy : public DocNode -{ - public: - DocCopy(DocNode *parent,const QCString &link,bool copyBrief,bool copyDetails) - : m_link(link), - m_copyBrief(copyBrief), m_copyDetails(copyDetails) { m_parent = parent; } - Kind kind() const { return Kind_Copy; } - QCString link() const { return m_link; } - void accept(DocVisitor * /*v*/) { /*CompAccept<DocCopy>::accept(this,v);*/ } - void parse(QList<DocNode> &children); - - private: - QCString m_link; - bool m_copyBrief; - bool m_copyDetails; -}; - /** Node representing an auto List */ class DocAutoList : public CompAccept<DocAutoList> { @@ -816,7 +798,7 @@ class DocDotFile : public CompAccept<DocDotFile> { public: DocDotFile(DocNode *parent,const QCString &name,const QCString &context); - void parse(); + bool parse(); Kind kind() const { return Kind_DotFile; } QCString name() const { return m_name; } QCString file() const { return m_file; } @@ -839,7 +821,7 @@ class DocMscFile : public CompAccept<DocMscFile> { public: DocMscFile(DocNode *parent,const QCString &name,const QCString &context); - void parse(); + bool parse(); Kind kind() const { return Kind_MscFile; } QCString name() const { return m_name; } QCString file() const { return m_file; } @@ -862,7 +844,7 @@ class DocDiaFile : public CompAccept<DocDiaFile> { public: DocDiaFile(DocNode *parent,const QCString &name,const QCString &context); - void parse(); + bool parse(); Kind kind() const { return Kind_DiaFile; } QCString name() const { return m_name; } QCString file() const { return m_file; } diff --git a/src/docsets.cpp b/src/docsets.cpp index 1d79c9d..055532a 100644 --- a/src/docsets.cpp +++ b/src/docsets.cpp @@ -236,7 +236,7 @@ void DocSets::addContentsItem(bool isDir, const char *anchor, bool /* separateIndex */, bool /* addToNavIndex */, - Definition * /*def*/) + const Definition * /*def*/) { (void)isDir; //printf("DocSets::addContentsItem(%s) m_dc=%d\n",name,m_dc); @@ -274,14 +274,14 @@ void DocSets::addContentsItem(bool isDir, } } -void DocSets::addIndexItem(Definition *context,MemberDef *md, +void DocSets::addIndexItem(const Definition *context,const MemberDef *md, const char *,const char *) { if (md==0 && context==0) return; - FileDef *fd = 0; - ClassDef *cd = 0; - NamespaceDef *nd = 0; + const FileDef *fd = 0; + const ClassDef *cd = 0; + const NamespaceDef *nd = 0; if (md) { @@ -417,7 +417,7 @@ void DocSets::addIndexItem(Definition *context,MemberDef *md, { scope = nd->name(); } - MemberDef *declMd = md->memberDeclaration(); + const MemberDef *declMd = md->memberDeclaration(); if (declMd==0) declMd = md; { fd = md->getFileDef(); @@ -432,15 +432,15 @@ void DocSets::addIndexItem(Definition *context,MemberDef *md, { if (fd==0 && context->definitionType()==Definition::TypeFile) { - fd = dynamic_cast<FileDef*>(context); + fd = dynamic_cast<const FileDef*>(context); } if (cd==0 && context->definitionType()==Definition::TypeClass) { - cd = dynamic_cast<ClassDef*>(context); + cd = dynamic_cast<const ClassDef*>(context); } if (nd==0 && context->definitionType()==Definition::TypeNamespace) { - nd = dynamic_cast<NamespaceDef*>(context); + nd = dynamic_cast<const NamespaceDef*>(context); } if (fd) { diff --git a/src/docsets.h b/src/docsets.h index 548ba75..0d75bfd 100644 --- a/src/docsets.h +++ b/src/docsets.h @@ -45,9 +45,9 @@ class DocSets : public IndexIntf const char *anchor, bool separateIndex, bool addToNavIndex, - Definition *def + const Definition *def ); - void addIndexItem(Definition *context,MemberDef *md, + void addIndexItem(const Definition *context,const MemberDef *md, const char *sectionAnchor,const char *title); void addIndexFile(const char *name); void addImageFile(const char *) {} diff --git a/src/doctokenizer.h b/src/doctokenizer.h index 8b8ca97..b59fc09 100644 --- a/src/doctokenizer.h +++ b/src/doctokenizer.h @@ -71,9 +71,7 @@ enum Tokens /** @brief Data associated with a token used by the comment block parser. */ struct TokenInfo { - // unknown token - char unknownChar; - + TokenInfo() : isEnumList(FALSE), indent(0), id(-1), endTag(FALSE), emptyTag(FALSE), paramDir(Unspecified) {} // command token QCString name; diff --git a/src/doctokenizer.l b/src/doctokenizer.l index 5cf5f02..5346c0a 100644 --- a/src/doctokenizer.l +++ b/src/doctokenizer.l @@ -211,7 +211,7 @@ static void handleHtmlTag() { char c=tagText.at(i); // skip spaces - while (i<(int)yyleng && isspace(c)) { c=tagText.at(++i); } + while (i<(int)yyleng && isspace((uchar)c)) { c=tagText.at(++i); } // check for end of the tag if (c == '>') break; // Check for XML style "empty" tag. @@ -222,17 +222,17 @@ static void handleHtmlTag() } startName=i; // search for end of name - while (i<(int)yyleng && !isspace(c) && c!='=') { c=tagText.at(++i); } + while (i<(int)yyleng && !isspace((uchar)c) && c!='=') { c=tagText.at(++i); } endName=i; HtmlAttrib opt; opt.name = tagText.mid(startName,endName-startName).lower(); // skip spaces - while (i<(int)yyleng && isspace(c)) { c=tagText.at(++i); } + while (i<(int)yyleng && isspace((uchar)c)) { c=tagText.at(++i); } if (tagText.at(i)=='=') // option has value { c=tagText.at(++i); // skip spaces - while (i<(int)yyleng && isspace(c)) { c=tagText.at(++i); } + while (i<(int)yyleng && isspace((uchar)c)) { c=tagText.at(++i); } if (tagText.at(i)=='\'') // option '...' { c=tagText.at(++i); @@ -256,7 +256,7 @@ static void handleHtmlTag() { startAttrib=i; // search for separator or end symbol - while (i<(int)yyleng && !isspace(c) && c!='>') { c=tagText.at(++i); } + while (i<(int)yyleng && !isspace((uchar)c) && c!='>') { c=tagText.at(++i); } endAttrib=i; if (i<(int)yyleng) c=tagText.at(++i); } @@ -658,7 +658,7 @@ REFWORD_NOCV {FILEMASK}|{LABELID}|{REFWORD2_NOCV}|{REFWORD3}|{REFWORD4_NOCV} g_token->isEMailAddr=TRUE; return TK_URL; } -<St_Para>"$"{ID}":"[^\n$]+"$" { /* RCS tag */ +<St_Para>"$"{ID}":"[^:\n$][^\n$]*"$" { /* RCS tag */ QCString tagName(yytext+1); int index=tagName.find(':'); g_token->name = tagName.left(index); @@ -902,6 +902,7 @@ REFWORD_NOCV {FILEMASK}|{LABELID}|{REFWORD2_NOCV}|{REFWORD3}|{REFWORD4_NOCV} g_token->sectionId = QCString(yytext).stripWhiteSpace(); return RetVal_OK; } +<St_PlantUMLOpt>"\n" | <St_PlantUMLOpt>. { g_token->sectionId = ""; unput(*yytext); diff --git a/src/docvisitor.h b/src/docvisitor.h index d2318c9..0a53595 100644 --- a/src/docvisitor.h +++ b/src/docvisitor.h @@ -79,7 +79,6 @@ class DocLinkedWord; class DocParamSect; class DocParamList; class DocInternalRef; -class DocCopy; // TODO: no longer generated => remove class DocText; class DocSimpleSectSep; class DocHtmlBlockQuote; @@ -187,8 +186,6 @@ class DocVisitor virtual void visitPost(DocXRefItem *) = 0; virtual void visitPre(DocInternalRef *) = 0; virtual void visitPost(DocInternalRef *) = 0; - virtual void visitPre(DocCopy *) = 0; - virtual void visitPost(DocCopy *) = 0; virtual void visitPre(DocText *) = 0; virtual void visitPost(DocText *) = 0; virtual void visitPre(DocHtmlBlockQuote *) = 0; diff --git a/src/dot.cpp b/src/dot.cpp index 40a7210..5cdf92c 100644 --- a/src/dot.cpp +++ b/src/dot.cpp @@ -1,13 +1,10 @@ /***************************************************************************** * - * - * - * - * Copyright (C) 1997-2015 by Dimitri van Heesch. + * Copyright (C) 1997-2019 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 + * 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. * @@ -26,390 +23,47 @@ #include <qwaitcondition.h> #include <qregexp.h> +#include "config.h" #include "dot.h" -#include "doxygen.h" -#include "message.h" +#include "dotrunner.h" +#include "dotfilepatcher.h" #include "util.h" -#include "config.h" -#include "language.h" -#include "defargs.h" -#include "docparser.h" -#include "debug.h" -#include "pagedef.h" #include "portable.h" -#include "dirdef.h" -#include "vhdldocgen.h" +#include "message.h" #include "ftextstream.h" -#include "md5.h" -#include "memberlist.h" -#include "groupdef.h" -#include "classlist.h" -#include "filename.h" -#include "namespacedef.h" -#include "memberdef.h" -#include "membergroup.h" +#include "doxygen.h" +#include "language.h" +#include "index.h" #define MAP_CMD "cmapx" -//#define FONTNAME "Helvetica" -#define FONTNAME getDotFontName() -#define FONTSIZE getDotFontSize() - -//-------------------------------------------------------------------- - -static const char svgZoomHeader[] = -"<svg id=\"main\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" xml:space=\"preserve\" onload=\"init(evt)\">\n" -"<style type=\"text/css\"><![CDATA[\n" -".edge:hover path { stroke: red; }\n" -".edge:hover polygon { stroke: red; fill: red; }\n" -"]]></style>\n" -"<script type=\"text/javascript\"><![CDATA[\n" -"var edges = document.getElementsByTagName('g');\n" -"if (edges && edges.length) {\n" -" for (var i=0;i<edges.length;i++) {\n" -" if (edges[i].id.substr(0,4)=='edge') {\n" -" edges[i].setAttribute('class','edge');\n" -" }\n" -" }\n" -"}\n" -"]]></script>\n" -" <defs>\n" -" <circle id=\"rim\" cx=\"0\" cy=\"0\" r=\"7\"/>\n" -" <circle id=\"rim2\" cx=\"0\" cy=\"0\" r=\"3.5\"/>\n" -" <g id=\"zoomPlus\">\n" -" <use xlink:href=\"#rim\" fill=\"#404040\">\n" -" <set attributeName=\"fill\" to=\"#808080\" begin=\"zoomplus.mouseover\" end=\"zoomplus.mouseout\"/>\n" -" </use>\n" -" <path d=\"M-4,0h8M0,-4v8\" fill=\"none\" stroke=\"white\" stroke-width=\"1.5\" pointer-events=\"none\"/>\n" -" </g>\n" -" <g id=\"zoomMin\">\n" -" <use xlink:href=\"#rim\" fill=\"#404040\">\n" -" <set attributeName=\"fill\" to=\"#808080\" begin=\"zoomminus.mouseover\" end=\"zoomminus.mouseout\"/>\n" -" </use>\n" -" <path d=\"M-4,0h8\" fill=\"none\" stroke=\"white\" stroke-width=\"1.5\" pointer-events=\"none\"/>\n" -" </g>\n" -" <g id=\"dirArrow\">\n" -" <path fill=\"none\" stroke=\"white\" stroke-width=\"1.5\" d=\"M0,-3.0v7 M-2.5,-0.5L0,-3.0L2.5,-0.5\"/>\n" -" </g>\n" -" <g id=\"resetDef\">\n" -" <use xlink:href=\"#rim2\" fill=\"#404040\">\n" -" <set attributeName=\"fill\" to=\"#808080\" begin=\"reset.mouseover\" end=\"reset.mouseout\"/>\n" -" </use>\n" -" </g>\n" -" </defs>\n" -"\n" -"<script type=\"text/javascript\">\n" -; - -static const char svgZoomFooter[] = -// navigation panel -" <g id=\"navigator\" transform=\"translate(0 0)\" fill=\"#404254\">\n" -" <rect fill=\"#f2f5e9\" fill-opacity=\"0.5\" stroke=\"#606060\" stroke-width=\".5\" x=\"0\" y=\"0\" width=\"60\" height=\"60\"/>\n" -// zoom in -" <use id=\"zoomplus\" xlink:href=\"#zoomPlus\" x=\"17\" y=\"9\" onmousedown=\"handleZoom(evt,'in')\"/>\n" -// zoom out -" <use id=\"zoomminus\" xlink:href=\"#zoomMin\" x=\"42\" y=\"9\" onmousedown=\"handleZoom(evt,'out')\"/>\n" -// reset zoom -" <use id=\"reset\" xlink:href=\"#resetDef\" x=\"30\" y=\"36\" onmousedown=\"handleReset()\"/>\n" -// arrow up -" <g id=\"arrowUp\" xlink:href=\"#dirArrow\" transform=\"translate(30 24)\" onmousedown=\"handlePan(0,-1)\">\n" -" <use xlink:href=\"#rim\" fill=\"#404040\">\n" -" <set attributeName=\"fill\" to=\"#808080\" begin=\"arrowUp.mouseover\" end=\"arrowUp.mouseout\"/>\n" -" </use>\n" -" <path fill=\"none\" stroke=\"white\" stroke-width=\"1.5\" d=\"M0,-3.0v7 M-2.5,-0.5L0,-3.0L2.5,-0.5\"/>\n" -" </g>\n" -// arrow right -" <g id=\"arrowRight\" xlink:href=\"#dirArrow\" transform=\"rotate(90) translate(36 -43)\" onmousedown=\"handlePan(1,0)\">\n" -" <use xlink:href=\"#rim\" fill=\"#404040\">\n" -" <set attributeName=\"fill\" to=\"#808080\" begin=\"arrowRight.mouseover\" end=\"arrowRight.mouseout\"/>\n" -" </use>\n" -" <path fill=\"none\" stroke=\"white\" stroke-width=\"1.5\" d=\"M0,-3.0v7 M-2.5,-0.5L0,-3.0L2.5,-0.5\"/>\n" -" </g>\n" -// arrow down -" <g id=\"arrowDown\" xlink:href=\"#dirArrow\" transform=\"rotate(180) translate(-30 -48)\" onmousedown=\"handlePan(0,1)\">\n" -" <use xlink:href=\"#rim\" fill=\"#404040\">\n" -" <set attributeName=\"fill\" to=\"#808080\" begin=\"arrowDown.mouseover\" end=\"arrowDown.mouseout\"/>\n" -" </use>\n" -" <path fill=\"none\" stroke=\"white\" stroke-width=\"1.5\" d=\"M0,-3.0v7 M-2.5,-0.5L0,-3.0L2.5,-0.5\"/>\n" -" </g>\n" -// arrow left -" <g id=\"arrowLeft\" xlink:href=\"#dirArrow\" transform=\"rotate(270) translate(-36 17)\" onmousedown=\"handlePan(-1,0)\">\n" -" <use xlink:href=\"#rim\" fill=\"#404040\">\n" -" <set attributeName=\"fill\" to=\"#808080\" begin=\"arrowLeft.mouseover\" end=\"arrowLeft.mouseout\"/>\n" -" </use>\n" -" <path fill=\"none\" stroke=\"white\" stroke-width=\"1.5\" d=\"M0,-3.0v7 M-2.5,-0.5L0,-3.0L2.5,-0.5\"/>\n" -" </g>\n" -" </g>\n" -// link to original SVG -" <svg viewBox=\"0 0 15 15\" width=\"100%\" height=\"30px\" preserveAspectRatio=\"xMaxYMin meet\">\n" -" <g id=\"arrow_out\" transform=\"scale(0.3 0.3)\">\n" -" <a xlink:href=\"$orgname\" target=\"_base\">\n" -" <rect id=\"button\" ry=\"5\" rx=\"5\" y=\"6\" x=\"6\" height=\"38\" width=\"38\"\n" -" fill=\"#f2f5e9\" fill-opacity=\"0.5\" stroke=\"#606060\" stroke-width=\"1.0\"/>\n" -" <path id=\"arrow\"\n" -" d=\"M 11.500037,31.436501 C 11.940474,20.09759 22.043105,11.32322 32.158766,21.979434 L 37.068811,17.246167 C 37.068811,17.246167 37.088388,32 37.088388,32 L 22.160133,31.978069 C 22.160133,31.978069 26.997745,27.140456 26.997745,27.140456 C 18.528582,18.264221 13.291696,25.230495 11.500037,31.436501 z\"\n" -" style=\"fill:#404040;\"/>\n" -" </a>\n" -" </g>\n" -" </svg>\n" -"</svg>\n" -; +static int DOT_NUM_THREADS; // will be initialized in initDot //-------------------------------------------------------------------- -/*! mapping from protection levels to color names */ -static const char *normalEdgeColorMap[] = -{ - "midnightblue", // Public - "darkgreen", // Protected - "firebrick4", // Private - "darkorchid3", // "use" relation - "grey75", // Undocumented - "orange", // template relation - "orange" // type constraint -}; - -static const char *normalArrowStyleMap[] = -{ - "empty", // Public - "empty", // Protected - "empty", // Private - "open", // "use" relation - 0, // Undocumented - 0 // template relation -}; - -static const char *normalEdgeStyleMap[] = -{ - "solid", // inheritance - "dashed" // usage -}; - -static const char *umlEdgeColorMap[] = -{ - "midnightblue", // Public - "darkgreen", // Protected - "firebrick4", // Private - "grey25", // "use" relation - "grey75", // Undocumented - "orange", // template relation - "orange" // type constraint -}; - -static const char *umlArrowStyleMap[] = -{ - "onormal", // Public - "onormal", // Protected - "onormal", // Private - "odiamond", // "use" relation - 0, // Undocumented - 0 // template relation -}; - -static const char *umlEdgeStyleMap[] = -{ - "solid", // inheritance - "solid" // usage -}; - -/** Helper struct holding the properties of a edge in a dot graph. */ -struct EdgeProperties -{ - const char * const *edgeColorMap; - const char * const *arrowStyleMap; - const char * const *edgeStyleMap; -}; - -static EdgeProperties normalEdgeProps = -{ - normalEdgeColorMap, normalArrowStyleMap, normalEdgeStyleMap -}; - -static EdgeProperties umlEdgeProps = +void initDot() { - umlEdgeColorMap, umlArrowStyleMap, umlEdgeStyleMap -}; - - -static QCString getDotFontName() -{ - static QCString dotFontName = Config_getString(DOT_FONTNAME); - if (dotFontName.isEmpty()) + DotGraph::DOT_FONTNAME = Config_getString(DOT_FONTNAME); + if (DotGraph::DOT_FONTNAME.isEmpty()) { - //dotFontName="FreeSans.ttf"; - dotFontName="Helvetica"; + DotGraph::DOT_FONTNAME="Helvetica"; } - return dotFontName; -} -static int getDotFontSize() -{ - static int dotFontSize = Config_getInt(DOT_FONTSIZE); - if (dotFontSize<4) dotFontSize=4; - return dotFontSize; -} + DotGraph::DOT_FONTSIZE = Config_getInt(DOT_FONTSIZE); + if (DotGraph::DOT_FONTSIZE<4) DotGraph::DOT_FONTSIZE=4; -static void writeGraphHeader(FTextStream &t,const QCString &title=QCString()) -{ - static bool interactiveSVG = Config_getBool(INTERACTIVE_SVG); - t << "digraph "; - if (title.isEmpty()) - { - t << "\"Dot Graph\""; - } - else - { - t << "\"" << convertToXML(title) << "\""; - } - t << endl << "{" << endl; - if (interactiveSVG) // insert a comment to force regeneration when this - // option is toggled - { - t << " // INTERACTIVE_SVG=YES\n"; - } - t << " // LATEX_PDF_SIZE\n"; // write placeholder for LaTeX PDF bounding box size repacement - if (Config_getBool(DOT_TRANSPARENT)) - { - t << " bgcolor=\"transparent\";" << endl; - } - t << " edge [fontname=\"" << FONTNAME << "\"," - "fontsize=\"" << FONTSIZE << "\"," - "labelfontname=\"" << FONTNAME << "\"," - "labelfontsize=\"" << FONTSIZE << "\"];\n"; - t << " node [fontname=\"" << FONTNAME << "\"," - "fontsize=\"" << FONTSIZE << "\",shape=record];\n"; -} + DOT_NUM_THREADS = Config_getInt(DOT_NUM_THREADS); + if (DOT_NUM_THREADS > 32) DOT_NUM_THREADS = 32; + if (DOT_NUM_THREADS <= 0) DOT_NUM_THREADS = QMAX(2,QThread::idealThreadCount()+1); -static void writeGraphFooter(FTextStream &t) -{ - t << "}" << endl; -} + // these are copied to be sure to be thread save + DotRunner::DOT_CLEANUP = Config_getBool(DOT_CLEANUP); + DotRunner::DOT_MULTI_TARGETS = Config_getBool(DOT_MULTI_TARGETS); + DotRunner::DOT_EXE.init(Config_getString(DOT_PATH) + "dot"); -static QCString replaceRef(const QCString &buf,const QCString relPath, - bool urlOnly,const QCString &context,const QCString &target=QCString()) -{ - // search for href="...", store ... part in link - QCString href = "href"; - //bool isXLink=FALSE; - int len = 6; - int indexS = buf.find("href=\""), indexE; - bool setTarget = FALSE; - if (indexS>5 && buf.find("xlink:href=\"")!=-1) // XLink href (for SVG) - { - indexS-=6; - len+=6; - href.prepend("xlink:"); - //isXLink=TRUE; - } - if (indexS>=0 && (indexE=buf.find('"',indexS+len))!=-1) - { - QCString link = buf.mid(indexS+len,indexE-indexS-len); - QCString result; - if (urlOnly) // for user defined dot graphs - { - if (link.left(5)=="\\ref " || link.left(5)=="@ref ") // \ref url - { - result=href+"=\""; - // fake ref node to resolve the url - DocRef *df = new DocRef( (DocNode*) 0, link.mid(5), context ); - result+=externalRef(relPath,df->ref(),TRUE); - if (!df->file().isEmpty()) - result += df->file().data() + Doxygen::htmlFileExtension; - if (!df->anchor().isEmpty()) - result += "#" + df->anchor(); - delete df; - result += "\""; - } - else - { - result = href+"=\"" + link + "\""; - } - } - else // ref$url (external ref via tag file), or $url (local ref) - { - int marker = link.find('$'); - if (marker!=-1) - { - QCString ref = link.left(marker); - QCString url = link.mid(marker+1); - if (!ref.isEmpty()) - { - result = externalLinkTarget(); - if (result != "") setTarget = TRUE; - } - result+= href+"=\""; - result+=externalRef(relPath,ref,TRUE); - result+= url + "\""; - } - else // should not happen, but handle properly anyway - { - result = href+"=\"" + link + "\""; - } - } - if (!target.isEmpty() && !setTarget) - { - result+=" target=\""+target+"\""; - } - QCString leftPart = buf.left(indexS); - QCString rightPart = buf.mid(indexE+1); - return leftPart + result + rightPart; - } - else - { - return buf; - } + DotGraph::IMG_EXT = getDotImageExtension(); } -/*! converts the rectangles in a client site image map into a stream - * \param t the stream to which the result is written. - * \param mapName the name of the map file. - * \param relPath the relative path to the root of the output directory - * (used in case CREATE_SUBDIRS is enabled). - * \param urlOnly if FALSE the url field in the map contains an external - * references followed by a $ and then the URL. - * \param context the context (file, class, or namespace) in which the - * map file was found - * \returns TRUE if successful. - */ -static bool convertMapFile(FTextStream &t,const char *mapName, - const QCString relPath, bool urlOnly=FALSE, - const QCString &context=QCString()) -{ - QFile f(mapName); - if (!f.open(IO_ReadOnly)) - { - err("problems opening map file %s for inclusion in the docs!\n" - "If you installed Graphviz/dot after a previous failing run, \n" - "try deleting the output directory and rerun doxygen.\n",mapName); - return FALSE; - } - const int maxLineLen=10240; - while (!f.atEnd()) // foreach line - { - QCString buf(maxLineLen); - int numBytes = f.readLine(buf.rawData(),maxLineLen); - if (numBytes>0) - { - buf.resize(numBytes+1); - - if (buf.left(5)=="<area") - { - QCString replBuf = replaceRef(buf,relPath,urlOnly,context); - // strip id="..." from replBuf since the id's are not needed and not unique. - int indexS = replBuf.find("id=\""), indexE; - if (indexS>0 && (indexE=replBuf.find('"',indexS+4))!=-1) - { - t << replBuf.left(indexS-1) << replBuf.right(replBuf.length() - indexE - 1); - } - else - { - t << replBuf; - } - } - } - } - return TRUE; -} static QCString g_dotFontPath; @@ -448,147 +102,6 @@ static void unsetDotFontPath() g_dotFontPath=""; } -static bool resetPDFSize(const int width,const int height, const char *base) -{ - QString tmpName = QString::fromUtf8(QCString(base)+".tmp"); - QString patchFile = QString::fromUtf8(QCString(base)+".dot"); - if (!QDir::current().rename(patchFile,tmpName)) - { - err("Failed to rename file %s to %s!\n",patchFile.data(),tmpName.data()); - return FALSE; - } - QFile fi(tmpName); - QFile fo(patchFile); - if (!fi.open(IO_ReadOnly)) - { - err("problem opening file %s for patching!\n",tmpName.data()); - QDir::current().rename(tmpName,patchFile); - return FALSE; - } - if (!fo.open(IO_WriteOnly)) - { - err("problem opening file %s for patching!\n",patchFile.data()); - QDir::current().rename(tmpName,patchFile); - fi.close(); - return FALSE; - } - FTextStream t(&fo); - const int maxLineLen=100*1024; - while (!fi.atEnd()) // foreach line - { - QCString line(maxLineLen); - int numBytes = fi.readLine(line.rawData(),maxLineLen); - if (numBytes<=0) - { - break; - } - line.resize(numBytes+1); - if (line.find("LATEX_PDF_SIZE") != -1) - { - double scale = (width > height ? width : height)/double(MAX_LATEX_GRAPH_INCH); - t << " size=\""<<width/scale << "," <<height/scale <<"\";\n"; - } - else - t << line; - } - fi.close(); - fo.close(); - // remove temporary file - QDir::current().remove(tmpName); - return TRUE; -} -static bool readBoundingBox(const char *fileName,int *width,int *height,bool isEps) -{ - QCString bb = isEps ? QCString("%%PageBoundingBox:") : QCString("/MediaBox ["); - QFile f(fileName); - if (!f.open(IO_ReadOnly|IO_Raw)) - { - //printf("readBoundingBox: could not open %s\n",fileName); - return FALSE; - } - const int maxLineLen=1024; - char buf[maxLineLen]; - while (!f.atEnd()) - { - int numBytes = f.readLine(buf,maxLineLen-1); // read line - if (numBytes>0) - { - buf[numBytes]='\0'; - const char *p = strstr(buf,bb); - if (p) // found PageBoundingBox or /MediaBox string - { - int x,y; - if (sscanf(p+bb.length(),"%d %d %d %d",&x,&y,width,height)!=4) - { - //printf("readBoundingBox sscanf fail\n"); - return FALSE; - } - return TRUE; - } - } - else // read error! - { - //printf("Read error %d!\n",numBytes); - return FALSE; - } - } - err("Failed to extract bounding box from generated diagram file %s\n",fileName); - return FALSE; -} - -static bool writeVecGfxFigure(FTextStream &out,const QCString &baseName, - const QCString &figureName) -{ - int width=400,height=550; - static bool usePdfLatex = Config_getBool(USE_PDFLATEX); - if (usePdfLatex) - { - if (!readBoundingBox(figureName+".pdf",&width,&height,FALSE)) - { - //printf("writeVecGfxFigure()=0\n"); - return FALSE; - } - } - else - { - if (!readBoundingBox(figureName+".eps",&width,&height,TRUE)) - { - //printf("writeVecGfxFigure()=0\n"); - return FALSE; - } - } - //printf("Got PDF/EPS size %d,%d\n",width,height); - int maxWidth = 350; /* approx. page width in points, excl. margins */ - int maxHeight = 550; /* approx. page height in points, excl. margins */ - out << "\\nopagebreak\n" - "\\begin{figure}[H]\n" - "\\begin{center}\n" - "\\leavevmode\n"; - if (width>maxWidth || height>maxHeight) // figure too big for page - { - // c*width/maxWidth > c*height/maxHeight, where c=maxWidth*maxHeight>0 - if (width*maxHeight>height*maxWidth) - { - out << "\\includegraphics[width=" << maxWidth << "pt]"; - } - else - { - out << "\\includegraphics[height=" << maxHeight << "pt]"; - } - } - else - { - out << "\\includegraphics[width=" << width << "pt]"; - } - - out << "{" << baseName << "}\n" - "\\end{center}\n" - "\\end{figure}\n"; - - //printf("writeVecGfxFigure()=1\n"); - return TRUE; -} - // extract size from a dot generated SVG file static bool readSVGSize(const QCString &fileName,int *width,int *height) { @@ -636,8 +149,8 @@ static void writeSVGNotSupported(FTextStream &out) // check if a reference to a SVG figure can be written and does so if possible. // return FALSE if not possible (for instance because the SVG file is not yet generated). -static bool writeSVGFigureLink(FTextStream &out,const QCString &relPath, - const QCString &baseName,const QCString &absImgName) +bool writeSVGFigureLink(FTextStream &out,const QCString &relPath, + const QCString &baseName,const QCString &absImgName) { int width=600,height=600; if (!readSVGSize(absImgName,&width,&height)) @@ -678,593 +191,6 @@ static bool writeSVGFigureLink(FTextStream &out,const QCString &relPath, return TRUE; } -// since dot silently reproduces the input file when it does not -// support the PNG format, we need to check the result. -static void checkDotResult(const char *imgExt, const char *imgName) -{ - if (qstrcmp(imgExt,"png")==0) - { - FILE *f = portable_fopen(imgName,"rb"); - if (f) - { - char data[4]; - if (fread(data,1,4,f)==4) - { - if (!(data[1]=='P' && data[2]=='N' && data[3]=='G')) - { - err("Image `%s' produced by dot is not a valid PNG!\n" - "You should either select a different format " - "(DOT_IMAGE_FORMAT in the config file) or install a more " - "recent version of graphviz (1.7+)\n",imgName - ); - } - } - else - { - err("Could not read image `%s' generated by dot!\n",imgName); - } - fclose(f); - } - else - { - err("Could not open image `%s' generated by dot!\n",imgName); - } - } -} - -static bool insertMapFile(FTextStream &out,const QCString &mapFile, - const QCString &relPath,const QCString &mapLabel) -{ - QFileInfo fi(mapFile); - if (fi.exists() && fi.size()>0) // reuse existing map file - { - QGString tmpstr; - FTextStream tmpout(&tmpstr); - convertMapFile(tmpout,mapFile,relPath,TRUE); - if (!tmpstr.isEmpty()) - { - out << "<map name=\"" << mapLabel << "\" id=\"" << mapLabel << "\">" << endl; - out << tmpstr; - out << "</map>" << endl; - } - return TRUE; - } - return FALSE; // no map file yet, need to generate it -} - -static void removeDotGraph(const QCString &dotName) -{ - static bool dotCleanUp = Config_getBool(DOT_CLEANUP); - if (dotCleanUp) - { - QDir d; - d.remove(dotName); - } -} - - - -/*! Checks if a file "baseName".md5 exists. If so the contents - * are compared with \a md5. If equal FALSE is returned. If the .md5 - * file does not exist or its contents are not equal to \a md5, - * a new .md5 is generated with the \a md5 string as contents. - */ -static bool checkAndUpdateMd5Signature(const QCString &baseName, - const QCString &md5) -{ - QFile f(baseName+".md5"); - if (f.open(IO_ReadOnly)) - { - // read checksum - QCString md5stored(33); - int bytesRead=f.readBlock(md5stored.rawData(),32); - md5stored[32]='\0'; - // compare checksum - if (bytesRead==32 && md5==md5stored) - { - // bail out if equal - return FALSE; - } - } - f.close(); - // create checksum file - if (f.open(IO_WriteOnly)) - { - f.writeBlock(md5.data(),32); - f.close(); - } - return TRUE; -} - -static bool checkDeliverables(const QCString &file1, - const QCString &file2=QCString()) -{ - bool file1Ok = TRUE; - bool file2Ok = TRUE; - if (!file1.isEmpty()) - { - QFileInfo fi(file1); - file1Ok = (fi.exists() && fi.size()>0); - } - if (!file2.isEmpty()) - { - QFileInfo fi(file2); - file2Ok = (fi.exists() && fi.size()>0); - } - return file1Ok && file2Ok; -} - -//-------------------------------------------------------------------- - -inline int DotNode::findParent( DotNode *n ) -{ - if ( !m_parents ) return -1; - return m_parents->find(n); -} - -//-------------------------------------------------------------------- - -int DotNodeList::compareValues(const DotNode *n1,const DotNode *n2) const -{ - return qstricmp(n1->m_label,n2->m_label); -} - -//-------------------------------------------------------------------- - -DotRunner::DotRunner(const QCString &file,const QCString &path, - bool checkResult,const QCString &imageName) - : m_dotExe(Config_getString(DOT_PATH)+"dot"), - m_file(file), m_path(path), - m_checkResult(checkResult), m_imageName(imageName), - m_imgExt(getDotImageExtension()) -{ - static bool dotCleanUp = Config_getBool(DOT_CLEANUP); - static bool dotMultiTargets = Config_getBool(DOT_MULTI_TARGETS); - m_cleanUp = dotCleanUp; - m_multiTargets = dotMultiTargets; - m_jobs.setAutoDelete(TRUE); -} - -void DotRunner::addJob(const char *format,const char *output, const char *base) -{ - QCString args = QCString("-T")+format+" -o \""+output+"\""; - m_jobs.append(new DotConstString(args, base)); -} - -void DotRunner::addPostProcessing(const char *cmd,const char *args) -{ - m_postCmd.set(cmd); - m_postArgs.set(args); -} - -bool DotRunner::run() -{ - int exitCode=0; - int width=0,height=0; - - QCString dotArgs; - QListIterator<DotConstString> li(m_jobs); - DotConstString *s; - if (m_multiTargets) - { - dotArgs=QCString("\"")+m_file.data()+"\""; - for (li.toFirst();(s=li.current());++li) - { - dotArgs+=' '; - dotArgs+=s->data(); - } - if ((exitCode=portable_system(m_dotExe.data(),dotArgs,FALSE))!=0) goto error; - dotArgs=QCString("\"")+m_file.data()+"\""; - bool redo = FALSE; - for (li.toFirst();(s=li.current());++li) - { - if (s->pdfData()) - { - if (!readBoundingBox(QCString(s->pdfData())+".pdf",&width,&height,FALSE)) goto error; - if ((width > MAX_LATEX_GRAPH_SIZE) || (height > MAX_LATEX_GRAPH_SIZE)) - { - if (!resetPDFSize(width,height,s->pdfData())) goto error; - dotArgs+=' '; - dotArgs+=s->data(); - redo = TRUE; - } - } - } - if (redo) - { - if ((exitCode=portable_system(m_dotExe.data(),dotArgs,FALSE))!=0) goto error; - } - } - else - { - for (li.toFirst();(s=li.current());++li) - { - dotArgs=QCString("\"")+m_file.data()+"\" "+s->data(); - if ((exitCode=portable_system(m_dotExe.data(),dotArgs,FALSE))!=0) goto error; - if (s->pdfData()) - { - if (!readBoundingBox(QCString(s->pdfData())+".pdf",&width,&height,FALSE)) goto error; - if ((width > MAX_LATEX_GRAPH_SIZE) || (height > MAX_LATEX_GRAPH_SIZE)) - { - if (!resetPDFSize(width,height,s->pdfData())) goto error; - if ((exitCode=portable_system(m_dotExe.data(),dotArgs,FALSE))!=0) goto error; - } - } - } - } - if (!m_postCmd.isEmpty() && portable_system(m_postCmd.data(),m_postArgs.data())!=0) - { - err("Problems running '%s' as a post-processing step for dot output\n",m_postCmd.data()); - return FALSE; - } - if (m_checkResult) - { - checkDotResult(m_imgExt.data(),m_imageName.data()); - } - if (m_cleanUp) - { - //printf("removing dot file %s\n",m_file.data()); - //QDir(path).remove(file); - m_cleanupItem.file.set(m_file.data()); - m_cleanupItem.path.set(m_path.data()); - } - return TRUE; -error: - err("Problems running dot: exit code=%d, command='%s', arguments='%s'\n", - exitCode,m_dotExe.data(),dotArgs.data()); - return FALSE; -} - -//-------------------------------------------------------------------- - -DotFilePatcher::DotFilePatcher(const char *patchFile) - : m_patchFile(patchFile) -{ - m_maps.setAutoDelete(TRUE); -} - -QCString DotFilePatcher::file() const -{ - return m_patchFile; -} - -int DotFilePatcher::addMap(const QCString &mapFile,const QCString &relPath, - bool urlOnly,const QCString &context,const QCString &label) -{ - int id = m_maps.count(); - Map *map = new Map; - map->mapFile = mapFile; - map->relPath = relPath; - map->urlOnly = urlOnly; - map->context = context; - map->label = label; - map->zoomable = FALSE; - map->graphId = -1; - m_maps.append(map); - return id; -} - -int DotFilePatcher::addFigure(const QCString &baseName, - const QCString &figureName,bool heightCheck) -{ - int id = m_maps.count(); - Map *map = new Map; - map->mapFile = figureName; - map->urlOnly = heightCheck; - map->label = baseName; - map->zoomable = FALSE; - map->graphId = -1; - m_maps.append(map); - return id; -} - -int DotFilePatcher::addSVGConversion(const QCString &relPath,bool urlOnly, - const QCString &context,bool zoomable, - int graphId) -{ - int id = m_maps.count(); - Map *map = new Map; - map->relPath = relPath; - map->urlOnly = urlOnly; - map->context = context; - map->zoomable = zoomable; - map->graphId = graphId; - m_maps.append(map); - return id; -} - -int DotFilePatcher::addSVGObject(const QCString &baseName, - const QCString &absImgName, - const QCString &relPath) -{ - int id = m_maps.count(); - Map *map = new Map; - map->mapFile = absImgName; - map->relPath = relPath; - map->label = baseName; - map->zoomable = FALSE; - map->graphId = -1; - m_maps.append(map); - return id; -} - -bool DotFilePatcher::run() -{ - //printf("DotFilePatcher::run(): %s\n",m_patchFile.data()); - static bool interactiveSVG = Config_getBool(INTERACTIVE_SVG); - bool isSVGFile = m_patchFile.right(4)==".svg"; - int graphId = -1; - QCString relPath; - if (isSVGFile) - { - Map *map = m_maps.at(0); // there is only one 'map' for a SVG file - interactiveSVG = interactiveSVG && map->zoomable; - graphId = map->graphId; - relPath = map->relPath; - //printf("DotFilePatcher::addSVGConversion: file=%s zoomable=%d\n", - // m_patchFile.data(),map->zoomable); - } - QString tmpName = QString::fromUtf8(m_patchFile+".tmp"); - QString patchFile = QString::fromUtf8(m_patchFile); - if (!QDir::current().rename(patchFile,tmpName)) - { - err("Failed to rename file %s to %s!\n",m_patchFile.data(),tmpName.data()); - return FALSE; - } - QFile fi(tmpName); - QFile fo(patchFile); - if (!fi.open(IO_ReadOnly)) - { - err("problem opening file %s for patching!\n",tmpName.data()); - QDir::current().rename(tmpName,patchFile); - return FALSE; - } - if (!fo.open(IO_WriteOnly)) - { - err("problem opening file %s for patching!\n",m_patchFile.data()); - QDir::current().rename(tmpName,patchFile); - return FALSE; - } - FTextStream t(&fo); - const int maxLineLen=100*1024; - int lineNr=1; - int width,height; - bool insideHeader=FALSE; - bool replacedHeader=FALSE; - bool foundSize=FALSE; - while (!fi.atEnd()) // foreach line - { - QCString line(maxLineLen); - int numBytes = fi.readLine(line.rawData(),maxLineLen); - if (numBytes<=0) - { - break; - } - line.resize(numBytes+1); - - //printf("line=[%s]\n",line.stripWhiteSpace().data()); - int i; - ASSERT(numBytes<maxLineLen); - if (isSVGFile) - { - if (interactiveSVG) - { - if (line.find("<svg")!=-1 && !replacedHeader) - { - int count; - count = sscanf(line.data(),"<svg width=\"%dpt\" height=\"%dpt\"",&width,&height); - //printf("width=%d height=%d\n",width,height); - foundSize = count==2 && (width>500 || height>450); - if (foundSize) insideHeader=TRUE; - } - else if (insideHeader && !replacedHeader && line.find("<title>")!=-1) - { - if (foundSize) - { - // insert special replacement header for interactive SVGs - t << "<!--zoomable " << height << " -->\n"; - t << svgZoomHeader; - t << "var viewWidth = " << width << ";\n"; - t << "var viewHeight = " << height << ";\n"; - if (graphId>=0) - { - t << "var sectionId = 'dynsection-" << graphId << "';\n"; - } - t << "</script>\n"; - t << "<script xlink:href=\"" << relPath << "svgpan.js\"/>\n"; - t << "<svg id=\"graph\" class=\"graph\">\n"; - t << "<g id=\"viewport\">\n"; - } - insideHeader=FALSE; - replacedHeader=TRUE; - } - } - if (!insideHeader || !foundSize) // copy SVG and replace refs, - // unless we are inside the header of the SVG. - // Then we replace it with another header. - { - Map *map = m_maps.at(0); // there is only one 'map' for a SVG file - t << replaceRef(line,map->relPath,map->urlOnly,map->context,"_top"); - } - } - else if ((i=line.find("<!-- SVG"))!=-1 || (i=line.find("[!-- SVG"))!=-1) - { - //printf("Found marker at %d\n",i); - int mapId=-1; - t << line.left(i); - int n = sscanf(line.data()+i+1,"!-- SVG %d",&mapId); - if (n==1 && mapId>=0 && mapId<(int)m_maps.count()) - { - int e = QMAX(line.find("--]"),line.find("-->")); - Map *map = m_maps.at(mapId); - //printf("DotFilePatcher::writeSVGFigure: file=%s zoomable=%d\n", - // m_patchFile.data(),map->zoomable); - if (!writeSVGFigureLink(t,map->relPath,map->label,map->mapFile)) - { - err("Problem extracting size from SVG file %s\n",map->mapFile.data()); - } - if (e!=-1) t << line.mid(e+3); - } - else // error invalid map id! - { - err("Found invalid SVG id in file %s!\n",m_patchFile.data()); - t << line.mid(i); - } - } - else if ((i=line.find("<!-- MAP"))!=-1) - { - int mapId=-1; - t << line.left(i); - int n = sscanf(line.data()+i,"<!-- MAP %d",&mapId); - if (n==1 && mapId>=0 && mapId<(int)m_maps.count()) - { - QGString result; - FTextStream tt(&result); - Map *map = m_maps.at(mapId); - //printf("patching MAP %d in file %s with contents of %s\n", - // mapId,m_patchFile.data(),map->mapFile.data()); - convertMapFile(tt,map->mapFile,map->relPath,map->urlOnly,map->context); - if (!result.isEmpty()) - { - t << "<map name=\"" << map->label << "\" id=\"" << map->label << "\">" << endl; - t << result; - t << "</map>" << endl; - } - } - else // error invalid map id! - { - err("Found invalid MAP id in file %s!\n",m_patchFile.data()); - t << line.mid(i); - } - } - else if ((i=line.find("% FIG"))!=-1) - { - int mapId=-1; - int n = sscanf(line.data()+i+2,"FIG %d",&mapId); - //printf("line='%s' n=%d\n",line.data()+i,n); - if (n==1 && mapId>=0 && mapId<(int)m_maps.count()) - { - Map *map = m_maps.at(mapId); - //printf("patching FIG %d in file %s with contents of %s\n", - // mapId,m_patchFile.data(),map->mapFile.data()); - if (!writeVecGfxFigure(t,map->label,map->mapFile)) - { - err("problem writing FIG %d figure!\n",mapId); - return FALSE; - } - } - else // error invalid map id! - { - err("Found invalid bounding FIG %d in file %s!\n",mapId,m_patchFile.data()); - t << line; - } - } - else - { - t << line; - } - lineNr++; - } - fi.close(); - if (isSVGFile && interactiveSVG && replacedHeader) - { - QCString orgName=m_patchFile.left(m_patchFile.length()-4)+"_org.svg"; - t << substitute(svgZoomFooter,"$orgname",stripPath(orgName)); - fo.close(); - // keep original SVG file so we can refer to it, we do need to replace - // dummy link by real ones - QFile fi(tmpName); - QFile fo(orgName); - if (!fi.open(IO_ReadOnly)) - { - err("problem opening file %s for reading!\n",tmpName.data()); - return FALSE; - } - if (!fo.open(IO_WriteOnly)) - { - err("problem opening file %s for writing!\n",orgName.data()); - return FALSE; - } - FTextStream t(&fo); - while (!fi.atEnd()) // foreach line - { - QCString line(maxLineLen); - int numBytes = fi.readLine(line.rawData(),maxLineLen); - if (numBytes<=0) - { - break; - } - line.resize(numBytes+1); - Map *map = m_maps.at(0); // there is only one 'map' for a SVG file - t << replaceRef(line,map->relPath,map->urlOnly,map->context,"_top"); - } - fi.close(); - fo.close(); - } - // remove temporary file - QDir::current().remove(tmpName); - return TRUE; -} - -//-------------------------------------------------------------------- - -void DotRunnerQueue::enqueue(DotRunner *runner) -{ - QMutexLocker locker(&m_mutex); - m_queue.enqueue(runner); - m_bufferNotEmpty.wakeAll(); -} - -DotRunner *DotRunnerQueue::dequeue() -{ - QMutexLocker locker(&m_mutex); - while (m_queue.isEmpty()) - { - // wait until something is added to the queue - m_bufferNotEmpty.wait(&m_mutex); - } - DotRunner *result = m_queue.dequeue(); - return result; -} - -uint DotRunnerQueue::count() const -{ - QMutexLocker locker(&m_mutex); - return m_queue.count(); -} - -//-------------------------------------------------------------------- - -DotWorkerThread::DotWorkerThread(DotRunnerQueue *queue) - : m_queue(queue) -{ - m_cleanupItems.setAutoDelete(TRUE); -} - -void DotWorkerThread::run() -{ - DotRunner *runner; - while ((runner=m_queue->dequeue())) - { - runner->run(); - const DotRunner::CleanupItem &cleanup = runner->cleanup(); - if (!cleanup.file.isEmpty()) - { - m_cleanupItems.append(new DotRunner::CleanupItem(cleanup)); - } - } -} - -void DotWorkerThread::cleanup() -{ - QListIterator<DotRunner::CleanupItem> it(m_cleanupItems); - DotRunner::CleanupItem *ci; - for (;(ci=it.current());++it) - { - QDir(ci->path.data()).remove(ci->file.data()); - } -} - //-------------------------------------------------------------------- DotManager *DotManager::m_theInstance = 0; @@ -1280,15 +206,13 @@ DotManager *DotManager::instance() DotManager::DotManager() : m_dotMaps(1009) { - m_dotRuns.setAutoDelete(TRUE); + m_runners.setAutoDelete(TRUE); m_dotMaps.setAutoDelete(TRUE); m_queue = new DotRunnerQueue; int i; - int numThreads = QMIN(32,Config_getInt(DOT_NUM_THREADS)); - if (numThreads!=1) + if (DOT_NUM_THREADS!=1) { - if (numThreads==0) numThreads = QMAX(2,QThread::idealThreadCount()+1); - for (i=0;i<numThreads;i++) + for (i=0;i<DOT_NUM_THREADS;i++) { DotWorkerThread *thread = new DotWorkerThread(m_queue); thread->start(); @@ -1310,11 +234,26 @@ DotManager::~DotManager() delete m_queue; } -void DotManager::addRun(DotRunner *run) +DotRunner* DotManager::createRunner(const QCString& absDotName, const QCString& md5Hash) { - m_dotRuns.append(run); + DotRunner * run = m_runners.find(absDotName); + if (run == 0) + { + run = new DotRunner(absDotName, md5Hash); + m_runners.insert(absDotName, run); + } + else + { + // we have a match + if (md5Hash != QCString(run->getMd5Hash().data())) + { + err("md5 hash does not match for two different runs of %s !\n", absDotName.data()); + } + } + return run; } + int DotManager::addMap(const QCString &file,const QCString &mapFile, const QCString &relPath,bool urlOnly,const QCString &context, const QCString &label) @@ -1367,7 +306,7 @@ int DotManager::addSVGObject(const QCString &file,const QCString &baseName, bool DotManager::run() { - uint numDotRuns = m_dotRuns.count(); + uint numDotRuns = m_runners.count(); uint numDotMaps = m_dotMaps.count(); if (numDotRuns+numDotMaps>1) { @@ -1381,7 +320,7 @@ bool DotManager::run() } } int i=1; - QListIterator<DotRunner> li(m_dotRuns); + QDictIterator<DotRunner> li(m_runners); bool setPath=FALSE; if (Config_getBool(GENERATE_HTML)) @@ -1449,11 +388,6 @@ bool DotManager::run() { m_workers.at(i)->wait(); } - // clean up dot files from main thread - for (i=0;i<(int)m_workers.count();i++) - { - m_workers.at(i)->cleanup(); - } } portable_sysTimerStop(); if (setPath) @@ -1492,2756 +426,59 @@ bool DotManager::run() //-------------------------------------------------------------------- - -/*! helper function that deletes all nodes in a connected graph, given - * one of the graph's nodes - */ -static void deleteNodes(DotNode *node,SDict<DotNode> *skipNodes=0) -{ - //printf("deleteNodes skipNodes=%p\n",skipNodes); - static DotNodeList deletedNodes; - deletedNodes.setAutoDelete(TRUE); - node->deleteNode(deletedNodes,skipNodes); // collect nodes to be deleted. - deletedNodes.clear(); // actually remove the nodes. -} - -DotNode::DotNode(int n,const char *lab,const char *tip, const char *url, - bool isRoot,ClassDef *cd) - : m_subgraphId(-1) - , m_number(n) - , m_label(lab) - , m_tooltip(tip) - , m_url(url) - , m_parents(0) - , m_children(0) - , m_edgeInfo(0) - , m_deleted(FALSE) - , m_written(FALSE) - , m_hasDoc(FALSE) - , m_isRoot(isRoot) - , m_classDef(cd) - , m_visible(FALSE) - , m_truncated(Unknown) - , m_distance(1000) - , m_renumbered(false) -{ -} - -DotNode::~DotNode() -{ - delete m_children; - delete m_parents; - delete m_edgeInfo; -} - -void DotNode::addChild(DotNode *n, - int edgeColor, - int edgeStyle, - const char *edgeLab, - const char *edgeURL, - int edgeLabCol - ) -{ - if (m_children==0) - { - m_children = new QList<DotNode>; - m_edgeInfo = new QList<EdgeInfo>; - m_edgeInfo->setAutoDelete(TRUE); - } - m_children->append(n); - EdgeInfo *ei = new EdgeInfo; - ei->m_color = edgeColor; - ei->m_style = edgeStyle; - ei->m_label = edgeLab; - ei->m_url = edgeURL; - if (edgeLabCol==-1) - ei->m_labColor=edgeColor; - else - ei->m_labColor=edgeLabCol; - m_edgeInfo->append(ei); -} - -void DotNode::addParent(DotNode *n) -{ - if (m_parents==0) - { - m_parents = new QList<DotNode>; - } - m_parents->append(n); -} - -void DotNode::removeChild(DotNode *n) -{ - if (m_children) m_children->remove(n); -} - -void DotNode::removeParent(DotNode *n) -{ - if (m_parents) m_parents->remove(n); -} - -void DotNode::deleteNode(DotNodeList &deletedList,SDict<DotNode> *skipNodes) -{ - if (m_deleted) return; // avoid recursive loops in case the graph has cycles - m_deleted=TRUE; - if (m_parents!=0) // delete all parent nodes of this node - { - QListIterator<DotNode> dnlip(*m_parents); - DotNode *pn; - for (dnlip.toFirst();(pn=dnlip.current());++dnlip) - { - //pn->removeChild(this); - pn->deleteNode(deletedList,skipNodes); - } - } - if (m_children!=0) // delete all child nodes of this node - { - QListIterator<DotNode> dnlic(*m_children); - DotNode *cn; - for (dnlic.toFirst();(cn=dnlic.current());++dnlic) - { - //cn->removeParent(this); - cn->deleteNode(deletedList,skipNodes); - } - } - // add this node to the list of deleted nodes. - //printf("skipNodes=%p find(%p)=%p\n",skipNodes,this,skipNodes ? skipNodes->find((int)this) : 0); - if (skipNodes==0 || skipNodes->find((char*)this)==0) - { - //printf("deleting\n"); - deletedList.append(this); - } -} - -void DotNode::setDistance(int distance) -{ - if (distance<m_distance) m_distance = distance; -} - -static QCString convertLabel(const QCString &l) -{ - QString bBefore("\\_/<({[: =-+@%#~?$"); // break before character set - QString bAfter(">]),:;|"); // break after character set - QString p(l); - if (p.isEmpty()) return QCString(); - QString result; - QChar c,pc=0; - uint idx = 0; - int len=p.length(); - int charsLeft=len; - int sinceLast=0; - int foldLen=17; // ideal text length - while (idx < p.length()) - { - c = p[idx++]; - QString replacement; - switch(c) - { - case '\\': replacement="\\\\"; break; - case '\n': replacement="\\n"; break; - case '<': replacement="\\<"; break; - case '>': replacement="\\>"; break; - case '|': replacement="\\|"; break; - case '{': replacement="\\{"; break; - case '}': replacement="\\}"; break; - case '"': replacement="\\\""; break; - default: replacement=c; break; - } - // Some heuristics to insert newlines to prevent too long - // boxes and at the same time prevent ugly breaks - if (c=='\n') - { - result+=replacement; - foldLen = (3*foldLen+sinceLast+2)/4; - sinceLast=1; - } - else if ((pc!=':' || c!=':') && charsLeft>foldLen/3 && sinceLast>foldLen && bBefore.contains(c)) - { - result+="\\l"; - result+=replacement; - foldLen = (foldLen+sinceLast+1)/2; - sinceLast=1; - } - else if (charsLeft>1+foldLen/4 && sinceLast>foldLen+foldLen/3 && - !isupper(c) && p[idx].category()==QChar::Letter_Uppercase) - { - result+=replacement; - result+="\\l"; - foldLen = (foldLen+sinceLast+1)/2; - sinceLast=0; - } - else if (charsLeft>foldLen/3 && sinceLast>foldLen && bAfter.contains(c) && (c!=':' || p[idx]!=':')) - { - result+=replacement; - result+="\\l"; - foldLen = (foldLen+sinceLast+1)/2; - sinceLast=0; - } - else - { - result+=replacement; - sinceLast++; - } - charsLeft--; - pc=c; - } - return result.utf8(); -} - -static QCString escapeTooltip(const QCString &tooltip) -{ - QCString result; - const char *p=tooltip.data(); - if (p==0) return result; - char c; - while ((c=*p++)) - { - switch(c) - { - case '"': result+="\\\""; break; - default: result+=c; break; - } - } - return result; -} - -static void writeBoxMemberList(FTextStream &t, - char prot,MemberList *ml,ClassDef *scope, - bool isStatic=FALSE,const QDict<void> *skipNames=0) -{ - (void)isStatic; - if (ml) - { - MemberListIterator mlia(*ml); - MemberDef *mma; - int totalCount=0; - for (mlia.toFirst();(mma = mlia.current());++mlia) - { - if (mma->getClassDef()==scope && - (skipNames==0 || skipNames->find(mma->name())==0)) - { - totalCount++; - } - } - - int count=0; - for (mlia.toFirst();(mma = mlia.current());++mlia) - { - if (mma->getClassDef() == scope && - (skipNames==0 || skipNames->find(mma->name())==0)) - { - static int limit = Config_getInt(UML_LIMIT_NUM_FIELDS); - if (limit>0 && (totalCount>limit*3/2 && count>=limit)) - { - t << theTranslator->trAndMore(QCString().sprintf("%d",totalCount-count)) << "\\l"; - break; - } - else - { - t << prot << " "; - t << convertLabel(mma->name()); - if (!mma->isObjCMethod() && - (mma->isFunction() || mma->isSlot() || mma->isSignal())) t << "()"; - t << "\\l"; - count++; - } - } - } - // write member groups within the memberlist - MemberGroupList *mgl = ml->getMemberGroupList(); - if (mgl) - { - MemberGroupListIterator mgli(*mgl); - MemberGroup *mg; - for (mgli.toFirst();(mg=mgli.current());++mgli) - { - if (mg->members()) - { - writeBoxMemberList(t,prot,mg->members(),scope,isStatic,skipNames); - } - } - } - } -} - -static QCString stripProtectionPrefix(const QCString &s) -{ - if (!s.isEmpty() && (s[0]=='-' || s[0]=='+' || s[0]=='~' || s[0]=='#')) - { - return s.mid(1); - } - else - { - return s; - } -} - -void DotNode::writeBox(FTextStream &t, - GraphType gt, - GraphOutputFormat /*format*/, - bool hasNonReachableChildren - ) -{ - const char *labCol = - m_url.isEmpty() ? "grey75" : // non link - ( - (hasNonReachableChildren) ? "red" : "black" - ); - t << " Node" << m_number << " [label=\""; - static bool umlLook = Config_getBool(UML_LOOK); - - if (m_classDef && umlLook && (gt==Inheritance || gt==Collaboration)) - { - // add names shown as relations to a dictionary, so we don't show - // them as attributes as well - QDict<void> arrowNames(17); - if (m_edgeInfo) - { - // for each edge - QListIterator<EdgeInfo> li(*m_edgeInfo); - EdgeInfo *ei; - for (li.toFirst();(ei=li.current());++li) - { - if (!ei->m_label.isEmpty()) // labels joined by \n - { - int li=ei->m_label.find('\n'); - int p=0; - QCString lab; - while ((li=ei->m_label.find('\n',p))!=-1) - { - lab = stripProtectionPrefix(ei->m_label.mid(p,li-p)); - arrowNames.insert(lab,(void*)0x8); - p=li+1; - } - lab = stripProtectionPrefix(ei->m_label.right(ei->m_label.length()-p)); - arrowNames.insert(lab,(void*)0x8); - } - } - } - - //printf("DotNode::writeBox for %s\n",m_classDef->name().data()); - static bool extractPrivate = Config_getBool(EXTRACT_PRIVATE); - t << "{" << convertLabel(m_label); - t << "\\n|"; - writeBoxMemberList(t,'+',m_classDef->getMemberList(MemberListType_pubAttribs),m_classDef,FALSE,&arrowNames); - writeBoxMemberList(t,'+',m_classDef->getMemberList(MemberListType_pubStaticAttribs),m_classDef,TRUE,&arrowNames); - writeBoxMemberList(t,'+',m_classDef->getMemberList(MemberListType_properties),m_classDef,FALSE,&arrowNames); - writeBoxMemberList(t,'~',m_classDef->getMemberList(MemberListType_pacAttribs),m_classDef,FALSE,&arrowNames); - writeBoxMemberList(t,'~',m_classDef->getMemberList(MemberListType_pacStaticAttribs),m_classDef,TRUE,&arrowNames); - writeBoxMemberList(t,'#',m_classDef->getMemberList(MemberListType_proAttribs),m_classDef,FALSE,&arrowNames); - writeBoxMemberList(t,'#',m_classDef->getMemberList(MemberListType_proStaticAttribs),m_classDef,TRUE,&arrowNames); - if (extractPrivate) - { - writeBoxMemberList(t,'-',m_classDef->getMemberList(MemberListType_priAttribs),m_classDef,FALSE,&arrowNames); - writeBoxMemberList(t,'-',m_classDef->getMemberList(MemberListType_priStaticAttribs),m_classDef,TRUE,&arrowNames); - } - t << "|"; - writeBoxMemberList(t,'+',m_classDef->getMemberList(MemberListType_pubMethods),m_classDef); - writeBoxMemberList(t,'+',m_classDef->getMemberList(MemberListType_pubStaticMethods),m_classDef,TRUE); - writeBoxMemberList(t,'+',m_classDef->getMemberList(MemberListType_pubSlots),m_classDef); - writeBoxMemberList(t,'~',m_classDef->getMemberList(MemberListType_pacMethods),m_classDef); - writeBoxMemberList(t,'~',m_classDef->getMemberList(MemberListType_pacStaticMethods),m_classDef,TRUE); - writeBoxMemberList(t,'#',m_classDef->getMemberList(MemberListType_proMethods),m_classDef); - writeBoxMemberList(t,'#',m_classDef->getMemberList(MemberListType_proStaticMethods),m_classDef,TRUE); - writeBoxMemberList(t,'#',m_classDef->getMemberList(MemberListType_proSlots),m_classDef); - if (extractPrivate) - { - writeBoxMemberList(t,'-',m_classDef->getMemberList(MemberListType_priMethods),m_classDef); - writeBoxMemberList(t,'-',m_classDef->getMemberList(MemberListType_priStaticMethods),m_classDef,TRUE); - writeBoxMemberList(t,'-',m_classDef->getMemberList(MemberListType_priSlots),m_classDef); - } - if (m_classDef->getLanguage()!=SrcLangExt_Fortran && - m_classDef->getMemberGroupSDict()) - { - MemberGroupSDict::Iterator mgdi(*m_classDef->getMemberGroupSDict()); - MemberGroup *mg; - for (mgdi.toFirst();(mg=mgdi.current());++mgdi) - { - if (mg->members()) - { - writeBoxMemberList(t,'*',mg->members(),m_classDef,FALSE,&arrowNames); - } - } - } - t << "}"; - } - else // standard look - { - t << convertLabel(m_label); - } - t << "\",height=0.2,width=0.4"; - if (m_isRoot) - { - t << ",color=\"black\", fillcolor=\"grey75\", style=\"filled\", fontcolor=\"black\""; - } - else - { - static bool dotTransparent = Config_getBool(DOT_TRANSPARENT); - if (!dotTransparent) - { - t << ",color=\"" << labCol << "\", fillcolor=\""; - t << "white"; - t << "\", style=\"filled\""; - } - else - { - t << ",color=\"" << labCol << "\""; - } - if (!m_url.isEmpty()) - { - int anchorPos = m_url.findRev('#'); - if (anchorPos==-1) - { - t << ",URL=\"" << m_url << Doxygen::htmlFileExtension << "\""; - } - else - { - t << ",URL=\"" << m_url.left(anchorPos) << Doxygen::htmlFileExtension - << m_url.right(m_url.length()-anchorPos) << "\""; - } - } - } - if (!m_tooltip.isEmpty()) - { - t << ",tooltip=\"" << escapeTooltip(m_tooltip) << "\""; - } - else - { - t << ",tooltip=\" \""; // space in tooltip is required otherwise still something like 'Node0' is used - } - t << "];" << endl; -} - -void DotNode::writeArrow(FTextStream &t, - GraphType gt, - GraphOutputFormat format, - DotNode *cn, - EdgeInfo *ei, - bool topDown, - bool pointBack - ) -{ - t << " Node"; - if (topDown) - t << cn->number(); - else - t << m_number; - t << " -> Node"; - if (topDown) - t << m_number; - else - t << cn->number(); - t << " ["; - - static bool umlLook = Config_getBool(UML_LOOK); - const EdgeProperties *eProps = umlLook ? ¨EdgeProps : &normalEdgeProps; - QCString aStyle = eProps->arrowStyleMap[ei->m_color]; - bool umlUseArrow = aStyle=="odiamond"; - - if (pointBack && !umlUseArrow) t << "dir=\"back\","; - t << "color=\"" << eProps->edgeColorMap[ei->m_color] - << "\",fontsize=\"" << FONTSIZE << "\","; - t << "style=\"" << eProps->edgeStyleMap[ei->m_style] << "\""; - if (!ei->m_label.isEmpty()) - { - t << ",label=\" " << convertLabel(ei->m_label) << "\" "; - } - if (umlLook && - eProps->arrowStyleMap[ei->m_color] && - (gt==Inheritance || gt==Collaboration) - ) - { - bool rev = pointBack; - if (umlUseArrow) rev=!rev; // UML use relates has arrow on the start side - if (rev) - t << ",arrowtail=\"" << eProps->arrowStyleMap[ei->m_color] << "\""; - else - t << ",arrowhead=\"" << eProps->arrowStyleMap[ei->m_color] << "\""; - } - - if (format==GOF_BITMAP) t << ",fontname=\"" << FONTNAME << "\""; - t << "];" << endl; -} - -void DotNode::write(FTextStream &t, - GraphType gt, - GraphOutputFormat format, - bool topDown, - bool toChildren, - bool backArrows - ) -{ - //printf("DotNode::write(%d) name=%s this=%p written=%d visible=%d\n",m_distance,m_label.data(),this,m_written,m_visible); - if (m_written) return; // node already written to the output - if (!m_visible) return; // node is not visible - writeBox(t,gt,format,m_truncated==Truncated); - m_written=TRUE; - QList<DotNode> *nl = toChildren ? m_children : m_parents; - if (nl) - { - if (toChildren) - { - QListIterator<DotNode> dnli1(*nl); - QListIterator<EdgeInfo> dnli2(*m_edgeInfo); - DotNode *cn; - for (dnli1.toFirst();(cn=dnli1.current());++dnli1,++dnli2) - { - if (cn->isVisible()) - { - //printf("write arrow %s%s%s\n",label().data(),backArrows?"<-":"->",cn->label().data()); - writeArrow(t,gt,format,cn,dnli2.current(),topDown,backArrows); - } - cn->write(t,gt,format,topDown,toChildren,backArrows); - } - } - else // render parents - { - QListIterator<DotNode> dnli(*nl); - DotNode *pn; - for (dnli.toFirst();(pn=dnli.current());++dnli) - { - if (pn->isVisible()) - { - //printf("write arrow %s%s%s\n",label().data(),backArrows?"<-":"->",pn->label().data()); - writeArrow(t, - gt, - format, - pn, - pn->m_edgeInfo->at(pn->m_children->findRef(this)), - FALSE, - backArrows - ); - } - pn->write(t,gt,format,TRUE,FALSE,backArrows); - } - } - } - //printf("end DotNode::write(%d) name=%s\n",distance,m_label.data()); -} - -void DotNode::writeXML(FTextStream &t,bool isClassGraph) -{ - t << " <node id=\"" << m_number << "\">" << endl; - t << " <label>" << convertToXML(m_label) << "</label>" << endl; - if (!m_url.isEmpty()) - { - QCString url(m_url); - const char *refPtr = url.data(); - char *urlPtr = strchr(url.rawData(),'$'); - if (urlPtr) - { - *urlPtr++='\0'; - t << " <link refid=\"" << convertToXML(urlPtr) << "\""; - if (*refPtr!='\0') - { - t << " external=\"" << convertToXML(refPtr) << "\""; - } - t << "/>" << endl; - } - } - if (m_children) - { - QListIterator<DotNode> nli(*m_children); - QListIterator<EdgeInfo> eli(*m_edgeInfo); - DotNode *childNode; - EdgeInfo *edgeInfo; - for (;(childNode=nli.current());++nli,++eli) - { - edgeInfo=eli.current(); - t << " <childnode refid=\"" << childNode->m_number << "\" relation=\""; - if (isClassGraph) - { - switch(edgeInfo->m_color) - { - case EdgeInfo::Blue: t << "public-inheritance"; break; - case EdgeInfo::Green: t << "protected-inheritance"; break; - case EdgeInfo::Red: t << "private-inheritance"; break; - case EdgeInfo::Purple: t << "usage"; break; - case EdgeInfo::Orange: t << "template-instance"; break; - case EdgeInfo::Orange2: t << "type-constraint"; break; - case EdgeInfo::Grey: ASSERT(0); break; - } - } - else // include graph - { - t << "include"; - } - t << "\">" << endl; - if (!edgeInfo->m_label.isEmpty()) - { - int p=0; - int ni; - while ((ni=edgeInfo->m_label.find('\n',p))!=-1) - { - t << " <edgelabel>" - << convertToXML(edgeInfo->m_label.mid(p,ni-p)) - << "</edgelabel>" << endl; - p=ni+1; - } - t << " <edgelabel>" - << convertToXML(edgeInfo->m_label.right(edgeInfo->m_label.length()-p)) - << "</edgelabel>" << endl; - } - t << " </childnode>" << endl; - } - } - t << " </node>" << endl; -} - -void DotNode::writeDocbook(FTextStream &t,bool isClassGraph) -{ - t << " <node id=\"" << m_number << "\">" << endl; - t << " <label>" << convertToXML(m_label) << "</label>" << endl; - if (!m_url.isEmpty()) - { - QCString url(m_url); - const char *refPtr = url.data(); - char *urlPtr = strchr(url.rawData(),'$'); - if (urlPtr) - { - *urlPtr++='\0'; - t << " <link refid=\"" << convertToXML(urlPtr) << "\""; - if (*refPtr!='\0') - { - t << " external=\"" << convertToXML(refPtr) << "\""; - } - t << "/>" << endl; - } - } - if (m_children) - { - QListIterator<DotNode> nli(*m_children); - QListIterator<EdgeInfo> eli(*m_edgeInfo); - DotNode *childNode; - EdgeInfo *edgeInfo; - for (;(childNode=nli.current());++nli,++eli) - { - edgeInfo=eli.current(); - t << " <childnode refid=\"" << childNode->m_number << "\" relation=\""; - if (isClassGraph) - { - switch(edgeInfo->m_color) - { - case EdgeInfo::Blue: t << "public-inheritance"; break; - case EdgeInfo::Green: t << "protected-inheritance"; break; - case EdgeInfo::Red: t << "private-inheritance"; break; - case EdgeInfo::Purple: t << "usage"; break; - case EdgeInfo::Orange: t << "template-instance"; break; - case EdgeInfo::Orange2: t << "type-constraint"; break; - case EdgeInfo::Grey: ASSERT(0); break; - } - } - else // include graph - { - t << "include"; - } - t << "\">" << endl; - if (!edgeInfo->m_label.isEmpty()) - { - int p=0; - int ni; - while ((ni=edgeInfo->m_label.find('\n',p))!=-1) - { - t << " <edgelabel>" - << convertToXML(edgeInfo->m_label.mid(p,ni-p)) - << "</edgelabel>" << endl; - p=ni+1; - } - t << " <edgelabel>" - << convertToXML(edgeInfo->m_label.right(edgeInfo->m_label.length()-p)) - << "</edgelabel>" << endl; - } - t << " </childnode>" << endl; - } - } - t << " </node>" << endl; -} - - -void DotNode::writeDEF(FTextStream &t) -{ - const char* nodePrefix = " node-"; - - t << " node = {" << endl; - t << nodePrefix << "id = " << m_number << ';' << endl; - t << nodePrefix << "label = '" << m_label << "';" << endl; - - if (!m_url.isEmpty()) - { - QCString url(m_url); - const char *refPtr = url.data(); - char *urlPtr = strchr(url.rawData(),'$'); - if (urlPtr) - { - *urlPtr++='\0'; - t << nodePrefix << "link = {" << endl << " " - << nodePrefix << "link-id = '" << urlPtr << "';" << endl; - - if (*refPtr!='\0') - { - t << " " << nodePrefix << "link-external = '" - << refPtr << "';" << endl; - } - t << " };" << endl; - } - } - if (m_children) - { - QListIterator<DotNode> nli(*m_children); - QListIterator<EdgeInfo> eli(*m_edgeInfo); - DotNode *childNode; - EdgeInfo *edgeInfo; - for (;(childNode=nli.current());++nli,++eli) - { - edgeInfo=eli.current(); - t << " node-child = {" << endl; - t << " child-id = '" << childNode->m_number << "';" << endl; - t << " relation = "; - - switch(edgeInfo->m_color) - { - case EdgeInfo::Blue: t << "public-inheritance"; break; - case EdgeInfo::Green: t << "protected-inheritance"; break; - case EdgeInfo::Red: t << "private-inheritance"; break; - case EdgeInfo::Purple: t << "usage"; break; - case EdgeInfo::Orange: t << "template-instance"; break; - case EdgeInfo::Orange2: t << "type-constraint"; break; - case EdgeInfo::Grey: ASSERT(0); break; - } - t << ';' << endl; - - if (!edgeInfo->m_label.isEmpty()) - { - t << " edgelabel = <<_EnD_oF_dEf_TeXt_" << endl - << edgeInfo->m_label << endl - << "_EnD_oF_dEf_TeXt_;" << endl; - } - t << " }; /* node-child */" << endl; - } /* for (;childNode...) */ - } - t << " }; /* node */" << endl; -} - - -void DotNode::clearWriteFlag() -{ - m_written=FALSE; - if (m_parents!=0) - { - QListIterator<DotNode> dnlip(*m_parents); - DotNode *pn; - for (dnlip.toFirst();(pn=dnlip.current());++dnlip) - { - if (pn->m_written) - { - pn->clearWriteFlag(); - } - } - } - if (m_children!=0) - { - QListIterator<DotNode> dnlic(*m_children); - DotNode *cn; - for (dnlic.toFirst();(cn=dnlic.current());++dnlic) - { - if (cn->m_written) - { - cn->clearWriteFlag(); - } - } - } -} - -void DotNode::colorConnectedNodes(int curColor) -{ - if (m_children) - { - QListIterator<DotNode> dnlic(*m_children); - DotNode *cn; - for (dnlic.toFirst();(cn=dnlic.current());++dnlic) - { - if (cn->m_subgraphId==-1) // uncolored child node - { - cn->m_subgraphId=curColor; - cn->markAsVisible(); - cn->colorConnectedNodes(curColor); - //printf("coloring node %s (%p): %d\n",cn->m_label.data(),cn,cn->m_subgraphId); - } - } - } - - if (m_parents) - { - QListIterator<DotNode> dnlip(*m_parents); - DotNode *pn; - for (dnlip.toFirst();(pn=dnlip.current());++dnlip) - { - if (pn->m_subgraphId==-1) // uncolored parent node - { - pn->m_subgraphId=curColor; - pn->markAsVisible(); - pn->colorConnectedNodes(curColor); - //printf("coloring node %s (%p): %d\n",pn->m_label.data(),pn,pn->m_subgraphId); - } - } - } -} - -void DotNode::renumberNodes(int &number) -{ - m_number = number++; - if (m_children) - { - QListIterator<DotNode> dnlic(*m_children); - DotNode *cn; - for (dnlic.toFirst();(cn=dnlic.current());++dnlic) - { - if (!cn->m_renumbered) - { - cn->m_renumbered = true; - cn->renumberNodes(number); - } - } - } -} - -const DotNode *DotNode::findDocNode() const -{ - if (!m_url.isEmpty()) return this; - //printf("findDocNode(): `%s'\n",m_label.data()); - if (m_parents) - { - QListIterator<DotNode> dnli(*m_parents); - DotNode *pn; - for (dnli.toFirst();(pn=dnli.current());++dnli) - { - if (!pn->m_hasDoc) - { - pn->m_hasDoc=TRUE; - const DotNode *dn = pn->findDocNode(); - if (dn) return dn; - } - } - } - if (m_children) - { - QListIterator<DotNode> dnli(*m_children); - DotNode *cn; - for (dnli.toFirst();(cn=dnli.current());++dnli) - { - if (!cn->m_hasDoc) - { - cn->m_hasDoc=TRUE; - const DotNode *dn = cn->findDocNode(); - if (dn) return dn; - } - } - } - return 0; -} - -//-------------------------------------------------------------------- - -void DotGfxHierarchyTable::createGraph(DotNode *n,FTextStream &out, - const char *path,const char *fileName,int id) const -{ - QDir d(path); - QCString baseName; - QCString imgExt = getDotImageExtension(); - QCString imgFmt = Config_getEnum(DOT_IMAGE_FORMAT); - if (m_prefix.isEmpty()) - baseName.sprintf("inherit_graph_%d",id); - else - baseName.sprintf("%sinherit_graph_%d",m_prefix.data(),id); - QCString imgName = baseName+"."+ imgExt; - QCString mapName = baseName+".map"; - QCString absImgName = QCString(d.absPath().data())+"/"+imgName; - QCString absMapName = QCString(d.absPath().data())+"/"+mapName; - QCString absBaseName = QCString(d.absPath().data())+"/"+baseName; - QListIterator<DotNode> dnli2(*m_rootNodes); - DotNode *node; - - // compute md5 checksum of the graph were are about to generate - QGString theGraph; - FTextStream md5stream(&theGraph); - writeGraphHeader(md5stream,theTranslator->trGraphicalHierarchy()); - md5stream << " rankdir=\"LR\";" << endl; - for (dnli2.toFirst();(node=dnli2.current());++dnli2) - { - if (node->m_subgraphId==n->m_subgraphId) - { - node->clearWriteFlag(); - } - } - for (dnli2.toFirst();(node=dnli2.current());++dnli2) - { - if (node->m_subgraphId==n->m_subgraphId) - { - node->write(md5stream,DotNode::Hierarchy,GOF_BITMAP,FALSE,TRUE,TRUE); - } - } - writeGraphFooter(md5stream); - uchar md5_sig[16]; - QCString sigStr(33); - MD5Buffer((const unsigned char *)theGraph.data(),theGraph.length(),md5_sig); - MD5SigToString(md5_sig,sigStr.rawData(),33); - bool regenerate=FALSE; - if (checkAndUpdateMd5Signature(absBaseName,sigStr) || - !checkDeliverables(absImgName,absMapName)) - { - regenerate=TRUE; - // image was new or has changed - QCString dotName=absBaseName+".dot"; - QFile f(dotName); - if (!f.open(IO_WriteOnly)) return; - FTextStream t(&f); - t << theGraph; - f.close(); - - DotRunner *dotRun = new DotRunner(dotName,d.absPath().data(),TRUE,absImgName); - dotRun->addJob(imgFmt,absImgName); - dotRun->addJob(MAP_CMD,absMapName); - DotManager::instance()->addRun(dotRun); - } - else - { - removeDotGraph(absBaseName+".dot"); - } - Doxygen::indexList->addImageFile(imgName); - // write image and map in a table row - QCString mapLabel = escapeCharsInString(n->m_label,FALSE); - if (imgExt=="svg") // vector graphics - { - if (regenerate || !writeSVGFigureLink(out,QCString(),baseName,absImgName)) - { - if (regenerate) - { - DotManager::instance()->addSVGConversion(absImgName,QCString(), - FALSE,QCString(),FALSE,0); - } - int mapId = DotManager::instance()->addSVGObject(fileName,baseName, - absImgName,QCString()); - out << "<!-- SVG " << mapId << " -->" << endl; - } - } - else // normal bitmap - { - out << "<img src=\"" << imgName << "\" border=\"0\" alt=\"\" usemap=\"#" - << mapLabel << "\"/>" << endl; - - if (regenerate || !insertMapFile(out,absMapName,QCString(),mapLabel)) - { - int mapId = DotManager::instance()->addMap(fileName,absMapName,QCString(), - FALSE,QCString(),mapLabel); - out << "<!-- MAP " << mapId << " -->" << endl; - } - } -} - -void DotGfxHierarchyTable::writeGraph(FTextStream &out, - const char *path,const char *fileName) const -{ - //printf("DotGfxHierarchyTable::writeGraph(%s)\n",name); - //printf("m_rootNodes=%p count=%d\n",m_rootNodes,m_rootNodes->count()); - - if (m_rootSubgraphs->count()==0) return; - - QDir d(path); - // store the original directory - if (!d.exists()) - { - err("Output dir %s does not exist!\n",path); exit(1); - } - - // put each connected subgraph of the hierarchy in a row of the HTML output - out << "<table border=\"0\" cellspacing=\"10\" cellpadding=\"0\">" << endl; - - QListIterator<DotNode> dnli(*m_rootSubgraphs); - DotNode *n; - int count=0; - for (dnli.toFirst();(n=dnli.current());++dnli) - { - out << "<tr><td>"; - createGraph(n,out,path,fileName,count++); - out << "</td></tr>" << endl; - } - out << "</table>" << endl; -} - -void DotGfxHierarchyTable::addHierarchy(DotNode *n,ClassDef *cd,bool hideSuper) -{ - //printf("addHierarchy `%s' baseClasses=%d\n",cd->name().data(),cd->baseClasses()->count()); - if (cd->subClasses()) - { - BaseClassListIterator bcli(*cd->subClasses()); - BaseClassDef *bcd; - for ( ; (bcd=bcli.current()) ; ++bcli ) - { - ClassDef *bClass=bcd->classDef; - //printf(" Trying sub class=`%s' usedNodes=%d\n",bClass->name().data(),m_usedNodes->count()); - if (bClass->isVisibleInHierarchy() && hasVisibleRoot(bClass->baseClasses())) - { - DotNode *bn; - //printf(" Node `%s' Found visible class=`%s'\n",n->m_label.data(), - // bClass->name().data()); - if ((bn=m_usedNodes->find(bClass->name()))) // node already present - { - if (n->m_children==0 || n->m_children->findRef(bn)==-1) // no arrow yet - { - n->addChild(bn,bcd->prot); - bn->addParent(n); - //printf(" Adding node %s to existing base node %s (c=%d,p=%d)\n", - // n->m_label.data(), - // bn->m_label.data(), - // bn->m_children ? bn->m_children->count() : 0, - // bn->m_parents ? bn->m_parents->count() : 0 - // ); - } - //else - //{ - // printf(" Class already has an arrow!\n"); - //} - } - else - { - QCString tmp_url=""; - if (bClass->isLinkable() && !bClass->isHidden()) - { - tmp_url=bClass->getReference()+"$"+bClass->getOutputFileBase(); - if (!bClass->anchor().isEmpty()) - { - tmp_url+="#"+bClass->anchor(); - } - } - QCString tooltip = bClass->briefDescriptionAsTooltip(); - bn = new DotNode(m_curNodeNumber++, - bClass->displayName(), - tooltip, - tmp_url.data() - ); - n->addChild(bn,bcd->prot); - bn->addParent(n); - //printf(" Adding node %s to new base node %s (c=%d,p=%d)\n", - // n->m_label.data(), - // bn->m_label.data(), - // bn->m_children ? bn->m_children->count() : 0, - // bn->m_parents ? bn->m_parents->count() : 0 - // ); - //printf(" inserting %s (%p)\n",bClass->name().data(),bn); - m_usedNodes->insert(bClass->name(),bn); // add node to the used list - } - if (!bClass->isVisited() && !hideSuper && bClass->subClasses()) - { - bool wasVisited=bClass->isVisited(); - bClass->setVisited(TRUE); - addHierarchy(bn,bClass,wasVisited); - } - } - } - } - //printf("end addHierarchy\n"); -} - -void DotGfxHierarchyTable::addClassList(ClassSDict *cl) -{ - static bool sliceOpt = Config_getBool(OPTIMIZE_OUTPUT_SLICE); - ClassSDict::Iterator cli(*cl); - ClassDef *cd; - for (cli.toLast();(cd=cli.current());--cli) - { - //printf("Trying %s subClasses=%d\n",cd->name().data(),cd->subClasses()->count()); - if (cd->getLanguage()==SrcLangExt_VHDL && - (VhdlDocGen::VhdlClasses)cd->protection()!=VhdlDocGen::ENTITYCLASS - ) - { - continue; - } - if (sliceOpt && cd->compoundType() != m_classType) - { - continue; - } - if (!hasVisibleRoot(cd->baseClasses()) && - cd->isVisibleInHierarchy() - ) // root node in the forest - { - QCString tmp_url=""; - if (cd->isLinkable() && !cd->isHidden()) - { - tmp_url=cd->getReference()+"$"+cd->getOutputFileBase(); - if (!cd->anchor().isEmpty()) - { - tmp_url+="#"+cd->anchor(); - } - } - //printf("Inserting root class %s\n",cd->name().data()); - QCString tooltip = cd->briefDescriptionAsTooltip(); - DotNode *n = new DotNode(m_curNodeNumber++, - cd->displayName(), - tooltip, - tmp_url.data()); - - //m_usedNodes->clear(); - m_usedNodes->insert(cd->name(),n); - m_rootNodes->insert(0,n); - if (!cd->isVisited() && cd->subClasses()) - { - addHierarchy(n,cd,cd->isVisited()); - cd->setVisited(TRUE); - } - } - } -} - -DotGfxHierarchyTable::DotGfxHierarchyTable(const char *prefix,ClassDef::CompoundType ct) - : m_prefix(prefix) - , m_classType(ct) - , m_curNodeNumber(1) -{ - m_rootNodes = new QList<DotNode>; - m_usedNodes = new QDict<DotNode>(1009); - m_usedNodes->setAutoDelete(TRUE); - m_rootSubgraphs = new DotNodeList; - - // build a graph with each class as a node and the inheritance relations - // as edges - initClassHierarchy(Doxygen::classSDict); - initClassHierarchy(Doxygen::hiddenClasses); - addClassList(Doxygen::classSDict); - addClassList(Doxygen::hiddenClasses); - // m_usedNodes now contains all nodes in the graph - - // color the graph into a set of independent subgraphs - bool done=FALSE; - int curColor=0; - QListIterator<DotNode> dnli(*m_rootNodes); - while (!done) // there are still nodes to color - { - DotNode *n; - done=TRUE; // we are done unless there are still uncolored nodes - for (dnli.toLast();(n=dnli.current());--dnli) - { - if (n->m_subgraphId==-1) // not yet colored - { - //printf("Starting at node %s (%p): %d\n",n->m_label.data(),n,curColor); - done=FALSE; // still uncolored nodes - n->m_subgraphId=curColor; - n->markAsVisible(); - n->colorConnectedNodes(curColor); - curColor++; - const DotNode *dn=n->findDocNode(); - if (dn!=0) - m_rootSubgraphs->inSort(dn); - else - m_rootSubgraphs->inSort(n); - } - } - } - - //printf("Number of independent subgraphs: %d\n",curColor); - QListIterator<DotNode> dnli2(*m_rootSubgraphs); - DotNode *n; - for (dnli2.toFirst();(n=dnli2.current());++dnli2) - { - //printf("Node %s color=%d (c=%d,p=%d)\n", - // n->m_label.data(),n->m_subgraphId, - // n->m_children?n->m_children->count():0, - // n->m_parents?n->m_parents->count():0); - int number=0; - n->renumberNodes(number); - } -} - -DotGfxHierarchyTable::~DotGfxHierarchyTable() -{ - //printf("DotGfxHierarchyTable::~DotGfxHierarchyTable\n"); - - //QDictIterator<DotNode> di(*m_usedNodes); - //DotNode *n; - //for (;(n=di.current());++di) - //{ - // printf("Node %p: %s\n",n,n->label().data()); - //} - - delete m_rootNodes; - delete m_usedNodes; - delete m_rootSubgraphs; -} - -//-------------------------------------------------------------------- - -void DotClassGraph::addClass(ClassDef *cd,DotNode *n,int prot, - const char *label,const char *usedName,const char *templSpec,bool base,int distance) -{ - if (Config_getBool(HIDE_UNDOC_CLASSES) && !cd->isLinkable()) return; - - int edgeStyle = (label || prot==EdgeInfo::Orange || prot==EdgeInfo::Orange2) ? EdgeInfo::Dashed : EdgeInfo::Solid; - QCString className; - if (cd->isAnonymous()) - { - className="anonymous:"; - className+=label; - } - else if (usedName) // name is a typedef - { - className=usedName; - } - else if (templSpec) // name has a template part - { - className=insertTemplateSpecifierInScope(cd->name(),templSpec); - } - else // just a normal name - { - className=cd->displayName(); - } - //printf("DotClassGraph::addClass(class=`%s',parent=%s,prot=%d,label=%s,dist=%d,usedName=%s,templSpec=%s,base=%d)\n", - // className.data(),n->m_label.data(),prot,label,distance,usedName,templSpec,base); - DotNode *bn = m_usedNodes->find(className); - if (bn) // class already inserted - { - if (base) - { - n->addChild(bn,prot,edgeStyle,label); - bn->addParent(n); - } - else - { - bn->addChild(n,prot,edgeStyle,label); - n->addParent(bn); - } - bn->setDistance(distance); - //printf(" add exiting node %s of %s\n",bn->m_label.data(),n->m_label.data()); - } - else // new class - { - QCString displayName=className; - if (Config_getBool(HIDE_SCOPE_NAMES)) displayName=stripScope(displayName); - QCString tmp_url; - if (cd->isLinkable() && !cd->isHidden()) - { - tmp_url=cd->getReference()+"$"+cd->getOutputFileBase(); - if (!cd->anchor().isEmpty()) - { - tmp_url+="#"+cd->anchor(); - } - } - QCString tooltip = cd->briefDescriptionAsTooltip(); - bn = new DotNode(m_curNodeNumber++, - displayName, - tooltip, - tmp_url.data(), - FALSE, // rootNode - cd - ); - if (base) - { - n->addChild(bn,prot,edgeStyle,label); - bn->addParent(n); - } - else - { - bn->addChild(n,prot,edgeStyle,label); - n->addParent(bn); - } - bn->setDistance(distance); - m_usedNodes->insert(className,bn); - //printf(" add new child node `%s' to %s hidden=%d url=%s\n", - // className.data(),n->m_label.data(),cd->isHidden(),tmp_url.data()); - - buildGraph(cd,bn,base,distance+1); - } -} - -void DotClassGraph::determineTruncatedNodes(QList<DotNode> &queue,bool includeParents) -{ - while (queue.count()>0) - { - DotNode *n = queue.take(0); - if (n->isVisible() && n->isTruncated()==DotNode::Unknown) - { - bool truncated = FALSE; - if (n->m_children) - { - QListIterator<DotNode> li(*n->m_children); - DotNode *dn; - for (li.toFirst();(dn=li.current());++li) - { - if (!dn->isVisible()) - truncated = TRUE; - else - queue.append(dn); - } - } - if (n->m_parents && includeParents) - { - QListIterator<DotNode> li(*n->m_parents); - DotNode *dn; - for (li.toFirst();(dn=li.current());++li) - { - if (!dn->isVisible()) - truncated = TRUE; - else - queue.append(dn); - } - } - n->markAsTruncated(truncated); - } - } -} - -bool DotClassGraph::determineVisibleNodes(DotNode *rootNode, - int maxNodes,bool includeParents) +class GraphLegendDotGraph : public DotGraph { - QList<DotNode> childQueue; - QList<DotNode> parentQueue; - QArray<int> childTreeWidth; - QArray<int> parentTreeWidth; - childQueue.append(rootNode); - if (includeParents) parentQueue.append(rootNode); - bool firstNode=TRUE; // flag to force reprocessing rootNode in the parent loop - // despite being marked visible in the child loop - while ((childQueue.count()>0 || parentQueue.count()>0) && maxNodes>0) - { - static int maxDistance = Config_getInt(MAX_DOT_GRAPH_DEPTH); - if (childQueue.count()>0) - { - DotNode *n = childQueue.take(0); - int distance = n->distance(); - if (!n->isVisible() && distance<=maxDistance) // not yet processed - { - if (distance>0) - { - int oldSize=(int)childTreeWidth.size(); - if (distance>oldSize) - { - childTreeWidth.resize(QMAX(childTreeWidth.size(),(uint)distance)); - int i; for (i=oldSize;i<distance;i++) childTreeWidth[i]=0; - } - childTreeWidth[distance-1]+=n->label().length(); - } - n->markAsVisible(); - maxNodes--; - // add direct children - if (n->m_children) - { - QListIterator<DotNode> li(*n->m_children); - DotNode *dn; - for (li.toFirst();(dn=li.current());++li) - { - childQueue.append(dn); - } - } - } - } - if (includeParents && parentQueue.count()>0) - { - DotNode *n = parentQueue.take(0); - if ((!n->isVisible() || firstNode) && n->distance()<=maxDistance) // not yet processed - { - firstNode=FALSE; - int distance = n->distance(); - if (distance>0) - { - int oldSize = (int)parentTreeWidth.size(); - if (distance>oldSize) - { - parentTreeWidth.resize(QMAX(parentTreeWidth.size(),(uint)distance)); - int i; for (i=oldSize;i<distance;i++) parentTreeWidth[i]=0; - } - parentTreeWidth[distance-1]+=n->label().length(); - } - n->markAsVisible(); - maxNodes--; - // add direct parents - if (n->m_parents) - { - QListIterator<DotNode> li(*n->m_parents); - DotNode *dn; - for (li.toFirst();(dn=li.current());++li) - { - parentQueue.append(dn); - } - } - } - } - } - if (Config_getBool(UML_LOOK)) return FALSE; // UML graph are always top to bottom - int maxWidth=0; - int maxHeight=(int)QMAX(childTreeWidth.size(),parentTreeWidth.size()); - uint i; - for (i=0;i<childTreeWidth.size();i++) - { - if (childTreeWidth.at(i)>maxWidth) maxWidth=childTreeWidth.at(i); - } - for (i=0;i<parentTreeWidth.size();i++) - { - if (parentTreeWidth.at(i)>maxWidth) maxWidth=parentTreeWidth.at(i); - } - //printf("max tree width=%d, max tree height=%d\n",maxWidth,maxHeight); - return maxWidth>80 && maxHeight<12; // used metric to decide to render the tree - // from left to right instead of top to bottom, - // with the idea to render very wide trees in - // left to right order. -} - -void DotClassGraph::buildGraph(ClassDef *cd,DotNode *n,bool base,int distance) -{ - static bool templateRelations = Config_getBool(TEMPLATE_RELATIONS); - //printf("DocClassGraph::buildGraph(%s,distance=%d,base=%d)\n", - // cd->name().data(),distance,base); - // ---- Add inheritance relations - - if (m_graphType == DotNode::Inheritance || m_graphType==DotNode::Collaboration) - { - BaseClassList *bcl = base ? cd->baseClasses() : cd->subClasses(); - if (bcl) - { - BaseClassListIterator bcli(*bcl); - BaseClassDef *bcd; - for ( ; (bcd=bcli.current()) ; ++bcli ) - { - //printf("-------- inheritance relation %s->%s templ=`%s'\n", - // cd->name().data(),bcd->classDef->name().data(),bcd->templSpecifiers.data()); - addClass(bcd->classDef,n,bcd->prot,0,bcd->usedName, - bcd->templSpecifiers,base,distance); - } - } - } - if (m_graphType == DotNode::Collaboration) - { - // ---- Add usage relations - - UsesClassDict *dict = - base ? cd->usedImplementationClasses() : - cd->usedByImplementationClasses() - ; - if (dict) - { - UsesClassDictIterator ucdi(*dict); - UsesClassDef *ucd; - for (;(ucd=ucdi.current());++ucdi) - { - QCString label; - QDictIterator<void> dvi(*ucd->accessors); - const char *s; - bool first=TRUE; - int count=0; - int maxLabels=10; - for (;(s=dvi.currentKey()) && count<maxLabels;++dvi,++count) - { - if (first) - { - label=s; - first=FALSE; - } - else - { - label+=QCString("\n")+s; - } - } - if (count==maxLabels) label+="\n..."; - //printf("addClass: %s templSpec=%s\n",ucd->classDef->name().data(),ucd->templSpecifiers.data()); - addClass(ucd->classDef,n,EdgeInfo::Purple,label,0, - ucd->templSpecifiers,base,distance); - } - } - } - if (templateRelations && base) - { - ConstraintClassDict *dict = cd->templateTypeConstraints(); - if (dict) - { - ConstraintClassDictIterator ccdi(*dict); - ConstraintClassDef *ccd; - for (;(ccd=ccdi.current());++ccdi) - { - QCString label; - QDictIterator<void> dvi(*ccd->accessors); - const char *s; - bool first=TRUE; - int count=0; - int maxLabels=10; - for (;(s=dvi.currentKey()) && count<maxLabels;++dvi,++count) - { - if (first) - { - label=s; - first=FALSE; - } - else - { - label+=QCString("\n")+s; - } - } - if (count==maxLabels) label+="\n..."; - //printf("addClass: %s templSpec=%s\n",ucd->classDef->name().data(),ucd->templSpecifiers.data()); - addClass(ccd->classDef,n,EdgeInfo::Orange2,label,0, - 0,TRUE,distance); - } - } - } - - // ---- Add template instantiation relations - - if (templateRelations) - { - if (base) // template relations for base classes - { - ClassDef *templMaster=cd->templateMaster(); - if (templMaster) - { - QDictIterator<ClassDef> cli(*templMaster->getTemplateInstances()); - ClassDef *templInstance; - for (;(templInstance=cli.current());++cli) - { - if (templInstance==cd) - { - addClass(templMaster,n,EdgeInfo::Orange,cli.currentKey(),0, - 0,TRUE,distance); - } - } - } - } - else // template relations for super classes + private: + virtual QCString getBaseName() const { - QDict<ClassDef> *templInstances = cd->getTemplateInstances(); - if (templInstances) - { - QDictIterator<ClassDef> cli(*templInstances); - ClassDef *templInstance; - for (;(templInstance=cli.current());++cli) - { - addClass(templInstance,n,EdgeInfo::Orange,cli.currentKey(),0, - 0,FALSE,distance); - } - } + return "graph_legend"; } - } -} - -int DotClassGraph::m_curNodeNumber = 0; -void DotClassGraph::resetNumbering() -{ - m_curNodeNumber = 0; -} - -DotClassGraph::DotClassGraph(ClassDef *cd,DotNode::GraphType t) -{ - //printf("--------------- DotClassGraph::DotClassGraph `%s'\n",cd->displayName().data()); - m_graphType = t; - QCString tmp_url=""; - if (cd->isLinkable() && !cd->isHidden()) - { - tmp_url=cd->getReference()+"$"+cd->getOutputFileBase(); - if (!cd->anchor().isEmpty()) + virtual void computeTheGraph() { - tmp_url+="#"+cd->anchor(); + FTextStream md5stream(&m_theGraph); + writeGraphHeader(md5stream,theTranslator->trLegendTitle()); + md5stream << " Node9 [shape=\"box\",label=\"Inherited\",fontsize=\"" << DOT_FONTSIZE << "\",height=0.2,width=0.4,fontname=\"" << DOT_FONTNAME << "\",fillcolor=\"grey75\",style=\"filled\" fontcolor=\"black\"];\n"; + md5stream << " Node10 -> Node9 [dir=\"back\",color=\"midnightblue\",fontsize=\"" << DOT_FONTSIZE << "\",style=\"solid\",fontname=\"" << DOT_FONTNAME << "\"];\n"; + md5stream << " Node10 [shape=\"box\",label=\"PublicBase\",fontsize=\"" << DOT_FONTSIZE << "\",height=0.2,width=0.4,fontname=\"" << DOT_FONTNAME << "\",color=\"black\",URL=\"$classPublicBase" << Doxygen::htmlFileExtension << "\"];\n"; + md5stream << " Node11 -> Node10 [dir=\"back\",color=\"midnightblue\",fontsize=\"" << DOT_FONTSIZE << "\",style=\"solid\",fontname=\"" << DOT_FONTNAME << "\"];\n"; + md5stream << " Node11 [shape=\"box\",label=\"Truncated\",fontsize=\"" << DOT_FONTSIZE << "\",height=0.2,width=0.4,fontname=\"" << DOT_FONTNAME << "\",color=\"red\",URL=\"$classTruncated" << Doxygen::htmlFileExtension << "\"];\n"; + md5stream << " Node13 -> Node9 [dir=\"back\",color=\"darkgreen\",fontsize=\"" << DOT_FONTSIZE << "\",style=\"solid\",fontname=\"" << DOT_FONTNAME << "\"];\n"; + md5stream << " Node13 [shape=\"box\",label=\"ProtectedBase\",fontsize=\"" << DOT_FONTSIZE << "\",height=0.2,width=0.4,fontname=\"" << DOT_FONTNAME << "\",color=\"black\",URL=\"$classProtectedBase" << Doxygen::htmlFileExtension << "\"];\n"; + md5stream << " Node14 -> Node9 [dir=\"back\",color=\"firebrick4\",fontsize=\"" << DOT_FONTSIZE << "\",style=\"solid\",fontname=\"" << DOT_FONTNAME << "\"];\n"; + md5stream << " Node14 [shape=\"box\",label=\"PrivateBase\",fontsize=\"" << DOT_FONTSIZE << "\",height=0.2,width=0.4,fontname=\"" << DOT_FONTNAME << "\",color=\"black\",URL=\"$classPrivateBase" << Doxygen::htmlFileExtension << "\"];\n"; + md5stream << " Node15 -> Node9 [dir=\"back\",color=\"midnightblue\",fontsize=\"" << DOT_FONTSIZE << "\",style=\"solid\",fontname=\"" << DOT_FONTNAME << "\"];\n"; + md5stream << " Node15 [shape=\"box\",label=\"Undocumented\",fontsize=\"" << DOT_FONTSIZE << "\",height=0.2,width=0.4,fontname=\"" << DOT_FONTNAME << "\",color=\"grey75\"];\n"; + md5stream << " Node16 -> Node9 [dir=\"back\",color=\"midnightblue\",fontsize=\"" << DOT_FONTSIZE << "\",style=\"solid\",fontname=\"" << DOT_FONTNAME << "\"];\n"; + md5stream << " Node16 [shape=\"box\",label=\"Templ< int >\",fontsize=\"" << DOT_FONTSIZE << "\",height=0.2,width=0.4,fontname=\"" << DOT_FONTNAME << "\",color=\"black\",URL=\"$classTempl" << Doxygen::htmlFileExtension << "\"];\n"; + md5stream << " Node17 -> Node16 [dir=\"back\",color=\"orange\",fontsize=\"" << DOT_FONTSIZE << "\",style=\"dashed\",label=\"< int >\",fontname=\"" << DOT_FONTNAME << "\"];\n"; + md5stream << " Node17 [shape=\"box\",label=\"Templ< T >\",fontsize=\"" << DOT_FONTSIZE << "\",height=0.2,width=0.4,fontname=\"" << DOT_FONTNAME << "\",color=\"black\",URL=\"$classTempl" << Doxygen::htmlFileExtension << "\"];\n"; + md5stream << " Node18 -> Node9 [dir=\"back\",color=\"darkorchid3\",fontsize=\"" << DOT_FONTSIZE << "\",style=\"dashed\",label=\"m_usedClass\",fontname=\"" << DOT_FONTNAME << "\"];\n"; + md5stream << " Node18 [shape=\"box\",label=\"Used\",fontsize=\"" << DOT_FONTSIZE << "\",height=0.2,width=0.4,fontname=\"" << DOT_FONTNAME << "\",color=\"black\",URL=\"$classUsed" << Doxygen::htmlFileExtension << "\"];\n"; + writeGraphFooter(md5stream); } - } - QCString className = cd->displayName(); - QCString tooltip = cd->briefDescriptionAsTooltip(); - m_startNode = new DotNode(m_curNodeNumber++, - className, - tooltip, - tmp_url.data(), - TRUE, // is a root node - cd - ); - m_startNode->setDistance(0); - m_usedNodes = new QDict<DotNode>(1009); - m_usedNodes->insert(className,m_startNode); - - //printf("Root node %s\n",cd->name().data()); - //if (m_recDepth>0) - //{ - buildGraph(cd,m_startNode,TRUE,1); - if (t==DotNode::Inheritance) buildGraph(cd,m_startNode,FALSE,1); - //} - - static int maxNodes = Config_getInt(DOT_GRAPH_MAX_NODES); - //int directChildNodes = 1; - //if (m_startNode->m_children!=0) - // directChildNodes+=m_startNode->m_children->count(); - //if (t==DotNode::Inheritance && m_startNode->m_parents!=0) - // directChildNodes+=m_startNode->m_parents->count(); - //if (directChildNodes>maxNodes) maxNodes=directChildNodes; - //openNodeQueue.append(m_startNode); - m_lrRank = determineVisibleNodes(m_startNode,maxNodes,t==DotNode::Inheritance); - QList<DotNode> openNodeQueue; - openNodeQueue.append(m_startNode); - determineTruncatedNodes(openNodeQueue,t==DotNode::Inheritance); - - m_collabFileName = cd->collaborationGraphFileName(); - m_inheritFileName = cd->inheritanceGraphFileName(); -} - -bool DotClassGraph::isTrivial() const -{ - static bool umlLook = Config_getBool(UML_LOOK); - if (m_graphType==DotNode::Inheritance) - return m_startNode->m_children==0 && m_startNode->m_parents==0; - else - return !umlLook && m_startNode->m_children==0; -} - -bool DotClassGraph::isTooBig() const -{ - static int maxNodes = Config_getInt(DOT_GRAPH_MAX_NODES); - int numNodes = 0; - numNodes+= m_startNode->m_children ? m_startNode->m_children->count() : 0; - if (m_graphType==DotNode::Inheritance) - { - numNodes+= m_startNode->m_parents ? m_startNode->m_parents->count() : 0; - } - return numNodes>=maxNodes; -} - -DotClassGraph::~DotClassGraph() -{ - deleteNodes(m_startNode); - delete m_usedNodes; -} -/*! Computes a 16 byte md5 checksum for a given dot graph. - * The md5 checksum is returned as a 32 character ASCII string. - */ -QCString computeMd5Signature(DotNode *root, - DotNode::GraphType gt, - GraphOutputFormat format, - const QCString &rank, // either "LR", "RL", or "" - bool renderParents, - bool backArrows, - const QCString &title, - QCString &graphStr - ) -{ - //printf("computeMd5Signature\n"); - QGString buf; - FTextStream md5stream(&buf); - writeGraphHeader(md5stream,title); - if (!rank.isEmpty()) - { - md5stream << " rankdir=\"" << rank << "\";" << endl; - } - root->clearWriteFlag(); - root->write(md5stream, - gt, - format, - gt!=DotNode::CallGraph && gt!=DotNode::Dependency, - TRUE, - backArrows); - if (renderParents && root->m_parents) - { - QListIterator<DotNode> dnli(*root->m_parents); - DotNode *pn; - for (dnli.toFirst();(pn=dnli.current());++dnli) + virtual QCString getMapLabel() const { - if (pn->isVisible()) - { - root->writeArrow(md5stream, // stream - gt, // graph type - format, // output format - pn, // child node - pn->m_edgeInfo->at(pn->m_children->findRef(root)), // edge info - FALSE, // topDown? - backArrows // point back? - ); - } - pn->write(md5stream, // stream - gt, // graph type - format, // output format - TRUE, // topDown? - FALSE, // toChildren? - backArrows // backward pointing arrows? - ); + return ""; } - } - writeGraphFooter(md5stream); - uchar md5_sig[16]; - QCString sigStr(33); - MD5Buffer((const unsigned char *)buf.data(),buf.length(),md5_sig); - MD5SigToString(md5_sig,sigStr.rawData(),33); - graphStr=buf.data(); - //printf("md5: %s | file: %s\n",sigStr,baseName.data()); - return sigStr; -} -static bool updateDotGraph(DotNode *root, - DotNode::GraphType gt, - const QCString &baseName, - GraphOutputFormat format, - const QCString &rank, - bool renderParents, - bool backArrows, - const QCString &title=QCString() - ) -{ - QCString theGraph; - // TODO: write graph to theGraph, then compute md5 checksum - QCString md5 = computeMd5Signature( - root,gt,format,rank,renderParents, - backArrows,title,theGraph); - QFile f(baseName+".dot"); - if (f.open(IO_WriteOnly)) - { - FTextStream t(&f); - t << theGraph; - } - return checkAndUpdateMd5Signature(baseName,md5); // graph needs to be regenerated -} - -QCString DotClassGraph::writeGraph(FTextStream &out, - GraphOutputFormat graphFormat, - EmbeddedOutputFormat textFormat, - const char *path, - const char *fileName, - const char *relPath, - bool /*isTBRank*/, - bool generateImageMap, - int graphId) const -{ - QDir d(path); - // store the original directory - if (!d.exists()) - { - err("Output dir %s does not exist!\n",path); exit(1); - } - static bool usePDFLatex = Config_getBool(USE_PDFLATEX); - - QCString baseName; - QCString mapName; - switch (m_graphType) - { - case DotNode::Collaboration: - mapName="coll_map"; - baseName=m_collabFileName; - break; - case DotNode::Inheritance: - mapName="inherit_map"; - baseName=m_inheritFileName; - break; - default: - ASSERT(0); - break; - } - - // derive target file names from baseName - QCString imgExt = getDotImageExtension(); - QCString imgFmt = Config_getEnum(DOT_IMAGE_FORMAT); - QCString absBaseName = d.absPath().utf8()+"/"+baseName; - QCString absDotName = absBaseName+".dot"; - QCString absMapName = absBaseName+".map"; - QCString absPdfName = absBaseName+".pdf"; - QCString absEpsName = absBaseName+".eps"; - QCString absImgName = absBaseName+"."+imgExt; - - bool regenerate = FALSE; - if (updateDotGraph(m_startNode, - m_graphType, - absBaseName, - graphFormat, - m_lrRank ? "LR" : "", - m_graphType==DotNode::Inheritance, - TRUE, - m_startNode->label() - ) || - !checkDeliverables(graphFormat==GOF_BITMAP ? absImgName : - usePDFLatex ? absPdfName : absEpsName, - graphFormat==GOF_BITMAP && generateImageMap ? absMapName : QCString()) - ) - { - regenerate=TRUE; - if (graphFormat==GOF_BITMAP) // run dot to create a bitmap image - { - DotRunner *dotRun = new DotRunner(absDotName, - d.absPath().data(),TRUE,absImgName); - dotRun->addJob(imgFmt,absImgName); - if (generateImageMap) dotRun->addJob(MAP_CMD,absMapName); - DotManager::instance()->addRun(dotRun); - - } - else if (graphFormat==GOF_EPS) // run dot to create a .eps image - { - DotRunner *dotRun = new DotRunner(absDotName,d.absPath().data(),FALSE); - if (usePDFLatex) - { - dotRun->addJob("pdf",absPdfName,absBaseName); - } - else - { - dotRun->addJob("ps",absEpsName); - } - DotManager::instance()->addRun(dotRun); - } - } - Doxygen::indexList->addImageFile(baseName+"."+imgExt); - - if (graphFormat==GOF_BITMAP && textFormat==EOF_DocBook) - { - out << "<para>" << endl; - out << " <informalfigure>" << endl; - out << " <mediaobject>" << endl; - out << " <imageobject>" << endl; - out << " <imagedata"; - out << " width=\"50%\" align=\"center\" valign=\"middle\" scalefit=\"0\" fileref=\"" << relPath << baseName << "." << imgExt << "\">"; - out << "</imagedata>" << endl; - out << " </imageobject>" << endl; - out << " </mediaobject>" << endl; - out << " </informalfigure>" << endl; - out << "</para>" << endl; - } - else if (graphFormat==GOF_BITMAP && generateImageMap) // produce HTML to include the image - { - QCString mapLabel = escapeCharsInString(m_startNode->m_label,FALSE)+"_"+ - escapeCharsInString(mapName,FALSE); - if (imgExt=="svg") // add link to SVG file without map file - { - out << "<div class=\"center\">"; - if (regenerate || !writeSVGFigureLink(out,relPath,baseName,absImgName)) // need to patch the links in the generated SVG file - { - if (regenerate) - { - DotManager::instance()->addSVGConversion(absImgName,relPath,FALSE,QCString(),TRUE,graphId); - } - int mapId = DotManager::instance()->addSVGObject(fileName,baseName,absImgName,relPath); - out << "<!-- SVG " << mapId << " -->" << endl; - } - out << "</div>" << endl; - } - else // add link to bitmap file with image map - { - out << "<div class=\"center\">"; - out << "<img src=\"" << relPath << baseName << "." - << imgExt << "\" border=\"0\" usemap=\"#" - << mapLabel << "\" alt=\""; - switch (m_graphType) - { - case DotNode::Collaboration: - out << "Collaboration graph"; - break; - case DotNode::Inheritance: - out << "Inheritance graph"; - break; - default: - ASSERT(0); - break; - } - out << "\"/>"; - out << "</div>" << endl; - if (regenerate || !insertMapFile(out,absMapName,relPath,mapLabel)) - { - int mapId = DotManager::instance()->addMap(fileName,absMapName,relPath, - FALSE,QCString(),mapLabel); - out << "<!-- MAP " << mapId << " -->" << endl; - } - } - } - else if (graphFormat==GOF_EPS) // produce tex to include the .eps image - { - if (regenerate || !writeVecGfxFigure(out,baseName,absBaseName)) - { - int figId = DotManager::instance()->addFigure(fileName,baseName,absBaseName,FALSE /*TRUE*/); - out << endl << "% FIG " << figId << endl; - } - } - if (!regenerate) removeDotGraph(absDotName); - - return baseName; -} - -//-------------------------------------------------------------------- - -void DotClassGraph::writeXML(FTextStream &t) -{ - QDictIterator<DotNode> dni(*m_usedNodes); - DotNode *node; - for (;(node=dni.current());++dni) - { - node->writeXML(t,TRUE); - } -} - -void DotClassGraph::writeDocbook(FTextStream &t) -{ - QDictIterator<DotNode> dni(*m_usedNodes); - DotNode *node; - for (;(node=dni.current());++dni) - { - node->writeDocbook(t,TRUE); - } -} - -void DotClassGraph::writeDEF(FTextStream &t) -{ - QDictIterator<DotNode> dni(*m_usedNodes); - DotNode *node; - for (;(node=dni.current());++dni) - { - node->writeDEF(t); - } -} - -//-------------------------------------------------------------------- - -void DotInclDepGraph::buildGraph(DotNode *n,FileDef *fd,int distance) -{ - QList<IncludeInfo> *includeFiles = - m_inverse ? fd->includedByFileList() : fd->includeFileList(); - if (includeFiles) - { - QListIterator<IncludeInfo> ili(*includeFiles); - IncludeInfo *ii; - for (;(ii=ili.current());++ili) - { - FileDef *bfd = ii->fileDef; - QCString in = ii->includeName; - //printf(">>>> in=`%s' bfd=%p\n",ii->includeName.data(),bfd); - bool doc=TRUE,src=FALSE; - if (bfd) - { - in = bfd->absFilePath(); - doc = bfd->isLinkable() && !bfd->isHidden(); - src = bfd->generateSourceFile(); - } - if (doc || src || !Config_getBool(HIDE_UNDOC_RELATIONS)) - { - QCString url=""; - if (bfd) url=bfd->getOutputFileBase().copy(); - if (!doc && src) - { - url=bfd->getSourceFileBase(); - } - DotNode *bn = m_usedNodes->find(in); - if (bn) // file is already a node in the graph - { - n->addChild(bn,0,0,0); - bn->addParent(n); - bn->setDistance(distance); - } - else - { - QCString tmp_url; - QCString tooltip; - if (bfd) - { - tmp_url=doc || src ? bfd->getReference()+"$"+url : QCString(); - tooltip = bfd->briefDescriptionAsTooltip(); - } - bn = new DotNode( - m_curNodeNumber++, // n - ii->includeName, // label - tooltip, // tip - tmp_url, // url - FALSE, // rootNode - 0 // cd - ); - n->addChild(bn,0,0,0); - bn->addParent(n); - m_usedNodes->insert(in,bn); - bn->setDistance(distance); - - if (bfd) buildGraph(bn,bfd,distance+1); - } - } - } - } -} - -void DotInclDepGraph::determineVisibleNodes(QList<DotNode> &queue, int &maxNodes) -{ - while (queue.count()>0 && maxNodes>0) - { - static int maxDistance = Config_getInt(MAX_DOT_GRAPH_DEPTH); - DotNode *n = queue.take(0); - if (!n->isVisible() && n->distance()<=maxDistance) // not yet processed - { - n->markAsVisible(); - maxNodes--; - // add direct children - if (n->m_children) - { - QListIterator<DotNode> li(*n->m_children); - DotNode *dn; - for (li.toFirst();(dn=li.current());++li) - { - queue.append(dn); - } - } - } - } -} - -void DotInclDepGraph::determineTruncatedNodes(QList<DotNode> &queue) -{ - while (queue.count()>0) - { - DotNode *n = queue.take(0); - if (n->isVisible() && n->isTruncated()==DotNode::Unknown) - { - bool truncated = FALSE; - if (n->m_children) - { - QListIterator<DotNode> li(*n->m_children); - DotNode *dn; - for (li.toFirst();(dn=li.current());++li) - { - if (!dn->isVisible()) - truncated = TRUE; - else - queue.append(dn); - } - } - n->markAsTruncated(truncated); - } - } -} - -int DotInclDepGraph::m_curNodeNumber = 0; - -void DotInclDepGraph::resetNumbering() -{ - m_curNodeNumber = 0; -} - -DotInclDepGraph::DotInclDepGraph(FileDef *fd,bool inverse) -{ - m_inverse = inverse; - ASSERT(fd!=0); - m_inclDepFileName = fd->includeDependencyGraphFileName(); - m_inclByDepFileName = fd->includedByDependencyGraphFileName(); - QCString tmp_url=fd->getReference()+"$"+fd->getOutputFileBase(); - QCString tooltip = fd->briefDescriptionAsTooltip(); - m_startNode = new DotNode(m_curNodeNumber++, - fd->docName(), - tooltip, - tmp_url.data(), - TRUE // root node - ); - m_startNode->setDistance(0); - m_usedNodes = new QDict<DotNode>(1009); - m_usedNodes->insert(fd->absFilePath(),m_startNode); - buildGraph(m_startNode,fd,1); - - static int nodes = Config_getInt(DOT_GRAPH_MAX_NODES); - int maxNodes = nodes; - //int directChildNodes = 1; - //if (m_startNode->m_children!=0) - // directChildNodes+=m_startNode->m_children->count(); - //if (directChildNodes>maxNodes) maxNodes=directChildNodes; - QList<DotNode> openNodeQueue; - openNodeQueue.append(m_startNode); - determineVisibleNodes(openNodeQueue,maxNodes); - openNodeQueue.clear(); - openNodeQueue.append(m_startNode); - determineTruncatedNodes(openNodeQueue); -} - -DotInclDepGraph::~DotInclDepGraph() -{ - deleteNodes(m_startNode); - delete m_usedNodes; -} - -QCString DotInclDepGraph::writeGraph(FTextStream &out, - GraphOutputFormat graphFormat, - EmbeddedOutputFormat textFormat, - const char *path, - const char *fileName, - const char *relPath, - bool generateImageMap, - int graphId - ) const -{ - QDir d(path); - // store the original directory - if (!d.exists()) - { - err("Output dir %s does not exist!\n",path); exit(1); - } - static bool usePDFLatex = Config_getBool(USE_PDFLATEX); - - QCString baseName; - if (m_inverse) - { - baseName=m_inclByDepFileName; - } - else - { - baseName=m_inclDepFileName; - } - QCString mapName=escapeCharsInString(m_startNode->m_label,FALSE); - if (m_inverse) mapName+="dep"; - - QCString imgExt = getDotImageExtension(); - QCString imgFmt = Config_getEnum(DOT_IMAGE_FORMAT); - QCString absBaseName = d.absPath().utf8()+"/"+baseName; - QCString absDotName = absBaseName+".dot"; - QCString absMapName = absBaseName+".map"; - QCString absPdfName = absBaseName+".pdf"; - QCString absEpsName = absBaseName+".eps"; - QCString absImgName = absBaseName+"."+imgExt; - - bool regenerate = FALSE; - if (updateDotGraph(m_startNode, - DotNode::Dependency, - absBaseName, - graphFormat, - "", // lrRank - FALSE, // renderParents - m_inverse, // backArrows - m_startNode->label() - ) || - !checkDeliverables(graphFormat==GOF_BITMAP ? absImgName : - usePDFLatex ? absPdfName : absEpsName, - graphFormat==GOF_BITMAP && generateImageMap ? absMapName : QCString()) - ) - { - regenerate=TRUE; - if (graphFormat==GOF_BITMAP) - { - // run dot to create a bitmap image - DotRunner *dotRun = new DotRunner(absDotName,d.absPath().data(),TRUE,absImgName); - dotRun->addJob(imgFmt,absImgName); - if (generateImageMap) dotRun->addJob(MAP_CMD,absMapName); - DotManager::instance()->addRun(dotRun); - } - else if (graphFormat==GOF_EPS) - { - DotRunner *dotRun = new DotRunner(absDotName,d.absPath().data(),FALSE); - if (usePDFLatex) - { - dotRun->addJob("pdf",absPdfName,absBaseName); - } - else - { - dotRun->addJob("ps",absEpsName); - } - DotManager::instance()->addRun(dotRun); - } - } - Doxygen::indexList->addImageFile(baseName+"."+imgExt); - - if (graphFormat==GOF_BITMAP && textFormat==EOF_DocBook) - { - out << "<para>" << endl; - out << " <informalfigure>" << endl; - out << " <mediaobject>" << endl; - out << " <imageobject>" << endl; - out << " <imagedata"; - out << " width=\"50%\" align=\"center\" valign=\"middle\" scalefit=\"0\" fileref=\"" << relPath << baseName << "." << imgExt << "\">"; - out << "</imagedata>" << endl; - out << " </imageobject>" << endl; - out << " </mediaobject>" << endl; - out << " </informalfigure>" << endl; - out << "</para>" << endl; - } - else if (graphFormat==GOF_BITMAP && generateImageMap) - { - if (imgExt=="svg") // Scalable vector graphics - { - out << "<div class=\"center\">"; - if (regenerate || !writeSVGFigureLink(out,relPath,baseName,absImgName)) // need to patch the links in the generated SVG file - { - if (regenerate) - { - DotManager::instance()->addSVGConversion(absImgName,relPath,FALSE,QCString(),TRUE,graphId); - } - int mapId = DotManager::instance()->addSVGObject(fileName,baseName,absImgName,relPath); - out << "<!-- SVG " << mapId << " -->" << endl; - } - out << "</div>" << endl; - } - else // bitmap graphics - { - out << "<div class=\"center\"><img src=\"" << relPath << baseName << "." << imgExt << "\" border=\"0\" usemap=\"#" << mapName << "\" alt=\"\"/>"; - out << "</div>" << endl; - - QCString absMapName = absBaseName+".map"; - if (regenerate || !insertMapFile(out,absMapName,relPath,mapName)) - { - int mapId = DotManager::instance()->addMap(fileName,absMapName,relPath, - FALSE,QCString(),mapName); - out << "<!-- MAP " << mapId << " -->" << endl; - } - } - } - else if (graphFormat==GOF_EPS) // encapsulated postscript - { - if (regenerate || !writeVecGfxFigure(out,baseName,absBaseName)) - { - int figId = DotManager::instance()->addFigure(fileName,baseName,absBaseName,FALSE); - out << endl << "% FIG " << figId << endl; - } - } - if (!regenerate) removeDotGraph(absDotName); - - return baseName; -} - -bool DotInclDepGraph::isTrivial() const -{ - return m_startNode->m_children==0; -} - -bool DotInclDepGraph::isTooBig() const -{ - static int maxNodes = Config_getInt(DOT_GRAPH_MAX_NODES); - int numNodes = m_startNode->m_children ? m_startNode->m_children->count() : 0; - return numNodes>=maxNodes; -} - -void DotInclDepGraph::writeXML(FTextStream &t) -{ - QDictIterator<DotNode> dni(*m_usedNodes); - DotNode *node; - for (;(node=dni.current());++dni) - { - node->writeXML(t,FALSE); - } -} - -void DotInclDepGraph::writeDocbook(FTextStream &t) -{ - QDictIterator<DotNode> dni(*m_usedNodes); - DotNode *node; - for (;(node=dni.current());++dni) - { - node->writeDocbook(t,FALSE); - } -} - -//------------------------------------------------------------- - -void DotCallGraph::buildGraph(DotNode *n,MemberDef *md,int distance) -{ - MemberSDict *refs = m_inverse ? md->getReferencedByMembers() : md->getReferencesMembers(); - if (refs) - { - MemberSDict::Iterator mri(*refs); - MemberDef *rmd; - for (;(rmd=mri.current());++mri) - { - if (rmd->showInCallGraph()) - { - QCString uniqueId; - uniqueId=rmd->getReference()+"$"+ - rmd->getOutputFileBase()+"#"+rmd->anchor(); - DotNode *bn = m_usedNodes->find(uniqueId); - if (bn) // file is already a node in the graph - { - n->addChild(bn,0,0,0); - bn->addParent(n); - bn->setDistance(distance); - } - else - { - QCString name; - if (Config_getBool(HIDE_SCOPE_NAMES)) - { - name = rmd->getOuterScope()==m_scope ? - rmd->name() : rmd->qualifiedName(); - } - else - { - name = rmd->qualifiedName(); - } - QCString tooltip = rmd->briefDescriptionAsTooltip(); - bn = new DotNode( - m_curNodeNumber++, - linkToText(rmd->getLanguage(),name,FALSE), - tooltip, - uniqueId, - 0 //distance - ); - n->addChild(bn,0,0,0); - bn->addParent(n); - bn->setDistance(distance); - m_usedNodes->insert(uniqueId,bn); - - buildGraph(bn,rmd,distance+1); - } - } - } - } -} - -void DotCallGraph::determineVisibleNodes(QList<DotNode> &queue, int &maxNodes) -{ - while (queue.count()>0 && maxNodes>0) - { - static int maxDistance = Config_getInt(MAX_DOT_GRAPH_DEPTH); - DotNode *n = queue.take(0); - if (!n->isVisible() && n->distance()<=maxDistance) // not yet processed - { - n->markAsVisible(); - maxNodes--; - // add direct children - if (n->m_children) - { - QListIterator<DotNode> li(*n->m_children); - DotNode *dn; - for (li.toFirst();(dn=li.current());++li) - { - queue.append(dn); - } - } - } - } -} - -void DotCallGraph::determineTruncatedNodes(QList<DotNode> &queue) -{ - while (queue.count()>0) - { - DotNode *n = queue.take(0); - if (n->isVisible() && n->isTruncated()==DotNode::Unknown) - { - bool truncated = FALSE; - if (n->m_children) - { - QListIterator<DotNode> li(*n->m_children); - DotNode *dn; - for (li.toFirst();(dn=li.current());++li) - { - if (!dn->isVisible()) - truncated = TRUE; - else - queue.append(dn); - } - } - n->markAsTruncated(truncated); - } - } -} - -int DotCallGraph::m_curNodeNumber = 0; - -void DotCallGraph::resetNumbering() -{ - m_curNodeNumber = 0; -} - -DotCallGraph::DotCallGraph(MemberDef *md,bool inverse) -{ - m_inverse = inverse; - m_diskName = md->getOutputFileBase()+"_"+md->anchor(); - m_scope = md->getOuterScope(); - QCString uniqueId; - uniqueId = md->getReference()+"$"+ - md->getOutputFileBase()+"#"+md->anchor(); - QCString name; - if (Config_getBool(HIDE_SCOPE_NAMES)) - { - name = md->name(); - } - else - { - name = md->qualifiedName(); - } - QCString tooltip = md->briefDescriptionAsTooltip(); - m_startNode = new DotNode(m_curNodeNumber++, - linkToText(md->getLanguage(),name,FALSE), - tooltip, - uniqueId.data(), - TRUE // root node - ); - m_startNode->setDistance(0); - m_usedNodes = new QDict<DotNode>(1009); - m_usedNodes->insert(uniqueId,m_startNode); - buildGraph(m_startNode,md,1); - - static int nodes = Config_getInt(DOT_GRAPH_MAX_NODES); - int maxNodes = nodes; - //int directChildNodes = 1; - //if (m_startNode->m_children!=0) - // directChildNodes+=m_startNode->m_children->count(); - //if (directChildNodes>maxNodes) maxNodes=directChildNodes; - QList<DotNode> openNodeQueue; - openNodeQueue.append(m_startNode); - determineVisibleNodes(openNodeQueue,maxNodes); - openNodeQueue.clear(); - openNodeQueue.append(m_startNode); - determineTruncatedNodes(openNodeQueue); -} - -DotCallGraph::~DotCallGraph() -{ - deleteNodes(m_startNode); - delete m_usedNodes; -} - -QCString DotCallGraph::writeGraph(FTextStream &out, GraphOutputFormat graphFormat, - EmbeddedOutputFormat textFormat, - const char *path,const char *fileName, - const char *relPath,bool generateImageMap,int - graphId) const -{ - QDir d(path); - // store the original directory - if (!d.exists()) - { - err("Output dir %s does not exist!\n",path); exit(1); - } - static bool usePDFLatex = Config_getBool(USE_PDFLATEX); - - QCString baseName = m_diskName + (m_inverse ? "_icgraph" : "_cgraph"); - QCString mapName = baseName; - - QCString imgExt = getDotImageExtension(); - QCString imgFmt = Config_getEnum(DOT_IMAGE_FORMAT); - QCString absBaseName = d.absPath().utf8()+"/"+baseName; - QCString absDotName = absBaseName+".dot"; - QCString absMapName = absBaseName+".map"; - QCString absPdfName = absBaseName+".pdf"; - QCString absEpsName = absBaseName+".eps"; - QCString absImgName = absBaseName+"."+imgExt; - - bool regenerate = FALSE; - - if (updateDotGraph(m_startNode, - DotNode::CallGraph, - absBaseName, - graphFormat, - m_inverse ? "RL" : "LR", // lrRank - FALSE, // renderParents - m_inverse, // backArrows - m_startNode->label() - ) || - !checkDeliverables(graphFormat==GOF_BITMAP ? absImgName : - usePDFLatex ? absPdfName : absEpsName, - graphFormat==GOF_BITMAP && generateImageMap ? absMapName : QCString()) - ) - { - regenerate=TRUE; - if (graphFormat==GOF_BITMAP) - { - // run dot to create a bitmap image - DotRunner *dotRun = new DotRunner(absDotName,d.absPath().data(),TRUE,absImgName); - dotRun->addJob(imgFmt,absImgName); - if (generateImageMap) dotRun->addJob(MAP_CMD,absMapName); - DotManager::instance()->addRun(dotRun); - - } - else if (graphFormat==GOF_EPS) - { - // run dot to create a .eps image - DotRunner *dotRun = new DotRunner(absDotName,d.absPath().data(),FALSE); - if (usePDFLatex) - { - dotRun->addJob("pdf",absPdfName,absBaseName); - } - else - { - dotRun->addJob("ps",absEpsName); - } - DotManager::instance()->addRun(dotRun); - - } - } - Doxygen::indexList->addImageFile(baseName+"."+imgExt); - - if (graphFormat==GOF_BITMAP && textFormat==EOF_DocBook) - { - out << "<para>" << endl; - out << " <informalfigure>" << endl; - out << " <mediaobject>" << endl; - out << " <imageobject>" << endl; - out << " <imagedata"; - out << " width=\"50%\" align=\"center\" valign=\"middle\" scalefit=\"0\" fileref=\"" << relPath << baseName << "." << imgExt << "\">"; - out << "</imagedata>" << endl; - out << " </imageobject>" << endl; - out << " </mediaobject>" << endl; - out << " </informalfigure>" << endl; - out << "</para>" << endl; - } - else if (graphFormat==GOF_BITMAP && generateImageMap) - { - if (imgExt=="svg") // Scalable vector graphics - { - out << "<div class=\"center\">"; - if (regenerate || !writeSVGFigureLink(out,relPath,baseName,absImgName)) // need to patch the links in the generated SVG file - { - if (regenerate) - { - DotManager::instance()->addSVGConversion(absImgName,relPath,FALSE,QCString(),TRUE,graphId); - } - int mapId = DotManager::instance()->addSVGObject(fileName,baseName,absImgName,relPath); - out << "<!-- SVG " << mapId << " -->" << endl; - } - out << "</div>" << endl; - } - else // bitmap graphics - { - out << "<div class=\"center\"><img src=\"" << relPath << baseName << "." - << imgExt << "\" border=\"0\" usemap=\"#" - << mapName << "\" alt=\""; - out << "\"/>"; - out << "</div>" << endl; - - if (regenerate || !insertMapFile(out,absMapName,relPath,mapName)) - { - int mapId = DotManager::instance()->addMap(fileName,absMapName,relPath, - FALSE,QCString(),mapName); - out << "<!-- MAP " << mapId << " -->" << endl; - } - } - } - else if (graphFormat==GOF_EPS) // encapsulated postscript - { - if (regenerate || !writeVecGfxFigure(out,baseName,absBaseName)) - { - int figId = DotManager::instance()->addFigure(fileName,baseName,absBaseName,FALSE); - out << endl << "% FIG " << figId << endl; - } - } - if (!regenerate) removeDotGraph(absDotName); - - return baseName; -} - -bool DotCallGraph::isTrivial() const -{ - return m_startNode->m_children==0; -} - -bool DotCallGraph::isTooBig() const -{ - static int maxNodes = Config_getInt(DOT_GRAPH_MAX_NODES); - int numNodes = m_startNode->m_children ? m_startNode->m_children->count() : 0; - return numNodes>=maxNodes; -} - -//------------------------------------------------------------- -static void writeDotDirDepGraph(FTextStream &t,DirDef *dd,bool linkRelations); - -DotDirDeps::DotDirDeps(DirDef *dir) : m_dir(dir) -{ -} - -DotDirDeps::~DotDirDeps() -{ -} - -QCString DotDirDeps::writeGraph(FTextStream &out, - GraphOutputFormat graphFormat, - EmbeddedOutputFormat textFormat, - const char *path, - const char *fileName, - const char *relPath, - bool generateImageMap, - int graphId, - bool linkRelations) const -{ - QDir d(path); - // store the original directory - if (!d.exists()) - { - err("Output dir %s does not exist!\n",path); exit(1); - } - static bool usePDFLatex = Config_getBool(USE_PDFLATEX); - - QCString baseName=m_dir->getOutputFileBase()+"_dep"; - QCString mapName=escapeCharsInString(baseName,FALSE); - - QCString imgExt = getDotImageExtension(); - QCString imgFmt = Config_getEnum(DOT_IMAGE_FORMAT); - QCString absBaseName = d.absPath().utf8()+"/"+baseName; - QCString absDotName = absBaseName+".dot"; - QCString absMapName = absBaseName+".map"; - QCString absPdfName = absBaseName+".pdf"; - QCString absEpsName = absBaseName+".eps"; - QCString absImgName = absBaseName+"."+imgExt; - - // compute md5 checksum of the graph were are about to generate - QGString theGraph; - FTextStream md5stream(&theGraph); - //m_dir->writeDepGraph(md5stream); - writeDotDirDepGraph(md5stream,m_dir,linkRelations); - uchar md5_sig[16]; - QCString sigStr(33); - MD5Buffer((const unsigned char *)theGraph.data(),theGraph.length(),md5_sig); - MD5SigToString(md5_sig,sigStr.rawData(),33); - bool regenerate=FALSE; - if (checkAndUpdateMd5Signature(absBaseName,sigStr) || - !checkDeliverables(graphFormat==GOF_BITMAP ? absImgName : - usePDFLatex ? absPdfName : absEpsName, - graphFormat==GOF_BITMAP && generateImageMap ? absMapName : QCString()) - ) - { - regenerate=TRUE; - - QFile f(absDotName); - if (!f.open(IO_WriteOnly)) - { - err("Cannot create file %s.dot for writing!\n",baseName.data()); - } - FTextStream t(&f); - t << theGraph.data(); - f.close(); - - if (graphFormat==GOF_BITMAP) - { - // run dot to create a bitmap image - DotRunner *dotRun = new DotRunner(absDotName,d.absPath().data(),TRUE,absImgName); - dotRun->addJob(imgFmt,absImgName); - if (generateImageMap) dotRun->addJob(MAP_CMD,absMapName); - DotManager::instance()->addRun(dotRun); - } - else if (graphFormat==GOF_EPS) - { - DotRunner *dotRun = new DotRunner(absDotName,d.absPath().data(),FALSE); - if (usePDFLatex) - { - dotRun->addJob("pdf",absPdfName,absBaseName); - } - else - { - dotRun->addJob("ps",absEpsName); - } - DotManager::instance()->addRun(dotRun); - } - } - Doxygen::indexList->addImageFile(baseName+"."+imgExt); - - if (graphFormat==GOF_BITMAP && textFormat==EOF_DocBook) - { - out << "<para>" << endl; - out << " <informalfigure>" << endl; - out << " <mediaobject>" << endl; - out << " <imageobject>" << endl; - out << " <imagedata"; - out << " width=\"50%\" align=\"center\" valign=\"middle\" scalefit=\"0\" fileref=\"" << relPath << baseName << "." << imgExt << "\">"; - out << "</imagedata>" << endl; - out << " </imageobject>" << endl; - out << " </mediaobject>" << endl; - out << " </informalfigure>" << endl; - out << "</para>" << endl; - } - else if (graphFormat==GOF_BITMAP && generateImageMap) - { - if (imgExt=="svg") // Scalable vector graphics - { - out << "<div class=\"center\">"; - if (regenerate || !writeSVGFigureLink(out,relPath,baseName,absImgName)) // need to patch the links in the generated SVG file - { - if (regenerate) - { - DotManager::instance()->addSVGConversion(absImgName,relPath,FALSE,QCString(),TRUE,graphId); - } - int mapId = DotManager::instance()->addSVGObject(fileName,baseName,absImgName,relPath); - out << "<!-- SVG " << mapId << " -->" << endl; - } - out << "</div>" << endl; - } - else // bitmap graphics - { - out << "<div class=\"center\"><img src=\"" << relPath << baseName << "." - << imgExt << "\" border=\"0\" usemap=\"#" - << mapName << "\" alt=\""; - out << convertToXML(m_dir->displayName()); - out << "\"/>"; - out << "</div>" << endl; - - if (regenerate || !insertMapFile(out,absMapName,relPath,mapName)) - { - int mapId = DotManager::instance()->addMap(fileName,absMapName,relPath, - TRUE,QCString(),mapName); - out << "<!-- MAP " << mapId << " -->" << endl; - } - } - } - else if (graphFormat==GOF_EPS) - { - if (regenerate || !writeVecGfxFigure(out,baseName,absBaseName)) - { - int figId = DotManager::instance()->addFigure(fileName,baseName,absBaseName,FALSE); - out << endl << "% FIG " << figId << endl; - } - } - if (!regenerate) removeDotGraph(absDotName); - - return baseName; -} - -bool DotDirDeps::isTrivial() const -{ - return m_dir->depGraphIsTrivial(); -} - -//------------------------------------------------------------- + friend void generateGraphLegend(const char* path); +}; void generateGraphLegend(const char *path) { QDir d(path); - // store the original directory - if (!d.exists()) - { - err("Output dir %s does not exist!\n",path); exit(1); - } - - QGString theGraph; - FTextStream md5stream(&theGraph); - writeGraphHeader(md5stream,theTranslator->trLegendTitle()); - md5stream << " Node9 [shape=\"box\",label=\"Inherited\",fontsize=\"" << FONTSIZE << "\",height=0.2,width=0.4,fontname=\"" << FONTNAME << "\",fillcolor=\"grey75\",style=\"filled\" fontcolor=\"black\"];\n"; - md5stream << " Node10 -> Node9 [dir=\"back\",color=\"midnightblue\",fontsize=\"" << FONTSIZE << "\",style=\"solid\",fontname=\"" << FONTNAME << "\"];\n"; - md5stream << " Node10 [shape=\"box\",label=\"PublicBase\",fontsize=\"" << FONTSIZE << "\",height=0.2,width=0.4,fontname=\"" << FONTNAME << "\",color=\"black\",URL=\"$classPublicBase" << Doxygen::htmlFileExtension << "\"];\n"; - md5stream << " Node11 -> Node10 [dir=\"back\",color=\"midnightblue\",fontsize=\"" << FONTSIZE << "\",style=\"solid\",fontname=\"" << FONTNAME << "\"];\n"; - md5stream << " Node11 [shape=\"box\",label=\"Truncated\",fontsize=\"" << FONTSIZE << "\",height=0.2,width=0.4,fontname=\"" << FONTNAME << "\",color=\"red\",URL=\"$classTruncated" << Doxygen::htmlFileExtension << "\"];\n"; - md5stream << " Node13 -> Node9 [dir=\"back\",color=\"darkgreen\",fontsize=\"" << FONTSIZE << "\",style=\"solid\",fontname=\"" << FONTNAME << "\"];\n"; - md5stream << " Node13 [shape=\"box\",label=\"ProtectedBase\",fontsize=\"" << FONTSIZE << "\",height=0.2,width=0.4,fontname=\"" << FONTNAME << "\",color=\"black\",URL=\"$classProtectedBase" << Doxygen::htmlFileExtension << "\"];\n"; - md5stream << " Node14 -> Node9 [dir=\"back\",color=\"firebrick4\",fontsize=\"" << FONTSIZE << "\",style=\"solid\",fontname=\"" << FONTNAME << "\"];\n"; - md5stream << " Node14 [shape=\"box\",label=\"PrivateBase\",fontsize=\"" << FONTSIZE << "\",height=0.2,width=0.4,fontname=\"" << FONTNAME << "\",color=\"black\",URL=\"$classPrivateBase" << Doxygen::htmlFileExtension << "\"];\n"; - md5stream << " Node15 -> Node9 [dir=\"back\",color=\"midnightblue\",fontsize=\"" << FONTSIZE << "\",style=\"solid\",fontname=\"" << FONTNAME << "\"];\n"; - md5stream << " Node15 [shape=\"box\",label=\"Undocumented\",fontsize=\"" << FONTSIZE << "\",height=0.2,width=0.4,fontname=\"" << FONTNAME << "\",color=\"grey75\"];\n"; - md5stream << " Node16 -> Node9 [dir=\"back\",color=\"midnightblue\",fontsize=\"" << FONTSIZE << "\",style=\"solid\",fontname=\"" << FONTNAME << "\"];\n"; - md5stream << " Node16 [shape=\"box\",label=\"Templ< int >\",fontsize=\"" << FONTSIZE << "\",height=0.2,width=0.4,fontname=\"" << FONTNAME << "\",color=\"black\",URL=\"$classTempl" << Doxygen::htmlFileExtension << "\"];\n"; - md5stream << " Node17 -> Node16 [dir=\"back\",color=\"orange\",fontsize=\"" << FONTSIZE << "\",style=\"dashed\",label=\"< int >\",fontname=\"" << FONTNAME << "\"];\n"; - md5stream << " Node17 [shape=\"box\",label=\"Templ< T >\",fontsize=\"" << FONTSIZE << "\",height=0.2,width=0.4,fontname=\"" << FONTNAME << "\",color=\"black\",URL=\"$classTempl" << Doxygen::htmlFileExtension << "\"];\n"; - md5stream << " Node18 -> Node9 [dir=\"back\",color=\"darkorchid3\",fontsize=\"" << FONTSIZE << "\",style=\"dashed\",label=\"m_usedClass\",fontname=\"" << FONTNAME << "\"];\n"; - md5stream << " Node18 [shape=\"box\",label=\"Used\",fontsize=\"" << FONTSIZE << "\",height=0.2,width=0.4,fontname=\"" << FONTNAME << "\",color=\"black\",URL=\"$classUsed" << Doxygen::htmlFileExtension << "\"];\n"; - writeGraphFooter(md5stream); - uchar md5_sig[16]; - QCString sigStr(33); - MD5Buffer((const unsigned char *)theGraph.data(),theGraph.length(),md5_sig); - MD5SigToString(md5_sig,sigStr.rawData(),33); - QCString absBaseName = (QCString)path+"/graph_legend"; - QCString absDotName = absBaseName+".dot"; - QCString imgExt = getDotImageExtension(); - QCString imgFmt = Config_getEnum(DOT_IMAGE_FORMAT); - QCString imgName = "graph_legend."+imgExt; - QCString absImgName = absBaseName+"."+imgExt; - if (checkAndUpdateMd5Signature(absBaseName,sigStr) || - !checkDeliverables(absImgName)) - { - QFile dotFile(absDotName); - if (!dotFile.open(IO_WriteOnly)) - { - err("Could not open file %s for writing\n",dotFile.name().data()); - return; - } - - FTextStream dotText(&dotFile); - dotText << theGraph; - dotFile.close(); - - // run dot to generate the a bitmap image from the graph + GraphLegendDotGraph dg; + FTextStream ts; + dg.writeGraph(ts, GOF_BITMAP, EOF_Html, path, "", "", FALSE, 0); - DotRunner *dotRun = new DotRunner(absDotName,d.absPath().data(),TRUE,absImgName); - dotRun->addJob(imgFmt,absImgName); - DotManager::instance()->addRun(dotRun); - } - else - { - removeDotGraph(absDotName); - } - Doxygen::indexList->addImageFile(imgName); - - if (imgExt=="svg") + if (getDotImageExtension()=="svg") { DotManager::instance()->addSVGObject( - absBaseName+Config_getString(HTML_FILE_EXTENSION), + dg.absBaseName()+Config_getString(HTML_FILE_EXTENSION), "graph_legend", - absImgName,QCString()); + dg.absImgName(),QCString()); } } @@ -4256,19 +493,20 @@ void writeDotGraphFromFile(const char *inFile,const char *outDir, } QCString imgExt = getDotImageExtension(); - QCString imgFmt = Config_getEnum(DOT_IMAGE_FORMAT); QCString imgName = (QCString)outFile+"."+imgExt; QCString absImgName = d.absPath().utf8()+"/"+imgName; QCString absOutFile = d.absPath().utf8()+"/"+outFile; - DotRunner dotRun(inFile,d.absPath().data(),FALSE,absImgName); + DotRunner dotRun(inFile, QCString()); if (format==GOF_BITMAP) - dotRun.addJob(imgFmt,absImgName); + { + dotRun.addJob(Config_getEnum(DOT_IMAGE_FORMAT),absImgName); + } else // format==GOF_EPS { if (Config_getBool(USE_PDFLATEX)) { - dotRun.addJob("pdf",absOutFile+".pdf",absOutFile); + dotRun.addJob("pdf",absOutFile+".pdf"); } else { @@ -4282,13 +520,10 @@ void writeDotGraphFromFile(const char *inFile,const char *outDir, return; } - if (format==GOF_BITMAP) checkDotResult(getDotImageExtension(),absImgName); - Doxygen::indexList->addImageFile(imgName); } - /*! Writes user defined image map to the output. * \param t text stream to write to * \param inFile just the basename part of the filename @@ -4312,11 +547,10 @@ void writeDotImageMapFromFile(FTextStream &t, QCString mapName = baseName+".map"; QCString imgExt = getDotImageExtension(); - QCString imgFmt = Config_getEnum(DOT_IMAGE_FORMAT); QCString imgName = baseName+"."+imgExt; QCString absOutFile = d.absPath().utf8()+"/"+mapName; - DotRunner dotRun(inFile,d.absPath().data(),FALSE); + DotRunner dotRun(inFile, QCString()); dotRun.addJob(MAP_CMD,absOutFile); dotRun.preventCleanUp(); if (!dotRun.run()) @@ -4331,7 +565,7 @@ void writeDotImageMapFromFile(FTextStream &t, QCString svgName=outDir+"/"+baseName+".svg"; writeSVGFigureLink(t,relPath,baseName,svgName); DotFilePatcher patcher(svgName); - patcher.addSVGConversion(relPath,TRUE,context,TRUE,graphId); + patcher.addSVGConversion("",TRUE,context,TRUE,graphId); patcher.run(); } else // bitmap graphics @@ -4351,628 +585,3 @@ void writeDotImageMapFromFile(FTextStream &t, } d.remove(absOutFile); } - -//------------------------------------------------------------- - -int DotGroupCollaboration::m_curNodeNumber = 0; - -void DotGroupCollaboration::resetNumbering() -{ - m_curNodeNumber = 0; -} - -DotGroupCollaboration::DotGroupCollaboration(GroupDef* gd) -{ - QCString tmp_url = gd->getReference()+"$"+gd->getOutputFileBase(); - m_usedNodes = new QDict<DotNode>(1009); - QCString tooltip = gd->briefDescriptionAsTooltip(); - m_rootNode = new DotNode(m_curNodeNumber++, gd->groupTitle(), tooltip, tmp_url, TRUE ); - m_rootNode->markAsVisible(); - m_usedNodes->insert(gd->name(), m_rootNode ); - m_edges.setAutoDelete(TRUE); - - m_diskName = gd->getOutputFileBase(); - - buildGraph( gd ); -} - -DotGroupCollaboration::~DotGroupCollaboration() -{ - delete m_usedNodes; -} - -void DotGroupCollaboration::buildGraph(GroupDef* gd) -{ - QCString tmp_url; - //=========================== - // hierarchy. - - // Write parents - GroupList *groups = gd->partOfGroups(); - if ( groups ) - { - GroupListIterator gli(*groups); - GroupDef *d; - for (gli.toFirst();(d=gli.current());++gli) - { - DotNode* nnode = m_usedNodes->find(d->name()); - if ( !nnode ) - { // add node - tmp_url = d->getReference()+"$"+d->getOutputFileBase(); - QCString tooltip = d->briefDescriptionAsTooltip(); - nnode = new DotNode(m_curNodeNumber++, d->groupTitle(), tooltip, tmp_url ); - nnode->markAsVisible(); - m_usedNodes->insert(d->name(), nnode ); - } - tmp_url = ""; - addEdge( nnode, m_rootNode, DotGroupCollaboration::thierarchy, tmp_url, tmp_url ); - } - } - - // Add subgroups - if ( gd->getSubGroups() && gd->getSubGroups()->count() ) - { - QListIterator<GroupDef> defli(*gd->getSubGroups()); - GroupDef *def; - for (;(def=defli.current());++defli) - { - DotNode* nnode = m_usedNodes->find(def->name()); - if ( !nnode ) - { // add node - tmp_url = def->getReference()+"$"+def->getOutputFileBase(); - QCString tooltip = def->briefDescriptionAsTooltip(); - nnode = new DotNode(m_curNodeNumber++, def->groupTitle(), tooltip, tmp_url ); - nnode->markAsVisible(); - m_usedNodes->insert(def->name(), nnode ); - } - tmp_url = ""; - addEdge( m_rootNode, nnode, DotGroupCollaboration::thierarchy, tmp_url, tmp_url ); - } - } - - //======================= - // Write collaboration - - // Add members - addMemberList( gd->getMemberList(MemberListType_allMembersList) ); - - // Add classes - if ( gd->getClasses() && gd->getClasses()->count() ) - { - ClassSDict::Iterator defli(*gd->getClasses()); - ClassDef *def; - for (;(def=defli.current());++defli) - { - tmp_url = def->getReference()+"$"+def->getOutputFileBase()+Doxygen::htmlFileExtension; - if (!def->anchor().isEmpty()) - { - tmp_url+="#"+def->anchor(); - } - addCollaborationMember( def, tmp_url, DotGroupCollaboration::tclass ); - } - } - - // Add namespaces - if ( gd->getNamespaces() && gd->getNamespaces()->count() ) - { - NamespaceSDict::Iterator defli(*gd->getNamespaces()); - NamespaceDef *def; - for (;(def=defli.current());++defli) - { - tmp_url = def->getReference()+"$"+def->getOutputFileBase()+Doxygen::htmlFileExtension; - addCollaborationMember( def, tmp_url, DotGroupCollaboration::tnamespace ); - } - } - - // Add files - if ( gd->getFiles() && gd->getFiles()->count() ) - { - QListIterator<FileDef> defli(*gd->getFiles()); - FileDef *def; - for (;(def=defli.current());++defli) - { - tmp_url = def->getReference()+"$"+def->getOutputFileBase()+Doxygen::htmlFileExtension; - addCollaborationMember( def, tmp_url, DotGroupCollaboration::tfile ); - } - } - - // Add pages - if ( gd->getPages() && gd->getPages()->count() ) - { - PageSDict::Iterator defli(*gd->getPages()); - PageDef *def; - for (;(def=defli.current());++defli) - { - tmp_url = def->getReference()+"$"+def->getOutputFileBase()+Doxygen::htmlFileExtension; - addCollaborationMember( def, tmp_url, DotGroupCollaboration::tpages ); - } - } - - // Add directories - if ( gd->getDirs() && gd->getDirs()->count() ) - { - QListIterator<DirDef> defli(*gd->getDirs()); - DirDef *def; - for (;(def=defli.current());++defli) - { - tmp_url = def->getReference()+"$"+def->getOutputFileBase()+Doxygen::htmlFileExtension; - addCollaborationMember( def, tmp_url, DotGroupCollaboration::tdir ); - } - } -} - -void DotGroupCollaboration::addMemberList( MemberList* ml ) -{ - if ( !( ml && ml->count()) ) return; - MemberListIterator defli(*ml); - MemberDef *def; - for (;(def=defli.current());++defli) - { - QCString tmp_url = def->getReference()+"$"+def->getOutputFileBase()+Doxygen::htmlFileExtension - +"#"+def->anchor(); - addCollaborationMember( def, tmp_url, DotGroupCollaboration::tmember ); - } -} - -DotGroupCollaboration::Edge* DotGroupCollaboration::addEdge( - DotNode* _pNStart, DotNode* _pNEnd, EdgeType _eType, - const QCString& _label, const QCString& _url ) -{ - // search a existing link. - QListIterator<Edge> lli(m_edges); - Edge* newEdge = 0; - for ( lli.toFirst(); (newEdge=lli.current()); ++lli) - { - if ( newEdge->pNStart==_pNStart && - newEdge->pNEnd==_pNEnd && - newEdge->eType==_eType - ) - { // edge already found - break; - } - } - if ( newEdge==0 ) // new link - { - newEdge = new Edge(_pNStart,_pNEnd,_eType); - m_edges.append( newEdge ); - } - - if (!_label.isEmpty()) - { - newEdge->links.append(new Link(_label,_url)); - } - - return newEdge; -} - -void DotGroupCollaboration::addCollaborationMember( - Definition* def, QCString& url, EdgeType eType ) -{ - // Create group nodes - if ( !def->partOfGroups() ) - return; - GroupListIterator gli(*def->partOfGroups()); - GroupDef *d; - QCString tmp_str; - for (;(d=gli.current());++gli) - { - DotNode* nnode = m_usedNodes->find(d->name()); - if ( nnode != m_rootNode ) - { - if ( nnode==0 ) - { // add node - tmp_str = d->getReference()+"$"+d->getOutputFileBase(); - QCString tooltip = d->briefDescriptionAsTooltip(); - nnode = new DotNode(m_curNodeNumber++, d->groupTitle(), tooltip, tmp_str ); - nnode->markAsVisible(); - m_usedNodes->insert(d->name(), nnode ); - } - tmp_str = def->qualifiedName(); - addEdge( m_rootNode, nnode, eType, tmp_str, url ); - } - } -} - - -QCString DotGroupCollaboration::writeGraph( FTextStream &t, - GraphOutputFormat graphFormat, EmbeddedOutputFormat textFormat, - const char *path, const char *fileName, const char *relPath, - bool writeImageMap,int graphId) const -{ - QDir d(path); - // store the original directory - if (!d.exists()) - { - err("Output dir %s does not exist!\n",path); exit(1); - } - static bool usePDFLatex = Config_getBool(USE_PDFLATEX); - - QGString theGraph; - FTextStream md5stream(&theGraph); - writeGraphHeader(md5stream,m_rootNode->label()); - - // clean write flags - QDictIterator<DotNode> dni(*m_usedNodes); - DotNode *pn; - for (dni.toFirst();(pn=dni.current());++dni) - { - pn->clearWriteFlag(); - } - - // write other nodes. - for (dni.toFirst();(pn=dni.current());++dni) - { - pn->write(md5stream,DotNode::Inheritance,graphFormat,TRUE,FALSE,FALSE); - } - - // write edges - QListIterator<Edge> eli(m_edges); - Edge* edge; - for (eli.toFirst();(edge=eli.current());++eli) - { - edge->write( md5stream ); - } - - writeGraphFooter(md5stream); - uchar md5_sig[16]; - QCString sigStr(33); - MD5Buffer((const unsigned char *)theGraph.data(),theGraph.length(),md5_sig); - MD5SigToString(md5_sig,sigStr.rawData(),33); - QCString imgExt = getDotImageExtension(); - QCString imgFmt = Config_getEnum(DOT_IMAGE_FORMAT); - QCString baseName = m_diskName; - QCString imgName = baseName+"."+imgExt; - QCString absPath = d.absPath().data(); - QCString absBaseName = absPath+"/"+baseName; - QCString absDotName = absBaseName+".dot"; - QCString absImgName = absBaseName+"."+imgExt; - QCString absMapName = absBaseName+".map"; - QCString absPdfName = absBaseName+".pdf"; - QCString absEpsName = absBaseName+".eps"; - bool regenerate=FALSE; - if (checkAndUpdateMd5Signature(absBaseName,sigStr) || - !checkDeliverables(graphFormat==GOF_BITMAP ? absImgName : - usePDFLatex ? absPdfName : absEpsName, - graphFormat==GOF_BITMAP /*&& generateImageMap*/ ? absMapName : QCString()) - ) - { - regenerate=TRUE; - - QFile dotfile(absDotName); - if (dotfile.open(IO_WriteOnly)) - { - FTextStream tdot(&dotfile); - tdot << theGraph; - dotfile.close(); - } - - if (graphFormat==GOF_BITMAP) // run dot to create a bitmap image - { - DotRunner *dotRun = new DotRunner(absDotName,d.absPath().data(),FALSE); - dotRun->addJob(imgFmt,absImgName); - if (writeImageMap) dotRun->addJob(MAP_CMD,absMapName); - DotManager::instance()->addRun(dotRun); - - } - else if (graphFormat==GOF_EPS) - { - DotRunner *dotRun = new DotRunner(absDotName,d.absPath().data(),FALSE); - if (usePDFLatex) - { - dotRun->addJob("pdf",absPdfName,absBaseName); - } - else - { - dotRun->addJob("ps",absEpsName); - } - DotManager::instance()->addRun(dotRun); - } - - } - if (graphFormat==GOF_BITMAP && textFormat==EOF_DocBook) - { - t << "<para>" << endl; - t << " <informalfigure>" << endl; - t << " <mediaobject>" << endl; - t << " <imageobject>" << endl; - t << " <imagedata"; - t << " width=\"50%\" align=\"center\" valign=\"middle\" scalefit=\"0\" fileref=\"" << relPath << baseName << "." << imgExt << "\">"; - t << "</imagedata>" << endl; - t << " </imageobject>" << endl; - t << " </mediaobject>" << endl; - t << " </informalfigure>" << endl; - t << "</para>" << endl; - } - else if (graphFormat==GOF_BITMAP && writeImageMap) - { - QCString mapLabel = escapeCharsInString(baseName,FALSE); - t << "<center><table><tr><td>"; - - if (imgExt=="svg") - { - t << "<div class=\"center\">"; - if (regenerate || !writeSVGFigureLink(t,relPath,baseName,absImgName)) // need to patch the links in the generated SVG file - { - if (regenerate) - { - DotManager::instance()->addSVGConversion(absImgName,relPath,FALSE,QCString(),TRUE,graphId); - } - int mapId = DotManager::instance()->addSVGObject(fileName,baseName,absImgName,relPath); - t << "<!-- SVG " << mapId << " -->" << endl; - } - t << "</div>" << endl; - } - else - { - t << "<img src=\"" << relPath << imgName - << "\" border=\"0\" alt=\"\" usemap=\"#" - << mapLabel << "\"/>" << endl; - if (regenerate || !insertMapFile(t,absMapName,relPath,mapLabel)) - { - int mapId = DotManager::instance()->addMap(fileName,absMapName,relPath, - FALSE,QCString(),mapLabel); - t << "<!-- MAP " << mapId << " -->" << endl; - } - } - t << "</td></tr></table></center>" << endl; - } - else if (graphFormat==GOF_EPS) - { - if (regenerate || !writeVecGfxFigure(t,baseName,absBaseName)) - { - int figId = DotManager::instance()->addFigure(fileName,baseName,absBaseName,FALSE); - t << endl << "% FIG " << figId << endl; - } - } - if (!regenerate) removeDotGraph(absDotName); - - return baseName; -} - -void DotGroupCollaboration::Edge::write( FTextStream &t ) const -{ - const char* linkTypeColor[] = { - "darkorchid3" - ,"orange" - ,"blueviolet" - ,"darkgreen" - ,"firebrick4" - ,"grey75" - ,"midnightblue" - }; - QCString arrowStyle = "dir=\"none\", style=\"dashed\""; - t << " Node" << pNStart->number(); - t << "->"; - t << "Node" << pNEnd->number(); - - t << " [shape=plaintext"; - if (links.count()>0) // there are links - { - t << ", "; - // HTML-like edge labels crash on my Mac with Graphviz 2.0! and - // are not supported by older version of dot. - // - //t << label=<<TABLE BORDER=\"0\" CELLBORDER=\"0\">"; - //QListIterator<Link> lli(links); - //Link *link; - //for( lli.toFirst(); (link=lli.current()); ++lli) - //{ - // t << "<TR><TD"; - // if ( !link->url.isEmpty() ) - // t << " HREF=\"" << link->url << "\""; - // t << ">" << link->label << "</TD></TR>"; - //} - //t << "</TABLE>>"; - - t << "label=\""; - QListIterator<Link> lli(links); - Link *link; - bool first=TRUE; - int count=0; - const int maxLabels = 10; - for( lli.toFirst(); (link=lli.current()) && count<maxLabels; ++lli,++count) - { - if (first) first=FALSE; else t << "\\n"; - t << convertLabel(link->label); - } - if (count==maxLabels) t << "\\n..."; - t << "\""; - - } - switch( eType ) - { - case thierarchy: - arrowStyle = "dir=\"back\", style=\"solid\""; - break; - default: - t << ", color=\"" << linkTypeColor[(int)eType] << "\""; - break; - } - t << ", " << arrowStyle; - t << "];" << endl; -} - -bool DotGroupCollaboration::isTrivial() const -{ - return m_usedNodes->count() <= 1; -} - -void DotGroupCollaboration::writeGraphHeader(FTextStream &t, - const QCString &title) const -{ - t << "digraph "; - if (title.isEmpty()) - { - t << "\"Dot Graph\""; - } - else - { - t << "\"" << convertToXML(title) << "\""; - } - t << endl; - t << "{" << endl; - if (Config_getBool(DOT_TRANSPARENT)) - { - t << " bgcolor=\"transparent\";" << endl; - } - t << " edge [fontname=\"" << FONTNAME << "\",fontsize=\"" << FONTSIZE << "\"," - "labelfontname=\"" << FONTNAME << "\",labelfontsize=\"" << FONTSIZE << "\"];\n"; - t << " node [fontname=\"" << FONTNAME << "\",fontsize=\"" << FONTSIZE << "\",shape=box];\n"; - t << " rankdir=LR;\n"; -} - -void writeDotDirDepGraph(FTextStream &t,DirDef *dd,bool linkRelations) -{ - t << "digraph \"" << dd->displayName() << "\" {\n"; - if (Config_getBool(DOT_TRANSPARENT)) - { - t << " bgcolor=transparent;\n"; - } - t << " compound=true\n"; - t << " node [ fontsize=\"" << FONTSIZE << "\", fontname=\"" << FONTNAME << "\"];\n"; - t << " edge [ labelfontsize=\"" << FONTSIZE << "\", labelfontname=\"" << FONTNAME << "\"];\n"; - - QDict<DirDef> dirsInGraph(257); - - dirsInGraph.insert(dd->getOutputFileBase(),dd); - if (dd->parent()) - { - t << " subgraph cluster" << dd->parent()->getOutputFileBase() << " {\n"; - t << " graph [ bgcolor=\"#ddddee\", pencolor=\"black\", label=\"" - << dd->parent()->shortName() - << "\" fontname=\"" << FONTNAME << "\", fontsize=\"" << FONTSIZE << "\", URL=\""; - t << dd->parent()->getOutputFileBase() << Doxygen::htmlFileExtension; - t << "\"]\n"; - } - if (dd->isCluster()) - { - t << " subgraph cluster" << dd->getOutputFileBase() << " {\n"; - t << " graph [ bgcolor=\"#eeeeff\", pencolor=\"black\", label=\"\"" - << " URL=\"" << dd->getOutputFileBase() << Doxygen::htmlFileExtension - << "\"];\n"; - t << " " << dd->getOutputFileBase() << " [shape=plaintext label=\"" - << dd->shortName() << "\"];\n"; - - // add nodes for sub directories - QListIterator<DirDef> sdi(dd->subDirs()); - DirDef *sdir; - for (sdi.toFirst();(sdir=sdi.current());++sdi) - { - t << " " << sdir->getOutputFileBase() << " [shape=box label=\"" - << sdir->shortName() << "\""; - if (sdir->isCluster()) - { - t << " color=\"red\""; - } - else - { - t << " color=\"black\""; - } - t << " fillcolor=\"white\" style=\"filled\""; - t << " URL=\"" << sdir->getOutputFileBase() - << Doxygen::htmlFileExtension << "\""; - t << "];\n"; - dirsInGraph.insert(sdir->getOutputFileBase(),sdir); - } - t << " }\n"; - } - else - { - t << " " << dd->getOutputFileBase() << " [shape=box, label=\"" - << dd->shortName() << "\", style=\"filled\", fillcolor=\"#eeeeff\"," - << " pencolor=\"black\", URL=\"" << dd->getOutputFileBase() - << Doxygen::htmlFileExtension << "\"];\n"; - } - if (dd->parent()) - { - t << " }\n"; - } - - // add nodes for other used directories - QDictIterator<UsedDir> udi(*dd->usedDirs()); - UsedDir *udir; - //printf("*** For dir %s\n",shortName().data()); - for (udi.toFirst();(udir=udi.current());++udi) - // for each used dir (=directly used or a parent of a directly used dir) - { - const DirDef *usedDir=udir->dir(); - DirDef *dir=dd; - while (dir) - { - //printf("*** check relation %s->%s same_parent=%d !%s->isParentOf(%s)=%d\n", - // dir->shortName().data(),usedDir->shortName().data(), - // dir->parent()==usedDir->parent(), - // usedDir->shortName().data(), - // shortName().data(), - // !usedDir->isParentOf(this) - // ); - if (dir!=usedDir && dir->parent()==usedDir->parent() && - !usedDir->isParentOf(dd)) - // include if both have the same parent (or no parent) - { - t << " " << usedDir->getOutputFileBase() << " [shape=box label=\"" - << usedDir->shortName() << "\""; - if (usedDir->isCluster()) - { - if (!Config_getBool(DOT_TRANSPARENT)) - { - t << " fillcolor=\"white\" style=\"filled\""; - } - t << " color=\"red\""; - } - t << " URL=\"" << usedDir->getOutputFileBase() - << Doxygen::htmlFileExtension << "\"];\n"; - dirsInGraph.insert(usedDir->getOutputFileBase(),usedDir); - break; - } - dir=dir->parent(); - } - } - - // add relations between all selected directories - DirDef *dir; - QDictIterator<DirDef> di(dirsInGraph); - for (di.toFirst();(dir=di.current());++di) // foreach dir in the graph - { - QDictIterator<UsedDir> udi(*dir->usedDirs()); - UsedDir *udir; - for (udi.toFirst();(udir=udi.current());++udi) // foreach used dir - { - const DirDef *usedDir=udir->dir(); - if ((dir!=dd || !udir->inherited()) && // only show direct dependendies for this dir - (usedDir!=dd || !udir->inherited()) && // only show direct dependendies for this dir - !usedDir->isParentOf(dir) && // don't point to own parent - dirsInGraph.find(usedDir->getOutputFileBase())) // only point to nodes that are in the graph - { - QCString relationName; - relationName.sprintf("dir_%06d_%06d",dir->dirCount(),usedDir->dirCount()); - if (Doxygen::dirRelations.find(relationName)==0) - { - // new relation - Doxygen::dirRelations.append(relationName, - new DirRelation(relationName,dir,udir)); - } - int nrefs = udir->filePairs().count(); - t << " " << dir->getOutputFileBase() << "->" - << usedDir->getOutputFileBase(); - t << " [headlabel=\"" << nrefs << "\", labeldistance=1.5"; - if (linkRelations) - { - t << " headhref=\"" << relationName << Doxygen::htmlFileExtension << "\""; - } - t << "];\n"; - } - } - } - - t << "}\n"; -} - -void resetDotNodeNumbering() -{ - DotClassGraph::resetNumbering(); - DotInclDepGraph::resetNumbering(); - DotCallGraph::resetNumbering(); - DotGroupCollaboration::resetNumbering(); -} - @@ -1,13 +1,10 @@ /****************************************************************************** * - * - * - * - * Copyright (C) 1997-2015 by Dimitri van Heesch. + * Copyright (C) 1997-2019 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 + * 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. * @@ -16,8 +13,8 @@ * */ -#ifndef _DOT_H -#define _DOT_H +#ifndef DOT_H +#define DOT_H #include <qlist.h> #include <qdict.h> @@ -26,466 +23,24 @@ #include <qqueue.h> #include <qthread.h> #include "sortdict.h" -#include "classdef.h" +#include "qgstring.h" +#include "qdir.h" +#include "qcstring.h" +#include "dotgraph.h" +#include "dotfilepatcher.h" +#include "dotrunner.h" -class FileDef; class FTextStream; -class DotNodeList; -class ClassSDict; -class MemberDef; -class Definition; -class DirDef; -class GroupDef; -class DotGroupCollaboration; +class DotRunner; class DotRunnerQueue; - -enum GraphOutputFormat { GOF_BITMAP, GOF_EPS }; -enum EmbeddedOutputFormat { EOF_Html, EOF_LaTeX, EOF_Rtf, EOF_DocBook }; - -// the graphicx LaTeX has a limitation of maximum size of 16384 -// To be on the save side we take it a little bit smaller i.e. 150 inch * 72 dpi -// It is anyway hard to view these size of images -#define MAX_LATEX_GRAPH_INCH 150 -#define MAX_LATEX_GRAPH_SIZE (MAX_LATEX_GRAPH_INCH * 72) - -/** Attributes of an edge of a dot graph */ -struct EdgeInfo -{ - enum Colors { Blue=0, Green=1, Red=2, Purple=3, Grey=4, Orange=5, Orange2=6 }; - enum Styles { Solid=0, Dashed=1 }; - EdgeInfo() : m_color(0), m_style(0), m_labColor(0) {} - ~EdgeInfo() {} - int m_color; - int m_style; - QCString m_label; - QCString m_url; - int m_labColor; -}; - -/** A node in a dot graph */ -class DotNode -{ - public: - enum GraphType { Dependency, Inheritance, Collaboration, Hierarchy, CallGraph }; - enum TruncState { Unknown, Truncated, Untruncated }; - DotNode(int n,const char *lab,const char *tip,const char *url, - bool rootNode=FALSE,ClassDef *cd=0); - ~DotNode(); - void addChild(DotNode *n, - int edgeColor=EdgeInfo::Purple, - int edgeStyle=EdgeInfo::Solid, - const char *edgeLab=0, - const char *edgeURL=0, - int edgeLabCol=-1 - ); - void addParent(DotNode *n); - void deleteNode(DotNodeList &deletedList,SDict<DotNode> *skipNodes=0); - void removeChild(DotNode *n); - void removeParent(DotNode *n); - int findParent( DotNode *n ); - void write(FTextStream &t,GraphType gt,GraphOutputFormat f, - bool topDown,bool toChildren,bool backArrows); - int m_subgraphId; - void clearWriteFlag(); - void writeXML(FTextStream &t,bool isClassGraph); - void writeDocbook(FTextStream &t,bool isClassGraph); - void writeDEF(FTextStream &t); - QCString label() const { return m_label; } - int number() const { return m_number; } - bool isVisible() const { return m_visible; } - TruncState isTruncated() const { return m_truncated; } - int distance() const { return m_distance; } - void renumberNodes(int &number); - - private: - void colorConnectedNodes(int curColor); - void writeBox(FTextStream &t,GraphType gt,GraphOutputFormat f, - bool hasNonReachableChildren); - void writeArrow(FTextStream &t,GraphType gt,GraphOutputFormat f,DotNode *cn, - EdgeInfo *ei,bool topDown, bool pointBack=TRUE); - void setDistance(int distance); - const DotNode *findDocNode() const; // only works for acyclic graphs! - void markAsVisible(bool b=TRUE) { m_visible=b; } - void markAsTruncated(bool b=TRUE) { m_truncated=b ? Truncated : Untruncated; } - int m_number; - QCString m_label; //!< label text - QCString m_tooltip; //!< node's tooltip - QCString m_url; //!< url of the node (format: remote$local) - QList<DotNode> *m_parents; //!< list of parent nodes (incoming arrows) - QList<DotNode> *m_children; //!< list of child nodes (outgoing arrows) - QList<EdgeInfo> *m_edgeInfo; //!< edge info for each child - bool m_deleted; //!< used to mark a node as deleted - bool m_written; //!< used to mark a node as written - bool m_hasDoc; //!< used to mark a node as documented - bool m_isRoot; //!< indicates if this is a root node - ClassDef * m_classDef; //!< class representing this node (can be 0) - bool m_visible; //!< is the node visible in the output - TruncState m_truncated; //!< does the node have non-visible children/parents - int m_distance; //!< shortest path to the root node - bool m_renumbered;//!< indicates if the node has been renumbered (to prevent endless loops) - - friend class DotGfxHierarchyTable; - friend class DotClassGraph; - friend class DotInclDepGraph; - friend class DotNodeList; - friend class DotCallGraph; - friend class DotGroupCollaboration; - friend class DotInheritanceGraph; - - friend QCString computeMd5Signature( - DotNode *root, GraphType gt, - GraphOutputFormat f, - const QCString &rank, - bool renderParents, - bool backArrows, - const QCString &title, - QCString &graphStr - ); -}; - -/** Class representing a list of DotNode objects. */ -class DotNodeList : public QList<DotNode> -{ - public: - DotNodeList() : QList<DotNode>() {} - ~DotNodeList() {} - private: - int compareValues(const DotNode *n1,const DotNode *n2) const; -}; - -/** Represents a graphical class hierarchy */ -class DotGfxHierarchyTable -{ - public: - DotGfxHierarchyTable(const char *prefix="",ClassDef::CompoundType ct=ClassDef::Class); - ~DotGfxHierarchyTable(); - void writeGraph(FTextStream &t,const char *path, const char *fileName) const; - void createGraph(DotNode *rootNode,FTextStream &t,const char *path,const char *fileName,int id) const; - const DotNodeList *subGraphs() const { return m_rootSubgraphs; } - - private: - void addHierarchy(DotNode *n,ClassDef *cd,bool hide); - void addClassList(ClassSDict *cl); - - QCString m_prefix; - ClassDef::CompoundType m_classType; - QList<DotNode> *m_rootNodes; - QDict<DotNode> *m_usedNodes; - int m_curNodeNumber; - DotNodeList *m_rootSubgraphs; -}; - -/** Representation of a class inheritance or dependency graph */ -class DotClassGraph -{ - public: - DotClassGraph(ClassDef *cd,DotNode::GraphType t); - ~DotClassGraph(); - bool isTrivial() const; - bool isTooBig() const; - QCString writeGraph(FTextStream &t,GraphOutputFormat gf,EmbeddedOutputFormat ef, - const char *path, const char *fileName, const char *relPath, - bool TBRank=TRUE,bool imageMap=TRUE,int graphId=-1) const; - - void writeXML(FTextStream &t); - void writeDocbook(FTextStream &t); - void writeDEF(FTextStream &t); - static void resetNumbering(); - - private: - void buildGraph(ClassDef *cd,DotNode *n,bool base,int distance); - bool determineVisibleNodes(DotNode *rootNode,int maxNodes,bool includeParents); - void determineTruncatedNodes(QList<DotNode> &queue,bool includeParents); - void addClass(ClassDef *cd,DotNode *n,int prot,const char *label, - const char *usedName,const char *templSpec, - bool base,int distance); - - DotNode * m_startNode; - QDict<DotNode> * m_usedNodes; - static int m_curNodeNumber; - DotNode::GraphType m_graphType; - QCString m_collabFileName; - QCString m_inheritFileName; - bool m_lrRank; -}; - -/** Representation of an include dependency graph */ -class DotInclDepGraph -{ - public: - DotInclDepGraph(FileDef *fd,bool inverse); - ~DotInclDepGraph(); - QCString writeGraph(FTextStream &t, GraphOutputFormat gf, EmbeddedOutputFormat ef, - const char *path,const char *fileName,const char *relPath, - bool writeImageMap=TRUE,int graphId=-1) const; - bool isTrivial() const; - bool isTooBig() const; - QCString diskName() const; - void writeXML(FTextStream &t); - void writeDocbook(FTextStream &t); - static void resetNumbering(); - - private: - void buildGraph(DotNode *n,FileDef *fd,int distance); - void determineVisibleNodes(QList<DotNode> &queue,int &maxNodes); - void determineTruncatedNodes(QList<DotNode> &queue); - - DotNode *m_startNode; - QDict<DotNode> *m_usedNodes; - static int m_curNodeNumber; - QCString m_inclDepFileName; - QCString m_inclByDepFileName; - bool m_inverse; -}; - -/** Representation of an call graph */ -class DotCallGraph -{ - public: - DotCallGraph(MemberDef *md,bool inverse); - ~DotCallGraph(); - QCString writeGraph(FTextStream &t, GraphOutputFormat gf, EmbeddedOutputFormat ef, - const char *path,const char *fileName, - const char *relPath,bool writeImageMap=TRUE, - int graphId=-1) const; - void buildGraph(DotNode *n,MemberDef *md,int distance); - bool isTrivial() const; - bool isTooBig() const; - void determineVisibleNodes(QList<DotNode> &queue, int &maxNodes); - void determineTruncatedNodes(QList<DotNode> &queue); - static void resetNumbering(); - - private: - DotNode *m_startNode; - static int m_curNodeNumber; - QDict<DotNode> *m_usedNodes; - bool m_inverse; - QCString m_diskName; - Definition * m_scope; -}; - -/** Representation of an directory dependency graph */ -class DotDirDeps -{ - public: - DotDirDeps(DirDef *dir); - ~DotDirDeps(); - bool isTrivial() const; - QCString writeGraph(FTextStream &out, - GraphOutputFormat gf, - EmbeddedOutputFormat ef, - const char *path, - const char *fileName, - const char *relPath, - bool writeImageMap=TRUE, - int graphId=-1, - bool linkRelations=TRUE) const; - private: - DirDef *m_dir; -}; - -/** Representation of a group collaboration graph */ -class DotGroupCollaboration -{ - public : - enum EdgeType - { tmember = 0, - tclass, - tnamespace, - tfile, - tpages, - tdir, - thierarchy - }; - - class Link - { - public: - Link(const QCString lab,const QCString &u) : label(lab), url(u) {} - QCString label; - QCString url; - }; - - class Edge - { - public : - Edge(DotNode *start,DotNode *end,EdgeType type) - : pNStart(start), pNEnd(end), eType(type) - { links.setAutoDelete(TRUE); } - - DotNode* pNStart; - DotNode* pNEnd; - EdgeType eType; - - QList<Link> links; - void write( FTextStream &t ) const; - }; - - DotGroupCollaboration(GroupDef* gd); - ~DotGroupCollaboration(); - QCString writeGraph(FTextStream &t, GraphOutputFormat gf,EmbeddedOutputFormat ef, - const char *path,const char *fileName,const char *relPath, - bool writeImageMap=TRUE,int graphId=-1) const; - void buildGraph(GroupDef* gd); - bool isTrivial() const; - static void resetNumbering(); - - private : - void addCollaborationMember( Definition* def, QCString& url, EdgeType eType ); - void addMemberList( class MemberList* ml ); - void writeGraphHeader(FTextStream &t,const QCString &title) const; - Edge* addEdge( DotNode* _pNStart, DotNode* _pNEnd, EdgeType _eType, - const QCString& _label, const QCString& _url ); - - DotNode *m_rootNode; - static int m_curNodeNumber; - QDict<DotNode> *m_usedNodes; - QCString m_diskName; - QList<Edge> m_edges; -}; - -/** Minimal constant string class that is thread safe, once initialized. */ -class DotConstString -{ - public: - DotConstString() { m_str=0; m_pdfstr=0;} - ~DotConstString() { delete[] m_str; delete[] m_pdfstr;} - DotConstString(const QCString &s, const QCString &p = NULL) : m_str(0), m_pdfstr(0) { set(s); setpdf(p);} - DotConstString(const DotConstString &s) : m_str(0), m_pdfstr(0) { set(s.data()); } - const char *data() const { return m_str; } - const char *pdfData() const { return m_pdfstr; } - bool isEmpty() const { return m_str==0 || m_str[0]=='\0'; } - void set(const QCString &s) - { - delete[] m_str; - m_str=0; - if (!s.isEmpty()) - { - m_str=new char[s.length()+1]; - qstrcpy(m_str,s.data()); - } - } - void setpdf(const QCString &p) - { - delete[] m_pdfstr; - m_pdfstr=0; - if (!p.isEmpty()) - { - m_pdfstr=new char[p.length()+1]; - qstrcpy(m_pdfstr,p.data()); - } - } - private: - DotConstString &operator=(const DotConstString &); - char *m_str; - char *m_pdfstr; -}; - -/** Helper class to run dot from doxygen. - */ -class DotRunner -{ - public: - struct CleanupItem - { - DotConstString path; - DotConstString file; - }; - - /** Creates a runner for a dot \a file. */ - DotRunner(const QCString &file,const QCString &fontPath,bool checkResult, - const QCString &imageName = QCString()); - - /** Adds an additional job to the run. - * Performing multiple jobs one file can be faster. - */ - void addJob(const char *format,const char *output, const char *base = NULL); - - void addPostProcessing(const char *cmd,const char *args); - - void preventCleanUp() { m_cleanUp = FALSE; } - - /** Runs dot for all jobs added. */ - bool run(); - const CleanupItem &cleanup() const { return m_cleanupItem; } - - private: - DotConstString m_dotExe; - bool m_multiTargets; - QList<DotConstString> m_jobs; - DotConstString m_postArgs; - DotConstString m_postCmd; - DotConstString m_file; - DotConstString m_path; - bool m_checkResult; - DotConstString m_imageName; - DotConstString m_imgExt; - bool m_cleanUp; - CleanupItem m_cleanupItem; -}; - -/** Helper class to insert a set of map file into an output file */ -class DotFilePatcher -{ - public: - struct Map - { - QCString mapFile; - QCString relPath; - bool urlOnly; - QCString context; - QCString label; - bool zoomable; - int graphId; - }; - DotFilePatcher(const char *patchFile); - int addMap(const QCString &mapFile,const QCString &relPath, - bool urlOnly,const QCString &context,const QCString &label); - int addFigure(const QCString &baseName, - const QCString &figureName,bool heightCheck); - int addSVGConversion(const QCString &relPath,bool urlOnly, - const QCString &context,bool zoomable,int graphId); - int addSVGObject(const QCString &baseName, const QCString &figureName, - const QCString &relPath); - bool run(); - QCString file() const; - - private: - QList<Map> m_maps; - QCString m_patchFile; -}; - -/** Queue of dot jobs to run. */ -class DotRunnerQueue -{ - public: - void enqueue(DotRunner *runner); - DotRunner *dequeue(); - uint count() const; - private: - QWaitCondition m_bufferNotEmpty; - QQueue<DotRunner> m_queue; - mutable QMutex m_mutex; -}; - -/** Worker thread to execute a dot run */ -class DotWorkerThread : public QThread -{ - public: - DotWorkerThread(DotRunnerQueue *queue); - void run(); - void cleanup(); - private: - DotRunnerQueue *m_queue; - QList<DotRunner::CleanupItem> m_cleanupItems; -}; +class DotWorkerThread; /** Singleton that manages dot relation actions */ class DotManager { public: static DotManager *instance(); - void addRun(DotRunner *run); + DotRunner* createRunner(const QCString& absDotName, const QCString& md5Hash); int addMap(const QCString &file,const QCString &mapFile, const QCString &relPath,bool urlOnly, const QCString &context,const QCString &label); @@ -500,13 +55,15 @@ class DotManager private: DotManager(); virtual ~DotManager(); - QList<DotRunner> m_dotRuns; + + QDict<DotRunner> m_runners; SDict<DotFilePatcher> m_dotMaps; static DotManager *m_theInstance; DotRunnerQueue *m_queue; QList<DotWorkerThread> m_workers; }; +void initDot(); /** Generated a graphs legend page */ void generateGraphLegend(const char *path); @@ -517,7 +74,10 @@ void writeDotImageMapFromFile(FTextStream &t, const QCString& inFile, const QCString& outDir, const QCString& relPath,const QCString& baseName, const QCString& context,int graphId=-1); - -void resetDotNodeNumbering(); +bool writeSVGFigureLink(FTextStream &out,const QCString &relPath, + const QCString &baseName,const QCString &absImgName); +bool convertMapFile(FTextStream &t,const char *mapName, + const QCString relPath, bool urlOnly=FALSE, + const QCString &context=QCString()); #endif diff --git a/src/dotcallgraph.cpp b/src/dotcallgraph.cpp new file mode 100644 index 0000000..15d408a --- /dev/null +++ b/src/dotcallgraph.cpp @@ -0,0 +1,217 @@ +/****************************************************************************** +* +* Copyright (C) 1997-2019 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. +* +* Documents produced by Doxygen are derivative works derived from the +* input used in their production; they are not affected by this license. +* +*/ + +#include "dotcallgraph.h" + +#include "dotnode.h" +#include "memberlist.h" +#include "config.h" +#include "util.h" + +#define HIDE_SCOPE_NAMES Config_getBool(HIDE_SCOPE_NAMES) +#define DOT_GRAPH_MAX_NODES Config_getInt(DOT_GRAPH_MAX_NODES) +#define MAX_DOT_GRAPH_DEPTH Config_getInt(MAX_DOT_GRAPH_DEPTH) + +void DotCallGraph::buildGraph(DotNode *n,const MemberDef *md,int distance) +{ + MemberSDict *refs = m_inverse ? md->getReferencedByMembers() : md->getReferencesMembers(); + if (refs) + { + refs->sort(); + MemberSDict::Iterator mri(*refs); + MemberDef *rmd; + for (;(rmd=mri.current());++mri) + { + if (rmd->showInCallGraph()) + { + QCString uniqueId; + uniqueId=rmd->getReference()+"$"+ + rmd->getOutputFileBase()+"#"+rmd->anchor(); + DotNode *bn = m_usedNodes->find(uniqueId); + if (bn) // file is already a node in the graph + { + n->addChild(bn,0,0,0); + bn->addParent(n); + bn->setDistance(distance); + } + else + { + QCString name; + if (HIDE_SCOPE_NAMES) + { + name = rmd->getOuterScope()==m_scope ? + rmd->name() : rmd->qualifiedName(); + } + else + { + name = rmd->qualifiedName(); + } + QCString tooltip = rmd->briefDescriptionAsTooltip(); + bn = new DotNode( + getNextNodeNumber(), + linkToText(rmd->getLanguage(),name,FALSE), + tooltip, + uniqueId, + 0 //distance + ); + n->addChild(bn,0,0,0); + bn->addParent(n); + bn->setDistance(distance); + m_usedNodes->insert(uniqueId,bn); + + buildGraph(bn,rmd,distance+1); + } + } + } + } +} + +void DotCallGraph::determineVisibleNodes(QList<DotNode> &queue, int &maxNodes) +{ + while (queue.count()>0 && maxNodes>0) + { + DotNode *n = queue.take(0); + if (!n->isVisible() && n->distance()<=MAX_DOT_GRAPH_DEPTH) // not yet processed + { + n->markAsVisible(); + maxNodes--; + // add direct children + if (n->children()) + { + QListIterator<DotNode> li(*n->children()); + DotNode *dn; + for (li.toFirst();(dn=li.current());++li) + { + queue.append(dn); + } + } + } + } +} + +void DotCallGraph::determineTruncatedNodes(QList<DotNode> &queue) +{ + while (queue.count()>0) + { + DotNode *n = queue.take(0); + if (n->isVisible() && n->isTruncated()==DotNode::Unknown) + { + bool truncated = FALSE; + if (n->children()) + { + QListIterator<DotNode> li(*n->children()); + const DotNode *dn; + for (li.toFirst();(dn=li.current());++li) + { + if (!dn->isVisible()) + truncated = TRUE; + else + queue.append(dn); + } + } + n->markAsTruncated(truncated); + } + } +} + +DotCallGraph::DotCallGraph(const MemberDef *md,bool inverse) +{ + m_inverse = inverse; + m_diskName = md->getOutputFileBase()+"_"+md->anchor(); + m_scope = md->getOuterScope(); + QCString uniqueId; + uniqueId = md->getReference()+"$"+ + md->getOutputFileBase()+"#"+md->anchor(); + QCString name; + if (HIDE_SCOPE_NAMES) + { + name = md->name(); + } + else + { + name = md->qualifiedName(); + } + QCString tooltip = md->briefDescriptionAsTooltip(); + m_startNode = new DotNode(getNextNodeNumber(), + linkToText(md->getLanguage(),name,FALSE), + tooltip, + uniqueId.data(), + TRUE // root node + ); + m_startNode->setDistance(0); + m_usedNodes = new QDict<DotNode>(1009); + m_usedNodes->insert(uniqueId,m_startNode); + buildGraph(m_startNode,md,1); + + int maxNodes = DOT_GRAPH_MAX_NODES; + QList<DotNode> openNodeQueue; + openNodeQueue.append(m_startNode); + determineVisibleNodes(openNodeQueue,maxNodes); + openNodeQueue.clear(); + openNodeQueue.append(m_startNode); + determineTruncatedNodes(openNodeQueue); +} + +DotCallGraph::~DotCallGraph() +{ + DotNode::deleteNodes(m_startNode); + delete m_usedNodes; +} + +QCString DotCallGraph::getBaseName() const +{ + return m_diskName + (m_inverse ? "_icgraph" : "_cgraph"); +} + +void DotCallGraph::computeTheGraph() +{ + computeGraph( + m_startNode, + CallGraph, + m_graphFormat, + m_inverse ? "RL" : "LR", + FALSE, + m_inverse, + m_startNode->label(), + m_theGraph); +} + +QCString DotCallGraph::getMapLabel() const +{ + return m_baseName; +} + +QCString DotCallGraph::writeGraph( + FTextStream &out, + GraphOutputFormat graphFormat, + EmbeddedOutputFormat textFormat, + const char *path, + const char *fileName, + const char *relPath,bool generateImageMap, + int graphId) +{ + return DotGraph::writeGraph(out, graphFormat, textFormat, path, fileName, relPath, generateImageMap, graphId); +} + +bool DotCallGraph::isTrivial() const +{ + return m_startNode->children()==0; +} + +bool DotCallGraph::isTooBig() const +{ + int numNodes = m_startNode->children() ? m_startNode->children()->count() : 0; + return numNodes>=DOT_GRAPH_MAX_NODES; +} diff --git a/src/dotcallgraph.h b/src/dotcallgraph.h new file mode 100644 index 0000000..c96b9cf --- /dev/null +++ b/src/dotcallgraph.h @@ -0,0 +1,52 @@ +/****************************************************************************** +* +* Copyright (C) 1997-2019 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. +* +* Documents produced by Doxygen are derivative works derived from the +* input used in their production; they are not affected by this license. +* +*/ + +#ifndef DOTCALLGRAPH_H +#define DOTCALLGRAPH_H + +#include "dotgraph.h" +#include "ftextstream.h" +#include "memberdef.h" + +/** Representation of an call graph */ +class DotCallGraph : public DotGraph +{ + public: + DotCallGraph(const MemberDef *md,bool inverse); + ~DotCallGraph(); + bool isTrivial() const; + bool isTooBig() const; + QCString writeGraph(FTextStream &t, GraphOutputFormat gf, EmbeddedOutputFormat ef, + const char *path,const char *fileName, + const char *relPath,bool writeImageMap=TRUE, + int graphId=-1); + + protected: + virtual QCString getBaseName() const; + virtual QCString getMapLabel() const; + virtual void computeTheGraph(); + + private: + void buildGraph(DotNode *n,const MemberDef *md,int distance); + void determineVisibleNodes(QList<DotNode> &queue, int &maxNodes); + void determineTruncatedNodes(QList<DotNode> &queue); + DotNode *m_startNode; + QDict<DotNode> *m_usedNodes; + bool m_inverse; + QCString m_diskName; + const Definition * m_scope; +}; + +#endif diff --git a/src/dotclassgraph.cpp b/src/dotclassgraph.cpp new file mode 100644 index 0000000..308be4b --- /dev/null +++ b/src/dotclassgraph.cpp @@ -0,0 +1,548 @@ +/****************************************************************************** +* +* Copyright (C) 1997-2019 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. +* +* Documents produced by Doxygen are derivative works derived from the +* input used in their production; they are not affected by this license. +* +*/ + +#include "dotclassgraph.h" +#include "dotnode.h" + +#include "config.h" +#include "util.h" + +#define HIDE_SCOPE_NAMES Config_getBool(HIDE_SCOPE_NAMES) +#define MAX_DOT_GRAPH_DEPTH Config_getInt(MAX_DOT_GRAPH_DEPTH) +#define UML_LOOK Config_getBool(UML_LOOK) +#define TEMPLATE_RELATIONS Config_getBool(TEMPLATE_RELATIONS) +#define DOT_GRAPH_MAX_NODES Config_getInt(DOT_GRAPH_MAX_NODES) + +void DotClassGraph::addClass(const ClassDef *cd,DotNode *n,int prot, + const char *label,const char *usedName,const char *templSpec,bool base,int distance) +{ + if (Config_getBool(HIDE_UNDOC_CLASSES) && !cd->isLinkable()) return; + + int edgeStyle = (label || prot==EdgeInfo::Orange || prot==EdgeInfo::Orange2) ? EdgeInfo::Dashed : EdgeInfo::Solid; + QCString className; + if (cd->isAnonymous()) + { + className="anonymous:"; + className+=label; + } + else if (usedName) // name is a typedef + { + className=usedName; + } + else if (templSpec) // name has a template part + { + className=insertTemplateSpecifierInScope(cd->name(),templSpec); + } + else // just a normal name + { + className=cd->displayName(); + } + //printf("DotClassGraph::addClass(class=`%s',parent=%s,prot=%d,label=%s,dist=%d,usedName=%s,templSpec=%s,base=%d)\n", + // className.data(),n->label().data(),prot,label,distance,usedName,templSpec,base); + DotNode *bn = m_usedNodes->find(className); + if (bn) // class already inserted + { + if (base) + { + n->addChild(bn,prot,edgeStyle,label); + bn->addParent(n); + } + else + { + bn->addChild(n,prot,edgeStyle,label); + n->addParent(bn); + } + bn->setDistance(distance); + //printf(" add exiting node %s of %s\n",bn->label().data(),n->label().data()); + } + else // new class + { + QCString displayName=className; + if (HIDE_SCOPE_NAMES) displayName=stripScope(displayName); + QCString tmp_url; + if (cd->isLinkable() && !cd->isHidden()) + { + tmp_url=cd->getReference()+"$"+cd->getOutputFileBase(); + if (!cd->anchor().isEmpty()) + { + tmp_url+="#"+cd->anchor(); + } + } + QCString tooltip = cd->briefDescriptionAsTooltip(); + bn = new DotNode(getNextNodeNumber(), + displayName, + tooltip, + tmp_url.data(), + FALSE, // rootNode + cd + ); + if (base) + { + n->addChild(bn,prot,edgeStyle,label); + bn->addParent(n); + } + else + { + bn->addChild(n,prot,edgeStyle,label); + n->addParent(bn); + } + bn->setDistance(distance); + m_usedNodes->insert(className,bn); + //printf(" add new child node `%s' to %s hidden=%d url=%s\n", + // className.data(),n->label().data(),cd->isHidden(),tmp_url.data()); + + buildGraph(cd,bn,base,distance+1); + } +} + +void DotClassGraph::determineTruncatedNodes(QList<DotNode> &queue,bool includeParents) +{ + while (queue.count()>0) + { + DotNode *n = queue.take(0); + if (n->isVisible() && n->isTruncated()==DotNode::Unknown) + { + bool truncated = FALSE; + if (n->children()) + { + QListIterator<DotNode> li(*n->children()); + const DotNode *dn; + for (li.toFirst();(dn=li.current());++li) + { + if (!dn->isVisible()) + truncated = TRUE; + else + queue.append(dn); + } + } + if (n->parents() && includeParents) + { + QListIterator<DotNode> li(*n->parents()); + const DotNode *dn; + for (li.toFirst();(dn=li.current());++li) + { + if (!dn->isVisible()) + truncated = TRUE; + else + queue.append(dn); + } + } + n->markAsTruncated(truncated); + } + } +} + +bool DotClassGraph::determineVisibleNodes(DotNode *rootNode, + int maxNodes,bool includeParents) +{ + QList<DotNode> childQueue; + QList<DotNode> parentQueue; + QArray<int> childTreeWidth; + QArray<int> parentTreeWidth; + childQueue.append(rootNode); + if (includeParents) parentQueue.append(rootNode); + bool firstNode=TRUE; // flag to force reprocessing rootNode in the parent loop + // despite being marked visible in the child loop + while ((childQueue.count()>0 || parentQueue.count()>0) && maxNodes>0) + { + if (childQueue.count()>0) + { + DotNode *n = childQueue.take(0); + int distance = n->distance(); + if (!n->isVisible() && distance<=MAX_DOT_GRAPH_DEPTH) // not yet processed + { + if (distance>0) + { + int oldSize=(int)childTreeWidth.size(); + if (distance>oldSize) + { + childTreeWidth.resize(QMAX(childTreeWidth.size(),(uint)distance)); + int i; for (i=oldSize;i<distance;i++) childTreeWidth[i]=0; + } + childTreeWidth[distance-1]+=n->label().length(); + } + n->markAsVisible(); + maxNodes--; + // add direct children + if (n->children()) + { + QListIterator<DotNode> li(*n->children()); + const DotNode *dn; + for (li.toFirst();(dn=li.current());++li) + { + childQueue.append(dn); + } + } + } + } + if (includeParents && parentQueue.count()>0) + { + DotNode *n = parentQueue.take(0); + if ((!n->isVisible() || firstNode) && n->distance()<=MAX_DOT_GRAPH_DEPTH) // not yet processed + { + firstNode=FALSE; + int distance = n->distance(); + if (distance>0) + { + int oldSize = (int)parentTreeWidth.size(); + if (distance>oldSize) + { + parentTreeWidth.resize(QMAX(parentTreeWidth.size(),(uint)distance)); + int i; for (i=oldSize;i<distance;i++) parentTreeWidth[i]=0; + } + parentTreeWidth[distance-1]+=n->label().length(); + } + n->markAsVisible(); + maxNodes--; + // add direct parents + if (n->parents()) + { + QListIterator<DotNode> li(*n->parents()); + const DotNode *dn; + for (li.toFirst();(dn=li.current());++li) + { + parentQueue.append(dn); + } + } + } + } + } + if (UML_LOOK) return FALSE; // UML graph are always top to bottom + int maxWidth=0; + int maxHeight=(int)QMAX(childTreeWidth.size(),parentTreeWidth.size()); + uint i; + for (i=0;i<childTreeWidth.size();i++) + { + if (childTreeWidth.at(i)>maxWidth) maxWidth=childTreeWidth.at(i); + } + for (i=0;i<parentTreeWidth.size();i++) + { + if (parentTreeWidth.at(i)>maxWidth) maxWidth=parentTreeWidth.at(i); + } + //printf("max tree width=%d, max tree height=%d\n",maxWidth,maxHeight); + return maxWidth>80 && maxHeight<12; // used metric to decide to render the tree + // from left to right instead of top to bottom, + // with the idea to render very wide trees in + // left to right order. +} + +void DotClassGraph::buildGraph(const ClassDef *cd,DotNode *n,bool base,int distance) +{ + //printf("DocClassGraph::buildGraph(%s,distance=%d,base=%d)\n", + // cd->name().data(),distance,base); + // ---- Add inheritance relations + + if (m_graphType == Inheritance || m_graphType==Collaboration) + { + BaseClassList *bcl = base ? cd->baseClasses() : cd->subClasses(); + if (bcl) + { + BaseClassListIterator bcli(*bcl); + BaseClassDef *bcd; + for ( ; (bcd=bcli.current()) ; ++bcli ) + { + //printf("-------- inheritance relation %s->%s templ=`%s'\n", + // cd->name().data(),bcd->classDef->name().data(),bcd->templSpecifiers.data()); + addClass(bcd->classDef,n,bcd->prot,0,bcd->usedName, + bcd->templSpecifiers,base,distance); + } + } + } + if (m_graphType == Collaboration) + { + // ---- Add usage relations + + UsesClassDict *dict = + base ? cd->usedImplementationClasses() : + cd->usedByImplementationClasses() + ; + if (dict) + { + UsesClassDictIterator ucdi(*dict); + UsesClassDef *ucd; + for (;(ucd=ucdi.current());++ucdi) + { + QCString label; + QDictIterator<void> dvi(*ucd->accessors); + const char *s; + bool first=TRUE; + int count=0; + int maxLabels=10; + for (;(s=dvi.currentKey()) && count<maxLabels;++dvi,++count) + { + if (first) + { + label=s; + first=FALSE; + } + else + { + label+=QCString("\n")+s; + } + } + if (count==maxLabels) label+="\n..."; + //printf("addClass: %s templSpec=%s\n",ucd->classDef->name().data(),ucd->templSpecifiers.data()); + addClass(ucd->classDef,n,EdgeInfo::Purple,label,0, + ucd->templSpecifiers,base,distance); + } + } + } + if (TEMPLATE_RELATIONS && base) + { + ConstraintClassDict *dict = cd->templateTypeConstraints(); + if (dict) + { + ConstraintClassDictIterator ccdi(*dict); + ConstraintClassDef *ccd; + for (;(ccd=ccdi.current());++ccdi) + { + QCString label; + QDictIterator<void> dvi(*ccd->accessors); + const char *s; + bool first=TRUE; + int count=0; + int maxLabels=10; + for (;(s=dvi.currentKey()) && count<maxLabels;++dvi,++count) + { + if (first) + { + label=s; + first=FALSE; + } + else + { + label+=QCString("\n")+s; + } + } + if (count==maxLabels) label+="\n..."; + //printf("addClass: %s templSpec=%s\n",ucd->classDef->name().data(),ucd->templSpecifiers.data()); + addClass(ccd->classDef,n,EdgeInfo::Orange2,label,0, + 0,TRUE,distance); + } + } + } + + // ---- Add template instantiation relations + + if (TEMPLATE_RELATIONS) + { + if (base) // template relations for base classes + { + const ClassDef *templMaster=cd->templateMaster(); + if (templMaster) + { + QDictIterator<ClassDef> cli(*templMaster->getTemplateInstances()); + const ClassDef *templInstance; + for (;(templInstance=cli.current());++cli) + { + if (templInstance==cd) + { + addClass(templMaster,n,EdgeInfo::Orange,cli.currentKey(),0, + 0,TRUE,distance); + } + } + } + } + else // template relations for super classes + { + const QDict<ClassDef> *templInstances = cd->getTemplateInstances(); + if (templInstances) + { + QDictIterator<ClassDef> cli(*templInstances); + const ClassDef *templInstance; + for (;(templInstance=cli.current());++cli) + { + addClass(templInstance,n,EdgeInfo::Orange,cli.currentKey(),0, + 0,FALSE,distance); + } + } + } + } +} + +DotClassGraph::DotClassGraph(const ClassDef *cd,GraphType t) +{ + //printf("--------------- DotClassGraph::DotClassGraph `%s'\n",cd->displayName().data()); + m_graphType = t; + QCString tmp_url=""; + if (cd->isLinkable() && !cd->isHidden()) + { + tmp_url=cd->getReference()+"$"+cd->getOutputFileBase(); + if (!cd->anchor().isEmpty()) + { + tmp_url+="#"+cd->anchor(); + } + } + QCString className = cd->displayName(); + QCString tooltip = cd->briefDescriptionAsTooltip(); + m_startNode = new DotNode(getNextNodeNumber(), + className, + tooltip, + tmp_url.data(), + TRUE, // is a root node + cd + ); + m_startNode->setDistance(0); + m_usedNodes = new QDict<DotNode>(1009); + m_usedNodes->insert(className,m_startNode); + + buildGraph(cd,m_startNode,TRUE,1); + if (t==Inheritance) buildGraph(cd,m_startNode,FALSE,1); + + m_lrRank = determineVisibleNodes(m_startNode,DOT_GRAPH_MAX_NODES,t==Inheritance); + QList<DotNode> openNodeQueue; + openNodeQueue.append(m_startNode); + determineTruncatedNodes(openNodeQueue,t==Inheritance); + + m_collabFileName = cd->collaborationGraphFileName(); + m_inheritFileName = cd->inheritanceGraphFileName(); +} + +bool DotClassGraph::isTrivial() const +{ + if (m_graphType==Inheritance) + return m_startNode->children()==0 && m_startNode->parents()==0; + else + return !UML_LOOK && m_startNode->children()==0; +} + +bool DotClassGraph::isTooBig() const +{ + int numNodes = 0; + numNodes+= m_startNode->children() ? m_startNode->children()->count() : 0; + if (m_graphType==Inheritance) + { + numNodes+= m_startNode->parents() ? m_startNode->parents()->count() : 0; + } + return numNodes>=DOT_GRAPH_MAX_NODES; +} + +DotClassGraph::~DotClassGraph() +{ + DotNode::deleteNodes(m_startNode); + delete m_usedNodes; +} + +QCString DotClassGraph::getBaseName() const +{ + switch (m_graphType) + { + case Collaboration: + return m_collabFileName; + break; + case Inheritance: + return m_inheritFileName; + break; + default: + ASSERT(0); + break; + } + return ""; +} + +void DotClassGraph::computeTheGraph() +{ + computeGraph( + m_startNode, + m_graphType, + m_graphFormat, + m_lrRank ? "LR" : "", + m_graphType == Inheritance, + TRUE, + m_startNode->label(), + m_theGraph + ); +} + +QCString DotClassGraph::getMapLabel() const +{ + QCString mapName; + switch (m_graphType) + { + case Collaboration: + mapName="coll_map"; + break; + case Inheritance: + mapName="inherit_map"; + break; + default: + ASSERT(0); + break; + } + + return escapeCharsInString(m_startNode->label(),FALSE)+"_"+escapeCharsInString(mapName,FALSE); +} + +QCString DotClassGraph::getImgAltText() const +{ + switch (m_graphType) + { + case Collaboration: + return "Collaboration graph"; + break; + case Inheritance: + return "Inheritance graph"; + break; + default: + ASSERT(0); + break; + } + return ""; +} + +QCString DotClassGraph::writeGraph(FTextStream &out, + GraphOutputFormat graphFormat, + EmbeddedOutputFormat textFormat, + const char *path, + const char *fileName, + const char *relPath, + bool /*isTBRank*/, + bool generateImageMap, + int graphId) +{ + return DotGraph::writeGraph(out, graphFormat, textFormat, path, fileName, relPath, generateImageMap, graphId); +} + +//-------------------------------------------------------------------- + +void DotClassGraph::writeXML(FTextStream &t) +{ + QDictIterator<DotNode> dni(*m_usedNodes); + DotNode *node; + for (;(node=dni.current());++dni) + { + node->writeXML(t,TRUE); + } +} + +void DotClassGraph::writeDocbook(FTextStream &t) +{ + QDictIterator<DotNode> dni(*m_usedNodes); + DotNode *node; + for (;(node=dni.current());++dni) + { + node->writeDocbook(t,TRUE); + } +} + +void DotClassGraph::writeDEF(FTextStream &t) +{ + QDictIterator<DotNode> dni(*m_usedNodes); + DotNode *node; + for (;(node=dni.current());++dni) + { + node->writeDEF(t); + } +} diff --git a/src/dotclassgraph.h b/src/dotclassgraph.h new file mode 100644 index 0000000..b3b9291 --- /dev/null +++ b/src/dotclassgraph.h @@ -0,0 +1,62 @@ +/****************************************************************************** +* +* Copyright (C) 1997-2019 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. +* +* Documents produced by Doxygen are derivative works derived from the +* input used in their production; they are not affected by this license. +* +*/ + +#ifndef DOTCLASSGRAPH_H +#define DOTCLASSGRAPH_H + +#include "classdef.h" + +#include "dotgraph.h" + +/** Representation of a class inheritance or dependency graph */ +class DotClassGraph : public DotGraph +{ +public: + DotClassGraph(const ClassDef *cd,GraphType t); + ~DotClassGraph(); + bool isTrivial() const; + bool isTooBig() const; + QCString writeGraph(FTextStream &t,GraphOutputFormat gf,EmbeddedOutputFormat ef, + const char *path, const char *fileName, const char *relPath, + bool TBRank=TRUE,bool imageMap=TRUE,int graphId=-1); + + void writeXML(FTextStream &t); + void writeDocbook(FTextStream &t); + void writeDEF(FTextStream &t); + +protected: + virtual QCString getBaseName() const; + virtual QCString getMapLabel() const; + virtual void computeTheGraph(); + virtual QCString getImgAltText() const; + +private: + void buildGraph(const ClassDef *cd,DotNode *n,bool base,int distance); + bool determineVisibleNodes(DotNode *rootNode,int maxNodes,bool includeParents); + void determineTruncatedNodes(QList<DotNode> &queue,bool includeParents); + void addClass(const ClassDef *cd,DotNode *n,int prot,const char *label, + const char *usedName,const char *templSpec, + bool base,int distance); + + DotNode * m_startNode; + QDict<DotNode> * m_usedNodes; + GraphType m_graphType; + QCString m_collabFileName; + QCString m_inheritFileName; + bool m_lrRank; +}; + + +#endif diff --git a/src/dotdirdeps.cpp b/src/dotdirdeps.cpp new file mode 100644 index 0000000..85906d1 --- /dev/null +++ b/src/dotdirdeps.cpp @@ -0,0 +1,220 @@ +/****************************************************************************** +* +* Copyright (C) 1997-2019 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. +* +* Documents produced by Doxygen are derivative works derived from the +* input used in their production; they are not affected by this license. +* +*/ + +#include "dotdirdeps.h" + +#include "ftextstream.h" +#include "util.h" +#include "doxygen.h" +#include "config.h" + +void writeDotDirDepGraph(FTextStream &t,const DirDef *dd,bool linkRelations) +{ + t << "digraph \"" << dd->displayName() << "\" {\n"; + if (Config_getBool(DOT_TRANSPARENT)) + { + t << " bgcolor=transparent;\n"; + } + t << " compound=true\n"; + t << " node [ fontsize=\"" << DotGraph::DOT_FONTSIZE << "\", fontname=\"" << DotGraph::DOT_FONTNAME << "\"];\n"; + t << " edge [ labelfontsize=\"" << DotGraph::DOT_FONTSIZE << "\", labelfontname=\"" << DotGraph::DOT_FONTNAME << "\"];\n"; + + QDict<DirDef> dirsInGraph(257); + + dirsInGraph.insert(dd->getOutputFileBase(),dd); + if (dd->parent()) + { + t << " subgraph cluster" << dd->parent()->getOutputFileBase() << " {\n"; + t << " graph [ bgcolor=\"#ddddee\", pencolor=\"black\", label=\"" + << dd->parent()->shortName() + << "\" fontname=\"" << DotGraph::DOT_FONTNAME << "\", fontsize=\"" << DotGraph::DOT_FONTSIZE << "\", URL=\""; + t << dd->parent()->getOutputFileBase() << Doxygen::htmlFileExtension; + t << "\"]\n"; + } + if (dd->isCluster()) + { + t << " subgraph cluster" << dd->getOutputFileBase() << " {\n"; + t << " graph [ bgcolor=\"#eeeeff\", pencolor=\"black\", label=\"\"" + << " URL=\"" << dd->getOutputFileBase() << Doxygen::htmlFileExtension + << "\"];\n"; + t << " " << dd->getOutputFileBase() << " [shape=plaintext label=\"" + << dd->shortName() << "\"];\n"; + + // add nodes for sub directories + QListIterator<DirDef> sdi(dd->subDirs()); + const DirDef *sdir; + for (sdi.toFirst();(sdir=sdi.current());++sdi) + { + t << " " << sdir->getOutputFileBase() << " [shape=box label=\"" + << sdir->shortName() << "\""; + if (sdir->isCluster()) + { + t << " color=\"red\""; + } + else + { + t << " color=\"black\""; + } + t << " fillcolor=\"white\" style=\"filled\""; + t << " URL=\"" << sdir->getOutputFileBase() + << Doxygen::htmlFileExtension << "\""; + t << "];\n"; + dirsInGraph.insert(sdir->getOutputFileBase(),sdir); + } + t << " }\n"; + } + else + { + t << " " << dd->getOutputFileBase() << " [shape=box, label=\"" + << dd->shortName() << "\", style=\"filled\", fillcolor=\"#eeeeff\"," + << " pencolor=\"black\", URL=\"" << dd->getOutputFileBase() + << Doxygen::htmlFileExtension << "\"];\n"; + } + if (dd->parent()) + { + t << " }\n"; + } + + // add nodes for other used directories + QDictIterator<UsedDir> udi(*dd->usedDirs()); + UsedDir *udir; + //printf("*** For dir %s\n",shortName().data()); + for (udi.toFirst();(udir=udi.current());++udi) + // for each used dir (=directly used or a parent of a directly used dir) + { + const DirDef *usedDir=udir->dir(); + const DirDef *dir=dd; + while (dir) + { + //printf("*** check relation %s->%s same_parent=%d !%s->isParentOf(%s)=%d\n", + // dir->shortName().data(),usedDir->shortName().data(), + // dir->parent()==usedDir->parent(), + // usedDir->shortName().data(), + // shortName().data(), + // !usedDir->isParentOf(this) + // ); + if (dir!=usedDir && dir->parent()==usedDir->parent() && + !usedDir->isParentOf(dd)) + // include if both have the same parent (or no parent) + { + t << " " << usedDir->getOutputFileBase() << " [shape=box label=\"" + << usedDir->shortName() << "\""; + if (usedDir->isCluster()) + { + if (!Config_getBool(DOT_TRANSPARENT)) + { + t << " fillcolor=\"white\" style=\"filled\""; + } + t << " color=\"red\""; + } + t << " URL=\"" << usedDir->getOutputFileBase() + << Doxygen::htmlFileExtension << "\"];\n"; + dirsInGraph.insert(usedDir->getOutputFileBase(),usedDir); + break; + } + dir=dir->parent(); + } + } + + // add relations between all selected directories + const DirDef *dir; + QDictIterator<DirDef> di(dirsInGraph); + for (di.toFirst();(dir=di.current());++di) // foreach dir in the graph + { + QDictIterator<UsedDir> udi(*dir->usedDirs()); + UsedDir *udir; + for (udi.toFirst();(udir=udi.current());++udi) // foreach used dir + { + const DirDef *usedDir=udir->dir(); + if ((dir!=dd || !udir->inherited()) && // only show direct dependendies for this dir + (usedDir!=dd || !udir->inherited()) && // only show direct dependendies for this dir + !usedDir->isParentOf(dir) && // don't point to own parent + dirsInGraph.find(usedDir->getOutputFileBase())) // only point to nodes that are in the graph + { + QCString relationName; + relationName.sprintf("dir_%06d_%06d",dir->dirCount(),usedDir->dirCount()); + if (Doxygen::dirRelations.find(relationName)==0) + { + // new relation + Doxygen::dirRelations.append(relationName, + new DirRelation(relationName,dir,udir)); + } + int nrefs = udir->filePairs().count(); + t << " " << dir->getOutputFileBase() << "->" + << usedDir->getOutputFileBase(); + t << " [headlabel=\"" << nrefs << "\", labeldistance=1.5"; + if (linkRelations) + { + t << " headhref=\"" << relationName << Doxygen::htmlFileExtension << "\""; + } + t << "];\n"; + } + } + } + + t << "}\n"; +} + +DotDirDeps::DotDirDeps(const DirDef *dir) : m_dir(dir) +{ +} + +DotDirDeps::~DotDirDeps() +{ +} + +QCString DotDirDeps::getBaseName() const +{ + return m_dir->getOutputFileBase()+"_dep"; + +} + +void DotDirDeps::computeTheGraph() +{ + // compute md5 checksum of the graph were are about to generate + FTextStream md5stream(&m_theGraph); + //m_dir->writeDepGraph(md5stream); + writeDotDirDepGraph(md5stream,m_dir,m_linkRelations); +} + +QCString DotDirDeps::getMapLabel() const +{ + return escapeCharsInString(m_baseName,FALSE); +} + +QCString DotDirDeps::getImgAltText() const +{ + return convertToXML(m_dir->displayName()); +} + +QCString DotDirDeps::writeGraph(FTextStream &out, + GraphOutputFormat graphFormat, + EmbeddedOutputFormat textFormat, + const char *path, + const char *fileName, + const char *relPath, + bool generateImageMap, + int graphId, + bool linkRelations) +{ + m_linkRelations = linkRelations; + m_urlOnly = TRUE; + return DotGraph::writeGraph(out, graphFormat, textFormat, path, fileName, relPath, generateImageMap, graphId); +} + +bool DotDirDeps::isTrivial() const +{ + return m_dir->depGraphIsTrivial(); +} diff --git a/src/dotdirdeps.h b/src/dotdirdeps.h new file mode 100644 index 0000000..f5eef65 --- /dev/null +++ b/src/dotdirdeps.h @@ -0,0 +1,51 @@ +/****************************************************************************** +* +* Copyright (C) 1997-2019 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. +* +* Documents produced by Doxygen are derivative works derived from the +* input used in their production; they are not affected by this license. +* +*/ + +#ifndef DOTDIRDEPS_H +#define DOTDIRDEPS_H + +#include "dotgraph.h" +#include "dirdef.h" + +/** Representation of an directory dependency graph */ +class DotDirDeps : public DotGraph +{ + public: + DotDirDeps(const DirDef *dir); + ~DotDirDeps(); + bool isTrivial() const; + QCString writeGraph(FTextStream &out, + GraphOutputFormat gf, + EmbeddedOutputFormat ef, + const char *path, + const char *fileName, + const char *relPath, + bool writeImageMap=TRUE, + int graphId=-1, + bool linkRelations=TRUE); + + protected: + virtual QCString getBaseName() const; + virtual QCString getMapLabel() const; + virtual void computeTheGraph(); + virtual QCString getImgAltText() const; + + private: + const DirDef *m_dir; + + bool m_linkRelations; +}; + +#endif diff --git a/src/dotfilepatcher.cpp b/src/dotfilepatcher.cpp new file mode 100644 index 0000000..91b7c78 --- /dev/null +++ b/src/dotfilepatcher.cpp @@ -0,0 +1,539 @@ +/****************************************************************************** +* +* Copyright (C) 1997-2019 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. +* +* Documents produced by Doxygen are derivative works derived from the +* input used in their production; they are not affected by this license. +* +*/ + +#include "dotfilepatcher.h" + +#include "qstring.h" +#include "config.h" +#include "qdir.h" +#include "message.h" +#include "ftextstream.h" +#include "docparser.h" +#include "doxygen.h" +#include "util.h" +#include "dot.h" + +static const char svgZoomHeader[] = +"<svg id=\"main\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" xml:space=\"preserve\" onload=\"init(evt)\">\n" +"<style type=\"text/css\"><![CDATA[\n" +".edge:hover path { stroke: red; }\n" +".edge:hover polygon { stroke: red; fill: red; }\n" +"]]></style>\n" +"<script type=\"text/javascript\"><![CDATA[\n" +"var edges = document.getElementsByTagName('g');\n" +"if (edges && edges.length) {\n" +" for (var i=0;i<edges.length;i++) {\n" +" if (edges[i].id.substr(0,4)=='edge') {\n" +" edges[i].setAttribute('class','edge');\n" +" }\n" +" }\n" +"}\n" +"]]></script>\n" +" <defs>\n" +" <circle id=\"rim\" cx=\"0\" cy=\"0\" r=\"7\"/>\n" +" <circle id=\"rim2\" cx=\"0\" cy=\"0\" r=\"3.5\"/>\n" +" <g id=\"zoomPlus\">\n" +" <use xlink:href=\"#rim\" fill=\"#404040\">\n" +" <set attributeName=\"fill\" to=\"#808080\" begin=\"zoomplus.mouseover\" end=\"zoomplus.mouseout\"/>\n" +" </use>\n" +" <path d=\"M-4,0h8M0,-4v8\" fill=\"none\" stroke=\"white\" stroke-width=\"1.5\" pointer-events=\"none\"/>\n" +" </g>\n" +" <g id=\"zoomMin\">\n" +" <use xlink:href=\"#rim\" fill=\"#404040\">\n" +" <set attributeName=\"fill\" to=\"#808080\" begin=\"zoomminus.mouseover\" end=\"zoomminus.mouseout\"/>\n" +" </use>\n" +" <path d=\"M-4,0h8\" fill=\"none\" stroke=\"white\" stroke-width=\"1.5\" pointer-events=\"none\"/>\n" +" </g>\n" +" <g id=\"dirArrow\">\n" +" <path fill=\"none\" stroke=\"white\" stroke-width=\"1.5\" d=\"M0,-3.0v7 M-2.5,-0.5L0,-3.0L2.5,-0.5\"/>\n" +" </g>\n" +" <g id=\"resetDef\">\n" +" <use xlink:href=\"#rim2\" fill=\"#404040\">\n" +" <set attributeName=\"fill\" to=\"#808080\" begin=\"reset.mouseover\" end=\"reset.mouseout\"/>\n" +" </use>\n" +" </g>\n" +" </defs>\n" +"\n" +"<script type=\"text/javascript\">\n" +; + +static const char svgZoomFooter[] = +// navigation panel +" <g id=\"navigator\" transform=\"translate(0 0)\" fill=\"#404254\">\n" +" <rect fill=\"#f2f5e9\" fill-opacity=\"0.5\" stroke=\"#606060\" stroke-width=\".5\" x=\"0\" y=\"0\" width=\"60\" height=\"60\"/>\n" +// zoom in +" <use id=\"zoomplus\" xlink:href=\"#zoomPlus\" x=\"17\" y=\"9\" onmousedown=\"handleZoom(evt,'in')\"/>\n" +// zoom out +" <use id=\"zoomminus\" xlink:href=\"#zoomMin\" x=\"42\" y=\"9\" onmousedown=\"handleZoom(evt,'out')\"/>\n" +// reset zoom +" <use id=\"reset\" xlink:href=\"#resetDef\" x=\"30\" y=\"36\" onmousedown=\"handleReset()\"/>\n" +// arrow up +" <g id=\"arrowUp\" xlink:href=\"#dirArrow\" transform=\"translate(30 24)\" onmousedown=\"handlePan(0,-1)\">\n" +" <use xlink:href=\"#rim\" fill=\"#404040\">\n" +" <set attributeName=\"fill\" to=\"#808080\" begin=\"arrowUp.mouseover\" end=\"arrowUp.mouseout\"/>\n" +" </use>\n" +" <path fill=\"none\" stroke=\"white\" stroke-width=\"1.5\" d=\"M0,-3.0v7 M-2.5,-0.5L0,-3.0L2.5,-0.5\"/>\n" +" </g>\n" +// arrow right +" <g id=\"arrowRight\" xlink:href=\"#dirArrow\" transform=\"rotate(90) translate(36 -43)\" onmousedown=\"handlePan(1,0)\">\n" +" <use xlink:href=\"#rim\" fill=\"#404040\">\n" +" <set attributeName=\"fill\" to=\"#808080\" begin=\"arrowRight.mouseover\" end=\"arrowRight.mouseout\"/>\n" +" </use>\n" +" <path fill=\"none\" stroke=\"white\" stroke-width=\"1.5\" d=\"M0,-3.0v7 M-2.5,-0.5L0,-3.0L2.5,-0.5\"/>\n" +" </g>\n" +// arrow down +" <g id=\"arrowDown\" xlink:href=\"#dirArrow\" transform=\"rotate(180) translate(-30 -48)\" onmousedown=\"handlePan(0,1)\">\n" +" <use xlink:href=\"#rim\" fill=\"#404040\">\n" +" <set attributeName=\"fill\" to=\"#808080\" begin=\"arrowDown.mouseover\" end=\"arrowDown.mouseout\"/>\n" +" </use>\n" +" <path fill=\"none\" stroke=\"white\" stroke-width=\"1.5\" d=\"M0,-3.0v7 M-2.5,-0.5L0,-3.0L2.5,-0.5\"/>\n" +" </g>\n" +// arrow left +" <g id=\"arrowLeft\" xlink:href=\"#dirArrow\" transform=\"rotate(270) translate(-36 17)\" onmousedown=\"handlePan(-1,0)\">\n" +" <use xlink:href=\"#rim\" fill=\"#404040\">\n" +" <set attributeName=\"fill\" to=\"#808080\" begin=\"arrowLeft.mouseover\" end=\"arrowLeft.mouseout\"/>\n" +" </use>\n" +" <path fill=\"none\" stroke=\"white\" stroke-width=\"1.5\" d=\"M0,-3.0v7 M-2.5,-0.5L0,-3.0L2.5,-0.5\"/>\n" +" </g>\n" +" </g>\n" +// link to original SVG +" <svg viewBox=\"0 0 15 15\" width=\"100%\" height=\"30px\" preserveAspectRatio=\"xMaxYMin meet\">\n" +" <g id=\"arrow_out\" transform=\"scale(0.3 0.3)\">\n" +" <a xlink:href=\"$orgname\" target=\"_base\">\n" +" <rect id=\"button\" ry=\"5\" rx=\"5\" y=\"6\" x=\"6\" height=\"38\" width=\"38\"\n" +" fill=\"#f2f5e9\" fill-opacity=\"0.5\" stroke=\"#606060\" stroke-width=\"1.0\"/>\n" +" <path id=\"arrow\"\n" +" d=\"M 11.500037,31.436501 C 11.940474,20.09759 22.043105,11.32322 32.158766,21.979434 L 37.068811,17.246167 C 37.068811,17.246167 37.088388,32 37.088388,32 L 22.160133,31.978069 C 22.160133,31.978069 26.997745,27.140456 26.997745,27.140456 C 18.528582,18.264221 13.291696,25.230495 11.500037,31.436501 z\"\n" +" style=\"fill:#404040;\"/>\n" +" </a>\n" +" </g>\n" +" </svg>\n" +"</svg>\n" +; + +static QCString replaceRef(const QCString &buf,const QCString relPath, + bool urlOnly,const QCString &context,const QCString &target=QCString()) +{ + // search for href="...", store ... part in link + QCString href = "href"; + //bool isXLink=FALSE; + int len = 6; + int indexS = buf.find("href=\""), indexE; + bool setTarget = FALSE; + if (indexS>5 && buf.find("xlink:href=\"")!=-1) // XLink href (for SVG) + { + indexS-=6; + len+=6; + href.prepend("xlink:"); + //isXLink=TRUE; + } + if (indexS>=0 && (indexE=buf.find('"',indexS+len))!=-1) + { + QCString link = buf.mid(indexS+len,indexE-indexS-len); + QCString result; + if (urlOnly) // for user defined dot graphs + { + if (link.left(5)=="\\ref " || link.left(5)=="@ref ") // \ref url + { + result=href+"=\""; + // fake ref node to resolve the url + DocRef *df = new DocRef( (DocNode*) 0, link.mid(5), context ); + result+=externalRef(relPath,df->ref(),TRUE); + if (!df->file().isEmpty()) + result += df->file().data() + Doxygen::htmlFileExtension; + if (!df->anchor().isEmpty()) + result += "#" + df->anchor(); + delete df; + result += "\""; + } + else + { + result = href+"=\"" + link + "\""; + } + } + else // ref$url (external ref via tag file), or $url (local ref) + { + int marker = link.find('$'); + if (marker!=-1) + { + QCString ref = link.left(marker); + QCString url = link.mid(marker+1); + if (!ref.isEmpty()) + { + result = externalLinkTarget(); + if (result != "") setTarget = TRUE; + } + result+= href+"=\""; + result+=externalRef(relPath,ref,TRUE); + result+= url + "\""; + } + else // should not happen, but handle properly anyway + { + result = href+"=\"" + link + "\""; + } + } + if (!target.isEmpty() && !setTarget) + { + result+=" target=\""+target+"\""; + } + QCString leftPart = buf.left(indexS); + QCString rightPart = buf.mid(indexE+1); + return leftPart + result + rightPart; + } + else + { + return buf; + } +} + +/*! converts the rectangles in a client site image map into a stream +* \param t the stream to which the result is written. +* \param mapName the name of the map file. +* \param relPath the relative path to the root of the output directory +* (used in case CREATE_SUBDIRS is enabled). +* \param urlOnly if FALSE the url field in the map contains an external +* references followed by a $ and then the URL. +* \param context the context (file, class, or namespace) in which the +* map file was found +* \returns TRUE if successful. +*/ +bool convertMapFile(FTextStream &t,const char *mapName, + const QCString relPath, bool urlOnly, + const QCString &context) +{ + QFile f(mapName); + if (!f.open(IO_ReadOnly)) + { + err("problems opening map file %s for inclusion in the docs!\n" + "If you installed Graphviz/dot after a previous failing run, \n" + "try deleting the output directory and rerun doxygen.\n",mapName); + return FALSE; + } + const int maxLineLen=10240; + while (!f.atEnd()) // foreach line + { + QCString buf(maxLineLen); + int numBytes = f.readLine(buf.rawData(),maxLineLen); + if (numBytes>0) + { + buf.resize(numBytes+1); + + if (buf.left(5)=="<area") + { + QCString replBuf = replaceRef(buf,relPath,urlOnly,context); + // strip id="..." from replBuf since the id's are not needed and not unique. + int indexS = replBuf.find("id=\""), indexE; + if (indexS>0 && (indexE=replBuf.find('"',indexS+4))!=-1) + { + t << replBuf.left(indexS-1) << replBuf.right(replBuf.length() - indexE - 1); + } + else + { + t << replBuf; + } + } + } + } + return TRUE; +} + +DotFilePatcher::DotFilePatcher(const char *patchFile) + : m_patchFile(patchFile) +{ + m_maps.setAutoDelete(TRUE); +} + +QCString DotFilePatcher::file() const +{ + return m_patchFile; +} + +int DotFilePatcher::addMap(const QCString &mapFile,const QCString &relPath, + bool urlOnly,const QCString &context,const QCString &label) +{ + int id = m_maps.count(); + Map *map = new Map; + map->mapFile = mapFile; + map->relPath = relPath; + map->urlOnly = urlOnly; + map->context = context; + map->label = label; + map->zoomable = FALSE; + map->graphId = -1; + m_maps.append(map); + return id; +} + +int DotFilePatcher::addFigure(const QCString &baseName, + const QCString &figureName,bool heightCheck) +{ + int id = m_maps.count(); + Map *map = new Map; + map->mapFile = figureName; + map->urlOnly = heightCheck; + map->label = baseName; + map->zoomable = FALSE; + map->graphId = -1; + m_maps.append(map); + return id; +} + +int DotFilePatcher::addSVGConversion(const QCString &relPath,bool urlOnly, + const QCString &context,bool zoomable, + int graphId) +{ + int id = m_maps.count(); + Map *map = new Map; + map->relPath = relPath; + map->urlOnly = urlOnly; + map->context = context; + map->zoomable = zoomable; + map->graphId = graphId; + m_maps.append(map); + return id; +} + +int DotFilePatcher::addSVGObject(const QCString &baseName, + const QCString &absImgName, + const QCString &relPath) +{ + int id = m_maps.count(); + Map *map = new Map; + map->mapFile = absImgName; + map->relPath = relPath; + map->label = baseName; + map->zoomable = FALSE; + map->graphId = -1; + m_maps.append(map); + return id; +} + +bool DotFilePatcher::run() +{ + //printf("DotFilePatcher::run(): %s\n",m_patchFile.data()); + bool interactiveSVG_local = Config_getBool(INTERACTIVE_SVG); + bool isSVGFile = m_patchFile.right(4)==".svg"; + int graphId = -1; + QCString relPath; + if (isSVGFile) + { + Map *map = m_maps.at(0); // there is only one 'map' for a SVG file + interactiveSVG_local = interactiveSVG_local && map->zoomable; + graphId = map->graphId; + relPath = map->relPath; + //printf("DotFilePatcher::addSVGConversion: file=%s zoomable=%d\n", + // m_patchFile.data(),map->zoomable); + } + QString tmpName = QString::fromUtf8(m_patchFile+".tmp"); + QString patchFile = QString::fromUtf8(m_patchFile); + if (!QDir::current().rename(patchFile,tmpName)) + { + err("Failed to rename file %s to %s!\n",m_patchFile.data(),tmpName.data()); + return FALSE; + } + QFile fi(tmpName); + QFile fo(patchFile); + if (!fi.open(IO_ReadOnly)) + { + err("problem opening file %s for patching!\n",tmpName.data()); + QDir::current().rename(tmpName,patchFile); + return FALSE; + } + if (!fo.open(IO_WriteOnly)) + { + err("problem opening file %s for patching!\n",m_patchFile.data()); + QDir::current().rename(tmpName,patchFile); + return FALSE; + } + FTextStream t(&fo); + const int maxLineLen=100*1024; + int lineNr=1; + int width,height; + bool insideHeader=FALSE; + bool replacedHeader=FALSE; + bool foundSize=FALSE; + while (!fi.atEnd()) // foreach line + { + QCString line(maxLineLen); + int numBytes = fi.readLine(line.rawData(),maxLineLen); + if (numBytes<=0) + { + break; + } + line.resize(numBytes+1); + + //printf("line=[%s]\n",line.stripWhiteSpace().data()); + int i; + ASSERT(numBytes<maxLineLen); + if (isSVGFile) + { + if (interactiveSVG_local) + { + if (line.find("<svg")!=-1 && !replacedHeader) + { + int count; + count = sscanf(line.data(),"<svg width=\"%dpt\" height=\"%dpt\"",&width,&height); + //printf("width=%d height=%d\n",width,height); + foundSize = count==2 && (width>500 || height>450); + if (foundSize) insideHeader=TRUE; + } + else if (insideHeader && !replacedHeader && line.find("<title>")!=-1) + { + if (foundSize) + { + // insert special replacement header for interactive SVGs + t << "<!--zoomable " << height << " -->\n"; + t << svgZoomHeader; + t << "var viewWidth = " << width << ";\n"; + t << "var viewHeight = " << height << ";\n"; + if (graphId>=0) + { + t << "var sectionId = 'dynsection-" << graphId << "';\n"; + } + t << "</script>\n"; + t << "<script xlink:href=\"" << relPath << "svgpan.js\"/>\n"; + t << "<svg id=\"graph\" class=\"graph\">\n"; + t << "<g id=\"viewport\">\n"; + } + insideHeader=FALSE; + replacedHeader=TRUE; + } + } + if (!insideHeader || !foundSize) // copy SVG and replace refs, + // unless we are inside the header of the SVG. + // Then we replace it with another header. + { + Map *map = m_maps.at(0); // there is only one 'map' for a SVG file + t << replaceRef(line,map->relPath,map->urlOnly,map->context,"_top"); + } + } + else if ((i=line.find("<!-- SVG"))!=-1 || (i=line.find("[!-- SVG"))!=-1) + { + //printf("Found marker at %d\n",i); + int mapId=-1; + t << line.left(i); + int n = sscanf(line.data()+i+1,"!-- SVG %d",&mapId); + if (n==1 && mapId>=0 && mapId<(int)m_maps.count()) + { + int e = QMAX(line.find("--]"),line.find("-->")); + Map *map = m_maps.at(mapId); + //printf("DotFilePatcher::writeSVGFigure: file=%s zoomable=%d\n", + // m_patchFile.data(),map->zoomable); + if (!writeSVGFigureLink(t,map->relPath,map->label,map->mapFile)) + { + err("Problem extracting size from SVG file %s\n",map->mapFile.data()); + } + if (e!=-1) t << line.mid(e+3); + } + else // error invalid map id! + { + err("Found invalid SVG id in file %s!\n",m_patchFile.data()); + t << line.mid(i); + } + } + else if ((i=line.find("<!-- MAP"))!=-1) + { + int mapId=-1; + t << line.left(i); + int n = sscanf(line.data()+i,"<!-- MAP %d",&mapId); + if (n==1 && mapId>=0 && mapId<(int)m_maps.count()) + { + QGString result; + FTextStream tt(&result); + Map *map = m_maps.at(mapId); + //printf("patching MAP %d in file %s with contents of %s\n", + // mapId,m_patchFile.data(),map->mapFile.data()); + convertMapFile(tt,map->mapFile,map->relPath,map->urlOnly,map->context); + if (!result.isEmpty()) + { + t << "<map name=\"" << map->label << "\" id=\"" << map->label << "\">" << endl; + t << result; + t << "</map>" << endl; + } + } + else // error invalid map id! + { + err("Found invalid MAP id in file %s!\n",m_patchFile.data()); + t << line.mid(i); + } + } + else if ((i=line.find("% FIG"))!=-1) + { + int mapId=-1; + int n = sscanf(line.data()+i+2,"FIG %d",&mapId); + //printf("line='%s' n=%d\n",line.data()+i,n); + if (n==1 && mapId>=0 && mapId<(int)m_maps.count()) + { + Map *map = m_maps.at(mapId); + //printf("patching FIG %d in file %s with contents of %s\n", + // mapId,m_patchFile.data(),map->mapFile.data()); + if (!DotGraph::writeVecGfxFigure(t,map->label,map->mapFile)) + { + err("problem writing FIG %d figure!\n",mapId); + return FALSE; + } + } + else // error invalid map id! + { + err("Found invalid bounding FIG %d in file %s!\n",mapId,m_patchFile.data()); + t << line; + } + } + else + { + t << line; + } + lineNr++; + } + fi.close(); + if (isSVGFile && interactiveSVG_local && replacedHeader) + { + QCString orgName=m_patchFile.left(m_patchFile.length()-4)+"_org.svg"; + t << substitute(svgZoomFooter,"$orgname",stripPath(orgName)); + fo.close(); + // keep original SVG file so we can refer to it, we do need to replace + // dummy link by real ones + QFile fi(tmpName); + QFile fo(orgName); + if (!fi.open(IO_ReadOnly)) + { + err("problem opening file %s for reading!\n",tmpName.data()); + return FALSE; + } + if (!fo.open(IO_WriteOnly)) + { + err("problem opening file %s for writing!\n",orgName.data()); + return FALSE; + } + FTextStream t(&fo); + while (!fi.atEnd()) // foreach line + { + QCString line(maxLineLen); + int numBytes = fi.readLine(line.rawData(),maxLineLen); + if (numBytes<=0) + { + break; + } + line.resize(numBytes+1); + Map *map = m_maps.at(0); // there is only one 'map' for a SVG file + t << replaceRef(line,map->relPath,map->urlOnly,map->context,"_top"); + } + fi.close(); + fo.close(); + } + // remove temporary file + QDir::current().remove(tmpName); + return TRUE; +} diff --git a/src/dotfilepatcher.h b/src/dotfilepatcher.h new file mode 100644 index 0000000..dd5c511 --- /dev/null +++ b/src/dotfilepatcher.h @@ -0,0 +1,53 @@ +/****************************************************************************** +* +* Copyright (C) 1997-2019 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. +* +* Documents produced by Doxygen are derivative works derived from the +* input used in their production; they are not affected by this license. +* +*/ + +#ifndef DOTFILEPATCHER_H +#define DOTFILEPATCHER_H + +#include "qcstring.h" +#include "qlist.h" + +/** Helper class to insert a set of map file into an output file */ +class DotFilePatcher +{ + public: + DotFilePatcher(const char *patchFile); + int addMap(const QCString &mapFile,const QCString &relPath, + bool urlOnly,const QCString &context,const QCString &label); + int addFigure(const QCString &baseName, + const QCString &figureName,bool heightCheck); + int addSVGConversion(const QCString &relPath,bool urlOnly, + const QCString &context,bool zoomable,int graphId); + int addSVGObject(const QCString &baseName, const QCString &figureName, + const QCString &relPath); + bool run(); + QCString file() const; + + private: + struct Map + { + QCString mapFile; + QCString relPath; + bool urlOnly; + QCString context; + QCString label; + bool zoomable; + int graphId; + }; + QList<Map> m_maps; + QCString m_patchFile; +}; + +#endif diff --git a/src/dotgfxhierarchytable.cpp b/src/dotgfxhierarchytable.cpp new file mode 100644 index 0000000..0082b7e --- /dev/null +++ b/src/dotgfxhierarchytable.cpp @@ -0,0 +1,302 @@ +/****************************************************************************** +* +* Copyright (C) 1997-2019 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. +* +* Documents produced by Doxygen are derivative works derived from the +* input used in their production; they are not affected by this license. +* +*/ + +#include "dotgfxhierarchytable.h" + +#include "language.h" +#include "util.h" +#include "message.h" +#include "doxygen.h" +#include "classlist.h" + +#define OPTIMIZE_OUTPUT_SLICE Config_getBool(OPTIMIZE_OUTPUT_SLICE) + +QCString DotGfxHierarchyTable::getBaseName() const +{ + QCString baseName; + if (m_prefix.isEmpty()) + baseName.sprintf("inherit_graph_%d", m_graphId); + else + baseName.sprintf("%sinherit_graph_%d",m_prefix.data(), m_graphId); + return baseName; +} + +void DotGfxHierarchyTable::computeTheGraph() +{ + QListIterator<DotNode> dnli2(*m_rootNodes); + DotNode *node; + + FTextStream md5stream(&m_theGraph); + writeGraphHeader(md5stream,theTranslator->trGraphicalHierarchy()); + md5stream << " rankdir=\"LR\";" << endl; + for (dnli2.toFirst();(node=dnli2.current());++dnli2) + { + if (node->subgraphId()==m_rootSubgraphNode->subgraphId()) + { + node->clearWriteFlag(); + } + } + for (dnli2.toFirst();(node=dnli2.current());++dnli2) + { + if (node->subgraphId()==m_rootSubgraphNode->subgraphId()) + { + node->write(md5stream,Hierarchy,GOF_BITMAP,FALSE,TRUE,TRUE); + } + } + writeGraphFooter(md5stream); + +} + +QCString DotGfxHierarchyTable::getMapLabel() const +{ + return escapeCharsInString(m_rootSubgraphNode->label(),FALSE); +} + +void DotGfxHierarchyTable::createGraph(DotNode *n,FTextStream &out, + const char *path,const char *fileName,int id) +{ + m_rootSubgraphNode = n; + m_graphId = id; + m_noDivTag = TRUE; + m_zoomable = FALSE; + DotGraph::writeGraph(out, GOF_BITMAP, EOF_Html, path, fileName, "", TRUE, 0); +} + +void DotGfxHierarchyTable::writeGraph(FTextStream &out, + const char *path,const char *fileName) +{ + //printf("DotGfxHierarchyTable::writeGraph(%s)\n",name); + //printf("m_rootNodes=%p count=%d\n",m_rootNodes,m_rootNodes->count()); + + if (m_rootSubgraphs->count()==0) return; + + QDir d(path); + // store the original directory + if (!d.exists()) + { + err("Output dir %s does not exist!\n",path); exit(1); + } + + // put each connected subgraph of the hierarchy in a row of the HTML output + out << "<table border=\"0\" cellspacing=\"10\" cellpadding=\"0\">" << endl; + + QListIterator<DotNode> dnli(*m_rootSubgraphs); + DotNode *n; + int count=0; + for (dnli.toFirst();(n=dnli.current());++dnli) + { + out << "<tr><td>"; + createGraph(n,out,path,fileName,count++); + out << "</td></tr>" << endl; + } + out << "</table>" << endl; +} + +void DotGfxHierarchyTable::addHierarchy(DotNode *n,const ClassDef *cd,bool hideSuper) +{ + //printf("addHierarchy `%s' baseClasses=%d\n",cd->name().data(),cd->baseClasses()->count()); + if (cd->subClasses()) + { + BaseClassListIterator bcli(*cd->subClasses()); + BaseClassDef *bcd; + for ( ; (bcd=bcli.current()) ; ++bcli ) + { + ClassDef *bClass=bcd->classDef; + //printf(" Trying sub class=`%s' usedNodes=%d\n",bClass->name().data(),m_usedNodes->count()); + if (bClass->isVisibleInHierarchy() && hasVisibleRoot(bClass->baseClasses())) + { + DotNode *bn; + //printf(" Node `%s' Found visible class=`%s'\n",n->label().data(), + // bClass->name().data()); + if ((bn=m_usedNodes->find(bClass->name()))) // node already present + { + if (n->children()==0 || n->children()->findRef(bn)==-1) // no arrow yet + { + n->addChild(bn,bcd->prot); + bn->addParent(n); + //printf(" Adding node %s to existing base node %s (c=%d,p=%d)\n", + // n->label().data(), + // bn->label().data(), + // bn->children() ? bn->children()->count() : 0, + // bn->parents() ? bn->parents()->count() : 0 + // ); + } + //else + //{ + // printf(" Class already has an arrow!\n"); + //} + } + else + { + QCString tmp_url=""; + if (bClass->isLinkable() && !bClass->isHidden()) + { + tmp_url=bClass->getReference()+"$"+bClass->getOutputFileBase(); + if (!bClass->anchor().isEmpty()) + { + tmp_url+="#"+bClass->anchor(); + } + } + QCString tooltip = bClass->briefDescriptionAsTooltip(); + bn = new DotNode(getNextNodeNumber(), + bClass->displayName(), + tooltip, + tmp_url.data() + ); + n->addChild(bn,bcd->prot); + bn->addParent(n); + //printf(" Adding node %s to new base node %s (c=%d,p=%d)\n", + // n->label().data(), + // bn->label().data(), + // bn->children() ? bn->children()->count() : 0, + // bn->parents() ? bn->parents()->count() : 0 + // ); + //printf(" inserting %s (%p)\n",bClass->name().data(),bn); + m_usedNodes->insert(bClass->name(),bn); // add node to the used list + } + if (!bClass->isVisited() && !hideSuper && bClass->subClasses()) + { + bool wasVisited=bClass->isVisited(); + bClass->setVisited(TRUE); + addHierarchy(bn,bClass,wasVisited); + } + } + } + } + //printf("end addHierarchy\n"); +} + +void DotGfxHierarchyTable::addClassList(const ClassSDict *cl) +{ + ClassSDict::Iterator cli(*cl); + ClassDef *cd; + for (cli.toLast();(cd=cli.current());--cli) + { + //printf("Trying %s subClasses=%d\n",cd->name().data(),cd->subClasses()->count()); + if (cd->getLanguage()==SrcLangExt_VHDL && + (VhdlDocGen::VhdlClasses)cd->protection()!=VhdlDocGen::ENTITYCLASS + ) + { + continue; + } + if (OPTIMIZE_OUTPUT_SLICE && cd->compoundType() != m_classType) + { + continue; + } + if (!hasVisibleRoot(cd->baseClasses()) && + cd->isVisibleInHierarchy() + ) // root node in the forest + { + QCString tmp_url=""; + if (cd->isLinkable() && !cd->isHidden()) + { + tmp_url=cd->getReference()+"$"+cd->getOutputFileBase(); + if (!cd->anchor().isEmpty()) + { + tmp_url+="#"+cd->anchor(); + } + } + //printf("Inserting root class %s\n",cd->name().data()); + QCString tooltip = cd->briefDescriptionAsTooltip(); + DotNode *n = new DotNode(getNextNodeNumber(), + cd->displayName(), + tooltip, + tmp_url.data()); + + //m_usedNodes->clear(); + m_usedNodes->insert(cd->name(),n); + m_rootNodes->insert(0,n); + if (!cd->isVisited() && cd->subClasses()) + { + addHierarchy(n,cd,cd->isVisited()); + cd->setVisited(TRUE); + } + } + } +} + +DotGfxHierarchyTable::DotGfxHierarchyTable(const char *prefix,ClassDef::CompoundType ct) + : m_prefix(prefix) + , m_classType(ct) +{ + m_rootNodes = new QList<DotNode>; + m_usedNodes = new QDict<DotNode>(1009); + m_usedNodes->setAutoDelete(TRUE); + m_rootSubgraphs = new DotNodeList; + + // build a graph with each class as a node and the inheritance relations + // as edges + initClassHierarchy(Doxygen::classSDict); + initClassHierarchy(Doxygen::hiddenClasses); + addClassList(Doxygen::classSDict); + addClassList(Doxygen::hiddenClasses); + // m_usedNodes now contains all nodes in the graph + + // color the graph into a set of independent subgraphs + bool done=FALSE; + int curColor=0; + QListIterator<DotNode> dnli(*m_rootNodes); + while (!done) // there are still nodes to color + { + DotNode *n; + done=TRUE; // we are done unless there are still uncolored nodes + for (dnli.toLast();(n=dnli.current());--dnli) + { + if (n->subgraphId()==-1) // not yet colored + { + //printf("Starting at node %s (%p): %d\n",n->label().data(),n,curColor); + done=FALSE; // still uncolored nodes + n->setSubgraphId(curColor); + n->markAsVisible(); + n->colorConnectedNodes(curColor); + curColor++; + const DotNode *dn=n->findDocNode(); + if (dn!=0) + m_rootSubgraphs->inSort(dn); + else + m_rootSubgraphs->inSort(n); + } + } + } + + //printf("Number of independent subgraphs: %d\n",curColor); + QListIterator<DotNode> dnli2(*m_rootSubgraphs); + DotNode *n; + for (dnli2.toFirst();(n=dnli2.current());++dnli2) + { + //printf("Node %s color=%d (c=%d,p=%d)\n", + // n->label().data(),n->m_subgraphId, + // n->children()?n->children()->count():0, + // n->parents()?n->parents()->count():0); + int number=0; + n->renumberNodes(number); + } +} + +DotGfxHierarchyTable::~DotGfxHierarchyTable() +{ + //printf("DotGfxHierarchyTable::~DotGfxHierarchyTable\n"); + + //QDictIterator<DotNode> di(*m_usedNodes); + //DotNode *n; + //for (;(n=di.current());++di) + //{ + // printf("Node %p: %s\n",n,n->label().data()); + //} + + delete m_rootNodes; + delete m_usedNodes; + delete m_rootSubgraphs; +} diff --git a/src/dotgfxhierarchytable.h b/src/dotgfxhierarchytable.h new file mode 100644 index 0000000..5a5bcad --- /dev/null +++ b/src/dotgfxhierarchytable.h @@ -0,0 +1,55 @@ +/****************************************************************************** +* +* Copyright (C) 1997-2019 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. +* +* Documents produced by Doxygen are derivative works derived from the +* input used in their production; they are not affected by this license. +* +*/ + +#ifndef DOTGFXHIERARCHYTABLE_H +#define DOTGFXHIERARCHYTABLE_H + +#include "classdef.h" +#include "ftextstream.h" + +#include "dotgraph.h" +#include "dotnode.h" + +/** Represents a graphical class hierarchy */ +class DotGfxHierarchyTable : public DotGraph +{ + public: + DotGfxHierarchyTable(const char *prefix="",ClassDef::CompoundType ct=ClassDef::Class); + ~DotGfxHierarchyTable(); + void createGraph(DotNode *rootNode,FTextStream &t,const char *path, + const char *fileName,int id); + void writeGraph(FTextStream &t,const char *path, const char *fileName); + const DotNodeList *subGraphs() const { return m_rootSubgraphs; } + + protected: + virtual QCString getBaseName() const; + virtual QCString getMapLabel() const; + virtual void computeTheGraph(); + + private: + void addHierarchy(DotNode *n,const ClassDef *cd,bool hide); + void addClassList(const ClassSDict *cl); + + int m_graphId; + QCString m_prefix; + ClassDef::CompoundType m_classType; + QList<DotNode> *m_rootNodes; + QDict<DotNode> *m_usedNodes; + DotNodeList *m_rootSubgraphs; + DotNode * m_rootSubgraphNode; +}; + + +#endif diff --git a/src/dotgraph.cpp b/src/dotgraph.cpp new file mode 100644 index 0000000..ca6bcca --- /dev/null +++ b/src/dotgraph.cpp @@ -0,0 +1,400 @@ +/****************************************************************************** +* +* Copyright (C) 1997-2019 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. +* +* Documents produced by Doxygen are derivative works derived from the +* input used in their production; they are not affected by this license. +* +*/ + +#include "config.h" +#include "doxygen.h" +#include "index.h" +#include "md5.h" +#include "message.h" +#include "util.h" + +#include "dot.h" +#include "dotrunner.h" +#include "dotgraph.h" +#include "dotnode.h" + +#define MAP_CMD "cmapx" + +QCString DotGraph::DOT_FONTNAME; // will be initialized in initDot +int DotGraph::DOT_FONTSIZE; // will be initialized in initDot + +/*! Checks if a file "baseName".md5 exists. If so the contents +* are compared with \a md5. If equal FALSE is returned. +* The .md5 is created or updated after successful creation of the output file. +*/ +static bool checkMd5Signature(const QCString &baseName, + const QCString &md5) +{ + QFile f(baseName+".md5"); + if (f.open(IO_ReadOnly)) + { + // read checksum + QCString md5stored(33); + int bytesRead=f.readBlock(md5stored.rawData(),32); + md5stored[32]='\0'; + // compare checksum + if (bytesRead==32 && md5==md5stored) + { + // bail out if equal + return FALSE; + } + } + f.close(); + return TRUE; +} + +static bool checkDeliverables(const QCString &file1, + const QCString &file2=QCString()) +{ + bool file1Ok = TRUE; + bool file2Ok = TRUE; + if (!file1.isEmpty()) + { + QFileInfo fi(file1); + file1Ok = (fi.exists() && fi.size()>0); + } + if (!file2.isEmpty()) + { + QFileInfo fi(file2); + file2Ok = (fi.exists() && fi.size()>0); + } + return file1Ok && file2Ok; +} + +static void removeDotGraph(const QCString &dotName) +{ + if (Config_getBool(DOT_CLEANUP)) + { + QDir d; + d.remove(dotName); + } +} + +static bool insertMapFile(FTextStream &out,const QCString &mapFile, + const QCString &relPath,const QCString &mapLabel) +{ + QFileInfo fi(mapFile); + if (fi.exists() && fi.size()>0) // reuse existing map file + { + QGString tmpstr; + FTextStream tmpout(&tmpstr); + convertMapFile(tmpout,mapFile,relPath,FALSE); + if (!tmpstr.isEmpty()) + { + out << "<map name=\"" << mapLabel << "\" id=\"" << mapLabel << "\">" << endl; + out << tmpstr; + out << "</map>" << endl; + } + return TRUE; + } + return FALSE; // no map file yet, need to generate it +} + +//-------------------------------------------------------------------- + +QCString DotGraph::IMG_EXT; + +QCString DotGraph::imgName() const +{ + return m_baseName + ((m_graphFormat == GOF_BITMAP) ? + ("." + IMG_EXT) : (Config_getBool(USE_PDFLATEX) ? ".pdf" : ".eps")); +} + +QCString DotGraph::writeGraph( + FTextStream& t, // output stream for the code file (html, ...) + GraphOutputFormat gf, // bitmap(png/svg) or ps(eps/pdf) + EmbeddedOutputFormat ef, // html, latex, ... + const char* path, // output folder + const char* fileName, // name of the code file (for code patcher) + const char* relPath, // output folder relativ to code file + bool generateImageMap, // in case of bitmap, shall there be code generated? + int graphId) // number of this graph in the current code, used in svg code +{ + m_graphFormat = gf; + m_textFormat = ef; + m_dir = QDir(path); + m_fileName = fileName; + m_relPath = relPath; + m_generateImageMap = generateImageMap; + m_graphId = graphId; + + m_absPath = QCString(m_dir.absPath().data()) + "/"; + m_baseName = getBaseName(); + + computeTheGraph(); + + m_regenerate = prepareDotFile(); + + if (!m_doNotAddImageToIndex) Doxygen::indexList->addImageFile(imgName()); + + generateCode(t); + + return m_baseName; +} + +bool DotGraph::prepareDotFile() +{ + if (!m_dir.exists()) + { + err("Output dir %s does not exist!\n", m_dir.path().data()); exit(1); + } + + QCString sigStr(33); + uchar md5_sig[16]; + // calculate md5 + MD5Buffer((const unsigned char*)m_theGraph.data(), m_theGraph.length(), md5_sig); + // convert result to a string + MD5SigToString(md5_sig, sigStr.rawData(), 33); + + // already queued files are processed again in case the output format has changed + + if (!checkMd5Signature(absBaseName(), sigStr) && + checkDeliverables(absImgName(), + m_graphFormat == GOF_BITMAP && m_generateImageMap ? absMapName() : QCString() + ) + ) + { + // all needed files are there + removeDotGraph(absDotName()); + return FALSE; + } + + // need to rebuild the image + + // write .dot file because image was new or has changed + QFile f(absDotName()); + if (!f.open(IO_WriteOnly)) + { + err("Could not open file %s for writing\n",f.name().data()); + return TRUE; + } + FTextStream t(&f); + t << m_theGraph; + f.close(); + + if (m_graphFormat == GOF_BITMAP) + { + // run dot to create a bitmap image + DotRunner * dotRun = DotManager::instance()->createRunner(absDotName(), sigStr); + dotRun->addJob(Config_getEnum(DOT_IMAGE_FORMAT), absImgName()); + if (m_generateImageMap) dotRun->addJob(MAP_CMD, absMapName()); + } + else if (m_graphFormat == GOF_EPS) + { + // run dot to create a .eps image + DotRunner *dotRun = DotManager::instance()->createRunner(absDotName(), sigStr); + if (Config_getBool(USE_PDFLATEX)) + { + dotRun->addJob("pdf",absImgName()); + } + else + { + dotRun->addJob("ps",absImgName()); + } + } + return TRUE; +} + +void DotGraph::generateCode(FTextStream &t) +{ + if (m_graphFormat==GOF_BITMAP && m_textFormat==EOF_DocBook) + { + t << "<para>" << endl; + t << " <informalfigure>" << endl; + t << " <mediaobject>" << endl; + t << " <imageobject>" << endl; + t << " <imagedata"; + t << " width=\"50%\" align=\"center\" valign=\"middle\" scalefit=\"0\" fileref=\"" << m_relPath << m_baseName << "." << IMG_EXT << "\">"; + t << "</imagedata>" << endl; + t << " </imageobject>" << endl; + t << " </mediaobject>" << endl; + t << " </informalfigure>" << endl; + t << "</para>" << endl; + } + else if (m_graphFormat==GOF_BITMAP && m_generateImageMap) // produce HTML to include the image + { + if (IMG_EXT=="svg") // add link to SVG file without map file + { + if (!m_noDivTag) t << "<div class=\"center\">"; + if (m_regenerate || !writeSVGFigureLink(t,m_relPath,m_baseName,absImgName())) // need to patch the links in the generated SVG file + { + if (m_regenerate) + { + DotManager::instance()->addSVGConversion(absImgName(),m_relPath,FALSE,QCString(),m_zoomable,m_graphId); + } + int mapId = DotManager::instance()->addSVGObject(m_fileName,m_baseName,absImgName(),m_relPath); + t << "<!-- SVG " << mapId << " -->" << endl; + } + if (!m_noDivTag) t << "</div>" << endl; + } + else // add link to bitmap file with image map + { + if (!m_noDivTag) t << "<div class=\"center\">"; + t << "<img src=\"" << relImgName() << "\" border=\"0\" usemap=\"#" << getMapLabel() << "\" alt=\"" << getImgAltText() << "\"/>"; + if (!m_noDivTag) t << "</div>"; + t << endl; + if (m_regenerate || !insertMapFile(t, absMapName(), m_relPath, getMapLabel())) + { + int mapId = DotManager::instance()->addMap(m_fileName, absMapName(), m_relPath, m_urlOnly, QCString(), getMapLabel()); + t << "<!-- MAP " << mapId << " -->" << endl; + } + } + } + else if (m_graphFormat==GOF_EPS) // produce tex to include the .eps image + { + if (m_regenerate || !writeVecGfxFigure(t,m_baseName,absBaseName())) + { + int figId = DotManager::instance()->addFigure(m_fileName,m_baseName,absBaseName(),FALSE /*TRUE*/); + t << endl << "% FIG " << figId << endl; + } + } +} + +void DotGraph::writeGraphHeader(FTextStream &t,const QCString &title) +{ + t << "digraph "; + if (title.isEmpty()) + { + t << "\"Dot Graph\""; + } + else + { + t << "\"" << convertToXML(title) << "\""; + } + t << endl << "{" << endl; + if (Config_getBool(INTERACTIVE_SVG)) // insert a comment to force regeneration when this + // option is toggled + { + t << " // INTERACTIVE_SVG=YES\n"; + } + t << " // LATEX_PDF_SIZE\n"; // write placeholder for LaTeX PDF bounding box size repacement + if (Config_getBool(DOT_TRANSPARENT)) + { + t << " bgcolor=\"transparent\";" << endl; + } + t << " edge [fontname=\"" << DOT_FONTNAME << "\"," + "fontsize=\"" << DOT_FONTSIZE << "\"," + "labelfontname=\"" << DOT_FONTNAME << "\"," + "labelfontsize=\"" << DOT_FONTSIZE << "\"];\n"; + t << " node [fontname=\"" << DOT_FONTNAME << "\"," + "fontsize=\"" << DOT_FONTSIZE << "\",shape=record];\n"; +} + +void DotGraph::writeGraphFooter(FTextStream &t) +{ + t << "}" << endl; +} + +void DotGraph::computeGraph(DotNode *root, + GraphType gt, + GraphOutputFormat format, + const QCString &rank, // either "LR", "RL", or "" + bool renderParents, + bool backArrows, + const QCString &title, + QGString &graphStr) +{ + //printf("computeMd5Signature\n"); + QGString buf; + FTextStream md5stream(&buf); + writeGraphHeader(md5stream,title); + if (!rank.isEmpty()) + { + md5stream << " rankdir=\"" << rank << "\";" << endl; + } + root->clearWriteFlag(); + root->write(md5stream, gt, format, gt!=CallGraph && gt!=Dependency, TRUE, backArrows); + if (renderParents && root->parents()) + { + QListIterator<DotNode> dnli(*root->parents()); + const DotNode *pn; + for (dnli.toFirst();(pn=dnli.current());++dnli) + { + if (pn->isVisible()) + { + root->writeArrow(md5stream, // stream + gt, // graph type + format, // output format + pn, // child node + pn->edgeInfo()->at(pn->children()->findRef(root)), // edge info + FALSE, // topDown? + backArrows // point back? + ); + } + pn->write(md5stream, // stream + gt, // graph type + format, // output format + TRUE, // topDown? + FALSE, // toChildren? + backArrows // backward pointing arrows? + ); + } + } + writeGraphFooter(md5stream); + + graphStr=buf.data(); +} + +bool DotGraph::writeVecGfxFigure(FTextStream &out,const QCString &baseName, + const QCString &figureName) +{ + int width=400,height=550; + if (Config_getBool(USE_PDFLATEX)) + { + if (!DotRunner::readBoundingBox(figureName+".pdf",&width,&height,FALSE)) + { + //printf("writeVecGfxFigure()=0\n"); + return FALSE; + } + } + else + { + if (!DotRunner::readBoundingBox(figureName+".eps",&width,&height,TRUE)) + { + //printf("writeVecGfxFigure()=0\n"); + return FALSE; + } + } + //printf("Got PDF/EPS size %d,%d\n",width,height); + int maxWidth = 350; /* approx. page width in points, excl. margins */ + int maxHeight = 550; /* approx. page height in points, excl. margins */ + out << "\\nopagebreak\n" + "\\begin{figure}[H]\n" + "\\begin{center}\n" + "\\leavevmode\n"; + if (width>maxWidth || height>maxHeight) // figure too big for page + { + // c*width/maxWidth > c*height/maxHeight, where c=maxWidth*maxHeight>0 + if (width*maxHeight>height*maxWidth) + { + out << "\\includegraphics[width=" << maxWidth << "pt]"; + } + else + { + out << "\\includegraphics[height=" << maxHeight << "pt]"; + } + } + else + { + out << "\\includegraphics[width=" << width << "pt]"; + } + + out << "{" << baseName << "}\n" + "\\end{center}\n" + "\\end{figure}\n"; + + //printf("writeVecGfxFigure()=1\n"); + return TRUE; +} diff --git a/src/dotgraph.h b/src/dotgraph.h new file mode 100644 index 0000000..27d6938 --- /dev/null +++ b/src/dotgraph.h @@ -0,0 +1,113 @@ +/****************************************************************************** + * + * Copyright (C) 1997-2019 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. + * + * Documents produced by Doxygen are derivative works derived from the + * input used in their production; they are not affected by this license. + * + */ + +#ifndef DOTGRAPH_H +#define DOTGRAPH_H + +#include <qcstring.h> +#include <qgstring.h> +#include <qdir.h> + +class FTextStream; +class DotNode; + +enum GraphOutputFormat { GOF_BITMAP, GOF_EPS }; +enum EmbeddedOutputFormat { EOF_Html, EOF_LaTeX, EOF_Rtf, EOF_DocBook }; +enum GraphType { Dependency, Inheritance, Collaboration, Hierarchy, CallGraph }; + +/** A dot graph */ +class DotGraph +{ + public: + DotGraph() : m_curNodeNumber(0), m_doNotAddImageToIndex(FALSE), m_noDivTag(FALSE), m_zoomable(TRUE), m_urlOnly(FALSE) {} + virtual ~DotGraph() {} + + static QCString DOT_FONTNAME; // will be initialized in initDot + static int DOT_FONTSIZE; // will be initialized in initDot + + static bool writeVecGfxFigure(FTextStream& out, const QCString& baseName, const QCString& figureName); + + protected: + /** returns node numbers. The Counter is reset by the constructor */ + int getNextNodeNumber() { return ++m_curNodeNumber; } + + QCString writeGraph(FTextStream &t, + GraphOutputFormat gf, + EmbeddedOutputFormat ef, + const char *path, + const char *fileName, + const char *relPath, + bool writeImageMap=TRUE, + int graphId=-1 + ); + + static void writeGraphHeader(FTextStream& t, const QCString& title = QCString()); + static void writeGraphFooter(FTextStream& t); + static void computeGraph(DotNode* root, + GraphType gt, + GraphOutputFormat format, + const QCString& rank, // either "LR", "RL", or "" + bool renderParents, + bool backArrows, + const QCString& title, + QGString& graphStr + ); + + virtual QCString getBaseName() const = 0; + virtual QCString absMapName() const { return m_absPath + m_baseName + ".map"; } + virtual QCString getMapLabel() const = 0; + virtual QCString getImgAltText() const { return ""; } + + virtual void computeTheGraph() = 0; + + static QCString IMG_EXT; + + friend void initDot(); + + QCString absBaseName() const { return m_absPath + m_baseName; } + QCString absDotName() const { return m_absPath + m_baseName + ".dot"; } + QCString imgName() const; + QCString absImgName() const { return m_absPath + imgName(); } + QCString relImgName() const { return m_relPath + imgName(); } + + // the following variables are used while writing the graph to a .dot file + GraphOutputFormat m_graphFormat; + EmbeddedOutputFormat m_textFormat; + QDir m_dir; + QCString m_fileName; + QCString m_relPath; + bool m_generateImageMap; + int m_graphId; + + QCString m_absPath; + QCString m_baseName; + QGString m_theGraph; + bool m_regenerate; + bool m_doNotAddImageToIndex; + bool m_noDivTag; + bool m_zoomable; + bool m_urlOnly; + + private: + DotGraph(const DotGraph &); + DotGraph &operator=(const DotGraph &); + + bool prepareDotFile(); + void generateCode(FTextStream &t); + + int m_curNodeNumber; +}; + +#endif diff --git a/src/dotgroupcollaboration.cpp b/src/dotgroupcollaboration.cpp new file mode 100644 index 0000000..be55ac0 --- /dev/null +++ b/src/dotgroupcollaboration.cpp @@ -0,0 +1,381 @@ +/****************************************************************************** +* +* Copyright (C) 1997-2019 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. +* +* Documents produced by Doxygen are derivative works derived from the +* input used in their production; they are not affected by this license. +* +*/ + +#include "dotgroupcollaboration.h" + +#include "dotnode.h" +#include "classlist.h" +#include "doxygen.h" +#include "namespacedef.h" +#include "pagedef.h" +#include "util.h" +#include "config.h" + +#define DOT_TRANSPARENT Config_getBool(DOT_TRANSPARENT) + +DotGroupCollaboration::DotGroupCollaboration(const GroupDef* gd) +{ + QCString tmp_url = gd->getReference()+"$"+gd->getOutputFileBase(); + m_usedNodes = new QDict<DotNode>(1009); + QCString tooltip = gd->briefDescriptionAsTooltip(); + m_rootNode = new DotNode(getNextNodeNumber(), gd->groupTitle(), tooltip, tmp_url, TRUE ); + m_rootNode->markAsVisible(); + m_usedNodes->insert(gd->name(), m_rootNode ); + m_edges.setAutoDelete(TRUE); + + m_diskName = gd->getOutputFileBase(); + + buildGraph( gd ); +} + +DotGroupCollaboration::~DotGroupCollaboration() +{ + delete m_usedNodes; +} + +void DotGroupCollaboration::buildGraph(const GroupDef* gd) +{ + QCString tmp_url; + //=========================== + // hierarchy. + + // Write parents + const GroupList *groups = gd->partOfGroups(); + if ( groups ) + { + GroupListIterator gli(*groups); + const GroupDef *d; + for (gli.toFirst();(d=gli.current());++gli) + { + DotNode* nnode = m_usedNodes->find(d->name()); + if ( !nnode ) + { // add node + tmp_url = d->getReference()+"$"+d->getOutputFileBase(); + QCString tooltip = d->briefDescriptionAsTooltip(); + nnode = new DotNode(getNextNodeNumber(), d->groupTitle(), tooltip, tmp_url ); + nnode->markAsVisible(); + m_usedNodes->insert(d->name(), nnode ); + } + tmp_url = ""; + addEdge( nnode, m_rootNode, DotGroupCollaboration::thierarchy, tmp_url, tmp_url ); + } + } + + // Add subgroups + if ( gd->getSubGroups() && gd->getSubGroups()->count() ) + { + QListIterator<GroupDef> defli(*gd->getSubGroups()); + const GroupDef *def; + for (;(def=defli.current());++defli) + { + DotNode* nnode = m_usedNodes->find(def->name()); + if ( !nnode ) + { // add node + tmp_url = def->getReference()+"$"+def->getOutputFileBase(); + QCString tooltip = def->briefDescriptionAsTooltip(); + nnode = new DotNode(getNextNodeNumber(), def->groupTitle(), tooltip, tmp_url ); + nnode->markAsVisible(); + m_usedNodes->insert(def->name(), nnode ); + } + tmp_url = ""; + addEdge( m_rootNode, nnode, DotGroupCollaboration::thierarchy, tmp_url, tmp_url ); + } + } + + //======================= + // Write collaboration + + // Add members + addMemberList( gd->getMemberList(MemberListType_allMembersList) ); + + // Add classes + if ( gd->getClasses() && gd->getClasses()->count() ) + { + ClassSDict::Iterator defli(*gd->getClasses()); + ClassDef *def; + for (;(def=defli.current());++defli) + { + tmp_url = def->getReference()+"$"+def->getOutputFileBase()+Doxygen::htmlFileExtension; + if (!def->anchor().isEmpty()) + { + tmp_url+="#"+def->anchor(); + } + addCollaborationMember( def, tmp_url, DotGroupCollaboration::tclass ); + } + } + + // Add namespaces + if ( gd->getNamespaces() && gd->getNamespaces()->count() ) + { + NamespaceSDict::Iterator defli(*gd->getNamespaces()); + NamespaceDef *def; + for (;(def=defli.current());++defli) + { + tmp_url = def->getReference()+"$"+def->getOutputFileBase()+Doxygen::htmlFileExtension; + addCollaborationMember( def, tmp_url, DotGroupCollaboration::tnamespace ); + } + } + + // Add files + if ( gd->getFiles() && gd->getFiles()->count() ) + { + QListIterator<FileDef> defli(*gd->getFiles()); + const FileDef *def; + for (;(def=defli.current());++defli) + { + tmp_url = def->getReference()+"$"+def->getOutputFileBase()+Doxygen::htmlFileExtension; + addCollaborationMember( def, tmp_url, DotGroupCollaboration::tfile ); + } + } + + // Add pages + if ( gd->getPages() && gd->getPages()->count() ) + { + PageSDict::Iterator defli(*gd->getPages()); + PageDef *def; + for (;(def=defli.current());++defli) + { + tmp_url = def->getReference()+"$"+def->getOutputFileBase()+Doxygen::htmlFileExtension; + addCollaborationMember( def, tmp_url, DotGroupCollaboration::tpages ); + } + } + + // Add directories + if ( gd->getDirs() && gd->getDirs()->count() ) + { + QListIterator<DirDef> defli(*gd->getDirs()); + const DirDef *def; + for (;(def=defli.current());++defli) + { + tmp_url = def->getReference()+"$"+def->getOutputFileBase()+Doxygen::htmlFileExtension; + addCollaborationMember( def, tmp_url, DotGroupCollaboration::tdir ); + } + } +} + +void DotGroupCollaboration::addMemberList( MemberList* ml ) +{ + if ( !( ml && ml->count()) ) return; + MemberListIterator defli(*ml); + MemberDef *def; + for (;(def=defli.current());++defli) + { + QCString tmp_url = def->getReference()+"$"+def->getOutputFileBase()+Doxygen::htmlFileExtension + +"#"+def->anchor(); + addCollaborationMember( def, tmp_url, DotGroupCollaboration::tmember ); + } +} + +DotGroupCollaboration::Edge* DotGroupCollaboration::addEdge( + DotNode* _pNStart, DotNode* _pNEnd, EdgeType _eType, + const QCString& _label, const QCString& _url ) +{ + // search a existing link. + QListIterator<Edge> lli(m_edges); + Edge* newEdge = 0; + for ( lli.toFirst(); (newEdge=lli.current()); ++lli) + { + if ( newEdge->pNStart==_pNStart && + newEdge->pNEnd==_pNEnd && + newEdge->eType==_eType + ) + { // edge already found + break; + } + } + if ( newEdge==0 ) // new link + { + newEdge = new Edge(_pNStart,_pNEnd,_eType); + m_edges.append( newEdge ); + } + + if (!_label.isEmpty()) + { + newEdge->links.append(new Link(_label,_url)); + } + + return newEdge; +} + +void DotGroupCollaboration::addCollaborationMember( + const Definition* def, QCString& url, EdgeType eType ) +{ + // Create group nodes + if ( !def->partOfGroups() ) + return; + GroupListIterator gli(*def->partOfGroups()); + GroupDef *d; + QCString tmp_str; + for (;(d=gli.current());++gli) + { + DotNode* nnode = m_usedNodes->find(d->name()); + if ( nnode != m_rootNode ) + { + if ( nnode==0 ) + { // add node + tmp_str = d->getReference()+"$"+d->getOutputFileBase(); + QCString tooltip = d->briefDescriptionAsTooltip(); + nnode = new DotNode(getNextNodeNumber(), d->groupTitle(), tooltip, tmp_str ); + nnode->markAsVisible(); + m_usedNodes->insert(d->name(), nnode ); + } + tmp_str = def->qualifiedName(); + addEdge( m_rootNode, nnode, eType, tmp_str, url ); + } + } +} + +QCString DotGroupCollaboration::getBaseName() const +{ + return m_diskName; +} + +void DotGroupCollaboration::computeTheGraph() +{ + FTextStream md5stream(&m_theGraph); + writeGraphHeader(md5stream,m_rootNode->label()); + + // clean write flags + QDictIterator<DotNode> dni(*m_usedNodes); + DotNode *pn; + for (dni.toFirst();(pn=dni.current());++dni) + { + pn->clearWriteFlag(); + } + + // write other nodes. + for (dni.toFirst();(pn=dni.current());++dni) + { + pn->write(md5stream,Inheritance,m_graphFormat,TRUE,FALSE,FALSE); + } + + // write edges + QListIterator<Edge> eli(m_edges); + Edge* edge; + for (eli.toFirst();(edge=eli.current());++eli) + { + edge->write( md5stream ); + } + + writeGraphFooter(md5stream); + +} + +QCString DotGroupCollaboration::getMapLabel() const +{ + return escapeCharsInString(m_baseName, FALSE); +} + +QCString DotGroupCollaboration::writeGraph( FTextStream &t, + GraphOutputFormat graphFormat, EmbeddedOutputFormat textFormat, + const char *path, const char *fileName, const char *relPath, + bool generateImageMap,int graphId) +{ + m_doNotAddImageToIndex = TRUE; + + return DotGraph::writeGraph(t, graphFormat, textFormat, path, fileName, relPath, generateImageMap, graphId); +} + +void DotGroupCollaboration::Edge::write( FTextStream &t ) const +{ + const char* linkTypeColor[] = { + "darkorchid3" + ,"orange" + ,"blueviolet" + ,"darkgreen" + ,"firebrick4" + ,"grey75" + ,"midnightblue" + }; + QCString arrowStyle = "dir=\"none\", style=\"dashed\""; + t << " Node" << pNStart->number(); + t << "->"; + t << "Node" << pNEnd->number(); + + t << " [shape=plaintext"; + if (links.count()>0) // there are links + { + t << ", "; + // HTML-like edge labels crash on my Mac with Graphviz 2.0! and + // are not supported by older version of dot. + // + //t << label=<<TABLE BORDER=\"0\" CELLBORDER=\"0\">"; + //QListIterator<Link> lli(links); + //Link *link; + //for( lli.toFirst(); (link=lli.current()); ++lli) + //{ + // t << "<TR><TD"; + // if ( !link->url.isEmpty() ) + // t << " HREF=\"" << link->url << "\""; + // t << ">" << link->label << "</TD></TR>"; + //} + //t << "</TABLE>>"; + + t << "label=\""; + QListIterator<Link> lli(links); + Link *link; + bool first=TRUE; + int count=0; + const int maxLabels = 10; + for( lli.toFirst(); (link=lli.current()) && count<maxLabels; ++lli,++count) + { + if (first) first=FALSE; else t << "\\n"; + t << DotNode::convertLabel(link->label); + } + if (count==maxLabels) t << "\\n..."; + t << "\""; + + } + switch( eType ) + { + case thierarchy: + arrowStyle = "dir=\"back\", style=\"solid\""; + break; + default: + t << ", color=\"" << linkTypeColor[(int)eType] << "\""; + break; + } + t << ", " << arrowStyle; + t << "];" << endl; +} + +bool DotGroupCollaboration::isTrivial() const +{ + return m_usedNodes->count() <= 1; +} + +void DotGroupCollaboration::writeGraphHeader(FTextStream &t, + const QCString &title) const +{ + t << "digraph "; + if (title.isEmpty()) + { + t << "\"Dot Graph\""; + } + else + { + t << "\"" << convertToXML(title) << "\""; + } + t << endl; + t << "{" << endl; + if (DOT_TRANSPARENT) + { + t << " bgcolor=\"transparent\";" << endl; + } + t << " edge [fontname=\"" << DOT_FONTNAME << "\",fontsize=\"" << DOT_FONTSIZE << "\"," + "labelfontname=\"" << DOT_FONTNAME << "\",labelfontsize=\"" << DOT_FONTSIZE << "\"];\n"; + t << " node [fontname=\"" << DOT_FONTNAME << "\",fontsize=\"" << DOT_FONTSIZE << "\",shape=box];\n"; + t << " rankdir=LR;\n"; +} diff --git a/src/dotgroupcollaboration.h b/src/dotgroupcollaboration.h new file mode 100644 index 0000000..539637f --- /dev/null +++ b/src/dotgroupcollaboration.h @@ -0,0 +1,85 @@ +/****************************************************************************** +* +* Copyright (C) 1997-2019 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. +* +* Documents produced by Doxygen are derivative works derived from the +* input used in their production; they are not affected by this license. +* +*/ + +#ifndef DOTGROUPCOLLABORATION_H +#define DOTGROUPCOLLABORATION_H + +#include "dotgraph.h" +#include "qlist.h" +#include "groupdef.h" + +/** Representation of a group collaboration graph */ +class DotGroupCollaboration : public DotGraph +{ + public : + DotGroupCollaboration(const GroupDef* gd); + ~DotGroupCollaboration(); + QCString writeGraph(FTextStream &t, GraphOutputFormat gf,EmbeddedOutputFormat ef, + const char *path,const char *fileName,const char *relPath, + bool writeImageMap=TRUE,int graphId=-1); + bool isTrivial() const; + + protected: + virtual QCString getBaseName() const; + virtual QCString getMapLabel() const; + virtual void computeTheGraph(); + + private : + enum EdgeType + { + tmember = 0, + tclass, + tnamespace, + tfile, + tpages, + tdir, + thierarchy + }; + + struct Link + { + Link(const QCString lab,const QCString &u) : label(lab), url(u) {} + QCString label; + QCString url; + }; + + struct Edge + { + Edge(DotNode *start,DotNode *end,EdgeType type) + : pNStart(start), pNEnd(end), eType(type) + { links.setAutoDelete(TRUE); } + + DotNode* pNStart; + DotNode* pNEnd; + EdgeType eType; + + QList<Link> links; + void write( FTextStream &t ) const; + }; + + void buildGraph(const GroupDef* gd); + void addCollaborationMember(const Definition* def, QCString& url, EdgeType eType ); + void addMemberList( class MemberList* ml ); + void writeGraphHeader(FTextStream &t,const QCString &title) const; + Edge* addEdge( DotNode* _pNStart, DotNode* _pNEnd, EdgeType _eType, + const QCString& _label, const QCString& _url ); + + DotNode *m_rootNode; + QDict<DotNode> *m_usedNodes; + QCString m_diskName; + QList<Edge> m_edges; +}; + +#endif diff --git a/src/dotincldepgraph.cpp b/src/dotincldepgraph.cpp new file mode 100644 index 0000000..c968b68 --- /dev/null +++ b/src/dotincldepgraph.cpp @@ -0,0 +1,238 @@ +/****************************************************************************** +* +* Copyright (C) 1997-2019 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. +* +* Documents produced by Doxygen are derivative works derived from the +* input used in their production; they are not affected by this license. +* +*/ + +#include "dotincldepgraph.h" +#include "dotnode.h" +#include "util.h" +#include "config.h" + +void DotInclDepGraph::buildGraph(DotNode *n,const FileDef *fd,int distance) +{ + QList<IncludeInfo> *includeFiles = m_inverse ? fd->includedByFileList() : fd->includeFileList(); + if (includeFiles) + { + QListIterator<IncludeInfo> ili(*includeFiles); + IncludeInfo *ii; + for (;(ii=ili.current());++ili) + { + const FileDef *bfd = ii->fileDef; + QCString in = ii->includeName; + //printf(">>>> in=`%s' bfd=%p\n",ii->includeName.data(),bfd); + bool doc=TRUE,src=FALSE; + if (bfd) + { + in = bfd->absFilePath(); + doc = bfd->isLinkable() && !bfd->isHidden(); + src = bfd->generateSourceFile(); + } + if (doc || src || !Config_getBool(HIDE_UNDOC_RELATIONS)) + { + QCString url=""; + if (bfd) url=bfd->getOutputFileBase().copy(); + if (!doc && src) + { + url=bfd->getSourceFileBase(); + } + DotNode *bn = m_usedNodes->find(in); + if (bn) // file is already a node in the graph + { + n->addChild(bn,0,0,0); + bn->addParent(n); + bn->setDistance(distance); + } + else + { + QCString tmp_url; + QCString tooltip; + if (bfd) + { + tmp_url=doc || src ? bfd->getReference()+"$"+url : QCString(); + tooltip = bfd->briefDescriptionAsTooltip(); + } + bn = new DotNode(getNextNodeNumber(),// n + ii->includeName, // label + tooltip, // tip + tmp_url, // url + FALSE, // rootNode + 0); // cd + n->addChild(bn,0,0,0); + bn->addParent(n); + m_usedNodes->insert(in,bn); + bn->setDistance(distance); + + if (bfd) buildGraph(bn,bfd,distance+1); + } + } + } + } +} + +void DotInclDepGraph::determineVisibleNodes(QList<DotNode> &queue, int &maxNodes) +{ + while (queue.count()>0 && maxNodes>0) + { + DotNode *n = queue.take(0); + if (!n->isVisible() && n->distance()<=Config_getInt(MAX_DOT_GRAPH_DEPTH)) // not yet processed + { + n->markAsVisible(); + maxNodes--; + // add direct children + if (n->children()) + { + QListIterator<DotNode> li(*n->children()); + const DotNode *dn; + for (li.toFirst();(dn=li.current());++li) + { + queue.append(dn); + } + } + } + } +} + +void DotInclDepGraph::determineTruncatedNodes(QList<DotNode> &queue) +{ + while (queue.count()>0) + { + DotNode *n = queue.take(0); + if (n->isVisible() && n->isTruncated()==DotNode::Unknown) + { + bool truncated = FALSE; + if (n->children()) + { + QListIterator<DotNode> li(*n->children()); + const DotNode *dn; + for (li.toFirst();(dn=li.current());++li) + { + if (!dn->isVisible()) + { + truncated = TRUE; + } + else + { + queue.append(dn); + } + } + } + n->markAsTruncated(truncated); + } + } +} + +DotInclDepGraph::DotInclDepGraph(const FileDef *fd,bool inverse) +{ + m_inverse = inverse; + ASSERT(fd!=0); + m_inclDepFileName = fd->includeDependencyGraphFileName(); + m_inclByDepFileName = fd->includedByDependencyGraphFileName(); + QCString tmp_url=fd->getReference()+"$"+fd->getOutputFileBase(); + QCString tooltip = fd->briefDescriptionAsTooltip(); + m_startNode = new DotNode(getNextNodeNumber(), + fd->docName(), + tooltip, + tmp_url.data(), + TRUE); // root node + m_startNode->setDistance(0); + m_usedNodes = new QDict<DotNode>(1009); + m_usedNodes->insert(fd->absFilePath(),m_startNode); + buildGraph(m_startNode,fd,1); + + int maxNodes = Config_getInt(DOT_GRAPH_MAX_NODES); + QList<DotNode> openNodeQueue; + openNodeQueue.append(m_startNode); + determineVisibleNodes(openNodeQueue,maxNodes); + openNodeQueue.clear(); + openNodeQueue.append(m_startNode); + determineTruncatedNodes(openNodeQueue); +} + +DotInclDepGraph::~DotInclDepGraph() +{ + DotNode::deleteNodes(m_startNode); + delete m_usedNodes; +} + +QCString DotInclDepGraph::getBaseName() const +{ + if (m_inverse) + { + return m_inclByDepFileName; + } + else + { + return m_inclDepFileName; + } +} + +void DotInclDepGraph::computeTheGraph() +{ + computeGraph(m_startNode, Dependency, m_graphFormat, "", FALSE, + m_inverse, m_startNode->label(), m_theGraph); +} + +QCString DotInclDepGraph::getMapLabel() const +{ + if (m_inverse) + { + return escapeCharsInString(m_startNode->label(),FALSE) + "dep"; + } + else + { + return escapeCharsInString(m_startNode->label(),FALSE); + } +} + +QCString DotInclDepGraph::writeGraph(FTextStream &out, + GraphOutputFormat graphFormat, + EmbeddedOutputFormat textFormat, + const char *path, + const char *fileName, + const char *relPath, + bool generateImageMap, + int graphId) +{ + return DotGraph::writeGraph(out, graphFormat, textFormat, path, fileName, relPath, generateImageMap, graphId); +} + +bool DotInclDepGraph::isTrivial() const +{ + return m_startNode->children()==0; +} + +bool DotInclDepGraph::isTooBig() const +{ + int numNodes = m_startNode->children() ? m_startNode->children()->count() : 0; + return numNodes>=Config_getInt(DOT_GRAPH_MAX_NODES); +} + +void DotInclDepGraph::writeXML(FTextStream &t) +{ + QDictIterator<DotNode> dni(*m_usedNodes); + DotNode *node; + for (;(node=dni.current());++dni) + { + node->writeXML(t,FALSE); + } +} + +void DotInclDepGraph::writeDocbook(FTextStream &t) +{ + QDictIterator<DotNode> dni(*m_usedNodes); + DotNode *node; + for (;(node=dni.current());++dni) + { + node->writeDocbook(t,FALSE); + } +} diff --git a/src/dotincldepgraph.h b/src/dotincldepgraph.h new file mode 100644 index 0000000..b664ccb --- /dev/null +++ b/src/dotincldepgraph.h @@ -0,0 +1,56 @@ +/****************************************************************************** +* +* Copyright (C) 1997-2019 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. +* +* Documents produced by Doxygen are derivative works derived from the +* input used in their production; they are not affected by this license. +* +*/ + +#ifndef DOTINCLDEPGRAPH_H +#define DOTINCLDEPGRAPH_H + +#include "qcstring.h" +#include "filedef.h" + +#include "dotgraph.h" + +/** Representation of an include dependency graph */ +class DotInclDepGraph : public DotGraph +{ + public: + DotInclDepGraph(const FileDef *fd,bool inverse); + ~DotInclDepGraph(); + QCString writeGraph(FTextStream &t, GraphOutputFormat gf, EmbeddedOutputFormat ef, + const char *path,const char *fileName,const char *relPath, + bool writeImageMap=TRUE,int graphId=-1); + bool isTrivial() const; + bool isTooBig() const; + void writeXML(FTextStream &t); + void writeDocbook(FTextStream &t); + + protected: + virtual QCString getBaseName() const; + virtual QCString getMapLabel() const; + virtual void computeTheGraph(); + + private: + QCString diskName() const; + void buildGraph(DotNode *n,const FileDef *fd,int distance); + void determineVisibleNodes(QList<DotNode> &queue,int &maxNodes); + void determineTruncatedNodes(QList<DotNode> &queue); + + DotNode *m_startNode; + QDict<DotNode> *m_usedNodes; + QCString m_inclDepFileName; + QCString m_inclByDepFileName; + bool m_inverse; +}; + +#endif diff --git a/src/dotnode.cpp b/src/dotnode.cpp new file mode 100644 index 0000000..41d5f06 --- /dev/null +++ b/src/dotnode.cpp @@ -0,0 +1,950 @@ +/****************************************************************************** +* +* Copyright (C) 1997-2019 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. +* +* Documents produced by Doxygen are derivative works derived from the +* input used in their production; they are not affected by this license. +* +*/ + +#include "dotnode.h" + +#include "ftextstream.h" +#include "classdef.h" +#include "config.h" +#include "memberlist.h" +#include "membergroup.h" +#include "language.h" +#include "doxygen.h" +#include "util.h" + +/** Helper struct holding the properties of a edge in a dot graph. */ +struct EdgeProperties +{ + const char * const *edgeColorMap; + const char * const *arrowStyleMap; + const char * const *edgeStyleMap; +}; + +/*! mapping from protection levels to color names */ +static const char *normalEdgeColorMap[] = +{ + "midnightblue", // Public + "darkgreen", // Protected + "firebrick4", // Private + "darkorchid3", // "use" relation + "grey75", // Undocumented + "orange", // template relation + "orange" // type constraint +}; + +static const char *normalArrowStyleMap[] = +{ + "empty", // Public + "empty", // Protected + "empty", // Private + "open", // "use" relation + 0, // Undocumented + 0 // template relation +}; + +static const char *normalEdgeStyleMap[] = +{ + "solid", // inheritance + "dashed" // usage +}; + +static const char *umlEdgeColorMap[] = +{ + "midnightblue", // Public + "darkgreen", // Protected + "firebrick4", // Private + "grey25", // "use" relation + "grey75", // Undocumented + "orange", // template relation + "orange" // type constraint +}; + +static const char *umlArrowStyleMap[] = +{ + "onormal", // Public + "onormal", // Protected + "onormal", // Private + "odiamond", // "use" relation + 0, // Undocumented + 0 // template relation +}; + +static const char *umlEdgeStyleMap[] = +{ + "solid", // inheritance + "solid" // usage +}; + +static EdgeProperties normalEdgeProps = +{ + normalEdgeColorMap, normalArrowStyleMap, normalEdgeStyleMap +}; + +static EdgeProperties umlEdgeProps = +{ + umlEdgeColorMap, umlArrowStyleMap, umlEdgeStyleMap +}; + +static QCString escapeTooltip(const QCString &tooltip) +{ + QCString result; + const char *p=tooltip.data(); + if (p==0) return result; + char c; + while ((c=*p++)) + { + switch(c) + { + case '"': result+="\\\""; break; + case '\\': result+="\\\\"; break; + default: result+=c; break; + } + } + return result; +} + +static void writeBoxMemberList(FTextStream &t, + char prot,MemberList *ml,const ClassDef *scope, + bool isStatic=FALSE,const QDict<void> *skipNames=0) +{ + (void)isStatic; + if (ml) + { + MemberListIterator mlia(*ml); + MemberDef *mma; + int totalCount=0; + for (mlia.toFirst();(mma = mlia.current());++mlia) + { + if (mma->getClassDef()==scope && + (skipNames==0 || skipNames->find(mma->name())==0)) + { + totalCount++; + } + } + + int count=0; + for (mlia.toFirst();(mma = mlia.current());++mlia) + { + if (mma->getClassDef() == scope && + (skipNames==0 || skipNames->find(mma->name())==0)) + { + int numFields = Config_getInt(UML_LIMIT_NUM_FIELDS); + if (numFields>0 && (totalCount>numFields*3/2 && count>=numFields)) + { + t << theTranslator->trAndMore(QCString().sprintf("%d",totalCount-count)) << "\\l"; + break; + } + else + { + t << prot << " "; + t << DotNode::convertLabel(mma->name()); + if (!mma->isObjCMethod() && + (mma->isFunction() || mma->isSlot() || mma->isSignal())) t << "()"; + t << "\\l"; + count++; + } + } + } + // write member groups within the memberlist + MemberGroupList *mgl = ml->getMemberGroupList(); + if (mgl) + { + MemberGroupListIterator mgli(*mgl); + MemberGroup *mg; + for (mgli.toFirst();(mg=mgli.current());++mgli) + { + if (mg->members()) + { + writeBoxMemberList(t,prot,mg->members(),scope,isStatic,skipNames); + } + } + } + } +} + +QCString DotNode::convertLabel(const QCString &l) +{ + QString bBefore("\\_/<({[: =-+@%#~?$"); // break before character set + QString bAfter(">]),:;|"); // break after character set + QString p(l); + if (p.isEmpty()) return QCString(); + QString result; + QChar c,pc=0; + uint idx = 0; + int len=p.length(); + int charsLeft=len; + int sinceLast=0; + int foldLen=17; // ideal text length + while (idx < p.length()) + { + c = p[idx++]; + QString replacement; + switch(c) + { + case '\\': replacement="\\\\"; break; + case '\n': replacement="\\n"; break; + case '<': replacement="\\<"; break; + case '>': replacement="\\>"; break; + case '|': replacement="\\|"; break; + case '{': replacement="\\{"; break; + case '}': replacement="\\}"; break; + case '"': replacement="\\\""; break; + default: replacement=c; break; + } + // Some heuristics to insert newlines to prevent too long + // boxes and at the same time prevent ugly breaks + if (c=='\n') + { + result+=replacement; + foldLen = (3*foldLen+sinceLast+2)/4; + sinceLast=1; + } + else if ((pc!=':' || c!=':') && charsLeft>foldLen/3 && sinceLast>foldLen && bBefore.contains(c)) + { + result+="\\l"; + result+=replacement; + foldLen = (foldLen+sinceLast+1)/2; + sinceLast=1; + } + else if (charsLeft>1+foldLen/4 && sinceLast>foldLen+foldLen/3 && + !isupper(c) && p[idx].category()==QChar::Letter_Uppercase) + { + result+=replacement; + result+="\\l"; + foldLen = (foldLen+sinceLast+1)/2; + sinceLast=0; + } + else if (charsLeft>foldLen/3 && sinceLast>foldLen && bAfter.contains(c) && (c!=':' || p[idx]!=':')) + { + result+=replacement; + result+="\\l"; + foldLen = (foldLen+sinceLast+1)/2; + sinceLast=0; + } + else + { + result+=replacement; + sinceLast++; + } + charsLeft--; + pc=c; + } + return result.utf8(); +} + +static QCString stripProtectionPrefix(const QCString &s) +{ + if (!s.isEmpty() && (s[0]=='-' || s[0]=='+' || s[0]=='~' || s[0]=='#')) + { + return s.mid(1); + } + else + { + return s; + } +} + +DotNode::DotNode(int n,const char *lab,const char *tip, const char *url, + bool isRoot,const ClassDef *cd) + : m_subgraphId(-1) + , m_number(n) + , m_label(lab) + , m_tooltip(tip) + , m_url(url) + , m_parents(0) + , m_children(0) + , m_edgeInfo(0) + , m_deleted(FALSE) + , m_written(FALSE) + , m_hasDoc(FALSE) + , m_isRoot(isRoot) + , m_classDef(cd) + , m_visible(FALSE) + , m_truncated(Unknown) + , m_distance(1000) + , m_renumbered(false) +{ +} + +DotNode::~DotNode() +{ + delete m_children; + delete m_parents; + delete m_edgeInfo; +} + +void DotNode::addChild(DotNode *n, + int edgeColor, + int edgeStyle, + const char *edgeLab, + const char *edgeURL, + int edgeLabCol +) +{ + if (m_children==0) + { + m_children = new QList<DotNode>; + m_edgeInfo = new QList<EdgeInfo>; + m_edgeInfo->setAutoDelete(TRUE); + } + m_children->append(n); + EdgeInfo *ei = new EdgeInfo( + edgeColor, + edgeStyle, + edgeLab, + edgeURL, + edgeLabCol==-1 ? edgeColor : edgeLabCol); + m_edgeInfo->append(ei); +} + +void DotNode::addParent(DotNode *n) +{ + if (m_parents==0) + { + m_parents = new QList<DotNode>; + } + m_parents->append(n); +} + +void DotNode::removeChild(DotNode *n) +{ + if (m_children) m_children->remove(n); +} + +void DotNode::removeParent(DotNode *n) +{ + if (m_parents) m_parents->remove(n); +} + +void DotNode::deleteNode(DotNodeList &deletedList,SDict<DotNode> *skipNodes) +{ + if (m_deleted) return; // avoid recursive loops in case the graph has cycles + m_deleted=TRUE; + if (m_parents!=0) // delete all parent nodes of this node + { + QListIterator<DotNode> dnlip(*m_parents); + DotNode *pn; + for (dnlip.toFirst();(pn=dnlip.current());++dnlip) + { + //pn->removeChild(this); + pn->deleteNode(deletedList,skipNodes); + } + } + if (m_children!=0) // delete all child nodes of this node + { + QListIterator<DotNode> dnlic(*m_children); + DotNode *cn; + for (dnlic.toFirst();(cn=dnlic.current());++dnlic) + { + //cn->removeParent(this); + cn->deleteNode(deletedList,skipNodes); + } + } + // add this node to the list of deleted nodes. + //printf("skipNodes=%p find(%p)=%p\n",skipNodes,this,skipNodes ? skipNodes->find((int)this) : 0); + if (skipNodes==0 || skipNodes->find((char*)this)==0) + { + //printf("deleting\n"); + deletedList.append(this); + } +} + +void DotNode::setDistance(int distance) +{ + if (distance<m_distance) m_distance = distance; +} + +inline int DotNode::findParent( DotNode *n ) +{ + if ( !m_parents ) return -1; + return m_parents->find(n); +} + +/*! helper function that deletes all nodes in a connected graph, given +* one of the graph's nodes +*/ +void DotNode::deleteNodes(DotNode *node,SDict<DotNode> *skipNodes) +{ + //printf("deleteNodes skipNodes=%p\n",skipNodes); + static DotNodeList deletedNodes; + deletedNodes.setAutoDelete(TRUE); + node->deleteNode(deletedNodes,skipNodes); // collect nodes to be deleted. + deletedNodes.clear(); // actually remove the nodes. +} + +void DotNode::writeBox(FTextStream &t, + GraphType gt, + GraphOutputFormat /*format*/, + bool hasNonReachableChildren) const +{ + const char *labCol = + m_url.isEmpty() ? "grey75" : // non link + (hasNonReachableChildren ? "red" : "black"); + t << " Node" << m_number << " [label=\""; + + if (m_classDef && Config_getBool(UML_LOOK) && (gt==Inheritance || gt==Collaboration)) + { + // add names shown as relations to a dictionary, so we don't show + // them as attributes as well + QDict<void> arrowNames(17); + if (m_edgeInfo) + { + // for each edge + QListIterator<EdgeInfo> li(*m_edgeInfo); + EdgeInfo *ei; + for (li.toFirst();(ei=li.current());++li) + { + if (!ei->label().isEmpty()) // labels joined by \n + { + int li=ei->label().find('\n'); + int p=0; + QCString lab; + while ((li=ei->label().find('\n',p))!=-1) + { + lab = stripProtectionPrefix(ei->label().mid(p,li-p)); + arrowNames.insert(lab,(void*)0x8); + p=li+1; + } + lab = stripProtectionPrefix(ei->label().right(ei->label().length()-p)); + arrowNames.insert(lab,(void*)0x8); + } + } + } + + //printf("DotNode::writeBox for %s\n",m_classDef->name().data()); + t << "{" << convertLabel(m_label); + t << "\\n|"; + writeBoxMemberList(t,'+',m_classDef->getMemberList(MemberListType_pubAttribs),m_classDef,FALSE,&arrowNames); + writeBoxMemberList(t,'+',m_classDef->getMemberList(MemberListType_pubStaticAttribs),m_classDef,TRUE,&arrowNames); + writeBoxMemberList(t,'+',m_classDef->getMemberList(MemberListType_properties),m_classDef,FALSE,&arrowNames); + writeBoxMemberList(t,'~',m_classDef->getMemberList(MemberListType_pacAttribs),m_classDef,FALSE,&arrowNames); + writeBoxMemberList(t,'~',m_classDef->getMemberList(MemberListType_pacStaticAttribs),m_classDef,TRUE,&arrowNames); + writeBoxMemberList(t,'#',m_classDef->getMemberList(MemberListType_proAttribs),m_classDef,FALSE,&arrowNames); + writeBoxMemberList(t,'#',m_classDef->getMemberList(MemberListType_proStaticAttribs),m_classDef,TRUE,&arrowNames); + if (Config_getBool(EXTRACT_PRIVATE)) + { + writeBoxMemberList(t,'-',m_classDef->getMemberList(MemberListType_priAttribs),m_classDef,FALSE,&arrowNames); + writeBoxMemberList(t,'-',m_classDef->getMemberList(MemberListType_priStaticAttribs),m_classDef,TRUE,&arrowNames); + } + t << "|"; + writeBoxMemberList(t,'+',m_classDef->getMemberList(MemberListType_pubMethods),m_classDef); + writeBoxMemberList(t,'+',m_classDef->getMemberList(MemberListType_pubStaticMethods),m_classDef,TRUE); + writeBoxMemberList(t,'+',m_classDef->getMemberList(MemberListType_pubSlots),m_classDef); + writeBoxMemberList(t,'~',m_classDef->getMemberList(MemberListType_pacMethods),m_classDef); + writeBoxMemberList(t,'~',m_classDef->getMemberList(MemberListType_pacStaticMethods),m_classDef,TRUE); + writeBoxMemberList(t,'#',m_classDef->getMemberList(MemberListType_proMethods),m_classDef); + writeBoxMemberList(t,'#',m_classDef->getMemberList(MemberListType_proStaticMethods),m_classDef,TRUE); + writeBoxMemberList(t,'#',m_classDef->getMemberList(MemberListType_proSlots),m_classDef); + if (Config_getBool(EXTRACT_PRIVATE)) + { + writeBoxMemberList(t,'-',m_classDef->getMemberList(MemberListType_priMethods),m_classDef); + writeBoxMemberList(t,'-',m_classDef->getMemberList(MemberListType_priStaticMethods),m_classDef,TRUE); + writeBoxMemberList(t,'-',m_classDef->getMemberList(MemberListType_priSlots),m_classDef); + } + if (m_classDef->getLanguage()!=SrcLangExt_Fortran && + m_classDef->getMemberGroupSDict()) + { + MemberGroupSDict::Iterator mgdi(*m_classDef->getMemberGroupSDict()); + MemberGroup *mg; + for (mgdi.toFirst();(mg=mgdi.current());++mgdi) + { + if (mg->members()) + { + writeBoxMemberList(t,'*',mg->members(),m_classDef,FALSE,&arrowNames); + } + } + } + t << "}"; + } + else // standard look + { + t << convertLabel(m_label); + } + t << "\",height=0.2,width=0.4"; + if (m_isRoot) + { + t << ",color=\"black\", fillcolor=\"grey75\", style=\"filled\", fontcolor=\"black\""; + } + else + { + if (!Config_getBool(DOT_TRANSPARENT)) + { + t << ",color=\"" << labCol << "\", fillcolor=\""; + t << "white"; + t << "\", style=\"filled\""; + } + else + { + t << ",color=\"" << labCol << "\""; + } + if (!m_url.isEmpty()) + { + int anchorPos = m_url.findRev('#'); + if (anchorPos==-1) + { + t << ",URL=\"" << m_url << Doxygen::htmlFileExtension << "\""; + } + else + { + t << ",URL=\"" << m_url.left(anchorPos) << Doxygen::htmlFileExtension + << m_url.right(m_url.length()-anchorPos) << "\""; + } + } + } + if (!m_tooltip.isEmpty()) + { + t << ",tooltip=\"" << escapeTooltip(m_tooltip) << "\""; + } + else + { + t << ",tooltip=\" \""; // space in tooltip is required otherwise still something like 'Node0' is used + } + t << "];" << endl; +} + +void DotNode::writeArrow(FTextStream &t, + GraphType gt, + GraphOutputFormat format, + const DotNode *cn, + const EdgeInfo *ei, + bool topDown, + bool pointBack) const +{ + t << " Node"; + if (topDown) + t << cn->number(); + else + t << m_number; + t << " -> Node"; + if (topDown) + t << m_number; + else + t << cn->number(); + t << " ["; + + const EdgeProperties *eProps = Config_getBool(UML_LOOK) ? ¨EdgeProps : &normalEdgeProps; + QCString aStyle = eProps->arrowStyleMap[ei->color()]; + bool umlUseArrow = aStyle=="odiamond"; + + if (pointBack && !umlUseArrow) t << "dir=\"back\","; + t << "color=\"" << eProps->edgeColorMap[ei->color()] + << "\",fontsize=\"" << DotGraph::DOT_FONTSIZE << "\","; + t << "style=\"" << eProps->edgeStyleMap[ei->style()] << "\""; + if (!ei->label().isEmpty()) + { + t << ",label=\" " << convertLabel(ei->label()) << "\" "; + } + if (Config_getBool(UML_LOOK) && + eProps->arrowStyleMap[ei->color()] && + (gt==Inheritance || gt==Collaboration) + ) + { + bool rev = pointBack; + if (umlUseArrow) rev=!rev; // UML use relates has arrow on the start side + if (rev) + t << ",arrowtail=\"" << eProps->arrowStyleMap[ei->color()] << "\""; + else + t << ",arrowhead=\"" << eProps->arrowStyleMap[ei->color()] << "\""; + } + + if (format==GOF_BITMAP) t << ",fontname=\"" << DotGraph::DOT_FONTNAME << "\""; + t << "];" << endl; +} + +void DotNode::write(FTextStream &t, + GraphType gt, + GraphOutputFormat format, + bool topDown, + bool toChildren, + bool backArrows) const +{ + //printf("DotNode::write(%d) name=%s this=%p written=%d visible=%d\n",m_distance,m_label.data(),this,m_written,m_visible); + if (m_written) return; // node already written to the output + if (!m_visible) return; // node is not visible + writeBox(t,gt,format,m_truncated==Truncated); + m_written=TRUE; + QList<DotNode> *nl = toChildren ? m_children : m_parents; + if (nl) + { + if (toChildren) + { + QListIterator<DotNode> dnli1(*nl); + QListIterator<EdgeInfo> dnli2(*m_edgeInfo); + const DotNode *cn; + for (dnli1.toFirst();(cn=dnli1.current());++dnli1,++dnli2) + { + if (cn->isVisible()) + { + //printf("write arrow %s%s%s\n",label().data(),backArrows?"<-":"->",cn->label().data()); + writeArrow(t,gt,format,cn,dnli2.current(),topDown,backArrows); + } + cn->write(t,gt,format,topDown,toChildren,backArrows); + } + } + else // render parents + { + QListIterator<DotNode> dnli(*nl); + DotNode *pn; + for (dnli.toFirst();(pn=dnli.current());++dnli) + { + if (pn->isVisible()) + { + //printf("write arrow %s%s%s\n",label().data(),backArrows?"<-":"->",pn->label().data()); + writeArrow(t, + gt, + format, + pn, + pn->edgeInfo()->at(pn->children()->findRef(this)), + FALSE, + backArrows + ); + } + pn->write(t,gt,format,TRUE,FALSE,backArrows); + } + } + } + //printf("end DotNode::write(%d) name=%s\n",distance,m_label.data()); +} + +void DotNode::writeXML(FTextStream &t,bool isClassGraph) const +{ + t << " <node id=\"" << m_number << "\">" << endl; + t << " <label>" << convertToXML(m_label) << "</label>" << endl; + if (!m_url.isEmpty()) + { + QCString url(m_url); + const char *refPtr = url.data(); + char *urlPtr = strchr(url.rawData(),'$'); + if (urlPtr) + { + *urlPtr++='\0'; + t << " <link refid=\"" << convertToXML(urlPtr) << "\""; + if (*refPtr!='\0') + { + t << " external=\"" << convertToXML(refPtr) << "\""; + } + t << "/>" << endl; + } + } + if (m_children) + { + QListIterator<DotNode> nli(*m_children); + QListIterator<EdgeInfo> eli(*m_edgeInfo); + DotNode *childNode; + EdgeInfo *edgeInfo; + for (;(childNode=nli.current());++nli,++eli) + { + edgeInfo=eli.current(); + t << " <childnode refid=\"" << childNode->number() << "\" relation=\""; + if (isClassGraph) + { + switch(edgeInfo->color()) + { + case EdgeInfo::Blue: t << "public-inheritance"; break; + case EdgeInfo::Green: t << "protected-inheritance"; break; + case EdgeInfo::Red: t << "private-inheritance"; break; + case EdgeInfo::Purple: t << "usage"; break; + case EdgeInfo::Orange: t << "template-instance"; break; + case EdgeInfo::Orange2: t << "type-constraint"; break; + case EdgeInfo::Grey: ASSERT(0); break; + } + } + else // include graph + { + t << "include"; + } + t << "\">" << endl; + if (!edgeInfo->label().isEmpty()) + { + int p=0; + int ni; + while ((ni=edgeInfo->label().find('\n',p))!=-1) + { + t << " <edgelabel>" + << convertToXML(edgeInfo->label().mid(p,ni-p)) + << "</edgelabel>" << endl; + p=ni+1; + } + t << " <edgelabel>" + << convertToXML(edgeInfo->label().right(edgeInfo->label().length()-p)) + << "</edgelabel>" << endl; + } + t << " </childnode>" << endl; + } + } + t << " </node>" << endl; +} + +void DotNode::writeDocbook(FTextStream &t,bool isClassGraph) const +{ + t << " <node id=\"" << m_number << "\">" << endl; + t << " <label>" << convertToXML(m_label) << "</label>" << endl; + if (!m_url.isEmpty()) + { + QCString url(m_url); + const char *refPtr = url.data(); + char *urlPtr = strchr(url.rawData(),'$'); + if (urlPtr) + { + *urlPtr++='\0'; + t << " <link refid=\"" << convertToXML(urlPtr) << "\""; + if (*refPtr!='\0') + { + t << " external=\"" << convertToXML(refPtr) << "\""; + } + t << "/>" << endl; + } + } + if (m_children) + { + QListIterator<DotNode> nli(*m_children); + QListIterator<EdgeInfo> eli(*m_edgeInfo); + DotNode *childNode; + EdgeInfo *edgeInfo; + for (;(childNode=nli.current());++nli,++eli) + { + edgeInfo=eli.current(); + t << " <childnode refid=\"" << childNode->number() << "\" relation=\""; + if (isClassGraph) + { + switch(edgeInfo->color()) + { + case EdgeInfo::Blue: t << "public-inheritance"; break; + case EdgeInfo::Green: t << "protected-inheritance"; break; + case EdgeInfo::Red: t << "private-inheritance"; break; + case EdgeInfo::Purple: t << "usage"; break; + case EdgeInfo::Orange: t << "template-instance"; break; + case EdgeInfo::Orange2: t << "type-constraint"; break; + case EdgeInfo::Grey: ASSERT(0); break; + } + } + else // include graph + { + t << "include"; + } + t << "\">" << endl; + if (!edgeInfo->label().isEmpty()) + { + int p=0; + int ni; + while ((ni=edgeInfo->label().find('\n',p))!=-1) + { + t << " <edgelabel>" + << convertToXML(edgeInfo->label().mid(p,ni-p)) + << "</edgelabel>" << endl; + p=ni+1; + } + t << " <edgelabel>" + << convertToXML(edgeInfo->label().right(edgeInfo->label().length()-p)) + << "</edgelabel>" << endl; + } + t << " </childnode>" << endl; + } + } + t << " </node>" << endl; +} + + +void DotNode::writeDEF(FTextStream &t) const +{ + const char* nodePrefix = " node-"; + + t << " node = {" << endl; + t << nodePrefix << "id = " << m_number << ';' << endl; + t << nodePrefix << "label = '" << m_label << "';" << endl; + + if (!m_url.isEmpty()) + { + QCString url(m_url); + const char *refPtr = url.data(); + char *urlPtr = strchr(url.rawData(),'$'); + if (urlPtr) + { + *urlPtr++='\0'; + t << nodePrefix << "link = {" << endl << " " + << nodePrefix << "link-id = '" << urlPtr << "';" << endl; + + if (*refPtr!='\0') + { + t << " " << nodePrefix << "link-external = '" + << refPtr << "';" << endl; + } + t << " };" << endl; + } + } + if (m_children) + { + QListIterator<DotNode> nli(*m_children); + QListIterator<EdgeInfo> eli(*m_edgeInfo); + DotNode *childNode; + EdgeInfo *edgeInfo; + for (;(childNode=nli.current());++nli,++eli) + { + edgeInfo=eli.current(); + t << " node-child = {" << endl; + t << " child-id = '" << childNode->number() << "';" << endl; + t << " relation = "; + + switch(edgeInfo->color()) + { + case EdgeInfo::Blue: t << "public-inheritance"; break; + case EdgeInfo::Green: t << "protected-inheritance"; break; + case EdgeInfo::Red: t << "private-inheritance"; break; + case EdgeInfo::Purple: t << "usage"; break; + case EdgeInfo::Orange: t << "template-instance"; break; + case EdgeInfo::Orange2: t << "type-constraint"; break; + case EdgeInfo::Grey: ASSERT(0); break; + } + t << ';' << endl; + + if (!edgeInfo->label().isEmpty()) + { + t << " edgelabel = <<_EnD_oF_dEf_TeXt_" << endl + << edgeInfo->label() << endl + << "_EnD_oF_dEf_TeXt_;" << endl; + } + t << " }; /* node-child */" << endl; + } /* for (;childNode...) */ + } + t << " }; /* node */" << endl; +} + + +void DotNode::clearWriteFlag() +{ + m_written=FALSE; + if (m_parents!=0) + { + QListIterator<DotNode> dnlip(*m_parents); + DotNode *pn; + for (dnlip.toFirst();(pn=dnlip.current());++dnlip) + { + if (pn->isWritten()) + { + pn->clearWriteFlag(); + } + } + } + if (m_children!=0) + { + QListIterator<DotNode> dnlic(*m_children); + DotNode *cn; + for (dnlic.toFirst();(cn=dnlic.current());++dnlic) + { + if (cn->isWritten()) + { + cn->clearWriteFlag(); + } + } + } +} + +void DotNode::colorConnectedNodes(int curColor) +{ + if (m_children) + { + QListIterator<DotNode> dnlic(*m_children); + DotNode *cn; + for (dnlic.toFirst();(cn=dnlic.current());++dnlic) + { + if (cn->subgraphId()==-1) // uncolored child node + { + cn->setSubgraphId(curColor); + cn->markAsVisible(); + cn->colorConnectedNodes(curColor); + //printf("coloring node %s (%p): %d\n",cn->label().data(),cn,cn->subgraphId()); + } + } + } + + if (m_parents) + { + QListIterator<DotNode> dnlip(*m_parents); + DotNode *pn; + for (dnlip.toFirst();(pn=dnlip.current());++dnlip) + { + if (pn->subgraphId()==-1) // uncolored parent node + { + pn->setSubgraphId(curColor); + pn->markAsVisible(); + pn->colorConnectedNodes(curColor); + //printf("coloring node %s (%p): %d\n",pn->label().data(),pn,pn->subgraphId()); + } + } + } +} + +void DotNode::renumberNodes(int &number) +{ + m_number = number++; + if (m_children) + { + QListIterator<DotNode> dnlic(*m_children); + DotNode *cn; + for (dnlic.toFirst();(cn=dnlic.current());++dnlic) + { + if (!cn->isRenumbered()) + { + cn->markRenumbered(); + cn->renumberNodes(number); + } + } + } +} + +const DotNode *DotNode::findDocNode() const +{ + if (!m_url.isEmpty()) return this; + //printf("findDocNode(): `%s'\n",m_label.data()); + if (m_parents) + { + QListIterator<DotNode> dnli(*m_parents); + DotNode *pn; + for (dnli.toFirst();(pn=dnli.current());++dnli) + { + if (!pn->hasDocumentation()) + { + pn->markHasDocumentation(); + const DotNode *dn = pn->findDocNode(); + if (dn) return dn; + } + } + } + if (m_children) + { + QListIterator<DotNode> dnli(*m_children); + DotNode *cn; + for (dnli.toFirst();(cn=dnli.current());++dnli) + { + if (!cn->hasDocumentation()) + { + cn->markHasDocumentation(); + const DotNode *dn = cn->findDocNode(); + if (dn) return dn; + } + } + } + return 0; +} + +//-------------------------------------------------------------- + +int DotNodeList::compareValues(const DotNode *n1,const DotNode *n2) const +{ + return qstricmp(n1->label(),n2->label()); +} + + + diff --git a/src/dotnode.h b/src/dotnode.h new file mode 100644 index 0000000..334fdef --- /dev/null +++ b/src/dotnode.h @@ -0,0 +1,138 @@ +/****************************************************************************** +* +* Copyright (C) 1997-2019 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. +* +* Documents produced by Doxygen are derivative works derived from the +* input used in their production; they are not affected by this license. +* +*/ + +#ifndef DOTNODE_H +#define DOTNODE_H + +#include "sortdict.h" + +#include "dotgraph.h" + +class ClassDef; +class DotNodeList; +class FTextStream; + +/** Attributes of an edge of a dot graph */ +class EdgeInfo +{ + public: + enum Colors { Blue=0, Green=1, Red=2, Purple=3, Grey=4, Orange=5, Orange2=6 }; + enum Styles { Solid=0, Dashed=1 }; + EdgeInfo(int color,int style,const QCString &lab,const QCString &url,int labColor) + : m_color(color), m_style(style), m_label(lab), m_url(url), m_labColor(labColor) {} + ~EdgeInfo() {} + int color() const { return m_color; } + int style() const { return m_style; } + QCString label() const { return m_label; } + QCString url() const { return m_url; } + int labelColor() const { return m_labColor; } + private: + int m_color; + int m_style; + QCString m_label; + QCString m_url; + int m_labColor; +}; + +/** A node in a dot graph */ +class DotNode +{ + public: + static void deleteNodes(DotNode* node, SDict<DotNode>* skipNodes = 0); + static QCString convertLabel(const QCString& l); + DotNode(int n,const char *lab,const char *tip,const char *url, + bool rootNode=FALSE,const ClassDef *cd=0); + ~DotNode(); + + enum TruncState { Unknown, Truncated, Untruncated }; + + void addChild(DotNode *n, + int edgeColor=EdgeInfo::Purple, + int edgeStyle=EdgeInfo::Solid, + const char *edgeLab=0, + const char *edgeURL=0, + int edgeLabCol=-1); + void addParent(DotNode *n); + void deleteNode(DotNodeList &deletedList,SDict<DotNode> *skipNodes=0); + void removeChild(DotNode *n); + void removeParent(DotNode *n); + int findParent( DotNode *n ); + + void write(FTextStream &t,GraphType gt,GraphOutputFormat f, + bool topDown,bool toChildren,bool backArrows) const; + void writeXML(FTextStream &t,bool isClassGraph) const; + void writeDocbook(FTextStream &t,bool isClassGraph) const; + void writeDEF(FTextStream &t) const; + void writeBox(FTextStream &t,GraphType gt,GraphOutputFormat f, + bool hasNonReachableChildren) const; + void writeArrow(FTextStream &t,GraphType gt,GraphOutputFormat f,const DotNode *cn, + const EdgeInfo *ei,bool topDown, bool pointBack=TRUE) const; + + QCString label() const { return m_label; } + int number() const { return m_number; } + bool isVisible() const { return m_visible; } + TruncState isTruncated() const { return m_truncated; } + int distance() const { return m_distance; } + int subgraphId() const { return m_subgraphId; } + bool isRenumbered() const { return m_renumbered; } + bool hasDocumentation() const { return m_hasDoc; } + bool isWritten() const { return m_written; } + + void clearWriteFlag(); + void renumberNodes(int &number); + void markRenumbered() { m_renumbered = true; } + void markHasDocumentation() { m_hasDoc = true; } + void setSubgraphId(int id) { m_subgraphId = id; } + + void colorConnectedNodes(int curColor); + void setDistance(int distance); + const DotNode *findDocNode() const; // only works for acyclic graphs! + void markAsVisible(bool b=TRUE) { m_visible=b; } + void markAsTruncated(bool b=TRUE) { m_truncated=b ? Truncated : Untruncated; } + const QList<DotNode> *children() const { return m_children; } + const QList<DotNode> *parents() const { return m_parents; } + const QList<EdgeInfo> *edgeInfo() const { return m_edgeInfo; } + + private: + int m_number; + QCString m_label; //!< label text + QCString m_tooltip; //!< node's tooltip + QCString m_url; //!< url of the node (format: remote$local) + QList<DotNode> *m_parents; //!< list of parent nodes (incoming arrows) + QList<DotNode> *m_children; //!< list of child nodes (outgoing arrows) + QList<EdgeInfo> *m_edgeInfo; //!< edge info for each child + bool m_deleted; //!< used to mark a node as deleted + mutable bool m_written; //!< used to mark a node as written + bool m_hasDoc; //!< used to mark a node as documented + bool m_isRoot; //!< indicates if this is a root node + const ClassDef * m_classDef; //!< class representing this node (can be 0) + bool m_visible; //!< is the node visible in the output + TruncState m_truncated; //!< does the node have non-visible children/parents + int m_distance; //!< shortest path to the root node + bool m_renumbered;//!< indicates if the node has been renumbered (to prevent endless loops) + int m_subgraphId; +}; + +/** Class representing a list of DotNode objects. */ +class DotNodeList : public QList<DotNode> +{ + public: + DotNodeList() : QList<DotNode>() {} + ~DotNodeList() {} + private: + int compareValues(const DotNode *n1,const DotNode *n2) const; +}; + +#endif diff --git a/src/dotrunner.cpp b/src/dotrunner.cpp new file mode 100644 index 0000000..22a0081 --- /dev/null +++ b/src/dotrunner.cpp @@ -0,0 +1,294 @@ +/****************************************************************************** +* +* Copyright (C) 1997-2019 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. +* +* Documents produced by Doxygen are derivative works derived from the +* input used in their production; they are not affected by this license. +* +*/ + +#include "dotrunner.h" + +#include "util.h" +#include "portable.h" +#include "dot.h" +#include "message.h" +#include "ftextstream.h" +#include "config.h" + +// the graphicx LaTeX has a limitation of maximum size of 16384 +// To be on the save side we take it a little bit smaller i.e. 150 inch * 72 dpi +// It is anyway hard to view these size of images +#define MAX_LATEX_GRAPH_INCH 150 +#define MAX_LATEX_GRAPH_SIZE (MAX_LATEX_GRAPH_INCH * 72) + + +// since dot silently reproduces the input file when it does not +// support the PNG format, we need to check the result. +static void checkPngResult(const char *imgName) +{ + FILE *f = portable_fopen(imgName,"rb"); + if (f) + { + char data[4]; + if (fread(data,1,4,f)==4) + { + if (!(data[1]=='P' && data[2]=='N' && data[3]=='G')) + { + err("Image `%s' produced by dot is not a valid PNG!\n" + "You should either select a different format " + "(DOT_IMAGE_FORMAT in the config file) or install a more " + "recent version of graphviz (1.7+)\n",imgName + ); + } + } + else + { + err("Could not read image `%s' generated by dot!\n",imgName); + } + fclose(f); + } + else + { + err("Could not open image `%s' generated by dot!\n",imgName); + } +} + +static bool resetPDFSize(const int width,const int height, const char *base) +{ + QString tmpName = QString::fromUtf8(QCString(base)+".tmp"); + QString patchFile = QString::fromUtf8(QCString(base)+".dot"); + if (!QDir::current().rename(patchFile,tmpName)) + { + err("Failed to rename file %s to %s!\n",patchFile.data(),tmpName.data()); + return FALSE; + } + QFile fi(tmpName); + QFile fo(patchFile); + if (!fi.open(IO_ReadOnly)) + { + err("problem opening file %s for patching!\n",tmpName.data()); + QDir::current().rename(tmpName,patchFile); + return FALSE; + } + if (!fo.open(IO_WriteOnly)) + { + err("problem opening file %s for patching!\n",patchFile.data()); + QDir::current().rename(tmpName,patchFile); + fi.close(); + return FALSE; + } + FTextStream t(&fo); + const int maxLineLen=100*1024; + while (!fi.atEnd()) // foreach line + { + QCString line(maxLineLen); + int numBytes = fi.readLine(line.rawData(),maxLineLen); + if (numBytes<=0) + { + break; + } + line.resize(numBytes+1); + if (line.find("LATEX_PDF_SIZE") != -1) + { + double scale = (width > height ? width : height)/double(MAX_LATEX_GRAPH_INCH); + t << " size=\""<<width/scale << "," <<height/scale <<"\";\n"; + } + else + t << line; + } + fi.close(); + fo.close(); + // remove temporary file + QDir::current().remove(tmpName); + return TRUE; +} + +bool DotRunner::readBoundingBox(const char *fileName,int *width,int *height,bool isEps) +{ + const char *bb = isEps ? "%%PageBoundingBox:" : "/MediaBox ["; + int bblen = strlen(bb); + FILE *f = portable_fopen(fileName,"rb"); + if (!f) + { + //printf("readBoundingBox: could not open %s\n",fileName); + return FALSE; + } + const int maxLineLen=1024; + char buf[maxLineLen]; + while (fgets(buf,maxLineLen,f)!=NULL) + { + const char *p = strstr(buf,bb); + if (p) // found PageBoundingBox or /MediaBox string + { + int x,y; + fclose(f); + if (sscanf(p+bblen,"%d %d %d %d",&x,&y,width,height)!=4) + { + //printf("readBoundingBox sscanf fail\n"); + return FALSE; + } + return TRUE; + } + } + err("Failed to extract bounding box from generated diagram file %s\n",fileName); + fclose(f); + return FALSE; +} + +bool DotRunner::DOT_CLEANUP; +bool DotRunner::DOT_MULTI_TARGETS; +DotConstString DotRunner::DOT_EXE; + +DotRunner::DotRunner(const QCString& absDotName, const QCString& md5Hash) + : m_file(absDotName), m_md5Hash(md5Hash), m_cleanUp(DOT_CLEANUP) +{ + m_jobs.setAutoDelete(TRUE); +} + +void DotRunner::addJob(const char *format,const char *output) +{ + QListIterator<DotJob> li(m_jobs); + DotJob *s; + for (li.toFirst(); (s = li.current()); ++li) + { + if (qstrcmp(s->format.data(), format) != 0) continue; + if (qstrcmp(s->output.data(), output) != 0) continue; + // we have this job already + return; + } + QCString args = QCString("-T")+format+" -o \""+output+"\""; + m_jobs.append(new DotJob(format, output, args)); +} + +QCString getBaseNameOfOutput(QCString const& output) +{ + int index = output.findRev('.'); + if (index < 0) return output; + return output.left(index); +} + +bool DotRunner::run() +{ + int exitCode=0; + + QCString dotArgs; + QListIterator<DotJob> li(m_jobs); + DotJob *s; + + // create output + if (DOT_MULTI_TARGETS) + { + dotArgs=QCString("\"")+m_file.data()+"\""; + for (li.toFirst();(s=li.current());++li) + { + dotArgs+=' '; + dotArgs+=s->args.data(); + } + if ((exitCode=portable_system(DOT_EXE.data(),dotArgs,FALSE))!=0) goto error; + } + else + { + for (li.toFirst();(s=li.current());++li) + { + dotArgs=QCString("\"")+m_file.data()+"\" "+s->args.data(); + if ((exitCode=portable_system(DOT_EXE.data(),dotArgs,FALSE))!=0) goto error; + } + } + + // check output + // As there should be only one pdf file be generated, we don't need code for regenerating multiple pdf files in one call + for (li.toFirst();(s=li.current());++li) + { + if (qstrncmp(s->format.data(), "pdf", 3) == 0) + { + int width=0,height=0; + if (!readBoundingBox(s->output.data(),&width,&height,FALSE)) goto error; + if ((width > MAX_LATEX_GRAPH_SIZE) || (height > MAX_LATEX_GRAPH_SIZE)) + { + if (!resetPDFSize(width,height,getBaseNameOfOutput(s->output.data()))) goto error; + dotArgs=QCString("\"")+m_file.data()+"\" "+s->args.data(); + if ((exitCode=portable_system(DOT_EXE.data(),dotArgs,FALSE))!=0) goto error; + } + } + + if (qstrncmp(s->format.data(), "png", 3) == 0) + { + checkPngResult(s->output.data()); + } + } + + // remove .dot files + if (m_cleanUp) + { + //printf("removing dot file %s\n",m_file.data()); + portable_unlink(m_file.data()); + } + + // create checksum file + if (!m_md5Hash.isEmpty()) + { + QCString md5Name = getBaseNameOfOutput(m_file.data()) + ".md5"; + FILE *f = portable_fopen(md5Name,"w"); + if (f) + { + fwrite(m_md5Hash.data(),1,32,f); + fclose(f); + } + } + return TRUE; +error: + err("Problems running dot: exit code=%d, command='%s', arguments='%s'\n", + exitCode,DOT_EXE.data(),dotArgs.data()); + return FALSE; +} + + +//-------------------------------------------------------------------- + +void DotRunnerQueue::enqueue(DotRunner *runner) +{ + QMutexLocker locker(&m_mutex); + m_queue.enqueue(runner); + m_bufferNotEmpty.wakeAll(); +} + +DotRunner *DotRunnerQueue::dequeue() +{ + QMutexLocker locker(&m_mutex); + while (m_queue.isEmpty()) + { + // wait until something is added to the queue + m_bufferNotEmpty.wait(&m_mutex); + } + DotRunner *result = m_queue.dequeue(); + return result; +} + +uint DotRunnerQueue::count() const +{ + QMutexLocker locker(&m_mutex); + return m_queue.count(); +} + +//-------------------------------------------------------------------- + +DotWorkerThread::DotWorkerThread(DotRunnerQueue *queue) + : m_queue(queue) +{ +} + +void DotWorkerThread::run() +{ + DotRunner *runner; + while ((runner=m_queue->dequeue())) + { + runner->run(); + } +} diff --git a/src/dotrunner.h b/src/dotrunner.h new file mode 100644 index 0000000..4128fe8 --- /dev/null +++ b/src/dotrunner.h @@ -0,0 +1,138 @@ +/****************************************************************************** +* +* Copyright (C) 1997-2019 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. +* +* Documents produced by Doxygen are derivative works derived from the +* input used in their production; they are not affected by this license. +* +*/ + +#ifndef DOTRUNNER_H +#define DOTRUNNER_H + +#include "qcstring.h" +#include "qlist.h" +#include "qwaitcondition.h" +#include "qthread.h" +#include "qqueue.h" +#include "qmutex.h" + +/** Minimal constant string class that is thread safe, once initialized. */ +class DotConstString +{ + public: + DotConstString() { m_str=0;} + ~DotConstString() { delete[] m_str;} + DotConstString(char const* s) : m_str(0) { set(s); } + DotConstString(const QCString &s) : m_str(0) { set(s); } + DotConstString(const DotConstString &s) : m_str(0) { set(s.data()); } + const char *data() const { return m_str; } + bool isEmpty() const { return m_str==0 || m_str[0]=='\0'; } + void init(const char *s) { set(s); } + + private: + void set(char const* s) + { + delete[] m_str; + m_str=0; + if (s) + { + m_str=new char[strlen(s) + 1]; + qstrcpy(m_str,s); + } + } + + void set(const QCString &s) + { + delete[] m_str; + m_str=0; + if (!s.isEmpty()) + { + m_str=new char[s.length()+1]; + qstrcpy(m_str,s.data()); + } + } + + DotConstString &operator=(const DotConstString &); + + char *m_str; +}; + +/** Helper class to run dot from doxygen from multiple threads. */ +class DotRunner +{ + public: + struct DotJob + { + DotJob(const DotConstString & format, + const DotConstString & output, + const DotConstString & args) + : format(format), output(output), args(args) {} + DotConstString format; + DotConstString output; + DotConstString args; + }; + + /** Creates a runner for a dot \a file. */ + DotRunner(const QCString& absDotName, const QCString& md5Hash); + + /** Adds an additional job to the run. + * Performing multiple jobs one file can be faster. + */ + void addJob(const char *format,const char *output); + + /** Prevent cleanup of the dot file (for user provided dot files) */ + void preventCleanUp() { m_cleanUp = FALSE; } + + /** Runs dot for all jobs added. */ + bool run(); + + // DotConstString const& getFileName() { return m_file; } + DotConstString const& getMd5Hash() { return m_md5Hash; } + + static bool readBoundingBox(const char* fileName, int* width, int* height, bool isEps); + + private: + DotConstString m_file; + DotConstString m_md5Hash; + bool m_cleanUp; + QList<DotJob> m_jobs; + + static bool DOT_CLEANUP; + static bool DOT_MULTI_TARGETS; + static DotConstString DOT_EXE; + friend void initDot(); + +}; + +/** Queue of dot jobs to run. */ +// all methods are thread save +class DotRunnerQueue +{ + public: + void enqueue(DotRunner *runner); + DotRunner *dequeue(); + uint count() const; + private: + QWaitCondition m_bufferNotEmpty; + QQueue<DotRunner> m_queue; + mutable QMutex m_mutex; +}; + +/** Worker thread to execute a dot run */ +class DotWorkerThread : public QThread +{ + public: + DotWorkerThread(DotRunnerQueue *queue); + void run(); + private: + DotRunnerQueue *m_queue; +}; + +#endif diff --git a/src/doxygen.cpp b/src/doxygen.cpp index 9c98d8c..92e5292 100644 --- a/src/doxygen.cpp +++ b/src/doxygen.cpp @@ -174,6 +174,7 @@ QCString Doxygen::spaces; bool Doxygen::generatingXmlOutput = FALSE; bool Doxygen::markdownSupport = TRUE; GenericsSDict *Doxygen::genericsDict; +DocGroup Doxygen::docGroup; // locally accessible globals static QDict<Entry> g_classEntries(1009); @@ -766,6 +767,16 @@ static void buildFileList(Entry *root) { bool ambig; FileDef *fd=findFileDef(Doxygen::inputNameDict,root->name,ambig); + if (!fd || ambig) + { + int save_ambig = ambig; + // use the directory of the file to see if the described file is in the same + // directory as the describing file. + QCString fn = root->fileName; + int newIndex=fn.findRev('/'); + fd=findFileDef(Doxygen::inputNameDict,fn.left(newIndex) + "/" + root->name,ambig); + if (!fd) ambig = save_ambig; + } //printf("**************** root->name=%s fd=%p\n",root->name.data(),fd); if (fd && !ambig) { @@ -795,7 +806,7 @@ static void buildFileList(Entry *root) const char *fn = root->fileName.data(); QCString text(4096); text.sprintf("the name `%s' supplied as " - "the second argument in the \\file statement ", + "the argument in the \\file statement ", qPrint(root->name)); if (ambig) // name is ambiguous { @@ -1209,7 +1220,6 @@ ClassDef::CompoundType convertToCompoundType(int section,uint64 specifier) static void addClassToContext(Entry *root) { - //printf("Loading entry for rootNav=%p name=%s\n",rootNav,rootNav->name().data()); FileDef *fd = root->fileDef(); QCString scName; @@ -1423,6 +1433,31 @@ static void resolveClassNestingRelations() //printf("****** adding %s to scope %s in iteration %d\n",cd->name().data(),d->name().data(),iteration); d->addInnerCompound(cd); cd->setOuterScope(d); + + // for inline namespace add an alias of the class to the outer scope + while (d->definitionType()==DefinitionIntf::TypeNamespace) + { + NamespaceDef *nd = dynamic_cast<NamespaceDef*>(d); + //printf("d->isInline()=%d\n",nd->isInline()); + if (nd->isInline()) + { + d = d->getOuterScope(); + if (d) + { + ClassDef *aliasCd = createClassDefAlias(d,cd); + d->addInnerCompound(aliasCd); + QCString aliasFullName = d->qualifiedName()+"::"+aliasCd->localName(); + Doxygen::classSDict->append(aliasFullName,aliasCd); + printf("adding %s to %s as %s\n",qPrint(aliasCd->name()),qPrint(d->name()),qPrint(aliasFullName)); + aliasCd->setVisited(TRUE); + } + } + else + { + break; + } + } + cd->setVisited(TRUE); done=FALSE; } @@ -1752,6 +1787,7 @@ static void buildNamespaceList(Entry *root) nd->setLanguage(root->lang); nd->setId(root->id); nd->setMetaData(root->metaData); + nd->setInline((root->spec&Entry::Inline)!=0); //printf("Adding namespace to group\n"); addNamespaceToGroups(root,nd); @@ -1786,6 +1822,25 @@ static void buildNamespaceList(Entry *root) { d->addInnerCompound(nd); nd->setOuterScope(d); + // in case of d is an inline namespace, alias insert nd in the part scope of d. + while (d->definitionType()==DefinitionIntf::TypeNamespace) + { + NamespaceDef *pnd = dynamic_cast<NamespaceDef*>(d); + if (pnd->isInline()) + { + d = d->getOuterScope(); + if (d) + { + NamespaceDef *aliasNd = createNamespaceDefAlias(d,nd); + //printf("adding %s to %s\n",qPrint(aliasNd->name()),qPrint(d->name())); + d->addInnerCompound(aliasNd); + } + } + else + { + break; + } + } } } } @@ -1795,15 +1850,15 @@ static void buildNamespaceList(Entry *root) //---------------------------------------------------------------------- -static NamespaceDef *findUsedNamespace(NamespaceSDict *unl, +static const NamespaceDef *findUsedNamespace(const NamespaceSDict *unl, const QCString &name) { - NamespaceDef *usingNd =0; + const NamespaceDef *usingNd =0; if (unl) { //printf("Found namespace dict %d\n",unl->count()); NamespaceSDict::Iterator unli(*unl); - NamespaceDef *und; + const NamespaceDef *und; for (unli.toFirst();(und=unli.current());++unli) { QCString uScope=und->name()+"::"; @@ -1827,7 +1882,7 @@ static void findUsingDirectives(Entry *root) } if (!name.isEmpty()) { - NamespaceDef *usingNd = 0; + const NamespaceDef *usingNd = 0; NamespaceDef *nd = 0; FileDef *fd = root->fileDef(); QCString nsName; @@ -1869,17 +1924,17 @@ static void findUsingDirectives(Entry *root) if (usingNd==0 && nd) // not found, try used namespaces in this scope // or in one of the parent namespace scopes { - NamespaceDef *pnd = nd; + const NamespaceDef *pnd = nd; while (pnd && usingNd==0) { // also try with one of the used namespaces found earlier usingNd = findUsedNamespace(pnd->getUsedNamespaces(),name); // goto the parent - Definition *s = pnd->getOuterScope(); + const Definition *s = pnd->getOuterScope(); if (s && s->definitionType()==Definition::TypeNamespace) { - pnd = dynamic_cast<NamespaceDef*>(s); + pnd = dynamic_cast<const NamespaceDef*>(s); } else { @@ -1923,6 +1978,7 @@ static void findUsingDirectives(Entry *root) nd->setLanguage(root->lang); nd->setId(root->id); nd->setMetaData(root->metaData); + nd->setInline((root->spec&Entry::Inline)!=0); QListIterator<Grouping> gli(*root->groups); Grouping *g; @@ -2014,7 +2070,7 @@ static void findUsingDeclarations(Entry *root) // vector -> std::vector if (usingCd==0) { - usingCd = getResolvedClass(nd,fd,name); // try via resolving (see also bug757509) + usingCd = const_cast<ClassDef*>(getResolvedClass(nd,fd,name)); // try via resolving (see also bug757509) } if (usingCd==0) { @@ -2080,7 +2136,7 @@ static void findUsingDeclImports(Entry *root) { QCString scope=root->name.left(i); QCString memName=root->name.right(root->name.length()-i-2); - ClassDef *bcd = getResolvedClass(cd,0,scope); // todo: file in fileScope parameter + const ClassDef *bcd = getResolvedClass(cd,0,scope); // todo: file in fileScope parameter if (bcd) { //printf("found class %s memName=%s\n",bcd->name().data(),memName.data()); @@ -2105,8 +2161,8 @@ static void findUsingDeclImports(Entry *root) { fileName = root->tagInfo->tagName; } - ArgumentList *templAl = md->templateArguments(); - ArgumentList *al = md->templateArguments(); + const ArgumentList *templAl = md->templateArguments(); + const ArgumentList *al = md->templateArguments(); newMd = createMemberDef( fileName,root->startLine,root->startColumn, md->typeString(),memName,md->argsString(), @@ -2272,7 +2328,8 @@ static MemberDef *addVariableToClass( { //printf("md->getClassDef()=%p cd=%p type=[%s] md->typeString()=[%s]\n", // md->getClassDef(),cd,root->type.data(),md->typeString()); - if (md->getClassDef()==cd && + if (!md->isAlias() && + md->getClassDef()==cd && removeRedundantWhiteSpace(root->type)==md->typeString()) // member already in the scope { @@ -2500,7 +2557,7 @@ static MemberDef *addVariableToFile( MemberDef *md; for (mni.toFirst();(md=mni.current());++mni) { - if ( + if (!md->isAlias() && ((nd==0 && md->getNamespaceDef()==0 && md->getFileDef() && root->fileName==md->getFileDef()->absFilePath() ) // both variable names in the same file @@ -3541,146 +3598,149 @@ static void buildFunctionList(Entry *root) MemberNameIterator mni(*mn); for (mni.toFirst();(!found && (md=mni.current()));++mni) { - NamespaceDef *mnd = md->getNamespaceDef(); - NamespaceDef *rnd = 0; - //printf("root namespace=%s\n",rootNav->parent()->name().data()); - QCString fullScope = scope; - QCString parentScope = root->parent()->name; - if (!parentScope.isEmpty() && !leftScopeMatch(parentScope,scope)) + if (!md->isAlias()) { - if (!scope.isEmpty()) fullScope.prepend("::"); - fullScope.prepend(parentScope); - } - //printf("fullScope=%s\n",fullScope.data()); - rnd = getResolvedNamespace(fullScope); - FileDef *mfd = md->getFileDef(); - QCString nsName,rnsName; - if (mnd) nsName = mnd->name().copy(); - if (rnd) rnsName = rnd->name().copy(); - //printf("matching arguments for %s%s %s%s\n", - // md->name().data(),md->argsString(),rname.data(),argListToString(root->argList).data()); - ArgumentList *mdAl = md->argumentList(); - ArgumentList *mdTempl = md->templateArguments(); - - // in case of template functions, we need to check if the - // functions have the same number of template parameters - bool sameNumTemplateArgs = TRUE; - bool matchingReturnTypes = TRUE; - if (mdTempl!=0 && root->tArgLists) - { - if (mdTempl->count()!=root->tArgLists->getLast()->count()) + const NamespaceDef *mnd = md->getNamespaceDef(); + NamespaceDef *rnd = 0; + //printf("root namespace=%s\n",rootNav->parent()->name().data()); + QCString fullScope = scope; + QCString parentScope = root->parent()->name; + if (!parentScope.isEmpty() && !leftScopeMatch(parentScope,scope)) { - sameNumTemplateArgs = FALSE; + if (!scope.isEmpty()) fullScope.prepend("::"); + fullScope.prepend(parentScope); } - if (md->typeString()!=removeRedundantWhiteSpace(root->type)) + //printf("fullScope=%s\n",fullScope.data()); + rnd = getResolvedNamespace(fullScope); + const FileDef *mfd = md->getFileDef(); + QCString nsName,rnsName; + if (mnd) nsName = mnd->name().copy(); + if (rnd) rnsName = rnd->name().copy(); + //printf("matching arguments for %s%s %s%s\n", + // md->name().data(),md->argsString(),rname.data(),argListToString(root->argList).data()); + ArgumentList *mdAl = md->argumentList(); + const ArgumentList *mdTempl = md->templateArguments(); + + // in case of template functions, we need to check if the + // functions have the same number of template parameters + bool sameNumTemplateArgs = TRUE; + bool matchingReturnTypes = TRUE; + if (mdTempl!=0 && root->tArgLists) { - matchingReturnTypes = FALSE; + if (mdTempl->count()!=root->tArgLists->getLast()->count()) + { + sameNumTemplateArgs = FALSE; + } + if (md->typeString()!=removeRedundantWhiteSpace(root->type)) + { + matchingReturnTypes = FALSE; + } } - } - bool staticsInDifferentFiles = - root->stat && md->isStatic() && root->fileName!=md->getDefFileName(); + bool staticsInDifferentFiles = + root->stat && md->isStatic() && root->fileName!=md->getDefFileName(); - if ( - matchArguments2(md->getOuterScope(),mfd,mdAl, - rnd ? rnd : Doxygen::globalScope,rfd,root->argList, - FALSE) && - sameNumTemplateArgs && - matchingReturnTypes && - !staticsInDifferentFiles - ) - { - GroupDef *gd=0; - if (root->groups->getFirst()!=0) - { - gd = Doxygen::groupSDict->find(root->groups->getFirst()->groupname.data()); - } - //printf("match!\n"); - //printf("mnd=%p rnd=%p nsName=%s rnsName=%s\n",mnd,rnd,nsName.data(),rnsName.data()); - // see if we need to create a new member - found=(mnd && rnd && nsName==rnsName) || // members are in the same namespace - ((mnd==0 && rnd==0 && mfd!=0 && // no external reference and - mfd->absFilePath()==root->fileName // prototype in the same file - ) - ); - // otherwise, allow a duplicate global member with the same argument list - if (!found && gd && gd==md->getGroupDef() && nsName==rnsName) + if ( + matchArguments2(md->getOuterScope(),mfd,mdAl, + rnd ? rnd : Doxygen::globalScope,rfd,root->argList, + FALSE) && + sameNumTemplateArgs && + matchingReturnTypes && + !staticsInDifferentFiles + ) { - // member is already in the group, so we don't want to add it again. - found=TRUE; - } + GroupDef *gd=0; + if (root->groups->getFirst()!=0) + { + gd = Doxygen::groupSDict->find(root->groups->getFirst()->groupname.data()); + } + //printf("match!\n"); + //printf("mnd=%p rnd=%p nsName=%s rnsName=%s\n",mnd,rnd,nsName.data(),rnsName.data()); + // see if we need to create a new member + found=(mnd && rnd && nsName==rnsName) || // members are in the same namespace + ((mnd==0 && rnd==0 && mfd!=0 && // no external reference and + mfd->absFilePath()==root->fileName // prototype in the same file + ) + ); + // otherwise, allow a duplicate global member with the same argument list + if (!found && gd && gd==md->getGroupDef() && nsName==rnsName) + { + // member is already in the group, so we don't want to add it again. + found=TRUE; + } - //printf("combining function with prototype found=%d in namespace %s\n", - // found,nsName.data()); + //printf("combining function with prototype found=%d in namespace %s\n", + // found,nsName.data()); - if (found) - { - // merge argument lists - mergeArguments(mdAl,root->argList,!root->doc.isEmpty()); - // merge documentation - if (md->documentation().isEmpty() && !root->doc.isEmpty()) + if (found) { - ArgumentList *argList = new ArgumentList; - stringToArgumentList(root->args,argList); - if (root->proto) + // merge argument lists + mergeArguments(mdAl,root->argList,!root->doc.isEmpty()); + // merge documentation + if (md->documentation().isEmpty() && !root->doc.isEmpty()) { - //printf("setDeclArgumentList to %p\n",argList); - md->setDeclArgumentList(argList); + ArgumentList *argList = new ArgumentList; + stringToArgumentList(root->args,argList); + if (root->proto) + { + //printf("setDeclArgumentList to %p\n",argList); + md->setDeclArgumentList(argList); + } + else + { + md->setArgumentList(argList); + } } - else + + md->setDocumentation(root->doc,root->docFile,root->docLine); + md->setInbodyDocumentation(root->inbodyDocs,root->inbodyFile,root->inbodyLine); + md->setDocsForDefinition(!root->proto); + if (md->getStartBodyLine()==-1 && root->bodyLine!=-1) { - md->setArgumentList(argList); + md->setBodySegment(root->bodyLine,root->endBodyLine); + md->setBodyDef(rfd); } - } - - md->setDocumentation(root->doc,root->docFile,root->docLine); - md->setInbodyDocumentation(root->inbodyDocs,root->inbodyFile,root->inbodyLine); - md->setDocsForDefinition(!root->proto); - if (md->getStartBodyLine()==-1 && root->bodyLine!=-1) - { - md->setBodySegment(root->bodyLine,root->endBodyLine); - md->setBodyDef(rfd); - } - if (md->briefDescription().isEmpty() && !root->brief.isEmpty()) - { - md->setArgsString(root->args); - } - md->setBriefDescription(root->brief,root->briefFile,root->briefLine); + if (md->briefDescription().isEmpty() && !root->brief.isEmpty()) + { + md->setArgsString(root->args); + } + md->setBriefDescription(root->brief,root->briefFile,root->briefLine); - md->addSectionsToDefinition(root->anchors); + md->addSectionsToDefinition(root->anchors); - md->enableCallGraph(md->hasCallGraph() || root->callGraph); - md->enableCallerGraph(md->hasCallerGraph() || root->callerGraph); - md->enableReferencedByRelation(md->hasReferencedByRelation() || root->referencedByRelation); - md->enableReferencesRelation(md->hasReferencesRelation() || root->referencesRelation); + md->enableCallGraph(md->hasCallGraph() || root->callGraph); + md->enableCallerGraph(md->hasCallerGraph() || root->callerGraph); + md->enableReferencedByRelation(md->hasReferencedByRelation() || root->referencedByRelation); + md->enableReferencesRelation(md->hasReferencesRelation() || root->referencesRelation); - // merge ingroup specifiers - if (md->getGroupDef()==0 && root->groups->getFirst()!=0) - { - addMemberToGroups(root,md); - } - else if (md->getGroupDef()!=0 && root->groups->count()==0) - { - //printf("existing member is grouped, new member not\n"); - root->groups->append(new Grouping(md->getGroupDef()->name(), md->getGroupPri())); - } - else if (md->getGroupDef()!=0 && root->groups->getFirst()!=0) - { - //printf("both members are grouped\n"); - } + // merge ingroup specifiers + if (md->getGroupDef()==0 && root->groups->getFirst()!=0) + { + addMemberToGroups(root,md); + } + else if (md->getGroupDef()!=0 && root->groups->count()==0) + { + //printf("existing member is grouped, new member not\n"); + root->groups->append(new Grouping(md->getGroupDef()->name(), md->getGroupPri())); + } + else if (md->getGroupDef()!=0 && root->groups->getFirst()!=0) + { + //printf("both members are grouped\n"); + } - // if md is a declaration and root is the corresponding - // definition, then turn md into a definition. - if (md->isPrototype() && !root->proto) - { - md->setDeclFile(md->getDefFileName(),md->getDefLine(),md->getDefColumn()); - md->setPrototype(FALSE,root->fileName,root->startLine,root->startColumn); - } - // if md is already the definition, then add the declaration info - else if (!md->isPrototype() && root->proto) - { - md->setDeclFile(root->fileName,root->startLine,root->startColumn); + // if md is a declaration and root is the corresponding + // definition, then turn md into a definition. + if (md->isPrototype() && !root->proto) + { + md->setDeclFile(md->getDefFileName(),md->getDefLine(),md->getDefColumn()); + md->setPrototype(FALSE,root->fileName,root->startLine,root->startColumn); + } + // if md is already the definition, then add the declaration info + else if (!md->isPrototype() && root->proto) + { + md->setDeclFile(root->fileName,root->startLine,root->startColumn); + } } } } @@ -3870,24 +3930,27 @@ static void findFriends() MemberDef *fmd; for (;(fmd=fni.current());++fni) // for each function with that name { + const MemberDef *cfmd = const_cast<const MemberDef*>(fmd); MemberNameIterator mni(*mn); MemberDef *mmd; for (;(mmd=mni.current());++mni) // for each member with that name { + const MemberDef *cmmd = const_cast<const MemberDef*>(mmd); //printf("Checking for matching arguments // mmd->isRelated()=%d mmd->isFriend()=%d mmd->isFunction()=%d\n", // mmd->isRelated(),mmd->isFriend(),mmd->isFunction()); - ArgumentList *mmdAl = mmd->argumentList(); - ArgumentList *fmdAl = fmd->argumentList(); - if ((mmd->isFriend() || (mmd->isRelated() && mmd->isFunction())) && - matchArguments2(mmd->getOuterScope(), mmd->getFileDef(), mmdAl, - fmd->getOuterScope(), fmd->getFileDef(), fmdAl, + if ((cmmd->isFriend() || (cmmd->isRelated() && cmmd->isFunction())) && + !fmd->isAlias() && !mmd->isAlias() && + matchArguments2(cmmd->getOuterScope(), cmmd->getFileDef(), cmmd->argumentList(), + cfmd->getOuterScope(), cfmd->getFileDef(), cfmd->argumentList(), TRUE ) ) // if the member is related and the arguments match then the // function is actually a friend. { + ArgumentList *mmdAl = mmd->argumentList(); + ArgumentList *fmdAl = fmd->argumentList(); mergeArguments(mmdAl,fmdAl); if (!fmd->documentation().isEmpty()) { @@ -3968,7 +4031,10 @@ static void transferFunctionDocumentation() MemberNameIterator mni2(*mn); for (;(mdef=mni2.current());++mni2) { - combineDeclarationAndDefinition(mdec,mdef); + if (!mdec->isAlias() && !mdef->isAlias()) + { + combineDeclarationAndDefinition(mdec,mdef); + } } } } @@ -4091,12 +4157,11 @@ static void transferRelatedFunctionDocumentation() MemberNameIterator rmni(*rmn); for (rmni.toFirst();(rmd=rmni.current());++rmni) // for each member with the same name { - ArgumentList *mdAl = md->argumentList(); - ArgumentList *rmdAl = rmd->argumentList(); //printf(" Member found: related=`%d'\n",rmd->isRelated()); if ((rmd->isRelated() || rmd->isForeign()) && // related function - matchArguments2( md->getOuterScope(), md->getFileDef(), mdAl, - rmd->getOuterScope(),rmd->getFileDef(),rmdAl, + !md->isAlias() && !rmd->isAlias() && + matchArguments2( md->getOuterScope(), md->getFileDef(), md->argumentList(), + rmd->getOuterScope(),rmd->getFileDef(),rmd->argumentList(), TRUE ) ) @@ -4165,11 +4230,11 @@ static ClassDef *findClassWithinClassContext(Definition *context,ClassDef *cd,co FileDef *fd=cd->getFileDef(); if (context && cd!=context) { - result = getResolvedClass(context,0,name,0,0,TRUE,TRUE); + result = const_cast<ClassDef*>(getResolvedClass(context,0,name,0,0,TRUE,TRUE)); } if (result==0) { - result = getResolvedClass(cd,fd,name,0,0,TRUE,TRUE); + result = const_cast<ClassDef*>(getResolvedClass(cd,fd,name,0,0,TRUE,TRUE)); } if (result==0) // try direct class, needed for namespaced classes imported via tag files (see bug624095) { @@ -4237,7 +4302,7 @@ static void findUsedClassesForClass(Entry *root, while (!found && extractClassNameFromType(type,pos,usedClassName,templSpec,root->lang)!=-1) { // find the type (if any) that matches usedClassName - ClassDef *typeCd = getResolvedClass(masterCd, + const ClassDef *typeCd = getResolvedClass(masterCd, masterCd->getFileDef(), usedClassName, 0,0, @@ -4638,16 +4703,17 @@ static bool findClassRelation( //baseClassName=stripTemplateSpecifiersFromScope // (removeRedundantWhiteSpace(baseClassName),TRUE, // &stripped); - MemberDef *baseClassTypeDef=0; + const MemberDef *baseClassTypeDef=0; QCString templSpec; - ClassDef *baseClass=getResolvedClass(explicitGlobalScope ? Doxygen::globalScope : context, + ClassDef *baseClass=const_cast<ClassDef*>( + getResolvedClass(explicitGlobalScope ? Doxygen::globalScope : context, cd->getFileDef(), baseClassName, &baseClassTypeDef, &templSpec, mode==Undocumented, TRUE - ); + )); //printf("baseClassName=%s baseClass=%p cd=%p explicitGlobalScope=%d\n", // baseClassName.data(),baseClass,cd,explicitGlobalScope); //printf(" scope=`%s' baseClassName=`%s' baseClass=%s templSpec=%s\n", @@ -4698,14 +4764,15 @@ static bool findClassRelation( { templSpec=removeRedundantWhiteSpace(baseClassName.mid(i,e-i)); baseClassName=baseClassName.left(i)+baseClassName.right(baseClassName.length()-e); - baseClass=getResolvedClass(explicitGlobalScope ? Doxygen::globalScope : context, - cd->getFileDef(), - baseClassName, - &baseClassTypeDef, - 0, //&templSpec, - mode==Undocumented, - TRUE - ); + baseClass=const_cast<ClassDef*>( + getResolvedClass(explicitGlobalScope ? Doxygen::globalScope : context, + cd->getFileDef(), + baseClassName, + &baseClassTypeDef, + 0, //&templSpec, + mode==Undocumented, + TRUE + )); //printf("baseClass=%p -> baseClass=%s templSpec=%s\n", // baseClass,baseClassName.data(),templSpec.data()); } @@ -4734,14 +4801,15 @@ static bool findClassRelation( QCString tmpTemplSpec; // replace any namespace aliases replaceNamespaceAliases(baseClassName,si); - baseClass=getResolvedClass(explicitGlobalScope ? Doxygen::globalScope : context, + baseClass=const_cast<ClassDef*>( + getResolvedClass(explicitGlobalScope ? Doxygen::globalScope : context, cd->getFileDef(), baseClassName, &baseClassTypeDef, &tmpTemplSpec, mode==Undocumented, TRUE - ); + )); found=baseClass!=0 && baseClass!=cd; if (found) templSpec = tmpTemplSpec; } @@ -5183,7 +5251,10 @@ static void addListReferences() ClassDef *cd=0; for (cli.toFirst();(cd=cli.current());++cli) { - cd->addListReferences(); + if (!cd->isAlias()) + { + cd->addListReferences(); + } } FileNameListIterator fnli(*Doxygen::inputNameList); @@ -5202,7 +5273,10 @@ static void addListReferences() NamespaceDef *nd=0; for (nli.toFirst();(nd=nli.current());++nli) { - nd->addListReferences(); + if (!nd->isAlias()) + { + nd->addListReferences(); + } } GroupSDict::Iterator gli(*Doxygen::groupSDict); @@ -5281,8 +5355,8 @@ static void addMemberDocs(Entry *root, md->enableCallerGraph(root->callerGraph); md->enableReferencedByRelation(root->referencedByRelation); md->enableReferencesRelation(root->referencesRelation); - ClassDef *cd=md->getClassDef(); - NamespaceDef *nd=md->getNamespaceDef(); + ClassDef *cd=md->getClassDef(); + const NamespaceDef *nd=md->getNamespaceDef(); QCString fullName; if (cd) fullName = cd->name(); @@ -5407,10 +5481,10 @@ static void addMemberDocs(Entry *root, // find a class definition given the scope name and (optionally) a // template list specifier -static ClassDef *findClassDefinition(FileDef *fd,NamespaceDef *nd, +static const ClassDef *findClassDefinition(FileDef *fd,NamespaceDef *nd, const char *scopeName) { - ClassDef *tcd = getResolvedClass(nd,fd,scopeName,0,0,TRUE,TRUE); + const ClassDef *tcd = getResolvedClass(nd,fd,scopeName,0,0,TRUE,TRUE); return tcd; } @@ -5448,12 +5522,20 @@ static bool findGlobalMember(Entry *root, bool found=FALSE; for (mni.toFirst();(md=mni.current()) && !found;++mni) { - NamespaceDef *nd=md->getNamespaceDef(); - - //printf("Namespace namespaceName=%s nd=%s\n", - // namespaceName.data(),nd ? nd->name().data() : "<none>"); + const NamespaceDef *nd=0; + if (md->isAlias() && md->getOuterScope() && + md->getOuterScope()->definitionType()==Definition::TypeNamespace) + { + nd = dynamic_cast<const NamespaceDef *>(md->getOuterScope()); + } + else + { + nd = md->getNamespaceDef(); + } + //const Definition *scope=md->getOuterScope(); + //md = md->resolveAlias(); - FileDef *fd=root->fileDef(); + const FileDef *fd=root->fileDef(); //printf("File %s\n",fd ? fd->name().data() : "<none>"); NamespaceSDict *nl = fd ? fd->getUsedNamespaces() : 0; //SDict<Definition> *cl = fd ? fd->getUsedClasses() : 0; @@ -5474,11 +5556,11 @@ static bool findGlobalMember(Entry *root, NamespaceDef *rnd = 0; if (!namespaceName.isEmpty()) rnd = Doxygen::namespaceSDict->find(namespaceName); - ArgumentList *mdAl = md->argumentList(); + const ArgumentList *mdAl = const_cast<const MemberDef *>(md)->argumentList(); bool matching= (mdAl==0 && root->argList->count()==0) || md->isVariable() || md->isTypedef() || /* in case of function pointers */ - matchArguments2(md->getOuterScope(),md->getFileDef(),mdAl, + matchArguments2(md->getOuterScope(),const_cast<const MemberDef *>(md)->getFileDef(),mdAl, rnd ? rnd : Doxygen::globalScope,fd,root->argList, FALSE); @@ -5487,7 +5569,7 @@ static bool findGlobalMember(Entry *root, // different functions. if (matching && root->tArgLists) { - ArgumentList *mdTempl = md->templateArguments(); + const ArgumentList *mdTempl = md->templateArguments(); if (mdTempl) { if (root->tArgLists->getLast()->count()!=mdTempl->count()) @@ -5528,7 +5610,7 @@ static bool findGlobalMember(Entry *root, if (matching) // add docs to the member { Debug::print(Debug::FindMembers,0,"5. Match found\n"); - addMemberDocs(root,md,decl,root->argList,FALSE); + addMemberDocs(root,md->resolveAlias(),decl,root->argList,FALSE); found=TRUE; } } @@ -5547,7 +5629,7 @@ static bool findGlobalMember(Entry *root, warnMsg+=" '"; warnMsg+=substitute(md->declaration(),"%","%%"); warnMsg+="' at line "+QCString().setNum(md->getDefLine())+ - " of file"+md->getDefFileName()+"\n"; + " of file "+md->getDefFileName()+"\n"; } } warn(root->fileName,root->startLine,warnMsg); @@ -5587,12 +5669,12 @@ static bool isSpecialization( return FALSE; } -static bool scopeIsTemplate(Definition *d) +static bool scopeIsTemplate(const Definition *d) { bool result=FALSE; if (d && d->definitionType()==Definition::TypeClass) { - result = (dynamic_cast<ClassDef*>(d))->templateArguments() || scopeIsTemplate(d->getOuterScope()); + result = (dynamic_cast<const ClassDef*>(d))->templateArguments() || scopeIsTemplate(d->getOuterScope()); } return result; } @@ -6089,7 +6171,7 @@ static void findMember(Entry *root, //printf("scopeName %s->%s\n",scopeName.data(), // stripTemplateSpecifiersFromScope(scopeName,FALSE).data()); - ClassDef *tcd=findClassDefinition(fd,nd,scopeName); + const ClassDef *tcd=findClassDefinition(fd,nd,scopeName); if (tcd==0 && cd && stripAnonymousNamespaceScope(cd->name())==scopeName) { // don't be fooled by anonymous scopes @@ -6106,7 +6188,7 @@ static void findMember(Entry *root, // get the template parameter lists found at the member declaration QList<ArgumentList> declTemplArgs; cd->getTemplateParameterLists(declTemplArgs); - ArgumentList *templAl = md->templateArguments(); + const ArgumentList *templAl = md->templateArguments(); if (templAl) { declTemplArgs.append(templAl); @@ -6224,6 +6306,8 @@ static void findMember(Entry *root, // TODO: copy other aspects? root->protection=md->protection(); // copy protection level + root->stat=md->isStatic(); + root->virt=md->virtualness(); addMethodToClass(root,cd,md->name(),isFriend); return; } @@ -6251,7 +6335,7 @@ static void findMember(Entry *root, if (count==0 && !(isFriend && funcType=="class")) { int candidates=0; - ClassDef *ecd = 0, *ucd = 0; + const ClassDef *ecd = 0, *ucd = 0; MemberDef *emd = 0, *umd = 0; if (mn->count()>0) { @@ -6263,10 +6347,14 @@ static void findMember(Entry *root, //printf("ccd->name()==%s className=%s\n",ccd->name().data(),className.data()); if (ccd!=0 && rightScopeMatch(ccd->name(),className)) { - ArgumentList *templAl = md->templateArguments(); + const ArgumentList *templAl = md->templateArguments(); if (root->tArgLists && templAl!=0 && root->tArgLists->getLast()->count()<=templAl->count()) { + Debug::print(Debug::FindMembers,0,"7. add template specialization\n"); + root->protection=md->protection(); + root->stat=md->isStatic(); + root->virt=md->virtualness(); addMethodToClass(root,ccd,md->name(),isFriend); return; } @@ -6337,10 +6425,10 @@ static void findMember(Entry *root, warnMsg+="Possible candidates:\n"; for (mni.toFirst();(md=mni.current());++mni) { - ClassDef *cd=md->getClassDef(); + const ClassDef *cd=md->getClassDef(); if (cd!=0 && rightScopeMatch(cd->name(),className)) { - ArgumentList *templAl = md->templateArguments(); + const ArgumentList *templAl = md->templateArguments(); if (templAl!=0) { warnMsg+=" 'template "; @@ -6443,7 +6531,7 @@ static void findMember(Entry *root, bool unique=TRUE; for (;(md=mni.current());++mni) { - ClassDef *cd=md->getClassDef(); + const ClassDef *cd=md->getClassDef(); if (className!=cd->name()) unique=FALSE; } if (unique) @@ -6638,10 +6726,10 @@ static void findMember(Entry *root, if (rmn) { MemberNameIterator rmni(*rmn); - MemberDef *rmd; + const MemberDef *rmd; while ((rmd=rmni.current()) && !found) // see if we got another member with matching arguments { - ArgumentList *rmdAl = rmd->argumentList(); + const ArgumentList *rmdAl = rmd->argumentList(); // check for matching argument lists if ( matchArguments2(rmd->getOuterScope(),rmd->getFileDef(),rmdAl, @@ -7247,7 +7335,7 @@ static void addEnumValuesToEnums(Entry *root) MemberDef *md; for (mni.toFirst(); (md=mni.current()) ; ++mni) // for each enum in this list { - if (md->isEnumerate() && root->children()) + if (!md->isAlias() && md->isEnumerate() && root->children()) { //printf(" enum with %d children\n",root->children()->count()); EntryListIterator eli(*root->children()); // for each enum value @@ -7335,7 +7423,7 @@ static void addEnumValuesToEnums(Entry *root) // fmd->name().data(),fmd->getOuterScope()->name().data()); if (nd && !nd->name().isEmpty() && nd->name().at(0)!='@') { - NamespaceDef *fnd=fmd->getNamespaceDef(); + const NamespaceDef *fnd=fmd->getNamespaceDef(); if (fnd==nd) // enum value is inside a namespace { md->insertEnumField(fmd); @@ -7344,7 +7432,7 @@ static void addEnumValuesToEnums(Entry *root) } else if (isGlobal) { - FileDef *ffd=fmd->getFileDef(); + const FileDef *ffd=fmd->getFileDef(); if (ffd==fd) // enum value has file scope { md->insertEnumField(fmd); @@ -7363,7 +7451,7 @@ static void addEnumValuesToEnums(Entry *root) } else { - ClassDef *fcd=fmd->getClassDef(); + const ClassDef *fcd=fmd->getClassDef(); if (fcd==cd) // enum value is inside a class { //printf("Inserting enum field %s in enum scope %s\n", @@ -7437,7 +7525,7 @@ static void findEnumDocumentation(Entry *root) MemberDef *md; for (mni.toFirst();(md=mni.current()) && !found;++mni) { - ClassDef *cd=md->getClassDef(); + const ClassDef *cd=md->getClassDef(); if (cd && cd->name()==className && md->isEnumerate()) { // documentation outside a compound overrides the documentation inside it @@ -7471,7 +7559,7 @@ static void findEnumDocumentation(Entry *root) md->addSectionsToDefinition(root->anchors); md->setRefItems(root->sli); - GroupDef *gd=md->getGroupDef(); + const GroupDef *gd=md->getGroupDef(); if (gd==0 &&root->groups->getFirst()!=0) // member not grouped but out-of-line documentation is { addMemberToGroups(root,md); @@ -7505,7 +7593,7 @@ static void findEnumDocumentation(Entry *root) md->addSectionsToDefinition(root->anchors); md->setMemberGroupId(root->mGrpId); - GroupDef *gd=md->getGroupDef(); + const GroupDef *gd=md->getGroupDef(); if (gd==0 && root->groups->getFirst()!=0) // member not grouped but out-of-line documentation is { addMemberToGroups(root,md); @@ -7544,7 +7632,7 @@ static void findDEV(const MemberNameSDict &mnsd) { if (md->isEnumerate()) // member is an enum { - MemberList *fmdl = md->enumFieldList(); + const MemberList *fmdl = md->enumFieldList(); int documentedEnumValues=0; if (fmdl) // enum has values { @@ -7597,19 +7685,54 @@ static void addMembersToIndex() // for each member definition for (mni.toFirst();(md=mni.current());++mni) { - if (md->getNamespaceDef()) - { - addNamespaceMemberNameToIndex(md); - } - else + if (!md->isAlias()) { - addFileMemberNameToIndex(md); + if (md->getNamespaceDef()) + { + addNamespaceMemberNameToIndex(md); + } + else + { + addFileMemberNameToIndex(md); + } } } } } //---------------------------------------------------------------------- + +static void vhdlCorrectMemberProperties() +{ + MemberName *mn; + MemberNameSDict::Iterator mnli(*Doxygen::memberNameSDict); + // for each member name + for (mnli.toFirst();(mn=mnli.current());++mnli) + { + MemberDef *md; + MemberNameIterator mni(*mn); + // for each member definition + for (mni.toFirst();(md=mni.current());++mni) + { + VhdlDocGen::correctMemberProperties(md); + } + } + MemberNameSDict::Iterator fnli(*Doxygen::functionNameSDict); + // for each member name + for (fnli.toFirst();(mn=fnli.current());++fnli) + { + MemberDef *md; + MemberNameIterator mni(*mn); + // for each member definition + for (mni.toFirst();(md=mni.current());++mni) + { + VhdlDocGen::correctMemberProperties(md); + } + } +} + + +//---------------------------------------------------------------------- // 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. @@ -7628,10 +7751,10 @@ static void computeMemberRelations() { for ( bmdi.toFirst() ; (bmd=bmdi.current()); ++bmdi ) // for each other member with the same name { - ClassDef *mcd = md->getClassDef(); + const ClassDef *mcd = md->getClassDef(); if (mcd && mcd->baseClasses()) { - ClassDef *bmcd = bmd->getClassDef(); + const ClassDef *bmcd = bmd->getClassDef(); //printf("Check relation between `%s'::`%s' (%p) and `%s'::`%s' (%p)\n", // mcd->name().data(),md->name().data(),md, // bmcd->name().data(),bmd->name().data(),bmd @@ -7856,7 +7979,7 @@ static void generateFileSources() { QStrList filesInSameTu; fd->startParsing(); - if (fd->generateSourceFile() && !g_useOutputTemplate) // sources need to be shown in the output + if (fd->generateSourceFile() && !Htags::useHtags && !g_useOutputTemplate) // sources need to be shown in the output { msg("Generating code for file %s...\n",fd->docName().data()); fd->writeSource(*g_outputList,FALSE,filesInSameTu); @@ -7886,7 +8009,7 @@ static void generateFileSources() { QStrList filesInSameTu; fd->startParsing(); - if (fd->generateSourceFile() && !g_useOutputTemplate) // sources need to be shown in the output + if (fd->generateSourceFile() && !Htags::useHtags && !g_useOutputTemplate) // sources need to be shown in the output { msg("Generating code for file %s...\n",fd->docName().data()); fd->writeSource(*g_outputList,FALSE,filesInSameTu); @@ -8055,6 +8178,85 @@ static void sortMemberLists() } //---------------------------------------------------------------------------- + +static void setAnonymousEnumType() +{ + ClassSDict::Iterator cli(*Doxygen::classSDict); + ClassDef *cd=0; + for (cli.toFirst();(cd=cli.current());++cli) + { + cd->setAnonymousEnumType(); + } + +#if 0 + NamespaceSDict::Iterator nli(*Doxygen::namespaceSDict); + NamespaceDef *nd=0; + for (nli.toFirst();(nd=nli.current());++nli) + { + nd->setAnonymousEnumType(); + } + + FileNameListIterator fnli(*Doxygen::inputNameList); + FileName *fn; + for (;(fn=fnli.current());++fnli) + { + FileNameIterator fni(*fn); + FileDef *fd; + for (;(fd=fni.current());++fni) + { + fd->setAnonymousEnumType(); + } + } + + GroupSDict::Iterator gli(*Doxygen::groupSDict); + GroupDef *gd; + for (gli.toFirst();(gd=gli.current());++gli) + { + gd->setAnonymousEnumType(); + } +#endif +} + +//---------------------------------------------------------------------------- + +static void countMembers() +{ + ClassSDict::Iterator cli(*Doxygen::classSDict); + ClassDef *cd=0; + for (cli.toFirst();(cd=cli.current());++cli) + { + cd->countMembers(); + } + + NamespaceSDict::Iterator nli(*Doxygen::namespaceSDict); + NamespaceDef *nd=0; + for (nli.toFirst();(nd=nli.current());++nli) + { + nd->countMembers(); + } + + FileNameListIterator fnli(*Doxygen::inputNameList); + FileName *fn; + for (;(fn=fnli.current());++fnli) + { + FileNameIterator fni(*fn); + FileDef *fd; + for (;(fd=fni.current());++fni) + { + fd->countMembers(); + } + } + + GroupSDict::Iterator gli(*Doxygen::groupSDict); + GroupDef *gd; + for (gli.toFirst();(gd=gli.current());++gli) + { + gd->countMembers(); + } +} + + +//---------------------------------------------------------------------------- // generate the documentation of all classes static void generateClassList(ClassSDict &classSDict) @@ -8321,7 +8523,7 @@ static void flushCachedTemplateRelations() { if (fmd->isTypedefValCached()) { - ClassDef *cd = fmd->getCachedTypedefVal(); + const ClassDef *cd = fmd->getCachedTypedefVal(); if (cd->isTemplate()) fmd->invalidateTypedefValCache(); } } @@ -8335,7 +8537,7 @@ static void flushCachedTemplateRelations() { if (fmd->isTypedefValCached()) { - ClassDef *cd = fmd->getCachedTypedefVal(); + const ClassDef *cd = fmd->getCachedTypedefVal(); if (cd->isTemplate()) fmd->invalidateTypedefValCache(); } } @@ -8469,7 +8671,7 @@ static void findDefineDocumentation(Entry *root) { if (md->memberType()==MemberType_Define) { - FileDef *fd=md->getFileDef(); + const FileDef *fd=md->getFileDef(); if (fd && fd->absFilePath()==root->fileName) // doc and define in the same file assume they belong together. { @@ -8792,7 +8994,7 @@ static void resolveUserReferences() { // TODO: there should be one function in Definition that returns // the file to link to, so we can avoid the following tests. - GroupDef *gd=0; + const GroupDef *gd=0; if (si->definition->definitionType()==Definition::TypeMember) { gd = (dynamic_cast<MemberDef *>(si->definition))->getGroupDef(); @@ -9956,7 +10158,7 @@ static void usage(const char *name) msg(" RTF: %s -e rtf extensionsFile\n\n",name); msg("7) Use doxygen to compare the used configuration file with the template configuration file\n"); msg(" %s -x [configFile]\n\n",name); - msg("8) Use doxygen to show a list of build in emoji.\n"); + msg("8) Use doxygen to show a list of built-in emojis.\n"); msg(" %s -f emoji outputFileName\n\n",name); msg(" If - is used for outputFileName doxygen will write to standard output.\n\n"); msg("If -s is specified the comments of the configuration items in the config file will be omitted.\n"); @@ -11094,9 +11296,7 @@ void parseInput() if (layoutFile.open(IO_ReadOnly)) { msg("Parsing layout file %s...\n",layoutFileName.data()); - QTextStream t(&layoutFile); - t.setEncoding(QTextStream::Latin1); - LayoutDocManager::instance().parse(t,layoutFileName); + LayoutDocManager::instance().parse(layoutFileName); } else if (!defaultLayoutUsed) { @@ -11198,9 +11398,6 @@ void parseInput() buildClassList(root); g_s.end(); - g_s.begin("Associating documentation with classes...\n"); - buildClassDocList(root); - // build list of using declarations here (global list) buildListOfUsingDecls(root); g_s.end(); @@ -11218,6 +11415,9 @@ void parseInput() // we don't need the list of using declaration anymore g_usingDeclarations.clear(); + g_s.begin("Associating documentation with classes...\n"); + buildClassDocList(root); + g_s.begin("Building example list...\n"); buildExampleList(root); g_s.end(); @@ -11407,6 +11607,10 @@ void parseInput() sortMemberLists(); g_s.end(); + g_s.begin("Setting anonymous enum type...\n"); + setAnonymousEnumType(); + g_s.end(); + if (Config_getBool(DIRECTORY_GRAPH)) { g_s.begin("Computing dependencies between directories...\n"); @@ -11421,6 +11625,10 @@ void parseInput() Doxygen::citeDict->generatePage(); g_s.end(); + g_s.begin("Counting members...\n"); + countMembers(); + g_s.end(); + g_s.begin("Counting data structures...\n"); countDataStructures(); g_s.end(); @@ -11444,6 +11652,11 @@ void parseInput() g_s.begin("Adding members to index pages...\n"); addMembersToIndex(); g_s.end(); + + g_s.begin("Correcting members for VHDL...\n"); + vhdlCorrectMemberProperties(); + g_s.end(); + } void generateOutput() @@ -11463,6 +11676,7 @@ void generateOutput() } initSearchIndexer(); + initDot(); bool generateHtml = Config_getBool(GENERATE_HTML); bool generateLatex = Config_getBool(GENERATE_LATEX); @@ -11517,7 +11731,7 @@ void generateOutput() QCString htmldir = Config_getString(HTML_OUTPUT); if (!Htags::execute(htmldir)) err("USE_HTAGS is YES but htags(1) failed. \n"); - if (!Htags::loadFilemap(htmldir)) + else if (!Htags::loadFilemap(htmldir)) err("htags(1) ended normally but failed to load the filemap. \n"); } @@ -11564,12 +11778,9 @@ void generateOutput() generateExampleDocs(); g_s.end(); - if (!Htags::useHtags) - { - g_s.begin("Generating file sources...\n"); - generateFileSources(); - g_s.end(); - } + g_s.begin("Generating file sources...\n"); + generateFileSources(); + g_s.end(); g_s.begin("Generating file documentation...\n"); generateFileDocs(); diff --git a/src/doxygen.h b/src/doxygen.h index 4ff8a56..c8eee7c 100644 --- a/src/doxygen.h +++ b/src/doxygen.h @@ -27,6 +27,7 @@ #include "membergroup.h" #include "dirdef.h" #include "memberlist.h" +#include "docgroup.h" class RefList; class PageSList; @@ -76,10 +77,10 @@ class StringDict : public QDict<QCString> struct LookupInfo { LookupInfo() : classDef(0), typeDef(0) {} - LookupInfo(ClassDef *cd,MemberDef *td,QCString ts,QCString rt) + LookupInfo(const ClassDef *cd,const MemberDef *td,QCString ts,QCString rt) : classDef(cd), typeDef(td), templSpec(ts),resolvedType(rt) {} - ClassDef *classDef; - MemberDef *typeDef; + const ClassDef *classDef; + const MemberDef *typeDef; QCString templSpec; QCString resolvedType; }; @@ -150,6 +151,7 @@ class Doxygen static bool generatingXmlOutput; static bool markdownSupport; static GenericsSDict *genericsDict; + static DocGroup docGroup; }; void initDoxygen(); diff --git a/src/eclipsehelp.cpp b/src/eclipsehelp.cpp index bf150b4..dab001a 100644 --- a/src/eclipsehelp.cpp +++ b/src/eclipsehelp.cpp @@ -174,7 +174,7 @@ void EclipseHelp::addContentsItem( const char *anchor, bool /* separateIndex */, bool /* addToNavIndex */, - Definition * /*def*/) + const Definition * /*def*/) { // -- write the topic tag closedTag(); @@ -216,8 +216,8 @@ void EclipseHelp::addContentsItem( } void EclipseHelp::addIndexItem( - Definition * /* context */, - MemberDef * /* md */, + const Definition * /* context */, + const MemberDef * /* md */, const char * /* sectionAnchor */, const char * /* title */) { diff --git a/src/eclipsehelp.h b/src/eclipsehelp.h index a7cde1e..5d63768 100644 --- a/src/eclipsehelp.h +++ b/src/eclipsehelp.h @@ -50,8 +50,8 @@ class EclipseHelp : public IndexIntf virtual void decContentsDepth(); virtual void addContentsItem(bool isDir, const char *name, const char *ref, const char *file, const char *anchor,bool separateIndex,bool addToNavIndex, - Definition *def); - virtual void addIndexItem(Definition *context,MemberDef *md, + const Definition *def); + virtual void addIndexItem(const Definition *context,const MemberDef *md, const char *sectionAnchor,const char *title); virtual void addIndexFile(const char *name); virtual void addImageFile(const char *name); diff --git a/src/entry.h b/src/entry.h index 8810c18..6dfa0c6 100644 --- a/src/entry.h +++ b/src/entry.h @@ -186,7 +186,7 @@ class Entry enum GroupDocType { GROUPDOC_NORMAL, //!< defgroup - GROUPDOC_ADD, //!< addgroup + GROUPDOC_ADD, //!< addtogroup GROUPDOC_WEAK //!< weakgroup }; //!< kind of group @@ -301,7 +301,7 @@ class Entry switch( groupDocType ) { case GROUPDOC_NORMAL: return "\\defgroup"; - case GROUPDOC_ADD: return "\\addgroup"; + case GROUPDOC_ADD: return "\\addtogroup"; case GROUPDOC_WEAK: return "\\weakgroup"; default: return "unknown group command"; } diff --git a/src/filedef.cpp b/src/filedef.cpp index 130679e..7a3323d 100644 --- a/src/filedef.cpp +++ b/src/filedef.cpp @@ -26,6 +26,7 @@ #include "language.h" #include "outputlist.h" #include "dot.h" +#include "dotincldepgraph.h" #include "message.h" #include "docparser.h" #include "searchindex.h" @@ -90,11 +91,14 @@ class FileDefImpl : public DefinitionImpl, public FileDef virtual bool hasDetailedDescription() const; virtual QCString fileVersion() const; virtual bool subGrouping() const { return m_subGrouping; } + virtual void countMembers(); + virtual int numDocMembers() const; + virtual int numDecMembers() const; virtual void addSourceRef(int line,Definition *d,MemberDef *md); virtual void writeDocumentation(OutputList &ol); virtual void writeMemberPages(OutputList &ol); - virtual void writeQuickMemberLinks(OutputList &ol,MemberDef *currentMd) const; - virtual void writeSummaryLinks(OutputList &ol); + virtual void writeQuickMemberLinks(OutputList &ol,const MemberDef *currentMd) const; + virtual void writeSummaryLinks(OutputList &ol) const; virtual void writeTagFile(FTextStream &t); virtual void startParsing(); virtual void writeSource(OutputList &ol,bool sameTu,QStrList &filesInSameTu); @@ -107,7 +111,7 @@ class FileDefImpl : public DefinitionImpl, public FileDef virtual void computeAnchors(); virtual void setPackageDef(PackageDef *pd) { m_package=pd; } virtual void setDirDef(DirDef *dd) { m_dir=dd; } - virtual void addUsingDirective(NamespaceDef *nd); + virtual void addUsingDirective(const NamespaceDef *nd); virtual void addUsingDeclaration(Definition *def); virtual void combineUsingRelations(); virtual bool generateSourceFile() const; @@ -203,7 +207,7 @@ class DevNullCodeDocInterface : public CodeOutputInterface virtual void endFontClass() {} virtual void writeCodeAnchor(const char *) {} virtual void linkableSymbol(int, const char *,Definition *,Definition *) {} - virtual void setCurrentDoc(Definition *,const char *,bool) {} + virtual void setCurrentDoc(const Definition *,const char *,bool) {} virtual void addWord(const char *,bool) {} }; @@ -801,7 +805,7 @@ void FileDefImpl::writeAuthorSection(OutputList &ol) ol.popGeneratorState(); } -void FileDefImpl::writeSummaryLinks(OutputList &ol) +void FileDefImpl::writeSummaryLinks(OutputList &ol) const { ol.pushGeneratorState(); ol.disableAllBut(OutputGenerator::Html); @@ -1103,7 +1107,7 @@ void FileDefImpl::writeMemberPages(OutputList &ol) ol.popGeneratorState(); } -void FileDefImpl::writeQuickMemberLinks(OutputList &ol,MemberDef *currentMd) const +void FileDefImpl::writeQuickMemberLinks(OutputList &ol,const MemberDef *currentMd) const { static bool createSubDirs=Config_getBool(CREATE_SUBDIRS); @@ -1503,7 +1507,7 @@ MemberDef *FileDefImpl::getSourceMember(int lineNr) const } -void FileDefImpl::addUsingDirective(NamespaceDef *nd) +void FileDefImpl::addUsingDirective(const NamespaceDef *nd) { if (m_usingDirList==0) { @@ -2210,3 +2214,36 @@ QCString FileDefImpl::includedByDependencyGraphFileName() const return m_inclByDepFileName; } +void FileDefImpl::countMembers() +{ + QListIterator<MemberList> mli(m_memberLists); + MemberList *ml; + for (mli.toFirst();(ml=mli.current());++mli) + { + ml->countDecMembers(); + ml->countDocMembers(); + } + if (m_memberGroupSDict) + { + MemberGroupSDict::Iterator mgli(*m_memberGroupSDict); + MemberGroup *mg; + for (;(mg=mgli.current());++mgli) + { + mg->countDecMembers(); + mg->countDocMembers(); + } + } +} + +int FileDefImpl::numDocMembers() const +{ + MemberList *ml = getMemberList(MemberListType_allMembersList); + return ml ? ml->numDocMembers() : 0; +} + +int FileDefImpl::numDecMembers() const +{ + MemberList *ml = getMemberList(MemberListType_allMembersList); + return ml ? ml->numDecMembers() : 0; +} + diff --git a/src/filedef.h b/src/filedef.h index 63cacf5..b66d7be 100644 --- a/src/filedef.h +++ b/src/filedef.h @@ -135,14 +135,18 @@ class FileDef : virtual public Definition virtual bool subGrouping() const = 0; + virtual void countMembers() = 0; + virtual int numDocMembers() const = 0; + virtual int numDecMembers() const = 0; + //--------------------------------- virtual void addSourceRef(int line,Definition *d,MemberDef *md) = 0; virtual void writeDocumentation(OutputList &ol) = 0; virtual void writeMemberPages(OutputList &ol) = 0; - virtual void writeQuickMemberLinks(OutputList &ol,MemberDef *currentMd) const = 0; - virtual void writeSummaryLinks(OutputList &ol) = 0; + virtual void writeQuickMemberLinks(OutputList &ol,const MemberDef *currentMd) const = 0; + virtual void writeSummaryLinks(OutputList &ol) const = 0; virtual void writeTagFile(FTextStream &t) = 0; virtual void startParsing() = 0; @@ -159,7 +163,7 @@ class FileDef : virtual public Definition virtual void setPackageDef(PackageDef *pd) = 0; virtual void setDirDef(DirDef *dd) = 0; - virtual void addUsingDirective(NamespaceDef *nd) = 0; + virtual void addUsingDirective(const NamespaceDef *nd) = 0; virtual void addUsingDeclaration(Definition *def) = 0; virtual void combineUsingRelations() = 0; diff --git a/src/fileparser.cpp b/src/fileparser.cpp index 6883622..45bdc81 100644 --- a/src/fileparser.cpp +++ b/src/fileparser.cpp @@ -26,9 +26,9 @@ void FileParser::parseCode(CodeOutputInterface &codeOutIntf, int startLine, int endLine, bool, // inlineFragment - MemberDef *, // memberDef + const MemberDef *, // memberDef bool showLineNumbers, - Definition *, // searchCtx, + const Definition *, // searchCtx, bool // collectXRefs ) { diff --git a/src/fileparser.h b/src/fileparser.h index 4568a39..4b311e6 100644 --- a/src/fileparser.h +++ b/src/fileparser.h @@ -37,9 +37,9 @@ class FileParser : public ParserInterface int startLine=-1, int endLine=-1, bool inlineFragment=FALSE, - MemberDef *memberDef=0, + const MemberDef *memberDef=0, bool showLineNumbers=TRUE, - Definition *searchCtx=0, + const Definition *searchCtx=0, bool collectXRefs=TRUE ); void resetCodeParserState() {} diff --git a/src/fortrancode.h b/src/fortrancode.h index c110852..4df20a9 100644 --- a/src/fortrancode.h +++ b/src/fortrancode.h @@ -29,7 +29,7 @@ class Definition; void parseFortranCode(CodeOutputInterface &,const char *,const QCString &, bool ,const char *,FileDef *fd, int startLine,int endLine,bool inlineFragment, - MemberDef *memberDef,bool showLineNumbers,Definition *searchCtx, + const MemberDef *memberDef,bool showLineNumbers,const Definition *searchCtx, bool collectRefs, FortranFormat format); void resetFortranCodeParserState(); void codeFreeScanner(); diff --git a/src/fortrancode.l b/src/fortrancode.l index 31924fa..926a3ff 100644 --- a/src/fortrancode.l +++ b/src/fortrancode.l @@ -140,7 +140,7 @@ static int g_yyLineNr; //!< current line number static int g_contLineNr; //!< current, local, line number for continuation determination static int *g_hasContLine = NULL; //!< signals whether or not a line has a continuation line (fixed source form) static bool g_needsTermination; -static Definition *g_searchCtx; +static const Definition *g_searchCtx; static bool g_collectXRefs; static bool g_isFixedForm; @@ -452,16 +452,16 @@ static bool getFortranDefs(const QCString &memberName, const QCString &moduleNam MemberNameIterator mli(*mn); for (mli.toFirst();(md=mli.current());++mli) // all found functions with given name { - FileDef *fd=md->getFileDef(); - GroupDef *gd=md->getGroupDef(); - ClassDef *cd=md->getClassDef(); + const FileDef *fd=md->getFileDef(); + const GroupDef *gd=md->getGroupDef(); + const ClassDef *cd=md->getClassDef(); //cout << "found link with same name: " << fd->fileName() << " " << memberName; //if (md->getNamespaceDef() != 0) cout << " in namespace " << md->getNamespaceDef()->name();cout << endl; if ((gd && gd->isLinkable()) || (fd && fd->isLinkable())) { - NamespaceDef *nspace= md->getNamespaceDef(); + const NamespaceDef *nspace= md->getNamespaceDef(); if (nspace == 0) { // found function in global scope @@ -532,8 +532,8 @@ static bool getLink(UseSDict *usedict, // dictonary with used modules if (md->isVariable() && (md->getLanguage()!=SrcLangExt_Fortran)) return FALSE; // Non Fortran variables aren't handled yet, // see also linkifyText in util.cpp - Definition *d = md->getOuterScope()==Doxygen::globalScope ? - md->getBodyDef() : md->getOuterScope(); + const Definition *d = md->getOuterScope()==Doxygen::globalScope ? + md->getBodyDef() : md->getOuterScope(); if (md->getGroupDef()) d = md->getGroupDef(); if (d && d->isLinkable()) { @@ -1313,18 +1313,14 @@ static void checkContLines(const char *s) g_hasContLine[0] = 0; } -void parseFortranCode(CodeOutputInterface &od,const char *className,const QCString &s, +void parseFortranCode(CodeOutputInterface &od,const char *,const QCString &s, bool exBlock, const char *exName,FileDef *fd, int startLine,int endLine,bool inlineFragment, - MemberDef *memberDef,bool,Definition *searchCtx, + const MemberDef *,bool,const Definition *searchCtx, bool collectXRefs, FortranFormat format) { //printf("***parseCode() exBlock=%d exName=%s fd=%p\n",exBlock,exName,fd); - // used parameters - (void)memberDef; - (void)className; - if (s.isEmpty()) return; printlex(yy_flex_debug, TRUE, __FILE__, fd ? fd->fileName().data(): NULL); g_code = &od; diff --git a/src/fortranscanner.h b/src/fortranscanner.h index bc8071b..15a9bf0 100644 --- a/src/fortranscanner.h +++ b/src/fortranscanner.h @@ -47,9 +47,9 @@ class FortranLanguageScanner : public ParserInterface int startLine=-1, int endLine=-1, bool inlineFragment=FALSE, - MemberDef *memberDef=0, + const MemberDef *memberDef=0, bool showLineNumbers=TRUE, - Definition *searchCtx=0, + const Definition *searchCtx=0, bool collectXRefs=TRUE ); void resetCodeParserState(); diff --git a/src/fortranscanner.l b/src/fortranscanner.l index 7d7437d..1076e68 100644 --- a/src/fortranscanner.l +++ b/src/fortranscanner.l @@ -698,6 +698,14 @@ private { typeMode = false; yy_pop_state(); } +^{BS}"end"{BS}/(\n|!|;) { /* incorrect end type definition */ + warn(yyFileName,yyLineNr, "Found 'END' instead of 'END TYPE'"); + last_entry->parent()->endBodyLine = yyLineNr; + if (!endScope(current_root)) + yyterminate(); + typeMode = false; + yy_pop_state(); + } } /*------- module/global/typedef variable ---------------------------------------------------*/ @@ -2296,7 +2304,7 @@ static void initEntry() current->virt = virt; current->stat = gstat; current->lang = SrcLangExt_Fortran; - initGroupInfo(current); + Doxygen::docGroup.initGroupInfo(current); } /** @@ -2704,7 +2712,7 @@ static void parseMain(const char *fileName,const char *fileBuf,Entry *rt, Fortra global_scope = rt; startScope(rt); // implies current_root = rt initParser(); - groupEnterFile(yyFileName,yyLineNr); + Doxygen::docGroup.enterFile(yyFileName,yyLineNr); current = new Entry; current->lang = SrcLangExt_Fortran; @@ -2721,7 +2729,7 @@ static void parseMain(const char *fileName,const char *fileBuf,Entry *rt, Fortra } fortranscannerYYlex(); - groupLeaveFile(yyFileName,yyLineNr); + Doxygen::docGroup.leaveFile(yyFileName,yyLineNr); if (global_scope && global_scope != (Entry *) -1) endScope(current_root, TRUE); // TRUE - global root @@ -2770,9 +2778,9 @@ void FortranLanguageScanner::parseCode(CodeOutputInterface & codeOutIntf, int startLine, int endLine, bool inlineFragment, - MemberDef *memberDef, + const MemberDef *memberDef, bool showLineNumbers, - Definition *searchCtx, + const Definition *searchCtx, bool collectXRefs ) { @@ -2819,7 +2827,7 @@ static void scanner_abort() // dummy call to avoid compiler warning (void)yy_top_state(); - + return; //exit(-1); } diff --git a/src/ftvhelp.cpp b/src/ftvhelp.cpp index d66a935..149f43c 100644 --- a/src/ftvhelp.cpp +++ b/src/ftvhelp.cpp @@ -46,7 +46,7 @@ static int folderId=1; struct FTVNode { FTVNode(bool dir,const char *r,const char *f,const char *a, - const char *n,bool sepIndex,bool navIndex,Definition *df) + const char *n,bool sepIndex,bool navIndex,const Definition *df) : isLast(TRUE), isDir(dir),ref(r),file(f),anchor(a),name(n), index(0), parent(0), separateIndex(sepIndex), addToNavIndex(navIndex), def(df) { children.setAutoDelete(TRUE); } @@ -63,7 +63,7 @@ struct FTVNode FTVNode *parent; bool separateIndex; bool addToNavIndex; - Definition *def; + const Definition *def; }; int FTVNode::computeTreeDepth(int level) const @@ -187,7 +187,7 @@ void FTVHelp::addContentsItem(bool isDir, const char *anchor, bool separateIndex, bool addToNavIndex, - Definition *def + const Definition *def ) { //printf("%p: m_indent=%d addContentsItem(%s,%s,%s,%s)\n",this,m_indent,name,ref,file,anchor); @@ -207,7 +207,7 @@ void FTVHelp::addContentsItem(bool isDir, } -static QCString node2URL(FTVNode *n,bool overruleFile=FALSE,bool srcLink=FALSE) +static QCString node2URL(const FTVNode *n,bool overruleFile=FALSE,bool srcLink=FALSE) { QCString url = n->file; if (!url.isEmpty() && url.at(0)=='!') // relative URL @@ -223,7 +223,7 @@ static QCString node2URL(FTVNode *n,bool overruleFile=FALSE,bool srcLink=FALSE) { if (overruleFile && n->def && n->def->definitionType()==Definition::TypeFile) { - FileDef *fd = dynamic_cast<FileDef*>(n->def); + const FileDef *fd = dynamic_cast<const FileDef*>(n->def); if (srcLink) { url = fd->getSourceFileBase(); @@ -315,7 +315,7 @@ void FTVHelp::generateLink(FTextStream &t,FTVNode *n) } } -static void generateBriefDoc(FTextStream &t,Definition *def) +static void generateBriefDoc(FTextStream &t,const Definition *def) { QCString brief = def->briefDescription(TRUE); //printf("*** %p: generateBriefDoc(%s)='%s'\n",def,def->name().data(),brief.data()); @@ -332,7 +332,7 @@ static void generateBriefDoc(FTextStream &t,Definition *def) } } -static char compoundIcon(ClassDef *cd) +static char compoundIcon(const ClassDef *cd) { char icon='C'; if (cd->getLanguage() == SrcLangExt_Slice) @@ -392,7 +392,7 @@ void FTVHelp::generateTree(FTextStream &t, const QList<FTVNode> &nl,int level,in } else if (n->def && n->def->definitionType()==Definition::TypeClass) { - char icon=compoundIcon(dynamic_cast<ClassDef*>(n->def)); + char icon=compoundIcon(dynamic_cast<const ClassDef*>(n->def)); t << "<span class=\"icona\"><span class=\"icon\">" << icon << "</span></span>"; } else @@ -415,11 +415,11 @@ void FTVHelp::generateTree(FTextStream &t, const QList<FTVNode> &nl,int level,in } else // leaf node { - FileDef *srcRef=0; + const FileDef *srcRef=0; if (n->def && n->def->definitionType()==Definition::TypeFile && - (dynamic_cast<FileDef*>(n->def))->generateSourceFile()) + (dynamic_cast<const FileDef*>(n->def))->generateSourceFile()) { - srcRef = dynamic_cast<FileDef*>(n->def); + srcRef = dynamic_cast<const FileDef*>(n->def); } if (srcRef) { @@ -448,7 +448,7 @@ void FTVHelp::generateTree(FTextStream &t, const QList<FTVNode> &nl,int level,in } else if (n->def && n->def->definitionType()==Definition::TypeClass) { - char icon=compoundIcon(dynamic_cast<ClassDef*>(n->def)); + char icon=compoundIcon(dynamic_cast<const ClassDef*>(n->def)); t << "<span class=\"icona\"><span class=\"icon\">" << icon << "</span></span>"; } else @@ -492,7 +492,7 @@ class NavIndexEntryList : public QList<NavIndexEntry> } }; -static QCString pathToNode(FTVNode *leaf,FTVNode *n) +static QCString pathToNode(const FTVNode *leaf,const FTVNode *n) { QCString result; if (n->parent) @@ -511,7 +511,7 @@ static bool dupOfParent(const FTVNode *n) return FALSE; } -static void generateJSLink(FTextStream &t,FTVNode *n) +static void generateJSLink(FTextStream &t,const FTVNode *n) { if (n->file.isEmpty()) // no link { @@ -542,7 +542,7 @@ static bool generateJSTree(NavIndexEntryList &navIndex,FTextStream &t, indentStr.fill(' ',level*2); bool found=FALSE; QListIterator<FTVNode> nli(nl); - FTVNode *n; + const FTVNode *n; for (nli.toFirst();(n=nli.current());++nli) { // terminate previous entry @@ -560,7 +560,7 @@ static bool generateJSTree(NavIndexEntryList &navIndex,FTextStream &t, { if (n->def && n->def->definitionType()==Definition::TypeFile) { - FileDef *fd = dynamic_cast<FileDef*>(n->def); + const FileDef *fd = dynamic_cast<const FileDef*>(n->def); bool doc,src; doc = fileVisibleInIndex(fd,src); if (doc) diff --git a/src/ftvhelp.h b/src/ftvhelp.h index eac0367..4c3f986 100644 --- a/src/ftvhelp.h +++ b/src/ftvhelp.h @@ -50,8 +50,8 @@ class FTVHelp : public IndexIntf const char *anchor, bool separateIndex, bool addToNavIndex, - Definition *def); - void addIndexItem(Definition *,MemberDef *,const char *,const char *) {} + const Definition *def); + void addIndexItem(const Definition *,const MemberDef *,const char *,const char *) {} void addIndexFile(const char *) {} void addImageFile(const char *) {} void addStyleSheetFile(const char *) {} diff --git a/src/groupdef.cpp b/src/groupdef.cpp index 31eb7fe..9525053 100644 --- a/src/groupdef.cpp +++ b/src/groupdef.cpp @@ -33,6 +33,7 @@ #include "docparser.h" #include "searchindex.h" #include "dot.h" +#include "dotgroupcollaboration.h" #include "vhdldocgen.h" #include "layout.h" #include "arguments.h" @@ -69,13 +70,14 @@ class GroupDefImpl : public DefinitionImpl, public GroupDef virtual bool findGroup(const GroupDef *def) const; // true if def is a subgroup of this group virtual void writeDocumentation(OutputList &ol); virtual void writeMemberPages(OutputList &ol); - virtual void writeQuickMemberLinks(OutputList &ol,MemberDef *currentMd) const; + virtual void writeQuickMemberLinks(OutputList &ol,const MemberDef *currentMd) const; virtual void writeTagFile(FTextStream &); - virtual int countMembers() const; + virtual int numDocMembers() const; virtual bool isLinkableInProject() const; virtual bool isLinkable() const; virtual bool isASubGroup() const; virtual void computeAnchors(); + virtual void countMembers(); virtual void addMembersToMemberGroup(); virtual void distributeMemberGroupDocumentation(); @@ -127,7 +129,7 @@ class GroupDefImpl : public DefinitionImpl, public GroupDef void startMemberDocumentation(OutputList &ol); void endMemberDocumentation(OutputList &ol); void writeAuthorSection(OutputList &ol); - void writeSummaryLinks(OutputList &ol); + void writeSummaryLinks(OutputList &ol) const; void updateLanguage(const Definition *); QCString title; // title of the group @@ -383,10 +385,10 @@ bool GroupDefImpl::insertMember(MemberDef *md,bool docOnly) if ((mni=(*allMemberNameInfoSDict)[md->name()])) { // member with this name already found MemberNameInfoIterator srcMnii(*mni); - MemberInfo *srcMi; + const MemberInfo *srcMi; for ( ; (srcMi=srcMnii.current()) ; ++srcMnii ) { - MemberDef *srcMd = srcMi->memberDef; + const MemberDef *srcMd = srcMi->memberDef; if (srcMd==md) return FALSE; // already added before! bool sameScope = srcMd->getOuterScope()==md->getOuterScope() || // same class or namespace @@ -394,10 +396,10 @@ bool GroupDefImpl::insertMember(MemberDef *md,bool docOnly) (srcMd->getOuterScope()->definitionType()==Definition::TypeFile && md->getOuterScope()->definitionType()==Definition::TypeFile); - ArgumentList *srcMdAl = srcMd->argumentList(); - ArgumentList *mdAl = md->argumentList(); - ArgumentList *tSrcMdAl = srcMd->templateArguments(); - ArgumentList *tMdAl = md->templateArguments(); + const ArgumentList *srcMdAl = srcMd->argumentList(); + const ArgumentList *mdAl = md->argumentList(); + const ArgumentList *tSrcMdAl = srcMd->templateArguments(); + const ArgumentList *tMdAl = md->templateArguments(); if (srcMd->isFunction() && md->isFunction() && // both are a function ((tSrcMdAl==0 && tMdAl==0) || @@ -662,7 +664,28 @@ bool GroupDefImpl::isASubGroup() const return groups!=0 && groups->count()!=0; } -int GroupDefImpl::countMembers() const +void GroupDefImpl::countMembers() +{ + QListIterator<MemberList> mli(m_memberLists); + MemberList *ml; + for (;(ml=mli.current());++mli) + { + ml->countDecMembers(); + ml->countDocMembers(); + } + if (memberGroupSDict) + { + MemberGroupSDict::Iterator mgli(*memberGroupSDict); + MemberGroup *mg; + for (;(mg=mgli.current());++mgli) + { + mg->countDecMembers(); + mg->countDocMembers(); + } + } +} + +int GroupDefImpl::numDocMembers() const { return fileList->count()+ classSDict->count()+ @@ -830,7 +853,7 @@ void GroupDefImpl::writeDetailedDescription(OutputList &ol,const QCString &title ) { ol.pushGeneratorState(); - if (pageDict->count()!=countMembers()) // not only pages -> classical layout + if (pageDict->count()!=numDocMembers()) // not only pages -> classical layout { ol.pushGeneratorState(); ol.disable(OutputGenerator::Html); @@ -1154,7 +1177,7 @@ void GroupDefImpl::writeAuthorSection(OutputList &ol) ol.popGeneratorState(); } -void GroupDefImpl::writeSummaryLinks(OutputList &ol) +void GroupDefImpl::writeSummaryLinks(OutputList &ol) const { ol.pushGeneratorState(); ol.disableAllBut(OutputGenerator::Html); @@ -1394,7 +1417,7 @@ void GroupDefImpl::writeMemberPages(OutputList &ol) ol.popGeneratorState(); } -void GroupDefImpl::writeQuickMemberLinks(OutputList &ol,MemberDef *currentMd) const +void GroupDefImpl::writeQuickMemberLinks(OutputList &ol,const MemberDef *currentMd) const { static bool createSubDirs=Config_getBool(CREATE_SUBDIRS); @@ -1557,7 +1580,7 @@ void addMemberToGroups(Entry *root,MemberDef *md) // put member into group defined by this entry? if (fgd) { - GroupDef *mgd = md->getGroupDef(); + GroupDef *mgd = const_cast<GroupDef*>(md->getGroupDef()); //printf("mgd=%p\n",mgd); bool insertit = FALSE; if (mgd==0) diff --git a/src/groupdef.h b/src/groupdef.h index 2649de7..92d524f 100644 --- a/src/groupdef.h +++ b/src/groupdef.h @@ -66,13 +66,14 @@ class GroupDef : virtual public Definition virtual bool findGroup(const GroupDef *def) const = 0; virtual void writeDocumentation(OutputList &ol) = 0; virtual void writeMemberPages(OutputList &ol) = 0; - virtual void writeQuickMemberLinks(OutputList &ol,MemberDef *currentMd) const = 0; + virtual void writeQuickMemberLinks(OutputList &ol,const MemberDef *currentMd) const = 0; virtual void writeTagFile(FTextStream &) = 0; - virtual int countMembers() const = 0; + virtual int numDocMembers() const = 0; virtual bool isLinkableInProject() const = 0; virtual bool isLinkable() const = 0; virtual bool isASubGroup() const = 0; virtual void computeAnchors() = 0; + virtual void countMembers() = 0; virtual void addMembersToMemberGroup() = 0; virtual void distributeMemberGroupDocumentation() = 0; diff --git a/src/htags.cpp b/src/htags.cpp index 77b1f8d..51cd6d9 100644 --- a/src/htags.cpp +++ b/src/htags.cpp @@ -91,6 +91,10 @@ bool Htags::execute(const QCString &htmldir) //printf("CommandLine=[%s]\n",commandLine.data()); portable_sysTimerStart(); bool result=portable_system("htags",commandLine,FALSE)==0; + if (!result) + { + err("Problems running %s. Check your installation\n", "htags"); + } portable_sysTimerStop(); QDir::setCurrent(oldDir); return result; @@ -128,7 +132,7 @@ bool Htags::loadFilemap(const QCString &htmlDir) int len; while ((len=f.readLine(line.rawData(),maxlen))>0) { - line.resize(len+1); + line.at(len)='\0'; //printf("Read line: %s",line.data()); int sep = line.find('\t'); if (sep!=-1) diff --git a/src/htmldocvisitor.cpp b/src/htmldocvisitor.cpp index 37f6bd0..05cdc42 100644 --- a/src/htmldocvisitor.cpp +++ b/src/htmldocvisitor.cpp @@ -270,7 +270,7 @@ static QCString htmlAttribsToString(const HtmlAttribList &attribs, QCString *pAl //------------------------------------------------------------------------- HtmlDocVisitor::HtmlDocVisitor(FTextStream &t,CodeOutputInterface &ci, - Definition *ctx) + const Definition *ctx) : DocVisitor(DocVisitor_Html), m_t(t), m_ci(ci), m_insidePre(FALSE), m_hide(FALSE), m_ctx(ctx) { @@ -784,19 +784,21 @@ void HtmlDocVisitor::visit(DocIncOperator *op) pushEnabled(); m_hide=TRUE; } - SrcLangExt langExt = getLanguageFromFileName(m_langExt); + QCString locLangExt = getFileNameExtension(op->includeFileName()); + if (locLangExt.isEmpty()) locLangExt = m_langExt; + SrcLangExt langExt = getLanguageFromFileName(locLangExt); if (op->type()!=DocIncOperator::Skip) { popEnabled(); if (!m_hide) { - FileDef *fd; + FileDef *fd = 0; if (!op->includeFileName().isEmpty()) { QFileInfo cfi( op->includeFileName() ); fd = createFileDef( cfi.dirPath().utf8(), cfi.fileName().utf8() ); } - Doxygen::parserManager->getParser(m_langExt) + Doxygen::parserManager->getParser(locLangExt) ->parseCode( m_ci, op->context(), @@ -2116,14 +2118,6 @@ void HtmlDocVisitor::visitPost(DocInternalRef *) m_t << " "; } -void HtmlDocVisitor::visitPre(DocCopy *) -{ -} - -void HtmlDocVisitor::visitPost(DocCopy *) -{ -} - void HtmlDocVisitor::visitPre(DocText *) { } diff --git a/src/htmldocvisitor.h b/src/htmldocvisitor.h index 7184f0f..c994bac 100644 --- a/src/htmldocvisitor.h +++ b/src/htmldocvisitor.h @@ -33,7 +33,7 @@ class CodeOutputInterface; class HtmlDocVisitor : public DocVisitor { public: - HtmlDocVisitor(FTextStream &t,CodeOutputInterface &ci,Definition *ctx); + HtmlDocVisitor(FTextStream &t,CodeOutputInterface &ci,const Definition *ctx); //-------------------------------------- // visitor functions for leaf nodes @@ -127,8 +127,6 @@ class HtmlDocVisitor : public DocVisitor void visitPost(DocXRefItem *); void visitPre(DocInternalRef *); void visitPost(DocInternalRef *); - void visitPre(DocCopy *); - void visitPost(DocCopy *); void visitPre(DocText *); void visitPost(DocText *); void visitPre(DocHtmlBlockQuote *); @@ -171,7 +169,7 @@ class HtmlDocVisitor : public DocVisitor bool m_insidePre; bool m_hide; QStack<bool> m_enabled; - Definition *m_ctx; + const Definition *m_ctx; QCString m_langExt; }; diff --git a/src/htmlgen.cpp b/src/htmlgen.cpp index cd45e5f..402b4e4 100644 --- a/src/htmlgen.cpp +++ b/src/htmlgen.cpp @@ -28,6 +28,12 @@ #include "diagram.h" #include "version.h" #include "dot.h" +#include "dotcallgraph.h" +#include "dotclassgraph.h" +#include "dotdirdeps.h" +#include "dotgfxhierarchytable.h" +#include "dotgroupcollaboration.h" +#include "dotincldepgraph.h" #include "language.h" #include "htmlhelp.h" #include "docparser.h" @@ -51,6 +57,7 @@ static QCString g_header; static QCString g_footer; static QCString g_mathjax_code; +static bool DoxyCodeLineOpen = FALSE; // note: this is only active if DISABLE_INDEX=YES, if DISABLE_INDEX is disabled, this // part will be rendered inside menu.js @@ -524,7 +531,12 @@ void HtmlCodeGenerator::writeLineNumber(const char *ref,const char *filename, qsnprintf(lineNumber,maxLineNrStr,"%5d",l); qsnprintf(lineAnchor,maxLineNrStr,"l%05d",l); - m_t << "<div class=\"line\">"; + if (!DoxyCodeLineOpen) + { + m_t << "<div class=\"line\">"; + DoxyCodeLineOpen = TRUE; + } + m_t << "<a name=\"" << lineAnchor << "\"></a><span class=\"lineno\">"; if (filename) { @@ -655,12 +667,16 @@ void HtmlCodeGenerator::writeTooltip(const char *id, const DocLinkInfo &docInfo, } -void HtmlCodeGenerator::startCodeLine(bool hasLineNumbers) +void HtmlCodeGenerator::startCodeLine(bool) { if (m_streamSet) { - if (!hasLineNumbers) m_t << "<div class=\"line\">"; m_col=0; + if (!DoxyCodeLineOpen) + { + m_t << "<div class=\"line\">"; + DoxyCodeLineOpen = TRUE; + } } } @@ -673,7 +689,11 @@ void HtmlCodeGenerator::endCodeLine() m_t << " "; m_col++; } - m_t << "</div>"; + if (DoxyCodeLineOpen) + { + m_t << "</div>\n"; + DoxyCodeLineOpen = FALSE; + } } } @@ -1775,7 +1795,7 @@ void HtmlGenerator::startDotGraph() startSectionHeader(t,relPath,m_sectionCount); } -void HtmlGenerator::endDotGraph(const DotClassGraph &g) +void HtmlGenerator::endDotGraph(DotClassGraph &g) { bool generateLegend = Config_getBool(GENERATE_LEGEND); bool umlLook = Config_getBool(UML_LOOK); @@ -1803,7 +1823,7 @@ void HtmlGenerator::startInclDepGraph() startSectionHeader(t,relPath,m_sectionCount); } -void HtmlGenerator::endInclDepGraph(const DotInclDepGraph &g) +void HtmlGenerator::endInclDepGraph(DotInclDepGraph &g) { endSectionHeader(t); startSectionSummary(t,m_sectionCount); @@ -1821,7 +1841,7 @@ void HtmlGenerator::startGroupCollaboration() startSectionHeader(t,relPath,m_sectionCount); } -void HtmlGenerator::endGroupCollaboration(const DotGroupCollaboration &g) +void HtmlGenerator::endGroupCollaboration(DotGroupCollaboration &g) { endSectionHeader(t); startSectionSummary(t,m_sectionCount); @@ -1839,7 +1859,7 @@ void HtmlGenerator::startCallGraph() startSectionHeader(t,relPath,m_sectionCount); } -void HtmlGenerator::endCallGraph(const DotCallGraph &g) +void HtmlGenerator::endCallGraph(DotCallGraph &g) { endSectionHeader(t); startSectionSummary(t,m_sectionCount); @@ -1857,7 +1877,7 @@ void HtmlGenerator::startDirDepGraph() startSectionHeader(t,relPath,m_sectionCount); } -void HtmlGenerator::endDirDepGraph(const DotDirDeps &g) +void HtmlGenerator::endDirDepGraph(DotDirDeps &g) { endSectionHeader(t); startSectionSummary(t,m_sectionCount); @@ -1870,7 +1890,7 @@ void HtmlGenerator::endDirDepGraph(const DotDirDeps &g) m_sectionCount++; } -void HtmlGenerator::writeGraphicalHierarchy(const DotGfxHierarchyTable &g) +void HtmlGenerator::writeGraphicalHierarchy(DotGfxHierarchyTable &g) { g.writeGraph(t,dir,fileName); } @@ -1994,7 +2014,7 @@ void HtmlGenerator::endParamList() t << "</dl>"; } -void HtmlGenerator::writeDoc(DocNode *n,Definition *ctx,MemberDef *) +void HtmlGenerator::writeDoc(DocNode *n,const Definition *ctx,const MemberDef *) { HtmlDocVisitor *visitor = new HtmlDocVisitor(t,m_codeGen,ctx); n->accept(visitor); @@ -2634,6 +2654,19 @@ void HtmlGenerator::endConstraintList() t << "</div>" << endl; } +void HtmlGenerator::startCodeFragment() +{ + t << PREFRAG_START; +} + +void HtmlGenerator::endCodeFragment() +{ + //endCodeLine checks is there is still an open code line, if so closes it. + endCodeLine(); + + t << PREFRAG_END; +} + void HtmlGenerator::lineBreak(const char *style) { if (style) @@ -2819,7 +2852,7 @@ void HtmlGenerator::endMemberDeclaration(const char *anchor,const char *inheritI t << "\"><td class=\"memSeparator\" colspan=\"2\"> </td></tr>\n"; } -void HtmlGenerator::setCurrentDoc(Definition *context,const char *anchor,bool isSourceFile) +void HtmlGenerator::setCurrentDoc(const Definition *context,const char *anchor,bool isSourceFile) { if (Doxygen::searchIndex) { diff --git a/src/htmlgen.h b/src/htmlgen.h index 221269f..2db5b74 100644 --- a/src/htmlgen.h +++ b/src/htmlgen.h @@ -52,7 +52,7 @@ class HtmlCodeGenerator : public CodeOutputInterface void startFontClass(const char *s); void endFontClass(); void writeCodeAnchor(const char *anchor); - void setCurrentDoc(Definition *,const char *,bool) {} + void setCurrentDoc(const Definition *,const char *,bool) {} void addWord(const char *,bool) {} private: @@ -119,9 +119,9 @@ class HtmlGenerator : public OutputGenerator { m_codeGen.writeCodeAnchor(anchor); } // --------------------------- - void setCurrentDoc(Definition *context,const char *anchor,bool isSourceFile); + void setCurrentDoc(const Definition *context,const char *anchor,bool isSourceFile); void addWord(const char *word,bool hiPriority); - void writeDoc(DocNode *,Definition *,MemberDef *); + void writeDoc(DocNode *,const Definition *,const MemberDef *); void startFile(const char *name,const char *manName,const char *title); void writeFooter(const char *navPath); @@ -212,8 +212,8 @@ class HtmlGenerator : public OutputGenerator void writeRuler() { t << "<hr/>"; } void writeAnchor(const char *,const char *name) { t << "<a name=\"" << name <<"\" id=\"" << name << "\"></a>"; } - void startCodeFragment() { t << PREFRAG_START; } - void endCodeFragment() { t << PREFRAG_END; } + void startCodeFragment(); + void endCodeFragment(); void startEmphasis() { t << "<em>"; } void endEmphasis() { t << "</em>"; } void startBold() { t << "<b>"; } @@ -283,16 +283,16 @@ class HtmlGenerator : public OutputGenerator void endDescTableData(); void startDotGraph(); - void endDotGraph(const DotClassGraph &g); + void endDotGraph(DotClassGraph &g); void startInclDepGraph(); - void endInclDepGraph(const DotInclDepGraph &g); + void endInclDepGraph(DotInclDepGraph &g); void startGroupCollaboration(); - void endGroupCollaboration(const DotGroupCollaboration &g); + void endGroupCollaboration(DotGroupCollaboration &g); void startCallGraph(); - void endCallGraph(const DotCallGraph &g); + void endCallGraph(DotCallGraph &g); void startDirDepGraph(); - void endDirDepGraph(const DotDirDeps &g); - void writeGraphicalHierarchy(const DotGfxHierarchyTable &g); + void endDirDepGraph(DotDirDeps &g); + void writeGraphicalHierarchy(DotGfxHierarchyTable &g); void startTextBlock(bool) { t << "<div class=\"textblock\">"; } diff --git a/src/htmlhelp.cpp b/src/htmlhelp.cpp index 3ed3d64..20cb6ca 100644 --- a/src/htmlhelp.cpp +++ b/src/htmlhelp.cpp @@ -632,7 +632,7 @@ void HtmlHelp::addContentsItem(bool isDir, const char *anchor, bool /* separateIndex */, bool /* addToNavIndex */, - Definition * /* def */) + const Definition * /* def */) { // If we're using a binary toc then folders cannot have links. // Tried this and I didn't see any problems, when not using @@ -677,7 +677,7 @@ void HtmlHelp::addContentsItem(bool isDir, } -void HtmlHelp::addIndexItem(Definition *context,MemberDef *md, +void HtmlHelp::addIndexItem(const Definition *context,const MemberDef *md, const char *sectionAnchor,const char *word) { if (md) diff --git a/src/htmlhelp.h b/src/htmlhelp.h index 9c3fa04..184b929 100644 --- a/src/htmlhelp.h +++ b/src/htmlhelp.h @@ -78,8 +78,8 @@ class HtmlHelp : public IndexIntf const char *anchor, bool separateIndex, bool addToNavIndex, - Definition *def); - void addIndexItem(Definition *context,MemberDef *md, + const Definition *def); + void addIndexItem(const Definition *context,const MemberDef *md, const char *sectionAnchor, const char *title); void addIndexFile(const char *name); void addImageFile(const char *); diff --git a/src/index.cpp b/src/index.cpp index b401a0a..5d6c0a5 100644 --- a/src/index.cpp +++ b/src/index.cpp @@ -40,6 +40,7 @@ #include "htmlhelp.h" #include "ftvhelp.h" #include "dot.h" +#include "dotgfxhierarchytable.h" #include "pagedef.h" #include "dirdef.h" #include "vhdldocgen.h" @@ -146,7 +147,7 @@ static void endIndexHierarchy(OutputList &ol,int level) class MemberIndexList : public QList<MemberDef> { public: - typedef MemberDef ElementType; + typedef const MemberDef ElementType; MemberIndexList(uint letter) : QList<MemberDef>(), m_letter(letter) {} ~MemberIndexList() {} int compareValues(const MemberDef *md1, const MemberDef *md2) const @@ -252,7 +253,7 @@ QCString fixSpaces(const QCString &s) return substitute(s," "," "); } -void startTitle(OutputList &ol,const char *fileName,Definition *def) +void startTitle(OutputList &ol,const char *fileName,const Definition *def) { ol.startHeaderSection(); if (def) def->writeSummaryLinks(ol); @@ -285,7 +286,6 @@ void startFile(OutputList &ol,const char *name,const char *manName, } ol.writeSplitBar(altSidebarName ? altSidebarName : name); ol.writeSearchInfo(); - resetDotNodeNumbering(); } void endFile(OutputList &ol,bool skipNavIndex,bool skipEndContents, @@ -309,7 +309,7 @@ void endFile(OutputList &ol,bool skipNavIndex,bool skipEndContents, TooltipManager::instance()->clearTooltips(); // Only clear after the last is written } -void endFileWithNavPath(Definition *d,OutputList &ol) +void endFileWithNavPath(const Definition *d,OutputList &ol) { static bool generateTreeView = Config_getBool(GENERATE_TREEVIEW); QCString navPath; @@ -365,7 +365,7 @@ void addMembersToIndex(T *def,LayoutDocManager::LayoutPart part, MemberDef *md; for (mi.toFirst();(md=mi.current());++mi) { - MemberList *enumList = md->enumFieldList(); + const MemberList *enumList = md->enumFieldList(); bool isDir = enumList!=0 && md->isEnumerate(); bool isAnonymous = md->name().find('@')!=-1; static bool hideUndocMembers = Config_getBool(HIDE_UNDOC_MEMBERS); @@ -1649,14 +1649,14 @@ void writeClassTree(ClassSDict *clDict,FTVHelp *ftv,bool addToIndex,bool globalO } } -static void writeNamespaceTree(NamespaceSDict *nsDict,FTVHelp *ftv, +static void writeNamespaceTree(const NamespaceSDict *nsDict,FTVHelp *ftv, bool rootOnly,bool showClasses,bool addToIndex,ClassDef::CompoundType ct) { static bool sliceOpt = Config_getBool(OPTIMIZE_OUTPUT_SLICE); if (nsDict) { NamespaceSDict::Iterator nli(*nsDict); - NamespaceDef *nd; + const NamespaceDef *nd; for (nli.toFirst();(nd=nli.current());++nli) { if (nd->localName().find('@')==-1 && @@ -1985,7 +1985,7 @@ static QCString letterToLabel(uint startLetter) class PrefixIgnoreClassList : public ClassList { public: - typedef ClassDef ElementType; + typedef const ClassDef ElementType; PrefixIgnoreClassList(uint letter) : m_letter(letter) {} uint letter() const { return m_letter; } private: @@ -2071,7 +2071,7 @@ static void writeAlphabeticalClassList(OutputList &ol, ClassDef::CompoundType ct // first count the number of headers ClassSDict::Iterator cli(*Doxygen::classSDict); - ClassDef *cd; + const ClassDef *cd; uint startLetter=0; int headerItems=0; for (;(cd=cli.current());++cli) @@ -2748,7 +2748,7 @@ static void writeAnnotatedExceptionIndex(OutputList &ol) static void writeClassLinkForMember(OutputList &ol,MemberDef *md,const char *separator, QCString &prevClassName) { - ClassDef *cd=md->getClassDef(); + const ClassDef *cd=md->getClassDef(); if ( cd && prevClassName!=cd->displayName()) { ol.docify(separator); @@ -2762,7 +2762,7 @@ static void writeClassLinkForMember(OutputList &ol,MemberDef *md,const char *sep static void writeFileLinkForMember(OutputList &ol,MemberDef *md,const char *separator, QCString &prevFileName) { - FileDef *fd=md->getFileDef(); + const FileDef *fd=md->getFileDef(); if (fd && prevFileName!=fd->name()) { ol.docify(separator); @@ -2776,7 +2776,7 @@ static void writeFileLinkForMember(OutputList &ol,MemberDef *md,const char *sepa static void writeNamespaceLinkForMember(OutputList &ol,MemberDef *md,const char *separator, QCString &prevNamespaceName) { - NamespaceDef *nd=md->getNamespaceDef(); + const NamespaceDef *nd=md->getNamespaceDef(); if (nd && prevNamespaceName!=nd->displayName()) { ol.docify(separator); @@ -2898,9 +2898,7 @@ void initClassMemberIndices() void addClassMemberNameToIndex(MemberDef *md) { static bool hideFriendCompounds = Config_getBool(HIDE_FRIEND_COMPOUNDS); - ClassDef *cd=0; - - + const ClassDef *cd=0; if (md->isLinkableInProject() && (cd=md->getClassDef()) && @@ -2982,7 +2980,7 @@ void initNamespaceMemberIndices() void addNamespaceMemberNameToIndex(MemberDef *md) { - NamespaceDef *nd=md->getNamespaceDef(); + const NamespaceDef *nd=md->getNamespaceDef(); if (nd && nd->isLinkableInProject() && md->isLinkableInProject()) { QCString n = md->name(); @@ -3049,7 +3047,7 @@ void initFileMemberIndices() void addFileMemberNameToIndex(MemberDef *md) { - FileDef *fd=md->getFileDef(); + const FileDef *fd=md->getFileDef(); if (fd && fd->isLinkableInProject() && md->isLinkableInProject()) { QCString n = md->name(); @@ -4052,7 +4050,7 @@ static void writeGroupTreeNode(OutputList &ol, GroupDef *gd, int level, FTVHelp* MemberDef *md; for (mi.toFirst();(md=mi.current());++mi) { - MemberList *enumList = md->enumFieldList(); + const MemberList *enumList = md->enumFieldList(); bool isDir = enumList!=0 && md->isEnumerate(); if (md->isVisible() && md->name().find('@')==-1) { @@ -4733,7 +4731,7 @@ static void writeIndex(OutputList &ol) ol.parseText(/*projPrefix+*/theTranslator->trExceptionIndex()); ol.endIndexSection(isCompoundIndex); } - if (documentedFiles>0) + if (Config_getBool(SHOW_FILES) && (documentedFiles>0)) { ol.startIndexSection(isFileIndex); ol.parseText(/*projPrefix+*/theTranslator->trFileIndex()); diff --git a/src/index.h b/src/index.h index f3e0241..c6baba5 100644 --- a/src/index.h +++ b/src/index.h @@ -37,8 +37,8 @@ class IndexIntf virtual void decContentsDepth() = 0; virtual void addContentsItem(bool isDir, const char *name, const char *ref, const char *file, const char *anchor, bool separateIndex, - bool addToNavIndex,Definition *def) = 0; - virtual void addIndexItem(Definition *context,MemberDef *md, + bool addToNavIndex,const Definition *def) = 0; + virtual void addIndexItem(const Definition *context,const MemberDef *md, const char *sectionAnchor,const char *title) = 0; virtual void addIndexFile(const char *name) = 0; virtual void addImageFile(const char *name) = 0; @@ -136,11 +136,11 @@ class IndexList : public IndexIntf { if (m_enabled) foreach(&IndexIntf::decContentsDepth); } void addContentsItem(bool isDir, const char *name, const char *ref, const char *file, const char *anchor,bool separateIndex=FALSE,bool addToNavIndex=FALSE, - Definition *def=0) - { if (m_enabled) foreach<bool,const char *,const char *,const char *,const char*,bool,bool,Definition *> + const Definition *def=0) + { if (m_enabled) foreach<bool,const char *,const char *,const char *,const char*,bool,bool,const Definition *> (&IndexIntf::addContentsItem,isDir,name,ref,file,anchor,separateIndex,addToNavIndex,def); } - void addIndexItem(Definition *context,MemberDef *md,const char *sectionAnchor=0,const char *title=0) - { if (m_enabled) foreach<Definition *,MemberDef *,const char *,const char *> + void addIndexItem(const Definition *context,const MemberDef *md,const char *sectionAnchor=0,const char *title=0) + { if (m_enabled) foreach<const Definition *,const MemberDef *,const char *,const char *> (&IndexIntf::addIndexItem,context,md,sectionAnchor,title); } void addIndexFile(const char *name) { if (m_enabled) foreach<const char *>(&IndexIntf::addIndexFile,name); } @@ -289,14 +289,14 @@ extern int documentedDirs; extern int documentedHtmlFiles; extern int documentedPages; -void startTitle(OutputList &ol,const char *fileName,Definition *def=0); +void startTitle(OutputList &ol,const char *fileName,const Definition *def=0); void endTitle(OutputList &ol,const char *fileName,const char *name); void startFile(OutputList &ol,const char *name,const char *manName, const char *title,HighlightedItem hli=HLI_None, bool additionalIndices=FALSE,const char *altSidebarName=0); void endFile(OutputList &ol,bool skipNavIndex=FALSE,bool skipEndContents=FALSE, const QCString &navPath=QCString()); -void endFileWithNavPath(Definition *d,OutputList &ol); +void endFileWithNavPath(const Definition *d,OutputList &ol); void initClassMemberIndices(); void initFileMemberIndices(); diff --git a/src/latexdocvisitor.cpp b/src/latexdocvisitor.cpp index 2e979bd..9652580 100644 --- a/src/latexdocvisitor.cpp +++ b/src/latexdocvisitor.cpp @@ -566,20 +566,22 @@ void LatexDocVisitor::visit(DocIncOperator *op) pushEnabled(); m_hide = TRUE; } - SrcLangExt langExt = getLanguageFromFileName(m_langExt); + QCString locLangExt = getFileNameExtension(op->includeFileName()); + if (locLangExt.isEmpty()) locLangExt = m_langExt; + SrcLangExt langExt = getLanguageFromFileName(locLangExt); if (op->type()!=DocIncOperator::Skip) { popEnabled(); if (!m_hide) { - FileDef *fd; + FileDef *fd = 0; if (!op->includeFileName().isEmpty()) { QFileInfo cfi( op->includeFileName() ); fd = createFileDef( cfi.dirPath().utf8(), cfi.fileName().utf8() ); } - Doxygen::parserManager->getParser(m_langExt) + Doxygen::parserManager->getParser(locLangExt) ->parseCode(m_ci,op->context(),op->text(),langExt, op->isExample(),op->exampleFile(), fd, // fileDef @@ -1696,14 +1698,6 @@ void LatexDocVisitor::visitPost(DocInternalRef *ref) endLink(0,ref->file(),ref->anchor()); } -void LatexDocVisitor::visitPre(DocCopy *) -{ -} - -void LatexDocVisitor::visitPost(DocCopy *) -{ -} - void LatexDocVisitor::visitPre(DocText *) { } diff --git a/src/latexdocvisitor.h b/src/latexdocvisitor.h index 7ea8ae1..71fb5be 100644 --- a/src/latexdocvisitor.h +++ b/src/latexdocvisitor.h @@ -128,8 +128,6 @@ class LatexDocVisitor : public DocVisitor void visitPost(DocXRefItem *); void visitPre(DocInternalRef *); void visitPost(DocInternalRef *); - void visitPre(DocCopy *); - void visitPost(DocCopy *); void visitPre(DocText *); void visitPost(DocText *); void visitPre(DocHtmlBlockQuote *); diff --git a/src/latexgen.cpp b/src/latexgen.cpp index 36109fe..e6c6861 100644 --- a/src/latexgen.cpp +++ b/src/latexgen.cpp @@ -27,6 +27,11 @@ #include "language.h" #include "version.h" #include "dot.h" +#include "dotcallgraph.h" +#include "dotclassgraph.h" +#include "dotdirdeps.h" +#include "dotgroupcollaboration.h" +#include "dotincldepgraph.h" #include "pagedef.h" #include "docparser.h" #include "latexdocvisitor.h" @@ -480,7 +485,7 @@ static void writeDefaultHeaderPart1(FTextStream &t) if (Config_getBool(LATEX_BATCHMODE)) t << "\\batchmode\n"; - // to overcome problems wit too many open files + // to overcome problems with too many open files t << "\\let\\mypdfximage\\pdfximage" "\\def\\pdfximage{\\immediate\\mypdfximage}"; @@ -492,6 +497,14 @@ static void writeDefaultHeaderPart1(FTextStream &t) documentClass = "book"; t << "\\documentclass[twoside]{" << documentClass << "}\n" "\n"; + t << "%% moved from doxygen.sty due to workaround for LaTex 2019 version and unmaintained tabu package\n" + "\\usepackage{ifthen}\n" + "\\ifx\\requestedLaTeXdate\\undefined\n" + "\\usepackage{array}\n" + "\\else\n" + "\\usepackage{array}[=2016-10-06]\n" + "\\fi\n" + "%%\n"; // Load required packages t << "% Packages required by doxygen\n" @@ -1324,6 +1337,15 @@ void LatexGenerator::writeStyleInfo(int part) startPlainFile("doxygen.sty"); writeDefaultStyleSheet(t); endPlainFile(); + + // workaround for the problem caused by change in LaTeX in version 2019 + // in the unmaintained tabu package + startPlainFile("tabu_doxygen.sty"); + t << ResourceMgr::instance().getAsString("tabu_doxygen.sty"); + endPlainFile(); + startPlainFile("longtable_doxygen.sty"); + t << ResourceMgr::instance().getAsString("longtable_doxygen.sty"); + endPlainFile(); } void LatexGenerator::newParagraph() @@ -1376,7 +1398,7 @@ void LatexGenerator::startHtmlLink(const char *url) if (Config_getBool(PDF_HYPERLINKS)) { t << "\\href{"; - t << url; + t << latexFilterURL(url); t << "}"; } t << "{\\texttt{ "; @@ -2034,7 +2056,7 @@ void LatexGenerator::startDotGraph() newParagraph(); } -void LatexGenerator::endDotGraph(const DotClassGraph &g) +void LatexGenerator::endDotGraph(DotClassGraph &g) { g.writeGraph(t,GOF_EPS,EOF_LaTeX,Config_getString(LATEX_OUTPUT),fileName,relPath); } @@ -2043,7 +2065,7 @@ void LatexGenerator::startInclDepGraph() { } -void LatexGenerator::endInclDepGraph(const DotInclDepGraph &g) +void LatexGenerator::endInclDepGraph(DotInclDepGraph &g) { g.writeGraph(t,GOF_EPS,EOF_LaTeX,Config_getString(LATEX_OUTPUT),fileName,relPath); } @@ -2052,7 +2074,7 @@ void LatexGenerator::startGroupCollaboration() { } -void LatexGenerator::endGroupCollaboration(const DotGroupCollaboration &g) +void LatexGenerator::endGroupCollaboration(DotGroupCollaboration &g) { g.writeGraph(t,GOF_EPS,EOF_LaTeX,Config_getString(LATEX_OUTPUT),fileName,relPath); } @@ -2061,7 +2083,7 @@ void LatexGenerator::startCallGraph() { } -void LatexGenerator::endCallGraph(const DotCallGraph &g) +void LatexGenerator::endCallGraph(DotCallGraph &g) { g.writeGraph(t,GOF_EPS,EOF_LaTeX,Config_getString(LATEX_OUTPUT),fileName,relPath); } @@ -2070,7 +2092,7 @@ void LatexGenerator::startDirDepGraph() { } -void LatexGenerator::endDirDepGraph(const DotDirDeps &g) +void LatexGenerator::endDirDepGraph(DotDirDeps &g) { g.writeGraph(t,GOF_EPS,EOF_LaTeX,Config_getString(LATEX_OUTPUT),fileName,relPath); } @@ -2175,7 +2197,7 @@ void LatexGenerator::exceptionEntry(const char* prefix,bool closeBracket) t << " "; } -void LatexGenerator::writeDoc(DocNode *n,Definition *ctx,MemberDef *) +void LatexGenerator::writeDoc(DocNode *n,const Definition *ctx,const MemberDef *) { LatexDocVisitor *visitor = new LatexDocVisitor(t,*this,ctx?ctx->getDefFileExtension():QCString(""),insideTabbing); diff --git a/src/latexgen.h b/src/latexgen.h index 1460000..6430dbc 100644 --- a/src/latexgen.h +++ b/src/latexgen.h @@ -49,7 +49,7 @@ class LatexCodeGenerator : public CodeOutputInterface void startFontClass(const char *); void endFontClass(); void writeCodeAnchor(const char *) {} - void setCurrentDoc(Definition *,const char *,bool) {} + void setCurrentDoc(const Definition *,const char *,bool) {} void addWord(const char *,bool) {} static void setDoxyCodeOpen(bool val); @@ -116,7 +116,7 @@ class LatexGenerator : public OutputGenerator // --------------------------- - void writeDoc(DocNode *,Definition *ctx,MemberDef *); + void writeDoc(DocNode *,const Definition *ctx,const MemberDef *); void startFile(const char *name,const char *manName,const char *title); void writeSearchInfo() {} @@ -273,16 +273,16 @@ class LatexGenerator : public OutputGenerator void lastIndexPage(); void startDotGraph(); - void endDotGraph(const DotClassGraph &); + void endDotGraph(DotClassGraph &); void startInclDepGraph(); - void endInclDepGraph(const DotInclDepGraph &); + void endInclDepGraph(DotInclDepGraph &); void startCallGraph(); void startGroupCollaboration(); - void endGroupCollaboration(const DotGroupCollaboration &g); - void endCallGraph(const DotCallGraph &); + void endGroupCollaboration(DotGroupCollaboration &g); + void endCallGraph(DotCallGraph &); void startDirDepGraph(); - void endDirDepGraph(const DotDirDeps &g); - void writeGraphicalHierarchy(const DotGfxHierarchyTable &) {} + void endDirDepGraph(DotDirDeps &g); + void writeGraphicalHierarchy(DotGfxHierarchyTable &) {} void startTextBlock(bool) {} void endTextBlock(bool) {} @@ -321,7 +321,7 @@ class LatexGenerator : public OutputGenerator void writeLabel(const char *l,bool isLast); void endLabels(); - void setCurrentDoc(Definition *,const char *,bool) {} + void setCurrentDoc(const Definition *,const char *,bool) {} void addWord(const char *,bool) {} diff --git a/src/layout.cpp b/src/layout.cpp index f9fe3b0..30c41f9 100644 --- a/src/layout.cpp +++ b/src/layout.cpp @@ -106,7 +106,7 @@ QCString LayoutNavEntry::url() const } else if (url.left(5)=="@ref " || url.left(5)=="\\ref ") { - Definition *d; + const Definition *d = 0; QCString anchor; bool found=FALSE; if (resolveLink(0,url.mid(5).stripWhiteSpace(),TRUE,&d,anchor)) @@ -1538,10 +1538,11 @@ void LayoutDocManager::clear(LayoutDocManager::LayoutPart p) d->docEntries[(int)p].clear(); } -void LayoutDocManager::parse(QTextStream &t,const char *fileName) +void LayoutDocManager::parse(const char *fileName) { LayoutErrorHandler errorHandler(fileName); - QXmlInputSource source( t ); + QXmlInputSource source; + source.setData(fileToString(fileName)); QXmlSimpleReader reader; reader.setContentHandler( &LayoutParser::instance() ); reader.setErrorHandler( &errorHandler ); diff --git a/src/layout.h b/src/layout.h index b25aa4e..b1facf5 100644 --- a/src/layout.h +++ b/src/layout.h @@ -201,7 +201,7 @@ class LayoutDocManager LayoutNavEntry *rootNavEntry() const; /** Parses a user provided layout */ - void parse(QTextStream &t,const char *fileName); + void parse(const char *fileName); void init(); private: void addEntry(LayoutPart p,LayoutDocEntry*e); diff --git a/src/lodepng.cpp b/src/lodepng.cpp deleted file mode 100644 index 1906f09..0000000 --- a/src/lodepng.cpp +++ /dev/null @@ -1,2445 +0,0 @@ -/* -LodePNG version 20080927 - -Copyright (c) 2005-2008 Lode Vandevenne - -This software is provided 'as-is', without any express or implied -warranty. In no event will the authors be held liable for any damages -arising from the use of this software. - -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it -freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - - 3. This notice may not be removed or altered from any source - distribution. -*/ - -/* -The manual and changelog can be found in the header file "lodepng.h" -You are free to name this file lodepng.cpp or lodepng.c depending on your usage. -*/ - -#include "lodepng.h" -#include "portable.h" - -#define USE_BRUTE_FORCE_ENCODING 1 - -#define VERSION_STRING "20080927" - -/* ////////////////////////////////////////////////////////////////////////// */ -/* / Tools For C / */ -/* ////////////////////////////////////////////////////////////////////////// */ - -/* -About these tools (vector, uivector, ucvector and string): --LodePNG was originally written in C++. The vectors replace the std::vectors that were used in the C++ version. --The string tools are made to avoid problems with compilers that declare things like strncat as deprecated. --They're not used in the interface, only internally in this file, so all their functions are made static. -*/ - -//-------------------------------------------------------------------------------------------- - - -/*LodePNG_chunk functions: These functions need as input a large enough amount of allocated memory.*/ - -static unsigned LodePNG_chunk_length(const unsigned char* chunk); /*get the length of the data of the chunk. Total chunk length has 12 bytes more.*/ - -static void LodePNG_chunk_generate_crc(unsigned char* chunk); /*generates the correct CRC from the data and puts it in the last 4 bytes of the chunk*/ - -/*add chunks to out buffer. It reallocs the buffer to append the data. returns error code*/ -static unsigned LodePNG_create_chunk(unsigned char** out, size_t* outlength, unsigned length, const char* type, const unsigned char* data); /*appends new chunk to out. Returns pointer to start of appended chunk, or NULL if error happened; may change memory address of out buffer*/ - -static void LodePNG_InfoColor_init(LodePNG_InfoColor* info); -static void LodePNG_InfoColor_cleanup(LodePNG_InfoColor* info); -static unsigned LodePNG_InfoColor_copy(LodePNG_InfoColor* dest, const LodePNG_InfoColor* source); - -/*Use these functions instead of allocating palette manually*/ -static void LodePNG_InfoColor_clearPalette(LodePNG_InfoColor* info); - -/*additional color info*/ -static unsigned LodePNG_InfoColor_getBpp(const LodePNG_InfoColor* info); /*bits per pixel*/ -static unsigned LodePNG_InfoColor_isGreyscaleType(const LodePNG_InfoColor* info); /*is it a greyscale type? (colorType 0 or 4)*/ -static unsigned LodePNG_InfoColor_isAlphaType(const LodePNG_InfoColor* info); /*has it an alpha channel? (colorType 2 or 6)*/ - -static void LodePNG_InfoPng_init(LodePNG_InfoPng* info); -static void LodePNG_InfoPng_cleanup(LodePNG_InfoPng* info); -static unsigned LodePNG_InfoPng_copy(LodePNG_InfoPng* dest, const LodePNG_InfoPng* source); - -static void LodePNG_InfoRaw_init(LodePNG_InfoRaw* info); -static void LodePNG_InfoRaw_cleanup(LodePNG_InfoRaw* info); -static unsigned LodePNG_InfoRaw_copy(LodePNG_InfoRaw* dest, const LodePNG_InfoRaw* source); - -/* -LodePNG_convert: Converts from any color type to 24-bit or 32-bit (later maybe more supported). return value = LodePNG error code -The out buffer must have (w * h * bpp + 7) / 8, where bpp is the bits per pixel of the output color type (LodePNG_InfoColor_getBpp) -*/ -static unsigned LodePNG_convert(unsigned char* out, const unsigned char* in, LodePNG_InfoColor* infoOut, LodePNG_InfoColor* infoIn, unsigned w, unsigned h); - -static void LodeZlib_DeflateSettings_init(LodeZlib_DeflateSettings* settings); - -/* ////////////////////////////////////////////////////////////////////////// */ -/* LodeFlate & LodeZlib */ -/* ////////////////////////////////////////////////////////////////////////// */ - -/*This function reallocates the out buffer and appends the data. -Either, *out must be NULL and *outsize must be 0, or, *out must be a valid buffer and *outsize its size in bytes.*/ -//unsigned LodeZlib_compress(unsigned char** out, size_t* outsize, const unsigned char* in, size_t insize, const LodeZlib_DeflateSettings* settings); - -//-------------------------------------------------------------------------------------------- - -typedef struct vector /*this one is used only by the deflate compressor*/ -{ - void* data; - size_t size; /*in groups of bytes depending on type*/ - size_t allocsize; /*in bytes*/ - unsigned typesize; /*sizeof the type you store in data*/ -} vector; - -static unsigned vector_resize(vector* p, size_t size) /*returns 1 if success, 0 if failure ==> nothing done*/ -{ - if(size * p->typesize > p->allocsize) - { - size_t newsize = size * p->typesize * 2; - void* data = realloc(p->data, newsize); - if(data) - { - p->allocsize = newsize; - p->data = data; - p->size = size; - } - else return 0; - } - else p->size = size; - return 1; -} - -static unsigned vector_resized(vector* p, size_t size, void dtor(void*)) /*resize and use destructor on elements if it gets smaller*/ -{ - size_t i; - if(size < p->size) for(i = size; i < p->size; i++) dtor(&((char*)(p->data))[i * p->typesize]); - return vector_resize(p, size); -} - -static void vector_cleanup(void* p) -{ - ((vector*)p)->size = ((vector*)p)->allocsize = 0; - free(((vector*)p)->data); - ((vector*)p)->data = NULL; -} - -static void vector_cleanupd(vector* p, void dtor(void*)) /*clear and use destructor on elements*/ -{ - vector_resized(p, 0, dtor); - vector_cleanup(p); -} - -static void vector_init(vector* p, unsigned typesize) -{ - p->data = NULL; - p->size = p->allocsize = 0; - p->typesize = typesize; -} - -static void vector_swap(vector* p, vector* q) /*they're supposed to have the same typesize*/ -{ - size_t tmp; - void* tmpp; - tmp = p->size; p->size = q->size; q->size = tmp; - tmp = p->allocsize; p->allocsize = q->allocsize; q->allocsize = tmp; - tmpp = p->data; p->data = q->data; q->data = tmpp; -} - -static void* vector_get(vector* p, size_t index) -{ - return &((char*)p->data)[index * p->typesize]; -} - -/* /////////////////////////////////////////////////////////////////////////// */ - -typedef struct uivector -{ - unsigned* data; - size_t size; /*size in number of unsigned longs*/ - size_t allocsize; /*allocated size in bytes*/ -} uivector; - -static void uivector_cleanup(void* p) -{ - ((uivector*)p)->size = ((uivector*)p)->allocsize = 0; - free(((uivector*)p)->data); - ((uivector*)p)->data = NULL; -} - -static unsigned uivector_resize(uivector* p, size_t size) /*returns 1 if success, 0 if failure ==> nothing done*/ -{ - if(size * sizeof(unsigned) > p->allocsize) - { - size_t newsize = size * sizeof(unsigned) * 2; - void* data = realloc(p->data, newsize); - if(data) - { - p->allocsize = newsize; - p->data = (unsigned*)data; - p->size = size; - } - else return 0; - } - else p->size = size; - return 1; -} - -static unsigned uivector_resizev(uivector* p, size_t size, unsigned value) /*resize and give all new elements the value*/ -{ - size_t oldsize = p->size, i; - if(!uivector_resize(p, size)) return 0; - for(i = oldsize; i < size; i++) p->data[i] = value; - return 1; -} - -static void uivector_init(uivector* p) -{ - p->data = NULL; - p->size = p->allocsize = 0; -} - -static unsigned uivector_push_back(uivector* p, unsigned c) /*returns 1 if success, 0 if failure ==> nothing done*/ -{ - if(!uivector_resize(p, p->size + 1)) return 0; - p->data[p->size - 1] = c; - return 1; -} - -static unsigned uivector_copy(uivector* p, const uivector* q) /*copy q to p, returns 1 if success, 0 if failure ==> nothing done*/ -{ - size_t i; - if(!uivector_resize(p, q->size)) return 0; - for(i = 0; i < q->size; i++) p->data[i] = q->data[i]; - return 1; -} - -static void uivector_swap(uivector* p, uivector* q) -{ - size_t tmp; - unsigned* tmpp; - tmp = p->size; p->size = q->size; q->size = tmp; - tmp = p->allocsize; p->allocsize = q->allocsize; q->allocsize = tmp; - tmpp = p->data; p->data = q->data; q->data = tmpp; -} - -/* /////////////////////////////////////////////////////////////////////////// */ - -typedef struct ucvector -{ - unsigned char* data; - size_t size; /*used size*/ - size_t allocsize; /*allocated size*/ -} ucvector; - -static void ucvector_cleanup(void* p) -{ - ((ucvector*)p)->size = ((ucvector*)p)->allocsize = 0; - free(((ucvector*)p)->data); - ((ucvector*)p)->data = NULL; -} - -static unsigned ucvector_resize(ucvector* p, size_t size) /*returns 1 if success, 0 if failure ==> nothing done*/ -{ - if(size * sizeof(unsigned) > p->allocsize) - { - size_t newsize = size * sizeof(unsigned) * 2; - void* data = realloc(p->data, newsize); - if(data) - { - p->allocsize = newsize; - p->data = (unsigned char*)data; - p->size = size; - } - else return 0; /*error: not enough memory*/ - } - else p->size = size; - return 1; -} - - -static void ucvector_init(ucvector* p) -{ - p->data = NULL; - p->size = p->allocsize = 0; -} - -/*you can both convert from vector to buffer&size and vica versa*/ -static void ucvector_init_buffer(ucvector* p, unsigned char* buffer, size_t size) -{ - p->data = buffer; - p->allocsize = p->size = size; -} - -static unsigned ucvector_push_back(ucvector* p, unsigned char c) /*returns 1 if success, 0 if failure ==> nothing done*/ -{ - if(!ucvector_resize(p, p->size + 1)) return 0; - p->data[p->size - 1] = c; - return 1; -} - -/* ////////////////////////////////////////////////////////////////////////// */ -/* / Reading and writing single bits and bytes from/to stream for Deflate / */ -/* ////////////////////////////////////////////////////////////////////////// */ - -static void addBitToStream(size_t* bitpointer, ucvector* bitstream, unsigned char bit) -{ - if((*bitpointer) % 8 == 0) ucvector_push_back(bitstream, 0); /*add a new byte at the end*/ - (bitstream->data[bitstream->size - 1]) |= (bit << ((*bitpointer) & 0x7)); /*earlier bit of huffman code is in a lesser significant bit of an earlier byte*/ - (*bitpointer)++; -} - -static void addBitsToStream(size_t* bitpointer, ucvector* bitstream, unsigned value, size_t nbits) -{ - size_t i; - for(i = 0; i < nbits; i++) addBitToStream(bitpointer, bitstream, (unsigned char)((value >> i) & 1)); -} - -static void addBitsToStreamReversed(size_t* bitpointer, ucvector* bitstream, unsigned value, size_t nbits) -{ - size_t i; - for(i = 0; i < nbits; i++) addBitToStream(bitpointer, bitstream, (unsigned char)((value >> (nbits - 1 - i)) & 1)); -} - - -/* ////////////////////////////////////////////////////////////////////////// */ -/* / Deflate - Huffman / */ -/* ////////////////////////////////////////////////////////////////////////// */ - -#define FIRST_LENGTH_CODE_INDEX 257 -#define LAST_LENGTH_CODE_INDEX 285 -#define NUM_DEFLATE_CODE_SYMBOLS 288 /*256 literals, the end code, some length codes, and 2 unused codes*/ -#define NUM_DISTANCE_SYMBOLS 32 /*the distance codes have their own symbols, 30 used, 2 unused*/ -#define NUM_CODE_LENGTH_CODES 19 /*the code length codes. 0-15: code lengths, 16: copy previous 3-6 times, 17: 3-10 zeros, 18: 11-138 zeros*/ - -static const unsigned LENGTHBASE[29] /*the base lengths represented by codes 257-285*/ - = {3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258}; -static const unsigned LENGTHEXTRA[29] /*the extra bits used by codes 257-285 (added to base length)*/ - = {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0}; -static const unsigned DISTANCEBASE[30] /*the base backwards distances (the bits of distance codes appear after length codes and use their own huffman tree)*/ - = {1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577}; -static const unsigned DISTANCEEXTRA[30] /*the extra bits of backwards distances (added to base)*/ - = {0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13}; -static const unsigned CLCL[NUM_CODE_LENGTH_CODES] /*the order in which "code length alphabet code lengths" are stored, out of this the huffman tree of the dynamic huffman tree lengths is generated*/ - = {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; - -/* /////////////////////////////////////////////////////////////////////////// */ - -/*terminology used for the package-merge algorithm and the coin collector's problem*/ -typedef struct Coin /*a coin can be multiple coins (when they're merged)*/ -{ - uivector symbols; - float weight; /*the sum of all weights in this coin*/ -} Coin; - -static void Coin_init(Coin* c) -{ - uivector_init(&c->symbols); -} - -static void Coin_cleanup(void* c) /*void* so that this dtor can be given as function pointer to the vector resize function*/ -{ - uivector_cleanup(&((Coin*)c)->symbols); -} - -static void Coin_copy(Coin* c1, const Coin* c2) -{ - c1->weight = c2->weight; - uivector_copy(&c1->symbols, &c2->symbols); -} - -static void addCoins(Coin* c1, const Coin* c2) -{ - unsigned i; - for(i = 0; i < c2->symbols.size; i++) uivector_push_back(&c1->symbols, c2->symbols.data[i]); - c1->weight += c2->weight; -} - -static void Coin_sort(Coin* data, size_t amount) /*combsort*/ -{ - size_t gap = amount; - unsigned char swapped = 0; - while(gap > 1 || swapped) - { - size_t i; - gap = (gap * 10) / 13; /*shrink factor 1.3*/ - if(gap == 9 || gap == 10) gap = 11; /*combsort11*/ - if(gap < 1) gap = 1; - swapped = 0; - for(i = 0; i < amount - gap; i++) - { - size_t j = i + gap; - if(data[j].weight < data[i].weight) - { - float temp = data[j].weight; data[j].weight = data[i].weight; data[i].weight = temp; - uivector_swap(&data[i].symbols, &data[j].symbols); - swapped = 1; - } - } - } -} - -typedef struct HuffmanTree -{ - uivector tree2d; - uivector tree1d; - uivector lengths; /*the lengths of the codes of the 1d-tree*/ - unsigned maxbitlen; /*maximum number of bits a single code can get*/ - unsigned numcodes; /*number of symbols in the alphabet = number of codes*/ -} HuffmanTree; - -/*function used for debug purposes*/ -/*#include <iostream> -static void HuffmanTree_draw(HuffmanTree* tree) -{ - std::cout << "tree. length: " << tree->numcodes << " maxbitlen: " << tree->maxbitlen << std::endl; - for(size_t i = 0; i < tree->tree1d.size; i++) - { - if(tree->lengths.data[i]) - std::cout << i << " " << tree->tree1d.data[i] << " " << tree->lengths.data[i] << std::endl; - } - std::cout << std::endl; -}*/ - -static void HuffmanTree_init(HuffmanTree* tree) -{ - uivector_init(&tree->tree2d); - uivector_init(&tree->tree1d); - uivector_init(&tree->lengths); -} - -static void HuffmanTree_cleanup(HuffmanTree* tree) -{ - uivector_cleanup(&tree->tree2d); - uivector_cleanup(&tree->tree1d); - uivector_cleanup(&tree->lengths); -} - -/*the tree representation used by the decoder. return value is error*/ -static unsigned HuffmanTree_make2DTree(HuffmanTree* tree) -{ - unsigned nodefilled = 0; /*up to which node it is filled*/ - unsigned treepos = 0; /*position in the tree (1 of the numcodes columns)*/ - unsigned n, i; - - if(!uivector_resize(&tree->tree2d, tree->numcodes * 2)) return 9901; /*if failed return not enough memory error*/ - /*convert tree1d[] to tree2d[][]. In the 2D array, a value of 32767 means uninited, a value >= numcodes is an address to another bit, a value < numcodes is a code. The 2 rows are the 2 possible bit values (0 or 1), there are as many columns as codes - 1 - a good huffmann tree has N * 2 - 1 nodes, of which N - 1 are internal nodes. Here, the internal nodes are stored (what their 0 and 1 option point to). There is only memory for such good tree currently, if there are more nodes (due to too long length codes), error 55 will happen*/ - for(n = 0; n < tree->numcodes * 2; n++) tree->tree2d.data[n] = 32767; /*32767 here means the tree2d isn't filled there yet*/ - - for(n = 0; n < tree->numcodes; n++) /*the codes*/ - for(i = 0; i < tree->lengths.data[n]; i++) /*the bits for this code*/ - { - unsigned char bit = (unsigned char)((tree->tree1d.data[n] >> (tree->lengths.data[n] - i - 1)) & 1); - if(treepos > tree->numcodes - 2) return 55; /*error 55: oversubscribed; see description in header*/ - if(tree->tree2d.data[2 * treepos + bit] == 32767) /*not yet filled in*/ - { - if(i + 1 == tree->lengths.data[n]) /*last bit*/ - { - tree->tree2d.data[2 * treepos + bit] = n; /*put the current code in it*/ - treepos = 0; - } - else /*put address of the next step in here, first that address has to be found of course (it's just nodefilled + 1)...*/ - { - nodefilled++; - tree->tree2d.data[2 * treepos + bit] = nodefilled + tree->numcodes; /*addresses encoded with numcodes added to it*/ - treepos = nodefilled; - } - } - else treepos = tree->tree2d.data[2 * treepos + bit] - tree->numcodes; - } - for(n = 0; n < tree->numcodes * 2; n++) if(tree->tree2d.data[n] == 32767) tree->tree2d.data[n] = 0; /*remove possible remaining 32767's*/ - - return 0; -} - -static unsigned HuffmanTree_makeFromLengths2(HuffmanTree* tree) /*given that numcodes, lengths and maxbitlen are already filled in correctly. return value is error.*/ -{ - uivector blcount; - uivector nextcode; - unsigned bits, n, error = 0; - - uivector_init(&blcount); - uivector_init(&nextcode); - if(!uivector_resize(&tree->tree1d, tree->numcodes) - || !uivector_resizev(&blcount, tree->maxbitlen + 1, 0) - || !uivector_resizev(&nextcode, tree->maxbitlen + 1, 0)) - error = 9902; - - if(!error) - { - /*step 1: count number of instances of each code length*/ - for(bits = 0; bits < tree->numcodes; bits++) blcount.data[tree->lengths.data[bits]]++; - /*step 2: generate the nextcode values*/ - for(bits = 1; bits <= tree->maxbitlen; bits++) nextcode.data[bits] = (nextcode.data[bits - 1] + blcount.data[bits - 1]) << 1; - /*step 3: generate all the codes*/ - for(n = 0; n < tree->numcodes; n++) if(tree->lengths.data[n] != 0) tree->tree1d.data[n] = nextcode.data[tree->lengths.data[n]]++; - } - - uivector_cleanup(&blcount); - uivector_cleanup(&nextcode); - - if(!error) return HuffmanTree_make2DTree(tree); - else return error; -} - -/*given the code lengths (as stored in the PNG file), generate the tree as defined by Deflate. maxbitlen is the maximum bits that a code in the tree can have. return value is error.*/ -static unsigned HuffmanTree_makeFromLengths(HuffmanTree* tree, const unsigned* bitlen, size_t numcodes, unsigned maxbitlen) -{ - unsigned i; - if(!uivector_resize(&tree->lengths, numcodes)) return 9903; - for(i = 0; i < numcodes; i++) tree->lengths.data[i] = bitlen[i]; - tree->numcodes = (unsigned)numcodes; /*number of symbols*/ - tree->maxbitlen = maxbitlen; - return HuffmanTree_makeFromLengths2(tree); -} - -static unsigned HuffmanTree_fillInCoins(vector* coins, const unsigned* frequencies, unsigned numcodes, size_t sum) -{ - unsigned i; - for(i = 0; i < numcodes; i++) - { - Coin* coin; - if(frequencies[i] == 0) continue; /*it's important to exclude symbols that aren't present*/ - if(!vector_resize(coins, coins->size + 1)) { vector_cleanup(coins); return 9904; } - coin = (Coin*)(vector_get(coins, coins->size - 1)); - Coin_init(coin); - coin->weight = frequencies[i] / (float)sum; - uivector_push_back(&coin->symbols, i); - } - if(coins->size) Coin_sort((Coin*)coins->data, coins->size); - return 0; -} - -static unsigned HuffmanTree_makeFromFrequencies(HuffmanTree* tree, const unsigned* frequencies, size_t numcodes, unsigned maxbitlen) -{ - unsigned i, j; - size_t sum = 0, numpresent = 0; - unsigned error = 0; - - vector prev_row; /*type Coin, the previous row of coins*/ - vector coins; /*type Coin, the coins of the currently calculated row*/ - - tree->maxbitlen = maxbitlen; - - for(i = 0; i < numcodes; i++) - { - if(frequencies[i] > 0) - { - numpresent++; - sum += frequencies[i]; - } - } - - if(numcodes == 0) return 80; /*error: a tree of 0 symbols is not supposed to be made*/ - tree->numcodes = (unsigned)numcodes; /*number of symbols*/ - uivector_resize(&tree->lengths, 0); - if(!uivector_resizev(&tree->lengths, tree->numcodes, 0)) return 9905; - - if(numpresent == 0) /*there are no symbols at all, in that case add one symbol of value 0 to the tree (see RFC 1951 section 3.2.7) */ - { - tree->lengths.data[0] = 1; - return HuffmanTree_makeFromLengths2(tree); - } - else if(numpresent == 1) /*the package merge algorithm gives wrong results if there's only one symbol (theoretically 0 bits would then suffice, but we need a proper symbol for zlib)*/ - { - for(i = 0; i < numcodes; i++) if(frequencies[i]) tree->lengths.data[i] = 1; - return HuffmanTree_makeFromLengths2(tree); - } - - vector_init(&coins, sizeof(Coin)); - vector_init(&prev_row, sizeof(Coin)); - - /*Package-Merge algorithm represented by coin collector's problem - For every symbol, maxbitlen coins will be created*/ - - /*first row, lowest denominator*/ - error = HuffmanTree_fillInCoins(&coins, frequencies, tree->numcodes, sum); - if(!error) - { - for(j = 1; j <= maxbitlen && !error; j++) /*each of the remaining rows*/ - { - vector_swap(&coins, &prev_row); /*swap instead of copying*/ - if(!vector_resized(&coins, 0, Coin_cleanup)) { error = 9906; break; } - - for(i = 0; i + 1 < prev_row.size; i += 2) - { - if(!vector_resize(&coins, coins.size + 1)) { error = 9907; break; } - Coin_init((Coin*)vector_get(&coins, coins.size - 1)); - Coin_copy((Coin*)vector_get(&coins, coins.size - 1), (Coin*)vector_get(&prev_row, i)); - addCoins((Coin*)vector_get(&coins, coins.size - 1), (Coin*)vector_get(&prev_row, i + 1)); /*merge the coins into packages*/ - } - if(j < maxbitlen) - { - error = HuffmanTree_fillInCoins(&coins, frequencies, tree->numcodes, sum); - } - } - } - - if(!error) - { - /*keep the coins with lowest weight, so that they add up to the amount of symbols - 1*/ - vector_resized(&coins, numpresent - 1, Coin_cleanup); - - /*calculate the lengths of each symbol, as the amount of times a coin of each symbol is used*/ - for(i = 0; i < coins.size; i++) - { - Coin* coin = (Coin*)vector_get(&coins, i); - for(j = 0; j < coin->symbols.size; j++) tree->lengths.data[coin->symbols.data[j]]++; - } - - error = HuffmanTree_makeFromLengths2(tree); - } - - vector_cleanupd(&coins, Coin_cleanup); - vector_cleanupd(&prev_row, Coin_cleanup); - - return error; -} - -static unsigned HuffmanTree_getCode(const HuffmanTree* tree, unsigned index) { return tree->tree1d.data[index]; } -static unsigned HuffmanTree_getLength(const HuffmanTree* tree, unsigned index) { return tree->lengths.data[index]; } - -/*get the tree of a deflated block with fixed tree, as specified in the deflate specification*/ -static unsigned generateFixedTree(HuffmanTree* tree) -{ - unsigned i, error = 0; - uivector bitlen; - uivector_init(&bitlen); - if(!uivector_resize(&bitlen, NUM_DEFLATE_CODE_SYMBOLS)) error = 9909; - - if(!error) - { - /*288 possible codes: 0-255=literals, 256=endcode, 257-285=lengthcodes, 286-287=unused*/ - for(i = 0; i <= 143; i++) bitlen.data[i] = 8; - for(i = 144; i <= 255; i++) bitlen.data[i] = 9; - for(i = 256; i <= 279; i++) bitlen.data[i] = 7; - for(i = 280; i <= 287; i++) bitlen.data[i] = 8; - - error = HuffmanTree_makeFromLengths(tree, bitlen.data, NUM_DEFLATE_CODE_SYMBOLS, 15); - } - - uivector_cleanup(&bitlen); - return error; -} - -static unsigned generateDistanceTree(HuffmanTree* tree) -{ - unsigned i, error = 0; - uivector bitlen; - uivector_init(&bitlen); - if(!uivector_resize(&bitlen, NUM_DISTANCE_SYMBOLS)) error = 9910; - - /*there are 32 distance codes, but 30-31 are unused*/ - if(!error) - { - for(i = 0; i < NUM_DISTANCE_SYMBOLS; i++) bitlen.data[i] = 5; - error = HuffmanTree_makeFromLengths(tree, bitlen.data, NUM_DISTANCE_SYMBOLS, 15); - } - uivector_cleanup(&bitlen); - return error; -} - -/* ////////////////////////////////////////////////////////////////////////// */ -/* / Deflator / */ -/* ////////////////////////////////////////////////////////////////////////// */ - -static const size_t MAX_SUPPORTED_DEFLATE_LENGTH = 258; - -/*bitlen is the size in bits of the code*/ -static void addHuffmanSymbol(size_t* bp, ucvector* compressed, unsigned code, unsigned bitlen) -{ - addBitsToStreamReversed(bp, compressed, code, bitlen); -} - -/*search the index in the array, that has the largest value smaller than or equal to the given value, given array must be sorted (if no value is smaller, it returns the size of the given array)*/ -static size_t searchCodeIndex(const unsigned* array, size_t array_size, size_t value) -{ - /*linear search implementation*/ - /*for(size_t i = 1; i < array_size; i++) if(array[i] > value) return i - 1; - return array_size - 1;*/ - - /*binary search implementation (not that much faster) (precondition: array_size > 0)*/ - size_t left = 1; - size_t right = array_size - 1; - while(left <= right) - { - size_t mid = (left + right) / 2; - if(array[mid] <= value) left = mid + 1; /*the value to find is more to the right*/ - else if(array[mid - 1] > value) right = mid - 1; /*the value to find is more to the left*/ - else return mid - 1; - } - return array_size - 1; -} - -static void addLengthDistance(uivector* values, size_t length, size_t distance) -{ - /*values in encoded vector are those used by deflate: - 0-255: literal bytes - 256: end - 257-285: length/distance pair (length code, followed by extra length bits, distance code, extra distance bits) - 286-287: invalid*/ - - unsigned length_code = (unsigned)searchCodeIndex(LENGTHBASE, 29, length); - unsigned extra_length = (unsigned)(length - LENGTHBASE[length_code]); - unsigned dist_code = (unsigned)searchCodeIndex(DISTANCEBASE, 30, distance); - unsigned extra_distance = (unsigned)(distance - DISTANCEBASE[dist_code]); - - uivector_push_back(values, length_code + FIRST_LENGTH_CODE_INDEX); - uivector_push_back(values, extra_length); - uivector_push_back(values, dist_code); - uivector_push_back(values, extra_distance); -} - -#if USE_BRUTE_FORCE_ENCODING -#define encodeLZ77 encodeLZ77_brute -/*the "brute force" version of the encodeLZ7 algorithm, not used anymore, kept here for reference*/ -static unsigned encodeLZ77_brute(uivector* out, const unsigned char* in, size_t size, unsigned windowSize) -{ - size_t pos; - /*using pointer instead of vector for input makes it faster when NOT using optimization when compiling; no influence if optimization is used*/ - for(pos = 0; pos < size; pos++) - { - /*Phase 1: doxygen images often have long runs of the same color, try to find them*/ - const int minLength = 4; // Minimum length for a run to make sense - - if(pos < size - minLength * 4) - { - size_t p, fp; - size_t current_length; - - /*RGBA pixel run?*/ - p = pos; - fp = pos + 4; - current_length = 0; - - while(fp < size && in[p] == in[fp] && current_length < MAX_SUPPORTED_DEFLATE_LENGTH) - { - ++p; - ++fp; - ++current_length; - } - - if (current_length > (minLength - 1 ) * 4) /*worth using?*/ - { - uivector_push_back(out, in[pos ]); - uivector_push_back(out, in[pos + 1]); - uivector_push_back(out, in[pos + 2]); - uivector_push_back(out, in[pos + 3]); - addLengthDistance(out, current_length, 4); - - pos += current_length + 4 - 1; /*-1 for loop's pos++*/ - continue; - } - - /*RGB pixel run?*/ - p = pos; - fp = pos + 3; - current_length = 0; - - while(fp < size && in[p] == in[fp] && current_length < MAX_SUPPORTED_DEFLATE_LENGTH) - { - ++p; - ++fp; - ++current_length; - } - - if (current_length > (minLength - 1 ) * 3) /*worth using?*/ - { - uivector_push_back(out, in[pos ]); - uivector_push_back(out, in[pos + 1]); - uivector_push_back(out, in[pos + 2]); - addLengthDistance(out, current_length, 3); - - pos += current_length + 3 - 1; /*-1 for loop's pos++*/ - continue; - } - } - - size_t length = 0, offset = 0; /*the length and offset found for the current position*/ - size_t max_offset = pos < windowSize ? pos : windowSize; /*how far back to test*/ - size_t current_offset; - - /**search for the longest string**/ - for(current_offset = 1; current_offset < max_offset; current_offset++) /*search backwards through all possible distances (=offsets)*/ - { - size_t backpos = pos - current_offset; - if(in[backpos] == in[pos]) - { - /*test the next characters*/ - size_t current_length = 1; - size_t backtest = backpos + 1; - size_t foretest = pos + 1; - while(foretest < size && in[backtest] == in[foretest] && current_length < MAX_SUPPORTED_DEFLATE_LENGTH) /*maximum support length by deflate is max length*/ - { - if(backpos >= pos) backpos -= current_offset; /*continue as if we work on the decoded bytes after pos by jumping back before pos*/ - current_length++; - backtest++; - foretest++; - } - if(current_length > length) - { - length = current_length; /*the longest length*/ - offset = current_offset; /*the offset that is related to this longest length*/ - if(current_length == MAX_SUPPORTED_DEFLATE_LENGTH) break; /*you can jump out of this for loop once a length of max length is found (gives significant speed gain)*/ - } - } - } - - /**encode it as length/distance pair or literal value**/ - if(length < 3) /*only lengths of 3 or higher are supported as length/distance pair*/ - { - uivector_push_back(out, in[pos]); - } - else - { - addLengthDistance(out, length, offset); - pos += (length - 1); - } - } /*end of the loop through each character of input*/ - - return 0; -} -#endif - -/* -static const unsigned HASH_NUM_VALUES = 65536; -static const unsigned HASH_NUM_CHARACTERS = 6; -static const unsigned HASH_SHIFT = 2; -Good and fast values: HASH_NUM_VALUES=65536, HASH_NUM_CHARACTERS=6, HASH_SHIFT=2 -making HASH_NUM_CHARACTERS larger (like 8), makes the file size larger but is a bit faster -making HASH_NUM_CHARACTERS smaller (like 3), makes the file size smaller but is slower -*/ - -#if !defined(USE_BRUTE_FORCE_ENCODING) -static unsigned getHash(const unsigned char* data, size_t size, size_t pos) -{ - unsigned result = 0; - size_t amount, i; - if(pos >= size) return 0; - amount = HASH_NUM_CHARACTERS; if(pos + amount >= size) amount = size - pos; - for(i = 0; i < amount; i++) result ^= (data[pos + i] << (i * HASH_SHIFT)); - return result % HASH_NUM_VALUES; -} - -/*LZ77-encode the data using a hash table technique to let it encode faster. Return value is error code*/ -static unsigned encodeLZ77(uivector* out, const unsigned char* in, size_t size, unsigned windowSize) -{ - /**generate hash table**/ - vector table; /*HASH_NUM_VALUES uivectors; this represents what would be an std::vector<std::vector<unsigned> > in C++*/ - uivector tablepos1, tablepos2; - unsigned pos, i, error = 0; - - vector_init(&table, sizeof(uivector)); - if(!vector_resize(&table, HASH_NUM_VALUES)) return 9917; - for(i = 0; i < HASH_NUM_VALUES; i++) - { - uivector* v = (uivector*)vector_get(&table, i); - uivector_init(v); - } - - /*remember start and end positions in the tables to searching in*/ - uivector_init(&tablepos1); - uivector_init(&tablepos2); - if(!uivector_resizev(&tablepos1, HASH_NUM_VALUES, 0)) error = 9918; - if(!uivector_resizev(&tablepos2, HASH_NUM_VALUES, 0)) error = 9919; - - if(!error) - { - for(pos = 0; pos < size; pos++) - { - unsigned length = 0, offset = 0; /*the length and offset found for the current position*/ - unsigned max_offset = pos < windowSize ? pos : windowSize; /*how far back to test*/ - unsigned tablepos; - - /*/search for the longest string*/ - /*first find out where in the table to start (the first value that is in the range from "pos - max_offset" to "pos")*/ - unsigned hash = getHash(in, size, pos); - if(!uivector_push_back((uivector*)vector_get(&table, hash), pos)) { error = 9920; break; } - - while(((uivector*)vector_get(&table, hash))->data[tablepos1.data[hash]] < pos - max_offset) tablepos1.data[hash]++; /*it now points to the first value in the table for which the index is larger than or equal to pos - max_offset*/ - while(((uivector*)vector_get(&table, hash))->data[tablepos2.data[hash]] < pos) tablepos2.data[hash]++; /*it now points to the first value in the table for which the index is larger than or equal to pos*/ - - for(tablepos = tablepos2.data[hash] - 1; tablepos >= tablepos1.data[hash] && tablepos < tablepos2.data[hash]; tablepos--) - { - unsigned backpos = ((uivector*)vector_get(&table, hash))->data[tablepos]; - unsigned current_offset = pos - backpos; - - /*test the next characters*/ - unsigned current_length = 0; - unsigned backtest = backpos; - unsigned foretest = pos; - while(foretest < size && in[backtest] == in[foretest] && current_length < MAX_SUPPORTED_DEFLATE_LENGTH) /*maximum support length by deflate is max length*/ - { - if(backpos >= pos) backpos -= current_offset; /*continue as if we work on the decoded bytes after pos by jumping back before pos*/ - current_length++; - backtest++; - foretest++; - } - if(current_length > length) - { - length = current_length; /*the longest length*/ - offset = current_offset; /*the offset that is related to this longest length*/ - if(current_length == MAX_SUPPORTED_DEFLATE_LENGTH) break; /*you can jump out of this for loop once a length of max length is found (gives significant speed gain)*/ - } - } - - /**encode it as length/distance pair or literal value**/ - if(length < 3) /*only lengths of 3 or higher are supported as length/distance pair*/ - { - if(!uivector_push_back(out, in[pos])) { error = 9921; break; } - } - else - { - unsigned j; - addLengthDistance(out, length, offset); - for(j = 0; j < length - 1; j++) - { - pos++; - if(!uivector_push_back((uivector*)vector_get(&table, getHash(in, size, pos)), pos)) { error = 9922; break; } - } - } - } /*end of the loop through each character of input*/ - } /*end of "if(!error)"*/ - - /*cleanup*/ - for(i = 0; i < table.size; i++) - { - uivector* v = (uivector*)vector_get(&table, i); - uivector_cleanup(v); - } - vector_cleanup(&table); - uivector_cleanup(&tablepos1); - uivector_cleanup(&tablepos2); - return error; -} -#endif - -/* /////////////////////////////////////////////////////////////////////////// */ - -static unsigned deflateNoCompression(ucvector* out, const unsigned char* data, size_t datasize) -{ - /*non compressed deflate block data: 1 bit BFINAL,2 bits BTYPE,(5 bits): it jumps to start of next byte, 2 bytes LEN, 2 bytes NLEN, LEN bytes literal DATA*/ - - size_t i, j, numdeflateblocks = datasize / 65536 + 1; - unsigned datapos = 0; - for(i = 0; i < numdeflateblocks; i++) - { - unsigned BFINAL, BTYPE, LEN, NLEN; - unsigned char firstbyte; - - BFINAL = (i == numdeflateblocks - 1); - BTYPE = 0; - - firstbyte = (unsigned char)(BFINAL + ((BTYPE & 1) << 1) + ((BTYPE & 2) << 1)); - ucvector_push_back(out, firstbyte); - - LEN = 65535; - if(datasize - datapos < 65535) LEN = (unsigned)datasize - datapos; - NLEN = 65535 - LEN; - - ucvector_push_back(out, (unsigned char)(LEN % 256)); - ucvector_push_back(out, (unsigned char)(LEN / 256)); - ucvector_push_back(out, (unsigned char)(NLEN % 256)); - ucvector_push_back(out, (unsigned char)(NLEN / 256)); - - /*Decompressed data*/ - for(j = 0; j < 65535 && datapos < datasize; j++) - { - ucvector_push_back(out, data[datapos++]); - } - } - - return 0; -} - -/*write the encoded data, using lit/len as well as distance codes*/ -static void writeLZ77data(size_t* bp, ucvector* out, const uivector* lz77_encoded, const HuffmanTree* codes, const HuffmanTree* codesD) -{ - size_t i = 0; - for(i = 0; i < lz77_encoded->size; i++) - { - unsigned val = lz77_encoded->data[i]; - addHuffmanSymbol(bp, out, HuffmanTree_getCode(codes, val), HuffmanTree_getLength(codes, val)); - if(val > 256) /*for a length code, 3 more things have to be added*/ - { - unsigned length_index = val - FIRST_LENGTH_CODE_INDEX; - unsigned n_length_extra_bits = LENGTHEXTRA[length_index]; - unsigned length_extra_bits = lz77_encoded->data[++i]; - - unsigned distance_code = lz77_encoded->data[++i]; - - unsigned distance_index = distance_code; - unsigned n_distance_extra_bits = DISTANCEEXTRA[distance_index]; - unsigned distance_extra_bits = lz77_encoded->data[++i]; - - addBitsToStream(bp, out, length_extra_bits, n_length_extra_bits); - addHuffmanSymbol(bp, out, HuffmanTree_getCode(codesD, distance_code), HuffmanTree_getLength(codesD, distance_code)); - addBitsToStream(bp, out, distance_extra_bits, n_distance_extra_bits); - } - } -} - -static unsigned deflateDynamic(ucvector* out, const unsigned char* data, size_t datasize, const LodeZlib_DeflateSettings* settings) -{ - /* - after the BFINAL and BTYPE, the dynamic block consists out of the following: - - 5 bits HLIT, 5 bits HDIST, 4 bits HCLEN - - (HCLEN+4)*3 bits code lengths of code length alphabet - - HLIT + 257 code lengths of lit/length alphabet (encoded using the code length alphabet, + possible repetition codes 16, 17, 18) - - HDIST + 1 code lengths of distance alphabet (encoded using the code length alphabet, + possible repetition codes 16, 17, 18) - - compressed data - - 256 (end code) - */ - - unsigned error = 0; - - uivector lz77_encoded; - HuffmanTree codes; /*tree for literal values and length codes*/ - HuffmanTree codesD; /*tree for distance codes*/ - HuffmanTree codelengthcodes; - uivector frequencies; - uivector frequenciesD; - uivector amounts; /*the amounts in the "normal" order*/ - uivector lldl; - uivector lldll; /*lit/len & dist code lengths*/ - uivector clcls; - - unsigned BFINAL = 1; /*make only one block... the first and final one*/ - size_t numcodes, numcodesD, i, bp = 0; /*the bit pointer*/ - unsigned HLIT, HDIST, HCLEN; - - uivector_init(&lz77_encoded); - HuffmanTree_init(&codes); - HuffmanTree_init(&codesD); - HuffmanTree_init(&codelengthcodes); - uivector_init(&frequencies); - uivector_init(&frequenciesD); - uivector_init(&amounts); - uivector_init(&lldl); - uivector_init(&lldll); - uivector_init(&clcls); - - while(!error) /*the goto-avoiding while construct: break out to go to the cleanup phase, a break at the end makes sure the while is never repeated*/ - { - if(settings->useLZ77) - { - error = encodeLZ77(&lz77_encoded, data, datasize, settings->windowSize); /*LZ77 encoded*/ - if(error) break; - } - else - { - if(!uivector_resize(&lz77_encoded, datasize)) { error = 9923; break; } - for(i = 0; i < datasize; i++) lz77_encoded.data[i] = data[i]; /*no LZ77, but still will be Huffman compressed*/ - } - - if(!uivector_resizev(&frequencies, 286, 0)) { error = 9924; break; } - if(!uivector_resizev(&frequenciesD, 30, 0)) { error = 9925; break; } - for(i = 0; i < lz77_encoded.size; i++) - { - unsigned symbol = lz77_encoded.data[i]; - frequencies.data[symbol]++; - if(symbol > 256) - { - unsigned dist = lz77_encoded.data[i + 2]; - frequenciesD.data[dist]++; - i += 3; - } - } - frequencies.data[256] = 1; /*there will be exactly 1 end code, at the end of the block*/ - - error = HuffmanTree_makeFromFrequencies(&codes, frequencies.data, frequencies.size, 15); - if(error) break; - error = HuffmanTree_makeFromFrequencies(&codesD, frequenciesD.data, frequenciesD.size, 15); - if(error) break; - - addBitToStream(&bp, out, BFINAL); - addBitToStream(&bp, out, 0); /*first bit of BTYPE "dynamic"*/ - addBitToStream(&bp, out, 1); /*second bit of BTYPE "dynamic"*/ - - numcodes = codes.numcodes; if(numcodes > 286) numcodes = 286; - numcodesD = codesD.numcodes; if(numcodesD > 30) numcodesD = 30; - for(i = 0; i < numcodes; i++) uivector_push_back(&lldll, HuffmanTree_getLength(&codes, (unsigned)i)); - for(i = 0; i < numcodesD; i++) uivector_push_back(&lldll, HuffmanTree_getLength(&codesD, (unsigned)i)); - - /*make lldl smaller by using repeat codes 16 (copy length 3-6 times), 17 (3-10 zeros), 18 (11-138 zeros)*/ - for(i = 0; i < (unsigned)lldll.size; i++) - { - unsigned j = 0; - while(i + j + 1 < (unsigned)lldll.size && lldll.data[i + j + 1] == lldll.data[i]) j++; - - if(lldll.data[i] == 0 && j >= 2) - { - j++; /*include the first zero*/ - if(j <= 10) { uivector_push_back(&lldl, 17); uivector_push_back(&lldl, j - 3); } - else - { - if(j > 138) j = 138; - uivector_push_back(&lldl, 18); uivector_push_back(&lldl, j - 11); - } - i += (j - 1); - } - else if(j >= 3) - { - size_t k; - unsigned num = j / 6, rest = j % 6; - uivector_push_back(&lldl, lldll.data[i]); - for(k = 0; k < num; k++) { uivector_push_back(&lldl, 16); uivector_push_back(&lldl, 6 - 3); } - if(rest >= 3) { uivector_push_back(&lldl, 16); uivector_push_back(&lldl, rest - 3); } - else j -= rest; - i += j; - } - else uivector_push_back(&lldl, lldll.data[i]); - } - - /*generate huffmantree for the length codes of lit/len and dist codes*/ - if(!uivector_resizev(&amounts, 19, 0)) { error = 9926; break; } /*16 possible lengths (0-15) and 3 repeat codes (16, 17 and 18)*/ - for(i = 0; i < lldl.size; i++) - { - amounts.data[lldl.data[i]]++; - if(lldl.data[i] >= 16) i++; /*after a repeat code come the bits that specify the amount, those don't need to be in the amounts calculation*/ - } - - error = HuffmanTree_makeFromFrequencies(&codelengthcodes, amounts.data, amounts.size, 7); - if(error) break; - - if(!uivector_resize(&clcls, 19)) { error = 9927; break; } - for(i = 0; i < 19; i++) clcls.data[i] = HuffmanTree_getLength(&codelengthcodes, CLCL[i]); /*lengths of code length tree is in the order as specified by deflate*/ - while(clcls.data[clcls.size - 1] == 0 && clcls.size > 4) - { - if(!uivector_resize(&clcls, clcls.size - 1)) { error = 9928; break; } /*remove zeros at the end, but minimum size must be 4*/ - } - if(error) break; - - /*write the HLIT, HDIST and HCLEN values*/ - HLIT = (unsigned)(numcodes - 257); - HDIST = (unsigned)(numcodesD - 1); - HCLEN = (unsigned)clcls.size - 4; - addBitsToStream(&bp, out, HLIT, 5); - addBitsToStream(&bp, out, HDIST, 5); - addBitsToStream(&bp, out, HCLEN, 4); - - /*write the code lengths of the code length alphabet*/ - for(i = 0; i < HCLEN + 4; i++) addBitsToStream(&bp, out, clcls.data[i], 3); - - /*write the lengths of the lit/len AND the dist alphabet*/ - for(i = 0; i < lldl.size; i++) - { - addHuffmanSymbol(&bp, out, HuffmanTree_getCode(&codelengthcodes, lldl.data[i]), HuffmanTree_getLength(&codelengthcodes, lldl.data[i])); - /*extra bits of repeat codes*/ - if(lldl.data[i] == 16) addBitsToStream(&bp, out, lldl.data[++i], 2); - else if(lldl.data[i] == 17) addBitsToStream(&bp, out, lldl.data[++i], 3); - else if(lldl.data[i] == 18) addBitsToStream(&bp, out, lldl.data[++i], 7); - } - - /*write the compressed data symbols*/ - writeLZ77data(&bp, out, &lz77_encoded, &codes, &codesD); - if(HuffmanTree_getLength(&codes, 256) == 0) { error = 64; break; } /*the length of the end code 256 must be larger than 0*/ - addHuffmanSymbol(&bp, out, HuffmanTree_getCode(&codes, 256), HuffmanTree_getLength(&codes, 256)); /*end code*/ - - break; /*end of error-while*/ - } - - /*cleanup*/ - uivector_cleanup(&lz77_encoded); - HuffmanTree_cleanup(&codes); - HuffmanTree_cleanup(&codesD); - HuffmanTree_cleanup(&codelengthcodes); - uivector_cleanup(&frequencies); - uivector_cleanup(&frequenciesD); - uivector_cleanup(&amounts); - uivector_cleanup(&lldl); - uivector_cleanup(&lldll); - uivector_cleanup(&clcls); - - return error; -} - -static unsigned deflateFixed(ucvector* out, const unsigned char* data, size_t datasize, const LodeZlib_DeflateSettings* settings) -{ - HuffmanTree codes; /*tree for literal values and length codes*/ - HuffmanTree codesD; /*tree for distance codes*/ - - unsigned BFINAL = 1; /*make only one block... the first and final one*/ - unsigned error = 0; - size_t i, bp = 0; /*the bit pointer*/ - - HuffmanTree_init(&codes); - HuffmanTree_init(&codesD); - - generateFixedTree(&codes); - generateDistanceTree(&codesD); - - addBitToStream(&bp, out, BFINAL); - addBitToStream(&bp, out, 1); /*first bit of BTYPE*/ - addBitToStream(&bp, out, 0); /*second bit of BTYPE*/ - - if(settings->useLZ77) /*LZ77 encoded*/ - { - uivector lz77_encoded; - uivector_init(&lz77_encoded); - error = encodeLZ77(&lz77_encoded, data, datasize, settings->windowSize); - if(!error) writeLZ77data(&bp, out, &lz77_encoded, &codes, &codesD); - uivector_cleanup(&lz77_encoded); - } - else /*no LZ77, but still will be Huffman compressed*/ - { - for(i = 0; i < datasize; i++) addHuffmanSymbol(&bp, out, HuffmanTree_getCode(&codes, data[i]), HuffmanTree_getLength(&codes, data[i])); - } - if(!error) addHuffmanSymbol(&bp, out, HuffmanTree_getCode(&codes, 256), HuffmanTree_getLength(&codes, 256)); /*"end" code*/ - - /*cleanup*/ - HuffmanTree_cleanup(&codes); - HuffmanTree_cleanup(&codesD); - - return error; -} - -unsigned LodeFlate_deflate(ucvector* out, const unsigned char* data, size_t datasize, const LodeZlib_DeflateSettings* settings) -{ - unsigned error = 0; - if(settings->btype == 0) error = deflateNoCompression(out, data, datasize); - else if(settings->btype == 1) error = deflateFixed(out, data, datasize, settings); - else if(settings->btype == 2) error = deflateDynamic(out, data, datasize, settings); - else error = 61; - return error; -} - - -/* ////////////////////////////////////////////////////////////////////////// */ -/* / Adler32 */ -/* ////////////////////////////////////////////////////////////////////////// */ - -static unsigned update_adler32(unsigned adler, const unsigned char* data, unsigned len) -{ - unsigned s1 = adler & 0xffff; - unsigned s2 = (adler >> 16) & 0xffff; - - while(len > 0) - { - /*at least 5550 sums can be done before the sums overflow, saving us from a lot of module divisions*/ - unsigned amount = len > 5550 ? 5550 : len; - len -= amount; - while(amount > 0) - { - s1 = (s1 + *data++); - s2 = (s2 + s1); - amount--; - } - s1 %= 65521; - s2 %= 65521; - } - - return (s2 << 16) | s1; -} - -/*Return the adler32 of the bytes data[0..len-1]*/ -static unsigned adler32(const unsigned char* data, unsigned len) -{ - return update_adler32(1L, data, len); -} - -/* ////////////////////////////////////////////////////////////////////////// */ -/* / Reading and writing single bits and bytes from/to stream for Zlib / */ -/* ////////////////////////////////////////////////////////////////////////// */ - -static void LodeZlib_add32bitInt(ucvector* buffer, unsigned value) -{ - ucvector_push_back(buffer, (unsigned char)((value >> 24) & 0xff)); - ucvector_push_back(buffer, (unsigned char)((value >> 16) & 0xff)); - ucvector_push_back(buffer, (unsigned char)((value >> 8) & 0xff)); - ucvector_push_back(buffer, (unsigned char)((value ) & 0xff)); -} - -/* ////////////////////////////////////////////////////////////////////////// */ -/* / Zlib / */ -/* ////////////////////////////////////////////////////////////////////////// */ - -static unsigned LodeZlib_compress(unsigned char** out, size_t* outsize, const unsigned char* in, size_t insize, const LodeZlib_DeflateSettings* settings) -{ - /*initially, *out must be NULL and outsize 0, if you just give some random *out that's pointing to a non allocated buffer, this'll crash*/ - ucvector deflatedata, outv; - size_t i; - unsigned error; - - unsigned ADLER32; - /*zlib data: 1 byte CMF (CM+CINFO), 1 byte FLG, deflate data, 4 byte ADLER32 checksum of the Decompressed data*/ - unsigned CMF = 120; /*0b01111000: CM 8, CINFO 7. With CINFO 7, any window size up to 32768 can be used.*/ - unsigned FLEVEL = 0; - unsigned FDICT = 0; - unsigned CMFFLG = 256 * CMF + FDICT * 32 + FLEVEL * 64; - unsigned FCHECK = 31 - CMFFLG % 31; - CMFFLG += FCHECK; - - ucvector_init_buffer(&outv, *out, *outsize); /*ucvector-controlled version of the output buffer, for dynamic array*/ - - ucvector_push_back(&outv, (unsigned char)(CMFFLG / 256)); - ucvector_push_back(&outv, (unsigned char)(CMFFLG % 256)); - - ucvector_init(&deflatedata); - error = LodeFlate_deflate(&deflatedata, in, insize, settings); - - if(!error) - { - ADLER32 = adler32(in, (unsigned)insize); - for(i = 0; i < deflatedata.size; i++) ucvector_push_back(&outv, deflatedata.data[i]); - ucvector_cleanup(&deflatedata); - LodeZlib_add32bitInt(&outv, ADLER32); - } - - *out = outv.data; - *outsize = outv.size; - - return error; -} - -/* ////////////////////////////////////////////////////////////////////////// */ - -void LodeZlib_DeflateSettings_init(LodeZlib_DeflateSettings* settings) -{ - settings->btype = 2; /*compress with dynamic huffman tree (not in the mathematical sense, just not the predefined one)*/ - settings->useLZ77 = 1; - settings->windowSize = 2048; /*this is a good tradeoff between speed and compression ratio*/ -} - -/* ////////////////////////////////////////////////////////////////////////// */ -/* ////////////////////////////////////////////////////////////////////////// */ -/* ////////////////////////////////////////////////////////////////////////// */ -/* ////////////////////////////////////////////////////////////////////////// */ -/* ////////////////////////////////////////////////////////////////////////// */ -/* // End of Zlib related code, now comes the PNG related code that uses it// */ -/* ////////////////////////////////////////////////////////////////////////// */ -/* ////////////////////////////////////////////////////////////////////////// */ -/* ////////////////////////////////////////////////////////////////////////// */ -/* ////////////////////////////////////////////////////////////////////////// */ -/* ////////////////////////////////////////////////////////////////////////// */ - -/* -The two functions below (LodePNG_decompress and LodePNG_compress) directly call the -LodeZlib_decompress and LodeZlib_compress functions. The only purpose of the functions -below, is to provide the ability to let LodePNG use a different Zlib encoder by only -changing the two functions below, instead of changing it inside the various places -in the other LodePNG functions. - -*out must be NULL and *outsize must be 0 initially, and after the function is done, -*out must point to the decompressed data, *outsize must be the size of it, and must -be the size of the useful data in bytes, not the alloc size. -*/ - -static unsigned LodePNG_compress(unsigned char** out, size_t* outsize, const unsigned char* in, size_t insize, const LodeZlib_DeflateSettings* settings) -{ - return LodeZlib_compress(out, outsize, in, insize, settings); -} - -/* ////////////////////////////////////////////////////////////////////////// */ -/* / CRC32 / */ -/* ////////////////////////////////////////////////////////////////////////// */ - -static unsigned Crc32_crc_table_computed = 0; -static unsigned Crc32_crc_table[256]; - -/*Make the table for a fast CRC.*/ -static void Crc32_make_crc_table(void) -{ - unsigned int c, k, n; - for(n = 0; n < 256; n++) - { - c = n; - for(k = 0; k < 8; k++) - { - if(c & 1) c = (unsigned int)(0xedb88320L ^ (c >> 1)); - else c = c >> 1; - } - Crc32_crc_table[n] = c; - } - Crc32_crc_table_computed = 1; -} - -/*Update a running CRC with the bytes buf[0..len-1]--the CRC should be -initialized to all 1's, and the transmitted value is the 1's complement of the -final running CRC (see the crc() routine below).*/ -static unsigned Crc32_update_crc(const unsigned char* buf, unsigned int crc, size_t len) -{ - unsigned int c = crc; - size_t n; - - if(!Crc32_crc_table_computed) Crc32_make_crc_table(); - for(n = 0; n < len; n++) - { - c = Crc32_crc_table[(c ^ buf[n]) & 0xff] ^ (c >> 8); - } - return c; -} - -/*Return the CRC of the bytes buf[0..len-1].*/ -static unsigned Crc32_crc(const unsigned char* buf, size_t len) -{ - return Crc32_update_crc(buf, 0xffffffffu, len) ^ 0xffffffffu; -} - -/* ////////////////////////////////////////////////////////////////////////// */ -/* / Reading and writing single bits and bytes from/to stream for LodePNG / */ -/* ////////////////////////////////////////////////////////////////////////// */ - -static unsigned char readBitFromReversedStream(size_t* bitpointer, const unsigned char* bitstream) -{ - unsigned char result = (unsigned char)((bitstream[(*bitpointer) >> 3] >> (7 - ((*bitpointer) & 0x7))) & 1); - (*bitpointer)++; - return result; -} - -static unsigned readBitsFromReversedStream(size_t* bitpointer, const unsigned char* bitstream, size_t nbits) -{ - unsigned result = 0; - size_t i; - for(i = nbits - 1; i < nbits; i--) result += (unsigned)readBitFromReversedStream(bitpointer, bitstream) << i; - return result; -} - -static void setBitOfReversedStream(size_t* bitpointer, unsigned char* bitstream, unsigned char bit) -{ - /*the current bit in bitstream may be 0 or 1 for this to work*/ - if(bit == 0) bitstream[(*bitpointer) >> 3] &= (unsigned char)(~(1 << (7 - ((*bitpointer) & 0x7)))); - else bitstream[(*bitpointer) >> 3] |= (1 << (7 - ((*bitpointer) & 0x7))); - (*bitpointer)++; -} - -static unsigned LodePNG_read32bitInt(const unsigned char* buffer) -{ - return (buffer[0] << 24) | (buffer[1] << 16) | (buffer[2] << 8) | buffer[3]; -} - -static void LodePNG_set32bitInt(unsigned char* buffer, unsigned value) /*buffer must have at least 4 allocated bytes available*/ -{ - buffer[0] = (unsigned char)((value >> 24) & 0xff); - buffer[1] = (unsigned char)((value >> 16) & 0xff); - buffer[2] = (unsigned char)((value >> 8) & 0xff); - buffer[3] = (unsigned char)((value ) & 0xff); -} - -static void LodePNG_add32bitInt(ucvector* buffer, unsigned value) -{ - ucvector_resize(buffer, buffer->size + 4); - LodePNG_set32bitInt(&buffer->data[buffer->size - 4], value); -} - -/* ////////////////////////////////////////////////////////////////////////// */ -/* / PNG chunks / */ -/* ////////////////////////////////////////////////////////////////////////// */ - -static unsigned LodePNG_chunk_length(const unsigned char* chunk) /*get the length of the data of the chunk. Total chunk length has 12 bytes more.*/ -{ - return LodePNG_read32bitInt(&chunk[0]); -} - -static void LodePNG_chunk_generate_crc(unsigned char* chunk) /*generates the correct CRC from the data and puts it in the last 4 bytes of the chunk*/ -{ - unsigned length = LodePNG_chunk_length(chunk); - unsigned CRC = Crc32_crc(&chunk[4], length + 4); - LodePNG_set32bitInt(chunk + 8 + length, CRC); -} - -static unsigned LodePNG_create_chunk(unsigned char** out, size_t* outlength, unsigned length, const char* type, const unsigned char* data) /*appends new chunk to out. Returns error code; may change memory address of out buffer*/ -{ - unsigned i; - unsigned char *chunk, *new_buffer; - size_t new_length = (*outlength) + length + 12; - if(new_length < length + 12 || new_length < (*outlength)) return 77; /*integer overflow happened*/ - new_buffer = (unsigned char*)realloc(*out, new_length); - if(!new_buffer) return 9930; - (*out) = new_buffer; - (*outlength) = new_length; - chunk = &(*out)[(*outlength) - length - 12]; - - /*1: length*/ - LodePNG_set32bitInt(chunk, (unsigned)length); - - /*2: chunk name (4 letters)*/ - chunk[4] = type[0]; - chunk[5] = type[1]; - chunk[6] = type[2]; - chunk[7] = type[3]; - - /*3: the data*/ - for(i = 0; i < length; i++) chunk[8 + i] = data[i]; - - /*4: CRC (of the chunkname characters and the data)*/ - LodePNG_chunk_generate_crc(chunk); - - return 0; -} - -/* ////////////////////////////////////////////////////////////////////////// */ -/* / Color types and such / */ -/* ////////////////////////////////////////////////////////////////////////// */ - -/*return type is a LodePNG error code*/ -static unsigned checkColorValidity(unsigned colorType, unsigned bd) /*bd = bitDepth*/ -{ - switch(colorType) - { - case 0: if(!(bd == 1 || bd == 2 || bd == 4 || bd == 8 || bd == 16)) return 37; break; /*grey*/ - case 2: if(!( bd == 8 || bd == 16)) return 37; break; /*RGB*/ - case 3: if(!(bd == 1 || bd == 2 || bd == 4 || bd == 8 )) return 37; break; /*palette*/ - case 4: if(!( bd == 8 || bd == 16)) return 37; break; /*grey + alpha*/ - case 6: if(!( bd == 8 || bd == 16)) return 37; break; /*RGBA*/ - default: return 31; - } - return 0; /*allowed color type / bits combination*/ -} - -static unsigned getNumColorChannels(unsigned colorType) -{ - switch(colorType) - { - case 0: return 1; /*grey*/ - case 2: return 3; /*RGB*/ - case 3: return 1; /*palette*/ - case 4: return 2; /*grey + alpha*/ - case 6: return 4; /*RGBA*/ - } - return 0; /*unexisting color type*/ -} - -static unsigned getBpp(unsigned colorType, unsigned bitDepth) -{ - return getNumColorChannels(colorType) * bitDepth; /*bits per pixel is amount of channels * bits per channel*/ -} - -/* ////////////////////////////////////////////////////////////////////////// */ - -static void LodePNG_InfoColor_init(LodePNG_InfoColor* info) -{ - info->key_defined = 0; - info->key_r = info->key_g = info->key_b = 0; - info->colorType = 6; - info->bitDepth = 8; - info->palette = 0; - info->palettesize = 0; -} - -static void LodePNG_InfoColor_cleanup(LodePNG_InfoColor* info) -{ - LodePNG_InfoColor_clearPalette(info); -} - -static void LodePNG_InfoColor_clearPalette(LodePNG_InfoColor* info) -{ - if(info->palette) free(info->palette); - info->palettesize = 0; -} - -unsigned LodePNG_InfoColor_addPalette(LodePNG_InfoColor* info, unsigned char r, unsigned char g, unsigned char b, unsigned char a) -{ - unsigned char* data; - /*the same resize technique as C++ std::vectors is used, and here it's made so that for a palette with the max of 256 colors, it'll have the exact alloc size*/ - if(!(info->palettesize & (info->palettesize - 1))) /*if palettesize is 0 or a power of two*/ - { - /*allocated data must be at least 4* palettesize (for 4 color bytes)*/ - size_t alloc_size = info->palettesize == 0 ? 4 : info->palettesize * 4 * 2; - data = (unsigned char*)realloc(info->palette, alloc_size); - if(!data) return 9931; - else info->palette = data; - } - info->palette[4 * info->palettesize + 0] = r; - info->palette[4 * info->palettesize + 1] = g; - info->palette[4 * info->palettesize + 2] = b; - info->palette[4 * info->palettesize + 3] = a; - info->palettesize++; - return 0; -} - -static unsigned LodePNG_InfoColor_getBpp(const LodePNG_InfoColor* info) { return getBpp(info->colorType, info->bitDepth); } /*calculate bits per pixel out of colorType and bitDepth*/ -static unsigned LodePNG_InfoColor_isGreyscaleType(const LodePNG_InfoColor* info) { return info->colorType == 0 || info->colorType == 4; } -static unsigned LodePNG_InfoColor_isAlphaType(const LodePNG_InfoColor* info) { return (info->colorType & 4) != 0; } - -static unsigned LodePNG_InfoColor_equal(const LodePNG_InfoColor* info1, const LodePNG_InfoColor* info2) -{ - return info1->colorType == info2->colorType - && info1->bitDepth == info2->bitDepth; /*palette and color key not compared*/ -} - - -static void LodePNG_InfoPng_init(LodePNG_InfoPng* info) -{ - info->width = info->height = 0; - LodePNG_InfoColor_init(&info->color); - info->interlaceMethod = 0; - info->compressionMethod = 0; - info->filterMethod = 0; -} - -static void LodePNG_InfoPng_cleanup(LodePNG_InfoPng* info) -{ - LodePNG_InfoColor_cleanup(&info->color); -} - -static unsigned LodePNG_InfoPng_copy(LodePNG_InfoPng* dest, const LodePNG_InfoPng* source) -{ - unsigned error = 0; - LodePNG_InfoPng_cleanup(dest); - *dest = *source; - LodePNG_InfoColor_init(&dest->color); - error = LodePNG_InfoColor_copy(&dest->color, &source->color); if(error) return error; - return error; -} - -static unsigned LodePNG_InfoColor_copy(LodePNG_InfoColor* dest, const LodePNG_InfoColor* source) -{ - size_t i; - LodePNG_InfoColor_cleanup(dest); - *dest = *source; - dest->palette = (unsigned char*)malloc(source->palettesize * 4); - if(!dest->palette && source->palettesize) return 9935; - for(i = 0; i < source->palettesize * 4; i++) dest->palette[i] = source->palette[i]; - return 0; -} - -static void LodePNG_InfoRaw_init(LodePNG_InfoRaw* info) -{ - LodePNG_InfoColor_init(&info->color); -} - -static void LodePNG_InfoRaw_cleanup(LodePNG_InfoRaw* info) -{ - LodePNG_InfoColor_cleanup(&info->color); -} - -static unsigned LodePNG_InfoRaw_copy(LodePNG_InfoRaw* dest, const LodePNG_InfoRaw* source) -{ - unsigned error = 0; - LodePNG_InfoRaw_cleanup(dest); - *dest = *source; - LodePNG_InfoColor_init(&dest->color); - error = LodePNG_InfoColor_copy(&dest->color, &source->color); - return error; -} - -/* ////////////////////////////////////////////////////////////////////////// */ - -/* -converts from any color type to 24-bit or 32-bit (later maybe more supported). return value = LodePNG error code -the out buffer must have (w * h * bpp + 7) / 8 bytes, where bpp is the bits per pixel of the output color type (LodePNG_InfoColor_getBpp) -for < 8 bpp images, there may _not_ be padding bits at the end of scanlines. -*/ -static unsigned LodePNG_convert(unsigned char* out, const unsigned char* in, LodePNG_InfoColor* infoOut, LodePNG_InfoColor* infoIn, unsigned w, unsigned h) -{ - const size_t numpixels = w * h; /*amount of pixels*/ - const unsigned OUT_BYTES = LodePNG_InfoColor_getBpp(infoOut) / 8; /*bytes per pixel in the output image*/ - const unsigned OUT_ALPHA = LodePNG_InfoColor_isAlphaType(infoOut); /*use 8-bit alpha channel*/ - size_t i, c, bp = 0; /*bitpointer, used by less-than-8-bit color types*/ - - /*cases where in and out already have the same format*/ - if(LodePNG_InfoColor_equal(infoIn, infoOut)) - { - size_t i, size = (w * h * LodePNG_InfoColor_getBpp(infoIn) + 7) / 8; - for(i = 0; i < size; i++) out[i] = in[i]; - return 0; - } - - if((infoOut->colorType == 2 || infoOut->colorType == 6) && infoOut->bitDepth == 8) - { - if(infoIn->bitDepth == 8) - { - switch(infoIn->colorType) - { - case 0: /*greyscale color*/ - for(i = 0; i < numpixels; i++) - { - if(OUT_ALPHA) out[OUT_BYTES * i + 3] = 255; - out[OUT_BYTES * i + 0] = out[OUT_BYTES * i + 1] = out[OUT_BYTES * i + 2] = in[i]; - if(OUT_ALPHA && infoIn->key_defined && in[i] == infoIn->key_r) out[OUT_BYTES * i + 3] = 0; - } - break; - case 2: /*RGB color*/ - for(i = 0; i < numpixels; i++) - { - if(OUT_ALPHA) out[OUT_BYTES * i + 3] = 255; - for(c = 0; c < 3; c++) out[OUT_BYTES * i + c] = in[3 * i + c]; - if(OUT_ALPHA && infoIn->key_defined == 1 && in[3 * i + 0] == infoIn->key_r && in[3 * i + 1] == infoIn->key_g && in[3 * i + 2] == infoIn->key_b) out[OUT_BYTES * i + 3] = 0; - } - break; - case 3: /*indexed color (palette)*/ - for(i = 0; i < numpixels; i++) - { - if(OUT_ALPHA) out[OUT_BYTES * i + 3] = 255; - if(in[i] >= infoIn->palettesize) return 46; - for(c = 0; c < OUT_BYTES; c++) out[OUT_BYTES * i + c] = infoIn->palette[4 * in[i] + c]; /*get rgb colors from the palette*/ - } - break; - case 4: /*greyscale with alpha*/ - for(i = 0; i < numpixels; i++) - { - out[OUT_BYTES * i + 0] = out[OUT_BYTES * i + 1] = out[OUT_BYTES * i + 2] = in[2 * i + 0]; - if(OUT_ALPHA) out[OUT_BYTES * i + 3] = in[2 * i + 1]; - } - break; - case 6: /*RGB with alpha*/ - for(i = 0; i < numpixels; i++) - { - for(c = 0; c < OUT_BYTES; c++) out[OUT_BYTES * i + c] = in[4 * i + c]; - } - break; - default: break; - } - } - else if(infoIn->bitDepth == 16) - { - switch(infoIn->colorType) - { - case 0: /*greyscale color*/ - for(i = 0; i < numpixels; i++) - { - if(OUT_ALPHA) out[OUT_BYTES * i + 3] = 255; - out[OUT_BYTES * i + 0] = out[OUT_BYTES * i + 1] = out[OUT_BYTES * i + 2] = in[2 * i]; - if(OUT_ALPHA && infoIn->key_defined && 256U * in[i] + in[i + 1] == infoIn->key_r) out[OUT_BYTES * i + 3] = 0; - } - break; - case 2: /*RGB color*/ - for(i = 0; i < numpixels; i++) - { - if(OUT_ALPHA) out[OUT_BYTES * i + 3] = 255; - for(c = 0; c < 3; c++) out[OUT_BYTES * i + c] = in[6 * i + 2 * c]; - if(OUT_ALPHA && infoIn->key_defined && 256U * in[6 * i + 0] + in[6 * i + 1] == infoIn->key_r && 256U * in[6 * i + 2] + in[6 * i + 3] == infoIn->key_g && 256U * in[6 * i + 4] + in[6 * i + 5] == infoIn->key_b) out[OUT_BYTES * i + 3] = 0; - } - break; - case 4: /*greyscale with alpha*/ - for(i = 0; i < numpixels; i++) - { - out[OUT_BYTES * i + 0] = out[OUT_BYTES * i + 1] = out[OUT_BYTES * i + 2] = in[4 * i]; /*most significant byte*/ - if(OUT_ALPHA) out[OUT_BYTES * i + 3] = in[4 * i + 2]; - } - break; - case 6: /*RGB with alpha*/ - for(i = 0; i < numpixels; i++) - { - for(c = 0; c < OUT_BYTES; c++) out[OUT_BYTES * i + c] = in[8 * i + 2 * c]; - } - break; - default: break; - } - } - else /*infoIn->bitDepth is less than 8 bit per channel*/ - { - switch(infoIn->colorType) - { - case 0: /*greyscale color*/ - for(i = 0; i < numpixels; i++) - { - unsigned value = readBitsFromReversedStream(&bp, in, infoIn->bitDepth); - if(OUT_ALPHA) out[OUT_BYTES * i + 3] = 255; - if(OUT_ALPHA && infoIn->key_defined && value && ((1U << infoIn->bitDepth) - 1U) == infoIn->key_r && ((1U << infoIn->bitDepth) - 1U)) out[OUT_BYTES * i + 3] = 0; - value = (value * 255) / ((1 << infoIn->bitDepth) - 1); /*scale value from 0 to 255*/ - out[OUT_BYTES * i + 0] = out[OUT_BYTES * i + 1] = out[OUT_BYTES * i + 2] = (unsigned char)(value); - } - break; - case 3: /*indexed color (palette)*/ - for(i = 0; i < numpixels; i++) - { - unsigned value = readBitsFromReversedStream(&bp, in, infoIn->bitDepth); - if(OUT_ALPHA) out[OUT_BYTES * i + 3] = 255; - if(value >= infoIn->palettesize) return 47; - for(c = 0; c < OUT_BYTES; c++) out[OUT_BYTES * i + c] = infoIn->palette[4 * value + c]; /*get rgb colors from the palette*/ - } - break; - default: break; - } - } - } - else if(LodePNG_InfoColor_isGreyscaleType(infoOut) && infoOut->bitDepth == 8) /*conversion from greyscale to greyscale*/ - { - if(!LodePNG_InfoColor_isGreyscaleType(infoIn)) return 62; - if(infoIn->bitDepth == 8) - { - switch(infoIn->colorType) - { - case 0: /*greyscale color*/ - for(i = 0; i < numpixels; i++) - { - if(OUT_ALPHA) out[OUT_BYTES * i + 1] = 255; - out[OUT_BYTES * i] = in[i]; - if(OUT_ALPHA && infoIn->key_defined && in[i] == infoIn->key_r) out[OUT_BYTES * i + 1] = 0; - } - break; - case 4: /*greyscale with alpha*/ - for(i = 0; i < numpixels; i++) - { - out[OUT_BYTES * i + 0] = in[2 * i + 0]; - if(OUT_ALPHA) out[OUT_BYTES * i + 1] = in[2 * i + 1]; - } - break; - default: return 31; - } - } - else if(infoIn->bitDepth == 16) - { - switch(infoIn->colorType) - { - case 0: /*greyscale color*/ - for(i = 0; i < numpixels; i++) - { - if(OUT_ALPHA) out[OUT_BYTES * i + 1] = 255; - out[OUT_BYTES * i] = in[2 * i]; - if(OUT_ALPHA && infoIn->key_defined && 256U * in[i] + in[i + 1] == infoIn->key_r) out[OUT_BYTES * i + 1] = 0; - } - break; - case 4: /*greyscale with alpha*/ - for(i = 0; i < numpixels; i++) - { - out[OUT_BYTES * i] = in[4 * i]; /*most significant byte*/ - if(OUT_ALPHA) out[OUT_BYTES * i + 1] = in[4 * i + 2]; /*most significant byte*/ - } - break; - default: return 31; - } - } - else /*infoIn->bitDepth is less than 8 bit per channel*/ - { - if(infoIn->colorType != 0) return 31; /*colorType 0 is the only greyscale type with < 8 bits per channel*/ - for(i = 0; i < numpixels; i++) - { - unsigned value = readBitsFromReversedStream(&bp, in, infoIn->bitDepth); - if(OUT_ALPHA) out[OUT_BYTES * i + 1] = 255; - if(OUT_ALPHA && infoIn->key_defined && value && ((1U << infoIn->bitDepth) - 1U) == infoIn->key_r && ((1U << infoIn->bitDepth) - 1U)) out[OUT_BYTES * i + 1] = 0; - value = (value * 255) / ((1 << infoIn->bitDepth) - 1); /*scale value from 0 to 255*/ - out[OUT_BYTES * i] = (unsigned char)(value); - } - } - } - else return 59; - - return 0; -} - -/*Path predictor, used by PNG filter type 4*/ -static int paethPredictor(int a, int b, int c) -{ - int p = a + b - c; - int pa = p > a ? p - a : a - p; - int pb = p > b ? p - b : b - p; - int pc = p > c ? p - c : c - p; - - if(pa <= pb && pa <= pc) return a; - else if(pb <= pc) return b; - else return c; -} - -/*shared values used by multiple Adam7 related functions*/ - -static const unsigned ADAM7_IX[7] = { 0, 4, 0, 2, 0, 1, 0 }; /*x start values*/ -static const unsigned ADAM7_IY[7] = { 0, 0, 4, 0, 2, 0, 1 }; /*y start values*/ -static const unsigned ADAM7_DX[7] = { 8, 8, 4, 4, 2, 2, 1 }; /*x delta values*/ -static const unsigned ADAM7_DY[7] = { 8, 8, 8, 4, 4, 2, 2 }; /*y delta values*/ - -static void Adam7_getpassvalues(unsigned passw[7], unsigned passh[7], size_t filter_passstart[8], size_t padded_passstart[8], size_t passstart[8], unsigned w, unsigned h, unsigned bpp) -{ - /*the passstart values have 8 values: the 8th one actually indicates the byte after the end of the 7th (= last) pass*/ - unsigned i; - - /*calculate width and height in pixels of each pass*/ - for(i = 0; i < 7; i++) - { - passw[i] = (w + ADAM7_DX[i] - ADAM7_IX[i] - 1) / ADAM7_DX[i]; - passh[i] = (h + ADAM7_DY[i] - ADAM7_IY[i] - 1) / ADAM7_DY[i]; - if(passw[i] == 0) passh[i] = 0; - if(passh[i] == 0) passw[i] = 0; - } - - filter_passstart[0] = padded_passstart[0] = passstart[0] = 0; - for(i = 0; i < 7; i++) - { - filter_passstart[i + 1] = filter_passstart[i] + ((passw[i] && passh[i]) ? passh[i] * (1 + (passw[i] * bpp + 7) / 8) : 0); /*if passw[i] is 0, it's 0 bytes, not 1 (no filtertype-byte)*/ - padded_passstart[i + 1] = padded_passstart[i] + passh[i] * ((passw[i] * bpp + 7) / 8); /*bits padded if needed to fill full byte at end of each scanline*/ - passstart[i + 1] = passstart[i] + (passh[i] * passw[i] * bpp + 7) / 8; /*only padded at end of reduced image*/ - } -} - - -/* ////////////////////////////////////////////////////////////////////////// */ -/* / PNG Encoder / */ -/* ////////////////////////////////////////////////////////////////////////// */ - -/*chunkName must be string of 4 characters*/ -static unsigned addChunk(ucvector* out, const char* chunkName, const unsigned char* data, size_t length) -{ - unsigned error = LodePNG_create_chunk(&out->data, &out->size, (unsigned)length, chunkName, data); - if(error) return error; - out->allocsize = out->size; /*fix the allocsize again*/ - return 0; -} - -static void writeSignature(ucvector* out) -{ - /*8 bytes PNG signature*/ - ucvector_push_back(out, 137); - ucvector_push_back(out, 80); - ucvector_push_back(out, 78); - ucvector_push_back(out, 71); - ucvector_push_back(out, 13); - ucvector_push_back(out, 10); - ucvector_push_back(out, 26); - ucvector_push_back(out, 10); -} - -static unsigned addChunk_IHDR(ucvector* out, unsigned w, unsigned h, unsigned bitDepth, unsigned colorType, unsigned interlaceMethod) -{ - unsigned error = 0; - ucvector header; - ucvector_init(&header); - - LodePNG_add32bitInt(&header, w); /*width*/ - LodePNG_add32bitInt(&header, h); /*height*/ - ucvector_push_back(&header, (unsigned char)bitDepth); /*bit depth*/ - ucvector_push_back(&header, (unsigned char)colorType); /*color type*/ - ucvector_push_back(&header, 0); /*compression method*/ - ucvector_push_back(&header, 0); /*filter method*/ - ucvector_push_back(&header, interlaceMethod); /*interlace method*/ - - error = addChunk(out, "IHDR", header.data, header.size); - ucvector_cleanup(&header); - - return error; -} - -static unsigned addChunk_PLTE(ucvector* out, const LodePNG_InfoColor* info) -{ - unsigned error = 0; - size_t i; - ucvector PLTE; - ucvector_init(&PLTE); - for(i = 0; i < info->palettesize * 4; i++) if(i % 4 != 3) ucvector_push_back(&PLTE, info->palette[i]); /*add all channels except alpha channel*/ - error = addChunk(out, "PLTE", PLTE.data, PLTE.size); - ucvector_cleanup(&PLTE); - - return error; -} - -static unsigned addChunk_tRNS(ucvector* out, const LodePNG_InfoColor* info) -{ - unsigned error = 0; - size_t i; - ucvector tRNS; - ucvector_init(&tRNS); - if(info->colorType == 3) - { - for(i = 0; i < info->palettesize; i++) ucvector_push_back(&tRNS, info->palette[4 * i + 3]); /*add only alpha channel*/ - } - else if(info->colorType == 0) - { - if(info->key_defined) - { - ucvector_push_back(&tRNS, (unsigned char)(info->key_r / 256)); - ucvector_push_back(&tRNS, (unsigned char)(info->key_r % 256)); - } - } - else if(info->colorType == 2) - { - if(info->key_defined) - { - ucvector_push_back(&tRNS, (unsigned char)(info->key_r / 256)); - ucvector_push_back(&tRNS, (unsigned char)(info->key_r % 256)); - ucvector_push_back(&tRNS, (unsigned char)(info->key_g / 256)); - ucvector_push_back(&tRNS, (unsigned char)(info->key_g % 256)); - ucvector_push_back(&tRNS, (unsigned char)(info->key_b / 256)); - ucvector_push_back(&tRNS, (unsigned char)(info->key_b % 256)); - } - } - - error = addChunk(out, "tRNS", tRNS.data, tRNS.size); - ucvector_cleanup(&tRNS); - - return error; -} - -static unsigned addChunk_IDAT(ucvector* out, const unsigned char* data, size_t datasize, LodeZlib_DeflateSettings* zlibsettings) -{ - ucvector zlibdata; - unsigned error = 0; - - /*compress with the Zlib compressor*/ - ucvector_init(&zlibdata); - error = LodePNG_compress(&zlibdata.data, &zlibdata.size, data, datasize, zlibsettings); - if(!error) error = addChunk(out, "IDAT", zlibdata.data, zlibdata.size); - ucvector_cleanup(&zlibdata); - - return error; -} - -static unsigned addChunk_IEND(ucvector* out) -{ - unsigned error = 0; - error = addChunk(out, "IEND", 0, 0); - return error; -} - -static void filterScanline(unsigned char* out, const unsigned char* scanline, const unsigned char* prevline, size_t length, size_t bytewidth, unsigned char filterType) -{ - size_t i; - switch(filterType) - { - case 0: - for(i = 0; i < length; i++) out[i] = scanline[i]; - break; - case 1: - for(i = 0; i < bytewidth; i++) out[i] = scanline[i]; - for(i = bytewidth; i < length; i++) out[i] = scanline[i] - scanline[i - bytewidth]; - break; - case 2: - if(prevline) for(i = 0; i < length; i++) out[i] = scanline[i] - prevline[i]; - else for(i = 0; i < length; i++) out[i] = scanline[i]; - break; - case 3: - if(prevline) - { - for(i = 0; i < bytewidth; i++) out[i] = scanline[i] - prevline[i] / 2; - for(i = bytewidth; i < length; i++) out[i] = scanline[i] - ((scanline[i - bytewidth] + prevline[i]) / 2); - } - else - { - for(i = 0; i < length; i++) out[i] = scanline[i]; - for(i = bytewidth; i < length; i++) out[i] = scanline[i] - scanline[i - bytewidth] / 2; - } - break; - case 4: - if(prevline) - { - for(i = 0; i < bytewidth; i++) out[i] = (unsigned char)(scanline[i] - paethPredictor(0, prevline[i], 0)); - for(i = bytewidth; i < length; i++) out[i] = (unsigned char)(scanline[i] - paethPredictor(scanline[i - bytewidth], prevline[i], prevline[i - bytewidth])); - } - else - { - for(i = 0; i < bytewidth; i++) out[i] = scanline[i]; - for(i = bytewidth; i < length; i++) out[i] = (unsigned char)(scanline[i] - paethPredictor(scanline[i - bytewidth], 0, 0)); - } - break; - default: return; /*unexisting filter type given*/ - } -} - -static unsigned filter(unsigned char* out, const unsigned char* in, unsigned w, unsigned h, const LodePNG_InfoColor* info) -{ - /* - For PNG filter method 0 - out must be a buffer with as size: h + (w * h * bpp + 7) / 8, because there are the scanlines with 1 extra byte per scanline - - There is a nice heuristic described here: http://www.cs.toronto.edu/~cosmin/pngtech/optipng.html. It says: - * If the image type is Palette, or the bit depth is smaller than 8, then do not filter the image (i.e. use fixed filtering, with the filter None). - * (The other case) If the image type is Grayscale or RGB (with or without Alpha), and the bit depth is not smaller than 8, then use adaptive filtering heuristic as follows: independently for each row, apply all five filters and select the filter that produces the smallest sum of absolute values per row. - - Here the above method is used mostly. Note though that it appears to be better to use the adaptive filtering on the plasma 8-bit palette example, but that image isn't the best reference for palette images in general. - */ - - unsigned bpp = LodePNG_InfoColor_getBpp(info); - size_t linebytes = (w * bpp + 7) / 8; /*the width of a scanline in bytes, not including the filter type*/ - size_t bytewidth = (bpp + 7) / 8; /*bytewidth is used for filtering, is 1 when bpp < 8, number of bytes per pixel otherwise*/ - const unsigned char* prevline = 0; - unsigned x, y; - unsigned heuristic; - unsigned error = 0; - - if(bpp == 0) return 31; /*invalid color type*/ - - /*choose heuristic as described above*/ - if(info->colorType == 3 || info->bitDepth < 8) heuristic = 0; - else heuristic = 1; - - if(heuristic == 0) /*None filtertype for everything*/ - { - for(y = 0; y < h; y++) - { - size_t outindex = (1 + linebytes) * y; /*the extra filterbyte added to each row*/ - size_t inindex = linebytes * y; - const unsigned TYPE = 0; - out[outindex] = TYPE; /*filter type byte*/ - filterScanline(&out[outindex + 1], &in[inindex], prevline, linebytes, bytewidth, TYPE); - prevline = &in[inindex]; - } - } - else if(heuristic == 1) /*adaptive filtering*/ - { - size_t sum[5]; - ucvector attempt[5]; /*five filtering attempts, one for each filter type*/ - size_t smallest = 0; - unsigned type, bestType = 0; - - for(type = 0; type < 5; type++) ucvector_init(&attempt[type]); - for(type = 0; type < 5; type++) - { - if(!ucvector_resize(&attempt[type], linebytes)) { error = 9949; break; } - } - - if(!error) - { - for(y = 0; y < h; y++) - { - /*try the 5 filter types*/ - for(type = 0; type < 5; type++) - { - filterScanline(attempt[type].data, &in[y * linebytes], prevline, linebytes, bytewidth, type); - - /*calculate the sum of the result*/ - sum[type] = 0; - for(x = 0; x < attempt[type].size; x+=3) sum[type] += attempt[type].data[x]; /*note that not all pixels are checked to speed this up while still having probably the best choice*/ - - /*check if this is smallest sum (or if type == 0 it's the first case so always store the values)*/ - if(type == 0 || sum[type] < smallest) - { - bestType = type; - smallest = sum[type]; - } - } - - prevline = &in[y * linebytes]; - - /*now fill the out values*/ - out[y * (linebytes + 1)] = bestType; /*the first byte of a scanline will be the filter type*/ - for(x = 0; x < linebytes; x++) out[y * (linebytes + 1) + 1 + x] = attempt[bestType].data[x]; - } - } - - for(type = 0; type < 5; type++) ucvector_cleanup(&attempt[type]); - } - - return error; -} - -static void addPaddingBits(unsigned char* out, const unsigned char* in, size_t olinebits, size_t ilinebits, unsigned h) -{ - /*The opposite of the removePaddingBits function - olinebits must be >= ilinebits*/ - unsigned y; - size_t diff = olinebits - ilinebits; - size_t obp = 0, ibp = 0; /*bit pointers*/ - for(y = 0; y < h; y++) - { - size_t x; - for(x = 0; x < ilinebits; x++) - { - unsigned char bit = readBitFromReversedStream(&ibp, in); - setBitOfReversedStream(&obp, out, bit); - } - /*obp += diff; --> no, fill in some value in the padding bits too, to avoid "Use of uninitialised value of size ###" warning from valgrind*/ - for(x = 0; x < diff; x++) setBitOfReversedStream(&obp, out, 0); - } -} - -static void Adam7_interlace(unsigned char* out, const unsigned char* in, unsigned w, unsigned h, unsigned bpp) -{ - /*Note: this function works on image buffers WITHOUT padding bits at end of scanlines with non-multiple-of-8 bit amounts, only between reduced images is padding*/ - unsigned passw[7], passh[7]; size_t filter_passstart[8], padded_passstart[8], passstart[8]; - unsigned i; - - Adam7_getpassvalues(passw, passh, filter_passstart, padded_passstart, passstart, w, h, bpp); - - if(bpp >= 8) - { - for(i = 0; i < 7; i++) - { - unsigned x, y, b; - size_t bytewidth = bpp / 8; - for(y = 0; y < passh[i]; y++) - for(x = 0; x < passw[i]; x++) - { - size_t pixelinstart = ((ADAM7_IY[i] + y * ADAM7_DY[i]) * w + ADAM7_IX[i] + x * ADAM7_DX[i]) * bytewidth; - size_t pixeloutstart = passstart[i] + (y * passw[i] + x) * bytewidth; - for(b = 0; b < bytewidth; b++) - { - out[pixeloutstart + b] = in[pixelinstart + b]; - } - } - } - } - else /*bpp < 8: Adam7 with pixels < 8 bit is a bit trickier: with bit pointers*/ - { - for(i = 0; i < 7; i++) - { - unsigned x, y, b; - unsigned ilinebits = bpp * passw[i]; - unsigned olinebits = bpp * w; - size_t obp, ibp; /*bit pointers (for out and in buffer)*/ - for(y = 0; y < passh[i]; y++) - for(x = 0; x < passw[i]; x++) - { - ibp = (ADAM7_IY[i] + y * ADAM7_DY[i]) * olinebits + (ADAM7_IX[i] + x * ADAM7_DX[i]) * bpp; - obp = (8 * passstart[i]) + (y * ilinebits + x * bpp); - for(b = 0; b < bpp; b++) - { - unsigned char bit = readBitFromReversedStream(&ibp, in); - setBitOfReversedStream(&obp, out, bit); - } - } - } - } -} - -/*out must be buffer big enough to contain uncompressed IDAT chunk data, and in must contain the full image*/ -static unsigned preProcessScanlines(unsigned char** out, size_t* outsize, const unsigned char* in, const LodePNG_InfoPng* infoPng) /*return value is error*/ -{ - /* - This function converts the pure 2D image with the PNG's colortype, into filtered-padded-interlaced data. Steps: - *) if no Adam7: 1) add padding bits (= possible extra bits per scanline if bpp < 8) 2) filter - *) if adam7: 1) Adam7_interlace 2) 7x add padding bits 3) 7x filter - */ - unsigned bpp = LodePNG_InfoColor_getBpp(&infoPng->color); - unsigned w = infoPng->width; - unsigned h = infoPng->height; - unsigned error = 0; - - if(infoPng->interlaceMethod == 0) - { - *outsize = h + (h * ((w * bpp + 7) / 8)); /*image size plus an extra byte per scanline + possible padding bits*/ - *out = (unsigned char*)malloc(*outsize); - if(!(*out) && (*outsize)) error = 9950; - - if(!error) - { - if(bpp < 8 && w * bpp != ((w * bpp + 7) / 8) * 8) /*non multiple of 8 bits per scanline, padding bits needed per scanline*/ - { - ucvector padded; - ucvector_init(&padded); - if(!ucvector_resize(&padded, h * ((w * bpp + 7) / 8))) error = 9951; - if(!error) - { - addPaddingBits(padded.data, in, ((w * bpp + 7) / 8) * 8, w * bpp, h); - error = filter(*out, padded.data, w, h, &infoPng->color); - } - ucvector_cleanup(&padded); - } - else error = filter(*out, in, w, h, &infoPng->color); /*we can immediately filter into the out buffer, no other steps needed*/ - } - } - else /*interlaceMethod is 1 (Adam7)*/ - { - unsigned char* adam7 = (unsigned char*)malloc((h * w * bpp + 7) / 8); - if(!adam7 && ((h * w * bpp + 7) / 8)) error = 9952; /*malloc failed*/ - - while(!error) /*not a real while loop, used to break out to cleanup to avoid a goto*/ - { - unsigned passw[7], passh[7]; size_t filter_passstart[8], padded_passstart[8], passstart[8]; - unsigned i; - - Adam7_getpassvalues(passw, passh, filter_passstart, padded_passstart, passstart, w, h, bpp); - - *outsize = filter_passstart[7]; /*image size plus an extra byte per scanline + possible padding bits*/ - *out = (unsigned char*)malloc(*outsize); - if(!(*out) && (*outsize)) { error = 9953; break; } - - Adam7_interlace(adam7, in, w, h, bpp); - - for(i = 0; i < 7; i++) - { - if(bpp < 8) - { - ucvector padded; - ucvector_init(&padded); - if(!ucvector_resize(&padded, h * ((w * bpp + 7) / 8))) error = 9954; - if(!error) - { - addPaddingBits(&padded.data[padded_passstart[i]], &adam7[passstart[i]], ((passw[i] * bpp + 7) / 8) * 8, passw[i] * bpp, passh[i]); - error = filter(&(*out)[filter_passstart[i]], &padded.data[padded_passstart[i]], passw[i], passh[i], &infoPng->color); - } - - ucvector_cleanup(&padded); - } - else - { - error = filter(&(*out)[filter_passstart[i]], &adam7[padded_passstart[i]], passw[i], passh[i], &infoPng->color); - } - } - - break; - } - - free(adam7); - } - - return error; -} - -/*palette must have 4 * palettesize bytes allocated*/ -static unsigned isPaletteFullyOpaque(const unsigned char* palette, size_t palettesize) /*palette given in format RGBARGBARGBARGBA...*/ -{ - size_t i; - for(i = 0; i < palettesize; i++) - { - if(palette[4 * i + 3] != 255) return 0; - } - return 1; -} - -/*this function checks if the input image given by the user has no transparent pixels*/ -static unsigned isFullyOpaque(const unsigned char* image, unsigned w, unsigned h, const LodePNG_InfoColor* info) -{ - /*TODO: When the user specified a color key for the input image, then this function must also check for pixels that are the same as the color key and treat those as transparent.*/ - - unsigned i, numpixels = w * h; - if(info->colorType == 6) - { - if(info->bitDepth == 8) - { - for(i = 0; i < numpixels; i++) if(image[i * 4 + 3] != 255) return 0; - } - else - { - for(i = 0; i < numpixels; i++) if(image[i * 8 + 6] != 255 || image[i * 8 + 7] != 255) return 0; - } - return 1; /*no single pixel with alpha channel other than 255 found*/ - } - else if(info->colorType == 4) - { - if(info->bitDepth == 8) - { - for(i = 0; i < numpixels; i++) if(image[i * 2 + 1] != 255) return 0; - } - else - { - for(i = 0; i < numpixels; i++) if(image[i * 4 + 2] != 255 || image[i * 4 + 3] != 255) return 0; - } - return 1; /*no single pixel with alpha channel other than 255 found*/ - } - else if(info->colorType == 3) - { - /*when there's a palette, we could check every pixel for translucency, but much quicker is to just check the palette*/ - return(isPaletteFullyOpaque(info->palette, info->palettesize)); - } - - return 0; /*color type that isn't supported by this function yet, so assume there is transparency to be safe*/ -} - -void LodePNG_encode(LodePNG_Encoder* encoder, unsigned char** out, size_t* outsize, const unsigned char* image, unsigned w, unsigned h) -{ - LodePNG_InfoPng info; - ucvector outv; - unsigned char* data = 0; /*uncompressed version of the IDAT chunk data*/ - size_t datasize = 0; - - /*provide some proper output values if error will happen*/ - *out = 0; - *outsize = 0; - encoder->error = 0; - - info = encoder->infoPng; /*UNSAFE copy to avoid having to cleanup! but we will only change primitive parameters, and not invoke the cleanup function nor touch the palette's buffer so we use it safely*/ - info.width = w; - info.height = h; - - if(encoder->settings.autoLeaveOutAlphaChannel && isFullyOpaque(image, w, h, &encoder->infoRaw.color)) - { - /*go to a color type without alpha channel*/ - if(info.color.colorType == 6) info.color.colorType = 2; - else if(info.color.colorType == 4) info.color.colorType = 0; - } - - if(encoder->settings.zlibsettings.windowSize > 32768) { encoder->error = 60; return; } /*error: windowsize larger than allowed*/ - if(encoder->settings.zlibsettings.btype > 2) { encoder->error = 61; return; } /*error: unexisting btype*/ - if(encoder->infoPng.interlaceMethod > 1) { encoder->error = 71; return; } /*error: unexisting interlace mode*/ - if((encoder->error = checkColorValidity(info.color.colorType, info.color.bitDepth))) return; /*error: unexisting color type given*/ - if((encoder->error = checkColorValidity(encoder->infoRaw.color.colorType, encoder->infoRaw.color.bitDepth))) return; /*error: unexisting color type given*/ - - if(!LodePNG_InfoColor_equal(&encoder->infoRaw.color, &info.color)) - { - unsigned char* converted; - size_t size = (w * h * LodePNG_InfoColor_getBpp(&info.color) + 7) / 8; - - if((info.color.colorType != 6 && info.color.colorType != 2) || (info.color.bitDepth != 8)) { encoder->error = 59; return; } /*for the output image, only these types are supported*/ - converted = (unsigned char*)malloc(size); - if(!converted && size) encoder->error = 9955; /*error: malloc failed*/ - if(!encoder->error) encoder->error = LodePNG_convert(converted, image, &info.color, &encoder->infoRaw.color, w, h); - if(!encoder->error) preProcessScanlines(&data, &datasize, converted, &info);/*filter(data.data, converted.data, w, h, LodePNG_InfoColor_getBpp(&info.color));*/ - free(converted); - } - else preProcessScanlines(&data, &datasize, image, &info);/*filter(data.data, image, w, h, LodePNG_InfoColor_getBpp(&info.color));*/ - - ucvector_init(&outv); - while(!encoder->error) /*not really a while loop, this is only used to break out if an error happens to avoid goto's to do the ucvector cleanup*/ - { - /*write signature and chunks*/ - writeSignature(&outv); - /*IHDR*/ - addChunk_IHDR(&outv, w, h, info.color.bitDepth, info.color.colorType, info.interlaceMethod); - /*PLTE*/ - if(info.color.colorType == 3) - { - if(info.color.palettesize == 0 || info.color.palettesize > 256) { encoder->error = 68; break; } - addChunk_PLTE(&outv, &info.color); - } - if(encoder->settings.force_palette && (info.color.colorType == 2 || info.color.colorType == 6)) - { - if(info.color.palettesize == 0 || info.color.palettesize > 256) { encoder->error = 68; break; } - addChunk_PLTE(&outv, &info.color); - } - /*tRNS*/ - if(info.color.colorType == 3 && !isPaletteFullyOpaque(info.color.palette, info.color.palettesize)) addChunk_tRNS(&outv, &info.color); - if((info.color.colorType == 0 || info.color.colorType == 2) && info.color.key_defined) addChunk_tRNS(&outv, &info.color); - /*IDAT (multiple IDAT chunks must be consecutive)*/ - encoder->error = addChunk_IDAT(&outv, data, datasize, &encoder->settings.zlibsettings); - if(encoder->error) break; - /*IEND*/ - addChunk_IEND(&outv); - - break; /*this isn't really a while loop; no error happened so break out now!*/ - } - - free(data); - /*instead of cleaning the vector up, give it to the output*/ - *out = outv.data; - *outsize = outv.size; -} - -void LodePNG_EncodeSettings_init(LodePNG_EncodeSettings* settings) -{ - LodeZlib_DeflateSettings_init(&settings->zlibsettings); - settings->autoLeaveOutAlphaChannel = 1; - settings->force_palette = 0; -} - -void LodePNG_Encoder_init(LodePNG_Encoder* encoder) -{ - LodePNG_EncodeSettings_init(&encoder->settings); - LodePNG_InfoPng_init(&encoder->infoPng); - LodePNG_InfoRaw_init(&encoder->infoRaw); - encoder->error = 1; -} - -void LodePNG_Encoder_cleanup(LodePNG_Encoder* encoder) -{ - LodePNG_InfoPng_cleanup(&encoder->infoPng); - LodePNG_InfoRaw_cleanup(&encoder->infoRaw); -} - -void LodePNG_Encoder_copy(LodePNG_Encoder* dest, const LodePNG_Encoder* source) -{ - LodePNG_Encoder_cleanup(dest); - *dest = *source; - LodePNG_InfoPng_init(&dest->infoPng); - LodePNG_InfoRaw_init(&dest->infoRaw); - dest->error = LodePNG_InfoPng_copy(&dest->infoPng, &source->infoPng); if(dest->error) return; - dest->error = LodePNG_InfoRaw_copy(&dest->infoRaw, &source->infoRaw); if(dest->error) return; -} - -/* ////////////////////////////////////////////////////////////////////////// */ -/* / File IO / */ -/* ////////////////////////////////////////////////////////////////////////// */ - -/*write given buffer to the file, overwriting the file, it doesn't append to it.*/ -unsigned LodePNG_saveFile(const unsigned char* buffer, size_t buffersize, const char* filename) -{ - FILE* file; - file = portable_fopen(filename, "wb" ); - if(!file) return 79; - fwrite((char*)buffer , 1 , buffersize, file); - fclose(file); - return 0; -} - diff --git a/src/lodepng.h b/src/lodepng.h deleted file mode 100644 index fb079cc..0000000 --- a/src/lodepng.h +++ /dev/null @@ -1,119 +0,0 @@ -/* -LodePNG version 20080927 - -Copyright (c) 2005-2008 Lode Vandevenne - -This software is provided 'as-is', without any express or implied -warranty. In no event will the authors be held liable for any damages -arising from the use of this software. - -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it -freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - - 3. This notice may not be removed or altered from any source - distribution. -*/ - -/** Minified version of LodePNG, with only the encoder code */ - -#ifndef LODEPNG_H -#define LODEPNG_H - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -/* ////////////////////////////////////////////////////////////////////////// */ -/* LodeFlate & LodeZlib Setting structs */ -/* ////////////////////////////////////////////////////////////////////////// */ - - -typedef struct LodeZlib_DeflateSettings /*deflate = compress*/ -{ - /*LZ77 related settings*/ - unsigned btype; /*the block type for LZ*/ - unsigned useLZ77; /*whether or not to use LZ77*/ - unsigned windowSize; /*the maximum is 32768*/ -} LodeZlib_DeflateSettings; - - -/* ////////////////////////////////////////////////////////////////////////// */ -/* LodePNG */ -/* ////////////////////////////////////////////////////////////////////////// */ - -typedef struct LodePNG_InfoColor /*info about the color type of an image*/ -{ - /*header (IHDR)*/ - unsigned colorType; /*color type*/ - unsigned bitDepth; /*bits per sample*/ - - /*palette (PLTE)*/ - unsigned char* palette; /*palette in RGBARGBA... order*/ - size_t palettesize; /*palette size in number of colors (amount of bytes is 4 * palettesize)*/ - - /*transparent color key (tRNS)*/ - unsigned key_defined; /*is a transparent color key given?*/ - unsigned key_r; /*red component of color key*/ - unsigned key_g; /*green component of color key*/ - unsigned key_b; /*blue component of color key*/ -} LodePNG_InfoColor; - -typedef struct LodePNG_InfoPng /*information about the PNG image, except pixels and sometimes except width and height*/ -{ - /*header (IHDR), palette (PLTE) and transparency (tRNS)*/ - unsigned width; /*width of the image in pixels (ignored by encoder, but filled in by decoder)*/ - unsigned height; /*height of the image in pixels (ignored by encoder, but filled in by decoder)*/ - unsigned compressionMethod; /*compression method of the original file*/ - unsigned filterMethod; /*filter method of the original file*/ - unsigned interlaceMethod; /*interlace method of the original file*/ - LodePNG_InfoColor color; /*color type and bits, palette, transparency*/ -} LodePNG_InfoPng; - -typedef struct LodePNG_InfoRaw /*contains user-chosen information about the raw image data, which is independent of the PNG image*/ -{ - LodePNG_InfoColor color; -} LodePNG_InfoRaw; - -unsigned LodePNG_InfoColor_addPalette(LodePNG_InfoColor* info, unsigned char r, unsigned char g, unsigned char b, unsigned char a); /*add 1 color to the palette*/ - -typedef struct LodePNG_EncodeSettings -{ - LodeZlib_DeflateSettings zlibsettings; /*settings for the zlib encoder, such as window size, ...*/ - - unsigned autoLeaveOutAlphaChannel; /*automatically use color type without alpha instead of given one, if given image is opaque*/ - unsigned force_palette; /*force creating a PLTE chunk if colortype is 2 or 6 (= a suggested palette). If colortype is 3, PLTE is _always_ created.*/ -} LodePNG_EncodeSettings; - -void LodePNG_EncodeSettings_init(LodePNG_EncodeSettings* settings); - -typedef struct LodePNG_Encoder -{ - LodePNG_EncodeSettings settings; - LodePNG_InfoPng infoPng; /*the info specified by the user may not be changed by the encoder. The encoder will try to generate a PNG close to the given info.*/ - LodePNG_InfoRaw infoRaw; /*put the properties of the input raw image in here*/ - unsigned error; -} LodePNG_Encoder; - -void LodePNG_Encoder_init(LodePNG_Encoder* encoder); -void LodePNG_Encoder_cleanup(LodePNG_Encoder* encoder); -void LodePNG_Encoder_copy(LodePNG_Encoder* dest, const LodePNG_Encoder* source); - -/*This function allocates the out buffer and stores the size in *outsize.*/ -void LodePNG_encode(LodePNG_Encoder* encoder, unsigned char** out, size_t* outsize, const unsigned char* image, unsigned w, unsigned h); - -/*free functions allowing to load and save a file from/to harddisk*/ -/*This function allocates the out buffer and stores the size in *outsize.*/ -//unsigned LodePNG_loadFile(unsigned char** out, size_t* outsize, const char* filename); -unsigned LodePNG_saveFile(const unsigned char* buffer, size_t buffersize, const char* filename); - -#endif - diff --git a/src/mandocvisitor.cpp b/src/mandocvisitor.cpp index 5c98c6f..9f5a45b 100644 --- a/src/mandocvisitor.cpp +++ b/src/mandocvisitor.cpp @@ -367,7 +367,9 @@ void ManDocVisitor::visit(DocInclude *inc) void ManDocVisitor::visit(DocIncOperator *op) { - SrcLangExt langExt = getLanguageFromFileName(m_langExt); + QCString locLangExt = getFileNameExtension(op->includeFileName()); + if (locLangExt.isEmpty()) locLangExt = m_langExt; + SrcLangExt langExt = getLanguageFromFileName(locLangExt); //printf("DocIncOperator: type=%d first=%d, last=%d text=`%s'\n", // op->type(),op->isFirst(),op->isLast(),op->text().data()); if (op->isFirst()) @@ -386,14 +388,14 @@ void ManDocVisitor::visit(DocIncOperator *op) popEnabled(); if (!m_hide) { - FileDef *fd; + FileDef *fd = 0; if (!op->includeFileName().isEmpty()) { QFileInfo cfi( op->includeFileName() ); fd = createFileDef( cfi.dirPath().utf8(), cfi.fileName().utf8() ); } - Doxygen::parserManager->getParser(m_langExt) + Doxygen::parserManager->getParser(locLangExt) ->parseCode(m_ci,op->context(),op->text(),langExt, op->isExample(),op->exampleFile(), fd, // fileDef @@ -569,7 +571,7 @@ void ManDocVisitor::visitPre(DocSimpleSect *s) // special case 1: user defined title if (s->type()!=DocSimpleSect::User && s->type()!=DocSimpleSect::Rcs) { - m_t << ":\\fP" << endl; + m_t << "\\fP" << endl; m_t << ".RS 4" << endl; } } @@ -942,7 +944,7 @@ void ManDocVisitor::visitPre(DocParamSect *s) default: ASSERT(0); } - m_t << ":\\fP" << endl; + m_t << "\\fP" << endl; m_t << ".RS 4" << endl; } @@ -1026,14 +1028,6 @@ void ManDocVisitor::visitPost(DocInternalRef *) m_t << "\\fP"; } -void ManDocVisitor::visitPre(DocCopy *) -{ -} - -void ManDocVisitor::visitPost(DocCopy *) -{ -} - void ManDocVisitor::visitPre(DocText *) { } diff --git a/src/mandocvisitor.h b/src/mandocvisitor.h index 8efc223..fa65424 100644 --- a/src/mandocvisitor.h +++ b/src/mandocvisitor.h @@ -128,8 +128,6 @@ class ManDocVisitor : public DocVisitor void visitPost(DocXRefItem *); void visitPre(DocInternalRef *); void visitPost(DocInternalRef *); - void visitPre(DocCopy *); - void visitPost(DocCopy *); void visitPre(DocText *); void visitPost(DocText *); void visitPre(DocHtmlBlockQuote *); diff --git a/src/mangen.cpp b/src/mangen.cpp index b3ae732..06d3c4a 100644 --- a/src/mangen.cpp +++ b/src/mangen.cpp @@ -706,7 +706,7 @@ void ManGenerator::endParamList() { } -void ManGenerator::writeDoc(DocNode *n,Definition *ctx,MemberDef *) +void ManGenerator::writeDoc(DocNode *n,const Definition *ctx,const MemberDef *) { ManDocVisitor *visitor = new ManDocVisitor(t,*this,ctx?ctx->getDefFileExtension():QCString("")); n->accept(visitor); diff --git a/src/mangen.h b/src/mangen.h index e109355..d912923 100644 --- a/src/mangen.h +++ b/src/mangen.h @@ -41,7 +41,7 @@ class ManGenerator : public OutputGenerator bool isEnabled(OutputType o) { return (o==Man && active); } OutputGenerator *get(OutputType o) { return (o==Man) ? this : 0; } - void writeDoc(DocNode *,Definition *,MemberDef *); + void writeDoc(DocNode *,const Definition *,const MemberDef *); static void init(); void startFile(const char *name,const char *manName,const char *title); @@ -207,16 +207,16 @@ class ManGenerator : public OutputGenerator void endDescTableData() {} void startDotGraph() {} - void endDotGraph(const DotClassGraph &) {} + void endDotGraph(DotClassGraph &) {} void startInclDepGraph() {} - void endInclDepGraph(const DotInclDepGraph &) {} + void endInclDepGraph(DotInclDepGraph &) {} void startGroupCollaboration() {} - void endGroupCollaboration(const DotGroupCollaboration &) {} + void endGroupCollaboration(DotGroupCollaboration &) {} void startCallGraph() {} - void endCallGraph(const DotCallGraph &) {} + void endCallGraph(DotCallGraph &) {} void startDirDepGraph() {} - void endDirDepGraph(const DotDirDeps &) {} - void writeGraphicalHierarchy(const DotGfxHierarchyTable &) {} + void endDirDepGraph(DotDirDeps &) {} + void writeGraphicalHierarchy(DotGfxHierarchyTable &) {} void startTextBlock(bool) {} void endTextBlock(bool) {} @@ -260,7 +260,7 @@ class ManGenerator : public OutputGenerator void endLabels(); void writeCodeAnchor(const char *) {} - void setCurrentDoc(Definition *,const char *,bool) {} + void setCurrentDoc(const Definition *,const char *,bool) {} void addWord(const char *,bool) {} private: diff --git a/src/markdown.cpp b/src/markdown.cpp index dea2476..8670642 100644 --- a/src/markdown.cpp +++ b/src/markdown.cpp @@ -107,13 +107,7 @@ static action_t g_actions[256]; static Entry *g_current; static QCString g_fileName; static int g_lineNr; - -// In case a markdown page starts with a level1 header, that header is used -// as a title of the page, in effect making it a level0 header, so the -// level of all other sections needs to be corrected as well. -// This flag is TRUE if corrections are needed. -//static bool g_correctSectionLevel; - +static int g_indentLevel=0; // 0 is outside markdown, -1=page level //---------- @@ -915,7 +909,7 @@ static int processLink(GrowBuf &out,const char *data,int,int size) { SrcLangExt lang = getLanguageFromFileName(link); int lp=-1; - if ((lp=link.find("@ref "))!=-1 || (lp=link.find("\\ref "))!=-1 || lang==SrcLangExt_Markdown) + if ((lp=link.find("@ref "))!=-1 || (lp=link.find("\\ref "))!=-1 || (lang==SrcLangExt_Markdown && !isURL(link))) // assume doxygen symbol link { if (lp==-1) // link to markdown page @@ -1103,7 +1097,7 @@ static void processInline(GrowBuf &out,const char *data,int size) } /** returns whether the line is a setext-style hdr underline */ -static int isHeaderline(const char *data, int size) +static int isHeaderline(const char *data, int size, bool allowAdjustLevel) { int i=0, c=0; while (i<size && data[i]==' ') i++; @@ -1113,14 +1107,24 @@ static int isHeaderline(const char *data, int size) { while (i<size && data[i]=='=') i++,c++; while (i<size && data[i]==' ') i++; - return (c>1 && (i>=size || data[i]=='\n')) ? 1 : 0; + int level = (c>1 && (i>=size || data[i]=='\n')) ? 1 : 0; + if (allowAdjustLevel && level==1 && g_indentLevel==-1) + { + // In case a page starts with a header line we use it as title, promoting it to @page. + // We set g_indentLevel to -1 to promoting the other sections if they have a deeper + // nesting level than the page header, i.e. @section..@subsection becomes @page..@section. + // In case a section at the same level is found (@section..@section) however we need + // to undo this (and the result will be @page..@section). + g_indentLevel=0; + } + return g_indentLevel+level; } // test of level 2 header if (data[i]=='-') { while (i<size && data[i]=='-') i++,c++; while (i<size && data[i]==' ') i++; - return (c>1 && (i>=size || data[i]=='\n')) ? 2 : 0; + return (c>1 && (i>=size || data[i]=='\n')) ? g_indentLevel+2 : 0; } return 0; } @@ -1295,7 +1299,7 @@ static QCString extractTitleId(QCString &title, int level) static int isAtxHeader(const char *data,int size, - QCString &header,QCString &id) + QCString &header,QCString &id,bool allowAdjustLevel) { int i = 0, end; int level = 0, blanks=0; @@ -1328,7 +1332,29 @@ static int isAtxHeader(const char *data,int size, header=header.left(i+1); } - return level; + if (allowAdjustLevel && level==1 && g_indentLevel==-1) + { + // in case we find a `# Section` on a markdown page that started with the same level + // header, we no longer need to artificially decrease the paragraph level. + // So both + // ------------------- + // # heading 1 <-- here we set g_indentLevel to -1 + // # heading 2 <-- here we set g_indentLevel back to 0 such that this will be a @section + // ------------------- + // and + // ------------------- + // # heading 1 <-- here we set g_indentLevel to -1 + // ## heading 2 <-- here we keep g_indentLevel at -1 such that @subsection will be @section + // ------------------- + // will convert to + // ------------------- + // @page md_page Heading 1 + // @section autotoc_md1 Heading 2 + // ------------------- + + g_indentLevel=0; + } + return level+g_indentLevel; } static int isEmptyLine(const char *data,int size) @@ -1913,10 +1939,8 @@ void writeOneLineHeaderOrRuler(GrowBuf &out,const char *data,int size) { out.addStr("\n<hr>\n"); } - else if ((level=isAtxHeader(data,size,header,id))) + else if ((level=isAtxHeader(data,size,header,id,TRUE))) { - //if (level==1) g_correctSectionLevel=FALSE; - //if (g_correctSectionLevel) level--; QCString hTag; if (level<5 && !id.isEmpty()) { @@ -2258,10 +2282,8 @@ static QCString processBlocks(const QCString &s,int indent) QCString lang; blockIndent = indent; //printf("isHeaderLine(%s)=%d\n",QCString(data+i).left(size-i).data(),level); - if ((level=isHeaderline(data+i,size-i))>0) + if ((level=isHeaderline(data+i,size-i,TRUE))>0) { - //if (level==1) g_correctSectionLevel=FALSE; - //if (g_correctSectionLevel) level--; //printf("Found header at %d-%d\n",i,end); while (pi<size && data[pi]==' ') pi++; QCString header,id; @@ -2402,7 +2424,7 @@ static QCString extractPageTitle(QCString &docs,QCString &id) // second line form end1..end2 int end2=end1+1; while (end2<size && data[end2-1]!='\n') end2++; - if (isHeaderline(data+end1,size-end1)) + if (isHeaderline(data+end1,size-end1,FALSE)) { convertStringFragment(title,data+i,end1-i-1); QCString lns; @@ -2413,10 +2435,14 @@ static QCString extractPageTitle(QCString &docs,QCString &id) return title; } } - if (i<end1 && isAtxHeader(data+i,end1-i,title,id)>0) + if (i<end1 && isAtxHeader(data+i,end1-i,title,id,FALSE)>0) { docs=docs.mid(end1); } + else + { + id = extractTitleId(title, 0); + } //printf("extractPageTitle(title='%s' docs='%s' id='%s')\n",title.data(),docs.data(),id.data()); return title; } @@ -2453,19 +2479,32 @@ static QCString detab(const QCString &s,int &refIndent) col++; break; default: // non-whitespace => update minIndent - out.addChar(c); if (c<0 && i<size) // multibyte sequence { - out.addChar(data[i++]); // >= 2 bytes - if (((uchar)c&0xE0)==0xE0 && i<size) + // special handling of the UTF-8 nbsp character 0xc2 0xa0 + if (c == '\xc2' && data[i] == '\xa0') { - out.addChar(data[i++]); // 3 bytes + out.addStr(" "); + i++; } - if (((uchar)c&0xF0)==0xF0 && i<size) + else { - out.addChar(data[i++]); // 4 byres + out.addChar(c); + out.addChar(data[i++]); // >= 2 bytes + if (((uchar)c&0xE0)==0xE0 && i<size) + { + out.addChar(data[i++]); // 3 bytes + } + if (((uchar)c&0xF0)==0xF0 && i<size) + { + out.addChar(data[i++]); // 4 byres + } } } + else + { + out.addChar(c); + } if (col<minIndent) minIndent=col; col++; } @@ -2536,6 +2575,7 @@ QCString markdownFileNameToId(const QCString &fileName) return "md_"+baseName; } + void MarkdownFileParser::parseInput(const char *fileName, const char *fileBuf, Entry *root, @@ -2550,6 +2590,7 @@ void MarkdownFileParser::parseInput(const char *fileName, QCString docs = fileBuf; QCString id; QCString title=extractPageTitle(docs,id).stripWhiteSpace(); + g_indentLevel=title.isEmpty() ? 0 : -1; QCString titleFn = QFileInfo(fileName).baseName().utf8(); QCString fn = QFileInfo(fileName).fileName().utf8(); static QCString mdfileAsMainPage = Config_getString(USE_MDFILE_AS_MAINPAGE); @@ -2616,7 +2657,7 @@ void MarkdownFileParser::parseInput(const char *fileName, // restore setting Doxygen::markdownSupport = markdownEnabled; - //g_correctSectionLevel = FALSE; + g_indentLevel=0; } void MarkdownFileParser::parseCode(CodeOutputInterface &codeOutIntf, @@ -2629,9 +2670,9 @@ void MarkdownFileParser::parseCode(CodeOutputInterface &codeOutIntf, int startLine, int endLine, bool inlineFragment, - MemberDef *memberDef, + const MemberDef *memberDef, bool showLineNumbers, - Definition *searchCtx, + const Definition *searchCtx, bool collectXRefs ) { diff --git a/src/markdown.h b/src/markdown.h index e2e3a74..1a3895e 100644 --- a/src/markdown.h +++ b/src/markdown.h @@ -47,9 +47,9 @@ class MarkdownFileParser : public ParserInterface int startLine=-1, int endLine=-1, bool inlineFragment=FALSE, - MemberDef *memberDef=0, + const MemberDef *memberDef=0, bool showLineNumbers=TRUE, - Definition *searchCtx=0, + const Definition *searchCtx=0, bool collectXRefs=TRUE ); void resetCodeParserState(); diff --git a/src/memberdef.cpp b/src/memberdef.cpp index 995901a..4dca53f 100644 --- a/src/memberdef.cpp +++ b/src/memberdef.cpp @@ -33,6 +33,7 @@ #include "defargs.h" #include "docparser.h" #include "dot.h" +#include "dotcallgraph.h" #include "searchindex.h" #include "parserintf.h" #include "objcache.h" @@ -58,6 +59,8 @@ class MemberDefImpl : public DefinitionImpl, public MemberDef virtual ~MemberDefImpl(); virtual DefType definitionType() const { return TypeMember; } + virtual MemberDef *resolveAlias() { return this; } + virtual const MemberDef *resolveAlias() const { return this; } virtual MemberDef *deepCopy() const; virtual void moveTo(Definition *); virtual QCString getOutputFileBase() const; @@ -73,15 +76,19 @@ class MemberDefImpl : public DefinitionImpl, public MemberDef virtual const QCString &initializer() const; virtual int initializerLines() const; virtual uint64 getMemberSpecifiers() const; - virtual MemberList *getSectionList(Definition *d) const; + virtual const MemberList *getSectionList(const Definition *d) const; virtual QCString displayDefinition() const; - virtual ClassDef *getClassDef() const; - virtual FileDef *getFileDef() const; - virtual NamespaceDef* getNamespaceDef() const; + virtual const ClassDef *getClassDef() const; + virtual ClassDef *getClassDef(); + virtual const FileDef *getFileDef() const; + virtual FileDef *getFileDef(); + virtual const NamespaceDef* getNamespaceDef() const; + virtual NamespaceDef* getNamespaceDef(); + virtual const GroupDef *getGroupDef() const; + virtual GroupDef *getGroupDef(); virtual ClassDef *accessorClass() const; virtual const char *getReadAccessor() const; virtual const char *getWriteAccessor() const; - virtual GroupDef *getGroupDef() const; virtual Grouping::GroupPri_t getGroupPri() const; virtual const char *getGroupFileName() const; virtual int getGroupStartLine() const; @@ -141,7 +148,7 @@ class MemberDefImpl : public DefinitionImpl, public MemberDef virtual bool isSealed() const; virtual bool isImplementation() const; virtual bool isExternal() const; - virtual bool isAlias() const; + virtual bool isTypeAlias() const; virtual bool isDefault() const; virtual bool isDelete() const; virtual bool isNoExcept() const; @@ -156,8 +163,6 @@ class MemberDefImpl : public DefinitionImpl, public MemberDef virtual bool isMaybeAmbiguous() const; virtual bool isPublished() const; virtual bool isTemplateSpecialization() const; - virtual bool hasDocumentedParams() const; - virtual bool hasDocumentedReturnType() const; virtual bool isObjCMethod() const; virtual bool isObjCProperty() const; virtual bool isConstructor() const; @@ -184,22 +189,23 @@ class MemberDefImpl : public DefinitionImpl, public MemberDef virtual bool isDocumentedFriendClass() const; virtual MemberDef *reimplements() const; virtual MemberList *reimplementedBy() const; - virtual bool isReimplementedBy(ClassDef *cd) const; + virtual bool isReimplementedBy(const ClassDef *cd) const; virtual ClassDef *relatedAlso() const; virtual bool hasDocumentedEnumValues() const; - virtual MemberDef *getAnonymousEnumType() const; + virtual const MemberDef *getAnonymousEnumType() const; virtual bool isDocsForDefinition() const; - virtual MemberDef *getEnumScope() const; - virtual MemberList *enumFieldList() const; + virtual const MemberDef *getEnumScope() const; + virtual const MemberList *enumFieldList() const; virtual void setEnumBaseType(const QCString &type); virtual QCString enumBaseType() const; - virtual bool hasExamples(); + virtual bool hasExamples() const; virtual ExampleSDict *getExamples() const; virtual bool isPrototype() const; - virtual ArgumentList *argumentList() const; - virtual ArgumentList *declArgumentList() const; - virtual ArgumentList *templateArguments() const; - virtual QList<ArgumentList> *definitionTemplateParameterLists() const; + virtual const ArgumentList *argumentList() const; + virtual ArgumentList *argumentList(); + virtual const ArgumentList *declArgumentList() const; + virtual const ArgumentList *templateArguments() const; + virtual const QList<ArgumentList> *definitionTemplateParameterLists() const; virtual int getMemberGroupId() const; virtual MemberGroup *getMemberGroup() const; virtual bool fromAnonymousScope() const; @@ -207,25 +213,25 @@ class MemberDefImpl : public DefinitionImpl, public MemberDef virtual MemberDef *fromAnonymousMember() const; virtual bool hasCallGraph() const; virtual bool hasCallerGraph() const; - virtual bool visibleMemberGroup(bool hideNoHeader); + virtual bool visibleMemberGroup(bool hideNoHeader) const; virtual bool hasReferencesRelation() const; virtual bool hasReferencedByRelation() const; virtual MemberDef *templateMaster() const; virtual QCString getScopeString() const; - virtual ClassDef *getClassDefOfAnonymousType(); + virtual ClassDef *getClassDefOfAnonymousType() const; virtual bool isTypedefValCached() const; - virtual ClassDef *getCachedTypedefVal() const; + virtual const ClassDef *getCachedTypedefVal() const; virtual QCString getCachedTypedefTemplSpec() const; virtual QCString getCachedResolvedTypedef() const; virtual MemberDef *memberDefinition() const; virtual MemberDef *memberDeclaration() const; virtual MemberDef *inheritsDocsFrom() const; - virtual MemberDef *getGroupAlias() const; + virtual const MemberDef *getGroupAlias() const; virtual ClassDef *category() const; virtual MemberDef *categoryRelation() const; virtual QCString displayName(bool=TRUE) const; virtual QCString getDeclType() const; - virtual void getLabels(QStrList &sl,Definition *container) const; + virtual void getLabels(QStrList &sl,const Definition *container) const; virtual const ArgumentList *typeConstraints() const; virtual QCString documentation() const; virtual QCString briefDescription(bool abbr=FALSE) const; @@ -254,8 +260,6 @@ class MemberDefImpl : public DefinitionImpl, public MemberDef virtual void setTemplateSpecialization(bool b); virtual void makeRelated(); virtual void makeForeign(); - virtual void setHasDocumentedParams(bool b); - virtual void setHasDocumentedReturnType(bool b); virtual void setInheritsDocsFrom(MemberDef *md); virtual void setTagInfo(TagInfo *i); virtual void setArgsString(const char *as); @@ -266,7 +270,7 @@ class MemberDefImpl : public DefinitionImpl, public MemberDef virtual void setEnumScope(MemberDef *md,bool livesInsideEnum=FALSE); virtual void setEnumClassScope(ClassDef *cd); virtual void setDocumentedEnumValues(bool value); - virtual void setAnonymousEnumType(MemberDef *md); + virtual void setAnonymousEnumType(const MemberDef *md); virtual bool addExample(const char *anchor,const char *name,const char *file); virtual void setPrototype(bool p,const QCString &df,int line, int column); virtual void setExplicitExternal(bool b,const QCString &df,int line,int column); @@ -281,7 +285,7 @@ class MemberDefImpl : public DefinitionImpl, public MemberDef virtual void setMemberGroup(MemberGroup *grp); virtual void setMemberGroupId(int id); virtual void makeImplementationDetail(); - virtual void setFromAnonymousScope(bool b); + virtual void setFromAnonymousScope(bool b) const; virtual void setFromAnonymousMember(MemberDef *m); virtual void enableCallGraph(bool e); virtual void enableCallerGraph(bool e); @@ -290,13 +294,13 @@ class MemberDefImpl : public DefinitionImpl, public MemberDef virtual void setTemplateMaster(MemberDef *mt); virtual void addListReference(Definition *d); virtual void setDocsForDefinition(bool b); - virtual void setGroupAlias(MemberDef *md); - virtual void cacheTypedefVal(ClassDef *val,const QCString &templSpec,const QCString &resolvedType); + virtual void setGroupAlias(const MemberDef *md); + virtual void cacheTypedefVal(const ClassDef *val,const QCString &templSpec,const QCString &resolvedType); virtual void invalidateTypedefValCache(); virtual void invalidateCachedArgumentTypes(); virtual void setMemberDefinition(MemberDef *md); virtual void setMemberDeclaration(MemberDef *md); - virtual void setAnonymousUsed(); + virtual void setAnonymousUsed() const; virtual void copyArgumentNames(MemberDef *bmd); virtual void setCategory(ClassDef *); virtual void setCategoryRelation(MemberDef *); @@ -305,42 +309,43 @@ class MemberDefImpl : public DefinitionImpl, public MemberDef virtual void setInbodyDocumentation(const char *d,const char *inbodyFile,int inbodyLine); virtual void setHidden(bool b); virtual void writeDeclaration(OutputList &ol, - ClassDef *cd,NamespaceDef *nd,FileDef *fd,GroupDef *gd, - bool inGroup, ClassDef *inheritFrom=0,const char *inheritId=0); - virtual void writeDocumentation(MemberList *ml,int memCount,int memTotal,OutputList &ol, - const char *scopeName,Definition *container, + const ClassDef *cd,const NamespaceDef *nd,const FileDef *fd,const GroupDef *gd, + bool inGroup, const ClassDef *inheritFrom=0,const char *inheritId=0) const; + virtual void writeDocumentation(const MemberList *ml,int memCount,int memTotal,OutputList &ol, + const char *scopeName,const Definition *container, bool inGroup,bool showEnumValues=FALSE,bool - showInline=FALSE); - virtual void writeMemberDocSimple(OutputList &ol,Definition *container); + showInline=FALSE) const; + virtual void writeMemberDocSimple(OutputList &ol,const Definition *container) const; virtual void writeEnumDeclaration(OutputList &typeDecl, - ClassDef *cd,NamespaceDef *nd,FileDef *fd,GroupDef *gd); - virtual void writeTagFile(FTextStream &); - virtual void warnIfUndocumented(); - virtual void warnIfUndocumentedParams(); + const ClassDef *cd,const NamespaceDef *nd,const FileDef *fd,const GroupDef *gd) const; + virtual void writeTagFile(FTextStream &) const; + virtual void warnIfUndocumented() const; + virtual void warnIfUndocumentedParams() const; + virtual void detectUndocumentedParams(bool hasParamCommand,bool hasReturnCommand) const; virtual MemberDef *createTemplateInstanceMember(ArgumentList *formalArgs, - ArgumentList *actualArgs); + ArgumentList *actualArgs) const; virtual void findSectionsInDocumentation(); virtual void writeLink(OutputList &ol, - ClassDef *cd,NamespaceDef *nd,FileDef *fd,GroupDef *gd, - bool onlyText=FALSE); - virtual void addToSearchIndex(); + const ClassDef *cd,const NamespaceDef *nd,const FileDef *fd,const GroupDef *gd, + bool onlyText=FALSE) const; + virtual void addToSearchIndex() const; private: void _computeLinkableInProject(); void _computeIsConstructor(); void _computeIsDestructor(); - void _writeGroupInclude(OutputList &ol,bool inGroup); - void _writeCallGraph(OutputList &ol); - void _writeCallerGraph(OutputList &ol); - void _writeReimplements(OutputList &ol); - void _writeReimplementedBy(OutputList &ol); - void _writeExamples(OutputList &ol); - void _writeTypeConstraints(OutputList &ol); - void _writeEnumValues(OutputList &ol,Definition *container, + void _writeGroupInclude(OutputList &ol,bool inGroup) const; + void _writeCallGraph(OutputList &ol) const; + void _writeCallerGraph(OutputList &ol) const; + void _writeReimplements(OutputList &ol) const; + void _writeReimplementedBy(OutputList &ol) const; + void _writeExamples(OutputList &ol) const; + void _writeTypeConstraints(OutputList &ol) const; + void _writeEnumValues(OutputList &ol,const Definition *container, const QCString &cfname,const QCString &ciname, - const QCString &cname); - void _writeCategoryRelation(OutputList &ol); - void _writeTagData(const DefType); + const QCString &cname) const; + void _writeCategoryRelation(OutputList &ol) const; + void _writeTagData(const DefType) const; static int s_indentLevel; @@ -367,6 +372,485 @@ MemberDef *createMemberDef(const char *defFileName,int defLine,int defColumn, stat,related,t,tal,al,metaData); } +//----------------------------------------------------------------------------- + +class MemberDefAliasImpl : public DefinitionAliasImpl, public MemberDef +{ + public: + MemberDefAliasImpl(const Definition *newScope,const MemberDef *md) + : DefinitionAliasImpl(newScope,md) {} + virtual ~MemberDefAliasImpl() {} + virtual DefType definitionType() const { return TypeMember; } + + const MemberDef *getMdAlias() const { return dynamic_cast<const MemberDef*>(getAlias()); } + virtual MemberDef *resolveAlias() { return const_cast<MemberDef*>(getMdAlias()); } + virtual const MemberDef *resolveAlias() const { return getMdAlias(); } + + virtual MemberDef *deepCopy() const { + return createMemberDefAlias(getScope(),getMdAlias()); + } + virtual void moveTo(Definition *) {} + + virtual QCString getOutputFileBase() const + { return getMdAlias()->getOutputFileBase(); } + virtual QCString getReference() const + { return getMdAlias()->getReference(); } + virtual QCString anchor() const + { return getMdAlias()->anchor(); } + virtual const char *declaration() const + { return getMdAlias()->declaration(); } + virtual const char *definition() const + { return getMdAlias()->definition(); } + virtual const char *typeString() const + { return getMdAlias()->typeString(); } + virtual const char *argsString() const + { return getMdAlias()->argsString(); } + virtual const char *excpString() const + { return getMdAlias()->excpString(); } + virtual const char *bitfieldString() const + { return getMdAlias()->bitfieldString(); } + virtual const char *extraTypeChars() const + { return getMdAlias()->extraTypeChars(); } + virtual const QCString &initializer() const + { return getMdAlias()->initializer(); } + virtual int initializerLines() const + { return getMdAlias()->initializerLines(); } + virtual uint64 getMemberSpecifiers() const + { return getMdAlias()->getMemberSpecifiers(); } + virtual const MemberList *getSectionList(const Definition *d) const + { return getMdAlias()->getSectionList(d); } + virtual QCString displayDefinition() const + { return getMdAlias()->displayDefinition(); } + virtual const ClassDef *getClassDef() const + { return getMdAlias()->getClassDef(); } + virtual const FileDef *getFileDef() const + { return getMdAlias()->getFileDef(); } + virtual const NamespaceDef* getNamespaceDef() const + { return getMdAlias()->getNamespaceDef(); } + virtual ClassDef *accessorClass() const + { return getMdAlias()->accessorClass(); } + virtual const char *getReadAccessor() const + { return getMdAlias()->getReadAccessor(); } + virtual const char *getWriteAccessor() const + { return getMdAlias()->getWriteAccessor(); } + virtual const GroupDef *getGroupDef() const + { return getMdAlias()->getGroupDef(); } + virtual Grouping::GroupPri_t getGroupPri() const + { return getMdAlias()->getGroupPri(); } + virtual const char *getGroupFileName() const + { return getMdAlias()->getGroupFileName(); } + virtual int getGroupStartLine() const + { return getMdAlias()->getGroupStartLine(); } + virtual bool getGroupHasDocs() const + { return getMdAlias()->getGroupHasDocs(); } + virtual QCString qualifiedName() const + { return getMdAlias()->qualifiedName(); } + virtual QCString objCMethodName(bool localLink,bool showStatic) const + { return getMdAlias()->objCMethodName(localLink,showStatic); } + virtual Protection protection() const + { return getMdAlias()->protection(); } + virtual Specifier virtualness(int count) const + { return getMdAlias()->virtualness(); } + virtual MemberType memberType() const + { return getMdAlias()->memberType(); } + virtual QCString memberTypeName() const + { return getMdAlias()->memberTypeName(); } + virtual bool isSignal() const + { return getMdAlias()->isSignal(); } + virtual bool isSlot() const + { return getMdAlias()->isSlot(); } + virtual bool isVariable() const + { return getMdAlias()->isVariable(); } + virtual bool isEnumerate() const + { return getMdAlias()->isEnumerate(); } + virtual bool isEnumValue() const + { return getMdAlias()->isEnumValue(); } + virtual bool isTypedef() const + { return getMdAlias()->isTypedef(); } + virtual bool isSequence() const + { return getMdAlias()->isSequence(); } + virtual bool isDictionary() const + { return getMdAlias()->isDictionary(); } + virtual bool isFunction() const + { return getMdAlias()->isFunction(); } + virtual bool isFunctionPtr() const + { return getMdAlias()->isFunctionPtr(); } + virtual bool isDefine() const + { return getMdAlias()->isDefine(); } + virtual bool isFriend() const + { return getMdAlias()->isFriend(); } + virtual bool isDCOP() const + { return getMdAlias()->isDCOP(); } + virtual bool isProperty() const + { return getMdAlias()->isProperty(); } + virtual bool isEvent() const + { return getMdAlias()->isEvent(); } + virtual bool isRelated() const + { return getMdAlias()->isRelated(); } + virtual bool isForeign() const + { return getMdAlias()->isForeign(); } + virtual bool isStatic() const + { return getMdAlias()->isStatic(); } + virtual bool isInline() const + { return getMdAlias()->isInline(); } + virtual bool isExplicit() const + { return getMdAlias()->isExplicit(); } + virtual bool isMutable() const + { return getMdAlias()->isMutable(); } + virtual bool isGettable() const + { return getMdAlias()->isGettable(); } + virtual bool isPrivateGettable() const + { return getMdAlias()->isPrivateGettable(); } + virtual bool isProtectedGettable() const + { return getMdAlias()->isProtectedGettable(); } + virtual bool isSettable() const + { return getMdAlias()->isSettable(); } + virtual bool isPrivateSettable() const + { return getMdAlias()->isPrivateSettable(); } + virtual bool isProtectedSettable() const + { return getMdAlias()->isProtectedSettable(); } + virtual bool isReadable() const + { return getMdAlias()->isReadable(); } + virtual bool isWritable() const + { return getMdAlias()->isWritable(); } + virtual bool isAddable() const + { return getMdAlias()->isAddable(); } + virtual bool isRemovable() const + { return getMdAlias()->isRemovable(); } + virtual bool isRaisable() const + { return getMdAlias()->isRaisable(); } + virtual bool isFinal() const + { return getMdAlias()->isFinal(); } + virtual bool isAbstract() const + { return getMdAlias()->isAbstract(); } + virtual bool isOverride() const + { return getMdAlias()->isOverride(); } + virtual bool isInitonly() const + { return getMdAlias()->isInitonly(); } + virtual bool isOptional() const + { return getMdAlias()->isOptional(); } + virtual bool isRequired() const + { return getMdAlias()->isRequired(); } + virtual bool isNonAtomic() const + { return getMdAlias()->isNonAtomic(); } + virtual bool isCopy() const + { return getMdAlias()->isCopy(); } + virtual bool isAssign() const + { return getMdAlias()->isAssign(); } + virtual bool isRetain() const + { return getMdAlias()->isRetain(); } + virtual bool isWeak() const + { return getMdAlias()->isWeak(); } + virtual bool isStrong() const + { return getMdAlias()->isStrong(); } + virtual bool isUnretained() const + { return getMdAlias()->isUnretained(); } + virtual bool isNew() const + { return getMdAlias()->isNew(); } + virtual bool isSealed() const + { return getMdAlias()->isSealed(); } + virtual bool isImplementation() const + { return getMdAlias()->isImplementation(); } + virtual bool isExternal() const + { return getMdAlias()->isExternal(); } + virtual bool isTypeAlias() const + { return getMdAlias()->isTypeAlias(); } + virtual bool isDefault() const + { return getMdAlias()->isDefault(); } + virtual bool isDelete() const + { return getMdAlias()->isDelete(); } + virtual bool isNoExcept() const + { return getMdAlias()->isNoExcept(); } + virtual bool isAttribute() const + { return getMdAlias()->isAttribute(); } + virtual bool isUNOProperty() const + { return getMdAlias()->isUNOProperty(); } + virtual bool isReadonly() const + { return getMdAlias()->isReadable(); } + virtual bool isBound() const + { return getMdAlias()->isBound(); } + virtual bool isConstrained() const + { return getMdAlias()->isConstrained(); } + virtual bool isTransient() const + { return getMdAlias()->isTransient(); } + virtual bool isMaybeVoid() const + { return getMdAlias()->isMaybeVoid(); } + virtual bool isMaybeDefault() const + { return getMdAlias()->isMaybeDefault(); } + virtual bool isMaybeAmbiguous() const + { return getMdAlias()->isMaybeAmbiguous(); } + virtual bool isPublished() const + { return getMdAlias()->isPublished(); } + virtual bool isTemplateSpecialization() const + { return getMdAlias()->isTemplateSpecialization(); } + virtual bool isObjCMethod() const + { return getMdAlias()->isObjCMethod(); } + virtual bool isObjCProperty() const + { return getMdAlias()->isObjCProperty(); } + virtual bool isConstructor() const + { return getMdAlias()->isConstructor(); } + virtual bool isDestructor() const + { return getMdAlias()->isDestructor(); } + virtual bool hasOneLineInitializer() const + { return getMdAlias()->hasOneLineInitializer(); } + virtual bool hasMultiLineInitializer() const + { return getMdAlias()->hasMultiLineInitializer(); } + virtual bool showInCallGraph() const + { return getMdAlias()->showInCallGraph(); } + virtual bool isStrongEnumValue() const + { return getMdAlias()->isStrongEnumValue(); } + virtual bool livesInsideEnum() const + { return getMdAlias()->livesInsideEnum(); } + virtual bool isSliceLocal() const + { return getMdAlias()->isSliceLocal(); } + virtual bool isConstExpr() const + { return getMdAlias()->isConstExpr(); } + virtual bool isFriendToHide() const + { return getMdAlias()->isFriendToHide(); } + virtual bool isNotFriend() const + { return getMdAlias()->isNotFriend(); } + virtual bool isFunctionOrSignalSlot() const + { return getMdAlias()->isFunctionOrSignalSlot(); } + virtual bool isRelatedOrFriend() const + { return getMdAlias()->isRelatedOrFriend(); } + virtual bool isLinkableInProject() const + { return getMdAlias()->isLinkableInProject(); } + virtual bool isLinkable() const + { return getMdAlias()->isLinkable(); } + virtual bool hasDocumentation() const + { return getMdAlias()->hasDocumentation(); } + virtual bool isDeleted() const + { return getMdAlias()->isDeleted(); } + virtual bool isBriefSectionVisible() const + { return getMdAlias()->isBriefSectionVisible(); } + virtual bool isDetailedSectionVisible(bool inGroup,bool inFile) const + { return getMdAlias()->isDetailedSectionVisible(inGroup,inFile); } + virtual bool isDetailedSectionLinkable() const + { return getMdAlias()->isDetailedSectionLinkable(); } + virtual bool isFriendClass() const + { return getMdAlias()->isFriendClass(); } + virtual bool isDocumentedFriendClass() const + { return getMdAlias()->isDocumentedFriendClass(); } + virtual MemberDef *reimplements() const + { return getMdAlias()->reimplements(); } + virtual MemberList *reimplementedBy() const + { return getMdAlias()->reimplementedBy(); } + virtual bool isReimplementedBy(const ClassDef *cd) const + { return getMdAlias()->isReimplementedBy(cd); } + virtual ClassDef *relatedAlso() const + { return getMdAlias()->relatedAlso(); } + virtual bool hasDocumentedEnumValues() const + { return getMdAlias()->hasDocumentedEnumValues(); } + virtual const MemberDef *getAnonymousEnumType() const + { return getMdAlias()->getAnonymousEnumType(); } + virtual bool isDocsForDefinition() const + { return getMdAlias()->isDocsForDefinition(); } + virtual const MemberDef *getEnumScope() const + { return getMdAlias()->getEnumScope(); } + virtual const MemberList *enumFieldList() const + { return getMdAlias()->enumFieldList(); } + virtual QCString enumBaseType() const + { return getMdAlias()->enumBaseType(); } + virtual bool hasExamples() const + { return getMdAlias()->hasExamples(); } + virtual ExampleSDict *getExamples() const + { return getMdAlias()->getExamples(); } + virtual bool isPrototype() const + { return getMdAlias()->isPrototype(); } + virtual const ArgumentList *argumentList() const + { return getMdAlias()->argumentList(); } + virtual const ArgumentList *declArgumentList() const + { return getMdAlias()->declArgumentList(); } + virtual const ArgumentList *templateArguments() const + { return getMdAlias()->templateArguments(); } + virtual const QList<ArgumentList> *definitionTemplateParameterLists() const + { return getMdAlias()->definitionTemplateParameterLists(); } + virtual int getMemberGroupId() const + { return getMdAlias()->getMemberGroupId(); } + virtual MemberGroup *getMemberGroup() const + { return getMdAlias()->getMemberGroup(); } + virtual bool fromAnonymousScope() const + { return getMdAlias()->fromAnonymousScope(); } + virtual bool anonymousDeclShown() const + { return getMdAlias()->anonymousDeclShown(); } + virtual MemberDef *fromAnonymousMember() const + { return getMdAlias()->fromAnonymousMember(); } + virtual bool hasCallGraph() const + { return getMdAlias()->hasCallGraph(); } + virtual bool hasCallerGraph() const + { return getMdAlias()->hasCallerGraph(); } + virtual bool visibleMemberGroup(bool hideNoHeader) const + { return getMdAlias()->visibleMemberGroup(hideNoHeader); } + virtual bool hasReferencesRelation() const + { return getMdAlias()->hasReferencesRelation(); } + virtual bool hasReferencedByRelation() const + { return getMdAlias()->hasReferencedByRelation(); } + virtual MemberDef *templateMaster() const + { return getMdAlias()->templateMaster(); } + virtual QCString getScopeString() const + { return getMdAlias()->getScopeString(); } + virtual ClassDef *getClassDefOfAnonymousType() const + { return getMdAlias()->getClassDefOfAnonymousType(); } + virtual bool isTypedefValCached() const + { return getMdAlias()->isTypedefValCached(); } + virtual const ClassDef *getCachedTypedefVal() const + { return getMdAlias()->getCachedTypedefVal(); } + virtual QCString getCachedTypedefTemplSpec() const + { return getMdAlias()->getCachedTypedefTemplSpec(); } + virtual QCString getCachedResolvedTypedef() const + { return getMdAlias()->getCachedResolvedTypedef(); } + virtual MemberDef *memberDefinition() const + { return getMdAlias()->memberDefinition(); } + virtual MemberDef *memberDeclaration() const + { return getMdAlias()->memberDeclaration(); } + virtual MemberDef *inheritsDocsFrom() const + { return getMdAlias()->inheritsDocsFrom(); } + virtual const MemberDef *getGroupAlias() const + { return getMdAlias()->getGroupAlias(); } + virtual ClassDef *category() const + { return getMdAlias()->category(); } + virtual MemberDef *categoryRelation() const + { return getMdAlias()->categoryRelation(); } + virtual QCString displayName(bool b=TRUE) const + { return getMdAlias()->displayName(b); } + virtual QCString getDeclType() const + { return getMdAlias()->getDeclType(); } + virtual void getLabels(QStrList &sl,const Definition *container) const + { return getMdAlias()->getLabels(sl,container); } + virtual const ArgumentList *typeConstraints() const + { return getMdAlias()->typeConstraints(); } + virtual QCString documentation() const + { return getMdAlias()->documentation(); } + virtual QCString briefDescription(bool abbr=FALSE) const + { return getMdAlias()->briefDescription(); } + virtual QCString fieldType() const + { return getMdAlias()->fieldType(); } + virtual bool isReference() const + { return getMdAlias()->isReference(); } + virtual QCString getDeclFileName() const + { return getMdAlias()->getDeclFileName(); } + virtual int getDeclLine() const + { return getMdAlias()->getDeclLine(); } + virtual int getDeclColumn() const + { return getMdAlias()->getDeclColumn(); } + + // non-const getters should not be called + virtual ClassDef *getClassDef() + { err("non-const getClassDef() called on aliased member. Please report as a bug.\n"); return 0; } + virtual FileDef *getFileDef() + { err("non-const getFileDef() called on aliased member. Please report as a bug.\n"); return 0; } + virtual NamespaceDef* getNamespaceDef() + { err("non-const getNamespaceDef() called on aliased member. Please report as a bug.\n"); return 0; } + virtual GroupDef *getGroupDef() + { err("non-const getGroupDef() called on aliased member. Please report as a bug.\n"); return 0; } + virtual ArgumentList *argumentList() + { err("non-const argumentList() called on aliased member. Please report as bug.\n"); return 0; } + + virtual void setEnumBaseType(const QCString &type) {} + virtual void setMemberType(MemberType t) {} + virtual void setDefinition(const char *d) {} + virtual void setFileDef(FileDef *fd) {} + virtual void setAnchor() {} + virtual void setProtection(Protection p) {} + virtual void setMemberSpecifiers(uint64 s) {} + virtual void mergeMemberSpecifiers(uint64 s) {} + virtual void setInitializer(const char *i) {} + virtual void setBitfields(const char *s) {} + virtual void setMaxInitLines(int lines) {} + virtual void setMemberClass(ClassDef *cd) {} + virtual void setSectionList(Definition *d,MemberList *sl) {} + virtual void setGroupDef(GroupDef *gd,Grouping::GroupPri_t pri, + const QCString &fileName,int startLine,bool hasDocs, + MemberDef *member=0) {} + virtual void setReadAccessor(const char *r) {} + virtual void setWriteAccessor(const char *w) {} + virtual void setTemplateSpecialization(bool b) {} + virtual void makeRelated() {} + virtual void makeForeign() {} + virtual void setInheritsDocsFrom(MemberDef *md) {} + virtual void setTagInfo(TagInfo *i) {} + virtual void setArgsString(const char *as) {} + virtual void setReimplements(MemberDef *md) {} + virtual void insertReimplementedBy(MemberDef *md) {} + virtual void setRelatedAlso(ClassDef *cd) {} + virtual void insertEnumField(MemberDef *md) {} + virtual void setEnumScope(MemberDef *md,bool livesInsideEnum=FALSE) {} + virtual void setEnumClassScope(ClassDef *cd) {} + virtual void setDocumentedEnumValues(bool value) {} + virtual void setAnonymousEnumType(const MemberDef *md) {} + virtual bool addExample(const char *anchor,const char *name,const char *file) { return FALSE; } + virtual void setPrototype(bool p,const QCString &df,int line, int column) {} + virtual void setExplicitExternal(bool b,const QCString &df,int line,int column) {} + virtual void setDeclFile(const QCString &df,int line,int column) {} + virtual void setArgumentList(ArgumentList *al) {} + virtual void setDeclArgumentList(ArgumentList *al) {} + virtual void setDefinitionTemplateParameterLists(QList<ArgumentList> *lists) {} + virtual void setTypeConstraints(ArgumentList *al) {} + virtual void setType(const char *t) {} + virtual void setAccessorType(ClassDef *cd,const char *t) {} + virtual void setNamespace(NamespaceDef *nd) {} + virtual void setMemberGroup(MemberGroup *grp) {} + virtual void setMemberGroupId(int id) {} + virtual void makeImplementationDetail() {} + virtual void setFromAnonymousScope(bool b) const {} + virtual void setFromAnonymousMember(MemberDef *m) {} + virtual void enableCallGraph(bool e) {} + virtual void enableCallerGraph(bool e) {} + virtual void enableReferencedByRelation(bool e) {} + virtual void enableReferencesRelation(bool e) {} + virtual void setTemplateMaster(MemberDef *mt) {} + virtual void addListReference(Definition *d) {} + virtual void setDocsForDefinition(bool b) {} + virtual void setGroupAlias(const MemberDef *md) {} + virtual void cacheTypedefVal(const ClassDef *val,const QCString &templSpec,const QCString &resolvedType) {} + virtual void invalidateTypedefValCache() {} + virtual void invalidateCachedArgumentTypes() {} + virtual void setMemberDefinition(MemberDef *md) {} + virtual void setMemberDeclaration(MemberDef *md) {} + virtual void setAnonymousUsed() const {} + virtual void copyArgumentNames(MemberDef *bmd) {} + virtual void setCategory(ClassDef *) {} + virtual void setCategoryRelation(MemberDef *) {} + virtual void setDocumentation(const char *d,const char *docFile,int docLine,bool stripWhiteSpace=TRUE) {} + virtual void setBriefDescription(const char *b,const char *briefFile,int briefLine) {} + virtual void setInbodyDocumentation(const char *d,const char *inbodyFile,int inbodyLine) {} + virtual void setHidden(bool b) {} + virtual void addToSearchIndex() const {} + virtual void findSectionsInDocumentation() {} + virtual MemberDef *createTemplateInstanceMember(ArgumentList *formalArgs, + ArgumentList *actualArgs) const + { return getMdAlias()->createTemplateInstanceMember(formalArgs,actualArgs); } + + virtual void writeDeclaration(OutputList &ol, + const ClassDef *cd,const NamespaceDef *nd,const FileDef *fd,const GroupDef *gd, + bool inGroup, const ClassDef *inheritFrom=0,const char *inheritId=0) const + { + getMdAlias()->writeDeclaration(ol,cd,nd,fd,gd,inGroup,inheritFrom,inheritId); + } + virtual void writeEnumDeclaration(OutputList &typeDecl, + const ClassDef *cd,const NamespaceDef *nd,const FileDef *fd,const GroupDef *gd) const + { + getMdAlias()->writeEnumDeclaration(typeDecl,cd,nd,fd,gd); + } + virtual void writeDocumentation(const MemberList *ml,int memCount,int memTotal,OutputList &ol, + const char *scopeName,const Definition *container, + bool inGroup,bool showEnumValues=FALSE,bool + showInline=FALSE) const {} + virtual void writeMemberDocSimple(OutputList &ol,const Definition *container) const {} + virtual void writeLink(OutputList &ol, + const ClassDef *cd,const NamespaceDef *nd,const FileDef *fd,const GroupDef *gd, + bool onlyText=FALSE) const {} + virtual void writeTagFile(FTextStream &) const {} + virtual void warnIfUndocumented() const {} + virtual void warnIfUndocumentedParams() const {} + virtual void detectUndocumentedParams(bool hasParamCommand,bool hasReturnCommand) const {} +}; + + +MemberDef *createMemberDefAlias(const Definition *newScope,const MemberDef *aliasMd) +{ + return new MemberDefAliasImpl(newScope,aliasMd); +} //----------------------------------------------------------------------------- @@ -441,9 +925,9 @@ static QCString addTemplateNames(const QCString &s,const QCString &n,const QCStr // ol.endMemberDoc(hasArgs=FALSE); // -static bool writeDefArgumentList(OutputList &ol,Definition *scope,MemberDef *md) +static bool writeDefArgumentList(OutputList &ol,const Definition *scope,const MemberDef *md) { - ArgumentList *defArgList=(md->isDocsForDefinition()) ? + const ArgumentList *defArgList=(md->isDocsForDefinition()) ? md->argumentList() : md->declArgumentList(); //printf("writeDefArgumentList `%s' isDocsForDefinition()=%d\n",md->name().data(),md->isDocsForDefinition()); if (defArgList==0 || md->isProperty()) @@ -517,9 +1001,9 @@ static bool writeDefArgumentList(OutputList &ol,Definition *scope,MemberDef *md) cName=cName.mid(il,ir-il+1); //printf("1. cName=%s\n",cName.data()); } - else if (scope->definitionType()==Definition::TypeClass && (dynamic_cast<ClassDef*>(scope))->templateArguments()) + else if (scope->definitionType()==Definition::TypeClass && (dynamic_cast<const ClassDef*>(scope))->templateArguments()) { - cName=tempArgListToString((dynamic_cast<ClassDef*>(scope))->templateArguments(),scope->getLanguage()); + cName=tempArgListToString((dynamic_cast<const ClassDef*>(scope))->templateArguments(),scope->getLanguage()); //printf("2. cName=%s\n",cName.data()); } else // no template specifier @@ -712,7 +1196,7 @@ static bool writeDefArgumentList(OutputList &ol,Definition *scope,MemberDef *md) } static void writeExceptionListImpl( - OutputList &ol, ClassDef *cd, MemberDef *md, QCString const& exception) + OutputList &ol, const ClassDef *cd, const MemberDef *md, QCString const& exception) { // this is ordinary exception spec - there must be a '(' //printf("exception='%s'\n",exception.data()); @@ -750,7 +1234,7 @@ static void writeExceptionListImpl( } } -static void writeExceptionList(OutputList &ol, ClassDef *cd, MemberDef *md) +static void writeExceptionList(OutputList &ol, const ClassDef *cd, const MemberDef *md) { QCString exception(QCString(md->excpString()).stripWhiteSpace()); if ('{'==exception.at(0)) @@ -773,7 +1257,7 @@ static void writeExceptionList(OutputList &ol, ClassDef *cd, MemberDef *md) } } -static void writeTemplatePrefix(OutputList &ol,ArgumentList *al) +static void writeTemplatePrefix(OutputList &ol,const ArgumentList *al) { ol.docify("template<"); ArgumentListIterator ali(*al); @@ -816,7 +1300,7 @@ class MemberDefImpl::IMPL MemberDef *enumScope; // the enclosing scope, if this is an enum field bool livesInsideEnum; - MemberDef *annEnumType; // the anonymous enum that is the type of this member + const MemberDef *annEnumType; // the anonymous enum that is the type of this member MemberList *enumFields; // enumeration fields MemberDef *redefines; // the members that this member redefines @@ -870,7 +1354,7 @@ class MemberDefImpl::IMPL // cached here. SDict<MemberList> *classSectionSDict; // not accessible - MemberDef *groupAlias; // Member containing the definition + const MemberDef *groupAlias; // Member containing the definition int grpId; // group id MemberGroup *memberGroup; // group's member definition GroupDef *group; // group in which this member is in @@ -880,7 +1364,7 @@ class MemberDefImpl::IMPL MemberDef *groupMember; bool isTypedefValCached; - ClassDef *cachedTypedefValue; + const ClassDef *cachedTypedefValue; QCString cachedTypedefTemplSpec; QCString cachedResolvedType; @@ -898,15 +1382,17 @@ class MemberDefImpl::IMPL // objective-c bool implOnly; // function found in implementation but not // in the interface - bool hasDocumentedParams; - bool hasDocumentedReturnType; + mutable bool hasDocumentedParams; + mutable bool hasDocumentedReturnType; bool isDMember; Relationship related; // relationship of this to the class bool stat; // is it a static function? bool proto; // is it a prototype; bool docEnumValues; // is an enum with documented enum values. - bool annScope; // member is part of an anonymous scope - bool annUsed; + + mutable bool annScope; // member is part of an anonymous scope + mutable bool annUsed; // ugly: needs to be mutable to allow setAnonymousUsed to act as a + // const member. bool hasCallGraph; bool hasCallerGraph; bool hasReferencedByRelation; @@ -1238,7 +1724,7 @@ MemberList *MemberDefImpl::reimplementedBy() const return m_impl->redefinedBy; } -bool MemberDefImpl::isReimplementedBy(ClassDef *cd) const +bool MemberDefImpl::isReimplementedBy(const ClassDef *cd) const { if (cd && m_impl->redefinedBy) { @@ -1246,7 +1732,7 @@ bool MemberDefImpl::isReimplementedBy(ClassDef *cd) const MemberDef *md; for (mi.toFirst();(md=mi.current());++mi) { - ClassDef *mcd = md->getClassDef(); + const ClassDef *mcd = md->getClassDef(); if (mcd) { if (cd==mcd || cd->isBaseClass(mcd,TRUE)) @@ -1283,7 +1769,7 @@ bool MemberDefImpl::addExample(const char *anchor,const char *nameStr, return FALSE; } -bool MemberDefImpl::hasExamples() +bool MemberDefImpl::hasExamples() const { if (m_impl->exampleSDict==0) return FALSE; @@ -1300,33 +1786,37 @@ QCString MemberDefImpl::getOutputFileBase() const //printf("Member: %s: templateMaster=%p group=%p classDef=%p nspace=%p fileDef=%p\n", // name().data(),m_impl->templateMaster,m_impl->group,m_impl->classDef, // m_impl->nspace,m_impl->fileDef); + const NamespaceDef *nspace = getNamespaceDef(); + const FileDef *fileDef = getFileDef(); + const ClassDef *classDef = getClassDef(); + const GroupDef *groupDef = getGroupDef(); if (!m_impl->explicitOutputFileBase.isEmpty()) { return m_impl->explicitOutputFileBase; } - else if (m_impl->templateMaster) + else if (templateMaster()) { - return m_impl->templateMaster->getOutputFileBase(); + return templateMaster()->getOutputFileBase(); } - else if (m_impl->group) + else if (groupDef) { - baseName=m_impl->group->getOutputFileBase(); + baseName=groupDef->getOutputFileBase(); } - else if (m_impl->classDef) + else if (classDef) { - baseName=m_impl->classDef->getOutputFileBase(); - if (inlineSimpleClasses && m_impl->classDef->isSimple()) + baseName=classDef->getOutputFileBase(); + if (inlineSimpleClasses && classDef->isSimple()) { return baseName; } } - else if (m_impl->nspace && m_impl->nspace->isLinkableInProject()) + else if (nspace && nspace->isLinkableInProject()) { - baseName=m_impl->nspace->getOutputFileBase(); + baseName=nspace->getOutputFileBase(); } - else if (m_impl->fileDef) + else if (fileDef) { - baseName=m_impl->fileDef->getOutputFileBase(); + baseName=fileDef->getOutputFileBase(); } if (baseName.isEmpty()) @@ -1358,25 +1848,29 @@ QCString MemberDefImpl::getReference() const { return ref; } - if (m_impl->templateMaster) + const NamespaceDef *nspace = getNamespaceDef(); + const FileDef *fileDef = getFileDef(); + const ClassDef *classDef = getClassDef(); + const GroupDef *groupDef = getGroupDef(); + if (templateMaster()) { - return m_impl->templateMaster->getReference(); + return templateMaster()->getReference(); } - else if (m_impl->group) + else if (groupDef) { - return m_impl->group->getReference(); + return groupDef->getReference(); } - else if (m_impl->classDef) + else if (classDef) { - return m_impl->classDef->getReference(); + return classDef->getReference(); } - else if (m_impl->nspace) + else if (nspace) { - return m_impl->nspace->getReference(); + return nspace->getReference(); } - else if (m_impl->fileDef) + else if (fileDef) { - return m_impl->fileDef->getReference(); + return fileDef->getReference(); } return ""; } @@ -1390,7 +1884,7 @@ QCString MemberDefImpl::anchor() const { result.prepend(m_impl->enumScope->anchor()); } - if (m_impl->group) + if (getGroupDef()) { if (m_impl->groupMember) { @@ -1416,10 +1910,10 @@ void MemberDefImpl::_computeLinkableInProject() m_isLinkableCached = 1; return; } - if (m_impl->templateMaster) + if (templateMaster()) { //printf("has template master\n"); - m_isLinkableCached = m_impl->templateMaster->isLinkableInProject() ? 2 : 1; + m_isLinkableCached = templateMaster()->isLinkableInProject() ? 2 : 1; return; } if (name().isEmpty() || name().at(0)=='@') @@ -1434,28 +1928,32 @@ void MemberDefImpl::_computeLinkableInProject() m_isLinkableCached = 1; // no documentation return; } - if (m_impl->group && !m_impl->group->isLinkableInProject()) + const GroupDef *groupDef = getGroupDef(); + const ClassDef *classDef = getClassDef(); + if (groupDef && !groupDef->isLinkableInProject()) { //printf("group but group not linkable!\n"); m_isLinkableCached = 1; // group but group not linkable return; } - if (!m_impl->group && m_impl->classDef && !m_impl->classDef->isLinkableInProject()) + if (!groupDef && classDef && !classDef->isLinkableInProject()) { //printf("in a class but class not linkable!\n"); m_isLinkableCached = 1; // in class but class not linkable return; } - if (!m_impl->group && m_impl->nspace && !m_impl->related && !m_impl->nspace->isLinkableInProject() - && (m_impl->fileDef==0 || !m_impl->fileDef->isLinkableInProject())) + const NamespaceDef *nspace = getNamespaceDef(); + const FileDef *fileDef = getFileDef(); + if (!groupDef && nspace && !m_impl->related && !nspace->isLinkableInProject() + && (fileDef==0 || !fileDef->isLinkableInProject())) { //printf("in a namespace but namespace not linkable!\n"); m_isLinkableCached = 1; // in namespace but namespace not linkable return; } - if (!m_impl->group && !m_impl->nspace && - !m_impl->related && !m_impl->classDef && - m_impl->fileDef && !m_impl->fileDef->isLinkableInProject()) + if (!groupDef && !nspace && + !m_impl->related && !classDef && + fileDef && !fileDef->isLinkableInProject()) { //printf("in a file but file not linkable!\n"); m_isLinkableCached = 1; // in file (and not in namespace) but file not linkable @@ -1468,7 +1966,7 @@ void MemberDefImpl::_computeLinkableInProject() m_isLinkableCached = 1; // hidden due to protection return; } - if (m_impl->stat && m_impl->classDef==0 && !extractStatic) + if (m_impl->stat && classDef==0 && !extractStatic) { //printf("static and invisible!\n"); m_isLinkableCached = 1; // hidden due to staticness @@ -1535,26 +2033,29 @@ void MemberDefImpl::setDefinitionTemplateParameterLists(QList<ArgumentList> *lis } } -void MemberDefImpl::writeLink(OutputList &ol,ClassDef *,NamespaceDef *, - FileDef *fd,GroupDef *gd,bool onlyText) +void MemberDefImpl::writeLink(OutputList &ol, + const ClassDef *,const NamespaceDef *,const FileDef *fd,const GroupDef *gd, + bool onlyText) const { SrcLangExt lang = getLanguage(); static bool hideScopeNames = Config_getBool(HIDE_SCOPE_NAMES); QCString sep = getLanguageSpecificSeparator(lang,TRUE); QCString n = name(); + const ClassDef *classDef = getClassDef(); + const NamespaceDef *nspace = getNamespaceDef(); if (!hideScopeNames) { if (m_impl->enumScope && m_impl->livesInsideEnum) { n.prepend(m_impl->enumScope->displayName()+sep); } - if (m_impl->classDef && gd && !isRelated()) + if (classDef && gd && !isRelated()) { - n.prepend(m_impl->classDef->displayName()+sep); + n.prepend(classDef->displayName()+sep); } - else if (m_impl->nspace && (gd || fd)) + else if (nspace && (gd || fd)) { - n.prepend(m_impl->nspace->displayName()+sep); + n.prepend(nspace->displayName()+sep); } } @@ -1567,7 +2068,7 @@ void MemberDefImpl::writeLink(OutputList &ol,ClassDef *,NamespaceDef *, if (m_impl->mtype==MemberType_EnumValue && getGroupDef()==0 && // enum value is not grouped getEnumScope() && getEnumScope()->getGroupDef()) // but its container is { - GroupDef *enumValGroup = getEnumScope()->getGroupDef(); + const GroupDef *enumValGroup = getEnumScope()->getGroupDef(); ol.writeObjectLink(enumValGroup->getReference(), enumValGroup->getOutputFileBase(), anchor(),n); @@ -1588,18 +2089,18 @@ void MemberDefImpl::writeLink(OutputList &ol,ClassDef *,NamespaceDef *, /*! If this member has an anonymous class/struct/union as its type, then * this method will return the ClassDef that describes this return type. */ -ClassDef *MemberDefImpl::getClassDefOfAnonymousType() +ClassDef *MemberDefImpl::getClassDefOfAnonymousType() const { if (m_impl->cachedAnonymousType) return m_impl->cachedAnonymousType; QCString cname; if (getClassDef()!=0) { - cname=getClassDef()->name().copy(); + cname=getClassDef()->name(); } else if (getNamespaceDef()!=0) { - cname=getNamespaceDef()->name().copy(); + cname=getNamespaceDef()->name(); } QCString ltype(m_impl->type); // strip `static' keyword from ltype @@ -1746,7 +2247,7 @@ QCString MemberDefImpl::getDeclType() const { ltype.prepend("typedef "); } - if (isAlias()) + if (isTypeAlias()) { ltype="using"; } @@ -1768,8 +2269,8 @@ QCString MemberDefImpl::getDeclType() const } void MemberDefImpl::writeDeclaration(OutputList &ol, - ClassDef *cd,NamespaceDef *nd,FileDef *fd,GroupDef *gd, - bool inGroup, ClassDef *inheritedFrom,const char *inheritId) + const ClassDef *cd,const NamespaceDef *nd,const FileDef *fd,const GroupDef *gd, + bool inGroup, const ClassDef *inheritedFrom,const char *inheritId) const { //printf("%s MemberDefImpl::writeDeclaration() inGroup=%d\n",qualifiedName().data(),inGroup); @@ -1778,7 +2279,7 @@ void MemberDefImpl::writeDeclaration(OutputList &ol, if (!inGroup && m_impl->mtype==MemberType_EnumValue) return; - Definition *d=0; + const Definition *d=0; ASSERT (cd!=0 || nd!=0 || fd!=0 || gd!=0); // member should belong to something if (cd) d=cd; else if (nd) d=nd; else if (fd) d=fd; else d=gd; if (d==gd) // see bug 753608 @@ -1788,7 +2289,6 @@ void MemberDefImpl::writeDeclaration(OutputList &ol, else if (getFileDef()) d = getFileDef(); } - //_writeTagData(compoundType); addToSearchIndex(); QCString cname = d->name(); @@ -1810,7 +2310,7 @@ void MemberDefImpl::writeDeclaration(OutputList &ol, // If there is no detailed description we need to write the anchor here. bool detailsVisible = isDetailedSectionLinkable(); - bool writeAnchor = (inGroup || m_impl->group==0) && // only write anchors for member that have no details and are + bool writeAnchor = (inGroup || getGroupDef()==0) && // only write anchors for member that have no details and are !detailsVisible && !m_impl->annMemb; // rendered inside the group page or are not grouped at all if (writeAnchor) { @@ -1856,7 +2356,7 @@ void MemberDefImpl::writeDeclaration(OutputList &ol, { ltype.prepend("typedef "); } - if (isAlias()) + if (isTypeAlias()) { ltype="using"; } @@ -1911,7 +2411,7 @@ void MemberDefImpl::writeDeclaration(OutputList &ol, ); getAnonymousEnumType()->writeEnumDeclaration(ol,cd,nd,fd,gd); //ol+=*getAnonymousEnumType()->enumDecl(); - linkifyText(TextGeneratorOLImpl(ol),d,m_impl->fileDef,this,ltype.right(ltype.length()-i-l),TRUE); + linkifyText(TextGeneratorOLImpl(ol),d,getFileDef(),this,ltype.right(ltype.length()-i-l),TRUE); } else { @@ -1978,7 +2478,7 @@ void MemberDefImpl::writeDeclaration(OutputList &ol, if (!(name().isEmpty() || name().at(0)=='@') && // name valid (hasDocumentation() || isReference()) && // has docs !(m_impl->prot==Private && !extractPrivate && (m_impl->virt==Normal || !extractPrivateVirtual) && m_impl->mtype!=MemberType_Friend) && // hidden due to protection - !(isStatic() && m_impl->classDef==0 && !extractStatic) // hidden due to static-ness + !(isStatic() && getClassDef()==0 && !extractStatic) // hidden due to static-ness ) { if (m_impl->annMemb) @@ -1996,8 +2496,8 @@ void MemberDefImpl::writeDeclaration(OutputList &ol, else { //printf("writeLink %s->%d\n",name.data(),hasDocumentation()); - ClassDef *rcd = cd; - if (isReference() && m_impl->classDef) rcd = m_impl->classDef; + const ClassDef *rcd = cd; + if (isReference() && getClassDef()) rcd = getClassDef(); writeLink(ol,rcd,nd,fd,gd); } } @@ -2016,8 +2516,8 @@ void MemberDefImpl::writeDeclaration(OutputList &ol, m_impl->annMemb->setAnonymousUsed(); setAnonymousUsed(); } - ClassDef *rcd = cd; - if (isReference() && m_impl->classDef) rcd = m_impl->classDef; + const ClassDef *rcd = cd; + if (isReference() && getClassDef()) rcd = getClassDef(); writeLink(ol,rcd,nd,fd,gd,TRUE); } } @@ -2090,7 +2590,7 @@ void MemberDefImpl::writeDeclaration(OutputList &ol, linkifyText(TextGeneratorOLImpl(ol),d,getBodyDef(),this,m_impl->initializer); } } - else if (isAlias()) // using template alias + else if (isTypeAlias()) // using template alias { ol.writeString(" = "); linkifyText(TextGeneratorOLImpl(ol),d,getBodyDef(),this,m_impl->type); @@ -2189,18 +2689,7 @@ void MemberDefImpl::writeDeclaration(OutputList &ol, ol.disableAllBut(OutputGenerator::Html); //ol.endEmphasis(); ol.docify(" "); - if (inheritedFrom || - separateMemberPages || - (m_impl->group!=0 && gd==0) || - (m_impl->nspace!=0 && nd==0) - ) // forward link to the page or group or namespace - { - ol.startTextLink(getOutputFileBase(),anchor()); - } - else // local link - { - ol.startTextLink(0,anchor()); - } + ol.startTextLink(getOutputFileBase(),anchor()); ol.parseText(theTranslator->trMore()); ol.endTextLink(); //ol.startEmphasis(); @@ -2271,11 +2760,6 @@ bool MemberDefImpl::isDetailedSectionLinkable() const bool privateFilter = protectionLevelVisible(protection()) || m_impl->mtype==MemberType_Friend || (m_impl->prot==Private && m_impl->virt!=Normal && extractPrivateVirtual); - // member is part of an anonymous scope that is the type of - // another member in the list. - // - //bool inAnonymousScope = !briefDescription().isEmpty() && annUsed; - // hide friend (class|struct|union) member if HIDE_FRIEND_COMPOUNDS // is true bool friendCompoundFilter = !(Config_getBool(HIDE_FRIEND_COMPOUNDS) && @@ -2287,8 +2771,7 @@ bool MemberDefImpl::isDetailedSectionLinkable() const ); - bool result = ((docFilter && staticFilter && privateFilter && friendCompoundFilter && !isHidden())); - //printf("%s::isDetailedSectionLinkable: %d\n",name().data(),result); + bool result = (docFilter && staticFilter && privateFilter && friendCompoundFilter && !isHidden()); return result; } @@ -2310,7 +2793,7 @@ bool MemberDefImpl::isDetailedSectionVisible(bool inGroup,bool inFile) const return result; } -void MemberDefImpl::getLabels(QStrList &sl,Definition *container) const +void MemberDefImpl::getLabels(QStrList &sl,const Definition *container) const { static bool inlineInfo = Config_getBool(INLINE_INFO); @@ -2321,7 +2804,7 @@ void MemberDefImpl::getLabels(QStrList &sl,Definition *container) const (isInline() && inlineInfo) || isSignal() || isSlot() || isStatic() || - (m_impl->classDef && m_impl->classDef!=container && container->definitionType()==TypeClass) || + (getClassDef() && getClassDef()!=container && container->definitionType()==TypeClass) || (m_impl->memSpec & ~Entry::Inline)!=0 ) ) @@ -2412,9 +2895,9 @@ void MemberDefImpl::getLabels(QStrList &sl,Definition *container) const sl.append("implementation"); } } - if (m_impl->classDef && + if (getClassDef() && container->definitionType()==TypeClass && - m_impl->classDef!=container && + getClassDef()!=container && !isRelated() ) { @@ -2428,7 +2911,7 @@ void MemberDefImpl::getLabels(QStrList &sl,Definition *container) const } } -void MemberDefImpl::_writeCallGraph(OutputList &ol) +void MemberDefImpl::_writeCallGraph(OutputList &ol) const { // write call graph if (m_impl->hasCallGraph @@ -2452,7 +2935,7 @@ void MemberDefImpl::_writeCallGraph(OutputList &ol) } } -void MemberDefImpl::_writeCallerGraph(OutputList &ol) +void MemberDefImpl::_writeCallerGraph(OutputList &ol) const { if (m_impl->hasCallerGraph && (isFunction() || isSlot() || isSignal()) && Config_getBool(HAVE_DOT) @@ -2463,7 +2946,7 @@ void MemberDefImpl::_writeCallerGraph(OutputList &ol) { warn_uncond("Caller graph for '%s' not generated, too many nodes. Consider increasing DOT_GRAPH_MAX_NODES.\n",qPrint(qualifiedName())); } - else if (!callerGraph.isTrivial() && !callerGraph.isTooBig()) + else if (!callerGraph.isTrivial()) { msg("Generating caller graph for function %s\n",qPrint(qualifiedName())); ol.disable(OutputGenerator::Man); @@ -2475,10 +2958,10 @@ void MemberDefImpl::_writeCallerGraph(OutputList &ol) } } -void MemberDefImpl::_writeReimplements(OutputList &ol) +void MemberDefImpl::_writeReimplements(OutputList &ol) const { MemberDef *bmd=reimplements(); - ClassDef *bcd=0; + const ClassDef *bcd=0; if (bmd && (bcd=bmd->getClassDef())) { // write class that contains a member that is reimplemented by this one @@ -2534,7 +3017,7 @@ void MemberDefImpl::_writeReimplements(OutputList &ol) } } -void MemberDefImpl::_writeReimplementedBy(OutputList &ol) +void MemberDefImpl::_writeReimplementedBy(OutputList &ol) const { MemberList *bml=reimplementedBy(); if (bml) @@ -2542,7 +3025,7 @@ void MemberDefImpl::_writeReimplementedBy(OutputList &ol) MemberListIterator mli(*bml); MemberDef *bmd=0; uint count=0; - ClassDef *bcd=0; + const ClassDef *bcd=0; for (mli.toFirst();(bmd=mli.current()) && (bcd=bmd->getClassDef());++mli) { // count the members that directly inherit from md and for @@ -2559,7 +3042,7 @@ void MemberDefImpl::_writeReimplementedBy(OutputList &ol) ol.startParagraph(); QCString reimplInLine; - if (m_impl->virt==Pure || (m_impl->classDef && m_impl->classDef->compoundType()==ClassDef::Interface)) + if (m_impl->virt==Pure || (getClassDef() && getClassDef()->compoundType()==ClassDef::Interface)) { reimplInLine = theTranslator->trImplementedInList(count); } @@ -2609,9 +3092,9 @@ void MemberDefImpl::_writeReimplementedBy(OutputList &ol) } } -void MemberDefImpl::_writeCategoryRelation(OutputList &ol) +void MemberDefImpl::_writeCategoryRelation(OutputList &ol) const { - if (m_impl->classDef) // this should be a member of a class/category + if (getClassDef()) // this should be a member of a class/category { //printf("%s: category %s relation %s class=%s categoryOf=%s\n", // name().data(), @@ -2635,12 +3118,12 @@ void MemberDefImpl::_writeCategoryRelation(OutputList &ol) text = theTranslator->trProvidedByCategory(); name = m_impl->category->displayName(); } - else if (m_impl->classDef->categoryOf()) + else if (getClassDef()->categoryOf()) { // this member is part of a category so link to the corresponding class member of the class we extend // so link to method 'categoryRelation' with 'extends class 'classDef->categoryOf()' text = theTranslator->trExtendsClass(); - name = m_impl->classDef->categoryOf()->displayName(); + name = getClassDef()->categoryOf()->displayName(); } i=text.find("@0"); if (i!=-1) @@ -2662,7 +3145,7 @@ void MemberDefImpl::_writeCategoryRelation(OutputList &ol) } } -void MemberDefImpl::_writeExamples(OutputList &ol) +void MemberDefImpl::_writeExamples(OutputList &ol) const { // write the list of examples that use this member if (hasExamples()) @@ -2675,7 +3158,7 @@ void MemberDefImpl::_writeExamples(OutputList &ol) } } -void MemberDefImpl::_writeTypeConstraints(OutputList &ol) +void MemberDefImpl::_writeTypeConstraints(OutputList &ol) const { if (m_impl->typeConstraints) { @@ -2683,15 +3166,15 @@ void MemberDefImpl::_writeTypeConstraints(OutputList &ol) } } -void MemberDefImpl::_writeEnumValues(OutputList &ol,Definition *container, +void MemberDefImpl::_writeEnumValues(OutputList &ol,const Definition *container, const QCString &cfname,const QCString &ciname, - const QCString &cname) + const QCString &cname) const { // For enum, we also write the documented enum values if (isEnumerate()) { bool first=TRUE; - MemberList *fmdl=enumFieldList(); + const MemberList *fmdl=enumFieldList(); //printf("** %s: enum values=%d\n",name().data(),fmdl!=0 ? fmdl->count() : 0); if (fmdl) { @@ -2802,7 +3285,7 @@ QCString MemberDefImpl::displayDefinition() const if (ni>=ei) ei=ni+2; ldef = ldef.left(si) + " { ... } " + ldef.right(ldef.length()-ei); } - ClassDef *cd=getClassDef(); + const ClassDef *cd=getClassDef(); if (cd && cd->isObjectiveC()) { // strip scope name @@ -2840,12 +3323,12 @@ QCString MemberDefImpl::displayDefinition() const return substitute(ldef,"::",sep); } -void MemberDefImpl::_writeGroupInclude(OutputList &ol,bool inGroup) +void MemberDefImpl::_writeGroupInclude(OutputList &ol,bool inGroup) const { // only write out the include file if this is not part of a class or file // definition static bool showGroupedMembInc = Config_getBool(SHOW_GROUPED_MEMB_INC); - FileDef *fd = getFileDef(); + const FileDef *fd = getFileDef(); QCString nm; if (fd) nm = getFileDef()->docName(); if (inGroup && fd && showGroupedMembInc && !nm.isEmpty()) @@ -2884,15 +3367,15 @@ void MemberDefImpl::_writeGroupInclude(OutputList &ol,bool inGroup) /*! Writes the "detailed documentation" section of this member to * all active output formats. */ -void MemberDefImpl::writeDocumentation(MemberList *ml, +void MemberDefImpl::writeDocumentation(const MemberList *ml, int memCount,int memTotal, OutputList &ol, const char *scName, - Definition *container, + const Definition *container, bool inGroup, bool showEnumValues, bool showInline - ) + ) const { // if this member is in a group find the real scope name. bool hasParameterList = FALSE; @@ -2913,13 +3396,13 @@ void MemberDefImpl::writeDocumentation(MemberList *ml, QCString scopeName = scName; QCString memAnchor = anchor(); QCString ciname = container->displayName(); - Definition *scopedContainer = container; // see bug 753608 + const Definition *scopedContainer = container; // see bug 753608 if (container->definitionType()==TypeGroup) { if (getClassDef()) { scopeName=getClassDef()->displayName(); scopedContainer=getClassDef(); } else if (getNamespaceDef()) { scopeName=getNamespaceDef()->displayName(); scopedContainer=getNamespaceDef(); } else if (getFileDef()) { scopeName=getFileDef()->displayName(); scopedContainer=getFileDef(); } - ciname = (dynamic_cast<GroupDef *>(container))->groupTitle(); + ciname = (dynamic_cast<const GroupDef *>(container))->groupTitle(); } else if (container->definitionType()==TypeFile && getNamespaceDef() && lang != SrcLangExt_Python) { // member is in a namespace, but is written as part of the file documentation @@ -3048,8 +3531,8 @@ void MemberDefImpl::writeDocumentation(MemberList *ml, ol.endMemberDocPrefixItem(); } - ClassDef *cd=getClassDef(); - NamespaceDef *nd=getNamespaceDef(); + const ClassDef *cd=getClassDef(); + const NamespaceDef *nd=getNamespaceDef(); if (!Config_getBool(HIDE_SCOPE_NAMES)) { bool first=TRUE; @@ -3163,7 +3646,7 @@ void MemberDefImpl::writeDocumentation(MemberList *ml, ldef.left(pos) ); ol.docify(ldef.mid(pos)); - Definition *scope = cd; + const Definition *scope = cd; if (scope==0) scope = nd; hasParameterList=writeDefArgumentList(ol,scope,this); } @@ -3175,7 +3658,7 @@ void MemberDefImpl::writeDocumentation(MemberList *ml, this, substitute(ldef,"::",sep) ); - Definition *scope = cd; + const Definition *scope = cd; if (scope==0) scope = nd; hasParameterList=writeDefArgumentList(ol,scope,this); } @@ -3276,7 +3759,7 @@ void MemberDefImpl::writeDocumentation(MemberList *ml, ParserInterface *pIntf = Doxygen::parserManager->getParser(getDefFileExtension()); pIntf->resetCodeParserState(); ol.startCodeFragment(); - pIntf->parseCode(ol,scopeName,m_impl->initializer,lang,FALSE,0,getFileDef(), + pIntf->parseCode(ol,scopeName,m_impl->initializer,lang,FALSE,0,const_cast<FileDef*>(getFileDef()), -1,-1,TRUE,this,FALSE,this); ol.endCodeFragment(); } @@ -3475,7 +3958,7 @@ QCString MemberDefImpl::fieldType() const return simplifyTypeForTable(type); } -void MemberDefImpl::writeMemberDocSimple(OutputList &ol, Definition *container) +void MemberDefImpl::writeMemberDocSimple(OutputList &ol, const Definition *container) const { Definition *scope = getOuterScope(); QCString doxyName = name(); @@ -3493,7 +3976,7 @@ void MemberDefImpl::writeMemberDocSimple(OutputList &ol, Definition *container) //printf("===> %s::anonymous: %s\n",name().data(),cd?cd->name().data():"<none>"); if (container && container->definitionType()==Definition::TypeClass && - !(dynamic_cast<ClassDef*>(container))->isJavaEnum()) + !(dynamic_cast<const ClassDef*>(container))->isJavaEnum()) { ol.startInlineMemberType(); ol.startDoxyAnchor(cfname,cname,memAnchor,doxyName,doxyArgs); @@ -3594,17 +4077,17 @@ QCString MemberDefImpl::memberTypeName() const } } -void MemberDefImpl::warnIfUndocumented() +void MemberDefImpl::warnIfUndocumented() const { /* * Removed bug_303020: * if (m_impl->memberGroup) return; */ - ClassDef *cd = getClassDef(); - NamespaceDef *nd = getNamespaceDef(); - FileDef *fd = getFileDef(); - GroupDef *gd = getGroupDef(); - Definition *d=0; + const ClassDef *cd = getClassDef(); + const NamespaceDef *nd = getNamespaceDef(); + const FileDef *fd = getFileDef(); + const GroupDef *gd = getGroupDef(); + const Definition *d=0; const char *t=0; if (cd) t="class", d=cd; @@ -3641,22 +4124,114 @@ void MemberDefImpl::warnIfUndocumented() } } +void MemberDefImpl::detectUndocumentedParams(bool hasParamCommand,bool hasReturnCommand) const +{ + if (!Config_getBool(WARN_NO_PARAMDOC)) return; + QCString returnType = typeString(); + bool isPython = getLanguage()==SrcLangExt_Python; + + if (!m_impl->hasDocumentedParams && hasParamCommand) + { + //printf("%s:hasDocumentedParams=TRUE;\n",name().data()); + m_impl->hasDocumentedParams = TRUE; + } + else if (!m_impl->hasDocumentedParams) + { + const ArgumentList *al = argumentList(); + const ArgumentList *declAl = declArgumentList(); + bool allDoc=TRUE; // no parameter => all parameters are documented + if ( // member has parameters + al!=0 && // but the member has a parameter list + al->count()>0 // with at least one parameter (that is not void) + ) + { + ArgumentListIterator ali(*al); + Argument *a; + + // see if all parameters have documentation + for (ali.toFirst();(a=ali.current()) && allDoc;++ali) + { + if (!a->name.isEmpty() && a->type!="void" && + !(isPython && (a->name=="self" || a->name=="cls")) + ) + { + allDoc = !a->docs.isEmpty(); + } + //printf("a->type=%s a->name=%s doc=%s\n", + // a->type.data(),a->name.data(),a->docs.data()); + } + if (!allDoc && declAl!=0) // try declaration arguments as well + { + allDoc=TRUE; + ArgumentListIterator ali(*declAl); + Argument *a; + for (ali.toFirst();(a=ali.current()) && allDoc;++ali) + { + if (!a->name.isEmpty() && a->type!="void" && + !(isPython && (a->name=="self" || a->name=="cls")) + ) + { + allDoc = !a->docs.isEmpty(); + } + //printf("a->name=%s doc=%s\n",a->name.data(),a->docs.data()); + } + } + } + if (allDoc) + { + //printf("%s:hasDocumentedParams=TRUE;\n",name().data()); + m_impl->hasDocumentedParams = TRUE; + } + } + + //printf("Member %s hasDocumentedReturnType=%d hasReturnCommand=%d\n", + // name().data(),m_impl->hasDocumentedReturnType,hasReturnCommand); + if (!m_impl->hasDocumentedReturnType && // docs not yet found + hasReturnCommand) + { + m_impl->hasDocumentedReturnType = TRUE; + } + else if ( // see if return type is documented in a function w/o return type + hasReturnCommand && + ( + returnType.find("void")!=-1 || // void return type + returnType.find("subroutine")!=-1 || // fortran subroutine + isConstructor() || // a constructor + isDestructor() // or destructor + ) + ) + { + warn_doc_error(getDefFileName(),getDefLine(),"documented empty return type of %s", + qualifiedName().data()); + } + else if ( // see if return needs to documented + m_impl->hasDocumentedReturnType || + returnType.find("void")!=-1 || // void return type + returnType.find("subroutine")!=-1 || // fortran subroutine + isConstructor() || // a constructor + isDestructor() // or destructor + ) + { + m_impl->hasDocumentedReturnType = TRUE; + } +} -void MemberDefImpl::warnIfUndocumentedParams() +void MemberDefImpl::warnIfUndocumentedParams() const { if (!Config_getBool(EXTRACT_ALL) && Config_getBool(WARN_IF_UNDOCUMENTED) && Config_getBool(WARN_NO_PARAMDOC) && + !isDeleted() && !isReference() && !Doxygen::suppressDocWarnings) { - if (!hasDocumentedParams()) + if (!m_impl->hasDocumentedParams) { warn_doc_error(getDefFileName(),getDefLine(), "parameters of member %s are not (all) documented", qPrint(qualifiedName())); } - if (!hasDocumentedReturnType() && + if (!m_impl->hasDocumentedReturnType && isFunction() && hasDocumentation()) { warn_doc_error(getDefFileName(),getDefLine(), @@ -3709,7 +4284,7 @@ void MemberDefImpl::setMemberGroup(MemberGroup *grp) m_impl->memberGroup = grp; } -bool MemberDefImpl::visibleMemberGroup(bool hideNoHeader) +bool MemberDefImpl::visibleMemberGroup(bool hideNoHeader) const { return m_impl->memberGroup!=0 && (!hideNoHeader || m_impl->memberGroup->header()!="[NOHEADER]"); @@ -3821,7 +4396,7 @@ void MemberDefImpl::setNamespace(NamespaceDef *nd) } MemberDef *MemberDefImpl::createTemplateInstanceMember( - ArgumentList *formalArgs,ArgumentList *actualArgs) + ArgumentList *formalArgs,ArgumentList *actualArgs) const { //printf(" Member %s %s %s\n",typeString(),name().data(),argsString()); ArgumentList *actualArgList = 0; @@ -3954,7 +4529,7 @@ void MemberDefImpl::addListReference(Definition *) } } -MemberList *MemberDefImpl::getSectionList(Definition *d) const +const MemberList *MemberDefImpl::getSectionList(const Definition *d) const { char key[20]; sprintf(key,"%p",d); @@ -3993,7 +4568,7 @@ Specifier MemberDefImpl::virtualness(int count) const return v; } -void MemberDefImpl::writeTagFile(FTextStream &tagFile) +void MemberDefImpl::writeTagFile(FTextStream &tagFile) const { if (!isLinkableInProject()) return; tagFile << " <member kind=\""; @@ -4077,7 +4652,7 @@ void MemberDefImpl::writeTagFile(FTextStream &tagFile) void MemberDefImpl::_computeIsConstructor() { m_isConstructorCached=1; // FALSE - if (m_impl->classDef) + if (getClassDef()) { if (m_impl->isDMember) // for D { @@ -4102,7 +4677,7 @@ void MemberDefImpl::_computeIsConstructor() } else // for other languages { - QCString locName = m_impl->classDef->localName(); + QCString locName = getClassDef()->localName(); int i=locName.find('<'); if (i==-1) // not a template class { @@ -4170,7 +4745,7 @@ bool MemberDefImpl::isDestructor() const } void MemberDefImpl::writeEnumDeclaration(OutputList &typeDecl, - ClassDef *cd,NamespaceDef *nd,FileDef *fd,GroupDef *gd) + const ClassDef *cd,const NamespaceDef *nd,const FileDef *fd,const GroupDef *gd) const { int enumMemCount=0; @@ -4387,13 +4962,13 @@ void MemberDefImpl::setInbodyDocumentation(const char *docs, bool MemberDefImpl::isObjCMethod() const { - if (m_impl->classDef && m_impl->classDef->isObjectiveC() && isFunction()) return TRUE; + if (getClassDef() && getClassDef()->isObjectiveC() && isFunction()) return TRUE; return FALSE; } bool MemberDefImpl::isObjCProperty() const { - if (m_impl->classDef && m_impl->classDef->isObjectiveC() && isProperty()) return TRUE; + if (getClassDef() && getClassDef()->isObjectiveC() && isProperty()) return TRUE; return FALSE; } @@ -4404,7 +4979,7 @@ QCString MemberDefImpl::qualifiedName() const QCString qm; if (isStatic()) qm="+"; else qm="-"; qm+="["; - qm+=m_impl->classDef->name()+" "; + qm+=getClassDef()->name()+" "; qm+=name(); qm+="]"; return qm; @@ -4443,7 +5018,7 @@ QCString MemberDefImpl::objCMethodName(bool localLink,bool showStatic) const if (!localLink) // link to method of same class { qm+=" ("; - qm+=m_impl->classDef->name(); + qm+=getClassDef()->name(); qm+=")"; } return qm; @@ -4499,17 +5074,32 @@ uint64 MemberDefImpl::getMemberSpecifiers() const return m_impl->memSpec; } -ClassDef *MemberDefImpl::getClassDef() const +const ClassDef *MemberDefImpl::getClassDef() const +{ + return m_impl->classDef; +} + +ClassDef *MemberDefImpl::getClassDef() { return m_impl->classDef; } -FileDef *MemberDefImpl::getFileDef() const +const FileDef *MemberDefImpl::getFileDef() const +{ + return m_impl->fileDef; +} + +FileDef *MemberDefImpl::getFileDef() { return m_impl->fileDef; } -NamespaceDef* MemberDefImpl::getNamespaceDef() const +const NamespaceDef* MemberDefImpl::getNamespaceDef() const +{ + return m_impl->nspace; +} + +NamespaceDef* MemberDefImpl::getNamespaceDef() { return m_impl->nspace; } @@ -4524,7 +5114,12 @@ const char *MemberDefImpl::getWriteAccessor() const return m_impl->write; } -GroupDef *MemberDefImpl::getGroupDef() const +const GroupDef *MemberDefImpl::getGroupDef() const +{ + return m_impl->group; +} + +GroupDef *MemberDefImpl::getGroupDef() { return m_impl->group; } @@ -4801,7 +5396,7 @@ bool MemberDefImpl::isUnretained() const return (m_impl->memSpec&Entry::Unretained)!=0; } -bool MemberDefImpl::isAlias() const +bool MemberDefImpl::isTypeAlias() const { return (m_impl->memSpec&Entry::Alias)!=0; } @@ -4887,16 +5482,6 @@ bool MemberDefImpl::isTemplateSpecialization() const return m_impl->tspec; } -bool MemberDefImpl::hasDocumentedParams() const -{ - return m_impl->hasDocumentedParams; -} - -bool MemberDefImpl::hasDocumentedReturnType() const -{ - return m_impl->hasDocumentedReturnType; -} - bool MemberDefImpl::showInCallGraph() const { return isFunction() || @@ -4916,7 +5501,7 @@ bool MemberDefImpl::hasDocumentedEnumValues() const return m_impl->docEnumValues; } -MemberDef *MemberDefImpl::getAnonymousEnumType() const +const MemberDef *MemberDefImpl::getAnonymousEnumType() const { return m_impl->annEnumType; } @@ -4926,7 +5511,7 @@ bool MemberDefImpl::isDocsForDefinition() const return m_impl->docsForDefinition; } -MemberDef *MemberDefImpl::getEnumScope() const +const MemberDef *MemberDefImpl::getEnumScope() const { return m_impl->enumScope; } @@ -4946,7 +5531,7 @@ bool MemberDefImpl::isConstExpr() const return (m_impl->memSpec&Entry::ConstExpr)!=0; } -MemberList *MemberDefImpl::enumFieldList() const +const MemberList *MemberDefImpl::enumFieldList() const { return m_impl->enumFields; } @@ -4961,22 +5546,27 @@ bool MemberDefImpl::isPrototype() const return m_impl->proto; } -ArgumentList *MemberDefImpl::argumentList() const +const ArgumentList *MemberDefImpl::argumentList() const +{ + return m_impl->defArgList; +} + +ArgumentList *MemberDefImpl::argumentList() { return m_impl->defArgList; } -ArgumentList *MemberDefImpl::declArgumentList() const +const ArgumentList *MemberDefImpl::declArgumentList() const { return m_impl->declArgList; } -ArgumentList *MemberDefImpl::templateArguments() const +const ArgumentList *MemberDefImpl::templateArguments() const { return m_impl->tArgList; } -QList<ArgumentList> *MemberDefImpl::definitionTemplateParameterLists() const +const QList<ArgumentList> *MemberDefImpl::definitionTemplateParameterLists() const { return m_impl->defTmpArgLists; } @@ -5001,7 +5591,7 @@ bool MemberDefImpl::anonymousDeclShown() const return m_impl->annUsed; } -void MemberDefImpl::setAnonymousUsed() +void MemberDefImpl::setAnonymousUsed() const { m_impl->annUsed = TRUE; } @@ -5036,7 +5626,7 @@ bool MemberDefImpl::isTypedefValCached() const return m_impl->isTypedefValCached; } -ClassDef *MemberDefImpl::getCachedTypedefVal() const +const ClassDef *MemberDefImpl::getCachedTypedefVal() const { return m_impl->cachedTypedefValue; } @@ -5067,7 +5657,7 @@ MemberDef *MemberDefImpl::inheritsDocsFrom() const return m_impl->docProvider; } -MemberDef *MemberDefImpl::getGroupAlias() const +const MemberDef *MemberDefImpl::getGroupAlias() const { return m_impl->groupAlias; } @@ -5165,16 +5755,6 @@ void MemberDefImpl::makeForeign() m_isLinkableCached = 0; } -void MemberDefImpl::setHasDocumentedParams(bool b) -{ - m_impl->hasDocumentedParams = b; -} - -void MemberDefImpl::setHasDocumentedReturnType(bool b) -{ - m_impl->hasDocumentedReturnType = b; -} - void MemberDefImpl::setInheritsDocsFrom(MemberDef *md) { m_impl->docProvider = md; @@ -5202,7 +5782,7 @@ void MemberDefImpl::setDocumentedEnumValues(bool value) m_impl->docEnumValues=value; } -void MemberDefImpl::setAnonymousEnumType(MemberDef *md) +void MemberDefImpl::setAnonymousEnumType(const MemberDef *md) { m_impl->annEnumType = md; } @@ -5251,7 +5831,7 @@ void MemberDefImpl::makeImplementationDetail() m_impl->implOnly=TRUE; } -void MemberDefImpl::setFromAnonymousScope(bool b) +void MemberDefImpl::setFromAnonymousScope(bool b) const { m_impl->annScope=b; } @@ -5277,7 +5857,7 @@ void MemberDefImpl::setDocsForDefinition(bool b) m_impl->docsForDefinition = b; } -void MemberDefImpl::setGroupAlias(MemberDef *md) +void MemberDefImpl::setGroupAlias(const MemberDef *md) { m_impl->groupAlias = md; } @@ -5328,7 +5908,7 @@ QCString MemberDefImpl::enumBaseType() const } -void MemberDefImpl::cacheTypedefVal(ClassDef*val, const QCString & templSpec, const QCString &resolvedType) +void MemberDefImpl::cacheTypedefVal(const ClassDef*val, const QCString & templSpec, const QCString &resolvedType) { m_impl->isTypedefValCached=TRUE; m_impl->cachedTypedefValue=val; @@ -5340,28 +5920,32 @@ void MemberDefImpl::cacheTypedefVal(ClassDef*val, const QCString & templSpec, co void MemberDefImpl::copyArgumentNames(MemberDef *bmd) { { - ArgumentList *arguments = bmd->argumentList(); + const ArgumentList *arguments = bmd->argumentList(); if (m_impl->defArgList && arguments) { ArgumentListIterator aliDst(*m_impl->defArgList); ArgumentListIterator aliSrc(*arguments); - Argument *argDst, *argSrc; + Argument *argDst; + const Argument *argSrc; for (;(argDst=aliDst.current()) && (argSrc=aliSrc.current());++aliDst,++aliSrc) { argDst->name = argSrc->name; + argDst->docs = argSrc->docs; } } } { - ArgumentList *arguments = bmd->declArgumentList(); + const ArgumentList *arguments = bmd->declArgumentList(); if (m_impl->declArgList && arguments) { ArgumentListIterator aliDst(*m_impl->declArgList); ArgumentListIterator aliSrc(*arguments); - Argument *argDst, *argSrc; + Argument *argDst; + const Argument *argSrc; for (;(argDst=aliDst.current()) && (argSrc=aliSrc.current());++aliDst,++aliSrc) { argDst->name = argSrc->name; + argDst->docs = argSrc->docs; } } } @@ -5393,7 +5977,7 @@ QCString MemberDefImpl::displayName(bool) const return DefinitionImpl::name(); } -void MemberDefImpl::addToSearchIndex() +void MemberDefImpl::addToSearchIndex() const { // write search index info if (Doxygen::searchIndex && isLinkableInProject()) @@ -5459,12 +6043,14 @@ void combineDeclarationAndDefinition(MemberDef *mdec,MemberDef *mdef) // mdef, mdef ? mdef->name().data() : "", // mdec, mdec ? mdec->name().data() : ""); + const MemberDef *cmdec = const_cast<const MemberDef*>(mdec); + const MemberDef *cmdef = const_cast<const MemberDef*>(mdef); ArgumentList *mdefAl = mdef->argumentList(); ArgumentList *mdecAl = mdec->argumentList(); - if (matchArguments2(mdef->getOuterScope(),mdef->getFileDef(),mdefAl, - mdec->getOuterScope(),mdec->getFileDef(),mdecAl, - TRUE - ) + if (matchArguments2(cmdef->getOuterScope(),cmdef->getFileDef(),mdefAl, + cmdec->getOuterScope(),cmdec->getFileDef(),mdecAl, + TRUE + ) ) /* match found */ { //printf("Found member %s: definition in %s (doc=`%s') and declaration in %s (doc=`%s')\n", diff --git a/src/memberdef.h b/src/memberdef.h index 555935a..af4fb0a 100644 --- a/src/memberdef.h +++ b/src/memberdef.h @@ -47,6 +47,9 @@ class MemberDef : virtual public Definition // move this member into a different scope virtual MemberDef *deepCopy() const =0; virtual void moveTo(Definition *) = 0; + + virtual MemberDef *resolveAlias() = 0; + virtual const MemberDef *resolveAlias() const = 0; //----------------------------------------------------------------------------------- // ---- getters ----- @@ -67,13 +70,22 @@ class MemberDef : virtual public Definition virtual const QCString &initializer() const = 0; virtual int initializerLines() const = 0; virtual uint64 getMemberSpecifiers() const = 0; - virtual MemberList *getSectionList(Definition *d) const = 0; + virtual const MemberList *getSectionList(const Definition *d) const = 0; virtual QCString displayDefinition() const = 0; // scope query members - virtual ClassDef *getClassDef() const = 0; - virtual FileDef *getFileDef() const = 0; - virtual NamespaceDef* getNamespaceDef() const = 0; + virtual const ClassDef *getClassDef() const = 0; + virtual ClassDef *getClassDef() = 0; + + virtual const FileDef *getFileDef() const = 0; + virtual FileDef *getFileDef() = 0; + + virtual const NamespaceDef* getNamespaceDef() const = 0; + virtual NamespaceDef* getNamespaceDef() = 0; + + virtual const GroupDef *getGroupDef() const = 0; + virtual GroupDef *getGroupDef() = 0; + virtual ClassDef *accessorClass() const = 0; // grabbing the property read/write accessor names @@ -81,7 +93,6 @@ class MemberDef : virtual public Definition virtual const char *getWriteAccessor() const = 0; // querying the grouping definition - virtual GroupDef *getGroupDef() const = 0; virtual Grouping::GroupPri_t getGroupPri() const = 0; virtual const char *getGroupFileName() const = 0; virtual int getGroupStartLine() const = 0; @@ -145,7 +156,7 @@ class MemberDef : virtual public Definition virtual bool isSealed() const = 0; virtual bool isImplementation() const = 0; virtual bool isExternal() const = 0; - virtual bool isAlias() const = 0; + virtual bool isTypeAlias() const = 0; virtual bool isDefault() const = 0; virtual bool isDelete() const = 0; virtual bool isNoExcept() const = 0; @@ -160,8 +171,6 @@ class MemberDef : virtual public Definition virtual bool isMaybeAmbiguous() const = 0; virtual bool isPublished() const = 0; // UNO IDL published virtual bool isTemplateSpecialization() const = 0; - virtual bool hasDocumentedParams() const = 0; - virtual bool hasDocumentedReturnType() const = 0; virtual bool isObjCMethod() const = 0; virtual bool isObjCProperty() const = 0; virtual bool isConstructor() const = 0; @@ -194,27 +203,28 @@ class MemberDef : virtual public Definition virtual MemberDef *reimplements() const = 0; virtual MemberList *reimplementedBy() const = 0; - virtual bool isReimplementedBy(ClassDef *cd) const = 0; + virtual bool isReimplementedBy(const ClassDef *cd) const = 0; virtual ClassDef *relatedAlso() const = 0; virtual bool hasDocumentedEnumValues() const = 0; - virtual MemberDef *getAnonymousEnumType() const = 0; + virtual const MemberDef *getAnonymousEnumType() const = 0; virtual bool isDocsForDefinition() const = 0; - virtual MemberDef *getEnumScope() const = 0; - virtual MemberList *enumFieldList() const = 0; + virtual const MemberDef *getEnumScope() const = 0; + virtual const MemberList *enumFieldList() const = 0; virtual void setEnumBaseType(const QCString &type) = 0; virtual QCString enumBaseType() const = 0; - virtual bool hasExamples() = 0; + virtual bool hasExamples() const = 0; virtual ExampleSDict *getExamples() const = 0; virtual bool isPrototype() const = 0; // argument related members - virtual ArgumentList *argumentList() const = 0; - virtual ArgumentList *declArgumentList() const = 0; - virtual ArgumentList *templateArguments() const = 0; - virtual QList<ArgumentList> *definitionTemplateParameterLists() const = 0; + virtual const ArgumentList *argumentList() const = 0; + virtual ArgumentList *argumentList() = 0; + virtual const ArgumentList *declArgumentList() const = 0; + virtual const ArgumentList *templateArguments() const = 0; + virtual const QList<ArgumentList> *definitionTemplateParameterLists() const = 0; // member group related members virtual int getMemberGroupId() const = 0; @@ -227,32 +237,32 @@ class MemberDef : virtual public Definition // callgraph related members virtual bool hasCallGraph() const = 0; virtual bool hasCallerGraph() const = 0; - virtual bool visibleMemberGroup(bool hideNoHeader) = 0; + virtual bool visibleMemberGroup(bool hideNoHeader) const = 0; // refrenced related members virtual bool hasReferencesRelation() const = 0; virtual bool hasReferencedByRelation() const = 0; virtual MemberDef *templateMaster() const = 0; virtual QCString getScopeString() const = 0; - virtual ClassDef *getClassDefOfAnonymousType() = 0; + virtual ClassDef *getClassDefOfAnonymousType() const = 0; // cached typedef functions virtual bool isTypedefValCached() const = 0; - virtual ClassDef *getCachedTypedefVal() const = 0; + virtual const ClassDef *getCachedTypedefVal() const = 0; virtual QCString getCachedTypedefTemplSpec() const = 0; virtual QCString getCachedResolvedTypedef() const = 0; virtual MemberDef *memberDefinition() const = 0; virtual MemberDef *memberDeclaration() const = 0; virtual MemberDef *inheritsDocsFrom() const = 0; - virtual MemberDef *getGroupAlias() const = 0; + virtual const MemberDef *getGroupAlias() const = 0; virtual ClassDef *category() const = 0; virtual MemberDef *categoryRelation() const = 0; virtual QCString displayName(bool=TRUE) const = 0; virtual QCString getDeclType() const = 0; - virtual void getLabels(QStrList &sl,Definition *container) const = 0; + virtual void getLabels(QStrList &sl,const Definition *container) const = 0; virtual const ArgumentList *typeConstraints() const = 0; @@ -292,8 +302,6 @@ class MemberDef : virtual public Definition virtual void makeRelated() = 0; virtual void makeForeign() = 0; - virtual void setHasDocumentedParams(bool b) = 0; - virtual void setHasDocumentedReturnType(bool b) = 0; virtual void setInheritsDocsFrom(MemberDef *md) = 0; virtual void setTagInfo(TagInfo *i) = 0; virtual void setArgsString(const char *as) = 0; @@ -309,7 +317,7 @@ class MemberDef : virtual public Definition virtual void setEnumScope(MemberDef *md,bool livesInsideEnum=FALSE) = 0; virtual void setEnumClassScope(ClassDef *cd) = 0; virtual void setDocumentedEnumValues(bool value) = 0; - virtual void setAnonymousEnumType(MemberDef *md) = 0; + virtual void setAnonymousEnumType(const MemberDef *md) = 0; // example related members virtual bool addExample(const char *anchor,const char *name,const char *file) = 0; @@ -336,7 +344,6 @@ class MemberDef : virtual public Definition virtual void makeImplementationDetail() = 0; // anonymous scope members - virtual void setFromAnonymousScope(bool b) = 0; virtual void setFromAnonymousMember(MemberDef *m) = 0; virtual void enableCallGraph(bool e) = 0; @@ -348,18 +355,17 @@ class MemberDef : virtual public Definition virtual void setTemplateMaster(MemberDef *mt) = 0; virtual void addListReference(Definition *d) = 0; virtual void setDocsForDefinition(bool b) = 0; - virtual void setGroupAlias(MemberDef *md) = 0; + virtual void setGroupAlias(const MemberDef *md) = 0; - virtual void cacheTypedefVal(ClassDef *val,const QCString &templSpec,const QCString &resolvedType) = 0; + virtual void cacheTypedefVal(const ClassDef *val,const QCString &templSpec,const QCString &resolvedType) = 0; virtual void invalidateTypedefValCache() = 0; virtual void invalidateCachedArgumentTypes() = 0; - + // declaration <-> definition relation virtual void setMemberDefinition(MemberDef *md) = 0; virtual void setMemberDeclaration(MemberDef *md) = 0; - - virtual void setAnonymousUsed() = 0; + virtual void copyArgumentNames(MemberDef *bmd) = 0; virtual void setCategory(ClassDef *) = 0; @@ -375,29 +381,36 @@ class MemberDef : virtual public Definition // --- actions ---- //----------------------------------------------------------------------------------- - // output generation - virtual void writeDeclaration(OutputList &ol, - ClassDef *cd,NamespaceDef *nd,FileDef *fd,GroupDef *gd, - bool inGroup, ClassDef *inheritFrom=0,const char *inheritId=0) = 0; - virtual void writeDocumentation(MemberList *ml,int memCount,int memTotal,OutputList &ol, - const char *scopeName,Definition *container, - bool inGroup,bool showEnumValues=FALSE,bool - showInline=FALSE) = 0; - virtual void writeMemberDocSimple(OutputList &ol,Definition *container) = 0; - virtual void writeEnumDeclaration(OutputList &typeDecl, - ClassDef *cd,NamespaceDef *nd,FileDef *fd,GroupDef *gd) = 0; - virtual void writeTagFile(FTextStream &) = 0; - virtual void warnIfUndocumented() = 0; - virtual void warnIfUndocumentedParams() = 0; - virtual MemberDef *createTemplateInstanceMember(ArgumentList *formalArgs, - ArgumentList *actualArgs) = 0; - + ArgumentList *actualArgs) const = 0; virtual void findSectionsInDocumentation() = 0; + virtual void addToSearchIndex() const = 0; + + //----------------------------------------------------------------------------------- + // --- write output ---- + //----------------------------------------------------------------------------------- + + virtual void writeDeclaration(OutputList &ol, + const ClassDef *cd,const NamespaceDef *nd,const FileDef *fd,const GroupDef *gd, + bool inGroup, const ClassDef *inheritFrom=0,const char *inheritId=0) const = 0; + virtual void writeDocumentation(const MemberList *ml,int memCount,int memTotal,OutputList &ol, + const char *scopeName,const Definition *container, + bool inGroup,bool showEnumValues=FALSE,bool + showInline=FALSE) const = 0; + virtual void writeMemberDocSimple(OutputList &ol,const Definition *container) const = 0; + virtual void writeEnumDeclaration(OutputList &typeDecl, const ClassDef *cd, + const NamespaceDef *nd,const FileDef *fd,const GroupDef *gd) const = 0; + virtual void writeTagFile(FTextStream &) const = 0; virtual void writeLink(OutputList &ol, - ClassDef *cd,NamespaceDef *nd,FileDef *fd,GroupDef *gd, - bool onlyText=FALSE) = 0; - virtual void addToSearchIndex() = 0; + const ClassDef *cd,const NamespaceDef *nd,const FileDef *fd,const GroupDef *gd, + bool onlyText=FALSE) const = 0; + + // write helpers + virtual void warnIfUndocumented() const = 0; + virtual void warnIfUndocumentedParams() const = 0; + virtual void detectUndocumentedParams(bool hasParamCommand,bool hasReturnCommand) const = 0; + virtual void setAnonymousUsed() const = 0; + virtual void setFromAnonymousScope(bool b) const = 0; }; @@ -408,6 +421,8 @@ MemberDef *createMemberDef(const char *defFileName,int defLine,int defColumn, Relationship related,MemberType t,const ArgumentList *tal, const ArgumentList *al,const char *metaData); +MemberDef *createMemberDefAlias(const Definition *newScope,const MemberDef *aliasMd); + void combineDeclarationAndDefinition(MemberDef *mdec,MemberDef *mdef); #endif diff --git a/src/membergroup.cpp b/src/membergroup.cpp index 9c48668..04689b4 100644 --- a/src/membergroup.cpp +++ b/src/membergroup.cpp @@ -40,7 +40,7 @@ MemberGroup::MemberGroup() { } -MemberGroup::MemberGroup(Definition *parent, +MemberGroup::MemberGroup(const Definition *parent, int id,const char *hdr,const char *d,const char *docFile,int docLine) { static bool sortBriefDocs = Config_getBool(SORT_BRIEF_DOCS); @@ -51,7 +51,6 @@ MemberGroup::MemberGroup(Definition *parent, grpId = id; grpHeader = hdr; doc = d; - scope = 0; inSameSection = TRUE; inDeclSection = 0; m_numDecMembers = -1; @@ -86,14 +85,14 @@ void MemberGroup::insertMember(MemberDef *md) } else if (inDeclSection==0) { - inDeclSection = md->getSectionList(m_parent); + inDeclSection = const_cast<MemberList*>(md->getSectionList(m_parent)); //printf("inDeclSection=%p type=%d\n",inDeclSection,inDeclSection->listType()); } memberList->append(md); // copy the group of the first member in the memberGroup GroupDef *gd; - if (firstMd && (gd=firstMd->getGroupDef())) + if (firstMd && (gd=const_cast<GroupDef*>(firstMd->getGroupDef()))) { md->setGroupDef(gd, firstMd->getGroupPri(), firstMd->getGroupFileName(), firstMd->getGroupStartLine(), @@ -109,8 +108,8 @@ void MemberGroup::setAnchors() } void MemberGroup::writeDeclarations(OutputList &ol, - ClassDef *cd,NamespaceDef *nd,FileDef *fd,GroupDef *gd, - bool showInline) + const ClassDef *cd,const NamespaceDef *nd,const FileDef *fd,const GroupDef *gd, + bool showInline) const { //printf("MemberGroup::writeDeclarations() %s\n",grpHeader.data()); QCString ldoc = doc; @@ -119,29 +118,34 @@ void MemberGroup::writeDeclarations(OutputList &ol, } void MemberGroup::writePlainDeclarations(OutputList &ol, - ClassDef *cd,NamespaceDef *nd,FileDef *fd,GroupDef *gd, - ClassDef *inheritedFrom,const char *inheritId - ) + const ClassDef *cd,const NamespaceDef *nd,const FileDef *fd,const GroupDef *gd, + const ClassDef *inheritedFrom,const char *inheritId + ) const { //printf("MemberGroup::writePlainDeclarations() memberList->count()=%d\n",memberList->count()); memberList->writePlainDeclarations(ol,cd,nd,fd,gd,inheritedFrom,inheritId); } void MemberGroup::writeDocumentation(OutputList &ol,const char *scopeName, - Definition *container,bool showEnumValues,bool showInline) + const Definition *container,bool showEnumValues,bool showInline) const { memberList->writeDocumentation(ol,scopeName,container,0,showEnumValues,showInline); } void MemberGroup::writeDocumentationPage(OutputList &ol,const char *scopeName, - Definition *container) + const Definition *container) const { memberList->writeDocumentationPage(ol,scopeName,container); } -void MemberGroup::addGroupedInheritedMembers(OutputList &ol,ClassDef *cd, +void MemberGroup::setAnonymousEnumType() +{ + memberList->setAnonymousEnumType(); +} + +void MemberGroup::addGroupedInheritedMembers(OutputList &ol,const ClassDef *cd, MemberListType lt, - ClassDef *inheritedFrom,const QCString &inheritId) + const ClassDef *inheritedFrom,const QCString &inheritId) const { //printf("** addGroupedInheritedMembers()\n"); MemberListIterator li(*memberList); @@ -149,11 +153,12 @@ void MemberGroup::addGroupedInheritedMembers(OutputList &ol,ClassDef *cd, for (li.toFirst();(md=li.current());++li) { //printf("matching %d == %d\n",lt,md->getSectionList(m_parent)->listType()); - MemberList *ml = md->getSectionList(m_parent); + const MemberList *ml = md->getSectionList(m_parent); if (ml && lt==ml->listType()) { MemberList ml(lt); ml.append(md); + ml.countDecMembers(); ml.writePlainDeclarations(ol,cd,0,0,0,inheritedFrom,inheritId); } } @@ -168,7 +173,7 @@ int MemberGroup::countGroupedInheritedMembers(MemberListType lt) for (li.toFirst();(md=li.current());++li) { //printf("matching %d == %d\n",lt,md->getSectionList(m_parent)->listType()); - MemberList *ml = md->getSectionList(m_parent); + const MemberList *ml = md->getSectionList(m_parent); if (ml && lt==ml->listType()) { count++; @@ -185,33 +190,24 @@ void MemberGroup::addToDeclarationSection() { if (inDeclSection) { - //printf("Adding group %p to list %p (type=%d)\n",this, - // inDeclSection,inDeclSection->listType()); + //printf("Adding group %p to list %p (type=%d) memberList=%p\n",this, + // inDeclSection,inDeclSection->listType(),memberList); inDeclSection->addMemberGroup(this); } } -int MemberGroup::countDecMembers(GroupDef *gd) +void MemberGroup::countDecMembers() { - if (m_numDecMembers==-1) /* number of member not cached */ - { - memberList->countDecMembers(gd); - m_numDecMembers = memberList->numDecMembers(); - } - return m_numDecMembers; + memberList->countDecMembers(); } -int MemberGroup::countDocMembers() +void MemberGroup::countDocMembers() { - if (m_numDocMembers==-1) - { - memberList->countDocMembers(); - m_numDocMembers = memberList->numDocMembers(); - } - return m_numDocMembers; + memberList->countDocMembers(); } -int MemberGroup::countInheritableMembers(ClassDef *inheritedFrom) const + +int MemberGroup::countInheritableMembers(const ClassDef *inheritedFrom) const { return memberList->countInheritableMembers(inheritedFrom); } @@ -255,6 +251,7 @@ void MemberGroup::distributeMemberGroupDocumentation() } } +#if 0 int MemberGroup::varCount() const { return memberList->varCount(); @@ -304,15 +301,26 @@ int MemberGroup::friendCount() const { return memberList->friendCount(); } +#endif -int MemberGroup::numDecMembers() const -{ - return memberList->numDecMembers(); +int MemberGroup::numDecMembers() const +{ + return memberList->numDecMembers(); } -int MemberGroup::numDocMembers() const -{ - return memberList->numDocMembers(); +int MemberGroup::numDecEnumValues() const +{ + return memberList->numDecEnumValues(); +} + +int MemberGroup::numDocMembers() const +{ + return memberList->numDocMembers(); +} + +int MemberGroup::numDocEnumValues() const +{ + return memberList->numDocEnumValues(); } void MemberGroup::setInGroup(bool b) @@ -320,6 +328,7 @@ void MemberGroup::setInGroup(bool b) memberList->setInGroup(b); } + QCString MemberGroup::anchor() const { uchar md5_sig[16]; diff --git a/src/membergroup.h b/src/membergroup.h index 51123bb..c07d025 100644 --- a/src/membergroup.h +++ b/src/membergroup.h @@ -41,7 +41,7 @@ class MemberGroup { public: MemberGroup(); - MemberGroup(Definition *parent,int id,const char *header, + MemberGroup(const Definition *parent,int id,const char *header, const char *docs,const char *docFile,int docLine); ~MemberGroup(); QCString header() const { return grpHeader; } @@ -49,28 +49,30 @@ class MemberGroup void insertMember(MemberDef *md); void setAnchors(); void writePlainDeclarations(OutputList &ol, - ClassDef *cd,NamespaceDef *nd,FileDef *fd,GroupDef *gd, - ClassDef *inheritedFrom,const char *inheritId); + const ClassDef *cd,const NamespaceDef *nd,const FileDef *fd,const GroupDef *gd, + const ClassDef *inheritedFrom,const char *inheritId) const; void writeDeclarations(OutputList &ol, - ClassDef *cd,NamespaceDef *nd,FileDef *fd,GroupDef *gd, - bool showInline=FALSE); + const ClassDef *cd,const NamespaceDef *nd,const FileDef *fd,const GroupDef *gd, + bool showInline=FALSE) const; void writeDocumentation(OutputList &ol,const char *scopeName, - Definition *container,bool showEnumValues,bool showInline); + const Definition *container,bool showEnumValues,bool showInline) const; void writeDocumentationPage(OutputList &ol,const char *scopeName, - Definition *container); + const Definition *container) const; void writeTagFile(FTextStream &); - void addGroupedInheritedMembers(OutputList &ol,ClassDef *cd, + void addGroupedInheritedMembers(OutputList &ol,const ClassDef *cd, MemberListType lt, - ClassDef *inheritedFrom,const QCString &inheritId); + const ClassDef *inheritedFrom,const QCString &inheritId) const; + void setAnonymousEnumType(); const QCString &documentation() const { return doc; } bool allMembersInSameSection() const { return inSameSection; } void addToDeclarationSection(); - int countDecMembers(GroupDef *gd=0); - int countDocMembers(); + void countDecMembers(); + void countDocMembers(); int countGroupedInheritedMembers(MemberListType lt); void distributeMemberGroupDocumentation(); void findSectionsInDocumentation(); + /* int varCount() const; int funcCount() const; int enumCount() const; @@ -81,14 +83,18 @@ class MemberGroup int protoCount() const; int defineCount() const; int friendCount() const; + */ int numDecMembers() const; + int numDecEnumValues() const; int numDocMembers() const; - int countInheritableMembers(ClassDef *inheritedFrom) const; + int numDocEnumValues() const; + + int countInheritableMembers(const ClassDef *inheritedFrom) const; void setInGroup(bool b); void addListReferences(Definition *d); void setRefItems(const QList<ListItemInfo> *sli); MemberList *members() const { return memberList; } - Definition *parent() const { return m_parent; } + const Definition *parent() const { return m_parent; } QCString anchor() const; QCString docFile() const { return m_docFile; } @@ -100,12 +106,11 @@ class MemberGroup int grpId; QCString grpHeader; QCString fileName; // base name of the generated file - Definition *scope; QCString doc; bool inSameSection; int m_numDecMembers; int m_numDocMembers; - Definition *m_parent; + const Definition *m_parent; QCString m_docFile; int m_docLine; QList<ListItemInfo> *m_xrefListItems; diff --git a/src/memberlist.cpp b/src/memberlist.cpp index 418b24a..94bb916 100644 --- a/src/memberlist.cpp +++ b/src/memberlist.cpp @@ -34,19 +34,12 @@ MemberList::MemberList() : m_listType(MemberListType_pubMethods) { + //printf("%p: MemberList::MemberList()\n",this); memberGroupList=0; - m_varCnt=0; - m_funcCnt=0; - m_enumCnt=0; - m_enumValCnt=0; - m_typeCnt=0; - m_seqCnt=0; - m_dictCnt=0; - m_protoCnt=0; - m_defCnt=0; - m_friendCnt=0; m_numDecMembers=-1; // special value indicating that value needs to be computed + m_numDecEnumValues=0; m_numDocMembers=-1; // special value indicating that value needs to be computed + m_numDocEnumValues=0; m_inGroup=FALSE; m_inFile=FALSE; m_needsSorting=FALSE; @@ -54,19 +47,12 @@ MemberList::MemberList() : m_listType(MemberListType_pubMethods) MemberList::MemberList(MemberListType lt) : m_listType(lt) { + //printf("%p: MemberList::MemberList(%d)\n",this,lt); memberGroupList=0; - m_varCnt=0; - m_funcCnt=0; - m_enumCnt=0; - m_enumValCnt=0; - m_typeCnt=0; - m_seqCnt=0; - m_dictCnt=0; - m_protoCnt=0; - m_defCnt=0; - m_friendCnt=0; m_numDecMembers=-1; // special value indicating that value needs to be computed + m_numDecEnumValues=0; m_numDocMembers=-1; // special value indicating that value needs to be computed + m_numDocEnumValues=0; m_inGroup=FALSE; m_inFile=FALSE; m_needsSorting=FALSE; @@ -93,11 +79,11 @@ int MemberList::compareValues(const MemberDef *c1, const MemberDef *c2) const return cmp!=0 ? cmp : c1->getDefLine()-c2->getDefLine(); } -int MemberList::countInheritableMembers(ClassDef *inheritedFrom) const +int MemberList::countInheritableMembers(const ClassDef *inheritedFrom) const { int count=0; QListIterator<MemberDef> mli(*this); - MemberDef *md; + const MemberDef *md; for (mli.toFirst();(md=mli.current());++mli) { if (md->isBriefSectionVisible()) @@ -137,13 +123,15 @@ int MemberList::countInheritableMembers(ClassDef *inheritedFrom) const /*! Count the number of members in this list that are visible in * the declaration part of a compound's documentation page. */ -void MemberList::countDecMembers(bool countEnumValues,GroupDef *gd) +void MemberList::countDecMembers() { - if (m_numDecMembers!=-1) return; - + if (m_numDecMembers!=-1) return; + //printf("----- countDecMembers count=%d ----\n",count()); + /* m_varCnt=m_funcCnt=m_enumCnt=m_enumValCnt=0; m_typeCnt=m_seqCnt=m_dictCnt=m_protoCnt=m_defCnt=m_friendCnt=0; + */ m_numDecMembers=0; QListIterator<MemberDef> mli(*this); MemberDef *md; @@ -156,7 +144,8 @@ void MemberList::countDecMembers(bool countEnumValues,GroupDef *gd) { case MemberType_Variable: // fall through case MemberType_Event: // fall through - case MemberType_Property: m_varCnt++,m_numDecMembers++; + case MemberType_Property: /*m_varCnt++,*/ + m_numDecMembers++; break; // apparently necessary to get this to show up in declarations section? case MemberType_Interface: // fall through @@ -165,23 +154,33 @@ void MemberList::countDecMembers(bool countEnumValues,GroupDef *gd) case MemberType_Signal: // fall through case MemberType_DCOP: // fall through case MemberType_Slot: if (!md->isRelated() || md->getClassDef()) - m_funcCnt++,m_numDecMembers++; + /*m_funcCnt++,*/ + m_numDecMembers++; + break; + case MemberType_Enumeration: /*m_enumCnt++,*/ + m_numDecMembers++; + break; + case MemberType_EnumValue: m_numDecEnumValues++; + m_numDecMembers++; + break; + case MemberType_Typedef: /*m_typeCnt++,*/ + m_numDecMembers++; break; - case MemberType_Enumeration: m_enumCnt++,m_numDecMembers++; break; - case MemberType_EnumValue: if (countEnumValues) - m_enumValCnt++,m_numDecMembers++; + case MemberType_Sequence: /*m_seqCnt++,*/ + m_numDecMembers++; + break; + case MemberType_Dictionary: /*m_dictCnt++,*/ + m_numDecMembers++; break; - case MemberType_Typedef: m_typeCnt++,m_numDecMembers++; break; - case MemberType_Sequence: m_seqCnt++,m_numDecMembers++; break; - case MemberType_Dictionary: m_dictCnt++,m_numDecMembers++; break; //case MemberType_Prototype: m_protoCnt++,m_numDecMembers++; break; - case MemberType_Define: if (Config_getBool(EXTRACT_ALL) || - md->argsString() || + case MemberType_Define: if (Config_getBool(EXTRACT_ALL) || + md->argsString() || !md->initializer().isEmpty() || - md->hasDocumentation() - ) m_defCnt++,m_numDecMembers++; + md->hasDocumentation() + ) /*m_defCnt++,*/ m_numDecMembers++; break; - case MemberType_Friend: m_friendCnt++,m_numDecMembers++; + case MemberType_Friend: /*m_friendCnt++,*/ + m_numDecMembers++; break; default: err("Unknown member type found for member `%s'\n!",md->name().data()); @@ -194,7 +193,8 @@ void MemberList::countDecMembers(bool countEnumValues,GroupDef *gd) MemberGroup *mg; for (;(mg=mgli.current());++mgli) { - mg->countDecMembers(gd); + mg->countDecMembers(); + /* m_varCnt+=mg->varCount(); m_funcCnt+=mg->funcCount(); m_enumCnt+=mg->enumCount(); @@ -205,7 +205,9 @@ void MemberList::countDecMembers(bool countEnumValues,GroupDef *gd) m_protoCnt+=mg->protoCount(); m_defCnt+=mg->defineCount(); m_friendCnt+=mg->friendCount(); + */ m_numDecMembers+=mg->numDecMembers(); + m_numDecEnumValues+=mg->numDecEnumValues(); } } //printf("----- end countDecMembers ----\n"); @@ -213,7 +215,7 @@ void MemberList::countDecMembers(bool countEnumValues,GroupDef *gd) //printf("MemberList::countDecMembers()=%d\n",m_numDecMembers); } -void MemberList::countDocMembers(bool countEnumValues) +void MemberList::countDocMembers() { if (m_numDocMembers!=-1) return; // used cached value m_numDocMembers=0; @@ -221,11 +223,14 @@ void MemberList::countDocMembers(bool countEnumValues) MemberDef *md; for (mli.toFirst();(md=mli.current());++mli) { - if (md->isDetailedSectionVisible(m_inGroup,m_inFile)) + if (md->isDetailedSectionVisible(m_inGroup,m_inFile) && !md->isAlias()) { // do not count enum values, since they do not produce entries of their own - if (countEnumValues || md->memberType()!=MemberType_EnumValue) - m_numDocMembers++; + if (md->memberType()==MemberType_EnumValue) + { + m_numDocEnumValues++; + } + m_numDocMembers++; } } if (memberGroupList) @@ -236,6 +241,7 @@ void MemberList::countDocMembers(bool countEnumValues) { mg->countDocMembers(); m_numDocMembers+=mg->numDocMembers(); + m_numDocEnumValues+=mg->numDocEnumValues(); } } //printf("MemberList::countDocMembers()=%d memberGroupList=%p\n",m_numDocMembers,memberGroupList); @@ -286,36 +292,74 @@ MemberListIterator::MemberListIterator(const MemberList &l) : { } -int MemberList::countEnumValues(MemberDef *md,bool setAnonEnumType) const +void MemberList::setAnonymousEnumType() { - int enumVars=0; + //printf("MemberList(%p)::setAnonymousEnumType()\n",this); + MemberListIterator mli(*this); + const MemberDef *md; + for ( ; (md=mli.current()); ++mli ) + { + if (md->isBriefSectionVisible()) + { + QCString name(md->name()); + int i=name.findRev("::"); + if (i!=-1) name=name.right(name.length()-i-2); + if (md->memberType()==MemberType_Enumeration && name[0]=='@') + { + const MemberList *mfl = md->enumFieldList(); + if (mfl) + { + MemberListIterator vmli(*mfl); + MemberDef *vmd; + for ( ; (vmd=vmli.current()) ; ++vmli) + { + QCString vtype=vmd->typeString(); + if ((vtype.find(name))!=-1) + { + vmd->setAnonymousEnumType(md); + } + } + } + } + } + } + if (memberGroupList) + { + MemberGroupListIterator mgli(*memberGroupList); + MemberGroup *mg; + for (;(mg=mgli.current());++mgli) + { + mg->setAnonymousEnumType(); + } + } +} + +int MemberList::countEnumValues(const MemberDef *md) const +{ + int numEnumValues=0; MemberListIterator vmli(*this); - MemberDef *vmd; + const MemberDef *vmd; QCString name(md->name()); int i=name.findRev("::"); - if (i!=-1) name=name.right(name.length()-i-2); // strip scope (TODO: is this needed?) - if (name[0]=='@') // anonymous enum => append variables + if (i!=-1) name=name.right(name.length()-i-2); + if (name[0]=='@') { for ( ; (vmd=vmli.current()) ; ++vmli) { QCString vtype=vmd->typeString(); - if ((vtype.find(name))!=-1) + if ((vtype.find(name))!=-1) { - enumVars++; - if (setAnonEnumType) - { - vmd->setAnonymousEnumType(md); - } + numEnumValues++; } } } - return enumVars; + return numEnumValues; } bool MemberList::declVisible() const { MemberListIterator mli(*this); - MemberDef *md; + const MemberDef *md; for ( ; (md=mli.current()); ++mli ) { if (md->isBriefSectionVisible()) @@ -340,7 +384,7 @@ bool MemberList::declVisible() const { // if this is an anonymous enum and there are variables of this // enum type (i.e. enumVars>0), then we do not show the enum here. - if (countEnumValues(md,FALSE)==0) // show enum here + if (countEnumValues(md)==0) // show enum here { return TRUE; } @@ -363,14 +407,18 @@ bool MemberList::declVisible() const } void MemberList::writePlainDeclarations(OutputList &ol, - ClassDef *cd,NamespaceDef *nd,FileDef *fd, - GroupDef *gd,ClassDef *inheritedFrom,const char *inheritId - ) + const ClassDef *cd,const NamespaceDef *nd,const FileDef *fd, + const GroupDef *gd,const ClassDef *inheritedFrom,const char *inheritId + ) const { //printf("----- writePlainDeclaration() ----\n"); static bool hideUndocMembers = Config_getBool(HIDE_UNDOC_MEMBERS); - countDecMembers(); - if (numDecMembers()==0) + if (numDecMembers()==-1) + { + err("MemberList::numDecMembers()==-1, so the members of this list have not been counted. Please report as a bug.\n"); + abort(); + } + if (numDecMembers()<=numDecEnumValues()) { //printf(" --> no members!\n"); return; // no members in this list @@ -381,7 +429,7 @@ void MemberList::writePlainDeclarations(OutputList &ol, ol.pushGeneratorState(); bool first=TRUE; - MemberDef *md; + const MemberDef *md; MemberListIterator mli(*this); for ( ; (md=mli.current()); ++mli ) { @@ -416,7 +464,7 @@ void MemberList::writePlainDeclarations(OutputList &ol, { // if this is an anonymous enum and there are variables of this // enum type (i.e. enumVars>0), then we do not show the enum here. - if (countEnumValues(md,TRUE)==0) // show enum here + if (countEnumValues(md)==0) // show enum here { //printf("Enum!!\n"); if (first) @@ -549,9 +597,9 @@ void MemberList::writePlainDeclarations(OutputList &ol, * @param lt Type of list that is inherited from. */ void MemberList::writeDeclarations(OutputList &ol, - ClassDef *cd,NamespaceDef *nd,FileDef *fd,GroupDef *gd, + const ClassDef *cd,const NamespaceDef *nd,const FileDef *fd,const GroupDef *gd, const char *title,const char *subtitle, bool showEnumValues, - bool showInline,ClassDef *inheritedFrom,MemberListType lt) + bool showInline,const ClassDef *inheritedFrom,MemberListType lt) const { (void)showEnumValues; // unused @@ -559,8 +607,7 @@ void MemberList::writeDeclarations(OutputList &ol, static bool optimizeVhdl = Config_getBool(OPTIMIZE_OUTPUT_VHDL); QCString inheritId; - countDecMembers(/*showEnumValues*/FALSE,gd); // count members shown in this section - Definition *ctx = cd; + const Definition *ctx = cd; if (ctx==0 && nd) ctx = nd; if (ctx==0 && gd) ctx = gd; if (ctx==0 && fd) ctx = fd; @@ -569,6 +616,7 @@ void MemberList::writeDeclarations(OutputList &ol, // this,title,subtitle,numDecMembers(),inheritedFrom); int num = numDecMembers(); + int numEnumValues = numDecEnumValues(); if (inheritedFrom) { //if ( cd && !optimizeVhdl && countInheritableMembers(inheritedFrom)>0 ) @@ -588,7 +636,7 @@ void MemberList::writeDeclarations(OutputList &ol, ol.popGeneratorState(); } } - else if (num>0) + else if (num>numEnumValues) { if (title) { @@ -622,7 +670,7 @@ void MemberList::writeDeclarations(OutputList &ol, } } } - if (num>0) + if (num>numEnumValues) { // TODO: Two things need to be worked out for proper VHDL output: // 1. Signals and types under the group need to be @@ -685,13 +733,17 @@ void MemberList::writeDeclarations(OutputList &ol, } void MemberList::writeDocumentation(OutputList &ol, - const char *scopeName, Definition *container, - const char *title,bool showEnumValues,bool showInline) + const char *scopeName, const Definition *container, + const char *title,bool showEnumValues,bool showInline) const { - //printf("MemberList::writeDocumentation()\n"); + if (numDocMembers()==-1) + { + err("MemberList::numDocMembers()==-1, so the members of this list have not been counted. Please report as a bug.\n"); + abort(); + } - countDocMembers(showEnumValues); if (numDocMembers()==0) return; + if (!showEnumValues && numDocMembers()<=numDocEnumValues()) return; if (title) { @@ -706,7 +758,7 @@ void MemberList::writeDocumentation(OutputList &ol, ol.startMemberDocList(); MemberListIterator mli(*this); - MemberDef *md; + const MemberDef *md; // count the number of overloaded members QDict<uint> overloadTotalDict(67); @@ -758,20 +810,19 @@ void MemberList::writeDocumentation(OutputList &ol, // members in a table void MemberList::writeSimpleDocumentation(OutputList &ol, - Definition *container) + const Definition *container) const { - countDocMembers(FALSE); - //printf("MemberList count=%d\n",numDocMembers()); - if (numDocMembers()==0) return; + //printf("MemberList count=%d enumValues=%d\n",numDocMembers(),numDocEnumValues()); + if (numDocMembers()<=numDocEnumValues()) return; // only enum values and they should be excluded - ClassDef *cd = 0; + const ClassDef *cd = 0; if (container && container->definitionType()==Definition::TypeClass) { - cd = dynamic_cast<ClassDef*>(container); + cd = dynamic_cast<const ClassDef*>(container); } ol.startMemberDocSimple(cd && cd->isJavaEnum()); MemberListIterator mli(*this); - MemberDef *md; + const MemberDef *md; for ( ; (md=mli.current()) ; ++mli) { md->writeMemberDocSimple(ol,container); @@ -781,7 +832,7 @@ void MemberList::writeSimpleDocumentation(OutputList &ol, // separate member pages void MemberList::writeDocumentationPage(OutputList &ol, - const char *scopeName, Definition *container) + const char *scopeName, const Definition *container) const { static bool generateTreeView = Config_getBool(GENERATE_TREEVIEW); @@ -791,7 +842,7 @@ void MemberList::writeDocumentationPage(OutputList &ol, overloadTotalDict.setAutoDelete(TRUE); overloadCountDict.setAutoDelete(TRUE); MemberListIterator mli(*this); - MemberDef *md; + const MemberDef *md; for (mli.toFirst() ; (md=mli.current()) ; ++mli) { if (md->isDetailedSectionLinkable()) @@ -882,10 +933,10 @@ void MemberList::addListReferences(Definition *def) MemberDef *md; for ( ; (md=mli.current()) ; ++mli) { - if (md->getGroupDef()==0 || def->definitionType()==Definition::TypeGroup) + if (!md->isAlias() && (md->getGroupDef()==0 || def->definitionType()==Definition::TypeGroup)) { md->addListReference(def); - MemberList *enumFields = md->enumFieldList(); + const MemberList *enumFields = md->enumFieldList(); if (md->memberType()==MemberType_Enumeration && enumFields) { //printf(" Adding enum values!\n"); diff --git a/src/memberlist.h b/src/memberlist.h index f0cc63d..3c227be 100644 --- a/src/memberlist.h +++ b/src/memberlist.h @@ -49,7 +49,7 @@ class MemberList : private QList<MemberDef> MemberDef *getFirst() const; MemberDef *take(uint index); - +/* int varCount() const { ASSERT(m_numDecMembers!=-1); return m_varCnt; } int funcCount() const { ASSERT(m_numDecMembers!=-1); return m_funcCnt; } int enumCount() const { ASSERT(m_numDecMembers!=-1); return m_enumCnt; } @@ -60,25 +60,29 @@ class MemberList : private QList<MemberDef> int protoCount() const { ASSERT(m_numDecMembers!=-1); return m_protoCnt; } int defineCount() const { ASSERT(m_numDecMembers!=-1); return m_defCnt; } int friendCount() const { ASSERT(m_numDecMembers!=-1); return m_friendCnt; } +*/ int numDecMembers() const { ASSERT(m_numDecMembers!=-1); return m_numDecMembers; } + int numDecEnumValues() const { return m_numDecEnumValues; } int numDocMembers() const { ASSERT(m_numDocMembers!=-1); return m_numDocMembers; } + int numDocEnumValues() const { return m_numDocEnumValues; } bool needsSorting() const { return m_needsSorting; } - void countDecMembers(bool countEnumValues=FALSE,GroupDef *gd=0); - void countDocMembers(bool countEnumValues=FALSE); - int countInheritableMembers(ClassDef *inheritedFrom) const; + void countDecMembers(); + void countDocMembers(); + int countInheritableMembers(const ClassDef *inheritedFrom) const; void writePlainDeclarations(OutputList &ol, - ClassDef *cd,NamespaceDef *nd,FileDef *fd, GroupDef *gd, - ClassDef *inheritedFrom,const char *inheritId); + const ClassDef *cd,const NamespaceDef *nd,const FileDef *fd, const GroupDef *gd, + const ClassDef *inheritedFrom,const char *inheritId) const; void writeDeclarations(OutputList &ol, - ClassDef *cd,NamespaceDef *nd,FileDef *fd,GroupDef *gd, + const ClassDef *cd,const NamespaceDef *nd,const FileDef *fd,const GroupDef *gd, const char *title,const char *subtitle, bool showEnumValues=FALSE,bool showInline=FALSE, - ClassDef *inheritedFrom=0,MemberListType lt=MemberListType_pubMethods); + const ClassDef *inheritedFrom=0,MemberListType lt=MemberListType_pubMethods) const; void writeDocumentation(OutputList &ol,const char *scopeName, - Definition *container,const char *title,bool showEnumValues=FALSE,bool showInline=FALSE); - void writeSimpleDocumentation(OutputList &ol,Definition *container); + const Definition *container,const char *title, + bool showEnumValues=FALSE,bool showInline=FALSE) const; + void writeSimpleDocumentation(OutputList &ol,const Definition *container) const; void writeDocumentationPage(OutputList &ol, - const char *scopeName, Definition *container); + const char *scopeName, const Definition *container) const; void writeTagFile(FTextStream &); bool declVisible() const; void addMemberGroup(MemberGroup *mg); @@ -88,22 +92,26 @@ class MemberList : private QList<MemberDef> void findSectionsInDocumentation(); void setNeedsSorting(bool b); MemberGroupList *getMemberGroupList() const { return memberGroupList; } + void setAnonymousEnumType(); private: int compareValues(const MemberDef *item1,const MemberDef *item2) const; - int countEnumValues(MemberDef *md,bool setAnonEnumType) const; + int countEnumValues(const MemberDef *md) const; + /* int m_varCnt; int m_funcCnt; int m_enumCnt; - int m_enumValCnt; int m_typeCnt; int m_seqCnt; int m_dictCnt; int m_protoCnt; int m_defCnt; int m_friendCnt; + */ int m_numDecMembers; // number of members in the brief part of the memberlist + int m_numDecEnumValues; int m_numDocMembers; // number of members in the detailed part of the memberlist + int m_numDocEnumValues; MemberGroupList *memberGroupList; bool m_inGroup; // is this list part of a group definition bool m_inFile; // is this list part of a file definition diff --git a/src/membername.cpp b/src/membername.cpp index a5248c3..72809b3 100644 --- a/src/membername.cpp +++ b/src/membername.cpp @@ -32,10 +32,10 @@ MemberName::~MemberName() int MemberName::compareValues(const MemberDef *m1, const MemberDef *m2) const { - ClassDef *c1=m1->getClassDef(); - ClassDef *c2=m2->getClassDef(); - FileDef *f1=m1->getFileDef(); - FileDef *f2=m2->getFileDef(); + const ClassDef *c1=m1->getClassDef(); + const ClassDef *c2=m2->getClassDef(); + const FileDef *f1=m1->getFileDef(); + const FileDef *f2=m2->getFileDef(); if (c1 && c2) return qstrcmp(c1->name(),c2->name()); else if (f1 && f2) @@ -52,10 +52,10 @@ MemberNameInfo::MemberNameInfo(const char *n) : QList<MemberInfo>() int MemberNameInfo::compareValues(const MemberInfo *m1,const MemberInfo *m2) const { - ClassDef *c1=m1->memberDef->getClassDef(); - ClassDef *c2=m2->memberDef->getClassDef(); - FileDef *f1=m1->memberDef->getFileDef(); - FileDef *f2=m2->memberDef->getFileDef(); + const ClassDef *c1=m1->memberDef->getClassDef(); + const ClassDef *c2=m2->memberDef->getClassDef(); + const FileDef *f1=m1->memberDef->getFileDef(); + const FileDef *f2=m2->memberDef->getFileDef(); if (c1 && c2) return qstrcmp(c1->name(),c2->name()); else if (f1 && f2) diff --git a/src/message.cpp b/src/message.cpp index 2f3a06f..ddf757a 100644 --- a/src/message.cpp +++ b/src/message.cpp @@ -167,17 +167,29 @@ static void format_warn(const char *file,int line,const char *text) static void do_warn(bool enabled, const char *file, int line, const char *prefix, const char *fmt, va_list args) { if (!enabled) return; // warning type disabled - const int bufSize = 40960; - char text[bufSize]; + + va_list argsCopy; + va_copy(argsCopy, args); + int l=0; if (prefix) { - qstrncpy(text,prefix,bufSize); l=strlen(prefix); } - vsnprintf(text+l, bufSize-l, fmt, args); + // determine needed buffersize based on: + // format + arguments + // prefix + // 1 position for `\0` + int bufSize = vsnprintf(NULL, 0, fmt, args) + l + 1; + char *text = (char *)malloc(sizeof(char) * bufSize); + if (prefix) + { + qstrncpy(text,prefix,bufSize); + } + vsnprintf(text+l, bufSize-l, fmt, argsCopy); text[bufSize-1]='\0'; format_warn(file,line,text); + free(text); } void warn(const char *file,int line,const char *fmt, ...) diff --git a/src/msc.cpp b/src/msc.cpp index 29f96ac..0137e1b 100644 --- a/src/msc.cpp +++ b/src/msc.cpp @@ -24,6 +24,7 @@ #include "index.h" #include "util.h" #include "ftextstream.h" +#include "mscgen_api.h" #include <qdir.h> @@ -97,50 +98,38 @@ void writeMscGraphFromFile(const char *inFile,const char *outDir, absOutFile+=portable_pathSeparator(); absOutFile+=outFile; - // chdir to the output dir, so dot can find the font file. - QCString oldDir = QDir::currentDirPath().utf8(); - // go to the html output directory (i.e. path) - QDir::setCurrent(outDir); - //printf("Going to dir %s\n",QDir::currentDirPath().data()); - QCString mscExe = Config_getString(MSCGEN_PATH)+"mscgen"+portable_commandExtension(); - QCString mscArgs; - QCString imgName = outFile; + mscgen_format_t msc_format; + QCString imgName = absOutFile; switch (format) { case MSC_BITMAP: - mscArgs+="-T png"; + msc_format = mscgen_format_png; imgName+=".png"; break; case MSC_EPS: - mscArgs+="-T eps"; + msc_format = mscgen_format_eps; imgName+=".eps"; break; case MSC_SVG: - mscArgs+="-T svg"; + msc_format = mscgen_format_svg; imgName+=".svg"; break; default: - goto error; // I am not very fond of goto statements, but when in Rome... + return; } - mscArgs+=" -i \""; - mscArgs+=inFile; - - mscArgs+="\" -o \""; - mscArgs+=imgName+"\""; - int exitCode; -// printf("*** running: %s %s outDir:%s %s\n",mscExe.data(),mscArgs.data(),outDir,outFile); - portable_sysTimerStart(); - if ((exitCode=portable_system(mscExe,mscArgs,FALSE))!=0) + int code; + if ((code=mscgen_generate(inFile,imgName,msc_format))!=0) { - portable_sysTimerStop(); - goto error; + err("Problems generating msc output (error=%s). Look for typos in you msc file %s\n", + mscgen_error2str(code),inFile); + return; } - portable_sysTimerStop(); + if ( (format==MSC_EPS) && (Config_getBool(USE_PDFLATEX)) ) { QCString epstopdfArgs(maxCmdLine); epstopdfArgs.sprintf("\"%s.eps\" --outfile=\"%s.pdf\"", - outFile,outFile); + absOutFile.data(),absOutFile.data()); portable_sysTimerStart(); if (portable_system("epstopdf",epstopdfArgs)!=0) { @@ -151,45 +140,28 @@ void writeMscGraphFromFile(const char *inFile,const char *outDir, Doxygen::indexList->addImageFile(imgName); -error: - QDir::setCurrent(oldDir); } -QCString getMscImageMapFromFile(const QCString& inFile, const QCString& outDir, - const QCString& relPath,const QCString& context) +static QCString getMscImageMapFromFile(const QCString& inFile, const QCString& outDir, + const QCString& relPath,const QCString& context, + bool writeSVGMap) { QCString outFile = inFile + ".map"; - - //printf("*** running:getMscImageMapFromFile \n"); - // chdir to the output dir, so dot can find the font file. - QCString oldDir = QDir::currentDirPath().utf8(); - // go to the html output directory (i.e. path) - QDir::setCurrent(outDir); - //printf("Going to dir %s\n",QDir::currentDirPath().data()); - - QCString mscExe = Config_getString(MSCGEN_PATH)+"mscgen"+portable_commandExtension(); - QCString mscArgs = "-T ismap -i \""; - mscArgs+=inFile; - mscArgs+="\" -o \""; - mscArgs+=outFile + "\""; - - int exitCode; - portable_sysTimerStart(); - if ((exitCode=portable_system(mscExe,mscArgs,FALSE))!=0) + int code; + if ((code=mscgen_generate(inFile,outFile, + writeSVGMap ? mscgen_format_svgmap : mscgen_format_pngmap))!=0) { - portable_sysTimerStop(); - QDir::setCurrent(oldDir); + err("Problems generating msc output (error=%s). Look for typos in you msc file %s\n", + mscgen_error2str(code),inFile.data()); return ""; } - portable_sysTimerStop(); - + QGString result; FTextStream tmpout(&result); convertMapFile(tmpout, outFile, relPath, context); QDir().remove(outFile); - QDir::setCurrent(oldDir); return result.data(); } @@ -217,7 +189,7 @@ void writeMscImageMapFromFile(FTextStream &t,const QCString &inFile, default: t << "unknown"; } - QCString imap = getMscImageMapFromFile(inFile,outDir,relPath,context); + QCString imap = getMscImageMapFromFile(inFile,outDir,relPath,context,format==MSC_SVG); if (!imap.isEmpty()) { t << "\" alt=\"" diff --git a/src/namespacedef.cpp b/src/namespacedef.cpp index 0740512..1e526ae 100644 --- a/src/namespacedef.cpp +++ b/src/namespacedef.cpp @@ -31,6 +31,7 @@ #include "membergroup.h" #include "config.h" #include "definitionimpl.h" +#include "membername.h" //------------------------------------------------------------------ @@ -48,17 +49,18 @@ class NamespaceDefImpl : public DefinitionImpl, public NamespaceDef virtual void insertUsedFile(FileDef *fd); virtual void writeDocumentation(OutputList &ol); virtual void writeMemberPages(OutputList &ol); - virtual void writeQuickMemberLinks(OutputList &ol,MemberDef *currentMd) const; + virtual void writeQuickMemberLinks(OutputList &ol,const MemberDef *currentMd) const; virtual void writeTagFile(FTextStream &); - virtual void insertClass(ClassDef *cd); - virtual void insertNamespace(NamespaceDef *nd); + virtual void insertClass(const ClassDef *cd); + virtual void insertNamespace(const NamespaceDef *nd); virtual void insertMember(MemberDef *md); virtual void computeAnchors(); - virtual int countMembers(); - virtual void addUsingDirective(NamespaceDef *nd); - virtual NamespaceSDict *getUsedNamespaces() const; - virtual void addUsingDeclaration(Definition *def); - virtual SDict<Definition> *getUsedClasses() const { return usingDeclList; } + virtual void countMembers(); + virtual int numDocMembers() const; + virtual void addUsingDirective(const NamespaceDef *nd); + virtual const NamespaceSDict *getUsedNamespaces() const; + virtual void addUsingDeclaration(const Definition *def); + virtual const SDict<Definition> *getUsedClasses() const { return usingDeclList; } virtual void combineUsingRelations(); virtual QCString displayName(bool=TRUE) const; virtual QCString localName() const; @@ -75,7 +77,7 @@ class NamespaceDefImpl : public DefinitionImpl, public NamespaceDef virtual void findSectionsInDocumentation(); virtual void sortMemberLists(); virtual Definition *findInnerCompound(const char *name) const; - virtual void addInnerCompound(Definition *d); + virtual void addInnerCompound(const Definition *d); virtual void addListReferences(); virtual void setFileName(const QCString &fn); virtual bool subGrouping() const { return m_subGrouping; } @@ -87,7 +89,7 @@ class NamespaceDefImpl : public DefinitionImpl, public NamespaceDef virtual ClassSDict *getInterfaceSDict() const { return interfaceSDict; } virtual ClassSDict *getStructSDict() const { return structSDict; } virtual ClassSDict *getExceptionSDict() const { return exceptionSDict; } - virtual NamespaceSDict *getNamespaceSDict() const { return namespaceSDict; } + virtual const NamespaceSDict *getNamespaceSDict() const { return namespaceSDict; } virtual QCString title() const; virtual QCString compoundTypeString() const; @@ -108,21 +110,22 @@ class NamespaceDefImpl : public DefinitionImpl, public NamespaceDef void endMemberDeclarations(OutputList &ol); void writeClassDeclarations(OutputList &ol,const QCString &title,ClassSDict *d); void writeInlineClasses(OutputList &ol); - void writeNamespaceDeclarations(OutputList &ol,const QCString &title, - bool isConstantGroup=false); void writeMemberGroups(OutputList &ol); void writeAuthorSection(OutputList &ol); void startMemberDocumentation(OutputList &ol); void endMemberDocumentation(OutputList &ol); - void writeSummaryLinks(OutputList &ol); + void writeSummaryLinks(OutputList &ol) const; void addNamespaceAttributes(OutputList &ol); void writeClassesToTagFile(FTextStream &,ClassSDict *d); + void writeNamespaceDeclarations(OutputList &ol,const QCString &title, + bool isConstantGroup=false); + QCString fileName; FileList files; NamespaceSDict *usingDirList; - SDict<Definition> *usingDeclList; + SDict<Definition> *usingDeclList; SDict<Definition> *m_innerCompounds; MemberSDict *m_allMembersDict; @@ -150,6 +153,109 @@ NamespaceDef *createNamespaceDef(const char *defFileName,int defLine,int defColu //------------------------------------------------------------------ +class NamespaceDefAliasImpl : public DefinitionAliasImpl, public NamespaceDef +{ + public: + NamespaceDefAliasImpl(const Definition *newScope,const NamespaceDef *nd) : DefinitionAliasImpl(newScope,nd) {} + virtual ~NamespaceDefAliasImpl() {} + virtual DefType definitionType() const { return TypeNamespace; } + + const NamespaceDef *getNSAlias() const { return dynamic_cast<const NamespaceDef*>(getAlias()); } + + // ---- getters + virtual QCString getOutputFileBase() const + { return getNSAlias()->getOutputFileBase(); } + virtual QCString anchor() const + { return getNSAlias()->anchor(); } + virtual int numDocMembers() const + { return getNSAlias()->numDocMembers(); } + virtual void addUsingDirective(const NamespaceDef *nd) {} + virtual const NamespaceSDict *getUsedNamespaces() const + { return getNSAlias()->getUsedNamespaces(); } + virtual void addUsingDeclaration(const Definition *def) {} + virtual const SDict<Definition> *getUsedClasses() const + { return getNSAlias()->getUsedClasses(); } + virtual void combineUsingRelations() {} + virtual QCString displayName(bool b=TRUE) const + { return getNSAlias()->displayName(b); } + virtual QCString localName() const + { return getNSAlias()->localName(); } + virtual void setInline(bool isInline) { } + virtual bool isConstantGroup() const + { return getNSAlias()->isConstantGroup(); } + virtual bool isModule() const + { return getNSAlias()->isModule(); } + virtual bool isLibrary() const + { return getNSAlias()->isLibrary(); } + virtual bool isInline() const + { return getNSAlias()->isInline(); } + virtual bool isLinkableInProject() const + { return getNSAlias()->isLinkableInProject(); } + virtual bool isLinkable() const + { return getNSAlias()->isLinkable(); } + virtual bool hasDetailedDescription() const + { return getNSAlias()->hasDetailedDescription(); } + virtual Definition *findInnerCompound(const char *name) const + { return getNSAlias()->findInnerCompound(name); } + virtual bool subGrouping() const + { return getNSAlias()->subGrouping(); } + virtual MemberList *getMemberList(MemberListType lt) const + { return getNSAlias()->getMemberList(lt); } + virtual const QList<MemberList> &getMemberLists() const + { return getNSAlias()->getMemberLists(); } + virtual MemberDef *getMemberByName(const QCString &name) const + { return getNSAlias()->getMemberByName(name); } + virtual MemberGroupSDict *getMemberGroupSDict() const + { return getNSAlias()->getMemberGroupSDict(); } + virtual ClassSDict *getClassSDict() const + { return getNSAlias()->getClassSDict(); } + virtual ClassSDict *getInterfaceSDict() const + { return getNSAlias()->getInterfaceSDict(); } + virtual ClassSDict *getStructSDict() const + { return getNSAlias()->getStructSDict(); } + virtual ClassSDict *getExceptionSDict() const + { return getNSAlias()->getExceptionSDict(); } + virtual const NamespaceSDict *getNamespaceSDict() const + { return getNSAlias()->getNamespaceSDict(); } + virtual QCString title() const + { return getNSAlias()->title(); } + virtual QCString compoundTypeString() const + { return getNSAlias()->compoundTypeString(); } + + // --- setters/actions + virtual void setMetaData(const QCString &m) {} + virtual void insertUsedFile(FileDef *fd) { } + virtual void writeDocumentation(OutputList &ol) {} + virtual void writeMemberPages(OutputList &ol) {} + virtual void writeQuickMemberLinks(OutputList &ol,const MemberDef *currentMd) const {} + virtual void writeTagFile(FTextStream &) {} + virtual void insertClass(const ClassDef *cd) {} + virtual void insertNamespace(const NamespaceDef *nd) {} + virtual void insertMember(MemberDef *md) {} + virtual void computeAnchors() {} + virtual void countMembers() {} + virtual void addMembersToMemberGroup() {} + virtual void distributeMemberGroupDocumentation() {} + virtual void findSectionsInDocumentation() {} + virtual void sortMemberLists() {} + virtual void addInnerCompound(const Definition *d) {} + virtual void addListReferences() {} + virtual void setFileName(const QCString &fn) {} + + void setVisited(bool v) { m_visited = v; } + bool isVisited() const { return m_visited; } + + private: + bool m_visited; +}; + +NamespaceDef *createNamespaceDefAlias(const Definition *newScope,const NamespaceDef *nd) +{ + return new NamespaceDefAliasImpl(newScope,nd); +} + +//------------------------------------------------------------------ + NamespaceDefImpl::NamespaceDefImpl(const char *df,int dl,int dc, const char *name,const char *lref, const char *fName, const char*type, @@ -185,6 +291,7 @@ NamespaceDefImpl::NamespaceDefImpl(const char *df,int dl,int dc, memberGroupSDict = new MemberGroupSDict; memberGroupSDict->setAutoDelete(TRUE); m_visited=FALSE; + m_inline=FALSE; m_subGrouping=Config_getBool(SUBGROUPING); if (type && !strcmp("module", type)) { @@ -272,20 +379,20 @@ void NamespaceDefImpl::insertUsedFile(FileDef *fd) } } -void NamespaceDefImpl::addInnerCompound(Definition *d) +void NamespaceDefImpl::addInnerCompound(const Definition *d) { m_innerCompounds->append(d->localName(),d); if (d->definitionType()==Definition::TypeNamespace) { - insertNamespace(dynamic_cast<NamespaceDef *>(d)); + insertNamespace(dynamic_cast<const NamespaceDef *>(d)); } else if (d->definitionType()==Definition::TypeClass) { - insertClass(dynamic_cast<ClassDef *>(d)); + insertClass(dynamic_cast<const ClassDef *>(d)); } } -void NamespaceDefImpl::insertClass(ClassDef *cd) +void NamespaceDefImpl::insertClass(const ClassDef *cd) { ClassSDict *d = classSDict; @@ -318,7 +425,7 @@ void NamespaceDefImpl::insertClass(ClassDef *cd) } } -void NamespaceDefImpl::insertNamespace(NamespaceDef *nd) +void NamespaceDefImpl::insertNamespace(const NamespaceDef *nd) { if (namespaceSDict->find(nd->name())==0) { @@ -360,6 +467,7 @@ void NamespaceDefImpl::addMembersToMemberGroup() void NamespaceDefImpl::insertMember(MemberDef *md) { + //printf("%s::insertMember(%s)\n",qPrint(name()),qPrint(md->name())); if (md->isHidden()) return; MemberList *allMemberList = getMemberList(MemberListType_allMembersList); if (allMemberList==0) @@ -415,6 +523,40 @@ void NamespaceDefImpl::insertMember(MemberDef *md) md->getClassDef() ? md->getClassDef()->name().data() : "", name().data()); } + // if this is an inline namespace, then insert an alias of this member in the outer scope. + if (isInline()) + { + Definition *outerScope = getOuterScope(); + if (outerScope) + { + MemberDef *aliasMd = 0; + if (outerScope->definitionType()==Definition::TypeNamespace) + { + aliasMd = createMemberDefAlias(outerScope,md); + dynamic_cast<NamespaceDef*>(outerScope)->insertMember(aliasMd); + } + else if (outerScope->definitionType()==Definition::TypeFile) + { + aliasMd = createMemberDefAlias(outerScope,md); + dynamic_cast<FileDef*>(outerScope)->insertMember(aliasMd); + } + if (aliasMd) + { + MemberName *mn; + QCString name = md->name(); + if ((mn=Doxygen::functionNameSDict->find(name))) + { + mn->append(aliasMd); + } + else + { + mn = new MemberName(name); + mn->append(aliasMd); + Doxygen::functionNameSDict->append(name,mn); + } + } + } + } } void NamespaceDefImpl::computeAnchors() @@ -582,7 +724,7 @@ void NamespaceDefImpl::writeBriefDescription(OutputList &ol) if (hasDetailedDescription()) { ol.disableAllBut(OutputGenerator::Html); - ol.startTextLink(0,"details"); + ol.startTextLink(getOutputFileBase(),"details"); ol.parseText(theTranslator->trMore()); ol.endTextLink(); } @@ -693,7 +835,7 @@ void NamespaceDefImpl::writeAuthorSection(OutputList &ol) ol.popGeneratorState(); } -void NamespaceDefImpl::writeSummaryLinks(OutputList &ol) +void NamespaceDefImpl::writeSummaryLinks(OutputList &ol) const { ol.pushGeneratorState(); ol.disableAllBut(OutputGenerator::Html); @@ -972,7 +1114,7 @@ void NamespaceDefImpl::writeMemberPages(OutputList &ol) ol.popGeneratorState(); } -void NamespaceDefImpl::writeQuickMemberLinks(OutputList &ol,MemberDef *currentMd) const +void NamespaceDefImpl::writeQuickMemberLinks(OutputList &ol,const MemberDef *currentMd) const { static bool createSubDirs=Config_getBool(CREATE_SUBDIRS); @@ -1015,15 +1157,34 @@ void NamespaceDefImpl::writeQuickMemberLinks(OutputList &ol,MemberDef *currentMd ol.writeString(" </div>\n"); } -int NamespaceDefImpl::countMembers() +void NamespaceDefImpl::countMembers() +{ + QListIterator<MemberList> mli(m_memberLists); + MemberList *ml; + for (mli.toFirst();(ml=mli.current());++mli) + { + ml->countDecMembers(); + ml->countDocMembers(); + } + if (memberGroupSDict) + { + MemberGroupSDict::Iterator mgli(*memberGroupSDict); + MemberGroup *mg; + for (;(mg=mgli.current());++mgli) + { + mg->countDecMembers(); + mg->countDocMembers(); + } + } +} + +int NamespaceDefImpl::numDocMembers() const { MemberList *allMemberList = getMemberList(MemberListType_allMembersList); - if (allMemberList) allMemberList->countDocMembers(); - return (allMemberList ? allMemberList->numDocMembers() : 0) + - classSDict->count() + interfaceSDict->count() + structSDict->count() + exceptionSDict->count(); + return (allMemberList ? allMemberList->numDocMembers() : 0) + m_innerCompounds->count(); } -void NamespaceDefImpl::addUsingDirective(NamespaceDef *nd) +void NamespaceDefImpl::addUsingDirective(const NamespaceDef *nd) { if (usingDirList==0) { @@ -1036,13 +1197,13 @@ void NamespaceDefImpl::addUsingDirective(NamespaceDef *nd) //printf("%p: NamespaceDefImpl::addUsingDirective: %s:%d\n",this,name().data(),usingDirList->count()); } -NamespaceSDict *NamespaceDefImpl::getUsedNamespaces() const +const NamespaceSDict *NamespaceDefImpl::getUsedNamespaces() const { //printf("%p: NamespaceDefImpl::getUsedNamespace: %s:%d\n",this,name().data(),usingDirList?usingDirList->count():0); return usingDirList; } -void NamespaceDefImpl::addUsingDeclaration(Definition *d) +void NamespaceDefImpl::addUsingDeclaration(const Definition *d) { if (usingDeclList==0) { @@ -1297,14 +1458,10 @@ void NamespaceDefImpl::addMemberToList(MemberListType lt,MemberDef *md) ((ml->listType()&MemberListType_documentationLists) && sortMemberDocs)); ml->append(md); -#if 0 - if (ml->needsSorting()) - ml->inSort(md); - else - ml->append(md); -#endif - - if (ml->listType()&MemberListType_declarationLists) md->setSectionList(this,ml); + if (ml->listType()&MemberListType_declarationLists) + { + md->setSectionList(this,ml); + } } void NamespaceDefImpl::sortMemberLists() diff --git a/src/namespacedef.h b/src/namespacedef.h index bfa8c42..3be54f2 100644 --- a/src/namespacedef.h +++ b/src/namespacedef.h @@ -45,19 +45,20 @@ class NamespaceDef : virtual public Definition virtual void writeDocumentation(OutputList &ol) = 0; virtual void writeMemberPages(OutputList &ol) = 0; - virtual void writeQuickMemberLinks(OutputList &ol,MemberDef *currentMd) const = 0; + virtual void writeQuickMemberLinks(OutputList &ol,const MemberDef *currentMd) const = 0; virtual void writeTagFile(FTextStream &) = 0; - virtual void insertClass(ClassDef *cd) = 0; - virtual void insertNamespace(NamespaceDef *nd) = 0; - virtual void insertMember(MemberDef *md) = 0; + virtual void insertClass(const ClassDef *cd) = 0; + virtual void insertNamespace(const NamespaceDef *nd) = 0; + virtual void insertMember(MemberDef *md) = 0; // md cannot be const, since setSectionList is called on it virtual void computeAnchors() = 0; - virtual int countMembers() = 0; - virtual void addUsingDirective(NamespaceDef *nd) = 0; - virtual NamespaceSDict *getUsedNamespaces() const = 0; - virtual void addUsingDeclaration(Definition *def) = 0; - virtual SDict<Definition> *getUsedClasses() const = 0; + virtual void countMembers() = 0; + virtual int numDocMembers() const = 0; + virtual void addUsingDirective(const NamespaceDef *nd) = 0; + virtual const NamespaceSDict *getUsedNamespaces() const = 0; + virtual void addUsingDeclaration(const Definition *def) = 0; + virtual const SDict<Definition> *getUsedClasses() const = 0; virtual void combineUsingRelations() = 0; virtual QCString displayName(bool=TRUE) const = 0; virtual QCString localName() const = 0; @@ -77,7 +78,7 @@ class NamespaceDef : virtual public Definition virtual void sortMemberLists() = 0; virtual Definition *findInnerCompound(const char *name) const = 0; - virtual void addInnerCompound(Definition *d) = 0; + virtual void addInnerCompound(const Definition *d) = 0; virtual void addListReferences() = 0; virtual void setFileName(const QCString &fn) = 0; @@ -103,7 +104,7 @@ class NamespaceDef : virtual public Definition virtual ClassSDict *getExceptionSDict() const = 0; /*! Returns the namespaces contained in this namespace */ - virtual NamespaceSDict *getNamespaceSDict() const = 0; + virtual const NamespaceSDict *getNamespaceSDict() const = 0; virtual QCString title() const = 0; virtual QCString compoundTypeString() const = 0; @@ -119,6 +120,9 @@ NamespaceDef *createNamespaceDef(const char *defFileName,int defLine,int defColu const char *refFile=0,const char*type=0, bool isPublished=false); +/** Factory method to create an alias of an existing namespace. Used for inline namespaces. */ +NamespaceDef *createNamespaceDefAlias(const Definition *newScope, const NamespaceDef *nd); + /** A list of NamespaceDef objects. */ class NamespaceList : public QList<NamespaceDef> { diff --git a/src/outputgen.h b/src/outputgen.h index a99cff3..e302f42 100644 --- a/src/outputgen.h +++ b/src/outputgen.h @@ -124,7 +124,7 @@ class CodeOutputInterface */ virtual void writeCodeAnchor(const char *name) = 0; - virtual void setCurrentDoc(Definition *context,const char *anchor,bool isSourceFile) = 0; + virtual void setCurrentDoc(const Definition *context,const char *anchor,bool isSourceFile) = 0; virtual void addWord(const char *word,bool hiPriority) = 0; }; @@ -346,7 +346,7 @@ class OutputGenerator : public BaseOutputDocInterface //void setEncoding(const QCString &enc) { encoding = enc; } //virtual void postProcess(QByteArray &) { } - virtual void writeDoc(DocNode *,Definition *ctx,MemberDef *md) = 0; + virtual void writeDoc(DocNode *,const Definition *ctx,const MemberDef *md) = 0; /////////////////////////////////////////////////////////////// // structural output interface @@ -428,16 +428,16 @@ class OutputGenerator : public BaseOutputDocInterface virtual void startClassDiagram() = 0; virtual void endClassDiagram(const ClassDiagram &,const char *,const char *) = 0; virtual void startDotGraph() = 0; - virtual void endDotGraph(const DotClassGraph &g) = 0; + virtual void endDotGraph(DotClassGraph &g) = 0; virtual void startInclDepGraph() = 0; - virtual void endInclDepGraph(const DotInclDepGraph &g) = 0; + virtual void endInclDepGraph(DotInclDepGraph &g) = 0; virtual void startGroupCollaboration() = 0; - virtual void endGroupCollaboration(const DotGroupCollaboration &g) = 0; + virtual void endGroupCollaboration(DotGroupCollaboration &g) = 0; virtual void startCallGraph() = 0; - virtual void endCallGraph(const DotCallGraph &g) = 0; + virtual void endCallGraph(DotCallGraph &g) = 0; virtual void startDirDepGraph() = 0; - virtual void endDirDepGraph(const DotDirDeps &g) = 0; - virtual void writeGraphicalHierarchy(const DotGfxHierarchyTable &g) = 0; + virtual void endDirDepGraph(DotDirDeps &g) = 0; + virtual void writeGraphicalHierarchy(DotGfxHierarchyTable &g) = 0; virtual void startQuickIndices() = 0; virtual void endQuickIndices() = 0; virtual void writeSplitBar(const char *) = 0; diff --git a/src/outputlist.cpp b/src/outputlist.cpp index 93a1b6e..0306f94 100644 --- a/src/outputlist.cpp +++ b/src/outputlist.cpp @@ -129,7 +129,7 @@ void OutputList::popGeneratorState() } bool OutputList::generateDoc(const char *fileName,int startLine, - Definition *ctx,MemberDef * md, + const Definition *ctx,const MemberDef * md, const QCString &docStr,bool indexWords, bool isExample,const char *exampleName, bool singleLine,bool linkFromIndex) @@ -159,7 +159,7 @@ bool OutputList::generateDoc(const char *fileName,int startLine, return isEmpty; } -void OutputList::writeDoc(DocRoot *root,Definition *ctx,MemberDef *md) +void OutputList::writeDoc(DocRoot *root,const Definition *ctx,const MemberDef *md) { QListIterator<OutputGenerator> it(m_outputs); OutputGenerator *og; @@ -316,12 +316,12 @@ void OutputList::forall(void (OutputGenerator::*func)(a1,a2,a3,a4,a5,a6,a7,a8),a FORALL1(const char *a1,a1) FORALL1(char a1,a1) FORALL1(int a1,a1) -FORALL1(const DotClassGraph &a1,a1) -FORALL1(const DotInclDepGraph &a1,a1) -FORALL1(const DotCallGraph &a1,a1) -FORALL1(const DotDirDeps &a1,a1) -FORALL1(const DotGfxHierarchyTable &a1,a1) -FORALL1(const DotGroupCollaboration &a1,a1) +FORALL1(DotClassGraph &a1,a1) +FORALL1(DotInclDepGraph &a1,a1) +FORALL1(DotCallGraph &a1,a1) +FORALL1(DotDirDeps &a1,a1) +FORALL1(DotGfxHierarchyTable &a1,a1) +FORALL1(DotGroupCollaboration &a1,a1) FORALL1(SectionTypes a1,a1) #if defined(HAS_BOOL_TYPE) || defined(Q_HAS_BOOL_TYPE) FORALL1(bool a1,a1) @@ -345,7 +345,7 @@ FORALL3(const char *a1,const char *a2,bool a3,a1,a2,a3) FORALL3(const char *a1,int a2,const char *a3,a1,a2,a3) FORALL3(const char *a1,const char *a2,SectionInfo::SectionType a3,a1,a2,a3) FORALL3(uchar a1,uchar a2,uchar a3,a1,a2,a3) -FORALL3(Definition *a1,const char *a2,bool a3,a1,a2,a3) +FORALL3(const Definition *a1,const char *a2,bool a3,a1,a2,a3) FORALL4(SectionTypes a1,const char *a2,const char *a3,const char *a4,a1,a2,a3,a4) FORALL4(const char *a1,const char *a2,const char *a3,const char *a4,a1,a2,a3,a4) FORALL4(const char *a1,const char *a2,const char *a3,int a4,a1,a2,a3,a4) diff --git a/src/outputlist.h b/src/outputlist.h index 5fd8017..35d68a8 100644 --- a/src/outputlist.h +++ b/src/outputlist.h @@ -75,10 +75,10 @@ class OutputList : public OutputDocInterface ////////////////////////////////////////////////// bool generateDoc(const char *fileName,int startLine, - Definition *ctx,MemberDef *md,const QCString &docStr, + const Definition *ctx,const MemberDef *md,const QCString &docStr, bool indexWords,bool isExample,const char *exampleName=0, bool singleLine=FALSE,bool linkFromIndex=FALSE); - void writeDoc(DocRoot *root,Definition *ctx,MemberDef *md); + void writeDoc(DocRoot *root,const Definition *ctx,const MemberDef *md); bool parseText(const QCString &textStr); @@ -391,25 +391,25 @@ class OutputList : public OutputDocInterface { forall(&OutputGenerator::endDescTableData); } void startDotGraph() { forall(&OutputGenerator::startDotGraph); } - void endDotGraph(const DotClassGraph &g) + void endDotGraph(DotClassGraph &g) { forall(&OutputGenerator::endDotGraph,g); } void startInclDepGraph() { forall(&OutputGenerator::startInclDepGraph); } - void endInclDepGraph(const DotInclDepGraph &g) + void endInclDepGraph(DotInclDepGraph &g) { forall(&OutputGenerator::endInclDepGraph,g); } void startCallGraph() { forall(&OutputGenerator::startCallGraph); } - void endCallGraph(const DotCallGraph &g) + void endCallGraph(DotCallGraph &g) { forall(&OutputGenerator::endCallGraph,g); } void startDirDepGraph() { forall(&OutputGenerator::startDirDepGraph); } - void endDirDepGraph(const DotDirDeps &g) + void endDirDepGraph(DotDirDeps &g) { forall(&OutputGenerator::endDirDepGraph,g); } void startGroupCollaboration() { forall(&OutputGenerator::startGroupCollaboration); } - void endGroupCollaboration(const DotGroupCollaboration &g) + void endGroupCollaboration(DotGroupCollaboration &g) { forall(&OutputGenerator::endGroupCollaboration,g); } - void writeGraphicalHierarchy(const DotGfxHierarchyTable &g) + void writeGraphicalHierarchy(DotGfxHierarchyTable &g) { forall(&OutputGenerator::writeGraphicalHierarchy,g); } void startTextBlock(bool dense=FALSE) { forall(&OutputGenerator::startTextBlock,dense); } @@ -487,7 +487,7 @@ class OutputList : public OutputDocInterface { forall(&OutputGenerator::endFontClass); } void writeCodeAnchor(const char *name) { forall(&OutputGenerator::writeCodeAnchor,name); } - void setCurrentDoc(Definition *context,const char *anchor,bool isSourceFile) + void setCurrentDoc(const Definition *context,const char *anchor,bool isSourceFile) { forall(&OutputGenerator::setCurrentDoc,context,anchor,isSourceFile); } void addWord(const char *word,bool hiPriority) { forall(&OutputGenerator::addWord,word,hiPriority); } @@ -520,12 +520,12 @@ class OutputList : public OutputDocInterface FORALLPROTO1(char); FORALLPROTO1(IndexSections); FORALLPROTO1(int); - FORALLPROTO1(const DotClassGraph &); - FORALLPROTO1(const DotInclDepGraph &); - FORALLPROTO1(const DotCallGraph &); - FORALLPROTO1(const DotGroupCollaboration &); - FORALLPROTO1(const DotDirDeps &); - FORALLPROTO1(const DotGfxHierarchyTable &); + FORALLPROTO1(DotClassGraph &); + FORALLPROTO1(DotInclDepGraph &); + FORALLPROTO1(DotCallGraph &); + FORALLPROTO1(DotGroupCollaboration &); + FORALLPROTO1(DotDirDeps &); + FORALLPROTO1(DotGfxHierarchyTable &); FORALLPROTO1(SectionTypes); #if defined(HAS_BOOL_TYPE) || defined(Q_HAS_BOOL_TYPE) FORALLPROTO1(bool); @@ -548,7 +548,7 @@ class OutputList : public OutputDocInterface FORALLPROTO3(uchar,uchar,uchar); FORALLPROTO3(const char *,const char *,const char *); FORALLPROTO3(const ClassDiagram &,const char *,const char *); - FORALLPROTO3(Definition*,const char *,bool); + FORALLPROTO3(const Definition*,const char *,bool); FORALLPROTO4(SectionTypes,const char *,const char *,const char *); FORALLPROTO4(const char *,const char *,const char *,const char *); FORALLPROTO4(const char *,const char *,const char *,bool); diff --git a/src/pagedef.cpp b/src/pagedef.cpp index 8272cf6..9f11eb0 100644 --- a/src/pagedef.cpp +++ b/src/pagedef.cpp @@ -268,16 +268,16 @@ void PageDefImpl::writeDocumentation(OutputList &ol) } writePageDocumentation(ol); + ol.endContents(); ol.endPageDoc(); if (generateTreeView && getOuterScope()!=Doxygen::globalScope && !Config_getBool(DISABLE_INDEX)) { - ol.endContents(); endFileWithNavPath(getOuterScope(),ol); } else { - endFile(ol); + endFile(ol,FALSE,TRUE); } ol.popGeneratorState(); diff --git a/src/parserintf.h b/src/parserintf.h index 0942106..f03aac7 100644 --- a/src/parserintf.h +++ b/src/parserintf.h @@ -110,9 +110,9 @@ class ParserInterface int startLine=-1, int endLine=-1, bool inlineFragment=FALSE, - MemberDef *memberDef=0, + const MemberDef *memberDef=0, bool showLineNumbers=TRUE, - Definition *searchCtx=0, + const Definition *searchCtx=0, bool collectXRefs=TRUE ) = 0; diff --git a/src/perlmodgen.cpp b/src/perlmodgen.cpp index 1ec4bf3..7a804b1 100644 --- a/src/perlmodgen.cpp +++ b/src/perlmodgen.cpp @@ -388,8 +388,6 @@ public: void visitPost(DocXRefItem *); void visitPre(DocInternalRef *); void visitPost(DocInternalRef *); - void visitPre(DocCopy *); - void visitPost(DocCopy *); void visitPre(DocText *); void visitPost(DocText *); void visitPre(DocHtmlBlockQuote *); @@ -1385,14 +1383,6 @@ void PerlModDocVisitor::visitPost(DocInternalRef *) closeItem(); } -void PerlModDocVisitor::visitPre(DocCopy *) -{ -} - -void PerlModDocVisitor::visitPost(DocCopy *) -{ -} - void PerlModDocVisitor::visitPre(DocText *) { } @@ -1462,7 +1452,7 @@ static void addMemberTemplateLists(MemberDef *md,PerlModOutput &output) } #endif -static void addTemplateList(ClassDef *cd,PerlModOutput &output) +static void addTemplateList(const ClassDef *cd,PerlModOutput &output) { addTemplateArgumentList(cd->templateArguments(),output,cd->name()); } @@ -1471,8 +1461,8 @@ static void addPerlModDocBlock(PerlModOutput &output, const char *name, const QCString &fileName, int lineNr, - Definition *scope, - MemberDef *md, + const Definition *scope, + const MemberDef *md, const QCString &text) { QCString stext = text.stripWhiteSpace(); @@ -1543,14 +1533,14 @@ public: inline PerlModGenerator(bool pretty) : m_output(pretty) { } - void generatePerlModForMember(MemberDef *md, Definition *); - void generatePerlModSection(Definition *d, MemberList *ml, + void generatePerlModForMember(const MemberDef *md, const Definition *); + void generatePerlModSection(const Definition *d, MemberList *ml, const char *name, const char *header=0); - void addListOfAllMembers(ClassDef *cd); - void generatePerlModForClass(ClassDef *cd); - void generatePerlModForNamespace(NamespaceDef *nd); - void generatePerlModForFile(FileDef *fd); - void generatePerlModForGroup(GroupDef *gd); + void addListOfAllMembers(const ClassDef *cd); + void generatePerlModForClass(const ClassDef *cd); + void generatePerlModForNamespace(const NamespaceDef *nd); + void generatePerlModForFile(const FileDef *fd); + void generatePerlModForGroup(const GroupDef *gd); void generatePerlModForPage(PageDef *pi); bool createOutputFile(QFile &f, const char *s); @@ -1567,7 +1557,7 @@ public: void generate(); }; -void PerlModGenerator::generatePerlModForMember(MemberDef *md,Definition *) +void PerlModGenerator::generatePerlModForMember(const MemberDef *md,const Definition *) { // + declaration/definition arg lists // + reimplements @@ -1617,23 +1607,23 @@ void PerlModGenerator::generatePerlModForMember(MemberDef *md,Definition *) md->memberType()!=MemberType_Enumeration) m_output.addFieldQuotedString("type", md->typeString()); - ArgumentList *al = md->argumentList(); + const ArgumentList *al = md->argumentList(); if (isFunc) //function { m_output.addFieldBoolean("const", al!=0 && al->constSpecifier) .addFieldBoolean("volatile", al!=0 && al->volatileSpecifier); m_output.openList("parameters"); - ArgumentList *declAl = md->declArgumentList(); - ArgumentList *defAl = md->argumentList(); + const ArgumentList *declAl = md->declArgumentList(); + const ArgumentList *defAl = md->argumentList(); if (declAl && defAl && declAl->count()>0) { ArgumentListIterator declAli(*declAl); ArgumentListIterator defAli(*defAl); - Argument *a; + const Argument *a; for (declAli.toFirst();(a=declAli.current());++declAli) { - Argument *defArg = defAli.current(); + const Argument *defArg = defAli.current(); m_output.openHash(); if (!a->name.isEmpty()) @@ -1665,7 +1655,7 @@ void PerlModGenerator::generatePerlModForMember(MemberDef *md,Definition *) { m_output.openList("parameters"); ArgumentListIterator ali(*al); - Argument *a; + const Argument *a; for (ali.toFirst();(a=ali.current());++ali) { m_output.openHash() @@ -1687,12 +1677,12 @@ void PerlModGenerator::generatePerlModForMember(MemberDef *md,Definition *) if (md->memberType()==MemberType_Enumeration) // enum { - MemberList *enumFields = md->enumFieldList(); + const MemberList *enumFields = md->enumFieldList(); if (enumFields) { m_output.openList("values"); MemberListIterator emli(*enumFields); - MemberDef *emd; + const MemberDef *emd; for (emli.toFirst();(emd=emli.current());++emli) { m_output.openHash() @@ -1711,7 +1701,7 @@ void PerlModGenerator::generatePerlModForMember(MemberDef *md,Definition *) } } - MemberDef *rmd = md->reimplements(); + const MemberDef *rmd = md->reimplements(); if (rmd) m_output.openHash("reimplements") .addFieldQuotedString("name", rmd->name()) @@ -1732,7 +1722,7 @@ void PerlModGenerator::generatePerlModForMember(MemberDef *md,Definition *) m_output.closeHash(); } -void PerlModGenerator::generatePerlModSection(Definition *d, +void PerlModGenerator::generatePerlModSection(const Definition *d, MemberList *ml,const char *name,const char *header) { if (ml==0) return; // empty list @@ -1744,7 +1734,7 @@ void PerlModGenerator::generatePerlModSection(Definition *d, m_output.openList("members"); MemberListIterator mli(*ml); - MemberDef *md; + const MemberDef *md; for (mli.toFirst();(md=mli.current());++mli) { generatePerlModForMember(md,d); @@ -1753,7 +1743,7 @@ void PerlModGenerator::generatePerlModSection(Definition *d, .closeHash(); } -void PerlModGenerator::addListOfAllMembers(ClassDef *cd) +void PerlModGenerator::addListOfAllMembers(const ClassDef *cd) { m_output.openList("all_members"); if (cd->memberNameInfoSDict()) @@ -1766,9 +1756,9 @@ void PerlModGenerator::addListOfAllMembers(ClassDef *cd) MemberInfo *mi; for (mii.toFirst();(mi=mii.current());++mii) { - MemberDef *md=mi->memberDef; - ClassDef *cd=md->getClassDef(); - Definition *d=md->getGroupDef(); + const MemberDef *md=mi->memberDef; + const ClassDef *cd=md->getClassDef(); + const Definition *d=md->getGroupDef(); if (d==0) d = cd; m_output.openHash() @@ -1787,7 +1777,7 @@ void PerlModGenerator::addListOfAllMembers(ClassDef *cd) m_output.closeList(); } -void PerlModGenerator::generatePerlModForClass(ClassDef *cd) +void PerlModGenerator::generatePerlModForClass(const ClassDef *cd) { // + brief description // + detailed description @@ -1845,7 +1835,7 @@ void PerlModGenerator::generatePerlModForClass(ClassDef *cd) { m_output.openList("inner"); ClassSDict::Iterator cli(*cl); - ClassDef *cd; + const ClassDef *cd; for (cli.toFirst();(cd=cli.current());++cli) m_output.openHash() .addFieldQuotedString("name", cd->name()) @@ -1937,7 +1927,7 @@ void PerlModGenerator::generatePerlModForClass(ClassDef *cd) m_output.closeHash(); } -void PerlModGenerator::generatePerlModForNamespace(NamespaceDef *nd) +void PerlModGenerator::generatePerlModForNamespace(const NamespaceDef *nd) { // + contained class definitions // + contained namespace definitions @@ -1958,7 +1948,7 @@ void PerlModGenerator::generatePerlModForNamespace(NamespaceDef *nd) { m_output.openList("classes"); ClassSDict::Iterator cli(*cl); - ClassDef *cd; + const ClassDef *cd; for (cli.toFirst();(cd=cli.current());++cli) m_output.openHash() .addFieldQuotedString("name", cd->name()) @@ -1966,12 +1956,12 @@ void PerlModGenerator::generatePerlModForNamespace(NamespaceDef *nd) m_output.closeList(); } - NamespaceSDict *nl = nd->getNamespaceSDict(); + const NamespaceSDict *nl = nd->getNamespaceSDict(); if (nl) { m_output.openList("namespaces"); NamespaceSDict::Iterator nli(*nl); - NamespaceDef *nd; + const NamespaceDef *nd; for (nli.toFirst();(nd=nli.current());++nli) m_output.openHash() .addFieldQuotedString("name", nd->name()) @@ -1982,7 +1972,7 @@ void PerlModGenerator::generatePerlModForNamespace(NamespaceDef *nd) if (nd->getMemberGroupSDict()) { MemberGroupSDict::Iterator mgli(*nd->getMemberGroupSDict()); - MemberGroup *mg; + const MemberGroup *mg; for (;(mg=mgli.current());++mgli) generatePerlModSection(nd,mg->members(),"user-defined",mg->header()); } @@ -2000,7 +1990,7 @@ void PerlModGenerator::generatePerlModForNamespace(NamespaceDef *nd) m_output.closeHash(); } -void PerlModGenerator::generatePerlModForFile(FileDef *fd) +void PerlModGenerator::generatePerlModForFile(const FileDef *fd) { // + includes files // + includedby files @@ -2069,7 +2059,7 @@ void PerlModGenerator::generatePerlModForFile(FileDef *fd) m_output.closeHash(); } -void PerlModGenerator::generatePerlModForGroup(GroupDef *gd) +void PerlModGenerator::generatePerlModForGroup(const GroupDef *gd) { // + members // + member groups @@ -2094,7 +2084,7 @@ void PerlModGenerator::generatePerlModForGroup(GroupDef *gd) { m_output.openList("files"); QListIterator<FileDef> fli(*fl); - FileDef *fd; + const FileDef *fd; for (fli.toFirst();(fd=fli.current());++fli) m_output.openHash() .addFieldQuotedString("name", fd->name()) @@ -2107,7 +2097,7 @@ void PerlModGenerator::generatePerlModForGroup(GroupDef *gd) { m_output.openList("classes"); ClassSDict::Iterator cli(*cl); - ClassDef *cd; + const ClassDef *cd; for (cli.toFirst();(cd=cli.current());++cli) m_output.openHash() .addFieldQuotedString("name", cd->name()) @@ -2120,7 +2110,7 @@ void PerlModGenerator::generatePerlModForGroup(GroupDef *gd) { m_output.openList("namespaces"); NamespaceSDict::Iterator nli(*nl); - NamespaceDef *nd; + const NamespaceDef *nd; for (nli.toFirst();(nd=nli.current());++nli) m_output.openHash() .addFieldQuotedString("name", nd->name()) @@ -2146,7 +2136,7 @@ void PerlModGenerator::generatePerlModForGroup(GroupDef *gd) { m_output.openList("groups"); GroupListIterator gli(*gl); - GroupDef *sgd; + const GroupDef *sgd; for (gli.toFirst();(sgd=gli.current());++gli) m_output.openHash() .addFieldQuotedString("title", sgd->groupTitle()) @@ -2207,14 +2197,14 @@ bool PerlModGenerator::generatePerlModOutput() m_output.openList("classes"); ClassSDict::Iterator cli(*Doxygen::classSDict); - ClassDef *cd; + const ClassDef *cd; for (cli.toFirst();(cd=cli.current());++cli) generatePerlModForClass(cd); m_output.closeList(); m_output.openList("namespaces"); NamespaceSDict::Iterator nli(*Doxygen::namespaceSDict); - NamespaceDef *nd; + const NamespaceDef *nd; for (nli.toFirst();(nd=nli.current());++nli) generatePerlModForNamespace(nd); m_output.closeList(); @@ -2225,7 +2215,7 @@ bool PerlModGenerator::generatePerlModOutput() for (;(fn=fnli.current());++fnli) { FileNameIterator fni(*fn); - FileDef *fd; + const FileDef *fd; for (;(fd=fni.current());++fni) generatePerlModForFile(fd); } @@ -2233,7 +2223,7 @@ bool PerlModGenerator::generatePerlModOutput() m_output.openList("groups"); GroupSDict::Iterator gli(*Doxygen::groupSDict); - GroupDef *gd; + const GroupDef *gd; for (;(gd=gli.current());++gli) { generatePerlModForGroup(gd); diff --git a/src/portable.cpp b/src/portable.cpp index 3dccaed..3d64638 100644 --- a/src/portable.cpp +++ b/src/portable.cpp @@ -396,7 +396,7 @@ const char *portable_commandExtension() bool portable_fileSystemIsCaseSensitive() { -#if defined(_WIN32) || defined(macintosh) || defined(__MACOSX__) || defined(__APPLE__) +#if defined(_WIN32) || defined(macintosh) || defined(__MACOSX__) || defined(__APPLE__) || defined(__CYGWIN__) return FALSE; #else return TRUE; @@ -463,7 +463,18 @@ void portable_correct_path(void) { #if defined(_WIN32) && !defined(__CYGWIN__) const char *p = portable_getenv("PATH"); + if (!p) return; // no path nothing to correct QCString result = substitute(p,'/','\\'); if (result!=p) portable_setenv("PATH",result.data()); #endif } + +void portable_unlink(const char *fileName) +{ +#if defined(_WIN32) && !defined(__CYGWIN__) + _unlink(fileName); +#else + unlink(fileName); +#endif +} + diff --git a/src/portable.h b/src/portable.h index c5578a3..83f90ef 100644 --- a/src/portable.h +++ b/src/portable.h @@ -23,6 +23,7 @@ void portable_unsetenv(const char *variable); portable_off_t portable_fseek(FILE *f,portable_off_t offset, int whence); portable_off_t portable_ftell(FILE *f); FILE * portable_fopen(const char *fileName,const char *mode); +void portable_unlink(const char *fileName); char portable_pathSeparator(); char portable_pathListSeparator(); const char * portable_ghostScriptCommand(); @@ -73,9 +73,10 @@ struct CondCtx struct FileState { - FileState(int size) : lineNr(1), fileBuf(size), + FileState(int size) : lineNr(1), curlyCount(0),fileBuf(size), oldFileBuf(0), oldFileBufPos(0), bufState(0) {} int lineNr; + int curlyCount; BufStr fileBuf; BufStr *oldFileBuf; int oldFileBufPos; @@ -1088,7 +1089,12 @@ static void expandExpression(QCString &expr,QCString *rest,int pos) if (g_expandedDict->find(macroName)==0) // expand macro { Define *def=DefineManager::instance().isDefined(macroName); - if (definedTest) // macro name was found after defined + if (macroName=="defined") + { + //printf("found defined inside macro definition '%s'\n",expr.right(expr.length()-p).data()); + definedTest=TRUE; + } + else if (definedTest) // macro name was found after defined { if (def) expMacro = " 1 "; else expMacro = " 0 "; replaced=TRUE; @@ -1117,11 +1123,6 @@ static void expandExpression(QCString &expr,QCString *rest,int pos) replaced=replaceFunctionMacro(expr,rest,p+l,len,def,expMacro); len+=l; } - else if (macroName=="defined") - { - //printf("found defined inside macro definition '%s'\n",expr.right(expr.length()-p).data()); - definedTest=TRUE; - } if (replaced) // expand the macro and rescan the expression { @@ -1255,6 +1256,7 @@ QCString removeIdsAndMarkers(const char *s) result+="0L"; p++; while ((c=*p) && isId(c)) p++; + while ((c=*p) && isspace((uchar)c)) p++; if (*p=='(') // undefined function macro { p++; @@ -1605,6 +1607,8 @@ static void readIncludeFile(const QCString &inc) fs->bufState = YY_CURRENT_BUFFER; fs->lineNr = oldLineNr; fs->fileName = oldFileName; + fs->curlyCount = g_curlyCount; + g_curlyCount = 0; // push the state on the stack g_includeStack.push(fs); // set the scanner to the include file @@ -2948,6 +2952,7 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) //preYYin = fs->oldYYin; g_inputBuf = fs->oldFileBuf; g_inputBufPos = fs->oldFileBufPos; + g_curlyCount = fs->curlyCount; setFileName(fs->fileName); DBG_CTX((stderr,"######## FileName %s\n",g_yyFileName.data())); diff --git a/src/printdocvisitor.h b/src/printdocvisitor.h index 26bb3e7..b4997fd 100644 --- a/src/printdocvisitor.h +++ b/src/printdocvisitor.h @@ -676,16 +676,6 @@ class PrintDocVisitor : public DocVisitor indent_post(); printf("</internalref>\n"); } - void visitPre(DocCopy *c) - { - indent_pre(); - printf("<copy link=\"%s\">\n",c->link().data()); - } - void visitPost(DocCopy *) - { - indent_post(); - printf("</copy>\n"); - } void visitPre(DocText *) { indent_pre(); diff --git a/src/pycode.h b/src/pycode.h index 9817c39..de0a8a9 100644 --- a/src/pycode.h +++ b/src/pycode.h @@ -36,7 +36,7 @@ class Definition; extern void parsePythonCode(CodeOutputInterface &,const char *,const QCString &, bool ,const char *,FileDef *fd, int startLine,int endLine,bool inlineFragment, - MemberDef *memberDef,bool showLineNumbers,Definition *searchCtx, + const MemberDef *memberDef,bool showLineNumbers,const Definition *searchCtx, bool collectXRefs); extern void resetPythonCodeParserState(); diff --git a/src/pycode.l b/src/pycode.l index 4fb27f1..010d188 100644 --- a/src/pycode.l +++ b/src/pycode.l @@ -63,7 +63,7 @@ static const char * g_inputString; //!< the code fragment as text static int g_inputPosition; //!< read offset during parsing static const char * g_currentFontClass; static bool g_needsTermination; -static Definition *g_searchCtx; +static const Definition *g_searchCtx; static bool g_collectXRefs; static int g_inputLines; //!< number of line in the code fragment static int g_yyLineNr; //!< current line number @@ -162,7 +162,7 @@ void PyVariableContext::addVariable(const QCString &type,const QCString &name) QCString lname = name.simplifyWhiteSpace(); Scope *scope = m_scopes.count()==0 ? &m_globalScope : m_scopes.getLast(); - ClassDef *varType; + const ClassDef *varType; if ( (varType=g_codeClassSDict[ltype]) || // look for class definitions inside the code block (varType=getResolvedClass(g_currentDefinition,g_sourceFileDef,ltype)) // look for global class definitions @@ -212,7 +212,7 @@ class PyCallContext Ctx() : name(g_name), type(g_type), cd(0) {} QCString name; QCString type; - ClassDef *cd; + const ClassDef *cd; }; PyCallContext() @@ -223,7 +223,7 @@ class PyCallContext virtual ~PyCallContext() {} - void setClass(ClassDef *cd) + void setClass(const ClassDef *cd) { Ctx *ctx = m_classList.getLast(); if (ctx) @@ -259,7 +259,7 @@ class PyCallContext m_classList.append(new Ctx); } - ClassDef *getClass() const + const ClassDef *getClass() const { Ctx *ctx = m_classList.getLast(); @@ -320,7 +320,7 @@ static void addToSearchIndex(const char *text) } -static ClassDef *stripClassName(const char *s,Definition *d=g_currentDefinition) +static const ClassDef *stripClassName(const char *s,Definition *d=g_currentDefinition) { int pos=0; QCString type = s; @@ -330,7 +330,7 @@ static ClassDef *stripClassName(const char *s,Definition *d=g_currentDefinition) { QCString clName=className+templSpec; - ClassDef *cd=0; + const ClassDef *cd=0; if (!g_classScope.isEmpty()) { cd=getResolvedClass(d,g_sourceFileDef,g_classScope+"::"+clName); @@ -437,7 +437,7 @@ static void nextCodeLine() * split into multiple links with the same destination, one for each line. */ static void writeMultiLineCodeLink(CodeOutputInterface &ol, - Definition *d, + const Definition *d, const char *text) { static bool sourceTooltips = Config_getBool(SOURCE_TOOLTIPS); @@ -544,11 +544,11 @@ static bool getLinkInScope(const QCString &c, // scope const char *text ) { - MemberDef *md; - ClassDef *cd; - FileDef *fd; - NamespaceDef *nd; - GroupDef *gd; + const MemberDef *md = 0; + const ClassDef *cd = 0; + const FileDef *fd = 0; + const NamespaceDef *nd = 0; + const GroupDef *gd = 0; //printf("Trying `%s'::`%s'\n",c.data(),m.data()); if (getDefs(c,m,"()",md,cd,fd,nd,gd,FALSE,g_sourceFileDef) && md->isLinkable()) @@ -556,8 +556,8 @@ static bool getLinkInScope(const QCString &c, // scope //Definition *d=0; //if (cd) d=cd; else if (nd) d=nd; else if (fd) d=fd; else d=gd; - Definition *d = md->getOuterScope()==Doxygen::globalScope ? - md->getBodyDef() : md->getOuterScope(); + const Definition *d = md->getOuterScope()==Doxygen::globalScope ? + md->getBodyDef() : md->getOuterScope(); //printf("Found! d=%s\n",d?d->name().data():"<none>"); if (md->getGroupDef()) d = md->getGroupDef(); if (d && d->isLinkable()) @@ -569,7 +569,7 @@ static bool getLinkInScope(const QCString &c, // scope if (g_currentDefinition && g_currentMemberDef && md!=g_currentMemberDef && g_collectXRefs) { - addDocCrossReference(g_currentMemberDef,md); + addDocCrossReference(g_currentMemberDef,const_cast<MemberDef*>(md)); } //printf("d->getReference()=`%s' d->getOutputBase()=`%s' name=`%s' member name=`%s'\n",d->getReference().data(),d->getOutputFileBase().data(),d->name().data(),md->name().data()); @@ -616,8 +616,8 @@ static void generateClassOrGlobalLink(CodeOutputInterface &ol,char *clName, DBG_CTX((stderr,"generateClassOrGlobalLink(className=%s)\n",className.data())); - ClassDef *cd=0,*lcd=0; /** Class def that we may find */ - MemberDef *md=0; /** Member def that we may find */ + const ClassDef *cd=0,*lcd=0; /** Class def that we may find */ + const MemberDef *md=0; /** Member def that we may find */ //bool isLocal=FALSE; if ((lcd=g_theVarContext.findVariable(className))==0) // not a local variable @@ -634,7 +634,7 @@ static void generateClassOrGlobalLink(CodeOutputInterface &ol,char *clName, if (cd==0 && md==0) // also see if it is variable or enum or enum value { - NamespaceDef *nd = getResolvedNamespace(scope); + const NamespaceDef *nd = getResolvedNamespace(scope); if (nd) { writeMultiLineCodeLink(ol,nd,clName); @@ -663,13 +663,13 @@ static void generateClassOrGlobalLink(CodeOutputInterface &ol,char *clName, addToSearchIndex(className); if (md) { - Definition *d = md->getOuterScope()==Doxygen::globalScope ? - md->getBodyDef() : md->getOuterScope(); + const Definition *d = md->getOuterScope()==Doxygen::globalScope ? + md->getBodyDef() : md->getOuterScope(); if (md->getGroupDef()) d = md->getGroupDef(); if (d && d->isLinkable() && md->isLinkable() && g_currentMemberDef && g_collectXRefs) { - addDocCrossReference(g_currentMemberDef,md); + addDocCrossReference(g_currentMemberDef,const_cast<MemberDef*>(md)); } } } @@ -690,8 +690,8 @@ static void generateClassOrGlobalLink(CodeOutputInterface &ol,char *clName, g_theCallContext.setClass(stripClassName(md->typeString(),md->getOuterScope())); writeMultiLineCodeLink(ol,md,clName); addToSearchIndex(className); - Definition *d = md->getOuterScope()==Doxygen::globalScope ? - md->getBodyDef() : md->getOuterScope(); + const Definition *d = md->getOuterScope()==Doxygen::globalScope ? + md->getBodyDef() : md->getOuterScope(); if (md->getGroupDef()) d = md->getGroupDef(); if (d && d->isLinkable() && md->isLinkable() && g_currentMemberDef && g_collectXRefs) @@ -703,7 +703,7 @@ static void generateClassOrGlobalLink(CodeOutputInterface &ol,char *clName, } else // check namespace as well { - NamespaceDef *mnd = getResolvedNamespace(scope); + const NamespaceDef *mnd = getResolvedNamespace(scope); if (mnd) { MemberDef *md=mnd->getMemberByName(locName); @@ -713,8 +713,8 @@ static void generateClassOrGlobalLink(CodeOutputInterface &ol,char *clName, g_theCallContext.setClass(stripClassName(md->typeString(),md->getOuterScope())); writeMultiLineCodeLink(ol,md,clName); addToSearchIndex(className); - Definition *d = md->getOuterScope()==Doxygen::globalScope ? - md->getBodyDef() : md->getOuterScope(); + const Definition *d = md->getOuterScope()==Doxygen::globalScope ? + md->getBodyDef() : md->getOuterScope(); if (md->getGroupDef()) d = md->getGroupDef(); if (d && d->isLinkable() && md->isLinkable() && g_currentMemberDef && g_collectXRefs) @@ -1091,7 +1091,7 @@ TARGET ({IDENTIFIER}|"("{TARGET_LIST}")"|"["{TARGET_LIST}"]"|{ATTRIBUT char *s=g_curClassBases.first(); while (s) { - ClassDef *baseDefToAdd=g_codeClassSDict[s]; + const ClassDef *baseDefToAdd=g_codeClassSDict[s]; // Try to find class in global // scope @@ -1102,7 +1102,7 @@ TARGET ({IDENTIFIER}|"("{TARGET_LIST}")"|"["{TARGET_LIST}"]"|{ATTRIBUT if (baseDefToAdd && baseDefToAdd!=classDefToAdd) { - classDefToAdd->insertBaseClass(baseDefToAdd,s,Public,Normal); + classDefToAdd->insertBaseClass(const_cast<ClassDef*>(baseDefToAdd),s,Public,Normal); } s=g_curClassBases.next(); @@ -1560,7 +1560,7 @@ static void adjustScopesAndSuites(unsigned indentLength) void parsePythonCode(CodeOutputInterface &od,const char * /*className*/, const QCString &s,bool exBlock, const char *exName, FileDef *fd,int startLine,int endLine,bool inlineFragment, - MemberDef *,bool,Definition *searchCtx,bool collectXRefs) + const MemberDef *,bool,const Definition *searchCtx,bool collectXRefs) { //printf("***parseCode()\n"); diff --git a/src/pyscanner.h b/src/pyscanner.h index affa7ca..01235ee 100644 --- a/src/pyscanner.h +++ b/src/pyscanner.h @@ -53,9 +53,9 @@ class PythonLanguageScanner : public ParserInterface int startLine=-1, int endLine=-1, bool inlineFragment=FALSE, - MemberDef *memberDef=0, + const MemberDef *memberDef=0, bool showLineNumbers=TRUE, - Definition *searchCtx=0, + const Definition *searchCtx=0, bool collectXrefs=TRUE ); void resetCodeParserState(); diff --git a/src/pyscanner.l b/src/pyscanner.l index 655b6e2..3f98f3a 100644 --- a/src/pyscanner.l +++ b/src/pyscanner.l @@ -143,7 +143,7 @@ static void initEntry() current->stat = gstat; current->lang = SrcLangExt_Python; current->setParent(current_root); - initGroupInfo(current); + Doxygen::docGroup.initGroupInfo(current); gstat = FALSE; } @@ -537,6 +537,8 @@ STARTDOCSYMS "##" %x SingleQuoteString %x DoubleQuoteString %x TripleString +%x SingleQuoteStringIgnore +%x DoubleQuoteStringIgnore /* import */ %x FromMod @@ -1282,8 +1284,28 @@ STARTDOCSYMS "##" ); //Has base class-do stuff } + "'" { // start of a single quoted string + g_stringContext=YY_START; + BEGIN( SingleQuoteStringIgnore ); + } + "\"" { // start of a double quoted string + g_stringContext=YY_START; + BEGIN( DoubleQuoteStringIgnore ); + } } +<SingleQuoteStringIgnore>{ + "'" { // end of a single quoted string + BEGIN(g_stringContext); + } + . { } +} +<DoubleQuoteStringIgnore>{ + "\"" { // end of a double quoted string + BEGIN(g_stringContext); + } + . { } +} <ClassCaptureIndent>{ "\n"|({BB}"\n") { @@ -1702,6 +1724,10 @@ STARTDOCSYMS "##" lineCount(); } +<*>"'" { + fprintf(stderr,"Quote: %d\n",YY_START); + } + <*>. { //printf("[pyscanner] '%s' [ state %d ] [line %d] no match\n", // yytext, YY_START, yyLineNr); @@ -1746,14 +1772,14 @@ static void parseCompounds(Entry *rt) current = new Entry; initEntry(); - groupEnterCompound(yyFileName,yyLineNr,ce->name); + Doxygen::docGroup.enterCompound(yyFileName,yyLineNr,ce->name); pyscannerYYlex() ; g_lexInit=TRUE; delete current; current=0; ce->program.resize(0); - groupLeaveCompound(yyFileName,yyLineNr,ce->name); + Doxygen::docGroup.leaveCompound(yyFileName,yyLineNr,ce->name); } parseCompounds(ce); @@ -1813,7 +1839,7 @@ static void parseMain(const char *fileName,const char *fileBuf,Entry *rt) initParser(); current = new Entry; - groupEnterFile(yyFileName,yyLineNr); + Doxygen::docGroup.enterFile(yyFileName,yyLineNr); current->reset(); initEntry(); @@ -1822,7 +1848,7 @@ static void parseMain(const char *fileName,const char *fileBuf,Entry *rt) pyscannerYYlex(); g_lexInit=TRUE; - groupLeaveFile(yyFileName,yyLineNr); + Doxygen::docGroup.leaveFile(yyFileName,yyLineNr); current_root->program.resize(0); delete current; current=0; @@ -1926,9 +1952,9 @@ void PythonLanguageScanner::parseCode(CodeOutputInterface &codeOutIntf, int startLine, int endLine, bool inlineFragment, - MemberDef *memberDef, + const MemberDef *memberDef, bool showLineNumbers, - Definition *searchCtx, + const Definition *searchCtx, bool collectXRefs ) { diff --git a/src/qhp.cpp b/src/qhp.cpp index 6ce6b06..6260d09 100644 --- a/src/qhp.cpp +++ b/src/qhp.cpp @@ -193,7 +193,7 @@ void Qhp::addContentsItem(bool /*isDir*/, const char * name, const char * /*ref*/, const char * file, const char *anchor, bool /* separateIndex */, bool /* addToNavIndex */, - Definition * /*def*/) + const Definition * /*def*/) { //printf("Qhp::addContentsItem(%s) %d\n",name,m_sectionLevel); // Backup difference before modification @@ -214,7 +214,7 @@ void Qhp::addContentsItem(bool /*isDir*/, const char * name, } } -void Qhp::addIndexItem(Definition *context,MemberDef *md, +void Qhp::addIndexItem(const Definition *context,const MemberDef *md, const char *sectionAnchor,const char *word) { (void)word; @@ -34,8 +34,8 @@ class Qhp : public IndexIntf void addContentsItem(bool isDir, const char * name, const char * ref, const char * file, const char * anchor, bool separateIndex,bool addToNavIndex, - Definition *def); - void addIndexItem(Definition *context, MemberDef *md, + const Definition *def); + void addIndexItem(const Definition *context, const MemberDef *md, const char *sectionAnchor, const char *title); void addIndexFile(const char * name); void addImageFile(const char * name); diff --git a/src/rtfdocvisitor.cpp b/src/rtfdocvisitor.cpp index 55c03a5..4e89193 100644 --- a/src/rtfdocvisitor.cpp +++ b/src/rtfdocvisitor.cpp @@ -532,7 +532,9 @@ void RTFDocVisitor::visit(DocIncOperator *op) //printf("DocIncOperator: type=%d first=%d, last=%d text=`%s'\n", // op->type(),op->isFirst(),op->isLast(),op->text().data()); DBG_RTF("{\\comment RTFDocVisitor::visit(DocIncOperator)}\n"); - SrcLangExt langExt = getLanguageFromFileName(m_langExt); + QCString locLangExt = getFileNameExtension(op->includeFileName()); + if (locLangExt.isEmpty()) locLangExt = m_langExt; + SrcLangExt langExt = getLanguageFromFileName(locLangExt); if (op->isFirst()) { if (!m_hide) @@ -549,14 +551,14 @@ void RTFDocVisitor::visit(DocIncOperator *op) popEnabled(); if (!m_hide) { - FileDef *fd; + FileDef *fd = 0; if (!op->includeFileName().isEmpty()) { QFileInfo cfi( op->includeFileName() ); fd = createFileDef( cfi.dirPath().utf8(), cfi.fileName().utf8() ); } - Doxygen::parserManager->getParser(m_langExt) + Doxygen::parserManager->getParser(locLangExt) ->parseCode(m_ci,op->context(),op->text(),langExt, op->isExample(),op->exampleFile(), fd, // fileDef @@ -782,7 +784,6 @@ void RTFDocVisitor::visitPre(DocSimpleSect *s) // special case 1: user defined title if (s->type()!=DocSimpleSect::User && s->type()!=DocSimpleSect::Rcs) { - m_t << ":"; m_t << "\\par"; m_t << "}"; // end bold incIndentLevel(); @@ -1377,7 +1378,6 @@ void RTFDocVisitor::visitPre(DocParamSect *s) default: ASSERT(0); } - m_t << ":"; m_t << "\\par"; m_t << "}" << endl; bool useTable = s->type()==DocParamSect::Param || @@ -1655,18 +1655,6 @@ void RTFDocVisitor::visitPost(DocInternalRef *) m_t << " "; } -void RTFDocVisitor::visitPre(DocCopy *) -{ - if (m_hide) return; - DBG_RTF("{\\comment RTFDocVisitor::visitPre(DocCopy)}\n"); -} - -void RTFDocVisitor::visitPost(DocCopy *) -{ - if (m_hide) return; - DBG_RTF("{\\comment RTFDocVisitor::visitPost(DocCopy)}\n"); -} - void RTFDocVisitor::visitPre(DocText *) { if (m_hide) return; diff --git a/src/rtfdocvisitor.h b/src/rtfdocvisitor.h index b7cc3ea..82e4453 100644 --- a/src/rtfdocvisitor.h +++ b/src/rtfdocvisitor.h @@ -126,8 +126,6 @@ class RTFDocVisitor : public DocVisitor void visitPost(DocXRefItem *); void visitPre(DocInternalRef *); void visitPost(DocInternalRef *); - void visitPre(DocCopy *); - void visitPost(DocCopy *); void visitPre(DocText *); void visitPost(DocText *); void visitPre(DocHtmlBlockQuote *); diff --git a/src/rtfgen.cpp b/src/rtfgen.cpp index bb69898..948d4cf 100644 --- a/src/rtfgen.cpp +++ b/src/rtfgen.cpp @@ -31,6 +31,10 @@ #include "diagram.h" #include "language.h" #include "dot.h" +#include "dotcallgraph.h" +#include "dotclassgraph.h" +#include "dotdirdeps.h" +#include "dotincldepgraph.h" #include "version.h" #include "pagedef.h" #include "rtfstyle.h" @@ -44,6 +48,8 @@ #include "filename.h" #include "namespacedef.h" +static bool DoxyCodeLineOpen = FALSE; + //#define DBG_RTF(x) x; #define DBG_RTF(x) @@ -1948,6 +1954,9 @@ void RTFGenerator::endCodeFragment() //styleStack.pop(); //printf("RTFGenerator::endCodeFrament() top=%s\n",styleStack.top()); //t << rtf_Style_Reset << styleStack.top() << endl; + //endCodeLine checks is there is still an open code line, if so closes it. + endCodeLine(); + DBG_RTF(t << "{\\comment (endCodeFragment) }" << endl) t << "}" << endl; m_omitParagraph = TRUE; @@ -2497,7 +2506,7 @@ void RTFGenerator::startDotGraph() DBG_RTF(t << "{\\comment (startDotGraph)}" << endl) } -void RTFGenerator::endDotGraph(const DotClassGraph &g) +void RTFGenerator::endDotGraph(DotClassGraph &g) { newParagraph(); @@ -2521,7 +2530,7 @@ void RTFGenerator::startInclDepGraph() DBG_RTF(t << "{\\comment (startInclDepGraph)}" << endl) } -void RTFGenerator::endInclDepGraph(const DotInclDepGraph &g) +void RTFGenerator::endInclDepGraph(DotInclDepGraph &g) { newParagraph(); @@ -2543,7 +2552,7 @@ void RTFGenerator::startGroupCollaboration() { } -void RTFGenerator::endGroupCollaboration(const DotGroupCollaboration &) +void RTFGenerator::endGroupCollaboration(DotGroupCollaboration &) { } @@ -2552,7 +2561,7 @@ void RTFGenerator::startCallGraph() DBG_RTF(t << "{\\comment (startCallGraph)}" << endl) } -void RTFGenerator::endCallGraph(const DotCallGraph &g) +void RTFGenerator::endCallGraph(DotCallGraph &g) { newParagraph(); @@ -2575,7 +2584,7 @@ void RTFGenerator::startDirDepGraph() DBG_RTF(t << "{\\comment (startDirDepGraph)}" << endl) } -void RTFGenerator::endDirDepGraph(const DotDirDeps &g) +void RTFGenerator::endDirDepGraph(DotDirDeps &g) { newParagraph(); @@ -2803,7 +2812,7 @@ void RTFGenerator::exceptionEntry(const char* prefix,bool closeBracket) t << " "; } -void RTFGenerator::writeDoc(DocNode *n,Definition *ctx,MemberDef *) +void RTFGenerator::writeDoc(DocNode *n,const Definition *ctx,const MemberDef *) { RTFDocVisitor *visitor = new RTFDocVisitor(t,*this,ctx?ctx->getDefFileExtension():QCString("")); n->accept(visitor); @@ -3037,6 +3046,22 @@ void RTFGenerator::endInlineMemberDoc() t << "\\cell }{\\row }" << endl; } +void RTFGenerator::writeLineNumber(const char *,const char *,const char *,int l) +{ + DoxyCodeLineOpen = TRUE; + t << QString("%1").arg(l,5) << " "; +} +void RTFGenerator::startCodeLine(bool) +{ + DoxyCodeLineOpen = TRUE; + col=0; +} +void RTFGenerator::endCodeLine() +{ + if (DoxyCodeLineOpen) lineBreak(); + DoxyCodeLineOpen = FALSE; +} + void RTFGenerator::startLabels() { } diff --git a/src/rtfgen.h b/src/rtfgen.h index b6b32c7..b5f06f0 100644 --- a/src/rtfgen.h +++ b/src/rtfgen.h @@ -41,7 +41,7 @@ class RTFGenerator : public OutputGenerator bool isEnabled(OutputType o) { return (o==RTF && active); } OutputGenerator *get(OutputType o) { return (o==RTF) ? this : 0; } - void writeDoc(DocNode *,Definition *,MemberDef *); + void writeDoc(DocNode *,const Definition *,const MemberDef *); void startFile(const char *name,const char *manName,const char *title); void writeSearchInfo() {} @@ -127,9 +127,9 @@ class RTFGenerator : public OutputGenerator void writeAnchor(const char *fileName,const char *name); void startCodeFragment(); void endCodeFragment(); - void writeLineNumber(const char *,const char *,const char *,int l) { t << QString("%1").arg(l,5) << " "; } - void startCodeLine(bool) { col=0; } - void endCodeLine() { lineBreak(); } + void writeLineNumber(const char *,const char *,const char *,int l); + void startCodeLine(bool); + void endCodeLine(); void startEmphasis() { t << "{\\i "; } void endEmphasis() { t << "}"; } void startBold() { t << "{\\b "; } @@ -202,16 +202,16 @@ class RTFGenerator : public OutputGenerator void endDescTableData(); void startDotGraph(); - void endDotGraph(const DotClassGraph &); + void endDotGraph(DotClassGraph &); void startInclDepGraph(); - void endInclDepGraph(const DotInclDepGraph &); + void endInclDepGraph(DotInclDepGraph &); void startGroupCollaboration(); - void endGroupCollaboration(const DotGroupCollaboration &g); + void endGroupCollaboration(DotGroupCollaboration &g); void startCallGraph(); - void endCallGraph(const DotCallGraph &); + void endCallGraph(DotCallGraph &); void startDirDepGraph(); - void endDirDepGraph(const DotDirDeps &g); - void writeGraphicalHierarchy(const DotGfxHierarchyTable &) {} + void endDirDepGraph(DotDirDeps &g); + void writeGraphicalHierarchy(DotGfxHierarchyTable &) {} void startMemberGroupHeader(bool); void endMemberGroupHeader(); @@ -262,7 +262,7 @@ class RTFGenerator : public OutputGenerator void endFontClass(); void writeCodeAnchor(const char *) {} - void setCurrentDoc(Definition *,const char *,bool) {} + void setCurrentDoc(const Definition *,const char *,bool) {} void addWord(const char *,bool) {} static bool preProcessFileInplace(const char *path,const char *name); diff --git a/src/scanner.h b/src/scanner.h index ac574e2..c0d3dff 100644 --- a/src/scanner.h +++ b/src/scanner.h @@ -48,9 +48,9 @@ class CLanguageScanner : public ParserInterface int startLine=-1, int endLine=-1, bool inlineFragment=FALSE, - MemberDef *memberDef=0, + const MemberDef *memberDef=0, bool showLineNumbers=TRUE, - Definition *searchCtx=0, + const Definition *searchCtx=0, bool collectXRefs=TRUE ); void resetCodeParserState(); diff --git a/src/scanner.l b/src/scanner.l index 3d3c109..5ecf261 100644 --- a/src/scanner.l +++ b/src/scanner.l @@ -78,6 +78,7 @@ static int lastHereDocContext; static int lastDefineContext; static int lastAlignAsContext; static int lastC11AttributeContext; +static int lastModifierContext; static Protection protection; static Protection baseProt; static int sharpCount = 0 ; @@ -246,7 +247,7 @@ static void initEntry() // //printf("Appending group %s\n",autoGroupStack.top()->groupname.data()); // current->groups->append(new Grouping(*autoGroupStack.top())); //} - initGroupInfo(current); + Doxygen::docGroup.initGroupInfo(current); isTypedef=FALSE; } @@ -766,6 +767,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) /** Slice states */ +%x SliceOptional %x SliceMetadata %x SliceSequence %x SliceSequenceName @@ -1390,6 +1392,10 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) current->explicitExternal = TRUE; lineCount(); } +<FindMembers>{B}*"const"{BN}+ { current->type += " const "; + if (insideCS) current->stat = TRUE; + lineCount(); + } <FindMembers>{B}*"virtual"{BN}+ { current->type += " virtual "; current->virt = Virtual; lineCount(); @@ -2435,6 +2441,19 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) current->type+=yytext; BEGIN(DeclType); } + else if (insideSlice && qstrcmp(yytext,"optional")==0) + { + if (current->type.isEmpty()) + { + current->type = "optional"; + } + else + { + current->type += " optional"; + } + lastModifierContext = YY_START; + BEGIN(SliceOptional); + } else { if (YY_START==FindMembers) @@ -2830,17 +2849,17 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) } } -<FindMembers,FindFields>("//"([!/]?){B}*{CMD}"{")|("/*"([!*]?){B}*{CMD}"{") { +<FindMembers,FindFields>("//"([!/]){B}*{CMD}"{")|("/*"([!*]){B}*{CMD}"{") { //handleGroupStartCommand(current->name); if (previous && previous->section==Entry::GROUPDOC_SEC) { // link open command to the group defined in the previous entry - openGroup(previous,yyFileName,yyLineNr); + Doxygen::docGroup.open(previous,yyFileName,yyLineNr); } else { // link open command to the current entry - openGroup(current,yyFileName,yyLineNr); + Doxygen::docGroup.open(current,yyFileName,yyLineNr); } //current = tmp; initEntry(); @@ -2882,9 +2901,9 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) } } } -<FindMembers,FindFields,ReadInitializer>"//"([!/]?){B}*{CMD}"}".*|"/*"([!*]?){B}*{CMD}"}"[^*]*"*/" { +<FindMembers,FindFields,ReadInitializer>"//"([!/]){B}*{CMD}"}".*|"/*"([!*]){B}*{CMD}"}"[^*]*"*/" { bool insideEnum = YY_START==FindFields || (YY_START==ReadInitializer && lastInitializerContext==FindFields); // see bug746226 - closeGroup(current,yyFileName,yyLineNr,insideEnum); + Doxygen::docGroup.close(current,yyFileName,yyLineNr,insideEnum); } <FindMembers>"=" { // in PHP code this could also be due to "<?=" current->bodyLine = yyLineNr; @@ -3589,6 +3608,20 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) BEGIN (lastSquareContext); } } +<SliceOptional>"(" { + current->type += "("; + roundCount++; + } +<SliceOptional>[0-9]+ { + current->type += yytext; + } +<SliceOptional>")" { + current->type += ")"; + if(--roundCount<=0) + { + BEGIN (lastModifierContext); + } + } <IDLAttribute>"]" { // end of IDL function attribute if (--squareCount<=0) @@ -3941,6 +3974,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) else { current->endBodyLine = yyLineNr; + Entry * original_root = current_root; // save root this namespace is in if (current->section == Entry::NAMESPACE_SEC && current->type == "namespace") { int split_point; @@ -4005,6 +4039,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) ) { // namespaces and interfaces and java classes ends with a closing bracket without semicolon current->reset(); + current_root = original_root; // restore scope from before namespace descent initEntry(); memspecEntry = 0; BEGIN( FindMembers ) ; @@ -4625,7 +4660,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) unput(lastCopyArgChar); BEGIN( lastCommentInArgContext ); } -<CopyArgCommentLine>{CMD}("verbatim"|"latexonly"|"htmlonly"|"xmlonly"|"manonly"|"dot"|"code")/[^a-z_A-Z0-9] { // verbatim command (which could contain nested comments!) +<CopyArgCommentLine>{CMD}("verbatim"|"latexonly"|"htmlonly"|"xmlonly"|"manonly"|"dot"|"code")/[^a-z_A-Z0-9\-] { // verbatim command (which could contain nested comments!) docBlockName=&yytext[1]; fullArgString+=yytext; BEGIN(CopyArgVerbatim); @@ -4643,7 +4678,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) fullArgString+=yytext; BEGIN(CopyArgVerbatim); } -<CopyArgVerbatim>[\\@]("endverbatim"|"endlatexonly"|"endhtmlonly"|"endxmlonly"|"enddocbookonly"|"endmanonly"|"enddot"|"endcode"|"f$"|"f]"|"f}")/[^a-z_A-Z0-9] { // end of verbatim block +<CopyArgVerbatim>[\\@]("endverbatim"|"endlatexonly"|"endhtmlonly"|"endxmlonly"|"enddocbookonly"|"endmanonly"|"enddot"|"endcode"|"f$"|"f]"|"f}")/[^a-z_A-Z0-9\-] { // end of verbatim block fullArgString+=yytext; if (yytext[1]=='f') // end of formula { @@ -6252,6 +6287,43 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) startCommentBlock(FALSE); BEGIN( DocBlock ); } +<FindMembers,FindFields,MemberSpec,FuncQual,SkipCurly,Operator,ClassVar,SkipInits,Bases,OldStyleArgs>"/**"[*]+{BL} { + + static bool javadocBanner = Config_getBool(JAVADOC_BANNER); + + if( javadocBanner ) { + lastDocContext = YY_START; + + //printf("Found comment banner at %s:%d\n",yyFileName,yyLineNr); + if (current_root->section & Entry::SCOPE_MASK) + { + current->inside = current_root->name+"::"; + } + current->docLine = yyLineNr; + current->docFile = yyFileName; + docBlockContext = YY_START; + docBlockInBody = YY_START==SkipCurly; + static bool javadocAutoBrief = Config_getBool(JAVADOC_AUTOBRIEF); + docBlockAutoBrief = javadocAutoBrief; + + QCString indent; + indent.fill(' ',computeIndent(yytext,g_column)); + docBlock=indent; + + if (docBlockAutoBrief) + { + current->briefLine = yyLineNr; + current->briefFile = yyFileName; + } + startCommentBlock(FALSE); + BEGIN( DocBlock ); + } else { + current->program += yytext ; + lastContext = YY_START ; + BEGIN( Comment ) ; + } + + } <FindMembers,FindFields,MemberSpec,FuncQual,SkipCurly,Operator,ClassVar,SkipInits,Bases,OldStyleArgs>("//"{B}*)?"/**"/[^/*] { removeSlashes=(yytext[1]=='/'); lastDocContext = YY_START; @@ -6563,7 +6635,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) g_nestedComment=FALSE; BEGIN(DocCopyBlock); } -<DocBlock>{CMD}("verbatim"|"latexonly"|"htmlonly"|"xmlonly"|"manonly"|"dot"|"code")/[^a-z_A-Z0-9] { // verbatim command (which could contain nested comments!) +<DocBlock>{CMD}("verbatim"|"latexonly"|"htmlonly"|"xmlonly"|"manonly"|"dot"|"code")/[^a-z_A-Z0-9\-] { // verbatim command (which could contain nested comments!) docBlock+=yytext; docBlockName=&yytext[1]; g_fencedSize=0; @@ -7135,13 +7207,13 @@ static void parseCompounds(Entry *rt) //memberGroupId = DOX_NOGROUP; //memberGroupRelates.resize(0); //memberGroupInside.resize(0); - groupEnterCompound(yyFileName,yyLineNr,ce->name); + Doxygen::docGroup.enterCompound(yyFileName,yyLineNr,ce->name); scannerYYlex() ; g_lexInit=TRUE; //forceEndGroup(); - groupLeaveCompound(yyFileName,yyLineNr,ce->name); + Doxygen::docGroup.leaveCompound(yyFileName,yyLineNr,ce->name); delete current; current=0; ce->program.resize(0); @@ -7201,7 +7273,7 @@ static void parseMain(const char *fileName, current_root = rt ; initParser(); - groupEnterFile(yyFileName,yyLineNr); + Doxygen::docGroup.enterFile(yyFileName,yyLineNr); current = new Entry; //printf("current=%p current_root=%p\n",current,current_root); int sec=guessSection(yyFileName); @@ -7233,7 +7305,7 @@ static void parseMain(const char *fileName, } //forceEndGroup(); - groupLeaveFile(yyFileName,yyLineNr); + Doxygen::docGroup.leaveFile(yyFileName,yyLineNr); //if (depthIf>0) //{ @@ -7368,9 +7440,9 @@ void CLanguageScanner::parseCode(CodeOutputInterface & codeOutIntf, int startLine, int endLine, bool inlineFragment, - MemberDef *memberDef, + const MemberDef *memberDef, bool showLineNumbers, - Definition *searchCtx, + const Definition *searchCtx, bool collectXRefs ) { diff --git a/src/searchindex.cpp b/src/searchindex.cpp index c9f8ec1..b21d587 100644 --- a/src/searchindex.cpp +++ b/src/searchindex.cpp @@ -86,12 +86,12 @@ SearchIndex::SearchIndex() : SearchIndexIntf(Internal), for (i=0;i<numIndexEntries;i++) m_index.insert(i,new QList<IndexWord>); } -void SearchIndex::setCurrentDoc(Definition *ctx,const char *anchor,bool isSourceFile) +void SearchIndex::setCurrentDoc(const Definition *ctx,const char *anchor,bool isSourceFile) { if (ctx==0) return; assert(!isSourceFile || ctx->definitionType()==Definition::TypeFile); //printf("SearchIndex::setCurrentDoc(%s,%s,%s)\n",name,baseName,anchor); - QCString url=isSourceFile ? (dynamic_cast<FileDef*>(ctx))->getSourceFileBase() : ctx->getOutputFileBase(); + QCString url=isSourceFile ? (dynamic_cast<const FileDef*>(ctx))->getSourceFileBase() : ctx->getOutputFileBase(); url+=Config_getString(HTML_FILE_EXTENSION); QCString baseUrl = url; if (anchor) url+=QCString("#")+anchor; @@ -99,7 +99,7 @@ void SearchIndex::setCurrentDoc(Definition *ctx,const char *anchor,bool isSource QCString name=ctx->qualifiedName(); if (ctx->definitionType()==Definition::TypeMember) { - MemberDef *md = dynamic_cast<MemberDef *>(ctx); + const MemberDef *md = dynamic_cast<const MemberDef *>(ctx); name.prepend((md->getLanguage()==SrcLangExt_Fortran ? theTranslator->trSubprogram(TRUE,TRUE) : theTranslator->trMember(TRUE,TRUE))+" "); @@ -116,7 +116,7 @@ void SearchIndex::setCurrentDoc(Definition *ctx,const char *anchor,bool isSource { case Definition::TypePage: { - PageDef *pd = dynamic_cast<PageDef *>(ctx); + const PageDef *pd = dynamic_cast<const PageDef *>(ctx); if (pd->hasTitle()) { name = theTranslator->trPage(TRUE,TRUE)+" "+pd->title(); @@ -129,7 +129,7 @@ void SearchIndex::setCurrentDoc(Definition *ctx,const char *anchor,bool isSource break; case Definition::TypeClass: { - ClassDef *cd = dynamic_cast<ClassDef *>(ctx); + const ClassDef *cd = dynamic_cast<const ClassDef *>(ctx); name.prepend(cd->compoundTypeString()+" "); } break; @@ -151,7 +151,7 @@ void SearchIndex::setCurrentDoc(Definition *ctx,const char *anchor,bool isSource break; case Definition::TypeGroup: { - GroupDef *gd = dynamic_cast<GroupDef *>(ctx); + const GroupDef *gd = dynamic_cast<const GroupDef *>(ctx); if (gd->groupTitle()) { name = theTranslator->trGroup(TRUE,TRUE)+" "+gd->groupTitle(); @@ -442,11 +442,11 @@ SearchIndexExternal::~SearchIndexExternal() delete p; } -static QCString definitionToName(Definition *ctx) +static QCString definitionToName(const Definition *ctx) { if (ctx && ctx->definitionType()==Definition::TypeMember) { - MemberDef *md = dynamic_cast<MemberDef*>(ctx); + const MemberDef *md = dynamic_cast<const MemberDef*>(ctx); if (md->isFunction()) return "function"; else if (md->isSlot()) @@ -477,7 +477,7 @@ static QCString definitionToName(Definition *ctx) switch(ctx->definitionType()) { case Definition::TypeClass: - return (dynamic_cast<ClassDef*>(ctx))->compoundTypeString(); + return (dynamic_cast<const ClassDef*>(ctx))->compoundTypeString(); case Definition::TypeFile: return "file"; case Definition::TypeNamespace: @@ -497,10 +497,10 @@ static QCString definitionToName(Definition *ctx) return "unknown"; } -void SearchIndexExternal::setCurrentDoc(Definition *ctx,const char *anchor,bool isSourceFile) +void SearchIndexExternal::setCurrentDoc(const Definition *ctx,const char *anchor,bool isSourceFile) { QCString extId = stripPath(Config_getString(EXTERNAL_SEARCH_ID)); - QCString baseName = isSourceFile ? (dynamic_cast<FileDef*>(ctx))->getSourceFileBase() : ctx->getOutputFileBase(); + QCString baseName = isSourceFile ? (dynamic_cast<const FileDef*>(ctx))->getSourceFileBase() : ctx->getOutputFileBase(); QCString url = baseName + Doxygen::htmlFileExtension; if (anchor) url+=QCString("#")+anchor; QCString key = extId+";"+url; @@ -514,7 +514,7 @@ void SearchIndexExternal::setCurrentDoc(Definition *ctx,const char *anchor,bool e->name = ctx->qualifiedName(); if (ctx->definitionType()==Definition::TypeMember) { - e->args = (dynamic_cast<MemberDef*>(ctx))->argsString(); + e->args = (dynamic_cast<const MemberDef*>(ctx))->argsString(); } e->extId = extId; e->url = url; @@ -585,14 +585,14 @@ void SearchIndexExternal::write(const char *fileName) static SearchIndexInfo g_searchIndexInfo[NUM_SEARCH_INDICES]; -static void addMemberToSearchIndex(MemberDef *md) +static void addMemberToSearchIndex(const MemberDef *md) { static bool hideFriendCompounds = Config_getBool(HIDE_FRIEND_COMPOUNDS); bool isLinkable = md->isLinkable(); - ClassDef *cd=0; - NamespaceDef *nd=0; - FileDef *fd=0; - GroupDef *gd=0; + const ClassDef *cd=0; + const NamespaceDef *nd=0; + const FileDef *fd=0; + const GroupDef *gd=0; if (isLinkable && ( ((cd=md->getClassDef()) && cd->isLinkable() && cd->templateMaster()==0) || @@ -956,6 +956,7 @@ void createJavascriptSearchIndex() void writeJavascriptSearchIndex() { int i; + int cnt = 0; // write index files QCString searchDirName = Config_getString(HTML_OUTPUT)+"/search"; @@ -1043,7 +1044,7 @@ void writeJavascriptSearchIndex() } firstEntry=FALSE; - ti << " ['" << dl->id() << "',['" << convertToXML(dl->name()) << "',["; + ti << " ['" << dl->id() << "_" << cnt++ << "',['" << convertToXML(dl->name()) << "',["; if (dl->count()==1) // item with a unique name { @@ -1074,7 +1075,7 @@ void writeJavascriptSearchIndex() } else if (md) { - FileDef *fd = md->getBodyDef(); + const FileDef *fd = md->getBodyDef(); if (fd==0) fd = md->getFileDef(); if (fd) { @@ -1155,8 +1156,8 @@ void writeJavascriptSearchIndex() { if (md) { - FileDef *fd = md->getBodyDef(); - if (fd==0) fd = md->getFileDef(); + const FileDef *fd = md->getBodyDef(); + if (fd==0) fd = md->resolveAlias()->getFileDef(); if (fd) { if (!prefix.isEmpty()) prefix+=": "; @@ -1165,7 +1166,7 @@ void writeJavascriptSearchIndex() } } } - else if (md && (md->getClassDef() || md->getNamespaceDef())) + else if (md && (md->resolveAlias()->getClassDef() || md->resolveAlias()->getNamespaceDef())) // member in class or namespace scope { SrcLangExt lang = md->getLanguage(); @@ -1315,7 +1316,7 @@ SearchIndexList::~SearchIndexList() { } -void SearchIndexList::append(Definition *d) +void SearchIndexList::append(const Definition *d) { QCString dispName = d->localName(); SearchDefinitionList *l = find(dispName); @@ -1323,11 +1324,11 @@ void SearchIndexList::append(Definition *d) { if (d->definitionType()==Definition::TypeGroup) { - dispName = (dynamic_cast<GroupDef*>(d))->groupTitle(); + dispName = (dynamic_cast<const GroupDef*>(d))->groupTitle(); } else if (d->definitionType()==Definition::TypePage) { - dispName = (dynamic_cast<PageDef*>(d))->title(); + dispName = (dynamic_cast<const PageDef*>(d))->title(); } l=new SearchDefinitionList(searchId(dispName),dispName); SDict< SearchDefinitionList >::append(dispName,l); diff --git a/src/searchindex.h b/src/searchindex.h index 0345b41..9a612ad 100644 --- a/src/searchindex.h +++ b/src/searchindex.h @@ -72,7 +72,7 @@ class SearchIndexIntf enum Kind { Internal, External }; SearchIndexIntf(Kind k) : m_kind(k) {} virtual ~SearchIndexIntf() {} - virtual void setCurrentDoc(Definition *ctx,const char *anchor,bool isSourceFile) = 0; + virtual void setCurrentDoc(const Definition *ctx,const char *anchor,bool isSourceFile) = 0; virtual void addWord(const char *word,bool hiPriority) = 0; virtual void write(const char *file) = 0; Kind kind() const { return m_kind; } @@ -84,7 +84,7 @@ class SearchIndex : public SearchIndexIntf { public: SearchIndex(); - void setCurrentDoc(Definition *ctx,const char *anchor,bool isSourceFile); + void setCurrentDoc(const Definition *ctx,const char *anchor,bool isSourceFile); void addWord(const char *word,bool hiPriority); void write(const char *file); private: @@ -103,7 +103,7 @@ class SearchIndexExternal : public SearchIndexIntf public: SearchIndexExternal(); ~SearchIndexExternal(); - void setCurrentDoc(Definition *ctx,const char *anchor,bool isSourceFile); + void setCurrentDoc(const Definition *ctx,const char *anchor,bool isSourceFile); void addWord(const char *word,bool hiPriority); void write(const char *file); private: @@ -148,10 +148,10 @@ class SearchDefinitionList : public QList<Definition> class SearchIndexList : public SDict< SearchDefinitionList > { public: - typedef Definition ElementType; + typedef const Definition ElementType; SearchIndexList(uint letter); ~SearchIndexList(); - void append(Definition *d); + void append(const Definition *d); uint letter() const; private: int compareValues(const SearchDefinitionList *md1, const SearchDefinitionList *md2) const; diff --git a/src/sqlcode.h b/src/sqlcode.h index 9c1f7e0..d8a09b7 100644 --- a/src/sqlcode.h +++ b/src/sqlcode.h @@ -30,7 +30,7 @@ class Definition; extern void parseSqlCode(CodeOutputInterface &,const char *,const QCString &, bool ,const char *,FileDef *fd, int startLine,int endLine,bool inlineFragment, - MemberDef *memberDef,bool showLineNumbers,Definition *searchCtx, + const MemberDef *memberDef,bool showLineNumbers,const Definition *searchCtx, bool collectXRefs); extern void resetSqlCodeParserState(); diff --git a/src/sqlcode.l b/src/sqlcode.l index 5e45083..eec9732 100644 --- a/src/sqlcode.l +++ b/src/sqlcode.l @@ -15,6 +15,10 @@ %option never-interactive %option prefix="sqlcodeYY" +%option noyywrap +%option nounput +%option reentrant +%option extra-type="struct sqlcodeYY_state *" %{ @@ -31,133 +35,261 @@ #include "config.h" #include "filedef.h" #include "tooltip.h" +#include "message.h" #define YY_NEVER_INTERACTIVE 1 #define YY_NO_INPUT 1 #define YY_NO_UNISTD_H 1 -static CodeOutputInterface * g_code; -static QCString g_curClassName; -static QCString g_parmType; -static QCString g_parmName; -static const char * g_inputString; //!< the code fragment as text -static int g_inputPosition; //!< read offset during parsing -static int g_inputLines; //!< number of line in the code fragment -static int g_yyLineNr; //!< current line number -static bool g_needsTermination; -static Definition *g_searchCtx; - -static bool g_exampleBlock; -static QCString g_exampleName; -static QCString g_exampleFile; - -static QCString g_type; -static QCString g_name; -static QCString g_args; -static QCString g_classScope; - -static QCString g_CurrScope; - -static FileDef * g_sourceFileDef; -static Definition * g_currentDefinition; -static MemberDef * g_currentMemberDef; -static bool g_includeCodeFragment; -static const char * g_currentFontClass; - -static void codify(const char* text) +struct sqlcodeYY_state +{ + CodeOutputInterface * code; + const char *inputString; //!< the code fragment as text + int inputPosition; //!< read offset during parsing + int inputLines; //!< number of line in the code fragment + int yyLineNr; //!< current line number + bool needsTermination; + const Definition *searchCtx; + + bool exampleBlock; + QCString exampleName; + QCString classScope; + + FileDef *sourceFileDef; + Definition *currentDefinition; + MemberDef *currentMemberDef; + bool includeCodeFragment; + const char *currentFontClass; +}; + +static void codify(const char* text); +static void setCurrentDoc(const QCString &anchor,yyscan_t yyscanner); +static void startCodeLine(yyscan_t yyscanner); +static void endFontClass(yyscan_t yyscanner); +static void endCodeLine(yyscan_t yyscanner); +static void nextCodeLine(yyscan_t yyscanner); +static void codifyLines(char *text,yyscan_t yyscanner); +static void startFontClass(const char *s,yyscan_t yyscanner); +static int countLines(yyscan_t yyscanner); +static int yyread(char *buf,int max_size,yyscan_t yyscanner); + +#undef YY_INPUT +#define YY_INPUT(buf,result,max_size) result=yyread(buf,max_size,yyscanner); + +%} + +nl (\r\n|\r|\n) +ws [ \t]+ +idchar [A-Za-z0-9\-_]+ +keywords1 ("ADD"|"ALL"|"ALLOCATE"|"ALTER"|"AND"|"ANY"|"ARE"|"AS"|"ASENSITIVE"|"ASYMMETRIC"|"AT"|"ATOMIC"|"AUTHORIZATION"|"BETWEEN"|"BOTH"|"BY"|"CALL"|"CALLED"|"CASCADED"|"CAST") +keywords2 ("CHECK"|"CLOSE"|"COLLATE"|"COLUMN"|"COMMIT"|"CONNECT"|"CONSTRAINT"|"CONTINUE"|"CORRESPONDING"|"CREATE"|"CROSS"|"CUBE"|"CURRENT"|"CURRENT_DATE"|"CURRENT_DEFAULT_TRANSFORM_GROUP") +keywords3 ("CURRENT_PATH"|"CURRENT_ROLE"|"CURRENT_TIME"|"CURRENT_TIMESTAMP"|"CURRENT_TRANSFORM_GROUP_FOR_TYPE"|"CURRENT_USER") +keywords4 ("CURSOR"|"CYCLE"|"DAY"|"DEALLOCATE"|"DECLARE"|"DEFAULT"|"DELETE"|"DEREF"|"DESCRIBE"|"DETERMINISTIC"|"DISCONNECT"|"DISTINCT"|"DROP"|"DYNAMIC") +keywords5 ("EACH"|"ELEMENT"|"END-EXEC"|"ESCAPE"|"EXCEPT"|"EXEC"|"EXECUTE"|"EXISTS"|"EXTERNAL"|"FETCH"|"FILTER"|"FOR"|"FOREIGN"|"FREE"|"FROM"|"FULL"|"FUNCTION") +keywords6 ("GET"|"GLOBAL"|"GRANT"|"GROUP"|"GROUPING"|"HAVING"|"HOLD"|"HOUR"|"IDENTITY"|"IMMEDIATE"|"IN"|"INDICATOR"|"INNER"|"INOUT"|"INPUT"|"INSENSITIVE"|"INSERT"|"INTERSECT") +keywords7 ("INTERVAL"|"INTO"|"IS"|"ISOLATION"|"JOIN"|"LANGUAGE"|"LARGE"|"LATERAL"|"LEADING"|"LEFT"|"LIKE"|"LOCAL"|"LOCALTIME"|"LOCALTIMESTAMP"|"MATCH"|"MEMBER"|"MERGE"|"METHOD"|"MINUTE") +keywords8 ("MODIFIES"|"MODULE"|"MONTH"|"MULTISET"|"NATIONAL"|"NATURAL"|"NEW"|"NO"|"NONE"|"NOT"|"OF"|"OLD"|"ON"|"ONLY"|"OPEN"|"OR"|"ORDER"|"OUT"|"OUTER"|"OUTPUT") +keywords9 ("OVER"|"OVERLAPS"|"PARAMETER"|"PARTITION"|"PRECISION"|"PREPARE"|"PRIMARY"|"PROCEDURE"|"RANGE"|"READS"|"RECURSIVE"|"REF"|"REFERENCES"|"REFERENCING"|"REGR_AVGX"|"REGR_AVGY") +keywords10 ("REGR_COUNT"|"REGR_INTERCEPT"|"REGR_R2"|"REGR_SLOPE"|"REGR_SXX"|"REGR_SXY"|"REGR_SYY"|"RELEASE"|"RESULT"|"RETURN"|"RETURNS"|"REVOKE"|"RIGHT"|"ROLLBACK"|"ROLLUP"|"ROW"|"ROWS"|"SAVEPOINT") +keywords11 ("SCROLL"|"SEARCH"|"SECOND"|"SELECT"|"SENSITIVE"|"SESSION_USER"|"SET"|"SIMILAR"|"SOME"|"SPECIFIC"|"SPECIFICTYPE"|"SQL"|"SQLEXCEPTION"|"SQLSTATE"|"SQLWARNING"|"START"|"STATIC") +keywords12 ("SUBMULTISET"|"SYMMETRIC"|"SYSTEM"|"SYSTEM_USER"|"TABLE"|"THEN"|"TIMEZONE_HOUR"|"TIMEZONE_MINUTE"|"TO"|"TRAILING"|"TRANSLATION"|"TREAT"|"TRIGGER"|"UESCAPE"|"UNION") +keywords13 ("UNIQUE"|"UNNEST"|"UPDATE"|"UPPER"|"USER"|"USING"|"VALUE"|"VALUES"|"VAR_POP"|"VAR_SAMP"|"VARYING"|"WHEN"|"WHENEVER"|"WHERE"|"WIDTH_BUCKET"|"WINDOW"|"WITH"|"WITHIN"|"WITHOUT"|"YEAR") + +/* Need multiple keyword definitions due to max length */ +keyword (?i:{keywords1}|{keywords2}|{keywords3}|{keywords4}|{keywords5}|{keywords6}|{keywords7}|{keywords8}|{keywords9}|{keywords10}|{keywords11}|{keywords12}|{keywords13}) + +typekeyword (?i:"ARRAY"|"BIGINT"|"BINARY"|"BLOB"|"BOOLEAN"|"CHAR"|"CHARACTER"|"CLOB"|"DATE"|"DEC"|"DECIMAL"|"DOUBLE"|"FLOAT"|"INT"|"INTEGER"|"NCHAR"|"NCLOB"|"NUMERIC"|"NVARCHAR"|"REAL"|"SMALLINT"|"TIME"|"TIMESTAMP"|"VARCHAR") + +flowkeyword (?i:"CASE"|"IF"|"ELSE"|"BEGIN"|"END"|"WHILE") + +literalkeyword (?i:"FALSE"|"TRUE"|"NULL"|"UNKNOWN") +stringliteral (\"[^"]*\")|('[^']*') +number [0-9]+ +literals ({literalkeyword}|{stringliteral}|{number}) + +variable @{idchar}+ + +simplecomment --.* +commentopen "/\*" +commentclose "\*/" + +%x COMMENT + +%% + +{literals} { + startFontClass("stringliteral",yyscanner); + codifyLines(yytext,yyscanner); + endFontClass(yyscanner); + } + + +{keyword} { + startFontClass("keyword",yyscanner); + codifyLines(yytext,yyscanner); + endFontClass(yyscanner); + } + +{flowkeyword} { + startFontClass("keywordflow",yyscanner); + codifyLines(yytext,yyscanner); + endFontClass(yyscanner); + } + +{typekeyword} { + startFontClass("keywordtype",yyscanner); + codifyLines(yytext,yyscanner); + endFontClass(yyscanner); + } + +{variable} { + startFontClass("preprocessor",yyscanner); + codifyLines(yytext,yyscanner); + endFontClass(yyscanner); + } + +{simplecomment} { + startFontClass("comment",yyscanner); + codifyLines(yytext,yyscanner); + endFontClass(yyscanner); + } + +{commentopen} { + startFontClass("comment",yyscanner); + codifyLines(yytext,yyscanner); + BEGIN(COMMENT); + } + +<COMMENT>. { + codifyLines(yytext,yyscanner); + + } +<COMMENT>{nl} { + codifyLines(yytext,yyscanner); + } + +<COMMENT>{commentclose} { + codifyLines(yytext,yyscanner); + endFontClass(yyscanner); + BEGIN(INITIAL); + } + +{idchar} { + codifyLines(yytext,yyscanner); + } + +{nl} { + codifyLines(yytext,yyscanner); + } + +. { + codifyLines(yytext,yyscanner); + } + +%% + + +static void codify(const char* text, yyscan_t yyscanner) { - g_code->codify(text); + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + yyextra->code->codify(text); } -static void setCurrentDoc(const QCString &anchor) +static void setCurrentDoc(const QCString &anchor, yyscan_t yyscanner) { + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; if (Doxygen::searchIndex) { - if (g_searchCtx) + if (yyextra->searchCtx) { - Doxygen::searchIndex->setCurrentDoc(g_searchCtx,g_searchCtx->anchor(),FALSE); + Doxygen::searchIndex->setCurrentDoc(yyextra->searchCtx,yyextra->searchCtx->anchor(),FALSE); } else { - Doxygen::searchIndex->setCurrentDoc(g_sourceFileDef,anchor,TRUE); + Doxygen::searchIndex->setCurrentDoc(yyextra->sourceFileDef,anchor,TRUE); } } } -/*! start a new line of code, inserting a line number if g_sourceFileDef +/*! start a new line of code, inserting a line number if yyextra->sourceFileDef * is TRUE. If a definition starts at the current line, then the line * number is linked to the documentation of that definition. */ -static void startCodeLine() +static void startCodeLine(yyscan_t yyscanner) { - if (g_sourceFileDef) + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + if (yyextra->sourceFileDef) { - Definition *d = g_sourceFileDef->getSourceDefinition(g_yyLineNr); + Definition *d = yyextra->sourceFileDef->getSourceDefinition(yyextra->yyLineNr); - if (!g_includeCodeFragment && d && d->isLinkableInProject()) + if (!yyextra->includeCodeFragment && d && d->isLinkableInProject()) { - g_currentDefinition = d; - g_currentMemberDef = g_sourceFileDef->getSourceMember(g_yyLineNr); - g_classScope = d->name().copy(); + yyextra->currentDefinition = d; + yyextra->currentMemberDef = yyextra->sourceFileDef->getSourceMember(yyextra->yyLineNr); + yyextra->classScope = d->name().copy(); QCString lineAnchor; - lineAnchor.sprintf("l%05d",g_yyLineNr); - if (g_currentMemberDef) + lineAnchor.sprintf("l%05d",yyextra->yyLineNr); + if (yyextra->currentMemberDef) { - g_code->writeLineNumber(g_currentMemberDef->getReference(), - g_currentMemberDef->getOutputFileBase(), - g_currentMemberDef->anchor(),g_yyLineNr); - setCurrentDoc(lineAnchor); + yyextra->code->writeLineNumber(yyextra->currentMemberDef->getReference(), + yyextra->currentMemberDef->getOutputFileBase(), + yyextra->currentMemberDef->anchor(),yyextra->yyLineNr); + setCurrentDoc(lineAnchor,yyscanner); } else { - g_code->writeLineNumber(d->getReference(), + yyextra->code->writeLineNumber(d->getReference(), d->getOutputFileBase(), - 0,g_yyLineNr); - setCurrentDoc(lineAnchor); + 0,yyextra->yyLineNr); + setCurrentDoc(lineAnchor,yyscanner); } } else { - g_code->writeLineNumber(0,0,0,g_yyLineNr); + yyextra->code->writeLineNumber(0,0,0,yyextra->yyLineNr); } } - g_code->startCodeLine(g_sourceFileDef); + yyextra->code->startCodeLine(yyextra->sourceFileDef); - if (g_currentFontClass) + if (yyextra->currentFontClass) { - g_code->startFontClass(g_currentFontClass); + yyextra->code->startFontClass(yyextra->currentFontClass); } } -static void endFontClass() +static void endFontClass(yyscan_t yyscanner) { - if (g_currentFontClass) + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + if (yyextra->currentFontClass) { - g_code->endFontClass(); - g_currentFontClass=0; + yyextra->code->endFontClass(); + yyextra->currentFontClass=0; } } -static void endCodeLine() +static void endCodeLine(yyscan_t yyscanner) { - endFontClass(); - g_code->endCodeLine(); + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + endFontClass(yyscanner); + yyextra->code->endCodeLine(); } -static void nextCodeLine() +static void nextCodeLine(yyscan_t yyscanner) { - const char *fc = g_currentFontClass; - endCodeLine(); - if (g_yyLineNr<g_inputLines) + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + const char *fc = yyextra->currentFontClass; + endCodeLine(yyscanner); + if (yyextra->yyLineNr<yyextra->inputLines) { - g_currentFontClass = fc; - startCodeLine(); + yyextra->currentFontClass = fc; + startCodeLine(yyscanner); } } -static void codifyLines(char *text) +static void codifyLines(char *text,yyscan_t yyscanner) { + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; char *p=text,*sp=p; char c; bool done=FALSE; @@ -170,30 +302,32 @@ static void codifyLines(char *text) if (c=='\n') { - g_yyLineNr++; + yyextra->yyLineNr++; *(p-1)='\0'; - g_code->codify(sp); - nextCodeLine(); + yyextra->code->codify(sp); + nextCodeLine(yyscanner); } else { - g_code->codify(sp); + yyextra->code->codify(sp); done=TRUE; } } } -static void startFontClass(const char *s) +static void startFontClass(const char *s,yyscan_t yyscanner) { - endFontClass(); - g_code->startFontClass(s); - g_currentFontClass=s; + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + endFontClass(yyscanner); + yyextra->code->startFontClass(s); + yyextra->currentFontClass=s; } /*! counts the number of lines in the input */ -static int countLines() +static int countLines(yyscan_t yyscanner) { - const char *p=g_inputString; + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + const char *p=yyextra->inputString; char c; int count=1; while ((c=*p)) @@ -201,142 +335,31 @@ static int countLines() p++ ; if (c=='\n') count++; } - if (p>g_inputString && *(p-1)!='\n') + if (p>yyextra->inputString && *(p-1)!='\n') { // last line does not end with a \n, so we add an extra // line and explicitly terminate the line after parsing. count++, - g_needsTermination=TRUE; + yyextra->needsTermination=TRUE; } return count; } -#undef YY_INPUT -#define YY_INPUT(buf,result,max_size) result=yyread(buf,max_size); - -static int yyread(char *buf,int max_size) +static int yyread(char *buf,int max_size,yyscan_t yyscanner) { + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; int c=0; - while( c < max_size && g_inputString[g_inputPosition] ) + while( c < max_size && yyextra->inputString[yyextra->inputPosition] ) { - *buf = g_inputString[g_inputPosition++] ; + *buf = yyextra->inputString[yyextra->inputPosition++] ; c++; buf++; } return c; } -%} - -nl (\r\n|\r|\n) -ws [ \t]+ -idchar [A-Za-z0-9\-_]+ -keywords1 ("ADD"|"ALL"|"ALLOCATE"|"ALTER"|"AND"|"ANY"|"ARE"|"AS"|"ASENSITIVE"|"ASYMMETRIC"|"AT"|"ATOMIC"|"AUTHORIZATION"|"BETWEEN"|"BOTH"|"BY"|"CALL"|"CALLED"|"CASCADED"|"CAST") -keywords2 ("CHECK"|"CLOSE"|"COLLATE"|"COLUMN"|"COMMIT"|"CONNECT"|"CONSTRAINT"|"CONTINUE"|"CORRESPONDING"|"CREATE"|"CROSS"|"CUBE"|"CURRENT"|"CURRENT_DATE"|"CURRENT_DEFAULT_TRANSFORM_GROUP") -keywords3 ("CURRENT_PATH"|"CURRENT_ROLE"|"CURRENT_TIME"|"CURRENT_TIMESTAMP"|"CURRENT_TRANSFORM_GROUP_FOR_TYPE"|"CURRENT_USER") -keywords4 ("CURSOR"|"CYCLE"|"DAY"|"DEALLOCATE"|"DECLARE"|"DEFAULT"|"DELETE"|"DEREF"|"DESCRIBE"|"DETERMINISTIC"|"DISCONNECT"|"DISTINCT"|"DROP"|"DYNAMIC") -keywords5 ("EACH"|"ELEMENT"|"END-EXEC"|"ESCAPE"|"EXCEPT"|"EXEC"|"EXECUTE"|"EXISTS"|"EXTERNAL"|"FETCH"|"FILTER"|"FOR"|"FOREIGN"|"FREE"|"FROM"|"FULL"|"FUNCTION") -keywords6 ("GET"|"GLOBAL"|"GRANT"|"GROUP"|"GROUPING"|"HAVING"|"HOLD"|"HOUR"|"IDENTITY"|"IMMEDIATE"|"IN"|"INDICATOR"|"INNER"|"INOUT"|"INPUT"|"INSENSITIVE"|"INSERT"|"INTERSECT") -keywords7 ("INTERVAL"|"INTO"|"IS"|"ISOLATION"|"JOIN"|"LANGUAGE"|"LARGE"|"LATERAL"|"LEADING"|"LEFT"|"LIKE"|"LOCAL"|"LOCALTIME"|"LOCALTIMESTAMP"|"MATCH"|"MEMBER"|"MERGE"|"METHOD"|"MINUTE") -keywords8 ("MODIFIES"|"MODULE"|"MONTH"|"MULTISET"|"NATIONAL"|"NATURAL"|"NEW"|"NO"|"NONE"|"NOT"|"OF"|"OLD"|"ON"|"ONLY"|"OPEN"|"OR"|"ORDER"|"OUT"|"OUTER"|"OUTPUT") -keywords9 ("OVER"|"OVERLAPS"|"PARAMETER"|"PARTITION"|"PRECISION"|"PREPARE"|"PRIMARY"|"PROCEDURE"|"RANGE"|"READS"|"RECURSIVE"|"REF"|"REFERENCES"|"REFERENCING"|"REGR_AVGX"|"REGR_AVGY") -keywords10 ("REGR_COUNT"|"REGR_INTERCEPT"|"REGR_R2"|"REGR_SLOPE"|"REGR_SXX"|"REGR_SXY"|"REGR_SYY"|"RELEASE"|"RESULT"|"RETURN"|"RETURNS"|"REVOKE"|"RIGHT"|"ROLLBACK"|"ROLLUP"|"ROW"|"ROWS"|"SAVEPOINT") -keywords11 ("SCROLL"|"SEARCH"|"SECOND"|"SELECT"|"SENSITIVE"|"SESSION_USER"|"SET"|"SIMILAR"|"SOME"|"SPECIFIC"|"SPECIFICTYPE"|"SQL"|"SQLEXCEPTION"|"SQLSTATE"|"SQLWARNING"|"START"|"STATIC") -keywords12 ("SUBMULTISET"|"SYMMETRIC"|"SYSTEM"|"SYSTEM_USER"|"TABLE"|"THEN"|"TIMEZONE_HOUR"|"TIMEZONE_MINUTE"|"TO"|"TRAILING"|"TRANSLATION"|"TREAT"|"TRIGGER"|"UESCAPE"|"UNION") -keywords13 ("UNIQUE"|"UNNEST"|"UPDATE"|"UPPER"|"USER"|"USING"|"VALUE"|"VALUES"|"VAR_POP"|"VAR_SAMP"|"VARYING"|"WHEN"|"WHENEVER"|"WHERE"|"WIDTH_BUCKET"|"WINDOW"|"WITH"|"WITHIN"|"WITHOUT"|"YEAR") - -/* Need multiple keyword definitions due to max length */ -keyword (?i:{keywords1}|{keywords2}|{keywords3}|{keywords4}|{keywords5}|{keywords6}|{keywords7}|{keywords8}|{keywords9}|{keywords10}|{keywords11}|{keywords12}|{keywords13}) - -typekeyword (?i:"ARRAY"|"BIGINT"|"BINARY"|"BLOB"|"BOOLEAN"|"CHAR"|"CHARACTER"|"CLOB"|"DATE"|"DEC"|"DECIMAL"|"DOUBLE"|"FLOAT"|"INT"|"INTEGER"|"NCHAR"|"NCLOB"|"NUMERIC"|"NVARCHAR"|"REAL"|"SMALLINT"|"TIME"|"TIMESTAMP"|"VARCHAR") - -flowkeyword (?i:"CASE"|"IF"|"ELSE"|"BEGIN"|"END"|"WHILE") - -literalkeyword (?i:"FALSE"|"TRUE"|"NULL"|"UNKNOWN") -stringliteral (\"[^"]*\")|('[^']*') -number [0-9]+ -literals ({literalkeyword}|{stringliteral}|{number}) -variable @{idchar}+ - -simplecomment --.* -commentopen "/\*" -commentclose "\*/" - -%option noyywrap -%option nounput - -%x COMMENT - -%% - -{literals} { - startFontClass("stringliteral"); - codifyLines(yytext); - endFontClass(); - } - - -{keyword} { - startFontClass("keyword"); - codifyLines(yytext); - endFontClass(); - } - -{flowkeyword} { - startFontClass("keywordflow"); - codifyLines(yytext); - endFontClass(); - } - -{typekeyword} { - startFontClass("keywordtype"); - codifyLines(yytext); - endFontClass(); - } - -{variable} { - startFontClass("preprocessor"); - codifyLines(yytext); - endFontClass(); - } - -{simplecomment} { - startFontClass("comment"); - codifyLines(yytext); - endFontClass(); - } - -{commentopen} { - startFontClass("comment"); - codifyLines(yytext); - BEGIN(COMMENT); - } - -<COMMENT>. { - codifyLines(yytext); - } -<COMMENT>{nl} { - codifyLines(yytext); - } - -<COMMENT>{commentclose} { - codifyLines(yytext); - endFontClass(); - BEGIN(INITIAL); - } - -{idchar} { - codifyLines(yytext); - } - -{nl} { - codifyLines(yytext); - } - -. { - codifyLines(yytext); - } - -%% +// public interface ----------------------------------------------------------- +static yyscan_t yyscanner; +static struct sqlcodeYY_state sqlcode_extra; void parseSqlCode( CodeOutputInterface &od, @@ -348,74 +371,86 @@ void parseSqlCode( int startLine, int endLine, bool inlineFragment, - MemberDef *, - bool,Definition *searchCtx, + const MemberDef *, + bool,const Definition *searchCtx, bool /*collectXRefs*/ ) { if (s.isEmpty()) return; + + sqlcodeYYlex_init_extra(&sqlcode_extra, &yyscanner); + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + +#ifdef FLEX_DEBUG + yyset_debug(1,yyscanner); +#endif + + printlex(yy_flex_debug, TRUE, __FILE__, fd ? fd->fileName().data(): NULL); - g_code = &od; - g_inputString = s; - g_inputPosition = 0; - g_currentFontClass = 0; - g_needsTermination = FALSE; - g_searchCtx=searchCtx; + yyextra->code = &od; + yyextra->inputString = s; + yyextra->inputPosition = 0; + yyextra->currentFontClass = 0; + yyextra->needsTermination = FALSE; + yyextra->searchCtx=searchCtx; if (startLine!=-1) - g_yyLineNr = startLine; + yyextra->yyLineNr = startLine; else - g_yyLineNr = 1; + yyextra->yyLineNr = 1; if (endLine!=-1) - g_inputLines = endLine+1; + yyextra->inputLines = endLine+1; else - g_inputLines = g_yyLineNr + countLines() - 1; + yyextra->inputLines = yyextra->yyLineNr + countLines(yyscanner) - 1; - g_exampleBlock = exBlock; - g_exampleName = exName; - g_sourceFileDef = fd; + yyextra->exampleBlock = exBlock; + yyextra->exampleName = exName; + yyextra->sourceFileDef = fd; bool cleanupSourceDef = FALSE; if (exBlock && fd==0) { // create a dummy filedef for the example - g_sourceFileDef = createFileDef("",(exName?exName:"generated")); + yyextra->sourceFileDef = createFileDef("",(exName?exName:"generated")); cleanupSourceDef = TRUE; } - if (g_sourceFileDef) + if (yyextra->sourceFileDef) { - setCurrentDoc("l00001"); + setCurrentDoc("l00001",yyscanner); } - g_includeCodeFragment = inlineFragment; + yyextra->includeCodeFragment = inlineFragment; // Starts line 1 on the output - startCodeLine(); + startCodeLine(yyscanner); - sqlcodeYYrestart( sqlcodeYYin ); + sqlcodeYYrestart( yyin,yyscanner ); - sqlcodeYYlex(); + sqlcodeYYlex(yyscanner); - if (g_needsTermination) + if (yyextra->needsTermination) { - endCodeLine(); + endCodeLine(yyscanner); } if (cleanupSourceDef) { // delete the temporary file definition used for this example - delete g_sourceFileDef; - g_sourceFileDef=0; + delete yyextra->sourceFileDef; + yyextra->sourceFileDef=0; } + printlex(yy_flex_debug, FALSE, __FILE__, fd ? fd->fileName().data(): NULL); + sqlcodeYYlex_destroy(yyscanner); return; } void resetSqlCodeParserState() { - g_currentDefinition = 0; - g_currentMemberDef = 0; + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + yyextra->currentDefinition = 0; + yyextra->currentMemberDef = 0; } #if !defined(YY_FLEX_SUBMINOR_VERSION) diff --git a/src/sqlite3gen.cpp b/src/sqlite3gen.cpp index a1ea115..012a0c0 100644 --- a/src/sqlite3gen.cpp +++ b/src/sqlite3gen.cpp @@ -1015,16 +1015,16 @@ static void insertMemberReference(const MemberDef *src, const MemberDef *dst, co static void insertMemberFunctionParams(int memberdef_id, const MemberDef *md, const Definition *def) { - ArgumentList *declAl = md->declArgumentList(); - ArgumentList *defAl = md->argumentList(); + const ArgumentList *declAl = md->declArgumentList(); + const ArgumentList *defAl = md->argumentList(); if (declAl!=0 && defAl!=0 && declAl->count()>0) { ArgumentListIterator declAli(*declAl); ArgumentListIterator defAli(*defAl); - Argument *a; + const Argument *a; for (declAli.toFirst();(a=declAli.current());++declAli) { - Argument *defArg = defAli.current(); + const Argument *defArg = defAli.current(); if (!a->attrib.isEmpty()) { @@ -1410,7 +1410,7 @@ static void writeTemplateArgumentList(const ArgumentList * al, static void writeMemberTemplateLists(const MemberDef *md) { - ArgumentList *templMd = md->templateArguments(); + const ArgumentList *templMd = md->templateArguments(); if (templMd) // function template prefix { writeTemplateArgumentList(templMd,md->getClassDef(),md->getFileDef()); @@ -1434,7 +1434,7 @@ QCString getSQLDocBlock(const Definition *scope, fileName, lineNr, const_cast<Definition*>(scope), - const_cast<MemberDef*>(reinterpret_cast<const MemberDef*>(def)), + dynamic_cast<const MemberDef*>(def), doc, FALSE, FALSE @@ -1675,7 +1675,7 @@ static void generateSqlite3ForMember(const MemberDef *md, struct Refid scope_ref if (isFunc) { - ArgumentList *al = md->argumentList(); + const ArgumentList *al = md->argumentList(); if (al!=0) { bindIntParameter(memberdef_insert,":const",al->constSpecifier); @@ -2009,7 +2009,11 @@ static void generateSqlite3ForClass(const ClassDef *cd) if (nm.isEmpty() && ii->fileDef) nm = ii->fileDef->docName(); if (!nm.isEmpty()) { - int header_id=insertPath(ii->fileDef->absFilePath(),!ii->fileDef->isReference()); + int header_id=-1; + if (ii->fileDef) + { + insertPath(ii->fileDef->absFilePath(),!ii->fileDef->isReference()); + } DBG_CTX(("-----> ClassDef includeInfo for %s\n", nm.data())); DBG_CTX((" local : %d\n", ii->local)); DBG_CTX((" imported : %d\n", ii->imported)); diff --git a/src/sqlscanner.h b/src/sqlscanner.h index 7afa869..3ca6fe3 100644 --- a/src/sqlscanner.h +++ b/src/sqlscanner.h @@ -41,9 +41,9 @@ public: int startLine=-1, int endLine=-1, bool inlineFragment=FALSE, - MemberDef *memberDef=0, + const MemberDef *memberDef=0, bool showLineNumbers=TRUE, - Definition *searchCtx=0, + const Definition *searchCtx=0, bool collectXRefs=TRUE ) { diff --git a/src/tclscanner.h b/src/tclscanner.h index aa1673c..0e56bdd 100644 --- a/src/tclscanner.h +++ b/src/tclscanner.h @@ -47,9 +47,9 @@ class TclLanguageScanner : public ParserInterface int startLine=-1, int endLine=-1, bool inlineFragment=FALSE, - MemberDef *memberDef=0, + const MemberDef *memberDef=0, bool showLineNumbers=TRUE, - Definition *searchCtx=0, + const Definition *searchCtx=0, bool collectXRefs=TRUE ); void resetCodeParserState(); diff --git a/src/tclscanner.l b/src/tclscanner.l index 88714ce..9ec512a 100644 --- a/src/tclscanner.l +++ b/src/tclscanner.l @@ -456,7 +456,7 @@ static struct QAsciiDict<Entry> fn; // all read function entries QList<Entry> entry; // list of all created entries, will be deleted after codifying Protection protection; // current protections state - MemberDef *memberdef; // contain current MemberDef when codifying + const MemberDef *memberdef; // contain current MemberDef when codifying bool collectXRefs; } tcl; @@ -486,7 +486,7 @@ Entry* tcl_entry_new() // myEntry->stat = FALSE; myEntry->fileName = tcl.file_name; myEntry->lang = SrcLangExt_Tcl; - initGroupInfo(myEntry); + Doxygen::docGroup.initGroupInfo(myEntry); // collect entries if (!tcl.code) { @@ -1722,7 +1722,7 @@ static void tcl_codify_link(QCString name) if (tcl.memberdef) { myDef->addSourceReferencedBy(tcl.memberdef); - tcl.memberdef->addSourceReferences(myDef); + //tcl.memberdef->addSourceReferences(myDef); } else { Entry* callerEntry; unsigned int i; @@ -2950,7 +2950,7 @@ tcl_inf("%s\n",fileName); printlex(yy_flex_debug, TRUE, __FILE__, fileName); msg("Parsing %s...\n",fileName); - groupEnterFile(fileName,yylineno); + Doxygen::docGroup.enterFile(fileName,yylineno); tcl_init(); tcl.code = NULL; @@ -2958,7 +2958,7 @@ tcl_inf("%s\n",fileName); tcl.this_parser = this; tcl.entry_main = root; /* toplevel entry */ tcl_parse("",""); - groupLeaveFile(tcl.file_name,yylineno); + Doxygen::docGroup.leaveFile(tcl.file_name,yylineno); root->program.resize(0); myFile.close(); printlex(yy_flex_debug, FALSE, __FILE__, fileName); @@ -2975,9 +2975,9 @@ void TclLanguageScanner::parseCode(CodeOutputInterface & codeOutIntf, int startLine, int endLine, bool inlineFragment, - MemberDef *memberDef, + const MemberDef *memberDef, bool showLineNumbers, - Definition *searchCtx, + const Definition *searchCtx, bool collectXRefs ) { diff --git a/src/textdocvisitor.h b/src/textdocvisitor.h index bbc70e8..c4ba3d7 100644 --- a/src/textdocvisitor.h +++ b/src/textdocvisitor.h @@ -125,8 +125,6 @@ class TextDocVisitor : public DocVisitor void visitPost(DocXRefItem *) {} void visitPre(DocInternalRef *) {} void visitPost(DocInternalRef *) {} - void visitPre(DocCopy *) {} - void visitPost(DocCopy *) {} void visitPre(DocText *) {} void visitPost(DocText *) {} void visitPre(DocHtmlBlockQuote *) {} diff --git a/src/tooltip.cpp b/src/tooltip.cpp index 2c6f6e1..a30a85c 100644 --- a/src/tooltip.cpp +++ b/src/tooltip.cpp @@ -68,7 +68,7 @@ static QCString escapeId(const char *s) return res; } -void TooltipManager::addTooltip(Definition *d) +void TooltipManager::addTooltip(const Definition *d) { static bool sourceTooltips = Config_getBool(SOURCE_TOOLTIPS); if (!sourceTooltips) return; diff --git a/src/tooltip.h b/src/tooltip.h index 34a578a..170ea3c 100644 --- a/src/tooltip.h +++ b/src/tooltip.h @@ -23,7 +23,7 @@ class TooltipManager public: static TooltipManager *instance(); void clearTooltips(); - void addTooltip(Definition *d); + void addTooltip(const Definition *d); void writeTooltips(CodeOutputInterface &ol); private: diff --git a/src/util.cpp b/src/util.cpp index 507ced9..695a52c 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -346,8 +346,8 @@ int guessSection(const char *name) return 0; } -QCString resolveTypeDef(Definition *context,const QCString &qualifiedName, - Definition **typedefContext) +QCString resolveTypeDef(const Definition *context,const QCString &qualifiedName, + const Definition **typedefContext) { //printf("<<resolveTypeDef(%s,%s)\n", // context ? context->name().data() : "<none>",qualifiedName.data()); @@ -358,7 +358,7 @@ QCString resolveTypeDef(Definition *context,const QCString &qualifiedName, return result; } - Definition *mContext=context; + const Definition *mContext=context; if (typedefContext) *typedefContext=context; // see if the qualified name has a scope part @@ -378,7 +378,7 @@ QCString resolveTypeDef(Definition *context,const QCString &qualifiedName, while (mContext && md==0) { // step 1: get the right scope - Definition *resScope=mContext; + const Definition *resScope=mContext; if (scopeIndex!=-1) { // split-off scope part @@ -518,10 +518,10 @@ static QDict<MemberDef> g_resolvedTypedefs; static QDict<Definition> g_visitedNamespaces; // forward declaration -static ClassDef *getResolvedClassRec(const Definition *scope, +static const ClassDef *getResolvedClassRec(const Definition *scope, const FileDef *fileScope, const char *n, - MemberDef **pTypeDef, + const MemberDef **pTypeDef, QCString *pTemplSpec, QCString *pResolvedType ); @@ -535,10 +535,12 @@ int isAccessibleFromWithExpScope(const Definition *scope,const FileDef *fileScop * * Example: typedef int T; will return 0, since "int" is not a class. */ -ClassDef *newResolveTypedef(const FileDef *fileScope,MemberDef *md, - MemberDef **pMemType,QCString *pTemplSpec, - QCString *pResolvedType, - ArgumentList *actTemplParams) +const ClassDef *newResolveTypedef(const FileDef *fileScope, + const MemberDef *md, + const MemberDef **pMemType, + QCString *pTemplSpec, + QCString *pResolvedType, + ArgumentList *actTemplParams) { //printf("newResolveTypedef(md=%p,cachedVal=%p)\n",md,md->getCachedTypedefVal()); bool isCached = md->isTypedefValCached(); // value already cached @@ -559,7 +561,7 @@ ClassDef *newResolveTypedef(const FileDef *fileScope,MemberDef *md, g_resolvedTypedefs.insert(qname,md); // put on the trace list - ClassDef *typeClass = md->getClassDef(); + const ClassDef *typeClass = md->getClassDef(); QCString type = md->typeString(); // get the "value" of the typedef if (typeClass && typeClass->isTemplate() && actTemplParams && actTemplParams->count()>0) @@ -581,8 +583,8 @@ ClassDef *newResolveTypedef(const FileDef *fileScope,MemberDef *md, int sp=0; tl=type.length(); // length may have been changed while (sp<tl && type.at(sp)==' ') sp++; - MemberDef *memTypeDef = 0; - ClassDef *result = getResolvedClassRec(md->getOuterScope(), + const MemberDef *memTypeDef = 0; + const ClassDef *result = getResolvedClassRec(md->getOuterScope(), fileScope,type,&memTypeDef,0,pResolvedType); // if type is a typedef then return what it resolves to. if (memTypeDef && memTypeDef->isTypedef()) @@ -652,7 +654,7 @@ done: //printf("setting cached typedef %p in result %p\n",md,result); //printf("==> %s (%s,%d)\n",result->name().data(),result->getDefFileName().data(),result->getDefLine()); //printf("*pResolvedType=%s\n",pResolvedType?pResolvedType->data():"<none>"); - md->cacheTypedefVal(result, + const_cast<MemberDef*>(md)->cacheTypedefVal(result, pTemplSpec ? *pTemplSpec : QCString(), pResolvedType ? *pResolvedType : QCString() ); @@ -667,7 +669,7 @@ done: * value of the typedef or \a name if no typedef was found. */ static QCString substTypedef(const Definition *scope,const FileDef *fileScope,const QCString &name, - MemberDef **pTypeDef=0) + const MemberDef **pTypeDef=0) { QCString result=name; if (name.isEmpty()) return result; @@ -730,7 +732,7 @@ static QCString substTypedef(const Definition *scope,const FileDef *fileScope,co return result; } -static Definition *endOfPathIsUsedClass(SDict<Definition> *cl,const QCString &localName) +static const Definition *endOfPathIsUsedClass(const SDict<Definition> *cl,const QCString &localName) { if (cl) { @@ -763,12 +765,12 @@ static const Definition *followPath(const Definition *start,const FileDef *fileS while ((is=getScopeFragment(path,ps,&l))!=-1) { // try to resolve the part if it is a typedef - MemberDef *typeDef=0; + const MemberDef *typeDef=0; QCString qualScopePart = substTypedef(current,fileScope,path.mid(is,l),&typeDef); //printf(" qualScopePart=%s\n",qualScopePart.data()); if (typeDef) { - ClassDef *type = newResolveTypedef(fileScope,typeDef); + const ClassDef *type = newResolveTypedef(fileScope,typeDef); if (type) { //printf("Found type %s\n",type->name().data()); @@ -852,18 +854,21 @@ bool accessibleViaUsingNamespace(const NamespaceSDict *nl, //printf("] found it\n"); return TRUE; } - QCString key=und->name(); - if (und->getUsedNamespaces() && visitedDict.find(key)==0) + if (item->getLanguage()==SrcLangExt_Cpp) { - visitedDict.insert(key,(void *)0x08); - - if (accessibleViaUsingNamespace(und->getUsedNamespaces(),fileScope,item,explicitScopePart)) + QCString key=und->name(); + if (und->getUsedNamespaces() && visitedDict.find(key)==0) { - //printf("] found it via recursion\n"); - return TRUE; - } + visitedDict.insert(key,(void *)0x08); + + if (accessibleViaUsingNamespace(und->getUsedNamespaces(),fileScope,item,explicitScopePart)) + { + //printf("] found it via recursion\n"); + return TRUE; + } - visitedDict.remove(key); + visitedDict.remove(key); + } } //printf("] Try via used namespace done\n"); } @@ -1011,13 +1016,13 @@ int isAccessibleFrom(const Definition *scope,const FileDef *fileScope,const Defi { const NamespaceDef *nscope = dynamic_cast<const NamespaceDef*>(scope); //printf(" %s is namespace with %d used classes\n",nscope->name().data(),nscope->getUsedClasses()); - SDict<Definition> *cl = nscope->getUsedClasses(); + const SDict<Definition> *cl = nscope->getUsedClasses(); if (accessibleViaUsingClass(cl,fileScope,item)) { //printf("> found via used class\n"); goto done; } - NamespaceSDict *nl = nscope->getUsedNamespaces(); + const NamespaceSDict *nl = nscope->getUsedNamespaces(); if (accessibleViaUsingNamespace(nl,fileScope,item)) { //printf("> found via used namespace\n"); @@ -1115,11 +1120,11 @@ int isAccessibleFromWithExpScope(const Definition *scope,const FileDef *fileScop // in A via a using directive. //printf("newScope is a namespace: %s!\n",newScope->name().data()); const NamespaceDef *nscope = dynamic_cast<const NamespaceDef*>(newScope); - SDict<Definition> *cl = nscope->getUsedClasses(); + const SDict<Definition> *cl = nscope->getUsedClasses(); if (cl) { SDict<Definition>::Iterator cli(*cl); - Definition *cd; + const Definition *cd; for (cli.toFirst();(cd=cli.current());++cli) { //printf("Trying for class %s\n",cd->name().data()); @@ -1130,11 +1135,11 @@ int isAccessibleFromWithExpScope(const Definition *scope,const FileDef *fileScop } } } - NamespaceSDict *nl = nscope->getUsedNamespaces(); + const NamespaceSDict *nl = nscope->getUsedNamespaces(); if (nl) { NamespaceSDict::Iterator nli(*nl); - NamespaceDef *nd; + const NamespaceDef *nd; for (nli.toFirst();(nd=nli.current());++nli) { if (g_visitedNamespaces.find(nd->name())==0) @@ -1166,7 +1171,7 @@ int isAccessibleFromWithExpScope(const Definition *scope,const FileDef *fileScop if (scope->definitionType()==Definition::TypeNamespace) { const NamespaceDef *nscope = dynamic_cast<const NamespaceDef*>(scope); - NamespaceSDict *nl = nscope->getUsedNamespaces(); + const NamespaceSDict *nl = nscope->getUsedNamespaces(); if (accessibleViaUsingNamespace(nl,fileScope,item,explicitScopePart)) { //printf("> found in used namespace\n"); @@ -1177,7 +1182,7 @@ int isAccessibleFromWithExpScope(const Definition *scope,const FileDef *fileScop { if (fileScope) { - NamespaceSDict *nl = fileScope->getUsedNamespaces(); + const NamespaceSDict *nl = fileScope->getUsedNamespaces(); if (accessibleViaUsingNamespace(nl,fileScope,item,explicitScopePart)) { //printf("> found in used namespace\n"); @@ -1215,8 +1220,8 @@ static void getResolvedSymbol(const Definition *scope, const QCString &explicitScopePart, ArgumentList *actTemplParams, int &minDistance, - ClassDef *&bestMatch, - MemberDef *&bestTypedef, + const ClassDef *&bestMatch, + const MemberDef *&bestTypedef, QCString &bestTemplSpec, QCString &bestResolvedType ) @@ -1303,8 +1308,8 @@ static void getResolvedSymbol(const Definition *scope, QCString spec; QCString type; minDistance=distance; - MemberDef *enumType = 0; - ClassDef *cd = newResolveTypedef(fileScope,md,&enumType,&spec,&type,actTemplParams); + const MemberDef *enumType = 0; + const ClassDef *cd = newResolveTypedef(fileScope,md,&enumType,&spec,&type,actTemplParams); if (cd) // type resolves to a class { //printf(" bestTypeDef=%p spec=%s type=%s\n",md,spec.data(),type.data()); @@ -1374,10 +1379,10 @@ static void getResolvedSymbol(const Definition *scope, * match against the input name. Can recursively call itself when * resolving typedefs. */ -static ClassDef *getResolvedClassRec(const Definition *scope, +static const ClassDef *getResolvedClassRec(const Definition *scope, const FileDef *fileScope, const char *n, - MemberDef **pTypeDef, + const MemberDef **pTypeDef, QCString *pTemplSpec, QCString *pResolvedType ) @@ -1496,8 +1501,8 @@ static ClassDef *getResolvedClassRec(const Definition *scope, Doxygen::lookupCache->insert(key,new LookupInfo); } - ClassDef *bestMatch=0; - MemberDef *bestTypedef=0; + const ClassDef *bestMatch=0; + const MemberDef *bestTypedef=0; QCString bestTemplSpec; QCString bestResolvedType; int minDistance=10000; // init at "infinite" @@ -1563,10 +1568,10 @@ static ClassDef *getResolvedClassRec(const Definition *scope, * Loops through scope and each of its parent scopes looking for a * match against the input name. */ -ClassDef *getResolvedClass(const Definition *scope, +const ClassDef *getResolvedClass(const Definition *scope, const FileDef *fileScope, const char *n, - MemberDef **pTypeDef, + const MemberDef **pTypeDef, QCString *pTemplSpec, bool mayBeUnlinkable, bool mayBeHidden, @@ -1590,7 +1595,7 @@ ClassDef *getResolvedClass(const Definition *scope, // n, // mayBeUnlinkable // ); - ClassDef *result; + const ClassDef *result; if (optimizeOutputVhdl) { result = getClass(n); @@ -1672,6 +1677,7 @@ struct CharAroundSpace charMap['='].after=FALSE; charMap[' '].after=FALSE; + charMap['['].after=FALSE; charMap[']'].after=FALSE; charMap['\t'].after=FALSE; charMap['\n'].after=FALSE; @@ -1869,7 +1875,7 @@ QCString removeRedundantWhiteSpace(const QCString &s) case '@': // '@name' -> ' @name' case '$': // '$name' -> ' $name' case '\'': // ''name' -> '' name' - if (i>0 && i<l-1 && pc!='=' && pc!=':' && !isspace(pc) && + if (i>0 && i<l-1 && pc!='=' && pc!=':' && !isspace((uchar)pc) && isId(nc) && osp<8) // ")id" -> ") id" { *dst++=' '; @@ -1913,14 +1919,14 @@ QCString removeRedundantWhiteSpace(const QCString &s) default: *dst++=c; if (c=='t' && csp==5 && i<l-1 && // found 't' in 'const' - !(isId(nc) || nc==')' || nc==',' || isspace(nc)) + !(isId(nc) || nc==')' || nc==',' || isspace((uchar)nc)) ) // prevent const ::A from being converted to const::A { *dst++=' '; csp=0; } else if (c=='l' && vsp==7 && i<l-1 && // found 'l' in 'virtual' - !(isId(nc) || nc==')' || nc==',' || isspace(nc)) + !(isId(nc) || nc==')' || nc==',' || isspace((uchar)nc)) ) // prevent virtual ::A from being converted to virtual::A { *dst++=' '; @@ -2028,12 +2034,17 @@ void linkifyText(const TextGeneratorIntf &out, const Definition *scope, int floatingIndex=0; if (strLen==0) return; // read a word from the text string - while ((newIndex=regExp.match(txtStr,index,&matchLen))!=-1 && - (newIndex==0 || !(txtStr.at(newIndex-1)>='0' && txtStr.at(newIndex-1)<='9')) // avoid matching part of hex numbers - ) + while ((newIndex=regExp.match(txtStr,index,&matchLen))!=-1) { - // add non-word part to the result floatingIndex+=newIndex-skipIndex+matchLen; + if (newIndex>0 && txtStr.at(newIndex-1)=='0') // ignore hex numbers (match x00 in 0x00) + { + out.writeString(txtStr.mid(skipIndex,newIndex+matchLen-skipIndex),keepSpaces); + skipIndex=index=newIndex+matchLen; + continue; + } + + // add non-word part to the result bool insideString=FALSE; int i; for (i=index;i<newIndex;i++) @@ -2077,14 +2088,14 @@ void linkifyText(const TextGeneratorIntf &out, const Definition *scope, bool found=FALSE; if (!insideString) { - ClassDef *cd=0; - FileDef *fd=0; - MemberDef *md=0; - NamespaceDef *nd=0; - GroupDef *gd=0; + const MemberDef *md=0; + const ClassDef *cd=0; + const FileDef *fd=0; + const NamespaceDef *nd=0; + const GroupDef *gd=0; //printf("** Match word '%s'\n",matchWord.data()); - MemberDef *typeDef=0; + const MemberDef *typeDef=0; cd=getResolvedClass(scope,fileScope,matchWord,&typeDef); if (typeDef) // First look at typedef then class, see bug 584184. { @@ -2249,12 +2260,12 @@ void writeExample(OutputList &ol,ExampleSDict *ed) } -QCString argListToString(ArgumentList *al,bool useCanonicalType,bool showDefVals) +QCString argListToString(const ArgumentList *al,bool useCanonicalType,bool showDefVals) { QCString result; if (al==0) return result; ArgumentListIterator ali(*al); - Argument *a=ali.current(); + const Argument *a=ali.current(); result+="("; while (a) { @@ -2297,13 +2308,13 @@ QCString argListToString(ArgumentList *al,bool useCanonicalType,bool showDefVals return removeRedundantWhiteSpace(result); } -QCString tempArgListToString(ArgumentList *al,SrcLangExt lang) +QCString tempArgListToString(const ArgumentList *al,SrcLangExt lang) { QCString result; if (al==0) return result; result="<"; ArgumentListIterator ali(*al); - Argument *a=ali.current(); + const Argument *a=ali.current(); while (a) { if (!a->name.isEmpty()) // add template argument name @@ -2662,7 +2673,7 @@ int minClassDistance(const ClassDef *cd,const ClassDef *bcd,int level) return m; } -Protection classInheritedProtectionLevel(ClassDef *cd,ClassDef *bcd,Protection prot,int level) +Protection classInheritedProtectionLevel(const ClassDef *cd,const ClassDef *bcd,Protection prot,int level) { if (bcd->categoryOf()) // use class that is being extended in case of // an Objective-C category @@ -2681,7 +2692,7 @@ Protection classInheritedProtectionLevel(ClassDef *cd,ClassDef *bcd,Protection p else if (cd->baseClasses()) { BaseClassListIterator bcli(*cd->baseClasses()); - BaseClassDef *bcdi; + const BaseClassDef *bcdi; for (;(bcdi=bcli.current()) && prot!=Private;++bcli) { Protection baseProt = classInheritedProtectionLevel(bcdi->classDef,bcd,bcdi->prot,level+1); @@ -3448,9 +3459,9 @@ static QCString stripDeclKeywords(const QCString &s) } // forward decl for circular dependencies -static QCString extractCanonicalType(Definition *d,FileDef *fs,QCString type); +static QCString extractCanonicalType(const Definition *d,const FileDef *fs,QCString type); -QCString getCanonicalTemplateSpec(Definition *d,FileDef *fs,const QCString& spec) +QCString getCanonicalTemplateSpec(const Definition *d,const FileDef *fs,const QCString& spec) { QCString templSpec = spec.stripWhiteSpace(); @@ -3471,7 +3482,7 @@ QCString getCanonicalTemplateSpec(Definition *d,FileDef *fs,const QCString& spec static QCString getCanonicalTypeForIdentifier( - Definition *d,FileDef *fs,const QCString &word, + const Definition *d,const FileDef *fs,const QCString &word, QCString *tSpec,int count=0) { if (count>10) return word; // oops recursion @@ -3492,8 +3503,8 @@ static QCString getCanonicalTypeForIdentifier( //printf("getCanonicalTypeForIdentifier(%s,[%s->%s]) start\n", // word.data(),tSpec?tSpec->data():"<none>",templSpec.data()); - ClassDef *cd = 0; - MemberDef *mType = 0; + const ClassDef *cd = 0; + const MemberDef *mType = 0; QCString ts; QCString resolvedType; @@ -3607,7 +3618,7 @@ static QCString getCanonicalTypeForIdentifier( return result; } -static QCString extractCanonicalType(Definition *d,FileDef *fs,QCString type) +static QCString extractCanonicalType(const Definition *d,const FileDef *fs,QCString type) { type = type.stripWhiteSpace(); @@ -3677,7 +3688,7 @@ static QCString extractCanonicalType(Definition *d,FileDef *fs,QCString type) return removeRedundantWhiteSpace(canType); } -static QCString extractCanonicalArgType(Definition *d,FileDef *fs,const Argument *arg) +static QCString extractCanonicalArgType(const Definition *d,const FileDef *fs,const Argument *arg) { QCString type = arg->type.stripWhiteSpace(); QCString name = arg->name; @@ -3701,8 +3712,8 @@ static QCString extractCanonicalArgType(Definition *d,FileDef *fs,const Argument } static bool matchArgument2( - Definition *srcScope,FileDef *srcFileScope,Argument *srcA, - Definition *dstScope,FileDef *dstFileScope,Argument *dstA + const Definition *srcScope,const FileDef *srcFileScope,Argument *srcA, + const Definition *dstScope,const FileDef *dstFileScope,Argument *dstA ) { //printf(">> match argument: %s::`%s|%s' (%s) <-> %s::`%s|%s' (%s)\n", @@ -3762,10 +3773,9 @@ static bool matchArgument2( // new algorithm for argument matching -bool matchArguments2(Definition *srcScope,FileDef *srcFileScope,ArgumentList *srcAl, - Definition *dstScope,FileDef *dstFileScope,ArgumentList *dstAl, - bool checkCV - ) +bool matchArguments2(const Definition *srcScope,const FileDef *srcFileScope,const ArgumentList *srcAl, + const Definition *dstScope,const FileDef *dstFileScope,const ArgumentList *dstAl, + bool checkCV) { //printf("*** matchArguments2\n"); ASSERT(srcScope!=0 && dstScope!=0); @@ -3791,7 +3801,7 @@ bool matchArguments2(Definition *srcScope,FileDef *srcFileScope,ArgumentList *sr { // special case for finding match between func() and func(void) Argument *a=new Argument; a->type = "void"; - srcAl->append(a); + const_cast<ArgumentList*>(srcAl)->append(a); MATCH return TRUE; } @@ -3800,7 +3810,7 @@ bool matchArguments2(Definition *srcScope,FileDef *srcFileScope,ArgumentList *sr { // special case for finding match between func(void) and func() Argument *a=new Argument; a->type = "void"; - dstAl->append(a); + const_cast<ArgumentList*>(dstAl)->append(a); MATCH return TRUE; } @@ -3987,7 +3997,7 @@ void mergeArguments(ArgumentList *srcAl,ArgumentList *dstAl,bool forceNameOverwr static void findMembersWithSpecificName(MemberName *mn, const char *args, bool checkStatics, - FileDef *currentFile, + const FileDef *currentFile, bool checkCV, const char *forceTagFile, QList<MemberDef> &members) @@ -3995,11 +4005,11 @@ static void findMembersWithSpecificName(MemberName *mn, //printf(" Function with global scope name `%s' args=`%s'\n", // mn->memberName(),args); MemberNameIterator mli(*mn); - MemberDef *md; + const MemberDef *md = 0; for (mli.toFirst();(md=mli.current());++mli) { - FileDef *fd=md->getFileDef(); - GroupDef *gd=md->getGroupDef(); + const FileDef *fd=md->getFileDef(); + const GroupDef *gd=md->getGroupDef(); //printf(" md->name()=`%s' md->args=`%s' fd=%p gd=%p current=%p ref=%s\n", // md->name().data(),args,fd,gd,currentFile,md->getReference().data()); if ( @@ -4014,7 +4024,7 @@ static void findMembersWithSpecificName(MemberName *mn, if (args && !md->isDefine() && qstrcmp(args,"()")!=0) { argList=new ArgumentList; - ArgumentList *mdAl = md->argumentList(); + const ArgumentList *mdAl = md->argumentList(); stringToArgumentList(args,argList); match=matchArguments2( md->getOuterScope(),fd,mdAl, @@ -4056,13 +4066,13 @@ static void findMembersWithSpecificName(MemberName *mn, bool getDefs(const QCString &scName, const QCString &mbName, const char *args, - MemberDef *&md, - ClassDef *&cd, - FileDef *&fd, - NamespaceDef *&nd, - GroupDef *&gd, + const MemberDef *&md, + const ClassDef *&cd, + const FileDef *&fd, + const NamespaceDef *&nd, + const GroupDef *&gd, bool forceEmptyScope, - FileDef *currentFile, + const FileDef *currentFile, bool checkCV, const char *forceTagFile ) @@ -4127,8 +4137,8 @@ bool getDefs(const QCString &scName, className=mScope; } - MemberDef *tmd=0; - ClassDef *fcd=getResolvedClass(Doxygen::globalScope,0,className,&tmd); + const MemberDef *tmd=0; + const ClassDef *fcd=getResolvedClass(Doxygen::globalScope,0,className,&tmd); if (fcd==0 && className.find('<')!=-1) // try without template specifiers as well { QCString nameWithoutTemplates = stripTemplateSpecifiersFromScope(className,FALSE); @@ -4225,7 +4235,7 @@ bool getDefs(const QCString &scName, if (tmd && tmd->isEnumerate() && tmd->isStrong()) // scoped enum { //printf("Found scoped enum!\n"); - MemberList *tml = tmd->enumFieldList(); + const MemberList *tml = tmd->enumFieldList(); if (tml) { MemberListIterator tmi(*tml); @@ -4334,12 +4344,12 @@ bool getDefs(const QCString &scName, // namespaceName.data(),mn->count()); bool found=FALSE; MemberNameIterator mmli(*mn); - MemberDef *mmd; + const MemberDef *mmd; for (mmli.toFirst();((mmd=mmli.current()) && !found);++mmli) { //printf("mmd->getNamespaceDef()=%p fnd=%p\n", // mmd->getNamespaceDef(),fnd); - MemberDef *emd = mmd->getEnumScope(); + const MemberDef *emd = mmd->getEnumScope(); if (emd && emd->isStrong()) { //printf("yes match %s<->%s!\n",mScope.data(),emd->localName().data()); @@ -4358,14 +4368,14 @@ bool getDefs(const QCString &scName, return FALSE; } } - else if (mmd->getNamespaceDef()==fnd /* && mmd->isLinkable() */ ) + else if (mmd->getOuterScope()==fnd /* && mmd->isLinkable() */ ) { // namespace is found bool match=TRUE; ArgumentList *argList=0; if (args && qstrcmp(args,"()")!=0) { argList=new ArgumentList; - ArgumentList *mmdAl = mmd->argumentList(); + const ArgumentList *mmdAl = mmd->argumentList(); stringToArgumentList(args,argList); match=matchArguments2( mmd->getOuterScope(),mmd->getFileDef(),mmdAl, @@ -4398,7 +4408,7 @@ bool getDefs(const QCString &scName, } } } - if (found) + if (found) { if (!md->isLinkable()) { @@ -4408,7 +4418,7 @@ bool getDefs(const QCString &scName, } else { - gd=md->getGroupDef(); + gd=md->resolveAlias()->getGroupDef(); if (gd && gd->isLinkable()) nd=0; else gd=0; return TRUE; } @@ -4421,7 +4431,7 @@ bool getDefs(const QCString &scName, MemberDef *mmd; for (mmli.toFirst();(mmd=mmli.current());++mmli) { - MemberDef *tmd = mmd->getEnumScope(); + const MemberDef *tmd = mmd->getEnumScope(); //printf("try member %s tmd=%s\n",mmd->name().data(),tmd?tmd->name().data():"<none>"); int ni=namespaceName.findRev("::"); //printf("namespaceName=%s ni=%d\n",namespaceName.data(),ni); @@ -4475,7 +4485,7 @@ bool getDefs(const QCString &scName, //printf("member is linkable md->name()=`%s'\n",md->name().data()); fd=md->getFileDef(); gd=md->getGroupDef(); - MemberDef *tmd = md->getEnumScope(); + const MemberDef *tmd = md->getEnumScope(); if ( (gd && gd->isLinkable()) || (fd && fd->isLinkable()) || (tmd && tmd->isStrong()) @@ -4602,10 +4612,10 @@ static bool isLowerCase(QCString &s) bool resolveRef(/* in */ const char *scName, /* in */ const char *name, /* in */ bool inSeeBlock, - /* out */ Definition **resContext, - /* out */ MemberDef **resMember, + /* out */ const Definition **resContext, + /* out */ const MemberDef **resMember, bool lookForSpecialization, - FileDef *currentFile, + const FileDef *currentFile, bool checkScope ) { @@ -4704,11 +4714,11 @@ bool resolveRef(/* in */ const char *scName, QCString scopeStr=scName; - MemberDef *md = 0; - ClassDef *cd = 0; - FileDef *fd = 0; - NamespaceDef *nd = 0; - GroupDef *gd = 0; + const MemberDef *md = 0; + const ClassDef *cd = 0; + const FileDef *fd = 0; + const NamespaceDef *nd = 0; + const GroupDef *gd = 0; // check if nameStr is a member or global. //printf("getDefs(scope=%s,name=%s,args=%s checkScope=%d)\n", @@ -4876,7 +4886,7 @@ bool generateRef(OutputDocInterface &od,const char *scName, bool resolveLink(/* in */ const char *scName, /* in */ const char *lr, /* in */ bool /*inSeeBlock*/, - /* out */ Definition **resContext, + /* out */ const Definition **resContext, /* out */ QCString &resAnchor ) { @@ -4885,12 +4895,12 @@ bool resolveLink(/* in */ const char *scName, QCString linkRef=lr; QCString linkRefWithoutTemplates = stripTemplateSpecifiersFromScope(linkRef,FALSE); //printf("ResolveLink linkRef=%s\n",lr); - FileDef *fd; - GroupDef *gd; - PageDef *pd; - ClassDef *cd; - DirDef *dir; - NamespaceDef *nd; + const FileDef *fd; + const GroupDef *gd; + const PageDef *pd; + const ClassDef *cd; + const DirDef *dir; + const NamespaceDef *nd; SectionInfo *si=0; bool ambig; if (linkRef.isEmpty()) // no reference name! @@ -4899,7 +4909,7 @@ bool resolveLink(/* in */ const char *scName, } else if ((pd=Doxygen::pageSDict->find(linkRef))) // link to a page { - GroupDef *gd = pd->getGroupDef(); + const GroupDef *gd = pd->getGroupDef(); if (gd) { if (!pd->name().isEmpty()) si=Doxygen::sectionDict->find(pd->name()); @@ -4971,7 +4981,7 @@ bool resolveLink(/* in */ const char *scName, } else // probably a member reference { - MemberDef *md; + const MemberDef *md = 0; bool res = resolveRef(scName,lr,TRUE,resContext,&md); if (md) resAnchor=md->anchor(); return res; @@ -4990,7 +5000,7 @@ bool generateLink(OutputDocInterface &od,const char *clName, const char *lr,bool inSeeBlock,const char *lt) { //printf("generateLink(clName=%s,lr=%s,lr=%s)\n",clName,lr,lt); - Definition *compound; + const Definition *compound = 0; //PageDef *pageDef=0; QCString anchor,linkText=linkToText(SrcLangExt_Unknown,lt,FALSE); //printf("generateLink linkText=%s\n",linkText.data()); @@ -5002,7 +5012,7 @@ bool generateLink(OutputDocInterface &od,const char *clName, compound->definitionType()==Definition::TypeGroup /* is group */ ) { - linkText=(dynamic_cast<GroupDef *>(compound))->groupTitle(); // use group's title as link + linkText=(dynamic_cast<const GroupDef *>(compound))->groupTitle(); // use group's title as link } else if (compound->definitionType()==Definition::TypeFile) { @@ -5127,7 +5137,7 @@ FileDef *findFileDef(const FileNameDict *fnDict,const char *n,bool &ambig) if (fn->count()==1) { FileDef *fd = fn->getFirst(); -#if defined(_WIN32) || defined(__MACOSX__) // Windows or MacOSX +#if defined(_WIN32) || defined(__MACOSX__) || defined(__CYGWIN__) // Windows or MacOSX bool isSamePath = fd->getPath().right(path.length()).lower()==path.lower(); #else // Unix bool isSamePath = fd->getPath().right(path.length())==path; @@ -5379,7 +5389,7 @@ static void initBaseClassHierarchy(BaseClassList *bcl) } //---------------------------------------------------------------------------- -bool classHasVisibleChildren(ClassDef *cd) +bool classHasVisibleChildren(const ClassDef *cd) { BaseClassList *bcl; @@ -5421,14 +5431,14 @@ void initClassHierarchy(ClassSDict *cl) //---------------------------------------------------------------------------- -bool hasVisibleRoot(BaseClassList *bcl) +bool hasVisibleRoot(const BaseClassList *bcl) { if (bcl) { BaseClassListIterator bcli(*bcl); for ( ; bcli.current(); ++bcli) { - ClassDef *cd=bcli.current()->classDef; + const ClassDef *cd=bcli.current()->classDef; if (cd->isVisibleInHierarchy()) return TRUE; hasVisibleRoot(cd->baseClasses()); } @@ -5473,10 +5483,12 @@ QCString escapeCharsInString(const char *name,bool allowDots,bool allowUnderscor case '(': growBuf.addStr("_07"); break; case ')': growBuf.addStr("_08"); break; case '+': growBuf.addStr("_09"); break; - case '=': growBuf.addStr("_0A"); break; - case '$': growBuf.addStr("_0B"); break; - case '\\': growBuf.addStr("_0C"); break; - case '@': growBuf.addStr("_0D"); break; + case '=': growBuf.addStr("_0a"); break; + case '$': growBuf.addStr("_0b"); break; + case '\\': growBuf.addStr("_0c"); break; + case '@': growBuf.addStr("_0d"); break; + case ']': growBuf.addStr("_0e"); break; + case '[': growBuf.addStr("_0f"); break; default: if (c<0) { @@ -6154,7 +6166,7 @@ QCString getOverloadDocs() void addMembersToMemberGroup(MemberList *ml, MemberGroupSDict **ppMemberGroupSDict, - Definition *context) + const Definition *context) { ASSERT(context!=0); //printf("addMemberToMemberGroup()\n"); @@ -6166,7 +6178,7 @@ void addMembersToMemberGroup(MemberList *ml, { if (md->isEnumerate()) // insert enum value of this enum into groups { - MemberList *fmdl=md->enumFieldList(); + const MemberList *fmdl=md->enumFieldList(); if (fmdl!=0) { MemberListIterator fmli(*fmdl); @@ -6324,7 +6336,7 @@ int extractClassNameFromType(const QCString &type,int &pos,QCString &name,QCStri QCString normalizeNonTemplateArgumentsInString( const QCString &name, - Definition *context, + const Definition *context, const ArgumentList * formalArgs) { // skip until < @@ -6344,7 +6356,7 @@ QCString normalizeNonTemplateArgumentsInString( if (formalArgs) // check that n is not a formal template argument { ArgumentListIterator formAli(*formalArgs); - Argument *formArg; + const Argument *formArg; for (formAli.toFirst(); (formArg=formAli.current()) && !found; ++formAli @@ -6356,7 +6368,7 @@ QCString normalizeNonTemplateArgumentsInString( if (!found) { // try to resolve the type - ClassDef *cd = getResolvedClass(context,0,n); + const ClassDef *cd = getResolvedClass(context,0,n); if (cd) { result+=cd->name(); @@ -6656,7 +6668,7 @@ found: PageDef *addRelatedPage(const char *name,const QCString &ptitle, const QCString &doc, - QList<SectionInfo> * /*anchors*/, + const QList<SectionInfo> * /*anchors*/, const char *fileName,int startLine, const QList<ListItemInfo> *sli, GroupDef *gd, @@ -6782,7 +6794,7 @@ void addRefItem(const QList<ListItemInfo> *sli, } } -bool recursivelyAddGroupListToTitle(OutputList &ol,Definition *d,bool root) +bool recursivelyAddGroupListToTitle(OutputList &ol,const Definition *d,bool root) { GroupList *groups = d->partOfGroups(); if (groups) // write list of group to which this definition belongs @@ -6815,7 +6827,7 @@ bool recursivelyAddGroupListToTitle(OutputList &ol,Definition *d,bool root) return false; } -void addGroupListToTitle(OutputList &ol,Definition *d) +void addGroupListToTitle(OutputList &ol,const Definition *d) { recursivelyAddGroupListToTitle(ol,d,TRUE); } @@ -7077,6 +7089,7 @@ QCString latexFilterURL(const char *s) switch (c) { case '#': t << "\\#"; break; + case '%': t << "\\%"; break; default: t << c; break; @@ -7200,7 +7213,7 @@ bool findAndRemoveWord(QCString &s,const QCString &word) { if (i>0 && isspace((uchar)s.at(i-1))) i--,l++; - else if (i+l<(int)s.length() && isspace(s.at(i+l))) + else if (i+l<(int)s.length() && isspace((uchar)s.at(i+l))) l++; s = s.left(i)+s.mid(i+l); // remove word + spacing return TRUE; @@ -7412,27 +7425,31 @@ void addCodeOnlyMappings() SrcLangExt getLanguageFromFileName(const QCString& fileName) { - int i = fileName.findRev('.'); - if (i!=-1) // name has an extension - { - QCString extStr=fileName.right(fileName.length()-i).lower(); - if (!extStr.isEmpty()) // non-empty extension + QFileInfo fi(fileName); + QCString extName = fi.extension().lower().data(); + if (extName.isEmpty()) extName=".no_extension"; + if (extName.at(0)!='.') extName.prepend("."); + int *pVal=g_extLookup.find(extName.data()); + if (pVal) // listed extension { - int *pVal=g_extLookup.find(extStr); - if (pVal) // listed extension - { - //printf("getLanguageFromFileName(%s)=%x\n",extStr.data(),*pVal); - return (SrcLangExt)*pVal; - } + //printf("getLanguageFromFileName(%s)=%x\n",fi.extension().data(),*pVal); + return (SrcLangExt)*pVal; } - } //printf("getLanguageFromFileName(%s) not found!\n",fileName.data()); return SrcLangExt_Cpp; // not listed => assume C-ish language. } +QCString getFileNameExtension(QCString fn) +{ + if (fn.isEmpty()) return ""; + int lastDot = fn.findRev('.'); + if (lastDot!=-1) return fn.mid(lastDot); + return ""; +} + //-------------------------------------------------------------------------- -MemberDef *getMemberFromSymbol(Definition *scope,FileDef *fileScope, +MemberDef *getMemberFromSymbol(const Definition *scope,const FileDef *fileScope, const char *n) { if (scope==0 || @@ -7504,7 +7521,7 @@ MemberDef *getMemberFromSymbol(Definition *scope,FileDef *fileScope, } /*! Returns true iff the given name string appears to be a typedef in scope. */ -bool checkIfTypedef(Definition *scope,FileDef *fileScope,const char *n) +bool checkIfTypedef(const Definition *scope,const FileDef *fileScope,const char *n) { MemberDef *bestMatch = getMemberFromSymbol(scope,fileScope,n); @@ -7931,12 +7948,12 @@ QCString expandAlias(const QCString &aliasName,const QCString &aliasValue) return result; } -void writeTypeConstraints(OutputList &ol,Definition *d,ArgumentList *al) +void writeTypeConstraints(OutputList &ol,const Definition *d,const ArgumentList *al) { if (al==0) return; ol.startConstraintList(theTranslator->trTypeConstraints()); ArgumentListIterator ali(*al); - Argument *a; + const Argument *a; for (;(a=ali.current());++ali) { ol.startConstraintParam(); @@ -8136,7 +8153,7 @@ bool patternMatch(const QFileInfo &fi,const QStrList *patList) bool found = FALSE; // For Windows/Mac, always do the case insensitive match -#if defined(_WIN32) || defined(__MACOSX__) +#if defined(_WIN32) || defined(__MACOSX__) || defined(__CYGWIN__) caseSenseNames = FALSE; #endif @@ -8452,16 +8469,20 @@ QCString getLanguageSpecificSeparator(SrcLangExt lang,bool classScope) return "::"; } } - +/** Checks whether the given url starts with a supported protocol */ +bool isURL(const QCString &url) +{ + QCString loc_url = url.stripWhiteSpace(); + return loc_url.left(5)=="http:" || loc_url.left(6)=="https:" || + loc_url.left(4)=="ftp:" || loc_url.left(5)=="file:"; +} /** Corrects URL \a url according to the relative path \a relPath. * Returns the corrected URL. For absolute URLs no correction will be done. */ QCString correctURL(const QCString &url,const QCString &relPath) { QCString result = url; - if (!relPath.isEmpty() && - url.left(5)!="http:" && url.left(6)!="https:" && - url.left(4)!="ftp:" && url.left(5)!="file:") + if (!relPath.isEmpty() && !isURL(url)) { result.prepend(relPath); } @@ -8549,7 +8570,7 @@ QCString stripIndentation(const QCString &s) } -bool fileVisibleInIndex(FileDef *fd,bool &genSourceFile) +bool fileVisibleInIndex(const FileDef *fd,bool &genSourceFile) { static bool allExternals = Config_getBool(ALLEXTERNALS); bool isDocFile = fd->isDocumentationFile(); @@ -8668,12 +8689,12 @@ uint getUtf8CodeToUpper( const QCString& s, int idx ) //-------------------------------------------------------------------------------------- -bool namespaceHasVisibleChild(NamespaceDef *nd,bool includeClasses,bool filterClasses,ClassDef::CompoundType ct) +bool namespaceHasVisibleChild(const NamespaceDef *nd,bool includeClasses,bool filterClasses,ClassDef::CompoundType ct) { if (nd->getNamespaceSDict()) { NamespaceSDict::Iterator cnli(*nd->getNamespaceSDict()); - NamespaceDef *cnd; + const NamespaceDef *cnd; for (cnli.toFirst();(cnd=cnli.current());++cnli) { if (cnd->isLinkableInProject() && cnd->localName().find('@')==-1) @@ -8688,7 +8709,7 @@ bool namespaceHasVisibleChild(NamespaceDef *nd,bool includeClasses,bool filterCl } if (includeClasses) { - ClassSDict *d = nd->getClassSDict(); + const ClassSDict *d = nd->getClassSDict(); if (filterClasses) { if (ct == ClassDef::Interface) @@ -8708,7 +8729,7 @@ bool namespaceHasVisibleChild(NamespaceDef *nd,bool includeClasses,bool filterCl if (d) { ClassSDict::Iterator cli(*d); - ClassDef *cd; + const ClassDef *cd; for (;(cd=cli.current());++cli) { if (cd->isLinkableInProject() && cd->templateMaster()==0) @@ -8723,7 +8744,7 @@ bool namespaceHasVisibleChild(NamespaceDef *nd,bool includeClasses,bool filterCl //---------------------------------------------------------------------------- -bool classVisibleInIndex(ClassDef *cd) +bool classVisibleInIndex(const ClassDef *cd) { static bool allExternals = Config_getBool(ALLEXTERNALS); return (allExternals && cd->isLinkable()) || cd->isLinkableInProject(); @@ -142,13 +142,13 @@ QCString dateToString(bool); bool getDefs(const QCString &scopeName, const QCString &memberName, const char *, - MemberDef *&md, - ClassDef *&cd, - FileDef *&fd, - NamespaceDef *&nd, - GroupDef *&gd, + const MemberDef *&md, + const ClassDef *&cd, + const FileDef *&fd, + const NamespaceDef *&nd, + const GroupDef *&gd, bool forceEmptyScope=FALSE, - FileDef *currentFile=0, + const FileDef *currentFile=0, bool checkCV=FALSE, const char *forceTagFile=0 ); @@ -158,17 +158,17 @@ QCString getFileFilter(const char* name,bool isSourceCode); bool resolveRef(/* in */ const char *scName, /* in */ const char *name, /* in */ bool inSeeBlock, - /* out */ Definition **resContext, - /* out */ MemberDef **resMember, + /* out */ const Definition **resContext, + /* out */ const MemberDef **resMember, /* in */ bool lookForSpecializations = TRUE, - /* in */ FileDef *currentFile = 0, + /* in */ const FileDef *currentFile = 0, /* in */ bool checkScope = FALSE ); bool resolveLink(/* in */ const char *scName, /* in */ const char *lr, /* in */ bool inSeeBlock, - /* out */ Definition **resContext, + /* out */ const Definition **resContext, /* out */ QCString &resAnchor ); @@ -183,10 +183,10 @@ void generateFileRef(OutputDocInterface &od,const char *, void writePageRef(OutputDocInterface &od,const char *cn,const char *mn); -QCString getCanonicalTemplateSpec(Definition *d,FileDef *fs,const QCString& spec); +QCString getCanonicalTemplateSpec(const Definition *d,const FileDef *fs,const QCString& spec); -bool matchArguments2(Definition *srcScope,FileDef *srcFileScope,ArgumentList *srcAl, - Definition *dstScope,FileDef *dstFileScope,ArgumentList *dstAl, +bool matchArguments2(const Definition *srcScope,const FileDef *srcFileScope,const ArgumentList *srcAl, + const Definition *dstScope,const FileDef *dstFileScope,const ArgumentList *dstAl, bool checkCV ); @@ -206,10 +206,10 @@ QCString resolveDefines(const char *n); ClassDef *getClass(const char *key); -ClassDef *getResolvedClass(const Definition *scope, +const ClassDef *getResolvedClass(const Definition *scope, const FileDef *fileScope, const char *key, - MemberDef **pTypeDef=0, + const MemberDef **pTypeDef=0, QCString *pTemplSpec=0, bool mayBeUnlinkable=FALSE, bool mayBeHidden=FALSE, @@ -231,9 +231,9 @@ inline bool isId(int c) QCString removeRedundantWhiteSpace(const QCString &s); -QCString argListToString(ArgumentList *al,bool useCanonicalType=FALSE,bool showDefVals=TRUE); +QCString argListToString(const ArgumentList *al,bool useCanonicalType=FALSE,bool showDefVals=TRUE); -QCString tempArgListToString(ArgumentList *al,SrcLangExt lang); +QCString tempArgListToString(const ArgumentList *al,SrcLangExt lang); QCString generateMarker(int id); @@ -260,13 +260,13 @@ QCString replaceAnonymousScopes(const QCString &s,const char *replacement=0); void initClassHierarchy(ClassSDict *cl); -bool hasVisibleRoot(BaseClassList *bcl); -bool classHasVisibleChildren(ClassDef *cd); -bool namespaceHasVisibleChild(NamespaceDef *nd,bool includeClasses,bool filterClasses,ClassDef::CompoundType ct); -bool classVisibleInIndex(ClassDef *cd); +bool hasVisibleRoot(const BaseClassList *bcl); +bool classHasVisibleChildren(const ClassDef *cd); +bool namespaceHasVisibleChild(const NamespaceDef *nd,bool includeClasses,bool filterClasses,ClassDef::CompoundType ct); +bool classVisibleInIndex(const ClassDef *cd); int minClassDistance(const ClassDef *cd,const ClassDef *bcd,int level=0); -Protection classInheritedProtectionLevel(ClassDef *cd,ClassDef *bcd,Protection prot=Public,int level=0); +Protection classInheritedProtectionLevel(const ClassDef *cd,const ClassDef *bcd,Protection prot=Public,int level=0); QCString convertNameToFile(const char *name,bool allowDots=FALSE,bool allowUnderscore=FALSE); @@ -292,16 +292,16 @@ QCString convertToJSString(const char *s, bool applyTextDir = true); QCString getOverloadDocs(); -void addMembersToMemberGroup(/* in */ MemberList *ml, +void addMembersToMemberGroup(/* in,out */ MemberList *ml, /* in,out */ MemberGroupSDict **ppMemberGroupSDict, - /* in */ Definition *context); + /* in */ const Definition *context); int extractClassNameFromType(const QCString &type,int &pos, QCString &name,QCString &templSpec,SrcLangExt=SrcLangExt_Unknown); QCString normalizeNonTemplateArgumentsInString( const QCString &name, - Definition *context, + const Definition *context, const ArgumentList *formalArgs); QCString substituteTemplateArgumentsInString( @@ -315,8 +315,8 @@ QCString stripTemplateSpecifiersFromScope(const QCString &fullName, bool parentOnly=TRUE, QCString *lastScopeStripped=0); -QCString resolveTypeDef(Definition *d,const QCString &name, - Definition **typedefContext=0); +QCString resolveTypeDef(const Definition *d,const QCString &name, + const Definition **typedefContext=0); QCString mergeScopes(const QCString &leftScope,const QCString &rightScope); @@ -328,18 +328,20 @@ void addRefItem(const QList<ListItemInfo> *sli,const char *prefix, const char *key, const char *name,const char *title,const char *args,Definition *scope); -PageDef *addRelatedPage(const char *name,const QCString &ptitle, - const QCString &doc,QList<SectionInfo> *anchors, - const char *fileName,int startLine, - const QList<ListItemInfo> *sli, - GroupDef *gd=0, - TagInfo *tagInfo=0, - SrcLangExt lang=SrcLangExt_Unknown - ); +PageDef *addRelatedPage(const char *name, + const QCString &ptitle, + const QCString &doc, + const QList<SectionInfo> *anchors, + const char *fileName,int startLine, + const QList<ListItemInfo> *sli, + GroupDef *gd=0, + TagInfo *tagInfo=0, + SrcLangExt lang=SrcLangExt_Unknown + ); QCString escapeCharsInString(const char *name,bool allowDots,bool allowUnderscore=FALSE); -void addGroupListToTitle(OutputList &ol,Definition *d); +void addGroupListToTitle(OutputList &ol,const Definition *d); void filterLatexString(FTextStream &t,const char *str, bool insideTabbing=FALSE, @@ -385,23 +387,22 @@ bool findAndRemoveWord(QCString &s,const QCString &word); QCString stripLeadingAndTrailingEmptyLines(const QCString &s,int &docLine); -//void stringToSearchIndex(const QCString &docUrlBase,const QCString &title, -// const QCString &str, bool priority=FALSE, -// const QCString &anchor=""); - bool updateLanguageMapping(const QCString &extension,const QCString &parser); SrcLangExt getLanguageFromFileName(const QCString& fileName); +QCString getFileNameExtension(QCString fn); void initDefaultExtensionMapping(); void addCodeOnlyMappings(); -MemberDef *getMemberFromSymbol(Definition *scope,FileDef *fileScope, +MemberDef *getMemberFromSymbol(const Definition *scope,const FileDef *fileScope, const char *n); -bool checkIfTypedef(Definition *scope,FileDef *fileScope,const char *n); +bool checkIfTypedef(const Definition *scope,const FileDef *fileScope,const char *n); -ClassDef *newResolveTypedef(const FileDef *fileScope,MemberDef *md, - MemberDef **pMemType=0,QCString *pTemplSpec=0, - QCString *pResolvedType=0, - ArgumentList *actTemplParams=0); +const ClassDef *newResolveTypedef(const FileDef *fileScope, + const MemberDef *md, + const MemberDef **pMemType=0, + QCString *pTemplSpec=0, + QCString *pResolvedType=0, + ArgumentList *actTemplParams=0); QCString parseCommentAsText(const Definition *scope,const MemberDef *member,const QCString &doc,const QCString &fileName,int lineNr); @@ -418,7 +419,7 @@ int countAliasArguments(const QCString argList); QCString resolveAliasCmd(const QCString aliasCmd); QCString expandAlias(const QCString &aliasName,const QCString &aliasValue); -void writeTypeConstraints(OutputList &ol,Definition *d,ArgumentList *al); +void writeTypeConstraints(OutputList &ol,const Definition *d,const ArgumentList *al); QCString convertCharEntitiesToUTF8(const QCString &s); @@ -453,6 +454,8 @@ bool copyFile(const QCString &src,const QCString &dest); QCString extractBlock(const QCString text,const QCString marker); int lineBlock(const QCString text,const QCString marker); +bool isURL(const QCString &url); + QCString correctURL(const QCString &url,const QCString &relPath); QCString processMarkup(const QCString &s); @@ -463,7 +466,7 @@ QCString stripIndentation(const QCString &s); QCString getDotImageExtension(void); -bool fileVisibleInIndex(FileDef *fd,bool &genSourceFile); +bool fileVisibleInIndex(const FileDef *fd,bool &genSourceFile); void addDocCrossReference(MemberDef *src,MemberDef *dst); diff --git a/src/vhdlcode.h b/src/vhdlcode.h index e21ddea..a7b4687 100644 --- a/src/vhdlcode.h +++ b/src/vhdlcode.h @@ -8,7 +8,7 @@ class MemberDef; void parseVhdlCode(CodeOutputInterface &,const char *,const QCString &, bool ,const char *,FileDef *fd, int startLine,int endLine,bool inlineFragment, - MemberDef *memberDef,bool showLineNumbers,Definition *searchCtx, + const MemberDef *memberDef,bool showLineNumbers,const Definition *searchCtx, bool collectXRefs); void resetVhdlCodeParserState(); void codeFreeVhdlScanner(); diff --git a/src/vhdlcode.l b/src/vhdlcode.l index 9e296cc..7c6cfa4 100644 --- a/src/vhdlcode.l +++ b/src/vhdlcode.l @@ -86,7 +86,7 @@ static int g_inputPosition; //!< read offset during parsing static int g_inputLines; //!< number of line in the code fragment static int g_yyLineNr; //!< current line number static bool g_needsTermination; -static Definition *g_searchCtx; +static const Definition *g_searchCtx; static bool g_exampleBlock; static QCString g_exampleName; @@ -430,13 +430,13 @@ static void writeMultiLineCodeLink(CodeOutputInterface &ol, } } -static void setParameterList(MemberDef *md) +static void setParameterList(const MemberDef *md) { g_classScope = md->getClassDef() ? md->getClassDef()->name().data() : ""; - ArgumentList *al = md->argumentList(); + const ArgumentList *al = md->argumentList(); if (al==0) return; ArgumentListIterator ali(*al); - Argument *a; + const Argument *a; for (ali.toFirst();(a=ali.current());++ali) { g_parmName = a->name.copy(); @@ -1543,7 +1543,7 @@ void resetVhdlCodeParserState() void parseVhdlCode(CodeOutputInterface &od,const char *className,const QCString &s, bool exBlock, const char *exName,FileDef *fd, int startLine,int endLine,bool inlineFragment, - MemberDef *memberDef,bool,Definition *searchCtx, + const MemberDef *memberDef,bool,const Definition *searchCtx, bool /* collectXRefs */) { //printf("***parseCode() exBlock=%d exName=%s fd=%p\n",exBlock,exName,fd); @@ -1551,7 +1551,7 @@ void parseVhdlCode(CodeOutputInterface &od,const char *className,const QCString printlex(yy_flex_debug, TRUE, __FILE__, fd ? fd->fileName().data(): NULL); if (memberDef) { - ClassDef *dd=memberDef->getClassDef(); + const ClassDef *dd=memberDef->getClassDef(); if (dd) g_CurrClass=dd->name(); } resetVhdlCodeParserState(); diff --git a/src/vhdldocgen.cpp b/src/vhdldocgen.cpp index e70f099..bba249a 100644 --- a/src/vhdldocgen.cpp +++ b/src/vhdldocgen.cpp @@ -1730,8 +1730,8 @@ QCString VhdlDocGen::convertArgumentListToString(const ArgumentList* al,bool fun } -void VhdlDocGen::writeVhdlDeclarations(MemberList* ml, - OutputList& ol,GroupDef* gd,ClassDef* cd,FileDef *fd,NamespaceDef* nd) +void VhdlDocGen::writeVhdlDeclarations(const MemberList* ml, + OutputList& ol,const GroupDef* gd,const ClassDef* cd,const FileDef *fd,const NamespaceDef* nd) { VhdlDocGen::writeVHDLDeclarations(ml,ol,cd,nd,fd,gd,theTranslator_vhdlType(VhdlDocGen::LIBRARY,FALSE),0,FALSE,VhdlDocGen::LIBRARY); VhdlDocGen::writeVHDLDeclarations(ml,ol,cd,nd,fd,gd,theTranslator_vhdlType(VhdlDocGen::USE,FALSE),0,FALSE,VhdlDocGen::USE); @@ -1761,36 +1761,49 @@ void VhdlDocGen::writeVhdlDeclarations(MemberList* ml, } -static void setGlobalType(MemberList *ml) +void VhdlDocGen::correctMemberProperties(MemberDef *md) { - if (ml==0) return; - MemberDef *mdd=0; - MemberListIterator mmli(*ml); - for ( ; (mdd=mmli.current()); ++mmli ) + if (qstrcmp(md->argsString(),"package")==0) { - if (qstrcmp(mdd->argsString(),"package")==0) - { - mdd->setMemberSpecifiers(VhdlDocGen::INSTANTIATION); - } - else if (qstrcmp(mdd->argsString(),"configuration")==0) - { - mdd->setMemberSpecifiers(VhdlDocGen::CONFIG); - } - else if (qstrcmp(mdd->typeString(),"library")==0) - { - mdd->setMemberSpecifiers(VhdlDocGen::LIBRARY); - } - else if (qstrcmp(mdd->typeString(),"use")==0) - { - mdd->setMemberSpecifiers(VhdlDocGen::USE); - } - else if (qstricmp(mdd->typeString(),"misc")==0) + md->setMemberSpecifiers(VhdlDocGen::INSTANTIATION); + } + else if (qstrcmp(md->argsString(),"configuration")==0) + { + md->setMemberSpecifiers(VhdlDocGen::CONFIG); + } + else if (qstrcmp(md->typeString(),"library")==0) + { + md->setMemberSpecifiers(VhdlDocGen::LIBRARY); + } + else if (qstrcmp(md->typeString(),"use")==0) + { + md->setMemberSpecifiers(VhdlDocGen::USE); + } + else if (qstricmp(md->typeString(),"misc")==0) + { + md->setMemberSpecifiers(VhdlDocGen::MISCELLANEOUS); + } + else if (qstricmp(md->typeString(),"ucf_const")==0) + { + md->setMemberSpecifiers(VhdlDocGen::UCF_CONST); + } + + if (md->getMemberSpecifiers()==VhdlDocGen::UCF_CONST) + { + int mm=md->name().findRev('_'); + if (mm>0) { - mdd->setMemberSpecifiers(VhdlDocGen::MISCELLANEOUS); + md->setName(md->name().left(mm)); } - else if (qstricmp(mdd->typeString(),"ucf_const")==0) + } + else if (md->getMemberSpecifiers()==VhdlDocGen::TYPE) + { + QCString largs=md->argsString(); + bool bRec=largs.stripPrefix("record") ; + bool bUnit=largs.stripPrefix("units") ; + if (bRec || bUnit) { - mdd->setMemberSpecifiers(VhdlDocGen::UCF_CONST); + md->setType(""); } } } @@ -1924,11 +1937,11 @@ void VhdlDocGen::writeTagFile(MemberDef *mdef,FTextStream &tagFile) /* writes a vhdl type declaration */ -void VhdlDocGen::writeVHDLDeclaration(MemberDef* mdef,OutputList &ol, - ClassDef *cd,NamespaceDef *nd,FileDef *fd,GroupDef *gd, +void VhdlDocGen::writeVHDLDeclaration(const MemberDef* mdef,OutputList &ol, + const ClassDef *cd,const NamespaceDef *nd,const FileDef *fd,const GroupDef *gd, bool /*inGroup*/) { - Definition *d=0; + const Definition *d=0; ASSERT(cd!=0 || nd!=0 || fd!=0 || gd!=0 || mdef->getMemberSpecifiers()==VhdlDocGen::LIBRARY || @@ -1987,14 +2000,9 @@ void VhdlDocGen::writeVHDLDeclaration(MemberDef* mdef,OutputList &ol, /*VHDL CHANGE */ bool bRec,bUnit; QCString ltype(mdef->typeString()); - // ltype=ltype.replace(reg," "); QCString largs(mdef->argsString()); - // largs=largs.replace(reg," "); - mdef->setType(ltype.data()); - mdef->setArgsString(largs.data()); - //ClassDef * plo=mdef->getClassDef(); ClassDef *kl=0; - ArgumentList *alp = mdef->argumentList(); + const ArgumentList *alp = mdef->argumentList(); QCString nn; //VhdlDocGen::adjustRecordMember(mdef); if (gd) gd=0; @@ -2153,11 +2161,6 @@ void VhdlDocGen::writeVHDLDeclaration(MemberDef* mdef,OutputList &ol, } break; case VhdlDocGen::UCF_CONST: - mm=mdef->name().findRev('_'); - if (mm>0) - { - mdef->setName(mdef->name().left(mm)); - } writeUCFLink(mdef,ol); break; case VhdlDocGen::SIGNAL: @@ -2198,7 +2201,6 @@ void VhdlDocGen::writeVHDLDeclaration(MemberDef* mdef,OutputList &ol, if (bRec || bUnit) { writeRecorUnit(largs,ol,mdef); - mdef->setType(""); } ol.endBold(); break; @@ -2260,8 +2262,8 @@ void VhdlDocGen::writeVHDLDeclaration(MemberDef* mdef,OutputList &ol, void VhdlDocGen::writePlainVHDLDeclarations( - MemberList* mlist,OutputList &ol, - ClassDef *cd,NamespaceDef *nd,FileDef *fd,GroupDef *gd,int specifier) + const MemberList* mlist,OutputList &ol, + const ClassDef *cd,const NamespaceDef *nd,const FileDef *fd,const GroupDef *gd,int specifier) { SDict<QCString> pack(1009); @@ -2292,7 +2294,7 @@ void VhdlDocGen::writePlainVHDLDeclarations( pack.clear(); }//plainDeclaration -static bool membersHaveSpecificType(MemberList *ml,uint64 type) +static bool membersHaveSpecificType(const MemberList *ml,uint64 type) { if (ml==0) return FALSE; MemberDef *mdd=0; @@ -2320,11 +2322,10 @@ static bool membersHaveSpecificType(MemberList *ml,uint64 type) return FALSE; } -void VhdlDocGen::writeVHDLDeclarations(MemberList* ml,OutputList &ol, - ClassDef *cd,NamespaceDef *nd,FileDef *fd,GroupDef *gd, +void VhdlDocGen::writeVHDLDeclarations(const MemberList* ml,OutputList &ol, + const ClassDef *cd,const NamespaceDef *nd,const FileDef *fd,const GroupDef *gd, const char *title,const char *subtitle,bool /*showEnumValues*/,int type) { - setGlobalType(ml); if (!membersHaveSpecificType(ml,type)) return; if (title) @@ -2377,7 +2378,7 @@ void VhdlDocGen::writeVHDLDeclarations(MemberList* ml,OutputList &ol, }// writeVHDLDeclarations -bool VhdlDocGen::writeClassType( ClassDef *& cd, +bool VhdlDocGen::writeClassType( const ClassDef * cd, OutputList &ol ,QCString & cname) { int id=cd->protection(); @@ -2398,7 +2399,7 @@ void VhdlDocGen::writeStringLink(const MemberDef *mdef,QCString mem, OutputList& { if (mdef) { - ClassDef *cd=mdef->getClassDef(); + const ClassDef *cd=mdef->getClassDef(); if (cd) { QCString n=cd->name(); @@ -2418,7 +2419,7 @@ void VhdlDocGen::writeStringLink(const MemberDef *mdef,QCString mem, OutputList& -void VhdlDocGen::writeSource(MemberDef *mdef,OutputList& ol,QCString & cname) +void VhdlDocGen::writeSource(const MemberDef *mdef,OutputList& ol,const QCString & cname) { ParserInterface *pIntf = Doxygen::parserManager->getParser(".vhd"); // pIntf->resetCodeParserState(); @@ -2452,7 +2453,7 @@ void VhdlDocGen::writeSource(MemberDef *mdef,OutputList& ol,QCString & cname) SrcLangExt_VHDL, // lang FALSE, // isExample 0, // exampleName - mdef->getFileDef(), // fileDef + const_cast<FileDef*>(mdef->getFileDef()), // fileDef mdef->getStartBodyLine(), // startLine mdef->getEndBodyLine(), // endLine TRUE, // inlineFragment @@ -3091,7 +3092,7 @@ bool VhdlDocGen::isSubClass(ClassDef* cd,ClassDef *scd, bool followInstances,int BaseClassListIterator bcli(*cd->subClasses()); for ( ; bcli.current() && !found ; ++bcli) { - ClassDef *ccd=bcli.current()->classDef; + const ClassDef *ccd=bcli.current()->classDef; if (!followInstances && ccd->templateMaster()) ccd=ccd->templateMaster(); //printf("isSubClass() subclass %s\n",ccd->name().data()); if (ccd==scd) @@ -3178,7 +3179,7 @@ void VhdlDocGen::createFlowChart(const MemberDef *mdef) int actualStart= mdef->getStartBodyLine(); int actualEnd=mdef->getEndBodyLine(); - FileDef* fd=mdef->getFileDef(); + const FileDef* fd=mdef->getFileDef(); bool b=readCodeFragment( fd->absFilePath().data(), actualStart,actualEnd,codeFragment); if (!b) return; @@ -4374,9 +4375,9 @@ void VHDLLanguageScanner::parseCode(CodeOutputInterface &codeOutIntf, int startLine, int endLine, bool inlineFragment, - MemberDef *memberDef, + const MemberDef *memberDef, bool showLineNumbers, - Definition *searchCtx, + const Definition *searchCtx, bool collectXRefs ) { diff --git a/src/vhdldocgen.h b/src/vhdldocgen.h index 9dd8417..e2c843c 100644 --- a/src/vhdldocgen.h +++ b/src/vhdldocgen.h @@ -163,20 +163,21 @@ class VhdlDocGen static bool writeVHDLTypeDocumentation(const MemberDef* mdef, const Definition* d, OutputList &ol); - static void writeVhdlDeclarations(MemberList*,OutputList&,GroupDef*,ClassDef*,FileDef*,NamespaceDef*); + static void writeVhdlDeclarations(const MemberList*,OutputList&,const GroupDef*,const ClassDef*,const FileDef*,const NamespaceDef*); - static void writeVHDLDeclaration(MemberDef* mdef,OutputList &ol, - ClassDef *cd,NamespaceDef *nd,FileDef *fd,GroupDef *gd, + static void writeVHDLDeclaration(const MemberDef* mdef,OutputList &ol, + const ClassDef *cd,const NamespaceDef *nd,const FileDef *fd,const GroupDef *gd, bool inGroup); - static void writePlainVHDLDeclarations(MemberList* ml,OutputList &ol, - ClassDef *cd,NamespaceDef *nd,FileDef *fd,GroupDef *gd,int specifier); + static void writePlainVHDLDeclarations(const MemberList* ml,OutputList &ol, + const ClassDef *cd,const NamespaceDef *nd,const FileDef *fd,const GroupDef *gd, + int specifier); - static void writeVHDLDeclarations(MemberList* ml,OutputList &ol, - ClassDef *cd,NamespaceDef *nd,FileDef *fd,GroupDef *gd, + static void writeVHDLDeclarations(const MemberList* ml,OutputList &ol, + const ClassDef *cd,const NamespaceDef *nd,const FileDef *fd,const GroupDef *gd, const char *title,const char *subtitle,bool showEnumValues,int type); - static bool writeClassType(ClassDef *&,OutputList &ol ,QCString & cname); + static bool writeClassType(const ClassDef *,OutputList &ol ,QCString & cname); static QCString convertArgumentListToString(const ArgumentList* al,bool f); static QCString getProcessNumber(); @@ -192,8 +193,9 @@ class VhdlDocGen static ClassDef* findArchitecture(const ClassDef *cd); static ClassDef* findArchitecture(QCString identifier, QCString entity_name); + static void correctMemberProperties(MemberDef *md); - static void writeSource(MemberDef *mdef,OutputList& ol,QCString & cname); + static void writeSource(const MemberDef *mdef,OutputList& ol,const QCString & cname); static void writeAlphbeticalClass(OutputList& ol,const ClassDef* cd,const QCString &); static QCString parseForConfig(QCString & entity,QCString & arch); diff --git a/src/vhdljjparser.cpp b/src/vhdljjparser.cpp index 4a312bd..aeed048 100644 --- a/src/vhdljjparser.cpp +++ b/src/vhdljjparser.cpp @@ -146,7 +146,7 @@ void VHDLLanguageScanner::parseInput(const char *fileName,const char *fileBuf,En oldEntry = 0; VhdlParser::current=new Entry(); VhdlParser::initEntry(VhdlParser::current); - groupEnterFile(fileName,yyLineNr); + Doxygen::docGroup.enterFile(fileName,yyLineNr); vhdlFileName = fileName; lineParse=new int[200]; // Dimitri: dangerous constant: should be bigger than largest token id in VhdlParserConstants.h VhdlParserIF::parseVhdlfile(fileBuf,inLine); @@ -193,7 +193,7 @@ void VhdlParser::initEntry(Entry *e) e->fileName = yyFileName; e->lang = SrcLangExt_VHDL; isVhdlDocPending(); - initGroupInfo(e); + Doxygen::docGroup.initGroupInfo(e); } void VhdlParser::newEntry() diff --git a/src/vhdljjparser.h b/src/vhdljjparser.h index 3a2ed61..fffea47 100644 --- a/src/vhdljjparser.h +++ b/src/vhdljjparser.h @@ -59,9 +59,9 @@ class VHDLLanguageScanner : public ParserInterface int startLine=-1, int endLine=-1, bool inlineFragment=FALSE, - MemberDef *memberDef=0, + const MemberDef *memberDef=0, bool showLineNumbers=TRUE, - Definition *searchCtx=0, + const Definition *searchCtx=0, bool collectXRefs=TRUE ); bool needsPreprocessing(const QCString &) { return TRUE; } diff --git a/src/xmlcode.h b/src/xmlcode.h index 5a9c78c..e463866 100644 --- a/src/xmlcode.h +++ b/src/xmlcode.h @@ -30,7 +30,7 @@ class Definition; extern void parseXmlCode(CodeOutputInterface &,const char *,const QCString &, bool ,const char *,FileDef *fd, int startLine,int endLine,bool inlineFragment, - MemberDef *memberDef,bool showLineNumbers,Definition *searchCtx, + const MemberDef *memberDef,bool showLineNumbers,const Definition *searchCtx, bool collectXRefs); extern void resetXmlCodeParserState(); diff --git a/src/xmlcode.l b/src/xmlcode.l index c9529d6..42218b1 100644 --- a/src/xmlcode.l +++ b/src/xmlcode.l @@ -35,6 +35,7 @@ #include "config.h" #include "filedef.h" #include "tooltip.h" +#include "message.h" #define YY_NEVER_INTERACTIVE 1 #define YY_NO_INPUT 1 @@ -49,7 +50,7 @@ static int g_inputPosition; //!< read offset during parsing static int g_inputLines; //!< number of line in the code fragment static int g_yyLineNr; //!< current line number static bool g_needsTermination; -static Definition *g_searchCtx; +static const Definition *g_searchCtx; static bool g_exampleBlock; static QCString g_exampleName; @@ -332,12 +333,13 @@ void parseXmlCode( int startLine, int endLine, bool inlineFragment, - MemberDef *, - bool,Definition *searchCtx, + const MemberDef *, + bool,const Definition *searchCtx, bool /*collectXRefs*/ ) { if (s.isEmpty()) return; + printlex(yy_flex_debug, TRUE, __FILE__, fd ? fd->fileName().data(): NULL); g_code = &od; g_inputString = s; @@ -393,6 +395,7 @@ void parseXmlCode( g_sourceFileDef=0; } + printlex(yy_flex_debug, FALSE, __FILE__, fd ? fd->fileName().data(): NULL); return; } diff --git a/src/xmldocvisitor.cpp b/src/xmldocvisitor.cpp index 1005719..c8d23a8 100644 --- a/src/xmldocvisitor.cpp +++ b/src/xmldocvisitor.cpp @@ -415,20 +415,22 @@ void XmlDocVisitor::visit(DocIncOperator *op) pushEnabled(); m_hide = TRUE; } - SrcLangExt langExt = getLanguageFromFileName(m_langExt); + QCString locLangExt = getFileNameExtension(op->includeFileName()); + if (locLangExt.isEmpty()) locLangExt = m_langExt; + SrcLangExt langExt = getLanguageFromFileName(locLangExt); if (op->type()!=DocIncOperator::Skip) { popEnabled(); if (!m_hide) { - FileDef *fd; + FileDef *fd = 0; if (!op->includeFileName().isEmpty()) { QFileInfo cfi( op->includeFileName() ); fd = createFileDef( cfi.dirPath().utf8(), cfi.fileName().utf8() ); } - Doxygen::parserManager->getParser(m_langExt) + Doxygen::parserManager->getParser(locLangExt) ->parseCode(m_ci,op->context(), op->text(),langExt,op->isExample(), op->exampleFile(), @@ -1078,18 +1080,6 @@ void XmlDocVisitor::visitPost(DocInternalRef *) m_t << " "; } -void XmlDocVisitor::visitPre(DocCopy *c) -{ - if (m_hide) return; - m_t << "<copydoc link=\"" << convertToXML(c->link()) << "\">"; -} - -void XmlDocVisitor::visitPost(DocCopy *) -{ - if (m_hide) return; - m_t << "</copydoc>" << endl; -} - void XmlDocVisitor::visitPre(DocText *) { } diff --git a/src/xmldocvisitor.h b/src/xmldocvisitor.h index c2c6537..6fa1392 100644 --- a/src/xmldocvisitor.h +++ b/src/xmldocvisitor.h @@ -130,8 +130,6 @@ class XmlDocVisitor : public DocVisitor void visitPost(DocXRefItem *); void visitPre(DocInternalRef *); void visitPost(DocInternalRef *); - void visitPre(DocCopy *); - void visitPost(DocCopy *); void visitPre(DocText *); void visitPost(DocText *); void visitPre(DocHtmlBlockQuote *); diff --git a/src/xmlgen.cpp b/src/xmlgen.cpp index d3b8355..16abbf2 100644 --- a/src/xmlgen.cpp +++ b/src/xmlgen.cpp @@ -29,6 +29,8 @@ #include "defargs.h" #include "outputgen.h" #include "dot.h" +#include "dotclassgraph.h" +#include "dotincldepgraph.h" #include "pagedef.h" #include "filename.h" #include "version.h" @@ -336,10 +338,10 @@ void XMLCodeGenerator::finish() if (m_insideCodeLine) endCodeLine(); } -static void writeTemplateArgumentList(ArgumentList *al, +static void writeTemplateArgumentList(const ArgumentList *al, FTextStream &t, - Definition *scope, - FileDef *fileScope, + const Definition *scope, + const FileDef *fileScope, int indent) { QCString indentStr; @@ -348,7 +350,7 @@ static void writeTemplateArgumentList(ArgumentList *al, { t << indentStr << "<templateparamlist>" << endl; ArgumentListIterator ali(*al); - Argument *a; + const Argument *a; for (ali.toFirst();(a=ali.current());++ali) { t << indentStr << " <param>" << endl; @@ -381,16 +383,16 @@ static void writeTemplateArgumentList(ArgumentList *al, } } -static void writeMemberTemplateLists(MemberDef *md,FTextStream &t) +static void writeMemberTemplateLists(const MemberDef *md,FTextStream &t) { - ArgumentList *templMd = md->templateArguments(); + const ArgumentList *templMd = md->templateArguments(); if (templMd) // function template prefix { writeTemplateArgumentList(templMd,t,md->getClassDef(),md->getFileDef(),8); } } -static void writeTemplateList(ClassDef *cd,FTextStream &t) +static void writeTemplateList(const ClassDef *cd,FTextStream &t) { writeTemplateArgumentList(cd->templateArguments(),t,cd,0,4); } @@ -398,8 +400,8 @@ static void writeTemplateList(ClassDef *cd,FTextStream &t) static void writeXMLDocBlock(FTextStream &t, const QCString &fileName, int lineNr, - Definition *scope, - MemberDef * md, + const Definition *scope, + const MemberDef * md, const QCString &text) { QCString stext = text.stripWhiteSpace(); @@ -442,7 +444,7 @@ void writeXMLCodeBlock(FTextStream &t,FileDef *fd) delete xmlGen; } -static void writeMemberReference(FTextStream &t,Definition *def,MemberDef *rmd,const char *tagName) +static void writeMemberReference(FTextStream &t,const Definition *def,const MemberDef *rmd,const char *tagName) { QCString scope = rmd->getScopeString(); QCString name = rmd->name(); @@ -478,7 +480,7 @@ static void stripQualifiers(QCString &typeStr) } } -static QCString classOutputFileBase(ClassDef *cd) +static QCString classOutputFileBase(const ClassDef *cd) { //static bool inlineGroupedClasses = Config_getBool(INLINE_GROUPED_CLASSES); //if (inlineGroupedClasses && cd->partOfGroups()!=0) @@ -487,7 +489,7 @@ static QCString classOutputFileBase(ClassDef *cd) // return cd->getOutputFileBase(); } -static QCString memberOutputFileBase(MemberDef *md) +static QCString memberOutputFileBase(const MemberDef *md) { //static bool inlineGroupedClasses = Config_getBool(INLINE_GROUPED_CLASSES); //if (inlineGroupedClasses && md->getClassDef() && md->getClassDef()->partOfGroups()!=0) @@ -498,7 +500,7 @@ static QCString memberOutputFileBase(MemberDef *md) } -static void generateXMLForMember(MemberDef *md,FTextStream &ti,FTextStream &t,Definition *def) +static void generateXMLForMember(const MemberDef *md,FTextStream &ti,FTextStream &t,const Definition *def) { // + declaration/definition arg lists @@ -589,7 +591,7 @@ static void generateXMLForMember(MemberDef *md,FTextStream &ti,FTextStream &t,De if (isFunc) { - ArgumentList *al = md->argumentList(); + const ArgumentList *al = md->argumentList(); t << " const=\""; if (al!=0 && al->constSpecifier) t << "yes"; else t << "no"; t << "\""; @@ -817,7 +819,7 @@ static void generateXMLForMember(MemberDef *md,FTextStream &ti,FTextStream &t,De t << " <bitfield>" << convertToXML(bitfield) << "</bitfield>" << endl; } - MemberDef *rmd = md->reimplements(); + const MemberDef *rmd = md->reimplements(); if (rmd) { t << " <reimplements refid=\"" @@ -838,13 +840,13 @@ static void generateXMLForMember(MemberDef *md,FTextStream &ti,FTextStream &t,De if (isFunc) //function { - ArgumentList *declAl = md->declArgumentList(); - ArgumentList *defAl = md->argumentList(); + const ArgumentList *declAl = md->declArgumentList(); + const ArgumentList *defAl = md->argumentList(); if (declAl && defAl && declAl->count()>0) { ArgumentListIterator declAli(*declAl); ArgumentListIterator defAli(*defAl); - Argument *a; + const Argument *a; for (declAli.toFirst();(a=declAli.current());++declAli) { Argument *defArg = defAli.current(); @@ -908,7 +910,7 @@ static void generateXMLForMember(MemberDef *md,FTextStream &ti,FTextStream &t,De else { ArgumentListIterator ali(*md->argumentList()); - Argument *a; + const Argument *a; for (ali.toFirst();(a=ali.current());++ali) { t << " <param><defname>" << a->type << "</defname></param>" << endl; @@ -932,11 +934,11 @@ static void generateXMLForMember(MemberDef *md,FTextStream &ti,FTextStream &t,De if (md->memberType()==MemberType_Enumeration) // enum { - MemberList *enumFields = md->enumFieldList(); + const MemberList *enumFields = md->enumFieldList(); if (enumFields) { MemberListIterator emli(*enumFields); - MemberDef *emd; + const MemberDef *emd; for (emli.toFirst();(emd=emli.current());++emli) { ti << " <member refid=\"" << memberOutputFileBase(md) @@ -1011,7 +1013,7 @@ static void generateXMLForMember(MemberDef *md,FTextStream &ti,FTextStream &t,De if (mdict) { MemberSDict::Iterator mdi(*mdict); - MemberDef *rmd; + const MemberDef *rmd; for (mdi.toFirst();(rmd=mdi.current());++mdi) { writeMemberReference(t,def,rmd,"references"); @@ -1021,7 +1023,7 @@ static void generateXMLForMember(MemberDef *md,FTextStream &ti,FTextStream &t,De if (mdict) { MemberSDict::Iterator mdi(*mdict); - MemberDef *rmd; + const MemberDef *rmd; for (mdi.toFirst();(rmd=mdi.current());++mdi) { writeMemberReference(t,def,rmd,"referencedby"); @@ -1033,20 +1035,20 @@ static void generateXMLForMember(MemberDef *md,FTextStream &ti,FTextStream &t,De // namespace members are also inserted in the file scope, but // to prevent this duplication in the XML output, we optionally filter those here. -static bool memberVisible(Definition *d,MemberDef *md) +static bool memberVisible(const Definition *d,const MemberDef *md) { return Config_getBool(XML_NS_MEMB_FILE_SCOPE) || d->definitionType()!=Definition::TypeFile || md->getNamespaceDef()==0; } -static void generateXMLSection(Definition *d,FTextStream &ti,FTextStream &t, +static void generateXMLSection(const Definition *d,FTextStream &ti,FTextStream &t, MemberList *ml,const char *kind,const char *header=0, const char *documentation=0) { if (ml==0) return; MemberListIterator mli(*ml); - MemberDef *md; + const MemberDef *md; int count=0; for (mli.toFirst();(md=mli.current());++mli) { @@ -1079,7 +1081,7 @@ static void generateXMLSection(Definition *d,FTextStream &ti,FTextStream &t, t << " </sectiondef>" << endl; } -static void writeListOfAllMembers(ClassDef *cd,FTextStream &t) +static void writeListOfAllMembers(const ClassDef *cd,FTextStream &t) { t << " <listofallmembers>" << endl; if (cd->memberNameInfoSDict()) @@ -1092,7 +1094,7 @@ static void writeListOfAllMembers(ClassDef *cd,FTextStream &t) MemberInfo *mi; for (mii.toFirst();(mi=mii.current());++mii) { - MemberDef *md=mi->memberDef; + const MemberDef *md=mi->memberDef; if (md->name().at(0)!='@') // skip anonymous members { Protection prot = mi->prot; @@ -1132,7 +1134,7 @@ static void writeInnerClasses(const ClassSDict *cl,FTextStream &t) if (cl) { ClassSDict::Iterator cli(*cl); - ClassDef *cd; + const ClassDef *cd; for (cli.toFirst();(cd=cli.current());++cli) { if (!cd->isHidden() && cd->name().find('@')==-1) // skip anonymous scopes @@ -1157,7 +1159,7 @@ static void writeInnerNamespaces(const NamespaceSDict *nl,FTextStream &t) if (nl) { NamespaceSDict::Iterator nli(*nl); - NamespaceDef *nd; + const NamespaceDef *nd; for (nli.toFirst();(nd=nli.current());++nli) { if (!nd->isHidden() && nd->name().find('@')==-1) // skip anonymous scopes @@ -1206,7 +1208,7 @@ static void writeInnerGroups(const GroupList *gl,FTextStream &t) if (gl) { GroupListIterator gli(*gl); - GroupDef *sgd; + const GroupDef *sgd; for (gli.toFirst();(sgd=gli.current());++gli) { t << " <innergroup refid=\"" << sgd->getOutputFileBase() @@ -1230,7 +1232,7 @@ static void writeInnerDirs(const DirList *dl,FTextStream &t) } } -static void generateXMLForClass(ClassDef *cd,FTextStream &ti) +static void generateXMLForClass(const ClassDef *cd,FTextStream &ti) { // + brief description // + detailed description @@ -1407,14 +1409,14 @@ static void generateXMLForClass(ClassDef *cd,FTextStream &ti) t << " <detaileddescription>" << endl; writeXMLDocBlock(t,cd->docFile(),cd->docLine(),cd,0,cd->documentation()); t << " </detaileddescription>" << endl; - DotClassGraph inheritanceGraph(cd,DotNode::Inheritance); + DotClassGraph inheritanceGraph(cd,Inheritance); if (!inheritanceGraph.isTrivial()) { t << " <inheritancegraph>" << endl; inheritanceGraph.writeXML(t); t << " </inheritancegraph>" << endl; } - DotClassGraph collaborationGraph(cd,DotNode::Collaboration); + DotClassGraph collaborationGraph(cd,Collaboration); if (!collaborationGraph.isTrivial()) { t << " <collaborationgraph>" << endl; @@ -1443,7 +1445,7 @@ static void generateXMLForClass(ClassDef *cd,FTextStream &ti) ti << " </compound>" << endl; } -static void generateXMLForNamespace(NamespaceDef *nd,FTextStream &ti) +static void generateXMLForNamespace(const NamespaceDef *nd,FTextStream &ti) { // + contained class definitions // + contained namespace definitions @@ -1659,7 +1661,7 @@ static void generateXMLForFile(FileDef *fd,FTextStream &ti) ti << " </compound>" << endl; } -static void generateXMLForGroup(GroupDef *gd,FTextStream &ti) +static void generateXMLForGroup(const GroupDef *gd,FTextStream &ti) { // + members // + member groups @@ -1983,7 +1985,7 @@ void generateXML() { ClassSDict::Iterator cli(*Doxygen::classSDict); - ClassDef *cd; + const ClassDef *cd; for (cli.toFirst();(cd=cli.current());++cli) { generateXMLForClass(cd,t); @@ -1999,7 +2001,7 @@ void generateXML() // } //} NamespaceSDict::Iterator nli(*Doxygen::namespaceSDict); - NamespaceDef *nd; + const NamespaceDef *nd; for (nli.toFirst();(nd=nli.current());++nli) { msg("Generating XML output for namespace %s\n",nd->name().data()); @@ -2018,7 +2020,7 @@ void generateXML() } } GroupSDict::Iterator gli(*Doxygen::groupSDict); - GroupDef *gd; + const GroupDef *gd; for (;(gd=gli.current());++gli) { msg("Generating XML output for group %s\n",gd->name().data()); diff --git a/src/xmlgen.h b/src/xmlgen.h index 0555546..4458b9f 100644 --- a/src/xmlgen.h +++ b/src/xmlgen.h @@ -39,7 +39,7 @@ class XMLCodeGenerator : public CodeOutputInterface void writeCodeAnchor(const char *); void writeLineNumber(const char *extRef,const char *compId, const char *anchorId,int l); - void setCurrentDoc(Definition *,const char *,bool){} + void setCurrentDoc(const Definition *,const char *,bool){} void addWord(const char *,bool){} void finish(); diff --git a/src/xmlscanner.h b/src/xmlscanner.h index 6053b96..cb9792c 100644 --- a/src/xmlscanner.h +++ b/src/xmlscanner.h @@ -41,9 +41,9 @@ public: int startLine=-1, int endLine=-1, bool inlineFragment=FALSE, - MemberDef *memberDef=0, + const MemberDef *memberDef=0, bool showLineNumbers=TRUE, - Definition *searchCtx=0, + const Definition *searchCtx=0, bool collectXRefs=TRUE ) { |