diff options
Diffstat (limited to 'src')
150 files changed, 20205 insertions, 18638 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index cb28911..4f4d132 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,13 +1,13 @@ # vim:ts=4:sw=4:expandtab:autoindent: 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}/src + ${PROJECT_SOURCE_DIR}/qtools + ${PROJECT_SOURCE_DIR}/libmd5 + ${PROJECT_SOURCE_DIR}/liblodepng + ${PROJECT_SOURCE_DIR}/libmscgen + ${PROJECT_SOURCE_DIR}/libversion + ${PROJECT_SOURCE_DIR}/vhdlparser + ${PROJECT_SOURCE_DIR}/src ${CLANG_INCLUDEDIR} ${GENERATED_SRC} ) @@ -78,7 +78,7 @@ set_source_files_properties(${GENERATED_SRC}/ce_parse.h PROPERTIES GENERATED 1) # lang_cfg.h add_custom_command( COMMENT "Generating ${GENERATED_SRC}/lang_cfg.h" - COMMAND ${CMAKE_COMMAND} -P ${CMAKE_SOURCE_DIR}/cmake/lang_cfg.cmake ${GENERATED_SRC}/lang_cfg.h ${LANG_CODES} + COMMAND ${CMAKE_COMMAND} -P ${PROJECT_SOURCE_DIR}/cmake/lang_cfg.cmake ${GENERATED_SRC}/lang_cfg.h ${LANG_CODES} DEPENDS ${LANGUAGE_FILES} OUTPUT ${GENERATED_SRC}/lang_cfg.h ) @@ -86,15 +86,15 @@ set_source_files_properties(${GENERATED_SRC}/lang_cfg.h PROPERTIES GENERATED 1) # all resource files if (${CMAKE_VERSION} VERSION_EQUAL "3.11.0" OR ${CMAKE_VERSION} VERSION_GREATER "3.11.0") - file(GLOB RESOURCES CONFIGURE_DEPENDS ${CMAKE_SOURCE_DIR}/templates/*/*) + file(GLOB RESOURCES CONFIGURE_DEPENDS ${PROJECT_SOURCE_DIR}/templates/*/*) else() - file(GLOB RESOURCES ${CMAKE_SOURCE_DIR}/templates/*/*) + file(GLOB RESOURCES ${PROJECT_SOURCE_DIR}/templates/*/*) endif() # resources.cpp add_custom_command( COMMENT "Generating ${GENERATED_SRC}/resources.cpp" - COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_LIST_DIR}/res2cc_cmd.py ${CMAKE_SOURCE_DIR}/templates ${GENERATED_SRC}/resources.cpp + COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_LIST_DIR}/res2cc_cmd.py ${PROJECT_SOURCE_DIR}/templates ${GENERATED_SRC}/resources.cpp DEPENDS ${RESOURCES} ${CMAKE_CURRENT_LIST_DIR}/res2cc_cmd.py OUTPUT ${GENERATED_SRC}/resources.cpp ) @@ -138,9 +138,9 @@ foreach(lex_file ${LEX_FILES}) set_source_files_properties(${GENERATED_SRC}/${lex_file}.l.h PROPERTIES GENERATED 1) # for code coverage we need the flex sources in the build src directory add_custom_command( - COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/src/${lex_file}.l ${CMAKE_BINARY_DIR}/src/${lex_file}.l - DEPENDS ${CMAKE_SOURCE_DIR}/src/${lex_file}.l - OUTPUT ${CMAKE_BINARY_DIR}/src/${lex_file}.l + COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_SOURCE_DIR}/src/${lex_file}.l ${PROJECT_BINARY_DIR}/src/${lex_file}.l + DEPENDS ${PROJECT_SOURCE_DIR}/src/${lex_file}.l + OUTPUT ${PROJECT_BINARY_DIR}/src/${lex_file}.l ) FLEX_TARGET(${lex_file} @@ -156,9 +156,9 @@ BISON_TARGET(constexp COMPILE_FLAGS "${YACC_FLAGS}") add_custom_command( - COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/src/constexp.y ${CMAKE_BINARY_DIR}/src - DEPENDS ${CMAKE_SOURCE_DIR}/src/constexp.y - OUTPUT ${CMAKE_BINARY_DIR}/src/constexp.y + COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_SOURCE_DIR}/src/constexp.y ${PROJECT_BINARY_DIR}/src + DEPENDS ${PROJECT_SOURCE_DIR}/src/constexp.y + OUTPUT ${PROJECT_BINARY_DIR}/src/constexp.y ) add_library(doxycfg STATIC @@ -240,6 +240,7 @@ add_library(doxymain STATIC docgroup.cpp docparser.cpp docsets.cpp + docvisitor.cpp dot.cpp dotcallgraph.cpp dotclassgraph.cpp @@ -295,6 +296,7 @@ add_library(doxymain STATIC searchindex.cpp sqlite3gen.cpp stlsupport.cpp + symbolresolver.cpp tagreader.cpp template.cpp textdocvisitor.cpp @@ -327,7 +329,6 @@ if (use_libclang) find_package(LLVM REQUIRED CONFIG) find_package(Clang REQUIRED CONFIG) if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang") - cmake_minimum_required(VERSION 3.1) target_compile_features(doxymain PRIVATE cxx_alignof) target_compile_features(doxygen PRIVATE cxx_alignof) if (use_libc++) diff --git a/src/cache.h b/src/cache.h new file mode 100644 index 0000000..5f7c834 --- /dev/null +++ b/src/cache.h @@ -0,0 +1,162 @@ +/***************************************************************************** + * + * Copyright (C) 1997-2020 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 CACHE_H +#define CACHE_H + +#include <list> +#include <unordered_map> +#include <mutex> +#include <ctype.h> + +/*! Fixed size cache for value type V using keys of type K. + * + * When the maximum capacity has reached, the least recently used value is removed from the cache + * (LRU strategy). + */ +template<typename K,typename V> +class Cache +{ + public: + using kv_pair = std::pair<K,V>; + using iterator = typename std::list<kv_pair>::iterator; + using const_iterator = typename std::list<kv_pair>::const_iterator; + + //! creates a cache that can hold \a capacity elements + Cache(size_t capacity) : m_capacity(capacity) + { + } + + //! Inserts \a value under \a key in the cache + V *insert(const K &key,V &&value) + { + // remove item if it already exists + remove(key); + // store new item + m_cacheItemList.push_front(kv_pair(key,std::move(value))); + V *result = &m_cacheItemList.front().second; + m_cacheItemMap[key] = m_cacheItemList.begin(); + // remove least recently used item if cache is full + resize(); + return result; + } + + //! Inserts \a value under \a key in the cache + V *insert(const K &key,const V &value) + { + // remove item if it already exists + remove(key); + // store new item + m_cacheItemList.push_front(kv_pair(key,value)); + V *result = &m_cacheItemList.front().second; + m_cacheItemMap[key] = m_cacheItemList.begin(); + // remove least recently used item if cache is full + resize(); + return result; + } + + //! Removes entry \a key from the cache. + //! \note this invalidates any iterators + void remove(const K &key) + { + // remove item if it already exists + auto it = m_cacheItemMap.find(key); + if (it != m_cacheItemMap.end()) + { + m_cacheItemList.erase(it->second); + m_cacheItemMap.erase(it); + } + } + + //! Finds a value in the cache given the corresponding \a key. + //! @returns a pointer to the value or nullptr if the key is not found in the cache + //! @note The hit and miss counters are updated, see hits() and misses(). + V *find(const K &key) + { + auto it = m_cacheItemMap.find(key); + if (it != m_cacheItemMap.end()) + { + // move the item to the front of the list + m_cacheItemList.splice(m_cacheItemList.begin(), + m_cacheItemList, + it->second); + m_hits++; + // return the value + return &it->second->second; + } + else + { + m_misses++; + } + return nullptr; + } + + //! Returns the number of values stored in the cache. + size_t size() const + { + return m_cacheItemMap.size(); + } + + //! Returns the maximum number of values that can be stored in the cache. + size_t capacity() const + { + return m_capacity; + } + + //! Returns how many of the find() calls did find a value in the cache. + uint64_t hits() const + { + return m_hits; + } + + //! Returns how many of the find() calls did not found a value in the cache. + uint64_t misses() const + { + return m_misses; + } + + //! Clears all values in the cache. + void clear() + { + m_cacheItemMap.clear(); + m_cacheItemList.clear(); + } + + iterator begin() { return m_cacheItemList.begin(); } + iterator end() { return m_cacheItemList.end(); } + const_iterator begin() const { return m_cacheItemList.cbegin(); } + const_iterator end() const { return m_cacheItemList.cend(); } + + private: + void resize() + { + if (m_cacheItemMap.size() > m_capacity) + { + auto last_it = m_cacheItemList.end(); + --last_it; + m_cacheItemMap.erase(last_it->first); + m_cacheItemList.pop_back(); + } + } + size_t m_capacity; + // list of items in the cache, sorted by most to least recently used. + std::list<kv_pair> m_cacheItemList; + // mapping for each key to a place in the list where item is found + std::unordered_map<K,iterator> m_cacheItemMap; + uint64_t m_hits=0; + uint64_t m_misses=0; +}; + +#endif diff --git a/src/cite.cpp b/src/cite.cpp index 03bdb02..e02641a 100644 --- a/src/cite.cpp +++ b/src/cite.cpp @@ -368,7 +368,7 @@ void CitationManager::generatePage() //printf("doc=[%s]\n",doc.data()); // 7. add it as a page - addRelatedPage(fileName(),theTranslator->trCiteReferences(),doc,fileName(),1); + addRelatedPage(fileName(),theTranslator->trCiteReferences(),doc,fileName(),1,1); // 8. for latex we just copy the bib files to the output and let // latex do this work. diff --git a/src/clangparser.cpp b/src/clangparser.cpp index 1ac9138..6f32576 100644 --- a/src/clangparser.cpp +++ b/src/clangparser.cpp @@ -25,7 +25,8 @@ //-------------------------------------------------------------------------- -std::mutex g_clangMutex; +static std::mutex g_clangMutex; +static std::mutex g_docCrossReferenceMutex; ClangParser *ClangParser::instance() { @@ -129,7 +130,7 @@ class ClangTUParser::Private std::vector<CXUnsavedFile> ufs; std::vector<CXCursor> cursors; std::unordered_map<std::string,uint> fileMapping; - CXTranslationUnit tu; + CXTranslationUnit tu = 0; CXToken *tokens = 0; uint numTokens = 0; StringVector filesInSameTU; @@ -572,7 +573,7 @@ void ClangTUParser::writeMultiLineCodeLink(CodeOutputInterface &ol, const char *text) { static bool sourceTooltips = Config_getBool(SOURCE_TOOLTIPS); - TooltipManager::instance()->addTooltip(d); + TooltipManager::instance().addTooltip(ol,d); QCString ref = d->getReference(); QCString file = d->getOutputFileBase(); QCString anchor = d->anchor(); @@ -695,7 +696,8 @@ void ClangTUParser::linkIdentifier(CodeOutputInterface &ol,FileDef *fd, p->currentMemberDef && d->definitionType()==Definition::TypeMember && (p->currentMemberDef!=d || p->currentLine<line)) // avoid self-reference { - addDocCrossReference(p->currentMemberDef,dynamic_cast<MemberDef *>(d)); + std::lock_guard<std::mutex> lock(g_docCrossReferenceMutex); + addDocCrossReference(toMemberDefMutable(p->currentMemberDef),toMemberDefMutable(d)); } writeMultiLineCodeLink(ol,fd,line,column,d,text); } @@ -858,7 +860,7 @@ class ClangParser::Private QCString clangCompileDatabase = Config_getString(CLANG_DATABASE_PATH); // load a clang compilation database (https://clang.llvm.org/docs/JSONCompilationDatabase.html) db = clang::tooling::CompilationDatabase::loadFromDirectory(clangCompileDatabase.data(), error); - if (clangCompileDatabase!="0" && db==nullptr) + if (!clangCompileDatabase.isEmpty() && clangCompileDatabase!="0" && db==nullptr) { // user specified a path, but DB file was not found err("%s using clang compilation database path of: \"%s\"\n", error.c_str(), @@ -884,6 +886,7 @@ ClangParser::~ClangParser() std::unique_ptr<ClangTUParser> ClangParser::createTUParser(const FileDef *fd) const { + //printf("ClangParser::createTUParser()\n"); return std::make_unique<ClangTUParser>(*this,fd); } diff --git a/src/clangparser.h b/src/clangparser.h index 8ee1bdb..f948c33 100644 --- a/src/clangparser.h +++ b/src/clangparser.h @@ -30,7 +30,7 @@ class ClangTUParser void parse(); /** Switches to another file within the translation unit started with start(). - * @param[in] fileName The name of the file to switch to. + * @param[in] fd The file definition with the name of the file to switch to. */ void switchToFile(FileDef *fd); diff --git a/src/classdef.cpp b/src/classdef.cpp index c3cd3ee..9586731 100644 --- a/src/classdef.cpp +++ b/src/classdef.cpp @@ -50,12 +50,116 @@ #include "namespacedef.h" #include "membergroup.h" #include "definitionimpl.h" +#include "symbolresolver.h" + +//----------------------------------------------------------------------------- + +static QCString makeQualifiedNameWithTemplateParameters(const ClassDef *cd, + const ArgumentLists *actualParams,uint *actualParamIndex) +{ + //static bool optimizeOutputJava = Config_getBool(OPTIMIZE_OUTPUT_JAVA); + bool hideScopeNames = Config_getBool(HIDE_SCOPE_NAMES); + //printf("qualifiedNameWithTemplateParameters() localName=%s\n",localName().data()); + QCString scName; + const Definition *d=cd->getOuterScope(); + if (d) + { + if (d->definitionType()==Definition::TypeClass) + { + const ClassDef *ocd=toClassDef(d); + scName = ocd->qualifiedNameWithTemplateParameters(actualParams,actualParamIndex); + } + else if (!hideScopeNames) + { + scName = d->qualifiedName(); + } + } + + SrcLangExt lang = cd->getLanguage(); + QCString scopeSeparator = getLanguageSpecificSeparator(lang); + if (!scName.isEmpty()) scName+=scopeSeparator; + + bool isSpecialization = cd->localName().find('<')!=-1; + + QCString clName = cd->className(); + //bool isGeneric = getLanguage()==SrcLangExt_CSharp; + //if (isGeneric && clName.right(2)=="-g") + //{ + // clName = clName.left(clName.length()-2); + //} + //printf("m_impl->lang=%d clName=%s isSpecialization=%d\n",getLanguage(),clName.data(),isSpecialization); + scName+=clName; + if (!cd->templateArguments().empty()) + { + if (actualParams && *actualParamIndex<actualParams->size()) + { + const ArgumentList &al = actualParams->at(*actualParamIndex); + if (!isSpecialization) + { + scName+=tempArgListToString(al,lang); + } + (*actualParamIndex)++; + } + else + { + if (!isSpecialization) + { + scName+=tempArgListToString(cd->templateArguments(),lang); + } + } + } + //printf("qualifiedNameWithTemplateParameters: scope=%s qualifiedName=%s\n",name().data(),scName.data()); + return scName; +} + +static QCString makeDisplayName(const ClassDef *cd,bool includeScope) +{ + //static bool optimizeOutputForJava = Config_getBool(OPTIMIZE_OUTPUT_JAVA); + SrcLangExt lang = cd->getLanguage(); + //static bool vhdlOpt = Config_getBool(OPTIMIZE_OUTPUT_VHDL); + QCString n; + if (lang==SrcLangExt_VHDL) + { + n = VhdlDocGen::getClassName(cd); + } + else + { + if (includeScope) + { + n=cd->qualifiedNameWithTemplateParameters(); + } + else + { + n=cd->className(); + } + } + if (cd->isAnonymous()) + { + n = removeAnonymousScopes(n); + } + QCString sep=getLanguageSpecificSeparator(lang); + if (sep!="::") + { + n=substitute(n,"::",sep); + } + if (cd->compoundType()==ClassDef::Protocol && n.right(2)=="-p") + { + n="<"+n.left(n.length()-2)+">"; + } + //else if (n.right(2)=="-g") + //{ + // n = n.left(n.length()-2); + //} + //printf("ClassDefImpl::displayName()=%s\n",n.data()); + return n; +} + //----------------------------------------------------------------------------- /** Implementation of the ClassDef interface */ -class ClassDefImpl : public DefinitionImpl, public ClassDef +class ClassDefImpl : public DefinitionMixin<ClassDefMutable> { public: ClassDefImpl(const char *fileName,int startLine,int startColumn, @@ -81,8 +185,10 @@ class ClassDefImpl : public DefinitionImpl, public ClassDef virtual QCString displayName(bool includeScope=TRUE) const; virtual CompoundType compoundType() const; virtual QCString compoundTypeString() const; - virtual BaseClassList *baseClasses() const; - virtual BaseClassList *subClasses() const; + virtual BaseClassList baseClasses() const; + virtual void updateBaseClasses(const BaseClassList &bcd); + virtual BaseClassList subClasses() const; + virtual void updateSubClasses(const BaseClassList &bcd); virtual const MemberNameInfoLinkedMap &memberNameInfoLinkedMap() const; virtual Protection protection() const; virtual bool isLinkableInProject() const; @@ -105,7 +211,7 @@ class ClassDefImpl : public DefinitionImpl, public ClassDef virtual UsesClassDict *usedInterfaceClasses() const; virtual ConstraintClassDict *templateTypeConstraints() const; virtual bool isTemplateArgument() const; - virtual Definition *findInnerCompound(const char *name) const; + virtual const Definition *findInnerCompound(const char *name) const; virtual ArgumentLists getTemplateParameterLists() const; virtual QCString qualifiedNameWithTemplateParameters( const ArgumentLists *actualParams=0,uint *actualParamIndex=0) const; @@ -196,7 +302,7 @@ class ClassDefImpl : public DefinitionImpl, public ClassDef 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 reclassifyMember(MemberDefMutable *md,MemberType t); virtual void writeInlineDocumentation(OutputList &ol) const; virtual void writeDeclarationLink(OutputList &ol,bool &found, const char *header,bool localNames) const; @@ -209,8 +315,6 @@ class ClassDefImpl : public DefinitionImpl, public ClassDef 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; virtual int countInheritanceNodes() const; virtual int countMemberDeclarations(MemberListType lt,const ClassDef *inheritedFrom, @@ -221,7 +325,6 @@ class ClassDefImpl : public DefinitionImpl, public ClassDef QPtrDict<void> *visitedClasses=0) const; private: - mutable bool m_visited; void addUsedInterfaceClasses(MemberDef *md,const char *typeStr); void showUsedFiles(OutputList &ol) const; @@ -270,7 +373,7 @@ class ClassDefImpl : public DefinitionImpl, public ClassDef IMPL *m_impl = 0; }; -ClassDef *createClassDef( +ClassDefMutable *createClassDef( const char *fileName,int startLine,int startColumn, const char *name,ClassDef::CompoundType ct, const char *ref,const char *fName, @@ -280,14 +383,15 @@ ClassDef *createClassDef( } //----------------------------------------------------------------------------- -class ClassDefAliasImpl : public DefinitionAliasImpl, public ClassDef +class ClassDefAliasImpl : public DefinitionAliasMixin<ClassDef> { public: - ClassDefAliasImpl(const Definition *newScope,const ClassDef *cd) : DefinitionAliasImpl(newScope,cd) {} - virtual ~ClassDefAliasImpl() {} + ClassDefAliasImpl(const Definition *newScope,const ClassDef *cd) + : DefinitionAliasMixin(newScope,cd) { init(); } + virtual ~ClassDefAliasImpl() { deinit(); } virtual DefType definitionType() const { return TypeClass; } - const ClassDef *getCdAlias() const { return dynamic_cast<const ClassDef*>(getAlias()); } + const ClassDef *getCdAlias() const { return toClassDef(getAlias()); } virtual ClassDef *resolveAlias() { return const_cast<ClassDef*>(getCdAlias()); } virtual QCString getOutputFileBase() const @@ -313,14 +417,14 @@ class ClassDefAliasImpl : public DefinitionAliasImpl, public ClassDef virtual QCString inheritanceGraphFileName() const { return getCdAlias()->inheritanceGraphFileName(); } virtual QCString displayName(bool includeScope=TRUE) const - { return getCdAlias()->displayName(includeScope); } + { return makeDisplayName(this,includeScope); } virtual CompoundType compoundType() const { return getCdAlias()->compoundType(); } virtual QCString compoundTypeString() const { return getCdAlias()->compoundTypeString(); } - virtual BaseClassList *baseClasses() const + virtual BaseClassList baseClasses() const { return getCdAlias()->baseClasses(); } - virtual BaseClassList *subClasses() const + virtual BaseClassList subClasses() const { return getCdAlias()->subClasses(); } virtual const MemberNameInfoLinkedMap &memberNameInfoLinkedMap() const { return getCdAlias()->memberNameInfoLinkedMap(); } @@ -366,13 +470,13 @@ class ClassDefAliasImpl : public DefinitionAliasImpl, public ClassDef { return getCdAlias()->templateTypeConstraints(); } virtual bool isTemplateArgument() const { return getCdAlias()->isTemplateArgument(); } - virtual Definition *findInnerCompound(const char *name) const + virtual const Definition *findInnerCompound(const char *name) const { return getCdAlias()->findInnerCompound(name); } virtual ArgumentLists getTemplateParameterLists() const { return getCdAlias()->getTemplateParameterLists(); } virtual QCString qualifiedNameWithTemplateParameters( const ArgumentLists *actualParams=0,uint *actualParamIndex=0) const - { return getCdAlias()->qualifiedNameWithTemplateParameters(actualParams,actualParamIndex); } + { return makeQualifiedNameWithTemplateParameters(this,actualParams,actualParamIndex); } virtual bool isAbstract() const { return getCdAlias()->isAbstract(); } virtual bool isObjectiveC() const @@ -447,72 +551,7 @@ class ClassDefAliasImpl : public DefinitionAliasImpl, public ClassDef { 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 *,Protection,Specifier,const char *) { } - virtual void insertSubClass(ClassDef *,Protection,Specifier,const char *) { } - virtual void setIncludeFile(FileDef *,const char *,bool,bool) {} - virtual void insertMember(MemberDef *) {} - virtual void insertUsedFile(FileDef *) {} - virtual bool addExample(const char *,const char *, const char *) { return FALSE; } - virtual void mergeCategory(ClassDef *) {} - virtual void setNamespace(NamespaceDef *) {} - virtual void setFileDef(FileDef *) {} - virtual void setSubGrouping(bool) {} - virtual void setProtection(Protection) {} - virtual void setGroupDefForAllMembers(GroupDef *,Grouping::GroupPri_t,const QCString &,int,bool) {} - virtual void addInnerCompound(const Definition *) {} - virtual void addUsedClass(ClassDef *,const char *,Protection) {} - virtual void addUsedByClass(ClassDef *,const char *,Protection) {} - virtual void setIsStatic(bool) {} - virtual void setCompoundType(CompoundType) {} - virtual void setClassName(const char *) {} - virtual void setClassSpecifier(uint64) {} - virtual void setTemplateArguments(const ArgumentList &) {} - virtual void setTemplateBaseClassNames(QDict<int> *) {} - virtual void setTemplateMaster(const ClassDef *) {} - virtual void setTypeConstraints(const ArgumentList &) {} - virtual void addMembersToTemplateInstance(const ClassDef *,const char *) {} - virtual void makeTemplateArgument(bool=TRUE) {} - virtual void setCategoryOf(ClassDef *) {} - virtual void setUsedOnly(bool) {} - virtual void addTaggedInnerClass(ClassDef *) {} - virtual void setTagLessReference(ClassDef *) {} - virtual void setName(const char *) {} - virtual void setMetaData(const char *) {} - 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 &) const {} - virtual void writeDocumentationForInnerClasses(OutputList &) const {} - virtual void writeMemberPages(OutputList &) const {} - virtual void writeMemberList(OutputList &) const {} - virtual void writeDeclaration(OutputList &,const MemberDef *,bool, - const ClassDef *,const char *) const {} - virtual void writeQuickMemberLinks(OutputList &,const MemberDef *) const {} - virtual void writeSummaryLinks(OutputList &) const {} - virtual void reclassifyMember(MemberDef *,MemberType) {} - virtual void writeInlineDocumentation(OutputList &) const {} - virtual void writeDeclarationLink(OutputList &ol,bool &found, - const char *header,bool localNames) const - { getCdAlias()->writeDeclarationLink(ol,found,header,localNames); } - virtual void removeMemberFromLists(MemberDef *) {} - virtual void setAnonymousEnumType() {} - virtual void countMembers() {} - virtual void sortAllMembersList() {} - virtual void addGroupedInheritedMembers(OutputList &,MemberListType, - const ClassDef *,const QCString &) 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 @@ -520,17 +559,27 @@ class ClassDefAliasImpl : public DefinitionAliasImpl, public ClassDef 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 &,MemberListType,const QCString &, - const char *,bool,const ClassDef *, int,bool,bool, QPtrDict<void> *) const {} - private: - mutable bool m_visited = false; + virtual void writeDeclarationLink(OutputList &ol,bool &found, + const char *header,bool localNames) const + { getCdAlias()->writeDeclarationLink(ol,found,header,localNames); } + 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 updateBaseClasses(const BaseClassList &) {} + virtual void updateSubClasses(const BaseClassList &) {} }; + ClassDef *createClassDefAlias(const Definition *newScope,const ClassDef *cd) { - return new ClassDefAliasImpl(newScope,cd); + ClassDef *acd = new ClassDefAliasImpl(newScope,cd); + //printf("cd name=%s localName=%s qualifiedName=%s qualifiedNameWith=%s displayName()=%s\n", + // acd->name().data(),acd->localName().data(),acd->qualifiedName().data(), + // acd->qualifiedNameWithTemplateParameters().data(),acd->displayName().data()); + return acd; } //----------------------------------------------------------------------------- @@ -567,11 +616,11 @@ class ClassDefImpl::IMPL /*! List of base class (or super-classes) from which this class derives * directly. */ - BaseClassList *inherits = 0; + BaseClassList inherits; /*! List of sub-classes that directly derive from this class */ - BaseClassList *inheritedBy = 0; + BaseClassList inheritedBy; /*! Namespace this class is part of * (this is the inner most namespace in case of nested namespaces) @@ -703,8 +752,6 @@ void ClassDefImpl::IMPL::init(const char *defFileName, const char *name, fileName=ctStr+name; } exampleSDict = 0; - inherits = 0; - inheritedBy = 0; incInfo=0; prot=Public; nspace=0; @@ -756,8 +803,6 @@ ClassDefImpl::IMPL::IMPL() : vhdlSummaryTitles(17) ClassDefImpl::IMPL::~IMPL() { - delete inherits; - delete inheritedBy; delete exampleSDict; delete usesImplClassDict; delete usedByImplClassDict; @@ -780,9 +825,8 @@ ClassDefImpl::ClassDefImpl( const char *nm,CompoundType ct, const char *lref,const char *fName, bool isSymbol,bool isJavaEnum) - : DefinitionImpl(defFileName,defLine,defColumn,removeRedundantWhiteSpace(nm),0,0,isSymbol) + : DefinitionMixin(defFileName,defLine,defColumn,removeRedundantWhiteSpace(nm),0,0,isSymbol) { - m_visited=FALSE; setReference(lref); m_impl = new ClassDefImpl::IMPL; m_impl->compType = ct; @@ -810,44 +854,7 @@ QCString ClassDefImpl::getMemberListFileName() const QCString ClassDefImpl::displayName(bool includeScope) const { - //static bool optimizeOutputForJava = Config_getBool(OPTIMIZE_OUTPUT_JAVA); - SrcLangExt lang = getLanguage(); - //static bool vhdlOpt = Config_getBool(OPTIMIZE_OUTPUT_VHDL); - QCString n; - if (lang==SrcLangExt_VHDL) - { - n = VhdlDocGen::getClassName(this); - } - else - { - if (includeScope) - { - n=qualifiedNameWithTemplateParameters(); - } - else - { - n=className(); - } - } - if (isAnonymous()) - { - n = removeAnonymousScopes(n); - } - QCString sep=getLanguageSpecificSeparator(lang); - if (sep!="::") - { - n=substitute(n,"::",sep); - } - if (m_impl->compType==ClassDef::Protocol && n.right(2)=="-p") - { - n="<"+n.left(n.length()-2)+">"; - } - //else if (n.right(2)=="-g") - //{ - // n = n.left(n.length()-2); - //} - //printf("ClassDefImpl::displayName()=%s\n",n.data()); - return n; + return makeDisplayName(this,includeScope); } // inserts a base/super class in the inheritance list @@ -855,13 +862,7 @@ void ClassDefImpl::insertBaseClass(ClassDef *cd,const char *n,Protection p, Specifier s,const char *t) { //printf("*** insert base class %s into %s\n",cd->name().data(),name().data()); - //inherits->inSort(new BaseClassDef(cd,p,s,t)); - if (m_impl->inherits==0) - { - m_impl->inherits = new BaseClassList; - m_impl->inherits->setAutoDelete(TRUE); - } - m_impl->inherits->append(new BaseClassDef(cd,n,p,s,t)); + m_impl->inherits.push_back(BaseClassDef(cd,n,p,s,t)); m_impl->isSimple = FALSE; } @@ -872,12 +873,7 @@ void ClassDefImpl::insertSubClass(ClassDef *cd,Protection p, //printf("*** insert sub class %s into %s\n",cd->name().data(),name().data()); static bool extractPrivate = Config_getBool(EXTRACT_PRIVATE); if (!extractPrivate && cd->protection()==Private) return; - if (m_impl->inheritedBy==0) - { - m_impl->inheritedBy = new BaseClassList; - m_impl->inheritedBy->setAutoDelete(TRUE); - } - m_impl->inheritedBy->inSort(new BaseClassDef(cd,0,p,s,t)); + m_impl->inheritedBy.push_back(BaseClassDef(cd,0,p,s,t)); m_impl->isSimple = FALSE; } @@ -1218,7 +1214,7 @@ void ClassDefImpl::computeAnchors() { if ((ml->listType()&MemberListType_detailedLists)==0) { - setAnchors(ml); + ml->setAnchors(); } } @@ -1248,6 +1244,7 @@ void ClassDefImpl::distributeMemberGroupDocumentation() void ClassDefImpl::findSectionsInDocumentation() { + docFindSections(briefDescription(),this,docFile()); docFindSections(documentation(),this,docFile()); if (m_impl->memberGroupSDict) { @@ -1281,27 +1278,31 @@ void ClassDefImpl::insertUsedFile(FileDef *fd) ClassDef *cd; for (qdi.toFirst();(cd=qdi.current());++qdi) { - cd->insertUsedFile(fd); + ClassDefMutable *cdm = toClassDefMutable(cd); + if (cdm) + { + cdm->insertUsedFile(fd); + } } } } -static void writeInheritanceSpecifier(OutputList &ol,BaseClassDef *bcd) +static void writeInheritanceSpecifier(OutputList &ol,const BaseClassDef &bcd) { - if (bcd->prot!=Public || bcd->virt!=Normal) + if (bcd.prot!=Public || bcd.virt!=Normal) { ol.startTypewriter(); ol.docify(" ["); - QStrList sl; - if (bcd->prot==Protected) sl.append("protected"); - else if (bcd->prot==Private) sl.append("private"); - if (bcd->virt==Virtual) sl.append("virtual"); - const char *s=sl.first(); - while (s) + StringVector sl; + if (bcd.prot==Protected) sl.push_back("protected"); + else if (bcd.prot==Private) sl.push_back("private"); + if (bcd.virt==Virtual) sl.push_back("virtual"); + bool first=true; + for (const auto &s : sl) { - ol.docify(s); - s=sl.next(); - if (s) ol.docify(", "); + if (!first) ol.docify(", "); + ol.docify(s.c_str()); + first=false; } ol.docify("]"); ol.endTypewriter(); @@ -1358,7 +1359,7 @@ static void searchTemplateSpecs(/*in*/ const Definition *d, { searchTemplateSpecs(d->getOuterScope(),result,name,lang); } - const ClassDef *cd=dynamic_cast<const ClassDef *>(d); + const ClassDef *cd=toClassDef(d); if (!name.isEmpty()) name+="::"; QCString clName = d->localName(); if (/*clName.right(2)=="-g" ||*/ clName.right(2)=="-p") @@ -1659,24 +1660,15 @@ void ClassDefImpl::showUsedFiles(OutputList &ol) const int ClassDefImpl::countInheritanceNodes() const { int count=0; - BaseClassDef *ibcd; - if (m_impl->inheritedBy) + for (const auto &ibcd : m_impl->inheritedBy) { - BaseClassListIterator it(*m_impl->inheritedBy); - for (;(ibcd=it.current());++it) - { - ClassDef *icd=ibcd->classDef; - if ( icd->isVisibleInHierarchy()) count++; - } + const ClassDef *icd=ibcd.classDef; + if ( icd->isVisibleInHierarchy()) count++; } - if (m_impl->inherits) + for (const auto &ibcd : m_impl->inherits) { - BaseClassListIterator it(*m_impl->inherits); - for (;(ibcd=it.current());++it) - { - ClassDef *icd=ibcd->classDef; - if ( icd->isVisibleInHierarchy()) count++; - } + const ClassDef *icd=ibcd.classDef; + if ( icd->isVisibleInHierarchy()) count++; } return count; } @@ -1726,12 +1718,12 @@ void ClassDefImpl::writeInheritanceGraph(OutputList &ol) const ol.disableAllBut(OutputGenerator::Man); } - if (m_impl->inherits && m_impl->inherits->count()>0) + if (!m_impl->inherits.empty()) { ol.startParagraph(); //parseText(ol,theTranslator->trInherits()+" "); - QCString inheritLine = theTranslator->trInheritsList((int)m_impl->inherits->count()); + QCString inheritLine = theTranslator->trInheritsList((int)m_impl->inherits.size()); QRegExp marker("@[0-9]+"); int index=0,newIndex,matchLen; // now replace all markers in inheritLine with links to the classes @@ -1740,15 +1732,15 @@ void ClassDefImpl::writeInheritanceGraph(OutputList &ol) const ol.parseText(inheritLine.mid(index,newIndex-index)); bool ok; uint entryIndex = inheritLine.mid(newIndex+1,matchLen-1).toUInt(&ok); - BaseClassDef *bcd=m_impl->inherits->at(entryIndex); - if (ok && bcd) + BaseClassDef &bcd=m_impl->inherits.at(entryIndex); + if (ok) { - ClassDef *cd=bcd->classDef; + ClassDef *cd=bcd.classDef; // use the class name but with the template arguments as given // in the inheritance relation QCString displayName = insertTemplateSpecifierInScope( - cd->displayName(),bcd->templSpecifiers); + cd->displayName(),bcd.templSpecifiers); if (cd->isLinkable()) { @@ -1773,10 +1765,10 @@ void ClassDefImpl::writeInheritanceGraph(OutputList &ol) const } // write subclasses - if (m_impl->inheritedBy && m_impl->inheritedBy->count()>0) + if (!m_impl->inheritedBy.empty()) { ol.startParagraph(); - QCString inheritLine = theTranslator->trInheritedByList((int)m_impl->inheritedBy->count()); + QCString inheritLine = theTranslator->trInheritedByList((int)m_impl->inheritedBy.size()); QRegExp marker("@[0-9]+"); int index=0,newIndex,matchLen; // now replace all markers in inheritLine with links to the classes @@ -1785,10 +1777,10 @@ void ClassDefImpl::writeInheritanceGraph(OutputList &ol) const ol.parseText(inheritLine.mid(index,newIndex-index)); bool ok; uint entryIndex = inheritLine.mid(newIndex+1,matchLen-1).toUInt(&ok); - BaseClassDef *bcd=m_impl->inheritedBy->at(entryIndex); - if (ok && bcd) + BaseClassDef &bcd=m_impl->inheritedBy.at(entryIndex); + if (ok) { - ClassDef *cd=bcd->classDef; + ClassDef *cd=bcd.classDef; if (cd->isLinkable()) { ol.writeObjectLink(cd->getReference(),cd->getOutputFileBase(),cd->anchor(),cd->displayName()); @@ -1934,35 +1926,30 @@ void ClassDefImpl::writeIncludeFilesForSlice(OutputList &ol) const ol.docify("class "); } ol.docify(stripScope(name())); - if (m_impl->inherits) + if (!m_impl->inherits.empty()) { if (m_impl->spec & (Entry::Interface|Entry::Exception)) { ol.docify(" extends "); - BaseClassListIterator it(*m_impl->inherits); - BaseClassDef *ibcd; - for (;(ibcd=it.current());++it) + bool first=true; + for (const auto &ibcd : m_impl->inherits) { - ClassDef *icd = ibcd->classDef; + if (!first) ol.docify(", "); + ClassDef *icd = ibcd.classDef; ol.docify(icd->name()); - if (!it.atLast()) - { - ol.docify(", "); - } + first=false; } } else { // Must be a class. - bool implements = FALSE; - BaseClassListIterator it(*m_impl->inherits); - BaseClassDef *ibcd; - for (;(ibcd=it.current());++it) + bool implements = false; + for (const auto &ibcd : m_impl->inherits) { - ClassDef *icd = ibcd->classDef; + ClassDef *icd = ibcd.classDef; if (icd->isInterface()) { - implements = TRUE; + implements = true; } else { @@ -1973,20 +1960,14 @@ void ClassDefImpl::writeIncludeFilesForSlice(OutputList &ol) const if (implements) { ol.docify(" implements "); - bool first = TRUE; - for (ibcd=it.toFirst();(ibcd=it.current());++it) + bool first = true; + for (const auto &ibcd : m_impl->inherits) { - ClassDef *icd = ibcd->classDef; + ClassDef *icd = ibcd.classDef; if (icd->isInterface()) { - if (!first) - { - ol.docify(", "); - } - else - { - first = FALSE; - } + if (!first) ol.docify(", "); + first = false; ol.docify(icd->name()); } } @@ -2222,32 +2203,27 @@ void ClassDefImpl::writeTagFile(FTextStream &tagFile) { tagFile << " <templarg>" << convertToXML(a.name) << "</templarg>" << endl; } - if (m_impl->inherits) + for (const auto &ibcd : m_impl->inherits) { - BaseClassListIterator it(*m_impl->inherits); - BaseClassDef *ibcd; - for (it.toFirst();(ibcd=it.current());++it) + ClassDef *cd=ibcd.classDef; + if (cd && cd->isLinkable()) { - ClassDef *cd=ibcd->classDef; - if (cd && cd->isLinkable()) + if (!Config_getString(GENERATE_TAGFILE).isEmpty()) { - if (!Config_getString(GENERATE_TAGFILE).isEmpty()) + tagFile << " <base"; + if (ibcd.prot==Protected) { - tagFile << " <base"; - if (ibcd->prot==Protected) - { - tagFile << " protection=\"protected\""; - } - else if (ibcd->prot==Private) - { - tagFile << " protection=\"private\""; - } - if (ibcd->virt==Virtual) - { - tagFile << " virtualness=\"virtual\""; - } - tagFile << ">" << convertToXML(cd->name()) << "</base>" << endl; + tagFile << " protection=\"protected\""; } + else if (ibcd.prot==Private) + { + tagFile << " protection=\"private\""; + } + if (ibcd.virt==Virtual) + { + tagFile << " virtualness=\"virtual\""; + } + tagFile << ">" << convertToXML(cd->name()) << "</base>" << endl; } } } @@ -2936,16 +2912,21 @@ void ClassDefImpl::writeDocumentationForInnerClasses(OutputList &ol) const ClassDef *innerCd; for (cli.toFirst();(innerCd=cli.current());++cli) { - if (innerCd->isLinkableInProject() && innerCd->templateMaster()==0 && - protectionLevelVisible(innerCd->protection()) && - !innerCd->isEmbeddedInOuterScope() - ) + ClassDefMutable *innerCdm = toClassDefMutable(innerCd); + if (innerCdm) { - msg("Generating docs for nested compound %s...\n",qPrint(innerCd->name())); - innerCd->writeDocumentation(ol); - innerCd->writeMemberList(ol); + if ( + innerCd->isLinkableInProject() && innerCd->templateMaster()==0 && + protectionLevelVisible(innerCd->protection()) && + !innerCd->isEmbeddedInOuterScope() + ) + { + msg("Generating docs for nested compound %s...\n",qPrint(innerCd->name())); + innerCdm->writeDocumentation(ol); + innerCdm->writeMemberList(ol); + } + innerCdm->writeDocumentationForInnerClasses(ol); } - innerCd->writeDocumentationForInnerClasses(ol); } } } @@ -3266,7 +3247,8 @@ void ClassDefImpl::addTypeConstraint(const QCString &typeConstraint,const QCStri //printf("addTypeConstraint(%s,%s)\n",type.data(),typeConstraint.data()); static bool hideUndocRelation = Config_getBool(HIDE_UNDOC_RELATIONS); if (typeConstraint.isEmpty() || type.isEmpty()) return; - ClassDef *cd = const_cast<ClassDef*>(getResolvedClass(this,getFileDef(),typeConstraint)); + SymbolResolver resolver(getFileDef()); + ClassDefMutable *cd = resolver.resolveClassMutable(this,typeConstraint); if (cd==0 && !hideUndocRelation) { cd = new ClassDefImpl(getDefFileName(),getDefLine(),getDefColumn(),typeConstraint,ClassDef::Class); @@ -3337,29 +3319,29 @@ bool ClassDefImpl::hasNonReferenceSuperClass() const { return TRUE; // we're done if this class is not a reference } - if (m_impl->inheritedBy) + for (const auto &ibcd : m_impl->inheritedBy) { - BaseClassListIterator bcli(*m_impl->inheritedBy); - for ( ; bcli.current() && !found ; ++bcli ) // for each super class + ClassDef *bcd=ibcd.classDef; + // recurse into the super class branch + found = found || bcd->hasNonReferenceSuperClass(); + if (!found) { - ClassDef *bcd=bcli.current()->classDef; - // recurse into the super class branch - found = found || bcd->hasNonReferenceSuperClass(); - if (!found) + // look for template instances that might have non-reference super classes + QDict<ClassDef> *cil = bcd->getTemplateInstances(); + if (cil) { - // look for template instances that might have non-reference super classes - QDict<ClassDef> *cil = bcd->getTemplateInstances(); - if (cil) + QDictIterator<ClassDef> tidi(*cil); + for ( ; tidi.current() && !found ; ++tidi) // for each template instance { - QDictIterator<ClassDef> tidi(*cil); - for ( ; tidi.current() && !found ; ++tidi) // for each template instance - { - // recurse into the template instance branch - found = found || tidi.current()->hasNonReferenceSuperClass(); - } + // recurse into the template instance branch + found = found || tidi.current()->hasNonReferenceSuperClass(); } } } + else + { + break; + } } return found; } @@ -3455,16 +3437,14 @@ bool ClassDefImpl::isLinkable() const /*! the class is visible in a class diagram, or class hierarchy */ bool ClassDefImpl::isVisibleInHierarchy() const { - static bool allExternals = Config_getBool(ALLEXTERNALS); - static bool hideUndocClasses = Config_getBool(HIDE_UNDOC_CLASSES); - static bool extractStatic = Config_getBool(EXTRACT_STATIC); + bool allExternals = Config_getBool(ALLEXTERNALS); + bool hideUndocClasses = Config_getBool(HIDE_UNDOC_CLASSES); + bool extractStatic = Config_getBool(EXTRACT_STATIC); return // show all classes or a subclass is visible - (allExternals || hasNonReferenceSuperClass()) && + ((allExternals && !isArtificial()) || hasNonReferenceSuperClass()) && // and not an anonymous compound !isAnonymous() && - // not an artificially introduced class - /*!isArtificial() &&*/ // 1.8.2: allowed these to appear // and not privately inherited protectionLevelVisible(m_impl->prot) && // documented or shown anyway or documentation is external @@ -3479,7 +3459,7 @@ bool ClassDefImpl::isVisibleInHierarchy() const bool ClassDefImpl::hasDocumentation() const { - return DefinitionImpl::hasDocumentation(); + return DefinitionMixin::hasDocumentation(); } //---------------------------------------------------------------------- @@ -3496,21 +3476,12 @@ bool ClassDefImpl::isBaseClass(const ClassDef *bcd, bool followInstances,int lev err("Possible recursive class relation while inside %s and looking for base class %s\n",qPrint(name()),qPrint(bcd->name())); return FALSE; } - if (baseClasses()) + for (const auto &bclass : baseClasses()) { - // Beware: trying to optimise the iterator away using ->first() & ->next() - // causes bug 625531 - BaseClassListIterator bcli(*baseClasses()); - for ( ; bcli.current() && !found ; ++bcli) - { - const ClassDef *ccd=bcli.current()->classDef; - if (!followInstances && ccd->templateMaster()) ccd=ccd->templateMaster(); - //printf("isBaseClass() baseclass %s\n",ccd->name().data()); - if (ccd==bcd) - found=TRUE; - else - found=ccd->isBaseClass(bcd,followInstances,level+1); - } + const ClassDef *ccd = bclass.classDef; + if (!followInstances && ccd->templateMaster()) ccd=ccd->templateMaster(); + found = (ccd==bcd) || ccd->isBaseClass(bcd,followInstances,level+1); + if (found) break; } return found; } @@ -3525,17 +3496,11 @@ bool ClassDefImpl::isSubClass(ClassDef *cd,int level) const err("Possible recursive class relation while inside %s and looking for derived class %s\n",qPrint(name()),qPrint(cd->name())); return FALSE; } - if (subClasses()) + for (const auto &iscd : subClasses()) { - BaseClassListIterator bcli(*subClasses()); - for ( ; bcli.current() && !found ; ++bcli) - { - ClassDef *ccd=bcli.current()->classDef; - if (ccd==cd) - found=TRUE; - else - found=ccd->isSubClass(cd,level+1); - } + ClassDef *ccd=iscd.classDef; + found = (ccd==cd) || ccd->isSubClass(cd,level+1); + if (found) break; } return found; } @@ -3568,15 +3533,11 @@ void ClassDefImpl::mergeMembers() //printf(" mergeMembers for %s\n",name().data()); static bool inlineInheritedMembers = Config_getBool(INLINE_INHERITED_MEMB); static bool extractPrivate = Config_getBool(EXTRACT_PRIVATE); - if (baseClasses()) + for (const auto &bcd : baseClasses()) { - //printf(" => has base classes!\n"); - BaseClassListIterator bcli(*baseClasses()); - BaseClassDef *bcd; - for ( ; (bcd=bcli.current()) ; ++bcli ) + ClassDefMutable *bClass=toClassDefMutable(bcd.classDef); + if (bClass) { - ClassDef *bClass=bcd->classDef; - // merge the members in the base class of this inheritance branch first bClass->mergeMembers(); @@ -3610,8 +3571,8 @@ void ClassDefImpl::mergeMembers() if (srcCd==dstCd || dstCd->isBaseClass(srcCd,TRUE)) // member is in the same or a base class { - ArgumentList &srcAl = srcMd->argumentList(); - ArgumentList &dstAl = dstMd->argumentList(); + ArgumentList &srcAl = const_cast<ArgumentList&>(srcMd->argumentList()); + ArgumentList &dstAl = const_cast<ArgumentList&>(dstMd->argumentList()); found=matchArguments2( srcMd->getOuterScope(),srcMd->getFileDef(),&srcAl, dstMd->getOuterScope(),dstMd->getFileDef(),&dstAl, @@ -3683,8 +3644,8 @@ void ClassDefImpl::mergeMembers() if (!found && srcMd->protection()!=Private && !srcMd->isFriend()) { Protection prot=srcMd->protection(); - if (bcd->prot==Protected && prot==Public) prot=bcd->prot; - else if (bcd->prot==Private) prot=bcd->prot; + if (bcd.prot==Protected && prot==Public) prot=bcd.prot; + else if (bcd.prot==Private) prot=bcd.prot; if (inlineInheritedMembers) { @@ -3696,7 +3657,7 @@ void ClassDefImpl::mergeMembers() } Specifier virt=srcMi->virt(); - if (virt==Normal && bcd->virt!=Normal) virt=bcd->virt; + if (virt==Normal && bcd.virt!=Normal) virt=bcd.virt; std::unique_ptr<MemberInfo> newMi = std::make_unique<MemberInfo>(srcMd,prot,virt,TRUE); newMi->setScopePath(bClass->name()+sep+srcMi->scopePath()); @@ -3742,22 +3703,22 @@ void ClassDefImpl::mergeMembers() if (!mi->memberDef()->isFriend()) // don't inherit friends { Protection prot = mi->prot(); - if (bcd->prot==Protected) + if (bcd.prot==Protected) { if (prot==Public) prot=Protected; } - else if (bcd->prot==Private) + else if (bcd.prot==Private) { prot=Private; } - //printf("%s::%s: prot=%d bcd->prot=%d result=%d\n", + //printf("%s::%s: prot=%d bcd.prot=%d result=%d\n", // name().data(),mi->memberDef->name().data(),mi->prot, - // bcd->prot,prot); + // bcd.prot,prot); if (prot!=Private || extractPrivate) { Specifier virt=mi->virt(); - if (virt==Normal && bcd->virt!=Normal) virt=bcd->virt; + if (virt==Normal && bcd.virt!=Normal) virt=bcd.virt; if (inlineInheritedMembers) { @@ -3787,105 +3748,113 @@ void ClassDefImpl::mergeMembers() /*! Merges the members of a Objective-C category into this class. */ -void ClassDefImpl::mergeCategory(ClassDef *category) +void ClassDefImpl::mergeCategory(ClassDef *cat) { - static bool extractLocalMethods = Config_getBool(EXTRACT_LOCAL_METHODS); - bool makePrivate = category->isLocal(); - // in case extract local methods is not enabled we don't add the methods - // of the category in case it is defined in the .m file. - if (makePrivate && !extractLocalMethods) return; - bool isExtension = category->isExtension(); - - category->setCategoryOf(this); - if (isExtension) + ClassDefMutable *category = toClassDefMutable(cat); + if (category) { - category->setArtificial(TRUE); + static bool extractLocalMethods = Config_getBool(EXTRACT_LOCAL_METHODS); + bool makePrivate = category->isLocal(); + // in case extract local methods is not enabled we don't add the methods + // of the category in case it is defined in the .m file. + if (makePrivate && !extractLocalMethods) return; + bool isExtension = category->isExtension(); - // copy base classes/protocols from extension - if (category->baseClasses()) + category->setCategoryOf(this); + if (isExtension) { - BaseClassListIterator bcli(*category->baseClasses()); - BaseClassDef *bcd; - for ( ; (bcd=bcli.current()) ; ++bcli ) + category->setArtificial(TRUE); + + // copy base classes/protocols from extension + for (const auto &bcd : category->baseClasses()) { - insertBaseClass(bcd->classDef,bcd->usedName,bcd->prot,bcd->virt,bcd->templSpecifiers); - // correct bcd->classDef so that they do no longer derive from + insertBaseClass(bcd.classDef,bcd.usedName,bcd.prot,bcd.virt,bcd.templSpecifiers); + // correct bcd.classDef so that they do no longer derive from // category, but from this class! - if (bcd->classDef->subClasses()) + BaseClassList scl = bcd.classDef->subClasses(); + for (auto &scd : scl) { - BaseClassListIterator scli(*bcd->classDef->subClasses()); - BaseClassDef *scd; - for ( ; (scd=scli.current()) ; ++scli ) + if (scd.classDef==category) { - if (scd->classDef==category) - { - scd->classDef=this; - } + scd.classDef=this; } } + bcd.classDef->updateSubClasses(scl); } } - } - // make methods private for categories defined in the .m file - //printf("%s::mergeCategory makePrivate=%d\n",name().data(),makePrivate); + // make methods private for categories defined in the .m file + //printf("%s::mergeCategory makePrivate=%d\n",name().data(),makePrivate); - const MemberNameInfoLinkedMap &srcMnd = category->memberNameInfoLinkedMap(); - MemberNameInfoLinkedMap &dstMnd = m_impl->allMemberNameInfoLinkedMap; + const MemberNameInfoLinkedMap &srcMnd = category->memberNameInfoLinkedMap(); + MemberNameInfoLinkedMap &dstMnd = m_impl->allMemberNameInfoLinkedMap; - for (auto &srcMni : srcMnd) - { - MemberNameInfo *dstMni=dstMnd.find(srcMni->memberName()); - if (dstMni) // method is already defined in the class + for (auto &srcMni : srcMnd) { - //printf("Existing member %s\n",srcMni->memberName()); - auto &dstMi = dstMni->front(); - auto &srcMi = srcMni->front(); - if (srcMi && dstMi) + MemberNameInfo *dstMni=dstMnd.find(srcMni->memberName()); + if (dstMni) // method is already defined in the class { - combineDeclarationAndDefinition(srcMi->memberDef(),dstMi->memberDef()); - dstMi->memberDef()->setCategory(category); - dstMi->memberDef()->setCategoryRelation(srcMi->memberDef()); - srcMi->memberDef()->setCategoryRelation(dstMi->memberDef()); + //printf("Existing member %s\n",srcMni->memberName()); + auto &dstMi = dstMni->front(); + auto &srcMi = srcMni->front(); + if (srcMi && dstMi) + { + MemberDefMutable *smdm = toMemberDefMutable(srcMi->memberDef()); + MemberDefMutable *dmdm = toMemberDefMutable(dstMi->memberDef()); + if (smdm && dmdm) + { + combineDeclarationAndDefinition(smdm,dmdm); + dmdm->setCategory(category); + dmdm->setCategoryRelation(smdm); + smdm->setCategoryRelation(dmdm); + } + } } - } - else // new method name - { - //printf("New member %s\n",srcMni->memberName()); - // create a deep copy of the list - MemberNameInfo *newMni = dstMnd.add(srcMni->memberName()); - - // copy the member(s) from the category to this class - for (auto &mi : *srcMni) + else // new method name { - //printf("Adding '%s'\n",mi->memberDef->name().data()); - Protection prot = mi->prot(); - //if (makePrivate) prot = Private; - std::unique_ptr<MemberDef> newMd { mi->memberDef()->deepCopy() }; - if (newMd) + //printf("New member %s\n",srcMni->memberName()); + // create a deep copy of the list + MemberNameInfo *newMni = dstMnd.add(srcMni->memberName()); + + // copy the member(s) from the category to this class + for (auto &mi : *srcMni) { - //printf("Copying member %s\n",mi->memberDef->name().data()); - newMd->moveTo(this); + //printf("Adding '%s'\n",mi->memberDef->name().data()); + Protection prot = mi->prot(); + //if (makePrivate) prot = Private; + std::unique_ptr<MemberDefMutable> newMd { toMemberDefMutable(mi->memberDef()->deepCopy()) }; + if (newMd) + { + //printf("Copying member %s\n",mi->memberDef->name().data()); + newMd->moveTo(this); - std::unique_ptr<MemberInfo> newMi=std::make_unique<MemberInfo>(newMd.get(),prot,mi->virt(),mi->inherited()); - newMi->setScopePath(mi->scopePath()); - newMi->setAmbigClass(mi->ambigClass()); - newMi->setAmbiguityResolutionScope(mi->ambiguityResolutionScope()); - newMni->push_back(std::move(newMi)); + std::unique_ptr<MemberInfo> newMi=std::make_unique<MemberInfo>(newMd.get(),prot,mi->virt(),mi->inherited()); + newMi->setScopePath(mi->scopePath()); + newMi->setAmbigClass(mi->ambigClass()); + newMi->setAmbiguityResolutionScope(mi->ambiguityResolutionScope()); + newMni->push_back(std::move(newMi)); - // also add the newly created member to the global members list + // also add the newly created member to the global members list - QCString name = newMd->name(); - MemberName *mn = Doxygen::memberNameLinkedMap->add(name); + QCString name = newMd->name(); + MemberName *mn = Doxygen::memberNameLinkedMap->add(name); - newMd->setCategory(category); - newMd->setCategoryRelation(mi->memberDef()); - mi->memberDef()->setCategoryRelation(newMd.get()); - if (makePrivate || isExtension) - { - newMd->makeImplementationDetail(); + if (newMd) + { + newMd->setCategory(category); + newMd->setCategoryRelation(mi->memberDef()); + } + MemberDefMutable *mdm = toMemberDefMutable(mi->memberDef()); + if (mdm) + { + mdm->setCategoryRelation(newMd.get()); + } + if (newMd && (makePrivate || isExtension)) + { + newMd->makeImplementationDetail(); + } + internalInsertMember(newMd.get(),prot,FALSE); + mn->push_back(std::move(newMd)); } - internalInsertMember(newMd.get(),prot,FALSE); - mn->push_back(std::move(newMd)); } } } @@ -4047,7 +4016,7 @@ QCString ClassDefImpl::getSourceFileBase() const } else { - return DefinitionImpl::getSourceFileBase(); + return DefinitionMixin::getSourceFileBase(); } } @@ -4059,11 +4028,14 @@ void ClassDefImpl::setGroupDefForAllMembers(GroupDef *gd,Grouping::GroupPri_t pr { for (auto &mi : *mni) { - MemberDef *md=mi->memberDef(); - md->setGroupDef(gd,pri,fileName,startLine,hasDocs); - gd->insertMember(md,TRUE); - ClassDef *innerClass = md->getClassDefOfAnonymousType(); - if (innerClass) innerClass->setGroupDefForAllMembers(gd,pri,fileName,startLine,hasDocs); + MemberDefMutable *md = toMemberDefMutable(mi->memberDef()); + if (md) + { + md->setGroupDef(gd,pri,fileName,startLine,hasDocs); + gd->insertMember(md,TRUE); + ClassDefMutable *innerClass = toClassDefMutable(md->getClassDefOfAnonymousType()); + if (innerClass) innerClass->setGroupDefForAllMembers(gd,pri,fileName,startLine,hasDocs); + } } } } @@ -4078,13 +4050,13 @@ void ClassDefImpl::addInnerCompound(const Definition *d) { m_impl->innerClasses = new ClassSDict(17); } - m_impl->innerClasses->inSort(d->localName(),dynamic_cast<const ClassDef *>(d)); + m_impl->innerClasses->inSort(d->localName(),toClassDef(d)); } } -Definition *ClassDefImpl::findInnerCompound(const char *name) const +const Definition *ClassDefImpl::findInnerCompound(const char *name) const { - Definition *result=0; + const Definition *result=0; if (name==0) return 0; if (m_impl->innerClasses) { @@ -4101,7 +4073,7 @@ ClassDef *ClassDefImpl::insertTemplateInstance(const QCString &fileName, { m_impl->templateInstances = new QDict<ClassDef>(17); } - ClassDef *templateClass=m_impl->templateInstances->find(templSpec); + ClassDefMutable *templateClass=toClassDefMutable(m_impl->templateInstances->find(templSpec)); if (templateClass==0) { Debug::print(Debug::Classes,0," New template instance class '%s''%s'\n",qPrint(name()),qPrint(templSpec)); @@ -4124,7 +4096,7 @@ ClassDef *ClassDefImpl::getVariableInstance(const char *templSpec) const m_impl->variableInstances = new QDict<ClassDef>(17); m_impl->variableInstances->setAutoDelete(TRUE); } - ClassDef *templateClass=m_impl->variableInstances->find(templSpec); + ClassDefMutable *templateClass=toClassDefMutable(m_impl->variableInstances->find(templSpec)); if (templateClass==0) { Debug::print(Debug::Classes,0," New template variable instance class '%s' '%s'\n",qPrint(name()),qPrint(templSpec)); @@ -4171,7 +4143,7 @@ void ClassDefImpl::addMembersToTemplateInstance(const ClassDef *cd,const char *t { auto actualArguments_p = stringToArgumentList(getLanguage(),templSpec); MemberDef *md = mi->memberDef(); - std::unique_ptr<MemberDef> imd { md->createTemplateInstanceMember( + std::unique_ptr<MemberDefMutable> imd { md->createTemplateInstanceMember( cd->templateArguments(),actualArguments_p) }; //printf("%s->setMemberClass(%p)\n",imd->name().data(),this); imd->setMemberClass(this); @@ -4201,7 +4173,7 @@ QCString ClassDefImpl::getReference() const } else { - return DefinitionImpl::getReference(); + return DefinitionMixin::getReference(); } } @@ -4213,7 +4185,7 @@ bool ClassDefImpl::isReference() const } else { - return DefinitionImpl::isReference(); + return DefinitionMixin::isReference(); } } @@ -4223,7 +4195,7 @@ ArgumentLists ClassDefImpl::getTemplateParameterLists() const Definition *d=getOuterScope(); while (d && d->definitionType()==Definition::TypeClass) { - result.insert(result.begin(),dynamic_cast<ClassDef*>(d)->templateArguments()); + result.insert(result.begin(),toClassDef(d)->templateArguments()); d = d->getOuterScope(); } if (!templateArguments().empty()) @@ -4236,59 +4208,7 @@ ArgumentLists ClassDefImpl::getTemplateParameterLists() const QCString ClassDefImpl::qualifiedNameWithTemplateParameters( const ArgumentLists *actualParams,uint *actualParamIndex) const { - //static bool optimizeOutputJava = Config_getBool(OPTIMIZE_OUTPUT_JAVA); - static bool hideScopeNames = Config_getBool(HIDE_SCOPE_NAMES); - //printf("qualifiedNameWithTemplateParameters() localName=%s\n",localName().data()); - QCString scName; - Definition *d=getOuterScope(); - if (d) - { - if (d->definitionType()==Definition::TypeClass) - { - ClassDef *cd=dynamic_cast<ClassDef *>(d); - scName = cd->qualifiedNameWithTemplateParameters(actualParams,actualParamIndex); - } - else if (!hideScopeNames) - { - scName = d->qualifiedName(); - } - } - - SrcLangExt lang = getLanguage(); - QCString scopeSeparator = getLanguageSpecificSeparator(lang); - if (!scName.isEmpty()) scName+=scopeSeparator; - - bool isSpecialization = localName().find('<')!=-1; - - QCString clName = className(); - //bool isGeneric = getLanguage()==SrcLangExt_CSharp; - //if (isGeneric && clName.right(2)=="-g") - //{ - // clName = clName.left(clName.length()-2); - //} - //printf("m_impl->lang=%d clName=%s isSpecialization=%d\n",getLanguage(),clName.data(),isSpecialization); - scName+=clName; - if (!templateArguments().empty()) - { - if (actualParams && *actualParamIndex<actualParams->size()) - { - const ArgumentList &al = actualParams->at(*actualParamIndex); - if (!isSpecialization) - { - scName+=tempArgListToString(al,lang); - } - (*actualParamIndex)++; - } - else - { - if (!isSpecialization) - { - scName+=tempArgListToString(templateArguments(),lang); - } - } - } - //printf("qualifiedNameWithTemplateParameters: scope=%s qualifiedName=%s\n",name().data(),scName.data()); - return scName; + return makeQualifiedNameWithTemplateParameters(this,actualParams,actualParamIndex); } QCString ClassDefImpl::className() const @@ -4416,7 +4336,14 @@ void ClassDefImpl::addMemberToList(MemberListType lt,MemberDef *md,bool isBrief) ml->append(md); // for members in the declaration lists we set the section, needed for member grouping - if ((ml->listType()&MemberListType_detailedLists)==0) md->setSectionList(this,ml); + if ((ml->listType()&MemberListType_detailedLists)==0) + { + MemberDefMutable *mdm = toMemberDefMutable(md); + if (mdm) + { + mdm->setSectionList(this,ml); + } + } } void ClassDefImpl::sortMemberLists() @@ -4536,26 +4463,21 @@ int ClassDefImpl::countInheritedDecMembers(MemberListType lt, // name().data(),lt,process,count,invert); if ((process^invert) || showAlways) { - if (m_impl->inherits) + for (const auto &ibcd : m_impl->inherits) { - BaseClassListIterator it(*m_impl->inherits); - BaseClassDef *ibcd; - for (it.toFirst();(ibcd=it.current());++it) + ClassDefMutable *icd=toClassDefMutable(ibcd.classDef); + int lt1,lt2; + if (icd && icd->isLinkable()) { - ClassDef *icd=ibcd->classDef; - int lt1,lt2; - if (icd->isLinkable()) + convertProtectionLevel(lt,ibcd.prot,<1,<2); + //printf("%s: convert %d->(%d,%d) prot=%d\n", + // icd->name().data(),lt,lt1,lt2,ibcd->prot); + if (visitedClasses->find(icd)==0) { - convertProtectionLevel(lt,ibcd->prot,<1,<2); - //printf("%s: convert %d->(%d,%d) prot=%d\n", - // icd->name().data(),lt,lt1,lt2,ibcd->prot); - if (visitedClasses->find(icd)==0) + visitedClasses->insert(icd,icd); // guard for multiple virtual inheritance + if (lt1!=-1) { - visitedClasses->insert(icd,icd); // guard for multiple virtual inheritance - if (lt1!=-1) - { - inhCount+=icd->countMemberDeclarations((MemberListType)lt1,inheritedFrom,lt2,FALSE,TRUE,visitedClasses); - } + inhCount+=icd->countMemberDeclarations((MemberListType)lt1,inheritedFrom,lt2,FALSE,TRUE,visitedClasses); } } } @@ -4677,36 +4599,31 @@ void ClassDefImpl::writeInheritedMemberDeclarations(OutputList &ol, // name().data(),lt,process,invert,showAlways); if ((process^invert) || showAlways) { - if (m_impl->inherits) + for (const auto &ibcd : m_impl->inherits) { - BaseClassListIterator it(*m_impl->inherits); - BaseClassDef *ibcd; - for (it.toFirst();(ibcd=it.current());++it) + ClassDefMutable *icd=toClassDefMutable(ibcd.classDef); + if (icd && icd->isLinkable()) { - ClassDef *icd=ibcd->classDef; - if (icd->isLinkable()) + int lt1,lt3; + convertProtectionLevel(lt,ibcd.prot,<1,<3); + if (lt2==-1 && lt3!=-1) { - int lt1,lt3; - convertProtectionLevel(lt,ibcd->prot,<1,<3); - if (lt2==-1 && lt3!=-1) - { - lt2=lt3; - } - //printf("%s:convert %d->(%d,%d) prot=%d\n",icd->name().data(),lt,lt1,lt2,ibcd->prot); - if (visitedClasses->find(icd)==0) - { - visitedClasses->insert(icd,icd); // guard for multiple virtual inheritance - if (lt1!=-1) - { - icd->writeMemberDeclarations(ol,(MemberListType)lt1, - title,QCString(),FALSE,inheritedFrom,lt2,FALSE,TRUE,visitedClasses); - } - } - else + lt2=lt3; + } + //printf("%s:convert %d->(%d,%d) prot=%d\n",icd->name().data(),lt,lt1,lt2,ibcd->prot); + if (visitedClasses->find(icd)==0) + { + visitedClasses->insert(icd,icd); // guard for multiple virtual inheritance + if (lt1!=-1) { - //printf("%s: class already visited!\n",icd->name().data()); + icd->writeMemberDeclarations(ol,(MemberListType)lt1, + title,QCString(),FALSE,inheritedFrom,lt2,FALSE,TRUE,visitedClasses); } } + else + { + //printf("%s: class already visited!\n",icd->name().data()); + } } } } @@ -4821,16 +4738,26 @@ ClassDefImpl::CompoundType ClassDefImpl::compoundType() const return m_impl->compType; } -BaseClassList *ClassDefImpl::baseClasses() const +BaseClassList ClassDefImpl::baseClasses() const { return m_impl->inherits; } -BaseClassList *ClassDefImpl::subClasses() const +void ClassDefImpl::updateBaseClasses(const BaseClassList &bcd) +{ + m_impl->inherits = bcd; +} + +BaseClassList ClassDefImpl::subClasses() const { return m_impl->inheritedBy; } +void ClassDefImpl::updateSubClasses(const BaseClassList &bcd) +{ + m_impl->inheritedBy = bcd; +} + const MemberNameInfoLinkedMap &ClassDefImpl::memberNameInfoLinkedMap() const { return m_impl->allMemberNameInfoLinkedMap; @@ -5036,7 +4963,7 @@ MemberDef *ClassDefImpl::isSmartPointer() const return m_impl->arrowOperator; } -void ClassDefImpl::reclassifyMember(MemberDef *md,MemberType t) +void ClassDefImpl::reclassifyMember(MemberDefMutable *md,MemberType t) { md->setMemberType(t); QListIterator<MemberList> mli(m_impl->memberLists); @@ -5186,7 +5113,7 @@ bool ClassDefImpl::isSliceLocal() const void ClassDefImpl::setName(const char *name) { - DefinitionImpl::setName(name); + DefinitionMixin::setName(name); } void ClassDefImpl::setMetaData(const char *md) @@ -5204,3 +5131,67 @@ QCString ClassDefImpl::inheritanceGraphFileName() const return m_impl->inheritFileName; } +// --- Cast functions +// +ClassDef *toClassDef(Definition *d) +{ + if (d && (typeid(*d)==typeid(ClassDefImpl) || typeid(*d)==typeid(ClassDefAliasImpl))) + { + return static_cast<ClassDef*>(d); + } + else + { + return 0; + } +} + +ClassDef *toClassDef(DefinitionMutable *md) +{ + Definition *d = toDefinition(md); + if (d && typeid(*d)==typeid(ClassDefImpl)) + { + return static_cast<ClassDef*>(d); + } + else + { + return 0; + } +} + +const ClassDef *toClassDef(const Definition *d) +{ + if (d && (typeid(*d)==typeid(ClassDefImpl) || typeid(*d)==typeid(ClassDefAliasImpl))) + { + return static_cast<const ClassDef*>(d); + } + else + { + return 0; + } +} + +ClassDefMutable *toClassDefMutable(Definition *d) +{ + if (d && typeid(*d)==typeid(ClassDefImpl)) + { + return static_cast<ClassDefMutable*>(d); + } + else + { + return 0; + } +} + +ClassDefMutable *toClassDefMutable(const Definition *d) +{ + if (d && typeid(*d)==typeid(ClassDefImpl)) + { + return const_cast<ClassDefMutable*>(static_cast<const ClassDefMutable*>(d)); + } + else + { + return 0; + } +} + + diff --git a/src/classdef.h b/src/classdef.h index d413794..54664e5 100644 --- a/src/classdef.h +++ b/src/classdef.h @@ -19,6 +19,7 @@ #define CLASSDEF_H #include <vector> +#include <set> #include <qlist.h> #include <qdict.h> @@ -30,6 +31,7 @@ struct Argument; class MemberDef; +class MemberDefMutable; class MemberList; class MemberDict; class ClassList; @@ -37,7 +39,6 @@ class ClassSDict; class OutputList; class FileDef; class FileList; -class BaseClassList; class NamespaceDef; class MemberDef; class ExampleSDict; @@ -52,13 +53,46 @@ class StringDict; struct IncludeInfo; class ClassDefImpl; class FTextStream; +class ClassDef; +class ClassDefMutable; + +/** Class that contains information about an inheritance relation. + */ +struct BaseClassDef +{ + BaseClassDef(ClassDef *cd,const char *n,Protection p, Specifier v,const char *t) : + classDef(cd), usedName(n), prot(p), virt(v), templSpecifiers(t) {} + + /** Class definition that this relation inherits from. */ + ClassDef *classDef; + + /** name used in the inheritance list + * (may be a typedef name instead of the class name) + */ + QCString usedName; + + /** Protection level of the inheritance relation: + * Public, Protected, or Private + */ + Protection prot; + + /** Virtualness of the inheritance relation: + * Normal, or Virtual + */ + Specifier virt; + + /** Template arguments used for the base class */ + QCString templSpecifiers; +}; + +using BaseClassList = std::vector<BaseClassDef>; /** A abstract class representing of a compound symbol. * * A compound can be a class, struct, union, interface, service, singleton, * or exception. */ -class ClassDef : virtual public Definition +class ClassDef : public Definition { public: /** The various compound types */ @@ -75,7 +109,6 @@ class ClassDef : virtual public Definition virtual ~ClassDef() {} - //----------------------------------------------------------------------------------- // --- getters //----------------------------------------------------------------------------------- @@ -126,11 +159,17 @@ class ClassDef : virtual public Definition /** Returns the list of base classes from which this class directly * inherits. */ - virtual BaseClassList *baseClasses() const = 0; + virtual BaseClassList baseClasses() const = 0; + + /** Update the list of base classes to the one passed */ + virtual void updateBaseClasses(const BaseClassList &bcd) = 0; /** Returns the list of sub classes that directly derive from this class */ - virtual BaseClassList *subClasses() const = 0; + virtual BaseClassList subClasses() const = 0; + + /** Update the list of sub classes to the one passed */ + virtual void updateSubClasses(const BaseClassList &bcd) = 0; /** Returns a dictionary of all members. This includes any inherited * members. Members are sorted alphabetically. @@ -221,7 +260,7 @@ class ClassDef : virtual public Definition * available, or 0 otherwise. * @param name The name of the nested compound */ - virtual Definition *findInnerCompound(const char *name) const = 0; + virtual const Definition *findInnerCompound(const char *name) const = 0; /** Returns the template parameter lists that form the template * declaration of this class. @@ -319,6 +358,30 @@ class ClassDef : virtual public Definition virtual bool hasNonReferenceSuperClass() 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; + + //----------------------------------------------------------------------------------- + // --- helpers ---- + //----------------------------------------------------------------------------------- + + virtual ClassDef *insertTemplateInstance(const QCString &fileName,int startLine,int startColumn, + const QCString &templSpec,bool &freshInstance) const = 0; + virtual void writeDeclarationLink(OutputList &ol,bool &found, + const char *header,bool localNames) const = 0; + +}; + +class ClassDefMutable : public DefinitionMutable, public ClassDef +{ + public: + //----------------------------------------------------------------------------------- // --- setters ---- //----------------------------------------------------------------------------------- @@ -354,8 +417,6 @@ class ClassDef : virtual public Definition 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; @@ -368,7 +429,7 @@ class ClassDef : virtual public Definition virtual void mergeMembers() = 0; virtual void sortMemberLists() = 0; virtual void distributeMemberGroupDocumentation() = 0; - virtual void reclassifyMember(MemberDef *md,MemberType t) = 0; + virtual void reclassifyMember(MemberDefMutable *md,MemberType t) = 0; virtual void removeMemberFromLists(MemberDef *md) = 0; virtual void setAnonymousEnumType() = 0; virtual void countMembers() = 0; @@ -387,8 +448,6 @@ class ClassDef : virtual public Definition 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,const ClassDef *inheritedFrom=0, @@ -397,27 +456,11 @@ class ClassDef : virtual public Definition 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 */ -ClassDef *createClassDef( +ClassDefMutable *createClassDef( const char *fileName,int startLine,int startColumn, const char *name,ClassDef::CompoundType ct, const char *ref=0,const char *fName=0, @@ -425,6 +468,17 @@ ClassDef *createClassDef( ClassDef *createClassDefAlias(const Definition *newScope,const ClassDef *cd); +// --- Set of classes + +using ClassDefSet = std::set<const ClassDef*>; + +// --- Cast functions + +ClassDef *toClassDef(Definition *d); +ClassDef *toClassDef(DefinitionMutable *d); +const ClassDef *toClassDef(const Definition *d); +ClassDefMutable *toClassDefMutable(Definition *d); +ClassDefMutable *toClassDefMutable(const Definition *d); //------------------------------------------------------------------------ @@ -480,65 +534,6 @@ class UsesClassDictIterator : public QDictIterator<UsesClassDef> //------------------------------------------------------------------------ -/** Class that contains information about an inheritance relation. - */ -struct BaseClassDef -{ - BaseClassDef(ClassDef *cd,const char *n,Protection p, Specifier v,const char *t) : - classDef(cd), usedName(n), prot(p), virt(v), templSpecifiers(t) {} - - /** Class definition that this relation inherits from. */ - ClassDef *classDef; - - /** name used in the inheritance list - * (may be a typedef name instead of the class name) - */ - QCString usedName; - - /** Protection level of the inheritance relation: - * Public, Protected, or Private - */ - Protection prot; - - /** Virtualness of the inheritance relation: - * Normal, or Virtual - */ - Specifier virt; - - /** Template arguments used for the base class */ - QCString templSpecifiers; -}; - -/** List of base classes. - * - * The classes are alphabetically sorted on name if inSort() is used. - */ -class BaseClassList : public QList<BaseClassDef> -{ - public: - ~BaseClassList() {} - int compareValues(const BaseClassDef *item1,const BaseClassDef *item2) const - { - const ClassDef *c1=item1->classDef; - const ClassDef *c2=item2->classDef; - if (c1==0 || c2==0) - return FALSE; - else - return qstricmp(c1->name(),c2->name()); - } -}; - -/** Iterator for a list of base classes. - */ -class BaseClassListIterator : public QListIterator<BaseClassDef> -{ - public: - BaseClassListIterator(const BaseClassList &bcl) : - QListIterator<BaseClassDef>(bcl) {} -}; - -//------------------------------------------------------------------------ - /** Class that contains information about a type constraint relations. */ diff --git a/src/classlist.cpp b/src/classlist.cpp index ee4ffa4..d0f37ce 100644 --- a/src/classlist.cpp +++ b/src/classlist.cpp @@ -154,7 +154,11 @@ void ClassSDict::writeDocumentation(OutputList &ol,const Definition * container) ol.endGroupHeader(); found=TRUE; } - cd->writeInlineDocumentation(ol); + ClassDefMutable *cdm = toClassDefMutable(cd); + if (cdm) + { + cdm->writeInlineDocumentation(ol); + } } } } @@ -1,12 +1,10 @@ /****************************************************************************** * - * - * - * Copyright (C) 1997-2015 by Dimitri van Heesch. + * Copyright (C) 1997-2020 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. * @@ -25,18 +23,23 @@ %{ /* - * includes + * includes */ +#include <utility> #include <memory> #include <algorithm> +#include <unordered_map> +#include <stack> +#include <vector> +#include <string> +#include <mutex> #include <stdio.h> #include <assert.h> #include <ctype.h> #include <qregexp.h> #include <qdir.h> -#include <qstack.h> #include "code.h" #include "entry.h" @@ -54,6 +57,8 @@ #include "filename.h" #include "namespacedef.h" #include "tooltip.h" +#include "scopedtypevariant.h" +#include "symbolresolver.h" // Toggle for some debugging info //#define DBG_CTX(x) fprintf x @@ -61,16 +66,12 @@ #define YY_NO_UNISTD_H 1 -#define CLASSBLOCK (int *)4 -#define SCOPEBLOCK (int *)8 -#define INNERBLOCK (int *)12 +#define CLASSBLOCK 1 +#define SCOPEBLOCK 2 +#define INNERBLOCK 3 #define USE_STATE2STRING 0 -/* ----------------------------------------------------------------- - * statics - */ - // context for an Objective-C method call struct ObjCCallCtx { @@ -86,144 +87,11 @@ struct ObjCCallCtx int braceCount; }; -/*! Represents a stack of variable to class mappings as found in the - * code. Each scope is enclosed in pushScope() and popScope() calls. - * Variables are added by calling addVariables() and one can search - * for variable using findVariable(). - */ -class VariableContext -{ - public: - static const ClassDef *dummyContext; - - class Scope : public SDict<ClassDef> - { - public: - Scope() : SDict<ClassDef>(17) {} - }; - - VariableContext() - { - m_scopes.setAutoDelete(TRUE); - } - virtual ~VariableContext() - { - } - - void pushScope() - { - m_scopes.append(new Scope); - DBG_CTX((stderr,"** Push var context %d\n",m_scopes.count())); - } - - void popScope() - { - if (m_scopes.count()>0) - { - DBG_CTX((stderr,"** Pop var context %d\n",m_scopes.count())); - m_scopes.remove(m_scopes.count()-1); - } - else - { - DBG_CTX((stderr,"** ILLEGAL: Pop var context\n")); - } - } - - void clear() - { - m_scopes.clear(); - m_globalScope.clear(); - } - - void clearExceptGlobal() - { - DBG_CTX((stderr,"** Clear var context\n")); - m_scopes.clear(); - } - - void addVariable(yyscan_t yyscanner,const QCString &type,const QCString &name); - ClassDef *findVariable(const QCString &name); - - uint count() const { return m_scopes.count(); } - - private: - Scope m_globalScope; - QList<Scope> m_scopes; -}; - -//------------------------------------------------------------------- - -class CallContext -{ - public: - struct Ctx - { - Ctx(QCString _name, QCString _type) : name(_name), type(_type), d(0) {} - QCString name; - QCString type; - const Definition *d; - }; - - CallContext() - { - m_defList.append(new Ctx("","")); - m_defList.setAutoDelete(TRUE); - } - virtual ~CallContext() {} - void setScope(const Definition *d) - { - Ctx *ctx = m_defList.getLast(); - if (ctx) - { - DBG_CTX((stderr,"** Set call context %s (%p)\n",d==0 ? "<null>" : d->name().data(),d)); - ctx->d=d; - } - } - void pushScope(QCString _name, QCString _type) - { - m_defList.append(new Ctx(_name,_type)); - DBG_CTX((stderr,"** Push call context %d\n",m_defList.count())); - } - void popScope(QCString &_name, QCString &_type) - { - if (m_defList.count()>1) - { - DBG_CTX((stderr,"** Pop call context %d\n",m_defList.count())); - Ctx *ctx = m_defList.getLast(); - if (ctx) - { - _name = ctx->name; - _type = ctx->type; - } - m_defList.removeLast(); - } - else - { - DBG_CTX((stderr,"** ILLEGAL: Pop call context\n")); - } - } - void clear() - { - DBG_CTX((stderr,"** Clear call context\n")); - m_defList.clear(); - m_defList.append(new Ctx("","")); - } - const Definition *getScope() const - { - Ctx *ctx = m_defList.getLast(); - if (ctx) return ctx->d; else return 0; - } - - private: - QList<Ctx> m_defList; -}; - - struct codeYY_state { CodeOutputInterface * code = 0; - ClassSDict *codeClassSDict = 0; + std::unordered_map< std::string, ScopedTypeVariant > codeClassMap; QCString curClassName; QStrList curClassBases; @@ -231,10 +99,10 @@ struct codeYY_state QCString parmName; const char * inputString = 0; //!< the code fragment as text - yy_size_t inputPosition = 0; //!< read offset during parsing + yy_size_t inputPosition = 0; //!< read offset during parsing int inputLines = 0; //!< number of line in the code fragment - int yyLineNr = 0; //!< current line number - int yyColNr = 0; //!< current column number + int yyLineNr = 0; //!< current line number + yy_size_t yyColNr = 0; //!< current column number bool needsTermination = FALSE; bool exampleBlock = FALSE; @@ -247,12 +115,12 @@ struct codeYY_state QCString args; QCString classScope; QCString realScope; - QStack<int> scopeStack; //!< 1 if bracket starts a scope, - // 2 for internal blocks + std::stack<int> scopeStack; //!< 1 if bracket starts a scope, + // 2 for internal blocks int anchorCount = 0; FileDef * sourceFileDef = 0; bool lineNumbers = FALSE; - Definition * currentDefinition = 0; + const Definition * currentDefinition = 0; MemberDef * currentMemberDef = 0; bool includeCodeFragment = FALSE; const char * currentFontClass = 0; @@ -263,20 +131,20 @@ struct codeYY_state QCString saveType; QCString delimiter; - int bracketCount = 0; - int curlyCount = 0; - int sharpCount = 0; + int bracketCount = 0; + int curlyCount = 0; + int sharpCount = 0; bool inFunctionTryBlock = FALSE; bool inForEachExpression = FALSE; int lastTemplCastContext = 0; - int lastSpecialCContext = 0; + int lastSpecialCContext = 0; int lastStringContext = 0; int lastSkipCppContext = 0; int lastVerbStringContext = 0; int lastObjCCallContext = 0; int memCallContext = 0; - int lastCContext = 0; + int lastCContext = 0; int skipInlineInitContext = 0; SrcLangExt lang = SrcLangExt_Unknown; @@ -285,9 +153,9 @@ struct codeYY_state bool lexInit = FALSE; - QStack<int> classScopeLengthStack; + std::stack<int> classScopeLengthStack; - int prefixed_with_this_keyword = FALSE; + int isPrefixedWithThis = FALSE; const Definition *searchCtx = 0; bool collectXRefs = FALSE; @@ -297,17 +165,17 @@ struct codeYY_state int currentObjId=0; int currentWordId=0; int currentCommentId=0; - QStack<ObjCCallCtx> contextStack; - QIntDict<ObjCCallCtx> contextDict; - QIntDict<QCString> nameDict; - QIntDict<QCString> objectDict; - QIntDict<QCString> wordDict; - QIntDict<QCString> commentDict; + std::stack<ObjCCallCtx*> contextStack; + std::unordered_map< int,std::unique_ptr<ObjCCallCtx> > contextMap; + std::unordered_map< int, QCString> nameMap; + std::unordered_map< int, QCString> objectMap; + std::unordered_map< int, QCString> wordMap; + std::unordered_map< int, QCString> commentMap; int braceCount=0; - QCString forceTagReference; VariableContext theVarContext; CallContext theCallContext; + SymbolResolver symbolResolver; }; static bool isCastKeyword(const QCString &s); @@ -331,6 +199,7 @@ static void nextCodeLine(yyscan_t yyscanner); static void startFontClass(yyscan_t yyscanner,const char *s); static void endFontClass(yyscan_t yyscanner); static void codifyLines(yyscan_t yyscanner,const char *text); +static void incrementFlowKeyWordCount(yyscan_t yyscanner); static void writeMultiLineCodeLink(yyscan_t yyscanner,CodeOutputInterface &ol, const Definition *d, const char *text); @@ -338,21 +207,21 @@ static void addType(yyscan_t yyscanner); static void addParmType(yyscan_t yyscanner); static void addUsingDirective(yyscan_t yyscanner,const char *name); static void setParameterList(yyscan_t yyscanner,const MemberDef *md); -static const ClassDef *stripClassName(yyscan_t yyscanner,const char *s,Definition *d); -static MemberDef *setCallContextForVar(yyscan_t yyscanner,const QCString &name); +static const ClassDef *stripClassName(yyscan_t yyscanner,const char *s,const Definition *d); +static const MemberDef *setCallContextForVar(yyscan_t yyscanner,const QCString &name); static void updateCallContextForSmartPointer(yyscan_t yyscanner); static bool getLinkInScope(yyscan_t yyscanner,const QCString &c, // scope const QCString &m, // member - const char *memberText, // exact text - CodeOutputInterface &ol, - const char *text, - bool varOnly=FALSE - ); + const char *memberText, // exact text + CodeOutputInterface &ol, + const char *text, + bool varOnly=FALSE + ); static bool getLink(yyscan_t yyscanner,const char *className, const char *memberName, - CodeOutputInterface &ol, - const char *text=0, - bool varOnly=FALSE); + CodeOutputInterface &ol, + const char *text=0, + bool varOnly=FALSE); static void generateClassOrGlobalLink(yyscan_t yyscanner,CodeOutputInterface &ol,const char *clName, bool typeOnly=FALSE,bool varOnly=FALSE); static bool generateClassMemberLink(yyscan_t yyscanner,CodeOutputInterface &ol,MemberDef *xmd,const char *memName); @@ -369,19 +238,26 @@ static QCString escapeWord(yyscan_t yyscanner,const char *s); static QCString escapeComment(yyscan_t yyscanner,const char *s); static bool skipLanguageSpecificKeyword(yyscan_t yyscanner,const QCString &kw); static yy_size_t yyread(yyscan_t yyscanner,char *buf,yy_size_t max_size); +static void addVariable(yyscan_t yyscanner,QCString type,QCString name); +//------------------------------------------------------------------- + +static std::mutex g_searchIndexMutex; +static std::mutex g_docCrossReferenceMutex; +static std::mutex g_addExampleMutex; +static std::mutex g_countFlowKeywordsMutex; /* ----------------------------------------------------------------- */ -#undef YY_INPUT -#define YY_INPUT(buf,result,max_size) result=yyread(yyscanner,buf,max_size); +#undef YY_INPUT +#define YY_INPUT(buf,result,max_size) result=yyread(yyscanner,buf,max_size); %} B [ \t] BN [ \t\n\r] -ID "$"?[a-z_A-Z\x80-\xFF][a-z_A-Z0-9\x80-\xFF]* +ID "$"?[a-z_A-Z\x80-\xFF][a-z_A-Z0-9\x80-\xFF]* SEP ("::"|"\\") SCOPENAME ({SEP}{BN}*)?({ID}{BN}*{SEP}{BN}*)*("~"{BN}*)?{ID} TEMPLIST "<"[^\"\}\{\(\)\/\n\>]*">" @@ -436,12 +312,12 @@ NUMBER {INTEGER_NUMBER}|{FLOAT_NUMBER} %x SkipString %x SkipStringS %x SkipVerbString -%x SkipCPP -%x SkipComment -%x SkipCxxComment -%x RemoveSpecialCComment -%x StripSpecialCComment -%x Body +%x SkipCPP +%x SkipComment +%x SkipCxxComment +%x RemoveSpecialCComment +%x StripSpecialCComment +%x Body %x FuncCall %x MemberCall %x MemberCall2 @@ -451,22 +327,22 @@ NUMBER {INTEGER_NUMBER}|{FLOAT_NUMBER} %x AlignAsEnd %x PackageName %x ClassVar -%x CppCliTypeModifierFollowup +%x CppCliTypeModifierFollowup %x Bases %x SkipSharp %x ReadInclude %x TemplDecl %x TemplCast -%x CallEnd +%x CallEnd %x ObjCMethod -%x ObjCParams -%x ObjCParamType +%x ObjCParams +%x ObjCParamType %x ObjCCall %x ObjCMName %x ObjCSkipStr %x ObjCCallComment %x OldStyleArgs -%x UsingName +%x UsingName %x RawString %x InlineInit @@ -474,486 +350,493 @@ NUMBER {INTEGER_NUMBER}|{FLOAT_NUMBER} <*>\x0d <Body>^([ \t]*"#"[ \t]*("include"|"import")[ \t]*)("<"|"\"") { - startFontClass(yyscanner,"preprocessor"); - yyextra->code->codify(yytext); - BEGIN( ReadInclude ); - } -<Body>("@interface"|"@implementation"|"@protocol")[ \t\n]+ { + startFontClass(yyscanner,"preprocessor"); + yyextra->code->codify(yytext); + BEGIN( ReadInclude ); + } +<Body>("@interface"|"@implementation"|"@protocol")[ \t\n]+ { yyextra->insideObjC=TRUE; - startFontClass(yyscanner,"keyword"); - codifyLines(yyscanner,yytext); - endFontClass(yyscanner); - if (!yyextra->insideTemplate) - BEGIN( ClassName ); - } + startFontClass(yyscanner,"keyword"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + if (!yyextra->insideTemplate) + BEGIN( ClassName ); + } <Body>(("public"|"private"){B}+)?("ref"|"value"|"interface"|"enum"){B}+("class"|"struct") { - if (yyextra->insideTemplate) REJECT; - startFontClass(yyscanner,"keyword"); - codifyLines(yyscanner,yytext); - endFontClass(yyscanner); - BEGIN( ClassName ); - } -<Body>"property"|"event"/{BN}* { - if (yyextra->insideTemplate) REJECT; - startFontClass(yyscanner,"keyword"); - codifyLines(yyscanner,yytext); - endFontClass(yyscanner); - } -<Body>(KEYWORD_CPPCLI_DATATYPE|("partial"{B}+)?"class"|"struct"|"union"|"namespace"|"interface"){B}+ { - startFontClass(yyscanner,"keyword"); - codifyLines(yyscanner,yytext); - endFontClass(yyscanner); - if (!yyextra->insideTemplate) - BEGIN( ClassName ); - } -<Body>("package")[ \t\n]+ { - startFontClass(yyscanner,"keyword"); - codifyLines(yyscanner,yytext); - endFontClass(yyscanner); - BEGIN( PackageName ); - } -<ClassVar>\n { - if (!yyextra->insideObjC) REJECT; - codifyLines(yyscanner,yytext); - BEGIN(Body); - } -<Body,ClassVar,Bases>"-"|"+" { - if (!yyextra->insideObjC || yyextra->insideBody) - { - yyextra->code->codify(yytext); - } - else // Start of Objective-C method - { - //printf("Method!\n"); - yyextra->code->codify(yytext); - BEGIN(ObjCMethod); - } - } -<ObjCMethod>":" { - yyextra->code->codify(yytext); - BEGIN(ObjCParams); - } -<ObjCParams>"(" { - yyextra->code->codify(yytext); - BEGIN(ObjCParamType); - } -<ObjCParams,ObjCMethod>";"|"{" { - yyextra->code->codify(yytext); - if (*yytext=='{') - { - if (yyextra->searchingForBody) - { - yyextra->searchingForBody=FALSE; - yyextra->insideBody=TRUE; - } - if (yyextra->insideBody) yyextra->bodyCurlyCount++; - if (!yyextra->curClassName.isEmpty()) // valid class name - { - pushScope(yyscanner,yyextra->curClassName); + if (yyextra->insideTemplate) REJECT; + startFontClass(yyscanner,"keyword"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + BEGIN( ClassName ); + } +<Body>"property"|"event"/{BN}* { + if (yyextra->insideTemplate) REJECT; + startFontClass(yyscanner,"keyword"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + } +<Body>(KEYWORD_CPPCLI_DATATYPE|("partial"{B}+)?"class"|"struct"|"union"|"namespace"|"interface"){B}+ { + startFontClass(yyscanner,"keyword"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + if (!yyextra->insideTemplate) + BEGIN( ClassName ); + } +<Body>("package")[ \t\n]+ { + startFontClass(yyscanner,"keyword"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + BEGIN( PackageName ); + } +<ClassVar>\n { + if (!yyextra->insideObjC) REJECT; + codifyLines(yyscanner,yytext); + BEGIN(Body); + } +<Body,ClassVar,Bases>"-"|"+" { + if (!yyextra->insideObjC || yyextra->insideBody) + { + yyextra->code->codify(yytext); + } + else // Start of Objective-C method + { + //printf("Method!\n"); + yyextra->code->codify(yytext); + BEGIN(ObjCMethod); + } + } +<ObjCMethod>":" { + yyextra->code->codify(yytext); + BEGIN(ObjCParams); + } +<ObjCParams>"(" { + yyextra->code->codify(yytext); + BEGIN(ObjCParamType); + } +<ObjCParams,ObjCMethod>";"|"{" { + yyextra->code->codify(yytext); + if (*yytext=='{') + { + if (yyextra->searchingForBody) + { + yyextra->searchingForBody=FALSE; + yyextra->insideBody=TRUE; + } + if (yyextra->insideBody) yyextra->bodyCurlyCount++; + if (!yyextra->curClassName.isEmpty()) // valid class name + { + pushScope(yyscanner,yyextra->curClassName); DBG_CTX((stderr,"** scope stack push SCOPEBLOCK\n")); - yyextra->scopeStack.push(SCOPEBLOCK); - } - } + yyextra->scopeStack.push(SCOPEBLOCK); + } + } yyextra->type.resize(0); yyextra->name.resize(0); - BEGIN(Body); - } -<ObjCParams>{ID}{B}*":" { - yyextra->code->codify(yytext); - } -<ObjCParamType>{TYPEKW} { - startFontClass(yyscanner,"keywordtype"); - yyextra->code->codify(yytext); - endFontClass(yyscanner); - yyextra->parmType=yytext; - } -<ObjCParamType>{ID} { - generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext); - yyextra->parmType=yytext; - } -<ObjCParamType>")" { - yyextra->code->codify(yytext); - BEGIN(ObjCParams); - } -<ObjCParams>{ID} { - yyextra->code->codify(yytext); - yyextra->parmName=yytext; - yyextra->theVarContext.addVariable(yyscanner,yyextra->parmType,yyextra->parmName); - yyextra->parmType.resize(0);yyextra->parmName.resize(0); - } + BEGIN(Body); + } +<ObjCParams>{ID}{B}*":" { + yyextra->code->codify(yytext); + } +<ObjCParamType>{TYPEKW} { + startFontClass(yyscanner,"keywordtype"); + yyextra->code->codify(yytext); + endFontClass(yyscanner); + yyextra->parmType=yytext; + } +<ObjCParamType>{ID} { + generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext); + yyextra->parmType=yytext; + } +<ObjCParamType>")" { + yyextra->code->codify(yytext); + BEGIN(ObjCParams); + } +<ObjCParams>{ID} { + yyextra->code->codify(yytext); + yyextra->parmName=yytext; + addVariable(yyscanner,yyextra->parmType,yyextra->parmName); + yyextra->parmType.resize(0);yyextra->parmName.resize(0); + } <ObjCMethod,ObjCParams,ObjCParamType>{ID} { - generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext); - } -<ObjCMethod,ObjCParams,ObjCParamType>. { - yyextra->code->codify(yytext); - } -<ObjCMethod,ObjCParams,ObjCParamType>\n { - codifyLines(yyscanner,yytext); - } -<ReadInclude>[^\n\"\>]+/(">"|"\"") { - //FileInfo *f; - bool ambig; - bool found=FALSE; - //QCString absPath = yytext; - //if (yyextra->sourceFileDef && QDir::isRelativePath(absPath)) - //{ - // absPath = QDir::cleanDirPath(yyextra->sourceFileDef->getPath()+"/"+absPath); - //} + generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext); + } +<ObjCMethod,ObjCParams,ObjCParamType>. { + yyextra->code->codify(yytext); + } +<ObjCMethod,ObjCParams,ObjCParamType>\n { + codifyLines(yyscanner,yytext); + } +<ReadInclude>[^\n\"\>]+/(">"|"\"") { + //FileInfo *f; + bool ambig; + bool found=FALSE; const FileDef *fd=findFileDef(Doxygen::inputNameLinkedMap,yytext,ambig); - //printf("looking for include %s -> %s fd=%p\n",yytext,absPath.data(),fd); - if (fd && fd->isLinkable()) - { - if (ambig) // multiple input files match the name - { - //printf("===== yes %s is ambiguous\n",yytext); - QCString name = QDir::cleanDirPath(yytext).utf8(); - if (!name.isEmpty() && yyextra->sourceFileDef) - { - FileName *fn = Doxygen::inputNameLinkedMap->find(name); - if (fn) - { - // see if this source file actually includes the file + //printf("looking for include %s -> %s fd=%p\n",yytext,absPath.data(),fd); + if (fd && fd->isLinkable()) + { + if (ambig) // multiple input files match the name + { + //printf("===== yes %s is ambiguous\n",yytext); + QCString name = QDir::cleanDirPath(yytext).utf8(); + if (!name.isEmpty() && yyextra->sourceFileDef) + { + const FileName *fn = Doxygen::inputNameLinkedMap->find(name); + if (fn) + { + // see if this source file actually includes the file auto it = std::find_if(fn->begin(), fn->end(), [&sfd=yyextra->sourceFileDef] (const auto &lfd) { return sfd->isIncluded(lfd->absFilePath()); }); found = it!=fn->end(); - } - } - } - else // not ambiguous - { - found = TRUE; - } - } - //printf(" include file %s found=%d\n",fd ? fd->absFilePath().data() : "<none>",found); - if (found) - { - writeMultiLineCodeLink(yyscanner,*yyextra->code,fd,yytext); - } - else - { - yyextra->code->codify(yytext); - } - char c=(char)yyinput(yyscanner); - QCString text; - text+=c; - yyextra->code->codify(text); - endFontClass(yyscanner); - BEGIN( Body ); - } -<Body,Bases>^[ \t]*"#" { - startFontClass(yyscanner,"preprocessor"); - yyextra->lastSkipCppContext = YY_START; - yyextra->code->codify(yytext); - BEGIN( SkipCPP ) ; - } -<SkipCPP>\" { - yyextra->code->codify(yytext); - yyextra->lastStringContext=YY_START; - BEGIN( SkipString ) ; - } -<SkipCPP>. { - yyextra->code->codify(yytext); - } -<SkipCPP>[^\n\/\\\"]+ { - yyextra->code->codify(yytext); - } -<SkipCPP>\\[\r]?\n { - codifyLines(yyscanner,yytext); - } -<SkipCPP>"//"/[^/!] { - REJECT; - yyextra->code->codify(yytext); - } -<Body,FuncCall>"{" { + } + } + } + else // not ambiguous + { + found = TRUE; + } + } + //printf(" include file %s found=%d\n",fd ? fd->absFilePath().data() : "<none>",found); + if (found) + { + writeMultiLineCodeLink(yyscanner,*yyextra->code,fd,yytext); + } + else + { + yyextra->code->codify(yytext); + } + char c=(char)yyinput(yyscanner); + QCString text; + text+=c; + yyextra->code->codify(text); + endFontClass(yyscanner); + BEGIN( Body ); + } +<Body,Bases>^[ \t]*"#" { + startFontClass(yyscanner,"preprocessor"); + yyextra->lastSkipCppContext = YY_START; + yyextra->code->codify(yytext); + BEGIN( SkipCPP ) ; + } +<SkipCPP>\" { + yyextra->code->codify(yytext); + yyextra->lastStringContext=YY_START; + BEGIN( SkipString ) ; + } +<SkipCPP>. { + yyextra->code->codify(yytext); + } +<SkipCPP>[^\n\/\\\"]+ { + yyextra->code->codify(yytext); + } +<SkipCPP>\\[\r]?\n { + codifyLines(yyscanner,yytext); + } +<SkipCPP>"//"/[^/!] { + REJECT; + yyextra->code->codify(yytext); + } +<Body,FuncCall>"{" { yyextra->theVarContext.pushScope(); DBG_CTX((stderr,"** scope stack push INNERBLOCK\n")); - yyextra->scopeStack.push(INNERBLOCK); - - if (yyextra->searchingForBody) - { - yyextra->searchingForBody=FALSE; - yyextra->insideBody=TRUE; - } - yyextra->code->codify(yytext); - if (yyextra->insideBody) - { - yyextra->bodyCurlyCount++; - } - yyextra->type.resize(0); - yyextra->name.resize(0); - BEGIN( Body ); - } -<Body,FuncCall,MemberCall,MemberCall2>"}" { + yyextra->scopeStack.push(INNERBLOCK); + + if (yyextra->searchingForBody) + { + yyextra->searchingForBody=FALSE; + yyextra->insideBody=TRUE; + } + yyextra->code->codify(yytext); + if (yyextra->insideBody) + { + yyextra->bodyCurlyCount++; + } + yyextra->type.resize(0); + yyextra->name.resize(0); + BEGIN( Body ); + } +<Body,FuncCall,MemberCall,MemberCall2>"}" { yyextra->theVarContext.popScope(); - yyextra->type.resize(0); - yyextra->name.resize(0); - - int *scope = yyextra->scopeStack.pop(); - DBG_CTX((stderr,"** scope stack pop SCOPEBLOCK=%d\n",scope==SCOPEBLOCK)); - if (scope==SCOPEBLOCK || scope==CLASSBLOCK) - { - popScope(yyscanner); - } - - yyextra->code->codify(yytext); - - DBG_CTX((stderr,"yyextra->bodyCurlyCount=%d\n",yyextra->bodyCurlyCount)); - if (--yyextra->bodyCurlyCount<=0) - { - yyextra->insideBody=FALSE; - yyextra->currentMemberDef=0; - if (yyextra->currentDefinition) - yyextra->currentDefinition=yyextra->currentDefinition->getOuterScope(); - } - BEGIN(Body); - } -<Body,ClassVar>"@end" { - //printf("End of objc scope fd=%s\n",yyextra->sourceFileDef->name().data()); + yyextra->type.resize(0); + yyextra->name.resize(0); + + if (!yyextra->scopeStack.empty()) + { + int scope = yyextra->scopeStack.top(); + yyextra->scopeStack.pop(); + DBG_CTX((stderr,"** scope stack pop SCOPEBLOCK=%d\n",scope==SCOPEBLOCK)); + if (scope==SCOPEBLOCK || scope==CLASSBLOCK) + { + popScope(yyscanner); + } + } + + yyextra->code->codify(yytext); + + DBG_CTX((stderr,"yyextra->bodyCurlyCount=%d\n",yyextra->bodyCurlyCount)); + if (--yyextra->bodyCurlyCount<=0) + { + yyextra->insideBody=FALSE; + yyextra->currentMemberDef=0; + if (yyextra->currentDefinition) + yyextra->currentDefinition=yyextra->currentDefinition->getOuterScope(); + } + BEGIN(Body); + } +<Body,ClassVar>"@end" { + //printf("End of objc scope fd=%s\n",yyextra->sourceFileDef->name().data()); if (yyextra->sourceFileDef) - { - FileDef *fd=yyextra->sourceFileDef; - yyextra->insideObjC = fd->name().lower().right(2)==".m" || - fd->name().lower().right(3)==".mm"; - //printf("insideObjC=%d\n",yyextra->insideObjC); - } - else - { - yyextra->insideObjC = FALSE; - } - if (yyextra->insideBody) - { + { + const FileDef *fd=yyextra->sourceFileDef; + yyextra->insideObjC = fd->name().lower().right(2)==".m" || + fd->name().lower().right(3)==".mm"; + //printf("insideObjC=%d\n",yyextra->insideObjC); + } + else + { + yyextra->insideObjC = FALSE; + } + if (yyextra->insideBody) + { yyextra->theVarContext.popScope(); - int *scope = yyextra->scopeStack.pop(); - DBG_CTX((stderr,"** scope stack pop SCOPEBLOCK=%d\n",scope==SCOPEBLOCK)); - if (scope==SCOPEBLOCK || scope==CLASSBLOCK) - { - popScope(yyscanner); - } - yyextra->insideBody=FALSE; - } - - startFontClass(yyscanner,"keyword"); - yyextra->code->codify(yytext); - endFontClass(yyscanner); - - yyextra->currentMemberDef=0; - if (yyextra->currentDefinition) - yyextra->currentDefinition=yyextra->currentDefinition->getOuterScope(); - BEGIN(Body); - } -<ClassName,ClassVar>";" { - yyextra->code->codify(yytext); - yyextra->searchingForBody=FALSE; - BEGIN( Body ); - } -<ClassName,ClassVar>[*&^%]+ { - yyextra->type=yyextra->curClassName.copy(); - yyextra->name.resize(0); - yyextra->code->codify(yytext); - BEGIN( Body ); // variable of type struct * - } -<ClassName>"__declspec"{B}*"("{B}*{ID}{B}*")" { - startFontClass(yyscanner,"keyword"); - yyextra->code->codify(yytext); - endFontClass(yyscanner); - } -<ClassName>{ID}("."{ID})* | -<ClassName>{ID}("::"{ID})* { + if (!yyextra->scopeStack.empty()) + { + int scope = yyextra->scopeStack.top(); + yyextra->scopeStack.pop(); + DBG_CTX((stderr,"** scope stack pop SCOPEBLOCK=%d\n",scope==SCOPEBLOCK)); + if (scope==SCOPEBLOCK || scope==CLASSBLOCK) + { + popScope(yyscanner); + } + } + yyextra->insideBody=FALSE; + } + + startFontClass(yyscanner,"keyword"); + yyextra->code->codify(yytext); + endFontClass(yyscanner); + + yyextra->currentMemberDef=0; + if (yyextra->currentDefinition) + yyextra->currentDefinition=yyextra->currentDefinition->getOuterScope(); + BEGIN(Body); + } +<ClassName,ClassVar>";" { + yyextra->code->codify(yytext); + yyextra->searchingForBody=FALSE; + BEGIN( Body ); + } +<ClassName,ClassVar>[*&^%]+ { + yyextra->type=yyextra->curClassName.copy(); + yyextra->name.resize(0); + yyextra->code->codify(yytext); + BEGIN( Body ); // variable of type struct * + } +<ClassName>"__declspec"{B}*"("{B}*{ID}{B}*")" { + startFontClass(yyscanner,"keyword"); + yyextra->code->codify(yytext); + endFontClass(yyscanner); + } +<ClassName>{ID}("."{ID})* | +<ClassName>{ID}("::"{ID})* { if (yyextra->lang==SrcLangExt_CSharp) yyextra->curClassName=substitute(yytext,".","::"); else yyextra->curClassName=yytext; - addType(yyscanner); + addType(yyscanner); if (yyextra->curClassName=="alignas") { - startFontClass(yyscanner,"keyword"); - yyextra->code->codify(yytext); + startFontClass(yyscanner,"keyword"); + yyextra->code->codify(yytext); endFontClass(yyscanner); BEGIN( AlignAs ); } else { - generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext); - BEGIN( ClassVar ); + generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext); + BEGIN( ClassVar ); } - } -<AlignAs>"(" { + } +<AlignAs>"(" { yyextra->bracketCount=1; - yyextra->code->codify(yytext); + yyextra->code->codify(yytext); BEGIN( AlignAsEnd ); } -<AlignAs>\n { yyextra->yyLineNr++; +<AlignAs>\n { yyextra->yyLineNr++; codifyLines(yyscanner,yytext); } <AlignAs>. { yyextra->code->codify(yytext); } <AlignAsEnd>"(" { yyextra->code->codify(yytext); - yyextra->bracketCount++; + yyextra->bracketCount++; } -<AlignAsEnd>")" { +<AlignAsEnd>")" { yyextra->code->codify(yytext); if (--yyextra->bracketCount<=0) { BEGIN(ClassName); } } -<AlignAsEnd>\n { yyextra->yyLineNr++; - codifyLines(yyscanner,yytext); +<AlignAsEnd>\n { yyextra->yyLineNr++; + codifyLines(yyscanner,yytext); } <AlignAsEnd>. { yyextra->code->codify(yytext); } -<ClassName>{ID}("\\"{ID})* { // PHP namespace +<ClassName>{ID}("\\"{ID})* { // PHP namespace yyextra->curClassName=substitute(yytext,"\\","::"); - yyextra->scopeStack.push(CLASSBLOCK); - pushScope(yyscanner,yyextra->curClassName); - addType(yyscanner); - generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext); - BEGIN( ClassVar ); - } + yyextra->scopeStack.push(CLASSBLOCK); + pushScope(yyscanner,yyextra->curClassName); + addType(yyscanner); + generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext); + BEGIN( ClassVar ); + } <ClassName>{ID}{B}*"("{ID}")" { // Obj-C category yyextra->curClassName=removeRedundantWhiteSpace(yytext); - yyextra->scopeStack.push(CLASSBLOCK); - pushScope(yyscanner,yyextra->curClassName); - addType(yyscanner); - generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext); - BEGIN( ClassVar ); - } -<PackageName>{ID}("."{ID})* { - yyextra->curClassName=substitute(yytext,".","::"); - //printf("found package: %s\n",yyextra->curClassName.data()); - addType(yyscanner); - codifyLines(yyscanner,yytext); - } -<ClassVar>"=" { - unput(*yytext); - BEGIN( Body ); - } -<ClassVar>("extends"|"implements") { // Java, Slice - startFontClass(yyscanner,"keyword"); - codifyLines(yyscanner,yytext); - endFontClass(yyscanner); - yyextra->curClassBases.clear(); - BEGIN( Bases ); - } + yyextra->scopeStack.push(CLASSBLOCK); + pushScope(yyscanner,yyextra->curClassName); + addType(yyscanner); + generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext); + BEGIN( ClassVar ); + } +<PackageName>{ID}("."{ID})* { + yyextra->curClassName=substitute(yytext,".","::"); + //printf("found package: %s\n",yyextra->curClassName.data()); + addType(yyscanner); + codifyLines(yyscanner,yytext); + } +<ClassVar>"=" { + unput(*yytext); + BEGIN( Body ); + } +<ClassVar>("extends"|"implements") { // Java, Slice + startFontClass(yyscanner,"keyword"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + yyextra->curClassBases.clear(); + BEGIN( Bases ); + } <ClassVar>("sealed"|"abstract")/{BN}*(":"|"{") { - DBG_CTX((stderr,"***** C++/CLI modifier %s on yyextra->curClassName=%s\n",yytext,yyextra->curClassName.data())); - startFontClass(yyscanner,"keyword"); - codifyLines(yyscanner,yytext); - endFontClass(yyscanner); - BEGIN( CppCliTypeModifierFollowup ); - } -<ClassVar>{ID} { - yyextra->type = yyextra->curClassName.copy(); - yyextra->name = yytext; - if (yyextra->insideBody) - { - yyextra->theVarContext.addVariable(yyscanner,yyextra->type,yyextra->name); - } - generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext); - } -<ClassName,ClassVar,CppCliTypeModifierFollowup>{B}*":"{B}* { - codifyLines(yyscanner,yytext); - yyextra->curClassBases.clear(); - BEGIN( Bases ); - } -<PackageName>[ \t]*";" | + DBG_CTX((stderr,"***** C++/CLI modifier %s on yyextra->curClassName=%s\n",yytext,yyextra->curClassName.data())); + startFontClass(yyscanner,"keyword"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + BEGIN( CppCliTypeModifierFollowup ); + } +<ClassVar>{ID} { + yyextra->type = yyextra->curClassName.copy(); + yyextra->name = yytext; + if (yyextra->insideBody) + { + addVariable(yyscanner,yyextra->type,yyextra->name); + } + generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext); + } +<ClassName,ClassVar,CppCliTypeModifierFollowup>{B}*":"{B}* { + codifyLines(yyscanner,yytext); + yyextra->curClassBases.clear(); + BEGIN( Bases ); + } +<PackageName>[ \t]*";" | <Bases>^{B}*/"@"{ID} | // Objective-C interface <Bases,ClassName,ClassVar,CppCliTypeModifierFollowup>{B}*"{"{B}* { yyextra->theVarContext.pushScope(); - yyextra->code->codify(yytext); - if (YY_START==ClassVar && yyextra->curClassName.isEmpty()) - { - yyextra->curClassName = yyextra->name.copy(); - } - if (yyextra->searchingForBody) - { - yyextra->searchingForBody=FALSE; - yyextra->insideBody=TRUE; - } - if (yyextra->insideBody) yyextra->bodyCurlyCount++; - if (!yyextra->curClassName.isEmpty()) // valid class name - { + yyextra->code->codify(yytext); + if (YY_START==ClassVar && yyextra->curClassName.isEmpty()) + { + yyextra->curClassName = yyextra->name.copy(); + } + if (yyextra->searchingForBody) + { + yyextra->searchingForBody=FALSE; + yyextra->insideBody=TRUE; + } + if (yyextra->insideBody) yyextra->bodyCurlyCount++; + if (!yyextra->curClassName.isEmpty()) // valid class name + { DBG_CTX((stderr,"** scope stack push CLASSBLOCK\n")); - yyextra->scopeStack.push(CLASSBLOCK); - pushScope(yyscanner,yyextra->curClassName); - DBG_CTX((stderr,"***** yyextra->curClassName=%s\n",yyextra->curClassName.data())); - if (getResolvedClass(yyextra->currentDefinition,yyextra->sourceFileDef,yyextra->curClassName)==0) - { - DBG_CTX((stderr,"Adding new class %s\n",yyextra->curClassName.data())); - ClassDef *ncd=createClassDef("<code>",1,1, - yyextra->curClassName,ClassDef::Class,0,0,FALSE); - yyextra->codeClassSDict->append(yyextra->curClassName,ncd); - // insert base classes. - char *s=yyextra->curClassBases.first(); - while (s) - { - const ClassDef *bcd=yyextra->codeClassSDict->find(s); - if (bcd==0) bcd=getResolvedClass(yyextra->currentDefinition,yyextra->sourceFileDef,s); - if (bcd && bcd!=ncd) - { - ncd->insertBaseClass(const_cast<ClassDef*>(bcd),s,Public,Normal); - } - s=yyextra->curClassBases.next(); - } - } - //printf("yyextra->codeClassList.count()=%d\n",yyextra->codeClassList.count()); - } - else // not a class name -> assume inner block - { + yyextra->scopeStack.push(CLASSBLOCK); + pushScope(yyscanner,yyextra->curClassName); + DBG_CTX((stderr,"***** yyextra->curClassName=%s\n",yyextra->curClassName.data())); + if (yyextra->symbolResolver.resolveClass(yyextra->currentDefinition,yyextra->curClassName)==0) + { + DBG_CTX((stderr,"Adding new class %s\n",yyextra->curClassName.data())); + ScopedTypeVariant var(yyextra->curClassName); + // insert base classes. + char *s=yyextra->curClassBases.first(); + while (s) + { + const ClassDef *bcd=0; + auto it = yyextra->codeClassMap.find(s); + if (it!=yyextra->codeClassMap.end()) + { + bcd = toClassDef(it->second.globalDef()); + } + if (bcd==0) bcd=yyextra->symbolResolver.resolveClass(yyextra->currentDefinition,s); + if (bcd && bcd->name()!=yyextra->curClassName) + { + var.localDef()->insertBaseClass(bcd->name()); + } + s=yyextra->curClassBases.next(); + } + yyextra->codeClassMap.emplace(std::make_pair(yyextra->curClassName.str(),std::move(var))); + } + //printf("yyextra->codeClassList.count()=%d\n",yyextra->codeClassList.count()); + } + else // not a class name -> assume inner block + { DBG_CTX((stderr,"** scope stack push INNERBLOCK\n")); - yyextra->scopeStack.push(INNERBLOCK); - } - yyextra->curClassName.resize(0); - yyextra->curClassBases.clear(); - BEGIN( Body ); - } -<Bases>"virtual"|"public"|"protected"|"private"|"@public"|"@private"|"@protected" { - startFontClass(yyscanner,"keyword"); - yyextra->code->codify(yytext); - endFontClass(yyscanner); - } -<Bases>{SEP}?({ID}{SEP})*{ID} { - DBG_CTX((stderr,"%s:addBase(%s)\n",yyextra->curClassName.data(),yytext)); - yyextra->curClassBases.inSort(yytext); - generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext); - } -<Bases>"<" { - yyextra->code->codify(yytext); - if (!yyextra->insideObjC) - { - yyextra->sharpCount=1; - BEGIN ( SkipSharp ); - } - else - { - yyextra->insideProtocolList=TRUE; - } - } -<Bases>">" { - yyextra->code->codify(yytext); - yyextra->insideProtocolList=FALSE; - } + yyextra->scopeStack.push(INNERBLOCK); + } + yyextra->curClassName.resize(0); + yyextra->curClassBases.clear(); + BEGIN( Body ); + } +<Bases>"virtual"|"public"|"protected"|"private"|"@public"|"@private"|"@protected" { + startFontClass(yyscanner,"keyword"); + yyextra->code->codify(yytext); + endFontClass(yyscanner); + } +<Bases>{SEP}?({ID}{SEP})*{ID} { + DBG_CTX((stderr,"%s:addBase(%s)\n",yyextra->curClassName.data(),yytext)); + yyextra->curClassBases.inSort(yytext); + generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext); + } +<Bases>"<" { + yyextra->code->codify(yytext); + if (!yyextra->insideObjC) + { + yyextra->sharpCount=1; + BEGIN ( SkipSharp ); + } + else + { + yyextra->insideProtocolList=TRUE; + } + } +<Bases>">" { + yyextra->code->codify(yytext); + yyextra->insideProtocolList=FALSE; + } <SkipSharp>"<" { - yyextra->code->codify(yytext); - ++yyextra->sharpCount; - } -<SkipSharp>">" { - yyextra->code->codify(yytext); - if (--yyextra->sharpCount<=0) - BEGIN ( Bases ); - } + yyextra->code->codify(yytext); + ++yyextra->sharpCount; + } +<SkipSharp>">" { + yyextra->code->codify(yytext); + if (--yyextra->sharpCount<=0) + BEGIN ( Bases ); + } <SkipSharp>"\"" { - yyextra->code->codify(yytext); - yyextra->lastStringContext=YY_START; + yyextra->code->codify(yytext); + yyextra->lastStringContext=YY_START; BEGIN(SkipString); } <SkipSharp>"\'" { - yyextra->code->codify(yytext); - yyextra->lastStringContext=YY_START; + yyextra->code->codify(yytext); + yyextra->lastStringContext=YY_START; BEGIN(SkipStringS); } <Bases>"(" { @@ -970,111 +853,108 @@ NUMBER {INTEGER_NUMBER}|{FLOAT_NUMBER} if (--yyextra->sharpCount<=0) BEGIN ( Bases ); } - - -<Bases>"," { - yyextra->code->codify(yytext); - } - + + +<Bases>"," { + yyextra->code->codify(yytext); + } + <Body>{SCOPEPREFIX}?"operator"{B}*"()"{B}*/"(" { - addType(yyscanner); - generateFunctionLink(yyscanner,*yyextra->code,yytext); - yyextra->bracketCount=0; - yyextra->args.resize(0); - yyextra->name+=yytext; - BEGIN( FuncCall ); - } + addType(yyscanner); + generateFunctionLink(yyscanner,*yyextra->code,yytext); + yyextra->bracketCount=0; + yyextra->args.resize(0); + yyextra->name+=yytext; + BEGIN( FuncCall ); + } <Body>{SCOPEPREFIX}?"operator"/"(" { - addType(yyscanner); - generateFunctionLink(yyscanner,*yyextra->code,yytext); - yyextra->bracketCount=0; - yyextra->args.resize(0); - yyextra->name+=yytext; - BEGIN( FuncCall ); + addType(yyscanner); + generateFunctionLink(yyscanner,*yyextra->code,yytext); + yyextra->bracketCount=0; + yyextra->args.resize(0); + yyextra->name+=yytext; + BEGIN( FuncCall ); } <Body>{SCOPEPREFIX}?"operator"[^a-z_A-Z0-9\(\n]+/"(" { - addType(yyscanner); - generateFunctionLink(yyscanner,*yyextra->code,yytext); - yyextra->bracketCount=0; - yyextra->args.resize(0); - yyextra->name+=yytext; - BEGIN( FuncCall ); - } -<Body,TemplDecl>("template"|"generic")/([^a-zA-Z0-9]) { - startFontClass(yyscanner,"keyword"); - codifyLines(yyscanner,yytext); - endFontClass(yyscanner); - yyextra->insideTemplate=TRUE; - yyextra->sharpCount=0; - } -<Body>"using"{BN}+"namespace"{BN}+ { - startFontClass(yyscanner,"keyword"); - codifyLines(yyscanner,yytext); - endFontClass(yyscanner); - BEGIN(UsingName); - } -<UsingName>{ID}("::"{ID})* { addUsingDirective(yyscanner,yytext); - generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext); + addType(yyscanner); + generateFunctionLink(yyscanner,*yyextra->code,yytext); + yyextra->bracketCount=0; + yyextra->args.resize(0); + yyextra->name+=yytext; + BEGIN( FuncCall ); + } +<Body,TemplDecl>("template"|"generic")/([^a-zA-Z0-9]) { + startFontClass(yyscanner,"keyword"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + yyextra->insideTemplate=TRUE; + yyextra->sharpCount=0; + } +<Body>"using"{BN}+"namespace"{BN}+ { + startFontClass(yyscanner,"keyword"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + BEGIN(UsingName); + } +<UsingName>{ID}("::"{ID})* { addUsingDirective(yyscanner,yytext); + generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext); DBG_CTX((stderr,"** scope stack push CLASSBLOCK\n")); - yyextra->scopeStack.push(CLASSBLOCK); - pushScope(yyscanner,yytext); - BEGIN(Body); + yyextra->scopeStack.push(CLASSBLOCK); + pushScope(yyscanner,yytext); + BEGIN(Body); } -<UsingName>\n { codifyLines(yyscanner,yytext); BEGIN(Body); } -<UsingName>. { codifyLines(yyscanner,yytext); BEGIN(Body); } -<Body,FuncCall>"$"?"this"("->"|".") { yyextra->code->codify(yytext); // this-> for C++, this. for C# - yyextra->prefixed_with_this_keyword = TRUE; +<UsingName>\n { codifyLines(yyscanner,yytext); BEGIN(Body); } +<UsingName>. { codifyLines(yyscanner,yytext); BEGIN(Body); } +<Body,FuncCall>"$"?"this"("->"|".") { yyextra->code->codify(yytext); // this-> for C++, this. for C# + yyextra->isPrefixedWithThis = TRUE; } -<Body>{KEYWORD}/([^a-z_A-Z0-9]) { +<Body>{KEYWORD}/([^a-z_A-Z0-9]) { if (yyextra->lang==SrcLangExt_Java && qstrcmp("internal",yytext) ==0) REJECT; if (skipLanguageSpecificKeyword(yyscanner,yytext)) REJECT; - startFontClass(yyscanner,"keyword"); - codifyLines(yyscanner,yytext); - if (QCString(yytext)=="typedef") - { - addType(yyscanner); - yyextra->name+=yytext; - } - endFontClass(yyscanner); - } -<Body>{KEYWORD}/{B}* { + startFontClass(yyscanner,"keyword"); + codifyLines(yyscanner,yytext); + if (QCString(yytext)=="typedef") + { + addType(yyscanner); + yyextra->name+=yytext; + } + endFontClass(yyscanner); + } +<Body>{KEYWORD}/{B}* { if (skipLanguageSpecificKeyword(yyscanner,yytext)) REJECT; - startFontClass(yyscanner,"keyword"); - codifyLines(yyscanner,yytext); - endFontClass(yyscanner); - } -<Body>{KEYWORD}/{BN}*"(" { + startFontClass(yyscanner,"keyword"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + } +<Body>{KEYWORD}/{BN}*"(" { if (skipLanguageSpecificKeyword(yyscanner,yytext)) REJECT; - startFontClass(yyscanner,"keyword"); - codifyLines(yyscanner,yytext); - endFontClass(yyscanner); - yyextra->name.resize(0);yyextra->type.resize(0); - } -<FuncCall>"in"/{BN}* { - if (!yyextra->inForEachExpression) REJECT; - startFontClass(yyscanner,"keywordflow"); - codifyLines(yyscanner,yytext); - endFontClass(yyscanner); - // insert the variable in the parent scope, see bug 546158 - yyextra->theVarContext.popScope(); - yyextra->theVarContext.addVariable(yyscanner,yyextra->parmType,yyextra->parmName); - yyextra->theVarContext.pushScope(); - yyextra->name.resize(0);yyextra->type.resize(0); - } -<Body>{FLOWKW}/{BN}*"(" { - startFontClass(yyscanner,"keywordflow"); - codifyLines(yyscanner,yytext); - endFontClass(yyscanner); - yyextra->name.resize(0);yyextra->type.resize(0); - yyextra->inForEachExpression = (qstrcmp(yytext,"for each")==0 || qstrcmp(yytext, "foreach")==0); - BEGIN(FuncCall); - } + startFontClass(yyscanner,"keyword"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + yyextra->name.resize(0);yyextra->type.resize(0); + } +<FuncCall>"in"/{BN}* { + if (!yyextra->inForEachExpression) REJECT; + startFontClass(yyscanner,"keywordflow"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + // insert the variable in the parent scope, see bug 546158 + yyextra->theVarContext.popScope(); + addVariable(yyscanner,yyextra->parmType,yyextra->parmName); + yyextra->theVarContext.pushScope(); + yyextra->name.resize(0);yyextra->type.resize(0); + } +<Body>{FLOWKW}/{BN}*"(" { + startFontClass(yyscanner,"keywordflow"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + yyextra->name.resize(0);yyextra->type.resize(0); + yyextra->inForEachExpression = (qstrcmp(yytext,"for each")==0 || qstrcmp(yytext, "foreach")==0); + BEGIN(FuncCall); + } <Body>{FLOWCONDITION}/{BN}*"(" { - if (yyextra->currentMemberDef && yyextra->currentMemberDef->isFunction()) - { - yyextra->currentMemberDef->incrementFlowKeyWordCount(); - } + incrementFlowKeyWordCount(yyscanner); startFontClass(yyscanner,"keywordflow"); codifyLines(yyscanner,yytext); endFontClass(yyscanner); @@ -1082,20 +962,17 @@ NUMBER {INTEGER_NUMBER}|{FLOAT_NUMBER} yyextra->inForEachExpression = (strcmp(yytext,"for each")==0 || strcmp(yytext, "foreach")==0); BEGIN(FuncCall); } -<Body>{FLOWKW}/([^a-z_A-Z0-9]) { - startFontClass(yyscanner,"keywordflow"); - codifyLines(yyscanner,yytext); - endFontClass(yyscanner); - if (yyextra->inFunctionTryBlock && (qstrcmp(yytext,"catch")==0 || qstrcmp(yytext,"finally")==0)) - { - yyextra->inFunctionTryBlock=FALSE; - } - } -<Body>{FLOWCONDITION}/([^a-z_A-Z0-9]) { - if (yyextra->currentMemberDef && yyextra->currentMemberDef->isFunction()) +<Body>{FLOWKW}/([^a-z_A-Z0-9]) { + startFontClass(yyscanner,"keywordflow"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + if (yyextra->inFunctionTryBlock && (qstrcmp(yytext,"catch")==0 || qstrcmp(yytext,"finally")==0)) { - yyextra->currentMemberDef->incrementFlowKeyWordCount(); + yyextra->inFunctionTryBlock=FALSE; } + } +<Body>{FLOWCONDITION}/([^a-z_A-Z0-9]) { + incrementFlowKeyWordCount(yyscanner); startFontClass(yyscanner,"keywordflow"); codifyLines(yyscanner,yytext); endFontClass(yyscanner); @@ -1104,47 +981,44 @@ NUMBER {INTEGER_NUMBER}|{FLOAT_NUMBER} yyextra->inFunctionTryBlock=FALSE; } } -<Body>{FLOWKW}/{B}* { - startFontClass(yyscanner,"keywordflow"); - codifyLines(yyscanner,yytext); - endFontClass(yyscanner); - } +<Body>{FLOWKW}/{B}* { + startFontClass(yyscanner,"keywordflow"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + } <Body>{FLOWCONDITION}/{B}* { - if (yyextra->currentMemberDef && yyextra->currentMemberDef->isFunction()) - { - yyextra->currentMemberDef->incrementFlowKeyWordCount(); - } + incrementFlowKeyWordCount(yyscanner); startFontClass(yyscanner,"keywordflow"); codifyLines(yyscanner,yytext); endFontClass(yyscanner); } <Body>"*"{B}*")" { // end of cast? - yyextra->code->codify(yytext); - yyextra->theCallContext.popScope(yyextra->name, yyextra->type); - yyextra->bracketCount--; + yyextra->code->codify(yytext); + yyextra->theCallContext.popScope(yyextra->name, yyextra->type); + yyextra->bracketCount--; yyextra->parmType = yyextra->name; - BEGIN(FuncCall); + BEGIN(FuncCall); } <Body>"\\)"|"\\(" { yyextra->code->codify(yytext); } -<Body>[\\|\)\+\-\/\%\~\!] { - yyextra->code->codify(yytext); - yyextra->name.resize(0);yyextra->type.resize(0); - if (*yytext==')') - { - yyextra->theCallContext.popScope(yyextra->name, yyextra->type); - yyextra->bracketCount--; - BEGIN(FuncCall); - } - } +<Body>[\\|\)\+\-\/\%\~\!] { + yyextra->code->codify(yytext); + yyextra->name.resize(0);yyextra->type.resize(0); + if (*yytext==')') + { + yyextra->theCallContext.popScope(yyextra->name, yyextra->type); + yyextra->bracketCount--; + BEGIN(FuncCall); + } + } <Body,TemplDecl,ObjCMethod>{TYPEKW}/{B}* { - startFontClass(yyscanner,"keywordtype"); - yyextra->code->codify(yytext); - endFontClass(yyscanner); - addType(yyscanner); - yyextra->name+=yytext; - } + startFontClass(yyscanner,"keywordtype"); + yyextra->code->codify(yytext); + endFontClass(yyscanner); + addType(yyscanner); + yyextra->name+=yytext; + } <Body,TemplDecl,ObjCMethod>{TYPEKWSL}/{B}* { if (yyextra->lang!=SrcLangExt_Slice) { @@ -1152,394 +1026,395 @@ NUMBER {INTEGER_NUMBER}|{FLOAT_NUMBER} } else { - startFontClass(yyscanner,"keywordtype"); - yyextra->code->codify(yytext); - endFontClass(yyscanner); - addType(yyscanner); - yyextra->name+=yytext; + startFontClass(yyscanner,"keywordtype"); + yyextra->code->codify(yytext); + endFontClass(yyscanner); + addType(yyscanner); + yyextra->name+=yytext; } - } + } <Body>"generic"/{B}*"<"[^\n\/\-\.\{\"\>]*">"{B}* { - startFontClass(yyscanner,"keyword"); - yyextra->code->codify(yytext); - endFontClass(yyscanner); - yyextra->sharpCount=0; - BEGIN(TemplDecl); - } + startFontClass(yyscanner,"keyword"); + yyextra->code->codify(yytext); + endFontClass(yyscanner); + yyextra->sharpCount=0; + BEGIN(TemplDecl); + } <Body>"template"/{B}*"<"[^\n\/\-\.\{\"\>]*">"{B}* { // template<...> - startFontClass(yyscanner,"keyword"); - yyextra->code->codify(yytext); - endFontClass(yyscanner); - yyextra->sharpCount=0; - BEGIN(TemplDecl); - } -<TemplDecl>"class"|"typename" { - startFontClass(yyscanner,"keyword"); - codifyLines(yyscanner,yytext); - endFontClass(yyscanner); - } -<TemplDecl>"<" { + startFontClass(yyscanner,"keyword"); + yyextra->code->codify(yytext); + endFontClass(yyscanner); + yyextra->sharpCount=0; + BEGIN(TemplDecl); + } +<TemplDecl>"class"|"typename" { + startFontClass(yyscanner,"keyword"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + } +<TemplDecl>"<" { yyextra->code->codify(yytext); yyextra->sharpCount++; - } -<TemplDecl>">" { + } +<TemplDecl>">" { yyextra->code->codify(yytext); yyextra->sharpCount--; - if (yyextra->sharpCount<=0) - { - BEGIN(Body); - } - } -<TemplCast>">" { - startFontClass(yyscanner,"keyword"); - codifyLines(yyscanner,yytext); - endFontClass(yyscanner); - BEGIN( yyextra->lastTemplCastContext ); - } -<TemplCast>{ID}("::"{ID})* { - generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext); - } -<TemplCast>("const"|"volatile"){B}* { - startFontClass(yyscanner,"keyword"); - codifyLines(yyscanner,yytext); - endFontClass(yyscanner); - } -<TemplCast>[*^]* { - codifyLines(yyscanner,yytext); - } + if (yyextra->sharpCount<=0) + { + BEGIN(Body); + } + } +<TemplCast>">" { + startFontClass(yyscanner,"keyword"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + BEGIN( yyextra->lastTemplCastContext ); + } +<TemplCast>{ID}("::"{ID})* { + generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext); + } +<TemplCast>("const"|"volatile"){B}* { + startFontClass(yyscanner,"keyword"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + } +<TemplCast>[*^]* { + codifyLines(yyscanner,yytext); + } <Body,MemberCall2,FuncCall>{CASTKW}{B}*"<" { // static_cast<T>( - startFontClass(yyscanner,"keyword"); - codifyLines(yyscanner,yytext); - endFontClass(yyscanner); + startFontClass(yyscanner,"keyword"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); yyextra->lastTemplCastContext = YY_START; - BEGIN(TemplCast); - } + BEGIN(TemplCast); + } <Body>"$this->"{SCOPENAME}/{BN}*[;,)\]] { // PHP member variable - addType(yyscanner); - generatePHPVariableLink(yyscanner,*yyextra->code,yytext); - yyextra->name+=yytext+7; + addType(yyscanner); + generatePHPVariableLink(yyscanner,*yyextra->code,yytext); + yyextra->name+=yytext+7; } <Body,TemplCast>{SCOPENAME}{B}*"<"[^\n\/\-\.\{\"\>\(]*">"("::"{ID})*/{B}* { // A<T> *pt; - if (isCastKeyword(yytext) && YY_START==Body) - { - REJECT; - } - addType(yyscanner); - generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext); - yyextra->name+=yytext; - } -<Body>{SCOPENAME}/{BN}*[:;,)\]] { // "int var;" or "var, var2" or "debug(f) macro" , or int var : 5; - addType(yyscanner); - // changed this to generateFunctionLink, see bug 624514 - //generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext,FALSE,TRUE); - generateFunctionLink(yyscanner,*yyextra->code,yytext); - yyextra->name+=yytext; - } -<Body>{SCOPENAME}/{B}* { // p->func() - addType(yyscanner); - generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext); - yyextra->name+=yytext; - } -<Body>"("{B}*("*"{B}*)+{SCOPENAME}+{B}*")"/{B}* { // (*p)->func() but not "if (p) ..." - yyextra->code->codify(yytext); - uint s=0;while (s<(uint)yyleng && !isId(yytext[s])) s++; + if (isCastKeyword(yytext) && YY_START==Body) + { + REJECT; + } + addType(yyscanner); + generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext); + yyextra->name+=yytext; + } +<Body>{SCOPENAME}/{BN}*[:;,)\]] { // "int var;" or "var, var2" or "debug(f) macro" , or int var : 5; + addType(yyscanner); + // changed this to generateFunctionLink, see bug 624514 + //generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext,FALSE,TRUE); + generateFunctionLink(yyscanner,*yyextra->code,yytext); + yyextra->name+=yytext; + } +<Body>{SCOPENAME}/{B}* { // p->func() + addType(yyscanner); + generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext); + yyextra->name+=yytext; + } +<Body>"("{B}*("*"{B}*)+{SCOPENAME}+{B}*")"/{B}* { // (*p)->func() but not "if (p) ..." + yyextra->code->codify(yytext); + uint s=0;while (s<(uint)yyleng && !isId(yytext[s])) s++; uint e=(uint)yyleng-1;while (e>1 && !isId(yytext[e])) e--; - QCString varname = ((QCString)yytext).mid(s,e-s+1); - addType(yyscanner); - yyextra->name=varname; - } + QCString varname = ((QCString)yytext).mid(s,e-s+1); + addType(yyscanner); + yyextra->name=varname; + } <Body>{SCOPETNAME}{B}*"<"[^\n\/\-\.\{\"\>]*">"/{BN}*"(" | -<Body>{SCOPETNAME}/{BN}*"(" { // a() or c::a() or t<A,B>::a() or A\B\foo() - if (isCastKeyword(yytext)) - { - REJECT; - } - addType(yyscanner); - generateFunctionLink(yyscanner,*yyextra->code,yytext); - yyextra->bracketCount=0; - yyextra->args.resize(0); - yyextra->name+=yytext; - BEGIN( FuncCall ); - } -<FuncCall,Body,MemberCall,MemberCall2,SkipInits,InlineInit>{RAWBEGIN} { +<Body>{SCOPETNAME}/{BN}*"(" { // a() or c::a() or t<A,B>::a() or A\B\foo() + if (isCastKeyword(yytext)) + { + REJECT; + } + addType(yyscanner); + generateFunctionLink(yyscanner,*yyextra->code,yytext); + yyextra->bracketCount=0; + yyextra->args.resize(0); + yyextra->name+=yytext; + BEGIN( FuncCall ); + } +<FuncCall,Body,MemberCall,MemberCall2,SkipInits,InlineInit>{RAWBEGIN} { QCString text=yytext; uint i=(uint)text.find('R'); yyextra->code->codify(text.left(i+1)); - startFontClass(yyscanner,"stringliteral"); - yyextra->code->codify(yytext+i+1); - yyextra->lastStringContext=YY_START; - yyextra->inForEachExpression = FALSE; + startFontClass(yyscanner,"stringliteral"); + yyextra->code->codify(yytext+i+1); + yyextra->lastStringContext=YY_START; + yyextra->inForEachExpression = FALSE; yyextra->delimiter = yytext+i+2; yyextra->delimiter=yyextra->delimiter.left(yyextra->delimiter.length()-1); - BEGIN( RawString ); - } -<FuncCall,Body,MemberCall,MemberCall2,SkipInits,InlineInit>\" { - startFontClass(yyscanner,"stringliteral"); - yyextra->code->codify(yytext); - yyextra->lastStringContext=YY_START; - yyextra->inForEachExpression = FALSE; - BEGIN( SkipString ); - } + BEGIN( RawString ); + } +<FuncCall,Body,MemberCall,MemberCall2,SkipInits,InlineInit>\" { + startFontClass(yyscanner,"stringliteral"); + yyextra->code->codify(yytext); + yyextra->lastStringContext=YY_START; + yyextra->inForEachExpression = FALSE; + BEGIN( SkipString ); + } <FuncCall,Body,MemberCall,MemberCall2,SkipInits,InlineInit>{NUMBER} { //Note similar code in commentcnv.l if (yyextra->lang!=SrcLangExt_Cpp) REJECT; - yyextra->code->codify(yytext); - } -<FuncCall,Body,MemberCall,MemberCall2,SkipInits,InlineInit>\' { - startFontClass(yyscanner,"stringliteral"); - yyextra->code->codify(yytext); - yyextra->lastStringContext=YY_START; - yyextra->inForEachExpression = FALSE; - BEGIN( SkipStringS ); - } -<SkipString>[^\"\\\r\n]* { - yyextra->code->codify(yytext); - } -<SkipStringS>[^\'\\\r\n]* { - yyextra->code->codify(yytext); - } -<SkipString,SkipStringS>"//"|"/*" { - yyextra->code->codify(yytext); - } -<SkipString>@?\" { - yyextra->code->codify(yytext); - endFontClass(yyscanner); - BEGIN( yyextra->lastStringContext ); - } -<SkipStringS>\' { - yyextra->code->codify(yytext); - endFontClass(yyscanner); - BEGIN( yyextra->lastStringContext ); - } -<SkipString,SkipStringS>\\. { - yyextra->code->codify(yytext); - } -<RawString>{RAWEND} { + yyextra->code->codify(yytext); + } +<FuncCall,Body,MemberCall,MemberCall2,SkipInits,InlineInit>\' { + startFontClass(yyscanner,"stringliteral"); + yyextra->code->codify(yytext); + yyextra->lastStringContext=YY_START; + yyextra->inForEachExpression = FALSE; + BEGIN( SkipStringS ); + } +<SkipString>[^\"\\\r\n]* { + yyextra->code->codify(yytext); + } +<SkipStringS>[^\'\\\r\n]* { + yyextra->code->codify(yytext); + } +<SkipString,SkipStringS>"//"|"/*" { + yyextra->code->codify(yytext); + } +<SkipString>@?\" { + yyextra->code->codify(yytext); + endFontClass(yyscanner); + BEGIN( yyextra->lastStringContext ); + } +<SkipStringS>\' { + yyextra->code->codify(yytext); + endFontClass(yyscanner); + BEGIN( yyextra->lastStringContext ); + } +<SkipString,SkipStringS>\\. { + yyextra->code->codify(yytext); + } +<RawString>{RAWEND} { yyextra->code->codify(yytext); QCString delimiter = yytext+1; delimiter=delimiter.left(delimiter.length()-1); if (delimiter==yyextra->delimiter) { - BEGIN( yyextra->lastStringContext ); + BEGIN( yyextra->lastStringContext ); } } <RawString>[^)\n]+ { yyextra->code->codify(yytext); } <RawString>. { yyextra->code->codify(yytext); } <RawString>\n { codifyLines(yyscanner,yytext); } -<SkipVerbString>[^"\n]+ { - yyextra->code->codify(yytext); - } -<SkipVerbString>\"\" { // escaped quote - yyextra->code->codify(yytext); - } -<SkipVerbString>\" { // end of string - yyextra->code->codify(yytext); - endFontClass(yyscanner); - BEGIN( yyextra->lastVerbStringContext ); - } -<SkipVerbString>. { - yyextra->code->codify(yytext); - } -<SkipVerbString>\n { - codifyLines(yyscanner,yytext); - } -<Body>":" { - yyextra->code->codify(yytext); - yyextra->name.resize(0);yyextra->type.resize(0); - } -<Body>"<" { - if (yyextra->insideTemplate) - { - yyextra->sharpCount++; - } - yyextra->code->codify(yytext); - } -<Body>">" { - if (yyextra->insideTemplate) - { - if (--yyextra->sharpCount<=0) - { - yyextra->insideTemplate=FALSE; - } - } - yyextra->code->codify(yytext); - } -<Body,MemberCall,MemberCall2,FuncCall>"'"((\\0[Xx0-9]+)|(\\.)|(.))"'" { - startFontClass(yyscanner,"charliteral"); - yyextra->code->codify(yytext); - endFontClass(yyscanner); - } -<Body>"."|"->" { - if (yytext[0]=='-') // -> could be overloaded - { - updateCallContextForSmartPointer(yyscanner); - } - yyextra->code->codify(yytext); - yyextra->memCallContext = YY_START; - BEGIN( MemberCall ); - } -<MemberCall>{SCOPETNAME}/{BN}*"(" { - if (yyextra->theCallContext.getScope()) - { - if (!generateClassMemberLink(yyscanner,*yyextra->code,yyextra->theCallContext.getScope(),yytext)) - { - yyextra->code->codify(yytext); - addToSearchIndex(yyscanner,yytext); - } - yyextra->name.resize(0); - } - else - { - yyextra->code->codify(yytext); - addToSearchIndex(yyscanner,yytext); - yyextra->name.resize(0); - } - yyextra->type.resize(0); - if (yyextra->memCallContext==Body) - { - BEGIN(FuncCall); - } - else - { - BEGIN(yyextra->memCallContext); - } - } -<MemberCall>{SCOPENAME}/{B}* { - if (yyextra->theCallContext.getScope()) - { - DBG_CTX((stderr,"yyextra->theCallContext.getClass()=%p\n",yyextra->theCallContext.getScope())); - if (!generateClassMemberLink(yyscanner,*yyextra->code,yyextra->theCallContext.getScope(),yytext)) - { - yyextra->code->codify(yytext); - addToSearchIndex(yyscanner,yytext); - } - yyextra->name.resize(0); - } - else - { - DBG_CTX((stderr,"no class context!\n")); - yyextra->code->codify(yytext); - addToSearchIndex(yyscanner,yytext); - yyextra->name.resize(0); - } - yyextra->type.resize(0); - BEGIN(yyextra->memCallContext); - } -<Body>[,=;\[] { - if (yyextra->insideObjC && *yytext=='[') - { - //printf("Found start of ObjC call!\n"); - // start of a method call - yyextra->contextDict.setAutoDelete(TRUE); - yyextra->nameDict.setAutoDelete(TRUE); - yyextra->objectDict.setAutoDelete(TRUE); - yyextra->wordDict.setAutoDelete(TRUE); - yyextra->commentDict.setAutoDelete(TRUE); - yyextra->contextDict.clear(); - yyextra->nameDict.clear(); - yyextra->objectDict.clear(); - yyextra->wordDict.clear(); - yyextra->commentDict.clear(); - yyextra->currentCtxId = 0; - yyextra->currentNameId = 0; - yyextra->currentObjId = 0; - yyextra->currentCtx = 0; - yyextra->braceCount = 0; - unput('['); - BEGIN(ObjCCall); - } - else - { - yyextra->code->codify(yytext); - yyextra->saveName = yyextra->name.copy(); - yyextra->saveType = yyextra->type.copy(); - if (*yytext!='[' && !yyextra->type.isEmpty()) - { - //printf("yyextra->scopeStack.bottom()=%p\n",yyextra->scopeStack.bottom()); - //if (yyextra->scopeStack.top()!=CLASSBLOCK) // commented out for bug731363 - { - //printf("AddVariable: '%s' '%s' context=%d\n", - // yyextra->type.data(),yyextra->name.data(),yyextra->theVarContext.count()); - yyextra->theVarContext.addVariable(yyscanner,yyextra->type,yyextra->name); - } - yyextra->name.resize(0); - } - if (*yytext==';' || *yytext=='=') - { - yyextra->type.resize(0); - yyextra->name.resize(0); - } - else if (*yytext=='[') - { - yyextra->theCallContext.pushScope(yyextra->name, yyextra->type); - } - yyextra->args.resize(0); +<SkipVerbString>[^"\n]+ { + yyextra->code->codify(yytext); + } +<SkipVerbString>\"\" { // escaped quote + yyextra->code->codify(yytext); + } +<SkipVerbString>\" { // end of string + yyextra->code->codify(yytext); + endFontClass(yyscanner); + BEGIN( yyextra->lastVerbStringContext ); + } +<SkipVerbString>. { + yyextra->code->codify(yytext); + } +<SkipVerbString>\n { + codifyLines(yyscanner,yytext); + } +<Body>":" { + yyextra->code->codify(yytext); + yyextra->name.resize(0);yyextra->type.resize(0); + } +<Body>"<" { + if (yyextra->insideTemplate) + { + yyextra->sharpCount++; + } + yyextra->code->codify(yytext); + } +<Body>">" { + if (yyextra->insideTemplate) + { + if (--yyextra->sharpCount<=0) + { + yyextra->insideTemplate=FALSE; + } + } + yyextra->code->codify(yytext); + } +<Body,MemberCall,MemberCall2,FuncCall>"'"((\\0[Xx0-9]+)|(\\.)|(.))"'" { + startFontClass(yyscanner,"charliteral"); + yyextra->code->codify(yytext); + endFontClass(yyscanner); + } +<Body>"."|"->" { + if (yytext[0]=='-') // -> could be overloaded + { + updateCallContextForSmartPointer(yyscanner); + } + yyextra->code->codify(yytext); + yyextra->memCallContext = YY_START; + BEGIN( MemberCall ); + } +<MemberCall>{SCOPETNAME}/{BN}*"(" { + if (yyextra->theCallContext.getScope().globalDef()) + { + if (!generateClassMemberLink(yyscanner,*yyextra->code,yyextra->theCallContext.getScope().globalDef(),yytext)) + { + yyextra->code->codify(yytext); + addToSearchIndex(yyscanner,yytext); + } + yyextra->name.resize(0); + } + else + { + yyextra->code->codify(yytext); + addToSearchIndex(yyscanner,yytext); + yyextra->name.resize(0); + } + yyextra->type.resize(0); + if (yyextra->memCallContext==Body) + { + BEGIN(FuncCall); + } + else + { + BEGIN(yyextra->memCallContext); + } + } +<MemberCall>{SCOPENAME}/{B}* { + if (yyextra->theCallContext.getScope().globalDef()) + { + DBG_CTX((stderr,"yyextra->theCallContext.getClass()=%p\n",yyextra->theCallContext.getScope().globalDef())); + if (!generateClassMemberLink(yyscanner,*yyextra->code,yyextra->theCallContext.getScope().globalDef(),yytext)) + { + yyextra->code->codify(yytext); + addToSearchIndex(yyscanner,yytext); + } + yyextra->name.resize(0); + } + else + { + DBG_CTX((stderr,"no class context!\n")); + yyextra->code->codify(yytext); + addToSearchIndex(yyscanner,yytext); + yyextra->name.resize(0); + } + yyextra->type.resize(0); + BEGIN(yyextra->memCallContext); + } +<Body>[,=;\[] { + if (yyextra->insideObjC && *yytext=='[') + { + //printf("Found start of ObjC call!\n"); + // start of a method call + yyextra->contextMap.clear(); + yyextra->nameMap.clear(); + yyextra->objectMap.clear(); + yyextra->wordMap.clear(); + yyextra->commentMap.clear(); + yyextra->currentCtxId = 0; + yyextra->currentNameId = 0; + yyextra->currentObjId = 0; + yyextra->currentCtx = 0; + yyextra->braceCount = 0; + unput('['); + BEGIN(ObjCCall); + } + else + { + yyextra->code->codify(yytext); + yyextra->saveName = yyextra->name.copy(); + yyextra->saveType = yyextra->type.copy(); + if (*yytext!='[' && !yyextra->type.isEmpty()) + { + //printf("yyextra->scopeStack.bottom()=%p\n",yyextra->scopeStack.bottom()); + //if (yyextra->scopeStack.top()!=CLASSBLOCK) // commented out for bug731363 + { + //printf("AddVariable: '%s' '%s' context=%d\n", + // yyextra->type.data(),yyextra->name.data(),yyextra->theVarContext.count()); + addVariable(yyscanner,yyextra->type,yyextra->name); + } + yyextra->name.resize(0); + } + if (*yytext==';' || *yytext=='=') + { + yyextra->type.resize(0); + yyextra->name.resize(0); + } + else if (*yytext=='[') + { + yyextra->theCallContext.pushScope(yyextra->name, yyextra->type); + } + yyextra->args.resize(0); yyextra->parmType.resize(0); yyextra->parmName.resize(0); - } - } + } + } /* -<ObjCMemberCall>{ID} { - if (qstrcmp(yytext,"self")==0 || qstrcmp(yytext,"super")==0) - { - // TODO: get proper base class for "super" - yyextra->theCallContext.setClass(getClass(yyextra->curClassName)); - startFontClass(yyscanner,"keyword"); - yyextra->code->codify(yytext); - endFontClass(yyscanner); - } - else - { - generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext); - } - yyextra->name.resize(0); - BEGIN(ObjCMemberCall2); - } -<ObjCMemberCall>"[" { - yyextra->code->codify(yytext); - yyextra->theCallContext.pushScope(yyscanner,yyextra->name, yyextra->type); - } -<ObjCMemberCall2>{ID}":"? { - yyextra->name+=yytext; - if (yyextra->theCallContext.getClass()) - { - //printf("Calling method %s\n",yyextra->name.data()); - if (!generateClassMemberLink(yyscanner,*yyextra->code,yyextra->theCallContext.getClass(),yyextra->name)) - { - yyextra->code->codify(yytext); - addToSearchIndex(yyscanner,yyextra->name); - } - } - else - { - yyextra->code->codify(yytext); - addToSearchIndex(yyscanner,yyextra->name); - } - yyextra->name.resize(0); - BEGIN(ObjCMemberCall3); - } -<ObjCMemberCall2,ObjCMemberCall3>"]" { - yyextra->theCallContext.popScope(yyextra->name, yyextra->type); - yyextra->code->codify(yytext); - BEGIN(Body); - } +<ObjCMemberCall>{ID} { + if (qstrcmp(yytext,"self")==0 || qstrcmp(yytext,"super")==0) + { + // TODO: get proper base class for "super" + yyextra->theCallContext.setClass(getClass(yyextra->curClassName)); + startFontClass(yyscanner,"keyword"); + yyextra->code->codify(yytext); + endFontClass(yyscanner); + } + else + { + generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext); + } + yyextra->name.resize(0); + BEGIN(ObjCMemberCall2); + } +<ObjCMemberCall>"[" { + yyextra->code->codify(yytext); + yyextra->theCallContext.pushScope(yyscanner,yyextra->name, yyextra->type); + } +<ObjCMemberCall2>{ID}":"? { + yyextra->name+=yytext; + if (yyextra->theCallContext.getClass()) + { + //printf("Calling method %s\n",yyextra->name.data()); + if (!generateClassMemberLink(yyscanner,*yyextra->code,yyextra->theCallContext.getClass(),yyextra->name)) + { + yyextra->code->codify(yytext); + addToSearchIndex(yyscanner,yyextra->name); + } + } + else + { + yyextra->code->codify(yytext); + addToSearchIndex(yyscanner,yyextra->name); + } + yyextra->name.resize(0); + BEGIN(ObjCMemberCall3); + } +<ObjCMemberCall2,ObjCMemberCall3>"]" { + yyextra->theCallContext.popScope(yyextra->name, yyextra->type); + yyextra->code->codify(yytext); + BEGIN(Body); + } */ <ObjCCall,ObjCMName>"["|"{" { saveObjCContext(yyscanner); - yyextra->currentCtx->format+=*yytext; - BEGIN(ObjCCall); - //printf("open\n"); + yyextra->currentCtx->format+=*yytext; + BEGIN(ObjCCall); + //printf("open\n"); } <ObjCCall,ObjCMName>"]"|"}" { - yyextra->currentCtx->format+=*yytext; + yyextra->currentCtx->format+=*yytext; restoreObjCContext(yyscanner); - BEGIN(ObjCMName); - if (yyextra->currentCtx==0) - { - // end of call - writeObjCMethodCall(yyscanner,yyextra->contextDict.find(0)); - BEGIN(Body); - } - //printf("close\n"); + BEGIN(ObjCMName); + if (yyextra->currentCtx==0) + { + // end of call + ObjCCallCtx *ctx = 0; + auto it = yyextra->contextMap.find(0); + if (it!=yyextra->contextMap.end()) + { + ctx = it->second.get(); + } + writeObjCMethodCall(yyscanner,ctx); + BEGIN(Body); + } + //printf("close\n"); } <ObjCCall,ObjCMName>"//".* { yyextra->currentCtx->format+=escapeComment(yyscanner,yytext); @@ -1549,92 +1424,92 @@ NUMBER {INTEGER_NUMBER}|{FLOAT_NUMBER} yyextra->currentCtx->comment=yytext; BEGIN(ObjCCallComment); } -<ObjCCallComment>"*/" { +<ObjCCallComment>"*/" { yyextra->currentCtx->comment+=yytext; yyextra->currentCtx->format+=escapeComment(yyscanner,yyextra->currentCtx->comment); - BEGIN(yyextra->lastObjCCallContext); - } + BEGIN(yyextra->lastObjCCallContext); + } <ObjCCallComment>[^*\n]+ { yyextra->currentCtx->comment+=yytext; } <ObjCCallComment>"//"|"/*" { yyextra->currentCtx->comment+=yytext; } <ObjCCallComment>\n { yyextra->currentCtx->comment+=*yytext; } <ObjCCallComment>. { yyextra->currentCtx->comment+=*yytext; } -<ObjCCall>{ID} { +<ObjCCall>{ID} { yyextra->currentCtx->format+=escapeObject(yyscanner,yytext); - if (yyextra->braceCount==0) - { - yyextra->currentCtx->objectTypeOrName=yytext; + if (yyextra->braceCount==0) + { + yyextra->currentCtx->objectTypeOrName=yytext; //printf("new type=%s\n",yyextra->currentCtx->objectTypeOrName.data()); - BEGIN(ObjCMName); - } - } -<ObjCMName>{ID}/{BN}*"]" { - if (yyextra->braceCount==0 && - yyextra->currentCtx->methodName.isEmpty()) + BEGIN(ObjCMName); + } + } +<ObjCMName>{ID}/{BN}*"]" { + if (yyextra->braceCount==0 && + yyextra->currentCtx->methodName.isEmpty()) { - yyextra->currentCtx->methodName=yytext; + yyextra->currentCtx->methodName=yytext; yyextra->currentCtx->format+=escapeName(yyscanner,yytext); - } - else - { + } + else + { yyextra->currentCtx->format+=escapeWord(yyscanner,yytext); - } + } } -<ObjCMName>{ID}/{BN}*":" { +<ObjCMName>{ID}/{BN}*":" { if (yyextra->braceCount==0) { - yyextra->currentCtx->methodName+=yytext; + yyextra->currentCtx->methodName+=yytext; yyextra->currentCtx->methodName+=":"; - } + } yyextra->currentCtx->format+=escapeName(yyscanner,yytext); } <ObjCSkipStr>[^\n\"$\\]* { yyextra->currentCtx->format+=yytext; } -<ObjCSkipStr>\\. { yyextra->currentCtx->format+=yytext; } -<ObjCSkipStr>"\"" { yyextra->currentCtx->format+=yytext; - BEGIN(yyextra->lastStringContext); +<ObjCSkipStr>\\. { yyextra->currentCtx->format+=yytext; } +<ObjCSkipStr>"\"" { yyextra->currentCtx->format+=yytext; + BEGIN(yyextra->lastStringContext); } <ObjCCall,ObjCMName>{CHARLIT} { yyextra->currentCtx->format+=yytext; } -<ObjCCall,ObjCMName>"@"?"\"" { yyextra->currentCtx->format+=yytext; +<ObjCCall,ObjCMName>"@"?"\"" { yyextra->currentCtx->format+=yytext; yyextra->lastStringContext=YY_START; - BEGIN(ObjCSkipStr); + BEGIN(ObjCSkipStr); } <ObjCCall,ObjCMName,ObjCSkipStr>"$" { yyextra->currentCtx->format+="$$"; } <ObjCCall,ObjCMName>"(" { yyextra->currentCtx->format+=*yytext; yyextra->braceCount++; } <ObjCCall,ObjCMName>")" { yyextra->currentCtx->format+=*yytext; yyextra->braceCount--; } -<ObjCSkipStr>"@"/"\"" { // needed to prevent matching the global rule (for C#) +<ObjCSkipStr>"@"/"\"" { // needed to prevent matching the global rule (for C#) yyextra->currentCtx->format+=yytext; } <ObjCCall,ObjCMName,ObjCSkipStr>{ID} { yyextra->currentCtx->format+=escapeWord(yyscanner,yytext); } <ObjCCall,ObjCMName,ObjCSkipStr>. { yyextra->currentCtx->format+=*yytext; } <ObjCCall,ObjCMName,ObjCSkipStr>\n { yyextra->currentCtx->format+=*yytext; } -<Body>"]" { - yyextra->theCallContext.popScope(yyextra->name, yyextra->type); - yyextra->code->codify(yytext); - // TODO: nested arrays like: a[b[0]->func()]->func() - yyextra->name = yyextra->saveName.copy(); - yyextra->type = yyextra->saveType.copy(); - } -<Body>[0-9]+ { - yyextra->code->codify(yytext); - } -<Body>[0-9]+[xX][0-9A-Fa-f]+ { - yyextra->code->codify(yytext); - } +<Body>"]" { + yyextra->theCallContext.popScope(yyextra->name, yyextra->type); + yyextra->code->codify(yytext); + // TODO: nested arrays like: a[b[0]->func()]->func() + yyextra->name = yyextra->saveName.copy(); + yyextra->type = yyextra->saveType.copy(); + } +<Body>[0-9]+ { + yyextra->code->codify(yytext); + } +<Body>[0-9]+[xX][0-9A-Fa-f]+ { + yyextra->code->codify(yytext); + } <MemberCall2,FuncCall>{KEYWORD}/([^a-z_A-Z0-9]) { - //addParmType(yyscanner); - //yyextra->parmName=yytext; + //addParmType(yyscanner); + //yyextra->parmName=yytext; if (skipLanguageSpecificKeyword(yyscanner,yytext)) REJECT; - startFontClass(yyscanner,"keyword"); - yyextra->code->codify(yytext); - endFontClass(yyscanner); - } + startFontClass(yyscanner,"keyword"); + yyextra->code->codify(yytext); + endFontClass(yyscanner); + } <MemberCall2,FuncCall,OldStyleArgs,TemplCast>{TYPEKW}/([^a-z_A-Z0-9]) { - addParmType(yyscanner); - yyextra->parmName=yytext; - startFontClass(yyscanner,"keywordtype"); - yyextra->code->codify(yytext); - endFontClass(yyscanner); - } + addParmType(yyscanner); + yyextra->parmName=yytext; + startFontClass(yyscanner,"keywordtype"); + yyextra->code->codify(yytext); + endFontClass(yyscanner); + } <MemberCall2,FuncCall,OldStyleArgs,TemplCast>{TYPEKWSL}/([^a-z_A-Z0-9]) { if (yyextra->lang!=SrcLangExt_Slice) { @@ -1642,25 +1517,22 @@ NUMBER {INTEGER_NUMBER}|{FLOAT_NUMBER} } else { - addParmType(yyscanner); - yyextra->parmName=yytext; - startFontClass(yyscanner,"keywordtype"); - yyextra->code->codify(yytext); - endFontClass(yyscanner); + addParmType(yyscanner); + yyextra->parmName=yytext; + startFontClass(yyscanner,"keywordtype"); + yyextra->code->codify(yytext); + endFontClass(yyscanner); } - } + } <MemberCall2,FuncCall>{FLOWKW}/([^a-z_A-Z0-9]) { - addParmType(yyscanner); - yyextra->parmName=yytext; - startFontClass(yyscanner,"keywordflow"); - yyextra->code->codify(yytext); - endFontClass(yyscanner); - } + addParmType(yyscanner); + yyextra->parmName=yytext; + startFontClass(yyscanner,"keywordflow"); + yyextra->code->codify(yytext); + endFontClass(yyscanner); + } <MemberCall2,FuncCall>{FLOWCONDITION}/([^a-z_A-Z0-9]) { - if (yyextra->currentMemberDef && yyextra->currentMemberDef->isFunction()) - { - yyextra->currentMemberDef->incrementFlowKeyWordCount(); - } + incrementFlowKeyWordCount(yyscanner); addParmType(yyscanner); yyextra->parmName=yytext; startFontClass(yyscanner,"keywordflow"); @@ -1668,25 +1540,25 @@ NUMBER {INTEGER_NUMBER}|{FLOAT_NUMBER} endFontClass(yyscanner); } <MemberCall2,FuncCall>{ID}(({B}*"<"[^\n\[\](){}<>]*">")?({B}*"::"{B}*{ID})?)* { - if (isCastKeyword(yytext)) - { - REJECT; - } - addParmType(yyscanner); - yyextra->parmName=yytext; - generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext,!yyextra->insideBody); - } -<FuncCall>";" { // probably a cast, not a function call - yyextra->code->codify(yytext); - yyextra->inForEachExpression = FALSE; - BEGIN( Body ); - } -<MemberCall2,FuncCall>, { - yyextra->code->codify(yytext); - yyextra->theVarContext.addVariable(yyscanner,yyextra->parmType,yyextra->parmName); - yyextra->parmType.resize(0);yyextra->parmName.resize(0); - } -<MemberCall2,FuncCall>"{" { + if (isCastKeyword(yytext)) + { + REJECT; + } + addParmType(yyscanner); + yyextra->parmName=yytext; + generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext,!yyextra->insideBody); + } +<FuncCall>";" { // probably a cast, not a function call + yyextra->code->codify(yytext); + yyextra->inForEachExpression = FALSE; + BEGIN( Body ); + } +<MemberCall2,FuncCall>, { + yyextra->code->codify(yytext); + addVariable(yyscanner,yyextra->parmType,yyextra->parmName); + yyextra->parmType.resize(0);yyextra->parmName.resize(0); + } +<MemberCall2,FuncCall>"{" { if (yyextra->bracketCount>0) { yyextra->code->codify(yytext); @@ -1715,28 +1587,28 @@ NUMBER {INTEGER_NUMBER}|{FLOAT_NUMBER} <InlineInit>. { yyextra->code->codify(yytext); } -<MemberCall2,FuncCall>"(" { - yyextra->parmType.resize(0);yyextra->parmName.resize(0); - yyextra->code->codify(yytext); - yyextra->bracketCount++; - yyextra->theCallContext.pushScope(yyextra->name, yyextra->type); - if (YY_START==FuncCall && !yyextra->insideBody) - { - yyextra->theVarContext.pushScope(); - } - } +<MemberCall2,FuncCall>"(" { + yyextra->parmType.resize(0);yyextra->parmName.resize(0); + yyextra->code->codify(yytext); + yyextra->bracketCount++; + yyextra->theCallContext.pushScope(yyextra->name, yyextra->type); + if (YY_START==FuncCall && !yyextra->insideBody) + { + yyextra->theVarContext.pushScope(); + } + } <MemberCall2,FuncCall>{OPERATOR} { // operator - if (qstrcmp(yytext,"*") && - qstrcmp(yytext,"&") && - qstrcmp(yytext,"^") && - qstrcmp(yytext,"%")) // typically a pointer or reference - { - // not a * or &, or C++/CLI's ^ or % - yyextra->parmType.resize(0);yyextra->parmName.resize(0); - } - yyextra->code->codify(yytext); - } -<MemberCall,MemberCall2,FuncCall>("*"{B}*)?")" { + if (qstrcmp(yytext,"*") && + qstrcmp(yytext,"&") && + qstrcmp(yytext,"^") && + qstrcmp(yytext,"%")) // typically a pointer or reference + { + // not a * or &, or C++/CLI's ^ or % + yyextra->parmType.resize(0);yyextra->parmName.resize(0); + } + yyextra->code->codify(yytext); + } +<MemberCall,MemberCall2,FuncCall>("*"{B}*)?")" { if (yytext[0]==')') // no a pointer cast { //printf("addVariable(%s,%s)\n",yyextra->parmType.data(),yyextra->parmName.data()); @@ -1745,281 +1617,289 @@ NUMBER {INTEGER_NUMBER}|{FLOAT_NUMBER} yyextra->parmType=yyextra->parmName; yyextra->parmName.resize(0); } - yyextra->theVarContext.addVariable(yyscanner,yyextra->parmType,yyextra->parmName); + addVariable(yyscanner,yyextra->parmType,yyextra->parmName); } else { yyextra->parmType = yyextra->parmName; yyextra->parmName.resize(0); - yyextra->theVarContext.addVariable(yyscanner,yyextra->parmType,yyextra->parmName); - } - yyextra->theCallContext.popScope(yyextra->name, yyextra->type); - yyextra->inForEachExpression = FALSE; - //yyextra->theCallContext.setClass(0); // commented out, otherwise a()->b() does not work for b(). - yyextra->code->codify(yytext); - if (--yyextra->bracketCount<=0) - { - if (yyextra->name.isEmpty()) - { - BEGIN( Body ); - } - else - { - BEGIN( CallEnd ); - } - } - } -<CallEnd>[ \t\n]* { codifyLines(yyscanner,yytext); } + addVariable(yyscanner,yyextra->parmType,yyextra->parmName); + } + yyextra->theCallContext.popScope(yyextra->name, yyextra->type); + yyextra->inForEachExpression = FALSE; + //yyextra->theCallContext.setClass(0); // commented out, otherwise a()->b() does not work for b(). + yyextra->code->codify(yytext); + if (--yyextra->bracketCount<=0) + { + if (yyextra->name.isEmpty()) + { + BEGIN( Body ); + } + else + { + BEGIN( CallEnd ); + } + } + } +<CallEnd>[ \t\n]* { codifyLines(yyscanner,yytext); } /* -<MemberCall2,FuncCall>")"[ \t\n]*[;:] { +<MemberCall2,FuncCall>")"[ \t\n]*[;:] { */ -<CallEnd>[;:] { - codifyLines(yyscanner,yytext); - yyextra->bracketCount=0; - if (*yytext==';') yyextra->searchingForBody=FALSE; - if (!yyextra->type.isEmpty()) - { - DBG_CTX((stderr,"add variable yyextra->type=%s yyextra->name=%s)\n",yyextra->type.data(),yyextra->name.data())); - yyextra->theVarContext.addVariable(yyscanner,yyextra->type,yyextra->name); - } - yyextra->parmType.resize(0);yyextra->parmName.resize(0); - yyextra->theCallContext.setScope(0); - if (*yytext==';' || yyextra->insideBody) - { - if (!yyextra->insideBody) - { +<CallEnd>[;:] { + codifyLines(yyscanner,yytext); + yyextra->bracketCount=0; + if (*yytext==';') yyextra->searchingForBody=FALSE; + if (!yyextra->type.isEmpty()) + { + DBG_CTX((stderr,"add variable yyextra->type=%s yyextra->name=%s)\n",yyextra->type.data(),yyextra->name.data())); + addVariable(yyscanner,yyextra->type,yyextra->name); + } + yyextra->parmType.resize(0);yyextra->parmName.resize(0); + yyextra->theCallContext.setScope(ScopedTypeVariant()); + if (*yytext==';' || yyextra->insideBody) + { + if (!yyextra->insideBody) + { yyextra->theVarContext.popScope(); - } - yyextra->name.resize(0);yyextra->type.resize(0); - BEGIN( Body ); - } - else - { - yyextra->bracketCount=0; - BEGIN( SkipInits ); - } - } + } + yyextra->name.resize(0);yyextra->type.resize(0); + BEGIN( Body ); + } + else + { + yyextra->bracketCount=0; + BEGIN( SkipInits ); + } + } <CallEnd>("const"|"volatile"|"sealed"|"override")({BN}+("const"|"volatile"|"sealed"|"override"))*/{BN}*(";"|"="|"throw"{BN}*"(") { - startFontClass(yyscanner,"keyword"); - codifyLines(yyscanner,yytext); - endFontClass(yyscanner); - } + startFontClass(yyscanner,"keyword"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + } <CallEnd,OldStyleArgs>("const"|"volatile"|"sealed"|"override")*({BN}+("const"|"volatile"|"sealed"|"override"))*{BN}*"{" { if (yyextra->insideBody) - { - yyextra->theVarContext.pushScope(); - } - yyextra->theVarContext.addVariable(yyscanner,yyextra->parmType,yyextra->parmName); - //yyextra->theCallContext.popScope(yyextra->name, yyextra->type); - yyextra->parmType.resize(0);yyextra->parmName.resize(0); - int index = yyextra->name.findRev("::"); - DBG_CTX((stderr,"yyextra->name=%s\n",yyextra->name.data())); - if (index!=-1) - { - QCString scope = yyextra->name.left((uint)index); - if (!yyextra->classScope.isEmpty()) scope.prepend(yyextra->classScope+"::"); - const ClassDef *cd=getResolvedClass(Doxygen::globalScope,yyextra->sourceFileDef,scope); - if (cd) - { - setClassScope(yyscanner,cd->name()); - yyextra->scopeStack.push(SCOPEBLOCK); + { + yyextra->theVarContext.pushScope(); + } + addVariable(yyscanner,yyextra->parmType,yyextra->parmName); + //yyextra->theCallContext.popScope(yyextra->name, yyextra->type); + yyextra->parmType.resize(0);yyextra->parmName.resize(0); + int index = yyextra->name.findRev("::"); + DBG_CTX((stderr,"yyextra->name=%s\n",yyextra->name.data())); + if (index!=-1) + { + QCString scope = yyextra->name.left((uint)index); + if (!yyextra->classScope.isEmpty()) scope.prepend(yyextra->classScope+"::"); + const ClassDef *cd=yyextra->symbolResolver.resolveClass(Doxygen::globalScope,scope); + if (cd) + { + setClassScope(yyscanner,cd->name()); + yyextra->scopeStack.push(SCOPEBLOCK); DBG_CTX((stderr,"** scope stack push SCOPEBLOCK\n")); - } - else - { - //setClassScope(yyscanner,yyextra->realScope); - yyextra->scopeStack.push(INNERBLOCK); + } + else + { + //setClassScope(yyscanner,yyextra->realScope); + yyextra->scopeStack.push(INNERBLOCK); DBG_CTX((stderr,"** scope stack push INNERBLOCK\n")); - } - } - else - { + } + } + else + { DBG_CTX((stderr,"** scope stack push INNERBLOCK\n")); - yyextra->scopeStack.push(INNERBLOCK); - } - yytext[yyleng-1]='\0'; - QCString cv(yytext); - if (!cv.stripWhiteSpace().isEmpty()) - { - startFontClass(yyscanner,"keyword"); - codifyLines(yyscanner,yytext); - endFontClass(yyscanner); - } - else // just whitespace - { - codifyLines(yyscanner,yytext); - } - yyextra->code->codify("{"); - if (yyextra->searchingForBody) - { - yyextra->searchingForBody=FALSE; - yyextra->insideBody=TRUE; - } - if (yyextra->insideBody) yyextra->bodyCurlyCount++; - yyextra->type.resize(0); yyextra->name.resize(0); - BEGIN( Body ); - } -<CallEnd>"try" { // function-try-block - startFontClass(yyscanner,"keyword"); - yyextra->code->codify(yytext); - endFontClass(yyscanner); - yyextra->inFunctionTryBlock=TRUE; - } -<CallEnd>{ID} { - if (yyextra->insideBody || !yyextra->parmType.isEmpty()) - { - REJECT; - } - // could be K&R style definition - addParmType(yyscanner); - yyextra->parmName=yytext; - generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext,!yyextra->insideBody); - BEGIN(OldStyleArgs); - } -<OldStyleArgs>{ID} { - addParmType(yyscanner); - yyextra->parmName=yytext; - generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext,!yyextra->insideBody); - } -<OldStyleArgs>[,;] { - yyextra->code->codify(yytext); - yyextra->theVarContext.addVariable(yyscanner,yyextra->parmType,yyextra->parmName); - if (*yytext==';') yyextra->parmType.resize(0); - yyextra->parmName.resize(0); - } -<CallEnd,OldStyleArgs>"#" { - startFontClass(yyscanner,"preprocessor"); - yyextra->lastSkipCppContext = Body; - yyextra->code->codify(yytext); - BEGIN( SkipCPP ); - } -<CallEnd>. { - unput(*yytext); - if (!yyextra->insideBody) - { - yyextra->theVarContext.popScope(); - } - yyextra->name.resize(0);yyextra->args.resize(0); - yyextra->parmType.resize(0);yyextra->parmName.resize(0); - BEGIN( Body ); - } -<SkipInits>";" { - yyextra->code->codify(yytext); - yyextra->type.resize(0); yyextra->name.resize(0); - BEGIN( Body ); - } -<SkipInits>"{" { - yyextra->code->codify(yytext); - if (yyextra->searchingForBody) - { - yyextra->searchingForBody=FALSE; - yyextra->insideBody=TRUE; - } - if (yyextra->insideBody) yyextra->bodyCurlyCount++; - if (yyextra->name.find("::")!=-1) - { + yyextra->scopeStack.push(INNERBLOCK); + } + yytext[yyleng-1]='\0'; + QCString cv(yytext); + if (!cv.stripWhiteSpace().isEmpty()) + { + startFontClass(yyscanner,"keyword"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + } + else // just whitespace + { + codifyLines(yyscanner,yytext); + } + yyextra->code->codify("{"); + if (yyextra->searchingForBody) + { + yyextra->searchingForBody=FALSE; + yyextra->insideBody=TRUE; + } + if (yyextra->insideBody) yyextra->bodyCurlyCount++; + yyextra->type.resize(0); yyextra->name.resize(0); + BEGIN( Body ); + } +<CallEnd>"try" { // function-try-block + startFontClass(yyscanner,"keyword"); + yyextra->code->codify(yytext); + endFontClass(yyscanner); + yyextra->inFunctionTryBlock=TRUE; + } +<CallEnd>{ID} { + if (yyextra->insideBody || !yyextra->parmType.isEmpty()) + { + REJECT; + } + // could be K&R style definition + addParmType(yyscanner); + yyextra->parmName=yytext; + generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext,!yyextra->insideBody); + BEGIN(OldStyleArgs); + } +<OldStyleArgs>{ID} { + addParmType(yyscanner); + yyextra->parmName=yytext; + generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext,!yyextra->insideBody); + } +<OldStyleArgs>[,;] { + yyextra->code->codify(yytext); + addVariable(yyscanner,yyextra->parmType,yyextra->parmName); + if (*yytext==';') yyextra->parmType.resize(0); + yyextra->parmName.resize(0); + } +<CallEnd,OldStyleArgs>"#" { + startFontClass(yyscanner,"preprocessor"); + yyextra->lastSkipCppContext = Body; + yyextra->code->codify(yytext); + BEGIN( SkipCPP ); + } +<CallEnd>. { + unput(*yytext); + if (!yyextra->insideBody) + { + yyextra->theVarContext.popScope(); + } + yyextra->name.resize(0);yyextra->args.resize(0); + yyextra->parmType.resize(0);yyextra->parmName.resize(0); + BEGIN( Body ); + } +<SkipInits>";" { + yyextra->code->codify(yytext); + yyextra->type.resize(0); yyextra->name.resize(0); + BEGIN( Body ); + } +<SkipInits>"{" { + yyextra->code->codify(yytext); + if (yyextra->searchingForBody) + { + yyextra->searchingForBody=FALSE; + yyextra->insideBody=TRUE; + } + if (yyextra->insideBody) yyextra->bodyCurlyCount++; + if (yyextra->name.find("::")!=-1) + { DBG_CTX((stderr,"** scope stack push SCOPEBLOCK\n")); - yyextra->scopeStack.push(SCOPEBLOCK); - setClassScope(yyscanner,yyextra->realScope); - } - else - { + yyextra->scopeStack.push(SCOPEBLOCK); + setClassScope(yyscanner,yyextra->realScope); + } + else + { DBG_CTX((stderr,"** scope stack push INNERBLOCK\n")); - yyextra->scopeStack.push(INNERBLOCK); - } - yyextra->type.resize(0); yyextra->name.resize(0); - BEGIN( Body ); - } -<SkipInits>{ID} { - generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext); - } -<FuncCall>{ID}/"(" { - generateFunctionLink(yyscanner,*yyextra->code,yytext); - } -<FuncCall>{ID}/("."|"->") { - yyextra->name=yytext; - generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext); - BEGIN( MemberCall2 ); - } -<FuncCall,MemberCall2>("("{B}*("*"{B}*)+{ID}+{B}*")"{B}*)/("."|"->") { - yyextra->code->codify(yytext); - uint s=0;while (!isId(yytext[s])) s++; + yyextra->scopeStack.push(INNERBLOCK); + } + yyextra->type.resize(0); yyextra->name.resize(0); + BEGIN( Body ); + } +<SkipInits>{ID}{B}*"{" { + QCString text = yytext; + int bracketPos = text.find('{'); + int spacePos = text.find(' '); + int len = spacePos==-1 ? bracketPos : spacePos; + generateClassOrGlobalLink(yyscanner,*yyextra->code,text.left(len)); + yyextra->code->codify(yytext+len); + } +<SkipInits>{ID} { + generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext); + } +<FuncCall>{ID}/"(" { + generateFunctionLink(yyscanner,*yyextra->code,yytext); + } +<FuncCall>{ID}/("."|"->") { + yyextra->name=yytext; + generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext); + BEGIN( MemberCall2 ); + } +<FuncCall,MemberCall2>("("{B}*("*"{B}*)+{ID}+{B}*")"{B}*)/("."|"->") { + yyextra->code->codify(yytext); + uint s=0;while (!isId(yytext[s])) s++; uint e=(uint)yyleng-1;while (e>1 && !isId(yytext[e])) e--; - yyextra->name=((QCString)yytext).mid(s,e-s+1); - BEGIN( MemberCall2 ); - } -<MemberCall2>{ID}/([ \t\n]*"(") { - if (!yyextra->args.isEmpty()) - generateMemberLink(yyscanner,*yyextra->code,yyextra->args,yytext); - else - generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext); - yyextra->args.resize(0); - BEGIN( FuncCall ); - } + yyextra->name=((QCString)yytext).mid(s,e-s+1); + BEGIN( MemberCall2 ); + } +<MemberCall2>{ID}/([ \t\n]*"(") { + if (!yyextra->args.isEmpty()) + generateMemberLink(yyscanner,*yyextra->code,yyextra->args,yytext); + else + generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext); + yyextra->args.resize(0); + BEGIN( FuncCall ); + } <MemberCall2>{ID}/([ \t\n]*("."|"->")) { - //yyextra->code->codify(yytext); - yyextra->name=yytext; - generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext); - BEGIN( MemberCall2 ); - } -<MemberCall2>"->"|"." { - if (yytext[0]=='-') // -> could be overloaded - { - updateCallContextForSmartPointer(yyscanner); - } - yyextra->code->codify(yytext); - yyextra->memCallContext = YY_START; - BEGIN( MemberCall ); - } -<SkipComment>"/*"("!"?)"*/" { - yyextra->code->codify(yytext); - endFontClass(yyscanner); - BEGIN( yyextra->lastCContext ) ; - } -<SkipComment>"//"|"/*" { - yyextra->code->codify(yytext); - } -<SkipComment>[^*/\n]+ { - yyextra->code->codify(yytext); - } -<SkipComment>[ \t]*"*/" { - yyextra->code->codify(yytext); - endFontClass(yyscanner); - if (yyextra->lastCContext==SkipCPP) + //yyextra->code->codify(yytext); + yyextra->name=yytext; + generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext); + BEGIN( MemberCall2 ); + } +<MemberCall2>"->"|"." { + if (yytext[0]=='-') // -> could be overloaded + { + updateCallContextForSmartPointer(yyscanner); + } + yyextra->code->codify(yytext); + yyextra->memCallContext = YY_START; + BEGIN( MemberCall ); + } +<SkipComment>"/*"("!"?)"*/" { + yyextra->code->codify(yytext); + endFontClass(yyscanner); + BEGIN( yyextra->lastCContext ) ; + } +<SkipComment>"//"|"/*" { + yyextra->code->codify(yytext); + } +<SkipComment>[^*/\n]+ { + yyextra->code->codify(yytext); + } +<SkipComment>[ \t]*"*/" { + yyextra->code->codify(yytext); + endFontClass(yyscanner); + if (yyextra->lastCContext==SkipCPP) { startFontClass(yyscanner,"preprocessor"); } - BEGIN( yyextra->lastCContext ) ; - } -<SkipCxxComment>[^\r\n]*"\\"[\r]?\n { // line continuation - codifyLines(yyscanner,yytext); - } -<SkipCxxComment>[^\r\n]+ { - yyextra->code->codify(yytext); - } -<SkipCxxComment>\r -<SkipCxxComment>\n { - unput('\n'); - endFontClass(yyscanner); - BEGIN( yyextra->lastCContext ) ; - } -<SkipCxxComment>. { - yyextra->code->codify(yytext); - } + BEGIN( yyextra->lastCContext ) ; + } +<SkipCxxComment>[^\r\n]*"\\"[\r]?\n { // line continuation + codifyLines(yyscanner,yytext); + } +<SkipCxxComment>[^\r\n]+ { + yyextra->code->codify(yytext); + } +<SkipCxxComment>\r +<SkipCxxComment>\n { + unput('\n'); + endFontClass(yyscanner); + BEGIN( yyextra->lastCContext ) ; + } +<SkipCxxComment>. { + yyextra->code->codify(yytext); + } <RemoveSpecialCComment>"*/"{B}*\n({B}*\n)*({B}*(("//@"[{}])|("/*@"[{}]"*/")){B}*\n)?{B}*"/*"[*!]/[^/*] { - yyextra->yyLineNr+=QCString(yytext).contains('\n'); - } + yyextra->yyLineNr+=QCString(yytext).contains('\n'); + } <RemoveSpecialCComment>"*/"{B}*\n({B}*\n)*({B}*(("//@"[{}])|("/*@"[{}]"*/")){B}*\n)? { - if (yyextra->lastSpecialCContext==SkipCxxComment) - { // force end of C++ comment here - yyextra->yyLineNr+=QCString(yytext).contains('\n'); - nextCodeLine(yyscanner); - endFontClass(yyscanner); - BEGIN( yyextra->lastCContext ) ; - } - else - { - yyextra->yyLineNr+=QCString(yytext).contains('\n'); + if (yyextra->lastSpecialCContext==SkipCxxComment) + { // force end of C++ comment here + yyextra->yyLineNr+=QCString(yytext).contains('\n'); + nextCodeLine(yyscanner); + endFontClass(yyscanner); + BEGIN( yyextra->lastCContext ) ; + } + else + { + yyextra->yyLineNr+=QCString(yytext).contains('\n'); if (yytext[yyleng-1]=='\n') { yyextra->yyLineNr--; @@ -2027,276 +1907,274 @@ NUMBER {INTEGER_NUMBER}|{FLOAT_NUMBER} } else { - nextCodeLine(yyscanner); + nextCodeLine(yyscanner); } - BEGIN(yyextra->lastSpecialCContext); - } - } -<RemoveSpecialCComment>"*/" { - BEGIN(yyextra->lastSpecialCContext); - } + BEGIN(yyextra->lastSpecialCContext); + } + } +<RemoveSpecialCComment>"*/" { + BEGIN(yyextra->lastSpecialCContext); + } <RemoveSpecialCComment>[^*\n]+ <RemoveSpecialCComment>"//"|"/*" <RemoveSpecialCComment>\n { yyextra->yyLineNr++; } <RemoveSpecialCComment>. -<MemberCall>[^a-z_A-Z0-9(\n] { - yyextra->code->codify(yytext); - yyextra->type.resize(0); - yyextra->name.resize(0); - BEGIN(yyextra->memCallContext); - } -<*>\n({B}*"//"[!/][^\n]*\n)+ { // remove special one-line comment - if (YY_START==SkipCPP) REJECT; - if (Config_getBool(STRIP_CODE_COMMENTS)) - { - yyextra->yyLineNr+=QCString(yytext).contains('\n'); - nextCodeLine(yyscanner); - } - else - { - startFontClass(yyscanner,"comment"); - codifyLines(yyscanner,yytext); - endFontClass(yyscanner); - } - if (YY_START==SkipCxxComment) - { - endFontClass(yyscanner); - BEGIN( yyextra->lastCContext ) ; - } - } -<SkipCPP>\n/.*\n { - endFontClass(yyscanner); - BEGIN( yyextra->lastSkipCppContext ) ; +<MemberCall>[^a-z_A-Z0-9(\n] { + yyextra->code->codify(yytext); + yyextra->type.resize(0); + yyextra->name.resize(0); + BEGIN(yyextra->memCallContext); + } +<*>\n({B}*"//"[!/][^\n]*\n)+ { // remove special one-line comment + if (YY_START==SkipCPP) REJECT; + if (Config_getBool(STRIP_CODE_COMMENTS)) + { + yyextra->yyLineNr+=QCString(yytext).contains('\n'); + nextCodeLine(yyscanner); + } + else + { + startFontClass(yyscanner,"comment"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + } + if (YY_START==SkipCxxComment) + { + endFontClass(yyscanner); + BEGIN( yyextra->lastCContext ) ; + } + } +<SkipCPP>\n/.*\n { + endFontClass(yyscanner); + BEGIN( yyextra->lastSkipCppContext ) ; unput('\n'); - } -<*>\n{B}*"//@"[{}].*\n { // remove one-line group marker - if (Config_getBool(STRIP_CODE_COMMENTS)) - { - yyextra->yyLineNr+=2; - nextCodeLine(yyscanner); - } - else - { - startFontClass(yyscanner,"comment"); - codifyLines(yyscanner,yytext); - endFontClass(yyscanner); - } - if (YY_START==SkipCxxComment) - { - endFontClass(yyscanner); - BEGIN( yyextra->lastCContext ) ; - } - } -<*>\n{B}*"/*@"[{}] { // remove one-line group marker - if (Config_getBool(STRIP_CODE_COMMENTS)) - { - if (YY_START != RemoveSpecialCComment) yyextra->lastSpecialCContext = YY_START; - yyextra->yyLineNr++; - BEGIN(RemoveSpecialCComment); - } - else - { - // check is to prevent getting stuck in skipping C++ comments - if (YY_START != SkipComment && YY_START != SkipCxxComment) - { - yyextra->lastCContext = YY_START ; - } - startFontClass(yyscanner,"comment"); - codifyLines(yyscanner,yytext); - BEGIN(SkipComment); - } - } -<*>^{B}*"//@"[{}].*\n { // remove one-line group marker - if (Config_getBool(STRIP_CODE_COMMENTS)) - { - yyextra->yyLineNr++; - nextCodeLine(yyscanner); - } - else - { - startFontClass(yyscanner,"comment"); - codifyLines(yyscanner,yytext); - endFontClass(yyscanner); - } - } -<*>^{B}*"/*@"[{}] { // remove multi-line group marker - if (Config_getBool(STRIP_CODE_COMMENTS)) - { - if (YY_START != RemoveSpecialCComment) yyextra->lastSpecialCContext = YY_START; - BEGIN(RemoveSpecialCComment); - } - else - { - // check is to prevent getting stuck in skipping C++ comments - if (YY_START != SkipComment && YY_START != SkipCxxComment) - { - yyextra->lastCContext = YY_START ; - } - startFontClass(yyscanner,"comment"); - yyextra->code->codify(yytext); - BEGIN(SkipComment); - } - } -<*>^{B}*"//"[!/][^\n]*\n { // remove special one-line comment - if (Config_getBool(STRIP_CODE_COMMENTS)) - { - yyextra->yyLineNr++; - //nextCodeLine(yyscanner); - } - else - { - startFontClass(yyscanner,"comment"); - codifyLines(yyscanner,yytext); - endFontClass(yyscanner); - } - } -<*>"//"[!/][^\n]*/\n { // strip special one-line comment + } +<*>\n{B}*"//@"[{}].*\n { // remove one-line group marker + if (Config_getBool(STRIP_CODE_COMMENTS)) + { + yyextra->yyLineNr+=2; + nextCodeLine(yyscanner); + } + else + { + startFontClass(yyscanner,"comment"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + } + if (YY_START==SkipCxxComment) + { + endFontClass(yyscanner); + BEGIN( yyextra->lastCContext ) ; + } + } +<*>\n{B}*"/*@"[{}] { // remove one-line group marker + if (Config_getBool(STRIP_CODE_COMMENTS)) + { + if (YY_START != RemoveSpecialCComment) yyextra->lastSpecialCContext = YY_START; + yyextra->yyLineNr++; + BEGIN(RemoveSpecialCComment); + } + else + { + // check is to prevent getting stuck in skipping C++ comments + if (YY_START != SkipComment && YY_START != SkipCxxComment) + { + yyextra->lastCContext = YY_START ; + } + startFontClass(yyscanner,"comment"); + codifyLines(yyscanner,yytext); + BEGIN(SkipComment); + } + } +<*>^{B}*"//@"[{}].*\n { // remove one-line group marker + if (Config_getBool(STRIP_CODE_COMMENTS)) + { + yyextra->yyLineNr++; + nextCodeLine(yyscanner); + } + else + { + startFontClass(yyscanner,"comment"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + } + } +<*>^{B}*"/*@"[{}] { // remove multi-line group marker + if (Config_getBool(STRIP_CODE_COMMENTS)) + { + if (YY_START != RemoveSpecialCComment) yyextra->lastSpecialCContext = YY_START; + BEGIN(RemoveSpecialCComment); + } + else + { + // check is to prevent getting stuck in skipping C++ comments + if (YY_START != SkipComment && YY_START != SkipCxxComment) + { + yyextra->lastCContext = YY_START ; + } + startFontClass(yyscanner,"comment"); + yyextra->code->codify(yytext); + BEGIN(SkipComment); + } + } +<*>^{B}*"//"[!/][^\n]*\n { // remove special one-line comment + if (Config_getBool(STRIP_CODE_COMMENTS)) + { + yyextra->yyLineNr++; + //nextCodeLine(yyscanner); + } + else + { + startFontClass(yyscanner,"comment"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + } + } +<*>"//"[!/][^\n]*/\n { // strip special one-line comment if (YY_START==SkipComment || YY_START==SkipString) REJECT; - if (!Config_getBool(STRIP_CODE_COMMENTS)) - { - startFontClass(yyscanner,"comment"); - codifyLines(yyscanner,yytext); - endFontClass(yyscanner); - } - } -<*>"/*[tag:"[^\]\n]*"]*/"{B}* { // special pattern /*[tag:filename]*/ to force linking to a tag file - yyextra->forceTagReference=yytext; - uint s=(uint)yyextra->forceTagReference.find(':'); - uint e=(uint)yyextra->forceTagReference.findRev(']'); - yyextra->forceTagReference = yyextra->forceTagReference.mid(s+1,e-s-1); - } -<*>\n{B}*"/*"[!*]/[^/*] { - if (Config_getBool(STRIP_CODE_COMMENTS)) - { - if (YY_START != RemoveSpecialCComment) yyextra->lastSpecialCContext = YY_START; - yyextra->yyLineNr++; - BEGIN(RemoveSpecialCComment); - } - else - { - // check is to prevent getting stuck in skipping C++ comments - if (YY_START != SkipComment && YY_START != SkipCxxComment) - { - yyextra->lastCContext = YY_START ; - } - startFontClass(yyscanner,"comment"); - codifyLines(yyscanner,yytext); - BEGIN(SkipComment); - } - } -<*>^{B}*"/**"[*]+/[^/] { // special C "banner" comment block at a new line - if (Config_getBool(JAVADOC_BANNER) && Config_getBool(STRIP_CODE_COMMENTS)) - { - if (YY_START != RemoveSpecialCComment) yyextra->lastSpecialCContext = YY_START; - BEGIN(RemoveSpecialCComment); - } - else - { - // check is to prevent getting stuck in skipping C++ comments - if (YY_START != SkipComment && YY_START != SkipCxxComment) - { - yyextra->lastCContext = YY_START ; - } - startFontClass(yyscanner,"comment"); - yyextra->code->codify(yytext); - BEGIN(SkipComment); - } - } -<*>^{B}*"/*"[!*]/[^/*] { // special C comment block at a new line - if (Config_getBool(STRIP_CODE_COMMENTS)) - { - if (YY_START != RemoveSpecialCComment) yyextra->lastSpecialCContext = YY_START; - BEGIN(RemoveSpecialCComment); - } - else - { - // check is to prevent getting stuck in skipping C++ comments - if (YY_START != SkipComment && YY_START != SkipCxxComment) - { - yyextra->lastCContext = YY_START ; - } - startFontClass(yyscanner,"comment"); - yyextra->code->codify(yytext); - BEGIN(SkipComment); - } - } -<*>"/*"[!*]/[^/*] { // special C comment block half way a line + if (!Config_getBool(STRIP_CODE_COMMENTS)) + { + startFontClass(yyscanner,"comment"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + } + } +<*>\n{B}*"/*"[!*]/[^/*] { + if (Config_getBool(STRIP_CODE_COMMENTS)) + { + if (YY_START != RemoveSpecialCComment) yyextra->lastSpecialCContext = YY_START; + yyextra->yyLineNr++; + BEGIN(RemoveSpecialCComment); + } + else + { + // check is to prevent getting stuck in skipping C++ comments + if (YY_START != SkipComment && YY_START != SkipCxxComment) + { + yyextra->lastCContext = YY_START ; + } + startFontClass(yyscanner,"comment"); + codifyLines(yyscanner,yytext); + BEGIN(SkipComment); + } + } +<*>^{B}*"/**"[*]+/[^/] { // special C "banner" comment block at a new line + if (Config_getBool(JAVADOC_BANNER) && Config_getBool(STRIP_CODE_COMMENTS)) + { + if (YY_START != RemoveSpecialCComment) yyextra->lastSpecialCContext = YY_START; + BEGIN(RemoveSpecialCComment); + } + else + { + // check is to prevent getting stuck in skipping C++ comments + if (YY_START != SkipComment && YY_START != SkipCxxComment) + { + yyextra->lastCContext = YY_START ; + } + startFontClass(yyscanner,"comment"); + yyextra->code->codify(yytext); + BEGIN(SkipComment); + } + } +<*>^{B}*"/*"[!*]/[^/*] { // special C comment block at a new line + if (Config_getBool(STRIP_CODE_COMMENTS)) + { + if (YY_START != RemoveSpecialCComment) yyextra->lastSpecialCContext = YY_START; + BEGIN(RemoveSpecialCComment); + } + else + { + // check is to prevent getting stuck in skipping C++ comments + if (YY_START != SkipComment && YY_START != SkipCxxComment) + { + yyextra->lastCContext = YY_START ; + } + startFontClass(yyscanner,"comment"); + yyextra->code->codify(yytext); + BEGIN(SkipComment); + } + } +<*>"/*"[!*]/[^/*] { // special C comment block half way a line if (YY_START==SkipString) REJECT; - if (Config_getBool(STRIP_CODE_COMMENTS)) - { - if (YY_START != RemoveSpecialCComment) yyextra->lastSpecialCContext = YY_START; - BEGIN(RemoveSpecialCComment); - } - else - { - // check is to prevent getting stuck in skipping C++ comments - if (YY_START != SkipComment && YY_START != SkipCxxComment) - { - yyextra->lastCContext = YY_START ; - } - startFontClass(yyscanner,"comment"); - yyextra->code->codify(yytext); - BEGIN(SkipComment); - } - } -<*>"/*"("!"?)"*/" { + if (Config_getBool(STRIP_CODE_COMMENTS)) + { + if (YY_START != RemoveSpecialCComment) yyextra->lastSpecialCContext = YY_START; + BEGIN(RemoveSpecialCComment); + } + else + { + // check is to prevent getting stuck in skipping C++ comments + if (YY_START != SkipComment && YY_START != SkipCxxComment) + { + yyextra->lastCContext = YY_START ; + } + startFontClass(yyscanner,"comment"); + yyextra->code->codify(yytext); + BEGIN(SkipComment); + } + } +<*>"/*"("!"?)"*/" { if (YY_START==SkipString) REJECT; if (!Config_getBool(STRIP_CODE_COMMENTS)) - { - startFontClass(yyscanner,"comment"); - yyextra->code->codify(yytext); - endFontClass(yyscanner); - } - } + { + startFontClass(yyscanner,"comment"); + yyextra->code->codify(yytext); + endFontClass(yyscanner); + } + } <SkipComment>[^\*\n]+ { yyextra->code->codify(yytext); } -<*>"/*" { - startFontClass(yyscanner,"comment"); - yyextra->code->codify(yytext); - // check is to prevent getting stuck in skipping C++ comments - if (YY_START != SkipComment && YY_START != SkipCxxComment) - { - yyextra->lastCContext = YY_START ; - } - BEGIN( SkipComment ) ; - } -<*>@\" { // C# verbatim string - startFontClass(yyscanner,"stringliteral"); - yyextra->code->codify(yytext); - yyextra->lastVerbStringContext=YY_START; - BEGIN(SkipVerbString); - } -<*>"//" { - startFontClass(yyscanner,"comment"); - yyextra->code->codify(yytext); - yyextra->lastCContext = YY_START ; - BEGIN( SkipCxxComment ) ; - } -<*>"("|"[" { - yyextra->code->codify(yytext); - yyextra->theCallContext.pushScope(yyextra->name, yyextra->type); - } -<*>")"|"]" { - yyextra->code->codify(yytext); - yyextra->theCallContext.popScope(yyextra->name, yyextra->type); - } -<*>\n { - yyextra->yyColNr++; - codifyLines(yyscanner,yytext); - } -<*>. { - yyextra->yyColNr++; - yyextra->code->codify(yytext); - } +<*>"/*" { + startFontClass(yyscanner,"comment"); + yyextra->code->codify(yytext); + // check is to prevent getting stuck in skipping C++ comments + if (YY_START != SkipComment && YY_START != SkipCxxComment) + { + yyextra->lastCContext = YY_START ; + } + BEGIN( SkipComment ) ; + } +<*>@\" { // C# verbatim string + startFontClass(yyscanner,"stringliteral"); + yyextra->code->codify(yytext); + yyextra->lastVerbStringContext=YY_START; + BEGIN(SkipVerbString); + } +<*>"//" { + startFontClass(yyscanner,"comment"); + yyextra->code->codify(yytext); + yyextra->lastCContext = YY_START ; + BEGIN( SkipCxxComment ) ; + } +<*>"("|"[" { + yyextra->code->codify(yytext); + yyextra->theCallContext.pushScope(yyextra->name, yyextra->type); + } +<*>")"|"]" { + yyextra->code->codify(yytext); + yyextra->theCallContext.popScope(yyextra->name, yyextra->type); + } +<*>\n { + yyextra->yyColNr++; + codifyLines(yyscanner,yytext); + } +<*>[\x80-\xFF]* { // keep utf8 characters together... + yyextra->yyColNr+=yyleng; + yyextra->code->codify(yytext); + } +<*>. { + yyextra->yyColNr++; + yyextra->code->codify(yytext); + } /* -<*>([ \t\n]*"\n"){2,} { // combine multiple blank lines - //QCString sepLine=yytext; - //yyextra->code->codify("\n\n"); - //yyextra->yyLineNr+=sepLine.contains('\n'); - //char sepLine[3]="\n\n"; - codifyLines(yyscanner,yytext); - } +<*>([ \t\n]*"\n"){2,} { // combine multiple blank lines + //QCString sepLine=yytext; + //yyextra->code->codify("\n\n"); + //yyextra->yyLineNr+=sepLine.contains('\n'); + //char sepLine[3]="\n\n"; + codifyLines(yyscanner,yytext); + } */ %% @@ -2304,13 +2182,13 @@ NUMBER {INTEGER_NUMBER}|{FLOAT_NUMBER} /*@ ---------------------------------------------------------------------------- */ -void VariableContext::addVariable(yyscan_t yyscanner,const QCString &type,const QCString &name) +static void addVariable(yyscan_t yyscanner,QCString type,QCString name) { struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; //printf("VariableContext::addVariable(%s,%s)\n",type.data(),name.data()); QCString ltype = type.simplifyWhiteSpace(); QCString lname = name.simplifyWhiteSpace(); - if (ltype.left(7)=="struct ") + if (ltype.left(7)=="struct ") { ltype = ltype.right(ltype.length()-7); } @@ -2319,94 +2197,53 @@ void VariableContext::addVariable(yyscan_t yyscanner,const QCString &type,const ltype = ltype.right(ltype.length()-6); } if (ltype.isEmpty() || lname.isEmpty()) return; - 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(); - const ClassDef *varType; - int i=0; - if ( - (varType=yyextra->codeClassSDict->find(ltype)) || // look for class definitions inside the code block - (varType=getResolvedClass(yyextra->currentDefinition,yyextra->sourceFileDef,ltype)) // look for global class definitions - ) + DBG_CTX((stderr,"** addVariable trying: type='%s' name='%s' currentDefinition=%s\n", + ltype.data(),lname.data(),yyextra->currentDefinition?yyextra->currentDefinition->name().data():"<none>")); + auto it = yyextra->codeClassMap.find(ltype.str()); + if (it!=yyextra->codeClassMap.end()) // look for class definitions inside the code block { DBG_CTX((stderr,"** addVariable type='%s' name='%s'\n",ltype.data(),lname.data())); - scope->append(lname,varType); // add it to a list - } - else if ((i=ltype.find('<'))!=-1) - { - // probably a template class - QCString typeName(ltype.left(i)); - ClassDef* newDef = 0; - QCString templateArgs(ltype.right(ltype.length() - i)); - if ( !typeName.isEmpty() && - ( // look for class definitions inside the code block - (varType=yyextra->codeClassSDict->find(typeName)) || - // otherwise look for global class definitions - (varType=getResolvedClass(yyextra->currentDefinition,yyextra->sourceFileDef,typeName,0,0,TRUE,TRUE)) - ) && // and it must be a template - !varType->templateArguments().empty()) - { - newDef = varType->getVariableInstance( templateArgs ); - } - if (newDef) - { - DBG_CTX((stderr,"** addVariable type='%s' templ='%s' name='%s'\n",typeName.data(),templateArgs.data(),lname.data())); - scope->append(lname, newDef); - } - else - { - // Doesn't seem to be a template. Try just the base name. - addVariable(yyscanner,typeName,name); - } + yyextra->theVarContext.addVariable(lname,std::move(it->second)); // add it to a list } - else + else { - if (m_scopes.count()>0) // for local variables add a dummy entry so the name - // is hidden to avoid false links to global variables with the same name - // TODO: make this work for namespaces as well! + const ClassDef *varDef = yyextra->symbolResolver.resolveClass(yyextra->currentDefinition,ltype); + int i=0; + if (varDef) { - DBG_CTX((stderr,"** addVariable: dummy context for '%s'\n",lname.data())); - scope->append(lname,dummyContext); + DBG_CTX((stderr,"** addVariable type='%s' name='%s'\n",ltype.data(),lname.data())); + yyextra->theVarContext.addVariable(lname,ScopedTypeVariant(varDef)); // add it to a list } - else + else if ((i=ltype.find('<'))!=-1) { - DBG_CTX((stderr,"** addVariable: not adding variable!\n")); + // probably a template class + QCString typeName(ltype.left(i)); + addVariable(yyscanner,typeName,name); } - } -} - -ClassDef *VariableContext::findVariable(const QCString &name) -{ - if (name.isEmpty()) return 0; - ClassDef *result = 0; - QListIterator<Scope> sli(m_scopes); - Scope *scope; - QCString key = name; - // search from inner to outer scope - for (sli.toLast();(scope=sli.current());--sli) - { - result = scope->find(key); - if (result) + else { - DBG_CTX((stderr,"** findVariable(%s)=%p\n",name.data(),result)); - return result; + if (!yyextra->theVarContext.atGlobalScope()) // for local variables add a dummy entry so the name + // is hidden to avoid false links to global variables with the same name + // TODO: make this work for namespaces as well! + { + DBG_CTX((stderr,"** addVariable: dummy context for '%s'\n",lname.data())); + yyextra->theVarContext.addVariable(lname,ScopedTypeVariant()); + } + else + { + DBG_CTX((stderr,"** addVariable: not adding variable!\n")); + } } } - // nothing found -> also try the global scope - result=m_globalScope.find(name); - DBG_CTX((stderr,"** findVariable(%s)=%p\n",name.data(),result)); - return result; } -const ClassDef *VariableContext::dummyContext = (ClassDef*)0x8; - //------------------------------------------------------------------- /*! add class/namespace name s to the scope */ static void pushScope(yyscan_t yyscanner,const char *s) { struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; - yyextra->classScopeLengthStack.push(new int(yyextra->classScope.length())); + yyextra->classScopeLengthStack.push(int(yyextra->classScope.length())); if (yyextra->classScope.isEmpty() || leftScopeMatch(s,yyextra->classScope)) { yyextra->classScope = s; @@ -2424,11 +2261,11 @@ static void pushScope(yyscan_t yyscanner,const char *s) static void popScope(yyscan_t yyscanner) { struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; - if (!yyextra->classScopeLengthStack.isEmpty()) + if (!yyextra->classScopeLengthStack.empty()) { - int *pLength = yyextra->classScopeLengthStack.pop(); - yyextra->classScope.truncate(*pLength); - delete pLength; + int length = yyextra->classScopeLengthStack.top(); + yyextra->classScopeLengthStack.pop(); + yyextra->classScope.truncate(length); } else { @@ -2442,6 +2279,7 @@ static void setCurrentDoc(yyscan_t yyscanner,const QCString &anchor) struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; if (Doxygen::searchIndex) { + std::lock_guard<std::mutex> lock(g_searchIndexMutex); if (yyextra->searchCtx) { yyextra->code->setCurrentDoc(yyextra->searchCtx,yyextra->searchCtx->anchor(),FALSE); @@ -2458,6 +2296,7 @@ static void addToSearchIndex(yyscan_t yyscanner,const char *text) struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; if (Doxygen::searchIndex) { + std::lock_guard<std::mutex> lock(g_searchIndexMutex); yyextra->code->addWord(text,FALSE); } } @@ -2476,7 +2315,7 @@ static void setClassScope(yyscan_t yyscanner,const QCString &name) // remove template from scope n=n.left(ts)+n.right(n.length()-te-1); } - while (!yyextra->classScopeLengthStack.isEmpty()) + while (!yyextra->classScopeLengthStack.empty()) { popScope(yyscanner); } @@ -2504,7 +2343,7 @@ static void startCodeLine(yyscan_t yyscanner) //QCString lineNumber,lineAnchor; //lineNumber.sprintf("%05d",yyextra->yyLineNr); //lineAnchor.sprintf("l%05d",yyextra->yyLineNr); - + Definition *d = yyextra->sourceFileDef->getSourceDefinition(yyextra->yyLineNr); //printf("%s:startCodeLine(%d)=%p\n",yyextra->sourceFileDef->name().data(),yyextra->yyLineNr,d); if (!yyextra->includeCodeFragment && d) @@ -2527,15 +2366,15 @@ static void startCodeLine(yyscan_t yyscanner) if (yyextra->currentMemberDef) { yyextra->code->writeLineNumber(yyextra->currentMemberDef->getReference(), - yyextra->currentMemberDef->getOutputFileBase(), - yyextra->currentMemberDef->anchor(),yyextra->yyLineNr); + yyextra->currentMemberDef->getOutputFileBase(), + yyextra->currentMemberDef->anchor(),yyextra->yyLineNr); setCurrentDoc(yyscanner,lineAnchor); } else if (d->isLinkableInProject()) { yyextra->code->writeLineNumber(d->getReference(), - d->getOutputFileBase(), - 0,yyextra->yyLineNr); + d->getOutputFileBase(), + 0,yyextra->yyLineNr); setCurrentDoc(yyscanner,lineAnchor); } } @@ -2545,7 +2384,7 @@ static void startCodeLine(yyscan_t yyscanner) } } DBG_CTX((stderr,"startCodeLine(%d)\n",yyextra->yyLineNr)); - yyextra->code->startCodeLine(yyextra->sourceFileDef && yyextra->lineNumbers); + yyextra->code->startCodeLine(yyextra->sourceFileDef && yyextra->lineNumbers); if (yyextra->currentFontClass) { yyextra->code->startFontClass(yyextra->currentFontClass); @@ -2567,7 +2406,7 @@ static void nextCodeLine(yyscan_t yyscanner) struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; const char * fc = yyextra->currentFontClass; endCodeLine(yyscanner); - if (yyextra->yyLineNr<yyextra->inputLines) + if (yyextra->yyLineNr<yyextra->inputLines) { yyextra->currentFontClass = fc; startCodeLine(yyscanner); @@ -2592,7 +2431,6 @@ static void codifyLines(yyscan_t yyscanner,const char *text) { yyextra->yyLineNr++; yyextra->yyColNr=1; - //*(p-1)='\0'; int l = (int)(p-sp-1); char *tmp = (char*)malloc(l+1); memcpy(tmp,sp,l); @@ -2609,8 +2447,22 @@ static void codifyLines(yyscan_t yyscanner,const char *text) } } +static void incrementFlowKeyWordCount(yyscan_t yyscanner) +{ + std::lock_guard<std::mutex> lock(g_countFlowKeywordsMutex); + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + if (yyextra->currentMemberDef && yyextra->currentMemberDef->isFunction()) + { + MemberDefMutable *md = toMemberDefMutable(yyextra->currentMemberDef); + if (md) + { + md->incrementFlowKeyWordCount(); + } + } +} + /*! writes a link to a fragment \a text that may span multiple lines, inserting - * line numbers for each line. If \a text contains newlines, the link will be + * line numbers for each line. If \a text contains newlines, the link will be * split into multiple links with the same destination, one for each line. */ static void writeMultiLineCodeLink(yyscan_t yyscanner,CodeOutputInterface &ol, @@ -2618,12 +2470,12 @@ static void writeMultiLineCodeLink(yyscan_t yyscanner,CodeOutputInterface &ol, const char *text) { struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; - static bool sourceTooltips = Config_getBool(SOURCE_TOOLTIPS); - TooltipManager::instance()->addTooltip(d); + bool sourceTooltips = Config_getBool(SOURCE_TOOLTIPS); + TooltipManager::instance().addTooltip(ol,d); QCString ref = d->getReference(); QCString file = d->getOutputFileBase(); QCString anchor = d->anchor(); - QCString tooltip; + QCString tooltip; if (!sourceTooltips) // fall back to simple "title" tooltips { tooltip = d->briefDescriptionAsTooltip(); @@ -2678,7 +2530,7 @@ static void addUsingDirective(yyscan_t yyscanner,const char *name) struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; if (yyextra->sourceFileDef && name) { - NamespaceDef *nd = Doxygen::namespaceSDict->find(name); + const NamespaceDef *nd = Doxygen::namespaceSDict->find(name); if (nd) { yyextra->sourceFileDef->addUsingDirective(nd); @@ -2700,11 +2552,11 @@ static void setParameterList(yyscan_t yyscanner,const MemberDef *md) if (i!=-1) yyextra->parmType = yyextra->parmType.left(i); yyextra->parmType.stripPrefix("const "); yyextra->parmType=yyextra->parmType.stripWhiteSpace(); - yyextra->theVarContext.addVariable(yyscanner,yyextra->parmType,yyextra->parmName); + addVariable(yyscanner,yyextra->parmType,yyextra->parmName); } } -static const ClassDef *stripClassName(yyscan_t yyscanner,const char *s,Definition *d) +static const ClassDef *stripClassName(yyscan_t yyscanner,const char *s,const Definition *d) { struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; int pos=0; @@ -2717,11 +2569,11 @@ static const ClassDef *stripClassName(yyscan_t yyscanner,const char *s,Definitio const ClassDef *cd=0; if (!yyextra->classScope.isEmpty()) { - cd=getResolvedClass(d,yyextra->sourceFileDef,yyextra->classScope+"::"+clName); + cd=yyextra->symbolResolver.resolveClass(d,yyextra->classScope+"::"+clName); } if (cd==0) { - cd=getResolvedClass(d,yyextra->sourceFileDef,clName); + cd=yyextra->symbolResolver.resolveClass(d,clName); } //printf("stripClass trying '%s' = %p\n",clName.data(),cd); if (cd) @@ -2733,7 +2585,7 @@ static const ClassDef *stripClassName(yyscan_t yyscanner,const char *s,Definitio return 0; } -static MemberDef *setCallContextForVar(yyscan_t yyscanner,const QCString &name) +static const MemberDef *setCallContextForVar(yyscan_t yyscanner,const QCString &name) { if (name.isEmpty()) return 0; struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; @@ -2745,14 +2597,14 @@ static MemberDef *setCallContextForVar(yyscan_t yyscanner,const QCString &name) QCString scope = name.left(scopeEnd); QCString locName = name.right(name.length()-scopeEnd-2); //printf("explicit scope: name=%s scope=%s\n",locName.data(),scope.data()); - ClassDef *mcd = getClass(scope); + const ClassDef *mcd = getClass(scope); if (mcd && !locName.isEmpty()) { MemberDef *md=mcd->getMemberByName(locName); if (md) { //printf("name=%s scope=%s\n",locName.data(),scope.data()); - yyextra->theCallContext.setScope(stripClassName(yyscanner,md->typeString(),md->getOuterScope())); + yyextra->theCallContext.setScope(ScopedTypeVariant(stripClassName(yyscanner,md->typeString(),md->getOuterScope()))); return md; } } @@ -2761,46 +2613,46 @@ static MemberDef *setCallContextForVar(yyscan_t yyscanner,const QCString &name) const NamespaceDef *mnd = getResolvedNamespace(scope); if (mnd && !locName.isEmpty()) { - MemberDef *md=mnd->getMemberByName(locName); - if (md) - { - //printf("name=%s scope=%s\n",locName.data(),scope.data()); - yyextra->theCallContext.setScope(stripClassName(yyscanner,md->typeString(),md->getOuterScope())); - return md; - } + MemberDef *md=mnd->getMemberByName(locName); + if (md) + { + //printf("name=%s scope=%s\n",locName.data(),scope.data()); + yyextra->theCallContext.setScope(ScopedTypeVariant(stripClassName(yyscanner,md->typeString(),md->getOuterScope()))); + return md; + } } } } - - MemberName *mn; - ClassDef *mcd = yyextra->theVarContext.findVariable(name); - if (mcd) // local variable + + const MemberName *mn; + const ScopedTypeVariant *mcv = yyextra->theVarContext.findVariable(name); + if (mcv) { DBG_CTX((stderr,"local variable?\n")); - if (mcd!=VariableContext::dummyContext) + if (mcv->type()!=ScopedTypeVariant::Dummy) // locally found variable { - DBG_CTX((stderr,"local var '%s' mcd=%s\n",name.data(),mcd->name().data())); - yyextra->theCallContext.setScope(mcd); + DBG_CTX((stderr,"local var '%s' mcd=%s\n",name.data(),mcv->name().data())); + yyextra->theCallContext.setScope(*mcv); } } else { DBG_CTX((stderr,"class member? scope=%s\n",yyextra->classScope.data())); - // look for a class member - mcd = getClass(yyextra->classScope); + // look for a class member + const ClassDef *mcd = getClass(yyextra->classScope); if (mcd) { DBG_CTX((stderr,"Inside class %s\n",mcd->name().data())); - MemberDef *md=mcd->getMemberByName(name); - if (md) + const MemberDef *md=mcd->getMemberByName(name); + if (md) { DBG_CTX((stderr,"Found member %s\n",md->name().data())); - if (yyextra->scopeStack.top()!=CLASSBLOCK) - { + if (yyextra->scopeStack.empty() || yyextra->scopeStack.top()!=CLASSBLOCK) + { DBG_CTX((stderr,"class member '%s' mcd=%s\n",name.data(),mcd->name().data())); - yyextra->theCallContext.setScope(stripClassName(yyscanner,md->typeString(),md->getOuterScope())); - } - return md; + yyextra->theCallContext.setScope(ScopedTypeVariant(stripClassName(yyscanner,md->typeString(),md->getOuterScope()))); + } + return md; } } } @@ -2814,7 +2666,7 @@ static MemberDef *setCallContextForVar(yyscan_t yyscanner,const QCString &name) const std::unique_ptr<MemberDef> &md=mn->front(); if (!md->isStatic() || md->getBodyDef()==yyextra->sourceFileDef) { - yyextra->theCallContext.setScope(stripClassName(yyscanner,md->typeString(),md->getOuterScope())); + yyextra->theCallContext.setScope(ScopedTypeVariant(stripClassName(yyscanner,md->typeString(),md->getOuterScope()))); return md.get(); } return 0; @@ -2823,19 +2675,17 @@ static MemberDef *setCallContextForVar(yyscan_t yyscanner,const QCString &name) { for (const auto &md : *mn) { - //printf("mn=%p md=%p md->getBodyDef()=%p yyextra->sourceFileDef=%p\n", - // mn,md, - // md->getBodyDef(),yyextra->sourceFileDef); - - // in case there are multiple members we could link to, we - // only link to members if defined in the same file or - // defined as external. - if ((!md->isStatic() || md->getBodyDef()==yyextra->sourceFileDef) && - (yyextra->forceTagReference.isEmpty() || yyextra->forceTagReference==md->getReference()) - ) + //printf("mn=%p md=%p md->getBodyDef()=%p yyextra->sourceFileDef=%p\n", + // mn,md, + // md->getBodyDef(),yyextra->sourceFileDef); + + // in case there are multiple members we could link to, we + // only link to members if defined in the same file or + // defined as external. + if (!md->isStatic() || md->getBodyDef()==yyextra->sourceFileDef) { - yyextra->theCallContext.setScope(stripClassName(yyscanner,md->typeString(),md->getOuterScope())); - //printf("returning member %s in source file %s\n",md->name().data(),yyextra->sourceFileDef->name().data()); + yyextra->theCallContext.setScope(ScopedTypeVariant(stripClassName(yyscanner,md->typeString(),md->getOuterScope()))); + //printf("returning member %s in source file %s\n",md->name().data(),yyextra->sourceFileDef->name().data()); return md.get(); } } @@ -2848,15 +2698,15 @@ static MemberDef *setCallContextForVar(yyscan_t yyscanner,const QCString &name) static void updateCallContextForSmartPointer(yyscan_t yyscanner) { struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; - const Definition *d = yyextra->theCallContext.getScope(); + const Definition *d = yyextra->theCallContext.getScope().globalDef(); //printf("updateCallContextForSmartPointer() cd=%s\n",cd ? d->name().data() : "<none>"); - MemberDef *md; - if (d && d->definitionType()==Definition::TypeClass && (md=(dynamic_cast<const ClassDef*>(d))->isSmartPointer())) + const MemberDef *md; + if (d && d->definitionType()==Definition::TypeClass && (md=(toClassDef(d))->isSmartPointer())) { const ClassDef *ncd = stripClassName(yyscanner,md->typeString(),md->getOuterScope()); if (ncd) { - yyextra->theCallContext.setScope(ncd); + yyextra->theCallContext.setScope(ScopedTypeVariant(ncd)); //printf("Found smart pointer call %s->%s!\n",cd->name().data(),ncd->name().data()); } } @@ -2865,11 +2715,11 @@ static void updateCallContextForSmartPointer(yyscan_t yyscanner) static bool getLinkInScope(yyscan_t yyscanner, const QCString &c, // scope const QCString &m, // member - const char *memberText, // exact text - CodeOutputInterface &ol, - const char *text, - bool varOnly - ) + const char *memberText, // exact text + CodeOutputInterface &ol, + const char *text, + bool varOnly + ) { struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; const MemberDef *md = 0; @@ -2878,7 +2728,7 @@ static bool getLinkInScope(yyscan_t yyscanner, 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,yyextra->sourceFileDef,FALSE,yyextra->forceTagReference) && + if (getDefs(c,m,"()",md,cd,fd,nd,gd,FALSE,yyextra->sourceFileDef,FALSE) && (!varOnly || md->isVariable())) { if (md->isLinkable()) @@ -2886,11 +2736,13 @@ static bool getLinkInScope(yyscan_t yyscanner, //printf("found it %s!\n",md->qualifiedName().data()); if (yyextra->exampleBlock) { + std::lock_guard<std::mutex> lock(g_addExampleMutex); QCString anchor; anchor.sprintf("a%d",yyextra->anchorCount); //printf("addExampleFile(%s,%s,%s)\n",anchor.data(),yyextra->exampleName.data(), // yyextra->exampleFile.data()); - if (const_cast<MemberDef*>(md)->addExample(anchor,yyextra->exampleName,yyextra->exampleFile)) + MemberDefMutable *mdm = toMemberDefMutable(md); + if (mdm && mdm->addExample(anchor,yyextra->exampleName,yyextra->exampleFile)) { ol.writeCodeAnchor(anchor); yyextra->anchorCount++; @@ -2902,14 +2754,15 @@ static bool getLinkInScope(yyscan_t yyscanner, if (md->resolveAlias()->getGroupDef()) d = md->resolveAlias()->getGroupDef(); if (d && d->isLinkable()) { - yyextra->theCallContext.setScope(stripClassName(yyscanner,md->typeString(),md->getOuterScope())); + yyextra->theCallContext.setScope(ScopedTypeVariant(stripClassName(yyscanner,md->typeString(),md->getOuterScope()))); //printf("yyextra->currentDefinition=%p yyextra->currentMemberDef=%p yyextra->insideBody=%d\n", // yyextra->currentDefinition,yyextra->currentMemberDef,yyextra->insideBody); if (yyextra->currentDefinition && yyextra->currentMemberDef && md!=yyextra->currentMemberDef && yyextra->insideBody && yyextra->collectXRefs) { - addDocCrossReference(yyextra->currentMemberDef,const_cast<MemberDef*>(md)); + std::lock_guard<std::mutex> lock(g_docCrossReferenceMutex); + addDocCrossReference(toMemberDefMutable(yyextra->currentMemberDef),toMemberDefMutable(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()); @@ -2931,9 +2784,9 @@ static bool getLinkInScope(yyscan_t yyscanner, static bool getLink(yyscan_t yyscanner, const char *className, const char *memberName, - CodeOutputInterface &ol, - const char *text, - bool varOnly) + CodeOutputInterface &ol, + const char *text, + bool varOnly) { struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; //printf("getLink(%s,%s) yyextra->curClassName=%s\n",className,memberName,yyextra->curClassName.data()); @@ -2979,18 +2832,20 @@ static void generateClassOrGlobalLink(yyscan_t yyscanner, { className = substitute(className,".","::"); // for PHP namespaces } - const ClassDef *cd=0,*lcd=0; + const ScopedTypeVariant *lcd=0; + const ClassDef *cd=0; const MemberDef *md=0; bool isLocal=FALSE; //printf("generateClassOrGlobalLink(className=%s)\n",className.data()); - if (!yyextra->prefixed_with_this_keyword || (lcd=yyextra->theVarContext.findVariable(className))==0) // not a local variable + if (!yyextra->isPrefixedWithThis || (lcd=yyextra->theVarContext.findVariable(className))==0) // not a local variable { - Definition *d = yyextra->currentDefinition; + const Definition *d = yyextra->currentDefinition; //printf("d=%s yyextra->sourceFileDef=%s\n",d?d->name().data():"<none>",yyextra->sourceFileDef?yyextra->sourceFileDef->name().data():"<none>"); - cd = getResolvedClass(d,yyextra->sourceFileDef,className,&md); - DBG_CTX((stderr,"non-local variable name=%s context=%d cd=%s md=%s!\n", - className.data(),yyextra->theVarContext.count(),cd?cd->name().data():"<none>", + cd = yyextra->symbolResolver.resolveClass(d,className); + md = yyextra->symbolResolver.getTypedef(); + DBG_CTX((stderr,"non-local variable name=%s cd=%s md=%s!\n", + className.data(),cd?cd->name().data():"<none>", md?md->name().data():"<none>")); if (cd==0 && md==0 && (i=className.find('<'))!=-1) { @@ -2998,13 +2853,14 @@ static void generateClassOrGlobalLink(yyscan_t yyscanner, DBG_CTX((stderr,"bareName=%s\n",bareName.data())); if (bareName!=className) { - cd=getResolvedClass(d,yyextra->sourceFileDef,bareName,&md); // try unspecialized version + cd = yyextra->symbolResolver.resolveClass(d,bareName); // try unspecialized version + md = yyextra->symbolResolver.getTypedef(); } } const NamespaceDef *nd = getResolvedNamespace(className); if (nd && nd->isLinkable()) { - yyextra->theCallContext.setScope(nd); + yyextra->theCallContext.setScope(ScopedTypeVariant(nd)); addToSearchIndex(yyscanner,className); writeMultiLineCodeLink(yyscanner,*yyextra->code,nd,clName); return; @@ -3017,58 +2873,61 @@ static void generateClassOrGlobalLink(yyscan_t yyscanner, { if (getLink(yyscanner,yyextra->classScope,clName,ol,clName,varOnly)) { - return; + return; } } } else { //printf("local variable!\n"); - if (lcd!=VariableContext::dummyContext) + if (lcd->type()!=ScopedTypeVariant::Dummy) { //printf("non-dummy context lcd=%s!\n",lcd->name().data()); - yyextra->theCallContext.setScope(lcd); + yyextra->theCallContext.setScope(*lcd); // to following is needed for links to a global variable, but is // no good for a link to a local variable that is also a global symbol. - + //if (getLink(yyscanner,yyextra->classScope,clName,ol,clName)) //{ - //return; + //return; //} } isLocal=TRUE; DBG_CTX((stderr,"is a local variable cd=%p!\n",cd)); } - yyextra->prefixed_with_this_keyword = FALSE; // discard the "this" prefix for the next calls + yyextra->isPrefixedWithThis = FALSE; // discard the "this" prefix for the next calls if (cd && cd->isLinkable()) // is it a linkable class { DBG_CTX((stderr,"is linkable class %s\n",clName)); if (yyextra->exampleBlock) { + std::lock_guard<std::mutex> lock(g_addExampleMutex); QCString anchor; anchor.sprintf("_a%d",yyextra->anchorCount); //printf("addExampleClass(%s,%s,%s)\n",anchor.data(),yyextra->exampleName.data(), // yyextra->exampleFile.data()); - if (const_cast<ClassDef*>(cd)->addExample(anchor,yyextra->exampleName,yyextra->exampleFile)) + ClassDefMutable *cdm = toClassDefMutable(const_cast<ClassDef*>(cd)); + if (cdm && cdm->addExample(anchor,yyextra->exampleName,yyextra->exampleFile)) { - ol.writeCodeAnchor(anchor); - yyextra->anchorCount++; + ol.writeCodeAnchor(anchor); + yyextra->anchorCount++; } } writeMultiLineCodeLink(yyscanner,ol,cd,clName); addToSearchIndex(yyscanner,className); - yyextra->theCallContext.setScope(cd); + yyextra->theCallContext.setScope(ScopedTypeVariant(cd)); if (md) { const Definition *d = md->getOuterScope()==Doxygen::globalScope ? md->getFileDef() : md->getOuterScope(); if (md->getGroupDef()) d = md->getGroupDef(); - if (d && d->isLinkable() && md->isLinkable() && + if (d && d->isLinkable() && md->isLinkable() && yyextra->currentMemberDef && yyextra->collectXRefs) { - addDocCrossReference(yyextra->currentMemberDef,const_cast<MemberDef*>(md)); + std::lock_guard<std::mutex> lock(g_docCrossReferenceMutex); + addDocCrossReference(toMemberDefMutable(yyextra->currentMemberDef),toMemberDefMutable(md)); } } } @@ -3079,55 +2938,40 @@ static void generateClassOrGlobalLink(yyscan_t yyscanner, { if (md==0) // not found as a typedef { - md = setCallContextForVar(yyscanner,clName); - //printf("setCallContextForVar(%s) md=%p yyextra->currentDefinition=%p\n",clName,md,yyextra->currentDefinition); - if (md && yyextra->currentDefinition) - { - DBG_CTX((stderr,"%s accessible from %s? %d md->getOuterScope=%s\n", - md->name().data(),yyextra->currentDefinition->name().data(), - isAccessibleFrom(yyextra->currentDefinition,yyextra->sourceFileDef,md), - md->getOuterScope()->name().data())); - } - - if (md && yyextra->currentDefinition && - isAccessibleFrom(yyextra->currentDefinition,yyextra->sourceFileDef,md)==-1) - { - md=0; // variable not accessible - } + md = setCallContextForVar(yyscanner,clName); + //printf("setCallContextForVar(%s) md=%p yyextra->currentDefinition=%p\n",clName,md,yyextra->currentDefinition); + if (md && yyextra->currentDefinition) + { + DBG_CTX((stderr,"%s accessible from %s? %d md->getOuterScope=%s\n", + md->name().data(),yyextra->currentDefinition->name().data(), + yyextra->symbolResolver.isAccessibleFrom(yyextra->currentDefinition,md), + md->getOuterScope()->name().data())); + } + + if (md && yyextra->currentDefinition && + yyextra->symbolResolver.isAccessibleFrom(yyextra->currentDefinition,md)==-1) + { + md=0; // variable not accessible + } } if (md && (!varOnly || md->isVariable())) { DBG_CTX((stderr,"is a global md=%p yyextra->currentDefinition=%s linkable=%d\n",md,yyextra->currentDefinition?yyextra->currentDefinition->name().data():"<none>",md->isLinkable())); - if (md->isLinkable()) - { - QCString text; - if (!yyextra->forceTagReference.isEmpty()) // explicit reference to symbol in tag file - { - text=yyextra->forceTagReference; - if (text.right(4)==".tag") // strip .tag if present - { - text=text.left(text.length()-4); - } - text+=getLanguageSpecificSeparator(md->getLanguage()); - text+=clName; - const_cast<MemberDef*>(md)->setName(text); - const_cast<MemberDef*>(md)->setLocalName(text); - } - else // normal reference - { - text=clName; - } - writeMultiLineCodeLink(yyscanner,ol,md,text); + if (md->isLinkable()) + { + QCString text=clName; + writeMultiLineCodeLink(yyscanner,ol,md,text); addToSearchIndex(yyscanner,clName); - if (yyextra->currentMemberDef && yyextra->collectXRefs) - { - addDocCrossReference(yyextra->currentMemberDef,const_cast<MemberDef*>(md)); - } - return; - } + if (yyextra->currentMemberDef && yyextra->collectXRefs) + { + std::lock_guard<std::mutex> lock(g_docCrossReferenceMutex); + addDocCrossReference(toMemberDefMutable(yyextra->currentMemberDef),toMemberDefMutable(md)); + } + return; + } } } - + // nothing found, just write out the word DBG_CTX((stderr,"not found!\n")); codifyLines(yyscanner,clName); @@ -3150,11 +2994,13 @@ static bool generateClassMemberLink(yyscan_t yyscanner, if (yyextra->exampleBlock) { + std::lock_guard<std::mutex> lock(g_addExampleMutex); QCString anchor; anchor.sprintf("a%d",yyextra->anchorCount); //printf("addExampleFile(%s,%s,%s)\n",anchor.data(),yyextra->exampleName.data(), // yyextra->exampleFile.data()); - if (xmd->addExample(anchor,yyextra->exampleName,yyextra->exampleFile)) + MemberDefMutable *mdm = toMemberDefMutable(xmd); + if (mdm && mdm->addExample(anchor,yyextra->exampleName,yyextra->exampleFile)) { ol.writeCodeAnchor(anchor); yyextra->anchorCount++; @@ -3163,7 +3009,7 @@ static bool generateClassMemberLink(yyscan_t yyscanner, const ClassDef *typeClass = stripClassName(yyscanner,removeAnonymousScopes(xmd->typeString()),xmd->getOuterScope()); DBG_CTX((stderr,"%s -> typeName=%p\n",xmd->typeString(),typeClass)); - yyextra->theCallContext.setScope(typeClass); + yyextra->theCallContext.setScope(ScopedTypeVariant(typeClass)); const Definition *xd = xmd->getOuterScope()==Doxygen::globalScope ? xmd->getFileDef() : xmd->getOuterScope(); @@ -3179,9 +3025,10 @@ static bool generateClassMemberLink(yyscan_t yyscanner, { // add usage reference if (yyextra->currentDefinition && yyextra->currentMemberDef && - /*xmd!=yyextra->currentMemberDef &&*/ yyextra->insideBody && yyextra->collectXRefs) + /*xmd!=yyextra->currentMemberDef &&*/ yyextra->insideBody && yyextra->collectXRefs) { - addDocCrossReference(yyextra->currentMemberDef,xmd); + std::lock_guard<std::mutex> lock(g_docCrossReferenceMutex); + addDocCrossReference(toMemberDefMutable(yyextra->currentMemberDef),toMemberDefMutable(xmd)); } // write the actual link @@ -3202,7 +3049,7 @@ static bool generateClassMemberLink(yyscan_t yyscanner, struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; if (def && def->definitionType()==Definition::TypeClass) { - const ClassDef *cd = dynamic_cast<const ClassDef*>(def); + const ClassDef *cd = toClassDef(def); MemberDef *xmd = cd->getMemberByName(memName); //printf("generateClassMemberLink(class=%s,member=%s)=%p\n",def->name().data(),memName,xmd); if (xmd) @@ -3211,10 +3058,10 @@ static bool generateClassMemberLink(yyscan_t yyscanner, } else { - Definition *innerDef = cd->findInnerCompound(memName); + const Definition *innerDef = cd->findInnerCompound(memName); if (innerDef) { - yyextra->theCallContext.setScope(innerDef); + yyextra->theCallContext.setScope(ScopedTypeVariant(innerDef)); addToSearchIndex(yyscanner,memName); writeMultiLineCodeLink(yyscanner,*yyextra->code,innerDef,memName); return TRUE; @@ -3223,12 +3070,12 @@ static bool generateClassMemberLink(yyscan_t yyscanner, } else if (def && def->definitionType()==Definition::TypeNamespace) { - const NamespaceDef *nd = dynamic_cast<const NamespaceDef*>(def); + const NamespaceDef *nd = toNamespaceDef(def); //printf("Looking for %s inside namespace %s\n",memName,nd->name().data()); - Definition *innerDef = nd->findInnerCompound(memName); + const Definition *innerDef = nd->findInnerCompound(memName); if (innerDef) { - yyextra->theCallContext.setScope(innerDef); + yyextra->theCallContext.setScope(ScopedTypeVariant(innerDef)); addToSearchIndex(yyscanner,memName); writeMultiLineCodeLink(yyscanner,*yyextra->code,innerDef,memName); return TRUE; @@ -3249,80 +3096,79 @@ static void generateMemberLink(yyscan_t yyscanner, if (varName.isEmpty()) return; // look for the variable in the current context - const ClassDef *vcd = yyextra->theVarContext.findVariable(varName); - if (vcd) + const ScopedTypeVariant *stv = yyextra->theVarContext.findVariable(varName); + if (stv) { - if (vcd!=VariableContext::dummyContext) + if (stv->type()!=ScopedTypeVariant::Dummy) { //printf("Class found!\n"); - if (getLink(yyscanner,vcd->name(),memName,ol)) + if (getLink(yyscanner,stv->name(),memName,ol)) { - //printf("Found result!\n"); - return; + //printf("Found result!\n"); + return; } - if (vcd->baseClasses()) + if (stv->localDef() && !stv->localDef()->baseClasses().empty()) { - BaseClassListIterator bcli(*vcd->baseClasses()); - for ( ; bcli.current() ; ++bcli) - { - if (getLink(yyscanner,bcli.current()->classDef->name(),memName,ol)) - { - //printf("Found result!\n"); - return; - } - } + for (const auto &bcName : stv->localDef()->baseClasses()) + { + if (getLink(yyscanner,bcName,memName,ol)) + { + //printf("Found result!\n"); + return; + } + } } } } else // variable not in current context, maybe it is in a parent context { - vcd = getResolvedClass(yyextra->currentDefinition,yyextra->sourceFileDef,yyextra->classScope); + const ClassDef *vcd = yyextra->symbolResolver.resolveClass(yyextra->currentDefinition,yyextra->classScope); if (vcd && vcd->isLinkable()) { //printf("Found class %s for variable '%s'\n",yyextra->classScope.data(),varName.data()); MemberName *vmn=Doxygen::memberNameLinkedMap->find(varName); if (vmn==0) { - int vi; - QCString vn=varName; - if ((vi=vn.findRev("::"))!=-1 || (vi=vn.findRev('.'))!=-1) // explicit scope A::b(), probably static member - { - ClassDef *jcd = getClass(vn.left(vi)); - vn=vn.right(vn.length()-vi-2); - vmn=Doxygen::memberNameLinkedMap->find(vn); - //printf("Trying name '%s' scope=%s\n",vn.data(),scope.data()); - if (vmn) - { + int vi; + QCString vn=varName; + if ((vi=vn.findRev("::"))!=-1 || (vi=vn.findRev('.'))!=-1) // explicit scope A::b(), probably static member + { + const ClassDef *jcd = getClass(vn.left(vi)); + vn=vn.right(vn.length()-vi-2); + vmn=Doxygen::memberNameLinkedMap->find(vn); + //printf("Trying name '%s' scope=%s\n",vn.data(),scope.data()); + if (vmn) + { for (const auto &vmd : *vmn) - { - if (vmd->getClassDef()==jcd) - { - //printf("Found variable type=%s\n",vmd->typeString()); - const ClassDef *mcd=stripClassName(yyscanner,vmd->typeString(),vmd->getOuterScope()); - if (mcd && mcd->isLinkable()) - { - if (generateClassMemberLink(yyscanner,ol,mcd,memName)) return; - } - } - } - } - } + { + if (vmd->getClassDef()==jcd) + { + //printf("Found variable type=%s\n",vmd->typeString()); + const ClassDef *mcd=stripClassName(yyscanner,vmd->typeString(),vmd->getOuterScope()); + if (mcd && mcd->isLinkable()) + { + if (generateClassMemberLink(yyscanner,ol,mcd,memName)) return; + } + } + } + } + } } if (vmn) { - //printf("There is a variable with name '%s'\n",varName); + //printf("There is a variable with name '%s'\n",varName); for (const auto &vmd : *vmn) - { - if (vmd->getClassDef()==vcd) - { - //printf("Found variable type=%s\n",vmd->typeString()); - const ClassDef *mcd=stripClassName(yyscanner,vmd->typeString(),vmd->getOuterScope()); - if (mcd && mcd->isLinkable()) - { - if (generateClassMemberLink(yyscanner,ol,mcd,memName)) return; - } - } - } + { + if (vmd->getClassDef()==vcd) + { + //printf("Found variable type=%s\n",vmd->typeString()); + const ClassDef *mcd=stripClassName(yyscanner,vmd->typeString(),vmd->getOuterScope()); + if (mcd && mcd->isLinkable()) + { + if (generateClassMemberLink(yyscanner,ol,mcd,memName)) return; + } + } + } } } } @@ -3348,7 +3194,6 @@ static void generateFunctionLink(yyscan_t yyscanner,CodeOutputInterface &ol,cons { struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; //CodeClassDef *ccd=0; - ClassDef *ccd=0; QCString locScope=yyextra->classScope; QCString locFunc=removeRedundantWhiteSpace(funcName); if (yyextra->lang==SrcLangExt_PHP && locFunc.startsWith("self::")) locFunc=locFunc.mid(4); @@ -3360,13 +3205,13 @@ static void generateFunctionLink(yyscan_t yyscanner,CodeOutputInterface &ol,cons int len=2; int i=locFunc.findRev("::"); if (yyextra->currentMemberDef && yyextra->currentMemberDef->resolveAlias()->getClassDef() && - funcName==yyextra->currentMemberDef->localName() && + funcName==yyextra->currentMemberDef->localName() && yyextra->currentMemberDef->getDefLine()==yyextra->yyLineNr && generateClassMemberLink(yyscanner,ol,yyextra->currentMemberDef,funcName) ) { // special case where funcName is the name of a method that is also - // defined on this line. In this case we can directly link to + // defined on this line. In this case we can directly link to // yyextra->currentMemberDef, which is not only faster, but // in case of overloaded methods, this will make sure that we link to // the correct method, and thereby get the correct reimplemented relations. @@ -3408,33 +3253,41 @@ static void generateFunctionLink(yyscan_t yyscanner,CodeOutputInterface &ol,cons funcWithFullScope = locScope+"::"+funcWithScope; } } - if (!fullScope.isEmpty() && (ccd=yyextra->codeClassSDict->find(fullScope))) + + if (!fullScope.isEmpty()) { - //printf("using classScope %s\n",yyextra->classScope.data()); - if (ccd->baseClasses()) + auto it = yyextra->codeClassMap.find(fullScope.str()); + if (it!=yyextra->codeClassMap.end()) { - BaseClassListIterator bcli(*ccd->baseClasses()); - for ( ; bcli.current() ; ++bcli) + ScopedTypeVariant ccd = it->second; + if (ccd.localDef() && !ccd.localDef()->baseClasses().empty()) { - if (getLink(yyscanner,bcli.current()->classDef->name(),locFunc,ol,funcName)) - { - goto exit; - } + for (const auto &bcName : ccd.localDef()->baseClasses()) + { + if (getLink(yyscanner,bcName,locFunc,ol,funcName)) + { + goto exit; + } + } } } } - if (!locScope.isEmpty() && fullScope!=locScope && (ccd=yyextra->codeClassSDict->find(locScope))) + + if (!locScope.isEmpty() && fullScope!=locScope) { - //printf("using classScope %s\n",yyextra->classScope.data()); - if (ccd->baseClasses()) + auto it = yyextra->codeClassMap.find(locScope.str()); + if (it!=yyextra->codeClassMap.end()) { - BaseClassListIterator bcli(*ccd->baseClasses()); - for ( ; bcli.current() ; ++bcli) + ScopedTypeVariant ccd = it->second; + if (ccd.localDef() && !ccd.localDef()->baseClasses().empty()) { - if (getLink(yyscanner,bcli.current()->classDef->name(),funcWithScope,ol,funcName)) - { - goto exit; - } + for (const auto &bcName : ccd.localDef()->baseClasses()) + { + if (getLink(yyscanner,bcName,funcWithScope,ol,funcName)) + { + goto exit; + } + } } } } @@ -3442,8 +3295,7 @@ static void generateFunctionLink(yyscan_t yyscanner,CodeOutputInterface &ol,cons { generateClassOrGlobalLink(yyscanner,ol,funcName); } -exit: - yyextra->forceTagReference.resize(0); +exit: return; } @@ -3454,17 +3306,17 @@ static int countLines(yyscan_t yyscanner) const char *p=yyextra->inputString; char c; int count=1; - while ((c=*p)) - { - p++ ; - if (c=='\n') count++; + while ((c=*p)) + { + p++ ; + if (c=='\n') count++; } - if (p>yyextra->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++, - yyextra->needsTermination=TRUE; - } + count++, + yyextra->needsTermination=TRUE; + } return count; } @@ -3502,62 +3354,63 @@ static void writeObjCMethodCall(yyscan_t yyscanner,ObjCCallCtx *ctx) if (!ctx->objectTypeOrName.isEmpty() && ctx->objectTypeOrName.at(0)!='$') { //printf("Looking for object=%s method=%s\n",ctx->objectTypeOrName.data(), - // ctx->methodName.data()); - ClassDef *cd = yyextra->theVarContext.findVariable(ctx->objectTypeOrName); - if (cd==0) // not a local variable + // ctx->methodName.data()); + const ScopedTypeVariant *stv = yyextra->theVarContext.findVariable(ctx->objectTypeOrName); + if (stv==0) // not a local variable { - if (ctx->objectTypeOrName=="self") - { - if (yyextra->currentDefinition && - yyextra->currentDefinition->definitionType()==Definition::TypeClass) - { - ctx->objectType = dynamic_cast<ClassDef *>(yyextra->currentDefinition); - } - } - else - { - ctx->objectType = getResolvedClass( - yyextra->currentDefinition, - yyextra->sourceFileDef, - ctx->objectTypeOrName, - &ctx->method); - } - //printf(" object is class? %p\n",ctx->objectType); - if (ctx->objectType) // found class - { - ctx->method = ctx->objectType->getMemberByName(ctx->methodName); - //printf(" yes->method=%s\n",ctx->method?ctx->method->name().data():"<none>"); - } - else if (ctx->method==0) // search for class variable with the same name - { - //printf(" no\n"); - //printf("yyextra->currentDefinition=%p\n",yyextra->currentDefinition); - if (yyextra->currentDefinition && - yyextra->currentDefinition->definitionType()==Definition::TypeClass) - { - ctx->objectVar = (dynamic_cast<ClassDef *>(yyextra->currentDefinition))->getMemberByName(ctx->objectTypeOrName); - //printf(" ctx->objectVar=%p\n",ctx->objectVar); - if (ctx->objectVar) - { - ctx->objectType = stripClassName(yyscanner,ctx->objectVar->typeString(),yyextra->currentDefinition); - //printf(" ctx->objectType=%p\n",ctx->objectType); - if (ctx->objectType && !ctx->methodName.isEmpty()) - { - ctx->method = ctx->objectType->getMemberByName(ctx->methodName); - //printf(" ctx->method=%p\n",ctx->method); - } - } - } - } + if (ctx->objectTypeOrName=="self") + { + if (yyextra->currentDefinition && + yyextra->currentDefinition->definitionType()==Definition::TypeClass) + { + ctx->objectType = toClassDef(yyextra->currentDefinition); + } + } + else + { + ctx->objectType = yyextra->symbolResolver.resolveClass(yyextra->currentDefinition,ctx->objectTypeOrName); + ctx->method = yyextra->symbolResolver.getTypedef(); + } + //printf(" object is class? %p\n",ctx->objectType); + if (ctx->objectType) // found class + { + ctx->method = ctx->objectType->getMemberByName(ctx->methodName); + //printf(" yes->method=%s\n",ctx->method?ctx->method->name().data():"<none>"); + } + else if (ctx->method==0) // search for class variable with the same name + { + //printf(" no\n"); + //printf("yyextra->currentDefinition=%p\n",yyextra->currentDefinition); + if (yyextra->currentDefinition && + yyextra->currentDefinition->definitionType()==Definition::TypeClass) + { + ctx->objectVar = (toClassDef(yyextra->currentDefinition))->getMemberByName(ctx->objectTypeOrName); + //printf(" ctx->objectVar=%p\n",ctx->objectVar); + if (ctx->objectVar) + { + ctx->objectType = stripClassName(yyscanner,ctx->objectVar->typeString(),yyextra->currentDefinition); + //printf(" ctx->objectType=%p\n",ctx->objectType); + if (ctx->objectType && !ctx->methodName.isEmpty()) + { + ctx->method = ctx->objectType->getMemberByName(ctx->methodName); + //printf(" ctx->method=%p\n",ctx->method); + } + } + } + } } else // local variable { - //printf(" object is local variable\n"); - if (cd!=VariableContext::dummyContext && !ctx->methodName.isEmpty()) - { - ctx->method = cd->getMemberByName(ctx->methodName); - //printf(" class=%p method=%p\n",cd,ctx->method); - } + //printf(" object is local variable\n"); + if (stv->globalDef() && !ctx->methodName.isEmpty()) + { + const ClassDef *cd = toClassDef(stv->globalDef()); + if (cd) + { + ctx->method = cd->getMemberByName(ctx->methodName); + } + //printf(" class=%p method=%p\n",cd,ctx->method); + } } } } @@ -3570,210 +3423,209 @@ static void writeObjCMethodCall(yyscan_t yyscanner,ObjCCallCtx *ctx) char nc=*p++; if (nc=='$') // escaped $ { - yyextra->code->codify("$"); + yyextra->code->codify("$"); } - else // name fragment or reference to a nested call + else // name fragment or reference to a nested call { - if (nc=='n') // name fragment - { + if (nc=='n') // name fragment + { nc=*p++; - QCString refIdStr; - while (nc!=0 && isdigit(nc)) { refIdStr+=nc; nc=*p++; } - p--; - int refId=refIdStr.toInt(); - QCString *pName = yyextra->nameDict.find(refId); - if (pName) - { - if (ctx->method && ctx->method->isLinkable()) - { - writeMultiLineCodeLink(yyscanner,*yyextra->code,ctx->method,pName->data()); - if (yyextra->currentMemberDef && yyextra->collectXRefs) - { - addDocCrossReference(yyextra->currentMemberDef,const_cast<MemberDef*>(ctx->method)); - } - } - else - { - codifyLines(yyscanner,pName->data()); - } - } - else - { - //printf("Invalid name: id=%d\n",refId); - } - } - else if (nc=='o') // reference to potential object name - { + QCString refIdStr; + while (nc!=0 && isdigit(nc)) { refIdStr+=nc; nc=*p++; } + p--; + int refId=refIdStr.toInt(); + auto it = yyextra->nameMap.find(refId); + if (it!=yyextra->nameMap.end()) + { + QCString name = it->second; + if (ctx->method && ctx->method->isLinkable()) + { + writeMultiLineCodeLink(yyscanner,*yyextra->code,ctx->method,name); + if (yyextra->currentMemberDef && yyextra->collectXRefs) + { + std::lock_guard<std::mutex> lock(g_docCrossReferenceMutex); + addDocCrossReference(toMemberDefMutable(yyextra->currentMemberDef),toMemberDefMutable(ctx->method)); + } + } + else + { + codifyLines(yyscanner,name); + } + } + else + { + //printf("Invalid name: id=%d\n",refId); + } + } + else if (nc=='o') // reference to potential object name + { nc=*p++; - QCString refIdStr; - while (nc!=0 && isdigit(nc)) { refIdStr+=nc; nc=*p++; } - p--; - int refId=refIdStr.toInt(); - QCString *pObject = yyextra->objectDict.find(refId); - if (pObject) - { - if (*pObject=="self") - { - if (yyextra->currentDefinition && - yyextra->currentDefinition->definitionType()==Definition::TypeClass) - { - ctx->objectType = dynamic_cast<ClassDef *>(yyextra->currentDefinition); - if (ctx->objectType->categoryOf()) - { - ctx->objectType = ctx->objectType->categoryOf(); - } - if (ctx->objectType && !ctx->methodName.isEmpty()) - { - ctx->method = ctx->objectType->getMemberByName(ctx->methodName); - } - } - startFontClass(yyscanner,"keyword"); - codifyLines(yyscanner,pObject->data()); - endFontClass(yyscanner); - } - else if (*pObject=="super") - { - if (yyextra->currentDefinition && - yyextra->currentDefinition->definitionType()==Definition::TypeClass) - { - ClassDef *cd = dynamic_cast<ClassDef *>(yyextra->currentDefinition); - if (cd->categoryOf()) - { - cd = cd->categoryOf(); - } - BaseClassList *bcd = cd->baseClasses(); - if (bcd) // get direct base class (there should be only one) - { - BaseClassListIterator bli(*bcd); - BaseClassDef *bclass; - for (bli.toFirst();(bclass=bli.current());++bli) - { - if (bclass->classDef->compoundType()!=ClassDef::Protocol) - { - ctx->objectType = bclass->classDef; - if (ctx->objectType && !ctx->methodName.isEmpty()) - { - ctx->method = ctx->objectType->getMemberByName(ctx->methodName); - } - } - } - } - } - startFontClass(yyscanner,"keyword"); - codifyLines(yyscanner,pObject->data()); - endFontClass(yyscanner); - } - else if (ctx->objectVar && ctx->objectVar->isLinkable()) // object is class variable - { - writeMultiLineCodeLink(yyscanner,*yyextra->code,ctx->objectVar,pObject->data()); - if (yyextra->currentMemberDef && yyextra->collectXRefs) - { - addDocCrossReference(yyextra->currentMemberDef,const_cast<MemberDef*>(ctx->objectVar)); - } - } - else if (ctx->objectType && - ctx->objectType!=VariableContext::dummyContext && - ctx->objectType->isLinkable() - ) // object is class name - { - const ClassDef *cd = ctx->objectType; - writeMultiLineCodeLink(yyscanner,*yyextra->code,cd,pObject->data()); - } - else // object still needs to be resolved - { - const ClassDef *cd = getResolvedClass(yyextra->currentDefinition, - yyextra->sourceFileDef, *pObject); - if (cd && cd->isLinkable()) - { - if (ctx->objectType==0) ctx->objectType=cd; - writeMultiLineCodeLink(yyscanner,*yyextra->code,cd,pObject->data()); - } - else - { - codifyLines(yyscanner,pObject->data()); - } - } - } - else - { - //printf("Invalid object: id=%d\n",refId); - } - } - else if (nc=='c') // reference to nested call - { + QCString refIdStr; + while (nc!=0 && isdigit(nc)) { refIdStr+=nc; nc=*p++; } + p--; + int refId=refIdStr.toInt(); + auto it = yyextra->objectMap.find(refId); + if (it!=yyextra->objectMap.end()) + { + QCString object = it->second; + if (object=="self") + { + if (yyextra->currentDefinition && + yyextra->currentDefinition->definitionType()==Definition::TypeClass) + { + ctx->objectType = toClassDef(yyextra->currentDefinition); + if (ctx->objectType->categoryOf()) + { + ctx->objectType = ctx->objectType->categoryOf(); + } + if (ctx->objectType && !ctx->methodName.isEmpty()) + { + ctx->method = ctx->objectType->getMemberByName(ctx->methodName); + } + } + startFontClass(yyscanner,"keyword"); + codifyLines(yyscanner,object); + endFontClass(yyscanner); + } + else if (object=="super") + { + if (yyextra->currentDefinition && + yyextra->currentDefinition->definitionType()==Definition::TypeClass) + { + const ClassDef *cd = toClassDef(yyextra->currentDefinition); + if (cd->categoryOf()) + { + cd = cd->categoryOf(); + } + for (const auto &bclass : cd->baseClasses()) + { + if (bclass.classDef->compoundType()!=ClassDef::Protocol) + { + ctx->objectType = bclass.classDef; + if (ctx->objectType && !ctx->methodName.isEmpty()) + { + ctx->method = ctx->objectType->getMemberByName(ctx->methodName); + } + } + } + } + startFontClass(yyscanner,"keyword"); + codifyLines(yyscanner,object); + endFontClass(yyscanner); + } + else if (ctx->objectVar && ctx->objectVar->isLinkable()) // object is class variable + { + writeMultiLineCodeLink(yyscanner,*yyextra->code,ctx->objectVar,object); + if (yyextra->currentMemberDef && yyextra->collectXRefs) + { + std::lock_guard<std::mutex> lock(g_docCrossReferenceMutex); + addDocCrossReference(toMemberDefMutable(yyextra->currentMemberDef),toMemberDefMutable(ctx->objectVar)); + } + } + else if (ctx->objectType && + ctx->objectType->isLinkable() + ) // object is class name + { + const ClassDef *cd = ctx->objectType; + writeMultiLineCodeLink(yyscanner,*yyextra->code,cd,object); + } + else // object still needs to be resolved + { + const ClassDef *cd = yyextra->symbolResolver.resolveClass(yyextra->currentDefinition, object); + if (cd && cd->isLinkable()) + { + if (ctx->objectType==0) ctx->objectType=cd; + writeMultiLineCodeLink(yyscanner,*yyextra->code,cd,object); + } + else + { + codifyLines(yyscanner,object); + } + } + } + else + { + //printf("Invalid object: id=%d\n",refId); + } + } + else if (nc=='c') // reference to nested call + { nc=*p++; - QCString refIdStr; - while (nc!=0 && isdigit(nc)) { refIdStr+=nc; nc=*p++; } - p--; - int refId=refIdStr.toInt(); - ObjCCallCtx *ictx = yyextra->contextDict.find(refId); - if (ictx) // recurse into nested call - { - writeObjCMethodCall(yyscanner,ictx); - if (ictx->method) // link to nested call successfully - { - // get the ClassDef representing the method's return type - if (QCString(ictx->method->typeString())=="id") - { - // see if the method name is unique, if so we link to it - MemberName *mn=Doxygen::memberNameLinkedMap->find(ctx->methodName); - //printf("mn->count=%d ictx->method=%s ctx->methodName=%s\n", - // mn==0?-1:(int)mn->count(), - // ictx->method->name().data(), - // ctx->methodName.data()); - if (mn && mn->size()==1) // member name unique - { - ctx->method = mn->front().get(); - } - } - else - { - ctx->objectType = stripClassName(yyscanner,ictx->method->typeString(),yyextra->currentDefinition); - if (ctx->objectType && !ctx->methodName.isEmpty()) - { - ctx->method = ctx->objectType->getMemberByName(ctx->methodName); - } - } - //printf(" ***** method=%s -> object=%p\n",ictx->method->name().data(),ctx->objectType); - } - } - else - { - //printf("Invalid context: id=%d\n",refId); - } - } - else if (nc=='w') // some word - { + QCString refIdStr; + while (nc!=0 && isdigit(nc)) { refIdStr+=nc; nc=*p++; } + p--; + int refId=refIdStr.toInt(); + auto it = yyextra->contextMap.find(refId); + if (it!=yyextra->contextMap.end()) // recurse into nested call + { + ObjCCallCtx *ictx = it->second.get(); + writeObjCMethodCall(yyscanner,ictx); + if (ictx->method) // link to nested call successfully + { + // get the ClassDef representing the method's return type + if (QCString(ictx->method->typeString())=="id") + { + // see if the method name is unique, if so we link to it + MemberName *mn=Doxygen::memberNameLinkedMap->find(ctx->methodName); + //printf("mn->count=%d ictx->method=%s ctx->methodName=%s\n", + // mn==0?-1:(int)mn->count(), + // ictx->method->name().data(), + // ctx->methodName.data()); + if (mn && mn->size()==1) // member name unique + { + ctx->method = mn->front().get(); + } + } + else + { + ctx->objectType = stripClassName(yyscanner,ictx->method->typeString(),yyextra->currentDefinition); + if (ctx->objectType && !ctx->methodName.isEmpty()) + { + ctx->method = ctx->objectType->getMemberByName(ctx->methodName); + } + } + //printf(" ***** method=%s -> object=%p\n",ictx->method->name().data(),ctx->objectType); + } + } + else + { + //printf("Invalid context: id=%d\n",refId); + } + } + else if (nc=='w') // some word + { nc=*p++; - QCString refIdStr; - while (nc!=0 && isdigit(nc)) { refIdStr+=nc; nc=*p++; } - p--; - int refId=refIdStr.toInt(); - QCString *pWord = yyextra->wordDict.find(refId); - if (pWord) - { - codifyLines(yyscanner,pWord->data()); - } - } + QCString refIdStr; + while (nc!=0 && isdigit(nc)) { refIdStr+=nc; nc=*p++; } + p--; + int refId=refIdStr.toInt(); + auto it = yyextra->wordMap.find(refId); + if (it!=yyextra->wordMap.end()) + { + QCString word = it->second; + codifyLines(yyscanner,word); + } + } else if (nc=='d') // comment block { nc=*p++; - QCString refIdStr; - while (nc!=0 && isdigit(nc)) { refIdStr+=nc; nc=*p++; } - p--; - int refId=refIdStr.toInt(); - QCString *pComment = yyextra->commentDict.find(refId); - if (pComment) + QCString refIdStr; + while (nc!=0 && isdigit(nc)) { refIdStr+=nc; nc=*p++; } + p--; + int refId=refIdStr.toInt(); + auto it = yyextra->commentMap.find(refId); + if (it!=yyextra->commentMap.end()) { + QCString comment = it->second; startFontClass(yyscanner,"comment"); - codifyLines(yyscanner,pComment->data()); - endFontClass(yyscanner); + codifyLines(yyscanner,comment); + endFontClass(yyscanner); } } - else // illegal marker - { - ASSERT("invalid escape sequence"==0); - } + else // illegal marker + { + ASSERT("invalid escape sequence"==0); + } } } else // normal non-marker character @@ -3790,14 +3642,14 @@ static void writeObjCMethodCall(yyscan_t yyscanner,ObjCCallCtx *ctx) } // Replaces an Objective-C method name fragment s by a marker of the form -// $n12, the number (12) can later be used as a key for obtaining the name -// fragment, from yyextra->nameDict +// $n12, the number (12) can later be used as a key for obtaining the name +// fragment, from yyextra->nameMap static QCString escapeName(yyscan_t yyscanner,const char *s) { struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; QCString result; result.sprintf("$n%d",yyextra->currentNameId); - yyextra->nameDict.insert(yyextra->currentNameId,new QCString(s)); + yyextra->nameMap.emplace(std::make_pair(yyextra->currentNameId,s)); yyextra->currentNameId++; return result; } @@ -3807,7 +3659,7 @@ static QCString escapeObject(yyscan_t yyscanner,const char *s) struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; QCString result; result.sprintf("$o%d",yyextra->currentObjId); - yyextra->objectDict.insert(yyextra->currentObjId,new QCString(s)); + yyextra->objectMap.emplace(std::make_pair(yyextra->currentObjId,s)); yyextra->currentObjId++; return result; } @@ -3817,7 +3669,7 @@ static QCString escapeWord(yyscan_t yyscanner,const char *s) struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; QCString result; result.sprintf("$w%d",yyextra->currentWordId); - yyextra->wordDict.insert(yyextra->currentWordId,new QCString(s)); + yyextra->wordMap.emplace(std::make_pair(yyextra->currentWordId,s)); yyextra->currentWordId++; return result; } @@ -3827,7 +3679,7 @@ static QCString escapeComment(yyscan_t yyscanner,const char *s) struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; QCString result; result.sprintf("$d%d",yyextra->currentCommentId); - yyextra->commentDict.insert(yyextra->currentCommentId,new QCString(s)); + yyextra->commentMap.emplace(std::make_pair(yyextra->currentCommentId,s)); yyextra->currentCommentId++; return result; } @@ -3879,7 +3731,7 @@ static void saveObjCContext(yyscan_t yyscanner) { //printf("Trying to save NULL context!\n"); } - ObjCCallCtx *newCtx = new ObjCCallCtx; + auto newCtx = std::make_unique<ObjCCallCtx>(); newCtx->id = yyextra->currentCtxId; newCtx->lexState = YY_START; newCtx->braceCount = yyextra->braceCount; @@ -3887,8 +3739,8 @@ static void saveObjCContext(yyscan_t yyscanner) newCtx->objectVar = 0; newCtx->method = 0; //printf("save state=%d\n",YY_START); - yyextra->contextDict.insert(yyextra->currentCtxId,newCtx); - yyextra->currentCtx = newCtx; + yyextra->currentCtx = newCtx.get(); + yyextra->contextMap.emplace(std::make_pair(yyextra->currentCtxId,std::move(newCtx))); yyextra->braceCount = 0; yyextra->currentCtxId++; } @@ -3899,9 +3751,10 @@ static void restoreObjCContext(yyscan_t yyscanner) //printf("restore state=%d->%d\n",YY_START,yyextra->currentCtx->lexState); BEGIN(yyextra->currentCtx->lexState); yyextra->braceCount = yyextra->currentCtx->braceCount; - if (!yyextra->contextStack.isEmpty()) + if (!yyextra->contextStack.empty()) { - yyextra->currentCtx = yyextra->contextStack.pop(); + yyextra->currentCtx = yyextra->contextStack.top(); + yyextra->contextStack.pop(); } else { @@ -3922,14 +3775,11 @@ CCodeParser::CCodeParser() : p(std::make_unique<CCodeParser::Private>()) #ifdef FLEX_DEBUG codeYYset_debug(1,p->yyscanner); #endif + resetCodeParserState(); } CCodeParser::~CCodeParser() { - struct yyguts_t *yyg = (struct yyguts_t*)p->yyscanner; - yyextra->classScopeLengthStack.clear(); - delete yyextra->codeClassSDict; - yyextra->codeClassSDict=0; codeYYlex_destroy(p->yyscanner); } @@ -3937,22 +3787,17 @@ void CCodeParser::resetCodeParserState() { struct yyguts_t *yyg = (struct yyguts_t*)p->yyscanner; //printf("***CodeParser::reset()\n"); - yyextra->forceTagReference.resize(0); yyextra->theVarContext.clear(); - yyextra->classScopeLengthStack.setAutoDelete(TRUE); - yyextra->classScopeLengthStack.clear(); - delete yyextra->codeClassSDict; - yyextra->codeClassSDict = new ClassSDict(17); - yyextra->codeClassSDict->setAutoDelete(TRUE); - yyextra->codeClassSDict->clear(); + while (!yyextra->classScopeLengthStack.empty()) yyextra->classScopeLengthStack.pop(); + yyextra->codeClassMap.clear(); yyextra->curClassBases.clear(); yyextra->anchorCount = 0; } -void CCodeParser::parseCode(CodeOutputInterface &od,const char *className,const QCString &s, +void CCodeParser::parseCode(CodeOutputInterface &od,const char *className,const QCString &s, SrcLangExt lang,bool exBlock, const char *exName,FileDef *fd, - int startLine,int endLine,bool inlineFragment, - const MemberDef *memberDef,bool showLineNumbers,const Definition *searchCtx, + int startLine,int endLine,bool inlineFragment, + const MemberDef *memberDef,bool showLineNumbers,const Definition *searchCtx, bool collectXRefs) { yyscan_t yyscanner = p->yyscanner; @@ -3964,10 +3809,6 @@ void CCodeParser::parseCode(CodeOutputInterface &od,const char *className,const printlex(yy_flex_debug, TRUE, __FILE__, fd ? fd->fileName().data(): NULL); - if (yyextra->codeClassSDict==0) - { - resetCodeParserState(); - } yyextra->code = &od; yyextra->inputString = s; yyextra->inputPosition = 0; @@ -3977,6 +3818,7 @@ void CCodeParser::parseCode(CodeOutputInterface &od,const char *className,const yyextra->searchCtx = searchCtx; yyextra->collectXRefs = collectXRefs; yyextra->inFunctionTryBlock = FALSE; + yyextra->symbolResolver.setFileScope(fd); if (startLine!=-1) yyextra->yyLineNr = startLine; @@ -3994,10 +3836,10 @@ void CCodeParser::parseCode(CodeOutputInterface &od,const char *className,const yyextra->sharpCount = 0; yyextra->insideTemplate = FALSE; yyextra->theCallContext.clear(); - yyextra->scopeStack.clear(); + while (!yyextra->scopeStack.empty()) yyextra->scopeStack.pop(); yyextra->classScope = className; //printf("parseCCode %s\n",className); - yyextra->exampleBlock = exBlock; + yyextra->exampleBlock = exBlock; yyextra->exampleName = exName; yyextra->sourceFileDef = fd; yyextra->lineNumbers = fd!=0 && showLineNumbers; @@ -4010,7 +3852,7 @@ void CCodeParser::parseCode(CodeOutputInterface &od,const char *className,const } yyextra->lang = lang; yyextra->insideObjC = lang==SrcLangExt_ObjC; - if (yyextra->sourceFileDef) + if (yyextra->sourceFileDef) { setCurrentDoc(yyscanner,"l00001"); } @@ -4048,6 +3890,8 @@ void CCodeParser::parseCode(CodeOutputInterface &od,const char *className,const delete yyextra->sourceFileDef; yyextra->sourceFileDef=0; } + // write the tooltips + TooltipManager::instance().writeTooltips(od); printlex(yy_flex_debug, FALSE, __FILE__, fd ? fd->fileName().data(): NULL); return; diff --git a/src/commentcnv.l b/src/commentcnv.l index c1ec170..036f830 100644 --- a/src/commentcnv.l +++ b/src/commentcnv.l @@ -1108,45 +1108,6 @@ static void replaceComment(yyscan_t yyscanner,int offset) } } -// simplified way to know if this is fixed form -// duplicate in fortrancode.l -static bool recognizeFixedForm(const char* contents) -{ - int column=0; - bool skipLine=FALSE; - - for(int i=0;;i++) { - column++; - - switch(contents[i]) { - case '\n': - column=0; - skipLine=FALSE; - break; - case ' ': - break; - case '\000': - return FALSE; - case 'C': - case 'c': - case '*': - if(column==1) return TRUE; - if(skipLine) break; - return FALSE; - case '!': - if(column>1 && column<7) return FALSE; - skipLine=TRUE; - break; - default: - if(skipLine) break; - if(column==7) return TRUE; - return FALSE; - } - } - return FALSE; -} - - /*! This function does three things: * -# It converts multi-line C++ style comment blocks (that are aligned) * to C style comment blocks (if MULTILINE_CPP_IS_BRIEF is set to NO). @@ -1183,7 +1144,8 @@ void convertCppComments(BufStr *inBuf,BufStr *outBuf,const char *fileName) yyextra->isFixedForm = FALSE; if (yyextra->lang==SrcLangExt_Fortran) { - yyextra->isFixedForm = recognizeFixedForm(inBuf->data()); + FortranFormat fmt = convertFileNameFortranParserCode(fileName); + yyextra->isFixedForm = recognizeFixedForm(inBuf->data(),fmt); } if (yyextra->lang==SrcLangExt_Markdown) @@ -1205,7 +1167,7 @@ void convertCppComments(BufStr *inBuf,BufStr *outBuf,const char *fileName) warn(yyextra->fileName,ctx->lineNr,"Conditional section%sdoes not have " "a corresponding \\endcond command within this file.",sectionInfo.data()); } - if (yyextra->nestingCount>0 && yyextra->lang!=SrcLangExt_Markdown) + if (yyextra->nestingCount>0 && yyextra->lang!=SrcLangExt_Markdown && yyextra->lang!=SrcLangExt_Fortran) { QCString tmp= "(probable line reference: "; bool first = TRUE; diff --git a/src/commentscan.l b/src/commentscan.l index 5a71b14..e636aa6 100644 --- a/src/commentscan.l +++ b/src/commentscan.l @@ -148,7 +148,8 @@ enum class CommandSpacing { Invisible, // command sets some property but does not appear in the output. Inline, // command appears inline in the output which can be a brief description. - Block // command starts a new paragraphs / ends a brief description. + Block, // command starts a new paragraphs / ends a brief description. + XRef // command is a cross reference (todo, bug, test, xrefitem). }; struct DocCmdMap @@ -170,7 +171,7 @@ static const std::map< std::string, DocCmdMap > docCmdMap = { "author", { 0, CommandSpacing::Block }}, { "authors", { 0, CommandSpacing::Block }}, { "brief", { &handleBrief, CommandSpacing::Invisible }}, - { "bug", { &handleBug, CommandSpacing::Block }}, + { "bug", { &handleBug, CommandSpacing::XRef }}, { "callergraph", { &handleCallergraph, CommandSpacing::Invisible }}, { "callgraph", { &handleCallgraph, CommandSpacing::Invisible }}, { "category", { &handleCategory, CommandSpacing::Invisible }}, @@ -283,10 +284,10 @@ static const std::map< std::string, DocCmdMap > docCmdMap = { "subsection", { &handleSection, CommandSpacing::Block }}, { "subsubsection", { &handleSection, CommandSpacing::Block }}, { "tableofcontents", { &handleToc, CommandSpacing::Invisible }}, - { "test", { &handleTest, CommandSpacing::Block }}, + { "test", { &handleTest, CommandSpacing::XRef }}, { "throw", { 0, CommandSpacing::Block }}, { "throws", { 0, CommandSpacing::Block }}, - { "todo", { &handleTodo, CommandSpacing::Block }}, + { "todo", { &handleTodo, CommandSpacing::XRef }}, { "tparam", { 0, CommandSpacing::Block }}, { "typedef", { &handleFn, CommandSpacing::Invisible }}, { "union", { &handleUnion, CommandSpacing::Invisible }}, @@ -299,7 +300,7 @@ static const std::map< std::string, DocCmdMap > docCmdMap = { "weakgroup", { &handleWeakGroup, CommandSpacing::Invisible }}, { "xmlinclude", { 0, CommandSpacing::Inline }}, { "xmlonly", { &handleFormatBlock, CommandSpacing::Invisible }}, - { "xrefitem", { &handleXRefItem, CommandSpacing::Block }} + { "xrefitem", { &handleXRefItem, CommandSpacing::XRef }} }; #define YY_NO_INPUT 1 @@ -438,6 +439,8 @@ static void handleGuard(yyscan_t yyscanner,const QCString &expr); static yy_size_t yyread(yyscan_t yyscanner,char *buf,yy_size_t max_size); static void addCite(yyscan_t yyscanner); +#define unput_string(yytext,yyleng) do { for (int i=(int)yyleng-1;i>=0;i--) unput(yytext[i]); } while(0) + //----------------------------------------------------------------------------- #undef YY_INPUT @@ -666,6 +669,7 @@ RCSTAG "$"{ID}":"[^\n$]+"$" optList = QCStringList::split(',',optStr); } auto it = docCmdMap.find(cmdName.data()); + //printf("lookup command '%s' found=%d\n",cmdName.data(),it!=docCmdMap.end()); if (it!=docCmdMap.end()) // special action is required { int i=0; @@ -871,9 +875,9 @@ RCSTAG "$"{ID}":"[^\n$]+"$" yyextra->briefEndsAtDot=FALSE; } } -<Comment>\n { // newline - addOutput(yyscanner,*yytext); - yyextra->lineNr++; +<Comment>{DOCNL} { // newline + addOutput(yyscanner,yytext); + if (*yytext == '\n') yyextra->lineNr++; } <Comment>. { // catch-all for anything else addOutput(yyscanner,*yytext); @@ -884,7 +888,11 @@ RCSTAG "$"{ID}":"[^\n$]+"$" <HtmlComment>"--"[!]?">"{B}* { BEGIN( Comment ); } <HtmlComment>{DOCNL} { - if (*yytext=='\n') yyextra->lineNr++; + if (*yytext=='\n') + { + addOutput(yyscanner,*yytext); + yyextra->lineNr++; + } } <HtmlComment>[^\\\n\-]+ { // ignore unimportant characters } @@ -953,7 +961,7 @@ RCSTAG "$"{ID}":"[^\n$]+"$" warn(yyextra->fileName,yyextra->lineNr, "missing argument after \\enum." ); - unput('\n'); + unput_string(yytext,yyleng); //addOutput(yyscanner,'\n'); //if (*yytext=='\n') yyextra->lineNr++; BEGIN( Comment ); @@ -976,7 +984,7 @@ RCSTAG "$"{ID}":"[^\n$]+"$" "missing argument after " "\\namespace." ); - unput('\n'); + unput_string(yytext,yyleng); //addOutput(yyscanner,'\n'); //if (*yytext=='\n') yyextra->lineNr++; BEGIN( Comment ); @@ -999,7 +1007,7 @@ RCSTAG "$"{ID}":"[^\n$]+"$" "missing argument after " "\\package." ); - unput('\n'); + unput_string(yytext,yyleng); //addOutput(yyscanner,'\n'); //if (*yytext=='\n') yyextra->lineNr++; BEGIN( Comment ); @@ -1037,12 +1045,18 @@ RCSTAG "$"{ID}":"[^\n$]+"$" ); //addOutput(yyscanner,'\n'); //if (*yytext=='\n') yyextra->lineNr++; - unput('\n'); + unput_string(yytext,yyleng); BEGIN( Comment ); } <ClassDocArg1,CategoryDocArg1>. { // ignore other stuff } +<ClassDocArg2>{DOCNL} { + //addOutput(yyscanner,'\n'); + //if (*yytext=='\n') yyextra->lineNr++; + unput_string(yytext,yyleng); + BEGIN( Comment ); + } <ClassDocArg2>{FILE}|"<>" { // second argument; include file yyextra->current->includeFile = yytext; BEGIN( ClassDocArg3 ); @@ -1051,12 +1065,6 @@ RCSTAG "$"{ID}":"[^\n$]+"$" yyextra->lineNr++; addOutput(yyscanner,'\n'); } -<ClassDocArg2>{DOCNL} { - //addOutput(yyscanner,'\n'); - //if (*yytext=='\n') yyextra->lineNr++; - unput('\n'); - BEGIN( Comment ); - } <ClassDocArg2>. { // ignore other stuff } @@ -1070,7 +1078,7 @@ RCSTAG "$"{ID}":"[^\n$]+"$" } <ClassDocArg3>{DOCNL} { //if (*yytext=='\n') yyextra->lineNr++; - unput('\n'); + unput_string(yytext,yyleng); BEGIN( Comment ); } <ClassDocArg3>. { // ignore other stuff @@ -1101,7 +1109,7 @@ RCSTAG "$"{ID}":"[^\n$]+"$" ); //addOutput(yyscanner,'\n'); //if (*yytext=='\n') yyextra->lineNr++; - unput('\n'); + unput_string(yytext,yyleng); BEGIN( Comment ); } <GroupDocArg1>. { // ignore other stuff @@ -1124,7 +1132,7 @@ RCSTAG "$"{ID}":"[^\n$]+"$" "\\defgroup %s", yyextra->current->name.data() ); } - unput('\n'); + unput_string(yytext,yyleng); //if (*yytext=='\n') yyextra->lineNr++; //addOutput(yyscanner,'\n'); BEGIN( Comment ); @@ -1149,7 +1157,7 @@ RCSTAG "$"{ID}":"[^\n$]+"$" "missing argument after " "\\page." ); - unput('\n'); + unput_string(yytext,yyleng); //if (*yytext=='\n') yyextra->lineNr++; //addOutput(yyscanner,'\n'); BEGIN( Comment ); @@ -1157,7 +1165,7 @@ RCSTAG "$"{ID}":"[^\n$]+"$" <PageDocArg1>. { // ignore other stuff } <PageDocArg2>{DOCNL} { // second argument; page title - unput('\n'); + unput_string(yytext,yyleng); //if (*yytext=='\n') yyextra->lineNr++; //addOutput(yyscanner,'\n'); BEGIN( Comment ); @@ -1191,7 +1199,7 @@ RCSTAG "$"{ID}":"[^\n$]+"$" /* --------- handle arguments of the file/dir/example command ------------ */ <FileDocArg1>{DOCNL} { // no file name specified - unput('\n'); + unput_string(yytext,yyleng); //if (*yytext=='\n') yyextra->lineNr++; //addOutput(yyscanner,'\n'); BEGIN( Comment ); @@ -1289,7 +1297,7 @@ RCSTAG "$"{ID}":"[^\n$]+"$" warn(yyextra->fileName,yyextra->lineNr, "Missing argument of '\\%s' command",yyextra->currentCmd.data() ); - unput('\n'); + unput_string(yytext,yyleng); //if (*yytext=='\n') yyextra->lineNr++; //addOutput(yyscanner,'\n'); BEGIN( Comment ); @@ -1303,7 +1311,7 @@ RCSTAG "$"{ID}":"[^\n$]+"$" <LineParam>{DOCNL} { // end of argument //if (*yytext=='\n') yyextra->lineNr++; //addOutput(yyscanner,'\n'); - unput('\n'); + unput_string(yytext,yyleng); BEGIN( Comment ); } <LineParam>{LC} { // line continuation @@ -1667,7 +1675,7 @@ RCSTAG "$"{ID}":"[^\n$]+"$" <NameParam>{DOCNL} { // end of argument //if (*yytext=='\n') yyextra->lineNr++; //addOutput(yyscanner,'\n'); - unput('\n'); + unput_string(yytext,yyleng); BEGIN( Comment ); } <NameParam>{LC} { // line continuation @@ -1705,7 +1713,7 @@ RCSTAG "$"{ID}":"[^\n$]+"$" } //if (*yytext=='\n') yyextra->lineNr++; //addOutput(yyscanner,'\n'); - unput('\n'); + unput_string(yytext,yyleng); BEGIN( Comment ); } <InGroupParam>{LC} { // line continuation @@ -1723,7 +1731,7 @@ RCSTAG "$"{ID}":"[^\n$]+"$" { //if (*yytext=='\n') yyextra->lineNr++; //addOutput(yyscanner,'\n'); - unput('\n'); + unput_string(yytext,yyleng); yyextra->langParser->parsePrototype(yyextra->functionProto); BEGIN( Comment ); } @@ -1810,7 +1818,7 @@ RCSTAG "$"{ID}":"[^\n$]+"$" ); //if (*yytext=='\n') yyextra->lineNr++; //addOutput(yyscanner,'\n'); - unput('\n'); + unput_string(yytext,yyleng); BEGIN( Comment ); } <ExtendsParam>. { // ignore other stuff @@ -1847,7 +1855,7 @@ RCSTAG "$"{ID}":"[^\n$]+"$" ); //if (*yytext=='\n') yyextra->lineNr++; //addOutput(yyscanner,'\n'); - unput('\n'); + unput_string(yytext,yyleng); BEGIN( Comment ); } <CiteLabel>. { // invalid character for cite label @@ -2782,6 +2790,7 @@ static bool makeStructuralIndicator(yyscan_t yyscanner,Entry::Sections s) yyextra->current->section = s; yyextra->current->fileName = yyextra->fileName; yyextra->current->startLine = yyextra->lineNr; + yyextra->current->docLine = yyextra->lineNr; return FALSE; } } @@ -2823,28 +2832,29 @@ static void addXRefItem(yyscan_t yyscanner, RefList *refList = RefListManager::instance().add(listName,listTitle,itemTitle); RefItem *item = 0; - for (RefItem *i : yyextra->current->sli) + for (auto it = yyextra->current->sli.rbegin(); it != yyextra->current->sli.rend(); ++it) { + RefItem *i = *it; if (i && qstrcmp(i->list()->listName(),listName)==0) { - //printf("found %s lii->type=%s\n",listName,lii->type); + //printf("found %s lii->type=%s\n",listName,i->list()->listName().data()); item = i; break; } } if (item && append) // already found item of same type just before this one { - //printf("listName=%s item id = %d existing\n",listName,lii->itemId); + //printf("listName=%s item id = %d existing\n",listName,item->id()); item->setText(item->text() + " <p>" + yyextra->outputXRef); //printf("%s: text +=%s\n",listName,item->text.data()); } else // new item { - //printf("listName=%s item id = %d new yyextra->current=%p\n",listName,itemId,yyextra->current); // if we have already an item from the same list type (e.g. a second @todo) // in the same Entry (i.e. lii!=0) then we reuse its link anchor. item = refList->add(); + //printf("listName=%s item id = %d new yyextra->current=%p\n",listName,item->id(),yyextra->current); QCString anchorLabel; anchorLabel.sprintf("_%s%06d",listName,item->id()); item->setText(yyextra->outputXRef); @@ -3234,7 +3244,7 @@ bool CommentScanner::parseCommentBlock(/* in */ OutlineParserInterface *pars yyextra->guards = std::stack<GuardedSection>(); yyextra->langParser = parser; yyextra->current = curEntry; - yyextra->current->docLine = (lineNr > 1 ? lineNr-1: 1); + yyextra->current->docLine = (lineNr > 1 ? lineNr : 1); if (comment.isEmpty()) return FALSE; // avoid empty strings yyextra->inputString = comment; yyextra->inputString.append(" "); diff --git a/src/config.xml b/src/config.xml index b3718be..fb48c63 100644 --- a/src/config.xml +++ b/src/config.xml @@ -660,7 +660,9 @@ Go to the <a href="commands.html">next</a> section or return to the <br>Note: For files without extension you can use `no_extension` as a placeholder. <br>Note that for custom extensions you also need to set \ref cfg_file_patterns "FILE_PATTERNS" otherwise the - files are not read by doxygen. + files are not read by doxygen. When specifying `no_extension` you should add `*` + to the \ref cfg_file_patterns "FILE_PATTERNS". + <br>Note see also the list of \ref default_file_extension_mapping "default file extension mappings". ]]> </docs> </option> @@ -916,6 +918,15 @@ Go to the <a href="commands.html">next</a> section or return to the ]]> </docs> </option> + <option type='bool' id='RESOLVE_UNNAMED_PARAMS' defval='1'> + <docs> +<![CDATA[ + If this flag is set to \c YES, the name of an unnamed parameter in a declaration will be + determined by the corresponding definition. By default unnamed parameters remain unnamed + in the output. +]]> + </docs> + </option> <option type='bool' id='HIDE_UNDOC_MEMBERS' defval='0'> <docs> <![CDATA[ @@ -971,12 +982,20 @@ Go to the <a href="commands.html">next</a> section or return to the <option type='bool' id='CASE_SENSE_NAMES' defval='0' altdefval='Portable::fileSystemIsCaseSensitive()'> <docs> <![CDATA[ - If the \c CASE_SENSE_NAMES tag is set to \c NO then doxygen - 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 (including Cygwin) and - Mac users are advised to set this option to \c NO. + With the correct setting of option \c CASE_SENSE_NAMES doxygen will better be able to match the + capabilities of the underlying filesystem. + + In case the filesystem is case sensitive (i.e. it supports files in the same directory + whose names only differ in casing), the option must be set to \c YES to properly deal with such files + in case they appear in the input. + + For filesystems that are not case sensitive the option should be be set to \c NO to properly + deal with output files written for symbols that only differ in casing, such as for two classes, + one named \c CLASS and the other named \c Class, and to also support references to files without + having to specify the exact matching casing. + + On Windows (including Cygwin) and MacOS, users should typically set this option to \c NO, + whereas on Linux or other Unix flavors it should typically be set to \c YES. ]]> </docs> </option> @@ -1386,6 +1405,8 @@ FILE_VERSION_FILTER = "cleartool desc -fmt \%Vn" Note that for custom extensions or not directly supported extensions you also need to set \ref cfg_extension_mapping "EXTENSION_MAPPING" for the extension otherwise the files are not read by doxygen.<br> + Note the list of default checked file patterns might differ from the list of + \ref default_file_extension_mapping "default file extension mappings".<br> If left blank the following patterns are tested: ]]> </docs> @@ -1420,8 +1441,6 @@ FILE_VERSION_FILTER = "cleartool desc -fmt \%Vn" <value name='*.md'/> <value name='*.mm'/> <value name='*.dox' desc='(to be provided as doxygen C comment)'/> - <value name='*.doc' desc='(to be provided as doxygen C comment)'/> - <value name='*.txt' desc='(to be provided as doxygen C comment)'/> <value name='*.py'/> <value name='*.pyw'/> <value name='*.f90'/> @@ -1730,10 +1749,10 @@ to disable this feature. <docs> <![CDATA[ If clang assisted parsing is enabled you can provide the clang parser with the - path to the directory containing a file called compile_commands.json. + path to the directory containing a file called `compile_commands.json`. This file is the <a href="http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html"> compilation database</a> containing the options used when the source files were built. - This is equivalent to specifying the "-p" option to a clang tool, such as clang-check. + This is equivalent to specifying the `-p` option to a clang tool, such as `clang-check`. These options will then be passed to the parser. Any options specified with \ref cfg_clang_options "CLANG_OPTIONS" will be added as well. @@ -2279,7 +2298,9 @@ The \c DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. <option type='string' id='QHG_LOCATION' format='file' defval='' depends='GENERATE_QHP'> <docs> <![CDATA[ - The \c QHG_LOCATION tag can be used to specify the location of Qt's qhelpgenerator. + The \c QHG_LOCATION tag can + be used to specify the location (absolute path including file name) of + Qt's qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the generated `.qhp` file. ]]> </docs> @@ -3409,7 +3430,7 @@ to be found in the default search path. ]]> </docs> </option> - <option type='int' id='UML_LIMIT_NUM_FIELDS' defval='10' minval='0' maxval='100' depends='HAVE_DOT'> + <option type='int' id='UML_LIMIT_NUM_FIELDS' defval='10' minval='0' maxval='100' depends='UML_LOOK'> <docs> <![CDATA[ If the \ref cfg_uml_look "UML_LOOK" tag is enabled, the fields and methods are shown inside @@ -3423,6 +3444,23 @@ to be found in the default search path. ]]> </docs> </option> + <option type='bool' id='DOT_UML_DETAILS' defval='0' depends='UML_LOOK'> + <docs> +<![CDATA[ +If the \c DOT_UML_DETAILS tag is set to \c YES, doxygen will +add type and arguments for attributes and methods in the UML graphs. +]]> + </docs> + </option> + <option type='int' id='DOT_WRAP_THRESHOLD' defval='17' minval='0' maxval='1000' depends='HAVE_DOT'> + <docs> +<![CDATA[ + The \c DOT_WRAP_THRESHOLD tag can be used to set the maximum number of characters to display on + a single line. If the actual line length exceeds this threshold significantly it will wrapped + across multiple lines. Some heuristics are apply to avoid ugly line breaks. +]]> + </docs> + </option> <option type='bool' id='TEMPLATE_RELATIONS' defval='0' depends='HAVE_DOT'> <docs> <![CDATA[ @@ -3653,11 +3691,14 @@ to be found in the default search path. ]]> </docs> </option> - <option type='bool' id='DOT_CLEANUP' defval='1' depends='HAVE_DOT'> + <option type='bool' id='DOT_CLEANUP' defval='1'> <docs> <![CDATA[ If the \c DOT_CLEANUP tag is set to \c YES, doxygen will -remove the intermediate dot files that are used to generate the various graphs. +remove the intermediate files that are used to generate the various graphs. + <br>Note: +This setting is not only used for dot files but also for msc and plantuml +temporary files. ]]> </docs> </option> diff --git a/src/configgen.py b/src/configgen.py index 4ffa8f8..063c1f4 100755 --- a/src/configgen.py +++ b/src/configgen.py @@ -62,7 +62,7 @@ def transformDocs(doc): # fallback for not handled doc = re.sub('\\\\ref', '', doc) #<a href="address">description</a> -> description (see: address) - doc = re.sub('<a +href="([^"]*)" *>([^<]*)</a>', '\\2 (see: \\1)', doc) + doc = re.sub('<a +href="([^"]*)" *>([^<]*)</a>', '\\2 (see: \n\\1)', doc) # LaTeX name as formula -> LaTeX doc = doc.replace("\\f$\\mbox{\\LaTeX}\\f$", "LaTeX") # Other formula's (now just 2) so explicitly mentioned. diff --git a/src/configimpl.l b/src/configimpl.l index ed23a12..cad0095 100644 --- a/src/configimpl.l +++ b/src/configimpl.l @@ -512,8 +512,8 @@ static int g_inputPosition; static int g_yyLineNr; static QCString g_yyFileName; static QCString g_tmpString; +static QCString g_cmd; static QCString *g_string=0; -static bool *g_bool=0; static StringVector *g_list=0; static int g_lastState; static QCString g_elemStr; @@ -523,6 +523,7 @@ static int g_includeDepth; static bool g_configUpdate = FALSE; static QCString g_encoding; static ConfigImpl *g_config; +static int g_part; /* ----------------------------------------------------------------- */ @@ -686,11 +687,9 @@ static void readIncludeFile(const char *incName) %x SkipComment %x SkipInvalid %x GetString -%x GetBool %x GetStrList %x GetStrList1 %x GetQuotedString -%x GetEnvVar %x Include %% @@ -701,15 +700,16 @@ static void readIncludeFile(const char *incName) BEGIN(Start); unput(*yytext); } -<Start,GetString,GetStrList,GetStrList1,GetBool,SkipInvalid>"##".*"\n" { g_config->appendUserComment(yytext);g_yyLineNr++;} -<Start,GetString,GetStrList,GetStrList1,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(); - ConfigOption *option = g_config->get(cmd); +<Start,GetString,GetStrList,GetStrList1,SkipInvalid>"##".*"\n" { g_config->appendUserComment(yytext);g_yyLineNr++;} +<Start,GetString,GetStrList,GetStrList1,SkipInvalid>"#" { BEGIN(SkipComment); } +<Start>[a-z_A-Z][a-z_A-Z0-9]*[ \t]*"=" { g_cmd=yytext; + g_cmd=g_cmd.left(g_cmd.length()-1).stripWhiteSpace(); + g_part=0; + ConfigOption *option = g_config->get(g_cmd); if (option==0) // oops not known { config_warn("ignoring unsupported tag '%s' at line %d, file %s\n", - cmd.data(),g_yyLineNr,g_yyFileName.data()); + g_cmd.data(),g_yyLineNr,g_yyFileName.data()); BEGIN(SkipInvalid); } else // known tag @@ -726,7 +726,7 @@ static void readIncludeFile(const char *incName) g_list = ((ConfigList *)option)->valueRef(); g_list->clear(); g_elemStr=""; - if (cmd == "PREDEFINED") + if (g_cmd == "PREDEFINED") { BEGIN(GetStrList1); } @@ -759,13 +759,13 @@ static void readIncludeFile(const char *incName) if (g_configUpdate) { config_warn("Tag '%s' at line %d of file '%s' has become obsolete.\n" - " This tag has been removed.\n", cmd.data(),g_yyLineNr,g_yyFileName.data()); + " This tag has been removed.\n", g_cmd.data(),g_yyLineNr,g_yyFileName.data()); } else { config_warn("Tag '%s' at line %d of file '%s' has become obsolete.\n" " To avoid this warning please remove this line from your configuration " - "file or upgrade it using \"doxygen -u\"\n", cmd.data(),g_yyLineNr,g_yyFileName.data()); + "file or upgrade it using \"doxygen -u\"\n", g_cmd.data(),g_yyLineNr,g_yyFileName.data()); } BEGIN(SkipInvalid); break; @@ -773,26 +773,26 @@ static void readIncludeFile(const char *incName) if (g_configUpdate) { config_warn("Tag '%s' at line %d of file '%s' belongs to an option that was not enabled at compile time.\n" - " This tag has been removed.\n", cmd.data(),g_yyLineNr,g_yyFileName.data()); + " This tag has been removed.\n", g_cmd.data(),g_yyLineNr,g_yyFileName.data()); } else { config_warn("Tag '%s' at line %d of file '%s' belongs to an option that was not enabled at compile time.\n" " To avoid this warning please remove this line from your configuration " - "file or upgrade it using \"doxygen -u\", or recompile doxygen with this feature enabled.\n", cmd.data(),g_yyLineNr,g_yyFileName.data()); + "file or upgrade it using \"doxygen -u\", or recompile doxygen with this feature enabled.\n", g_cmd.data(),g_yyLineNr,g_yyFileName.data()); } BEGIN(SkipInvalid); break; } } } -<Start>[a-z_A-Z][a-z_A-Z0-9]*[ \t]*"+=" { QCString cmd=yytext; - cmd=cmd.left(cmd.length()-2).stripWhiteSpace(); - ConfigOption *option = g_config->get(cmd); +<Start>[a-z_A-Z][a-z_A-Z0-9]*[ \t]*"+=" { g_cmd=yytext; + g_cmd=g_cmd.left(g_cmd.length()-2).stripWhiteSpace(); + ConfigOption *option = g_config->get(g_cmd); if (option==0) // oops not known { config_warn("ignoring unsupported tag '%s' at line %d, file %s\n", - cmd.data(),g_yyLineNr,g_yyFileName.data()); + g_cmd.data(),g_yyLineNr,g_yyFileName.data()); BEGIN(SkipInvalid); } else // known tag @@ -807,7 +807,7 @@ static void readIncludeFile(const char *incName) case ConfigOption::O_List: g_list = ((ConfigList *)option)->valueRef(); g_elemStr=""; - if (cmd == "PREDEFINED") + if (g_cmd == "PREDEFINED") { BEGIN(GetStrList1); } @@ -827,13 +827,13 @@ static void readIncludeFile(const char *incName) case ConfigOption::O_Obsolete: config_warn("Tag '%s' at line %d of file %s has become obsolete.\n" "To avoid this warning please update your configuration " - "file using \"doxygen -u\"\n", cmd.data(),g_yyLineNr,g_yyFileName.data()); + "file using \"doxygen -u\"\n", g_cmd.data(),g_yyLineNr,g_yyFileName.data()); BEGIN(SkipInvalid); break; case ConfigOption::O_Disabled: config_warn("Tag '%s' at line %d of file %s belongs to an option that was not enabled at compile time.\n" "To avoid this warning please remove this line from your configuration " - "file, upgrade it using \"doxygen -u\", or recompile doxygen with this feature enabled.\n", cmd.data(),g_yyLineNr,g_yyFileName.data()); + "file, upgrade it using \"doxygen -u\", or recompile doxygen with this feature enabled.\n", g_cmd.data(),g_yyLineNr,g_yyFileName.data()); BEGIN(SkipInvalid); break; } @@ -869,7 +869,7 @@ static void readIncludeFile(const char *incName) } <Start>[a-z_A-Z0-9]+ { config_warn("ignoring unknown tag '%s' at line %d, file %s\n",yytext,g_yyLineNr,g_yyFileName.data()); } -<GetString,GetBool,SkipInvalid>\n { g_yyLineNr++; BEGIN(Start); } +<GetString,SkipInvalid>\n { g_yyLineNr++; BEGIN(Start); } <GetStrList,GetStrList1>\n { g_yyLineNr++; if (!g_elemStr.isEmpty()) @@ -895,8 +895,26 @@ static void readIncludeFile(const char *incName) } g_elemStr.resize(0); } -<GetString>[^ \"\t\r\n]+ { (*g_string)+=configStringRecode(yytext,g_encoding,"UTF-8"); - checkEncoding(); +<GetString>[^ \"\t\r\n]+ { + // for each command we only want 1 warning + if (g_part==1) + { + config_warn("Invalid value for '%s' tag in line %d, file %s\n" + "Value should not contain unquoted whitespace, " + "using the default.\n", + g_cmd.data(),g_yyLineNr,g_yyFileName.data()); + (*g_string)=""; + } + else if (g_part > 1) + { + (*g_string)=""; + } + else + { + (*g_string)+=configStringRecode(yytext,g_encoding,"UTF-8"); + checkEncoding(); + } + g_part++; } <GetString,GetStrList,GetStrList1,SkipInvalid>"\"" { g_lastState=YY_START; BEGIN(GetQuotedString); @@ -908,8 +926,25 @@ static void readIncludeFile(const char *incName) //printf("Quoted String = '%s'\n",g_tmpString.data()); if (g_lastState==GetString) { - (*g_string)+=configStringRecode(g_tmpString,g_encoding,"UTF-8"); - checkEncoding(); + // for each command we only want 1 warning + if (g_part==1) + { + config_warn("Invalid value for '%s' tag in line %d, file %s\n" + "Value should not contain unquoted whitespace, " + "using the default.\n", + g_cmd.data(),g_yyLineNr,g_yyFileName.data()); + (*g_string)=""; + } + else if (g_part > 1) + { + (*g_string)=""; + } + else + { + (*g_string)+=configStringRecode(g_tmpString,g_encoding,"UTF-8"); + checkEncoding(); + } + g_part++; } else { @@ -922,25 +957,13 @@ static void readIncludeFile(const char *incName) } BEGIN(g_lastState); } +<GetQuotedString>("\\\\"|"@\\"|"\\@"|"@@") { + g_tmpString+=yytext; + } <GetQuotedString>"\\\"" { g_tmpString+='"'; } <GetQuotedString>. { g_tmpString+=*yytext; } -<GetBool>[a-zA-Z]+ { - QCString bs=yytext; - bs=bs.upper(); - if (bs=="YES" || bs=="1") - *g_bool=TRUE; - else if (bs=="NO" || bs=="0") - *g_bool=FALSE; - else - { - *g_bool=FALSE; - config_warn("Invalid value '%s' for " - "boolean tag in line %d, file %s; use YES or NO\n", - bs.data(),g_yyLineNr,g_yyFileName.data()); - } - } <GetStrList1>[^ \#\"\t\r\n]+ { g_elemStr+=configStringRecode(yytext,g_encoding,"UTF-8"); } @@ -949,8 +972,10 @@ static void readIncludeFile(const char *incName) } <SkipComment>\n { g_yyLineNr++; BEGIN(Start); } <SkipComment>\\[ \r\t]*\n { g_yyLineNr++; BEGIN(Start); } +<SkipComment,SkipInvalid>. <*>\\[ \r\t]*\n { g_yyLineNr++; } -<*>. +<*>[ \t\r] +<*>. { config_warn("ignoring unknown character '%c' at line %d, file %s\n",yytext[0],g_yyLineNr,g_yyFileName.data()); } <*>\n { g_yyLineNr++ ; } %% diff --git a/src/context.cpp b/src/context.cpp index 29a704a..074e6ec 100644 --- a/src/context.cpp +++ b/src/context.cpp @@ -1301,8 +1301,8 @@ static TemplateVariant parseDoc(const Definition *def,const QCString &file,int l static TemplateVariant parseCode(MemberDef *md,const QCString &scopeName,const QCString &relPath, const QCString &code,int startLine=-1,int endLine=-1,bool showLineNumbers=FALSE) { - CodeParserInterface &intf = Doxygen::parserManager->getCodeParser(md->getDefFileExtension()); - intf.resetCodeParserState(); + auto intf = Doxygen::parserManager->getCodeParser(md->getDefFileExtension()); + intf->resetCodeParserState(); QGString s; FTextStream t(&s); switch (g_globals.outputFormat) @@ -1310,14 +1310,14 @@ static TemplateVariant parseCode(MemberDef *md,const QCString &scopeName,const Q case ContextOutputFormat_Html: { HtmlCodeGenerator codeGen(t,relPath); - intf.parseCode(codeGen,scopeName,code,md->getLanguage(),FALSE,0,md->getBodyDef(), + intf->parseCode(codeGen,scopeName,code,md->getLanguage(),FALSE,0,md->getBodyDef(), startLine,endLine,TRUE,md,showLineNumbers,md); } break; case ContextOutputFormat_Latex: { LatexCodeGenerator codeGen(t,relPath,md->docFile()); - intf.parseCode(codeGen,scopeName,code,md->getLanguage(),FALSE,0,md->getBodyDef(), + intf->parseCode(codeGen,scopeName,code,md->getLanguage(),FALSE,0,md->getBodyDef(), startLine,endLine,TRUE,md,showLineNumbers,md); } break; @@ -1332,8 +1332,8 @@ static TemplateVariant parseCode(MemberDef *md,const QCString &scopeName,const Q static TemplateVariant parseCode(const FileDef *fd,const QCString &relPath) { static bool filterSourceFiles = Config_getBool(FILTER_SOURCE_FILES); - CodeParserInterface &intf = Doxygen::parserManager->getCodeParser(fd->getDefFileExtension()); - intf.resetCodeParserState(); + auto intf = Doxygen::parserManager->getCodeParser(fd->getDefFileExtension()); + intf->resetCodeParserState(); QGString s; FTextStream t(&s); switch (g_globals.outputFormat) @@ -1341,7 +1341,7 @@ static TemplateVariant parseCode(const FileDef *fd,const QCString &relPath) case ContextOutputFormat_Html: { HtmlCodeGenerator codeGen(t,relPath); - intf.parseCode(codeGen,0, + intf->parseCode(codeGen,0, fileToString(fd->absFilePath(),filterSourceFiles,TRUE), // the sources fd->getLanguage(), // lang FALSE, // isExampleBlock @@ -1360,7 +1360,7 @@ static TemplateVariant parseCode(const FileDef *fd,const QCString &relPath) case ContextOutputFormat_Latex: { LatexCodeGenerator codeGen(t,relPath,fd->docFile()); - intf.parseCode(codeGen,0, + intf->parseCode(codeGen,0, fileToString(fd->absFilePath(),filterSourceFiles,TRUE), // the sources fd->getLanguage(), // lang FALSE, // isExampleBlock @@ -1554,16 +1554,14 @@ class DefinitionContext QCString result = "unspecified"; switch (m_def->definitionType()) { - case DefinitionIntf::TypeClass: result="class"; break; - case DefinitionIntf::TypeFile: result="file"; break; - case DefinitionIntf::TypeNamespace: result="namespace"; break; - case DefinitionIntf::TypeGroup: result="module"; break; - case DefinitionIntf::TypePackage: result="package"; break; - case DefinitionIntf::TypePage: result="page"; break; - case DefinitionIntf::TypeDir: result="dir"; break; - case DefinitionIntf::TypeMember: // fall through - case DefinitionIntf::TypeSymbolList: - break; + case Definition::TypeClass: result="class"; break; + case Definition::TypeFile: result="file"; break; + case Definition::TypeNamespace: result="namespace"; break; + case Definition::TypeGroup: result="module"; break; + case Definition::TypePackage: result="package"; break; + case Definition::TypePage: result="page"; break; + case Definition::TypeDir: result="dir"; break; + case Definition::TypeMember: break; } return result; } @@ -1587,9 +1585,9 @@ class DefinitionContext { fillPath(outerScope,list); } - else if (type==Definition::TypeFile && (dynamic_cast<const FileDef*>(def))->getDirDef()) + else if (type==Definition::TypeFile && (toFileDef(def))->getDirDef()) { - fillPath((dynamic_cast<const FileDef*>(def))->getDirDef(),list); + fillPath((toFileDef(def))->getDirDef(),list); } list->append(NavPathElemContext::alloc(def)); } @@ -1603,9 +1601,9 @@ class DefinitionContext { fillPath(m_def->getOuterScope(),list); } - else if (m_def->definitionType()==Definition::TypeFile && (dynamic_cast<const FileDef *>(m_def))->getDirDef()) + else if (m_def->definitionType()==Definition::TypeFile && (toFileDef(m_def))->getDirDef()) { - fillPath((dynamic_cast<const FileDef *>(m_def))->getDirDef(),list); + fillPath((toFileDef(m_def))->getDirDef(),list); } cache.navPath.reset(list); } @@ -1672,7 +1670,6 @@ class DefinitionContext SharedPtr<TemplateStruct> lineLink; }; - private: Cachable &getCache() const { @@ -1680,7 +1677,7 @@ class DefinitionContext assert(c!=0); return *c; } - const Definition *m_def; + const Definition *m_def; }; //%% } @@ -2375,7 +2372,7 @@ class ClassContext::Private : public DefinitionContext<ClassContext::Private> { addTemplateDecls(parent,tl); } - const ClassDef *cd=dynamic_cast<const ClassDef *>(d); + const ClassDef *cd=toClassDef(d); if (!cd->templateArguments().empty()) { ArgumentListContext *al = ArgumentListContext::alloc(cd->templateArguments(),cd,relPathAsString()); @@ -3805,6 +3802,7 @@ class TextGeneratorHtml : public TextGeneratorIntf : m_ts(ts), m_relPath(relPath) {} void writeString(const char *s,bool keepSpaces) const { + static const char *hex="0123456789ABCDEF"; if (s==0) return; if (keepSpaces) { @@ -3820,6 +3818,19 @@ class TextGeneratorHtml : public TextGeneratorIntf case '"': m_ts << """; break; case '&': m_ts << "&"; break; case ' ': m_ts << " "; break; + default: + { + uchar uc = static_cast<uchar>(c); + if (uc<32 && !isspace(c)) // non-printable control characters + { + m_ts << "$" << hex[uc>>4] << hex[uc&0xF] << ";"; + } + else + { + m_ts << c; + } + } + break; } } } @@ -3896,13 +3907,25 @@ class TextGeneratorLatex : public TextGeneratorIntf if (f && anchor) m_ts << "_"; if (anchor) m_ts << anchor; m_ts << "}{"; - filterLatexString(m_ts,text); + filterLatexString(m_ts,text, + false, // insideTabbing + false, // insidePre + false, // insideItem + false, // insideTable + false // keepSpaces + ); m_ts << "}}"; } else { m_ts << "\\textbf{ "; - filterLatexString(m_ts,text); + filterLatexString(m_ts,text, + false, // insideTabbing + false, // insidePre + false, // insideItem + false, // insideTable + false // keepSpaces + ); m_ts << "}"; } } @@ -4931,7 +4954,7 @@ class MemberContext::Private : public DefinitionContext<MemberContext::Private> Cachable &cache = getCache(); if (!cache.sourceRefs) { - cache.sourceRefs.reset(MemberListContext::alloc(m_memberDef->getReferencesMembers(),TRUE)); + cache.sourceRefs.reset(MemberListContext::alloc(m_memberDef->getReferencesMembers())); } return cache.sourceRefs.get(); } @@ -4940,7 +4963,7 @@ class MemberContext::Private : public DefinitionContext<MemberContext::Private> Cachable &cache = getCache(); if (!cache.sourceRefBys) { - cache.sourceRefBys.reset(MemberListContext::alloc(m_memberDef->getReferencedByMembers(),TRUE)); + cache.sourceRefBys.reset(MemberListContext::alloc(m_memberDef->getReferencedByMembers())); } return cache.sourceRefBys.get(); } @@ -6046,10 +6069,9 @@ class ClassHierarchyContext::Private Private() { m_classTree.reset(NestingContext::alloc(0,0)); - initClassHierarchy(Doxygen::classSDict); - initClassHierarchy(Doxygen::hiddenClasses); - m_classTree->addClassHierarchy(*Doxygen::classSDict,TRUE); - m_classTree->addClassHierarchy(*Doxygen::hiddenClasses,TRUE); + ClassDefSet visitedClasses; + m_classTree->addClassHierarchy(*Doxygen::classSDict,visitedClasses); + m_classTree->addClassHierarchy(*Doxygen::hiddenClasses,visitedClasses); //%% ClassInheritance tree static bool init=FALSE; if (!init) @@ -6104,15 +6126,10 @@ class ClassHierarchyContext::Private { TemplateList *diagrams = TemplateList::alloc(); DotGfxHierarchyTable *hierarchy = getHierarchy(); - if (hierarchy->subGraphs()) + int id=0; + for (auto n : hierarchy->subGraphs()) { - int id=0; - QListIterator<DotNode> li(*hierarchy->subGraphs()); - DotNode *n; - for (li.toFirst();(n=li.current());++li) - { - diagrams->append(InheritanceGraphContext::alloc(hierarchy,n,id++)); - } + diagrams->append(InheritanceGraphContext::alloc(hierarchy,n,id++)); } m_cache.diagrams.reset(diagrams); } @@ -6191,7 +6208,8 @@ class NestingNodeContext::Private { public: Private(const NestingNodeContext *parent,const NestingNodeContext *thisNode, - const 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, + ClassDefSet &visitedClasses) : m_parent(parent), m_def(d), m_level(level), m_index(index) { m_children.reset(NestingContext::alloc(thisNode,level+1)); @@ -6231,11 +6249,11 @@ class NestingNodeContext::Private init=TRUE; } - addNamespaces(addCls); - addClasses(inherit,hideSuper); - addDirFiles(); - addPages(); - addModules(); + addNamespaces(addCls,visitedClasses); + addClasses(inherit,hideSuper,visitedClasses); + addDirFiles(visitedClasses); + addPages(visitedClasses); + addModules(visitedClasses); } TemplateVariant get(const char *n) const { @@ -6253,7 +6271,7 @@ class NestingNodeContext::Private { if (!m_cache.classContext && m_def->definitionType()==Definition::TypeClass) { - m_cache.classContext.reset(ClassContext::alloc(dynamic_cast<const ClassDef*>(m_def))); + m_cache.classContext.reset(ClassContext::alloc(toClassDef(m_def))); } if (m_cache.classContext) { @@ -6268,7 +6286,7 @@ class NestingNodeContext::Private { if (!m_cache.namespaceContext && m_def->definitionType()==Definition::TypeNamespace) { - m_cache.namespaceContext.reset(NamespaceContext::alloc(dynamic_cast<const NamespaceDef*>(m_def))); + m_cache.namespaceContext.reset(NamespaceContext::alloc(toNamespaceDef(m_def))); } if (m_cache.namespaceContext) { @@ -6283,7 +6301,7 @@ class NestingNodeContext::Private { if (!m_cache.dirContext && m_def->definitionType()==Definition::TypeDir) { - m_cache.dirContext.reset(DirContext::alloc(dynamic_cast<const DirDef*>(m_def))); + m_cache.dirContext.reset(DirContext::alloc(toDirDef(m_def))); } if (m_cache.dirContext) { @@ -6298,7 +6316,7 @@ class NestingNodeContext::Private { if (!m_cache.fileContext && m_def->definitionType()==Definition::TypeFile) { - m_cache.fileContext.reset(FileContext::alloc(dynamic_cast<const FileDef*>(m_def))); + m_cache.fileContext.reset(FileContext::alloc(toFileDef(m_def))); } if (m_cache.fileContext) { @@ -6313,7 +6331,7 @@ class NestingNodeContext::Private { if (!m_cache.pageContext && m_def->definitionType()==Definition::TypePage) { - m_cache.pageContext.reset(PageContext::alloc(dynamic_cast<const PageDef*>(m_def),FALSE,FALSE)); + m_cache.pageContext.reset(PageContext::alloc(toPageDef(m_def),FALSE,FALSE)); } if (m_cache.pageContext) { @@ -6328,7 +6346,7 @@ class NestingNodeContext::Private { if (!m_cache.moduleContext && m_def->definitionType()==Definition::TypeGroup) { - m_cache.moduleContext.reset(ModuleContext::alloc(dynamic_cast<const GroupDef*>(m_def))); + m_cache.moduleContext.reset(ModuleContext::alloc(toGroupDef(m_def))); } if (m_cache.moduleContext) { @@ -6398,23 +6416,23 @@ class NestingNodeContext::Private //------------------------------------------------------------------ - void addClasses(bool inherit, bool hideSuper) + void addClasses(bool inherit, bool hideSuper,ClassDefSet &visitedClasses) { - const ClassDef *cd = dynamic_cast<const ClassDef*>(m_def); + const ClassDef *cd = toClassDef(m_def); if (cd && inherit) { - bool hasChildren = !cd->isVisited() && !hideSuper && classHasVisibleChildren(cd); + bool hasChildren = visitedClasses.find(cd)==visitedClasses.end() && + !hideSuper && classHasVisibleChildren(cd); if (hasChildren) { - bool wasVisited=cd->isVisited(); - cd->setVisited(TRUE); + visitedClasses.insert(cd); if (cd->getLanguage()==SrcLangExt_VHDL) { - m_children->addDerivedClasses(cd->baseClasses(),wasVisited); + m_children->addDerivedClasses(cd->baseClasses(),false,visitedClasses); } else { - m_children->addDerivedClasses(cd->subClasses(),wasVisited); + m_children->addDerivedClasses(cd->subClasses(),false,visitedClasses); } } } @@ -6422,48 +6440,48 @@ class NestingNodeContext::Private { if (cd && cd->getClassSDict()) { - m_children->addClasses(*cd->getClassSDict(),FALSE); + m_children->addClasses(*cd->getClassSDict(),FALSE,visitedClasses); } } } - void addNamespaces(bool addClasses) + void addNamespaces(bool addClasses,ClassDefSet &visitedClasses) { - const NamespaceDef *nd = dynamic_cast<const NamespaceDef*>(m_def); + const NamespaceDef *nd = toNamespaceDef(m_def); if (nd && nd->getNamespaceSDict()) { - m_children->addNamespaces(*nd->getNamespaceSDict(),FALSE,addClasses); + m_children->addNamespaces(*nd->getNamespaceSDict(),FALSE,addClasses,visitedClasses); } if (addClasses && nd && nd->getClassSDict()) { - m_children->addClasses(*nd->getClassSDict(),FALSE); + m_children->addClasses(*nd->getClassSDict(),FALSE,visitedClasses); } } - void addDirFiles() + void addDirFiles(ClassDefSet &visitedClasses) { - const DirDef *dd = dynamic_cast<const DirDef*>(m_def); + const DirDef *dd = toDirDef(m_def); if (dd) { - m_children->addDirs(dd->subDirs()); + m_children->addDirs(dd->subDirs(),visitedClasses); if (dd && dd->getFiles()) { - m_children->addFiles(*dd->getFiles()); + m_children->addFiles(*dd->getFiles(),visitedClasses); } } } - void addPages() + void addPages(ClassDefSet &visitedClasses) { - const PageDef *pd = dynamic_cast<const PageDef*>(m_def); + const PageDef *pd = toPageDef(m_def); if (pd && pd->getSubPages()) { - m_children->addPages(*pd->getSubPages(),FALSE); + m_children->addPages(*pd->getSubPages(),FALSE,visitedClasses); } } - void addModules() + void addModules(ClassDefSet &visitedClasses) { - const GroupDef *gd = dynamic_cast<const GroupDef*>(m_def); + const GroupDef *gd = toGroupDef(m_def); if (gd && gd->getSubGroups()) { - m_children->addModules(*gd->getSubGroups()); + m_children->addModules(*gd->getSubGroups(),visitedClasses); } } private: @@ -6490,10 +6508,11 @@ class NestingNodeContext::Private PropertyMapper<NestingNodeContext::Private> NestingNodeContext::Private::s_inst; NestingNodeContext::NestingNodeContext(const NestingNodeContext *parent, - const 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, + ClassDefSet &visitedClasses) : RefCountedContext("NestingNodeContext") { - p = new Private(parent,this,d,index,level,addClass,inherit,hideSuper); + p = new Private(parent,this,d,index,level,addClass,inherit,hideSuper,visitedClasses); } NestingNodeContext::~NestingNodeContext() @@ -6520,7 +6539,7 @@ class NestingContext::Private : public GenericNodeListContext Private(const NestingNodeContext *parent,int level) : m_parent(parent), m_level(level), m_index(0) {} - void addNamespaces(const NamespaceSDict &nsDict,bool rootOnly,bool addClasses) + void addNamespaces(const NamespaceSDict &nsDict,bool rootOnly,bool addClasses,ClassDefSet &visitedClasses) { NamespaceSDict::Iterator nli(nsDict); const NamespaceDef *nd; @@ -6529,18 +6548,18 @@ class NestingContext::Private : public GenericNodeListContext if (!nd->isAnonymous() && (!rootOnly || nd->getOuterScope()==Doxygen::globalScope)) { - bool hasChildren = namespaceHasVisibleChild(nd,addClasses,false,ClassDef::Class); + bool hasChildren = namespaceHasNestedNamespace(nd); bool isLinkable = nd->isLinkableInProject(); if (isLinkable || hasChildren) { - NestingNodeContext *nnc = NestingNodeContext::alloc(m_parent,nd,m_index,m_level,addClasses,FALSE,FALSE); + NestingNodeContext *nnc = NestingNodeContext::alloc(m_parent,nd,m_index,m_level,addClasses,FALSE,FALSE,visitedClasses); append(nnc); m_index++; } } } } - void addClasses(const ClassSDict &clDict,bool rootOnly) + void addClasses(const ClassSDict &clDict,bool rootOnly,ClassDefSet &visitedClasses) { ClassSDict::Iterator cli(clDict); const ClassDef *cd; @@ -6562,14 +6581,14 @@ class NestingContext::Private : public GenericNodeListContext { if (classVisibleInIndex(cd) && cd->templateMaster()==0) { - NestingNodeContext *nnc = NestingNodeContext::alloc(m_parent,cd,m_index,m_level,TRUE,FALSE,FALSE); + NestingNodeContext *nnc = NestingNodeContext::alloc(m_parent,cd,m_index,m_level,TRUE,FALSE,FALSE,visitedClasses); append(nnc); m_index++; } } } } - void addDirs(const DirSDict &dirDict) + void addDirs(const DirSDict &dirDict,ClassDefSet &visitedClasses) { SDict<DirDef>::Iterator dli(dirDict); const DirDef *dd; @@ -6577,20 +6596,20 @@ class NestingContext::Private : public GenericNodeListContext { if (dd->getOuterScope()==Doxygen::globalScope) { - append(NestingNodeContext::alloc(m_parent,dd,m_index,m_level,FALSE,FALSE,FALSE)); + append(NestingNodeContext::alloc(m_parent,dd,m_index,m_level,FALSE,FALSE,FALSE,visitedClasses)); m_index++; } } } - void addDirs(const DirList &dirList) + void addDirs(const DirList &dirList,ClassDefSet &visitedClasses) { for(const auto dd : dirList) { - append(NestingNodeContext::alloc(m_parent,dd,m_index,m_level,FALSE,FALSE,FALSE)); + append(NestingNodeContext::alloc(m_parent,dd,m_index,m_level,FALSE,FALSE,FALSE,visitedClasses)); m_index++; } } - void addFiles(const FileNameLinkedMap &fnList) + void addFiles(const FileNameLinkedMap &fnList,ClassDefSet &visitedClasses) { for (const FileNameLinkedMap::Ptr &fn : fnList) { @@ -6598,23 +6617,23 @@ class NestingContext::Private : public GenericNodeListContext { if (fd->getDirDef()==0) // top level file { - append(NestingNodeContext::alloc(m_parent,fd.get(),m_index,m_level,FALSE,FALSE,FALSE)); + append(NestingNodeContext::alloc(m_parent,fd.get(),m_index,m_level,FALSE,FALSE,FALSE,visitedClasses)); m_index++; } } } } - void addFiles(const FileList &fList) + void addFiles(const FileList &fList,ClassDefSet &visitedClasses) { QListIterator<FileDef> li(fList); const FileDef *fd; for (li.toFirst();(fd=li.current());++li) { - append(NestingNodeContext::alloc(m_parent,fd,m_index,m_level,FALSE,FALSE,FALSE)); + append(NestingNodeContext::alloc(m_parent,fd,m_index,m_level,FALSE,FALSE,FALSE,visitedClasses)); m_index++; } } - void addPages(const PageSDict &pages,bool rootOnly) + void addPages(const PageSDict &pages,bool rootOnly,ClassDefSet &visitedClasses) { SDict<PageDef>::Iterator pli(pages); const PageDef *pd; @@ -6624,12 +6643,12 @@ class NestingContext::Private : public GenericNodeListContext pd->getOuterScope()==0 || pd->getOuterScope()->definitionType()!=Definition::TypePage) { - append(NestingNodeContext::alloc(m_parent,pd,m_index,m_level,FALSE,FALSE,FALSE)); + append(NestingNodeContext::alloc(m_parent,pd,m_index,m_level,FALSE,FALSE,FALSE,visitedClasses)); m_index++; } } } - void addModules(const GroupSDict &groups) + void addModules(const GroupSDict &groups,ClassDefSet &visitedClasses) { GroupSDict::Iterator gli(groups); const GroupDef *gd; @@ -6640,12 +6659,12 @@ class NestingContext::Private : public GenericNodeListContext (!gd->isReference() || externalGroups) ) { - append(NestingNodeContext::alloc(m_parent,gd,m_index,m_level,FALSE,FALSE,FALSE)); + append(NestingNodeContext::alloc(m_parent,gd,m_index,m_level,FALSE,FALSE,FALSE,visitedClasses)); m_index++; } } } - void addModules(const GroupList &list) + void addModules(const GroupList &list,ClassDefSet &visitedClasses) { GroupListIterator gli(list); const GroupDef *gd; @@ -6653,19 +6672,16 @@ class NestingContext::Private : public GenericNodeListContext { if (gd->isVisible()) { - append(NestingNodeContext::alloc(m_parent,gd,m_index,m_level,FALSE,FALSE,FALSE)); + append(NestingNodeContext::alloc(m_parent,gd,m_index,m_level,FALSE,FALSE,FALSE,visitedClasses)); m_index++; } } } - void addDerivedClasses(const BaseClassList *bcl,bool hideSuper) + void addDerivedClasses(const BaseClassList &bcl,bool hideSuper,ClassDefSet &visitedClasses) { - if (bcl==0) return; - BaseClassListIterator bcli(*bcl); - BaseClassDef *bcd; - for (bcli.toFirst() ; (bcd=bcli.current()) ; ++bcli) + for (const auto &bcd : bcl) { - const ClassDef *cd=bcd->classDef; + const ClassDef *cd=bcd.classDef; if (cd->getLanguage()==SrcLangExt_VHDL && (VhdlDocGen::VhdlClasses)cd->protection()!=VhdlDocGen::ENTITYCLASS) { continue; @@ -6683,13 +6699,13 @@ class NestingContext::Private : public GenericNodeListContext if (cd->isVisibleInHierarchy() && b) { - NestingNodeContext *tnc = NestingNodeContext::alloc(m_parent,cd,m_index,m_level,TRUE,TRUE,hideSuper); + NestingNodeContext *tnc = NestingNodeContext::alloc(m_parent,cd,m_index,m_level,TRUE,TRUE,hideSuper,visitedClasses); append(tnc); m_index++; } } } - void addClassHierarchy(const ClassSDict &classSDict,bool) + void addClassHierarchy(const ClassSDict &classSDict,ClassDefSet &visitedClasses) { ClassSDict::Iterator cli(classSDict); const ClassDef *cd; @@ -6713,7 +6729,7 @@ class NestingContext::Private : public GenericNodeListContext if (cd->isVisibleInHierarchy()) // should it be visible { // new root level class - NestingNodeContext *nnc = NestingNodeContext::alloc(m_parent,cd,m_index,m_level,TRUE,TRUE,cd->isVisited()); + NestingNodeContext *nnc = NestingNodeContext::alloc(m_parent,cd,m_index,m_level,TRUE,TRUE,FALSE,visitedClasses); append(nnc); m_index++; } @@ -6753,59 +6769,59 @@ TemplateListIntf::ConstIterator *NestingContext::createIterator() const return p->createIterator(); } -void NestingContext::addClasses(const ClassSDict &clDict,bool rootOnly) +void NestingContext::addClasses(const ClassSDict &clDict,bool rootOnly,ClassDefSet &visitedClasses) { - p->addClasses(clDict,rootOnly); + p->addClasses(clDict,rootOnly,visitedClasses); } -void NestingContext::addNamespaces(const NamespaceSDict &nsDict,bool rootOnly,bool addClasses) +void NestingContext::addNamespaces(const NamespaceSDict &nsDict,bool rootOnly,bool addClasses,ClassDefSet &visitedClasses) { - p->addNamespaces(nsDict,rootOnly,addClasses); + p->addNamespaces(nsDict,rootOnly,addClasses,visitedClasses); } -void NestingContext::addDirs(const DirSDict &dirs) +void NestingContext::addDirs(const DirSDict &dirs,ClassDefSet &visitedClasses) { - p->addDirs(dirs); + p->addDirs(dirs,visitedClasses); } -void NestingContext::addDirs(const DirList &dirs) +void NestingContext::addDirs(const DirList &dirs,ClassDefSet &visitedClasses) { - p->addDirs(dirs); + p->addDirs(dirs,visitedClasses); } -void NestingContext::addFiles(const FileNameLinkedMap &files) +void NestingContext::addFiles(const FileNameLinkedMap &files,ClassDefSet &visitedClasses) { - p->addFiles(files); + p->addFiles(files,visitedClasses); } -void NestingContext::addFiles(const FileList &files) +void NestingContext::addFiles(const FileList &files,ClassDefSet &visitedClasses) { - p->addFiles(files); + p->addFiles(files,visitedClasses); } -void NestingContext::addPages(const PageSDict &pages,bool rootOnly) +void NestingContext::addPages(const PageSDict &pages,bool rootOnly,ClassDefSet &visitedClasses) { - p->addPages(pages,rootOnly); + p->addPages(pages,rootOnly,visitedClasses); } -void NestingContext::addModules(const GroupSDict &modules) +void NestingContext::addModules(const GroupSDict &modules,ClassDefSet &visitedClasses) { - p->addModules(modules); + p->addModules(modules,visitedClasses); } -void NestingContext::addModules(const GroupList &modules) +void NestingContext::addModules(const GroupList &modules,ClassDefSet &visitedClasses) { - p->addModules(modules); + p->addModules(modules,visitedClasses); } -void NestingContext::addClassHierarchy(const ClassSDict &classSDict,bool rootOnly) +void NestingContext::addClassHierarchy(const ClassSDict &classSDict,ClassDefSet &visitedClasses) { - p->addClassHierarchy(classSDict,rootOnly); + p->addClassHierarchy(classSDict,visitedClasses); } -void NestingContext::addDerivedClasses(const BaseClassList *bcl,bool hideSuper) +void NestingContext::addDerivedClasses(const BaseClassList &bcl,bool hideSuper,ClassDefSet &visitedClasses) { - p->addDerivedClasses(bcl,hideSuper); + p->addDerivedClasses(bcl,hideSuper,visitedClasses); } //------------------------------------------------------------------------ @@ -6818,13 +6834,14 @@ class ClassTreeContext::Private Private() { m_classTree.reset(NestingContext::alloc(0,0)); + ClassDefSet visitedClasses; if (Doxygen::namespaceSDict) { - m_classTree->addNamespaces(*Doxygen::namespaceSDict,TRUE,TRUE); + m_classTree->addNamespaces(*Doxygen::namespaceSDict,TRUE,TRUE,visitedClasses); } if (Doxygen::classSDict) { - m_classTree->addClasses(*Doxygen::classSDict,TRUE); + m_classTree->addClasses(*Doxygen::classSDict,TRUE,visitedClasses); } //%% Nesting tree static bool init=FALSE; @@ -6990,9 +7007,10 @@ class NamespaceTreeContext::Private Private() { m_namespaceTree.reset(NestingContext::alloc(0,0)); + ClassDefSet visitedClasses; if (Doxygen::namespaceSDict) { - m_namespaceTree->addNamespaces(*Doxygen::namespaceSDict,TRUE,FALSE); + m_namespaceTree->addNamespaces(*Doxygen::namespaceSDict,TRUE,FALSE,visitedClasses); } //%% Nesting tree static bool init=FALSE; @@ -7262,13 +7280,14 @@ class FileTreeContext::Private { // Add dirs tree m_dirFileTree.reset(NestingContext::alloc(0,0)); + ClassDefSet visitedClasses; if (Doxygen::directories) { - m_dirFileTree->addDirs(*Doxygen::directories); + m_dirFileTree->addDirs(*Doxygen::directories,visitedClasses); } if (Doxygen::inputNameLinkedMap) { - m_dirFileTree->addFiles(*Doxygen::inputNameLinkedMap); + m_dirFileTree->addFiles(*Doxygen::inputNameLinkedMap,visitedClasses); } //%% DirFile tree: static bool init=FALSE; @@ -7374,10 +7393,11 @@ class PageTreeContext::Private Private(const PageSDict *pages) { m_pageTree.reset(NestingContext::alloc(0,0)); + ClassDefSet visitedClasses; // Add pages if (pages) { - m_pageTree->addPages(*pages,TRUE); + m_pageTree->addPages(*pages,TRUE,visitedClasses); } //%% PageNodeList tree: @@ -7627,10 +7647,11 @@ class ModuleTreeContext::Private Private() { m_moduleTree.reset(NestingContext::alloc(0,0)); + ClassDefSet visitedClasses; // Add modules if (Doxygen::groupSDict) { - m_moduleTree->addModules(*Doxygen::groupSDict); + m_moduleTree->addModules(*Doxygen::groupSDict,visitedClasses); } //%% ModuleList tree: @@ -7770,11 +7791,11 @@ class NavPathElemContext::Private QCString text = m_def->localName(); if (type==Definition::TypeGroup) { - text = (dynamic_cast<const GroupDef*>(m_def))->groupTitle(); + text = (toGroupDef(m_def))->groupTitle(); } - else if (type==Definition::TypePage && ((dynamic_cast<const PageDef*>(m_def))->hasTitle())) + else if (type==Definition::TypePage && ((toPageDef(m_def))->hasTitle())) { - text = (dynamic_cast<const PageDef*>(m_def))->title(); + text = (toPageDef(m_def))->title(); } else if (type==Definition::TypeClass) { @@ -7832,10 +7853,11 @@ class ExampleTreeContext::Private Private() { m_exampleTree.reset(NestingContext::alloc(0,0)); + ClassDefSet visitedClasses; // Add pages if (Doxygen::exampleSDict) { - m_exampleTree->addPages(*Doxygen::exampleSDict,TRUE); + m_exampleTree->addPages(*Doxygen::exampleSDict,TRUE,visitedClasses); } static bool init=FALSE; @@ -8524,29 +8546,24 @@ class InheritanceListContext::Private : public GenericNodeListContext } }; -InheritanceListContext::InheritanceListContext(const BaseClassList *list, bool baseClasses) : RefCountedContext("InheritanceListContext") +InheritanceListContext::InheritanceListContext(const BaseClassList &list, bool baseClasses) : RefCountedContext("InheritanceListContext") { p = new Private; - if (list) + for (const auto &bcd : list) { - BaseClassListIterator li(*list); - BaseClassDef *bcd; - for (li.toFirst();(bcd=li.current());++li) + const ClassDef *cd=bcd.classDef; + QCString name; + if (baseClasses) { - const ClassDef *cd=bcd->classDef; - QCString name; - if (baseClasses) - { - name = insertTemplateSpecifierInScope( - cd->displayName(),bcd->templSpecifiers); - } - else - { - name = cd->displayName(); - } - //printf("InheritanceListContext: adding %s baseClass=%d\n",name.data(),baseClasses); - p->addClass(cd,name); + name = insertTemplateSpecifierInScope( + cd->displayName(),bcd.templSpecifiers); + } + else + { + name = cd->displayName(); } + //printf("InheritanceListContext: adding %s baseClass=%d\n",name.data(),baseClasses); + p->addClass(cd,name); } } @@ -8577,7 +8594,7 @@ TemplateListIntf::ConstIterator *InheritanceListContext::createIterator() const class MemberListContext::Private : public GenericNodeListContext { public: - void addMember(MemberDef *md) + void addMember(const MemberDef *md) { append(MemberContext::alloc(md)); } @@ -8626,6 +8643,16 @@ MemberListContext::MemberListContext(MemberSDict *list,bool doSort) : RefCounted } } +MemberListContext::MemberListContext(std::vector<const MemberDef *> &&ml) : RefCountedContext("MemberListContext") +{ + p = new Private; + for (const auto &md : ml) + { + p->addMember(md); + } + ml.clear(); +} + MemberListContext::~MemberListContext() { delete p; @@ -9044,7 +9071,7 @@ class MemberListInfoContext::Private m_def->definitionType()==Definition::TypeClass) { InheritedMemberInfoListContext *ctx = InheritedMemberInfoListContext::alloc(); - ctx->addMemberList(dynamic_cast<const ClassDef*>(m_def),m_memberList->listType(),m_title,FALSE); + ctx->addMemberList(toClassDef(m_def),m_memberList->listType(),m_title,FALSE); m_cache.inherited.reset(ctx); } if (m_cache.inherited) @@ -9270,31 +9297,26 @@ class InheritedMemberInfoListContext::Private : public GenericNodeListContext int lt2, const QCString &title,bool additionalList, QPtrDict<void> *visitedClasses) { - if (cd->baseClasses()) + for (const auto &ibcd : cd->baseClasses()) { - BaseClassListIterator it(*cd->baseClasses()); - BaseClassDef *ibcd; - for (it.toFirst();(ibcd=it.current());++it) + ClassDef *icd=ibcd.classDef; + if (icd->isLinkable()) { - ClassDef *icd=ibcd->classDef; - if (icd->isLinkable()) + int lt1,lt3; + convertProtectionLevel(lt,ibcd.prot,<1,<3); + if (lt2==-1 && lt3!=-1) { - int lt1,lt3; - convertProtectionLevel(lt,ibcd->prot,<1,<3); - if (lt2==-1 && lt3!=-1) + lt2=lt3; + } + if (visitedClasses->find(icd)==0) + { + visitedClasses->insert(icd,icd); // guard for multiple virtual inheritance + if (lt1!=-1) { - lt2=lt3; - } - if (visitedClasses->find(icd)==0) - { - visitedClasses->insert(icd,icd); // guard for multiple virtual inheritance - if (lt1!=-1) - { - // add member info for members of cd with list type lt - addInheritedMembers(inheritedFrom,icd,lt,(MemberListType)lt1,lt2,title,additionalList); - // recurse down the inheritance tree - findInheritedMembers(inheritedFrom,icd,(MemberListType)lt1,lt2,title,additionalList,visitedClasses); - } + // add member info for members of cd with list type lt + addInheritedMembers(inheritedFrom,icd,lt,(MemberListType)lt1,lt2,title,additionalList); + // recurse down the inheritance tree + findInheritedMembers(inheritedFrom,icd,(MemberListType)lt1,lt2,title,additionalList,visitedClasses); } } } @@ -9551,7 +9573,7 @@ class SymbolContext::Private const Definition *prev = m_prevDef; const Definition *nextScope = next ? next->getOuterScope() : 0; const Definition *prevScope = prev ? prev->getOuterScope() : 0; - const MemberDef *md = dynamic_cast<const MemberDef*>(m_def); + const MemberDef *md = toMemberDef(m_def); bool isFunctionLike = md && (md->isFunction() || md->isSlot() || md->isSignal()); bool overloadedFunction = isFunctionLike && ((prevScope!=0 && scope==prevScope) || (scope && scope==nextScope)); @@ -10300,25 +10322,9 @@ void generateOutputViaTemplate() } // clear all cached data in Definition objects. - QDictIterator<DefinitionIntf> di(*Doxygen::symbolMap); - const DefinitionIntf *intf; - for (;(intf=di.current());++di) + for (const auto &kv : Doxygen::symbolMap) { - if (intf->definitionType()==DefinitionIntf::TypeSymbolList) // list of symbols - { - DefinitionListIterator dli(*dynamic_cast<const DefinitionList*>(intf)); - const Definition *d; - // for each symbol - for (dli.toFirst();(d=dli.current());++dli) - { - d->setCookie(0); - } - } - else // single symbol - { - const Definition *d = dynamic_cast<const Definition *>(intf); - d->setCookie(0); - } + kv.second->setCookie(0); } e.destroyContext(ctx); diff --git a/src/context.h b/src/context.h index 7256dc6..dca5d91 100644 --- a/src/context.h +++ b/src/context.h @@ -21,15 +21,12 @@ #include <qlist.h> #include <stdio.h> #include "dirdef.h" +#include "classdef.h" class Definition; -class ClassDef; -class ClassSDict; -class BaseClassList; class PageDef; class GroupDef; class NamespaceDef; -class BaseClassList; class NamespaceSDict; class FileDef; class FileList; @@ -455,7 +452,7 @@ class ClassInheritanceNodeContext : public RefCountedContext, public TemplateStr virtual int addRef() { return RefCountedContext::addRef(); } virtual int release() { return RefCountedContext::release(); } - void addChildren(const BaseClassList *bcl,bool hideSuper); + void addChildren(const BaseClassList &bcl,bool hideSuper); private: ClassInheritanceNodeContext(const ClassDef *); @@ -510,8 +507,9 @@ class NestingNodeContext : public RefCountedContext, public TemplateStructIntf { public: 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); } + int index,int level,bool addClasses,bool inherit,bool hideSuper, + ClassDefSet &visitedClasses) + { return new NestingNodeContext(parent,def,index,level,addClasses,inherit,hideSuper,visitedClasses); } QCString id() const; @@ -522,7 +520,8 @@ class NestingNodeContext : public RefCountedContext, public TemplateStructIntf private: NestingNodeContext(const NestingNodeContext *parent, - const Definition *,int index,int level,bool addClasses,bool inherit,bool hideSuper); + const Definition *,int index,int level,bool addClasses,bool inherit,bool hideSuper, + ClassDefSet &visitedClasses); ~NestingNodeContext(); class Private; Private *p; @@ -533,6 +532,7 @@ class NestingNodeContext : public RefCountedContext, public TemplateStructIntf class NestingContext : public RefCountedContext, public TemplateListIntf { public: + static NestingContext *alloc(const NestingNodeContext *parent,int level) { return new NestingContext(parent,level); } @@ -543,17 +543,17 @@ class NestingContext : public RefCountedContext, public TemplateListIntf virtual int addRef() { return RefCountedContext::addRef(); } virtual int release() { return RefCountedContext::release(); } - void addNamespaces(const NamespaceSDict &nsDict,bool rootOnly,bool addClasses); - void addClasses(const ClassSDict &clDict,bool rootOnly); - void addDirs(const DirSDict &); - void addDirs(const DirList &); - void addFiles(const FileNameLinkedMap &); - void addFiles(const FileList &); - void addPages(const PageSDict &pages,bool rootOnly); - void addModules(const GroupSDict &modules); - void addModules(const GroupList &modules); - void addClassHierarchy(const ClassSDict &clDict,bool rootOnly); - void addDerivedClasses(const BaseClassList *bcl,bool hideSuper); + void addNamespaces(const NamespaceSDict &nsDict,bool rootOnly,bool addClasses,ClassDefSet &visitedClasses); + void addClasses(const ClassSDict &clDict,bool rootOnly,ClassDefSet &visitedClasses); + void addDirs(const DirSDict &,ClassDefSet &visitedClasses); + void addDirs(const DirList &,ClassDefSet &visitedClasses); + void addFiles(const FileNameLinkedMap &,ClassDefSet &visitedClasses); + void addFiles(const FileList &,ClassDefSet &visitedClasses); + void addPages(const PageSDict &pages,bool rootOnly,ClassDefSet &visitedClasses); + void addModules(const GroupSDict &modules,ClassDefSet &visitedClasses); + void addModules(const GroupList &modules,ClassDefSet &visitedClasses); + void addClassHierarchy(const ClassSDict &clDict,ClassDefSet &visitedClasses); + void addDerivedClasses(const BaseClassList &bcl,bool hideSuper,ClassDefSet &visitedClasses); private: NestingContext(const NestingNodeContext *parent,int level); @@ -929,7 +929,7 @@ class InheritanceNodeContext : public RefCountedContext, public TemplateStructIn class InheritanceListContext : public RefCountedContext, public TemplateListIntf { public: - static InheritanceListContext *alloc(const BaseClassList *list,bool baseClasses) + static InheritanceListContext *alloc(const BaseClassList &list,bool baseClasses) { return new InheritanceListContext(list,baseClasses); } // TemplateListIntf @@ -940,7 +940,7 @@ class InheritanceListContext : public RefCountedContext, public TemplateListIntf virtual int release() { return RefCountedContext::release(); } private: - InheritanceListContext(const BaseClassList *list,bool baseClasses); + InheritanceListContext(const BaseClassList &list,bool baseClasses); ~InheritanceListContext(); class Private; Private *p; @@ -957,6 +957,8 @@ class MemberListContext : public RefCountedContext, public TemplateListIntf { return new MemberListContext(ml); } static MemberListContext *alloc(MemberSDict *ml,bool doSort) { return new MemberListContext(ml,doSort); } + static MemberListContext *alloc(std::vector<const MemberDef *> &&ml) + { return new MemberListContext(std::move(ml)); } // TemplateListIntf virtual uint count() const; @@ -969,6 +971,7 @@ class MemberListContext : public RefCountedContext, public TemplateListIntf MemberListContext(); MemberListContext(const MemberList *ml); MemberListContext(MemberSDict *ml,bool doSort); + MemberListContext(std::vector<const MemberDef *> &&ml); ~MemberListContext(); class Private; Private *p; diff --git a/src/defargs.l b/src/defargs.l index 6ecc7ff..e25c1fe 100644 --- a/src/defargs.l +++ b/src/defargs.l @@ -511,6 +511,8 @@ RAWEND ")"[^ \t\(\)\\]{0,16}\" <FuncQual>"volatile" { yyextra->argList->setVolatileSpecifier(TRUE); } +<FuncQual>"override" { + } <FuncQual>"&" { yyextra->argList->setRefQualifier(RefQualifierLValue); } @@ -790,7 +792,7 @@ std::unique_ptr<ArgumentList> stringToArgumentList(SrcLangExt lang, const char * yyextra->argList->setNoParameters(TRUE); } if (extraTypeChars) *extraTypeChars=yyextra->extraTypeChars; - //printf("stringToArgumentList(%s) result=%s\n",argsString,argListToString(al).data()); + //printf("stringToArgumentList(%s) result=%s\n",argsString,argListToString(*al).data()); printlex(yy_flex_debug, FALSE, __FILE__, NULL); defargsYYlex_destroy(yyscanner); return al; diff --git a/src/defgen.cpp b/src/defgen.cpp index 02f51c5..82f7c26 100644 --- a/src/defgen.cpp +++ b/src/defgen.cpp @@ -243,71 +243,58 @@ void generateDEFForMember(MemberDef *md, //printf("md->getReferencesMembers()=%p\n",md->getReferencesMembers()); - MemberSDict *mdict = md->getReferencesMembers(); - if (mdict) + QCString refPrefix = " " + memPrefix + "ref-"; + auto refList = md->getReferencesMembers(); + for (const auto &rmd : refList) { - MemberSDict::Iterator mdi(*mdict); - MemberDef *rmd; - QCString refPrefix = " " + memPrefix + "ref-"; - - for (mdi.toFirst();(rmd=mdi.current());++mdi) + if (rmd->getStartBodyLine()!=-1 && rmd->getBodyDef()) { - if (rmd->getStartBodyLine()!=-1 && rmd->getBodyDef()) + t << memPrefix << "referenceto = {" << endl; + t << refPrefix << "id = '" + << rmd->getBodyDef()->getOutputFileBase() + << "_1" // encoded ':' character (see util.cpp:convertNameToFile) + << rmd->anchor() << "';" << endl; + + t << refPrefix << "line = '" + << rmd->getStartBodyLine() << "';" << endl; + + QCString scope = rmd->getScopeString(); + QCString name = rmd->name(); + if (!scope.isEmpty() && scope!=def->name()) { - t << memPrefix << "referenceto = {" << endl; - t << refPrefix << "id = '" - << rmd->getBodyDef()->getOutputFileBase() - << "_1" // encoded ':' character (see util.cpp:convertNameToFile) - << rmd->anchor() << "';" << endl; - - t << refPrefix << "line = '" - << rmd->getStartBodyLine() << "';" << endl; - - QCString scope = rmd->getScopeString(); - QCString name = rmd->name(); - if (!scope.isEmpty() && scope!=def->name()) - { - name.prepend(scope+"::"); - } - - t << refPrefix << "name = "; - writeDEFString(t,name); - t << ';' << endl << " };" << endl; + name.prepend(scope+"::"); } - } /* for (mdi.toFirst...) */ + + t << refPrefix << "name = "; + writeDEFString(t,name); + t << ';' << endl << " };" << endl; + } } - mdict = md->getReferencedByMembers(); - if (mdict) + auto refByList = md->getReferencedByMembers(); + for (const auto &rmd : refByList) { - MemberSDict::Iterator mdi(*mdict); - MemberDef *rmd; - QCString refPrefix = " " + memPrefix + "ref-"; - - for (mdi.toFirst();(rmd=mdi.current());++mdi) + if (rmd->getStartBodyLine()!=-1 && rmd->getBodyDef()) { - if (rmd->getStartBodyLine()!=-1 && rmd->getBodyDef()) + t << memPrefix << "referencedby = {" << endl; + t << refPrefix << "id = '" + << rmd->getBodyDef()->getOutputFileBase() + << "_1" // encoded ':' character (see util.cpp:convertNameToFile) + << rmd->anchor() << "';" << endl; + + t << refPrefix << "line = '" + << rmd->getStartBodyLine() << "';" << endl; + + QCString scope = rmd->getScopeString(); + QCString name = rmd->name(); + if (!scope.isEmpty() && scope!=def->name()) { - t << memPrefix << "referencedby = {" << endl; - t << refPrefix << "id = '" - << rmd->getBodyDef()->getOutputFileBase() - << "_1" // encoded ':' character (see util.cpp:convertNameToFile) - << rmd->anchor() << "';" << endl; - - t << refPrefix << "line = '" - << rmd->getStartBodyLine() << "';" << endl; - - QCString scope = rmd->getScopeString(); - QCString name = rmd->name(); - if (!scope.isEmpty() && scope!=def->name()) - { - name.prepend(scope+"::"); - } - - t << refPrefix << "name = "; - writeDEFString(t,name); - t << ';' << endl << " };" << endl; + name.prepend(scope+"::"); } - } /* for (mdi.toFirst...) */ + + t << refPrefix << "name = "; + writeDEFString(t,name); + t << ';' << endl << " };" << endl; + } } t << " }; /* " << Prefix << "-member */" << endl; @@ -358,60 +345,50 @@ void generateDEFForClass(ClassDef *cd,FTextStream &t) t << " cp-id = '" << cd->getOutputFileBase() << "';" << endl; t << " cp-name = '" << cd->name() << "';" << endl; - if (cd->baseClasses()) + for (const auto &bcd : cd->baseClasses()) { - BaseClassListIterator bcli(*cd->baseClasses()); - BaseClassDef *bcd; - for (bcli.toFirst();(bcd=bcli.current());++bcli) + t << " cp-ref = {" << endl << " ref-type = base;" << endl; + t << " ref-id = '" + << bcd.classDef->getOutputFileBase() << "';" << endl; + t << " ref-prot = "; + switch (bcd.prot) { - t << " cp-ref = {" << endl << " ref-type = base;" << endl; - t << " ref-id = '" - << bcd->classDef->getOutputFileBase() << "';" << endl; - t << " ref-prot = "; - switch (bcd->prot) - { - case Public: t << "public;" << endl; break; - case Package: // package scope is not possible - case Protected: t << "protected;" << endl; break; - case Private: t << "private;" << endl; break; - } - t << " ref-virt = "; - switch(bcd->virt) - { - case Normal: t << "non-virtual;"; break; - case Virtual: t << "virtual;"; break; - case Pure: t << "pure-virtual;"; break; - } - t << endl << " };" << endl; + case Public: t << "public;" << endl; break; + case Package: // package scope is not possible + case Protected: t << "protected;" << endl; break; + case Private: t << "private;" << endl; break; + } + t << " ref-virt = "; + switch(bcd.virt) + { + case Normal: t << "non-virtual;"; break; + case Virtual: t << "virtual;"; break; + case Pure: t << "pure-virtual;"; break; } + t << endl << " };" << endl; } - if (cd->subClasses()) + for (const auto &bcd : cd->subClasses()) { - BaseClassListIterator bcli(*cd->subClasses()); - BaseClassDef *bcd; - for (bcli.toFirst();(bcd=bcli.current());++bcli) + t << " cp-ref = {" << endl << " ref-type = derived;" << endl; + t << " ref-id = '" + << bcd.classDef->getOutputFileBase() << "';" << endl; + t << " ref-prot = "; + switch (bcd.prot) { - t << " cp-ref = {" << endl << " ref-type = derived;" << endl; - t << " ref-id = '" - << bcd->classDef->getOutputFileBase() << "';" << endl; - t << " ref-prot = "; - switch (bcd->prot) - { - case Public: t << "public;" << endl; break; - case Package: // packet scope is not possible! - case Protected: t << "protected;" << endl; break; - case Private: t << "private;" << endl; break; - } - t << " ref-virt = "; - switch(bcd->virt) - { - case Normal: t << "non-virtual;"; break; - case Virtual: t << "virtual;"; break; - case Pure: t << "pure-virtual;"; break; - } - t << endl << " };" << endl; + case Public: t << "public;" << endl; break; + case Package: // packet scope is not possible! + case Protected: t << "protected;" << endl; break; + case Private: t << "private;" << endl; break; + } + t << " ref-virt = "; + switch (bcd.virt) + { + case Normal: t << "non-virtual;"; break; + case Virtual: t << "virtual;"; break; + case Pure: t << "pure-virtual;"; break; } + t << endl << " };" << endl; } int numMembers = 0; diff --git a/src/definition.cpp b/src/definition.cpp index 3ed331c..b719388 100644 --- a/src/definition.cpp +++ b/src/definition.cpp @@ -16,6 +16,10 @@ */ #include <algorithm> +#include <iterator> +#include <unordered_map> +#include <string> + #include <ctype.h> #include <qregexp.h> #include "md5.h" @@ -46,6 +50,7 @@ #include "bufstr.h" #include "reflist.h" + //----------------------------------------------------------------------------------------- /** Private data associated with a Symbol DefinitionImpl object. */ @@ -56,10 +61,12 @@ class DefinitionImpl::IMPL void init(const char *df, const char *n); void setDefFileName(const QCString &df); + Definition *def = 0; + SectionRefs sectionRefs; - MemberSDict *sourceRefByDict = 0; - MemberSDict *sourceRefsDict = 0; + std::unordered_map<std::string,const MemberDef *> sourceRefByDict; + std::unordered_map<std::string,const MemberDef *> sourceRefsDict; RefItemVector xrefListItems; GroupList *partOfGroups = 0; @@ -94,14 +101,12 @@ class DefinitionImpl::IMPL QCString symbolName; int defLine; int defColumn; - Cookie *cookie; + Definition::Cookie *cookie; }; DefinitionImpl::IMPL::~IMPL() { - delete sourceRefByDict; - delete sourceRefsDict; delete partOfGroups; delete brief; delete details; @@ -138,8 +143,8 @@ void DefinitionImpl::IMPL::init(const char *df, const char *n) details = 0; body = 0; inbodyDocs = 0; - sourceRefByDict = 0; - sourceRefsDict = 0; + sourceRefByDict.clear(); + sourceRefsDict.clear(); outerScope = Doxygen::globalScope; partOfGroups = 0; hidden = FALSE; @@ -176,14 +181,14 @@ static bool matchExcludedSymbols(const char *name) QRegExp re(substitute(pattern,"*",".*"),TRUE); int pl; int i = re.match(symName,0,&pl); - //printf(" %d = re.match(%s) pattern=%s\n",i,symName.data(),pattern.data()); + //printf(" %d = re.match(%s) pattern=%s pl=%d len=%d\n",i,symName.data(),pattern.data(),pl,symName.length()); if (i!=-1) // wildcard match { uint ui=(uint)i; uint sl=symName.length(); // check if it is a whole word match - if ((ui==0 || pattern.at(0)=='*' || (!isId(symName.at(ui-1)) && !forceStart)) && - (ui+pl==sl || pattern.at(ui+pl)=='*' || (!isId(symName.at(ui+pl)) && !forceEnd)) + if ((ui==0 || pattern.at(0)=='*' || (!isId(symName.at(ui-1)) && !forceStart)) && + (ui+pl==sl || pattern.at(pattern.length()-1)=='*' || (!isId(symName.at(ui+pl)) && !forceEnd)) ) { //printf("--> name=%s pattern=%s match at %d\n",symName.data(),pattern.data(),i); @@ -222,86 +227,30 @@ static void addToMap(const char *name,Definition *d) if (!vhdlOpt && index!=-1) symbolName=symbolName.mid(index+2); if (!symbolName.isEmpty()) { - //printf("******* adding symbol '%s' (%p)\n",symbolName.data(),d); - DefinitionIntf *di=Doxygen::symbolMap->find(symbolName); - //printf(" addToMap(%p): looking for symbol %s: %p\n",d,symbolName.data(),di); - if (di==0) // new Symbol - { - //printf(" new symbol!\n"); - Doxygen::symbolMap->insert(symbolName,d); - } - else // existing symbol - { - //printf(" existing symbol: "); - if (di->definitionType()==DefinitionIntf::TypeSymbolList) // already multiple symbols - { - //printf("adding to exiting list\n"); - DefinitionList *dl = (DefinitionList*)di; - dl->append(d); - } - else // going from one to two symbols - { - Doxygen::symbolMap->take(symbolName); - DefinitionList *dl = new DefinitionList; - //printf("replacing symbol by list %p with elements %p and %p\n",dl,di,d); - dl->append((Definition*)di); - dl->append(d); - Doxygen::symbolMap->insert(symbolName,dl); - } - } - - // auto resize if needed - static int sizeIndex=9; - if (Doxygen::symbolMap->size()>SDict_primes[sizeIndex]) - { - Doxygen::symbolMap->resize(SDict_primes[++sizeIndex]); - } + Doxygen::symbolMap.add(symbolName,d); d->_setSymbolName(symbolName); } } -static void removeFromMap(Definition *d) +static void removeFromMap(const char *name,Definition *d) { - QCString symbolName = d->_symbolName(); - if (!symbolName.isEmpty()) - { - //printf("******* removing symbol '%s' (%p)\n",symbolName.data(),d); - DefinitionIntf *di=Doxygen::symbolMap->find(symbolName); - if (di) - { - if (di!=d) // symbolName not unique - { - //printf(" removing from list: %p!\n",di); - DefinitionList *dl = (DefinitionList*)di; - bool b = dl->removeRef(d); - ASSERT(b==TRUE); - if (dl->isEmpty()) - { - Doxygen::symbolMap->take(symbolName); - delete dl; - } - } - else // symbolName unique - { - //printf(" removing symbol %p\n",di); - Doxygen::symbolMap->take(symbolName); - } - } - } + Doxygen::symbolMap.remove(name,d); } -DefinitionImpl::DefinitionImpl(const char *df,int dl,int dc, +DefinitionImpl::DefinitionImpl(Definition *def, + const char *df,int dl,int dc, const char *name,const char *b, const char *d,bool isSymbol) { m_impl = new DefinitionImpl::IMPL; setName(name); + m_impl->def = def; m_impl->defLine = dl; m_impl->defColumn = dc; m_impl->init(df,name); m_impl->isSymbol = isSymbol; - if (isSymbol) addToMap(name,this); + if (isSymbol) addToMap(name,def); _setBriefDescription(b,df,dl); _setDocumentation(d,df,dl,TRUE,FALSE); if (matchExcludedSymbols(name)) @@ -314,33 +263,11 @@ DefinitionImpl::DefinitionImpl(const DefinitionImpl &d) { m_impl = new DefinitionImpl::IMPL; *m_impl = *d.m_impl; - m_impl->sourceRefByDict = 0; - m_impl->sourceRefsDict = 0; m_impl->partOfGroups = 0; m_impl->brief = 0; m_impl->details = 0; m_impl->body = 0; m_impl->inbodyDocs = 0; - if (d.m_impl->sourceRefByDict) - { - m_impl->sourceRefByDict = new MemberSDict; - MemberSDict::IteratorDict it(*d.m_impl->sourceRefByDict); - MemberDef *md; - for (it.toFirst();(md=it.current());++it) - { - m_impl->sourceRefByDict->append(it.currentKey(),md); - } - } - if (d.m_impl->sourceRefsDict) - { - m_impl->sourceRefsDict = new MemberSDict; - MemberSDict::IteratorDict it(*d.m_impl->sourceRefsDict); - MemberDef *md; - for (it.toFirst();(md=it.current());++it) - { - m_impl->sourceRefsDict->append(it.currentKey(),md); - } - } if (d.m_impl->partOfGroups) { GroupListIterator it(*d.m_impl->partOfGroups); @@ -367,14 +294,14 @@ DefinitionImpl::DefinitionImpl(const DefinitionImpl &d) m_impl->inbodyDocs = new DocInfo(*d.m_impl->inbodyDocs); } - if (m_impl->isSymbol) addToMap(m_impl->name,this); + if (m_impl->isSymbol) addToMap(m_impl->name,m_impl->def); } DefinitionImpl::~DefinitionImpl() { if (m_impl->isSymbol) { - removeFromMap(this); + removeFromMap(m_impl->symbolName,m_impl->def); } if (m_impl) { @@ -399,7 +326,7 @@ void DefinitionImpl::setId(const char *id) if (Doxygen::clangUsrMap) { //printf("DefinitionImpl::setId '%s'->'%s'\n",id,m_impl->name.data()); - Doxygen::clangUsrMap->insert(id,this); + Doxygen::clangUsrMap->insert(id,m_impl->def); } } @@ -425,7 +352,7 @@ void DefinitionImpl::addSectionsToDefinition(const std::vector<const SectionInfo if (m_impl->sectionRefs.find(gsi->label())==0) { m_impl->sectionRefs.add(gsi); - gsi->setDefinition(this); + gsi->setDefinition(m_impl->def); } } } @@ -481,7 +408,7 @@ void DefinitionImpl::addSectionsToIndex() ((int)((*it_next)->type()) > nextLevel) : FALSE; Doxygen::indexList->addContentsItem(isDir,title, getReference(), - getOutputFileBase(), + m_impl->def->getOutputFileBase(), si->label(), FALSE, TRUE); @@ -505,7 +432,7 @@ void DefinitionImpl::writeDocAnchorsToTagFile(FTextStream &tagFile) const if (!si->generated() && si->ref().isEmpty() && !si->label().startsWith("autotoc_md")) { //printf("write an entry!\n"); - if (definitionType()==TypeMember) tagFile << " "; + if (m_impl->def->definitionType()==Definition::TypeMember) tagFile << " "; tagFile << " <docanchor file=\"" << addHtmlExtensionIfMissing(si->fileName()) << "\""; if (!si->title().isEmpty()) { @@ -613,6 +540,8 @@ void DefinitionImpl::_setBriefDescription(const char *b,const char *briefFile,in outputLanguage!="Korean"; QCString brief = b; brief = brief.stripWhiteSpace(); + brief = stripLeadingAndTrailingEmptyLines(brief,briefLine); + brief = brief.stripWhiteSpace(); if (brief.isEmpty()) return; uint bl = brief.length(); if (bl>0 && needsDot) // add punctuation if needed @@ -976,7 +905,7 @@ bool readCodeFragment(const char *fileName, QCString DefinitionImpl::getSourceFileBase() const { - ASSERT(definitionType()!=Definition::TypeFile); // file overloads this method + ASSERT(m_impl->def->definitionType()!=Definition::TypeFile); // file overloads this method QCString fn; static bool sourceBrowser = Config_getBool(SOURCE_BROWSER); if (sourceBrowser && @@ -1234,37 +1163,56 @@ void DefinitionImpl::writeInlineCode(OutputList &ol,const char *scopeName) const { //printf("Adding code fragment '%s' ext='%s'\n", // codeFragment.data(),m_impl->defFileExt.data()); - CodeParserInterface &intf = Doxygen::parserManager->getCodeParser(m_impl->defFileExt); - intf.resetCodeParserState(); + auto intf = Doxygen::parserManager->getCodeParser(m_impl->defFileExt); + intf->resetCodeParserState(); //printf("Read:\n'%s'\n\n",codeFragment.data()); const MemberDef *thisMd = 0; - if (definitionType()==TypeMember) thisMd = dynamic_cast <const MemberDef*>(this); - - ol.startCodeFragment(); - intf.parseCode(ol, // codeOutIntf - scopeName, // scope - codeFragment, // input - m_impl->lang, // lang - FALSE, // isExample - 0, // exampleName - m_impl->body->fileDef, // fileDef - actualStart, // startLine - actualEnd, // endLine - TRUE, // inlineFragment - thisMd, // memberDef - TRUE // show line numbers - ); - ol.endCodeFragment(); + if (m_impl->def->definitionType()==Definition::TypeMember) + { + thisMd = toMemberDef(m_impl->def); + } + + ol.startCodeFragment("DoxyCode"); + intf->parseCode(ol, // codeOutIntf + scopeName, // scope + codeFragment, // input + m_impl->lang, // lang + FALSE, // isExample + 0, // exampleName + m_impl->body->fileDef, // fileDef + actualStart, // startLine + actualEnd, // endLine + TRUE, // inlineFragment + thisMd, // memberDef + TRUE // show line numbers + ); + ol.endCodeFragment("DoxyCode"); } } ol.popGeneratorState(); } +static inline std::vector<const MemberDef*> refMapToVector(const std::unordered_map<std::string,const MemberDef *> &map) +{ + // convert map to a vector of values + std::vector<const MemberDef *> result; + std::transform(map.begin(),map.end(), // iterate over map + std::back_inserter(result), // add results to vector + [](const auto &item) + { return item.second; } // extract value to add from map Key,Value pair + ); + // and sort it + std::sort(result.begin(),result.end(), + [](const auto &m1,const auto &m2) { return genericCompareMembers(m1,m2)<0; }); + return result; +} + /*! Write a reference to the source code fragments in which this * definition is used. */ void DefinitionImpl::_writeSourceRefList(OutputList &ol,const char *scopeName, - const QCString &text,MemberSDict *members,bool /*funcOnly*/) const + const QCString &text,const std::unordered_map<std::string,const MemberDef *> &membersMap, + bool /*funcOnly*/) const { static bool latexSourceCode = Config_getBool(LATEX_SOURCE_CODE); static bool docbookSourceCode = Config_getBool(DOCBOOK_PROGRAMLISTING); @@ -1272,15 +1220,15 @@ void DefinitionImpl::_writeSourceRefList(OutputList &ol,const char *scopeName, static bool sourceBrowser = Config_getBool(SOURCE_BROWSER); static bool refLinkSource = Config_getBool(REFERENCES_LINK_SOURCE); ol.pushGeneratorState(); - if (members) + if (!membersMap.empty()) { - members->sort(); + auto members = refMapToVector(membersMap); ol.startParagraph("reference"); ol.parseText(text); ol.docify(" "); - QCString ldefLine=theTranslator->trWriteList((int)members->count()); + QCString ldefLine=theTranslator->trWriteList((int)members.size()); QRegExp marker("@[0-9]+"); uint index=0; @@ -1292,7 +1240,7 @@ void DefinitionImpl::_writeSourceRefList(OutputList &ol,const char *scopeName, bool ok; ol.parseText(ldefLine.mid(index,(uint)newIndex-index)); uint entryIndex = ldefLine.mid(newIndex+1,matchLen-1).toUInt(&ok); - MemberDef *md=members->at(entryIndex); + const MemberDef *md=members.at(entryIndex); if (ok && md) { QCString scope=md->getScopeString(); @@ -1464,14 +1412,7 @@ void DefinitionImpl::addSourceReferencedBy(const MemberDef *md) name.prepend(scope+"::"); } - if (m_impl->sourceRefByDict==0) - { - m_impl->sourceRefByDict = new MemberSDict; - } - if (m_impl->sourceRefByDict->find(name)==0) - { - m_impl->sourceRefByDict->append(name,md); - } + m_impl->sourceRefByDict.insert({name.str(),md}); } } @@ -1487,18 +1428,11 @@ void DefinitionImpl::addSourceReferences(const MemberDef *md) name.prepend(scope+"::"); } - if (m_impl->sourceRefsDict==0) - { - m_impl->sourceRefsDict = new MemberSDict; - } - if (m_impl->sourceRefsDict->find(name)==0) - { - m_impl->sourceRefsDict->append(name,md); - } + m_impl->sourceRefsDict.insert({name.str(),md}); } } -Definition *DefinitionImpl::findInnerCompound(const char *) const +const Definition *DefinitionImpl::findInnerCompound(const char *) const { return 0; } @@ -1633,16 +1567,18 @@ QCString DefinitionImpl::pathFragment() const { result = m_impl->outerScope->pathFragment(); } - if (isLinkable()) + if (m_impl->def->isLinkable()) { if (!result.isEmpty()) result+="/"; - if (definitionType()==Definition::TypeGroup && (dynamic_cast <const GroupDef*>(this))->groupTitle()) + if (m_impl->def->definitionType()==Definition::TypeGroup && + (toGroupDef(m_impl->def))->groupTitle()) { - result+=(dynamic_cast <const GroupDef*>(this))->groupTitle(); + result+=(toGroupDef(m_impl->def))->groupTitle(); } - else if (definitionType()==Definition::TypePage && (dynamic_cast <const PageDef*>(this))->hasTitle()) + else if (m_impl->def->definitionType()==Definition::TypePage && + (toPageDef(m_impl->def))->hasTitle()) { - result+=(dynamic_cast <const PageDef*>(this))->title(); + result+=(toPageDef(m_impl->def))->title(); } else { @@ -1671,37 +1607,37 @@ QCString DefinitionImpl::navigationPathAsString() const { result+=outerScope->navigationPathAsString(); } - else if (definitionType()==Definition::TypeFile && (dynamic_cast<const FileDef*>(this))->getDirDef()) + else if (m_impl->def->definitionType()==Definition::TypeFile && (toFileDef(m_impl->def))->getDirDef()) { - result+=(dynamic_cast<const FileDef*>(this))->getDirDef()->navigationPathAsString(); + result+=(toFileDef(m_impl->def))->getDirDef()->navigationPathAsString(); } result+="<li class=\"navelem\">"; - if (isLinkable()) + if (m_impl->def->isLinkable()) { - if (definitionType()==Definition::TypeGroup && (dynamic_cast<const GroupDef*>(this))->groupTitle()) + if (m_impl->def->definitionType()==Definition::TypeGroup && (toGroupDef(m_impl->def))->groupTitle()) { - result+="<a class=\"el\" href=\"$relpath^"+getOutputFileBase()+Doxygen::htmlFileExtension+"\">"+ - convertToHtml((dynamic_cast<const GroupDef*>(this))->groupTitle())+"</a>"; + result+="<a class=\"el\" href=\"$relpath^"+m_impl->def->getOutputFileBase()+Doxygen::htmlFileExtension+"\">"+ + convertToHtml((toGroupDef(m_impl->def))->groupTitle())+"</a>"; } - else if (definitionType()==Definition::TypePage && (dynamic_cast<const PageDef*>(this))->hasTitle()) + else if (m_impl->def->definitionType()==Definition::TypePage && (toPageDef(m_impl->def))->hasTitle()) { - result+="<a class=\"el\" href=\"$relpath^"+getOutputFileBase()+Doxygen::htmlFileExtension+"\">"+ - convertToHtml((dynamic_cast<const PageDef*>(this))->title())+"</a>"; + result+="<a class=\"el\" href=\"$relpath^"+m_impl->def->getOutputFileBase()+Doxygen::htmlFileExtension+"\">"+ + convertToHtml((toPageDef(m_impl->def))->title())+"</a>"; } - else if (definitionType()==Definition::TypeClass) + else if (m_impl->def->definitionType()==Definition::TypeClass) { QCString name = locName; if (name.right(2)=="-p" /*|| name.right(2)=="-g"*/) { name = name.left(name.length()-2); } - result+="<a class=\"el\" href=\"$relpath^"+getOutputFileBase()+Doxygen::htmlFileExtension; - if (!anchor().isEmpty()) result+="#"+anchor(); + result+="<a class=\"el\" href=\"$relpath^"+m_impl->def->getOutputFileBase()+Doxygen::htmlFileExtension; + if (!m_impl->def->anchor().isEmpty()) result+="#"+m_impl->def->anchor(); result+="\">"+convertToHtml(name)+"</a>"; } else { - result+="<a class=\"el\" href=\"$relpath^"+getOutputFileBase()+Doxygen::htmlFileExtension+"\">"+ + result+="<a class=\"el\" href=\"$relpath^"+m_impl->def->getOutputFileBase()+Doxygen::htmlFileExtension+"\">"+ convertToHtml(locName)+"</a>"; } } @@ -1954,33 +1890,24 @@ QCString DefinitionImpl::briefDescription(bool abbr) const { //printf("%s::briefDescription(%d)='%s'\n",name().data(),abbr,m_impl->brief?m_impl->brief->doc.data():"<none>"); return m_impl->brief ? - (abbr ? abbreviate(m_impl->brief->doc,displayName()) : m_impl->brief->doc) : + (abbr ? abbreviate(m_impl->brief->doc,m_impl->def->displayName()) : m_impl->brief->doc) : QCString(""); } -QCString DefinitionImpl::briefDescriptionAsTooltip() const +void DefinitionImpl::computeTooltip() { - if (m_impl->brief) + if (m_impl->brief && m_impl->brief->tooltip.isEmpty() && !m_impl->brief->doc.isEmpty()) { - if (m_impl->brief->tooltip.isEmpty() && !m_impl->brief->doc.isEmpty()) - { - static bool reentering=FALSE; - if (!reentering) - { - const MemberDef *md = definitionType()==TypeMember ? dynamic_cast<const MemberDef*>(this) : 0; - const Definition *scope = definitionType()==TypeMember ? getOuterScope() : this; - reentering=TRUE; // prevent requests for tooltips while parsing a tooltip - m_impl->brief->tooltip = parseCommentAsText( - scope,md, - m_impl->brief->doc, - m_impl->brief->file, - m_impl->brief->line); - reentering=FALSE; - } - } - return m_impl->brief->tooltip; + const MemberDef *md = m_impl->def->definitionType()==Definition::TypeMember ? toMemberDef(m_impl->def) : 0; + const Definition *scope = m_impl->def->definitionType()==Definition::TypeMember ? m_impl->def->getOuterScope() : m_impl->def; + m_impl->brief->tooltip = parseCommentAsText(scope,md, + m_impl->brief->doc, m_impl->brief->file, m_impl->brief->line); } - return QCString(""); +} + +QCString DefinitionImpl::briefDescriptionAsTooltip() const +{ + return m_impl->brief ? m_impl->brief->tooltip : QCString(); } int DefinitionImpl::briefLine() const @@ -2030,12 +1957,12 @@ bool DefinitionImpl::isHidden() const bool DefinitionImpl::isVisibleInProject() const { - return isLinkableInProject() && !m_impl->hidden; + return m_impl->def->isLinkableInProject() && !m_impl->hidden; } bool DefinitionImpl::isVisible() const { - return isLinkable() && !m_impl->hidden; + return m_impl->def->isLinkable() && !m_impl->hidden; } bool DefinitionImpl::isArtificial() const @@ -2098,16 +2025,49 @@ Definition *DefinitionImpl::getOuterScope() const return m_impl->outerScope; } -MemberSDict *DefinitionImpl::getReferencesMembers() const +std::vector<const MemberDef*> DefinitionImpl::getReferencesMembers() const +{ + return refMapToVector(m_impl->sourceRefsDict); +} + +std::vector<const MemberDef*> DefinitionImpl::getReferencedByMembers() const { - return m_impl->sourceRefsDict; + return refMapToVector(m_impl->sourceRefByDict); } -MemberSDict *DefinitionImpl::getReferencedByMembers() const +void DefinitionImpl::mergeReferences(const Definition *other) { - return m_impl->sourceRefByDict; + const DefinitionImpl *defImpl = other->toDefinitionImpl_(); + if (defImpl) + { + for (const auto &kv : defImpl->m_impl->sourceRefsDict) + { + auto it = m_impl->sourceRefsDict.find(kv.first); + if (it != m_impl->sourceRefsDict.end()) + { + m_impl->sourceRefsDict.insert(kv); + } + } + } } +void DefinitionImpl::mergeReferencedBy(const Definition *other) +{ + const DefinitionImpl *defImpl = other->toDefinitionImpl_(); + if (defImpl) + { + for (const auto &kv : defImpl->m_impl->sourceRefByDict) + { + auto it = m_impl->sourceRefByDict.find(kv.first); + if (it != m_impl->sourceRefByDict.end()) + { + m_impl->sourceRefByDict.insert({kv.first,kv.second}); + } + } + } +} + + void DefinitionImpl::setReference(const char *r) { m_impl->ref=r; @@ -2177,7 +2137,7 @@ QCString DefinitionImpl::externalReference(const QCString &relPath) const return relPath; } -const QCString &DefinitionImpl::name() const +QCString DefinitionImpl::name() const { return m_impl->name; } @@ -2197,7 +2157,7 @@ int DefinitionImpl::getDefColumn() const return m_impl->defColumn; } -void DefinitionImpl::setCookie(Cookie *cookie) const +void DefinitionImpl::setCookie(Definition::Cookie *cookie) const { delete m_impl->cookie; m_impl->cookie = cookie; @@ -2218,16 +2178,62 @@ void DefinitionImpl::writeSummaryLinks(OutputList &) const //--------------------------------------------------------------------------------- -DefinitionAliasImpl::DefinitionAliasImpl(const Definition *scope,const Definition *alias) - : m_scope(scope), m_def(alias), m_cookie(0) +DefinitionAliasImpl::DefinitionAliasImpl(Definition *def,const Definition *scope, const Definition *alias) + : m_def(def), m_scope(scope), m_symbolName(alias->_symbolName()) { - //printf("%s::addToMap(%s)\n",qPrint(name()),qPrint(alias->name())); - addToMap(alias->name(),this); } DefinitionAliasImpl::~DefinitionAliasImpl() { - //printf("~DefinitionAliasImpl()\n"); - removeFromMap(this); +} + +void DefinitionAliasImpl::init() +{ + //printf("%s::addToMap(%s)\n",qPrint(name()),qPrint(alias->name())); + addToMap(m_symbolName,m_def); +} + +void DefinitionAliasImpl::deinit() +{ + removeFromMap(m_symbolName,m_def); +} + +QCString DefinitionAliasImpl::qualifiedName() const +{ + //printf("start %s::qualifiedName() localName=%s\n",name().data(),m_impl->localName.data()); + if (m_scope==0) + { + return m_def->localName(); + } + else + { + return m_scope->qualifiedName()+ + getLanguageSpecificSeparator(m_scope->getLanguage())+ + m_def->localName(); + } +} + +QCString DefinitionAliasImpl::name() const +{ + return qualifiedName(); +} + +//--------------------------------------------------------------------------------- + +Definition *toDefinition(DefinitionMutable *dm) +{ + if (dm==0) return 0; + return dm->toDefinition_(); +} + +DefinitionMutable *toDefinitionMutable(Definition *d) +{ + if (d==0) return 0; + return d->toDefinitionMutable_(); +} + +DefinitionMutable *toDefinitionMutable(const Definition *d) +{ + return toDefinitionMutable(const_cast<Definition*>(d)); } diff --git a/src/definition.h b/src/definition.h index 8ad15b2..204e6f6 100644 --- a/src/definition.h +++ b/src/definition.h @@ -40,6 +40,8 @@ class GroupDef; class GroupList; class SectionInfo; class Definition; +class DefinitionMutable; +class DefinitionImpl; class FTextStream; /** Data associated with a detailed description. */ @@ -68,12 +70,19 @@ struct BodyInfo FileDef *fileDef; //!< file definition containing the function body }; -/** Abstract interface for a Definition or DefinitionList */ -class DefinitionIntf +/** The common base class of all entity definitions found in the sources. + * + * This can be a class or a member function, or a file, or a namespace, etc. + * Use definitionType() to find which type of definition this is. + */ +class Definition { public: - DefinitionIntf() {} - virtual ~DefinitionIntf() {} + struct Cookie + { + virtual ~Cookie() {} + }; + /*! Types of derived classes */ enum DefType { @@ -84,34 +93,22 @@ class DefinitionIntf TypeGroup = 4, TypePackage = 5, TypePage = 6, - TypeDir = 7, - TypeSymbolList = 8 + TypeDir = 7 }; - /*! Use this for dynamic inspection of the type of the derived class */ - virtual DefType definitionType() const = 0; -}; -/** The common base class of all entity definitions found in the sources. - * - * This can be a class or a member function, or a file, or a namespace, etc. - * Use definitionType() to find which type of definition this is. - */ -class Definition : public DefinitionIntf -{ - public: - struct Cookie - { - virtual ~Cookie() {} - }; //----------------------------------------------------------------------------------- // ---- getters ----- //----------------------------------------------------------------------------------- + + /*! Use this for dynamic inspection of the type of the derived class */ + virtual DefType definitionType() const = 0; + /*! Returns TRUE if this is an alias of another definition */ virtual bool isAlias() const = 0; /*! Returns the name of the definition */ - virtual const QCString &name() const = 0; + virtual QCString name() const = 0; /*! Returns TRUE iff this definition has an artificially generated name * (typically starting with a @) that is used for nameless definitions @@ -269,11 +266,11 @@ class Definition : public DefinitionIntf virtual const RefItemVector &xrefListItems() const = 0; - virtual Definition *findInnerCompound(const char *name) const = 0; + virtual const Definition *findInnerCompound(const char *name) const = 0; virtual Definition *getOuterScope() const = 0; - virtual MemberSDict *getReferencesMembers() const = 0; - virtual MemberSDict *getReferencedByMembers() const = 0; + virtual std::vector<const MemberDef *> getReferencesMembers() const = 0; + virtual std::vector<const MemberDef *> getReferencedByMembers() const = 0; virtual bool hasSections() const = 0; virtual bool hasSources() const = 0; @@ -290,6 +287,34 @@ class Definition : public DefinitionIntf virtual QCString pathFragment() 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; + + // --------------------------------- + virtual ~Definition() = default; + + private: + friend class DefinitionImpl; + friend DefinitionMutable* toDefinitionMutable(Definition *); + friend DefinitionMutable* toDefinitionMutable(const Definition *); + virtual DefinitionMutable *toDefinitionMutable_() = 0; + virtual const DefinitionImpl *toDefinitionImpl_() const = 0; +}; + +class DefinitionMutable +{ + public: + + + //----------------------------------------------------------------------------------- // ---- setters ----- //----------------------------------------------------------------------------------- @@ -347,6 +372,9 @@ class Definition : public DefinitionIntf virtual void mergeRefItems(Definition *d) = 0; virtual void addInnerCompound(const Definition *d) = 0; virtual void addSectionsToIndex() = 0; + virtual void mergeReferences(const Definition *other) = 0; + virtual void mergeReferencedBy(const Definition *other) = 0; + virtual void computeTooltip() = 0; //----------------------------------------------------------------------------------- // --- writing output ---- @@ -361,40 +389,17 @@ class Definition : public DefinitionIntf 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; -}; - -/** A list of Definition objects. */ -class DefinitionList : public QList<Definition>, public DefinitionIntf -{ - public: - ~DefinitionList() {} - DefType definitionType() const { return TypeSymbolList; } - int compareValues(const Definition *item1,const Definition *item2) const - { - return qstricmp(item1->name(),item2->name()); - } + // --------------------------------- + virtual ~DefinitionMutable() = default; + private: + friend Definition* toDefinition(DefinitionMutable *); + virtual Definition *toDefinition_() = 0; }; -/** An iterator for Definition objects in a DefinitionList. */ -class DefinitionListIterator : public QListIterator<Definition> -{ - public: - DefinitionListIterator(const DefinitionList &l) : - QListIterator<Definition>(l) {} - ~DefinitionListIterator() {} -}; +Definition *toDefinition(DefinitionMutable *dm); +DefinitionMutable *toDefinitionMutable(Definition *d); +DefinitionMutable *toDefinitionMutable(const Definition *d); /** Reads a fragment from file \a fileName starting with line \a startLine * and ending with line \a endLine. The result is returned as a string diff --git a/src/definitionimpl.h b/src/definitionimpl.h index e91d989..e455dc4 100644 --- a/src/definitionimpl.h +++ b/src/definitionimpl.h @@ -18,113 +18,116 @@ #ifndef DEFINITIONIMPL_H #define DEFINITIONIMPL_H +#include <unordered_map> +#include <string> + #include "definition.h" -class DefinitionImpl : virtual public Definition +class DefinitionImpl { public: - /*! Create a new definition */ DefinitionImpl( + Definition *def, const char *defFileName,int defLine,int defColumn, const char *name,const char *b=0,const char *d=0, bool isSymbol=TRUE); virtual ~DefinitionImpl(); - virtual bool isAlias() const { return FALSE; } - virtual const QCString &name() const; - virtual bool isAnonymous() const; - virtual QCString localName() const; - virtual QCString qualifiedName() const; - virtual QCString symbolName() const; - virtual QCString getSourceFileBase() const; - virtual QCString getSourceAnchor() const; - virtual QCString documentation() const; - virtual int docLine() const; - virtual QCString docFile() const; - virtual QCString briefDescription(bool abbreviate=FALSE) const; - virtual QCString briefDescriptionAsTooltip() const; - virtual int briefLine() const; - virtual QCString inbodyDocumentation() const; - virtual QCString inbodyFile() const; - virtual int inbodyLine() const; - virtual QCString briefFile() const; - virtual QCString getDefFileName() const; - virtual QCString getDefFileExtension() const; - virtual int getDefLine() const; - virtual int getDefColumn() const; - virtual bool hasDocumentation() const; - virtual bool hasUserDocumentation() const; - virtual bool isVisibleInProject() const; - virtual bool isVisible() const; - virtual bool isHidden() const; - virtual bool isArtificial() const; - virtual QCString getReference() const; - virtual bool isReference() const; - virtual QCString externalReference(const QCString &relPath) const; - virtual int getStartDefLine() const; - virtual int getStartBodyLine() const; - virtual int getEndBodyLine() const; - virtual FileDef *getBodyDef() const; - virtual SrcLangExt getLanguage() const; - virtual GroupList *partOfGroups() const; - virtual bool isLinkableViaGroup() const; - virtual const RefItemVector &xrefListItems() const; - virtual Definition *findInnerCompound(const char *name) const; - virtual Definition *getOuterScope() const; - virtual MemberSDict *getReferencesMembers() const; - virtual MemberSDict *getReferencedByMembers() const; - virtual bool hasSections() const; - virtual bool hasSources() const; - virtual bool hasBriefDescription() const; - virtual QCString id() const; - virtual const SectionRefs &getSectionRefs() const; - 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(const std::vector<const SectionInfo*> &anchorList); - virtual void setBodySegment(int defLine,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 RefItemVector &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 QCString navigationPathAsString() const; - virtual void writeQuickMemberLinks(OutputList &,const MemberDef *) const; - virtual void writeSummaryLinks(OutputList &) const; - virtual QCString pathFragment() 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; - virtual Cookie *cookie() const; - - protected: + QCString name() const; + bool isAnonymous() const; + QCString localName() const; + QCString qualifiedName() const; + QCString symbolName() const; + QCString getSourceFileBase() const; + QCString getSourceAnchor() const; + QCString documentation() const; + int docLine() const; + QCString docFile() const; + QCString briefDescription(bool abbreviate=FALSE) const; + QCString briefDescriptionAsTooltip() const; + int briefLine() const; + QCString inbodyDocumentation() const; + QCString inbodyFile() const; + int inbodyLine() const; + QCString briefFile() const; + QCString getDefFileName() const; + QCString getDefFileExtension() const; + int getDefLine() const; + int getDefColumn() const; + bool hasDocumentation() const; + bool hasUserDocumentation() const; + bool isVisibleInProject() const; + bool isVisible() const; + bool isHidden() const; + bool isArtificial() const; + QCString getReference() const; + bool isReference() const; + QCString externalReference(const QCString &relPath) const; + int getStartDefLine() const; + int getStartBodyLine() const; + int getEndBodyLine() const; + FileDef *getBodyDef() const; + SrcLangExt getLanguage() const; + GroupList *partOfGroups() const; + bool isLinkableViaGroup() const; + const RefItemVector &xrefListItems() const; + const Definition *findInnerCompound(const char *name) const; + Definition *getOuterScope() const; + std::vector<const MemberDef *> getReferencesMembers() const; + std::vector<const MemberDef *> getReferencedByMembers() const; + bool hasSections() const; + bool hasSources() const; + bool hasBriefDescription() const; + QCString id() const; + const SectionRefs &getSectionRefs() const; + void setName(const char *name); + void setId(const char *name); + void setDefFile(const QCString& df,int defLine,int defColumn); + void setDocumentation(const char *d,const char *docFile,int docLine,bool stripWhiteSpace=TRUE); + void setBriefDescription(const char *b,const char *briefFile,int briefLine); + void setInbodyDocumentation(const char *d,const char *docFile,int docLine); + void setReference(const char *r); + void addSectionsToDefinition(const std::vector<const SectionInfo*> &anchorList); + void setBodySegment(int defLine,int bls,int ble); + void setBodyDef(FileDef *fd); + void addSourceReferencedBy(const MemberDef *d); + void addSourceReferences(const MemberDef *d); + void setRefItems(const RefItemVector &sli); + void mergeRefItems(Definition *d); + void mergeReferences(const Definition *other); + void mergeReferencedBy(const Definition *other); + void addInnerCompound(const Definition *d); + void setOuterScope(Definition *d); + void setHidden(bool b); + void setArtificial(bool b); + void setLanguage(SrcLangExt lang); + void writeSourceDef(OutputList &ol,const char *scopeName) const; + void writeInlineCode(OutputList &ol,const char *scopeName) const; + void writeSourceRefs(OutputList &ol,const char *scopeName) const; + void writeSourceReffedBy(OutputList &ol,const char *scopeName) const; + void makePartOfGroup(GroupDef *gd); + void writeNavigationPath(OutputList &ol) const; + QCString navigationPathAsString() const; + void writeQuickMemberLinks(OutputList &,const MemberDef *) const; + void writeSummaryLinks(OutputList &) const; + QCString pathFragment() const; + void writeDocAnchorsToTagFile(FTextStream &) const; + void setLocalName(const QCString name); + void addSectionsToIndex(); + void writeToc(OutputList &ol, const LocalToc <) const; + void setCookie(Definition::Cookie *cookie) const; + Definition::Cookie *cookie() const; + void computeTooltip(); + void _setSymbolName(const QCString &name); + QCString _symbolName() const; DefinitionImpl(const DefinitionImpl &d); private: - 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; + void _writeSourceRefList(OutputList &ol,const char *scopeName,const QCString &text, + const std::unordered_map<std::string,const MemberDef *> &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); @@ -135,156 +138,308 @@ class DefinitionImpl : virtual public Definition IMPL *m_impl; // internal structure holding all private data }; -class DefinitionAliasImpl : virtual public Definition +template<class Base> +class DefinitionMixin : public Base { public: - DefinitionAliasImpl(const Definition *scope,const Definition *alias); + /*! Create a new definition */ + DefinitionMixin( + const char *defFileName,int defLine,int defColumn, + const char *name,const char *b=0,const char *d=0, + bool isSymbol=TRUE) : m_impl(this,defFileName,defLine,defColumn,name,b,d,isSymbol) {} + virtual ~DefinitionMixin() {} + + virtual bool isAlias() const { return FALSE; } + + //======== Definition + virtual QCString name() const { return m_impl.name(); } + virtual bool isAnonymous() const { return m_impl.isAnonymous(); } + virtual QCString localName() const { return m_impl.localName(); } + virtual QCString qualifiedName() const { return m_impl.qualifiedName(); } + virtual QCString symbolName() const { return m_impl.symbolName(); } + virtual QCString getSourceFileBase() const { return m_impl.getSourceFileBase(); } + virtual QCString getSourceAnchor() const { return m_impl.getSourceAnchor(); } + virtual QCString documentation() const { return m_impl.documentation(); } + virtual int docLine() const { return m_impl.docLine(); } + virtual QCString docFile() const { return m_impl.docFile(); } + virtual QCString briefDescription(bool abbreviate=FALSE) const { return m_impl.briefDescription(abbreviate); } + virtual QCString briefDescriptionAsTooltip() const { return m_impl.briefDescriptionAsTooltip(); } + virtual int briefLine() const { return m_impl.briefLine(); } + virtual QCString inbodyDocumentation() const { return m_impl.inbodyDocumentation(); } + virtual QCString inbodyFile() const { return m_impl.inbodyFile(); } + virtual int inbodyLine() const { return m_impl.inbodyLine(); } + virtual QCString briefFile() const { return m_impl.briefFile(); } + virtual QCString getDefFileName() const { return m_impl.getDefFileName(); } + virtual QCString getDefFileExtension() const { return m_impl.getDefFileExtension(); } + virtual int getDefLine() const { return m_impl.getDefLine(); } + virtual int getDefColumn() const { return m_impl.getDefColumn(); } + virtual bool hasDocumentation() const { return m_impl.hasDocumentation(); } + virtual bool hasUserDocumentation() const { return m_impl.hasUserDocumentation(); } + virtual bool isVisibleInProject() const { return m_impl.isVisibleInProject(); } + virtual bool isVisible() const { return m_impl.isVisible(); } + virtual bool isHidden() const { return m_impl.isHidden(); } + virtual bool isArtificial() const { return m_impl.isArtificial(); } + virtual QCString getReference() const { return m_impl.getReference(); } + virtual bool isReference() const { return m_impl.isReference(); } + virtual QCString externalReference(const QCString &relPath) const { return m_impl.externalReference(relPath); } + virtual int getStartDefLine() const { return m_impl.getStartDefLine(); } + virtual int getStartBodyLine() const { return m_impl.getStartBodyLine(); } + virtual int getEndBodyLine() const { return m_impl.getEndBodyLine(); } + virtual FileDef *getBodyDef() const { return m_impl.getBodyDef(); } + virtual SrcLangExt getLanguage() const { return m_impl.getLanguage(); } + virtual GroupList *partOfGroups() const { return m_impl.partOfGroups(); } + virtual bool isLinkableViaGroup() const { return m_impl.isLinkableViaGroup(); } + virtual const RefItemVector &xrefListItems() const { return m_impl.xrefListItems(); } + virtual const Definition *findInnerCompound(const char *name) const { return m_impl.findInnerCompound(name); } + virtual Definition *getOuterScope() const { return m_impl.getOuterScope(); } + virtual std::vector<const MemberDef *> getReferencesMembers() const { return m_impl.getReferencesMembers(); } + virtual std::vector<const MemberDef *> getReferencedByMembers() const { return m_impl.getReferencedByMembers(); } + virtual bool hasSections() const { return m_impl.hasSections(); } + virtual bool hasSources() const { return m_impl.hasSources(); } + virtual bool hasBriefDescription() const { return m_impl.hasBriefDescription(); } + virtual QCString id() const { return m_impl.id(); } + virtual const SectionRefs &getSectionRefs() const { return m_impl.getSectionRefs(); } + + //======== DefinitionMutable + virtual void setName(const char *name) { m_impl.setName(name); } + virtual void setId(const char *name) { m_impl.setId(name); } + virtual void setDefFile(const QCString& df,int defLine,int defColumn) + { m_impl.setDefFile(df,defLine,defColumn); } + virtual void setDocumentation(const char *doc,const char *docFile,int docLine,bool stripWhiteSpace=TRUE) + { m_impl.setDocumentation(doc,docFile,docLine,stripWhiteSpace); } + virtual void setBriefDescription(const char *brief,const char *briefFile,int briefLine) + { m_impl.setBriefDescription(brief,briefFile,briefLine); } + virtual void setInbodyDocumentation(const char *doc,const char *docFile,int docLine) + { m_impl.setInbodyDocumentation(doc,docFile,docLine); } + virtual void setReference(const char *r) + { m_impl.setReference(r); } + virtual void addSectionsToDefinition(const std::vector<const SectionInfo*> &anchorList) + { m_impl.addSectionsToDefinition(anchorList); } + virtual void setBodySegment(int defLine,int bls,int ble) + { m_impl.setBodySegment(defLine,bls,ble); } + virtual void setBodyDef(FileDef *fd) + { m_impl.setBodyDef(fd); } + virtual void addSourceReferencedBy(const MemberDef *md) + { m_impl.addSourceReferencedBy(md); } + virtual void addSourceReferences(const MemberDef *md) + { m_impl.addSourceReferences(md); } + virtual void setRefItems(const RefItemVector &sli) + { m_impl.setRefItems(sli); } + virtual void mergeRefItems(Definition *def) + { m_impl.mergeRefItems(def); } + virtual void mergeReferences(const Definition *other) + { m_impl.mergeReferences(other); } + virtual void mergeReferencedBy(const Definition *other) + { m_impl.mergeReferencedBy(other); } + virtual void addInnerCompound(const Definition *def) + { m_impl.addInnerCompound(def); } + virtual void setOuterScope(Definition *def) + { m_impl.setOuterScope(def); } + virtual void setHidden(bool b) + { m_impl.setHidden(b); } + virtual void setArtificial(bool b) + { m_impl.setArtificial(b); } + virtual void setLanguage(SrcLangExt lang) + { m_impl.setLanguage(lang); } + virtual void writeSourceDef(OutputList &ol,const char *scopeName) const + { m_impl.writeSourceDef(ol,scopeName); } + virtual void writeInlineCode(OutputList &ol,const char *scopeName) const + { m_impl.writeInlineCode(ol,scopeName); } + virtual void writeSourceRefs(OutputList &ol,const char *scopeName) const + { m_impl.writeSourceRefs(ol,scopeName); } + virtual void writeSourceReffedBy(OutputList &ol,const char *scopeName) const + { m_impl.writeSourceReffedBy(ol,scopeName); } + virtual void makePartOfGroup(GroupDef *gd) + { m_impl.makePartOfGroup(gd); } + virtual void writeNavigationPath(OutputList &ol) const + { m_impl.writeNavigationPath(ol); } + virtual QCString navigationPathAsString() const + { return m_impl.navigationPathAsString(); } + virtual void writeQuickMemberLinks(OutputList &ol,const MemberDef *md) const + { m_impl.writeQuickMemberLinks(ol,md); } + virtual void writeSummaryLinks(OutputList &ol) const + { m_impl.writeSummaryLinks(ol); } + virtual QCString pathFragment() const + { return m_impl.pathFragment(); } + virtual void writeDocAnchorsToTagFile(FTextStream &fs) const + { m_impl.writeDocAnchorsToTagFile(fs); } + virtual void setLocalName(const QCString name) + { m_impl.setLocalName(name); } + virtual void addSectionsToIndex() + { m_impl.addSectionsToIndex(); } + virtual void writeToc(OutputList &ol, const LocalToc <) const + { m_impl.writeToc(ol,lt); } + virtual void setCookie(Definition::Cookie *cookie) const + { m_impl.setCookie(cookie); } + virtual Definition::Cookie *cookie() const + { return m_impl.cookie(); } + virtual void computeTooltip() + { m_impl.computeTooltip(); } + virtual void _setSymbolName(const QCString &name) + { m_impl._setSymbolName(name); } + virtual QCString _symbolName() const + { return m_impl._symbolName(); } + + protected: + + DefinitionMixin(const DefinitionMixin &def) = default; + + private: + virtual Definition *toDefinition_() { return this; } + virtual DefinitionMutable *toDefinitionMutable_() { return this; } + virtual const DefinitionImpl *toDefinitionImpl_() const { return &m_impl; } + + DefinitionImpl m_impl; +}; + +class DefinitionAliasImpl +{ + public: + DefinitionAliasImpl(Definition *def,const Definition *scope,const Definition *alias); virtual ~DefinitionAliasImpl(); + void init(); + void deinit(); + QCString name() const; + QCString qualifiedName() const; + private: + Definition *m_def; + const Definition *m_scope; + QCString m_symbolName; + QCString m_qualifiedName; +}; + +template<class Base> +class DefinitionAliasMixin : public Base +{ + public: + DefinitionAliasMixin(const Definition *scope,const Definition *alias) + : m_impl(this,scope,alias), m_scope(scope), m_alias(alias), m_cookie(0) {} + + void init() { m_impl.init(); } + void deinit() { m_impl.deinit(); } + + virtual ~DefinitionAliasMixin() = default; virtual bool isAlias() const { return TRUE; } - virtual const QCString &name() const - { return m_def->name(); } + + //======== Definition + virtual QCString name() const + { return m_impl.name(); } virtual bool isAnonymous() const - { return m_def->isAnonymous(); } + { return m_alias->isAnonymous(); } virtual QCString localName() const - { return m_def->localName(); } + { return m_alias->localName(); } virtual QCString qualifiedName() const - { return m_def->qualifiedName(); } + { return m_impl.qualifiedName(); } virtual QCString symbolName() const - { return m_def->symbolName(); } + { return m_alias->symbolName(); } virtual QCString getSourceFileBase() const - { return m_def->getSourceFileBase(); } + { return m_alias->getSourceFileBase(); } virtual QCString getSourceAnchor() const - { return m_def->getSourceAnchor(); } + { return m_alias->getSourceAnchor(); } virtual QCString documentation() const - { return m_def->documentation(); } + { return m_alias->documentation(); } virtual int docLine() const - { return m_def->docLine(); } + { return m_alias->docLine(); } virtual QCString docFile() const - { return m_def->docFile(); } + { return m_alias->docFile(); } virtual QCString briefDescription(bool abbreviate=FALSE) const - { return m_def->briefDescription(abbreviate); } + { return m_alias->briefDescription(abbreviate); } virtual QCString briefDescriptionAsTooltip() const - { return m_def->briefDescriptionAsTooltip(); } + { return m_alias->briefDescriptionAsTooltip(); } virtual int briefLine() const - { return m_def->briefLine(); } + { return m_alias->briefLine(); } virtual QCString inbodyDocumentation() const - { return m_def->inbodyDocumentation(); } + { return m_alias->inbodyDocumentation(); } virtual QCString inbodyFile() const - { return m_def->inbodyFile(); } + { return m_alias->inbodyFile(); } virtual int inbodyLine() const - { return m_def->inbodyLine(); } + { return m_alias->inbodyLine(); } virtual QCString briefFile() const - { return m_def->briefFile(); } + { return m_alias->briefFile(); } virtual QCString getDefFileName() const - { return m_def->getDefFileName(); } + { return m_alias->getDefFileName(); } virtual QCString getDefFileExtension() const - { return m_def->getDefFileExtension(); } + { return m_alias->getDefFileExtension(); } virtual int getDefLine() const - { return m_def->getDefLine(); } + { return m_alias->getDefLine(); } virtual int getDefColumn() const - { return m_def->getDefColumn(); } + { return m_alias->getDefColumn(); } virtual bool hasDocumentation() const - { return m_def->hasDocumentation(); } + { return m_alias->hasDocumentation(); } virtual bool hasUserDocumentation() const - { return m_def->hasUserDocumentation(); } + { return m_alias->hasUserDocumentation(); } virtual bool isVisibleInProject() const - { return m_def->isVisibleInProject(); } + { return m_alias->isVisibleInProject(); } virtual bool isVisible() const - { return m_def->isVisible(); } + { return m_alias->isVisible(); } virtual bool isHidden() const - { return m_def->isHidden(); } + { return m_alias->isHidden(); } virtual bool isArtificial() const - { return m_def->isArtificial(); } + { return m_alias->isArtificial(); } virtual QCString getReference() const - { return m_def->getReference(); } + { return m_alias->getReference(); } virtual bool isReference() const - { return m_def->isReference(); } + { return m_alias->isReference(); } virtual QCString externalReference(const QCString &relPath) const - { return m_def->externalReference(relPath); } + { return m_alias->externalReference(relPath); } virtual int getStartDefLine() const - { return m_def->getStartDefLine(); } + { return m_alias->getStartDefLine(); } virtual int getStartBodyLine() const - { return m_def->getStartBodyLine(); } + { return m_alias->getStartBodyLine(); } virtual int getEndBodyLine() const - { return m_def->getEndBodyLine(); } + { return m_alias->getEndBodyLine(); } virtual FileDef *getBodyDef() const - { return m_def->getBodyDef(); } + { return m_alias->getBodyDef(); } virtual SrcLangExt getLanguage() const - { return m_def->getLanguage(); } + { return m_alias->getLanguage(); } virtual GroupList *partOfGroups() const - { return m_def->partOfGroups(); } + { return m_alias->partOfGroups(); } virtual bool isLinkableViaGroup() const - { return m_def->isLinkableViaGroup(); } + { return m_alias->isLinkableViaGroup(); } virtual const RefItemVector &xrefListItems() const - { return m_def->xrefListItems(); } - virtual Definition *findInnerCompound(const char *name) const - { return m_def->findInnerCompound(name); } + { return m_alias->xrefListItems(); } + virtual const Definition *findInnerCompound(const char *name) const + { return m_alias->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 std::vector<const MemberDef *> getReferencesMembers() const + { return m_alias->getReferencesMembers(); } + virtual std::vector<const MemberDef *> getReferencedByMembers() const + { return m_alias->getReferencedByMembers(); } virtual bool hasSections() const - { return m_def->hasSections(); } + { return m_alias->hasSections(); } virtual bool hasSources() const - { return m_def->hasSources(); } + { return m_alias->hasSources(); } virtual bool hasBriefDescription() const - { return m_def->hasBriefDescription(); } + { return m_alias->hasBriefDescription(); } virtual QCString id() const - { return m_def->id(); } + { return m_alias->id(); } virtual const SectionRefs &getSectionRefs() const - { return m_def->getSectionRefs(); } + { return m_alias->getSectionRefs(); } virtual QCString navigationPathAsString() const - { return m_def->navigationPathAsString(); } + { return m_alias->navigationPathAsString(); } virtual QCString pathFragment() const - { return m_def->pathFragment(); } - virtual void setName(const char *) { } - virtual void setId(const char *) { } - virtual void setDefFile(const QCString&,int,int) {} - virtual void setDocumentation(const char *,const char *,int,bool=TRUE) {} - virtual void setBriefDescription(const char *,const char *,int) {} - virtual void setInbodyDocumentation(const char *,const char *,int) {} - virtual void setReference(const char *) {} - virtual void addSectionsToDefinition(const std::vector<const SectionInfo*> &) {} - virtual void setBodySegment(int,int,int) {} - virtual void setBodyDef(FileDef *) {} - virtual void addSourceReferencedBy(const MemberDef *) {} - virtual void addSourceReferences(const MemberDef *) {} - virtual void setRefItems(const RefItemVector &) {} - virtual void mergeRefItems(Definition *) {} - virtual void addInnerCompound(const Definition *) {} - virtual void setOuterScope(Definition *) {} - virtual void setHidden(bool) {} - virtual void setArtificial(bool) {} - virtual void setLanguage(SrcLangExt) {} - virtual void writeSourceDef(OutputList &,const char *) const {} - virtual void writeInlineCode(OutputList &,const char *) const {} - virtual void writeSourceRefs(OutputList &,const char *) const {} - virtual void writeSourceReffedBy(OutputList &,const char *) const {} - virtual void makePartOfGroup(GroupDef *) {} - virtual void writeNavigationPath(OutputList &) const {} - virtual void writeQuickMemberLinks(OutputList &,const MemberDef *) const {} - virtual void writeSummaryLinks(OutputList &) const {} - virtual void writeDocAnchorsToTagFile(FTextStream &) const {} - virtual void setLocalName(const QCString) {} - virtual void addSectionsToIndex() {} - virtual void writeToc(OutputList &, const LocalToc &) const {} - virtual void setCookie(Cookie *cookie) const { delete m_cookie; m_cookie = cookie; } - virtual Cookie *cookie() const { return m_cookie; } + { return m_alias->pathFragment(); } + protected: - const Definition *getAlias() const { return m_def; } + const Definition *getAlias() const { return m_alias; } const Definition *getScope() const { return m_scope; } private: + virtual Definition *toDefinition_() { return this; } + virtual DefinitionMutable *toDefinitionMutable_() { return 0; } + virtual const DefinitionImpl *toDefinitionImpl_() const { return 0; } + + virtual void setCookie(Definition::Cookie *cookie) const { delete m_cookie; m_cookie = cookie; } + virtual Definition::Cookie *cookie() const { return m_cookie; } virtual void _setSymbolName(const QCString &name) { m_symbolName = name; } virtual QCString _symbolName() const { return m_symbolName; } + DefinitionAliasImpl m_impl; const Definition *m_scope; - const Definition *m_def; - mutable Cookie *m_cookie; + const Definition *m_alias; + mutable Definition::Cookie *m_cookie; QCString m_symbolName; }; - #endif diff --git a/src/diagram.cpp b/src/diagram.cpp index d0b7a08..64ea491 100644 --- a/src/diagram.cpp +++ b/src/diagram.cpp @@ -1,13 +1,10 @@ /****************************************************************************** * - * - * - * - * Copyright (C) 1997-2015 by Dimitri van Heesch. + * Copyright (C) 1997-2020 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. * @@ -36,86 +33,80 @@ //----------------------------------------------------------------------------- -class DiagramItemList; +class TreeDiagram; +class DiagramItem; +using DiagramItemList = std::vector<DiagramItem*>; /** Class representing a single node in the built-in class diagram */ -class DiagramItem +class DiagramItem { public: DiagramItem(DiagramItem *p,uint number,const ClassDef *cd, Protection prot,Specifier virt,const char *ts); - ~DiagramItem(); QCString label() const; QCString fileName() const; - DiagramItem *parentItem() { return parent; } - DiagramItemList *getChildren() { return children; } - void move(int dx,int dy) { x+=(uint)dx; y+=(uint)dy; } - uint xPos() const { return x; } - uint yPos() const { return y; } + DiagramItem *parentItem() { return m_parent; } + DiagramItemList getChildren() { return m_children; } + void move(int dx,int dy) { m_x+=(uint)dx; m_y+=(uint)dy; } + uint xPos() const { return m_x; } + uint yPos() const { return m_y; } uint avgChildPos() const; uint numChildren() const; void addChild(DiagramItem *di); - uint number() const { return num; } - Protection protection() const { return prot; } - Specifier virtualness() const { return virt; } - void putInList() { inList=TRUE; } - bool isInList() const { return inList; } - const ClassDef *getClassDef() const { return classDef; } + uint number() const { return m_num; } + Protection protection() const { return m_prot; } + Specifier virtualness() const { return m_virt; } + void putInList() { m_inList=TRUE; } + bool isInList() const { return m_inList; } + const ClassDef *getClassDef() const { return m_classDef; } private: - DiagramItemList *children; - DiagramItem *parent; - uint x,y; - uint num; - Protection prot; - Specifier virt; - QCString templSpec; - bool inList; - const ClassDef *classDef; -}; - -/** Class representing a list of DiagramItem object. */ -class DiagramItemList : public QList<DiagramItem> -{ - public: - DiagramItemList() : QList<DiagramItem>() {} - ~DiagramItemList() {} + DiagramItemList m_children; + DiagramItem *m_parent; + uint m_x = 0; + uint m_y = 0; + uint m_num; + Protection m_prot; + Specifier m_virt; + QCString m_templSpec; + bool m_inList = false; + const ClassDef *m_classDef; }; /** Class representing a row in the built-in class diagram */ -class DiagramRow : public QList<DiagramItem> +class DiagramRow { public: - DiagramRow(TreeDiagram *d,uint l) : QList<DiagramItem>() - { - diagram=d; - level=l; - setAutoDelete(TRUE); - } + using Ptr = std::unique_ptr<DiagramItem>; + using Vec = std::vector<Ptr>; + using iterator = typename Vec::iterator; + using reverse_iterator = typename Vec::reverse_iterator; + DiagramRow(TreeDiagram *d,uint l) : m_diagram(d), m_level(l) {} void insertClass(DiagramItem *parent,const ClassDef *cd,bool doBases, Protection prot,Specifier virt,const char *ts); - uint number() { return level; } + uint number() { return m_level; } + + DiagramItem *item(int index) { return m_items.at(index).get(); } + uint numItems() const { return static_cast<uint>(m_items.size()); } + iterator begin() { return m_items.begin(); } + iterator end() { return m_items.end(); } + reverse_iterator rbegin() { return m_items.rbegin(); } + reverse_iterator rend() { return m_items.rend(); } private: - TreeDiagram *diagram; - uint level; -}; - -/** Class representing iterator for the rows in the built-in class diagram. */ -class DiagramRowIterator : public QListIterator<DiagramRow> -{ - public: - DiagramRowIterator(const QList<DiagramRow> &d) - : QListIterator<DiagramRow>(d) {} + TreeDiagram *m_diagram; + uint m_level; + Vec m_items; }; /** Class representing the tree layout for the built-in class diagram. */ -class TreeDiagram : public QList<DiagramRow> +class TreeDiagram { public: + using Ptr = std::unique_ptr<DiagramRow>; + using Vec = std::vector<Ptr>; + using iterator = typename Vec::iterator; TreeDiagram(const ClassDef *root,bool doBases); - ~TreeDiagram(); void computeLayout(); uint computeRows(); - //uint computeCols(); void moveChildren(DiagramItem *root,int dx); void computeExtremes(uint *labelWidth,uint *xpos); void drawBoxes(FTextStream &t,Image *image, @@ -128,10 +119,17 @@ class TreeDiagram : public QList<DiagramRow> bool doBase,bool bitmap, uint baseRows,uint superRows, uint cellWidth,uint cellheight); + DiagramRow *row(int index) { return m_rows.at(index).get(); } + uint numRows() const { return static_cast<uint>(m_rows.size()); } + DiagramRow *addRow(uint l) + { m_rows.push_back(std::make_unique<DiagramRow>(this,l)); return m_rows.back().get(); } + iterator begin() { return m_rows.begin(); } + iterator end() { return m_rows.end(); } private: bool layoutTree(DiagramItem *root,uint row); TreeDiagram &operator=(const TreeDiagram &); TreeDiagram(const TreeDiagram &); + Vec m_rows; }; @@ -147,18 +145,6 @@ const uint labelVertSpacing = 32; // vertical distance between labels const uint labelHorMargin = 6; // horiz. spacing between label and box const uint fontHeight = 12; // height of a character -//static QCString escapeLatex(const char *s) -//{ -// QCString result; -// char c; -// while ((c=*s++)) -// { -// if (c=='_') result+="\\_"; -// else result+=c; -// } -// return result; -//} - static uint protToMask(Protection p) { switch(p) @@ -207,18 +193,21 @@ static uint virtToMask(Specifier p) } // pre: dil is not empty -static Protection getMinProtectionLevel(DiagramItemList *dil) +static Protection getMinProtectionLevel(const DiagramItemList &dil) { - QListIterator<DiagramItem> it(*dil); - DiagramItem *di=it.current(); - Protection result=di->protection(); - for (++it;(di=it.current());++it) + auto it = dil.begin(); + Protection result = Private; + if (it!=dil.end()) { - Protection p=di->protection(); - if (p!=result) + result=(*it)->protection(); + for (++it;it!=dil.end();++it) { - if (result==Protected && p==Public) result=p; - else if (result==Private) result=p; + Protection p=(*it)->protection(); + if (p!=result) + { + if (result==Protected && p==Public) result=p; + else if (result==Private) result=p; + } } } return result; @@ -261,7 +250,7 @@ static void writeMapArea(FTextStream &t,const ClassDef *cd,QCString relPath, { QCString ref=cd->getReference(); t << "<area "; - if (!ref.isEmpty()) + if (!ref.isEmpty()) { t << externalLinkTarget(true); } @@ -278,7 +267,7 @@ static void writeMapArea(FTextStream &t,const ClassDef *cd,QCString relPath, { t << "title=\"" << convertToHtml(tooltip) << "\" "; } - t << "alt=\"" << convertToXML(cd->displayName()); + t << "alt=\"" << convertToXML(cd->displayName()); t << "\" shape=\"rect\" coords=\"" << x << "," << y << ","; t << (x+w) << "," << (y+h) << "\"/>" << endl; } @@ -286,41 +275,28 @@ static void writeMapArea(FTextStream &t,const ClassDef *cd,QCString relPath, //----------------------------------------------------------------------------- DiagramItem::DiagramItem(DiagramItem *p,uint number,const ClassDef *cd, - Protection pr,Specifier vi,const char *ts) -{ - parent=p; - x=y=0; - num=number; - children = new DiagramItemList; - prot=pr; - virt=vi; - inList=FALSE; - classDef=cd; - templSpec=ts; -} - -DiagramItem::~DiagramItem() + Protection pr,Specifier vi,const char *ts) + : m_parent(p), m_num(number), m_prot(pr), m_virt(vi), m_templSpec(ts), m_classDef(cd) { - delete children; } QCString DiagramItem::label() const { QCString result; - if (!templSpec.isEmpty()) + if (!m_templSpec.isEmpty()) { // we use classDef->name() here and not displayName() in order // to get the name used in the inheritance relation. - QCString n = classDef->name(); + QCString n = m_classDef->name(); if (/*n.right(2)=="-g" ||*/ n.right(2)=="-p") { n = n.left(n.length()-2); } - result=insertTemplateSpecifierInScope(n,templSpec); + result=insertTemplateSpecifierInScope(n,m_templSpec); } else { - result=classDef->displayName(); + result=m_classDef->displayName(); } if (Config_getBool(HIDE_SCOPE_NAMES)) result=stripScope(result); return result; @@ -328,104 +304,88 @@ QCString DiagramItem::label() const QCString DiagramItem::fileName() const { - return classDef->getOutputFileBase(); + return m_classDef->getOutputFileBase(); } uint DiagramItem::avgChildPos() const { DiagramItem *di; - uint c=children->count(); + size_t c=m_children.size(); if (c==0) // no children -> don't move return xPos(); - if ((di=children->getFirst())->isInList()) // children should be in a list + if ((di=m_children.front())->isInList()) // children should be in a list return di->xPos(); if (c&1) // odd number of children -> get pos of middle child - return children->at(c/2)->xPos(); + return m_children.at(c/2)->xPos(); else // even number of children -> get middle of most middle children - return (children->at(c/2-1)->xPos()+children->at(c/2)->xPos())/2; + return (m_children.at(c/2-1)->xPos()+m_children.at(c/2)->xPos())/2; } uint DiagramItem::numChildren() const { - return children->count(); + return static_cast<uint>(m_children.size()); } void DiagramItem::addChild(DiagramItem *di) { - children->append(di); + m_children.push_back(di); } +//--------------------------------------------------------------------------- + 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 - // multiple inheritance of the same class! - DiagramItem *di=new DiagramItem(parent, diagram->at(level)->count(), - cd,prot,virt,ts); - //cd->visited=TRUE; - if (parent) parent->addChild(di); - di->move((int)(count()*gridWidth),(int)(level*gridHeight)); - append(di); - BaseClassList *bcl=doBases ? cd->baseClasses() : cd->subClasses(); + auto di = std::make_unique<DiagramItem>(parent, m_diagram->row(m_level)->numItems(), + cd,prot,virt,ts); + DiagramItem *di_ptr = di.get(); + if (parent) parent->addChild(di_ptr); + di->move((int)(m_items.size()*gridWidth),(int)(m_level*gridHeight)); + m_items.push_back(std::move(di)); int count=0; - if (bcl) + for (const auto &bcd : doBases ? cd->baseClasses() : cd->subClasses()) { /* there are base/sub classes */ - BaseClassListIterator it(*bcl); - BaseClassDef *bcd; - for (;(bcd=it.current());++it) - { - ClassDef *ccd=bcd->classDef; - if (ccd && ccd->isVisibleInHierarchy() /*&& !ccd->visited*/) count++; - } + ClassDef *ccd=bcd.classDef; + if (ccd && ccd->isVisibleInHierarchy()) count++; } if (count>0 && (prot!=Private || !doBases)) { DiagramRow *row=0; - if (diagram->count()<=level+1) /* add new row */ + if (m_diagram->numRows()<=m_level+1) /* add new row */ { - row = new DiagramRow(diagram,level+1); - diagram->append(row); + row=m_diagram->addRow(m_level+1); } else /* get next row */ { - row=diagram->at(level+1); + row=m_diagram->row(m_level+1); } - /* insert base classes in the next row */ - BaseClassListIterator it(*bcl); - BaseClassDef *bcd; - for (;(bcd=it.current());++it) + for (const auto &bcd : doBases ? cd->baseClasses() : cd->subClasses()) { - ClassDef *ccd=bcd->classDef; - if (ccd && ccd->isVisibleInHierarchy() /*&& !ccd->visited*/) + ClassDef *ccd=bcd.classDef; + if (ccd && ccd->isVisibleInHierarchy()) { - row->insertClass(di,ccd,doBases,bcd->prot, - doBases?bcd->virt:Normal, - doBases?bcd->templSpecifiers.data():""); + row->insertClass(di_ptr,ccd,doBases,bcd.prot, + doBases?bcd.virt:Normal, + doBases?bcd.templSpecifiers.data():""); } } } } -TreeDiagram::TreeDiagram(const ClassDef *root,bool doBases) -{ - setAutoDelete(TRUE); - DiagramRow *row=new DiagramRow(this,0); - append(row); - row->insertClass(0,root,doBases,Public,Normal,0); -} +//--------------------------------------------------------------------------- -TreeDiagram::~TreeDiagram() +TreeDiagram::TreeDiagram(const ClassDef *root,bool doBases) { + auto row = std::make_unique<DiagramRow>(this,0); + DiagramRow *row_ptr = row.get(); + m_rows.push_back(std::move(row)); + row_ptr->insertClass(0,root,doBases,Public,Normal,0); } - void TreeDiagram::moveChildren(DiagramItem *root,int dx) { - DiagramItemList *dil=root->getChildren(); - QListIterator<DiagramItem> it(*dil); - DiagramItem *di; - for (;(di=it.current());++it) + for (const auto &di : root->getChildren()) { di->move(dx,0); moveChildren(di,dx); @@ -437,37 +397,36 @@ bool TreeDiagram::layoutTree(DiagramItem *root,uint r) bool moved=FALSE; //printf("layoutTree(%s,%d)\n",root->label().data(),r); - DiagramItemList *dil=root->getChildren(); - if (dil->count()>0) + if (root->numChildren()>0) { + auto children = root->getChildren(); uint k; uint pPos=root->xPos(); uint cPos=root->avgChildPos(); if (pPos>cPos) // move children { - DiagramRow *row=at(r+1); + const auto &row=m_rows.at(r+1); //printf("Moving children %d-%d in row %d\n", // dil->getFirst()->number(),row->count()-1,r+1); - for (k=dil->getFirst()->number();k<row->count();k++) - row->at(k)->move((int)(pPos-cPos),0); + for (k=children.front()->number();k<row->numItems();k++) + row->item(k)->move((int)(pPos-cPos),0); moved=TRUE; } else if (pPos<cPos) // move parent { - DiagramRow *row=at(r); + const auto &row=m_rows.at(r); //printf("Moving parents %d-%d in row %d\n", // root->number(),row->count()-1,r); - for (k=root->number();k<row->count();k++) - row->at(k)->move((int)(cPos-pPos),0); + for (k=root->number();k<row->numItems();k++) + row->item(k)->move((int)(cPos-pPos),0); moved=TRUE; } // recurse to children - QListIterator<DiagramItem> it(*dil); - DiagramItem *di; - for (;(di=it.current()) && !moved && !di->isInList();++it) + auto it = children.begin(); + for (;it!=children.end() && !moved && !(*it)->isInList();++it) { - moved = layoutTree(di,r+1); + moved = layoutTree(*it,r+1); } } return moved; @@ -475,18 +434,16 @@ bool TreeDiagram::layoutTree(DiagramItem *root,uint r) void TreeDiagram::computeLayout() { - QListIterator<DiagramRow> it(*this); - DiagramRow *row; - for (;(row=it.current()) && row->count()<maxTreeWidth;++it) {} - if (row) + auto it = m_rows.begin(); + while (it!=m_rows.end() && (*it)->numItems()<maxTreeWidth) ++it; + if (it!=m_rows.end()) { + const auto &row = *it; //printf("computeLayout() list row at %d\n",row->number()); - QListIterator<DiagramItem> rit(*row); - DiagramItem *di; DiagramItem *opi=0; int delta=0; bool first=TRUE; - for (;(di=rit.current());++rit) + for (const auto &di : *row) { DiagramItem *pi=di->parentItem(); if (pi==opi && !first) { delta-=gridWidth; } @@ -499,21 +456,24 @@ void TreeDiagram::computeLayout() } // re-organize the diagram items - DiagramItem *root=getFirst()->getFirst(); + DiagramItem *root=m_rows.front()->item(0); while (layoutTree(root,0)) { } // move first items of the lists - if (row) + if (it!=m_rows.end()) { - QListIterator<DiagramItem> rit(*row); - DiagramItem *di; - while ((di=rit.current())) + const auto &row = *it; + auto rit = row->begin(); + while (rit!=row->end()) { - DiagramItem *pi=di->parentItem(); - if (pi->getChildren()->count()>1) + DiagramItem *pi=(*rit)->parentItem(); + if (pi->numChildren()>1) { - di->move(gridWidth,0); - while (di && di->parentItem()==pi) { ++rit; di=rit.current(); } + (*rit)->move(gridWidth,0); + while (rit!=row->end() && (*rit)->parentItem()==pi) + { + ++rit; + } } else { @@ -527,23 +487,23 @@ uint TreeDiagram::computeRows() { //printf("TreeDiagram::computeRows()=%d\n",count()); uint count=0; - QListIterator<DiagramRow> it(*this); - DiagramRow *row; - for (;(row=it.current()) && !row->getFirst()->isInList();++it) + auto it = m_rows.begin(); + while (it!=m_rows.end() && !(*it)->item(0)->isInList()) { - count++; + ++it; + ++count; } + //printf("count=%d row=%p\n",count,row); - if (row) + if (it!=m_rows.end()) { + const auto &row = *it; uint maxListLen=0; uint curListLen=0; DiagramItem *opi=0; - QListIterator<DiagramItem> rit(*row); - DiagramItem *di; - for (;(di=rit.current());++rit) + for (const auto &di : *row) // for each item in a row { - if (di->parentItem()!=opi) curListLen=1; else curListLen++; + if (di->parentItem()!=opi) curListLen=1; else curListLen++; if (curListLen>maxListLen) maxListLen=curListLen; opi=di->parentItem(); } @@ -556,48 +516,80 @@ uint TreeDiagram::computeRows() void TreeDiagram::computeExtremes(uint *maxLabelLen,uint *maxXPos) { uint ml=0,mx=0; - QListIterator<DiagramRow> it(*this); - DiagramRow *dr; - bool done=FALSE; - for (;(dr=it.current()) && !done;++it) + for (const auto &dr : m_rows) // for each row { - QListIterator<DiagramItem> rit(*dr); - DiagramItem *di; - for (;(di=rit.current());++rit) + bool done=FALSE; + for (const auto &di : *dr) // for each item in a row { if (di->isInList()) done=TRUE; if (maxXPos) mx=QMAX(mx,(uint)di->xPos()); if (maxLabelLen) ml=QMAX(ml,Image::stringLength(di->label())); } + if (done) break; } if (maxLabelLen) *maxLabelLen=ml; if (maxXPos) *maxXPos=mx; } -void TreeDiagram::drawBoxes(FTextStream &t,Image *image, +//! helper class representing an iterator that can iterate forwards or backwards +template<class C,class I> +class DualDirIterator +{ + public: + DualDirIterator(C &container,bool fwd) + : m_container(container), m_forward(fwd) + { + if (fwd) m_it = container.begin(); + else m_rit = container.rbegin(); + } + void operator++() + { + if (m_forward) ++m_it++; else ++m_rit; + } + I &operator*() + { + return m_forward ? *m_it : *m_rit; + } + + bool atEnd() + { + if (m_forward) + return m_it==m_container.end(); + else + return m_rit==m_container.rend(); + } + + private: + C &m_container; + bool m_forward; + typename C::iterator m_it; + typename C::reverse_iterator m_rit; +}; + +void TreeDiagram::drawBoxes(FTextStream &t,Image *image, bool doBase,bool bitmap, uint baseRows,uint superRows, uint cellWidth,uint cellHeight, QCString relPath, bool generateMap) { - QListIterator<DiagramRow> it(*this); - DiagramRow *dr; - if (!doBase) ++it; - bool done=FALSE; + auto it = m_rows.begin(); + if (it!=m_rows.end() && !doBase) ++it; bool firstRow = doBase; - for (;(dr=it.current()) && !done;++it) + bool done=FALSE; + for (;it!=m_rows.end() && !done;++it) // for each row { + const auto &dr = *it; uint x=0,y=0; float xf=0.0f,yf=0.0f; - QListIterator<DiagramItem> rit(*dr); - DiagramItem *di = rit.current(); - if (di->isInList()) // put boxes in a list + DiagramItem *firstDi = dr->item(0); + if (firstDi->isInList()) // put boxes in a list { DiagramItem *opi=0; - if (doBase) rit.toLast(); else rit.toFirst(); - while ((di=rit.current())) + DualDirIterator<DiagramRow,const std::unique_ptr<DiagramItem>&> dit(*dr,!doBase); + while (!dit.atEnd()) { + DiagramItem *di = (*dit).get(); if (di->parentItem()==opi) { if (bitmap) @@ -643,27 +635,27 @@ void TreeDiagram::drawBoxes(FTextStream &t,Image *image, } } opi=di->parentItem(); - + if (bitmap) { bool hasDocs=di->getClassDef()->isLinkable(); writeBitmapBox(di,image,x,y,cellWidth,cellHeight,firstRow, - hasDocs,di->getChildren()->count()>0); - if (!firstRow && generateMap) + hasDocs,di->numChildren()>0); + if (!firstRow && generateMap) writeMapArea(t,di->getClassDef(),relPath,x,y,cellWidth,cellHeight); } else { - writeVectorBox(t,di,xf,yf,di->getChildren()->count()>0); + writeVectorBox(t,di,xf,yf,di->numChildren()>0); } - - if (doBase) --rit; else ++rit; + + ++dit; } done=TRUE; } else // draw a tree of boxes { - for (rit.toFirst();(di=rit.current());++rit) + for (const auto &di : *dr) { if (bitmap) { @@ -681,8 +673,8 @@ void TreeDiagram::drawBoxes(FTextStream &t,Image *image, di->yPos()*(cellHeight+labelVertSpacing)/gridHeight; } bool hasDocs=di->getClassDef()->isLinkable(); - writeBitmapBox(di,image,x,y,cellWidth,cellHeight,firstRow,hasDocs); - if (!firstRow && generateMap) + writeBitmapBox(di.get(),image,x,y,cellWidth,cellHeight,firstRow,hasDocs); + if (!firstRow && generateMap) writeMapArea(t,di->getClassDef(),relPath,x,y,cellWidth,cellHeight); } else @@ -696,7 +688,7 @@ void TreeDiagram::drawBoxes(FTextStream &t,Image *image, { yf = superRows-1-di->yPos()/(float)gridHeight; } - writeVectorBox(t,di,xf,yf); + writeVectorBox(t,di.get(),xf,yf); } } } @@ -709,22 +701,23 @@ void TreeDiagram::drawConnectors(FTextStream &t,Image *image, uint baseRows,uint superRows, uint cellWidth,uint cellHeight) { - QListIterator<DiagramRow> it(*this); - DiagramRow *dr; bool done=FALSE; - for (;(dr=it.current()) && !done;++it) // for each row + auto it = m_rows.begin(); + for (;it!=m_rows.end() && !done;++it) // for each row { - QListIterator<DiagramItem> rit(*dr); - DiagramItem *di = rit.current(); - if (di->isInList()) // row consists of list connectors + const auto &dr = *it; + DiagramItem *rootDi = dr->item(0); + if (rootDi->isInList()) // row consists of list connectors { uint x=0,y=0,ys=0; float xf=0.0f,yf=0.0f,ysf=0.0f; - for (;(di=rit.current());++rit) + auto rit = dr->begin(); + while (rit!=dr->end()) { + DiagramItem *di=(*rit).get(); DiagramItem *pi=di->parentItem(); - DiagramItemList *dil=pi->getChildren(); - DiagramItem *last=dil->getLast(); + DiagramItemList dil=pi->getChildren(); + DiagramItem *last=dil.back(); if (di==last) // single child { if (bitmap) // draw pixels @@ -754,12 +747,12 @@ void TreeDiagram::drawConnectors(FTextStream &t,Image *image, t << protToString(di->protection()) << endl; if (doBase) { - t << "1 " << (di->xPos()/(float)gridWidth) << " " + t << "1 " << (di->xPos()/(float)gridWidth) << " " << (di->yPos()/(float)gridHeight+superRows-1) << " in\n"; } else { - t << "0 " << (di->xPos()/(float)gridWidth) << " " + t << "0 " << (di->xPos()/(float)gridWidth) << " " << ((float)superRows-0.25f-di->yPos()/(float)gridHeight) << " in\n"; } @@ -832,7 +825,8 @@ void TreeDiagram::drawConnectors(FTextStream &t,Image *image, yf -= 1.0f; } } - ++rit; di=rit.current(); + ++rit; + if (rit!=dr->end()) di = (*rit).get(); else di=0; } // add last horizontal line and a vertical connection line if (bitmap) @@ -878,15 +872,16 @@ void TreeDiagram::drawConnectors(FTextStream &t,Image *image, } } } + if (rit!=dr->end()) ++rit; } done=TRUE; // the tree is drawn now } else // normal tree connector { - for (;(di=rit.current());++rit) + for (const auto &di : *dr) { uint x=0,y=0; - DiagramItemList *dil = di->getChildren(); + DiagramItemList dil = di->getChildren(); DiagramItem *parent = di->parentItem(); if (parent) // item has a parent -> connect to it { @@ -919,18 +914,18 @@ void TreeDiagram::drawConnectors(FTextStream &t,Image *image, t << protToString(di->protection()) << endl; if (doBase) { - t << "1 " << di->xPos()/(float)gridWidth << " " + t << "1 " << di->xPos()/(float)gridWidth << " " << (di->yPos()/(float)gridHeight+superRows-1) << " in\n"; } else { - t << "0 " << di->xPos()/(float)gridWidth << " " + t << "0 " << di->xPos()/(float)gridWidth << " " << ((float)superRows-0.25f-di->yPos()/(float)gridHeight) << " in\n"; } } } - if (dil->count()>0) + if (!dil.empty()) { Protection p=getMinProtectionLevel(dil); uint mask=protToMask(p); @@ -959,19 +954,19 @@ void TreeDiagram::drawConnectors(FTextStream &t,Image *image, t << protToString(p) << endl; if (doBase) { - t << "0 " << di->xPos()/(float)gridWidth << " " + t << "0 " << di->xPos()/(float)gridWidth << " " << (di->yPos()/(float)gridHeight+superRows-1) << " out\n"; } else { - t << "1 " << di->xPos()/(float)gridWidth << " " + t << "1 " << di->xPos()/(float)gridWidth << " " << ((float)superRows-1.75f-di->yPos()/(float)gridHeight) << " out\n"; } } /* write input line */ - DiagramItem *first = dil->getFirst(); - DiagramItem *last = dil->getLast(); + DiagramItem *first = dil.front(); + DiagramItem *last = dil.back(); if (first!=last && !first->isInList()) /* connect with all base classes */ { if (bitmap) @@ -979,14 +974,14 @@ void TreeDiagram::drawConnectors(FTextStream &t,Image *image, uint xs = first->xPos()*(cellWidth+labelHorSpacing)/gridWidth + cellWidth/2; uint xe = last->xPos()*(cellWidth+labelHorSpacing)/gridWidth - + cellWidth/2; + + cellWidth/2; if (doBase) // base classes { - image->drawHorzLine(y,xs,xe,col,mask); + image->drawHorzLine(y,xs,xe,col,mask); } else // super classes { - image->drawHorzLine(y+labelVertSpacing/2,xs,xe,col,mask); + image->drawHorzLine(y+labelVertSpacing/2,xs,xe,col,mask); } } else @@ -994,14 +989,14 @@ void TreeDiagram::drawConnectors(FTextStream &t,Image *image, t << protToString(p) << endl; if (doBase) { - t << first->xPos()/(float)gridWidth << " " + t << first->xPos()/(float)gridWidth << " " << last->xPos()/(float)gridWidth << " " - << (first->yPos()/(float)gridHeight+superRows-1) + << (first->yPos()/(float)gridHeight+superRows-1) << " conn\n"; } else { - t << first->xPos()/(float)gridWidth << " " + t << first->xPos()/(float)gridWidth << " " << last->xPos()/(float)gridWidth << " " << ((float)superRows-first->yPos()/(float)gridHeight) << " conn\n"; @@ -1014,74 +1009,69 @@ void TreeDiagram::drawConnectors(FTextStream &t,Image *image, } } +//----------------------------------------------------------------- -void clearVisitFlags() +struct ClassDiagram::Private { - ClassSDict::Iterator cli(*Doxygen::classSDict); - ClassDef *cd; - for (;(cd=cli.current());++cli) - { - cd->setVisited(FALSE); - } -} + Private(const ClassDef *root) : base(root,true), super(root,false) {} + TreeDiagram base; + TreeDiagram super; +}; + +//----------------------------------------------------------------- + -ClassDiagram::ClassDiagram(const ClassDef *root) +ClassDiagram::ClassDiagram(const ClassDef *root) : p(std::make_unique<Private>(root)) { - clearVisitFlags(); - base = new TreeDiagram(root,TRUE); - base->computeLayout(); - clearVisitFlags(); - super = new TreeDiagram(root,FALSE); - super->computeLayout(); - DiagramItem *baseItem = base->getFirst()->getFirst(); - DiagramItem *superItem = super->getFirst()->getFirst(); + p->base.computeLayout(); + p->super.computeLayout(); + DiagramItem *baseItem = p->base.row(0)->item(0); + DiagramItem *superItem = p->super.row(0)->item(0); uint xbase = baseItem->xPos(); uint xsuper = superItem->xPos(); if (xbase>xsuper) { superItem->move((int)(xbase-xsuper),0); - super->moveChildren(superItem,(int)(xbase-xsuper)); + p->super.moveChildren(superItem,(int)(xbase-xsuper)); } else if (xbase<xsuper) { baseItem->move((int)(xsuper-xbase),0); - base->moveChildren(baseItem,(int)(xsuper-xbase)); + p->base.moveChildren(baseItem,(int)(xsuper-xbase)); } } ClassDiagram::~ClassDiagram() { - delete base; - delete super; } void ClassDiagram::writeFigure(FTextStream &output,const char *path, const char *fileName) const { - uint baseRows=base->computeRows(); - uint superRows=super->computeRows(); + uint baseRows=p->base.computeRows(); + uint superRows=p->super.computeRows(); uint baseMaxX, baseMaxLabelWidth, superMaxX, superMaxLabelWidth; - base->computeExtremes(&baseMaxLabelWidth,&baseMaxX); - super->computeExtremes(&superMaxLabelWidth,&superMaxX); + p->base.computeExtremes(&baseMaxLabelWidth,&baseMaxX); + p->super.computeExtremes(&superMaxLabelWidth,&superMaxX); uint rows=baseRows+superRows-1; uint cols=(QMAX(baseMaxX,superMaxX)+gridWidth*2-1)/gridWidth; - + // Estimate the image aspect width and height in pixels. uint estHeight = rows*40; uint estWidth = cols*(20+QMAX(baseMaxLabelWidth,superMaxLabelWidth)); //printf("Estimated size %d x %d\n",estWidth,estHeight); - + const float pageWidth = 14.0f; // estimated page width in cm. // Somewhat lower to deal with estimation - // errors. - + // errors. + // compute the image height in centimeters based on the estimates float realHeight = QMIN(rows,12); // real height in cm float realWidth = realHeight * estWidth/(float)estHeight; if (realWidth>pageWidth) // assume that the page width is about 15 cm { - realHeight*=pageWidth/realWidth; + realHeight*=pageWidth/realWidth; realWidth=pageWidth; } @@ -1089,11 +1079,11 @@ void ClassDiagram::writeFigure(FTextStream &output,const char *path, output << "\\begin{figure}[H]\n" "\\begin{center}\n" "\\leavevmode\n"; - output << "\\includegraphics[height=" << realHeight << "cm]{" + output << "\\includegraphics[height=" << realHeight << "cm]{" << fileName << "}" << endl; output << "\\end{center}\n" "\\end{figure}\n"; - + //printf("writeFigure rows=%d cols=%d\n",rows,cols); QCString epsBaseName=(QCString)path+"/"+fileName; @@ -1105,11 +1095,11 @@ void ClassDiagram::writeFigure(FTextStream &output,const char *path, term("Could not open file %s for writing\n",f1.name().data()); } FTextStream t(&f1); - + //printf("writeEPS() rows=%d cols=%d\n",rows,cols); - + // generate EPS header and postscript variables and procedures - + t << "%!PS-Adobe-2.0 EPSF-2.0\n"; t << "%%Title: ClassName\n"; t << "%%Creator: Doxygen\n"; @@ -1287,31 +1277,29 @@ void ClassDiagram::writeFigure(FTextStream &output,const char *path, t << "1 boundaspect scale\n"; - bool done=FALSE; - QListIterator<DiagramRow> bit(*base); - DiagramRow *dr; - for (;(dr=bit.current()) && !done;++bit) + for (const auto &dr : p->base) { - QListIterator<DiagramItem> rit(*dr); - DiagramItem *di; - for (;(di=rit.current());++rit) + bool done=FALSE; + for (const auto &di : *dr) { done=di->isInList(); t << "(" << convertToPSString(di->label()) << ") cw\n"; } + if (done) break; } - QListIterator<DiagramRow> sit(*super); - ++sit; - done=FALSE; - for (;(dr=sit.current()) && !done;++sit) + + auto it = p->super.begin(); + if (it!=p->super.end()) ++it; + for (;it!=p->super.end();++it) { - QListIterator<DiagramItem> rit(*dr); - DiagramItem *di; - for (;(di=rit.current());++rit) + const auto &dr = *it; + bool done=FALSE; + for (const auto &di : *dr) { done=di->isInList(); t << "(" << convertToPSString(di->label()) << ") cw\n"; } + if (done) break; } t << "/boxwidth boxwidth marginwidth 2 mul add def\n" @@ -1322,14 +1310,14 @@ void ClassDiagram::writeFigure(FTextStream &output,const char *path, << " boxheight rows mul disty rows 1 sub mul add boundaspect mul \n" << " max def\n" << "boundx scalefactor div boundy scalefactor div scale\n"; - + t << "\n% ----- classes -----\n\n"; - base->drawBoxes(t,0,TRUE,FALSE,baseRows,superRows,0,0); - super->drawBoxes(t,0,FALSE,FALSE,baseRows,superRows,0,0); - + p->base.drawBoxes(t,0,TRUE,FALSE,baseRows,superRows,0,0); + p->super.drawBoxes(t,0,FALSE,FALSE,baseRows,superRows,0,0); + t << "\n% ----- relations -----\n\n"; - base->drawConnectors(t,0,TRUE,FALSE,baseRows,superRows,0,0); - super->drawConnectors(t,0,FALSE,FALSE,baseRows,superRows,0,0); + p->base.drawConnectors(t,0,TRUE,FALSE,baseRows,superRows,0,0); + p->super.drawConnectors(t,0,FALSE,FALSE,baseRows,superRows,0,0); f1.close(); if (Config_getBool(USE_PDFLATEX)) @@ -1351,17 +1339,17 @@ void ClassDiagram::writeFigure(FTextStream &output,const char *path, void ClassDiagram::writeImage(FTextStream &t,const char *path, - const char *relPath,const char *fileName, + const char *relPath,const char *fileName, bool generateMap) const { - uint baseRows=base->computeRows(); - uint superRows=super->computeRows(); + uint baseRows=p->base.computeRows(); + uint superRows=p->super.computeRows(); uint rows=baseRows+superRows-1; uint lb,ls,xb,xs; - base->computeExtremes(&lb,&xb); - super->computeExtremes(&ls,&xs); - + p->base.computeExtremes(&lb,&xb); + p->super.computeExtremes(&ls,&xs); + uint cellWidth = QMAX(lb,ls)+labelHorMargin*2; uint maxXPos = QMAX(xb,xs); uint labelVertMargin = 6; //QMAX(6,(cellWidth-fontHeight)/6); // aspect at least 1:3 @@ -1372,10 +1360,10 @@ void ClassDiagram::writeImage(FTextStream &t,const char *path, Image image(imageWidth,imageHeight); - base->drawBoxes(t,&image,TRUE,TRUE,baseRows,superRows,cellWidth,cellHeight,relPath,generateMap); - super->drawBoxes(t,&image,FALSE,TRUE,baseRows,superRows,cellWidth,cellHeight,relPath,generateMap); - base->drawConnectors(t,&image,TRUE,TRUE,baseRows,superRows,cellWidth,cellHeight); - super->drawConnectors(t,&image,FALSE,TRUE,baseRows,superRows,cellWidth,cellHeight); + p->base.drawBoxes(t,&image,TRUE,TRUE,baseRows,superRows,cellWidth,cellHeight,relPath,generateMap); + p->super.drawBoxes(t,&image,FALSE,TRUE,baseRows,superRows,cellWidth,cellHeight,relPath,generateMap); + p->base.drawConnectors(t,&image,TRUE,TRUE,baseRows,superRows,cellWidth,cellHeight); + p->super.drawConnectors(t,&image,FALSE,TRUE,baseRows,superRows,cellWidth,cellHeight); #define IMAGE_EXT ".png" image.save((QCString)path+"/"+fileName+IMAGE_EXT); diff --git a/src/diagram.h b/src/diagram.h index 05af28e..d8e7612 100644 --- a/src/diagram.h +++ b/src/diagram.h @@ -1,13 +1,13 @@ /****************************************************************************** * - * + * * * * Copyright (C) 1997-2015 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. * @@ -19,10 +19,9 @@ #ifndef DIAGRAM_H #define DIAGRAM_H -#include <qglobal.h> +#include <memory> class ClassDef; -class TreeDiagram; class FTextStream; /** Class representing a built-in class diagram. */ @@ -36,8 +35,8 @@ class ClassDiagram void writeImage(FTextStream &t,const char *path,const char *relPath, const char *file,bool generateMap=TRUE) const; private: - TreeDiagram *base; - TreeDiagram *super; + struct Private; + std::unique_ptr<Private> p; }; #endif diff --git a/src/dirdef.cpp b/src/dirdef.cpp index b058f86..14d978e 100644 --- a/src/dirdef.cpp +++ b/src/dirdef.cpp @@ -19,7 +19,7 @@ //---------------------------------------------------------------------- -class DirDefImpl : public DefinitionImpl, public DirDef +class DirDefImpl : public DefinitionMixin<DirDef> { public: DirDefImpl(const char *path); @@ -93,7 +93,7 @@ DirDef *createDirDef(const char *path) static int g_dirCount=0; -DirDefImpl::DirDefImpl(const char *path) : DefinitionImpl(path,1,1,path) +DirDefImpl::DirDefImpl(const char *path) : DefinitionMixin(path,1,1,path) { bool fullPathNames = Config_getBool(FULL_PATH_NAMES); // get display name (stripping the paths mentioned in STRIP_FROM_PATH) @@ -1101,3 +1101,31 @@ bool compareDirDefs(const DirDef *item1, const DirDef *item2) return qstricmp(item1->shortName(),item2->shortName()) < 0; } +// --- Cast functions + +DirDef *toDirDef(Definition *d) +{ + if (d==0) return 0; + if (d && typeid(*d)==typeid(DirDefImpl)) + { + return static_cast<DirDef*>(d); + } + else + { + return 0; + } +} + +const DirDef *toDirDef(const Definition *d) +{ + if (d==0) return 0; + if (d && typeid(*d)==typeid(DirDefImpl)) + { + return static_cast<const DirDef*>(d); + } + else + { + return 0; + } +} + diff --git a/src/dirdef.h b/src/dirdef.h index 468901d..32fa442 100644 --- a/src/dirdef.h +++ b/src/dirdef.h @@ -39,7 +39,7 @@ typedef std::vector<DirDef*> DirList; bool compareDirDefs(const DirDef *item1, const DirDef *item2); /** A model of a directory symbol. */ -class DirDef : virtual public Definition +class DirDef : public DefinitionMutable, public Definition { public: virtual ~DirDef() {} @@ -79,6 +79,14 @@ class DirDef : virtual public Definition virtual void computeDependencies() = 0; }; +// --- Cast functions + +DirDef *toDirDef(Definition *d); +const DirDef *toDirDef(const Definition *d); + +// ------------------ + + /** Class representing a pair of FileDef objects */ class FilePair { diff --git a/src/docbookgen.cpp b/src/docbookgen.cpp index da7987b..385c2ef 100644 --- a/src/docbookgen.cpp +++ b/src/docbookgen.cpp @@ -101,9 +101,21 @@ inline void writeDocbookCodeString(FTextStream &t,const char *s, int &col) case '&': t << "&"; col++; break; case '\'': t << "'"; col++; break; case '"': t << """; col++; break; - case '\007': t << "^G"; col++; break; // bell - case '\014': t << "^L"; col++; break; // form feed - default: t << c; col++; break; + default: + { + uchar uc = static_cast<uchar>(c); + static const char *hex="0123456789ABCDEF"; + if (uc<32) + { + t << "$" << hex[uc>>4] << hex[uc&0xF] << ";"; + } + else + { + t << c; + } + col++; + } + break; } } } @@ -242,18 +254,23 @@ void DocbookCodeGenerator::finish() { endCodeLine(); } -void DocbookCodeGenerator::startCodeFragment() +void DocbookCodeGenerator::startCodeFragment(const char *) { - m_t << "<literallayout><computeroutput>" << endl; +DB_GEN_C + m_t << "<programlisting>"; } -void DocbookCodeGenerator::endCodeFragment() + +void DocbookCodeGenerator::endCodeFragment(const char *) { +DB_GEN_C //endCodeLine checks is there is still an open code line, if so closes it. endCodeLine(); - m_t << "</computeroutput></literallayout>" << endl; + m_t << "</programlisting>"; } +//------------------------------------------------------------------------------- + DocbookGenerator::DocbookGenerator() : OutputGenerator(Config_getString(DOCBOOK_OUTPUT)) { DB_GEN_C @@ -291,7 +308,7 @@ void DocbookGenerator::init() createSubDirs(d); } -void DocbookGenerator::startFile(const char *name,const char *,const char *) +void DocbookGenerator::startFile(const char *name,const char *,const char *,int) { DB_GEN_C QCString fileName=name; @@ -520,7 +537,7 @@ DB_GEN_C2("IndexSections " << is) bool found=FALSE; for (nli.toFirst();(nd=nli.current()) && !found;++nli) { - if (nd->isLinkableInProject()) + if (nd->isLinkableInProject() && !nd->isAlias()) { t << "<xi:include href=\"" << nd->getOutputFileBase() << ".xml\" xmlns:xi=\"http://www.w3.org/2001/XInclude\"/>" << endl; found=TRUE; @@ -528,7 +545,7 @@ DB_GEN_C2("IndexSections " << is) } while ((nd=nli.current())) { - if (nd->isLinkableInProject()) + if (nd->isLinkableInProject() && !nd->isAlias()) { t << "<xi:include href=\"" << nd->getOutputFileBase() << ".xml\" xmlns:xi=\"http://www.w3.org/2001/XInclude\"/>" << endl; } @@ -547,7 +564,8 @@ DB_GEN_C2("IndexSections " << is) { if (cd->isLinkableInProject() && cd->templateMaster()==0 && - !cd->isEmbeddedInOuterScope() + !cd->isEmbeddedInOuterScope() && + !cd->isAlias() ) { t << " <xi:include href=\"" << cd->getOutputFileBase() << ".xml\" xmlns:xi=\"http://www.w3.org/2001/XInclude\"/>" << endl; @@ -558,7 +576,8 @@ DB_GEN_C2("IndexSections " << is) { if (cd->isLinkableInProject() && cd->templateMaster()==0 && - !cd->isEmbeddedInOuterScope() + !cd->isEmbeddedInOuterScope() && + !cd->isAlias() ) { t << " <xi:include href=\"" << cd->getOutputFileBase() << ".xml\" xmlns:xi=\"http://www.w3.org/2001/XInclude\"/>" << endl; @@ -649,7 +668,7 @@ DB_GEN_C } } -void DocbookGenerator::writeDoc(DocNode *n,const Definition *,const MemberDef *) +void DocbookGenerator::writeDoc(DocNode *n,const Definition *,const MemberDef *,int) { DB_GEN_C DocbookDocVisitor *visitor = @@ -732,12 +751,12 @@ void DocbookGenerator::endMemberItem() DB_GEN_C t << "</para>" << endl; } -void DocbookGenerator::startBold(void) +void DocbookGenerator::startBold() { DB_GEN_C t << "<emphasis role=\"strong\">"; } -void DocbookGenerator::endBold(void) +void DocbookGenerator::endBold() { DB_GEN_C t << "</emphasis>"; @@ -755,7 +774,7 @@ DB_GEN_C2("extraIndentLevel " << extraIndentLevel) t << "<section>" << endl; t << "<title>"; } -void DocbookGenerator::writeRuler(void) +void DocbookGenerator::writeRuler() { DB_GEN_C2("m_inLevel " << m_inLevel) DB_GEN_C2("m_inGroup " << m_inGroup) @@ -945,12 +964,12 @@ void DocbookGenerator::endExamples() DB_GEN_C t << "</simplesect>" << endl; } -void DocbookGenerator::startSubsubsection(void) +void DocbookGenerator::startSubsubsection() { DB_GEN_C t << "<simplesect><title>"; } -void DocbookGenerator::endSubsubsection(void) +void DocbookGenerator::endSubsubsection() { DB_GEN_C t << "</title></simplesect>" << endl; @@ -995,19 +1014,6 @@ DB_GEN_C if (closeBracket) t << ")"; } } -void DocbookGenerator::startCodeFragment() -{ -DB_GEN_C - t << "<programlisting>"; -} -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() { DB_GEN_C diff --git a/src/docbookgen.h b/src/docbookgen.h index 0fefe4b..214ec97 100644 --- a/src/docbookgen.h +++ b/src/docbookgen.h @@ -53,8 +53,8 @@ class DocbookCodeGenerator : public CodeOutputInterface void setCurrentDoc(const Definition *,const char *,bool); void addWord(const char *,bool); void finish(); - void startCodeFragment(); - void endCodeFragment(); + void startCodeFragment(const char *style); + void endCodeFragment(const char *style); private: FTextStream m_t; @@ -130,15 +130,19 @@ class DocbookGenerator : public OutputGenerator { m_codeGen.endFontClass(); } void writeCodeAnchor(const char *anchor) { m_codeGen.writeCodeAnchor(anchor); } + void startCodeFragment(const char *style) + { m_codeGen.startCodeFragment(style); } + void endCodeFragment(const char *style) + { m_codeGen.endCodeFragment(style); } // --------------------------- - void writeDoc(DocNode *,const Definition *ctx,const MemberDef *md); + void writeDoc(DocNode *,const Definition *ctx,const MemberDef *md,int id); /////////////////////////////////////////////////////////////// // structural output interface /////////////////////////////////////////////////////////////// void startFile(const char *name,const char *manName, - const char *title); + const char *title,int id); void writeSearchInfo(){DB_GEN_EMPTY}; void writeFooter(const char *){DB_GEN_NEW}; void endFile(); @@ -169,35 +173,33 @@ class DocbookGenerator : public OutputGenerator void writeChar(char); void writeString(const char *); void startParagraph(const char *); - void endParagraph(void); + void endParagraph(); void writeObjectLink(const char *,const char *,const char *,const char *); void startHtmlLink(const char *){DB_GEN_NEW}; - void endHtmlLink(void){DB_GEN_NEW}; - void startBold(void); - void endBold(void); - void startTypewriter(void); - void endTypewriter(void); - void startEmphasis(void){DB_GEN_NEW}; - void endEmphasis(void){DB_GEN_NEW}; - void startCodeFragment(void); - void endCodeFragment(void); - void writeRuler(void); - void startDescription(void){DB_GEN_NEW}; - void endDescription(void){DB_GEN_NEW}; - void startDescItem(void){DB_GEN_NEW}; - void startDescForItem(void){DB_GEN_EMPTY}; - void endDescForItem(void){DB_GEN_EMPTY}; - void endDescItem(void){DB_GEN_NEW}; - void startCenter(void){DB_GEN_NEW}; - void endCenter(void){DB_GEN_NEW}; - void startSmall(void){DB_GEN_NEW}; - void endSmall(void){DB_GEN_NEW}; - void startExamples(void); - void endExamples(void); + void endHtmlLink(){DB_GEN_NEW}; + void startBold(); + void endBold(); + void startTypewriter(); + void endTypewriter(); + void startEmphasis(){DB_GEN_NEW}; + void endEmphasis(){DB_GEN_NEW}; + void writeRuler(); + void startDescription(){DB_GEN_NEW}; + void endDescription(){DB_GEN_NEW}; + void startDescItem(){DB_GEN_NEW}; + void startDescForItem(){DB_GEN_EMPTY}; + void endDescForItem(){DB_GEN_EMPTY}; + void endDescItem(){DB_GEN_NEW}; + void startCenter(){DB_GEN_NEW}; + void endCenter(){DB_GEN_NEW}; + void startSmall(){DB_GEN_NEW}; + void endSmall(){DB_GEN_NEW}; + void startExamples(); + void endExamples(); void startParamList(BaseOutputDocInterface::ParamListTypes,const char *){DB_GEN_NEW}; - void endParamList(void){DB_GEN_NEW}; - void startTitle(void){DB_GEN_NEW}; - void endTitle(void){DB_GEN_NEW}; + void endParamList(){DB_GEN_NEW}; + void startTitle(){DB_GEN_NEW}; + void endTitle(){DB_GEN_NEW}; void writeAnchor(const char *,const char *){DB_GEN_EMPTY}; void startSection(const char *,const char *,SectionType); void endSection(const char *,SectionType); @@ -205,21 +207,21 @@ class DocbookGenerator : public OutputGenerator void addIndexItem(const char *,const char *); void writeNonBreakableSpace(int); void startDescTable(const char *); - void endDescTable(void); - void startDescTableRow(void); - void endDescTableRow(void); - void startDescTableTitle(void); - void endDescTableTitle(void); - void startDescTableData(void); - void endDescTableData(void); + void endDescTable(); + void startDescTableRow(); + void endDescTableRow(); + void startDescTableTitle(); + void endDescTableTitle(); + void startDescTableData(); + void endDescTableData(); void startTextLink(const char *,const char *){DB_GEN_NEW}; - void endTextLink(void){DB_GEN_NEW}; - void startPageRef(void){DB_GEN_NEW}; + void endTextLink(){DB_GEN_NEW}; + void startPageRef(){DB_GEN_NEW}; void endPageRef(const char *,const char *){DB_GEN_NEW}; - void startSubsection(void){DB_GEN_NEW}; - void endSubsection(void){DB_GEN_NEW}; - void startSubsubsection(void); - void endSubsubsection(void); + void startSubsection(){DB_GEN_NEW}; + void endSubsection(){DB_GEN_NEW}; + void startSubsubsection(); + void endSubsubsection(); void startGroupHeader(int); diff --git a/src/docbookvisitor.cpp b/src/docbookvisitor.cpp index 78af6e0..d444b7b 100644 --- a/src/docbookvisitor.cpp +++ b/src/docbookvisitor.cpp @@ -316,9 +316,11 @@ DB_VIS_C { case DocVerbatim::Code: // fall though m_t << "<literallayout><computeroutput>"; - Doxygen::parserManager->getCodeParser(m_langExt) - .parseCode(m_ci,s->context(),s->text(),langExt, - s->isExample(),s->exampleFile()); + getCodeParser(m_langExt).parseCode(m_ci,s->context(), + s->text(), + langExt, + s->isExample(), + s->exampleFile()); m_t << "</computeroutput></literallayout>"; break; case DocVerbatim::Verbatim: @@ -354,12 +356,13 @@ DB_VIS_C QFile file(baseName+".dot"); if (!file.open(IO_WriteOnly)) { - err("Could not open file %s.msc for writing\n",baseName.data()); + err("Could not open file %s.dot for writing\n",baseName.data()); } file.writeBlock( stext, stext.length() ); file.close(); writeDotFile(baseName, s); m_t << "</para>" << endl; + if (Config_getBool(DOT_CLEANUP)) file.remove(); } break; case DocVerbatim::Msc: @@ -386,6 +389,7 @@ DB_VIS_C file.close(); writeMscFile(baseName,s); m_t << "</para>" << endl; + if (Config_getBool(DOT_CLEANUP)) file.remove(); } break; case DocVerbatim::PlantUML: @@ -425,24 +429,22 @@ DB_VIS_C m_t << "<literallayout><computeroutput>"; QFileInfo cfi( inc->file() ); FileDef *fd = createFileDef( cfi.dirPath().utf8(), cfi.fileName().utf8() ); - Doxygen::parserManager->getCodeParser(inc->extension()) - .parseCode(m_ci,inc->context(), - inc->text(), - langExt, - inc->isExample(), - inc->exampleFile(), fd); + getCodeParser(inc->extension()).parseCode(m_ci,inc->context(), + inc->text(), + langExt, + inc->isExample(), + inc->exampleFile(), fd); delete fd; m_t << "</computeroutput></literallayout>"; } break; case DocInclude::Include: m_t << "<literallayout><computeroutput>"; - Doxygen::parserManager->getCodeParser(inc->extension()) - .parseCode(m_ci,inc->context(), - inc->text(), - langExt, - inc->isExample(), - inc->exampleFile()); + getCodeParser(inc->extension()).parseCode(m_ci,inc->context(), + inc->text(), + langExt, + inc->isExample(), + inc->exampleFile()); m_t << "</computeroutput></literallayout>"; break; case DocInclude::DontInclude: @@ -463,14 +465,13 @@ DB_VIS_C break; case DocInclude::Snippet: m_t << "<literallayout><computeroutput>"; - Doxygen::parserManager->getCodeParser(inc->extension()) - .parseCode(m_ci, - inc->context(), - extractBlock(inc->text(),inc->blockId()), - langExt, - inc->isExample(), - inc->exampleFile() - ); + getCodeParser(inc->extension()).parseCode(m_ci, + inc->context(), + extractBlock(inc->text(),inc->blockId()), + langExt, + inc->isExample(), + inc->exampleFile() + ); m_t << "</computeroutput></literallayout>"; break; case DocInclude::SnipWithLines: @@ -478,8 +479,7 @@ DB_VIS_C QFileInfo cfi( inc->file() ); FileDef *fd = createFileDef( cfi.dirPath().utf8(), cfi.fileName().utf8() ); m_t << "<literallayout><computeroutput>"; - Doxygen::parserManager->getCodeParser(inc->extension()) - .parseCode(m_ci, + getCodeParser(inc->extension()).parseCode(m_ci, inc->context(), extractBlock(inc->text(),inc->blockId()), langExt, @@ -531,17 +531,16 @@ DB_VIS_C fd = createFileDef( cfi.dirPath().utf8(), cfi.fileName().utf8() ); } - Doxygen::parserManager->getCodeParser(locLangExt) - .parseCode(m_ci,op->context(), - op->text(),langExt,op->isExample(), - op->exampleFile(), - fd, // fileDef - op->line(), // startLine - -1, // endLine - FALSE, // inline fragment - 0, // memberDef - op->showLineNo() // show line numbers - ); + getCodeParser(locLangExt).parseCode(m_ci,op->context(), + op->text(),langExt,op->isExample(), + op->exampleFile(), + fd, // fileDef + op->line(), // startLine + -1, // endLine + FALSE, // inline fragment + 0, // memberDef + op->showLineNo() // show line numbers + ); if (fd) delete fd; } pushEnabled(); diff --git a/src/docparser.cpp b/src/docparser.cpp index 73131f6..8621cc7 100644 --- a/src/docparser.cpp +++ b/src/docparser.cpp @@ -176,7 +176,7 @@ static void docParserPushContext(bool saveParamInfo=TRUE) ctx->initialStyleStack = g_initialStyleStack; ctx->copyStack = g_copyStack; ctx->fileName = g_fileName; - ctx->lineNo = doctokenizerYYlineno; + ctx->lineNo = getDoctokinizerLineNr(); ctx->relPath = g_relPath; if (saveParamInfo) @@ -217,7 +217,7 @@ static void docParserPopContext(bool keepParamInfo=FALSE) g_initialStyleStack = ctx->initialStyleStack; g_copyStack = ctx->copyStack; g_fileName = ctx->fileName; - doctokenizerYYlineno = ctx->lineNo; + setDoctokinizerLineNr(ctx->lineNo); g_relPath = ctx->relPath; if (!keepParamInfo) @@ -292,7 +292,7 @@ static QCString findAndCopyImage(const char *fileName,DocImage::Type type, bool text.sprintf("image file name %s is ambiguous.\n",qPrint(fileName)); text+="Possible candidates:\n"; text+=showFileDefMatches(Doxygen::imageNameLinkedMap,fileName); - warn_doc_error(g_fileName,doctokenizerYYlineno,"%s", text.data()); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"%s", text.data()); } QCString inputFile = fd->absFilePath(); @@ -331,7 +331,7 @@ static QCString findAndCopyImage(const char *fileName,DocImage::Type type, bool if (outfi.isSymLink()) { QFile::remove(outputFile); - warn_doc_error(g_fileName,doctokenizerYYlineno, + warn_doc_error(g_fileName,getDoctokinizerLineNr(), "destination of image %s is a symlink, replacing with image", qPrint(outputFile)); } @@ -349,19 +349,19 @@ static QCString findAndCopyImage(const char *fileName,DocImage::Type type, bool } else { - warn_doc_error(g_fileName,doctokenizerYYlineno, + warn_doc_error(g_fileName,getDoctokinizerLineNr(), "could not write output image %s",qPrint(outputFile)); } } //else //{ - // warn(g_fileName,doctokenizerYYlineno, + // warn(g_fileName,getDoctokinizerLineNr(), // "Prevented to copy file %s onto itself!\n",qPrint(inputFile)); //} } else { - warn_doc_error(g_fileName,doctokenizerYYlineno, + warn_doc_error(g_fileName,getDoctokinizerLineNr(), "could not open image %s",qPrint(fileName)); } @@ -389,7 +389,7 @@ static QCString findAndCopyImage(const char *fileName,DocImage::Type type, bool result=fileName; if (result.left(5)!="http:" && result.left(6)!="https:" && dowarn) { - warn_doc_error(g_fileName,doctokenizerYYlineno, + warn_doc_error(g_fileName,getDoctokinizerLineNr(), "image file %s is not found in IMAGE_PATH: " "assuming external image.",qPrint(fileName) ); @@ -812,16 +812,16 @@ inline void errorHandleDefaultToken(DocNode *parent,int tok, cmd_start = "@"; case TK_COMMAND_BS: children.append(new DocWord(parent,TK_COMMAND_CHAR(tok) + g_token->name)); - warn_doc_error(g_fileName,doctokenizerYYlineno,"Illegal command %s as part of a %s", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Illegal command %s as part of a %s", qPrint(cmd_start + g_token->name),txt); break; case TK_SYMBOL: - warn_doc_error(g_fileName,doctokenizerYYlineno,"Unsupported symbol %s found found as part of a %s", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Unsupported symbol %s found found as part of a %s", qPrint(g_token->name), txt); break; default: children.append(new DocWord(parent,g_token->name)); - warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected token %s found as part of a %s", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Unexpected token %s found as part of a %s", tokToString(tok), txt); break; } @@ -841,7 +841,7 @@ 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", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"expected whitespace after \\%s command", qPrint(saveCmdName)); return tok; } @@ -910,22 +910,22 @@ static void handleStyleLeave(DocNode *parent,QList<DocNode> &children, { if (g_styleStack.isEmpty()) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"found </%s> tag without matching <%s>", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"found </%s> tag without matching <%s>", qPrint(tagName),qPrint(tagName)); } else if (g_styleStack.top()->tagName()!=tagNameLower) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"found </%s> tag while expecting </%s>", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"found </%s> tag while expecting </%s>", qPrint(tagName),qPrint(g_styleStack.top()->tagName())); } else if (g_styleStack.top()->style()!=s) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"found </%s> tag while expecting </%s>", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"found </%s> tag while expecting </%s>", qPrint(tagName),qPrint(g_styleStack.top()->tagName())); } else { - warn_doc_error(g_fileName,doctokenizerYYlineno,"found </%s> at different nesting level (%d) than expected (%d)", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"found </%s> at different nesting level (%d) than expected (%d)", qPrint(tagName),g_nodeStack.count(),g_styleStack.top()->position()); } } @@ -988,7 +988,7 @@ static int handleAHref(DocNode *parent,QList<DocNode> &children,const HtmlAttrib } else { - warn_doc_error(g_fileName,doctokenizerYYlineno,"found <a> tag with name option but without value!"); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"found <a> tag with name option but without value!"); } } else if (opt->name=="href") // <a href=url>..</a> tag @@ -1042,7 +1042,7 @@ static void handleUnclosedStyleCommands() DocStyleChange *sc = g_initialStyleStack.top(); g_initialStyleStack.pop(); handleUnclosedStyleCommands(); - warn_doc_error(g_fileName,doctokenizerYYlineno, + warn_doc_error(g_fileName,getDoctokinizerLineNr(), "end of comment block while expecting " "command </%s>",qPrint(sc->tagName())); } @@ -1100,7 +1100,7 @@ static void handleLinkedWord(DocNode *parent,QList<DocNode> &children,bool ignor } else if (compound->definitionType()==Definition::TypeGroup) { - name=(dynamic_cast<const GroupDef*>(compound))->groupTitle(); + name=(toGroupDef(compound))->groupTitle(); } children.append(new DocLinkedWord(parent,name, @@ -1112,7 +1112,7 @@ static void handleLinkedWord(DocNode *parent,QList<DocNode> &children,bool ignor ); } else if (compound->definitionType()==Definition::TypeFile && - (dynamic_cast<const FileDef*>(compound))->generateSourceFile() + (toFileDef(compound))->generateSourceFile() ) // undocumented file that has source code we can link to { children.append(new @@ -1165,7 +1165,7 @@ static void handleLinkedWord(DocNode *parent,QList<DocNode> &children,bool ignor { if (g_token->name.left(1)=="#" || g_token->name.left(2)=="::") { - warn_doc_error(g_fileName,doctokenizerYYlineno,"explicit link request to '%s' could not be resolved",qPrint(name)); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"explicit link request to '%s' could not be resolved",qPrint(name)); children.append(new DocWord(parent,g_token->name)); } else @@ -1205,7 +1205,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,getDoctokinizerLineNr(),"expected whitespace after \\%s command", qPrint(tokenName)); return 0; } @@ -1213,7 +1213,7 @@ static DocInternalRef *handleInternalRef(DocNode *parent) tok=doctokenizerYYlex(); // get the reference id if (tok!=TK_WORD && tok!=TK_LNKWORD) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected token %s as the argument of %s", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"unexpected token %s as the argument of %s", tokToString(tok),qPrint(tokenName)); return 0; } @@ -1225,7 +1225,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,getDoctokinizerLineNr(),"expected whitespace after \\%s command", qPrint(g_token->name)); return 0; } @@ -1233,13 +1233,13 @@ static DocAnchor *handleAnchor(DocNode *parent) tok=doctokenizerYYlex(); if (tok==0) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected end of comment block while parsing the " + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"unexpected end of comment block while parsing the " "argument of command %s",qPrint(g_token->name)); return 0; } else if (tok!=TK_WORD && tok!=TK_LNKWORD) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected token %s as the argument of %s", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"unexpected token %s as the argument of %s", tokToString(tok),qPrint(g_token->name)); return 0; } @@ -1301,7 +1301,7 @@ static void defaultHandleTitleAndSize(const int cmd, DocNode *parent, QList<DocN } else { - warn_doc_error(g_fileName,doctokenizerYYlineno,"Unknown option '%s' after \\%s command, expected 'width' or 'height'", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Unknown option '%s' after \\%s command, expected 'width' or 'height'", qPrint(g_token->name), Mappers::cmdMapper->find(cmd).data()); break; } @@ -1330,7 +1330,7 @@ static void defaultHandleTitleAndSize(const int cmd, DocNode *parent, QList<DocN static bool defaultHandleToken(DocNode *parent,int tok, QList<DocNode> &children,bool handleWord) { - DBG(("token %s at %d",tokToString(tok),doctokenizerYYlineno)); + DBG(("token %s at %d",tokToString(tok),getDoctokinizerLineNr())); if (tok==TK_WORD || tok==TK_LNKWORD || tok==TK_SYMBOL || tok==TK_URL || tok==TK_COMMAND_AT || tok==TK_COMMAND_BS || tok==TK_HTMLTAG ) @@ -1445,7 +1445,7 @@ reparsetoken: doctokenizerYYsetStateHtmlOnly(); tok = doctokenizerYYlex(); children.append(new DocVerbatim(parent,g_context,g_token->verb,DocVerbatim::HtmlOnly,g_isExample,g_exampleName,g_token->name=="block")); - if (tok==0) warn_doc_error(g_fileName,doctokenizerYYlineno,"htmlonly section ended without end marker"); + if (tok==0) warn_doc_error(g_fileName,getDoctokinizerLineNr(),"htmlonly section ended without end marker"); doctokenizerYYsetStatePara(); } break; @@ -1454,7 +1454,7 @@ reparsetoken: doctokenizerYYsetStateManOnly(); tok = doctokenizerYYlex(); children.append(new DocVerbatim(parent,g_context,g_token->verb,DocVerbatim::ManOnly,g_isExample,g_exampleName)); - if (tok==0) warn_doc_error(g_fileName,doctokenizerYYlineno,"manonly section ended without end marker"); + if (tok==0) warn_doc_error(g_fileName,getDoctokinizerLineNr(),"manonly section ended without end marker"); doctokenizerYYsetStatePara(); } break; @@ -1463,7 +1463,7 @@ reparsetoken: doctokenizerYYsetStateRtfOnly(); tok = doctokenizerYYlex(); children.append(new DocVerbatim(parent,g_context,g_token->verb,DocVerbatim::RtfOnly,g_isExample,g_exampleName)); - if (tok==0) warn_doc_error(g_fileName,doctokenizerYYlineno,"rtfonly section ended without end marker"); + if (tok==0) warn_doc_error(g_fileName,getDoctokinizerLineNr(),"rtfonly section ended without end marker"); doctokenizerYYsetStatePara(); } break; @@ -1472,7 +1472,7 @@ reparsetoken: doctokenizerYYsetStateLatexOnly(); tok = doctokenizerYYlex(); children.append(new DocVerbatim(parent,g_context,g_token->verb,DocVerbatim::LatexOnly,g_isExample,g_exampleName)); - if (tok==0) warn_doc_error(g_fileName,doctokenizerYYlineno,"latexonly section ended without end marker"); + if (tok==0) warn_doc_error(g_fileName,getDoctokinizerLineNr(),"latexonly section ended without end marker"); doctokenizerYYsetStatePara(); } break; @@ -1481,7 +1481,7 @@ reparsetoken: doctokenizerYYsetStateXmlOnly(); tok = doctokenizerYYlex(); children.append(new DocVerbatim(parent,g_context,g_token->verb,DocVerbatim::XmlOnly,g_isExample,g_exampleName)); - if (tok==0) warn_doc_error(g_fileName,doctokenizerYYlineno,"xmlonly section ended without end marker"); + if (tok==0) warn_doc_error(g_fileName,getDoctokinizerLineNr(),"xmlonly section ended without end marker"); doctokenizerYYsetStatePara(); } break; @@ -1490,7 +1490,7 @@ reparsetoken: doctokenizerYYsetStateDbOnly(); tok = doctokenizerYYlex(); children.append(new DocVerbatim(parent,g_context,g_token->verb,DocVerbatim::DocbookOnly,g_isExample,g_exampleName)); - if (tok==0) warn_doc_error(g_fileName,doctokenizerYYlineno,"docbookonly section ended without end marker"); + if (tok==0) warn_doc_error(g_fileName,getDoctokinizerLineNr(),"docbookonly section ended without end marker"); doctokenizerYYsetStatePara(); } break; @@ -1543,10 +1543,10 @@ reparsetoken: switch (Mappers::htmlTagMapper->map(tokenName)) { case HTML_DIV: - warn_doc_error(g_fileName,doctokenizerYYlineno,"found <div> tag in heading\n"); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"found <div> tag in heading\n"); break; case HTML_PRE: - warn_doc_error(g_fileName,doctokenizerYYlineno,"found <pre> tag in heading\n"); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"found <pre> tag in heading\n"); break; case HTML_BOLD: if (!g_token->endTag) @@ -1758,7 +1758,7 @@ static void handleImg(DocNode *parent,QList<DocNode> &children,const HtmlAttribL } if (!found) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"IMG tag does not have a SRC attribute!\n"); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"IMG tag does not have a SRC attribute!\n"); } } @@ -1787,7 +1787,7 @@ DocEmoji::DocEmoji(DocNode *parent,const QCString &symName) : m_index = EmojiEntityMapper::instance()->symbol2index(m_symName); if (m_index==-1) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"Found unsupported emoji symbol '%s'\n",qPrint(m_symName)); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Found unsupported emoji symbol '%s'\n",qPrint(m_symName)); } } @@ -1867,7 +1867,7 @@ static void readTextFileByName(const QCString &file,QCString &text) text = fileToString(fd->absFilePath(),Config_getBool(FILTER_SOURCE_FILES)); if (ambig) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"included file name %s is ambiguous" + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"included file name %s is ambiguous" "Possible candidates:\n%s",qPrint(file), qPrint(showFileDefMatches(Doxygen::exampleNameLinkedMap,file)) ); @@ -1875,7 +1875,7 @@ static void readTextFileByName(const QCString &file,QCString &text) } else { - warn_doc_error(g_fileName,doctokenizerYYlineno,"included file %s is not found. " + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"included file %s is not found. " "Check your EXAMPLE_PATH",qPrint(file)); } } @@ -1918,7 +1918,7 @@ DocAnchor::DocAnchor(DocNode *parent,const QCString &id,bool newAnchor) m_parent = parent; if (id.isEmpty()) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"Empty anchor label"); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Empty anchor label"); return; } @@ -1934,7 +1934,7 @@ DocAnchor::DocAnchor(DocNode *parent,const QCString &id,bool newAnchor) } else { - warn_doc_error(g_fileName,doctokenizerYYlineno,"Invalid cite anchor id '%s'",qPrint(id)); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Invalid cite anchor id '%s'",qPrint(id)); m_anchor = "invalid"; m_file = "invalid"; } @@ -1954,7 +1954,7 @@ DocAnchor::DocAnchor(DocNode *parent,const QCString &id,bool newAnchor) } else { - warn_doc_error(g_fileName,doctokenizerYYlineno,"Invalid anchor id '%s'",qPrint(id)); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Invalid anchor id '%s'",qPrint(id)); m_anchor = "invalid"; m_file = "invalid"; } @@ -2015,7 +2015,7 @@ void DocInclude::parse() int count; if (!m_blockId.isEmpty() && (count=m_text.contains(m_blockId.data()))!=2) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"block marked with %s for \\snippet should appear twice in file %s, found it %d times\n", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"block marked with %s for \\snippet should appear twice in file %s, found it %d times\n", m_blockId.data(),m_file.data(),count); } break; @@ -2033,7 +2033,7 @@ void DocIncOperator::parse() { if (g_includeFileName.isEmpty()) { - warn_doc_error(g_fileName,doctokenizerYYlineno, + warn_doc_error(g_fileName,getDoctokinizerLineNr(), "No previous '\\include' or '\\dontinclude' command for '\\%s' present", typeAsString()); } @@ -2225,7 +2225,7 @@ DocFormula::DocFormula(DocNode *parent,int id) : } else // wrong \_form#<n> command { - warn_doc_error(g_fileName,doctokenizerYYlineno,"Wrong formula id %d",id); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Wrong formula id %d",id); m_id = -1; } } @@ -2287,13 +2287,13 @@ void DocSecRefItem::parse() } else { - warn_doc_error(g_fileName,doctokenizerYYlineno,"reference to unknown section %s", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"reference to unknown section %s", qPrint(m_target)); } } else { - warn_doc_error(g_fileName,doctokenizerYYlineno,"reference to empty target"); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"reference to empty target"); } DBG(("DocSecRefItem::parse() end\n")); @@ -2324,13 +2324,13 @@ void DocSecRefList::parse() tok=doctokenizerYYlex(); if (tok!=TK_WHITESPACE) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after \\refitem command"); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"expected whitespace after \\refitem command"); break; } tok=doctokenizerYYlex(); if (tok!=TK_WORD && tok!=TK_LNKWORD) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected token %s as the argument of \\refitem", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"unexpected token %s as the argument of \\refitem", tokToString(tok)); break; } @@ -2343,7 +2343,7 @@ void DocSecRefList::parse() case CMD_ENDSECREFLIST: goto endsecreflist; default: - warn_doc_error(g_fileName,doctokenizerYYlineno,"Illegal command %s as part of a \\secreflist", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Illegal command %s as part of a \\secreflist", qPrint(cmd_start + g_token->name)); goto endsecreflist; } @@ -2354,7 +2354,7 @@ void DocSecRefList::parse() } else { - warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected token %s inside section reference list", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Unexpected token %s inside section reference list", tokToString(tok)); goto endsecreflist; } @@ -2448,8 +2448,8 @@ DocRef::DocRef(DocNode *parent,const QCString &target,const QCString &context) : } m_isSubPage = pd && pd->hasParentPage(); if (sec->type()!=SectionType::Page || m_isSubPage) m_anchor = sec->label(); - //printf("m_text=%s,m_ref=%s,m_file=%s,m_refToAnchor=%d type=%d\n", - // m_text.data(),m_ref.data(),m_file.data(),m_refToAnchor,sec->type); + //printf("m_text=%s,m_ref=%s,m_file=%s,type=%d\n", + // m_text.data(),m_ref.data(),m_file.data(),m_refType); return; } else if (resolveLink(context,target,TRUE,&compound,anchor)) @@ -2464,16 +2464,16 @@ DocRef::DocRef(DocNode *parent,const QCString &target,const QCString &context) : { if (anchor.isEmpty() && /* compound link */ compound->definitionType()==Definition::TypeGroup && /* is group */ - (dynamic_cast<const GroupDef *>(compound))->groupTitle() /* with title */ + (toGroupDef(compound))->groupTitle() /* with title */ ) { - m_text=(dynamic_cast<const GroupDef *>(compound))->groupTitle(); // use group's title as link + m_text=(toGroupDef(compound))->groupTitle(); // use group's title as link } else if (compound->definitionType()==Definition::TypeMember && - (dynamic_cast<const MemberDef*>(compound))->isObjCMethod()) + (toMemberDef(compound))->isObjCMethod()) { // Objective C Method - const MemberDef *member = dynamic_cast<const MemberDef*>(compound); + const MemberDef *member = toMemberDef(compound); bool localLink = g_memberDef ? member->getClassDef()==g_memberDef->getClassDef() : FALSE; m_text = member->objCMethodName(localLink,g_inSeeBlock); } @@ -2485,7 +2485,7 @@ DocRef::DocRef(DocNode *parent,const QCString &target,const QCString &context) : return; } else if (compound && compound->definitionType()==Definition::TypeFile && - (dynamic_cast<const FileDef*>(compound))->generateSourceFile() + (toFileDef(compound))->generateSourceFile() ) // undocumented file that has source code we can link to { m_file = compound->getSourceFileBase(); @@ -2494,7 +2494,7 @@ DocRef::DocRef(DocNode *parent,const QCString &target,const QCString &context) : } } m_text = target; - warn_doc_error(g_fileName,doctokenizerYYlineno,"unable to resolve reference to '%s' for \\ref command", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"unable to resolve reference to '%s' for \\ref command", qPrint(target)); } @@ -2589,16 +2589,16 @@ DocCite::DocCite(DocNode *parent,const QCString &target,const QCString &) //cont m_text = target; if (numBibFiles==0) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"\\cite command found but no bib files specified via CITE_BIB_FILES!"); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"\\cite command found but no bib files specified via CITE_BIB_FILES!"); } else if (cite==0) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"unable to resolve reference to '%s' for \\cite command", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"unable to resolve reference to '%s' for \\cite command", qPrint(target)); } else { - warn_doc_error(g_fileName,doctokenizerYYlineno,"\\cite command to '%s' does not have an associated number", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"\\cite command to '%s' does not have an associated number", qPrint(target)); } } @@ -2626,7 +2626,7 @@ DocLink::DocLink(DocNode *parent,const QCString &target) m_ref = compound->getReference(); } else if (compound && compound->definitionType()==Definition::TypeFile && - (dynamic_cast<const FileDef*>(compound))->generateSourceFile() + (toFileDef(compound))->generateSourceFile() ) // undocumented file that has source code we can link to { m_file = compound->getSourceFileBase(); @@ -2636,7 +2636,7 @@ DocLink::DocLink(DocNode *parent,const QCString &target) } // bogus link target - warn_doc_error(g_fileName,doctokenizerYYlineno,"unable to resolve link to '%s' for \\link command", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"unable to resolve link to '%s' for \\link command", qPrint(target)); } @@ -2664,23 +2664,23 @@ QCString DocLink::parse(bool isJavaLink,bool isXmlLink) case CMD_ENDLINK: if (isJavaLink) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"{@link.. ended with @endlink command"); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"{@link.. ended with @endlink command"); } goto endlink; default: - warn_doc_error(g_fileName,doctokenizerYYlineno,"Illegal command %s as part of a \\link", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Illegal command %s as part of a \\link", qPrint(cmd_start + g_token->name)); break; } break; case TK_SYMBOL: - warn_doc_error(g_fileName,doctokenizerYYlineno,"Unsupported symbol %s found as part of a \\link", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Unsupported symbol %s found as part of a \\link", qPrint(g_token->name)); break; case TK_HTMLTAG: if (g_token->name!="see" || !isXmlLink) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected xml/html command %s found as part of a \\link", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Unexpected xml/html command %s found as part of a \\link", qPrint(g_token->name)); } goto endlink; @@ -2708,7 +2708,7 @@ QCString DocLink::parse(bool isJavaLink,bool isXmlLink) m_children.append(new DocWord(this,g_token->name)); break; default: - warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected token %s", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Unexpected token %s", tokToString(tok)); break; } @@ -2716,7 +2716,7 @@ QCString DocLink::parse(bool isJavaLink,bool isXmlLink) } if (tok==0) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected end of comment while inside" + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Unexpected end of comment while inside" " link command\n"); } endlink: @@ -2759,7 +2759,7 @@ bool DocDotFile::parse() ok = true; if (ambig) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"included dot file name %s is ambiguous.\n" + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"included dot file name %s is ambiguous.\n" "Possible candidates:\n%s",qPrint(m_name), qPrint(showFileDefMatches(Doxygen::dotFileNameLinkedMap,m_name)) ); @@ -2767,7 +2767,7 @@ bool DocDotFile::parse() } else { - warn_doc_error(g_fileName,doctokenizerYYlineno,"included dot file %s is not found " + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"included dot file %s is not found " "in any of the paths specified via DOTFILE_DIRS!",qPrint(m_name)); } return ok; @@ -2796,7 +2796,7 @@ bool DocMscFile::parse() ok = true; if (ambig) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"included msc file name %s is ambiguous.\n" + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"included msc file name %s is ambiguous.\n" "Possible candidates:\n%s",qPrint(m_name), qPrint(showFileDefMatches(Doxygen::mscFileNameLinkedMap,m_name)) ); @@ -2804,7 +2804,7 @@ bool DocMscFile::parse() } else { - warn_doc_error(g_fileName,doctokenizerYYlineno,"included msc file %s is not found " + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"included msc file %s is not found " "in any of the paths specified via MSCFILE_DIRS!",qPrint(m_name)); } return ok; @@ -2835,7 +2835,7 @@ bool DocDiaFile::parse() ok = true; if (ambig) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"included dia file name %s is ambiguous.\n" + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"included dia file name %s is ambiguous.\n" "Possible candidates:\n%s",qPrint(m_name), qPrint(showFileDefMatches(Doxygen::diaFileNameLinkedMap,m_name)) ); @@ -2843,7 +2843,7 @@ bool DocDiaFile::parse() } else { - warn_doc_error(g_fileName,doctokenizerYYlineno,"included dia file %s is not found " + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"included dia file %s is not found " "in any of the paths specified via DIAFILE_DIRS!",qPrint(m_name)); } return ok; @@ -2930,7 +2930,7 @@ int DocHtmlHeader::parse() { if (m_level!=1) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"<h%d> ended with </h1>", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"<h%d> ended with </h1>", m_level); } goto endheader; @@ -2939,7 +2939,7 @@ int DocHtmlHeader::parse() { if (m_level!=2) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"<h%d> ended with </h2>", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"<h%d> ended with </h2>", m_level); } goto endheader; @@ -2948,7 +2948,7 @@ int DocHtmlHeader::parse() { if (m_level!=3) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"<h%d> ended with </h3>", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"<h%d> ended with </h3>", m_level); } goto endheader; @@ -2957,7 +2957,7 @@ int DocHtmlHeader::parse() { if (m_level!=4) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"<h%d> ended with </h4>", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"<h%d> ended with </h4>", m_level); } goto endheader; @@ -2966,7 +2966,7 @@ int DocHtmlHeader::parse() { if (m_level!=5) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"<h%d> ended with </h5>", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"<h%d> ended with </h5>", m_level); } goto endheader; @@ -2975,7 +2975,7 @@ int DocHtmlHeader::parse() { if (m_level!=6) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"<h%d> ended with </h6>", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"<h%d> ended with </h6>", m_level); } goto endheader; @@ -2994,7 +2994,7 @@ int DocHtmlHeader::parse() } else { - warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected html tag <%s%s> found within <h%d> context", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Unexpected html tag <%s%s> found within <h%d> context", g_token->endTag?"/":"",qPrint(g_token->name),m_level); } } @@ -3008,7 +3008,7 @@ int DocHtmlHeader::parse() } if (tok==0) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected end of comment while inside" + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Unexpected end of comment while inside" " <h%d> tag\n",m_level); } endheader: @@ -3043,7 +3043,7 @@ int DocHRef::parse() } else { - warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected html tag <%s%s> found within <a href=...> context", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Unexpected html tag <%s%s> found within <a href=...> context", g_token->endTag?"/":"",qPrint(g_token->name)); } } @@ -3056,7 +3056,7 @@ int DocHRef::parse() } if (tok==0) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected end of comment while inside" + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Unexpected end of comment while inside" " <a href=...> tag"); } endhref: @@ -3094,7 +3094,7 @@ int DocInternal::parse(int level) } if (retval==TK_LISTITEM) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"Invalid list item found"); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Invalid list item found"); } } while (retval!=0 && retval!=RetVal_Section && @@ -3120,7 +3120,7 @@ int DocInternal::parse(int level) if (retval==RetVal_Internal) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"\\internal command found inside internal section"); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"\\internal command found inside internal section"); } DBG(("DocInternal::parse() end: retval=%x\n",retval)); @@ -3139,7 +3139,7 @@ int DocIndexEntry::parse() int tok=doctokenizerYYlex(); if (tok!=TK_WHITESPACE) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after \\addindex command"); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"expected whitespace after \\addindex command"); goto endindexentry; } doctokenizerYYsetStateTitle(); @@ -3177,7 +3177,7 @@ int DocIndexEntry::parse() case DocSymbol::Sym_ndash: m_entry+="--"; break; case DocSymbol::Sym_mdash: m_entry+="---"; break; default: - warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected symbol found as argument of \\addindex"); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Unexpected symbol found as argument of \\addindex"); break; } } @@ -3204,13 +3204,13 @@ int DocIndexEntry::parse() case CMD_MINUS: m_entry+='-'; break; case CMD_EQUAL: m_entry+='='; break; default: - warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected command %s found as argument of \\addindex", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Unexpected command %s found as argument of \\addindex", qPrint(g_token->name)); break; } break; default: - warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected token %s", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Unexpected token %s", tokToString(tok)); break; } @@ -3245,7 +3245,7 @@ DocHtmlCaption::DocHtmlCaption(DocNode *parent,const HtmlAttribList &attribs) } else { - warn_doc_error(g_fileName,doctokenizerYYlineno,"Invalid caption id '%s'",qPrint(opt->value)); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Invalid caption id '%s'",qPrint(opt->value)); } } else // copy attribute @@ -3278,7 +3278,7 @@ int DocHtmlCaption::parse() } else { - warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected html tag <%s%s> found within <caption> context", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Unexpected html tag <%s%s> found within <caption> context", g_token->endTag?"/":"",qPrint(g_token->name)); } } @@ -3291,7 +3291,7 @@ int DocHtmlCaption::parse() } if (tok==0) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected end of comment while inside" + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Unexpected end of comment while inside" " <caption> tag"); } endcaption: @@ -3478,7 +3478,7 @@ int DocHtmlRow::parse() } else // found some other tag { - warn_doc_error(g_fileName,doctokenizerYYlineno,"expected <td> or <th> tag but " + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"expected <td> or <th> tag but " "found <%s> instead!",qPrint(g_token->name)); doctokenizerYYpushBackHtmlTag(g_token->name); goto endrow; @@ -3486,13 +3486,13 @@ int DocHtmlRow::parse() } else if (tok==0) // premature end of comment { - warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected end of comment while looking" + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"unexpected end of comment while looking" " for a html description title"); goto endrow; } else // token other than html token { - warn_doc_error(g_fileName,doctokenizerYYlineno,"expected <td> or <th> tag but found %s token instead!", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"expected <td> or <th> tag but found %s token instead!", tokToString(tok)); goto endrow; } @@ -3542,7 +3542,7 @@ int DocHtmlRow::parseXml(bool isHeading) } else // found some other tag { - warn_doc_error(g_fileName,doctokenizerYYlineno,"expected <term> or <description> tag but " + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"expected <term> or <description> tag but " "found <%s> instead!",qPrint(g_token->name)); doctokenizerYYpushBackHtmlTag(g_token->name); goto endrow; @@ -3550,13 +3550,13 @@ int DocHtmlRow::parseXml(bool isHeading) } else if (tok==0) // premature end of comment { - warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected end of comment while looking" + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"unexpected end of comment while looking" " for a html description title"); goto endrow; } else // token other than html token { - warn_doc_error(g_fileName,doctokenizerYYlineno,"expected <td> or <th> tag but found %s token instead!", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"expected <td> or <th> tag but found %s token instead!", tokToString(tok)); goto endrow; } @@ -3605,7 +3605,7 @@ getrow: { if (m_caption) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"table already has a caption, found another one"); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"table already has a caption, found another one"); } else { @@ -3620,18 +3620,18 @@ getrow: } else // found wrong token { - warn_doc_error(g_fileName,doctokenizerYYlineno,"expected <tr> or <caption> tag but " + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"expected <tr> or <caption> tag but " "found <%s%s> instead!", g_token->endTag ? "/" : "", qPrint(g_token->name)); } } else if (tok==0) // premature end of comment { - warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected end of comment while looking" + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"unexpected end of comment while looking" " for a <tr> or <caption> tag"); } else // token other than html token { - warn_doc_error(g_fileName,doctokenizerYYlineno,"expected <tr> tag but found %s token instead!", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"expected <tr> tag but found %s token instead!", tokToString(tok)); } @@ -3813,7 +3813,7 @@ int DocHtmlDescTitle::parse() tok=doctokenizerYYlex(); if (tok!=TK_WHITESPACE) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after \\%s command", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"expected whitespace after \\%s command", qPrint(g_token->name)); } else @@ -3822,7 +3822,7 @@ int DocHtmlDescTitle::parse() tok=doctokenizerYYlex(); // get the reference id if (tok!=TK_WORD) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected token %s as the argument of \\%s command", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"unexpected token %s as the argument of \\%s command", tokToString(tok),qPrint(cmdName)); } else @@ -3843,7 +3843,7 @@ int DocHtmlDescTitle::parse() tok=doctokenizerYYlex(); if (tok!=TK_WHITESPACE) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after \\%s command", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"expected whitespace after \\%s command", qPrint(cmdName)); } else @@ -3852,7 +3852,7 @@ int DocHtmlDescTitle::parse() tok=doctokenizerYYlex(); if (tok!=TK_WORD) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected token %s as the argument of \\%s command", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"unexpected token %s as the argument of \\%s command", tokToString(tok),qPrint(cmdName)); } else @@ -3871,13 +3871,13 @@ int DocHtmlDescTitle::parse() break; default: - warn_doc_error(g_fileName,doctokenizerYYlineno,"Illegal command %s found as part of a <dt> tag", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Illegal command %s found as part of a <dt> tag", qPrint(cmd_start + g_token->name)); } } break; case TK_SYMBOL: - warn_doc_error(g_fileName,doctokenizerYYlineno,"Unsupported symbol \\%s found as part of a <dt> tag", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Unsupported symbol \\%s found as part of a <dt> tag", qPrint(g_token->name)); break; case TK_HTMLTAG: @@ -3912,13 +3912,13 @@ int DocHtmlDescTitle::parse() } else { - warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected html tag <%s%s> found within <dt> context", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Unexpected html tag <%s%s> found within <dt> context", g_token->endTag?"/":"",qPrint(g_token->name)); } } break; default: - warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected token %s found as part of a <dt> tag", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Unexpected token %s found as part of a <dt> tag", tokToString(tok)); break; } @@ -3926,7 +3926,7 @@ int DocHtmlDescTitle::parse() } if (tok==0) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected end of comment while inside" + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Unexpected end of comment while inside" " <dt> tag"); } endtitle: @@ -3986,7 +3986,7 @@ int DocHtmlDescList::parse() } else // found some other tag { - warn_doc_error(g_fileName,doctokenizerYYlineno,"expected <dt> tag but " + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"expected <dt> tag but " "found <%s> instead!",qPrint(g_token->name)); doctokenizerYYpushBackHtmlTag(g_token->name); goto enddesclist; @@ -3994,13 +3994,13 @@ int DocHtmlDescList::parse() } else if (tok==0) // premature end of comment { - warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected end of comment while looking" + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"unexpected end of comment while looking" " for a html description title"); goto enddesclist; } else // token other than html token { - warn_doc_error(g_fileName,doctokenizerYYlineno,"expected <dt> tag but found %s token instead!", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"expected <dt> tag but found %s token instead!", tokToString(tok)); goto enddesclist; } @@ -4025,7 +4025,7 @@ int DocHtmlDescList::parse() if (retval==0) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected end of comment while inside <dl> block"); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"unexpected end of comment while inside <dl> block"); } enddesclist: @@ -4125,7 +4125,7 @@ int DocHtmlList::parse() { // add dummy item to obtain valid HTML m_children.append(new DocHtmlListItem(this,HtmlAttribList(),1)); - warn_doc_error(g_fileName,doctokenizerYYlineno,"empty list!"); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"empty list!"); retval = RetVal_EndList; goto endlist; } @@ -4133,7 +4133,7 @@ int DocHtmlList::parse() { // add dummy item to obtain valid HTML m_children.append(new DocHtmlListItem(this,HtmlAttribList(),1)); - warn_doc_error(g_fileName,doctokenizerYYlineno,"expected <li> tag but " + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"expected <li> tag but " "found <%s%s> instead!",g_token->endTag?"/":"",qPrint(g_token->name)); doctokenizerYYpushBackHtmlTag(g_token->name); goto endlist; @@ -4143,7 +4143,7 @@ int DocHtmlList::parse() { // add dummy item to obtain valid HTML m_children.append(new DocHtmlListItem(this,HtmlAttribList(),1)); - warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected end of comment while looking" + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"unexpected end of comment while looking" " for a html list item"); goto endlist; } @@ -4151,7 +4151,7 @@ int DocHtmlList::parse() { // add dummy item to obtain valid HTML m_children.append(new DocHtmlListItem(this,HtmlAttribList(),1)); - warn_doc_error(g_fileName,doctokenizerYYlineno,"expected <li> tag but found %s token instead!", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"expected <li> tag but found %s token instead!", tokToString(tok)); goto endlist; } @@ -4165,7 +4165,7 @@ int DocHtmlList::parse() if (retval==0) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected end of comment while inside <%cl> block", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"unexpected end of comment while inside <%cl> block", m_type==Unordered ? 'u' : 'o'); } @@ -4198,7 +4198,7 @@ int DocHtmlList::parseXml() } else // found some other tag { - warn_doc_error(g_fileName,doctokenizerYYlineno,"expected <item> tag but " + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"expected <item> tag but " "found <%s> instead!",qPrint(g_token->name)); doctokenizerYYpushBackHtmlTag(g_token->name); goto endlist; @@ -4206,13 +4206,13 @@ int DocHtmlList::parseXml() } else if (tok==0) // premature end of comment { - warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected end of comment while looking" + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"unexpected end of comment while looking" " for a html list item"); goto endlist; } else // token other than html token { - warn_doc_error(g_fileName,doctokenizerYYlineno,"expected <item> tag but found %s token instead!", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"expected <item> tag but found %s token instead!", tokToString(tok)); goto endlist; } @@ -4228,7 +4228,7 @@ int DocHtmlList::parseXml() if (retval==0) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected end of comment while inside <list type=\"%s\"> block", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"unexpected end of comment while inside <list type=\"%s\"> block", m_type==Unordered ? "bullet" : "number"); } @@ -4616,7 +4616,7 @@ int DocParamList::parse(const QCString &cmdName) int tok=doctokenizerYYlex(); if (tok!=TK_WHITESPACE) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after \\%s command", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"expected whitespace after \\%s command", qPrint(saveCmdName)); retval=0; goto endparamlist; @@ -4654,14 +4654,14 @@ int DocParamList::parse(const QCString &cmdName) doctokenizerYYsetStatePara(); if (tok==0) /* premature end of comment block */ { - warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected end of comment block while parsing the " + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"unexpected end of comment block while parsing the " "argument of command %s",qPrint(saveCmdName)); retval=0; goto endparamlist; } if (tok!=TK_WHITESPACE) /* premature end of comment block */ { - warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected token in comment block while parsing the " + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"unexpected token in comment block while parsing the " "argument of command %s",qPrint(saveCmdName)); retval=0; goto endparamlist; @@ -4734,7 +4734,7 @@ int DocParamList::parseXml(const QCString ¶mName) if (retval==0) /* premature end of comment block */ { - warn_doc_error(g_fileName,doctokenizerYYlineno,"unterminated param or exception tag"); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"unterminated param or exception tag"); } else { @@ -4853,7 +4853,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,getDoctokinizerLineNr(),"expected whitespace after \\%s command", qPrint("cite")); return; } @@ -4861,13 +4861,13 @@ void DocPara::handleCite() tok=doctokenizerYYlex(); if (tok==0) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected end of comment block while parsing the " + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"unexpected end of comment block while parsing the " "argument of command %s\n", qPrint("cite")); return; } else if (tok!=TK_WORD && tok!=TK_LNKWORD) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected token %s as the argument of %s", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"unexpected token %s as the argument of %s", tokToString(tok),qPrint("cite")); return; } @@ -4885,7 +4885,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,getDoctokinizerLineNr(),"expected whitespace after \\%s command", qPrint("emoji")); return; } @@ -4893,13 +4893,13 @@ void DocPara::handleEmoji() tok=doctokenizerYYlex(); if (tok==0) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected end of comment block while parsing the " + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"unexpected end of comment block while parsing the " "argument of command %s\n", qPrint("emoji")); return; } else if (tok!=TK_WORD) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected token %s as the argument of %s", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"unexpected token %s as the argument of %s", tokToString(tok),qPrint("emoji")); return; } @@ -4937,7 +4937,7 @@ void DocPara::handleIncludeOperator(const QCString &cmdName,DocIncOperator::Type int tok=doctokenizerYYlex(); if (tok!=TK_WHITESPACE) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after \\%s command", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"expected whitespace after \\%s command", qPrint(saveCmdName)); return; } @@ -4946,13 +4946,13 @@ void DocPara::handleIncludeOperator(const QCString &cmdName,DocIncOperator::Type doctokenizerYYsetStatePara(); if (tok==0) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected end of comment block while parsing the " + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"unexpected end of comment block while parsing the " "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", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"unexpected token %s as the argument of %s", tokToString(tok),qPrint(saveCmdName)); return; } @@ -5001,7 +5001,7 @@ void DocPara::handleImage(const QCString &cmdName) { if (g_token->name.lower() != "inline") { - warn_doc_error(g_fileName,doctokenizerYYlineno,"currently only 'inline' supported as option of %s command", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"currently only 'inline' supported as option of %s command", qPrint(saveCmdName)); } else @@ -5012,14 +5012,14 @@ void DocPara::handleImage(const QCString &cmdName) } if (!((tok==TK_WORD) && (g_token->name == "}"))) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"expected closing '}' at option of %s command", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"expected closing '}' at option of %s command", qPrint(saveCmdName)); return; } tok=doctokenizerYYlex(); if (tok!=TK_WHITESPACE) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after \\%s command with option", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"expected whitespace after \\%s command with option", qPrint(saveCmdName)); return; } @@ -5027,7 +5027,7 @@ void DocPara::handleImage(const QCString &cmdName) } else { - warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after \\%s command", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"expected whitespace after \\%s command", qPrint(saveCmdName)); return; } @@ -5035,14 +5035,14 @@ void DocPara::handleImage(const QCString &cmdName) tok=doctokenizerYYlex(); if (tok!=TK_WORD && tok!=TK_LNKWORD) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected token %s as the argument of %s", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"unexpected token %s as the argument of %s", tokToString(tok),qPrint(saveCmdName)); return; } tok=doctokenizerYYlex(); if (tok!=TK_WHITESPACE) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after \\%s command", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"expected whitespace after \\%s command", qPrint(saveCmdName)); return; } @@ -5054,7 +5054,7 @@ void DocPara::handleImage(const QCString &cmdName) else if (imgType=="rtf") t=DocImage::Rtf; else { - warn_doc_error(g_fileName,doctokenizerYYlineno,"output format %s specified as the first argument of " + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"output format %s specified as the first argument of " "%s command is not valid", qPrint(imgType),qPrint(saveCmdName)); return; @@ -5064,7 +5064,7 @@ void DocPara::handleImage(const QCString &cmdName) doctokenizerYYsetStatePara(); if (tok!=TK_WORD) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected token %s as the argument of %s", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"unexpected token %s as the argument of %s", tokToString(tok),qPrint(saveCmdName)); return; } @@ -5081,7 +5081,7 @@ void DocPara::handleFile(const QCString &cmdName) int tok=doctokenizerYYlex(); if (tok!=TK_WHITESPACE) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after \\%s command", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"expected whitespace after \\%s command", qPrint(saveCmdName)); return; } @@ -5090,7 +5090,7 @@ void DocPara::handleFile(const QCString &cmdName) doctokenizerYYsetStatePara(); if (tok!=TK_WORD) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected token %s as the argument of %s", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"unexpected token %s as the argument of %s", tokToString(tok),qPrint(saveCmdName)); return; } @@ -5119,7 +5119,7 @@ void DocPara::handleLink(const QCString &cmdName,bool isJavaLink) int tok=doctokenizerYYlex(); if (tok!=TK_WHITESPACE) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after \\%s command", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"expected whitespace after \\%s command", qPrint(saveCmdName)); return; } @@ -5127,7 +5127,7 @@ void DocPara::handleLink(const QCString &cmdName,bool isJavaLink) tok=doctokenizerYYlex(); if (tok!=TK_WORD) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"%s as the argument of %s", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"%s as the argument of %s", tokToString(tok),qPrint(saveCmdName)); return; } @@ -5148,7 +5148,7 @@ void DocPara::handleRef(const QCString &cmdName) int tok=doctokenizerYYlex(); if (tok!=TK_WHITESPACE) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after \\%s command", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"expected whitespace after \\%s command", qPrint(saveCmdName)); return; } @@ -5157,7 +5157,7 @@ void DocPara::handleRef(const QCString &cmdName) DocRef *ref=0; if (tok!=TK_WORD) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected token %s as the argument of %s", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"unexpected token %s as the argument of %s", tokToString(tok),qPrint(saveCmdName)); goto endref; } @@ -5212,7 +5212,7 @@ 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", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"expected whitespace after \\%s command", qPrint(saveCmdName)); return; } @@ -5221,13 +5221,13 @@ void DocPara::handleInclude(const QCString &cmdName,DocInclude::Type t) doctokenizerYYsetStatePara(); if (tok==0) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected end of comment block while parsing the " + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"unexpected end of comment block while parsing the " "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", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"unexpected token %s as the argument of %s", tokToString(tok),qPrint(saveCmdName)); return; } @@ -5241,7 +5241,7 @@ void DocPara::handleInclude(const QCString &cmdName,DocInclude::Type t) doctokenizerYYsetStatePara(); if (tok!=TK_WORD) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"expected block identifier, but found token %s instead while parsing the %s command", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"expected block identifier, but found token %s instead while parsing the %s command", tokToString(tok),qPrint(saveCmdName)); return; } @@ -5262,7 +5262,7 @@ void DocPara::handleInclude(const QCString &cmdName,DocInclude::Type t) } docParserPushContext(); g_fileName = fileName; - doctokenizerYYlineno=inc_line; + setDoctokinizerLineNr(inc_line); internalValidatingParseDoc(this,m_children,inc_text); docParserPopContext(); } @@ -5281,20 +5281,20 @@ void DocPara::handleSection(const QCString &cmdName) int tok=doctokenizerYYlex(); if (tok!=TK_WHITESPACE) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"expected whitespace after \\%s command", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"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 " + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"unexpected end of comment block while parsing the " "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", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"unexpected token %s as the argument of %s", tokToString(tok),qPrint(saveCmdName)); return; } @@ -5341,7 +5341,7 @@ int DocPara::handleStartCode() i++; } m_children.append(new DocVerbatim(this,g_context,stripIndentation(g_token->verb.mid(li)),DocVerbatim::Code,g_isExample,g_exampleName,FALSE,lang)); - if (retval==0) warn_doc_error(g_fileName,doctokenizerYYlineno,"code section ended without end marker"); + if (retval==0) warn_doc_error(g_fileName,getDoctokinizerLineNr(),"code section ended without end marker"); doctokenizerYYsetStatePara(); return retval; } @@ -5384,7 +5384,7 @@ int DocPara::handleCommand(const QCString &cmdName, const int tok) { case CMD_UNKNOWN: m_children.append(new DocWord(this,TK_COMMAND_CHAR(tok) + cmdName)); - warn_doc_error(g_fileName,doctokenizerYYlineno,"Found unknown command '%c%s'",TK_COMMAND_CHAR(tok),qPrint(cmdName)); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Found unknown command '%c%s'",TK_COMMAND_CHAR(tok),qPrint(cmdName)); break; case CMD_EMPHASIS: m_children.append(new DocStyleChange(this,g_nodeStack.count(),DocStyleChange::Italic,cmdName,TRUE)); @@ -5551,7 +5551,7 @@ int DocPara::handleCommand(const QCString &cmdName, const int tok) doctokenizerYYsetStateHtmlOnly(); retval = doctokenizerYYlex(); m_children.append(new DocVerbatim(this,g_context,g_token->verb,DocVerbatim::HtmlOnly,g_isExample,g_exampleName,g_token->name=="block")); - if (retval==0) warn_doc_error(g_fileName,doctokenizerYYlineno,"htmlonly section ended without end marker"); + if (retval==0) warn_doc_error(g_fileName,getDoctokinizerLineNr(),"htmlonly section ended without end marker"); doctokenizerYYsetStatePara(); } break; @@ -5560,7 +5560,7 @@ int DocPara::handleCommand(const QCString &cmdName, const int tok) doctokenizerYYsetStateManOnly(); retval = doctokenizerYYlex(); m_children.append(new DocVerbatim(this,g_context,g_token->verb,DocVerbatim::ManOnly,g_isExample,g_exampleName)); - if (retval==0) warn_doc_error(g_fileName,doctokenizerYYlineno,"manonly section ended without end marker"); + if (retval==0) warn_doc_error(g_fileName,getDoctokinizerLineNr(),"manonly section ended without end marker"); doctokenizerYYsetStatePara(); } break; @@ -5569,7 +5569,7 @@ int DocPara::handleCommand(const QCString &cmdName, const int tok) doctokenizerYYsetStateRtfOnly(); retval = doctokenizerYYlex(); m_children.append(new DocVerbatim(this,g_context,g_token->verb,DocVerbatim::RtfOnly,g_isExample,g_exampleName)); - if (retval==0) warn_doc_error(g_fileName,doctokenizerYYlineno,"rtfonly section ended without end marker"); + if (retval==0) warn_doc_error(g_fileName,getDoctokinizerLineNr(),"rtfonly section ended without end marker"); doctokenizerYYsetStatePara(); } break; @@ -5578,7 +5578,7 @@ int DocPara::handleCommand(const QCString &cmdName, const int tok) doctokenizerYYsetStateLatexOnly(); retval = doctokenizerYYlex(); m_children.append(new DocVerbatim(this,g_context,g_token->verb,DocVerbatim::LatexOnly,g_isExample,g_exampleName)); - if (retval==0) warn_doc_error(g_fileName,doctokenizerYYlineno,"latexonly section ended without end marker"); + if (retval==0) warn_doc_error(g_fileName,getDoctokinizerLineNr(),"latexonly section ended without end marker"); doctokenizerYYsetStatePara(); } break; @@ -5587,7 +5587,7 @@ int DocPara::handleCommand(const QCString &cmdName, const int tok) doctokenizerYYsetStateXmlOnly(); retval = doctokenizerYYlex(); m_children.append(new DocVerbatim(this,g_context,g_token->verb,DocVerbatim::XmlOnly,g_isExample,g_exampleName)); - if (retval==0) warn_doc_error(g_fileName,doctokenizerYYlineno,"xmlonly section ended without end marker"); + if (retval==0) warn_doc_error(g_fileName,getDoctokinizerLineNr(),"xmlonly section ended without end marker"); doctokenizerYYsetStatePara(); } break; @@ -5596,7 +5596,7 @@ int DocPara::handleCommand(const QCString &cmdName, const int tok) doctokenizerYYsetStateDbOnly(); retval = doctokenizerYYlex(); m_children.append(new DocVerbatim(this,g_context,g_token->verb,DocVerbatim::DocbookOnly,g_isExample,g_exampleName)); - if (retval==0) warn_doc_error(g_fileName,doctokenizerYYlineno,"docbookonly section ended without end marker"); + if (retval==0) warn_doc_error(g_fileName,getDoctokinizerLineNr(),"docbookonly section ended without end marker"); doctokenizerYYsetStatePara(); } break; @@ -5605,7 +5605,7 @@ int DocPara::handleCommand(const QCString &cmdName, const int tok) doctokenizerYYsetStateVerbatim(); retval = doctokenizerYYlex(); m_children.append(new DocVerbatim(this,g_context,g_token->verb,DocVerbatim::Verbatim,g_isExample,g_exampleName)); - if (retval==0) warn_doc_error(g_fileName,doctokenizerYYlineno,"verbatim section ended without end marker"); + if (retval==0) warn_doc_error(g_fileName,getDoctokinizerLineNr(),"verbatim section ended without end marker"); doctokenizerYYsetStatePara(); } break; @@ -5621,7 +5621,7 @@ int DocPara::handleCommand(const QCString &cmdName, const int tok) dv->setWidth(width); dv->setHeight(height); m_children.append(dv); - if (retval==0) warn_doc_error(g_fileName,doctokenizerYYlineno,"dot section ended without end marker"); + if (retval==0) warn_doc_error(g_fileName,getDoctokinizerLineNr(),"dot section ended without end marker"); doctokenizerYYsetStatePara(); } break; @@ -5637,7 +5637,7 @@ int DocPara::handleCommand(const QCString &cmdName, const int tok) dv->setWidth(width); dv->setHeight(height); m_children.append(dv); - if (retval==0) warn_doc_error(g_fileName,doctokenizerYYlineno,"msc section ended without end marker"); + if (retval==0) warn_doc_error(g_fileName,getDoctokinizerLineNr(),"msc section ended without end marker"); doctokenizerYYsetStatePara(); } break; @@ -5659,14 +5659,14 @@ int DocPara::handleCommand(const QCString &cmdName, const int tok) dv->setHeight(height); if (jarPath.isEmpty()) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"ignoring \\startuml command because PLANTUML_JAR_PATH is not set"); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"ignoring \\startuml command because PLANTUML_JAR_PATH is not set"); delete dv; } else { m_children.append(dv); } - if (retval==0) warn_doc_error(g_fileName,doctokenizerYYlineno,"startuml section ended without end marker"); + if (retval==0) warn_doc_error(g_fileName,getDoctokinizerLineNr(),"startuml section ended without end marker"); doctokenizerYYsetStatePara(); } break; @@ -5685,7 +5685,7 @@ int DocPara::handleCommand(const QCString &cmdName, const int tok) case CMD_ENDDOT: case CMD_ENDMSC: case CMD_ENDUML: - warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected command %s",qPrint(g_token->name)); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"unexpected command %s",qPrint(g_token->name)); break; case CMD_PARAM: retval = handleParamSection(cmdName,DocParamSect::Param,FALSE,g_token->paramDir); @@ -5838,10 +5838,10 @@ int DocPara::handleCommand(const QCString &cmdName, const int tok) } break; case CMD_SECREFITEM: - warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected command %s",qPrint(g_token->name)); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"unexpected command %s",qPrint(g_token->name)); break; case CMD_ENDSECREFLIST: - warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected command %s",qPrint(g_token->name)); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"unexpected command %s",qPrint(g_token->name)); break; case CMD_FORMULA: { @@ -5853,7 +5853,7 @@ int DocPara::handleCommand(const QCString &cmdName, const int tok) // retval = handleLanguageSwitch(); // break; case CMD_INTERNALREF: - //warn_doc_error(g_fileName,doctokenizerYYlineno,"unexpected command %s",qPrint(g_token->name)); + //warn_doc_error(g_fileName,getDoctokinizerLineNr(),"unexpected command %s",qPrint(g_token->name)); { DocInternalRef *ref = handleInternalRef(this); if (ref) @@ -5908,7 +5908,7 @@ int DocPara::handleHtmlStartTag(const QCString &tagName,const HtmlAttribList &ta if (g_token->emptyTag && !(tagId&XML_CmdMask) && tagId!=HTML_UNKNOWN && tagId!=HTML_IMG && tagId!=HTML_BR && tagId!=HTML_HR && tagId!=HTML_P) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"HTML tag ('<%s/>') may not use the 'empty tag' XHTML syntax.", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"HTML tag ('<%s/>') may not use the 'empty tag' XHTML syntax.", tagName.data()); } switch (tagId) @@ -5933,7 +5933,7 @@ int DocPara::handleHtmlStartTag(const QCString &tagName,const HtmlAttribList &ta if (g_token->emptyTag) break; if (!insideUL(this) && !insideOL(this)) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"lonely <li> tag found"); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"lonely <li> tag found"); } else { @@ -6014,7 +6014,7 @@ int DocPara::handleHtmlStartTag(const QCString &tagName,const HtmlAttribList &ta retval = RetVal_DescTitle; break; case HTML_DD: - warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected tag <dd> found"); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Unexpected tag <dd> found"); break; case HTML_TABLE: if (!g_token->emptyTag) @@ -6034,7 +6034,7 @@ int DocPara::handleHtmlStartTag(const QCString &tagName,const HtmlAttribList &ta retval = RetVal_TableHCell; break; case HTML_CAPTION: - warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected tag <caption> found"); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Unexpected tag <caption> found"); break; case HTML_BR: { @@ -6115,7 +6115,7 @@ int DocPara::handleHtmlStartTag(const QCString &tagName,const HtmlAttribList &ta { if (Config_getBool(WARN_NO_PARAMDOC)) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"empty 'name' attribute for <param%s> tag.",tagId==XML_PARAM?"":"type"); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"empty 'name' attribute for <param%s> tag.",tagId==XML_PARAM?"":"type"); } } else @@ -6127,7 +6127,7 @@ int DocPara::handleHtmlStartTag(const QCString &tagName,const HtmlAttribList &ta } else { - warn_doc_error(g_fileName,doctokenizerYYlineno,"Missing 'name' attribute from <param%s> tag.",tagId==XML_PARAM?"":"type"); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Missing 'name' attribute from <param%s> tag.",tagId==XML_PARAM?"":"type"); } } break; @@ -6145,7 +6145,7 @@ int DocPara::handleHtmlStartTag(const QCString &tagName,const HtmlAttribList &ta } else { - warn_doc_error(g_fileName,doctokenizerYYlineno,"Missing 'name' attribute from <param%sref> tag.",tagId==XML_PARAMREF?"":"type"); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Missing 'name' attribute from <param%sref> tag.",tagId==XML_PARAMREF?"":"type"); } } break; @@ -6160,7 +6160,7 @@ int DocPara::handleHtmlStartTag(const QCString &tagName,const HtmlAttribList &ta } else { - warn_doc_error(g_fileName,doctokenizerYYlineno,"Missing 'cref' attribute from <exception> tag."); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Missing 'cref' attribute from <exception> tag."); } } break; @@ -6176,7 +6176,7 @@ int DocPara::handleHtmlStartTag(const QCString &tagName,const HtmlAttribList &ta } else { - warn_doc_error(g_fileName,doctokenizerYYlineno,"lonely <item> tag found"); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"lonely <item> tag found"); } break; case XML_RETURNS: @@ -6237,7 +6237,7 @@ int DocPara::handleHtmlStartTag(const QCString &tagName,const HtmlAttribList &ta } else { - warn_doc_error(g_fileName,doctokenizerYYlineno,"Missing 'cref' or 'langword' attribute from <see> tag."); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Missing 'cref' or 'langword' attribute from <see> tag."); } } break; @@ -6271,7 +6271,7 @@ int DocPara::handleHtmlStartTag(const QCString &tagName,const HtmlAttribList &ta } else { - warn_doc_error(g_fileName,doctokenizerYYlineno,"Missing 'cref' attribute from <seealso> tag."); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Missing 'cref' attribute from <seealso> tag."); } } break; @@ -6305,7 +6305,7 @@ int DocPara::handleHtmlStartTag(const QCString &tagName,const HtmlAttribList &ta g_xmlComment=TRUE; break; case HTML_UNKNOWN: - warn_doc_error(g_fileName,doctokenizerYYlineno,"Unsupported xml/html tag <%s> found", qPrint(tagName)); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Unsupported xml/html tag <%s> found", qPrint(tagName)); m_children.append(new DocWord(this, "<"+tagName+g_token->attribsStr+">")); break; case XML_INHERITDOC: @@ -6329,7 +6329,7 @@ int DocPara::handleHtmlEndTag(const QCString &tagName) case HTML_UL: if (!insideUL(this)) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"found </ul> tag without matching <ul>"); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"found </ul> tag without matching <ul>"); } else { @@ -6339,7 +6339,7 @@ int DocPara::handleHtmlEndTag(const QCString &tagName) case HTML_OL: if (!insideOL(this)) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"found </ol> tag without matching <ol>"); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"found </ol> tag without matching <ol>"); } else { @@ -6349,7 +6349,7 @@ int DocPara::handleHtmlEndTag(const QCString &tagName) case HTML_LI: if (!insideLI(this)) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"found </li> tag without matching <li>"); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"found </li> tag without matching <li>"); } else { @@ -6362,7 +6362,7 @@ int DocPara::handleHtmlEndTag(const QCString &tagName) //case HTML_PRE: // if (!insidePRE(this)) // { - // warn_doc_error(g_fileName,doctokenizerYYlineno,"found </pre> tag without matching <pre>"); + // warn_doc_error(g_fileName,getDoctokinizerLineNr(),"found </pre> tag without matching <pre>"); // } // else // { @@ -6441,37 +6441,37 @@ int DocPara::handleHtmlEndTag(const QCString &tagName) // ignore </th> tag break; case HTML_CAPTION: - warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected tag </caption> found"); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Unexpected tag </caption> found"); break; case HTML_BR: - warn_doc_error(g_fileName,doctokenizerYYlineno,"Illegal </br> tag found\n"); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Illegal </br> tag found\n"); break; case HTML_H1: - warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected tag </h1> found"); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Unexpected tag </h1> found"); break; case HTML_H2: - warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected tag </h2> found"); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Unexpected tag </h2> found"); break; case HTML_H3: - warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected tag </h3> found"); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Unexpected tag </h3> found"); break; case HTML_H4: - warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected tag </h4> found"); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Unexpected tag </h4> found"); break; case HTML_H5: - warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected tag </h5> found"); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Unexpected tag </h5> found"); break; case HTML_H6: - warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected tag </h6> found"); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Unexpected tag </h6> found"); break; case HTML_IMG: - warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected tag </img> found"); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Unexpected tag </img> found"); break; case HTML_HR: - warn_doc_error(g_fileName,doctokenizerYYlineno,"Illegal </hr> tag found\n"); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Illegal </hr> tag found\n"); break; case HTML_A: - //warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected tag </a> found"); + //warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Unexpected tag </a> found"); // ignore </a> tag (can be part of <a name=...></a> break; @@ -6506,12 +6506,12 @@ int DocPara::handleHtmlEndTag(const QCString &tagName) // These tags are defined in .Net but are currently unsupported break; case HTML_UNKNOWN: - warn_doc_error(g_fileName,doctokenizerYYlineno,"Unsupported xml/html tag </%s> found", qPrint(tagName)); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Unsupported xml/html tag </%s> found", qPrint(tagName)); m_children.append(new DocWord(this,"</"+tagName+">")); break; default: // we should not get here! - warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected end tag %s\n",qPrint(tagName)); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Unexpected end tag %s\n",qPrint(tagName)); ASSERT(0); break; } @@ -6529,7 +6529,7 @@ int DocPara::parse() while ((tok=doctokenizerYYlex())) // get the next token { reparsetoken: - DBG(("token %s at %d",tokToString(tok),doctokenizerYYlineno)); + DBG(("token %s at %d",tokToString(tok),getDoctokinizerLineNr())); if (tok==TK_WORD || tok==TK_LNKWORD || tok==TK_SYMBOL || tok==TK_URL || tok==TK_COMMAND_AT || tok == TK_COMMAND_BS || tok==TK_HTMLTAG ) @@ -6651,7 +6651,7 @@ reparsetoken: } break; case TK_ENDLIST: - DBG(("Found end of list inside of paragraph at line %d\n",doctokenizerYYlineno)); + DBG(("Found end of list inside of paragraph at line %d\n",getDoctokinizerLineNr())); if (parent()->kind()==DocNode::Kind_AutoListItem) { ASSERT(parent()->parent()->kind()==DocNode::Kind_AutoList); @@ -6664,13 +6664,13 @@ reparsetoken: } else { - warn_doc_error(g_fileName,doctokenizerYYlineno,"End of list marker found " + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"End of list marker found " "has invalid indent level"); } } else { - warn_doc_error(g_fileName,doctokenizerYYlineno,"End of list marker found without any preceding " + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"End of list marker found without any preceding " "list items"); } break; @@ -6783,7 +6783,7 @@ reparsetoken: } else { - warn_doc_error(g_fileName,doctokenizerYYlineno,"Unsupported symbol %s found", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Unsupported symbol %s found", qPrint(g_token->name)); } break; @@ -6818,7 +6818,7 @@ reparsetoken: } break; default: - warn_doc_error(g_fileName,doctokenizerYYlineno, + warn_doc_error(g_fileName,getDoctokinizerLineNr(), "Found unexpected token (id=%x)\n",tok); break; } @@ -6880,7 +6880,7 @@ int DocSection::parse() } if (retval==TK_LISTITEM) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"Invalid list item found"); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Invalid list item found"); } if (retval==RetVal_Internal) { @@ -6921,7 +6921,7 @@ int DocSection::parse() else if (retval==RetVal_Subsubsection && m_level<=Doxygen::subpageNestingLevel+2) { if ((m_level<=1+Doxygen::subpageNestingLevel) && !g_token->sectionId.startsWith("autotoc_md")) - warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected subsubsection command found inside %s!",sectionLevelToName[m_level]); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Unexpected subsubsection command found inside %s!",sectionLevelToName[m_level]); // then parse any number of nested sections while (retval==RetVal_Subsubsection) // more sections follow { @@ -6935,7 +6935,7 @@ int DocSection::parse() else if (retval==RetVal_Paragraph && m_level<=QMIN(5,Doxygen::subpageNestingLevel+3)) { if ((m_level<=2+Doxygen::subpageNestingLevel) && !g_token->sectionId.startsWith("autotoc_md")) - warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected paragraph command found inside %s!",sectionLevelToName[m_level]); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Unexpected paragraph command found inside %s!",sectionLevelToName[m_level]); // then parse any number of nested sections while (retval==RetVal_Paragraph) // more sections follow { @@ -6995,7 +6995,7 @@ void DocText::parse() } else { - warn_doc_error(g_fileName,doctokenizerYYlineno,"Unsupported symbol %s found", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Unsupported symbol %s found", qPrint(g_token->name)); } } @@ -7057,13 +7057,13 @@ void DocText::parse() m_children.append(new DocSymbol(this,DocSymbol::Sym_Equal)); break; default: - warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected command '%s' found", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Unexpected command '%s' found", qPrint(g_token->name)); break; } break; default: - warn_doc_error(g_fileName,doctokenizerYYlineno,"Unexpected token %s", + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Unexpected token %s", tokToString(tok)); break; } @@ -7107,7 +7107,7 @@ void DocRoot::parse() { if (!g_token->sectionId.startsWith("autotoc_md")) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"found paragraph command (id: '%s') outside of subsubsection context!",qPrint(g_token->sectionId)); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"found paragraph command (id: '%s') outside of subsubsection context!",qPrint(g_token->sectionId)); } while (retval==RetVal_Paragraph) { @@ -7123,13 +7123,13 @@ void DocRoot::parse() } else { - warn_doc_error(g_fileName,doctokenizerYYlineno,"Invalid paragraph id '%s'; ignoring paragraph",qPrint(g_token->sectionId)); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Invalid paragraph id '%s'; ignoring paragraph",qPrint(g_token->sectionId)); retval = 0; } } else { - warn_doc_error(g_fileName,doctokenizerYYlineno,"Missing id for paragraph; ignoring paragraph"); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Missing id for paragraph; ignoring paragraph"); retval = 0; } } @@ -7137,7 +7137,7 @@ void DocRoot::parse() if (retval==RetVal_Subsubsection) { if (!(g_token->sectionId.startsWith("autotoc_md"))) - warn_doc_error(g_fileName,doctokenizerYYlineno,"found subsubsection command (id: '%s') outside of subsection context!",qPrint(g_token->sectionId)); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"found subsubsection command (id: '%s') outside of subsection context!",qPrint(g_token->sectionId)); while (retval==RetVal_Subsubsection) { if (!g_token->sectionId.isEmpty()) @@ -7152,13 +7152,13 @@ void DocRoot::parse() } else { - warn_doc_error(g_fileName,doctokenizerYYlineno,"Invalid subsubsection id '%s'; ignoring subsubsection",qPrint(g_token->sectionId)); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Invalid subsubsection id '%s'; ignoring subsubsection",qPrint(g_token->sectionId)); retval = 0; } } else { - warn_doc_error(g_fileName,doctokenizerYYlineno,"Missing id for subsubsection; ignoring subsubsection"); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Missing id for subsubsection; ignoring subsubsection"); retval = 0; } } @@ -7167,7 +7167,7 @@ void DocRoot::parse() { if (!g_token->sectionId.startsWith("autotoc_md")) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"found subsection command (id: '%s') outside of section context!",qPrint(g_token->sectionId)); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"found subsection command (id: '%s') outside of section context!",qPrint(g_token->sectionId)); } while (retval==RetVal_Subsection) { @@ -7183,20 +7183,20 @@ void DocRoot::parse() } else { - warn_doc_error(g_fileName,doctokenizerYYlineno,"Invalid subsection id '%s'; ignoring subsection",qPrint(g_token->sectionId)); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Invalid subsection id '%s'; ignoring subsection",qPrint(g_token->sectionId)); retval = 0; } } else { - warn_doc_error(g_fileName,doctokenizerYYlineno,"Missing id for subsection; ignoring subsection"); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Missing id for subsection; ignoring subsection"); retval = 0; } } } if (retval==TK_LISTITEM) { - warn_doc_error(g_fileName,doctokenizerYYlineno,"Invalid list item found"); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Invalid list item found"); } if (retval==RetVal_Internal) { @@ -7223,13 +7223,13 @@ void DocRoot::parse() } else { - warn_doc_error(g_fileName,doctokenizerYYlineno,"Invalid section id '%s'; ignoring section",qPrint(g_token->sectionId)); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Invalid section id '%s'; ignoring section",qPrint(g_token->sectionId)); retval = 0; } } else { - warn_doc_error(g_fileName,doctokenizerYYlineno,"Missing id for section; ignoring section"); + warn_doc_error(g_fileName,getDoctokinizerLineNr(),"Missing id for section; ignoring section"); retval = 0; } } @@ -7397,14 +7397,14 @@ static QCString processCopyDoc(const char *data,uint &len) } else { - warn_doc_error(g_fileName,doctokenizerYYlineno, + warn_doc_error(g_fileName,getDoctokinizerLineNr(), "Found recursive @copy%s or @copydoc relation for argument '%s'.\n", isBrief?"brief":"details",id.data()); } } else { - warn_doc_error(g_fileName,doctokenizerYYlineno, + warn_doc_error(g_fileName,getDoctokinizerLineNr(), "@copy%s or @copydoc target '%s' not found", isBrief?"brief":"details", id.data()); } @@ -7590,12 +7590,12 @@ DocRoot *validatingParseDoc(const char *fileName,int startLine, } else if (ctx && ctx->definitionType()==Definition::TypePage) { - const Definition *scope = (dynamic_cast<const PageDef*>(ctx))->getPageScope(); + const Definition *scope = (toPageDef(ctx))->getPageScope(); if (scope && scope!=Doxygen::globalScope) g_context = scope->name(); } else if (ctx && ctx->definitionType()==Definition::TypeGroup) { - const Definition *scope = (dynamic_cast<const GroupDef*>(ctx))->getGroupScope(); + const Definition *scope = (toGroupDef(ctx))->getGroupScope(); if (scope && scope!=Doxygen::globalScope) g_context = scope->name(); } else @@ -7727,7 +7727,7 @@ DocRoot *validatingParseDoc(const char *fileName,int startLine, g_markdownSupport = markdownSupport; //printf("Starting comment block at %s:%d\n",g_fileName.data(),startLine); - doctokenizerYYlineno=startLine; + setDoctokinizerLineNr(startLine); uint inpLen=qstrlen(input); QCString inpStr = processCopyDoc(input,inpLen); if (inpStr.isEmpty() || inpStr.at(inpStr.length()-1)!='\n') @@ -7802,7 +7802,7 @@ DocText *validatingParseText(const char *input) if (input) { - doctokenizerYYlineno=1; + setDoctokinizerLineNr(1); doctokenizerYYinit(input,g_fileName,Config_getBool(MARKDOWN_SUPPORT)); // build abstract syntax tree diff --git a/src/docsets.cpp b/src/docsets.cpp index d92e4f3..c59ca76 100644 --- a/src/docsets.cpp +++ b/src/docsets.cpp @@ -3,8 +3,8 @@ * Copyright (C) 1997-2015 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. * @@ -66,7 +66,7 @@ void DocSets::initialize() } FTextStream ts(&makefile); - ts << "DOCSET_NAME=" << bundleId << ".docset\n" + ts << "DOCSET_NAME=" << bundleId << ".docset\n" "DOCSET_CONTENTS=$(DOCSET_NAME)/Contents\n" "DOCSET_RESOURCES=$(DOCSET_CONTENTS)/Resources\n" "DOCSET_DOCUMENTS=$(DOCSET_RESOURCES)/Documents\n" @@ -116,25 +116,25 @@ void DocSets::initialize() } FTextStream ts(&plist); - ts << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" - "<!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\"\n" - "\"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n" - "<plist version=\"1.0\">\n" - "<dict>\n" - " <key>CFBundleName</key>\n" - " <string>" << projectName << "</string>\n" + ts << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + "<!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\"\n" + "\"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n" + "<plist version=\"1.0\">\n" + "<dict>\n" + " <key>CFBundleName</key>\n" + " <string>" << projectName << "</string>\n" " <key>CFBundleIdentifier</key>\n" - " <string>" << bundleId << "</string>\n" + " <string>" << bundleId << "</string>\n" " <key>CFBundleVersion</key>\n" " <string>" << projectNumber << "</string>\n" - " <key>DocSetFeedName</key>\n" + " <key>DocSetFeedName</key>\n" " <string>" << feedName << "</string>\n" " <key>DocSetPublisherIdentifier</key>\n" " <string>" << publisherId << "</string>\n" " <key>DocSetPublisherName</key>\n" " <string>" << publisherName << "</string>\n" // markers for Dash - " <key>DashDocSetFamily</key>\n" + " <key>DashDocSetFamily</key>\n" " <string>doxy</string>\n" " <key>DocSetPlatformFamily</key>\n" " <string>doxygen</string>\n" @@ -226,8 +226,8 @@ void DocSets::decContentsDepth() } void DocSets::addContentsItem(bool isDir, - const char *name, - const char *ref, + const char *name, + const char *ref, const char *file, const char *anchor, bool /* separateIndex */, @@ -247,7 +247,7 @@ void DocSets::addContentsItem(bool isDir, m_nts << indent() << " <Name>" << convertToXML(name) << "</Name>" << endl; if (file && file[0]=='^') // URL marker { - m_nts << indent() << " <URL>" << convertToXML(&file[1]) + m_nts << indent() << " <URL>" << convertToXML(&file[1]) << "</URL>" << endl; } else // relative file @@ -294,11 +294,11 @@ void DocSets::addIndexItem(const Definition *context,const MemberDef *md, // determine language QCString lang; SrcLangExt langExt = SrcLangExt_Cpp; - if (md) + if (md) { langExt = md->getLanguage(); } - else if (context) + else if (context) { langExt = context->getLanguage(); } @@ -309,7 +309,7 @@ void DocSets::addIndexItem(const Definition *context,const MemberDef *md, { if (md && (md->isObjCMethod() || md->isObjCProperty())) lang="occ"; // Objective C/C++ - else if (fd && fd->name().right(2).lower()==".c") + else if (fd && fd->name().right(2).lower()==".c") lang="c"; // Plain C else if (cd==0 && nd==0) lang="c"; // Plain C symbol outside any class or namespace @@ -386,9 +386,9 @@ void DocSets::addIndexItem(const Definition *context,const MemberDef *md, case MemberType_DCOP: type="dcop"; break; case MemberType_Property: - if (cd && cd->compoundType()==ClassDef::Protocol) + if (cd && cd->compoundType()==ClassDef::Protocol) type="intfp"; // interface property - else + else type="instp"; // instance property break; case MemberType_Event: @@ -404,7 +404,7 @@ void DocSets::addIndexItem(const Definition *context,const MemberDef *md, } cd = md->getClassDef(); nd = md->getNamespaceDef(); - if (cd) + if (cd) { scope = cd->qualifiedName(); } @@ -427,28 +427,28 @@ void DocSets::addIndexItem(const Definition *context,const MemberDef *md, { if (fd==0 && context->definitionType()==Definition::TypeFile) { - fd = dynamic_cast<const FileDef*>(context); + fd = toFileDef(context); } if (cd==0 && context->definitionType()==Definition::TypeClass) { - cd = dynamic_cast<const ClassDef*>(context); + cd = toClassDef(context); } if (nd==0 && context->definitionType()==Definition::TypeNamespace) { - nd = dynamic_cast<const NamespaceDef*>(context); + nd = toNamespaceDef(context); } if (fd) { type="file"; } - else if (cd) + else if (cd) { scope = cd->qualifiedName(); if (cd->isTemplate()) { type="tmplt"; } - else if (cd->compoundType()==ClassDef::Protocol) + else if (cd->compoundType()==ClassDef::Protocol) { type="intf"; if (scope.right(2)=="-p") scope=scope.left(scope.length()-2); @@ -461,7 +461,7 @@ void DocSets::addIndexItem(const Definition *context,const MemberDef *md, { type="cat"; } - else + else { type = "cl"; } @@ -510,7 +510,7 @@ void DocSets::writeToken(FTextStream &t, t << " <Scope>" << convertToXML(scope) << "</Scope>" << endl; } t << " </TokenIdentifier>" << endl; - t << " <Path>" << d->getOutputFileBase() + t << " <Path>" << d->getOutputFileBase() << Doxygen::htmlFileExtension << "</Path>" << endl; if (anchor) { diff --git a/src/doctokenizer.h b/src/doctokenizer.h index f43cd07..235b403 100644 --- a/src/doctokenizer.h +++ b/src/doctokenizer.h @@ -115,12 +115,14 @@ struct TokenInfo // globals extern TokenInfo *g_token; -extern int doctokenizerYYlineno; extern FILE *doctokenizerYYin; // helper functions const char *tokToString(int token); +void setDoctokinizerLineNr(int lineno); +int getDoctokinizerLineNr(void); + // operations on the scanner void doctokenizerYYFindSections(const char *input,const Definition *d, const char *fileName); diff --git a/src/doctokenizer.l b/src/doctokenizer.l index ac5b6d2..f756186 100644 --- a/src/doctokenizer.l +++ b/src/doctokenizer.l @@ -6,8 +6,8 @@ * Copyright (C) 1997-2015 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. * @@ -49,7 +49,7 @@ #define USE_STATE2STRING 0 #define TK_COMMAND_SEL() (yytext[0] == '@' ? TK_COMMAND_AT : TK_COMMAND_BS) - + //-------------------------------------------------------------------------- // context for tokenizer phase @@ -75,13 +75,18 @@ struct DocLexerContext TokenInfo *token; int rule; int autoListLevel; - int inputPos; + yy_size_t inputPos; const char *inputString; YY_BUFFER_STATE state; }; static QStack<DocLexerContext> g_lexerStack; +static int g_yyLineNr = 0; + +#define lineCount(s,len) do { for(int i=0;i<(int)len;i++) if (s[i]=='\n') g_yyLineNr++; } while(0) + + #if USE_STATE2STRING static const char *stateToString(int state); #endif @@ -187,7 +192,7 @@ static void processSection() } else { - warn(g_fileName,yylineno,"Found section/anchor %s without context\n",g_secLabel.data()); + warn(g_fileName,g_yyLineNr,"Found section/anchor %s without context\n",g_secLabel.data()); } SectionInfo *si = SectionManager::instance().find(g_secLabel); if (si) @@ -203,10 +208,10 @@ static void handleHtmlTag() g_token->attribs.clear(); g_token->endTag = FALSE; g_token->emptyTag = FALSE; - + // Check for end tag int startNamePos=1; - if (tagText.at(1)=='/') + if (tagText.at(1)=='/') { g_token->endTag = TRUE; startNamePos++; @@ -234,7 +239,7 @@ static void handleHtmlTag() // check for end of the tag if (c == '>') break; // Check for XML style "empty" tag. - if (c == '/') + if (c == '/') { g_token->emptyTag = TRUE; break; @@ -244,42 +249,42 @@ static void handleHtmlTag() while (i<(int)yyleng && !isspace((uchar)c) && c!='=' && c!= '>') { c=tagText.at(++i); } endName=i; HtmlAttrib opt; - opt.name = tagText.mid(startName,endName-startName).lower(); + opt.name = tagText.mid(startName,endName-startName).lower(); // skip spaces - while (i<(int)yyleng && isspace((uchar)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((uchar)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); - startAttrib=i; - - // search for matching quote - while (i<(int)yyleng && c!='\'') { c=tagText.at(++i); } - endAttrib=i; + startAttrib=i; + + // search for matching quote + while (i<(int)yyleng && c!='\'') { c=tagText.at(++i); } + endAttrib=i; if (i<(int)yyleng) { c=tagText.at(++i);} } else if (tagText.at(i)=='"') // option "..." { c=tagText.at(++i); - startAttrib=i; - // search for matching quote - while (i<(int)yyleng && c!='"') { c=tagText.at(++i); } - endAttrib=i; + startAttrib=i; + // search for matching quote + while (i<(int)yyleng && c!='"') { c=tagText.at(++i); } + endAttrib=i; if (i<(int)yyleng) { c=tagText.at(++i);} } else // value without any quotes { - startAttrib=i; - // search for separator or end symbol - while (i<(int)yyleng && !isspace((uchar)c) && c!='>') { c=tagText.at(++i); } - endAttrib=i; + startAttrib=i; + // search for separator or end symbol + while (i<(int)yyleng && !isspace((uchar)c) && c!='>') { c=tagText.at(++i); } + endAttrib=i; if (i<(int)yyleng) { c=tagText.at(++i);} } - opt.value = tagText.mid(startAttrib,endAttrib-startAttrib); + opt.value = tagText.mid(startAttrib,endAttrib-startAttrib); if (opt.name == "align") opt.value = opt.value.lower(); else if (opt.name == "valign") { @@ -296,7 +301,7 @@ static void handleHtmlTag() } g_token->attribsStr = tagText.mid(startAttribList,i-startAttribList); } - + static QCString stripEmptyLines(const QCString &s) { if (s.isEmpty()) return QCString(); @@ -307,11 +312,11 @@ static QCString stripEmptyLines(const QCString &s) { int c; while ((c=s[p]) && (c==' ' || c=='\t')) p++; - if (s[p]=='\n') + if (s[p]=='\n') { - start=++p; + start=++p; } - else + else { break; } @@ -323,7 +328,7 @@ static QCString stripEmptyLines(const QCString &s) { int c; while ((c=s[p]) && (c==' ' || c=='\t')) p--; - if (s[p]=='\n') + if (s[p]=='\n') { end=p; } @@ -337,6 +342,7 @@ static QCString stripEmptyLines(const QCString &s) return s.mid(start,end-start); } +#define unput_string(yytext,yyleng) do { for (int i=(int)yyleng-1;i>=0;i--) unput(yytext[i]); } while(0) //-------------------------------------------------------------------------- #undef YY_INPUT @@ -381,18 +387,18 @@ ATTRIB {ATTRNAME}{WS}*("="{WS}*(("\""[^\"]*"\"")|("'"[^\']*"'")|[^ \t\r\n'">< URLCHAR [a-z_A-Z0-9\!\~\,\:\;\'\$\?\@\&\%\#\.\-\+\/\=] URLMASK ({URLCHAR}+([({]{URLCHAR}*[)}])?)+ URLPROTOCOL ("http:"|"https:"|"ftp:"|"file:"|"news:"|"irc") -FILESCHAR [a-z_A-Z0-9\\:\\\/\-\+&#] -FILEECHAR [a-z_A-Z0-9\-\+&#] +FILESCHAR [a-z_A-Z0-9\\:\\\/\-\+&#@] +FILEECHAR [a-z_A-Z0-9\-\+&#@] HFILEMASK ("."{FILESCHAR}*{FILEECHAR}+)+ FILEMASK ({FILESCHAR}*{FILEECHAR}+("."{FILESCHAR}*{FILEECHAR}+)*)|{HFILEMASK} -LINKMASK [^ \t\n\r\\@<&${}]+("("[^\n)]*")")?({BLANK}*("const"|"volatile"){BLANK}+)? +LINKMASK [^ \t\n\r\\@<&${}]+("("[^\n)]*")")?({BLANK}*("const"|"volatile"){BLANK}+)? VERBATIM "verbatim"{BLANK}* SPCMD1 {CMD}([a-z_A-Z][a-z_A-Z0-9]*|{VERBATIM}|"--"|"---") SPCMD2 {CMD}[\\@<>&$#%~".+=|-] SPCMD3 {CMD}_form#[0-9]+ SPCMD4 {CMD}"::" SPCMD5 {CMD}":" -INOUT "in"|"out"|("in"{BLANK}*","?{BLANK}*"out")|("out"{BLANK}*","?{BLANK}*"in") +INOUT "in"|"out"|("in"{BLANK}*","?{BLANK}*"out")|("out"{BLANK}*","?{BLANK}*"in") PARAMIO {CMD}param{BLANK}*"["{BLANK}*{INOUT}{BLANK}*"]" VARARGS "..." TEMPCHAR [a-z_A-Z0-9.,: \t\*\&\(\)\[\]] @@ -427,7 +433,7 @@ WORD2 "."|","|"("|")"|"["|"]"|"::"|":"|";"|"\?"|"="|"'" WORD1NQ {ESCWORD}|{CHARWORDQ}+|"{"|"}" WORD2NQ "."|","|"("|")"|"["|"]"|"::"|":"|";"|"\?"|"="|"'" CAPTION [cC][aA][pP][tT][iI][oO][nN] -HTMLTAG "<"(("/")?){ID}({WS}+{ATTRIB})*{WS}*(("/")?)">" +HTMLTAG "<"(("/")?){ID}({WS}+{ATTRIB})*{WS}*(("/")?)">" HTMLKEYL "strong"|"center"|"table"|"caption"|"small"|"code"|"dfn"|"var"|"img"|"pre"|"sub"|"sup"|"tr"|"td"|"th"|"ol"|"ul"|"li"|"tt"|"kbd"|"em"|"hr"|"dl"|"dt"|"dd"|"br"|"i"|"a"|"b"|"p"|"strike"|"u"|"del"|"ins"|"s" HTMLKEYU "STRONG"|"CENTER"|"TABLE"|"CAPTION"|"SMALL"|"CODE"|"DFN"|"VAR"|"IMG"|"PRE"|"SUB"|"SUP"|"TR"|"TD"|"TH"|"OL"|"UL"|"LI"|"TT"|"KBD"|"EM"|"HR"|"DL"|"DT"|"DD"|"BR"|"I"|"A"|"B"|"P"|"STRIKE"|"U"|"DEL"|"INS"|"S" HTMLKEYW {HTMLKEYL}|{HTMLKEYU} @@ -439,9 +445,9 @@ REFWORD4_NOCV (({SCOPEPRE}*"operator"{OPMASKOP2})|(("::"|"#"){SCOPEPRE}*"operat REFWORD4 {REFWORD4_NOCV}{CVSPEC}? REFWORD {FILEMASK}|{LABELID}|{REFWORD2}|{REFWORD3}|{REFWORD4} REFWORD_NOCV {FILEMASK}|{LABELID}|{REFWORD2_NOCV}|{REFWORD3}|{REFWORD4_NOCV} +RCSID "$"("Author"|"Date"|"Header"|"Id"|"Locker"|"Log"|"Name"|"RCSfile"|"Revision"|"Source"|"State")":"[^:\n$][^\n$]*"$" %option noyywrap -%option yylineno %x St_Para %x St_Comment @@ -493,21 +499,23 @@ REFWORD_NOCV {FILEMASK}|{LABELID}|{REFWORD2_NOCV}|{REFWORD3}|{REFWORD4_NOCV} %% <St_Para>\r /* skip carriage return */ -<St_Para>^{LISTITEM} { /* list item */ +<St_Para>^{LISTITEM} { /* list item */ + lineCount(yytext,yyleng); QCString text=yytext; - int dashPos = text.findRev('-'); - g_token->isEnumList = text.at(dashPos+1)=='#'; + int dashPos = text.findRev('-'); + g_token->isEnumList = text.at(dashPos+1)=='#'; g_token->id = -1; - g_token->indent = computeIndent(yytext,dashPos); + g_token->indent = computeIndent(yytext,dashPos); return TK_LISTITEM; } -<St_Para>^{MLISTITEM} { /* list item */ +<St_Para>^{MLISTITEM} { /* list item */ if (!g_markdownSupport || g_insidePre) { REJECT; } else { + lineCount(yytext,yyleng); QCString text=yytext; static QRegExp re("[*+]"); int listPos = text.findRev(re); @@ -517,7 +525,7 @@ REFWORD_NOCV {FILEMASK}|{LABELID}|{REFWORD2_NOCV}|{REFWORD3}|{REFWORD4_NOCV} return TK_LISTITEM; } } -<St_Para>^{OLISTITEM} { /* numbered list item */ +<St_Para>^{OLISTITEM} { /* numbered list item */ if (!g_markdownSupport || g_insidePre) { REJECT; @@ -534,21 +542,23 @@ REFWORD_NOCV {FILEMASK}|{LABELID}|{REFWORD2_NOCV}|{REFWORD3}|{REFWORD4_NOCV} return TK_LISTITEM; } } -<St_Para>{BLANK}*(\n|"\\ilinebr"){LISTITEM} { /* list item on next line */ +<St_Para>{BLANK}*(\n|"\\ilinebr"){LISTITEM} { /* list item on next line */ + lineCount(yytext,yyleng); QCString text=extractPartAfterNewLine(yytext); - int dashPos = text.findRev('-'); - g_token->isEnumList = text.at(dashPos+1)=='#'; + int dashPos = text.findRev('-'); + g_token->isEnumList = text.at(dashPos+1)=='#'; g_token->id = -1; - g_token->indent = computeIndent(text,dashPos); + g_token->indent = computeIndent(text,dashPos); return TK_LISTITEM; } -<St_Para>{BLANK}*(\n|"\\ilinebr"){MLISTITEM} { /* list item on next line */ +<St_Para>{BLANK}*(\n|"\\ilinebr"){MLISTITEM} { /* list item on next line */ if (!g_markdownSupport || g_insidePre) { REJECT; } else { + lineCount(yytext,yyleng); QCString text=extractPartAfterNewLine(yytext); static QRegExp re("[*+]"); int markPos = text.findRev(re); @@ -558,13 +568,14 @@ REFWORD_NOCV {FILEMASK}|{LABELID}|{REFWORD2_NOCV}|{REFWORD3}|{REFWORD4_NOCV} return TK_LISTITEM; } } -<St_Para>{BLANK}*(\n|"\\ilinebr"){OLISTITEM} { /* list item on next line */ +<St_Para>{BLANK}*(\n|"\\ilinebr"){OLISTITEM} { /* list item on next line */ if (!g_markdownSupport || g_insidePre) { REJECT; } else { + lineCount(yytext,yyleng); QCString text=extractPartAfterNewLine(yytext); static QRegExp re("[1-9]"); int digitPos = text.find(re); @@ -575,41 +586,44 @@ REFWORD_NOCV {FILEMASK}|{LABELID}|{REFWORD2_NOCV}|{REFWORD3}|{REFWORD4_NOCV} return TK_LISTITEM; } } -<St_Para>^{ENDLIST} { /* end list */ +<St_Para>^{ENDLIST} { /* end list */ + lineCount(yytext,yyleng); int dotPos = QCString(yytext).findRev('.'); - g_token->indent = computeIndent(yytext,dotPos); + g_token->indent = computeIndent(yytext,dotPos); return TK_ENDLIST; } -<St_Para>{BLANK}*(\n|"\\ilinebr"){ENDLIST} { /* end list on next line */ +<St_Para>{BLANK}*(\n|"\\ilinebr"){ENDLIST} { /* end list on next line */ + lineCount(yytext,yyleng); QCString text=extractPartAfterNewLine(yytext); int dotPos = text.findRev('.'); - g_token->indent = computeIndent(text,dotPos); + g_token->indent = computeIndent(text,dotPos); return TK_ENDLIST; } <St_Para>"{"{BLANK}*"@link"/{BLANK}+ { - g_token->name = "javalink"; - return TK_COMMAND_AT; - } + g_token->name = "javalink"; + return TK_COMMAND_AT; + } <St_Para>"{"{BLANK}*"@inheritDoc"{BLANK}*"}" { - g_token->name = "inheritdoc"; - return TK_COMMAND_AT; - } + g_token->name = "inheritdoc"; + return TK_COMMAND_AT; + } <St_Para>"@_fakenl" { // artificial new line - yylineno++; - } + //g_yyLineNr++; + } <St_Para>{SPCMD3} { - g_token->name = "_form"; - bool ok; - g_token->id = QCString(yytext).right((int)yyleng-7).toInt(&ok); - ASSERT(ok); - return TK_COMMAND_SEL(); - } + g_token->name = "_form"; + bool ok; + g_token->id = QCString(yytext).right((int)yyleng-7).toInt(&ok); + ASSERT(ok); + return TK_COMMAND_SEL(); + } <St_Para>{CMD}"n"\n { /* \n followed by real newline */ - yylineno++; + lineCount(yytext,yyleng); + //g_yyLineNr++; g_token->name = yytext+1; - g_token->name = g_token->name.stripWhiteSpace(); - g_token->paramDir=TokenInfo::Unspecified; - return TK_COMMAND_SEL(); + g_token->name = g_token->name.stripWhiteSpace(); + g_token->paramDir=TokenInfo::Unspecified; + return TK_COMMAND_SEL(); } <St_Para>"\\ilinebr" { } @@ -618,108 +632,109 @@ REFWORD_NOCV {FILEMASK}|{LABELID}|{REFWORD2_NOCV}|{REFWORD3}|{REFWORD4_NOCV} <St_Para>{SPCMD5} | <St_Para>{SPCMD4} { /* special command */ g_token->name = yytext+1; - g_token->name = g_token->name.stripWhiteSpace(); - g_token->paramDir=TokenInfo::Unspecified; + g_token->name = g_token->name.stripWhiteSpace(); + g_token->paramDir=TokenInfo::Unspecified; return TK_COMMAND_SEL(); - } + } <St_Para>{PARAMIO} { /* param [in,out] command */ - g_token->name = "param"; - QCString s(yytext); - bool isIn = s.find("in")!=-1; - bool isOut = s.find("out")!=-1; - if (isIn) - { - if (isOut) - { - g_token->paramDir=TokenInfo::InOut; - } - else - { - g_token->paramDir=TokenInfo::In; - } - } - else if (isOut) - { - g_token->paramDir=TokenInfo::Out; - } - else - { - g_token->paramDir=TokenInfo::Unspecified; - } - return TK_COMMAND_SEL(); - } + g_token->name = "param"; + QCString s(yytext); + bool isIn = s.find("in")!=-1; + bool isOut = s.find("out")!=-1; + if (isIn) + { + if (isOut) + { + g_token->paramDir=TokenInfo::InOut; + } + else + { + g_token->paramDir=TokenInfo::In; + } + } + else if (isOut) + { + g_token->paramDir=TokenInfo::Out; + } + else + { + g_token->paramDir=TokenInfo::Unspecified; + } + return TK_COMMAND_SEL(); + } <St_Para>{URLPROTOCOL}{URLMASK}/[,\.] { // URL, or URL. g_token->name=yytext; - g_token->isEMailAddr=FALSE; - return TK_URL; + g_token->isEMailAddr=FALSE; + return TK_URL; } <St_Para>{URLPROTOCOL}{URLMASK} { // URL g_token->name=yytext; - g_token->isEMailAddr=FALSE; - return TK_URL; + g_token->isEMailAddr=FALSE; + return TK_URL; } <St_Para>"<"{URLPROTOCOL}{URLMASK}">" { // URL g_token->name=yytext; g_token->name = g_token->name.mid(1,g_token->name.length()-2); - g_token->isEMailAddr=FALSE; - return TK_URL; + g_token->isEMailAddr=FALSE; + return TK_URL; } <St_Para>{MAILADDR} { // Mail address g_token->name=yytext; g_token->name.stripPrefix("mailto:"); - g_token->isEMailAddr=TRUE; - return TK_URL; + g_token->isEMailAddr=TRUE; + return TK_URL; } <St_Para>"<"{MAILADDR}">" { // Mail address g_token->name=yytext; g_token->name = g_token->name.mid(1,g_token->name.length()-2); g_token->name.stripPrefix("mailto:"); - g_token->isEMailAddr=TRUE; - return TK_URL; + g_token->isEMailAddr=TRUE; + return TK_URL; } <St_Para>"<"{MAILADDR2}">" { // anti spam mail address g_token->name=yytext; - return TK_WORD; + return TK_WORD; } -<St_Para>"$"{ID}":"[^:\n$][^\n$]*"$" { /* RCS tag */ +<St_Para>{RCSID} { /* RCS tag */ QCString tagName(yytext+1); - int index=tagName.find(':'); - g_token->name = tagName.left(index); - int text_begin = index+2; - int text_end = tagName.length()-1; - if (tagName[text_begin-1]==':') /* check for Subversion fixed-length keyword */ - { - ++text_begin; - if (tagName[text_end-1]=='#') - --text_end; - } - g_token->text = tagName.mid(text_begin,text_end-text_begin); - return TK_RCSTAG; - } + int index=tagName.find(':'); + g_token->name = tagName.left(index); + int text_begin = index+2; + int text_end = tagName.length()-1; + if (tagName[text_begin-1]==':') /* check for Subversion fixed-length keyword */ + { + ++text_begin; + if (tagName[text_end-1]=='#') + --text_end; + } + g_token->text = tagName.mid(text_begin,text_end-text_begin); + return TK_RCSTAG; + } <St_Para,St_HtmlOnly,St_ManOnly,St_LatexOnly,St_RtfOnly,St_XmlOnly,St_DbOnly>"$("{ID}")" | /* environment variable */ <St_Para,St_HtmlOnly,St_ManOnly,St_LatexOnly,St_RtfOnly,St_XmlOnly,St_DbOnly>"$("{ID}"("{ID}"))" { /* environment variable */ QCString name = &yytext[2]; - name = name.left(name.length()-1); - QCString value = Portable::getenv(name); - for (int i=value.length()-1;i>=0;i--) unput(value.at(i)); + name = name.left(name.length()-1); + QCString value = Portable::getenv(name); + for (int i=value.length()-1;i>=0;i--) unput(value.at(i)); } -<St_Para>{HTMLTAG} { /* html tag */ +<St_Para>{HTMLTAG} { /* html tag */ + lineCount(yytext,yyleng); handleHtmlTag(); return TK_HTMLTAG; } -<St_Para,St_Text>"&"{ID}";" { /* special symbol */ +<St_Para,St_Text>"&"{ID}";" { /* special symbol */ g_token->name = yytext; return TK_SYMBOL; } /********* patterns for linkable words ******************/ -<St_Para>{ID}/"<"{HTMLKEYW}">" { /* this rule is to prevent opening html - * tag to be recognized as a templated classes - */ +<St_Para>{ID}/"<"{HTMLKEYW}">" { /* this rule is to prevent opening html + * tag to be recognized as a templated classes + */ g_token->name = yytext; return TK_LNKWORD; - } + } <St_Para>{LNKWORD1}/"<br>" | // prevent <br> html tag to be parsed as template arguments <St_Para>{LNKWORD1} | <St_Para>{LNKWORD1}{FUNCARG} | @@ -727,34 +742,35 @@ REFWORD_NOCV {FILEMASK}|{LABELID}|{REFWORD2_NOCV}|{REFWORD3}|{REFWORD4_NOCV} <St_Para>{LNKWORD3} { g_token->name = yytext; return TK_LNKWORD; - } + } <St_Para>{LNKWORD1}{FUNCARG}{CVSPEC}[^a-z_A-Z0-9] { g_token->name = yytext; g_token->name = g_token->name.left(g_token->name.length()-1); - unput(yytext[(int)yyleng-1]); + unput(yytext[(int)yyleng-1]); return TK_LNKWORD; } /********* patterns for normal words ******************/ <St_Para,St_Text>[\-+0-9] | <St_Para,St_Text>{WORD1} | -<St_Para,St_Text>{WORD2} { /* function call */ +<St_Para,St_Text>{WORD2} { /* function call */ + lineCount(yytext,yyleng); if (yytext[0]=='%') // strip % if present - g_token->name = &yytext[1]; - else + g_token->name = &yytext[1]; + else g_token->name = yytext; return TK_WORD; - /* the following is dummy code to please the - * compiler, removing this results in a warning - * on my machine - */ - goto find_rule; + /* the following is dummy code to please the + * compiler, removing this results in a warning + * on my machine + */ + goto find_rule; } <St_Text>({ID}".")+{ID} { g_token->name = yytext; return TK_WORD; - } + } <St_Para,St_Text>"operator"/{BLANK}*"<"[a-zA-Z_0-9]+">" { // Special case: word "operator" followed by a HTML command // avoid interpretation as "operator <" g_token->name = yytext; @@ -764,45 +780,58 @@ REFWORD_NOCV {FILEMASK}|{LABELID}|{REFWORD2_NOCV}|{REFWORD3}|{REFWORD4_NOCV} /*******************************************************/ <St_Para,St_Text>{BLANK}+ | -<St_Para,St_Text>{BLANK}*\n{BLANK}* { /* white space */ +<St_Para,St_Text>{BLANK}*\n{BLANK}* { /* white space */ + lineCount(yytext,yyleng); g_token->chars=yytext; return TK_WHITESPACE; } <St_Text>[\\@<>&$#%~] { g_token->name = yytext; return TK_COMMAND_SEL(); - } + } <St_Para>({BLANK}*\n)+{BLANK}*\n/{LISTITEM} { /* skip trailing paragraph followed by new list item */ if (g_insidePre || g_autoListLevel==0) { REJECT; } + lineCount(yytext,yyleng); } <St_Para>({BLANK}*\n)+{BLANK}*\n/{MLISTITEM} { /* skip trailing paragraph followed by new list item */ if (!g_markdownSupport || g_insidePre || g_autoListLevel==0) { REJECT; } + lineCount(yytext,yyleng); } <St_Para>({BLANK}*\n)+{BLANK}*\n/{OLISTITEM} { /* skip trailing paragraph followed by new list item */ if (!g_markdownSupport || g_insidePre || g_autoListLevel==0) { REJECT; } + lineCount(yytext,yyleng); } <St_Para>({BLANK}*\n)+{BLANK}*\n{BLANK}* { - g_token->indent=computeIndent(yytext,(int)yyleng); - int i; - // put back the indentation (needed for list items) - for (i=0;i<g_token->indent;i++) + lineCount(yytext,yyleng); + if (g_insidePre) + { + g_token->chars=yytext; + return TK_WHITESPACE; + } + else { - unput(' '); + g_token->indent=computeIndent(yytext,(int)yyleng); + int i; + // put back the indentation (needed for list items) + for (i=0;i<g_token->indent;i++) + { + unput(' '); + } + // tell flex that after putting the last indent + // back we are at the beginning of the line + YY_CURRENT_BUFFER->yy_at_bol=1; + // start of a new paragraph + return TK_NEWPARA; } - // tell flex that after putting the last indent - // back we are at the beginning of the line - YY_CURRENT_BUFFER->yy_at_bol=1; - // start of a new paragraph - return TK_NEWPARA; } <St_CodeOpt>{BLANK}*"{"(".")?{LABELID}"}" { g_token->name = yytext; @@ -813,20 +842,23 @@ REFWORD_NOCV {FILEMASK}|{LABELID}|{REFWORD2_NOCV}|{REFWORD3}|{REFWORD4_NOCV} <St_CodeOpt>"\\ilinebr" | <St_CodeOpt>\n | <St_CodeOpt>. { - for (int i=yyleng-1;i>=0;i--) unput(yytext[i]); + unput_string(yytext,yyleng); BEGIN(St_Code); } <St_Code>{WS}*{CMD}"endcode" { + lineCount(yytext,yyleng); return RetVal_OK; } <St_XmlCode>{WS}*"</code>" { + lineCount(yytext,yyleng); return RetVal_OK; } <St_Code,St_XmlCode>[^\\@\n<]+ | <St_Code,St_XmlCode>\n | <St_Code,St_XmlCode>. { - g_token->verb+=yytext; - } + lineCount(yytext,yyleng); + g_token->verb+=yytext; + } <St_HtmlOnlyOption>" [block]" { // the space is added in commentscan.l g_token->name="block"; BEGIN(St_HtmlOnly); @@ -836,7 +868,7 @@ REFWORD_NOCV {FILEMASK}|{LABELID}|{REFWORD2_NOCV}|{REFWORD3}|{REFWORD4_NOCV} BEGIN(St_HtmlOnly); } <St_HtmlOnlyOption>"\\ilinebr" { - for (int i=yyleng-1;i>=0;i--) unput(yytext[i]); + unput_string(yytext,yyleng); BEGIN(St_HtmlOnly); } <St_HtmlOnly>{CMD}"endhtmlonly" { @@ -845,77 +877,86 @@ REFWORD_NOCV {FILEMASK}|{LABELID}|{REFWORD2_NOCV}|{REFWORD3}|{REFWORD4_NOCV} <St_HtmlOnly>[^\\@\n$]+ | <St_HtmlOnly>\n | <St_HtmlOnly>. { - g_token->verb+=yytext; - } + lineCount(yytext,yyleng); + g_token->verb+=yytext; + } <St_ManOnly>{CMD}"endmanonly" { return RetVal_OK; } <St_ManOnly>[^\\@\n$]+ | <St_ManOnly>\n | <St_ManOnly>. { - g_token->verb+=yytext; - } + lineCount(yytext,yyleng); + g_token->verb+=yytext; + } <St_RtfOnly>{CMD}"endrtfonly" { return RetVal_OK; } <St_RtfOnly>[^\\@\n$]+ | <St_RtfOnly>\n | <St_RtfOnly>. { - g_token->verb+=yytext; - } + lineCount(yytext,yyleng); + g_token->verb+=yytext; + } <St_LatexOnly>{CMD}"endlatexonly" { return RetVal_OK; } <St_LatexOnly>[^\\@\n]+ | <St_LatexOnly>\n | <St_LatexOnly>. { - g_token->verb+=yytext; - } + lineCount(yytext,yyleng); + g_token->verb+=yytext; + } <St_XmlOnly>{CMD}"endxmlonly" { return RetVal_OK; } <St_XmlOnly>[^\\@\n]+ | <St_XmlOnly>\n | <St_XmlOnly>. { - g_token->verb+=yytext; - } + lineCount(yytext,yyleng); + g_token->verb+=yytext; + } <St_DbOnly>{CMD}"enddocbookonly" { return RetVal_OK; } <St_DbOnly>[^\\@\n]+ | <St_DbOnly>\n | <St_DbOnly>. { - g_token->verb+=yytext; - } + lineCount(yytext,yyleng); + g_token->verb+=yytext; + } <St_Verbatim>{CMD}"endverbatim" { - g_token->verb=stripEmptyLines(g_token->verb); + g_token->verb=stripEmptyLines(g_token->verb); return RetVal_OK; } <St_Verbatim>[^\\@\n]+ | <St_Verbatim>\n | <St_Verbatim>. { /* Verbatim text */ - g_token->verb+=yytext; - } + lineCount(yytext,yyleng); + g_token->verb+=yytext; + } <St_Dot>{CMD}"enddot" { return RetVal_OK; } <St_Dot>[^\\@\n]+ | <St_Dot>\n | <St_Dot>. { /* dot text */ - g_token->verb+=yytext; - } + lineCount(yytext,yyleng); + g_token->verb+=yytext; + } <St_Msc>{CMD}("endmsc") { return RetVal_OK; } <St_Msc>[^\\@\n]+ | <St_Msc>\n | <St_Msc>. { /* msc text */ - g_token->verb+=yytext; - } + lineCount(yytext,yyleng); + g_token->verb+=yytext; + } <St_PlantUMLOpt>{BLANK}*"{"[^}]*"}" { // case 1: file name is specified as {filename} g_token->sectionId = QCString(yytext).stripWhiteSpace(); // skip curly brackets around the optional image name - g_token->sectionId = g_token->sectionId.mid(1,g_token->sectionId.length()-2).stripWhiteSpace(); + g_token->sectionId = g_token->sectionId.mid(1,g_token->sectionId.length()-2).stripWhiteSpace(); return RetVal_OK; } <St_PlantUMLOpt>{BLANK}*{FILEMASK}{BLANK}+/{ID}"=" { // case 2: plain file name specified followed by an attribute @@ -938,7 +979,7 @@ REFWORD_NOCV {FILEMASK}|{LABELID}|{REFWORD2_NOCV}|{REFWORD3}|{REFWORD4_NOCV} <St_PlantUMLOpt>"\n" | <St_PlantUMLOpt>. { g_token->sectionId = ""; - for (int i=yyleng-1;i>=0;i--) unput(yytext[i]); + unput_string(yytext,yyleng); return RetVal_OK; } <St_PlantUML>{CMD}"enduml" { @@ -947,117 +988,126 @@ REFWORD_NOCV {FILEMASK}|{LABELID}|{REFWORD2_NOCV}|{REFWORD3}|{REFWORD4_NOCV} <St_PlantUML>[^\\@\n]+ | <St_PlantUML>\n | <St_PlantUML>. { /* plantuml text */ - g_token->verb+=yytext; - } -<St_Title>"\"" { // quoted title - BEGIN(St_TitleQ); - } + lineCount(yytext,yyleng); + g_token->verb+=yytext; + } +<St_Title>"\"" { // quoted title + BEGIN(St_TitleQ); + } <St_Title>[ \t]+ { g_token->chars=yytext; - return TK_WHITESPACE; + return TK_WHITESPACE; } -<St_Title>. { // non-quoted title - unput(*yytext); - BEGIN(St_TitleN); +<St_Title>. { // non-quoted title + unput(*yytext); + BEGIN(St_TitleN); } -<St_Title>\n { +<St_Title>\n { unput(*yytext); - return 0; - } + return 0; + } <St_Title>"\\ilinebr" { - for (int i=yyleng-1;i>=0;i--) unput(yytext[i]); - return 0; + unput_string(yytext,yyleng); + return 0; } <St_TitleN>"&"{ID}";" { /* symbol */ g_token->name = yytext; - return TK_SYMBOL; + return TK_SYMBOL; } <St_TitleN>{HTMLTAG} { - } -<St_TitleN>(\n|"\\ilinebr") { /* new line => end of title */ - for (int i=yyleng-1;i>=0;i--) unput(yytext[i]); - return 0; + lineCount(yytext,yyleng); + } +<St_TitleN>\n { /* new line => end of title */ + unput(*yytext); + return 0; } -<St_TitleN>{SPCMD1} | -<St_TitleN>{SPCMD2} { /* special command */ +<St_TitleN>"\\ilinebr" { /* new line => end of title */ + unput_string(yytext,yyleng); + return 0; + } +<St_TitleN>{SPCMD1} | +<St_TitleN>{SPCMD2} { /* special command */ g_token->name = yytext+1; - g_token->paramDir=TokenInfo::Unspecified; + g_token->paramDir=TokenInfo::Unspecified; return TK_COMMAND_SEL(); } <St_TitleN>{ID}"=" { /* attribute */ if (yytext[0]=='%') // strip % if present - g_token->name = &yytext[1]; - else + g_token->name = &yytext[1]; + else g_token->name = yytext; - return TK_WORD; + return TK_WORD; } <St_TitleN>[\-+0-9] | <St_TitleN>{WORD1} | <St_TitleN>{WORD2} { /* word */ + lineCount(yytext,yyleng); if (yytext[0]=='%') // strip % if present - g_token->name = &yytext[1]; - else + g_token->name = &yytext[1]; + else g_token->name = yytext; - return TK_WORD; + return TK_WORD; } <St_TitleN>[ \t]+ { g_token->chars=yytext; - return TK_WHITESPACE; + return TK_WHITESPACE; } <St_TitleQ>"&"{ID}";" { /* symbol */ g_token->name = yytext; - return TK_SYMBOL; + return TK_SYMBOL; } <St_TitleQ>(\n|"\\ilinebr") { /* new line => end of title */ - for (int i=yyleng-1;i>=0;i--) unput(yytext[i]); - return 0; + unput_string(yytext,yyleng); + return 0; } -<St_TitleQ>{SPCMD1} | -<St_TitleQ>{SPCMD2} { /* special command */ +<St_TitleQ>{SPCMD1} | +<St_TitleQ>{SPCMD2} { /* special command */ g_token->name = yytext+1; - g_token->paramDir=TokenInfo::Unspecified; + g_token->paramDir=TokenInfo::Unspecified; return TK_COMMAND_SEL(); } <St_TitleQ>{WORD1NQ} | <St_TitleQ>{WORD2NQ} { /* word */ g_token->name = yytext; - return TK_WORD; + return TK_WORD; } <St_TitleQ>[ \t]+ { g_token->chars=yytext; - return TK_WHITESPACE; + return TK_WHITESPACE; } -<St_TitleQ>"\"" { /* closing quote => end of title */ - BEGIN(St_TitleA); - return 0; +<St_TitleQ>"\"" { /* closing quote => end of title */ + BEGIN(St_TitleA); + return 0; } <St_TitleA>{BLANK}*{ID}{BLANK}*"="{BLANK}* { // title attribute - g_token->name = yytext; - g_token->name = g_token->name.left(g_token->name.find('=')).stripWhiteSpace(); - BEGIN(St_TitleV); - } + g_token->name = yytext; + g_token->name = g_token->name.left(g_token->name.find('=')).stripWhiteSpace(); + BEGIN(St_TitleV); + } <St_TitleV>[^ \t\r\n]+ { // attribute value - g_token->chars = yytext; - BEGIN(St_TitleN); - return TK_WORD; - } + lineCount(yytext,yyleng); + g_token->chars = yytext; + BEGIN(St_TitleN); + return TK_WORD; + } <St_TitleV,St_TitleA>. { - unput(*yytext); - return 0; + unput(*yytext); + return 0; } <St_TitleV,St_TitleA>(\n|"\\ilinebr") { - for (int i=yyleng-1;i>=0;i--) unput(yytext[i]); - return 0; + unput_string(yytext,yyleng); + return 0; } <St_Anchor>{LABELID}{WS}? { // anchor - g_token->name = QCString(yytext).stripWhiteSpace(); - return TK_WORD; - } -<St_Anchor>. { - unput(*yytext); - return 0; - } + lineCount(yytext,yyleng); + g_token->name = QCString(yytext).stripWhiteSpace(); + return TK_WORD; + } +<St_Anchor>. { + unput(*yytext); + return 0; + } <St_Cite>{CITEID} { // label to cite if (yytext[0] =='"') { @@ -1068,59 +1118,60 @@ REFWORD_NOCV {FILEMASK}|{LABELID}|{REFWORD2_NOCV}|{REFWORD3}|{REFWORD4_NOCV} { g_token->name=yytext; } - return TK_WORD; - } + return TK_WORD; + } <St_Cite>{BLANK} { // white space - unput(' '); - return 0; + unput(' '); + return 0; } <St_Cite>(\n|"\\ilinebr") { // new line - for (int i=yyleng-1;i>=0;i--) unput(yytext[i]); - return 0; - } -<St_Cite>. { // any other character + unput_string(yytext,yyleng); + return 0; + } +<St_Cite>. { // any other character unput(*yytext); - return 0; - } + return 0; + } <St_Ref>{REFWORD_NOCV}/{BLANK}("const")[a-z_A-Z0-9] { // see bug776988 - g_token->name=yytext; - return TK_WORD; + g_token->name=yytext; + return TK_WORD; } <St_Ref>{REFWORD_NOCV}/{BLANK}("volatile")[a-z_A-Z0-9] { // see bug776988 - g_token->name=yytext; - return TK_WORD; + g_token->name=yytext; + return TK_WORD; } <St_Ref>{REFWORD} { // label to refer to - g_token->name=yytext; - return TK_WORD; - } + g_token->name=yytext; + return TK_WORD; + } <St_Ref>{BLANK} { // white space - unput(' '); - return 0; + unput(' '); + return 0; } <St_Ref>{WS}+"\""{WS}* { // white space following by quoted string - BEGIN(St_Ref2); + lineCount(yytext,yyleng); + BEGIN(St_Ref2); } <St_Ref>(\n|"\\ilinebr") { // new line - for (int i=yyleng-1;i>=0;i--) unput(yytext[i]); - return 0; - } -<St_Ref>. { // any other character + unput_string(yytext,yyleng); + return 0; + } +<St_Ref>. { // any other character unput(*yytext); - return 0; - } + return 0; + } <St_IntRef>[A-Z_a-z0-9.:/#\-\+\(\)]+ { g_token->name = yytext; - return TK_WORD; - } + return TK_WORD; + } <St_IntRef>{BLANK}+"\"" { BEGIN(St_Ref2); } <St_SetScope>({SCOPEMASK}|{ANONNS}){BLANK}|{FILEMASK} { g_token->name = yytext; g_token->name = g_token->name.stripWhiteSpace(); - return TK_WORD; - } + return TK_WORD; + } <St_SetScope>{SCOPEMASK}"<" { g_token->name = yytext; g_token->name = g_token->name.stripWhiteSpace(); @@ -1146,26 +1197,27 @@ REFWORD_NOCV {FILEMASK}|{LABELID}|{REFWORD2_NOCV}|{REFWORD3}|{REFWORD4_NOCV} } <St_Ref2>"&"{ID}";" { /* symbol */ g_token->name = yytext; - return TK_SYMBOL; + return TK_SYMBOL; } <St_Ref2>"\""|\n|"\\ilinebr" { /* " or \n => end of title */ - return 0; + lineCount(yytext,yyleng); + return 0; } -<St_Ref2>{SPCMD1} | -<St_Ref2>{SPCMD2} { /* special command */ +<St_Ref2>{SPCMD1} | +<St_Ref2>{SPCMD2} { /* special command */ g_token->name = yytext+1; - g_token->paramDir=TokenInfo::Unspecified; + g_token->paramDir=TokenInfo::Unspecified; return TK_COMMAND_SEL(); } <St_Ref2>{WORD1NQ} | <St_Ref2>{WORD2NQ} { /* word */ g_token->name = yytext; - return TK_WORD; + return TK_WORD; } <St_Ref2>[ \t]+ { g_token->chars=yytext; - return TK_WHITESPACE; + return TK_WHITESPACE; } <St_XRefItem>{LABELID} { g_token->name=yytext; @@ -1174,39 +1226,41 @@ REFWORD_NOCV {FILEMASK}|{LABELID}|{REFWORD2_NOCV}|{REFWORD3}|{REFWORD4_NOCV} BEGIN(St_XRefItem2); } <St_XRefItem2>[0-9]+"." { - QCString numStr=yytext; - numStr=numStr.left((int)yyleng-1); - g_token->id=numStr.toInt(); - return RetVal_OK; - } + QCString numStr=yytext; + numStr=numStr.left((int)yyleng-1); + g_token->id=numStr.toInt(); + return RetVal_OK; + } <St_Para,St_Title,St_Ref2>"<!--" { /* html style comment block */ g_commentState = YY_START; - BEGIN(St_Comment); + BEGIN(St_Comment); } <St_Param>"\""[^\n\"]+"\"" { - g_token->name = yytext+1; - g_token->name = g_token->name.left((int)yyleng-2); - return TK_WORD; + g_token->name = yytext+1; + g_token->name = g_token->name.left((int)yyleng-2); + return TK_WORD; } <St_Param>({PHPTYPE}{BLANK}*("["{BLANK}*"]")*{BLANK}*"|"{BLANK}*)*{PHPTYPE}{BLANK}*("["{BLANK}*"]")*{WS}+("&")?"$"{LABELID} { - QCString params = yytext; - int j = params.find('&'); - int i = params.find('$'); - if (j<i && j!=-1) i=j; - QCString types = params.left(i).stripWhiteSpace(); - g_token->name = types+"#"+params.mid(i); - return TK_WORD; - } + lineCount(yytext,yyleng); + QCString params = yytext; + int j = params.find('&'); + int i = params.find('$'); + if (j<i && j!=-1) i=j; + QCString types = params.left(i).stripWhiteSpace(); + g_token->name = types+"#"+params.mid(i); + return TK_WORD; + } <St_Param>[^ \t\n,@\\]+ { - g_token->name = yytext; + g_token->name = yytext; if (g_token->name.at(static_cast<uint>(yyleng)-1)==':') { g_token->name=g_token->name.left(static_cast<uint>(yyleng)-1); } - return TK_WORD; + return TK_WORD; } <St_Param>{WS}*","{WS}* /* param separator */ -<St_Param>{WS} { +<St_Param>{WS} { + lineCount(yytext,yyleng); g_token->chars=yytext; return TK_WHITESPACE; } @@ -1215,6 +1269,7 @@ REFWORD_NOCV {FILEMASK}|{LABELID}|{REFWORD2_NOCV}|{REFWORD3}|{REFWORD4_NOCV} } <St_Options>{WS}*","{WS}* <St_Options>{WS} { /* option separator */ + lineCount(yytext,yyleng); g_token->name+=","; } <St_Options>"}" { @@ -1234,25 +1289,35 @@ REFWORD_NOCV {FILEMASK}|{LABELID}|{REFWORD2_NOCV}|{REFWORD3}|{REFWORD4_NOCV} return 0; } <St_File>{FILEMASK} { - g_token->name = yytext; - return TK_WORD; - } -<St_File>"\""[^\n\"]+"\"" { - QCString text=yytext; - g_token->name = text.mid(1,text.length()-2); - return TK_WORD; - } -<St_Pattern>[^\r\n]+ { g_token->name = yytext; + return TK_WORD; + } +<St_File>"\""[^\n\"]+"\"" { + QCString text=yytext; + g_token->name = text.mid(1,text.length()-2); + return TK_WORD; + } +<St_Pattern>[^\\\r\n]+ { + g_token->name += yytext; + } +<St_Pattern>"\\ilinebr" { g_token->name = g_token->name.stripWhiteSpace(); - return TK_WORD; - } + return TK_WORD; + } +<St_Pattern>\n { + lineCount(yytext,yyleng); + g_token->name = g_token->name.stripWhiteSpace(); + return TK_WORD; + } +<St_Pattern>. { + g_token->name += yytext; + } <St_Link>{LINKMASK}|{REFWORD} { g_token->name = yytext; - return TK_WORD; + return TK_WORD; } <St_Comment>"-->" { /* end of html comment */ - BEGIN(g_commentState); + BEGIN(g_commentState); } <St_Comment>[^-]+ /* inside html comment */ <St_Comment>. /* inside html comment */ @@ -1260,13 +1325,17 @@ REFWORD_NOCV {FILEMASK}|{LABELID}|{REFWORD2_NOCV}|{REFWORD3}|{REFWORD4_NOCV} /* State for skipping title (all chars until the end of the line) */ <St_SkipTitle>. -<St_SkipTitle>(\n|"\\ilinebr") { return 0; } +<St_SkipTitle>(\n|"\\ilinebr") { + lineCount(yytext,yyleng); + return 0; + } - /* State for the pass used to find the anchors and sections */ + /* State for the pass used to find the anchors and sections */ <St_Sections>[^\n@\\<]+ <St_Sections>{CMD}("<"|{CMD}) <St_Sections>"<"{CAPTION}({WS}+{ATTRIB})*">" { + lineCount(yytext,yyleng); QCString tag=yytext; int s=tag.find("id="); if (s!=-1) // command has id attribute @@ -1284,142 +1353,146 @@ REFWORD_NOCV {FILEMASK}|{LABELID}|{REFWORD2_NOCV}|{REFWORD3}|{REFWORD4_NOCV} } } } -<St_Sections>{CMD}"anchor"{BLANK}+ { - g_secType = SectionType::Anchor; - BEGIN(St_SecLabel1); +<St_Sections>{CMD}"anchor"{BLANK}+ { + g_secType = SectionType::Anchor; + BEGIN(St_SecLabel1); } -<St_Sections>{CMD}"section"{BLANK}+ { - g_secType = SectionType::Section; - BEGIN(St_SecLabel2); +<St_Sections>{CMD}"section"{BLANK}+ { + g_secType = SectionType::Section; + BEGIN(St_SecLabel2); } -<St_Sections>{CMD}"subsection"{BLANK}+ { - g_secType = SectionType::Subsection; - BEGIN(St_SecLabel2); +<St_Sections>{CMD}"subsection"{BLANK}+ { + g_secType = SectionType::Subsection; + BEGIN(St_SecLabel2); } -<St_Sections>{CMD}"subsubsection"{BLANK}+ { - g_secType = SectionType::Subsubsection; - BEGIN(St_SecLabel2); +<St_Sections>{CMD}"subsubsection"{BLANK}+ { + g_secType = SectionType::Subsubsection; + BEGIN(St_SecLabel2); } -<St_Sections>{CMD}"paragraph"{BLANK}+ { - g_secType = SectionType::Paragraph; - BEGIN(St_SecLabel2); +<St_Sections>{CMD}"paragraph"{BLANK}+ { + g_secType = SectionType::Paragraph; + BEGIN(St_SecLabel2); } <St_Sections>{CMD}"verbatim"/[^a-z_A-Z0-9] { g_endMarker="endverbatim"; - BEGIN(St_SecSkip); - } + BEGIN(St_SecSkip); + } <St_Sections>{CMD}"dot"/[^a-z_A-Z0-9] { g_endMarker="enddot"; - BEGIN(St_SecSkip); - } + BEGIN(St_SecSkip); + } <St_Sections>{CMD}"msc"/[^a-z_A-Z0-9] { g_endMarker="endmsc"; - BEGIN(St_SecSkip); - } + BEGIN(St_SecSkip); + } <St_Sections>{CMD}"startuml"/[^a-z_A-Z0-9] { g_endMarker="enduml"; - BEGIN(St_SecSkip); - } + BEGIN(St_SecSkip); + } <St_Sections>{CMD}"htmlonly"/[^a-z_A-Z0-9] { g_endMarker="endhtmlonly"; - BEGIN(St_SecSkip); + BEGIN(St_SecSkip); } <St_Sections>{CMD}"latexonly"/[^a-z_A-Z0-9] { g_endMarker="endlatexonly"; - BEGIN(St_SecSkip); + BEGIN(St_SecSkip); } <St_Sections>{CMD}"manonly"/[^a-z_A-Z0-9] { g_endMarker="endmanonly"; - BEGIN(St_SecSkip); + BEGIN(St_SecSkip); } <St_Sections>{CMD}"rtfonly"/[^a-z_A-Z0-9] { g_endMarker="endrtfonly"; - BEGIN(St_SecSkip); + BEGIN(St_SecSkip); } <St_Sections>{CMD}"xmlonly"/[^a-z_A-Z0-9] { g_endMarker="endxmlonly"; - BEGIN(St_SecSkip); + BEGIN(St_SecSkip); } <St_Sections>{CMD}"docbookonly"/[^a-z_A-Z0-9] { g_endMarker="enddocbookonly"; - BEGIN(St_SecSkip); + BEGIN(St_SecSkip); } <St_Sections>{CMD}"code"/[^a-z_A-Z0-9] { g_endMarker="endcode"; - BEGIN(St_SecSkip); - } + BEGIN(St_SecSkip); + } <St_Sections>"<!--" { g_endMarker="-->"; - BEGIN(St_SecSkip); + BEGIN(St_SecSkip); } -<St_SecSkip>{CMD}{ID} { +<St_SecSkip>{CMD}{ID} { if (qstrcmp(yytext+1,g_endMarker)==0) - { - BEGIN(St_Sections); - } + { + BEGIN(St_Sections); + } } -<St_SecSkip>"-->" { +<St_SecSkip>"-->" { if (qstrcmp(yytext,g_endMarker)==0) - { - BEGIN(St_Sections); - } + { + BEGIN(St_Sections); + } } <St_SecSkip>[^a-z_A-Z0-9\-\\\@]+ <St_SecSkip>. <St_SecSkip>(\n|"\\ilinebr") <St_Sections>. <St_Sections>(\n|"\\ilinebr") -<St_SecLabel1>{LABELID} { +<St_SecLabel1>{LABELID} { + lineCount(yytext,yyleng); g_secLabel = yytext; processSection(); BEGIN(St_Sections); } -<St_SecLabel2>{LABELID}{BLANK}+ | -<St_SecLabel2>{LABELID} { +<St_SecLabel2>{LABELID}{BLANK}+ | +<St_SecLabel2>{LABELID} { g_secLabel = yytext; - g_secLabel = g_secLabel.stripWhiteSpace(); + g_secLabel = g_secLabel.stripWhiteSpace(); BEGIN(St_SecTitle); } <St_SecTitle>[^\n]+ | <St_SecTitle>[^\n]*\n { + lineCount(yytext,yyleng); g_secTitle = yytext; - g_secTitle = g_secTitle.stripWhiteSpace(); + g_secTitle = g_secTitle.stripWhiteSpace(); if (g_secTitle.right(8)=="\\ilinebr") { g_secTitle.left(g_secTitle.length()-8); } processSection(); BEGIN(St_Sections); - } + } <St_SecTitle,St_SecLabel1,St_SecLabel2>. { - warn(g_fileName,yylineno,"Unexpected character '%s' while looking for section label or title",yytext); + warn(g_fileName,g_yyLineNr,"Unexpected character '%s' while looking for section label or title",yytext); } <St_Snippet>[^\\\n]+ { - g_token->name += yytext; + g_token->name += yytext; } <St_Snippet>"\\" { - g_token->name += yytext; + g_token->name += yytext; } <St_Snippet>(\n|"\\ilinebr") { - g_token->name = g_token->name.stripWhiteSpace(); - return TK_WORD; - } - - /* Generic rules that work for all states */ -<*>\n { - warn(g_fileName,yylineno,"Unexpected new line character"); - } + lineCount(yytext,yyleng); + g_token->name = g_token->name.stripWhiteSpace(); + return TK_WORD; + } + + /* Generic rules that work for all states */ +<*>\n { + lineCount(yytext,yyleng); + warn(g_fileName,g_yyLineNr,"Unexpected new line character"); + } <*>"\\ilinebr" { } <*>[\\@<>&$#%~"=] { /* unescaped special character */ - //warn(g_fileName,yylineno,"Unexpected character '%s', assuming command \\%s was meant.",yytext,yytext); - g_token->name = yytext; - return TK_COMMAND_SEL(); + //warn(g_fileName,g_yyLineNr,"Unexpected character '%s', assuming command \\%s was meant.",yytext,yytext); + g_token->name = yytext; + return TK_COMMAND_SEL(); + } +<*>. { + warn(g_fileName,g_yyLineNr,"Unexpected character '%s'",yytext); } -<*>. { - warn(g_fileName,yylineno,"Unexpected character '%s'",yytext); - } %% //-------------------------------------------------------------------------- @@ -1435,7 +1508,7 @@ void doctokenizerYYFindSections(const char *input,const Definition *d, g_definition = d; g_fileName = fileName; BEGIN(St_Sections); - doctokenizerYYlineno = 1; + g_yyLineNr = 1; doctokenizerYYlex(); printlex(yy_flex_debug, FALSE, __FILE__, fileName); } @@ -1565,6 +1638,7 @@ void doctokenizerYYsetStateFile() void doctokenizerYYsetStatePattern() { + g_token->name = ""; BEGIN(St_Pattern); } @@ -1672,6 +1746,17 @@ void doctokenizerYYendAutoList() // return retval; //} +void setDoctokinizerLineNr(int lineno) +{ + g_yyLineNr = lineno; +} + +int getDoctokinizerLineNr(void) +{ + return g_yyLineNr; +} + + #if USE_STATE2STRING #include "doctokenizer.l.h" #endif diff --git a/src/docvisitor.cpp b/src/docvisitor.cpp new file mode 100644 index 0000000..d46d8c0 --- /dev/null +++ b/src/docvisitor.cpp @@ -0,0 +1,58 @@ +/****************************************************************************** + * + * Copyright (C) 1997-2020 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 <unordered_map> + +#include "parserintf.h" +#include "docvisitor.h" +#include "util.h" +#include "types.h" +#include "doxygen.h" + +struct DocVisitor::Private +{ + int id; + std::unordered_map< std::string, std::unique_ptr<CodeParserInterface> > parserFactoryMap; +}; + +DocVisitor::DocVisitor(int id) : m_p(std::make_unique<Private>()) +{ + m_p->id = id; +} + +DocVisitor::~DocVisitor() +{ +} + +CodeParserInterface &DocVisitor::getCodeParser(const char *extension) +{ + std::string ext(extension?extension:""); + // for each extension we create a code parser once per visitor, so that + // the context of the same parser object is reused throughout multiple passes for instance + // for code fragments shown via dontinclude. + auto it = m_p->parserFactoryMap.find(ext); + if (it==m_p->parserFactoryMap.end()) + { + auto factory = Doxygen::parserManager->getCodeParserFactory(extension); + auto result = m_p->parserFactoryMap.insert(std::make_pair(ext,factory())); + it = result.first; + } + return *it->second.get(); +} + +int DocVisitor::id() const +{ + return m_p->id; +} diff --git a/src/docvisitor.h b/src/docvisitor.h index 0a53595..4d4b263 100644 --- a/src/docvisitor.h +++ b/src/docvisitor.h @@ -1,13 +1,10 @@ /****************************************************************************** * - * - * - * - * Copyright (C) 1997-2015 by Dimitri van Heesch. + * Copyright (C) 1997-2020 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. * @@ -19,6 +16,8 @@ #ifndef _DOCVISITOR_H #define _DOCVISITOR_H +#include <memory> + // ids const int DocVisitor_Html = 0; const int DocVisitor_Latex = 1; @@ -84,18 +83,21 @@ class DocSimpleSectSep; class DocHtmlBlockQuote; class DocVhdlFlow; class DocParBlock; +class CodeParserInterface; /*! @brief Abstract visitor that participates in the visitor pattern. */ class DocVisitor { - int m_id; + struct Private; + std::unique_ptr<Private> m_p; public: - DocVisitor(int id) : m_id(id) {} - virtual ~DocVisitor() {} - int id() const { return m_id; } + DocVisitor(int id); + virtual ~DocVisitor(); + int id() const; + CodeParserInterface &getCodeParser(const char *langExt); - /*! @name Visitor functions for leaf nodes + /*! @name Visitor functions for leaf nodes * @{ */ virtual void visit(DocWord *) = 0; @@ -117,7 +119,7 @@ class DocVisitor virtual void visit(DocCite *) = 0; /*! @} */ - /*! @name Visitor functions for internal nodes + /*! @name Visitor functions for internal nodes * @{ */ virtual void visitPre(DocAutoList *) = 0; @@ -167,7 +169,7 @@ class DocVisitor virtual void visitPre(DocDotFile *) = 0; virtual void visitPost(DocDotFile *) = 0; virtual void visitPre(DocMscFile *) = 0; - virtual void visitPost(DocMscFile *) = 0; + virtual void visitPost(DocMscFile *) = 0; virtual void visitPre(DocDiaFile *) = 0; virtual void visitPost(DocDiaFile *) = 0; virtual void visitPre(DocLink *) = 0; diff --git a/src/dotcallgraph.cpp b/src/dotcallgraph.cpp index 5e13f8e..cbd62ef 100644 --- a/src/dotcallgraph.cpp +++ b/src/dotcallgraph.cpp @@ -1,6 +1,6 @@ /****************************************************************************** * -* Copyright (C) 1997-2019 by Dimitri van Heesch. +* Copyright (C) 1997-2020 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 @@ -20,10 +20,6 @@ #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) - static QCString getUniqueId(const MemberDef *md) { QCString result = md->getReference()+"$"+ @@ -34,51 +30,45 @@ static QCString getUniqueId(const MemberDef *md) void DotCallGraph::buildGraph(DotNode *n,const MemberDef *md,int distance) { - MemberSDict *refs = m_inverse ? md->getReferencedByMembers() : md->getReferencesMembers(); - if (refs) + auto refs = m_inverse ? md->getReferencedByMembers() : md->getReferencesMembers(); + for (const auto &rmd : refs) { - refs->sort(); - MemberSDict::Iterator mri(*refs); - MemberDef *rmd; - for (;(rmd=mri.current());++mri) + if (rmd->showInCallGraph()) { - if (rmd->showInCallGraph()) + QCString uniqueId = getUniqueId(rmd); + 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 uniqueId = getUniqueId(rmd); - DotNode *bn = m_usedNodes->find(uniqueId); - if (bn) // file is already a node in the graph + QCString name; + if (Config_getBool(HIDE_SCOPE_NAMES)) { - n->addChild(bn,0,0,0); - bn->addParent(n); - bn->setDistance(distance); + name = rmd->getOuterScope()==m_scope ? + rmd->name() : rmd->qualifiedName(); } 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( + 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); + ); + n->addChild(bn,0,0,0); + bn->addParent(n); + bn->setDistance(distance); + m_usedNodes->insert(uniqueId,bn); - buildGraph(bn,rmd,distance+1); - } + buildGraph(bn,rmd,distance+1); } } } @@ -89,7 +79,7 @@ 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 + if (!n->isVisible() && n->distance()<=Config_getInt(MAX_DOT_GRAPH_DEPTH)) // not yet processed { n->markAsVisible(); maxNodes--; @@ -121,9 +111,9 @@ void DotCallGraph::determineTruncatedNodes(QList<DotNode> &queue) const DotNode *dn; for (li.toFirst();(dn=li.current());++li) { - if (!dn->isVisible()) + if (!dn->isVisible()) truncated = TRUE; - else + else queue.append(dn); } } @@ -139,7 +129,7 @@ DotCallGraph::DotCallGraph(const MemberDef *md,bool inverse) m_scope = md->getOuterScope(); QCString uniqueId = getUniqueId(md); QCString name; - if (HIDE_SCOPE_NAMES) + if (Config_getBool(HIDE_SCOPE_NAMES)) { name = md->name(); } @@ -159,7 +149,7 @@ DotCallGraph::DotCallGraph(const MemberDef *md,bool inverse) m_usedNodes->insert(uniqueId,m_startNode); buildGraph(m_startNode,md,1); - int maxNodes = DOT_GRAPH_MAX_NODES; + int maxNodes = Config_getInt(DOT_GRAPH_MAX_NODES); QList<DotNode> openNodeQueue; openNodeQueue.append(m_startNode); determineVisibleNodes(openNodeQueue,maxNodes); @@ -198,7 +188,7 @@ QCString DotCallGraph::getMapLabel() const } QCString DotCallGraph::writeGraph( - FTextStream &out, + FTextStream &out, GraphOutputFormat graphFormat, EmbeddedOutputFormat textFormat, const char *path, @@ -216,7 +206,7 @@ bool DotCallGraph::isTrivial() const bool DotCallGraph::isTooBig() const { - return numNodes()>=DOT_GRAPH_MAX_NODES; + return numNodes()>=Config_getInt(DOT_GRAPH_MAX_NODES); } int DotCallGraph::numNodes() const diff --git a/src/dotclassgraph.cpp b/src/dotclassgraph.cpp index 84b7962..4077d5b 100644 --- a/src/dotclassgraph.cpp +++ b/src/dotclassgraph.cpp @@ -20,12 +20,6 @@ #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) { @@ -71,7 +65,7 @@ void DotClassGraph::addClass(const ClassDef *cd,DotNode *n,int prot, else // new class { QCString displayName=className; - if (HIDE_SCOPE_NAMES) displayName=stripScope(displayName); + if (Config_getBool(HIDE_SCOPE_NAMES)) displayName=stripScope(displayName); QCString tmp_url; if (cd->isLinkable() && !cd->isHidden()) { @@ -162,7 +156,7 @@ bool DotClassGraph::determineVisibleNodes(DotNode *rootNode, { DotNode *n = childQueue.take(0); int distance = n->distance(); - if (!n->isVisible() && distance<=MAX_DOT_GRAPH_DEPTH) // not yet processed + if (!n->isVisible() && distance<=Config_getInt(MAX_DOT_GRAPH_DEPTH)) // not yet processed { if (distance>0) { @@ -191,7 +185,7 @@ bool DotClassGraph::determineVisibleNodes(DotNode *rootNode, if (includeParents && parentQueue.count()>0) { DotNode *n = parentQueue.take(0); - if ((!n->isVisible() || firstNode) && n->distance()<=MAX_DOT_GRAPH_DEPTH) // not yet processed + if ((!n->isVisible() || firstNode) && n->distance()<=Config_getInt(MAX_DOT_GRAPH_DEPTH)) // not yet processed { firstNode=FALSE; int distance = n->distance(); @@ -220,7 +214,7 @@ bool DotClassGraph::determineVisibleNodes(DotNode *rootNode, } } } - if (UML_LOOK) return FALSE; // UML graph are always top to bottom + 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; @@ -266,18 +260,11 @@ void DotClassGraph::buildGraph(const ClassDef *cd,DotNode *n,bool base,int dista if (m_graphType == Inheritance || m_graphType==Collaboration) { - BaseClassList *bcl = base ? cd->baseClasses() : cd->subClasses(); - if (bcl) + for (const auto &bcd : base ? cd->baseClasses() : cd->subClasses()) { - 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); - } + //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) @@ -300,7 +287,7 @@ void DotClassGraph::buildGraph(const ClassDef *cd,DotNode *n,bool base,int dista } } } - if (TEMPLATE_RELATIONS && base) + if (Config_getBool(TEMPLATE_RELATIONS) && base) { ConstraintClassDict *dict = cd->templateTypeConstraints(); if (dict) @@ -318,7 +305,7 @@ void DotClassGraph::buildGraph(const ClassDef *cd,DotNode *n,bool base,int dista // ---- Add template instantiation relations - if (TEMPLATE_RELATIONS) + if (Config_getBool(TEMPLATE_RELATIONS)) { if (base) // template relations for base classes { @@ -383,7 +370,7 @@ DotClassGraph::DotClassGraph(const ClassDef *cd,GraphType t) 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); + m_lrRank = determineVisibleNodes(m_startNode,Config_getInt(DOT_GRAPH_MAX_NODES),t==Inheritance); QList<DotNode> openNodeQueue; openNodeQueue.append(m_startNode); determineTruncatedNodes(openNodeQueue,t==Inheritance); @@ -397,12 +384,12 @@ 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; + return !Config_getBool(UML_LOOK) && m_startNode->children()==0; } bool DotClassGraph::isTooBig() const { - return numNodes()>=DOT_GRAPH_MAX_NODES; + return numNodes()>=Config_getInt(DOT_GRAPH_MAX_NODES); } int DotClassGraph::numNodes() const diff --git a/src/dotfilepatcher.cpp b/src/dotfilepatcher.cpp index 17f8cb7..285c0bb 100644 --- a/src/dotfilepatcher.cpp +++ b/src/dotfilepatcher.cpp @@ -174,6 +174,7 @@ static QCString replaceRef(const QCString &buf,const QCString relPath, if (!ref.isEmpty()) { result = externalLinkTarget(true); + if (!result.isEmpty())targetAlreadySet=true; } result+= href+"=\""; result+=externalRef(relPath,ref,TRUE); @@ -460,7 +461,7 @@ bool DotFilePatcher::run() const convertMapFile(tt,map->mapFile,map->relPath,map->urlOnly,map->context); if (!result.isEmpty()) { - t << "<map name=\"" << map->label << "\" id=\"" << correctId(map->label) << "\">" << endl; + t << "<map name=\"" << correctId(map->label) << "\" id=\"" << correctId(map->label) << "\">" << endl; t << result; t << "</map>" << endl; } diff --git a/src/dotgfxhierarchytable.cpp b/src/dotgfxhierarchytable.cpp index 3d56de8..a47cde0 100644 --- a/src/dotgfxhierarchytable.cpp +++ b/src/dotgfxhierarchytable.cpp @@ -21,8 +21,6 @@ #include "doxygen.h" #include "classlist.h" -#define OPTIMIZE_OUTPUT_SLICE Config_getBool(OPTIMIZE_OUTPUT_SLICE) - QCString DotGfxHierarchyTable::getBaseName() const { QCString baseName; @@ -35,22 +33,19 @@ QCString DotGfxHierarchyTable::getBaseName() const 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) + for (auto node : m_rootNodes) { - if (node->subgraphId()==m_rootSubgraphNode->subgraphId()) + if (node->subgraphId()==m_rootSubgraphNode->subgraphId()) { node->clearWriteFlag(); } } - for (dnli2.toFirst();(node=dnli2.current());++dnli2) + for (auto node : m_rootNodes) { - if (node->subgraphId()==m_rootSubgraphNode->subgraphId()) + if (node->subgraphId()==m_rootSubgraphNode->subgraphId()) { node->write(md5stream,Hierarchy,GOF_BITMAP,FALSE,TRUE,TRUE); } @@ -80,7 +75,7 @@ void DotGfxHierarchyTable::writeGraph(FTextStream &out, //printf("DotGfxHierarchyTable::writeGraph(%s)\n",name); //printf("m_rootNodes=%p count=%d\n",m_rootNodes,m_rootNodes->count()); - if (m_rootSubgraphs->count()==0) return; + if (m_rootSubgraphs.empty()) return; QDir d(path); // store the original directory @@ -92,10 +87,10 @@ void DotGfxHierarchyTable::writeGraph(FTextStream &out, // 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) + std::sort(m_rootSubgraphs.begin(),m_rootSubgraphs.end(), + [](auto n1,auto n2) { return qstricmp(n1->label(),n2->label())<0; }); + for (auto n : m_rootSubgraphs) { out << "<tr><td>"; createGraph(n,out,path,fileName,count++); @@ -104,81 +99,79 @@ void DotGfxHierarchyTable::writeGraph(FTextStream &out, out << "</table>" << endl; } -void DotGfxHierarchyTable::addHierarchy(DotNode *n,const ClassDef *cd,bool hideSuper) +void DotGfxHierarchyTable::addHierarchy(DotNode *n,const ClassDef *cd,ClassDefSet &visitedClasses) { //printf("addHierarchy '%s' baseClasses=%d\n",cd->name().data(),cd->baseClasses()->count()); - if (cd->subClasses()) + for (const auto &bcd : 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 && bClass->isVisibleInHierarchy() && hasVisibleRoot(bClass->baseClasses())) { - ClassDef *bClass=bcd->classDef; - //printf(" Trying sub class='%s' usedNodes=%d\n",bClass->name().data(),m_usedNodes->count()); - if (bClass->isVisibleInHierarchy() && hasVisibleRoot(bClass->baseClasses())) + auto it = m_usedNodes.find(bClass->name().str()); + //printf(" Node '%s' Found visible class='%s'\n",n->label().data(), + // bClass->name().data()); + DotNode *root = 0; + if (it!=m_usedNodes.end()) // node already present { - 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 + const auto &bn = it->second; + if (n->children()==0 || n->children()->findRef(bn.get())==-1) // no arrow yet { - 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"); - //} + n->addChild(bn.get(),bcd.prot); + bn->addParent(n); + root = bn.get(); + //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 + //else + //{ + // printf(" Class already has an arrow!\n"); + //} + } + else + { + QCString tmp_url=""; + if (bClass->isLinkable() && !bClass->isHidden()) { - QCString tmp_url=""; - if (bClass->isLinkable() && !bClass->isHidden()) + tmp_url=bClass->getReference()+"$"+bClass->getOutputFileBase(); + if (!bClass->anchor().isEmpty()) { - tmp_url=bClass->getReference()+"$"+bClass->getOutputFileBase(); - if (!bClass->anchor().isEmpty()) - { - tmp_url+="#"+bClass->anchor(); - } + tmp_url+="#"+bClass->anchor(); } - QCString tooltip = bClass->briefDescriptionAsTooltip(); - bn = new DotNode(getNextNodeNumber(), + } + QCString tooltip = bClass->briefDescriptionAsTooltip(); + auto bn = std::make_unique<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); - } + ); + n->addChild(bn.get(),bcd.prot); + bn->addParent(n); + root = bn.get(); + //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(std::make_pair(bClass->name().str(),std::move(bn))); // add node to the used list + } + if (visitedClasses.find(bClass)==visitedClasses.end() && !bClass->subClasses().empty()) + { + visitedClasses.insert(bClass); + addHierarchy(root,bClass,visitedClasses); } } } //printf("end addHierarchy\n"); } -void DotGfxHierarchyTable::addClassList(const ClassSDict *cl) +void DotGfxHierarchyTable::addClassList(const ClassSDict *cl,ClassDefSet &visitedClasses) { ClassSDict::Iterator cli(*cl); ClassDef *cd; @@ -191,7 +184,7 @@ void DotGfxHierarchyTable::addClassList(const ClassSDict *cl) { continue; } - if (OPTIMIZE_OUTPUT_SLICE && cd->compoundType() != m_classType) + if (Config_getBool(OPTIMIZE_OUTPUT_SLICE) && cd->compoundType() != m_classType) { continue; } @@ -200,7 +193,7 @@ void DotGfxHierarchyTable::addClassList(const ClassSDict *cl) ) // root node in the forest { QCString tmp_url=""; - if (cd->isLinkable() && !cd->isHidden()) + if (cd->isLinkable() && !cd->isHidden()) { tmp_url=cd->getReference()+"$"+cd->getOutputFileBase(); if (!cd->anchor().isEmpty()) @@ -210,18 +203,18 @@ void DotGfxHierarchyTable::addClassList(const ClassSDict *cl) } //printf("Inserting root class %s\n",cd->name().data()); QCString tooltip = cd->briefDescriptionAsTooltip(); - DotNode *n = new DotNode(getNextNodeNumber(), + auto n = std::make_unique<DotNode>(getNextNodeNumber(), cd->displayName(), tooltip, tmp_url.data()); + DotNode *root = n.get(); - //m_usedNodes->clear(); - m_usedNodes->insert(cd->name(),n); - m_rootNodes->insert(0,n); - if (!cd->isVisited() && cd->subClasses()) + m_usedNodes.insert(std::make_pair(cd->name().str(),std::move(n))); + m_rootNodes.push_back(root); + if (visitedClasses.find(cd)==visitedClasses.end() && !cd->subClasses().empty()) { - addHierarchy(n,cd,cd->isVisited()); - cd->setVisited(TRUE); + addHierarchy(root,cd,visitedClasses); + visitedClasses.insert(cd); } } } @@ -231,28 +224,20 @@ DotGfxHierarchyTable::DotGfxHierarchyTable(const char *prefix,ClassDef::Compound : 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); + ClassDefSet visitedClasses; + addClassList(Doxygen::classSDict,visitedClasses); + addClassList(Doxygen::hiddenClasses,visitedClasses); // m_usedNodes now contains all nodes in the graph // color the graph into a set of independent subgraphs - bool done=FALSE; + 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) + for (auto n : m_rootNodes) { if (n->subgraphId()==-1) // not yet colored { @@ -263,18 +248,16 @@ DotGfxHierarchyTable::DotGfxHierarchyTable(const char *prefix,ClassDef::Compound n->colorConnectedNodes(curColor); curColor++; const DotNode *dn=n->findDocNode(); - if (dn!=0) - m_rootSubgraphs->inSort(dn); + if (dn!=0) + m_rootSubgraphs.push_back(const_cast<DotNode*>(dn)); else - m_rootSubgraphs->inSort(n); + m_rootSubgraphs.push_back(n); } } } //printf("Number of independent subgraphs: %d\n",curColor); - QListIterator<DotNode> dnli2(*m_rootSubgraphs); - DotNode *n; - for (dnli2.toFirst();(n=dnli2.current());++dnli2) + for (auto n : m_rootSubgraphs) { //printf("Node %s color=%d (c=%d,p=%d)\n", // n->label().data(),n->m_subgraphId, @@ -285,18 +268,3 @@ DotGfxHierarchyTable::DotGfxHierarchyTable(const char *prefix,ClassDef::Compound } } -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 index 5a5bcad..0d884bd 100644 --- a/src/dotgfxhierarchytable.h +++ b/src/dotgfxhierarchytable.h @@ -16,6 +16,11 @@ #ifndef DOTGFXHIERARCHYTABLE_H #define DOTGFXHIERARCHYTABLE_H +#include <memory> +#include <string> +#include <unordered_map> +#include <vector> + #include "classdef.h" #include "ftextstream.h" @@ -27,11 +32,10 @@ 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; } + const std::vector<DotNode*> subGraphs() const { return m_rootSubgraphs; } protected: virtual QCString getBaseName() const; @@ -39,15 +43,16 @@ class DotGfxHierarchyTable : public DotGraph virtual void computeTheGraph(); private: - void addHierarchy(DotNode *n,const ClassDef *cd,bool hide); - void addClassList(const ClassSDict *cl); + void addHierarchy(DotNode *n,const ClassDef *cd,ClassDefSet &visited); + void addClassList(const ClassSDict *cl,ClassDefSet &visited); + using DotNodeMap = std::unordered_multimap< std::string, std::unique_ptr<DotNode> >; int m_graphId; QCString m_prefix; ClassDef::CompoundType m_classType; - QList<DotNode> *m_rootNodes; - QDict<DotNode> *m_usedNodes; - DotNodeList *m_rootSubgraphs; + std::vector<DotNode*> m_rootNodes; + DotNodeMap m_usedNodes; + std::vector<DotNode*> m_rootSubgraphs; DotNode * m_rootSubgraphNode; }; diff --git a/src/dotgraph.cpp b/src/dotgraph.cpp index 1ad85e1..287793e 100644 --- a/src/dotgraph.cpp +++ b/src/dotgraph.cpp @@ -239,7 +239,7 @@ void DotGraph::generateCode(FTextStream &t) t << "<img src=\"" << relImgName() << "\" border=\"0\" usemap=\"#" << correctId(getMapLabel()) << "\" alt=\"" << getImgAltText() << "\"/>"; if (!m_noDivTag) t << "</div>"; t << endl; - if (m_regenerate || !insertMapFile(t, absMapName(), m_relPath, getMapLabel())) + if (m_regenerate || !insertMapFile(t, absMapName(), m_relPath, correctId(getMapLabel()))) { int mapId = DotManager::instance()-> createFilePatcher(m_fileName.data())-> diff --git a/src/dotgroupcollaboration.cpp b/src/dotgroupcollaboration.cpp index 8121657..db6bd23 100644 --- a/src/dotgroupcollaboration.cpp +++ b/src/dotgroupcollaboration.cpp @@ -23,8 +23,6 @@ #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(); @@ -379,7 +377,7 @@ void DotGroupCollaboration::writeGraphHeader(FTextStream &t,const QCString &titl } t << endl; t << "{" << endl; - if (DOT_TRANSPARENT) + if (Config_getBool(DOT_TRANSPARENT)) { t << " bgcolor=\"transparent\";" << endl; } diff --git a/src/dotnode.cpp b/src/dotnode.cpp index c02827f..8ce1bb3 100644 --- a/src/dotnode.cpp +++ b/src/dotnode.cpp @@ -148,9 +148,25 @@ static void writeBoxMemberList(FTextStream &t, else { t << prot << " "; - t << DotNode::convertLabel(mma->name()); - if (!mma->isObjCMethod() && - (mma->isFunction() || mma->isSlot() || mma->isSignal())) t << "()"; + QCString label; + if(Config_getBool(DOT_UML_DETAILS)) + { + label+=mma->typeString(); + label+=" "; + } + label+=mma->name(); + if (!mma->isObjCMethod() && (mma->isFunction() || mma->isSlot() || mma->isSignal())) + { + if(Config_getBool(DOT_UML_DETAILS)) + { + label+=mma->argsString(); + } + else + { + label+="()"; + } + } + t << DotNode::convertLabel(label); t << "\\l"; count++; } @@ -185,7 +201,7 @@ QCString DotNode::convertLabel(const QCString &l) int len=p.length(); int charsLeft=len; int sinceLast=0; - int foldLen=17; // ideal text length + int foldLen = Config_getInt(DOT_WRAP_THRESHOLD); // ideal text length while (idx < p.length()) { c = p[idx++]; diff --git a/src/doxygen.cpp b/src/doxygen.cpp index d551292..4667cba 100644 --- a/src/doxygen.cpp +++ b/src/doxygen.cpp @@ -32,6 +32,7 @@ #include <algorithm> #include <unordered_map> #include <memory> +#include <cinttypes> #include "version.h" #include "doxygen.h" @@ -105,6 +106,7 @@ #include "stlsupport.h" #include "threadpool.h" #include "clangparser.h" +#include "symbolresolver.h" // provided by the generated file resources.cpp extern void initResources(); @@ -138,14 +140,14 @@ StringUnorderedSet Doxygen::expandAsDefinedSet; // all macros that should be exp QIntDict<MemberGroupInfo> Doxygen::memGrpInfoDict(1009); // dictionary of the member groups heading PageDef *Doxygen::mainPage = 0; bool Doxygen::insideMainPage = FALSE; // are we generating docs for the main page? -NamespaceDef *Doxygen::globalScope = 0; +NamespaceDefMutable *Doxygen::globalScope = 0; bool Doxygen::parseSourcesNeeded = FALSE; SearchIndexIntf *Doxygen::searchIndex=0; -QDict<DefinitionIntf> *Doxygen::symbolMap = 0; +SymbolMap<Definition> Doxygen::symbolMap; QDict<Definition> *Doxygen::clangUsrMap = 0; bool Doxygen::outputToWizard=FALSE; QDict<int> * Doxygen::htmlDirMap = 0; -QCache<LookupInfo> *Doxygen::lookupCache; +Cache<std::string,LookupInfo> *Doxygen::lookupCache; DirSDict *Doxygen::directories; SDict<DirRelation> Doxygen::dirRelations(257); ParserManager *Doxygen::parserManager = 0; @@ -164,7 +166,7 @@ DefinesPerFileList Doxygen::macroDefinitions; bool Doxygen::clangAssistedParsing = FALSE; // locally accessible globals -static std::unordered_map< std::string, const Entry* > g_classEntries; +static std::multimap< std::string, const Entry* > g_classEntries; static StringVector g_inputFiles; static QDict<void> g_compoundKeywordDict(7); // keywords recognised as compounds static OutputList *g_outputList = 0; // list of output generating objects @@ -274,7 +276,7 @@ void statistics() -static void addMemberDocs(const Entry *root,MemberDef *md, const char *funcDecl, +static void addMemberDocs(const Entry *root,MemberDefMutable *md, const char *funcDecl, const ArgumentList *al,bool over_load,uint64 spec); static void findMember(const Entry *root, const QCString &relates, @@ -295,7 +297,7 @@ enum FindBaseClassRelation_Mode static bool findClassRelation( const Entry *root, Definition *context, - ClassDef *cd, + ClassDefMutable *cd, const BaseInfo *bi, QDict<int> *templateNames, /*bool insertUndocumented*/ @@ -305,7 +307,7 @@ static bool findClassRelation( //---------------------------------------------------------------------------- -static Definition *findScopeFromQualifiedName(Definition *startScope,const QCString &n, +static Definition *findScopeFromQualifiedName(NamespaceDefMutable *startScope,const QCString &n, FileDef *fileScope,const TagInfo *tagInfo); static void addPageToContext(PageDef *pd,Entry *root) @@ -346,7 +348,9 @@ static void addRelatedPage(Entry *root) } PageDef *pd = addRelatedPage(root->name,root->args,doc, - root->docFile,root->docLine, + root->docFile, + root->docLine, + root->startLine, root->sli, gd,root->tagInfo(), FALSE, @@ -554,7 +558,7 @@ static void buildFileList(const Entry *root) for (const auto &e : root->children()) buildFileList(e.get()); } -static void addIncludeFile(ClassDef *cd,FileDef *ifd,const Entry *root) +static void addIncludeFile(ClassDefMutable *cd,FileDef *ifd,const Entry *root) { if ( (!root->doc.stripWhiteSpace().isEmpty() || @@ -729,26 +733,26 @@ static Definition *buildScopeFromQualifiedName(const QCString name, if (!fullScope.isEmpty()) fullScope+="::"; fullScope+=nsName; NamespaceDef *nd=Doxygen::namespaceSDict->find(fullScope); - Definition *innerScope = nd; + DefinitionMutable *innerScope = toDefinitionMutable(nd); ClassDef *cd=0; if (nd==0) cd = getClass(fullScope); if (nd==0 && cd) // scope is a class { - innerScope = cd; + innerScope = toDefinitionMutable(cd); } else if (nd==0 && cd==0 && fullScope.find('<')==-1) // scope is not known and could be a namespace! { // introduce bogus namespace //printf("++ adding dummy namespace %s to %s tagInfo=%p\n",nsName.data(),prevScope->name().data(),tagInfo); - nd=createNamespaceDef( + NamespaceDefMutable *newNd=createNamespaceDef( "[generated]",1,1,fullScope, tagInfo?tagInfo->tagName:QCString(), tagInfo?tagInfo->fileName:QCString()); - nd->setLanguage(lang); + newNd->setLanguage(lang); // add namespace to the list - Doxygen::namespaceSDict->inSort(fullScope,nd); - innerScope = nd; + Doxygen::namespaceSDict->inSort(fullScope,newNd); + innerScope = newNd; } else // scope is a namespace { @@ -756,7 +760,11 @@ static Definition *buildScopeFromQualifiedName(const QCString name, if (innerScope) { // make the parent/child scope relation - prevScope->addInnerCompound(innerScope); + DefinitionMutable *prevScopeMutable = toDefinitionMutable(prevScope); + if (prevScopeMutable) + { + prevScopeMutable->addInnerCompound(toDefinition(innerScope)); + } innerScope->setOuterScope(prevScope); } else // current scope is a class, so return only the namespace part... @@ -765,17 +773,17 @@ static Definition *buildScopeFromQualifiedName(const QCString name, } // proceed to the next scope fragment p=idx+l+2; - prevScope=innerScope; + prevScope=toDefinition(innerScope); i++; } return prevScope; } -static Definition *findScopeFromQualifiedName(Definition *startScope,const QCString &n, +static Definition *findScopeFromQualifiedName(NamespaceDefMutable *startScope,const QCString &n, FileDef *fileScope,const TagInfo *tagInfo) { //printf("<findScopeFromQualifiedName(%s,%s)\n",startScope ? startScope->name().data() : 0, n.data()); - Definition *resultScope=startScope; + Definition *resultScope=toDefinition(startScope); if (resultScope==0) resultScope=Doxygen::globalScope; QCString scope=stripTemplateSpecifiersFromScope(n,FALSE); int l1=0,i1; @@ -791,21 +799,17 @@ static Definition *findScopeFromQualifiedName(Definition *startScope,const QCStr QCString nestedNameSpecifier = scope.mid(i1,l1); Definition *orgScope = resultScope; //printf(" nestedNameSpecifier=%s\n",nestedNameSpecifier.data()); - resultScope = resultScope->findInnerCompound(nestedNameSpecifier); + resultScope = const_cast<Definition*>(resultScope->findInnerCompound(nestedNameSpecifier)); //printf(" resultScope=%p\n",resultScope); if (resultScope==0) { - NamespaceSDict *usedNamespaces; - if (orgScope==Doxygen::globalScope && fileScope && - (usedNamespaces = fileScope->getUsedNamespaces())) + if (orgScope==Doxygen::globalScope && fileScope && !fileScope->getUsedNamespaces().empty()) // also search for used namespaces { - NamespaceSDict::Iterator ni(*usedNamespaces); - NamespaceDef *nd; - for (ni.toFirst();((nd=ni.current()) && resultScope==0);++ni) + for (const auto &nd : fileScope->getUsedNamespaces()) { - // restart search within the used namespace - resultScope = findScopeFromQualifiedName(nd,n,fileScope,tagInfo); + resultScope = findScopeFromQualifiedName(toNamespaceDefMutable(nd),n,fileScope,tagInfo); + if (resultScope!=0) break; } if (resultScope) { @@ -970,10 +974,10 @@ static void addClassToContext(const Entry *root) } // see if we already found the class before - ClassDef *cd = getClass(qualifiedName); + ClassDefMutable *cd = getClassMutable(qualifiedName); - Debug::print(Debug::Classes,0, " Found class with name %s (qualifiedName=%s -> cd=%p)\n", - cd ? qPrint(cd->name()) : qPrint(root->name), qPrint(qualifiedName),cd); + //Debug::print(Debug::Classes,0, " Found class with name %s (qualifiedName=%s -> cd=%p)\n", + // cd ? qPrint(cd->name()) : qPrint(root->name), qPrint(qualifiedName),cd); if (cd) { @@ -1149,7 +1153,7 @@ static void buildClassDocList(const Entry *root) static void resolveClassNestingRelations() { ClassSDict::Iterator cli(*Doxygen::classSDict); - for (cli.toFirst();cli.current();++cli) cli.current()->setVisited(FALSE); + ClassDefSet visitedClasses; bool done=FALSE; int iteration=0; @@ -1157,38 +1161,46 @@ static void resolveClassNestingRelations() { done=TRUE; ++iteration; - ClassDef *cd=0; - for (cli.toFirst();(cd=cli.current());++cli) + ClassDef *icd=0; + for (cli.toFirst();(icd=cli.current());++cli) { - if (!cd->isVisited()) + ClassDefMutable *cd = toClassDefMutable(icd); + if (cd && visitedClasses.find(icd)==visitedClasses.end()) { - QCString name = stripAnonymousNamespaceScope(cd->name()); + QCString name = stripAnonymousNamespaceScope(icd->name()); //printf("processing=%s, iteration=%d\n",cd->name().data(),iteration); // also add class to the correct structural context Definition *d = findScopeFromQualifiedName(Doxygen::globalScope, - name,cd->getFileDef(),0); + name,icd->getFileDef(),0); if (d) { //printf("****** adding %s to scope %s in iteration %d\n",cd->name().data(),d->name().data(),iteration); - d->addInnerCompound(cd); + DefinitionMutable *dm = toDefinitionMutable(d); + if (dm) + { + dm->addInnerCompound(cd); + } cd->setOuterScope(d); // for inline namespace add an alias of the class to the outer scope - while (d->definitionType()==DefinitionIntf::TypeNamespace) + while (d->definitionType()==Definition::TypeNamespace) { - NamespaceDef *nd = dynamic_cast<NamespaceDef*>(d); - //printf("d->isInline()=%d\n",nd->isInline()); - if (nd->isInline()) + NamespaceDef *nd = toNamespaceDef(d); + //printf("nd->isInline()=%d\n",nd->isInline()); + if (nd && 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); + dm = toDefinitionMutable(d); + if (dm) + { + ClassDef *aliasCd = createClassDefAlias(d,cd); + dm->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)); + } } } else @@ -1197,7 +1209,7 @@ static void resolveClassNestingRelations() } } - cd->setVisited(TRUE); + visitedClasses.insert(icd); done=FALSE; } //else @@ -1209,22 +1221,27 @@ static void resolveClassNestingRelations() } //give warnings for unresolved compounds - ClassDef *cd=0; - for (cli.toFirst();(cd=cli.current());++cli) + ClassDef *icd=0; + for (cli.toFirst();(icd=cli.current());++cli) { - if (!cd->isVisited()) + ClassDefMutable *cd = toClassDefMutable(icd); + if (cd && visitedClasses.find(icd)==visitedClasses.end()) { QCString name = stripAnonymousNamespaceScope(cd->name()); //printf("processing unresolved=%s, iteration=%d\n",cd->name().data(),iteration); /// create the scope artificially // anyway, so we can at least relate scopes properly. Definition *d = buildScopeFromQualifiedName(name,name.contains("::"),cd->getLanguage(),0); - if (d!=cd && !cd->getDefFileName().isEmpty()) + if (d && d!=cd && !cd->getDefFileName().isEmpty()) // avoid recursion in case of redundant scopes, i.e: namespace N { class N::C {}; } // for this case doxygen assumes the existence of a namespace N::N in which C is to be found! // also avoid warning for stuff imported via a tagfile. { - d->addInnerCompound(cd); + DefinitionMutable *dm = toDefinitionMutable(d); + if (dm) + { + dm->addInnerCompound(cd); + } cd->setOuterScope(d); warn(cd->getDefFileName(),cd->getDefLine(), "Internal inconsistency: scope for class %s not " @@ -1241,15 +1258,15 @@ void distributeClassGroupRelations() //if (!inlineGroupedClasses) return; //printf("** distributeClassGroupRelations()\n"); + ClassDefSet visitedClasses; ClassSDict::Iterator cli(*Doxygen::classSDict); - for (cli.toFirst();cli.current();++cli) cli.current()->setVisited(FALSE); - ClassDef *cd; for (cli.toFirst();(cd=cli.current());++cli) { //printf("Checking %s\n",cd->name().data()); // distribute the group to nested classes as well - if (!cd->isVisited() && cd->partOfGroups()!=0 && cd->getClassSDict()) + if (cd && visitedClasses.find(cd)==visitedClasses.end() && + cd->partOfGroups()!=0 && cd->getClassSDict()) { //printf(" Candidate for merging\n"); ClassSDict::Iterator ncli(*cd->getClassSDict()); @@ -1257,27 +1274,28 @@ void distributeClassGroupRelations() GroupDef *gd = cd->partOfGroups()->at(0); for (ncli.toFirst();(ncd=ncli.current());++ncli) { - if (ncd->partOfGroups()==0) + ClassDefMutable *ncdm = toClassDefMutable(ncd); + if (ncdm && ncdm->partOfGroups()==0) { //printf(" Adding %s to group '%s'\n",ncd->name().data(), // gd->groupTitle()); - ncd->makePartOfGroup(gd); - gd->addClass(ncd); + ncdm->makePartOfGroup(gd); + gd->addClass(ncdm); } } - cd->setVisited(TRUE); // only visit every class once + visitedClasses.insert(cd); // only visit every class once } } } //---------------------------- -static ClassDef *createTagLessInstance(ClassDef *rootCd,ClassDef *templ,const QCString &fieldName) +static ClassDefMutable *createTagLessInstance(ClassDef *rootCd,ClassDef *templ,const QCString &fieldName) { QCString fullName = removeAnonymousScopes(templ->name()); if (fullName.right(2)=="::") fullName=fullName.left(fullName.length()-2); fullName+="."+fieldName; - ClassDef *cd = createClassDef(templ->getDefFileName(), + ClassDefMutable *cd = createClassDef(templ->getDefFileName(), templ->getDefLine(), templ->getDefColumn(), fullName, @@ -1291,7 +1309,11 @@ static ClassDef *createTagLessInstance(ClassDef *rootCd,ClassDef *templ,const QC cd->setOuterScope(rootCd->getOuterScope()); if (rootCd->getOuterScope()!=Doxygen::globalScope) { - rootCd->getOuterScope()->addInnerCompound(cd); + DefinitionMutable *outerScope = toDefinitionMutable(rootCd->getOuterScope()); + if (outerScope) + { + outerScope->addInnerCompound(cd); + } } FileDef *fd = templ->getFileDef(); @@ -1322,7 +1344,7 @@ static ClassDef *createTagLessInstance(ClassDef *rootCd,ClassDef *templ,const QC for (li.toFirst();(md=li.current());++li) { //printf(" Member %s type=%s\n",md->name().data(),md->typeString()); - MemberDef *imd = createMemberDef(md->getDefFileName(),md->getDefLine(),md->getDefColumn(), + MemberDefMutable *imd = createMemberDef(md->getDefFileName(),md->getDefLine(),md->getDefColumn(), md->typeString(),md->name(),md->argsString(),md->excpString(), md->protection(),md->virtualness(),md->isStatic(),Member, md->memberType(), @@ -1354,12 +1376,12 @@ static ClassDef *createTagLessInstance(ClassDef *rootCd,ClassDef *templ,const QC */ static void processTagLessClasses(ClassDef *rootCd, ClassDef *cd, - ClassDef *tagParentCd, + ClassDefMutable *tagParentCd, const QCString &prefix,int count) { //printf("%d: processTagLessClasses %s\n",count,cd->name().data()); //printf("checking members for %s\n",cd->name().data()); - if (cd->getClassSDict()) + if (tagParentCd && cd->getClassSDict()) { MemberList *ml = cd->getMemberList(MemberListType_pubAttribs); if (ml) @@ -1380,10 +1402,10 @@ static void processTagLessClasses(ClassDef *rootCd, if (type.find(icd->name())!=-1) // matching tag less struct/union { QCString name = md->name(); - if (md->isAnonymous()) name = "__unnamed__"; + if (md->isAnonymous()) name = "__unnamed" + name.right(name.length()-1)+"__"; if (!prefix.isEmpty()) name.prepend(prefix+"."); //printf(" found %s for class %s\n",name.data(),cd->name().data()); - ClassDef *ncd = createTagLessInstance(rootCd,icd,name); + ClassDefMutable *ncd = createTagLessInstance(rootCd,icd,name); processTagLessClasses(rootCd,icd,ncd,name,count+1); //printf(" addTagged %s to %s\n",ncd->name().data(),tagParentCd->name().data()); tagParentCd->addTaggedInnerClass(ncd); @@ -1403,9 +1425,10 @@ static void processTagLessClasses(ClassDef *rootCd, MemberDef *pmd; for (pli.toFirst();(pmd=pli.current());++pli) { - if (pmd->name()==md->name()) + MemberDefMutable *pmdm = toMemberDefMutable(pmd); + if (pmdm && pmd->name()==md->name()) { - pmd->setAccessorType(ncd,substitute(pmd->typeString(),icd->name(),ncd->name())); + pmdm->setAccessorType(ncd,substitute(pmd->typeString(),icd->name(),ncd->name())); //pmd->setType(substitute(pmd->typeString(),icd->name(),ncd->name())); } } @@ -1433,7 +1456,7 @@ static void findTagLessClasses(ClassDef *cd) } } - processTagLessClasses(cd,cd,cd,"",0); // process tag less inner struct/classes (if any) + processTagLessClasses(cd,cd,toClassDefMutable(cd),"",0); // process tag less inner struct/classes (if any) } static void findTagLessClasses() @@ -1477,8 +1500,8 @@ static void buildNamespaceList(const Entry *root) { //printf("Found namespace %s in %s at line %d\n",root->name.data(), // root->fileName.data(), root->startLine); - NamespaceDef *nd; - if ((nd=Doxygen::namespaceSDict->find(fullName))) // existing namespace + NamespaceDefMutable *nd; + if ((nd=toNamespaceDefMutable(Doxygen::namespaceSDict->find(fullName)))) // existing namespace { nd->setDocumentation(root->doc,root->docFile,root->docLine); nd->setName(fullName); // change name to match docs @@ -1552,27 +1575,40 @@ static void buildNamespaceList(const Entry *root) // anyway, so we can at least relate scopes properly. { d = buildScopeFromQualifiedName(fullName,fullName.contains("::"),nd->getLanguage(),tagInfo); - d->addInnerCompound(nd); + DefinitionMutable *dm = toDefinitionMutable(d); + if (dm) + { + dm->addInnerCompound(nd); + } nd->setOuterScope(d); // TODO: Due to the order in which the tag file is written // a nested class can be found before its parent! } else { - d->addInnerCompound(nd); + DefinitionMutable *dm = toDefinitionMutable(d); + if (dm) + { + dm->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) + while (d->definitionType()==Definition::TypeNamespace) { - NamespaceDef *pnd = dynamic_cast<NamespaceDef*>(d); - if (pnd->isInline()) + NamespaceDef *pnd = toNamespaceDef(d); + if (pnd && 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); + dm = toDefinitionMutable(d); + if (dm) + { + NamespaceDef *aliasNd = createNamespaceDefAlias(d,nd); + //printf("adding %s to %s\n",qPrint(aliasNd->name()),qPrint(d->name())); + dm->addInnerCompound(aliasNd); + Doxygen::namespaceSDict->inSort(aliasNd->name(),aliasNd); + } } } else @@ -1589,21 +1625,15 @@ static void buildNamespaceList(const Entry *root) //---------------------------------------------------------------------- -static const NamespaceDef *findUsedNamespace(const NamespaceSDict *unl, +static const NamespaceDef *findUsedNamespace(const LinkedRefMap<const NamespaceDef> &unl, const QCString &name) { const NamespaceDef *usingNd =0; - if (unl) + for (const auto &und : unl) { - //printf("Found namespace dict %d\n",unl->count()); - NamespaceSDict::Iterator unli(*unl); - const NamespaceDef *und; - for (unli.toFirst();(und=unli.current());++unli) - { - QCString uScope=und->name()+"::"; - usingNd = getResolvedNamespace(uScope+name); - //printf("Also trying with scope='%s' usingNd=%p\n",(uScope+name).data(),usingNd); - } + QCString uScope=und->name()+"::"; + usingNd = getResolvedNamespace(uScope+name); + if (usingNd!=0) break; } return usingNd; } @@ -1622,7 +1652,7 @@ static void findUsingDirectives(const Entry *root) if (!name.isEmpty()) { const NamespaceDef *usingNd = 0; - NamespaceDef *nd = 0; + NamespaceDefMutable *nd = 0; FileDef *fd = root->fileDef(); QCString nsName; @@ -1635,7 +1665,7 @@ static void findUsingDirectives(const Entry *root) nsName=stripAnonymousNamespaceScope(root->parent()->name); if (!nsName.isEmpty()) { - nd = getResolvedNamespace(nsName); + nd = getResolvedNamespaceMutable(nsName); } } @@ -1663,17 +1693,17 @@ static void findUsingDirectives(const Entry *root) if (usingNd==0 && nd) // not found, try used namespaces in this scope // or in one of the parent namespace scopes { - const NamespaceDef *pnd = nd; + const NamespaceDefMutable *pnd = nd; while (pnd && usingNd==0) { // also try with one of the used namespaces found earlier - usingNd = findUsedNamespace(pnd->getUsedNamespaces(),name); + usingNd = toNamespaceDefMutable(findUsedNamespace(pnd->getUsedNamespaces(),name)); // goto the parent const Definition *s = pnd->getOuterScope(); if (s && s->definitionType()==Definition::TypeNamespace) { - pnd = dynamic_cast<const NamespaceDef*>(s); + pnd = toNamespaceDefMutable(toNamespaceDef(s)); } else { @@ -1782,8 +1812,8 @@ static void findUsingDeclarations(const Entry *root) // rootNav->parent()->section()); if (!root->name.isEmpty()) { - ClassDef *usingCd = 0; - NamespaceDef *nd = 0; + ClassDefMutable *usingCd = 0; + NamespaceDefMutable *nd = 0; FileDef *fd = root->fileDef(); QCString scName; @@ -1794,7 +1824,7 @@ static void findUsingDeclarations(const Entry *root) scName=root->parent()->name; if (!scName.isEmpty()) { - nd = getResolvedNamespace(scName); + nd = getResolvedNamespaceMutable(scName); } } @@ -1805,16 +1835,17 @@ static void findUsingDeclarations(const Entry *root) // file scope). QCString name = substitute(root->name,".","::"); //Java/C# scope->internal - usingCd = getClass(name); // try direct lookup first, this is needed to get + usingCd = getClassMutable(name); // try direct lookup first, this is needed to get // builtin STL classes to properly resolve, e.g. // vector -> std::vector if (usingCd==0) { - usingCd = const_cast<ClassDef*>(getResolvedClass(nd,fd,name)); // try via resolving (see also bug757509) + SymbolResolver resolver(fd); + usingCd = resolver.resolveClassMutable(nd,name); // try via resolving (see also bug757509) } if (usingCd==0) { - usingCd = Doxygen::hiddenClasses->find(name); // check if it is already hidden + usingCd = toClassDefMutable(Doxygen::hiddenClasses->find(name)); // check if it is already hidden } //printf("%s -> %p\n",root->name.data(),usingCd); @@ -1867,7 +1898,7 @@ static void findUsingDeclImports(const Entry *root) QCString fullName=removeRedundantWhiteSpace(root->parent()->name); fullName=stripAnonymousNamespaceScope(fullName); fullName=stripTemplateSpecifiersFromScope(fullName); - ClassDef *cd = getClass(fullName); + ClassDefMutable *cd = getClassMutable(fullName); if (cd) { //printf("found class %s\n",cd->name().data()); @@ -1876,7 +1907,8 @@ static void findUsingDeclImports(const Entry *root) { QCString scope=root->name.left(i); QCString memName=root->name.right(root->name.length()-i-2); - const ClassDef *bcd = getResolvedClass(cd,0,scope); // todo: file in fileScope parameter + SymbolResolver resolver; + const ClassDef *bcd = resolver.resolveClass(cd,scope); // todo: file in fileScope parameter if (bcd && bcd!=cd) { //printf("found class %s memName=%s\n",bcd->name().data(),memName.data()); @@ -1897,7 +1929,7 @@ static void findUsingDeclImports(const Entry *root) } const ArgumentList &templAl = md->templateArguments(); const ArgumentList &al = md->templateArguments(); - std::unique_ptr<MemberDef> newMd { createMemberDef( + std::unique_ptr<MemberDefMutable> newMd { createMemberDef( fileName,root->startLine,root->startColumn, md->typeString(),memName,md->argsString(), md->excpString(),root->protection,root->virt, @@ -1950,25 +1982,15 @@ static void findUsingDeclImports(const Entry *root) static void findIncludedUsingDirectives() { - // first mark all files as not visited - for (const auto &fn : *Doxygen::inputNameLinkedMap) - { - for (const auto &fd : *fn) - { - fd->setVisited(FALSE); - } - } + FileDefSet visitedFiles; // then recursively add using directives found in #include files // to files that have not been visited. for (const auto &fn : *Doxygen::inputNameLinkedMap) { for (const auto &fd : *fn) { - if (!fd->isVisited()) - { - //printf("----- adding using directives for file %s\n",fd->name().data()); - fd->addIncludedUsingDirectives(); - } + //printf("----- adding using directives for file %s\n",fd->name().data()); + fd->addIncludedUsingDirectives(visitedFiles); } } } @@ -1977,7 +1999,7 @@ static void findIncludedUsingDirectives() static MemberDef *addVariableToClass( const Entry *root, - ClassDef *cd, + ClassDefMutable *cd, MemberType mtype, const QCString &type, const QCString &name, @@ -2052,11 +2074,12 @@ static MemberDef *addVariableToClass( MemberName *mn=Doxygen::memberNameLinkedMap->find(name); if (mn) { - for (const auto &md : *mn) + for (const auto &imd : *mn) { //printf("md->getClassDef()=%p cd=%p type=[%s] md->typeString()=[%s]\n", // md->getClassDef(),cd,type.data(),md->typeString()); - if (!md->isAlias() && + MemberDefMutable *md = toMemberDefMutable(imd.get()); + if (md && md->getClassDef()==cd && removeRedundantWhiteSpace(type)==md->typeString()) // member already in the scope @@ -2068,11 +2091,11 @@ static MemberDef *addVariableToClass( { // Objective-C 2.0 property // turn variable into a property md->setProtection(root->protection); - cd->reclassifyMember(md.get(),MemberType_Property); + cd->reclassifyMember(md,MemberType_Property); } - addMemberDocs(root,md.get(),def,0,FALSE,root->spec); + addMemberDocs(root,md,def,0,FALSE,root->spec); //printf(" Member already found!\n"); - return md.get(); + return md; } } } @@ -2084,7 +2107,7 @@ static MemberDef *addVariableToClass( } // new member variable, typedef or enum value - std::unique_ptr<MemberDef> md { createMemberDef( + std::unique_ptr<MemberDefMutable> md { createMemberDef( fileName,root->startLine,root->startColumn, type,name,args,root->exception, prot,Normal,root->stat,related, @@ -2179,7 +2202,7 @@ static MemberDef *addVariableToFile( if (s>=0) { QCString typeValue = ttype.mid(s,l); - ClassDef *cd = getClass(typeValue); + ClassDefMutable *cd = getClassMutable(typeValue); if (cd) { // this typedef should hide compound name cd, so we @@ -2194,15 +2217,11 @@ static MemberDef *addVariableToFile( } // see if the function is inside a namespace - NamespaceDef *nd = 0; + NamespaceDefMutable *nd = 0; if (!scope.isEmpty()) { if (scope.find('@')!=-1) return 0; // anonymous scope! - //nscope=removeAnonymousScopes(scope); - //if (!nscope.isEmpty()) - //{ - nd = getResolvedNamespace(scope); - //} + nd = getResolvedNamespaceMutable(scope); } QCString def; @@ -2266,11 +2285,12 @@ static MemberDef *addVariableToFile( //if (!nscope.isEmpty()) if (!scope.isEmpty()) { - nd = getResolvedNamespace(scope); + nd = getResolvedNamespaceMutable(scope); } - for (const auto &md : *mn) + for (const auto &imd : *mn) { - if (!md->isAlias() && + MemberDefMutable *md = toMemberDefMutable(imd.get()); + if (md && ((nd==0 && md->getNamespaceDef()==0 && md->getFileDef() && root->fileName==md->getFileDef()->absFilePath() ) // both variable names in the same file @@ -2296,7 +2316,7 @@ static MemberDef *addVariableToFile( { Debug::print(Debug::Variables,0, " variable already found: scope=%s\n",qPrint(md->getOuterScope()->name())); - addMemberDocs(root,md.get(),def,0,FALSE,root->spec); + addMemberDocs(root,md,def,0,FALSE,root->spec); md->setRefItems(root->sli); // if md is a variable forward declaration and root is the definition that // turn md into the definition @@ -2311,7 +2331,7 @@ static MemberDef *addVariableToFile( { md->setDeclFile(root->fileName,root->startLine,root->startColumn); } - return md.get(); + return md; } } } @@ -2326,7 +2346,7 @@ static MemberDef *addVariableToFile( Debug::print(Debug::Variables,0, " new variable, nd=%s tagInfo=%p!\n",nd?qPrint(nd->name()):"<global>",root->tagInfo()); // new global variable, enum value or typedef - std::unique_ptr<MemberDef> md { createMemberDef( + std::unique_ptr<MemberDefMutable> md { createMemberDef( fileName,root->startLine,root->startColumn, type,name,args,0, root->protection, Normal,root->stat,Member, @@ -2426,11 +2446,13 @@ static bool isVarWithConstructor(const Entry *root) static QRegExp initChars("[0-9\"'&*!^]+"); static QRegExp idChars("[a-z_A-Z][a-z_A-Z0-9]*"); bool result=FALSE; - bool typeIsClass; + bool typeIsClass = false; + bool typePtrType = false; QCString type; Definition *ctx = 0; - FileDef *fd = 0; + FileDef *fd = root->fileDef(); int ti; + SymbolResolver resolver(fd); //printf("isVarWithConstructor(%s)\n",rootNav->name().data()); if (root->parent()->section & Entry::COMPOUND_MASK) @@ -2438,9 +2460,7 @@ static bool isVarWithConstructor(const Entry *root) result=FALSE; goto done; } - else if ((fd = root->fileDef()) && - (fd->name().right(2)==".c" || fd->name().right(2)==".h") - ) + else if ((fd != nullptr) && (fd->name().right(2)==".c" || fd->name().right(2)==".h")) { // inside a .c file result=FALSE; goto done; @@ -2459,11 +2479,15 @@ static bool isVarWithConstructor(const Entry *root) findAndRemoveWord(type,"const"); findAndRemoveWord(type,"static"); findAndRemoveWord(type,"volatile"); + typePtrType = type.find('*')!=-1 || type.find('&')!=-1; //if (type.left(6)=="const ") type=type.right(type.length()-6); - typeIsClass=getResolvedClass(ctx,fd,type)!=0; - if (!typeIsClass && (ti=type.find('<'))!=-1) + if (!typePtrType) { - typeIsClass=getResolvedClass(ctx,fd,type.left(ti))!=0; + typeIsClass = resolver.resolveClass(ctx,type)!=0; + if (!typeIsClass && (ti=type.find('<'))!=-1) + { + typeIsClass=resolver.resolveClass(ctx,type.left(ti))!=0; + } } if (typeIsClass) // now we still have to check if the arguments are // types or values. Since we do not have complete type info @@ -2489,7 +2513,15 @@ static bool isVarWithConstructor(const Entry *root) } goto done; } - if (a.type.isEmpty() || getResolvedClass(ctx,fd,a.type)!=0) + if (!a.type.isEmpty() && + (a.type.at(a.type.length()-1)=='*' || + a.type.at(a.type.length()-1)=='&')) + // type ends with * or & => pointer or reference + { + result=FALSE; + goto done; + } + if (a.type.isEmpty() || resolver.resolveClass(ctx,a.type)!=0) { result=FALSE; // arg type is a known type goto done; @@ -2500,13 +2532,6 @@ static bool isVarWithConstructor(const Entry *root) result=FALSE; // argument is a typedef goto done; } - if (a.type.at(a.type.length()-1)=='*' || - a.type.at(a.type.length()-1)=='&') - // type ends with * or & => pointer or reference - { - result=FALSE; - goto done; - } if (a.type.find(initChars)==0) { result=TRUE; // argument type starts with typical initializer char @@ -2617,7 +2642,7 @@ static void addVariable(const Entry *root,int isFuncPtr=-1) MemberType mtype; type=type.stripWhiteSpace(); - ClassDef *cd=0; + ClassDefMutable *cd=0; bool isRelated=FALSE; bool isMemberOf=FALSE; @@ -2630,7 +2655,7 @@ static void addVariable(const Entry *root,int isFuncPtr=-1) if (type=="friend class" || type=="friend struct" || type=="friend union") { - cd=getClass(scope); + cd=getClassMutable(scope); if (cd) { addVariableToClass(root, // entry @@ -2681,8 +2706,8 @@ static void addVariable(const Entry *root,int isFuncPtr=-1) scope=root->relates; } - cd=getClass(scope); - if (cd==0 && classScope!=scope) cd=getClass(classScope); + cd=getClassMutable(scope); + if (cd==0 && classScope!=scope) cd=getClassMutable(classScope); if (cd) { MemberDef *md=0; @@ -2700,7 +2725,7 @@ static void addVariable(const Entry *root,int isFuncPtr=-1) if (si!=-1 && !inlineSimpleStructs) // anonymous scope or type { QCString pScope; - ClassDef *pcd=0; + ClassDefMutable *pcd=0; pScope = scope.left(QMAX(si-2,0)); // scope without tag less parts if (!pScope.isEmpty()) pScope.prepend(annScopePrefix); @@ -2708,7 +2733,7 @@ static void addVariable(const Entry *root,int isFuncPtr=-1) pScope=annScopePrefix.left(annScopePrefix.length()-2); if (name.at(0)!='@') { - if (!pScope.isEmpty() && (pcd=getClass(pScope))) + if (!pScope.isEmpty() && (pcd=getClassMutable(pScope))) { md=addVariableToClass(root, // entry pcd, // class to add member to @@ -2844,7 +2869,7 @@ static void buildVarList(const Entry *root) static void addInterfaceOrServiceToServiceOrSingleton( const Entry *root, - ClassDef *const cd, + ClassDefMutable *cd, QCString const& rname) { FileDef *fd = root->fileDef(); @@ -2856,7 +2881,7 @@ static void addInterfaceOrServiceToServiceOrSingleton( { fileName = root->tagInfo()->tagName; } - std::unique_ptr<MemberDef> md { createMemberDef( + std::unique_ptr<MemberDefMutable> md { createMemberDef( fileName, root->startLine, root->startColumn, root->type, rname, "", "", root->protection, root->virt, root->stat, Member, type, ArgumentList(), root->argList, root->metaData) }; @@ -2940,7 +2965,7 @@ static void buildInterfaceAndServiceList(const Entry *root) if (!rname.isEmpty()) { QCString scope = root->parent()->name; - ClassDef *cd = getClass(scope); + ClassDefMutable *cd = getClassMutable(scope); assert(cd); if (cd && ((ClassDef::Interface == cd->compoundType()) || (ClassDef::Service == cd->compoundType()) || @@ -2976,7 +3001,7 @@ static void buildInterfaceAndServiceList(const Entry *root) // Searches the Entry tree for Function sections. // If found they are stored in their class or in the global list. -static void addMethodToClass(const Entry *root,ClassDef *cd, +static void addMethodToClass(const Entry *root,ClassDefMutable *cd, const QCString &rtype,const QCString &rname,const QCString &rargs, bool isFriend, Protection protection,bool stat,Specifier virt,uint64 spec, @@ -3037,7 +3062,7 @@ static void addMethodToClass(const Entry *root,ClassDef *cd, // ); // adding class member - std::unique_ptr<MemberDef> md { createMemberDef( + std::unique_ptr<MemberDefMutable> md { createMemberDef( fileName,root->startLine,root->startColumn, type,name,args,root->exception, protection,virt, @@ -3133,8 +3158,7 @@ static void addMethodToClass(const Entry *root,ClassDef *cd, //------------------------------------------------------------------------------------------ -void addGlobalFunction(const Entry *root,const QCString &rname,const QCString &sc, - NamespaceDef *nd) +static void addGlobalFunction(const Entry *root,const QCString &rname,const QCString &sc) { QCString scope = sc; Debug::print(Debug::Functions,0," --> new function %s found!\n",qPrint(rname)); @@ -3143,7 +3167,7 @@ void addGlobalFunction(const Entry *root,const QCString &rname,const QCString &s // new global function QCString name=removeRedundantWhiteSpace(rname); - std::unique_ptr<MemberDef> md { createMemberDef( + std::unique_ptr<MemberDefMutable> md { createMemberDef( root->fileName,root->startLine,root->startColumn, root->type,name,root->args,root->exception, root->protection,root->virt,root->stat,Member, @@ -3168,15 +3192,16 @@ void addGlobalFunction(const Entry *root,const QCString &rname,const QCString &s md->setMemberSpecifiers(root->spec); md->setMemberGroupId(root->mGrpId); + NamespaceDefMutable *nd = 0; // see if the function is inside a namespace that was not part of // the name already (in that case nd should be non-zero already) - if (nd==0 && root->parent()->section == Entry::NAMESPACE_SEC ) + if (root->parent()->section == Entry::NAMESPACE_SEC ) { //QCString nscope=removeAnonymousScopes(root->parent()->name); QCString nscope=root->parent()->name; if (!nscope.isEmpty()) { - nd = getResolvedNamespace(nscope); + nd = getResolvedNamespaceMutable(nscope); } } @@ -3281,7 +3306,7 @@ static void buildFunctionList(const Entry *root) QCString scope=root->parent()->name; //stripAnonymousNamespaceScope(root->parent->name); if (!rname.isEmpty() && scope.find('@')==-1) { - ClassDef *cd=0; + ClassDefMutable *cd=0; // check if this function's parent is a class scope=stripTemplateSpecifiersFromScope(scope,FALSE); @@ -3289,14 +3314,13 @@ static void buildFunctionList(const Entry *root) int memIndex=rname.findRev("::"); - cd=getClass(scope); + cd=getClassMutable(scope); if (cd && scope+"::"==rname.left(scope.length()+2)) // found A::f inside A { // strip scope from name rname=rname.right(rname.length()-root->parent()->name.length()-2); } - NamespaceDef *nd = 0; bool isMember=FALSE; if (memIndex!=-1) { @@ -3364,9 +3388,10 @@ static void buildFunctionList(const Entry *root) if ((mn=Doxygen::functionNameLinkedMap->find(rname))) { Debug::print(Debug::Functions,0," --> function %s already found!\n",qPrint(rname)); - for (const auto &md : *mn) + for (const auto &imd : *mn) { - if (!md->isAlias()) + MemberDefMutable *md = toMemberDefMutable(imd.get()); + if (md) { const NamespaceDef *mnd = md->getNamespaceDef(); NamespaceDef *rnd = 0; @@ -3386,7 +3411,7 @@ static void buildFunctionList(const Entry *root) 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 &mdAl = md->argumentList(); const ArgumentList &mdTempl = md->templateArguments(); // in case of template functions, we need to check if the @@ -3444,7 +3469,7 @@ static void buildFunctionList(const Entry *root) { // merge argument lists ArgumentList mergedArgList = root->argList; - mergeArguments(mdAl,mergedArgList,!root->doc.isEmpty()); + mergeArguments(const_cast<ArgumentList&>(mdAl),mergedArgList,!root->doc.isEmpty()); // merge documentation if (md->documentation().isEmpty() && !root->doc.isEmpty()) { @@ -3484,7 +3509,7 @@ static void buildFunctionList(const Entry *root) // merge ingroup specifiers if (md->getGroupDef()==0 && !root->groups.empty()) { - addMemberToGroups(root,md.get()); + addMemberToGroups(root,md); } else if (md->getGroupDef()!=0 && root->groups.empty()) { @@ -3512,14 +3537,14 @@ static void buildFunctionList(const Entry *root) } if (found) { - md_found = md.get(); + md_found = md; break; } } } if (!found) /* global function is unique with respect to the file */ { - addGlobalFunction(root,rname,scope,nd); + addGlobalFunction(root,rname,scope); } else { @@ -3563,29 +3588,29 @@ static void findFriends() { // there are members with the same name //printf("Function name is also a member name\n"); // for each function with that name - for (const auto &fmd : *fn) + for (const auto &ifmd : *fn) { - const MemberDef *cfmd = fmd.get(); + MemberDefMutable *fmd = toMemberDefMutable(ifmd.get()); // for each member with that name - for (const auto &mmd : *mn) + for (const auto &immd : *mn) { - const MemberDef *cmmd = mmd.get(); + MemberDefMutable *mmd = toMemberDefMutable(immd.get()); //printf("Checking for matching arguments // mmd->isRelated()=%d mmd->isFriend()=%d mmd->isFunction()=%d\n", // mmd->isRelated(),mmd->isFriend(),mmd->isFunction()); - if ((cmmd->isFriend() || (cmmd->isRelated() && cmmd->isFunction())) && - !fmd->isAlias() && !mmd->isAlias() && - matchArguments2(cmmd->getOuterScope(), cmmd->getFileDef(), &cmmd->argumentList(), - cfmd->getOuterScope(), cfmd->getFileDef(), &cfmd->argumentList(), + if (fmd && mmd && + (mmd->isFriend() || (mmd->isRelated() && mmd->isFunction())) && + matchArguments2(mmd->getOuterScope(), mmd->getFileDef(), &mmd->argumentList(), + fmd->getOuterScope(), fmd->getFileDef(), &fmd->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); + const ArgumentList &mmdAl = mmd->argumentList(); + const ArgumentList &fmdAl = fmd->argumentList(); + mergeArguments(const_cast<ArgumentList&>(mmdAl),const_cast<ArgumentList&>(fmdAl)); if (!fmd->documentation().isEmpty()) { mmd->setDocumentation(fmd->documentation(),fmd->docFile(),fmd->docLine()); @@ -3652,19 +3677,21 @@ static void transferFunctionDocumentation() { //printf("memberName=%s count=%d\n",mn->memberName(),mn->count()); /* find a matching function declaration and definition for this function */ - for (const auto &mdec : *mn) + for (const auto &imdec : *mn) { - if (mdec->isPrototype() || - (mdec->isVariable() && mdec->isExternal()) - ) + MemberDefMutable *mdec = toMemberDefMutable(imdec.get()); + if (mdec && + (mdec->isPrototype() || + (mdec->isVariable() && mdec->isExternal()) + )) { - for (const auto &mdef : *mn) + for (const auto &imdef : *mn) { - if (mdec!=mdef && - !mdec->isAlias() && !mdef->isAlias() && + MemberDefMutable *mdef = toMemberDefMutable(imdef.get()); + if (mdef && mdec!=mdef && mdec->getNamespaceDef()==mdef->getNamespaceDef()) { - combineDeclarationAndDefinition(mdec.get(),mdef.get()); + combineDeclarationAndDefinition(mdec,mdef); } } } @@ -3678,87 +3705,41 @@ static void transferFunctionReferences() { for (const auto &mn : *Doxygen::functionNameLinkedMap) { - MemberDef *mdef=0,*mdec=0; + MemberDefMutable *mdef=0,*mdec=0; /* find a matching function declaration and definition for this function */ - for (const auto &md_p : *mn) + for (const auto &imd : *mn) { - MemberDef *md = md_p.get(); - if (md->isPrototype()) - mdec=md; - else if (md->isVariable() && md->isExternal()) - mdec=md; + MemberDefMutable *md = toMemberDefMutable(imd.get()); + if (md) + { + if (md->isPrototype()) + mdec=md; + else if (md->isVariable() && md->isExternal()) + mdec=md; - if (md->isFunction() && !md->isStatic() && !md->isPrototype()) - mdef=md; - else if (md->isVariable() && !md->isExternal() && !md->isStatic()) - mdef=md; + if (md->isFunction() && !md->isStatic() && !md->isPrototype()) + mdef=md; + else if (md->isVariable() && !md->isExternal() && !md->isStatic()) + mdef=md; + } if (mdef && mdec) break; } if (mdef && mdec) { - ArgumentList &mdefAl = mdef->argumentList(); - ArgumentList &mdecAl = mdec->argumentList(); + const ArgumentList &mdefAl = mdef->argumentList(); + const ArgumentList &mdecAl = mdec->argumentList(); if ( - matchArguments2(mdef->getOuterScope(),mdef->getFileDef(),&mdefAl, - mdec->getOuterScope(),mdec->getFileDef(),&mdecAl, + matchArguments2(mdef->getOuterScope(),mdef->getFileDef(),const_cast<ArgumentList*>(&mdefAl), + mdec->getOuterScope(),mdec->getFileDef(),const_cast<ArgumentList*>(&mdecAl), TRUE ) ) /* match found */ { - MemberSDict *defDict = mdef->getReferencesMembers(); - MemberSDict *decDict = mdec->getReferencesMembers(); - if (defDict!=0) - { - MemberSDict::IteratorDict msdi(*defDict); - MemberDef *rmd; - for (msdi.toFirst();(rmd=msdi.current());++msdi) - { - if (decDict==0 || decDict->find(rmd->name())==0) - { - mdec->addSourceReferences(rmd); - } - } - } - if (decDict!=0) - { - MemberSDict::IteratorDict msdi(*decDict); - MemberDef *rmd; - for (msdi.toFirst();(rmd=msdi.current());++msdi) - { - if (defDict==0 || defDict->find(rmd->name())==0) - { - mdef->addSourceReferences(rmd); - } - } - } - - defDict = mdef->getReferencedByMembers(); - decDict = mdec->getReferencedByMembers(); - if (defDict!=0) - { - MemberSDict::IteratorDict msdi(*defDict); - MemberDef *rmd; - for (msdi.toFirst();(rmd=msdi.current());++msdi) - { - if (decDict==0 || decDict->find(rmd->name())==0) - { - mdec->addSourceReferencedBy(rmd); - } - } - } - if (decDict!=0) - { - MemberSDict::IteratorDict msdi(*decDict); - MemberDef *rmd; - for (msdi.toFirst();(rmd=msdi.current());++msdi) - { - if (defDict==0 || defDict->find(rmd->name())==0) - { - mdef->addSourceReferencedBy(rmd); - } - } - } + mdef->mergeReferences(mdec); + mdec->mergeReferences(mdef); + mdef->mergeReferencedBy(mdec); + mdec->mergeReferencedBy(mdef); } } } @@ -3774,32 +3755,37 @@ static void transferRelatedFunctionDocumentation() { /* find a matching function declaration and definition for this function */ // for each global function - for (const auto &md : *mn) + for (const auto &imd : *mn) { - //printf(" Function '%s'\n",md->name().data()); - MemberName *rmn; - if ((rmn=Doxygen::memberNameLinkedMap->find(md->name()))) // check if there is a member with the same name + MemberDefMutable *md = toMemberDefMutable(imd.get()); + if (md) { - //printf(" Member name found\n"); - // for each member with the same name - for (const auto &rmd : *rmn) + //printf(" Function '%s'\n",md->name().data()); + MemberName *rmn; + if ((rmn=Doxygen::memberNameLinkedMap->find(md->name()))) // check if there is a member with the same name { - //printf(" Member found: related='%d'\n",rmd->isRelated()); - if ((rmd->isRelated() || rmd->isForeign()) && // related function - !md->isAlias() && !rmd->isAlias() && - matchArguments2( md->getOuterScope(), md->getFileDef(), &md->argumentList(), - rmd->getOuterScope(),rmd->getFileDef(),&rmd->argumentList(), - TRUE - ) - ) + //printf(" Member name found\n"); + // for each member with the same name + for (const auto &irmd : *rmn) { - //printf(" Found related member '%s'\n",md->name().data()); - if (rmd->relatedAlso()) - md->setRelatedAlso(rmd->relatedAlso()); - else if (rmd->isForeign()) - md->makeForeign(); - else - md->makeRelated(); + MemberDefMutable *rmd = toMemberDefMutable(irmd.get()); + //printf(" Member found: related='%d'\n",rmd->isRelated()); + if (rmd && + (rmd->isRelated() || rmd->isForeign()) && // related function + matchArguments2( md->getOuterScope(), md->getFileDef(), &md->argumentList(), + rmd->getOuterScope(),rmd->getFileDef(),&rmd->argumentList(), + TRUE + ) + ) + { + //printf(" Found related member '%s'\n",md->name().data()); + if (rmd->relatedAlso()) + md->setRelatedAlso(rmd->relatedAlso()); + else if (rmd->isForeign()) + md->makeForeign(); + else + md->makeRelated(); + } } } } @@ -3850,13 +3836,14 @@ static ClassDef *findClassWithinClassContext(Definition *context,ClassDef *cd,co return result; } FileDef *fd=cd->getFileDef(); + SymbolResolver resolver(fd); if (context && cd!=context) { - result = const_cast<ClassDef*>(getResolvedClass(context,0,name,0,0,TRUE,TRUE)); + result = const_cast<ClassDef*>(resolver.resolveClass(context,name,true,true)); } if (result==0) { - result = const_cast<ClassDef*>(getResolvedClass(cd,fd,name,0,0,TRUE,TRUE)); + result = const_cast<ClassDef*>(resolver.resolveClass(cd,name,true,true)); } if (result==0) // try direct class, needed for namespaced classes imported via tag files (see bug624095) { @@ -3881,14 +3868,13 @@ static ClassDef *findClassWithinClassContext(Definition *context,ClassDef *cd,co static void findUsedClassesForClass(const Entry *root, Definition *context, - ClassDef *masterCd, - ClassDef *instanceCd, + ClassDefMutable *masterCd, + ClassDefMutable *instanceCd, bool isArtificial, const std::unique_ptr<ArgumentList> &actualArgs = std::unique_ptr<ArgumentList>(), QDict<int> *templateNames=0 ) { - masterCd->setVisited(TRUE); const ArgumentList &formalArgs = masterCd->templateArguments(); for (auto &mni : masterCd->memberNameInfoLinkedMap()) { @@ -3915,12 +3901,8 @@ static void findUsedClassesForClass(const Entry *root, while (!found && extractClassNameFromType(type,pos,usedClassName,templSpec,root->lang)!=-1) { // find the type (if any) that matches usedClassName - const ClassDef *typeCd = getResolvedClass(masterCd, - masterCd->getFileDef(), - usedClassName, - 0,0, - FALSE,TRUE - ); + SymbolResolver resolver(masterCd->getFileDef()); + const ClassDefMutable *typeCd = resolver.resolveClassMutable(masterCd,usedClassName,false,true); //printf("====> usedClassName=%s -> typeCd=%s\n", // usedClassName.data(),typeCd?typeCd->name().data():"<none>"); if (typeCd) @@ -3956,7 +3938,7 @@ static void findUsedClassesForClass(const Entry *root, found=TRUE; Debug::print(Debug::Classes,0," New used class '%s'\n", qPrint(usedName)); - ClassDef *usedCd = Doxygen::hiddenClasses->find(usedName); + ClassDefMutable *usedCd = toClassDefMutable(Doxygen::hiddenClasses->find(usedName)); if (usedCd==0) { usedCd = createClassDef( @@ -3979,7 +3961,7 @@ static void findUsedClassesForClass(const Entry *root, if (!found) { - ClassDef *usedCd=findClassWithinClassContext(context,masterCd,usedName); + ClassDefMutable *usedCd=toClassDefMutable(findClassWithinClassContext(context,masterCd,usedName)); //printf("Looking for used class %s: result=%s master=%s\n", // usedName.data(),usedCd?usedCd->name().data():"<none>",masterCd?masterCd->name().data():"<none>"); @@ -3999,7 +3981,7 @@ static void findUsedClassesForClass(const Entry *root, } if (!found && !type.isEmpty()) // used class is not documented in any scope { - ClassDef *usedCd = Doxygen::hiddenClasses->find(type); + ClassDefMutable *usedCd = toClassDefMutable(Doxygen::hiddenClasses->find(type)); if (usedCd==0 && !Config_getBool(HIDE_UNDOC_RELATIONS)) { if (type.right(2)=="(*" || type.right(2)=="(^") // type is a function pointer @@ -4031,22 +4013,20 @@ static void findUsedClassesForClass(const Entry *root, static void findBaseClassesForClass( const Entry *root, Definition *context, - ClassDef *masterCd, - ClassDef *instanceCd, + ClassDefMutable *masterCd, + ClassDefMutable *instanceCd, FindBaseClassRelation_Mode mode, bool isArtificial, const std::unique_ptr<ArgumentList> &actualArgs = std::unique_ptr<ArgumentList>(), QDict<int> *templateNames=0 ) { - //if (masterCd->visited) return; - masterCd->setVisited(TRUE); // The base class could ofcouse also be a non-nested class const ArgumentList &formalArgs = masterCd->templateArguments(); for (const BaseInfo &bi : root->extends) { - //printf("masterCd=%s bi->name='%s' #actualArgs=%d\n", - // masterCd->localName().data(),bi->name.data(),actualArgs?(int)actualArgs->count():-1); + //printf("masterCd=%s bi.name='%s' #actualArgs=%d\n", + // masterCd->localName().data(),bi.name.data(),actualArgs ? (int)actualArgs->size() : -1); bool delTempNames=FALSE; if (templateNames==0) { @@ -4088,7 +4068,7 @@ static void findBaseClassesForClass( static bool findTemplateInstanceRelation(const Entry *root, Definition *context, - ClassDef *templateClass,const QCString &templSpec, + ClassDefMutable *templateClass,const QCString &templSpec, QDict<int> *templateNames, bool isArtificial) { @@ -4108,13 +4088,14 @@ static bool findTemplateInstanceRelation(const Entry *root, //printf("\n"); bool existingClass = (templSpec == - tempArgListToString(templateClass->templateArguments(),root->lang) + tempArgListToString(templateClass->templateArguments(),root->lang,false) ); if (existingClass) return TRUE; bool freshInstance=FALSE; - ClassDef *instanceClass = templateClass->insertTemplateInstance( - root->fileName,root->startLine,root->startColumn,templSpec,freshInstance); + ClassDefMutable *instanceClass = toClassDefMutable( + templateClass->insertTemplateInstance( + root->fileName,root->startLine,root->startColumn,templSpec,freshInstance)); if (isArtificial) instanceClass->setArtificial(TRUE); instanceClass->setLanguage(root->lang); @@ -4126,8 +4107,8 @@ static bool findTemplateInstanceRelation(const Entry *root, // search for new template instances caused by base classes of // instanceClass - auto it = g_classEntries.find(templateClass->name().data()); - if (it!=g_classEntries.end()) + auto it_pair = g_classEntries.equal_range(templateClass->name().data()); + for (auto it=it_pair.first ; it!=it_pair.second ; ++it) { const Entry *templateRoot = it->second; Debug::print(Debug::Classes,0," template root found %s templSpec=%s!\n", @@ -4139,11 +4120,6 @@ static bool findTemplateInstanceRelation(const Entry *root, findUsedClassesForClass(templateRoot,context,templateClass,instanceClass, isArtificial,templArgs,templateNames); } - else - { - Debug::print(Debug::Classes,0," no template root entry found!\n"); - // TODO: what happened if we get here? - } //Debug::print(Debug::Classes,0," Template instance %s : \n",instanceClass->name().data()); //ArgumentList *tl = templateClass->templateArguments(); @@ -4249,7 +4225,7 @@ static int findEndOfTemplate(const QCString &s,int startPos) static bool findClassRelation( const Entry *root, Definition *context, - ClassDef *cd, + ClassDefMutable *cd, const BaseInfo *bi, QDict<int> *templateNames, FindBaseClassRelation_Mode mode, @@ -4299,17 +4275,14 @@ static bool findClassRelation( //baseClassName=stripTemplateSpecifiersFromScope // (removeRedundantWhiteSpace(baseClassName),TRUE, // &stripped); - const MemberDef *baseClassTypeDef=0; - QCString templSpec; - ClassDef *baseClass=const_cast<ClassDef*>( - getResolvedClass(explicitGlobalScope ? Doxygen::globalScope : context, - cd->getFileDef(), + SymbolResolver resolver(cd->getFileDef()); + ClassDefMutable *baseClass = resolver.resolveClassMutable(explicitGlobalScope ? Doxygen::globalScope : context, baseClassName, - &baseClassTypeDef, - &templSpec, mode==Undocumented, - TRUE - )); + true + ); + const MemberDef *baseClassTypeDef = resolver.getTypedef(); + QCString templSpec = resolver.getTemplateSpec(); //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", @@ -4346,7 +4319,7 @@ static bool findClassRelation( if (baseClass==0 && (root->lang==SrcLangExt_CSharp || root->lang==SrcLangExt_Java)) { // for Java/C# strip the template part before looking for matching - baseClass = Doxygen::genericsDict->find(baseClassName.left(i)); + baseClass = toClassDefMutable(Doxygen::genericsDict->find(baseClassName.left(i))); //printf("looking for '%s' result=%p\n",baseClassName.data(),baseClass); } if (baseClass==0 && i!=-1) @@ -4358,17 +4331,14 @@ static bool findClassRelation( //printf("baseClass==0 i=%d e=%d\n",i,e); if (e!=-1) // end of template was found at e { - templSpec=removeRedundantWhiteSpace(baseClassName.mid(i,e-i)); - baseClassName=baseClassName.left(i)+baseClassName.right(baseClassName.length()-e); - baseClass=const_cast<ClassDef*>( - getResolvedClass(explicitGlobalScope ? Doxygen::globalScope : context, - cd->getFileDef(), + templSpec = removeRedundantWhiteSpace(baseClassName.mid(i,e-i)); + baseClassName = baseClassName.left(i)+baseClassName.right(baseClassName.length()-e); + baseClass = resolver.resolveClassMutable(explicitGlobalScope ? Doxygen::globalScope : context, baseClassName, - &baseClassTypeDef, - 0, //&templSpec, mode==Undocumented, - TRUE - )); + true + ); + baseClassTypeDef = resolver.getTypedef(); //printf("baseClass=%p -> baseClass=%s templSpec=%s\n", // baseClass,baseClassName.data(),templSpec.data()); } @@ -4379,8 +4349,8 @@ static bool findClassRelation( // instance (for instance if a class // derived from a template argument) { - //printf("baseClass=%p templSpec=%s\n",baseClass,templSpec.data()); - ClassDef *templClass=getClass(baseClass->name()+templSpec); + //printf("baseClass=%s templSpec=%s\n",baseClass->name().data(),templSpec.data()); + ClassDefMutable *templClass=getClassMutable(baseClass->name()+templSpec); if (templClass) { // use the template instance instead of the template base. @@ -4394,18 +4364,15 @@ static bool findClassRelation( //printf("1. found=%d\n",found); if (!found && si!=-1) { - QCString tmpTemplSpec; // replace any namespace aliases replaceNamespaceAliases(baseClassName,si); - baseClass=const_cast<ClassDef*>( - getResolvedClass(explicitGlobalScope ? Doxygen::globalScope : context, - cd->getFileDef(), + baseClass = resolver.resolveClassMutable(explicitGlobalScope ? Doxygen::globalScope : context, baseClassName, - &baseClassTypeDef, - &tmpTemplSpec, mode==Undocumented, - TRUE - )); + true + ); + baseClassTypeDef = resolver.getTypedef(); + QCString tmpTemplSpec = resolver.getTemplateSpec(); found=baseClass!=0 && baseClass!=cd; if (found) templSpec = tmpTemplSpec; } @@ -4420,7 +4387,7 @@ static bool findClassRelation( if (!found) { - baseClass=findClassWithinClassContext(context,cd,baseClassName); + baseClass=toClassDefMutable(findClassWithinClassContext(context,cd,baseClassName)); //printf("findClassWithinClassContext(%s,%s)=%p\n", // cd->name().data(),baseClassName.data(),baseClass); found = baseClass!=0 && baseClass!=cd; @@ -4433,7 +4400,7 @@ static bool findClassRelation( auto it = Doxygen::namespaceAliasMap.find(baseClassName.data()); if (it!=Doxygen::namespaceAliasMap.end()) // see if it is indeed a class. { - baseClass=getClass(it->second.c_str()); + baseClass=getClassMutable(it->second.c_str()); found = baseClass!=0 && baseClass!=cd; } } @@ -4466,7 +4433,7 @@ static bool findClassRelation( if (baseClassTypeDef==0) { //printf(" => findTemplateInstanceRelation: %p\n",baseClassTypeDef); - findTemplateInstanceRelation(root,context,baseClass,templSpec,templateNames,isArtificial); + findTemplateInstanceRelation(root,context,baseClass,templSpec,templateNames,baseClass->isArtificial()); } } else if (mode==DocumentedOnly || mode==Undocumented) @@ -4506,7 +4473,7 @@ static bool findClassRelation( baseClass=0; if (isATemplateArgument) { - baseClass=Doxygen::hiddenClasses->find(baseClassName); + baseClass=toClassDefMutable(Doxygen::hiddenClasses->find(baseClassName)); if (baseClass==0) { baseClass=createClassDef(root->fileName,root->startLine,root->startColumn, @@ -4519,7 +4486,7 @@ static bool findClassRelation( } else { - baseClass=Doxygen::classSDict->find(baseClassName); + baseClass=toClassDefMutable(Doxygen::classSDict->find(baseClassName)); //printf("*** classDDict->find(%s)=%p biName=%s templSpec=%s\n", // baseClassName.data(),baseClass,biName.data(),templSpec.data()); if (baseClass==0) @@ -4630,7 +4597,7 @@ static void findClassEntries(const Entry *root) { if (isClassSection(root)) { - g_classEntries.insert({root->name.data(),root}); + g_classEntries.insert({root->name.str(),root}); } for (const auto &e : root->children()) findClassEntries(e.get()); } @@ -4659,7 +4626,7 @@ static QCString extractClassName(const Entry *root) static void findInheritedTemplateInstances() { ClassSDict::Iterator cli(*Doxygen::classSDict); - for (cli.toFirst();cli.current();++cli) cli.current()->setVisited(FALSE); + ClassDefSet visitedClasses; for (const auto &kv : g_classEntries) { const Entry *root = kv.second; @@ -4668,8 +4635,12 @@ static void findInheritedTemplateInstances() Debug::print(Debug::Classes,0," Inheritance: Class %s : \n",qPrint(bName)); if ((cd=getClass(bName))) { - //printf("Class %s %d\n",cd->name().data(),root->extends->count()); - findBaseClassesForClass(root,cd,cd,cd,TemplateInstances,FALSE); + ClassDefMutable *cdm = toClassDefMutable(cd); + if (cdm) + { + //printf("Class %s %zu\n",cd->name().data(),root->extends.size()); + findBaseClassesForClass(root,cd,cdm,cdm,TemplateInstances,FALSE); + } } } } @@ -4677,7 +4648,6 @@ static void findInheritedTemplateInstances() static void findUsedTemplateInstances() { ClassSDict::Iterator cli(*Doxygen::classSDict); - for (cli.toFirst();cli.current();++cli) cli.current()->setVisited(FALSE); for (const auto &kv : g_classEntries) { const Entry *root = kv.second; @@ -4686,8 +4656,12 @@ static void findUsedTemplateInstances() Debug::print(Debug::Classes,0," Usage: Class %s : \n",qPrint(bName)); if ((cd=getClass(bName))) { - findUsedClassesForClass(root,cd,cd,cd,TRUE); - cd->addTypeConstraints(); + ClassDefMutable *cdm = toClassDefMutable(cd); + if (cdm) + { + findUsedClassesForClass(root,cd,cdm,cdm,TRUE); + cdm->addTypeConstraints(); + } } } } @@ -4695,15 +4669,14 @@ static void findUsedTemplateInstances() static void computeClassRelations() { ClassSDict::Iterator cli(*Doxygen::classSDict); - for (cli.toFirst();cli.current();++cli) cli.current()->setVisited(FALSE); for (const auto &kv : g_classEntries) { const Entry *root = kv.second; - ClassDef *cd; + ClassDefMutable *cd; QCString bName = extractClassName(root); Debug::print(Debug::Classes,0," Relations: Class %s : \n",qPrint(bName)); - if ((cd=getClass(bName))) + if ((cd=getClassMutable(bName))) { findBaseClassesForClass(root,cd,cd,cd,DocumentedOnly,FALSE); } @@ -4733,65 +4706,69 @@ static void computeTemplateClassRelations() const Entry *root = kv.second; QCString bName=stripAnonymousNamespaceScope(root->name); bName=stripTemplateSpecifiersFromScope(bName); - ClassDef *cd=getClass(bName); + ClassDefMutable *cd=getClassMutable(bName); // strip any anonymous scopes first QDict<ClassDef> *templInstances = 0; if (cd && (templInstances=cd->getTemplateInstances())) { Debug::print(Debug::Classes,0," Template class %s : \n",qPrint(cd->name())); QDictIterator<ClassDef> tdi(*templInstances); - ClassDef *tcd; - for (tdi.toFirst();(tcd=tdi.current());++tdi) // for each template instance - { - Debug::print(Debug::Classes,0," Template instance %s : \n",qPrint(tcd->name())); - QCString templSpec = tdi.currentKey(); - std::unique_ptr<ArgumentList> templArgs = stringToArgumentList(tcd->getLanguage(),templSpec); - for (const BaseInfo &bi : root->extends) - { - // check if the base class is a template argument - BaseInfo tbi = bi; - const ArgumentList &tl = cd->templateArguments(); - if (!tl.empty()) + ClassDef *itcd; + for (tdi.toFirst();(itcd=tdi.current());++tdi) // for each template instance + { + ClassDefMutable *tcd=toClassDefMutable(itcd); + if (tcd) + { + Debug::print(Debug::Classes,0," Template instance %s : \n",qPrint(tcd->name())); + QCString templSpec = tdi.currentKey(); + std::unique_ptr<ArgumentList> templArgs = stringToArgumentList(tcd->getLanguage(),templSpec); + for (const BaseInfo &bi : root->extends) { - QDict<int> *baseClassNames = tcd->getTemplateBaseClassNames(); - QDict<int> *templateNames = getTemplateArgumentsInName(tl,bi.name); - // for each template name that we inherit from we need to - // substitute the formal with the actual arguments - QDict<int> *actualTemplateNames = new QDict<int>(17); - actualTemplateNames->setAutoDelete(TRUE); - QDictIterator<int> qdi(*templateNames); - for (qdi.toFirst();qdi.current();++qdi) + // check if the base class is a template argument + BaseInfo tbi = bi; + const ArgumentList &tl = cd->templateArguments(); + if (!tl.empty()) { - int templIndex = *qdi.current(); - Argument actArg; - bool hasActArg=FALSE; - if (templIndex<(int)templArgs->size()) + QDict<int> *baseClassNames = tcd->getTemplateBaseClassNames(); + QDict<int> *templateNames = getTemplateArgumentsInName(tl,bi.name); + // for each template name that we inherit from we need to + // substitute the formal with the actual arguments + QDict<int> *actualTemplateNames = new QDict<int>(17); + actualTemplateNames->setAutoDelete(TRUE); + QDictIterator<int> qdi(*templateNames); + for (qdi.toFirst();qdi.current();++qdi) { - actArg=templArgs->at(templIndex); - hasActArg=TRUE; + int templIndex = *qdi.current(); + Argument actArg; + bool hasActArg=FALSE; + if (templIndex<(int)templArgs->size()) + { + actArg=templArgs->at(templIndex); + hasActArg=TRUE; + } + if (hasActArg && + baseClassNames!=0 && + baseClassNames->find(actArg.type)!=0 && + actualTemplateNames->find(actArg.type)==0 + ) + { + actualTemplateNames->insert(actArg.type,new int(templIndex)); + } } - if (hasActArg && - baseClassNames!=0 && - baseClassNames->find(actArg.type)!=0 && - actualTemplateNames->find(actArg.type)==0 - ) + delete templateNames; + + tbi.name = substituteTemplateArgumentsInString(bi.name,tl,templArgs); + // find a documented base class in the correct scope + if (!findClassRelation(root,cd,tcd,&tbi,actualTemplateNames,DocumentedOnly,FALSE)) { - actualTemplateNames->insert(actArg.type,new int(templIndex)); + // no documented base class -> try to find an undocumented one + findClassRelation(root,cd,tcd,&tbi,actualTemplateNames,Undocumented,TRUE); } + delete actualTemplateNames; } - delete templateNames; - - tbi.name = substituteTemplateArgumentsInString(bi.name,tl,templArgs); - // find a documented base class in the correct scope - if (!findClassRelation(root,cd,tcd,&tbi,actualTemplateNames,DocumentedOnly,FALSE)) - { - // no documented base class -> try to find an undocumented one - findClassRelation(root,cd,tcd,&tbi,actualTemplateNames,Undocumented,TRUE); - } - delete actualTemplateNames; } } - } // class has no base classes + } } } } @@ -4805,7 +4782,11 @@ static void computeMemberReferences() ClassDef *cd=0; for (cli.toFirst();(cd=cli.current());++cli) { - cd->computeAnchors(); + ClassDefMutable *cdm = toClassDefMutable(cd); + if (cdm) + { + cdm->computeAnchors(); + } } for (const auto &fn : *Doxygen::inputNameLinkedMap) { @@ -4818,7 +4799,11 @@ static void computeMemberReferences() NamespaceDef *nd=0; for (nli.toFirst();(nd=nli.current());++nli) { - nd->computeAnchors(); + NamespaceDefMutable *ndm = toNamespaceDefMutable(nd); + if (ndm) + { + ndm->computeAnchors(); + } } GroupSDict::Iterator gli(*Doxygen::groupSDict); GroupDef *gd; @@ -4836,9 +4821,10 @@ static void addListReferences() ClassDef *cd=0; for (cli.toFirst();(cd=cli.current());++cli) { - if (!cd->isAlias()) + ClassDefMutable *cdm = toClassDefMutable(cd); + if (cdm) { - cd->addListReferences(); + cdm->addListReferences(); } } @@ -4854,9 +4840,10 @@ static void addListReferences() NamespaceDef *nd=0; for (nli.toFirst();(nd=nli.current());++nli) { - if (!nd->isAlias()) + NamespaceDefMutable *ndm = toNamespaceDefMutable(nd); + if (ndm) { - nd->addListReferences(); + ndm->addListReferences(); } } @@ -4918,7 +4905,7 @@ static void generateXRefPages() // over_load is set the standard overload text is added. static void addMemberDocs(const Entry *root, - MemberDef *md, const char *funcDecl, + MemberDefMutable *md, const char *funcDecl, const ArgumentList *al, bool over_load, uint64 spec @@ -4934,7 +4921,7 @@ static void addMemberDocs(const Entry *root, md->enableCallerGraph(root->callerGraph); md->enableReferencedByRelation(root->referencedByRelation); md->enableReferencesRelation(root->referencesRelation); - ClassDef *cd=md->getClassDef(); + ClassDefMutable *cd=md->getClassDefMutable(); const NamespaceDef *nd=md->getNamespaceDef(); QCString fullName; if (cd) @@ -4949,17 +4936,17 @@ static void addMemberDocs(const Entry *root, // TODO determine scope based on root not md Definition *rscope = md->getOuterScope(); - ArgumentList &mdAl = md->argumentList(); + const ArgumentList &mdAl = md->argumentList(); if (al) { ArgumentList mergedAl = *al; //printf("merging arguments (1) docs=%d\n",root->doc.isEmpty()); - mergeArguments(mdAl,mergedAl,!root->doc.isEmpty()); + mergeArguments(const_cast<ArgumentList&>(mdAl),mergedAl,!root->doc.isEmpty()); } else { if ( - matchArguments2( md->getOuterScope(), md->getFileDef(), &mdAl, + matchArguments2( md->getOuterScope(), md->getFileDef(),const_cast<ArgumentList*>(&mdAl), rscope,rfd,&root->argList, TRUE ) @@ -4967,7 +4954,7 @@ static void addMemberDocs(const Entry *root, { //printf("merging arguments (2)\n"); ArgumentList mergedArgList = root->argList; - mergeArguments(mdAl,mergedArgList,!root->doc.isEmpty()); + mergeArguments(const_cast<ArgumentList&>(mdAl),mergedArgList,!root->doc.isEmpty()); } } if (over_load) // the \overload keyword was used @@ -5065,7 +5052,8 @@ static void addMemberDocs(const Entry *root, static const ClassDef *findClassDefinition(FileDef *fd,NamespaceDef *nd, const char *scopeName) { - const ClassDef *tcd = getResolvedClass(nd,fd,scopeName,0,0,TRUE,TRUE); + SymbolResolver resolver(fd); + const ClassDef *tcd = resolver.resolveClass(nd,scopeName,true,true); return tcd; } @@ -5106,24 +5094,25 @@ static bool findGlobalMember(const Entry *root, if (md->isAlias() && md->getOuterScope() && md->getOuterScope()->definitionType()==Definition::TypeNamespace) { - nd = dynamic_cast<const NamespaceDef *>(md->getOuterScope()); + nd = toNamespaceDef(md->getOuterScope()); } else { nd = md->getNamespaceDef(); } - //const Definition *scope=md->getOuterScope(); - //md = md->resolveAlias(); 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; + LinkedRefMap<const NamespaceDef> nl; + if (fd) + { + nl = fd->getUsedNamespaces(); + } //printf("NamespaceList %p\n",nl); // search in the list of namespaces that are imported via a // using declaration - bool viaUsingDirective = nl && nd && nl->find(nd->qualifiedName())!=0; + bool viaUsingDirective = nd && nl.find(nd->qualifiedName())!=0; if ((namespaceName.isEmpty() && nd==0) || // not in a namespace (nd && nd->name()==namespaceName) || // or in the same namespace @@ -5187,7 +5176,7 @@ static bool findGlobalMember(const Entry *root, if (matching) // add docs to the member { Debug::print(Debug::FindMembers,0,"5. Match found\n"); - addMemberDocs(root,md->resolveAlias(),decl,&root->argList,FALSE,root->spec); + addMemberDocs(root,toMemberDefMutable(md->resolveAlias()),decl,&root->argList,FALSE,root->spec); found=TRUE; break; } @@ -5252,7 +5241,7 @@ static bool scopeIsTemplate(const Definition *d) bool result=FALSE; if (d && d->definitionType()==Definition::TypeClass) { - result = !(dynamic_cast<const ClassDef*>(d))->templateArguments().empty() || + result = !(toClassDef(d))->templateArguments().empty() || scopeIsTemplate(d->getOuterScope()); } return result; @@ -5385,13 +5374,13 @@ static void addLocalObjCMethod(const Entry *root, uint64 spec) { //printf("scopeName='%s' className='%s'\n",scopeName.data(),className.data()); - ClassDef *cd=0; - if (Config_getBool(EXTRACT_LOCAL_METHODS) && (cd=getClass(scopeName))) + ClassDefMutable *cd=0; + if (Config_getBool(EXTRACT_LOCAL_METHODS) && (cd=getClassMutable(scopeName))) { Debug::print(Debug::FindMembers,0,"4. Local objective C method %s\n" " scopeName=%s\n",qPrint(root->name),qPrint(scopeName)); //printf("Local objective C method '%s' of class '%s' found\n",root->name.data(),cd->name().data()); - std::unique_ptr<MemberDef> md { createMemberDef( + std::unique_ptr<MemberDefMutable> md { createMemberDef( root->fileName,root->startLine,root->startColumn, funcType,funcName,funcArgs,exceptions, root->protection,root->virt,root->stat,Member, @@ -5455,16 +5444,19 @@ static void addMemberFunction(const Entry *root, int count=0; int noMatchCount=0; bool memFound=FALSE; - for (const auto &md : *mn) + for (const auto &imd : *mn) { - ClassDef *cd=md->getClassDef(); + MemberDefMutable *md = toMemberDefMutable(imd.get()); + if (md==0) continue; + ClassDefMutable *cd=md->getClassDefMutable(); Debug::print(Debug::FindMembers,0, "3. member definition found, " "scope needed='%s' scope='%s' args='%s' fileName=%s\n", qPrint(scopeName),cd ? qPrint(cd->name()) : "<none>", qPrint(md->argsString()), qPrint(root->fileName)); - //printf("Member %s (member scopeName=%s) (this scopeName=%s) classTempList=%s\n",md->name().data(),cd->name().data(),scopeName.data(),classTempList.data()); + //printf("Member %s (member scopeName=%s) (this scopeName=%s) isEnumValue()=%d\n", + // md->name().data(),cd->name().data(),scopeName.data(),md->isEnumValue()); FileDef *fd=root->fileDef(); NamespaceDef *nd=0; if (!namespaceName.isEmpty()) nd=getResolvedNamespace(namespaceName); @@ -5472,6 +5464,30 @@ static void addMemberFunction(const Entry *root, //printf("scopeName %s->%s\n",scopeName.data(), // stripTemplateSpecifiersFromScope(scopeName,FALSE).data()); + // if the member we are searching for is an enum value that is part of + // a "strong" enum, we need to look into the fields of the enum for a match + int enumNamePos=0; + if (md->isEnumValue() && (enumNamePos=className.findRev("::"))!=-1) + { + QCString enumName = className.mid(enumNamePos+2); + if (className.left(enumNamePos)==cd->name()) + { + MemberName *enumMn=Doxygen::memberNameLinkedMap->find(enumName); + //printf("enumMn(%s)=%p\n",className.data(),enumMn); + if (enumMn) + { + for (const auto &emd : *enumMn) + { + memFound = emd->isStrong() && md->getEnumScope()==emd.get(); + addMemberDocs(root,md,funcDecl,0,overloaded,spec); + count++; + if (memFound) break; + } + } + } + } + if (memFound) break; + const ClassDef *tcd=findClassDefinition(fd,nd,scopeName); if (tcd==0 && cd && stripAnonymousNamespaceScope(cd->name())==scopeName) { @@ -5606,7 +5622,7 @@ static void addMemberFunction(const Entry *root, } if (matching) { - addMemberDocs(root,md.get(),funcDecl,0,overloaded,spec); + addMemberDocs(root,md,funcDecl,0,overloaded,spec); count++; memFound=TRUE; } @@ -5633,7 +5649,7 @@ static void addMemberFunction(const Entry *root, //printf("Assume template class\n"); for (const auto &md : *mn) { - ClassDef *ccd=md->getClassDef(); + ClassDefMutable *ccd=md->getClassDefMutable(); MemberDef *cmd=md.get(); //printf("ccd->name()==%s className=%s\n",ccd->name().data(),className.data()); if (ccd!=0 && rightScopeMatch(ccd->name(),className)) @@ -5673,7 +5689,7 @@ static void addMemberFunction(const Entry *root, { // we didn't find an actual match on argument lists, but there is only 1 member with this // name in the same scope, so that has to be the one. - addMemberDocs(root,umd,funcDecl,0,overloaded,spec); + addMemberDocs(root,toMemberDefMutable(umd),funcDecl,0,overloaded,spec); return; } else if (candidates>1 && ecd && emd) @@ -5681,7 +5697,7 @@ static void addMemberFunction(const Entry *root, // we didn't find a unique match using type resolution, // but one of the matches has the exact same signature so // we take that one. - addMemberDocs(root,emd,funcDecl,0,overloaded,spec); + addMemberDocs(root,toMemberDefMutable(emd),funcDecl,0,overloaded,spec); return; } } @@ -5709,7 +5725,7 @@ static void addMemberFunction(const Entry *root, warnMsg+="Possible candidates:\n"; for (const auto &md : *mn) { - ClassDef *cd=md->getClassDef(); + const ClassDef *cd=md->getClassDef(); if (cd!=0 && rightScopeMatch(cd->name(),className)) { const ArgumentList &templAl = md->templateArguments(); @@ -5751,7 +5767,7 @@ static void addMemberFunction(const Entry *root, static void addMemberSpecialization(const Entry *root, MemberName *mn, - ClassDef *cd, + ClassDefMutable *cd, const QCString &funcType, const QCString &funcName, const QCString &funcArgs, @@ -5773,7 +5789,7 @@ static void addMemberSpecialization(const Entry *root, MemberType mtype=MemberType_Function; ArgumentList tArgList; // getTemplateArgumentsFromName(cd->name()+"::"+funcName,root->tArgLists); - std::unique_ptr<MemberDef> md { createMemberDef( + std::unique_ptr<MemberDefMutable> md { createMemberDef( root->fileName,root->startLine,root->startColumn, funcType,funcName,funcArgs,exceptions, declMd ? declMd->protection() : root->protection, @@ -5827,7 +5843,7 @@ static void addOverloaded(const Entry *root,MemberName *mn, } if (sameClass) { - ClassDef *cd = mn->front()->getClassDef(); + ClassDefMutable *cd = mn->front()->getClassDefMutable(); MemberType mtype; if (root->mtype==Signal) mtype=MemberType_Signal; else if (root->mtype==Slot) mtype=MemberType_Slot; @@ -5838,7 +5854,7 @@ static void addOverloaded(const Entry *root,MemberName *mn, std::unique_ptr<ArgumentList> tArgList = getTemplateArgumentsFromName(cd->name()+"::"+funcName,root->tArgLists); //printf("new related member %s args='%s'\n",md->name().data(),funcArgs.data()); - std::unique_ptr<MemberDef> md { createMemberDef( + std::unique_ptr<MemberDefMutable> md { createMemberDef( root->fileName,root->startLine,root->startColumn, funcType,funcName,funcArgs,exceptions, root->protection,root->virt,root->stat,Related, @@ -6031,20 +6047,13 @@ static void findMember(const Entry *root, FileDef *fd=root->fileDef(); if (fd) { - NamespaceSDict *fnl = fd->getUsedNamespaces(); - if (fnl) + for (const auto &fnd : fd->getUsedNamespaces()) { - QCString joinedName; - NamespaceDef *fnd; - NamespaceSDict::Iterator nsdi(*fnl); - for (nsdi.toFirst();(fnd=nsdi.current());++nsdi) + QCString joinedName = fnd->name()+"::"+scopeName; + if (Doxygen::namespaceSDict->find(joinedName)) { - joinedName = fnd->name()+"::"+scopeName; - if (Doxygen::namespaceSDict->find(joinedName)) - { - scopeName=joinedName; - break; - } + scopeName=joinedName; + break; } } } @@ -6099,7 +6108,7 @@ static void findMember(const Entry *root, //printf("new scope='%s'\n",scopeName.data()); QCString tempScopeName=scopeName; - ClassDef *cd=getClass(scopeName); + ClassDefMutable *cd=getClassMutable(scopeName); if (cd) { if (funcSpec.isEmpty()) @@ -6255,19 +6264,20 @@ static void findMember(const Entry *root, " scopeName=%s className=%s\n",qPrint(scopeName),qPrint(className)); if (className.isEmpty()) className=relates; //printf("scopeName='%s' className='%s'\n",scopeName.data(),className.data()); - if ((cd=getClass(scopeName))) + if ((cd=getClassMutable(scopeName))) { bool newMember=TRUE; // assume we have a new member - MemberDef *mdDefine=0; + MemberDefMutable *mdDefine=0; { mn = Doxygen::functionNameLinkedMap->find(funcName); if (mn) { - for (const auto &md : *mn) + for (const auto &imd : *mn) { - if (md->isDefine()) + MemberDefMutable *md = toMemberDefMutable(imd.get()); + if (md && md->isDefine()) { - mdDefine = md.get(); + mdDefine = md; break; } } @@ -6283,19 +6293,23 @@ static void findMember(const Entry *root, else { // see if we got another member with matching arguments - MemberDef *rmd_found = 0; - for (const auto &rmd : *mn) + MemberDefMutable *rmd_found = 0; + for (const auto &irmd : *mn) { - const ArgumentList &rmdAl = rmd->argumentList(); - - newMember= - className!=rmd->getOuterScope()->name() || - !matchArguments2(rmd->getOuterScope(),rmd->getFileDef(),&rmdAl, - cd,fd,&root->argList, - TRUE); - if (!newMember) + MemberDefMutable *rmd = toMemberDefMutable(irmd.get()); + if (rmd) { - rmd_found = rmd.get(); + const ArgumentList &rmdAl = rmd->argumentList(); + + newMember= + className!=rmd->getOuterScope()->name() || + !matchArguments2(rmd->getOuterScope(),rmd->getFileDef(),&rmdAl, + cd,fd,&root->argList, + TRUE); + if (!newMember) + { + rmd_found = rmd; + } } } if (rmd_found) // member already exists as rmd -> add docs @@ -6337,7 +6351,7 @@ static void findMember(const Entry *root, // this accurately reflects the template arguments of // the related function, which don't have to do with // those of the related class. - std::unique_ptr<MemberDef> md { createMemberDef( + std::unique_ptr<MemberDefMutable> md { createMemberDef( root->fileName,root->startLine,root->startColumn, funcType,funcName,funcArgs,exceptions, root->protection,root->virt, @@ -6379,20 +6393,24 @@ static void findMember(const Entry *root, MemberName *rmn=Doxygen::functionNameLinkedMap->find(funcName); if (rmn) { - const MemberDef *rmd_found=0; - for (const auto &rmd : *rmn) + const MemberDefMutable *rmd_found=0; + for (const auto &irmd : *rmn) { - const ArgumentList &rmdAl = rmd->argumentList(); - // check for matching argument lists - if ( - matchArguments2(rmd->getOuterScope(),rmd->getFileDef(),&rmdAl, - cd,fd,&root->argList, - TRUE) - ) + MemberDefMutable *rmd = toMemberDefMutable(irmd.get()); + if (rmd) { - found=TRUE; - rmd_found = rmd.get(); - break; + const ArgumentList &rmdAl = rmd->argumentList(); + // check for matching argument lists + if ( + matchArguments2(rmd->getOuterScope(),rmd->getFileDef(),&rmdAl, + cd,fd,&root->argList, + TRUE) + ) + { + found=TRUE; + rmd_found = rmd; + break; + } } } if (rmd_found) // member found -> copy line number info @@ -6711,9 +6729,9 @@ static void findEnums(const Entry *root) { if (root->section==Entry::ENUM_SEC) { - ClassDef *cd=0; - FileDef *fd=0; - NamespaceDef *nd=0; + ClassDefMutable *cd=0; + FileDef *fd=0; + NamespaceDefMutable *nd=0; MemberNameLinkedMap *mnsd=0; bool isGlobal; bool isRelated=FALSE; @@ -6728,7 +6746,7 @@ static void findEnums(const Entry *root) { scope=root->name.left(i); // extract scope name=root->name.right(root->name.length()-i-2); // extract name - if ((cd=getClass(scope))==0) nd=getResolvedNamespace(scope); + if ((cd=getClassMutable(scope))==0) nd=getResolvedNamespaceMutable(scope); } else // no scope, check the scope in which the docs where found { @@ -6737,7 +6755,7 @@ static void findEnums(const Entry *root) ) // found enum docs inside a compound { scope=root->parent()->name; - if ((cd=getClass(scope))==0) nd=getResolvedNamespace(scope); + if ((cd=getClassMutable(scope))==0) nd=getResolvedNamespaceMutable(scope); } name=root->name; } @@ -6750,7 +6768,7 @@ static void findEnums(const Entry *root) scope=mergeScopes(scope,root->relates); else scope=root->relates.copy(); - if ((cd=getClass(scope))==0) nd=getResolvedNamespace(scope); + if ((cd=getClassMutable(scope))==0) nd=getResolvedNamespaceMutable(scope); } if (cd && !name.isEmpty()) // found a enum inside a compound @@ -6775,7 +6793,7 @@ static void findEnums(const Entry *root) if (!name.isEmpty()) { // new enum type - std::unique_ptr<MemberDef> md { createMemberDef( + std::unique_ptr<MemberDefMutable> md { createMemberDef( root->fileName,root->startLine,root->startColumn, 0,name,0,0, root->protection,Normal,FALSE, @@ -6879,9 +6897,9 @@ static void addEnumValuesToEnums(const Entry *root) if (root->section==Entry::ENUM_SEC) // non anonymous enumeration { - ClassDef *cd=0; - FileDef *fd=0; - NamespaceDef *nd=0; + ClassDefMutable *cd=0; + FileDef *fd=0; + NamespaceDefMutable *nd=0; MemberNameLinkedMap *mnsd=0; bool isGlobal; bool isRelated=FALSE; @@ -6895,7 +6913,7 @@ static void addEnumValuesToEnums(const Entry *root) { scope=root->name.left(i); // extract scope name=root->name.right(root->name.length()-i-2); // extract name - if ((cd=getClass(scope))==0) nd=getResolvedNamespace(scope); + if ((cd=getClassMutable(scope))==0) nd=getResolvedNamespaceMutable(scope); } else // no scope, check the scope in which the docs where found { @@ -6904,7 +6922,7 @@ static void addEnumValuesToEnums(const Entry *root) ) // found enum docs inside a compound { scope=root->parent()->name; - if ((cd=getClass(scope))==0) nd=getResolvedNamespace(scope); + if ((cd=getClassMutable(scope))==0) nd=getResolvedNamespaceMutable(scope); } name=root->name; } @@ -6912,11 +6930,11 @@ static void addEnumValuesToEnums(const Entry *root) if (!root->relates.isEmpty()) { // related member, prefix user specified scope isRelated=TRUE; - if (getClass(root->relates)==0 && !scope.isEmpty()) + if (getClassMutable(root->relates)==0 && !scope.isEmpty()) scope=mergeScopes(scope,root->relates); else scope=root->relates.copy(); - if ((cd=getClass(scope))==0) nd=getResolvedNamespace(scope); + if ((cd=getClassMutable(scope))==0) nd=getResolvedNamespaceMutable(scope); } if (cd && !name.isEmpty()) // found a enum inside a compound @@ -6948,17 +6966,18 @@ static void addEnumValuesToEnums(const Entry *root) { struct EnumValueInfo { - EnumValueInfo(const QCString &n,std::unique_ptr<MemberDef> &md) : + EnumValueInfo(const QCString &n,std::unique_ptr<MemberDefMutable> &md) : name(n), member(std::move(md)) {} QCString name; - std::unique_ptr<MemberDef> member; + std::unique_ptr<MemberDefMutable> member; }; std::vector< EnumValueInfo > extraMembers; // for each enum in this list - for (const auto &md : *mn) + for (const auto &imd : *mn) { + MemberDefMutable *md = toMemberDefMutable(imd.get()); // use raw pointer in this loop, since we modify mn and can then invalidate mdp. - if (!md->isAlias() && md->isEnumerate() && !root->children().empty()) + if (md && md->isEnumerate() && !root->children().empty()) { //printf(" enum with %d children\n",root->children()->count()); for (const auto &e : root->children()) @@ -6990,7 +7009,7 @@ static void addEnumValuesToEnums(const Entry *root) { fileName = e->tagInfo()->tagName; } - std::unique_ptr<MemberDef> fmd { createMemberDef( + std::unique_ptr<MemberDefMutable> fmd { createMemberDef( fileName,e->startLine,e->startColumn, e->type,e->name,e->args,0, e->protection, Normal,e->stat,Member, @@ -7012,7 +7031,7 @@ static void addEnumValuesToEnums(const Entry *root) fmd->setRefItems(e->sli); fmd->setAnchor(); md->insertEnumField(fmd.get()); - fmd->setEnumScope(md.get(),TRUE); + fmd->setEnumScope(md,TRUE); extraMembers.push_back(EnumValueInfo(e->name,fmd)); } } @@ -7024,9 +7043,10 @@ static void addEnumValuesToEnums(const Entry *root) if (!e->name.isEmpty() && (fmn=emnsd->find(e->name))) // get list of members with the same name as the field { - for (const auto &fmd : *fmn) + for (const auto &ifmd : *fmn) { - if (fmd->isEnumValue() && fmd->getOuterScope()==md->getOuterScope()) // in same scope + MemberDefMutable *fmd = toMemberDefMutable(ifmd.get()); + if (fmd && fmd->isEnumValue() && fmd->getOuterScope()==md->getOuterScope()) // in same scope { //printf("found enum value with same name %s in scope %s\n", // fmd->name().data(),fmd->getOuterScope()->name().data()); @@ -7035,8 +7055,8 @@ static void addEnumValuesToEnums(const Entry *root) const NamespaceDef *fnd=fmd->getNamespaceDef(); if (fnd==nd) // enum value is inside a namespace { - md->insertEnumField(fmd.get()); - fmd->setEnumScope(md.get()); + md->insertEnumField(fmd); + fmd->setEnumScope(md); } } else if (isGlobal) @@ -7044,19 +7064,19 @@ static void addEnumValuesToEnums(const Entry *root) const FileDef *ffd=fmd->getFileDef(); if (ffd==fd) // enum value has file scope { - md->insertEnumField(fmd.get()); - fmd->setEnumScope(md.get()); + md->insertEnumField(fmd); + fmd->setEnumScope(md); } } else if (isRelated && cd) // reparent enum value to // match the enum's scope { - md->insertEnumField(fmd.get()); // add field def to list - fmd->setEnumScope(md.get()); // cross ref with enum name + md->insertEnumField(fmd); // add field def to list + fmd->setEnumScope(md); // cross ref with enum name fmd->setEnumClassScope(cd); // cross ref with enum name fmd->setOuterScope(cd); fmd->makeRelated(); - cd->insertMember(fmd.get()); + cd->insertMember(fmd); } else { @@ -7065,8 +7085,8 @@ static void addEnumValuesToEnums(const Entry *root) { //printf("Inserting enum field %s in enum scope %s\n", // fmd->name().data(),md->name().data()); - md->insertEnumField(fmd.get()); // add field def to list - fmd->setEnumScope(md.get()); // cross ref with enum name + md->insertEnumField(fmd); // add field def to list + fmd->setEnumScope(md); // cross ref with enum name } } } @@ -7124,7 +7144,7 @@ static void findEnumDocumentation(const Entry *root) if (!scope.isEmpty()) scope.prepend("::"); scope.prepend(root->parent()->name); } - ClassDef *cd=getClass(scope); + const ClassDef *cd=getClass(scope); if (!name.isEmpty()) { @@ -7136,10 +7156,10 @@ static void findEnumDocumentation(const Entry *root) MemberName *mn=Doxygen::memberNameLinkedMap->find(name); if (mn) { - for (const auto &md : *mn) + for (const auto &imd : *mn) { - cd=md->getClassDef(); - if (cd && cd->name()==className && md->isEnumerate()) + MemberDefMutable *md = toMemberDefMutable(imd.get()); + if (md && (cd=md->getClassDef()) && cd->name()==className && md->isEnumerate()) { // documentation outside a compound overrides the documentation inside it #if 0 @@ -7175,7 +7195,7 @@ static void findEnumDocumentation(const Entry *root) const GroupDef *gd=md->getGroupDef(); if (gd==0 && !root->groups.empty()) // member not grouped but out-of-line documentation is { - addMemberToGroups(root,md.get()); + addMemberToGroups(root,md); } found=TRUE; @@ -7194,9 +7214,10 @@ static void findEnumDocumentation(const Entry *root) MemberName *mn=Doxygen::functionNameLinkedMap->find(name); if (mn) { - for (const auto &md : *mn) + for (const auto &imd : *mn) { - if (md->isEnumerate()) + MemberDefMutable *md = toMemberDefMutable(imd.get()); + if (md && md->isEnumerate()) { md->setDocumentation(root->doc,root->docFile,root->docLine); md->setDocsForDefinition(!root->proto); @@ -7208,7 +7229,7 @@ static void findEnumDocumentation(const Entry *root) const GroupDef *gd=md->getGroupDef(); if (gd==0 && !root->groups.empty()) // member not grouped but out-of-line documentation is { - addMemberToGroups(root,md.get()); + addMemberToGroups(root,md); } found=TRUE; @@ -7237,9 +7258,10 @@ static void findDEV(const MemberNameLinkedMap &mnsd) for (const auto &mn : mnsd) { // for each member definition - for (const auto &md : *mn) + for (const auto &imd : *mn) { - if (md->isEnumerate()) // member is an enum + MemberDefMutable *md = toMemberDefMutable(imd.get()); + if (md && md->isEnumerate()) // member is an enum { const MemberList *fmdl = md->enumFieldList(); int documentedEnumValues=0; @@ -7285,17 +7307,18 @@ static void addMembersToIndex() for (const auto &mn : *Doxygen::functionNameLinkedMap) { // for each member definition - for (const auto &md : *mn) + for (const auto &imd : *mn) { - if (!md->isAlias()) + MemberDefMutable *md = toMemberDefMutable(imd.get()); + if (md) { if (md->getNamespaceDef()) { - addNamespaceMemberNameToIndex(md.get()); + addNamespaceMemberNameToIndex(md); } else { - addFileMemberNameToIndex(md.get()); + addFileMemberNameToIndex(md); } } } @@ -7310,18 +7333,26 @@ static void vhdlCorrectMemberProperties() for (const auto &mn : *Doxygen::memberNameLinkedMap) { // for each member definition - for (const auto &md : *mn) + for (const auto &imd : *mn) { - VhdlDocGen::correctMemberProperties(md.get()); + MemberDefMutable *md = toMemberDefMutable(imd.get()); + if (md) + { + VhdlDocGen::correctMemberProperties(md); + } } } // for each member name for (const auto &mn : *Doxygen::functionNameLinkedMap) { // for each member definition - for (const auto &md : *mn) + for (const auto &imd : *mn) { - VhdlDocGen::correctMemberProperties(md.get()); + MemberDefMutable *md = toMemberDefMutable(imd.get()); + if (md) + { + VhdlDocGen::correctMemberProperties(md); + } } } } @@ -7337,56 +7368,65 @@ static void computeMemberRelations() for (const auto &mn : *Doxygen::memberNameLinkedMap) { // for each member with a specific name - for (const auto &md : *mn) + for (const auto &imd : *mn) { - // for each other member with the same name - for ( const auto &bmd : *mn) + MemberDefMutable *md = toMemberDefMutable(imd.get()); + if (md) { - if (md!=bmd) + // for each other member with the same name + for ( const auto &ibmd : *mn) { - const ClassDef *mcd = md->getClassDef(); - if (mcd && mcd->baseClasses()) + MemberDefMutable *bmd = toMemberDefMutable(ibmd.get()); + if (bmd && md!=bmd) { - 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 - // ); - if (bmcd && mcd && bmcd!=mcd && - (bmd->virtualness()!=Normal || bmd->getLanguage()==SrcLangExt_Python || - bmd->getLanguage()==SrcLangExt_Java || bmd->getLanguage()==SrcLangExt_PHP || - bmcd->compoundType()==ClassDef::Interface || - bmcd->compoundType()==ClassDef::Protocol - ) && - md->isFunction() && - mcd->isLinkable() && - bmcd->isLinkable() && - mcd->isBaseClass(bmcd,TRUE)) + const ClassDef *mcd = md->getClassDef(); + if (mcd && !mcd->baseClasses().empty()) { - //printf(" derived scope\n"); - const ArgumentList &bmdAl = bmd->argumentList(); - const ArgumentList &mdAl = md->argumentList(); - //printf(" Base argList='%s'\n Super argList='%s'\n", - // argListToString(bmdAl.pointer()).data(), - // argListToString(mdAl.pointer()).data() + const ClassDef *bmcd = bmd->getClassDef(); + //printf("Check relation between '%s'::'%s' (%p) and '%s'::'%s' (%p)\n", + // mcd->name().data(),md->name().data(),md.get(), + // bmcd->name().data(),bmd->name().data(),bmd.get() // ); - if ( - matchArguments2(bmd->getOuterScope(),bmd->getFileDef(),&bmdAl, - md->getOuterScope(), md->getFileDef(), &mdAl, - TRUE - ) - ) + if (bmcd && mcd && bmcd!=mcd && + (bmd->virtualness()!=Normal || + bmd->getLanguage()==SrcLangExt_Python || bmd->getLanguage()==SrcLangExt_Java || bmd->getLanguage()==SrcLangExt_PHP || + bmcd->compoundType()==ClassDef::Interface || bmcd->compoundType()==ClassDef::Protocol + ) && + md->isFunction() && + mcd->isLinkable() && + bmcd->isLinkable() && + mcd->isBaseClass(bmcd,TRUE)) { - MemberDef *rmd; - if ((rmd=md->reimplements())==0 || - minClassDistance(mcd,bmcd)<minClassDistance(mcd,rmd->getClassDef()) + //printf(" derived scope\n"); + const ArgumentList &bmdAl = bmd->argumentList(); + const ArgumentList &mdAl = md->argumentList(); + //printf(" Base argList='%s'\n Super argList='%s'\n", + // argListToString(bmdAl).data(), + // argListToString(mdAl).data() + // ); + if ( + matchArguments2(bmd->getOuterScope(),bmd->getFileDef(),&bmdAl, + md->getOuterScope(), md->getFileDef(), &mdAl, + TRUE + ) ) { - //printf("setting (new) reimplements member\n"); - md->setReimplements(bmd.get()); + //printf("match!\n"); + MemberDef *rmd; + if ((rmd=md->reimplements())==0 || + minClassDistance(mcd,bmcd)<minClassDistance(mcd,rmd->getClassDef()) + ) + { + //printf("setting (new) reimplements member\n"); + md->setReimplements(bmd); + } + //printf("%s: add reimplementedBy member %s\n",bmcd->name().data(),mcd->name().data()); + bmd->insertReimplementedBy(md); + } + else + { + //printf("no match!\n"); } - //printf("%s: add reimplementedBy member %s\n",bmcd->name().data(),mcd->name().data()); - bmd->insertReimplementedBy(md.get()); } } } @@ -7426,7 +7466,11 @@ static void createTemplateInstanceMembers() // for each instance of the template for (qdi.toFirst();(tcd=qdi.current());++qdi) { - tcd->addMembersToTemplateInstance(cd,qdi.currentKey()); + ClassDefMutable *tcdm = toClassDefMutable(tcd); + if (tcdm) + { + tcdm->addMembersToTemplateInstance(cd,qdi.currentKey()); + } } } } @@ -7445,7 +7489,7 @@ static void mergeCategories() if (i!=-1) // it is an Objective-C category { QCString baseName=cd->name().left(i); - ClassDef *baseClass=Doxygen::classSDict->find(baseName); + ClassDefMutable *baseClass=toClassDefMutable(Doxygen::classSDict->find(baseName)); if (baseClass) { //printf("*** merging members of category %s into %s\n", @@ -7466,17 +7510,25 @@ static void buildCompleteMemberLists() for (cli.toFirst();(cd=cli.current());++cli) { if (// !cd->isReference() && // not an external class - cd->subClasses()==0 && // is a root of the hierarchy - cd->baseClasses()) // and has at least one base class + cd->subClasses().empty() && // is a root of the hierarchy + !cd->baseClasses().empty()) // and has at least one base class { - //printf("*** merging members for %s\n",cd->name().data()); - cd->mergeMembers(); + ClassDefMutable *cdm = toClassDefMutable(cd); + if (cdm) + { + //printf("*** merging members for %s\n",cd->name().data()); + cdm->mergeMembers(); + } } } // now sort the member list of all members for all classes. for (cli.toFirst();(cd=cli.current());++cli) { - cd->sortAllMembersList(); + ClassDefMutable *cdm = toClassDefMutable(cd); + if (cdm) + { + cdm->sortAllMembersList(); + } } } @@ -7506,15 +7558,20 @@ static void generateFileSources() { for (const auto &fd : *fn) { - if (fd->isSource() && !fd->isReference()) + if (fd->isSource() && !fd->isReference() && + ((fd->generateSourceFile() && !g_useOutputTemplate) || + (!fd->isReference() && Doxygen::parseSourcesNeeded) + ) + ) { auto clangParser = ClangParser::instance()->createTUParser(fd.get()); if (fd->generateSourceFile() && !g_useOutputTemplate) // sources need to be shown in the output { msg("Generating code for file %s...\n",fd->docName().data()); clangParser->parse(); - fd->writeSource(*g_outputList,clangParser.get()); - + fd->writeSourceHeader(*g_outputList); + fd->writeSourceBody(*g_outputList,clangParser.get()); + fd->writeSourceFooter(*g_outputList); } else if (!fd->isReference() && Doxygen::parseSourcesNeeded) // we needed to parse the sources even if we do not show them @@ -7538,7 +7595,9 @@ static void generateFileSources() if (ifd->generateSourceFile() && !g_useOutputTemplate) // sources need to be shown in the output { msg(" Generating code for file %s...\n",ifd->docName().data()); - ifd->writeSource(*g_outputList,clangParser.get()); + ifd->writeSourceHeader(*g_outputList); + ifd->writeSourceBody(*g_outputList,clangParser.get()); + ifd->writeSourceFooter(*g_outputList); } else if (!ifd->isReference() && Doxygen::parseSourcesNeeded) // we needed to parse the sources even if we do not show them @@ -7561,20 +7620,24 @@ static void generateFileSources() { if (processedFiles.find(fd->absFilePath().str())==processedFiles.end()) // not yet processed { - auto clangParser = ClangParser::instance()->createTUParser(fd.get()); if (fd->generateSourceFile() && !Htags::useHtags && !g_useOutputTemplate) // sources need to be shown in the output { + auto clangParser = ClangParser::instance()->createTUParser(fd.get()); msg("Generating code for file %s...\n",fd->docName().data()); clangParser->parse(); - fd->writeSource(*g_outputList,clangParser.get()); - + fd->writeSourceHeader(*g_outputList); + fd->writeSourceBody(*g_outputList,clangParser.get()); + fd->writeSourceFooter(*g_outputList); } else if (!fd->isReference() && Doxygen::parseSourcesNeeded) // we needed to parse the sources even if we do not show them { + auto clangParser = ClangParser::instance()->createTUParser(fd.get()); msg("Parsing code for file %s...\n",fd->docName().data()); clangParser->parse(); - fd->parseSource(clangParser.get()); + fd->writeSourceHeader(*g_outputList); + fd->writeSourceBody(*g_outputList,clangParser.get()); + fd->writeSourceFooter(*g_outputList); } } } @@ -7583,6 +7646,65 @@ static void generateFileSources() else #endif { +#define MULTITHREADED_SOURCE_GENERATOR 0 // not ready to be enabled yet +#if MULTITHREADED_SOURCE_GENERATOR + std::size_t numThreads = static_cast<std::size_t>(Config_getInt(NUM_PROC_THREADS)); + if (numThreads==0) + { + numThreads = std::thread::hardware_concurrency(); + } + msg("Generating code files using %zu threads.\n",numThreads); + struct SourceContext + { + SourceContext(FileDef *fd_,bool gen_,OutputList ol_) + : fd(fd_), generateSourceFile(gen_), ol(ol_) {} + FileDef *fd; + bool generateSourceFile; + OutputList ol; + }; + ThreadPool threadPool(numThreads); + std::vector< std::future< std::shared_ptr<SourceContext> > > results; + for (const auto &fn : *Doxygen::inputNameLinkedMap) + { + for (const auto &fd : *fn) + { + bool generateSourceFile = fd->generateSourceFile() && !Htags::useHtags && !g_useOutputTemplate; + auto ctx = std::make_shared<SourceContext>(fd.get(),generateSourceFile,*g_outputList); + if (generateSourceFile) + { + msg("Generating code for file %s...\n",fd->docName().data()); + fd->writeSourceHeader(ctx->ol); + } + else + { + msg("Parsing code for file %s...\n",fd->docName().data()); + } + auto processFile = [ctx]() { + StringVector filesInSameTu; + ctx->fd->getAllIncludeFilesRecursively(filesInSameTu); + if (ctx->generateSourceFile) // sources need to be shown in the output + { + ctx->fd->writeSourceBody(ctx->ol,nullptr); + } + else if (!ctx->fd->isReference() && Doxygen::parseSourcesNeeded) + // we needed to parse the sources even if we do not show them + { + ctx->fd->parseSource(nullptr); + } + return ctx; + }; + results.emplace_back(threadPool.queue(processFile)); + } + } + for (auto &f : results) + { + auto ctx = f.get(); + if (ctx->generateSourceFile) + { + ctx->fd->writeSourceFooter(ctx->ol); + } + } +#else // single threaded version for (const auto &fn : *Doxygen::inputNameLinkedMap) { for (const auto &fd : *fn) @@ -7592,7 +7714,9 @@ static void generateFileSources() 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,nullptr); + fd->writeSourceHeader(*g_outputList); + fd->writeSourceBody(*g_outputList,nullptr); + fd->writeSourceFooter(*g_outputList); } else if (!fd->isReference() && Doxygen::parseSourcesNeeded) // we needed to parse the sources even if we do not show them @@ -7602,6 +7726,7 @@ static void generateFileSources() } } } +#endif } } } @@ -7714,7 +7839,7 @@ static void buildDefineList() { for (const auto &def : it->second) { - std::unique_ptr<MemberDef> md { createMemberDef( + std::unique_ptr<MemberDefMutable> md { createMemberDef( def.fileName,def.lineNr,def.columnNr, "#define",def.name,def.args,0, Public,Normal,FALSE,Member,MemberType_Define, @@ -7748,7 +7873,11 @@ static void sortMemberLists() ClassDef *cd=0; for (cli.toFirst();(cd=cli.current());++cli) { - cd->sortMemberLists(); + ClassDefMutable *cdm = toClassDefMutable(cd); + if (cdm) + { + cdm->sortMemberLists(); + } } // sort namespace member lists @@ -7756,7 +7885,11 @@ static void sortMemberLists() NamespaceDef *nd=0; for (nli.toFirst();(nd=nli.current());++nli) { - nd->sortMemberLists(); + NamespaceDefMutable *ndm = toNamespaceDefMutable(nd); + if (ndm) + { + ndm->sortMemberLists(); + } } // sort file member lists @@ -7779,13 +7912,38 @@ static void sortMemberLists() //---------------------------------------------------------------------------- +static bool isSymbolHidden(const Definition *d) +{ + bool hidden = d->isHidden(); + const Definition *parent = d->getOuterScope(); + return parent ? hidden || isSymbolHidden(parent) : hidden; +} + +static void computeTooltipTexts() +{ + for (const auto &kv : Doxygen::symbolMap) + { + DefinitionMutable *dm = toDefinitionMutable(kv.second); + if (dm && !isSymbolHidden(toDefinition(dm)) && toDefinition(dm)->isLinkableInProject()) + { + dm->computeTooltip(); + } + } +} + +//---------------------------------------------------------------------------- + static void setAnonymousEnumType() { ClassSDict::Iterator cli(*Doxygen::classSDict); ClassDef *cd=0; for (cli.toFirst();(cd=cli.current());++cli) { - cd->setAnonymousEnumType(); + ClassDefMutable *cdm = toClassDefMutable(cd); + if (cdm) + { + cdm->setAnonymousEnumType(); + } } } @@ -7797,14 +7955,22 @@ static void countMembers() ClassDef *cd=0; for (cli.toFirst();(cd=cli.current());++cli) { - cd->countMembers(); + ClassDefMutable *cdm = toClassDefMutable(cd); + if (cdm) + { + cdm->countMembers(); + } } NamespaceSDict::Iterator nli(*Doxygen::namespaceSDict); NamespaceDef *nd=0; for (nli.toFirst();(nd=nli.current());++nli) { - nd->countMembers(); + NamespaceDefMutable *ndm = toNamespaceDefMutable(nd); + if (ndm) + { + ndm->countMembers(); + } } for (const auto &fn : *Doxygen::inputNameLinkedMap) @@ -7832,7 +7998,7 @@ static void generateClassList(ClassSDict &classSDict) ClassSDict::Iterator cli(classSDict); for ( ; cli.current() ; ++cli ) { - ClassDef *cd=cli.current(); + ClassDefMutable *cd=toClassDefMutable(cli.current()); //printf("cd=%s getOuterScope=%p global=%p\n",cd->name().data(),cd->getOuterScope(),Doxygen::globalScope); if (cd && @@ -7868,10 +8034,12 @@ static void inheritDocumentation() { for (const auto &mn : *Doxygen::memberNameLinkedMap) { - for (const auto &md : *mn) + for (const auto &imd : *mn) { - //printf("%04d Member '%s'\n",count++,md->name().data()); - if (md->documentation().isEmpty() && md->briefDescription().isEmpty()) + MemberDefMutable *md = toMemberDefMutable(imd.get()); + //static int count=0; + //printf("%04d Member '%s'\n",count++,md->qualifiedName().data()); + if (md && md->documentation().isEmpty() && md->briefDescription().isEmpty()) { // no documentation yet MemberDef *bmd = md->reimplements(); while (bmd && bmd->documentation().isEmpty() && @@ -7904,27 +8072,21 @@ static void combineUsingRelations() { for (const auto &fd : *fn) { - fd->setVisited(FALSE); - } - } - for (const auto &fn : *Doxygen::inputNameLinkedMap) - { - for (const auto &fd : *fn) - { fd->combineUsingRelations(); } } // for each namespace + NamespaceDefSet visitedNamespaces; NamespaceSDict::Iterator nli(*Doxygen::namespaceSDict); NamespaceDef *nd; for (nli.toFirst() ; (nd=nli.current()) ; ++nli ) { - nd->setVisited(FALSE); - } - for (nli.toFirst() ; (nd=nli.current()) ; ++nli ) - { - nd->combineUsingRelations(); + NamespaceDefMutable *ndm = toNamespaceDefMutable(nd); + if (ndm) + { + ndm->combineUsingRelations(visitedNamespaces); + } } } @@ -7937,7 +8099,11 @@ static void addMembersToMemberGroup() ClassDef *cd; for ( ; (cd=cli.current()) ; ++cli ) { - cd->addMembersToMemberGroup(); + ClassDefMutable *cdm = toClassDefMutable(cd); + if (cdm) + { + cdm->addMembersToMemberGroup(); + } } // for each file for (const auto &fn : *Doxygen::inputNameLinkedMap) @@ -7952,7 +8118,11 @@ static void addMembersToMemberGroup() NamespaceDef *nd; for ( ; (nd=nli.current()) ; ++nli ) { - nd->addMembersToMemberGroup(); + NamespaceDefMutable *ndm = toNamespaceDefMutable(nd); + if (ndm) + { + ndm->addMembersToMemberGroup(); + } } // for each group GroupSDict::Iterator gli(*Doxygen::groupSDict); @@ -7972,7 +8142,11 @@ static void distributeMemberGroupDocumentation() ClassDef *cd; for ( ; (cd=cli.current()) ; ++cli ) { - cd->distributeMemberGroupDocumentation(); + ClassDefMutable *cdm = toClassDefMutable(cd); + if (cdm) + { + cdm->distributeMemberGroupDocumentation(); + } } // for each file for (const auto &fn : *Doxygen::inputNameLinkedMap) @@ -7987,7 +8161,11 @@ static void distributeMemberGroupDocumentation() NamespaceDef *nd; for ( ; (nd=nli.current()) ; ++nli ) { - nd->distributeMemberGroupDocumentation(); + NamespaceDefMutable *ndm = toNamespaceDefMutable(nd); + if (ndm) + { + ndm->distributeMemberGroupDocumentation(); + } } // for each group GroupSDict::Iterator gli(*Doxygen::groupSDict); @@ -8007,7 +8185,11 @@ static void findSectionsInDocumentation() ClassDef *cd; for ( ; (cd=cli.current()) ; ++cli ) { - cd->findSectionsInDocumentation(); + ClassDefMutable *cdm = toClassDefMutable(cd); + if (cdm) + { + cdm->findSectionsInDocumentation(); + } } // for each file for (const auto &fn : *Doxygen::inputNameLinkedMap) @@ -8022,7 +8204,11 @@ static void findSectionsInDocumentation() NamespaceDef *nd; for ( ; (nd=nli.current()) ; ++nli ) { - nd->findSectionsInDocumentation(); + NamespaceDefMutable *ndm = toNamespaceDefMutable(nd); + if (ndm) + { + ndm->findSectionsInDocumentation(); + } } // for each group GroupSDict::Iterator gli(*Doxygen::groupSDict); @@ -8047,24 +8233,30 @@ static void flushCachedTemplateRelations() // as there can be new template instances in the inheritance path // to this class. Optimization: only remove those classes that // have inheritance instances as direct or indirect sub classes. - QCacheIterator<LookupInfo> ci(*Doxygen::lookupCache); - LookupInfo *li=0; - for (ci.toFirst();(li=ci.current());++ci) + StringVector elementsToRemove; + for (const auto &ci : *Doxygen::lookupCache) { - if (li->classDef) + const LookupInfo &li = ci.second; + if (li.classDef) { - Doxygen::lookupCache->remove(ci.currentKey()); + elementsToRemove.push_back(ci.first); } } + for (const auto &k : elementsToRemove) + { + Doxygen::lookupCache->remove(k); + } + // remove all cached typedef resolutions whose target is a // template class as this may now be a template instance // for each global function name for (const auto &fn : *Doxygen::functionNameLinkedMap) { // for each function with that name - for (const auto &fmd : *fn) + for (const auto &ifmd : *fn) { - if (fmd->isTypedefValCached()) + MemberDefMutable *fmd = toMemberDefMutable(ifmd.get()); + if (fmd && fmd->isTypedefValCached()) { const ClassDef *cd = fmd->getCachedTypedefVal(); if (cd->isTemplate()) fmd->invalidateTypedefValCache(); @@ -8075,9 +8267,10 @@ static void flushCachedTemplateRelations() for (const auto &nm : *Doxygen::memberNameLinkedMap) { // for each function with that name - for (const auto &md : *nm) + for (const auto &imd : *nm) { - if (md->isTypedefValCached()) + MemberDefMutable *md = toMemberDefMutable(imd.get()); + if (md && md->isTypedefValCached()) { const ClassDef *cd = md->getCachedTypedefVal(); if (cd->isTemplate()) md->invalidateTypedefValCache(); @@ -8099,33 +8292,45 @@ static void flushUnresolvedRelations() // class A { class I {} }; // class B : public A {}; // class C : public B::I {}; - // - QCacheIterator<LookupInfo> ci(*Doxygen::lookupCache); - LookupInfo *li=0; - for (ci.toFirst();(li=ci.current());++ci) + + StringVector elementsToRemove; + for (const auto &ci : *Doxygen::lookupCache) { - if (li->classDef==0 && li->typeDef==0) + const LookupInfo &li = ci.second; + if (li.classDef==0 && li.typeDef==0) { - Doxygen::lookupCache->remove(ci.currentKey()); + elementsToRemove.push_back(ci.first); } } + for (const auto &k : elementsToRemove) + { + Doxygen::lookupCache->remove(k); + } // for each global function name for (const auto &fn : *Doxygen::functionNameLinkedMap) { // for each function with that name - for (const auto &fmd : *fn) + for (const auto &ifmd : *fn) { - fmd->invalidateCachedArgumentTypes(); + MemberDefMutable *fmd = toMemberDefMutable(ifmd.get()); + if (fmd) + { + fmd->invalidateCachedArgumentTypes(); + } } } // for each class method name for (const auto &nm : *Doxygen::memberNameLinkedMap) { // for each function with that name - for (const auto &md : *nm) + for (const auto &imd : *nm) { - md->invalidateCachedArgumentTypes(); + MemberDefMutable *md = toMemberDefMutable(imd.get()); + if (md) + { + md->invalidateCachedArgumentTypes(); + } } } @@ -8144,7 +8349,7 @@ static void findDefineDocumentation(Entry *root) if (root->tagInfo() && !root->name.isEmpty()) // define read from a tag file { - std::unique_ptr<MemberDef> md { createMemberDef(root->tagInfo()->tagName,1,1, + std::unique_ptr<MemberDefMutable> md { createMemberDef(root->tagInfo()->tagName,1,1, "#define",root->name,root->args,0, Public,Normal,FALSE,Member,MemberType_Define, ArgumentList(),ArgumentList(),"") }; @@ -8166,9 +8371,10 @@ static void findDefineDocumentation(Entry *root) } if (count==1) { - for (const auto &md : *mn) + for (const auto &imd : *mn) { - if (md->memberType()==MemberType_Define) + MemberDefMutable *md = toMemberDefMutable(imd.get()); + if (md && md->memberType()==MemberType_Define) { md->setDocumentation(root->doc,root->docFile,root->docLine); md->setDocsForDefinition(!root->proto); @@ -8183,7 +8389,7 @@ static void findDefineDocumentation(Entry *root) md->setMaxInitLines(root->initLines); md->setRefItems(root->sli); if (root->mGrpId!=-1) md->setMemberGroupId(root->mGrpId); - addMemberToGroups(root,md.get()); + addMemberToGroups(root,md); } } } @@ -8196,27 +8402,18 @@ static void findDefineDocumentation(Entry *root) // multiple defines don't know where to add docs // but maybe they are in different files together with their documentation { - for (const auto &md : *mn) + for (const auto &imd : *mn) { - if (md->memberType()==MemberType_Define) + MemberDefMutable *md = toMemberDefMutable(imd.get()); + if (md && md->memberType()==MemberType_Define) { const FileDef *fd=md->getFileDef(); if (fd && fd->absFilePath()==root->fileName) // doc and define in the same file assume they belong together. { -#if 0 - if (md->documentation().isEmpty()) -#endif - { - md->setDocumentation(root->doc,root->docFile,root->docLine); - md->setDocsForDefinition(!root->proto); - } -#if 0 - if (md->briefDescription().isEmpty()) -#endif - { - md->setBriefDescription(root->brief,root->briefFile,root->briefLine); - } + md->setDocumentation(root->doc,root->docFile,root->docLine); + md->setDocsForDefinition(!root->proto); + md->setBriefDescription(root->brief,root->briefFile,root->briefLine); if (md->inbodyDocumentation().isEmpty()) { md->setInbodyDocumentation(root->inbodyDocs,root->inbodyFile,root->inbodyLine); @@ -8227,7 +8424,7 @@ static void findDefineDocumentation(Entry *root) md->setRefItems(root->sli); md->setLanguage(root->lang); if (root->mGrpId!=-1) md->setMemberGroupId(root->mGrpId); - addMemberToGroups(root,md.get()); + addMemberToGroups(root,md); } } } @@ -8358,6 +8555,7 @@ static void findMainPage(Entry *root) { if (Doxygen::mainPage==0 && root->tagInfo()==0) { + //printf("mainpage: docLine=%d startLine=%d\n",root->docLine,root->startLine); //printf("Found main page! \n======\n%s\n=======\n",root->doc.data()); QCString title=root->args.stripWhiteSpace(); //QCString indexName=Config_getBool(GENERATE_TREEVIEW)?"main":"index"; @@ -8366,6 +8564,7 @@ static void findMainPage(Entry *root) indexName, root->brief+root->doc+root->inbodyDocs,title); //setFileNameForSections(root->anchors,"index",Doxygen::mainPage); Doxygen::mainPage->setBriefDescription(root->brief,root->briefFile,root->briefLine); + Doxygen::mainPage->setBodySegment(root->startLine,root->startLine,-1); Doxygen::mainPage->setFileName(indexName); Doxygen::mainPage->setLocalToc(root->localToc); addPageToContext(Doxygen::mainPage,root); @@ -8401,7 +8600,7 @@ static void findMainPage(Entry *root) { warn(root->fileName,root->startLine, "found more than one \\mainpage comment block! (first occurrence: %s, line %d), Skipping current block!", - Doxygen::mainPage->docFile().data(),Doxygen::mainPage->docLine()); + Doxygen::mainPage->docFile().data(),Doxygen::mainPage->getStartBodyLine()); } } for (const auto &e : root->children()) findMainPage(e.get()); @@ -8520,7 +8719,7 @@ static void resolveUserReferences() const GroupDef *gd=0; if (si->definition()->definitionType()==Definition::TypeMember) { - gd = (dynamic_cast<MemberDef *>(si->definition()))->getGroupDef(); + gd = (toMemberDef(si->definition()))->getGroupDef(); } if (gd) @@ -8624,8 +8823,8 @@ static void generateExampleDocs() for (pdi.toFirst();(pd=pdi.current());++pdi) { msg("Generating docs for example %s...\n",pd->name().data()); - CodeParserInterface &intf = Doxygen::parserManager->getCodeParser(".c"); // TODO: do this on code type - intf.resetCodeParserState(); + auto intf = Doxygen::parserManager->getCodeParser(".c"); // TODO: do this on code type + intf->resetCodeParserState(); QCString n=pd->getOutputFileBase(); startFile(*g_outputList,n,n,pd->name()); startTitle(*g_outputList,n); @@ -8697,19 +8896,23 @@ static void generateNamespaceClassDocs(ClassSDict *d) ClassDef *cd; for ( ; (cd=cli.current()) ; ++cli ) { - if ( ( cd->isLinkableInProject() && - cd->templateMaster()==0 - ) // skip external references, anonymous compounds and - // template instances and nested classes - && !cd->isHidden() && !cd->isEmbeddedInOuterScope() - ) + ClassDefMutable *cdm = toClassDefMutable(cd); + if (cdm) { - msg("Generating docs for compound %s...\n",cd->name().data()); + if ( ( cd->isLinkableInProject() && + cd->templateMaster()==0 + ) // skip external references, anonymous compounds and + // template instances and nested classes + && !cd->isHidden() && !cd->isEmbeddedInOuterScope() + ) + { + msg("Generating docs for compound %s...\n",cd->name().data()); - cd->writeDocumentation(*g_outputList); - cd->writeMemberList(*g_outputList); + cdm->writeDocumentation(*g_outputList); + cdm->writeMemberList(*g_outputList); + } + cdm->writeDocumentationForInnerClasses(*g_outputList); } - cd->writeDocumentationForInnerClasses(*g_outputList); } } @@ -8727,8 +8930,12 @@ static void generateNamespaceDocs() if (nd->isLinkableInProject()) { - msg("Generating docs for namespace %s\n",nd->name().data()); - nd->writeDocumentation(*g_outputList); + NamespaceDefMutable *ndm = toNamespaceDefMutable(nd); + if (ndm) + { + msg("Generating docs for namespace %s\n",nd->name().data()); + ndm->writeDocumentation(*g_outputList); + } } generateNamespaceClassDocs(nd->getClassSDict()); @@ -9022,8 +9229,8 @@ static void generateDiskNames() // as the common prefix between the first and last entry const FileEntry &first = fileEntries[0]; const FileEntry &last = fileEntries[size-1]; - int first_path_size = static_cast<int>(first.path.size()); - int last_path_size = static_cast<int>(last.path.size()); + int first_path_size = static_cast<int>(first.path.size())-1; // -1 to skip trailing slash + int last_path_size = static_cast<int>(last.path.size())-1; // -1 to skip trailing slash int j=0; for (int i=0;i<first_path_size && i<last_path_size;i++) { @@ -9473,7 +9680,7 @@ static int readDir(QFileInfo *fi, { if (errorIfNotExist) { - warn_uncond("source %s is not a readable file or directory... skipping.\n",cfi->absFilePath().data()); + warn_uncond("source '%s' is not a readable file or directory... skipping.\n",cfi->absFilePath().data()); } } else if (cfi->isFile() && @@ -9553,7 +9760,7 @@ int readFileOrDirectory(const char *s, { if (errorIfNotExist) { - warn_uncond("source %s is not a readable file or directory... skipping.\n",s); + warn_uncond("source '%s' is not a readable file or directory... skipping.\n",s); } } else if (!Config_getBool(EXCLUDE_SYMLINKS) || !fi.isSymLink()) @@ -9631,6 +9838,7 @@ static void escapeAliases() newValue+=value.mid(p,in-p); // expand \n's except if \n is part of a built-in command. if (value.mid(in,5)!="\\note" && + value.mid(in,5)!="\\noop" && value.mid(in,5)!="\\name" && value.mid(in,10)!="\\namespace" && value.mid(in,14)!="\\nosubgrouping" @@ -9704,7 +9912,7 @@ static void dumpSymbol(FTextStream &t,Definition *d) QCString anchor; if (d->definitionType()==Definition::TypeMember) { - MemberDef *md = dynamic_cast<MemberDef *>(d); + MemberDef *md = toMemberDef(d); anchor=":"+md->anchor(); } QCString scope; @@ -9727,25 +9935,9 @@ static void dumpSymbolMap() if (f.open(IO_WriteOnly)) { FTextStream t(&f); - QDictIterator<DefinitionIntf> di(*Doxygen::symbolMap); - DefinitionIntf *intf; - for (;(intf=di.current());++di) + for (const auto &kv : Doxygen::symbolMap) { - if (intf->definitionType()==DefinitionIntf::TypeSymbolList) // list of symbols - { - DefinitionListIterator dli(*(DefinitionList*)intf); - Definition *d; - // for each symbol - for (dli.toFirst();(d=dli.current());++dli) - { - dumpSymbol(t,d); - } - } - else // single symbol - { - Definition *d = (Definition *)intf; - if (d!=Doxygen::globalScope) dumpSymbol(t,d); - } + dumpSymbol(t,kv.second); } } } @@ -9825,7 +10017,7 @@ class NullOutlineParser : public OutlineParserInterface }; -template<class T> std::function< std::unique_ptr<T>() > make_output_parser_factory() +template<class T> std::function< std::unique_ptr<T>() > make_parser_factory() { return []() { return std::make_unique<T>(); }; } @@ -9842,26 +10034,26 @@ void initDoxygen() Portable::correct_path(); Debug::startTimer(); - Doxygen::parserManager = new ParserManager( make_output_parser_factory<NullOutlineParser>(), - std::make_unique<FileCodeParser>()); - Doxygen::parserManager->registerParser("c", make_output_parser_factory<COutlineParser>(), - std::make_unique<CCodeParser>()); - Doxygen::parserManager->registerParser("python", make_output_parser_factory<PythonOutlineParser>(), - std::make_unique<PythonCodeParser>()); - Doxygen::parserManager->registerParser("fortran", make_output_parser_factory<FortranOutlineParser>(), - std::make_unique<FortranCodeParser>()); - Doxygen::parserManager->registerParser("fortranfree", make_output_parser_factory<FortranOutlineParserFree>(), - std::make_unique<FortranCodeParserFree>()); - Doxygen::parserManager->registerParser("fortranfixed", make_output_parser_factory<FortranOutlineParserFixed>(), - std::make_unique<FortranCodeParserFixed>()); - Doxygen::parserManager->registerParser("vhdl", make_output_parser_factory<VHDLOutlineParser>(), - std::make_unique<VHDLCodeParser>()); - Doxygen::parserManager->registerParser("xml", make_output_parser_factory<NullOutlineParser>(), - std::make_unique<XMLCodeParser>()); - Doxygen::parserManager->registerParser("sql", make_output_parser_factory<NullOutlineParser>(), - std::make_unique<SQLCodeParser>()); - Doxygen::parserManager->registerParser("md", make_output_parser_factory<MarkdownOutlineParser>(), - std::make_unique<FileCodeParser>()); + Doxygen::parserManager = new ParserManager( make_parser_factory<NullOutlineParser>(), + make_parser_factory<FileCodeParser>()); + Doxygen::parserManager->registerParser("c", make_parser_factory<COutlineParser>(), + make_parser_factory<CCodeParser>()); + Doxygen::parserManager->registerParser("python", make_parser_factory<PythonOutlineParser>(), + make_parser_factory<PythonCodeParser>()); + Doxygen::parserManager->registerParser("fortran", make_parser_factory<FortranOutlineParser>(), + make_parser_factory<FortranCodeParser>()); + Doxygen::parserManager->registerParser("fortranfree", make_parser_factory<FortranOutlineParserFree>(), + make_parser_factory<FortranCodeParserFree>()); + Doxygen::parserManager->registerParser("fortranfixed", make_parser_factory<FortranOutlineParserFixed>(), + make_parser_factory<FortranCodeParserFixed>()); + Doxygen::parserManager->registerParser("vhdl", make_parser_factory<VHDLOutlineParser>(), + make_parser_factory<VHDLCodeParser>()); + Doxygen::parserManager->registerParser("xml", make_parser_factory<NullOutlineParser>(), + make_parser_factory<XMLCodeParser>()); + Doxygen::parserManager->registerParser("sql", make_parser_factory<NullOutlineParser>(), + make_parser_factory<SQLCodeParser>()); + Doxygen::parserManager->registerParser("md", make_parser_factory<MarkdownOutlineParser>(), + make_parser_factory<FileCodeParser>()); // register any additional parsers here... @@ -9870,7 +10062,6 @@ void initDoxygen() initNamespaceMemberIndices(); initFileMemberIndices(); - Doxygen::symbolMap = new QDict<DefinitionIntf>(50177); #ifdef USE_LIBCLANG Doxygen::clangUsrMap = new QDict<Definition>(50177); #endif @@ -9943,26 +10134,6 @@ void cleanUpDoxygen() delete g_outputList; Mappers::freeMappers(); - if (Doxygen::symbolMap) - { - // iterate through Doxygen::symbolMap and delete all - // DefinitionList objects, since they have no owner - QDictIterator<DefinitionIntf> dli(*Doxygen::symbolMap); - DefinitionIntf *di; - for (dli.toFirst();(di=dli.current());) - { - if (di->definitionType()==DefinitionIntf::TypeSymbolList) - { - DefinitionIntf *tmp = Doxygen::symbolMap->take(dli.currentKey()); - delete (DefinitionList *)tmp; - } - else - { - ++dli; - } - } - } - delete Doxygen::memberNameLinkedMap; delete Doxygen::functionNameLinkedMap; delete Doxygen::groupSDict; @@ -9972,11 +10143,6 @@ void cleanUpDoxygen() delete Doxygen::directories; DotManager::deleteInstance(); - - //delete Doxygen::symbolMap; <- we cannot do this unless all static lists - // (such as Doxygen::namespaceSDict) - // with objects based on Definition are made - // dynamic first } static int computeIdealCacheParam(uint v) @@ -10037,15 +10203,15 @@ void readConfiguration(int argc, char **argv) debugLabel=getArg(argc,argv,optind); if (!debugLabel) { - err("option \"-d\" is missing debug specifier.\n"); devUsage(); cleanUpDoxygen(); - exit(1); + exit(0); } retVal = Debug::setFlag(debugLabel); if (!retVal) { err("option \"-d\" has unknown debug specifier: \"%s\".\n",debugLabel); + devUsage(); cleanUpDoxygen(); exit(1); } @@ -10440,7 +10606,7 @@ void adjustConfiguration() } else { - msg("Adding custom extension mapping: .%s will be treated as language %s\n", + msg("Adding custom extension mapping: '%s' will be treated as language '%s'\n", ext.data(),language.data()); } } @@ -10520,14 +10686,22 @@ static void writeTagFile() ClassDef *cd; for ( ; (cd=cli.current()) ; ++cli ) { - if (cd->isLinkableInProject()) cd->writeTagFile(tagFile); + ClassDefMutable *cdm = toClassDefMutable(cd); + if (cdm && cdm->isLinkableInProject()) + { + cdm->writeTagFile(tagFile); + } } // for each namespace NamespaceSDict::Iterator nli(*Doxygen::namespaceSDict); NamespaceDef *nd; for ( ; (nd=nli.current()) ; ++nli ) { - if (nd->isLinkableInProject()) nd->writeTagFile(tagFile); + NamespaceDefMutable *ndm = toNamespaceDefMutable(nd); + if (ndm && nd->isLinkableInProject()) + { + ndm->writeTagFile(tagFile); + } } // for each group GroupSDict::Iterator gli(*Doxygen::groupSDict); @@ -10838,14 +11012,14 @@ void parseInput() if (!dir.mkdir(outputDirectory)) { err("tag OUTPUT_DIRECTORY: Output directory '%s' does not " - "exist and cannot be created\n",outputDirectory.data()); + "exist and cannot be created\n",outputDirectory.data()); cleanUpDoxygen(); exit(1); } else { - msg("Notice: Output directory '%s' does not exist. " - "I have created it for you.\n", outputDirectory.data()); + msg("Notice: Output directory '%s' does not exist. " + "I have created it for you.\n", outputDirectory.data()); } dir.cd(outputDirectory); } @@ -10861,8 +11035,7 @@ void parseInput() if (cacheSize<0) cacheSize=0; if (cacheSize>9) cacheSize=9; uint lookupSize = 65536 << cacheSize; - Doxygen::lookupCache = new QCache<LookupInfo>(lookupSize,lookupSize); - Doxygen::lookupCache->setAutoDelete(TRUE); + Doxygen::lookupCache = new Cache<std::string,LookupInfo>(lookupSize); #ifdef HAS_SIGNALS signal(SIGINT, stopDoxygen); @@ -11351,6 +11524,10 @@ void parseInput() vhdlCorrectMemberProperties(); g_s.end(); + g_s.begin("Computing tooltip texts...\n"); + computeTooltipTexts(); + g_s.end(); + if (Config_getBool(SORT_GROUP_NAMES)) { Doxygen::groupSDict->sort(); @@ -11504,6 +11681,8 @@ void generateOutput() generateExampleDocs(); g_s.end(); + warn_flush(); + g_s.begin("Generating file sources...\n"); generateFileSources(); g_s.end(); @@ -11608,6 +11787,8 @@ void generateOutput() if (g_useOutputTemplate) generateOutputViaTemplate(); + warn_flush(); + if (generateRtf) { g_s.begin("Combining RTF output...\n"); @@ -11618,10 +11799,14 @@ void generateOutput() g_s.end(); } + warn_flush(); + g_s.begin("Running plantuml with JAVA...\n"); PlantumlManager::instance()->run(); g_s.end(); + warn_flush(); + if (Config_getBool(HAVE_DOT)) { g_s.begin("Running dot...\n"); @@ -11669,6 +11854,9 @@ void generateOutput() QDir::setCurrent(oldDir); g_s.end(); } + + warn_flush(); + if ( generateHtml && Config_getBool(GENERATE_QHP) && !Config_getString(QHG_LOCATION).isEmpty()) @@ -11691,9 +11879,9 @@ void generateOutput() } int cacheParam; - msg("lookup cache used %d/%d hits=%d misses=%d\n", - Doxygen::lookupCache->count(), + msg("lookup cache used %zu/%zu hits=%" PRIu64 " misses=%" PRIu64 "\n", Doxygen::lookupCache->size(), + Doxygen::lookupCache->capacity(), Doxygen::lookupCache->hits(), Doxygen::lookupCache->misses()); cacheParam = computeIdealCacheParam(Doxygen::lookupCache->misses()*2/3); // part of the cache is flushed, hence the 2/3 correction factor @@ -11728,7 +11916,6 @@ void generateOutput() thisDir.remove(Doxygen::filterDBFileName); Config::deinit(); QTextCodec::deleteAllCodecs(); - delete Doxygen::symbolMap; delete Doxygen::clangUsrMap; g_successfulRun=TRUE; } diff --git a/src/doxygen.h b/src/doxygen.h index dc05750..8ab8679 100644 --- a/src/doxygen.h +++ b/src/doxygen.h @@ -17,7 +17,6 @@ #define DOXYGEN_H #include <qdatetime.h> -#include <qcache.h> #include <qstrlist.h> #include <qdict.h> #include <qintdict.h> @@ -29,6 +28,8 @@ #include "dirdef.h" #include "memberlist.h" #include "define.h" +#include "cache.h" +#include "symbolmap.h" #define THREAD_LOCAL thread_local #define AtomicInt std::atomic_int @@ -54,7 +55,6 @@ class MemberNameLinkedMap; class FileNameLinkedMap; class NamespaceSDict; class NamespaceDef; -class DefinitionIntf; class DirSDict; class DirRelation; class IndexList; @@ -63,11 +63,10 @@ class FormulaDict; class FormulaNameDict; class Preprocessor; struct MemberGroupInfo; +class NamespaceDefMutable; typedef QList<QCString> StringList; typedef QListIterator<QCString> StringListIterator; -//typedef QDict<FileDef> FileDict; -//typedef QDict<GroupDef> GroupDict; class StringDict : public QDict<QCString> { @@ -78,11 +77,11 @@ class StringDict : public QDict<QCString> struct LookupInfo { - LookupInfo() : classDef(0), typeDef(0) {} + LookupInfo() = default; LookupInfo(const ClassDef *cd,const MemberDef *td,QCString ts,QCString rt) : classDef(cd), typeDef(td), templSpec(ts),resolvedType(rt) {} - const ClassDef *classDef; - const MemberDef *typeDef; + const ClassDef *classDef = 0; + const MemberDef *typeDef = 0; QCString templSpec; QCString resolvedType; }; @@ -119,15 +118,15 @@ class Doxygen static StringDict aliasDict; static QIntDict<MemberGroupInfo> memGrpInfoDict; static StringUnorderedSet expandAsDefinedSet; - static NamespaceDef *globalScope; + static NamespaceDefMutable *globalScope; static QCString htmlFileExtension; static bool parseSourcesNeeded; static SearchIndexIntf *searchIndex; - static QDict<DefinitionIntf> *symbolMap; + static SymbolMap<Definition> symbolMap; static QDict<Definition> *clangUsrMap; static bool outputToWizard; static QDict<int> *htmlDirMap; - static QCache<LookupInfo> *lookupCache; + static Cache<std::string,LookupInfo> *lookupCache; static DirSDict *directories; static SDict<DirRelation> dirRelations; static ParserManager *parserManager; diff --git a/src/doxygen.md b/src/doxygen.md index d8db231..e3db534 100644 --- a/src/doxygen.md +++ b/src/doxygen.md @@ -7,7 +7,7 @@ Introduction This page provides a high-level overview of the internals of doxygen, with links to the relevant parts of the code. This document is intended for developers who want to work on doxygen. Users of doxygen are referred to the -[User Manual](http://www.doxygen.nl/manual/index.html). +[User Manual](https://www.doxygen.nl/manual/index.html). The generic starting point of the application is of course the main() function. @@ -15,13 +15,13 @@ Configuration options ===================== Configuration file data is stored in singleton class Config and can be -accessed using wrapper macros +accessed using wrapper macros Config_getString(), Config_getInt(), Config_getList(), Config_getEnum(), and Config_getBool() depending on the type of the -option. +option. The format of the configuration file (options and types) is defined -by the file `config.xml`. As part of the build process, +by the file `config.xml`. As part of the build process, the python script `configgen.py` will create a file `configoptions.cpp` from this, which serves as the input for the configuration file parser that is invoked using Config::parse(). The script `configgen.py` will also @@ -43,18 +43,18 @@ for each file. Each parser implements the abstract interface ParserInterface. If the parser indicates it needs preprocessing via ParserInterface::needsPreprocessing(), doxygen will call preprocessFile() -on the file. +on the file. A second step is to convert multiline C++-style comments into C style comments -for easier processing later on. As side effect of this step also -aliases (ALIASES option) are resolved. The function that performs these +for easier processing later on. As side effect of this step also +aliases (ALIASES option) are resolved. The function that performs these 2 tasks is called convertCppComments(). *Note:* Alias resolution should better be done in a separate step as it is now coupled to C/C++ code and does not work automatically for other languages! -The third step is the actual language parsing and is done by calling -ParserInterface::parseInput() on the parser interface returned by +The third step is the actual language parsing and is done by calling +ParserInterface::parseInput() on the parser interface returned by the ParserManager. The result of parsing is a tree of Entry objects. @@ -67,19 +67,19 @@ converted into a Definition object. When a parser finds a special comment block in the input, it will do a first pass parsing via parseCommentBlock(). During this pass the comment block is split into multiple parts if needed. Some data that is later needed is -extracted like section labels, xref items, and formulas. +extracted like section labels, xref items, and formulas. Also Markdown markup is processed using processMarkdown() during this pass. Resolving relations =================== -The Entry objects created and filled during parsing are stored on disk -(to keep memory needs low). The name, parent/child relation, and -location on disk of each Entry is stored as a tree of EntryNav nodes, which is +The Entry objects created and filled during parsing are stored on disk +(to keep memory needs low). The name, parent/child relation, and +location on disk of each Entry is stored as a tree of EntryNav nodes, which is kept in memory. Doxygen does a number of tree walks over the EntryNav nodes in the tree to -build up the data structures needed to produce the output. +build up the data structures needed to produce the output. The resulting data structures are all children of the generic base class called Definition which holds all non-specific data for a symbol definition. @@ -141,9 +141,9 @@ easy ways to get debug information. - classes<br> Gives of classes en modules its scope and other relevant information. - preprocessor<br> - Shows the results of the preprocessing phase, i.e. results from include files, + Shows the results of the preprocessing phase, i.e. results from include files, <tt>\#define</tt> statements etc., definitions in the doxygen configuration file like: - `EXPAND_ONLY_PREDEF`, `PREDEFINED` and `MACRO_EXPANSION`. + `EXPAND_ONLY_PREDEF`, `PREDEFINED` and `MACRO_EXPANSION`. - commentcnv<br> Shows the results of the comment conversion, the comment conversion does the following: @@ -216,8 +216,8 @@ Topics TODO - perlmod - i18n via Translator and language.cpp - Customizing the layout via LayoutDocManager -- Parsers - - C Preprocessing +- Parsers + - C Preprocessing - const expression evaluation - C link languages - Python diff --git a/src/filedef.cpp b/src/filedef.cpp index f07201d..68c2218 100644 --- a/src/filedef.cpp +++ b/src/filedef.cpp @@ -48,14 +48,14 @@ //--------------------------------------------------------------------------- -class FileDefImpl : public DefinitionImpl, public FileDef +class FileDefImpl : public DefinitionMixin<FileDef> { public: FileDefImpl(const char *p,const char *n,const char *ref=0,const char *dn=0); virtual ~FileDefImpl(); virtual DefType definitionType() const { return TypeFile; } - virtual const QCString &name() const; + virtual QCString name() const; virtual QCString displayName(bool=TRUE) const { return name(); } virtual QCString fileName() const { return m_fileName; } @@ -78,8 +78,8 @@ class FileDefImpl : public DefinitionImpl, public FileDef virtual bool isIncluded(const QCString &name) const; virtual PackageDef *packageDef() const { return m_package; } virtual DirDef *getDirDef() const { return m_dir; } - virtual NamespaceSDict *getUsedNamespaces() const; - virtual SDict<Definition> *getUsedClasses() const { return m_usingDeclList; } + virtual LinkedRefMap<const NamespaceDef> getUsedNamespaces() const; + virtual LinkedRefMap<const ClassDef> getUsedClasses() const { return m_usingDeclList; } virtual QList<IncludeInfo> *includeFileList() const { return m_includeList; } virtual QList<IncludeInfo> *includedByFileList() const { return m_includedByList; } virtual void getAllIncludeFilesRecursively(StringVector &incFiles) const; @@ -101,7 +101,9 @@ class FileDefImpl : public DefinitionImpl, public FileDef virtual void writeQuickMemberLinks(OutputList &ol,const MemberDef *currentMd) const; virtual void writeSummaryLinks(OutputList &ol) const; virtual void writeTagFile(FTextStream &t); - virtual void writeSource(OutputList &ol,ClangTUParser *clangParser); + virtual void writeSourceHeader(OutputList &ol); + virtual void writeSourceBody(OutputList &ol,ClangTUParser *clangParser); + virtual void writeSourceFooter(OutputList &ol); virtual void parseSource(ClangTUParser *clangParser); virtual void setDiskName(const QCString &name); virtual void insertMember(MemberDef *md); @@ -111,7 +113,7 @@ class FileDefImpl : public DefinitionImpl, public FileDef virtual void setPackageDef(PackageDef *pd) { m_package=pd; } virtual void setDirDef(DirDef *dd) { m_dir=dd; } virtual void addUsingDirective(const NamespaceDef *nd); - virtual void addUsingDeclaration(Definition *def); + virtual void addUsingDeclaration(const ClassDef *cd); virtual void combineUsingRelations(); virtual bool generateSourceFile() const; virtual void sortMemberLists(); @@ -120,13 +122,10 @@ class FileDefImpl : public DefinitionImpl, public FileDef virtual void addMembersToMemberGroup(); virtual void distributeMemberGroupDocumentation(); virtual void findSectionsInDocumentation(); - virtual void addIncludedUsingDirectives(); + virtual void addIncludedUsingDirectives(FileDefSet &visitedFiles); virtual void addListReferences(); - virtual void setVisited(bool v) { m_visited = v; } - virtual bool isVisited() const { return m_visited; } private: - bool m_visited; void acquireFileVersion(); MemberList *createMemberList(MemberListType lt); void addMemberToList(MemberListType lt,MemberDef *md); @@ -154,8 +153,8 @@ class FileDefImpl : public DefinitionImpl, public FileDef QList<IncludeInfo> *m_includeList; QDict<IncludeInfo> *m_includedByDict; QList<IncludeInfo> *m_includedByList; - NamespaceSDict *m_usingDirList; - SDict<Definition> *m_usingDeclList; + LinkedRefMap<const NamespaceDef> m_usingDirList; + LinkedRefMap<const ClassDef> m_usingDeclList; QCString m_path; QCString m_filePath; QCString m_inclDepFileName; @@ -208,6 +207,8 @@ class DevNullCodeDocInterface : public CodeOutputInterface virtual void linkableSymbol(int, const char *,Definition *,Definition *) {} virtual void setCurrentDoc(const Definition *,const char *,bool) {} virtual void addWord(const char *,bool) {} + virtual void startCodeFragment(const char *) {} + virtual void endCodeFragment(const char *) {} }; //--------------------------------------------------------------------------- @@ -218,7 +219,7 @@ class DevNullCodeDocInterface : public CodeOutputInterface */ FileDefImpl::FileDefImpl(const char *p,const char *nm, const char *lref,const char *dn) - : DefinitionImpl((QCString)p+nm,1,1,nm) + : DefinitionMixin((QCString)p+nm,1,1,nm) { m_path=p; m_filePath=m_path+nm; @@ -236,13 +237,10 @@ FileDefImpl::FileDefImpl(const char *p,const char *nm, m_namespaceSDict = 0; m_srcDefDict = 0; m_srcMemberDict = 0; - m_usingDirList = 0; - m_usingDeclList = 0; m_package = 0; m_isSource = guessSection(nm)==Entry::SOURCE_SEC; m_docname = nm; m_dir = 0; - m_visited = FALSE; if (Config_getBool(FULL_PATH_NAMES)) { m_docname.prepend(stripFromPath(m_path.copy())); @@ -267,8 +265,6 @@ FileDefImpl::~FileDefImpl() delete m_namespaceSDict; delete m_srcDefDict; delete m_srcMemberDict; - delete m_usingDirList; - delete m_usingDeclList; delete m_memberGroupSDict; } @@ -292,7 +288,7 @@ void FileDefImpl::setDiskName(const QCString &name) void FileDefImpl::computeAnchors() { MemberList *ml = getMemberList(MemberListType_allMembersList); - if (ml) setAnchors(ml); + if (ml) ml->setAnchors(); } void FileDefImpl::distributeMemberGroupDocumentation() @@ -311,6 +307,7 @@ void FileDefImpl::distributeMemberGroupDocumentation() void FileDefImpl::findSectionsInDocumentation() { + docFindSections(briefDescription(),this,docFile()); docFindSections(documentation(),this,docFile()); if (m_memberGroupSDict) { @@ -1149,14 +1146,12 @@ void FileDefImpl::writeQuickMemberLinks(OutputList &ol,const MemberDef *currentM } /*! Write a source listing of this file to the output */ -void FileDefImpl::writeSource(OutputList &ol,ClangTUParser *clangParser) +void FileDefImpl::writeSourceHeader(OutputList &ol) { bool generateTreeView = Config_getBool(GENERATE_TREEVIEW); - bool filterSourceFiles = Config_getBool(FILTER_SOURCE_FILES); bool latexSourceCode = Config_getBool(LATEX_SOURCE_CODE); bool docbookSourceCode = Config_getBool(DOCBOOK_PROGRAMLISTING); bool rtfSourceCode = Config_getBool(RTF_SOURCE_CODE); - DevNullCodeDocInterface devNullIntf; QCString title = m_docname; if (!m_fileVersion.isEmpty()) { @@ -1206,22 +1201,27 @@ void FileDefImpl::writeSource(OutputList &ol,ClangTUParser *clangParser) ol.endTextLink(); ol.popGeneratorState(); } +} +void FileDefImpl::writeSourceBody(OutputList &ol,ClangTUParser *clangParser) +{ + bool filterSourceFiles = Config_getBool(FILTER_SOURCE_FILES); + DevNullCodeDocInterface devNullIntf; #if USE_LIBCLANG if (Doxygen::clangAssistedParsing && clangParser && (getLanguage()==SrcLangExt_Cpp || getLanguage()==SrcLangExt_ObjC)) { - ol.startCodeFragment(); + ol.startCodeFragment("DoxyCode"); clangParser->switchToFile(this); clangParser->writeSources(ol,this); - ol.endCodeFragment(); + ol.endCodeFragment("DoxyCode"); } else #endif { - CodeParserInterface &intf = Doxygen::parserManager->getCodeParser(getDefFileExtension()); - intf.resetCodeParserState(); - ol.startCodeFragment(); + auto intf = Doxygen::parserManager->getCodeParser(getDefFileExtension()); + intf->resetCodeParserState(); + ol.startCodeFragment("DoxyCode"); bool needs2PassParsing = Doxygen::parseSourcesNeeded && // we need to parse (filtered) sources for cross-references !filterSourceFiles && // but user wants to show sources as-is @@ -1230,13 +1230,13 @@ void FileDefImpl::writeSource(OutputList &ol,ClangTUParser *clangParser) if (needs2PassParsing) { // parse code for cross-references only (see bug707641) - intf.parseCode(devNullIntf,0, + intf->parseCode(devNullIntf,0, fileToString(absFilePath(),TRUE,TRUE), getLanguage(), FALSE,0,this ); } - intf.parseCode(ol,0, + intf->parseCode(ol,0, fileToString(absFilePath(),filterSourceFiles,TRUE), getLanguage(), // lang FALSE, // isExampleBlock @@ -1250,8 +1250,12 @@ void FileDefImpl::writeSource(OutputList &ol,ClangTUParser *clangParser) 0, // searchCtx !needs2PassParsing // collectXRefs ); - ol.endCodeFragment(); + ol.endCodeFragment("DoxyCode"); } +} + +void FileDefImpl::writeSourceFooter(OutputList &ol) +{ ol.endContents(); endFileWithNavPath(this,ol); ol.enableAll(); @@ -1271,9 +1275,9 @@ void FileDefImpl::parseSource(ClangTUParser *clangParser) else #endif { - CodeParserInterface &intf = Doxygen::parserManager->getCodeParser(getDefFileExtension()); - intf.resetCodeParserState(); - intf.parseCode( + auto intf = Doxygen::parserManager->getCodeParser(getDefFileExtension()); + intf->resetCodeParserState(); + intf->parseCode( devNullIntf,0, fileToString(absFilePath(),filterSourceFiles,TRUE), getLanguage(), @@ -1431,12 +1435,12 @@ void FileDefImpl::insertNamespace(NamespaceDef *nd) } } -const QCString &FileDefImpl::name() const +QCString FileDefImpl::name() const { if (Config_getBool(FULL_PATH_NAMES)) return m_fileName; else - return DefinitionImpl::name(); + return DefinitionMixin::name(); } void FileDefImpl::addSourceRef(int line,Definition *d,MemberDef *md) @@ -1478,33 +1482,19 @@ MemberDef *FileDefImpl::getSourceMember(int lineNr) const void FileDefImpl::addUsingDirective(const NamespaceDef *nd) { - if (m_usingDirList==0) - { - m_usingDirList = new NamespaceSDict; - } - if (m_usingDirList->find(nd->qualifiedName())==0) - { - m_usingDirList->append(nd->qualifiedName(),nd); - } + m_usingDirList.add(nd->qualifiedName(),nd); //printf("%p: FileDefImpl::addUsingDirective: %s:%d\n",this,name().data(),usingDirList->count()); } -NamespaceSDict *FileDefImpl::getUsedNamespaces() const +LinkedRefMap<const NamespaceDef> FileDefImpl::getUsedNamespaces() const { //printf("%p: FileDefImpl::getUsedNamespace: %s:%d\n",this,name().data(),usingDirList?usingDirList->count():0); return m_usingDirList; } -void FileDefImpl::addUsingDeclaration(Definition *d) +void FileDefImpl::addUsingDeclaration(const ClassDef *cd) { - if (m_usingDeclList==0) - { - m_usingDeclList = new SDict<Definition>(17); - } - if (m_usingDeclList->find(d->qualifiedName())==0) - { - m_usingDeclList->append(d->qualifiedName(),d); - } + m_usingDeclList.add(cd->qualifiedName(),cd); } void FileDefImpl::addIncludeDependency(FileDef *fd,const char *incName,bool local,bool imported) @@ -1529,10 +1519,10 @@ void FileDefImpl::addIncludeDependency(FileDef *fd,const char *incName,bool loca } } -void FileDefImpl::addIncludedUsingDirectives() +void FileDefImpl::addIncludedUsingDirectives(FileDefSet &visitedFiles) { - if (m_visited) return; - m_visited=TRUE; + if (visitedFiles.find(this)!=visitedFiles.end()) return; // file already processed + visitedFiles.insert(this); //printf("( FileDefImpl::addIncludedUsingDirectives for file %s\n",name().data()); if (m_includeList) // file contains #includes @@ -1542,10 +1532,10 @@ void FileDefImpl::addIncludedUsingDirectives() IncludeInfo *ii; for (iii.toFirst();(ii=iii.current());++iii) // foreach #include... { - if (ii->fileDef && !ii->fileDef->isVisited()) // ...that is a known file + if (ii->fileDef) // ...that is a known file { // recurse into this file - ii->fileDef->addIncludedUsingDirectives(); + ii->fileDef->addIncludedUsingDirectives(visitedFiles); } } } @@ -1558,41 +1548,18 @@ void FileDefImpl::addIncludedUsingDirectives() if (ii->fileDef && ii->fileDef!=this) { // add using directives - NamespaceSDict *unl = ii->fileDef->getUsedNamespaces(); - if (unl) + auto unl = ii->fileDef->getUsedNamespaces(); + for (auto it = unl.rbegin(); it!=unl.rend(); ++it) { - NamespaceSDict::Iterator nli(*unl); - NamespaceDef *nd; - for (nli.toLast();(nd=nli.current());--nli) - { - // append each using directive found in a #include file - if (m_usingDirList==0) m_usingDirList = new NamespaceSDict; - //printf("Prepending used namespace %s to the list of file %s\n", - // nd->name().data(),name().data()); - if (m_usingDirList->find(nd->qualifiedName())==0) // not yet added - { - m_usingDirList->prepend(nd->qualifiedName(),nd); - } - } + const auto *nd = *it; + m_usingDirList.prepend(nd->qualifiedName(),nd); } // add using declarations - SDict<Definition> *udl = ii->fileDef->getUsedClasses(); - if (udl) + auto udl = ii->fileDef->getUsedClasses(); + for (auto it = udl.rbegin(); it!=udl.rend(); ++it) { - SDict<Definition>::Iterator udi(*udl); - Definition *d; - for (udi.toLast();(d=udi.current());--udi) - { - //printf("Adding using declaration %s\n",d->name().data()); - if (m_usingDeclList==0) - { - m_usingDeclList = new SDict<Definition>(17); - } - if (m_usingDeclList->find(d->qualifiedName())==0) - { - m_usingDeclList->prepend(d->qualifiedName(),d); - } - } + const auto *cd = *it; + m_usingDeclList.prepend(cd->qualifiedName(),cd); } } } @@ -1919,40 +1886,28 @@ void generateFileTree() void FileDefImpl::combineUsingRelations() { - if (m_visited) return; // already done - m_visited=TRUE; - if (m_usingDirList) + LinkedRefMap<const NamespaceDef> usingDirList = m_usingDirList; + NamespaceDefSet visitedNamespaces; + for (auto &nd : usingDirList) + { + NamespaceDefMutable *ndm = toNamespaceDefMutable(nd); + if (ndm) + { + ndm->combineUsingRelations(visitedNamespaces); + } + } + + for (auto &nd : usingDirList) { - NamespaceSDict::Iterator nli(*m_usingDirList); - NamespaceDef *nd; - for (nli.toFirst();(nd=nli.current());++nli) + // add used namespaces of namespace nd to this namespace + for (const auto &und : nd->getUsedNamespaces()) { - nd->combineUsingRelations(); + addUsingDirective(und); } - for (nli.toFirst();(nd=nli.current());++nli) + // add used classes of namespace nd to this namespace + for (const auto &ucd : nd->getUsedClasses()) { - // add used namespaces of namespace nd to this namespace - if (nd->getUsedNamespaces()) - { - NamespaceSDict::Iterator unli(*nd->getUsedNamespaces()); - NamespaceDef *und; - for (unli.toFirst();(und=unli.current());++unli) - { - //printf("Adding namespace %s to the using list of %s\n",und->qualifiedName().data(),qualifiedName().data()); - addUsingDirective(und); - } - } - // add used classes of namespace nd to this namespace - if (nd->getUsedClasses()) - { - SDict<Definition>::Iterator cli(*nd->getUsedClasses()); - Definition *ucd; - for (cli.toFirst();(ucd=cli.current());++cli) - { - //printf("Adding class %s to the using list of %s\n",cd->qualifiedName().data(),qualifiedName().data()); - addUsingDeclaration(ucd); - } - } + addUsingDeclaration(ucd); } } } @@ -1963,7 +1918,8 @@ bool FileDefImpl::isDocumentationFile() const name().right(4)==".txt" || name().right(4)==".dox" || name().right(3)==".md" || - name().right(9)==".markdown"; + name().right(9)==".markdown" || + getLanguageFromFileName(getFileNameExtension(name())) == SrcLangExt_Markdown; } void FileDefImpl::acquireFileVersion() @@ -2054,7 +2010,14 @@ void FileDefImpl::addMemberToList(MemberListType lt,MemberDef *md) { ml->setInFile(TRUE); } - if (ml->listType()&MemberListType_declarationLists) md->setSectionList(this,ml); + if (ml->listType()&MemberListType_declarationLists) + { + MemberDefMutable *mdm = toMemberDefMutable(md); + if (mdm) + { + mdm->setSectionList(this,ml); + } + } } void FileDefImpl::sortMemberLists() @@ -2203,3 +2166,31 @@ int FileDefImpl::numDecMembers() const return ml ? ml->numDecMembers() : 0; } +// --- Cast functions + +FileDef *toFileDef(Definition *d) +{ + if (d==0) return 0; + if (d && typeid(*d)==typeid(FileDefImpl)) + { + return static_cast<FileDef*>(d); + } + else + { + return 0; + } +} + +const FileDef *toFileDef(const Definition *d) +{ + if (d==0) return 0; + if (d && typeid(*d)==typeid(FileDefImpl)) + { + return static_cast<const FileDef*>(d); + } + else + { + return 0; + } +} + diff --git a/src/filedef.h b/src/filedef.h index e4bb549..055078f 100644 --- a/src/filedef.h +++ b/src/filedef.h @@ -18,6 +18,8 @@ #ifndef FILEDEF_H #define FILEDEF_H +#include <set> + #include "index.h" #include <qlist.h> #include <qintdict.h> @@ -26,6 +28,7 @@ #include "sortdict.h" #include "memberlist.h" #include "containers.h" +#include "classlist.h" class MemberList; class FileDef; @@ -43,6 +46,10 @@ class DirDef; class FTextStream; class ClangTUParser; +// --- Set of files + +using FileDefSet = std::set<const FileDef*>; + /** Class representing the data associated with a \#include statement. */ struct IncludeInfo { @@ -62,7 +69,7 @@ struct IncludeInfo * The member writeDocumentation() can be used to generate the page of * documentation to HTML and LaTeX. */ -class FileDef : virtual public Definition +class FileDef : public DefinitionMutable, public Definition { public: ~FileDef() {} @@ -72,7 +79,7 @@ class FileDef : virtual public Definition virtual DefType definitionType() const = 0; /*! Returns the unique file name (this may include part of the path). */ - virtual const QCString &name() const = 0; + virtual QCString name() const = 0; virtual QCString displayName(bool=TRUE) const = 0; virtual QCString fileName() const = 0; @@ -116,8 +123,8 @@ class FileDef : virtual public Definition virtual PackageDef *packageDef() const = 0; virtual DirDef *getDirDef() const = 0; - virtual NamespaceSDict *getUsedNamespaces() const = 0; - virtual SDict<Definition> *getUsedClasses() const = 0; + virtual LinkedRefMap<const NamespaceDef> getUsedNamespaces() const = 0; + virtual LinkedRefMap<const ClassDef> getUsedClasses() const = 0; virtual QList<IncludeInfo> *includeFileList() const = 0; virtual QList<IncludeInfo> *includedByFileList() const = 0; virtual void getAllIncludeFilesRecursively(StringVector &incFiles) const = 0; @@ -150,7 +157,9 @@ class FileDef : virtual public Definition virtual void writeSummaryLinks(OutputList &ol) const = 0; virtual void writeTagFile(FTextStream &t) = 0; - virtual void writeSource(OutputList &ol,ClangTUParser *clangParser) = 0; + virtual void writeSourceHeader(OutputList &ol) = 0; + virtual void writeSourceBody(OutputList &ol,ClangTUParser *clangParser) = 0; + virtual void writeSourceFooter(OutputList &ol) = 0; virtual void parseSource(ClangTUParser *clangParser) = 0; virtual void setDiskName(const QCString &name) = 0; @@ -163,7 +172,7 @@ class FileDef : virtual public Definition virtual void setDirDef(DirDef *dd) = 0; virtual void addUsingDirective(const NamespaceDef *nd) = 0; - virtual void addUsingDeclaration(Definition *def) = 0; + virtual void addUsingDeclaration(const ClassDef *cd) = 0; virtual void combineUsingRelations() = 0; virtual bool generateSourceFile() const = 0; @@ -175,16 +184,21 @@ class FileDef : virtual public Definition virtual void addMembersToMemberGroup() = 0; virtual void distributeMemberGroupDocumentation() = 0; virtual void findSectionsInDocumentation() = 0; - virtual void addIncludedUsingDirectives() = 0; + virtual void addIncludedUsingDirectives(FileDefSet &visitedFiles) = 0; virtual void addListReferences() = 0; - - virtual void setVisited(bool v) = 0; - virtual bool isVisited() const = 0; }; FileDef *createFileDef(const char *p,const char *n,const char *ref=0,const char *dn=0); + +// --- Cast functions + +FileDef *toFileDef(Definition *d); +const FileDef *toFileDef(const Definition *d); + +// ------------------ + /** Class representing a list of FileDef objects. */ class FileList : public QList<FileDef> { diff --git a/src/filename.h b/src/filename.h index c3a0d3e..d236046 100644 --- a/src/filename.h +++ b/src/filename.h @@ -20,6 +20,7 @@ #include <vector> #include "linkedmap.h" +#include "config.h" class FileDef; @@ -38,8 +39,38 @@ class FileName : public std::vector< std::unique_ptr<FileDef> > QCString m_pathName; }; +//! Custom combined key compare and hash functor that uses a lower case string in +//! case CASE_SENSE_NAMES is set to NO. +class FileNameFn +{ + public: + //! used as hash function + std::size_t operator()(const std::string& input) const noexcept + { + return std::hash<std::string>()(searchKey(input)); + } + //! used as equal operator + bool operator() (const std::string &t1, const std::string &t2) const + { + return searchKey(t1) == searchKey(t2); + } + private: + std::string searchKey(std::string input) const + { + std::string key = input; + if (!Config_getBool(CASE_SENSE_NAMES)) + { + // convert key to lower case + std::transform(key.begin(),key.end(),key.begin(), + [](char c){ return (char)std::tolower(c); }); + } + return key; + } +}; + /** Ordered dictionary of FileName objects. */ -class FileNameLinkedMap : public LinkedMap<FileName> +class FileNameLinkedMap : public LinkedMap<FileName,FileNameFn,FileNameFn, + std::unordered_multimap<std::string,FileName*,FileNameFn,FileNameFn> > { }; diff --git a/src/formula.cpp b/src/formula.cpp index ca50c9c..8ba9729 100644 --- a/src/formula.cpp +++ b/src/formula.cpp @@ -148,7 +148,7 @@ void FormulaManager::generateImages(const char *path,Format format,HighDPI hd) c // store the original directory if (!d.exists()) { - term("Output dir %s does not exist!\n",path); + term("Output directory '%s' does not exist!\n",path); } QCString oldDir = QDir::currentDirPath().utf8(); QCString macroFile = Config_getString(FORMULA_MACROFILE); @@ -167,7 +167,6 @@ void FormulaManager::generateImages(const char *path,Format format,HighDPI hd) c QCString texName="_formulas.tex"; IntVector formulasToGenerate; QFile f(texName); - bool formulaError=FALSE; if (f.open(IO_WriteOnly)) { FTextStream t(&f); @@ -214,8 +213,9 @@ void FormulaManager::generateImages(const char *path,Format format,HighDPI hd) c { err("Problems running latex. Check your installation or look " "for typos in _formulas.tex and check _formulas.log!\n"); - formulaError=TRUE; - //return; + Portable::sysTimerStop(); + QDir::setCurrent(oldDir); + return; } Portable::sysTimerStop(); //printf("Running dvips...\n"); @@ -439,12 +439,12 @@ void FormulaManager::generateImages(const char *path,Format format,HighDPI hd) c if (RM_TMP_FILES) { thisDir.remove("_formulas.dvi"); - if (!formulaError) thisDir.remove("_formulas.log"); // keep file in case of errors + thisDir.remove("_formulas.log"); // keep file in case of errors thisDir.remove("_formulas.aux"); } } // remove the latex file itself - if (RM_TMP_FILES && !formulaError) thisDir.remove("_formulas.tex"); + if (RM_TMP_FILES) thisDir.remove("_formulas.tex"); // write/update the formula repository so we know what text the // generated images represent (we use this next time to avoid regeneration diff --git a/src/fortrancode.h b/src/fortrancode.h index 7da6a61..b8cac31 100644 --- a/src/fortrancode.h +++ b/src/fortrancode.h @@ -1,12 +1,12 @@ /****************************************************************************** * - * + * * * Copyright (C) 1997-2015 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,13 +26,11 @@ class MemberDef; class QCString; class Definition; -void codeFreeScanner(); - - class FortranCodeParser : public CodeParserInterface { public: - FortranCodeParser(FortranFormat format=FortranFormat_Unknown) : m_format(format) { } + FortranCodeParser(FortranFormat format=FortranFormat_Unknown); + virtual ~FortranCodeParser(); void parseCode(CodeOutputInterface &codeOutIntf, const char *scopeName, const QCString &input, @@ -51,7 +49,8 @@ class FortranCodeParser : public CodeParserInterface void resetCodeParserState(); private: - FortranFormat m_format; + struct Private; + std::unique_ptr<Private> p; }; class FortranCodeParserFree : public FortranCodeParser diff --git a/src/fortrancode.l b/src/fortrancode.l index 4951001..1c1287d 100644 --- a/src/fortrancode.l +++ b/src/fortrancode.l @@ -4,6 +4,7 @@ * * Copyright (C) by Anke Visser * based on the work of Dimitri van Heesch. + * Copyright (C) 2020 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 @@ -25,7 +26,9 @@ **/ %option never-interactive %option case-insensitive +%option reentrant %option prefix="fortrancodeYY" +%option extra-type="struct fortrancodeYY_state *" %option noyy_top_state %top{ #include <stdint.h> @@ -34,7 +37,7 @@ %{ /* - * includes + * includes */ #include <stdio.h> #include <assert.h> @@ -58,6 +61,7 @@ #include "namespacedef.h" #include "tooltip.h" #include "fortrancode.h" +#include "fortranscanner.h" #include "containers.h" const int fixedCommentAfter = 72; @@ -121,219 +125,904 @@ class Scope /*===================================================================*/ /* - * statics + * statics */ -static QCString docBlock; //!< contents of all lines of a documentation block -static QCString currentModule=0; //!< name of the current enclosing module -static QCString currentClass=0; //!< name of the current enclosing class -static UseSDict *useMembers= new UseSDict; //!< info about used modules -static UseEntry *useEntry = 0; //!< current use statement info -static QList<Scope> scopeStack; -static bool g_isExternal = false; -// static QCStringList *currentUseNames= new QCStringList; //! contains names of used modules of current program unit -static QCString g_str=""; //!> contents of fortran string - -static CodeOutputInterface * g_code; - -// TODO: is this still needed? if so, make it work -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 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 const Definition *g_searchCtx; -static bool g_collectXRefs; -static bool g_isFixedForm; - -static bool g_insideBody; //!< inside subprog/program body? => create links -static const char * g_currentFontClass; - -static bool g_exampleBlock; -static QCString g_exampleName; -static QCString g_exampleFile; - -static FileDef * g_sourceFileDef; -static Definition * g_currentDefinition; -static MemberDef * g_currentMemberDef; -static bool g_includeCodeFragment; - -static char stringStartSymbol; // single or double quote +struct fortrancodeYY_state +{ + QCString docBlock; //!< contents of all lines of a documentation block + QCString currentModule=0; //!< name of the current enclosing module + UseSDict * useMembers= 0; //!< info about used modules + UseEntry * useEntry = 0; //!< current use statement info + QList<Scope> scopeStack; + bool isExternal = false; + QCString str=""; //!> contents of fortran string + + CodeOutputInterface * code = 0; + + const char * inputString = 0; //!< the code fragment as text + yy_size_t inputPosition = 0; //!< read offset during parsing + int inputLines = 0; //!< number of line in the code fragment + int yyLineNr = 0; //!< current line number + int contLineNr = 0; //!< current, local, line number for continuation determination + int *hasContLine = 0; //!< signals whether or not a line has a continuation line (fixed source form) + bool needsTermination = false; + const Definition *searchCtx = 0; + bool collectXRefs = false; + bool isFixedForm = false; + + bool insideBody = false; //!< inside subprog/program body? => create links + const char * currentFontClass = 0; + + bool exampleBlock = false; + QCString exampleName; + QCString exampleFile; + + FileDef * sourceFileDef = 0; + Definition * currentDefinition = 0; + MemberDef * currentMemberDef = 0; + bool includeCodeFragment = false; + + char stringStartSymbol = '\0'; // single or double quote // count in variable declaration to filter out // declared from referenced names -static int bracketCount = 0; + int bracketCount = 0; // signal when in type / class /procedure declaration -static int inTypeDecl = 0; + int inTypeDecl = 0; -static bool g_endComment; + bool endComment = false; +}; #if USE_STATE2STRING static const char *stateToString(int state); #endif -static void endFontClass() +static bool getFortranNamespaceDefs(const QCString &mname, + NamespaceDef *&cd); +static bool getFortranTypeDefs(const QCString &tname, const QCString &moduleName, + ClassDef *&cd, UseSDict *usedict=0); + +//---------------------------------------------------------------------------- + +static void endFontClass(yyscan_t yyscanner); +static void startFontClass(yyscan_t yyscanner,const char *s); +static void setCurrentDoc(yyscan_t yyscanner,const QCString &anchor); +static void addToSearchIndex(yyscan_t yyscanner,const char *text); +static void startCodeLine(yyscan_t yyscanner); +static void endCodeLine(yyscan_t yyscanner); +static void nextCodeLine(yyscan_t yyscanner); +static void codifyLines(yyscan_t yyscanner,const char *text); +static void writeMultiLineCodeLink(yyscan_t yyscanner,CodeOutputInterface &ol, + Definition *d,const char *text); +static bool getGenericProcedureLink(yyscan_t yyscanner,const ClassDef *cd, + const char *memberText, + CodeOutputInterface &ol); +static bool getLink(yyscan_t yyscanner,UseSDict *usedict, // dictionary with used modules + const char *memberText, // exact member text + CodeOutputInterface &ol, + const char *text); +static void generateLink(yyscan_t yyscanner,CodeOutputInterface &ol, char *lname); +static int countLines(yyscan_t yyscanner); +static void startScope(yyscan_t yyscanner); +static void endScope(yyscan_t yyscanner); +static void addUse(yyscan_t yyscanner,const QCString &moduleName); +static void addLocalVar(yyscan_t yyscanner,const QCString &varName); +static MemberDef *getFortranDefs(yyscan_t yyscanner,const QCString &memberName, const QCString &moduleName, + UseSDict *usedict=0); +static yy_size_t yyread(yyscan_t yyscanner,char *buf,yy_size_t max_size); + + +//------------------------------------------------------------------- + +static std::mutex g_docCrossReferenceMutex; +static std::mutex g_countFlowKeywordsMutex; + +/* -----------------------------------------------------------------*/ +#undef YY_INPUT +#define YY_INPUT(buf,result,max_size) result=yyread(yyscanner,buf,max_size); + +%} + +IDSYM [a-z_A-Z0-9] +ID [a-z_A-Z]+{IDSYM}* +SUBPROG (subroutine|function) +B [ \t] +BS [ \t]* +BS_ [ \t]+ +COMMA {BS},{BS} +ARGS_L0 ("("[^)]*")") +ARGS_L1a [^()]*"("[^)]*")"[^)]* +ARGS_L1 ("("{ARGS_L1a}*")") +ARGS_L2 "("({ARGS_L0}|[^()]|{ARGS_L1a}|{ARGS_L1})*")" +ARGS {BS}({ARGS_L0}|{ARGS_L1}|{ARGS_L2}) + +NUM_TYPE (complex|integer|logical|real) +LOG_OPER (\.and\.|\.eq\.|\.eqv\.|\.ge\.|\.gt\.|\.le\.|\.lt\.|\.ne\.|\.neqv\.|\.or\.|\.not\.) +KIND {ARGS} +CHAR (CHARACTER{ARGS}?|CHARACTER{BS}"*"({BS}[0-9]+|{ARGS})) +TYPE_SPEC (({NUM_TYPE}({BS}"*"{BS}[0-9]+)?)|({NUM_TYPE}{KIND})|DOUBLE{BS}COMPLEX|DOUBLE{BS}PRECISION|{CHAR}|TYPE|CLASS|PROCEDURE|ENUMERATOR) + +INTENT_SPEC intent{BS}"("{BS}(in|out|in{BS}out){BS}")" +ATTR_SPEC (IMPLICIT|ALLOCATABLE|DIMENSION{ARGS}|EXTERNAL|{INTENT_SPEC}|INTRINSIC|OPTIONAL|PARAMETER|POINTER|PROTECTED|PRIVATE|PUBLIC|SAVE|TARGET|(NON_)?RECURSIVE|PURE|IMPURE|ELEMENTAL|VALUE|NOPASS|DEFERRED|CONTIGUOUS|VOLATILE) +ACCESS_SPEC (PROTECTED|PRIVATE|PUBLIC) +/* Assume that attribute statements are almost the same as attributes. */ +ATTR_STMT {ATTR_SPEC}|DIMENSION +FLOW (DO|SELECT|CASE|SELECT{BS}(CASE|TYPE)|WHERE|IF|THEN|ELSE|WHILE|FORALL|ELSEWHERE|ELSEIF|RETURN|CONTINUE|EXIT|GO{BS}TO) +COMMANDS (FORMAT|CONTAINS|MODULE{BS_}PROCEDURE|WRITE|READ|ALLOCATE|ALLOCATED|ASSOCIATED|PRESENT|DEALLOCATE|NULLIFY|SIZE|INQUIRE|OPEN|CLOSE|FLUSH|DATA|COMMON) +IGNORE (CALL) +PREFIX ((NON_)?RECURSIVE{BS_}|IMPURE{BS_}|PURE{BS_}|ELEMENTAL{BS_}){0,4}((NON_)?RECURSIVE|IMPURE|PURE|ELEMENTAL)?0 +LANGUAGE_BIND_SPEC BIND{BS}"("{BS}C{BS}(,{BS}NAME{BS}"="{BS}"\""(.*)"\""{BS})?")" + +/* | */ + +%option noyywrap +%option stack +%option caseless +/*%option debug*/ + +%x Start +%x SubCall +%x FuncDef +%x ClassName +%x ClassVar +%x Subprog +%x DocBlock +%x Use +%x UseOnly +%x Import +%x Declaration +%x DeclarationBinding +%x DeclContLine +%x Parameterlist +%x String +%x Subprogend + +%% + /*==================================================================*/ + + /*-------- ignore ------------------------------------------------------------*/ + +<Start>{IGNORE}/{BS}"(" { // do not search keywords, intrinsics... TODO: complete list + codifyLines(yyscanner,yytext); + } + /*-------- inner construct ---------------------------------------------------*/ + +<Start>{COMMANDS}/{BS}[,( \t\n] { // highlight + /* font class is defined e.g. in doxygen.css */ + startFontClass(yyscanner,"keyword"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + } +<Start>{FLOW}/{BS}[,( \t\n] { + if (yyextra->isFixedForm) + { + if ((yy_my_start == 1) && ((yytext[0] == 'c') || (yytext[0] == 'C'))) YY_FTN_REJECT; + } + if (yyextra->currentMemberDef && yyextra->currentMemberDef->isFunction()) + { + std::lock_guard<std::mutex> lock(g_countFlowKeywordsMutex); + MemberDefMutable *mdm = toMemberDefMutable(yyextra->currentMemberDef); + if (mdm) + { + mdm->incrementFlowKeyWordCount(); + } + } + /* font class is defined e.g. in doxygen.css */ + startFontClass(yyscanner,"keywordflow"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + } +<Start>{BS}(CASE|CLASS|TYPE){BS_}(IS|DEFAULT) { + startFontClass(yyscanner,"keywordflow"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + } +<Start>{BS}"end"({BS}{FLOW})/[ \t\n] { // list is a bit long as not all have possible end + startFontClass(yyscanner,"keywordflow"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + } +<Start>"implicit"{BS}("none"|{TYPE_SPEC}) { + startFontClass(yyscanner,"keywordtype"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + } +<Start>^{BS}"namelist"/[//] { // Namelist specification + startFontClass(yyscanner,"keywordtype"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + } + /*-------- use statement -------------------------------------------*/ +<Start>"use"{BS_} { + startFontClass(yyscanner,"keywordtype"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + yy_push_state(YY_START,yyscanner); + BEGIN(Use); + } +<Use>"ONLY" { // TODO: rename + startFontClass(yyscanner,"keywordtype"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + yy_push_state(YY_START,yyscanner); + BEGIN(UseOnly); + } +<Use>{ID} { + QCString tmp = yytext; + tmp = tmp.lower(); + yyextra->insideBody=TRUE; + generateLink(yyscanner,*yyextra->code, yytext); + yyextra->insideBody=FALSE; + + /* append module name to use dict */ + yyextra->useEntry = new UseEntry(); + //yyextra->useEntry->module = yytext; + //yyextra->useMembers->append(yytext, yyextra->useEntry); + //addUse(yytext); + yyextra->useEntry->module = tmp; + yyextra->useMembers->append(tmp, yyextra->useEntry); + addUse(yyscanner,tmp); + } +<Use,UseOnly,Import>{BS},{BS} { codifyLines(yyscanner,yytext); } +<UseOnly,Import>{BS}&{BS}"\n" { codifyLines(yyscanner,yytext); + yyextra->contLineNr++; + YY_FTN_RESET} +<UseOnly>{ID} { + QCString tmp = yytext; + tmp = tmp.lower(); + yyextra->useEntry->onlyNames.append(tmp); + yyextra->insideBody=TRUE; + generateLink(yyscanner,*yyextra->code, yytext); + yyextra->insideBody=FALSE; + } +<Use,UseOnly,Import>"\n" { + unput(*yytext); + yy_pop_state(yyscanner); + YY_FTN_RESET + } +<*>"import"{BS}/"\n" | +<*>"import"{BS_} { + startFontClass(yyscanner,"keywordtype"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + yy_push_state(YY_START,yyscanner); + BEGIN(Import); + } +<Import>{ID} { + yyextra->insideBody=TRUE; + generateLink(yyscanner,*yyextra->code, yytext); + yyextra->insideBody=FALSE; + } +<Import>("ONLY"|"NONE"|"ALL") { + startFontClass(yyscanner,"keywordtype"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + } + /*-------- fortran module -----------------------------------------*/ +<Start>("block"{BS}"data"|"program"|"module"|"interface")/{BS_}|({COMMA}{ACCESS_SPEC})|\n { // + startScope(yyscanner); + startFontClass(yyscanner,"keyword"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + yy_push_state(YY_START,yyscanner); + BEGIN(ClassName); + if (!qstricmp(yytext,"module")) yyextra->currentModule="module"; + } +<Start>("enum")/{BS_}|{BS}{COMMA}{BS}{LANGUAGE_BIND_SPEC}|\n { // + startScope(yyscanner); + startFontClass(yyscanner,"keyword"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + yy_push_state(YY_START,yyscanner); + BEGIN(ClassName); + } +<*>{LANGUAGE_BIND_SPEC} { // + startFontClass(yyscanner,"keyword"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + } +<Start>("type")/{BS_}|({COMMA}({ACCESS_SPEC}|ABSTRACT|EXTENDS))|\n { // + startScope(yyscanner); + startFontClass(yyscanner,"keyword"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + yy_push_state(YY_START,yyscanner); + BEGIN(ClassName); + } +<ClassName>{ID} { + if (yyextra->currentModule == "module") + { + yyextra->currentModule=yytext; + yyextra->currentModule = yyextra->currentModule.lower(); + } + generateLink(yyscanner,*yyextra->code,yytext); + yy_pop_state(yyscanner); + } +<ClassName>({ACCESS_SPEC}|ABSTRACT|EXTENDS)/[,:( ] { //| variable declaration + startFontClass(yyscanner,"keyword"); + yyextra->code->codify(yytext); + endFontClass(yyscanner); + } +<ClassName>\n { // interface may be without name + yy_pop_state(yyscanner); + YY_FTN_REJECT; + } +<Start>^{BS}"end"({BS_}"enum").* { + YY_FTN_REJECT; + } +<Start>^{BS}"end"({BS_}"type").* { + YY_FTN_REJECT; + } +<Start>^{BS}"end"({BS_}"module").* { // just reset yyextra->currentModule, rest is done in following rule + yyextra->currentModule=0; + YY_FTN_REJECT; + } + /*-------- subprog definition -------------------------------------*/ +<Start>({PREFIX}{BS_})?{TYPE_SPEC}{BS_}({PREFIX}{BS_})?{BS}/{SUBPROG}{BS_} { // TYPE_SPEC is for old function style function result + startFontClass(yyscanner,"keyword"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + } +<Start>({PREFIX}{BS_})?{SUBPROG}{BS_} { // Fortran subroutine or function found + startFontClass(yyscanner,"keyword"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + yy_push_state(YY_START,yyscanner); + BEGIN(Subprog); + } +<Subprog>{ID} { // subroutine/function name + DBG_CTX((stderr, "===> start subprogram %s\n", yytext)); + startScope(yyscanner); + generateLink(yyscanner,*yyextra->code,yytext); + } +<Subprog>"result"/{BS}"("[^)]*")" { + startFontClass(yyscanner,"keyword"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + } +<Subprog>"("[^)]*")" { // ignore rest of line + codifyLines(yyscanner,yytext); + } +<Subprog,Subprogend>"\n" { codifyLines(yyscanner,yytext); + yyextra->contLineNr++; + yy_pop_state(yyscanner); + YY_FTN_RESET + } +<Start>"end"{BS}("block"{BS}"data"|{SUBPROG}|"module"|"program"|"enum"|"type"|"interface")?{BS} { // Fortran subroutine or function ends + //cout << "===> end function " << yytext << endl; + endScope(yyscanner); + startFontClass(yyscanner,"keyword"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + yy_push_state(YY_START,yyscanner); + BEGIN(Subprogend); + } +<Subprogend>{ID}/{BS}(\n|!|;) { + generateLink(yyscanner,*yyextra->code,yytext); + yy_pop_state(yyscanner); + } +<Start>"end"{BS}("block"{BS}"data"|{SUBPROG}|"module"|"program"|"enum"|"type"|"interface"){BS}/(\n|!|;) { // Fortran subroutine or function ends + //cout << "===> end function " << yytext << endl; + endScope(yyscanner); + startFontClass(yyscanner,"keyword"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + } + /*-------- variable declaration ----------------------------------*/ +<Start>^{BS}"real"/[,:( ] { // real is a bit tricky as it is a data type but also a function. + yy_push_state(YY_START,yyscanner); + BEGIN(Declaration); + startFontClass(yyscanner,"keywordtype"); + yyextra->code->codify(yytext); + endFontClass(yyscanner); + } +<Start>{TYPE_SPEC}/[,:( ] { + QCString typ = yytext; + typ = removeRedundantWhiteSpace(typ.lower()); + if (typ.startsWith("real")) YY_FTN_REJECT; + if (typ == "type" || typ == "class" || typ == "procedure") yyextra->inTypeDecl = 1; + yy_push_state(YY_START,yyscanner); + BEGIN(Declaration); + startFontClass(yyscanner,"keywordtype"); + yyextra->code->codify(yytext); + endFontClass(yyscanner); + } +<Start>{ATTR_SPEC} { + if (QCString(yytext) == "external") + { + yy_push_state(YY_START,yyscanner); + BEGIN(Declaration); + yyextra->isExternal = true; + } + startFontClass(yyscanner,"keywordtype"); + yyextra->code->codify(yytext); + endFontClass(yyscanner); + } +<Declaration>({TYPE_SPEC}|{ATTR_SPEC})/[,:( ] { //| variable declaration + if (QCString(yytext) == "external") yyextra->isExternal = true; + startFontClass(yyscanner,"keywordtype"); + yyextra->code->codify(yytext); + endFontClass(yyscanner); + } +<Declaration>{ID} { // local var + if (yyextra->isFixedForm && yy_my_start == 1) + { + startFontClass(yyscanner,"comment"); + yyextra->code->codify(yytext); + endFontClass(yyscanner); + } + else if (yyextra->currentMemberDef && + ((yyextra->currentMemberDef->isFunction() && (yyextra->currentMemberDef->typeString()!=QCString("subroutine") || yyextra->inTypeDecl)) || + yyextra->currentMemberDef->isVariable() || yyextra->currentMemberDef->isEnumValue() + ) + ) + { + generateLink(yyscanner,*yyextra->code, yytext); + } + else + { + yyextra->code->codify(yytext); + addLocalVar(yyscanner,yytext); + } + } +<Declaration>{BS}("=>"|"="){BS} { // Procedure binding + BEGIN(DeclarationBinding); + yyextra->code->codify(yytext); + } +<DeclarationBinding>{ID} { // Type bound procedure link + generateLink(yyscanner,*yyextra->code, yytext); + yy_pop_state(yyscanner); + } +<Declaration>[(] { // start of array or type / class specification + yyextra->bracketCount++; + yyextra->code->codify(yytext); + } + +<Declaration>[)] { // end array specification + yyextra->bracketCount--; + if (!yyextra->bracketCount) yyextra->inTypeDecl = 0; + yyextra->code->codify(yytext); + } + +<Declaration,DeclarationBinding>"&" { // continuation line + yyextra->code->codify(yytext); + if (!yyextra->isFixedForm) + { + yy_push_state(YY_START,yyscanner); + BEGIN(DeclContLine); + } + } +<DeclContLine>"\n" { // declaration not yet finished + yyextra->contLineNr++; + codifyLines(yyscanner,yytext); + yyextra->bracketCount = 0; + yy_pop_state(yyscanner); + YY_FTN_RESET + } +<Declaration,DeclarationBinding>"\n" { // end declaration line (?) + if (yyextra->endComment) + { + yyextra->endComment=FALSE; + } + else + { + codifyLines(yyscanner,yytext); + } + yyextra->bracketCount = 0; + yyextra->contLineNr++; + if (!(yyextra->hasContLine && yyextra->hasContLine[yyextra->contLineNr - 1])) + { + yyextra->isExternal = false; + yy_pop_state(yyscanner); + } + YY_FTN_RESET + } + + /*-------- subprog calls -----------------------------------------*/ + +<Start>"call"{BS_} { + startFontClass(yyscanner,"keyword"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + yy_push_state(YY_START,yyscanner); + BEGIN(SubCall); + } +<SubCall>{ID} { // subroutine call + yyextra->insideBody=TRUE; + generateLink(yyscanner,*yyextra->code, yytext); + yyextra->insideBody=FALSE; + yy_pop_state(yyscanner); + } +<Start>{ID}{BS}/"(" { // function call + if (yyextra->isFixedForm && yy_my_start == 6) + { + // fixed form continuation line + YY_FTN_REJECT; + } + else if (QCString(yytext).stripWhiteSpace().lower() == "type") + { + yy_push_state(YY_START,yyscanner); + BEGIN(Declaration); + startFontClass(yyscanner,"keywordtype"); + yyextra->code->codify(QCString(yytext).stripWhiteSpace()); + endFontClass(yyscanner); + yyextra->code->codify(yytext + 4); + } + else + { + yyextra->insideBody=TRUE; + generateLink(yyscanner,*yyextra->code, yytext); + yyextra->insideBody=FALSE; + } + } + + /*-------- comments ---------------------------------------------------*/ +<Start,Declaration,DeclarationBinding>\n?{BS}"!>"|"!<" { // start comment line or comment block + if (yytext[0] == '\n') + { + yyextra->contLineNr++; + yy_old_start = 0; + yy_my_start = 1; + yy_end = static_cast<int>(yyleng); + } + // Actually we should see if ! on position 6, can be continuation + // but the chance is very unlikely, so no effort to solve it here + yy_push_state(YY_START,yyscanner); + BEGIN(DocBlock); + yyextra->docBlock=yytext; + } +<Declaration,DeclarationBinding>{BS}"!<" { // start comment line or comment block + yy_push_state(YY_START,yyscanner); + BEGIN(DocBlock); + yyextra->docBlock=yytext; + } + +<DocBlock>.* { // contents of current comment line + yyextra->docBlock+=yytext; + } +<DocBlock>"\n"{BS}("!>"|"!<"|"!!") { // comment block (next line is also comment line) + yyextra->contLineNr++; + yy_old_start = 0; + yy_my_start = 1; + yy_end = static_cast<int>(yyleng); + // Actually we should see if ! on position 6, can be continuation + // but the chance is very unlikely, so no effort to solve it here + yyextra->docBlock+=yytext; + } +<DocBlock>"\n" { // comment block ends at the end of this line + // remove special comment (default config) + yyextra->contLineNr++; + if (Config_getBool(STRIP_CODE_COMMENTS)) + { + yyextra->yyLineNr+=((QCString)yyextra->docBlock).contains('\n'); + yyextra->yyLineNr+=1; + nextCodeLine(yyscanner); + yyextra->endComment=TRUE; + } + else // do not remove comment + { + startFontClass(yyscanner,"comment"); + codifyLines(yyscanner,yyextra->docBlock); + endFontClass(yyscanner); + } + unput(*yytext); + yyextra->contLineNr--; + yy_pop_state(yyscanner); + YY_FTN_RESET + } + +<*>"!"[^><\n].*|"!"$ { // normal comment + if(YY_START == String) YY_FTN_REJECT; // ignore in strings + if (yyextra->isFixedForm && yy_my_start == 6) YY_FTN_REJECT; + startFontClass(yyscanner,"comment"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + } + +<*>^[Cc*].* { // normal comment + if(! yyextra->isFixedForm) YY_FTN_REJECT; + + startFontClass(yyscanner,"comment"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + } +<*>"assignment"/{BS}"("{BS}"="{BS}")" { + startFontClass(yyscanner,"keyword"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + } +<*>"operator"/{BS}"("[^)]*")" { + startFontClass(yyscanner,"keyword"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + } + + /*------ preprocessor --------------------------------------------*/ +<Start>"#".*\n { + if (yyextra->isFixedForm && yy_my_start == 6) YY_FTN_REJECT; + yyextra->contLineNr++; + startFontClass(yyscanner,"preprocessor"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + YY_FTN_RESET + } + /*------ variable references? -------------------------------------*/ + +<Start>"%"{BS}{ID} { // ignore references to elements + yyextra->code->codify(yytext); + } +<Start>{ID} { + yyextra->insideBody=TRUE; + generateLink(yyscanner,*yyextra->code, yytext); + yyextra->insideBody=FALSE; + } + /*------ strings --------------------------------------------------*/ +<String>\n { // string with \n inside + yyextra->contLineNr++; + yyextra->str+=yytext; + startFontClass(yyscanner,"stringliteral"); + codifyLines(yyscanner,yyextra->str); + endFontClass(yyscanner); + yyextra->str = ""; + YY_FTN_RESET + } +<String>\"|\' { // string ends with next quote without previous backspace + if(yytext[0]!=yyextra->stringStartSymbol) YY_FTN_REJECT; // single vs double quote + yyextra->str+=yytext; + startFontClass(yyscanner,"stringliteral"); + codifyLines(yyscanner,yyextra->str); + endFontClass(yyscanner); + yy_pop_state(yyscanner); + } +<String>. {yyextra->str+=yytext;} + +<*>\"|\' { /* string starts */ + /* if(YY_START == StrIgnore) YY_FTN_REJECT; // ignore in simple comments */ + if (yyextra->isFixedForm && yy_my_start == 6) YY_FTN_REJECT; + yy_push_state(YY_START,yyscanner); + yyextra->stringStartSymbol=yytext[0]; // single or double quote + BEGIN(String); + yyextra->str=yytext; + } + /*-----------------------------------------------------------------------------*/ + +<*>\n { + if (yyextra->endComment) + { + yyextra->endComment=FALSE; + } + else + { + codifyLines(yyscanner,yytext); + // comment cannot extend over the end of a line so should always be terminated at the end of the line. + if (yyextra->currentFontClass && !strcmp(yyextra->currentFontClass,"comment")) endFontClass(yyscanner); + } + yyextra->contLineNr++; + YY_FTN_RESET + } +<*>^{BS}"type"{BS}"=" { yyextra->code->codify(yytext); } + +<*>[\x80-\xFF]* { // keep utf8 characters together... + if (yyextra->isFixedForm && yy_my_start > fixedCommentAfter) + { + startFontClass(yyscanner,"comment"); + codifyLines(yyscanner,yytext); + } + else + { + yyextra->code->codify(yytext); + } + } +<*>. { + if (yyextra->isFixedForm && yy_my_start > fixedCommentAfter) + { + //yy_push_state(YY_START,yyscanner); + //BEGIN(DocBlock); + //yyextra->docBlock=yytext; + startFontClass(yyscanner,"comment"); + codifyLines(yyscanner,yytext); + } + else + { + yyextra->code->codify(yytext); + } + } +<*>{LOG_OPER} { // Fortran logical comparison keywords + yyextra->code->codify(yytext); + } +<*><<EOF>> { + if (YY_START == DocBlock) { + if (!Config_getBool(STRIP_CODE_COMMENTS)) + { + startFontClass(yyscanner,"comment"); + codifyLines(yyscanner,yyextra->docBlock); + endFontClass(yyscanner); + } + } + yyterminate(); + } +%% + +/*@ ---------------------------------------------------------------------------- + */ + +static yy_size_t yyread(yyscan_t yyscanner,char *buf,yy_size_t max_size) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + yy_size_t inputPosition = yyextra->inputPosition; + const char *s = yyextra->inputString + inputPosition; + yy_size_t c=0; + while( c < max_size && *s) + { + *buf++ = *s++; + c++; + } + yyextra->inputPosition += c; + return c; +} + +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 startFontClass(const char *s) +static void startFontClass(yyscan_t yyscanner,const char *s) { + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; // if font class is already set don't stop and start it. // strcmp does not like null pointers as input. - if (!g_currentFontClass || !s || strcmp(g_currentFontClass,s)) + if (!yyextra->currentFontClass || !s || strcmp(yyextra->currentFontClass,s)) { - endFontClass(); - g_code->startFontClass(s); - g_currentFontClass=s; + endFontClass(yyscanner); + yyextra->code->startFontClass(s); + yyextra->currentFontClass=s; } } -static void setCurrentDoc(const QCString &anchor) +static void setCurrentDoc(yyscan_t yyscanner,const QCString &anchor) { + 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); + yyextra->code->setCurrentDoc(yyextra->searchCtx,yyextra->searchCtx->anchor(),FALSE); } else { - Doxygen::searchIndex->setCurrentDoc(g_sourceFileDef,anchor,TRUE); + yyextra->code->setCurrentDoc(yyextra->sourceFileDef,anchor,TRUE); } } } -static void addToSearchIndex(const char *text) +static void addToSearchIndex(yyscan_t yyscanner,const char *text) { + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; if (Doxygen::searchIndex) { - Doxygen::searchIndex->addWord(text,FALSE); + yyextra->code->addWord(text,FALSE); } } -/*! 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) { //QCString lineNumber,lineAnchor; - //lineNumber.sprintf("%05d",g_yyLineNr); - //lineAnchor.sprintf("l%05d",g_yyLineNr); + //lineNumber.sprintf("%05d",yyextra->yyLineNr); + //lineAnchor.sprintf("l%05d",yyextra->yyLineNr); - Definition *d = g_sourceFileDef->getSourceDefinition(g_yyLineNr); - //printf("startCodeLine %d d=%s\n", g_yyLineNr,d ? d->name().data() : "<null>"); - if (!g_includeCodeFragment && d) + Definition *d = yyextra->sourceFileDef->getSourceDefinition(yyextra->yyLineNr); + //printf("startCodeLine %d d=%s\n", yyextra->yyLineNr,d ? d->name().data() : "<null>"); + if (!yyextra->includeCodeFragment && d) { - g_currentDefinition = d; - g_currentMemberDef = g_sourceFileDef->getSourceMember(g_yyLineNr); - g_insideBody = FALSE; - g_endComment = FALSE; - g_parmType.resize(0); - g_parmName.resize(0); + yyextra->currentDefinition = d; + yyextra->currentMemberDef = yyextra->sourceFileDef->getSourceMember(yyextra->yyLineNr); + yyextra->insideBody = FALSE; + yyextra->endComment = FALSE; 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(yyscanner,lineAnchor); } else if (d->isLinkableInProject()) { - g_code->writeLineNumber(d->getReference(), - d->getOutputFileBase(), - 0,g_yyLineNr); - setCurrentDoc(lineAnchor); + yyextra->code->writeLineNumber(d->getReference(), + d->getOutputFileBase(), + 0,yyextra->yyLineNr); + setCurrentDoc(yyscanner,lineAnchor); } } else { - g_code->writeLineNumber(0,0,0,g_yyLineNr); + yyextra->code->writeLineNumber(0,0,0,yyextra->yyLineNr); } } - g_code->startCodeLine(g_sourceFileDef); - if (g_currentFontClass) + yyextra->code->startCodeLine(yyextra->sourceFileDef); + if (yyextra->currentFontClass) { - g_code->startFontClass(g_currentFontClass); + yyextra->code->startFontClass(yyextra->currentFontClass); } } -static void endFontClass(); -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(yyscan_t yyscanner) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + const char * fc = yyextra->currentFontClass; + endCodeLine(yyscanner); + if (yyextra->yyLineNr<yyextra->inputLines) + { + yyextra->currentFontClass = fc; + startCodeLine(yyscanner); + } } /*! write a code fragment 'text' that may span multiple lines, inserting * line numbers for each line. */ -static void codifyLines(char *text) +static void codifyLines(yyscan_t yyscanner,const char *text) { - //printf("codifyLines(%d,\"%s\")\n",g_yyLineNr,text); - char *p=text,*sp=p; + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + //printf("codifyLines(%d,\"%s\")\n",yyextra->yyLineNr,text); + const char *p=text,*sp=p; char c; bool done=FALSE; - const char * tmp_currentFontClass = g_currentFontClass; while (!done) { sp=p; while ((c=*p++) && c!='\n') { } if (c=='\n') { - g_yyLineNr++; - *(p-1)='\0'; - g_code->codify(sp); - endCodeLine(); - if (g_yyLineNr<g_inputLines) - { - startCodeLine(); - } - if (tmp_currentFontClass) - { - startFontClass(tmp_currentFontClass); - } + yyextra->yyLineNr++; + int l = (int)(p-sp-1); + char *tmp = (char*)malloc(l+1); + memcpy(tmp,sp,l); + tmp[l]='\0'; + yyextra->code->codify(tmp); + free(tmp); + nextCodeLine(yyscanner); } else { - g_code->codify(sp); + yyextra->code->codify(sp); done=TRUE; } } } -static void codifyLines(QCString str) -{ - char *tmp= (char *) malloc(str.length()+1); - strcpy(tmp, str); - codifyLines(tmp); - free(tmp); -} - /*! writes a link to a fragment \a text that may span multiple lines, inserting * line numbers for each line. If \a text contains newlines, the link will be * split into multiple links with the same destination, one for each line. */ -static void writeMultiLineCodeLink(CodeOutputInterface &ol, +static void writeMultiLineCodeLink(yyscan_t yyscanner,CodeOutputInterface &ol, Definition *d,const char *text) { + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; static bool sourceTooltips = Config_getBool(SOURCE_TOOLTIPS); - TooltipManager::instance()->addTooltip(d); + TooltipManager::instance().addTooltip(ol,d); QCString ref = d->getReference(); QCString file = d->getOutputFileBase(); QCString anchor = d->anchor(); @@ -351,15 +1040,11 @@ static void writeMultiLineCodeLink(CodeOutputInterface &ol, while ((c=*p++) && c!='\n') { } if (c=='\n') { - g_yyLineNr++; + yyextra->yyLineNr++; *(p-1)='\0'; //printf("writeCodeLink(%s,%s,%s,%s)\n",ref,file,anchor,sp); ol.writeCodeLink(ref,file,anchor,sp,tooltip); - endCodeLine(); - if (g_yyLineNr<g_inputLines) - { - startCodeLine(); - } + nextCodeLine(yyscanner); } else { @@ -396,7 +1081,7 @@ static bool getFortranNamespaceDefs(const QCString &mname, @returns true, if type is found */ static bool getFortranTypeDefs(const QCString &tname, const QCString &moduleName, - ClassDef *&cd, UseSDict *usedict=0) + ClassDef *&cd, UseSDict *usedict) { if (tname.isEmpty()) return FALSE; /* empty name => nothing to link */ @@ -420,7 +1105,7 @@ static bool getFortranTypeDefs(const QCString &tname, const QCString &moduleName { if ((cd= Doxygen::classSDict->find(use->module+"::"+tname))) { - //cout << "=== type found in used module" << endl; + //cout << "=== type found in used module" << endl; return TRUE; } } @@ -436,13 +1121,14 @@ static bool getFortranTypeDefs(const QCString &tname, const QCString &moduleName @param usedict array of data of USE-statement @returns MemberDef pointer, if found, or nullptr otherwise */ -static MemberDef *getFortranDefs(const QCString &memberName, const QCString &moduleName, - UseSDict *usedict=0) +static MemberDef *getFortranDefs(yyscan_t yyscanner,const QCString &memberName, const QCString &moduleName, + UseSDict *usedict) { + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; if (memberName.isEmpty()) return nullptr; /* empty name => nothing to link */ // look in local variables - QListIterator<Scope> it(scopeStack); + QListIterator<Scope> it(yyextra->scopeStack); Scope *scope; for (it.toLast();(scope=it.current());--it) { @@ -524,9 +1210,9 @@ static MemberDef *getFortranDefs(const QCString &memberName, const QCString &mod gets the link to a generic procedure which depends not on the name, but on the parameter list @todo implementation */ -static bool getGenericProcedureLink(const ClassDef *cd, +static bool getGenericProcedureLink(yyscan_t yyscanner,const ClassDef *cd, const char *memberText, - CodeOutputInterface &ol) + CodeOutputInterface &ol) { (void)cd; (void)memberText; @@ -534,31 +1220,33 @@ static bool getGenericProcedureLink(const ClassDef *cd, return FALSE; } -static bool getLink(UseSDict *usedict, // dictionary with used modules +static bool getLink(yyscan_t yyscanner,UseSDict *usedict, // dictionary with used modules const char *memberText, // exact member text - CodeOutputInterface &ol, - const char *text) + CodeOutputInterface &ol, + const char *text) { + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; MemberDef *md=0; QCString memberName= removeRedundantWhiteSpace(memberText); - if ((md=getFortranDefs(memberName, currentModule, usedict)) && md->isLinkable()) + if ((md=getFortranDefs(yyscanner,memberName, yyextra->currentModule, usedict)) && md->isLinkable()) { if (md->isVariable() && (md->getLanguage()!=SrcLangExt_Fortran)) return FALSE; // Non Fortran variables aren't handled yet, // see also linkifyText in util.cpp const Definition *d = md->getOuterScope()==Doxygen::globalScope ? - md->getBodyDef() : md->getOuterScope(); + md->getBodyDef() : md->getOuterScope(); if (md->getGroupDef()) d = md->getGroupDef(); if (d && d->isLinkable()) { - if (g_currentDefinition && g_currentMemberDef && - md!=g_currentMemberDef && g_insideBody && g_collectXRefs) + if (yyextra->currentDefinition && yyextra->currentMemberDef && + md!=yyextra->currentMemberDef && yyextra->insideBody && yyextra->collectXRefs) { - addDocCrossReference(g_currentMemberDef,md); + std::lock_guard<std::mutex> lock(g_docCrossReferenceMutex); + addDocCrossReference(toMemberDefMutable(yyextra->currentMemberDef),toMemberDefMutable(md)); } - writeMultiLineCodeLink(ol,md,text ? text : memberText); - addToSearchIndex(text ? text : memberText); + writeMultiLineCodeLink(yyscanner,ol,md,text ? text : memberText); + addToSearchIndex(yyscanner, text ? text : memberText); return TRUE; } } @@ -566,35 +1254,36 @@ static bool getLink(UseSDict *usedict, // dictionary with used modules } -static void generateLink(CodeOutputInterface &ol, char *lname) +static void generateLink(yyscan_t yyscanner,CodeOutputInterface &ol, char *lname) { + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; ClassDef *cd=0; NamespaceDef *nsd=0; QCString tmp = lname; tmp = removeRedundantWhiteSpace(tmp.lower()); // check if lowercase lname is a linkable type or interface - if ( (getFortranTypeDefs(tmp, currentModule, cd, useMembers)) && cd->isLinkable() ) + if ( (getFortranTypeDefs(tmp, yyextra->currentModule, cd, yyextra->useMembers)) && cd->isLinkable() ) { if ( (cd->compoundType() == ClassDef::Class) && // was Entry::INTERFACE_SEC) && - (getGenericProcedureLink(cd, tmp, ol)) ) + (getGenericProcedureLink(yyscanner, cd, tmp, ol)) ) { //cout << "=== generic procedure resolved" << endl; } else { // write type or interface link - writeMultiLineCodeLink(ol,cd,tmp); - addToSearchIndex(tmp.data()); + writeMultiLineCodeLink(yyscanner, ol,cd,tmp); + addToSearchIndex(yyscanner, tmp); } } // check for module else if ( (getFortranNamespaceDefs(tmp, nsd)) && nsd->isLinkable() ) { // write module link - writeMultiLineCodeLink(ol,nsd,tmp); - addToSearchIndex(tmp.data()); + writeMultiLineCodeLink(yyscanner,ol,nsd,tmp); + addToSearchIndex(yyscanner,tmp); } // check for function/variable - else if (getLink(useMembers, tmp, ol, tmp)) + else if (getLink(yyscanner,yyextra->useMembers, tmp, ol, tmp)) { //cout << "=== found link for lowercase " << lname << endl; } @@ -602,16 +1291,17 @@ static void generateLink(CodeOutputInterface &ol, char *lname) { // nothing found, just write out the word //startFontClass("charliteral"); //test - codifyLines(tmp); - //endFontClass(); //test - addToSearchIndex(tmp.data()); + codifyLines(yyscanner,tmp); + //endFontClass(yyscanner); //test + addToSearchIndex(yyscanner,tmp); } } /*! 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)) @@ -619,701 +1309,69 @@ 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; } //---------------------------------------------------------------------------- /** start scope */ -static void startScope() +static void startScope(yyscan_t yyscanner) { + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; DBG_CTX((stderr, "===> startScope %s",yytext)); Scope *scope = new Scope; - scopeStack.append(scope); + yyextra->scopeStack.append(scope); } /** end scope */ -static void endScope() +static void endScope(yyscan_t yyscanner) { + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; DBG_CTX((stderr,"===> endScope %s",yytext)); - if (scopeStack.isEmpty()) + if (yyextra->scopeStack.isEmpty()) { DBG_CTX((stderr,"WARNING: fortrancode.l: stack empty!\n")); return; } - Scope *scope = scopeStack.getLast(); - scopeStack.removeLast(); + Scope *scope = yyextra->scopeStack.getLast(); + yyextra->scopeStack.removeLast(); for ( QCStringList::Iterator it = scope->useNames.begin(); it != scope->useNames.end(); ++it) { - useMembers->remove(*it); + yyextra->useMembers->remove(*it); } delete scope; } -static void addUse(const QCString &moduleName) +static void addUse(yyscan_t yyscanner,const QCString &moduleName) { - if (!scopeStack.isEmpty()) - scopeStack.getLast()->useNames.append(moduleName); + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + if (!yyextra->scopeStack.isEmpty()) + yyextra->scopeStack.getLast()->useNames.append(moduleName); } -static void addLocalVar(const QCString &varName) +static void addLocalVar(yyscan_t yyscanner,const QCString &varName) { - if (!scopeStack.isEmpty()) + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + if (!yyextra->scopeStack.isEmpty()) { std::string lowVarName = varName.lower().str(); - scopeStack.getLast()->localVars.insert(lowVarName); - if (g_isExternal) scopeStack.getLast()->externalVars.insert(lowVarName); + yyextra->scopeStack.getLast()->localVars.insert(lowVarName); + if (yyextra->isExternal) yyextra->scopeStack.getLast()->externalVars.insert(lowVarName); } } -//---------------------------------------------------------------------------- - -/* -----------------------------------------------------------------*/ -#undef YY_INPUT -#define YY_INPUT(buf,result,max_size) result=yyread(buf,max_size); - -static yy_size_t yyread(char *buf,yy_size_t max_size) -{ - yy_size_t c=0; - while( c < max_size && g_inputString[g_inputPosition] ) - { - *buf = g_inputString[g_inputPosition++] ; - c++; buf++; - } - return c; -} - -%} - -IDSYM [a-z_A-Z0-9] -ID [a-z_A-Z]+{IDSYM}* -SUBPROG (subroutine|function) -B [ \t] -BS [ \t]* -BS_ [ \t]+ -COMMA {BS},{BS} -ARGS_L0 ("("[^)]*")") -ARGS_L1a [^()]*"("[^)]*")"[^)]* -ARGS_L1 ("("{ARGS_L1a}*")") -ARGS_L2 "("({ARGS_L0}|[^()]|{ARGS_L1a}|{ARGS_L1})*")" -ARGS {BS}({ARGS_L0}|{ARGS_L1}|{ARGS_L2}) - -NUM_TYPE (complex|integer|logical|real) -LOG_OPER (\.and\.|\.eq\.|\.eqv\.|\.ge\.|\.gt\.|\.le\.|\.lt\.|\.ne\.|\.neqv\.|\.or\.|\.not\.) -KIND {ARGS} -CHAR (CHARACTER{ARGS}?|CHARACTER{BS}"*"({BS}[0-9]+|{ARGS})) -TYPE_SPEC (({NUM_TYPE}({BS}"*"{BS}[0-9]+)?)|({NUM_TYPE}{KIND})|DOUBLE{BS}COMPLEX|DOUBLE{BS}PRECISION|{CHAR}|TYPE|CLASS|PROCEDURE|ENUMERATOR) - -INTENT_SPEC intent{BS}"("{BS}(in|out|in{BS}out){BS}")" -ATTR_SPEC (IMPLICIT|ALLOCATABLE|DIMENSION{ARGS}|EXTERNAL|{INTENT_SPEC}|INTRINSIC|OPTIONAL|PARAMETER|POINTER|PROTECTED|PRIVATE|PUBLIC|SAVE|TARGET|(NON_)?RECURSIVE|PURE|IMPURE|ELEMENTAL|VALUE|NOPASS|DEFERRED|CONTIGUOUS|VOLATILE) -ACCESS_SPEC (PROTECTED|PRIVATE|PUBLIC) -/* Assume that attribute statements are almost the same as attributes. */ -ATTR_STMT {ATTR_SPEC}|DIMENSION -FLOW (DO|SELECT|CASE|SELECT{BS}(CASE|TYPE)|WHERE|IF|THEN|ELSE|WHILE|FORALL|ELSEWHERE|ELSEIF|RETURN|CONTINUE|EXIT|GO{BS}TO) -COMMANDS (FORMAT|CONTAINS|MODULE{BS_}PROCEDURE|WRITE|READ|ALLOCATE|ALLOCATED|ASSOCIATED|PRESENT|DEALLOCATE|NULLIFY|SIZE|INQUIRE|OPEN|CLOSE|FLUSH|DATA|COMMON) -IGNORE (CALL) -PREFIX ((NON_)?RECURSIVE{BS_}|IMPURE{BS_}|PURE{BS_}|ELEMENTAL{BS_}){0,4}((NON_)?RECURSIVE|IMPURE|PURE|ELEMENTAL)?0 -LANGUAGE_BIND_SPEC BIND{BS}"("{BS}C{BS}(,{BS}NAME{BS}"="{BS}"\""(.*)"\""{BS})?")" - -/* | */ - -%option noyywrap -%option stack -%option caseless -/*%option debug*/ - -%x Start -%x SubCall -%x FuncDef -%x ClassName -%x ClassVar -%x Subprog -%x DocBlock -%x Use -%x UseOnly -%x Import -%x Declaration -%x DeclarationBinding -%x DeclContLine -%x Parameterlist -%x String -%x Subprogend - -%% - /*==================================================================*/ - - /*-------- ignore ------------------------------------------------------------*/ - -<Start>{IGNORE}/{BS}"(" { // do not search keywords, intrinsics... TODO: complete list - codifyLines(yytext); - } - /*-------- inner construct ---------------------------------------------------*/ - -<Start>{COMMANDS}/{BS}[,( \t\n] { // highlight - /* font class is defined e.g. in doxygen.css */ - startFontClass("keyword"); - codifyLines(yytext); - endFontClass(); - } -<Start>{FLOW}/{BS}[,( \t\n] { - if (g_isFixedForm) - { - if ((yy_my_start == 1) && ((yytext[0] == 'c') || (yytext[0] == 'C'))) YY_FTN_REJECT; - } - if (g_currentMemberDef && g_currentMemberDef->isFunction()) - { - g_currentMemberDef->incrementFlowKeyWordCount(); - } - /* font class is defined e.g. in doxygen.css */ - startFontClass("keywordflow"); - codifyLines(yytext); - endFontClass(); - } -<Start>{BS}(CASE|CLASS|TYPE){BS_}(IS|DEFAULT) { - startFontClass("keywordflow"); - codifyLines(yytext); - endFontClass(); - } -<Start>{BS}"end"({BS}{FLOW})/[ \t\n] { // list is a bit long as not all have possible end - startFontClass("keywordflow"); - codifyLines(yytext); - endFontClass(); - } -<Start>"implicit"{BS}("none"|{TYPE_SPEC}) { - startFontClass("keywordtype"); - codifyLines(yytext); - endFontClass(); - } -<Start>^{BS}"namelist"/[//] { // Namelist specification - startFontClass("keywordtype"); - codifyLines(yytext); - endFontClass(); - } - /*-------- use statement -------------------------------------------*/ -<Start>"use"{BS_} { - startFontClass("keywordtype"); - codifyLines(yytext); - endFontClass(); - yy_push_state(YY_START); - BEGIN(Use); - } -<Use>"ONLY" { // TODO: rename - startFontClass("keywordtype"); - codifyLines(yytext); - endFontClass(); - yy_push_state(YY_START); - BEGIN(UseOnly); - } -<Use>{ID} { - QCString tmp = yytext; - tmp = tmp.lower(); - g_insideBody=TRUE; - generateLink(*g_code, yytext); - g_insideBody=FALSE; - - /* append module name to use dict */ - useEntry = new UseEntry(); - //useEntry->module = yytext; - //useMembers->append(yytext, useEntry); - //addUse(yytext); - useEntry->module = tmp; - useMembers->append(tmp, useEntry); - addUse(tmp); - } -<Use,UseOnly,Import>{BS},{BS} { codifyLines(yytext); } -<UseOnly,Import>{BS}&{BS}"\n" { codifyLines(yytext); - g_contLineNr++; - YY_FTN_RESET} -<UseOnly>{ID} { - QCString tmp = yytext; - tmp = tmp.lower(); - useEntry->onlyNames.append(tmp); - g_insideBody=TRUE; - generateLink(*g_code, yytext); - g_insideBody=FALSE; - } -<Use,UseOnly,Import>"\n" { - unput(*yytext); - yy_pop_state();YY_FTN_RESET - } -<*>"import"{BS}/"\n" | -<*>"import"{BS_} { - startFontClass("keywordtype"); - codifyLines(yytext); - endFontClass(); - yy_push_state(YY_START); - BEGIN(Import); - } -<Import>{ID} { - g_insideBody=TRUE; - generateLink(*g_code, yytext); - g_insideBody=FALSE; - } -<Import>("ONLY"|"NONE"|"ALL") { - startFontClass("keywordtype"); - codifyLines(yytext); - endFontClass(); - } - /*-------- fortran module -----------------------------------------*/ -<Start>("block"{BS}"data"|"program"|"module"|"interface")/{BS_}|({COMMA}{ACCESS_SPEC})|\n { // - startScope(); - startFontClass("keyword"); - codifyLines(yytext); - endFontClass(); - yy_push_state(YY_START); - BEGIN(ClassName); - if (!qstricmp(yytext,"module")) currentModule="module"; - } -<Start>("enum")/{BS_}|{BS}{COMMA}{BS}{LANGUAGE_BIND_SPEC}|\n { // - startScope(); - startFontClass("keyword"); - codifyLines(yytext); - endFontClass(); - yy_push_state(YY_START); - BEGIN(ClassName); - currentClass="class"; - } -<*>{LANGUAGE_BIND_SPEC} { // - startFontClass("keyword"); - codifyLines(yytext); - endFontClass(); - } -<Start>("type")/{BS_}|({COMMA}({ACCESS_SPEC}|ABSTRACT|EXTENDS))|\n { // - startScope(); - startFontClass("keyword"); - codifyLines(yytext); - endFontClass(); - yy_push_state(YY_START); - BEGIN(ClassName); - currentClass="class"; - } -<ClassName>{ID} { - if (currentModule == "module") - { - currentModule=yytext; - currentModule = currentModule.lower(); - } - generateLink(*g_code,yytext); - yy_pop_state(); - } -<ClassName>({ACCESS_SPEC}|ABSTRACT|EXTENDS)/[,:( ] { //| variable declaration - startFontClass("keyword"); - g_code->codify(yytext); - endFontClass(); - } -<ClassName>\n { // interface may be without name - yy_pop_state(); - YY_FTN_REJECT; - } -<Start>^{BS}"end"({BS_}"enum").* { // just reset currentClass, rest is done in following rule - currentClass=0; - YY_FTN_REJECT; - } -<Start>^{BS}"end"({BS_}"type").* { // just reset currentClass, rest is done in following rule - currentClass=0; - YY_FTN_REJECT; - } -<Start>^{BS}"end"({BS_}"module").* { // just reset currentModule, rest is done in following rule - currentModule=0; - YY_FTN_REJECT; - } - /*-------- subprog definition -------------------------------------*/ -<Start>({PREFIX}{BS_})?{TYPE_SPEC}{BS_}({PREFIX}{BS_})?{BS}/{SUBPROG}{BS_} { // TYPE_SPEC is for old function style function result - startFontClass("keyword"); - codifyLines(yytext); - endFontClass(); - } -<Start>({PREFIX}{BS_})?{SUBPROG}{BS_} { // Fortran subroutine or function found - startFontClass("keyword"); - codifyLines(yytext); - endFontClass(); - yy_push_state(YY_START); - BEGIN(Subprog); - } -<Subprog>{ID} { // subroutine/function name - DBG_CTX((stderr, "===> start subprogram %s\n", yytext)); - startScope(); - generateLink(*g_code,yytext); - } -<Subprog>"result"/{BS}"("[^)]*")" { - startFontClass("keyword"); - codifyLines(yytext); - endFontClass(); - } -<Subprog>"("[^)]*")" { // ignore rest of line - codifyLines(yytext); - } -<Subprog,Subprogend>"\n" { codifyLines(yytext); - g_contLineNr++; - yy_pop_state(); - YY_FTN_RESET - } -<Start>"end"{BS}("block"{BS}"data"|{SUBPROG}|"module"|"program"|"enum"|"type"|"interface")?{BS} { // Fortran subroutine or function ends - //cout << "===> end function " << yytext << endl; - endScope(); - startFontClass("keyword"); - codifyLines(yytext); - endFontClass(); - yy_push_state(YY_START); - BEGIN(Subprogend); - } -<Subprogend>{ID}/{BS}(\n|!|;) { - generateLink(*g_code,yytext); - yy_pop_state(); - } -<Start>"end"{BS}("block"{BS}"data"|{SUBPROG}|"module"|"program"|"enum"|"type"|"interface"){BS}/(\n|!|;) { // Fortran subroutine or function ends - //cout << "===> end function " << yytext << endl; - endScope(); - startFontClass("keyword"); - codifyLines(yytext); - endFontClass(); - } - /*-------- variable declaration ----------------------------------*/ -<Start>^{BS}"real"/[,:( ] { // real is a bit tricky as it is a data type but also a function. - yy_push_state(YY_START); - BEGIN(Declaration); - startFontClass("keywordtype"); - g_code->codify(yytext); - endFontClass(); - } -<Start>{TYPE_SPEC}/[,:( ] { - QCString typ = yytext; - typ = removeRedundantWhiteSpace(typ.lower()); - if (typ.startsWith("real")) YY_FTN_REJECT; - if (typ == "type" || typ == "class" || typ == "procedure") inTypeDecl = 1; - yy_push_state(YY_START); - BEGIN(Declaration); - startFontClass("keywordtype"); - g_code->codify(yytext); - endFontClass(); - } -<Start>{ATTR_SPEC} { - if (QCString(yytext) == "external") - { - yy_push_state(YY_START); - BEGIN(Declaration); - g_isExternal = true; - } - startFontClass("keywordtype"); - g_code->codify(yytext); - endFontClass(); - } -<Declaration>({TYPE_SPEC}|{ATTR_SPEC})/[,:( ] { //| variable declaration - if (QCString(yytext) == "external") g_isExternal = true; - startFontClass("keywordtype"); - g_code->codify(yytext); - endFontClass(); - } -<Declaration>{ID} { // local var - if (g_isFixedForm && yy_my_start == 1) - { - startFontClass("comment"); - g_code->codify(yytext); - endFontClass(); - } - else if (g_currentMemberDef && - ((g_currentMemberDef->isFunction() && (g_currentMemberDef->typeString()!=QCString("subroutine") || inTypeDecl)) || - g_currentMemberDef->isVariable() || g_currentMemberDef->isEnumValue() - ) - ) - { - generateLink(*g_code, yytext); - } - else - { - g_code->codify(yytext); - addLocalVar(yytext); - } - } -<Declaration>{BS}("=>"|"="){BS} { // Procedure binding - BEGIN(DeclarationBinding); - g_code->codify(yytext); - } -<DeclarationBinding>{ID} { // Type bound procedure link - generateLink(*g_code, yytext); - yy_pop_state(); - } -<Declaration>[(] { // start of array or type / class specification - bracketCount++; - g_code->codify(yytext); - } - -<Declaration>[)] { // end array specification - bracketCount--; - if (!bracketCount) inTypeDecl = 0; - g_code->codify(yytext); - } - -<Declaration,DeclarationBinding>"&" { // continuation line - g_code->codify(yytext); - if (!g_isFixedForm) - { - yy_push_state(YY_START); - BEGIN(DeclContLine); - } - } -<DeclContLine>"\n" { // declaration not yet finished - g_contLineNr++; - codifyLines(yytext); - bracketCount = 0; - yy_pop_state(); - YY_FTN_RESET - } -<Declaration,DeclarationBinding>"\n" { // end declaration line (?) - if (g_endComment) - { - g_endComment=FALSE; - } - else - { - codifyLines(yytext); - } - bracketCount = 0; - g_contLineNr++; - if (!(g_hasContLine && g_hasContLine[g_contLineNr - 1])) - { - g_isExternal = false; - yy_pop_state(); - } - YY_FTN_RESET - } - - /*-------- subprog calls -----------------------------------------*/ - -<Start>"call"{BS_} { - startFontClass("keyword"); - codifyLines(yytext); - endFontClass(); - yy_push_state(YY_START); - BEGIN(SubCall); - } -<SubCall>{ID} { // subroutine call - g_insideBody=TRUE; - generateLink(*g_code, yytext); - g_insideBody=FALSE; - yy_pop_state(); - } -<Start>{ID}{BS}/"(" { // function call - if (g_isFixedForm && yy_my_start == 6) - { - // fixed form continuation line - YY_FTN_REJECT; - } - else if (QCString(yytext).stripWhiteSpace().lower() == "type") - { - yy_push_state(YY_START); - BEGIN(Declaration); - startFontClass("keywordtype"); - g_code->codify(QCString(yytext).stripWhiteSpace()); - endFontClass(); - g_code->codify(yytext + 4); - } - else - { - g_insideBody=TRUE; - generateLink(*g_code, yytext); - g_insideBody=FALSE; - } - } - - /*-------- comments ---------------------------------------------------*/ -<Start,Declaration,DeclarationBinding>\n?{BS}"!>"|"!<" { // start comment line or comment block - if (yytext[0] == '\n') - { - g_contLineNr++; - yy_old_start = 0; - yy_my_start = 1; - yy_end = static_cast<int>(yyleng); - } - // Actually we should see if ! on position 6, can be continuation - // but the chance is very unlikely, so no effort to solve it here - yy_push_state(YY_START); - BEGIN(DocBlock); - docBlock=yytext; - } -<Declaration,DeclarationBinding>{BS}"!<" { // start comment line or comment block - yy_push_state(YY_START); - BEGIN(DocBlock); - docBlock=yytext; - } - -<DocBlock>.* { // contents of current comment line - docBlock+=yytext; - } -<DocBlock>"\n"{BS}("!>"|"!<"|"!!") { // comment block (next line is also comment line) - g_contLineNr++; - yy_old_start = 0; - yy_my_start = 1; - yy_end = static_cast<int>(yyleng); - // Actually we should see if ! on position 6, can be continuation - // but the chance is very unlikely, so no effort to solve it here - docBlock+=yytext; - } -<DocBlock>"\n" { // comment block ends at the end of this line - // remove special comment (default config) - g_contLineNr++; - if (Config_getBool(STRIP_CODE_COMMENTS)) - { - g_yyLineNr+=((QCString)docBlock).contains('\n'); - g_yyLineNr+=1; - endCodeLine(); - if (g_yyLineNr<g_inputLines) - { - startCodeLine(); - } - g_endComment=TRUE; - } - else // do not remove comment - { - startFontClass("comment"); - codifyLines(docBlock); - endFontClass(); - } - unput(*yytext); - g_contLineNr--; - yy_pop_state(); - YY_FTN_RESET - } - -<*>"!"[^><\n].*|"!"$ { // normal comment - if(YY_START == String) YY_FTN_REJECT; // ignore in strings - if (g_isFixedForm && yy_my_start == 6) YY_FTN_REJECT; - startFontClass("comment"); - codifyLines(yytext); - endFontClass(); - } - -<*>^[Cc*].* { // normal comment - if(! g_isFixedForm) YY_FTN_REJECT; - - startFontClass("comment"); - codifyLines(yytext); - endFontClass(); - } -<*>"assignment"/{BS}"("{BS}"="{BS}")" { - startFontClass("keyword"); - codifyLines(yytext); - endFontClass(); - } -<*>"operator"/{BS}"("[^)]*")" { - startFontClass("keyword"); - codifyLines(yytext); - endFontClass(); - } - - /*------ preprocessor --------------------------------------------*/ -<Start>"#".*\n { - if (g_isFixedForm && yy_my_start == 6) YY_FTN_REJECT; - g_contLineNr++; - startFontClass("preprocessor"); - codifyLines(yytext); - endFontClass(); - YY_FTN_RESET - } - /*------ variable references? -------------------------------------*/ - -<Start>"%"{BS}{ID} { // ignore references to elements - g_code->codify(yytext); - } -<Start>{ID} { - g_insideBody=TRUE; - generateLink(*g_code, yytext); - g_insideBody=FALSE; - } - /*------ strings --------------------------------------------------*/ -<String>\n { // string with \n inside - g_contLineNr++; - g_str+=yytext; - startFontClass("stringliteral"); - codifyLines(g_str); - endFontClass(); - g_str = ""; - YY_FTN_RESET - } -<String>\"|\' { // string ends with next quote without previous backspace - if(yytext[0]!=stringStartSymbol) YY_FTN_REJECT; // single vs double quote - g_str+=yytext; - startFontClass("stringliteral"); - codifyLines(g_str); - endFontClass(); - yy_pop_state(); - } -<String>. {g_str+=yytext;} - -<*>\"|\' { /* string starts */ - /* if(YY_START == StrIgnore) YY_FTN_REJECT; // ignore in simple comments */ - if (g_isFixedForm && yy_my_start == 6) YY_FTN_REJECT; - yy_push_state(YY_START); - stringStartSymbol=yytext[0]; // single or double quote - BEGIN(String); - g_str=yytext; - } - /*-----------------------------------------------------------------------------*/ - -<*>\n { - if (g_endComment) - { - g_endComment=FALSE; - } - else - { - codifyLines(yytext); - // comment cannot extend over the end of a line so should always be terminated at the end of the line. - if (g_currentFontClass && !strcmp(g_currentFontClass,"comment")) endFontClass(); - } - g_contLineNr++; - YY_FTN_RESET - } -<*>^{BS}"type"{BS}"=" { g_code->codify(yytext); } - -<*>. { - if (g_isFixedForm && yy_my_start > fixedCommentAfter) - { - //yy_push_state(YY_START); - //BEGIN(DocBlock); - //docBlock=yytext; - startFontClass("comment"); - codifyLines(yytext); - } - else - { - g_code->codify(yytext); - } - } -<*>{LOG_OPER} { // Fortran logical comparison keywords - g_code->codify(yytext); - } -<*><<EOF>> { - if (YY_START == DocBlock) { - if (!Config_getBool(STRIP_CODE_COMMENTS)) - { - startFontClass("comment"); - codifyLines(docBlock); - endFontClass(); - } - } - yyterminate(); - } -%% - -/*@ ---------------------------------------------------------------------------- - */ - /*===================================================================*/ -void resetFortranCodeParserState() {} - -bool recognizeFixedForm(const char* contents, FortranFormat format); /* prototype, implementation in fortranscanner.l */ -const char* prepassFixedForm(const char* contents, int *hasContLine); /* prototype, implementation in fortranscanner.l */ -static void checkContLines(const char *s) +static void checkContLines(yyscan_t yyscanner,const char *s) { + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; int numLines = 0; int i = 0; const char *p = s; @@ -1325,115 +1383,153 @@ static void checkContLines(const char *s) p++; } - g_hasContLine = (int *) malloc((numLines) * sizeof(int)); + yyextra->hasContLine = (int *) malloc((numLines) * sizeof(int)); for (i = 0; i < numLines; i++) - g_hasContLine[i] = 0; - p = prepassFixedForm(s, g_hasContLine); - g_hasContLine[0] = 0; + yyextra->hasContLine[i] = 0; + p = prepassFixedForm(s, yyextra->hasContLine); + yyextra->hasContLine[0] = 0; } void parseFortranCode(CodeOutputInterface &od,const char *,const QCString &s, bool exBlock, const char *exName,FileDef *fd, - int startLine,int endLine,bool inlineFragment, - const MemberDef *,bool,const Definition *searchCtx, + int startLine,int endLine,bool inlineFragment, + const MemberDef *,bool,const Definition *searchCtx, bool collectXRefs, FortranFormat format) { //printf("***parseCode() exBlock=%d exName=%s fd=%p\n",exBlock,exName,fd); - if (s.isEmpty()) return; - printlex(yy_flex_debug, TRUE, __FILE__, fd ? fd->fileName().data(): NULL); - g_code = &od; - g_inputString = s; - g_inputPosition = 0; - g_isFixedForm = recognizeFixedForm((const char*)s,format); - g_contLineNr = 1; - g_hasContLine = NULL; - if (g_isFixedForm) + return; +} + +//--------------------------------------------------------- + +struct FortranCodeParser::Private +{ + yyscan_t yyscanner; + fortrancodeYY_state state; + FortranFormat format; +}; + +FortranCodeParser::FortranCodeParser(FortranFormat format) : p(std::make_unique<Private>()) +{ + p->format = format; + fortrancodeYYlex_init_extra(&p->state,&p->yyscanner); +#ifdef FLEX_DEBUG + fortrancodeYYset_debug(1,p->yyscanner); +#endif + resetCodeParserState(); + p->state.useMembers = new UseSDict; +} + +FortranCodeParser::~FortranCodeParser() +{ + delete p->state.useMembers; + fortrancodeYYlex_destroy(p->yyscanner); +} + +void FortranCodeParser::resetCodeParserState() +{ + struct yyguts_t *yyg = (struct yyguts_t*)p->yyscanner; + yyextra->currentDefinition = 0; + yyextra->currentMemberDef = 0; + yyextra->currentFontClass = 0; + yyextra->needsTermination = FALSE; + BEGIN( Start ); +} + +void FortranCodeParser::parseCode(CodeOutputInterface & codeOutIntf, + const char * scopeName, + const QCString & input, + SrcLangExt /*lang*/, + bool isExampleBlock, + const char * exampleName, + FileDef * fileDef, + int startLine, + int endLine, + bool inlineFragment, + const MemberDef *memberDef, + bool showLineNumbers, + const Definition *searchCtx, + bool collectXRefs + ) +{ + yyscan_t yyscanner = p->yyscanner; + struct yyguts_t *yyg = (struct yyguts_t*)p->yyscanner; + //::parseFortranCode(codeOutIntf,scopeName,input,isExampleBlock,exampleName, + // fileDef,startLine,endLine,inlineFragment,memberDef, + // showLineNumbers,searchCtx,collectXRefs,m_format); + // parseFortranCode(CodeOutputInterface &od,const char *,const QCString &s, + // bool exBlock, const char *exName,FileDef *fd, + // int startLine,int endLine,bool inlineFragment, + // const MemberDef *,bool,const Definition *searchCtx, + // bool collectXRefs, FortranFormat format) + if (input.isEmpty()) return; + printlex(yy_flex_debug, TRUE, __FILE__, fileDef ? fileDef->fileName().data(): NULL); + yyextra->code = &codeOutIntf; + yyextra->inputString = input; + yyextra->inputPosition = 0; + yyextra->isFixedForm = recognizeFixedForm(input,p->format); + yyextra->contLineNr = 1; + yyextra->hasContLine = NULL; + if (yyextra->isFixedForm) { - checkContLines(g_inputString); + checkContLines(yyscanner,yyextra->inputString); } - g_currentFontClass = 0; - g_needsTermination = FALSE; - g_searchCtx = searchCtx; - g_collectXRefs = collectXRefs; + yyextra->currentFontClass = 0; + yyextra->needsTermination = FALSE; + yyextra->searchCtx = searchCtx; + yyextra->collectXRefs = collectXRefs; 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; - if (exBlock && fd==0) + yyextra->exampleBlock = isExampleBlock; + yyextra->exampleName = exampleName; + yyextra->sourceFileDef = fileDef; + if (isExampleBlock && fileDef==0) { // create a dummy filedef for the example - g_sourceFileDef = createFileDef("",exName); + yyextra->sourceFileDef = createFileDef("",exampleName); } - if (g_sourceFileDef) + if (yyextra->sourceFileDef) { - setCurrentDoc("l00001"); + setCurrentDoc(yyscanner,"l00001"); } - g_currentDefinition = 0; - g_currentMemberDef = 0; - if (!g_exampleName.isEmpty()) + yyextra->currentDefinition = 0; + yyextra->currentMemberDef = 0; + if (!yyextra->exampleName.isEmpty()) { - g_exampleFile = convertNameToFile(g_exampleName+"-example"); + yyextra->exampleFile = convertNameToFile(yyextra->exampleName+"-example"); } - g_includeCodeFragment = inlineFragment; - startCodeLine(); - g_parmName.resize(0); - g_parmType.resize(0); - fortrancodeYYrestart( fortrancodeYYin ); + yyextra->includeCodeFragment = inlineFragment; + startCodeLine(yyscanner); + fortrancodeYYrestart(0, yyscanner); BEGIN( Start ); - fortrancodeYYlex(); - if (g_needsTermination) + fortrancodeYYlex(yyscanner); + if (yyextra->needsTermination) { - endFontClass(); - g_code->endCodeLine(); + endFontClass(yyscanner); + yyextra->code->endCodeLine(); } - if (exBlock && g_sourceFileDef) + if (isExampleBlock && yyextra->sourceFileDef) { // delete the temporary file definition used for this example - delete g_sourceFileDef; - g_sourceFileDef=0; + delete yyextra->sourceFileDef; + yyextra->sourceFileDef=0; } - if (g_hasContLine) free(g_hasContLine); - g_hasContLine = NULL; - printlex(yy_flex_debug, FALSE, __FILE__, fd ? fd->fileName().data(): NULL); - return; -} - -//--------------------------------------------------------- + if (yyextra->hasContLine) free(yyextra->hasContLine); + yyextra->hasContLine = NULL; -void FortranCodeParser::parseCode(CodeOutputInterface & codeOutIntf, - const char * scopeName, - const QCString & input, - SrcLangExt /*lang*/, - bool isExampleBlock, - const char * exampleName, - FileDef * fileDef, - int startLine, - int endLine, - bool inlineFragment, - const MemberDef *memberDef, - bool showLineNumbers, - const Definition *searchCtx, - bool collectXRefs - ) -{ - ::parseFortranCode(codeOutIntf,scopeName,input,isExampleBlock,exampleName, - fileDef,startLine,endLine,inlineFragment,memberDef, - showLineNumbers,searchCtx,collectXRefs,m_format); -} + // write the tooltips + TooltipManager::instance().writeTooltips(codeOutIntf); -void FortranCodeParser::resetCodeParserState() -{ - ::resetFortranCodeParserState(); + printlex(yy_flex_debug, FALSE, __FILE__, fileDef ? fileDef->fileName().data(): NULL); } //--------------------------------------------------------- diff --git a/src/fortranscanner.h b/src/fortranscanner.h index 0e67bb2..0fbba89 100644 --- a/src/fortranscanner.h +++ b/src/fortranscanner.h @@ -53,5 +53,6 @@ class FortranOutlineParserFixed : public FortranOutlineParser FortranOutlineParserFixed() : FortranOutlineParser(FortranFormat_Fixed) { } }; +const char* prepassFixedForm(const char* contents, int *hasContLine); #endif diff --git a/src/fortranscanner.l b/src/fortranscanner.l index cf48a3e..99e1f9a 100644 --- a/src/fortranscanner.l +++ b/src/fortranscanner.l @@ -48,6 +48,8 @@ %{ +#include <map> + #include <stdio.h> #include <stdlib.h> #include <assert.h> @@ -202,7 +204,7 @@ struct fortranscannerYY_state //! Accumulated modifiers of current statement, eg variable declaration. SymbolModifiers currentModifiers; //! Holds program scope->symbol name->symbol modifiers. - QMap<Entry*,QMap<QCString,SymbolModifiers> > modifiers; + std::map<Entry*,std::map<std::string,SymbolModifiers> > modifiers; int anonCount = 0 ; }; @@ -712,7 +714,7 @@ private { } {ID} { QCString name = yytext; - yyextra->modifiers[yyextra->current_root][name.lower()] |= yyextra->currentModifiers; + yyextra->modifiers[yyextra->current_root][name.lower().str()] |= yyextra->currentModifiers; yyextra->current->section = Entry::FUNCTION_SEC; yyextra->current->name = name; yyextra->current->fileName = yyextra->fileName; @@ -774,6 +776,7 @@ private { yyterminate(); } yyextra->subrCurrent.pop_back(); + yyextra->vtype = V_IGNORE; yy_pop_state(yyscanner) ; } <BlockData>{ @@ -871,7 +874,7 @@ private { QCString name=yytext; name = name.lower(); /* remember attributes for the symbol */ - yyextra->modifiers[yyextra->current_root][name.lower()] |= yyextra->currentModifiers; + yyextra->modifiers[yyextra->current_root][name.lower().str()] |= yyextra->currentModifiers; yyextra->argName= name; yyextra->vtype= V_IGNORE; @@ -912,12 +915,12 @@ private { // save, it may be function return type if (parameter) { - yyextra->modifiers[yyextra->current_root][name.lower()].type = yyextra->argType; + yyextra->modifiers[yyextra->current_root][name.lower().str()].type = yyextra->argType; } else { if ((yyextra->current_root->name.lower() == yyextra->argName.lower()) || - (yyextra->modifiers[yyextra->current_root->parent()][yyextra->current_root->name.lower()].returnName.lower() == yyextra->argName.lower())) + (yyextra->modifiers[yyextra->current_root->parent()][yyextra->current_root->name.lower().str()].returnName.lower() == yyextra->argName.lower())) { int strt = yyextra->current_root->type.find("function"); QCString lft; @@ -955,11 +958,11 @@ private { yyextra->current_root->type += " " + yyextra->argType.stripWhiteSpace(); } yyextra->current_root->type = yyextra->current_root->type.stripWhiteSpace(); - yyextra->modifiers[yyextra->current_root][name.lower()].type = yyextra->current_root->type; + yyextra->modifiers[yyextra->current_root][name.lower().str()].type = yyextra->current_root->type; } else { - yyextra->modifiers[yyextra->current_root][name.lower()].type = yyextra->argType; + yyextra->modifiers[yyextra->current_root][name.lower().str()].type = yyextra->argType; } } // any accumulated doc for argument should be emptied, @@ -973,7 +976,7 @@ private { QCString name(yyextra->argName); QCString attr("dimension"); attr += yytext; - yyextra->modifiers[yyextra->current_root][name.lower()] |= attr; + yyextra->modifiers[yyextra->current_root][name.lower().str()] |= attr; } <Variable>{COMMA} { //printf("COMMA: %d<=..<=%d\n", yyextra->colNr-(int)yyleng, yyextra->colNr); // locate !< comment @@ -1147,7 +1150,7 @@ private { <Subprog>{BS} { /* ignore white space */ } <Subprog>{ID} { yyextra->current->name = yytext; //cout << "1a==========> got " << yyextra->current->type << " " << yytext << " " << yyextra->lineNr << endl; - yyextra->modifiers[yyextra->current_root][yyextra->current->name.lower()].returnName = yyextra->current->name.lower(); + yyextra->modifiers[yyextra->current_root][yyextra->current->name.lower().str()].returnName = yyextra->current->name.lower(); if (yyextra->ifType == IF_ABSTRACT || yyextra->ifType == IF_SPECIFIC) { @@ -1196,7 +1199,7 @@ private { QCString result= yytext; result= result.right(result.length()-result.find("(")-1); result= result.stripWhiteSpace(); - yyextra->modifiers[yyextra->current_root->parent()][yyextra->current_root->name.lower()].returnName = result; + yyextra->modifiers[yyextra->current_root->parent()][yyextra->current_root->name.lower().str()].returnName = result; } //cout << "=====> got result " << result << endl; } @@ -1498,49 +1501,6 @@ void truncatePrepass(yyscan_t yyscanner,int index) yyextra->inputStringPrepass.truncate(index); } -// simplified way to know if this is fixed form -bool recognizeFixedForm(const char* contents, FortranFormat format) -{ - int column=0; - bool skipLine=FALSE; - - if (format == FortranFormat_Fixed) return TRUE; - if (format == FortranFormat_Free) return FALSE; - - for(int i=0;;i++) { - column++; - - switch(contents[i]) { - case '\n': - column=0; - skipLine=FALSE; - break; - case ' ': - break; - case '\000': - return FALSE; - case '#': - skipLine=TRUE; - break; - case 'C': - case 'c': - case '*': - if (column==1) return TRUE; - if (skipLine) break; - return FALSE; - case '!': - if (column>1 && column<7) return FALSE; - skipLine=TRUE; - break; - default: - if (skipLine) break; - if (column>=7) return TRUE; - return FALSE; - } - } - return FALSE; -} - /* This function assumes that contents has at least size=length+1 */ static void insertCharacter(char *contents, int length, int pos, char c) { @@ -2061,7 +2021,7 @@ static Argument *findArgument(Entry* subprog, QCString name, bool byTypeName = F /*! Apply yyextra->modifiers stored in \a mdfs to the \a typeName string. */ -static QCString applyModifiers(QCString typeName, SymbolModifiers& mdfs) +static QCString applyModifiers(QCString typeName, const SymbolModifiers& mdfs) { if (!mdfs.dimension.isNull()) { @@ -2178,14 +2138,14 @@ static QCString applyModifiers(QCString typeName, SymbolModifiers& mdfs) } /*! Apply yyextra->modifiers stored in \a mdfs to the \a arg argument. */ -static void applyModifiers(Argument *arg, SymbolModifiers& mdfs) +static void applyModifiers(Argument *arg, const SymbolModifiers& mdfs) { QCString tmp = arg->type; arg->type = applyModifiers(tmp, mdfs); } /*! Apply yyextra->modifiers stored in \a mdfs to the \a ent entry. */ -static void applyModifiers(Entry *ent, SymbolModifiers& mdfs) +static void applyModifiers(Entry *ent, const SymbolModifiers& mdfs) { QCString tmp = ent->type; ent->type = applyModifiers(tmp, mdfs); @@ -2206,8 +2166,7 @@ static void startScope(yyscan_t yyscanner,Entry *scope) //cout<<"start scope: "<<scope->name<<endl; yyextra->current_root= scope; /* start substructure */ - QMap<QCString,SymbolModifiers> mdfMap; - yyextra->modifiers.insert(scope, mdfMap); + yyextra->modifiers.insert(std::make_pair(scope, std::map<std::string,SymbolModifiers>())); } /*! Ends scope in fortran program: may update subprogram arguments or module variable attributes. @@ -2238,32 +2197,32 @@ static bool endScope(yyscan_t yyscanner,Entry *scope, bool isGlobalRoot) } // update variables or subprogram arguments with yyextra->modifiers - QMap<QCString,SymbolModifiers>& mdfsMap = yyextra->modifiers[scope]; + std::map<std::string,SymbolModifiers>& mdfsMap = yyextra->modifiers[scope]; if (scope->section == Entry::FUNCTION_SEC) { // iterate all symbol yyextra->modifiers of the scope - for (QMap<QCString,SymbolModifiers>::Iterator it=mdfsMap.begin(); it!=mdfsMap.end(); it++) + for (const auto &kv : mdfsMap) { //cout<<it.key()<<": "<<it.data()<<endl; - Argument *arg = findArgument(scope, it.key()); + Argument *arg = findArgument(scope, kv.first); if (arg) { - applyModifiers(arg, it.data()); + applyModifiers(arg, kv.second); } } // find return type for function //cout<<"RETURN NAME "<<yyextra->modifiers[yyextra->current_root][scope->name.lower()].returnName<<endl; - QCString returnName = yyextra->modifiers[yyextra->current_root][scope->name.lower()].returnName.lower(); - if (yyextra->modifiers[scope].contains(returnName)) + QCString returnName = yyextra->modifiers[yyextra->current_root][scope->name.lower().str()].returnName.lower(); + if (yyextra->modifiers[scope].find(returnName.str())!=yyextra->modifiers[scope].end()) { - scope->type = yyextra->modifiers[scope][returnName].type; // returning type works - applyModifiers(scope, yyextra->modifiers[scope][returnName]); // returning array works + scope->type = yyextra->modifiers[scope][returnName.str()].type; // returning type works + applyModifiers(scope, yyextra->modifiers[scope][returnName.str()]); // returning array works } - } + } if (scope->section == Entry::CLASS_SEC) { // was INTERFACE_SEC if (scope->parent()->section == Entry::FUNCTION_SEC) @@ -2291,7 +2250,7 @@ static bool endScope(yyscan_t yyscanner,Entry *scope, bool isGlobalRoot) if ((count == 1) && found) { // clear all yyextra->modifiers of the scope - yyextra->modifiers.remove(scope); + yyextra->modifiers.erase(scope); scope->parent()->removeSubEntry(scope); scope = 0; return TRUE; @@ -2307,13 +2266,13 @@ static bool endScope(yyscan_t yyscanner,Entry *scope, bool isGlobalRoot) continue; //cout<<ce->name<<", "<<mdfsMap.contains(ce->name.lower())<<mdfsMap.count()<<endl; - if (mdfsMap.contains(ce->name.lower())) - applyModifiers(ce.get(), mdfsMap[ce->name.lower()]); + if (mdfsMap.find(ce->name.lower().str())!=mdfsMap.end()) + applyModifiers(ce.get(), mdfsMap[ce->name.lower().str()]); } } // clear all yyextra->modifiers of the scope - yyextra->modifiers.remove(scope); + yyextra->modifiers.erase(scope); return TRUE; } @@ -2564,7 +2523,7 @@ static void subrHandleCommentBlock(yyscan_t yyscanner,const QCString &doc,bool b loc_doc.stripWhiteSpace(); // direction as defined with the declaration of the parameter - int dir1 = yyextra->modifiers[yyextra->current_root][yyextra->argName.lower()].direction; + int dir1 = yyextra->modifiers[yyextra->current_root][yyextra->argName.lower().str()].direction; // in description [in] is specified if (loc_doc.lower().find(directionParam[SymbolModifiers::IN]) == 0) { @@ -2687,6 +2646,9 @@ static void parseMain(yyscan_t yyscanner, const char *fileName,const char *fileB char *tmpBuf = NULL; initParser(yyscanner); + + if (fileBuf==0 || fileBuf[0]=='\0') return; + yyextra->defaultProtection = Public; yyextra->inputString = fileBuf; yyextra->inputPosition = 0; diff --git a/src/ftvhelp.cpp b/src/ftvhelp.cpp index 6fc14bf..c8edeb2 100644 --- a/src/ftvhelp.cpp +++ b/src/ftvhelp.cpp @@ -167,7 +167,7 @@ void FTVHelp::finalize() */ void FTVHelp::incContentsDepth() { - //printf("incContentsDepth() indent=%d\n",m_indent); + //printf("%p: incContentsDepth() indent=%d\n",this,m_indent); m_indent++; ASSERT(m_indent<MAX_INDENT); } @@ -178,7 +178,7 @@ void FTVHelp::incContentsDepth() */ void FTVHelp::decContentsDepth() { - //printf("decContentsDepth() indent=%d\n",m_indent); + //printf("%p: decContentsDepth() indent=%d\n",this,m_indent); ASSERT(m_indent>0); if (m_indent>0) { @@ -249,7 +249,7 @@ static QCString node2URL(const FTVNode *n,bool overruleFile=FALSE,bool srcLink=F { if (overruleFile && n->def && n->def->definitionType()==Definition::TypeFile) { - const FileDef *fd = dynamic_cast<const FileDef*>(n->def); + const FileDef *fd = toFileDef(n->def); if (srcLink) { url = fd->getSourceFileBase(); @@ -419,7 +419,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<const ClassDef*>(n->def)); + char icon=compoundIcon(toClassDef(n->def)); t << "<span class=\"icona\"><span class=\"icon\">" << icon << "</span></span>"; } else @@ -444,9 +444,9 @@ void FTVHelp::generateTree(FTextStream &t, const QList<FTVNode> &nl,int level,in { const FileDef *srcRef=0; if (n->def && n->def->definitionType()==Definition::TypeFile && - (dynamic_cast<const FileDef*>(n->def))->generateSourceFile()) + (toFileDef(n->def))->generateSourceFile()) { - srcRef = dynamic_cast<const FileDef*>(n->def); + srcRef = toFileDef(n->def); } if (srcRef) { @@ -475,7 +475,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<const ClassDef*>(n->def)); + char icon=compoundIcon(toClassDef(n->def)); t << "<span class=\"icona\"><span class=\"icon\">" << icon << "</span></span>"; } else if (n->def && n->def->definitionType()==Definition::TypeDir) @@ -591,7 +591,7 @@ static bool generateJSTree(NavIndexEntryList &navIndex,FTextStream &t, { if (n->def && n->def->definitionType()==Definition::TypeFile) { - const FileDef *fd = dynamic_cast<const FileDef*>(n->def); + const FileDef *fd = toFileDef(n->def); bool doc,src; doc = fileVisibleInIndex(fd,src); if (doc) diff --git a/src/groupdef.cpp b/src/groupdef.cpp index 9b33356..bad8526 100644 --- a/src/groupdef.cpp +++ b/src/groupdef.cpp @@ -45,7 +45,7 @@ //--------------------------------------------------------------------------- -class GroupDefImpl : public DefinitionImpl, public GroupDef +class GroupDefImpl : public DefinitionMixin<GroupDef> { public: GroupDefImpl(const char *fileName,int line,const char *name,const char *title,const char *refFileName=0); @@ -54,7 +54,7 @@ class GroupDefImpl : public DefinitionImpl, public GroupDef virtual DefType definitionType() const { return TypeGroup; } virtual QCString getOutputFileBase() const; virtual QCString anchor() const { return QCString(); } - virtual QCString displayName(bool=TRUE) const { return hasGroupTitle() ? m_title : DefinitionImpl::name(); } + virtual QCString displayName(bool=TRUE) const { return hasGroupTitle() ? m_title : DefinitionMixin::name(); } virtual const char *groupTitle() const { return m_title; } virtual void setGroupTitle( const char *newtitle ); virtual bool hasGroupTitle( ) const { return m_titleSet; } @@ -161,7 +161,7 @@ GroupDef *createGroupDef(const char *fileName,int line,const char *name, //--------------------------------------------------------------------------- GroupDefImpl::GroupDefImpl(const char *df,int dl,const char *na,const char *t, - const char *refFileName) : DefinitionImpl(df,dl,1,na) + const char *refFileName) : DefinitionMixin(df,dl,1,na) { m_fileList = new FileList; m_classSDict = new ClassSDict(17); @@ -228,6 +228,7 @@ void GroupDefImpl::distributeMemberGroupDocumentation() void GroupDefImpl::findSectionsInDocumentation() { + docFindSections(briefDescription(),this,docFile()); docFindSections(documentation(),this,docFile()); MemberGroupSDict::Iterator mgli(*m_memberGroupSDict); MemberGroup *mg; @@ -395,13 +396,14 @@ bool GroupDefImpl::insertMember(MemberDef *md,bool docOnly) sameScope // both are found in the same scope ) { - if (srcMd->getGroupAlias()==0) + MemberDefMutable *mdm = toMemberDefMutable(md); + if (mdm && srcMd->getGroupAlias()==0) { - md->setGroupAlias(srcMd); + mdm->setGroupAlias(srcMd); } - else if (md!=srcMd->getGroupAlias()) + else if (mdm && md!=srcMd->getGroupAlias()) { - md->setGroupAlias(srcMd->getGroupAlias()); + mdm->setGroupAlias(srcMd->getGroupAlias()); } return FALSE; // member is the same as one that is already added } @@ -663,7 +665,7 @@ int GroupDefImpl::numDocMembers() const void GroupDefImpl::computeAnchors() { //printf("GroupDefImpl::computeAnchors()\n"); - setAnchors(m_allMemberList); + m_allMemberList->setAnchors(); } void GroupDefImpl::writeTagFile(FTextStream &tagFile) @@ -1436,9 +1438,10 @@ void addClassToGroups(const Entry *root,ClassDef *cd) GroupDef *gd=0; if (!g.groupname.isEmpty() && (gd=Doxygen::groupSDict->find(g.groupname))) { - if (gd->addClass(cd)) + ClassDefMutable *cdm = toClassDefMutable(cd); + if (cdm && gd->addClass(cdm)) { - cd->makePartOfGroup(gd); + cdm->makePartOfGroup(gd); } //printf("Compound %s: in group %s\n",cd->name().data(),gd->groupTitle()); } @@ -1454,7 +1457,14 @@ void addNamespaceToGroups(const Entry *root,NamespaceDef *nd) //printf("group '%s'\n",s->data()); if (!g.groupname.isEmpty() && (gd=Doxygen::groupSDict->find(g.groupname))) { - if (gd->addNamespace(nd)) nd->makePartOfGroup(gd); + if (gd->addNamespace(nd)) + { + NamespaceDefMutable *ndm = toNamespaceDefMutable(nd); + if (ndm) + { + ndm->makePartOfGroup(gd); + } + } //printf("Namespace %s: in group %s\n",nd->name().data(),s->data()); } } @@ -1594,13 +1604,16 @@ void addMemberToGroups(const Entry *root,MemberDef *md) bool success = fgd->insertMember(md); if (success) { - //printf("insertMember successful\n"); - md->setGroupDef(fgd,pri,root->fileName,root->startLine, - !root->doc.isEmpty()); - ClassDef *cd = md->getClassDefOfAnonymousType(); - if (cd) + MemberDefMutable *mdm = toMemberDefMutable(md); + if (mdm) + { + //printf("insertMember successful\n"); + mdm->setGroupDef(fgd,pri,root->fileName,root->startLine,!root->doc.isEmpty()); + } + ClassDefMutable *cdm = toClassDefMutable(mdm->getClassDefOfAnonymousType()); + if (cdm) { - cd->setGroupDefForAllMembers(fgd,pri,root->fileName,root->startLine,root->doc.length() != 0); + cdm->setGroupDefForAllMembers(fgd,pri,root->fileName,root->startLine,root->doc.length() != 0); } } } @@ -1774,3 +1787,32 @@ bool GroupDefImpl::hasDetailedDescription() const !documentation().isEmpty()); } +// --- Cast functions + +GroupDef *toGroupDef(Definition *d) +{ + if (d==0) return 0; + if (d && typeid(*d)==typeid(GroupDefImpl)) + { + return static_cast<GroupDef*>(d); + } + else + { + return 0; + } +} + +const GroupDef *toGroupDef(const Definition *d) +{ + if (d==0) return 0; + if (d && typeid(*d)==typeid(GroupDefImpl)) + { + return static_cast<const GroupDef*>(d); + } + else + { + return 0; + } +} + + diff --git a/src/groupdef.h b/src/groupdef.h index 82fa004..0df5344 100644 --- a/src/groupdef.h +++ b/src/groupdef.h @@ -43,7 +43,7 @@ class MemberDef; class FTextStream; /** A model of a group of symbols. */ -class GroupDef : virtual public Definition +class GroupDef : public DefinitionMutable, public Definition { public: ~GroupDef() {} @@ -108,6 +108,14 @@ class GroupDef : virtual public Definition GroupDef *createGroupDef(const char *fileName,int line,const char *name, const char *title,const char *refFileName=0); +// --- Cast functions + +GroupDef *toGroupDef(Definition *d); +const GroupDef *toGroupDef(const Definition *d); + +// ------------------ + + /** A sorted dictionary of GroupDef objects. */ class GroupSDict : public SDict<GroupDef> { diff --git a/src/htmldocvisitor.cpp b/src/htmldocvisitor.cpp index ea2dffb..b93a2c4 100644 --- a/src/htmldocvisitor.cpp +++ b/src/htmldocvisitor.cpp @@ -1,13 +1,10 @@ /****************************************************************************** * - * - * - * - * Copyright (C) 1997-2015 by Dimitri van Heesch. + * Copyright (C) 1997-2020 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. * @@ -53,7 +50,7 @@ enum contexts_t INTERDD, // 8 INTERTD // 9 }; -static const char *contexts[10] = +static const char *contexts[10] = { "", // 0 "startli", // 1 "startdd", // 2 @@ -65,10 +62,10 @@ static const char *contexts[10] = "interdd", // 8 "intertd" // 9 }; +static const char *hex="0123456789ABCDEF"; static QCString convertIndexWordToAnchor(const QCString &word) { - static char hex[] = "0123456789abcdef"; static int cnt = 0; QCString result="a"; QCString cntStr; @@ -281,8 +278,8 @@ static QCString htmlAttribsToString(const HtmlAttribList &attribs, QCString *pAl //------------------------------------------------------------------------- HtmlDocVisitor::HtmlDocVisitor(FTextStream &t,CodeOutputInterface &ci, - const Definition *ctx) - : DocVisitor(DocVisitor_Html), m_t(t), m_ci(ci), m_insidePre(FALSE), + const Definition *ctx) + : DocVisitor(DocVisitor_Html), m_t(t), m_ci(ci), m_insidePre(FALSE), m_hide(FALSE), m_ctx(ctx) { if (ctx) m_langExt=ctx->getDefFileExtension(); @@ -341,7 +338,7 @@ void HtmlDocVisitor::visit(DocEmoji *s) const char *res = EmojiEntityMapper::instance()->unicode(s->index()); if (res) { - m_t << res; + m_t << "<span class=\"emoji\">"<<res<<"</span>"; } else { @@ -439,12 +436,12 @@ void HtmlDocVisitor::visit(DocStyleChange *s) if (s->enable()) m_t << "<sup" << htmlAttribsToString(s->attribs()) << ">"; else m_t << "</sup>"; break; case DocStyleChange::Center: - if (s->enable()) + if (s->enable()) { forceEndParagraph(s); - m_t << "<center" << htmlAttribsToString(s->attribs()) << ">"; + m_t << "<center" << htmlAttribsToString(s->attribs()) << ">"; } - else + else { m_t << "</center>"; forceStartParagraph(s); @@ -468,12 +465,12 @@ void HtmlDocVisitor::visit(DocStyleChange *s) } break; case DocStyleChange::Div: - if (s->enable()) + if (s->enable()) { forceEndParagraph(s); - m_t << "<div" << htmlAttribsToString(s->attribs()) << ">"; + m_t << "<div" << htmlAttribsToString(s->attribs()) << ">"; } - else + else { m_t << "</div>"; forceStartParagraph(s); @@ -490,7 +487,7 @@ void HtmlDocVisitor::visit(DocStyleChange *s) static void visitPreCaption(FTextStream &t, DocVerbatim *s) { if (s->hasCaption()) - { + { t << "<div class=\"caption\">" << endl; } } @@ -523,11 +520,10 @@ void HtmlDocVisitor::visit(DocVerbatim *s) SrcLangExt langExt = getLanguageFromFileName(lang); switch(s->type()) { - case DocVerbatim::Code: + case DocVerbatim::Code: forceEndParagraph(s); - m_t << PREFRAG_START; - Doxygen::parserManager->getCodeParser(lang) - .parseCode(m_ci, + m_ci.startCodeFragment("DoxyCode"); + getCodeParser(lang).parseCode(m_ci, s->context(), s->text(), langExt, @@ -541,14 +537,14 @@ void HtmlDocVisitor::visit(DocVerbatim *s) TRUE, // show line numbers m_ctx // search context ); - m_t << PREFRAG_END; + m_ci.endCodeFragment("DoxyCode"); forceStartParagraph(s); break; - case DocVerbatim::Verbatim: + case DocVerbatim::Verbatim: forceEndParagraph(s); - m_t << /*PREFRAG_START <<*/ "<pre class=\"fragment\">"; + m_t << "<pre class=\"fragment\">"; filter(s->text()); - m_t << "</pre>" /*<< PREFRAG_END*/; + m_t << "</pre>"; forceStartParagraph(s); break; case DocVerbatim::HtmlOnly: @@ -558,12 +554,12 @@ void HtmlDocVisitor::visit(DocVerbatim *s) if (s->isBlock()) forceStartParagraph(s); } break; - case DocVerbatim::ManOnly: - case DocVerbatim::LatexOnly: - case DocVerbatim::XmlOnly: + case DocVerbatim::ManOnly: + case DocVerbatim::LatexOnly: + case DocVerbatim::XmlOnly: case DocVerbatim::RtfOnly: case DocVerbatim::DocbookOnly: - /* nothing */ + /* nothing */ break; case DocVerbatim::Dot: @@ -572,8 +568,8 @@ void HtmlDocVisitor::visit(DocVerbatim *s) QCString fileName(4096); forceEndParagraph(s); - fileName.sprintf("%s%d%s", - (Config_getString(HTML_OUTPUT)+"/inline_dotgraph_").data(), + fileName.sprintf("%s%d%s", + (Config_getString(HTML_OUTPUT)+"/inline_dotgraph_").data(), dotindex++, ".dot" ); @@ -606,8 +602,8 @@ void HtmlDocVisitor::visit(DocVerbatim *s) static int mscindex = 1; QCString baseName(4096); - baseName.sprintf("%s%d", - (Config_getString(HTML_OUTPUT)+"/inline_mscgraph_").data(), + baseName.sprintf("%s%d", + (Config_getString(HTML_OUTPUT)+"/inline_mscgraph_").data(), mscindex++ ); QFile file(baseName+".msc"); @@ -671,11 +667,10 @@ void HtmlDocVisitor::visit(DocInclude *inc) SrcLangExt langExt = getLanguageFromFileName(inc->extension()); switch(inc->type()) { - case DocInclude::Include: + case DocInclude::Include: forceEndParagraph(inc); - m_t << PREFRAG_START; - Doxygen::parserManager->getCodeParser(inc->extension()) - .parseCode(m_ci, + m_ci.startCodeFragment("DoxyCode"); + getCodeParser(inc->extension()).parseCode(m_ci, inc->context(), inc->text(), langExt, @@ -687,24 +682,23 @@ void HtmlDocVisitor::visit(DocInclude *inc) TRUE, // inlineFragment 0, // memberDef FALSE, // show line numbers - m_ctx // search context + m_ctx // search context ); - m_t << PREFRAG_END; + m_ci.endCodeFragment("DoxyCode"); forceStartParagraph(inc); break; case DocInclude::IncWithLines: - { + { forceEndParagraph(inc); - m_t << PREFRAG_START; + m_ci.startCodeFragment("DoxyCode"); QFileInfo cfi( inc->file() ); FileDef *fd = createFileDef( cfi.dirPath().utf8(), cfi.fileName().utf8() ); - Doxygen::parserManager->getCodeParser(inc->extension()) - .parseCode(m_ci, + getCodeParser(inc->extension()).parseCode(m_ci, inc->context(), inc->text(), langExt, inc->isExample(), - inc->exampleFile(), + inc->exampleFile(), fd, // fileDef, -1, // start line -1, // end line @@ -714,7 +708,7 @@ void HtmlDocVisitor::visit(DocInclude *inc) m_ctx // search context ); delete fd; - m_t << PREFRAG_END; + m_ci.endCodeFragment("DoxyCode"); forceStartParagraph(inc); } break; @@ -733,24 +727,23 @@ void HtmlDocVisitor::visit(DocInclude *inc) if (inc->isBlock()) forceStartParagraph(inc); } break; - case DocInclude::VerbInclude: + case DocInclude::VerbInclude: forceEndParagraph(inc); - m_t << /*PREFRAG_START <<*/ "<pre class=\"fragment\">"; + m_t << "<pre class=\"fragment\">"; filter(inc->text()); - m_t << "</pre>" /*<< PREFRAG_END*/; + m_t << "</pre>"; forceStartParagraph(inc); break; case DocInclude::Snippet: { forceEndParagraph(inc); - m_t << PREFRAG_START; - Doxygen::parserManager->getCodeParser(inc->extension()) - .parseCode(m_ci, + m_ci.startCodeFragment("DoxyCode"); + getCodeParser(inc->extension()).parseCode(m_ci, inc->context(), extractBlock(inc->text(),inc->blockId()), langExt, inc->isExample(), - inc->exampleFile(), + inc->exampleFile(), 0, -1, // startLine -1, // endLine @@ -759,23 +752,22 @@ void HtmlDocVisitor::visit(DocInclude *inc) FALSE, // show line number m_ctx // search context ); - m_t << PREFRAG_END; + m_ci.endCodeFragment("DoxyCode"); forceStartParagraph(inc); } break; case DocInclude::SnipWithLines: { forceEndParagraph(inc); - m_t << PREFRAG_START; + m_ci.startCodeFragment("DoxyCode"); QFileInfo cfi( inc->file() ); FileDef *fd = createFileDef( cfi.dirPath().utf8(), cfi.fileName().utf8() ); - Doxygen::parserManager->getCodeParser(inc->extension()) - .parseCode(m_ci, + getCodeParser(inc->extension()).parseCode(m_ci, inc->context(), extractBlock(inc->text(),inc->blockId()), langExt, inc->isExample(), - inc->exampleFile(), + inc->exampleFile(), fd, lineBlock(inc->text(),inc->blockId()), -1, // endLine @@ -785,12 +777,12 @@ void HtmlDocVisitor::visit(DocInclude *inc) m_ctx // search context ); delete fd; - m_t << PREFRAG_END; + m_ci.endCodeFragment("DoxyCode"); forceStartParagraph(inc); } break; - case DocInclude::SnippetDoc: - case DocInclude::IncludeDoc: + case DocInclude::SnippetDoc: + case DocInclude::IncludeDoc: err("Internal inconsistency: found switch SnippetDoc / IncludeDoc in file: %s" "Please create a bug report\n",__FILE__); break; @@ -801,20 +793,20 @@ void HtmlDocVisitor::visit(DocIncOperator *op) { //printf("DocIncOperator: type=%d first=%d, last=%d text='%s'\n", // op->type(),op->isFirst(),op->isLast(),op->text().data()); - if (op->isFirst()) + if (op->isFirst()) { forceEndParagraph(op); - if (!m_hide) m_t << PREFRAG_START; + if (!m_hide) m_ci.startCodeFragment("DoxyCode"); pushEnabled(); m_hide=TRUE; } QCString locLangExt = getFileNameExtension(op->includeFileName()); if (locLangExt.isEmpty()) locLangExt = m_langExt; SrcLangExt langExt = getLanguageFromFileName(locLangExt); - if (op->type()!=DocIncOperator::Skip) + if (op->type()!=DocIncOperator::Skip) { popEnabled(); - if (!m_hide) + if (!m_hide) { FileDef *fd = 0; if (!op->includeFileName().isEmpty()) @@ -822,8 +814,7 @@ void HtmlDocVisitor::visit(DocIncOperator *op) QFileInfo cfi( op->includeFileName() ); fd = createFileDef( cfi.dirPath().utf8(), cfi.fileName().utf8() ); } - Doxygen::parserManager->getCodeParser(locLangExt) - .parseCode( + getCodeParser(locLangExt).parseCode( m_ci, op->context(), op->text(), @@ -843,10 +834,10 @@ void HtmlDocVisitor::visit(DocIncOperator *op) pushEnabled(); m_hide=TRUE; } - if (op->isLast()) + if (op->isLast()) { popEnabled(); - if (!m_hide) m_t << PREFRAG_END; + if (!m_hide) m_ci.endCodeFragment("DoxyCode"); forceStartParagraph(op); } else @@ -859,7 +850,7 @@ void HtmlDocVisitor::visit(DocFormula *f) { if (m_hide) return; bool bDisplay = !f->isInline(); - if (bDisplay) + if (bDisplay) { forceEndParagraph(f); m_t << "<p class=\"formulaDsp\">" << endl; @@ -869,7 +860,7 @@ void HtmlDocVisitor::visit(DocFormula *f) { QCString text = f->text(); bool closeInline = FALSE; - if (!bDisplay && !text.isEmpty() && text.at(0)=='$' && + if (!bDisplay && !text.isEmpty() && text.at(0)=='$' && text.at(text.length()-1)=='$') { closeInline=TRUE; @@ -884,7 +875,7 @@ void HtmlDocVisitor::visit(DocFormula *f) } else { - m_t << "<img class=\"formula" + m_t << "<img class=\"formula" << (bDisplay ? "Dsp" : "Inl"); m_t << "\" alt=\""; filterQuotedCdataAttr(f->text()); @@ -919,7 +910,7 @@ void HtmlDocVisitor::visit(DocFormula *f) void HtmlDocVisitor::visit(DocIndexEntry *e) { QCString anchor = convertIndexWordToAnchor(e->entry()); - if (e->member()) + if (e->member()) { anchor.prepend(e->member()->anchor()+"_"); } @@ -941,7 +932,7 @@ void HtmlDocVisitor::visit(DocSimpleSectSep *) void HtmlDocVisitor::visit(DocCite *cite) { if (m_hide) return; - if (!cite->file().isEmpty()) + if (!cite->file().isEmpty()) { startLink(cite->ref(),cite->file(),cite->relPath(),cite->anchor()); } @@ -950,7 +941,7 @@ void HtmlDocVisitor::visit(DocCite *cite) m_t << "<b>["; } filter(cite->text()); - if (!cite->file().isEmpty()) + if (!cite->file().isEmpty()) { endLink(); } @@ -978,7 +969,7 @@ void HtmlDocVisitor::visitPre(DocAutoList *l) // 1. // a. // i. - // A. + // A. // 1. (repeat)... // m_t << "<ol type=\"" << types[l->depth() % NUM_HTML_LIST_TYPES] << "\""; @@ -1013,20 +1004,20 @@ void HtmlDocVisitor::visitPre(DocAutoListItem *) m_t << "<li>"; } -void HtmlDocVisitor::visitPost(DocAutoListItem *li) +void HtmlDocVisitor::visitPost(DocAutoListItem *li) { if (m_hide) return; m_t << "</li>"; if (!li->isPreformatted()) m_t << "\n"; } -template<class T> +template<class T> bool isFirstChildNode(T *parent, DocNode *node) { return parent->children().getFirst()==node; } -template<class T> +template<class T> bool isLastChildNode(T *parent, DocNode *node) { return parent->children().getLast()==node; @@ -1070,7 +1061,7 @@ static int getParagraphContext(DocPara *p,bool &isFirst,bool &isLast) isLast=FALSE; if (p && p->parent()) { - switch (p->parent()->kind()) + switch (p->parent()->kind()) { case DocNode::Kind_ParBlock: { // hierarchy: node N -> para -> parblock -> para @@ -1215,7 +1206,7 @@ static int getParagraphContext(DocPara *p,bool &isFirst,bool &isLast) return t; } -void HtmlDocVisitor::visitPre(DocPara *p) +void HtmlDocVisitor::visitPre(DocPara *p) { if (m_hide) return; @@ -1223,9 +1214,9 @@ void HtmlDocVisitor::visitPre(DocPara *p) // p->parent() ? p->parent()->kind() : -1); bool needsTag = FALSE; - if (p && p->parent()) + if (p && p->parent()) { - switch (p->parent()->kind()) + switch (p->parent()->kind()) { case DocNode::Kind_Section: case DocNode::Kind_Internal: @@ -1250,7 +1241,7 @@ void HtmlDocVisitor::visitPre(DocPara *p) } // if the first element of a paragraph is something that should be outside of - // the paragraph (<ul>,<dl>,<table>,..) then that will already started the + // the paragraph (<ul>,<dl>,<table>,..) then that will already started the // paragraph and we don't need to do it here bool paragraphAlreadyStarted = false; uint nodeIndex = 0; @@ -1296,9 +1287,9 @@ void HtmlDocVisitor::visitPost(DocPara *p) // p->parent() ? p->parent()->kind() : -1); bool needsTag = FALSE; - if (p->parent()) + if (p->parent()) { - switch (p->parent()->kind()) + switch (p->parent()->kind()) { case DocNode::Kind_Section: case DocNode::Kind_Internal: @@ -1323,7 +1314,7 @@ void HtmlDocVisitor::visitPost(DocPara *p) } // if the last element of a paragraph is something that should be outside of - // the paragraph (<ul>,<dl>,<table>) then that will already have ended the + // the paragraph (<ul>,<dl>,<table>) then that will already have ended the // paragraph and we don't need to do it here int nodeIndex = p->children().count()-1; if (nodeIndex>=0) @@ -1372,21 +1363,21 @@ void HtmlDocVisitor::visitPre(DocSimpleSect *s) m_t << "<dl class=\"section " << s->typeString() << "\"><dt>"; switch(s->type()) { - case DocSimpleSect::See: + case DocSimpleSect::See: m_t << theTranslator->trSeeAlso(); break; - case DocSimpleSect::Return: + case DocSimpleSect::Return: m_t << theTranslator->trReturns(); break; - case DocSimpleSect::Author: + case DocSimpleSect::Author: m_t << theTranslator->trAuthor(TRUE,TRUE); break; - case DocSimpleSect::Authors: + case DocSimpleSect::Authors: m_t << theTranslator->trAuthor(TRUE,FALSE); break; - case DocSimpleSect::Version: + case DocSimpleSect::Version: m_t << theTranslator->trVersion(); break; - case DocSimpleSect::Since: + case DocSimpleSect::Since: m_t << theTranslator->trSince(); break; - case DocSimpleSect::Date: + case DocSimpleSect::Date: m_t << theTranslator->trDate(); break; - case DocSimpleSect::Note: + case DocSimpleSect::Note: m_t << theTranslator->trNote(); break; case DocSimpleSect::Warning: m_t << theTranslator->trWarning(); break; @@ -1454,7 +1445,7 @@ void HtmlDocVisitor::visitPre(DocSimpleListItem *) m_t << "<li>"; } -void HtmlDocVisitor::visitPost(DocSimpleListItem *li) +void HtmlDocVisitor::visitPost(DocSimpleListItem *li) { if (m_hide) return; m_t << "</li>"; @@ -1472,7 +1463,7 @@ void HtmlDocVisitor::visitPre(DocSection *s) m_t << "</h" << s->level() << ">\n"; } -void HtmlDocVisitor::visitPost(DocSection *s) +void HtmlDocVisitor::visitPost(DocSection *s) { forceStartParagraph(s); } @@ -1481,26 +1472,26 @@ void HtmlDocVisitor::visitPre(DocHtmlList *s) { if (m_hide) return; forceEndParagraph(s); - if (s->type()==DocHtmlList::Ordered) + if (s->type()==DocHtmlList::Ordered) { - m_t << "<ol" << htmlAttribsToString(s->attribs()); + m_t << "<ol" << htmlAttribsToString(s->attribs()); } - else + else { m_t << "<ul" << htmlAttribsToString(s->attribs()); } m_t << getDirHtmlClassOfNode(getTextDirByConfig(s)) << ">\n"; } -void HtmlDocVisitor::visitPost(DocHtmlList *s) +void HtmlDocVisitor::visitPost(DocHtmlList *s) { if (m_hide) return; - if (s->type()==DocHtmlList::Ordered) + if (s->type()==DocHtmlList::Ordered) { - m_t << "</ol>"; + m_t << "</ol>"; } else - { + { m_t << "</ul>"; } if (!s->isPreformatted()) m_t << "\n"; @@ -1514,7 +1505,7 @@ void HtmlDocVisitor::visitPre(DocHtmlListItem *i) if (!i->isPreformatted()) m_t << "\n"; } -void HtmlDocVisitor::visitPost(DocHtmlListItem *) +void HtmlDocVisitor::visitPost(DocHtmlListItem *) { if (m_hide) return; m_t << "</li>\n"; @@ -1527,7 +1518,7 @@ void HtmlDocVisitor::visitPre(DocHtmlDescList *dl) m_t << "<dl" << htmlAttribsToString(dl->attribs()) << ">\n"; } -void HtmlDocVisitor::visitPost(DocHtmlDescList *dl) +void HtmlDocVisitor::visitPost(DocHtmlDescList *dl) { if (m_hide) return; m_t << "</dl>\n"; @@ -1542,7 +1533,7 @@ void HtmlDocVisitor::visitPre(DocHtmlDescTitle *dt) << ">"; } -void HtmlDocVisitor::visitPost(DocHtmlDescTitle *) +void HtmlDocVisitor::visitPost(DocHtmlDescTitle *) { if (m_hide) return; m_t << "</dt>\n"; @@ -1551,12 +1542,12 @@ void HtmlDocVisitor::visitPost(DocHtmlDescTitle *) void HtmlDocVisitor::visitPre(DocHtmlDescData *dd) { if (m_hide) return; - m_t << "<dd" << htmlAttribsToString(dd->attribs()) + m_t << "<dd" << htmlAttribsToString(dd->attribs()) << getDirHtmlClassOfNode(getTextDirByConfig(dd)) << ">"; } -void HtmlDocVisitor::visitPost(DocHtmlDescData *) +void HtmlDocVisitor::visitPost(DocHtmlDescData *) { if (m_hide) return; m_t << "</dd>\n"; @@ -1598,7 +1589,7 @@ void HtmlDocVisitor::visitPre(DocHtmlTable *t) } } -void HtmlDocVisitor::visitPost(DocHtmlTable *t) +void HtmlDocVisitor::visitPost(DocHtmlTable *t) { if (m_hide) return; m_t << "</table>\n"; @@ -1611,7 +1602,7 @@ void HtmlDocVisitor::visitPre(DocHtmlRow *tr) m_t << "<tr" << htmlAttribsToString(tr->attribs()) << ">\n"; } -void HtmlDocVisitor::visitPost(DocHtmlRow *) +void HtmlDocVisitor::visitPost(DocHtmlRow *) { if (m_hide) return; m_t << "</tr>\n"; @@ -1620,17 +1611,17 @@ void HtmlDocVisitor::visitPost(DocHtmlRow *) void HtmlDocVisitor::visitPre(DocHtmlCell *c) { if (m_hide) return; - if (c->isHeading()) + if (c->isHeading()) { - m_t << "<th" << htmlAttribsToString(c->attribs()) << ">"; + m_t << "<th" << htmlAttribsToString(c->attribs()) << ">"; } - else + else { m_t << "<td" << htmlAttribsToString(c->attribs()) << ">"; } } -void HtmlDocVisitor::visitPost(DocHtmlCell *c) +void HtmlDocVisitor::visitPost(DocHtmlCell *c) { if (m_hide) return; if (c->isHeading()) m_t << "</th>"; else m_t << "</td>"; @@ -1642,7 +1633,7 @@ void HtmlDocVisitor::visitPre(DocHtmlCaption *c) m_t << "<caption" << htmlAttribsToString(c->attribs()) << ">"; } -void HtmlDocVisitor::visitPost(DocHtmlCaption *) +void HtmlDocVisitor::visitPost(DocHtmlCaption *) { if (m_hide) return; m_t << "</caption>\n"; @@ -1655,7 +1646,7 @@ void HtmlDocVisitor::visitPre(DocInternal *) //m_t << "<p><b>" << theTranslator->trForInternalUseOnly() << "</b></p>" << endl; } -void HtmlDocVisitor::visitPost(DocInternal *) +void HtmlDocVisitor::visitPost(DocInternal *) { if (m_hide) return; //forceStartParagraph(i); @@ -1676,7 +1667,7 @@ void HtmlDocVisitor::visitPre(DocHRef *href) } } -void HtmlDocVisitor::visitPost(DocHRef *) +void HtmlDocVisitor::visitPost(DocHRef *) { if (m_hide) return; m_t << "</a>"; @@ -1686,13 +1677,13 @@ void HtmlDocVisitor::visitPre(DocHtmlHeader *header) { if (m_hide) return; forceEndParagraph(header); - m_t << "<h" << header->level() - << htmlAttribsToString(header->attribs()) + m_t << "<h" << header->level() + << htmlAttribsToString(header->attribs()) << getDirHtmlClassOfNode(getTextDirByConfig(header)) << ">"; } -void HtmlDocVisitor::visitPost(DocHtmlHeader *header) +void HtmlDocVisitor::visitPost(DocHtmlHeader *header) { if (m_hide) return; m_t << "</h" << header->level() << ">\n"; @@ -1834,12 +1825,12 @@ void HtmlDocVisitor::visitPre(DocDotFile *df) m_t << "<div class=\"dotgraph\">" << endl; writeDotFile(df->file(),df->relPath(),df->context()); if (df->hasCaption()) - { + { m_t << "<div class=\"caption\">" << endl; } } -void HtmlDocVisitor::visitPost(DocDotFile *df) +void HtmlDocVisitor::visitPost(DocDotFile *df) { if (m_hide) return; if (df->hasCaption()) @@ -1855,11 +1846,11 @@ void HtmlDocVisitor::visitPre(DocMscFile *df) m_t << "<div class=\"mscgraph\">" << endl; writeMscFile(df->file(),df->relPath(),df->context()); if (df->hasCaption()) - { + { m_t << "<div class=\"caption\">" << endl; } } -void HtmlDocVisitor::visitPost(DocMscFile *df) +void HtmlDocVisitor::visitPost(DocMscFile *df) { if (m_hide) return; if (df->hasCaption()) @@ -1895,7 +1886,7 @@ void HtmlDocVisitor::visitPre(DocLink *lnk) startLink(lnk->ref(),lnk->file(),lnk->relPath(),lnk->anchor()); } -void HtmlDocVisitor::visitPost(DocLink *) +void HtmlDocVisitor::visitPost(DocLink *) { if (m_hide) return; endLink(); @@ -1904,7 +1895,7 @@ void HtmlDocVisitor::visitPost(DocLink *) void HtmlDocVisitor::visitPre(DocRef *ref) { if (m_hide) return; - if (!ref->file().isEmpty()) + if (!ref->file().isEmpty()) { // when ref->isSubPage()==TRUE we use ref->file() for HTML and // ref->anchor() for LaTeX/RTF @@ -1913,7 +1904,7 @@ void HtmlDocVisitor::visitPre(DocRef *ref) if (!ref->hasLinkText()) filter(ref->targetTitle()); } -void HtmlDocVisitor::visitPost(DocRef *ref) +void HtmlDocVisitor::visitPost(DocRef *ref) { if (m_hide) return; if (!ref->file().isEmpty()) endLink(); @@ -1928,7 +1919,7 @@ void HtmlDocVisitor::visitPre(DocSecRefItem *ref) } -void HtmlDocVisitor::visitPost(DocSecRefItem *) +void HtmlDocVisitor::visitPost(DocSecRefItem *) { if (m_hide) return; m_t << "</a></li>\n"; @@ -1942,7 +1933,7 @@ void HtmlDocVisitor::visitPre(DocSecRefList *s) m_t << "<ul class=\"multicol\">" << endl; } -void HtmlDocVisitor::visitPost(DocSecRefList *s) +void HtmlDocVisitor::visitPost(DocSecRefList *s) { if (m_hide) return; m_t << "</ul>" << endl; @@ -1960,7 +1951,7 @@ void HtmlDocVisitor::visitPost(DocSecRefList *s) // } //} // -//void HtmlDocVisitor::visitPost(DocLanguage *l) +//void HtmlDocVisitor::visitPost(DocLanguage *l) //{ // QCString langId = Config_getEnum(OUTPUT_LANGUAGE); // if (l->id().lower()!=langId.lower()) @@ -1977,19 +1968,19 @@ void HtmlDocVisitor::visitPre(DocParamSect *s) QCString heading; switch(s->type()) { - case DocParamSect::Param: - heading=theTranslator->trParameters(); + case DocParamSect::Param: + heading=theTranslator->trParameters(); className="params"; break; - case DocParamSect::RetVal: - heading=theTranslator->trReturnValues(); + case DocParamSect::RetVal: + heading=theTranslator->trReturnValues(); className="retval"; break; - case DocParamSect::Exception: - heading=theTranslator->trExceptions(); + case DocParamSect::Exception: + heading=theTranslator->trExceptions(); className="exception"; break; - case DocParamSect::TemplateParam: + case DocParamSect::TemplateParam: heading=theTranslator->trTemplateParameters(); className="tparams"; break; @@ -2052,11 +2043,11 @@ void HtmlDocVisitor::visitPre(DocParamList *pl) { if (type->kind()==DocNode::Kind_Word) { - visit((DocWord*)type); + visit((DocWord*)type); } else if (type->kind()==DocNode::Kind_LinkedWord) { - visit((DocLinkedWord*)type); + visit((DocLinkedWord*)type); } else if (type->kind()==DocNode::Kind_Sep) { @@ -2076,11 +2067,11 @@ void HtmlDocVisitor::visitPre(DocParamList *pl) if (!first) m_t << ","; else first=FALSE; if (param->kind()==DocNode::Kind_Word) { - visit((DocWord*)param); + visit((DocWord*)param); } else if (param->kind()==DocNode::Kind_LinkedWord) { - visit((DocLinkedWord*)param); + visit((DocLinkedWord*)param); } } m_t << "</td><td>"; @@ -2102,12 +2093,12 @@ void HtmlDocVisitor::visitPre(DocXRefItem *x) bool anonymousEnum = x->file()=="@"; if (!anonymousEnum) { - m_t << "<dl" << getDirHtmlClassOfNode(getTextDirByConfig(x), x->key()) + m_t << "<dl" << getDirHtmlClassOfNode(getTextDirByConfig(x), x->key()) << "><dt><b><a class=\"el\" href=\"" << x->relPath() << addHtmlExtensionIfMissing(x->file()) << "#" << x->anchor() << "\">"; } - else + else { m_t << "<dl class=\"" << x->key() << "\"><dt><b>"; } @@ -2131,7 +2122,7 @@ void HtmlDocVisitor::visitPre(DocInternalRef *ref) startLink(0,ref->file(),ref->relPath(),ref->anchor()); } -void HtmlDocVisitor::visitPost(DocInternalRef *) +void HtmlDocVisitor::visitPost(DocInternalRef *) { if (m_hide) return; endLink(); @@ -2180,7 +2171,7 @@ void HtmlDocVisitor::visitPre(DocVhdlFlow *vf) m_t << "<p>"; m_t << "flowchart: " ; // TODO: translate me m_t << "<a href=\""; - m_t << fname.data(); + m_t << fname.data(); m_t << ".svg\">"; m_t << VhdlDocGen::getFlowMember()->name().data(); m_t << "</a>"; @@ -2214,7 +2205,7 @@ void HtmlDocVisitor::visitPost(DocParBlock *) void HtmlDocVisitor::filter(const char *str) -{ +{ if (str==0) return; const char *p=str; char c; @@ -2227,11 +2218,23 @@ void HtmlDocVisitor::filter(const char *str) case '>': m_t << ">"; break; case '&': m_t << "&"; break; case '\\': if ((*p == '(') || (*p == ')')) - m_t << "\\‍" << *p++; - else - m_t << c; - break; - default: m_t << c; + m_t << "\\‍" << *p++; + else + m_t << c; + break; + default: + { + uchar uc = static_cast<uchar>(c); + if (uc<32 && !isspace(c)) // non-printable control characters + { + m_t << "$" << hex[uc>>4] << hex[uc&0xF] << ";"; + } + else + { + m_t << c; + } + } + break; } } } @@ -2253,11 +2256,23 @@ void HtmlDocVisitor::filterQuotedCdataAttr(const char* str) case '<': m_t << "<"; break; case '>': m_t << ">"; break; case '\\': if ((*p == '(') || (*p == ')')) - m_t << "\\‍" << *p++; - else - m_t << c; - break; - default: m_t << c; + m_t << "\\‍" << *p++; + else + m_t << c; + break; + default: + { + uchar uc = static_cast<uchar>(c); + if (uc<32 && !isspace(c)) // non-printable control characters + { + m_t << "$" << hex[uc>>4] << hex[uc&0xF] << ";"; + } + else + { + m_t << c; + } + } + break; } } } diff --git a/src/htmlgen.cpp b/src/htmlgen.cpp index 601c02e..cd615e4 100644 --- a/src/htmlgen.cpp +++ b/src/htmlgen.cpp @@ -16,8 +16,10 @@ */ #include <stdlib.h> - #include <assert.h> + +#include <mutex> + #include <qdir.h> #include <qregexp.h> #include "message.h" @@ -58,8 +60,7 @@ static QCString g_header; static QCString g_footer; static QCString g_mathjax_code; static QCString g_latex_macro; - -static bool DoxyCodeLineOpen = FALSE; +static const char *hex="0123456789ABCDEF"; // note: this is only active if DISABLE_INDEX=YES, if DISABLE_INDEX is disabled, this // part will be rendered inside menu.js @@ -608,12 +609,11 @@ static QCString substituteHtmlKeywords(const QCString &str, //-------------------------------------------------------------------------- HtmlCodeGenerator::HtmlCodeGenerator() - : m_streamSet(FALSE), m_col(0) { } HtmlCodeGenerator::HtmlCodeGenerator(FTextStream &t,const QCString &relPath) - : m_col(0), m_relPath(relPath) + : m_relPath(relPath) { setTextStream(t); } @@ -673,9 +673,21 @@ void HtmlCodeGenerator::codify(const char *str) m_t << "\\"; m_col++; break; - default: p=writeUtf8Char(m_t,p-1); - m_col++; - break; + default: + { + uchar uc = static_cast<uchar>(c); + if (uc<32) + { + m_t << "$" << hex[uc>>4] << hex[uc&0xF] << ";"; + m_col++; + } + else + { + p=writeUtf8Char(m_t,p-1); + m_col++; + } + } + break; } } } @@ -699,18 +711,30 @@ void HtmlCodeGenerator::docify(const char *str) case '&': m_t << "&"; break; case '"': m_t << """; break; case '\\': - if (*p=='<') - { m_t << "<"; p++; } - else if (*p=='>') - { m_t << ">"; p++; } - else if (*p=='(') - { m_t << "\\‍("; p++; } - else if (*p==')') - { m_t << "\\‍)"; p++; } - else - m_t << "\\"; - break; - default: m_t << c; + if (*p=='<') + { m_t << "<"; p++; } + else if (*p=='>') + { m_t << ">"; p++; } + else if (*p=='(') + { m_t << "\\‍("; p++; } + else if (*p==')') + { m_t << "\\‍)"; p++; } + else + m_t << "\\"; + break; + default: + { + uchar uc = static_cast<uchar>(c); + if (uc<32 && !isspace(c)) + { + m_t << "$" << hex[uc>>4] << hex[uc&0xF] << ";"; + } + else + { + m_t << c; + } + } + break; } } } @@ -726,10 +750,10 @@ void HtmlCodeGenerator::writeLineNumber(const char *ref,const char *filename, qsnprintf(lineNumber,maxLineNrStr,"%5d",l); qsnprintf(lineAnchor,maxLineNrStr,"l%05d",l); - if (!DoxyCodeLineOpen) + if (!m_lineOpen) { m_t << "<div class=\"line\">"; - DoxyCodeLineOpen = TRUE; + m_lineOpen = TRUE; } m_t << "<a name=\"" << lineAnchor << "\"></a><span class=\"lineno\">"; @@ -868,10 +892,10 @@ void HtmlCodeGenerator::startCodeLine(bool) if (m_streamSet) { m_col=0; - if (!DoxyCodeLineOpen) + if (!m_lineOpen) { m_t << "<div class=\"line\">"; - DoxyCodeLineOpen = TRUE; + m_lineOpen = TRUE; } } } @@ -885,10 +909,10 @@ void HtmlCodeGenerator::endCodeLine() m_t << " "; m_col++; } - if (DoxyCodeLineOpen) + if (m_lineOpen) { m_t << "</div>\n"; - DoxyCodeLineOpen = FALSE; + m_lineOpen = FALSE; } } } @@ -908,6 +932,20 @@ void HtmlCodeGenerator::writeCodeAnchor(const char *anchor) if (m_streamSet) m_t << "<a name=\"" << anchor << "\"></a>"; } +void HtmlCodeGenerator::startCodeFragment(const char *) +{ + if (m_streamSet) m_t << "<div class=\"fragment\">"; +} + +void HtmlCodeGenerator::endCodeFragment(const char *) +{ + //endCodeLine checks is there is still an open code line, if so closes it. + endCodeLine(); + + if (m_streamSet) m_t << "</div><!-- fragment -->"; +} + + //-------------------------------------------------------------------------- HtmlGenerator::HtmlGenerator() : OutputGenerator(Config_getString(HTML_OUTPUT)) @@ -1114,8 +1152,10 @@ void HtmlGenerator::writeFooterFile(QFile &file) t << ResourceMgr::instance().getAsString("footer.html"); } +static std::mutex g_indexLock; + void HtmlGenerator::startFile(const char *name,const char *, - const char *title) + const char *title,int id) { //printf("HtmlGenerator::startFile(%s)\n",name); m_relPath = relativePathToRoot(name); @@ -1123,9 +1163,13 @@ void HtmlGenerator::startFile(const char *name,const char *, m_lastTitle=title; startPlainFile(fileName); + m_codeGen.setId(id); m_codeGen.setTextStream(t); m_codeGen.setRelativePath(m_relPath); - Doxygen::indexList->addIndexFile(fileName); + { + std::lock_guard<std::mutex> lock(g_indexLock); + Doxygen::indexList->addIndexFile(fileName); + } m_lastFile = fileName; t << substituteHtmlKeywords(g_header,convertToHtml(filterTitle(title)),m_relPath); @@ -1139,7 +1183,7 @@ void HtmlGenerator::startFile(const char *name,const char *, t << "<script type=\"text/javascript\">\n"; t << "/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&dn=gpl-2.0.txt GPL-v2 */\n"; t << "var searchBox = new SearchBox(\"searchBox\", \"" - << m_relPath<< "search\",false,'" << theTranslator->trSearch() << "');\n"; + << m_relPath<< "search\",false,'" << theTranslator->trSearch() << "','" << Doxygen::htmlFileExtension << "');\n"; t << "/* @license-end */\n"; t << "</script>\n"; } @@ -1191,7 +1235,7 @@ QCString HtmlGenerator::writeLogoAsString(const char *path) { result += theTranslator->trGeneratedBy(); } - result += " \n<a href=\"http://www.doxygen.org/index.html\">\n" + result += " \n<a href=\"https://www.doxygen.org/index.html\">\n" "<img class=\"footer\" src=\""; result += path; result += "doxygen.svg\" width=\"104\" height=\"31\" alt=\"doxygen\"/></a> "; @@ -1213,9 +1257,6 @@ void HtmlGenerator::writePageFooter(FTextStream &t,const QCString &lastTitle, void HtmlGenerator::writeFooter(const char *navPath) { - // Currently only tooltips in HTML - TooltipManager::instance()->writeTooltips(m_codeGen); - writePageFooter(t,m_lastTitle,m_relPath,navPath); } @@ -2223,8 +2264,9 @@ void HtmlGenerator::endParamList() t << "</dl>"; } -void HtmlGenerator::writeDoc(DocNode *n,const Definition *ctx,const MemberDef *) +void HtmlGenerator::writeDoc(DocNode *n,const Definition *ctx,const MemberDef *,int id) { + m_codeGen.setId(id); HtmlDocVisitor *visitor = new HtmlDocVisitor(t,m_codeGen,ctx); n->accept(visitor); delete visitor; @@ -2674,7 +2716,7 @@ void HtmlGenerator::writeSearchPage() t << "<script type=\"text/javascript\">\n"; t << "/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&dn=gpl-2.0.txt GPL-v2 */\n"; t << "var searchBox = new SearchBox(\"searchBox\", \"" - << "search\",false,'" << theTranslator->trSearch() << "');\n"; + << "search\",false,'" << theTranslator->trSearch() << "','" << Doxygen::htmlFileExtension << "');\n"; t << "/* @license-end */\n"; t << "</script>\n"; if (!Config_getBool(DISABLE_INDEX)) @@ -2728,7 +2770,7 @@ void HtmlGenerator::writeExternalSearchPage() t << "<script type=\"text/javascript\">\n"; t << "/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&dn=gpl-2.0.txt GPL-v2 */\n"; t << "var searchBox = new SearchBox(\"searchBox\", \"" - << "search\",false,'" << theTranslator->trSearch() << "');\n"; + << "search\",false,'" << theTranslator->trSearch() << "','" << Doxygen::htmlFileExtension << "');\n"; t << "/* @license-end */\n"; t << "</script>\n"; if (!Config_getBool(DISABLE_INDEX)) @@ -2861,19 +2903,6 @@ 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) diff --git a/src/htmlgen.h b/src/htmlgen.h index 9487e60..659a69e 100644 --- a/src/htmlgen.h +++ b/src/htmlgen.h @@ -1,8 +1,6 @@ /****************************************************************************** * - * - * - * Copyright (C) 1997-2015 by Dimitri van Heesch. + * Copyright (C) 1997-2020 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 @@ -21,11 +19,6 @@ #include "outputgen.h" #include "ftextstream.h" -//#define PREFRAG_START "<div class=\"fragment\"><pre class=\"fragment\">" -//#define PREFRAG_END "</pre></div>" -#define PREFRAG_START "<div class=\"fragment\">" -#define PREFRAG_END "</div><!-- fragment -->" - class QFile; class HtmlCodeGenerator : public CodeOutputInterface @@ -33,6 +26,8 @@ class HtmlCodeGenerator : public CodeOutputInterface public: HtmlCodeGenerator(FTextStream &t,const QCString &relPath); HtmlCodeGenerator(); + int id() const { return m_id; } + void setId(int id) { m_id = id; } void setTextStream(FTextStream &t); void setRelativePath(const QCString &path); void codify(const char *text); @@ -54,6 +49,8 @@ class HtmlCodeGenerator : public CodeOutputInterface void writeCodeAnchor(const char *anchor); void setCurrentDoc(const Definition *,const char *,bool) {} void addWord(const char *,bool) {} + void startCodeFragment(const char *style); + void endCodeFragment(const char *); private: void _writeCodeLink(const char *className, @@ -61,10 +58,12 @@ class HtmlCodeGenerator : public CodeOutputInterface const char *anchor,const char *name, const char *tooltip); void docify(const char *str); - bool m_streamSet; + bool m_streamSet = false; FTextStream m_t; - int m_col; + int m_col = 0; QCString m_relPath; + bool m_lineOpen = false; + int m_id = 0; }; /** Generator for HTML output */ @@ -113,13 +112,17 @@ class HtmlGenerator : public OutputGenerator { m_codeGen.endFontClass(); } void writeCodeAnchor(const char *anchor) { m_codeGen.writeCodeAnchor(anchor); } + void startCodeFragment(const char *style) + { m_codeGen.startCodeFragment(style); } + void endCodeFragment(const char *style) + { m_codeGen.endCodeFragment(style); } // --------------------------- void setCurrentDoc(const Definition *context,const char *anchor,bool isSourceFile); void addWord(const char *word,bool hiPriority); - void writeDoc(DocNode *,const Definition *,const MemberDef *); + void writeDoc(DocNode *,const Definition *,const MemberDef *,int id); - void startFile(const char *name,const char *manName,const char *title); + void startFile(const char *name,const char *manName,const char *title,int id); void writeFooter(const char *navPath); void endFile(); void clearBuffer(); @@ -208,8 +211,6 @@ class HtmlGenerator : public OutputGenerator void writeRuler() { t << "<hr/>"; } void writeAnchor(const char *,const char *name) { t << "<a name=\"" << name <<"\" id=\"" << name << "\"></a>"; } - void startCodeFragment(); - void endCodeFragment(); void startEmphasis() { t << "<em>"; } void endEmphasis() { t << "</em>"; } void startBold() { t << "<b>"; } diff --git a/src/index.cpp b/src/index.cpp index 12f35f2..dbd9770 100644 --- a/src/index.cpp +++ b/src/index.cpp @@ -254,7 +254,7 @@ QCString fixSpaces(const QCString &s) return substitute(s," "," "); } -void startTitle(OutputList &ol,const char *fileName,const Definition *def) +void startTitle(OutputList &ol,const char *fileName,const DefinitionMutable *def) { ol.startHeaderSection(); if (def) def->writeSummaryLinks(ol); @@ -307,7 +307,6 @@ void endFile(OutputList &ol,bool skipNavIndex,bool skipEndContents, ol.writeFooter(navPath); // write the footer ol.popGeneratorState(); ol.endFile(); - TooltipManager::instance()->clearTooltips(); // Only clear after the last is written } void endFileWithNavPath(const Definition *d,OutputList &ol) @@ -326,6 +325,66 @@ void endFileWithNavPath(const Definition *d,OutputList &ol) } //---------------------------------------------------------------------- + +static bool memberVisibleInIndex(const MemberDef *md) +{ + bool isAnonymous = md->isAnonymous(); + bool hideUndocMembers = Config_getBool(HIDE_UNDOC_MEMBERS); + bool extractStatic = Config_getBool(EXTRACT_STATIC); + return (!isAnonymous && + (!hideUndocMembers || md->hasDocumentation()) && + (!md->isStatic() || extractStatic) + ); +} + +static void writeMemberToIndex(const Definition *def,const MemberDef *md,bool addToIndex) +{ + bool isAnonymous = md->isAnonymous(); + bool hideUndocMembers = Config_getBool(HIDE_UNDOC_MEMBERS); + const MemberList *enumList = md->enumFieldList(); + bool isDir = enumList!=0 && md->isEnumerate(); + if (md->getOuterScope()==def || md->getOuterScope()==Doxygen::globalScope) + { + Doxygen::indexList->addContentsItem(isDir, + md->name(),md->getReference(),md->getOutputFileBase(),md->anchor(),FALSE,addToIndex); + } + else // inherited member + { + Doxygen::indexList->addContentsItem(isDir, + md->name(),def->getReference(),def->getOutputFileBase(),md->anchor(),FALSE,addToIndex); + } + if (isDir) + { + if (!isAnonymous) + { + Doxygen::indexList->incContentsDepth(); + } + MemberListIterator emli(*enumList); + MemberDef *emd; + for (emli.toFirst();(emd=emli.current());++emli) + { + if (!hideUndocMembers || emd->hasDocumentation()) + { + if (emd->getOuterScope()==def || emd->getOuterScope()==Doxygen::globalScope) + { + Doxygen::indexList->addContentsItem(FALSE, + emd->name(),emd->getReference(),emd->getOutputFileBase(),emd->anchor(),FALSE,addToIndex); + } + else // inherited member + { + Doxygen::indexList->addContentsItem(FALSE, + emd->name(),def->getReference(),def->getOutputFileBase(),emd->anchor(),FALSE,addToIndex); + } + } + } + if (!isAnonymous) + { + Doxygen::indexList->decContentsDepth(); + } + } +} + +//---------------------------------------------------------------------- template<class T> void addMembersToIndex(T *def,LayoutDocManager::LayoutPart part, const QCString &name,const QCString &anchor, @@ -366,55 +425,9 @@ void addMembersToIndex(T *def,LayoutDocManager::LayoutPart part, MemberDef *md; for (mi.toFirst();(md=mi.current());++mi) { - const MemberList *enumList = md->enumFieldList(); - bool isDir = enumList!=0 && md->isEnumerate(); - bool isAnonymous = md->isAnonymous(); - static bool hideUndocMembers = Config_getBool(HIDE_UNDOC_MEMBERS); - static bool extractStatic = Config_getBool(EXTRACT_STATIC); - if (!isAnonymous && - (!hideUndocMembers || md->hasDocumentation()) && - (!md->isStatic() || extractStatic) - ) + if (memberVisibleInIndex(md)) { - if (md->getOuterScope()==def || md->getOuterScope()==Doxygen::globalScope) - { - Doxygen::indexList->addContentsItem(isDir, - md->name(),md->getReference(),md->getOutputFileBase(),md->anchor(),FALSE,addToIndex); - } - else // inherited member - { - Doxygen::indexList->addContentsItem(isDir, - md->name(),def->getReference(),def->getOutputFileBase(),md->anchor(),FALSE,addToIndex); - } - } - if (isDir) - { - if (!isAnonymous) - { - Doxygen::indexList->incContentsDepth(); - } - MemberListIterator emli(*enumList); - MemberDef *emd; - for (emli.toFirst();(emd=emli.current());++emli) - { - if (!hideUndocMembers || emd->hasDocumentation()) - { - if (emd->getOuterScope()==def || emd->getOuterScope()==Doxygen::globalScope) - { - Doxygen::indexList->addContentsItem(FALSE, - emd->name(),emd->getReference(),emd->getOutputFileBase(),emd->anchor(),FALSE,addToIndex); - } - else // inherited member - { - Doxygen::indexList->addContentsItem(FALSE, - emd->name(),def->getReference(),def->getOutputFileBase(),emd->anchor(),FALSE,addToIndex); - } - } - } - if (!isAnonymous) - { - Doxygen::indexList->decContentsDepth(); - } + writeMemberToIndex(def,md,addToIndex); } } } @@ -451,14 +464,13 @@ void addMembersToIndex(T *def,LayoutDocManager::LayoutPart part, //---------------------------------------------------------------------------- /*! Generates HTML Help tree of classes */ -static void writeClassTree(OutputList &ol,const BaseClassList *bcl,bool hideSuper,int level,FTVHelp* ftv,bool addToIndex) +static void writeClassTreeToOutput(OutputList &ol,const BaseClassList &bcl,int level,FTVHelp* ftv,bool addToIndex,ClassDefSet &visitedClasses) { - if (bcl==0) return; - BaseClassListIterator bcli(*bcl); + if (bcl.empty()) return; bool started=FALSE; - for ( ; bcli.current() ; ++bcli) + for (const auto &bcd : bcl) { - ClassDef *cd=bcli.current()->classDef; + ClassDef *cd=bcd.classDef; if (cd->getLanguage()==SrcLangExt_VHDL && (VhdlDocGen::VhdlClasses)cd->protection()!=VhdlDocGen::ENTITYCLASS) { continue; @@ -491,7 +503,8 @@ static void writeClassTree(OutputList &ol,const BaseClassList *bcl,bool hideSupe } ol.startIndexListItem(); //printf("Passed...\n"); - bool hasChildren = !cd->isVisited() && !hideSuper && classHasVisibleChildren(cd); + bool hasChildren = visitedClasses.find(cd)==visitedClasses.end() && + classHasVisibleChildren(cd); //printf("tree4: Has children %s: %d\n",cd->name().data(),hasChildren); if (cd->isLinkable()) { @@ -513,7 +526,7 @@ static void writeClassTree(OutputList &ol,const BaseClassList *bcl,bool hideSupe { if (cd->getLanguage()==SrcLangExt_VHDL) { - ftv->addContentsItem(hasChildren,bcli.current()->usedName,cd->getReference(),cd->getOutputFileBase(),cd->anchor(),FALSE,FALSE,cd); + ftv->addContentsItem(hasChildren,bcd.usedName,cd->getReference(),cd->getOutputFileBase(),cd->anchor(),FALSE,FALSE,cd); } else { @@ -538,15 +551,14 @@ static void writeClassTree(OutputList &ol,const BaseClassList *bcl,bool hideSupe if (hasChildren) { //printf("Class %s at %p visited=%d\n",cd->name().data(),cd,cd->visited); - bool wasVisited=cd->isVisited(); - cd->setVisited(TRUE); + visitedClasses.insert(cd); if (cd->getLanguage()==SrcLangExt_VHDL) { - writeClassTree(ol,cd->baseClasses(),wasVisited,level+1,ftv,addToIndex); + writeClassTreeToOutput(ol,cd->baseClasses(),level+1,ftv,addToIndex,visitedClasses); } else { - writeClassTree(ol,cd->subClasses(),wasVisited,level+1,ftv,addToIndex); + writeClassTreeToOutput(ol,cd->subClasses(),level+1,ftv,addToIndex,visitedClasses); } } ol.endIndexListItem(); @@ -820,7 +832,7 @@ static void writeDirHierarchy(OutputList &ol, FTVHelp* ftv,bool addToIndex) //---------------------------------------------------------------------------- static void writeClassTreeForList(OutputList &ol,ClassSDict *cl,bool &started,FTVHelp* ftv,bool addToIndex, - ClassDef::CompoundType ct) + ClassDef::CompoundType ct,ClassDefSet &visitedClasses) { static bool sliceOpt = Config_getBool(OPTIMIZE_OUTPUT_SLICE); ClassSDict::Iterator cli(*cl); @@ -864,7 +876,8 @@ static void writeClassTreeForList(OutputList &ol,ClassSDict *cl,bool &started,FT started=TRUE; } ol.startIndexListItem(); - bool hasChildren = !cd->isVisited() && classHasVisibleChildren(cd); + bool hasChildren = visitedClasses.find(cd)==visitedClasses.end() && + classHasVisibleChildren(cd); //printf("list: Has children %s: %d\n",cd->name().data(),hasChildren); if (cd->isLinkable()) { @@ -905,13 +918,13 @@ static void writeClassTreeForList(OutputList &ol,ClassSDict *cl,bool &started,FT } if (cd->getLanguage()==SrcLangExt_VHDL && hasChildren) { - writeClassTree(ol,cd->baseClasses(),cd->isVisited(),1,ftv,addToIndex); - cd->setVisited(TRUE); + writeClassTreeToOutput(ol,cd->baseClasses(),1,ftv,addToIndex,visitedClasses); + visitedClasses.insert(cd); } else if (hasChildren) { - writeClassTree(ol,cd->subClasses(),cd->isVisited(),1,ftv,addToIndex); - cd->setVisited(TRUE); + writeClassTreeToOutput(ol,cd->subClasses(),1,ftv,addToIndex,visitedClasses); + visitedClasses.insert(cd); } ol.endIndexListItem(); } @@ -921,16 +934,15 @@ static void writeClassTreeForList(OutputList &ol,ClassSDict *cl,bool &started,FT static void writeClassHierarchy(OutputList &ol, FTVHelp* ftv,bool addToIndex,ClassDef::CompoundType ct) { - initClassHierarchy(Doxygen::classSDict); - initClassHierarchy(Doxygen::hiddenClasses); + ClassDefSet visitedClasses; if (ftv) { ol.pushGeneratorState(); ol.disable(OutputGenerator::Html); } bool started=FALSE; - writeClassTreeForList(ol,Doxygen::classSDict,started,ftv,addToIndex,ct); - writeClassTreeForList(ol,Doxygen::hiddenClasses,started,ftv,addToIndex,ct); + writeClassTreeForList(ol,Doxygen::classSDict,started,ftv,addToIndex,ct,visitedClasses); + writeClassTreeForList(ol,Doxygen::hiddenClasses,started,ftv,addToIndex,ct,visitedClasses); if (started) { endIndexHierarchy(ol,0); @@ -963,7 +975,7 @@ static int countClassesInTreeList(const ClassSDict &cl, ClassDef::CompoundType c { if (cd->isVisibleInHierarchy()) // should it be visible { - if (cd->subClasses()) // should have sub classes + if (!cd->subClasses().empty()) // should have sub classes { count++; } @@ -976,8 +988,6 @@ static int countClassesInTreeList(const ClassSDict &cl, ClassDef::CompoundType c static int countClassHierarchy(ClassDef::CompoundType ct) { int count=0; - initClassHierarchy(Doxygen::classSDict); - initClassHierarchy(Doxygen::hiddenClasses); count+=countClassesInTreeList(*Doxygen::classSDict, ct); count+=countClassesInTreeList(*Doxygen::hiddenClasses, ct); return count; @@ -1555,7 +1565,7 @@ static int countNamespaces() //---------------------------------------------------------------------------- -void writeClassTree(ClassSDict *clDict,FTVHelp *ftv,bool addToIndex,bool globalOnly,ClassDef::CompoundType ct) +static void writeClassTree(ClassSDict *clDict,FTVHelp *ftv,bool addToIndex,bool globalOnly,ClassDef::CompoundType ct) { static bool sliceOpt = Config_getBool(OPTIMIZE_OUTPUT_SLICE); if (clDict) @@ -1564,7 +1574,8 @@ void writeClassTree(ClassSDict *clDict,FTVHelp *ftv,bool addToIndex,bool globalO ClassDef *cd; for (;(cd=cli.current());++cli) { - if (cd->getLanguage()==SrcLangExt_VHDL) + ClassDefMutable *cdm = toClassDefMutable(cd); + if (cdm && cd->getLanguage()==SrcLangExt_VHDL) { if ((VhdlDocGen::VhdlClasses)cd->protection()==VhdlDocGen::PACKAGECLASS || (VhdlDocGen::VhdlClasses)cd->protection()==VhdlDocGen::PACKBODYCLASS @@ -1575,7 +1586,7 @@ void writeClassTree(ClassSDict *clDict,FTVHelp *ftv,bool addToIndex,bool globalO if ((VhdlDocGen::VhdlClasses)cd->protection()==VhdlDocGen::ARCHITECTURECLASS) { QCString n=cd->name(); - cd->setClassName(n.data()); + cdm->setClassName(n.data()); } } @@ -1606,9 +1617,7 @@ void writeClassTree(ClassSDict *clDict,FTVHelp *ftv,bool addToIndex,bool globalO { ftv->addContentsItem(count>0,cd->displayName(FALSE),cd->getReference(), cd->getOutputFileBase(),cd->anchor(),FALSE,TRUE,cd); - if (addToIndex && - /*cd->partOfGroups()==0 &&*/ - (cd->getOuterScope()==0 || + if ((cd->getOuterScope()==0 || cd->getOuterScope()->definitionType()!=Definition::TypeClass ) ) @@ -1616,7 +1625,7 @@ void writeClassTree(ClassSDict *clDict,FTVHelp *ftv,bool addToIndex,bool globalO addMembersToIndex(cd,LayoutDocManager::Class, cd->displayName(FALSE), cd->anchor(), - cd->partOfGroups()==0 && !cd->isSimple()); + addToIndex && cd->partOfGroups()==0 && !cd->isSimple()); } if (count>0) { @@ -1630,10 +1639,64 @@ void writeClassTree(ClassSDict *clDict,FTVHelp *ftv,bool addToIndex,bool globalO } } +static int countVisibleMembers(const NamespaceDef *nd) +{ + int count=0; + QListIterator<LayoutDocEntry> eli(LayoutDocManager::instance().docEntries(LayoutDocManager::Namespace)); + LayoutDocEntry *lde; + for (eli.toFirst();(lde=eli.current());++eli) + { + if (lde->kind()==LayoutDocEntry::MemberDef) + { + LayoutDocEntryMemberDef *lmd = (LayoutDocEntryMemberDef*)lde; + MemberList *ml = nd->getMemberList(lmd->type); + if (ml) + { + MemberListIterator mi(*ml); + MemberDef *md; + for (mi.toFirst();(md=mi.current());++mi) + { + if (memberVisibleInIndex(md)) + { + count++; + } + } + } + } + } + return count; +} + +static void writeNamespaceMembers(const NamespaceDef *nd,bool addToIndex) +{ + QListIterator<LayoutDocEntry> eli(LayoutDocManager::instance().docEntries(LayoutDocManager::Namespace)); + LayoutDocEntry *lde; + for (eli.toFirst();(lde=eli.current());++eli) + { + if (lde->kind()==LayoutDocEntry::MemberDef) + { + LayoutDocEntryMemberDef *lmd = (LayoutDocEntryMemberDef*)lde; + MemberList *ml = nd->getMemberList(lmd->type); + if (ml) + { + MemberListIterator mi(*ml); + MemberDef *md; + for (mi.toFirst();(md=mi.current());++mi) + { + //printf(" member %s visible=%d\n",md->name().data(),memberVisibleInIndex(md)); + if (memberVisibleInIndex(md)) + { + writeMemberToIndex(nd,md,addToIndex); + } + } + } + } + } +} + static void writeNamespaceTree(const NamespaceSDict *nsDict,FTVHelp *ftv, - bool rootOnly,bool showClasses,bool addToIndex,ClassDef::CompoundType ct) + bool rootOnly,bool addToIndex) { - static bool sliceOpt = Config_getBool(OPTIMIZE_OUTPUT_SLICE); if (nsDict) { NamespaceSDict::Iterator nli(*nsDict); @@ -1644,8 +1707,12 @@ static void writeNamespaceTree(const NamespaceSDict *nsDict,FTVHelp *ftv, (!rootOnly || nd->getOuterScope()==Doxygen::globalScope)) { - bool hasChildren = namespaceHasVisibleChild(nd,showClasses,sliceOpt,ct); + bool hasChildren = namespaceHasNestedNamespace(nd) || + namespaceHasNestedClass(nd,false,ClassDef::Class); bool isLinkable = nd->isLinkableInProject(); + int visibleMembers = countVisibleMembers(nd); + + //printf("namespace %s hasChildren=%d visibleMembers=%d\n",nd->name().data(),hasChildren,visibleMembers); QCString ref; QCString file; @@ -1659,45 +1726,114 @@ static void writeNamespaceTree(const NamespaceSDict *nsDict,FTVHelp *ftv, } } - if ((isLinkable && !showClasses) || hasChildren) + bool isDir = hasChildren || visibleMembers>0; + if ((isLinkable) || isDir) { ftv->addContentsItem(hasChildren,nd->localName(),ref,file,0,FALSE,TRUE,nd); if (addToIndex) { - Doxygen::indexList->addContentsItem(hasChildren,nd->localName(),ref,file,QCString(), + Doxygen::indexList->addContentsItem(isDir,nd->localName(),ref,file,QCString(), hasChildren && !file.isEmpty(),addToIndex); } + if (addToIndex && isDir) + { + Doxygen::indexList->incContentsDepth(); + } - //printf("*** writeNamespaceTree count=%d addToIndex=%d showClasses=%d classCount=%d\n", - // count,addToIndex,showClasses,classCount); - if (hasChildren) + //printf("*** writeNamespaceTree count=%d addToIndex=%d false=%d classCount=%d\n", + // count,addToIndex,false,classCount); + if (isDir) { - if (addToIndex) Doxygen::indexList->incContentsDepth(); ftv->incContentsDepth(); - writeNamespaceTree(nd->getNamespaceSDict(),ftv,FALSE,showClasses,addToIndex,ct); - if (showClasses) + writeNamespaceTree(nd->getNamespaceSDict(),ftv,FALSE,addToIndex); + writeClassTree(nd->getClassSDict(),ftv,FALSE,FALSE,ClassDef::Class); + writeNamespaceMembers(nd,addToIndex); + ftv->decContentsDepth(); + } + if (addToIndex && isDir) + { + Doxygen::indexList->decContentsDepth(); + } + } + } + } + } +} + +static void writeClassTreeInsideNamespace(const NamespaceSDict *nsDict,FTVHelp *ftv, + bool rootOnly,bool addToIndex,ClassDef::CompoundType ct) +{ + static bool sliceOpt = Config_getBool(OPTIMIZE_OUTPUT_SLICE); + if (nsDict) + { + NamespaceSDict::Iterator nli(*nsDict); + const NamespaceDef *nd; + for (nli.toFirst();(nd=nli.current());++nli) + { + if (!nd->isAnonymous() && + (!rootOnly || nd->getOuterScope()==Doxygen::globalScope)) + { + bool isDir = namespaceHasNestedClass(nd,sliceOpt,ct); + bool isLinkable = nd->isLinkableInProject(); + + //printf("namespace %s isDir=%d\n",nd->name().data(),isDir); + + QCString ref; + QCString file; + if (isLinkable) + { + ref = nd->getReference(); + file = nd->getOutputFileBase(); + if (nd->getLanguage()==SrcLangExt_VHDL) // UGLY HACK + { + file=file.replace(0,qstrlen("namespace"),"class"); + } + } + + if (isDir) + { + ftv->addContentsItem(isDir,nd->localName(),ref,file,0,FALSE,TRUE,nd); + + if (addToIndex) + { + // the namespace entry is already shown under the namespace list so don't + // add it to the nav index and don't create a separate index file for it otherwise + // it will overwrite the one written for the namespace list. + Doxygen::indexList->addContentsItem(isDir,nd->localName(),ref,file,QCString(), + false, // separateIndex + false // addToNavIndex + ); + } + if (addToIndex) + { + Doxygen::indexList->incContentsDepth(); + } + + ftv->incContentsDepth(); + writeClassTreeInsideNamespace(nd->getNamespaceSDict(),ftv,FALSE,addToIndex,ct); + ClassSDict *d = nd->getClassSDict(); + if (sliceOpt) + { + if (ct == ClassDef::Interface) { - ClassSDict *d = nd->getClassSDict(); - if (sliceOpt) - { - if (ct == ClassDef::Interface) - { - d = nd->getInterfaceSDict(); - } - else if (ct == ClassDef::Struct) - { - d = nd->getStructSDict(); - } - else if (ct == ClassDef::Exception) - { - d = nd->getExceptionSDict(); - } - } - writeClassTree(d,ftv,addToIndex,FALSE,ct); + d = nd->getInterfaceSDict(); + } + else if (ct == ClassDef::Struct) + { + d = nd->getStructSDict(); + } + else if (ct == ClassDef::Exception) + { + d = nd->getExceptionSDict(); } - ftv->decContentsDepth(); - if (addToIndex) Doxygen::indexList->decContentsDepth(); + } + writeClassTree(d,ftv,addToIndex,FALSE,ct); + ftv->decContentsDepth(); + + if (addToIndex) + { + Doxygen::indexList->decContentsDepth(); } } } @@ -1795,7 +1931,7 @@ static void writeNamespaceIndex(OutputList &ol) Doxygen::indexList->incContentsDepth(); } FTVHelp* ftv = new FTVHelp(FALSE); - writeNamespaceTree(Doxygen::namespaceSDict,ftv,TRUE,FALSE,addToIndex,ClassDef::Class); + writeNamespaceTree(Doxygen::namespaceSDict,ftv,TRUE,addToIndex); QGString outStr; FTextStream t(&outStr); ftv->generateTreeViewInline(t); @@ -2425,26 +2561,50 @@ static void writeAlphabeticalExceptionIndex(OutputList &ol) //---------------------------------------------------------------------------- -static void writeAnnotatedIndex(OutputList &ol) +struct AnnotatedIndexContext +{ + AnnotatedIndexContext(int numAnno,int numPrint, + LayoutNavEntry::Kind lk,LayoutNavEntry::Kind fk, + const QCString &title,const QCString &intro, + ClassDef::CompoundType ct, + const QCString &fn, + HighlightedItem hi) : + numAnnotated(numAnno), numPrinted(numPrint), + listKind(lk), fallbackKind(fk), + listDefaultTitleText(title), listDefaultIntroText(intro), + compoundType(ct),fileBaseName(fn), + hiItem(hi) { } + + const int numAnnotated; + const int numPrinted; + const LayoutNavEntry::Kind listKind; + const LayoutNavEntry::Kind fallbackKind; + const QCString listDefaultTitleText; + const QCString listDefaultIntroText; + const ClassDef::CompoundType compoundType; + const QCString fileBaseName; + const HighlightedItem hiItem; +}; + +static void writeAnnotatedIndexGeneric(OutputList &ol,const AnnotatedIndexContext ctx) { //printf("writeAnnotatedIndex: count=%d printed=%d\n", // annotatedClasses,annotatedClassesPrinted); - if (annotatedClasses==0) return; + if (ctx.numAnnotated==0) return; ol.pushGeneratorState(); ol.disable(OutputGenerator::Man); - if (annotatedClassesPrinted==0) + if (ctx.numPrinted==0) { ol.disable(OutputGenerator::Latex); ol.disable(OutputGenerator::RTF); } - LayoutNavEntry *lne = LayoutDocManager::instance().rootNavEntry()->find(LayoutNavEntry::ClassList); - if (lne==0) lne = LayoutDocManager::instance().rootNavEntry()->find(LayoutNavEntry::Classes); // fall back - QCString title = lne ? lne->title() : theTranslator->trCompoundList(); + LayoutNavEntry *lne = LayoutDocManager::instance().rootNavEntry()->find(ctx.listKind); + if (lne==0) lne = LayoutDocManager::instance().rootNavEntry()->find(ctx.fallbackKind); // fall back + QCString title = lne ? lne->title() : ctx.listDefaultTitleText; bool addToIndex = lne==0 || lne->visible(); - - startFile(ol,"annotated",0,title,HLI_AnnotatedClasses); + startFile(ol,ctx.fileBaseName,0,title,ctx.hiItem); startTitle(ol,0); ol.parseText(title); @@ -2453,7 +2613,7 @@ static void writeAnnotatedIndex(OutputList &ol) ol.startContents(); ol.startTextBlock(); - ol.parseText(lne ? lne->intro() : theTranslator->trCompoundListDescription()); + ol.parseText(lne ? lne->intro() : ctx.listDefaultIntroText); ol.endTextBlock(); // --------------- @@ -2463,7 +2623,7 @@ static void writeAnnotatedIndex(OutputList &ol) ol.disable(OutputGenerator::Html); Doxygen::indexList->disable(); - writeAnnotatedClassList(ol, ClassDef::Class); + writeAnnotatedClassList(ol, ctx.compoundType); Doxygen::indexList->enable(); ol.popGeneratorState(); @@ -2477,17 +2637,16 @@ static void writeAnnotatedIndex(OutputList &ol) { if (addToIndex) { - Doxygen::indexList->addContentsItem(TRUE,title,0,"annotated",0,TRUE,TRUE); + Doxygen::indexList->addContentsItem(TRUE,title,0,ctx.fileBaseName,0,TRUE,TRUE); Doxygen::indexList->incContentsDepth(); } - FTVHelp* ftv = new FTVHelp(FALSE); - writeNamespaceTree(Doxygen::namespaceSDict,ftv,TRUE,TRUE,addToIndex,ClassDef::Class); - writeClassTree(Doxygen::classSDict,ftv,addToIndex,TRUE,ClassDef::Class); + FTVHelp ftv(false); + writeClassTreeInsideNamespace(Doxygen::namespaceSDict,&ftv,TRUE,addToIndex,ctx.compoundType); + writeClassTree(Doxygen::classSDict,&ftv,addToIndex,TRUE,ctx.compoundType); QGString outStr; FTextStream t(&outStr); - ftv->generateTreeViewInline(t); + ftv.generateTreeViewInline(t); ol.writeString(outStr); - delete ftv; if (addToIndex) { Doxygen::indexList->decContentsDepth(); @@ -2503,233 +2662,58 @@ static void writeAnnotatedIndex(OutputList &ol) //---------------------------------------------------------------------------- -static void writeAnnotatedInterfaceIndex(OutputList &ol) +static void writeAnnotatedIndex(OutputList &ol) { - //printf("writeAnnotatedInterfaceIndex: count=%d printed=%d\n", - // annotatedInterfaces,annotatedInterfacesPrinted); - if (annotatedInterfaces==0) return; - - ol.pushGeneratorState(); - ol.disable(OutputGenerator::Man); - if (annotatedInterfacesPrinted==0) - { - ol.disable(OutputGenerator::Latex); - ol.disable(OutputGenerator::RTF); - } - LayoutNavEntry *lne = LayoutDocManager::instance().rootNavEntry()->find(LayoutNavEntry::InterfaceList); - if (lne==0) lne = LayoutDocManager::instance().rootNavEntry()->find(LayoutNavEntry::Interfaces); // fall back - QCString title = lne ? lne->title() : theTranslator->trInterfaceList(); - bool addToIndex = lne==0 || lne->visible(); - - startFile(ol,"annotatedinterfaces",0,title,HLI_AnnotatedInterfaces); - - startTitle(ol,0); - ol.parseText(title); - endTitle(ol,0,0); - - ol.startContents(); - - ol.startTextBlock(); - ol.parseText(lne ? lne->intro() : theTranslator->trInterfaceListDescription()); - ol.endTextBlock(); - - // --------------- - // Linear interface index for Latex/RTF - // --------------- - ol.pushGeneratorState(); - ol.disable(OutputGenerator::Html); - Doxygen::indexList->disable(); + writeAnnotatedIndexGeneric(ol, + AnnotatedIndexContext(annotatedClasses,annotatedClassesPrinted, + LayoutNavEntry::ClassList,LayoutNavEntry::Classes, + theTranslator->trCompoundList(),theTranslator->trCompoundListDescription(), + ClassDef::Class, + "annotated", + HLI_AnnotatedClasses)); - writeAnnotatedClassList(ol, ClassDef::Interface); - - Doxygen::indexList->enable(); - ol.popGeneratorState(); - - // --------------- - // Hierarchical interface index for HTML - // --------------- - ol.pushGeneratorState(); - ol.disableAllBut(OutputGenerator::Html); +} - { - if (addToIndex) - { - Doxygen::indexList->addContentsItem(TRUE,title,0,"annotatedinterfaces",0,TRUE,TRUE); - Doxygen::indexList->incContentsDepth(); - } - FTVHelp* ftv = new FTVHelp(FALSE); - writeNamespaceTree(Doxygen::namespaceSDict,ftv,TRUE,TRUE,addToIndex,ClassDef::Interface); - writeClassTree(Doxygen::classSDict,ftv,addToIndex,TRUE,ClassDef::Interface); - QGString outStr; - FTextStream t(&outStr); - ftv->generateTreeViewInline(t); - ol.writeString(outStr); - delete ftv; - if (addToIndex) - { - Doxygen::indexList->decContentsDepth(); - } - } +//---------------------------------------------------------------------------- - ol.popGeneratorState(); - // ------ +static void writeAnnotatedInterfaceIndex(OutputList &ol) +{ + writeAnnotatedIndexGeneric(ol, + AnnotatedIndexContext(annotatedInterfaces,annotatedInterfacesPrinted, + LayoutNavEntry::InterfaceList,LayoutNavEntry::Interfaces, + theTranslator->trInterfaceList(),theTranslator->trInterfaceListDescription(), + ClassDef::Interface, + "annotatedinterfaces", + HLI_AnnotatedInterfaces)); - endFile(ol); // contains ol.endContents() - ol.popGeneratorState(); } //---------------------------------------------------------------------------- static void writeAnnotatedStructIndex(OutputList &ol) { - //printf("writeAnnotatedStructIndex: count=%d printed=%d\n", - // annotatedStructs,annotatedStructsPrinted); - if (annotatedStructs==0) return; - - ol.pushGeneratorState(); - ol.disable(OutputGenerator::Man); - if (annotatedStructsPrinted==0) - { - ol.disable(OutputGenerator::Latex); - ol.disable(OutputGenerator::RTF); - } - LayoutNavEntry *lne = LayoutDocManager::instance().rootNavEntry()->find(LayoutNavEntry::StructList); - if (lne==0) lne = LayoutDocManager::instance().rootNavEntry()->find(LayoutNavEntry::Structs); // fall back - QCString title = lne ? lne->title() : theTranslator->trStructList(); - bool addToIndex = lne==0 || lne->visible(); - - startFile(ol,"annotatedstructs",0,title,HLI_AnnotatedStructs); + writeAnnotatedIndexGeneric(ol, + AnnotatedIndexContext(annotatedStructs,annotatedStructsPrinted, + LayoutNavEntry::StructList,LayoutNavEntry::Structs, + theTranslator->trStructList(),theTranslator->trStructListDescription(), + ClassDef::Struct, + "annotatedstructs", + HLI_AnnotatedStructs)); - startTitle(ol,0); - ol.parseText(title); - endTitle(ol,0,0); - - ol.startContents(); - - ol.startTextBlock(); - ol.parseText(lne ? lne->intro() : theTranslator->trStructListDescription()); - ol.endTextBlock(); - - // --------------- - // Linear struct index for Latex/RTF - // --------------- - ol.pushGeneratorState(); - ol.disable(OutputGenerator::Html); - Doxygen::indexList->disable(); - - writeAnnotatedClassList(ol, ClassDef::Struct); - - Doxygen::indexList->enable(); - ol.popGeneratorState(); - - // --------------- - // Hierarchical struct index for HTML - // --------------- - ol.pushGeneratorState(); - ol.disableAllBut(OutputGenerator::Html); - - { - if (addToIndex) - { - Doxygen::indexList->addContentsItem(TRUE,title,0,"annotatedstructs",0,TRUE,TRUE); - Doxygen::indexList->incContentsDepth(); - } - FTVHelp* ftv = new FTVHelp(FALSE); - writeNamespaceTree(Doxygen::namespaceSDict,ftv,TRUE,TRUE,addToIndex,ClassDef::Struct); - writeClassTree(Doxygen::classSDict,ftv,addToIndex,TRUE,ClassDef::Struct); - QGString outStr; - FTextStream t(&outStr); - ftv->generateTreeViewInline(t); - ol.writeString(outStr); - delete ftv; - if (addToIndex) - { - Doxygen::indexList->decContentsDepth(); - } - } - - ol.popGeneratorState(); - // ------ - - endFile(ol); // contains ol.endContents() - ol.popGeneratorState(); } //---------------------------------------------------------------------------- static void writeAnnotatedExceptionIndex(OutputList &ol) { - //printf("writeAnnotatedExceptionIndex: count=%d printed=%d\n", - // annotatedExceptions,annotatedExceptionsPrinted); - if (annotatedExceptions==0) return; - - ol.pushGeneratorState(); - ol.disable(OutputGenerator::Man); - if (annotatedExceptionsPrinted==0) - { - ol.disable(OutputGenerator::Latex); - ol.disable(OutputGenerator::RTF); - } - LayoutNavEntry *lne = LayoutDocManager::instance().rootNavEntry()->find(LayoutNavEntry::ExceptionList); - if (lne==0) lne = LayoutDocManager::instance().rootNavEntry()->find(LayoutNavEntry::Exceptions); // fall back - QCString title = lne ? lne->title() : theTranslator->trExceptionList(); - bool addToIndex = lne==0 || lne->visible(); - - startFile(ol,"annotatedexceptions",0,title,HLI_AnnotatedExceptions); - - startTitle(ol,0); - ol.parseText(title); - endTitle(ol,0,0); - - ol.startContents(); - - ol.startTextBlock(); - ol.parseText(lne ? lne->intro() : theTranslator->trExceptionListDescription()); - ol.endTextBlock(); - - // --------------- - // Linear interface index for Latex/RTF - // --------------- - ol.pushGeneratorState(); - ol.disable(OutputGenerator::Html); - Doxygen::indexList->disable(); - - writeAnnotatedClassList(ol, ClassDef::Exception); + writeAnnotatedIndexGeneric(ol, + AnnotatedIndexContext(annotatedExceptions,annotatedExceptionsPrinted, + LayoutNavEntry::ExceptionList,LayoutNavEntry::Exceptions, + theTranslator->trExceptionList(),theTranslator->trExceptionListDescription(), + ClassDef::Exception, + "annotatedexceptions", + HLI_AnnotatedExceptions)); - Doxygen::indexList->enable(); - ol.popGeneratorState(); - - // --------------- - // Hierarchical interface index for HTML - // --------------- - ol.pushGeneratorState(); - ol.disableAllBut(OutputGenerator::Html); - - { - if (addToIndex) - { - Doxygen::indexList->addContentsItem(TRUE,title,0,"annotatedexceptions",0,TRUE,TRUE); - Doxygen::indexList->incContentsDepth(); - } - FTVHelp* ftv = new FTVHelp(FALSE); - writeNamespaceTree(Doxygen::namespaceSDict,ftv,TRUE,TRUE,addToIndex,ClassDef::Exception); - writeClassTree(Doxygen::classSDict,ftv,addToIndex,TRUE,ClassDef::Exception); - QGString outStr; - FTextStream t(&outStr); - ftv->generateTreeViewInline(t); - ol.writeString(outStr); - delete ftv; - if (addToIndex) - { - Doxygen::indexList->decContentsDepth(); - } - } - - ol.popGeneratorState(); - // ------ - - endFile(ol); // contains ol.endContents() - ol.popGeneratorState(); } //---------------------------------------------------------------------------- @@ -2777,7 +2761,7 @@ static void writeNamespaceLinkForMember(OutputList &ol,MemberDef *md,const char static void writeMemberList(OutputList &ol,bool useSections,int page, const LetterToIndexMap<MemberIndexList> &memberLists, - DefinitionIntf::DefType type) + Definition::DefType type) { int index = (int)type; ASSERT(index<3); @@ -4499,7 +4483,7 @@ static void writeIndex(OutputList &ol) { ol.startHeaderSection(); ol.startTitleHead(0); - ol.generateDoc(Doxygen::mainPage->docFile(),Doxygen::mainPage->docLine(), + ol.generateDoc(Doxygen::mainPage->docFile(),Doxygen::mainPage->getStartBodyLine(), Doxygen::mainPage,0,Doxygen::mainPage->title(),TRUE,FALSE, 0,TRUE,FALSE,Config_getBool(MARKDOWN_SUPPORT)); headerWritten = TRUE; diff --git a/src/index.h b/src/index.h index f571375..6cca60d 100644 --- a/src/index.h +++ b/src/index.h @@ -1,12 +1,12 @@ /****************************************************************************** * - * + * * * Copyright (C) 1997-2015 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. * @@ -23,6 +23,7 @@ #include <qcstring.h> class Definition; +class DefinitionMutable; class MemberDef; class OutputList; class FTextStream; @@ -36,7 +37,7 @@ class IndexIntf virtual void finalize() = 0; virtual void incContentsDepth() = 0; virtual void decContentsDepth() = 0; - virtual void addContentsItem(bool isDir, const char *name, const char *ref, + virtual void addContentsItem(bool isDir, const char *name, const char *ref, const char *file, const char *anchor, bool separateIndex, bool addToNavIndex,const Definition *def) = 0; virtual void addIndexItem(const Definition *context,const MemberDef *md, @@ -73,7 +74,7 @@ class IndexList : public IndexIntf /** Creates a list of indexes */ IndexList() { m_intfs.setAutoDelete(TRUE); m_enabled=TRUE; } /** Add an index generator to the list */ - void addIndex(IndexIntf *intf) + void addIndex(IndexIntf *intf) { m_intfs.append(intf); } void disable() { m_enabled = FALSE; } @@ -83,25 +84,25 @@ class IndexList : public IndexIntf { return m_enabled; } // IndexIntf implementation - void initialize() + void initialize() { foreach(&IndexIntf::initialize); } - void finalize() + void finalize() { foreach(&IndexIntf::finalize); } void incContentsDepth() { if (m_enabled) foreach(&IndexIntf::incContentsDepth); } void decContentsDepth() { if (m_enabled) foreach(&IndexIntf::decContentsDepth); } - void addContentsItem(bool isDir, const char *name, const char *ref, + void addContentsItem(bool isDir, const char *name, const char *ref, const char *file, const char *anchor,bool separateIndex=FALSE,bool addToNavIndex=FALSE, const Definition *def=0) { if (m_enabled) foreach(&IndexIntf::addContentsItem,isDir,name,ref,file,anchor,separateIndex,addToNavIndex,def); } void addIndexItem(const Definition *context,const MemberDef *md,const char *sectionAnchor=0,const char *title=0) { if (m_enabled) foreach(&IndexIntf::addIndexItem,context,md,sectionAnchor,title); } - void addIndexFile(const char *name) + void addIndexFile(const char *name) { if (m_enabled) foreach(&IndexIntf::addIndexFile,name); } - void addImageFile(const char *name) + void addImageFile(const char *name) { if (m_enabled) foreach(&IndexIntf::addImageFile,name); } - void addStyleSheetFile(const char *name) + void addStyleSheetFile(const char *name) { if (m_enabled) foreach(&IndexIntf::addStyleSheetFile,name); } private: @@ -244,7 +245,7 @@ extern int documentedDirs; extern int documentedHtmlFiles; extern int documentedPages; -void startTitle(OutputList &ol,const char *fileName,const Definition *def=0); +void startTitle(OutputList &ol,const char *fileName,const DefinitionMutable *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, diff --git a/src/latexdocvisitor.cpp b/src/latexdocvisitor.cpp index 19f01b0..fbb6530 100644 --- a/src/latexdocvisitor.cpp +++ b/src/latexdocvisitor.cpp @@ -175,7 +175,7 @@ QCString LatexDocVisitor::escapeMakeIndexChars(const char *s) } -LatexDocVisitor::LatexDocVisitor(FTextStream &t,CodeOutputInterface &ci, +LatexDocVisitor::LatexDocVisitor(FTextStream &t,LatexCodeGenerator &ci, const char *langExt,bool insideTabbing) : DocVisitor(DocVisitor_Latex), m_t(t), m_ci(ci), m_insidePre(FALSE), m_insideItem(FALSE), m_hide(FALSE), m_hideCaption(FALSE), m_insideTabbing(insideTabbing), @@ -351,13 +351,10 @@ void LatexDocVisitor::visit(DocVerbatim *s) { case DocVerbatim::Code: { - m_t << "\n\\begin{DoxyCode}{" << usedTableLevels() << "}\n"; - LatexCodeGenerator::setDoxyCodeOpen(TRUE); - Doxygen::parserManager->getCodeParser(lang) - .parseCode(m_ci,s->context(),s->text(),langExt, - s->isExample(),s->exampleFile()); - LatexCodeGenerator::setDoxyCodeOpen(FALSE); - m_t << "\\end{DoxyCode}\n"; + m_ci.startCodeFragment("DoxyCode"); + getCodeParser(lang).parseCode(m_ci,s->context(),s->text(),langExt, + s->isExample(),s->exampleFile()); + m_ci.endCodeFragment("DoxyCode"); } break; case DocVerbatim::Verbatim: @@ -461,44 +458,40 @@ void LatexDocVisitor::visit(DocInclude *inc) { case DocInclude::IncWithLines: { - m_t << "\n\\begin{DoxyCodeInclude}{" << usedTableLevels() << "}\n"; - LatexCodeGenerator::setDoxyCodeOpen(TRUE); - QFileInfo cfi( inc->file() ); - FileDef *fd = createFileDef( cfi.dirPath().utf8(), cfi.fileName().utf8() ); - Doxygen::parserManager->getCodeParser(inc->extension()) - .parseCode(m_ci,inc->context(), - inc->text(), - langExt, - inc->isExample(), - inc->exampleFile(), - fd, // fileDef, - -1, // start line - -1, // end line - FALSE, // inline fragment - 0, // memberDef - TRUE // show line numbers - ); - delete fd; - LatexCodeGenerator::setDoxyCodeOpen(FALSE); - m_t << "\\end{DoxyCodeInclude}" << endl; + m_ci.startCodeFragment("DoxyCodeInclude"); + QFileInfo cfi( inc->file() ); + FileDef *fd = createFileDef( cfi.dirPath().utf8(), cfi.fileName().utf8() ); + getCodeParser(inc->extension()).parseCode(m_ci,inc->context(), + inc->text(), + langExt, + inc->isExample(), + inc->exampleFile(), + fd, // fileDef, + -1, // start line + -1, // end line + FALSE, // inline fragment + 0, // memberDef + TRUE // show line numbers + ); + delete fd; + m_ci.endCodeFragment("DoxyCodeInclude"); } break; case DocInclude::Include: - m_t << "\n\\begin{DoxyCodeInclude}{" << usedTableLevels() << "}\n"; - LatexCodeGenerator::setDoxyCodeOpen(TRUE); - Doxygen::parserManager->getCodeParser(inc->extension()) - .parseCode(m_ci,inc->context(), - inc->text(),langExt,inc->isExample(), - inc->exampleFile(), - 0, // fileDef - -1, // startLine - -1, // endLine - TRUE, // inlineFragment - 0, // memberDef - FALSE - ); - LatexCodeGenerator::setDoxyCodeOpen(FALSE); - m_t << "\\end{DoxyCodeInclude}\n"; + { + m_ci.startCodeFragment("DoxyCodeInclude"); + getCodeParser(inc->extension()).parseCode(m_ci,inc->context(), + inc->text(),langExt,inc->isExample(), + inc->exampleFile(), + 0, // fileDef + -1, // startLine + -1, // endLine + TRUE, // inlineFragment + 0, // memberDef + FALSE + ); + m_ci.endCodeFragment("DoxyCodeInclude"); + } break; case DocInclude::DontInclude: case DocInclude::DontIncWithLines: @@ -518,43 +511,37 @@ void LatexDocVisitor::visit(DocInclude *inc) break; case DocInclude::Snippet: { - m_t << "\n\\begin{DoxyCodeInclude}{" << usedTableLevels() << "}\n"; - LatexCodeGenerator::setDoxyCodeOpen(TRUE); - Doxygen::parserManager->getCodeParser(inc->extension()) - .parseCode(m_ci, - inc->context(), - extractBlock(inc->text(),inc->blockId()), - langExt, - inc->isExample(), - inc->exampleFile() - ); - LatexCodeGenerator::setDoxyCodeOpen(FALSE); - m_t << "\\end{DoxyCodeInclude}" << endl; + m_ci.startCodeFragment("DoxyCodeInclude"); + getCodeParser(inc->extension()).parseCode(m_ci, + inc->context(), + extractBlock(inc->text(),inc->blockId()), + langExt, + inc->isExample(), + inc->exampleFile() + ); + m_ci.endCodeFragment("DoxyCodeInclude"); } break; case DocInclude::SnipWithLines: { - QFileInfo cfi( inc->file() ); - FileDef *fd = createFileDef( cfi.dirPath().utf8(), cfi.fileName().utf8() ); - m_t << "\n\\begin{DoxyCodeInclude}{" << usedTableLevels() << "}\n"; - LatexCodeGenerator::setDoxyCodeOpen(TRUE); - Doxygen::parserManager->getCodeParser(inc->extension()) - .parseCode(m_ci, - inc->context(), - extractBlock(inc->text(),inc->blockId()), - langExt, - inc->isExample(), - inc->exampleFile(), - fd, - lineBlock(inc->text(),inc->blockId()), - -1, // endLine - FALSE, // inlineFragment - 0, // memberDef - TRUE // show line number - ); - delete fd; - LatexCodeGenerator::setDoxyCodeOpen(FALSE); - m_t << "\\end{DoxyCodeInclude}" << endl; + QFileInfo cfi( inc->file() ); + FileDef *fd = createFileDef( cfi.dirPath().utf8(), cfi.fileName().utf8() ); + m_ci.startCodeFragment("DoxyCodeInclude"); + getCodeParser(inc->extension()).parseCode(m_ci, + inc->context(), + extractBlock(inc->text(),inc->blockId()), + langExt, + inc->isExample(), + inc->exampleFile(), + fd, + lineBlock(inc->text(),inc->blockId()), + -1, // endLine + FALSE, // inlineFragment + 0, // memberDef + TRUE // show line number + ); + delete fd; + m_ci.endCodeFragment("DoxyCodeInclude"); } break; case DocInclude::SnippetDoc: @@ -571,8 +558,7 @@ void LatexDocVisitor::visit(DocIncOperator *op) // op->type(),op->isFirst(),op->isLast(),op->text().data()); if (op->isFirst()) { - if (!m_hide) m_t << "\n\\begin{DoxyCodeInclude}{" << usedTableLevels() << "}\n"; - LatexCodeGenerator::setDoxyCodeOpen(TRUE); + if (!m_hide) m_ci.startCodeFragment("DoxyCodeInclude"); pushEnabled(); m_hide = TRUE; } @@ -591,16 +577,15 @@ void LatexDocVisitor::visit(DocIncOperator *op) fd = createFileDef( cfi.dirPath().utf8(), cfi.fileName().utf8() ); } - Doxygen::parserManager->getCodeParser(locLangExt) - .parseCode(m_ci,op->context(),op->text(),langExt, - op->isExample(),op->exampleFile(), - fd, // fileDef - op->line(), // startLine - -1, // endLine - FALSE, // inline fragment - 0, // memberDef - op->showLineNo() // show line numbers - ); + getCodeParser(locLangExt).parseCode(m_ci,op->context(),op->text(),langExt, + op->isExample(),op->exampleFile(), + fd, // fileDef + op->line(), // startLine + -1, // endLine + FALSE, // inline fragment + 0, // memberDef + op->showLineNo() // show line numbers + ); if (fd) delete fd; } pushEnabled(); @@ -609,8 +594,7 @@ void LatexDocVisitor::visit(DocIncOperator *op) if (op->isLast()) { popEnabled(); - LatexCodeGenerator::setDoxyCodeOpen(FALSE); - if (!m_hide) m_t << "\n\\end{DoxyCodeInclude}\n"; + if (!m_hide) m_ci.endCodeFragment("DoxyCodeInclude"); } else { @@ -1504,7 +1488,7 @@ void LatexDocVisitor::visitPre(DocParamSect *s) if (m_hide) return; bool hasInOutSpecs = s->hasInOutSpecifier(); bool hasTypeSpecs = s->hasTypeSpecifier(); - incUsedTableLevels(); + m_ci.incUsedTableLevel(); switch(s->type()) { case DocParamSect::Param: @@ -1535,7 +1519,7 @@ void LatexDocVisitor::visitPre(DocParamSect *s) void LatexDocVisitor::visitPost(DocParamSect *s) { if (m_hide) return; - decUsedTableLevels(); + m_ci.decUsedTableLevel(); switch(s->type()) { case DocParamSect::Param: @@ -1754,7 +1738,13 @@ void LatexDocVisitor::visitPost(DocParBlock *) void LatexDocVisitor::filter(const char *str) { - filterLatexString(m_t,str,m_insideTabbing,m_insidePre,m_insideItem); + filterLatexString(m_t,str, + m_insideTabbing, + m_insidePre, + m_insideItem, + m_ci.usedTableLevel()>0, // insideTable + false // keepSpaces + ); } void LatexDocVisitor::startLink(const QCString &ref,const QCString &file,const QCString &anchor,bool refToTable) diff --git a/src/latexdocvisitor.h b/src/latexdocvisitor.h index 71fb5be..003d780 100644 --- a/src/latexdocvisitor.h +++ b/src/latexdocvisitor.h @@ -1,13 +1,13 @@ /****************************************************************************** * - * + * * * * Copyright (C) 1997-2015 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. * @@ -25,19 +25,19 @@ #include <qlist.h> class FTextStream; -class CodeOutputInterface; +class LatexCodeGenerator; /*! @brief Concrete visitor implementation for LaTeX output. */ class LatexDocVisitor : public DocVisitor { public: - LatexDocVisitor(FTextStream &t,CodeOutputInterface &ci, + LatexDocVisitor(FTextStream &t,LatexCodeGenerator &ci, const char *langExt,bool insideTabbing); - + //-------------------------------------- // visitor functions for leaf nodes //-------------------------------------- - + void visit(DocWord *); void visit(DocLinkedWord *); void visit(DocWhiteSpace *); @@ -59,7 +59,7 @@ class LatexDocVisitor : public DocVisitor //-------------------------------------- // visitor functions for compound nodes //-------------------------------------- - + void visitPre(DocAutoList *); void visitPost(DocAutoList *); void visitPre(DocAutoListItem *); @@ -141,7 +141,7 @@ class LatexDocVisitor : public DocVisitor struct ActiveRowSpan { - ActiveRowSpan(DocHtmlCell *c,int rs,int cs,int col) + ActiveRowSpan(DocHtmlCell *c,int rs,int cs,int col) : cell(c), rowSpan(rs), colSpan(cs), column(col) {} DocHtmlCell *cell; int rowSpan; @@ -152,9 +152,9 @@ class LatexDocVisitor : public DocVisitor typedef QList<ActiveRowSpan> RowSpanList; //-------------------------------------- - // helper functions + // helper functions //-------------------------------------- - + void filter(const char *str); void startLink(const QCString &ref,const QCString &file, const QCString &anchor,bool refToTable=FALSE); @@ -184,7 +184,7 @@ class LatexDocVisitor : public DocVisitor //-------------------------------------- FTextStream &m_t; - CodeOutputInterface &m_ci; + LatexCodeGenerator &m_ci; bool m_insidePre; bool m_insideItem; bool m_hide; @@ -195,7 +195,7 @@ class LatexDocVisitor : public DocVisitor struct TableState { - TableState() : numCols(0), currentColumn(0), inRowSpan(FALSE), + TableState() : numCols(0), currentColumn(0), inRowSpan(FALSE), inColSpan(FALSE), firstRow(FALSE) { rowSpans.setAutoDelete(TRUE); } RowSpanList rowSpans; diff --git a/src/latexgen.cpp b/src/latexgen.cpp index b70f82a..3f4435f 100644 --- a/src/latexgen.cpp +++ b/src/latexgen.cpp @@ -44,18 +44,14 @@ #include "resourcemgr.h" #include "portable.h" -static bool DoxyCodeOpen = FALSE; -static bool DoxyCodeLineOpen = FALSE; -//------------------------------- - LatexCodeGenerator::LatexCodeGenerator(FTextStream &t,const QCString &relPath,const QCString &sourceFileName) - : m_relPath(relPath), m_sourceFileName(sourceFileName), m_col(0) + : m_relPath(relPath), m_sourceFileName(sourceFileName) { m_prettyCode=Config_getBool(LATEX_SOURCE_CODE); setTextStream(t); } -LatexCodeGenerator::LatexCodeGenerator() : m_streamSet(FALSE), m_col(0) +LatexCodeGenerator::LatexCodeGenerator() { m_prettyCode=Config_getBool(LATEX_SOURCE_CODE); } @@ -85,8 +81,8 @@ void LatexCodeGenerator::codify(const char *str) //char cs[5]; int spacesToNextTabStop; int tabSize = Config_getInt(TAB_SIZE); - static signed char *result = NULL; - static int lresult = 0; + static THREAD_LOCAL signed char *result = NULL; + static THREAD_LOCAL int lresult = 0; int i; while ((c=*p)) { @@ -108,7 +104,9 @@ void LatexCodeGenerator::codify(const char *str) m_col+=spacesToNextTabStop; p++; break; - case '\n': (usedTableLevels()>0 && !DoxyCodeOpen) ? m_t << "\\newline\n" : m_t << '\n'; m_col=0; p++; + case '\n': m_t << '\n'; + m_col=0; + p++; break; default: i=0; @@ -149,14 +147,13 @@ void LatexCodeGenerator::codify(const char *str) COPYCHAR(); } result[i]=0; // add terminator - //if (m_prettyCode) - //{ - filterLatexString(m_t,(const char *)result,FALSE,TRUE); - //} - //else - //{ - // t << result; - //} + filterLatexString(m_t,(const char *)result, + false, // insideTabbing + true, // insidePre + false, // insideItem + m_usedTableLevel>0, // insideTable + false // keepSpaces + ); break; } } @@ -192,10 +189,10 @@ void LatexCodeGenerator::writeLineNumber(const char *ref,const char *fileName,co { bool usePDFLatex = Config_getBool(USE_PDFLATEX); bool pdfHyperlinks = Config_getBool(PDF_HYPERLINKS); - if (!DoxyCodeLineOpen) + if (!m_doxyCodeLineOpen) { m_t << "\\DoxyCodeLine{"; - DoxyCodeLineOpen = TRUE; + m_doxyCodeLineOpen = TRUE; } if (m_prettyCode) { @@ -231,19 +228,19 @@ void LatexCodeGenerator::writeLineNumber(const char *ref,const char *fileName,co void LatexCodeGenerator::startCodeLine(bool) { m_col=0; - if (!DoxyCodeLineOpen) + if (!m_doxyCodeLineOpen) { m_t << "\\DoxyCodeLine{"; - DoxyCodeLineOpen = TRUE; + m_doxyCodeLineOpen = TRUE; } } void LatexCodeGenerator::endCodeLine() { - if (DoxyCodeLineOpen) + if (m_doxyCodeLineOpen) { m_t << "}"; - DoxyCodeLineOpen = FALSE; + m_doxyCodeLineOpen = FALSE; } codify("\n"); } @@ -258,11 +255,20 @@ void LatexCodeGenerator::endFontClass() m_t << "}"; } -void LatexCodeGenerator::setDoxyCodeOpen(bool val) +void LatexCodeGenerator::startCodeFragment(const char *style) +{ + m_t << "\n\\begin{" << style << "}{" << m_usedTableLevel << "}\n"; +} + +void LatexCodeGenerator::endCodeFragment(const char *style) { - DoxyCodeOpen = val; + //endCodeLine checks is there is still an open code line, if so closes it. + endCodeLine(); + + m_t << "\\end{" << style << "}\n"; } + //------------------------------- LatexGenerator::LatexGenerator() : OutputGenerator(Config_getString(LATEX_OUTPUT)) @@ -515,7 +521,6 @@ static void writeDefaultHeaderPart1(FTextStream &t) // Load required packages t << "% Packages required by doxygen\n" "\\usepackage{fixltx2e}\n" // for \textsubscript - "\\usepackage{calc}\n" "\\usepackage{doxygen}\n"; const StringVector &extraLatexStyles = Config_getList(LATEX_EXTRA_STYLESHEET); for (const auto &extraStyle : extraLatexStyles) @@ -541,13 +546,10 @@ static void writeDefaultHeaderPart1(FTextStream &t) t << "\\usepackage{graphicx}\n" "\\usepackage[utf8]{inputenc}\n" "\\usepackage{makeidx}\n" - "\\usepackage{multicol}\n" - "\\usepackage{multirow}\n" "\\PassOptionsToPackage{warn}{textcomp}\n" "\\usepackage{textcomp}\n" "\\usepackage[nointegrals]{wasysym}\n" - "\\usepackage[table]{xcolor}\n" - "\\usepackage{ifpdf,ifxetex}\n" + "\\usepackage{ifxetex}\n" "\n"; // Language support @@ -571,8 +573,7 @@ static void writeDefaultHeaderPart1(FTextStream &t) { t << font; } - t << "\\usepackage{amssymb}\n" - "\\usepackage{sectsty}\n" + t << "\\usepackage{sectsty}\n" "\\allsectionsfont{%\n" " \\fontseries{bc}\\selectfont%\n" " \\color{darkgray}%\n" @@ -650,23 +651,34 @@ static void writeDefaultHeaderPart1(FTextStream &t) { generatedBy = theTranslator->trGeneratedBy(); } - filterLatexString(tg, generatedBy, FALSE,FALSE,FALSE); + filterLatexString(tg, generatedBy, + false, // insideTabbing + false, // insidePre + false, // insideItem + false, // insideTable + false // keepSpaces + ); t << "% Headers & footers\n" "\\usepackage{fancyhdr}\n" "\\pagestyle{fancyplain}\n" - "\\fancyhead[LE]{\\fancyplain{}{\\bfseries\\thepage}}\n" - "\\fancyhead[CE]{\\fancyplain{}{}}\n" - "\\fancyhead[RE]{\\fancyplain{}{\\bfseries\\leftmark}}\n" - "\\fancyhead[LO]{\\fancyplain{}{\\bfseries\\rightmark}}\n" - "\\fancyhead[CO]{\\fancyplain{}{}}\n" - "\\fancyhead[RO]{\\fancyplain{}{\\bfseries\\thepage}}\n" - "\\fancyfoot[LE]{\\fancyplain{}{}}\n" - "\\fancyfoot[CE]{\\fancyplain{}{}}\n" - "\\fancyfoot[RE]{\\fancyplain{}{\\bfseries\\scriptsize " << genString << " Doxygen }}\n" - "\\fancyfoot[LO]{\\fancyplain{}{\\bfseries\\scriptsize " << genString << " Doxygen }}\n" - "\\fancyfoot[CO]{\\fancyplain{}{}}\n" - "\\fancyfoot[RO]{\\fancyplain{}{}}\n" - "\\renewcommand{\\footrulewidth}{0.4pt}\n"; + "\\renewcommand{\\footrulewidth}{0.4pt}\n" + "%\n" + "\\fancypagestyle{fancyplain}{\n" + "\\fancyhf{}\n" + "\\fancyhead[LE, RO]{\\bfseries\\thepage}\n" + "\\fancyhead[LO]{\\bfseries\\rightmark}\n" + "\\fancyhead[RE]{\\bfseries\\leftmark}\n" + "\\fancyfoot[LO, RE]{\\bfseries\\scriptsize " << genString << " Doxygen }\n" + "}\n" + "%\n" + "\\fancypagestyle{plain}{\n" + "\\fancyhf{}\n" + "\\fancyfoot[LO, RE]{\\bfseries\\scriptsize " << genString << " Doxygen }\n" + "\\renewcommand{\\headrulewidth}{0pt}}\n" + "%\n" + "\\pagestyle{fancyplain}\n" + "%\n"; + if (!Config_getBool(COMPACT_LATEX)) { t << "\\renewcommand{\\chaptermark}[1]{%\n" @@ -757,7 +769,8 @@ static void writeDefaultHeaderPart1(FTextStream &t) // End of preamble, now comes the document contents t << "%===== C O N T E N T S =====\n" "\n" - "\\begin{document}\n"; + "\\begin{document}\n" + "\\raggedbottom\n"; QCString documentPre = theTranslator->latexDocumentPre(); if (!documentPre.isEmpty()) { @@ -889,7 +902,7 @@ void LatexGenerator::writeStyleSheetFile(QFile &f) writeDefaultStyleSheet(t); } -void LatexGenerator::startFile(const char *name,const char *,const char *) +void LatexGenerator::startFile(const char *name,const char *,const char *,int) { #if 0 setEncoding(Config_getString(LATEX_OUTPUT_ENCODING)); @@ -1022,7 +1035,7 @@ void LatexGenerator::startIndexSection(IndexSections is) bool found=FALSE; for (nli.toFirst();(nd=nli.current()) && !found;++nli) { - if (nd->isLinkableInProject()) + if (nd->isLinkableInProject() && !nd->isAlias()) { if (compactLatex) t << "\\doxysection"; else t << "\\chapter"; t << "{"; // Namespace Documentation}\n": @@ -1040,7 +1053,8 @@ void LatexGenerator::startIndexSection(IndexSections is) { if (cd->isLinkableInProject() && cd->templateMaster()==0 && - !cd->isEmbeddedInOuterScope() + !cd->isEmbeddedInOuterScope() && + !cd->isAlias() ) { if (compactLatex) t << "\\doxysection"; else t << "\\chapter"; @@ -1191,7 +1205,7 @@ void LatexGenerator::endIndexSection(IndexSections is) bool found=FALSE; for (nli.toFirst();(nd=nli.current()) && !found;++nli) { - if (nd->isLinkableInProject()) + if (nd->isLinkableInProject() && !nd->isAlias()) { t << "}\n\\input{" << nd->getOutputFileBase() << "}\n"; found=TRUE; @@ -1218,7 +1232,8 @@ void LatexGenerator::endIndexSection(IndexSections is) { if (cd->isLinkableInProject() && cd->templateMaster()==0 && - !cd->isEmbeddedInOuterScope() + !cd->isEmbeddedInOuterScope() && + !cd->isAlias() ) { t << "}\n\\input{" << cd->getOutputFileBase() << "}\n"; @@ -1229,7 +1244,8 @@ void LatexGenerator::endIndexSection(IndexSections is) { if (cd->isLinkableInProject() && cd->templateMaster()==0 && - !cd->isEmbeddedInOuterScope() + !cd->isEmbeddedInOuterScope() && + !cd->isAlias() ) { //if (compactLatex) t << "\\input"; else t << "\\include"; @@ -1823,7 +1839,13 @@ void LatexGenerator::endSection(const char *lab,SectionType) void LatexGenerator::docify(const char *str) { - filterLatexString(t,str,m_insideTabbing,FALSE,FALSE); + filterLatexString(t,str, + m_insideTabbing, // insideTabbing + false, // insidePre + false, // insideItem + m_codeGen.usedTableLevel()>0, // insideTable + false // keepSpaces + ); } void LatexGenerator::writeChar(char c) @@ -1960,13 +1982,13 @@ void LatexGenerator::writeNonBreakableSpace(int) void LatexGenerator::startDescTable(const char *title) { - incUsedTableLevels(); + m_codeGen.incUsedTableLevel(); t << "\\begin{DoxyEnumFields}{" << title << "}" << endl; } void LatexGenerator::endDescTable() { - decUsedTableLevels(); + m_codeGen.decUsedTableLevel(); t << "\\end{DoxyEnumFields}" << endl; } @@ -2211,10 +2233,10 @@ void LatexGenerator::exceptionEntry(const char* prefix,bool closeBracket) t << " "; } -void LatexGenerator::writeDoc(DocNode *n,const Definition *ctx,const MemberDef *) +void LatexGenerator::writeDoc(DocNode *n,const Definition *ctx,const MemberDef *,int) { LatexDocVisitor *visitor = - new LatexDocVisitor(t,*this,ctx?ctx->getDefFileExtension():QCString(""),m_insideTabbing); + new LatexDocVisitor(t,m_codeGen,ctx?ctx->getDefFileExtension():QCString(""),m_insideTabbing); n->accept(visitor); delete visitor; } @@ -2260,21 +2282,6 @@ void LatexGenerator::endConstraintList() t << "\\end{Desc}" << endl; } -void LatexGenerator::startCodeFragment() -{ - t << "\n\\begin{DoxyCode}{" << usedTableLevels() << "}\n"; - DoxyCodeOpen = TRUE; -} - -void LatexGenerator::endCodeFragment() -{ - //endCodeLine checks is there is still an open code line, if so closes it. - endCodeLine(); - - t << "\\end{DoxyCode}\n"; - DoxyCodeOpen = FALSE; -} - void LatexGenerator::startInlineHeader() { if (Config_getBool(COMPACT_LATEX)) @@ -2306,7 +2313,7 @@ void LatexGenerator::lineBreak(const char *) void LatexGenerator::startMemberDocSimple(bool isEnum) { - incUsedTableLevels(); + m_codeGen.incUsedTableLevel(); if (isEnum) { t << "\\begin{DoxyEnumFields}{"; @@ -2322,7 +2329,7 @@ void LatexGenerator::startMemberDocSimple(bool isEnum) void LatexGenerator::endMemberDocSimple(bool isEnum) { - decUsedTableLevels(); + m_codeGen.decUsedTableLevel(); if (isEnum) { t << "\\end{DoxyEnumFields}" << endl; diff --git a/src/latexgen.h b/src/latexgen.h index 12b34d8..6be5de7 100644 --- a/src/latexgen.h +++ b/src/latexgen.h @@ -52,7 +52,13 @@ class LatexCodeGenerator : public CodeOutputInterface void writeCodeAnchor(const char *) {} void setCurrentDoc(const Definition *,const char *,bool) {} void addWord(const char *,bool) {} - static void setDoxyCodeOpen(bool val); + void startCodeFragment(const char *style); + void endCodeFragment(const char *style); + + // extra methods not part of CodeOutputInterface + void incUsedTableLevel() { m_usedTableLevel++; } + void decUsedTableLevel() { m_usedTableLevel--; } + int usedTableLevel() const { return m_usedTableLevel; } private: void _writeCodeLink(const char *className, @@ -60,12 +66,14 @@ class LatexCodeGenerator : public CodeOutputInterface const char *anchor,const char *name, const char *tooltip); void docify(const char *str); - bool m_streamSet; + bool m_streamSet = false; FTextStream m_t; QCString m_relPath; QCString m_sourceFileName; - int m_col; - bool m_prettyCode; + int m_col = 0; + bool m_prettyCode = false; + bool m_doxyCodeLineOpen = false; + int m_usedTableLevel = 0; }; /** Generator for LaTeX output. */ @@ -108,12 +116,16 @@ class LatexGenerator : public OutputGenerator { m_codeGen.endFontClass(); } void writeCodeAnchor(const char *anchor) { m_codeGen.writeCodeAnchor(anchor); } + void startCodeFragment(const char *style) + { m_codeGen.startCodeFragment(style); } + void endCodeFragment(const char *style) + { m_codeGen.endCodeFragment(style); } // --------------------------- - void writeDoc(DocNode *,const Definition *ctx,const MemberDef *); + void writeDoc(DocNode *,const Definition *ctx,const MemberDef *,int id); - void startFile(const char *name,const char *manName,const char *title); + void startFile(const char *name,const char *manName,const char *title,int id); void writeSearchInfo() {} void writeFooter(const char *) {} void endFile(); @@ -194,8 +206,6 @@ class LatexGenerator : public OutputGenerator void writeRuler() { t << endl << endl; } void writeAnchor(const char *fileName,const char *name); - void startCodeFragment(); - void endCodeFragment(); void startEmphasis() { t << "{\\em "; } void endEmphasis() { t << "}"; } void startBold() { t << "{\\bfseries "; } diff --git a/src/linkedmap.h b/src/linkedmap.h index 84dcf26..9ca0fa2 100644 --- a/src/linkedmap.h +++ b/src/linkedmap.h @@ -21,26 +21,30 @@ #include <memory> #include <string> #include <algorithm> +#include <cctype> -//! @brief Container class representing a vector of objects with unique keys. +//! @brief Container class representing a vector of objects with keys. //! @details Objects can efficiently be looked up given the key. //! Objects are owned by the container. //! When adding objects the order of addition is kept, and used while iterating. -template<class T> +template<class T, class Hash = std::hash<std::string>, + class KeyEqual = std::equal_to<std::string>, + class Map = std::unordered_map<std::string,T*,Hash,KeyEqual > > class LinkedMap { public: using Ptr = std::unique_ptr<T>; using Vec = std::vector<Ptr>; - using Map = std::unordered_map<std::string,T*>; using iterator = typename Vec::iterator; using const_iterator = typename Vec::const_iterator; + using reverse_iterator = typename Vec::reverse_iterator; + using const_reverse_iterator = typename Vec::const_reverse_iterator; //! Find an object given the key. //! Returns a pointer to the element if found or nullptr if it is not found. - const T *find(const char *k) const + const T *find(const char *key_) const { - std::string key = k ? std::string(k) : std::string(); + std::string key(key_ ? key_ : ""); auto it = m_lookup.find(key); return it!=m_lookup.end() ? it->second : nullptr; } @@ -51,7 +55,7 @@ class LinkedMap return const_cast<T*>(static_cast<const LinkedMap&>(*this).find(key)); } - //! Adds a new object to the ordered set if it was not added already. + //! Adds a new object to the ordered vector if it was not added already. //! Return a non-owning pointer to the newly added object, or to the existing object if //! it was already inserted before under the given key. template<class...Args> @@ -60,8 +64,8 @@ class LinkedMap T *result = find(k); if (result==nullptr) { - std::string key = k ? std::string(k) : std::string(); - Ptr ptr = std::make_unique<T>(k,std::forward<Args>(args)...); + std::string key(k ? k : ""); + Ptr ptr = std::make_unique<T>(key.c_str(),std::forward<Args>(args)...); result = ptr.get(); m_lookup.insert({key,result}); m_entries.push_back(std::move(ptr)); @@ -69,11 +73,29 @@ class LinkedMap return result; } + //! Prepends a new object to the ordered vector if it was not added already. + //! Return a non-owning pointer to the newly added object, or to the existing object if + //! it was already inserted before under the given key. + template<class...Args> + T *prepend(const char *k, Args&&... args) + { + T *result = find(k); + if (result==nullptr) + { + std::string key(k ? k : ""); + Ptr ptr = std::make_unique<T>(key.c_str(),std::forward<Args>(args)...); + result = ptr.get(); + m_lookup.insert({key,result}); + m_entries.push_front(std::move(ptr)); + } + return result; + } + //! Removes an object from the container and deletes it. - //! Returns true if the object was delete or false it is was not found. - bool del(const char *k) + //! Returns true if the object was deleted or false it is was not found. + bool del(const char *key_) { - std::string key = k ? std::string(k) : std::string(); + std::string key(key_ ? key_ : ""); auto it = m_lookup.find(key); if (it!=m_lookup.end()) { @@ -88,12 +110,16 @@ class LinkedMap return false; } - iterator begin() { return m_entries.begin(); } - iterator end() { return m_entries.end(); } - const_iterator begin() const { return m_entries.cbegin(); } - const_iterator end() const { return m_entries.cend(); } - bool empty() const { return m_entries.empty(); } - size_t size() const { return m_entries.size(); } + iterator begin() { return m_entries.begin(); } + iterator end() { return m_entries.end(); } + const_iterator begin() const { return m_entries.cbegin(); } + const_iterator end() const { return m_entries.cend(); } + reverse_iterator rbegin() { return m_entries.rbegin(); } + reverse_iterator rend() { return m_entries.rend(); } + const_reverse_iterator rbegin() const { return m_entries.crbegin(); } + const_reverse_iterator rend() const { return m_entries.crend(); } + bool empty() const { return m_entries.empty(); } + size_t size() const { return m_entries.size(); } void clear() { @@ -102,30 +128,33 @@ class LinkedMap } private: + Map m_lookup; Vec m_entries; }; -#if 0 // not yet used -//! @brief Container class representing a vector of objects with unique keys. +//! @brief Container class representing a vector of objects with keys. //! @details Objects can be efficiently be looked up given the key. //! Objects are \e not owned by the container, the container will only hold references. //! When adding objects the order of addition is kept, and used while iterating. -template<class T> +template<class T, class Hash = std::hash<std::string>, + class KeyEqual = std::equal_to<std::string>, + class Map = std::unordered_map<std::string,T*,Hash,KeyEqual > > class LinkedRefMap { public: using Ptr = T*; using Vec = std::vector<Ptr>; - using Map = std::unordered_map<std::string,T*>; using iterator = typename Vec::iterator; using const_iterator = typename Vec::const_iterator; + using reverse_iterator = typename Vec::reverse_iterator; + using const_reverse_iterator = typename Vec::const_reverse_iterator; //! find an object given the key. //! Returns a pointer to the object if found or nullptr if it is not found. - const T *find(const char *k) const + const T *find(const char *key_) const { - std::string key = k ? std::string(k) : std::string(); + std::string key(key_ ? key_ : ""); auto it = m_lookup.find(key); return it!=m_lookup.end() ? it->second : nullptr; } @@ -136,14 +165,14 @@ class LinkedRefMap return const_cast<T*>(static_cast<const LinkedRefMap&>(*this).find(key)); } - //! Adds a new object to the ordered set if it was not added already. - //! Return true if the object was added, and false if an object with the same key + //! Adds an object reference to the ordered vector if it was not added already. + //! Return true if the reference was added, and false if an object with the same key //! was already added before bool add(const char *k, T* obj) { if (find(k)==nullptr) // new element { - std::string key = k ? std::string(k) : std::string(); + std::string key(k ? k : ""); m_lookup.insert({key,obj}); m_entries.push_back(obj); return true; @@ -154,12 +183,53 @@ class LinkedRefMap } } - iterator begin() { return m_entries.begin(); } - iterator end() { return m_entries.end(); } - const_iterator begin() const { return m_entries.cbegin(); } - const_iterator end() const { return m_entries.cend(); } - bool empty() const { return m_entries.empty(); } - size_t size() const { return m_entries.size(); } + //! Prepends an object reference to the ordered vector if it was not added already. + //! Return true if the reference was added, and false if an object with the same key + //! was already added before + bool prepend(const char *k, T* obj) + { + if (find(k)==nullptr) // new element + { + std::string key(k ? k : ""); + m_lookup.insert({key,obj}); + m_entries.insert(m_entries.begin(),obj); + return true; + } + else // already existing, don't add + { + return false; + } + } + + //! Removes an object from the container and deletes it. + //! Returns true if the object was deleted or false it is was not found. + bool del(const char *key_) + { + std::string key(key_ ? key_ : ""); + auto it = m_lookup.find(key); + if (it!=m_lookup.end()) + { + auto vecit = std::find_if(m_entries.begin(),m_entries.end(),[obj=it->second](auto &el) { return el.get()==obj; }); + if (vecit!=m_entries.end()) // should always be true + { + m_entries.erase(vecit); + m_lookup.erase(it); + return true; + } + } + return false; + } + + iterator begin() { return m_entries.begin(); } + iterator end() { return m_entries.end(); } + const_iterator begin() const { return m_entries.cbegin(); } + const_iterator end() const { return m_entries.cend(); } + reverse_iterator rbegin() { return m_entries.rbegin(); } + reverse_iterator rend() { return m_entries.rend(); } + const_reverse_iterator rbegin() const { return m_entries.crbegin(); } + const_reverse_iterator rend() const { return m_entries.crend(); } + bool empty() const { return m_entries.empty(); } + size_t size() const { return m_entries.size(); } void clear() { @@ -171,7 +241,6 @@ class LinkedRefMap Map m_lookup; Vec m_entries; }; -#endif #endif diff --git a/src/mandocvisitor.cpp b/src/mandocvisitor.cpp index fef857e..875cd14 100644 --- a/src/mandocvisitor.cpp +++ b/src/mandocvisitor.cpp @@ -1,13 +1,10 @@ /****************************************************************************** * - * - * - * - * Copyright (C) 1997-2015 by Dimitri van Heesch. + * Copyright (C) 1997-2020 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,7 +13,7 @@ * */ -#include <qfileinfo.h> +#include <qfileinfo.h> #include "mandocvisitor.h" #include "docparser.h" @@ -33,7 +30,7 @@ #include "emoji.h" ManDocVisitor::ManDocVisitor(FTextStream &t,CodeOutputInterface &ci, - const char *langExt) + const char *langExt) : DocVisitor(DocVisitor_Man), m_t(t), m_ci(ci), m_insidePre(FALSE), m_hide(FALSE), m_firstCol(FALSE), m_indent(0), m_langExt(langExt) { @@ -205,8 +202,7 @@ void ManDocVisitor::visit(DocVerbatim *s) if (!m_firstCol) m_t << endl; m_t << ".PP" << endl; m_t << ".nf" << endl; - Doxygen::parserManager->getCodeParser(lang) - .parseCode(m_ci,s->context(),s->text(), + getCodeParser(lang).parseCode(m_ci,s->context(),s->text(), langExt, s->isExample(),s->exampleFile()); if (!m_firstCol) m_t << endl; @@ -214,7 +210,7 @@ void ManDocVisitor::visit(DocVerbatim *s) m_t << ".PP" << endl; m_firstCol=TRUE; break; - case DocVerbatim::Verbatim: + case DocVerbatim::Verbatim: if (!m_firstCol) m_t << endl; m_t << ".PP" << endl; m_t << ".nf" << endl; @@ -224,18 +220,18 @@ void ManDocVisitor::visit(DocVerbatim *s) m_t << ".PP" << endl; m_firstCol=TRUE; break; - case DocVerbatim::ManOnly: - m_t << s->text(); + case DocVerbatim::ManOnly: + m_t << s->text(); break; - case DocVerbatim::HtmlOnly: - case DocVerbatim::XmlOnly: - case DocVerbatim::LatexOnly: + case DocVerbatim::HtmlOnly: + case DocVerbatim::XmlOnly: + case DocVerbatim::LatexOnly: case DocVerbatim::RtfOnly: case DocVerbatim::DocbookOnly: - case DocVerbatim::Dot: - case DocVerbatim::Msc: - case DocVerbatim::PlantUML: - /* nothing */ + case DocVerbatim::Dot: + case DocVerbatim::Msc: + case DocVerbatim::PlantUML: + /* nothing */ break; } } @@ -252,14 +248,13 @@ void ManDocVisitor::visit(DocInclude *inc) switch(inc->type()) { case DocInclude::IncWithLines: - { + { if (!m_firstCol) m_t << endl; m_t << ".PP" << endl; m_t << ".nf" << endl; QFileInfo cfi( inc->file() ); FileDef *fd = createFileDef( cfi.dirPath().utf8(), cfi.fileName().utf8() ); - Doxygen::parserManager->getCodeParser(inc->extension()) - .parseCode(m_ci,inc->context(), + getCodeParser(inc->extension()).parseCode(m_ci,inc->context(), inc->text(), langExt, inc->isExample(), @@ -278,12 +273,11 @@ void ManDocVisitor::visit(DocInclude *inc) m_firstCol=TRUE; } break; - case DocInclude::Include: + case DocInclude::Include: if (!m_firstCol) m_t << endl; m_t << ".PP" << endl; m_t << ".nf" << endl; - Doxygen::parserManager->getCodeParser(inc->extension()) - .parseCode(m_ci,inc->context(), + getCodeParser(inc->extension()).parseCode(m_ci,inc->context(), inc->text(), langExt, inc->isExample(), @@ -311,7 +305,7 @@ void ManDocVisitor::visit(DocInclude *inc) case DocInclude::ManInclude: m_t << inc->text(); break; - case DocInclude::VerbInclude: + case DocInclude::VerbInclude: if (!m_firstCol) m_t << endl; m_t << ".PP" << endl; m_t << ".nf" << endl; @@ -325,8 +319,7 @@ void ManDocVisitor::visit(DocInclude *inc) if (!m_firstCol) m_t << endl; m_t << ".PP" << endl; m_t << ".nf" << endl; - Doxygen::parserManager->getCodeParser(inc->extension()) - .parseCode(m_ci, + getCodeParser(inc->extension()).parseCode(m_ci, inc->context(), extractBlock(inc->text(),inc->blockId()), langExt, @@ -345,13 +338,12 @@ void ManDocVisitor::visit(DocInclude *inc) m_t << ".nf" << endl; QFileInfo cfi( inc->file() ); FileDef *fd = createFileDef( cfi.dirPath().utf8(), cfi.fileName().utf8() ); - Doxygen::parserManager->getCodeParser(inc->extension()) - .parseCode(m_ci, + getCodeParser(inc->extension()).parseCode(m_ci, inc->context(), extractBlock(inc->text(),inc->blockId()), langExt, inc->isExample(), - inc->exampleFile(), + inc->exampleFile(), fd, lineBlock(inc->text(),inc->blockId()), -1, // endLine @@ -366,8 +358,8 @@ void ManDocVisitor::visit(DocInclude *inc) m_firstCol=TRUE; } break; - case DocInclude::SnippetDoc: - case DocInclude::IncludeDoc: + case DocInclude::SnippetDoc: + case DocInclude::IncludeDoc: err("Internal inconsistency: found switch SnippetDoc / IncludeDoc in file: %s" "Please create a bug report\n",__FILE__); break; @@ -381,7 +373,7 @@ void ManDocVisitor::visit(DocIncOperator *op) 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()) + if (op->isFirst()) { if (!m_hide) { @@ -392,10 +384,10 @@ void ManDocVisitor::visit(DocIncOperator *op) pushEnabled(); m_hide = TRUE; } - if (op->type()!=DocIncOperator::Skip) + if (op->type()!=DocIncOperator::Skip) { popEnabled(); - if (!m_hide) + if (!m_hide) { FileDef *fd = 0; if (!op->includeFileName().isEmpty()) @@ -404,8 +396,7 @@ void ManDocVisitor::visit(DocIncOperator *op) fd = createFileDef( cfi.dirPath().utf8(), cfi.fileName().utf8() ); } - Doxygen::parserManager->getCodeParser(locLangExt) - .parseCode(m_ci,op->context(),op->text(),langExt, + getCodeParser(locLangExt).parseCode(m_ci,op->context(),op->text(),langExt, op->isExample(),op->exampleFile(), fd, // fileDef op->line(), // startLine @@ -419,7 +410,7 @@ void ManDocVisitor::visit(DocIncOperator *op) pushEnabled(); m_hide=TRUE; } - if (op->isLast()) + if (op->isLast()) { popEnabled(); if (!m_hide) @@ -484,7 +475,7 @@ void ManDocVisitor::visitPre(DocAutoListItem *li) QCString ws; ws.fill(' ',m_indent-2); if (!m_firstCol) m_t << endl; - m_t << ".IP \"" << ws; + m_t << ".IP \"" << ws; if (((DocAutoList *)li->parent())->isEnumList()) { m_t << li->itemNumber() << ".\" " << m_indent+2; @@ -497,14 +488,14 @@ void ManDocVisitor::visitPre(DocAutoListItem *li) m_firstCol=TRUE; } -void ManDocVisitor::visitPost(DocAutoListItem *) +void ManDocVisitor::visitPost(DocAutoListItem *) { if (m_hide) return; m_t << endl; m_firstCol=TRUE; } -void ManDocVisitor::visitPre(DocPara *) +void ManDocVisitor::visitPre(DocPara *) { } @@ -515,7 +506,7 @@ void ManDocVisitor::visitPost(DocPara *p) !(p->parent() && // and for parameter sections p->parent()->kind()==DocNode::Kind_ParamSect ) - ) + ) { if (!m_firstCol) m_t << endl; m_t << ".PP" << endl; @@ -535,28 +526,28 @@ void ManDocVisitor::visitPre(DocSimpleSect *s) { if (m_hide) return; if (!m_firstCol) - { + { m_t << endl; m_t << ".PP" << endl; } m_t << "\\fB"; switch(s->type()) { - case DocSimpleSect::See: + case DocSimpleSect::See: m_t << theTranslator->trSeeAlso(); break; - case DocSimpleSect::Return: + case DocSimpleSect::Return: m_t << theTranslator->trReturns(); break; - case DocSimpleSect::Author: + case DocSimpleSect::Author: m_t << theTranslator->trAuthor(TRUE,TRUE); break; - case DocSimpleSect::Authors: + case DocSimpleSect::Authors: m_t << theTranslator->trAuthor(TRUE,FALSE); break; - case DocSimpleSect::Version: + case DocSimpleSect::Version: m_t << theTranslator->trVersion(); break; - case DocSimpleSect::Since: + case DocSimpleSect::Since: m_t << theTranslator->trSince(); break; - case DocSimpleSect::Date: + case DocSimpleSect::Date: m_t << theTranslator->trDate(); break; - case DocSimpleSect::Note: + case DocSimpleSect::Note: m_t << theTranslator->trNote(); break; case DocSimpleSect::Warning: m_t << theTranslator->trWarning(); break; @@ -630,7 +621,7 @@ void ManDocVisitor::visitPre(DocSimpleListItem *) m_firstCol=TRUE; } -void ManDocVisitor::visitPost(DocSimpleListItem *) +void ManDocVisitor::visitPost(DocSimpleListItem *) { if (m_hide) return; m_t << endl; @@ -649,7 +640,7 @@ void ManDocVisitor::visitPre(DocSection *s) m_firstCol=TRUE; } -void ManDocVisitor::visitPost(DocSection *) +void ManDocVisitor::visitPost(DocSection *) { } @@ -661,7 +652,7 @@ void ManDocVisitor::visitPre(DocHtmlList *) m_t << ".PD 0" << endl; } -void ManDocVisitor::visitPost(DocHtmlList *) +void ManDocVisitor::visitPost(DocHtmlList *) { if (m_hide) return; m_indent-=2; @@ -675,7 +666,7 @@ void ManDocVisitor::visitPre(DocHtmlListItem *li) QCString ws; ws.fill(' ',m_indent-2); if (!m_firstCol) m_t << endl; - m_t << ".IP \"" << ws; + m_t << ".IP \"" << ws; if (((DocHtmlList *)li->parent())->type()==DocHtmlList::Ordered) { m_t << li->itemNumber() << ".\" " << m_indent+2; @@ -688,7 +679,7 @@ void ManDocVisitor::visitPre(DocHtmlListItem *li) m_firstCol=TRUE; } -void ManDocVisitor::visitPost(DocHtmlListItem *) +void ManDocVisitor::visitPost(DocHtmlListItem *) { if (m_hide) return; m_t << endl; @@ -703,7 +694,7 @@ void ManDocVisitor::visitPost(DocHtmlListItem *) // m_insidePre=TRUE; //} // -//void ManDocVisitor::visitPost(DocHtmlPre *) +//void ManDocVisitor::visitPost(DocHtmlPre *) //{ // m_insidePre=FALSE; // if (!m_firstCol) m_t << endl; @@ -716,7 +707,7 @@ void ManDocVisitor::visitPre(DocHtmlDescList *) { } -void ManDocVisitor::visitPost(DocHtmlDescList *) +void ManDocVisitor::visitPost(DocHtmlDescList *) { if (m_hide) return; if (!m_firstCol) m_t << endl; @@ -732,7 +723,7 @@ void ManDocVisitor::visitPre(DocHtmlDescTitle *) m_firstCol=FALSE; } -void ManDocVisitor::visitPost(DocHtmlDescTitle *) +void ManDocVisitor::visitPost(DocHtmlDescTitle *) { if (m_hide) return; m_t << "\\fP\" 1c" << endl; @@ -743,7 +734,7 @@ void ManDocVisitor::visitPre(DocHtmlDescData *) { } -void ManDocVisitor::visitPost(DocHtmlDescData *) +void ManDocVisitor::visitPost(DocHtmlDescData *) { } @@ -751,7 +742,7 @@ void ManDocVisitor::visitPre(DocHtmlTable *) { } -void ManDocVisitor::visitPost(DocHtmlTable *) +void ManDocVisitor::visitPost(DocHtmlTable *) { } @@ -759,7 +750,7 @@ void ManDocVisitor::visitPre(DocHtmlCaption *) { } -void ManDocVisitor::visitPost(DocHtmlCaption *) +void ManDocVisitor::visitPost(DocHtmlCaption *) { } @@ -767,7 +758,7 @@ void ManDocVisitor::visitPre(DocHtmlRow *) { } -void ManDocVisitor::visitPost(DocHtmlRow *) +void ManDocVisitor::visitPost(DocHtmlRow *) { } @@ -775,7 +766,7 @@ void ManDocVisitor::visitPre(DocHtmlCell *) { } -void ManDocVisitor::visitPost(DocHtmlCell *) +void ManDocVisitor::visitPost(DocHtmlCell *) { } @@ -788,7 +779,7 @@ void ManDocVisitor::visitPre(DocInternal *) //m_t << ".RS 4" << endl; } -void ManDocVisitor::visitPost(DocInternal *) +void ManDocVisitor::visitPost(DocInternal *) { if (m_hide) return; //if (!m_firstCol) m_t << endl; @@ -803,7 +794,7 @@ void ManDocVisitor::visitPre(DocHRef *) m_t << "\\fC"; } -void ManDocVisitor::visitPost(DocHRef *) +void ManDocVisitor::visitPost(DocHRef *) { if (m_hide) return; m_t << "\\fP"; @@ -817,7 +808,7 @@ void ManDocVisitor::visitPre(DocHtmlHeader *header) m_t << " \""; } -void ManDocVisitor::visitPost(DocHtmlHeader *header) +void ManDocVisitor::visitPost(DocHtmlHeader *header) { if (m_hide) return; m_t << "\"" << endl; @@ -829,7 +820,7 @@ void ManDocVisitor::visitPre(DocImage *) { } -void ManDocVisitor::visitPost(DocImage *) +void ManDocVisitor::visitPost(DocImage *) { } @@ -837,14 +828,14 @@ void ManDocVisitor::visitPre(DocDotFile *) { } -void ManDocVisitor::visitPost(DocDotFile *) +void ManDocVisitor::visitPost(DocDotFile *) { } void ManDocVisitor::visitPre(DocMscFile *) { } -void ManDocVisitor::visitPost(DocMscFile *) +void ManDocVisitor::visitPost(DocMscFile *) { } @@ -862,7 +853,7 @@ void ManDocVisitor::visitPre(DocLink *) m_t << "\\fB"; } -void ManDocVisitor::visitPost(DocLink *) +void ManDocVisitor::visitPost(DocLink *) { if (m_hide) return; m_t << "\\fP"; @@ -875,7 +866,7 @@ void ManDocVisitor::visitPre(DocRef *ref) if (!ref->hasLinkText()) filter(ref->targetTitle()); } -void ManDocVisitor::visitPost(DocRef *) +void ManDocVisitor::visitPost(DocRef *) { if (m_hide) return; m_t << "\\fP"; @@ -891,7 +882,7 @@ void ManDocVisitor::visitPre(DocSecRefItem *) m_firstCol=TRUE; } -void ManDocVisitor::visitPost(DocSecRefItem *) +void ManDocVisitor::visitPost(DocSecRefItem *) { if (m_hide) return; m_t << endl; @@ -904,7 +895,7 @@ void ManDocVisitor::visitPre(DocSecRefList *) m_indent+=2; } -void ManDocVisitor::visitPost(DocSecRefList *) +void ManDocVisitor::visitPost(DocSecRefList *) { if (m_hide) return; m_indent-=2; @@ -916,20 +907,20 @@ void ManDocVisitor::visitPre(DocParamSect *s) { if (m_hide) return; if (!m_firstCol) - { + { m_t << endl; m_t << ".PP" << endl; } m_t << "\\fB"; switch(s->type()) { - case DocParamSect::Param: + case DocParamSect::Param: m_t << theTranslator->trParameters(); break; - case DocParamSect::RetVal: + case DocParamSect::RetVal: m_t << theTranslator->trReturnValues(); break; - case DocParamSect::Exception: + case DocParamSect::Exception: m_t << theTranslator->trExceptions(); break; - case DocParamSect::TemplateParam: + case DocParamSect::TemplateParam: m_t << theTranslator->trTemplateParameters(); break; default: ASSERT(0); @@ -961,11 +952,11 @@ void ManDocVisitor::visitPre(DocParamList *pl) if (!first) m_t << ","; else first=FALSE; if (param->kind()==DocNode::Kind_Word) { - visit((DocWord*)param); + visit((DocWord*)param); } else if (param->kind()==DocNode::Kind_LinkedWord) { - visit((DocLinkedWord*)param); + visit((DocLinkedWord*)param); } } m_t << "\\fP "; @@ -986,7 +977,7 @@ void ManDocVisitor::visitPre(DocXRefItem *x) if (m_hide) return; if (x->title().isEmpty()) return; if (!m_firstCol) - { + { m_t << endl; m_t << ".PP" << endl; } @@ -1012,7 +1003,7 @@ void ManDocVisitor::visitPre(DocInternalRef *) m_t << "\\fB"; } -void ManDocVisitor::visitPost(DocInternalRef *) +void ManDocVisitor::visitPost(DocInternalRef *) { if (m_hide) return; m_t << "\\fP"; @@ -1030,7 +1021,7 @@ void ManDocVisitor::visitPre(DocHtmlBlockQuote *) { if (m_hide) return; if (!m_firstCol) - { + { m_t << endl; m_t << ".PP" << endl; } @@ -1064,12 +1055,12 @@ void ManDocVisitor::visitPost(DocParBlock *) void ManDocVisitor::filter(const char *str) -{ +{ if (str) { const char *p=str; char c=0; - while ((c=*p++)) + while ((c=*p++)) { switch(c) { diff --git a/src/mangen.cpp b/src/mangen.cpp index 8574018..e58aa6e 100644 --- a/src/mangen.cpp +++ b/src/mangen.cpp @@ -155,7 +155,7 @@ static QCString buildFileName(const char *name) return fileName; } -void ManGenerator::startFile(const char *,const char *manName,const char *) +void ManGenerator::startFile(const char *,const char *manName,const char *,int) { startPlainFile( buildFileName( manName ) ); m_firstCol=TRUE; @@ -391,7 +391,7 @@ void ManGenerator::endItemListItem() { } -void ManGenerator::startCodeFragment() +void ManGenerator::startCodeFragment(const char *) { newParagraph(); t << ".nf" << endl; @@ -399,7 +399,7 @@ void ManGenerator::startCodeFragment() m_paragraph=FALSE; } -void ManGenerator::endCodeFragment() +void ManGenerator::endCodeFragment(const char *) { if (!m_firstCol) t << endl; t << ".fi" << endl; @@ -696,7 +696,7 @@ void ManGenerator::endParamList() { } -void ManGenerator::writeDoc(DocNode *n,const Definition *ctx,const MemberDef *) +void ManGenerator::writeDoc(DocNode *n,const Definition *ctx,const MemberDef *,int) { ManDocVisitor *visitor = new ManDocVisitor(t,*this,ctx?ctx->getDefFileExtension():QCString("")); n->accept(visitor); diff --git a/src/mangen.h b/src/mangen.h index 9bcdb18..052c5ee 100644 --- a/src/mangen.h +++ b/src/mangen.h @@ -34,10 +34,10 @@ class ManGenerator : public OutputGenerator OutputType type() const { return Man; } - void writeDoc(DocNode *,const Definition *,const MemberDef *); + void writeDoc(DocNode *,const Definition *,const MemberDef *,int); static void init(); - void startFile(const char *name,const char *manName,const char *title); + void startFile(const char *name,const char *manName,const char *title,int); void writeSearchInfo() {} void writeFooter(const char *) {} void endFile(); @@ -123,8 +123,8 @@ class ManGenerator : public OutputGenerator void writeRuler() {} void writeAnchor(const char *,const char *) {} - void startCodeFragment(); - void endCodeFragment(); + void startCodeFragment(const char *); + void endCodeFragment(const char *); void writeLineNumber(const char *,const char *,const char *,int l) { t << l << " "; m_col=0; } void startCodeLine(bool) {} void endCodeLine() { codify("\n"); m_col=0; } diff --git a/src/markdown.cpp b/src/markdown.cpp index 00c0723..33a471a 100644 --- a/src/markdown.cpp +++ b/src/markdown.cpp @@ -59,7 +59,7 @@ #ifdef ENABLE_TRACING #define IOSTREAM stdout #define DATA_BUFSIZE 20 -#if defined(_WIN32) && !defined(CYGWIN) +#if defined(_WIN32) && !defined(CYGWIN) && !defined(__MINGW32__) #define PRETTY_FUNC __FUNCSIG__ #else #define PRETTY_FUNC __PRETTY_FUNCTION__ @@ -784,7 +784,11 @@ void Markdown::writeMarkdownImage(const char *fmt, bool explicitTitle, m_out.addStr(title); m_out.addStr("\""); } - m_out.addStr("\n"); + else + { + m_out.addStr(" ");// so the line break will not be part of the image name + } + m_out.addStr("\\ilinebr"); } int Markdown::processLink(const char *data,int,int size) @@ -808,6 +812,7 @@ int Markdown::processLink(const char *data,int,int size) } contentStart=i; int level=1; + int nlTotal=0; int nl=0; // find the matching ] while (i<size) @@ -831,6 +836,8 @@ int Markdown::processLink(const char *data,int,int size) } i++; } + nlTotal += nl; + nl = 0; if (i>=size) return 0; // premature end of comment -> no link contentEnd=i; convertStringFragment(content,data+contentStart,contentEnd-contentStart); @@ -843,9 +850,12 @@ int Markdown::processLink(const char *data,int,int size) if (i<size && data[i]=='\n') // one newline allowed here { i++; + nl++; // skip more whitespace while (i<size && data[i]==' ') i++; } + nlTotal += nl; + nl = 0; bool explicitTitle=FALSE; if (i<size && data[i]=='(') // inline link @@ -854,7 +864,6 @@ int Markdown::processLink(const char *data,int,int size) while (i<size && data[i]==' ') i++; if (i<size && data[i]=='<') i++; linkStart=i; - nl=0; int braceCount=1; while (i<size && data[i]!='\'' && data[i]!='"' && braceCount>0) { @@ -876,6 +885,8 @@ int Markdown::processLink(const char *data,int,int size) i++; } } + nlTotal += nl; + nl = 0; if (i>=size || data[i]=='\n') return 0; convertStringFragment(link,data+linkStart,i-linkStart); link = link.stripWhiteSpace(); @@ -985,6 +996,8 @@ int Markdown::processLink(const char *data,int,int size) { return 0; } + nlTotal += nl; + nl = 0; if (isToc) // special case for [TOC] { int toc_level = Config_getInt(TOC_INCLUDE_HEADINGS); @@ -1037,7 +1050,11 @@ int Markdown::processLink(const char *data,int,int size) if (!(Portable::isAbsolutePath(link) || isURL(link))) { QFileInfo forg(link); - if (!(forg.exists() && forg.isReadable())) + if (forg.exists() && forg.isReadable()) + { + link = forg.absFilePath().data(); + } + else if (!(forg.exists() && forg.isReadable())) { QFileInfo fi(m_fileName); QCString mdFile = m_fileName.left(m_fileName.length()-fi.fileName().length()) + link; @@ -1066,6 +1083,7 @@ int Markdown::processLink(const char *data,int,int size) m_out.addStr("<a href=\""); m_out.addStr(link); m_out.addStr("\""); + for (int ii = 0; ii < nlTotal; ii++) m_out.addStr("\n"); if (!title.isEmpty()) { m_out.addStr(" title=\""); @@ -1923,16 +1941,16 @@ int Markdown::writeTableBlock(const char *data,int size) { if (row % 2) { - m_out.addStr("<tr class=\"markdownTableRowOdd\">"); + m_out.addStr("\n<tr class=\"markdownTableRowOdd\">"); } else { - m_out.addStr("<tr class=\"markdownTableRowEven\">"); + m_out.addStr("\n<tr class=\"markdownTableRowEven\">"); } } else { - m_out.addStr(" <tr class=\"markdownTableHead\">"); + m_out.addStr("\n <tr class=\"markdownTableHead\">"); } for (int c = 0; c < columns; c++) { @@ -1986,11 +2004,11 @@ int Markdown::writeTableBlock(const char *data,int size) } // need at least one space on either side of the cell text in // order for doxygen to do other formatting - m_out.addStr("> " + cellText + "\\ilinebr </" + cellTag + ">"); + m_out.addStr("> " + cellText + " \\ilinebr </" + cellTag + ">"); } cellTag = "td"; cellClass = "class=\"markdownTableBody"; - m_out.addStr(" </tr>\n"); + m_out.addStr(" </tr>"); } m_out.addStr("</table>\n"); @@ -2023,7 +2041,7 @@ void Markdown::writeOneLineHeaderOrRuler(const char *data,int size) QCString id; if (isHRuler(data,size)) { - m_out.addStr("\n<hr>\n"); + m_out.addStr("<hr>\n"); } else if ((level=isAtxHeader(data,size,header,id,TRUE))) { @@ -2058,13 +2076,17 @@ void Markdown::writeOneLineHeaderOrRuler(const char *data,int size) m_out.addStr("</"+hTag+">\n"); } } - else // nothing interesting -> just output the line + else if (size>0) // nothing interesting -> just output the line { - m_out.addStr(data,size); + int tmpSize = size; + if (data[size-1] == '\n') tmpSize--; + m_out.addStr(data,tmpSize); + if (hasLineBreak(data,size)) { - m_out.addStr("<br>\n"); + m_out.addStr("<br>"); } + if (tmpSize != size) m_out.addChar('\n'); } } @@ -2100,14 +2122,14 @@ int Markdown::writeBlockQuote(const char *data,int size) { for (l=curLevel;l<level;l++) { - m_out.addStr("<blockquote>\n"); + m_out.addStr("<blockquote>"); } } else if (level<curLevel) // quote level decreased => add end markers { for (l=level;l<curLevel;l++) { - m_out.addStr("</blockquote>\n"); + m_out.addStr("</blockquote>"); } } curLevel=level; @@ -2120,7 +2142,7 @@ int Markdown::writeBlockQuote(const char *data,int size) // end of comment within blockquote => add end markers for (l=0;l<curLevel;l++) { - m_out.addStr("</blockquote>\n"); + m_out.addStr("</blockquote>"); } return i; } @@ -2130,6 +2152,7 @@ int Markdown::writeCodeBlock(const char *data,int size,int refIndent) TRACE(data); int i=0,end; //printf("writeCodeBlock: data={%s}\n",QCString(data).left(size).data()); + // no need for \ilinebr here as the prvious like was empty and was skipped m_out.addStr("@verbatim\n"); int emptyLines=0; while (i<size) @@ -2164,7 +2187,7 @@ int Markdown::writeCodeBlock(const char *data,int size,int refIndent) break; } } - m_out.addStr("@endverbatim\n"); + m_out.addStr("@endverbatim\\ilinebr "); while (emptyLines>0) // write skipped empty lines { // add empty line @@ -2263,8 +2286,8 @@ void Markdown::writeFencedCodeBlock(const char *data,const char *lng, m_out.addStr("{"+lang+"}"); } addStrEscapeUtf8Nbsp(data+blockStart,blockEnd-blockStart); - m_out.addStr("\n"); - m_out.addStr("@endcode\n"); + m_out.addStr(" "); + m_out.addStr("@endcode"); } QCString Markdown::processQuotations(const QCString &s,int refIndent) @@ -2491,18 +2514,20 @@ static bool isExplicitPage(const QCString &docs) return FALSE; } -QCString Markdown::extractPageTitle(QCString &docs,QCString &id) +QCString Markdown::extractPageTitle(QCString &docs,QCString &id, int &prepend) { TRACE(docs.data()); - int ln=0; // first first non-empty line + prepend = 0; QCString title; - const char *data = docs.data(); int i=0; int size=docs.size(); + QCString docs_org(docs); + const char *data = docs_org.data(); + docs = ""; while (i<size && (data[i]==' ' || data[i]=='\n')) { - if (data[i]=='\n') ln++; + if (data[i]=='\n') prepend++; i++; } if (i>=size) return ""; @@ -2512,16 +2537,13 @@ QCString Markdown::extractPageTitle(QCString &docs,QCString &id) // first line from i..end1 if (end1<size) { - ln++; // second line form end1..end2 int end2=end1+1; while (end2<size && data[end2-1]!='\n') end2++; if (isHeaderline(data+end1,size-end1,FALSE)) { convertStringFragment(title,data+i,end1-i-1); - QCString lns; - lns.fill('\n',ln); - docs=lns+docs.mid(end2); + docs+="\n\n"+docs_org.mid(end2); id = extractTitleId(title, 0); //printf("extractPageTitle(title='%s' docs='%s' id='%s')\n",title.data(),docs.data(),id.data()); return title; @@ -2529,10 +2551,12 @@ QCString Markdown::extractPageTitle(QCString &docs,QCString &id) } if (i<end1 && isAtxHeader(data+i,end1-i,title,id,FALSE)>0) { - docs=docs.mid(end1); + docs+="\n"; + docs+=docs_org.mid(end1); } else { + docs=docs_org; id = extractTitleId(title, 0); } //printf("extractPageTitle(title='%s' docs='%s' id='%s')\n",title.data(),docs.data(),id.data()); @@ -2661,7 +2685,15 @@ QCString markdownFileNameToId(const QCString &fileName) QCString baseFn = stripFromPath(QFileInfo(fileName).absFilePath().utf8()); int i = baseFn.findRev('.'); if (i!=-1) baseFn = baseFn.left(i); - QCString baseName = substitute(substitute(substitute(baseFn," ","_"),"/","_"),":","_"); + QCString baseName = baseFn; + char *p = baseName.rawData(); + char c; + while ((c=*p)) + { + if (!isId(c)) *p='_'; // escape characters that do not yield an identifier by underscores + p++; + } + //printf("markdownFileNameToId(%s)=md_%s\n",qPrint(fileName),qPrint(baseName)); return "md_"+baseName; } @@ -2686,6 +2718,7 @@ void MarkdownOutlineParser::parseInput(const char *fileName, ClangTUParser* /*clangParser*/) { std::shared_ptr<Entry> current = std::make_shared<Entry>(); + int prepend = 0; // number of empty lines in front current->lang = SrcLangExt_Markdown; current->fileName = fileName; current->docFile = fileName; @@ -2693,7 +2726,7 @@ void MarkdownOutlineParser::parseInput(const char *fileName, QCString docs = fileBuf; QCString id; Markdown markdown(fileName,1,0); - QCString title=markdown.extractPageTitle(docs,id).stripWhiteSpace(); + QCString title=markdown.extractPageTitle(docs,id,prepend).stripWhiteSpace(); if (id.startsWith("autotoc_md")) id = ""; int indentLevel=title.isEmpty() ? 0 : -1; markdown.setIndentLevel(indentLevel); @@ -2710,24 +2743,26 @@ void MarkdownOutlineParser::parseInput(const char *fileName, QFileInfo(mdfileAsMainPage).absFilePath()) // file reference with path ) { - docs.prepend("@anchor " + id + "\n"); - docs.prepend("@mainpage "+title+"\n"); + docs.prepend("@anchor " + id + "\\ilinebr "); + docs.prepend("@mainpage "+title+"\\ilinebr "); } else if (id=="mainpage" || id=="index") { if (title.isEmpty()) title = titleFn; - docs.prepend("@anchor " + id + "\n"); - docs.prepend("@mainpage "+title+"\n"); + docs.prepend("@anchor " + id + "\\ilinebr "); + docs.prepend("@mainpage "+title+"\\ilinebr "); } else { - if (title.isEmpty()) title = titleFn; - if (!wasEmpty) docs.prepend("@anchor " + markdownFileNameToId(fileName) + "\n"); - docs.prepend("@page "+id+" "+title+"\n"); + if (title.isEmpty()) {title = titleFn;prepend=0;} + if (!wasEmpty) docs.prepend("@anchor " + markdownFileNameToId(fileName) + "\\ilinebr "); + docs.prepend("@page "+id+" "+title+"\\ilinebr "); } + for (int i = 0; i < prepend; i++) docs.prepend("\n"); } int lineNr=1; + p->commentScanner.enterFile(fileName,lineNr); Protection prot=Public; bool needsEntry = FALSE; int position=0; @@ -2759,6 +2794,7 @@ void MarkdownOutlineParser::parseInput(const char *fileName, { root->moveToSubEntryAndKeep(current); } + p->commentScanner.leaveFile(fileName,lineNr); } void MarkdownOutlineParser::parsePrototype(const char *text) diff --git a/src/markdown.h b/src/markdown.h index 1210967..dd4ff73 100644 --- a/src/markdown.h +++ b/src/markdown.h @@ -34,7 +34,7 @@ class Markdown public: Markdown(const char *fileName,int lineNr,int indentLevel=0); QCString process(const QCString &input, int &startNewlines); - QCString extractPageTitle(QCString &docs,QCString &id); + QCString extractPageTitle(QCString &docs,QCString &id,int &prepend); void setIndentLevel(int level) { m_indentLevel = level; } private: diff --git a/src/memberdef.cpp b/src/memberdef.cpp index 464dbd0..ca6026e 100644 --- a/src/memberdef.cpp +++ b/src/memberdef.cpp @@ -47,7 +47,7 @@ //----------------------------------------------------------------------------- -class MemberDefImpl : public DefinitionImpl, public MemberDef +class MemberDefImpl : public DefinitionMixin<MemberDefMutable> { public: MemberDefImpl(const char *defFileName,int defLine,int defColumn, @@ -76,15 +76,11 @@ class MemberDefImpl : public DefinitionImpl, public MemberDef virtual int initializerLines() const; virtual uint64 getMemberSpecifiers() const; virtual const MemberList *getSectionList(const Definition *) const; - virtual QCString displayDefinition() const; + virtual QCString displayDefinition() 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; @@ -242,7 +238,7 @@ class MemberDefImpl : public DefinitionImpl, public MemberDef virtual int getDeclColumn() const; virtual void setMemberType(MemberType t); virtual void setDefinition(const char *d); - virtual void setFileDef(FileDef *fd); + virtual void setFileDef(const FileDef *fd); virtual void setAnchor(); virtual void setProtection(Protection p); virtual void setMemberSpecifiers(uint64 s); @@ -250,9 +246,9 @@ class MemberDefImpl : public DefinitionImpl, public MemberDef virtual void setInitializer(const char *i); virtual void setBitfields(const char *s); virtual void setMaxInitLines(int lines); - virtual void setMemberClass(ClassDef *cd); + virtual void setMemberClass(const ClassDef *cd); virtual void setSectionList(const Definition *container,MemberList *sl); - virtual void setGroupDef(GroupDef *gd,Grouping::GroupPri_t pri, + virtual void setGroupDef(const GroupDef *gd,Grouping::GroupPri_t pri, const QCString &fileName,int startLine,bool hasDocs, MemberDef *member=0); virtual void setReadAccessor(const char *r); @@ -281,7 +277,7 @@ class MemberDefImpl : public DefinitionImpl, public MemberDef virtual void setTypeConstraints(const ArgumentList &al); virtual void setType(const char *t); virtual void setAccessorType(ClassDef *cd,const char *t); - virtual void setNamespace(NamespaceDef *nd); + virtual void setNamespace(const NamespaceDef *nd); virtual void setMemberGroup(MemberGroup *grp); virtual void setMemberGroupId(int id); virtual void makeImplementationDetail(); @@ -323,13 +319,14 @@ class MemberDefImpl : public DefinitionImpl, public MemberDef virtual void warnIfUndocumented() const; virtual void warnIfUndocumentedParams() const; virtual void detectUndocumentedParams(bool hasParamCommand,bool hasReturnCommand) const; - virtual MemberDef *createTemplateInstanceMember(const ArgumentList &formalArgs, + virtual MemberDefMutable *createTemplateInstanceMember(const ArgumentList &formalArgs, const std::unique_ptr<ArgumentList> &actualArgs) const; virtual void findSectionsInDocumentation(); virtual void writeLink(OutputList &ol, const ClassDef *cd,const NamespaceDef *nd,const FileDef *fd,const GroupDef *gd, bool onlyText=FALSE) const; virtual void addToSearchIndex() const; + virtual void resolveUnnamedParameters(const MemberDef *md); private: void _computeLinkableInProject(); @@ -360,10 +357,10 @@ class MemberDefImpl : public DefinitionImpl, public MemberDef IMPL *m_impl; uchar m_isLinkableCached; // 0 = not cached, 1=FALSE, 2=TRUE uchar m_isConstructorCached; // 0 = not cached, 1=FALSE, 2=TRUE - uchar m_isDestructorCached; // 0 = not cached, 1=FALSE, 2=TRUE + uchar m_isDestructorCached; // 1 = not cached, 1=FALSE, 2=TRUE }; -MemberDef *createMemberDef(const char *defFileName,int defLine,int defColumn, +MemberDefMutable *createMemberDef(const char *defFileName,int defLine,int defColumn, const char *type,const char *name,const char *args, const char *excp,Protection prot,Specifier virt,bool stat, Relationship related,MemberType t,const ArgumentList &tal, @@ -375,15 +372,15 @@ MemberDef *createMemberDef(const char *defFileName,int defLine,int defColumn, //----------------------------------------------------------------------------- -class MemberDefAliasImpl : public DefinitionAliasImpl, public MemberDef +class MemberDefAliasImpl : public DefinitionAliasMixin<MemberDef> { public: MemberDefAliasImpl(const Definition *newScope,const MemberDef *md) - : DefinitionAliasImpl(newScope,md), m_memberGroup(0) {} - virtual ~MemberDefAliasImpl() {} + : DefinitionAliasMixin(newScope,md), m_memberGroup(0) { init(); } + virtual ~MemberDefAliasImpl() { deinit(); } virtual DefType definitionType() const { return TypeMember; } - const MemberDef *getMdAlias() const { return dynamic_cast<const MemberDef*>(getAlias()); } + const MemberDef *getMdAlias() const { return toMemberDef(getAlias()); } virtual MemberDef *resolveAlias() { return const_cast<MemberDef*>(getMdAlias()); } virtual const MemberDef *resolveAlias() const { return getMdAlias(); } @@ -392,6 +389,8 @@ class MemberDefAliasImpl : public DefinitionAliasImpl, public MemberDef } virtual void moveTo(Definition *) {} + virtual QCString name() const + { return getMdAlias()->name(); } virtual QCString getOutputFileBase() const { return getMdAlias()->getOutputFileBase(); } virtual QCString getReference() const @@ -428,7 +427,7 @@ class MemberDefAliasImpl : public DefinitionAliasImpl, public MemberDef { return getMdAlias()->getFileDef(); } virtual const NamespaceDef* getNamespaceDef() const { return getMdAlias()->getNamespaceDef(); } - virtual ClassDef *accessorClass() const + virtual const ClassDef *accessorClass() const { return getMdAlias()->accessorClass(); } virtual const char *getReadAccessor() const { return getMdAlias()->getReadAccessor(); } @@ -737,95 +736,13 @@ class MemberDefAliasImpl : public DefinitionAliasImpl, public MemberDef 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"); - static ArgumentList dummy; return dummy; - } - - 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(const Definition *c,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(const 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 moveArgumentList(std::unique_ptr<ArgumentList> al) {} - virtual void moveDeclArgumentList(std::unique_ptr<ArgumentList> al) {} - virtual void setDefinitionTemplateParameterLists(const ArgumentLists &lists) {} - virtual void setTypeConstraints(const ArgumentList &al) {} - virtual void setType(const char *t) {} - virtual void setAccessorType(ClassDef *cd,const char *t) {} - virtual void setNamespace(NamespaceDef *nd) {} + virtual void warnIfUndocumented() const {} + virtual void warnIfUndocumentedParams() const {} + virtual void detectUndocumentedParams(bool hasParamCommand,bool hasReturnCommand) const {} virtual void setMemberGroup(MemberGroup *grp) { m_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(const ArgumentList &formalArgs, + virtual MemberDefMutable *createTemplateInstanceMember(const ArgumentList &formalArgs, const std::unique_ptr<ArgumentList> &actualArgs) const { return getMdAlias()->createTemplateInstanceMember(formalArgs,actualArgs); } - virtual void incrementFlowKeyWordCount() {} virtual void writeDeclaration(OutputList &ol, const ClassDef *cd,const NamespaceDef *nd,const FileDef *fd,const GroupDef *gd, @@ -838,18 +755,6 @@ class MemberDefAliasImpl : public DefinitionAliasImpl, public MemberDef { 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 {} private: MemberGroup *m_memberGroup; // group's member definition }; @@ -857,7 +762,9 @@ class MemberDefAliasImpl : public DefinitionAliasImpl, public MemberDef MemberDef *createMemberDefAlias(const Definition *newScope,const MemberDef *aliasMd) { - return new MemberDefAliasImpl(newScope,aliasMd); + MemberDef *amd = new MemberDefAliasImpl(newScope,aliasMd); + //printf("amd: name=%s displayName=%s\n",amd->name().data(),amd->displayName().data()); + return amd; } //----------------------------------------------------------------------------- @@ -985,7 +892,7 @@ static bool writeDefArgumentList(OutputList &ol,const Definition *scope,const Me } else if (scope->definitionType()==Definition::TypeClass) { - cName=tempArgListToString((dynamic_cast<const ClassDef*>(scope))->templateArguments(), + cName=tempArgListToString((toClassDef(scope))->templateArguments(), scope->getLanguage()); //printf("2. cName=%s\n",cName.data()); } @@ -1275,9 +1182,9 @@ class MemberDefImpl::IMPL const ArgumentList &al,const char *meta ); - ClassDef *classDef = 0; // member of or related to - FileDef *fileDef = 0; // member of file definition - NamespaceDef *nspace = 0; // the namespace this member is in. + const ClassDef *classDef = 0; // member of or related to + const FileDef *fileDef = 0; // member of file definition + const NamespaceDef *nspace = 0; // the namespace this member is in. MemberDef *enumScope = 0; // the enclosing scope, if this is an enum field bool livesInsideEnum = false; @@ -1338,7 +1245,7 @@ class MemberDefImpl::IMPL const MemberDef *groupAlias = 0; // Member containing the definition int grpId = 0; // group id MemberGroup *memberGroup = 0; // group's member definition - GroupDef *group = 0; // group in which this member is in + const GroupDef *group = 0; // group in which this member is in Grouping::GroupPri_t grouppri; // priority of this definition QCString groupFileName; // file where this grouping was defined int groupStartLine = 0; // line " " " " " @@ -1529,7 +1436,7 @@ MemberDefImpl::MemberDefImpl(const char *df,int dl,int dc, const char *t,const char *na,const char *a,const char *e, Protection p,Specifier v,bool s,Relationship r,MemberType mt, const ArgumentList &tal,const ArgumentList &al,const char *meta - ) : DefinitionImpl(df,dl,dc,removeRedundantWhiteSpace(na)) + ) : DefinitionMixin(df,dl,dc,removeRedundantWhiteSpace(na)) { //printf("MemberDefImpl::MemberDef(%s)\n",na); m_impl = new MemberDefImpl::IMPL; @@ -1539,7 +1446,7 @@ MemberDefImpl::MemberDefImpl(const char *df,int dl,int dc, m_isDestructorCached = 0; } -MemberDefImpl::MemberDefImpl(const MemberDefImpl &md) : DefinitionImpl(md) +MemberDefImpl::MemberDefImpl(const MemberDefImpl &md) : DefinitionMixin(md) { m_impl = new MemberDefImpl::IMPL; m_isLinkableCached = 0; @@ -1609,15 +1516,15 @@ void MemberDefImpl::moveTo(Definition *scope) setOuterScope(scope); if (scope->definitionType()==Definition::TypeClass) { - m_impl->classDef = dynamic_cast<ClassDef*>(scope); + m_impl->classDef = toClassDef(scope); } else if (scope->definitionType()==Definition::TypeFile) { - m_impl->fileDef = dynamic_cast<FileDef*>(scope); + m_impl->fileDef = toFileDef(scope); } else if (scope->definitionType()==Definition::TypeNamespace) { - m_impl->nspace = dynamic_cast<NamespaceDef*>(scope); + m_impl->nspace = toNamespaceDef(scope); } m_isLinkableCached = 0; m_isConstructorCached = 0; @@ -1641,7 +1548,11 @@ void MemberDefImpl::insertReimplementedBy(MemberDef *md) { if (m_impl->templateMaster) { - m_impl->templateMaster->insertReimplementedBy(md); + MemberDefMutable *mdm = toMemberDefMutable(m_impl->templateMaster); + if (mdm) + { + mdm->insertReimplementedBy(md); + } } if (m_impl->redefinedBy==0) m_impl->redefinedBy = new MemberList(MemberListType_redefinedBy); if (m_impl->redefinedBy->findRef(md)==-1) @@ -1779,7 +1690,7 @@ QCString MemberDefImpl::getOutputFileBase() const QCString MemberDefImpl::getReference() const { - QCString ref = DefinitionImpl::getReference(); + QCString ref = DefinitionMixin::getReference(); if (!ref.isEmpty()) { return ref; @@ -1914,25 +1825,25 @@ void MemberDefImpl::_computeLinkableInProject() void MemberDefImpl::setDocumentation(const char *d,const char *docFile,int docLine,bool stripWhiteSpace) { - DefinitionImpl::setDocumentation(d,docFile,docLine,stripWhiteSpace); + DefinitionMixin::setDocumentation(d,docFile,docLine,stripWhiteSpace); m_isLinkableCached = 0; } void MemberDefImpl::setBriefDescription(const char *b,const char *briefFile,int briefLine) { - DefinitionImpl::setBriefDescription(b,briefFile,briefLine); + DefinitionMixin::setBriefDescription(b,briefFile,briefLine); m_isLinkableCached = 0; } void MemberDefImpl::setInbodyDocumentation(const char *d,const char *inbodyFile,int inbodyLine) { - DefinitionImpl::setInbodyDocumentation(d,inbodyFile,inbodyLine); + DefinitionMixin::setInbodyDocumentation(d,inbodyFile,inbodyLine); m_isLinkableCached = 0; } void MemberDefImpl::setHidden(bool b) { - DefinitionImpl::setHidden(b); + DefinitionMixin::setHidden(b); m_isLinkableCached = 0; } @@ -1977,10 +1888,10 @@ void MemberDefImpl::writeLink(OutputList &ol, const NamespaceDef *nspace = getNamespaceDef(); if (!hideScopeNames) { - if (m_impl->enumScope && m_impl->livesInsideEnum) - { - n.prepend(m_impl->enumScope->displayName()+sep); - } + //if (m_impl->enumScope && m_impl->livesInsideEnum) + //{ + // n.prepend(m_impl->enumScope->displayName()+sep); + //} if (classDef && gd && !isRelated()) { n.prepend(classDef->displayName()+sep); @@ -2227,7 +2138,7 @@ void MemberDefImpl::writeDeclaration(OutputList &ol, QCString cfname = getOutputFileBase(); // search for the last anonymous scope in the member type - ClassDef *annoClassDef=getClassDefOfAnonymousType(); + ClassDefMutable *annoClassDef=toClassDefMutable(getClassDefOfAnonymousType()); ol.startMemberDeclaration(); @@ -2405,6 +2316,7 @@ void MemberDefImpl::writeDeclaration(OutputList &ol, static bool extractPrivate = Config_getBool(EXTRACT_PRIVATE); static bool extractPrivateVirtual = Config_getBool(EXTRACT_PRIV_VIRTUAL); static bool extractStatic = Config_getBool(EXTRACT_STATIC); + MemberDefMutable *annMemb = toMemberDefMutable(m_impl->annMemb); //printf("Member name=`%s gd=%p md->groupDef=%p inGroup=%d isLinkable()=%d hasDocumentation=%d\n",name().data(),gd,getGroupDef(),inGroup,isLinkable(),hasDocumentation()); if (!name().isEmpty() && // name valid (hasDocumentation() || isReference()) && // has docs @@ -2412,16 +2324,15 @@ void MemberDefImpl::writeDeclaration(OutputList &ol, !(isStatic() && getClassDef()==0 && !extractStatic) // hidden due to static-ness ) { - if (m_impl->annMemb) + if (annMemb) { //printf("anchor=%s ann_anchor=%s\n",anchor(),annMemb->anchor()); - m_impl->annMemb->writeLink(ol, - m_impl->annMemb->getClassDef(), - m_impl->annMemb->getNamespaceDef(), - m_impl->annMemb->getFileDef(), - m_impl->annMemb->getGroupDef() - ); - m_impl->annMemb->setAnonymousUsed(); + annMemb->writeLink(ol, + annMemb->getClassDef(), + annMemb->getNamespaceDef(), + annMemb->getFileDef(), + annMemb->getGroupDef()); + annMemb->setAnonymousUsed(); setAnonymousUsed(); } else @@ -2442,9 +2353,9 @@ void MemberDefImpl::writeDeclaration(OutputList &ol, // there is a brief member description and brief member // descriptions are enabled or there is no detailed description. { - if (m_impl->annMemb) + if (annMemb) { - m_impl->annMemb->setAnonymousUsed(); + annMemb->setAnonymousUsed(); setAnonymousUsed(); } const ClassDef *rcd = cd; @@ -3335,7 +3246,7 @@ void MemberDefImpl::writeDocumentation(const MemberList *ml, 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<const GroupDef *>(container))->groupTitle(); + ciname = (toGroupDef(container))->groupTitle(); } else if (container->definitionType()==TypeFile && getNamespaceDef() && getNamespaceDef()->isLinkable()) { // member is in a namespace, but is written as part of the file documentation @@ -3433,7 +3344,7 @@ void MemberDefImpl::writeDocumentation(const MemberList *ml, { //printf("Anonymous compound '%s'\n",cname.data()); ol.startDoxyAnchor(cfname,cname,memAnchor,doxyName,doxyArgs); - ol.startMemberDoc(ciname,name(),memAnchor,name(),memCount,memTotal,showInline); + ol.startMemberDoc(ciname,name(),memAnchor,"",memCount,memTotal,showInline); // search for the last anonymous compound name in the definition int si=ldef.find(' '),pi,ei=i+l; if (si==-1) si=0; @@ -3681,12 +3592,12 @@ void MemberDefImpl::writeDocumentation(const MemberList *ml, else ol.parseText(theTranslator->trInitialValue()); ol.endBold(); - CodeParserInterface &intf = Doxygen::parserManager->getCodeParser(getDefFileExtension()); - intf.resetCodeParserState(); - ol.startCodeFragment(); - intf.parseCode(ol,scopeName,m_impl->initializer,lang,FALSE,0,const_cast<FileDef*>(getFileDef()), + auto intf = Doxygen::parserManager->getCodeParser(getDefFileExtension()); + intf->resetCodeParserState(); + ol.startCodeFragment("DoxyCode"); + intf->parseCode(ol,scopeName,m_impl->initializer,lang,FALSE,0,const_cast<FileDef*>(getFileDef()), -1,-1,TRUE,this,FALSE,this); - ol.endCodeFragment(); + ol.endCodeFragment("DoxyCode"); } QCString brief = briefDescription(); @@ -3904,7 +3815,7 @@ void MemberDefImpl::writeMemberDocSimple(OutputList &ol, const Definition *conta //printf("===> %s::anonymous: %s\n",name().data(),cd?cd->name().data():"<none>"); if (container && container->definitionType()==Definition::TypeClass && - !(dynamic_cast<const ClassDef*>(container))->isJavaEnum()) + !(toClassDef(container))->isJavaEnum()) { ol.startInlineMemberType(); ol.startDoxyAnchor(cfname,cname,memAnchor,doxyName,doxyArgs); @@ -4050,6 +3961,18 @@ void MemberDefImpl::warnIfUndocumented() const warnIfUndocumentedParams(); } } +static QCString stripTrailingReturn(const QCString trailRet) +{ + QCString ret = trailRet; + + ret = ret.stripWhiteSpace(); + if (ret.startsWith("->")) + { + ret = ret.mid(2).stripWhiteSpace(); + return ret; + } + return trailRet; +} void MemberDefImpl::detectUndocumentedParams(bool hasParamCommand,bool hasReturnCommand) const { @@ -4058,7 +3981,17 @@ void MemberDefImpl::detectUndocumentedParams(bool hasParamCommand,bool hasReturn bool isPython = getLanguage()==SrcLangExt_Python; bool isFortran = getLanguage()==SrcLangExt_Fortran; bool isFortranSubroutine = isFortran && returnType.find("subroutine")!=-1; + bool isVoidReturn = (returnType=="void") || (returnType.right(5)==" void"); + if (!isVoidReturn && returnType == "auto") + { + const ArgumentList &defArgList=isDocsForDefinition() ? argumentList() : declArgumentList(); + if (!defArgList.trailingReturnType().isEmpty()) + { + QCString strippedTrailingReturn = stripTrailingReturn(defArgList.trailingReturnType()); + isVoidReturn = (strippedTrailingReturn=="void") || (strippedTrailingReturn.right(5)==" void"); + } + } if (!m_impl->hasDocumentedParams && hasParamCommand) { @@ -4186,7 +4119,7 @@ bool MemberDefImpl::isDeleted() const bool MemberDefImpl::hasDocumentation() const { - return DefinitionImpl::hasDocumentation() || + return DefinitionMixin::hasDocumentation() || (m_impl->mtype==MemberType_Enumeration && m_impl->docEnumValues) || // has enum values (m_impl->defArgList.hasDocumentation()); // has doc arguments } @@ -4194,7 +4127,7 @@ bool MemberDefImpl::hasDocumentation() const #if 0 bool MemberDefImpl::hasUserDocumentation() const { - bool hasDocs = DefinitionImpl::hasUserDocumentation(); + bool hasDocs = DefinitionMixin::hasUserDocumentation(); return hasDocs; } #endif @@ -4272,7 +4205,7 @@ void MemberDefImpl::setAnchor() m_impl->anc = "a"+sigStr; } -void MemberDefImpl::setGroupDef(GroupDef *gd,Grouping::GroupPri_t pri, +void MemberDefImpl::setGroupDef(const GroupDef *gd,Grouping::GroupPri_t pri, const QCString &fileName,int startLine, bool hasDocs,MemberDef *member) { @@ -4292,38 +4225,36 @@ void MemberDefImpl::setEnumScope(MemberDef *md,bool livesInsideEnum) m_impl->livesInsideEnum=livesInsideEnum; if (md->getGroupDef()) { - m_impl->group=md->getGroupDef(); - m_impl->grouppri=md->getGroupPri(); - m_impl->groupFileName=md->getGroupFileName(); - m_impl->groupStartLine=md->getGroupStartLine(); - m_impl->groupHasDocs=md->getGroupHasDocs(); + m_impl->group = const_cast<GroupDef*>(md->getGroupDef()); + m_impl->grouppri = md->getGroupPri(); + m_impl->groupFileName = md->getGroupFileName(); + m_impl->groupStartLine = md->getGroupStartLine(); + m_impl->groupHasDocs = md->getGroupHasDocs(); m_isLinkableCached = 0; } } -void MemberDefImpl::setMemberClass(ClassDef *cd) +void MemberDefImpl::setMemberClass(const ClassDef *cd) { m_impl->classDef=cd; m_isLinkableCached = 0; m_isConstructorCached = 0; - setOuterScope(cd); + setOuterScope(const_cast<ClassDef*>(cd)); } -void MemberDefImpl::setNamespace(NamespaceDef *nd) +void MemberDefImpl::setNamespace(const NamespaceDef *nd) { m_impl->nspace=nd; - setOuterScope(nd); + setOuterScope(const_cast<NamespaceDef*>(nd)); } -MemberDef *MemberDefImpl::createTemplateInstanceMember( +MemberDefMutable *MemberDefImpl::createTemplateInstanceMember( const ArgumentList &formalArgs,const std::unique_ptr<ArgumentList> &actualArgs) const { //printf(" Member %s %s %s\n",typeString(),name().data(),argsString()); - std::unique_ptr<ArgumentList> actualArgList; + std::unique_ptr<ArgumentList> actualArgList = std::make_unique<ArgumentList>(m_impl->defArgList); if (!m_impl->defArgList.empty()) { - actualArgList = std::make_unique<ArgumentList>(m_impl->defArgList); - // replace formal arguments with actuals for (Argument &arg : *actualArgList) { @@ -4332,10 +4263,6 @@ MemberDef *MemberDefImpl::createTemplateInstanceMember( actualArgList->setTrailingReturnType( substituteTemplateArgumentsInString(actualArgList->trailingReturnType(),formalArgs,actualArgs)); } - else - { - actualArgList = std::make_unique<ArgumentList>(); - } QCString methodName=name(); if (methodName.left(9)=="operator ") // conversion operator @@ -4343,7 +4270,7 @@ MemberDef *MemberDefImpl::createTemplateInstanceMember( methodName=substituteTemplateArgumentsInString(methodName,formalArgs,actualArgs); } - MemberDef *imd = createMemberDef( + MemberDefMutable *imd = createMemberDef( getDefFileName(),getDefLine(),getDefColumn(), substituteTemplateArgumentsInString(m_impl->type,formalArgs,actualArgs), methodName, @@ -4417,7 +4344,7 @@ void MemberDefImpl::addListReference(Definition *) QCString memName = name(); Definition *pd=getOuterScope(); QCString pdName = pd->definitionType()==Definition::TypeClass ? - (dynamic_cast<ClassDef*>(pd))->displayName() : pd->name(); + (toClassDef(pd))->displayName() : pd->name(); QCString sep = getLanguageSpecificSeparator(lang,TRUE); QCString memArgs; if (!isRelated() @@ -4712,12 +4639,17 @@ void MemberDefImpl::writeEnumDeclaration(OutputList &typeDecl, if (fmdl) { MemberListIterator mli(*fmdl); - MemberDef *fmd=mli.current(); + MemberDefMutable *fmd=toMemberDefMutable(mli.current()); bool fmdVisible = fmd ? fmd->isBriefSectionVisible() : TRUE; + bool first=true; while (fmd) { if (fmdVisible) { + if (!first) + { + typeDecl.writeString(", "); + } /* in html we start a new line after a number of items */ if (numVisibleEnumValues>enumValuesPerLine && (enumMemCount%enumValuesPerLine)==0 @@ -4752,15 +4684,12 @@ void MemberDefImpl::writeEnumDeclaration(OutputList &typeDecl, typeDecl.writeString(" "); typeDecl.parseText(fmd->initializer()); } + first=false; } bool prevVisible = fmdVisible; ++mli; - fmd=mli.current(); - if (fmd && (fmdVisible=fmd->isBriefSectionVisible())) - { - typeDecl.writeString(", "); - } + fmd=toMemberDefMutable(mli.current()); if (prevVisible) { typeDecl.disable(OutputGenerator::Man); @@ -4814,6 +4743,7 @@ ClassDef *MemberDefImpl::accessorClass() const void MemberDefImpl::findSectionsInDocumentation() { + docFindSections(briefDescription(),this,docFile()); docFindSections(documentation(),this,docFile()); } @@ -4894,7 +4824,7 @@ QCString MemberDefImpl::qualifiedName() const } else { - return DefinitionImpl::qualifiedName(); + return DefinitionMixin::qualifiedName(); } } @@ -4981,31 +4911,16 @@ const ClassDef *MemberDefImpl::getClassDef() const return m_impl->classDef; } -ClassDef *MemberDefImpl::getClassDef() -{ - return m_impl->classDef; -} - const FileDef *MemberDefImpl::getFileDef() const { return m_impl->fileDef; } -FileDef *MemberDefImpl::getFileDef() -{ - return m_impl->fileDef; -} - const NamespaceDef* MemberDefImpl::getNamespaceDef() const { return m_impl->nspace; } -NamespaceDef* MemberDefImpl::getNamespaceDef() -{ - return m_impl->nspace; -} - const char *MemberDefImpl::getReadAccessor() const { return m_impl->read; @@ -5021,11 +4936,6 @@ const GroupDef *MemberDefImpl::getGroupDef() const return m_impl->group; } -GroupDef *MemberDefImpl::getGroupDef() -{ - return m_impl->group; -} - Grouping::GroupPri_t MemberDefImpl::getGroupPri() const { return m_impl->grouppri; @@ -5463,6 +5373,54 @@ const ArgumentList &MemberDefImpl::declArgumentList() const return m_impl->declArgList; } +void MemberDefImpl::resolveUnnamedParameters(const MemberDef *md) +{ + ArgumentList &decAl = m_impl->declArgList; + ArgumentList &defAl = m_impl->defArgList; + const ArgumentList &decAlSrc = md->declArgumentList(); + const ArgumentList &defAlSrc = md->argumentList(); + auto decSrc = decAlSrc.begin(), defSrc = defAlSrc.begin(); + for (auto decIt = decAl.begin(), defIt = defAl.begin(); + decIt != decAl.end() && defIt != defAl.end() && decSrc != decAlSrc.end() && defSrc != defAlSrc.end(); + ++decIt, ++defIt, ++decSrc, ++defSrc++) + { + Argument &decA = *decIt; + Argument &defA = *defIt; + const Argument &decAS = *decSrc; + const Argument &defAS = *defSrc; + if (decA.name.isEmpty()) + { + if (!defA.name.isEmpty()) + { + decA.name = defA.name; + } + else if (!decAS.name.isEmpty()) + { + decA.name = decAS.name; + } + else if (!defAS.name.isEmpty()) + { + decA.name = defAS.name; + } + } + if (defA.name.isEmpty()) + { + if (!decA.name.isEmpty()) + { + defA.name = decA.name; + } + else if (!decAS.name.isEmpty()) + { + defA.name = decAS.name; + } + else if (!defAS.name.isEmpty()) + { + defA.name = defAS.name; + } + } + } +} + const ArgumentList &MemberDefImpl::templateArguments() const { return m_impl->tArgList; @@ -5593,7 +5551,7 @@ void MemberDefImpl::setDefinition(const char *d) m_impl->def=d; } -void MemberDefImpl::setFileDef(FileDef *fd) +void MemberDefImpl::setFileDef(const FileDef *fd) { m_impl->fileDef=fd; m_isLinkableCached = 0; @@ -5883,7 +5841,7 @@ int MemberDefImpl::numberOfFlowKeyWords() const QCString MemberDefImpl::displayName(bool) const { - return DefinitionImpl::name(); + return DefinitionMixin::name(); } void MemberDefImpl::addToSearchIndex() const @@ -5929,10 +5887,21 @@ static void transferArgumentDocumentation(ArgumentList &decAl,ArgumentList &defA { defA.docs = decA.docs; } + if (Config_getBool(RESOLVE_UNNAMED_PARAMS)) + { + if (decA.name.isEmpty() && !defA.name.isEmpty()) + { + decA.name = defA.name; + } + else if (defA.name.isEmpty() && !decA.name.isEmpty()) + { + defA.name = decA.name; + } + } } } -void combineDeclarationAndDefinition(MemberDef *mdec,MemberDef *mdef) +void combineDeclarationAndDefinition(MemberDefMutable *mdec,MemberDefMutable *mdef) { //printf("mdec=%s isPrototype()=%d\n",mdec->name().data(),mdec->isPrototype()); if ( @@ -5944,12 +5913,10 @@ 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(cmdef->getOuterScope(),cmdef->getFileDef(),&mdefAl, - cmdec->getOuterScope(),cmdec->getFileDef(),&mdecAl, + ArgumentList &mdefAl = const_cast<ArgumentList&>(mdef->argumentList()); + ArgumentList &mdecAl = const_cast<ArgumentList&>(mdec->argumentList()); + if (matchArguments2(mdef->getOuterScope(),mdef->getFileDef(),&mdefAl, + mdec->getOuterScope(),mdec->getFileDef(),&mdecAl, TRUE ) ) /* match found */ @@ -5960,6 +5927,11 @@ void combineDeclarationAndDefinition(MemberDef *mdec,MemberDef *mdef) // mdec->getFileDef()->name().data(),mdec->documentation().data() // ); + if (Config_getBool(RESOLVE_UNNAMED_PARAMS)) + { + mdec->resolveUnnamedParameters(mdef); + } + // first merge argument documentation transferArgumentDocumentation(mdecAl,mdefAl); @@ -6021,7 +5993,6 @@ void combineDeclarationAndDefinition(MemberDef *mdec,MemberDef *mdef) mdec->mergeMemberSpecifiers(mdef->getMemberSpecifiers()); mdef->mergeMemberSpecifiers(mdec->getMemberSpecifiers()); - // copy group info. if (mdec->getGroupDef()==0 && mdef->getGroupDef()!=0) { @@ -6072,7 +6043,7 @@ QCString MemberDefImpl::briefDescription(bool abbr) const } else { - return DefinitionImpl::briefDescription(abbr); + return DefinitionMixin::briefDescription(abbr); } } @@ -6084,7 +6055,7 @@ QCString MemberDefImpl::documentation() const } else { - return DefinitionImpl::documentation(); + return DefinitionMixin::documentation(); } } @@ -6128,7 +6099,114 @@ bool MemberDefImpl::isRelatedOrFriend() const bool MemberDefImpl::isReference() const { - return DefinitionImpl::isReference() || + return DefinitionMixin::isReference() || (m_impl->templateMaster && m_impl->templateMaster->isReference()); } +//------------------------------------------------------------------------------- +// Helpers + +void addDocCrossReference(MemberDefMutable *src,MemberDefMutable *dst) +{ + if (src==0 || dst==0) return; + //printf("--> addDocCrossReference src=%s,dst=%s\n",src->name().data(),dst->name().data()); + if (dst->isTypedef() || dst->isEnumerate()) return; // don't add types + if ((dst->hasReferencedByRelation() || dst->hasCallerGraph()) && + src->showInCallGraph() + ) + { + dst->addSourceReferencedBy(src); + MemberDefMutable *mdDef = toMemberDefMutable(dst->memberDefinition()); + if (mdDef) + { + mdDef->addSourceReferencedBy(src); + } + MemberDefMutable *mdDecl = toMemberDefMutable(dst->memberDeclaration()); + if (mdDecl) + { + mdDecl->addSourceReferencedBy(src); + } + } + if ((src->hasReferencesRelation() || src->hasCallGraph()) && + src->showInCallGraph() + ) + { + src->addSourceReferences(dst); + MemberDefMutable *mdDef = toMemberDefMutable(src->memberDefinition()); + if (mdDef) + { + mdDef->addSourceReferences(dst); + } + MemberDefMutable *mdDecl = toMemberDefMutable(src->memberDeclaration()); + if (mdDecl) + { + mdDecl->addSourceReferences(dst); + } + } +} + +// --- Cast functions +// +MemberDef *toMemberDef(Definition *d) +{ + if (d && (typeid(*d)==typeid(MemberDefImpl) || typeid(*d)==typeid(MemberDefAliasImpl))) + { + return static_cast<MemberDef*>(d); + } + else + { + return 0; + } +} + +MemberDef *toMemberDef(DefinitionMutable *md) +{ + Definition *d = toDefinition(md); + if (d && typeid(*d)==typeid(MemberDefImpl)) + { + return static_cast<MemberDef*>(d); + } + else + { + return 0; + } +} + +const MemberDef *toMemberDef(const Definition *d) +{ + if (d && (typeid(*d)==typeid(MemberDefImpl) || typeid(*d)==typeid(MemberDefAliasImpl))) + { + return static_cast<const MemberDef*>(d); + } + else + { + return 0; + } +} + +MemberDefMutable *toMemberDefMutable(Definition *d) +{ + if (d && typeid(*d)==typeid(MemberDefImpl)) + { + return static_cast<MemberDefMutable*>(d); + } + else + { + return 0; + } +} + +MemberDefMutable *toMemberDefMutable(const Definition *d) +{ + if (d && typeid(*d)==typeid(MemberDefImpl)) + { + return const_cast<MemberDefMutable*>(static_cast<const MemberDefMutable*>(d)); + } + else + { + return 0; + } +} + + + diff --git a/src/memberdef.h b/src/memberdef.h index f15c31e..11d403c 100644 --- a/src/memberdef.h +++ b/src/memberdef.h @@ -27,8 +27,8 @@ #include "types.h" #include "definition.h" #include "arguments.h" +#include "classdef.h" -class ClassDef; class NamespaceDef; class GroupDef; class FileDef; @@ -40,9 +40,10 @@ class GroupDef; class QTextStream; class QStrList; struct TagInfo; +class MemberDefMutable; /** A model of a class/file/namespace member symbol. */ -class MemberDef : virtual public Definition +class MemberDef : public Definition { public: virtual ~MemberDef() {} @@ -54,6 +55,8 @@ class MemberDef : virtual public Definition virtual MemberDef *resolveAlias() = 0; virtual const MemberDef *resolveAlias() const = 0; + ClassDefMutable *getClassDefMutable() const; + //----------------------------------------------------------------------------------- // ---- getters ----- //----------------------------------------------------------------------------------- @@ -77,25 +80,17 @@ class MemberDef : virtual public Definition virtual QCString displayDefinition() const = 0; // scope query members - virtual const ClassDef *getClassDef() const = 0; - virtual ClassDef *getClassDef() = 0; - virtual const FileDef *getFileDef() const = 0; - virtual FileDef *getFileDef() = 0; - + virtual const ClassDef *getClassDef() const = 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; + virtual const ClassDef *accessorClass() const = 0; // grabbing the property read/write accessor names virtual const char *getReadAccessor() const = 0; virtual const char *getWriteAccessor() const = 0; // querying the grouping definition + virtual const GroupDef *getGroupDef() const = 0; virtual Grouping::GroupPri_t getGroupPri() const = 0; virtual const char *getGroupFileName() const = 0; virtual int getGroupStartLine() const = 0; @@ -216,7 +211,6 @@ class MemberDef : virtual public Definition virtual bool isDocsForDefinition() 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() const = 0; @@ -225,7 +219,6 @@ class MemberDef : virtual public Definition // argument related members virtual const ArgumentList &argumentList() const = 0; - virtual ArgumentList &argumentList() = 0; virtual const ArgumentList &declArgumentList() const = 0; virtual const ArgumentList &templateArguments() const = 0; virtual const ArgumentLists &definitionTemplateParameterLists() const = 0; @@ -280,15 +273,33 @@ class MemberDef : virtual public Definition virtual int getDeclLine() const = 0; virtual int getDeclColumn() const = 0; + virtual MemberDefMutable *createTemplateInstanceMember(const ArgumentList &formalArgs, + const std::unique_ptr<ArgumentList> &actualArgs) const = 0; + 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 writeEnumDeclaration(OutputList &typeDecl, const ClassDef *cd, + const NamespaceDef *nd,const FileDef *fd,const GroupDef *gd) const = 0; + virtual void detectUndocumentedParams(bool hasParamCommand,bool hasReturnCommand) const = 0; + virtual void warnIfUndocumented() const = 0; + virtual void warnIfUndocumentedParams() const = 0; + + // TODO: this is not a getter, should be passed at construction + virtual void setMemberGroup(MemberGroup *grp) = 0; +}; + +class MemberDefMutable : public DefinitionMutable, public MemberDef +{ + public: + //----------------------------------------------------------------------------------- // ---- setters ----- //----------------------------------------------------------------------------------- - // set functions virtual void setMemberType(MemberType t) = 0; virtual void setDefinition(const char *d) = 0; - virtual void setFileDef(FileDef *fd) = 0; + virtual void setFileDef(const FileDef *fd) = 0; virtual void setAnchor() = 0; virtual void setProtection(Protection p) = 0; virtual void setMemberSpecifiers(uint64 s) = 0; @@ -296,9 +307,9 @@ class MemberDef : virtual public Definition virtual void setInitializer(const char *i) = 0; virtual void setBitfields(const char *s) = 0; virtual void setMaxInitLines(int lines) = 0; - virtual void setMemberClass(ClassDef *cd) = 0; + virtual void setMemberClass(const ClassDef *cd) = 0; virtual void setSectionList(const Definition *container,MemberList *sl) = 0; - virtual void setGroupDef(GroupDef *gd,Grouping::GroupPri_t pri, + virtual void setGroupDef(const GroupDef *gd,Grouping::GroupPri_t pri, const QCString &fileName,int startLine,bool hasDocs, MemberDef *member=0) = 0; virtual void setReadAccessor(const char *r) = 0; @@ -311,6 +322,7 @@ class MemberDef : virtual public Definition virtual void setTagInfo(const TagInfo *i) = 0; virtual void setArgsString(const char *as) = 0; virtual void incrementFlowKeyWordCount() = 0; + virtual void setEnumBaseType(const QCString &type) = 0; // relation to other members virtual void setReimplements(MemberDef *md) = 0; @@ -336,16 +348,16 @@ class MemberDef : virtual public Definition // argument related members virtual void moveArgumentList(std::unique_ptr<ArgumentList> al) = 0; virtual void moveDeclArgumentList(std::unique_ptr<ArgumentList> al) = 0; + virtual void resolveUnnamedParameters(const MemberDef *md) = 0; virtual void setDefinitionTemplateParameterLists(const ArgumentLists &lists) = 0; virtual void setTypeConstraints(const ArgumentList &al) = 0; virtual void setType(const char *t) = 0; virtual void setAccessorType(ClassDef *cd,const char *t) = 0; // namespace related members - virtual void setNamespace(NamespaceDef *nd) = 0; + virtual void setNamespace(const NamespaceDef *nd) = 0; // member group related members - virtual void setMemberGroup(MemberGroup *grp) = 0; virtual void setMemberGroupId(int id) = 0; virtual void makeImplementationDetail() = 0; @@ -387,8 +399,6 @@ class MemberDef : virtual public Definition // --- actions ---- //----------------------------------------------------------------------------------- - virtual MemberDef *createTemplateInstanceMember(const ArgumentList &formalArgs, - const std::unique_ptr<ArgumentList> &actualArgs) const = 0; virtual void findSectionsInDocumentation() = 0; virtual void addToSearchIndex() const = 0; @@ -396,32 +406,40 @@ class MemberDef : virtual public Definition // --- 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, 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; }; +inline ClassDefMutable *MemberDef::getClassDefMutable() const +{ + return toClassDefMutable(getClassDef()); +} + +// --- Cast functions + +MemberDef *toMemberDef(Definition *d); +MemberDef *toMemberDef(DefinitionMutable *d); +const MemberDef *toMemberDef(const Definition *d); +MemberDefMutable *toMemberDefMutable(Definition *d); +MemberDefMutable *toMemberDefMutable(const Definition *d); + +//------------------------------------------------------------------------ + + /** Factory method to create a new instance of a MemberDef */ -MemberDef *createMemberDef(const char *defFileName,int defLine,int defColumn, +MemberDefMutable *createMemberDef(const char *defFileName,int defLine,int defColumn, const char *type,const char *name,const char *args, const char *excp,Protection prot,Specifier virt,bool stat, Relationship related,MemberType t,const ArgumentList &tal, @@ -429,6 +447,7 @@ MemberDef *createMemberDef(const char *defFileName,int defLine,int defColumn, MemberDef *createMemberDefAlias(const Definition *newScope,const MemberDef *aliasMd); -void combineDeclarationAndDefinition(MemberDef *mdec,MemberDef *mdef); +void combineDeclarationAndDefinition(MemberDefMutable *mdec,MemberDefMutable *mdef); +void addDocCrossReference(MemberDefMutable *src,MemberDefMutable *dst); #endif diff --git a/src/membergroup.cpp b/src/membergroup.cpp index e229835..bd3bf0c 100644 --- a/src/membergroup.cpp +++ b/src/membergroup.cpp @@ -71,10 +71,14 @@ void MemberGroup::insertMember(MemberDef *md) GroupDef *gd; if (firstMd && !firstMd->isAlias() && (gd=const_cast<GroupDef*>(firstMd->getGroupDef()))) { - md->setGroupDef(gd, firstMd->getGroupPri(), - firstMd->getGroupFileName(), - firstMd->getGroupStartLine(), - firstMd->getGroupHasDocs()); + MemberDefMutable *mdm = toMemberDefMutable(md); + if (mdm) + { + mdm->setGroupDef(gd, firstMd->getGroupPri(), + firstMd->getGroupFileName(), + firstMd->getGroupStartLine(), + firstMd->getGroupHasDocs()); + } gd->insertMember(md); } } @@ -82,7 +86,7 @@ void MemberGroup::insertMember(MemberDef *md) void MemberGroup::setAnchors() { - ::setAnchors(memberList); + memberList->setAnchors(); } void MemberGroup::writeDeclarations(OutputList &ol, @@ -112,7 +116,7 @@ void MemberGroup::writeDocumentation(OutputList &ol,const char *scopeName, } void MemberGroup::writeDocumentationPage(OutputList &ol,const char *scopeName, - const Definition *container) const + const DefinitionMutable *container) const { memberList->writeDocumentationPage(ol,scopeName,container); } @@ -217,12 +221,13 @@ void MemberGroup::distributeMemberGroupDocumentation() if (md) // distribute docs of md to other members of the list { //printf("Member %s has documentation!\n",md->name().data()); - MemberDef *omd; - for (li.toFirst();(omd=li.current());++li) + MemberDef *iomd; + for (li.toFirst();(iomd=li.current());++li) { - if (md!=omd && omd->documentation().isEmpty() && - omd->briefDescription().isEmpty() && - omd->inbodyDocumentation().isEmpty() + MemberDefMutable *omd = toMemberDefMutable(iomd); + if (omd && md!=omd && omd->documentation().isEmpty() && + omd->briefDescription().isEmpty() && + omd->inbodyDocumentation().isEmpty() ) { //printf("Copying documentation to member %s\n",omd->name().data()); diff --git a/src/membergroup.h b/src/membergroup.h index c10e421..e1dae25 100644 --- a/src/membergroup.h +++ b/src/membergroup.h @@ -35,6 +35,7 @@ class FileDef; class GroupDef; class OutputList; class Definition; +class DefinitionMutable; class FTextStream; class RefItem; @@ -59,7 +60,7 @@ class MemberGroup void writeDocumentation(OutputList &ol,const char *scopeName, const Definition *container,bool showEnumValues,bool showInline) const; void writeDocumentationPage(OutputList &ol,const char *scopeName, - const Definition *container) const; + const DefinitionMutable *container) const; void writeTagFile(FTextStream &); void addGroupedInheritedMembers(OutputList &ol,const ClassDef *cd, MemberListType lt, diff --git a/src/memberlist.cpp b/src/memberlist.cpp index b8e5e89..d8700d4 100644 --- a/src/memberlist.cpp +++ b/src/memberlist.cpp @@ -63,7 +63,7 @@ MemberList::~MemberList() delete memberGroupList; } -static int genericCompareMembers(const MemberDef *c1,const MemberDef *c2) +int genericCompareMembers(const MemberDef *c1,const MemberDef *c2) { bool sortConstructorsFirst = Config_getBool(SORT_MEMBERS_CTORS_1ST); if (sortConstructorsFirst) @@ -334,10 +334,14 @@ void MemberList::setAnonymousEnumType() MemberDef *vmd; for ( ; (vmd=vmli.current()) ; ++vmli) { - QCString vtype=vmd->typeString(); - if ((vtype.find(name))!=-1) + MemberDefMutable *vmdm = toMemberDefMutable(vmd); + if (vmdm) { - vmd->setAnonymousEnumType(md); + QCString vtype=vmd->typeString(); + if ((vtype.find(name))!=-1) + { + vmdm->setAnonymousEnumType(md); + } } } } @@ -504,6 +508,10 @@ void MemberList::writePlainDeclarations(OutputList &ol, ol.writeString("local "); } ol.writeString("enum "); + if (md->isStrong()) + { + ol.writeString("class "); + } ol.insertMemberAlign(); md->writeEnumDeclaration(ol,cd,nd,fd,gd); if (!detailsLinkable) @@ -576,7 +584,8 @@ void MemberList::writePlainDeclarations(OutputList &ol, { if (md->fromAnonymousScope() && !md->anonymousDeclShown()) { - md->setFromAnonymousScope(FALSE); + MemberDefMutable *mdm = toMemberDefMutable(md); + if (mdm) mdm->setFromAnonymousScope(FALSE); //printf("anonymous compound members\n"); if (md->isBriefSectionVisible()) { @@ -587,7 +596,7 @@ void MemberList::writePlainDeclarations(OutputList &ol, } md->writeDeclaration(ol,cd,nd,fd,gd,m_inGroup); } - md->setFromAnonymousScope(TRUE); + if (mdm) mdm->setFromAnonymousScope(TRUE); } } } @@ -747,9 +756,13 @@ void MemberList::writeDeclarations(OutputList &ol, } if (inheritedFrom && cd) { - // also add members that of this list type, that are grouped together - // in a separate list in class 'inheritedFrom' - cd->addGroupedInheritedMembers(ol,m_listType,inheritedFrom,inheritId); + const ClassDefMutable *cdm = toClassDefMutable(cd); + if (cdm) + { + // also add members that of this list type, that are grouped together + // in a separate list in class 'inheritedFrom' + cdm->addGroupedInheritedMembers(ol,m_listType,inheritedFrom,inheritId); + } } //printf("----- end writeDeclaration() ----\n"); } @@ -812,9 +825,13 @@ void MemberList::writeDocumentation(OutputList &ol, { uint overloadCount = *overloadTotalDict.find(md->name()); uint *pCount = overloadCountDict.find(md->name()); - md->writeDocumentation(this,*pCount,overloadCount,ol,scopeName,container, - m_inGroup,showEnumValues,showInline); - (*pCount)++; + MemberDefMutable *mdm = toMemberDefMutable(md); + if (mdm) + { + mdm->writeDocumentation(this,*pCount,overloadCount,ol,scopeName,container, + m_inGroup,showEnumValues,showInline); + (*pCount)++; + } } } if (memberGroupList) @@ -840,21 +857,25 @@ void MemberList::writeSimpleDocumentation(OutputList &ol, const ClassDef *cd = 0; if (container && container->definitionType()==Definition::TypeClass) { - cd = dynamic_cast<const ClassDef*>(container); + cd = toClassDef(container); } ol.startMemberDocSimple(cd && cd->isJavaEnum()); MemberListIterator mli(*this); const MemberDef *md; for ( ; (md=mli.current()) ; ++mli) { - md->writeMemberDocSimple(ol,container); + MemberDefMutable *mdm = toMemberDefMutable(md); + if (mdm) + { + mdm->writeMemberDocSimple(ol,container); + } } ol.endMemberDocSimple(cd && cd->isJavaEnum()); } // separate member pages void MemberList::writeDocumentationPage(OutputList &ol, - const char *scopeName, const Definition *container) const + const char *scopeName, const DefinitionMutable *container) const { static bool generateTreeView = Config_getBool(GENERATE_TREEVIEW); @@ -864,9 +885,11 @@ void MemberList::writeDocumentationPage(OutputList &ol, overloadTotalDict.setAutoDelete(TRUE); overloadCountDict.setAutoDelete(TRUE); MemberListIterator mli(*this); - const MemberDef *md; - for (mli.toFirst() ; (md=mli.current()) ; ++mli) + const MemberDef *imd; + for (mli.toFirst() ; (imd=mli.current()) ; ++mli) { + MemberDefMutable *md = toMemberDefMutable(imd); + if (md->isDetailedSectionLinkable()) { uint *pCount = overloadTotalDict.find(md->name()); @@ -882,8 +905,10 @@ void MemberList::writeDocumentationPage(OutputList &ol, } } - for ( mli.toFirst() ; (md=mli.current()) ; ++mli) + for ( mli.toFirst() ; (imd=mli.current()) ; ++mli) { + Definition *container_d = toDefinition(const_cast<DefinitionMutable*>(container)); + MemberDefMutable *md = toMemberDefMutable(imd); if (md->isDetailedSectionLinkable()) { uint overloadCount = *overloadTotalDict.find(md->name()); @@ -900,10 +925,11 @@ void MemberList::writeDocumentationPage(OutputList &ol, if (generateTreeView) { - md->writeDocumentation(this,*pCount,overloadCount,ol,scopeName,container,m_inGroup); + md->writeDocumentation(this,*pCount,overloadCount,ol,scopeName,container_d,m_inGroup); (*pCount)++; + ol.endContents(); - endFileWithNavPath(container,ol); + endFileWithNavPath(container_d,ol); } else { @@ -916,7 +942,7 @@ void MemberList::writeDocumentationPage(OutputList &ol, ol.writeString(" </td>\n"); ol.writeString(" <td valign=\"top\" class=\"mempage\">\n"); - md->writeDocumentation(this,*pCount,overloadCount,ol,scopeName,container,m_inGroup); + md->writeDocumentation(this,*pCount,overloadCount,ol,scopeName,container_d,m_inGroup); (*pCount)++; ol.writeString(" </td>\n"); @@ -952,10 +978,11 @@ void MemberList::addMemberGroup(MemberGroup *mg) void MemberList::addListReferences(Definition *def) { MemberListIterator mli(*this); - MemberDef *md; - for ( ; (md=mli.current()) ; ++mli) + MemberDef *imd; + for ( ; (imd=mli.current()) ; ++mli) { - if (!md->isAlias() && (md->getGroupDef()==0 || def->definitionType()==Definition::TypeGroup)) + MemberDefMutable *md = toMemberDefMutable(imd); + if (md && !md->isAlias() && (md->getGroupDef()==0 || def->definitionType()==Definition::TypeGroup)) { md->addListReference(def); const MemberList *enumFields = md->enumFieldList(); @@ -966,8 +993,12 @@ void MemberList::addListReferences(Definition *def) MemberDef *vmd; for ( ; (vmd=vmli.current()) ; ++vmli) { - //printf(" adding %s\n",vmd->name().data()); - vmd->addListReference(def); + MemberDefMutable *vmdm = toMemberDefMutable(vmd); + if (vmdm) + { + //printf(" adding %s\n",vmd->name().data()); + vmdm->addListReference(def); + } } } } @@ -986,10 +1017,14 @@ void MemberList::addListReferences(Definition *def) void MemberList::findSectionsInDocumentation(const Definition *d) { MemberListIterator mli(*this); - MemberDef *md; - for ( ; (md=mli.current()) ; ++mli) + MemberDef *imd; + for ( ; (imd=mli.current()) ; ++mli) { - md->findSectionsInDocumentation(); + MemberDefMutable *md = toMemberDefMutable(imd); + if (md) + { + md->findSectionsInDocumentation(); + } } if (memberGroupList) { @@ -1068,25 +1103,33 @@ QCString MemberList::listTypeAsString(MemberListType type) void MemberList::writeTagFile(FTextStream &tagFile) { MemberListIterator mli(*this); - MemberDef *md; - for ( ; (md=mli.current()) ; ++mli) + MemberDef *imd; + for ( ; (imd=mli.current()) ; ++mli) { - if (md->getLanguage()!=SrcLangExt_VHDL) + MemberDefMutable *md = toMemberDefMutable(imd); + if (md) { - md->writeTagFile(tagFile); - if (md->memberType()==MemberType_Enumeration && md->enumFieldList() && !md->isStrong()) + if (md->getLanguage()!=SrcLangExt_VHDL) { - MemberListIterator vmli(*md->enumFieldList()); - MemberDef *vmd; - for ( ; (vmd=vmli.current()) ; ++vmli) + md->writeTagFile(tagFile); + if (md->memberType()==MemberType_Enumeration && md->enumFieldList() && !md->isStrong()) { - vmd->writeTagFile(tagFile); + MemberListIterator vmli(*md->enumFieldList()); + MemberDef *ivmd; + for ( ; (ivmd=vmli.current()) ; ++vmli) + { + MemberDefMutable *vmd = toMemberDefMutable(ivmd); + if (vmd) + { + vmd->writeTagFile(tagFile); + } + } } } - } - else - { - VhdlDocGen::writeTagFile(md,tagFile); + else + { + VhdlDocGen::writeTagFile(md,tagFile); + } } } if (memberGroupList) @@ -1100,6 +1143,24 @@ void MemberList::writeTagFile(FTextStream &tagFile) } } +// compute the HTML anchors for a list of members +void MemberList::setAnchors() +{ + //int count=0; + MemberListIterator mli(*this); + MemberDef *md; + for (;(md=mli.current());++mli) + { + MemberDefMutable *mdm = toMemberDefMutable(md); + if (mdm && !md->isReference()) + { + mdm->setAnchor(); + } + } +} + + + //-------------------------------------------------------------------------- int MemberSDict::compareValues(const MemberDef *c1, const MemberDef *c2) const diff --git a/src/memberlist.h b/src/memberlist.h index 4038453..e62655b 100644 --- a/src/memberlist.h +++ b/src/memberlist.h @@ -1,12 +1,10 @@ /****************************************************************************** * - * - * - * Copyright (C) 1997-2015 by Dimitri van Heesch. + * Copyright (C) 1997-2020 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. * @@ -81,7 +79,7 @@ class MemberList : private QList<MemberDef> bool showEnumValues=FALSE,bool showInline=FALSE) const; void writeSimpleDocumentation(OutputList &ol,const Definition *container) const; void writeDocumentationPage(OutputList &ol, - const char *scopeName, const Definition *container) const; + const char *scopeName, const DefinitionMutable *container) const; void writeTagFile(FTextStream &); bool declVisible() const; void addMemberGroup(MemberGroup *mg); @@ -92,6 +90,7 @@ class MemberList : private QList<MemberDef> void setNeedsSorting(bool b); MemberGroupList *getMemberGroupList() const { return memberGroupList; } void setAnonymousEnumType(); + void setAnchors(); private: int compareValues(const MemberDef *item1,const MemberDef *item2) const; @@ -105,7 +104,7 @@ class MemberList : private QList<MemberDef> int m_dictCnt; int m_protoCnt; int m_defCnt; - int m_friendCnt; + int m_friendCnt; */ int m_numDecMembers; // number of members in the brief part of the memberlist int m_numDecEnumValues; @@ -145,5 +144,6 @@ class MemberSDict : public SDict<MemberDef> int compareValues(const MemberDef *item1,const MemberDef *item2) const; }; +int genericCompareMembers(const MemberDef *c1,const MemberDef *c2); #endif diff --git a/src/message.cpp b/src/message.cpp index 984a00f..e107139 100644 --- a/src/message.cpp +++ b/src/message.cpp @@ -161,7 +161,7 @@ static void format_warn(const char *file,int line,const char *text) } } -static void handle_warn_as_error(void) +static void handle_warn_as_error() { static bool warnAsError = Config_getBool(WARN_AS_ERROR); if (warnAsError) @@ -279,6 +279,12 @@ void term(const char *fmt, ...) exit(1); } +void warn_flush() +{ + fflush(warnFile); +} + + void printlex(int dbg, bool enter, const char *lexName, const char *fileName) { const char *enter_txt = "entering"; diff --git a/src/message.h b/src/message.h index e84344b..dd9eeeb 100644 --- a/src/message.h +++ b/src/message.h @@ -35,6 +35,7 @@ extern void err(const char *fmt, ...) PRINTFLIKE(1, 2); extern void err_full(const char *file,int line,const char *fmt, ...) PRINTFLIKE(3, 4); extern void term(const char *fmt, ...) PRINTFLIKE(1, 2); void initWarningFormat(); +void warn_flush(); extern void printlex(int dbg, bool enter, const char *lexName, const char *fileName); diff --git a/src/namespacedef.cpp b/src/namespacedef.cpp index 88eea5d..4b8b4d8 100644 --- a/src/namespacedef.cpp +++ b/src/namespacedef.cpp @@ -34,8 +34,21 @@ #include "membername.h" //------------------------------------------------------------------ +static QCString makeDisplayName(const NamespaceDef *nd,bool includeScope) +{ + QCString result=includeScope ? nd->name() : nd->localName(); + SrcLangExt lang = nd->getLanguage(); + QCString sep = getLanguageSpecificSeparator(lang); + if (sep!="::") + { + result = substitute(result,"::",sep); + } + //printf("makeDisplayName() %s->%s lang=%d\n",name().data(),result.data(),lang); + return result; +} +//------------------------------------------------------------------ -class NamespaceDefImpl : public DefinitionImpl, public NamespaceDef +class NamespaceDefImpl : public DefinitionMixin<NamespaceDefMutable> { public: NamespaceDefImpl(const char *defFileName,int defLine,int defColumn, @@ -58,10 +71,10 @@ class NamespaceDefImpl : public DefinitionImpl, public NamespaceDef 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 LinkedRefMap<const NamespaceDef> getUsedNamespaces() const { return m_usingDirList; } + virtual void addUsingDeclaration(const ClassDef *cd); + virtual LinkedRefMap<const ClassDef> getUsedClasses() const { return m_usingDeclList; } + virtual void combineUsingRelations(NamespaceDefSet &visitedNamespace); virtual QCString displayName(bool=TRUE) const; virtual QCString localName() const; virtual void setInline(bool isInline) { m_inline = isInline; } @@ -76,7 +89,7 @@ class NamespaceDefImpl : public DefinitionImpl, public NamespaceDef virtual void distributeMemberGroupDocumentation(); virtual void findSectionsInDocumentation(); virtual void sortMemberLists(); - virtual Definition *findInnerCompound(const char *name) const; + virtual const Definition *findInnerCompound(const char *name) const; virtual void addInnerCompound(const Definition *d); virtual void addListReferences(); virtual void setFileName(const QCString &fn); @@ -95,11 +108,8 @@ class NamespaceDefImpl : public DefinitionImpl, public NamespaceDef virtual QCString compoundTypeString() const; virtual void setMetaData(const QCString &m); - void setVisited(bool v) { m_visited = v; } - bool isVisited() const { return m_visited; } private: - bool m_visited; MemberList *createMemberList(MemberListType lt); void addMemberToList(MemberListType lt,MemberDef *md); void writeMemberDeclarations(OutputList &ol,MemberListType lt,const QCString &title); @@ -124,8 +134,8 @@ class NamespaceDefImpl : public DefinitionImpl, public NamespaceDef QCString fileName; FileList files; - NamespaceSDict *usingDirList = 0; - SDict<Definition> *usingDeclList = 0; + LinkedRefMap<const NamespaceDef> m_usingDirList; + LinkedRefMap<const ClassDef> m_usingDeclList; SDict<Definition> *m_innerCompounds = 0; MemberSDict *m_allMembersDict = 0; @@ -143,7 +153,7 @@ class NamespaceDefImpl : public DefinitionImpl, public NamespaceDef bool m_inline = false; }; -NamespaceDef *createNamespaceDef(const char *defFileName,int defLine,int defColumn, +NamespaceDefMutable *createNamespaceDef(const char *defFileName,int defLine,int defColumn, const char *name,const char *ref, const char *refFile,const char*type, bool isPublished) @@ -153,14 +163,15 @@ NamespaceDef *createNamespaceDef(const char *defFileName,int defLine,int defColu //------------------------------------------------------------------ -class NamespaceDefAliasImpl : public DefinitionAliasImpl, public NamespaceDef +class NamespaceDefAliasImpl : public DefinitionAliasMixin<NamespaceDef> { public: - NamespaceDefAliasImpl(const Definition *newScope,const NamespaceDef *nd) : DefinitionAliasImpl(newScope,nd) {} - virtual ~NamespaceDefAliasImpl() {} + NamespaceDefAliasImpl(const Definition *newScope,const NamespaceDef *nd) + : DefinitionAliasMixin(newScope,nd) { init(); } + virtual ~NamespaceDefAliasImpl() { deinit(); } virtual DefType definitionType() const { return TypeNamespace; } - const NamespaceDef *getNSAlias() const { return dynamic_cast<const NamespaceDef*>(getAlias()); } + const NamespaceDef *getNSAlias() const { return toNamespaceDef(getAlias()); } // ---- getters virtual QCString getOutputFileBase() const @@ -169,18 +180,14 @@ class NamespaceDefAliasImpl : public DefinitionAliasImpl, public NamespaceDef { return getNSAlias()->anchor(); } virtual int numDocMembers() const { return getNSAlias()->numDocMembers(); } - virtual void addUsingDirective(const NamespaceDef *nd) {} - virtual const NamespaceSDict *getUsedNamespaces() const + virtual LinkedRefMap<const NamespaceDef> getUsedNamespaces() const { return getNSAlias()->getUsedNamespaces(); } - virtual void addUsingDeclaration(const Definition *def) {} - virtual const SDict<Definition> *getUsedClasses() const + virtual LinkedRefMap<const ClassDef> getUsedClasses() const { return getNSAlias()->getUsedClasses(); } - virtual void combineUsingRelations() {} virtual QCString displayName(bool b=TRUE) const - { return getNSAlias()->displayName(b); } + { return makeDisplayName(this,b); } virtual QCString localName() const { return getNSAlias()->localName(); } - virtual void setInline(bool isInline) { } virtual bool isConstantGroup() const { return getNSAlias()->isConstantGroup(); } virtual bool isModule() const @@ -195,7 +202,7 @@ class NamespaceDefAliasImpl : public DefinitionAliasImpl, public NamespaceDef { return getNSAlias()->isLinkable(); } virtual bool hasDetailedDescription() const { return getNSAlias()->hasDetailedDescription(); } - virtual Definition *findInnerCompound(const char *name) const + virtual const Definition *findInnerCompound(const char *name) const { return getNSAlias()->findInnerCompound(name); } virtual bool subGrouping() const { return getNSAlias()->subGrouping(); } @@ -221,37 +228,15 @@ class NamespaceDefAliasImpl : public DefinitionAliasImpl, public NamespaceDef { 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 = false; }; NamespaceDef *createNamespaceDefAlias(const Definition *newScope,const NamespaceDef *nd) { - return new NamespaceDefAliasImpl(newScope,nd); + NamespaceDef *alnd = new NamespaceDefAliasImpl(newScope,nd); + //printf("alnd name=%s localName=%s qualifiedName=%s displayName()=%s\n", + // alnd->name().data(),alnd->localName().data(),alnd->qualifiedName().data(), + // alnd->displayName().data()); + return alnd; } //------------------------------------------------------------------ @@ -260,7 +245,7 @@ NamespaceDefImpl::NamespaceDefImpl(const char *df,int dl,int dc, const char *name,const char *lref, const char *fName, const char*type, bool isPublished) : - DefinitionImpl(df,dl,dc,name) + DefinitionMixin(df,dl,dc,name) ,m_isPublished(isPublished) { if (fName) @@ -284,13 +269,10 @@ NamespaceDefImpl::NamespaceDefImpl(const char *df,int dl,int dc, exceptionSDict = new ClassSDict(17); namespaceSDict = new NamespaceSDict(17); m_innerCompounds = new SDict<Definition>(17); - usingDirList = 0; - usingDeclList = 0; m_allMembersDict = 0; setReference(lref); memberGroupSDict = new MemberGroupSDict; memberGroupSDict->setAutoDelete(TRUE); - m_visited=FALSE; m_inline=FALSE; m_subGrouping=Config_getBool(SUBGROUPING); if (type && !strcmp("module", type)) @@ -319,8 +301,6 @@ NamespaceDefImpl::~NamespaceDefImpl() delete exceptionSDict; delete namespaceSDict; delete m_innerCompounds; - delete usingDirList; - delete usingDeclList; delete memberGroupSDict; delete m_allMembersDict; } @@ -349,6 +329,7 @@ void NamespaceDefImpl::distributeMemberGroupDocumentation() void NamespaceDefImpl::findSectionsInDocumentation() { + docFindSections(briefDescription(),this,docFile()); docFindSections(documentation(),this,docFile()); MemberGroupSDict::Iterator mgli(*memberGroupSDict); MemberGroup *mg; @@ -384,11 +365,11 @@ void NamespaceDefImpl::addInnerCompound(const Definition *d) m_innerCompounds->append(d->localName(),d); if (d->definitionType()==Definition::TypeNamespace) { - insertNamespace(dynamic_cast<const NamespaceDef *>(d)); + insertNamespace(toNamespaceDef(d)); } else if (d->definitionType()==Definition::TypeClass) { - insertClass(dynamic_cast<const ClassDef *>(d)); + insertClass(toClassDef(d)); } } @@ -470,6 +451,7 @@ void NamespaceDefImpl::insertMember(MemberDef *md) //printf("%s::insertMember(%s) isInline=%d hasDocs=%d\n",qPrint(name()),qPrint(md->name()), // isInline(),hasDocumentation()); if (md->isHidden()) return; + MemberDefMutable *mdm = toMemberDefMutable(md); // if this is an inline namespace that is not documented, then insert the // member in the parent scope instead @@ -480,16 +462,25 @@ void NamespaceDefImpl::insertMember(MemberDef *md) { if (outerScope->definitionType()==Definition::TypeNamespace) { - NamespaceDef *nd = dynamic_cast<NamespaceDef*>(outerScope); - nd->insertMember(md); - md->setNamespace(nd); + NamespaceDefMutable *nd = toNamespaceDefMutable(outerScope); + if (nd) + { + nd->insertMember(md); + if (mdm) + { + mdm->setNamespace(nd); + } + } } else if (outerScope->definitionType()==Definition::TypeFile) { - FileDef *fd = dynamic_cast<FileDef*>(outerScope); + FileDef *fd = toFileDef(outerScope); fd->insertMember(md); - md->setFileDef(fd); - md->setOuterScope(fd); + if (mdm) + { + mdm->setFileDef(fd); + mdm->setOuterScope(fd); + } } } } @@ -559,12 +550,16 @@ void NamespaceDefImpl::insertMember(MemberDef *md) if (outerScope->definitionType()==Definition::TypeNamespace) { aliasMd.reset(createMemberDefAlias(outerScope,md)); - dynamic_cast<NamespaceDef*>(outerScope)->insertMember(aliasMd.get()); + NamespaceDefMutable *ndm = toNamespaceDefMutable(outerScope); + if (ndm) + { + ndm->insertMember(aliasMd.get()); + } } else if (outerScope->definitionType()==Definition::TypeFile) { aliasMd.reset(createMemberDefAlias(outerScope,md)); - dynamic_cast<FileDef*>(outerScope)->insertMember(aliasMd.get()); + toFileDef(outerScope)->insertMember(aliasMd.get()); } if (aliasMd) { @@ -581,7 +576,7 @@ void NamespaceDefImpl::insertMember(MemberDef *md) void NamespaceDefImpl::computeAnchors() { MemberList *allMemberList = getMemberList(MemberListType_allMembersList); - if (allMemberList) setAnchors(allMemberList); + if (allMemberList) allMemberList->setAnchors(); } bool NamespaceDefImpl::hasDetailedDescription() const @@ -1208,33 +1203,13 @@ int NamespaceDefImpl::numDocMembers() const void NamespaceDefImpl::addUsingDirective(const NamespaceDef *nd) { - if (usingDirList==0) - { - usingDirList = new NamespaceSDict; - } - if (usingDirList->find(nd->qualifiedName())==0) - { - usingDirList->append(nd->qualifiedName(),nd); - } - //printf("%p: NamespaceDefImpl::addUsingDirective: %s:%d\n",this,name().data(),usingDirList->count()); -} - -const NamespaceSDict *NamespaceDefImpl::getUsedNamespaces() const -{ - //printf("%p: NamespaceDefImpl::getUsedNamespace: %s:%d\n",this,name().data(),usingDirList?usingDirList->count():0); - return usingDirList; + m_usingDirList.add(nd->qualifiedName(),nd); + //printf("%p: NamespaceDefImpl::addUsingDirective: %s:%d\n",this,name().data(),m_usingDirList->count()); } -void NamespaceDefImpl::addUsingDeclaration(const Definition *d) +void NamespaceDefImpl::addUsingDeclaration(const ClassDef *cd) { - if (usingDeclList==0) - { - usingDeclList = new SDict<Definition>(17); - } - if (usingDeclList->find(d->qualifiedName())==0) - { - usingDeclList->append(d->qualifiedName(),d); - } + m_usingDeclList.add(cd->qualifiedName(),cd); } QCString NamespaceDefImpl::getOutputFileBase() const @@ -1242,19 +1217,19 @@ QCString NamespaceDefImpl::getOutputFileBase() const return fileName; } -Definition *NamespaceDefImpl::findInnerCompound(const char *n) const +const Definition *NamespaceDefImpl::findInnerCompound(const char *n) const { if (n==0) return 0; - Definition *d = m_innerCompounds->find(n); + const Definition *d = m_innerCompounds->find(n); if (d==0) { - if (usingDirList) + if (!m_usingDirList.empty()) { - d = usingDirList->find(n); + d = m_usingDirList.find(n); } - if (d==0 && usingDeclList) + if (d==0 && !m_usingDeclList.empty()) { - d = usingDeclList->find(n); + d = m_usingDeclList.find(n); } } return d; @@ -1294,15 +1269,7 @@ void NamespaceDefImpl::addListReferences() QCString NamespaceDefImpl::displayName(bool includeScope) const { - QCString result=includeScope ? name() : localName(); - SrcLangExt lang = getLanguage(); - QCString sep = getLanguageSpecificSeparator(lang); - if (sep!="::") - { - result = substitute(result,"::",sep); - } - //printf("NamespaceDefImpl::displayName() %s->%s lang=%d\n",name().data(),result.data(),lang); - return result; + return makeDisplayName(this,includeScope); } QCString NamespaceDefImpl::localName() const @@ -1316,42 +1283,32 @@ QCString NamespaceDefImpl::localName() const return result; } -void NamespaceDefImpl::combineUsingRelations() +void NamespaceDefImpl::combineUsingRelations(NamespaceDefSet &visitedNamespaces) { - if (m_visited) return; // already done - m_visited=TRUE; - if (usingDirList) + if (visitedNamespaces.find(this)!=visitedNamespaces.end()) return; // already processed + visitedNamespaces.insert(this); + + LinkedRefMap<const NamespaceDef> usingDirList = m_usingDirList; + for (auto &nd : usingDirList) { - NamespaceSDict::Iterator nli(*usingDirList); - NamespaceDef *nd; - for (nli.toFirst();(nd=nli.current());++nli) + NamespaceDefMutable *ndm = toNamespaceDefMutable(nd); + if (ndm) { - nd->combineUsingRelations(); + ndm->combineUsingRelations(visitedNamespaces); } - for (nli.toFirst();(nd=nli.current());++nli) + } + + for (auto &nd : usingDirList) + { + // add used namespaces of namespace nd to this namespace + for (const auto &und : nd->getUsedNamespaces()) { - // add used namespaces of namespace nd to this namespace - if (nd->getUsedNamespaces()) - { - NamespaceSDict::Iterator unli(*nd->getUsedNamespaces()); - NamespaceDef *und; - for (unli.toFirst();(und=unli.current());++unli) - { - //printf("Adding namespace %s to the using list of %s\n",und->qualifiedName().data(),qualifiedName().data()); - addUsingDirective(und); - } - } - // add used classes of namespace nd to this namespace - if (nd->getUsedClasses()) - { - SDict<Definition>::Iterator cli(*nd->getUsedClasses()); - Definition *ucd; - for (cli.toFirst();(ucd=cli.current());++cli) - { - //printf("Adding class %s to the using list of %s\n",cd->qualifiedName().data(),qualifiedName().data()); - addUsingDeclaration(ucd); - } - } + addUsingDirective(und); + } + // add used classes of namespace nd to this namespace + for (const auto &ucd : nd->getUsedClasses()) + { + addUsingDeclaration(ucd); } } } @@ -1483,7 +1440,11 @@ void NamespaceDefImpl::addMemberToList(MemberListType lt,MemberDef *md) if (ml->listType()&MemberListType_declarationLists) { - md->setSectionList(this,ml); + MemberDefMutable *mdm = toMemberDefMutable(md); + if (mdm) + { + mdm->setSectionList(this,ml); + } } } @@ -1644,3 +1605,68 @@ void NamespaceDefImpl::setMetaData(const QCString &m) { metaData = m; } + +// --- Cast functions +// +NamespaceDef *toNamespaceDef(Definition *d) +{ + if (d && (typeid(*d)==typeid(NamespaceDefImpl) || typeid(*d)==typeid(NamespaceDefAliasImpl))) + { + return static_cast<NamespaceDef*>(d); + } + else + { + return 0; + } +} + +NamespaceDef *toNamespaceDef(DefinitionMutable *md) +{ + Definition *d = toDefinition(md); + if (d && typeid(*d)==typeid(NamespaceDefImpl)) + { + return static_cast<NamespaceDef*>(d); + } + else + { + return 0; + } +} + + +const NamespaceDef *toNamespaceDef(const Definition *d) +{ + if (d && (typeid(*d)==typeid(NamespaceDefImpl) || typeid(*d)==typeid(NamespaceDefAliasImpl))) + { + return static_cast<const NamespaceDef*>(d); + } + else + { + return 0; + } +} + +NamespaceDefMutable *toNamespaceDefMutable(Definition *d) +{ + if (d && typeid(*d)==typeid(NamespaceDefImpl)) + { + return static_cast<NamespaceDefMutable*>(d); + } + else + { + return 0; + } +} + +NamespaceDefMutable *toNamespaceDefMutable(const Definition *d) +{ + if (d && typeid(*d)==typeid(NamespaceDefImpl)) + { + return const_cast<NamespaceDefMutable*>(static_cast<const NamespaceDefMutable*>(d)); + } + else + { + return 0; + } +} + diff --git a/src/namespacedef.h b/src/namespacedef.h index a35f0b1..18171f7 100644 --- a/src/namespacedef.h +++ b/src/namespacedef.h @@ -1,12 +1,10 @@ /****************************************************************************** * - * - * - * Copyright (C) 1997-2015 by Dimitri van Heesch. + * Copyright (C) 1997-2020 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. * @@ -18,11 +16,14 @@ #ifndef NAMESPACEDEF_H #define NAMESPACEDEF_H +#include <set> + #include <qstrlist.h> #include <qdict.h> #include "sortdict.h" #include "definition.h" #include "filedef.h" +#include "linkedmap.h" class MemberList; class ClassDef; @@ -32,61 +33,41 @@ class MemberDef; class MemberGroupSDict; class NamespaceSDict; class FTextStream; +class NamespaceDef; +class NamespaceDefMutable; + +// --- Set of namespaces + +using NamespaceDefSet = std::set<const NamespaceDef*>; + /** An abstract interface of a namespace symbol. */ -class NamespaceDef : virtual public Definition +class NamespaceDef : public Definition { public: virtual ~NamespaceDef() {} virtual DefType definitionType() const = 0; + + // ---- getters virtual QCString getOutputFileBase() const = 0; virtual QCString anchor() const = 0; - virtual void insertUsedFile(FileDef *fd) = 0; - - virtual void writeDocumentation(OutputList &ol) = 0; - virtual void writeMemberPages(OutputList &ol) = 0; - virtual void writeQuickMemberLinks(OutputList &ol,const MemberDef *currentMd) const = 0; - virtual void writeTagFile(FTextStream &) = 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 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 LinkedRefMap<const NamespaceDef> getUsedNamespaces() const = 0; + virtual LinkedRefMap<const ClassDef> getUsedClasses() const = 0; virtual QCString displayName(bool=TRUE) const = 0; virtual QCString localName() const = 0; - virtual void setInline(bool isInline) = 0; - virtual bool isConstantGroup() const = 0; virtual bool isModule() const = 0; virtual bool isLibrary() const = 0; virtual bool isInline() const = 0; - virtual bool isLinkableInProject() const = 0; virtual bool isLinkable() const = 0; virtual bool hasDetailedDescription() const = 0; - virtual void addMembersToMemberGroup() = 0; - virtual void distributeMemberGroupDocumentation() = 0; - virtual void findSectionsInDocumentation() = 0; - virtual void sortMemberLists() = 0; - - virtual Definition *findInnerCompound(const char *name) const = 0; - virtual void addInnerCompound(const Definition *d) = 0; - virtual void addListReferences() = 0; - virtual void setFileName(const QCString &fn) = 0; - + virtual const Definition *findInnerCompound(const char *name) const = 0; virtual bool subGrouping() const = 0; - virtual MemberList *getMemberList(MemberListType lt) const = 0; virtual const QList<MemberList> &getMemberLists() const = 0; - virtual MemberDef *getMemberByName(const QCString &) const = 0; + virtual MemberDef *getMemberByName(const QCString &) const = 0; /*! Returns the user defined member groups */ virtual MemberGroupSDict *getMemberGroupSDict() const = 0; @@ -108,14 +89,39 @@ class NamespaceDef : virtual public Definition virtual QCString title() const = 0; virtual QCString compoundTypeString() const = 0; +}; + +class NamespaceDefMutable : public DefinitionMutable, public NamespaceDef +{ + public: + // --- setters/actions virtual void setMetaData(const QCString &m) = 0; - virtual void setVisited(bool v) = 0; - virtual bool isVisited() const = 0; + virtual void insertUsedFile(FileDef *fd) = 0; + virtual void writeDocumentation(OutputList &ol) = 0; + virtual void writeMemberPages(OutputList &ol) = 0; + virtual void writeQuickMemberLinks(OutputList &ol,const MemberDef *currentMd) const = 0; + virtual void writeTagFile(FTextStream &) = 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 void countMembers() = 0; + virtual void addMembersToMemberGroup() = 0; + virtual void distributeMemberGroupDocumentation() = 0; + virtual void findSectionsInDocumentation() = 0; + virtual void sortMemberLists() = 0; + virtual void addInnerCompound(const Definition *d) = 0; + virtual void addListReferences() = 0; + virtual void setFileName(const QCString &fn) = 0; + virtual void combineUsingRelations(NamespaceDefSet &visitedNamespace) = 0; + virtual void addUsingDirective(const NamespaceDef *nd) = 0; + virtual void addUsingDeclaration(const ClassDef *cd) = 0; + virtual void setInline(bool isInline) = 0; }; /** Factory method to create new NamespaceDef instance */ -NamespaceDef *createNamespaceDef(const char *defFileName,int defLine,int defColumn, +NamespaceDefMutable *createNamespaceDef(const char *defFileName,int defLine,int defColumn, const char *name,const char *ref=0, const char *refFile=0,const char*type=0, bool isPublished=false); @@ -123,6 +129,19 @@ NamespaceDef *createNamespaceDef(const char *defFileName,int defLine,int defColu /** Factory method to create an alias of an existing namespace. Used for inline namespaces. */ NamespaceDef *createNamespaceDefAlias(const Definition *newScope, const NamespaceDef *nd); + +// --- Cast functions + +NamespaceDef *toNamespaceDef(Definition *d); +NamespaceDef *toNamespaceDef(DefinitionMutable *d); +const NamespaceDef *toNamespaceDef(const Definition *d); +NamespaceDefMutable *toNamespaceDefMutable(Definition *d); +NamespaceDefMutable *toNamespaceDefMutable(const Definition *d); + +//------------------------------------------------------------------------ + + + /** A list of NamespaceDef objects. */ class NamespaceList : public QList<NamespaceDef> { @@ -138,7 +157,7 @@ class NamespaceList : public QList<NamespaceDef> class NamespaceListIterator : public QListIterator<NamespaceDef> { public: - NamespaceListIterator(const NamespaceList &l) : + NamespaceListIterator(const NamespaceList &l) : QListIterator<NamespaceDef>(l) {} }; diff --git a/src/outputgen.cpp b/src/outputgen.cpp index 2c3bf46..5be6817 100644 --- a/src/outputgen.cpp +++ b/src/outputgen.cpp @@ -21,6 +21,7 @@ #include <qfile.h> +#include "doxygen.h" #include "outputgen.h" #include "message.h" #include "portable.h" diff --git a/src/outputgen.h b/src/outputgen.h index 4bfed25..0d64833 100644 --- a/src/outputgen.h +++ b/src/outputgen.h @@ -62,6 +62,9 @@ class CodeOutputInterface public: virtual ~CodeOutputInterface() {} + /** Identifier for the output file */ + virtual int id() const { return 0; } + /*! Writes an code fragment to the output. This function should keep * spaces visible, should break lines at a newline and should convert * tabs to the right number of spaces. @@ -127,6 +130,16 @@ class CodeOutputInterface virtual void setCurrentDoc(const Definition *context,const char *anchor,bool isSourceFile) = 0; virtual void addWord(const char *word,bool hiPriority) = 0; + + /*! Starts a source code fragment. The fragment will be + * fed to the code parser (see code.h) for syntax highlighting + * and cross-referencing. The fragment ends by a call to + * endCodeFragment() + * @param style The kind of code fragment. + */ + virtual void startCodeFragment(const char *style) = 0; + /*! Ends a block of code */ + virtual void endCodeFragment(const char *style) = 0; }; /** Base Interface used for generating output outside of the @@ -240,20 +253,6 @@ class BaseOutputDocInterface : public CodeOutputInterface /*! Ends a section of text displayed in italic. */ virtual void endEmphasis() = 0; - /*! Starts a source code fragment. The fragment will be - * fed to the code parser (see code.h) for syntax highlighting - * and cross-referencing. The fragment ends by a call to - * endCodeFragment() - */ - virtual void startCodeFragment() = 0; - - /*! Ends a source code fragment - */ - virtual void endCodeFragment() = 0; - - - - /*! Writes a horizontal ruler to the output */ virtual void writeRuler() = 0; @@ -355,13 +354,13 @@ class OutputGenerator : public BaseOutputDocInterface //void setEncoding(const QCString &enc) { encoding = enc; } //virtual void postProcess(QByteArray &) { } - virtual void writeDoc(DocNode *,const Definition *ctx,const MemberDef *md) = 0; + virtual void writeDoc(DocNode *,const Definition *ctx,const MemberDef *md,int id) = 0; /////////////////////////////////////////////////////////////// // structural output interface /////////////////////////////////////////////////////////////// virtual void startFile(const char *name,const char *manName, - const char *title) = 0; + const char *title,int id=0) = 0; virtual void writeSearchInfo() = 0; virtual void writeFooter(const char *navPath) = 0; virtual void endFile() = 0; diff --git a/src/outputlist.cpp b/src/outputlist.cpp index 3e05dac..f968c8b 100644 --- a/src/outputlist.cpp +++ b/src/outputlist.cpp @@ -29,15 +29,19 @@ #include "definition.h" #include "docparser.h" #include "vhdldocgen.h" +#include "doxygen.h" +static AtomicInt g_outId; OutputList::OutputList() { + newId(); //printf("OutputList::OutputList()\n"); } OutputList::OutputList(const OutputList &ol) { + m_id = ol.m_id; for (const auto &og : ol.m_outputs) { m_outputs.emplace_back(og->clone()); @@ -48,6 +52,7 @@ OutputList &OutputList::operator=(const OutputList &ol) { if (this!=&ol) { + m_id = ol.m_id; for (const auto &og : ol.m_outputs) { m_outputs.emplace_back(og->clone()); @@ -61,6 +66,11 @@ OutputList::~OutputList() //printf("OutputList::~OutputList()\n"); } +void OutputList::newId() +{ + m_id = ++g_outId; +} + void OutputList::disableAllBut(OutputGenerator::OutputType o) { for (const auto &og : m_outputs) @@ -150,17 +160,17 @@ void OutputList::generateDoc(const char *fileName,int startLine, root = validatingParseDoc(fileName,startLine, ctx,md,docStr,indexWords,isExample,exampleName, singleLine,linkFromIndex,markdownSupport); - if (count>0) writeDoc(root,ctx,md); + if (count>0) writeDoc(root,ctx,md,m_id); delete root; } -void OutputList::writeDoc(DocRoot *root,const Definition *ctx,const MemberDef *md) +void OutputList::writeDoc(DocRoot *root,const Definition *ctx,const MemberDef *md,int) { for (const auto &og : m_outputs) { //printf("og->printDoc(extension=%s)\n", // ctx?ctx->getDefFileExtension().data():"<null>"); - if (og->isEnabled()) og->writeDoc(root,ctx,md); + if (og->isEnabled()) og->writeDoc(root,ctx,md,m_id); } VhdlDocGen::setFlowMember(0); } @@ -183,7 +193,7 @@ void OutputList::parseText(const QCString &textStr) { for (const auto &og : m_outputs) { - if (og->isEnabled()) og->writeDoc(root,0,0); + if (og->isEnabled()) og->writeDoc(root,0,0,m_id); } } diff --git a/src/outputlist.h b/src/outputlist.h index 003e508..7baef7a 100644 --- a/src/outputlist.h +++ b/src/outputlist.h @@ -49,6 +49,7 @@ class OutputList : public OutputDocInterface } size_t size() const { return m_outputs.size(); } + int id() const { return m_id; } void disableAllBut(OutputGenerator::OutputType o); void enableAll(); @@ -69,7 +70,7 @@ class OutputList : public OutputDocInterface bool indexWords,bool isExample,const char *exampleName /*=0*/, bool singleLine /*=FALSE*/,bool linkFromIndex /*=FALSE*/, bool markdownSupport /*=FALSE*/); - void writeDoc(DocRoot *root,const Definition *ctx,const MemberDef *md); + void writeDoc(DocRoot *root,const Definition *ctx,const MemberDef *md,int id=0); void parseText(const QCString &textStr); void startIndexSection(IndexSections is) @@ -85,7 +86,10 @@ class OutputList : public OutputDocInterface void writeStyleInfo(int part) { forall(&OutputGenerator::writeStyleInfo,part); } void startFile(const char *name,const char *manName,const char *title) - { forall(&OutputGenerator::startFile,name,manName,title); } + { + newId(); + forall(&OutputGenerator::startFile,name,manName,title,m_id); + } void writeSearchInfo() { forall(&OutputGenerator::writeSearchInfo); } void writeFooter(const char *navPath) @@ -229,10 +233,10 @@ class OutputList : public OutputDocInterface { forall(&OutputGenerator::writeRuler); } void writeAnchor(const char *fileName,const char *name) { forall(&OutputGenerator::writeAnchor,fileName,name); } - void startCodeFragment() - { forall(&OutputGenerator::startCodeFragment); } - void endCodeFragment() - { forall(&OutputGenerator::endCodeFragment); } + void startCodeFragment(const char *style) + { forall(&OutputGenerator::startCodeFragment,style); } + void endCodeFragment(const char *style) + { forall(&OutputGenerator::endCodeFragment,style); } void startCodeLine(bool hasLineNumbers) { forall(&OutputGenerator::startCodeLine,hasLineNumbers); } void endCodeLine() @@ -486,6 +490,7 @@ class OutputList : public OutputDocInterface private: void debug(); void clear(); + void newId(); // For each output format that is enabled (OutputGenerator::isEnabled()) we forward // the method call. @@ -501,6 +506,7 @@ class OutputList : public OutputDocInterface } std::vector< std::unique_ptr<OutputGenerator> > m_outputs; + int m_id; }; diff --git a/src/pagedef.cpp b/src/pagedef.cpp index 09152de..b0d375e 100644 --- a/src/pagedef.cpp +++ b/src/pagedef.cpp @@ -29,7 +29,7 @@ //------------------------------------------------------------------------------------------ -class PageDefImpl : public DefinitionImpl, public PageDef +class PageDefImpl : public DefinitionMixin<PageDef> { public: PageDefImpl(const char *f,int l,const char *n,const char *d,const char *t); @@ -56,7 +56,7 @@ class PageDefImpl : public DefinitionImpl, public PageDef virtual LocalToc localToc() const { return m_localToc; } virtual void setPageScope(Definition *d){ m_pageScope = d; } virtual Definition *getPageScope() const { return m_pageScope; } - virtual QCString displayName(bool=TRUE) const { return hasTitle() ? m_title : DefinitionImpl::name(); } + virtual QCString displayName(bool=TRUE) const { return hasTitle() ? m_title : DefinitionMixin::name(); } virtual bool showLineNo() const; virtual void writeDocumentation(OutputList &ol); virtual void writeTagFile(FTextStream &); @@ -82,7 +82,7 @@ PageDef *createPageDef(const char *f,int l,const char *n,const char *d,const cha PageDefImpl::PageDefImpl(const char *f,int l,const char *n, const char *d,const char *t) - : DefinitionImpl(f,l,1,n), m_title(t) + : DefinitionMixin(f,l,1,n), m_title(t) { setDocumentation(d,f,l); m_subPageDict = new PageSDict(7); @@ -99,6 +99,7 @@ PageDefImpl::~PageDefImpl() void PageDefImpl::findSectionsInDocumentation() { + docFindSections(briefDescription(),this,docFile()); docFindSections(documentation(),this,docFile()); } @@ -121,21 +122,23 @@ void PageDefImpl::setFileName(const char *name) m_fileName = name; } -void PageDefImpl::addInnerCompound(const Definition *const_def) +void PageDefImpl::addInnerCompound(const Definition *def) { - if (const_def->definitionType()==Definition::TypePage) + if (def->definitionType()==Definition::TypePage) { - Definition *def = const_cast<Definition*>(const_def); // uck: fix me - PageDef *pd = dynamic_cast<PageDef*>(def); - m_subPageDict->append(pd->name(),pd); - def->setOuterScope(this); - if (this==Doxygen::mainPage) + PageDef *pd = const_cast<PageDef*>(toPageDef(def)); + if (pd) { - pd->setNestingLevel(m_nestingLevel); - } - else - { - pd->setNestingLevel(m_nestingLevel+1); + m_subPageDict->append(pd->name(),pd); + pd->setOuterScope(this); + if (this==Doxygen::mainPage) + { + pd->setNestingLevel(m_nestingLevel); + } + else + { + pd->setNestingLevel(m_nestingLevel+1); + } } } } @@ -208,7 +211,11 @@ void PageDefImpl::writeDocumentation(OutputList &ol) { if (getOuterScope()!=Doxygen::globalScope && !Config_getBool(DISABLE_INDEX)) { - getOuterScope()->writeNavigationPath(ol); + DefinitionMutable *outerScope = toDefinitionMutable(getOuterScope()); + if (outerScope) + { + outerScope->writeNavigationPath(ol); + } } ol.endQuickIndices(); } @@ -229,7 +236,7 @@ void PageDefImpl::writeDocumentation(OutputList &ol) if (si->title() != manPageName) { - ol.generateDoc(docFile(),docLine(),this,0,si->title(),TRUE,FALSE, + ol.generateDoc(docFile(),getStartBodyLine(),this,0,si->title(),TRUE,FALSE, 0,TRUE,FALSE,Config_getBool(MARKDOWN_SUPPORT)); ol.endSection(si->label(),si->type()); } @@ -249,7 +256,7 @@ void PageDefImpl::writeDocumentation(OutputList &ol) ol.startPageDoc(si->title()); //ol.startSection(si->label,si->title,si->type); startTitle(ol,getOutputFileBase(),this); - ol.generateDoc(docFile(),docLine(),this,0,si->title(),TRUE,FALSE, + ol.generateDoc(docFile(),getStartBodyLine(),this,0,si->title(),TRUE,FALSE, 0,TRUE,FALSE,Config_getBool(MARKDOWN_SUPPORT)); //stringToSearchIndex(getOutputFileBase(), // theTranslator->trPage(TRUE,TRUE)+" "+si->title, @@ -398,3 +405,31 @@ bool PageDefImpl::hasTitle() const return !m_title.isEmpty() && m_title.lower()!="notitle"; } +// --- Cast functions + +PageDef *toPageDef(Definition *d) +{ + if (d==0) return 0; + if (d && typeid(*d)==typeid(PageDefImpl)) + { + return static_cast<PageDef*>(d); + } + else + { + return 0; + } +} + +const PageDef *toPageDef(const Definition *d) +{ + if (d==0) return 0; + if (d && typeid(*d)==typeid(PageDefImpl)) + { + return static_cast<const PageDef*>(d); + } + else + { + return 0; + } +} + diff --git a/src/pagedef.h b/src/pagedef.h index e4d0268..03cc5a8 100644 --- a/src/pagedef.h +++ b/src/pagedef.h @@ -1,12 +1,10 @@ /****************************************************************************** * - * - * - * Copyright (C) 1997-2015 by Dimitri van Heesch. + * Copyright (C) 1997-2020 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,7 +24,7 @@ class OutputList; class FTextStream; /** @brief A model of a page symbol. */ -class PageDef : virtual public Definition +class PageDef : public DefinitionMutable, public Definition { public: virtual ~PageDef() {} @@ -67,6 +65,13 @@ class PageDef : virtual public Definition PageDef *createPageDef(const char *f,int l,const char *n,const char *d,const char *t); +// --- Cast functions + +PageDef *toPageDef(Definition *d); +const PageDef *toPageDef(const Definition *d); + +// ------------------ + class PageSDict : public SDict<PageDef> { public: diff --git a/src/parserintf.h b/src/parserintf.h index 911b707..2fde2f1 100644 --- a/src/parserintf.h +++ b/src/parserintf.h @@ -137,6 +137,7 @@ class CodeParserInterface //----------------------------------------------------------------------------- using OutlineParserFactory = std::function<std::unique_ptr<OutlineParserInterface>()>; +using CodeParserFactory = std::function<std::unique_ptr<CodeParserInterface>()>; /** \brief Manages programming language parsers. * @@ -145,38 +146,42 @@ using OutlineParserFactory = std::function<std::unique_ptr<OutlineParserInterfac */ class ParserManager { - public: struct ParserPair { - ParserPair(OutlineParserFactory opf, std::unique_ptr<CodeParserInterface> cpi) - : outlineParserFactory(opf), codeParserInterface(std::move(cpi)) + ParserPair(OutlineParserFactory opf, CodeParserFactory cpf, const QCString pn) + : outlineParserFactory(opf), codeParserFactory(cpf), parserName(pn) { } OutlineParserFactory outlineParserFactory; - std::unique_ptr<CodeParserInterface> codeParserInterface; + CodeParserFactory codeParserFactory; + QCString parserName; }; + public: + /** Create the parser manager + * @param outlineParserFactory the fallback outline parser factory to use for unknown extensions + * @param codeParserFactory the fallback code parser factory to use for unknown extensions + */ ParserManager(OutlineParserFactory outlineParserFactory, - std::unique_ptr<CodeParserInterface> codeParserInterface) - : m_defaultParsers(outlineParserFactory,std::move(codeParserInterface)) + CodeParserFactory codeParserFactory) + : m_defaultParsers(outlineParserFactory,codeParserFactory, "") { } /** Registers an additional parser. * @param[in] name A symbolic name of the parser, i.e. "c", * "python", "fortran", "vhdl", ... - * @param[in] outlineParser The language parser (scanner) that is to be used for the - * given name. - * @param[in] codeParser The code parser that is to be used for the - * given name. + * @param[in] outlineParserFactory A factory method to create a language parser (scanner) that + * is to be used for the given name. + * @param[in] codeParserFactory A factory method to create a code parser that is to be used + * for the given name. */ void registerParser(const char *name,OutlineParserFactory outlineParserFactory, - std::unique_ptr<CodeParserInterface> codeParserInterface) + CodeParserFactory codeParserFactory) { - m_parsers.emplace(std::string(name), - ParserPair(outlineParserFactory,std::move(codeParserInterface))); + m_parsers.emplace(std::string(name),ParserPair(outlineParserFactory,codeParserFactory,name)); } /** Registers a file \a extension with a parser with name \a parserName. @@ -198,7 +203,7 @@ class ParserManager return TRUE; } - /** Gets the interface to the parser associated with given \a extension. + /** Gets the interface to the parser associated with a given \a extension. * If there is no parser explicitly registered for the supplied extension, * the interface to the default parser will be returned. */ @@ -207,13 +212,29 @@ class ParserManager return getParsers(extension).outlineParserFactory(); } - /** Gets the interface to the parser associated with given \a extension. + /** Gets the interface to the parser associated with a given \a extension. * If there is no parser explicitly registered for the supplied extension, * the interface to the default parser will be returned. */ - CodeParserInterface &getCodeParser(const char *extension) + std::unique_ptr<CodeParserInterface> getCodeParser(const char *extension) + { + auto factory = getCodeParserFactory(extension); + return factory(); + } + + /** Get the factory for create code parser objects with a given \a extension. */ + CodeParserFactory &getCodeParserFactory(const char *extension) + { + return getParsers(extension).codeParserFactory; + } + + /** Gets the name of the parser associated with given \a extension. + * If there is no parser explicitly registered for the supplied extension, + * te empty string will be reurned. + */ + QCString getParserName(const char *extension) { - return *getParsers(extension).codeParserInterface; + return getParsers(extension).parserName; } private: diff --git a/src/perlmodgen.cpp b/src/perlmodgen.cpp index a6e9f22..c2d120f 100644 --- a/src/perlmodgen.cpp +++ b/src/perlmodgen.cpp @@ -1569,6 +1569,7 @@ void PerlModGenerator::generatePerlModForMember(const MemberDef *md,const Defini // (templateArguments(), definitionTemplateParameterLists()) QCString memType; + QCString name; bool isFunc=FALSE; switch (md->memberType()) { @@ -1590,9 +1591,12 @@ void PerlModGenerator::generatePerlModForMember(const MemberDef *md,const Defini case MemberType_Dictionary: memType="dictionary"; break; } + name = md->name(); + if (md->isAnonymous()) name = "__unnamed" + name.right(name.length() - 1)+"__"; + m_output.openHash() .addFieldQuotedString("kind", memType) - .addFieldQuotedString("name", md->name()) + .addFieldQuotedString("name", name) .addFieldQuotedString("virtualness", getVirtualnessName(md->virtualness())) .addFieldQuotedString("protection", getProtectionName(md->protection())) .addFieldBoolean("static", md->isStatic()); @@ -1696,14 +1700,12 @@ void PerlModGenerator::generatePerlModForMember(const MemberDef *md,const Defini } } - /* DGA: fix #7495 Perlmod does not generate bitfield */ if (md->memberType() == MemberType_Variable && md->bitfieldString()) { - QCString bitfield = md->bitfieldString(); - if (bitfield.at(0) == ':') bitfield = bitfield.mid(1); - m_output.addFieldQuotedString("bitfield", bitfield); + QCString bitfield = md->bitfieldString(); + if (bitfield.at(0) == ':') bitfield = bitfield.mid(1); + m_output.addFieldQuotedString("bitfield", bitfield); } - /* DGA: end of fix #7495 */ const MemberDef *rmd = md->reimplements(); if (rmd) @@ -1830,32 +1832,34 @@ void PerlModGenerator::generatePerlModForClass(const ClassDef *cd) m_output.openHash() .addFieldQuotedString("name", cd->name()); + /* DGA: fix # #7547 Perlmod does not generate "kind" information to discriminate struct/union */ + m_output.addFieldQuotedString("kind", cd->compoundTypeString()); - if (cd->baseClasses()) + if (!cd->baseClasses().empty()) { m_output.openList("base"); - BaseClassListIterator bcli(*cd->baseClasses()); - BaseClassDef *bcd; - for (bcli.toFirst();(bcd=bcli.current());++bcli) + for (const auto &bcd : cd->baseClasses()) + { m_output.openHash() - .addFieldQuotedString("name", bcd->classDef->displayName()) - .addFieldQuotedString("virtualness", getVirtualnessName(bcd->virt)) - .addFieldQuotedString("protection", getProtectionName(bcd->prot)) + .addFieldQuotedString("name", bcd.classDef->displayName()) + .addFieldQuotedString("virtualness", getVirtualnessName(bcd.virt)) + .addFieldQuotedString("protection", getProtectionName(bcd.prot)) .closeHash(); + } m_output.closeList(); } - if (cd->subClasses()) + if (!cd->subClasses().empty()) { m_output.openList("derived"); - BaseClassListIterator bcli(*cd->subClasses()); - BaseClassDef *bcd; - for (bcli.toFirst();(bcd=bcli.current());++bcli) + for (const auto &bcd : cd->subClasses()) + { m_output.openHash() - .addFieldQuotedString("name", bcd->classDef->displayName()) - .addFieldQuotedString("virtualness", getVirtualnessName(bcd->virt)) - .addFieldQuotedString("protection", getProtectionName(bcd->prot)) + .addFieldQuotedString("name", bcd.classDef->displayName()) + .addFieldQuotedString("virtualness", getVirtualnessName(bcd.virt)) + .addFieldQuotedString("protection", getProtectionName(bcd.prot)) .closeHash(); + } m_output.closeList(); } diff --git a/src/portable.cpp b/src/portable.cpp index d3799c7..0ffbd49 100644 --- a/src/portable.cpp +++ b/src/portable.cpp @@ -196,7 +196,7 @@ int Portable::system(const char *command,const char *args,bool commandHasConsole } -unsigned int Portable::pid(void) +unsigned int Portable::pid() { unsigned int pid; #if !defined(_WIN32) || defined(__CYGWIN__) @@ -322,7 +322,7 @@ FILE *Portable::fopen(const char *fileName,const char *mode) #endif } -char Portable::pathSeparator(void) +char Portable::pathSeparator() { #if defined(_WIN32) && !defined(__CYGWIN__) return '\\'; @@ -331,7 +331,7 @@ char Portable::pathSeparator(void) #endif } -char Portable::pathListSeparator(void) +char Portable::pathListSeparator() { #if defined(_WIN32) && !defined(__CYGWIN__) return ';'; @@ -386,7 +386,7 @@ bool Portable::checkForExecutable(const char *fileName) #endif } -const char *Portable::ghostScriptCommand(void) +const char *Portable::ghostScriptCommand() { #if defined(_WIN32) && !defined(__CYGWIN__) static char *gsexe = NULL; @@ -410,7 +410,7 @@ const char *Portable::ghostScriptCommand(void) #endif } -const char *Portable::commandExtension(void) +const char *Portable::commandExtension() { #if defined(_WIN32) && !defined(__CYGWIN__) return ".exe"; @@ -419,7 +419,7 @@ const char *Portable::commandExtension(void) #endif } -bool Portable::fileSystemIsCaseSensitive(void) +bool Portable::fileSystemIsCaseSensitive() { #if defined(_WIN32) || defined(macintosh) || defined(__MACOSX__) || defined(__APPLE__) || defined(__CYGWIN__) return FALSE; @@ -446,17 +446,17 @@ int Portable::pclose(FILE *stream) #endif } -void Portable::sysTimerStart(void) +void Portable::sysTimerStart() { g_time.start(); } -void Portable::sysTimerStop(void) +void Portable::sysTimerStop() { g_sysElapsedTime+=((double)g_time.elapsed())/1000.0; } -double Portable::getSysElapsedTime(void) +double Portable::getSysElapsedTime() { return g_sysElapsedTime; } @@ -492,7 +492,7 @@ bool Portable::isAbsolutePath(const char *fileName) * * This routine was inspired by the cause for bug 766059 was that in the Windows path there were forward slashes. */ -void Portable::correct_path(void) +void Portable::correct_path() { #if defined(_WIN32) && !defined(__CYGWIN__) const char *p = Portable::getenv("PATH"); @@ -511,7 +511,7 @@ void Portable::unlink(const char *fileName) #endif } -void Portable::setShortDir(void) +void Portable::setShortDir() { #if defined(_WIN32) && !defined(__CYGWIN__) long length = 0; diff --git a/src/portable.h b/src/portable.h index bf6cfea..d2b3036 100644 --- a/src/portable.h +++ b/src/portable.h @@ -20,7 +20,7 @@ typedef off_t portable_off_t; namespace Portable { int system(const char *command,const char *args,bool commandHasConsole=true); - unsigned int pid(void); + unsigned int pid(); const char * getenv(const char *variable); void setenv(const char *variable,const char *value); void unsetenv(const char *variable); @@ -28,20 +28,20 @@ namespace Portable portable_off_t ftell(FILE *f); FILE * fopen(const char *fileName,const char *mode); void unlink(const char *fileName); - char pathSeparator(void); - char pathListSeparator(void); - const char * ghostScriptCommand(void); - const char * commandExtension(void); + char pathSeparator(); + char pathListSeparator(); + const char * ghostScriptCommand(); + const char * commandExtension(); bool fileSystemIsCaseSensitive(); FILE * popen(const char *name,const char *type); int pclose(FILE *stream); - void sysTimerStart(void); - void sysTimerStop(void); - double getSysElapsedTime(void); + void sysTimerStart(); + void sysTimerStop(); + double getSysElapsedTime(); void sleep(int ms); bool isAbsolutePath(const char *fileName); - void correct_path(void); - void setShortDir(void); + void correct_path(); + void setShortDir(); const char * strnstr(const char *haystack, const char *needle, size_t haystack_len); const char * devNull(); bool checkForExecutable(const char *fileName); @@ -2416,6 +2416,10 @@ static bool expandExpression(yyscan_t yyscanner,QCString &expr,QCString *rest,in expanded = expandExpression(yyscanner,resultExpr,&restExpr,0,level+1); state->expandedDict.erase(toStdString(macroName)); } + else if (def && def->nonRecursive) + { + expanded = true; + } if (expanded) { expr=expr.left(p)+resultExpr+restExpr; diff --git a/src/pycode.h b/src/pycode.h index e3a01b4..8bce2a9 100644 --- a/src/pycode.h +++ b/src/pycode.h @@ -1,12 +1,10 @@ /****************************************************************************** * - * - * - * Copyright (C) 1997-2015 by Dimitri van Heesch. + * Copyright (C) 1997-2020 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. * @@ -36,6 +34,8 @@ class Definition; class PythonCodeParser : public CodeParserInterface { public: + PythonCodeParser(); + virtual ~PythonCodeParser(); void parseCode(CodeOutputInterface &codeOutIntf, const char *scopeName, const QCString &input, @@ -52,6 +52,9 @@ class PythonCodeParser : public CodeParserInterface bool collectXrefs=TRUE ); void resetCodeParserState(); + private: + struct Private; + std::unique_ptr<Private> p; }; diff --git a/src/pycode.l b/src/pycode.l index 8cb85a3..b7f3b66 100644 --- a/src/pycode.l +++ b/src/pycode.l @@ -1,12 +1,10 @@ /****************************************************************************** * - * - * - * Copyright (C) 1997-2015 by Dimitri van Heesch. + * Copyright (C) 1997-2020 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. * @@ -23,6 +21,8 @@ %option never-interactive %option prefix="pycodeYY" +%option reentrant +%option extra-type="struct pycodeYY_state *" %option noyy_top_state %top{ #include <stdint.h> @@ -30,12 +30,15 @@ %{ +#include <vector> +#include <unordered_map> +#include <string> +#include <stack> + #include <stdio.h> -#include <qvaluestack.h> #include "pycode.h" #include "message.h" - #include "scanner.h" #include "entry.h" #include "doxygen.h" @@ -49,6 +52,8 @@ #include "filedef.h" #include "namespacedef.h" #include "tooltip.h" +#include "scopedtypevariant.h" +#include "symbolresolver.h" // Toggle for some debugging info //#define DBG_CTX(x) fprintf x @@ -59,279 +64,911 @@ #define USE_STATE2STRING 0 -static ClassSDict g_codeClassSDict(17); -static QCString g_curClassName; -static QStrList g_curClassBases; - - -static CodeOutputInterface * g_code; -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 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 -static FileDef * g_sourceFileDef; -static Definition * g_currentDefinition; -static MemberDef * g_currentMemberDef; -static bool g_includeCodeFragment; -static QCString g_realScope; -//static bool g_insideBody; -static int g_bodyCurlyCount; -static bool g_searchingForBody; -static QCString g_classScope; -static int g_paramParens; -//static int g_anchorCount; - -static bool g_exampleBlock; -static QCString g_exampleName; - -static QCString g_type; -static QCString g_name; - -static bool g_doubleStringIsDoc; -static bool g_doubleQuote; -static bool g_noSuiteFound; -static int g_stringContext; - -static QValueStack<uint> g_indents; //!< Tracks indentation levels for scoping in python - -static QCString g_docBlock; //!< contents of all lines of a documentation block -static bool g_endComment; - -static void endFontClass(); -static void adjustScopesAndSuites(unsigned indentLength); + +struct pycodeYY_state +{ + std::unordered_map< std::string, ScopedTypeVariant > codeClassMap; + QCString curClassName; + QStrList curClassBases; + + CodeOutputInterface * code = 0; + const char * inputString = 0; //!< the code fragment as text + yy_size_t inputPosition = 0; //!< read offset during parsing + const char * currentFontClass = 0; + bool needsTermination = FALSE; + const Definition *searchCtx = 0; + bool collectXRefs = FALSE; + int inputLines = 0; //!< number of line in the code fragment + int yyLineNr = 0; //!< current line number + FileDef * sourceFileDef = 0; + Definition * currentDefinition = 0; + MemberDef * currentMemberDef = 0; + bool includeCodeFragment = FALSE; + QCString realScope; + int bodyCurlyCount = 0; + bool searchingForBody = FALSE; + QCString classScope; + int paramParens = 0; + + bool exampleBlock = FALSE; + QCString exampleName; + + QCString type; + QCString name; + + bool doubleStringIsDoc = FALSE; + bool doubleQuote = FALSE; + bool noSuiteFound = FALSE; + int stringContext = 0; + + std::stack<yy_size_t> indents; //!< Tracks indentation levels for scoping in python + + QCString docBlock; //!< contents of all lines of a documentation block + bool endComment = FALSE; + VariableContext theVarContext; + CallContext theCallContext; + SymbolResolver symbolResolver; +}; + #if USE_STATE2STRING static const char *stateToString(int state); #endif +static void startCodeLine(yyscan_t yyscanner); +static int countLines(yyscan_t yyscanner); +static void setCurrentDoc(yyscan_t yyscanner, const QCString &anchor); +static void addToSearchIndex(yyscan_t yyscanner, const char *text); +static const ClassDef *stripClassName(yyscan_t yyscanner,const char *s,Definition *d); +static void codify(yyscan_t yyscanner,const char* text); +static void endCodeLine(yyscan_t yyscanner); +static void nextCodeLine(yyscan_t yyscanner); +static void writeMultiLineCodeLink(yyscan_t yyscanner, CodeOutputInterface &ol, const Definition *d, const char *text); +static void startFontClass(yyscan_t yyscanner,const char *s); +static void endFontClass(yyscan_t yyscanner); +static void codifyLines(yyscan_t yyscanner,const char *text); +static bool getLinkInScope(yyscan_t yyscanner, const QCString &c, const QCString &m, + const char *memberText, CodeOutputInterface &ol, const char *text); +static bool getLink(yyscan_t yyscanner, const char *className, const char *memberName, + CodeOutputInterface &ol, const char *text=0); +static void generateClassOrGlobalLink(yyscan_t yyscanner, CodeOutputInterface &ol, + const char *clName, bool typeOnly=FALSE); +static void generateFunctionLink(yyscan_t yyscanner, CodeOutputInterface &ol, + const char *funcName); +static bool findMemberLink(yyscan_t yyscanner, CodeOutputInterface &ol, + Definition *sym, const char *symName); +static void findMemberLink(yyscan_t yyscanner, CodeOutputInterface &ol, + const char *symName); +static void adjustScopesAndSuites(yyscan_t yyscanner,unsigned indentLength); +static yy_size_t yyread(yyscan_t yyscanner,char *buf,yy_size_t max_size); + +#if 0 // TODO: call me to store local variables and get better syntax highlighting, see code.l +static void addVariable(yyscan_t yyscanner, QCString type, QCString name); +#endif -/*! Represents a stack of variable to class mappings as found in the - * code. Each scope is enclosed in pushScope() and popScope() calls. - * Variables are added by calling addVariables() and one can search - * for variable using findVariable(). - */ -class PyVariableContext -{ - public: - static const ClassDef *dummyContext; - class Scope : public SDict<ClassDef> - { - public: - Scope() : SDict<ClassDef>(17) {} - }; - - PyVariableContext() - { - m_scopes.setAutoDelete(TRUE); - } +//------------------------------------------------------------------- - virtual ~PyVariableContext() - { - } - - void pushScope() - { - m_scopes.append(new Scope); - } +static std::mutex g_searchIndexMutex; +static std::mutex g_docCrossReferenceMutex; +static std::mutex g_countFlowKeywordsMutex; - void popScope() - { - if (m_scopes.count()>0) - { - m_scopes.remove(m_scopes.count()-1); - } - } +//------------------------------------------------------------------- - void clear() - { - m_scopes.clear(); - m_globalScope.clear(); - } +#undef YY_INPUT +#define YY_INPUT(buf,result,max_size) result=yyread(yyscanner,buf,max_size); - void clearExceptGlobal() - { - m_scopes.clear(); - } +%} - void addVariable(const QCString &type,const QCString &name); - ClassDef *findVariable(const QCString &name); - - private: - Scope m_globalScope; - QList<Scope> m_scopes; -}; -void PyVariableContext::addVariable(const QCString &type,const QCString &name) +BB [ \t]+ +B [ \t]* +NEWLINE \n + +DIGIT [0-9] +LETTER [A-Za-z\x80-\xFF] +NONEMPTY [A-Za-z0-9_\x80-\xFF] +EXPCHAR [#(){}\[\],:.%/\\=`*~|&<>!;+-] +NONEMPTYEXP [^ \t\n:] +PARAMNONEMPTY [^ \t\n():] +IDENTIFIER ({LETTER}|"_")({LETTER}|{DIGIT}|"_")* +SCOPE {IDENTIFIER}("."{IDENTIFIER})* +CALLANY "("[^)]*")" +BORDER ([^A-Za-z0-9]) + +POUNDCOMMENT "##" + +TRISINGLEQUOTE "'''" +TRIDOUBLEQUOTE "\"\"\"" +LONGSTRINGCHAR [^\\"'] +ESCAPESEQ ("\\")(.) +LONGSTRINGITEM ({LONGSTRINGCHAR}|{ESCAPESEQ}) +SMALLQUOTE ("\"\""|"\""|"'"|"''") +LONGSTRINGBLOCK ({LONGSTRINGITEM}+|{SMALLQUOTE}) + +SHORTSTRING ("'"{SHORTSTRINGITEM}*"'"|'"'{SHORTSTRINGITEM}*'"') +SHORTSTRINGITEM ({SHORTSTRINGCHAR}|{ESCAPESEQ}) +SHORTSTRINGCHAR [^\\\n"] +STRINGLITERAL {STRINGPREFIX}?( {SHORTSTRING} | {LONGSTRING}) +STRINGPREFIX ("r"|"u"|"ur"|"R"|"U"|"UR"|"Ur"|"uR") +KEYWORD ("lambda"|"import"|"class"|"assert"|"with"|"as"|"from"|"global"|"def"|"True"|"False") +FLOWKW ("or"|"and"|"is"|"not"|"print"|"for"|"in"|"if"|"try"|"except"|"yield"|"raise"|"break"|"continue"|"pass"|"if"|"return"|"while"|"elif"|"else"|"finally") +QUOTES ("\""[^"]*"\"") +SINGLEQUOTES ("'"[^']*"'") + +LONGINTEGER {INTEGER}("l"|"L") +INTEGER ({DECIMALINTEGER}|{OCTINTEGER}|{HEXINTEGER}) +DECIMALINTEGER ({NONZERODIGIT}{DIGIT}*|"0") +OCTINTEGER "0"{OCTDIGIT}+ +HEXINTEGER "0"("x"|"X"){HEXDIGIT}+ +NONZERODIGIT [1-9] +OCTDIGIT [0-7] +HEXDIGIT ({DIGIT}|[a-f]|[A-F]) +FLOATNUMBER ({POINTFLOAT}|{EXPONENTFLOAT}) +POINTFLOAT ({INTPART}?{FRACTION}|{INTPART}".") +EXPONENTFLOAT ({INTPART}|{POINTFLOAT}){EXPONENT} +INTPART {DIGIT}+ +FRACTION "."{DIGIT}+ +EXPONENT ("e"|"E")("+"|"-")?{DIGIT}+ +IMAGNUMBER ({FLOATNUMBER}|{INTPART})("j"|"J") +ATOM ({IDENTIFIER}|{LITERAL}|{ENCLOSURE}) +ENCLOSURE ({PARENTH_FORM}|{LIST_DISPLAY}|{DICT_DISPLAY}|{STRING_CONVERSION}) +LITERAL ({STRINGLITERAL}|{INTEGER}|{LONGINTEGER}|{FLOATNUMBER}|{IMAGNUMBER}) +PARENTH_FORM "("{EXPRESSION_LIST}?")" +TEST ({AND_TEST}("or"{AND_TEST})*|{LAMBDA_FORM}) +TESTLIST {TEST}( ","{TEST})*","? +LIST_DISPLAY "["{LISTMAKER}?"]" +LISTMAKER {EXPRESSION}({LIST_FOR}|(","{EXPRESSION})*","?) +LIST_ITER ({LIST_FOR}|{LIST_IF}) +LIST_FOR "for"{EXPRESSION_LIST}"in"{TESTLIST}{LIST_ITER}? +LIST_IF "if"{TEST}{LIST_ITER}? +DICT_DISPLAY "\{"{KEY_DATUM_LIST}?"\}" +KEY_DATUM_LIST {KEY_DATUM}(","{KEY_DATUM})*","? +KEY_DATUM {EXPRESSION}":"{EXPRESSION} +STRING_CONVERSION "`"{EXPRESSION_LIST}"`" +PRIMARY ({ATOM}|{ATTRIBUTEREF}|{SUBSCRIPTION}|{SLICING}|{CALL}) +ATTRIBUTEREF {PRIMARY}"."{IDENTIFIER} +SUBSCRIPTION {PRIMARY}"["{EXPRESSION_LIST}"]" +SLICING ({SIMPLE_SLICING}|{EXTENDED_SLICING}) +SIMPLE_SLICING {PRIMARY}"["{SHORT_SLICE}"]" +EXTENDED_SLICING {PRIMARY}"["{SLICE_LIST}"]" +SLICE_LIST {SLICE_ITEM}(","{SLICE_ITEM})*","? +SLICE_ITEM ({EXPRESSION}|{PROPER_SLICE}|{ELLIPSIS}) +PROPER_SLICE ({SHORT_SLICE}|{LONG_SLICE}) +SHORT_SLICE {LOWER_BOUND}?":"{UPPER_BOUND}? +LONG_SLICE {SHORT_SLICE}":"{STRIDE}? +LOWER_BOUND {EXPRESSION} +UPPER_BOUND {EXPRESSION} +STRIDE {EXPRESSION} +ELLIPSIS "..." +CALL {PRIMARY}"("({ARGUMENT_LIST}","?)?")" +ARGUMENT_LIST ({POSITIONAL_ARGUMENTS}(","{KEYWORD_ARGUMENTS})?(",""*"{EXPRESSION})?(",""**"{EXPRESSION})?|{KEYWORD_ARGUMENTS}(",""*"{EXPRESSION})?(",""**"{EXPRESSION})?|"*"{EXPRESSION}(",""**"{EXPRESSION})?|"**"{EXPRESSION}) +POSITIONAL_ARGUMENTS {EXPRESSION}(","{EXPRESSION})* +KEYWORD_ARGUMENTS {KEYWORD_ITEM}(","{KEYWORD_ITEM})* +KEYWORD_ITEM {IDENTIFIER}"="{EXPRESSION} +POWER {PRIMARY}("**"{U_EXPR})? +U_EXPR ({POWER}|"-"{U_EXPR}|"+"{U_EXPR}|"\~"{U_EXPR}) +M_EXPR ({U_EXPR}|{M_EXPR}"*"{U_EXPR}|{M_EXPR}"//"{U_EXPR}|{M_EXPR}"/"{U_EXPR}|{M_EXPR}"\%"{U_EXPR}) +A_EXPR ({M_EXPR}|{A_EXPR}"+"{M_EXPR}|{A_EXPR}"-"{M_EXPR} +SHIFT_EXPR ({A_EXPR}|{SHIFT_EXPR}("<<"|">>"){A_EXPR}) +AND_EXPR ({SHIFT_EXPR}|{AND_EXPR}"\;SPMamp;"{SHIFT_EXPR} +XOR_EXPR ({AND_EXPR}|{XOR_EXPR}"\textasciicircum"{AND_EXPR}) +OR_EXPR ({XOR_EXPR}|{OR_EXPR}"|"{ XOR_EXPR}) + +COMPARISON {OR_EXPR}({COMP_OPERATOR}{OR_EXPR})* +COMP_OPERATOR ("<"|">"|"=="|">="|"<="|"<>"|"!="|"is""not"?|"not"?"in") +EXPRESSION ({OR_TEST}|{LAMBDA_FORM}) +OR_TEST ({AND_TEST}|{OR_TEST}"or"{AND_TEST}) +AND_TEST ({NOT_TEST}|{AND_TEST}"and"{NOT_TEST}) +NOT_TEST ({COMPARISON}|"not"{NOT_TEST}) +LAMBDA_FORM "lambda"{PARAMETER_LIST}?":"{EXPRESSION} +EXPRESSION_LIST {EXPRESSION}(","{EXPRESSION})*","? +SIMPLE_STMT ({EXPRESSION_STMT}|{ASSERT_STMT}|{ASSIGNMENT_STMT}|{AUGMENTED_ASSIGNMENT_STMT}|{PASS_STMT}|{DEL_STMT}|{PRINT_STMT}|{RETURN_STMT}|{YIELD_STMT}|{RAISE_STMT}|{BREAK_STMT}|{CONTINUE_STMT}|{IMPORT_STMT}|{GLOBAL_STMT}|{EXEC_STMT}) +EXPRESSION_STMT {EXPRESSION_LIST} +ASSERT_STMT "assert"{EXPRESSION}(","{EXPRESSION})? +ASSIGNMENT_STMT ({TARGET_LIST}"=")+{EXPRESSION_LIST} +TARGET_LIST {TARGET}(","{TARGET})*","? +TARGET ({IDENTIFIER}|"("{TARGET_LIST}")"|"["{TARGET_LIST}"]"|{ATTRIBUTEREF}|{SUBSCRIPTION}|{SLICING}) + +%option noyywrap +%option stack + +%x Body + +%x FunctionDec +%x FunctionParams + +%x ClassDec +%x ClassInheritance + +%x Suite +%x SuiteCaptureIndent +%x SuiteStart +%x SuiteMaintain +%x SuiteContinuing + +%x LongString + +%x SingleQuoteString +%x DoubleQuoteString +%x TripleString + +%x DocBlock +%% + +<Body,Suite>{ + "def"{BB} { + startFontClass(yyscanner,"keyword"); + codify(yyscanner,yytext); + endFontClass(yyscanner); + BEGIN( FunctionDec ); + } + + "class"{BB} { + startFontClass(yyscanner,"keyword"); + codify(yyscanner,yytext); + endFontClass(yyscanner); + BEGIN( ClassDec ); + } + "None" { + startFontClass(yyscanner,"keywordtype"); + codify(yyscanner,yytext); + endFontClass(yyscanner); + } + "self."{IDENTIFIER}/"."({IDENTIFIER}".")*{IDENTIFIER}"(" { + codify(yyscanner,"self."); + findMemberLink(yyscanner,*yyextra->code,&yytext[5]); + } + "self."{IDENTIFIER}/"(" { + codify(yyscanner,"self."); + findMemberLink(yyscanner,*yyextra->code,&yytext[5]); + } + "self."{IDENTIFIER}/"."({IDENTIFIER}".")*{IDENTIFIER} { + codify(yyscanner,"self."); + findMemberLink(yyscanner,*yyextra->code,&yytext[5]); + } + "self."{IDENTIFIER} { + codify(yyscanner,"self."); + findMemberLink(yyscanner,*yyextra->code,&yytext[5]); + } + "cls."{IDENTIFIER}/"."({IDENTIFIER}".")*{IDENTIFIER}"(" { + codify(yyscanner,"cls."); + findMemberLink(yyscanner,*yyextra->code,&yytext[4]); + } + "cls."{IDENTIFIER}/"(" { + codify(yyscanner,"cls."); + findMemberLink(yyscanner,*yyextra->code,&yytext[4]); + } + "cls."{IDENTIFIER}/"."({IDENTIFIER}".")*{IDENTIFIER} { + codify(yyscanner,"cls."); + findMemberLink(yyscanner,*yyextra->code,&yytext[4]); + } + "cls."{IDENTIFIER} { + codify(yyscanner,"cls."); + findMemberLink(yyscanner,*yyextra->code,&yytext[4]); + } + "@"{SCOPE}{CALLANY}? { // decorator + startFontClass(yyscanner,"preprocessor"); + codify(yyscanner,yytext); + endFontClass(yyscanner); + } +} + +<ClassDec>{IDENTIFIER} { + generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext); + // codify(yyscanner,yytext); + yyextra->curClassName = yytext; + yyextra->curClassBases.clear(); + BEGIN( ClassInheritance ); + } + +<ClassInheritance>{ + ({BB}|[(,)]) { + codify(yyscanner,yytext); + } + + ({IDENTIFIER}".")*{IDENTIFIER} { + // The parser + // is assuming + // that ALL identifiers + // in this state + // are base classes; + // it doesn't check to see + // that the first parenthesis + // has been seen. + + // This is bad - it should + // probably be more strict + // about what to accept. + + yyextra->curClassBases.inSort(yytext); + generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext); + // codify(yyscanner,yytext); + } + + ":" { + codify(yyscanner,yytext); + + // Assume this will + // be a one-line suite; + // found counter-example + // in SuiteStart. + + // Push a class scope + + std::unique_ptr<ClassDef> classDefToAdd { createClassDef("<code>",1,1,yyextra->curClassName,ClassDef::Class,0,0,FALSE) }; + ScopedTypeVariant var(yyextra->curClassName); + char *s=yyextra->curClassBases.first(); + while (s) + { + const ClassDef *baseDefToAdd = 0; + // find class in the local scope + auto it = yyextra->codeClassMap.find(s); + if (it != yyextra->codeClassMap.end()) + { + baseDefToAdd = toClassDef(it->second.globalDef()); + } + // Try to find class in global scope + if (baseDefToAdd==0) + { + baseDefToAdd=yyextra->symbolResolver.resolveClass(yyextra->currentDefinition,s); + } + + if (baseDefToAdd && baseDefToAdd->name()!=yyextra->curClassName) + { + var.localDef()->insertBaseClass(baseDefToAdd->name()); + } + + s=yyextra->curClassBases.next(); + } + yyextra->codeClassMap.emplace(std::make_pair(yyextra->curClassName.str(),std::move(var))); + + // Reset class-parsing variables. + yyextra->curClassName.resize(0); + yyextra->curClassBases.clear(); + + yyextra->noSuiteFound = TRUE; + BEGIN( SuiteStart ); + } +} + + +<FunctionDec>{ + {IDENTIFIER} { + generateFunctionLink(yyscanner,*yyextra->code,yytext); + } + + {B}"(" { + codify(yyscanner,yytext); + BEGIN( FunctionParams ); + } +} + +<FunctionParams>{ + ({BB}|",") { + // Parses delimiters + codify(yyscanner,yytext); + } + + ({IDENTIFIER}|{PARAMNONEMPTY}+) { + codify(yyscanner,yytext); + } + + ")" { + codify(yyscanner,yytext); + } + + "\n" { + codifyLines(yyscanner,yytext); + } + + ":" { + codify(yyscanner,yytext); + + // Assume this will + // be a one-line suite; + // found counter-example + // in SuiteStart. + yyextra->noSuiteFound = TRUE; + BEGIN( SuiteStart ); + } +} + +<Body,Suite>{ + + {KEYWORD} { + // Position-sensitive rules! + // Must come AFTER keyword-triggered rules + // Must come BEFORE identifier NONEMPTY-like rules + // to syntax highlight. + + startFontClass(yyscanner,"keyword"); + codify(yyscanner,yytext); + endFontClass(yyscanner); + } + + {FLOWKW} { + if (yyextra->currentMemberDef && yyextra->currentMemberDef->isFunction()) + { + std::lock_guard<std::mutex> lock(g_countFlowKeywordsMutex); + MemberDefMutable *mdm = toMemberDefMutable(yyextra->currentMemberDef); + if (mdm) + { + mdm->incrementFlowKeyWordCount(); + } + } + startFontClass(yyscanner,"keywordflow"); + codify(yyscanner,yytext); + endFontClass(yyscanner); + } + ({IDENTIFIER}".")*{IDENTIFIER}/"(" { + generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext); + } + ({IDENTIFIER}".")+{IDENTIFIER} { + generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext,TRUE); + } + {IDENTIFIER} { codify(yyscanner,yytext); } + +} + + + +<SuiteStart>{ + + {BB} { + codify(yyscanner,yytext); + } + "pass" { + startFontClass(yyscanner,"keyword"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + BEGIN(Body); + } + {KEYWORD} { + startFontClass(yyscanner,"keyword"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + + // No indentation necessary + yyextra->noSuiteFound = FALSE; + } + + {FLOWKW} { + if (yyextra->currentMemberDef && yyextra->currentMemberDef->isFunction()) + { + std::lock_guard<std::mutex> lock(g_countFlowKeywordsMutex); + MemberDefMutable *mdm = toMemberDefMutable(yyextra->currentMemberDef); + if (mdm) + { + mdm->incrementFlowKeyWordCount(); + } + } + startFontClass(yyscanner,"keywordflow"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + + // No indentation necessary + yyextra->noSuiteFound = FALSE; + } + {IDENTIFIER} { + codify(yyscanner,yytext); + } + + + {POUNDCOMMENT} { + if (YY_START==SingleQuoteString || + YY_START==DoubleQuoteString || + YY_START==TripleString + ) + { + REJECT; + } + yy_push_state(YY_START,yyscanner); + BEGIN(DocBlock); + yyextra->docBlock=yytext; + } + + {NEWLINE} { + codifyLines(yyscanner,yytext); + if ( yyextra->noSuiteFound ) + { + // printf("New suite to capture! [%d]\n", yyextra->yyLineNr); + BEGIN ( SuiteCaptureIndent ); + } + } +} + +<SuiteCaptureIndent>{ + "\n"|({BB}"\n") { + // Blankline - ignore, keep looking for indentation. + codifyLines(yyscanner,yytext); + } + + {BB} { + // This state lasts momentarily, + // to check the indentation + // level that is about to be + // used. + codifyLines(yyscanner,yytext); + yyextra->indents.push(yyleng); + // printf("Captured indent of %d [line %d]\n", yyleng, yyextra->yyLineNr); + BEGIN( Suite ); + } +} + +<SuiteMaintain>{ + + {BB}/({NONEMPTY}|{EXPCHAR}) { + // This implements poor + // indentation-tracking; + // should be improved. + // (translate tabs to space, etc) + codifyLines(yyscanner,yytext); + adjustScopesAndSuites(yyscanner,static_cast<int>(yyleng)); + } + + "\n"|({BB}"\n") { + // If this ever succeeds, + // it means that this is + // a blank line, and + // can be ignored. + codifyLines(yyscanner,yytext); + } + + ""/({NONEMPTY}|{EXPCHAR}) { + // Default rule; matches + // the empty string, assuming + // real text starts here. + // Just go straight to Body. + adjustScopesAndSuites(yyscanner,0); + } +} + + +<Suite>{NEWLINE} { + codifyLines(yyscanner,yytext); + BEGIN( SuiteMaintain ); + } +<Body>{IDENTIFIER} { + codify(yyscanner,yytext); + } +<Body>{NEWLINE} { + codifyLines(yyscanner,yytext); + } + +<SingleQuoteString>{ // Single quoted string like 'That\'s a """nice""" string!' + \\{B}\n { // line continuation + codifyLines(yyscanner,yytext); + } + \\. { // escaped char + codify(yyscanner,yytext); + } + {STRINGPREFIX}?{TRIDOUBLEQUOTE} { // triple double quotes + codify(yyscanner,yytext); + } + "'" { // end of the string + codify(yyscanner,yytext); + endFontClass(yyscanner); + BEGIN(yyextra->stringContext); + } + [^"'\n\\]+ { // normal chars + codify(yyscanner,yytext); + } + . { // normal char + codify(yyscanner,yytext); + } +} + +<DoubleQuoteString>{ // Double quoted string like "That's \"a '''nice'''\" string!" + \\{B}\n { // line continuation + codifyLines(yyscanner,yytext); + } + \\. { // escaped char + codify(yyscanner,yytext); + } + {STRINGPREFIX}?{TRISINGLEQUOTE} { // triple single quotes + codify(yyscanner,yytext); + } + "\"" { // end of the string + codify(yyscanner,yytext); + endFontClass(yyscanner); + BEGIN(yyextra->stringContext); + } + [^"'\n\\]+ { // normal chars + codify(yyscanner,yytext); + } + . { // normal char + codify(yyscanner,yytext); + } +} + +<TripleString>{ + {TRIDOUBLEQUOTE} | + {TRISINGLEQUOTE} { + codify(yyscanner,yytext); + if (yyextra->doubleQuote==(yytext[0]=='"')) + { + endFontClass(yyscanner); + BEGIN(yyextra->stringContext); + } + } + {LONGSTRINGBLOCK} { + codifyLines(yyscanner,yytext); + } + \n { + codifyLines(yyscanner,yytext); + } + . { + codify(yyscanner,yytext); + } +} + + +<*>{STRINGPREFIX}?{TRISINGLEQUOTE} { + if (YY_START==SingleQuoteString) REJECT; + startFontClass(yyscanner,"stringliteral"); + yyextra->stringContext=YY_START; + yyextra->doubleQuote=yytext[yyleng-1]=='"'; + codify(yyscanner,yytext); + BEGIN(TripleString); + } +<*>{STRINGPREFIX}?{TRIDOUBLEQUOTE} { + if (YY_START==DoubleQuoteString) REJECT; + startFontClass(yyscanner,"stringliteral"); + yyextra->stringContext=YY_START; + yyextra->doubleQuote=yytext[yyleng-1]=='"'; + codify(yyscanner,yytext); + BEGIN(TripleString); + } +<*>{STRINGPREFIX}?"'" { // single quoted string + if (YY_START==SingleQuoteString || + YY_START==DoubleQuoteString || + YY_START==TripleString) + { + REJECT; + } + startFontClass(yyscanner,"stringliteral"); + yyextra->stringContext=YY_START; + codify(yyscanner,yytext); + BEGIN(SingleQuoteString); + } +<*>{STRINGPREFIX}?"\"" { // double quoted string + if (YY_START==SingleQuoteString || + YY_START==DoubleQuoteString || + YY_START==TripleString) + { + REJECT; + } + startFontClass(yyscanner,"stringliteral"); + yyextra->stringContext=YY_START; + codify(yyscanner,yytext); + BEGIN(DoubleQuoteString); + } +<DocBlock>.* { // contents of current comment line + yyextra->docBlock+=yytext; + } +<DocBlock>"\n"{B}("#") { // comment block (next line is also comment line) + yyextra->docBlock+=yytext; + } +<DocBlock>{NEWLINE} { // comment block ends at the end of this line + // remove special comment (default config) + if (Config_getBool(STRIP_CODE_COMMENTS)) + { + yyextra->yyLineNr+=((QCString)yyextra->docBlock).contains('\n'); + yyextra->endComment=TRUE; + } + else // do not remove comment + { + startFontClass(yyscanner,"comment"); + codifyLines(yyscanner,yyextra->docBlock); + endFontClass(yyscanner); + } + unput(*yytext); + yy_pop_state(yyscanner); + } +<*>{POUNDCOMMENT}.* { + if (YY_START==SingleQuoteString || + YY_START==DoubleQuoteString || + YY_START==TripleString) + { + REJECT; + } + yy_push_state(YY_START,yyscanner); + BEGIN(DocBlock); + yyextra->docBlock=yytext; + } +<*>"#".* { // normal comment + if (YY_START==SingleQuoteString || + YY_START==DoubleQuoteString || + YY_START==TripleString) + { + REJECT; + } + startFontClass(yyscanner,"comment"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + } +<*>{NEWLINE} { + if (yyextra->endComment) + { + yyextra->endComment=FALSE; + } + else + { + codifyLines(yyscanner,yytext); + } + //printf("[pycode] %d NEWLINE [line %d] no match\n", + // YY_START, yyextra->yyLineNr); + + BEGIN(Body); + } + +<*>[ \t]+ { + codify(yyscanner,yytext); + BEGIN(Body); + } +<*>. { + codify(yyscanner,yytext); + // printf("[pycode] '%s' [ state %d ] [line %d] no match\n", + // yytext, YY_START, yyextra->yyLineNr); + + BEGIN(Body); + } + +<*><<EOF>> { + if (YY_START==DocBlock && !Config_getBool(STRIP_CODE_COMMENTS)) + { + startFontClass(yyscanner,"comment"); + codifyLines(yyscanner,yyextra->docBlock); + endFontClass(yyscanner); + } + yyterminate(); + } +%% + +/*@ ---------------------------------------------------------------------------- + */ + +#if 0 // TODO: call me to store local variables and get better syntax highlighting, see code.l +static void addVariable(yyscan_t yyscanner, QCString type, QCString name) { + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; //printf("PyVariableContext::addVariable(%s,%s)\n",type.data(),name.data()); QCString ltype = type.simplifyWhiteSpace(); QCString lname = name.simplifyWhiteSpace(); - Scope *scope = m_scopes.count()==0 ? &m_globalScope : m_scopes.getLast(); - 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 - ) + auto it = yyextra->codeClassMap.find(ltype.str()); + if (it!=yyextra->codeClassMap.end()) { - scope->append(lname,varType); // add it to a list + yyextra->theVarContext.addVariable(lname,std::move(it->second)); } - else + else { - if (m_scopes.count()>0) // for local variables add a dummy entry so the name - // is hidden to avoid FALSE links to global variables with the same name - // TODO: make this work for namespaces as well! + const ClassDef *varType = getResolvedClass(yyextra->currentDefinition,yyextra->sourceFileDef,ltype); // look for global class definitions + if (varType) { - scope->append(lname,dummyContext); + yyextra->theVarContext.addVariable(lname,ScopedTypeVariant(varType)); + } + else + { + if (!yyextra->theVarContext.atGlobalScope()) // for local variable add a dummy entry to avoid linking to a global that is shadowed. + { + yyextra->theVarContext.addVariable(lname.str(),ScopedTypeVariant()); + } } } } +#endif + +//------------------------------------------------------------------------------- -ClassDef *PyVariableContext::findVariable(const QCString &name) +static yy_size_t yyread(yyscan_t yyscanner, char *buf,yy_size_t max_size) { - if (name.isEmpty()) return 0; - ClassDef *result = 0; - QListIterator<Scope> sli(m_scopes); - Scope *scope; - // search from inner to outer scope - for (sli.toLast();(scope=sli.current());--sli) + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + yy_size_t inputPosition = yyextra->inputPosition; + const char *s = yyextra->inputString + inputPosition; + yy_size_t c=0; + while( c < max_size && *s ) { - result = scope->find(name); - if (result) - { - return result; - } + *buf++ = *s++; + c++; } - // nothing found -> also try the global scope - result=m_globalScope.find(name); - return result; + yyextra->inputPosition += c; + return c; } -static PyVariableContext g_theVarContext; -const ClassDef *PyVariableContext::dummyContext = (ClassDef*)0x8; +//------------------------------------------------------------------------------- -class PyCallContext +/*! + Examines current stack of white-space indentations; + re-syncs the parser with the correct scope. +*/ +static void adjustScopesAndSuites(yyscan_t yyscanner,unsigned indentLength) { - public: - struct Ctx - { - Ctx() : name(g_name), type(g_type), cd(0) {} - QCString name; - QCString type; - const ClassDef *cd; - }; - - PyCallContext() - { - m_classList.append(new Ctx); - m_classList.setAutoDelete(TRUE); - } - - virtual ~PyCallContext() {} - - void setClass(const ClassDef *cd) - { - Ctx *ctx = m_classList.getLast(); - if (ctx) - { - ctx->cd=cd; - } - } - void pushScope() - { - m_classList.append(new Ctx); - } - - void popScope() - { - if (m_classList.count()>1) - { - Ctx *ctx = m_classList.getLast(); - if (ctx) - { - g_name = ctx->name; - g_type = ctx->type; - } - m_classList.removeLast(); - } - else - { - } - } - - void clear() - { - m_classList.clear(); - m_classList.append(new Ctx); - } - - const ClassDef *getClass() const + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + // States to pop + if (!yyextra->indents.empty() && indentLength < yyextra->indents.top()) + { + while (!yyextra->indents.empty() && indentLength < yyextra->indents.top()) { - Ctx *ctx = m_classList.getLast(); + // printf("Exited scope indent of [%d]\n", yyextra->indents.top()); + yyextra->indents.pop(); // Pop the old suite's indentation - if (ctx) - return ctx->cd; - else - return 0; + yyextra->currentMemberDef=0; + if (yyextra->currentDefinition) + yyextra->currentDefinition=yyextra->currentDefinition->getOuterScope(); } + } - private: - QList<Ctx> m_classList; -}; - -static PyCallContext g_theCallContext; + // Are there any remaining indentation levels for suites? + if (!yyextra->indents.empty()) + { + BEGIN( Suite ); + } + else + { + BEGIN( Body ); + } +} +//------------------------------------------------------------------------------- /*! 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)) - { - p++ ; - if (c=='\n') count++; + while ((c=*p)) + { + 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; - } + count++; + yyextra->needsTermination=TRUE; + } return count; } -static void setCurrentDoc(const QCString &anchor) +//------------------------------------------------------------------------------- + +static void setCurrentDoc(yyscan_t yyscanner, const QCString &anchor) { + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; if (Doxygen::searchIndex) { - if (g_searchCtx) + std::lock_guard<std::mutex> lock(g_searchIndexMutex); + if (yyextra->searchCtx) { - Doxygen::searchIndex->setCurrentDoc(g_searchCtx,g_searchCtx->anchor(),FALSE); + yyextra->code->setCurrentDoc(yyextra->searchCtx,yyextra->searchCtx->anchor(),FALSE); } else { - Doxygen::searchIndex->setCurrentDoc(g_sourceFileDef,anchor,TRUE); + yyextra->code->setCurrentDoc(yyextra->sourceFileDef,anchor,TRUE); } } } -static void addToSearchIndex(const char *text) +//------------------------------------------------------------------------------- + +static void addToSearchIndex(yyscan_t yyscanner, const char *text) { + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; if (Doxygen::searchIndex) { - Doxygen::searchIndex->addWord(text,FALSE); + std::lock_guard<std::mutex> lock(g_searchIndexMutex); + yyextra->code->addWord(text,FALSE); } } +//------------------------------------------------------------------------------- -static const ClassDef *stripClassName(const char *s,Definition *d=g_currentDefinition) +static const ClassDef *stripClassName(yyscan_t yyscanner,const char *s,Definition *d) { + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; int pos=0; QCString type = s; QCString className; @@ -339,15 +976,14 @@ static const ClassDef *stripClassName(const char *s,Definition *d=g_currentDefin while (extractClassNameFromType(type,pos,className,templSpec)!=-1) { QCString clName=className+templSpec; - const ClassDef *cd=0; - if (!g_classScope.isEmpty()) + if (!yyextra->classScope.isEmpty()) { - cd=getResolvedClass(d,g_sourceFileDef,g_classScope+"::"+clName); + cd=yyextra->symbolResolver.resolveClass(d,yyextra->classScope+"::"+clName); } if (cd==0) { - cd=getResolvedClass(d,g_sourceFileDef,clName); + cd=yyextra->symbolResolver.resolveClass(d,clName); } if (cd) { @@ -358,104 +994,117 @@ static const ClassDef *stripClassName(const char *s,Definition *d=g_currentDefin return 0; } +//------------------------------------------------------------------------------- - -/*! 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_currentFontClass) { g_code->endFontClass(); } - if (g_sourceFileDef) + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + //if (yyextra->currentFontClass) { yyextra->code->endFontClass(yyscanner); } + if (yyextra->sourceFileDef) { //QCString lineNumber,lineAnchor; - //lineNumber.sprintf("%05d",g_yyLineNr); - //lineAnchor.sprintf("l%05d",g_yyLineNr); - - Definition *d = g_sourceFileDef->getSourceDefinition(g_yyLineNr); - //printf("startCodeLine %d d=%p\n",g_yyLineNr,d); - //g_code->startLineNumber(); - - if (!g_includeCodeFragment && d && d->isLinkableInProject()) + //lineNumber.sprintf("%05d",yyextra->yyLineNr); + //lineAnchor.sprintf("l%05d",yyextra->yyLineNr); + + Definition *d = yyextra->sourceFileDef->getSourceDefinition(yyextra->yyLineNr); + //printf("startCodeLine %d d=%p\n",yyextra->yyLineNr,d); + //yyextra->code->startLineNumber(); + + if (!yyextra->includeCodeFragment && d && d->isLinkableInProject()) { - g_currentDefinition = d; - g_currentMemberDef = g_sourceFileDef->getSourceMember(g_yyLineNr); - //g_insideBody = FALSE; - g_endComment = FALSE; - g_searchingForBody = TRUE; - g_realScope = d->name().copy(); - g_classScope = d->name().copy(); - //printf("Real scope: '%s'\n",g_realScope.data()); - g_bodyCurlyCount = 0; + yyextra->currentDefinition = d; + yyextra->currentMemberDef = yyextra->sourceFileDef->getSourceMember(yyextra->yyLineNr); + //yyextra->insideBody = FALSE; + yyextra->endComment = FALSE; + yyextra->searchingForBody = TRUE; + yyextra->realScope = d->name().copy(); + yyextra->classScope = d->name().copy(); + //printf("Real scope: '%s'\n",yyextra->realScope.data()); + yyextra->bodyCurlyCount = 0; 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(yyscanner,lineAnchor); } else { - g_code->writeLineNumber(d->getReference(), - d->getOutputFileBase(), - 0,g_yyLineNr); - setCurrentDoc(lineAnchor); + yyextra->code->writeLineNumber(d->getReference(), + d->getOutputFileBase(), + 0,yyextra->yyLineNr); + setCurrentDoc(yyscanner,lineAnchor); } } else { - //g_code->codify(lineNumber); - g_code->writeLineNumber(0,0,0,g_yyLineNr); + //yyextra->code->codify(lineNumber); + yyextra->code->writeLineNumber(0,0,0,yyextra->yyLineNr); } - //g_code->endLineNumber(); + //yyextra->code->endLineNumber(); } - g_code->startCodeLine(g_sourceFileDef); - if (g_currentFontClass) + yyextra->code->startCodeLine(yyextra->sourceFileDef); + if (yyextra->currentFontClass) { - g_code->startFontClass(g_currentFontClass); + yyextra->code->startFontClass(yyextra->currentFontClass); } } -static void codify(const char* text) -{ - g_code->codify(text); +//------------------------------------------------------------------------------- + +static void codify(yyscan_t yyscanner,const char* text) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + yyextra->code->codify(text); } -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); } } +//------------------------------------------------------------------------------- /*! writes a link to a fragment \a text that may span multiple lines, inserting - * line numbers for each line. If \a text contains newlines, the link will be + * line numbers for each line. If \a text contains newlines, the link will be * split into multiple links with the same destination, one for each line. */ -static void writeMultiLineCodeLink(CodeOutputInterface &ol, +static void writeMultiLineCodeLink(yyscan_t yyscanner, + CodeOutputInterface &ol, const Definition *d, const char *text) { - static bool sourceTooltips = Config_getBool(SOURCE_TOOLTIPS); - TooltipManager::instance()->addTooltip(d); + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + bool sourceTooltips = Config_getBool(SOURCE_TOOLTIPS); + TooltipManager::instance().addTooltip(ol,d); QCString ref = d->getReference(); QCString file = d->getOutputFileBase(); QCString anchor = d->anchor(); - QCString tooltip; + QCString tooltip; if (!sourceTooltips) // fall back to simple "title" tooltips { tooltip = d->briefDescriptionAsTooltip(); @@ -469,11 +1118,11 @@ static void writeMultiLineCodeLink(CodeOutputInterface &ol, while ((c=*p++) && c!='\n') { } if (c=='\n') { - g_yyLineNr++; + yyextra->yyLineNr++; *(p-1)='\0'; //printf("writeCodeLink(%s,%s,%s,%s)\n",ref,file,anchor,sp); ol.writeCodeLink(ref,file,anchor,sp,tooltip); - nextCodeLine(); + nextCodeLine(yyscanner); } else { @@ -484,141 +1133,150 @@ static void writeMultiLineCodeLink(CodeOutputInterface &ol, } } -static void startFontClass(const char *s) +//------------------------------------------------------------------------------- + +static void startFontClass(yyscan_t yyscanner,const char *s) { + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; // if font class is already set don't stop and start it. // strcmp does not like null pointers as input. - if (!g_currentFontClass || !s || strcmp(g_currentFontClass,s)) + if (!yyextra->currentFontClass || !s || strcmp(yyextra->currentFontClass,s)) { - endFontClass(); - g_code->startFontClass(s); - g_currentFontClass=s; + endFontClass(yyscanner); + yyextra->code->startFontClass(s); + yyextra->currentFontClass=s; } } -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 codifyLines(char *text) +//------------------------------------------------------------------------------- + +static void codifyLines(yyscan_t yyscanner,const char *text) { - //printf("codifyLines(%d,\"%s\")\n",g_yyLineNr,text); - char *p=text,*sp=p; + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + //printf("codifyLines(%d,\"%s\")\n",yyextra->yyLineNr,text); + const char *p=text,*sp=p; char c; bool done=FALSE; - const char * tmp_currentFontClass = g_currentFontClass; while (!done) { sp=p; while ((c=*p++) && c!='\n') { } if (c=='\n') { - g_yyLineNr++; - *(p-1)='\0'; - g_code->codify(sp); - endCodeLine(); - if (g_yyLineNr<g_inputLines) - { - startCodeLine(); - } - if (tmp_currentFontClass) - { - startFontClass(tmp_currentFontClass); - } + yyextra->yyLineNr++; + int l = (int)(p-sp-1); + char *tmp = (char*)malloc(l+1); + memcpy(tmp,sp,l); + tmp[l]='\0'; + yyextra->code->codify(tmp); + free(tmp); + nextCodeLine(yyscanner); } else { - g_code->codify(sp); + yyextra->code->codify(sp); done=TRUE; } } } -static void codifyLines(const QCString &str) -{ - char *tmp= (char *)malloc(str.length()+1); - qstrcpy(tmp, str); - codifyLines(tmp); - free(tmp); -} +//------------------------------------------------------------------------------- -static bool getLinkInScope(const QCString &c, // scope +static bool getLinkInScope(yyscan_t yyscanner, + const QCString &c, // scope const QCString &m, // member - const char *memberText, // exact text - CodeOutputInterface &ol, - const char *text - ) + const char *memberText, // exact text + CodeOutputInterface &ol, + const char *text + ) { + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; 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) && + if (getDefs(c,m,"()",md,cd,fd,nd,gd,FALSE,yyextra->sourceFileDef) && md->isLinkable()) { //Definition *d=0; //if (cd) d=cd; else if (nd) d=nd; else if (fd) d=fd; else d=gd; const Definition *d = md->getOuterScope()==Doxygen::globalScope ? - md->getBodyDef() : md->getOuterScope(); + md->getBodyDef() : md->getOuterScope(); //printf("Found! d=%s\n",d?d->name().data():"<none>"); if (md->getGroupDef()) d = md->getGroupDef(); if (d && d->isLinkable()) { - g_theCallContext.setClass(stripClassName(md->typeString(),md->getOuterScope())); - //printf("g_currentDefinition=%p g_currentMemberDef=%p\n", - // g_currentDefinition,g_currentMemberDef); + yyextra->theCallContext.setScope(ScopedTypeVariant(stripClassName(yyscanner,md->typeString(),md->getOuterScope()))); + //printf("yyextra->currentDefinition=%p yyextra->currentMemberDef=%p\n", + // yyextra->currentDefinition,yyextra->currentMemberDef); - if (g_currentDefinition && g_currentMemberDef && - md!=g_currentMemberDef && g_collectXRefs) + if (yyextra->currentDefinition && yyextra->currentMemberDef && + md!=yyextra->currentMemberDef && yyextra->collectXRefs) { - addDocCrossReference(g_currentMemberDef,const_cast<MemberDef*>(md)); + std::lock_guard<std::mutex> lock(g_docCrossReferenceMutex); + addDocCrossReference(toMemberDefMutable(yyextra->currentMemberDef),toMemberDefMutable(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()); - - writeMultiLineCodeLink(ol,md, text ? text : memberText); - addToSearchIndex(text ? text : memberText); + + writeMultiLineCodeLink(yyscanner,ol,md, text ? text : memberText); + addToSearchIndex(yyscanner,text ? text : memberText); return TRUE; - } + } } return FALSE; } -static bool getLink(const char *className, +//------------------------------------------------------------------------------- + +static bool getLink(yyscan_t yyscanner, + const char *className, const char *memberName, - CodeOutputInterface &ol, - const char *text=0) + CodeOutputInterface &ol, + const char *text) { + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; QCString m=removeRedundantWhiteSpace(memberName); QCString c=className; - if (!getLinkInScope(c,m,memberName,ol,text)) + if (!getLinkInScope(yyscanner,c,m,memberName,ol,text)) { - if (!g_curClassName.isEmpty()) + if (!yyextra->curClassName.isEmpty()) { if (!c.isEmpty()) c.prepend("::"); - c.prepend(g_curClassName); - return getLinkInScope(c,m,memberName,ol,text); + c.prepend(yyextra->curClassName); + return getLinkInScope(yyscanner,c,m,memberName,ol,text); } return FALSE; } return TRUE; } +//------------------------------------------------------------------------------- /* For a given string in the source code, finds its class or global id and links to it. */ -static void generateClassOrGlobalLink(CodeOutputInterface &ol,char *clName, - bool typeOnly=FALSE) +static void generateClassOrGlobalLink(yyscan_t yyscanner, + CodeOutputInterface &ol, + const char *clName, + bool typeOnly) { + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; QCString className=clName; // Don't do anything for empty text @@ -626,20 +1284,22 @@ static void generateClassOrGlobalLink(CodeOutputInterface &ol,char *clName, DBG_CTX((stderr,"generateClassOrGlobalLink(className=%s)\n",className.data())); - const ClassDef *cd=0,*lcd=0; /** Class def that we may find */ - const MemberDef *md=0; /** Member def that we may find */ + const ScopedTypeVariant *lcd = 0; + const ClassDef *cd=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 + if ((lcd=yyextra->theVarContext.findVariable(className))==0) // not a local variable { - Definition *d = g_currentDefinition; + Definition *d = yyextra->currentDefinition; QCString scope = substitute(className,".","::"); - cd = getResolvedClass(d,g_sourceFileDef,substitute(className,".","::"),&md); + cd = yyextra->symbolResolver.resolveClass(d,substitute(className,".","::")); + md = yyextra->symbolResolver.getTypedef(); - DBG_CTX((stderr,"d=%s g_sourceFileDef=%s\n", + DBG_CTX((stderr,"d=%s yyextra->sourceFileDef=%s\n", d?d->displayName().data():"<null>", - g_currentDefinition?g_currentDefinition->displayName().data():"<null>")); + yyextra->currentDefinition?yyextra->currentDefinition->displayName().data():"<null>")); DBG_CTX((stderr,"is found as a type %s\n",cd?cd->name().data():"<null>")); if (cd==0 && md==0) // also see if it is variable or enum or enum value @@ -647,21 +1307,21 @@ static void generateClassOrGlobalLink(CodeOutputInterface &ol,char *clName, const NamespaceDef *nd = getResolvedNamespace(scope); if (nd) { - writeMultiLineCodeLink(ol,nd,clName); - addToSearchIndex(className); + writeMultiLineCodeLink(yyscanner,ol,nd,clName); + addToSearchIndex(yyscanner,className); return; } - else if (getLink(g_classScope,clName,ol,clName)) + else if (getLink(yyscanner,yyextra->classScope,clName,ol,clName)) { - return; + return; } } } else { - if (lcd!=PyVariableContext::dummyContext) + if (lcd->type()!=ScopedTypeVariant::Dummy) { - g_theCallContext.setClass(lcd); + yyextra->theCallContext.setScope(*lcd); } //isLocal=TRUE; DBG_CTX((stderr,"is a local variable cd=%p!\n",cd)); @@ -669,17 +1329,18 @@ static void generateClassOrGlobalLink(CodeOutputInterface &ol,char *clName, if (cd && cd->isLinkable()) // is it a linkable class { - writeMultiLineCodeLink(ol,cd,clName); - addToSearchIndex(className); + writeMultiLineCodeLink(yyscanner,ol,cd,clName); + addToSearchIndex(yyscanner,className); if (md) { 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) + if (d && d->isLinkable() && md->isLinkable() && + yyextra->currentMemberDef && yyextra->collectXRefs) { - addDocCrossReference(g_currentMemberDef,const_cast<MemberDef*>(md)); + std::lock_guard<std::mutex> lock(g_docCrossReferenceMutex); + addDocCrossReference(toMemberDefMutable(yyextra->currentMemberDef),toMemberDefMutable(md)); } } } @@ -694,55 +1355,59 @@ static void generateClassOrGlobalLink(CodeOutputInterface &ol,char *clName, DBG_CTX((stderr,"scope=%s locName=%s mcd=%p\n",scope.data(),locName.data(),mcd)); if (mcd) { - MemberDef *mmd = mcd->getMemberByName(locName); - if (mmd) - { - g_theCallContext.setClass(stripClassName(mmd->typeString(),mmd->getOuterScope())); - writeMultiLineCodeLink(ol,mmd,clName); - addToSearchIndex(className); - const Definition *d = mmd->getOuterScope()==Doxygen::globalScope ? - mmd->getBodyDef() : mmd->getOuterScope(); - if (mmd->getGroupDef()) d = mmd->getGroupDef(); - if (d && d->isLinkable() && mmd->isLinkable() && - g_currentMemberDef && g_collectXRefs) - { - addDocCrossReference(g_currentMemberDef,mmd); - } - return; - } + MemberDef *mmd = mcd->getMemberByName(locName); + if (mmd) + { + yyextra->theCallContext.setScope(ScopedTypeVariant(stripClassName(yyscanner,mmd->typeString(),mmd->getOuterScope()))); + writeMultiLineCodeLink(yyscanner,ol,mmd,clName); + addToSearchIndex(yyscanner,className); + const Definition *d = mmd->getOuterScope()==Doxygen::globalScope ? + mmd->getBodyDef() : mmd->getOuterScope(); + if (mmd->getGroupDef()) d = mmd->getGroupDef(); + if (d && d->isLinkable() && mmd->isLinkable() && + yyextra->currentMemberDef && yyextra->collectXRefs) + { + std::lock_guard<std::mutex> lock(g_docCrossReferenceMutex); + addDocCrossReference(toMemberDefMutable(yyextra->currentMemberDef),toMemberDefMutable(mmd)); + } + return; + } } else // check namespace as well { const NamespaceDef *mnd = getResolvedNamespace(scope); if (mnd) { - MemberDef *mmd=mnd->getMemberByName(locName); - if (mmd) + MemberDef *mmd=mnd->getMemberByName(locName); + if (mmd) { - //printf("name=%s scope=%s\n",locName.data(),scope.data()); - g_theCallContext.setClass(stripClassName(mmd->typeString(),mmd->getOuterScope())); - writeMultiLineCodeLink(ol,mmd,clName); - addToSearchIndex(className); - const Definition *d = mmd->getOuterScope()==Doxygen::globalScope ? - mmd->getBodyDef() : mmd->getOuterScope(); - if (mmd->getGroupDef()) d = mmd->getGroupDef(); - if (d && d->isLinkable() && mmd->isLinkable() && - g_currentMemberDef && g_collectXRefs) - { - addDocCrossReference(g_currentMemberDef,mmd); - } - return; + //printf("name=%s scope=%s\n",locName.data(),scope.data()); + yyextra->theCallContext.setScope(ScopedTypeVariant(stripClassName(yyscanner,mmd->typeString(),mmd->getOuterScope()))); + writeMultiLineCodeLink(yyscanner,ol,mmd,clName); + addToSearchIndex(yyscanner,className); + const Definition *d = mmd->getOuterScope()==Doxygen::globalScope ? + mmd->getBodyDef() : mmd->getOuterScope(); + if (mmd->getGroupDef()) d = mmd->getGroupDef(); + if (d && d->isLinkable() && mmd->isLinkable() && + yyextra->currentMemberDef && yyextra->collectXRefs) + { + std::lock_guard<std::mutex> lock(g_docCrossReferenceMutex); + addDocCrossReference(toMemberDefMutable(yyextra->currentMemberDef),toMemberDefMutable(mmd)); + } + return; } } } } - + // nothing found, just write out the word - codifyLines(clName); - addToSearchIndex(clName); + codifyLines(yyscanner,clName); + addToSearchIndex(yyscanner,clName); } } +//------------------------------------------------------------------------------- + /* As of June 1, this function seems to work for file members, but scopes are not @@ -750,11 +1415,12 @@ static void generateClassOrGlobalLink(CodeOutputInterface &ol,char *clName, so it doesn't work for classes yet. */ -static void generateFunctionLink(CodeOutputInterface &ol,char *funcName) +static void generateFunctionLink(yyscan_t yyscanner, + CodeOutputInterface &ol, + const char *funcName) { - //CodeClassDef *ccd=0; - ClassDef *ccd=0; - QCString locScope=g_classScope.copy(); + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + QCString locScope=yyextra->classScope; QCString locFunc=removeRedundantWhiteSpace(funcName); DBG_CTX((stdout,"*** locScope=%s locFunc=%s\n",locScope.data(),locFunc.data())); int i=locFunc.findRev("::"); @@ -764,915 +1430,213 @@ static void generateFunctionLink(CodeOutputInterface &ol,char *funcName) locFunc=locFunc.right(locFunc.length()-i-2).stripWhiteSpace(); } //printf("generateFunctionLink(%s) classScope='%s'\n",locFunc.data(),locScope.data()); - if (!locScope.isEmpty() && (ccd=g_codeClassSDict[locScope])) + if (!locScope.isEmpty()) { - //printf("using classScope %s\n",g_classScope.data()); - if (ccd->baseClasses()) + auto it = yyextra->codeClassMap.find(locScope.str()); + if (it!=yyextra->codeClassMap.end()) { - BaseClassListIterator bcli(*ccd->baseClasses()); - for ( ; bcli.current() ; ++bcli) + ScopedTypeVariant ccd = it->second; + //printf("using classScope %s\n",yyextra->classScope.data()); + if (ccd.localDef() && !ccd.localDef()->baseClasses().empty()) { - if (getLink(bcli.current()->classDef->name(),locFunc,ol,funcName)) - { - return; - } + for (const auto &bcName : ccd.localDef()->baseClasses()) + { + if (getLink(yyscanner,bcName,locFunc,ol,funcName)) + { + return; + } + } } } } - if (!getLink(locScope,locFunc,ol,funcName)) + if (!getLink(yyscanner,locScope,locFunc,ol,funcName)) { - generateClassOrGlobalLink(ol,funcName); + generateClassOrGlobalLink(yyscanner,ol,funcName); } return; } -static bool findMemberLink(CodeOutputInterface &ol,Definition *sym,const char *symName) +//------------------------------------------------------------------------------- + +static bool findMemberLink(yyscan_t yyscanner, + CodeOutputInterface &ol, + Definition *sym, + const char *symName) { + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; //printf("sym %s outerScope=%s equal=%d\n", // sym->name().data(),sym->getOuterScope()->name().data(), - // sym->getOuterScope()==g_currentDefinition); + // sym->getOuterScope()==yyextra->currentDefinition); if (sym->getOuterScope() && sym->getOuterScope()->definitionType()==Definition::TypeClass && - g_currentDefinition->definitionType()==Definition::TypeClass) + yyextra->currentDefinition->definitionType()==Definition::TypeClass) { - ClassDef *cd = dynamic_cast<ClassDef*>(sym->getOuterScope()); - ClassDef *thisCd = dynamic_cast<ClassDef *>(g_currentDefinition); + ClassDef *cd = toClassDef(sym->getOuterScope()); + ClassDef *thisCd = toClassDef(yyextra->currentDefinition); if (sym->definitionType()==Definition::TypeMember) { - if (g_currentMemberDef && g_collectXRefs) + if (yyextra->currentMemberDef && yyextra->collectXRefs) { - addDocCrossReference(g_currentMemberDef,dynamic_cast<MemberDef*>(sym)); + std::lock_guard<std::mutex> lock(g_docCrossReferenceMutex); + addDocCrossReference(toMemberDefMutable(yyextra->currentMemberDef),toMemberDefMutable(toMemberDef(sym))); } } DBG_CTX((stderr,"cd=%s thisCd=%s\n",cd?cd->name().data():"<none>",thisCd?thisCd->name().data():"<none>")); // TODO: find the nearest base class in case cd is a base class of - // thisCd + // thisCd if (cd==thisCd || (thisCd && thisCd->isBaseClass(cd,TRUE))) { - writeMultiLineCodeLink(ol,sym,symName); + writeMultiLineCodeLink(yyscanner,ol,sym,symName); return TRUE; } } return FALSE; } -static void findMemberLink(CodeOutputInterface &ol,char *symName) +//------------------------------------------------------------------------------- + +static void findMemberLink(yyscan_t yyscanner, + CodeOutputInterface &ol, + const char *symName) { + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; //printf("Member reference: %s scope=%s member=%s\n", // yytext, - // g_currentDefinition?g_currentDefinition->name().data():"<none>", - // g_currentMemberDef?g_currentMemberDef->name().data():"<none>" + // yyextra->currentDefinition?yyextra->currentDefinition->name().data():"<none>", + // yyextra->currentMemberDef?yyextra->currentMemberDef->name().data():"<none>" // ); - if (g_currentDefinition) + if (yyextra->currentDefinition) { - DefinitionIntf *di = Doxygen::symbolMap->find(symName); - if (di) + auto range = Doxygen::symbolMap.find(symName); + for (auto it = range.first; it!=range.second; ++it) { - if (di->definitionType()==DefinitionIntf::TypeSymbolList) // multiple symbols - { - DefinitionListIterator dli(*(DefinitionList*)di); - Definition *sym; - for (dli.toFirst();(sym=dli.current());++dli) - { - if (findMemberLink(ol,sym,symName)) return; - } - } - else // single symbol - { - if (findMemberLink(ol,(Definition*)di,symName)) return; - } + findMemberLink(yyscanner,ol,it->second,symName); } } //printf("sym %s not found\n",&yytext[5]); - codify(symName); -} - -#undef YY_INPUT -#define YY_INPUT(buf,result,max_size) result=yyread(buf,max_size); - -static yy_size_t yyread(char *buf,yy_size_t max_size) -{ - yy_size_t c=0; - while( c < max_size && g_inputString[g_inputPosition] ) - { - *buf = g_inputString[g_inputPosition++] ; - c++; buf++; - } - return c; -} - -%} - - -BB [ \t]+ -B [ \t]* -NEWLINE \n - -DIGIT [0-9] -LETTER [A-Za-z\x80-\xFF] -NONEMPTY [A-Za-z0-9_\x80-\xFF] -EXPCHAR [#(){}\[\],:.%/\\=`*~|&<>!;+-] -NONEMPTYEXP [^ \t\n:] -PARAMNONEMPTY [^ \t\n():] -IDENTIFIER ({LETTER}|"_")({LETTER}|{DIGIT}|"_")* -BORDER ([^A-Za-z0-9]) - -POUNDCOMMENT "##" - -TRISINGLEQUOTE "'''" -TRIDOUBLEQUOTE "\"\"\"" -LONGSTRINGCHAR [^\\"'] -ESCAPESEQ ("\\")(.) -LONGSTRINGITEM ({LONGSTRINGCHAR}|{ESCAPESEQ}) -SMALLQUOTE ("\"\""|"\""|"'"|"''") -LONGSTRINGBLOCK ({LONGSTRINGITEM}+|{SMALLQUOTE}) - -SHORTSTRING ("'"{SHORTSTRINGITEM}*"'"|'"'{SHORTSTRINGITEM}*'"') -SHORTSTRINGITEM ({SHORTSTRINGCHAR}|{ESCAPESEQ}) -SHORTSTRINGCHAR [^\\\n"] -STRINGLITERAL {STRINGPREFIX}?( {SHORTSTRING} | {LONGSTRING}) -STRINGPREFIX ("r"|"u"|"ur"|"R"|"U"|"UR"|"Ur"|"uR") -KEYWORD ("lambda"|"import"|"class"|"assert"|"with"|"as"|"from"|"global"|"def"|"True"|"False") -FLOWKW ("or"|"and"|"is"|"not"|"print"|"for"|"in"|"if"|"try"|"except"|"yield"|"raise"|"break"|"continue"|"pass"|"if"|"return"|"while"|"elif"|"else"|"finally") -QUOTES ("\""[^"]*"\"") -SINGLEQUOTES ("'"[^']*"'") - -LONGINTEGER {INTEGER}("l"|"L") -INTEGER ({DECIMALINTEGER}|{OCTINTEGER}|{HEXINTEGER}) -DECIMALINTEGER ({NONZERODIGIT}{DIGIT}*|"0") -OCTINTEGER "0"{OCTDIGIT}+ -HEXINTEGER "0"("x"|"X"){HEXDIGIT}+ -NONZERODIGIT [1-9] -OCTDIGIT [0-7] -HEXDIGIT ({DIGIT}|[a-f]|[A-F]) -FLOATNUMBER ({POINTFLOAT}|{EXPONENTFLOAT}) -POINTFLOAT ({INTPART}?{FRACTION}|{INTPART}".") -EXPONENTFLOAT ({INTPART}|{POINTFLOAT}){EXPONENT} -INTPART {DIGIT}+ -FRACTION "."{DIGIT}+ -EXPONENT ("e"|"E")("+"|"-")?{DIGIT}+ -IMAGNUMBER ({FLOATNUMBER}|{INTPART})("j"|"J") -ATOM ({IDENTIFIER}|{LITERAL}|{ENCLOSURE}) -ENCLOSURE ({PARENTH_FORM}|{LIST_DISPLAY}|{DICT_DISPLAY}|{STRING_CONVERSION}) -LITERAL ({STRINGLITERAL}|{INTEGER}|{LONGINTEGER}|{FLOATNUMBER}|{IMAGNUMBER}) -PARENTH_FORM "("{EXPRESSION_LIST}?")" -TEST ({AND_TEST}("or"{AND_TEST})*|{LAMBDA_FORM}) -TESTLIST {TEST}( ","{TEST})*","? -LIST_DISPLAY "["{LISTMAKER}?"]" -LISTMAKER {EXPRESSION}({LIST_FOR}|(","{EXPRESSION})*","?) -LIST_ITER ({LIST_FOR}|{LIST_IF}) -LIST_FOR "for"{EXPRESSION_LIST}"in"{TESTLIST}{LIST_ITER}? -LIST_IF "if"{TEST}{LIST_ITER}? -DICT_DISPLAY "\{"{KEY_DATUM_LIST}?"\}" -KEY_DATUM_LIST {KEY_DATUM}(","{KEY_DATUM})*","? -KEY_DATUM {EXPRESSION}":"{EXPRESSION} -STRING_CONVERSION "`"{EXPRESSION_LIST}"`" -PRIMARY ({ATOM}|{ATTRIBUTEREF}|{SUBSCRIPTION}|{SLICING}|{CALL}) -ATTRIBUTEREF {PRIMARY}"."{IDENTIFIER} -SUBSCRIPTION {PRIMARY}"["{EXPRESSION_LIST}"]" -SLICING ({SIMPLE_SLICING}|{EXTENDED_SLICING}) -SIMPLE_SLICING {PRIMARY}"["{SHORT_SLICE}"]" -EXTENDED_SLICING {PRIMARY}"["{SLICE_LIST}"]" -SLICE_LIST {SLICE_ITEM}(","{SLICE_ITEM})*","? -SLICE_ITEM ({EXPRESSION}|{PROPER_SLICE}|{ELLIPSIS}) -PROPER_SLICE ({SHORT_SLICE}|{LONG_SLICE}) -SHORT_SLICE {LOWER_BOUND}?":"{UPPER_BOUND}? -LONG_SLICE {SHORT_SLICE}":"{STRIDE}? -LOWER_BOUND {EXPRESSION} -UPPER_BOUND {EXPRESSION} -STRIDE {EXPRESSION} -ELLIPSIS "..." -CALL {PRIMARY}"("({ARGUMENT_LIST}","?)?")" -ARGUMENT_LIST ({POSITIONAL_ARGUMENTS}(","{KEYWORD_ARGUMENTS})?(",""*"{EXPRESSION})?(",""**"{EXPRESSION})?|{KEYWORD_ARGUMENTS}(",""*"{EXPRESSION})?(",""**"{EXPRESSION})?|"*"{EXPRESSION}(",""**"{EXPRESSION})?|"**"{EXPRESSION}) -POSITIONAL_ARGUMENTS {EXPRESSION}(","{EXPRESSION})* -KEYWORD_ARGUMENTS {KEYWORD_ITEM}(","{KEYWORD_ITEM})* -KEYWORD_ITEM {IDENTIFIER}"="{EXPRESSION} -POWER {PRIMARY}("**"{U_EXPR})? -U_EXPR ({POWER}|"-"{U_EXPR}|"+"{U_EXPR}|"\~"{U_EXPR}) -M_EXPR ({U_EXPR}|{M_EXPR}"*"{U_EXPR}|{M_EXPR}"//"{U_EXPR}|{M_EXPR}"/"{U_EXPR}|{M_EXPR}"\%"{U_EXPR}) -A_EXPR ({M_EXPR}|{A_EXPR}"+"{M_EXPR}|{A_EXPR}"-"{M_EXPR} -SHIFT_EXPR ({A_EXPR}|{SHIFT_EXPR}("<<"|">>"){A_EXPR}) -AND_EXPR ({SHIFT_EXPR}|{AND_EXPR}"\;SPMamp;"{SHIFT_EXPR} -XOR_EXPR ({AND_EXPR}|{XOR_EXPR}"\textasciicircum"{AND_EXPR}) -OR_EXPR ({XOR_EXPR}|{OR_EXPR}"|"{ XOR_EXPR}) - -COMPARISON {OR_EXPR}({COMP_OPERATOR}{OR_EXPR})* -COMP_OPERATOR ("<"|">"|"=="|">="|"<="|"<>"|"!="|"is""not"?|"not"?"in") -EXPRESSION ({OR_TEST}|{LAMBDA_FORM}) -OR_TEST ({AND_TEST}|{OR_TEST}"or"{AND_TEST}) -AND_TEST ({NOT_TEST}|{AND_TEST}"and"{NOT_TEST}) -NOT_TEST ({COMPARISON}|"not"{NOT_TEST}) -LAMBDA_FORM "lambda"{PARAMETER_LIST}?":"{EXPRESSION} -EXPRESSION_LIST {EXPRESSION}(","{EXPRESSION})*","? -SIMPLE_STMT ({EXPRESSION_STMT}|{ASSERT_STMT}|{ASSIGNMENT_STMT}|{AUGMENTED_ASSIGNMENT_STMT}|{PASS_STMT}|{DEL_STMT}|{PRINT_STMT}|{RETURN_STMT}|{YIELD_STMT}|{RAISE_STMT}|{BREAK_STMT}|{CONTINUE_STMT}|{IMPORT_STMT}|{GLOBAL_STMT}|{EXEC_STMT}) -EXPRESSION_STMT {EXPRESSION_LIST} -ASSERT_STMT "assert"{EXPRESSION}(","{EXPRESSION})? -ASSIGNMENT_STMT ({TARGET_LIST}"=")+{EXPRESSION_LIST} -TARGET_LIST {TARGET}(","{TARGET})*","? -TARGET ({IDENTIFIER}|"("{TARGET_LIST}")"|"["{TARGET_LIST}"]"|{ATTRIBUTEREF}|{SUBSCRIPTION}|{SLICING}) - - -%option noyywrap -%option stack - -%x Body - -%x FunctionDec -%x FunctionParams - -%x ClassDec -%x ClassInheritance - -%x Suite -%x SuiteCaptureIndent -%x SuiteStart -%x SuiteMaintain -%x SuiteContinuing - -%x LongString - -%x SingleQuoteString -%x DoubleQuoteString -%x TripleString - -%x DocBlock -%% - -<Body,Suite>{ - "def"{BB} { - startFontClass("keyword"); - codify(yytext); - endFontClass(); - BEGIN( FunctionDec ); - } - - "class"{BB} { - startFontClass("keyword"); - codify(yytext); - endFontClass(); - BEGIN( ClassDec ); - } - "None" { - startFontClass("keywordtype"); - codify(yytext); - endFontClass(); - } - "self."{IDENTIFIER}/"."({IDENTIFIER}".")*{IDENTIFIER}"(" { - codify("self."); - findMemberLink(*g_code,&yytext[5]); - } - "self."{IDENTIFIER}/"(" { - codify("self."); - findMemberLink(*g_code,&yytext[5]); - } - "self."{IDENTIFIER}/"."({IDENTIFIER}".")*{IDENTIFIER} { - codify("self."); - findMemberLink(*g_code,&yytext[5]); - } - "self."{IDENTIFIER} { - codify("self."); - findMemberLink(*g_code,&yytext[5]); - } - "cls."{IDENTIFIER}/"."({IDENTIFIER}".")*{IDENTIFIER}"(" { - codify("cls."); - findMemberLink(*g_code,&yytext[4]); - } - "cls."{IDENTIFIER}/"(" { - codify("cls."); - findMemberLink(*g_code,&yytext[4]); - } - "cls."{IDENTIFIER}/"."({IDENTIFIER}".")*{IDENTIFIER} { - codify("cls."); - findMemberLink(*g_code,&yytext[4]); - } - "cls."{IDENTIFIER} { - codify("cls."); - findMemberLink(*g_code,&yytext[4]); - } -} - -<ClassDec>{IDENTIFIER} { - - generateClassOrGlobalLink(*g_code,yytext); - // codify(yytext); - g_curClassName = yytext; - g_curClassBases.clear(); - BEGIN( ClassInheritance ); - } - -<ClassInheritance>{ - ({BB}|[(,)]) { - codify(yytext); - } - - ({IDENTIFIER}".")*{IDENTIFIER} { - // The parser - // is assuming - // that ALL identifiers - // in this state - // are base classes; - // it doesn't check to see - // that the first parenthesis - // has been seen. - - // This is bad - it should - // probably be more strict - // about what to accept. - - g_curClassBases.inSort(yytext); - generateClassOrGlobalLink(*g_code,yytext); - // codify(yytext); - } - - ":" { - codify(yytext); - - // Assume this will - // be a one-line suite; - // found counter-example - // in SuiteStart. - - // Push a class scope - - ClassDef *classDefToAdd = createClassDef("<code>",1,1,g_curClassName,ClassDef::Class,0,0,FALSE); - g_codeClassSDict.append(g_curClassName,classDefToAdd); - char *s=g_curClassBases.first(); - while (s) - { - const ClassDef *baseDefToAdd=g_codeClassSDict[s]; - - // Try to find class in global - // scope - if (baseDefToAdd==0) - { - baseDefToAdd=getResolvedClass(g_currentDefinition,g_sourceFileDef,s); - } - - if (baseDefToAdd && baseDefToAdd!=classDefToAdd) - { - classDefToAdd->insertBaseClass(const_cast<ClassDef*>(baseDefToAdd),s,Public,Normal); - } - - s=g_curClassBases.next(); - } - - // Reset class-parsing variables. - g_curClassName.resize(0); - g_curClassBases.clear(); - - g_noSuiteFound = TRUE; - BEGIN( SuiteStart ); - } + codify(yyscanner,symName); } -<FunctionDec>{ - {IDENTIFIER} { - generateFunctionLink(*g_code,yytext); - } +//------------------------------------------------------------------------------- - {B}"(" { - codify(yytext); - BEGIN( FunctionParams ); - } -} - -<FunctionParams>{ - ({BB}|",") { - // Parses delimiters - codify(yytext); - } - - ({IDENTIFIER}|{PARAMNONEMPTY}+) { - codify(yytext); - } - - ")" { - codify(yytext); - } - - "\n" { - codifyLines(yytext); - } - - ":" { - codify(yytext); - - // Assume this will - // be a one-line suite; - // found counter-example - // in SuiteStart. - g_noSuiteFound = TRUE; - BEGIN( SuiteStart ); - } -} - -<Body,Suite>{ - - {KEYWORD} { - // Position-sensitive rules! - // Must come AFTER keyword-triggered rules - // Must come BEFORE identifier NONEMPTY-like rules - // to syntax highlight. - - startFontClass("keyword"); - codify(yytext); - endFontClass(); - } - - {FLOWKW} { - if (g_currentMemberDef && g_currentMemberDef->isFunction()) - { - g_currentMemberDef->incrementFlowKeyWordCount(); - } - startFontClass("keywordflow"); - codify(yytext); - endFontClass(); - } - ({IDENTIFIER}".")*{IDENTIFIER}/"(" { - generateClassOrGlobalLink(*g_code,yytext); - } - ({IDENTIFIER}".")+{IDENTIFIER} { - generateClassOrGlobalLink(*g_code,yytext,TRUE); - } - {IDENTIFIER} { codify(yytext); } - -} - - - -<SuiteStart>{ - - {BB} { - codify(yytext); - } - "pass" { - startFontClass("keyword"); - codifyLines(yytext); - endFontClass(); - BEGIN(Body); - } - {KEYWORD} { - startFontClass("keyword"); - codifyLines(yytext); - endFontClass(); - - // No indentation necessary - g_noSuiteFound = FALSE; - } - - {FLOWKW} { - if (g_currentMemberDef && g_currentMemberDef->isFunction()) - { - g_currentMemberDef->incrementFlowKeyWordCount(); - } - startFontClass("keywordflow"); - codifyLines(yytext); - endFontClass(); - - // No indentation necessary - g_noSuiteFound = FALSE; - } - {IDENTIFIER} { - codify(yytext); - } - - - {POUNDCOMMENT} { - if (YY_START==SingleQuoteString || - YY_START==DoubleQuoteString || - YY_START==TripleString - ) - { - REJECT; - } - yy_push_state(YY_START); - BEGIN(DocBlock); - g_docBlock=yytext; - } - - {NEWLINE} { - codifyLines(yytext); - if ( g_noSuiteFound ) - { - // printf("New suite to capture! [%d]\n", g_yyLineNr); - BEGIN ( SuiteCaptureIndent ); - } - } -} - -<SuiteCaptureIndent>{ - "\n"|({BB}"\n") { - // Blankline - ignore, keep looking for indentation. - codifyLines(yytext); - } - - {BB} { - // This state lasts momentarily, - // to check the indentation - // level that is about to be - // used. - codifyLines(yytext); - g_indents.push(static_cast<int>(yyleng)); - // printf("Captured indent of %d [line %d]\n", yyleng, g_yyLineNr); - BEGIN( Suite ); - } -} - -<SuiteMaintain>{ - - {BB}/({NONEMPTY}|{EXPCHAR}) { - // This implements poor - // indentation-tracking; - // should be improved. - // (translate tabs to space, etc) - codifyLines(yytext); - adjustScopesAndSuites(static_cast<int>(yyleng)); - } - - "\n"|({BB}"\n") { - // If this ever succeeds, - // it means that this is - // a blank line, and - // can be ignored. - codifyLines(yytext); - } - - ""/({NONEMPTY}|{EXPCHAR}) { - // Default rule; matches - // the empty string, assuming - // real text starts here. - // Just go straight to Body. - adjustScopesAndSuites(0); - } -} - - -<Suite>{NEWLINE} { - codifyLines(yytext); - BEGIN( SuiteMaintain ); - } -<Body>{IDENTIFIER} { - codify(yytext); - } -<Body>{NEWLINE} { - codifyLines(yytext); - } - -<SingleQuoteString>{ // Single quoted string like 'That\'s a """nice""" string!' - \\{B}\n { // line continuation - codifyLines(yytext); - } - \\. { // escaped char - codify(yytext); - } - {STRINGPREFIX}?{TRIDOUBLEQUOTE} { // triple double quotes - codify(yytext); - } - "'" { // end of the string - codify(yytext); - endFontClass(); - BEGIN(g_stringContext); - } - [^"'\n\\]+ { // normal chars - codify(yytext); - } - . { // normal char - codify(yytext); - } -} - -<DoubleQuoteString>{ // Double quoted string like "That's \"a '''nice'''\" string!" - \\{B}\n { // line continuation - codifyLines(yytext); - } - \\. { // escaped char - codify(yytext); - } - {STRINGPREFIX}?{TRISINGLEQUOTE} { // triple single quotes - codify(yytext); - } - "\"" { // end of the string - codify(yytext); - endFontClass(); - BEGIN(g_stringContext); - } - [^"'\n\\]+ { // normal chars - codify(yytext); - } - . { // normal char - codify(yytext); - } -} +struct PythonCodeParser::Private +{ + yyscan_t yyscanner; + pycodeYY_state state; +}; -<TripleString>{ - {TRIDOUBLEQUOTE} | - {TRISINGLEQUOTE} { - codify(yytext); - if (g_doubleQuote==(yytext[0]=='"')) - { - endFontClass(); - BEGIN(g_stringContext); - } - } - {LONGSTRINGBLOCK} { - codifyLines(yytext); - } - \n { - codifyLines(yytext); - } - . { - codify(yytext); - } +PythonCodeParser::PythonCodeParser() : p(std::make_unique<Private>()) +{ + pycodeYYlex_init_extra(&p->state,&p->yyscanner); +#ifdef FLEX_DEBUG + pycodeYYset_debug(1,p->yyscanner); +#endif + resetCodeParserState(); } - /* -<*>({NONEMPTY}|{EXPCHAR}|{BB}) { // This should go one character at a time. - codify(yytext); - // printf("[pycode] '%s' [ state %d ] [line %d] no match\n", - // yytext, YY_START, g_yyLineNr); - - //endFontClass(); - BEGIN(Body); - } - */ - -<*>{STRINGPREFIX}?{TRISINGLEQUOTE} { - if (YY_START==SingleQuoteString) REJECT; - startFontClass("stringliteral"); - g_stringContext=YY_START; - g_doubleQuote=yytext[yyleng-1]=='"'; - codify(yytext); - BEGIN(TripleString); - } -<*>{STRINGPREFIX}?{TRIDOUBLEQUOTE} { - if (YY_START==DoubleQuoteString) REJECT; - startFontClass("stringliteral"); - g_stringContext=YY_START; - g_doubleQuote=yytext[yyleng-1]=='"'; - codify(yytext); - BEGIN(TripleString); - } -<*>{STRINGPREFIX}?"'" { // single quoted string - if (YY_START==SingleQuoteString || - YY_START==DoubleQuoteString || - YY_START==TripleString - ) - { - REJECT; - } - startFontClass("stringliteral"); - g_stringContext=YY_START; - codify(yytext); - BEGIN(SingleQuoteString); - } -<*>{STRINGPREFIX}?"\"" { // double quoted string - if (YY_START==SingleQuoteString || - YY_START==DoubleQuoteString || - YY_START==TripleString - ) - { - REJECT; - } - startFontClass("stringliteral"); - g_stringContext=YY_START; - codify(yytext); - BEGIN(DoubleQuoteString); - } -<DocBlock>.* { // contents of current comment line - g_docBlock+=yytext; - } -<DocBlock>"\n"{B}("#") { // comment block (next line is also comment line) - g_docBlock+=yytext; - } -<DocBlock>{NEWLINE} { // comment block ends at the end of this line - // remove special comment (default config) - if (Config_getBool(STRIP_CODE_COMMENTS)) - { - g_yyLineNr+=((QCString)g_docBlock).contains('\n'); - g_endComment=TRUE; - } - else // do not remove comment - { - startFontClass("comment"); - codifyLines(g_docBlock); - endFontClass(); - } - unput(*yytext); - yy_pop_state(); - } -<*>{POUNDCOMMENT}.* { - if (YY_START==SingleQuoteString || - YY_START==DoubleQuoteString || - YY_START==TripleString - ) - { - REJECT; - } - yy_push_state(YY_START); - BEGIN(DocBlock); - g_docBlock=yytext; - } -<*>"#".* { // normal comment - if (YY_START==SingleQuoteString || - YY_START==DoubleQuoteString || - YY_START==TripleString - ) - { - REJECT; - } - startFontClass("comment"); - codifyLines(yytext); - endFontClass(); - } -<*>{NEWLINE} { - if (g_endComment) - { - g_endComment=FALSE; - } - else - { - codifyLines(yytext); - } - //printf("[pycode] %d NEWLINE [line %d] no match\n", - // YY_START, g_yyLineNr); - - //endFontClass(); - BEGIN(Body); - } - -<*>[ \t]+ { - codify(yytext); - BEGIN(Body); - } -<*>. { - codify(yytext); - // printf("[pycode] '%s' [ state %d ] [line %d] no match\n", - // yytext, YY_START, g_yyLineNr); - - //endFontClass(); - BEGIN(Body); - } - -<*><<EOF>> { - if (YY_START == DocBlock) { - if (!Config_getBool(STRIP_CODE_COMMENTS)) - { - startFontClass("comment"); - codifyLines(g_docBlock); - endFontClass(); - } - } - yyterminate(); - } -%% - -/*@ ---------------------------------------------------------------------------- - */ - -void resetPythonCodeParserState() +PythonCodeParser::~PythonCodeParser() { - g_codeClassSDict.setAutoDelete(TRUE); - g_codeClassSDict.clear(); - g_currentDefinition = 0; - g_currentMemberDef = 0; - g_doubleStringIsDoc = FALSE; - g_paramParens = 0; - g_indents.clear(); - BEGIN( Body ); + pycodeYYlex_destroy(p->yyscanner); } -/*! - Examines current stack of white-space indentations; - re-syncs the parser with the correct scope. -*/ -static void adjustScopesAndSuites(unsigned indentLength) +void PythonCodeParser::resetCodeParserState() { - // States to pop - if (!g_indents.isEmpty() && indentLength < g_indents.top()) - { - while (!g_indents.isEmpty() && indentLength < g_indents.top()) - { - // printf("Exited scope indent of [%d]\n", g_indents.top()); - g_indents.pop(); // Pop the old suite's indentation - - g_currentMemberDef=0; - if (g_currentDefinition) - g_currentDefinition=g_currentDefinition->getOuterScope(); - } - } - - // Are there any remaining indentation levels for suites? - if (!g_indents.isEmpty()) - { - BEGIN( Suite ); - } - else - { - BEGIN( Body ); - } + struct yyguts_t *yyg = (struct yyguts_t*)p->yyscanner; + yyextra->codeClassMap.clear(); + yyextra->currentDefinition = 0; + yyextra->currentMemberDef = 0; + yyextra->doubleStringIsDoc = FALSE; + yyextra->paramParens = 0; + while (!yyextra->indents.empty()) yyextra->indents.pop(); + BEGIN( Body ); } -void parsePythonCode(CodeOutputInterface &od,const char * /*className*/, - const QCString &s,bool exBlock, const char *exName, - FileDef *fd,int startLine,int endLine,bool inlineFragment, - const MemberDef *,bool,const Definition *searchCtx,bool collectXRefs) +void PythonCodeParser::parseCode(CodeOutputInterface &codeOutIntf, + const char *scopeName, + const QCString &input, + SrcLangExt /*lang*/, + bool isExampleBlock, + const char *exampleName, + FileDef *fileDef, + int startLine, + int endLine, + bool inlineFragment, + const MemberDef *memberDef, + bool showLineNumbers, + const Definition *searchCtx, + bool collectXRefs + ) { + yyscan_t yyscanner = p->yyscanner; + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; //printf("***parseCode()\n"); - - //-------------------------------------- - if (s.isEmpty()) return; - printlex(yy_flex_debug, TRUE, __FILE__, fd ? fd->fileName().data(): NULL); - g_codeClassSDict.setAutoDelete(TRUE); - g_code = &od; - g_inputString = s; - g_inputPosition = 0; - g_currentFontClass = 0; - g_needsTermination = FALSE; - g_searchCtx=searchCtx; - g_collectXRefs=collectXRefs; + + if (input.isEmpty()) return; + printlex(yy_flex_debug, TRUE, __FILE__, fileDef ? fileDef->fileName().data(): NULL); + yyextra->code = &codeOutIntf; + yyextra->inputString = input; + yyextra->inputPosition = 0; + yyextra->currentFontClass = 0; + yyextra->needsTermination = FALSE; + yyextra->searchCtx=searchCtx; + yyextra->collectXRefs=collectXRefs; 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; - - - g_exampleBlock = exBlock; - g_exampleName = exName; - g_sourceFileDef = fd; + yyextra->inputLines = yyextra->yyLineNr + countLines(yyscanner) - 1; + + + yyextra->exampleBlock = isExampleBlock; + yyextra->exampleName = exampleName; + yyextra->sourceFileDef = fileDef; + yyextra->symbolResolver.setFileScope(fileDef); bool cleanupSourceDef = FALSE; - if (exBlock && fd==0) + if (yyextra->exampleBlock && fileDef==0) { // create a dummy filedef for the example - g_sourceFileDef = createFileDef("",(exName?exName:"generated")); + yyextra->sourceFileDef = createFileDef("",(exampleName?exampleName:"generated")); cleanupSourceDef = TRUE; } - if (g_sourceFileDef) + if (yyextra->sourceFileDef) { - setCurrentDoc("l00001"); + setCurrentDoc(yyscanner,"l00001"); } - g_includeCodeFragment = inlineFragment; - // Starts line 1 on the output - startCodeLine(); + yyextra->includeCodeFragment = inlineFragment; + // Starts line 1 on the output + startCodeLine(yyscanner); - pycodeYYrestart( pycodeYYin ); + pycodeYYrestart(0,yyscanner); - pycodeYYlex(); + pycodeYYlex(yyscanner); - if (!g_indents.isEmpty()) + if (!yyextra->indents.empty()) { // printf("Exited pysourceparser in inconsistent state!\n"); } - 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); - return; -} - -//---------------------------------------------------------------------------- - -void PythonCodeParser::parseCode(CodeOutputInterface &codeOutIntf, - const char *scopeName, - const QCString &input, - SrcLangExt /*lang*/, - bool isExampleBlock, - const char *exampleName, - FileDef *fileDef, - int startLine, - int endLine, - bool inlineFragment, - const MemberDef *memberDef, - bool showLineNumbers, - const Definition *searchCtx, - bool collectXRefs - ) -{ - ::parsePythonCode(codeOutIntf,scopeName,input,isExampleBlock,exampleName, - fileDef,startLine,endLine,inlineFragment,memberDef, - showLineNumbers,searchCtx,collectXRefs); -} - -void PythonCodeParser::resetCodeParserState() -{ - ::resetPythonCodeParserState(); + // write the tooltips + TooltipManager::instance().writeTooltips(codeOutIntf); + printlex(yy_flex_debug, FALSE, __FILE__, fileDef ? fileDef->fileName().data(): NULL); } #if USE_STATE2STRING diff --git a/src/pyscanner.l b/src/pyscanner.l index d7996b4..4a9552e 100644 --- a/src/pyscanner.l +++ b/src/pyscanner.l @@ -113,6 +113,7 @@ struct pyscannerYY_state int search_count = 0; QCString argType; bool funcParamsEnd = FALSE; + std::vector<QCString> decorators; }; //----------------------------------------------------------------------------- @@ -175,6 +176,7 @@ NONEMPTYEXP [^ \t\n:] PARAMNONEMPTY [^ \t\n():] IDENTIFIER ({LETTER}|"_")({LETTER}|{DIGIT}|"_")* SCOPE {IDENTIFIER}("."{IDENTIFIER})* +CALL "("[^)]*")" BORDER ([^A-Za-z0-9]) TRISINGLEQUOTE {STRINGPREFIX}?"'''"(!)? @@ -335,6 +337,8 @@ STARTDOCSYMS "##" "@staticmethod" { yyextra->stat=TRUE; } + "@"{SCOPE}{CALL}? { // decorator + } {SCRIPTCOMMENT} { // Unix type script comment if (yyextra->yyLineNr != 1) REJECT; } @@ -651,6 +655,7 @@ STARTDOCSYMS "##" {B}":"{B} { // function without arguments yyextra->specialBlock = TRUE; // expecting a docstring yyextra->bodyEntry = yyextra->current; + yyextra->current->bodyLine = yyextra->yyLineNr; BEGIN(FunctionBody); } @@ -1322,7 +1327,6 @@ STARTDOCSYMS "##" \n/{B}"#" { // continuation of the comment on the next line yyextra->docBlock+='\n'; yyextra->docBrief = FALSE; - startCommentBlock(yyscanner,FALSE); incLineNr(yyscanner); } [^#\n]+ { // any other stuff @@ -1426,7 +1430,7 @@ STARTDOCSYMS "##" } <*>"'" { - fprintf(stderr,"Quote: %d\n",YY_START); + //fprintf(stderr,"Quote: %d\n",YY_START); } <*>. { @@ -1626,7 +1630,7 @@ static void handleCommentBlock(yyscan_t yyscanner,const QCString &doc,bool brief } int position = 0; - bool needsEntry; + bool needsEntry = false; int lineNr = brief ? yyextra->current->briefLine : yyextra->current->docLine; Markdown markdown(yyextra->yyFileName,lineNr); QCString processedDoc = Config_getBool(MARKDOWN_SUPPORT) ? markdown.process(doc,lineNr) : doc; @@ -1711,7 +1715,7 @@ static void initSpecialBlock(yyscan_t yyscanner) yyextra->docBrief = TRUE; yyextra->docBlock.resize(0); yyextra->commentIndent = yyextra->curIndent; - startCommentBlock(yyscanner,TRUE); + startCommentBlock(yyscanner,FALSE); } static void searchFoundDef(yyscan_t yyscanner) @@ -1757,8 +1761,8 @@ static void parseCompounds(yyscan_t yyscanner,std::shared_ptr<Entry> rt) std::shared_ptr<Entry> ce = rt->children()[i]; if (!ce->program.isEmpty()) { - //printf("-- %s ---------\n%s\n---------------\n", - // ce->name.data(),ce->program.data()); + //fprintf(stderr,"parseCompounds: -- %s (line %d) ---------\n%s\n---------------\n", + // ce->name.data(), ce->bodyLine, ce->program.data()); // init scanner state yyextra->inputString = ce->program; yyextra->inputPosition = 0; diff --git a/src/reflist.cpp b/src/reflist.cpp index 0aaa75f..5840138 100644 --- a/src/reflist.cpp +++ b/src/reflist.cpp @@ -60,7 +60,7 @@ void RefList::generatePage() std::sort(m_entries.begin(),m_entries.end(), [](std::unique_ptr<RefItem> &left,std::unique_ptr<RefItem> &right) - { return qstricmp(left->title(),left->title()); }); + { return qstricmp(left->title(),right->title()) < 0; }); //RefItem *item; QCString doc; int cnt = 0; @@ -124,6 +124,6 @@ void RefList::generatePage() //printf("generatePage('%s')\n",doc.data()); if (cnt>0) { - addRelatedPage(m_listName,m_pageTitle,doc,m_fileName,1,RefItemVector(),0,0,TRUE); + addRelatedPage(m_listName,m_pageTitle,doc,m_fileName,1,1,RefItemVector(),0,0,TRUE); } } diff --git a/src/rtfdocvisitor.cpp b/src/rtfdocvisitor.cpp index fbe7cc1..2bd2c29 100644 --- a/src/rtfdocvisitor.cpp +++ b/src/rtfdocvisitor.cpp @@ -306,9 +306,8 @@ void RTFDocVisitor::visit(DocVerbatim *s) m_t << "{" << endl; m_t << "\\par" << endl; m_t << rtf_Style_Reset << getStyle("CodeExample"); - Doxygen::parserManager->getCodeParser(lang) - .parseCode(m_ci,s->context(),s->text(),langExt, - s->isExample(),s->exampleFile()); + getCodeParser(lang).parseCode(m_ci,s->context(),s->text(),langExt, + s->isExample(),s->exampleFile()); //m_t << "\\par" << endl; m_t << "}" << endl; break; @@ -433,8 +432,7 @@ void RTFDocVisitor::visit(DocInclude *inc) m_t << rtf_Style_Reset << getStyle("CodeExample"); QFileInfo cfi( inc->file() ); FileDef *fd = createFileDef( cfi.dirPath().utf8(), cfi.fileName().utf8() ); - Doxygen::parserManager->getCodeParser(inc->extension()) - .parseCode(m_ci,inc->context(), + getCodeParser(inc->extension()).parseCode(m_ci,inc->context(), inc->text(), langExt, inc->isExample(), @@ -455,8 +453,7 @@ void RTFDocVisitor::visit(DocInclude *inc) m_t << "{" << endl; m_t << "\\par" << endl; m_t << rtf_Style_Reset << getStyle("CodeExample"); - Doxygen::parserManager->getCodeParser(inc->extension()) - .parseCode(m_ci,inc->context(), + getCodeParser(inc->extension()).parseCode(m_ci,inc->context(), inc->text(),langExt,inc->isExample(), inc->exampleFile(), 0, // fileDef @@ -492,8 +489,7 @@ void RTFDocVisitor::visit(DocInclude *inc) m_t << "{" << endl; if (!m_lastIsPara) m_t << "\\par" << endl; m_t << rtf_Style_Reset << getStyle("CodeExample"); - Doxygen::parserManager->getCodeParser(inc->extension()) - .parseCode(m_ci, + getCodeParser(inc->extension()).parseCode(m_ci, inc->context(), extractBlock(inc->text(),inc->blockId()), langExt, @@ -509,8 +505,7 @@ void RTFDocVisitor::visit(DocInclude *inc) m_t << "{" << endl; if (!m_lastIsPara) m_t << "\\par" << endl; m_t << rtf_Style_Reset << getStyle("CodeExample"); - Doxygen::parserManager->getCodeParser(inc->extension()) - .parseCode(m_ci, + getCodeParser(inc->extension()).parseCode(m_ci, inc->context(), extractBlock(inc->text(),inc->blockId()), langExt, @@ -567,8 +562,7 @@ void RTFDocVisitor::visit(DocIncOperator *op) fd = createFileDef( cfi.dirPath().utf8(), cfi.fileName().utf8() ); } - Doxygen::parserManager->getCodeParser(locLangExt) - .parseCode(m_ci,op->context(),op->text(),langExt, + getCodeParser(locLangExt).parseCode(m_ci,op->context(),op->text(),langExt, op->isExample(),op->exampleFile(), fd, // fileDef op->line(), // startLine diff --git a/src/rtfgen.cpp b/src/rtfgen.cpp index dff4cdd..17ed794 100644 --- a/src/rtfgen.cpp +++ b/src/rtfgen.cpp @@ -48,8 +48,6 @@ #include "filename.h" #include "namespacedef.h" -static bool DoxyCodeLineOpen = FALSE; - //#define DBG_RTF(x) x; #define DBG_RTF(x) @@ -374,7 +372,7 @@ void RTFGenerator::beginRTFSection() t << rtf_Style["Heading2"]->reference() << "\n"; } -void RTFGenerator::startFile(const char *name,const char *,const char *) +void RTFGenerator::startFile(const char *name,const char *,const char *,int) { //setEncoding(QCString().sprintf("CP%s",theTranslator->trRTFansicp())); QCString fileName=name; @@ -528,7 +526,8 @@ void RTFGenerator::startIndexSection(IndexSections is) { if (cd->isLinkableInProject() && cd->templateMaster()==0 && - !cd->isEmbeddedInOuterScope() + !cd->isEmbeddedInOuterScope() && + !cd->isAlias() ) { beginRTFChapter(); @@ -630,7 +629,7 @@ void RTFGenerator::endIndexSection(IndexSections is) { DocText *root = validatingParseText(projectName); t << "{\\field\\fldedit {\\*\\fldinst TITLE \\\\*MERGEFORMAT}{\\fldrslt "; - writeDoc(root,0,0); + writeDoc(root,0,0,0); t << "}}\\par" << endl; } @@ -785,7 +784,7 @@ void RTFGenerator::endIndexSection(IndexSections is) bool found=FALSE; for (nli.toFirst();(nd=nli.current()) && !found;++nli) { - if (nd->isLinkableInProject()) + if (nd->isLinkableInProject() && !nd->isAlias()) { t << "\\par " << rtf_Style_Reset << endl; t << "{\\field\\fldedit{\\*\\fldinst INCLUDETEXT \""; @@ -796,7 +795,7 @@ void RTFGenerator::endIndexSection(IndexSections is) } while ((nd=nli.current())) { - if (nd->isLinkableInProject()) + if (nd->isLinkableInProject() && !nd->isAlias()) { t << "\\par " << rtf_Style_Reset << endl; beginRTFSection(); @@ -825,7 +824,8 @@ void RTFGenerator::endIndexSection(IndexSections is) { if (cd->isLinkableInProject() && cd->templateMaster()==0 && - !cd->isEmbeddedInOuterScope() + !cd->isEmbeddedInOuterScope() && + !cd->isAlias() ) { t << "\\par " << rtf_Style_Reset << endl; @@ -839,7 +839,8 @@ void RTFGenerator::endIndexSection(IndexSections is) { if (cd->isLinkableInProject() && cd->templateMaster()==0 && - !cd->isEmbeddedInOuterScope() + !cd->isEmbeddedInOuterScope() && + !cd->isAlias() ) { t << "\\par " << rtf_Style_Reset << endl; @@ -1935,22 +1936,15 @@ void RTFGenerator::writeRTFReference(const char *label) t << " \\\\*MERGEFORMAT}{\\fldrslt pagenum}}"; } -void RTFGenerator::startCodeFragment() +void RTFGenerator::startCodeFragment(const char *) { DBG_RTF(t << "{\\comment (startCodeFragment) }" << endl) t << "{" << endl; - //newParagraph(); t << rtf_Style_Reset << rtf_Code_DepthStyle(); - //styleStack.push(rtf_Style_CodeExample); } -void RTFGenerator::endCodeFragment() +void RTFGenerator::endCodeFragment(const char *) { - //newParagraph(); - //styleStack.pop(); - //printf("RTFGenerator::endCodeFragment() 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) @@ -2805,7 +2799,7 @@ void RTFGenerator::exceptionEntry(const char* prefix,bool closeBracket) t << " "; } -void RTFGenerator::writeDoc(DocNode *n,const Definition *ctx,const MemberDef *) +void RTFGenerator::writeDoc(DocNode *n,const Definition *ctx,const MemberDef *,int) { RTFDocVisitor *visitor = new RTFDocVisitor(t,*this,ctx?ctx->getDefFileExtension():QCString("")); n->accept(visitor); @@ -3043,7 +3037,7 @@ void RTFGenerator::writeLineNumber(const char *ref,const char *fileName,const ch { bool rtfHyperlinks = Config_getBool(RTF_HYPERLINKS); - DoxyCodeLineOpen = TRUE; + m_doxyCodeLineOpen = true; QCString lineNumber; lineNumber.sprintf("%05d",l); if (m_prettyCode) @@ -3070,13 +3064,13 @@ void RTFGenerator::writeLineNumber(const char *ref,const char *fileName,const ch } void RTFGenerator::startCodeLine(bool) { - DoxyCodeLineOpen = TRUE; + m_doxyCodeLineOpen = true; m_col=0; } void RTFGenerator::endCodeLine() { - if (DoxyCodeLineOpen) lineBreak(); - DoxyCodeLineOpen = FALSE; + if (m_doxyCodeLineOpen) lineBreak(); + m_doxyCodeLineOpen = false; } void RTFGenerator::startLabels() diff --git a/src/rtfgen.h b/src/rtfgen.h index ac6f580..0aebd15 100644 --- a/src/rtfgen.h +++ b/src/rtfgen.h @@ -41,9 +41,9 @@ class RTFGenerator : public OutputGenerator void setRelativePath(const QCString &path); void setSourceFileName(const QCString &sourceFileName); - void writeDoc(DocNode *,const Definition *,const MemberDef *); + void writeDoc(DocNode *,const Definition *,const MemberDef *,int); - void startFile(const char *name,const char *manName,const char *title); + void startFile(const char *name,const char *manName,const char *title,int id); void writeSearchInfo() {} void writeFooter(const char *) {} void endFile(); @@ -125,8 +125,8 @@ class RTFGenerator : public OutputGenerator void writeRuler() { rtfwriteRuler_thin(); } void writeAnchor(const char *fileName,const char *name); - void startCodeFragment(); - void endCodeFragment(); + void startCodeFragment(const char *style); + void endCodeFragment(const char *style); void writeLineNumber(const char *,const char *,const char *,int l); void startCodeLine(bool); void endCodeLine(); @@ -293,6 +293,7 @@ class RTFGenerator : public OutputGenerator bool m_omitParagraph = false; // should a the next paragraph command be ignored? int m_numCols = 0; // number of columns in a table QCString m_relPath; + bool m_doxyCodeLineOpen = false; }; #endif diff --git a/src/scanner.l b/src/scanner.l index bf1e96f..85a1f0c 100644 --- a/src/scanner.l +++ b/src/scanner.l @@ -1,12 +1,12 @@ /***************************************************************************** * - * + * * * Copyright (C) 1997-2015 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. * @@ -25,7 +25,7 @@ %{ /* - * includes + * includes */ #include <algorithm> @@ -227,15 +227,15 @@ static yy_size_t yyread(yyscan_t yyscanner,char *buf,yy_size_t max_size); /* ----------------------------------------------------------------- */ -#undef YY_INPUT -#define YY_INPUT(buf,result,max_size) result=yyread(yyscanner,buf,max_size); +#undef YY_INPUT +#define YY_INPUT(buf,result,max_size) result=yyread(yyscanner,buf,max_size); %} /* start command character */ -CMD ("\\"|"@") +CMD ("\\"|"@") BN [ \t\n\r] -BL [ \t\r]*"\n" +BL [ \t\r]*"\n" B [ \t] ID "$"?[a-z_A-Z\x80-\xFF][a-z_A-Z0-9\x80-\xFF]* SCOPENAME "$"?(({ID}?{BN}*"::"{BN}*)*)(((~|!){BN}*)?{ID}) @@ -244,7 +244,7 @@ CSSCOPENAME (({ID}?{BN}*"."{BN}*)*)((~{BN}*)?{ID}) PRE [pP][rR][eE] CODE [cC][oO][dD][eE] CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) -PHPKW ("require"|"require_once"|"include"|"include_once"|"echo")[^a-zA-Z0-9_;] +PHPKW ("require"|"require_once"|"include"|"include_once"|"echo")[^a-zA-Z0-9_;] PHPUSEKW ("public"|"private"|"protected") IDLATTR ("["[^\]]*"]"){BN}* TYPEDEFPREFIX (("typedef"{BN}+)?)((("volatile"|"const"){BN}+)?) @@ -262,139 +262,139 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) %x AlignAs %x AlignAsEnd -%x Define -%x DefineEnd -%x CompoundName -%x ClassVar -%x CSConstraintName -%x CSConstraintType -%x CSIndexer -%x ClassCategory -%x ClassTemplSpec +%x Define +%x DefineEnd +%x CompoundName +%x ClassVar +%x CSConstraintName +%x CSConstraintType +%x CSIndexer +%x ClassCategory +%x ClassTemplSpec %x CliPropertyType %x CliPropertyIndex %x CliOverride -%x Bases -%x BasesProt -%x NextSemi -%x BitFields -%x EnumBaseType -%x FindMembers -%x FindMembersPHP -%x FindMemberName +%x Bases +%x BasesProt +%x NextSemi +%x BitFields +%x EnumBaseType +%x FindMembers +%x FindMembersPHP +%x FindMemberName %x FindFields %x FindFieldArg -%x Function -%x FuncRound -%x ExcpRound -%x ExcpList -%x FuncQual +%x Function +%x FuncRound +%x ExcpRound +%x ExcpList +%x FuncQual %x TrailingReturn -%x Operator -%x Array -%x ReadBody -%x ReadNSBody -%x ReadBodyIntf -%x Using -%x UsingAlias -%x UsingAliasEnd -%x UsingDirective -%x SkipCurly -%x SkipCurlyCpp -%x SkipCurlyEndDoc +%x Operator +%x Array +%x ReadBody +%x ReadNSBody +%x ReadBodyIntf +%x Using +%x UsingAlias +%x UsingAliasEnd +%x UsingDirective +%x SkipCurly +%x SkipCurlyCpp +%x SkipCurlyEndDoc %x SkipString %x SkipPHPString -%x SkipInits -%x SkipC11Inits +%x SkipInits +%x SkipC11Inits %x SkipC11Attribute -%x SkipCPP -%x SkipCPPBlock -%x SkipComment -%x SkipCxxComment +%x SkipCPP +%x SkipCPPBlock +%x SkipComment +%x SkipCxxComment %x SkipCurlyBlock %x SkipRoundBlock -%x Sharp -%x SkipRound -%x SkipSquare -%x SkipRemainder +%x Sharp +%x SkipRound +%x SkipSquare +%x SkipRemainder %x StaticAssert %x DeclType -%x TypedefName -%x TryFunctionBlock -%x TryFunctionBlockEnd -%x Comment -%x PackageName -%x JavaImport -%x PHPUse -%x PHPUseAs -%x CSAccessorDecl -%x CSGeneric -%x PreLineCtrl -%x DefinePHP -%x DefinePHPEnd -%x OldStyleArgs -%x SkipVerbString +%x TypedefName +%x TryFunctionBlock +%x TryFunctionBlockEnd +%x Comment +%x PackageName +%x JavaImport +%x PHPUse +%x PHPUseAs +%x CSAccessorDecl +%x CSGeneric +%x PreLineCtrl +%x DefinePHP +%x DefinePHPEnd +%x OldStyleArgs +%x SkipVerbString %x ObjCMethod %x ObjCReturnType %x ObjCParams %x ObjCParamType %x ObjCProtocolList -%x ObjCPropAttr -%x ObjCSkipStatement -%x QtPropType -%x QtPropName -%x QtPropAttr -%x QtPropRead -%x QtPropWrite -%x ReadInitializer +%x ObjCPropAttr +%x ObjCSkipStatement +%x QtPropType +%x QtPropName +%x QtPropAttr +%x QtPropRead +%x QtPropWrite +%x ReadInitializer %x ReadInitializerPtr -%x UNOIDLAttributeBlock -%x GetCallType -%x CppQuote -%x EndCppQuote +%x UNOIDLAttributeBlock +%x GetCallType +%x CppQuote +%x EndCppQuote %x MemberSpec %x MemberSpecSkip -%x EndTemplate -%x FuncPtr -%x FuncPtrOperator -%x EndFuncPtr -%x ReadFuncArgType -%x ReadTempArgs -%x IDLUnionCase -%x NSAliasName -%x NSAliasArg -%x CopyString -%x CopyPHPString -%x CopyGString -%x CopyPHPGString -%x CopyRound -%x CopyCurly -%x GCopyRound -%x GCopySquare -%x GCopyCurly -%x SkipUnionSwitch -%x Specialization -%x SpecializationSingleQuote -%x SpecializationDoubleQuote -%x FuncPtrInit -%x FuncFunc -%x FuncFuncEnd -%x FuncFuncType -%x FuncFuncArray +%x EndTemplate +%x FuncPtr +%x FuncPtrOperator +%x EndFuncPtr +%x ReadFuncArgType +%x ReadTempArgs +%x IDLUnionCase +%x NSAliasName +%x NSAliasArg +%x CopyString +%x CopyPHPString +%x CopyGString +%x CopyPHPGString +%x CopyRound +%x CopyCurly +%x GCopyRound +%x GCopySquare +%x GCopyCurly +%x SkipUnionSwitch +%x Specialization +%x SpecializationSingleQuote +%x SpecializationDoubleQuote +%x FuncPtrInit +%x FuncFunc +%x FuncFuncEnd +%x FuncFuncType +%x FuncFuncArray %x CopyArgString %x CopyArgPHPString -%x CopyArgRound -%x CopyArgSharp -%x CopyArgComment -%x CopyArgCommentLine -%x CopyArgVerbatim -%x HereDoc -%x HereDocEnd -%x CopyHereDoc -%x CopyHereDocEnd -%x RawString -%x RawGString -%x CSString +%x CopyArgRound +%x CopyArgSharp +%x CopyArgComment +%x CopyArgCommentLine +%x CopyArgVerbatim +%x HereDoc +%x HereDocEnd +%x CopyHereDoc +%x CopyHereDocEnd +%x RawString +%x RawGString +%x CSString %x IDLAttribute %x IDLProp @@ -419,421 +419,421 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) /** comment parsing states */ -%x DocLine -%x DocBlock +%x DocLine +%x DocBlock %x DocCopyBlock %% -<NextSemi>"{" { - yyextra->curlyCount=0; - yyextra->needsSemi = TRUE; - BEGIN(SkipCurlyBlock); - } -<NextSemi>"(" { - yyextra->roundCount=0; - BEGIN(SkipRoundBlock); - } -<SkipRoundBlock>"(" { - ++yyextra->roundCount; - } -<SkipRoundBlock>")" { - if (yyextra->roundCount ) - --yyextra->roundCount ; - else - BEGIN( NextSemi ) ; - } -<SkipCurlyBlock>"{" { - ++yyextra->curlyCount ; - } -<SkipCurlyBlock>"}" { - if( yyextra->curlyCount ) - { - --yyextra->curlyCount ; - } - else if (yyextra->needsSemi) - { - BEGIN( NextSemi ); - } - else - { - BEGIN( FindMembers ); - } - } -<NextSemi>\' { - if (yyextra->insidePHP) - { - yyextra->lastStringContext=NextSemi; - BEGIN(SkipPHPString); - } - } -<NextSemi>{CHARLIT} { if (yyextra->insidePHP) REJECT; } -<NextSemi>\" { - yyextra->lastStringContext=NextSemi; - BEGIN(SkipString); - } -<NextSemi>[;,] { - unput(*yytext); - BEGIN( FindMembers ); - } -<BitFields>[;,] { - unput(*yytext); - BEGIN( FindMembers ); - } +<NextSemi>"{" { + yyextra->curlyCount=0; + yyextra->needsSemi = TRUE; + BEGIN(SkipCurlyBlock); + } +<NextSemi>"(" { + yyextra->roundCount=0; + BEGIN(SkipRoundBlock); + } +<SkipRoundBlock>"(" { + ++yyextra->roundCount; + } +<SkipRoundBlock>")" { + if (yyextra->roundCount ) + --yyextra->roundCount ; + else + BEGIN( NextSemi ) ; + } +<SkipCurlyBlock>"{" { + ++yyextra->curlyCount ; + } +<SkipCurlyBlock>"}" { + if( yyextra->curlyCount ) + { + --yyextra->curlyCount ; + } + else if (yyextra->needsSemi) + { + BEGIN( NextSemi ); + } + else + { + BEGIN( FindMembers ); + } + } +<NextSemi>\' { + if (yyextra->insidePHP) + { + yyextra->lastStringContext=NextSemi; + BEGIN(SkipPHPString); + } + } +<NextSemi>{CHARLIT} { if (yyextra->insidePHP) REJECT; } +<NextSemi>\" { + yyextra->lastStringContext=NextSemi; + BEGIN(SkipString); + } +<NextSemi>[;,] { + unput(*yytext); + BEGIN( FindMembers ); + } +<BitFields>[;,] { + unput(*yytext); + BEGIN( FindMembers ); + } <EnumBaseType>[{;,] { yyextra->current->args = yyextra->current->args.simplifyWhiteSpace(); - unput(*yytext); - BEGIN( ClassVar ); + unput(*yytext); + BEGIN( ClassVar ); } -<FindMembers>"<?php" { // PHP code with unsupported extension? +<FindMembers>"<?php" { // PHP code with unsupported extension? yyextra->insidePHP = TRUE; - } + } <FindMembersPHP>"<?"("php"?) { // PHP code start BEGIN( FindMembers ); - } + } <FindMembersPHP>"<script"{BN}+"language"{BN}*"="{BN}*['"]?"php"['"]?{BN}*">" { // PHP code start - lineCount(yyscanner) ; + lineCount(yyscanner) ; BEGIN( FindMembers ); - } + } <FindMembers>"?>"|"</script>" { // PHP code end - if (yyextra->insidePHP) - BEGIN( FindMembersPHP ); - else - REJECT; + if (yyextra->insidePHP) + BEGIN( FindMembersPHP ); + else + REJECT; } <FindMembersPHP>[^\n<]+ { // Non-PHP code text, ignore - } + } <FindMembersPHP>\n { // Non-PHP code text, ignore lineCount(yyscanner); - } + } <FindMembersPHP>. { // Non-PHP code text, ignore - } -<FindMembers>{PHPKW} { if (yyextra->insidePHP) - BEGIN( NextSemi ); - else - REJECT; - } -<FindMembers>"%{"[^\n]* { // Mozilla XPIDL lang-specific block - if (!yyextra->insideIDL) - REJECT; - } -<FindMembers>"%}" { // Mozilla XPIDL lang-specific block end - if (!yyextra->insideIDL) - REJECT; - } -<FindMembers>{B}*("properties"){BN}*":"{BN}* { // IDL or Borland C++ builder property - yyextra->current->mtype = yyextra->mtype = Property; - yyextra->current->protection = yyextra->protection = Public ; - yyextra->current->type.resize(0); - yyextra->current->name.resize(0); - yyextra->current->args.resize(0); - yyextra->current->argList.clear(); - lineCount(yyscanner) ; - } + } +<FindMembers>{PHPKW} { if (yyextra->insidePHP) + BEGIN( NextSemi ); + else + REJECT; + } +<FindMembers>"%{"[^\n]* { // Mozilla XPIDL lang-specific block + if (!yyextra->insideIDL) + REJECT; + } +<FindMembers>"%}" { // Mozilla XPIDL lang-specific block end + if (!yyextra->insideIDL) + REJECT; + } +<FindMembers>{B}*("properties"){BN}*":"{BN}* { // IDL or Borland C++ builder property + yyextra->current->mtype = yyextra->mtype = Property; + yyextra->current->protection = yyextra->protection = Public ; + yyextra->current->type.resize(0); + yyextra->current->name.resize(0); + yyextra->current->args.resize(0); + yyextra->current->argList.clear(); + lineCount(yyscanner) ; + } <FindMembers>{B}*"k_dcop"{BN}*":"{BN}* { yyextra->current->mtype = yyextra->mtype = DCOP; - yyextra->current->protection = yyextra->protection = Public ; - yyextra->current->type.resize(0); - yyextra->current->name.resize(0); - yyextra->current->args.resize(0); - yyextra->current->argList.clear(); - lineCount(yyscanner) ; - } + yyextra->current->protection = yyextra->protection = Public ; + yyextra->current->type.resize(0); + yyextra->current->name.resize(0); + yyextra->current->args.resize(0); + yyextra->current->argList.clear(); + lineCount(yyscanner) ; + } <FindMembers>{B}*("signals"|"Q_SIGNALS"){BN}*":"{BN}* { yyextra->current->mtype = yyextra->mtype = Signal; - - yyextra->current->protection = yyextra->protection = Public ; - yyextra->current->type.resize(0); - yyextra->current->name.resize(0); - yyextra->current->args.resize(0); - yyextra->current->argList.clear(); - lineCount(yyscanner) ; - } + + yyextra->current->protection = yyextra->protection = Public ; + yyextra->current->type.resize(0); + yyextra->current->name.resize(0); + yyextra->current->args.resize(0); + yyextra->current->argList.clear(); + lineCount(yyscanner) ; + } <FindMembers>{B}*"public"{BN}*("slots"|"Q_SLOTS"){BN}*":"{BN}* { - yyextra->current->protection = yyextra->protection = Public ; - yyextra->current->mtype = yyextra->mtype = Slot; - yyextra->current->type.resize(0); - yyextra->current->name.resize(0); - yyextra->current->args.resize(0); - yyextra->current->argList.clear(); - lineCount(yyscanner); - } + yyextra->current->protection = yyextra->protection = Public ; + yyextra->current->mtype = yyextra->mtype = Slot; + yyextra->current->type.resize(0); + yyextra->current->name.resize(0); + yyextra->current->args.resize(0); + yyextra->current->argList.clear(); + lineCount(yyscanner); + } <FindMembers>{B}*"protected"{BN}*("slots"|"Q_SLOTS"){BN}*":"{BN}* { - yyextra->current->protection = yyextra->protection = Protected ; - yyextra->current->mtype = yyextra->mtype = Slot; - yyextra->current->type.resize(0); - yyextra->current->name.resize(0); - yyextra->current->args.resize(0); - yyextra->current->argList.clear(); - lineCount(yyscanner); - } + yyextra->current->protection = yyextra->protection = Protected ; + yyextra->current->mtype = yyextra->mtype = Slot; + yyextra->current->type.resize(0); + yyextra->current->name.resize(0); + yyextra->current->args.resize(0); + yyextra->current->argList.clear(); + lineCount(yyscanner); + } <FindMembers>{B}*"private"{BN}*("slots"|"Q_SLOTS"){BN}*":"{BN}* { - yyextra->current->protection = yyextra->protection = Private ; - yyextra->current->mtype = yyextra->mtype = Slot; - yyextra->current->type.resize(0); - yyextra->current->name.resize(0); - yyextra->current->args.resize(0); - yyextra->current->argList.clear(); - lineCount(yyscanner); - } -<FindMembers>{B}*("public"|"methods"|"__published"){BN}*":"{BN}* { - yyextra->current->protection = yyextra->protection = Public ; - yyextra->current->mtype = yyextra->mtype = Method; - yyextra->current->type.resize(0); - yyextra->current->name.resize(0); - yyextra->current->args.resize(0); - yyextra->current->argList.clear(); - lineCount(yyscanner) ; - } + yyextra->current->protection = yyextra->protection = Private ; + yyextra->current->mtype = yyextra->mtype = Slot; + yyextra->current->type.resize(0); + yyextra->current->name.resize(0); + yyextra->current->args.resize(0); + yyextra->current->argList.clear(); + lineCount(yyscanner); + } +<FindMembers>{B}*("public"|"methods"|"__published"){BN}*":"{BN}* { + yyextra->current->protection = yyextra->protection = Public ; + yyextra->current->mtype = yyextra->mtype = Method; + yyextra->current->type.resize(0); + yyextra->current->name.resize(0); + yyextra->current->args.resize(0); + yyextra->current->argList.clear(); + lineCount(yyscanner) ; + } <FindMembers>{B}*"internal"{BN}*":"{BN}* { // for now treat C++/CLI's internal as package... - if (yyextra->insideCli) - { - yyextra->current->protection = yyextra->protection = Package ; - yyextra->current->mtype = yyextra->mtype = Method; - yyextra->current->type.resize(0); - yyextra->current->name.resize(0); - yyextra->current->args.resize(0); - yyextra->current->argList.clear(); - lineCount(yyscanner) ; - } - else - { - REJECT; - } - } -<FindMembers>{B}*"protected"{BN}*":"{BN}* { - yyextra->current->protection = yyextra->protection = Protected ; - yyextra->current->mtype = yyextra->mtype = Method; - yyextra->current->type.resize(0); - yyextra->current->name.resize(0); - yyextra->current->args.resize(0); - yyextra->current->argList.clear(); - lineCount(yyscanner) ; - } -<FindMembers>{B}*"private"{BN}*":"{BN}* { - yyextra->current->protection = yyextra->protection = Private ; - yyextra->current->mtype = yyextra->mtype = Method; - yyextra->current->type.resize(0); - yyextra->current->name.resize(0); - yyextra->current->args.resize(0); - yyextra->current->argList.clear(); - lineCount(yyscanner) ; - } -<FindMembers>{B}*"event"{BN}+ { - if (yyextra->insideCli) - { - // C++/CLI event - lineCount(yyscanner) ; - yyextra->current->mtype = yyextra->mtype = Event; - yyextra->current->bodyLine = yyextra->yyLineNr; - yyextra->current->bodyColumn = yyextra->yyColNr; - yyextra->curlyCount=0; - BEGIN( CliPropertyType ); - } - else if (yyextra->insideCS) - { - lineCount(yyscanner) ; - yyextra->current->mtype = Event; - yyextra->current->bodyLine = yyextra->yyLineNr; - yyextra->current->bodyColumn = yyextra->yyColNr; - } - else - { - REJECT; - } - } -<FindMembers>{B}*"property"{BN}+ { - if (yyextra->insideCli) - { - // C++/CLI property - lineCount(yyscanner) ; - yyextra->current->mtype = yyextra->mtype = Property; - yyextra->current->bodyLine = yyextra->yyLineNr; - yyextra->current->bodyColumn = yyextra->yyColNr; - yyextra->curlyCount=0; - BEGIN( CliPropertyType ); - } - else - { - REJECT; - } - } -<CliPropertyType>{ID} { - addType(yyscanner); - yyextra->current->name = yytext; - } -<CliPropertyType>"[" { // C++/CLI indexed property - yyextra->current->args = "["; - BEGIN( CliPropertyIndex ); - } -<CliPropertyType>"{" { - yyextra->curlyCount=0; - //printf("event: '%s' '%s'\n",yyextra->current->type.data(),yyextra->current->name.data()); - BEGIN( CSAccessorDecl ); - } -<CliPropertyType>";" { - unput(*yytext); - BEGIN( FindMembers ); - } -<CliPropertyType>\n { + if (yyextra->insideCli) + { + yyextra->current->protection = yyextra->protection = Package ; + yyextra->current->mtype = yyextra->mtype = Method; + yyextra->current->type.resize(0); + yyextra->current->name.resize(0); + yyextra->current->args.resize(0); + yyextra->current->argList.clear(); + lineCount(yyscanner) ; + } + else + { + REJECT; + } + } +<FindMembers>{B}*"protected"{BN}*":"{BN}* { + yyextra->current->protection = yyextra->protection = Protected ; + yyextra->current->mtype = yyextra->mtype = Method; + yyextra->current->type.resize(0); + yyextra->current->name.resize(0); + yyextra->current->args.resize(0); + yyextra->current->argList.clear(); + lineCount(yyscanner) ; + } +<FindMembers>{B}*"private"{BN}*":"{BN}* { + yyextra->current->protection = yyextra->protection = Private ; + yyextra->current->mtype = yyextra->mtype = Method; + yyextra->current->type.resize(0); + yyextra->current->name.resize(0); + yyextra->current->args.resize(0); + yyextra->current->argList.clear(); + lineCount(yyscanner) ; + } +<FindMembers>{B}*"event"{BN}+ { + if (yyextra->insideCli) + { + // C++/CLI event + lineCount(yyscanner) ; + yyextra->current->mtype = yyextra->mtype = Event; + yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->current->bodyColumn = yyextra->yyColNr; + yyextra->curlyCount=0; + BEGIN( CliPropertyType ); + } + else if (yyextra->insideCS) + { + lineCount(yyscanner) ; + yyextra->current->mtype = Event; + yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->current->bodyColumn = yyextra->yyColNr; + } + else + { + REJECT; + } + } +<FindMembers>{B}*"property"{BN}+ { + if (yyextra->insideCli) + { + // C++/CLI property + lineCount(yyscanner) ; + yyextra->current->mtype = yyextra->mtype = Property; + yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->current->bodyColumn = yyextra->yyColNr; + yyextra->curlyCount=0; + BEGIN( CliPropertyType ); + } + else + { + REJECT; + } + } +<CliPropertyType>{ID} { + addType(yyscanner); + yyextra->current->name = yytext; + } +<CliPropertyType>"[" { // C++/CLI indexed property + yyextra->current->args = "["; + BEGIN( CliPropertyIndex ); + } +<CliPropertyType>"{" { + yyextra->curlyCount=0; + //printf("event: '%s' '%s'\n",yyextra->current->type.data(),yyextra->current->name.data()); + BEGIN( CSAccessorDecl ); + } +<CliPropertyType>";" { + unput(*yytext); + BEGIN( FindMembers ); + } +<CliPropertyType>\n { lineCount(yyscanner); - } -<CliPropertyType>{B}* { - } -<CliPropertyType>. { - addType(yyscanner); - yyextra->current->type += yytext; - } -<CliPropertyIndex>"]" { + } +<CliPropertyType>{B}* { + } +<CliPropertyType>. { + addType(yyscanner); + yyextra->current->type += yytext; + } +<CliPropertyIndex>"]" { BEGIN( CliPropertyType ); - yyextra->current->args+=yytext; - } -<CliPropertyIndex>. { - yyextra->current->args+=yytext; - } + yyextra->current->args+=yytext; + } +<CliPropertyIndex>. { + yyextra->current->args+=yytext; + } /* -<FindMembers>{B}*"property"{BN}+ { +<FindMembers>{B}*"property"{BN}+ { if (!yyextra->current->type.isEmpty()) - { - REJECT; + { + REJECT; } - else - { + else + { yyextra->current->mtype = yyextra->mtype = Property; lineCount(yyscanner); - } + } } */ -<FindMembers>{B}*"@private"{BN}+ { - yyextra->current->protection = yyextra->protection = Private ; - yyextra->current->mtype = yyextra->mtype = Method; - yyextra->current->type.resize(0); - yyextra->current->name.resize(0); - yyextra->current->args.resize(0); - yyextra->current->argList.clear(); - lineCount(yyscanner) ; - } -<FindMembers>{B}*"@protected"{BN}+ { - yyextra->current->protection = yyextra->protection = Protected ; - yyextra->current->mtype = yyextra->mtype = Method; - yyextra->current->type.resize(0); - yyextra->current->name.resize(0); - yyextra->current->args.resize(0); - yyextra->current->argList.clear(); - lineCount(yyscanner) ; - } -<FindMembers>{B}*"@public"{BN}+ { - yyextra->current->protection = yyextra->protection = Public ; - yyextra->current->mtype = yyextra->mtype = Method; - yyextra->current->type.resize(0); - yyextra->current->name.resize(0); - yyextra->current->args.resize(0); - yyextra->current->argList.clear(); - lineCount(yyscanner) ; - } -<FindMembers>[\-+]{BN}* { - if (!yyextra->insideObjC) - { - REJECT; - } - else - { - lineCount(yyscanner); - yyextra->current->fileName = yyextra->yyFileName; - yyextra->current->startLine = yyextra->yyLineNr; - yyextra->current->startColumn = yyextra->yyColNr; - yyextra->current->bodyLine = yyextra->yyLineNr; - yyextra->current->bodyColumn = yyextra->yyColNr; - yyextra->current->section = Entry::FUNCTION_SEC; - yyextra->current->protection = yyextra->protection = Public ; - yyextra->language = yyextra->current->lang = SrcLangExt_ObjC; - yyextra->insideObjC = TRUE; - yyextra->current->virt = Virtual; - yyextra->current->stat=yytext[0]=='+'; - yyextra->current->mtype = yyextra->mtype = Method; - yyextra->current->type.resize(0); - yyextra->current->name.resize(0); - yyextra->current->args.resize(0); - yyextra->current->argList.clear(); - BEGIN( ObjCMethod ); - } - } -<ObjCMethod>"(" { // start of method's return type - BEGIN( ObjCReturnType ); - } -<ObjCMethod>{ID} { // found method name - if (yyextra->current->type.isEmpty()) - { - yyextra->current->type = "id"; - } - yyextra->current->name = yytext; +<FindMembers>{B}*"@private"{BN}+ { + yyextra->current->protection = yyextra->protection = Private ; + yyextra->current->mtype = yyextra->mtype = Method; + yyextra->current->type.resize(0); + yyextra->current->name.resize(0); + yyextra->current->args.resize(0); + yyextra->current->argList.clear(); + lineCount(yyscanner) ; + } +<FindMembers>{B}*"@protected"{BN}+ { + yyextra->current->protection = yyextra->protection = Protected ; + yyextra->current->mtype = yyextra->mtype = Method; + yyextra->current->type.resize(0); + yyextra->current->name.resize(0); + yyextra->current->args.resize(0); + yyextra->current->argList.clear(); + lineCount(yyscanner) ; + } +<FindMembers>{B}*"@public"{BN}+ { + yyextra->current->protection = yyextra->protection = Public ; + yyextra->current->mtype = yyextra->mtype = Method; + yyextra->current->type.resize(0); + yyextra->current->name.resize(0); + yyextra->current->args.resize(0); + yyextra->current->argList.clear(); + lineCount(yyscanner) ; + } +<FindMembers>[\-+]{BN}* { + if (!yyextra->insideObjC) + { + REJECT; + } + else + { + lineCount(yyscanner); + yyextra->current->fileName = yyextra->yyFileName; + yyextra->current->startLine = yyextra->yyLineNr; + yyextra->current->startColumn = yyextra->yyColNr; + yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->current->bodyColumn = yyextra->yyColNr; + yyextra->current->section = Entry::FUNCTION_SEC; + yyextra->current->protection = yyextra->protection = Public ; + yyextra->language = yyextra->current->lang = SrcLangExt_ObjC; + yyextra->insideObjC = TRUE; + yyextra->current->virt = Virtual; + yyextra->current->stat=yytext[0]=='+'; + yyextra->current->mtype = yyextra->mtype = Method; + yyextra->current->type.resize(0); + yyextra->current->name.resize(0); + yyextra->current->args.resize(0); + yyextra->current->argList.clear(); + BEGIN( ObjCMethod ); + } + } +<ObjCMethod>"(" { // start of method's return type + BEGIN( ObjCReturnType ); + } +<ObjCMethod>{ID} { // found method name + if (yyextra->current->type.isEmpty()) + { + yyextra->current->type = "id"; + } + yyextra->current->name = yytext; if (yyextra->clangParser && (yyextra->insideCpp || yyextra->insideObjC)) { yyextra->current->id = yyextra->clangParser->lookup(yyextra->yyLineNr,yytext); } - } -<ObjCMethod>":"{B}* { // start of parameter list - yyextra->current->name += ':'; - Argument a; - yyextra->current->argList.push_back(a); - BEGIN( ObjCParams ); - } -<ObjCReturnType>[^)]* { // TODO: check if nested braches are possible. - yyextra->current->type = yytext; - } -<ObjCReturnType>")" { - BEGIN( ObjCMethod ); - } -<ObjCParams>({ID})?{BN}*":" { // Keyword of parameter - QCString keyw = yytext; - keyw=keyw.left(keyw.length()-1).stripWhiteSpace(); // strip : - if (keyw.isEmpty()) - { - yyextra->current->name += " :"; - } - else - { - yyextra->current->name += keyw+":"; - } - if (yyextra->current->argList.back().type.isEmpty()) - { - yyextra->current->argList.back().type="id"; - } - Argument a; - a.attrib=(QCString)"["+keyw+"]"; - yyextra->current->argList.push_back(a); - } -<ObjCParams>{ID}{BN}* { // name of parameter - lineCount(yyscanner); - yyextra->current->argList.back().name=QCString(yytext).stripWhiteSpace(); - } -<ObjCParams>","{BN}*"..." { // name of parameter - lineCount(yyscanner); - // do we want the comma as part of the name? - //yyextra->current->name += ","; - Argument a; - a.attrib="[,]"; - a.type="..."; - yyextra->current->argList.push_back(a); - } + } +<ObjCMethod>":"{B}* { // start of parameter list + yyextra->current->name += ':'; + Argument a; + yyextra->current->argList.push_back(a); + BEGIN( ObjCParams ); + } +<ObjCReturnType>[^)]* { // TODO: check if nested braches are possible. + yyextra->current->type = yytext; + } +<ObjCReturnType>")" { + BEGIN( ObjCMethod ); + } +<ObjCParams>({ID})?{BN}*":" { // Keyword of parameter + QCString keyw = yytext; + keyw=keyw.left(keyw.length()-1).stripWhiteSpace(); // strip : + if (keyw.isEmpty()) + { + yyextra->current->name += " :"; + } + else + { + yyextra->current->name += keyw+":"; + } + if (yyextra->current->argList.back().type.isEmpty()) + { + yyextra->current->argList.back().type="id"; + } + Argument a; + a.attrib=(QCString)"["+keyw+"]"; + yyextra->current->argList.push_back(a); + } +<ObjCParams>{ID}{BN}* { // name of parameter + lineCount(yyscanner); + yyextra->current->argList.back().name=QCString(yytext).stripWhiteSpace(); + } +<ObjCParams>","{BN}*"..." { // name of parameter + lineCount(yyscanner); + // do we want the comma as part of the name? + //yyextra->current->name += ","; + Argument a; + a.attrib="[,]"; + a.type="..."; + yyextra->current->argList.push_back(a); + } /* -<ObjCParams>":" { - yyextra->current->name += ':'; - } +<ObjCParams>":" { + yyextra->current->name += ':'; + } */ -<ObjCParams>"(" { - yyextra->roundCount=0; - yyextra->current->argList.back().type.resize(0); - BEGIN( ObjCParamType ); - } +<ObjCParams>"(" { + yyextra->roundCount=0; + yyextra->current->argList.back().type.resize(0); + BEGIN( ObjCParamType ); + } <ObjCParamType>"(" { yyextra->roundCount++; - yyextra->current->argList.back().type+=yytext; + yyextra->current->argList.back().type+=yytext; } -<ObjCParamType>")"/{B}* { +<ObjCParamType>")"/{B}* { if (yyextra->roundCount<=0) { BEGIN( ObjCParams ); @@ -843,221 +843,221 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) yyextra->current->argList.back().type+=yytext; yyextra->roundCount--; } - } -<ObjCParamType>[^()]* { - yyextra->current->argList.back().type+=QCString(yytext).stripWhiteSpace(); - } -<ObjCMethod,ObjCParams>";" { // end of method declaration - if (!yyextra->current->argList.empty() && yyextra->current->argList.back().type.isEmpty()) - { - yyextra->current->argList.back().type="id"; - } + } +<ObjCParamType>[^()]* { + yyextra->current->argList.back().type+=QCString(yytext).stripWhiteSpace(); + } +<ObjCMethod,ObjCParams>";" { // end of method declaration + if (!yyextra->current->argList.empty() && yyextra->current->argList.back().type.isEmpty()) + { + yyextra->current->argList.back().type="id"; + } if (yyextra->current->argList.empty()) // method without parameters { yyextra->current->argList.setNoParameters(TRUE); } - yyextra->current->args = argListToString(yyextra->current->argList); - //printf("argList=%s\n",yyextra->current->args.data()); - unput(';'); - BEGIN( Function ); + yyextra->current->args = argListToString(yyextra->current->argList); + //printf("argList=%s\n",yyextra->current->args.data()); + unput(';'); + BEGIN( Function ); } -<ObjCMethod,ObjCParams>(";"{BN}+)?"{" { // start of a method body - lineCount(yyscanner); +<ObjCMethod,ObjCParams>(";"{BN}+)?"{" { // start of a method body + lineCount(yyscanner); //printf("Type=%s Name=%s args=%s\n", - // yyextra->current->type.data(),yyextra->current->name.data(),argListToString(yyextra->current->argList).data() - // ); - if (!yyextra->current->argList.empty() && yyextra->current->argList.back().type.isEmpty()) - { - yyextra->current->argList.back().type="id"; - } + // yyextra->current->type.data(),yyextra->current->name.data(),argListToString(yyextra->current->argList).data() + // ); + if (!yyextra->current->argList.empty() && yyextra->current->argList.back().type.isEmpty()) + { + yyextra->current->argList.back().type="id"; + } if (yyextra->current->argList.empty()) // method without parameters { yyextra->current->argList.setNoParameters(TRUE); } - yyextra->current->args = argListToString(yyextra->current->argList); + yyextra->current->args = argListToString(yyextra->current->argList); unput('{'); - BEGIN( Function ); - } + BEGIN( Function ); + } <FindMembers>{B}*"sequence"{BN}*"<"{BN}* { - if (yyextra->insideSlice) - { + if (yyextra->insideSlice) + { lineCount(yyscanner); - yyextra->current->bodyLine = yyextra->yyLineNr; - yyextra->current->bodyColumn = yyextra->yyColNr; + yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->current->bodyColumn = yyextra->yyColNr; yyextra->current->fileName = yyextra->yyFileName ; - yyextra->current->startLine = yyextra->yyLineNr ; - yyextra->current->startColumn = yyextra->yyColNr; + yyextra->current->startLine = yyextra->yyLineNr ; + yyextra->current->startColumn = yyextra->yyColNr; yyextra->current->args.resize(0); - yyextra->current->section = Entry::TYPEDEF_SEC ; + yyextra->current->section = Entry::TYPEDEF_SEC ; yyextra->isTypedef = TRUE; - BEGIN( SliceSequence ); - } - else - REJECT; - } + BEGIN( SliceSequence ); + } + else + REJECT; + } <FindMembers>{B}*"dictionary"{BN}*"<"{BN}* { - if (yyextra->insideSlice) - { + if (yyextra->insideSlice) + { lineCount(yyscanner); - yyextra->current->bodyLine = yyextra->yyLineNr; - yyextra->current->bodyColumn = yyextra->yyColNr; + yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->current->bodyColumn = yyextra->yyColNr; yyextra->current->fileName = yyextra->yyFileName ; - yyextra->current->startLine = yyextra->yyLineNr ; - yyextra->current->startColumn = yyextra->yyColNr; + yyextra->current->startLine = yyextra->yyLineNr ; + yyextra->current->startColumn = yyextra->yyColNr; yyextra->current->args.resize(0); - yyextra->current->section = Entry::TYPEDEF_SEC ; + yyextra->current->section = Entry::TYPEDEF_SEC ; yyextra->isTypedef = TRUE; - BEGIN( SliceDictionary ); - } - else - REJECT; - } -<FindMembers>{BN}{1,80} { - lineCount(yyscanner); - } -<FindMembers>"@"({ID}".")*{ID}{BN}*"(" { - if (yyextra->insideJava) // Java annotation - { - lineCount(yyscanner); - yyextra->lastSkipRoundContext = YY_START; - yyextra->roundCount=0; - BEGIN( SkipRound ); - } - else if (qstrncmp(yytext,"@property",9)==0) // ObjC 2.0 property - { - yyextra->current->mtype = yyextra->mtype = Property; - yyextra->current->spec|=Entry::Readable | Entry::Writable | Entry::Assign; - yyextra->current->protection = Public ; - unput('('); - BEGIN( ObjCPropAttr ); - } - else - { - REJECT; - } - } -<ObjCPropAttr>"getter="{ID} { + BEGIN( SliceDictionary ); + } + else + REJECT; + } +<FindMembers>{BN}{1,80} { + lineCount(yyscanner); + } +<FindMembers>"@"({ID}".")*{ID}{BN}*"(" { + if (yyextra->insideJava) // Java annotation + { + lineCount(yyscanner); + yyextra->lastSkipRoundContext = YY_START; + yyextra->roundCount=0; + BEGIN( SkipRound ); + } + else if (qstrncmp(yytext,"@property",9)==0) // ObjC 2.0 property + { + yyextra->current->mtype = yyextra->mtype = Property; + yyextra->current->spec|=Entry::Readable | Entry::Writable | Entry::Assign; + yyextra->current->protection = Public ; + unput('('); + BEGIN( ObjCPropAttr ); + } + else + { + REJECT; + } + } +<ObjCPropAttr>"getter="{ID} { yyextra->current->read = yytext+7; - } -<ObjCPropAttr>"setter="{ID} { + } +<ObjCPropAttr>"setter="{ID} { yyextra->current->write = yytext+7; - } -<ObjCPropAttr>"readonly" { - yyextra->current->spec&=~Entry::Writable; - } -<ObjCPropAttr>"readwrite" { // default - } -<ObjCPropAttr>"assign" { // default - } + } +<ObjCPropAttr>"readonly" { + yyextra->current->spec&=~Entry::Writable; + } +<ObjCPropAttr>"readwrite" { // default + } +<ObjCPropAttr>"assign" { // default + } <ObjCPropAttr>"unsafe_unretained" { - yyextra->current->spec&=~Entry::Assign; - yyextra->current->spec|=Entry::Unretained; - } -<ObjCPropAttr>"retain" { - yyextra->current->spec&=~Entry::Assign; - yyextra->current->spec|=Entry::Retain; - } -<ObjCPropAttr>"copy" { - yyextra->current->spec&=~Entry::Assign; - yyextra->current->spec|=Entry::Copy; - } + yyextra->current->spec&=~Entry::Assign; + yyextra->current->spec|=Entry::Unretained; + } +<ObjCPropAttr>"retain" { + yyextra->current->spec&=~Entry::Assign; + yyextra->current->spec|=Entry::Retain; + } +<ObjCPropAttr>"copy" { + yyextra->current->spec&=~Entry::Assign; + yyextra->current->spec|=Entry::Copy; + } <ObjCPropAttr>"weak" { - yyextra->current->spec&=~Entry::Assign; - yyextra->current->spec|=Entry::Weak; + yyextra->current->spec&=~Entry::Assign; + yyextra->current->spec|=Entry::Weak; } <ObjCPropAttr>"strong" { - yyextra->current->spec&=~Entry::Assign; - yyextra->current->spec|=Entry::Strong; - } -<ObjCPropAttr>"nonatomic" { - yyextra->current->spec|=Entry::NonAtomic; - } -<ObjCPropAttr>")" { - BEGIN(FindMembers); - } -<FindMembers>"@"{ID} { - if (yyextra->insideJava) // Java annotation - { - // skip annotation - } - else if (qstrcmp(yytext,"@property")==0) // ObjC 2.0 property - { - yyextra->current->mtype = yyextra->mtype = Property; - yyextra->current->spec|=Entry::Writable | Entry::Readable; - yyextra->current->protection = Public ; - } - else if (qstrcmp(yytext,"@synthesize")==0) - { - BEGIN( ObjCSkipStatement ); - } - else if (qstrcmp(yytext,"@dynamic")==0) - { - BEGIN( ObjCSkipStatement ); - } - else - { - REJECT; - } - } -<ObjCSkipStatement>";" { - BEGIN(FindMembers); - } -<PackageName>{ID}(("."|"\\"){ID})* { - yyextra->isTypedef=FALSE; - //printf("Found namespace %s lang=%d\n",yytext,yyextra->current->lang); - yyextra->current->name = yytext; - yyextra->current->name = substitute(yyextra->current->name,".","::"); - yyextra->current->name = substitute(yyextra->current->name,"\\","::"); - yyextra->current->section = Entry::NAMESPACE_SEC; - yyextra->current->type = "namespace" ; - yyextra->current->fileName = yyextra->yyFileName; - yyextra->current->startLine = yyextra->yyLineNr; - yyextra->current->startColumn = yyextra->yyColNr; - yyextra->current->bodyLine = yyextra->yyLineNr; - yyextra->current->bodyColumn = yyextra->yyColNr; - lineCount(yyscanner); - } -<PackageName>";" { + yyextra->current->spec&=~Entry::Assign; + yyextra->current->spec|=Entry::Strong; + } +<ObjCPropAttr>"nonatomic" { + yyextra->current->spec|=Entry::NonAtomic; + } +<ObjCPropAttr>")" { + BEGIN(FindMembers); + } +<FindMembers>"@"{ID} { + if (yyextra->insideJava) // Java annotation + { + // skip annotation + } + else if (qstrcmp(yytext,"@property")==0) // ObjC 2.0 property + { + yyextra->current->mtype = yyextra->mtype = Property; + yyextra->current->spec|=Entry::Writable | Entry::Readable; + yyextra->current->protection = Public ; + } + else if (qstrcmp(yytext,"@synthesize")==0) + { + BEGIN( ObjCSkipStatement ); + } + else if (qstrcmp(yytext,"@dynamic")==0) + { + BEGIN( ObjCSkipStatement ); + } + else + { + REJECT; + } + } +<ObjCSkipStatement>";" { + BEGIN(FindMembers); + } +<PackageName>{ID}(("."|"\\"){ID})* { + yyextra->isTypedef=FALSE; + //printf("Found namespace %s lang=%d\n",yytext,yyextra->current->lang); + yyextra->current->name = yytext; + yyextra->current->name = substitute(yyextra->current->name,".","::"); + yyextra->current->name = substitute(yyextra->current->name,"\\","::"); + yyextra->current->section = Entry::NAMESPACE_SEC; + yyextra->current->type = "namespace" ; + yyextra->current->fileName = yyextra->yyFileName; + yyextra->current->startLine = yyextra->yyLineNr; + yyextra->current->startColumn = yyextra->yyColNr; + yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->current->bodyColumn = yyextra->yyColNr; + lineCount(yyscanner); + } +<PackageName>";" { std::shared_ptr<Entry> tmp = yyextra->current; - yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current); + yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current); yyextra->current_root = tmp; - initEntry(yyscanner); - BEGIN(FindMembers); - } -<PackageName>"{" { - yyextra->curlyCount=0; - BEGIN( ReadNSBody ); - } -<FindMembers>{B}*"initonly"{BN}+ { - yyextra->current->type += " initonly "; - if (yyextra->insideCli) yyextra->current->spec |= Entry::Initonly; - lineCount(yyscanner); - } -<FindMembers>{B}*"static"{BN}+ { yyextra->current->type += " static "; - yyextra->current->stat = TRUE; - lineCount(yyscanner); - } -<FindMembers>{B}*"extern"{BN}+ { - yyextra->current->stat = FALSE; - yyextra->current->explicitExternal = TRUE; - lineCount(yyscanner); - } -<FindMembers>{B}*"const"{BN}+ { if (yyextra->insideCS) - { - yyextra->current->type += " const "; - if (yyextra->insideCS) yyextra->current->stat = TRUE; - lineCount(yyscanner); - } - else - { - REJECT; - } - } -<FindMembers>{B}*"virtual"{BN}+ { yyextra->current->type += " virtual "; - yyextra->current->virt = Virtual; - lineCount(yyscanner); - } -<FindMembers>{B}*"constexpr"{BN}+ { + initEntry(yyscanner); + BEGIN(FindMembers); + } +<PackageName>"{" { + yyextra->curlyCount=0; + BEGIN( ReadNSBody ); + } +<FindMembers>{B}*"initonly"{BN}+ { + yyextra->current->type += " initonly "; + if (yyextra->insideCli) yyextra->current->spec |= Entry::Initonly; + lineCount(yyscanner); + } +<FindMembers>{B}*"static"{BN}+ { yyextra->current->type += " static "; + yyextra->current->stat = TRUE; + lineCount(yyscanner); + } +<FindMembers>{B}*"extern"{BN}+ { + yyextra->current->stat = FALSE; + yyextra->current->explicitExternal = TRUE; + lineCount(yyscanner); + } +<FindMembers>{B}*"const"{BN}+ { if (yyextra->insideCS) + { + yyextra->current->type += " const "; + if (yyextra->insideCS) yyextra->current->stat = TRUE; + lineCount(yyscanner); + } + else + { + REJECT; + } + } +<FindMembers>{B}*"virtual"{BN}+ { yyextra->current->type += " virtual "; + yyextra->current->virt = Virtual; + lineCount(yyscanner); + } +<FindMembers>{B}*"constexpr"{BN}+ { if (yyextra->insideCpp) { yyextra->current->type += " constexpr "; @@ -1068,300 +1068,300 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) { REJECT; } - } -<FindMembers>{B}*"published"{BN}+ { // UNO IDL published keyword - if (yyextra->insideIDL) - { - lineCount(yyscanner); - yyextra->current->spec |= Entry::Published; - } - else - { - REJECT; - } - } -<FindMembers>{B}*"abstract"{BN}+ { - if (!yyextra->insidePHP) - { - yyextra->current->type += " abstract "; - if (!yyextra->insideJava) - { + } +<FindMembers>{B}*"published"{BN}+ { // UNO IDL published keyword + if (yyextra->insideIDL) + { + lineCount(yyscanner); + yyextra->current->spec |= Entry::Published; + } + else + { + REJECT; + } + } +<FindMembers>{B}*"abstract"{BN}+ { + if (!yyextra->insidePHP) + { + yyextra->current->type += " abstract "; + if (!yyextra->insideJava) + { yyextra->current->virt = Pure; - } - else - { + } + else + { yyextra->current->spec|=Entry::Abstract; - } - } - else - { - yyextra->current->spec|=Entry::Abstract; - } - lineCount(yyscanner); - } -<FindMembers>{B}*"inline"{BN}+ { yyextra->current->spec|=Entry::Inline; - lineCount(yyscanner); + } + } + else + { + yyextra->current->spec|=Entry::Abstract; + } + lineCount(yyscanner); } -<FindMembers>{B}*"mutable"{BN}+ { yyextra->current->spec|=Entry::Mutable; - lineCount(yyscanner); +<FindMembers>{B}*"inline"{BN}+ { yyextra->current->spec|=Entry::Inline; + lineCount(yyscanner); } -<FindMembers>{B}*"explicit"{BN}+ { yyextra->current->spec|=Entry::Explicit; - lineCount(yyscanner); +<FindMembers>{B}*"mutable"{BN}+ { yyextra->current->spec|=Entry::Mutable; + lineCount(yyscanner); } -<FindMembers>{B}*"local"{BN}+ { yyextra->current->spec|=Entry::Local; - lineCount(yyscanner); +<FindMembers>{B}*"explicit"{BN}+ { yyextra->current->spec|=Entry::Explicit; + lineCount(yyscanner); + } +<FindMembers>{B}*"local"{BN}+ { yyextra->current->spec|=Entry::Local; + lineCount(yyscanner); } -<FindMembers>{B}*"@required"{BN}+ { // Objective C 2.0 protocol required section +<FindMembers>{B}*"@required"{BN}+ { // Objective C 2.0 protocol required section yyextra->current->spec=(yyextra->current->spec & ~Entry::Optional) | Entry::Required; - lineCount(yyscanner); + lineCount(yyscanner); } -<FindMembers>{B}*"@optional"{BN}+ { // Objective C 2.0 protocol optional section +<FindMembers>{B}*"@optional"{BN}+ { // Objective C 2.0 protocol optional section yyextra->current->spec=(yyextra->current->spec & ~Entry::Required) | Entry::Optional; - lineCount(yyscanner); + lineCount(yyscanner); } /* -<FindMembers>{B}*"import"{BN}+ { // IDL import keyword - BEGIN( NextSemi ); - } +<FindMembers>{B}*"import"{BN}+ { // IDL import keyword + BEGIN( NextSemi ); + } */ -<FindMembers>{B}*"typename"{BN}+ { lineCount(yyscanner); } -<FindMembers>{B}*"namespace"{BN}*/[^a-z_A-Z0-9] { - yyextra->isTypedef=FALSE; - yyextra->current->section = Entry::NAMESPACE_SEC; - yyextra->current->type = "namespace" ; - yyextra->current->fileName = yyextra->yyFileName; - yyextra->current->startLine = yyextra->yyLineNr; - yyextra->current->startColumn = yyextra->yyColNr; - yyextra->current->bodyLine = yyextra->yyLineNr; - yyextra->current->bodyColumn = yyextra->yyColNr; - lineCount(yyscanner); - if (yyextra->insidePHP) - { - BEGIN( PackageName ); - } - else - { - BEGIN( CompoundName ); - } - } -<FindMembers>{B}*"module"{BN}+ { - lineCount(yyscanner); +<FindMembers>{B}*"typename"{BN}+ { lineCount(yyscanner); } +<FindMembers>{B}*"namespace"{BN}*/[^a-z_A-Z0-9] { + yyextra->isTypedef=FALSE; + yyextra->current->section = Entry::NAMESPACE_SEC; + yyextra->current->type = "namespace" ; + yyextra->current->fileName = yyextra->yyFileName; + yyextra->current->startLine = yyextra->yyLineNr; + yyextra->current->startColumn = yyextra->yyColNr; + yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->current->bodyColumn = yyextra->yyColNr; + lineCount(yyscanner); + if (yyextra->insidePHP) + { + BEGIN( PackageName ); + } + else + { + BEGIN( CompoundName ); + } + } +<FindMembers>{B}*"module"{BN}+ { + lineCount(yyscanner); if (yyextra->insideIDL || yyextra->insideSlice) - { - yyextra->isTypedef=FALSE; - yyextra->current->section = Entry::NAMESPACE_SEC; - yyextra->current->type = "module" ; - yyextra->current->fileName = yyextra->yyFileName; - yyextra->current->startLine = yyextra->yyLineNr; - yyextra->current->startColumn = yyextra->yyColNr; - yyextra->current->bodyLine = yyextra->yyLineNr; - yyextra->current->bodyColumn = yyextra->yyColNr; - BEGIN( CompoundName ); - } - else if (yyextra->insideD) - { - lineCount(yyscanner); - BEGIN(PackageName); - } - else - { - addType(yyscanner); - yyextra->current->name = QCString(yytext).stripWhiteSpace(); - } - } -<FindMembers>{B}*"library"{BN}+ { - lineCount(yyscanner); + { + yyextra->isTypedef=FALSE; + yyextra->current->section = Entry::NAMESPACE_SEC; + yyextra->current->type = "module" ; + yyextra->current->fileName = yyextra->yyFileName; + yyextra->current->startLine = yyextra->yyLineNr; + yyextra->current->startColumn = yyextra->yyColNr; + yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->current->bodyColumn = yyextra->yyColNr; + BEGIN( CompoundName ); + } + else if (yyextra->insideD) + { + lineCount(yyscanner); + BEGIN(PackageName); + } + else + { + addType(yyscanner); + yyextra->current->name = QCString(yytext).stripWhiteSpace(); + } + } +<FindMembers>{B}*"library"{BN}+ { + lineCount(yyscanner); if (yyextra->insideIDL) - { - yyextra->isTypedef=FALSE; - yyextra->current->section = Entry::NAMESPACE_SEC; - yyextra->current->type = "library" ; - yyextra->current->fileName = yyextra->yyFileName; - yyextra->current->startLine = yyextra->yyLineNr; - yyextra->current->startColumn = yyextra->yyColNr; - yyextra->current->bodyLine = yyextra->yyLineNr; - yyextra->current->bodyColumn = yyextra->yyColNr; - BEGIN( CompoundName ); - } - else - { - addType(yyscanner); - yyextra->current->name = QCString(yytext).stripWhiteSpace(); - } - } -<FindMembers>{B}*"constants"{BN}+ { // UNO IDL constant group - lineCount(yyscanner); - if (yyextra->insideIDL) - { - yyextra->isTypedef=FALSE; - yyextra->current->section = Entry::NAMESPACE_SEC; - yyextra->current->type = "constants"; - yyextra->current->fileName = yyextra->yyFileName; - yyextra->current->startLine = yyextra->yyLineNr; - yyextra->current->startColumn = yyextra->yyColNr; - yyextra->current->bodyLine = yyextra->yyLineNr; - yyextra->current->bodyColumn = yyextra->yyColNr; - BEGIN( CompoundName ); - } - else - { - addType(yyscanner); - yyextra->current->name = QCString(yytext).stripWhiteSpace(); - } - } -<FindMembers>{BN}*("service"){BN}+ { // UNO IDL service - lineCount(yyscanner); - if (yyextra->insideIDL) - { - yyextra->isTypedef=FALSE; - yyextra->current->section = Entry::CLASS_SEC; - yyextra->current->spec = Entry::Service | - // preserve UNO IDL [optional] or published - (yyextra->current->spec & (Entry::Optional|Entry::Published)); - addType(yyscanner); - yyextra->current->type += " service " ; - yyextra->current->fileName = yyextra->yyFileName; - yyextra->current->startLine = yyextra->yyLineNr; - yyextra->current->bodyLine = yyextra->yyLineNr; - yyextra->current->bodyColumn = yyextra->yyColNr; - BEGIN( CompoundName ); - } - else // TODO is addType right? just copy/pasted - { - addType(yyscanner); - yyextra->current->name = QCString(yytext).stripWhiteSpace(); - } - } -<FindMembers>{BN}*("singleton"){BN}+ { // UNO IDL singleton - lineCount(yyscanner); - if (yyextra->insideIDL) - { - yyextra->isTypedef=FALSE; - yyextra->current->section = Entry::CLASS_SEC; - yyextra->current->spec = Entry::Singleton | - (yyextra->current->spec & Entry::Published); // preserve - addType(yyscanner); - yyextra->current->type += " singleton " ; - yyextra->current->fileName = yyextra->yyFileName; - yyextra->current->startLine = yyextra->yyLineNr; - yyextra->current->bodyLine = yyextra->yyLineNr; - yyextra->current->bodyColumn = yyextra->yyColNr; - BEGIN( CompoundName ); - } - else // TODO is addType right? just copy/pasted - { - addType(yyscanner); - yyextra->current->name = QCString(yytext).stripWhiteSpace(); - } - } -<FindMembers>{BN}*((("disp")?"interface")|"valuetype"){BN}+ { // M$/Corba/UNO IDL/Java/Slice interface - lineCount(yyscanner); + { + yyextra->isTypedef=FALSE; + yyextra->current->section = Entry::NAMESPACE_SEC; + yyextra->current->type = "library" ; + yyextra->current->fileName = yyextra->yyFileName; + yyextra->current->startLine = yyextra->yyLineNr; + yyextra->current->startColumn = yyextra->yyColNr; + yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->current->bodyColumn = yyextra->yyColNr; + BEGIN( CompoundName ); + } + else + { + addType(yyscanner); + yyextra->current->name = QCString(yytext).stripWhiteSpace(); + } + } +<FindMembers>{B}*"constants"{BN}+ { // UNO IDL constant group + lineCount(yyscanner); + if (yyextra->insideIDL) + { + yyextra->isTypedef=FALSE; + yyextra->current->section = Entry::NAMESPACE_SEC; + yyextra->current->type = "constants"; + yyextra->current->fileName = yyextra->yyFileName; + yyextra->current->startLine = yyextra->yyLineNr; + yyextra->current->startColumn = yyextra->yyColNr; + yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->current->bodyColumn = yyextra->yyColNr; + BEGIN( CompoundName ); + } + else + { + addType(yyscanner); + yyextra->current->name = QCString(yytext).stripWhiteSpace(); + } + } +<FindMembers>{BN}*("service"){BN}+ { // UNO IDL service + lineCount(yyscanner); + if (yyextra->insideIDL) + { + yyextra->isTypedef=FALSE; + yyextra->current->section = Entry::CLASS_SEC; + yyextra->current->spec = Entry::Service | + // preserve UNO IDL [optional] or published + (yyextra->current->spec & (Entry::Optional|Entry::Published)); + addType(yyscanner); + yyextra->current->type += " service " ; + yyextra->current->fileName = yyextra->yyFileName; + yyextra->current->startLine = yyextra->yyLineNr; + yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->current->bodyColumn = yyextra->yyColNr; + BEGIN( CompoundName ); + } + else // TODO is addType right? just copy/pasted + { + addType(yyscanner); + yyextra->current->name = QCString(yytext).stripWhiteSpace(); + } + } +<FindMembers>{BN}*("singleton"){BN}+ { // UNO IDL singleton + lineCount(yyscanner); + if (yyextra->insideIDL) + { + yyextra->isTypedef=FALSE; + yyextra->current->section = Entry::CLASS_SEC; + yyextra->current->spec = Entry::Singleton | + (yyextra->current->spec & Entry::Published); // preserve + addType(yyscanner); + yyextra->current->type += " singleton " ; + yyextra->current->fileName = yyextra->yyFileName; + yyextra->current->startLine = yyextra->yyLineNr; + yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->current->bodyColumn = yyextra->yyColNr; + BEGIN( CompoundName ); + } + else // TODO is addType right? just copy/pasted + { + addType(yyscanner); + yyextra->current->name = QCString(yytext).stripWhiteSpace(); + } + } +<FindMembers>{BN}*((("disp")?"interface")|"valuetype"){BN}+ { // M$/Corba/UNO IDL/Java/Slice interface + lineCount(yyscanner); if (yyextra->insideIDL || yyextra->insideJava || yyextra->insideCS || yyextra->insideD || yyextra->insidePHP || yyextra->insideSlice) - { - yyextra->isTypedef=FALSE; - yyextra->current->section = Entry::CLASS_SEC; - yyextra->current->spec = Entry::Interface | + { + yyextra->isTypedef=FALSE; + yyextra->current->section = Entry::CLASS_SEC; + yyextra->current->spec = Entry::Interface | // preserve UNO IDL [optional], published, Slice local (yyextra->current->spec & (Entry::Optional|Entry::Published|Entry::Local)); - addType(yyscanner); - yyextra->current->type += " interface" ; - yyextra->current->fileName = yyextra->yyFileName; - yyextra->current->startLine = yyextra->yyLineNr; - yyextra->current->startColumn = yyextra->yyColNr; - yyextra->current->bodyLine = yyextra->yyLineNr; - yyextra->current->bodyColumn = yyextra->yyColNr; - BEGIN( CompoundName ); - } - else - { - addType(yyscanner); - yyextra->current->name = QCString(yytext).stripWhiteSpace(); - } - } -<FindMembers>{B}*"@implementation"{BN}+ { // Objective-C class implementation - lineCount(yyscanner); - yyextra->isTypedef=FALSE; - yyextra->current->section = Entry::OBJCIMPL_SEC; - yyextra->language = yyextra->current->lang = SrcLangExt_ObjC; - yyextra->insideObjC = TRUE; - yyextra->current->protection = yyextra->protection = Public ; - addType(yyscanner); - yyextra->current->type += " implementation" ; - yyextra->current->fileName = yyextra->yyFileName; - yyextra->current->startLine = yyextra->yyLineNr; - yyextra->current->bodyLine = yyextra->yyLineNr; - yyextra->current->bodyColumn = yyextra->yyColNr; - BEGIN( CompoundName ); - } -<FindMembers>{B}*"@interface"{BN}+ { // Objective-C class interface, or Java attribute - lineCount(yyscanner); - yyextra->isTypedef=FALSE; - yyextra->current->section = Entry::CLASS_SEC; + addType(yyscanner); + yyextra->current->type += " interface" ; + yyextra->current->fileName = yyextra->yyFileName; + yyextra->current->startLine = yyextra->yyLineNr; + yyextra->current->startColumn = yyextra->yyColNr; + yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->current->bodyColumn = yyextra->yyColNr; + BEGIN( CompoundName ); + } + else + { + addType(yyscanner); + yyextra->current->name = QCString(yytext).stripWhiteSpace(); + } + } +<FindMembers>{B}*"@implementation"{BN}+ { // Objective-C class implementation + lineCount(yyscanner); + yyextra->isTypedef=FALSE; + yyextra->current->section = Entry::OBJCIMPL_SEC; + yyextra->language = yyextra->current->lang = SrcLangExt_ObjC; + yyextra->insideObjC = TRUE; + yyextra->current->protection = yyextra->protection = Public ; + addType(yyscanner); + yyextra->current->type += " implementation" ; + yyextra->current->fileName = yyextra->yyFileName; + yyextra->current->startLine = yyextra->yyLineNr; + yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->current->bodyColumn = yyextra->yyColNr; + BEGIN( CompoundName ); + } +<FindMembers>{B}*"@interface"{BN}+ { // Objective-C class interface, or Java attribute + lineCount(yyscanner); + yyextra->isTypedef=FALSE; + yyextra->current->section = Entry::CLASS_SEC; yyextra->current->spec = Entry::Interface; - if (!yyextra->insideJava) - { - yyextra->language = yyextra->current->lang = SrcLangExt_ObjC; - yyextra->insideObjC = TRUE; - } - yyextra->current->protection = yyextra->protection = Public ; - addType(yyscanner); - yyextra->current->type += " interface" ; - yyextra->current->fileName = yyextra->yyFileName; - yyextra->current->startLine = yyextra->yyLineNr; - yyextra->current->startColumn = yyextra->yyColNr; - yyextra->current->bodyLine = yyextra->yyLineNr; - yyextra->current->bodyColumn = yyextra->yyColNr; - BEGIN( CompoundName ); - } -<FindMembers>{B}*"@protocol"{BN}+ { // Objective-C protocol definition - lineCount(yyscanner); - yyextra->isTypedef=FALSE; - yyextra->current->section = Entry::CLASS_SEC; + if (!yyextra->insideJava) + { + yyextra->language = yyextra->current->lang = SrcLangExt_ObjC; + yyextra->insideObjC = TRUE; + } + yyextra->current->protection = yyextra->protection = Public ; + addType(yyscanner); + yyextra->current->type += " interface" ; + yyextra->current->fileName = yyextra->yyFileName; + yyextra->current->startLine = yyextra->yyLineNr; + yyextra->current->startColumn = yyextra->yyColNr; + yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->current->bodyColumn = yyextra->yyColNr; + BEGIN( CompoundName ); + } +<FindMembers>{B}*"@protocol"{BN}+ { // Objective-C protocol definition + lineCount(yyscanner); + yyextra->isTypedef=FALSE; + yyextra->current->section = Entry::CLASS_SEC; yyextra->current->spec = Entry::Protocol; - yyextra->language = yyextra->current->lang = SrcLangExt_ObjC; - yyextra->insideObjC = TRUE; - yyextra->current->protection = yyextra->protection = Public ; - addType(yyscanner); - yyextra->current->type += " protocol" ; - yyextra->current->fileName = yyextra->yyFileName; - yyextra->current->startLine = yyextra->yyLineNr; - yyextra->current->startColumn = yyextra->yyColNr; - yyextra->current->bodyLine = yyextra->yyLineNr; - yyextra->current->bodyColumn = yyextra->yyColNr; - BEGIN( CompoundName ); - } -<FindMembers>{B}*"exception"{BN}+ { // Corba IDL/Slice exception - yyextra->isTypedef=FALSE; - yyextra->current->section = Entry::CLASS_SEC; + yyextra->language = yyextra->current->lang = SrcLangExt_ObjC; + yyextra->insideObjC = TRUE; + yyextra->current->protection = yyextra->protection = Public ; + addType(yyscanner); + yyextra->current->type += " protocol" ; + yyextra->current->fileName = yyextra->yyFileName; + yyextra->current->startLine = yyextra->yyLineNr; + yyextra->current->startColumn = yyextra->yyColNr; + yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->current->bodyColumn = yyextra->yyColNr; + BEGIN( CompoundName ); + } +<FindMembers>{B}*"exception"{BN}+ { // Corba IDL/Slice exception + yyextra->isTypedef=FALSE; + yyextra->current->section = Entry::CLASS_SEC; // preserve UNO IDL, Slice local - yyextra->current->spec = Entry::Exception | - (yyextra->current->spec & Entry::Published) | - (yyextra->current->spec & Entry::Local); - addType(yyscanner); - yyextra->current->type += " exception" ; - yyextra->current->fileName = yyextra->yyFileName; - yyextra->current->startLine = yyextra->yyLineNr; - yyextra->current->startColumn = yyextra->yyColNr; - yyextra->current->bodyLine = yyextra->yyLineNr; - yyextra->current->bodyColumn = yyextra->yyColNr; - lineCount(yyscanner); - BEGIN( CompoundName ); - } + yyextra->current->spec = Entry::Exception | + (yyextra->current->spec & Entry::Published) | + (yyextra->current->spec & Entry::Local); + addType(yyscanner); + yyextra->current->type += " exception" ; + yyextra->current->fileName = yyextra->yyFileName; + yyextra->current->startLine = yyextra->yyLineNr; + yyextra->current->startColumn = yyextra->yyColNr; + yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->current->bodyColumn = yyextra->yyColNr; + lineCount(yyscanner); + BEGIN( CompoundName ); + } <FindMembers>"@class" | // for Objective C class declarations <FindMembers>{B}*{TYPEDEFPREFIX}"class{" | -<FindMembers>{B}*{TYPEDEFPREFIX}"class"{BN}+ { +<FindMembers>{B}*{TYPEDEFPREFIX}"class"{BN}+ { QCString decl = yytext; - yyextra->isTypedef=decl.find("typedef")!=-1; + yyextra->isTypedef=decl.find("typedef")!=-1; bool isConst=decl.find("const")!=-1; bool isVolatile=decl.find("volatile")!=-1; - yyextra->current->section = Entry::CLASS_SEC; - addType(yyscanner); + yyextra->current->section = Entry::CLASS_SEC; + addType(yyscanner); uint64 spec = yyextra->current->spec; - if (yyextra->insidePHP && yyextra->current->spec&Entry::Abstract) - { - // convert Abstract to AbstractClass - yyextra->current->spec=(yyextra->current->spec&~Entry::Abstract)|Entry::AbstractClass; - } + if (yyextra->insidePHP && yyextra->current->spec&Entry::Abstract) + { + // convert Abstract to AbstractClass + yyextra->current->spec=(yyextra->current->spec&~Entry::Abstract)|Entry::AbstractClass; + } if (yyextra->insideSlice && spec&Entry::Local) { yyextra->current->spec|=Entry::Local; @@ -1374,107 +1374,107 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) { yyextra->current->type += " volatile"; } - yyextra->current->type += " class" ; - yyextra->current->fileName = yyextra->yyFileName; - yyextra->current->startLine = yyextra->yyLineNr; - yyextra->current->startColumn = yyextra->yyColNr; - yyextra->current->bodyLine = yyextra->yyLineNr; - yyextra->current->bodyColumn = yyextra->yyColNr; - if (yytext[0]=='@') - { - yyextra->language = yyextra->current->lang = SrcLangExt_ObjC; - yyextra->insideObjC = TRUE; - } - lineCount(yyscanner) ; - if (yytext[yyleng-1]=='{') unput('{'); - BEGIN( CompoundName ) ; - } + yyextra->current->type += " class" ; + yyextra->current->fileName = yyextra->yyFileName; + yyextra->current->startLine = yyextra->yyLineNr; + yyextra->current->startColumn = yyextra->yyColNr; + yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->current->bodyColumn = yyextra->yyColNr; + if (yytext[0]=='@') + { + yyextra->language = yyextra->current->lang = SrcLangExt_ObjC; + yyextra->insideObjC = TRUE; + } + lineCount(yyscanner) ; + if (yytext[yyleng-1]=='{') unput('{'); + BEGIN( CompoundName ) ; + } <FindMembers>{B}*"value class{" | // C++/CLI extension <FindMembers>{B}*"value class"{BN}+ { - yyextra->isTypedef=FALSE; - yyextra->current->section = Entry::CLASS_SEC; + yyextra->isTypedef=FALSE; + yyextra->current->section = Entry::CLASS_SEC; yyextra->current->spec = Entry::Value; - addType(yyscanner); - yyextra->current->type += " value class" ; - yyextra->current->fileName = yyextra->yyFileName; - yyextra->current->startLine = yyextra->yyLineNr; - yyextra->current->startColumn = yyextra->yyColNr; - yyextra->current->bodyLine = yyextra->yyLineNr; - yyextra->current->bodyColumn = yyextra->yyColNr; - lineCount(yyscanner) ; - if (yytext[yyleng-1]=='{') unput('{'); - BEGIN( CompoundName ) ; - } + addType(yyscanner); + yyextra->current->type += " value class" ; + yyextra->current->fileName = yyextra->yyFileName; + yyextra->current->startLine = yyextra->yyLineNr; + yyextra->current->startColumn = yyextra->yyColNr; + yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->current->bodyColumn = yyextra->yyColNr; + lineCount(yyscanner) ; + if (yytext[yyleng-1]=='{') unput('{'); + BEGIN( CompoundName ) ; + } <FindMembers>{B}*"ref class{" | // C++/CLI extension <FindMembers>{B}*"ref class"{BN}+ { - yyextra->isTypedef=FALSE; - yyextra->current->section = Entry::CLASS_SEC; + yyextra->isTypedef=FALSE; + yyextra->current->section = Entry::CLASS_SEC; yyextra->current->spec = Entry::Ref; - addType(yyscanner); - yyextra->current->type += " ref class" ; - yyextra->current->fileName = yyextra->yyFileName; - yyextra->current->startLine = yyextra->yyLineNr; - yyextra->current->startColumn = yyextra->yyColNr; - yyextra->current->bodyLine = yyextra->yyLineNr; - yyextra->current->bodyColumn = yyextra->yyColNr; - lineCount(yyscanner) ; - if (yytext[yyleng-1]=='{') unput('{'); - BEGIN( CompoundName ) ; - } + addType(yyscanner); + yyextra->current->type += " ref class" ; + yyextra->current->fileName = yyextra->yyFileName; + yyextra->current->startLine = yyextra->yyLineNr; + yyextra->current->startColumn = yyextra->yyColNr; + yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->current->bodyColumn = yyextra->yyColNr; + lineCount(yyscanner) ; + if (yytext[yyleng-1]=='{') unput('{'); + BEGIN( CompoundName ) ; + } <FindMembers>{B}*"interface class{" | // C++/CLI extension <FindMembers>{B}*"interface class"{BN}+ { - yyextra->isTypedef=FALSE; - yyextra->current->section = Entry::CLASS_SEC; + yyextra->isTypedef=FALSE; + yyextra->current->section = Entry::CLASS_SEC; yyextra->current->spec = Entry::Interface; - addType(yyscanner); - yyextra->current->type += " interface class" ; - yyextra->current->fileName = yyextra->yyFileName; - yyextra->current->startLine = yyextra->yyLineNr; - yyextra->current->startColumn = yyextra->yyColNr; - yyextra->current->bodyLine = yyextra->yyLineNr; - yyextra->current->bodyColumn = yyextra->yyColNr; - lineCount(yyscanner) ; - if (yytext[yyleng-1]=='{') unput('{'); - BEGIN( CompoundName ) ; - } -<FindMembers>{B}*"coclass"{BN}+ { - if (yyextra->insideIDL) - { - yyextra->isTypedef=FALSE; - yyextra->current->section = Entry::CLASS_SEC; - addType(yyscanner); - yyextra->current->type += " coclass" ; - yyextra->current->fileName = yyextra->yyFileName; - yyextra->current->startLine = yyextra->yyLineNr; - yyextra->current->startColumn = yyextra->yyColNr; - yyextra->current->bodyLine = yyextra->yyLineNr; - yyextra->current->bodyColumn = yyextra->yyColNr; - lineCount(yyscanner) ; - BEGIN( CompoundName ) ; - } - else - { - addType(yyscanner); - yyextra->current->name = yytext; - yyextra->current->name = yyextra->current->name.stripWhiteSpace(); - lineCount(yyscanner); - } - } -<FindMembers>{B}*{TYPEDEFPREFIX}"struct{" | -<FindMembers>{B}*{TYPEDEFPREFIX}"struct"/{BN}+ { + addType(yyscanner); + yyextra->current->type += " interface class" ; + yyextra->current->fileName = yyextra->yyFileName; + yyextra->current->startLine = yyextra->yyLineNr; + yyextra->current->startColumn = yyextra->yyColNr; + yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->current->bodyColumn = yyextra->yyColNr; + lineCount(yyscanner) ; + if (yytext[yyleng-1]=='{') unput('{'); + BEGIN( CompoundName ) ; + } +<FindMembers>{B}*"coclass"{BN}+ { + if (yyextra->insideIDL) + { + yyextra->isTypedef=FALSE; + yyextra->current->section = Entry::CLASS_SEC; + addType(yyscanner); + yyextra->current->type += " coclass" ; + yyextra->current->fileName = yyextra->yyFileName; + yyextra->current->startLine = yyextra->yyLineNr; + yyextra->current->startColumn = yyextra->yyColNr; + yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->current->bodyColumn = yyextra->yyColNr; + lineCount(yyscanner) ; + BEGIN( CompoundName ) ; + } + else + { + addType(yyscanner); + yyextra->current->name = yytext; + yyextra->current->name = yyextra->current->name.stripWhiteSpace(); + lineCount(yyscanner); + } + } +<FindMembers>{B}*{TYPEDEFPREFIX}"struct{" | +<FindMembers>{B}*{TYPEDEFPREFIX}"struct"/{BN}+ { QCString decl = yytext; - yyextra->isTypedef=decl.find("typedef")!=-1; + yyextra->isTypedef=decl.find("typedef")!=-1; bool isConst=decl.find("const")!=-1; bool isVolatile=decl.find("volatile")!=-1; - yyextra->current->section = Entry::CLASS_SEC ; + yyextra->current->section = Entry::CLASS_SEC ; // preserve UNO IDL & Inline attributes, Slice local - yyextra->current->spec = Entry::Struct | - (yyextra->current->spec & Entry::Published) | + yyextra->current->spec = Entry::Struct | + (yyextra->current->spec & Entry::Published) | (yyextra->current->spec & Entry::Inline) | - (yyextra->current->spec & Entry::Local); - // bug 582676: can be a struct nested in an interface so keep yyextra->insideObjC state - //yyextra->current->objc = yyextra->insideObjC = FALSE; - addType(yyscanner); + (yyextra->current->spec & Entry::Local); + // bug 582676: can be a struct nested in an interface so keep yyextra->insideObjC state + //yyextra->current->objc = yyextra->insideObjC = FALSE; + addType(yyscanner); if (isConst) { yyextra->current->type += " const"; @@ -1483,75 +1483,75 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) { yyextra->current->type += " volatile"; } - yyextra->current->type += " struct" ; - yyextra->current->fileName = yyextra->yyFileName; - yyextra->current->startLine = yyextra->yyLineNr; - yyextra->current->startColumn = yyextra->yyColNr; - yyextra->current->bodyLine = yyextra->yyLineNr; - yyextra->current->bodyColumn = yyextra->yyColNr; - lineCount(yyscanner) ; - if (yytext[yyleng-1]=='{') unput('{'); - BEGIN( CompoundName ) ; - } + yyextra->current->type += " struct" ; + yyextra->current->fileName = yyextra->yyFileName; + yyextra->current->startLine = yyextra->yyLineNr; + yyextra->current->startColumn = yyextra->yyColNr; + yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->current->bodyColumn = yyextra->yyColNr; + lineCount(yyscanner) ; + if (yytext[yyleng-1]=='{') unput('{'); + BEGIN( CompoundName ) ; + } <FindMembers>{B}*"value struct{" | // C++/CLI extension <FindMembers>{B}*"value struct"{BN}+ { - yyextra->isTypedef=FALSE; - yyextra->current->section = Entry::CLASS_SEC; + yyextra->isTypedef=FALSE; + yyextra->current->section = Entry::CLASS_SEC; yyextra->current->spec = Entry::Struct | Entry::Value; - addType(yyscanner); - yyextra->current->type += " value struct" ; - yyextra->current->fileName = yyextra->yyFileName; - yyextra->current->startLine = yyextra->yyLineNr; - yyextra->current->startColumn = yyextra->yyColNr; - yyextra->current->bodyLine = yyextra->yyLineNr; - yyextra->current->bodyColumn = yyextra->yyColNr; - lineCount(yyscanner) ; - if (yytext[yyleng-1]=='{') unput('{'); - BEGIN( CompoundName ) ; - } + addType(yyscanner); + yyextra->current->type += " value struct" ; + yyextra->current->fileName = yyextra->yyFileName; + yyextra->current->startLine = yyextra->yyLineNr; + yyextra->current->startColumn = yyextra->yyColNr; + yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->current->bodyColumn = yyextra->yyColNr; + lineCount(yyscanner) ; + if (yytext[yyleng-1]=='{') unput('{'); + BEGIN( CompoundName ) ; + } <FindMembers>{B}*"ref struct{" | // C++/CLI extension <FindMembers>{B}*"ref struct"{BN}+ { - yyextra->isTypedef=FALSE; - yyextra->current->section = Entry::CLASS_SEC; + yyextra->isTypedef=FALSE; + yyextra->current->section = Entry::CLASS_SEC; yyextra->current->spec = Entry::Struct | Entry::Ref; - addType(yyscanner); - yyextra->current->type += " ref struct" ; - yyextra->current->fileName = yyextra->yyFileName; - yyextra->current->startLine = yyextra->yyLineNr; - yyextra->current->startColumn = yyextra->yyColNr; - yyextra->current->bodyLine = yyextra->yyLineNr; - yyextra->current->bodyColumn = yyextra->yyColNr; - lineCount(yyscanner) ; - if (yytext[yyleng-1]=='{') unput('{'); - BEGIN( CompoundName ) ; - } + addType(yyscanner); + yyextra->current->type += " ref struct" ; + yyextra->current->fileName = yyextra->yyFileName; + yyextra->current->startLine = yyextra->yyLineNr; + yyextra->current->startColumn = yyextra->yyColNr; + yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->current->bodyColumn = yyextra->yyColNr; + lineCount(yyscanner) ; + if (yytext[yyleng-1]=='{') unput('{'); + BEGIN( CompoundName ) ; + } <FindMembers>{B}*"interface struct{" | // C++/CLI extension <FindMembers>{B}*"interface struct"{BN}+ { - yyextra->isTypedef=FALSE; - yyextra->current->section = Entry::CLASS_SEC; + yyextra->isTypedef=FALSE; + yyextra->current->section = Entry::CLASS_SEC; yyextra->current->spec = Entry::Struct | Entry::Interface; - addType(yyscanner); - yyextra->current->type += " interface struct"; - yyextra->current->fileName = yyextra->yyFileName; - yyextra->current->startLine = yyextra->yyLineNr; - yyextra->current->startColumn = yyextra->yyColNr; - yyextra->current->bodyLine = yyextra->yyLineNr; - yyextra->current->bodyColumn = yyextra->yyColNr; - lineCount(yyscanner) ; - if (yytext[yyleng-1]=='{') unput('{'); - BEGIN( CompoundName ) ; - } + addType(yyscanner); + yyextra->current->type += " interface struct"; + yyextra->current->fileName = yyextra->yyFileName; + yyextra->current->startLine = yyextra->yyLineNr; + yyextra->current->startColumn = yyextra->yyColNr; + yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->current->bodyColumn = yyextra->yyColNr; + lineCount(yyscanner) ; + if (yytext[yyleng-1]=='{') unput('{'); + BEGIN( CompoundName ) ; + } <FindMembers>{B}*{TYPEDEFPREFIX}"union{" | -<FindMembers>{B}*{TYPEDEFPREFIX}"union"{BN}+ { +<FindMembers>{B}*{TYPEDEFPREFIX}"union"{BN}+ { QCString decl=yytext; - yyextra->isTypedef=decl.find("typedef")!=-1; + yyextra->isTypedef=decl.find("typedef")!=-1; bool isConst=decl.find("const")!=-1; bool isVolatile=decl.find("volatile")!=-1; - yyextra->current->section = Entry::CLASS_SEC; + yyextra->current->section = Entry::CLASS_SEC; yyextra->current->spec = Entry::Union; - // bug 582676: can be a struct nested in an interface so keep yyextra->insideObjC state - //yyextra->current->objc = yyextra->insideObjC = FALSE; - addType(yyscanner); + // bug 582676: can be a struct nested in an interface so keep yyextra->insideObjC state + //yyextra->current->objc = yyextra->insideObjC = FALSE; + addType(yyscanner); if (isConst) { yyextra->current->type += " const"; @@ -1560,239 +1560,239 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) { yyextra->current->type += " volatile"; } - yyextra->current->type += " union" ; - yyextra->current->fileName = yyextra->yyFileName; - yyextra->current->startLine = yyextra->yyLineNr; - yyextra->current->startColumn = yyextra->yyColNr; - yyextra->current->bodyLine = yyextra->yyLineNr; - yyextra->current->bodyColumn = yyextra->yyColNr; - lineCount(yyscanner) ; - if (yytext[yyleng-1]=='{') unput('{'); - BEGIN( CompoundName ) ; - } + yyextra->current->type += " union" ; + yyextra->current->fileName = yyextra->yyFileName; + yyextra->current->startLine = yyextra->yyLineNr; + yyextra->current->startColumn = yyextra->yyColNr; + yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->current->bodyColumn = yyextra->yyColNr; + lineCount(yyscanner) ; + if (yytext[yyleng-1]=='{') unput('{'); + BEGIN( CompoundName ) ; + } <FindMembers>{B}*{TYPEDEFPREFIX}{IDLATTR}?"enum"({BN}+("class"|"struct"))?"{" | <FindMembers>{B}*{TYPEDEFPREFIX}{IDLATTR}?"enum"({BN}+("class"|"struct"))?{BN}+ { // for IDL: typedef [something] enum QCString text=yytext; - yyextra->isTypedef = text.find("typedef")!=-1; + yyextra->isTypedef = text.find("typedef")!=-1; bool isStrongEnum = text.find("struct")!=-1 || text.find("class")!=-1 || yyextra->insideCS; - if (yyextra->insideJava) - { - yyextra->current->section = Entry::CLASS_SEC; - yyextra->current->spec = Entry::Enum; - } - else - { - yyextra->current->section = Entry::ENUM_SEC ; - } - addType(yyscanner); - yyextra->current->type += " enum"; + if (yyextra->insideJava) + { + yyextra->current->section = Entry::CLASS_SEC; + yyextra->current->spec = Entry::Enum; + } + else + { + yyextra->current->section = Entry::ENUM_SEC ; + } + addType(yyscanner); + yyextra->current->type += " enum"; if (isStrongEnum) { yyextra->current->spec |= Entry::Strong; } - yyextra->current->fileName = yyextra->yyFileName; - yyextra->current->startLine = yyextra->yyLineNr; - yyextra->current->startColumn = yyextra->yyColNr; - yyextra->current->bodyLine = yyextra->yyLineNr; - yyextra->current->bodyColumn = yyextra->yyColNr; - lineCount(yyscanner) ; - if (yytext[yyleng-1]=='{') unput('{'); - BEGIN( CompoundName ) ; - } + yyextra->current->fileName = yyextra->yyFileName; + yyextra->current->startLine = yyextra->yyLineNr; + yyextra->current->startColumn = yyextra->yyColNr; + yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->current->bodyColumn = yyextra->yyColNr; + lineCount(yyscanner) ; + if (yytext[yyleng-1]=='{') unput('{'); + BEGIN( CompoundName ) ; + } <Operator>"("{BN}*")"({BN}*"<"[^>]*">"){BN}*/"(" { // A::operator()<int>(int arg) - lineCount(yyscanner); - yyextra->current->name += "()"; - BEGIN( FindMembers ); - } -<Operator>"("{BN}*")"{BN}*/"(" { - lineCount(yyscanner); - yyextra->current->name += yytext ; - yyextra->current->name = yyextra->current->name.simplifyWhiteSpace(); - BEGIN( FindMembers ) ; - } -<Operator>";" { // can occur when importing members - unput(';'); - BEGIN( FindMembers ) ; - } -<Operator>[^(] { - lineCount(yyscanner); - yyextra->current->name += *yytext ; - } -<Operator>"<>" { /* skip guided templ specifiers */ } -<Operator>"(" { - yyextra->current->name = yyextra->current->name.simplifyWhiteSpace(); - unput(*yytext); - BEGIN( FindMembers ) ; - } -<FindMembers>("template"|"generic")({BN}*)"<"/[>]? { // generic is a C++/CLI extension - lineCount(yyscanner); - ArgumentList al; - //yyextra->current->spec |= (yytext[0]=='g') ? Entry::Generic : Entry::Template; - yyextra->current->tArgLists.push_back(al); - yyextra->currentArgumentList = &yyextra->current->tArgLists.back(); - yyextra->templateStr="<"; - yyextra->fullArgString = yyextra->templateStr; - yyextra->copyArgString = &yyextra->templateStr; - yyextra->currentArgumentContext = FindMembers; - BEGIN( ReadTempArgs ); - } + lineCount(yyscanner); + yyextra->current->name += "()"; + BEGIN( FindMembers ); + } +<Operator>"("{BN}*")"{BN}*/"(" { + lineCount(yyscanner); + yyextra->current->name += yytext ; + yyextra->current->name = yyextra->current->name.simplifyWhiteSpace(); + BEGIN( FindMembers ) ; + } +<Operator>";" { // can occur when importing members + unput(';'); + BEGIN( FindMembers ) ; + } +<Operator>[^(] { + lineCount(yyscanner); + yyextra->current->name += *yytext ; + } +<Operator>"<>" { /* skip guided templ specifiers */ } +<Operator>"(" { + yyextra->current->name = yyextra->current->name.simplifyWhiteSpace(); + unput(*yytext); + BEGIN( FindMembers ) ; + } +<FindMembers>("template"|"generic")({BN}*)"<"/[>]? { // generic is a C++/CLI extension + lineCount(yyscanner); + ArgumentList al; + //yyextra->current->spec |= (yytext[0]=='g') ? Entry::Generic : Entry::Template; + yyextra->current->tArgLists.push_back(al); + yyextra->currentArgumentList = &yyextra->current->tArgLists.back(); + yyextra->templateStr="<"; + yyextra->fullArgString = yyextra->templateStr; + yyextra->copyArgString = &yyextra->templateStr; + yyextra->currentArgumentContext = FindMembers; + BEGIN( ReadTempArgs ); + } <FindMembers>"namespace"{BN}+/{ID}{BN}*"=" { // namespace alias - lineCount(yyscanner); - BEGIN( NSAliasName ); - } -<NSAliasName>{ID} { - yyextra->aliasName = yytext; - BEGIN( NSAliasArg ); - } -<NSAliasArg>({ID}"::")*{ID} { - //printf("Inserting namespace alias %s::%s->%s\n",yyextra->current_root->name.data(),yyextra->aliasName.data(),yytext); + lineCount(yyscanner); + BEGIN( NSAliasName ); + } +<NSAliasName>{ID} { + yyextra->aliasName = yytext; + BEGIN( NSAliasArg ); + } +<NSAliasArg>({ID}"::")*{ID} { + //printf("Inserting namespace alias %s::%s->%s\n",yyextra->current_root->name.data(),yyextra->aliasName.data(),yytext); // TODO: namespace aliases are now treated as global entities // while they should be aware of the scope they are in Doxygen::namespaceAliasMap.insert({yyextra->aliasName.data(),std::string(yytext)}); - } -<NSAliasArg>";" { - BEGIN( FindMembers ); - } + } +<NSAliasArg>";" { + BEGIN( FindMembers ); + } <PHPUse>({ID}{BN}*"\\"{BN}*)*{ID}/{BN}+"as" { - lineCount(yyscanner); - yyextra->aliasName=yytext; - BEGIN(PHPUseAs); - } -<PHPUse>({ID}{BN}*"\\"{BN}*)*{ID} { - lineCount(yyscanner); - yyextra->current->name=removeRedundantWhiteSpace(substitute(yytext,"\\","::")); - //printf("PHP: adding use relation: %s\n",yyextra->current->name.data()); - yyextra->current->fileName = yyextra->yyFileName; + lineCount(yyscanner); + yyextra->aliasName=yytext; + BEGIN(PHPUseAs); + } +<PHPUse>({ID}{BN}*"\\"{BN}*)*{ID} { + lineCount(yyscanner); + yyextra->current->name=removeRedundantWhiteSpace(substitute(yytext,"\\","::")); + //printf("PHP: adding use relation: %s\n",yyextra->current->name.data()); + yyextra->current->fileName = yyextra->yyFileName; // add a using declaration - yyextra->current->section=Entry::USINGDECL_SEC; - yyextra->current_root->copyToSubEntry(yyextra->current); + yyextra->current->section=Entry::USINGDECL_SEC; + yyextra->current_root->copyToSubEntry(yyextra->current); // also add it as a using directive - yyextra->current->section=Entry::USINGDIR_SEC; - yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current); - initEntry(yyscanner); - yyextra->aliasName.resize(0); - } -<PHPUseAs>{BN}+"as"{BN}+ { - lineCount(yyscanner); - } + yyextra->current->section=Entry::USINGDIR_SEC; + yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current); + initEntry(yyscanner); + yyextra->aliasName.resize(0); + } +<PHPUseAs>{BN}+"as"{BN}+ { + lineCount(yyscanner); + } <PHPUseAs>{PHPUSEKW} { } -<PHPUseAs>{ID} { - //printf("PHP: adding use as relation: %s->%s\n",yytext,yyextra->aliasName.data()); +<PHPUseAs>{ID} { + //printf("PHP: adding use as relation: %s->%s\n",yytext,yyextra->aliasName.data()); if (!yyextra->aliasName.isEmpty()) { Doxygen::namespaceAliasMap.insert({yytext, - std::string(removeRedundantWhiteSpace( - substitute(yyextra->aliasName,"\\","::")).data())}); - } - yyextra->aliasName.resize(0); - } -<PHPUse,PHPUseAs>[,;] { - if (*yytext==',') - { - BEGIN(PHPUse); - } - else - { - BEGIN(FindMembers); - } - } -<JavaImport>({ID}{BN}*"."{BN}*)+"*" { // package import => add as a using directive - lineCount(yyscanner); - QCString scope=yytext; - yyextra->current->name=removeRedundantWhiteSpace(substitute(scope.left(scope.length()-1),".","::")); - yyextra->current->fileName = yyextra->yyFileName; - yyextra->current->section=Entry::USINGDIR_SEC; - yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current); - initEntry(yyscanner); - BEGIN(Using); - } -<JavaImport>({ID}{BN}*"."{BN}*)+{ID} { // class import => add as a using declaration + std::string(removeRedundantWhiteSpace( + substitute(yyextra->aliasName,"\\","::")).data())}); + } + yyextra->aliasName.resize(0); + } +<PHPUse,PHPUseAs>[,;] { + if (*yytext==',') + { + BEGIN(PHPUse); + } + else + { + BEGIN(FindMembers); + } + } +<JavaImport>({ID}{BN}*"."{BN}*)+"*" { // package import => add as a using directive + lineCount(yyscanner); + QCString scope=yytext; + yyextra->current->name=removeRedundantWhiteSpace(substitute(scope.left(scope.length()-1),".","::")); + yyextra->current->fileName = yyextra->yyFileName; + yyextra->current->section=Entry::USINGDIR_SEC; + yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current); + initEntry(yyscanner); + BEGIN(Using); + } +<JavaImport>({ID}{BN}*"."{BN}*)+{ID} { // class import => add as a using declaration lineCount(yyscanner); - QCString scope=yytext; - yyextra->current->name=removeRedundantWhiteSpace(substitute(scope,".","::")); - yyextra->current->fileName = yyextra->yyFileName; - if (yyextra->insideD) - { - yyextra->current->section=Entry::USINGDIR_SEC; - } - else - { - //printf("import name = %s -> %s\n",yytext,yyextra->current->name.data()); - yyextra->current->section=Entry::USINGDECL_SEC; - } + QCString scope=yytext; + yyextra->current->name=removeRedundantWhiteSpace(substitute(scope,".","::")); + yyextra->current->fileName = yyextra->yyFileName; + if (yyextra->insideD) + { + yyextra->current->section=Entry::USINGDIR_SEC; + } + else + { + //printf("import name = %s -> %s\n",yytext,yyextra->current->name.data()); + yyextra->current->section=Entry::USINGDECL_SEC; + } yyextra->previous = yyextra->current; - yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current); - initEntry(yyscanner); - BEGIN(Using); - } -<FindMembers>"using"{BN}+ { - yyextra->current->startLine=yyextra->yyLineNr; - yyextra->current->startColumn = yyextra->yyColNr; - lineCount(yyscanner); - BEGIN(Using); - } -<Using>"namespace"{BN}+ { lineCount(yyscanner); BEGIN(UsingDirective); } + yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current); + initEntry(yyscanner); + BEGIN(Using); + } +<FindMembers>"using"{BN}+ { + yyextra->current->startLine=yyextra->yyLineNr; + yyextra->current->startColumn = yyextra->yyColNr; + lineCount(yyscanner); + BEGIN(Using); + } +<Using>"namespace"{BN}+ { lineCount(yyscanner); BEGIN(UsingDirective); } <Using>({ID}{BN}*("::"|"."){BN}*)*({ID}|{OPERATOR}) { lineCount(yyscanner); - yyextra->current->name=yytext; - yyextra->current->fileName = yyextra->yyFileName; - yyextra->current->section=Entry::USINGDECL_SEC; + yyextra->current->name=yytext; + yyextra->current->fileName = yyextra->yyFileName; + yyextra->current->section=Entry::USINGDECL_SEC; yyextra->current->startLine = yyextra->yyLineNr; yyextra->previous = yyextra->current; - yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current); - initEntry(yyscanner); - if (yyextra->insideCS) /* Hack: in C# a using declaration and - directive have the same syntax, so we - also add it as a using directive here - */ - { - yyextra->current->name=yytext; - yyextra->current->fileName = yyextra->yyFileName; - yyextra->current->startLine = yyextra->yyLineNr; - yyextra->current->startColumn = yyextra->yyColNr; - yyextra->current->section=Entry::USINGDIR_SEC; - yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current); - initEntry(yyscanner); - } - BEGIN(Using); - } + yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current); + initEntry(yyscanner); + if (yyextra->insideCS) /* Hack: in C# a using declaration and + directive have the same syntax, so we + also add it as a using directive here + */ + { + yyextra->current->name=yytext; + yyextra->current->fileName = yyextra->yyFileName; + yyextra->current->startLine = yyextra->yyLineNr; + yyextra->current->startColumn = yyextra->yyColNr; + yyextra->current->section=Entry::USINGDIR_SEC; + yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current); + initEntry(yyscanner); + } + BEGIN(Using); + } <Using>"=" { // C++11 style template alias? BEGIN(UsingAlias); } -<UsingAlias>";" { +<UsingAlias>";" { yyextra->previous->section=Entry::VARIABLE_SEC; yyextra->previous->type = "typedef "+yyextra->previous->args; - yyextra->previous->type=yyextra->previous->type.simplifyWhiteSpace(); + yyextra->previous->type=yyextra->previous->type.simplifyWhiteSpace(); yyextra->previous->args.resize(0); - yyextra->previous->name=yyextra->previous->name.stripWhiteSpace(); - yyextra->previous->bodyLine = yyextra->yyLineNr; - yyextra->previous->bodyColumn = yyextra->yyColNr; + yyextra->previous->name=yyextra->previous->name.stripWhiteSpace(); + yyextra->previous->bodyLine = yyextra->yyLineNr; + yyextra->previous->bodyColumn = yyextra->yyColNr; yyextra->previous->spec |= Entry::Alias; - BEGIN(FindMembers); + BEGIN(FindMembers); } <UsingAlias>";"{BN}*("/**"|"//!"|"/*!"|"///")"<" { - yyextra->docBlockContext = UsingAliasEnd; - yyextra->docBlockInBody = FALSE; - yyextra->docBlockAutoBrief = ( yytext[yyleng-2]=='*' && Config_getBool(JAVADOC_AUTOBRIEF) ) || - ( yytext[yyleng-2]=='!' && Config_getBool(QT_AUTOBRIEF) ); + yyextra->docBlockContext = UsingAliasEnd; + yyextra->docBlockInBody = FALSE; + yyextra->docBlockAutoBrief = ( yytext[yyleng-2]=='*' && Config_getBool(JAVADOC_AUTOBRIEF) ) || + ( yytext[yyleng-2]=='!' && Config_getBool(QT_AUTOBRIEF) ); QCString indent; indent.fill(' ',computeIndent(yytext,yyextra->column)); yyextra->docBlock=indent; - lineCount(yyscanner); - - yyextra->docBlockTerm = ';'; - if (yytext[yyleng-3]=='/') - { - startCommentBlock(yyscanner,TRUE); - BEGIN( DocLine ); - } - else - { - startCommentBlock(yyscanner,FALSE); - BEGIN( DocBlock ); - } - } + lineCount(yyscanner); + + yyextra->docBlockTerm = ';'; + if (yytext[yyleng-3]=='/') + { + startCommentBlock(yyscanner,TRUE); + BEGIN( DocLine ); + } + else + { + startCommentBlock(yyscanner,FALSE); + BEGIN( DocBlock ); + } + } <UsingAlias>">>" { yyextra->previous->args+="> >"; // see bug769552 } @@ -1811,301 +1811,301 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) unput(';'); BEGIN(UsingAlias); } -<UsingDirective>{SCOPENAME} { yyextra->current->name=removeRedundantWhiteSpace(yytext); - yyextra->current->fileName = yyextra->yyFileName; - yyextra->current->section=Entry::USINGDIR_SEC; - yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current); - initEntry(yyscanner); - BEGIN(Using); - } -<Using>";" { BEGIN(FindMembers); } -<FindMembers>{SCOPENAME}{BN}*"<>" { // guided template decl - QCString n=yytext; - addType(yyscanner); - yyextra->current->name=n.left(n.length()-2); - } -<FindMembers>{SCOPENAME}{BN}*/"<" { // Note: this could be a return type! +<UsingDirective>{SCOPENAME} { yyextra->current->name=removeRedundantWhiteSpace(yytext); + yyextra->current->fileName = yyextra->yyFileName; + yyextra->current->section=Entry::USINGDIR_SEC; + yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current); + initEntry(yyscanner); + BEGIN(Using); + } +<Using>";" { BEGIN(FindMembers); } +<FindMembers>{SCOPENAME}{BN}*"<>" { // guided template decl + QCString n=yytext; + addType(yyscanner); + yyextra->current->name=n.left(n.length()-2); + } +<FindMembers>{SCOPENAME}{BN}*/"<" { // Note: this could be a return type! yyextra->roundCount=0; - yyextra->sharpCount=0; - lineCount(yyscanner); - addType(yyscanner); - yyextra->current->name=yytext; - yyextra->current->name=yyextra->current->name.stripWhiteSpace(); - //yyextra->current->scopeSpec.resize(0); - // yyextra->currentTemplateSpec = &yyextra->current->scopeSpec; - if (nameIsOperator(yyextra->current->name)) - BEGIN( Operator ); - else - BEGIN( EndTemplate ); - } -<FindMemberName>{SCOPENAME}{BN}*/"<" { - yyextra->sharpCount=0; - yyextra->roundCount=0; - lineCount(yyscanner); - yyextra->current->name+=((QCString)yytext).stripWhiteSpace(); - //yyextra->current->memberSpec.resize(0); - // yyextra->currentTemplateSpec = &yyextra->current->memberSpec; - if (nameIsOperator(yyextra->current->name)) - BEGIN( Operator ); - else - BEGIN( EndTemplate ); - } -<EndTemplate>"<<<" { - if (!yyextra->insidePHP) - { - REJECT; - } - else - { + yyextra->sharpCount=0; + lineCount(yyscanner); + addType(yyscanner); + yyextra->current->name=yytext; + yyextra->current->name=yyextra->current->name.stripWhiteSpace(); + //yyextra->current->scopeSpec.resize(0); + // yyextra->currentTemplateSpec = &yyextra->current->scopeSpec; + if (nameIsOperator(yyextra->current->name)) + BEGIN( Operator ); + else + BEGIN( EndTemplate ); + } +<FindMemberName>{SCOPENAME}{BN}*/"<" { + yyextra->sharpCount=0; + yyextra->roundCount=0; + lineCount(yyscanner); + yyextra->current->name+=((QCString)yytext).stripWhiteSpace(); + //yyextra->current->memberSpec.resize(0); + // yyextra->currentTemplateSpec = &yyextra->current->memberSpec; + if (nameIsOperator(yyextra->current->name)) + BEGIN( Operator ); + else + BEGIN( EndTemplate ); + } +<EndTemplate>"<<<" { + if (!yyextra->insidePHP) + { + REJECT; + } + else + { yyextra->lastHereDocContext = YY_START; - BEGIN(HereDoc); - } - } -<ClassTemplSpec,EndTemplate>"<<" { - yyextra->current->name+=yytext; - // *yyextra->currentTemplateSpec+=yytext; - } -<EndTemplate>"<" { + BEGIN(HereDoc); + } + } +<ClassTemplSpec,EndTemplate>"<<" { + yyextra->current->name+=yytext; + // *yyextra->currentTemplateSpec+=yytext; + } +<EndTemplate>"<" { if (yyextra->roundCount==0) { - // *yyextra->currentTemplateSpec+='<'; - yyextra->sharpCount++; + // *yyextra->currentTemplateSpec+='<'; + yyextra->sharpCount++; } - yyextra->current->name+=yytext; - } -<ClassTemplSpec,EndTemplate>">>" { - if (yyextra->insideJava || yyextra->insideCS || yyextra->insideCli || yyextra->roundCount==0) - { - unput('>'); - unput(' '); - unput('>'); - } - else - { - yyextra->current->name+=yytext; - } - // *yyextra->currentTemplateSpec+=yytext; - } -<EndTemplate>">" { - yyextra->current->name+='>'; - // *yyextra->currentTemplateSpec+='>'; - if (yyextra->roundCount==0 && --yyextra->sharpCount<=0) - { - //printf("Found %s\n",yyextra->current->name.data()); - BEGIN(FindMembers); - } - } -<EndTemplate>">"{BN}*"(" { - lineCount(yyscanner); - yyextra->current->name+='>'; - // *yyextra->currentTemplateSpec+='>'; - if (yyextra->roundCount==0 && --yyextra->sharpCount<=0) - { - yyextra->current->bodyLine = yyextra->yyLineNr; - yyextra->current->bodyColumn = yyextra->yyColNr; - yyextra->current->args = "("; - yyextra->currentArgumentContext = FuncQual; - yyextra->fullArgString = yyextra->current->args.copy(); - yyextra->copyArgString = &yyextra->current->args; - //printf("Found %s\n",yyextra->current->name.data()); - BEGIN( ReadFuncArgType ) ; - } - } + yyextra->current->name+=yytext; + } +<ClassTemplSpec,EndTemplate>">>" { + if (yyextra->insideJava || yyextra->insideCS || yyextra->insideCli || yyextra->roundCount==0) + { + unput('>'); + unput(' '); + unput('>'); + } + else + { + yyextra->current->name+=yytext; + } + // *yyextra->currentTemplateSpec+=yytext; + } +<EndTemplate>">" { + yyextra->current->name+='>'; + // *yyextra->currentTemplateSpec+='>'; + if (yyextra->roundCount==0 && --yyextra->sharpCount<=0) + { + //printf("Found %s\n",yyextra->current->name.data()); + BEGIN(FindMembers); + } + } +<EndTemplate>">"{BN}*"(" { + lineCount(yyscanner); + yyextra->current->name+='>'; + // *yyextra->currentTemplateSpec+='>'; + if (yyextra->roundCount==0 && --yyextra->sharpCount<=0) + { + yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->current->bodyColumn = yyextra->yyColNr; + yyextra->current->args = "("; + yyextra->currentArgumentContext = FuncQual; + yyextra->fullArgString = yyextra->current->args.copy(); + yyextra->copyArgString = &yyextra->current->args; + //printf("Found %s\n",yyextra->current->name.data()); + BEGIN( ReadFuncArgType ) ; + } + } <EndTemplate>">"{BN}*/"("({BN}*{ID}{BN}*"::")*({BN}*"*"{BN}*)+ { // function pointer returning a template instance - lineCount(yyscanner); - yyextra->current->name+='>'; + lineCount(yyscanner); + yyextra->current->name+='>'; if (yyextra->roundCount==0) { - BEGIN(FindMembers); - } - } -<EndTemplate>">"{BN}*/"::" { - lineCount(yyscanner); - yyextra->current->name+='>'; - // *yyextra->currentTemplateSpec+='>'; - if (yyextra->roundCount==0 && --yyextra->sharpCount<=0) - { - BEGIN(FindMemberName); - } - } + BEGIN(FindMembers); + } + } +<EndTemplate>">"{BN}*/"::" { + lineCount(yyscanner); + yyextra->current->name+='>'; + // *yyextra->currentTemplateSpec+='>'; + if (yyextra->roundCount==0 && --yyextra->sharpCount<=0) + { + BEGIN(FindMemberName); + } + } <ClassTemplSpec,EndTemplate>"(" { yyextra->current->name+=*yytext; - yyextra->roundCount++; + yyextra->roundCount++; } <ClassTemplSpec,EndTemplate>")" { yyextra->current->name+=*yytext; - if (yyextra->roundCount>0) yyextra->roundCount--; + if (yyextra->roundCount>0) yyextra->roundCount--; + } +<EndTemplate>. { + yyextra->current->name+=*yytext; + // *yyextra->currentTemplateSpec+=*yytext; + } +<FindMembers>"define"{BN}*"("{BN}*["'] { + if (yyextra->insidePHP) + { + yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->current->bodyColumn = yyextra->yyColNr; + BEGIN( DefinePHP ); + } + else + REJECT; } -<EndTemplate>. { - yyextra->current->name+=*yytext; - // *yyextra->currentTemplateSpec+=*yytext; - } -<FindMembers>"define"{BN}*"("{BN}*["'] { - if (yyextra->insidePHP) - { - yyextra->current->bodyLine = yyextra->yyLineNr; - yyextra->current->bodyColumn = yyextra->yyColNr; - BEGIN( DefinePHP ); - } - else - REJECT; - } <CopyHereDoc>{ID} { // PHP heredoc - yyextra->delimiter = yytext; + yyextra->delimiter = yytext; *yyextra->pCopyHereDocGString += yytext; - BEGIN(CopyHereDocEnd); + BEGIN(CopyHereDocEnd); } -<CopyHereDoc>"'"{ID}/"'" { // PHP nowdoc - yyextra->delimiter = &yytext[1]; +<CopyHereDoc>"'"{ID}/"'" { // PHP nowdoc + yyextra->delimiter = &yytext[1]; *yyextra->pCopyHereDocGString += yytext; - BEGIN(CopyHereDocEnd); - } -<HereDoc>{ID} { // PHP heredoc - yyextra->delimiter = yytext; - BEGIN(HereDocEnd); - } -<HereDoc>"'"{ID}/"'" { // PHP nowdoc - yyextra->delimiter = &yytext[1]; - BEGIN(HereDocEnd); - } -<HereDocEnd>^{ID} { // id at start of the line could mark the end of the block - if (yyextra->delimiter==yytext) // it is the end marker - { - BEGIN(yyextra->lastHereDocContext); - } - } -<HereDocEnd>. { } -<CopyHereDocEnd>^{ID} { // id at start of the line could mark the end of the block + BEGIN(CopyHereDocEnd); + } +<HereDoc>{ID} { // PHP heredoc + yyextra->delimiter = yytext; + BEGIN(HereDocEnd); + } +<HereDoc>"'"{ID}/"'" { // PHP nowdoc + yyextra->delimiter = &yytext[1]; + BEGIN(HereDocEnd); + } +<HereDocEnd>^{ID} { // id at start of the line could mark the end of the block + if (yyextra->delimiter==yytext) // it is the end marker + { + BEGIN(yyextra->lastHereDocContext); + } + } +<HereDocEnd>. { } +<CopyHereDocEnd>^{ID} { // id at start of the line could mark the end of the block *yyextra->pCopyHereDocGString += yytext; - if (yyextra->delimiter==yytext) // it is the end marker - { - BEGIN(yyextra->lastHereDocContext); - } - } -<CopyHereDocEnd>\n { + if (yyextra->delimiter==yytext) // it is the end marker + { + BEGIN(yyextra->lastHereDocContext); + } + } +<CopyHereDocEnd>\n { lineCount(yyscanner); *yyextra->pCopyHereDocGString += yytext; } -<CopyHereDocEnd>{ID} { +<CopyHereDocEnd>{ID} { *yyextra->pCopyHereDocGString += yytext; } -<CopyHereDocEnd>. { +<CopyHereDocEnd>. { *yyextra->pCopyHereDocGString += yytext; } -<FindMembers>"Q_OBJECT" { // Qt object macro - } -<FindMembers>"Q_PROPERTY" { // Qt property declaration - yyextra->current->protection = Public ; // see bug734245 & bug735462 - yyextra->current->mtype = yyextra->mtype = Property; - yyextra->current->type.resize(0); - BEGIN(QtPropType); - } -<QtPropType>"(" { // start of property arguments - } -<QtPropAttr>")" { // end of property arguments - unput(';'); - BEGIN(FindMembers); - } -<QtPropType>{B}+ { - yyextra->current->name+=yytext; - } -<QtPropType>"*" { - yyextra->current->type+= yyextra->current->name; - yyextra->current->type+= yytext; - yyextra->current->name=""; - } -<QtPropType>({TSCOPE}"::")*{TSCOPE} { - yyextra->current->type+= yyextra->current->name; - yyextra->current->name=yytext; - } -<QtPropType,QtPropAttr>{B}+"READ"{B}+ { - yyextra->current->spec |= Entry::Readable; - BEGIN(QtPropRead); - } -<QtPropType,QtPropAttr>{B}+"WRITE"{B}+ { - yyextra->current->spec |= Entry::Writable; - BEGIN(QtPropWrite); - } -<QtPropType,QtPropAttr>{B}+"MEMBER"{B}+{ID} | // member property => not supported yet -<QtPropType,QtPropAttr>{B}+"RESET"{B}+{ID} | // reset method => not supported yet -<QtPropType,QtPropAttr>{B}+"SCRIPTABLE"{B}+{ID} | // scriptable property => not supported yet -<QtPropType,QtPropAttr>{B}+"DESIGNABLE"{B}+{ID} | // designable property => not supported yet -<QtPropType,QtPropAttr>{B}+"NOTIFY"{B}+{ID} | // notify property => not supported yet -<QtPropType,QtPropAttr>{B}+"REVISION"{B}+{ID} | // revision property => not supported yet -<QtPropType,QtPropAttr>{B}+"STORED"{B}+{ID} | // stored property => not supported yet -<QtPropType,QtPropAttr>{B}+"USER"{B}+{ID} | // user property => not supported yet -<QtPropType,QtPropAttr>{B}+"CONSTANT"{B} | // constant property => not supported yet -<QtPropType,QtPropAttr>{B}+"FINAL"{B} { // final property => not supported yet - BEGIN(QtPropAttr); - } -<QtPropRead>{ID} { - yyextra->current->read = yytext; - BEGIN(QtPropAttr); - } -<QtPropWrite>{ID} { - yyextra->current->write = yytext; - BEGIN(QtPropAttr); - } +<FindMembers>"Q_OBJECT" { // Qt object macro + } +<FindMembers>"Q_PROPERTY" { // Qt property declaration + yyextra->current->protection = Public ; // see bug734245 & bug735462 + yyextra->current->mtype = yyextra->mtype = Property; + yyextra->current->type.resize(0); + BEGIN(QtPropType); + } +<QtPropType>"(" { // start of property arguments + } +<QtPropAttr>")" { // end of property arguments + unput(';'); + BEGIN(FindMembers); + } +<QtPropType>{B}+ { + yyextra->current->name+=yytext; + } +<QtPropType>"*" { + yyextra->current->type+= yyextra->current->name; + yyextra->current->type+= yytext; + yyextra->current->name=""; + } +<QtPropType>({TSCOPE}"::")*{TSCOPE} { + yyextra->current->type+= yyextra->current->name; + yyextra->current->name=yytext; + } +<QtPropType,QtPropAttr>{B}+"READ"{B}+ { + yyextra->current->spec |= Entry::Readable; + BEGIN(QtPropRead); + } +<QtPropType,QtPropAttr>{B}+"WRITE"{B}+ { + yyextra->current->spec |= Entry::Writable; + BEGIN(QtPropWrite); + } +<QtPropType,QtPropAttr>{B}+"MEMBER"{B}+{ID} | // member property => not supported yet +<QtPropType,QtPropAttr>{B}+"RESET"{B}+{ID} | // reset method => not supported yet +<QtPropType,QtPropAttr>{B}+"SCRIPTABLE"{B}+{ID} | // scriptable property => not supported yet +<QtPropType,QtPropAttr>{B}+"DESIGNABLE"{B}+{ID} | // designable property => not supported yet +<QtPropType,QtPropAttr>{B}+"NOTIFY"{B}+{ID} | // notify property => not supported yet +<QtPropType,QtPropAttr>{B}+"REVISION"{B}+{ID} | // revision property => not supported yet +<QtPropType,QtPropAttr>{B}+"STORED"{B}+{ID} | // stored property => not supported yet +<QtPropType,QtPropAttr>{B}+"USER"{B}+{ID} | // user property => not supported yet +<QtPropType,QtPropAttr>{B}+"CONSTANT"{B} | // constant property => not supported yet +<QtPropType,QtPropAttr>{B}+"FINAL"{B} { // final property => not supported yet + BEGIN(QtPropAttr); + } +<QtPropRead>{ID} { + yyextra->current->read = yytext; + BEGIN(QtPropAttr); + } +<QtPropWrite>{ID} { + yyextra->current->write = yytext; + BEGIN(QtPropAttr); + } <FindMembers>"friend"{BN}+("class"|"union"|"struct"){BN}+ { - yyextra->current->name=yytext; - BEGIN(FindMembers); - } -<FindMembers,FindMemberName>{SCOPENAME} { + yyextra->current->name=yytext; + BEGIN(FindMembers); + } +<FindMembers,FindMemberName>{SCOPENAME} { if (yyextra->clangParser && (yyextra->insideCpp || yyextra->insideObjC)) { yyextra->current->id = yyextra->clangParser->lookup(yyextra->yyLineNr,yytext); } - yyextra->yyBegColNr=yyextra->yyColNr; - yyextra->yyBegLineNr=yyextra->yyLineNr; - lineCount(yyscanner); + yyextra->yyBegColNr=yyextra->yyColNr; + yyextra->yyBegLineNr=yyextra->yyLineNr; + lineCount(yyscanner); if (yyextra->insideIDL && yyleng==9 && qstrcmp(yytext,"cpp_quote")==0) - { - BEGIN(CppQuote); - } - else if ((yyextra->insideIDL || yyextra->insideJava || yyextra->insideD) && yyleng==6 && qstrcmp(yytext,"import")==0) - { - if (yyextra->insideIDL) - BEGIN(NextSemi); - else // yyextra->insideJava or yyextra->insideD - BEGIN(JavaImport); - } - else if (yyextra->insidePHP && qstrcmp(yytext,"use")==0) - { - BEGIN(PHPUse); - } - else if (yyextra->insideJava && qstrcmp(yytext,"package")==0) - { - lineCount(yyscanner); - BEGIN(PackageName); - } - else if (yyextra->insideIDL && qstrcmp(yytext,"case")==0) - { - BEGIN(IDLUnionCase); - } - else if (yyextra->insideTryBlock && qstrcmp(yytext,"catch")==0) - { - yyextra->insideTryBlock=FALSE; - BEGIN(TryFunctionBlock); - } + { + BEGIN(CppQuote); + } + else if ((yyextra->insideIDL || yyextra->insideJava || yyextra->insideD) && yyleng==6 && qstrcmp(yytext,"import")==0) + { + if (yyextra->insideIDL) + BEGIN(NextSemi); + else // yyextra->insideJava or yyextra->insideD + BEGIN(JavaImport); + } + else if (yyextra->insidePHP && qstrcmp(yytext,"use")==0) + { + BEGIN(PHPUse); + } + else if (yyextra->insideJava && qstrcmp(yytext,"package")==0) + { + lineCount(yyscanner); + BEGIN(PackageName); + } + else if (yyextra->insideIDL && qstrcmp(yytext,"case")==0) + { + BEGIN(IDLUnionCase); + } + else if (yyextra->insideTryBlock && qstrcmp(yytext,"catch")==0) + { + yyextra->insideTryBlock=FALSE; + BEGIN(TryFunctionBlock); + } else if (yyextra->insideCpp && qstrcmp(yytext,"alignas")==0) { yyextra->lastAlignAsContext = YY_START; BEGIN(AlignAs); } - else if (yyextra->insideJS && qstrcmp(yytext,"var")==0) - { // javascript variable - yyextra->current->type="var"; - } - else if (yyextra->insideJS && qstrcmp(yytext,"function")==0) - { // javascript function - yyextra->current->type="function"; - } - else if (yyextra->insideCS && qstrcmp(yytext,"this")==0) - { - // C# indexer - addType(yyscanner); - yyextra->current->name="this"; - BEGIN(CSIndexer); - } + else if (yyextra->insideJS && qstrcmp(yytext,"var")==0) + { // javascript variable + yyextra->current->type="var"; + } + else if (yyextra->insideJS && qstrcmp(yytext,"function")==0) + { // javascript function + yyextra->current->type="function"; + } + else if (yyextra->insideCS && qstrcmp(yytext,"this")==0) + { + // C# indexer + addType(yyscanner); + yyextra->current->name="this"; + BEGIN(CSIndexer); + } else if (yyextra->insideCpp && qstrcmp(yytext,"static_assert")==0) { // C++11 static_assert @@ -2114,7 +2114,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) else if (yyextra->insideCpp && qstrcmp(yytext,"decltype")==0) { // C++11 decltype(x) - yyextra->current->type+=yytext; + yyextra->current->type+=yytext; BEGIN(DeclType); } else if (yyextra->insideSlice && qstrcmp(yytext,"optional")==0) @@ -2130,88 +2130,88 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) yyextra->lastModifierContext = YY_START; BEGIN(SliceOptional); } - else - { - if (YY_START==FindMembers) - { - addType(yyscanner); - } - bool javaLike = yyextra->insideJava || yyextra->insideCS || yyextra->insideD || yyextra->insidePHP || yyextra->insideJS; - if (javaLike && qstrcmp(yytext,"public")==0) - { - yyextra->current->protection = Public; - } - else if (javaLike && qstrcmp(yytext,"protected")==0) - { - yyextra->current->protection = Protected; - } - else if ((yyextra->insideCS || yyextra->insideD || yyextra->insidePHP || yyextra->insideJS) && qstrcmp(yytext,"internal")==0) - { - yyextra->current->protection = Package; - } - else if (javaLike && qstrcmp(yytext,"private")==0) - { - yyextra->current->protection = Private; - } - else if (javaLike && qstrcmp(yytext,"static")==0) - { - if (YY_START==FindMembers) - yyextra->current->name = yytext; - else - yyextra->current->name += yytext; - yyextra->current->stat = TRUE; - } - else - { - if (YY_START==FindMembers) - yyextra->current->name = yytext; - else - yyextra->current->name += yytext; - if (yyextra->current->name.left(7)=="static ") - { - yyextra->current->stat = TRUE; - yyextra->current->name= yyextra->current->name.mid(7); - } - else if (yyextra->current->name.left(7)=="inline ") - { - if (yyextra->current->type.isEmpty()) - { - yyextra->current->type="inline"; - } - else - { - yyextra->current->type+="inline "; - } - yyextra->current->name= yyextra->current->name.mid(7); - } - else if (yyextra->current->name.left(6)=="const ") - { - if (yyextra->current->type.isEmpty()) - { - yyextra->current->type="const"; - } - else - { - yyextra->current->type+="const "; - } - yyextra->current->name=yyextra->current->name.mid(6); - } - } - QCString tmp=yytext; - if (nameIsOperator(tmp)) + else + { + if (YY_START==FindMembers) { - BEGIN( Operator ); + addType(yyscanner); } - else + bool javaLike = yyextra->insideJava || yyextra->insideCS || yyextra->insideD || yyextra->insidePHP || yyextra->insideJS; + if (javaLike && qstrcmp(yytext,"public")==0) { - yyextra->externC=FALSE; // see bug759247 - BEGIN(FindMembers); + yyextra->current->protection = Public; } - } - } + else if (javaLike && qstrcmp(yytext,"protected")==0) + { + yyextra->current->protection = Protected; + } + else if ((yyextra->insideCS || yyextra->insideD || yyextra->insidePHP || yyextra->insideJS) && qstrcmp(yytext,"internal")==0) + { + yyextra->current->protection = Package; + } + else if (javaLike && qstrcmp(yytext,"private")==0) + { + yyextra->current->protection = Private; + } + else if (javaLike && qstrcmp(yytext,"static")==0) + { + if (YY_START==FindMembers) + yyextra->current->name = yytext; + else + yyextra->current->name += yytext; + yyextra->current->stat = TRUE; + } + else + { + if (YY_START==FindMembers) + yyextra->current->name = yytext; + else + yyextra->current->name += yytext; + if (yyextra->current->name.left(7)=="static ") + { + yyextra->current->stat = TRUE; + yyextra->current->name= yyextra->current->name.mid(7); + } + else if (yyextra->current->name.left(7)=="inline ") + { + if (yyextra->current->type.isEmpty()) + { + yyextra->current->type="inline"; + } + else + { + yyextra->current->type+="inline "; + } + yyextra->current->name= yyextra->current->name.mid(7); + } + else if (yyextra->current->name.left(6)=="const ") + { + if (yyextra->current->type.isEmpty()) + { + yyextra->current->type="const"; + } + else + { + yyextra->current->type+="const "; + } + yyextra->current->name=yyextra->current->name.mid(6); + } + } + QCString tmp=yytext; + if (nameIsOperator(tmp)) + { + BEGIN( Operator ); + } + else + { + yyextra->externC=FALSE; // see bug759247 + BEGIN(FindMembers); + } + } + } <StaticAssert>"(" { - yyextra->lastSkipRoundContext = FindMembers; - yyextra->roundCount=0; + yyextra->lastSkipRoundContext = FindMembers; + yyextra->roundCount=0; BEGIN(SkipRound); } <StaticAssert>{BN}+ { lineCount(yyscanner); } @@ -2220,10 +2220,10 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) BEGIN(FindMembers); } <DeclType>"(" { - yyextra->current->type+=yytext; - yyextra->lastRoundContext=FindMembers; - yyextra->pCopyRoundString=&yyextra->current->type; - yyextra->roundCount=0; + yyextra->current->type+=yytext; + yyextra->lastRoundContext=FindMembers; + yyextra->pCopyRoundString=&yyextra->current->type; + yyextra->roundCount=0; BEGIN(CopyRound); } <DeclType>{BN}+ { lineCount(yyscanner); } @@ -2231,361 +2231,361 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) unput(*yytext); BEGIN(FindMembers); } -<CSIndexer>"["[^\n\]]*"]" { - yyextra->current->name+=removeRedundantWhiteSpace(yytext); - BEGIN(FindMembers); - } -<FindMembers>[0-9]{ID} { // some number where we did not expect one - } -<FindMembers>"." { - if (yyextra->insideJava || yyextra->insideCS || yyextra->insideD) - { - yyextra->current->name+="."; - } - } -<FindMembers>"::" { - yyextra->current->name+=yytext; - } -<CppQuote>"("{B}*"\"" { - yyextra->insideCppQuote=TRUE; - BEGIN(FindMembers); - } +<CSIndexer>"["[^\n\]]*"]" { + yyextra->current->name+=removeRedundantWhiteSpace(yytext); + BEGIN(FindMembers); + } +<FindMembers>[0-9]{ID} { // some number where we did not expect one + } +<FindMembers>"." { + if (yyextra->insideJava || yyextra->insideCS || yyextra->insideD) + { + yyextra->current->name+="."; + } + } +<FindMembers>"::" { + yyextra->current->name+=yytext; + } +<CppQuote>"("{B}*"\"" { + yyextra->insideCppQuote=TRUE; + BEGIN(FindMembers); + } <IDLUnionCase>"::" -<IDLUnionCase>":" { BEGIN(FindMembers); } -<IDLUnionCase>\n { lineCount(yyscanner); } +<IDLUnionCase>":" { BEGIN(FindMembers); } +<IDLUnionCase>\n { lineCount(yyscanner); } <IDLUnionCase>. -<TryFunctionBlock>\n { lineCount(yyscanner); } -<TryFunctionBlock>"{" { - yyextra->curlyCount=0; - yyextra->lastCurlyContext = TryFunctionBlockEnd ; - BEGIN( SkipCurly ); - } +<TryFunctionBlock>\n { lineCount(yyscanner); } +<TryFunctionBlock>"{" { + yyextra->curlyCount=0; + yyextra->lastCurlyContext = TryFunctionBlockEnd ; + BEGIN( SkipCurly ); + } <TryFunctionBlock>. -<TryFunctionBlockEnd>{BN}*"catch" { lineCount(yyscanner); BEGIN(TryFunctionBlock); // {BN}* added to fix bug 611193 - } -<TryFunctionBlockEnd>\n { unput(*yytext); // rule added to fix bug id 601138 - BEGIN( FindMembers ); - } -<TryFunctionBlockEnd>. { unput(*yytext); - BEGIN( FindMembers ); - } -<EndCppQuote>")" { - yyextra->insideCppQuote=FALSE; - BEGIN(FindMembers); - } -<FindMembers,FindFields>{B}*"#" { if (yyextra->insidePHP) - REJECT; - yyextra->lastCPPContext = YY_START; - BEGIN( SkipCPP ) ; - } -<FindMembers,FindFields>{B}*"#"{B}*("cmake")?"define" { - if (yyextra->insidePHP) - REJECT; - yyextra->current->bodyLine = yyextra->yyLineNr; - yyextra->current->bodyColumn = yyextra->yyColNr; +<TryFunctionBlockEnd>{BN}*"catch" { lineCount(yyscanner); BEGIN(TryFunctionBlock); // {BN}* added to fix bug 611193 + } +<TryFunctionBlockEnd>\n { unput(*yytext); // rule added to fix bug id 601138 + BEGIN( FindMembers ); + } +<TryFunctionBlockEnd>. { unput(*yytext); + BEGIN( FindMembers ); + } +<EndCppQuote>")" { + yyextra->insideCppQuote=FALSE; + BEGIN(FindMembers); + } +<FindMembers,FindFields>{B}*"#" { if (yyextra->insidePHP) + REJECT; + yyextra->lastCPPContext = YY_START; + BEGIN( SkipCPP ) ; + } +<FindMembers,FindFields>{B}*"#"{B}*("cmake")?"define" { + if (yyextra->insidePHP) + REJECT; + yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->current->bodyColumn = yyextra->yyColNr; yyextra->lastDefineContext = YY_START; - BEGIN( Define ); - } -<FindMembers,ReadBody,ReadNSBody,ReadBodyIntf,SkipCurly,SkipCurlyCpp>{B}*"#"{B}+[0-9]+{B}+/"\"" { /* line control directive */ + BEGIN( Define ); + } +<FindMembers,ReadBody,ReadNSBody,ReadBodyIntf,SkipCurly,SkipCurlyCpp>{B}*"#"{B}+[0-9]+{B}+/"\"" { /* line control directive */ yyextra->yyLineNr = atoi(&yytext[1]); - //printf("setting line number to %d\n",yyextra->yyLineNr); - yyextra->lastPreLineCtrlContext = YY_START; - if (YY_START==ReadBody || - YY_START==ReadNSBody || - YY_START==ReadBodyIntf) - { - yyextra->current->program+=yytext; - } - BEGIN( PreLineCtrl ); - } -<PreLineCtrl>"\""[^\n\"]*"\"" { - yyextra->yyFileName = stripQuotes(yytext); - if (yyextra->lastPreLineCtrlContext==ReadBody || - yyextra->lastPreLineCtrlContext==ReadNSBody || - yyextra->lastPreLineCtrlContext==ReadBodyIntf) - { - yyextra->current->program+=yytext; - } - } -<PreLineCtrl>. { - if (yyextra->lastPreLineCtrlContext==ReadBody || - yyextra->lastPreLineCtrlContext==ReadNSBody || - yyextra->lastPreLineCtrlContext==ReadBodyIntf) - { - yyextra->current->program+=yytext; - } - } -<PreLineCtrl>\n { - if (yyextra->lastPreLineCtrlContext==ReadBody || - yyextra->lastPreLineCtrlContext==ReadNSBody || - yyextra->lastPreLineCtrlContext==ReadBodyIntf) - { - yyextra->current->program+=yytext; - } + //printf("setting line number to %d\n",yyextra->yyLineNr); + yyextra->lastPreLineCtrlContext = YY_START; + if (YY_START==ReadBody || + YY_START==ReadNSBody || + YY_START==ReadBodyIntf) + { + yyextra->current->program+=yytext; + } + BEGIN( PreLineCtrl ); + } +<PreLineCtrl>"\""[^\n\"]*"\"" { + yyextra->yyFileName = stripQuotes(yytext); + if (yyextra->lastPreLineCtrlContext==ReadBody || + yyextra->lastPreLineCtrlContext==ReadNSBody || + yyextra->lastPreLineCtrlContext==ReadBodyIntf) + { + yyextra->current->program+=yytext; + } + } +<PreLineCtrl>. { + if (yyextra->lastPreLineCtrlContext==ReadBody || + yyextra->lastPreLineCtrlContext==ReadNSBody || + yyextra->lastPreLineCtrlContext==ReadBodyIntf) + { + yyextra->current->program+=yytext; + } + } +<PreLineCtrl>\n { + if (yyextra->lastPreLineCtrlContext==ReadBody || + yyextra->lastPreLineCtrlContext==ReadNSBody || + yyextra->lastPreLineCtrlContext==ReadBodyIntf) + { + yyextra->current->program+=yytext; + } lineCount(yyscanner); - BEGIN( yyextra->lastPreLineCtrlContext ); - } + BEGIN( yyextra->lastPreLineCtrlContext ); + } <SkipCPP>. -<SkipCPP>\\[\r]*"\n"[\r]* { lineCount(yyscanner); } -<SkipCPP>[\r]*\n[\r]* { lineCount(yyscanner); - BEGIN( yyextra->lastCPPContext) ; - } -<Define>{ID}{B}*"(" { - yyextra->current->name = yytext; - yyextra->current->name = yyextra->current->name.left(yyextra->current->name.length()-1).stripWhiteSpace(); - yyextra->current->args = "("; - yyextra->current->bodyLine = yyextra->yyLineNr; - yyextra->current->bodyColumn = yyextra->yyColNr; - yyextra->currentArgumentContext = DefineEnd; - yyextra->fullArgString=yyextra->current->args.copy(); - yyextra->copyArgString=&yyextra->current->args; - BEGIN( ReadFuncArgType ) ; - } +<SkipCPP>\\[\r]*"\n"[\r]* { lineCount(yyscanner); } +<SkipCPP>[\r]*\n[\r]* { lineCount(yyscanner); + BEGIN( yyextra->lastCPPContext) ; + } +<Define>{ID}{B}*"(" { + yyextra->current->name = yytext; + yyextra->current->name = yyextra->current->name.left(yyextra->current->name.length()-1).stripWhiteSpace(); + yyextra->current->args = "("; + yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->current->bodyColumn = yyextra->yyColNr; + yyextra->currentArgumentContext = DefineEnd; + yyextra->fullArgString=yyextra->current->args.copy(); + yyextra->copyArgString=&yyextra->current->args; + BEGIN( ReadFuncArgType ) ; + } /* -<DefineArg>")" { - //printf("Define with args\n"); - yyextra->current->args += ')'; - BEGIN( DefineEnd ); - } -<DefineArg>. { - yyextra->current->args += *yytext; - } +<DefineArg>")" { + //printf("Define with args\n"); + yyextra->current->args += ')'; + BEGIN( DefineEnd ); + } +<DefineArg>. { + yyextra->current->args += *yytext; + } */ -<Define>{ID} { - //printf("Define '%s' without args\n",yytext); +<Define>{ID} { + //printf("Define '%s' without args\n",yytext); if (yyextra->clangParser && (yyextra->insideCpp || yyextra->insideObjC)) { yyextra->current->id = yyextra->clangParser->lookup(yyextra->yyLineNr,yytext); } - yyextra->current->bodyLine = yyextra->yyLineNr; - yyextra->current->bodyColumn = yyextra->yyColNr; - yyextra->current->name = yytext; - BEGIN(DefineEnd); - } -<DefineEnd>\n { - //printf("End define: doc=%s docFile=%s docLine=%d\n",yyextra->current->doc.data(),yyextra->current->docFile.data(),yyextra->current->docLine); - yyextra->current->fileName = yyextra->yyFileName; - yyextra->current->startLine = yyextra->yyLineNr; - yyextra->current->startColumn = yyextra->yyColNr; - yyextra->current->type.resize(0); - yyextra->current->args = yyextra->current->args.simplifyWhiteSpace(); - yyextra->current->name = yyextra->current->name.stripWhiteSpace(); - yyextra->current->section = Entry::DEFINE_SEC; - yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current); + yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->current->bodyColumn = yyextra->yyColNr; + yyextra->current->name = yytext; + BEGIN(DefineEnd); + } +<DefineEnd>\n { + //printf("End define: doc=%s docFile=%s docLine=%d\n",yyextra->current->doc.data(),yyextra->current->docFile.data(),yyextra->current->docLine); + yyextra->current->fileName = yyextra->yyFileName; + yyextra->current->startLine = yyextra->yyLineNr; + yyextra->current->startColumn = yyextra->yyColNr; + yyextra->current->type.resize(0); + yyextra->current->args = yyextra->current->args.simplifyWhiteSpace(); + yyextra->current->name = yyextra->current->name.stripWhiteSpace(); + yyextra->current->section = Entry::DEFINE_SEC; + yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current); lineCount(yyscanner); - initEntry(yyscanner); - BEGIN(yyextra->lastDefineContext); - } -<DefinePHPEnd>";" { - //printf("End define\n"); - yyextra->current->fileName = yyextra->yyFileName; - yyextra->current->startLine = yyextra->yyLineNr; - yyextra->current->startColumn = yyextra->yyColNr; - yyextra->current->type.resize(0); + initEntry(yyscanner); + BEGIN(yyextra->lastDefineContext); + } +<DefinePHPEnd>";" { + //printf("End define\n"); + yyextra->current->fileName = yyextra->yyFileName; + yyextra->current->startLine = yyextra->yyLineNr; + yyextra->current->startColumn = yyextra->yyColNr; + yyextra->current->type.resize(0); yyextra->current->type = "const"; QCString init = yyextra->current->initializer.data(); - init = init.simplifyWhiteSpace(); - init = init.left(init.length()-1); + init = init.simplifyWhiteSpace(); + init = init.left(init.length()-1); yyextra->current->initializer = init; - yyextra->current->name = yyextra->current->name.stripWhiteSpace(); - yyextra->current->section = Entry::VARIABLE_SEC; - yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current); - initEntry(yyscanner); - BEGIN(FindMembers); - } + yyextra->current->name = yyextra->current->name.stripWhiteSpace(); + yyextra->current->section = Entry::VARIABLE_SEC; + yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current); + initEntry(yyscanner); + BEGIN(FindMembers); + } <DefinePHPEnd>. -<DefineEnd>\\[\r]?\n { +<DefineEnd>\\[\r]?\n { lineCount(yyscanner); - } -<DefineEnd>\" { - if (yyextra->insideIDL && yyextra->insideCppQuote) - { - BEGIN(EndCppQuote); - } - else - { - yyextra->lastStringContext=DefineEnd; - BEGIN(SkipString); - } - } -<DefineEnd>. -<DefinePHP>{ID}["']{BN}*","{BN}* { - yyextra->current->name = yytext; - yyextra->current->name = yyextra->current->name.stripWhiteSpace(); - yyextra->current->name = yyextra->current->name.left(yyextra->current->name.length()-1).stripWhiteSpace(); - yyextra->current->name = yyextra->current->name.left(yyextra->current->name.length()-1); - yyextra->current->bodyLine = yyextra->yyLineNr; - yyextra->current->bodyColumn = yyextra->yyColNr; - yyextra->lastRoundContext = DefinePHPEnd; - yyextra->pCopyRoundGString = &yyextra->current->initializer; - yyextra->roundCount = 0; - BEGIN( GCopyRound ); - } + } +<DefineEnd>\" { + if (yyextra->insideIDL && yyextra->insideCppQuote) + { + BEGIN(EndCppQuote); + } + else + { + yyextra->lastStringContext=DefineEnd; + BEGIN(SkipString); + } + } +<DefineEnd>. +<DefinePHP>{ID}["']{BN}*","{BN}* { + yyextra->current->name = yytext; + yyextra->current->name = yyextra->current->name.stripWhiteSpace(); + yyextra->current->name = yyextra->current->name.left(yyextra->current->name.length()-1).stripWhiteSpace(); + yyextra->current->name = yyextra->current->name.left(yyextra->current->name.length()-1); + yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->current->bodyColumn = yyextra->yyColNr; + yyextra->lastRoundContext = DefinePHPEnd; + yyextra->pCopyRoundGString = &yyextra->current->initializer; + yyextra->roundCount = 0; + BEGIN( GCopyRound ); + } -<FindMembers>[\^%] { // ^ and % are C++/CLI extensions - if (yyextra->insideCli) - { - addType(yyscanner); - yyextra->current->name = yytext ; - } - else - { - REJECT; - } - } -<FindMembers>[*&]+ { - yyextra->current->name += yytext ; - addType(yyscanner); - } +<FindMembers>[\^%] { // ^ and % are C++/CLI extensions + if (yyextra->insideCli) + { + addType(yyscanner); + yyextra->current->name = yytext ; + } + else + { + REJECT; + } + } +<FindMembers>[*&]+ { + yyextra->current->name += yytext ; + addType(yyscanner); + } <FindMembers,MemberSpec,Function,NextSemi,EnumBaseType,BitFields,ReadInitializer,ReadInitializerPtr,OldStyleArgs,DefinePHPEnd>";"{BN}*("/**"|"//!"|"/*!"|"///")"<" { - if (yyextra->current->bodyLine==-1) - { - yyextra->current->bodyLine=yyextra->yyLineNr; - yyextra->current->bodyColumn = yyextra->yyColNr; - } - yyextra->docBlockContext = YY_START; - yyextra->docBlockInBody = FALSE; - yyextra->docBlockAutoBrief = ( yytext[yyleng-2]=='*' && Config_getBool(JAVADOC_AUTOBRIEF) ) || - ( yytext[yyleng-2]=='!' && Config_getBool(QT_AUTOBRIEF) ); + if (yyextra->current->bodyLine==-1) + { + yyextra->current->bodyLine=yyextra->yyLineNr; + yyextra->current->bodyColumn = yyextra->yyColNr; + } + yyextra->docBlockContext = YY_START; + yyextra->docBlockInBody = FALSE; + yyextra->docBlockAutoBrief = ( yytext[yyleng-2]=='*' && Config_getBool(JAVADOC_AUTOBRIEF) ) || + ( yytext[yyleng-2]=='!' && Config_getBool(QT_AUTOBRIEF) ); QCString indent; indent.fill(' ',computeIndent(yytext,yyextra->column)); yyextra->docBlock=indent; //printf("indent=%d\n",computeIndent(yytext+1,yyextra->column)); - lineCount(yyscanner); + lineCount(yyscanner); - yyextra->docBlockTerm = ';'; + yyextra->docBlockTerm = ';'; if (YY_START==EnumBaseType && yyextra->current->section==Entry::ENUM_SEC) { yyextra->current->bitfields = ":"+yyextra->current->args; yyextra->current->args.resize(0); yyextra->current->section=Entry::VARIABLE_SEC; } - if (yytext[yyleng-3]=='/') - { - startCommentBlock(yyscanner,TRUE); - BEGIN( DocLine ); - } - else - { - startCommentBlock(yyscanner,FALSE); - BEGIN( DocBlock ); - } - } + if (yytext[yyleng-3]=='/') + { + startCommentBlock(yyscanner,TRUE); + BEGIN( DocLine ); + } + else + { + startCommentBlock(yyscanner,FALSE); + BEGIN( DocBlock ); + } + } <MemberSpec,FindFields,FindMembers,NextSemi,EnumBaseType,BitFields,ReadInitializer,ReadInitializerPtr,OldStyleArgs>","{BN}*("/**"|"//!"|"/*!"|"///")"<" { - yyextra->docBlockContext = YY_START; - yyextra->docBlockInBody = FALSE; - yyextra->docBlockAutoBrief = ( yytext[yyleng-2]=='*' && Config_getBool(JAVADOC_AUTOBRIEF) ) || - ( yytext[yyleng-2]=='!' && Config_getBool(QT_AUTOBRIEF) ); + yyextra->docBlockContext = YY_START; + yyextra->docBlockInBody = FALSE; + yyextra->docBlockAutoBrief = ( yytext[yyleng-2]=='*' && Config_getBool(JAVADOC_AUTOBRIEF) ) || + ( yytext[yyleng-2]=='!' && Config_getBool(QT_AUTOBRIEF) ); QCString indent; indent.fill(' ',computeIndent(yytext,yyextra->column)); yyextra->docBlock=indent; - lineCount(yyscanner); + lineCount(yyscanner); - yyextra->docBlockTerm = ','; + yyextra->docBlockTerm = ','; if (YY_START==EnumBaseType && yyextra->current->section==Entry::ENUM_SEC) { yyextra->current->bitfields = ":"+yyextra->current->args; yyextra->current->args.resize(0); yyextra->current->section=Entry::VARIABLE_SEC; } - if (yytext[yyleng-3]=='/') - { - startCommentBlock(yyscanner,TRUE); - BEGIN( DocLine ); - } - else - { - startCommentBlock(yyscanner,FALSE); - BEGIN( DocBlock ); - } - } + if (yytext[yyleng-3]=='/') + { + startCommentBlock(yyscanner,TRUE); + BEGIN( DocLine ); + } + else + { + startCommentBlock(yyscanner,FALSE); + BEGIN( DocBlock ); + } + } <DefineEnd,FindFields,FindFieldArg,ReadInitializer,ReadInitializerPtr,OldStyleArgs>{BN}*("/**"|"//!"|"/*!"|"///")"<" { - if (yyextra->current->bodyLine==-1) - { - yyextra->current->bodyLine=yyextra->yyLineNr; - yyextra->current->bodyColumn = yyextra->yyColNr; - } - yyextra->docBlockContext = YY_START; - yyextra->docBlockInBody = FALSE; - yyextra->docBlockAutoBrief = ( yytext[yyleng-2]=='*' && Config_getBool(JAVADOC_AUTOBRIEF) ) || - ( yytext[yyleng-2]=='!' && Config_getBool(QT_AUTOBRIEF) ); + if (yyextra->current->bodyLine==-1) + { + yyextra->current->bodyLine=yyextra->yyLineNr; + yyextra->current->bodyColumn = yyextra->yyColNr; + } + yyextra->docBlockContext = YY_START; + yyextra->docBlockInBody = FALSE; + yyextra->docBlockAutoBrief = ( yytext[yyleng-2]=='*' && Config_getBool(JAVADOC_AUTOBRIEF) ) || + ( yytext[yyleng-2]=='!' && Config_getBool(QT_AUTOBRIEF) ); QCString indent; indent.fill(' ',computeIndent(yytext,yyextra->column)); yyextra->docBlock=indent; - lineCount(yyscanner); - - yyextra->docBlockTerm = 0; - if (yytext[yyleng-3]=='/') - { - startCommentBlock(yyscanner,TRUE); - BEGIN( DocLine ); - } - else - { - startCommentBlock(yyscanner,FALSE); - BEGIN( DocBlock ); - } - } - -<FindMembers,FindFields>("//"([!/]){B}*{CMD}"{")|("/*"([!*]){B}*{CMD}"{") { - //handleGroupStartCommand(yyextra->current->name); + lineCount(yyscanner); + + yyextra->docBlockTerm = 0; + if (yytext[yyleng-3]=='/') + { + startCommentBlock(yyscanner,TRUE); + BEGIN( DocLine ); + } + else + { + startCommentBlock(yyscanner,FALSE); + BEGIN( DocBlock ); + } + } + +<FindMembers,FindFields>("//"([!/]){B}*{CMD}"{")|("/*"([!*]){B}*{CMD}"{") { + //handleGroupStartCommand(yyextra->current->name); if (yyextra->previous && yyextra->previous->section==Entry::GROUPDOC_SEC) - { - // link open command to the group defined in the yyextra->previous entry - yyextra->commentScanner.open(yyextra->previous.get(),yyextra->yyFileName,yyextra->yyLineNr); - } - else - { - // link open command to the yyextra->current entry - yyextra->commentScanner.open(yyextra->current.get(),yyextra->yyFileName,yyextra->yyLineNr); - } - //yyextra->current = tmp; - initEntry(yyscanner); - if (yytext[1]=='/') - { - if (yytext[2]=='!' || yytext[2]=='/') - { - yyextra->docBlockContext = YY_START; - yyextra->docBlockInBody = FALSE; - yyextra->docBlockAutoBrief = FALSE; - yyextra->docBlock.resize(0); - yyextra->docBlockTerm = 0; - startCommentBlock(yyscanner,TRUE); - BEGIN(DocLine); - } - else - { - yyextra->lastCContext=YY_START; - BEGIN(SkipCxxComment); - } - } - else - { - if (yytext[2]=='!' || yytext[2]=='*') - { - yyextra->docBlockContext = YY_START; - yyextra->docBlockInBody = FALSE; - yyextra->docBlock.resize(0); - yyextra->docBlockAutoBrief = ( yytext[yyleng-2]=='*' && Config_getBool(JAVADOC_AUTOBRIEF) ) || - ( yytext[yyleng-2]=='!' && Config_getBool(QT_AUTOBRIEF) ); - yyextra->docBlockTerm = 0; - startCommentBlock(yyscanner,FALSE); - BEGIN(DocBlock); - } - else - { - yyextra->lastCContext=YY_START; - BEGIN(SkipComment); - } - } - } + { + // link open command to the group defined in the yyextra->previous entry + yyextra->commentScanner.open(yyextra->previous.get(),yyextra->yyFileName,yyextra->yyLineNr); + } + else + { + // link open command to the yyextra->current entry + yyextra->commentScanner.open(yyextra->current.get(),yyextra->yyFileName,yyextra->yyLineNr); + } + //yyextra->current = tmp; + initEntry(yyscanner); + if (yytext[1]=='/') + { + if (yytext[2]=='!' || yytext[2]=='/') + { + yyextra->docBlockContext = YY_START; + yyextra->docBlockInBody = FALSE; + yyextra->docBlockAutoBrief = FALSE; + yyextra->docBlock.resize(0); + yyextra->docBlockTerm = 0; + startCommentBlock(yyscanner,TRUE); + BEGIN(DocLine); + } + else + { + yyextra->lastCContext=YY_START; + BEGIN(SkipCxxComment); + } + } + else + { + if (yytext[2]=='!' || yytext[2]=='*') + { + yyextra->docBlockContext = YY_START; + yyextra->docBlockInBody = FALSE; + yyextra->docBlock.resize(0); + yyextra->docBlockAutoBrief = ( yytext[yyleng-2]=='*' && Config_getBool(JAVADOC_AUTOBRIEF) ) || + ( yytext[yyleng-2]=='!' && Config_getBool(QT_AUTOBRIEF) ); + yyextra->docBlockTerm = 0; + startCommentBlock(yyscanner,FALSE); + BEGIN(DocBlock); + } + else + { + yyextra->lastCContext=YY_START; + BEGIN(SkipComment); + } + } + } <FindMembers,FindFields,ReadInitializer,ReadInitializerPtr>"//"([!/]){B}*{CMD}"}".*|"/*"([!*]){B}*{CMD}"}"[^*]*"*/" { bool insideEnum = YY_START==FindFields || ((YY_START==ReadInitializer || YY_START==ReadInitializerPtr) && yyextra->lastInitializerContext==FindFields); // see bug746226 - yyextra->commentScanner.close(yyextra->current.get(),yyextra->yyFileName,yyextra->yyLineNr,insideEnum); - lineCount(yyscanner); - } + yyextra->commentScanner.close(yyextra->current.get(),yyextra->yyFileName,yyextra->yyLineNr,insideEnum); + lineCount(yyscanner); + } <FindMembers>"=>" { if (!yyextra->insideCS) REJECT; yyextra->current->bodyLine = yyextra->yyLineNr; @@ -2597,80 +2597,80 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) yyextra->current->spec |= Entry::Gettable; BEGIN(ReadInitializerPtr); } -<FindMembers>"=" { // in PHP code this could also be due to "<?=" - yyextra->current->bodyLine = yyextra->yyLineNr; - yyextra->current->bodyColumn = yyextra->yyColNr; +<FindMembers>"=" { // in PHP code this could also be due to "<?=" + yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->current->bodyColumn = yyextra->yyColNr; yyextra->current->initializer = yytext; - yyextra->lastInitializerContext = YY_START; - yyextra->initBracketCount=0; - BEGIN(ReadInitializer); - } -<UNOIDLAttributeBlock>{BN}*[gs]"et"{BN}+"raises"{BN}*"("{BN}*{SCOPENAME}{BN}*(","{BN}*{SCOPENAME}{BN}*)*")"{BN}*";" { - lineCount(yyscanner); - yyextra->current->exception += " "; - yyextra->current->exception += removeRedundantWhiteSpace(yytext); - } -<UNOIDLAttributeBlock>"}" { - yyextra->current->exception += " }"; - BEGIN(FindMembers); - } + yyextra->lastInitializerContext = YY_START; + yyextra->initBracketCount=0; + BEGIN(ReadInitializer); + } +<UNOIDLAttributeBlock>{BN}*[gs]"et"{BN}+"raises"{BN}*"("{BN}*{SCOPENAME}{BN}*(","{BN}*{SCOPENAME}{BN}*)*")"{BN}*";" { + lineCount(yyscanner); + yyextra->current->exception += " "; + yyextra->current->exception += removeRedundantWhiteSpace(yytext); + } +<UNOIDLAttributeBlock>"}" { + yyextra->current->exception += " }"; + BEGIN(FindMembers); + } /* Read initializer rules */ <ReadInitializer,ReadInitializerPtr>"(" { - yyextra->lastRoundContext=YY_START; - yyextra->pCopyRoundGString=&yyextra->current->initializer; - yyextra->roundCount=0; - yyextra->current->initializer+=*yytext; - BEGIN(GCopyRound); - } + yyextra->lastRoundContext=YY_START; + yyextra->pCopyRoundGString=&yyextra->current->initializer; + yyextra->roundCount=0; + yyextra->current->initializer+=*yytext; + BEGIN(GCopyRound); + } <ReadInitializer,ReadInitializerPtr>"[" { if (!yyextra->insidePHP) REJECT; yyextra->lastSquareContext=YY_START; yyextra->pCopySquareGString=&yyextra->current->initializer; yyextra->squareCount=0; - yyextra->current->initializer+=*yytext; + yyextra->current->initializer+=*yytext; BEGIN(GCopySquare); } <ReadInitializer,ReadInitializerPtr>"{" { - yyextra->lastCurlyContext=YY_START; - yyextra->pCopyCurlyGString=&yyextra->current->initializer; - yyextra->curlyCount=0; - yyextra->current->initializer+=*yytext; - BEGIN(GCopyCurly); - } + yyextra->lastCurlyContext=YY_START; + yyextra->pCopyCurlyGString=&yyextra->current->initializer; + yyextra->curlyCount=0; + yyextra->current->initializer+=*yytext; + BEGIN(GCopyCurly); + } <ReadInitializer,ReadInitializerPtr>[;,] { - //printf(">> initializer '%s' <<\n",yyextra->current->initializer.data()); + //printf(">> initializer '%s' <<\n",yyextra->current->initializer.data()); if (*yytext==';' && (yyextra->current_root->spec&Entry::Enum)) - { - yyextra->current->fileName = yyextra->yyFileName; - yyextra->current->startLine = yyextra->yyLineNr; - yyextra->current->startColumn = yyextra->yyColNr; - yyextra->current->args = yyextra->current->args.simplifyWhiteSpace(); - yyextra->current->name = yyextra->current->name.stripWhiteSpace(); - yyextra->current->section = Entry::VARIABLE_SEC; - yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current); - initEntry(yyscanner); - BEGIN(FindMembers); - } - else if (*yytext==';' || (yyextra->lastInitializerContext==FindFields && yyextra->initBracketCount==0)) // yyextra->initBracketCount==0 was added for bug 665778 - { - unput(*yytext); + { + yyextra->current->fileName = yyextra->yyFileName; + yyextra->current->startLine = yyextra->yyLineNr; + yyextra->current->startColumn = yyextra->yyColNr; + yyextra->current->args = yyextra->current->args.simplifyWhiteSpace(); + yyextra->current->name = yyextra->current->name.stripWhiteSpace(); + yyextra->current->section = Entry::VARIABLE_SEC; + yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current); + initEntry(yyscanner); + BEGIN(FindMembers); + } + else if (*yytext==';' || (yyextra->lastInitializerContext==FindFields && yyextra->initBracketCount==0)) // yyextra->initBracketCount==0 was added for bug 665778 + { + unput(*yytext); if (YY_START == ReadInitializerPtr) yyextra->current->initializer.resize(0); - BEGIN(yyextra->lastInitializerContext); - } - else if (*yytext==',' && yyextra->initBracketCount==0) // for "int a=0,b=0" - { - unput(*yytext); + BEGIN(yyextra->lastInitializerContext); + } + else if (*yytext==',' && yyextra->initBracketCount==0) // for "int a=0,b=0" + { + unput(*yytext); if (YY_START == ReadInitializerPtr) yyextra->current->initializer.resize(0); - BEGIN(yyextra->lastInitializerContext); - } - else - { - yyextra->current->initializer+=*yytext; - } - } + BEGIN(yyextra->lastInitializerContext); + } + else + { + yyextra->current->initializer+=*yytext; + } + } <ReadInitializer,ReadInitializerPtr>{RAWBEGIN} { // C++11 raw string if (!yyextra->insideCpp) - { + { REJECT; } else @@ -2707,7 +2707,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) } <RawString>{RAWEND} { *yyextra->pCopyRawString+=yytext; - yyextra->fullArgString+=yytext; + yyextra->fullArgString+=yytext; QCString delimiter = yytext+1; delimiter=delimiter.left(delimiter.length()-1); if (delimiter==yyextra->delimiter) @@ -2717,265 +2717,265 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) } <RawString>[^)]+ { *yyextra->pCopyRawString+=yytext; - yyextra->fullArgString+=yytext; + yyextra->fullArgString+=yytext; } <RawString>. { *yyextra->pCopyRawString+=yytext; - yyextra->fullArgString+=yytext; + yyextra->fullArgString+=yytext; } <RawString>\n { *yyextra->pCopyRawString+=yytext; - yyextra->fullArgString+=yytext; + yyextra->fullArgString+=yytext; lineCount(yyscanner); } <ReadInitializer,ReadInitializerPtr>\" { - if (yyextra->insideIDL && yyextra->insideCppQuote) - { - BEGIN(EndCppQuote); - } - else - { + if (yyextra->insideIDL && yyextra->insideCppQuote) + { + BEGIN(EndCppQuote); + } + else + { yyextra->lastStringContext=YY_START; - yyextra->current->initializer+=yytext; - yyextra->pCopyQuotedGString=&yyextra->current->initializer; - BEGIN(CopyGString); - } - } + yyextra->current->initializer+=yytext; + yyextra->pCopyQuotedGString=&yyextra->current->initializer; + BEGIN(CopyGString); + } + } <ReadInitializer,ReadInitializerPtr>"->" { - yyextra->current->initializer+=yytext; - } + yyextra->current->initializer+=yytext; + } <ReadInitializer,ReadInitializerPtr>"<<" { - yyextra->current->initializer+=yytext; - } + yyextra->current->initializer+=yytext; + } <ReadInitializer,ReadInitializerPtr>">>" { - yyextra->current->initializer+=yytext; - } + yyextra->current->initializer+=yytext; + } <ReadInitializer,ReadInitializerPtr>[<\[{(] { - yyextra->initBracketCount++; - yyextra->current->initializer+=*yytext; - } + yyextra->initBracketCount++; + yyextra->current->initializer+=*yytext; + } <ReadInitializer,ReadInitializerPtr>[>\]})] { - yyextra->initBracketCount--; - yyextra->current->initializer+=*yytext; - } + yyextra->initBracketCount--; + yyextra->current->initializer+=*yytext; + } <ReadInitializer,ReadInitializerPtr>\' { - if (yyextra->insidePHP) - { - yyextra->current->initializer+=yytext; + if (yyextra->insidePHP) + { + yyextra->current->initializer+=yytext; yyextra->pCopyQuotedGString = &yyextra->current->initializer; yyextra->lastStringContext=YY_START; - BEGIN(CopyPHPGString); - } - else - { - yyextra->current->initializer+=yytext; - } - } + BEGIN(CopyPHPGString); + } + else + { + yyextra->current->initializer+=yytext; + } + } <ReadInitializer,ReadInitializerPtr>{CHARLIT} { - if (yyextra->insidePHP) - { - REJECT; - } - else - { - yyextra->current->initializer+=yytext; - } - } + if (yyextra->insidePHP) + { + REJECT; + } + else + { + yyextra->current->initializer+=yytext; + } + } <ReadInitializer,ReadInitializerPtr>\n { - yyextra->current->initializer+=*yytext; + yyextra->current->initializer+=*yytext; lineCount(yyscanner); - } + } <ReadInitializer,ReadInitializerPtr>"@\"" { - //printf("yyextra->insideCS=%d\n",yyextra->insideCS); - yyextra->current->initializer+=yytext; - if (!yyextra->insideCS && !yyextra->insideObjC) - { - REJECT; - } - else - { - // C#/ObjC verbatim string - yyextra->lastSkipVerbStringContext=YY_START; - yyextra->pSkipVerbString=&yyextra->current->initializer; - BEGIN(SkipVerbString); - } - } -<SkipVerbString>[^\n"]+ { - *yyextra->pSkipVerbString+=yytext; - } -<SkipVerbString>"\"\"" { // quote escape - *yyextra->pSkipVerbString+=yytext; - } -<SkipVerbString>"\"" { - *yyextra->pSkipVerbString+=*yytext; - BEGIN(yyextra->lastSkipVerbStringContext); - } -<SkipVerbString>\n { - *yyextra->pSkipVerbString+=*yytext; + //printf("yyextra->insideCS=%d\n",yyextra->insideCS); + yyextra->current->initializer+=yytext; + if (!yyextra->insideCS && !yyextra->insideObjC) + { + REJECT; + } + else + { + // C#/ObjC verbatim string + yyextra->lastSkipVerbStringContext=YY_START; + yyextra->pSkipVerbString=&yyextra->current->initializer; + BEGIN(SkipVerbString); + } + } +<SkipVerbString>[^\n"]+ { + *yyextra->pSkipVerbString+=yytext; + } +<SkipVerbString>"\"\"" { // quote escape + *yyextra->pSkipVerbString+=yytext; + } +<SkipVerbString>"\"" { + *yyextra->pSkipVerbString+=*yytext; + BEGIN(yyextra->lastSkipVerbStringContext); + } +<SkipVerbString>\n { + *yyextra->pSkipVerbString+=*yytext; lineCount(yyscanner); - } -<SkipVerbString>. { - *yyextra->pSkipVerbString+=*yytext; - } + } +<SkipVerbString>. { + *yyextra->pSkipVerbString+=*yytext; + } <ReadInitializer,ReadInitializerPtr>"?>" { - if (yyextra->insidePHP) - BEGIN( FindMembersPHP ); - else - yyextra->current->initializer+=yytext; - } + if (yyextra->insidePHP) + BEGIN( FindMembersPHP ); + else + yyextra->current->initializer+=yytext; + } <ReadInitializer,ReadInitializerPtr>. { - yyextra->current->initializer+=*yytext; - } + yyextra->current->initializer+=*yytext; + } /* generic quoted string copy rules */ -<CopyString,CopyPHPString>\\. { - *yyextra->pCopyQuotedString+=yytext; - } -<CopyString>\" { - *yyextra->pCopyQuotedString+=*yytext; - BEGIN( yyextra->lastStringContext ); - } -<CopyPHPString>\' { - *yyextra->pCopyQuotedString+=*yytext; - BEGIN( yyextra->lastStringContext ); - } +<CopyString,CopyPHPString>\\. { + *yyextra->pCopyQuotedString+=yytext; + } +<CopyString>\" { + *yyextra->pCopyQuotedString+=*yytext; + BEGIN( yyextra->lastStringContext ); + } +<CopyPHPString>\' { + *yyextra->pCopyQuotedString+=*yytext; + BEGIN( yyextra->lastStringContext ); + } <CopyString,CopyPHPString>"/*"|"*/"|"//" { - *yyextra->pCopyQuotedString+=yytext; - } -<CopyString,CopyPHPString>\n { - *yyextra->pCopyQuotedString+=*yytext; + *yyextra->pCopyQuotedString+=yytext; + } +<CopyString,CopyPHPString>\n { + *yyextra->pCopyQuotedString+=*yytext; lineCount(yyscanner); - } -<CopyString,CopyPHPString>. { - *yyextra->pCopyQuotedString+=*yytext; - } + } +<CopyString,CopyPHPString>. { + *yyextra->pCopyQuotedString+=*yytext; + } /* generic quoted growable string copy rules */ -<CopyGString,CopyPHPGString>\\. { - *yyextra->pCopyQuotedGString+=yytext; - } -<CopyGString>\" { - *yyextra->pCopyQuotedGString+=*yytext; - BEGIN( yyextra->lastStringContext ); - } -<CopyPHPGString>\' { - *yyextra->pCopyQuotedGString+=*yytext; - BEGIN( yyextra->lastStringContext ); - } -<CopyGString,CopyPHPGString>"<?php" { // we had an odd number of quotes. - *yyextra->pCopyQuotedGString += yytext; - BEGIN( yyextra->lastStringContext ); - } +<CopyGString,CopyPHPGString>\\. { + *yyextra->pCopyQuotedGString+=yytext; + } +<CopyGString>\" { + *yyextra->pCopyQuotedGString+=*yytext; + BEGIN( yyextra->lastStringContext ); + } +<CopyPHPGString>\' { + *yyextra->pCopyQuotedGString+=*yytext; + BEGIN( yyextra->lastStringContext ); + } +<CopyGString,CopyPHPGString>"<?php" { // we had an odd number of quotes. + *yyextra->pCopyQuotedGString += yytext; + BEGIN( yyextra->lastStringContext ); + } <CopyGString,CopyPHPGString>"/*"|"*/"|"//" { - *yyextra->pCopyQuotedGString+=yytext; - } -<CopyGString,CopyPHPGString>\n { - *yyextra->pCopyQuotedGString+=*yytext; + *yyextra->pCopyQuotedGString+=yytext; + } +<CopyGString,CopyPHPGString>\n { + *yyextra->pCopyQuotedGString+=*yytext; lineCount(yyscanner); - } -<CopyGString,CopyPHPGString>. { - *yyextra->pCopyQuotedGString+=*yytext; - } + } +<CopyGString,CopyPHPGString>. { + *yyextra->pCopyQuotedGString+=*yytext; + } /* generic round bracket list copy rules */ -<CopyRound>\" { - *yyextra->pCopyRoundString+=*yytext; - yyextra->pCopyQuotedString=yyextra->pCopyRoundString; - yyextra->lastStringContext=YY_START; - BEGIN(CopyString); - } -<CopyRound>"(" { - *yyextra->pCopyRoundString+=*yytext; - yyextra->roundCount++; - } -<CopyRound>")" { - *yyextra->pCopyRoundString+=*yytext; - if (--yyextra->roundCount<0) - BEGIN(yyextra->lastRoundContext); - } -<CopyRound>\n { +<CopyRound>\" { + *yyextra->pCopyRoundString+=*yytext; + yyextra->pCopyQuotedString=yyextra->pCopyRoundString; + yyextra->lastStringContext=YY_START; + BEGIN(CopyString); + } +<CopyRound>"(" { + *yyextra->pCopyRoundString+=*yytext; + yyextra->roundCount++; + } +<CopyRound>")" { + *yyextra->pCopyRoundString+=*yytext; + if (--yyextra->roundCount<0) + BEGIN(yyextra->lastRoundContext); + } +<CopyRound>\n { lineCount(yyscanner); - *yyextra->pCopyRoundString+=*yytext; - } -<CopyRound>\' { - if (yyextra->insidePHP) - { - yyextra->current->initializer+=yytext; + *yyextra->pCopyRoundString+=*yytext; + } +<CopyRound>\' { + if (yyextra->insidePHP) + { + yyextra->current->initializer+=yytext; yyextra->pCopyQuotedString = yyextra->pCopyRoundString; yyextra->lastStringContext=YY_START; - BEGIN(CopyPHPString); - } - else - { - *yyextra->pCopyRoundString+=yytext; - } - } -<CopyRound>{CHARLIT} { + BEGIN(CopyPHPString); + } + else + { + *yyextra->pCopyRoundString+=yytext; + } + } +<CopyRound>{CHARLIT} { if (yyextra->insidePHP) - { - REJECT; - } - else - { - *yyextra->pCopyRoundString+=yytext; - } - } -<CopyRound>[^"'()\n,]+ { - *yyextra->pCopyRoundString+=yytext; - } -<CopyRound>. { - *yyextra->pCopyRoundString+=*yytext; - } + { + REJECT; + } + else + { + *yyextra->pCopyRoundString+=yytext; + } + } +<CopyRound>[^"'()\n,]+ { + *yyextra->pCopyRoundString+=yytext; + } +<CopyRound>. { + *yyextra->pCopyRoundString+=*yytext; + } /* generic round bracket list copy rules for growable strings */ -<GCopyRound>\" { - *yyextra->pCopyRoundGString+=*yytext; - yyextra->pCopyQuotedGString=yyextra->pCopyRoundGString; - yyextra->lastStringContext=YY_START; - BEGIN(CopyGString); - } -<GCopyRound>"(" { - *yyextra->pCopyRoundGString+=*yytext; - yyextra->roundCount++; - } -<GCopyRound>")" { - *yyextra->pCopyRoundGString+=*yytext; - if (--yyextra->roundCount<0) - BEGIN(yyextra->lastRoundContext); - } -<GCopyRound>\n { +<GCopyRound>\" { + *yyextra->pCopyRoundGString+=*yytext; + yyextra->pCopyQuotedGString=yyextra->pCopyRoundGString; + yyextra->lastStringContext=YY_START; + BEGIN(CopyGString); + } +<GCopyRound>"(" { + *yyextra->pCopyRoundGString+=*yytext; + yyextra->roundCount++; + } +<GCopyRound>")" { + *yyextra->pCopyRoundGString+=*yytext; + if (--yyextra->roundCount<0) + BEGIN(yyextra->lastRoundContext); + } +<GCopyRound>\n { lineCount(yyscanner); - *yyextra->pCopyRoundGString+=*yytext; - } -<GCopyRound>\' { - if (yyextra->insidePHP) - { - yyextra->current->initializer+=yytext; + *yyextra->pCopyRoundGString+=*yytext; + } +<GCopyRound>\' { + if (yyextra->insidePHP) + { + yyextra->current->initializer+=yytext; yyextra->pCopyQuotedGString = yyextra->pCopyRoundGString; yyextra->lastStringContext=YY_START; - BEGIN(CopyPHPGString); - } - else - { - *yyextra->pCopyRoundGString+=yytext; - } - } -<GCopyRound>{CHARLIT} { + BEGIN(CopyPHPGString); + } + else + { + *yyextra->pCopyRoundGString+=yytext; + } + } +<GCopyRound>{CHARLIT} { if (yyextra->insidePHP) - { - REJECT; - } - else - { - *yyextra->pCopyRoundGString+=yytext; - } - } -<GCopyRound>[^"'()\n\/,]+ { - *yyextra->pCopyRoundGString+=yytext; - } -<GCopyRound>. { - *yyextra->pCopyRoundGString+=*yytext; - } + { + REJECT; + } + else + { + *yyextra->pCopyRoundGString+=yytext; + } + } +<GCopyRound>[^"'()\n\/,]+ { + *yyextra->pCopyRoundGString+=yytext; + } +<GCopyRound>. { + *yyextra->pCopyRoundGString+=*yytext; + } /* generic square bracket list copy rules for growable strings, we should only enter here in case of php, left the test part as in GCopyRound to keep it compatible with the round bracket version */ <GCopySquare>\" { @@ -3000,7 +3000,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) <GCopySquare>\' { if (yyextra->insidePHP) { - yyextra->current->initializer+=yytext; + yyextra->current->initializer+=yytext; yyextra->pCopyQuotedGString = yyextra->pCopySquareGString; yyextra->lastStringContext=YY_START; BEGIN(CopyPHPGString); @@ -3010,14 +3010,14 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) *yyextra->pCopySquareGString+=yytext; } } -<GCopySquare>{CHARLIT} { +<GCopySquare>{CHARLIT} { if (yyextra->insidePHP) { REJECT; } else { - *yyextra->pCopySquareGString+=yytext; + *yyextra->pCopySquareGString+=yytext; } } <GCopySquare>[^"\[\]\n\/,]+ { @@ -3028,230 +3028,230 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) } /* generic curly bracket list copy rules */ -<CopyCurly>\" { - *yyextra->pCopyCurlyString+=*yytext; - yyextra->pCopyQuotedString=yyextra->pCopyCurlyString; - yyextra->lastStringContext=YY_START; - BEGIN(CopyString); - } -<CopyCurly>\' { - *yyextra->pCopyCurlyString+=*yytext; - if (yyextra->insidePHP) - { - yyextra->pCopyQuotedString=yyextra->pCopyCurlyString; - yyextra->lastStringContext=YY_START; - BEGIN(CopyPHPString); - } - } -<CopyCurly>"{" { - *yyextra->pCopyCurlyString+=*yytext; - yyextra->curlyCount++; - } -<CopyCurly>"}" { - *yyextra->pCopyCurlyString+=*yytext; - if (--yyextra->curlyCount<0) - BEGIN(yyextra->lastCurlyContext); - } -<CopyCurly>{CHARLIT} { if (yyextra->insidePHP) - { - REJECT; - } - else - { - *yyextra->pCopyCurlyString+=yytext; - } - } -<CopyCurly>[^"'{}\/\n,]+ { - *yyextra->pCopyCurlyString+=yytext; - } -<CopyCurly>"/" { *yyextra->pCopyCurlyString+=yytext; } -<CopyCurly>\n { +<CopyCurly>\" { + *yyextra->pCopyCurlyString+=*yytext; + yyextra->pCopyQuotedString=yyextra->pCopyCurlyString; + yyextra->lastStringContext=YY_START; + BEGIN(CopyString); + } +<CopyCurly>\' { + *yyextra->pCopyCurlyString+=*yytext; + if (yyextra->insidePHP) + { + yyextra->pCopyQuotedString=yyextra->pCopyCurlyString; + yyextra->lastStringContext=YY_START; + BEGIN(CopyPHPString); + } + } +<CopyCurly>"{" { + *yyextra->pCopyCurlyString+=*yytext; + yyextra->curlyCount++; + } +<CopyCurly>"}" { + *yyextra->pCopyCurlyString+=*yytext; + if (--yyextra->curlyCount<0) + BEGIN(yyextra->lastCurlyContext); + } +<CopyCurly>{CHARLIT} { if (yyextra->insidePHP) + { + REJECT; + } + else + { + *yyextra->pCopyCurlyString+=yytext; + } + } +<CopyCurly>[^"'{}\/\n,]+ { + *yyextra->pCopyCurlyString+=yytext; + } +<CopyCurly>"/" { *yyextra->pCopyCurlyString+=yytext; } +<CopyCurly>\n { lineCount(yyscanner); - *yyextra->pCopyCurlyString+=*yytext; - } -<CopyCurly>. { - *yyextra->pCopyCurlyString+=*yytext; - } + *yyextra->pCopyCurlyString+=*yytext; + } +<CopyCurly>. { + *yyextra->pCopyCurlyString+=*yytext; + } /* generic curly bracket list copy rules for growable strings */ <GCopyCurly>^"#"{B}+[0-9]+{B}+"\""[^\"\n]+"\""{B}+"1"{B}*\n? { // start of included file marker } <GCopyCurly>^"#"{B}+[0-9]+{B}+"\""[^\"\n]+"\""{B}+"2"{B}*\n? { // end of included file marker - QCString line = QCString(yytext); - int s = line.find(' '); - int e = line.find('"',s); - yyextra->yyLineNr = line.mid(s,e-s).toInt(); - if (yytext[yyleng-1]=='\n') - { + QCString line = QCString(yytext); + int s = line.find(' '); + int e = line.find('"',s); + yyextra->yyLineNr = line.mid(s,e-s).toInt(); + if (yytext[yyleng-1]=='\n') + { lineCount(yyscanner); yyextra->column=0; - } - } -<GCopyCurly>\" { - *yyextra->pCopyCurlyGString+=*yytext; - yyextra->pCopyQuotedGString=yyextra->pCopyCurlyGString; - yyextra->lastStringContext=YY_START; - BEGIN(CopyGString); - } -<GCopyCurly>\' { - *yyextra->pCopyCurlyGString+=*yytext; - if (yyextra->insidePHP) - { - yyextra->pCopyQuotedGString=yyextra->pCopyCurlyGString; - yyextra->lastStringContext=YY_START; - BEGIN(CopyPHPGString); - } - } -<GCopyCurly>"{" { - *yyextra->pCopyCurlyGString+=*yytext; - yyextra->curlyCount++; - } -<GCopyCurly>"}" { - *yyextra->pCopyCurlyGString+=*yytext; - if (--yyextra->curlyCount<0) - BEGIN(yyextra->lastCurlyContext); - } -<GCopyCurly>{CHARLIT} { if (yyextra->insidePHP) - { - REJECT; - } - else - { - *yyextra->pCopyCurlyGString+=yytext; - } - } -<GCopyCurly>[^"'{}\/\n,]+ { - *yyextra->pCopyCurlyGString+=yytext; - } -<GCopyCurly>[,]+ { - *yyextra->pCopyCurlyGString+=yytext; - } -<GCopyCurly>"/" { *yyextra->pCopyCurlyGString+=yytext; } -<GCopyCurly>\n { + } + } +<GCopyCurly>\" { + *yyextra->pCopyCurlyGString+=*yytext; + yyextra->pCopyQuotedGString=yyextra->pCopyCurlyGString; + yyextra->lastStringContext=YY_START; + BEGIN(CopyGString); + } +<GCopyCurly>\' { + *yyextra->pCopyCurlyGString+=*yytext; + if (yyextra->insidePHP) + { + yyextra->pCopyQuotedGString=yyextra->pCopyCurlyGString; + yyextra->lastStringContext=YY_START; + BEGIN(CopyPHPGString); + } + } +<GCopyCurly>"{" { + *yyextra->pCopyCurlyGString+=*yytext; + yyextra->curlyCount++; + } +<GCopyCurly>"}" { + *yyextra->pCopyCurlyGString+=*yytext; + if (--yyextra->curlyCount<0) + BEGIN(yyextra->lastCurlyContext); + } +<GCopyCurly>{CHARLIT} { if (yyextra->insidePHP) + { + REJECT; + } + else + { + *yyextra->pCopyCurlyGString+=yytext; + } + } +<GCopyCurly>[^"'{}\/\n,]+ { + *yyextra->pCopyCurlyGString+=yytext; + } +<GCopyCurly>[,]+ { + *yyextra->pCopyCurlyGString+=yytext; + } +<GCopyCurly>"/" { *yyextra->pCopyCurlyGString+=yytext; } +<GCopyCurly>\n { lineCount(yyscanner); - *yyextra->pCopyCurlyGString+=*yytext; - } -<GCopyCurly>. { - *yyextra->pCopyCurlyGString+=*yytext; - } + *yyextra->pCopyCurlyGString+=*yytext; + } +<GCopyCurly>. { + *yyextra->pCopyCurlyGString+=*yytext; + } /* ---------------------- */ -<FindMembers>":" { - if (yyextra->current->type.isEmpty() && +<FindMembers>":" { + if (yyextra->current->type.isEmpty() && yyextra->current->name=="enum") // see bug 69041, C++11 style anon enum: 'enum : unsigned int {...}' - { + { yyextra->current->section=Entry::ENUM_SEC; - yyextra->current->name.resize(0); + yyextra->current->name.resize(0); yyextra->current->args.resize(0); - BEGIN(EnumBaseType); - } - else + BEGIN(EnumBaseType); + } + else { if (yyextra->current->type.isEmpty()) // anonymous padding field, e.g. "int :7;" - { - addType(yyscanner); - yyextra->current->name.sprintf("__pad%d__",yyextra->padCount++); - } - BEGIN(BitFields); - yyextra->current->bitfields+=":"; - } - } -<BitFields>. { - yyextra->current->bitfields+=*yytext; - } -<EnumBaseType>. { - yyextra->current->args+=*yytext; - } -<EnumBaseType>\n { + { + addType(yyscanner); + yyextra->current->name.sprintf("__pad%d__",yyextra->padCount++); + } + BEGIN(BitFields); + yyextra->current->bitfields+=":"; + } + } +<BitFields>. { + yyextra->current->bitfields+=*yytext; + } +<EnumBaseType>. { + yyextra->current->args+=*yytext; + } +<EnumBaseType>\n { lineCount(yyscanner); - yyextra->current->args+=' '; - } -<FindMembers>[;,] { - QCString oldType = yyextra->current->type; - if (yyextra->current->bodyLine==-1) - { - yyextra->current->bodyLine = yyextra->yyLineNr; - yyextra->current->bodyColumn = yyextra->yyColNr; - } + yyextra->current->args+=' '; + } +<FindMembers>[;,] { + QCString oldType = yyextra->current->type; + if (yyextra->current->bodyLine==-1) + { + yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->current->bodyColumn = yyextra->yyColNr; + } if ( yyextra->insidePHP && yyextra->current->type.left(3) == "var" ) { yyextra->current->type = yyextra->current->type.mid(3); } - if (yyextra->isTypedef && yyextra->current->type.left(8)!="typedef ") - { - yyextra->current->type.prepend("typedef "); - } - bool stat = yyextra->current->stat; - if (!yyextra->current->name.isEmpty() && yyextra->current->section!=Entry::ENUM_SEC) - { - yyextra->current->type=yyextra->current->type.simplifyWhiteSpace(); - yyextra->current->args=removeRedundantWhiteSpace(yyextra->current->args); - yyextra->current->name=yyextra->current->name.stripWhiteSpace(); - if (yyextra->current->section==Entry::CLASS_SEC) // remove spec for "struct Bla bla;" - { - yyextra->current->spec = 0; - } - yyextra->current->section = Entry::VARIABLE_SEC ; - yyextra->current->fileName = yyextra->yyFileName; - yyextra->current->startLine = yyextra->yyBegLineNr; - yyextra->current->startColumn = yyextra->yyBegColNr; - yyextra->current_root->moveToSubEntryAndRefresh( yyextra->current ) ; + if (yyextra->isTypedef && yyextra->current->type.left(8)!="typedef ") + { + yyextra->current->type.prepend("typedef "); + } + bool stat = yyextra->current->stat; + if (!yyextra->current->name.isEmpty() && yyextra->current->section!=Entry::ENUM_SEC) + { + yyextra->current->type=yyextra->current->type.simplifyWhiteSpace(); + yyextra->current->args=removeRedundantWhiteSpace(yyextra->current->args); + yyextra->current->name=yyextra->current->name.stripWhiteSpace(); + if (yyextra->current->section==Entry::CLASS_SEC) // remove spec for "struct Bla bla;" + { + yyextra->current->spec = 0; + } + yyextra->current->section = Entry::VARIABLE_SEC ; + yyextra->current->fileName = yyextra->yyFileName; + yyextra->current->startLine = yyextra->yyBegLineNr; + yyextra->current->startColumn = yyextra->yyBegColNr; + yyextra->current_root->moveToSubEntryAndRefresh( yyextra->current ) ; initEntry(yyscanner); - } - if ( *yytext == ',') - { - yyextra->current->stat = stat; // the static attribute holds for all variables - yyextra->current->name.resize(0); - yyextra->current->args.resize(0); - yyextra->current->brief.resize(0); - yyextra->current->doc.resize(0); - yyextra->current->initializer.resize(0); - yyextra->current->bitfields.resize(0); - int i=oldType.length(); - while (i>0 && (oldType[i-1]=='*' || oldType[i-1]=='&' || oldType[i-1]==' ')) i--; - yyextra->current->type = oldType.left(i); - } - else - { + } + if ( *yytext == ',') + { + yyextra->current->stat = stat; // the static attribute holds for all variables + yyextra->current->name.resize(0); + yyextra->current->args.resize(0); + yyextra->current->brief.resize(0); + yyextra->current->doc.resize(0); + yyextra->current->initializer.resize(0); + yyextra->current->bitfields.resize(0); + int i=oldType.length(); + while (i>0 && (oldType[i-1]=='*' || oldType[i-1]=='&' || oldType[i-1]==' ')) i--; + yyextra->current->type = oldType.left(i); + } + else + { yyextra->mtype = Method; yyextra->virt = Normal; - yyextra->current->groups.clear(); - initEntry(yyscanner); - } - } + yyextra->current->groups.clear(); + initEntry(yyscanner); + } + } -<FindMembers>"[" { +<FindMembers>"[" { if (yyextra->insideSlice) { - yyextra->squareCount=1; + yyextra->squareCount=1; yyextra->lastSquareContext = YY_START; yyextra->current->metaData += "["; BEGIN( SliceMetadata ); } - else if (!yyextra->insideCS && - (yyextra->current->name.isEmpty() || - yyextra->current->name=="typedef" - ) - ) // IDL function property - { - yyextra->squareCount=1; - yyextra->lastSquareContext = YY_START; - yyextra->idlAttr.resize(0); - yyextra->idlProp.resize(0); - yyextra->current->mtype = yyextra->mtype; - - if (Config_getBool(IDL_PROPERTY_SUPPORT) && - yyextra->current->mtype == Property) - { // we are yyextra->inside the properties section of a dispinterface - yyextra->odlProp = true; - yyextra->current->spec |= Entry::Gettable; - yyextra->current->spec |= Entry::Settable; - } - - BEGIN( IDLAttribute ); - } + else if (!yyextra->insideCS && + (yyextra->current->name.isEmpty() || + yyextra->current->name=="typedef" + ) + ) // IDL function property + { + yyextra->squareCount=1; + yyextra->lastSquareContext = YY_START; + yyextra->idlAttr.resize(0); + yyextra->idlProp.resize(0); + yyextra->current->mtype = yyextra->mtype; + + if (Config_getBool(IDL_PROPERTY_SUPPORT) && + yyextra->current->mtype == Property) + { // we are yyextra->inside the properties section of a dispinterface + yyextra->odlProp = true; + yyextra->current->spec |= Entry::Gettable; + yyextra->current->spec |= Entry::Settable; + } + + BEGIN( IDLAttribute ); + } else if (yyextra->insideCS && yyextra->current->name.isEmpty()) { @@ -3262,20 +3262,20 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) yyextra->current->args.resize(0); BEGIN( SkipSquare ); } - else - { - yyextra->current->args += yytext ; - yyextra->squareCount=1; - yyextra->externC=FALSE; // see bug759247 - BEGIN( Array ) ; - } - } + else + { + yyextra->current->args += yytext ; + yyextra->squareCount=1; + yyextra->externC=FALSE; // see bug759247 + BEGIN( Array ) ; + } + } <SliceMetadata>"[" { // Global metadata. - yyextra->squareCount++; + yyextra->squareCount++; yyextra->current->metaData += "["; } <SliceMetadata>{BN}* { - lineCount(yyscanner); + lineCount(yyscanner); } <SliceMetadata>\"[^\"]*\" { yyextra->current->metaData += yytext; @@ -3304,294 +3304,294 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) BEGIN (yyextra->lastModifierContext); } } -<IDLAttribute>"]" { - // end of IDL function attribute - if (--yyextra->squareCount<=0) - { - lineCount(yyscanner); - if (yyextra->current->mtype == Property) - BEGIN( IDLPropName ); - else - BEGIN( yyextra->lastSquareContext ); - } - } -<IDLAttribute>"propput" { +<IDLAttribute>"]" { + // end of IDL function attribute + if (--yyextra->squareCount<=0) + { + lineCount(yyscanner); + if (yyextra->current->mtype == Property) + BEGIN( IDLPropName ); + else + BEGIN( yyextra->lastSquareContext ); + } + } +<IDLAttribute>"propput" { if (Config_getBool(IDL_PROPERTY_SUPPORT)) - { - yyextra->current->mtype = Property; - } - yyextra->current->spec |= Entry::Settable; - } -<IDLAttribute>"propget" { + { + yyextra->current->mtype = Property; + } + yyextra->current->spec |= Entry::Settable; + } +<IDLAttribute>"propget" { if (Config_getBool(IDL_PROPERTY_SUPPORT)) - { - yyextra->current->mtype = Property; - } - yyextra->current->spec |= Entry::Gettable; - } + { + yyextra->current->mtype = Property; + } + yyextra->current->spec |= Entry::Gettable; + } <IDLAttribute>"property" { // UNO IDL property - yyextra->current->spec |= Entry::Property; - } + yyextra->current->spec |= Entry::Property; + } <IDLAttribute>"attribute" { // UNO IDL attribute - yyextra->current->spec |= Entry::Attribute; - } + yyextra->current->spec |= Entry::Attribute; + } <IDLAttribute>"optional" { // on UNO IDL interface/service/attribute/property yyextra->current->spec |= Entry::Optional; } <IDLAttribute>"readonly" { // on UNO IDL attribute or property - if (Config_getBool(IDL_PROPERTY_SUPPORT) && yyextra->odlProp) - { - yyextra->current->spec ^= Entry::Settable; - } - else - { - yyextra->current->spec |= Entry::Readonly; - } - } + if (Config_getBool(IDL_PROPERTY_SUPPORT) && yyextra->odlProp) + { + yyextra->current->spec ^= Entry::Settable; + } + else + { + yyextra->current->spec |= Entry::Readonly; + } + } <IDLAttribute>"bound" { // on UNO IDL attribute or property - yyextra->current->spec |= Entry::Bound; - } + yyextra->current->spec |= Entry::Bound; + } <IDLAttribute>"removable" { // on UNO IDL property - yyextra->current->spec |= Entry::Removable; - } + yyextra->current->spec |= Entry::Removable; + } <IDLAttribute>"constrained" { // on UNO IDL property - yyextra->current->spec |= Entry::Constrained; - } + yyextra->current->spec |= Entry::Constrained; + } <IDLAttribute>"transient" { // on UNO IDL property - yyextra->current->spec |= Entry::Transient; - } + yyextra->current->spec |= Entry::Transient; + } <IDLAttribute>"maybevoid" { // on UNO IDL property - yyextra->current->spec |= Entry::MaybeVoid; - } + yyextra->current->spec |= Entry::MaybeVoid; + } <IDLAttribute>"maybedefault" { // on UNO IDL property - yyextra->current->spec |= Entry::MaybeDefault; - } + yyextra->current->spec |= Entry::MaybeDefault; + } <IDLAttribute>"maybeambiguous" { // on UNO IDL property - yyextra->current->spec |= Entry::MaybeAmbiguous; - } -<IDLAttribute>. { - } -<IDLPropName>{BN}*{ID}{BN}* { - // return type (probably HRESULT) - skip it + yyextra->current->spec |= Entry::MaybeAmbiguous; + } +<IDLAttribute>. { + } +<IDLPropName>{BN}*{ID}{BN}* { + // return type (probably HRESULT) - skip it - if (yyextra->odlProp) - { // property type - yyextra->idlProp = yytext; - } - } -<IDLPropName>{ID}{BN}*"(" { - yyextra->current->name = yytext; - yyextra->current->name = yyextra->current->name.left(yyextra->current->name.length()-1).stripWhiteSpace(); - yyextra->current->startLine = yyextra->yyLineNr; - yyextra->current->startColumn = yyextra->yyColNr; - BEGIN( IDLProp ); - } -<IDLPropName>{BN}*"("{BN}*{ID}{BN}*")"{BN}* { - if (yyextra->odlProp) - { - yyextra->idlProp += yytext; - } - } -<IDLPropName>{ID}{BN}*/";" { - if (yyextra->odlProp) - { - yyextra->current->name = yytext; - yyextra->idlProp = yyextra->idlProp.stripWhiteSpace(); - yyextra->odlProp = false; - - BEGIN( IDLProp ); - } - } -<IDLProp>{BN}*"["[^\]]*"]"{BN}* { // attribute of a parameter - yyextra->idlAttr = yytext; - yyextra->idlAttr=yyextra->idlAttr.stripWhiteSpace(); - } -<IDLProp>{ID} { // property type - yyextra->idlProp = yytext; - } -<IDLProp>{BN}*{ID}{BN}*"," { // Rare: Another parameter ([propput] HRESULT Item(int index, [in] Type theRealProperty);) - if (!yyextra->current->args) - yyextra->current->args = "("; - else - yyextra->current->args += ", "; - yyextra->current->args += yyextra->idlAttr; - yyextra->current->args += " "; - yyextra->current->args += yyextra->idlProp; // prop was actually type of extra parameter - yyextra->current->args += " "; - yyextra->current->args += yytext; - yyextra->current->args = yyextra->current->args.left(yyextra->current->args.length() - 1); // strip comma - yyextra->idlProp.resize(0); - yyextra->idlAttr.resize(0); - BEGIN( IDLProp ); - } -<IDLProp>{BN}*{ID}{BN}*")"{BN}* { - // the parameter name for the property - just skip. - } -<IDLProp>";" { - yyextra->current->fileName = yyextra->yyFileName; - yyextra->current->type = yyextra->idlProp; - yyextra->current->args = yyextra->current->args.simplifyWhiteSpace(); - if (yyextra->current->args) - yyextra->current->args += ")"; - yyextra->current->name = yyextra->current->name.stripWhiteSpace(); - yyextra->current->section = Entry::VARIABLE_SEC; - yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current); - initEntry(yyscanner); - BEGIN( FindMembers ); - } -<IDLProp>. { // spaces, *, or other stuff - //yyextra->idlProp+=yytext; - } -<Array>"]" { yyextra->current->args += *yytext ; - if (--yyextra->squareCount<=0) - BEGIN( FindMembers ) ; - } -<FuncFuncArray>"]" { yyextra->current->args += *yytext ; - if (--yyextra->squareCount<=0) - BEGIN( Function ) ; - } -<Array,FuncFuncArray>"[" { yyextra->current->args += *yytext ; - yyextra->squareCount++; - } -<Array,FuncFuncArray>. { yyextra->current->args += *yytext ; } -<SkipSquare>"[" { yyextra->squareCount++; } -<SkipSquare>"]" { - if (--yyextra->squareCount<=0) - BEGIN( yyextra->lastSquareContext ); - } -<SkipSquare>\" { - yyextra->lastStringContext=YY_START; - BEGIN( SkipString ); - } + if (yyextra->odlProp) + { // property type + yyextra->idlProp = yytext; + } + } +<IDLPropName>{ID}{BN}*"(" { + yyextra->current->name = yytext; + yyextra->current->name = yyextra->current->name.left(yyextra->current->name.length()-1).stripWhiteSpace(); + yyextra->current->startLine = yyextra->yyLineNr; + yyextra->current->startColumn = yyextra->yyColNr; + BEGIN( IDLProp ); + } +<IDLPropName>{BN}*"("{BN}*{ID}{BN}*")"{BN}* { + if (yyextra->odlProp) + { + yyextra->idlProp += yytext; + } + } +<IDLPropName>{ID}{BN}*/";" { + if (yyextra->odlProp) + { + yyextra->current->name = yytext; + yyextra->idlProp = yyextra->idlProp.stripWhiteSpace(); + yyextra->odlProp = false; + + BEGIN( IDLProp ); + } + } +<IDLProp>{BN}*"["[^\]]*"]"{BN}* { // attribute of a parameter + yyextra->idlAttr = yytext; + yyextra->idlAttr=yyextra->idlAttr.stripWhiteSpace(); + } +<IDLProp>{ID} { // property type + yyextra->idlProp = yytext; + } +<IDLProp>{BN}*{ID}{BN}*"," { // Rare: Another parameter ([propput] HRESULT Item(int index, [in] Type theRealProperty);) + if (!yyextra->current->args) + yyextra->current->args = "("; + else + yyextra->current->args += ", "; + yyextra->current->args += yyextra->idlAttr; + yyextra->current->args += " "; + yyextra->current->args += yyextra->idlProp; // prop was actually type of extra parameter + yyextra->current->args += " "; + yyextra->current->args += yytext; + yyextra->current->args = yyextra->current->args.left(yyextra->current->args.length() - 1); // strip comma + yyextra->idlProp.resize(0); + yyextra->idlAttr.resize(0); + BEGIN( IDLProp ); + } +<IDLProp>{BN}*{ID}{BN}*")"{BN}* { + // the parameter name for the property - just skip. + } +<IDLProp>";" { + yyextra->current->fileName = yyextra->yyFileName; + yyextra->current->type = yyextra->idlProp; + yyextra->current->args = yyextra->current->args.simplifyWhiteSpace(); + if (yyextra->current->args) + yyextra->current->args += ")"; + yyextra->current->name = yyextra->current->name.stripWhiteSpace(); + yyextra->current->section = Entry::VARIABLE_SEC; + yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current); + initEntry(yyscanner); + BEGIN( FindMembers ); + } +<IDLProp>. { // spaces, *, or other stuff + //yyextra->idlProp+=yytext; + } +<Array>"]" { yyextra->current->args += *yytext ; + if (--yyextra->squareCount<=0) + BEGIN( FindMembers ) ; + } +<FuncFuncArray>"]" { yyextra->current->args += *yytext ; + if (--yyextra->squareCount<=0) + BEGIN( Function ) ; + } +<Array,FuncFuncArray>"[" { yyextra->current->args += *yytext ; + yyextra->squareCount++; + } +<Array,FuncFuncArray>. { yyextra->current->args += *yytext ; } +<SkipSquare>"[" { yyextra->squareCount++; } +<SkipSquare>"]" { + if (--yyextra->squareCount<=0) + BEGIN( yyextra->lastSquareContext ); + } +<SkipSquare>\" { + yyextra->lastStringContext=YY_START; + BEGIN( SkipString ); + } <SkipSquare>[^\n\[\]\"]+ -<FindMembers>"<" { addType(yyscanner); - yyextra->current->type += yytext ; - BEGIN( Sharp ) ; - } -<Sharp>">" { yyextra->current->type += *yytext ; - if (--yyextra->sharpCount<=0) - BEGIN( FindMembers ) ; - } -<Sharp>"<" { yyextra->current->type += *yytext ; - yyextra->sharpCount++; - } -<Sharp>{BN}+ { +<FindMembers>"<" { addType(yyscanner); + yyextra->current->type += yytext ; + BEGIN( Sharp ) ; + } +<Sharp>">" { yyextra->current->type += *yytext ; + if (--yyextra->sharpCount<=0) + BEGIN( FindMembers ) ; + } +<Sharp>"<" { yyextra->current->type += *yytext ; + yyextra->sharpCount++; + } +<Sharp>{BN}+ { yyextra->current->type += ' '; - lineCount(yyscanner); - } -<Sharp>. { yyextra->current->type += *yytext ; } -<FindFields>{ID} { + lineCount(yyscanner); + } +<Sharp>. { yyextra->current->type += *yytext ; } +<FindFields>{ID} { if (yyextra->clangParser && (yyextra->insideCpp || yyextra->insideObjC)) { yyextra->current->id = yyextra->clangParser->lookup(yyextra->yyLineNr,yytext); } - yyextra->current->bodyLine = yyextra->yyLineNr; - yyextra->current->bodyColumn = yyextra->yyColNr; - yyextra->current->name = yytext; - } -<FindFields>"(" { - // Java enum initializer - unput('('); - yyextra->lastInitializerContext = YY_START; - yyextra->initBracketCount=0; + yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->current->bodyColumn = yyextra->yyColNr; + yyextra->current->name = yytext; + } +<FindFields>"(" { + // Java enum initializer + unput('('); + yyextra->lastInitializerContext = YY_START; + yyextra->initBracketCount=0; yyextra->current->initializer = "="; - BEGIN(ReadInitializer); - } -<FindFields>"=" { - yyextra->lastInitializerContext = YY_START; - yyextra->initBracketCount=0; + BEGIN(ReadInitializer); + } +<FindFields>"=" { + yyextra->lastInitializerContext = YY_START; + yyextra->initBracketCount=0; yyextra->current->initializer = yytext; - BEGIN(ReadInitializer); - } + BEGIN(ReadInitializer); + } <FindFields>";" { - if (yyextra->insideJava) // yyextra->last enum field in Java class - { - if (!yyextra->current->name.isEmpty()) - { - yyextra->current->fileName = yyextra->yyFileName; - yyextra->current->startLine = yyextra->yyLineNr; - yyextra->current->startColumn = yyextra->yyColNr; - if (!(yyextra->current_root->spec&Entry::Enum)) - { - yyextra->current->type = "@"; // enum marker - } - yyextra->current->args = yyextra->current->args.simplifyWhiteSpace(); - yyextra->current->name = yyextra->current->name.stripWhiteSpace(); - yyextra->current->section = Entry::VARIABLE_SEC; - yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current); - initEntry(yyscanner); - } - - BEGIN( FindMembers ); - } - else - { - REJECT; - } - } -<SkipRemainder>\n { + if (yyextra->insideJava) // yyextra->last enum field in Java class + { + if (!yyextra->current->name.isEmpty()) + { + yyextra->current->fileName = yyextra->yyFileName; + yyextra->current->startLine = yyextra->yyLineNr; + yyextra->current->startColumn = yyextra->yyColNr; + if (!(yyextra->current_root->spec&Entry::Enum)) + { + yyextra->current->type = "@"; // enum marker + } + yyextra->current->args = yyextra->current->args.simplifyWhiteSpace(); + yyextra->current->name = yyextra->current->name.stripWhiteSpace(); + yyextra->current->section = Entry::VARIABLE_SEC; + yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current); + initEntry(yyscanner); + } + + BEGIN( FindMembers ); + } + else + { + REJECT; + } + } +<SkipRemainder>\n { lineCount(yyscanner); } <SkipRemainder>[^\n]* -<FindFields>"," { - //printf("adding '%s' '%s' '%s' to enum '%s' (mGrpId=%d)\n", - // yyextra->current->type.data(), yyextra->current->name.data(), - // yyextra->current->args.data(), yyextra->current_root->name.data(),yyextra->current->mGrpId); - if (!yyextra->current->name.isEmpty()) - { - yyextra->current->fileName = yyextra->yyFileName; - yyextra->current->startLine = yyextra->yyLineNr; - yyextra->current->startColumn = yyextra->yyColNr; - if (!(yyextra->current_root->spec&Entry::Enum)) - { - yyextra->current->type = "@"; // enum marker - } - yyextra->current->args = yyextra->current->args.simplifyWhiteSpace(); - yyextra->current->name = yyextra->current->name.stripWhiteSpace(); - yyextra->current->section = Entry::VARIABLE_SEC; - // add to the scope of the enum - if (!yyextra->insideCS && !yyextra->insideJava && - !(yyextra->current_root->spec&Entry::Strong)) +<FindFields>"," { + //printf("adding '%s' '%s' '%s' to enum '%s' (mGrpId=%d)\n", + // yyextra->current->type.data(), yyextra->current->name.data(), + // yyextra->current->args.data(), yyextra->current_root->name.data(),yyextra->current->mGrpId); + if (!yyextra->current->name.isEmpty()) + { + yyextra->current->fileName = yyextra->yyFileName; + yyextra->current->startLine = yyextra->yyLineNr; + yyextra->current->startColumn = yyextra->yyColNr; + if (!(yyextra->current_root->spec&Entry::Enum)) + { + yyextra->current->type = "@"; // enum marker + } + yyextra->current->args = yyextra->current->args.simplifyWhiteSpace(); + yyextra->current->name = yyextra->current->name.stripWhiteSpace(); + yyextra->current->section = Entry::VARIABLE_SEC; + // add to the scope of the enum + if (!yyextra->insideCS && !yyextra->insideJava && + !(yyextra->current_root->spec&Entry::Strong)) // for C# and Java 1.5+ enum values always have to be explicitly qualified, // same for C++11 style enums (enum class Name {}) - { - // add to the scope surrounding the enum (copy!) + { + // add to the scope surrounding the enum (copy!) // we cannot during it directly as that would invalidate the iterator in parseCompounds. //printf("*** adding outer scope entry for %s\n",yyextra->current->name.data()); yyextra->outerScopeEntries.emplace_back(yyextra->current_root->parent(), std::make_shared<Entry>(*yyextra->current)); - } - yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current); - initEntry(yyscanner); - } - else // probably a redundant , - { - yyextra->current->reset(); - initEntry(yyscanner); - } - } -<FindFields>"[" { // attribute list in IDL - yyextra->squareCount=1; - yyextra->lastSquareContext = YY_START; - BEGIN(SkipSquare); - } + } + yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current); + initEntry(yyscanner); + } + else // probably a redundant , + { + yyextra->current->reset(); + initEntry(yyscanner); + } + } +<FindFields>"[" { // attribute list in IDL + yyextra->squareCount=1; + yyextra->lastSquareContext = YY_START; + BEGIN(SkipSquare); + } /* -<FindFieldArg>"," { unput(*yytext); BEGIN(FindFields); } +<FindFieldArg>"," { unput(*yytext); BEGIN(FindFields); } */ -<ReadBody,ReadNSBody,ReadBodyIntf>[^\r\n\#{}"@'/<]* { yyextra->current->program += yytext ; } -<ReadBody,ReadNSBody,ReadBodyIntf>"//".* { yyextra->current->program += yytext ; } -<ReadBody,ReadNSBody,ReadBodyIntf>"#".* { if (!yyextra->insidePHP) - REJECT; - // append PHP comment. - yyextra->current->program += yytext ; - } -<ReadBody,ReadNSBody,ReadBodyIntf>@\" { yyextra->current->program += yytext ; +<ReadBody,ReadNSBody,ReadBodyIntf>[^\r\n\#{}"@'/<]* { yyextra->current->program += yytext ; } +<ReadBody,ReadNSBody,ReadBodyIntf>"//".* { yyextra->current->program += yytext ; } +<ReadBody,ReadNSBody,ReadBodyIntf>"#".* { if (!yyextra->insidePHP) + REJECT; + // append PHP comment. + yyextra->current->program += yytext ; + } +<ReadBody,ReadNSBody,ReadBodyIntf>@\" { yyextra->current->program += yytext ; yyextra->pSkipVerbString = &yyextra->current->program; yyextra->lastSkipVerbStringContext=YY_START; BEGIN( SkipVerbString ); - } -<ReadBody,ReadNSBody,ReadBodyIntf>"<<<" { if (yyextra->insidePHP) + } +<ReadBody,ReadNSBody,ReadBodyIntf>"<<<" { if (yyextra->insidePHP) { - yyextra->current->program += yytext ; + yyextra->current->program += yytext ; yyextra->pCopyHereDocGString = &yyextra->current->program; yyextra->lastHereDocContext=YY_START; BEGIN( CopyHereDoc ); @@ -3600,61 +3600,61 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) { REJECT; } - } -<ReadBody,ReadNSBody,ReadBodyIntf>\" { yyextra->current->program += yytext ; + } +<ReadBody,ReadNSBody,ReadBodyIntf>\" { yyextra->current->program += yytext ; yyextra->pCopyQuotedGString = &yyextra->current->program; yyextra->lastStringContext=YY_START; BEGIN( CopyGString ); - } -<ReadBody,ReadNSBody,ReadBodyIntf>"/*"{B}* { yyextra->current->program += yytext ; - yyextra->lastContext = YY_START ; - BEGIN( Comment ) ; - } -<ReadBody,ReadNSBody,ReadBodyIntf>"/*"{BL} { yyextra->current->program += yytext ; - ++yyextra->yyLineNr ; - yyextra->lastContext = YY_START ; - BEGIN( Comment ) ; - } -<ReadBody,ReadNSBody,ReadBodyIntf>"'" { - if (!yyextra->insidePHP) - { - yyextra->current->program += yytext; - } - else - { // begin of single quoted string - yyextra->current->program += yytext; + } +<ReadBody,ReadNSBody,ReadBodyIntf>"/*"{B}* { yyextra->current->program += yytext ; + yyextra->lastContext = YY_START ; + BEGIN( Comment ) ; + } +<ReadBody,ReadNSBody,ReadBodyIntf>"/*"{BL} { yyextra->current->program += yytext ; + ++yyextra->yyLineNr ; + yyextra->lastContext = YY_START ; + BEGIN( Comment ) ; + } +<ReadBody,ReadNSBody,ReadBodyIntf>"'" { + if (!yyextra->insidePHP) + { + yyextra->current->program += yytext; + } + else + { // begin of single quoted string + yyextra->current->program += yytext; yyextra->pCopyQuotedGString = &yyextra->current->program; yyextra->lastStringContext=YY_START; - BEGIN(CopyPHPGString); - } - } -<ReadBody,ReadNSBody,ReadBodyIntf>{CHARLIT} { - if (yyextra->insidePHP) - { - REJECT; // for PHP code single quotes - // are used for strings of arbitrary length - } - else - { - yyextra->current->program += yytext; - } + BEGIN(CopyPHPGString); + } + } +<ReadBody,ReadNSBody,ReadBodyIntf>{CHARLIT} { + if (yyextra->insidePHP) + { + REJECT; // for PHP code single quotes + // are used for strings of arbitrary length + } + else + { + yyextra->current->program += yytext; + } } <ReadBody,ReadNSBody,ReadBodyIntf>"{" { yyextra->current->program += yytext ; - ++yyextra->curlyCount ; - } -<ReadBodyIntf>"}" { - yyextra->current->program += yytext ; - --yyextra->curlyCount ; - } -<ReadBody,ReadNSBody>"}" { //err("ReadBody count=%d\n",yyextra->curlyCount); - if ( yyextra->curlyCount>0 ) - { - yyextra->current->program += yytext ; - --yyextra->curlyCount ; - } - else - { - yyextra->current->endBodyLine = yyextra->yyLineNr; + ++yyextra->curlyCount ; + } +<ReadBodyIntf>"}" { + yyextra->current->program += yytext ; + --yyextra->curlyCount ; + } +<ReadBody,ReadNSBody>"}" { //err("ReadBody count=%d\n",yyextra->curlyCount); + if ( yyextra->curlyCount>0 ) + { + yyextra->current->program += yytext ; + --yyextra->curlyCount ; + } + else + { + yyextra->current->endBodyLine = yyextra->yyLineNr; std::shared_ptr<Entry> original_root = yyextra->current_root; // save root this namespace is in if (yyextra->current->section == Entry::NAMESPACE_SEC && yyextra->current->type == "namespace") { @@ -3693,817 +3693,817 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) yyextra->current->briefLine = briefLine; yyextra->current->briefFile = briefFile; } - QCString &cn = yyextra->current->name; - QCString rn = yyextra->current_root->name.copy(); - //printf("cn='%s' rn='%s' yyextra->isTypedef=%d\n",cn.data(),rn.data(),yyextra->isTypedef); - if (!cn.isEmpty() && !rn.isEmpty()) - { - prependScope(yyscanner); - } - if (yyextra->isTypedef && cn.isEmpty()) - { - //printf("Typedef Name\n"); - BEGIN( TypedefName ); - } - else - { - if ((yyextra->current->section == Entry::ENUM_SEC) || (yyextra->current->spec&Entry::Enum)) - { - yyextra->current->program+=','; // add field terminator - } - // add compound definition to the tree - yyextra->current->args=removeRedundantWhiteSpace(yyextra->current->args); - // was: yyextra->current->args.simplifyWhiteSpace(); - yyextra->current->type = yyextra->current->type.simplifyWhiteSpace(); - yyextra->current->name = yyextra->current->name.stripWhiteSpace(); - //printf("adding '%s' '%s' '%s' brief=%s yyextra->insideObjC=%d %x\n",yyextra->current->type.data(),yyextra->current->name.data(),yyextra->current->args.data(),yyextra->current->brief.data(),yyextra->insideObjC,yyextra->current->section); - if (yyextra->insideObjC && - ((yyextra->current->spec&Entry::Interface) || (yyextra->current->spec==Entry::Category)) - ) // method definition follows - { - BEGIN( ReadBodyIntf ) ; - } - else - { - yyextra->memspecEntry = yyextra->current; - yyextra->current_root->moveToSubEntryAndKeep( yyextra->current ) ; - yyextra->current = std::make_shared<Entry>(*yyextra->current); - if (yyextra->current->section==Entry::NAMESPACE_SEC || - (yyextra->current->spec==Entry::Interface) || - yyextra->insideJava || yyextra->insidePHP || yyextra->insideCS || yyextra->insideD || yyextra->insideJS || + QCString &cn = yyextra->current->name; + QCString rn = yyextra->current_root->name.copy(); + //printf("cn='%s' rn='%s' yyextra->isTypedef=%d\n",cn.data(),rn.data(),yyextra->isTypedef); + if (!cn.isEmpty() && !rn.isEmpty()) + { + prependScope(yyscanner); + } + if (yyextra->isTypedef && cn.isEmpty()) + { + //printf("Typedef Name\n"); + BEGIN( TypedefName ); + } + else + { + if ((yyextra->current->section == Entry::ENUM_SEC) || (yyextra->current->spec&Entry::Enum)) + { + yyextra->current->program+=','; // add field terminator + } + // add compound definition to the tree + yyextra->current->args=removeRedundantWhiteSpace(yyextra->current->args); + // was: yyextra->current->args.simplifyWhiteSpace(); + yyextra->current->type = yyextra->current->type.simplifyWhiteSpace(); + yyextra->current->name = yyextra->current->name.stripWhiteSpace(); + //printf("adding '%s' '%s' '%s' brief=%s yyextra->insideObjC=%d %x\n",yyextra->current->type.data(),yyextra->current->name.data(),yyextra->current->args.data(),yyextra->current->brief.data(),yyextra->insideObjC,yyextra->current->section); + if (yyextra->insideObjC && + ((yyextra->current->spec&Entry::Interface) || (yyextra->current->spec==Entry::Category)) + ) // method definition follows + { + BEGIN( ReadBodyIntf ) ; + } + else + { + yyextra->memspecEntry = yyextra->current; + yyextra->current_root->moveToSubEntryAndKeep( yyextra->current ) ; + yyextra->current = std::make_shared<Entry>(*yyextra->current); + if (yyextra->current->section==Entry::NAMESPACE_SEC || + (yyextra->current->spec==Entry::Interface) || + yyextra->insideJava || yyextra->insidePHP || yyextra->insideCS || yyextra->insideD || yyextra->insideJS || yyextra->insideSlice - ) - { // namespaces and interfaces and java classes ends with a closing bracket without semicolon + ) + { // namespaces and interfaces and java classes ends with a closing bracket without semicolon yyextra->current->reset(); yyextra->current_root = original_root; // restore scope from before namespace descent - initEntry(yyscanner); - yyextra->memspecEntry.reset(); - BEGIN( FindMembers ) ; - } - else - { + initEntry(yyscanner); + yyextra->memspecEntry.reset(); + BEGIN( FindMembers ) ; + } + else + { static QRegExp re("@[0-9]+$"); - if (!yyextra->isTypedef && yyextra->memspecEntry && + if (!yyextra->isTypedef && yyextra->memspecEntry && yyextra->memspecEntry->name.find(re)==-1) // not typedef or anonymous type (see bug691071) - { - // enabled the next two lines for bug 623424 - yyextra->current->doc.resize(0); - yyextra->current->brief.resize(0); - } - BEGIN( MemberSpec ) ; - } - } - } - } - } -<ReadBody>"}"{BN}+"typedef"{BN}+ { //err("ReadBody count=%d\n",yyextra->curlyCount); - lineCount(yyscanner); - if ( yyextra->curlyCount>0 ) - { - yyextra->current->program += yytext ; - --yyextra->curlyCount ; - } - else - { - yyextra->isTypedef = TRUE; - yyextra->current->endBodyLine = yyextra->yyLineNr; - QCString &cn = yyextra->current->name; - QCString rn = yyextra->current_root->name.copy(); - if (!cn.isEmpty() && !rn.isEmpty()) - { - prependScope(yyscanner); - } - BEGIN( TypedefName ); - } - } -<TypedefName>("const"|"volatile"){BN} { // late "const" or "volatile" keyword - lineCount(yyscanner); - yyextra->current->type.prepend(yytext); - } -<TypedefName>{ID} { - if ((yyextra->current->section == Entry::ENUM_SEC) || (yyextra->current->spec&Entry::Enum)) - { - yyextra->current->program+=","; // add field terminator - } - yyextra->current->name=yytext; - prependScope(yyscanner); - yyextra->current->args = yyextra->current->args.simplifyWhiteSpace(); - yyextra->current->type = yyextra->current->type.simplifyWhiteSpace(); - //printf("Adding compound %s %s %s\n",yyextra->current->type.data(),yyextra->current->name.data(),yyextra->current->args.data()); - if (!yyextra->firstTypedefEntry) - { - yyextra->firstTypedefEntry = yyextra->current; - } - yyextra->current_root->moveToSubEntryAndRefresh( yyextra->current ) ; - initEntry(yyscanner); - yyextra->isTypedef=TRUE; // to undo reset by initEntry(yyscanner) - BEGIN(MemberSpecSkip); - } -<TypedefName>";" { /* typedef of anonymous type */ - yyextra->current->name.sprintf("@%d",anonCount++); - if ((yyextra->current->section == Entry::ENUM_SEC) || (yyextra->current->spec&Entry::Enum)) - { - yyextra->current->program+=','; // add field terminator - } - // add compound definition to the tree - yyextra->current->args = yyextra->current->args.simplifyWhiteSpace(); - yyextra->current->type = yyextra->current->type.simplifyWhiteSpace(); - yyextra->memspecEntry = yyextra->current; - yyextra->current_root->moveToSubEntryAndRefresh( yyextra->current ) ; - initEntry(yyscanner); - unput(';'); - BEGIN( MemberSpec ) ; - } + { + // enabled the next two lines for bug 623424 + yyextra->current->doc.resize(0); + yyextra->current->brief.resize(0); + } + BEGIN( MemberSpec ) ; + } + } + } + } + } +<ReadBody>"}"{BN}+"typedef"{BN}+ { //err("ReadBody count=%d\n",yyextra->curlyCount); + lineCount(yyscanner); + if ( yyextra->curlyCount>0 ) + { + yyextra->current->program += yytext ; + --yyextra->curlyCount ; + } + else + { + yyextra->isTypedef = TRUE; + yyextra->current->endBodyLine = yyextra->yyLineNr; + QCString &cn = yyextra->current->name; + QCString rn = yyextra->current_root->name.copy(); + if (!cn.isEmpty() && !rn.isEmpty()) + { + prependScope(yyscanner); + } + BEGIN( TypedefName ); + } + } +<TypedefName>("const"|"volatile"){BN} { // late "const" or "volatile" keyword + lineCount(yyscanner); + yyextra->current->type.prepend(yytext); + } +<TypedefName>{ID} { + if ((yyextra->current->section == Entry::ENUM_SEC) || (yyextra->current->spec&Entry::Enum)) + { + yyextra->current->program+=","; // add field terminator + } + yyextra->current->name=yytext; + prependScope(yyscanner); + yyextra->current->args = yyextra->current->args.simplifyWhiteSpace(); + yyextra->current->type = yyextra->current->type.simplifyWhiteSpace(); + //printf("Adding compound %s %s %s\n",yyextra->current->type.data(),yyextra->current->name.data(),yyextra->current->args.data()); + if (!yyextra->firstTypedefEntry) + { + yyextra->firstTypedefEntry = yyextra->current; + } + yyextra->current_root->moveToSubEntryAndRefresh( yyextra->current ) ; + initEntry(yyscanner); + yyextra->isTypedef=TRUE; // to undo reset by initEntry(yyscanner) + BEGIN(MemberSpecSkip); + } +<TypedefName>";" { /* typedef of anonymous type */ + yyextra->current->name.sprintf("@%d",anonCount++); + if ((yyextra->current->section == Entry::ENUM_SEC) || (yyextra->current->spec&Entry::Enum)) + { + yyextra->current->program+=','; // add field terminator + } + // add compound definition to the tree + yyextra->current->args = yyextra->current->args.simplifyWhiteSpace(); + yyextra->current->type = yyextra->current->type.simplifyWhiteSpace(); + yyextra->memspecEntry = yyextra->current; + yyextra->current_root->moveToSubEntryAndRefresh( yyextra->current ) ; + initEntry(yyscanner); + unput(';'); + BEGIN( MemberSpec ) ; + } <MemberSpec>([*&]*{BN}*)*{ID}{BN}*("["[^\]\n]*"]")* { // the [] part could be improved. - lineCount(yyscanner); - int i=0,l=(int)yyleng,j; - while (i<l && (!isId(yytext[i]))) i++; - yyextra->msName = QCString(yytext).right(l-i).stripWhiteSpace(); - j=yyextra->msName.find("["); - if (j!=-1) - { - yyextra->msArgs=yyextra->msName.right(yyextra->msName.length()-j); - yyextra->msName=yyextra->msName.left(j); - } - yyextra->msType=QCString(yytext).left(i); - - // handle *pName in: typedef { ... } name, *pName; - if (yyextra->firstTypedefEntry) - { - if (yyextra->firstTypedefEntry->spec&Entry::Struct) - { - yyextra->msType.prepend("struct "+yyextra->firstTypedefEntry->name); - } - else if (yyextra->firstTypedefEntry->spec&Entry::Union) - { - yyextra->msType.prepend("union "+yyextra->firstTypedefEntry->name); - } - else if (yyextra->firstTypedefEntry->section==Entry::ENUM_SEC) - { - yyextra->msType.prepend("enum "+yyextra->firstTypedefEntry->name); - } - else - { - yyextra->msType.prepend(yyextra->firstTypedefEntry->name); - } - } - } -<MemberSpec>"(" { // function with struct return type - addType(yyscanner); - yyextra->current->name = yyextra->msName; - yyextra->current->spec = 0; - unput('('); - BEGIN(FindMembers); - } -<MemberSpec>[,;] { - if (yyextra->msName.isEmpty() && !yyextra->current->name.isEmpty()) - { - // see if the compound does not have a name or is yyextra->inside another - // anonymous compound. If so we insert a - // special 'anonymous' variable. - //Entry *p=yyextra->current_root; + lineCount(yyscanner); + int i=0,l=(int)yyleng,j; + while (i<l && (!isId(yytext[i]))) i++; + yyextra->msName = QCString(yytext).right(l-i).stripWhiteSpace(); + j=yyextra->msName.find("["); + if (j!=-1) + { + yyextra->msArgs=yyextra->msName.right(yyextra->msName.length()-j); + yyextra->msName=yyextra->msName.left(j); + } + yyextra->msType=QCString(yytext).left(i); + + // handle *pName in: typedef { ... } name, *pName; + if (yyextra->firstTypedefEntry) + { + if (yyextra->firstTypedefEntry->spec&Entry::Struct) + { + yyextra->msType.prepend("struct "+yyextra->firstTypedefEntry->name); + } + else if (yyextra->firstTypedefEntry->spec&Entry::Union) + { + yyextra->msType.prepend("union "+yyextra->firstTypedefEntry->name); + } + else if (yyextra->firstTypedefEntry->section==Entry::ENUM_SEC) + { + yyextra->msType.prepend("enum "+yyextra->firstTypedefEntry->name); + } + else + { + yyextra->msType.prepend(yyextra->firstTypedefEntry->name); + } + } + } +<MemberSpec>"(" { // function with struct return type + addType(yyscanner); + yyextra->current->name = yyextra->msName; + yyextra->current->spec = 0; + unput('('); + BEGIN(FindMembers); + } +<MemberSpec>[,;] { + if (yyextra->msName.isEmpty() && !yyextra->current->name.isEmpty()) + { + // see if the compound does not have a name or is yyextra->inside another + // anonymous compound. If so we insert a + // special 'anonymous' variable. + //Entry *p=yyextra->current_root; const Entry *p=yyextra->current.get(); - while (p) - { - // only look for class scopes, not namespace scopes - if ((p->section & Entry::COMPOUND_MASK) && !p->name.isEmpty()) - { - //printf("Trying scope '%s'\n",p->name.data()); - int i=p->name.findRev("::"); - int pi = (i==-1) ? 0 : i+2; - if (p->name.at(pi)=='@') - { - // anonymous compound yyextra->inside -> insert dummy variable name - //printf("Adding anonymous variable for scope %s\n",p->name.data()); - yyextra->msName.sprintf("@%d",anonCount++); - break; - } - } - //p=p->parent; - if (p==yyextra->current.get()) p=yyextra->current_root.get(); else p=p->parent(); - } - } - //printf("yyextra->msName=%s yyextra->current->name=%s\n",yyextra->msName.data(),yyextra->current->name.data()); - if (!yyextra->msName.isEmpty() - /*&& yyextra->msName!=yyextra->current->name*/) // skip typedef T {} T;, removed due to bug608493 - { - bool typedefHidesStruct = Config_getBool(TYPEDEF_HIDES_STRUCT); - // case 1: typedef struct _S { ... } S_t; - // -> omit typedef and use S_t as the struct name - if (typedefHidesStruct && - yyextra->isTypedef && - ((yyextra->current->spec&(Entry::Struct|Entry::Union)) || - yyextra->current->section==Entry::ENUM_SEC )&& - yyextra->msType.stripWhiteSpace().isEmpty() && - yyextra->memspecEntry) - { - yyextra->memspecEntry->name=yyextra->msName; - } - else // case 2: create a typedef field - { + while (p) + { + // only look for class scopes, not namespace scopes + if ((p->section & Entry::COMPOUND_MASK) && !p->name.isEmpty()) + { + //printf("Trying scope '%s'\n",p->name.data()); + int i=p->name.findRev("::"); + int pi = (i==-1) ? 0 : i+2; + if (p->name.at(pi)=='@') + { + // anonymous compound yyextra->inside -> insert dummy variable name + //printf("Adding anonymous variable for scope %s\n",p->name.data()); + yyextra->msName.sprintf("@%d",anonCount++); + break; + } + } + //p=p->parent; + if (p==yyextra->current.get()) p=yyextra->current_root.get(); else p=p->parent(); + } + } + //printf("yyextra->msName=%s yyextra->current->name=%s\n",yyextra->msName.data(),yyextra->current->name.data()); + if (!yyextra->msName.isEmpty() + /*&& yyextra->msName!=yyextra->current->name*/) // skip typedef T {} T;, removed due to bug608493 + { + bool typedefHidesStruct = Config_getBool(TYPEDEF_HIDES_STRUCT); + // case 1: typedef struct _S { ... } S_t; + // -> omit typedef and use S_t as the struct name + if (typedefHidesStruct && + yyextra->isTypedef && + ((yyextra->current->spec&(Entry::Struct|Entry::Union)) || + yyextra->current->section==Entry::ENUM_SEC )&& + yyextra->msType.stripWhiteSpace().isEmpty() && + yyextra->memspecEntry) + { + yyextra->memspecEntry->name=yyextra->msName; + } + else // case 2: create a typedef field + { std::shared_ptr<Entry> varEntry=std::make_shared<Entry>(); - varEntry->lang = yyextra->language; - varEntry->protection = yyextra->current->protection ; - varEntry->mtype = yyextra->current->mtype; - varEntry->virt = yyextra->current->virt; - varEntry->stat = yyextra->current->stat; - varEntry->section = Entry::VARIABLE_SEC; - varEntry->name = yyextra->msName.stripWhiteSpace(); - varEntry->type = yyextra->current->type.simplifyWhiteSpace()+" "; - varEntry->args = yyextra->msArgs; - if (yyextra->isTypedef) - { - varEntry->type.prepend("typedef "); - // //printf("yyextra->current->name = %s %s\n",yyextra->current->name.data(),yyextra->msName.data()); - } - if (typedefHidesStruct && - yyextra->isTypedef && - (yyextra->current->spec&(Entry::Struct|Entry::Union)) && - yyextra->memspecEntry - ) // case 1: use S_t as type for pS_t in "typedef struct _S {} S_t, *pS_t;" - { - varEntry->type+=yyextra->memspecEntry->name+yyextra->msType; - } - else // case 2: use _S as type for for pS_t - { - varEntry->type+=yyextra->current->name+yyextra->msType; - } - varEntry->fileName = yyextra->yyFileName; - varEntry->startLine = yyextra->yyLineNr; - varEntry->startColumn = yyextra->yyColNr; - varEntry->doc = yyextra->current->doc.copy(); - varEntry->brief = yyextra->current->brief.copy(); - varEntry->mGrpId = yyextra->current->mGrpId; + varEntry->lang = yyextra->language; + varEntry->protection = yyextra->current->protection ; + varEntry->mtype = yyextra->current->mtype; + varEntry->virt = yyextra->current->virt; + varEntry->stat = yyextra->current->stat; + varEntry->section = Entry::VARIABLE_SEC; + varEntry->name = yyextra->msName.stripWhiteSpace(); + varEntry->type = yyextra->current->type.simplifyWhiteSpace()+" "; + varEntry->args = yyextra->msArgs; + if (yyextra->isTypedef) + { + varEntry->type.prepend("typedef "); + // //printf("yyextra->current->name = %s %s\n",yyextra->current->name.data(),yyextra->msName.data()); + } + if (typedefHidesStruct && + yyextra->isTypedef && + (yyextra->current->spec&(Entry::Struct|Entry::Union)) && + yyextra->memspecEntry + ) // case 1: use S_t as type for pS_t in "typedef struct _S {} S_t, *pS_t;" + { + varEntry->type+=yyextra->memspecEntry->name+yyextra->msType; + } + else // case 2: use _S as type for for pS_t + { + varEntry->type+=yyextra->current->name+yyextra->msType; + } + varEntry->fileName = yyextra->yyFileName; + varEntry->startLine = yyextra->yyLineNr; + varEntry->startColumn = yyextra->yyColNr; + varEntry->doc = yyextra->current->doc.copy(); + varEntry->brief = yyextra->current->brief.copy(); + varEntry->mGrpId = yyextra->current->mGrpId; varEntry->initializer = yyextra->current->initializer; varEntry->groups = yyextra->current->groups; varEntry->sli = yyextra->current->sli; - //printf("Add: type='%s',name='%s',args='%s' brief=%s doc=%s\n", - // varEntry->type.data(),varEntry->name.data(), - // varEntry->args.data(),varEntry->brief.data(),varEntry->doc.data()); - yyextra->current_root->moveToSubEntryAndKeep(varEntry); - } - } - if (*yytext==';') // end of a struct/class ... - { - if (!yyextra->isTypedef && yyextra->msName.isEmpty() && yyextra->memspecEntry && (yyextra->current->section&Entry::COMPOUND_MASK)) - { // case where a class/struct has a doc block after it - if (!yyextra->current->doc.isEmpty()) - { - yyextra->memspecEntry->doc += yyextra->current->doc; - } - if (!yyextra->current->brief.isEmpty()) - { - yyextra->memspecEntry->brief += yyextra->current->brief; - } - } - yyextra->msType.resize(0); - yyextra->msName.resize(0); - yyextra->msArgs.resize(0); - yyextra->isTypedef=FALSE; - yyextra->firstTypedefEntry.reset(); - yyextra->memspecEntry.reset(); - yyextra->current->reset(); - initEntry(yyscanner); - BEGIN( FindMembers ); - } - else - { - yyextra->current->doc.resize(0); - yyextra->current->brief.resize(0); - } - - } -<MemberSpec>"=" { - yyextra->lastInitializerContext=YY_START; - yyextra->initBracketCount=0; + //printf("Add: type='%s',name='%s',args='%s' brief=%s doc=%s\n", + // varEntry->type.data(),varEntry->name.data(), + // varEntry->args.data(),varEntry->brief.data(),varEntry->doc.data()); + yyextra->current_root->moveToSubEntryAndKeep(varEntry); + } + } + if (*yytext==';') // end of a struct/class ... + { + if (!yyextra->isTypedef && yyextra->msName.isEmpty() && yyextra->memspecEntry && (yyextra->current->section&Entry::COMPOUND_MASK)) + { // case where a class/struct has a doc block after it + if (!yyextra->current->doc.isEmpty()) + { + yyextra->memspecEntry->doc += yyextra->current->doc; + } + if (!yyextra->current->brief.isEmpty()) + { + yyextra->memspecEntry->brief += yyextra->current->brief; + } + } + yyextra->msType.resize(0); + yyextra->msName.resize(0); + yyextra->msArgs.resize(0); + yyextra->isTypedef=FALSE; + yyextra->firstTypedefEntry.reset(); + yyextra->memspecEntry.reset(); + yyextra->current->reset(); + initEntry(yyscanner); + BEGIN( FindMembers ); + } + else + { + yyextra->current->doc.resize(0); + yyextra->current->brief.resize(0); + } + + } +<MemberSpec>"=" { + yyextra->lastInitializerContext=YY_START; + yyextra->initBracketCount=0; yyextra->current->initializer = yytext; - BEGIN(ReadInitializer); - /* BEGIN(MemberSpecSkip); */ - } + BEGIN(ReadInitializer); + /* BEGIN(MemberSpecSkip); */ + } /* -<MemberSpecSkip>"{" { - yyextra->curlyCount=0; - yyextra->lastCurlyContext = MemberSpecSkip; - yyextra->previous = yyextra->current; - BEGIN(SkipCurly); - } +<MemberSpecSkip>"{" { + yyextra->curlyCount=0; + yyextra->lastCurlyContext = MemberSpecSkip; + yyextra->previous = yyextra->current; + BEGIN(SkipCurly); + } */ -<MemberSpecSkip>"," { BEGIN(MemberSpec); } -<MemberSpecSkip>";" { unput(';'); BEGIN(MemberSpec); } +<MemberSpecSkip>"," { BEGIN(MemberSpec); } +<MemberSpecSkip>";" { unput(';'); BEGIN(MemberSpec); } <ReadBody,ReadNSBody,ReadBodyIntf>{BN}{1,80} { yyextra->current->program += yytext ; - lineCount(yyscanner) ; - } -<ReadBodyIntf>"@end"/[^a-z_A-Z0-9] { // end of Objective C block - yyextra->current_root->moveToSubEntryAndRefresh( yyextra->current ) ; - initEntry(yyscanner); - yyextra->language = yyextra->current->lang = SrcLangExt_Cpp; // see bug746361 - yyextra->insideObjC=FALSE; - BEGIN( FindMembers ); - } -<ReadBody,ReadNSBody,ReadBodyIntf>. { yyextra->current->program += yytext ; } + lineCount(yyscanner) ; + } +<ReadBodyIntf>"@end"/[^a-z_A-Z0-9] { // end of Objective C block + yyextra->current_root->moveToSubEntryAndRefresh( yyextra->current ) ; + initEntry(yyscanner); + yyextra->language = yyextra->current->lang = SrcLangExt_Cpp; // see bug746361 + yyextra->insideObjC=FALSE; + BEGIN( FindMembers ); + } +<ReadBody,ReadNSBody,ReadBodyIntf>. { yyextra->current->program += yytext ; } <FindMembers>"("/{BN}*"::"*{BN}*({TSCOPE}{BN}*"::")*{TSCOPE}{BN}*")"{BN}*"(" | /* typedef void (A<int>::func_t)(args...) */ <FindMembers>("("({BN}*"::"*{BN}*{TSCOPE}{BN}*"::")*({BN}*[*&\^]{BN}*)+)+ { /* typedef void (A::*ptr_t)(args...) or int (*func(int))[], the ^ is for Obj-C blocks */ - if (yyextra->insidePHP) // reference parameter - { - REJECT - } - else - { - yyextra->current->bodyLine = yyextra->yyLineNr; - yyextra->current->bodyColumn = yyextra->yyColNr; - lineCount(yyscanner); - addType(yyscanner); - yyextra->funcPtrType=yytext; - yyextra->roundCount=0; - //yyextra->current->type += yytext; - BEGIN( FuncPtr ); - } - } -<FuncPtr>{SCOPENAME} { - yyextra->current->name = yytext; - if (nameIsOperator(yyextra->current->name)) - { - BEGIN( FuncPtrOperator ); - } - else - { - if (yyextra->current->name=="const" || yyextra->current->name=="volatile") - { - yyextra->funcPtrType += yyextra->current->name; - } - else - { - BEGIN( EndFuncPtr ); - } - } - } -<FuncPtr>. { - //printf("error: FuncPtr '%c' unexpected at line %d of %s\n",*yytext,yyextra->yyLineNr,yyextra->yyFileName); - } -<FuncPtrOperator>"("{BN}*")"{BN}*/"(" { - yyextra->current->name += yytext; - yyextra->current->name = yyextra->current->name.simplifyWhiteSpace(); - lineCount(yyscanner); - } -<FuncPtrOperator>\n { + if (yyextra->insidePHP) // reference parameter + { + REJECT + } + else + { + yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->current->bodyColumn = yyextra->yyColNr; + lineCount(yyscanner); + addType(yyscanner); + yyextra->funcPtrType=yytext; + yyextra->roundCount=0; + //yyextra->current->type += yytext; + BEGIN( FuncPtr ); + } + } +<FuncPtr>{SCOPENAME} { + yyextra->current->name = yytext; + if (nameIsOperator(yyextra->current->name)) + { + BEGIN( FuncPtrOperator ); + } + else + { + if (yyextra->current->name=="const" || yyextra->current->name=="volatile") + { + yyextra->funcPtrType += yyextra->current->name; + } + else + { + BEGIN( EndFuncPtr ); + } + } + } +<FuncPtr>. { + //printf("error: FuncPtr '%c' unexpected at line %d of %s\n",*yytext,yyextra->yyLineNr,yyextra->yyFileName); + } +<FuncPtrOperator>"("{BN}*")"{BN}*/"(" { + yyextra->current->name += yytext; + yyextra->current->name = yyextra->current->name.simplifyWhiteSpace(); + lineCount(yyscanner); + } +<FuncPtrOperator>\n { lineCount(yyscanner); - yyextra->current->name += *yytext; - } -<FuncPtrOperator>"(" { - unput(*yytext); - BEGIN( EndFuncPtr ); - } -<FuncPtrOperator>. { - yyextra->current->name += *yytext; - } -<EndFuncPtr>")"{BN}*/";" { // a variable with extra braces - lineCount(yyscanner); - yyextra->current->type+=yyextra->funcPtrType.data()+1; - BEGIN(FindMembers); - } -<EndFuncPtr>")"{BN}*/"(" { // a function pointer - lineCount(yyscanner); - yyextra->current->type+=yyextra->funcPtrType+")"; - BEGIN(FindMembers); - } -<EndFuncPtr>")"{BN}*/"[" { // an array of variables - lineCount(yyscanner); - yyextra->current->type+=yyextra->funcPtrType.data(); - yyextra->current->args += ")"; - BEGIN(FindMembers); - } -<EndFuncPtr>"(" { // a function returning a function or + yyextra->current->name += *yytext; + } +<FuncPtrOperator>"(" { + unput(*yytext); + BEGIN( EndFuncPtr ); + } +<FuncPtrOperator>. { + yyextra->current->name += *yytext; + } +<EndFuncPtr>")"{BN}*/";" { // a variable with extra braces + lineCount(yyscanner); + yyextra->current->type+=yyextra->funcPtrType.data()+1; + BEGIN(FindMembers); + } +<EndFuncPtr>")"{BN}*/"(" { // a function pointer + lineCount(yyscanner); + yyextra->current->type+=yyextra->funcPtrType+")"; + BEGIN(FindMembers); + } +<EndFuncPtr>")"{BN}*/"[" { // an array of variables + lineCount(yyscanner); + yyextra->current->type+=yyextra->funcPtrType.data(); + yyextra->current->args += ")"; + BEGIN(FindMembers); + } +<EndFuncPtr>"(" { // a function returning a function or // a function returning a pointer to an array - yyextra->current->args += *yytext ; - //yyextra->roundCount=0; - //BEGIN( FuncFunc ); - yyextra->current->bodyLine = yyextra->yyLineNr; - yyextra->current->bodyColumn = yyextra->yyColNr; - yyextra->currentArgumentContext = FuncFuncEnd; - yyextra->fullArgString=yyextra->current->args.copy(); - yyextra->copyArgString=&yyextra->current->args; - BEGIN( ReadFuncArgType ) ; - } -<EndFuncPtr>"["[^\n\]]*"]" { - yyextra->funcPtrType+=yytext; - } -<EndFuncPtr>")" { - BEGIN(FindMembers); - } -<FuncFunc>"(" { - yyextra->current->args += *yytext ; - ++yyextra->roundCount; - } -<FuncFunc>")" { - yyextra->current->args += *yytext ; - if ( yyextra->roundCount ) - --yyextra->roundCount; - else - { - BEGIN(FuncFuncEnd); - } - } -<FuncFuncEnd>")"{BN}*"(" { - lineCount(yyscanner); - yyextra->current->type+=yyextra->funcPtrType+")("; - BEGIN(FuncFuncType); - } -<FuncFuncEnd>")"{BN}*/[;{] { - lineCount(yyscanner); - yyextra->current->type+=yyextra->funcPtrType.data()+1; - BEGIN(Function); - } -<FuncFuncEnd>")"{BN}*/"[" { // function returning a pointer to an array + yyextra->current->args += *yytext ; + //yyextra->roundCount=0; + //BEGIN( FuncFunc ); + yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->current->bodyColumn = yyextra->yyColNr; + yyextra->currentArgumentContext = FuncFuncEnd; + yyextra->fullArgString=yyextra->current->args.copy(); + yyextra->copyArgString=&yyextra->current->args; + BEGIN( ReadFuncArgType ) ; + } +<EndFuncPtr>"["[^\n\]]*"]" { + yyextra->funcPtrType+=yytext; + } +<EndFuncPtr>")" { + BEGIN(FindMembers); + } +<FuncFunc>"(" { + yyextra->current->args += *yytext ; + ++yyextra->roundCount; + } +<FuncFunc>")" { + yyextra->current->args += *yytext ; + if ( yyextra->roundCount ) + --yyextra->roundCount; + else + { + BEGIN(FuncFuncEnd); + } + } +<FuncFuncEnd>")"{BN}*"(" { lineCount(yyscanner); - yyextra->current->type+=yyextra->funcPtrType; - yyextra->current->args+=")"; - BEGIN(FuncFuncArray); - } -<FuncFuncEnd>. { - yyextra->current->args += *yytext; - } -<FuncFuncType>"(" { - yyextra->current->type += *yytext; - yyextra->roundCount++; - } -<FuncFuncType>")" { - yyextra->current->type += *yytext; - if (yyextra->roundCount) - --yyextra->roundCount; - else - BEGIN(Function); - } -<FuncFuncType>{BN}*","{BN}* { lineCount(yyscanner) ; yyextra->current->type += ", " ; } -<FuncFuncType>{BN}+ { lineCount(yyscanner) ; yyextra->current->type += ' ' ; } -<FuncFuncType>. { - yyextra->current->type += *yytext; - } + yyextra->current->type+=yyextra->funcPtrType+")("; + BEGIN(FuncFuncType); + } +<FuncFuncEnd>")"{BN}*/[;{] { + lineCount(yyscanner); + yyextra->current->type+=yyextra->funcPtrType.data()+1; + BEGIN(Function); + } +<FuncFuncEnd>")"{BN}*/"[" { // function returning a pointer to an array + lineCount(yyscanner); + yyextra->current->type+=yyextra->funcPtrType; + yyextra->current->args+=")"; + BEGIN(FuncFuncArray); + } +<FuncFuncEnd>. { + yyextra->current->args += *yytext; + } +<FuncFuncType>"(" { + yyextra->current->type += *yytext; + yyextra->roundCount++; + } +<FuncFuncType>")" { + yyextra->current->type += *yytext; + if (yyextra->roundCount) + --yyextra->roundCount; + else + BEGIN(Function); + } +<FuncFuncType>{BN}*","{BN}* { lineCount(yyscanner) ; yyextra->current->type += ", " ; } +<FuncFuncType>{BN}+ { lineCount(yyscanner) ; yyextra->current->type += ' ' ; } +<FuncFuncType>. { + yyextra->current->type += *yytext; + } <FindMembers>"("/{BN}*{ID}{BN}*"*"{BN}*{ID}*")"{BN}*"(" { // for catching typedef void (__stdcall *f)() like definitions - if (yyextra->current->type.left(7)=="typedef" && yyextra->current->bodyLine==-1) - // the bodyLine check is to prevent this guard to be true more than once - { - yyextra->current->bodyLine = yyextra->yyLineNr; - yyextra->current->bodyColumn = yyextra->yyColNr; - BEGIN( GetCallType ); - } - else if (!yyextra->current->name.isEmpty()) // normal function - { - yyextra->current->args = yytext; - yyextra->current->bodyLine = yyextra->yyLineNr; - yyextra->current->bodyColumn = yyextra->yyColNr; - yyextra->currentArgumentContext = FuncQual; - yyextra->fullArgString=yyextra->current->args.copy(); - yyextra->copyArgString=&yyextra->current->args; - BEGIN( ReadFuncArgType ) ; - //printf(">>> Read function arguments!\n"); - } - } -<GetCallType>{BN}*{ID}{BN}*"*" { - lineCount(yyscanner); - addType(yyscanner); - yyextra->funcPtrType="("; - yyextra->funcPtrType+=yytext; - yyextra->roundCount=0; - BEGIN( FuncPtr ); - } -<FindMembers>"(" { + if (yyextra->current->type.left(7)=="typedef" && yyextra->current->bodyLine==-1) + // the bodyLine check is to prevent this guard to be true more than once + { + yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->current->bodyColumn = yyextra->yyColNr; + BEGIN( GetCallType ); + } + else if (!yyextra->current->name.isEmpty()) // normal function + { + yyextra->current->args = yytext; + yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->current->bodyColumn = yyextra->yyColNr; + yyextra->currentArgumentContext = FuncQual; + yyextra->fullArgString=yyextra->current->args.copy(); + yyextra->copyArgString=&yyextra->current->args; + BEGIN( ReadFuncArgType ) ; + //printf(">>> Read function arguments!\n"); + } + } +<GetCallType>{BN}*{ID}{BN}*"*" { + lineCount(yyscanner); + addType(yyscanner); + yyextra->funcPtrType="("; + yyextra->funcPtrType+=yytext; + yyextra->roundCount=0; + BEGIN( FuncPtr ); + } +<FindMembers>"(" { if (!yyextra->current->name.isEmpty()) - { - yyextra->current->args = yytext; - yyextra->current->bodyLine = yyextra->yyLineNr; - yyextra->current->bodyColumn = yyextra->yyColNr; - yyextra->currentArgumentContext = FuncQual; - yyextra->fullArgString=yyextra->current->args.copy(); - yyextra->copyArgString=&yyextra->current->args; - BEGIN( ReadFuncArgType ) ; - //printf(">>> Read function arguments yyextra->current->argList.size()=%d\n",yyextra->current->argList.size()); - } - } + { + yyextra->current->args = yytext; + yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->current->bodyColumn = yyextra->yyColNr; + yyextra->currentArgumentContext = FuncQual; + yyextra->fullArgString=yyextra->current->args.copy(); + yyextra->copyArgString=&yyextra->current->args; + BEGIN( ReadFuncArgType ) ; + //printf(">>> Read function arguments yyextra->current->argList.size()=%d\n",yyextra->current->argList.size()); + } + } /* -<FindMembers>"("{BN}*("void"{BN}*)?")" { - lineCount(yyscanner); - yyextra->current->args = "()"; - BEGIN( FuncQual ); - } +<FindMembers>"("{BN}*("void"{BN}*)?")" { + lineCount(yyscanner); + yyextra->current->args = "()"; + BEGIN( FuncQual ); + } */ /*- Function argument reading rules ---------------------------------------*/ -<ReadFuncArgType>[^ \/\r\t\n\)\(\"\'#]+ { *yyextra->copyArgString+=yytext; - yyextra->fullArgString+=yytext; - } -<CopyArgString,CopyArgPHPString>[^\n\\\"\']+ { *yyextra->copyArgString+=yytext; - yyextra->fullArgString+=yytext; - } -<CopyArgRound>[^\/\n\)\(\"\']+ { - *yyextra->copyArgString+=yytext; - yyextra->fullArgString+=yytext; - } -<ReadFuncArgType,ReadTempArgs>{BN}* { - *yyextra->copyArgString+=" "; - yyextra->fullArgString+=" "; - lineCount(yyscanner); - } -<ReadFuncArgType,CopyArgRound,CopyArgSharp,ReadTempArgs>{RAWBEGIN} { +<ReadFuncArgType>[^ \/\r\t\n\)\(\"\'#]+ { *yyextra->copyArgString+=yytext; + yyextra->fullArgString+=yytext; + } +<CopyArgString,CopyArgPHPString>[^\n\\\"\']+ { *yyextra->copyArgString+=yytext; + yyextra->fullArgString+=yytext; + } +<CopyArgRound>[^\/\n\)\(\"\']+ { + *yyextra->copyArgString+=yytext; + yyextra->fullArgString+=yytext; + } +<ReadFuncArgType,ReadTempArgs>{BN}* { + *yyextra->copyArgString+=" "; + yyextra->fullArgString+=" "; + lineCount(yyscanner); + } +<ReadFuncArgType,CopyArgRound,CopyArgSharp,ReadTempArgs>{RAWBEGIN} { yyextra->delimiter = yytext+2; yyextra->delimiter=yyextra->delimiter.left(yyextra->delimiter.length()-1); yyextra->lastRawStringContext = YY_START; yyextra->pCopyRawString = yyextra->copyArgString; *yyextra->pCopyRawString+=yytext; - yyextra->fullArgString+=yytext; + yyextra->fullArgString+=yytext; BEGIN(RawString); } -<ReadFuncArgType,CopyArgRound,CopyArgSharp,ReadTempArgs>\" { - *yyextra->copyArgString+=*yytext; - yyextra->fullArgString+=*yytext; - yyextra->lastCopyArgStringContext = YY_START; - BEGIN( CopyArgString ); - } -<ReadFuncArgType,ReadTempArgs>"(" { - *yyextra->copyArgString+=*yytext; - yyextra->fullArgString+=*yytext; - yyextra->argRoundCount=0; - yyextra->lastCopyArgContext = YY_START; - BEGIN( CopyArgRound ); - } -<ReadFuncArgType>")" { - *yyextra->copyArgString+=*yytext; - yyextra->fullArgString+=*yytext; +<ReadFuncArgType,CopyArgRound,CopyArgSharp,ReadTempArgs>\" { + *yyextra->copyArgString+=*yytext; + yyextra->fullArgString+=*yytext; + yyextra->lastCopyArgStringContext = YY_START; + BEGIN( CopyArgString ); + } +<ReadFuncArgType,ReadTempArgs>"(" { + *yyextra->copyArgString+=*yytext; + yyextra->fullArgString+=*yytext; + yyextra->argRoundCount=0; + yyextra->lastCopyArgContext = YY_START; + BEGIN( CopyArgRound ); + } +<ReadFuncArgType>")" { + *yyextra->copyArgString+=*yytext; + yyextra->fullArgString+=*yytext; yyextra->current->argList = *stringToArgumentList(yyextra->language, yyextra->fullArgString); - if (yyextra->insideJS) - { - fixArgumentListForJavaScript(yyextra->current->argList); - } + if (yyextra->insideJS) + { + fixArgumentListForJavaScript(yyextra->current->argList); + } handleParametersCommentBlocks(yyscanner,yyextra->current->argList); - /* remember the yyextra->current documentation block, since - we could overwrite it with the documentation of - a function argument, which we then have to correct later - on - */ - yyextra->docBackup = yyextra->current->doc; - yyextra->briefBackup = yyextra->current->brief; + /* remember the yyextra->current documentation block, since + we could overwrite it with the documentation of + a function argument, which we then have to correct later + on + */ + yyextra->docBackup = yyextra->current->doc; + yyextra->briefBackup = yyextra->current->brief; - BEGIN( yyextra->currentArgumentContext ); - } - /* a special comment */ -<ReadFuncArgType,ReadTempArgs>("/*"[*!]|"//"[/!])("<"?) { + BEGIN( yyextra->currentArgumentContext ); + } + /* a special comment */ +<ReadFuncArgType,ReadTempArgs>("/*"[*!]|"//"[/!])("<"?) { if (yyextra->currentArgumentContext==DefineEnd) - { - // for defines we interpret a comment - // as documentation for the define - int i;for (i=(int)yyleng-1;i>=0;i--) - { - unput(yytext[i]); - } + { + // for defines we interpret a comment + // as documentation for the define + int i;for (i=(int)yyleng-1;i>=0;i--) + { + unput(yytext[i]); + } yyextra->current->argList = *stringToArgumentList(yyextra->language, yyextra->fullArgString); handleParametersCommentBlocks(yyscanner,yyextra->current->argList); - BEGIN( yyextra->currentArgumentContext ); - } - else // not a define - { - // for functions we interpret a comment - // as documentation for the argument - yyextra->fullArgString+=yytext; - yyextra->lastCopyArgChar=0; - yyextra->lastCommentInArgContext=YY_START; - if (yytext[1]=='/') - BEGIN( CopyArgCommentLine ); - else - BEGIN( CopyArgComment ); - } - } - /* a non-special comment */ -<ReadFuncArgType,ReadTempArgs>"/**/" { /* empty comment */ } -<ReadFuncArgType,ReadTempArgs>"/*" { - yyextra->lastCContext = YY_START; - BEGIN( SkipComment ); - } -<ReadFuncArgType,ReadTempArgs>"//" { - yyextra->lastCContext = YY_START; - BEGIN( SkipCxxComment ); - } + BEGIN( yyextra->currentArgumentContext ); + } + else // not a define + { + // for functions we interpret a comment + // as documentation for the argument + yyextra->fullArgString+=yytext; + yyextra->lastCopyArgChar=0; + yyextra->lastCommentInArgContext=YY_START; + if (yytext[1]=='/') + BEGIN( CopyArgCommentLine ); + else + BEGIN( CopyArgComment ); + } + } + /* a non-special comment */ +<ReadFuncArgType,ReadTempArgs>"/**/" { /* empty comment */ } +<ReadFuncArgType,ReadTempArgs>"/*" { + yyextra->lastCContext = YY_START; + BEGIN( SkipComment ); + } +<ReadFuncArgType,ReadTempArgs>"//" { + yyextra->lastCContext = YY_START; + BEGIN( SkipCxxComment ); + } /* -<ReadFuncArgType,ReadTempArgs>"'#" { if (yyextra->insidePHP) +<ReadFuncArgType,ReadTempArgs>"'#" { if (yyextra->insidePHP) REJECT; - *yyextra->copyArgString+=yytext; - yyextra->fullArgString+=yytext; - } -<ReadFuncArgType,ReadTempArgs>"#" { - if (!yyextra->insidePHP) - REJECT; - yyextra->lastCContext = YY_START; - BEGIN( SkipCxxComment ); - } + *yyextra->copyArgString+=yytext; + yyextra->fullArgString+=yytext; + } +<ReadFuncArgType,ReadTempArgs>"#" { + if (!yyextra->insidePHP) + REJECT; + yyextra->lastCContext = YY_START; + BEGIN( SkipCxxComment ); + } */ - /* ')' followed by a special comment */ -<ReadFuncArgType>")"{BN}*("/*"[*!]|"//"[/!])"<" { - lineCount(yyscanner); + /* ')' followed by a special comment */ +<ReadFuncArgType>")"{BN}*("/*"[*!]|"//"[/!])"<" { + lineCount(yyscanner); if (yyextra->currentArgumentContext==DefineEnd) - { - // for defines we interpret a comment - // as documentation for the define - int i;for (i=(int)yyleng-1;i>0;i--) - { - unput(yytext[i]); - } - *yyextra->copyArgString+=*yytext; - yyextra->fullArgString+=*yytext; + { + // for defines we interpret a comment + // as documentation for the define + int i;for (i=(int)yyleng-1;i>0;i--) + { + unput(yytext[i]); + } + *yyextra->copyArgString+=*yytext; + yyextra->fullArgString+=*yytext; yyextra->current->argList = *stringToArgumentList(yyextra->language, yyextra->fullArgString); handleParametersCommentBlocks(yyscanner,yyextra->current->argList); - BEGIN( yyextra->currentArgumentContext ); - } - else - { - // for functions we interpret a comment - // as documentation for the yyextra->last argument - yyextra->lastCopyArgChar=*yytext; - QCString text=&yytext[1]; - text=text.stripWhiteSpace(); - yyextra->lastCommentInArgContext=YY_START; - yyextra->fullArgString+=text; - if (text.find("//")!=-1) - BEGIN( CopyArgCommentLine ); - else - BEGIN( CopyArgComment ); - } - } -<CopyArgComment>^{B}*"*"+/{BN}+ -<CopyArgComment>[^\n\\\@\*]+ { yyextra->fullArgString+=yytext; } -<CopyArgComment>"*/" { yyextra->fullArgString+=yytext; - if (yyextra->lastCopyArgChar!=0) - unput(yyextra->lastCopyArgChar); - BEGIN( yyextra->lastCommentInArgContext ); - } -<CopyArgCommentLine>\n { yyextra->fullArgString+=yytext; + BEGIN( yyextra->currentArgumentContext ); + } + else + { + // for functions we interpret a comment + // as documentation for the yyextra->last argument + yyextra->lastCopyArgChar=*yytext; + QCString text=&yytext[1]; + text=text.stripWhiteSpace(); + yyextra->lastCommentInArgContext=YY_START; + yyextra->fullArgString+=text; + if (text.find("//")!=-1) + BEGIN( CopyArgCommentLine ); + else + BEGIN( CopyArgComment ); + } + } +<CopyArgComment>^{B}*"*"+/{BN}+ +<CopyArgComment>[^\n\\\@\*]+ { yyextra->fullArgString+=yytext; } +<CopyArgComment>"*/" { yyextra->fullArgString+=yytext; + if (yyextra->lastCopyArgChar!=0) + unput(yyextra->lastCopyArgChar); + BEGIN( yyextra->lastCommentInArgContext ); + } +<CopyArgCommentLine>\n { yyextra->fullArgString+=yytext; lineCount(yyscanner); - if (yyextra->lastCopyArgChar!=0) - unput(yyextra->lastCopyArgChar); - BEGIN( yyextra->lastCommentInArgContext ); - } -<CopyArgCommentLine>{CMD}("verbatim"|"latexonly"|"htmlonly"|"xmlonly"|"manonly"|"rtfonly"|"docbookonly"|"dot"|"code")/[^a-z_A-Z0-9\-] { // verbatim command (which could contain nested comments!) - yyextra->docBlockName=&yytext[1]; - yyextra->fullArgString+=yytext; - BEGIN(CopyArgVerbatim); - } -<CopyArgCommentLine>{CMD}("f$"|"f["|"f{") { - yyextra->docBlockName=&yytext[1]; - if (yyextra->docBlockName.at(1)=='[') - { - yyextra->docBlockName.at(1)='}'; - } - if (yyextra->docBlockName.at(1)=='{') - { - yyextra->docBlockName.at(1)='}'; - } - yyextra->fullArgString+=yytext; - BEGIN(CopyArgVerbatim); + if (yyextra->lastCopyArgChar!=0) + unput(yyextra->lastCopyArgChar); + BEGIN( yyextra->lastCommentInArgContext ); + } +<CopyArgCommentLine>{CMD}("verbatim"|"latexonly"|"htmlonly"|"xmlonly"|"manonly"|"rtfonly"|"docbookonly"|"dot"|"code")/[^a-z_A-Z0-9\-] { // verbatim command (which could contain nested comments!) + yyextra->docBlockName=&yytext[1]; + yyextra->fullArgString+=yytext; + BEGIN(CopyArgVerbatim); + } +<CopyArgCommentLine>{CMD}("f$"|"f["|"f{") { + yyextra->docBlockName=&yytext[1]; + if (yyextra->docBlockName.at(1)=='[') + { + yyextra->docBlockName.at(1)='}'; + } + if (yyextra->docBlockName.at(1)=='{') + { + yyextra->docBlockName.at(1)='}'; + } + yyextra->fullArgString+=yytext; + BEGIN(CopyArgVerbatim); } <CopyArgVerbatim>[\\@]("endverbatim"|"endlatexonly"|"endhtmlonly"|"endxmlonly"|"enddocbookonly"|"endmanonly"|"endrtfonly"|"enddot"|"endcode"|"f$"|"f]"|"f}")/[^a-z_A-Z0-9\-] { // end of verbatim block - yyextra->fullArgString+=yytext; - if (yytext[1]=='f') // end of formula - { - BEGIN(CopyArgCommentLine); - } - if (&yytext[4]==yyextra->docBlockName) - { - BEGIN(CopyArgCommentLine); - } - } -<CopyArgCommentLine>[^\\\@\n]+ { yyextra->fullArgString+=yytext; } -<CopyArgCommentLine>. { yyextra->fullArgString+=*yytext; } -<CopyArgComment,CopyArgVerbatim>\n { yyextra->fullArgString+=*yytext; lineCount(yyscanner); } -<CopyArgComment,CopyArgVerbatim>. { yyextra->fullArgString+=*yytext; } + yyextra->fullArgString+=yytext; + if (yytext[1]=='f') // end of formula + { + BEGIN(CopyArgCommentLine); + } + if (&yytext[4]==yyextra->docBlockName) + { + BEGIN(CopyArgCommentLine); + } + } +<CopyArgCommentLine>[^\\\@\n]+ { yyextra->fullArgString+=yytext; } +<CopyArgCommentLine>. { yyextra->fullArgString+=*yytext; } +<CopyArgComment,CopyArgVerbatim>\n { yyextra->fullArgString+=*yytext; lineCount(yyscanner); } +<CopyArgComment,CopyArgVerbatim>. { yyextra->fullArgString+=*yytext; } <CopyArgComment>{CMD}("brief"|"short"){B}+ { - warn(yyextra->yyFileName,yyextra->yyLineNr, - "Ignoring %cbrief command inside argument documentation",*yytext - ); + warn(yyextra->yyFileName,yyextra->yyLineNr, + "Ignoring %cbrief command inside argument documentation",*yytext + ); yyextra->fullArgString+=' '; } -<ReadTempArgs>"<" { - *yyextra->copyArgString+=*yytext; - yyextra->fullArgString+=*yytext; - yyextra->argSharpCount=1; - BEGIN( CopyArgSharp ); - } -<ReadTempArgs>">" { - *yyextra->copyArgString+=*yytext; - yyextra->fullArgString+=*yytext; - //printf("end template list '%s'\n",yyextra->copyArgString->data()); +<ReadTempArgs>"<" { + *yyextra->copyArgString+=*yytext; + yyextra->fullArgString+=*yytext; + yyextra->argSharpCount=1; + BEGIN( CopyArgSharp ); + } +<ReadTempArgs>">" { + *yyextra->copyArgString+=*yytext; + yyextra->fullArgString+=*yytext; + //printf("end template list '%s'\n",yyextra->copyArgString->data()); *yyextra->currentArgumentList = *stringToArgumentList(yyextra->language, yyextra->fullArgString); - BEGIN( yyextra->currentArgumentContext ); - } -<CopyArgRound>"(" { - yyextra->argRoundCount++; - *yyextra->copyArgString+=*yytext; - yyextra->fullArgString+=*yytext; - } -<CopyArgRound>")" { - *yyextra->copyArgString+=*yytext; - yyextra->fullArgString+=*yytext; - if (yyextra->argRoundCount>0) - yyextra->argRoundCount--; - else - BEGIN( yyextra->lastCopyArgContext ); - } + BEGIN( yyextra->currentArgumentContext ); + } +<CopyArgRound>"(" { + yyextra->argRoundCount++; + *yyextra->copyArgString+=*yytext; + yyextra->fullArgString+=*yytext; + } +<CopyArgRound>")" { + *yyextra->copyArgString+=*yytext; + yyextra->fullArgString+=*yytext; + if (yyextra->argRoundCount>0) + yyextra->argRoundCount--; + else + BEGIN( yyextra->lastCopyArgContext ); + } <CopyArgSharp>"(" { - *yyextra->copyArgString+=*yytext; - yyextra->fullArgString+=*yytext; - yyextra->argRoundCount=0; - yyextra->lastCopyArgContext = YY_START; - BEGIN( CopyArgRound ); - } -<CopyArgSharp>"<" { - yyextra->argSharpCount++; - //printf("yyextra->argSharpCount++=%d copy\n",yyextra->argSharpCount); - *yyextra->copyArgString+=*yytext; - yyextra->fullArgString+=*yytext; - } -<CopyArgSharp>">" { - *yyextra->copyArgString+=*yytext; - yyextra->fullArgString+=*yytext; - yyextra->argSharpCount--; - if (yyextra->argSharpCount>0) - { - //printf("yyextra->argSharpCount--=%d copy\n",yyextra->argSharpCount); - } - else - { - BEGIN( ReadTempArgs ); - //printf("end of yyextra->argSharpCount\n"); - } - } -<CopyArgString,CopyArgPHPString>\\. { - *yyextra->copyArgString+=yytext; - yyextra->fullArgString+=yytext; - } -<CopyArgString>\" { - *yyextra->copyArgString+=*yytext; - yyextra->fullArgString+=*yytext; - BEGIN( yyextra->lastCopyArgStringContext ); - } -<CopyArgPHPString>\' { - *yyextra->copyArgString+=*yytext; - yyextra->fullArgString+=*yytext; - BEGIN( yyextra->lastCopyArgStringContext ); - } -<ReadFuncArgType,ReadTempArgs,CopyArgRound,CopyArgSharp>{CHARLIT} { + *yyextra->copyArgString+=*yytext; + yyextra->fullArgString+=*yytext; + yyextra->argRoundCount=0; + yyextra->lastCopyArgContext = YY_START; + BEGIN( CopyArgRound ); + } +<CopyArgSharp>"<" { + yyextra->argSharpCount++; + //printf("yyextra->argSharpCount++=%d copy\n",yyextra->argSharpCount); + *yyextra->copyArgString+=*yytext; + yyextra->fullArgString+=*yytext; + } +<CopyArgSharp>">" { + *yyextra->copyArgString+=*yytext; + yyextra->fullArgString+=*yytext; + yyextra->argSharpCount--; + if (yyextra->argSharpCount>0) + { + //printf("yyextra->argSharpCount--=%d copy\n",yyextra->argSharpCount); + } + else + { + BEGIN( ReadTempArgs ); + //printf("end of yyextra->argSharpCount\n"); + } + } +<CopyArgString,CopyArgPHPString>\\. { + *yyextra->copyArgString+=yytext; + yyextra->fullArgString+=yytext; + } +<CopyArgString>\" { + *yyextra->copyArgString+=*yytext; + yyextra->fullArgString+=*yytext; + BEGIN( yyextra->lastCopyArgStringContext ); + } +<CopyArgPHPString>\' { + *yyextra->copyArgString+=*yytext; + yyextra->fullArgString+=*yytext; + BEGIN( yyextra->lastCopyArgStringContext ); + } +<ReadFuncArgType,ReadTempArgs,CopyArgRound,CopyArgSharp>{CHARLIT} { if (yyextra->insidePHP) - { - REJECT; - } - else - { - *yyextra->copyArgString+=yytext; - yyextra->fullArgString+=yytext; - } - } -<ReadFuncArgType,ReadTempArgs,CopyArgRound,CopyArgSharp>\' { - *yyextra->copyArgString+=yytext; - yyextra->fullArgString+=yytext; - if (yyextra->insidePHP) - { - yyextra->lastCopyArgStringContext=YY_START; - BEGIN(CopyArgPHPString); - } - } -<ReadFuncArgType,ReadTempArgs,CopyArgString,CopyArgPHPString,CopyArgRound,CopyArgSharp>\n { + { + REJECT; + } + else + { + *yyextra->copyArgString+=yytext; + yyextra->fullArgString+=yytext; + } + } +<ReadFuncArgType,ReadTempArgs,CopyArgRound,CopyArgSharp>\' { + *yyextra->copyArgString+=yytext; + yyextra->fullArgString+=yytext; + if (yyextra->insidePHP) + { + yyextra->lastCopyArgStringContext=YY_START; + BEGIN(CopyArgPHPString); + } + } +<ReadFuncArgType,ReadTempArgs,CopyArgString,CopyArgPHPString,CopyArgRound,CopyArgSharp>\n { lineCount(yyscanner); - *yyextra->copyArgString+=*yytext; - yyextra->fullArgString+=*yytext; - } -<ReadFuncArgType,ReadTempArgs,CopyArgString,CopyArgPHPString,CopyArgRound,CopyArgSharp>. { - *yyextra->copyArgString+=*yytext; - yyextra->fullArgString+=*yytext; - } + *yyextra->copyArgString+=*yytext; + yyextra->fullArgString+=*yytext; + } +<ReadFuncArgType,ReadTempArgs,CopyArgString,CopyArgPHPString,CopyArgRound,CopyArgSharp>. { + *yyextra->copyArgString+=*yytext; + yyextra->fullArgString+=*yytext; + } /*------------------------------------------------------------------------*/ -<FuncRound>"(" { yyextra->current->args += *yytext ; - ++yyextra->roundCount ; - } -<FuncRound>")" { yyextra->current->args += *yytext ; - if ( yyextra->roundCount ) - --yyextra->roundCount ; - else - BEGIN( FuncQual ) ; - } +<FuncRound>"(" { yyextra->current->args += *yytext ; + ++yyextra->roundCount ; + } +<FuncRound>")" { yyextra->current->args += *yytext ; + if ( yyextra->roundCount ) + --yyextra->roundCount ; + else + BEGIN( FuncQual ) ; + } /* -<FuncQual>"#" { if (yyextra->insidePHP) - REJECT; - yyextra->lastCPPContext = YY_START; - BEGIN(SkipCPP); - } +<FuncQual>"#" { if (yyextra->insidePHP) + REJECT; + yyextra->lastCPPContext = YY_START; + BEGIN(SkipCPP); + } */ <FuncQual>[{:;,] { - if ( qstrcmp(yytext,";")==0 && - yyextra->insidePHP && - !containsWord(yyextra->current->type,"function") ) + if ( qstrcmp(yytext,";")==0 && + yyextra->insidePHP && + !containsWord(yyextra->current->type,"function") ) { yyextra->current->reset(); initEntry(yyscanner); @@ -4515,54 +4515,54 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) } } <FuncQual>{BN}*"abstract"{BN}* { // pure virtual member function - lineCount(yyscanner) ; + lineCount(yyscanner) ; yyextra->current->virt = Pure; - yyextra->current->args += " override "; + yyextra->current->args += " override "; } <FuncQual,TrailingReturn>{BN}*"override"{BN}* { // C++11 overridden virtual member function - lineCount(yyscanner) ; + lineCount(yyscanner) ; yyextra->current->spec |= Entry::Override; - yyextra->current->args += " override "; + yyextra->current->args += " override "; BEGIN(FuncQual); } <FuncQual,TrailingReturn>{BN}*"final"{BN}* { // C++11 final method - lineCount(yyscanner) ; + lineCount(yyscanner) ; yyextra->current->spec |= Entry::Final; - yyextra->current->args += " final "; + yyextra->current->args += " final "; BEGIN(FuncQual); } <FuncQual>{BN}*"sealed"{BN}* { // sealed member function - lineCount(yyscanner) ; + lineCount(yyscanner) ; yyextra->current->spec |= Entry::Sealed; - yyextra->current->args += " sealed "; + yyextra->current->args += " sealed "; } <FuncQual>{BN}*"new"{BN}* { // new member function - lineCount(yyscanner) ; + lineCount(yyscanner) ; yyextra->current->spec |= Entry::New; - yyextra->current->args += " new "; + yyextra->current->args += " new "; } -<FuncQual>{BN}*"const"{BN}* { // const member function - lineCount(yyscanner) ; - yyextra->current->args += " const "; - yyextra->current->argList.setConstSpecifier(TRUE); - } -<FuncQual>{BN}*"volatile"{BN}* { // volatile member function - lineCount(yyscanner) ; - yyextra->current->args += " volatile "; - yyextra->current->argList.setVolatileSpecifier(TRUE); - } -<FuncQual>{BN}*"noexcept"{BN}* { // noexcept qualifier - lineCount(yyscanner) ; - yyextra->current->args += " noexcept "; - yyextra->current->spec |= Entry::NoExcept; - } -<FuncQual>{BN}*"noexcept"{BN}*"(" { // noexcept expression - lineCount(yyscanner) ; - yyextra->current->args += " noexcept("; - yyextra->current->spec |= Entry::NoExcept; - yyextra->lastRoundContext=FuncQual; - yyextra->pCopyRoundString=&yyextra->current->args; - yyextra->roundCount=0; +<FuncQual>{BN}*"const"{BN}* { // const member function + lineCount(yyscanner) ; + yyextra->current->args += " const "; + yyextra->current->argList.setConstSpecifier(TRUE); + } +<FuncQual>{BN}*"volatile"{BN}* { // volatile member function + lineCount(yyscanner) ; + yyextra->current->args += " volatile "; + yyextra->current->argList.setVolatileSpecifier(TRUE); + } +<FuncQual>{BN}*"noexcept"{BN}* { // noexcept qualifier + lineCount(yyscanner) ; + yyextra->current->args += " noexcept "; + yyextra->current->spec |= Entry::NoExcept; + } +<FuncQual>{BN}*"noexcept"{BN}*"(" { // noexcept expression + lineCount(yyscanner) ; + yyextra->current->args += " noexcept("; + yyextra->current->spec |= Entry::NoExcept; + yyextra->lastRoundContext=FuncQual; + yyextra->pCopyRoundString=&yyextra->current->args; + yyextra->roundCount=0; BEGIN(CopyRound); } <FuncQual>{BN}*"&" { @@ -4574,36 +4574,57 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) yyextra->current->argList.setRefQualifier(RefQualifierRValue); } -<FuncQual,TrailingReturn>{BN}*"="{BN}*"0"{BN}* { // pure virtual member function - lineCount(yyscanner) ; - yyextra->current->args += " = 0"; - yyextra->current->virt = Pure; - yyextra->current->argList.setPureSpecifier(TRUE); +<FuncQual,TrailingReturn>{BN}*"="{BN}*"0"{BN}* { // pure virtual member function + lineCount(yyscanner) ; + yyextra->current->args += " = 0"; + yyextra->current->virt = Pure; + yyextra->current->argList.setPureSpecifier(TRUE); BEGIN(FuncQual); - } + } <FuncQual,TrailingReturn>{BN}*"="{BN}*"delete"{BN}* { // C++11 explicitly delete member lineCount(yyscanner); yyextra->current->args += " = delete"; - yyextra->current->spec |= Entry::Delete; - yyextra->current->argList.setIsDeleted(TRUE); + yyextra->current->spec |= Entry::Delete; + yyextra->current->argList.setIsDeleted(TRUE); BEGIN(FuncQual); } <FuncQual,TrailingReturn>{BN}*"="{BN}*"default"{BN}* { // C++11 explicitly defaulted constructor/assignment operator lineCount(yyscanner); yyextra->current->args += " = default"; - yyextra->current->spec |= Entry::Default; + yyextra->current->spec |= Entry::Default; BEGIN(FuncQual); } <FuncQual>{BN}*"->"{BN}* { lineCount(yyscanner); yyextra->current->argList.setTrailingReturnType(" -> "); yyextra->current->args += " -> "; + yyextra->roundCount=0; BEGIN(TrailingReturn); } <TrailingReturn>[{;] { + if (yyextra->roundCount>0) REJECT; unput(*yytext); BEGIN(FuncQual); } +<TrailingReturn>"(" { + yyextra->roundCount++; + yyextra->current->argList.setTrailingReturnType(yyextra->current->argList.trailingReturnType()+yytext); + yyextra->current->args+=yytext; + } +<TrailingReturn>")" { + if (yyextra->roundCount>0) + { + yyextra->roundCount--; + } + else + { + warn(yyextra->yyFileName,yyextra->yyLineNr, + "Found ')' without opening '(' for trailing return type '%s)...'", + yyextra->current->argList.trailingReturnType().data()); + } + yyextra->current->argList.setTrailingReturnType(yyextra->current->argList.trailingReturnType()+yytext); + yyextra->current->args+=yytext; + } <TrailingReturn>. { yyextra->current->argList.setTrailingReturnType(yyextra->current->argList.trailingReturnType()+yytext); yyextra->current->args+=yytext; @@ -4613,207 +4634,207 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) yyextra->current->argList.setTrailingReturnType(yyextra->current->argList.trailingReturnType()+yytext); yyextra->current->args+=' '; } -<FuncRound,FuncFunc>{BN}*","{BN}* { - lineCount(yyscanner) ; - yyextra->current->args += ", " ; - } -<FuncQual,FuncRound,FuncFunc>{BN}+ { - lineCount(yyscanner) ; - yyextra->current->args += ' ' ; - } +<FuncRound,FuncFunc>{BN}*","{BN}* { + lineCount(yyscanner) ; + yyextra->current->args += ", " ; + } +<FuncQual,FuncRound,FuncFunc>{BN}+ { + lineCount(yyscanner) ; + yyextra->current->args += ' ' ; + } <Function,FuncQual,FuncRound,FuncFunc>"#" { if (yyextra->insidePHP) - REJECT; - yyextra->lastCPPContext = YY_START; - BEGIN(SkipCPP); - } -<FuncQual>"=" { - if (yyextra->insideCli && - (yyextra->current_root->section&Entry::COMPOUND_MASK) - ) - { - BEGIN(CliOverride); - } - else - { + REJECT; + yyextra->lastCPPContext = YY_START; + BEGIN(SkipCPP); + } +<FuncQual>"=" { + if (yyextra->insideCli && + (yyextra->current_root->section&Entry::COMPOUND_MASK) + ) + { + BEGIN(CliOverride); + } + else + { // typically an initialized function pointer - yyextra->lastInitializerContext=YY_START; - yyextra->initBracketCount=0; + yyextra->lastInitializerContext=YY_START; + yyextra->initBracketCount=0; yyextra->current->initializer = yytext; - BEGIN(ReadInitializer); - } - } -<CliOverride>{ID} { - } -<CliOverride>"{" { - unput(*yytext); - BEGIN(FuncQual); - } -<CliOverride>\n { + BEGIN(ReadInitializer); + } + } +<CliOverride>{ID} { + } +<CliOverride>"{" { + unput(*yytext); + BEGIN(FuncQual); + } +<CliOverride>\n { lineCount(yyscanner); - } -<CliOverride>. { - } -<FuncPtrInit>[{;] { - unput(*yytext); - BEGIN(FuncQual); - } -<FuncPtrInit>\" { - yyextra->current->args += *yytext; - yyextra->pCopyQuotedString=&yyextra->current->args; - yyextra->lastStringContext=FuncPtrInit; - BEGIN(CopyString); - } -<FuncPtrInit>\' { - yyextra->current->args += *yytext; - if (yyextra->insidePHP) - { - yyextra->pCopyQuotedString=&yyextra->current->args; - yyextra->lastStringContext=FuncPtrInit; - BEGIN(CopyPHPString); - } - } -<FuncPtrInit>{CHARLIT} { + } +<CliOverride>. { + } +<FuncPtrInit>[{;] { + unput(*yytext); + BEGIN(FuncQual); + } +<FuncPtrInit>\" { + yyextra->current->args += *yytext; + yyextra->pCopyQuotedString=&yyextra->current->args; + yyextra->lastStringContext=FuncPtrInit; + BEGIN(CopyString); + } +<FuncPtrInit>\' { + yyextra->current->args += *yytext; if (yyextra->insidePHP) - { - REJECT; - } - else - { - yyextra->current->args += yytext; - } - } -<FuncPtrInit>{ID} { - yyextra->current->args += yytext; - } -<FuncPtrInit>. { - yyextra->current->args += *yytext; - } -<FuncPtrInit>\n { - yyextra->current->args += *yytext; + { + yyextra->pCopyQuotedString=&yyextra->current->args; + yyextra->lastStringContext=FuncPtrInit; + BEGIN(CopyPHPString); + } + } +<FuncPtrInit>{CHARLIT} { + if (yyextra->insidePHP) + { + REJECT; + } + else + { + yyextra->current->args += yytext; + } + } +<FuncPtrInit>{ID} { + yyextra->current->args += yytext; + } +<FuncPtrInit>. { + yyextra->current->args += *yytext; + } +<FuncPtrInit>\n { + yyextra->current->args += *yytext; lineCount(yyscanner); - } -<FuncQual>{ID} { // typically a K&R style C function + } +<FuncQual>{ID} { // typically a K&R style C function if (yyextra->insideCS && qstrcmp(yytext,"where")==0) - { - // type constraint for a method - yyextra->current->typeConstr.clear(); - yyextra->current->typeConstr.push_back(Argument()); - yyextra->lastCSConstraint = YY_START; - BEGIN( CSConstraintName ); - } - else if (checkForKnRstyleC(yyscanner)) - { - yyextra->current->args = yytext; - yyextra->oldStyleArgType.resize(0); - BEGIN(OldStyleArgs); - } - else - { - yyextra->current->args += yytext; - } - } -<OldStyleArgs>[,;] { - QCString oldStyleArgPtr; - QCString oldStyleArgName; - splitKnRArg(yyscanner,oldStyleArgPtr,oldStyleArgName); - QCString doc,brief; - if (yyextra->current->doc!=yyextra->docBackup) - { + { + // type constraint for a method + yyextra->current->typeConstr.clear(); + yyextra->current->typeConstr.push_back(Argument()); + yyextra->lastCSConstraint = YY_START; + BEGIN( CSConstraintName ); + } + else if (checkForKnRstyleC(yyscanner)) + { + yyextra->current->args = yytext; + yyextra->oldStyleArgType.resize(0); + BEGIN(OldStyleArgs); + } + else + { + yyextra->current->args += yytext; + } + } +<OldStyleArgs>[,;] { + QCString oldStyleArgPtr; + QCString oldStyleArgName; + splitKnRArg(yyscanner,oldStyleArgPtr,oldStyleArgName); + QCString doc,brief; + if (yyextra->current->doc!=yyextra->docBackup) + { doc=yyextra->current->doc.copy(); - yyextra->current->doc=yyextra->docBackup; - } - if (yyextra->current->brief!=yyextra->briefBackup) - { + yyextra->current->doc=yyextra->docBackup; + } + if (yyextra->current->brief!=yyextra->briefBackup) + { brief=yyextra->current->brief.copy(); - yyextra->current->brief=yyextra->briefBackup; - } - addKnRArgInfo(yyscanner,yyextra->oldStyleArgType+oldStyleArgPtr, - oldStyleArgName,brief,doc); - yyextra->current->args.resize(0); - if (*yytext==';') yyextra->oldStyleArgType.resize(0); - } -<OldStyleArgs>{ID} { yyextra->current->args += yytext; } -<OldStyleArgs>"{" { + yyextra->current->brief=yyextra->briefBackup; + } + addKnRArgInfo(yyscanner,yyextra->oldStyleArgType+oldStyleArgPtr, + oldStyleArgName,brief,doc); + yyextra->current->args.resize(0); + if (*yytext==';') yyextra->oldStyleArgType.resize(0); + } +<OldStyleArgs>{ID} { yyextra->current->args += yytext; } +<OldStyleArgs>"{" { if (yyextra->current->argList.empty()) { yyextra->current->argList.setNoParameters(TRUE); } - yyextra->current->args = argListToString(yyextra->current->argList); - unput('{'); - BEGIN(FuncQual); - } -<OldStyleArgs>. { yyextra->current->args += *yytext; } -<FuncQual,FuncRound,FuncFunc>. { yyextra->current->args += *yytext; } -<FuncQual>{BN}*"try:" | -<FuncQual>{BN}*"try"{BN}+ { /* try-function-block */ - yyextra->insideTryBlock=TRUE; - lineCount(yyscanner); - if (yytext[yyleng-1]==':') - { - unput(':'); - BEGIN( Function ); - } - } -<FuncQual>{BN}*"throw"{BN}*"(" { // C++ style throw clause - yyextra->current->exception = " throw (" ; - yyextra->roundCount=0; - lineCount(yyscanner) ; - BEGIN( ExcpRound ) ; - } + yyextra->current->args = argListToString(yyextra->current->argList); + unput('{'); + BEGIN(FuncQual); + } +<OldStyleArgs>. { yyextra->current->args += *yytext; } +<FuncQual,FuncRound,FuncFunc>. { yyextra->current->args += *yytext; } +<FuncQual>{BN}*"try:" | +<FuncQual>{BN}*"try"{BN}+ { /* try-function-block */ + yyextra->insideTryBlock=TRUE; + lineCount(yyscanner); + if (yytext[yyleng-1]==':') + { + unput(':'); + BEGIN( Function ); + } + } +<FuncQual>{BN}*"throw"{BN}*"(" { // C++ style throw clause + yyextra->current->exception = " throw (" ; + yyextra->roundCount=0; + lineCount(yyscanner) ; + BEGIN( ExcpRound ) ; + } <FuncQual>{BN}*"raises"{BN}*"(" { - yyextra->current->exception = " raises (" ; - lineCount(yyscanner) ; - yyextra->roundCount=0; - BEGIN( ExcpRound ) ; - } -<FuncQual>{BN}*"throws"{BN}+ { // Java style throw clause - yyextra->current->exception = " throws " ; - lineCount(yyscanner) ; - BEGIN( ExcpList ); - } -<ExcpRound>"(" { yyextra->current->exception += *yytext ; - ++yyextra->roundCount ; - } -<ExcpRound>")" { yyextra->current->exception += *yytext ; - if ( yyextra->roundCount ) - --yyextra->roundCount ; - else - BEGIN( FuncQual ) ; - } -<ExcpRound>. { - yyextra->current->exception += *yytext; - } -<ExcpList>"{" { - unput('{'); BEGIN( FuncQual ); - } -<ExcpList>";" { - unput(';'); BEGIN( FuncQual ); - } -<ExcpList>"\n" { - yyextra->current->exception += ' '; + yyextra->current->exception = " raises (" ; + lineCount(yyscanner) ; + yyextra->roundCount=0; + BEGIN( ExcpRound ) ; + } +<FuncQual>{BN}*"throws"{BN}+ { // Java style throw clause + yyextra->current->exception = " throws " ; + lineCount(yyscanner) ; + BEGIN( ExcpList ); + } +<ExcpRound>"(" { yyextra->current->exception += *yytext ; + ++yyextra->roundCount ; + } +<ExcpRound>")" { yyextra->current->exception += *yytext ; + if ( yyextra->roundCount ) + --yyextra->roundCount ; + else + BEGIN( FuncQual ) ; + } +<ExcpRound>. { + yyextra->current->exception += *yytext; + } +<ExcpList>"{" { + unput('{'); BEGIN( FuncQual ); + } +<ExcpList>";" { + unput(';'); BEGIN( FuncQual ); + } +<ExcpList>"\n" { + yyextra->current->exception += ' '; lineCount(yyscanner); - } -<ExcpList>. { - yyextra->current->exception += *yytext; - } -<Function>"(" { yyextra->current->type += yyextra->current->name ; - yyextra->current->name = yyextra->current->args ; - yyextra->current->args = yytext ; - yyextra->roundCount=0; - BEGIN( FuncRound ) ; - } -<Function>":" { - if (!yyextra->insidePHP) BEGIN(SkipInits); - } -<Function>[;{,] { - yyextra->current->name=yyextra->current->name.simplifyWhiteSpace(); - yyextra->current->type=yyextra->current->type.simplifyWhiteSpace(); - yyextra->current->args=removeRedundantWhiteSpace(yyextra->current->args); - // was: yyextra->current->args.simplifyWhiteSpace(); - yyextra->current->fileName = yyextra->yyFileName; - yyextra->current->startLine = yyextra->yyBegLineNr; - yyextra->current->startColumn = yyextra->yyBegColNr; - static QRegExp re("([^)]*[*&][^)]*)"); // (...*...) + } +<ExcpList>. { + yyextra->current->exception += *yytext; + } +<Function>"(" { yyextra->current->type += yyextra->current->name ; + yyextra->current->name = yyextra->current->args ; + yyextra->current->args = yytext ; + yyextra->roundCount=0; + BEGIN( FuncRound ) ; + } +<Function>":" { + if (!yyextra->insidePHP) BEGIN(SkipInits); + } +<Function>[;{,] { + yyextra->current->name=yyextra->current->name.simplifyWhiteSpace(); + yyextra->current->type=yyextra->current->type.simplifyWhiteSpace(); + yyextra->current->args=removeRedundantWhiteSpace(yyextra->current->args); + // was: yyextra->current->args.simplifyWhiteSpace(); + yyextra->current->fileName = yyextra->yyFileName; + yyextra->current->startLine = yyextra->yyBegLineNr; + yyextra->current->startColumn = yyextra->yyBegColNr; + static QRegExp re("([^)]*[*&][^)]*)"); // (...*...) int ts=yyextra->current->type.find('<'); int te=yyextra->current->type.findRev('>'); int ti=yyextra->current->type.find(re,0); @@ -4822,117 +4843,117 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) bool isFunction = ti==-1 || // not a (...*...) pattern (ts!=-1 && ts<te && ts<ti && ti<te); // (...*...) is part of a template argument list bool isVariable = (!yyextra->current->type.isEmpty() && - (!isFunction || yyextra->current->type.left(8)=="typedef ")); + (!isFunction || yyextra->current->type.left(8)=="typedef ")); //printf("type=%s ts=%d te=%d ti=%d isFunction=%d\n", // yyextra->current->type.data(),ts,te,ti,isFunction); - if (*yytext!=';' || (yyextra->current_root->section&Entry::COMPOUND_MASK) ) - { - int tempArg=yyextra->current->name.find('<'); - QCString tempName; - if (tempArg==-1) tempName=yyextra->current->name; else tempName=yyextra->current->name.left(tempArg); - if (isVariable) - { - //printf("Scanner.l: found in class variable: '%s' '%s' '%s'\n", yyextra->current->type.data(),yyextra->current->name.data(),yyextra->current->args.data()); - if (yyextra->isTypedef && yyextra->current->type.left(8)!="typedef ") - { - yyextra->current->type.prepend("typedef "); - } - yyextra->current->section = Entry::VARIABLE_SEC ; - } - else - { - //printf("Scanner.l: found in class function: '%s' '%s' '%s'\n", yyextra->current->type.data(),yyextra->current->name.data(),yyextra->current->args.data()); - yyextra->current->section = Entry::FUNCTION_SEC ; - yyextra->current->proto = *yytext==';'; - } - } - else // a global function prototype or function variable - { - //printf("Scanner.l: prototype? type='%s' name='%s' args='%s'\n",yyextra->current->type.data(),yyextra->current->name.data(),yyextra->current->args.data()); - if (isVariable) - { - if (yyextra->isTypedef && yyextra->current->type.left(8)!="typedef ") - { - yyextra->current->type.prepend("typedef "); - } - //printf("Scanner.l: found function variable!\n"); - yyextra->current->section = Entry::VARIABLE_SEC; - } - else - { - //printf("Scanner.l: found prototype\n"); - yyextra->current->section = Entry::FUNCTION_SEC; - yyextra->current->proto = TRUE; - } - } - //printf("Adding entry '%s'\n",yyextra->current->name.data()); - if ( yyextra->insidePHP) - { - if (findAndRemoveWord(yyextra->current->type,"final")) - { - yyextra->current->spec |= Entry::Final; - } - if (findAndRemoveWord(yyextra->current->type,"abstract")) - { - yyextra->current->spec |= Entry::Abstract; - } - } - if ( yyextra->insidePHP && !containsWord(yyextra->current->type,"function")) - { - initEntry(yyscanner); - if ( *yytext == '{' ) - { - yyextra->lastCurlyContext = FindMembers; - yyextra->curlyCount=0; - BEGIN( SkipCurly ); - } - else - { - BEGIN( FindMembers ); - } - } - else - { - if ( yyextra->insidePHP) - { - findAndRemoveWord(yyextra->current->type,"function"); - } - yyextra->previous = yyextra->current; - yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current); - initEntry(yyscanner); - // Objective C 2.0: Required/Optional section - if (yyextra->previous->spec & (Entry::Optional | Entry::Required)) - { - yyextra->current->spec |= yyextra->previous->spec & (Entry::Optional|Entry::Required); - } - yyextra->lastCurlyContext = FindMembers; - if ( *yytext == ',' ) - { - yyextra->current->type = yyextra->previous->type; - // we need to strip any trailing * and & (see bugs 623023 and 649103 for test cases) - int i=yyextra->current->type.length(); - while (i>0 && (yyextra->current->type[i-1]=='*' || yyextra->current->type[i-1]=='&' || yyextra->current->type[i-1]==' ')) i--; - yyextra->current->type = yyextra->current->type.left(i); - } - if ( *yytext == '{' ) - { - if ( !yyextra->insidePHP && (yyextra->current_root->section & Entry::COMPOUND_MASK) ) - { - yyextra->previous->spec |= Entry::Inline; - } - //addToBody(yytext); - yyextra->curlyCount=0; - BEGIN( SkipCurly ) ; - } - else - { - if (yyextra->previous->section!=Entry::VARIABLE_SEC) - yyextra->previous->bodyLine=-1; // a function/member declaration - BEGIN( FindMembers ) ; - } - } + if (*yytext!=';' || (yyextra->current_root->section&Entry::COMPOUND_MASK) ) + { + int tempArg=yyextra->current->name.find('<'); + QCString tempName; + if (tempArg==-1) tempName=yyextra->current->name; else tempName=yyextra->current->name.left(tempArg); + if (isVariable) + { + //printf("Scanner.l: found in class variable: '%s' '%s' '%s'\n", yyextra->current->type.data(),yyextra->current->name.data(),yyextra->current->args.data()); + if (yyextra->isTypedef && yyextra->current->type.left(8)!="typedef ") + { + yyextra->current->type.prepend("typedef "); + } + yyextra->current->section = Entry::VARIABLE_SEC ; + } + else + { + //printf("Scanner.l: found in class function: '%s' '%s' '%s'\n", yyextra->current->type.data(),yyextra->current->name.data(),yyextra->current->args.data()); + yyextra->current->section = Entry::FUNCTION_SEC ; + yyextra->current->proto = *yytext==';'; + } + } + else // a global function prototype or function variable + { + //printf("Scanner.l: prototype? type='%s' name='%s' args='%s'\n",yyextra->current->type.data(),yyextra->current->name.data(),yyextra->current->args.data()); + if (isVariable) + { + if (yyextra->isTypedef && yyextra->current->type.left(8)!="typedef ") + { + yyextra->current->type.prepend("typedef "); + } + //printf("Scanner.l: found function variable!\n"); + yyextra->current->section = Entry::VARIABLE_SEC; + } + else + { + //printf("Scanner.l: found prototype\n"); + yyextra->current->section = Entry::FUNCTION_SEC; + yyextra->current->proto = TRUE; + } + } + //printf("Adding entry '%s'\n",yyextra->current->name.data()); + if ( yyextra->insidePHP) + { + if (findAndRemoveWord(yyextra->current->type,"final")) + { + yyextra->current->spec |= Entry::Final; + } + if (findAndRemoveWord(yyextra->current->type,"abstract")) + { + yyextra->current->spec |= Entry::Abstract; + } + } + if ( yyextra->insidePHP && !containsWord(yyextra->current->type,"function")) + { + initEntry(yyscanner); + if ( *yytext == '{' ) + { + yyextra->lastCurlyContext = FindMembers; + yyextra->curlyCount=0; + BEGIN( SkipCurly ); + } + else + { + BEGIN( FindMembers ); + } + } + else + { + if ( yyextra->insidePHP) + { + findAndRemoveWord(yyextra->current->type,"function"); + } + yyextra->previous = yyextra->current; + yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current); + initEntry(yyscanner); + // Objective C 2.0: Required/Optional section + if (yyextra->previous->spec & (Entry::Optional | Entry::Required)) + { + yyextra->current->spec |= yyextra->previous->spec & (Entry::Optional|Entry::Required); + } + yyextra->lastCurlyContext = FindMembers; + if ( *yytext == ',' ) + { + yyextra->current->type = yyextra->previous->type; + // we need to strip any trailing * and & (see bugs 623023 and 649103 for test cases) + int i=yyextra->current->type.length(); + while (i>0 && (yyextra->current->type[i-1]=='*' || yyextra->current->type[i-1]=='&' || yyextra->current->type[i-1]==' ')) i--; + yyextra->current->type = yyextra->current->type.left(i); + } + if ( *yytext == '{' ) + { + if ( !yyextra->insidePHP && (yyextra->current_root->section & Entry::COMPOUND_MASK) ) + { + yyextra->previous->spec |= Entry::Inline; + } + //addToBody(yytext); + yyextra->curlyCount=0; + BEGIN( SkipCurly ) ; + } + else + { + if (yyextra->previous->section!=Entry::VARIABLE_SEC) + yyextra->previous->bodyLine=-1; // a function/member declaration + BEGIN( FindMembers ) ; + } + } } <SkipInits>">"{BN}*"{" { // C++11 style initializer (see bug 790788) lineCount(yyscanner); @@ -4948,7 +4969,7 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) ++yyextra->curlyCount; } <SkipC11Inits>"}" { - if ( --yyextra->curlyCount<=0 ) + if ( --yyextra->curlyCount<=0 ) { BEGIN(SkipInits); } @@ -4956,116 +4977,116 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) <SkipC11Attribute>"]]" { BEGIN(yyextra->lastC11AttributeContext); } -<SkipInits>"{" { // C++11 style initializer - unput('{'); - BEGIN( Function ); - } -<SkipCurly>"{" { - //addToBody(yytext); - ++yyextra->curlyCount ; - } +<SkipInits>"{" { // C++11 style initializer + unput('{'); + BEGIN( Function ); + } +<SkipCurly>"{" { + //addToBody(yytext); + ++yyextra->curlyCount ; + } <SkipCurly>"}"/{BN}*("/*!"|"/**"|"//!"|"///")"<!--" | /* see bug710917 */ -<SkipCurly>"}" { - //addToBody(yytext); - if( yyextra->curlyCount ) - { - --yyextra->curlyCount ; - } - else - { - if (!yyextra->current->sli.empty() && yyextra->previous) // copy special list items - { +<SkipCurly>"}" { + //addToBody(yytext); + if( yyextra->curlyCount ) + { + --yyextra->curlyCount ; + } + else + { + if (!yyextra->current->sli.empty() && yyextra->previous) // copy special list items + { yyextra->previous->sli = yyextra->current->sli; - yyextra->current->sli.clear(); - } - if (yyextra->previous) yyextra->previous->endBodyLine=yyextra->yyLineNr; - BEGIN( yyextra->lastCurlyContext ) ; - } - } -<SkipCurly>"}"{BN}*("/*!"|"/**"|"//!"|"///")"<" { - lineCount(yyscanner); - if ( yyextra->curlyCount ) - { - //addToBody(yytext); - --yyextra->curlyCount ; - } - else - { - yyextra->current->endBodyLine=yyextra->yyLineNr; - yyextra->tempEntry = yyextra->current; // temporarily switch to the previous entry - yyextra->current = yyextra->previous; - - yyextra->docBlockContext = SkipCurlyEndDoc; - yyextra->docBlockInBody = FALSE; - yyextra->docBlockAutoBrief = ( yytext[yyleng-2]=='*' && Config_getBool(JAVADOC_AUTOBRIEF) ) || - ( yytext[yyleng-2]=='!' && Config_getBool(QT_AUTOBRIEF) ); - yyextra->docBlock.resize(0); - yyextra->docBlockTerm = '}'; - if (yytext[yyleng-3]=='/') - { - startCommentBlock(yyscanner,TRUE); - BEGIN( DocLine ); - } - else - { - startCommentBlock(yyscanner,FALSE); - BEGIN( DocBlock ); - } - } - } + yyextra->current->sli.clear(); + } + if (yyextra->previous) yyextra->previous->endBodyLine=yyextra->yyLineNr; + BEGIN( yyextra->lastCurlyContext ) ; + } + } +<SkipCurly>"}"{BN}*("/*!"|"/**"|"//!"|"///")"<" { + lineCount(yyscanner); + if ( yyextra->curlyCount ) + { + //addToBody(yytext); + --yyextra->curlyCount ; + } + else + { + yyextra->current->endBodyLine=yyextra->yyLineNr; + yyextra->tempEntry = yyextra->current; // temporarily switch to the previous entry + yyextra->current = yyextra->previous; + + yyextra->docBlockContext = SkipCurlyEndDoc; + yyextra->docBlockInBody = FALSE; + yyextra->docBlockAutoBrief = ( yytext[yyleng-2]=='*' && Config_getBool(JAVADOC_AUTOBRIEF) ) || + ( yytext[yyleng-2]=='!' && Config_getBool(QT_AUTOBRIEF) ); + yyextra->docBlock.resize(0); + yyextra->docBlockTerm = '}'; + if (yytext[yyleng-3]=='/') + { + startCommentBlock(yyscanner,TRUE); + BEGIN( DocLine ); + } + else + { + startCommentBlock(yyscanner,FALSE); + BEGIN( DocBlock ); + } + } + } <SkipCurlyEndDoc>"}"{BN}*("/*!"|"/**"|"//!"|"///")"<" { // desc is followed by another one - yyextra->docBlockContext = SkipCurlyEndDoc; - yyextra->docBlockInBody = FALSE; - yyextra->docBlockAutoBrief = ( yytext[yyleng-2]=='*' && Config_getBool(JAVADOC_AUTOBRIEF) ) || - ( yytext[yyleng-2]=='!' && Config_getBool(QT_AUTOBRIEF) ); - yyextra->docBlock.resize(0); - yyextra->docBlockTerm = '}'; - if (yytext[yyleng-3]=='/') - { - startCommentBlock(yyscanner,TRUE); - BEGIN( DocLine ); - } - else - { - startCommentBlock(yyscanner,FALSE); - BEGIN( DocBlock ); - } - } -<SkipCurlyEndDoc>"}" { - //addToBody("}"); + yyextra->docBlockContext = SkipCurlyEndDoc; + yyextra->docBlockInBody = FALSE; + yyextra->docBlockAutoBrief = ( yytext[yyleng-2]=='*' && Config_getBool(JAVADOC_AUTOBRIEF) ) || + ( yytext[yyleng-2]=='!' && Config_getBool(QT_AUTOBRIEF) ); + yyextra->docBlock.resize(0); + yyextra->docBlockTerm = '}'; + if (yytext[yyleng-3]=='/') + { + startCommentBlock(yyscanner,TRUE); + BEGIN( DocLine ); + } + else + { + startCommentBlock(yyscanner,FALSE); + BEGIN( DocBlock ); + } + } +<SkipCurlyEndDoc>"}" { + //addToBody("}"); if (yyextra->tempEntry) // we can only switch back to yyextra->current if no new item was created - { - yyextra->current = yyextra->tempEntry; - yyextra->tempEntry.reset(); - } - BEGIN( yyextra->lastCurlyContext ); - } -<SkipCurly>\" { - //addToBody(yytext); - yyextra->lastStringContext=SkipCurly; - BEGIN( SkipString ); - } -<SkipCurly>^{B}*"#" { - if (yyextra->insidePHP) - REJECT; - //addToBody(yytext); - BEGIN( SkipCurlyCpp ); - } -<SkipCurly,SkipC11Inits,SkipInits,SkipC11Attribute>\n { + { + yyextra->current = yyextra->tempEntry; + yyextra->tempEntry.reset(); + } + BEGIN( yyextra->lastCurlyContext ); + } +<SkipCurly>\" { + //addToBody(yytext); + yyextra->lastStringContext=SkipCurly; + BEGIN( SkipString ); + } +<SkipCurly>^{B}*"#" { + if (yyextra->insidePHP) + REJECT; + //addToBody(yytext); + BEGIN( SkipCurlyCpp ); + } +<SkipCurly,SkipC11Inits,SkipInits,SkipC11Attribute>\n { lineCount(yyscanner); - //addToBody(yytext); - } + //addToBody(yytext); + } <SkipCurly,SkipCurlyCpp,ReadInitializer,ReadInitializerPtr>"<<<" { - if (!yyextra->insidePHP) - { - REJECT; - } - else - { + if (!yyextra->insidePHP) + { + REJECT; + } + else + { yyextra->lastHereDocContext = YY_START; - BEGIN(HereDoc); - } - } + BEGIN(HereDoc); + } + } <SkipCurly,SkipCurlyCpp>{B}*{RAWBEGIN} { QCString raw=QCString(yytext).stripWhiteSpace(); yyextra->delimiter = raw.data()+2; @@ -5078,191 +5099,191 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) } <SkipCurly,SkipCurlyCpp>[^\n#"'@\\/{}<]+ { lineCount(yyscanner); // for yyextra->column updates - //addToBody(yytext); - } -<SkipCurlyCpp>\n { - //addToBody(yytext); + //addToBody(yytext); + } +<SkipCurlyCpp>\n { + //addToBody(yytext); lineCount(yyscanner); - yyextra->lastCurlyContext = FindMembers; - BEGIN( SkipCurly ); - } -<SkipCurlyCpp>\\[\r]*"\n"[\r]* { - //addToBody(yytext); + yyextra->lastCurlyContext = FindMembers; + BEGIN( SkipCurly ); + } +<SkipCurlyCpp>\\[\r]*"\n"[\r]* { + //addToBody(yytext); lineCount(yyscanner); - } -<SkipInits,SkipC11Inits,SkipCurly,SkipCurlyCpp,SkipC11Attribute>"/*" { - //addToBody(yytext); - yyextra->lastCContext = YY_START; - BEGIN(SkipComment); - } + } +<SkipInits,SkipC11Inits,SkipCurly,SkipCurlyCpp,SkipC11Attribute>"/*" { + //addToBody(yytext); + yyextra->lastCContext = YY_START; + BEGIN(SkipComment); + } <SkipInits,SkipC11Inits,SkipCurly,SkipCurlyCpp,SkipC11Attribute>"//" { - //addToBody(yytext); - yyextra->lastCContext = YY_START; - BEGIN(SkipCxxComment); - } + //addToBody(yytext); + yyextra->lastCContext = YY_START; + BEGIN(SkipCxxComment); + } <SkipInits,SkipC11Inits,SkipC11Attribute>"(" { yyextra->roundCount=0; yyextra->lastSkipRoundContext=YY_START; BEGIN(SkipRound); } -<SkipInits,SkipC11Inits,SkipC11Attribute>\" { - yyextra->lastStringContext=YY_START; - BEGIN( SkipString ); - } -<SkipInits>; { - warn(yyextra->yyFileName,yyextra->yyLineNr, - "Found ';' while parsing initializer list! " - "(doxygen could be confused by a macro call without semicolon)" - ); - BEGIN( FindMembers ); - } +<SkipInits,SkipC11Inits,SkipC11Attribute>\" { + yyextra->lastStringContext=YY_START; + BEGIN( SkipString ); + } +<SkipInits>; { + warn(yyextra->yyFileName,yyextra->yyLineNr, + "Found ';' while parsing initializer list! " + "(doxygen could be confused by a macro call without semicolon)" + ); + BEGIN( FindMembers ); + } <SkipInits,SkipCurly,SkipCurlyCpp>"#" { - if (!yyextra->insidePHP) - REJECT; - //addToBody(yytext); - yyextra->lastCContext = YY_START; - BEGIN(SkipCxxComment); - } + if (!yyextra->insidePHP) + REJECT; + //addToBody(yytext); + yyextra->lastCContext = YY_START; + BEGIN(SkipCxxComment); + } <SkipInits,SkipCurly,SkipCurlyCpp>@\" { - if (!yyextra->insideCS) REJECT; - // C# verbatim string - yyextra->lastSkipVerbStringContext=YY_START; - yyextra->pSkipVerbString=&yyextra->current->initializer; - BEGIN(SkipVerbString); - } -<SkipInits,SkipCurly,SkipCurlyCpp>{CHARLIT} { + if (!yyextra->insideCS) REJECT; + // C# verbatim string + yyextra->lastSkipVerbStringContext=YY_START; + yyextra->pSkipVerbString=&yyextra->current->initializer; + BEGIN(SkipVerbString); + } +<SkipInits,SkipCurly,SkipCurlyCpp>{CHARLIT} { if (yyextra->insidePHP) REJECT; } -<SkipInits,SkipCurly,SkipCurlyCpp>\' { - if (yyextra->insidePHP) - { - yyextra->lastStringContext=YY_START; - BEGIN(SkipPHPString); - } - } -<SkipInits,SkipC11Inits,SkipCurly,SkipCurlyCpp,SkipC11Attribute>. { } -<SkipString,SkipPHPString>\\. { } -<SkipString>\" { - BEGIN( yyextra->lastStringContext ); - } -<SkipPHPString>\' { - BEGIN( yyextra->lastStringContext ); - } +<SkipInits,SkipCurly,SkipCurlyCpp>\' { + if (yyextra->insidePHP) + { + yyextra->lastStringContext=YY_START; + BEGIN(SkipPHPString); + } + } +<SkipInits,SkipC11Inits,SkipCurly,SkipCurlyCpp,SkipC11Attribute>. { } +<SkipString,SkipPHPString>\\. { } +<SkipString>\" { + BEGIN( yyextra->lastStringContext ); + } +<SkipPHPString>\' { + BEGIN( yyextra->lastStringContext ); + } <SkipString,SkipPHPString>"/*"|"*/"|"//" { } -<SkipString,SkipPHPString>\n { +<SkipString,SkipPHPString>\n { lineCount(yyscanner); - } -<SkipString,SkipPHPString>. { } -<CompoundName>":" { // for "class : public base {} var;" construct, see bug 608359 - unput(':'); - BEGIN(ClassVar); - } -<CompoundName>";" { - yyextra->current->section = Entry::EMPTY_SEC ; - yyextra->current->type.resize(0) ; - yyextra->current->name.resize(0) ; - yyextra->current->args.resize(0) ; - yyextra->current->argList.clear(); - BEGIN( FindMembers ) ; - } -<Bases>";" { - if (yyextra->insideIDL && (yyextra->current->spec & (Entry::Singleton | - Entry::Service))) - { - // in UNO IDL a service or singleton may be defined - // completely like this: "service Foo : XFoo;" - if (!yyextra->current->name.isEmpty() && !yyextra->current_root->name.isEmpty()) - { - prependScope(yyscanner); - } - yyextra->current->name = yyextra->current->name.stripWhiteSpace(); - // there can be only one base class here - if (!yyextra->baseName.isEmpty()) - { - yyextra->current->extends.push_back( - BaseInfo(yyextra->baseName,Public,Normal)); - yyextra->baseName.resize(0); - } - yyextra->current_root->moveToSubEntryAndRefresh( yyextra->current ) ; + } +<SkipString,SkipPHPString>. { } +<CompoundName>":" { // for "class : public base {} var;" construct, see bug 608359 + unput(':'); + BEGIN(ClassVar); + } +<CompoundName>";" { + yyextra->current->section = Entry::EMPTY_SEC ; + yyextra->current->type.resize(0) ; + yyextra->current->name.resize(0) ; + yyextra->current->args.resize(0) ; + yyextra->current->argList.clear(); + BEGIN( FindMembers ) ; + } +<Bases>";" { + if (yyextra->insideIDL && (yyextra->current->spec & (Entry::Singleton | + Entry::Service))) + { + // in UNO IDL a service or singleton may be defined + // completely like this: "service Foo : XFoo;" + if (!yyextra->current->name.isEmpty() && !yyextra->current_root->name.isEmpty()) + { + prependScope(yyscanner); + } + yyextra->current->name = yyextra->current->name.stripWhiteSpace(); + // there can be only one base class here + if (!yyextra->baseName.isEmpty()) + { + yyextra->current->extends.push_back( + BaseInfo(yyextra->baseName,Public,Normal)); + yyextra->baseName.resize(0); + } + yyextra->current_root->moveToSubEntryAndRefresh( yyextra->current ) ; initEntry(yyscanner); - } - else - { - yyextra->current->section = Entry::EMPTY_SEC ; - yyextra->current->type.resize(0) ; - yyextra->current->name.resize(0) ; - yyextra->current->args.resize(0) ; - yyextra->current->argList.clear(); - } - BEGIN( FindMembers ) ; - } -<CompoundName>{SCOPENAME}/{BN}*"<" { - yyextra->sharpCount = 0; - yyextra->current->name = yytext ; - if (yyextra->current->spec & Entry::Protocol) - { - yyextra->current->name+="-p"; - } - lineCount(yyscanner); - yyextra->lastClassTemplSpecContext = ClassVar; - if (yyextra->insideObjC) // protocol list - { - BEGIN( ObjCProtocolList ); - } - else if (yyextra->insideCS) // C# generic class - { + } + else + { + yyextra->current->section = Entry::EMPTY_SEC ; + yyextra->current->type.resize(0) ; + yyextra->current->name.resize(0) ; + yyextra->current->args.resize(0) ; + yyextra->current->argList.clear(); + } + BEGIN( FindMembers ) ; + } +<CompoundName>{SCOPENAME}/{BN}*"<" { + yyextra->sharpCount = 0; + yyextra->current->name = yytext ; + if (yyextra->current->spec & Entry::Protocol) + { + yyextra->current->name+="-p"; + } + lineCount(yyscanner); + yyextra->lastClassTemplSpecContext = ClassVar; + if (yyextra->insideObjC) // protocol list + { + BEGIN( ObjCProtocolList ); + } + else if (yyextra->insideCS) // C# generic class + { //yyextra->current->name+="-g"; - BEGIN( CSGeneric ); - } - else // C++ template specialization - { - yyextra->roundCount=0; - BEGIN( ClassTemplSpec ); - } - } -<CSGeneric>"<" { - ArgumentList al; - // check bug 612858 before enabling the next line - //yyextra->current->spec |= Entry::Template; - yyextra->current->tArgLists.push_back(al); - yyextra->currentArgumentList = &yyextra->current->tArgLists.back(); - yyextra->templateStr="<"; - yyextra->current->name += "<"; - yyextra->fullArgString = yyextra->templateStr; - yyextra->copyArgString = &yyextra->current->name; - //yyextra->copyArgString = &yyextra->templateStr; - yyextra->currentArgumentContext = ClassVar; - BEGIN( ReadTempArgs ); - } -<ObjCProtocolList>"<" { - yyextra->insideProtocolList=TRUE; - BEGIN( Bases ); - } -<ClassTemplSpec>">"({BN}*"::"{BN}*{SCOPENAME})? { - yyextra->current->name += yytext; - lineCount(yyscanner); - if (yyextra->roundCount==0 && --yyextra->sharpCount<=0) - { - yyextra->current->name = removeRedundantWhiteSpace(yyextra->current->name); - if (yyextra->current->spec & Entry::Protocol) - { // Objective-C protocol - unput('{'); // fake start of body - BEGIN( ClassVar ); - } - else - { - BEGIN( yyextra->lastClassTemplSpecContext ); - } - } - } -<ClassTemplSpec>"<" { - yyextra->current->name += yytext; - if (yyextra->roundCount==0) yyextra->sharpCount++; - } -<ClassTemplSpec>. { - yyextra->current->name += yytext; - } -<CompoundName>{SCOPENAME}{BN}*";" { // forward declaration + BEGIN( CSGeneric ); + } + else // C++ template specialization + { + yyextra->roundCount=0; + BEGIN( ClassTemplSpec ); + } + } +<CSGeneric>"<" { + ArgumentList al; + // check bug 612858 before enabling the next line + //yyextra->current->spec |= Entry::Template; + yyextra->current->tArgLists.push_back(al); + yyextra->currentArgumentList = &yyextra->current->tArgLists.back(); + yyextra->templateStr="<"; + yyextra->current->name += "<"; + yyextra->fullArgString = yyextra->templateStr; + yyextra->copyArgString = &yyextra->current->name; + //yyextra->copyArgString = &yyextra->templateStr; + yyextra->currentArgumentContext = ClassVar; + BEGIN( ReadTempArgs ); + } +<ObjCProtocolList>"<" { + yyextra->insideProtocolList=TRUE; + BEGIN( Bases ); + } +<ClassTemplSpec>">"({BN}*"::"{BN}*{SCOPENAME})? { + yyextra->current->name += yytext; + lineCount(yyscanner); + if (yyextra->roundCount==0 && --yyextra->sharpCount<=0) + { + yyextra->current->name = removeRedundantWhiteSpace(yyextra->current->name); + if (yyextra->current->spec & Entry::Protocol) + { // Objective-C protocol + unput('{'); // fake start of body + BEGIN( ClassVar ); + } + else + { + BEGIN( yyextra->lastClassTemplSpecContext ); + } + } + } +<ClassTemplSpec>"<" { + yyextra->current->name += yytext; + if (yyextra->roundCount==0) yyextra->sharpCount++; + } +<ClassTemplSpec>. { + yyextra->current->name += yytext; + } +<CompoundName>{SCOPENAME}{BN}*";" { // forward declaration if (!yyextra->current->tArgLists.empty()) { // found a forward template declaration, this has @@ -5270,54 +5291,54 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) yyextra->current->name = yytext; yyextra->current->name=yyextra->current->name.left(yyextra->current->name.length()-1).stripWhiteSpace(); //printf("template class declaration for %s!\n",yyextra->current->name.data()); - QCString rn = yyextra->current_root->name.copy(); - //printf("cn='%s' rn='%s' yyextra->isTypedef=%d\n",cn.data(),rn.data(),yyextra->isTypedef); - if (!yyextra->current->name.isEmpty() && !rn.isEmpty()) - { - prependScope(yyscanner); - } + QCString rn = yyextra->current_root->name.copy(); + //printf("cn='%s' rn='%s' yyextra->isTypedef=%d\n",cn.data(),rn.data(),yyextra->isTypedef); + if (!yyextra->current->name.isEmpty() && !rn.isEmpty()) + { + prependScope(yyscanner); + } yyextra->current->spec|=Entry::ForwardDecl; yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current); } - else if (yyextra->insideIDL && - (((yyextra->current_root->spec & (Entry::Interface | - Entry::Service)) && - (yyextra->current->spec & Entry::Interface)) || - ((yyextra->current_root->spec & (Entry::Service | - Entry::Singleton)) && - (yyextra->current->spec & Entry::Service)))) - { - // interface yyextra->inside of UNO IDL service or interface - // service yyextra->inside of UNO IDL service or singleton - // there may be documentation on the member, - // so do not throw it away... - yyextra->current->name = yytext; - yyextra->current->name=yyextra->current->name.left(yyextra->current->name.length()-1).stripWhiteSpace(); - yyextra->current->section = (yyextra->current->spec & Entry::Interface) - ? Entry::EXPORTED_INTERFACE_SEC - : Entry::INCLUDED_SERVICE_SEC; -// yyextra->current->section = Entry::MEMBERDOC_SEC; - yyextra->current->spec &= ~(Entry::Interface|Entry::Service); // FIXME: horrible: Interface == Gettable, so need to clear it - actually we're mixing values from different enums in this case... granted only Optional and Interface are actually valid in this context but urgh... - yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current); - } - - unput(';'); - yyextra->current->reset(); - initEntry(yyscanner); + else if (yyextra->insideIDL && + (((yyextra->current_root->spec & (Entry::Interface | + Entry::Service)) && + (yyextra->current->spec & Entry::Interface)) || + ((yyextra->current_root->spec & (Entry::Service | + Entry::Singleton)) && + (yyextra->current->spec & Entry::Service)))) + { + // interface yyextra->inside of UNO IDL service or interface + // service yyextra->inside of UNO IDL service or singleton + // there may be documentation on the member, + // so do not throw it away... + yyextra->current->name = yytext; + yyextra->current->name=yyextra->current->name.left(yyextra->current->name.length()-1).stripWhiteSpace(); + yyextra->current->section = (yyextra->current->spec & Entry::Interface) + ? Entry::EXPORTED_INTERFACE_SEC + : Entry::INCLUDED_SERVICE_SEC; +// yyextra->current->section = Entry::MEMBERDOC_SEC; + yyextra->current->spec &= ~(Entry::Interface|Entry::Service); // FIXME: horrible: Interface == Gettable, so need to clear it - actually we're mixing values from different enums in this case... granted only Optional and Interface are actually valid in this context but urgh... + yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current); + } + + unput(';'); + yyextra->current->reset(); + initEntry(yyscanner); if (yyextra->insideObjC) // see bug746361 { - yyextra->language = yyextra->current->lang = SrcLangExt_Cpp; + yyextra->language = yyextra->current->lang = SrcLangExt_Cpp; yyextra->insideObjC = FALSE; } - if (yyextra->isTypedef) // typedef of a class, put typedef keyword back - { - yyextra->current->type.prepend("typedef"); - } - BEGIN( FindMembers ); - } -<CompoundName>{SCOPENAME}/{BN}*"(" { - yyextra->current->name = yytext ; - lineCount(yyscanner); + if (yyextra->isTypedef) // typedef of a class, put typedef keyword back + { + yyextra->current->type.prepend("typedef"); + } + BEGIN( FindMembers ); + } +<CompoundName>{SCOPENAME}/{BN}*"(" { + yyextra->current->name = yytext ; + lineCount(yyscanner); if (yyextra->insideCpp && yyextra->current->name=="alignas") // C++11 { yyextra->lastAlignAsContext = YY_START; @@ -5331,186 +5352,186 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) } BEGIN( ClassVar ); } - } -<AlignAs>"(" { yyextra->roundCount=0; - BEGIN( AlignAsEnd ); + } +<AlignAs>"(" { yyextra->roundCount=0; + BEGIN( AlignAsEnd ); } <AlignAs>\n { lineCount(yyscanner); } <AlignAs>. <AlignAsEnd>"(" { yyextra->roundCount++; } -<AlignAsEnd>")" { if (--yyextra->roundCount<0) +<AlignAsEnd>")" { if (--yyextra->roundCount<0) { - BEGIN( yyextra->lastAlignAsContext ); + BEGIN( yyextra->lastAlignAsContext ); } } <AlignAsEnd>\n { lineCount(yyscanner); } <AlignAsEnd>. -<CompoundName>{SCOPENAME}/{BN}*"," { // multiple forward declarations on one line +<CompoundName>{SCOPENAME}/{BN}*"," { // multiple forward declarations on one line // e.g. @protocol A,B; - yyextra->current->reset(); - initEntry(yyscanner); - } -<CompoundName>{SCOPENAME} { - yyextra->current->name = yytext ; + yyextra->current->reset(); + initEntry(yyscanner); + } +<CompoundName>{SCOPENAME} { + yyextra->current->name = yytext ; if (yyextra->clangParser && (yyextra->insideCpp || yyextra->insideObjC)) { yyextra->current->id = yyextra->clangParser->lookup(yyextra->yyLineNr,yytext); } - lineCount(yyscanner); - if (yyextra->current->spec & Entry::Protocol) - { - yyextra->current->name += "-p"; - } - if ((yyextra->current->spec & Entry::Protocol) || - yyextra->current->section == Entry::OBJCIMPL_SEC) - { - unput('{'); // fake start of body - } - BEGIN( ClassVar ); - } -<CompoundName>{CSSCOPENAME} { // C# style scope - yyextra->current->name = substitute(yytext,".","::"); - lineCount(yyscanner); - BEGIN( ClassVar ); - } -<ClassVar>{SCOPENAME}{BN}*/"(" { - if (yyextra->insideIDL && qstrncmp(yytext,"switch",6)==0 && !isId(yytext[6])) - { - // Corba IDL style union - yyextra->roundCount=0; - BEGIN(SkipUnionSwitch); - } - else - { - addType(yyscanner); - yyextra->current->name = yytext; - yyextra->current->name = yyextra->current->name.stripWhiteSpace(); - lineCount(yyscanner); - BEGIN( FindMembers ); - } - } -<ClassVar>"," { - if (yyextra->isTypedef) - { - // multiple types in one typedef - unput(','); - yyextra->current->type.prepend("typedef "); - BEGIN(FindMembers); - } - else - { - // Multiple class forward declaration - } - } + lineCount(yyscanner); + if (yyextra->current->spec & Entry::Protocol) + { + yyextra->current->name += "-p"; + } + if ((yyextra->current->spec & Entry::Protocol) || + yyextra->current->section == Entry::OBJCIMPL_SEC) + { + unput('{'); // fake start of body + } + BEGIN( ClassVar ); + } +<CompoundName>{CSSCOPENAME} { // C# style scope + yyextra->current->name = substitute(yytext,".","::"); + lineCount(yyscanner); + BEGIN( ClassVar ); + } +<ClassVar>{SCOPENAME}{BN}*/"(" { + if (yyextra->insideIDL && qstrncmp(yytext,"switch",6)==0 && !isId(yytext[6])) + { + // Corba IDL style union + yyextra->roundCount=0; + BEGIN(SkipUnionSwitch); + } + else + { + addType(yyscanner); + yyextra->current->name = yytext; + yyextra->current->name = yyextra->current->name.stripWhiteSpace(); + lineCount(yyscanner); + BEGIN( FindMembers ); + } + } +<ClassVar>"," { + if (yyextra->isTypedef) + { + // multiple types in one typedef + unput(','); + yyextra->current->type.prepend("typedef "); + BEGIN(FindMembers); + } + else + { + // Multiple class forward declaration + } + } <ClassVar>("sealed"|"abstract")/{BN}*(":"|"{") { - if (yyextra->insideCli) - { - if (yytext[0]=='s') // sealed - yyextra->current->spec |= Entry::SealedClass; - else // abstract - yyextra->current->spec |= Entry::AbstractClass; - BEGIN( ClassVar ); - } - else - { - REJECT; - } - } -<ClassVar>{ID} { + if (yyextra->insideCli) + { + if (yytext[0]=='s') // sealed + yyextra->current->spec |= Entry::SealedClass; + else // abstract + yyextra->current->spec |= Entry::AbstractClass; + BEGIN( ClassVar ); + } + else + { + REJECT; + } + } +<ClassVar>{ID} { if (yyextra->clangParser && (yyextra->insideCpp || yyextra->insideObjC)) { yyextra->current->id = yyextra->clangParser->lookup(yyextra->yyLineNr,yytext); } - if (yyextra->insideIDL && qstrcmp(yytext,"switch")==0) - { - // Corba IDL style union - yyextra->roundCount=0; - BEGIN(SkipUnionSwitch); - } - else if ((yyextra->insideJava || yyextra->insidePHP || yyextra->insideJS || yyextra->insideSlice) && (qstrcmp(yytext,"implements")==0 || qstrcmp(yytext,"extends")==0)) - { - yyextra->current->type.resize(0); - yyextra->baseProt=Public; + if (yyextra->insideIDL && qstrcmp(yytext,"switch")==0) + { + // Corba IDL style union + yyextra->roundCount=0; + BEGIN(SkipUnionSwitch); + } + else if ((yyextra->insideJava || yyextra->insidePHP || yyextra->insideJS || yyextra->insideSlice) && (qstrcmp(yytext,"implements")==0 || qstrcmp(yytext,"extends")==0)) + { + yyextra->current->type.resize(0); + yyextra->baseProt=Public; yyextra->baseVirt=Normal; - yyextra->baseName.resize(0); - BEGIN( BasesProt ) ; - } - else if (yyextra->insideCS && qstrcmp(yytext,"where")==0) // C# type constraint - { + yyextra->baseName.resize(0); + BEGIN( BasesProt ) ; + } + else if (yyextra->insideCS && qstrcmp(yytext,"where")==0) // C# type constraint + { yyextra->current->typeConstr.clear(); - yyextra->current->typeConstr.push_back(Argument()); - yyextra->lastCSConstraint = YY_START; - BEGIN( CSConstraintName ); - } - else if (yyextra->insideCli && qstrcmp(yytext,"abstract")==0) - { - yyextra->current->spec|=Entry::Abstract; - } - else if (yyextra->insideCli && qstrcmp(yytext,"sealed")==0) - { - yyextra->current->spec|=Entry::Sealed; - } + yyextra->current->typeConstr.push_back(Argument()); + yyextra->lastCSConstraint = YY_START; + BEGIN( CSConstraintName ); + } + else if (yyextra->insideCli && qstrcmp(yytext,"abstract")==0) + { + yyextra->current->spec|=Entry::Abstract; + } + else if (yyextra->insideCli && qstrcmp(yytext,"sealed")==0) + { + yyextra->current->spec|=Entry::Sealed; + } else if (qstrcmp(yytext,"final")==0) { yyextra->current->spec|=Entry::Final; } - else - { - if (yyextra->current->section == Entry::ENUM_SEC) - { // found "enum a b" -> variable - yyextra->current->section = Entry::VARIABLE_SEC ; - } - yyextra->current->type += ' ' ; - yyextra->current->type += yyextra->current->name ; - yyextra->current->name = yytext ; - - if (nameIsOperator(yyextra->current->name)) - { - BEGIN( Operator ); - } - } - } -<ClassVar>[(\[] { - if (yyextra->insideObjC && *yytext=='(') // class category - { - yyextra->current->name+='('; + else + { + if (yyextra->current->section == Entry::ENUM_SEC) + { // found "enum a b" -> variable + yyextra->current->section = Entry::VARIABLE_SEC ; + } + yyextra->current->type += ' ' ; + yyextra->current->type += yyextra->current->name ; + yyextra->current->name = yytext ; + + if (nameIsOperator(yyextra->current->name)) + { + BEGIN( Operator ); + } + } + } +<ClassVar>[(\[] { + if (yyextra->insideObjC && *yytext=='(') // class category + { + yyextra->current->name+='('; //if (yyextra->current->section!=Entry::OBJCIMPL_SEC) //{ - yyextra->current->spec|=Entry::Category; + yyextra->current->spec|=Entry::Category; //} - BEGIN( ClassCategory ); - } - else - { + BEGIN( ClassCategory ); + } + else + { // probably a function anyway unput(*yytext); - BEGIN( FindMembers ); - } - } + BEGIN( FindMembers ); + } + } <CSConstraintType,CSConstraintName>"/**/" { /* empty comment */ } -<CSConstraintType,CSConstraintName>("/*"[*!]|"//"[/!])("<"?) { // special comment +<CSConstraintType,CSConstraintName>("/*"[*!]|"//"[/!])("<"?) { // special comment yyextra->fullArgString.resize(0); - yyextra->lastCopyArgChar='#'; // end marker - yyextra->lastCommentInArgContext=YY_START; - if (yytext[1]=='/') - BEGIN( CopyArgCommentLine ); - else - BEGIN( CopyArgComment ); - } -<CSConstraintType,CSConstraintName>"#" { // artificially inserted token to signal end of comment block + yyextra->lastCopyArgChar='#'; // end marker + yyextra->lastCommentInArgContext=YY_START; + if (yytext[1]=='/') + BEGIN( CopyArgCommentLine ); + else + BEGIN( CopyArgComment ); + } +<CSConstraintType,CSConstraintName>"#" { // artificially inserted token to signal end of comment block yyextra->current->typeConstr.back().docs = yyextra->fullArgString; - } -<CSConstraintType>"{" { // end of type constraint reached + } +<CSConstraintType>"{" { // end of type constraint reached // parse documentation of the constraints handleParametersCommentBlocks(yyscanner,yyextra->current->typeConstr); - unput('{'); - BEGIN( yyextra->lastCSConstraint ); - } + unput('{'); + BEGIN( yyextra->lastCSConstraint ); + } <CSConstraintType,CSConstraintName>";" { handleParametersCommentBlocks(yyscanner,yyextra->current->typeConstr); - unput(';'); - BEGIN( yyextra->lastCSConstraint ); - } + unput(';'); + BEGIN( yyextra->lastCSConstraint ); + } <CSConstraintName>":" { BEGIN( CSConstraintType ); } @@ -5518,10 +5539,10 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) // parameter name yyextra->current->typeConstr.back().name=yytext; } -<CSConstraintType>"where" { // another constraint for a different param - yyextra->current->typeConstr.push_back(Argument()); +<CSConstraintType>"where" { // another constraint for a different param + yyextra->current->typeConstr.push_back(Argument()); BEGIN( CSConstraintName ); - } + } <CSConstraintType>({ID}".")*{ID}("<"{ID}">")?("()")? { if (yyextra->current->typeConstr.back().type.isEmpty()) // first type constraint for this parameter @@ -5536,300 +5557,300 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) yyextra->current->typeConstr.back().type=yytext; } } -<CSConstraintName,CSConstraintType>\n { +<CSConstraintName,CSConstraintType>\n { lineCount(yyscanner); - } -<CSConstraintName,CSConstraintType>. { - } -<ClassCategory>{ID} { - yyextra->current->name+=yytext; - } -<ClassCategory>")"/{BN}*"{" { - yyextra->current->name+=')'; - BEGIN( ClassVar ); - } -<ClassCategory>")"/{BN}*"<" { - yyextra->current->name+=')'; - BEGIN( ObjCProtocolList ); - } -<ClassCategory>")" { - yyextra->current->name+=')'; - if ((yyextra->current->section & Entry::Protocol) || - yyextra->current->section == Entry::OBJCIMPL_SEC) - { - unput('{'); // fake start of body - } - else // category has no variables so push back an empty body - { - unput('}'); - unput('{'); - } - BEGIN( ClassVar ); - } -<ClassVar>":" { + } +<CSConstraintName,CSConstraintType>. { + } +<ClassCategory>{ID} { + yyextra->current->name+=yytext; + } +<ClassCategory>")"/{BN}*"{" { + yyextra->current->name+=')'; + BEGIN( ClassVar ); + } +<ClassCategory>")"/{BN}*"<" { + yyextra->current->name+=')'; + BEGIN( ObjCProtocolList ); + } +<ClassCategory>")" { + yyextra->current->name+=')'; + if ((yyextra->current->section & Entry::Protocol) || + yyextra->current->section == Entry::OBJCIMPL_SEC) + { + unput('{'); // fake start of body + } + else // category has no variables so push back an empty body + { + unput('}'); + unput('{'); + } + BEGIN( ClassVar ); + } +<ClassVar>":" { if (yyextra->current->section==Entry::VARIABLE_SEC) // enum A B:2, see bug 748208 { yyextra->current->bitfields+=":"; yyextra->current->args.resize(0); BEGIN(BitFields); } - else if (yyextra->current->section==Entry::ENUM_SEC) // enum E:2, see bug 313527, + else if (yyextra->current->section==Entry::ENUM_SEC) // enum E:2, see bug 313527, // or C++11 style enum: 'E : unsigned int {...}' - { - yyextra->current->args.resize(0); - BEGIN(EnumBaseType); - } - else - { - yyextra->current->type.resize(0); - if ((yyextra->current->spec & Entry::Interface) || - (yyextra->current->spec & Entry::Struct) || - (yyextra->current->spec & Entry::Ref) || - (yyextra->current->spec & Entry::Value) || - yyextra->insidePHP || yyextra->insideCS || yyextra->insideD || yyextra->insideObjC || yyextra->insideIDL - ) - yyextra->baseProt=Public; - else - yyextra->baseProt=Private; - yyextra->baseVirt=Normal; - yyextra->baseName.resize(0); - BEGIN( BasesProt ) ; - } - } -<ClassVar>[;=*&] { - unput(*yytext); - if (yyextra->isTypedef) // typedef of a class, put typedef keyword back - { - yyextra->current->type.prepend("typedef"); - } - if ((yytext[0]=='*' || yytext[0]=='&') && - yyextra->current->section == Entry::ENUM_SEC) - { // found "enum a *b" -> variable - yyextra->current->section = Entry::VARIABLE_SEC ; - } - BEGIN( FindMembers ); - } + { + yyextra->current->args.resize(0); + BEGIN(EnumBaseType); + } + else + { + yyextra->current->type.resize(0); + if ((yyextra->current->spec & Entry::Interface) || + (yyextra->current->spec & Entry::Struct) || + (yyextra->current->spec & Entry::Ref) || + (yyextra->current->spec & Entry::Value) || + yyextra->insidePHP || yyextra->insideCS || yyextra->insideD || yyextra->insideObjC || yyextra->insideIDL + ) + yyextra->baseProt=Public; + else + yyextra->baseProt=Private; + yyextra->baseVirt=Normal; + yyextra->baseName.resize(0); + BEGIN( BasesProt ) ; + } + } +<ClassVar>[;=*&] { + unput(*yytext); + if (yyextra->isTypedef) // typedef of a class, put typedef keyword back + { + yyextra->current->type.prepend("typedef"); + } + if ((yytext[0]=='*' || yytext[0]=='&') && + yyextra->current->section == Entry::ENUM_SEC) + { // found "enum a *b" -> variable + yyextra->current->section = Entry::VARIABLE_SEC ; + } + BEGIN( FindMembers ); + } <Bases,ClassVar>"///"/[^/] { - if (!yyextra->insideObjC) - { - REJECT; - } - else - { - lineCount(yyscanner); - yyextra->current->program+=yytext; + if (!yyextra->insideObjC) + { + REJECT; + } + else + { + lineCount(yyscanner); + yyextra->current->program+=yytext; yyextra->current->fileName = yyextra->yyFileName ; - yyextra->current->startLine = yyextra->yyLineNr ; - yyextra->current->startColumn = yyextra->yyColNr; - yyextra->curlyCount=0; - BEGIN( ReadBodyIntf ); - } - } + yyextra->current->startLine = yyextra->yyLineNr ; + yyextra->current->startColumn = yyextra->yyColNr; + yyextra->curlyCount=0; + BEGIN( ReadBodyIntf ); + } + } <Bases,ClassVar>("//"{B}*)?"/**"/[^/*] | <Bases,ClassVar>("//"{B}*)?"/*!" | <Bases,ClassVar>"//!" | -<Bases,ClassVar>[\-+]{BN}* { - if (!yyextra->insideObjC) - { - REJECT; - } - else - { - lineCount(yyscanner); - yyextra->current->program+=yytext; +<Bases,ClassVar>[\-+]{BN}* { + if (!yyextra->insideObjC) + { + REJECT; + } + else + { + lineCount(yyscanner); + yyextra->current->program+=yytext; yyextra->current->fileName = yyextra->yyFileName ; - yyextra->current->startLine = yyextra->yyLineNr ; - yyextra->current->startColumn = yyextra->yyColNr; - yyextra->curlyCount=0; - BEGIN( ReadBodyIntf ); - } - } -<CompoundName,ClassVar>{B}*"{"{B}* { + yyextra->current->startLine = yyextra->yyLineNr ; + yyextra->current->startColumn = yyextra->yyColNr; + yyextra->curlyCount=0; + BEGIN( ReadBodyIntf ); + } + } +<CompoundName,ClassVar>{B}*"{"{B}* { yyextra->current->program.resize(0); yyextra->current->fileName = yyextra->yyFileName ; - yyextra->current->bodyLine = yyextra->yyLineNr; - yyextra->current->bodyColumn = yyextra->yyColNr; - yyextra->current->name = removeRedundantWhiteSpace(yyextra->current->name); - if (yyextra->current->name.isEmpty() && !yyextra->isTypedef) // anonymous compound - { - if (yyextra->current->section==Entry::NAMESPACE_SEC) // allow reopening of anonymous namespaces - { - if (Config_getBool(EXTRACT_ANON_NSPACES)) // use visible name - { - yyextra->current->name="anonymous_namespace{"+stripPath(yyextra->current->fileName)+"}"; - } - else // use invisible name - { - yyextra->current->name.sprintf("@%d",anonNSCount.load()); - } - } - else - { - yyextra->current->name.sprintf("@%d",anonCount++); - } - } - yyextra->curlyCount=0; - if (yyextra->current_root && // not a nested struct yyextra->inside an @interface section - !(yyextra->current_root->spec & Entry::Interface) && - ((yyextra->current->spec & (Entry::Interface | Entry::Protocol | Entry::Category) || - yyextra->current->section==Entry::OBJCIMPL_SEC) - ) && - yyextra->insideObjC - ) - { // ObjC body that ends with @end - BEGIN( ReadBodyIntf ); - } - else if (yyextra->current->section==Entry::NAMESPACE_SEC) - { // namespace body - BEGIN( ReadNSBody ); - } - else - { // class body - BEGIN( ReadBody ) ; - } - } + yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->current->bodyColumn = yyextra->yyColNr; + yyextra->current->name = removeRedundantWhiteSpace(yyextra->current->name); + if (yyextra->current->name.isEmpty() && !yyextra->isTypedef) // anonymous compound + { + if (yyextra->current->section==Entry::NAMESPACE_SEC) // allow reopening of anonymous namespaces + { + if (Config_getBool(EXTRACT_ANON_NSPACES)) // use visible name + { + yyextra->current->name="anonymous_namespace{"+stripPath(yyextra->current->fileName)+"}"; + } + else // use invisible name + { + yyextra->current->name.sprintf("@%d",anonNSCount.load()); + } + } + else + { + yyextra->current->name.sprintf("@%d",anonCount++); + } + } + yyextra->curlyCount=0; + if (yyextra->current_root && // not a nested struct yyextra->inside an @interface section + !(yyextra->current_root->spec & Entry::Interface) && + ((yyextra->current->spec & (Entry::Interface | Entry::Protocol | Entry::Category) || + yyextra->current->section==Entry::OBJCIMPL_SEC) + ) && + yyextra->insideObjC + ) + { // ObjC body that ends with @end + BEGIN( ReadBodyIntf ); + } + else if (yyextra->current->section==Entry::NAMESPACE_SEC) + { // namespace body + BEGIN( ReadNSBody ); + } + else + { // class body + BEGIN( ReadBody ) ; + } + } <BasesProt>"virtual"{BN}+ { lineCount(yyscanner); yyextra->baseVirt = Virtual; } <BasesProt>"public"{BN}+ { lineCount(yyscanner); yyextra->baseProt = Public; } <BasesProt>"protected"{BN}+ { lineCount(yyscanner); yyextra->baseProt = Protected; } <BasesProt>"internal"{BN}+ { if (!yyextra->insideCli) REJECT ; lineCount(yyscanner); yyextra->baseProt = Package; } <BasesProt>"private"{BN}+ { lineCount(yyscanner); yyextra->baseProt = Private; } -<BasesProt>{BN} { lineCount(yyscanner); } -<BasesProt>. { unput(*yytext); BEGIN(Bases); } -<Bases>("\\")?({ID}"\\")*{ID} { // PHP namespace token, not sure if interspacing is allowed but it gives problems (see bug 640847) +<BasesProt>{BN} { lineCount(yyscanner); } +<BasesProt>. { unput(*yytext); BEGIN(Bases); } +<Bases>("\\")?({ID}"\\")*{ID} { // PHP namespace token, not sure if interspacing is allowed but it gives problems (see bug 640847) if (!yyextra->insidePHP) - { - REJECT; - } - else // PHP base class of the form \Ns\Cl or Ns\Cl - { - lineCount(yyscanner); - QCString bn=yytext; - bn = substitute(bn,"\\","::"); - yyextra->baseName += bn; - yyextra->current->args += ' '; - yyextra->current->args += yytext; - } - } -<Bases>("::")?{BN}*({ID}{BN}*"::"{BN}*)*{ID} { - lineCount(yyscanner); + { + REJECT; + } + else // PHP base class of the form \Ns\Cl or Ns\Cl + { + lineCount(yyscanner); + QCString bn=yytext; + bn = substitute(bn,"\\","::"); + yyextra->baseName += bn; + yyextra->current->args += ' '; + yyextra->current->args += yytext; + } + } +<Bases>("::")?{BN}*({ID}{BN}*"::"{BN}*)*{ID} { + lineCount(yyscanner); QCString baseScope = yytext; if (yyextra->insideCS && baseScope.stripWhiteSpace()=="where") - { - // type constraint for a class + { + // type constraint for a class yyextra->current->typeConstr.clear(); - yyextra->current->typeConstr.push_back(Argument()); - yyextra->lastCSConstraint = YY_START; - BEGIN( CSConstraintName ); - } - else - { - yyextra->baseName+=yytext; - yyextra->current->args += ' '; - yyextra->current->args += yytext; - } - } -<Bases>{BN}*{ID}("."{ID})* { // Java style class - QCString name = substitute(yytext,".","::"); - yyextra->baseName += name; - yyextra->current->args += ' '; - yyextra->current->args += name; - } -<ClassVar,Bases>\n/{BN}*[^{, \t\n] { - if (!yyextra->insideObjC) - { - REJECT; - } - else - { + yyextra->current->typeConstr.push_back(Argument()); + yyextra->lastCSConstraint = YY_START; + BEGIN( CSConstraintName ); + } + else + { + yyextra->baseName+=yytext; + yyextra->current->args += ' '; + yyextra->current->args += yytext; + } + } +<Bases>{BN}*{ID}("."{ID})* { // Java style class + QCString name = substitute(yytext,".","::"); + yyextra->baseName += name; + yyextra->current->args += ' '; + yyextra->current->args += name; + } +<ClassVar,Bases>\n/{BN}*[^{, \t\n] { + if (!yyextra->insideObjC) + { + REJECT; + } + else + { lineCount(yyscanner); - unput('{'); - } - } -<ClassVar,Bases>"@end" { // empty ObjC interface - unput('d'); // insert fake body: {}@end - unput('n'); - unput('e'); - unput('@'); - unput('}'); - unput('{'); - } -<ClassVar>"<" { yyextra->current->name += *yytext; - yyextra->sharpCount=1; - yyextra->roundCount=0; - yyextra->lastSkipSharpContext = YY_START; - yyextra->specName = &yyextra->current->name; - BEGIN ( Specialization ); - } + unput('{'); + } + } +<ClassVar,Bases>"@end" { // empty ObjC interface + unput('d'); // insert fake body: {}@end + unput('n'); + unput('e'); + unput('@'); + unput('}'); + unput('{'); + } +<ClassVar>"<" { yyextra->current->name += *yytext; + yyextra->sharpCount=1; + yyextra->roundCount=0; + yyextra->lastSkipSharpContext = YY_START; + yyextra->specName = &yyextra->current->name; + BEGIN ( Specialization ); + } <Bases>{BN}*"<" { lineCount(yyscanner); - yyextra->sharpCount=1; - yyextra->roundCount=0; - yyextra->lastSkipSharpContext = YY_START; - if (yyextra->insideObjC) // start of protocol list - { - unput(','); - } - else // template specialization - { - //if (yyextra->insideCS) // generic - //{ - // yyextra->baseName+="-g"; - //} + yyextra->sharpCount=1; + yyextra->roundCount=0; + yyextra->lastSkipSharpContext = YY_START; + if (yyextra->insideObjC) // start of protocol list + { + unput(','); + } + else // template specialization + { + //if (yyextra->insideCS) // generic + //{ + // yyextra->baseName+="-g"; + //} yyextra->templateStr = yytext; - yyextra->specName = &yyextra->templateStr; - BEGIN ( Specialization ); - } - } -<Specialization>"<" { *yyextra->specName += *yytext; - if (yyextra->roundCount==0) yyextra->sharpCount++; - } -<Specialization>">" { - *yyextra->specName += *yytext; - if (yyextra->roundCount==0 && --yyextra->sharpCount<=0) - { - yyextra->baseName+=removeRedundantWhiteSpace(*yyextra->specName); - BEGIN(yyextra->lastSkipSharpContext); - } - } -<Specialization>{BN}+ { lineCount(yyscanner); *yyextra->specName +=' '; } -<Specialization>"<<" { *yyextra->specName += yytext; } -<Specialization>">>"/{B}*"::" { // M$ C++ extension to allow >> to close a template... - unput('>'); - unput(' '); - unput('>'); - } -<Specialization>">>" { + yyextra->specName = &yyextra->templateStr; + BEGIN ( Specialization ); + } + } +<Specialization>"<" { *yyextra->specName += *yytext; + if (yyextra->roundCount==0) yyextra->sharpCount++; + } +<Specialization>">" { + *yyextra->specName += *yytext; + if (yyextra->roundCount==0 && --yyextra->sharpCount<=0) + { + yyextra->baseName+=removeRedundantWhiteSpace(*yyextra->specName); + BEGIN(yyextra->lastSkipSharpContext); + } + } +<Specialization>{BN}+ { lineCount(yyscanner); *yyextra->specName +=' '; } +<Specialization>"<<" { *yyextra->specName += yytext; } +<Specialization>">>"/{B}*"::" { // M$ C++ extension to allow >> to close a template... + unput('>'); + unput(' '); + unput('>'); + } +<Specialization>">>" { if (yyextra->insideCS) // for C# >> ends a nested template - { - REJECT; - } - else // for C++ >> is a bitshift - // operator and > > would end - // a nested template. - // We require the bitshift to be enclosed in braces. - // See http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1757.html - { - if (yyextra->roundCount>0) - { - *yyextra->specName += yytext; - } - else - { - unput('>'); - unput(' '); - unput('>'); - } - } - } -<Specialization>"typename"{BN}+ { lineCount(yyscanner); } -<Specialization>"(" { *yyextra->specName += *yytext; yyextra->roundCount++; } -<Specialization>")" { *yyextra->specName += *yytext; yyextra->roundCount--; } - -<Specialization>"\\\\" { *yyextra->specName += *yytext;} -<Specialization>"\\'" { *yyextra->specName += *yytext;} -<Specialization>"\\\"" { *yyextra->specName += *yytext;} -<Specialization>"'" { *yyextra->specName += *yytext;BEGIN(SpecializationSingleQuote);} -<Specialization>"\"" { *yyextra->specName += *yytext;BEGIN(SpecializationDoubleQuote);} + { + REJECT; + } + else // for C++ >> is a bitshift + // operator and > > would end + // a nested template. + // We require the bitshift to be enclosed in braces. + // See http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1757.html + { + if (yyextra->roundCount>0) + { + *yyextra->specName += yytext; + } + else + { + unput('>'); + unput(' '); + unput('>'); + } + } + } +<Specialization>"typename"{BN}+ { lineCount(yyscanner); } +<Specialization>"(" { *yyextra->specName += *yytext; yyextra->roundCount++; } +<Specialization>")" { *yyextra->specName += *yytext; yyextra->roundCount--; } + +<Specialization>"\\\\" { *yyextra->specName += *yytext;} +<Specialization>"\\'" { *yyextra->specName += *yytext;} +<Specialization>"\\\"" { *yyextra->specName += *yytext;} +<Specialization>"'" { *yyextra->specName += *yytext;BEGIN(SpecializationSingleQuote);} +<Specialization>"\"" { *yyextra->specName += *yytext;BEGIN(SpecializationDoubleQuote);} <SpecializationSingleQuote,SpecializationDoubleQuote>"\\\\" { *yyextra->specName += *yytext;} <SpecializationSingleQuote>"\\'" { *yyextra->specName += *yytext;} <SpecializationSingleQuote>"'" { *yyextra->specName += *yytext; BEGIN(Specialization);} @@ -5837,154 +5858,154 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) <SpecializationDoubleQuote>"\"" { *yyextra->specName += *yytext; BEGIN(Specialization);} <SpecializationSingleQuote,SpecializationDoubleQuote>. { *yyextra->specName += *yytext;} -<Specialization>. { - *yyextra->specName += *yytext; - } -<SkipRound>"(" { ++yyextra->roundCount; } -<SkipRound>")" { if (--yyextra->roundCount<0) - BEGIN ( yyextra->lastSkipRoundContext ); - } -<SkipRound>\" { - yyextra->lastStringContext=SkipRound; - BEGIN(SkipString); - } -<Bases>","|(">"({BN}*"{")?)|({BN}+"implements"{BN}*) { lineCount(yyscanner); +<Specialization>. { + *yyextra->specName += *yytext; + } +<SkipRound>"(" { ++yyextra->roundCount; } +<SkipRound>")" { if (--yyextra->roundCount<0) + BEGIN ( yyextra->lastSkipRoundContext ); + } +<SkipRound>\" { + yyextra->lastStringContext=SkipRound; + BEGIN(SkipString); + } +<Bases>","|(">"({BN}*"{")?)|({BN}+"implements"{BN}*) { lineCount(yyscanner); if (yyextra->insideProtocolList) - { - yyextra->baseName+="-p"; - } - else - { - yyextra->current->args += ',' ; - } - yyextra->current->name = removeRedundantWhiteSpace(yyextra->current->name); - if (!yyextra->baseName.isEmpty()) - { - yyextra->current->extends.push_back( - BaseInfo(yyextra->baseName,yyextra->baseProt,yyextra->baseVirt) - ); - } - if ((yyextra->current->spec & (Entry::Interface|Entry::Struct)) || - yyextra->insideJava || yyextra->insidePHP || yyextra->insideCS || - yyextra->insideD || yyextra->insideObjC || yyextra->insideIDL || yyextra->insideSlice) - { - yyextra->baseProt=Public; - } - else - { - yyextra->baseProt=Private; - } - yyextra->baseVirt=Normal; - yyextra->baseName.resize(0); + { + yyextra->baseName+="-p"; + } + else + { + yyextra->current->args += ',' ; + } + yyextra->current->name = removeRedundantWhiteSpace(yyextra->current->name); + if (!yyextra->baseName.isEmpty()) + { + yyextra->current->extends.push_back( + BaseInfo(yyextra->baseName,yyextra->baseProt,yyextra->baseVirt) + ); + } + if ((yyextra->current->spec & (Entry::Interface|Entry::Struct)) || + yyextra->insideJava || yyextra->insidePHP || yyextra->insideCS || + yyextra->insideD || yyextra->insideObjC || yyextra->insideIDL || yyextra->insideSlice) + { + yyextra->baseProt=Public; + } + else + { + yyextra->baseProt=Private; + } + yyextra->baseVirt=Normal; + yyextra->baseName.resize(0); if (*yytext=='>') - { // end of a ObjC protocol list - yyextra->insideProtocolList=FALSE; - if (yyleng==1) - { - unput('{'); // dummy start body - } - else - { - yyless(1); - } - } - else - { - if (*yytext==',' && yyextra->insideObjC) // Begin of protocol list - { - yyextra->insideProtocolList=TRUE; - } - BEGIN(BasesProt); - } - } -<Bases>{B}*"{"{B}* { + { // end of a ObjC protocol list + yyextra->insideProtocolList=FALSE; + if (yyleng==1) + { + unput('{'); // dummy start body + } + else + { + yyless(1); + } + } + else + { + if (*yytext==',' && yyextra->insideObjC) // Begin of protocol list + { + yyextra->insideProtocolList=TRUE; + } + BEGIN(BasesProt); + } + } +<Bases>{B}*"{"{B}* { yyextra->current->program.resize(0); yyextra->current->fileName = yyextra->yyFileName ; - yyextra->current->bodyLine = yyextra->yyLineNr; - yyextra->current->bodyColumn = yyextra->yyColNr; - yyextra->current->name = removeRedundantWhiteSpace(yyextra->current->name); - if (!yyextra->baseName.isEmpty()) - yyextra->current->extends.push_back( - BaseInfo(yyextra->baseName,yyextra->baseProt,yyextra->baseVirt) - ); - yyextra->curlyCount=0; - if (yyextra->insideObjC) - { - BEGIN( ReadBodyIntf ); - } - else - { - BEGIN( ReadBody ) ; - } - } -<SkipUnionSwitch>{B}*"(" { - yyextra->roundCount++; - } -<SkipUnionSwitch>")" { - if (--yyextra->roundCount==0) - { - BEGIN(ClassVar); - } - } -<SkipUnionSwitch>\n { lineCount(yyscanner); } -<SkipUnionSwitch>. -<Comment>{BN}+ { yyextra->current->program += yytext ; - lineCount(yyscanner) ; - } -<Comment>"/*" { yyextra->current->program += yytext ; } -<Comment>"//" { yyextra->current->program += yytext ; } -<Comment>{CMD}("code"|"verbatim") { + yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->current->bodyColumn = yyextra->yyColNr; + yyextra->current->name = removeRedundantWhiteSpace(yyextra->current->name); + if (!yyextra->baseName.isEmpty()) + yyextra->current->extends.push_back( + BaseInfo(yyextra->baseName,yyextra->baseProt,yyextra->baseVirt) + ); + yyextra->curlyCount=0; + if (yyextra->insideObjC) + { + BEGIN( ReadBodyIntf ); + } + else + { + BEGIN( ReadBody ) ; + } + } +<SkipUnionSwitch>{B}*"(" { + yyextra->roundCount++; + } +<SkipUnionSwitch>")" { + if (--yyextra->roundCount==0) + { + BEGIN(ClassVar); + } + } +<SkipUnionSwitch>\n { lineCount(yyscanner); } +<SkipUnionSwitch>. +<Comment>{BN}+ { yyextra->current->program += yytext ; + lineCount(yyscanner) ; + } +<Comment>"/*" { yyextra->current->program += yytext ; } +<Comment>"//" { yyextra->current->program += yytext ; } +<Comment>{CMD}("code"|"verbatim") { yyextra->insideCode=TRUE; - yyextra->current->program += yytext ; - } -<Comment>{CMD}("endcode"|"endverbatim") { + yyextra->current->program += yytext ; + } +<Comment>{CMD}("endcode"|"endverbatim") { yyextra->insideCode=FALSE; - yyextra->current->program += yytext ; - } -<Comment>[^ \.\t\r\n\/\*]+ { yyextra->current->program += yytext ; } -<Comment>"*/" { yyextra->current->program += yytext ; - if (!yyextra->insideCode) BEGIN( yyextra->lastContext ) ; - } -<Comment>. { yyextra->current->program += *yytext ; } + yyextra->current->program += yytext ; + } +<Comment>[^ \.\t\r\n\/\*]+ { yyextra->current->program += yytext ; } +<Comment>"*/" { yyextra->current->program += yytext ; + if (!yyextra->insideCode) BEGIN( yyextra->lastContext ) ; + } +<Comment>. { yyextra->current->program += *yytext ; } -<FindMembers,FindFields,MemberSpec,FuncQual,SkipCurly,Operator,ClassVar,SkipInits,SkipC11Inits,SkipC11Attribute,Bases,OldStyleArgs>("//"{B}*)?"/*!" { - //printf("Start doc block at %d\n",yyextra->yyLineNr); - if (!yyextra->current->doc.isEmpty()) - { - yyextra->current->doc+="\n\n"; - } - else - { - yyextra->current->docLine = yyextra->yyLineNr; - yyextra->current->docFile = yyextra->yyFileName; - } +<FindMembers,FindFields,MemberSpec,FuncQual,SkipCurly,Operator,ClassVar,SkipInits,SkipC11Inits,SkipC11Attribute,Bases,OldStyleArgs>("//"{B}*)?"/*!" { + //printf("Start doc block at %d\n",yyextra->yyLineNr); + if (!yyextra->current->doc.isEmpty()) + { + yyextra->current->doc+="\n\n"; + } + else + { + yyextra->current->docLine = yyextra->yyLineNr; + yyextra->current->docFile = yyextra->yyFileName; + } - yyextra->lastDocContext = YY_START; - if (yyextra->current_root->section & Entry::SCOPE_MASK) + yyextra->lastDocContext = YY_START; + if (yyextra->current_root->section & Entry::SCOPE_MASK) { - yyextra->current->inside = yyextra->current_root->name+"::"; + yyextra->current->inside = yyextra->current_root->name+"::"; } - yyextra->docBlockContext = YY_START; - yyextra->docBlockInBody = YY_START==SkipCurly; - yyextra->docBlockAutoBrief = Config_getBool(QT_AUTOBRIEF); + yyextra->docBlockContext = YY_START; + yyextra->docBlockInBody = YY_START==SkipCurly; + yyextra->docBlockAutoBrief = Config_getBool(QT_AUTOBRIEF); QCString indent; indent.fill(' ',computeIndent(yytext,yyextra->column)); yyextra->docBlock=indent; - if (yyextra->docBlockAutoBrief) - { - yyextra->current->briefLine = yyextra->yyLineNr; - yyextra->current->briefFile = yyextra->yyFileName; - } - startCommentBlock(yyscanner,FALSE); - BEGIN( DocBlock ); - } + if (yyextra->docBlockAutoBrief) + { + yyextra->current->briefLine = yyextra->yyLineNr; + yyextra->current->briefFile = yyextra->yyFileName; + } + startCommentBlock(yyscanner,FALSE); + BEGIN( DocBlock ); + } <FindMembers,FindFields,MemberSpec,FuncQual,SkipCurly,Operator,ClassVar,SkipInits,Bases,OldStyleArgs>"/**"[*]+{BL} { - bool javadocBanner = Config_getBool(JAVADOC_BANNER); + bool javadocBanner = Config_getBool(JAVADOC_BANNER); lineCount(yyscanner); - if( javadocBanner ) + if( javadocBanner ) { yyextra->lastDocContext = YY_START; @@ -6014,185 +6035,185 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) } else { - yyextra->current->program += yytext ; - yyextra->lastContext = YY_START ; - BEGIN( Comment ) ; - } - } + yyextra->current->program += yytext ; + yyextra->lastContext = YY_START ; + BEGIN( Comment ) ; + } + } <FindMembers,FindFields,MemberSpec,FuncQual,SkipCurly,Operator,ClassVar,SkipInits,Bases,OldStyleArgs>("//"{B}*)?"/**"/[^/*] { - yyextra->lastDocContext = YY_START; + yyextra->lastDocContext = YY_START; - //printf("Found comment block at %s:%d\n",yyextra->yyFileName,yyextra->yyLineNr); - if (yyextra->current_root->section & Entry::SCOPE_MASK) + //printf("Found comment block at %s:%d\n",yyextra->yyFileName,yyextra->yyLineNr); + if (yyextra->current_root->section & Entry::SCOPE_MASK) { - yyextra->current->inside = yyextra->current_root->name+"::"; + yyextra->current->inside = yyextra->current_root->name+"::"; } - yyextra->current->docLine = yyextra->yyLineNr; - yyextra->current->docFile = yyextra->yyFileName; - yyextra->docBlockContext = YY_START; - yyextra->docBlockInBody = YY_START==SkipCurly; + yyextra->current->docLine = yyextra->yyLineNr; + yyextra->current->docFile = yyextra->yyFileName; + yyextra->docBlockContext = YY_START; + yyextra->docBlockInBody = YY_START==SkipCurly; bool javadocAutoBrief = Config_getBool(JAVADOC_AUTOBRIEF); - yyextra->docBlockAutoBrief = javadocAutoBrief; + yyextra->docBlockAutoBrief = javadocAutoBrief; QCString indent; indent.fill(' ',computeIndent(yytext,yyextra->column)); yyextra->docBlock=indent; - if (yyextra->docBlockAutoBrief) - { - yyextra->current->briefLine = yyextra->yyLineNr; - yyextra->current->briefFile = yyextra->yyFileName; - } - startCommentBlock(yyscanner,FALSE); - BEGIN( DocBlock ); - } -<FindMembers,FindFields,MemberSpec,SkipCurly,FuncQual,Operator,ClassVar,Bases,OldStyleArgs>"//!" { - yyextra->lastDocContext = YY_START; - if (yyextra->current_root->section & Entry::SCOPE_MASK) + if (yyextra->docBlockAutoBrief) { - yyextra->current->inside = yyextra->current_root->name+"::"; + yyextra->current->briefLine = yyextra->yyLineNr; + yyextra->current->briefFile = yyextra->yyFileName; } - yyextra->docBlockContext = YY_START; - yyextra->docBlockInBody = YY_START==SkipCurly; - yyextra->docBlockAutoBrief = FALSE; + startCommentBlock(yyscanner,FALSE); + BEGIN( DocBlock ); + } +<FindMembers,FindFields,MemberSpec,SkipCurly,FuncQual,Operator,ClassVar,Bases,OldStyleArgs>"//!" { + yyextra->lastDocContext = YY_START; + if (yyextra->current_root->section & Entry::SCOPE_MASK) + { + yyextra->current->inside = yyextra->current_root->name+"::"; + } + yyextra->docBlockContext = YY_START; + yyextra->docBlockInBody = YY_START==SkipCurly; + yyextra->docBlockAutoBrief = FALSE; QCString indent; indent.fill(' ',computeIndent(yytext,yyextra->column)); yyextra->docBlock=indent; - startCommentBlock(yyscanner,yyextra->current->brief.isEmpty()); - BEGIN( DocLine ); - } -<FindMembers,FindFields,MemberSpec,SkipCurly,FuncQual,Operator,ClassVar,Bases,OldStyleArgs>"///"/[^/] { - yyextra->lastDocContext = YY_START; - if (yyextra->current_root->section & Entry::SCOPE_MASK) + startCommentBlock(yyscanner,yyextra->current->brief.isEmpty()); + BEGIN( DocLine ); + } +<FindMembers,FindFields,MemberSpec,SkipCurly,FuncQual,Operator,ClassVar,Bases,OldStyleArgs>"///"/[^/] { + yyextra->lastDocContext = YY_START; + if (yyextra->current_root->section & Entry::SCOPE_MASK) { - yyextra->current->inside = yyextra->current_root->name+"::"; + yyextra->current->inside = yyextra->current_root->name+"::"; } - yyextra->docBlockContext = YY_START; - yyextra->docBlockInBody = YY_START==SkipCurly; - yyextra->docBlockAutoBrief = FALSE; + yyextra->docBlockContext = YY_START; + yyextra->docBlockInBody = YY_START==SkipCurly; + yyextra->docBlockAutoBrief = FALSE; QCString indent; indent.fill(' ',computeIndent(yytext,yyextra->column)); yyextra->docBlock=indent; - startCommentBlock(yyscanner,yyextra->current->brief.isEmpty()); - BEGIN( DocLine ); - } + startCommentBlock(yyscanner,yyextra->current->brief.isEmpty()); + BEGIN( DocLine ); + } <FindMembers>"extern"{BN}*"\"C"("++")?"\""{BN}*("{")? { - lineCount(yyscanner); - yyextra->externC=TRUE; - } -<FindMembers>"{" { - if (yyextra->externC) - { - yyextra->externC=FALSE; - } - else if (yyextra->insideCS && - !yyextra->current->name.isEmpty() && - !yyextra->current->type.isEmpty()) - { - if (containsWord(yyextra->current->type,"event")) // event - { - yyextra->current->mtype = yyextra->mtype = Event; - } - else // property - { - yyextra->current->mtype = yyextra->mtype = Property; - } - yyextra->current->bodyLine = yyextra->yyLineNr; - yyextra->current->bodyColumn = yyextra->yyColNr; - yyextra->curlyCount=0; - BEGIN( CSAccessorDecl ); - } - else if (yyextra->insideIDL && (yyextra->current->spec & Entry::Attribute)) - { - // UNO IDL: attributes may have setter and getter - // exception specifications - yyextra->current->exception = " {"; - BEGIN(UNOIDLAttributeBlock); - } - else - { - if ((yyextra->insideJava || yyextra->insideCS || yyextra->insideD) && - yyextra->current->name.isEmpty() - ) - { - // static Java initializer - yyextra->needsSemi = FALSE; - if (yyextra->current->stat) - { - yyextra->current->name="[static initializer]"; - yyextra->current->type.resize(0); - } - else - { - yyextra->current->name="[instance initializer]"; - } - unput(*yytext); - BEGIN( Function ); - } - else - { - // pre C++11 code -> ignore the initializer + lineCount(yyscanner); + yyextra->externC=TRUE; + } +<FindMembers>"{" { + if (yyextra->externC) + { + yyextra->externC=FALSE; + } + else if (yyextra->insideCS && + !yyextra->current->name.isEmpty() && + !yyextra->current->type.isEmpty()) + { + if (containsWord(yyextra->current->type,"event")) // event + { + yyextra->current->mtype = yyextra->mtype = Event; + } + else // property + { + yyextra->current->mtype = yyextra->mtype = Property; + } + yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->current->bodyColumn = yyextra->yyColNr; + yyextra->curlyCount=0; + BEGIN( CSAccessorDecl ); + } + else if (yyextra->insideIDL && (yyextra->current->spec & Entry::Attribute)) + { + // UNO IDL: attributes may have setter and getter + // exception specifications + yyextra->current->exception = " {"; + BEGIN(UNOIDLAttributeBlock); + } + else + { + if ((yyextra->insideJava || yyextra->insideCS || yyextra->insideD) && + yyextra->current->name.isEmpty() + ) + { + // static Java initializer + yyextra->needsSemi = FALSE; + if (yyextra->current->stat) + { + yyextra->current->name="[static initializer]"; + yyextra->current->type.resize(0); + } + else + { + yyextra->current->name="[instance initializer]"; + } + unput(*yytext); + BEGIN( Function ); + } + else + { + // pre C++11 code -> ignore the initializer //yyextra->needsSemi = TRUE; - //yyextra->current->type.resize(0); - //yyextra->current->name.resize(0); - //yyextra->current->args.resize(0); - //yyextra->current->argList.clear(); - //yyextra->curlyCount=0; - //BEGIN( SkipCurlyBlock ); + //yyextra->current->type.resize(0); + //yyextra->current->name.resize(0); + //yyextra->current->args.resize(0); + //yyextra->current->argList.clear(); + //yyextra->curlyCount=0; + //BEGIN( SkipCurlyBlock ); // C++11 style initializer list - yyextra->current->bodyLine = yyextra->yyLineNr; - yyextra->current->bodyColumn = yyextra->yyColNr; + yyextra->current->bodyLine = yyextra->yyLineNr; + yyextra->current->bodyColumn = yyextra->yyColNr; yyextra->current->initializer = yytext; - yyextra->lastInitializerContext = YY_START; - yyextra->initBracketCount=1; - BEGIN(ReadInitializer); - } - } - } -<CSAccessorDecl>"{" { yyextra->curlyCount++; } -<CSAccessorDecl>"}"{B}*"=" { - // fall back to next rule if it's not the right bracket - if (yyextra->curlyCount != 0) REJECT; - yyextra->current->initializer = "="; - yyextra->current->endBodyLine=yyextra->yyLineNr; - yyextra->lastInitializerContext = FindMembers; - BEGIN(ReadInitializer); - } -<CSAccessorDecl>"}" { - if (yyextra->curlyCount) - { - yyextra->curlyCount--; - } - else - { - yyextra->mtype = Method; + yyextra->lastInitializerContext = YY_START; + yyextra->initBracketCount=1; + BEGIN(ReadInitializer); + } + } + } +<CSAccessorDecl>"{" { yyextra->curlyCount++; } +<CSAccessorDecl>"}"{B}*"=" { + // fall back to next rule if it's not the right bracket + if (yyextra->curlyCount != 0) REJECT; + yyextra->current->initializer = "="; + yyextra->current->endBodyLine=yyextra->yyLineNr; + yyextra->lastInitializerContext = FindMembers; + BEGIN(ReadInitializer); + } +<CSAccessorDecl>"}" { + if (yyextra->curlyCount) + { + yyextra->curlyCount--; + } + else + { + yyextra->mtype = Method; yyextra->virt = Normal; - // not really important, but while we are at it - yyextra->current->endBodyLine=yyextra->yyLineNr; + // not really important, but while we are at it + yyextra->current->endBodyLine=yyextra->yyLineNr; unput(';'); - BEGIN(FindMembers); - } - } -<CSAccessorDecl>"private "{BN}*"set" { if (yyextra->curlyCount==0) yyextra->current->spec |= Entry::PrivateSettable; } -<CSAccessorDecl>"protected "{BN}*"set" { if (yyextra->curlyCount==0) yyextra->current->spec |= Entry::ProtectedSettable; } -<CSAccessorDecl>"private "{BN}*"get" { if (yyextra->curlyCount==0) yyextra->current->spec |= Entry::PrivateGettable; } -<CSAccessorDecl>"protected "{BN}*"get" { if (yyextra->curlyCount==0) yyextra->current->spec |= Entry::ProtectedGettable; } -<CSAccessorDecl>"set" { if (yyextra->curlyCount==0) yyextra->current->spec |= Entry::Settable; } -<CSAccessorDecl>"get" { if (yyextra->curlyCount==0) yyextra->current->spec |= Entry::Gettable; } -<CSAccessorDecl>"add" { if (yyextra->curlyCount==0) yyextra->current->spec |= Entry::Addable; } -<CSAccessorDecl>"remove" { if (yyextra->curlyCount==0) yyextra->current->spec |= Entry::Removable; } -<CSAccessorDecl>"raise" { if (yyextra->curlyCount==0) yyextra->current->spec |= Entry::Raisable; } -<CSAccessorDecl>"\"" { BEGIN(CSString);} -<CSAccessorDecl>"." {} -<CSAccessorDecl>\n { lineCount(yyscanner); } -<CSString>"\"" { BEGIN(CSAccessorDecl);} -<CSString>"//" {} // Otherwise the rule <*>"//" will kick in -<CSString>"/*" {} // Otherwise the rule <*>"/*" will kick in -<CSString>\n { lineCount(yyscanner); } -<CSString>"." {} + BEGIN(FindMembers); + } + } +<CSAccessorDecl>"private "{BN}*"set" { if (yyextra->curlyCount==0) yyextra->current->spec |= Entry::PrivateSettable; } +<CSAccessorDecl>"protected "{BN}*"set" { if (yyextra->curlyCount==0) yyextra->current->spec |= Entry::ProtectedSettable; } +<CSAccessorDecl>"private "{BN}*"get" { if (yyextra->curlyCount==0) yyextra->current->spec |= Entry::PrivateGettable; } +<CSAccessorDecl>"protected "{BN}*"get" { if (yyextra->curlyCount==0) yyextra->current->spec |= Entry::ProtectedGettable; } +<CSAccessorDecl>"set" { if (yyextra->curlyCount==0) yyextra->current->spec |= Entry::Settable; } +<CSAccessorDecl>"get" { if (yyextra->curlyCount==0) yyextra->current->spec |= Entry::Gettable; } +<CSAccessorDecl>"add" { if (yyextra->curlyCount==0) yyextra->current->spec |= Entry::Addable; } +<CSAccessorDecl>"remove" { if (yyextra->curlyCount==0) yyextra->current->spec |= Entry::Removable; } +<CSAccessorDecl>"raise" { if (yyextra->curlyCount==0) yyextra->current->spec |= Entry::Raisable; } +<CSAccessorDecl>"\"" { BEGIN(CSString);} +<CSAccessorDecl>"." {} +<CSAccessorDecl>\n { lineCount(yyscanner); } +<CSString>"\"" { BEGIN(CSAccessorDecl);} +<CSString>"//" {} // Otherwise the rule <*>"//" will kick in +<CSString>"/*" {} // Otherwise the rule <*>"/*" will kick in +<CSString>\n { lineCount(yyscanner); } +<CSString>"." {} /* ---- Slice-specific rules ------ */ @@ -6260,80 +6281,80 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) /* ---- Single line comments ------ */ <DocLine>[^\n]*"\n"[ \t]*"//"[/!][<]? { // continuation of multiline C++-style comment - yyextra->docBlock+=yytext; + yyextra->docBlock+=yytext; int markerLen = yytext[yyleng-1]=='<' ? 4 : 3; - yyextra->docBlock.resize(yyextra->docBlock.length() - markerLen); + yyextra->docBlock.resize(yyextra->docBlock.length() - markerLen); lineCount(yyscanner); } -<DocLine>{B}*"///"[/]+{B}*/"\n" { // ignore marker line (see bug700345) - handleCommentBlock(yyscanner,yyextra->docBlock.data(),yyextra->current->brief.isEmpty()); - BEGIN( yyextra->docBlockContext ); - } -<DocLine>[^\n]*/"\n"{B}*"//"[!/]{B}*{CMD}"}" { // next line is an end group marker, see bug 752712 - yyextra->docBlock+=yytext; - handleCommentBlock(yyscanner,yyextra->docBlock.data(),yyextra->current->brief.isEmpty()); - BEGIN( yyextra->docBlockContext ); - } -<DocLine>[^\n]*/"\n" { // whole line - yyextra->docBlock+=yytext; - handleCommentBlock(yyscanner,yyextra->docBlock.data(),yyextra->current->brief.isEmpty()); - BEGIN( yyextra->docBlockContext ); - } +<DocLine>{B}*"///"[/]+{B}*/"\n" { // ignore marker line (see bug700345) + handleCommentBlock(yyscanner,yyextra->docBlock.data(),yyextra->current->brief.isEmpty()); + BEGIN( yyextra->docBlockContext ); + } +<DocLine>[^\n]*/"\n"{B}*"//"[!/]{B}*{CMD}"}" { // next line is an end group marker, see bug 752712 + yyextra->docBlock+=yytext; + handleCommentBlock(yyscanner,yyextra->docBlock.data(),yyextra->current->brief.isEmpty()); + BEGIN( yyextra->docBlockContext ); + } +<DocLine>[^\n]*/"\n" { // whole line + yyextra->docBlock+=yytext; + handleCommentBlock(yyscanner,yyextra->docBlock.data(),yyextra->current->brief.isEmpty()); + BEGIN( yyextra->docBlockContext ); + } /* ---- Comments blocks ------ */ -<DocBlock>"*"*"*/" { // end of comment block - handleCommentBlock(yyscanner,yyextra->docBlock.data(),FALSE); - BEGIN(yyextra->docBlockContext); - } -<DocBlock>^{B}*"*"+/[^/] { +<DocBlock>"*"*"*/" { // end of comment block + handleCommentBlock(yyscanner,yyextra->docBlock.data(),FALSE); + BEGIN(yyextra->docBlockContext); + } +<DocBlock>^{B}*"*"+/[^/] { QCString indent; indent.fill(' ',computeIndent(yytext,yyextra->column)); yyextra->docBlock+=indent; - } -<DocBlock>^{B}*("//")?{B}*"*"+/[^//a-z_A-Z0-9*] { // start of a comment line + } +<DocBlock>^{B}*("//")?{B}*"*"+/[^//a-z_A-Z0-9*] { // start of a comment line QCString indent; indent.fill(' ',computeIndent(yytext,yyextra->column)); yyextra->docBlock+=indent; - } -<DocBlock>^{B}*("//"){B}* { // strip embedded C++ comments if at the start of a line - } -<DocBlock>"//" { // slashes in the middle of a comment block - yyextra->docBlock+=yytext; - } -<DocBlock>"/*" { // start of a new comment in the + } +<DocBlock>^{B}*("//"){B}* { // strip embedded C++ comments if at the start of a line + } +<DocBlock>"//" { // slashes in the middle of a comment block + yyextra->docBlock+=yytext; + } +<DocBlock>"/*" { // start of a new comment in the // middle of a comment block - yyextra->docBlock+=yytext; - } + yyextra->docBlock+=yytext; + } <DocBlock>({CMD}{CMD}){ID}/[^a-z_A-Z0-9] { // escaped command - yyextra->docBlock+=yytext; - } -<DocBlock>{CMD}("f$"|"f["|"f{") { yyextra->docBlock+=yytext; - yyextra->docBlockName=&yytext[1]; - if (yyextra->docBlockName.at(1)=='{') - { - yyextra->docBlockName.at(1)='}'; - } + } +<DocBlock>{CMD}("f$"|"f["|"f{") { + yyextra->docBlock+=yytext; + yyextra->docBlockName=&yytext[1]; + if (yyextra->docBlockName.at(1)=='{') + { + yyextra->docBlockName.at(1)='}'; + } yyextra->fencedSize=0; yyextra->nestedComment=FALSE; - BEGIN(DocCopyBlock); + BEGIN(DocCopyBlock); } -<DocBlock>{B}*"<"{PRE}">" { +<DocBlock>{B}*"<"{PRE}">" { yyextra->docBlock+=yytext; - yyextra->docBlockName="<pre>"; + yyextra->docBlockName="<pre>"; yyextra->fencedSize=0; yyextra->nestedComment=FALSE; - BEGIN(DocCopyBlock); - } -<DocBlock>{CMD}("verbatim"|"latexonly"|"htmlonly"|"xmlonly"|"manonly"|"rtfonly"|"docbookonly"|"dot"|"code")/[^a-z_A-Z0-9\-] { // verbatim command (which could contain nested comments!) + BEGIN(DocCopyBlock); + } +<DocBlock>{CMD}("verbatim"|"latexonly"|"htmlonly"|"xmlonly"|"manonly"|"rtfonly"|"docbookonly"|"dot"|"code")/[^a-z_A-Z0-9\-] { // verbatim command (which could contain nested comments!) yyextra->docBlock+=yytext; - yyextra->docBlockName=&yytext[1]; + yyextra->docBlockName=&yytext[1]; yyextra->fencedSize=0; yyextra->nestedComment=FALSE; - BEGIN(DocCopyBlock); - } + BEGIN(DocCopyBlock); + } <DocBlock>^({B}*"*"+)?{B}{0,3}"~~~"[~]* { QCString pat = substitute(yytext,"*"," "); @@ -6352,86 +6373,86 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) BEGIN(DocCopyBlock); } <DocBlock>{B}*"<code>" { - if (yyextra->insideCS) - { - yyextra->docBlock+=yytext; - yyextra->docBlockName="<code>"; + if (yyextra->insideCS) + { + yyextra->docBlock+=yytext; + yyextra->docBlockName="<code>"; yyextra->nestedComment=FALSE; - BEGIN(DocCopyBlock); - } - else - { - REJECT; - } - } -<DocBlock>[^@*~\/\\\n]+ { // any character that isn't special - yyextra->docBlock+=yytext; - } -<DocBlock>\n { // newline + BEGIN(DocCopyBlock); + } + else + { + REJECT; + } + } +<DocBlock>[^@*~\/\\\n]+ { // any character that isn't special + yyextra->docBlock+=yytext; + } +<DocBlock>\n { // newline lineCount(yyscanner); - yyextra->docBlock+=*yytext; - } -<DocBlock>. { // command block - yyextra->docBlock+=*yytext; - } + yyextra->docBlock+=*yytext; + } +<DocBlock>. { // command block + yyextra->docBlock+=*yytext; + } /* ---- Copy verbatim sections ------ */ -<DocCopyBlock>"</"{PRE}">" { // end of a <pre> block - yyextra->docBlock+=yytext; - if (yyextra->docBlockName=="<pre>") - { - BEGIN(DocBlock); - } - } -<DocCopyBlock>"</"{CODE}">" { // end of a <code> block - yyextra->docBlock+=yytext; - if (yyextra->docBlockName=="<code>") - { - BEGIN(DocBlock); - } - } +<DocCopyBlock>"</"{PRE}">" { // end of a <pre> block + yyextra->docBlock+=yytext; + if (yyextra->docBlockName=="<pre>") + { + BEGIN(DocBlock); + } + } +<DocCopyBlock>"</"{CODE}">" { // end of a <code> block + yyextra->docBlock+=yytext; + if (yyextra->docBlockName=="<code>") + { + BEGIN(DocBlock); + } + } <DocCopyBlock>[\\@]("f$"|"f]"|"f}") { - yyextra->docBlock+=yytext; - BEGIN(DocBlock); - } + yyextra->docBlock+=yytext; + BEGIN(DocBlock); + } <DocCopyBlock>[\\@]("endverbatim"|"endlatexonly"|"endhtmlonly"|"endxmlonly"|"enddocbookonly"|"endmanonly"|"endrtfonly"|"enddot"|"endcode")/[^a-z_A-Z0-9] { // end of verbatim block - yyextra->docBlock+=yytext; - if (&yytext[4]==yyextra->docBlockName) - { - BEGIN(DocBlock); - } - } -<DocCopyBlock>^{B}*"*"+/{BN}+ { // start of a comment line - if (yyextra->docBlockName=="verbatim") - { - REJECT; - } - else if (yyextra->docBlockName=="code") - { - REJECT; - } + yyextra->docBlock+=yytext; + if (&yytext[4]==yyextra->docBlockName) + { + BEGIN(DocBlock); + } + } +<DocCopyBlock>^{B}*"*"+/{BN}+ { // start of a comment line + if (yyextra->docBlockName=="verbatim") + { + REJECT; + } + else if (yyextra->docBlockName=="code") + { + REJECT; + } else { QCString indent; indent.fill(' ',computeIndent(yytext,0)); yyextra->docBlock+=indent; } - } -<DocCopyBlock>^{B}*"*"+/{B}+"*"{BN}* { // start of a comment line with two *'s - if (yyextra->docBlockName=="code") + } +<DocCopyBlock>^{B}*"*"+/{B}+"*"{BN}* { // start of a comment line with two *'s + if (yyextra->docBlockName=="code") { QCString indent; indent.fill(' ',computeIndent(yytext,0)); yyextra->docBlock+=indent; } else - { - REJECT; - } - } -<DocCopyBlock>^{B}*"*"+/({ID}|"(") { // Assume *var or *(... is part of source code (see bug723516) - if (yyextra->docBlockName=="code") + { + REJECT; + } + } +<DocCopyBlock>^{B}*"*"+/({ID}|"(") { // Assume *var or *(... is part of source code (see bug723516) + if (yyextra->docBlockName=="code") { QCString indent; indent.fill(' ',computeIndent(yytext,-1)); @@ -6442,8 +6463,8 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) REJECT; } } -<DocCopyBlock>^{B}*"*"+/{BN}* { // start of a comment line with one * - if (yyextra->docBlockName=="code") +<DocCopyBlock>^{B}*"*"+/{BN}* { // start of a comment line with one * + if (yyextra->docBlockName=="code") { QCString indent; if (yyextra->nestedComment) // keep * it is part of the code @@ -6458,10 +6479,10 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) } } else - { - REJECT; - } - } + { + REJECT; + } + } <DocCopyBlock>^({B}*"*"+)?{B}{0,3}"~~~"[~]* { QCString pat = substitute(yytext,"*"," "); yyextra->docBlock+=pat; @@ -6478,10 +6499,10 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) BEGIN(DocBlock); } } -<DocCopyBlock>[^\<@/*\]~\$\\\n]+ { // any character that is not special - yyextra->docBlock+=yytext; - } -<DocCopyBlock>"/*"|"*/"|"//" { +<DocCopyBlock>[^\<@/*\]~\$\\\n]+ { // any character that is not special + yyextra->docBlock+=yytext; + } +<DocCopyBlock>"/*"|"*/"|"//" { if (yytext[1]=='*') { yyextra->nestedComment=TRUE; @@ -6490,117 +6511,117 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) { yyextra->nestedComment=FALSE; } - yyextra->docBlock+=yytext; - } -<DocCopyBlock>\n { // newline - yyextra->docBlock+=*yytext; + yyextra->docBlock+=yytext; + } +<DocCopyBlock>\n { // newline + yyextra->docBlock+=*yytext; lineCount(yyscanner); - } -<DocCopyBlock>. { // any other character - yyextra->docBlock+=*yytext; - } -<DocCopyBlock><<EOF>> { - warn(yyextra->yyFileName,yyextra->yyLineNr, - "reached end of file while inside a '%s' block!\n" - "The command that should end the block seems to be missing!\n", - yyextra->docBlockName.data()); - yyterminate(); - } + } +<DocCopyBlock>. { // any other character + yyextra->docBlock+=*yytext; + } +<DocCopyBlock><<EOF>> { + warn(yyextra->yyFileName,yyextra->yyLineNr, + "reached end of file while inside a '%s' block!\n" + "The command that should end the block seems to be missing!\n", + yyextra->docBlockName.data()); + yyterminate(); + } /* ------------- Prototype parser -------------- */ -<Prototype>"operator"{B}*"("{B}*")" { - yyextra->current->name+=yytext; - } -<Prototype>"(" { - yyextra->current->args+=*yytext; - yyextra->currentArgumentContext = PrototypeQual; - yyextra->fullArgString = yyextra->current->args.copy(); - yyextra->copyArgString = &yyextra->current->args; - BEGIN( ReadFuncArgType ) ; - } -<Prototype>"("({ID}"::")*({B}*[&*])+ { - if (yyextra->insidePHP) // reference parameter - { - REJECT; - } - else - { - yyextra->current->type+=yyextra->current->name+yytext; - yyextra->current->name.resize(0); - BEGIN( PrototypePtr ); - } - } -<PrototypePtr>{SCOPENAME} { - yyextra->current->name+=yytext; - } -<PrototypePtr>"(" { - yyextra->current->args+=*yytext; - yyextra->currentArgumentContext = PrototypeQual; - yyextra->fullArgString = yyextra->current->args.copy(); - yyextra->copyArgString = &yyextra->current->args; - BEGIN( ReadFuncArgType ) ; - } -<PrototypePtr>")" { - yyextra->current->type+=')'; - BEGIN( Prototype ); - } -<PrototypePtr>. { - yyextra->current->name+=yytext; - } -<PrototypeQual>"{" { - BEGIN( PrototypeSkipLine); - } -<PrototypeQual>{B}*"const"{B}* { - yyextra->current->args += " const "; - yyextra->current->argList.setConstSpecifier(TRUE); - } -<PrototypeQual>{B}*"volatile"{B}* { - yyextra->current->args += " volatile "; - yyextra->current->argList.setVolatileSpecifier(TRUE); - } -<PrototypeQual>{B}*"="{B}*"0"{B}* { - yyextra->current->args += " = 0"; - yyextra->current->virt = Pure; - yyextra->current->argList.setPureSpecifier(TRUE); - } -<PrototypeQual>"throw"{B}*"(" { - yyextra->current->exception = "throw("; - BEGIN(PrototypeExc); - } -<PrototypeExc>")" { - yyextra->current->exception += ')'; - BEGIN(PrototypeQual); - } -<PrototypeExc>. { - yyextra->current->exception += *yytext; - } -<PrototypeQual>. { - yyextra->current->args += *yytext; - } -<Prototype>. { - yyextra->current->name += *yytext; - } -<PrototypeSkipLine>. { - } - - - - -<SkipCxxComment>.*"\\\n" { // line continuation - if (yyextra->insideCS) - { - REJECT; - } - else - { +<Prototype>"operator"{B}*"("{B}*")" { + yyextra->current->name+=yytext; + } +<Prototype>"(" { + yyextra->current->args+=*yytext; + yyextra->currentArgumentContext = PrototypeQual; + yyextra->fullArgString = yyextra->current->args.copy(); + yyextra->copyArgString = &yyextra->current->args; + BEGIN( ReadFuncArgType ) ; + } +<Prototype>"("({ID}"::")*({B}*[&*])+ { + if (yyextra->insidePHP) // reference parameter + { + REJECT; + } + else + { + yyextra->current->type+=yyextra->current->name+yytext; + yyextra->current->name.resize(0); + BEGIN( PrototypePtr ); + } + } +<PrototypePtr>{SCOPENAME} { + yyextra->current->name+=yytext; + } +<PrototypePtr>"(" { + yyextra->current->args+=*yytext; + yyextra->currentArgumentContext = PrototypeQual; + yyextra->fullArgString = yyextra->current->args.copy(); + yyextra->copyArgString = &yyextra->current->args; + BEGIN( ReadFuncArgType ) ; + } +<PrototypePtr>")" { + yyextra->current->type+=')'; + BEGIN( Prototype ); + } +<PrototypePtr>. { + yyextra->current->name+=yytext; + } +<PrototypeQual>"{" { + BEGIN( PrototypeSkipLine); + } +<PrototypeQual>{B}*"const"{B}* { + yyextra->current->args += " const "; + yyextra->current->argList.setConstSpecifier(TRUE); + } +<PrototypeQual>{B}*"volatile"{B}* { + yyextra->current->args += " volatile "; + yyextra->current->argList.setVolatileSpecifier(TRUE); + } +<PrototypeQual>{B}*"="{B}*"0"{B}* { + yyextra->current->args += " = 0"; + yyextra->current->virt = Pure; + yyextra->current->argList.setPureSpecifier(TRUE); + } +<PrototypeQual>"throw"{B}*"(" { + yyextra->current->exception = "throw("; + BEGIN(PrototypeExc); + } +<PrototypeExc>")" { + yyextra->current->exception += ')'; + BEGIN(PrototypeQual); + } +<PrototypeExc>. { + yyextra->current->exception += *yytext; + } +<PrototypeQual>. { + yyextra->current->args += *yytext; + } +<Prototype>. { + yyextra->current->name += *yytext; + } +<PrototypeSkipLine>. { + } + + + + +<SkipCxxComment>.*"\\\n" { // line continuation + if (yyextra->insideCS) + { + REJECT; + } + else + { lineCount(yyscanner); - } - } -<SkipCxxComment>.*/\n { - BEGIN( yyextra->lastCContext ) ; - } + } + } +<SkipCxxComment>.*/\n { + BEGIN( yyextra->lastCContext ) ; + } <SkipComment>[^\*\n]+ /* ------------ Generic rules -------------- */ @@ -6612,59 +6633,59 @@ OPERATOR "operator"{B}*({ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP}) BEGIN( SkipC11Attribute ); } -<*>\n { lineCount(yyscanner); } -<*>\" { - if (yyextra->insideIDL && yyextra->insideCppQuote) - { - BEGIN(EndCppQuote); - } - } -<*>"#" { - if (!yyextra->insidePHP) - REJECT; - yyextra->lastCContext = YY_START ; - BEGIN( SkipCxxComment ) ; - } -<*>\' { - if (yyextra->insidePHP) - { - yyextra->lastStringContext=YY_START; - BEGIN(SkipPHPString); - } - } -<*>\" { - if (yyextra->insidePHP) - { - yyextra->lastStringContext=YY_START; - BEGIN(SkipString); - } - } +<*>\n { lineCount(yyscanner); } +<*>\" { + if (yyextra->insideIDL && yyextra->insideCppQuote) + { + BEGIN(EndCppQuote); + } + } +<*>"#" { + if (!yyextra->insidePHP) + REJECT; + yyextra->lastCContext = YY_START ; + BEGIN( SkipCxxComment ) ; + } +<*>\' { + if (yyextra->insidePHP) + { + yyextra->lastStringContext=YY_START; + BEGIN(SkipPHPString); + } + } +<*>\" { + if (yyextra->insidePHP) + { + yyextra->lastStringContext=YY_START; + BEGIN(SkipString); + } + } <*>\? { - if (yyextra->insideCS && (YY_START != SkipRound)) - { - if (yyextra->current->type.isEmpty()) - { - if (yyextra->current->name.isEmpty()) - yyextra->current->name="?"; - else - yyextra->current->name+="?"; - } - else - { - yyextra->current->type+="?"; - } - } - } + if (yyextra->insideCS && (YY_START != SkipRound)) + { + if (yyextra->current->type.isEmpty()) + { + if (yyextra->current->name.isEmpty()) + yyextra->current->name="?"; + else + yyextra->current->name+="?"; + } + else + { + yyextra->current->type+="?"; + } + } + } <*>. <SkipComment>"//"|"/*" -<*>"/*" { yyextra->lastCContext = YY_START ; - BEGIN( SkipComment ) ; - } -<SkipComment>{B}*"*/" { BEGIN( yyextra->lastCContext ) ; } -<*>"//" { - yyextra->lastCContext = YY_START ; - BEGIN( SkipCxxComment ) ; - } +<*>"/*" { yyextra->lastCContext = YY_START ; + BEGIN( SkipComment ) ; + } +<SkipComment>{B}*"*/" { BEGIN( yyextra->lastCContext ) ; } +<*>"//" { + yyextra->lastCContext = YY_START ; + BEGIN( SkipCxxComment ) ; + } %% //---------------------------------------------------------------------------- @@ -6709,7 +6730,7 @@ static void initParser(yyscan_t yyscanner) static void initEntry(yyscan_t yyscanner) { struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; - if (yyextra->insideJava) + if (yyextra->insideJava) { yyextra->protection = (yyextra->current_root->spec & (Entry::Interface|Entry::Enum)) ? Public : Package; } @@ -6733,15 +6754,15 @@ static void lineCount(yyscan_t yyscanner) const char *p; for (p = yytext ; *p ; ++p ) { - if (*p=='\n') + if (*p=='\n') { yyextra->yyLineNr++,yyextra->column=0,yyextra->yyColNr=1; } - else if (*p=='\t') + else if (*p=='\t') { yyextra->column+=tabSize - (yyextra->column%tabSize); } - else + else { yyextra->column++,yyextra->yyColNr++; } @@ -6768,14 +6789,14 @@ static void addType(yyscan_t yyscanner) { struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; uint tl=yyextra->current->type.length(); - if( tl>0 && !yyextra->current->name.isEmpty() && yyextra->current->type.at(tl-1)!='.') + if( tl>0 && !yyextra->current->name.isEmpty() && yyextra->current->type.at(tl-1)!='.') { yyextra->current->type += ' ' ; } yyextra->current->type += yyextra->current->name ; yyextra->current->name.resize(0) ; tl=yyextra->current->type.length(); - if( tl>0 && !yyextra->current->args.isEmpty() && yyextra->current->type.at(tl-1)!='.') + if( tl>0 && !yyextra->current->args.isEmpty() && yyextra->current->type.at(tl-1)!='.') { yyextra->current->type += ' ' ; } @@ -6816,7 +6837,7 @@ static void setContext(yyscan_t yyscanner) yyextra->language = getLanguageFromFileName(yyextra->yyFileName); yyextra->insideIDL = yyextra->language==SrcLangExt_IDL; yyextra->insideJava = yyextra->language==SrcLangExt_Java; - yyextra->insideCS = yyextra->language==SrcLangExt_CSharp; + yyextra->insideCS = yyextra->language==SrcLangExt_CSharp; yyextra->insideD = yyextra->language==SrcLangExt_D; yyextra->insidePHP = yyextra->language==SrcLangExt_PHP; yyextra->insideObjC = yyextra->language==SrcLangExt_ObjC; @@ -6826,7 +6847,7 @@ static void setContext(yyscan_t yyscanner) //printf("setContext(%s) yyextra->insideIDL=%d yyextra->insideJava=%d yyextra->insideCS=%d " // "yyextra->insideD=%d yyextra->insidePHP=%d yyextra->insideObjC=%d\n", // yyextra->yyFileName.data(),yyextra->insideIDL,yyextra->insideJava,yyextra->insideCS,yyextra->insideD,yyextra->insidePHP,yyextra->insideObjC - // ); + // ); } //----------------------------------------------------------------------------- @@ -6873,7 +6894,7 @@ static void splitKnRArg(yyscan_t yyscanner,QCString &oldStyleArgPtr,QCString &ol { static QRegExp re("([^)]*)"); int bi1 = yyextra->current->args.findRev(re); - int bi2 = bi1!=-1 ? yyextra->current->args.findRev(re,bi1-1) : -1; + int bi2 = bi1!=-1 ? yyextra->current->args.findRev(re,bi1-1) : -1; char c; if (bi1!=-1 && bi2!=-1) // found something like "int (*func)(int arg)" { @@ -6910,13 +6931,13 @@ static void splitKnRArg(yyscan_t yyscanner,QCString &oldStyleArgPtr,QCString &ol i++; if (i!=l) { - yyextra->oldStyleArgType=yyextra->current->args.left(i); - oldStyleArgPtr=yyextra->current->args.mid(i,j-i); - oldStyleArgName=yyextra->current->args.mid(j).stripWhiteSpace(); + yyextra->oldStyleArgType=yyextra->current->args.left(i); + oldStyleArgPtr=yyextra->current->args.mid(i,j-i); + oldStyleArgName=yyextra->current->args.mid(j).stripWhiteSpace(); } else { - oldStyleArgName=yyextra->current->args.copy().stripWhiteSpace(); + oldStyleArgName=yyextra->current->args.copy().stripWhiteSpace(); } } } @@ -6954,7 +6975,7 @@ static void addKnRArgInfo(yyscan_t yyscanner,const QCString &type,const QCString a.type=type.stripWhiteSpace(); if (a.type.left(9)=="register ") // strip keyword { - a.type=a.type.mid(9); + a.type=a.type.mid(9); } a.name=name.stripWhiteSpace(); if (!brief.isEmpty() && !docs.isEmpty()) @@ -6967,7 +6988,7 @@ static void addKnRArgInfo(yyscan_t yyscanner,const QCString &type,const QCString } else { - a.docs=docs; + a.docs=docs; } } } @@ -7003,15 +7024,15 @@ static void startCommentBlock(yyscan_t yyscanner,bool brief) yyextra->current->docLine = yyextra->yyLineNr; } } - + //---------------------------------------------------------------------------- static void newEntry(yyscan_t yyscanner) { struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; - if (yyextra->tempEntry==0) // if temp entry is not 0, it holds yyextra->current, - // and yyextra->current is actually replaced by yyextra->previous which was - // already added to yyextra->current_root, so we should not add it again + if (yyextra->tempEntry==0) // if temp entry is not 0, it holds yyextra->current, + // and yyextra->current is actually replaced by yyextra->previous which was + // already added to yyextra->current_root, so we should not add it again // (see bug723314) { yyextra->previous = yyextra->current; @@ -7048,15 +7069,15 @@ static void handleCommentBlock(yyscan_t yyscanner,const QCString &doc,bool brief QCString strippedDoc = stripIndentation(doc); QCString processedDoc = Config_getBool(MARKDOWN_SUPPORT) ? markdown.process(strippedDoc,lineNr) : strippedDoc; while (yyextra->commentScanner.parseCommentBlock( - yyextra->thisParser, - yyextra->docBlockInBody && yyextra->previous ? yyextra->previous.get() : yyextra->current.get(), - processedDoc, // text - yyextra->yyFileName, // file - lineNr, // line of block start - yyextra->docBlockInBody ? FALSE : brief, // isBrief - yyextra->docBlockInBody ? FALSE : yyextra->docBlockAutoBrief, // isJavaDocStyle - yyextra->docBlockInBody, // isInBody - yyextra->protection, + yyextra->thisParser, + yyextra->docBlockInBody && yyextra->previous ? yyextra->previous.get() : yyextra->current.get(), + processedDoc, // text + yyextra->yyFileName, // file + lineNr, // line of block start + yyextra->docBlockInBody ? FALSE : brief, // isBrief + yyextra->docBlockInBody ? FALSE : yyextra->docBlockAutoBrief, // isJavaDocStyle + yyextra->docBlockInBody, // isInBody + yyextra->protection, position, needsEntry, Config_getBool(MARKDOWN_SUPPORT) @@ -7064,7 +7085,7 @@ static void handleCommentBlock(yyscan_t yyscanner,const QCString &doc,bool brief ) { //printf("parseCommentBlock position=%d [%s]\n",position,doc.data()+position); - if (needsEntry) + if (needsEntry) { QCString docFile = yyextra->current->docFile; newEntry(yyscanner); @@ -7108,27 +7129,27 @@ static void handleParametersCommentBlocks(yyscan_t yyscanner,ArgumentList &al) //printf("handleParametersCommentBlock [%s]\n",doc.data()); while (yyextra->commentScanner.parseCommentBlock( - yyextra->thisParser, - yyextra->current.get(), - a.docs, // text - yyextra->yyFileName, // file - yyextra->current->docLine, // line of block start - FALSE, - FALSE, - FALSE, - yyextra->protection, - position, - needsEntry, + yyextra->thisParser, + yyextra->current.get(), + a.docs, // text + yyextra->yyFileName, // file + yyextra->current->docLine, // line of block start + FALSE, + FALSE, + FALSE, + yyextra->protection, + position, + needsEntry, Config_getBool(MARKDOWN_SUPPORT) - ) - ) + ) + ) { - //printf("handleParametersCommentBlock position=%d [%s]\n",position,doc.data()+position); - if (needsEntry) newEntry(yyscanner); + //printf("handleParametersCommentBlock position=%d [%s]\n",position,doc.data()+position); + if (needsEntry) newEntry(yyscanner); } if (needsEntry) { - newEntry(yyscanner); + newEntry(yyscanner); } a.docs = yyextra->current->doc; @@ -7161,9 +7182,9 @@ static void parseCompounds(yyscan_t yyscanner,const std::shared_ptr<Entry> &rt) yyextra->inputString = ce->program; yyextra->inputPosition = 0; if (ce->section==Entry::ENUM_SEC || (ce->spec&Entry::Enum)) - BEGIN( FindFields ) ; + BEGIN( FindFields ) ; else - BEGIN( FindMembers ) ; + BEGIN( FindMembers ) ; yyextra->current_root = ce; yyextra->yyFileName = ce->fileName; //setContext(); @@ -7187,44 +7208,44 @@ static void parseCompounds(yyscan_t yyscanner,const std::shared_ptr<Entry> &rt) if( ce->section==Entry::CLASS_SEC ) // class { if (yyextra->insidePHP || yyextra->insideD || yyextra->insideJS || yyextra->insideIDL || yyextra->insideSlice) - { - yyextra->current->protection = yyextra->protection = Public ; - } - else if (yyextra->insideJava) - { + { + yyextra->current->protection = yyextra->protection = Public ; + } + else if (yyextra->insideJava) + { yyextra->current->protection = yyextra->protection = (ce->spec & (Entry::Interface|Entry::Enum)) ? Public : Package; - } - else if (ce->spec&(Entry::Interface | Entry::Ref | Entry::Value | Entry::Struct | Entry::Union)) - { - if (ce->lang==SrcLangExt_ObjC) - { - yyextra->current->protection = yyextra->protection = Protected ; - } - else - { - yyextra->current->protection = yyextra->protection = Public ; - } - } - else - { + } + else if (ce->spec&(Entry::Interface | Entry::Ref | Entry::Value | Entry::Struct | Entry::Union)) + { + if (ce->lang==SrcLangExt_ObjC) + { + yyextra->current->protection = yyextra->protection = Protected ; + } + else + { + yyextra->current->protection = yyextra->protection = Public ; + } + } + else + { yyextra->current->protection = yyextra->protection = Private ; - } + } } else if (ce->section == Entry::ENUM_SEC ) // enum { - yyextra->current->protection = yyextra->protection = ce->protection; + yyextra->current->protection = yyextra->protection = ce->protection; } else if (!ce->name.isEmpty() && ce->name.at(ni)=='@') // unnamed union or namespace { - if (ce->section == Entry::NAMESPACE_SEC ) // unnamed namespace - { + if (ce->section == Entry::NAMESPACE_SEC ) // unnamed namespace + { yyextra->current->stat = yyextra->stat = TRUE; - } - yyextra->current->protection = yyextra->protection = ce->protection; + } + yyextra->current->protection = yyextra->protection = ce->protection; } else // named struct, union, protocol, category { - yyextra->current->protection = yyextra->protection = Public ; + yyextra->current->protection = yyextra->protection = Public ; } yyextra->mtype = Method; yyextra->virt = Normal; @@ -7235,19 +7256,19 @@ static void parseCompounds(yyscan_t yyscanner,const std::shared_ptr<Entry> &rt) //memberGroupInside.resize(0); QCString name = ce->name; yyextra->commentScanner.enterCompound(yyextra->yyFileName,yyextra->yyLineNr,name); - + scannerYYlex(yyscanner); yyextra->lexInit=TRUE; //forceEndGroup(); yyextra->commentScanner.leaveCompound(yyextra->yyFileName,yyextra->yyLineNr,name); - + ce->program.resize(0); //if (depthIf>0) //{ - // warn(yyextra->yyFileName,yyextra->yyLineNr,"Documentation block ended in the middle of a conditional section!"); + // warn(yyextra->yyFileName,yyextra->yyLineNr,"Documentation block ended in the middle of a conditional section!"); //} } parseCompounds(yyscanner,ce); @@ -7341,7 +7362,7 @@ static void parsePrototype(yyscan_t yyscanner,const QCString &text) { struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; //printf("**** parsePrototype(%s) begin\n",text.data()); - if (text.isEmpty()) + if (text.isEmpty()) { warn(yyextra->yyFileName,yyextra->yyLineNr,"Empty prototype found!"); return; @@ -7354,11 +7375,11 @@ static void parsePrototype(yyscan_t yyscanner,const QCString &text) const char *orgInputString; int orgInputPosition; YY_BUFFER_STATE orgState; - + // save scanner state orgState = YY_CURRENT_BUFFER; yy_switch_to_buffer(yy_create_buffer(0, YY_BUF_SIZE, yyscanner), yyscanner); - orgInputString = yyextra->inputString; + orgInputString = yyextra->inputString; orgInputPosition = yyextra->inputPosition; // set new string @@ -7378,7 +7399,7 @@ static void parsePrototype(yyscan_t yyscanner,const QCString &text) YY_BUFFER_STATE tmpState = YY_CURRENT_BUFFER; yy_switch_to_buffer(orgState, yyscanner); yy_delete_buffer(tmpState, yyscanner); - yyextra->inputString = orgInputString; + yyextra->inputString = orgInputString; yyextra->inputPosition = orgInputPosition; @@ -7439,7 +7460,7 @@ bool COutlineParser::needsPreprocessing(const QCString &extension) const QCString fe=extension.lower(); SrcLangExt lang = getLanguageFromFileName(extension); return (SrcLangExt_Cpp == lang) || - !( fe==".java" || fe==".as" || fe==".d" || fe==".php" || + !( fe==".java" || fe==".as" || fe==".d" || fe==".php" || fe==".php4" || fe==".inc" || fe==".phtml"|| fe==".php5" ); } diff --git a/src/scopedtypevariant.h b/src/scopedtypevariant.h new file mode 100644 index 0000000..d544434 --- /dev/null +++ b/src/scopedtypevariant.h @@ -0,0 +1,292 @@ +/****************************************************************************** + * + * Copyright (C) 1997-2020 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 SCOPEDTYPEVARIANT_H +#define SCOPEDTYPEVARIANT_H + +#include <utility> +#include <vector> +#include <qcstring.h> +#include "definition.h" + +//! Class representing a local class definition found while +//! generating syntax highlighted code. +class LocalDef +{ + public: + void insertBaseClass(const QCString &name) { m_baseClasses.push_back(name); } + std::vector<QCString> baseClasses() const { return m_baseClasses; } + private: + std::vector<QCString> m_baseClasses; +}; + +//----------------------------------------------------------------------------- + +/*! Variant class for a scoped type. + * + * Variants: + * - Dummy: a type used for hiding a global type. + * - Local: a locally defined type (e.g. found inside a function) + * - Global: a globally defined type (processed by doxygen in an earlier pass). + */ +class ScopedTypeVariant +{ + public: + //! possible variant types + enum Variant + { + Global, + Local, + Dummy + }; + //! default constructor for creating a variant of type Dummy + ScopedTypeVariant() : m_variant(Dummy) + { + m_u.globalDef = 0; + } + //! constructor for creating a variant of type Global + explicit ScopedTypeVariant(const Definition *d) + { + if (d) + { + m_name = d->name(); + m_variant = Global; + m_u.globalDef = d; + } + else + { + m_variant = Dummy; + m_u.globalDef = 0; + } + } + //! constructor for creating a variant of type Local + explicit ScopedTypeVariant(const QCString &name) + { + m_name = name; + m_variant = Local; + m_u.localDef = new LocalDef; + } + //! copy constructor + ScopedTypeVariant(const ScopedTypeVariant &stv) + { + m_variant = stv.m_variant; + m_name = stv.m_name; + if (m_variant==Local) + { + m_u.localDef = new LocalDef(*stv.m_u.localDef); + } + else if (m_variant==Global) + { + m_u.globalDef = stv.m_u.globalDef; + } + } + //! move constructor + ScopedTypeVariant(ScopedTypeVariant &&stv) noexcept : ScopedTypeVariant() + { + swap(*this,stv); + } + //! assignment operator + ScopedTypeVariant &operator=(ScopedTypeVariant stv) + { + swap(*this,stv); + return *this; + } + //! destructor + ~ScopedTypeVariant() + { + if (m_variant==Local) + { + delete m_u.localDef; + } + } + //! swap function + friend void swap(ScopedTypeVariant &first,ScopedTypeVariant &second) + { + using std::swap; // enable ADL + swap(first.m_variant,second.m_variant); + swap(first.m_name,second.m_name); + swap(first.m_u.globalDef,second.m_u.globalDef); + } + //! Turn the variant into a Global type + void setGlobal(const Definition *def) + { + if (m_variant==Local) + { + delete m_u.localDef; + } + m_variant = Global; + m_name = def->name(); + m_u.globalDef = def; + } + //! Turn the variant into a Local type + LocalDef *setLocal(const QCString &name) + { + if (m_variant==Local) + { + delete m_u.localDef; + } + m_variant = Local; + m_name = name; + m_u.localDef = new LocalDef; + return m_u.localDef; + } + //! Turn the variant into a Dummy type + void setDummy() + { + if (m_variant==Local) + { + delete m_u.localDef; + } + m_variant = Dummy; + m_name = ""; + m_u.localDef=0; + } + Variant type() const { return m_variant; } + QCString name() const { return m_name; } + LocalDef *localDef() const { return m_variant==Local ? m_u.localDef : 0; } + const Definition *globalDef() const { return m_variant==Global ? m_u.globalDef : 0; } + + private: + Variant m_variant; + QCString m_name; + union + { + const Definition *globalDef; + LocalDef *localDef; + } m_u; +}; + +//----------------------------------------------------------------------------- + +/*! Represents a stack of variable to class mappings as found in the + * code. Each scope is enclosed in pushScope() and popScope() calls. + * Variables are added by calling addVariables() and one can search + * for variable using findVariable(). + */ +class VariableContext +{ + public: + using Scope = std::unordered_map<std::string,ScopedTypeVariant>; + + void pushScope() + { + m_scopes.push_back(Scope()); + } + void popScope() + { + if (!m_scopes.empty()) + { + m_scopes.pop_back(); + } + } + void clear() + { + m_scopes.clear(); + m_globalScope.clear(); + } + void clearExceptGlobal() + { + m_scopes.clear(); + } + void addVariable(const QCString &name,ScopedTypeVariant stv) + { + Scope *scope = m_scopes.empty() ? &m_globalScope : &m_scopes.back(); + scope->emplace(std::make_pair(name.str(),std::move(stv))); // add it to a list + } + const ScopedTypeVariant *findVariable(const QCString &name) + { + const ScopedTypeVariant *result = 0; + if (name.isEmpty()) return result; + + // search from inner to outer scope + auto it = std::rbegin(m_scopes); + while (it != std::rend(m_scopes)) + { + auto it2 = it->find(name.str()); + if (it2 != std::end(*it)) + { + result = &it2->second; + return result; + } + ++it; + } + // nothing found -> also try the global scope + auto it2 = m_globalScope.find(name.str()); + if (it2 != m_globalScope.end()) + { + result = &it2->second; + } + return result; + } + bool atGlobalScope() const { return m_scopes.empty(); } + + private: + Scope m_globalScope; + std::vector<Scope> m_scopes; +}; + +//----------------------------------------------------------------------------- + +/** Represents the call context */ +class CallContext +{ + public: + struct Ctx + { + Ctx(const QCString &name_,const QCString &type_) : name(name_), type(type_) {} + QCString name; + QCString type; + ScopedTypeVariant stv; + }; + + CallContext() + { + clear(); + } + void setScope(const ScopedTypeVariant &stv) + { + Ctx &ctx = m_stvList.back(); + ctx.stv=std::move(stv); + } + void pushScope(const QCString &name_,const QCString &type_) + { + m_stvList.push_back(Ctx(name_,type_)); + } + void popScope(QCString &name_,QCString &type_) + { + if (m_stvList.size()>1) + { + const Ctx &ctx = m_stvList.back(); + name_ = ctx.name; + type_ = ctx.type; + m_stvList.pop_back(); + } + } + void clear() + { + m_stvList.clear(); + m_stvList.push_back(Ctx("","")); + } + const ScopedTypeVariant getScope() const + { + return m_stvList.back().stv; + } + + private: + std::vector<Ctx> m_stvList; +}; + + +#endif diff --git a/src/searchindex.cpp b/src/searchindex.cpp index ec7f7d6..0464cb4 100644 --- a/src/searchindex.cpp +++ b/src/searchindex.cpp @@ -37,6 +37,8 @@ #include "filename.h" #include "membername.h" #include "resourcemgr.h" +#include "namespacedef.h" +#include "classdef.h" // file format: (all multi-byte values are stored in big endian format) // 4 byte header @@ -49,41 +51,33 @@ // (4 bytes index to url string + 4 bytes frequency counter) // for each url: a \0 terminated string -const int numIndexEntries = 256*256; +const size_t numIndexEntries = 256*256; //-------------------------------------------------------------------- -IndexWord::IndexWord(const char *word) : m_word(word), m_urls(17) +IndexWord::IndexWord(QCString word) : m_word(word) { - m_urls.setAutoDelete(TRUE); //printf("IndexWord::IndexWord(%s)\n",word); } void IndexWord::addUrlIndex(int idx,bool hiPriority) { //printf("IndexWord::addUrlIndex(%d,%d)\n",idx,hiPriority); - URLInfo *ui = m_urls.find(idx); - if (ui==0) + auto it = m_urls.find(idx); + if (it==m_urls.end()) { //printf("URLInfo::URLInfo(%d)\n",idx); - ui=new URLInfo(idx,0); - m_urls.insert(idx,ui); + it = m_urls.insert(std::make_pair(idx,URLInfo(idx,0))).first; } - ui->freq+=2; - if (hiPriority) ui->freq|=1; // mark as high priority document + it->second.freq+=2; + if (hiPriority) it->second.freq|=1; // mark as high priority document } //-------------------------------------------------------------------- -SearchIndex::SearchIndex() : SearchIndexIntf(Internal), - m_words(328829), m_index(numIndexEntries), m_url2IdMap(10007), m_urls(10007), m_urlIndex(-1) +SearchIndex::SearchIndex() : SearchIndexIntf(Internal) { - int i; - m_words.setAutoDelete(TRUE); - m_url2IdMap.setAutoDelete(TRUE); - m_urls.setAutoDelete(TRUE); - m_index.setAutoDelete(TRUE); - for (i=0;i<numIndexEntries;i++) m_index.insert(i,new QList<IndexWord>); + m_index.resize(numIndexEntries); } void SearchIndex::setCurrentDoc(const Definition *ctx,const char *anchor,bool isSourceFile) @@ -91,7 +85,7 @@ void SearchIndex::setCurrentDoc(const Definition *ctx,const char *anchor,bool is 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<const FileDef*>(ctx))->getSourceFileBase() : ctx->getOutputFileBase(); + QCString url=isSourceFile ? (toFileDef(ctx))->getSourceFileBase() : ctx->getOutputFileBase(); url+=Config_getString(HTML_FILE_EXTENSION); QCString baseUrl = url; if (anchor) url+=QCString("#")+anchor; @@ -99,7 +93,7 @@ void SearchIndex::setCurrentDoc(const Definition *ctx,const char *anchor,bool is QCString name=ctx->qualifiedName(); if (ctx->definitionType()==Definition::TypeMember) { - const MemberDef *md = dynamic_cast<const MemberDef *>(ctx); + const MemberDef *md = toMemberDef(ctx); name.prepend((md->getLanguage()==SrcLangExt_Fortran ? theTranslator->trSubprogram(TRUE,TRUE) : theTranslator->trMember(TRUE,TRUE))+" "); @@ -116,7 +110,7 @@ void SearchIndex::setCurrentDoc(const Definition *ctx,const char *anchor,bool is { case Definition::TypePage: { - const PageDef *pd = dynamic_cast<const PageDef *>(ctx); + const PageDef *pd = toPageDef(ctx); if (pd->hasTitle()) { name = theTranslator->trPage(TRUE,TRUE)+" "+pd->title(); @@ -129,7 +123,7 @@ void SearchIndex::setCurrentDoc(const Definition *ctx,const char *anchor,bool is break; case Definition::TypeClass: { - const ClassDef *cd = dynamic_cast<const ClassDef *>(ctx); + const ClassDef *cd = toClassDef(ctx); name.prepend(cd->compoundTypeString()+" "); } break; @@ -151,7 +145,7 @@ void SearchIndex::setCurrentDoc(const Definition *ctx,const char *anchor,bool is break; case Definition::TypeGroup: { - const GroupDef *gd = dynamic_cast<const GroupDef *>(ctx); + const GroupDef *gd = toGroupDef(ctx); if (gd->groupTitle()) { name = theTranslator->trGroup(TRUE,TRUE)+" "+gd->groupTitle(); @@ -167,16 +161,16 @@ void SearchIndex::setCurrentDoc(const Definition *ctx,const char *anchor,bool is } } - int *pIndex = m_url2IdMap.find(baseUrl); - if (pIndex==0) + auto it = m_url2IdMap.find(baseUrl.str()); + if (it == m_url2IdMap.end()) { ++m_urlIndex; - m_url2IdMap.insert(baseUrl,new int(m_urlIndex)); - m_urls.insert(m_urlIndex,new URL(name,url)); + m_url2IdMap.insert(std::make_pair(baseUrl.str(),m_urlIndex)); + m_urls.insert(std::make_pair(m_urlIndex,URL(name,url))); } else { - m_urls.insert(*pIndex,new URL(name,url)); + m_urls.insert(std::make_pair(it->second,URL(name,url))); } } @@ -208,17 +202,16 @@ void SearchIndex::addWord(const char *word,bool hiPriority,bool recurse) if (word==0 || word[0]=='\0') return; QCString wStr = QCString(word).lower(); //printf("SearchIndex::addWord(%s,%d) wStr=%s\n",word,hiPriority,wStr.data()); - IndexWord *w = m_words[wStr]; - if (w==0) + int idx=charsToIndex(wStr); + if (idx<0 || idx>=static_cast<int>(m_index.size())) return; + auto it = m_words.find(wStr.str()); + if (it==m_words.end()) { - int idx=charsToIndex(wStr); //fprintf(stderr,"addWord(%s) at index %d\n",word,idx); - if (idx<0) return; - w = new IndexWord(wStr); - m_index[idx]->append(w); - m_words.insert(wStr,w); + m_index[idx].push_back(IndexWord(wStr)); + it = m_words.insert({ wStr.str(), static_cast<int>(m_index[idx].size())-1 }).first; } - w->addUrlIndex(m_urlIndex,hiPriority); + m_index[idx][it->second].addUrlIndex(m_urlIndex,hiPriority); int i; bool found=FALSE; if (!recurse) // the first time we check if we can strip the prefix @@ -244,12 +237,12 @@ void SearchIndex::addWord(const char *word,bool hiPriority) addWord(word,hiPriority,FALSE); } -static void writeInt(QFile &f,int index) +static void writeInt(QFile &f,size_t index) { - f.putch(((uint)index)>>24); - f.putch((((uint)index)>>16)&0xff); - f.putch((((uint)index)>>8)&0xff); - f.putch(((uint)index)&0xff); + f.putch(static_cast<int>(index>>24)); + f.putch(static_cast<int>((index>>16)&0xff)); + f.putch(static_cast<int>((index>>8)&0xff)); + f.putch(static_cast<int>(index&0xff)); } static void writeString(QFile &f,const char *s) @@ -261,21 +254,19 @@ static void writeString(QFile &f,const char *s) void SearchIndex::write(const char *fileName) { - int i; - int size=4; // for the header + size_t i; + size_t size=4; // for the header size+=4*numIndexEntries; // for the index - int wordsOffset = size; + size_t wordsOffset = size; // first pass: compute the size of the wordlist for (i=0;i<numIndexEntries;i++) { - QList<IndexWord> *wlist = m_index[i]; - if (!wlist->isEmpty()) + const auto &wlist = m_index[i]; + if (!wlist.empty()) { - QListIterator<IndexWord> iwi(*wlist); - IndexWord *iw; - for (iwi.toFirst();(iw=iwi.current());++iwi) + for (const auto &iw : wlist) { - int ws = iw->word().length()+1; + int ws = iw.word().length()+1; size+=ws+4; // word + url info list offset } size+=1; // zero list terminator @@ -283,19 +274,17 @@ void SearchIndex::write(const char *fileName) } // second pass: compute the offsets in the index - int indexOffsets[numIndexEntries]; - int offset=wordsOffset; + size_t indexOffsets[numIndexEntries]; + size_t offset=wordsOffset; for (i=0;i<numIndexEntries;i++) { - QList<IndexWord> *wlist = m_index[i]; - if (!wlist->isEmpty()) + const auto &wlist = m_index[i]; + if (!wlist.empty()) { indexOffsets[i]=offset; - QListIterator<IndexWord> iwi(*wlist); - IndexWord *iw; - for (iwi.toFirst();(iw=iwi.current());++iwi) + for (const auto &iw : wlist) { - offset+= iw->word().length()+1; + offset+= iw.word().length()+1; offset+=4; // word + offset to url info array } offset+=1; // zero list terminator @@ -305,42 +294,36 @@ void SearchIndex::write(const char *fileName) indexOffsets[i]=0; } } - int padding = size; + size_t padding = size; size = (size+3)&~3; // round up to 4 byte boundary padding = size - padding; - //int statsOffset = size; - //IndexWord *iw; - int *wordStatOffsets = new int[m_words.count()]; + std::vector<size_t> wordStatOffsets(m_words.size()); int count=0; // third pass: compute offset to stats info for each word for (i=0;i<numIndexEntries;i++) { - QList<IndexWord> *wlist = m_index[i]; - if (!wlist->isEmpty()) + const auto &wlist = m_index[i]; + if (!wlist.empty()) { - QListIterator<IndexWord> iwi(*wlist); - IndexWord *iw; - for (iwi.toFirst();(iw=iwi.current());++iwi) + for (const auto &iw : wlist) { //printf("wordStatOffsets[%d]=%d\n",count,size); wordStatOffsets[count++] = size; - size+=4+iw->urls().count()*8; // count + (url_index,freq) per url + size+=4 + iw.urls().size() * 8; // count + (url_index,freq) per url } } } - int *urlOffsets = new int[m_urls.count()]; - //int urlsOffset = size; - QIntDictIterator<URL> udi(m_urls); - URL *url; - for (udi.toFirst();(url=udi.current());++udi) + std::vector<size_t> urlOffsets(m_urls.size()); + for (const auto &udi : m_urls) { - urlOffsets[udi.currentKey()]=size; - size+=url->name.length()+1+ - url->url.length()+1; + urlOffsets[udi.first]=size; + size+=udi.second.name.length()+1+ + udi.second.url.length()+1; } + //printf("Total size %x bytes (word=%x stats=%x urls=%x)\n",size,wordsOffset,statsOffset,urlsOffset); QFile f(fileName); if (f.open(IO_WriteOnly)) @@ -356,14 +339,12 @@ void SearchIndex::write(const char *fileName) count=0; for (i=0;i<numIndexEntries;i++) { - QList<IndexWord> *wlist = m_index[i]; - if (!wlist->isEmpty()) + const auto &wlist = m_index[i]; + if (!wlist.empty()) { - QListIterator<IndexWord> iwi(*wlist); - IndexWord *iw; - for (iwi.toFirst();(iw=iwi.current());++iwi) + for (const auto &iw : wlist) { - writeString(f,iw->word()); + writeString(f,iw.word()); writeInt(f,wordStatOffsets[count++]); } f.putch(0); @@ -374,35 +355,29 @@ void SearchIndex::write(const char *fileName) // write word statistics for (i=0;i<numIndexEntries;i++) { - QList<IndexWord> *wlist = m_index[i]; - if (!wlist->isEmpty()) + const auto &wlist = m_index[i]; + if (!wlist.empty()) { - QListIterator<IndexWord> iwi(*wlist); - IndexWord *iw; - for (iwi.toFirst();(iw=iwi.current());++iwi) + for (const auto &iw : wlist) { - int numUrls = iw->urls().count(); + size_t numUrls = iw.urls().size(); writeInt(f,numUrls); - QIntDictIterator<URLInfo> uli(iw->urls()); - URLInfo *ui; - for (uli.toFirst();(ui=uli.current());++uli) + for (const auto &ui : iw.urls()) { - writeInt(f,urlOffsets[ui->urlIdx]); - writeInt(f,ui->freq); + writeInt(f,urlOffsets[ui.second.urlIdx]); + writeInt(f,ui.second.freq); } } } } // write urls - for (udi.toFirst();(url=udi.current());++udi) + for (const auto &udi : m_urls) { - writeString(f,url->name); - writeString(f,url->url); + writeString(f,udi.second.name); + writeString(f,udi.second.url); } } - delete[] urlOffsets; - delete[] wordStatOffsets; } @@ -422,29 +397,19 @@ struct SearchDocEntry struct SearchIndexExternal::Private { - Private() : docEntries(12251) {} - SDict<SearchDocEntry> docEntries; + std::map<std::string,SearchDocEntry> docEntries; SearchDocEntry *current = 0; }; -SearchIndexExternal::SearchIndexExternal() : SearchIndexIntf(External) -{ - p = new SearchIndexExternal::Private; - p->docEntries.setAutoDelete(TRUE); - p->current=0; -} - -SearchIndexExternal::~SearchIndexExternal() +SearchIndexExternal::SearchIndexExternal() : SearchIndexIntf(External), p(std::make_unique<Private>()) { - //printf("p->docEntries.count()=%d\n",p->docEntries.count()); - delete p; } static QCString definitionToName(const Definition *ctx) { if (ctx && ctx->definitionType()==Definition::TypeMember) { - const MemberDef *md = dynamic_cast<const MemberDef*>(ctx); + const MemberDef *md = toMemberDef(ctx); if (md->isFunction()) return "function"; else if (md->isSlot()) @@ -475,7 +440,7 @@ static QCString definitionToName(const Definition *ctx) switch(ctx->definitionType()) { case Definition::TypeClass: - return (dynamic_cast<const ClassDef*>(ctx))->compoundTypeString(); + return (toClassDef(ctx))->compoundTypeString(); case Definition::TypeFile: return "file"; case Definition::TypeNamespace: @@ -497,29 +462,28 @@ static QCString definitionToName(const Definition *ctx) void SearchIndexExternal::setCurrentDoc(const Definition *ctx,const char *anchor,bool isSourceFile) { - QCString extId = stripPath(Config_getString(EXTERNAL_SEARCH_ID)); - QCString baseName = isSourceFile ? (dynamic_cast<const FileDef*>(ctx))->getSourceFileBase() : ctx->getOutputFileBase(); + static QCString extId = stripPath(Config_getString(EXTERNAL_SEARCH_ID)); + QCString baseName = isSourceFile ? (toFileDef(ctx))->getSourceFileBase() : ctx->getOutputFileBase(); QCString url = baseName + Doxygen::htmlFileExtension; if (anchor) url+=QCString("#")+anchor; QCString key = extId+";"+url; - p->current = p->docEntries.find(key); - //printf("setCurrentDoc(url=%s,isSourceFile=%d) current=%p\n",url.data(),isSourceFile,p->current); - if (!p->current) + auto it = p->docEntries.find(key.str()); + if (it == p->docEntries.end()) { - SearchDocEntry *e = new SearchDocEntry; - e->type = isSourceFile ? QCString("source") : definitionToName(ctx); - e->name = ctx->qualifiedName(); + SearchDocEntry e; + e.type = isSourceFile ? QCString("source") : definitionToName(ctx); + e.name = ctx->qualifiedName(); if (ctx->definitionType()==Definition::TypeMember) { - e->args = (dynamic_cast<const MemberDef*>(ctx))->argsString(); + e.args = (toMemberDef(ctx))->argsString(); } - e->extId = extId; - e->url = url; - p->current = e; - p->docEntries.append(key,e); + e.extId = extId; + e.url = url; + it = p->docEntries.insert({key.str(),e}).first; //printf("searchIndexExt %s : %s\n",e->name.data(),e->url.data()); } + p->current = &it->second; } void SearchIndexExternal::addWord(const char *word,bool hiPriority) @@ -539,26 +503,25 @@ void SearchIndexExternal::write(const char *fileName) FTextStream t(&f); t << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << endl; t << "<add>" << endl; - SDict<SearchDocEntry>::Iterator it(p->docEntries); - SearchDocEntry *doc; - for (it.toFirst();(doc=it.current());++it) + for (auto &kv : p->docEntries) { - doc->normalText.addChar(0); // make sure buffer ends with a 0 terminator - doc->importantText.addChar(0); // make sure buffer ends with a 0 terminator + SearchDocEntry &doc = kv.second; + doc.normalText.addChar(0); // make sure buffer ends with a 0 terminator + doc.importantText.addChar(0); // make sure buffer ends with a 0 terminator t << " <doc>" << endl; - t << " <field name=\"type\">" << doc->type << "</field>" << endl; - t << " <field name=\"name\">" << convertToXML(doc->name) << "</field>" << endl; - if (!doc->args.isEmpty()) + t << " <field name=\"type\">" << doc.type << "</field>" << endl; + t << " <field name=\"name\">" << convertToXML(doc.name) << "</field>" << endl; + if (!doc.args.isEmpty()) { - t << " <field name=\"args\">" << convertToXML(doc->args) << "</field>" << endl; + t << " <field name=\"args\">" << convertToXML(doc.args) << "</field>" << endl; } - if (!doc->extId.isEmpty()) + if (!doc.extId.isEmpty()) { - t << " <field name=\"tag\">" << convertToXML(doc->extId) << "</field>" << endl; + t << " <field name=\"tag\">" << convertToXML(doc.extId) << "</field>" << endl; } - t << " <field name=\"url\">" << convertToXML(doc->url) << "</field>" << endl; - t << " <field name=\"keywords\">" << convertToXML(doc->importantText.get()) << "</field>" << endl; - t << " <field name=\"text\">" << convertToXML(doc->normalText.get()) << "</field>" << endl; + t << " <field name=\"url\">" << convertToXML(doc.url) << "</field>" << endl; + t << " <field name=\"keywords\">" << convertToXML(doc.importantText.get()) << "</field>" << endl; + t << " <field name=\"text\">" << convertToXML(doc.normalText.get()) << "</field>" << endl; t << " </doc>" << endl; } t << "</add>" << endl; @@ -572,14 +535,6 @@ void SearchIndexExternal::write(const char *fileName) //--------------------------------------------------------------------------- // the following part is for the javascript based search engine -#include "memberdef.h" -#include "namespacedef.h" -#include "pagedef.h" -#include "classdef.h" -#include "filedef.h" -#include "language.h" -#include "doxygen.h" -#include "message.h" static SearchIndexInfo g_searchIndexInfo[NUM_SEARCH_INDICES]; @@ -956,7 +911,7 @@ void writeJavaScriptSearchIndex() QCString baseName; baseName.sprintf("%s_%x",g_searchIndexInfo[i].name.data(),p); - QCString fileName = searchDirName + "/"+baseName+".html"; + QCString fileName = searchDirName + "/"+baseName+Doxygen::htmlFileExtension; QCString dataFileName = searchDirName + "/"+baseName+".js"; QFile outFile(fileName); @@ -968,7 +923,8 @@ void writeJavaScriptSearchIndex() t << "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"" " \"https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">" << endl; - t << "<html><head><title></title>" << endl; + t << "<html xmlns=\"http://www.w3.org/1999/xhtml\">" << endl; + t << "<head><title></title>" << endl; t << "<meta http-equiv=\"Content-Type\" content=\"text/xhtml;charset=UTF-8\"/>" << endl; t << "<meta name=\"generator\" content=\"Doxygen " << getDoxygenVersion() << "\"/>" << endl; t << "<link rel=\"stylesheet\" type=\"text/css\" href=\"search.css\"/>" << endl; @@ -979,18 +935,18 @@ void writeJavaScriptSearchIndex() t << "<div id=\"SRIndex\">" << endl; t << "<div class=\"SRStatus\" id=\"Loading\">" << theTranslator->trLoading() << "</div>" << endl; t << "<div id=\"SRResults\"></div>" << endl; // here the results will be inserted - t << "<script type=\"text/javascript\"><!--" << endl; - t << "/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&dn=gpl-2.0.txt GPL-v2 */\n"; + t << "<script type=\"text/javascript\">" << endl; + t << "/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&dn=gpl-2.0.txt GPL-v2 */\n"; t << "createResults();" << endl; // this function will insert the results - t << "/* @license-end */\n"; - t << "--></script>" << endl; + t << "/* @license-end */\n"; + t << "</script>" << endl; t << "<div class=\"SRStatus\" id=\"Searching\">" << theTranslator->trSearching() << "</div>" << endl; t << "<div class=\"SRStatus\" id=\"NoMatches\">" << theTranslator->trNoMatches() << "</div>" << endl; - t << "<script type=\"text/javascript\"><!--" << endl; - t << "/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&dn=gpl-2.0.txt GPL-v2 */\n"; + t << "<script type=\"text/javascript\">" << endl; + t << "/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&dn=gpl-2.0.txt GPL-v2 */\n"; t << "document.getElementById(\"Loading\").style.display=\"none\";" << endl; t << "document.getElementById(\"NoMatches\").style.display=\"none\";" << endl; t << "var searchResults = new SearchResults(\"searchResults\");" << endl; @@ -1001,8 +957,8 @@ void writeJavaScriptSearchIndex() t << " if (elem) elem.focus();" << endl; t << " }" << endl; t << "});" << endl; - t << "/* @license-end */\n"; - t << "--></script>" << endl; + t << "/* @license-end */\n"; + t << "</script>" << endl; t << "</div>" << endl; // SRIndex t << "</body>" << endl; t << "</html>" << endl; @@ -1040,7 +996,7 @@ void writeJavaScriptSearchIndex() if (dl->count()==1) // item with a unique name { - const MemberDef *md = dynamic_cast<const MemberDef*>(d); + const MemberDef *md = toMemberDef(d); QCString anchor = d->anchor(); ti << "'" << externalRef("../",d->getReference(),TRUE) @@ -1092,7 +1048,7 @@ void writeJavaScriptSearchIndex() const Definition *scope = d->getOuterScope(); const Definition *next = di.current(); const Definition *nextScope = 0; - const MemberDef *md = dynamic_cast<const MemberDef*>(d); + const MemberDef *md = toMemberDef(d); if (next) nextScope = next->getOuterScope(); QCString anchor = d->anchor(); @@ -1136,12 +1092,12 @@ void writeJavaScriptSearchIndex() QCString name; if (d->definitionType()==Definition::TypeClass) { - name = convertToXML((dynamic_cast<const ClassDef*>(d))->displayName()); + name = convertToXML((toClassDef(d))->displayName()); found = TRUE; } else if (d->definitionType()==Definition::TypeNamespace) { - name = convertToXML((dynamic_cast<const NamespaceDef*>(d))->displayName()); + name = convertToXML((toNamespaceDef(d))->displayName()); found = TRUE; } else if (scope==0 || scope==Doxygen::globalScope) // in global scope @@ -1268,13 +1224,14 @@ void writeJavaScriptSearchIndex() ResourceMgr::instance().copyResource("search.js",searchDirName); } { - QFile f(searchDirName+"/nomatches.html"); + QFile f(searchDirName+"/nomatches"+Doxygen::htmlFileExtension); if (f.open(IO_WriteOnly)) { FTextStream t(&f); t << "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" " "\"https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">" << endl; - t << "<html><head><title></title>" << endl; + t << "<html xmlns=\"http://www.w3.org/1999/xhtml\">" << endl; + t << "<head><title></title>" << endl; t << "<meta http-equiv=\"Content-Type\" content=\"text/xhtml;charset=UTF-8\"/>" << endl; t << "<link rel=\"stylesheet\" type=\"text/css\" href=\"search.css\"/>" << endl; t << "<script type=\"text/javascript\" src=\"search.js\"></script>" << endl; @@ -1316,11 +1273,11 @@ void SearchIndexList::append(const Definition *d) { if (d->definitionType()==Definition::TypeGroup) { - dispName = (dynamic_cast<const GroupDef*>(d))->groupTitle(); + dispName = (toGroupDef(d))->groupTitle(); } else if (d->definitionType()==Definition::TypePage) { - dispName = (dynamic_cast<const PageDef*>(d))->title(); + dispName = (toPageDef(d))->title(); } l=new SearchDefinitionList(searchId(dispName),dispName); SDict< SearchDefinitionList >::append(dispName,l); diff --git a/src/searchindex.h b/src/searchindex.h index 923973c..71c1ce1 100644 --- a/src/searchindex.h +++ b/src/searchindex.h @@ -1,12 +1,12 @@ /****************************************************************************** * - * + * * * Copyright (C) 1997-2015 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. * @@ -18,11 +18,15 @@ #ifndef _SEARCHINDEX_H #define _SEARCHINDEX_H +#include <memory> +#include <vector> +#include <map> +#include <unordered_map> +#include <string> + #include <qintdict.h> #include <qlist.h> -#include <qdict.h> #include <qintdict.h> -#include <qvector.h> #include "sortdict.h" #include "definition.h" #include "util.h" @@ -40,7 +44,7 @@ void finalizeSearchIndexer(); struct URL { - URL(const char *n,const char *u) : name(n), url(u) {} + URL(QCString n,QCString u) : name(n), url(u) {} QCString name; QCString url; }; @@ -56,14 +60,15 @@ struct URLInfo class IndexWord { public: - IndexWord(const char *word); + using URLInfoMap = std::unordered_map<int,URLInfo>; + IndexWord(QCString word); void addUrlIndex(int,bool); - const QIntDict<URLInfo> &urls() const { return m_urls; } + URLInfoMap urls() const { return m_urls; } QCString word() const { return m_word; } private: QCString m_word; - QIntDict<URLInfo> m_urls; + URLInfoMap m_urls; }; class SearchIndexIntf @@ -84,16 +89,16 @@ class SearchIndex : public SearchIndexIntf { public: SearchIndex(); - void setCurrentDoc(const Definition *ctx,const char *anchor,bool isSourceFile); - void addWord(const char *word,bool hiPriority); - void write(const char *file); + void setCurrentDoc(const Definition *ctx,const char *anchor,bool isSourceFile) override; + void addWord(const char *word,bool hiPriority) override; + void write(const char *file) override; private: void addWord(const char *word,bool hiPrio,bool recurse); - QDict<IndexWord> m_words; - QVector< QList<IndexWord> > m_index; - QDict<int> m_url2IdMap; - QIntDict<URL> m_urls; - int m_urlIndex; + std::unordered_map<std::string,int> m_words; + std::vector< std::vector< IndexWord> > m_index; + std::unordered_map<std::string,int> m_url2IdMap; + std::map<int,URL> m_urls; + int m_urlIndex = -1; }; @@ -102,12 +107,11 @@ class SearchIndexExternal : public SearchIndexIntf struct Private; public: SearchIndexExternal(); - ~SearchIndexExternal(); void setCurrentDoc(const Definition *ctx,const char *anchor,bool isSourceFile); void addWord(const char *word,bool hiPriority); void write(const char *file); private: - Private *p; + std::unique_ptr<Private> p; }; //------- client side search index ---------------------- diff --git a/src/sqlcode.h b/src/sqlcode.h index 20e20f7..aa465d7 100644 --- a/src/sqlcode.h +++ b/src/sqlcode.h @@ -1,12 +1,10 @@ /****************************************************************************** * - * - * - * Copyright (C) 1997-2014 by Dimitri van Heesch. + * Copyright (C) 1997-2020 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. * @@ -32,6 +30,8 @@ class Definition; class SQLCodeParser : public CodeParserInterface { public: + SQLCodeParser(); + virtual ~SQLCodeParser(); void parseCode(CodeOutputInterface &codeOutIntf, const char *scopeName, const QCString &input, @@ -48,6 +48,9 @@ class SQLCodeParser : public CodeParserInterface bool collectXRefs=TRUE ); void resetCodeParserState(); + private: + struct Private; + std::unique_ptr<Private> p; }; diff --git a/src/sqlcode.l b/src/sqlcode.l index 58a2fce..74318bb 100644 --- a/src/sqlcode.l +++ b/src/sqlcode.l @@ -1,10 +1,10 @@ /****************************************************************************** * - * Copyright (C) 1997-2014 by Dimitri van Heesch. + * Copyright (C) 1997-2020 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. * @@ -50,7 +50,7 @@ struct sqlcodeYY_state { CodeOutputInterface * code; const char *inputString; //!< the code fragment as text - int inputPosition; //!< read offset during parsing + yy_size_t inputPosition; //!< read offset during parsing int inputLines; //!< number of line in the code fragment int yyLineNr; //!< current line number bool needsTermination; @@ -60,9 +60,9 @@ struct sqlcodeYY_state QCString exampleName; QCString classScope; - FileDef *sourceFileDef; - Definition *currentDefinition; - MemberDef *currentMemberDef; + const FileDef *sourceFileDef; + const Definition *currentDefinition; + const MemberDef *currentMemberDef; bool includeCodeFragment; const char *currentFontClass; }; @@ -71,18 +71,18 @@ struct sqlcodeYY_state static const char *stateToString(int state); #endif -static void setCurrentDoc(const QCString &anchor,yyscan_t yyscanner); +static void setCurrentDoc(yyscan_t yyscanner,const QCString &anchor); 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 void codifyLines(yyscan_t yyscanner,const char *text); +static void startFontClass(yyscan_t yyscanner,const char *s); static int countLines(yyscan_t yyscanner); -static yy_size_t yyread(char *buf,yy_size_t max_size,yyscan_t yyscanner); +static yy_size_t yyread(yyscan_t yyscanner,char *buf,yy_size_t max_size); #undef YY_INPUT -#define YY_INPUT(buf,result,max_size) result=yyread(buf,max_size,yyscanner); +#define YY_INPUT(buf,result,max_size) result=yyread(yyscanner,buf,max_size); %} @@ -110,7 +110,7 @@ typekeyword (?i:"ARRAY"|"BIGINT"|"BINARY"|"BLOB"|"BOOLEAN"|"CHAR"|"CHARACTER flowkeyword (?i:"CASE"|"IF"|"ELSE"|"BEGIN"|"END"|"WHILE") -literalkeyword (?i:"FALSE"|"TRUE"|"NULL"|"UNKNOWN") +literalkeyword (?i:"false"|"true"|"NULL"|"UNKNOWN") stringliteral (\"[^"]*\")|('[^']*') number [0-9]+ literals ({literalkeyword}|{stringliteral}|{number}) @@ -126,104 +126,107 @@ commentclose "\*/" %% {literals} { - startFontClass("stringliteral",yyscanner); - codifyLines(yytext,yyscanner); + startFontClass(yyscanner,"stringliteral"); + codifyLines(yyscanner,yytext); endFontClass(yyscanner); } - + {keyword} { - startFontClass("keyword",yyscanner); - codifyLines(yytext,yyscanner); + startFontClass(yyscanner,"keyword"); + codifyLines(yyscanner,yytext); endFontClass(yyscanner); } {flowkeyword} { - startFontClass("keywordflow",yyscanner); - codifyLines(yytext,yyscanner); + startFontClass(yyscanner,"keywordflow"); + codifyLines(yyscanner,yytext); endFontClass(yyscanner); } {typekeyword} { - startFontClass("keywordtype",yyscanner); - codifyLines(yytext,yyscanner); + startFontClass(yyscanner,"keywordtype"); + codifyLines(yyscanner,yytext); endFontClass(yyscanner); } {variable} { - startFontClass("preprocessor",yyscanner); - codifyLines(yytext,yyscanner); + startFontClass(yyscanner,"preprocessor"); + codifyLines(yyscanner,yytext); endFontClass(yyscanner); } {simplecomment} { - startFontClass("comment",yyscanner); - codifyLines(yytext,yyscanner); + startFontClass(yyscanner,"comment"); + codifyLines(yyscanner,yytext); endFontClass(yyscanner); } {commentopen} { - startFontClass("comment",yyscanner); - codifyLines(yytext,yyscanner); + startFontClass(yyscanner,"comment"); + codifyLines(yyscanner,yytext); BEGIN(COMMENT); } <COMMENT>. { - codifyLines(yytext,yyscanner); - + codifyLines(yyscanner,yytext); + } <COMMENT>{nl} { - codifyLines(yytext,yyscanner); + codifyLines(yyscanner,yytext); } <COMMENT>{commentclose} { - codifyLines(yytext,yyscanner); + codifyLines(yyscanner,yytext); endFontClass(yyscanner); BEGIN(INITIAL); } - + {idchar} { - codifyLines(yytext,yyscanner); + codifyLines(yyscanner,yytext); } {nl} { - codifyLines(yytext,yyscanner); + codifyLines(yyscanner,yytext); } +[\x80-\xFF]* { // keep utf8 characters together... + codifyLines(yyscanner,yytext); + } . { - codifyLines(yytext,yyscanner); + codifyLines(yyscanner,yytext); } %% -static void setCurrentDoc(const QCString &anchor, yyscan_t yyscanner) +static void setCurrentDoc(yyscan_t yyscanner,const QCString &anchor) { struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; if (Doxygen::searchIndex) { if (yyextra->searchCtx) { - Doxygen::searchIndex->setCurrentDoc(yyextra->searchCtx,yyextra->searchCtx->anchor(),FALSE); + yyextra->code->setCurrentDoc(yyextra->searchCtx,yyextra->searchCtx->anchor(),false); } else { - Doxygen::searchIndex->setCurrentDoc(yyextra->sourceFileDef,anchor,TRUE); + yyextra->code->setCurrentDoc(yyextra->sourceFileDef,anchor,true); } } } /*! 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 + * 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(yyscan_t yyscanner) { struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; if (yyextra->sourceFileDef) - { - Definition *d = yyextra->sourceFileDef->getSourceDefinition(yyextra->yyLineNr); - + { + const Definition *d = yyextra->sourceFileDef->getSourceDefinition(yyextra->yyLineNr); + if (!yyextra->includeCodeFragment && d && d->isLinkableInProject()) { yyextra->currentDefinition = d; @@ -236,14 +239,14 @@ static void startCodeLine(yyscan_t yyscanner) yyextra->code->writeLineNumber(yyextra->currentMemberDef->getReference(), yyextra->currentMemberDef->getOutputFileBase(), yyextra->currentMemberDef->anchor(),yyextra->yyLineNr); - setCurrentDoc(lineAnchor,yyscanner); + setCurrentDoc(yyscanner,lineAnchor); } else { yyextra->code->writeLineNumber(d->getReference(), d->getOutputFileBase(), 0,yyextra->yyLineNr); - setCurrentDoc(lineAnchor,yyscanner); + setCurrentDoc(yyscanner,lineAnchor); } } else @@ -251,9 +254,9 @@ static void startCodeLine(yyscan_t yyscanner) yyextra->code->writeLineNumber(0,0,0,yyextra->yyLineNr); } } - + yyextra->code->startCodeLine(yyextra->sourceFileDef); - + if (yyextra->currentFontClass) { yyextra->code->startFontClass(yyextra->currentFontClass); @@ -282,42 +285,43 @@ static void nextCodeLine(yyscan_t yyscanner) struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; const char *fc = yyextra->currentFontClass; endCodeLine(yyscanner); - if (yyextra->yyLineNr<yyextra->inputLines) + if (yyextra->yyLineNr<yyextra->inputLines) { yyextra->currentFontClass = fc; startCodeLine(yyscanner); } } -static void codifyLines(char *text,yyscan_t yyscanner) +static void codifyLines(yyscan_t yyscanner,const char *text) { struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; - char *p=text,*sp=p; + const char *p=text,*sp=p; char c; - bool done=FALSE; - + bool done=false; while (!done) { sp=p; - while ((c=*p++) && c!='\n') { } - if (c=='\n') { yyextra->yyLineNr++; - *(p-1)='\0'; - yyextra->code->codify(sp); + int l = (int)(p-sp-1); + char *tmp = (char*)malloc(l+1); + memcpy(tmp,sp,l); + tmp[l]='\0'; + yyextra->code->codify(tmp); + free(tmp); nextCodeLine(yyscanner); } else { yyextra->code->codify(sp); - done=TRUE; + done=true; } } } -static void startFontClass(const char *s,yyscan_t yyscanner) +static void startFontClass(yyscan_t yyscanner,const char *s) { struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; endFontClass(yyscanner); @@ -332,103 +336,128 @@ static int countLines(yyscan_t yyscanner) const char *p=yyextra->inputString; char c; int count=1; - while ((c=*p)) - { - p++ ; - if (c=='\n') count++; + while ((c=*p)) + { + p++ ; + if (c=='\n') count++; } - if (p>yyextra->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++, - yyextra->needsTermination=TRUE; - } + count++, + yyextra->needsTermination=true; + } return count; } -static yy_size_t yyread(char *buf,yy_size_t max_size,yyscan_t yyscanner) +static yy_size_t yyread(yyscan_t yyscanner,char *buf,yy_size_t max_size) { struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + yy_size_t inputPosition = yyextra->inputPosition; + const char *s = yyextra->inputString + inputPosition; yy_size_t c=0; - while( c < max_size && yyextra->inputString[yyextra->inputPosition] ) + while( c < max_size && *s ) { - *buf = yyextra->inputString[yyextra->inputPosition++] ; - c++; buf++; + *buf++ = *s++; + c++; } + yyextra->inputPosition += c; return c; } // public interface ----------------------------------------------------------- -static yyscan_t yyscanner; -static struct sqlcodeYY_state sqlcode_extra; - -void parseSqlCode( - CodeOutputInterface &od, - const char * /*className*/, - const QCString &s, - bool exBlock, - const char *exName, - FileDef *fd, - int startLine, - int endLine, - bool inlineFragment, - 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; +struct SQLCodeParser::Private +{ + yyscan_t yyscanner; + sqlcodeYY_state state; +}; + +SQLCodeParser::SQLCodeParser() : p(std::make_unique<Private>()) +{ + sqlcodeYYlex_init_extra(&p->state, &p->yyscanner); #ifdef FLEX_DEBUG sqlcodeYYset_debug(1,yyscanner); #endif + resetCodeParserState(); +} + +SQLCodeParser::~SQLCodeParser() +{ + sqlcodeYYlex_destroy(p->yyscanner); +} + +void SQLCodeParser::resetCodeParserState() +{ + struct yyguts_t *yyg = (struct yyguts_t*)p->yyscanner; + yyextra->currentDefinition = 0; + yyextra->currentMemberDef = 0; +} + +void SQLCodeParser::parseCode(CodeOutputInterface &codeOutIntf, + const char *scopeName, + const QCString &input, + SrcLangExt, + bool isExampleBlock, + const char *exampleName, + FileDef *fileDef, + int startLine, + int endLine, + bool inlineFragment, + const MemberDef *memberDef, + bool showLineNumbers, + const Definition *searchCtx, + bool collectXRefs + ) +{ + yyscan_t yyscanner = p->yyscanner; + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; - printlex(yy_flex_debug, TRUE, __FILE__, fd ? fd->fileName().data(): NULL); - - yyextra->code = &od; - yyextra->inputString = s; + if (input.isEmpty()) return; + + printlex(yy_flex_debug, true, __FILE__, fileDef ? fileDef->fileName().data(): NULL); + + yyextra->code = &codeOutIntf; + yyextra->inputString = input; yyextra->inputPosition = 0; yyextra->currentFontClass = 0; - yyextra->needsTermination = FALSE; + yyextra->needsTermination = false; yyextra->searchCtx=searchCtx; - + if (startLine!=-1) yyextra->yyLineNr = startLine; else yyextra->yyLineNr = 1; - + if (endLine!=-1) yyextra->inputLines = endLine+1; else yyextra->inputLines = yyextra->yyLineNr + countLines(yyscanner) - 1; - - yyextra->exampleBlock = exBlock; - yyextra->exampleName = exName; - yyextra->sourceFileDef = fd; - - bool cleanupSourceDef = FALSE; - - if (exBlock && fd==0) + + yyextra->exampleBlock = isExampleBlock; + yyextra->exampleName = exampleName; + yyextra->sourceFileDef = fileDef; + + bool cleanupSourceDef = false; + + if (isExampleBlock && fileDef==0) { // create a dummy filedef for the example - yyextra->sourceFileDef = createFileDef("",(exName?exName:"generated")); - cleanupSourceDef = TRUE; + yyextra->sourceFileDef = createFileDef("",(exampleName?exampleName:"generated")); + cleanupSourceDef = true; } - - if (yyextra->sourceFileDef) + + if (yyextra->sourceFileDef) { - setCurrentDoc("l00001",yyscanner); + setCurrentDoc(yyscanner,"l00001"); } yyextra->includeCodeFragment = inlineFragment; - // Starts line 1 on the output + // Starts line 1 on the output startCodeLine(yyscanner); - sqlcodeYYrestart( yyin,yyscanner ); + sqlcodeYYrestart( 0, yyscanner ); sqlcodeYYlex(yyscanner); @@ -442,45 +471,8 @@ void parseSqlCode( delete yyextra->sourceFileDef; yyextra->sourceFileDef=0; } - - printlex(yy_flex_debug, FALSE, __FILE__, fd ? fd->fileName().data(): NULL); - sqlcodeYYlex_destroy(yyscanner); - return; -} - -void resetSqlCodeParserState() -{ - struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; - yyextra->currentDefinition = 0; - yyextra->currentMemberDef = 0; -} - -//--------------------------------------------------------------------------------- -void SQLCodeParser::parseCode(CodeOutputInterface &codeOutIntf, - const char *scopeName, - const QCString &input, - SrcLangExt, - bool isExampleBlock, - const char *exampleName, - FileDef *fileDef, - int startLine, - int endLine, - bool inlineFragment, - const MemberDef *memberDef, - bool showLineNumbers, - const Definition *searchCtx, - bool collectXRefs - ) -{ - parseSqlCode(codeOutIntf,scopeName,input,isExampleBlock,exampleName, - fileDef,startLine,endLine,inlineFragment,memberDef, - showLineNumbers,searchCtx,collectXRefs); -} - -void SQLCodeParser::resetCodeParserState() -{ - resetSqlCodeParserState(); + printlex(yy_flex_debug, false, __FILE__, fileDef ? fileDef->fileName().data(): NULL); } //--------------------------------------------------------------------------------- diff --git a/src/sqlite3gen.cpp b/src/sqlite3gen.cpp index 2f72221..bfbe25e 100644 --- a/src/sqlite3gen.cpp +++ b/src/sqlite3gen.cpp @@ -1421,7 +1421,7 @@ QCString getSQLDocBlock(const Definition *scope, fileName, lineNr, const_cast<Definition*>(scope), - dynamic_cast<const MemberDef*>(def), + toMemberDef(def), doc, FALSE, FALSE, @@ -1619,26 +1619,16 @@ static void generateSqlite3ForMember(const MemberDef *md, struct Refid scope_ref // + source references // The cross-references in initializers only work when both the src and dst // are defined. - MemberSDict *mdict = md->getReferencesMembers(); - if (mdict!=0) + auto refList = md->getReferencesMembers(); + for (const auto &rmd : refList) { - MemberSDict::IteratorDict mdi(*mdict); - const MemberDef *rmd; - for (mdi.toFirst();(rmd=mdi.current());++mdi) - { - insertMemberReference(md,rmd, "inline"); - } + insertMemberReference(md,rmd, "inline"); } // + source referenced by - mdict = md->getReferencedByMembers(); - if (mdict!=0) + auto refByList = md->getReferencedByMembers(); + for (const auto &rmd : refByList) { - MemberSDict::IteratorDict mdi(*mdict); - const MemberDef *rmd; - for (mdi.toFirst();(rmd=mdi.current());++mdi) - { - insertMemberReference(rmd,md, "inline"); - } + insertMemberReference(rmd,md, "inline"); } return; } @@ -1856,24 +1846,16 @@ static void generateSqlite3ForMember(const MemberDef *md, struct Refid scope_ref // + source references // The cross-references in initializers only work when both the src and dst // are defined. - MemberSDict *mdict = md->getReferencesMembers(); - if (mdict!=0) + auto refList = md->getReferencesMembers(); + for (const auto &refmd : refList) { - MemberSDict::IteratorDict mdi(*mdict); - for (mdi.toFirst();(rmd=mdi.current());++mdi) - { - insertMemberReference(md,rmd, "inline"); - } + insertMemberReference(md,refmd, "inline"); } // + source referenced by - mdict = md->getReferencedByMembers(); - if (mdict!=0) + auto refByList = md->getReferencedByMembers(); + for (const auto &refmd : refByList) { - MemberSDict::IteratorDict mdi(*mdict); - for (mdi.toFirst();(rmd=mdi.current());++mdi) - { - insertMemberReference(rmd,md, "inline"); - } + insertMemberReference(refmd,md, "inline"); } } @@ -2012,37 +1994,27 @@ static void generateSqlite3ForClass(const ClassDef *cd) step(compounddef_insert); // + list of direct super classes - if (cd->baseClasses()) + for (const auto &bcd : cd->baseClasses()) { - BaseClassListIterator bcli(*cd->baseClasses()); - const BaseClassDef *bcd; - for (bcli.toFirst();(bcd=bcli.current());++bcli) - { - struct Refid base_refid = insertRefid(bcd->classDef->getOutputFileBase()); - struct Refid derived_refid = insertRefid(cd->getOutputFileBase()); - bindIntParameter(compoundref_insert,":base_rowid", base_refid.rowid); - bindIntParameter(compoundref_insert,":derived_rowid", derived_refid.rowid); - bindIntParameter(compoundref_insert,":prot",bcd->prot); - bindIntParameter(compoundref_insert,":virt",bcd->virt); - step(compoundref_insert); - } + struct Refid base_refid = insertRefid(bcd.classDef->getOutputFileBase()); + struct Refid derived_refid = insertRefid(cd->getOutputFileBase()); + bindIntParameter(compoundref_insert,":base_rowid", base_refid.rowid); + bindIntParameter(compoundref_insert,":derived_rowid", derived_refid.rowid); + bindIntParameter(compoundref_insert,":prot",bcd.prot); + bindIntParameter(compoundref_insert,":virt",bcd.virt); + step(compoundref_insert); } // + list of direct sub classes - if (cd->subClasses()) - { - BaseClassListIterator bcli(*cd->subClasses()); - const BaseClassDef *bcd; - for (bcli.toFirst();(bcd=bcli.current());++bcli) - { - struct Refid derived_refid = insertRefid(bcd->classDef->getOutputFileBase()); - struct Refid base_refid = insertRefid(cd->getOutputFileBase()); - bindIntParameter(compoundref_insert,":base_rowid", base_refid.rowid); - bindIntParameter(compoundref_insert,":derived_rowid", derived_refid.rowid); - bindIntParameter(compoundref_insert,":prot",bcd->prot); - bindIntParameter(compoundref_insert,":virt",bcd->virt); - step(compoundref_insert); - } + for (const auto &bcd : cd->subClasses()) + { + struct Refid derived_refid = insertRefid(bcd.classDef->getOutputFileBase()); + struct Refid base_refid = insertRefid(cd->getOutputFileBase()); + bindIntParameter(compoundref_insert,":base_rowid", base_refid.rowid); + bindIntParameter(compoundref_insert,":derived_rowid", derived_refid.rowid); + bindIntParameter(compoundref_insert,":prot",bcd.prot); + bindIntParameter(compoundref_insert,":virt",bcd.virt); + step(compoundref_insert); } // + list of inner classes diff --git a/src/symbolmap.h b/src/symbolmap.h new file mode 100644 index 0000000..0f837d4 --- /dev/null +++ b/src/symbolmap.h @@ -0,0 +1,79 @@ +/****************************************************************************** + * + * Copyright (C) 1997-2020 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 SYMBOLMAP_H +#define SYMBOLMAP_H + +#include <algorithm> +#include <map> +#include <vector> +#include <string> +#include <utility> + +//! Class implementing a symbol map that maps symbol names to objects. +//! Symbol names do not have to be unique. +//! Supports adding symbols with add(), removing symbols with remove(), and +//! finding symbols with find(). +template<class T> +class SymbolMap +{ + public: + using Ptr = T *; + using Map = std::multimap<std::string,Ptr>; + using iterator = typename Map::iterator; + using const_iterator = typename Map::const_iterator; + + //! Add a symbol \a def into the map under key \a name + void add(const char *name,Ptr def) + { + m_map.insert({std::string(name),def}); + } + + //! Remove a symbol \a def from the map that was stored under key \a name + void remove(const char *name,Ptr def) + { + auto range = find(name); + for (auto it=range.first; it!=range.second; ) + { + if (it->second==def) it = m_map.erase(it); else ++it; + } + } + + //! Find the list of symbols stored under key \a name + //! Returns a pair of iterators pointing to the start and end of the range of matching symbols + std::pair<const_iterator,const_iterator> find(const char *name) const + { + return m_map.equal_range(name ? name : ""); + } + + //! Find the list of symbols stored under key \a name + //! Returns a pair of iterators pointing to the start and end of the range of matching symbols + std::pair<iterator,iterator> find(const char *name) + { + return m_map.equal_range(name ? name : ""); + } + + iterator begin() { return m_map.begin(); } + iterator end() { return m_map.end(); } + const_iterator begin() const { return m_map.cbegin(); } + const_iterator end() const { return m_map.cend(); } + bool empty() const { return m_map.empty(); } + size_t size() const { return m_map.size(); } + + private: + Map m_map; +}; + +#endif diff --git a/src/symbolresolver.cpp b/src/symbolresolver.cpp new file mode 100644 index 0000000..9f80c15 --- /dev/null +++ b/src/symbolresolver.cpp @@ -0,0 +1,1114 @@ +/****************************************************************************** + * + * Copyright (C) 1997-2020 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 <unordered_map> +#include <string> +#include <vector> + +#include "symbolresolver.h" +#include "util.h" +#include "doxygen.h" +#include "namespacedef.h" +#include "config.h" +#include "defargs.h" + +static std::mutex g_cacheMutex; + +//-------------------------------------------------------------------------------------- + +/** Helper class representing the stack of items considered while resolving + * the scope. + */ +class AccessStack +{ + /** Element in the stack. */ + struct AccessElem + { + AccessElem(const Definition *d,const FileDef *f,const Definition *i,QCString e = QCString()) : scope(d), fileScope(f), item(i), expScope(e) {} + const Definition *scope; + const FileDef *fileScope; + const Definition *item; + QCString expScope; + }; + public: + void push(const Definition *scope,const FileDef *fileScope,const Definition *item) + { + m_elements.push_back(AccessElem(scope,fileScope,item)); + } + void push(const Definition *scope,const FileDef *fileScope,const Definition *item,const QCString &expScope) + { + m_elements.push_back(AccessElem(scope,fileScope,item,expScope)); + } + void pop() + { + if (!m_elements.empty()) m_elements.pop_back(); + } + bool find(const Definition *scope,const FileDef *fileScope, const Definition *item) + { + auto it = std::find_if(m_elements.begin(),m_elements.end(), + [&](const AccessElem &e) { return e.scope==scope && e.fileScope==fileScope && e.item==item; }); + return it!=m_elements.end(); + } + bool find(const Definition *scope,const FileDef *fileScope, const Definition *item,const QCString &expScope) + { + auto it = std::find_if(m_elements.begin(),m_elements.end(), + [&](const AccessElem &e) { return e.scope==scope && e.fileScope==fileScope && e.item==item && e.expScope==expScope; }); + return it!=m_elements.end(); + } + void clear() + { + m_elements.clear(); + } + + private: + std::vector<AccessElem> m_elements; +}; + +//-------------------------------------------------------------------------------------- + +using VisitedNamespaces = std::unordered_map<std::string,const Definition *>; + +//-------------------------------------------------------------------------------------- + +struct SymbolResolver::Private +{ + public: + Private(const FileDef *f) : m_fileScope(f) {} + void reset() + { + m_resolvedTypedefs.clear(); + resolvedType.resize(0); + typeDef = 0; + templateSpec.resize(0); + } + void setFileScope(const FileDef *fileScope) + { + m_fileScope = fileScope; + } + + QCString resolvedType; + const MemberDef *typeDef = 0; + QCString templateSpec; + + const ClassDef *getResolvedClassRec( + const Definition *scope, // in + const char *n, // in + const MemberDef **pTypeDef, // out + QCString *pTemplSpec, // out + QCString *pResolvedType); // out + + int isAccessibleFrom( AccessStack &accessStack, + const Definition *scope, + const Definition *item); + + int isAccessibleFromWithExpScope( + VisitedNamespaces &visitedNamespaces, + AccessStack &accessStack, + const Definition *scope, + const Definition *item, + const QCString &explicitScopePart); + + private: + void getResolvedSymbol(const Definition *scope, // in + const Definition *d, // in + const QCString &explicitScopePart, // in + const std::unique_ptr<ArgumentList> &actTemplParams, // in + int &minDistance, // input + const ClassDef *&bestMatch, // out + const MemberDef *&bestTypedef, // out + QCString &bestTemplSpec, // out + QCString &bestResolvedType // out + ); + + const ClassDef *newResolveTypedef( + const Definition *scope, // in + const MemberDef *md, // in + const MemberDef **pMemType, // out + QCString *pTemplSpec, // out + QCString *pResolvedType, // out + const std::unique_ptr<ArgumentList> &actTemplParams = std::unique_ptr<ArgumentList>() + ); + + const Definition *followPath(const Definition *start,const QCString &path); + + const Definition *endOfPathIsUsedClass(LinkedRefMap<const ClassDef> cl,const QCString &localName); + + bool accessibleViaUsingNamespace(StringUnorderedSet &visited, + const LinkedRefMap<const NamespaceDef> &nl, + const Definition *item, + const QCString &explicitScopePart=""); + bool accessibleViaUsingClass(const LinkedRefMap<const ClassDef> &cl, + const Definition *item, + const QCString &explicitScopePart="" + ); + QCString substTypedef(const Definition *scope,const QCString &name, + const MemberDef **pTypeDef=0); + + const FileDef *m_fileScope; + std::unordered_map<std::string,const MemberDef*> m_resolvedTypedefs; +}; + + + +const ClassDef *SymbolResolver::Private::getResolvedClassRec( + const Definition *scope, + const char *n, + const MemberDef **pTypeDef, + QCString *pTemplSpec, + QCString *pResolvedType) +{ + if (n==0 || *n=='\0') return 0; + //static int level=0; + //fprintf(stderr,"%d [getResolvedClassRec(%s,%s)\n",level++,scope?scope->name().data():"<global>",n); + QCString name; + QCString explicitScopePart; + QCString strippedTemplateParams; + name=stripTemplateSpecifiersFromScope + (removeRedundantWhiteSpace(n),TRUE, + &strippedTemplateParams); + std::unique_ptr<ArgumentList> actTemplParams; + if (!strippedTemplateParams.isEmpty()) // template part that was stripped + { + actTemplParams = stringToArgumentList(scope->getLanguage(),strippedTemplateParams); + } + + int qualifierIndex = computeQualifiedIndex(name); + //printf("name=%s qualifierIndex=%d\n",name.data(),qualifierIndex); + if (qualifierIndex!=-1) // qualified name + { + // split off the explicit scope part + explicitScopePart=name.left(qualifierIndex); + // todo: improve namespace alias substitution + replaceNamespaceAliases(explicitScopePart,explicitScopePart.length()); + name=name.mid(qualifierIndex+2); + } + + if (name.isEmpty()) + { + //fprintf(stderr,"%d ] empty name\n",--level); + return 0; // empty name + } + + //printf("Looking for symbol %s\n",name.data()); + auto range = Doxygen::symbolMap.find(name); + // the -g (for C# generics) and -p (for ObjC protocols) are now already + // stripped from the key used in the symbolMap, so that is not needed here. + if (range.first==range.second) + { + range = Doxygen::symbolMap.find(name+"-p"); + if (range.first==range.second) + { + //fprintf(stderr,"%d ] no such symbol!\n",--level); + return 0; + } + } + //printf("found symbol!\n"); + + bool hasUsingStatements = + (m_fileScope && (!m_fileScope->getUsedNamespaces().empty() || + !m_fileScope->getUsedClasses().empty()) + ); + //printf("hasUsingStatements=%d\n",hasUsingStatements); + // Since it is often the case that the same name is searched in the same + // scope over an over again (especially for the linked source code generation) + // we use a cache to collect previous results. This is possible since the + // result of a lookup is deterministic. As the key we use the concatenated + // scope, the name to search for and the explicit scope prefix. The speedup + // achieved by this simple cache can be enormous. + int scopeNameLen = scope->name().length()+1; + int nameLen = name.length()+1; + int explicitPartLen = explicitScopePart.length(); + int fileScopeLen = hasUsingStatements ? 1+m_fileScope->absFilePath().length() : 0; + + // below is a more efficient coding of + // QCString key=scope->name()+"+"+name+"+"+explicitScopePart; + QCString key(scopeNameLen+nameLen+explicitPartLen+fileScopeLen+1); + char *pk=key.rawData(); + qstrcpy(pk,scope->name()); *(pk+scopeNameLen-1)='+'; + pk+=scopeNameLen; + qstrcpy(pk,name); *(pk+nameLen-1)='+'; + pk+=nameLen; + qstrcpy(pk,explicitScopePart); + pk+=explicitPartLen; + + // if a file scope is given and it contains using statements we should + // also use the file part in the key (as a class name can be in + // two different namespaces and a using statement in a file can select + // one of them). + if (hasUsingStatements) + { + // below is a more efficient coding of + // key+="+"+m_fileScope->name(); + *pk++='+'; + qstrcpy(pk,m_fileScope->absFilePath()); + pk+=fileScopeLen-1; + } + *pk='\0'; + + LookupInfo *pval = 0; + { + std::lock_guard<std::mutex> lock(g_cacheMutex); + pval=Doxygen::lookupCache->find(key.str()); + //printf("Searching for %s result=%p\n",key.data(),pval); + if (pval) + { + //printf("LookupInfo %p %p '%s' %p\n", + // pval->classDef, pval->typeDef, pval->templSpec.data(), + // pval->resolvedType.data()); + if (pTemplSpec) *pTemplSpec=pval->templSpec; + if (pTypeDef) *pTypeDef=pval->typeDef; + if (pResolvedType) *pResolvedType=pval->resolvedType; + //fprintf(stderr,"%d ] cachedMatch=%s\n",--level, + // pval->classDef?pval->classDef->name().data():"<none>"); + //if (pTemplSpec) + // printf("templSpec=%s\n",pTemplSpec->data()); + return pval->classDef; + } + else // not found yet; we already add a 0 to avoid the possibility of + // endless recursion. + { + pval = Doxygen::lookupCache->insert(key.str(),LookupInfo()); + } + } + + const ClassDef *bestMatch=0; + const MemberDef *bestTypedef=0; + QCString bestTemplSpec; + QCString bestResolvedType; + int minDistance=10000; // init at "infinite" + + for (auto it=range.first ; it!=range.second; ++it) + { + Definition *d = it->second; + getResolvedSymbol(scope,d,explicitScopePart,actTemplParams, + minDistance,bestMatch,bestTypedef,bestTemplSpec,bestResolvedType); + } + + if (pTypeDef) + { + *pTypeDef = bestTypedef; + } + if (pTemplSpec) + { + *pTemplSpec = bestTemplSpec; + } + if (pResolvedType) + { + *pResolvedType = bestResolvedType; + } + + //printf("getResolvedClassRec: bestMatch=%p pval->resolvedType=%s\n", + // bestMatch,bestResolvedType.data()); + + if (pval) + { + std::lock_guard<std::mutex> lock(g_cacheMutex); + pval->classDef = bestMatch; + pval->typeDef = bestTypedef; + pval->templSpec = bestTemplSpec; + pval->resolvedType = bestResolvedType; + } + //fprintf(stderr,"%d ] bestMatch=%s distance=%d\n",--level, + // bestMatch?bestMatch->name().data():"<none>",minDistance); + //if (pTemplSpec) + // printf("templSpec=%s\n",pTemplSpec->data()); + return bestMatch; +} + +void SymbolResolver::Private::getResolvedSymbol( + const Definition *scope, // in + const Definition *d, // in + const QCString &explicitScopePart, // in + const std::unique_ptr<ArgumentList> &actTemplParams, // in + int &minDistance, // inout + const ClassDef *&bestMatch, // out + const MemberDef *&bestTypedef, // out + QCString &bestTemplSpec, // out + QCString &bestResolvedType // out + ) +{ + //fprintf(stderr,"getResolvedSymbol(%s,%s)\n",scope->name().data(),d->qualifiedName().data()); + // only look at classes and members that are enums or typedefs + if (d->definitionType()==Definition::TypeClass || + (d->definitionType()==Definition::TypeMember && + ((toMemberDef(d))->isTypedef() || + (toMemberDef(d))->isEnumerate()) + ) + ) + { + VisitedNamespaces visitedNamespaces; + AccessStack accessStack; + // test accessibility of definition within scope. + int distance = isAccessibleFromWithExpScope(visitedNamespaces,accessStack,scope,d,explicitScopePart); + //fprintf(stderr," %s; distance %s (%p) is %d\n",scope->name().data(),d->name().data(),d,distance); + if (distance!=-1) // definition is accessible + { + // see if we are dealing with a class or a typedef + if (d->definitionType()==Definition::TypeClass) // d is a class + { + const ClassDef *cd = toClassDef(d); + //printf("cd=%s\n",cd->name().data()); + if (!cd->isTemplateArgument()) // skip classes that + // are only there to + // represent a template + // argument + { + //printf("is not a templ arg\n"); + if (distance<minDistance) // found a definition that is "closer" + { + minDistance=distance; + bestMatch = cd; + bestTypedef = 0; + bestTemplSpec.resize(0); + bestResolvedType = cd->qualifiedName(); + } + else if (distance==minDistance && + m_fileScope && bestMatch && + !m_fileScope->getUsedNamespaces().empty() && + d->getOuterScope()->definitionType()==Definition::TypeNamespace && + bestMatch->getOuterScope()==Doxygen::globalScope + ) + { + // in case the distance is equal it could be that a class X + // is defined in a namespace and in the global scope. When searched + // in the global scope the distance is 0 in both cases. We have + // to choose one of the definitions: we choose the one in the + // namespace if the fileScope imports namespaces and the definition + // found was in a namespace while the best match so far isn't. + // Just a non-perfect heuristic but it could help in some situations + // (kdecore code is an example). + minDistance=distance; + bestMatch = cd; + bestTypedef = 0; + bestTemplSpec.resize(0); + bestResolvedType = cd->qualifiedName(); + } + } + else + { + //printf(" is a template argument!\n"); + } + } + else if (d->definitionType()==Definition::TypeMember) + { + const MemberDef *md = toMemberDef(d); + //fprintf(stderr," member isTypedef()=%d\n",md->isTypedef()); + if (md->isTypedef()) // d is a typedef + { + QCString args=md->argsString(); + if (args.isEmpty()) // do not expand "typedef t a[4];" + { + //printf(" found typedef!\n"); + + // we found a symbol at this distance, but if it didn't + // resolve to a class, we still have to make sure that + // something at a greater distance does not match, since + // that symbol is hidden by this one. + if (distance<minDistance) + { + QCString spec; + QCString type; + minDistance=distance; + const MemberDef *enumType = 0; + const ClassDef *cd = newResolveTypedef(scope,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()); + bestMatch = cd; + bestTypedef = md; + bestTemplSpec = spec; + bestResolvedType = type; + } + else if (enumType) // type resolves to a member type + { + //printf(" is enum\n"); + bestMatch = 0; + bestTypedef = enumType; + bestTemplSpec = ""; + bestResolvedType = enumType->qualifiedName(); + } + else if (md->isReference()) // external reference + { + bestMatch = 0; + bestTypedef = md; + bestTemplSpec = spec; + bestResolvedType = type; + } + else + { + bestMatch = 0; + bestTypedef = md; + bestTemplSpec.resize(0); + bestResolvedType.resize(0); + //printf(" no match\n"); + } + } + else + { + //printf(" not the best match %d min=%d\n",distance,minDistance); + } + } + else + { + //printf(" not a simple typedef\n") + } + } + else if (md->isEnumerate()) + { + if (distance<minDistance) + { + minDistance=distance; + bestMatch = 0; + bestTypedef = md; + bestTemplSpec = ""; + bestResolvedType = md->qualifiedName(); + } + } + } + } // if definition accessible + else + { + //printf(" Not accessible!\n"); + } + } // if definition is a class or member + //printf(" bestMatch=%p bestResolvedType=%s\n",bestMatch,bestResolvedType.data()); +} + +const ClassDef *SymbolResolver::Private::newResolveTypedef( + const Definition *scope, // in + const MemberDef *md, // in + const MemberDef **pMemType, // out + QCString *pTemplSpec, // out + QCString *pResolvedType, // out + const std::unique_ptr<ArgumentList> &actTemplParams) // in +{ + //printf("newResolveTypedef(md=%p,cachedVal=%p)\n",md,md->getCachedTypedefVal()); + bool isCached = md->isTypedefValCached(); // value already cached + if (isCached) + { + //printf("Already cached %s->%s [%s]\n", + // md->name().data(), + // md->getCachedTypedefVal()?md->getCachedTypedefVal()->name().data():"<none>", + // md->getCachedResolvedTypedef()?md->getCachedResolvedTypedef().data():"<none>"); + + if (pTemplSpec) *pTemplSpec = md->getCachedTypedefTemplSpec(); + if (pResolvedType) *pResolvedType = md->getCachedResolvedTypedef(); + return md->getCachedTypedefVal(); + } + //printf("new typedef\n"); + QCString qname = md->qualifiedName(); + if (m_resolvedTypedefs.find(qname.str())!=m_resolvedTypedefs.end()) + { + return 0; // typedef already done + } + + auto typedef_it = m_resolvedTypedefs.insert({qname.str(),md}).first; // put on the trace list + + const ClassDef *typeClass = md->getClassDef(); + QCString type = md->typeString(); // get the "value" of the typedef + if (typeClass && typeClass->isTemplate() && + actTemplParams && !actTemplParams->empty()) + { + type = substituteTemplateArgumentsInString(type, + typeClass->templateArguments(),actTemplParams); + } + QCString typedefValue = type; + int tl=type.length(); + int ip=tl-1; // remove * and & at the end + while (ip>=0 && (type.at(ip)=='*' || type.at(ip)=='&' || type.at(ip)==' ')) + { + ip--; + } + type=type.left(ip+1); + type.stripPrefix("const "); // strip leading "const" + type.stripPrefix("struct "); // strip leading "struct" + type.stripPrefix("union "); // strip leading "union" + int sp=0; + tl=type.length(); // length may have been changed + while (sp<tl && type.at(sp)==' ') sp++; + const MemberDef *memTypeDef = 0; + const ClassDef *result = getResolvedClassRec(md->getOuterScope(),type, + &memTypeDef,0,pResolvedType); + // if type is a typedef then return what it resolves to. + if (memTypeDef && memTypeDef->isTypedef()) + { + result=newResolveTypedef(m_fileScope,memTypeDef,pMemType,pTemplSpec,0); + goto done; + } + else if (memTypeDef && memTypeDef->isEnumerate() && pMemType) + { + *pMemType = memTypeDef; + } + + //printf("type=%s result=%p\n",type.data(),result); + if (result==0) + { + // try unspecialized version if type is template + int si=type.findRev("::"); + int i=type.find('<'); + if (si==-1 && i!=-1) // typedef of a template => try the unspecialized version + { + if (pTemplSpec) *pTemplSpec = type.mid(i); + result = getResolvedClassRec(md->getOuterScope(),type.left(i),0,0,pResolvedType); + //printf("result=%p pRresolvedType=%s sp=%d ip=%d tl=%d\n", + // result,pResolvedType?pResolvedType->data():"<none>",sp,ip,tl); + } + else if (si!=-1) // A::B + { + i=type.find('<',si); + if (i==-1) // Something like A<T>::B => lookup A::B + { + i=type.length(); + } + else // Something like A<T>::B<S> => lookup A::B, spec=<S> + { + if (pTemplSpec) *pTemplSpec = type.mid(i); + } + result = getResolvedClassRec(md->getOuterScope(), + stripTemplateSpecifiersFromScope(type.left(i),FALSE),0,0,pResolvedType); + } + + //if (result) ip=si+sp+1; + } + +done: + if (pResolvedType) + { + if (result) + { + *pResolvedType = result->qualifiedName(); + //printf("*pResolvedType=%s\n",pResolvedType->data()); + if (sp>0) pResolvedType->prepend(typedefValue.left(sp)); + if (ip<tl-1) pResolvedType->append(typedefValue.right(tl-ip-1)); + } + else + { + *pResolvedType = typedefValue; + } + } + + // remember computed value for next time + if (result && result->getDefFileName()!="<code>") + // this check is needed to prevent that temporary classes that are + // introduced while parsing code fragments are being cached here. + { + //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>"); + MemberDefMutable *mdm = toMemberDefMutable(md); + if (mdm) + { + mdm->cacheTypedefVal(result, + pTemplSpec ? *pTemplSpec : QCString(), + pResolvedType ? *pResolvedType : QCString() + ); + } + } + + m_resolvedTypedefs.erase(typedef_it); // remove from the trace list + + return result; +} + +int SymbolResolver::Private::isAccessibleFromWithExpScope( + VisitedNamespaces &visitedNamespaces, + AccessStack &accessStack, + const Definition *scope, + const Definition *item, + const QCString &explicitScopePart) +{ + if (explicitScopePart.isEmpty()) + { + // handle degenerate case where there is no explicit scope. + return isAccessibleFrom(accessStack,scope,item); + } + + if (accessStack.find(scope,m_fileScope,item,explicitScopePart)) + { + return -1; + } + accessStack.push(scope,m_fileScope,item,explicitScopePart); + + + //printf(" <isAccessibleFromWithExpScope(%s,%s,%s)\n",scope?scope->name().data():"<global>", + // item?item->name().data():"<none>", + // explicitScopePart.data()); + int result=0; // assume we found it + const Definition *newScope = followPath(scope,explicitScopePart); + if (newScope) // explicitScope is inside scope => newScope is the result + { + Definition *itemScope = item->getOuterScope(); + //printf(" scope traversal successful %s<->%s!\n",itemScope->name().data(),newScope->name().data()); + //if (newScope && newScope->definitionType()==Definition::TypeClass) + //{ + // ClassDef *cd = (ClassDef *)newScope; + // printf("---> Class %s: bases=%p\n",cd->name().data(),cd->baseClasses()); + //} + if (itemScope==newScope) // exact match of scopes => distance==0 + { + //printf("> found it\n"); + } + else if (itemScope && newScope && + itemScope->definitionType()==Definition::TypeClass && + newScope->definitionType()==Definition::TypeClass && + (toClassDef(newScope))->isBaseClass(toClassDef(itemScope),TRUE,0) + ) + { + // inheritance is also ok. Example: looking for B::I, where + // class A { public: class I {} }; + // class B : public A {} + // but looking for B::I, where + // class A { public: class I {} }; + // class B { public: class I {} }; + // will find A::I, so we still prefer a direct match and give this one a distance of 1 + result=1; + + //printf("scope(%s) is base class of newScope(%s)\n", + // scope->name().data(),newScope->name().data()); + } + else + { + int i=-1; + if (newScope->definitionType()==Definition::TypeNamespace) + { + visitedNamespaces.insert({newScope->name().str(),newScope}); + // this part deals with the case where item is a class + // A::B::C but is explicit referenced as A::C, where B is imported + // in A via a using directive. + //printf("newScope is a namespace: %s!\n",newScope->name().data()); + const NamespaceDef *nscope = toNamespaceDef(newScope); + for (const auto &cd : nscope->getUsedClasses()) + { + //printf("Trying for class %s\n",cd->name().data()); + if (cd==item) + { + goto done; + } + } + for (const auto &nd : nscope->getUsedNamespaces()) + { + if (visitedNamespaces.find(nd->name().str())==visitedNamespaces.end()) + { + //printf("Trying for namespace %s\n",nd->name().data()); + i = isAccessibleFromWithExpScope(visitedNamespaces,accessStack,scope,item,nd->name()); + if (i!=-1) + { + //printf("> found via explicit scope of used namespace\n"); + goto done; + } + } + } + } + // repeat for the parent scope + if (scope!=Doxygen::globalScope) + { + i = isAccessibleFromWithExpScope(visitedNamespaces,accessStack,scope->getOuterScope(),item,explicitScopePart); + } + //printf(" | result=%d\n",i); + result = (i==-1) ? -1 : i+2; + } + } + else // failed to resolve explicitScope + { + //printf(" failed to resolve: scope=%s\n",scope->name().data()); + if (scope->definitionType()==Definition::TypeNamespace) + { + const NamespaceDef *nscope = toNamespaceDef(scope); + StringUnorderedSet visited; + if (accessibleViaUsingNamespace(visited,nscope->getUsedNamespaces(),item,explicitScopePart)) + { + //printf("> found in used namespace\n"); + goto done; + } + } + if (scope==Doxygen::globalScope) + { + if (m_fileScope) + { + StringUnorderedSet visited; + if (accessibleViaUsingNamespace(visited,m_fileScope->getUsedNamespaces(),item,explicitScopePart)) + { + //printf("> found in used namespace\n"); + goto done; + } + } + //printf("> not found\n"); + result=-1; + } + else // continue by looking into the parent scope + { + int i=isAccessibleFromWithExpScope(visitedNamespaces,accessStack,scope->getOuterScope(),item,explicitScopePart); + //printf("> result=%d\n",i); + result= (i==-1) ? -1 : i+2; + } + } + +done: + //printf(" > result=%d\n",result); + accessStack.pop(); + return result; +} + +const Definition *SymbolResolver::Private::followPath(const Definition *start,const QCString &path) +{ + int is,ps; + int l; + const Definition *current=start; + ps=0; + //printf("followPath: start='%s' path='%s'\n",start?start->name().data():"<none>",path.data()); + // for each part of the explicit scope + while ((is=getScopeFragment(path,ps,&l))!=-1) + { + // try to resolve the part if it is a typedef + const MemberDef *memTypeDef=0; + QCString qualScopePart = substTypedef(current,path.mid(is,l),&memTypeDef); + //printf(" qualScopePart=%s\n",qualScopePart.data()); + if (memTypeDef) + { + const ClassDef *type = newResolveTypedef(m_fileScope,memTypeDef,0,0,0); + if (type) + { + //printf("Found type %s\n",type->name().data()); + return type; + } + } + const Definition *next = current->findInnerCompound(qualScopePart); + //printf("++ Looking for %s inside %s result %s\n", + // qualScopePart.data(), + // current->name().data(), + // next?next->name().data():"<null>"); + if (next==0) // failed to follow the path + { + //printf("==> next==0!\n"); + if (current->definitionType()==Definition::TypeNamespace) + { + next = endOfPathIsUsedClass( + (toNamespaceDef(current))->getUsedClasses(),qualScopePart); + } + else if (current->definitionType()==Definition::TypeFile) + { + next = endOfPathIsUsedClass( + (toFileDef(current))->getUsedClasses(),qualScopePart); + } + current = next; + if (current==0) break; + } + else // continue to follow scope + { + current = next; + //printf("==> current = %p\n",current); + } + ps=is+l; + } + //printf("followPath(start=%s,path=%s) result=%s\n", + // start->name().data(),path.data(),current?current->name().data():"<null>"); + return current; // path could be followed +} + +const Definition *SymbolResolver::Private::endOfPathIsUsedClass(LinkedRefMap<const ClassDef> cl,const QCString &localName) +{ + for (const auto &cd : cl) + { + if (cd->localName()==localName) + { + return cd; + } + } + return 0; +} + +bool SymbolResolver::Private::accessibleViaUsingNamespace(StringUnorderedSet &visited, + const LinkedRefMap<const NamespaceDef> &nl, + const Definition *item, + const QCString &explicitScopePart) +{ + for (const auto &und : nl) // check used namespaces for the class + { + //printf("[Trying via used namespace %s: count=%d/%d\n",und->name().data(), + // count,nl->count()); + const Definition *sc = explicitScopePart.isEmpty() ? und : followPath(und,explicitScopePart); + if (sc && item->getOuterScope()==sc) + { + //printf("] found it\n"); + return true; + } + if (item->getLanguage()==SrcLangExt_Cpp) + { + QCString key=und->name(); + if (!und->getUsedNamespaces().empty() && visited.find(key.str())==visited.end()) + { + visited.insert(key.str()); + + if (accessibleViaUsingNamespace(visited,und->getUsedNamespaces(),item,explicitScopePart)) + { + //printf("] found it via recursion\n"); + return true; + } + + visited.erase(key.str()); + } + } + //printf("] Try via used namespace done\n"); + } + return false; +} + + +bool SymbolResolver::Private::accessibleViaUsingClass(const LinkedRefMap<const ClassDef> &cl, + const Definition *item, + const QCString &explicitScopePart) +{ + for (const auto &ucd : cl) + { + //printf("Trying via used class %s\n",ucd->name().data()); + const Definition *sc = explicitScopePart.isEmpty() ? ucd : followPath(ucd,explicitScopePart); + if (sc && sc==item) return true; + //printf("Try via used class done\n"); + } + return false; +} + +int SymbolResolver::Private::isAccessibleFrom(AccessStack &accessStack, + const Definition *scope, + const Definition *item) +{ + //printf("<isAccessibleFrom(scope=%s,item=%s itemScope=%s)\n", + // scope->name().data(),item->name().data(),item->getOuterScope()->name().data()); + + if (accessStack.find(scope,m_fileScope,item)) + { + return -1; + } + accessStack.push(scope,m_fileScope,item); + + int result=0; // assume we found it + int i; + + Definition *itemScope=item->getOuterScope(); + bool memberAccessibleFromScope = + (item->definitionType()==Definition::TypeMember && // a member + itemScope && itemScope->definitionType()==Definition::TypeClass && // of a class + scope->definitionType()==Definition::TypeClass && // accessible + (toClassDef(scope))->isAccessibleMember(toMemberDef(item)) // from scope + ); + bool nestedClassInsideBaseClass = + (item->definitionType()==Definition::TypeClass && // a nested class + itemScope && itemScope->definitionType()==Definition::TypeClass && // inside a base + scope->definitionType()==Definition::TypeClass && // class of scope + (toClassDef(scope))->isBaseClass(toClassDef(itemScope),TRUE) + ); + + if (itemScope==scope || memberAccessibleFromScope || nestedClassInsideBaseClass) + { + //printf("> found it\n"); + if (nestedClassInsideBaseClass) result++; // penalty for base class to prevent + // this is preferred over nested class in this class + // see bug 686956 + } + else if (scope==Doxygen::globalScope) + { + if (m_fileScope) + { + if (accessibleViaUsingClass(m_fileScope->getUsedClasses(),item)) + { + //printf("> found via used class\n"); + goto done; + } + StringUnorderedSet visited; + if (accessibleViaUsingNamespace(visited,m_fileScope->getUsedNamespaces(),item)) + { + //printf("> found via used namespace\n"); + goto done; + } + } + //printf("> reached global scope\n"); + result=-1; // not found in path to globalScope + } + else // keep searching + { + // check if scope is a namespace, which is using other classes and namespaces + if (scope->definitionType()==Definition::TypeNamespace) + { + const NamespaceDef *nscope = toNamespaceDef(scope); + //printf(" %s is namespace with %d used classes\n",nscope->name().data(),nscope->getUsedClasses()); + if (accessibleViaUsingClass(nscope->getUsedClasses(),item)) + { + //printf("> found via used class\n"); + goto done; + } + StringUnorderedSet visited; + if (accessibleViaUsingNamespace(visited,nscope->getUsedNamespaces(),item)) + { + //printf("> found via used namespace\n"); + goto done; + } + } + // repeat for the parent scope + i=isAccessibleFrom(accessStack,scope->getOuterScope(),item); + //printf("> result=%d\n",i); + result= (i==-1) ? -1 : i+2; + } +done: + accessStack.pop(); + return result; +} + +QCString SymbolResolver::Private::substTypedef( + const Definition *scope,const QCString &name, + const MemberDef **pTypeDef) +{ + QCString result=name; + if (name.isEmpty()) return result; + + auto range = Doxygen::symbolMap.find(name); + if (range.first==range.second) + return result; // no matches + + MemberDef *bestMatch=0; + int minDistance=10000; // init at "infinite" + + for (auto it = range.first; it!=range.second; ++it) + { + Definition *d = it->second; + // only look at members + if (d->definitionType()==Definition::TypeMember) + { + // that are also typedefs + MemberDef *md = toMemberDef(d); + if (md->isTypedef()) // d is a typedef + { + VisitedNamespaces visitedNamespaces; + AccessStack accessStack; + // test accessibility of typedef within scope. + int distance = isAccessibleFromWithExpScope(visitedNamespaces,accessStack,scope,d,""); + if (distance!=-1 && distance<minDistance) + // definition is accessible and a better match + { + minDistance=distance; + bestMatch = md; + } + } + } + } + + if (bestMatch) + { + result = bestMatch->typeString(); + if (pTypeDef) *pTypeDef=bestMatch; + } + + //printf("substTypedef(%s,%s)=%s\n",scope?scope->name().data():"<global>", + // name.data(),result.data()); + return result; +} + +//---------------------------------------------------------------------------------------------- + + +SymbolResolver::SymbolResolver(const FileDef *fileScope) + : p(std::make_unique<Private>(fileScope)) +{ +} + +SymbolResolver::~SymbolResolver() +{ +} + + +const ClassDef *SymbolResolver::resolveClass(const Definition *scope, + const char *name, + bool mayBeUnlinkable, + bool mayBeHidden) +{ + p->reset(); + + if (scope==0 || + (scope->definitionType()!=Definition::TypeClass && + scope->definitionType()!=Definition::TypeNamespace + ) || + (scope->getLanguage()==SrcLangExt_Java && QCString(name).find("::")!=-1) + ) + { + scope=Doxygen::globalScope; + } + //fprintf(stderr,"------------ resolveClass(scope=%s,name=%s,mayUnlinkable=%d)\n", + // scope?scope->name().data():"<global>", + // name, + // mayBeUnlinkable + // ); + const ClassDef *result; + if (Config_getBool(OPTIMIZE_OUTPUT_VHDL)) + { + result = getClass(name); + } + else + { + result = p->getResolvedClassRec(scope,name,&p->typeDef,&p->templateSpec,&p->resolvedType); + if (result==0) // for nested classes imported via tag files, the scope may not + // present, so we check the class name directly as well. + // See also bug701314 + { + result = getClass(name); + } + } + if (!mayBeUnlinkable && result && !result->isLinkable()) + { + if (!mayBeHidden || !result->isHidden()) + { + //printf("result was %s\n",result?result->name().data():"<none>"); + result=0; // don't link to artificial/hidden classes unless explicitly allowed + } + } + //fprintf(stderr,"ResolvedClass(%s,%s)=%s\n",scope?scope->name().data():"<global>", + // name,result?result->name().data():"<none>"); + return result; +} + +int SymbolResolver::isAccessibleFrom(const Definition *scope,const Definition *item) +{ + p->reset(); + AccessStack accessStack; + return p->isAccessibleFrom(accessStack,scope,item); +} + +int SymbolResolver::isAccessibleFromWithExpScope(const Definition *scope,const Definition *item, + const QCString &explicitScopePart) +{ + p->reset(); + VisitedNamespaces visitedNamespaces; + AccessStack accessStack; + return p->isAccessibleFromWithExpScope(visitedNamespaces,accessStack,scope,item,explicitScopePart); +} + +void SymbolResolver::setFileScope(const FileDef *fileScope) +{ + p->setFileScope(fileScope); +} + +const MemberDef *SymbolResolver::getTypedef() const +{ + return p->typeDef; +} + +QCString SymbolResolver::getTemplateSpec() const +{ + return p->templateSpec; +} + +QCString SymbolResolver::getResolvedType() const +{ + return p->resolvedType; +} + diff --git a/src/symbolresolver.h b/src/symbolresolver.h new file mode 100644 index 0000000..5536c1e --- /dev/null +++ b/src/symbolresolver.h @@ -0,0 +1,104 @@ +/****************************************************************************** + * + * Copyright (C) 1997-2020 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 SYMBOLRESOLVER_H +#define SYMBOLRESOLVER_H + +#include <memory> +#include "qcstring.h" +#include "classdef.h" + +class Definition; +class FileDef; +class MemberDef; + +//! Helper class to find a class definition or check if +//! A symbol is accessible in a given scope. +class SymbolResolver +{ + public: + explicit SymbolResolver(const FileDef *fileScope = 0); + ~SymbolResolver(); + + // actions + + /** Find the class definition matching name within + * the scope set. + * @param scope The scope to search from. + * @param name The name of the symbol. + * @param maybeUnlinkable include unlinkable symbols in the search. + * @param mayBeHidden include hidden symbols in the search. + * @note As a result of this call the getters getTypedef(), + * getTemplateSpec(), and getResolvedType() are set as well. + */ + const ClassDef *resolveClass(const Definition *scope, + const char *name, + bool maybeUnlinkable=false, + bool mayBeHidden=false); + + /** Wrapper around resolveClass that returns a mutable interface to + * the class object or a nullptr if the symbol is immutable. + */ + ClassDefMutable *resolveClassMutable(const Definition *scope, + const char *name, + bool mayBeUnlinkable=false, + bool mayBeHidden=false) + { + return toClassDefMutable(resolveClass(scope,name,mayBeUnlinkable,mayBeHidden)); + } + + /** Checks if symbol \a item is accessible from within \a scope. + * @returns -1 if \a item is not accessible or a number indicating how + * many scope levels up the nearest match was found. + */ + int isAccessibleFrom(const Definition *scope, + const Definition *item); + + /** Check if symbol \a item is accessible from within \a scope, + * where it has to match the \a explicitScopePart. + * @returns -1 if \a item is not accessible or a number indicating how + * many scope levels up the nearest match was found. + */ + int isAccessibleFromWithExpScope(const Definition *scope, + const Definition *item, + const QCString &explicitScopePart + ); + + /** Sets or updates the file scope using when resolving symbols. */ + void setFileScope(const FileDef *fd); + + // getters + + /** In case a call to resolveClass() resolves to a type member (e.g. an enum) + * this method will return it. + */ + const MemberDef *getTypedef() const; + + /** In case a call to resolveClass() points to a template specialization, the + * template part is return via this method. + */ + QCString getTemplateSpec() const; + + /** In case a call to resolveClass() points to a typedef or using declaration. + * The type name it resolved to is returned via this method. + */ + QCString getResolvedType() const; + + private: + struct Private; + std::unique_ptr<Private> p; +}; + +#endif diff --git a/src/template.cpp b/src/template.cpp index 66347c4..58188fe 100644 --- a/src/template.cpp +++ b/src/template.cpp @@ -338,7 +338,7 @@ int TemplateList::release() uint TemplateList::count() const { - return p->elems.size(); + return static_cast<uint>(p->elems.size()); } void TemplateList::append(const TemplateVariant &v) diff --git a/src/tooltip.cpp b/src/tooltip.cpp index 8cc1f87..f8222d7 100644 --- a/src/tooltip.cpp +++ b/src/tooltip.cpp @@ -1,10 +1,10 @@ /****************************************************************************** * - * Copyright (C) 1997-2015 by Dimitri van Heesch. + * Copyright (C) 1997-2020 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. * @@ -13,7 +13,11 @@ * */ -#include <qdict.h> +#include <map> +#include <memory> +#include <unordered_map> +#include <string> +#include <mutex> #include "tooltip.h" #include "definition.h" @@ -23,37 +27,33 @@ #include "doxygen.h" #include "config.h" -class TooltipManager::Private +static std::mutex g_tooltipLock; + +struct TooltipData { - public: - Private() : tooltipInfo(10007) {} - QDict<Definition> tooltipInfo; + std::map<std::string,const Definition*> tooltipInfo; + std::set<std::string> tooltipWritten; }; -TooltipManager *TooltipManager::s_theInstance = 0; - -TooltipManager::TooltipManager() +class TooltipManager::Private { - p = new Private; -} + public: + std::unordered_map<int, std::unique_ptr<TooltipData> > tooltips; + std::unique_ptr<TooltipData> &getTooltipData(int id); +}; -TooltipManager::~TooltipManager() +TooltipManager &TooltipManager::instance() { - delete p; + static TooltipManager s_instance; + return s_instance; } -TooltipManager *TooltipManager::instance() +TooltipManager::TooltipManager() : p(std::make_unique<Private>()) { - if (!s_theInstance) - { - s_theInstance = new TooltipManager; - } - return s_theInstance; } -void TooltipManager::clearTooltips() +TooltipManager::~TooltipManager() { - p->tooltipInfo.clear(); } static QCString escapeId(const char *s) @@ -68,10 +68,22 @@ static QCString escapeId(const char *s) return res; } -void TooltipManager::addTooltip(const Definition *d) +std::unique_ptr<TooltipData> &TooltipManager::Private::getTooltipData(int id) { - static bool sourceTooltips = Config_getBool(SOURCE_TOOLTIPS); + std::lock_guard<std::mutex> lock(g_tooltipLock); + auto it = tooltips.insert(std::make_pair(id,std::make_unique<TooltipData>())).first; + return it->second; +} + +void TooltipManager::addTooltip(CodeOutputInterface &ol,const Definition *d) +{ + bool sourceTooltips = Config_getBool(SOURCE_TOOLTIPS); if (!sourceTooltips) return; + int outputId = ol.id(); + if (outputId==0) return; + + auto &ttd = p->getTooltipData(outputId); + QCString id = d->getOutputFileBase(); int i=id.findRev('/'); if (i!=-1) @@ -85,48 +97,57 @@ void TooltipManager::addTooltip(const Definition *d) id+="_"+anc; } id = "a" + id; - if (p->tooltipInfo.find(id)==0) - { - p->tooltipInfo.insert(id,d); - } + ttd->tooltipInfo.insert(std::make_pair(id.str(),d)); + //printf("%p: addTooltip(%s) ol=%d\n",this,id.data(),ol.id()); } void TooltipManager::writeTooltips(CodeOutputInterface &ol) { - QDictIterator<Definition> di(p->tooltipInfo); - Definition *d; - for (di.toFirst();(d=di.current());++di) + int outputId = ol.id(); // get unique identifier per output file + if (outputId==0) return; // not set => no HTML output + auto it = p->tooltips.find(outputId); // see if we have tooltips for this file + if (it!=p->tooltips.end()) { - DocLinkInfo docInfo; - docInfo.name = d->qualifiedName(); - docInfo.ref = d->getReference(); - docInfo.url = d->getOutputFileBase(); - docInfo.anchor = d->anchor(); - SourceLinkInfo defInfo; - if (d->getBodyDef() && d->getStartBodyLine()!=-1) - { - defInfo.file = d->getBodyDef()->name(); - defInfo.line = d->getStartBodyLine(); - defInfo.url = d->getSourceFileBase(); - defInfo.anchor = d->getSourceAnchor(); - } - SourceLinkInfo declInfo; // TODO: fill in... - QCString decl; - if (d->definitionType()==Definition::TypeMember) + auto &ttd = it->second; + for (const auto &kv : ttd->tooltipInfo) { - MemberDef *md = dynamic_cast<MemberDef*>(d); - if (!md->isAnonymous()) + if (ttd->tooltipWritten.find(kv.first)==ttd->tooltipWritten.end()) // only write tooltips once { - decl = md->declaration(); + //printf("%p: writeTooltips(%s) ol=%d\n",this,kv.first.c_str(),ol.id()); + const Definition *d = kv.second; + DocLinkInfo docInfo; + docInfo.name = d->qualifiedName(); + docInfo.ref = d->getReference(); + docInfo.url = d->getOutputFileBase(); + docInfo.anchor = d->anchor(); + SourceLinkInfo defInfo; + if (d->getBodyDef() && d->getStartBodyLine()!=-1) + { + defInfo.file = d->getBodyDef()->name(); + defInfo.line = d->getStartBodyLine(); + defInfo.url = d->getSourceFileBase(); + defInfo.anchor = d->getSourceAnchor(); + } + SourceLinkInfo declInfo; // TODO: fill in... + QCString decl; + if (d->definitionType()==Definition::TypeMember) + { + const MemberDef *md = toMemberDef(d); + if (!md->isAnonymous()) + { + decl = md->declaration(); + } + } + ol.writeTooltip(kv.first.c_str(), // id + docInfo, // symName + decl, // decl + d->briefDescriptionAsTooltip(), // desc + defInfo, + declInfo + ); + ttd->tooltipWritten.insert(kv.first); } } - ol.writeTooltip(di.currentKey(), // id - docInfo, // symName - decl, // decl - d->briefDescriptionAsTooltip(), // desc - defInfo, - declInfo - ); } } diff --git a/src/tooltip.h b/src/tooltip.h index 170ea3c..acdacb4 100644 --- a/src/tooltip.h +++ b/src/tooltip.h @@ -1,10 +1,10 @@ /****************************************************************************** * - * Copyright (C) 1997-2015 by Dimitri van Heesch. + * Copyright (C) 1997-2020 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. * @@ -15,23 +15,28 @@ #ifndef TOOLTIP_H #define TOOLTIP_H +#include <memory> + class Definition; class CodeOutputInterface; +//! Class that manages the tooltips for a source file class TooltipManager { public: - static TooltipManager *instance(); - void clearTooltips(); - void addTooltip(const Definition *d); + static TooltipManager &instance(); + ~TooltipManager(); + + /** add a tooltip for a given symbol definition */ + void addTooltip(CodeOutputInterface &ol,const Definition *d); + + /** write the list of all collected tooltip to the given outputs */ void writeTooltips(CodeOutputInterface &ol); private: - class Private; - Private *p; TooltipManager(); - ~TooltipManager(); - static TooltipManager *s_theInstance; + class Private; + std::unique_ptr<Private> p; }; #endif diff --git a/src/translator_br.h b/src/translator_br.h index 5be0282..29a0e20 100644 --- a/src/translator_br.h +++ b/src/translator_br.h @@ -267,6 +267,10 @@ class TranslatorBrazilian : public TranslatorAdapter_1_8_19 { return "Aqui estão as estruturas de dados, uniões e suas respectivas descrições:"; } + else if (Config_getBool(OPTIMIZE_OUTPUT_SLICE)) + { + return "Aqui estão as classes e suas respectivas descrições:"; + } else { return "Aqui estão as classes, estruturas, uniões e interfaces e suas respectivas descrições:"; diff --git a/src/translator_ca.h b/src/translator_ca.h index a608ff0..7a7e79a 100644 --- a/src/translator_ca.h +++ b/src/translator_ca.h @@ -251,6 +251,10 @@ class TranslatorCatalan : public TranslatorAdapter_1_8_0 { return "Aquestes són les estructures de dades acompanyades amb breus descripcions:"; } + else if (Config_getBool(OPTIMIZE_OUTPUT_SLICE)) + { + return "Aquestes són les classes acompanyades amb breus descripcions:"; + } else { return "Aquestes són les classes, estructures, " diff --git a/src/translator_de.h b/src/translator_de.h index 63b0802..be51653 100644 --- a/src/translator_de.h +++ b/src/translator_de.h @@ -348,13 +348,17 @@ class TranslatorGerman : public TranslatorAdapter_1_8_15 { if (Config_getBool(OPTIMIZE_OUTPUT_FOR_C)) { - return "Hier folgt die Aufzählung aller Datenstrukturen " - "mit einer Kurzbeschreibung:"; + return "Hier folgt die Aufzählung aller Datenstrukturen " + "mit einer Kurzbeschreibung:"; + } + else if (Config_getBool(OPTIMIZE_OUTPUT_SLICE)) + { + return "Hier folgt die Aufzählung aller Klassen mit einer Kurzbeschreibung:"; } else { - return "Hier folgt die Aufzählung aller Klassen, Strukturen, " - "Varianten und Schnittstellen mit einer Kurzbeschreibung:"; + return "Hier folgt die Aufzählung aller Klassen, Strukturen, " + "Varianten und Schnittstellen mit einer Kurzbeschreibung:"; } } diff --git a/src/translator_dk.h b/src/translator_dk.h index 2e9f7d0..fa1db9a 100644 --- a/src/translator_dk.h +++ b/src/translator_dk.h @@ -284,6 +284,8 @@ class TranslatorDanish : public TranslatorAdapter_1_8_0 if (Config_getBool(OPTIMIZE_OUTPUT_FOR_C)) { return "Her er datastrukturerne med korte beskrivelser:"; + } else if (Config_getBool(OPTIMIZE_OUTPUT_SLICE)) { + return "Her er klasserne med korte beskrivelser:"; } else { return "Her er klasserne, datastrukturerne, " "unionerne og grænsefladerne med korte beskrivelser:"; diff --git a/src/translator_eo.h b/src/translator_eo.h index 3ab9f8a..4ae6ee9 100644 --- a/src/translator_eo.h +++ b/src/translator_eo.h @@ -252,6 +252,10 @@ class TranslatorEsperanto : public TranslatorAdapter_1_8_4 { return "Jen datumstrukturoj kun mallongaj priskriboj:"; } + else if (Config_getBool(OPTIMIZE_OUTPUT_SLICE)) + { + return "Jen la klasoj kun mallongaj priskriboj:"; + } else { return "Jen la klasoj, strukturoj, kunigoj kaj interfacoj " diff --git a/src/translator_es.h b/src/translator_es.h index e4b35f3..554c487 100644 --- a/src/translator_es.h +++ b/src/translator_es.h @@ -243,6 +243,10 @@ class TranslatorSpanish : public TranslatorAdapter_1_8_15 { return "Lista de estructuras con una breve descripción:"; } + else if (Config_getBool(OPTIMIZE_OUTPUT_SLICE)) + { + return "Lista de las clases con una breve descripción:"; + } else { return "Lista de las clases, estructuras, " diff --git a/src/translator_fi.h b/src/translator_fi.h index bc6cbd9..dd2d38c 100644 --- a/src/translator_fi.h +++ b/src/translator_fi.h @@ -311,6 +311,11 @@ class TranslatorFinnish : public TranslatorAdapter_1_6_0 { return "Tässä ovat tietueet lyhyen selitteen kanssa:"; // "Here are the data structures with brief descriptions:" } + else if (Config_getBool(OPTIMIZE_OUTPUT_SLICE)) + { + return "Tässä ovat luokat " // "Here are the classes + "lyhyen selitteen kanssa:"; // "with brief descriptions:" + } else { return "Tässä ovat luokat, tietueet ja " // "Here are the classes, structs and " diff --git a/src/translator_gr.h b/src/translator_gr.h index c4af814..a0511b7 100644 --- a/src/translator_gr.h +++ b/src/translator_gr.h @@ -247,6 +247,10 @@ class TranslatorGreek : public TranslatorAdapter_1_8_15 { return "Ακολουθούν οι δομές δεδομένων με σύντομες περιγραφές:"; } + else if (Config_getBool(OPTIMIZE_OUTPUT_SLICE)) + { + return "Ακολουθούν οι κλάσεις με σύντομες περιγραφές:"; + } else { return "Ακολουθούν οι κλάσεις, οι δομές, " diff --git a/src/translator_hu.h b/src/translator_hu.h index f7d9788..ae2e169 100644 --- a/src/translator_hu.h +++ b/src/translator_hu.h @@ -276,6 +276,10 @@ class TranslatorHungarian : public TranslatorAdapter_1_8_15 { return "Az összes adatszerkezet listája rövid leírásokkal:"; } + else if (Config_getBool(OPTIMIZE_OUTPUT_SLICE)) + { + return "Az összes osztály listája rövid leírásokkal:"; + } else { return "Az összes osztály, struktúra, unió és interfész " diff --git a/src/translator_id.h b/src/translator_id.h index 05d36ee..4b5626a 100644 --- a/src/translator_id.h +++ b/src/translator_id.h @@ -234,6 +234,10 @@ class TranslatorIndonesian : public TranslatorAdapter_1_8_0 { return "Berikut ini daftar struktur data, dengan penjelasan singkat:"; } + else if (Config_getBool(OPTIMIZE_OUTPUT_SLICE)) + { + return "Berikut ini daftar kelas, dengan penjelasan singkat:"; + } else { return "Berikut ini daftar kelas, struct, union, dan interface, dengan penjelasan singkat:"; diff --git a/src/translator_it.h b/src/translator_it.h index f7f3534..4b12dae 100644 --- a/src/translator_it.h +++ b/src/translator_it.h @@ -291,6 +291,10 @@ class TranslatorItalian : public TranslatorAdapter_1_8_15 { return "Queste sono le strutture dati con una loro breve descrizione:"; } + else if (Config_getBool(OPTIMIZE_OUTPUT_SLICE)) + { + return "Queste sono le classi con una loro breve descrizione:"; + } else { return "Queste sono le classi, le struct, le union e le interfacce con una loro breve descrizione:"; diff --git a/src/translator_lt.h b/src/translator_lt.h index b491080..1be20d2 100644 --- a/src/translator_lt.h +++ b/src/translator_lt.h @@ -241,6 +241,10 @@ class TranslatorLithuanian : public TranslatorAdapter_1_4_6 { return "Duomenų struktūros su trumpais aprašymais:"; } + else if (Config_getBool(OPTIMIZE_OUTPUT_SLICE)) + { + return "Klasės su trumpais aprašymais:"; + } else { return "Klasės, struktūros, " diff --git a/src/translator_lv.h b/src/translator_lv.h index 36cd78a..8dcc45b 100644 --- a/src/translator_lv.h +++ b/src/translator_lv.h @@ -256,6 +256,10 @@ class TranslatorLatvian : public TranslatorAdapter_1_8_4 { return "Šeit ir visas datu struktūras ar īsu aprakstu:"; } + else if (Config_getBool(OPTIMIZE_OUTPUT_SLICE)) + { + return "Šeit ir visas klases ar īsu aprakstu:"; + } else { return "Šeit ir visas klases, struktūras, " diff --git a/src/translator_mk.h b/src/translator_mk.h index ea5c3c8..97a55dc 100644 --- a/src/translator_mk.h +++ b/src/translator_mk.h @@ -236,6 +236,10 @@ class TranslatorMacedonian : public TranslatorAdapter_1_6_0 { return "Список на структури со кратки описи:"; } + else if (Config_getBool(OPTIMIZE_OUTPUT_SLICE)) + { + return "Список на класи со кратки описи:"; + } else { return "Список на класи, структури, унии и интерфејси " diff --git a/src/translator_nl.h b/src/translator_nl.h index 07e90ae..413d353 100644 --- a/src/translator_nl.h +++ b/src/translator_nl.h @@ -111,8 +111,22 @@ class TranslatorDutch : public Translator return result; } QCString trCompoundListDescription() - { return "Hieronder volgen de klassen, structs en " - "unions met voor elk een korte beschrijving:"; + { + if (Config_getBool(OPTIMIZE_OUTPUT_FOR_C)) + { + return "Hieronder volgen de structs " + "met voor elk een korte beschrijving:"; + } + else if (Config_getBool(OPTIMIZE_OUTPUT_SLICE)) + { + return "Hieronder volgen de klassen " + "met voor elk een korte beschrijving:"; + } + else + { + return "Hieronder volgen de klassen, structs en " + "unions met voor elk een korte beschrijving:"; + } } QCString trCompoundMembersDescription(bool extractAll) { diff --git a/src/translator_no.h b/src/translator_no.h index 1dc331a..dee96d0 100755 --- a/src/translator_no.h +++ b/src/translator_no.h @@ -255,6 +255,10 @@ class TranslatorNorwegian : public TranslatorAdapter_1_4_6 { return "Her er datastrukturene med korte beskrivelser:"; } + else if (Config_getBool(OPTIMIZE_OUTPUT_SLICE)) + { + return "Her er klasser med korte beskrivelser:"; + } else { return "Her er klasser, struct'er, " diff --git a/src/translator_pl.h b/src/translator_pl.h index 096e9b0..86bc72b 100644 --- a/src/translator_pl.h +++ b/src/translator_pl.h @@ -234,6 +234,10 @@ class TranslatorPolish : public TranslatorAdapter_1_8_2 { return "Tutaj znajdują się struktury danych wraz z ich krótkimi opisami:"; } + else if (Config_getBool(OPTIMIZE_OUTPUT_SLICE)) + { + return "Tutaj znajdują się klasy wraz z ich krótkimi opisami:"; + } else { return "Tutaj znajdują się klasy, struktury, " diff --git a/src/translator_pt.h b/src/translator_pt.h index 0185aea..3456aad 100644 --- a/src/translator_pt.h +++ b/src/translator_pt.h @@ -267,6 +267,10 @@ class TranslatorPortuguese : public TranslatorAdapter_1_8_19 { return "Lista das estruturas de dados com uma breve descrição:"; } + else if (Config_getBool(OPTIMIZE_OUTPUT_SLICE)) + { + return "Lista de classes com uma breve descrição:"; + } else { return "Lista de classes, estruturas, uniões e interfaces com uma breve descrição:"; diff --git a/src/translator_ro.h b/src/translator_ro.h index edb82bf..01765a6 100644 --- a/src/translator_ro.h +++ b/src/translator_ro.h @@ -254,6 +254,10 @@ class TranslatorRomanian : public TranslatorAdapter_1_8_15 { return "Lista structurilor de date, cu scurte descrieri:"; } + else if (Config_getBool(OPTIMIZE_OUTPUT_SLICE)) + { + return "Lista claselor, cu scurte descrieri:"; + } else { return "Lista claselor, structurilor, uniunilor şi interfeţelor" diff --git a/src/translator_ru.h b/src/translator_ru.h index aafae90..3e3f7dc 100644 --- a/src/translator_ru.h +++ b/src/translator_ru.h @@ -212,6 +212,10 @@ class TranslatorRussian : public TranslatorAdapter_1_8_15 { return "Структуры данных с их кратким описанием."; } + else if (Config_getBool(OPTIMIZE_OUTPUT_SLICE)) + { + return "Классы с их кратким описанием."; + } else { return "Классы с их кратким описанием."; diff --git a/src/translator_sc.h b/src/translator_sc.h index 5217948..b8b5b42 100644 --- a/src/translator_sc.h +++ b/src/translator_sc.h @@ -254,6 +254,10 @@ class TranslatorSerbianCyrillic : public TranslatorAdapter_1_6_0 { return "Овде су структуре са кратким описима:"; } + else if (Config_getBool(OPTIMIZE_OUTPUT_SLICE)) + { + return "Овде су класе са кратким описима:"; + } else { return "Овде су класе, структуре, " diff --git a/src/translator_sr.h b/src/translator_sr.h index bfd32f6..cb080ea 100644 --- a/src/translator_sr.h +++ b/src/translator_sr.h @@ -235,6 +235,10 @@ class TranslatorSerbian : public TranslatorAdapter_1_6_0 { return "Spisak struktura sa kratkim opisima:"; } + else if (Config_getBool(OPTIMIZE_OUTPUT_SLICE)) + { + return "Spisak klasa sa kratkim opisima:"; + } else { return "Spisak klasa, struktura, unija i interfejsa sa kratkim opisima:"; diff --git a/src/translator_sv.h b/src/translator_sv.h index bc63870..853e265 100644 --- a/src/translator_sv.h +++ b/src/translator_sv.h @@ -353,6 +353,10 @@ class TranslatorSwedish : public Translator { return "Här följer datastrukturerna med korta beskrivningar:"; } + else if (Config_getBool(OPTIMIZE_OUTPUT_SLICE)) + { + return "Här följer klasserna med korta beskrivningar:"; + } else { return "Här följer klasserna, strukterna, unionerna och " diff --git a/src/translator_ua.h b/src/translator_ua.h index 2c5047c..e24136c 100644 --- a/src/translator_ua.h +++ b/src/translator_ua.h @@ -208,6 +208,10 @@ class TranslatorUkrainian : public TranslatorAdapter_1_8_4 { return "Структури даних з коротким описом." ; } + else if (Config_getBool(OPTIMIZE_OUTPUT_SLICE)) + { + return "Класи з коротким описом." ; + } else { return "Класи, структури, об'єднання та інтерфейси з коротким описом." ; diff --git a/src/translator_vi.h b/src/translator_vi.h index 50c0a01..272dedd 100644 --- a/src/translator_vi.h +++ b/src/translator_vi.h @@ -270,6 +270,10 @@ class TranslatorVietnamese : public TranslatorAdapter_1_6_0 { return "Đây là cấu trúc cơ sở dữ liệu với mô tả tóm tắt:"; } + else if (Config_getBool(OPTIMIZE_OUTPUT_SLICE)) + { + return "Đây là các classes với các mô tả tóm tắt:"; + } else { return "Đây là các classes, structs, " diff --git a/src/translator_za.h b/src/translator_za.h index fdf3e6a..8fc847e 100644 --- a/src/translator_za.h +++ b/src/translator_za.h @@ -235,6 +235,10 @@ class TranslatorAfrikaans : public TranslatorAdapter_1_6_0 { return " Data strukture met kort beskrywings:"; } + else if (Config_getBool(OPTIMIZE_OUTPUT_SLICE)) + { + return "Klasse met kort beskrywings:"; + } else { return "Klasse, structs, " diff --git a/src/util.cpp b/src/util.cpp index acc6098..74e5226 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -31,7 +31,6 @@ #include <qfileinfo.h> #include <qdir.h> #include <qdatetime.h> -#include <qcache.h> #include "util.h" #include "message.h" @@ -68,6 +67,7 @@ #include "membergroup.h" #include "dirdef.h" #include "htmlentity.h" +#include "symbolresolver.h" #define ENABLE_TRACINGSUPPORT 0 @@ -96,6 +96,8 @@ #define REL_PATH_TO_ROOT "../../" +static const char *hex = "0123456789ABCDEF"; + //------------------------------------------------------------------------ // TextGeneratorOLImpl implementation //------------------------------------------------------------------------ @@ -430,7 +432,8 @@ QCString resolveTypeDef(const Definition *context,const QCString &qualifiedName, // tmd->getOuterScope()->name().data(), mContext); if (tmd->isTypedef() /*&& tmd->getOuterScope()==resScope*/) { - int dist=isAccessibleFrom(resScope,0,tmd); + SymbolResolver resolver; + int dist=resolver.isAccessibleFrom(resScope,tmd); if (dist!=-1 && (md==0 || dist<minDist)) { md = tmd; @@ -506,1112 +509,12 @@ NamespaceDef *getResolvedNamespace(const char *name) } } -static QDict<MemberDef> g_resolvedTypedefs; -static QDict<Definition> g_visitedNamespaces; - -// forward declaration -static const ClassDef *getResolvedClassRec(const Definition *scope, - const FileDef *fileScope, - const char *n, - const MemberDef **pTypeDef, - QCString *pTemplSpec, - QCString *pResolvedType - ); -int isAccessibleFromWithExpScope(const Definition *scope,const FileDef *fileScope,const Definition *item, - const QCString &explicitScopePart); - -/*! Returns the class representing the value of the typedef represented by \a md - * within file \a fileScope. - * - * Example: typedef A T; will return the class representing A if it is a class. - * - * Example: typedef int T; will return 0, since "int" is not a class. - */ -const ClassDef *newResolveTypedef(const FileDef *fileScope, - const MemberDef *md, - const MemberDef **pMemType, - QCString *pTemplSpec, - QCString *pResolvedType, - const std::unique_ptr<ArgumentList> &actTemplParams) -{ - //printf("newResolveTypedef(md=%p,cachedVal=%p)\n",md,md->getCachedTypedefVal()); - bool isCached = md->isTypedefValCached(); // value already cached - if (isCached) - { - //printf("Already cached %s->%s [%s]\n", - // md->name().data(), - // md->getCachedTypedefVal()?md->getCachedTypedefVal()->name().data():"<none>", - // md->getCachedResolvedTypedef()?md->getCachedResolvedTypedef().data():"<none>"); - - if (pTemplSpec) *pTemplSpec = md->getCachedTypedefTemplSpec(); - if (pResolvedType) *pResolvedType = md->getCachedResolvedTypedef(); - return md->getCachedTypedefVal(); - } - //printf("new typedef\n"); - QCString qname = md->qualifiedName(); - if (g_resolvedTypedefs.find(qname)) return 0; // typedef already done - - g_resolvedTypedefs.insert(qname,md); // put on the trace list - - const ClassDef *typeClass = md->getClassDef(); - QCString type = md->typeString(); // get the "value" of the typedef - if (typeClass && typeClass->isTemplate() && - actTemplParams && !actTemplParams->empty()) - { - type = substituteTemplateArgumentsInString(type, - typeClass->templateArguments(),actTemplParams); - } - QCString typedefValue = type; - int tl=type.length(); - int ip=tl-1; // remove * and & at the end - while (ip>=0 && (type.at(ip)=='*' || type.at(ip)=='&' || type.at(ip)==' ')) - { - ip--; - } - type=type.left(ip+1); - type.stripPrefix("const "); // strip leading "const" - type.stripPrefix("struct "); // strip leading "struct" - type.stripPrefix("union "); // strip leading "union" - int sp=0; - tl=type.length(); // length may have been changed - while (sp<tl && type.at(sp)==' ') sp++; - 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()) - { - result=newResolveTypedef(fileScope,memTypeDef,pMemType,pTemplSpec); - goto done; - } - else if (memTypeDef && memTypeDef->isEnumerate() && pMemType) - { - *pMemType = memTypeDef; - } - - //printf("type=%s result=%p\n",type.data(),result); - if (result==0) - { - // try unspecialized version if type is template - int si=type.findRev("::"); - int i=type.find('<'); - if (si==-1 && i!=-1) // typedef of a template => try the unspecialized version - { - if (pTemplSpec) *pTemplSpec = type.mid(i); - result = getResolvedClassRec(md->getOuterScope(),fileScope, - type.left(i),0,0,pResolvedType); - //printf("result=%p pRresolvedType=%s sp=%d ip=%d tl=%d\n", - // result,pResolvedType?pResolvedType->data():"<none>",sp,ip,tl); - } - else if (si!=-1) // A::B - { - i=type.find('<',si); - if (i==-1) // Something like A<T>::B => lookup A::B - { - i=type.length(); - } - else // Something like A<T>::B<S> => lookup A::B, spec=<S> - { - if (pTemplSpec) *pTemplSpec = type.mid(i); - } - result = getResolvedClassRec(md->getOuterScope(),fileScope, - stripTemplateSpecifiersFromScope(type.left(i),FALSE),0,0, - pResolvedType); - } - - //if (result) ip=si+sp+1; - } - -done: - if (pResolvedType) - { - if (result) - { - *pResolvedType=result->qualifiedName(); - //printf("*pResolvedType=%s\n",pResolvedType->data()); - if (sp>0) pResolvedType->prepend(typedefValue.left(sp)); - if (ip<tl-1) pResolvedType->append(typedefValue.right(tl-ip-1)); - } - else - { - *pResolvedType=typedefValue; - } - } - - // remember computed value for next time - if (result && result->getDefFileName()!="<code>") - // this check is needed to prevent that temporary classes that are - // introduced while parsing code fragments are being cached here. - { - //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>"); - const_cast<MemberDef*>(md)->cacheTypedefVal(result, - pTemplSpec ? *pTemplSpec : QCString(), - pResolvedType ? *pResolvedType : QCString() - ); - } - - g_resolvedTypedefs.remove(qname); // remove from the trace list - - return result; -} - -/*! Substitutes a simple unqualified \a name within \a scope. Returns the - * value of the typedef or \a name if no typedef was found. - */ -static QCString substTypedef(const Definition *scope,const FileDef *fileScope,const QCString &name, - const MemberDef **pTypeDef=0) -{ - QCString result=name; - if (name.isEmpty()) return result; - - // lookup scope fragment in the symbol map - DefinitionIntf *di = Doxygen::symbolMap->find(name); - if (di==0) return result; // no matches - - MemberDef *bestMatch=0; - if (di->definitionType()==DefinitionIntf::TypeSymbolList) // multi symbols - { - // search for the best match - DefinitionListIterator dli(*(DefinitionList*)di); - Definition *d; - int minDistance=10000; // init at "infinite" - for (dli.toFirst();(d=dli.current());++dli) // foreach definition - { - // only look at members - if (d->definitionType()==Definition::TypeMember) - { - // that are also typedefs - MemberDef *md = dynamic_cast<MemberDef *>(d); - if (md->isTypedef()) // d is a typedef - { - // test accessibility of typedef within scope. - int distance = isAccessibleFromWithExpScope(scope,fileScope,d,""); - if (distance!=-1 && distance<minDistance) - // definition is accessible and a better match - { - minDistance=distance; - bestMatch = md; - } - } - } - } - } - else if (di->definitionType()==DefinitionIntf::TypeMember) // single symbol - { - Definition *d = (Definition*)di; - // that are also typedefs - MemberDef *md = dynamic_cast<MemberDef *>(di); - if (md->isTypedef()) // d is a typedef - { - // test accessibility of typedef within scope. - int distance = isAccessibleFromWithExpScope(scope,fileScope,d,""); - if (distance!=-1) // definition is accessible - { - bestMatch = md; - } - } - } - if (bestMatch) - { - result = bestMatch->typeString(); - if (pTypeDef) *pTypeDef=bestMatch; - } - - //printf("substTypedef(%s,%s)=%s\n",scope?scope->name().data():"<global>", - // name.data(),result.data()); - return result; -} - -static const Definition *endOfPathIsUsedClass(const SDict<Definition> *cl,const QCString &localName) -{ - if (cl) - { - SDict<Definition>::Iterator cli(*cl); - Definition *cd; - for (cli.toFirst();(cd=cli.current());++cli) - { - if (cd->localName()==localName) - { - return cd; - } - } - } - return 0; -} - -/*! Starting with scope \a start, the string \a path is interpreted as - * a part of a qualified scope name (e.g. A::B::C), and the scope is - * searched. If found the scope definition is returned, otherwise 0 - * is returned. - */ -static const Definition *followPath(const Definition *start,const FileDef *fileScope,const QCString &path) -{ - int is,ps; - int l; - const Definition *current=start; - ps=0; - //printf("followPath: start='%s' path='%s'\n",start?start->name().data():"<none>",path.data()); - // for each part of the explicit scope - while ((is=getScopeFragment(path,ps,&l))!=-1) - { - // try to resolve the part if it is a typedef - const MemberDef *typeDef=0; - QCString qualScopePart = substTypedef(current,fileScope,path.mid(is,l),&typeDef); - //printf(" qualScopePart=%s\n",qualScopePart.data()); - if (typeDef) - { - const ClassDef *type = newResolveTypedef(fileScope,typeDef); - if (type) - { - //printf("Found type %s\n",type->name().data()); - return type; - } - } - const Definition *next = current->findInnerCompound(qualScopePart); - //printf("++ Looking for %s inside %s result %s\n", - // qualScopePart.data(), - // current->name().data(), - // next?next->name().data():"<null>"); - if (next==0) // failed to follow the path - { - //printf("==> next==0!\n"); - if (current->definitionType()==Definition::TypeNamespace) - { - next = endOfPathIsUsedClass( - (dynamic_cast<const NamespaceDef *>(current))->getUsedClasses(),qualScopePart); - } - else if (current->definitionType()==Definition::TypeFile) - { - next = endOfPathIsUsedClass( - (dynamic_cast<const FileDef *>(current))->getUsedClasses(),qualScopePart); - } - current = next; - if (current==0) break; - } - else // continue to follow scope - { - current = next; - //printf("==> current = %p\n",current); - } - ps=is+l; - } - //printf("followPath(start=%s,path=%s) result=%s\n", - // start->name().data(),path.data(),current?current->name().data():"<null>"); - return current; // path could be followed -} - -bool accessibleViaUsingClass(const SDict<Definition> *cl, - const FileDef *fileScope, - const Definition *item, - const QCString &explicitScopePart="" - ) -{ - //printf("accessibleViaUsingClass(%p)\n",cl); - if (cl) // see if the class was imported via a using statement - { - SDict<Definition>::Iterator cli(*cl); - Definition *ucd; - bool explicitScopePartEmpty = explicitScopePart.isEmpty(); - for (cli.toFirst();(ucd=cli.current());++cli) - { - //printf("Trying via used class %s\n",ucd->name().data()); - const Definition *sc = explicitScopePartEmpty ? ucd : followPath(ucd,fileScope,explicitScopePart); - if (sc && sc==item) return TRUE; - //printf("Try via used class done\n"); - } - } - return FALSE; -} - -bool accessibleViaUsingNamespace(const NamespaceSDict *nl, - const FileDef *fileScope, - const Definition *item, - const QCString &explicitScopePart="") -{ - static QDict<void> visitedDict; - if (nl) // check used namespaces for the class - { - NamespaceSDict::Iterator nli(*nl); - NamespaceDef *und; - int count=0; - for (nli.toFirst();(und=nli.current());++nli,count++) - { - //printf("[Trying via used namespace %s: count=%d/%d\n",und->name().data(), - // count,nl->count()); - const Definition *sc = explicitScopePart.isEmpty() ? und : followPath(und,fileScope,explicitScopePart); - if (sc && item->getOuterScope()==sc) - { - //printf("] found it\n"); - return TRUE; - } - if (item->getLanguage()==SrcLangExt_Cpp) - { - QCString key=und->name(); - if (und->getUsedNamespaces() && visitedDict.find(key)==0) - { - visitedDict.insert(key,(void *)0x08); - - if (accessibleViaUsingNamespace(und->getUsedNamespaces(),fileScope,item,explicitScopePart)) - { - //printf("] found it via recursion\n"); - return TRUE; - } - - visitedDict.remove(key); - } - } - //printf("] Try via used namespace done\n"); - } - } - return FALSE; -} - -const int MAX_STACK_SIZE = 1000; - -/** Helper class representing the stack of items considered while resolving - * the scope. - */ -class AccessStack -{ - public: - AccessStack() : m_index(0) {} - void push(const Definition *scope,const FileDef *fileScope,const Definition *item) - { - if (m_index<MAX_STACK_SIZE) - { - m_elements[m_index].scope = scope; - m_elements[m_index].fileScope = fileScope; - m_elements[m_index].item = item; - m_index++; - } - } - void push(const Definition *scope,const FileDef *fileScope,const Definition *item,const QCString &expScope) - { - if (m_index<MAX_STACK_SIZE) - { - m_elements[m_index].scope = scope; - m_elements[m_index].fileScope = fileScope; - m_elements[m_index].item = item; - m_elements[m_index].expScope = expScope; - m_index++; - } - } - void pop() - { - if (m_index>0) m_index--; - } - bool find(const Definition *scope,const FileDef *fileScope, const Definition *item) - { - int i=0; - for (i=0;i<m_index;i++) - { - AccessElem *e = &m_elements[i]; - if (e->scope==scope && e->fileScope==fileScope && e->item==item) - { - return TRUE; - } - } - return FALSE; - } - bool find(const Definition *scope,const FileDef *fileScope, const Definition *item,const QCString &expScope) - { - int i=0; - for (i=0;i<m_index;i++) - { - AccessElem *e = &m_elements[i]; - if (e->scope==scope && e->fileScope==fileScope && e->item==item && e->expScope==expScope) - { - return TRUE; - } - } - return FALSE; - } - - private: - /** Element in the stack. */ - struct AccessElem - { - const Definition *scope; - const FileDef *fileScope; - const Definition *item; - QCString expScope; - }; - int m_index; - AccessElem m_elements[MAX_STACK_SIZE]; -}; - -/* Returns the "distance" (=number of levels up) from item to scope, or -1 - * if item in not inside scope. - */ -int isAccessibleFrom(const Definition *scope,const FileDef *fileScope,const Definition *item) -{ - //printf("<isAccessibleFrom(scope=%s,item=%s itemScope=%s)\n", - // scope->name().data(),item->name().data(),item->getOuterScope()->name().data()); - - static AccessStack accessStack; - if (accessStack.find(scope,fileScope,item)) - { - return -1; - } - accessStack.push(scope,fileScope,item); - - int result=0; // assume we found it - int i; - - Definition *itemScope=item->getOuterScope(); - bool memberAccessibleFromScope = - (item->definitionType()==Definition::TypeMember && // a member - itemScope && itemScope->definitionType()==Definition::TypeClass && // of a class - scope->definitionType()==Definition::TypeClass && // accessible - (dynamic_cast<const ClassDef*>(scope))->isAccessibleMember(dynamic_cast<const MemberDef *>(item)) // from scope - ); - bool nestedClassInsideBaseClass = - (item->definitionType()==Definition::TypeClass && // a nested class - itemScope && itemScope->definitionType()==Definition::TypeClass && // inside a base - scope->definitionType()==Definition::TypeClass && // class of scope - (dynamic_cast<const ClassDef*>(scope))->isBaseClass(dynamic_cast<ClassDef*>(itemScope),TRUE) - ); - - if (itemScope==scope || memberAccessibleFromScope || nestedClassInsideBaseClass) - { - //printf("> found it\n"); - if (nestedClassInsideBaseClass) result++; // penalty for base class to prevent - // this is preferred over nested class in this class - // see bug 686956 - } - else if (scope==Doxygen::globalScope) - { - if (fileScope) - { - SDict<Definition> *cl = fileScope->getUsedClasses(); - if (accessibleViaUsingClass(cl,fileScope,item)) - { - //printf("> found via used class\n"); - goto done; - } - NamespaceSDict *nl = fileScope->getUsedNamespaces(); - if (accessibleViaUsingNamespace(nl,fileScope,item)) - { - //printf("> found via used namespace\n"); - goto done; - } - } - //printf("> reached global scope\n"); - result=-1; // not found in path to globalScope - } - else // keep searching - { - // check if scope is a namespace, which is using other classes and namespaces - if (scope->definitionType()==Definition::TypeNamespace) - { - const NamespaceDef *nscope = dynamic_cast<const NamespaceDef*>(scope); - //printf(" %s is namespace with %d used classes\n",nscope->name().data(),nscope->getUsedClasses()); - const SDict<Definition> *cl = nscope->getUsedClasses(); - if (accessibleViaUsingClass(cl,fileScope,item)) - { - //printf("> found via used class\n"); - goto done; - } - const NamespaceSDict *nl = nscope->getUsedNamespaces(); - if (accessibleViaUsingNamespace(nl,fileScope,item)) - { - //printf("> found via used namespace\n"); - goto done; - } - } - // repeat for the parent scope - i=isAccessibleFrom(scope->getOuterScope(),fileScope,item); - //printf("> result=%d\n",i); - result= (i==-1) ? -1 : i+2; - } -done: - accessStack.pop(); - //Doxygen::lookupCache.insert(key,new int(result)); - return result; -} - - -/* Returns the "distance" (=number of levels up) from item to scope, or -1 - * if item in not in this scope. The explicitScopePart limits the search - * to scopes that match \a scope (or its parent scope(s)) plus the explicit part. - * Example: - * - * class A { public: class I {}; }; - * class B { public: class J {}; }; - * - * - Looking for item=='J' inside scope=='B' will return 0. - * - Looking for item=='I' inside scope=='B' will return -1 - * (as it is not found in B nor in the global scope). - * - Looking for item=='A::I' inside scope=='B', first the match B::A::I is tried but - * not found and then A::I is searched in the global scope, which matches and - * thus the result is 1. - */ -int isAccessibleFromWithExpScope(const Definition *scope,const FileDef *fileScope, - const Definition *item,const QCString &explicitScopePart) -{ - if (explicitScopePart.isEmpty()) - { - // handle degenerate case where there is no explicit scope. - return isAccessibleFrom(scope,fileScope,item); - } - - static AccessStack accessStack; - if (accessStack.find(scope,fileScope,item,explicitScopePart)) - { - return -1; - } - accessStack.push(scope,fileScope,item,explicitScopePart); - - - //printf(" <isAccessibleFromWithExpScope(%s,%s,%s)\n",scope?scope->name().data():"<global>", - // item?item->name().data():"<none>", - // explicitScopePart.data()); - int result=0; // assume we found it - const Definition *newScope = followPath(scope,fileScope,explicitScopePart); - if (newScope) // explicitScope is inside scope => newScope is the result - { - Definition *itemScope = item->getOuterScope(); - //printf(" scope traversal successful %s<->%s!\n",itemScope->name().data(),newScope->name().data()); - //if (newScope && newScope->definitionType()==Definition::TypeClass) - //{ - // ClassDef *cd = (ClassDef *)newScope; - // printf("---> Class %s: bases=%p\n",cd->name().data(),cd->baseClasses()); - //} - if (itemScope==newScope) // exact match of scopes => distance==0 - { - //printf("> found it\n"); - } - else if (itemScope && newScope && - itemScope->definitionType()==Definition::TypeClass && - newScope->definitionType()==Definition::TypeClass && - (dynamic_cast<const ClassDef*>(newScope))->isBaseClass(dynamic_cast<const ClassDef*>(itemScope),TRUE,0) - ) - { - // inheritance is also ok. Example: looking for B::I, where - // class A { public: class I {} }; - // class B : public A {} - // but looking for B::I, where - // class A { public: class I {} }; - // class B { public: class I {} }; - // will find A::I, so we still prefer a direct match and give this one a distance of 1 - result=1; - - //printf("scope(%s) is base class of newScope(%s)\n", - // scope->name().data(),newScope->name().data()); - } - else - { - int i=-1; - if (newScope->definitionType()==Definition::TypeNamespace) - { - g_visitedNamespaces.insert(newScope->name(),newScope); - // this part deals with the case where item is a class - // A::B::C but is explicit referenced as A::C, where B is imported - // in A via a using directive. - //printf("newScope is a namespace: %s!\n",newScope->name().data()); - const NamespaceDef *nscope = dynamic_cast<const NamespaceDef*>(newScope); - const SDict<Definition> *cl = nscope->getUsedClasses(); - if (cl) - { - SDict<Definition>::Iterator cli(*cl); - const Definition *cd; - for (cli.toFirst();(cd=cli.current());++cli) - { - //printf("Trying for class %s\n",cd->name().data()); - if (cd==item) - { - //printf("> class is used in this scope\n"); - goto done; - } - } - } - const NamespaceSDict *nl = nscope->getUsedNamespaces(); - if (nl) - { - NamespaceSDict::Iterator nli(*nl); - const NamespaceDef *nd; - for (nli.toFirst();(nd=nli.current());++nli) - { - if (g_visitedNamespaces.find(nd->name())==0) - { - //printf("Trying for namespace %s\n",nd->name().data()); - i = isAccessibleFromWithExpScope(scope,fileScope,item,nd->name()); - if (i!=-1) - { - //printf("> found via explicit scope of used namespace\n"); - goto done; - } - } - } - } - } - // repeat for the parent scope - if (scope!=Doxygen::globalScope) - { - i = isAccessibleFromWithExpScope(scope->getOuterScope(),fileScope, - item,explicitScopePart); - } - //printf(" | result=%d\n",i); - result = (i==-1) ? -1 : i+2; - } - } - else // failed to resolve explicitScope - { - //printf(" failed to resolve: scope=%s\n",scope->name().data()); - if (scope->definitionType()==Definition::TypeNamespace) - { - const NamespaceDef *nscope = dynamic_cast<const NamespaceDef*>(scope); - const NamespaceSDict *nl = nscope->getUsedNamespaces(); - if (accessibleViaUsingNamespace(nl,fileScope,item,explicitScopePart)) - { - //printf("> found in used namespace\n"); - goto done; - } - } - if (scope==Doxygen::globalScope) - { - if (fileScope) - { - const NamespaceSDict *nl = fileScope->getUsedNamespaces(); - if (accessibleViaUsingNamespace(nl,fileScope,item,explicitScopePart)) - { - //printf("> found in used namespace\n"); - goto done; - } - } - //printf("> not found\n"); - result=-1; - } - else // continue by looking into the parent scope - { - int i=isAccessibleFromWithExpScope(scope->getOuterScope(),fileScope, - item,explicitScopePart); - //printf("> result=%d\n",i); - result= (i==-1) ? -1 : i+2; - } - } - -done: - //printf(" > result=%d\n",result); - accessStack.pop(); - //Doxygen::lookupCache.insert(key,new int(result)); - return result; -} - int computeQualifiedIndex(const QCString &name) { int i = name.find('<'); return name.findRev("::",i==-1 ? name.length() : i); } -static void getResolvedSymbol(const Definition *scope, - const FileDef *fileScope, - Definition *d, - const QCString &explicitScopePart, - const std::unique_ptr<ArgumentList> &actTemplParams, - int &minDistance, - const ClassDef *&bestMatch, - const MemberDef *&bestTypedef, - QCString &bestTemplSpec, - QCString &bestResolvedType - ) -{ - //printf(" => found type %x name=%s d=%p\n", - // d->definitionType(),d->name().data(),d); - - // only look at classes and members that are enums or typedefs - if (d->definitionType()==Definition::TypeClass || - (d->definitionType()==Definition::TypeMember && - ((dynamic_cast<MemberDef*>(d))->isTypedef() || (dynamic_cast<MemberDef*>(d))->isEnumerate()) - ) - ) - { - g_visitedNamespaces.clear(); - // test accessibility of definition within scope. - int distance = isAccessibleFromWithExpScope(scope,fileScope,d,explicitScopePart); - //printf(" %s; distance %s (%p) is %d\n",scope->name().data(),d->name().data(),d,distance); - if (distance!=-1) // definition is accessible - { - // see if we are dealing with a class or a typedef - if (d->definitionType()==Definition::TypeClass) // d is a class - { - ClassDef *cd = dynamic_cast<ClassDef *>(d); - //printf("cd=%s\n",cd->name().data()); - if (!cd->isTemplateArgument()) // skip classes that - // are only there to - // represent a template - // argument - { - //printf("is not a templ arg\n"); - if (distance<minDistance) // found a definition that is "closer" - { - minDistance=distance; - bestMatch = cd; - bestTypedef = 0; - bestTemplSpec.resize(0); - bestResolvedType = cd->qualifiedName(); - } - else if (distance==minDistance && - fileScope && bestMatch && - fileScope->getUsedNamespaces() && - d->getOuterScope()->definitionType()==Definition::TypeNamespace && - bestMatch->getOuterScope()==Doxygen::globalScope - ) - { - // in case the distance is equal it could be that a class X - // is defined in a namespace and in the global scope. When searched - // in the global scope the distance is 0 in both cases. We have - // to choose one of the definitions: we choose the one in the - // namespace if the fileScope imports namespaces and the definition - // found was in a namespace while the best match so far isn't. - // Just a non-perfect heuristic but it could help in some situations - // (kdecore code is an example). - minDistance=distance; - bestMatch = cd; - bestTypedef = 0; - bestTemplSpec.resize(0); - bestResolvedType = cd->qualifiedName(); - } - } - else - { - //printf(" is a template argument!\n"); - } - } - else if (d->definitionType()==Definition::TypeMember) - { - MemberDef *md = dynamic_cast<MemberDef *>(d); - //printf(" member isTypedef()=%d\n",md->isTypedef()); - if (md->isTypedef()) // d is a typedef - { - QCString args=md->argsString(); - if (args.isEmpty()) // do not expand "typedef t a[4];" - { - //printf(" found typedef!\n"); - - // we found a symbol at this distance, but if it didn't - // resolve to a class, we still have to make sure that - // something at a greater distance does not match, since - // that symbol is hidden by this one. - if (distance<minDistance) - { - QCString spec; - QCString type; - minDistance=distance; - 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()); - bestMatch = cd; - bestTypedef = md; - bestTemplSpec = spec; - bestResolvedType = type; - } - else if (enumType) // type resolves to a enum - { - //printf(" is enum\n"); - bestMatch = 0; - bestTypedef = enumType; - bestTemplSpec = ""; - bestResolvedType = enumType->qualifiedName(); - } - else if (md->isReference()) // external reference - { - bestMatch = 0; - bestTypedef = md; - bestTemplSpec = spec; - bestResolvedType = type; - } - else - { - bestMatch = 0; - bestTypedef = md; - bestTemplSpec.resize(0); - bestResolvedType.resize(0); - //printf(" no match\n"); - } - } - else - { - //printf(" not the best match %d min=%d\n",distance,minDistance); - } - } - else - { - //printf(" not a simple typedef\n") - } - } - else if (md->isEnumerate()) - { - if (distance<minDistance) - { - minDistance=distance; - bestMatch = 0; - bestTypedef = md; - bestTemplSpec = ""; - bestResolvedType = md->qualifiedName(); - } - } - } - } // if definition accessible - else - { - //printf(" Not accessible!\n"); - } - } // if definition is a class or member - //printf(" bestMatch=%p bestResolvedType=%s\n",bestMatch,bestResolvedType.data()); -} - -/* Find the fully qualified class name referred to by the input class - * or typedef name against the input scope. - * Loops through scope and each of its parent scopes looking for a - * match against the input name. Can recursively call itself when - * resolving typedefs. - */ -static const ClassDef *getResolvedClassRec(const Definition *scope, - const FileDef *fileScope, - const char *n, - const MemberDef **pTypeDef, - QCString *pTemplSpec, - QCString *pResolvedType - ) -{ - //printf("[getResolvedClassRec(%s,%s)\n",scope?scope->name().data():"<global>",n); - if (n==0 || *n=='\0') return 0; - QCString name; - QCString explicitScopePart; - QCString strippedTemplateParams; - name=stripTemplateSpecifiersFromScope - (removeRedundantWhiteSpace(n),TRUE, - &strippedTemplateParams); - std::unique_ptr<ArgumentList> actTemplParams; - if (!strippedTemplateParams.isEmpty()) // template part that was stripped - { - actTemplParams = stringToArgumentList(scope->getLanguage(),strippedTemplateParams); - } - - int qualifierIndex = computeQualifiedIndex(name); - //printf("name=%s qualifierIndex=%d\n",name.data(),qualifierIndex); - if (qualifierIndex!=-1) // qualified name - { - // split off the explicit scope part - explicitScopePart=name.left(qualifierIndex); - // todo: improve namespace alias substitution - replaceNamespaceAliases(explicitScopePart,explicitScopePart.length()); - name=name.mid(qualifierIndex+2); - } - - if (name.isEmpty()) - { - //printf("] empty name\n"); - return 0; // empty name - } - - //printf("Looking for symbol %s\n",name.data()); - DefinitionIntf *di = Doxygen::symbolMap->find(name); - // the -g (for C# generics) and -p (for ObjC protocols) are now already - // stripped from the key used in the symbolMap, so that is not needed here. - if (di==0) - { - di = Doxygen::symbolMap->find(name+"-p"); - if (di==0) - { - //printf("no such symbol!\n"); - return 0; - } - } - //printf("found symbol!\n"); - - bool hasUsingStatements = - (fileScope && ((fileScope->getUsedNamespaces() && - fileScope->getUsedNamespaces()->count()>0) || - (fileScope->getUsedClasses() && - fileScope->getUsedClasses()->count()>0)) - ); - //printf("hasUsingStatements=%d\n",hasUsingStatements); - // Since it is often the case that the same name is searched in the same - // scope over an over again (especially for the linked source code generation) - // we use a cache to collect previous results. This is possible since the - // result of a lookup is deterministic. As the key we use the concatenated - // scope, the name to search for and the explicit scope prefix. The speedup - // achieved by this simple cache can be enormous. - int scopeNameLen = scope->name().length()+1; - int nameLen = name.length()+1; - int explicitPartLen = explicitScopePart.length(); - int fileScopeLen = hasUsingStatements ? 1+fileScope->absFilePath().length() : 0; - - // below is a more efficient coding of - // QCString key=scope->name()+"+"+name+"+"+explicitScopePart; - QCString key(scopeNameLen+nameLen+explicitPartLen+fileScopeLen+1); - char *p=key.rawData(); - qstrcpy(p,scope->name()); *(p+scopeNameLen-1)='+'; - p+=scopeNameLen; - qstrcpy(p,name); *(p+nameLen-1)='+'; - p+=nameLen; - qstrcpy(p,explicitScopePart); - p+=explicitPartLen; - - // if a file scope is given and it contains using statements we should - // also use the file part in the key (as a class name can be in - // two different namespaces and a using statement in a file can select - // one of them). - if (hasUsingStatements) - { - // below is a more efficient coding of - // key+="+"+fileScope->name(); - *p++='+'; - qstrcpy(p,fileScope->absFilePath()); - p+=fileScopeLen-1; - } - *p='\0'; - - LookupInfo *pval=Doxygen::lookupCache->find(key); - //printf("Searching for %s result=%p\n",key.data(),pval); - if (pval) - { - //printf("LookupInfo %p %p '%s' %p\n", - // pval->classDef, pval->typeDef, pval->templSpec.data(), - // pval->resolvedType.data()); - if (pTemplSpec) *pTemplSpec=pval->templSpec; - if (pTypeDef) *pTypeDef=pval->typeDef; - if (pResolvedType) *pResolvedType=pval->resolvedType; - //printf("] cachedMatch=%s\n", - // pval->classDef?pval->classDef->name().data():"<none>"); - //if (pTemplSpec) - // printf("templSpec=%s\n",pTemplSpec->data()); - return pval->classDef; - } - else // not found yet; we already add a 0 to avoid the possibility of - // endless recursion. - { - Doxygen::lookupCache->insert(key,new LookupInfo); - } - - const ClassDef *bestMatch=0; - const MemberDef *bestTypedef=0; - QCString bestTemplSpec; - QCString bestResolvedType; - int minDistance=10000; // init at "infinite" - - if (di->definitionType()==DefinitionIntf::TypeSymbolList) // not a unique name - { - //printf(" name is not unique\n"); - DefinitionListIterator dli(*(DefinitionList*)di); - Definition *d; - int count=0; - for (dli.toFirst();(d=dli.current());++dli,++count) // foreach definition - { - getResolvedSymbol(scope,fileScope,d,explicitScopePart,actTemplParams, - minDistance,bestMatch,bestTypedef,bestTemplSpec, - bestResolvedType); - } - } - else // unique name - { - //printf(" name is unique\n"); - Definition *d = (Definition *)di; - getResolvedSymbol(scope,fileScope,d,explicitScopePart,actTemplParams, - minDistance,bestMatch,bestTypedef,bestTemplSpec, - bestResolvedType); - } - - if (pTypeDef) - { - *pTypeDef = bestTypedef; - } - if (pTemplSpec) - { - *pTemplSpec = bestTemplSpec; - } - if (pResolvedType) - { - *pResolvedType = bestResolvedType; - } - //printf("getResolvedClassRec: bestMatch=%p pval->resolvedType=%s\n", - // bestMatch,bestResolvedType.data()); - - pval=Doxygen::lookupCache->find(key); - if (pval) - { - pval->classDef = bestMatch; - pval->typeDef = bestTypedef; - pval->templSpec = bestTemplSpec; - pval->resolvedType = bestResolvedType; - } - else - { - Doxygen::lookupCache->insert(key,new LookupInfo(bestMatch,bestTypedef,bestTemplSpec,bestResolvedType)); - } - //printf("] bestMatch=%s distance=%d\n", - // bestMatch?bestMatch->name().data():"<none>",minDistance); - //if (pTemplSpec) - // printf("templSpec=%s\n",pTemplSpec->data()); - return bestMatch; -} - -/* Find the fully qualified class name referred to by the input class - * or typedef name against the input scope. - * Loops through scope and each of its parent scopes looking for a - * match against the input name. - */ -const ClassDef *getResolvedClass(const Definition *scope, - const FileDef *fileScope, - const char *n, - const MemberDef **pTypeDef, - QCString *pTemplSpec, - bool mayBeUnlinkable, - bool mayBeHidden, - QCString *pResolvedType - ) -{ - static bool optimizeOutputVhdl = Config_getBool(OPTIMIZE_OUTPUT_VHDL); - g_resolvedTypedefs.clear(); - if (scope==0 || - (scope->definitionType()!=Definition::TypeClass && - scope->definitionType()!=Definition::TypeNamespace - ) || - (scope->getLanguage()==SrcLangExt_Java && QCString(n).find("::")!=-1) - ) - { - scope=Doxygen::globalScope; - } - //printf("------------ getResolvedClass(scope=%s,file=%s,name=%s,mayUnlinkable=%d)\n", - // scope?scope->name().data():"<global>", - // fileScope?fileScope->name().data():"<none>", - // n, - // mayBeUnlinkable - // ); - const ClassDef *result; - if (optimizeOutputVhdl) - { - result = getClass(n); - } - else - { - result = getResolvedClassRec(scope,fileScope,n,pTypeDef,pTemplSpec,pResolvedType); - } - if (result==0) // for nested classes imported via tag files, the scope may not - // present, so we check the class name directly as well. - // See also bug701314 - { - result = getClass(n); - } - if (!mayBeUnlinkable && result && !result->isLinkable()) - { - if (!mayBeHidden || !result->isHidden()) - { - //printf("result was %s\n",result?result->name().data():"<none>"); - result=0; // don't link to artificial/hidden classes unless explicitly allowed - } - } - //printf("getResolvedClass(%s,%s)=%s\n",scope?scope->name().data():"<global>", - // n,result?result->name().data():"<none>"); - return result; -} - //------------------------------------------------------------------------- //------------------------------------------------------------------------- //------------------------------------------------------------------------- @@ -1828,7 +731,7 @@ QCString removeRedundantWhiteSpace(const QCString &s) { if (nc != '=') // avoid splitting operator&= - { + { *dst++=' '; } } @@ -2058,8 +961,9 @@ void linkifyText(const TextGeneratorIntf &out, const Definition *scope, const GroupDef *gd=0; //printf("** Match word '%s'\n",matchWord.data()); - const MemberDef *typeDef=0; - cd=getResolvedClass(scope,fileScope,matchWord,&typeDef); + SymbolResolver resolver(fileScope); + cd=resolver.resolveClass(scope,matchWord); + const MemberDef *typeDef = resolver.getTypedef(); if (typeDef) // First look at typedef then class, see bug 584184. { //printf("Found typedef %s\n",typeDef->name().data()); @@ -2263,90 +1167,68 @@ QCString argListToString(const ArgumentList &al,bool useCanonicalType,bool showD if (al.volatileSpecifier()) result+=" volatile"; if (al.refQualifier()==RefQualifierLValue) result+=" &"; else if (al.refQualifier()==RefQualifierRValue) result+=" &&"; - if (!al.trailingReturnType().isEmpty()) result+=" -> "+al.trailingReturnType(); + if (!al.trailingReturnType().isEmpty()) result+=al.trailingReturnType(); if (al.pureSpecifier()) result+=" =0"; return removeRedundantWhiteSpace(result); } -QCString tempArgListToString(const ArgumentList &al,SrcLangExt lang) +QCString tempArgListToString(const ArgumentList &al,SrcLangExt lang,bool includeDefault) { QCString result; if (al.empty()) return result; result="<"; - auto it = al.begin(); - while (it!=al.end()) + bool first=true; + for (const auto &a : al) { - Argument a = *it; - if (!a.name.isEmpty()) // add template argument name + if (a.defval.isEmpty() || includeDefault) { - if (a.type.left(4)=="out") // C# covariance - { - result+="out "; - } - else if (a.type.left(3)=="in") // C# contravariance - { - result+="in "; - } - if (lang==SrcLangExt_Java || lang==SrcLangExt_CSharp) + if (!first) result+=", "; + if (!a.name.isEmpty()) // add template argument name { - result+=a.type+" "; + if (a.type.left(4)=="out") // C# covariance + { + result+="out "; + } + else if (a.type.left(3)=="in") // C# contravariance + { + result+="in "; + } + if (lang==SrcLangExt_Java || lang==SrcLangExt_CSharp) + { + result+=a.type+" "; + } + result+=a.name; } - result+=a.name; - } - else // extract name from type - { - int i=a.type.length()-1; - while (i>=0 && isId(a.type.at(i))) i--; - if (i>0) + else // extract name from type { - result+=a.type.right(a.type.length()-i-1); - if (a.type.find("...")!=-1) + int i=a.type.length()-1; + while (i>=0 && isId(a.type.at(i))) i--; + if (i>0) + { + result+=a.type.right(a.type.length()-i-1); + if (a.type.find("...")!=-1) + { + result+="..."; + } + } + else // nothing found -> take whole name { - result+="..."; + result+=a.type; } } - else // nothing found -> take whole name + if (!a.typeConstraint.isEmpty() && lang==SrcLangExt_Java) { - result+=a.type; + result+=" extends "; // TODO: now Java specific, C# has where... + result+=a.typeConstraint; } + first=false; } - if (!a.typeConstraint.isEmpty() && lang==SrcLangExt_Java) - { - result+=" extends "; // TODO: now Java specific, C# has where... - result+=a.typeConstraint; - } - ++it; - if (it!=al.end()) result+=", "; } result+=">"; return removeRedundantWhiteSpace(result); } -// compute the HTML anchors for a list of members -void setAnchors(MemberList *ml) -{ - //int count=0; - if (ml==0) return; - MemberListIterator mli(*ml); - MemberDef *md; - for (;(md=mli.current());++mli) - { - if (!md->isReference()) - { - //QCString anchor; - //if (groupId==-1) - // anchor.sprintf("%c%d",id,count++); - //else - // anchor.sprintf("%c%d_%d",id,groupId,count++); - //if (cd) anchor.prepend(escapeCharsInString(cd->name(),FALSE)); - md->setAnchor(); - //printf("setAnchors(): Member %s outputFileBase=%s anchor %s result %s\n", - // md->name().data(),md->getOutputFileBase().data(),anchor.data(),md->anchor().data()); - } - } -} - //---------------------------------------------------------------------------- /*! takes the \a buf of the given length \a len and converts CR LF (DOS) @@ -2622,16 +1504,11 @@ int minClassDistance(const ClassDef *cd,const ClassDef *bcd,int level) return -1; } int m=maxInheritanceDepth; - if (cd->baseClasses()) + for (const auto &bcdi : cd->baseClasses()) { - BaseClassListIterator bcli(*cd->baseClasses()); - BaseClassDef *bcdi; - for (;(bcdi=bcli.current());++bcli) - { - int mc=minClassDistance(bcdi->classDef,bcd,level+1); - if (mc<m) m=mc; - if (m<0) break; - } + int mc=minClassDistance(bcdi.classDef,bcd,level+1); + if (mc<m) m=mc; + if (m<0) break; } return m; } @@ -2652,14 +1529,12 @@ Protection classInheritedProtectionLevel(const ClassDef *cd,const ClassDef *bcd, err("Internal inconsistency: found class %s seem to have a recursive " "inheritance relation! Please send a bug report to doxygen@gmail.com\n",cd->name().data()); } - else if (cd->baseClasses()) + else if (prot!=Private) { - BaseClassListIterator bcli(*cd->baseClasses()); - const BaseClassDef *bcdi; - for (;(bcdi=bcli.current()) && prot!=Private;++bcli) + for (const auto &bcdi : cd->baseClasses()) { - Protection baseProt = classInheritedProtectionLevel(bcdi->classDef,bcd,bcdi->prot,level+1); - if (baseProt==Private) prot=Private; + Protection baseProt = classInheritedProtectionLevel(bcdi.classDef,bcd,bcdi.prot,level+1); + if (baseProt==Private) prot=Private; else if (baseProt==Protected) prot=Protected; } } @@ -2668,14 +1543,12 @@ exit: return prot; } -void trimBaseClassScope(BaseClassList *bcl,QCString &s,int level=0) +void trimBaseClassScope(const BaseClassList &bcl,QCString &s,int level=0) { //printf("trimBaseClassScope level=%d '%s'\n",level,s.data()); - BaseClassListIterator bcli(*bcl); - BaseClassDef *bcd; - for (;(bcd=bcli.current());++bcli) + for (const auto &bcd : bcl) { - ClassDef *cd=bcd->classDef; + ClassDef *cd=bcd.classDef; //printf("Trying class %s\n",cd->name().data()); int spos=s.find(cd->name()+"::"); if (spos!=-1) @@ -2685,8 +1558,10 @@ void trimBaseClassScope(BaseClassList *bcl,QCString &s,int level=0) ); } //printf("base class '%s'\n",cd->name().data()); - if (cd->baseClasses()) + if (!cd->baseClasses().empty()) + { trimBaseClassScope(cd->baseClasses(),s,level+1); + } } } @@ -2877,7 +1752,6 @@ static QCString getCanonicalTypeForIdentifier( if (count>10) return word; // oops recursion QCString symName,result,templSpec,tmpName; - //DefinitionList *defList=0; if (tSpec && !tSpec->isEmpty()) templSpec = stripDeclKeywords(getCanonicalTemplateSpec(d,fs,*tSpec)); @@ -2889,21 +1763,26 @@ static QCString getCanonicalTypeForIdentifier( { symName=word; } - //printf("getCanonicalTypeForIdentifier(%s,[%s->%s]) start\n", - // word.data(),tSpec?tSpec->data():"<none>",templSpec.data()); - - const ClassDef *cd = 0; - const MemberDef *mType = 0; - QCString ts; - QCString resolvedType; + //printf("getCanonicalTypeForIdentifier(%s d=%s fs=%s ,[%s->%s]) start\n", + // word.data(), + // d ? d->name().data() : "<null>",fs ? fs->name().data() : "<null>", + // tSpec?tSpec->data():"<none>",templSpec.data()); // lookup class / class template instance - cd = getResolvedClass(d,fs,word+templSpec,&mType,&ts,TRUE,TRUE,&resolvedType); + SymbolResolver resolver(fs); + const ClassDef *cd = resolver.resolveClass(d,word+templSpec,true,true); + const MemberDef *mType = resolver.getTypedef(); + QCString ts = resolver.getTemplateSpec(); + QCString resolvedType = resolver.getResolvedType(); + bool isTemplInst = cd && !templSpec.isEmpty(); if (!cd && !templSpec.isEmpty()) { // class template specialization not known, look up class template - cd = getResolvedClass(d,fs,word,&mType,&ts,TRUE,TRUE,&resolvedType); + cd = resolver.resolveClass(d,word,true,true); + mType = resolver.getTypedef(); + ts = resolver.getTemplateSpec(); + resolvedType = resolver.getResolvedType(); } if (cd && cd->isUsedOnly()) cd=0; // ignore types introduced by usage relations @@ -2983,7 +1862,13 @@ static QCString getCanonicalTypeForIdentifier( //printf("word=%s typeString=%s\n",word.data(),mType->typeString()); if (word!=mType->typeString()) { - result = getCanonicalTypeForIdentifier(d,fs,mType->typeString(),tSpec,count+1); + QCString type = mType->typeString(); + if (type.startsWith("typename ")) + { + type.stripPrefix("typename "); + type = stripTemplateSpecifiersFromScope(type,FALSE); + } + result = getCanonicalTypeForIdentifier(d,fs,type,tSpec,count+1); } else { @@ -3036,7 +1921,6 @@ static QCString extractCanonicalType(const Definition *d,const FileDef *fs,QCStr //printf(" i=%d p=%d\n",i,p); if (i>pp) canType += type.mid(pp,i-pp); - QCString ct = getCanonicalTypeForIdentifier(d,fs,word,&templSpec); // in case the ct is empty it means that "word" represents scope "d" @@ -3107,9 +1991,9 @@ static bool matchArgument2( { //printf(">> match argument: %s::'%s|%s' (%s) <-> %s::'%s|%s' (%s)\n", // srcScope ? srcScope->name().data() : "", - // srcA->type.data(),srcA->name.data(),srcA->canType.data(), + // srcA.type.data(),srcA.name.data(),srcA.canType.data(), // dstScope ? dstScope->name().data() : "", - // dstA->type.data(),dstA->name.data(),dstA->canType.data()); + // dstA.type.data(),dstA.name.data(),dstA.canType.data()); //if (srcA->array!=dstA->array) // nomatch for char[] against char //{ @@ -3392,7 +2276,6 @@ static void findMembersWithSpecificName(const MemberName *mn, bool checkStatics, const FileDef *currentFile, bool checkCV, - const char *forceTagFile, QList<MemberDef> &members) { //printf(" Function with global scope name '%s' args='%s'\n", @@ -3421,7 +2304,7 @@ static void findMembersWithSpecificName(const MemberName *mn, Doxygen::globalScope,fd,argList_p.get(), checkCV); } - if (match && (forceTagFile==0 || md->getReference()==forceTagFile)) + if (match) { //printf("Found match!\n"); members.append(md); @@ -3462,8 +2345,7 @@ bool getDefs(const QCString &scName, const GroupDef *&gd, bool forceEmptyScope, const FileDef *currentFile, - bool checkCV, - const char *forceTagFile + bool checkCV ) { fd=0, md=0, cd=0, nd=0, gd=0; @@ -3526,12 +2408,15 @@ bool getDefs(const QCString &scName, className=mScope; } - const MemberDef *tmd=0; - const ClassDef *fcd=getResolvedClass(Doxygen::globalScope,0,className,&tmd); + SymbolResolver resolver; + const ClassDef *fcd=resolver.resolveClass(Doxygen::globalScope,className); + const MemberDef *tmd=resolver.getTypedef(); + if (fcd==0 && className.find('<')!=-1) // try without template specifiers as well { QCString nameWithoutTemplates = stripTemplateSpecifiersFromScope(className,FALSE); - fcd=getResolvedClass(Doxygen::globalScope,0,nameWithoutTemplates,&tmd); + fcd=resolver.resolveClass(Doxygen::globalScope,nameWithoutTemplates); + tmd=resolver.getTypedef(); } //printf("Trying class scope %s: fcd=%p tmd=%p\n",className.data(),fcd,tmd); // todo: fill in correct fileScope! @@ -3559,7 +2444,7 @@ bool getDefs(const QCString &scName, //printf("match=%d\n",match); if (match) { - ClassDef *mcd=mmd->getClassDef(); + const ClassDef *mcd=mmd->getClassDef(); if (mcd) { int m=minClassDistance(fcd,mcd); @@ -3582,7 +2467,7 @@ bool getDefs(const QCString &scName, MemberDef *mmd = mmd_p.get(); //if (mmd->isLinkable()) //{ - ClassDef *mcd=mmd->getClassDef(); + const ClassDef *mcd=mmd->getClassDef(); //printf(" >Class %s found\n",mcd->name().data()); if (mcd) { @@ -3856,11 +2741,11 @@ bool getDefs(const QCString &scName, { QList<MemberDef> members; // search for matches with strict static checking - findMembersWithSpecificName(mn,args,TRUE,currentFile,checkCV,forceTagFile,members); + findMembersWithSpecificName(mn,args,TRUE,currentFile,checkCV,members); if (members.count()==0) // nothing found { // search again without strict static checking - findMembersWithSpecificName(mn,args,FALSE,currentFile,checkCV,forceTagFile,members); + findMembersWithSpecificName(mn,args,FALSE,currentFile,checkCV,members); } //printf("found %d members\n",members.count()); if (members.count()!=1 && args && !qstrcmp(args,"()")) @@ -4408,7 +3293,7 @@ bool generateLink(OutputDocInterface &od,const char *clName, compound->definitionType()==Definition::TypeGroup /* is group */ ) { - linkText=(dynamic_cast<const GroupDef *>(compound))->groupTitle(); // use group's title as link + linkText=(toGroupDef(compound))->groupTitle(); // use group's title as link } else if (compound->definitionType()==Definition::TypeFile) { @@ -4487,7 +3372,7 @@ struct FindFileCacheElem bool isAmbig; }; -static QCache<FindFileCacheElem> g_findFileDefCache(5000); +static Cache<std::string,FindFileCacheElem> g_findFileDefCache(5000); static std::mutex g_findFileDefMutex; @@ -4504,8 +3389,7 @@ FileDef *findFileDef(const FileNameLinkedMap *fnMap,const char *n,bool &ambig) QCString key = addr; key+=n; - g_findFileDefCache.setAutoDelete(TRUE); - FindFileCacheElem *cachedResult = g_findFileDefCache.find(key); + FindFileCacheElem *cachedResult = g_findFileDefCache.find(key.str()); //printf("key=%s cachedResult=%p\n",key.data(),cachedResult); if (cachedResult) { @@ -4515,7 +3399,7 @@ FileDef *findFileDef(const FileNameLinkedMap *fnMap,const char *n,bool &ambig) } else { - cachedResult = new FindFileCacheElem(0,FALSE); + cachedResult = g_findFileDefCache.insert(key.str(),FindFileCacheElem(0,FALSE)); } QCString name=QDir::cleanDirPath(n).utf8(); @@ -4543,8 +3427,6 @@ FileDef *findFileDef(const FileNameLinkedMap *fnMap,const char *n,bool &ambig) if (path.isEmpty() || isSamePath) { cachedResult->fileDef = fd.get(); - g_findFileDefCache.insert(key,cachedResult); - //printf("=1 ===> add to cache %p\n",fd); return fd.get(); } } @@ -4563,12 +3445,10 @@ FileDef *findFileDef(const FileNameLinkedMap *fnMap,const char *n,bool &ambig) lastMatch=fd; } } - //printf(">1 ===> add to cache %p\n",fd); ambig=(count>1); cachedResult->isAmbig = ambig; cachedResult->fileDef = lastMatch; - g_findFileDefCache.insert(key,cachedResult); return lastMatch; } } @@ -4577,8 +3457,6 @@ FileDef *findFileDef(const FileNameLinkedMap *fnMap,const char *n,bool &ambig) //printf("not found!\n"); } exit: - //printf("0 ===> add to cache %p: %s\n",cachedResult,n); - g_findFileDefCache.insert(key,cachedResult); //delete cachedResult; return 0; } @@ -4654,41 +3532,24 @@ int getPrefixIndex(const QCString &name) //---------------------------------------------------------------------------- -static void initBaseClassHierarchy(BaseClassList *bcl) -{ - if (bcl==0) return; - BaseClassListIterator bcli(*bcl); - for ( ; bcli.current(); ++bcli) - { - ClassDef *cd=bcli.current()->classDef; - if (cd->baseClasses()==0) // no base classes => new root - { - initBaseClassHierarchy(cd->baseClasses()); - } - cd->setVisited(FALSE); - } -} -//---------------------------------------------------------------------------- - bool classHasVisibleChildren(const ClassDef *cd) { - BaseClassList *bcl; + BaseClassList bcl; if (cd->getLanguage()==SrcLangExt_VHDL) // reverse baseClass/subClass relation { - if (cd->baseClasses()==0) return FALSE; + if (cd->baseClasses().empty()) return FALSE; bcl=cd->baseClasses(); } else { - if (cd->subClasses()==0) return FALSE; + if (cd->subClasses().empty()) return FALSE; bcl=cd->subClasses(); } - BaseClassListIterator bcli(*bcl); - for ( ; bcli.current() ; ++bcli) + for (const auto &bcd : bcl) { - if (bcli.current()->classDef->isVisibleInHierarchy()) + if (bcd.classDef->isVisibleInHierarchy()) { return TRUE; } @@ -4696,33 +3557,15 @@ bool classHasVisibleChildren(const ClassDef *cd) return FALSE; } - -//---------------------------------------------------------------------------- - -void initClassHierarchy(ClassSDict *cl) -{ - ClassSDict::Iterator cli(*cl); - ClassDef *cd; - for ( ; (cd=cli.current()); ++cli) - { - cd->setVisited(FALSE); - initBaseClassHierarchy(cd->baseClasses()); - } -} - //---------------------------------------------------------------------------- -bool hasVisibleRoot(const BaseClassList *bcl) +bool hasVisibleRoot(const BaseClassList &bcl) { - if (bcl) + for (const auto &bcd : bcl) { - BaseClassListIterator bcli(*bcl); - for ( ; bcli.current(); ++bcli) - { - const ClassDef *cd=bcli.current()->classDef; - if (cd->isVisibleInHierarchy()) return TRUE; - hasVisibleRoot(cd->baseClasses()); - } + const ClassDef *cd=bcd.classDef; + if (cd->isVisibleInHierarchy()) return TRUE; + hasVisibleRoot(cd->baseClasses()); } return FALSE; } @@ -4732,11 +3575,10 @@ bool hasVisibleRoot(const BaseClassList *bcl) // note that this function is not reentrant due to the use of static growBuf! QCString escapeCharsInString(const char *name,bool allowDots,bool allowUnderscore) { - static bool caseSenseNames = Config_getBool(CASE_SENSE_NAMES); - static bool allowUnicodeNames = Config_getBool(ALLOW_UNICODE_NAMES); - static GrowBuf growBuf; - growBuf.clear(); + bool caseSenseNames = Config_getBool(CASE_SENSE_NAMES); + bool allowUnicodeNames = Config_getBool(ALLOW_UNICODE_NAMES); if (name==0) return ""; + GrowBuf growBuf; signed char c; const signed char *p=(const signed char*)name; while ((c=*p++)!=0) @@ -5229,10 +4071,8 @@ QCString stripScope(const char *name) /*! Converts a string to a HTML id string */ QCString convertToId(const char *s) { - static const char hex[] = "0123456789ABCDEF"; - static GrowBuf growBuf; - growBuf.clear(); if (s==0) return ""; + GrowBuf growBuf; const char *p=s; char c; bool first=TRUE; @@ -5271,9 +4111,8 @@ QCString correctId(QCString s) /*! Converts a string to an XML-encoded string */ QCString convertToXML(const char *s, bool keepEntities) { - static GrowBuf growBuf; - growBuf.clear(); if (s==0) return ""; + GrowBuf growBuf; const char *p=s; char c; while ((c=*p++)) @@ -5323,9 +4162,8 @@ QCString convertToXML(const char *s, bool keepEntities) /*! Converts a string to an DocBook-encoded string */ QCString convertToDocBook(const char *s) { - static GrowBuf growBuf; - growBuf.clear(); if (s==0) return ""; + GrowBuf growBuf; const unsigned char *q; int cnt; const unsigned char *p=(const unsigned char *)s; @@ -5367,13 +4205,18 @@ QCString convertToDocBook(const char *s) break; case '\'': growBuf.addStr("'"); break; case '"': growBuf.addStr("""); break; - case '\007': growBuf.addStr("␇"); break; - case 1: case 2: case 3: case 4: case 5: case 6: case 8: - case 11: case 12: case 13: case 14: case 15: case 16: case 17: case 18: + case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8: + case 11: case 12: case 14: case 15: case 16: case 17: case 18: case 19: case 20: case 21: case 22: case 23: case 24: case 25: case 26: case 27: case 28: case 29: case 30: case 31: - break; // skip invalid XML characters (see http://www.w3.org/TR/2000/REC-xml-20001006#NT-Char) - default: growBuf.addChar(c); break; + growBuf.addStr("$"); + growBuf.addChar(hex[static_cast<uchar>(c)>>4]); + growBuf.addChar(hex[static_cast<uchar>(c)&0xF]); + growBuf.addChar(';'); + break; + default: + growBuf.addChar(c); + break; } } growBuf.addChar(0); @@ -5383,9 +4226,8 @@ QCString convertToDocBook(const char *s) /*! Converts a string to a HTML-encoded string */ QCString convertToHtml(const char *s,bool keepEntities) { - static GrowBuf growBuf; - growBuf.clear(); if (s==0) return ""; + GrowBuf growBuf; growBuf.addStr(getHtmlDirEmbeddingChar(getTextDirByConfig(s))); const char *p=s; char c; @@ -5421,7 +4263,22 @@ QCString convertToHtml(const char *s,bool keepEntities) break; case '\'': growBuf.addStr("'"); break; case '"': growBuf.addStr("""); break; - default: growBuf.addChar(c); break; + default: + { + uchar uc = static_cast<uchar>(c); + if (uc<32 && !isspace(c)) + { + growBuf.addStr("$"); + growBuf.addChar(hex[uc>>4]); + growBuf.addChar(hex[uc&0xF]); + growBuf.addChar(';'); + } + else + { + growBuf.addChar(c); + } + } + break; } } growBuf.addChar(0); @@ -5430,9 +4287,8 @@ QCString convertToHtml(const char *s,bool keepEntities) QCString convertToJSString(const char *s, bool applyTextDir) { - static GrowBuf growBuf; - growBuf.clear(); if (s==0) return ""; + GrowBuf growBuf; if (applyTextDir) growBuf.addStr(getJsDirEmbeddingChar(getTextDirByConfig(s))); const char *p=s; @@ -5452,9 +4308,8 @@ QCString convertToJSString(const char *s, bool applyTextDir) QCString convertToPSString(const char *s) { - static GrowBuf growBuf; - growBuf.clear(); if (s==0) return ""; + GrowBuf growBuf; const char *p=s; char c; while ((c=*p++)) @@ -5474,7 +4329,7 @@ QCString convertToLaTeX(const QCString &s,bool insideTabbing,bool keepSpaces) { QGString result; FTextStream t(&result); - filterLatexString(t,s,insideTabbing,FALSE,FALSE,keepSpaces); + filterLatexString(t,s,insideTabbing,false,false,false,keepSpaces); return result.data(); } @@ -5486,8 +4341,7 @@ QCString convertCharEntitiesToUTF8(const QCString &s) static QRegExp entityPat("&[a-zA-Z]+[0-9]*;"); if (s.length()==0) return result; - static GrowBuf growBuf; - growBuf.clear(); + GrowBuf growBuf; int p,i=0,l; while ((p=entityPat.match(s,i,&l))!=-1) { @@ -5714,7 +4568,7 @@ QCString normalizeNonTemplateArgumentsInString( result += name.mid(p,i-p); QCString n = name.mid(i,l); bool found=FALSE; - for (const Argument formArg : formalArgs) + for (const Argument &formArg : formalArgs) { if (formArg.name == n) { @@ -5725,7 +4579,8 @@ QCString normalizeNonTemplateArgumentsInString( if (!found) { // try to resolve the type - const ClassDef *cd = getResolvedClass(context,0,n); + SymbolResolver resolver; + const ClassDef *cd = resolver.resolveClass(context,n); if (cd) { result+=cd->name(); @@ -6020,7 +4875,9 @@ found: PageDef *addRelatedPage(const char *name,const QCString &ptitle, const QCString &doc, - const char *fileName,int startLine, + const char *fileName, + int docLine, + int startLine, const RefItemVector &sli, GroupDef *gd, const TagInfo *tagInfo, @@ -6033,9 +4890,9 @@ PageDef *addRelatedPage(const char *name,const QCString &ptitle, if ((pd=Doxygen::pageSDict->find(name)) && !tagInfo) { if (!xref) warn(fileName,startLine,"multiple use of page label '%s', (other occurrence: %s, line: %d)", - name,pd->docFile().data(),pd->docLine()); + name,pd->docFile().data(),pd->getStartBodyLine()); // append documentation block to the page. - pd->setDocumentation(doc,fileName,startLine); + pd->setDocumentation(doc,fileName,docLine); //printf("Adding page docs '%s' pi=%p name=%s\n",doc.data(),pd,name); // append (x)refitems to the page. pd->setRefItems(sli); @@ -6049,7 +4906,8 @@ PageDef *addRelatedPage(const char *name,const QCString &ptitle, baseName=baseName.left(baseName.length()-Doxygen::htmlFileExtension.length()); QCString title=ptitle.stripWhiteSpace(); - pd=createPageDef(fileName,startLine,baseName,doc,title); + pd=createPageDef(fileName,docLine,baseName,doc,title); + pd->setBodySegment(startLine,startLine,-1); pd->setRefItems(sli); pd->setLanguage(lang); @@ -6071,24 +4929,29 @@ PageDef *addRelatedPage(const char *name,const QCString &ptitle, // a page name is a label as well! QCString file; + QCString orgFile; + int line = -1; if (gd) { file=gd->getOutputFileBase(); + orgFile=gd->getOutputFileBase(); } else { file=pd->getOutputFileBase(); + orgFile=pd->docFile(); + line = pd->getStartBodyLine(); } const SectionInfo *si = SectionManager::instance().find(pd->name()); if (si) { if (si->lineNr() != -1) { - warn(file,-1,"multiple use of section label '%s', (first occurrence: %s, line %d)",pd->name().data(),si->fileName().data(),si->lineNr()); + warn(orgFile,line,"multiple use of section label '%s', (first occurrence: %s, line %d)",pd->name().data(),si->fileName().data(),si->lineNr()); } else { - warn(file,-1,"multiple use of section label '%s', (first occurrence: %s)",pd->name().data(),si->fileName().data()); + warn(orgFile,line,"multiple use of section label '%s', (first occurrence: %s)",pd->name().data(),si->fileName().data()); } } else @@ -6166,7 +5029,7 @@ void addGroupListToTitle(OutputList &ol,const Definition *d) } void filterLatexString(FTextStream &t,const char *str, - bool insideTabbing,bool insidePre,bool insideItem,bool keepSpaces) + bool insideTabbing,bool insidePre,bool insideItem,bool insideTable,bool keepSpaces) { if (str==0) return; //if (strlen(str)<2) stackTrace(); @@ -6203,12 +5066,13 @@ void filterLatexString(FTextStream &t,const char *str, case '$': t << "\\$"; break; case '"': t << "\"{}"; break; case '-': t << "-\\/"; break; - case '^': (usedTableLevels()>0) ? t << "\\string^" : t << (char)c; break; + case '^': insideTable ? t << "\\string^" : t << (char)c; break; case '~': t << "\\string~"; break; case ' ': if (keepSpaces) t << "~"; else t << ' '; break; default: - t << (char)c; + if (c<32) t << ' '; // non printable control character + else t << (char)c; break; } } @@ -6297,12 +5161,19 @@ void filterLatexString(FTextStream &t,const char *str, default: //if (!insideTabbing && forceBreaks && c!=' ' && *p!=' ') if (!insideTabbing && - ((c>='A' && c<='Z' && pc!=' ' && pc!='\0' && *p) || (c==':' && pc!=':') || (pc=='.' && isId(c))) + ((c>='A' && c<='Z' && pc!=' ' && !(pc>='A' && pc <= 'Z') && pc!='\0' && *p) || (c==':' && pc!=':') || (pc=='.' && isId(c))) ) { t << "\\+"; } - t << (char)c; + if (c<32) + { + t << ' '; // non-printable control character + } + else + { + t << (char)c; + } } } pc = c; @@ -6340,7 +5211,13 @@ QCString latexEscapeLabelName(const char *s) p++; } tmp[i]=0; - filterLatexString(t,tmp,TRUE); + filterLatexString(t,tmp, + true, // insideTabbing + false, // insidePre + false, // insideItem + false, // insideTable + false // keepSpaces + ); break; } } @@ -6379,7 +5256,13 @@ QCString latexEscapeIndexChars(const char *s) p++; } tmp[i]=0; - filterLatexString(t,tmp.data(),TRUE); + filterLatexString(t,tmp.data(), + true, // insideTabbing + false, // insidePre + false, // insideItem + false, // insideTable + false // keepSpaces + ); break; } } @@ -6802,7 +5685,7 @@ QCString getFileNameExtension(QCString fn) //-------------------------------------------------------------------------- -MemberDef *getMemberFromSymbol(const Definition *scope,const FileDef *fileScope, +static MemberDef *getMemberFromSymbol(const Definition *scope,const FileDef *fileScope, const char *n) { if (scope==0 || @@ -6818,8 +5701,8 @@ MemberDef *getMemberFromSymbol(const Definition *scope,const FileDef *fileScope, if (name.isEmpty()) return 0; // no name was given - DefinitionIntf *di = Doxygen::symbolMap->find(name); - if (di==0) + auto range = Doxygen::symbolMap.find(name); + if (range.first==range.second) return 0; // could not find any matching symbols // mostly copied from getResolvedClassRec() @@ -6836,40 +5719,21 @@ MemberDef *getMemberFromSymbol(const Definition *scope,const FileDef *fileScope, int minDistance = 10000; MemberDef *bestMatch = 0; - if (di->definitionType()==DefinitionIntf::TypeSymbolList) + for (auto it=range.first; it!=range.second; ++it) { - //printf("multiple matches!\n"); - // find the closest closest matching definition - DefinitionListIterator dli(*(DefinitionList*)di); - Definition *d; - for (dli.toFirst();(d=dli.current());++dli) + Definition *d = it->second; + if (d->definitionType()==Definition::TypeMember) { - if (d->definitionType()==Definition::TypeMember) + SymbolResolver resolver(fileScope); + int distance = resolver.isAccessibleFromWithExpScope(scope,d,explicitScopePart); + if (distance!=-1 && distance<minDistance) { - g_visitedNamespaces.clear(); - int distance = isAccessibleFromWithExpScope(scope,fileScope,d,explicitScopePart); - if (distance!=-1 && distance<minDistance) - { - minDistance = distance; - bestMatch = dynamic_cast<MemberDef *>(d); - //printf("new best match %s distance=%d\n",bestMatch->qualifiedName().data(),distance); - } + minDistance = distance; + bestMatch = toMemberDef(d); + //printf("new best match %s distance=%d\n",bestMatch->qualifiedName().data(),distance); } } } - else if (di->definitionType()==Definition::TypeMember) - { - //printf("unique match!\n"); - Definition *d = (Definition *)di; - g_visitedNamespaces.clear(); - int distance = isAccessibleFromWithExpScope(scope,fileScope,d,explicitScopePart); - if (distance!=-1 && distance<minDistance) - { - minDistance = distance; - bestMatch = dynamic_cast<MemberDef *>(d); - //printf("new best match %s distance=%d\n",bestMatch->qualifiedName().data(),distance); - } - } return bestMatch; } @@ -7053,8 +5917,7 @@ static QCString replaceAliasArguments(StringUnorderedSet &aliasesProcessed, //printf("----- replaceAliasArguments(val=[%s],args=[%s])\n",aliasValue.data(),argList.data()); // first make a list of arguments from the comma separated argument list - QList<QCString> args; - args.setAutoDelete(TRUE); + std::vector<QCString> args; int i,l=(int)argList.length(); int s=0; for (i=0;i<l;i++) @@ -7062,7 +5925,7 @@ static QCString replaceAliasArguments(StringUnorderedSet &aliasesProcessed, char c = argList.at(i); if (c==',' && (i==0 || argList.at(i-1)!='\\')) { - args.append(new QCString(argList.mid(s,i-s))); + args.push_back(QCString(argList.mid(s,i-s))); s=i+1; // start of next argument } else if (c=='@' || c=='\\') @@ -7071,68 +5934,58 @@ static QCString replaceAliasArguments(StringUnorderedSet &aliasesProcessed, i+=findEndOfCommand(argList.data()+i+1); } } - if (l>s) args.append(new QCString(argList.right(l-s))); + if (l>s) args.push_back(QCString(argList.right(l-s))); //printf("found %d arguments\n",args.count()); // next we look for the positions of the markers and add them to a list - QList<Marker> markerList; - markerList.setAutoDelete(TRUE); + std::vector<Marker> markerList; l = aliasValue.length(); + char pc='\0'; + bool insideMarkerId=false; int markerStart=0; - int markerEnd=0; - for (i=0;i<l;i++) + auto isDigit = [](char c) { return c>='0' && c<='9'; }; + for (i=0;i<=l;i++) { - if (markerStart==0 && aliasValue.at(i)=='\\') // start of a \xx marker + char c = i<l ? aliasValue.at(i) : '\0'; + if (insideMarkerId && !isDigit(c)) // found end of a markerId { - markerStart=i+1; + insideMarkerId = false; + int markerLen = i-markerStart; + markerList.push_back(Marker(markerStart-1, + atoi(aliasValue.mid(markerStart,markerLen)), + markerLen+1)); } - else if (markerStart>0 && aliasValue.at(i)>='0' && aliasValue.at(i)<='9') + if (c=='\\' && (pc=='@' || pc=='\\')) // found escaped backslash { - // read digit that make up the marker number - markerEnd=i+1; + // skip + pc = '\0'; } else { - if (markerStart>0 && markerEnd>markerStart) // end of marker + if (isDigit(c) && pc=='\\') // found start of a markerId { - int markerLen = markerEnd-markerStart; - markerList.append(new Marker(markerStart-1, // include backslash - atoi(aliasValue.mid(markerStart,markerLen)),markerLen+1)); - //printf("found marker at %d with len %d and number %d\n", - // markerStart-1,markerLen+1,atoi(aliasValue.mid(markerStart,markerLen))); + insideMarkerId=true; + markerStart=i; } - markerStart=0; // outside marker - markerEnd=0; + pc = c; } } - if (markerStart>0) - { - markerEnd=l; - } - if (markerStart>0 && markerEnd>markerStart) - { - int markerLen = markerEnd-markerStart; - markerList.append(new Marker(markerStart-1, // include backslash - atoi(aliasValue.mid(markerStart,markerLen)),markerLen+1)); - //printf("found marker at %d with len %d and number %d\n", - // markerStart-1,markerLen+1,atoi(aliasValue.mid(markerStart,markerLen))); - } // then we replace the markers with the corresponding arguments in one pass QCString result; int p=0; - for (i=0;i<(int)markerList.count();i++) + for (i=0;i<(int)markerList.size();i++) { - Marker *m = markerList.at(i); - result+=aliasValue.mid(p,m->pos-p); + const Marker &m = markerList.at(i); + result+=aliasValue.mid(p,m.pos-p); //printf("part before marker %d: '%s'\n",i,aliasValue.mid(p,m->pos-p).data()); - if (m->number>0 && m->number<=(int)args.count()) // valid number + if (m.number>0 && m.number<=(int)args.size()) // valid number { - result+=expandAliasRec(aliasesProcessed,*args.at(m->number-1),TRUE); + result+=expandAliasRec(aliasesProcessed,args.at(m.number-1),TRUE); //printf("marker index=%d pos=%d number=%d size=%d replacement %s\n",i,m->pos,m->number,m->size, // args.at(m->number-1)->data()); } - p=m->pos+m->size; // continue after the marker + p=m.pos+m.size; // continue after the marker } result+=aliasValue.right(l-p); // append remainder //printf("string after replacement of markers: '%s'\n",result.data()); @@ -7649,7 +6502,6 @@ QCString replaceColorMarkers(const char *str) QCString s=str; if (s.isEmpty()) return result; static QRegExp re("##[0-9A-Fa-f][0-9A-Fa-f]"); - static const char hex[] = "0123456789ABCDEF"; static int hue = Config_getInt(HTML_COLORSTYLE_HUE); static int sat = Config_getInt(HTML_COLORSTYLE_SAT); static int gamma = Config_getInt(HTML_COLORSTYLE_GAMMA); @@ -7991,44 +6843,6 @@ bool fileVisibleInIndex(const FileDef *fd,bool &genSourceFile) ); } -void addDocCrossReference(MemberDef *src,MemberDef *dst) -{ - //printf("--> addDocCrossReference src=%s,dst=%s\n",src->name().data(),dst->name().data()); - if (dst->isTypedef() || dst->isEnumerate()) return; // don't add types - if ((dst->hasReferencedByRelation() || dst->hasCallerGraph()) && - src->showInCallGraph() - ) - { - dst->addSourceReferencedBy(src); - MemberDef *mdDef = dst->memberDefinition(); - if (mdDef) - { - mdDef->addSourceReferencedBy(src); - } - MemberDef *mdDecl = dst->memberDeclaration(); - if (mdDecl) - { - mdDecl->addSourceReferencedBy(src); - } - } - if ((src->hasReferencesRelation() || src->hasCallGraph()) && - src->showInCallGraph() - ) - { - src->addSourceReferences(dst); - MemberDef *mdDef = src->memberDefinition(); - if (mdDef) - { - mdDef->addSourceReferences(dst); - } - MemberDef *mdDecl = src->memberDeclaration(); - if (mdDecl) - { - mdDecl->addSourceReferences(dst); - } - } -} - //-------------------------------------------------------------------------------------- /*! @brief Get one unicode character as an unsigned integer from utf-8 string @@ -8097,54 +6911,65 @@ uint getUtf8CodeToUpper( const QCString& s, int idx ) } //-------------------------------------------------------------------------------------- +// +bool namespaceHasNestedNamespace(const NamespaceDef *nd) +{ + NamespaceSDict::Iterator cnli(*nd->getNamespaceSDict()); + const NamespaceDef *cnd; + for (cnli.toFirst();(cnd=cnli.current());++cnli) + { + if (cnd->isLinkableInProject() && !cnd->isAnonymous()) + { + return true; + } + } + return false; +} -bool namespaceHasVisibleChild(const NamespaceDef *nd,bool includeClasses,bool filterClasses,ClassDef::CompoundType ct) +bool namespaceHasNestedClass(const NamespaceDef *nd,bool filterClasses,ClassDef::CompoundType ct) { + //printf(">namespaceHasVisibleChild(%s,includeClasses=%d)\n",nd->name().data(),includeClasses); if (nd->getNamespaceSDict()) { NamespaceSDict::Iterator cnli(*nd->getNamespaceSDict()); const NamespaceDef *cnd; for (cnli.toFirst();(cnd=cnli.current());++cnli) { - if (cnd->isLinkableInProject() && !cnd->isAnonymous()) - { - return TRUE; - } - else if (namespaceHasVisibleChild(cnd,includeClasses,filterClasses,ct)) + if (namespaceHasNestedClass(cnd,filterClasses,ct)) { + //printf("<namespaceHasVisibleChild(%s,includeClasses=%d): case2\n",nd->name().data(),includeClasses); return TRUE; } } } - if (includeClasses) + + const ClassSDict *d = nd->getClassSDict(); + if (filterClasses) { - const ClassSDict *d = nd->getClassSDict(); - if (filterClasses) + if (ct == ClassDef::Interface) { - if (ct == ClassDef::Interface) - { - d = nd->getInterfaceSDict(); - } - else if (ct == ClassDef::Struct) - { - d = nd->getStructSDict(); - } - else if (ct == ClassDef::Exception) - { - d = nd->getExceptionSDict(); - } + d = nd->getInterfaceSDict(); + } + else if (ct == ClassDef::Struct) + { + d = nd->getStructSDict(); } + else if (ct == ClassDef::Exception) + { + d = nd->getExceptionSDict(); + } + } - if (d) + if (d) + { + ClassSDict::Iterator cli(*d); + const ClassDef *cd; + for (;(cd=cli.current());++cli) { - ClassSDict::Iterator cli(*d); - const ClassDef *cd; - for (;(cd=cli.current());++cli) + if (cd->isLinkableInProject() && cd->templateMaster()==0) { - if (cd->isLinkableInProject() && cd->templateMaster()==0) - { - return TRUE; - } + //printf("<namespaceHasVisibleChild(%s,includeClasses=%d): case3\n",nd->name().data(),includeClasses); + return TRUE; } } } @@ -8380,7 +7205,7 @@ bool mainPageHasTitle() return Doxygen::mainPage!=0 && Doxygen::mainPage->hasTitle(); } -QCString getDotImageExtension(void) +QCString getDotImageExtension() { QCString imgExt = Config_getEnum(DOT_IMAGE_FORMAT); int i= imgExt.find(':'); // strip renderer part when using e.g. 'png:cairo:gd' as format @@ -8457,20 +7282,56 @@ void writeLatexSpecialFormulaChars(FTextStream &t) } //------------------------------------------------------ +// simplified way to know if this is fixed form +bool recognizeFixedForm(const char* contents, FortranFormat format) +{ + int column=0; + bool skipLine=FALSE; -static int g_usedTableLevels = 0; + if (format == FortranFormat_Fixed) return TRUE; + if (format == FortranFormat_Free) return FALSE; -void incUsedTableLevels() -{ - g_usedTableLevels++; -} -void decUsedTableLevels() -{ - g_usedTableLevels--; + for(int i=0;;i++) { + column++; + + switch(contents[i]) { + case '\n': + column=0; + skipLine=FALSE; + break; + case ' ': + break; + case '\000': + return FALSE; + case '#': + skipLine=TRUE; + break; + case 'C': + case 'c': + case '*': + if (column==1) return TRUE; + if (skipLine) break; + return FALSE; + case '!': + if (column>1 && column<7) return FALSE; + skipLine=TRUE; + break; + default: + if (skipLine) break; + if (column>=7) return TRUE; + return FALSE; + } + } + return FALSE; } -int usedTableLevels() + +FortranFormat convertFileNameFortranParserCode(QCString fn) { - return g_usedTableLevels; -} + QCString ext = getFileNameExtension(fn); + QCString parserName = Doxygen::parserManager->getParserName(ext.data()); -//------------------------------------------------------ + if (parserName == "fortranfixed") return FortranFormat_Fixed; + else if (parserName == "fortranfree") return FortranFormat_Free; + + return FortranFormat_Unknown; +} @@ -23,6 +23,8 @@ */ #include <memory> +#include <unordered_map> +#include <algorithm> #include <qlist.h> #include <ctype.h> @@ -32,6 +34,7 @@ #include "classdef.h" #include "arguments.h" #include "containers.h" +#include "namespacedef.h" //-------------------------------------------------------------------- @@ -46,7 +49,6 @@ class OutputDocInterface; class MemberDef; class ExampleSDict; class ClassSDict; -class BaseClassList; class GroupDef; class NamespaceSDict; class ClassList; @@ -135,8 +137,6 @@ void linkifyText(const TextGeneratorIntf &ol, int indentLevel=0 ); -void setAnchors(MemberList *ml); - QCString fileToString(const char *name,bool filter=FALSE,bool isSourceCode=FALSE); QCString dateToString(bool); @@ -151,8 +151,7 @@ bool getDefs(const QCString &scopeName, const GroupDef *&gd, bool forceEmptyScope=FALSE, const FileDef *currentFile=0, - bool checkCV=FALSE, - const char *forceTagFile=0 + bool checkCV=FALSE ); QCString getFileFilter(const char* name,bool isSourceCode); @@ -204,17 +203,16 @@ QCString selectBlock(const QCString& s,const QCString &name,bool which); QCString resolveDefines(const char *n); ClassDef *getClass(const char *key); - -const ClassDef *getResolvedClass(const Definition *scope, - const FileDef *fileScope, - const char *key, - const MemberDef **pTypeDef=0, - QCString *pTemplSpec=0, - bool mayBeUnlinkable=FALSE, - bool mayBeHidden=FALSE, - QCString *pResolvedType=0); +inline ClassDefMutable *getClassMutable(const char *key) +{ + return toClassDefMutable(getClass(key)); +} NamespaceDef *getResolvedNamespace(const char *key); +inline NamespaceDefMutable *getResolvedNamespaceMutable(const char *key) +{ + return toNamespaceDefMutable(getResolvedNamespace(key)); +} FileDef *findFileDef(const FileNameLinkedMap *fnMap,const char *n, bool &ambig); @@ -232,7 +230,7 @@ QCString removeRedundantWhiteSpace(const QCString &s); QCString argListToString(const ArgumentList &al,bool useCanonicalType=FALSE,bool showDefVals=TRUE); -QCString tempArgListToString(const ArgumentList &al,SrcLangExt lang); +QCString tempArgListToString(const ArgumentList &al,SrcLangExt lang,bool includeDefaults=true); QCString generateMarker(int id); @@ -257,11 +255,10 @@ QCString removeAnonymousScopes(const QCString &s); QCString replaceAnonymousScopes(const QCString &s,const char *replacement=0); -void initClassHierarchy(ClassSDict *cl); - -bool hasVisibleRoot(const BaseClassList *bcl); +bool hasVisibleRoot(const BaseClassList &bcl); bool classHasVisibleChildren(const ClassDef *cd); -bool namespaceHasVisibleChild(const NamespaceDef *nd,bool includeClasses,bool filterClasses,ClassDef::CompoundType ct); +bool namespaceHasNestedNamespace(const NamespaceDef *nd); +bool namespaceHasNestedClass(const NamespaceDef *nd,bool filterClasses,ClassDef::CompoundType ct); bool classVisibleInIndex(const ClassDef *cd); int minClassDistance(const ClassDef *cd,const ClassDef *bcd,int level=0); @@ -311,8 +308,6 @@ QCString substituteTemplateArgumentsInString( const ArgumentList &formalArgs, const std::unique_ptr<ArgumentList> &actualArgs); -//QList<ArgumentList> *copyArgumentLists(const QList<ArgumentList> *srcLists); - QCString stripTemplateSpecifiersFromScope(const QCString &fullName, bool parentOnly=TRUE, QCString *lastScopeStripped=0); @@ -337,7 +332,9 @@ void addRefItem(const RefItemVector &sli, PageDef *addRelatedPage(const char *name, const QCString &ptitle, const QCString &doc, - const char *fileName,int startLine, + const char *fileName, + int docLine, + int startLine, const RefItemVector &sli = RefItemVector(), GroupDef *gd=0, const TagInfo *tagInfo=0, @@ -351,10 +348,11 @@ QCString unescapeCharsInString(const char *s); void addGroupListToTitle(OutputList &ol,const Definition *d); void filterLatexString(FTextStream &t,const char *str, - bool insideTabbing=FALSE, - bool insidePre=FALSE, - bool insideItem=FALSE, - bool keepSpaces=FALSE); + bool insideTabbing, + bool insidePre, + bool insideItem, + bool insideTable, + bool keepSpaces); QCString latexEscapeLabelName(const char *s); QCString latexEscapeIndexChars(const char *s); @@ -375,11 +373,6 @@ QCString stripExtension(const char *fName); void replaceNamespaceAliases(QCString &scope,int i); -int isAccessibleFrom(const Definition *scope,const FileDef *fileScope,const Definition *item); - -int isAccessibleFromWithExpScope(const Definition *scope,const FileDef *fileScope,const Definition *item, - const QCString &explicitScopePart); - int computeQualifiedIndex(const QCString &name); void addDirPrefix(QCString &fileName); @@ -402,17 +395,8 @@ QCString getFileNameExtension(QCString fn); void initDefaultExtensionMapping(); void addCodeOnlyMappings(); -MemberDef *getMemberFromSymbol(const Definition *scope,const FileDef *fileScope, - const char *n); bool checkIfTypedef(const Definition *scope,const FileDef *fileScope,const char *n); -const ClassDef *newResolveTypedef(const FileDef *fileScope, - const MemberDef *md, - const MemberDef **pMemType=0, - QCString *pTemplSpec=0, - QCString *pResolvedType=0, - const std::unique_ptr<ArgumentList> &actTemplParams=std::unique_ptr<ArgumentList>()); - QCString parseCommentAsText(const Definition *scope,const MemberDef *member,const QCString &doc,const QCString &fileName,int lineNr); QCString transcodeCharacterStringToUTF8(const QCString &input); @@ -423,8 +407,6 @@ QCString extractAliasArgs(const QCString &args,int pos); int countAliasArguments(const QCString argList); -//QCString replaceAliasArguments(const QCString &aliasValue,const QCString &argList); - QCString resolveAliasCmd(const QCString aliasCmd); QCString expandAlias(const QCString &aliasName,const QCString &aliasValue); @@ -474,12 +456,10 @@ bool protectionLevelVisible(Protection prot); QCString stripIndentation(const QCString &s); void stripIndentation(QCString &doc,const int indentationLevel); -QCString getDotImageExtension(void); +QCString getDotImageExtension(); bool fileVisibleInIndex(const FileDef *fd,bool &genSourceFile); -void addDocCrossReference(MemberDef *src,MemberDef *dst); - uint getUtf8Code( const QCString& s, int idx ); uint getUtf8CodeToLower( const QCString& s, int idx ); uint getUtf8CodeToUpper( const QCString& s, int idx ); @@ -498,8 +478,7 @@ bool openOutputFile(const char *outFile,QFile &f); void writeExtraLatexPackages(FTextStream &t); void writeLatexSpecialFormulaChars(FTextStream &t); -int usedTableLevels(); -void incUsedTableLevels(); -void decUsedTableLevels(); +bool recognizeFixedForm(const char* contents, FortranFormat format); +FortranFormat convertFileNameFortranParserCode(QCString fn); #endif diff --git a/src/vhdlcode.h b/src/vhdlcode.h index b79e2ab..48c15bb 100644 --- a/src/vhdlcode.h +++ b/src/vhdlcode.h @@ -1,3 +1,17 @@ +/****************************************************************************** + * + * Copyright (C) 1997-2020 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 VHDLCODE_H #define VHDLCODE_H @@ -12,7 +26,8 @@ void codeFreeVhdlScanner(); class VHDLCodeParser : public CodeParserInterface { public: - virtual ~VHDLCodeParser() {} + VHDLCodeParser(); + virtual ~VHDLCodeParser(); void parseCode(CodeOutputInterface &codeOutIntf, const char *scopeName, const QCString &input, @@ -28,8 +43,10 @@ class VHDLCodeParser : public CodeParserInterface const Definition *searchCtx=0, bool collectXRefs=TRUE ); - void resetCodeParserState() {} + void resetCodeParserState(); + private: + struct Private; + std::unique_ptr<Private> p; }; - -#endif +#endif diff --git a/src/vhdlcode.l b/src/vhdlcode.l index 808e5a2..efb367b 100644 --- a/src/vhdlcode.l +++ b/src/vhdlcode.l @@ -1,10 +1,10 @@ /****************************************************************************** * - * Copyright (C) 1997-2015 by Dimitri van Heesch. + * Copyright (C) 1997-2020 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. * @@ -20,12 +20,17 @@ %option never-interactive %option case-insensitive %option prefix="vhdlcodeYY" +%option reentrant +%option extra-type="struct vhdlcodeYY_state *" %top{ #include <stdint.h> } %{ +#include <unordered_set> +#include <string> + /* * includes */ @@ -55,11 +60,11 @@ #define YY_NO_UNISTD_H 1 #define USE_STATE2STRING 0 - + // Toggle for some debugging info //#define DBG_CTX(x) fprintf x #define DBG_CTX(x) do { } while(0) - + /* ----------------------------------------------------------------- * statics @@ -67,57 +72,70 @@ // ----------------- <vhdl> ---------------------------------- -//static bool isPackBody=FALSE; -//static bool isStartMap; -static bool isFuncProto=FALSE; -static bool isComponent=FALSE; -static bool isPackageBody=FALSE; -static bool isProto = FALSE; -static bool g_startCode = FALSE; -static QCString g_PrevString; -static QCString g_CurrClass; -static QDict<QCString>g_vhdlKeyDict; -static QCString g_tempComp; -static QCString g_PortMapComp; -static MemberDef *g_vhdlMember; -static QCString g_FuncProto; - -//----------------------------------------------------------- - -static CodeOutputInterface * g_code; -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 const Definition *g_searchCtx; - -static bool g_exampleBlock; -static QCString g_exampleName; -static QCString g_exampleFile; - -static QCString g_classScope; - -static bool g_CurrARCH = FALSE; - -static FileDef * g_sourceFileDef; -static Definition * g_currentDefinition; -static MemberDef * g_currentMemberDef; -static bool g_includeCodeFragment; -static const char * g_currentFontClass; - -static bool g_lexInit = FALSE; -static int g_braceCount=0; - - -static void writeFont(const char *s,const char* text); -static void generateMemLink(CodeOutputInterface &ol,QCString &clName,QCString& memberName); -static bool writeColoredWord(QCString& word ); -static void generateClassOrGlobalLink(CodeOutputInterface &ol,const char *clName, bool typeOnly=FALSE, const char *curr_class=0); -static void endFontClass(); -static void startFontClass(const char *s); +struct vhdlcodeYY_state +{ + bool isFuncProto = false; + bool isComponent = false; + bool isPackageBody = false; + bool isProto = false; + bool startCode = false; + QCString prevString; + QCString currClass; + std::unordered_set<std::string> vhdlKeyDict; + QCString tempComp; + QCString PortMapComp; + const MemberDef * vhdlMember = 0; + QCString funcProto; + + CodeOutputInterface * code = 0; + const char * inputString = 0; //!< the code fragment as text + yy_size_t inputPosition = 0; //!< read offset during parsing + int inputLines = 0; //!< number of line in the code fragment + int yyLineNr = 0; //!< current line number + bool needsTermination = false; + const Definition *searchCtx = 0; + + bool exampleBlock = false; + QCString exampleName; + QCString exampleFile; + + bool currArch = false; + + const FileDef * sourceFileDef = 0; + const Definition * currentDefinition = 0; + const MemberDef * currentMemberDef = 0; + bool includeCodeFragment = false; + const char * currentFontClass = 0; + + bool lexInit = false; + int braceCount = 0; +}; + + +static void writeFont(yyscan_t yyscanner,const char *s,const char* text); +static void generateMemLink(yyscan_t yyscanner,CodeOutputInterface &ol,QCString &clName,QCString& memberName); +static bool writeColoredWord(yyscan_t yyscanner,QCString& word ); +static void generateClassOrGlobalLink(yyscan_t yyscanner,CodeOutputInterface &ol,const char *clName, bool typeOnly=false, const char *curr_class=0); +static void setCurrentDoc(yyscan_t yyscanner,const QCString &anchor); +static bool checkVhdlString(yyscan_t yyscanner,QCString &name); +static void addToSearchIndex(yyscan_t yyscanner,const char *text); +static void startCodeLine(yyscan_t yyscanner); +static void endCodeLine(yyscan_t yyscanner); +static void nextCodeLine(yyscan_t yyscanner); +static void writeWord(yyscan_t yyscanner,const char *word,const char* curr_class=0,bool classLink=false); +static void codifyLines(yyscan_t yyscanner,const char *text,const char *cl=0,bool classlink=false,bool comment=false); +static void writeMultiLineCodeLink(yyscan_t yyscanner,CodeOutputInterface &ol, + Definition *d, + const char *text); +static void generateFuncLink(yyscan_t yyscanner,CodeOutputInterface &ol,MemberDef* mdef); +static int countLines(yyscan_t yyscanner); +static void endFontClass(yyscan_t yyscanner); +static void startFontClass(yyscan_t yyscanner,const char *s); +static void appStringLower(QCString& qcs,const char* text); +static void codifyMapLines(yyscan_t yyscanner,const char *text); +static void writeFuncProto(yyscan_t yyscanner); +static void writeProcessProto(yyscan_t yyscanner); +static yy_size_t yyread(yyscan_t yyscanner,char *buf,yy_size_t max_size); #if USE_STATE2STRING static const char *stateToString(int state); @@ -125,24 +143,818 @@ static const char *stateToString(int state); //------------------------------------------------------------------- -static void setCurrentDoc(const QCString &anchor) +#undef YY_INPUT +#define YY_INPUT(buf,result,max_size) result=yyread(yyscanner,buf,max_size); + +%} + + +B [ \t] +BN [ \t\n\r] +STRING ["][^"\n]*["] +NAME [a-z_A-Z][ a-z_A-Z0-9]* +FUNCNAME [a-z_A-Z"][a-z_A-Z0-9+*"/=<>-]* +ID "$"?[a-z_A-Z][a-z_A-Z0-9]* +SPECSIGN [:;, +*&\/=<>'\t]* +DIGITSS [0-9]+|[0-9]+("#")*[0-9_a-fA-F\+\.\-]+("#")* +ALLTYPESMAP {B}*[_a-zA-Z0-9. ]+{BN}* +ALLTYPESMAP1 {BN}*[_a-zA-Z0-9.() ]+{BN}* + +ARCHITECTURE ^{B}*("architecture"){BN}+{FUNCNAME}{BN}+("of"){BN}+{FUNCNAME}{BN}+("is") +PROCESS ({BN}*{FUNCNAME}{BN}*[:]+{BN}*("process"){BN}*[(]*)|[^a-zA-Z]("process "|"process("){BN}*[ (]*|[^a-zA-Z]("process"){BN}+ + +END1 {B}*("end "){BN}+("if"|"case"|"loop"|"generate"|"for") +END2 [^a-zA-Z_]("end"){BN}*[;] +END3 {BN}*[^a-zA-Z]("end"){BN}+{FUNCNAME}{BN}*[;] +END4 {B}*("end"){BN}+"function"{BN}+{FUNCNAME}{BN}*[;] +ENDEFUNC {END3}|{END4}|{END2} + +KEYWORD ("of"|"new"|"event"|"break"|"case"|"end"|"loop"|"else"|"for"|"goto"|"if"|"return"|"generate"|"is"|"while"|"in") +TYPEKW ^{B}*("type"|"subtype"|"constant"|"attribute"|"signal"|"variable","alias","configuration") +FUNC ^{B}*("function"|"procedure"){BN}*{FUNCNAME}{BN}*("(") + +ARITHOP "+"|"-"|"/"|"*"|"%"|"/="|":=" +ASSIGNOP "="|"*="|"/="|"%="|"+="|"-="|"<<="|">>="|"&="|"^="|"|=" +LOGICOP "=="|"!="|">"|"<"|">="|"<="|"&&"|"||"|"!" +BITOP "&"|"|"|"^"|"<<"|">>"|"~" +OPERATOR {ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP} + +PORT {B}*("port"){BN}*("(") +GENERIC {B}*("generic"){BN}*("(") + +BRACEOPEN [(]{1} +BRACECLOSE [)]{1} + +TEXTT {B}*"--"[^\n]* + +MAPCOMPONENT1 ({ALLTYPESMAP}[:]{ALLTYPESMAP}{TEXTT}*{BN}+("port"|"generic"){BN}+("map"){BN}*("("){1}) +MAPCOMPONENT2 {BN}*("port"|"generic"){BN}+("map"){BN}*("("){1} +MAPCOMPONENT3 ({ALLTYPESMAP}[:]{BN}*{ALLTYPESMAP1}{TEXTT}*{BN}+("port"|"generic"){BN}+("map"){BN}*("("){1}) +MAPCOMPONENT4 ({ALLTYPESMAP}[:]{BN}*("entity"|"component"|"configuration"){BN}+{ALLTYPESMAP1}{TEXTT}*{BN}*("port"|"generic"){BN}*("map"){BN}*("("){1}) + +XILINX "INST"|"NET"|"PIN"|"BLKNM"|"BUFG"|"COLLAPSE"|"CPLD"|"COMPGRP"|"CONFIG"|"CONFIG_MODE"|"COOL_CLK"|"DATA_GATE"|"DCI_VALUE"|"DISABLE"|"DRIVE"|"DROP_SPEC"|"ENABLE"|"FAST"|"FEEDBACK"|"FILE"|"FLOAT"|"FROM-THRU-TO"|"FROM-TO"|"HBLKNM"|"HU_SET"|"INREG"|"IOB"|"IOBDELAY"|"IOSTANDARD"|"KEEP"|"KEEPER"|"LOC"|"LOCATE"|"LOCK_PINS"|"MAP"|"MAXDELAY"|"MAXPT"|"MAXSKEW"|"NODELAY"|"NOREDUCE"|"OFFSET"|"OPEN_DRAIN"|"OPT_EFFORT"|"OPTIMIZE"|"PERIOD"|"PIN"|"PRIORITY"|"PROHIBIT"|"PULLDOWN"|"PULLUP"|"PWR_MODE"|"REG"|"RLOC"|"RLOC_ORIGIN"|"RLOC_RANGE"|"SAVE NET"|"FLAG"|"SYSTEM_JITTER"|"TEMPERATURE"|"TIMEGRP"|"TIMESPEC"|"VOLTAGE" + +%option noyywrap +%option nounput + +%x Bases +%x ParseType +%x ParseFuncProto +%x ParseComponent +%x ParsePackage +%x ParseProcessProto +%x ClassName +%x PackageName +%x ClassVar +%x ClassesName +%x Map +%x End +%x Body + +%% + +. { + BEGIN(Bases); + } + +<Map>{BRACEOPEN} { + yyextra->braceCount++; + writeFont(yyscanner,"vhdlchar",yytext); + BEGIN(Map); + } + +<Map>[^()\n,--]* { /* write and link a port map lines */ + QCString tt(yytext); + VhdlDocGen::deleteAllChars(tt,','); + QRegExp r("=>"); + QCStringList ql=QCStringList::split(r,tt); + if (ql.count()>=2) + { + unsigned int index=0; + QCString t1=ql[0]; + char cc=t1.at(index); + while (cc==' ' || cc=='\t') + { + char c2[2]; + c2[0]=cc; + c2[1]=0; + yyextra->code->codify(c2); + index++; + if (index>=t1.size()) break; + cc=t1.at(index); + } + + QCString s1=t1; + s1=s1.stripWhiteSpace(); + + // if (!yyextra->PortMapComp.isEmpty()) + generateMemLink(yyscanner,*yyextra->code,yyextra->PortMapComp,s1); + while (index++<t1.size()) + { + cc=t1.at(index); + if (cc==' ' || cc=='\t') + { + char c2[2]; + c2[0]=cc; + c2[1]=0; + yyextra->code->codify(c2); + } + } + codifyLines(yyscanner,"=>"); + index=0; + QCString s2=ql[1]; + t1=s2; + cc=t1.at(index); + while (cc==' ' || cc=='\t') + { + char c2[2]; + c2[0]=cc; + c2[1]=0; + yyextra->code->codify(c2); + index++; + if (index>=t1.size()) break; + cc=t1.at(index); + } + s2=s2.stripWhiteSpace(); + if (!checkVhdlString(yyscanner,s2)) + { + generateMemLink(yyscanner,*yyextra->code,yyextra->currClass,s2); + } + while (index++<t1.size()) + { + if (t1.at(index)==' ') + { + yyextra->code->codify(" "); + } + } + } + else + { + codifyLines(yyscanner,yytext,yyextra->currClass.data()); + } + BEGIN(Map); + } + +<Map>"\n"|"," { + codifyLines(yyscanner,yytext); + BEGIN(Map); + } + +<Map>{BRACECLOSE} { + yyextra->braceCount--; + writeFont(yyscanner,"vhdlchar",yytext); + if (yyextra->braceCount==0) + { + BEGIN(Bases); + } + } + +<ParseFuncProto>{NAME} { + QCString tmp(yytext); + tmp=tmp.stripWhiteSpace(); + appStringLower(yyextra->prevString,yytext); + yyextra->vhdlKeyDict.insert(yyextra->prevString.str()); + if (!writeColoredWord(yyscanner,tmp)) + { + generateMemLink(yyscanner,*yyextra->code,yyextra->currClass,tmp); + } + BEGIN(Bases); + } + +<ParseType>{STRING} { + QCString qcs(yytext); + VhdlDocGen::deleteAllChars(qcs,'"'); + VhdlDocGen::deleteAllChars(qcs,' '); + if (VhdlDocGen::isNumber(qcs)) + { + writeFont(yyscanner,"vhdllogic",yytext); + } + else + { + writeFont(yyscanner,"keyword",yytext); + } + } + +<ParseType>"\n" { + yyextra->funcProto.append(yytext); + if (yyextra->isProto) + { + codifyLines(yyscanner,yytext); + } + BEGIN(ParseType); + } + + +<ParseType>{TEXTT} { + yyextra->funcProto.append(yytext); + if (yyextra->isProto) + { + writeFont(yyscanner,"keyword",yytext); + } + BEGIN(ParseType); + } + +<ParseType>{ENDEFUNC} { + QRegExp regg("[\\s]"); + QCString tt(yytext); + codifyLines(yyscanner,yytext,yyextra->currClass.data()); + tt=tt.lower(); + VhdlDocGen::deleteAllChars(tt,';'); + tt.stripWhiteSpace(); + QCStringList ql=QCStringList::split(regg,tt); + int index=ql.findIndex(QCString("if"))+1; + index+=ql.findIndex(QCString("case"))+1; + index+=ql.findIndex(QCString("loop"))+1; + index+=ql.findIndex(QCString("generate"))+1; + if (index==0) + { + BEGIN(Bases); + } + else + { + BEGIN(ParseType); + } + } + +<ParseType>{END1} { + codifyLines(yyscanner,yytext,yyextra->currClass.data()); + yyextra->vhdlKeyDict.clear(); + } + +<ParseType>^{B}*("begin "|"begin") { + codifyLines(yyscanner,yytext,yyextra->currClass.data()); + yyextra->isFuncProto=false; + } + +<ParseType>{SPECSIGN} { + yyextra->funcProto.append(yytext); + if (yyextra->isProto) + { + codifyLines(yyscanner,yytext,yyextra->currClass.data()); + } + } + +<ParseType>["_a-zA-Z0-9]* { + QCString val(yytext); + yyextra->funcProto.append(yytext); + appStringLower(yyextra->prevString,yytext); + + if (yyextra->isFuncProto && yyextra->braceCount==0) + { + yyextra->vhdlKeyDict.insert(yyextra->prevString.str()); + } + + if (yyextra->isProto) + { + if (!writeColoredWord(yyscanner,val)) + { + if (!yyextra->isFuncProto && + yyextra->vhdlKeyDict.find(yyextra->prevString.str())==yyextra->vhdlKeyDict.end()) + { + val=val.stripWhiteSpace(); + if (VhdlDocGen::isNumber(val)) + { + startFontClass(yyscanner,"vhdllogic"); + codifyLines(yyscanner,yytext,yyextra->currClass.data()); + endFontClass(yyscanner); + } + else + { + generateMemLink(yyscanner,*yyextra->code,yyextra->currClass,val); + } + } + else + { + codifyLines(yyscanner,yytext,yyextra->currClass.data()); + } + } + } + BEGIN(ParseType); + } + +<ParseType>{BRACEOPEN} { + yyextra->braceCount++; + yyextra->funcProto+='('; + if (yyextra->isProto) + { + writeFont(yyscanner,"vhdlchar",yytext); + } + BEGIN(ParseType); + } + +<ParseType>{BRACECLOSE} { + yyextra->braceCount--; + yyextra->funcProto+=')'; + if (yyextra->isProto) + { + writeFont(yyscanner,"vhdlchar",yytext); + } + if (yyextra->braceCount==0 && !yyextra->isProto)// && !yyextra->isPackageBody) + { + yyextra->isProto=true; + appStringLower(yyextra->prevString,yytext); + writeFuncProto(yyscanner); + BEGIN(Bases); + } + if (yyextra->isPackageBody) + { + BEGIN(ParseType); + } + } + + +<ClassesName>{FUNCNAME} { + appStringLower(yyextra->prevString,yytext); + yyextra->currClass.resize(0); + yyextra->currClass.append(yytext); + yyextra->currClass=yyextra->currClass.stripWhiteSpace(); + + generateClassOrGlobalLink(yyscanner,*yyextra->code,yytext); + BEGIN(Bases); + } + + +<ParseComponent>{BRACEOPEN} { + yyextra->braceCount++; + yyextra->code->codify(yytext); + } + + +<ParseComponent>{BRACECLOSE} { + yyextra->braceCount--; + yyextra->code->codify(yytext); + if (yyextra->braceCount==0 && !yyextra->isComponent) + { + yyextra->tempComp.resize(0); + BEGIN(Bases); + } + else + { + BEGIN(ParseComponent); + } + } + +<ParseComponent>{B}*"-" { + if (strlen(yytext)>=2) // found text ? + { + writeFont(yyscanner,"keyword",yytext); + } + else + { + writeFont(yyscanner,"vhdlchar",yytext); + } + } + +<ParseComponent>{SPECSIGN} { + codifyLines(yyscanner,yytext); + } + + + +<ParseComponent>"\n"|" " { + codifyLines(yyscanner,yytext); + } + +<ParseComponent>{DIGITSS} { + startFontClass(yyscanner,"vhdllogic"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + } + +<ParseComponent>{PORT} { + codifyLines(yyscanner,yytext); + yyextra->braceCount=1; + yyextra->isComponent=false; + } + +<ParseComponent>{GENERIC} { + codifyLines(yyscanner,yytext); + yyextra->braceCount=1; + } + +<ParseComponent>[_a-zA_Z][_a-zA-Z0-9]* { + QCString temp(yytext); + appStringLower(yyextra->prevString,yytext); + if (!checkVhdlString(yyscanner,temp)) + { + if (!writeColoredWord(yyscanner,yyextra->prevString)) + { + generateMemLink(yyscanner,*yyextra->code,yyextra->tempComp,temp); + } + } + } + +<ParseComponent>{STRING} { + QCString temp(yytext); + if (!checkVhdlString(yyscanner,temp)) + { + codifyLines(yyscanner,yytext); + } + } + + +<ParseProcessProto>[^()]* { + yyextra->funcProto.append(yytext); + } + + + +<ParseProcessProto>{BRACEOPEN} { + yyextra->funcProto.append(yytext); + yyextra->braceCount++; + } + +<ParseProcessProto>{BRACECLOSE} { + yyextra->funcProto.append(yytext); + yyextra->braceCount--; + if (yyextra->braceCount==0) + { + writeProcessProto(yyscanner); + BEGIN(Bases); + } + } + +<ParsePackage>[^:;]* { //found package + QCString temp(yytext); + QCStringList strl=QCStringList::split(".",temp); + if (strl.count()>2) + { + QCString s1=strl[0]; + QCString s2=strl[1]; + QCString s3=strl[2]; + s1.append("."); + s3.prepend("."); + codifyLines(yyscanner,s1.data(),yyextra->currClass.data()); + ClassDef *cd=VhdlDocGen::getPackageName(s2); + if (cd) + { + generateClassOrGlobalLink(yyscanner,*yyextra->code,s2.data()); + } + else + { + codifyLines(yyscanner,s2.data()); + } + codifyLines(yyscanner,s3.data()); + } + else + { + writeFont(yyscanner,"keywordflow",yytext); + } + BEGIN(Bases); + } + +<Bases>{MAPCOMPONENT1}|{MAPCOMPONENT2}|{MAPCOMPONENT3}|{MAPCOMPONENT4} { // found port or generic map + QCString tt(yytext); + int j=tt.find('.'); + + if (j>0) + { + QCString left=tt.left(j+1); + codifyLines(yyscanner,left.data()); + tt=tt.right(tt.length()-j-1); + left=VhdlDocGen::getIndexWord(tt.data(),0); + if (!left.isEmpty()) + { + if (left.contains('(')) + { + j=left.find('(',false); + QCString name=left.left(j); + generateClassOrGlobalLink(yyscanner,*yyextra->code,name.data()); + yyextra->PortMapComp=name; + name=tt.right(tt.length()-name.length()); + codifyLines(yyscanner,name.data()); + } + else + { + generateClassOrGlobalLink(yyscanner,*yyextra->code,left.data()); + tt.stripPrefix(left.data()); //=tt.right(tt.length()-left.length()-1); + + yyextra->PortMapComp=left; + codifyLines(yyscanner,tt.data()); + } + } + } + else + { + if (tt.contains(':',false)) + { + codifyMapLines(yyscanner,tt.data()); + } + else + { + codifyLines(yyscanner,tt.data()); + } + } + yyextra->braceCount=1; + BEGIN(Map); + } + +<Bases>^{B}*("component"){BN}+{FUNCNAME} { // found component + appStringLower(yyextra->prevString,yytext); + QCString temp=VhdlDocGen::getIndexWord(yytext,1); + temp=temp.stripWhiteSpace(); + VhdlDocGen::deleteAllChars(temp,'\n'); + yyextra->tempComp=temp; + codifyLines(yyscanner,yytext,temp.data(),true); + yyextra->braceCount=0; + yyextra->isComponent=true; + BEGIN(ParseComponent); + } + + + +<Bases>{ARCHITECTURE} { // found architecture + yyextra->PortMapComp.resize(0); + QCString temp = VhdlDocGen::getIndexWord(yytext,3); + yyextra->currArch = true; + temp+="::"; + temp+=VhdlDocGen::getIndexWord(yytext,1); + yyextra->currClass=temp; + VhdlDocGen::deleteAllChars(temp,'\n'); + codifyLines(yyscanner,yytext,temp.data(),true); + yyextra->isPackageBody=false; + } + + +<Bases>^{B}*("package "){BN}*("body"){BN}*{FUNCNAME} { // found package body + QCString ss(yytext); + QCString temp=VhdlDocGen::getIndexWord(yytext,2); + QCStringList ql=QCStringList::split(temp,ss); + QCString ll=ql[0]; + codifyLines(yyscanner,ll.data(),yyextra->currClass.data()); + temp=temp.stripWhiteSpace(); + temp.prepend("_"); + generateClassOrGlobalLink(yyscanner,*yyextra->code,temp.data()); + yyextra->currClass.resize(0); + yyextra->currClass=temp; + yyextra->isProto=false; + yyextra->isPackageBody=true; + } + +<Bases>{PROCESS} { // found process + yyextra->isFuncProto=true; + yyextra->funcProto.resize(0); + yyextra->funcProto.append(yytext); + yyextra->vhdlKeyDict.clear(); + appStringLower(yyextra->prevString,yytext); + if (yyextra->prevString.contains('(')) + { + yyextra->braceCount=1; + BEGIN(ParseProcessProto); + } + else + { + writeProcessProto(yyscanner); + } + } + +<Bases>("end"){BN}+("process") { // end of process + yyextra->isFuncProto=false; + codifyLines(yyscanner,yytext); + BEGIN(Bases); + } + + +<Bases>^{B}*("begin "|"begin") { + yyextra->isFuncProto=false; + writeFont(yyscanner,"vhdlkeyword",yytext); + } + +<Bases>^{B}*("use"|"library"){BN}+ { //found package or library + writeFont(yyscanner,"vhdlkeyword",yytext); + BEGIN(ParsePackage); + } + + +<Bases>^{B}*("use"){BN}+("configuration")[^\n]* { + codifyLines(yyscanner,yytext); + } + +<Bases>{FUNC} { // found function|procedure + yyextra->vhdlKeyDict.clear(); + yyextra->funcProto.resize(0); + yyextra->isProto=false; + yyextra->funcProto.append(yytext); + yyextra->braceCount=1; + BEGIN(ParseType); + } + +<Bases>^{B}*("entity"|"package"){BN}+ { + appStringLower(yyextra->prevString,yytext); + writeFont(yyscanner,"keywordflow",yytext); + yyextra->isPackageBody=false; + BEGIN(ClassesName); + } + +<Bases>"end"{BN}+"architecture"{BN}+{FUNCNAME} { + codifyLines(yyscanner,yytext,yyextra->currClass.data(),true); + yyextra->currArch = false; + } +<Bases>"end"{BN}+{FUNCNAME} { + if (yyextra->currArch) + { + codifyLines(yyscanner,yytext,yyextra->currClass.data(),true); + yyextra->currArch = false; + } + else + { + REJECT; + } + } +<Bases>"end" { + appStringLower(yyextra->prevString,yytext); + QCString temp(yytext); + temp=temp.stripWhiteSpace(); + + writeColoredWord(yyscanner,temp); + BEGIN(End); + } +<End>{ID} { + appStringLower(yyextra->prevString,yytext); + QCString temp(yytext); + temp=temp.stripWhiteSpace(); + + if (!writeColoredWord(yyscanner,temp)) + { + generateClassOrGlobalLink(yyscanner,*yyextra->code,temp.data()); + } + } +<End>";" { + codifyLines(yyscanner,yytext); + BEGIN(Bases); + } +<Bases>{KEYWORD} { // found keyword + QCString qcs(yytext); + if (!writeColoredWord(yyscanner,qcs)) + { + startFontClass(yyscanner,"vhdlchar"); + yyextra->code->codify(yytext); + endFontClass(yyscanner); + } + } + + +<Bases>{ID} { + appStringLower(yyextra->prevString,yytext); + QCString temp(yytext); + temp=temp.stripWhiteSpace(); + + if (!writeColoredWord(yyscanner,temp)) + { + startFontClass(yyscanner,"vhdlchar"); + generateMemLink(yyscanner,*yyextra->code,yyextra->currClass,temp); + endFontClass(yyscanner); + } + } + +<Bases,ParseComponent>{DIGITSS} { + startFontClass(yyscanner,"vhdllogic"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + } + +<Bases>^{B}*("use"){BN}+("entity"|"component")[^\n]* { + codifyLines(yyscanner,yytext,yyextra->currClass.data(),true); + } + + +<Bases>{TYPEKW} { + codifyLines(yyscanner,yytext); + if (yyextra->isFuncProto) + { + BEGIN(ParseFuncProto); + } + else + { + BEGIN(Bases); + } + } + +<Bases>{OPERATOR} { + startFontClass(yyscanner,"vhdlchar"); + yyextra->code->codify(yytext); + endFontClass(yyscanner); + } + +<Bases>","|"."|":"|"'"|"("|")" { + startFontClass(yyscanner,"vhdlchar"); + yyextra->code->codify(yytext); + endFontClass(yyscanner); + } + +<Bases>{STRING} { + QCString qcs(yytext); + VhdlDocGen::deleteAllChars(qcs,'"'); + VhdlDocGen::deleteAllChars(qcs,' '); + + if (VhdlDocGen::isNumber(qcs)) + { + writeFont(yyscanner,"vhdllogic",yytext); + } + else + { + writeFont(yyscanner,"keyword",yytext); + } + } + +<Bases>{B}*"#"[^\n]* { + writeFont(yyscanner,"keyword",yytext); + } + +<Bases>^{B}*{XILINX}/[^a-zA-Z0-9_] { + writeWord(yyscanner,yytext); + //codifyLines(yyscanner,yytext,yyextra->currClass.data(),true); + } + +<Bases>^{B}*"set_"[^\n]* { + writeWord(yyscanner,yytext); + } + +<*>\n { + codifyLines(yyscanner,yytext); + BEGIN(Bases); + } + +<*>[\x80-\xFF]* { // keep utf8 characters together... + yyextra->code->codify(yytext); + } +<*>. { + yyextra->code->codify(yytext); + } + +<*>\n{TEXTT} { // found normal or special comment on its own line + QCString text(yytext); + int i=text.find("--"); + if (text.mid(i,3)=="--!") // && // hide special comment + { + if (!Config_getBool(STRIP_CODE_COMMENTS)) + { + codifyLines(yyscanner,text,0,false,true); + } + else yyextra->yyLineNr++; // skip complete line, but count line + } + else // normal comment + { + codifyLines(yyscanner,text,0,false,true); + } + } +<*>{TEXTT} { // found normal or special comment after something + QCString text(yytext); + int i=text.find("--"); + if (text.mid(i,3)=="--!") + { + // hide special comment + if (!Config_getBool(STRIP_CODE_COMMENTS)) + { + codifyLines(yyscanner,text,0,false,true); + } + } + else // normal comment + { + codifyLines(yyscanner,text,0,false,true); + } + } + +%% + +/*@ ---------------------------------------------------------------------------- + */ + +static yy_size_t yyread(yyscan_t yyscanner,char *buf,yy_size_t max_size) { + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + yy_size_t inputPosition = yyextra->inputPosition; + const char *s = yyextra->inputString + inputPosition; + yy_size_t c=0; + while( c < max_size && *s) + { + *buf++ = *s++; + c++; + } + yyextra->inputPosition += c; + return c; +} + +static void setCurrentDoc(yyscan_t yyscanner,const QCString &anchor) +{ + 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); + yyextra->code->setCurrentDoc(yyextra->searchCtx,yyextra->searchCtx->anchor(),false); } else { - Doxygen::searchIndex->setCurrentDoc(g_sourceFileDef,anchor,TRUE); + yyextra->code->setCurrentDoc(yyextra->sourceFileDef,anchor,true); } } } -static bool checkVhdlString(QCString &name) +static bool checkVhdlString(yyscan_t yyscanner,QCString &name) { - if (name.isEmpty()) return FALSE; + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + if (name.isEmpty()) return false; static QRegExp regg("[\\s\"]"); int len=name.length(); @@ -151,121 +963,123 @@ static bool checkVhdlString(QCString &name) QCStringList qrl=QCStringList::split(regg,name); if (VhdlDocGen::isNumber(qrl[0])) { - g_code->codify("\""); - startFontClass("vhdllogic"); + yyextra->code->codify("\""); + startFontClass(yyscanner,"vhdllogic"); QCString mid=name.mid(1,len-2); //" 1223 " - g_code->codify(mid.data()); - endFontClass(); - g_code->codify("\""); + yyextra->code->codify(mid.data()); + endFontClass(yyscanner); + yyextra->code->codify("\""); } else { - startFontClass("keyword"); - g_code->codify(name.data()); - endFontClass(); + startFontClass(yyscanner,"keyword"); + yyextra->code->codify(name.data()); + endFontClass(yyscanner); } - return TRUE; + return true; } if (VhdlDocGen::isNumber(name)) { - startFontClass("vhdllogic"); - g_code->codify(name.data()); - endFontClass(); - return TRUE; + startFontClass(yyscanner,"vhdllogic"); + yyextra->code->codify(name.data()); + endFontClass(yyscanner); + return true; } - return FALSE; + return false; } -static void addToSearchIndex(const char *text) +static void addToSearchIndex(yyscan_t yyscanner,const char *text) { + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; if (Doxygen::searchIndex) { - Doxygen::searchIndex->addWord(text,FALSE); + yyextra->code->addWord(text,false); } } -/*! start a new line of code, inserting a line number if g_sourceFileDef - * is TRUE. If a definition starts at the current line, then the line +/*! 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_currentFontClass) { g_code->endFontClass(); } - if (g_sourceFileDef) + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + //if (yyextra->currentFontClass) { yyextra->code->endFontClass(); } + if (yyextra->sourceFileDef) { //QCString lineNumber,lineAnchor; - //lineNumber.sprintf("%05d",g_yyLineNr); - //lineAnchor.sprintf("l%05d",g_yyLineNr); - // if ((g_yyLineNr % 500) == 0) - // fprintf(stderr,"\n starting Line %d:",g_yyLineNr); - Definition *d = g_sourceFileDef->getSourceDefinition(g_yyLineNr); - //printf("startCodeLine %d d=%s\n", g_yyLineNr,d ? d->name().data() : "<null>"); - if (!g_includeCodeFragment && d) + //lineNumber.sprintf("%05d",yyextra->yyLineNr); + //lineAnchor.sprintf("l%05d",yyextra->yyLineNr); + // if ((yyextra->yyLineNr % 500) == 0) + // fprintf(stderr,"\n starting Line %d:",yyextra->yyLineNr); + Definition *d = yyextra->sourceFileDef->getSourceDefinition(yyextra->yyLineNr); + //printf("startCodeLine %d d=%s\n", yyextra->yyLineNr,d ? d->name().data() : "<null>"); + if (!yyextra->includeCodeFragment && d) { - g_currentDefinition = d; - g_currentMemberDef = g_sourceFileDef->getSourceMember(g_yyLineNr); - if (!g_tempComp.isEmpty() && g_currentMemberDef ) + yyextra->currentDefinition = d; + yyextra->currentMemberDef = yyextra->sourceFileDef->getSourceMember(yyextra->yyLineNr); + if (!yyextra->tempComp.isEmpty() && yyextra->currentMemberDef ) { - //ClassDef *cf=VhdlDocGen::getClass(g_tempComp.data()); - QCString nn=g_currentMemberDef->name(); - MemberDef* mdeff=VhdlDocGen::findMember(g_tempComp,nn); + //ClassDef *cf=VhdlDocGen::getClass(yyextra->tempComp.data()); + QCString nn=yyextra->currentMemberDef->name(); + MemberDef* mdeff=VhdlDocGen::findMember(yyextra->tempComp,nn); if (mdeff) { - g_currentMemberDef=mdeff; + yyextra->currentMemberDef=mdeff; } } - g_parmType.resize(0); - g_parmName.resize(0); 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(yyscanner,lineAnchor); } else if (d->isLinkableInProject()) { - g_code->writeLineNumber(d->getReference(), + yyextra->code->writeLineNumber(d->getReference(), d->getOutputFileBase(), - 0,g_yyLineNr); - setCurrentDoc(lineAnchor); + 0,yyextra->yyLineNr); + setCurrentDoc(yyscanner,lineAnchor); } } else { - g_code->writeLineNumber(0,0,0,g_yyLineNr); + yyextra->code->writeLineNumber(0,0,0,yyextra->yyLineNr); } } - g_code->startCodeLine(g_sourceFileDef); - g_startCode=TRUE; - if (g_currentFontClass) + yyextra->code->startCodeLine(yyextra->sourceFileDef); + yyextra->startCode=true; + if (yyextra->currentFontClass) { - g_code->startFontClass(g_currentFontClass); + yyextra->code->startFontClass(yyextra->currentFontClass); } } -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) { - if (g_startCode) + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + if (yyextra->startCode) { - endCodeLine(); // </div> + endCodeLine(yyscanner); // </div> } - const char *fc = g_currentFontClass; - if (g_yyLineNr<g_inputLines) + const char *fc = yyextra->currentFontClass; + if (yyextra->yyLineNr<yyextra->inputLines) { - g_currentFontClass = fc; - startCodeLine(); //<div> + yyextra->currentFontClass = fc; + startCodeLine(yyscanner); //<div> } } @@ -274,10 +1088,11 @@ static void nextCodeLine() * and will be linked. */ -static void writeWord(const char *word,const char* curr_class=0,bool classLink=FALSE) +static void writeWord(yyscan_t yyscanner,const char *word,const char* curr_class,bool classLink) { - bool found=FALSE; - QCString temp; + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + bool found=false; + QCString temp; QCString tclass(curr_class); QCString ttt(word); if (ttt.isEmpty()) return; @@ -288,69 +1103,71 @@ static void writeWord(const char *word,const char* curr_class=0,bool classLink=F { if (found) { - if (!writeColoredWord(temp)) // is it a keyword ? + if (!writeColoredWord(yyscanner,temp)) // is it a keyword ? { //if (VhdlDocGen::findKeyWord(temp)) - // writeFont("vhdlkeyword",temp.data()); - //printf("writeWord: %s\n",temp.data()); + // writeFont(yyscanner,"vhdlkeyword",temp.data()); + //printf("writeWord: %s\n",temp.data()); if (!tclass.isEmpty()) { if (!classLink) - { - generateMemLink(*g_code,tclass,temp); - } + { + generateMemLink(yyscanner,*yyextra->code,tclass,temp); + } else { - generateClassOrGlobalLink(*g_code,temp,FALSE,curr_class); + generateClassOrGlobalLink(yyscanner,*yyextra->code,temp,false,curr_class); + } + } + else + { + if (!checkVhdlString(yyscanner,temp)) + { + yyextra->code->codify(temp.data()); } } - else - { - if (!checkVhdlString(temp)) - g_code->codify(temp.data()); - } } temp.resize(0); - found=FALSE; + found=false; } char cc[2]; cc[0]=c; cc[1]=0; - g_code->codify(cc); + yyextra->code->codify(cc); } else { - found=TRUE; + found=true; temp+=c; } } // for if (!temp.isEmpty()) { - if (!writeColoredWord(temp)) + if (!writeColoredWord(yyscanner,temp)) { if (!tclass.isEmpty()) { if (!classLink) { - generateMemLink(*g_code,tclass,temp); // generateMemLink(*g_code,g_CurrClass,left); + generateMemLink(yyscanner,*yyextra->code,tclass,temp); // generateMemLink(yyscanner,*yyextra->code,yyextra->currClass,left); } else { - generateClassOrGlobalLink(*g_code,temp,FALSE,curr_class); + generateClassOrGlobalLink(yyscanner,*yyextra->code,temp,false,curr_class); } } - else + else { QCString qc(temp.data()); if (VhdlDocGen::isNumber(qc)){ - startFontClass("vhdllogic"); - g_code->codify(temp.data()); - endFontClass(); + startFontClass(yyscanner,"vhdllogic"); + yyextra->code->codify(temp.data()); + endFontClass(yyscanner); } - else - g_code->codify(temp.data()); + else + yyextra->code->codify(temp.data()); } } } @@ -360,64 +1177,68 @@ static void writeWord(const char *word,const char* curr_class=0,bool classLink=F /*! write a code fragment 'text' that may span multiple lines, inserting * line numbers for each line. */ -static void codifyLines(const char *text,const char *cl=0,bool classlink=FALSE,bool comment=FALSE) +static void codifyLines(yyscan_t yyscanner,const char *text,const char *cl,bool classlink,bool comment) { + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; if (text==0) return; - //printf("codifyLines(%d,\"%s\")\n",g_yyLineNr,text); + //printf("codifyLines(%d,\"%s\")\n",yyextra->yyLineNr,text); const char *p=text,*sp=p; char c; - bool done=FALSE; + bool done=false; while (!done) { sp=p; while ((c=*p++) && c!='\n') {} if (c=='\n') { - g_yyLineNr++; + yyextra->yyLineNr++; QCString line = sp; line = line.left((int)(p-sp)-1); - //*(p-1)='\0'; - //g_code->codify(sp); if (comment) { - writeFont("comment",line.data()); + writeFont(yyscanner,"comment",line.data()); } else { - writeWord(line,cl,classlink); + writeWord(yyscanner,line,cl,classlink); } - nextCodeLine(); + nextCodeLine(yyscanner); } else { if (comment) - writeFont("comment",sp); + { + writeFont(yyscanner,"comment",sp); + } else - writeWord(sp,cl,classlink); - done=TRUE; + { + writeWord(yyscanner,sp,cl,classlink); + } + done=true; } } } /*! writes a link to a fragment \a text that may span multiple lines, inserting - * line numbers for each line. If \a text contains newlines, the link will be + * line numbers for each line. If \a text contains newlines, the link will be * split into multiple links with the same destination, one for each line. */ -static void writeMultiLineCodeLink(CodeOutputInterface &ol, +static void writeMultiLineCodeLink(yyscan_t yyscanner,CodeOutputInterface &ol, Definition *d, const char *text) { + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; static bool sourceTooltips = Config_getBool(SOURCE_TOOLTIPS); - TooltipManager::instance()->addTooltip(d); + TooltipManager::instance().addTooltip(ol,d); QCString ref = d->getReference(); QCString file = d->getOutputFileBase(); QCString anchor = d->anchor(); - QCString tooltip; + QCString tooltip; if (!sourceTooltips) // fall back to simple "title" tooltips { tooltip = d->briefDescriptionAsTooltip(); } - bool done=FALSE; + bool done=false; char *p=(char *)text; while (!done) { @@ -426,78 +1247,58 @@ static void writeMultiLineCodeLink(CodeOutputInterface &ol, while ((c=*p++) && c!='\n') {} if (c=='\n') { - g_yyLineNr++; + yyextra->yyLineNr++; *(p-1)='\0'; // printf("writeCodeLink(%s,%s,%s,%s)\n",ref,file,anchor,sp); ol.writeCodeLink(ref,file,anchor,sp,tooltip); - nextCodeLine(); + nextCodeLine(yyscanner); } else { ol.writeCodeLink(ref,file,anchor,sp,tooltip); - done=TRUE; + done=true; } } } -static void setParameterList(const MemberDef *md) -{ - g_classScope = md->getClassDef() ? md->getClassDef()->name().data() : ""; - for (const Argument &a: md->argumentList()) - { - g_parmName = a.name.copy(); - g_parmType = a.type.copy(); - int i = g_parmType.find('*'); - if (i!=-1) g_parmType = g_parmType.left(i); - i = g_parmType.find('&'); - if (i!=-1) g_parmType = g_parmType.left(i); - g_parmType.stripPrefix("const "); - g_parmType=g_parmType.stripWhiteSpace(); - // g_theVarContext.addVariable(g_parmType,g_parmName); - } -} - - /*! writes a link to a function or procedure */ - -static void generateFuncLink(CodeOutputInterface &ol,MemberDef* mdef) +static void generateFuncLink(yyscan_t yyscanner,CodeOutputInterface &ol,MemberDef* mdef) { - //printf("generateFuncLink(FuncName=%s)\n",mdef->name().data()); QCString memberName=mdef->name(); if (mdef && mdef->isLinkable()) // is it a linkable class { - writeMultiLineCodeLink(ol,mdef,mdef->name()); - addToSearchIndex(memberName); + writeMultiLineCodeLink(yyscanner,ol,mdef,mdef->name()); + addToSearchIndex(yyscanner,memberName); return; } - codifyLines(memberName.data()); - addToSearchIndex(memberName); + codifyLines(yyscanner,memberName.data()); + addToSearchIndex(yyscanner,memberName); } // generateFuncLink -static void generateMemLink(CodeOutputInterface &ol,QCString &clName,QCString& memberName) +static void generateMemLink(yyscan_t yyscanner,CodeOutputInterface &ol,QCString &clName,QCString& memberName) { - if (memberName.isEmpty()) return; + if (memberName.isEmpty()) return; if (clName.isEmpty()) { - codifyLines(memberName.data()); + codifyLines(yyscanner,memberName.data()); return; } - + QCString className=clName; MemberDef *md=0; //MemberDef *comp=0; - //bool isLocal=FALSE; + //bool isLocal=false; md=VhdlDocGen::findMember(className,memberName); ClassDef *po=VhdlDocGen::getClass(className.data()); - if (md==0 && po && (VhdlDocGen::VhdlClasses)po->protection()==VhdlDocGen::PACKBODYCLASS) + if (md==0 && po && (VhdlDocGen::VhdlClasses)po->protection()==VhdlDocGen::PACKBODYCLASS) { QCString temp=className;//.stripPrefix("_"); temp.stripPrefix("_"); @@ -506,17 +1307,17 @@ static void generateMemLink(CodeOutputInterface &ol,QCString &clName,QCString& m if (md && md->isLinkable()) // is it a linkable class { - writeMultiLineCodeLink(ol,md,memberName); - addToSearchIndex(memberName); + writeMultiLineCodeLink(yyscanner,ol,md,memberName); + addToSearchIndex(yyscanner,memberName); return; } // nothing found, just write out the word - codifyLines(memberName.data()); - addToSearchIndex(memberName); + codifyLines(yyscanner,memberName.data()); + addToSearchIndex(yyscanner,memberName); }// generateMemLink -static void generateClassOrGlobalLink(CodeOutputInterface &ol,const char *clName, bool /*typeOnly*/, const char *curr_class) +static void generateClassOrGlobalLink(yyscan_t yyscanner,CodeOutputInterface &ol,const char *clName, bool /*typeOnly*/, const char *curr_class) { QCString className=clName; @@ -524,9 +1325,9 @@ static void generateClassOrGlobalLink(CodeOutputInterface &ol,const char *clName ClassDef *cd=0; //MemberDef *md=0; - //bool isLocal=FALSE; + //bool isLocal=false; className.stripPrefix("_"); - cd = getClass(className.data()); + cd = getClass(className.data()); if (!cd && curr_class) { if (QCString(curr_class).contains(QRegExp("::"+QCString(clName)+"$"))) cd = getClass(curr_class); @@ -543,14 +1344,14 @@ static void generateClassOrGlobalLink(CodeOutputInterface &ol,const char *clName //{ // temp=VhdlDocGen::getClassName(cd); //} - writeMultiLineCodeLink(ol,cd,temp); - addToSearchIndex(className); + writeMultiLineCodeLink(yyscanner,ol,cd,temp); + addToSearchIndex(yyscanner,className); return; } Definition *d = cd->getOuterScope(); if (d && d->definitionType()==Definition::TypeClass) { - cd = dynamic_cast<ClassDef*>(d); + cd = toClassDef(d); } else { @@ -559,55 +1360,59 @@ static void generateClassOrGlobalLink(CodeOutputInterface &ol,const char *clName } // nothing found, just write out the word - codifyLines(clName); - addToSearchIndex(clName); + codifyLines(yyscanner,clName); + addToSearchIndex(yyscanner,clName); }// generateClasss or global link /*! 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)) - { - p++ ; - if (c=='\n') count++; + while ((c=*p)) + { + 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; - } + count++, + yyextra->needsTermination=true; + } return count; } -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 startFontClass(const char *s) +static void startFontClass(yyscan_t yyscanner,const char *s) { + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; if (s==0) return; - endFontClass(); - g_code->startFontClass(s); - g_currentFontClass=s; + endFontClass(yyscanner); + yyextra->code->startFontClass(s); + yyextra->currentFontClass=s; } -static void writeFont(const char *s,const char* text) +static void writeFont(yyscan_t yyscanner,const char *s,const char* text) { + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; if (s==0 || text==0) return; - //printf("writeFont(%d,\"%s\")\n",g_yyLineNr,text); - g_code->startFontClass(s); - g_code->codify(text); - g_code->endFontClass(); + //printf("writeFont(yyscanner,%d,\"%s\")\n",yyextra->yyLineNr,text); + yyextra->code->startFontClass(s); + yyextra->code->codify(text); + yyextra->code->endFontClass(); } //---------------------------------------------------------------------------- @@ -616,42 +1421,34 @@ static void appStringLower(QCString& qcs,const char* text) { qcs.resize(0); qcs.append(text); - //qcs=qcs.lower(); qcs=qcs.stripWhiteSpace(); } -//static void appString(QCString& qcs,const char* text) -//{ -// qcs.resize(0); -// qcs.append(text); -//} - -static QCString g_temp; - /* writes and links a port map statement */ -static void codifyMapLines(const char *text) +static void codifyMapLines(yyscan_t yyscanner,const char *text) { + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; if (text==0) return; - g_temp.resize(0); - //bool dot=FALSE; + QCString temp; + //bool dot=false; int wordCounter=0; QCString ctemp; - //printf("codifyLines(%d,\"%s\")\n",g_yyLineNr,text); + //printf("codifyMapLines(%d,\"%s\")\n",yyextra->yyLineNr,text); const char *p=text; //,*sp=p; char c; - bool done=FALSE; + bool done=false; while (!done) { //sp=p; while ((c=*p++) && c!='\n' && c!=':' && c != ' ' && c != '(' && c!='\0' && c!='\t') - { + { if (c!=0x9) - g_temp+=c; + temp+=c; } if (c=='\0') return; - if (!g_temp.isEmpty()) wordCounter++; + if (!temp.isEmpty()) wordCounter++; - if (!g_temp.isEmpty()) + if (!temp.isEmpty()) { // different kinds of component instantiations // xxx:yyy (generic/port) map( @@ -659,50 +1456,51 @@ static void codifyMapLines(const char *text) // xxx: entity yyy(zzz) (generic/port) map( if (wordCounter==2 || wordCounter==3) { - QCString q=g_temp.lower(); // consider (upper/lower) cases - if (q=="entity" || q=="component" || q=="configuration" || q=="port" || q=="generic") - { - generateMemLink(*g_code,g_CurrClass,g_temp); - } - else - { - g_PortMapComp=g_temp; - generateClassOrGlobalLink(*g_code,g_temp); - } + QCString q=temp.lower(); // consider (upper/lower) cases + if (q=="entity" || q=="component" || q=="configuration" || q=="port" || q=="generic") + { + generateMemLink(yyscanner,*yyextra->code,yyextra->currClass,temp); + } + else + { + yyextra->PortMapComp=temp; + generateClassOrGlobalLink(yyscanner,*yyextra->code,temp); + } } - else + else { - generateMemLink(*g_code,g_CurrClass,g_temp); + generateMemLink(yyscanner,*yyextra->code,yyextra->currClass,temp); } } ctemp.fill(c,1); - codifyLines(ctemp.data()); + codifyLines(yyscanner,ctemp.data()); ctemp.resize(0); - g_temp.resize(0); + temp.resize(0); }//while -}//codifymaplines +}//codifyMapLines /* -* writes a function|procedure prototype and links the function|procedure name +* writes a function|procedure prototype and links the function|procedure name */ -static void writeFuncProto() +static void writeFuncProto(yyscan_t yyscanner) { + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; QCString name,ret; - VhdlDocGen::parseFuncProto(g_FuncProto,name,ret,FALSE); + VhdlDocGen::parseFuncProto(yyextra->funcProto,name,ret,false); if (name.isEmpty()) { - codifyLines(g_FuncProto.data(),g_CurrClass.data()); + codifyLines(yyscanner,yyextra->funcProto.data(),yyextra->currClass.data()); return; } - QCStringList qlist=QCStringList::split(name,g_FuncProto); + QCStringList qlist=QCStringList::split(name,yyextra->funcProto); QCString temp=qlist[0]; - codifyLines(temp.data(),g_CurrClass.data()); - g_FuncProto.stripPrefix(temp.data()); + codifyLines(yyscanner,temp.data(),yyextra->currClass.data()); + yyextra->funcProto.stripPrefix(temp.data()); temp.resize(0); - temp=g_CurrClass; - if (isPackageBody) + temp=yyextra->currClass; + if (yyextra->isPackageBody) { temp.stripPrefix("_");// _{package body name} } @@ -710,844 +1508,69 @@ static void writeFuncProto() if (mdef) { - generateFuncLink(*g_code,mdef); - g_FuncProto.stripPrefix(name.data()); - codifyLines(g_FuncProto.data(),g_CurrClass.data()); + generateFuncLink(yyscanner,*yyextra->code,mdef); + yyextra->funcProto.stripPrefix(name.data()); + codifyLines(yyscanner,yyextra->funcProto.data(),yyextra->currClass.data()); } else { - codifyLines(g_FuncProto.data(),g_CurrClass.data()); + codifyLines(yyscanner,yyextra->funcProto.data(),yyextra->currClass.data()); } }// writeFuncProto /* writes a process prototype to the output */ - static void writeProcessProto(){ - codifyLines(g_FuncProto.data(),g_CurrClass.data()); - g_vhdlKeyDict.clear(); +static void writeProcessProto(yyscan_t yyscanner) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + codifyLines(yyscanner,yyextra->funcProto.data(),yyextra->currClass.data()); + yyextra->vhdlKeyDict.clear(); }// writeProcessProto /* writes a keyword */ -static bool writeColoredWord(QCString& word ) +static bool writeColoredWord(yyscan_t yyscanner,QCString& word ) { QCString qcs=word.lower(); - QCString *ss=VhdlDocGen::findKeyWord(qcs); - if (ss) + const char *ss=VhdlDocGen::findKeyWord(qcs); + if (ss) { - writeFont(ss->data(),word.data()); - return TRUE; + writeFont(yyscanner,ss,word.data()); + return true; } - return FALSE; + return false; } -#undef YY_INPUT -#define YY_INPUT(buf,result,max_size) result=yyread(buf,max_size); +//----------------------------------------------------------------------------------- -static int yyread(char *buf,int max_size) +struct VHDLCodeParser::Private { - int c=0; - while( c < max_size && g_inputString[g_inputPosition] ) - { - *buf = g_inputString[g_inputPosition++] ; - c++; buf++; - } - return c; -} - -%} - - -B [ \t] -BN [ \t\n\r] -STRING ["][^"\n]*["] -NAME [a-z_A-Z][ a-z_A-Z0-9]* -FUNCNAME [a-z_A-Z"][a-z_A-Z0-9+*"/=<>-]* -ID "$"?[a-z_A-Z][a-z_A-Z0-9]* -SPECSIGN [:;, +*&\/=<>'\t]* -DIGITSS [0-9]+|[0-9]+("#")*[0-9_a-fA-F\+\.\-]+("#")* -ALLTYPESMAP {B}*[_a-zA-Z0-9. ]+{BN}* -ALLTYPESMAP1 {BN}*[_a-zA-Z0-9.() ]+{BN}* - -ARCHITECTURE ^{B}*("architecture"){BN}+{FUNCNAME}{BN}+("of"){BN}+{FUNCNAME}{BN}+("is") -PROCESS ({BN}*{FUNCNAME}{BN}*[:]+{BN}*("process"){BN}*[(]*)|[^a-zA-Z]("process "|"process("){BN}*[ (]*|[^a-zA-Z]("process"){BN}+ - -END1 {B}*("end "){BN}+("if"|"case"|"loop"|"generate"|"for") -END2 [^a-zA-Z_]("end"){BN}*[;] -END3 {BN}*[^a-zA-Z]("end"){BN}+{FUNCNAME}{BN}*[;] -END4 {B}*("end"){BN}+"function"{BN}+{FUNCNAME}{BN}*[;] -ENDEFUNC {END3}|{END4}|{END2} - -KEYWORD ("of"|"new"|"event"|"break"|"case"|"end"|"loop"|"else"|"for"|"goto"|"if"|"return"|"generate"|"is"|"while"|"in") -TYPEKW ^{B}*("type"|"subtype"|"constant"|"attribute"|"signal"|"variable","alias","configuration") -FUNC ^{B}*("function"|"procedure"){BN}*{FUNCNAME}{BN}*("(") + yyscan_t yyscanner; + vhdlcodeYY_state state; +}; -ARITHOP "+"|"-"|"/"|"*"|"%"|"/="|":=" -ASSIGNOP "="|"*="|"/="|"%="|"+="|"-="|"<<="|">>="|"&="|"^="|"|=" -LOGICOP "=="|"!="|">"|"<"|">="|"<="|"&&"|"||"|"!" -BITOP "&"|"|"|"^"|"<<"|">>"|"~" -OPERATOR {ARITHOP}|{ASSIGNOP}|{LOGICOP}|{BITOP} - -PORT {B}*("port"){BN}*("(") -GENERIC {B}*("generic"){BN}*("(") - -BRACEOPEN [(]{1} -BRACECLOSE [)]{1} - -TEXTT {B}*"--"[^\n]* - -MAPCOMPONENT1 ({ALLTYPESMAP}[:]{ALLTYPESMAP}{TEXTT}*{BN}+("port"|"generic"){BN}+("map"){BN}*("("){1}) -MAPCOMPONENT2 {BN}*("port"|"generic"){BN}+("map"){BN}*("("){1} -MAPCOMPONENT3 ({ALLTYPESMAP}[:]{BN}*{ALLTYPESMAP1}{TEXTT}*{BN}+("port"|"generic"){BN}+("map"){BN}*("("){1}) -MAPCOMPONENT4 ({ALLTYPESMAP}[:]{BN}*("entity"|"component"|"configuration"){BN}+{ALLTYPESMAP1}{TEXTT}*{BN}*("port"|"generic"){BN}*("map"){BN}*("("){1}) - -XILINX "INST"|"NET"|"PIN"|"BLKNM"|"BUFG"|"COLLAPSE"|"CPLD"|"COMPGRP"|"CONFIG"|"CONFIG_MODE"|"COOL_CLK"|"DATA_GATE"|"DCI_VALUE"|"DISABLE"|"DRIVE"|"DROP_SPEC"|"ENABLE"|"FAST"|"FEEDBACK"|"FILE"|"FLOAT"|"FROM-THRU-TO"|"FROM-TO"|"HBLKNM"|"HU_SET"|"INREG"|"IOB"|"IOBDELAY"|"IOSTANDARD"|"KEEP"|"KEEPER"|"LOC"|"LOCATE"|"LOCK_PINS"|"MAP"|"MAXDELAY"|"MAXPT"|"MAXSKEW"|"NODELAY"|"NOREDUCE"|"OFFSET"|"OPEN_DRAIN"|"OPT_EFFORT"|"OPTIMIZE"|"PERIOD"|"PIN"|"PRIORITY"|"PROHIBIT"|"PULLDOWN"|"PULLUP"|"PWR_MODE"|"REG"|"RLOC"|"RLOC_ORIGIN"|"RLOC_RANGE"|"SAVE NET"|"FLAG"|"SYSTEM_JITTER"|"TEMPERATURE"|"TIMEGRP"|"TIMESPEC"|"VOLTAGE" - -%option noyywrap -%option nounput - -%x Bases -%x ParseType -%x ParseFuncProto -%x ParseComponent -%x ParsePackage -%x ParseProcessProto -%x ClassName -%x PackageName -%x ClassVar -%x ClassesName -%x Map -%x End -%x Body - -%% - -. { - BEGIN(Bases); - } - -<Map>{BRACEOPEN} { - g_braceCount++; - writeFont("vhdlchar",vhdlcodeYYtext); - BEGIN(Map); - } - -<Map>[^()\n,--]* { /* write and link a port map lines */ - QCString tt(vhdlcodeYYtext); - VhdlDocGen::deleteAllChars(tt,','); - QRegExp r("=>"); - QCStringList ql=QCStringList::split(r,tt); - if (ql.count()>=2) - { - unsigned int index=0; - QCString t1=ql[0]; - char cc=t1.at(index); - while (cc==' ' || cc=='\t') - { - char c2[2]; - c2[0]=cc; - c2[1]=0; - g_code->codify(c2); - index++; - if (index>=t1.size()) break; - cc=t1.at(index); - } - - QCString s1=t1; - s1=s1.stripWhiteSpace(); - - // if (!g_PortMapComp.isEmpty()) - generateMemLink(*g_code,g_PortMapComp,s1); - while (index++<t1.size()) - { - cc=t1.at(index); - if (cc==' ' || cc=='\t') - { - char c2[2]; - c2[0]=cc; - c2[1]=0; - g_code->codify(c2); - } - } - codifyLines("=>"); - index=0; - QCString s2=ql[1]; - t1=s2; - cc=t1.at(index); - while (cc==' ' || cc=='\t') - { - char c2[2]; - c2[0]=cc; - c2[1]=0; - g_code->codify(c2); - index++; - if (index>=t1.size()) break; - cc=t1.at(index); - } - s2=s2.stripWhiteSpace(); - if (!checkVhdlString(s2)) - generateMemLink(*g_code,g_CurrClass,s2); - while (index++<t1.size()) - { - if (t1.at(index)==' ') - { - g_code->codify(" "); - } - } - } - else - { - codifyLines(vhdlcodeYYtext,g_CurrClass.data()); - } - BEGIN(Map); - } - -<Map>"\n"|"," { - codifyLines(vhdlcodeYYtext); - BEGIN(Map); - } - -<Map>{BRACECLOSE} { - g_braceCount--; - writeFont("vhdlchar",vhdlcodeYYtext); - if (g_braceCount==0) - { - BEGIN(Bases); - } - } - -<ParseFuncProto>{NAME} { - QCString tmp(vhdlcodeYYtext); - tmp=tmp.stripWhiteSpace(); - appStringLower(g_PrevString,vhdlcodeYYtext); - g_vhdlKeyDict.insert(g_PrevString,new QCString(g_PrevString.data())); - if (!writeColoredWord(tmp)) - { - generateMemLink(*g_code,g_CurrClass,tmp); - } - BEGIN(Bases); - } - -<ParseType>{STRING} { - QCString qcs(vhdlcodeYYtext); - VhdlDocGen::deleteAllChars(qcs,'"'); - VhdlDocGen::deleteAllChars(qcs,' '); - if (VhdlDocGen::isNumber(qcs)) - writeFont("vhdllogic",vhdlcodeYYtext); - else - writeFont("keyword",vhdlcodeYYtext); - } - -<ParseType>"\n" { - g_FuncProto.append(vhdlcodeYYtext); - if (isProto) - { - codifyLines(vhdlcodeYYtext); - } - BEGIN(ParseType); - } - - -<ParseType>{TEXTT} { - g_FuncProto.append(vhdlcodeYYtext); - if (isProto) - { - writeFont("keyword",vhdlcodeYYtext); - } - BEGIN(ParseType); - } - -<ParseType>{ENDEFUNC} { - QRegExp regg("[\\s]"); - QCString tt(vhdlcodeYYtext); - codifyLines(vhdlcodeYYtext,g_CurrClass.data()); - tt=tt.lower(); - VhdlDocGen::deleteAllChars(tt,';'); - tt.stripWhiteSpace(); - QCStringList ql=QCStringList::split(regg,tt); - int index=ql.findIndex(QCString("if"))+1; - index+=ql.findIndex(QCString("case"))+1; - index+=ql.findIndex(QCString("loop"))+1; - index+=ql.findIndex(QCString("generate"))+1; - if (index==0) - { - BEGIN(Bases); - } - else - { - BEGIN(ParseType); - } - } - -<ParseType>{END1} { - codifyLines(vhdlcodeYYtext,g_CurrClass.data()); - g_vhdlKeyDict.clear(); - } - -<ParseType>^{B}*("begin "|"begin") { - codifyLines(vhdlcodeYYtext,g_CurrClass.data()); - isFuncProto=FALSE; - } - -<ParseType>{SPECSIGN} { - g_FuncProto.append(vhdlcodeYYtext); - if (isProto) - { - codifyLines(vhdlcodeYYtext,g_CurrClass.data()); - } - } - -<ParseType>["_a-zA-Z0-9]* { - QCString val(vhdlcodeYYtext); - g_FuncProto.append(vhdlcodeYYtext); - appStringLower(g_PrevString,vhdlcodeYYtext); - - if (isFuncProto && g_braceCount==0) - { - g_vhdlKeyDict.insert(g_PrevString,new QCString(g_PrevString.data())); - } - - if (isProto) - { - if (!writeColoredWord(val)) - { - if (!isFuncProto && !g_vhdlKeyDict.find(g_PrevString)) - { - val=val.stripWhiteSpace(); - if (VhdlDocGen::isNumber(val)) - { - startFontClass("vhdllogic"); - codifyLines(vhdlcodeYYtext,g_CurrClass.data()); - endFontClass(); - } - else - generateMemLink(*g_code,g_CurrClass,val); - } - else - { - codifyLines(vhdlcodeYYtext,g_CurrClass.data()); - } - } - } - BEGIN(ParseType); - } - -<ParseType>{BRACEOPEN} { - g_braceCount++; - g_FuncProto+='('; - if (isProto) - { - writeFont("vhdlchar",vhdlcodeYYtext); - } - BEGIN(ParseType); - } - -<ParseType>{BRACECLOSE} { - g_braceCount--; - g_FuncProto+=')'; - if (isProto) - { - writeFont("vhdlchar",vhdlcodeYYtext); - } - if (g_braceCount==0 && !isProto)// && !isPackageBody) - { - isProto=TRUE; - appStringLower(g_PrevString,vhdlcodeYYtext); - writeFuncProto(); - BEGIN(Bases); - } - if (isPackageBody) - { - BEGIN(ParseType); - } - } - - -<ClassesName>{FUNCNAME} { - appStringLower(g_PrevString,vhdlcodeYYtext); - g_CurrClass.resize(0); - g_CurrClass.append(vhdlcodeYYtext); - g_CurrClass=g_CurrClass.stripWhiteSpace(); - - generateClassOrGlobalLink(*g_code,vhdlcodeYYtext); - BEGIN(Bases); - } - - -<ParseComponent>{BRACEOPEN} { - g_braceCount++; - g_code->codify(vhdlcodeYYtext); - } - - -<ParseComponent>{BRACECLOSE} { - g_braceCount--; - g_code->codify(vhdlcodeYYtext); - if (g_braceCount==0 && !isComponent) - { - g_tempComp.resize(0); - BEGIN(Bases); - } - else - { - BEGIN(ParseComponent); - } - } - -<ParseComponent>{B}*"-" { - if (strlen(vhdlcodeYYtext)>=2) // found text ? - { - writeFont("keyword",vhdlcodeYYtext); - } - else - { - writeFont("vhdlchar",vhdlcodeYYtext); - } - } - -<ParseComponent>{SPECSIGN} { - codifyLines(vhdlcodeYYtext); - } - - - -<ParseComponent>"\n"|" " { - codifyLines(vhdlcodeYYtext); - } - -<ParseComponent>{DIGITSS} { - startFontClass("vhdllogic"); - codifyLines(vhdlcodeYYtext); - endFontClass(); - } - -<ParseComponent>{PORT} { - codifyLines(vhdlcodeYYtext); - g_braceCount=1; - isComponent=FALSE; - } - -<ParseComponent>{GENERIC} { - codifyLines(vhdlcodeYYtext); - g_braceCount=1; - } - -<ParseComponent>[_a-zA_Z][_a-zA-Z0-9]* { - QCString temp(vhdlcodeYYtext); - appStringLower(g_PrevString,vhdlcodeYYtext); - if (!checkVhdlString(temp)){ - if (!writeColoredWord(g_PrevString)) - { - generateMemLink(*g_code,g_tempComp,temp); - } - } - } - -<ParseComponent>{STRING} { - QCString temp(vhdlcodeYYtext); - if (!checkVhdlString(temp)) - codifyLines(vhdlcodeYYtext); - } - - -<ParseProcessProto>[^()]* { - g_FuncProto.append(vhdlcodeYYtext); - } - - - -<ParseProcessProto>{BRACEOPEN} { - g_FuncProto.append(vhdlcodeYYtext); - g_braceCount++; - } - -<ParseProcessProto>{BRACECLOSE} { - g_FuncProto.append(vhdlcodeYYtext); - g_braceCount--; - if (g_braceCount==0) - { - writeProcessProto(); - BEGIN(Bases); - } - } - -<ParsePackage>[^:;]* { //found package - QCString temp(vhdlcodeYYtext); - QCStringList strl=QCStringList::split(".",temp); - if (strl.count()>2) - { - QCString s1=strl[0]; - QCString s2=strl[1]; - QCString s3=strl[2]; - s1.append("."); - s3.prepend("."); - codifyLines(s1.data(),g_CurrClass.data()); - ClassDef *cd=VhdlDocGen::getPackageName(s2); - if (cd) - { - generateClassOrGlobalLink(*g_code,s2.data()); - } - else - { - codifyLines(s2.data()); - } - codifyLines(s3.data()); - } - else - { - writeFont("keywordflow",vhdlcodeYYtext); - } - BEGIN(Bases); - } - -<Bases>{MAPCOMPONENT1}|{MAPCOMPONENT2}|{MAPCOMPONENT3}|{MAPCOMPONENT4} { // found port or generic map - QCString tt(vhdlcodeYYtext); - /* - if (tt.contains(':',FALSE)) - { - isStartMap=TRUE; - } - else - { - isStartMap=FALSE; - } - */ - int j=tt.find('.'); - - if (j>0) - { - QCString left=tt.left(j+1); - codifyLines(left.data()); - tt=tt.right(tt.length()-j-1); - left=VhdlDocGen::getIndexWord(tt.data(),0); - if (!left.isEmpty()) - { - if (left.contains('(')) - { - j=left.find('(',FALSE); - QCString name=left.left(j); - generateClassOrGlobalLink(*g_code,name.data()); - g_PortMapComp=name; - name=tt.right(tt.length()-name.length()); - codifyLines(name.data()); - } - else - { - generateClassOrGlobalLink(*g_code,left.data()); - tt.stripPrefix(left.data()); //=tt.right(tt.length()-left.length()-1); - - g_PortMapComp=left; - codifyLines(tt.data()); - } - } - } - else - { - if (tt.contains(':',FALSE)) - codifyMapLines(tt.data()); - else - codifyLines(tt.data()); - } - g_braceCount=1; - BEGIN(Map); - } - -<Bases>^{B}*("component"){BN}+{FUNCNAME} { // found component - appStringLower(g_PrevString,vhdlcodeYYtext); - // writeFont("keywordflow",VhdlDocGen::getIndexWord(vhdlcodeYYtext,0).data()); - // writeFont("vhdlkeyword"," "); - QCString temp=VhdlDocGen::getIndexWord(vhdlcodeYYtext,1); - temp=temp.stripWhiteSpace(); - VhdlDocGen::deleteAllChars(temp,'\n'); - g_tempComp=temp; - codifyLines(vhdlcodeYYtext,temp.data(),TRUE); - g_braceCount=0; - - //if (getClass(temp.data())) - // generateClassOrGlobalLink(*g_code,temp.data()); - //else - // generateMemLink(*g_code,g_CurrClass,temp); - - isComponent=TRUE; - BEGIN(ParseComponent); - } - - - -<Bases>{ARCHITECTURE} { // found architecture - g_PortMapComp.resize(0); - // writeFont("vhdlkeyword",VhdlDocGen::getIndexWord(vhdlcodeYYtext,0).data()); - // writeFont("vhdlkeyword"," "); - // writeFont("vhdlchar",VhdlDocGen::getIndexWord(vhdlcodeYYtext,1).data()); - // writeFont("vhdlkeyword"," "); - // writeFont("vhdlkeyword",VhdlDocGen::getIndexWord(vhdlcodeYYtext,2).data()); - // writeFont("vhdlkeyword"," "); - //QCString temp=VhdlDocGen::getIndexWord(vhdlcodeYYtext,1); - //temp=temp.stripWhiteSpace(); - //temp+=("-"); - //temp+=VhdlDocGen::getIndexWord(vhdlcodeYYtext,3); - QCString temp = VhdlDocGen::getIndexWord(vhdlcodeYYtext,3); - g_CurrARCH = TRUE; - temp+="::"; - temp+=VhdlDocGen::getIndexWord(vhdlcodeYYtext,1); - g_CurrClass=temp; - VhdlDocGen::deleteAllChars(temp,'\n'); - codifyLines(vhdlcodeYYtext,temp.data(),TRUE); - //generateClassOrGlobalLink(*g_code,temp.data()); - isPackageBody=FALSE; - } - - -<Bases>^{B}*("package "){BN}*("body"){BN}*{FUNCNAME} { // found package body - QCString ss(vhdlcodeYYtext); - QCString temp=VhdlDocGen::getIndexWord(vhdlcodeYYtext,2); - QCStringList ql=QCStringList::split(temp,ss); - QCString ll=ql[0]; - codifyLines(ll.data(),g_CurrClass.data()); - temp=temp.stripWhiteSpace(); - temp.prepend("_"); - generateClassOrGlobalLink(*g_code,temp.data()); - g_CurrClass.resize(0); - g_CurrClass=temp; - isProto=FALSE; - isPackageBody=TRUE; - // BEGIN(ClassesName); - } - -<Bases>{PROCESS} { // found process - isFuncProto=TRUE; - g_FuncProto.resize(0); - g_FuncProto.append(vhdlcodeYYtext); - g_vhdlKeyDict.clear(); - appStringLower(g_PrevString,vhdlcodeYYtext); - if (g_PrevString.contains('(')) - { - g_braceCount=1; - BEGIN(ParseProcessProto); - } - else - { - writeProcessProto(); - } - } - -<Bases>("end"){BN}+("process") { // end of process - isFuncProto=FALSE; - codifyLines(vhdlcodeYYtext); - BEGIN(Bases); - } - - -<Bases>^{B}*("begin "|"begin") { - isFuncProto=FALSE; - writeFont("vhdlkeyword",vhdlcodeYYtext); - } - -<Bases>^{B}*("use"|"library"){BN}+ { //found package or library - writeFont("vhdlkeyword",vhdlcodeYYtext); - BEGIN(ParsePackage); - } - - -<Bases>^{B}*("use"){BN}+("configuration")[^\n]* { - codifyLines(vhdlcodeYYtext); - } - - - -<Bases>{FUNC} { // found function|procedure - g_vhdlKeyDict.clear(); - g_FuncProto.resize(0); - isProto=FALSE; - g_FuncProto.append(vhdlcodeYYtext); - g_braceCount=1; - BEGIN(ParseType); - } - - - -<Bases>^{B}*("entity"|"package"){BN}+ { - appStringLower(g_PrevString,vhdlcodeYYtext); - writeFont("keywordflow",vhdlcodeYYtext); - isPackageBody=FALSE; - BEGIN(ClassesName); - } - - -<Bases>"end"{BN}+"architecture"{BN}+{FUNCNAME} { - codifyLines(vhdlcodeYYtext,g_CurrClass.data(),TRUE); - g_CurrARCH = FALSE; - } -<Bases>"end"{BN}+{FUNCNAME} { - if (g_CurrARCH) - { - codifyLines(vhdlcodeYYtext,g_CurrClass.data(),TRUE); - g_CurrARCH = FALSE; - } - else - REJECT; - } -<Bases>"end" { - appStringLower(g_PrevString,vhdlcodeYYtext); - QCString temp(vhdlcodeYYtext); - temp=temp.stripWhiteSpace(); - - writeColoredWord(temp); - BEGIN(End); - } -<End>{ID} { - appStringLower(g_PrevString,vhdlcodeYYtext); - QCString temp(vhdlcodeYYtext); - temp=temp.stripWhiteSpace(); - - if (!writeColoredWord(temp)) - { - generateClassOrGlobalLink(*g_code,temp.data()); - } - } -<End>";" { - codifyLines(vhdlcodeYYtext); - BEGIN(Bases); - } -<Bases>{KEYWORD} { // found keyword - QCString qcs(vhdlcodeYYtext); - if (!writeColoredWord(qcs)) - { - startFontClass("vhdlchar"); - g_code->codify(vhdlcodeYYtext); - endFontClass(); - } - } - - -<Bases>{ID} { - appStringLower(g_PrevString,vhdlcodeYYtext); - QCString temp(vhdlcodeYYtext); - temp=temp.stripWhiteSpace(); - - if (!writeColoredWord(temp)) - { - startFontClass("vhdlchar"); - generateMemLink(*g_code,g_CurrClass,temp); - endFontClass(); - } - } - -<Bases,ParseComponent>{DIGITSS} { - startFontClass("vhdllogic"); - codifyLines(vhdlcodeYYtext); - endFontClass(); - } - -<Bases>^{B}*("use"){BN}+("entity"|"component")[^\n]* { - codifyLines(vhdlcodeYYtext,g_CurrClass.data(),TRUE); - } - - -<Bases>{TYPEKW} { - codifyLines(vhdlcodeYYtext); - if (isFuncProto) - { - BEGIN(ParseFuncProto); - } - else - { - BEGIN(Bases); - } - } - -<Bases>{OPERATOR} { - startFontClass("vhdlchar"); - g_code->codify(vhdlcodeYYtext); - endFontClass(); - } - -<Bases>","|"."|":"|"'"|"("|")" { - startFontClass("vhdlchar"); - g_code->codify(vhdlcodeYYtext); - endFontClass(); - } - -<Bases>{STRING} { - QCString qcs(vhdlcodeYYtext); - VhdlDocGen::deleteAllChars(qcs,'"'); - VhdlDocGen::deleteAllChars(qcs,' '); - - if (VhdlDocGen::isNumber(qcs)) - writeFont("vhdllogic",vhdlcodeYYtext); - else - writeFont("keyword",vhdlcodeYYtext); - } - -<Bases>{B}*"#"[^\n]* { - writeFont("keyword",vhdlcodeYYtext); - } - -<Bases>^{B}*{XILINX}/[^a-zA-Z0-9_] { - writeWord(yytext); - //codifyLines(vhdlcodeYYtext,g_CurrClass.data(),TRUE); - } - -<Bases>^{B}*"set_"[^\n]* { - writeWord(yytext); - } - -<*>\n { - codifyLines(vhdlcodeYYtext); - BEGIN(Bases); - } - -<*>. { - g_code->codify(vhdlcodeYYtext); - } - -<*>\n{TEXTT} { // found normal or special comment on its own line - QCString text(vhdlcodeYYtext); - int i=text.find("--"); - if (text.mid(i,3)=="--!") // && // hide special comment - { - if (!Config_getBool(STRIP_CODE_COMMENTS)) - { - codifyLines(text,0,FALSE,TRUE); - } - else g_yyLineNr++; // skip complete line, but count line - } - else // normal comment - { - codifyLines(text,0,FALSE,TRUE); - } - } -<*>{TEXTT} { // found normal or special comment after something - QCString text(vhdlcodeYYtext); - int i=text.find("--"); - if (text.mid(i,3)=="--!") - { - // hide special comment - if (!Config_getBool(STRIP_CODE_COMMENTS)) - { - codifyLines(text,0,FALSE,TRUE); - } - } - else // normal comment - { - codifyLines(text,0,FALSE,TRUE); - } - } - -%% +VHDLCodeParser::VHDLCodeParser() : p(std::make_unique<Private>()) +{ + vhdlcodeYYlex_init_extra(&p->state,&p->yyscanner); +#ifdef FLEX_DEBUG + vhdlcodeYYset_debug(1,p->yyscanner); +#endif + resetCodeParserState(); +} -/*@ ---------------------------------------------------------------------------- - */ +VHDLCodeParser::~VHDLCodeParser() +{ + vhdlcodeYYlex_destroy(p->yyscanner); +} -static void resetVhdlCodeParserState() +void VHDLCodeParser::resetCodeParserState() { - g_vhdlKeyDict.setAutoDelete(TRUE); - g_vhdlKeyDict.clear(); + p->state.vhdlKeyDict.clear(); } void VHDLCodeParser::parseCode(CodeOutputInterface &od, const char *className, - const QCString &s, + const QCString &s, SrcLangExt, bool exBlock, const char *exName, @@ -1560,96 +1583,84 @@ void VHDLCodeParser::parseCode(CodeOutputInterface &od, const Definition *searchCtx, bool /* collectXRefs */) { + yyscan_t yyscanner = p->yyscanner; + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; //printf("***parseCode() exBlock=%d exName=%s fd=%p\n",exBlock,exName,fd); if (s.isEmpty()) return; - printlex(yy_flex_debug, TRUE, __FILE__, fd ? fd->fileName().data(): NULL); + printlex(yy_flex_debug, true, __FILE__, fd ? fd->fileName().data(): NULL); if (memberDef) { const ClassDef *dd=memberDef->getClassDef(); - if (dd) g_CurrClass=dd->name(); + if (dd) yyextra->currClass=dd->name(); } - resetVhdlCodeParserState(); - g_code = &od; - g_inputString = s; - g_inputPosition = 0; - g_currentFontClass = 0; - g_needsTermination = FALSE; - g_searchCtx = searchCtx; + resetCodeParserState(); + 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_theCallContext.clear(); - g_classScope = className; - g_exampleBlock = exBlock; - g_exampleName = exName; - g_sourceFileDef = fd; - bool cleanupSourceDef = FALSE; + // yyextra->theCallContext.clear(); + 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); - cleanupSourceDef = TRUE; + yyextra->sourceFileDef = createFileDef("",exName); + cleanupSourceDef = true; } - if (g_sourceFileDef) + if (yyextra->sourceFileDef) { - setCurrentDoc("l00001"); + setCurrentDoc(yyscanner,"l00001"); } - g_currentDefinition = 0; - g_currentMemberDef = 0; - g_vhdlMember=0; - if (!g_exampleName.isEmpty()) + yyextra->currentDefinition = 0; + yyextra->currentMemberDef = 0; + yyextra->vhdlMember=0; + if (!yyextra->exampleName.isEmpty()) { - g_exampleFile = convertNameToFile(g_exampleName+"-example"); + yyextra->exampleFile = convertNameToFile(yyextra->exampleName+"-example"); } - g_includeCodeFragment = inlineFragment; - startCodeLine(); - // g_type.resize(0); - // g_name.resize(0); - // g_args.resize(0); - g_parmName.resize(0); - g_parmType.resize(0); - if(!g_lexInit) - VhdlDocGen::init(); - if (memberDef) + yyextra->includeCodeFragment = inlineFragment; + startCodeLine(yyscanner); + if (!yyextra->lexInit) { - setParameterList(memberDef); + VhdlDocGen::init(); + yyextra->lexInit=true; } - /*int iLine=*/countLines(); - vhdlcodeYYrestart( vhdlcodeYYin ); + /*int iLine=*/countLines(yyscanner); + vhdlcodeYYrestart( 0, yyscanner ); BEGIN( Bases ); - vhdlcodeYYlex(); - g_lexInit=TRUE; - if (g_needsTermination) + vhdlcodeYYlex(yyscanner); + 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; } - g_startCode=FALSE; - printlex(yy_flex_debug, FALSE, __FILE__, fd ? fd->fileName().data(): NULL); -} + yyextra->startCode=false; -void codeFreeVhdlScanner() -{ -#if defined(YY_FLEX_SUBMINOR_VERSION) - if (g_lexInit) - { - vhdlcodeYYlex_destroy(); - } -#endif + // write the tooltips + TooltipManager::instance().writeTooltips(od); + + printlex(yy_flex_debug, false, __FILE__, fd ? fd->fileName().data(): NULL); } #if USE_STATE2STRING diff --git a/src/vhdldocgen.cpp b/src/vhdldocgen.cpp index 8e311b7..93afb4b 100644 --- a/src/vhdldocgen.cpp +++ b/src/vhdldocgen.cpp @@ -55,6 +55,7 @@ #include "filename.h" #include "membergroup.h" #include "memberdef.h" +#include "membername.h" #include "plantuml.h" #include "vhdljjparser.h" #include "VhdlParser.h" @@ -63,14 +64,9 @@ //#define DEBUGFLOW #define theTranslator_vhdlType theTranslator->trVhdlType -static QDict<QCString> g_vhdlKeyDict0(17,FALSE); -static QDict<QCString> g_vhdlKeyDict1(17,FALSE); -static QDict<QCString> g_vhdlKeyDict2(17,FALSE); -static QDict<QCString> g_vhdlKeyDict3(17,FALSE); - static void initUCF(Entry* root,const char* type,QCString & qcs,int line,QCString & fileName,QCString & brief); static void writeUCFLink(const MemberDef* mdef,OutputList &ol); -static void addInstance(ClassDef* entity, ClassDef* arch, ClassDef *inst, +static void addInstance(ClassDefMutable* entity, ClassDefMutable* arch, ClassDefMutable *inst, const std::shared_ptr<Entry> &cur); //---------- create svg ------------------------------------------------------------- @@ -233,22 +229,16 @@ void VhdlDocGen::writeOverview() writeVhdlEntityToolTip(t,cd); delete port; - BaseClassList *bl=cd->baseClasses(); - if (bl) + for (const auto &bcd : cd->baseClasses()) { - BaseClassListIterator bcli(*bl); - BaseClassDef *bcd; - for ( ; (bcd=bcli.current()) ; ++bcli ) - { - ClassDef *bClass=bcd->classDef; - QCString dotn=cd->name()+":"; - dotn+=cd->name(); - QCString csc=bClass->name()+":"; - csc+=bClass->name(); - // fprintf(stderr,"\n <%s| %s>",dotn.data(),csc.data()); - writeVhdlDotLink(t,dotn,csc,0); - } - }// if bl + ClassDef *bClass=bcd.classDef; + QCString dotn=cd->name()+":"; + dotn+=cd->name(); + QCString csc=bClass->name()+":"; + csc+=bClass->name(); + // fprintf(stderr,"\n <%s| %s>",dotn.data(),csc.data()); + writeVhdlDotLink(t,dotn,csc,0); + } }// for endDot(t); @@ -567,11 +557,8 @@ VhdlDocGen::~VhdlDocGen() { } -void VhdlDocGen::init() -{ - // vhdl keywords included VHDL 2008 -const char* g_vhdlKeyWordMap0[] = +static const std::set< std::string > g_vhdlKeyWordSet0 = { "abs","access","after","alias","all","and","architecture","array","assert","assume","assume_guarantee","attribute", "begin","block","body","buffer","bus", @@ -592,100 +579,57 @@ const char* g_vhdlKeyWordMap0[] = "unaffected","units","until","use", "variable","vmode","vprop","vunit", "wait","when","while","with", - "xor","xnor", - 0 + "xor","xnor" }; // type -const char* g_vhdlKeyWordMap1[] = +static const std::set< std::string> g_vhdlKeyWordSet1 = { "natural","unsigned","signed","string","boolean", "bit","bit_vector","character", "std_ulogic","std_ulogic_vector","std_logic","std_logic_vector","integer", - "real","float","ufixed","sfixed","time","positive",0 + "real","float","ufixed","sfixed","time","positive" }; // logic -const char* g_vhdlKeyWordMap2[] = +static const std::set< std::string > g_vhdlKeyWordSet2 = { - "abs","and","or","not","mod", "xor","rem","xnor","ror","rol","sla", - "sll",0 + "abs","and","or","not","mod","xor","rem","xnor","ror","rol","sla","sll" }; // predefined attributes -const char* g_vhdlKeyWordMap3[] = +static const std::set< std::string > g_vhdlKeyWordSet3 = { -"base","left","right","high","low","ascending", -"image","value","pos","val","succ","pred","leftof","rightof","left","right","high","low", -"range","reverse_range","length","ascending","delayed","stable","quiet","transaction","event", -"active","last_event","last_active","last_value","driving","driving_value","simple_name","instance_name","path_name",0 + "base","left","right","high","low","ascending", + "image","value","pos","val","succ","pred","leftof","rightof","left","right","high","low", + "range","reverse_range","length","ascending","delayed","stable","quiet","transaction","event", + "active","last_event","last_active","last_value","driving","driving_value","simple_name","instance_name","path_name" }; - int j=0; - g_vhdlKeyDict0.setAutoDelete(TRUE); - g_vhdlKeyDict1.setAutoDelete(TRUE); - g_vhdlKeyDict2.setAutoDelete(TRUE); - g_vhdlKeyDict3.setAutoDelete(TRUE); - - while (g_vhdlKeyWordMap0[j]) - { - g_vhdlKeyDict0.insert(g_vhdlKeyWordMap0[j], - new QCString(g_vhdlKeyWordMap0[j])); - j++; - } - - j=0; - while (g_vhdlKeyWordMap1[j]) - { - g_vhdlKeyDict1.insert(g_vhdlKeyWordMap1[j], - new QCString(g_vhdlKeyWordMap1[j])); - j++; - } - - j=0; - while (g_vhdlKeyWordMap2[j]) - { - g_vhdlKeyDict2.insert(g_vhdlKeyWordMap2[j], - new QCString(g_vhdlKeyWordMap2[j])); - j++; - } - - j=0; - while (g_vhdlKeyWordMap3[j]) - { - g_vhdlKeyDict3.insert(g_vhdlKeyWordMap3[j], - new QCString(g_vhdlKeyWordMap3[j])); - j++; - } - -}// buildKeyMap +void VhdlDocGen::init() +{ +} /*! * returns the color of a keyword */ - -QCString* VhdlDocGen::findKeyWord(const QCString& tmp) +const char* VhdlDocGen::findKeyWord(const QCString& kw) { - static QCString vhdlkeyword("vhdlkeyword"); - static QCString vhdltype("keywordtype"); - static QCString vhdllogic("vhdllogic"); - static QCString preprocessor("keywordflow"); + std::string word=kw.lower().str(); - QCString word=tmp.lower(); + if (word.empty()) return 0; - if (word.isEmpty() || word.at(0)=='\0') return 0; + if (g_vhdlKeyWordSet0.find(word)!=g_vhdlKeyWordSet0.end()) + return "keywordflow"; - if (g_vhdlKeyDict0.find(word)) - return &preprocessor; + if (g_vhdlKeyWordSet1.find(word)!=g_vhdlKeyWordSet1.end()) + return "keywordtype"; - if (g_vhdlKeyDict1.find(word)) - return &vhdltype; + if (g_vhdlKeyWordSet2.find(word)!=g_vhdlKeyWordSet2.end()) + return "vhdllogic"; - if (g_vhdlKeyDict2.find(word)) - return &vhdllogic; - - if (g_vhdlKeyDict3.find(word)) - return &vhdlkeyword; + if (g_vhdlKeyWordSet3.find(word)!=g_vhdlKeyWordSet3.end()) + return "vhdlkeyword"; return 0; } @@ -693,21 +637,12 @@ QCString* VhdlDocGen::findKeyWord(const QCString& tmp) ClassDef *VhdlDocGen::getClass(const char *name) { if (name==0 || name[0]=='\0') return 0; - - ClassDef *cd=0; - QCString temp(name); - //temp=temp.lower(); - temp=temp.stripWhiteSpace(); - cd= Doxygen::classSDict->find(temp.data()); - return cd; + return Doxygen::classSDict->find(QCString(name).stripWhiteSpace()); } ClassDef* VhdlDocGen::getPackageName(const QCString & name) { - ClassDef* cd=0; - cd=getClass(name); - - return cd; + return getClass(name); } static QMap<QCString,MemberDef*> varMap; @@ -1272,7 +1207,6 @@ void VhdlDocGen::writeFormatString(const QCString& s,OutputList&ol,const MemberD QRegExp reg("[\\[\\]\\.\\/\\:\\<\\>\\:\\s\\,\\;\\'\\+\\-\\*\\|\\&\\=\\(\\)\"]"); QCString qcs = s; qcs+=QCString(" ");// parsing the last sign - QCString *ss; QCString find=qcs; QCString temp=qcs; char buf[2]; @@ -1289,7 +1223,7 @@ void VhdlDocGen::writeFormatString(const QCString& s,OutputList&ol,const MemberD { find=find.left(j); buf[0]=temp[j]; - ss=VhdlDocGen::findKeyWord(find); + const char *ss=VhdlDocGen::findKeyWord(find); bool k=isNumber(find); // is this a number if (k) { @@ -1299,7 +1233,7 @@ void VhdlDocGen::writeFormatString(const QCString& s,OutputList&ol,const MemberD } else if (j != 0 && ss) { - startFonts(find,ss->data(),ol); + startFonts(find,ss,ol); } else { @@ -1435,11 +1369,11 @@ void VhdlDocGen::writeProcedureProto(OutputList& ol,const ArgumentList &al,const nn+=": "; QCString defval = arg.defval; - QCString *str=VhdlDocGen::findKeyWord(defval); + const char *str=VhdlDocGen::findKeyWord(defval); defval+=" "; if (str) { - startFonts(defval,str->data(),ol); + startFonts(defval,str,ol); } else { @@ -1500,7 +1434,7 @@ void VhdlDocGen::writeFunctionProto(OutputList& ol,const ArgumentList &al,const } if (!att.isEmpty()) { - QCString *str=VhdlDocGen::findKeyWord(att); + const char *str=VhdlDocGen::findKeyWord(att); att+=" "; if (str) VhdlDocGen::formatString(att,ol,mdef); @@ -1514,7 +1448,7 @@ void VhdlDocGen::writeFunctionProto(OutputList& ol,const ArgumentList &al,const QCString w=ss.stripWhiteSpace();//.upper(); startFonts(nn,"vhdlchar",ol); startFonts("in ","stringliteral",ol); - QCString *str=VhdlDocGen::findKeyWord(ss); + const char *str=VhdlDocGen::findKeyWord(ss); if (str) VhdlDocGen::formatString(w,ol,mdef); else @@ -1717,7 +1651,7 @@ void VhdlDocGen::writeVhdlDeclarations(const MemberList* ml, } -void VhdlDocGen::correctMemberProperties(MemberDef *md) +void VhdlDocGen::correctMemberProperties(MemberDefMutable *md) { if (qstrcmp(md->argsString(),"package")==0) { @@ -1767,7 +1701,7 @@ void VhdlDocGen::correctMemberProperties(MemberDef *md) /* writes a vhdl type documentation */ bool VhdlDocGen::writeVHDLTypeDocumentation(const MemberDef* mdef, const Definition *d, OutputList &ol) { - const ClassDef *cd=dynamic_cast<const ClassDef*>(d); + const ClassDef *cd=toClassDef(d); bool hasParams = FALSE; if (cd==0) return hasParams; @@ -1849,7 +1783,7 @@ bool VhdlDocGen::writeVHDLTypeDocumentation(const MemberDef* mdef, const Definit return hasParams; } -void VhdlDocGen::writeTagFile(MemberDef *mdef,FTextStream &tagFile) +void VhdlDocGen::writeTagFile(MemberDefMutable *mdef,FTextStream &tagFile) { tagFile << " <member kind=\""; if (VhdlDocGen::isGeneric(mdef)) tagFile << "generic"; @@ -1893,7 +1827,7 @@ void VhdlDocGen::writeTagFile(MemberDef *mdef,FTextStream &tagFile) /* writes a vhdl type declaration */ -void VhdlDocGen::writeVHDLDeclaration(const MemberDef* mdef,OutputList &ol, +void VhdlDocGen::writeVHDLDeclaration(const MemberDefMutable* mdef,OutputList &ol, const ClassDef *cd,const NamespaceDef *nd,const FileDef *fd,const GroupDef *gd, bool /*inGroup*/) { @@ -2203,24 +2137,28 @@ void VhdlDocGen::writePlainVHDLDeclarations( pack.setAutoDelete(TRUE); bool first=TRUE; - MemberDef *md; + MemberDef *imd; MemberListIterator mli(*mlist); - for ( ; (md=mli.current()); ++mli ) + for ( ; (imd=mli.current()); ++mli ) { - int mems=md->getMemberSpecifiers(); - if (md->isBriefSectionVisible() && (mems==specifier) && (mems!=VhdlDocGen::LIBRARY) ) - { - if (first) { ol.startMemberList();first=FALSE; } - VhdlDocGen::writeVHDLDeclaration(md,ol,cd,nd,fd,gd,FALSE); - } //if - else if (md->isBriefSectionVisible() && (mems==specifier)) + MemberDefMutable *md = toMemberDefMutable(imd); + if (md) { - if (!pack.find(md->name().data())) + int mems=md->getMemberSpecifiers(); + if (md->isBriefSectionVisible() && (mems==specifier) && (mems!=VhdlDocGen::LIBRARY) ) { - if (first) ol.startMemberList(),first=FALSE; + if (first) { ol.startMemberList();first=FALSE; } VhdlDocGen::writeVHDLDeclaration(md,ol,cd,nd,fd,gd,FALSE); - pack.append(md->name().data(),new QCString(md->name().data())); - } + } //if + else if (md->isBriefSectionVisible() && (mems==specifier)) + { + if (!pack.find(md->name().data())) + { + if (first) ol.startMemberList(),first=FALSE; + VhdlDocGen::writeVHDLDeclaration(md,ol,cd,nd,fd,gd,FALSE); + pack.append(md->name().data(),new QCString(md->name().data())); + } + } //if } //if } //for if (!first) ol.endMemberList(); @@ -2354,9 +2292,9 @@ void VhdlDocGen::writeStringLink(const MemberDef *mdef,QCString mem, OutputList& -void VhdlDocGen::writeSource(const MemberDef *mdef,OutputList& ol,const QCString & cname) +void VhdlDocGen::writeSource(const MemberDefMutable *mdef,OutputList& ol,const QCString & cname) { - CodeParserInterface &intf = Doxygen::parserManager->getCodeParser(".vhd"); + auto intf = Doxygen::parserManager->getCodeParser(".vhd"); // pIntf->resetCodeParserState(); QCString codeFragment=mdef->documentation(); @@ -2381,8 +2319,8 @@ void VhdlDocGen::writeSource(const MemberDef *mdef,OutputList& ol,const QCString codeFragment.prepend("\n"); ol.pushGeneratorState(); - ol.startCodeFragment(); - intf.parseCode( ol, // codeOutIntf + ol.startCodeFragment("DoxyCode"); + intf->parseCode( ol, // codeOutIntf 0, // scope codeFragment, // input SrcLangExt_VHDL, // lang @@ -2396,7 +2334,7 @@ void VhdlDocGen::writeSource(const MemberDef *mdef,OutputList& ol,const QCString TRUE // show line numbers ); - ol.endCodeFragment(); + ol.endCodeFragment("DoxyCode"); ol.popGeneratorState(); if (cname.isEmpty()) return; @@ -2684,10 +2622,10 @@ void VhdlDocGen::computeVhdlComponentRelations() entity=cur->type; } - ClassDef *classEntity= VhdlDocGen::findVhdlClass(entity.data());//Doxygen::classSDict->find(entity); + ClassDefMutable *classEntity= toClassDefMutable(VhdlDocGen::findVhdlClass(entity.data())); inst=VhdlDocGen::getIndexWord(cur->args.data(),0); - ClassDef *cd=Doxygen::classSDict->find(inst); - ClassDef *ar=Doxygen::classSDict->find(cur->args); + ClassDefMutable *cd=toClassDefMutable(Doxygen::classSDict->find(inst)); + ClassDefMutable *ar=toClassDefMutable(Doxygen::classSDict->find(cur->args)); if (cd==0) { @@ -2702,8 +2640,8 @@ void VhdlDocGen::computeVhdlComponentRelations() } -static void addInstance(ClassDef* classEntity, ClassDef* ar, - ClassDef *cd , const std::shared_ptr<Entry> &cur) +static void addInstance(ClassDefMutable* classEntity, ClassDefMutable* ar, + ClassDefMutable *cd , const std::shared_ptr<Entry> &cur) { QCString bName,n1; @@ -2739,14 +2677,14 @@ static void addInstance(ClassDef* classEntity, ClassDef* ar, ferr: QCString uu=cur->name; - MemberDef *md=createMemberDef( + std::unique_ptr<MemberDefMutable> md { createMemberDef( ar->getDefFileName(), cur->startLine,cur->startColumn, n1,uu,uu, 0, Public, Normal, cur->stat,Member, MemberType_Variable, ArgumentList(), ArgumentList(), - ""); + "") }; if (ar->getOutputFileBase()) { @@ -2774,27 +2712,29 @@ ferr: //label.replace(epr,":"); //info+=label; //fprintf(stderr,"\n[%s:%d:%s]\n",fd->fileName().data(),cur->startLine,info.data()); - ar->insertMember(md); + ar->insertMember(md.get()); + MemberName *mn = Doxygen::functionNameLinkedMap->add(uu); + mn->push_back(std::move(md)); } -void VhdlDocGen::writeRecordUnit(QCString & largs,QCString & ltype,OutputList& ol ,const MemberDef *mdef) +void VhdlDocGen::writeRecordUnit(QCString & largs,QCString & ltype,OutputList& ol ,const MemberDefMutable *mdef) { - int i=mdef->name().find('~'); - if(i>0){ - //sets the real record member name - const_cast<MemberDef*>(mdef)->setName(mdef->name().left(i).data()); - } - - writeLink(mdef,ol); - ol.startBold(); - ol.insertMemberAlign(); - if (!ltype.isEmpty()){ - VhdlDocGen::formatString(ltype,ol,mdef); - } - ol.endBold(); + int i=mdef->name().find('~'); + if (i>0) + { + //sets the real record member name + const_cast<MemberDefMutable*>(mdef)->setName(mdef->name().left(i).data()); + } + writeLink(mdef,ol); + ol.startBold(); + ol.insertMemberAlign(); + if (!ltype.isEmpty()){ + VhdlDocGen::formatString(ltype,ol,mdef); + } + ol.endBold(); } @@ -2843,24 +2783,20 @@ bool VhdlDocGen::isSubClass(ClassDef* cd,ClassDef *scd, bool followInstances,int return FALSE; } - if (cd->subClasses()) + for (const auto &bcd :cd->subClasses()) { - BaseClassListIterator bcli(*cd->subClasses()); - for ( ; bcli.current() && !found ; ++bcli) + const ClassDef *ccd=bcd.classDef; + if (!followInstances && ccd->templateMaster()) ccd=ccd->templateMaster(); + //printf("isSubClass() subclass %s\n",ccd->name().data()); + if (ccd==scd) + { + found=TRUE; + } + else { - const ClassDef *ccd=bcli.current()->classDef; - if (!followInstances && ccd->templateMaster()) ccd=ccd->templateMaster(); - //printf("isSubClass() subclass %s\n",ccd->name().data()); - if (ccd==scd) + if (level <256) { - found=TRUE; - } - else - { - if (level <256) - { - found=ccd->isBaseClass(scd,followInstances,level+1); - } + found=ccd->isBaseClass(scd,followInstances,level+1); } } } @@ -2869,35 +2805,33 @@ bool VhdlDocGen::isSubClass(ClassDef* cd,ClassDef *scd, bool followInstances,int void VhdlDocGen::addBaseClass(ClassDef* cd,ClassDef *ent) { - if (cd->baseClasses()) + BaseClassList bcl = cd->baseClasses(); + for (auto &bcd : bcl) { - BaseClassListIterator bcli(*cd->baseClasses()); - for ( ; bcli.current() ; ++bcli) + ClassDef *ccd = bcd.classDef; + if (ccd==ent) { - ClassDef *ccd=bcli.current()->classDef; - if (ccd==ent) + QCString n = bcd.usedName; + int i = n.find('('); + if(i<0) { - QCString n = bcli.current()->usedName; - int i = n.find('('); - if(i<0) - { - bcli.current()->usedName.append("(2)"); - return; - } - static QRegExp reg("[0-9]+"); - QCString s=n.left(i); - QCString r=n.right(n.length()-i); - QCString t=r; - VhdlDocGen::deleteAllChars(r,')'); - VhdlDocGen::deleteAllChars(r,'('); - r.setNum(r.toInt()+1); - t.replace(reg,r.data()); - s.append(t.data()); - bcli.current()->usedName=s; - bcli.current()->templSpecifiers=t; + bcd.usedName.append("(2)"); + return; } - } - } + static QRegExp reg("[0-9]+"); + QCString s=n.left(i); + QCString r=n.right(n.length()-i); + QCString t=r; + VhdlDocGen::deleteAllChars(r,')'); + VhdlDocGen::deleteAllChars(r,'('); + r.setNum(r.toInt()+1); + t.replace(reg,r.data()); + s.append(t.data()); + bcd.usedName=s; + bcd.templSpecifiers=t; + } + } + cd->updateBaseClasses(bcl); } diff --git a/src/vhdldocgen.h b/src/vhdldocgen.h index 5442f88..b98ea44 100644 --- a/src/vhdldocgen.h +++ b/src/vhdldocgen.h @@ -31,6 +31,7 @@ class Entry; class ClassDef; class MemberList; class MemberDef; +class MemberDefMutable; class FTextStream; class OutputList; class Definition; @@ -129,7 +130,7 @@ class VhdlDocGen static void computeVhdlComponentRelations(); - static QCString* findKeyWord(const QCString& word); + static const char* findKeyWord(const QCString& word); static ClassDef* getPackageName(const QCString& name); static MemberDef* findMember(const QCString& className, @@ -144,7 +145,7 @@ class VhdlDocGen static QCString getClassTitle(const ClassDef*); static void writeInlineClassLink(const ClassDef*, OutputList &ol); - static void writeTagFile(MemberDef *mdef,FTextStream &tagFile); + static void writeTagFile(MemberDefMutable *mdef,FTextStream &tagFile); static bool isConstraint(const MemberDef *mdef); static bool isConfig(const MemberDef *mdef); @@ -190,7 +191,7 @@ class VhdlDocGen static void writeVhdlDeclarations(const MemberList*,OutputList&,const GroupDef*,const ClassDef*,const FileDef*,const NamespaceDef*); - static void writeVHDLDeclaration(const MemberDef* mdef,OutputList &ol, + static void writeVHDLDeclaration(const MemberDefMutable* mdef,OutputList &ol, const ClassDef *cd,const NamespaceDef *nd,const FileDef *fd,const GroupDef *gd, bool inGroup); @@ -217,9 +218,9 @@ class VhdlDocGen static ClassDef* findArchitecture(const ClassDef *cd); static ClassDef* findArchitecture(QCString identifier, QCString entity_name); - static void correctMemberProperties(MemberDef *md); + static void correctMemberProperties(MemberDefMutable *md); - static void writeSource(const MemberDef *mdef,OutputList& ol,const QCString & cname); + static void writeSource(const MemberDefMutable *mdef,OutputList& ol,const QCString & cname); static QCString parseForConfig(QCString & entity,QCString & arch); static QCString parseForBinding(QCString & entity,QCString & arch); @@ -252,7 +253,7 @@ class VhdlDocGen static void writeVhdlLink(const ClassDef* cdd ,OutputList& ol,QCString& type,QCString& name,QCString& beh); static void writeStringLink(const MemberDef *mdef,QCString mem,OutputList& ol); static void writeRecUnitDocu( const MemberDef *md, OutputList& ol,QCString largs); - static void writeRecordUnit(QCString & largs,QCString & ltype,OutputList& ol ,const MemberDef *mdef); + static void writeRecordUnit(QCString & largs,QCString & ltype,OutputList& ol,const MemberDefMutable *mdef); }; //------------------------------------------------------------------------------------------------------------------- diff --git a/src/vhdljjparser.cpp b/src/vhdljjparser.cpp index 7c83d52..4ca4bbe 100644 --- a/src/vhdljjparser.cpp +++ b/src/vhdljjparser.cpp @@ -114,7 +114,10 @@ void VHDLOutlineParser::Private::parseVhdlfile(const char *fileName, catch( std::exception &){ /* fprintf(stderr,"\n[%s]",e.what()); */ } // fprintf(stderr,"\n\nparsed lines: %d\n",yyLineNr); // fprintf(stderr,"\n\nerrors : %d\n\n",myErr->getErrorCount()); + // delete vhdlParser; + delete tokenManager; + delete stream; } VHDLOutlineParser::VHDLOutlineParser() : p(std::make_unique<Private>()) diff --git a/src/xmlcode.h b/src/xmlcode.h index 4cada9b..5a35506 100644 --- a/src/xmlcode.h +++ b/src/xmlcode.h @@ -1,12 +1,10 @@ /****************************************************************************** * - * - * - * Copyright (C) 1997-2014 by Dimitri van Heesch. + * Copyright (C) 1997-2020 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. * @@ -32,6 +30,8 @@ class Definition; class XMLCodeParser : public CodeParserInterface { public: + XMLCodeParser(); + virtual ~XMLCodeParser(); void parseCode(CodeOutputInterface &codeOutIntf, const char *scopeName, const QCString &input, @@ -48,6 +48,9 @@ class XMLCodeParser : public CodeParserInterface bool collectXRefs=TRUE ); void resetCodeParserState(); + private: + struct Private; + std::unique_ptr<Private> p; }; diff --git a/src/xmlcode.l b/src/xmlcode.l index b583bf5..c7322cb 100644 --- a/src/xmlcode.l +++ b/src/xmlcode.l @@ -1,10 +1,10 @@ /****************************************************************************** * - * Copyright (C) 1997-2014 by Dimitri van Heesch. + * Copyright (C) 1997-2020 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. * @@ -19,6 +19,11 @@ %option never-interactive %option prefix="xmlcodeYY" +%option reentrant +%option extra-type="struct xmlcodeYY_state *" +%option noyy_top_state +%option nounput +%option noyywrap %top{ #include <stdint.h> } @@ -44,401 +49,430 @@ #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 const 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; +struct xmlcodeYY_state +{ + CodeOutputInterface * code; + QCString curClassName; + QCString parmType; + QCString parmName; + const char * inputString = 0; //!< the code fragment as text + yy_size_t inputPosition = 0; //!< read offset during parsing + int inputLines = 0; //!< number of line in the code fragment + int yyLineNr = 0; //!< current line number + bool needsTermination = false; + const Definition *searchCtx = 0; + + bool exampleBlock = false; + QCString exampleName; + QCString exampleFile; + + QCString type; + QCString name; + QCString args; + QCString classScope; + + QCString CurrScope; + + const FileDef * sourceFileDef = 0; + const Definition * currentDefinition = 0; + const MemberDef * currentMemberDef = 0; + bool includeCodeFragment = false; + const char * currentFontClass = 0; +}; #if USE_STATE2STRING static const char *stateToString(int state); #endif -static void codify(const char* text) -{ - g_code->codify(text); +static void codify(yyscan_t yyscanner,const char* text); +static void setCurrentDoc(yyscan_t yyscanner,const QCString &anchor); +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(yyscan_t yyscanner,const char *text); +static void startFontClass(yyscan_t yyscanner,const char *s); +static int countLines(yyscan_t yyscanner); +static yy_size_t yyread(yyscan_t yyscanner,char *buf,yy_size_t max_size); + +#undef YY_INPUT +#define YY_INPUT(buf,result,max_size) result=yyread(yyscanner,buf,max_size); + +%} + +nl (\r\n|\r|\n) +ws [ \t]+ +open "<" +close ">" +namestart [A-Za-z\200-\377_] +namechar [:A-Za-z\200-\377_0-9.-] +esc "&#"[0-9]+";"|"&#x"[0-9a-fA-F]+";" +name {namestart}{namechar}* +comment {open}"!--"([^-]|"-"[^-])*"--"{close} +data "random string" +string \"([^"&]|{esc})*\"|\'([^'&]|{esc})*\' + +%option noyywrap +%option nounput + +%% + +<INITIAL>{ws} { + codifyLines(yyscanner,yytext); + } +<INITIAL>"/" { + endFontClass(yyscanner); + codify(yyscanner,yytext); + } +<INITIAL>"=" { + endFontClass(yyscanner); + codify(yyscanner,yytext); + } +<INITIAL>{close} { + endFontClass(yyscanner); + codify(yyscanner,yytext); + } +<INITIAL>{name} { + startFontClass(yyscanner,"keyword"); + codify(yyscanner,yytext); + endFontClass(yyscanner); + } +<INITIAL>{string} { + startFontClass(yyscanner,"stringliteral"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + } + +{open}{ws}?{name} { + // Write the < in a different color + char openBracket[] = { yytext[0], '\0' }; + codify(yyscanner,openBracket); + + // Then write the rest + yytext++; + startFontClass(yyscanner,"keywordtype"); + codify(yyscanner,yytext); + endFontClass(yyscanner); + + BEGIN(INITIAL); + } +{open}{ws}?"/"{name} { + // Write the "</" in a different color + char closeBracket[] = { yytext[0], yytext[1], '\0' }; + endFontClass(yyscanner); + codify(yyscanner,closeBracket); + + // Then write the rest + yytext++; // skip the '<' + yytext++; // skip the '/' + startFontClass(yyscanner,"keywordtype"); + codify(yyscanner,yytext); + endFontClass(yyscanner); + + BEGIN(INITIAL); + } +{comment} { + // Strip off the extra '!' + // yytext++; // < + // *yytext = '<'; // replace '!' with '<' + + startFontClass(yyscanner,"comment"); + codifyLines(yyscanner,yytext); + endFontClass(yyscanner); + } +{nl} { + codifyLines(yyscanner,yytext); + } + +. { + //printf("!ERROR(%c)\n", *yytext); + codifyLines(yyscanner,yytext); + } + +%% + +//---------------------------------------------------------------------------------------- + +static yy_size_t yyread(yyscan_t yyscanner,char *buf,size_t max_size) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + yy_size_t inputPosition = yyextra->inputPosition; + const char *s = yyextra->inputString + inputPosition; + yy_size_t c=0; + while( c < max_size && *s) + { + *buf++ = *s++; + c++; + } + yyextra->inputPosition += c; + return c; +} + +static void codify(yyscan_t yyscanner,const char* text) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + yyextra->code->codify(text); } -static void setCurrentDoc(const QCString &anchor) +static void setCurrentDoc(yyscan_t yyscanner,const QCString &anchor) { + 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); + yyextra->code->setCurrentDoc(yyextra->searchCtx,yyextra->searchCtx->anchor(),false); } else { - Doxygen::searchIndex->setCurrentDoc(g_sourceFileDef,anchor,TRUE); + yyextra->code->setCurrentDoc(yyextra->sourceFileDef,anchor,true); } } } -/*! start a new line of code, inserting a line number if g_sourceFileDef - * is TRUE. If a definition starts at the current line, then the line +/*! 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) - { - Definition *d = g_sourceFileDef->getSourceDefinition(g_yyLineNr); - - if (!g_includeCodeFragment && d && d->isLinkableInProject()) + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + if (yyextra->sourceFileDef) + { + Definition *d = yyextra->sourceFileDef->getSourceDefinition(yyextra->yyLineNr); + + if (!yyextra->includeCodeFragment && d && d->isLinkableInProject()) { - g_currentDefinition = d; - g_currentMemberDef = g_sourceFileDef->getSourceMember(g_yyLineNr); - //g_insideBody = FALSE; - g_classScope = d->name().copy(); + yyextra->currentDefinition = d; + yyextra->currentMemberDef = yyextra->sourceFileDef->getSourceMember(yyextra->yyLineNr); + //yyextra->insideBody = false; + 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(yyscanner,lineAnchor); } else { - g_code->writeLineNumber(d->getReference(), + yyextra->code->writeLineNumber(d->getReference(), d->getOutputFileBase(), - 0,g_yyLineNr); - setCurrentDoc(lineAnchor); + 0,yyextra->yyLineNr); + setCurrentDoc(yyscanner,lineAnchor); } } else { - g_code->writeLineNumber(0,0,0,g_yyLineNr); + yyextra->code->writeLineNumber(0,0,0,yyextra->yyLineNr); } } - - g_code->startCodeLine(g_sourceFileDef); - - if (g_currentFontClass) + + yyextra->code->startCodeLine(yyextra->sourceFileDef); + + 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(yyscan_t yyscanner,const char *text) { - char *p=text,*sp=p; + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + const char *p=text,*sp=p; char c; - bool done=FALSE; - + bool done=false; while (!done) { sp=p; - while ((c=*p++) && c!='\n') { } - if (c=='\n') { - g_yyLineNr++; - *(p-1)='\0'; - g_code->codify(sp); - nextCodeLine(); + yyextra->yyLineNr++; + int l = (int)(p-sp-1); + char *tmp = (char*)malloc(l+1); + tmp[l]='\0'; + yyextra->code->codify(tmp); + free(tmp); + nextCodeLine(yyscanner); } else { - g_code->codify(sp); - done=TRUE; + yyextra->code->codify(sp); + done=true; } } } -static void startFontClass(const char *s) +static void startFontClass(yyscan_t yyscanner,const char *s) { - 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)) - { - p++ ; - if (c=='\n') count++; + while ((c=*p)) + { + 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; - } + count++, + 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) +struct XMLCodeParser::Private { - int c=0; - while( c < max_size && g_inputString[g_inputPosition] ) - { - *buf = g_inputString[g_inputPosition++] ; - c++; buf++; - } - return c; -} - -%} + yyscan_t yyscanner; + xmlcodeYY_state state; +}; -nl (\r\n|\r|\n) -ws [ \t]+ -open "<" -close ">" -namestart [A-Za-z\200-\377_] -namechar [:A-Za-z\200-\377_0-9.-] -esc "&#"[0-9]+";"|"&#x"[0-9a-fA-F]+";" -name {namestart}{namechar}* -comment {open}"!--"([^-]|"-"[^-])*"--"{close} -data "random string" -string \"([^"&]|{esc})*\"|\'([^'&]|{esc})*\' - -%option noyywrap -%option nounput +XMLCodeParser::XMLCodeParser() : p(std::make_unique<Private>()) +{ + xmlcodeYYlex_init_extra(&p->state,&p->yyscanner); +#ifdef FLEX_DEBUG + xmlcodeYYset_debug(1,yyscanner); +#endif + resetCodeParserState(); +} -%% +XMLCodeParser::~XMLCodeParser() +{ + xmlcodeYYlex_destroy(p->yyscanner); +} -<INITIAL>{ws} { - codifyLines(yytext); - } -<INITIAL>"/" { - endFontClass(); - codify(yytext); - } -<INITIAL>"=" { - endFontClass(); - codify(yytext); - } -<INITIAL>{close} { - endFontClass(); - codify(yytext); - } -<INITIAL>{name} { - startFontClass("keyword"); - codify(yytext); - endFontClass(); - } -<INITIAL>{string} { - startFontClass("stringliteral"); - codifyLines(yytext); - endFontClass(); - } - -{open}{ws}?{name} { - // Write the < in a different color - char openBracket[] = { yytext[0], '\0' }; - codify(openBracket); - - // Then write the rest - yytext++; - startFontClass("keywordtype"); - codify(yytext); - endFontClass(); - - BEGIN(INITIAL); - } -{open}{ws}?"/"{name} { - // Write the "</" in a different color - char closeBracket[] = { yytext[0], yytext[1], '\0' }; - endFontClass(); - codify(closeBracket); - - // Then write the rest - yytext++; // skip the '<' - yytext++; // skip the '/' - startFontClass("keywordtype"); - codify(yytext); - endFontClass(); +void XMLCodeParser::resetCodeParserState() +{ + struct yyguts_t *yyg = (struct yyguts_t*)p->yyscanner; + yyextra->currentDefinition = 0; + yyextra->currentMemberDef = 0; +} - BEGIN(INITIAL); - } -{comment} { - // Strip off the extra '!' - // yytext++; // < - // *yytext = '<'; // replace '!' with '<' +void XMLCodeParser::parseCode(CodeOutputInterface &codeOutIntf, + const char *scopeName, + const QCString &input, + SrcLangExt, + bool isExampleBlock, + const char *exampleName, + FileDef *fileDef, + int startLine, + int endLine, + bool inlineFragment, + const MemberDef *memberDef, + bool showLineNumbers, + const Definition *searchCtx, + bool collectXRefs + ) +{ + yyscan_t yyscanner = p->yyscanner; + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; - startFontClass("comment"); - codifyLines(yytext); - endFontClass(); - } -{nl} { - codifyLines(yytext); - } + if (input.isEmpty()) return; -. { - //printf("!ERROR(%c)\n", *yytext); - codifyLines(yytext); - } + printlex(yy_flex_debug, true, __FILE__, fileDef ? fileDef->fileName().data(): NULL); -%% + yyextra->code = &codeOutIntf; + yyextra->inputString = input; + yyextra->inputPosition = 0; + yyextra->currentFontClass = 0; + yyextra->needsTermination = false; + yyextra->searchCtx = searchCtx; -void parseXmlCode( - CodeOutputInterface &od, - const char * /*className*/, - const QCString &s, - bool exBlock, - const char *exName, - FileDef *fd, - int startLine, - int endLine, - bool inlineFragment, - 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; - g_inputPosition = 0; - g_currentFontClass = 0; - g_needsTermination = FALSE; - g_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; - - g_exampleBlock = exBlock; - g_exampleName = exName; - g_sourceFileDef = fd; - - bool cleanupSourceDef = FALSE; - - if (exBlock && fd==0) + yyextra->inputLines = yyextra->yyLineNr + countLines(yyscanner) - 1; + + yyextra->exampleBlock = isExampleBlock; + yyextra->exampleName = exampleName; + yyextra->sourceFileDef = fileDef; + + bool cleanupSourceDef = false; + + if (isExampleBlock && fileDef==0) { // create a dummy filedef for the example - g_sourceFileDef = createFileDef("",(exName?exName:"generated")); - cleanupSourceDef = TRUE; + yyextra->sourceFileDef = createFileDef("",(exampleName?exampleName:"generated")); + cleanupSourceDef = true; } - - if (g_sourceFileDef) + + if (yyextra->sourceFileDef) { - setCurrentDoc("l00001"); + setCurrentDoc(yyscanner,"l00001"); } - g_includeCodeFragment = inlineFragment; - // Starts line 1 on the output - startCodeLine(); + yyextra->includeCodeFragment = inlineFragment; + // Starts line 1 on the output + startCodeLine(yyscanner); - xmlcodeYYrestart( xmlcodeYYin ); + xmlcodeYYrestart( 0, yyscanner ); - xmlcodeYYlex(); + xmlcodeYYlex(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); - return; -} - -void resetXmlCodeParserState() -{ - g_currentDefinition = 0; - g_currentMemberDef = 0; -} - -//---------------------------------------------------------------------------- -void XMLCodeParser::parseCode(CodeOutputInterface &codeOutIntf, - const char *scopeName, - const QCString &input, - SrcLangExt, - bool isExampleBlock, - const char *exampleName, - FileDef *fileDef, - int startLine, - int endLine, - bool inlineFragment, - const MemberDef *memberDef, - bool showLineNumbers, - const Definition *searchCtx, - bool collectXRefs - ) -{ - parseXmlCode(codeOutIntf,scopeName,input,isExampleBlock,exampleName, - fileDef,startLine,endLine,inlineFragment,memberDef, - showLineNumbers,searchCtx,collectXRefs); + printlex(yy_flex_debug, false, __FILE__, fileDef ? fileDef->fileName().data(): NULL); } -void XMLCodeParser::resetCodeParserState() -{ - resetXmlCodeParserState(); -} #if USE_STATE2STRING #include "xmlcode.l.h" diff --git a/src/xmldocvisitor.cpp b/src/xmldocvisitor.cpp index 045f87c..73aac7c 100644 --- a/src/xmldocvisitor.cpp +++ b/src/xmldocvisitor.cpp @@ -252,9 +252,8 @@ void XmlDocVisitor::visit(DocVerbatim *s) m_t << " filename=\"" << lang << "\">"; else m_t << ">"; - Doxygen::parserManager->getCodeParser(lang) - .parseCode(m_ci,s->context(),s->text(),langExt, - s->isExample(),s->exampleFile()); + getCodeParser(lang).parseCode(m_ci,s->context(),s->text(),langExt, + s->isExample(),s->exampleFile()); m_t << "</programlisting>"; break; case DocVerbatim::Verbatim: @@ -332,8 +331,7 @@ void XmlDocVisitor::visit(DocInclude *inc) m_t << "<programlisting filename=\"" << inc->file() << "\">"; QFileInfo cfi( inc->file() ); FileDef *fd = createFileDef( cfi.dirPath().utf8(), cfi.fileName().utf8() ); - Doxygen::parserManager->getCodeParser(inc->extension()) - .parseCode(m_ci,inc->context(), + getCodeParser(inc->extension()).parseCode(m_ci,inc->context(), inc->text(), langExt, inc->isExample(), @@ -351,8 +349,7 @@ void XmlDocVisitor::visit(DocInclude *inc) break; case DocInclude::Include: m_t << "<programlisting filename=\"" << inc->file() << "\">"; - Doxygen::parserManager->getCodeParser(inc->extension()) - .parseCode(m_ci,inc->context(), + getCodeParser(inc->extension()).parseCode(m_ci,inc->context(), inc->text(), langExt, inc->isExample(), @@ -411,8 +408,7 @@ void XmlDocVisitor::visit(DocInclude *inc) break; case DocInclude::Snippet: m_t << "<programlisting filename=\"" << inc->file() << "\">"; - Doxygen::parserManager->getCodeParser(inc->extension()) - .parseCode(m_ci, + getCodeParser(inc->extension()).parseCode(m_ci, inc->context(), extractBlock(inc->text(),inc->blockId()), langExt, @@ -426,8 +422,7 @@ void XmlDocVisitor::visit(DocInclude *inc) m_t << "<programlisting filename=\"" << inc->file() << "\">"; QFileInfo cfi( inc->file() ); FileDef *fd = createFileDef( cfi.dirPath().utf8(), cfi.fileName().utf8() ); - Doxygen::parserManager->getCodeParser(inc->extension()) - .parseCode(m_ci, + getCodeParser(inc->extension()).parseCode(m_ci, inc->context(), extractBlock(inc->text(),inc->blockId()), langExt, @@ -480,17 +475,16 @@ void XmlDocVisitor::visit(DocIncOperator *op) fd = createFileDef( cfi.dirPath().utf8(), cfi.fileName().utf8() ); } - Doxygen::parserManager->getCodeParser(locLangExt) - .parseCode(m_ci,op->context(), - op->text(),langExt,op->isExample(), - op->exampleFile(), - fd, // fileDef - op->line(), // startLine - -1, // endLine - FALSE, // inline fragment - 0, // memberDef - op->showLineNo() // show line numbers - ); + getCodeParser(locLangExt).parseCode(m_ci,op->context(), + op->text(),langExt,op->isExample(), + op->exampleFile(), + fd, // fileDef + op->line(), // startLine + -1, // endLine + FALSE, // inline fragment + 0, // memberDef + op->showLineNo() // show line numbers + ); if (fd) delete fd; } pushEnabled(); diff --git a/src/xmlgen.cpp b/src/xmlgen.cpp index 19f1553..1993c1e 100644 --- a/src/xmlgen.cpp +++ b/src/xmlgen.cpp @@ -226,6 +226,7 @@ class TextGeneratorXMLImpl : public TextGeneratorIntf FTextStream &m_t; }; +//------------------------------------------------------------------------------------------- /** Generator for producing XML formatted source code. */ void XMLCodeGenerator::codify(const char *text) @@ -340,6 +341,18 @@ void XMLCodeGenerator::finish() if (m_insideCodeLine) endCodeLine(); } +void XMLCodeGenerator::startCodeFragment(const char *) +{ + m_t << " <programlisting>" << endl; +} + +void XMLCodeGenerator::endCodeFragment(const char *) +{ + m_t << " </programlisting>" << endl; +} + +//------------------------------------------------------------------------------------------- + static void writeTemplateArgumentList(FTextStream &t, const ArgumentList &al, const Definition *scope, @@ -420,11 +433,12 @@ static void writeXMLDocBlock(FTextStream &t, void writeXMLCodeBlock(FTextStream &t,FileDef *fd) { - CodeParserInterface &intf=Doxygen::parserManager->getCodeParser(fd->getDefFileExtension()); + auto intf=Doxygen::parserManager->getCodeParser(fd->getDefFileExtension()); SrcLangExt langExt = getLanguageFromFileName(fd->getDefFileExtension()); - intf.resetCodeParserState(); + intf->resetCodeParserState(); XMLCodeGenerator *xmlGen = new XMLCodeGenerator(t); - intf.parseCode(*xmlGen, // codeOutIntf + xmlGen->startCodeFragment("DoxyCode"); + intf->parseCode(*xmlGen, // codeOutIntf 0, // scopeName fileToString(fd->absFilePath(),Config_getBool(FILTER_SOURCE_FILES)), langExt, // lang @@ -437,6 +451,7 @@ void writeXMLCodeBlock(FTextStream &t,FileDef *fd) 0, // memberDef TRUE // showLineNumbers ); + xmlGen->endCodeFragment("DoxyCode"); xmlGen->finish(); delete xmlGen; } @@ -1006,23 +1021,15 @@ static void generateXMLForMember(const MemberDef *md,FTextStream &ti,FTextStream } //printf("md->getReferencesMembers()=%p\n",md->getReferencesMembers()); - MemberSDict *mdict = md->getReferencesMembers(); - if (mdict) + auto refList = md->getReferencesMembers(); + for (const auto &refmd : refList) { - MemberSDict::Iterator mdi(*mdict); - for (mdi.toFirst();(rmd=mdi.current());++mdi) - { - writeMemberReference(t,def,rmd,"references"); - } + writeMemberReference(t,def,refmd,"references"); } - mdict = md->getReferencedByMembers(); - if (mdict) + auto refByList = md->getReferencedByMembers(); + for (const auto &refmd : refByList) { - MemberSDict::Iterator mdi(*mdict); - for (mdi.toFirst();(rmd=mdi.current());++mdi) - { - writeMemberReference(t,def,rmd,"referencedby"); - } + writeMemberReference(t,def,refmd,"referencedby"); } t << " </memberdef>" << endl; @@ -1279,73 +1286,63 @@ static void generateXMLForClass(const ClassDef *cd,FTextStream &ti) t << " <compoundname>"; writeXMLString(t,cd->name()); t << "</compoundname>" << endl; - if (cd->baseClasses()) + for (const auto &bcd : cd->baseClasses()) { - BaseClassListIterator bcli(*cd->baseClasses()); - BaseClassDef *bcd; - for (bcli.toFirst();(bcd=bcli.current());++bcli) + t << " <basecompoundref "; + if (bcd.classDef->isLinkable()) { - t << " <basecompoundref "; - if (bcd->classDef->isLinkable()) - { - t << "refid=\"" << classOutputFileBase(bcd->classDef) << "\" "; - } - t << "prot=\""; - switch (bcd->prot) - { - case Public: t << "public"; break; - case Protected: t << "protected"; break; - case Private: t << "private"; break; - case Package: ASSERT(0); break; - } - t << "\" virt=\""; - switch(bcd->virt) - { - case Normal: t << "non-virtual"; break; - case Virtual: t << "virtual"; break; - case Pure: t <<"pure-virtual"; break; - } - t << "\">"; - if (!bcd->templSpecifiers.isEmpty()) - { - t << convertToXML( - insertTemplateSpecifierInScope( - bcd->classDef->name(),bcd->templSpecifiers) - ); - } - else - { - t << convertToXML(bcd->classDef->displayName()); - } - t << "</basecompoundref>" << endl; + t << "refid=\"" << classOutputFileBase(bcd.classDef) << "\" "; + } + t << "prot=\""; + switch (bcd.prot) + { + case Public: t << "public"; break; + case Protected: t << "protected"; break; + case Private: t << "private"; break; + case Package: ASSERT(0); break; } + t << "\" virt=\""; + switch(bcd.virt) + { + case Normal: t << "non-virtual"; break; + case Virtual: t << "virtual"; break; + case Pure: t <<"pure-virtual"; break; + } + t << "\">"; + if (!bcd.templSpecifiers.isEmpty()) + { + t << convertToXML( + insertTemplateSpecifierInScope( + bcd.classDef->name(),bcd.templSpecifiers) + ); + } + else + { + t << convertToXML(bcd.classDef->displayName()); + } + t << "</basecompoundref>" << endl; } - if (cd->subClasses()) + for (const auto &bcd : cd->subClasses()) { - BaseClassListIterator bcli(*cd->subClasses()); - BaseClassDef *bcd; - for (bcli.toFirst();(bcd=bcli.current());++bcli) + t << " <derivedcompoundref refid=\"" + << classOutputFileBase(bcd.classDef) + << "\" prot=\""; + switch (bcd.prot) { - t << " <derivedcompoundref refid=\"" - << classOutputFileBase(bcd->classDef) - << "\" prot=\""; - switch (bcd->prot) - { - case Public: t << "public"; break; - case Protected: t << "protected"; break; - case Private: t << "private"; break; - case Package: ASSERT(0); break; - } - t << "\" virt=\""; - switch(bcd->virt) - { - case Normal: t << "non-virtual"; break; - case Virtual: t << "virtual"; break; - case Pure: t << "pure-virtual"; break; - } - t << "\">" << convertToXML(bcd->classDef->displayName()) - << "</derivedcompoundref>" << endl; + case Public: t << "public"; break; + case Protected: t << "protected"; break; + case Private: t << "private"; break; + case Package: ASSERT(0); break; + } + t << "\" virt=\""; + switch (bcd.virt) + { + case Normal: t << "non-virtual"; break; + case Virtual: t << "virtual"; break; + case Pure: t << "pure-virtual"; break; } + t << "\">" << convertToXML(bcd.classDef->displayName()) + << "</derivedcompoundref>" << endl; } IncludeInfo *ii=cd->includeInfo(); @@ -1639,9 +1636,7 @@ static void generateXMLForFile(FileDef *fd,FTextStream &ti) t << " </detaileddescription>" << endl; if (Config_getBool(XML_PROGRAMLISTING)) { - t << " <programlisting>" << endl; writeXMLCodeBlock(t,fd); - t << " </programlisting>" << endl; } t << " <location file=\"" << convertToXML(stripFromPath(fd->getDefFileName())) << "\"/>" << endl; t << " </compounddef>" << endl; diff --git a/src/xmlgen.h b/src/xmlgen.h index 4458b9f..27bb10b 100644 --- a/src/xmlgen.h +++ b/src/xmlgen.h @@ -1,12 +1,10 @@ /****************************************************************************** * - * - * - * Copyright (C) 1997-2015 by Dimitri van Heesch. + * Copyright (C) 1997-2020 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. * @@ -41,6 +39,8 @@ class XMLCodeGenerator : public CodeOutputInterface const char *anchorId,int l); void setCurrentDoc(const Definition *,const char *,bool){} void addWord(const char *,bool){} + void startCodeFragment(const char *); + void endCodeFragment(const char *); void finish(); |