diff options
Diffstat (limited to 'src')
45 files changed, 693 insertions, 485 deletions
diff --git a/src/clangparser.cpp b/src/clangparser.cpp index 7e97473..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() { @@ -133,7 +134,6 @@ class ClangTUParser::Private CXToken *tokens = 0; uint numTokens = 0; StringVector filesInSameTU; - TooltipManager tooltipManager; // state while parsing sources MemberDef *currentMemberDef=0; @@ -573,7 +573,7 @@ void ClangTUParser::writeMultiLineCodeLink(CodeOutputInterface &ol, const char *text) { static bool sourceTooltips = Config_getBool(SOURCE_TOOLTIPS); - p->tooltipManager.addTooltip(d); + TooltipManager::instance().addTooltip(ol,d); QCString ref = d->getReference(); QCString file = d->getOutputFileBase(); QCString anchor = d->anchor(); @@ -696,6 +696,7 @@ void ClangTUParser::linkIdentifier(CodeOutputInterface &ol,FileDef *fd, p->currentMemberDef && d->definitionType()==Definition::TypeMember && (p->currentMemberDef!=d || p->currentLine<line)) // avoid self-reference { + std::lock_guard<std::mutex> lock(g_docCrossReferenceMutex); addDocCrossReference(toMemberDefMutable(p->currentMemberDef),toMemberDefMutable(d)); } writeMultiLineCodeLink(ol,fd,line,column,d,text); diff --git a/src/classdef.cpp b/src/classdef.cpp index 572b550..9586731 100644 --- a/src/classdef.cpp +++ b/src/classdef.cpp @@ -54,6 +54,109 @@ //----------------------------------------------------------------------------- +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 DefinitionMixin<ClassDefMutable> @@ -314,7 +417,7 @@ class ClassDefAliasImpl : public DefinitionAliasMixin<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 @@ -373,7 +476,7 @@ class ClassDefAliasImpl : public DefinitionAliasMixin<ClassDef> { 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 @@ -472,7 +575,11 @@ class ClassDefAliasImpl : public DefinitionAliasMixin<ClassDef> 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; } //----------------------------------------------------------------------------- @@ -747,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 @@ -1144,7 +1214,7 @@ void ClassDefImpl::computeAnchors() { if ((ml->listType()&MemberListType_detailedLists)==0) { - setAnchors(ml); + ml->setAnchors(); } } @@ -4138,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=toClassDef(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 @@ -175,7 +175,6 @@ struct codeYY_state VariableContext theVarContext; CallContext theCallContext; - TooltipManager tooltipManager; SymbolResolver symbolResolver; }; @@ -245,6 +244,8 @@ 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; /* ----------------------------------------------------------------- */ @@ -2448,6 +2449,7 @@ 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()) { @@ -2469,7 +2471,7 @@ static void writeMultiLineCodeLink(yyscan_t yyscanner,CodeOutputInterface &ol, { struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; bool sourceTooltips = Config_getBool(SOURCE_TOOLTIPS); - yyextra->tooltipManager.addTooltip(d); + TooltipManager::instance().addTooltip(ol,d); QCString ref = d->getReference(); QCString file = d->getOutputFileBase(); QCString anchor = d->anchor(); @@ -2734,6 +2736,7 @@ 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(), @@ -2900,6 +2903,7 @@ static void generateClassOrGlobalLink(yyscan_t yyscanner, 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(), @@ -2990,6 +2994,7 @@ 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(), @@ -3886,7 +3891,7 @@ void CCodeParser::parseCode(CodeOutputInterface &od,const char *className,const yyextra->sourceFileDef=0; } // write the tooltips - yyextra->tooltipManager.writeTooltips(od); + TooltipManager::instance().writeTooltips(od); printlex(yy_flex_debug, FALSE, __FILE__, fd ? fd->fileName().data(): NULL); return; diff --git a/src/commentscan.l b/src/commentscan.l index ccf71f6..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 @@ -887,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 } @@ -2827,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); diff --git a/src/context.cpp b/src/context.cpp index fc8833d..074e6ec 100644 --- a/src/context.cpp +++ b/src/context.cpp @@ -3802,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) { @@ -3817,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; } } } diff --git a/src/definition.cpp b/src/definition.cpp index 615506f..b719388 100644 --- a/src/definition.cpp +++ b/src/definition.cpp @@ -2137,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; } @@ -2178,8 +2178,8 @@ void DefinitionImpl::writeSummaryLinks(OutputList &) const //--------------------------------------------------------------------------------- -DefinitionAliasImpl::DefinitionAliasImpl(Definition *def,const Definition *alias) - : m_def(def), m_symbolName(alias->_symbolName()) +DefinitionAliasImpl::DefinitionAliasImpl(Definition *def,const Definition *scope, const Definition *alias) + : m_def(def), m_scope(scope), m_symbolName(alias->_symbolName()) { } @@ -2198,6 +2198,26 @@ 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) diff --git a/src/definition.h b/src/definition.h index 50a481d..204e6f6 100644 --- a/src/definition.h +++ b/src/definition.h @@ -108,7 +108,7 @@ class 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 diff --git a/src/definitionimpl.h b/src/definitionimpl.h index 710611e..e455dc4 100644 --- a/src/definitionimpl.h +++ b/src/definitionimpl.h @@ -33,7 +33,7 @@ class DefinitionImpl bool isSymbol=TRUE); virtual ~DefinitionImpl(); - const QCString &name() const; + QCString name() const; bool isAnonymous() const; QCString localName() const; QCString qualifiedName() const; @@ -150,7 +150,9 @@ class DefinitionMixin : public Base virtual ~DefinitionMixin() {} virtual bool isAlias() const { return FALSE; } - virtual const QCString &name() const { return m_impl.name(); } + + //======== 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(); } @@ -198,6 +200,7 @@ class DefinitionMixin : public Base 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) @@ -292,13 +295,17 @@ class DefinitionMixin : public Base class DefinitionAliasImpl { public: - DefinitionAliasImpl(Definition *def,const Definition *alias); + 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> @@ -306,7 +313,7 @@ class DefinitionAliasMixin : public Base { public: DefinitionAliasMixin(const Definition *scope,const Definition *alias) - : m_impl(this,alias), m_scope(scope), m_alias(alias), m_cookie(0) {} + : m_impl(this,scope,alias), m_scope(scope), m_alias(alias), m_cookie(0) {} void init() { m_impl.init(); } void deinit() { m_impl.deinit(); } @@ -314,14 +321,16 @@ class DefinitionAliasMixin : public Base virtual ~DefinitionAliasMixin() = default; virtual bool isAlias() const { return TRUE; } - virtual const QCString &name() const - { return m_alias->name(); } + + //======== Definition + virtual QCString name() const + { return m_impl.name(); } virtual bool isAnonymous() const { return m_alias->isAnonymous(); } virtual QCString localName() const { return m_alias->localName(); } virtual QCString qualifiedName() const - { return m_alias->qualifiedName(); } + { return m_impl.qualifiedName(); } virtual QCString symbolName() const { return m_alias->symbolName(); } virtual QCString getSourceFileBase() const diff --git a/src/docbookgen.cpp b/src/docbookgen.cpp index b25a43c..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; } } } @@ -296,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; @@ -525,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; @@ -533,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; } @@ -552,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; @@ -563,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; @@ -654,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 = diff --git a/src/docbookgen.h b/src/docbookgen.h index 112d0a0..214ec97 100644 --- a/src/docbookgen.h +++ b/src/docbookgen.h @@ -136,13 +136,13 @@ class DocbookGenerator : public OutputGenerator { 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(); diff --git a/src/doxygen.cpp b/src/doxygen.cpp index 6c8c67a..4667cba 100644 --- a/src/doxygen.cpp +++ b/src/doxygen.cpp @@ -1607,6 +1607,7 @@ static void buildNamespaceList(const Entry *root) 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); } } } @@ -9837,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" 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 c2020e1..68c2218 100644 --- a/src/filedef.cpp +++ b/src/filedef.cpp @@ -55,7 +55,7 @@ class FileDefImpl : public DefinitionMixin<FileDef> 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; } @@ -288,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() @@ -1435,7 +1435,7 @@ void FileDefImpl::insertNamespace(NamespaceDef *nd) } } -const QCString &FileDefImpl::name() const +QCString FileDefImpl::name() const { if (Config_getBool(FULL_PATH_NAMES)) return m_fileName; diff --git a/src/filedef.h b/src/filedef.h index ac3d729..055078f 100644 --- a/src/filedef.h +++ b/src/filedef.h @@ -79,7 +79,7 @@ class FileDef : public DefinitionMutable, 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; diff --git a/src/fortrancode.l b/src/fortrancode.l index 0de7b84..1c1287d 100644 --- a/src/fortrancode.l +++ b/src/fortrancode.l @@ -172,7 +172,6 @@ struct fortrancodeYY_state int inTypeDecl = 0; bool endComment = false; - TooltipManager tooltipManager; }; #if USE_STATE2STRING @@ -214,6 +213,11 @@ static MemberDef *getFortranDefs(yyscan_t yyscanner,const QCString &memberName, 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); @@ -297,6 +301,7 @@ LANGUAGE_BIND_SPEC BIND{BS}"("{BS}C{BS}(,{BS}NAME{BS}"="{BS}"\""(.*)"\""{BS})?") } if (yyextra->currentMemberDef && yyextra->currentMemberDef->isFunction()) { + std::lock_guard<std::mutex> lock(g_countFlowKeywordsMutex); MemberDefMutable *mdm = toMemberDefMutable(yyextra->currentMemberDef); if (mdm) { @@ -1017,7 +1022,7 @@ static void writeMultiLineCodeLink(yyscan_t yyscanner,CodeOutputInterface &ol, { struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; static bool sourceTooltips = Config_getBool(SOURCE_TOOLTIPS); - yyextra->tooltipManager.addTooltip(d); + TooltipManager::instance().addTooltip(ol,d); QCString ref = d->getReference(); QCString file = d->getOutputFileBase(); QCString anchor = d->anchor(); @@ -1237,6 +1242,7 @@ static bool getLink(yyscan_t yyscanner,UseSDict *usedict, // dictionary with use if (yyextra->currentDefinition && yyextra->currentMemberDef && md!=yyextra->currentMemberDef && yyextra->insideBody && yyextra->collectXRefs) { + std::lock_guard<std::mutex> lock(g_docCrossReferenceMutex); addDocCrossReference(toMemberDefMutable(yyextra->currentMemberDef),toMemberDefMutable(md)); } writeMultiLineCodeLink(yyscanner,ol,md,text ? text : memberText); @@ -1521,7 +1527,7 @@ void FortranCodeParser::parseCode(CodeOutputInterface & codeOutIntf, yyextra->hasContLine = NULL; // write the tooltips - yyextra->tooltipManager.writeTooltips(codeOutIntf); + TooltipManager::instance().writeTooltips(codeOutIntf); printlex(yy_flex_debug, FALSE, __FILE__, fileDef ? fileDef->fileName().data(): NULL); } diff --git a/src/fortranscanner.l b/src/fortranscanner.l index 6b581d2..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; @@ -872,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; @@ -913,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; @@ -956,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, @@ -974,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 @@ -1148,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) { @@ -1197,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; } @@ -2019,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()) { @@ -2136,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); @@ -2164,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. @@ -2196,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) @@ -2249,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; @@ -2265,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; } @@ -2522,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) { diff --git a/src/groupdef.cpp b/src/groupdef.cpp index 2e01d64..bad8526 100644 --- a/src/groupdef.cpp +++ b/src/groupdef.cpp @@ -665,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) diff --git a/src/htmldocvisitor.cpp b/src/htmldocvisitor.cpp index a60a291..b93a2c4 100644 --- a/src/htmldocvisitor.cpp +++ b/src/htmldocvisitor.cpp @@ -62,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; @@ -2218,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; } } } @@ -2244,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 e1358a7..cd615e4 100644 --- a/src/htmlgen.cpp +++ b/src/htmlgen.cpp @@ -60,6 +60,7 @@ static QCString g_header; static QCString g_footer; static QCString g_mathjax_code; static QCString g_latex_macro; +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 @@ -672,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; } } } @@ -698,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; } } } @@ -1130,7 +1155,7 @@ void HtmlGenerator::writeFooterFile(QFile &file) 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); @@ -1138,6 +1163,7 @@ 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); { @@ -1209,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> "; @@ -2238,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; diff --git a/src/htmlgen.h b/src/htmlgen.h index 45899a6..659a69e 100644 --- a/src/htmlgen.h +++ b/src/htmlgen.h @@ -26,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); @@ -61,6 +63,7 @@ class HtmlCodeGenerator : public CodeOutputInterface int m_col = 0; QCString m_relPath; bool m_lineOpen = false; + int m_id = 0; }; /** Generator for HTML output */ @@ -117,9 +120,9 @@ class HtmlGenerator : public OutputGenerator 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(); diff --git a/src/latexgen.cpp b/src/latexgen.cpp index 668a8fa..3f4435f 100644 --- a/src/latexgen.cpp +++ b/src/latexgen.cpp @@ -902,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)); @@ -1035,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": @@ -1053,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"; @@ -1204,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; @@ -1231,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"; @@ -1242,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"; @@ -2230,7 +2233,7 @@ 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,m_codeGen,ctx?ctx->getDefFileExtension():QCString(""),m_insideTabbing); diff --git a/src/latexgen.h b/src/latexgen.h index 4c793fa..6be5de7 100644 --- a/src/latexgen.h +++ b/src/latexgen.h @@ -123,9 +123,9 @@ class LatexGenerator : public OutputGenerator // --------------------------- - 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(); diff --git a/src/mangen.cpp b/src/mangen.cpp index 4b01904..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; @@ -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 8a8def7..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(); diff --git a/src/memberdef.cpp b/src/memberdef.cpp index 7fe95db..ca6026e 100644 --- a/src/memberdef.cpp +++ b/src/memberdef.cpp @@ -357,7 +357,7 @@ class MemberDefImpl : public DefinitionMixin<MemberDefMutable> 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 }; MemberDefMutable *createMemberDef(const char *defFileName,int defLine,int defColumn, @@ -389,6 +389,8 @@ class MemberDefAliasImpl : public DefinitionAliasMixin<MemberDef> } virtual void moveTo(Definition *) {} + virtual QCString name() const + { return getMdAlias()->name(); } virtual QCString getOutputFileBase() const { return getMdAlias()->getOutputFileBase(); } virtual QCString getReference() const @@ -760,7 +762,9 @@ class MemberDefAliasImpl : public DefinitionAliasMixin<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; } //----------------------------------------------------------------------------- @@ -6099,6 +6103,48 @@ bool MemberDefImpl::isReference() const (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) diff --git a/src/memberdef.h b/src/memberdef.h index d2dd699..11d403c 100644 --- a/src/memberdef.h +++ b/src/memberdef.h @@ -448,5 +448,6 @@ MemberDefMutable *createMemberDef(const char *defFileName,int defLine,int defCol MemberDef *createMemberDefAlias(const Definition *newScope,const MemberDef *aliasMd); void combineDeclarationAndDefinition(MemberDefMutable *mdec,MemberDefMutable *mdef); +void addDocCrossReference(MemberDefMutable *src,MemberDefMutable *dst); #endif diff --git a/src/membergroup.cpp b/src/membergroup.cpp index d8d6193..bd3bf0c 100644 --- a/src/membergroup.cpp +++ b/src/membergroup.cpp @@ -86,7 +86,7 @@ void MemberGroup::insertMember(MemberDef *md) void MemberGroup::setAnchors() { - ::setAnchors(memberList); + memberList->setAnchors(); } void MemberGroup::writeDeclarations(OutputList &ol, diff --git a/src/memberlist.cpp b/src/memberlist.cpp index ed10bed..d8700d4 100644 --- a/src/memberlist.cpp +++ b/src/memberlist.cpp @@ -1143,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 7ee8925..e62655b 100644 --- a/src/memberlist.h +++ b/src/memberlist.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 @@ -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; diff --git a/src/namespacedef.cpp b/src/namespacedef.cpp index cef836a..4b8b4d8 100644 --- a/src/namespacedef.cpp +++ b/src/namespacedef.cpp @@ -34,6 +34,19 @@ #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 DefinitionMixin<NamespaceDefMutable> { @@ -172,7 +185,7 @@ class NamespaceDefAliasImpl : public DefinitionAliasMixin<NamespaceDef> virtual LinkedRefMap<const ClassDef> getUsedClasses() const { return getNSAlias()->getUsedClasses(); } virtual QCString displayName(bool b=TRUE) const - { return getNSAlias()->displayName(b); } + { return makeDisplayName(this,b); } virtual QCString localName() const { return getNSAlias()->localName(); } virtual bool isConstantGroup() const @@ -219,7 +232,11 @@ class NamespaceDefAliasImpl : public DefinitionAliasMixin<NamespaceDef> 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; } //------------------------------------------------------------------ @@ -559,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 @@ -1252,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 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 ba9f2f4..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. @@ -351,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 2d06598..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) @@ -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/pycode.l b/src/pycode.l index e136e91..b7f3b66 100644 --- a/src/pycode.l +++ b/src/pycode.l @@ -107,7 +107,6 @@ struct pycodeYY_state bool endComment = FALSE; VariableContext theVarContext; CallContext theCallContext; - TooltipManager tooltipManager; SymbolResolver symbolResolver; }; @@ -150,6 +149,8 @@ static void addVariable(yyscan_t yyscanner, QCString type, QCString name); //------------------------------------------------------------------- static std::mutex g_searchIndexMutex; +static std::mutex g_docCrossReferenceMutex; +static std::mutex g_countFlowKeywordsMutex; //------------------------------------------------------------------- @@ -488,6 +489,7 @@ TARGET ({IDENTIFIER}|"("{TARGET_LIST}")"|"["{TARGET_LIST}"]"|{ATTRIBU {FLOWKW} { if (yyextra->currentMemberDef && yyextra->currentMemberDef->isFunction()) { + std::lock_guard<std::mutex> lock(g_countFlowKeywordsMutex); MemberDefMutable *mdm = toMemberDefMutable(yyextra->currentMemberDef); if (mdm) { @@ -533,6 +535,7 @@ TARGET ({IDENTIFIER}|"("{TARGET_LIST}")"|"["{TARGET_LIST}"]"|{ATTRIBU {FLOWKW} { if (yyextra->currentMemberDef && yyextra->currentMemberDef->isFunction()) { + std::lock_guard<std::mutex> lock(g_countFlowKeywordsMutex); MemberDefMutable *mdm = toMemberDefMutable(yyextra->currentMemberDef); if (mdm) { @@ -1097,7 +1100,7 @@ static void writeMultiLineCodeLink(yyscan_t yyscanner, { struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; bool sourceTooltips = Config_getBool(SOURCE_TOOLTIPS); - yyextra->tooltipManager.addTooltip(d); + TooltipManager::instance().addTooltip(ol,d); QCString ref = d->getReference(); QCString file = d->getOutputFileBase(); QCString anchor = d->anchor(); @@ -1225,6 +1228,7 @@ static bool getLinkInScope(yyscan_t yyscanner, if (yyextra->currentDefinition && yyextra->currentMemberDef && md!=yyextra->currentMemberDef && yyextra->collectXRefs) { + 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()); @@ -1335,6 +1339,7 @@ static void generateClassOrGlobalLink(yyscan_t yyscanner, if (d && d->isLinkable() && md->isLinkable() && yyextra->currentMemberDef && yyextra->collectXRefs) { + std::lock_guard<std::mutex> lock(g_docCrossReferenceMutex); addDocCrossReference(toMemberDefMutable(yyextra->currentMemberDef),toMemberDefMutable(md)); } } @@ -1362,6 +1367,7 @@ static void generateClassOrGlobalLink(yyscan_t yyscanner, 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; @@ -1385,6 +1391,7 @@ static void generateClassOrGlobalLink(yyscan_t yyscanner, 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; @@ -1471,6 +1478,7 @@ static bool findMemberLink(yyscan_t yyscanner, { if (yyextra->currentMemberDef && yyextra->collectXRefs) { + std::lock_guard<std::mutex> lock(g_docCrossReferenceMutex); addDocCrossReference(toMemberDefMutable(yyextra->currentMemberDef),toMemberDefMutable(toMemberDef(sym))); } } @@ -1627,7 +1635,7 @@ void PythonCodeParser::parseCode(CodeOutputInterface &codeOutIntf, yyextra->sourceFileDef=0; } // write the tooltips - yyextra->tooltipManager.writeTooltips(codeOutIntf); + TooltipManager::instance().writeTooltips(codeOutIntf); printlex(yy_flex_debug, FALSE, __FILE__, fileDef ? fileDef->fileName().data(): NULL); } diff --git a/src/rtfgen.cpp b/src/rtfgen.cpp index 7acd14f..17ed794 100644 --- a/src/rtfgen.cpp +++ b/src/rtfgen.cpp @@ -372,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; @@ -526,7 +526,8 @@ void RTFGenerator::startIndexSection(IndexSections is) { if (cd->isLinkableInProject() && cd->templateMaster()==0 && - !cd->isEmbeddedInOuterScope() + !cd->isEmbeddedInOuterScope() && + !cd->isAlias() ) { beginRTFChapter(); @@ -628,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; } @@ -783,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 \""; @@ -794,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(); @@ -823,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; @@ -837,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; @@ -2796,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); diff --git a/src/rtfgen.h b/src/rtfgen.h index 8a2c3fe..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(); diff --git a/src/searchindex.cpp b/src/searchindex.cpp index b0f6abb..0464cb4 100644 --- a/src/searchindex.cpp +++ b/src/searchindex.cpp @@ -923,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; @@ -934,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; @@ -956,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; @@ -1229,7 +1230,8 @@ void writeJavaScriptSearchIndex() 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; diff --git a/src/tooltip.cpp b/src/tooltip.cpp index 3c2f0e1..f8222d7 100644 --- a/src/tooltip.cpp +++ b/src/tooltip.cpp @@ -14,7 +14,10 @@ */ #include <map> +#include <memory> +#include <unordered_map> #include <string> +#include <mutex> #include "tooltip.h" #include "definition.h" @@ -24,12 +27,27 @@ #include "doxygen.h" #include "config.h" +static std::mutex g_tooltipLock; + +struct TooltipData +{ + std::map<std::string,const Definition*> tooltipInfo; + std::set<std::string> tooltipWritten; +}; + class TooltipManager::Private { public: - std::map<std::string,const Definition*> tooltipInfo; + std::unordered_map<int, std::unique_ptr<TooltipData> > tooltips; + std::unique_ptr<TooltipData> &getTooltipData(int id); }; +TooltipManager &TooltipManager::instance() +{ + static TooltipManager s_instance; + return s_instance; +} + TooltipManager::TooltipManager() : p(std::make_unique<Private>()) { } @@ -50,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) +{ + 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) @@ -67,44 +97,57 @@ void TooltipManager::addTooltip(const Definition *d) id+="_"+anc; } id = "a" + id; - p->tooltipInfo.insert({id.str(),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) { - for (const auto &kv : p->tooltipInfo) + 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()) { - 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) + auto &ttd = it->second; + for (const auto &kv : ttd->tooltipInfo) { - const MemberDef *md = toMemberDef(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(kv.first.c_str(), // id - docInfo, // symName - decl, // decl - d->briefDescriptionAsTooltip(), // desc - defInfo, - declInfo - ); } } diff --git a/src/tooltip.h b/src/tooltip.h index 3517b5d..acdacb4 100644 --- a/src/tooltip.h +++ b/src/tooltip.h @@ -24,16 +24,17 @@ class CodeOutputInterface; class TooltipManager { public: - TooltipManager(); + static TooltipManager &instance(); ~TooltipManager(); /** add a tooltip for a given symbol definition */ - void addTooltip(const Definition *d); + void addTooltip(CodeOutputInterface &ol,const Definition *d); /** write the list of all collected tooltip to the given outputs */ void writeTooltips(CodeOutputInterface &ol); private: + TooltipManager(); class Private; std::unique_ptr<Private> p; }; diff --git a/src/util.cpp b/src/util.cpp index bc0abbd..74e5226 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -96,6 +96,8 @@ #define REL_PATH_TO_ROOT "../../" +static const char *hex = "0123456789ABCDEF"; + //------------------------------------------------------------------------ // TextGeneratorOLImpl implementation //------------------------------------------------------------------------ @@ -1227,24 +1229,6 @@ QCString tempArgListToString(const ArgumentList &al,SrcLangExt lang,bool include } -// compute the HTML anchors for a list of members -// TODO: make member of MemberList -void setAnchors(MemberList *ml) -{ - //int count=0; - if (ml==0) return; - MemberListIterator mli(*ml); - MemberDef *md; - for (;(md=mli.current());++mli) - { - MemberDefMutable *mdm = toMemberDefMutable(md); - if (mdm && !md->isReference()) - { - mdm->setAnchor(); - } - } -} - //---------------------------------------------------------------------------- /*! takes the \a buf of the given length \a len and converts CR LF (DOS) @@ -4087,7 +4071,6 @@ QCString stripScope(const char *name) /*! Converts a string to a HTML id string */ QCString convertToId(const char *s) { - static const char hex[] = "0123456789ABCDEF"; if (s==0) return ""; GrowBuf growBuf; const char *p=s; @@ -4222,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); @@ -4275,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); @@ -5068,7 +5071,8 @@ void filterLatexString(FTextStream &t,const char *str, case ' ': if (keepSpaces) t << "~"; else t << ' '; break; default: - t << (char)c; + if (c<32) t << ' '; // non printable control character + else t << (char)c; break; } } @@ -5162,7 +5166,14 @@ void filterLatexString(FTextStream &t,const char *str, { t << "\\+"; } - t << (char)c; + if (c<32) + { + t << ' '; // non-printable control character + } + else + { + t << (char)c; + } } } pc = c; @@ -6491,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); @@ -6833,45 +6843,6 @@ bool fileVisibleInIndex(const FileDef *fd,bool &genSourceFile) ); } -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); - } - } -} - //-------------------------------------------------------------------------------------- /*! @brief Get one unicode character as an unsigned integer from utf-8 string @@ -137,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); @@ -462,8 +460,6 @@ QCString getDotImageExtension(); bool fileVisibleInIndex(const FileDef *fd,bool &genSourceFile); -void addDocCrossReference(MemberDefMutable *src,MemberDefMutable *dst); - uint getUtf8Code( const QCString& s, int idx ); uint getUtf8CodeToLower( const QCString& s, int idx ); uint getUtf8CodeToUpper( const QCString& s, int idx ); diff --git a/src/vhdlcode.l b/src/vhdlcode.l index dfabe5b..efb367b 100644 --- a/src/vhdlcode.l +++ b/src/vhdlcode.l @@ -109,7 +109,6 @@ struct vhdlcodeYY_state bool lexInit = false; int braceCount = 0; - TooltipManager tooltipManager; }; @@ -1230,7 +1229,7 @@ static void writeMultiLineCodeLink(yyscan_t yyscanner,CodeOutputInterface &ol, { struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; static bool sourceTooltips = Config_getBool(SOURCE_TOOLTIPS); - yyextra->tooltipManager.addTooltip(d); + TooltipManager::instance().addTooltip(ol,d); QCString ref = d->getReference(); QCString file = d->getOutputFileBase(); QCString anchor = d->anchor(); @@ -1533,10 +1532,10 @@ static void writeProcessProto(yyscan_t yyscanner) static bool writeColoredWord(yyscan_t yyscanner,QCString& word ) { QCString qcs=word.lower(); - QCString *ss=VhdlDocGen::findKeyWord(qcs); + const char *ss=VhdlDocGen::findKeyWord(qcs); if (ss) { - writeFont(yyscanner,ss->data(),word.data()); + writeFont(yyscanner,ss,word.data()); return true; } return false; @@ -1659,7 +1658,7 @@ void VHDLCodeParser::parseCode(CodeOutputInterface &od, yyextra->startCode=false; // write the tooltips - yyextra->tooltipManager.writeTooltips(od); + TooltipManager::instance().writeTooltips(od); printlex(yy_flex_debug, false, __FILE__, fd ? fd->fileName().data(): NULL); } diff --git a/src/vhdldocgen.cpp b/src/vhdldocgen.cpp index d4af49e..93afb4b 100644 --- a/src/vhdldocgen.cpp +++ b/src/vhdldocgen.cpp @@ -64,11 +64,6 @@ //#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(ClassDefMutable* entity, ClassDefMutable* arch, ClassDefMutable *inst, @@ -562,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", @@ -587,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"); - - QCString word=tmp.lower(); + std::string word=kw.lower().str(); - if (word.isEmpty() || word.at(0)=='\0') return 0; + if (word.empty()) return 0; - if (g_vhdlKeyDict0.find(word)) - return &preprocessor; + if (g_vhdlKeyWordSet0.find(word)!=g_vhdlKeyWordSet0.end()) + return "keywordflow"; - if (g_vhdlKeyDict1.find(word)) - return &vhdltype; + if (g_vhdlKeyWordSet1.find(word)!=g_vhdlKeyWordSet1.end()) + return "keywordtype"; - if (g_vhdlKeyDict2.find(word)) - return &vhdllogic; + if (g_vhdlKeyWordSet2.find(word)!=g_vhdlKeyWordSet2.end()) + return "vhdllogic"; - if (g_vhdlKeyDict3.find(word)) - return &vhdlkeyword; + if (g_vhdlKeyWordSet3.find(word)!=g_vhdlKeyWordSet3.end()) + return "vhdlkeyword"; return 0; } @@ -688,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; @@ -1267,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]; @@ -1284,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) { @@ -1294,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 { @@ -1430,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 { @@ -1495,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); @@ -1509,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 diff --git a/src/vhdldocgen.h b/src/vhdldocgen.h index ec25380..b98ea44 100644 --- a/src/vhdldocgen.h +++ b/src/vhdldocgen.h @@ -130,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, |