From 5162dab5a4254ef65e2de972f07a00ff52e7734c Mon Sep 17 00:00:00 2001 From: Dimitri van Heesch Date: Sun, 13 Sep 2020 21:12:32 +0200 Subject: Refactoring: making sqlcode.l reentrant --- src/sqlcode.h | 13 ++- src/sqlcode.l | 294 ++++++++++++++++++++++++++++------------------------------ 2 files changed, 150 insertions(+), 157 deletions(-) diff --git a/src/sqlcode.h b/src/sqlcode.h index 20e20f7..aa465d7 100644 --- a/src/sqlcode.h +++ b/src/sqlcode.h @@ -1,12 +1,10 @@ /****************************************************************************** * - * - * - * Copyright (C) 1997-2014 by Dimitri van Heesch. + * Copyright (C) 1997-2020 by Dimitri van Heesch. * * Permission to use, copy, modify, and distribute this software and its - * documentation under the terms of the GNU General Public License is hereby - * granted. No representations are made about the suitability of this software + * documentation under the terms of the GNU General Public License is hereby + * granted. No representations are made about the suitability of this software * for any purpose. It is provided "as is" without express or implied warranty. * See the GNU General Public License for more details. * @@ -32,6 +30,8 @@ class Definition; class SQLCodeParser : public CodeParserInterface { public: + SQLCodeParser(); + virtual ~SQLCodeParser(); void parseCode(CodeOutputInterface &codeOutIntf, const char *scopeName, const QCString &input, @@ -48,6 +48,9 @@ class SQLCodeParser : public CodeParserInterface bool collectXRefs=TRUE ); void resetCodeParserState(); + private: + struct Private; + std::unique_ptr p; }; diff --git a/src/sqlcode.l b/src/sqlcode.l index 22a5e17..58d8481 100644 --- a/src/sqlcode.l +++ b/src/sqlcode.l @@ -1,10 +1,10 @@ /****************************************************************************** * - * Copyright (C) 1997-2014 by Dimitri van Heesch. + * Copyright (C) 1997-2020 by Dimitri van Heesch. * * Permission to use, copy, modify, and distribute this software and its - * documentation under the terms of the GNU General Public License is hereby - * granted. No representations are made about the suitability of this software + * documentation under the terms of the GNU General Public License is hereby + * granted. No representations are made about the suitability of this software * for any purpose. It is provided "as is" without express or implied warranty. * See the GNU General Public License for more details. * @@ -60,9 +60,9 @@ struct sqlcodeYY_state QCString exampleName; QCString classScope; - FileDef *sourceFileDef; - Definition *currentDefinition; - MemberDef *currentMemberDef; + const FileDef *sourceFileDef; + const Definition *currentDefinition; + const MemberDef *currentMemberDef; bool includeCodeFragment; const char *currentFontClass; }; @@ -71,18 +71,18 @@ struct sqlcodeYY_state static const char *stateToString(int state); #endif -static void setCurrentDoc(const QCString &anchor,yyscan_t yyscanner); +static void setCurrentDoc(yyscan_t yyscanner,const QCString &anchor); static void startCodeLine(yyscan_t yyscanner); static void endFontClass(yyscan_t yyscanner); static void endCodeLine(yyscan_t yyscanner); static void nextCodeLine(yyscan_t yyscanner); -static void codifyLines(char *text,yyscan_t yyscanner); -static void startFontClass(const char *s,yyscan_t yyscanner); +static void codifyLines(yyscan_t yyscanner,const char *text); +static void startFontClass(yyscan_t yyscanner,const char *s); static int countLines(yyscan_t yyscanner); -static yy_size_t yyread(char *buf,yy_size_t max_size,yyscan_t yyscanner); +static yy_size_t yyread(yyscan_t yyscanner,char *buf,yy_size_t max_size); #undef YY_INPUT -#define YY_INPUT(buf,result,max_size) result=yyread(buf,max_size,yyscanner); +#define YY_INPUT(buf,result,max_size) result=yyread(yyscanner,buf,max_size); %} @@ -110,7 +110,7 @@ typekeyword (?i:"ARRAY"|"BIGINT"|"BINARY"|"BLOB"|"BOOLEAN"|"CHAR"|"CHARACTER flowkeyword (?i:"CASE"|"IF"|"ELSE"|"BEGIN"|"END"|"WHILE") -literalkeyword (?i:"FALSE"|"TRUE"|"NULL"|"UNKNOWN") +literalkeyword (?i:"false"|"true"|"NULL"|"UNKNOWN") stringliteral (\"[^"]*\")|('[^']*') number [0-9]+ literals ({literalkeyword}|{stringliteral}|{number}) @@ -126,107 +126,107 @@ commentclose "\*/" %% {literals} { - startFontClass("stringliteral",yyscanner); - codifyLines(yytext,yyscanner); + startFontClass(yyscanner,"stringliteral"); + codifyLines(yyscanner,yytext); endFontClass(yyscanner); } - + {keyword} { - startFontClass("keyword",yyscanner); - codifyLines(yytext,yyscanner); + startFontClass(yyscanner,"keyword"); + codifyLines(yyscanner,yytext); endFontClass(yyscanner); } {flowkeyword} { - startFontClass("keywordflow",yyscanner); - codifyLines(yytext,yyscanner); + startFontClass(yyscanner,"keywordflow"); + codifyLines(yyscanner,yytext); endFontClass(yyscanner); } {typekeyword} { - startFontClass("keywordtype",yyscanner); - codifyLines(yytext,yyscanner); + startFontClass(yyscanner,"keywordtype"); + codifyLines(yyscanner,yytext); endFontClass(yyscanner); } {variable} { - startFontClass("preprocessor",yyscanner); - codifyLines(yytext,yyscanner); + startFontClass(yyscanner,"preprocessor"); + codifyLines(yyscanner,yytext); endFontClass(yyscanner); } {simplecomment} { - startFontClass("comment",yyscanner); - codifyLines(yytext,yyscanner); + startFontClass(yyscanner,"comment"); + codifyLines(yyscanner,yytext); endFontClass(yyscanner); } {commentopen} { - startFontClass("comment",yyscanner); - codifyLines(yytext,yyscanner); + startFontClass(yyscanner,"comment"); + codifyLines(yyscanner,yytext); BEGIN(COMMENT); } . { - codifyLines(yytext,yyscanner); - + codifyLines(yyscanner,yytext); + } {nl} { - codifyLines(yytext,yyscanner); + codifyLines(yyscanner,yytext); } {commentclose} { - codifyLines(yytext,yyscanner); + codifyLines(yyscanner,yytext); endFontClass(yyscanner); BEGIN(INITIAL); } - + {idchar} { - codifyLines(yytext,yyscanner); + codifyLines(yyscanner,yytext); } {nl} { - codifyLines(yytext,yyscanner); + codifyLines(yyscanner,yytext); } [\x80-\xFF]* { // keep utf8 characters together... - codifyLines(yytext,yyscanner); + codifyLines(yyscanner,yytext); } . { - codifyLines(yytext,yyscanner); + codifyLines(yyscanner,yytext); } %% -static void setCurrentDoc(const QCString &anchor, yyscan_t yyscanner) +static void setCurrentDoc(yyscan_t yyscanner,const QCString &anchor) { struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; if (Doxygen::searchIndex) { if (yyextra->searchCtx) { - Doxygen::searchIndex->setCurrentDoc(yyextra->searchCtx,yyextra->searchCtx->anchor(),FALSE); + yyextra->code->setCurrentDoc(yyextra->searchCtx,yyextra->searchCtx->anchor(),false); } else { - Doxygen::searchIndex->setCurrentDoc(yyextra->sourceFileDef,anchor,TRUE); + yyextra->code->setCurrentDoc(yyextra->sourceFileDef,anchor,true); } } } /*! start a new line of code, inserting a line number if yyextra->sourceFileDef - * is TRUE. If a definition starts at the current line, then the line + * is true. If a definition starts at the current line, then the line * number is linked to the documentation of that definition. */ static void startCodeLine(yyscan_t yyscanner) { struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; if (yyextra->sourceFileDef) - { - Definition *d = yyextra->sourceFileDef->getSourceDefinition(yyextra->yyLineNr); - + { + const Definition *d = yyextra->sourceFileDef->getSourceDefinition(yyextra->yyLineNr); + if (!yyextra->includeCodeFragment && d && d->isLinkableInProject()) { yyextra->currentDefinition = d; @@ -239,14 +239,14 @@ static void startCodeLine(yyscan_t yyscanner) yyextra->code->writeLineNumber(yyextra->currentMemberDef->getReference(), yyextra->currentMemberDef->getOutputFileBase(), yyextra->currentMemberDef->anchor(),yyextra->yyLineNr); - setCurrentDoc(lineAnchor,yyscanner); + setCurrentDoc(yyscanner,lineAnchor); } else { yyextra->code->writeLineNumber(d->getReference(), d->getOutputFileBase(), 0,yyextra->yyLineNr); - setCurrentDoc(lineAnchor,yyscanner); + setCurrentDoc(yyscanner,lineAnchor); } } else @@ -254,9 +254,9 @@ static void startCodeLine(yyscan_t yyscanner) yyextra->code->writeLineNumber(0,0,0,yyextra->yyLineNr); } } - + yyextra->code->startCodeLine(yyextra->sourceFileDef); - + if (yyextra->currentFontClass) { yyextra->code->startFontClass(yyextra->currentFontClass); @@ -285,42 +285,43 @@ static void nextCodeLine(yyscan_t yyscanner) struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; const char *fc = yyextra->currentFontClass; endCodeLine(yyscanner); - if (yyextra->yyLineNrinputLines) + if (yyextra->yyLineNrinputLines) { yyextra->currentFontClass = fc; startCodeLine(yyscanner); } } -static void codifyLines(char *text,yyscan_t yyscanner) +static void codifyLines(yyscan_t yyscanner,const char *text) { struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; - char *p=text,*sp=p; + const char *p=text,*sp=p; char c; - bool done=FALSE; - + bool done=false; while (!done) { sp=p; - while ((c=*p++) && c!='\n') { } - if (c=='\n') { yyextra->yyLineNr++; - *(p-1)='\0'; - yyextra->code->codify(sp); + int l = (int)(p-sp-1); + char *tmp = (char*)malloc(l+1); + memcpy(tmp,sp,l); + tmp[l]='\0'; + yyextra->code->codify(tmp); + free(tmp); nextCodeLine(yyscanner); } else { yyextra->code->codify(sp); - done=TRUE; + done=true; } } } -static void startFontClass(const char *s,yyscan_t yyscanner) +static void startFontClass(yyscan_t yyscanner,const char *s) { struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; endFontClass(yyscanner); @@ -335,103 +336,129 @@ static int countLines(yyscan_t yyscanner) const char *p=yyextra->inputString; char c; int count=1; - while ((c=*p)) - { - p++ ; - if (c=='\n') count++; + while ((c=*p)) + { + p++ ; + if (c=='\n') count++; } - if (p>yyextra->inputString && *(p-1)!='\n') + if (p>yyextra->inputString && *(p-1)!='\n') { // last line does not end with a \n, so we add an extra // line and explicitly terminate the line after parsing. - count++, - yyextra->needsTermination=TRUE; - } + count++, + yyextra->needsTermination=true; + } return count; } -static yy_size_t yyread(char *buf,yy_size_t max_size,yyscan_t yyscanner) +static yy_size_t yyread(yyscan_t yyscanner,char *buf,yy_size_t max_size) { struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + yy_size_t inputPosition = yyextra->inputPosition; + const char *s = yyextra->inputString + inputPosition; yy_size_t c=0; - while( c < max_size && yyextra->inputString[yyextra->inputPosition] ) + while( c < max_size && *s ) { - *buf = yyextra->inputString[yyextra->inputPosition++] ; - c++; buf++; + *buf++ = *s++; + c++; } + yyextra->inputPosition += c; return c; } // public interface ----------------------------------------------------------- -static yyscan_t yyscanner; -static struct sqlcodeYY_state sqlcode_extra; - -void parseSqlCode( - CodeOutputInterface &od, - const char * /*className*/, - const QCString &s, - bool exBlock, - const char *exName, - FileDef *fd, - int startLine, - int endLine, - bool inlineFragment, - const MemberDef *, - bool,const Definition *searchCtx, - bool /*collectXRefs*/ - ) -{ - if (s.isEmpty()) return; - - sqlcodeYYlex_init_extra(&sqlcode_extra, &yyscanner); - struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; +struct SQLCodeParser::Private +{ + yyscan_t yyscanner; + sqlcodeYY_state state; +}; + +SQLCodeParser::SQLCodeParser() : p(std::make_unique()) +{ + sqlcodeYYlex_init_extra(&p->state, &p->yyscanner); #ifdef FLEX_DEBUG sqlcodeYYset_debug(1,yyscanner); #endif + resetCodeParserState(); +} + +SQLCodeParser::~SQLCodeParser() +{ + sqlcodeYYlex_destroy(p->yyscanner); +} + +void SQLCodeParser::resetCodeParserState() +{ + struct yyguts_t *yyg = (struct yyguts_t*)p->yyscanner; + yyextra->currentDefinition = 0; + yyextra->currentMemberDef = 0; +} + - printlex(yy_flex_debug, TRUE, __FILE__, fd ? fd->fileName().data(): NULL); - - yyextra->code = &od; - yyextra->inputString = s; +//--------------------------------------------------------------------------------- + +void SQLCodeParser::parseCode(CodeOutputInterface &codeOutIntf, + const char *scopeName, + const QCString &input, + SrcLangExt, + bool isExampleBlock, + const char *exampleName, + FileDef *fileDef, + int startLine, + int endLine, + bool inlineFragment, + const MemberDef *memberDef, + bool showLineNumbers, + const Definition *searchCtx, + bool collectXRefs + ) +{ + yyscan_t yyscanner = p->yyscanner; + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + + printlex(yy_flex_debug, true, __FILE__, fileDef ? fileDef->fileName().data(): NULL); + + yyextra->code = &codeOutIntf; + yyextra->inputString = input; yyextra->inputPosition = 0; yyextra->currentFontClass = 0; - yyextra->needsTermination = FALSE; + yyextra->needsTermination = false; yyextra->searchCtx=searchCtx; - + if (startLine!=-1) yyextra->yyLineNr = startLine; else yyextra->yyLineNr = 1; - + if (endLine!=-1) yyextra->inputLines = endLine+1; else yyextra->inputLines = yyextra->yyLineNr + countLines(yyscanner) - 1; - - yyextra->exampleBlock = exBlock; - yyextra->exampleName = exName; - yyextra->sourceFileDef = fd; - - bool cleanupSourceDef = FALSE; - - if (exBlock && fd==0) + + yyextra->exampleBlock = isExampleBlock; + yyextra->exampleName = exampleName; + yyextra->sourceFileDef = fileDef; + + bool cleanupSourceDef = false; + + if (isExampleBlock && fileDef==0) { // create a dummy filedef for the example - yyextra->sourceFileDef = createFileDef("",(exName?exName:"generated")); - cleanupSourceDef = TRUE; + yyextra->sourceFileDef = createFileDef("",(exampleName?exampleName:"generated")); + cleanupSourceDef = true; } - - if (yyextra->sourceFileDef) + + if (yyextra->sourceFileDef) { - setCurrentDoc("l00001",yyscanner); + setCurrentDoc(yyscanner,"l00001"); } yyextra->includeCodeFragment = inlineFragment; - // Starts line 1 on the output + // Starts line 1 on the output startCodeLine(yyscanner); - sqlcodeYYrestart( yyin,yyscanner ); + sqlcodeYYrestart( 0, yyscanner ); sqlcodeYYlex(yyscanner); @@ -445,45 +472,8 @@ void parseSqlCode( delete yyextra->sourceFileDef; yyextra->sourceFileDef=0; } - - printlex(yy_flex_debug, FALSE, __FILE__, fd ? fd->fileName().data(): NULL); - sqlcodeYYlex_destroy(yyscanner); - return; -} - -void resetSqlCodeParserState() -{ - struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; - yyextra->currentDefinition = 0; - yyextra->currentMemberDef = 0; -} - -//--------------------------------------------------------------------------------- -void SQLCodeParser::parseCode(CodeOutputInterface &codeOutIntf, - const char *scopeName, - const QCString &input, - SrcLangExt, - bool isExampleBlock, - const char *exampleName, - FileDef *fileDef, - int startLine, - int endLine, - bool inlineFragment, - const MemberDef *memberDef, - bool showLineNumbers, - const Definition *searchCtx, - bool collectXRefs - ) -{ - parseSqlCode(codeOutIntf,scopeName,input,isExampleBlock,exampleName, - fileDef,startLine,endLine,inlineFragment,memberDef, - showLineNumbers,searchCtx,collectXRefs); -} - -void SQLCodeParser::resetCodeParserState() -{ - resetSqlCodeParserState(); + printlex(yy_flex_debug, false, __FILE__, fileDef ? fileDef->fileName().data(): NULL); } //--------------------------------------------------------------------------------- -- cgit v0.12