From c61d8701470352385bcf5720ee516ba95c4393c8 Mon Sep 17 00:00:00 2001 From: Dimitri van Heesch Date: Mon, 7 Jan 2019 21:51:07 +0100 Subject: [PATCH] issue #6734 parsing performance worsened --- src/commentscan.h | 13 ++++++++++++ src/commentscan.l | 48 ++++++++++++++++++++++++++------------------ src/fortranscanner.l | 7 ++++--- src/growbuf.h | 10 +++++++++ src/markdown.cpp | 9 +++++---- src/pyscanner.l | 5 +++-- src/scanner.l | 15 +++++++------- src/tclscanner.l | 19 ++++++++++++------ src/vhdljjparser.cpp | 7 ++++--- 9 files changed, 88 insertions(+), 45 deletions(-) diff --git a/src/commentscan.h b/src/commentscan.h index d324969b18f..75cd99f7e8e 100644 --- a/src/commentscan.h +++ b/src/commentscan.h @@ -24,6 +24,19 @@ class ParserInterface; /** @file * @brief Interface for the comment block parser */ +/** Invokes the comment block parser with the request to preprocess a + * single comment block. + * @param[in] comment A string representing the actual comment block. + * Note that leading *'s are already stripped from the comment block. + * @param[in] fileName The name of the file in which the comment is found. + * Mainly used for producing warnings. + * @param[in] lineNr The line number at which the comment block was found. + * @returns The prepocessed comment block + */ +QCString preprocessCommentBlock(const QCString &comment, + const QCString &fileName, + int lineNr); + /** Invokes the comment block parser with the request to parse a * single comment block. * @param[in] parser The language parse that invoked this function. diff --git a/src/commentscan.l b/src/commentscan.l index 235cd7cbfc3..f9cc3b10ff8 100644 --- a/src/commentscan.l +++ b/src/commentscan.l @@ -3074,6 +3074,33 @@ static void checkFormula() //---------------------------------------------------------------------------- +QCString preprocessCommentBlock(const QCString &comment, + const QCString &fileName, + int lineNr) +{ + if (!comment.isEmpty() && Doxygen::markdownSupport) + { + QCString result = processMarkdown(fileName,lineNr,0,comment); + const char *p = result.data(); + if (p) + { + while (*p==' ') p++; // skip over spaces + while (*p=='\n') p++; // skip over newlines + if (qstrncmp(p,"
",4)==0) p+=4; // skip over
+ } + if (p>result.data()) + { + // strip part of the input + result = result.mid(p-result.data()); + } + return result; + } + else + { + return comment; + } +} + bool parseCommentBlock(/* in */ ParserInterface *parser, /* in */ Entry *curEntry, /* in */ const QCString &comment, @@ -3096,26 +3123,7 @@ bool parseCommentBlock(/* in */ ParserInterface *parser, langParser = parser; current = curEntry; if (comment.isEmpty()) return FALSE; // avoid empty strings - if (Doxygen::markdownSupport) - { - inputString = processMarkdown(fileName,lineNr,NULL,comment); - const char *p = inputString.data(); - if (p) - { - while (*p==' ') p++; // skip over spaces - while (*p=='\n') p++; // skip over newlines - if (qstrncmp(p,"
",4)==0) p+=4; // skip over
- } - if (p>inputString.data()) - { - // strip part of the input - inputString = inputString.mid(p-inputString.data()); - } - } - else - { - inputString = comment; - } + inputString = comment; inputString.append(" "); inputPosition = position; yyLineNr = lineNr; diff --git a/src/fortranscanner.l b/src/fortranscanner.l index 5f10669264a..1f0c3564562 100644 --- a/src/fortranscanner.l +++ b/src/fortranscanner.l @@ -2411,9 +2411,7 @@ static void startCommentBlock(bool brief) static void handleCommentBlock(const QCString &doc,bool brief) { - bool needsEntry = FALSE; static bool hideInBodyDocs = Config_getBool(HIDE_IN_BODY_DOCS); - int position=0; if (docBlockInBody && hideInBodyDocs) { docBlockInBody = FALSE; @@ -2421,10 +2419,13 @@ static void handleCommentBlock(const QCString &doc,bool brief) } DBG_CTX((stderr,"call parseCommentBlock [%s]\n",doc.data())); int lineNr = brief ? current->briefLine : current->docLine; + int position=0; + bool needsEntry = FALSE; + QCString processedDoc = preprocessCommentBlock(doc,yyFileName,lineNr); while (parseCommentBlock( g_thisParser, docBlockInBody ? subrCurrent.getFirst() : current, - doc, // text + processedDoc, // text yyFileName, // file lineNr, docBlockInBody ? FALSE : brief, diff --git a/src/growbuf.h b/src/growbuf.h index bc8e4b51db3..4c49dce0b2b 100644 --- a/src/growbuf.h +++ b/src/growbuf.h @@ -11,11 +11,21 @@ class GrowBuf { public: GrowBuf() : str(0), pos(0), len(0) {} + GrowBuf(int initialSize) : pos(0), len(initialSize) { str=(char*)malloc(len); } ~GrowBuf() { free(str); str=0; pos=0; len=0; } void clear() { pos=0; } void addChar(char c) { if (pos>=len) { len+=GROW_AMOUNT; str = (char*)realloc(str,len); } str[pos++]=c; } + void addStr(const QCString &s) { + if (!s.isEmpty()) + { + int l=s.length(); + if (pos+l>=len) { len+=l+GROW_AMOUNT; str = (char*)realloc(str,len); } + strcpy(&str[pos],s.data()); + pos+=l; + } + } void addStr(const char *s) { if (s) { diff --git a/src/markdown.cpp b/src/markdown.cpp index b00070e320e..5253333a583 100644 --- a/src/markdown.cpp +++ b/src/markdown.cpp @@ -2451,8 +2451,8 @@ static QCString extractPageTitle(QCString &docs,QCString &id) static QCString detab(const QCString &s,int &refIndent) { static int tabSize = Config_getInt(TAB_SIZE); - GrowBuf out; int size = s.length(); + GrowBuf out(size); const char *data = s.data(); int i=0; int col=0; @@ -2601,19 +2601,20 @@ void MarkdownFileParser::parseInput(const char *fileName, } } int lineNr=1; - int position=0; // even without markdown support enabled, we still // parse markdown files as such bool markdownEnabled = Doxygen::markdownSupport; Doxygen::markdownSupport = TRUE; - bool needsEntry = FALSE; Protection prot=Public; + bool needsEntry = FALSE; + int position=0; + QCString processedDocs = preprocessCommentBlock(docs,fileName,lineNr); while (parseCommentBlock( this, current, - docs, + processedDocs, fileName, lineNr, FALSE, // isBrief diff --git a/src/pyscanner.l b/src/pyscanner.l index 1596b9d00b2..655b6e2d231 100644 --- a/src/pyscanner.l +++ b/src/pyscanner.l @@ -324,11 +324,12 @@ static void handleCommentBlock(const QCString &doc,bool brief) int position = 0; bool needsEntry; int lineNr = brief ? current->briefLine : current->docLine; + QCString processedDoc = preprocessCommentBlock(doc,yyFileName,lineNr); while (parseCommentBlock( g_thisParser, (docBlockInBody && previous) ? previous : current, - doc, // text - yyFileName, // file + processedDoc, // text + yyFileName, // file lineNr, docBlockInBody ? FALSE : brief, docBlockJavaStyle, // javadoc style // or FALSE, diff --git a/src/scanner.l b/src/scanner.l index 7559e0b77d9..86a83cbdd0d 100644 --- a/src/scanner.l +++ b/src/scanner.l @@ -6908,12 +6908,10 @@ static void newEntry() static void handleCommentBlock(const QCString &doc,bool brief) { static bool hideInBodyDocs = Config_getBool(HIDE_IN_BODY_DOCS); - int position=0; - bool needsEntry=FALSE; if (docBlockInBody && hideInBodyDocs) return; //printf("parseCommentBlock [%s] brief=%d\n",doc.data(),brief); int lineNr = brief ? current->briefLine : current->docLine; // line of block start - + // fill in inbodyFile && inbodyLine the first time, see bug 633891 Entry *docEntry = docBlockInBody && previous ? previous : current; if (docBlockInBody && docEntry && docEntry->inbodyLine==-1) @@ -6922,12 +6920,15 @@ static void handleCommentBlock(const QCString &doc,bool brief) docEntry->inbodyLine = lineNr; } + int position=0; + bool needsEntry=FALSE; + QCString processedDoc = preprocessCommentBlock(stripIndentation(doc),yyFileName,lineNr); while (parseCommentBlock( g_thisParser, docBlockInBody && previous ? previous : current, - stripIndentation(doc), // text - yyFileName, // file - lineNr, // line of block start + processedDoc, // text + yyFileName, // file + lineNr, // line of block start docBlockInBody ? FALSE : brief, // isBrief docBlockInBody ? FALSE : docBlockAutoBrief, // isJavaDocStyle docBlockInBody, // isInBody @@ -6935,7 +6936,7 @@ static void handleCommentBlock(const QCString &doc,bool brief) position, needsEntry ) - ) + ) { //printf("parseCommentBlock position=%d [%s]\n",position,doc.data()+position); if (needsEntry) diff --git a/src/tclscanner.l b/src/tclscanner.l index ca5294b9789..88714ce464a 100644 --- a/src/tclscanner.l +++ b/src/tclscanner.l @@ -1507,6 +1507,7 @@ tcl_inf("-> %s\n",(const char *)tcl.string_comment); myO.shrink(myO.curPos()-2); myO.addChar('\0'); QCString myDoc = myO.data(); + QCString processedDoc; if (what==99) { // inbody comment file or namespace or class or proc/method int myPos0; @@ -1526,14 +1527,16 @@ tcl_inf("-> %s\n",(const char *)tcl.string_comment); myPos0=myPos; myLine0=myLine; - while (parseCommentBlock(tcl.this_parser, &myEntry0, myDoc, tcl.file_name, + processedDoc = preprocessCommentBlock(myDoc,tcl.file_name,myLine); + while (parseCommentBlock(tcl.this_parser, &myEntry0, processedDoc, tcl.file_name, myLine, FALSE, tcl.config_autobrief, FALSE, myProt, myPos, myNew)) { if (myNew) { // we need a new entry in this case myNew=0; myEntry = tcl_entry_new(); - parseCommentBlock(tcl.this_parser, myEntry, myDoc, tcl.file_name, + processedDoc = preprocessCommentBlock(myDoc,tcl.file_name,myLine0); + parseCommentBlock(tcl.this_parser, myEntry, processedDoc, tcl.file_name, myLine0, FALSE, tcl.config_autobrief, FALSE, myProt, myPos0, myNew); tcl.entry_inside->addSubEntry(myEntry); } @@ -1543,7 +1546,8 @@ tcl_inf("-> %s\n",(const char *)tcl.string_comment); { myEntry1=tcl_entry_namespace(tcl.scan.at(0)->ns); } - parseCommentBlock(tcl.this_parser, myEntry1, myDoc, tcl.file_name, + processedDoc = preprocessCommentBlock(myDoc,tcl.file_name,myLine0); + parseCommentBlock(tcl.this_parser, myEntry1, processedDoc, tcl.file_name, myLine0, FALSE, tcl.config_autobrief, FALSE, myProt, myPos0, myNew); } myPos0=myPos; @@ -1553,7 +1557,8 @@ tcl_inf("-> %s\n",(const char *)tcl.string_comment); { // we need a new entry myNew=0; myEntry = tcl_entry_new(); - parseCommentBlock(tcl.this_parser, myEntry, myDoc, tcl.file_name, + processedDoc = preprocessCommentBlock(myDoc,tcl.file_name,myLine0); + parseCommentBlock(tcl.this_parser, myEntry, processedDoc, tcl.file_name, myLine0, FALSE, tcl.config_autobrief, FALSE, myProt, myPos0, myNew); tcl.entry_inside->addSubEntry(myEntry); } @@ -1563,14 +1568,16 @@ tcl_inf("-> %s\n",(const char *)tcl.string_comment); { myEntry1=tcl_entry_namespace(tcl.scan.at(0)->ns); } - parseCommentBlock(tcl.this_parser, myEntry1, myDoc, tcl.file_name, + processedDoc = preprocessCommentBlock(myDoc,tcl.file_name,myLine0); + parseCommentBlock(tcl.this_parser, myEntry1, processedDoc, tcl.file_name, myLine0, FALSE, tcl.config_autobrief, FALSE, myProt, myPos0, myNew); } } else { // new entry tcl.entry_current = tcl_entry_new(); - while (parseCommentBlock(tcl.this_parser, tcl.entry_current, myDoc, + processedDoc = preprocessCommentBlock(myDoc,tcl.file_name,myLine); + while (parseCommentBlock(tcl.this_parser, tcl.entry_current, processedDoc, tcl.file_name, myLine, FALSE, tcl.config_autobrief, FALSE, myProt, myPos, myNew)) { diff --git a/src/vhdljjparser.cpp b/src/vhdljjparser.cpp index 81a7ca1fe1d..4a312bd8773 100644 --- a/src/vhdljjparser.cpp +++ b/src/vhdljjparser.cpp @@ -244,7 +244,6 @@ void VhdlParser::handleFlowComment(const char* doc) void VhdlParser::handleCommentBlock(const char* doc1,bool brief) { - int position=0; QCString doc; doc.append(doc1); // fprintf(stderr,"\n %s",doc.data()); @@ -258,7 +257,6 @@ void VhdlParser::handleCommentBlock(const char* doc1,bool brief) VhdlDocGen::prepareComment(doc); - bool needsEntry=FALSE; Protection protection=Public; if (oldEntry==current) @@ -290,10 +288,13 @@ void VhdlParser::handleCommentBlock(const char* doc1,bool brief) current->stat=true; } + int position=0; + bool needsEntry=FALSE; + QCString processedDoc = preprocessCommentBlock(doc,yyFileName,iDocLine); while (parseCommentBlock( g_thisParser, current, - doc, // text + processedDoc, // text yyFileName, // file iDocLine, // line of block start brief,