diff options
author | Dimitri van Heesch <doxygen@gmail.com> | 2020-09-27 18:26:20 (GMT) |
---|---|---|
committer | Dimitri van Heesch <doxygen@gmail.com> | 2020-09-27 18:26:20 (GMT) |
commit | cfdabb54c5bcea38629eb0ec8f207d1306ff0939 (patch) | |
tree | cb323c258fe80e0e2422f939d40af66eefdd055e | |
parent | 55e15c86717f38c9b510e4287cb0b4f165b8cb10 (diff) | |
download | Doxygen-cfdabb54c5bcea38629eb0ec8f207d1306ff0939.zip Doxygen-cfdabb54c5bcea38629eb0ec8f207d1306ff0939.tar.gz Doxygen-cfdabb54c5bcea38629eb0ec8f207d1306ff0939.tar.bz2 |
Refactoring: prepare output generators for multi-threaded use
36 files changed, 872 insertions, 756 deletions
diff --git a/addon/doxyapp/doxyapp.cpp b/addon/doxyapp/doxyapp.cpp index 97f3755..3846ed7 100644 --- a/addon/doxyapp/doxyapp.cpp +++ b/addon/doxyapp/doxyapp.cpp @@ -62,6 +62,8 @@ class XRefDummyCodeGenerator : public CodeOutputInterface void writeCodeAnchor(const char *) {} void setCurrentDoc(const Definition *,const char *,bool) {} void addWord(const char *,bool) {} + void startCodeFragment(const char *) {} + void endCodeFragment() {} // here we are presented with the symbols found by the code parser void linkableSymbol(int l, const char *sym,Definition *symDef,Definition *context) @@ -109,19 +111,19 @@ class XRefDummyCodeGenerator : public CodeOutputInterface static void findXRefSymbols(FileDef *fd) { // get the interface to a parser that matches the file extension - CodeParserInterface &intf=Doxygen::parserManager->getCodeParser(fd->getDefFileExtension()); + auto intf=Doxygen::parserManager->getCodeParser(fd->getDefFileExtension()); // get the programming language from the file name SrcLangExt lang = getLanguageFromFileName(fd->name()); // reset the parsers state - intf.resetCodeParserState(); + intf->resetCodeParserState(); // create a new backend object XRefDummyCodeGenerator *xrefGen = new XRefDummyCodeGenerator(fd); // parse the source code - intf.parseCode(*xrefGen, + intf->parseCode(*xrefGen, 0, fileToString(fd->absFilePath()), lang, diff --git a/addon/doxyparse/doxyparse.cpp b/addon/doxyparse/doxyparse.cpp index c06eb1c..2032d06 100644 --- a/addon/doxyparse/doxyparse.cpp +++ b/addon/doxyparse/doxyparse.cpp @@ -70,6 +70,8 @@ class Doxyparse : public CodeOutputInterface void startCodeLine(bool) {} void setCurrentDoc(const Definition *,const char *,bool) {} void addWord(const char *,bool) {} + void startCodeFragment(const char *) {} + void endCodeFragment() {} void linkableSymbol(int l, const char *sym, Definition *symDef, Definition *context) { @@ -90,19 +92,19 @@ static bool is_c_code = true; static void findXRefSymbols(FileDef *fd) { // get the interface to a parser that matches the file extension - CodeParserInterface &intf=Doxygen::parserManager->getCodeParser(fd->getDefFileExtension()); + auto intf=Doxygen::parserManager->getCodeParser(fd->getDefFileExtension()); // get the programming language from the file name SrcLangExt lang = getLanguageFromFileName(fd->name()); // reset the parsers state - intf.resetCodeParserState(); + intf->resetCodeParserState(); // create a new backend object Doxyparse *parse = new Doxyparse(fd); // parse the source code - intf.parseCode(*parse, 0, fileToString(fd->absFilePath()), lang, FALSE, 0, fd); + intf->parseCode(*parse, 0, fileToString(fd->absFilePath()), lang, FALSE, 0, fd); // dismiss the object. delete parse; diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 067c6cd..c3d6f13 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -240,6 +240,7 @@ add_library(doxymain STATIC docgroup.cpp docparser.cpp docsets.cpp + docvisitor.cpp dot.cpp dotcallgraph.cpp dotclassgraph.cpp diff --git a/src/context.cpp b/src/context.cpp index 29a704a..ee394d4 100644 --- a/src/context.cpp +++ b/src/context.cpp @@ -1301,8 +1301,8 @@ static TemplateVariant parseDoc(const Definition *def,const QCString &file,int l static TemplateVariant parseCode(MemberDef *md,const QCString &scopeName,const QCString &relPath, const QCString &code,int startLine=-1,int endLine=-1,bool showLineNumbers=FALSE) { - CodeParserInterface &intf = Doxygen::parserManager->getCodeParser(md->getDefFileExtension()); - intf.resetCodeParserState(); + auto intf = Doxygen::parserManager->getCodeParser(md->getDefFileExtension()); + intf->resetCodeParserState(); QGString s; FTextStream t(&s); switch (g_globals.outputFormat) @@ -1310,14 +1310,14 @@ static TemplateVariant parseCode(MemberDef *md,const QCString &scopeName,const Q case ContextOutputFormat_Html: { HtmlCodeGenerator codeGen(t,relPath); - intf.parseCode(codeGen,scopeName,code,md->getLanguage(),FALSE,0,md->getBodyDef(), + intf->parseCode(codeGen,scopeName,code,md->getLanguage(),FALSE,0,md->getBodyDef(), startLine,endLine,TRUE,md,showLineNumbers,md); } break; case ContextOutputFormat_Latex: { LatexCodeGenerator codeGen(t,relPath,md->docFile()); - intf.parseCode(codeGen,scopeName,code,md->getLanguage(),FALSE,0,md->getBodyDef(), + intf->parseCode(codeGen,scopeName,code,md->getLanguage(),FALSE,0,md->getBodyDef(), startLine,endLine,TRUE,md,showLineNumbers,md); } break; @@ -1332,8 +1332,8 @@ static TemplateVariant parseCode(MemberDef *md,const QCString &scopeName,const Q static TemplateVariant parseCode(const FileDef *fd,const QCString &relPath) { static bool filterSourceFiles = Config_getBool(FILTER_SOURCE_FILES); - CodeParserInterface &intf = Doxygen::parserManager->getCodeParser(fd->getDefFileExtension()); - intf.resetCodeParserState(); + auto intf = Doxygen::parserManager->getCodeParser(fd->getDefFileExtension()); + intf->resetCodeParserState(); QGString s; FTextStream t(&s); switch (g_globals.outputFormat) @@ -1341,7 +1341,7 @@ static TemplateVariant parseCode(const FileDef *fd,const QCString &relPath) case ContextOutputFormat_Html: { HtmlCodeGenerator codeGen(t,relPath); - intf.parseCode(codeGen,0, + intf->parseCode(codeGen,0, fileToString(fd->absFilePath(),filterSourceFiles,TRUE), // the sources fd->getLanguage(), // lang FALSE, // isExampleBlock @@ -1360,7 +1360,7 @@ static TemplateVariant parseCode(const FileDef *fd,const QCString &relPath) case ContextOutputFormat_Latex: { LatexCodeGenerator codeGen(t,relPath,fd->docFile()); - intf.parseCode(codeGen,0, + intf->parseCode(codeGen,0, fileToString(fd->absFilePath(),filterSourceFiles,TRUE), // the sources fd->getLanguage(), // lang FALSE, // isExampleBlock @@ -3896,13 +3896,25 @@ class TextGeneratorLatex : public TextGeneratorIntf if (f && anchor) m_ts << "_"; if (anchor) m_ts << anchor; m_ts << "}{"; - filterLatexString(m_ts,text); + filterLatexString(m_ts,text, + false, // insideTabbing + false, // insidePre + false, // insideItem + false, // insideTable + false // keepSpaces + ); m_ts << "}}"; } else { m_ts << "\\textbf{ "; - filterLatexString(m_ts,text); + filterLatexString(m_ts,text, + false, // insideTabbing + false, // insidePre + false, // insideItem + false, // insideTable + false // keepSpaces + ); m_ts << "}"; } } diff --git a/src/definition.cpp b/src/definition.cpp index dc96839..6d5f3e3 100644 --- a/src/definition.cpp +++ b/src/definition.cpp @@ -1236,26 +1236,26 @@ void DefinitionImpl::writeInlineCode(OutputList &ol,const char *scopeName) const { //printf("Adding code fragment '%s' ext='%s'\n", // codeFragment.data(),m_impl->defFileExt.data()); - CodeParserInterface &intf = Doxygen::parserManager->getCodeParser(m_impl->defFileExt); - intf.resetCodeParserState(); + auto intf = Doxygen::parserManager->getCodeParser(m_impl->defFileExt); + intf->resetCodeParserState(); //printf("Read:\n'%s'\n\n",codeFragment.data()); const MemberDef *thisMd = 0; if (definitionType()==TypeMember) thisMd = dynamic_cast <const MemberDef*>(this); - ol.startCodeFragment(); - intf.parseCode(ol, // codeOutIntf - scopeName, // scope - codeFragment, // input - m_impl->lang, // lang - FALSE, // isExample - 0, // exampleName - m_impl->body->fileDef, // fileDef - actualStart, // startLine - actualEnd, // endLine - TRUE, // inlineFragment - thisMd, // memberDef - TRUE // show line numbers - ); + ol.startCodeFragment("DoxyCode"); + intf->parseCode(ol, // codeOutIntf + scopeName, // scope + codeFragment, // input + m_impl->lang, // lang + FALSE, // isExample + 0, // exampleName + m_impl->body->fileDef, // fileDef + actualStart, // startLine + actualEnd, // endLine + TRUE, // inlineFragment + thisMd, // memberDef + TRUE // show line numbers + ); ol.endCodeFragment(); } } diff --git a/src/docbookgen.cpp b/src/docbookgen.cpp index da7987b..8103f3c 100644 --- a/src/docbookgen.cpp +++ b/src/docbookgen.cpp @@ -242,18 +242,23 @@ void DocbookCodeGenerator::finish() { endCodeLine(); } -void DocbookCodeGenerator::startCodeFragment() +void DocbookCodeGenerator::startCodeFragment(const char *) { - m_t << "<literallayout><computeroutput>" << endl; +DB_GEN_C + m_t << "<programlisting>"; } + void DocbookCodeGenerator::endCodeFragment() { +DB_GEN_C //endCodeLine checks is there is still an open code line, if so closes it. endCodeLine(); - m_t << "</computeroutput></literallayout>" << endl; + m_t << "</programlisting>"; } +//------------------------------------------------------------------------------- + DocbookGenerator::DocbookGenerator() : OutputGenerator(Config_getString(DOCBOOK_OUTPUT)) { DB_GEN_C @@ -732,12 +737,12 @@ void DocbookGenerator::endMemberItem() DB_GEN_C t << "</para>" << endl; } -void DocbookGenerator::startBold(void) +void DocbookGenerator::startBold() { DB_GEN_C t << "<emphasis role=\"strong\">"; } -void DocbookGenerator::endBold(void) +void DocbookGenerator::endBold() { DB_GEN_C t << "</emphasis>"; @@ -755,7 +760,7 @@ DB_GEN_C2("extraIndentLevel " << extraIndentLevel) t << "<section>" << endl; t << "<title>"; } -void DocbookGenerator::writeRuler(void) +void DocbookGenerator::writeRuler() { DB_GEN_C2("m_inLevel " << m_inLevel) DB_GEN_C2("m_inGroup " << m_inGroup) @@ -945,12 +950,12 @@ void DocbookGenerator::endExamples() DB_GEN_C t << "</simplesect>" << endl; } -void DocbookGenerator::startSubsubsection(void) +void DocbookGenerator::startSubsubsection() { DB_GEN_C t << "<simplesect><title>"; } -void DocbookGenerator::endSubsubsection(void) +void DocbookGenerator::endSubsubsection() { DB_GEN_C t << "</title></simplesect>" << endl; @@ -995,19 +1000,6 @@ DB_GEN_C if (closeBracket) t << ")"; } } -void DocbookGenerator::startCodeFragment() -{ -DB_GEN_C - t << "<programlisting>"; -} -void DocbookGenerator::endCodeFragment() -{ -DB_GEN_C - //endCodeLine checks is there is still an open code line, if so closes it. - endCodeLine(); - - t << "</programlisting>"; -} void DocbookGenerator::startMemberTemplateParams() { DB_GEN_C diff --git a/src/docbookgen.h b/src/docbookgen.h index 0fefe4b..cc3fa10 100644 --- a/src/docbookgen.h +++ b/src/docbookgen.h @@ -53,7 +53,7 @@ class DocbookCodeGenerator : public CodeOutputInterface void setCurrentDoc(const Definition *,const char *,bool); void addWord(const char *,bool); void finish(); - void startCodeFragment(); + void startCodeFragment(const char *style); void endCodeFragment(); private: @@ -130,6 +130,10 @@ class DocbookGenerator : public OutputGenerator { m_codeGen.endFontClass(); } void writeCodeAnchor(const char *anchor) { m_codeGen.writeCodeAnchor(anchor); } + void startCodeFragment(const char *style) + { m_codeGen.startCodeFragment(style); } + void endCodeFragment() + { m_codeGen.endCodeFragment(); } // --------------------------- void writeDoc(DocNode *,const Definition *ctx,const MemberDef *md); @@ -169,35 +173,33 @@ class DocbookGenerator : public OutputGenerator void writeChar(char); void writeString(const char *); void startParagraph(const char *); - void endParagraph(void); + void endParagraph(); void writeObjectLink(const char *,const char *,const char *,const char *); void startHtmlLink(const char *){DB_GEN_NEW}; - void endHtmlLink(void){DB_GEN_NEW}; - void startBold(void); - void endBold(void); - void startTypewriter(void); - void endTypewriter(void); - void startEmphasis(void){DB_GEN_NEW}; - void endEmphasis(void){DB_GEN_NEW}; - void startCodeFragment(void); - void endCodeFragment(void); - void writeRuler(void); - void startDescription(void){DB_GEN_NEW}; - void endDescription(void){DB_GEN_NEW}; - void startDescItem(void){DB_GEN_NEW}; - void startDescForItem(void){DB_GEN_EMPTY}; - void endDescForItem(void){DB_GEN_EMPTY}; - void endDescItem(void){DB_GEN_NEW}; - void startCenter(void){DB_GEN_NEW}; - void endCenter(void){DB_GEN_NEW}; - void startSmall(void){DB_GEN_NEW}; - void endSmall(void){DB_GEN_NEW}; - void startExamples(void); - void endExamples(void); + void endHtmlLink(){DB_GEN_NEW}; + void startBold(); + void endBold(); + void startTypewriter(); + void endTypewriter(); + void startEmphasis(){DB_GEN_NEW}; + void endEmphasis(){DB_GEN_NEW}; + void writeRuler(); + void startDescription(){DB_GEN_NEW}; + void endDescription(){DB_GEN_NEW}; + void startDescItem(){DB_GEN_NEW}; + void startDescForItem(){DB_GEN_EMPTY}; + void endDescForItem(){DB_GEN_EMPTY}; + void endDescItem(){DB_GEN_NEW}; + void startCenter(){DB_GEN_NEW}; + void endCenter(){DB_GEN_NEW}; + void startSmall(){DB_GEN_NEW}; + void endSmall(){DB_GEN_NEW}; + void startExamples(); + void endExamples(); void startParamList(BaseOutputDocInterface::ParamListTypes,const char *){DB_GEN_NEW}; - void endParamList(void){DB_GEN_NEW}; - void startTitle(void){DB_GEN_NEW}; - void endTitle(void){DB_GEN_NEW}; + void endParamList(){DB_GEN_NEW}; + void startTitle(){DB_GEN_NEW}; + void endTitle(){DB_GEN_NEW}; void writeAnchor(const char *,const char *){DB_GEN_EMPTY}; void startSection(const char *,const char *,SectionType); void endSection(const char *,SectionType); @@ -205,21 +207,21 @@ class DocbookGenerator : public OutputGenerator void addIndexItem(const char *,const char *); void writeNonBreakableSpace(int); void startDescTable(const char *); - void endDescTable(void); - void startDescTableRow(void); - void endDescTableRow(void); - void startDescTableTitle(void); - void endDescTableTitle(void); - void startDescTableData(void); - void endDescTableData(void); + void endDescTable(); + void startDescTableRow(); + void endDescTableRow(); + void startDescTableTitle(); + void endDescTableTitle(); + void startDescTableData(); + void endDescTableData(); void startTextLink(const char *,const char *){DB_GEN_NEW}; - void endTextLink(void){DB_GEN_NEW}; - void startPageRef(void){DB_GEN_NEW}; + void endTextLink(){DB_GEN_NEW}; + void startPageRef(){DB_GEN_NEW}; void endPageRef(const char *,const char *){DB_GEN_NEW}; - void startSubsection(void){DB_GEN_NEW}; - void endSubsection(void){DB_GEN_NEW}; - void startSubsubsection(void); - void endSubsubsection(void); + void startSubsection(){DB_GEN_NEW}; + void endSubsection(){DB_GEN_NEW}; + void startSubsubsection(); + void endSubsubsection(); void startGroupHeader(int); diff --git a/src/docbookvisitor.cpp b/src/docbookvisitor.cpp index 78af6e0..bf6c827 100644 --- a/src/docbookvisitor.cpp +++ b/src/docbookvisitor.cpp @@ -316,9 +316,11 @@ DB_VIS_C { case DocVerbatim::Code: // fall though m_t << "<literallayout><computeroutput>"; - Doxygen::parserManager->getCodeParser(m_langExt) - .parseCode(m_ci,s->context(),s->text(),langExt, - s->isExample(),s->exampleFile()); + getCodeParser(m_langExt).parseCode(m_ci,s->context(), + s->text(), + langExt, + s->isExample(), + s->exampleFile()); m_t << "</computeroutput></literallayout>"; break; case DocVerbatim::Verbatim: @@ -425,24 +427,22 @@ DB_VIS_C m_t << "<literallayout><computeroutput>"; QFileInfo cfi( inc->file() ); FileDef *fd = createFileDef( cfi.dirPath().utf8(), cfi.fileName().utf8() ); - Doxygen::parserManager->getCodeParser(inc->extension()) - .parseCode(m_ci,inc->context(), - inc->text(), - langExt, - inc->isExample(), - inc->exampleFile(), fd); + getCodeParser(inc->extension()).parseCode(m_ci,inc->context(), + inc->text(), + langExt, + inc->isExample(), + inc->exampleFile(), fd); delete fd; m_t << "</computeroutput></literallayout>"; } break; case DocInclude::Include: m_t << "<literallayout><computeroutput>"; - Doxygen::parserManager->getCodeParser(inc->extension()) - .parseCode(m_ci,inc->context(), - inc->text(), - langExt, - inc->isExample(), - inc->exampleFile()); + getCodeParser(inc->extension()).parseCode(m_ci,inc->context(), + inc->text(), + langExt, + inc->isExample(), + inc->exampleFile()); m_t << "</computeroutput></literallayout>"; break; case DocInclude::DontInclude: @@ -463,14 +463,13 @@ DB_VIS_C break; case DocInclude::Snippet: m_t << "<literallayout><computeroutput>"; - Doxygen::parserManager->getCodeParser(inc->extension()) - .parseCode(m_ci, - inc->context(), - extractBlock(inc->text(),inc->blockId()), - langExt, - inc->isExample(), - inc->exampleFile() - ); + getCodeParser(inc->extension()).parseCode(m_ci, + inc->context(), + extractBlock(inc->text(),inc->blockId()), + langExt, + inc->isExample(), + inc->exampleFile() + ); m_t << "</computeroutput></literallayout>"; break; case DocInclude::SnipWithLines: @@ -478,8 +477,7 @@ DB_VIS_C QFileInfo cfi( inc->file() ); FileDef *fd = createFileDef( cfi.dirPath().utf8(), cfi.fileName().utf8() ); m_t << "<literallayout><computeroutput>"; - Doxygen::parserManager->getCodeParser(inc->extension()) - .parseCode(m_ci, + getCodeParser(inc->extension()).parseCode(m_ci, inc->context(), extractBlock(inc->text(),inc->blockId()), langExt, @@ -531,17 +529,16 @@ DB_VIS_C fd = createFileDef( cfi.dirPath().utf8(), cfi.fileName().utf8() ); } - Doxygen::parserManager->getCodeParser(locLangExt) - .parseCode(m_ci,op->context(), - op->text(),langExt,op->isExample(), - op->exampleFile(), - fd, // fileDef - op->line(), // startLine - -1, // endLine - FALSE, // inline fragment - 0, // memberDef - op->showLineNo() // show line numbers - ); + getCodeParser(locLangExt).parseCode(m_ci,op->context(), + op->text(),langExt,op->isExample(), + op->exampleFile(), + fd, // fileDef + op->line(), // startLine + -1, // endLine + FALSE, // inline fragment + 0, // memberDef + op->showLineNo() // show line numbers + ); if (fd) delete fd; } pushEnabled(); diff --git a/src/docvisitor.cpp b/src/docvisitor.cpp new file mode 100644 index 0000000..664d3ca --- /dev/null +++ b/src/docvisitor.cpp @@ -0,0 +1,58 @@ +/****************************************************************************** + * + * Copyright (C) 1997-2020 by Dimitri van Heesch. + * + * Permission to use, copy, modify, and distribute this software and its + * documentation under the terms of the GNU General Public License is hereby + * granted. No representations are made about the suitability of this software + * for any purpose. It is provided "as is" without express or implied warranty. + * See the GNU General Public License for more details. + * + * Documents produced by Doxygen are derivative works derived from the + * input used in their production; they are not affected by this license. + */ + + +#include <unordered_map> + +#include "parserintf.h" +#include "docvisitor.h" +#include "util.h" +#include "types.h" +#include "doxygen.h" + +struct DocVisitor::Private +{ + int id; + std::unordered_map< std::string, std::unique_ptr<CodeParserInterface> > parserFactoryMap; +}; + +DocVisitor::DocVisitor(int id) : p(std::make_unique<Private>()) +{ + p->id = id; +} + +DocVisitor::~DocVisitor() +{ +} + +CodeParserInterface &DocVisitor::getCodeParser(const char *extension) +{ + std::string ext(extension?extension:""); + // for each extension we create a code parser once per visitor, so that + // the context of the same parser object is reused thoughout multiple passes for instance + // for code fragments shown via dontinclude. + auto it = p->parserFactoryMap.find(ext); + if (it==p->parserFactoryMap.end()) + { + auto factory = Doxygen::parserManager->getCodeParserFactory(extension); + auto result = p->parserFactoryMap.insert(std::make_pair(ext,factory())); + it = result.first; + } + return *it->second.get(); +} + +int DocVisitor::id() const +{ + return p->id; +} diff --git a/src/docvisitor.h b/src/docvisitor.h index 0a53595..105b97c 100644 --- a/src/docvisitor.h +++ b/src/docvisitor.h @@ -1,13 +1,10 @@ /****************************************************************************** * - * - * - * - * Copyright (C) 1997-2015 by Dimitri van Heesch. + * Copyright (C) 1997-2020 by Dimitri van Heesch. * * Permission to use, copy, modify, and distribute this software and its - * documentation under the terms of the GNU General Public License is hereby - * granted. No representations are made about the suitability of this software + * documentation under the terms of the GNU General Public License is hereby + * granted. No representations are made about the suitability of this software * for any purpose. It is provided "as is" without express or implied warranty. * See the GNU General Public License for more details. * @@ -19,6 +16,8 @@ #ifndef _DOCVISITOR_H #define _DOCVISITOR_H +#include <memory> + // ids const int DocVisitor_Html = 0; const int DocVisitor_Latex = 1; @@ -84,18 +83,21 @@ class DocSimpleSectSep; class DocHtmlBlockQuote; class DocVhdlFlow; class DocParBlock; +class CodeParserInterface; /*! @brief Abstract visitor that participates in the visitor pattern. */ class DocVisitor { - int m_id; + struct Private; + std::unique_ptr<Private> p; public: - DocVisitor(int id) : m_id(id) {} - virtual ~DocVisitor() {} - int id() const { return m_id; } + DocVisitor(int id); + virtual ~DocVisitor(); + int id() const; + CodeParserInterface &getCodeParser(const char *langExt); - /*! @name Visitor functions for leaf nodes + /*! @name Visitor functions for leaf nodes * @{ */ virtual void visit(DocWord *) = 0; @@ -117,7 +119,7 @@ class DocVisitor virtual void visit(DocCite *) = 0; /*! @} */ - /*! @name Visitor functions for internal nodes + /*! @name Visitor functions for internal nodes * @{ */ virtual void visitPre(DocAutoList *) = 0; @@ -167,7 +169,7 @@ class DocVisitor virtual void visitPre(DocDotFile *) = 0; virtual void visitPost(DocDotFile *) = 0; virtual void visitPre(DocMscFile *) = 0; - virtual void visitPost(DocMscFile *) = 0; + virtual void visitPost(DocMscFile *) = 0; virtual void visitPre(DocDiaFile *) = 0; virtual void visitPost(DocDiaFile *) = 0; virtual void visitPre(DocLink *) = 0; diff --git a/src/doxygen.cpp b/src/doxygen.cpp index ee414e7..75985f5 100644 --- a/src/doxygen.cpp +++ b/src/doxygen.cpp @@ -7584,6 +7584,66 @@ static void generateFileSources() else #endif { +#define MULTITHREADED_SOURCE_GENERATOR 0 // not ready to be enabled yet +#if MULTITHREADED_SOURCE_GENERATOR + std::size_t numThreads = static_cast<std::size_t>(Config_getInt(NUM_PROC_THREADS)); + if (numThreads==0) + { + numThreads = std::thread::hardware_concurrency(); + } + msg("Generating code files using %zu threads.\n",numThreads); + struct SourceContext + { + SourceContext(FileDef *fd_,bool gen_,OutputList ol_) + : fd(fd_), generateSourceFile(gen_), ol(ol_) {} + FileDef *fd; + bool generateSourceFile; + OutputList ol; + }; + ThreadPool threadPool(numThreads); + std::vector< std::future< std::shared_ptr<SourceContext> > > results; + for (const auto &fn : *Doxygen::inputNameLinkedMap) + { + for (const auto &fd : *fn) + { + bool generateSourceFile = fd->generateSourceFile() && !Htags::useHtags && !g_useOutputTemplate; + auto ctx = std::make_shared<SourceContext>(fd.get(),generateSourceFile,*g_outputList); + if (generateSourceFile) + { + msg("Generating code for file %s...\n",fd->docName().data()); + fd->writeSourceHeader(ctx->ol); + } + else + { + msg("Parsing code for file %s...\n",fd->docName().data()); + } + auto processFile = [ctx]() { + StringVector filesInSameTu; + ctx->fd->getAllIncludeFilesRecursively(filesInSameTu); + if (ctx->generateSourceFile) // sources need to be shown in the output + { + ctx->fd->writeSourceBody(ctx->ol,nullptr); + } + else if (!ctx->fd->isReference() && Doxygen::parseSourcesNeeded) + // we needed to parse the sources even if we do not show them + { + ctx->fd->parseSource(nullptr); + } + return ctx; + }; + results.emplace_back(threadPool.queue(processFile)); + } + } + for (auto &f : results) + { + std::shared_ptr<SourceContext> ctx = f.get(); + if (ctx->generateSourceFile) + { + ctx->fd->writeSourceFooter(ctx->ol); + } + } + +#else // single threaded version for (const auto &fn : *Doxygen::inputNameLinkedMap) { for (const auto &fd : *fn) @@ -7593,7 +7653,9 @@ static void generateFileSources() if (fd->generateSourceFile() && !Htags::useHtags && !g_useOutputTemplate) // sources need to be shown in the output { msg("Generating code for file %s...\n",fd->docName().data()); - fd->writeSource(*g_outputList,nullptr); + fd->writeSourceHeader(*g_outputList); + fd->writeSourceBody(*g_outputList,nullptr); + fd->writeSourceFooter(*g_outputList); } else if (!fd->isReference() && Doxygen::parseSourcesNeeded) // we needed to parse the sources even if we do not show them @@ -7603,6 +7665,7 @@ static void generateFileSources() } } } +#endif } } } @@ -8634,8 +8697,8 @@ static void generateExampleDocs() for (pdi.toFirst();(pd=pdi.current());++pdi) { msg("Generating docs for example %s...\n",pd->name().data()); - CodeParserInterface &intf = Doxygen::parserManager->getCodeParser(".c"); // TODO: do this on code type - intf.resetCodeParserState(); + auto intf = Doxygen::parserManager->getCodeParser(".c"); // TODO: do this on code type + intf->resetCodeParserState(); QCString n=pd->getOutputFileBase(); startFile(*g_outputList,n,n,pd->name()); startTitle(*g_outputList,n); @@ -9835,7 +9898,7 @@ class NullOutlineParser : public OutlineParserInterface }; -template<class T> std::function< std::unique_ptr<T>() > make_output_parser_factory() +template<class T> std::function< std::unique_ptr<T>() > make_parser_factory() { return []() { return std::make_unique<T>(); }; } @@ -9852,26 +9915,26 @@ void initDoxygen() Portable::correct_path(); Debug::startTimer(); - Doxygen::parserManager = new ParserManager( make_output_parser_factory<NullOutlineParser>(), - std::make_unique<FileCodeParser>()); - Doxygen::parserManager->registerParser("c", make_output_parser_factory<COutlineParser>(), - std::make_unique<CCodeParser>()); - Doxygen::parserManager->registerParser("python", make_output_parser_factory<PythonOutlineParser>(), - std::make_unique<PythonCodeParser>()); - Doxygen::parserManager->registerParser("fortran", make_output_parser_factory<FortranOutlineParser>(), - std::make_unique<FortranCodeParser>()); - Doxygen::parserManager->registerParser("fortranfree", make_output_parser_factory<FortranOutlineParserFree>(), - std::make_unique<FortranCodeParserFree>()); - Doxygen::parserManager->registerParser("fortranfixed", make_output_parser_factory<FortranOutlineParserFixed>(), - std::make_unique<FortranCodeParserFixed>()); - Doxygen::parserManager->registerParser("vhdl", make_output_parser_factory<VHDLOutlineParser>(), - std::make_unique<VHDLCodeParser>()); - Doxygen::parserManager->registerParser("xml", make_output_parser_factory<NullOutlineParser>(), - std::make_unique<XMLCodeParser>()); - Doxygen::parserManager->registerParser("sql", make_output_parser_factory<NullOutlineParser>(), - std::make_unique<SQLCodeParser>()); - Doxygen::parserManager->registerParser("md", make_output_parser_factory<MarkdownOutlineParser>(), - std::make_unique<FileCodeParser>()); + Doxygen::parserManager = new ParserManager( make_parser_factory<NullOutlineParser>(), + make_parser_factory<FileCodeParser>()); + Doxygen::parserManager->registerParser("c", make_parser_factory<COutlineParser>(), + make_parser_factory<CCodeParser>()); + Doxygen::parserManager->registerParser("python", make_parser_factory<PythonOutlineParser>(), + make_parser_factory<PythonCodeParser>()); + Doxygen::parserManager->registerParser("fortran", make_parser_factory<FortranOutlineParser>(), + make_parser_factory<FortranCodeParser>()); + Doxygen::parserManager->registerParser("fortranfree", make_parser_factory<FortranOutlineParserFree>(), + make_parser_factory<FortranCodeParserFree>()); + Doxygen::parserManager->registerParser("fortranfixed", make_parser_factory<FortranOutlineParserFixed>(), + make_parser_factory<FortranCodeParserFixed>()); + Doxygen::parserManager->registerParser("vhdl", make_parser_factory<VHDLOutlineParser>(), + make_parser_factory<VHDLCodeParser>()); + Doxygen::parserManager->registerParser("xml", make_parser_factory<NullOutlineParser>(), + make_parser_factory<XMLCodeParser>()); + Doxygen::parserManager->registerParser("sql", make_parser_factory<NullOutlineParser>(), + make_parser_factory<SQLCodeParser>()); + Doxygen::parserManager->registerParser("md", make_parser_factory<MarkdownOutlineParser>(), + make_parser_factory<FileCodeParser>()); // register any additional parsers here... diff --git a/src/filedef.cpp b/src/filedef.cpp index b74fda9..f4db6da 100644 --- a/src/filedef.cpp +++ b/src/filedef.cpp @@ -101,7 +101,9 @@ class FileDefImpl : public DefinitionImpl, public FileDef virtual void writeQuickMemberLinks(OutputList &ol,const MemberDef *currentMd) const; virtual void writeSummaryLinks(OutputList &ol) const; virtual void writeTagFile(FTextStream &t); - virtual void writeSource(OutputList &ol,ClangTUParser *clangParser); + virtual void writeSourceHeader(OutputList &ol); + virtual void writeSourceBody(OutputList &ol,ClangTUParser *clangParser); + virtual void writeSourceFooter(OutputList &ol); virtual void parseSource(ClangTUParser *clangParser); virtual void setDiskName(const QCString &name); virtual void insertMember(MemberDef *md); @@ -208,6 +210,8 @@ class DevNullCodeDocInterface : public CodeOutputInterface virtual void linkableSymbol(int, const char *,Definition *,Definition *) {} virtual void setCurrentDoc(const Definition *,const char *,bool) {} virtual void addWord(const char *,bool) {} + virtual void startCodeFragment(const char *) {} + virtual void endCodeFragment() {} }; //--------------------------------------------------------------------------- @@ -1150,14 +1154,12 @@ void FileDefImpl::writeQuickMemberLinks(OutputList &ol,const MemberDef *currentM } /*! Write a source listing of this file to the output */ -void FileDefImpl::writeSource(OutputList &ol,ClangTUParser *clangParser) +void FileDefImpl::writeSourceHeader(OutputList &ol) { bool generateTreeView = Config_getBool(GENERATE_TREEVIEW); - bool filterSourceFiles = Config_getBool(FILTER_SOURCE_FILES); bool latexSourceCode = Config_getBool(LATEX_SOURCE_CODE); bool docbookSourceCode = Config_getBool(DOCBOOK_PROGRAMLISTING); bool rtfSourceCode = Config_getBool(RTF_SOURCE_CODE); - DevNullCodeDocInterface devNullIntf; QCString title = m_docname; if (!m_fileVersion.isEmpty()) { @@ -1207,7 +1209,12 @@ void FileDefImpl::writeSource(OutputList &ol,ClangTUParser *clangParser) ol.endTextLink(); ol.popGeneratorState(); } +} +void FileDefImpl::writeSourceBody(OutputList &ol,ClangTUParser *clangParser) +{ + bool filterSourceFiles = Config_getBool(FILTER_SOURCE_FILES); + DevNullCodeDocInterface devNullIntf; #if USE_LIBCLANG if (Doxygen::clangAssistedParsing && clangParser && (getLanguage()==SrcLangExt_Cpp || getLanguage()==SrcLangExt_ObjC)) @@ -1220,9 +1227,9 @@ void FileDefImpl::writeSource(OutputList &ol,ClangTUParser *clangParser) else #endif { - CodeParserInterface &intf = Doxygen::parserManager->getCodeParser(getDefFileExtension()); - intf.resetCodeParserState(); - ol.startCodeFragment(); + auto intf = Doxygen::parserManager->getCodeParser(getDefFileExtension()); + intf->resetCodeParserState(); + ol.startCodeFragment("DoxyCode"); bool needs2PassParsing = Doxygen::parseSourcesNeeded && // we need to parse (filtered) sources for cross-references !filterSourceFiles && // but user wants to show sources as-is @@ -1231,13 +1238,13 @@ void FileDefImpl::writeSource(OutputList &ol,ClangTUParser *clangParser) if (needs2PassParsing) { // parse code for cross-references only (see bug707641) - intf.parseCode(devNullIntf,0, + intf->parseCode(devNullIntf,0, fileToString(absFilePath(),TRUE,TRUE), getLanguage(), FALSE,0,this ); } - intf.parseCode(ol,0, + intf->parseCode(ol,0, fileToString(absFilePath(),filterSourceFiles,TRUE), getLanguage(), // lang FALSE, // isExampleBlock @@ -1253,6 +1260,10 @@ void FileDefImpl::writeSource(OutputList &ol,ClangTUParser *clangParser) ); ol.endCodeFragment(); } +} + +void FileDefImpl::writeSourceFooter(OutputList &ol) +{ ol.endContents(); endFileWithNavPath(this,ol); ol.enableAll(); @@ -1272,9 +1283,9 @@ void FileDefImpl::parseSource(ClangTUParser *clangParser) else #endif { - CodeParserInterface &intf = Doxygen::parserManager->getCodeParser(getDefFileExtension()); - intf.resetCodeParserState(); - intf.parseCode( + auto intf = Doxygen::parserManager->getCodeParser(getDefFileExtension()); + intf->resetCodeParserState(); + intf->parseCode( devNullIntf,0, fileToString(absFilePath(),filterSourceFiles,TRUE), getLanguage(), diff --git a/src/filedef.h b/src/filedef.h index e4bb549..2e11b97 100644 --- a/src/filedef.h +++ b/src/filedef.h @@ -150,7 +150,9 @@ class FileDef : virtual public Definition virtual void writeSummaryLinks(OutputList &ol) const = 0; virtual void writeTagFile(FTextStream &t) = 0; - virtual void writeSource(OutputList &ol,ClangTUParser *clangParser) = 0; + virtual void writeSourceHeader(OutputList &ol) = 0; + virtual void writeSourceBody(OutputList &ol,ClangTUParser *clangParser) = 0; + virtual void writeSourceFooter(OutputList &ol) = 0; virtual void parseSource(ClangTUParser *clangParser) = 0; virtual void setDiskName(const QCString &name) = 0; diff --git a/src/htmldocvisitor.cpp b/src/htmldocvisitor.cpp index ea2dffb..1db7f50 100644 --- a/src/htmldocvisitor.cpp +++ b/src/htmldocvisitor.cpp @@ -1,13 +1,10 @@ /****************************************************************************** * - * - * - * - * Copyright (C) 1997-2015 by Dimitri van Heesch. + * Copyright (C) 1997-2020 by Dimitri van Heesch. * * Permission to use, copy, modify, and distribute this software and its - * documentation under the terms of the GNU General Public License is hereby - * granted. No representations are made about the suitability of this software + * documentation under the terms of the GNU General Public License is hereby + * granted. No representations are made about the suitability of this software * for any purpose. It is provided "as is" without express or implied warranty. * See the GNU General Public License for more details. * @@ -53,7 +50,7 @@ enum contexts_t INTERDD, // 8 INTERTD // 9 }; -static const char *contexts[10] = +static const char *contexts[10] = { "", // 0 "startli", // 1 "startdd", // 2 @@ -281,8 +278,8 @@ static QCString htmlAttribsToString(const HtmlAttribList &attribs, QCString *pAl //------------------------------------------------------------------------- HtmlDocVisitor::HtmlDocVisitor(FTextStream &t,CodeOutputInterface &ci, - const Definition *ctx) - : DocVisitor(DocVisitor_Html), m_t(t), m_ci(ci), m_insidePre(FALSE), + const Definition *ctx) + : DocVisitor(DocVisitor_Html), m_t(t), m_ci(ci), m_insidePre(FALSE), m_hide(FALSE), m_ctx(ctx) { if (ctx) m_langExt=ctx->getDefFileExtension(); @@ -439,12 +436,12 @@ void HtmlDocVisitor::visit(DocStyleChange *s) if (s->enable()) m_t << "<sup" << htmlAttribsToString(s->attribs()) << ">"; else m_t << "</sup>"; break; case DocStyleChange::Center: - if (s->enable()) + if (s->enable()) { forceEndParagraph(s); - m_t << "<center" << htmlAttribsToString(s->attribs()) << ">"; + m_t << "<center" << htmlAttribsToString(s->attribs()) << ">"; } - else + else { m_t << "</center>"; forceStartParagraph(s); @@ -468,12 +465,12 @@ void HtmlDocVisitor::visit(DocStyleChange *s) } break; case DocStyleChange::Div: - if (s->enable()) + if (s->enable()) { forceEndParagraph(s); - m_t << "<div" << htmlAttribsToString(s->attribs()) << ">"; + m_t << "<div" << htmlAttribsToString(s->attribs()) << ">"; } - else + else { m_t << "</div>"; forceStartParagraph(s); @@ -490,7 +487,7 @@ void HtmlDocVisitor::visit(DocStyleChange *s) static void visitPreCaption(FTextStream &t, DocVerbatim *s) { if (s->hasCaption()) - { + { t << "<div class=\"caption\">" << endl; } } @@ -523,11 +520,10 @@ void HtmlDocVisitor::visit(DocVerbatim *s) SrcLangExt langExt = getLanguageFromFileName(lang); switch(s->type()) { - case DocVerbatim::Code: + case DocVerbatim::Code: forceEndParagraph(s); - m_t << PREFRAG_START; - Doxygen::parserManager->getCodeParser(lang) - .parseCode(m_ci, + m_ci.startCodeFragment("DoxyCode"); + getCodeParser(lang).parseCode(m_ci, s->context(), s->text(), langExt, @@ -541,14 +537,14 @@ void HtmlDocVisitor::visit(DocVerbatim *s) TRUE, // show line numbers m_ctx // search context ); - m_t << PREFRAG_END; + m_ci.endCodeFragment(); forceStartParagraph(s); break; - case DocVerbatim::Verbatim: + case DocVerbatim::Verbatim: forceEndParagraph(s); - m_t << /*PREFRAG_START <<*/ "<pre class=\"fragment\">"; + m_t << "<pre class=\"fragment\">"; filter(s->text()); - m_t << "</pre>" /*<< PREFRAG_END*/; + m_t << "</pre>"; forceStartParagraph(s); break; case DocVerbatim::HtmlOnly: @@ -558,12 +554,12 @@ void HtmlDocVisitor::visit(DocVerbatim *s) if (s->isBlock()) forceStartParagraph(s); } break; - case DocVerbatim::ManOnly: - case DocVerbatim::LatexOnly: - case DocVerbatim::XmlOnly: + case DocVerbatim::ManOnly: + case DocVerbatim::LatexOnly: + case DocVerbatim::XmlOnly: case DocVerbatim::RtfOnly: case DocVerbatim::DocbookOnly: - /* nothing */ + /* nothing */ break; case DocVerbatim::Dot: @@ -572,8 +568,8 @@ void HtmlDocVisitor::visit(DocVerbatim *s) QCString fileName(4096); forceEndParagraph(s); - fileName.sprintf("%s%d%s", - (Config_getString(HTML_OUTPUT)+"/inline_dotgraph_").data(), + fileName.sprintf("%s%d%s", + (Config_getString(HTML_OUTPUT)+"/inline_dotgraph_").data(), dotindex++, ".dot" ); @@ -606,8 +602,8 @@ void HtmlDocVisitor::visit(DocVerbatim *s) static int mscindex = 1; QCString baseName(4096); - baseName.sprintf("%s%d", - (Config_getString(HTML_OUTPUT)+"/inline_mscgraph_").data(), + baseName.sprintf("%s%d", + (Config_getString(HTML_OUTPUT)+"/inline_mscgraph_").data(), mscindex++ ); QFile file(baseName+".msc"); @@ -671,11 +667,10 @@ void HtmlDocVisitor::visit(DocInclude *inc) SrcLangExt langExt = getLanguageFromFileName(inc->extension()); switch(inc->type()) { - case DocInclude::Include: + case DocInclude::Include: forceEndParagraph(inc); - m_t << PREFRAG_START; - Doxygen::parserManager->getCodeParser(inc->extension()) - .parseCode(m_ci, + m_ci.startCodeFragment("DoxyCode"); + getCodeParser(inc->extension()).parseCode(m_ci, inc->context(), inc->text(), langExt, @@ -687,24 +682,23 @@ void HtmlDocVisitor::visit(DocInclude *inc) TRUE, // inlineFragment 0, // memberDef FALSE, // show line numbers - m_ctx // search context + m_ctx // search context ); - m_t << PREFRAG_END; + m_ci.endCodeFragment(); forceStartParagraph(inc); break; case DocInclude::IncWithLines: - { + { forceEndParagraph(inc); - m_t << PREFRAG_START; + m_ci.startCodeFragment("DoxyCode"); QFileInfo cfi( inc->file() ); FileDef *fd = createFileDef( cfi.dirPath().utf8(), cfi.fileName().utf8() ); - Doxygen::parserManager->getCodeParser(inc->extension()) - .parseCode(m_ci, + getCodeParser(inc->extension()).parseCode(m_ci, inc->context(), inc->text(), langExt, inc->isExample(), - inc->exampleFile(), + inc->exampleFile(), fd, // fileDef, -1, // start line -1, // end line @@ -714,7 +708,7 @@ void HtmlDocVisitor::visit(DocInclude *inc) m_ctx // search context ); delete fd; - m_t << PREFRAG_END; + m_ci.endCodeFragment(); forceStartParagraph(inc); } break; @@ -733,24 +727,23 @@ void HtmlDocVisitor::visit(DocInclude *inc) if (inc->isBlock()) forceStartParagraph(inc); } break; - case DocInclude::VerbInclude: + case DocInclude::VerbInclude: forceEndParagraph(inc); - m_t << /*PREFRAG_START <<*/ "<pre class=\"fragment\">"; + m_t << "<pre class=\"fragment\">"; filter(inc->text()); - m_t << "</pre>" /*<< PREFRAG_END*/; + m_t << "</pre>"; forceStartParagraph(inc); break; case DocInclude::Snippet: { forceEndParagraph(inc); - m_t << PREFRAG_START; - Doxygen::parserManager->getCodeParser(inc->extension()) - .parseCode(m_ci, + m_ci.startCodeFragment("DoxyCode"); + getCodeParser(inc->extension()).parseCode(m_ci, inc->context(), extractBlock(inc->text(),inc->blockId()), langExt, inc->isExample(), - inc->exampleFile(), + inc->exampleFile(), 0, -1, // startLine -1, // endLine @@ -759,23 +752,22 @@ void HtmlDocVisitor::visit(DocInclude *inc) FALSE, // show line number m_ctx // search context ); - m_t << PREFRAG_END; + m_ci.endCodeFragment(); forceStartParagraph(inc); } break; case DocInclude::SnipWithLines: { forceEndParagraph(inc); - m_t << PREFRAG_START; + m_ci.startCodeFragment("DoxyCode"); QFileInfo cfi( inc->file() ); FileDef *fd = createFileDef( cfi.dirPath().utf8(), cfi.fileName().utf8() ); - Doxygen::parserManager->getCodeParser(inc->extension()) - .parseCode(m_ci, + getCodeParser(inc->extension()).parseCode(m_ci, inc->context(), extractBlock(inc->text(),inc->blockId()), langExt, inc->isExample(), - inc->exampleFile(), + inc->exampleFile(), fd, lineBlock(inc->text(),inc->blockId()), -1, // endLine @@ -785,12 +777,12 @@ void HtmlDocVisitor::visit(DocInclude *inc) m_ctx // search context ); delete fd; - m_t << PREFRAG_END; + m_ci.endCodeFragment(); forceStartParagraph(inc); } break; - case DocInclude::SnippetDoc: - case DocInclude::IncludeDoc: + case DocInclude::SnippetDoc: + case DocInclude::IncludeDoc: err("Internal inconsistency: found switch SnippetDoc / IncludeDoc in file: %s" "Please create a bug report\n",__FILE__); break; @@ -801,20 +793,20 @@ void HtmlDocVisitor::visit(DocIncOperator *op) { //printf("DocIncOperator: type=%d first=%d, last=%d text='%s'\n", // op->type(),op->isFirst(),op->isLast(),op->text().data()); - if (op->isFirst()) + if (op->isFirst()) { forceEndParagraph(op); - if (!m_hide) m_t << PREFRAG_START; + if (!m_hide) m_ci.startCodeFragment("DoxyCode"); pushEnabled(); m_hide=TRUE; } QCString locLangExt = getFileNameExtension(op->includeFileName()); if (locLangExt.isEmpty()) locLangExt = m_langExt; SrcLangExt langExt = getLanguageFromFileName(locLangExt); - if (op->type()!=DocIncOperator::Skip) + if (op->type()!=DocIncOperator::Skip) { popEnabled(); - if (!m_hide) + if (!m_hide) { FileDef *fd = 0; if (!op->includeFileName().isEmpty()) @@ -822,8 +814,7 @@ void HtmlDocVisitor::visit(DocIncOperator *op) QFileInfo cfi( op->includeFileName() ); fd = createFileDef( cfi.dirPath().utf8(), cfi.fileName().utf8() ); } - Doxygen::parserManager->getCodeParser(locLangExt) - .parseCode( + getCodeParser(locLangExt).parseCode( m_ci, op->context(), op->text(), @@ -843,10 +834,10 @@ void HtmlDocVisitor::visit(DocIncOperator *op) pushEnabled(); m_hide=TRUE; } - if (op->isLast()) + if (op->isLast()) { popEnabled(); - if (!m_hide) m_t << PREFRAG_END; + if (!m_hide) m_ci.endCodeFragment(); forceStartParagraph(op); } else @@ -859,7 +850,7 @@ void HtmlDocVisitor::visit(DocFormula *f) { if (m_hide) return; bool bDisplay = !f->isInline(); - if (bDisplay) + if (bDisplay) { forceEndParagraph(f); m_t << "<p class=\"formulaDsp\">" << endl; @@ -869,7 +860,7 @@ void HtmlDocVisitor::visit(DocFormula *f) { QCString text = f->text(); bool closeInline = FALSE; - if (!bDisplay && !text.isEmpty() && text.at(0)=='$' && + if (!bDisplay && !text.isEmpty() && text.at(0)=='$' && text.at(text.length()-1)=='$') { closeInline=TRUE; @@ -884,7 +875,7 @@ void HtmlDocVisitor::visit(DocFormula *f) } else { - m_t << "<img class=\"formula" + m_t << "<img class=\"formula" << (bDisplay ? "Dsp" : "Inl"); m_t << "\" alt=\""; filterQuotedCdataAttr(f->text()); @@ -919,7 +910,7 @@ void HtmlDocVisitor::visit(DocFormula *f) void HtmlDocVisitor::visit(DocIndexEntry *e) { QCString anchor = convertIndexWordToAnchor(e->entry()); - if (e->member()) + if (e->member()) { anchor.prepend(e->member()->anchor()+"_"); } @@ -941,7 +932,7 @@ void HtmlDocVisitor::visit(DocSimpleSectSep *) void HtmlDocVisitor::visit(DocCite *cite) { if (m_hide) return; - if (!cite->file().isEmpty()) + if (!cite->file().isEmpty()) { startLink(cite->ref(),cite->file(),cite->relPath(),cite->anchor()); } @@ -950,7 +941,7 @@ void HtmlDocVisitor::visit(DocCite *cite) m_t << "<b>["; } filter(cite->text()); - if (!cite->file().isEmpty()) + if (!cite->file().isEmpty()) { endLink(); } @@ -978,7 +969,7 @@ void HtmlDocVisitor::visitPre(DocAutoList *l) // 1. // a. // i. - // A. + // A. // 1. (repeat)... // m_t << "<ol type=\"" << types[l->depth() % NUM_HTML_LIST_TYPES] << "\""; @@ -1013,20 +1004,20 @@ void HtmlDocVisitor::visitPre(DocAutoListItem *) m_t << "<li>"; } -void HtmlDocVisitor::visitPost(DocAutoListItem *li) +void HtmlDocVisitor::visitPost(DocAutoListItem *li) { if (m_hide) return; m_t << "</li>"; if (!li->isPreformatted()) m_t << "\n"; } -template<class T> +template<class T> bool isFirstChildNode(T *parent, DocNode *node) { return parent->children().getFirst()==node; } -template<class T> +template<class T> bool isLastChildNode(T *parent, DocNode *node) { return parent->children().getLast()==node; @@ -1070,7 +1061,7 @@ static int getParagraphContext(DocPara *p,bool &isFirst,bool &isLast) isLast=FALSE; if (p && p->parent()) { - switch (p->parent()->kind()) + switch (p->parent()->kind()) { case DocNode::Kind_ParBlock: { // hierarchy: node N -> para -> parblock -> para @@ -1215,7 +1206,7 @@ static int getParagraphContext(DocPara *p,bool &isFirst,bool &isLast) return t; } -void HtmlDocVisitor::visitPre(DocPara *p) +void HtmlDocVisitor::visitPre(DocPara *p) { if (m_hide) return; @@ -1223,9 +1214,9 @@ void HtmlDocVisitor::visitPre(DocPara *p) // p->parent() ? p->parent()->kind() : -1); bool needsTag = FALSE; - if (p && p->parent()) + if (p && p->parent()) { - switch (p->parent()->kind()) + switch (p->parent()->kind()) { case DocNode::Kind_Section: case DocNode::Kind_Internal: @@ -1250,7 +1241,7 @@ void HtmlDocVisitor::visitPre(DocPara *p) } // if the first element of a paragraph is something that should be outside of - // the paragraph (<ul>,<dl>,<table>,..) then that will already started the + // the paragraph (<ul>,<dl>,<table>,..) then that will already started the // paragraph and we don't need to do it here bool paragraphAlreadyStarted = false; uint nodeIndex = 0; @@ -1296,9 +1287,9 @@ void HtmlDocVisitor::visitPost(DocPara *p) // p->parent() ? p->parent()->kind() : -1); bool needsTag = FALSE; - if (p->parent()) + if (p->parent()) { - switch (p->parent()->kind()) + switch (p->parent()->kind()) { case DocNode::Kind_Section: case DocNode::Kind_Internal: @@ -1323,7 +1314,7 @@ void HtmlDocVisitor::visitPost(DocPara *p) } // if the last element of a paragraph is something that should be outside of - // the paragraph (<ul>,<dl>,<table>) then that will already have ended the + // the paragraph (<ul>,<dl>,<table>) then that will already have ended the // paragraph and we don't need to do it here int nodeIndex = p->children().count()-1; if (nodeIndex>=0) @@ -1372,21 +1363,21 @@ void HtmlDocVisitor::visitPre(DocSimpleSect *s) m_t << "<dl class=\"section " << s->typeString() << "\"><dt>"; switch(s->type()) { - case DocSimpleSect::See: + case DocSimpleSect::See: m_t << theTranslator->trSeeAlso(); break; - case DocSimpleSect::Return: + case DocSimpleSect::Return: m_t << theTranslator->trReturns(); break; - case DocSimpleSect::Author: + case DocSimpleSect::Author: m_t << theTranslator->trAuthor(TRUE,TRUE); break; - case DocSimpleSect::Authors: + case DocSimpleSect::Authors: m_t << theTranslator->trAuthor(TRUE,FALSE); break; - case DocSimpleSect::Version: + case DocSimpleSect::Version: m_t << theTranslator->trVersion(); break; - case DocSimpleSect::Since: + case DocSimpleSect::Since: m_t << theTranslator->trSince(); break; - case DocSimpleSect::Date: + case DocSimpleSect::Date: m_t << theTranslator->trDate(); break; - case DocSimpleSect::Note: + case DocSimpleSect::Note: m_t << theTranslator->trNote(); break; case DocSimpleSect::Warning: m_t << theTranslator->trWarning(); break; @@ -1454,7 +1445,7 @@ void HtmlDocVisitor::visitPre(DocSimpleListItem *) m_t << "<li>"; } -void HtmlDocVisitor::visitPost(DocSimpleListItem *li) +void HtmlDocVisitor::visitPost(DocSimpleListItem *li) { if (m_hide) return; m_t << "</li>"; @@ -1472,7 +1463,7 @@ void HtmlDocVisitor::visitPre(DocSection *s) m_t << "</h" << s->level() << ">\n"; } -void HtmlDocVisitor::visitPost(DocSection *s) +void HtmlDocVisitor::visitPost(DocSection *s) { forceStartParagraph(s); } @@ -1481,26 +1472,26 @@ void HtmlDocVisitor::visitPre(DocHtmlList *s) { if (m_hide) return; forceEndParagraph(s); - if (s->type()==DocHtmlList::Ordered) + if (s->type()==DocHtmlList::Ordered) { - m_t << "<ol" << htmlAttribsToString(s->attribs()); + m_t << "<ol" << htmlAttribsToString(s->attribs()); } - else + else { m_t << "<ul" << htmlAttribsToString(s->attribs()); } m_t << getDirHtmlClassOfNode(getTextDirByConfig(s)) << ">\n"; } -void HtmlDocVisitor::visitPost(DocHtmlList *s) +void HtmlDocVisitor::visitPost(DocHtmlList *s) { if (m_hide) return; - if (s->type()==DocHtmlList::Ordered) + if (s->type()==DocHtmlList::Ordered) { - m_t << "</ol>"; + m_t << "</ol>"; } else - { + { m_t << "</ul>"; } if (!s->isPreformatted()) m_t << "\n"; @@ -1514,7 +1505,7 @@ void HtmlDocVisitor::visitPre(DocHtmlListItem *i) if (!i->isPreformatted()) m_t << "\n"; } -void HtmlDocVisitor::visitPost(DocHtmlListItem *) +void HtmlDocVisitor::visitPost(DocHtmlListItem *) { if (m_hide) return; m_t << "</li>\n"; @@ -1527,7 +1518,7 @@ void HtmlDocVisitor::visitPre(DocHtmlDescList *dl) m_t << "<dl" << htmlAttribsToString(dl->attribs()) << ">\n"; } -void HtmlDocVisitor::visitPost(DocHtmlDescList *dl) +void HtmlDocVisitor::visitPost(DocHtmlDescList *dl) { if (m_hide) return; m_t << "</dl>\n"; @@ -1542,7 +1533,7 @@ void HtmlDocVisitor::visitPre(DocHtmlDescTitle *dt) << ">"; } -void HtmlDocVisitor::visitPost(DocHtmlDescTitle *) +void HtmlDocVisitor::visitPost(DocHtmlDescTitle *) { if (m_hide) return; m_t << "</dt>\n"; @@ -1551,12 +1542,12 @@ void HtmlDocVisitor::visitPost(DocHtmlDescTitle *) void HtmlDocVisitor::visitPre(DocHtmlDescData *dd) { if (m_hide) return; - m_t << "<dd" << htmlAttribsToString(dd->attribs()) + m_t << "<dd" << htmlAttribsToString(dd->attribs()) << getDirHtmlClassOfNode(getTextDirByConfig(dd)) << ">"; } -void HtmlDocVisitor::visitPost(DocHtmlDescData *) +void HtmlDocVisitor::visitPost(DocHtmlDescData *) { if (m_hide) return; m_t << "</dd>\n"; @@ -1598,7 +1589,7 @@ void HtmlDocVisitor::visitPre(DocHtmlTable *t) } } -void HtmlDocVisitor::visitPost(DocHtmlTable *t) +void HtmlDocVisitor::visitPost(DocHtmlTable *t) { if (m_hide) return; m_t << "</table>\n"; @@ -1611,7 +1602,7 @@ void HtmlDocVisitor::visitPre(DocHtmlRow *tr) m_t << "<tr" << htmlAttribsToString(tr->attribs()) << ">\n"; } -void HtmlDocVisitor::visitPost(DocHtmlRow *) +void HtmlDocVisitor::visitPost(DocHtmlRow *) { if (m_hide) return; m_t << "</tr>\n"; @@ -1620,17 +1611,17 @@ void HtmlDocVisitor::visitPost(DocHtmlRow *) void HtmlDocVisitor::visitPre(DocHtmlCell *c) { if (m_hide) return; - if (c->isHeading()) + if (c->isHeading()) { - m_t << "<th" << htmlAttribsToString(c->attribs()) << ">"; + m_t << "<th" << htmlAttribsToString(c->attribs()) << ">"; } - else + else { m_t << "<td" << htmlAttribsToString(c->attribs()) << ">"; } } -void HtmlDocVisitor::visitPost(DocHtmlCell *c) +void HtmlDocVisitor::visitPost(DocHtmlCell *c) { if (m_hide) return; if (c->isHeading()) m_t << "</th>"; else m_t << "</td>"; @@ -1642,7 +1633,7 @@ void HtmlDocVisitor::visitPre(DocHtmlCaption *c) m_t << "<caption" << htmlAttribsToString(c->attribs()) << ">"; } -void HtmlDocVisitor::visitPost(DocHtmlCaption *) +void HtmlDocVisitor::visitPost(DocHtmlCaption *) { if (m_hide) return; m_t << "</caption>\n"; @@ -1655,7 +1646,7 @@ void HtmlDocVisitor::visitPre(DocInternal *) //m_t << "<p><b>" << theTranslator->trForInternalUseOnly() << "</b></p>" << endl; } -void HtmlDocVisitor::visitPost(DocInternal *) +void HtmlDocVisitor::visitPost(DocInternal *) { if (m_hide) return; //forceStartParagraph(i); @@ -1676,7 +1667,7 @@ void HtmlDocVisitor::visitPre(DocHRef *href) } } -void HtmlDocVisitor::visitPost(DocHRef *) +void HtmlDocVisitor::visitPost(DocHRef *) { if (m_hide) return; m_t << "</a>"; @@ -1686,13 +1677,13 @@ void HtmlDocVisitor::visitPre(DocHtmlHeader *header) { if (m_hide) return; forceEndParagraph(header); - m_t << "<h" << header->level() - << htmlAttribsToString(header->attribs()) + m_t << "<h" << header->level() + << htmlAttribsToString(header->attribs()) << getDirHtmlClassOfNode(getTextDirByConfig(header)) << ">"; } -void HtmlDocVisitor::visitPost(DocHtmlHeader *header) +void HtmlDocVisitor::visitPost(DocHtmlHeader *header) { if (m_hide) return; m_t << "</h" << header->level() << ">\n"; @@ -1834,12 +1825,12 @@ void HtmlDocVisitor::visitPre(DocDotFile *df) m_t << "<div class=\"dotgraph\">" << endl; writeDotFile(df->file(),df->relPath(),df->context()); if (df->hasCaption()) - { + { m_t << "<div class=\"caption\">" << endl; } } -void HtmlDocVisitor::visitPost(DocDotFile *df) +void HtmlDocVisitor::visitPost(DocDotFile *df) { if (m_hide) return; if (df->hasCaption()) @@ -1855,11 +1846,11 @@ void HtmlDocVisitor::visitPre(DocMscFile *df) m_t << "<div class=\"mscgraph\">" << endl; writeMscFile(df->file(),df->relPath(),df->context()); if (df->hasCaption()) - { + { m_t << "<div class=\"caption\">" << endl; } } -void HtmlDocVisitor::visitPost(DocMscFile *df) +void HtmlDocVisitor::visitPost(DocMscFile *df) { if (m_hide) return; if (df->hasCaption()) @@ -1895,7 +1886,7 @@ void HtmlDocVisitor::visitPre(DocLink *lnk) startLink(lnk->ref(),lnk->file(),lnk->relPath(),lnk->anchor()); } -void HtmlDocVisitor::visitPost(DocLink *) +void HtmlDocVisitor::visitPost(DocLink *) { if (m_hide) return; endLink(); @@ -1904,7 +1895,7 @@ void HtmlDocVisitor::visitPost(DocLink *) void HtmlDocVisitor::visitPre(DocRef *ref) { if (m_hide) return; - if (!ref->file().isEmpty()) + if (!ref->file().isEmpty()) { // when ref->isSubPage()==TRUE we use ref->file() for HTML and // ref->anchor() for LaTeX/RTF @@ -1913,7 +1904,7 @@ void HtmlDocVisitor::visitPre(DocRef *ref) if (!ref->hasLinkText()) filter(ref->targetTitle()); } -void HtmlDocVisitor::visitPost(DocRef *ref) +void HtmlDocVisitor::visitPost(DocRef *ref) { if (m_hide) return; if (!ref->file().isEmpty()) endLink(); @@ -1928,7 +1919,7 @@ void HtmlDocVisitor::visitPre(DocSecRefItem *ref) } -void HtmlDocVisitor::visitPost(DocSecRefItem *) +void HtmlDocVisitor::visitPost(DocSecRefItem *) { if (m_hide) return; m_t << "</a></li>\n"; @@ -1942,7 +1933,7 @@ void HtmlDocVisitor::visitPre(DocSecRefList *s) m_t << "<ul class=\"multicol\">" << endl; } -void HtmlDocVisitor::visitPost(DocSecRefList *s) +void HtmlDocVisitor::visitPost(DocSecRefList *s) { if (m_hide) return; m_t << "</ul>" << endl; @@ -1960,7 +1951,7 @@ void HtmlDocVisitor::visitPost(DocSecRefList *s) // } //} // -//void HtmlDocVisitor::visitPost(DocLanguage *l) +//void HtmlDocVisitor::visitPost(DocLanguage *l) //{ // QCString langId = Config_getEnum(OUTPUT_LANGUAGE); // if (l->id().lower()!=langId.lower()) @@ -1977,19 +1968,19 @@ void HtmlDocVisitor::visitPre(DocParamSect *s) QCString heading; switch(s->type()) { - case DocParamSect::Param: - heading=theTranslator->trParameters(); + case DocParamSect::Param: + heading=theTranslator->trParameters(); className="params"; break; - case DocParamSect::RetVal: - heading=theTranslator->trReturnValues(); + case DocParamSect::RetVal: + heading=theTranslator->trReturnValues(); className="retval"; break; - case DocParamSect::Exception: - heading=theTranslator->trExceptions(); + case DocParamSect::Exception: + heading=theTranslator->trExceptions(); className="exception"; break; - case DocParamSect::TemplateParam: + case DocParamSect::TemplateParam: heading=theTranslator->trTemplateParameters(); className="tparams"; break; @@ -2052,11 +2043,11 @@ void HtmlDocVisitor::visitPre(DocParamList *pl) { if (type->kind()==DocNode::Kind_Word) { - visit((DocWord*)type); + visit((DocWord*)type); } else if (type->kind()==DocNode::Kind_LinkedWord) { - visit((DocLinkedWord*)type); + visit((DocLinkedWord*)type); } else if (type->kind()==DocNode::Kind_Sep) { @@ -2076,11 +2067,11 @@ void HtmlDocVisitor::visitPre(DocParamList *pl) if (!first) m_t << ","; else first=FALSE; if (param->kind()==DocNode::Kind_Word) { - visit((DocWord*)param); + visit((DocWord*)param); } else if (param->kind()==DocNode::Kind_LinkedWord) { - visit((DocLinkedWord*)param); + visit((DocLinkedWord*)param); } } m_t << "</td><td>"; @@ -2102,12 +2093,12 @@ void HtmlDocVisitor::visitPre(DocXRefItem *x) bool anonymousEnum = x->file()=="@"; if (!anonymousEnum) { - m_t << "<dl" << getDirHtmlClassOfNode(getTextDirByConfig(x), x->key()) + m_t << "<dl" << getDirHtmlClassOfNode(getTextDirByConfig(x), x->key()) << "><dt><b><a class=\"el\" href=\"" << x->relPath() << addHtmlExtensionIfMissing(x->file()) << "#" << x->anchor() << "\">"; } - else + else { m_t << "<dl class=\"" << x->key() << "\"><dt><b>"; } @@ -2131,7 +2122,7 @@ void HtmlDocVisitor::visitPre(DocInternalRef *ref) startLink(0,ref->file(),ref->relPath(),ref->anchor()); } -void HtmlDocVisitor::visitPost(DocInternalRef *) +void HtmlDocVisitor::visitPost(DocInternalRef *) { if (m_hide) return; endLink(); @@ -2180,7 +2171,7 @@ void HtmlDocVisitor::visitPre(DocVhdlFlow *vf) m_t << "<p>"; m_t << "flowchart: " ; // TODO: translate me m_t << "<a href=\""; - m_t << fname.data(); + m_t << fname.data(); m_t << ".svg\">"; m_t << VhdlDocGen::getFlowMember()->name().data(); m_t << "</a>"; @@ -2214,7 +2205,7 @@ void HtmlDocVisitor::visitPost(DocParBlock *) void HtmlDocVisitor::filter(const char *str) -{ +{ if (str==0) return; const char *p=str; char c; diff --git a/src/htmlgen.cpp b/src/htmlgen.cpp index 2c89507..1d7dd72 100644 --- a/src/htmlgen.cpp +++ b/src/htmlgen.cpp @@ -16,8 +16,10 @@ */ #include <stdlib.h> - #include <assert.h> + +#include <mutex> + #include <qdir.h> #include <qregexp.h> #include "message.h" @@ -59,8 +61,6 @@ static QCString g_footer; static QCString g_mathjax_code; static QCString g_latex_macro; -static bool DoxyCodeLineOpen = FALSE; - // note: this is only active if DISABLE_INDEX=YES, if DISABLE_INDEX is disabled, this // part will be rendered inside menu.js static void writeClientSearchBox(FTextStream &t,const char *relPath) @@ -608,12 +608,11 @@ static QCString substituteHtmlKeywords(const QCString &str, //-------------------------------------------------------------------------- HtmlCodeGenerator::HtmlCodeGenerator() - : m_streamSet(FALSE), m_col(0) { } HtmlCodeGenerator::HtmlCodeGenerator(FTextStream &t,const QCString &relPath) - : m_col(0), m_relPath(relPath) + : m_relPath(relPath) { setTextStream(t); } @@ -726,10 +725,10 @@ void HtmlCodeGenerator::writeLineNumber(const char *ref,const char *filename, qsnprintf(lineNumber,maxLineNrStr,"%5d",l); qsnprintf(lineAnchor,maxLineNrStr,"l%05d",l); - if (!DoxyCodeLineOpen) + if (!m_lineOpen) { m_t << "<div class=\"line\">"; - DoxyCodeLineOpen = TRUE; + m_lineOpen = TRUE; } m_t << "<a name=\"" << lineAnchor << "\"></a><span class=\"lineno\">"; @@ -868,10 +867,10 @@ void HtmlCodeGenerator::startCodeLine(bool) if (m_streamSet) { m_col=0; - if (!DoxyCodeLineOpen) + if (!m_lineOpen) { m_t << "<div class=\"line\">"; - DoxyCodeLineOpen = TRUE; + m_lineOpen = TRUE; } } } @@ -885,10 +884,10 @@ void HtmlCodeGenerator::endCodeLine() m_t << " "; m_col++; } - if (DoxyCodeLineOpen) + if (m_lineOpen) { m_t << "</div>\n"; - DoxyCodeLineOpen = FALSE; + m_lineOpen = FALSE; } } } @@ -908,6 +907,20 @@ void HtmlCodeGenerator::writeCodeAnchor(const char *anchor) if (m_streamSet) m_t << "<a name=\"" << anchor << "\"></a>"; } +void HtmlCodeGenerator::startCodeFragment(const char *) +{ + if (m_streamSet) m_t << "<div class=\"fragment\">"; +} + +void HtmlCodeGenerator::endCodeFragment() +{ + //endCodeLine checks is there is still an open code line, if so closes it. + endCodeLine(); + + if (m_streamSet) m_t << "</div><!-- fragment -->"; +} + + //-------------------------------------------------------------------------- HtmlGenerator::HtmlGenerator() : OutputGenerator(Config_getString(HTML_OUTPUT)) @@ -1114,6 +1127,8 @@ void HtmlGenerator::writeFooterFile(QFile &file) t << ResourceMgr::instance().getAsString("footer.html"); } +static std::mutex g_indexLock; + void HtmlGenerator::startFile(const char *name,const char *, const char *title) { @@ -1125,7 +1140,10 @@ void HtmlGenerator::startFile(const char *name,const char *, startPlainFile(fileName); m_codeGen.setTextStream(t); m_codeGen.setRelativePath(m_relPath); - Doxygen::indexList->addIndexFile(fileName); + { + std::lock_guard<std::mutex> lock(g_indexLock); + Doxygen::indexList->addIndexFile(fileName); + } m_lastFile = fileName; t << substituteHtmlKeywords(g_header,convertToHtml(filterTitle(title)),m_relPath); @@ -2861,19 +2879,6 @@ void HtmlGenerator::endConstraintList() t << "</div>" << endl; } -void HtmlGenerator::startCodeFragment() -{ - t << PREFRAG_START; -} - -void HtmlGenerator::endCodeFragment() -{ - //endCodeLine checks is there is still an open code line, if so closes it. - endCodeLine(); - - t << PREFRAG_END; -} - void HtmlGenerator::lineBreak(const char *style) { if (style) diff --git a/src/htmlgen.h b/src/htmlgen.h index 9487e60..ff77fe7 100644 --- a/src/htmlgen.h +++ b/src/htmlgen.h @@ -1,8 +1,6 @@ /****************************************************************************** * - * - * - * Copyright (C) 1997-2015 by Dimitri van Heesch. + * Copyright (C) 1997-2020 by Dimitri van Heesch. * * Permission to use, copy, modify, and distribute this software and its * documentation under the terms of the GNU General Public License is hereby @@ -21,11 +19,6 @@ #include "outputgen.h" #include "ftextstream.h" -//#define PREFRAG_START "<div class=\"fragment\"><pre class=\"fragment\">" -//#define PREFRAG_END "</pre></div>" -#define PREFRAG_START "<div class=\"fragment\">" -#define PREFRAG_END "</div><!-- fragment -->" - class QFile; class HtmlCodeGenerator : public CodeOutputInterface @@ -54,6 +47,8 @@ class HtmlCodeGenerator : public CodeOutputInterface void writeCodeAnchor(const char *anchor); void setCurrentDoc(const Definition *,const char *,bool) {} void addWord(const char *,bool) {} + void startCodeFragment(const char *style); + void endCodeFragment(); private: void _writeCodeLink(const char *className, @@ -61,10 +56,11 @@ class HtmlCodeGenerator : public CodeOutputInterface const char *anchor,const char *name, const char *tooltip); void docify(const char *str); - bool m_streamSet; + bool m_streamSet = false; FTextStream m_t; - int m_col; + int m_col = 0; QCString m_relPath; + bool m_lineOpen = false; }; /** Generator for HTML output */ @@ -113,6 +109,10 @@ class HtmlGenerator : public OutputGenerator { m_codeGen.endFontClass(); } void writeCodeAnchor(const char *anchor) { m_codeGen.writeCodeAnchor(anchor); } + void startCodeFragment(const char *style) + { m_codeGen.startCodeFragment(style); } + void endCodeFragment() + { m_codeGen.endCodeFragment(); } // --------------------------- void setCurrentDoc(const Definition *context,const char *anchor,bool isSourceFile); @@ -208,8 +208,6 @@ class HtmlGenerator : public OutputGenerator void writeRuler() { t << "<hr/>"; } void writeAnchor(const char *,const char *name) { t << "<a name=\"" << name <<"\" id=\"" << name << "\"></a>"; } - void startCodeFragment(); - void endCodeFragment(); void startEmphasis() { t << "<em>"; } void endEmphasis() { t << "</em>"; } void startBold() { t << "<b>"; } diff --git a/src/latexdocvisitor.cpp b/src/latexdocvisitor.cpp index 19f01b0..6c20792 100644 --- a/src/latexdocvisitor.cpp +++ b/src/latexdocvisitor.cpp @@ -175,7 +175,7 @@ QCString LatexDocVisitor::escapeMakeIndexChars(const char *s) } -LatexDocVisitor::LatexDocVisitor(FTextStream &t,CodeOutputInterface &ci, +LatexDocVisitor::LatexDocVisitor(FTextStream &t,LatexCodeGenerator &ci, const char *langExt,bool insideTabbing) : DocVisitor(DocVisitor_Latex), m_t(t), m_ci(ci), m_insidePre(FALSE), m_insideItem(FALSE), m_hide(FALSE), m_hideCaption(FALSE), m_insideTabbing(insideTabbing), @@ -351,13 +351,10 @@ void LatexDocVisitor::visit(DocVerbatim *s) { case DocVerbatim::Code: { - m_t << "\n\\begin{DoxyCode}{" << usedTableLevels() << "}\n"; - LatexCodeGenerator::setDoxyCodeOpen(TRUE); - Doxygen::parserManager->getCodeParser(lang) - .parseCode(m_ci,s->context(),s->text(),langExt, - s->isExample(),s->exampleFile()); - LatexCodeGenerator::setDoxyCodeOpen(FALSE); - m_t << "\\end{DoxyCode}\n"; + m_ci.startCodeFragment("DoxyCode"); + getCodeParser(lang).parseCode(m_ci,s->context(),s->text(),langExt, + s->isExample(),s->exampleFile()); + m_ci.endCodeFragment(); } break; case DocVerbatim::Verbatim: @@ -461,44 +458,40 @@ void LatexDocVisitor::visit(DocInclude *inc) { case DocInclude::IncWithLines: { - m_t << "\n\\begin{DoxyCodeInclude}{" << usedTableLevels() << "}\n"; - LatexCodeGenerator::setDoxyCodeOpen(TRUE); - QFileInfo cfi( inc->file() ); - FileDef *fd = createFileDef( cfi.dirPath().utf8(), cfi.fileName().utf8() ); - Doxygen::parserManager->getCodeParser(inc->extension()) - .parseCode(m_ci,inc->context(), - inc->text(), - langExt, - inc->isExample(), - inc->exampleFile(), - fd, // fileDef, - -1, // start line - -1, // end line - FALSE, // inline fragment - 0, // memberDef - TRUE // show line numbers - ); - delete fd; - LatexCodeGenerator::setDoxyCodeOpen(FALSE); - m_t << "\\end{DoxyCodeInclude}" << endl; + m_ci.startCodeFragment("DoxyCodeInclude"); + QFileInfo cfi( inc->file() ); + FileDef *fd = createFileDef( cfi.dirPath().utf8(), cfi.fileName().utf8() ); + getCodeParser(inc->extension()).parseCode(m_ci,inc->context(), + inc->text(), + langExt, + inc->isExample(), + inc->exampleFile(), + fd, // fileDef, + -1, // start line + -1, // end line + FALSE, // inline fragment + 0, // memberDef + TRUE // show line numbers + ); + delete fd; + m_ci.endCodeFragment(); } break; case DocInclude::Include: - m_t << "\n\\begin{DoxyCodeInclude}{" << usedTableLevels() << "}\n"; - LatexCodeGenerator::setDoxyCodeOpen(TRUE); - Doxygen::parserManager->getCodeParser(inc->extension()) - .parseCode(m_ci,inc->context(), - inc->text(),langExt,inc->isExample(), - inc->exampleFile(), - 0, // fileDef - -1, // startLine - -1, // endLine - TRUE, // inlineFragment - 0, // memberDef - FALSE - ); - LatexCodeGenerator::setDoxyCodeOpen(FALSE); - m_t << "\\end{DoxyCodeInclude}\n"; + { + m_ci.startCodeFragment("DoxyCodeInclude"); + getCodeParser(inc->extension()).parseCode(m_ci,inc->context(), + inc->text(),langExt,inc->isExample(), + inc->exampleFile(), + 0, // fileDef + -1, // startLine + -1, // endLine + TRUE, // inlineFragment + 0, // memberDef + FALSE + ); + m_ci.endCodeFragment(); + } break; case DocInclude::DontInclude: case DocInclude::DontIncWithLines: @@ -518,43 +511,37 @@ void LatexDocVisitor::visit(DocInclude *inc) break; case DocInclude::Snippet: { - m_t << "\n\\begin{DoxyCodeInclude}{" << usedTableLevels() << "}\n"; - LatexCodeGenerator::setDoxyCodeOpen(TRUE); - Doxygen::parserManager->getCodeParser(inc->extension()) - .parseCode(m_ci, - inc->context(), - extractBlock(inc->text(),inc->blockId()), - langExt, - inc->isExample(), - inc->exampleFile() - ); - LatexCodeGenerator::setDoxyCodeOpen(FALSE); - m_t << "\\end{DoxyCodeInclude}" << endl; + m_ci.startCodeFragment("DoxyCodeInclude"); + getCodeParser(inc->extension()).parseCode(m_ci, + inc->context(), + extractBlock(inc->text(),inc->blockId()), + langExt, + inc->isExample(), + inc->exampleFile() + ); + m_ci.endCodeFragment(); } break; case DocInclude::SnipWithLines: { - QFileInfo cfi( inc->file() ); - FileDef *fd = createFileDef( cfi.dirPath().utf8(), cfi.fileName().utf8() ); - m_t << "\n\\begin{DoxyCodeInclude}{" << usedTableLevels() << "}\n"; - LatexCodeGenerator::setDoxyCodeOpen(TRUE); - Doxygen::parserManager->getCodeParser(inc->extension()) - .parseCode(m_ci, - inc->context(), - extractBlock(inc->text(),inc->blockId()), - langExt, - inc->isExample(), - inc->exampleFile(), - fd, - lineBlock(inc->text(),inc->blockId()), - -1, // endLine - FALSE, // inlineFragment - 0, // memberDef - TRUE // show line number - ); - delete fd; - LatexCodeGenerator::setDoxyCodeOpen(FALSE); - m_t << "\\end{DoxyCodeInclude}" << endl; + QFileInfo cfi( inc->file() ); + FileDef *fd = createFileDef( cfi.dirPath().utf8(), cfi.fileName().utf8() ); + m_ci.startCodeFragment("DoxyCodeInclude"); + getCodeParser(inc->extension()).parseCode(m_ci, + inc->context(), + extractBlock(inc->text(),inc->blockId()), + langExt, + inc->isExample(), + inc->exampleFile(), + fd, + lineBlock(inc->text(),inc->blockId()), + -1, // endLine + FALSE, // inlineFragment + 0, // memberDef + TRUE // show line number + ); + delete fd; + m_ci.endCodeFragment(); } break; case DocInclude::SnippetDoc: @@ -571,8 +558,7 @@ void LatexDocVisitor::visit(DocIncOperator *op) // op->type(),op->isFirst(),op->isLast(),op->text().data()); if (op->isFirst()) { - if (!m_hide) m_t << "\n\\begin{DoxyCodeInclude}{" << usedTableLevels() << "}\n"; - LatexCodeGenerator::setDoxyCodeOpen(TRUE); + if (!m_hide) m_ci.startCodeFragment("DoxyCodeInclude"); pushEnabled(); m_hide = TRUE; } @@ -591,16 +577,15 @@ void LatexDocVisitor::visit(DocIncOperator *op) fd = createFileDef( cfi.dirPath().utf8(), cfi.fileName().utf8() ); } - Doxygen::parserManager->getCodeParser(locLangExt) - .parseCode(m_ci,op->context(),op->text(),langExt, - op->isExample(),op->exampleFile(), - fd, // fileDef - op->line(), // startLine - -1, // endLine - FALSE, // inline fragment - 0, // memberDef - op->showLineNo() // show line numbers - ); + getCodeParser(locLangExt).parseCode(m_ci,op->context(),op->text(),langExt, + op->isExample(),op->exampleFile(), + fd, // fileDef + op->line(), // startLine + -1, // endLine + FALSE, // inline fragment + 0, // memberDef + op->showLineNo() // show line numbers + ); if (fd) delete fd; } pushEnabled(); @@ -609,8 +594,7 @@ void LatexDocVisitor::visit(DocIncOperator *op) if (op->isLast()) { popEnabled(); - LatexCodeGenerator::setDoxyCodeOpen(FALSE); - if (!m_hide) m_t << "\n\\end{DoxyCodeInclude}\n"; + if (!m_hide) m_ci.endCodeFragment(); } else { @@ -1504,7 +1488,7 @@ void LatexDocVisitor::visitPre(DocParamSect *s) if (m_hide) return; bool hasInOutSpecs = s->hasInOutSpecifier(); bool hasTypeSpecs = s->hasTypeSpecifier(); - incUsedTableLevels(); + m_ci.incUsedTableLevel(); switch(s->type()) { case DocParamSect::Param: @@ -1535,7 +1519,7 @@ void LatexDocVisitor::visitPre(DocParamSect *s) void LatexDocVisitor::visitPost(DocParamSect *s) { if (m_hide) return; - decUsedTableLevels(); + m_ci.decUsedTableLevel(); switch(s->type()) { case DocParamSect::Param: @@ -1754,7 +1738,13 @@ void LatexDocVisitor::visitPost(DocParBlock *) void LatexDocVisitor::filter(const char *str) { - filterLatexString(m_t,str,m_insideTabbing,m_insidePre,m_insideItem); + filterLatexString(m_t,str, + m_insideTabbing, + m_insidePre, + m_insideItem, + m_ci.usedTableLevel()>0, // insideTable + false // keepSpaces + ); } void LatexDocVisitor::startLink(const QCString &ref,const QCString &file,const QCString &anchor,bool refToTable) diff --git a/src/latexdocvisitor.h b/src/latexdocvisitor.h index 71fb5be..003d780 100644 --- a/src/latexdocvisitor.h +++ b/src/latexdocvisitor.h @@ -1,13 +1,13 @@ /****************************************************************************** * - * + * * * * Copyright (C) 1997-2015 by Dimitri van Heesch. * * Permission to use, copy, modify, and distribute this software and its - * documentation under the terms of the GNU General Public License is hereby - * granted. No representations are made about the suitability of this software + * documentation under the terms of the GNU General Public License is hereby + * granted. No representations are made about the suitability of this software * for any purpose. It is provided "as is" without express or implied warranty. * See the GNU General Public License for more details. * @@ -25,19 +25,19 @@ #include <qlist.h> class FTextStream; -class CodeOutputInterface; +class LatexCodeGenerator; /*! @brief Concrete visitor implementation for LaTeX output. */ class LatexDocVisitor : public DocVisitor { public: - LatexDocVisitor(FTextStream &t,CodeOutputInterface &ci, + LatexDocVisitor(FTextStream &t,LatexCodeGenerator &ci, const char *langExt,bool insideTabbing); - + //-------------------------------------- // visitor functions for leaf nodes //-------------------------------------- - + void visit(DocWord *); void visit(DocLinkedWord *); void visit(DocWhiteSpace *); @@ -59,7 +59,7 @@ class LatexDocVisitor : public DocVisitor //-------------------------------------- // visitor functions for compound nodes //-------------------------------------- - + void visitPre(DocAutoList *); void visitPost(DocAutoList *); void visitPre(DocAutoListItem *); @@ -141,7 +141,7 @@ class LatexDocVisitor : public DocVisitor struct ActiveRowSpan { - ActiveRowSpan(DocHtmlCell *c,int rs,int cs,int col) + ActiveRowSpan(DocHtmlCell *c,int rs,int cs,int col) : cell(c), rowSpan(rs), colSpan(cs), column(col) {} DocHtmlCell *cell; int rowSpan; @@ -152,9 +152,9 @@ class LatexDocVisitor : public DocVisitor typedef QList<ActiveRowSpan> RowSpanList; //-------------------------------------- - // helper functions + // helper functions //-------------------------------------- - + void filter(const char *str); void startLink(const QCString &ref,const QCString &file, const QCString &anchor,bool refToTable=FALSE); @@ -184,7 +184,7 @@ class LatexDocVisitor : public DocVisitor //-------------------------------------- FTextStream &m_t; - CodeOutputInterface &m_ci; + LatexCodeGenerator &m_ci; bool m_insidePre; bool m_insideItem; bool m_hide; @@ -195,7 +195,7 @@ class LatexDocVisitor : public DocVisitor struct TableState { - TableState() : numCols(0), currentColumn(0), inRowSpan(FALSE), + TableState() : numCols(0), currentColumn(0), inRowSpan(FALSE), inColSpan(FALSE), firstRow(FALSE) { rowSpans.setAutoDelete(TRUE); } RowSpanList rowSpans; diff --git a/src/latexgen.cpp b/src/latexgen.cpp index b70f82a..292767e 100644 --- a/src/latexgen.cpp +++ b/src/latexgen.cpp @@ -44,18 +44,14 @@ #include "resourcemgr.h" #include "portable.h" -static bool DoxyCodeOpen = FALSE; -static bool DoxyCodeLineOpen = FALSE; -//------------------------------- - LatexCodeGenerator::LatexCodeGenerator(FTextStream &t,const QCString &relPath,const QCString &sourceFileName) - : m_relPath(relPath), m_sourceFileName(sourceFileName), m_col(0) + : m_relPath(relPath), m_sourceFileName(sourceFileName) { m_prettyCode=Config_getBool(LATEX_SOURCE_CODE); setTextStream(t); } -LatexCodeGenerator::LatexCodeGenerator() : m_streamSet(FALSE), m_col(0) +LatexCodeGenerator::LatexCodeGenerator() { m_prettyCode=Config_getBool(LATEX_SOURCE_CODE); } @@ -85,8 +81,8 @@ void LatexCodeGenerator::codify(const char *str) //char cs[5]; int spacesToNextTabStop; int tabSize = Config_getInt(TAB_SIZE); - static signed char *result = NULL; - static int lresult = 0; + static THREAD_LOCAL signed char *result = NULL; + static THREAD_LOCAL int lresult = 0; int i; while ((c=*p)) { @@ -108,7 +104,9 @@ void LatexCodeGenerator::codify(const char *str) m_col+=spacesToNextTabStop; p++; break; - case '\n': (usedTableLevels()>0 && !DoxyCodeOpen) ? m_t << "\\newline\n" : m_t << '\n'; m_col=0; p++; + case '\n': m_t << '\n'; + m_col=0; + p++; break; default: i=0; @@ -149,14 +147,13 @@ void LatexCodeGenerator::codify(const char *str) COPYCHAR(); } result[i]=0; // add terminator - //if (m_prettyCode) - //{ - filterLatexString(m_t,(const char *)result,FALSE,TRUE); - //} - //else - //{ - // t << result; - //} + filterLatexString(m_t,(const char *)result, + false, // insideTabbing + true, // insidePre + false, // insideItem + m_usedTableLevel>0, // insideTable + false // keepSpaces + ); break; } } @@ -192,10 +189,10 @@ void LatexCodeGenerator::writeLineNumber(const char *ref,const char *fileName,co { bool usePDFLatex = Config_getBool(USE_PDFLATEX); bool pdfHyperlinks = Config_getBool(PDF_HYPERLINKS); - if (!DoxyCodeLineOpen) + if (!m_doxyCodeLineOpen) { m_t << "\\DoxyCodeLine{"; - DoxyCodeLineOpen = TRUE; + m_doxyCodeLineOpen = TRUE; } if (m_prettyCode) { @@ -231,19 +228,19 @@ void LatexCodeGenerator::writeLineNumber(const char *ref,const char *fileName,co void LatexCodeGenerator::startCodeLine(bool) { m_col=0; - if (!DoxyCodeLineOpen) + if (!m_doxyCodeLineOpen) { m_t << "\\DoxyCodeLine{"; - DoxyCodeLineOpen = TRUE; + m_doxyCodeLineOpen = TRUE; } } void LatexCodeGenerator::endCodeLine() { - if (DoxyCodeLineOpen) + if (m_doxyCodeLineOpen) { m_t << "}"; - DoxyCodeLineOpen = FALSE; + m_doxyCodeLineOpen = FALSE; } codify("\n"); } @@ -258,11 +255,20 @@ void LatexCodeGenerator::endFontClass() m_t << "}"; } -void LatexCodeGenerator::setDoxyCodeOpen(bool val) +void LatexCodeGenerator::startCodeFragment(const char *style) +{ + m_t << "\n\\begin{" << style << "}{" << m_usedTableLevel << "}\n"; +} + +void LatexCodeGenerator::endCodeFragment() { - DoxyCodeOpen = val; + //endCodeLine checks is there is still an open code line, if so closes it. + endCodeLine(); + + m_t << "\\end{DoxyCode}\n"; } + //------------------------------- LatexGenerator::LatexGenerator() : OutputGenerator(Config_getString(LATEX_OUTPUT)) @@ -650,7 +656,13 @@ static void writeDefaultHeaderPart1(FTextStream &t) { generatedBy = theTranslator->trGeneratedBy(); } - filterLatexString(tg, generatedBy, FALSE,FALSE,FALSE); + filterLatexString(tg, generatedBy, + false, // insideTabbing + false, // insidePre + false, // insideItem + false, // insideTable + false // keepSpaces + ); t << "% Headers & footers\n" "\\usepackage{fancyhdr}\n" "\\pagestyle{fancyplain}\n" @@ -1823,7 +1835,13 @@ void LatexGenerator::endSection(const char *lab,SectionType) void LatexGenerator::docify(const char *str) { - filterLatexString(t,str,m_insideTabbing,FALSE,FALSE); + filterLatexString(t,str, + m_insideTabbing, // insideTabbing + false, // insidePre + false, // insideItem + m_codeGen.usedTableLevel()>0, // insideTable + false // keepSpaces + ); } void LatexGenerator::writeChar(char c) @@ -1960,13 +1978,13 @@ void LatexGenerator::writeNonBreakableSpace(int) void LatexGenerator::startDescTable(const char *title) { - incUsedTableLevels(); + m_codeGen.incUsedTableLevel(); t << "\\begin{DoxyEnumFields}{" << title << "}" << endl; } void LatexGenerator::endDescTable() { - decUsedTableLevels(); + m_codeGen.decUsedTableLevel(); t << "\\end{DoxyEnumFields}" << endl; } @@ -2214,7 +2232,7 @@ void LatexGenerator::exceptionEntry(const char* prefix,bool closeBracket) void LatexGenerator::writeDoc(DocNode *n,const Definition *ctx,const MemberDef *) { LatexDocVisitor *visitor = - new LatexDocVisitor(t,*this,ctx?ctx->getDefFileExtension():QCString(""),m_insideTabbing); + new LatexDocVisitor(t,m_codeGen,ctx?ctx->getDefFileExtension():QCString(""),m_insideTabbing); n->accept(visitor); delete visitor; } @@ -2260,21 +2278,6 @@ void LatexGenerator::endConstraintList() t << "\\end{Desc}" << endl; } -void LatexGenerator::startCodeFragment() -{ - t << "\n\\begin{DoxyCode}{" << usedTableLevels() << "}\n"; - DoxyCodeOpen = TRUE; -} - -void LatexGenerator::endCodeFragment() -{ - //endCodeLine checks is there is still an open code line, if so closes it. - endCodeLine(); - - t << "\\end{DoxyCode}\n"; - DoxyCodeOpen = FALSE; -} - void LatexGenerator::startInlineHeader() { if (Config_getBool(COMPACT_LATEX)) @@ -2306,7 +2309,7 @@ void LatexGenerator::lineBreak(const char *) void LatexGenerator::startMemberDocSimple(bool isEnum) { - incUsedTableLevels(); + m_codeGen.incUsedTableLevel(); if (isEnum) { t << "\\begin{DoxyEnumFields}{"; @@ -2322,7 +2325,7 @@ void LatexGenerator::startMemberDocSimple(bool isEnum) void LatexGenerator::endMemberDocSimple(bool isEnum) { - decUsedTableLevels(); + m_codeGen.decUsedTableLevel(); if (isEnum) { t << "\\end{DoxyEnumFields}" << endl; diff --git a/src/latexgen.h b/src/latexgen.h index 12b34d8..8a96df3 100644 --- a/src/latexgen.h +++ b/src/latexgen.h @@ -52,7 +52,13 @@ class LatexCodeGenerator : public CodeOutputInterface void writeCodeAnchor(const char *) {} void setCurrentDoc(const Definition *,const char *,bool) {} void addWord(const char *,bool) {} - static void setDoxyCodeOpen(bool val); + void startCodeFragment(const char *style); + void endCodeFragment(); + + // extra methods not part of CodeOutputInterface + void incUsedTableLevel() { m_usedTableLevel++; } + void decUsedTableLevel() { m_usedTableLevel--; } + int usedTableLevel() const { return m_usedTableLevel; } private: void _writeCodeLink(const char *className, @@ -60,12 +66,14 @@ class LatexCodeGenerator : public CodeOutputInterface const char *anchor,const char *name, const char *tooltip); void docify(const char *str); - bool m_streamSet; + bool m_streamSet = false; FTextStream m_t; QCString m_relPath; QCString m_sourceFileName; - int m_col; - bool m_prettyCode; + int m_col = 0; + bool m_prettyCode = false; + bool m_doxyCodeLineOpen = false; + int m_usedTableLevel = 0; }; /** Generator for LaTeX output. */ @@ -108,6 +116,10 @@ class LatexGenerator : public OutputGenerator { m_codeGen.endFontClass(); } void writeCodeAnchor(const char *anchor) { m_codeGen.writeCodeAnchor(anchor); } + void startCodeFragment(const char *style) + { m_codeGen.startCodeFragment(style); } + void endCodeFragment() + { m_codeGen.endCodeFragment(); } // --------------------------- @@ -194,8 +206,6 @@ class LatexGenerator : public OutputGenerator void writeRuler() { t << endl << endl; } void writeAnchor(const char *fileName,const char *name); - void startCodeFragment(); - void endCodeFragment(); void startEmphasis() { t << "{\\em "; } void endEmphasis() { t << "}"; } void startBold() { t << "{\\bfseries "; } diff --git a/src/mandocvisitor.cpp b/src/mandocvisitor.cpp index fef857e..875cd14 100644 --- a/src/mandocvisitor.cpp +++ b/src/mandocvisitor.cpp @@ -1,13 +1,10 @@ /****************************************************************************** * - * - * - * - * Copyright (C) 1997-2015 by Dimitri van Heesch. + * Copyright (C) 1997-2020 by Dimitri van Heesch. * * Permission to use, copy, modify, and distribute this software and its - * documentation under the terms of the GNU General Public License is hereby - * granted. No representations are made about the suitability of this software + * documentation under the terms of the GNU General Public License is hereby + * granted. No representations are made about the suitability of this software * for any purpose. It is provided "as is" without express or implied warranty. * See the GNU General Public License for more details. * @@ -16,7 +13,7 @@ * */ -#include <qfileinfo.h> +#include <qfileinfo.h> #include "mandocvisitor.h" #include "docparser.h" @@ -33,7 +30,7 @@ #include "emoji.h" ManDocVisitor::ManDocVisitor(FTextStream &t,CodeOutputInterface &ci, - const char *langExt) + const char *langExt) : DocVisitor(DocVisitor_Man), m_t(t), m_ci(ci), m_insidePre(FALSE), m_hide(FALSE), m_firstCol(FALSE), m_indent(0), m_langExt(langExt) { @@ -205,8 +202,7 @@ void ManDocVisitor::visit(DocVerbatim *s) if (!m_firstCol) m_t << endl; m_t << ".PP" << endl; m_t << ".nf" << endl; - Doxygen::parserManager->getCodeParser(lang) - .parseCode(m_ci,s->context(),s->text(), + getCodeParser(lang).parseCode(m_ci,s->context(),s->text(), langExt, s->isExample(),s->exampleFile()); if (!m_firstCol) m_t << endl; @@ -214,7 +210,7 @@ void ManDocVisitor::visit(DocVerbatim *s) m_t << ".PP" << endl; m_firstCol=TRUE; break; - case DocVerbatim::Verbatim: + case DocVerbatim::Verbatim: if (!m_firstCol) m_t << endl; m_t << ".PP" << endl; m_t << ".nf" << endl; @@ -224,18 +220,18 @@ void ManDocVisitor::visit(DocVerbatim *s) m_t << ".PP" << endl; m_firstCol=TRUE; break; - case DocVerbatim::ManOnly: - m_t << s->text(); + case DocVerbatim::ManOnly: + m_t << s->text(); break; - case DocVerbatim::HtmlOnly: - case DocVerbatim::XmlOnly: - case DocVerbatim::LatexOnly: + case DocVerbatim::HtmlOnly: + case DocVerbatim::XmlOnly: + case DocVerbatim::LatexOnly: case DocVerbatim::RtfOnly: case DocVerbatim::DocbookOnly: - case DocVerbatim::Dot: - case DocVerbatim::Msc: - case DocVerbatim::PlantUML: - /* nothing */ + case DocVerbatim::Dot: + case DocVerbatim::Msc: + case DocVerbatim::PlantUML: + /* nothing */ break; } } @@ -252,14 +248,13 @@ void ManDocVisitor::visit(DocInclude *inc) switch(inc->type()) { case DocInclude::IncWithLines: - { + { if (!m_firstCol) m_t << endl; m_t << ".PP" << endl; m_t << ".nf" << endl; QFileInfo cfi( inc->file() ); FileDef *fd = createFileDef( cfi.dirPath().utf8(), cfi.fileName().utf8() ); - Doxygen::parserManager->getCodeParser(inc->extension()) - .parseCode(m_ci,inc->context(), + getCodeParser(inc->extension()).parseCode(m_ci,inc->context(), inc->text(), langExt, inc->isExample(), @@ -278,12 +273,11 @@ void ManDocVisitor::visit(DocInclude *inc) m_firstCol=TRUE; } break; - case DocInclude::Include: + case DocInclude::Include: if (!m_firstCol) m_t << endl; m_t << ".PP" << endl; m_t << ".nf" << endl; - Doxygen::parserManager->getCodeParser(inc->extension()) - .parseCode(m_ci,inc->context(), + getCodeParser(inc->extension()).parseCode(m_ci,inc->context(), inc->text(), langExt, inc->isExample(), @@ -311,7 +305,7 @@ void ManDocVisitor::visit(DocInclude *inc) case DocInclude::ManInclude: m_t << inc->text(); break; - case DocInclude::VerbInclude: + case DocInclude::VerbInclude: if (!m_firstCol) m_t << endl; m_t << ".PP" << endl; m_t << ".nf" << endl; @@ -325,8 +319,7 @@ void ManDocVisitor::visit(DocInclude *inc) if (!m_firstCol) m_t << endl; m_t << ".PP" << endl; m_t << ".nf" << endl; - Doxygen::parserManager->getCodeParser(inc->extension()) - .parseCode(m_ci, + getCodeParser(inc->extension()).parseCode(m_ci, inc->context(), extractBlock(inc->text(),inc->blockId()), langExt, @@ -345,13 +338,12 @@ void ManDocVisitor::visit(DocInclude *inc) m_t << ".nf" << endl; QFileInfo cfi( inc->file() ); FileDef *fd = createFileDef( cfi.dirPath().utf8(), cfi.fileName().utf8() ); - Doxygen::parserManager->getCodeParser(inc->extension()) - .parseCode(m_ci, + getCodeParser(inc->extension()).parseCode(m_ci, inc->context(), extractBlock(inc->text(),inc->blockId()), langExt, inc->isExample(), - inc->exampleFile(), + inc->exampleFile(), fd, lineBlock(inc->text(),inc->blockId()), -1, // endLine @@ -366,8 +358,8 @@ void ManDocVisitor::visit(DocInclude *inc) m_firstCol=TRUE; } break; - case DocInclude::SnippetDoc: - case DocInclude::IncludeDoc: + case DocInclude::SnippetDoc: + case DocInclude::IncludeDoc: err("Internal inconsistency: found switch SnippetDoc / IncludeDoc in file: %s" "Please create a bug report\n",__FILE__); break; @@ -381,7 +373,7 @@ void ManDocVisitor::visit(DocIncOperator *op) SrcLangExt langExt = getLanguageFromFileName(locLangExt); //printf("DocIncOperator: type=%d first=%d, last=%d text='%s'\n", // op->type(),op->isFirst(),op->isLast(),op->text().data()); - if (op->isFirst()) + if (op->isFirst()) { if (!m_hide) { @@ -392,10 +384,10 @@ void ManDocVisitor::visit(DocIncOperator *op) pushEnabled(); m_hide = TRUE; } - if (op->type()!=DocIncOperator::Skip) + if (op->type()!=DocIncOperator::Skip) { popEnabled(); - if (!m_hide) + if (!m_hide) { FileDef *fd = 0; if (!op->includeFileName().isEmpty()) @@ -404,8 +396,7 @@ void ManDocVisitor::visit(DocIncOperator *op) fd = createFileDef( cfi.dirPath().utf8(), cfi.fileName().utf8() ); } - Doxygen::parserManager->getCodeParser(locLangExt) - .parseCode(m_ci,op->context(),op->text(),langExt, + getCodeParser(locLangExt).parseCode(m_ci,op->context(),op->text(),langExt, op->isExample(),op->exampleFile(), fd, // fileDef op->line(), // startLine @@ -419,7 +410,7 @@ void ManDocVisitor::visit(DocIncOperator *op) pushEnabled(); m_hide=TRUE; } - if (op->isLast()) + if (op->isLast()) { popEnabled(); if (!m_hide) @@ -484,7 +475,7 @@ void ManDocVisitor::visitPre(DocAutoListItem *li) QCString ws; ws.fill(' ',m_indent-2); if (!m_firstCol) m_t << endl; - m_t << ".IP \"" << ws; + m_t << ".IP \"" << ws; if (((DocAutoList *)li->parent())->isEnumList()) { m_t << li->itemNumber() << ".\" " << m_indent+2; @@ -497,14 +488,14 @@ void ManDocVisitor::visitPre(DocAutoListItem *li) m_firstCol=TRUE; } -void ManDocVisitor::visitPost(DocAutoListItem *) +void ManDocVisitor::visitPost(DocAutoListItem *) { if (m_hide) return; m_t << endl; m_firstCol=TRUE; } -void ManDocVisitor::visitPre(DocPara *) +void ManDocVisitor::visitPre(DocPara *) { } @@ -515,7 +506,7 @@ void ManDocVisitor::visitPost(DocPara *p) !(p->parent() && // and for parameter sections p->parent()->kind()==DocNode::Kind_ParamSect ) - ) + ) { if (!m_firstCol) m_t << endl; m_t << ".PP" << endl; @@ -535,28 +526,28 @@ void ManDocVisitor::visitPre(DocSimpleSect *s) { if (m_hide) return; if (!m_firstCol) - { + { m_t << endl; m_t << ".PP" << endl; } m_t << "\\fB"; switch(s->type()) { - case DocSimpleSect::See: + case DocSimpleSect::See: m_t << theTranslator->trSeeAlso(); break; - case DocSimpleSect::Return: + case DocSimpleSect::Return: m_t << theTranslator->trReturns(); break; - case DocSimpleSect::Author: + case DocSimpleSect::Author: m_t << theTranslator->trAuthor(TRUE,TRUE); break; - case DocSimpleSect::Authors: + case DocSimpleSect::Authors: m_t << theTranslator->trAuthor(TRUE,FALSE); break; - case DocSimpleSect::Version: + case DocSimpleSect::Version: m_t << theTranslator->trVersion(); break; - case DocSimpleSect::Since: + case DocSimpleSect::Since: m_t << theTranslator->trSince(); break; - case DocSimpleSect::Date: + case DocSimpleSect::Date: m_t << theTranslator->trDate(); break; - case DocSimpleSect::Note: + case DocSimpleSect::Note: m_t << theTranslator->trNote(); break; case DocSimpleSect::Warning: m_t << theTranslator->trWarning(); break; @@ -630,7 +621,7 @@ void ManDocVisitor::visitPre(DocSimpleListItem *) m_firstCol=TRUE; } -void ManDocVisitor::visitPost(DocSimpleListItem *) +void ManDocVisitor::visitPost(DocSimpleListItem *) { if (m_hide) return; m_t << endl; @@ -649,7 +640,7 @@ void ManDocVisitor::visitPre(DocSection *s) m_firstCol=TRUE; } -void ManDocVisitor::visitPost(DocSection *) +void ManDocVisitor::visitPost(DocSection *) { } @@ -661,7 +652,7 @@ void ManDocVisitor::visitPre(DocHtmlList *) m_t << ".PD 0" << endl; } -void ManDocVisitor::visitPost(DocHtmlList *) +void ManDocVisitor::visitPost(DocHtmlList *) { if (m_hide) return; m_indent-=2; @@ -675,7 +666,7 @@ void ManDocVisitor::visitPre(DocHtmlListItem *li) QCString ws; ws.fill(' ',m_indent-2); if (!m_firstCol) m_t << endl; - m_t << ".IP \"" << ws; + m_t << ".IP \"" << ws; if (((DocHtmlList *)li->parent())->type()==DocHtmlList::Ordered) { m_t << li->itemNumber() << ".\" " << m_indent+2; @@ -688,7 +679,7 @@ void ManDocVisitor::visitPre(DocHtmlListItem *li) m_firstCol=TRUE; } -void ManDocVisitor::visitPost(DocHtmlListItem *) +void ManDocVisitor::visitPost(DocHtmlListItem *) { if (m_hide) return; m_t << endl; @@ -703,7 +694,7 @@ void ManDocVisitor::visitPost(DocHtmlListItem *) // m_insidePre=TRUE; //} // -//void ManDocVisitor::visitPost(DocHtmlPre *) +//void ManDocVisitor::visitPost(DocHtmlPre *) //{ // m_insidePre=FALSE; // if (!m_firstCol) m_t << endl; @@ -716,7 +707,7 @@ void ManDocVisitor::visitPre(DocHtmlDescList *) { } -void ManDocVisitor::visitPost(DocHtmlDescList *) +void ManDocVisitor::visitPost(DocHtmlDescList *) { if (m_hide) return; if (!m_firstCol) m_t << endl; @@ -732,7 +723,7 @@ void ManDocVisitor::visitPre(DocHtmlDescTitle *) m_firstCol=FALSE; } -void ManDocVisitor::visitPost(DocHtmlDescTitle *) +void ManDocVisitor::visitPost(DocHtmlDescTitle *) { if (m_hide) return; m_t << "\\fP\" 1c" << endl; @@ -743,7 +734,7 @@ void ManDocVisitor::visitPre(DocHtmlDescData *) { } -void ManDocVisitor::visitPost(DocHtmlDescData *) +void ManDocVisitor::visitPost(DocHtmlDescData *) { } @@ -751,7 +742,7 @@ void ManDocVisitor::visitPre(DocHtmlTable *) { } -void ManDocVisitor::visitPost(DocHtmlTable *) +void ManDocVisitor::visitPost(DocHtmlTable *) { } @@ -759,7 +750,7 @@ void ManDocVisitor::visitPre(DocHtmlCaption *) { } -void ManDocVisitor::visitPost(DocHtmlCaption *) +void ManDocVisitor::visitPost(DocHtmlCaption *) { } @@ -767,7 +758,7 @@ void ManDocVisitor::visitPre(DocHtmlRow *) { } -void ManDocVisitor::visitPost(DocHtmlRow *) +void ManDocVisitor::visitPost(DocHtmlRow *) { } @@ -775,7 +766,7 @@ void ManDocVisitor::visitPre(DocHtmlCell *) { } -void ManDocVisitor::visitPost(DocHtmlCell *) +void ManDocVisitor::visitPost(DocHtmlCell *) { } @@ -788,7 +779,7 @@ void ManDocVisitor::visitPre(DocInternal *) //m_t << ".RS 4" << endl; } -void ManDocVisitor::visitPost(DocInternal *) +void ManDocVisitor::visitPost(DocInternal *) { if (m_hide) return; //if (!m_firstCol) m_t << endl; @@ -803,7 +794,7 @@ void ManDocVisitor::visitPre(DocHRef *) m_t << "\\fC"; } -void ManDocVisitor::visitPost(DocHRef *) +void ManDocVisitor::visitPost(DocHRef *) { if (m_hide) return; m_t << "\\fP"; @@ -817,7 +808,7 @@ void ManDocVisitor::visitPre(DocHtmlHeader *header) m_t << " \""; } -void ManDocVisitor::visitPost(DocHtmlHeader *header) +void ManDocVisitor::visitPost(DocHtmlHeader *header) { if (m_hide) return; m_t << "\"" << endl; @@ -829,7 +820,7 @@ void ManDocVisitor::visitPre(DocImage *) { } -void ManDocVisitor::visitPost(DocImage *) +void ManDocVisitor::visitPost(DocImage *) { } @@ -837,14 +828,14 @@ void ManDocVisitor::visitPre(DocDotFile *) { } -void ManDocVisitor::visitPost(DocDotFile *) +void ManDocVisitor::visitPost(DocDotFile *) { } void ManDocVisitor::visitPre(DocMscFile *) { } -void ManDocVisitor::visitPost(DocMscFile *) +void ManDocVisitor::visitPost(DocMscFile *) { } @@ -862,7 +853,7 @@ void ManDocVisitor::visitPre(DocLink *) m_t << "\\fB"; } -void ManDocVisitor::visitPost(DocLink *) +void ManDocVisitor::visitPost(DocLink *) { if (m_hide) return; m_t << "\\fP"; @@ -875,7 +866,7 @@ void ManDocVisitor::visitPre(DocRef *ref) if (!ref->hasLinkText()) filter(ref->targetTitle()); } -void ManDocVisitor::visitPost(DocRef *) +void ManDocVisitor::visitPost(DocRef *) { if (m_hide) return; m_t << "\\fP"; @@ -891,7 +882,7 @@ void ManDocVisitor::visitPre(DocSecRefItem *) m_firstCol=TRUE; } -void ManDocVisitor::visitPost(DocSecRefItem *) +void ManDocVisitor::visitPost(DocSecRefItem *) { if (m_hide) return; m_t << endl; @@ -904,7 +895,7 @@ void ManDocVisitor::visitPre(DocSecRefList *) m_indent+=2; } -void ManDocVisitor::visitPost(DocSecRefList *) +void ManDocVisitor::visitPost(DocSecRefList *) { if (m_hide) return; m_indent-=2; @@ -916,20 +907,20 @@ void ManDocVisitor::visitPre(DocParamSect *s) { if (m_hide) return; if (!m_firstCol) - { + { m_t << endl; m_t << ".PP" << endl; } m_t << "\\fB"; switch(s->type()) { - case DocParamSect::Param: + case DocParamSect::Param: m_t << theTranslator->trParameters(); break; - case DocParamSect::RetVal: + case DocParamSect::RetVal: m_t << theTranslator->trReturnValues(); break; - case DocParamSect::Exception: + case DocParamSect::Exception: m_t << theTranslator->trExceptions(); break; - case DocParamSect::TemplateParam: + case DocParamSect::TemplateParam: m_t << theTranslator->trTemplateParameters(); break; default: ASSERT(0); @@ -961,11 +952,11 @@ void ManDocVisitor::visitPre(DocParamList *pl) if (!first) m_t << ","; else first=FALSE; if (param->kind()==DocNode::Kind_Word) { - visit((DocWord*)param); + visit((DocWord*)param); } else if (param->kind()==DocNode::Kind_LinkedWord) { - visit((DocLinkedWord*)param); + visit((DocLinkedWord*)param); } } m_t << "\\fP "; @@ -986,7 +977,7 @@ void ManDocVisitor::visitPre(DocXRefItem *x) if (m_hide) return; if (x->title().isEmpty()) return; if (!m_firstCol) - { + { m_t << endl; m_t << ".PP" << endl; } @@ -1012,7 +1003,7 @@ void ManDocVisitor::visitPre(DocInternalRef *) m_t << "\\fB"; } -void ManDocVisitor::visitPost(DocInternalRef *) +void ManDocVisitor::visitPost(DocInternalRef *) { if (m_hide) return; m_t << "\\fP"; @@ -1030,7 +1021,7 @@ void ManDocVisitor::visitPre(DocHtmlBlockQuote *) { if (m_hide) return; if (!m_firstCol) - { + { m_t << endl; m_t << ".PP" << endl; } @@ -1064,12 +1055,12 @@ void ManDocVisitor::visitPost(DocParBlock *) void ManDocVisitor::filter(const char *str) -{ +{ if (str) { const char *p=str; char c=0; - while ((c=*p++)) + while ((c=*p++)) { switch(c) { diff --git a/src/mangen.cpp b/src/mangen.cpp index 8574018..8c75e25 100644 --- a/src/mangen.cpp +++ b/src/mangen.cpp @@ -391,7 +391,7 @@ void ManGenerator::endItemListItem() { } -void ManGenerator::startCodeFragment() +void ManGenerator::startCodeFragment(const char *) { newParagraph(); t << ".nf" << endl; diff --git a/src/mangen.h b/src/mangen.h index 9bcdb18..b06ca47 100644 --- a/src/mangen.h +++ b/src/mangen.h @@ -123,7 +123,7 @@ class ManGenerator : public OutputGenerator void writeRuler() {} void writeAnchor(const char *,const char *) {} - void startCodeFragment(); + void startCodeFragment(const char *); void endCodeFragment(); void writeLineNumber(const char *,const char *,const char *,int l) { t << l << " "; m_col=0; } void startCodeLine(bool) {} diff --git a/src/memberdef.cpp b/src/memberdef.cpp index 2f92ea0..0f416f4 100644 --- a/src/memberdef.cpp +++ b/src/memberdef.cpp @@ -3683,10 +3683,10 @@ void MemberDefImpl::writeDocumentation(const MemberList *ml, else ol.parseText(theTranslator->trInitialValue()); ol.endBold(); - CodeParserInterface &intf = Doxygen::parserManager->getCodeParser(getDefFileExtension()); - intf.resetCodeParserState(); - ol.startCodeFragment(); - intf.parseCode(ol,scopeName,m_impl->initializer,lang,FALSE,0,const_cast<FileDef*>(getFileDef()), + auto intf = Doxygen::parserManager->getCodeParser(getDefFileExtension()); + intf->resetCodeParserState(); + ol.startCodeFragment("DoxyCode"); + intf->parseCode(ol,scopeName,m_impl->initializer,lang,FALSE,0,const_cast<FileDef*>(getFileDef()), -1,-1,TRUE,this,FALSE,this); ol.endCodeFragment(); } diff --git a/src/outputgen.h b/src/outputgen.h index 4bfed25..3313dcd 100644 --- a/src/outputgen.h +++ b/src/outputgen.h @@ -127,6 +127,16 @@ class CodeOutputInterface virtual void setCurrentDoc(const Definition *context,const char *anchor,bool isSourceFile) = 0; virtual void addWord(const char *word,bool hiPriority) = 0; + + /*! Starts a source code fragment. The fragment will be + * fed to the code parser (see code.h) for syntax highlighting + * and cross-referencing. The fragment ends by a call to + * endCodeFragment() + * @param style The kind of code fragment. + */ + virtual void startCodeFragment(const char *style) = 0; + /*! Ends a block of code */ + virtual void endCodeFragment() = 0; }; /** Base Interface used for generating output outside of the @@ -240,20 +250,6 @@ class BaseOutputDocInterface : public CodeOutputInterface /*! Ends a section of text displayed in italic. */ virtual void endEmphasis() = 0; - /*! Starts a source code fragment. The fragment will be - * fed to the code parser (see code.h) for syntax highlighting - * and cross-referencing. The fragment ends by a call to - * endCodeFragment() - */ - virtual void startCodeFragment() = 0; - - /*! Ends a source code fragment - */ - virtual void endCodeFragment() = 0; - - - - /*! Writes a horizontal ruler to the output */ virtual void writeRuler() = 0; diff --git a/src/outputlist.h b/src/outputlist.h index 003e508..e25d7b6 100644 --- a/src/outputlist.h +++ b/src/outputlist.h @@ -229,8 +229,8 @@ class OutputList : public OutputDocInterface { forall(&OutputGenerator::writeRuler); } void writeAnchor(const char *fileName,const char *name) { forall(&OutputGenerator::writeAnchor,fileName,name); } - void startCodeFragment() - { forall(&OutputGenerator::startCodeFragment); } + void startCodeFragment(const char *style) + { forall(&OutputGenerator::startCodeFragment,style); } void endCodeFragment() { forall(&OutputGenerator::endCodeFragment); } void startCodeLine(bool hasLineNumbers) diff --git a/src/parserintf.h b/src/parserintf.h index 3087aa3..2fde2f1 100644 --- a/src/parserintf.h +++ b/src/parserintf.h @@ -137,6 +137,7 @@ class CodeParserInterface //----------------------------------------------------------------------------- using OutlineParserFactory = std::function<std::unique_ptr<OutlineParserInterface>()>; +using CodeParserFactory = std::function<std::unique_ptr<CodeParserInterface>()>; /** \brief Manages programming language parsers. * @@ -145,39 +146,42 @@ using OutlineParserFactory = std::function<std::unique_ptr<OutlineParserInterfac */ class ParserManager { - public: struct ParserPair { - ParserPair(OutlineParserFactory opf, std::unique_ptr<CodeParserInterface> cpi, const QCString pn) - : outlineParserFactory(opf), codeParserInterface(std::move(cpi)), parserName(pn) + ParserPair(OutlineParserFactory opf, CodeParserFactory cpf, const QCString pn) + : outlineParserFactory(opf), codeParserFactory(cpf), parserName(pn) { } OutlineParserFactory outlineParserFactory; - std::unique_ptr<CodeParserInterface> codeParserInterface; + CodeParserFactory codeParserFactory; QCString parserName; }; + public: + /** Create the parser manager + * @param outlineParserFactory the fallback outline parser factory to use for unknown extensions + * @param codeParserFactory the fallback code parser factory to use for unknown extensions + */ ParserManager(OutlineParserFactory outlineParserFactory, - std::unique_ptr<CodeParserInterface> codeParserInterface) - : m_defaultParsers(outlineParserFactory,std::move(codeParserInterface), "") + CodeParserFactory codeParserFactory) + : m_defaultParsers(outlineParserFactory,codeParserFactory, "") { } /** Registers an additional parser. * @param[in] name A symbolic name of the parser, i.e. "c", * "python", "fortran", "vhdl", ... - * @param[in] outlineParser The language parser (scanner) that is to be used for the - * given name. - * @param[in] codeParser The code parser that is to be used for the - * given name. + * @param[in] outlineParserFactory A factory method to create a language parser (scanner) that + * is to be used for the given name. + * @param[in] codeParserFactory A factory method to create a code parser that is to be used + * for the given name. */ void registerParser(const char *name,OutlineParserFactory outlineParserFactory, - std::unique_ptr<CodeParserInterface> codeParserInterface) + CodeParserFactory codeParserFactory) { - m_parsers.emplace(std::string(name), - ParserPair(outlineParserFactory,std::move(codeParserInterface),name)); + m_parsers.emplace(std::string(name),ParserPair(outlineParserFactory,codeParserFactory,name)); } /** Registers a file \a extension with a parser with name \a parserName. @@ -199,7 +203,7 @@ class ParserManager return TRUE; } - /** Gets the interface to the parser associated with given \a extension. + /** Gets the interface to the parser associated with a given \a extension. * If there is no parser explicitly registered for the supplied extension, * the interface to the default parser will be returned. */ @@ -208,13 +212,20 @@ class ParserManager return getParsers(extension).outlineParserFactory(); } - /** Gets the interface to the parser associated with given \a extension. + /** Gets the interface to the parser associated with a given \a extension. * If there is no parser explicitly registered for the supplied extension, * the interface to the default parser will be returned. */ - CodeParserInterface &getCodeParser(const char *extension) + std::unique_ptr<CodeParserInterface> getCodeParser(const char *extension) + { + auto factory = getCodeParserFactory(extension); + return factory(); + } + + /** Get the factory for create code parser objects with a given \a extension. */ + CodeParserFactory &getCodeParserFactory(const char *extension) { - return *getParsers(extension).codeParserInterface; + return getParsers(extension).codeParserFactory; } /** Gets the name of the parser associated with given \a extension. diff --git a/src/rtfdocvisitor.cpp b/src/rtfdocvisitor.cpp index fbe7cc1..2bd2c29 100644 --- a/src/rtfdocvisitor.cpp +++ b/src/rtfdocvisitor.cpp @@ -306,9 +306,8 @@ void RTFDocVisitor::visit(DocVerbatim *s) m_t << "{" << endl; m_t << "\\par" << endl; m_t << rtf_Style_Reset << getStyle("CodeExample"); - Doxygen::parserManager->getCodeParser(lang) - .parseCode(m_ci,s->context(),s->text(),langExt, - s->isExample(),s->exampleFile()); + getCodeParser(lang).parseCode(m_ci,s->context(),s->text(),langExt, + s->isExample(),s->exampleFile()); //m_t << "\\par" << endl; m_t << "}" << endl; break; @@ -433,8 +432,7 @@ void RTFDocVisitor::visit(DocInclude *inc) m_t << rtf_Style_Reset << getStyle("CodeExample"); QFileInfo cfi( inc->file() ); FileDef *fd = createFileDef( cfi.dirPath().utf8(), cfi.fileName().utf8() ); - Doxygen::parserManager->getCodeParser(inc->extension()) - .parseCode(m_ci,inc->context(), + getCodeParser(inc->extension()).parseCode(m_ci,inc->context(), inc->text(), langExt, inc->isExample(), @@ -455,8 +453,7 @@ void RTFDocVisitor::visit(DocInclude *inc) m_t << "{" << endl; m_t << "\\par" << endl; m_t << rtf_Style_Reset << getStyle("CodeExample"); - Doxygen::parserManager->getCodeParser(inc->extension()) - .parseCode(m_ci,inc->context(), + getCodeParser(inc->extension()).parseCode(m_ci,inc->context(), inc->text(),langExt,inc->isExample(), inc->exampleFile(), 0, // fileDef @@ -492,8 +489,7 @@ void RTFDocVisitor::visit(DocInclude *inc) m_t << "{" << endl; if (!m_lastIsPara) m_t << "\\par" << endl; m_t << rtf_Style_Reset << getStyle("CodeExample"); - Doxygen::parserManager->getCodeParser(inc->extension()) - .parseCode(m_ci, + getCodeParser(inc->extension()).parseCode(m_ci, inc->context(), extractBlock(inc->text(),inc->blockId()), langExt, @@ -509,8 +505,7 @@ void RTFDocVisitor::visit(DocInclude *inc) m_t << "{" << endl; if (!m_lastIsPara) m_t << "\\par" << endl; m_t << rtf_Style_Reset << getStyle("CodeExample"); - Doxygen::parserManager->getCodeParser(inc->extension()) - .parseCode(m_ci, + getCodeParser(inc->extension()).parseCode(m_ci, inc->context(), extractBlock(inc->text(),inc->blockId()), langExt, @@ -567,8 +562,7 @@ void RTFDocVisitor::visit(DocIncOperator *op) fd = createFileDef( cfi.dirPath().utf8(), cfi.fileName().utf8() ); } - Doxygen::parserManager->getCodeParser(locLangExt) - .parseCode(m_ci,op->context(),op->text(),langExt, + getCodeParser(locLangExt).parseCode(m_ci,op->context(),op->text(),langExt, op->isExample(),op->exampleFile(), fd, // fileDef op->line(), // startLine diff --git a/src/rtfgen.cpp b/src/rtfgen.cpp index dff4cdd..bf2711a 100644 --- a/src/rtfgen.cpp +++ b/src/rtfgen.cpp @@ -48,8 +48,6 @@ #include "filename.h" #include "namespacedef.h" -static bool DoxyCodeLineOpen = FALSE; - //#define DBG_RTF(x) x; #define DBG_RTF(x) @@ -1935,22 +1933,15 @@ void RTFGenerator::writeRTFReference(const char *label) t << " \\\\*MERGEFORMAT}{\\fldrslt pagenum}}"; } -void RTFGenerator::startCodeFragment() +void RTFGenerator::startCodeFragment(const char *) { DBG_RTF(t << "{\\comment (startCodeFragment) }" << endl) t << "{" << endl; - //newParagraph(); t << rtf_Style_Reset << rtf_Code_DepthStyle(); - //styleStack.push(rtf_Style_CodeExample); } void RTFGenerator::endCodeFragment() { - //newParagraph(); - //styleStack.pop(); - //printf("RTFGenerator::endCodeFragment() top=%s\n",styleStack.top()); - //t << rtf_Style_Reset << styleStack.top() << endl; - //endCodeLine checks is there is still an open code line, if so closes it. endCodeLine(); DBG_RTF(t << "{\\comment (endCodeFragment) }" << endl) @@ -3043,7 +3034,7 @@ void RTFGenerator::writeLineNumber(const char *ref,const char *fileName,const ch { bool rtfHyperlinks = Config_getBool(RTF_HYPERLINKS); - DoxyCodeLineOpen = TRUE; + m_doxyCodeLineOpen = true; QCString lineNumber; lineNumber.sprintf("%05d",l); if (m_prettyCode) @@ -3070,13 +3061,13 @@ void RTFGenerator::writeLineNumber(const char *ref,const char *fileName,const ch } void RTFGenerator::startCodeLine(bool) { - DoxyCodeLineOpen = TRUE; + m_doxyCodeLineOpen = true; m_col=0; } void RTFGenerator::endCodeLine() { - if (DoxyCodeLineOpen) lineBreak(); - DoxyCodeLineOpen = FALSE; + if (m_doxyCodeLineOpen) lineBreak(); + m_doxyCodeLineOpen = false; } void RTFGenerator::startLabels() diff --git a/src/rtfgen.h b/src/rtfgen.h index ac6f580..c16602b 100644 --- a/src/rtfgen.h +++ b/src/rtfgen.h @@ -125,7 +125,7 @@ class RTFGenerator : public OutputGenerator void writeRuler() { rtfwriteRuler_thin(); } void writeAnchor(const char *fileName,const char *name); - void startCodeFragment(); + void startCodeFragment(const char *style); void endCodeFragment(); void writeLineNumber(const char *,const char *,const char *,int l); void startCodeLine(bool); @@ -293,6 +293,7 @@ class RTFGenerator : public OutputGenerator bool m_omitParagraph = false; // should a the next paragraph command be ignored? int m_numCols = 0; // number of columns in a table QCString m_relPath; + bool m_doxyCodeLineOpen = false; }; #endif diff --git a/src/util.cpp b/src/util.cpp index 6b30584..8310862 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -4726,9 +4726,8 @@ QCString escapeCharsInString(const char *name,bool allowDots,bool allowUnderscor { bool caseSenseNames = Config_getBool(CASE_SENSE_NAMES); bool allowUnicodeNames = Config_getBool(ALLOW_UNICODE_NAMES); - static THREAD_LOCAL GrowBuf growBuf; - growBuf.clear(); if (name==0) return ""; + GrowBuf growBuf; signed char c; const signed char *p=(const signed char*)name; while ((c=*p++)!=0) @@ -5222,9 +5221,8 @@ QCString stripScope(const char *name) QCString convertToId(const char *s) { static const char hex[] = "0123456789ABCDEF"; - static GrowBuf growBuf; - growBuf.clear(); if (s==0) return ""; + GrowBuf growBuf; const char *p=s; char c; bool first=TRUE; @@ -5263,9 +5261,8 @@ QCString correctId(QCString s) /*! Converts a string to an XML-encoded string */ QCString convertToXML(const char *s, bool keepEntities) { - static GrowBuf growBuf; - growBuf.clear(); if (s==0) return ""; + GrowBuf growBuf; const char *p=s; char c; while ((c=*p++)) @@ -5315,9 +5312,8 @@ QCString convertToXML(const char *s, bool keepEntities) /*! Converts a string to an DocBook-encoded string */ QCString convertToDocBook(const char *s) { - static GrowBuf growBuf; - growBuf.clear(); if (s==0) return ""; + GrowBuf growBuf; const unsigned char *q; int cnt; const unsigned char *p=(const unsigned char *)s; @@ -5375,9 +5371,8 @@ QCString convertToDocBook(const char *s) /*! Converts a string to a HTML-encoded string */ QCString convertToHtml(const char *s,bool keepEntities) { - static GrowBuf growBuf; - growBuf.clear(); if (s==0) return ""; + GrowBuf growBuf; growBuf.addStr(getHtmlDirEmbeddingChar(getTextDirByConfig(s))); const char *p=s; char c; @@ -5422,9 +5417,8 @@ QCString convertToHtml(const char *s,bool keepEntities) QCString convertToJSString(const char *s, bool applyTextDir) { - static GrowBuf growBuf; - growBuf.clear(); if (s==0) return ""; + GrowBuf growBuf; if (applyTextDir) growBuf.addStr(getJsDirEmbeddingChar(getTextDirByConfig(s))); const char *p=s; @@ -5444,9 +5438,8 @@ QCString convertToJSString(const char *s, bool applyTextDir) QCString convertToPSString(const char *s) { - static GrowBuf growBuf; - growBuf.clear(); if (s==0) return ""; + GrowBuf growBuf; const char *p=s; char c; while ((c=*p++)) @@ -5466,7 +5459,7 @@ QCString convertToLaTeX(const QCString &s,bool insideTabbing,bool keepSpaces) { QGString result; FTextStream t(&result); - filterLatexString(t,s,insideTabbing,FALSE,FALSE,keepSpaces); + filterLatexString(t,s,insideTabbing,false,false,false,keepSpaces); return result.data(); } @@ -5478,8 +5471,7 @@ QCString convertCharEntitiesToUTF8(const QCString &s) static QRegExp entityPat("&[a-zA-Z]+[0-9]*;"); if (s.length()==0) return result; - static GrowBuf growBuf; - growBuf.clear(); + GrowBuf growBuf; int p,i=0,l; while ((p=entityPat.match(s,i,&l))!=-1) { @@ -6158,7 +6150,7 @@ void addGroupListToTitle(OutputList &ol,const Definition *d) } void filterLatexString(FTextStream &t,const char *str, - bool insideTabbing,bool insidePre,bool insideItem,bool keepSpaces) + bool insideTabbing,bool insidePre,bool insideItem,bool insideTable,bool keepSpaces) { if (str==0) return; //if (strlen(str)<2) stackTrace(); @@ -6195,7 +6187,7 @@ void filterLatexString(FTextStream &t,const char *str, case '$': t << "\\$"; break; case '"': t << "\"{}"; break; case '-': t << "-\\/"; break; - case '^': (usedTableLevels()>0) ? t << "\\string^" : t << (char)c; break; + case '^': insideTable ? t << "\\string^" : t << (char)c; break; case '~': t << "\\string~"; break; case ' ': if (keepSpaces) t << "~"; else t << ' '; break; @@ -6332,7 +6324,13 @@ QCString latexEscapeLabelName(const char *s) p++; } tmp[i]=0; - filterLatexString(t,tmp,TRUE); + filterLatexString(t,tmp, + true, // insideTabbing + false, // insidePre + false, // insideItem + false, // insideTable + false // keepSpaces + ); break; } } @@ -6371,7 +6369,13 @@ QCString latexEscapeIndexChars(const char *s) p++; } tmp[i]=0; - filterLatexString(t,tmp.data(),TRUE); + filterLatexString(t,tmp.data(), + true, // insideTabbing + false, // insidePre + false, // insideItem + false, // insideTable + false // keepSpaces + ); break; } } @@ -8449,23 +8453,6 @@ void writeLatexSpecialFormulaChars(FTextStream &t) } //------------------------------------------------------ - -static int g_usedTableLevels = 0; - -void incUsedTableLevels() -{ - g_usedTableLevels++; -} -void decUsedTableLevels() -{ - g_usedTableLevels--; -} -int usedTableLevels() -{ - return g_usedTableLevels; -} - -//------------------------------------------------------ // simplified way to know if this is fixed form bool recognizeFixedForm(const char* contents, FortranFormat format) { @@ -351,10 +351,11 @@ QCString unescapeCharsInString(const char *s); void addGroupListToTitle(OutputList &ol,const Definition *d); void filterLatexString(FTextStream &t,const char *str, - bool insideTabbing=FALSE, - bool insidePre=FALSE, - bool insideItem=FALSE, - bool keepSpaces=FALSE); + bool insideTabbing, + bool insidePre, + bool insideItem, + bool insideTable, + bool keepSpaces); QCString latexEscapeLabelName(const char *s); QCString latexEscapeIndexChars(const char *s); @@ -498,10 +499,6 @@ bool openOutputFile(const char *outFile,QFile &f); void writeExtraLatexPackages(FTextStream &t); void writeLatexSpecialFormulaChars(FTextStream &t); -int usedTableLevels(); -void incUsedTableLevels(); -void decUsedTableLevels(); - bool recognizeFixedForm(const char* contents, FortranFormat format); FortranFormat convertFileNameFortranParserCode(QCString fn); diff --git a/src/vhdldocgen.cpp b/src/vhdldocgen.cpp index ff47791..bf87a9a 100644 --- a/src/vhdldocgen.cpp +++ b/src/vhdldocgen.cpp @@ -2357,7 +2357,7 @@ void VhdlDocGen::writeStringLink(const MemberDef *mdef,QCString mem, OutputList& void VhdlDocGen::writeSource(const MemberDef *mdef,OutputList& ol,const QCString & cname) { - CodeParserInterface &intf = Doxygen::parserManager->getCodeParser(".vhd"); + auto intf = Doxygen::parserManager->getCodeParser(".vhd"); // pIntf->resetCodeParserState(); QCString codeFragment=mdef->documentation(); @@ -2382,8 +2382,8 @@ void VhdlDocGen::writeSource(const MemberDef *mdef,OutputList& ol,const QCString codeFragment.prepend("\n"); ol.pushGeneratorState(); - ol.startCodeFragment(); - intf.parseCode( ol, // codeOutIntf + ol.startCodeFragment("DoxyCode"); + intf->parseCode( ol, // codeOutIntf 0, // scope codeFragment, // input SrcLangExt_VHDL, // lang diff --git a/src/xmldocvisitor.cpp b/src/xmldocvisitor.cpp index 045f87c..73aac7c 100644 --- a/src/xmldocvisitor.cpp +++ b/src/xmldocvisitor.cpp @@ -252,9 +252,8 @@ void XmlDocVisitor::visit(DocVerbatim *s) m_t << " filename=\"" << lang << "\">"; else m_t << ">"; - Doxygen::parserManager->getCodeParser(lang) - .parseCode(m_ci,s->context(),s->text(),langExt, - s->isExample(),s->exampleFile()); + getCodeParser(lang).parseCode(m_ci,s->context(),s->text(),langExt, + s->isExample(),s->exampleFile()); m_t << "</programlisting>"; break; case DocVerbatim::Verbatim: @@ -332,8 +331,7 @@ void XmlDocVisitor::visit(DocInclude *inc) m_t << "<programlisting filename=\"" << inc->file() << "\">"; QFileInfo cfi( inc->file() ); FileDef *fd = createFileDef( cfi.dirPath().utf8(), cfi.fileName().utf8() ); - Doxygen::parserManager->getCodeParser(inc->extension()) - .parseCode(m_ci,inc->context(), + getCodeParser(inc->extension()).parseCode(m_ci,inc->context(), inc->text(), langExt, inc->isExample(), @@ -351,8 +349,7 @@ void XmlDocVisitor::visit(DocInclude *inc) break; case DocInclude::Include: m_t << "<programlisting filename=\"" << inc->file() << "\">"; - Doxygen::parserManager->getCodeParser(inc->extension()) - .parseCode(m_ci,inc->context(), + getCodeParser(inc->extension()).parseCode(m_ci,inc->context(), inc->text(), langExt, inc->isExample(), @@ -411,8 +408,7 @@ void XmlDocVisitor::visit(DocInclude *inc) break; case DocInclude::Snippet: m_t << "<programlisting filename=\"" << inc->file() << "\">"; - Doxygen::parserManager->getCodeParser(inc->extension()) - .parseCode(m_ci, + getCodeParser(inc->extension()).parseCode(m_ci, inc->context(), extractBlock(inc->text(),inc->blockId()), langExt, @@ -426,8 +422,7 @@ void XmlDocVisitor::visit(DocInclude *inc) m_t << "<programlisting filename=\"" << inc->file() << "\">"; QFileInfo cfi( inc->file() ); FileDef *fd = createFileDef( cfi.dirPath().utf8(), cfi.fileName().utf8() ); - Doxygen::parserManager->getCodeParser(inc->extension()) - .parseCode(m_ci, + getCodeParser(inc->extension()).parseCode(m_ci, inc->context(), extractBlock(inc->text(),inc->blockId()), langExt, @@ -480,17 +475,16 @@ void XmlDocVisitor::visit(DocIncOperator *op) fd = createFileDef( cfi.dirPath().utf8(), cfi.fileName().utf8() ); } - Doxygen::parserManager->getCodeParser(locLangExt) - .parseCode(m_ci,op->context(), - op->text(),langExt,op->isExample(), - op->exampleFile(), - fd, // fileDef - op->line(), // startLine - -1, // endLine - FALSE, // inline fragment - 0, // memberDef - op->showLineNo() // show line numbers - ); + getCodeParser(locLangExt).parseCode(m_ci,op->context(), + op->text(),langExt,op->isExample(), + op->exampleFile(), + fd, // fileDef + op->line(), // startLine + -1, // endLine + FALSE, // inline fragment + 0, // memberDef + op->showLineNo() // show line numbers + ); if (fd) delete fd; } pushEnabled(); diff --git a/src/xmlgen.cpp b/src/xmlgen.cpp index 19f1553..c942a61 100644 --- a/src/xmlgen.cpp +++ b/src/xmlgen.cpp @@ -226,6 +226,7 @@ class TextGeneratorXMLImpl : public TextGeneratorIntf FTextStream &m_t; }; +//------------------------------------------------------------------------------------------- /** Generator for producing XML formatted source code. */ void XMLCodeGenerator::codify(const char *text) @@ -340,6 +341,18 @@ void XMLCodeGenerator::finish() if (m_insideCodeLine) endCodeLine(); } +void XMLCodeGenerator::startCodeFragment(const char *) +{ + m_t << " <programlisting>" << endl; +} + +void XMLCodeGenerator::endCodeFragment() +{ + m_t << " </programlisting>" << endl; +} + +//------------------------------------------------------------------------------------------- + static void writeTemplateArgumentList(FTextStream &t, const ArgumentList &al, const Definition *scope, @@ -420,11 +433,12 @@ static void writeXMLDocBlock(FTextStream &t, void writeXMLCodeBlock(FTextStream &t,FileDef *fd) { - CodeParserInterface &intf=Doxygen::parserManager->getCodeParser(fd->getDefFileExtension()); + auto intf=Doxygen::parserManager->getCodeParser(fd->getDefFileExtension()); SrcLangExt langExt = getLanguageFromFileName(fd->getDefFileExtension()); - intf.resetCodeParserState(); + intf->resetCodeParserState(); XMLCodeGenerator *xmlGen = new XMLCodeGenerator(t); - intf.parseCode(*xmlGen, // codeOutIntf + xmlGen->startCodeFragment("DoxyCode"); + intf->parseCode(*xmlGen, // codeOutIntf 0, // scopeName fileToString(fd->absFilePath(),Config_getBool(FILTER_SOURCE_FILES)), langExt, // lang @@ -437,6 +451,7 @@ void writeXMLCodeBlock(FTextStream &t,FileDef *fd) 0, // memberDef TRUE // showLineNumbers ); + xmlGen->endCodeFragment(); xmlGen->finish(); delete xmlGen; } @@ -1639,9 +1654,7 @@ static void generateXMLForFile(FileDef *fd,FTextStream &ti) t << " </detaileddescription>" << endl; if (Config_getBool(XML_PROGRAMLISTING)) { - t << " <programlisting>" << endl; writeXMLCodeBlock(t,fd); - t << " </programlisting>" << endl; } t << " <location file=\"" << convertToXML(stripFromPath(fd->getDefFileName())) << "\"/>" << endl; t << " </compounddef>" << endl; diff --git a/src/xmlgen.h b/src/xmlgen.h index 4458b9f..dd8d616 100644 --- a/src/xmlgen.h +++ b/src/xmlgen.h @@ -1,12 +1,10 @@ /****************************************************************************** * - * - * - * Copyright (C) 1997-2015 by Dimitri van Heesch. + * Copyright (C) 1997-2020 by Dimitri van Heesch. * * Permission to use, copy, modify, and distribute this software and its - * documentation under the terms of the GNU General Public License is hereby - * granted. No representations are made about the suitability of this software + * documentation under the terms of the GNU General Public License is hereby + * granted. No representations are made about the suitability of this software * for any purpose. It is provided "as is" without express or implied warranty. * See the GNU General Public License for more details. * @@ -41,6 +39,8 @@ class XMLCodeGenerator : public CodeOutputInterface const char *anchorId,int l); void setCurrentDoc(const Definition *,const char *,bool){} void addWord(const char *,bool){} + void startCodeFragment(const char *); + void endCodeFragment(); void finish(); |