From 79cca781278544a7efc3a5538e2252ab399e08df Mon Sep 17 00:00:00 2001 From: Dimitri van Heesch Date: Wed, 1 Jan 2020 21:36:25 +0100 Subject: Make fortranscanner.l reentrant --- src/fortranscanner.h | 6 +- src/fortranscanner.l | 2409 +++++++++++++++++++++++++------------------------- 2 files changed, 1231 insertions(+), 1184 deletions(-) diff --git a/src/fortranscanner.h b/src/fortranscanner.h index 7a13f47..6ffcb1f 100644 --- a/src/fortranscanner.h +++ b/src/fortranscanner.h @@ -27,7 +27,8 @@ class FortranOutlineParser : public OutlineParserInterface { public: - FortranOutlineParser(FortranFormat format=FortranFormat_Unknown) : m_format(format) { } + FortranOutlineParser(FortranFormat format=FortranFormat_Unknown); + ~FortranOutlineParser(); void startTranslationUnit(const char *) {} void finishTranslationUnit() {} void parseInput(const char *fileName, @@ -39,7 +40,8 @@ class FortranOutlineParser : public OutlineParserInterface void parsePrototype(const char *text); private: - FortranFormat m_format; + struct Private; + std::unique_ptr p; }; class FortranOutlineParserFree : public FortranOutlineParser diff --git a/src/fortranscanner.l b/src/fortranscanner.l index d569763..18cfdcb 100644 --- a/src/fortranscanner.l +++ b/src/fortranscanner.l @@ -21,8 +21,8 @@ * - Consider using startScope(), endScope() functions with module, program, * subroutine or any other scope in fortran program. * - * - Symbol modifiers (attributes) are collected using SymbolModifiers |= operator during - * substructure parsing. When substructure ends all modifiers are applied to actual + * - Symbol yyextra->modifiers (attributes) are collected using SymbolModifiers |= operator during + * substructure parsing. When substructure ends all yyextra->modifiers are applied to actual * entries in applyModifiers() functions. * * - How case insensitiveness should be handled in code? @@ -35,11 +35,13 @@ * "functionA" or "MyInterface". So constructs like '(^|[ \t])interface({BS_}{ID})?/[ \t\n]' * are desired. * - * - Must track yyLineNr when using REJECT, unput() or similar commands. + * - Must track yyextra->lineNr when using REJECT, unput() or similar commands. */ %option never-interactive %option case-insensitive %option prefix="fortranscannerYY" +%option reentrant +%option extra-type="struct fortranscannerYY_state *" %{ @@ -80,8 +82,9 @@ enum ScanVar { V_IGNORE, V_VARIABLE, V_PARAMETER, V_RESULT}; enum InterfaceType { IF_NONE, IF_SPECIFIC, IF_GENERIC, IF_ABSTRACT }; // {{{ ----- Helper structs ----- -//! Holds modifiers (ie attributes) for one symbol (variable, function, etc) -struct SymbolModifiers { +//! Holds yyextra->modifiers (ie attributes) for one symbol (variable, function, etc) +struct SymbolModifiers +{ enum Protection {NONE_P, PUBLIC, PRIVATE}; enum Direction {NONE_D, IN, OUT, INOUT}; @@ -133,116 +136,110 @@ static const char *directionParam[] = // }}} -/* ----------------------------------------------------------------- - * - * statics - */ -static OutlineParserInterface *g_thisParser; -static CommentScanner g_commentScanner; -static const char * inputString; -static int inputPosition; -static bool isFixedForm; -static QCString inputStringPrepass; ///< Input string for prepass of line cont. '&' -static QCString inputStringSemi; ///< Input string after command separator ';' -static unsigned int inputPositionPrepass; -static int lineCountPrepass = 0; - -static std::vector< std::shared_ptr > subrCurrent; - -struct CommentInPrepass { +struct CommentInPrepass +{ int column; QCString str; CommentInPrepass(int column, QCString str) : column(column), str(str) {} }; -static QList comments; - -YY_BUFFER_STATE *include_stack = NULL; -int include_stack_ptr = 0; -int include_stack_cnt = 0; - -static QFile inputFile; -static QCString yyFileName; -static int yyLineNr = 1 ; -static int yyColNr = 0 ; -static Entry *current_root = 0; -static Entry *global_scope = 0; -static std::shared_ptr global_root; -static std::shared_ptr file_root; -static std::shared_ptr last_entry; -static std::shared_ptr last_enum; -static std::shared_ptr current; -static ScanVar v_type = V_IGNORE; // type of parsed variable -static std::vector > moduleProcedures; // list of all interfaces which contain unresolved - // module procedures -static QCString docBlock; -static bool docBlockInBody = FALSE; -static bool docBlockJavaStyle; - -static MethodTypes mtype; -static bool gstat; -static Specifier virt; - -static QCString debugStr; -static QCString result; // function result -static Argument *parameter; // element of parameter list -static QCString argType; // fortran type of an argument of a parameter list -static QCString argName; // last identifier name in variable list -static QCString initializer; // initial value of a variable -static int initializerArrayScope; // number if nested array scopes in initializer -static int initializerScope; // number if nested function calls in initializer -static QCString useModuleName; // name of module in the use statement -static Protection defaultProtection; -static Protection typeProtection; -static int typeMode = false; -static InterfaceType ifType = IF_NONE; -static bool functionLine = FALSE; - -static char stringStartSymbol; // single or double quote -static bool parsingPrototype = FALSE; // see parsePrototype() + +typedef std::vector< std::shared_ptr > EntryList; + +/* ----------------------------------------------------------------- + * + * statics + */ + +struct fortranscannerYY_state +{ + OutlineParserInterface * thisParser; + CommentScanner commentScanner; + const char * inputString; + int inputPosition; + bool isFixedForm; + QCString inputStringPrepass; ///< Input string for prepass of line cont. '&' + QCString inputStringSemi; ///< Input string after command separator ';' + unsigned int inputPositionPrepass; + int lineCountPrepass = 0; + EntryList subrCurrent; + QList comments; + YY_BUFFER_STATE * includeStack = NULL; + int includeStackPtr = 0; + int includeStackCnt = 0; + QCString fileName; + int lineNr = 1 ; + int colNr = 0 ; + Entry *current_root = 0; + Entry *global_scope = 0; + std::shared_ptr global_root; + std::shared_ptr file_root; + std::shared_ptr last_entry; + std::shared_ptr last_enum; + std::shared_ptr current; + ScanVar vtype = V_IGNORE; // type of parsed variable + EntryList moduleProcedures; // list of all interfaces which contain unresolved module procedures + QCString docBlock; + bool docBlockInBody = FALSE; + bool docBlockJavaStyle; + QCString debugStr; +// Argument *parameter; // element of parameter list + QCString argType; // fortran type of an argument of a parameter list + QCString argName; // last identifier name in variable list + QCString initializer; // initial value of a variable + int initializerArrayScope; // number if nested array scopes in initializer + int initializerScope; // number if nested function calls in initializer + QCString useModuleName; // name of module in the use statement + Protection defaultProtection; + Protection typeProtection; + bool typeMode = false; + InterfaceType ifType = IF_NONE; + bool functionLine = FALSE; + char stringStartSymbol; // single or double quote + bool parsingPrototype = FALSE; // see parsePrototype() //! Accumulated modifiers of current statement, eg variable declaration. -static SymbolModifiers currentModifiers; + SymbolModifiers currentModifiers; //! Holds program scope->symbol name->symbol modifiers. -static QMap > modifiers; + QMap > modifiers; + int anonCount = 0 ; +}; -static int anonCount = 0 ; //----------------------------------------------------------------------------- - -static int yyread(char *buf,int max_size); -static void startCommentBlock(bool); -static void handleCommentBlock(const QCString &doc,bool brief); -static void subrHandleCommentBlock(const QCString &doc,bool brief); -static void subrHandleCommentBlockResult(const QCString &doc,bool brief); -static void addCurrentEntry(bool case_insens); -static void addModule(const char *name, bool isModule=FALSE); -static void addSubprogram(const char *text); -static void addInterface(QCString name, InterfaceType type); -static Argument *getParameter(const QCString &name); -static void scanner_abort(); - -static void startScope(Entry *scope); -static bool endScope(Entry *scope, bool isGlobalRoot=FALSE); -//static bool isTypeName(QCString name); -static void resolveModuleProcedures(Entry *current_root); static int getAmpersandAtTheStart(const char *buf, int length); static int getAmpOrExclAtTheEnd(const char *buf, int length, char ch); -static void truncatePrepass(int index); -static void pushBuffer(QCString &buffer); -static void popBuffer(); -//static void extractPrefix(QCString& text); static QCString extractFromParens(const QCString name); static QCString extractBind(const QCString name); -static CommentInPrepass* locatePrepassComment(int from, int to); -static void updateVariablePrepassComment(int from, int to); -static void newLine(); -static void initEntry(); + + +static int yyread(yyscan_t yyscanner,char *buf,int max_size); +static void startCommentBlock(yyscan_t yyscanner,bool); +static void handleCommentBlock(yyscan_t yyscanner,const QCString &doc,bool brief); +static void subrHandleCommentBlock(yyscan_t yyscanner,const QCString &doc,bool brief); +static void subrHandleCommentBlockResult(yyscan_t yyscanner,const QCString &doc,bool brief); +static void addCurrentEntry(yyscan_t yyscanner,bool case_insens); +static void addModule(yyscan_t yyscanner,const char *name, bool isModule=FALSE); +static void addSubprogram(yyscan_t yyscanner,const char *text); +static void addInterface(yyscan_t yyscanner,QCString name, InterfaceType type); +static Argument *getParameter(yyscan_t yyscanner,const QCString &name); +static void scanner_abort(yyscan_t yyscanner); + +static void startScope(yyscan_t yyscanner,Entry *scope); +static bool endScope(yyscan_t yyscanner,Entry *scope, bool isGlobalRoot=FALSE); +static void resolveModuleProcedures(yyscan_t yyscanner,Entry *current_root); +static void truncatePrepass(yyscan_t yyscanner,int index); +static void pushBuffer(yyscan_t yyscanner,QCString &buffer); +static void popBuffer(yyscan_t yyscanner); +static CommentInPrepass* locatePrepassComment(yyscan_t yyscanner,int from, int to); +static void updateVariablePrepassComment(yyscan_t yyscanner,int from, int to); +static void newLine(yyscan_t yyscanner); +static void initEntry(yyscan_t yyscanner); static const char *stateToString(int state); //----------------------------------------------------------------------------- -#undef YY_INPUT -#define YY_INPUT(buf,result,max_size) result=yyread(buf,max_size); -#define YY_USER_ACTION yyColNr+=(int)yyleng; +#undef YY_INPUT +#define YY_INPUT(buf,result,max_size) result=yyread(yyscanner,buf,max_size); +#define YY_USER_ACTION yyextra->colNr+=(int)yyleng; #define INVALID_ENTRY ((Entry*)0x8) //----------------------------------------------------------------------------- @@ -250,7 +247,7 @@ static const char *stateToString(int state); //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- -IDSYM [a-z_A-Z0-9] +IDSYM [a-z_A-Z0-9] NOTIDSYM [^a-z_A-Z0-9] SEPARATE [:, \t] ID [a-z_A-Z%]+{IDSYM}* @@ -296,18 +293,18 @@ SCOPENAME ({ID}{BS}"::"{BS})* //--------------------------------------------------------------------------------- /** fortran parsing states */ -%x Subprog -%x SubprogPrefix -%x Parameterlist -%x SubprogBody -%x SubprogBodyContains -%x Start -%x Comment +%x Subprog +%x SubprogPrefix +%x Parameterlist +%x SubprogBody +%x SubprogBodyContains +%x Start +%x Comment %x Module %x Program %x ModuleBody -%x ModuleBodyContains -%x AttributeList +%x ModuleBodyContains +%x AttributeList %x Variable %x Initialization %x ArrayInitializer @@ -325,289 +322,325 @@ SCOPENAME ({ID}{BS}"::"{BS})* %x Prepass /** comment parsing states */ -%x DocBlock -%x DocBackLine -%x EndDoc +%x DocBlock +%x DocBackLine +%x EndDoc %x BlockData /** prototype parsing */ -%x Prototype -%x PrototypeSubprog -%x PrototypeArgs +%x Prototype +%x PrototypeSubprog +%x PrototypeArgs %% /*-----------------------------------------------------------------------------------*/ ^{BS}[&]*{BS}!.*\n { /* skip lines with just comment. Note code was in free format or has been converted to it */ - lineCountPrepass ++; + yyextra->lineCountPrepass ++; } ^{BS}\n { /* skip empty lines */ - lineCountPrepass ++; + yyextra->lineCountPrepass ++; } <*>^.*\n { // prepass: look for line continuations - functionLine = FALSE; + yyextra->functionLine = FALSE; DBG_CTX((stderr, "---%s", yytext)); - int indexStart = getAmpersandAtTheStart(yytext, (int)yyleng); - int indexEnd = getAmpOrExclAtTheEnd(yytext, (int)yyleng, '\0'); - if (indexEnd>=0 && yytext[indexEnd]!='&') //we are only interested in amp - indexEnd=-1; - - if(indexEnd<0){ // ----- no ampersand as line continuation - if(YY_START == Prepass) { // last line in "continuation" + int indexStart = getAmpersandAtTheStart(yytext, (int)yyleng); + int indexEnd = getAmpOrExclAtTheEnd(yytext, (int)yyleng, '\0'); + if (indexEnd>=0 && yytext[indexEnd]!='&') //we are only interested in amp + { + indexEnd=-1; + } - // Only take input after initial ampersand - inputStringPrepass+=(const char*)(yytext+(indexStart+1)); - - //printf("BUFFER:%s\n", (const char*)inputStringPrepass); - pushBuffer(inputStringPrepass); - yyColNr = 0; - yy_pop_state(); - } else { // simple line - yyColNr = 0; - REJECT; - } - - } else { // ----- line with continuation - if(YY_START != Prepass) { - comments.setAutoDelete(TRUE); - comments.clear(); - yy_push_state(Prepass); - } + if (indexEnd<0) + { // ----- no ampersand as line continuation + if (YY_START == Prepass) + { // last line in "continuation" - int length = inputStringPrepass.length(); + // Only take input after initial ampersand + yyextra->inputStringPrepass+=(const char*)(yytext+(indexStart+1)); + + //printf("BUFFER:%s\n", (const char*)yyextra->inputStringPrepass); + pushBuffer(yyscanner,yyextra->inputStringPrepass); + yyextra->colNr = 0; + yy_pop_state(yyscanner); + } + else + { // simple line + yyextra->colNr = 0; + REJECT; + } + } + else + { // ----- line with continuation + if (YY_START != Prepass) + { + yyextra->comments.setAutoDelete(TRUE); + yyextra->comments.clear(); + yy_push_state(Prepass,yyscanner); + } - // Only take input after initial ampersand - inputStringPrepass+=(const char*)(yytext+(indexStart+1)); - lineCountPrepass ++; + int length = yyextra->inputStringPrepass.length(); - // cut off & and remove following comment if present - truncatePrepass(length+indexEnd-(indexStart+1)); - } + // Only take input after initial ampersand + yyextra->inputStringPrepass+=(const char*)(yytext+(indexStart+1)); + yyextra->lineCountPrepass ++; + // cut off & and remove following comment if present + truncatePrepass(yyscanner,length+indexEnd-(indexStart+1)); + } } /*------ ignore strings that are not initialization strings */ \"|\' { // string ends with next quote without previous backspace - if (yytext[0]!=stringStartSymbol) { yyColNr -= (int)yyleng; REJECT; } // single vs double quote - if (yy_top_state() == Initialization - || yy_top_state() == ArrayInitializer) - initializer+=yytext; - yy_pop_state(); - } -. { if (yy_top_state() == Initialization - || yy_top_state() == ArrayInitializer) - initializer+=yytext; - } + if (yytext[0]!=yyextra->stringStartSymbol) + { + yyextra->colNr -= (int)yyleng; + REJECT; + } // single vs double quote + if (yy_top_state(yyscanner) == Initialization || + yy_top_state(yyscanner) == ArrayInitializer) + { + yyextra->initializer+=yytext; + } + yy_pop_state(yyscanner); + } +. { if (yy_top_state(yyscanner) == Initialization || + yy_top_state(yyscanner) == ArrayInitializer) + { + yyextra->initializer+=yytext; + } + } <*>\"|\' { /* string starts */ - if (YY_START == StrIgnore) { yyColNr -= (int)yyleng; REJECT; }; // ignore in simple comments - yy_push_state(YY_START); - if (yy_top_state() == Initialization - || yy_top_state() == ArrayInitializer) - initializer+=yytext; - stringStartSymbol=yytext[0]; // single or double quote + if (YY_START == StrIgnore) + { yyextra->colNr -= (int)yyleng; + REJECT; + }; // ignore in simple yyextra->comments + yy_push_state(YY_START,yyscanner); + if (yy_top_state(yyscanner) == Initialization || + yy_top_state(yyscanner) == ArrayInitializer) + { + yyextra->initializer+=yytext; + } + yyextra->stringStartSymbol=yytext[0]; // single or double quote BEGIN(String); } - /*------ ignore simple comment (not documentation comments) */ + /*------ ignore simple comment (not documentation yyextra->comments) */ -<*>"!"/[^<>\n] { if (YY_START == String) { yyColNr -= (int)yyleng; REJECT; } // "!" is ignored in strings - // skip comment line (without docu comments "!>" "!<" ) - /* ignore further "!" and ignore comments in Strings */ +<*>"!"/[^<>\n] { if (YY_START == String) + { yyextra->colNr -= (int)yyleng; + REJECT; + } // "!" is ignored in strings + // skip comment line (without docu yyextra->comments "!>" "!<" ) + /* ignore further "!" and ignore yyextra->comments in Strings */ if ((YY_START != StrIgnore) && (YY_START != String)) - { - yy_push_state(YY_START); + { + yy_push_state(YY_START,yyscanner); BEGIN(StrIgnore); - debugStr="*!"; - DBG_CTX((stderr,"start comment %d\n",yyLineNr)); + yyextra->debugStr="*!"; + DBG_CTX((stderr,"start comment %d\n",yyextra->lineNr)); } } -.?/\n { yy_pop_state(); // comment ends with endline character - DBG_CTX((stderr,"end comment %d %s\n",yyLineNr,debugStr.data())); +.?/\n { yy_pop_state(yyscanner); // comment ends with endline character + DBG_CTX((stderr,"end comment %d %s\n",yyextra->lineNr,yyextra->debugStr.data())); } // comment line ends -. { debugStr+=yytext; } +. { yyextra->debugStr+=yytext; } /*------ use handling ------------------------------------------------------------*/ "use"{BS_} { - if(YY_START == Start) + if (YY_START == Start) { - addModule(NULL); - yy_push_state(ModuleBody); //anon program + addModule(yyscanner,NULL); + yy_push_state(ModuleBody,yyscanner); //anon program } - yy_push_state(Use); + yy_push_state(Use,yyscanner); } {ID} { DBG_CTX((stderr,"using dir %s\n",yytext)); - current->name=yytext; - current->fileName = yyFileName; - current->section=Entry::USINGDIR_SEC; - current_root->moveToSubEntryAndRefresh(current); - current->lang = SrcLangExt_Fortran; - yy_pop_state(); + yyextra->current->name=yytext; + yyextra->current->fileName = yyextra->fileName; + yyextra->current->section=Entry::USINGDIR_SEC; + yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current); + yyextra->current->lang = SrcLangExt_Fortran; + yy_pop_state(yyscanner); } {ID}/, { - useModuleName=yytext; + yyextra->useModuleName=yytext; } ,{BS}"ONLY" { BEGIN(UseOnly); } {BS},{BS} {} {ID} { - current->name= useModuleName+"::"+yytext; - current->fileName = yyFileName; - current->section=Entry::USINGDECL_SEC; - current_root->moveToSubEntryAndRefresh(current); - current->lang = SrcLangExt_Fortran; - } + yyextra->current->name= yyextra->useModuleName+"::"+yytext; + yyextra->current->fileName = yyextra->fileName; + yyextra->current->section=Entry::USINGDECL_SEC; + yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current); + yyextra->current->lang = SrcLangExt_Fortran; + } "\n" { - yyColNr -= 1; + yyextra->colNr -= 1; unput(*yytext); - yy_pop_state(); + yy_pop_state(yyscanner); } /* INTERFACE definitions */ { -^{BS}interface{IDSYM}+ { /* variable with interface prefix */ } -^{BS}interface { ifType = IF_SPECIFIC; - yy_push_state(InterfaceBody); +^{BS}interface{IDSYM}+ { /* variable with interface prefix */ } +^{BS}interface { yyextra->ifType = IF_SPECIFIC; + yy_push_state(InterfaceBody,yyscanner); // do not start a scope here, every // interface body is a scope of its own } -^{BS}abstract{BS_}interface { ifType = IF_ABSTRACT; - yy_push_state(InterfaceBody); +^{BS}abstract{BS_}interface { yyextra->ifType = IF_ABSTRACT; + yy_push_state(InterfaceBody,yyscanner); // do not start a scope here, every // interface body is a scope of its own } -^{BS}interface{BS_}{ID}{ARGS}? { ifType = IF_GENERIC; - current->bodyLine = yyLineNr + lineCountPrepass + 1; // we have to be at the line after the definition and we have to take continuation lines into account. - yy_push_state(InterfaceBody); +^{BS}interface{BS_}{ID}{ARGS}? { yyextra->ifType = IF_GENERIC; + yyextra->current->bodyLine = yyextra->lineNr + yyextra->lineCountPrepass + 1; // we have to be at the line after the definition and we have to take continuation lines into account. + yy_push_state(InterfaceBody,yyscanner); // extract generic name QCString name = QCString(yytext).stripWhiteSpace(); name = name.right(name.length() - 9).stripWhiteSpace().lower(); - addInterface(name, ifType); - startScope(last_entry.get()); + addInterface(yyscanner,name, yyextra->ifType); + startScope(yyscanner,yyextra->last_entry.get()); } } ^{BS}end{BS}interface({BS_}{ID})? { // end scope only if GENERIC interface - if (ifType == IF_GENERIC) last_entry->parent()->endBodyLine = yyLineNr - 1; - if (ifType == IF_GENERIC && !endScope(current_root)) + if (yyextra->ifType == IF_GENERIC) + { + yyextra->last_entry->parent()->endBodyLine = yyextra->lineNr - 1; + } + if (yyextra->ifType == IF_GENERIC && !endScope(yyscanner,yyextra->current_root)) + { yyterminate(); - - ifType = IF_NONE; - yy_pop_state(); + } + yyextra->ifType = IF_NONE; + yy_pop_state(yyscanner); } -module{BS}procedure { yy_push_state(YY_START); +module{BS}procedure { yy_push_state(YY_START,yyscanner); BEGIN(ModuleProcedure); } -{ID} { if (ifType == IF_ABSTRACT || ifType == IF_SPECIFIC) +{ID} { if (yyextra->ifType == IF_ABSTRACT || yyextra->ifType == IF_SPECIFIC) { - addInterface(yytext, ifType); - startScope(last_entry.get()); + addInterface(yyscanner,yytext, yyextra->ifType); + startScope(yyscanner,yyextra->last_entry.get()); } - current->section = Entry::FUNCTION_SEC ; - current->name = yytext; - moduleProcedures.push_back(current); - addCurrentEntry(true); + yyextra->current->section = Entry::FUNCTION_SEC ; + yyextra->current->name = yytext; + yyextra->moduleProcedures.push_back(yyextra->current); + addCurrentEntry(yyscanner,true); } -"\n" { yyColNr -= 1; - unput(*yytext); - yy_pop_state(); +"\n" { yyextra->colNr -= 1; + unput(*yytext); + yy_pop_state(yyscanner); } . {} /*-- Contains handling --*/ -^{BS}{CONTAINS}/({BS}|\n|!|;) { - if(YY_START == Start) +^{BS}{CONTAINS}/({BS}|\n|!|;) { + if (YY_START == Start) { - addModule(NULL); - yy_push_state(ModuleBodyContains); //anon program - } + addModule(yyscanner,NULL); + yy_push_state(ModuleBodyContains,yyscanner); //anon program + } } ^{BS}{CONTAINS}/({BS}|\n|!|;) { BEGIN(ModuleBodyContains); } ^{BS}{CONTAINS}/({BS}|\n|!|;) { BEGIN(SubprogBodyContains); } ^{BS}{CONTAINS}/({BS}|\n|!|;) { BEGIN(TypedefBodyContains); } /*------ module handling ------------------------------------------------------------*/ -block{BS}data{BS}{ID_} { // - v_type = V_IGNORE; - yy_push_state(BlockData); - defaultProtection = Public; - } -module|program{BS_} { // - v_type = V_IGNORE; - if(yytext[0]=='m' || yytext[0]=='M') - yy_push_state(Module); - else - yy_push_state(Program); - defaultProtection = Public; - } +block{BS}data{BS}{ID_} { // + yyextra->vtype = V_IGNORE; + yy_push_state(BlockData,yyscanner); + yyextra->defaultProtection = Public; + } +module|program{BS_} { // + yyextra->vtype = V_IGNORE; + if (yytext[0]=='m' || yytext[0]=='M') + { + yy_push_state(Module,yyscanner); + } + else + { + yy_push_state(Program,yyscanner); + } + yyextra->defaultProtection = Public; + } ^{BS}"end"({BS}(block{BS}data)({BS_}{ID})?)?{BS}/(\n|!|;) { // end block data - //if (!endScope(current_root)) - // yyterminate(); - defaultProtection = Public; - yy_pop_state(); - } + //if (!endScope(yyscanner,yyextra->current_root)) + // yyterminate(); + yyextra->defaultProtection = Public; + yy_pop_state(yyscanner); + } "end"({BS}(module|program)({BS_}{ID})?)?{BS}/(\n|!|;) { // end module - resolveModuleProcedures(current_root); - if (!endScope(current_root)) - yyterminate(); - defaultProtection = Public; - if (global_scope) + resolveModuleProcedures(yyscanner,yyextra->current_root); + if (!endScope(yyscanner,yyextra->current_root)) + { + yyterminate(); + } + yyextra->defaultProtection = Public; + if (yyextra->global_scope) + { + if (yyextra->global_scope != INVALID_ENTRY) { - if (global_scope != INVALID_ENTRY) - yy_push_state(Start); - else - yy_pop_state(); // cannot pop artrificial entry + yy_push_state(Start,yyscanner); } else { - yy_push_state(Start); - global_scope = INVALID_ENTRY; // signal that the global_scope has already been used. + yy_pop_state(yyscanner); // cannot pop artrificial entry } - } -{ID} { - addModule(yytext, TRUE); - BEGIN(ModuleBody); - } - + } + else + { + yy_push_state(Start,yyscanner); + yyextra->global_scope = INVALID_ENTRY; // signal that the yyextra->global_scope has already been used. + } + } +{ID} { + addModule(yyscanner,yytext, TRUE); + BEGIN(ModuleBody); + } {ID} { - addModule(yytext, FALSE); - BEGIN(ModuleBody); - } + addModule(yyscanner,yytext, FALSE); + BEGIN(ModuleBody); + } /*------- access specification --------------------------------------------------------------------------*/ -private/{BS}(\n|"!") { defaultProtection = Private; - current->protection = defaultProtection ; - } -public/{BS}(\n|"!") { defaultProtection = Public; - current->protection = defaultProtection ; - } +private/{BS}(\n|"!") { yyextra->defaultProtection = Private; + yyextra->current->protection = yyextra->defaultProtection ; + } +public/{BS}(\n|"!") { yyextra->defaultProtection = Public; + yyextra->current->protection = yyextra->defaultProtection ; + } /*------- type definition -------------------------------------------------------------------------------*/ -^{BS}type/[^a-z0-9_] { - if(YY_START == Start) +^{BS}type/[^a-z0-9_] { + if (YY_START == Start) { - addModule(NULL); - yy_push_state(ModuleBody); //anon program + addModule(yyscanner,NULL); + yy_push_state(ModuleBody,yyscanner); //anon program } - yy_push_state(Typedef); - current->protection = defaultProtection; - typeProtection = defaultProtection; - typeMode = true; + yy_push_state(Typedef,yyscanner); + yyextra->current->protection = yyextra->defaultProtection; + yyextra->typeProtection = yyextra->defaultProtection; + yyextra->typeMode = true; } { {COMMA} {} @@ -615,100 +648,104 @@ SCOPENAME ({ID}{BS}"::"{BS})* {BS}"::"{BS} {} abstract { - current->spec |= Entry::AbstractClass; + yyextra->current->spec |= Entry::AbstractClass; } extends{ARGS} { QCString basename = extractFromParens(yytext).lower(); - current->extends.push_back(BaseInfo(basename, Public, Normal)); + yyextra->current->extends.push_back(BaseInfo(basename, Public, Normal)); } public { - current->protection = Public; - typeProtection = Public; + yyextra->current->protection = Public; + yyextra->typeProtection = Public; } private { - current->protection = Private; - typeProtection = Private; + yyextra->current->protection = Private; + yyextra->typeProtection = Private; } {LANGUAGE_BIND_SPEC} { /* ignored for now */ } {ID} { /* type name found */ - current->section = Entry::CLASS_SEC; - current->spec |= Entry::Struct; - current->name = yytext; - current->fileName = yyFileName; - current->bodyLine = yyLineNr; - current->startLine = yyLineNr; + yyextra->current->section = Entry::CLASS_SEC; + yyextra->current->spec |= Entry::Struct; + yyextra->current->name = yytext; + yyextra->current->fileName = yyextra->fileName; + yyextra->current->bodyLine = yyextra->lineNr; + yyextra->current->startLine = yyextra->lineNr; /* if type is part of a module, mod name is necessary for output */ - if (current_root && - (current_root->section == Entry::CLASS_SEC - || current_root->section == Entry::NAMESPACE_SEC)) + if (yyextra->current_root && + (yyextra->current_root->section == Entry::CLASS_SEC || + yyextra->current_root->section == Entry::NAMESPACE_SEC)) { - current->name = current_root->name + "::" + current->name; + yyextra->current->name = yyextra->current_root->name + "::" + yyextra->current->name; } - addCurrentEntry(true); - startScope(last_entry.get()); + addCurrentEntry(yyscanner,true); + startScope(yyscanner,yyextra->last_entry.get()); BEGIN(TypedefBody); } } { /* Type Bound Procedures */ ^{BS}PROCEDURE{ARGS}? { - current->type = QCString(yytext).simplifyWhiteSpace(); + yyextra->current->type = QCString(yytext).simplifyWhiteSpace(); } ^{BS}final { - current->spec |= Entry::Final; - current->type = QCString(yytext).simplifyWhiteSpace(); + yyextra->current->spec |= Entry::Final; + yyextra->current->type = QCString(yytext).simplifyWhiteSpace(); } ^{BS}generic { - current->type = QCString(yytext).simplifyWhiteSpace(); + yyextra->current->type = QCString(yytext).simplifyWhiteSpace(); } {COMMA} { } {ATTR_SPEC} { - currentModifiers |= QCString(yytext); + yyextra->currentModifiers |= QCString(yytext); } {BS}"::"{BS} { } {ID} { QCString name = yytext; - modifiers[current_root][name.lower()] |= currentModifiers; - current->section = Entry::FUNCTION_SEC; - current->name = name; - current->fileName = yyFileName; - current->bodyLine = yyLineNr; - current->startLine = yyLineNr; - addCurrentEntry(true); + yyextra->modifiers[yyextra->current_root][name.lower()] |= yyextra->currentModifiers; + yyextra->current->section = Entry::FUNCTION_SEC; + yyextra->current->name = name; + yyextra->current->fileName = yyextra->fileName; + yyextra->current->bodyLine = yyextra->lineNr; + yyextra->current->startLine = yyextra->lineNr; + addCurrentEntry(yyscanner,true); } {BS}"=>"[^(\n|\!)]* { /* Specific bindings come after the ID. */ QCString args = yytext; - last_entry->args = args.lower(); + yyextra->last_entry->args = args.lower(); } "\n" { - currentModifiers = SymbolModifiers(); - newLine(); - docBlock.resize(0); + yyextra->currentModifiers = SymbolModifiers(); + newLine(yyscanner); + yyextra->docBlock.resize(0); } } { ^{BS}"end"{BS}"type"({BS_}{ID})?{BS}/(\n|!|;) { /* end type definition */ - last_entry->parent()->endBodyLine = yyLineNr; - if (!endScope(current_root)) + yyextra->last_entry->parent()->endBodyLine = yyextra->lineNr; + if (!endScope(yyscanner,yyextra->current_root)) + { yyterminate(); - typeMode = false; - yy_pop_state(); + } + yyextra->typeMode = false; + yy_pop_state(yyscanner); } ^{BS}"end"{BS}/(\n|!|;) { /* incorrect end type definition */ - warn(yyFileName,yyLineNr, "Found 'END' instead of 'END TYPE'"); - last_entry->parent()->endBodyLine = yyLineNr; - if (!endScope(current_root)) + warn(yyextra->fileName,yyextra->lineNr, "Found 'END' instead of 'END TYPE'"); + yyextra->last_entry->parent()->endBodyLine = yyextra->lineNr; + if (!endScope(yyscanner,yyextra->current_root)) + { yyterminate(); - typeMode = false; - yy_pop_state(); + } + yyextra->typeMode = false; + yy_pop_state(yyscanner); } } @@ -720,603 +757,594 @@ private { // in a scope of their own, even if multiple // are group in one INTERFACE/END INTERFACE block. // - if (ifType == IF_ABSTRACT || ifType == IF_SPECIFIC) + if (yyextra->ifType == IF_ABSTRACT || yyextra->ifType == IF_SPECIFIC) { - endScope(current_root); - last_entry->endBodyLine = yyLineNr - 1; + endScope(yyscanner,yyextra->current_root); + yyextra->last_entry->endBodyLine = yyextra->lineNr - 1; } - current_root->endBodyLine = yyLineNr - 1; + yyextra->current_root->endBodyLine = yyextra->lineNr - 1; - if (!endScope(current_root)) - yyterminate(); - subrCurrent.pop_back(); - yy_pop_state() ; - } + if (!endScope(yyscanner,yyextra->current_root)) + { + yyterminate(); + } + yyextra->subrCurrent.pop_back(); + yy_pop_state(yyscanner) ; + } { {ID} { } } { ^{BS}{TYPE_SPEC}/{SEPARATE} { - last_enum.reset(); + yyextra->last_enum.reset(); if (YY_START == Enum) { - argType = "@"; // enum marker + yyextra->argType = "@"; // enum marker } else { - argType = QCString(yytext).simplifyWhiteSpace().lower(); + yyextra->argType = QCString(yytext).simplifyWhiteSpace().lower(); } - current->bodyLine = yyLineNr + 1; - current->endBodyLine = yyLineNr + lineCountPrepass; + yyextra->current->bodyLine = yyextra->lineNr + 1; + yyextra->current->endBodyLine = yyextra->lineNr + yyextra->lineCountPrepass; /* variable declaration starts */ - if(YY_START == Start) + if (YY_START == Start) { - addModule(NULL); - yy_push_state(ModuleBody); //anon program + addModule(yyscanner,NULL); + yy_push_state(ModuleBody,yyscanner); //anon program } - yy_push_state(AttributeList); - } - /* Dimitri: macro expansion should already be done during preprocessing not here! -^{BS}{PP_ID}{KIND}? { // check for preprocessor symbol expand to type - QCString str = yytext; - str = str.stripWhiteSpace(); - //DefineDict* defines = getGlobalDefineDict(); - QCString name; - int index = str.find("("); - if (index != -1) - name = str.left(index).stripWhiteSpace(); - else - name = str; - - Define *define = 0; //(*defines)[name]; - if (define != 0 && isTypeName(define->definition)) - { - argType = str; - yy_push_state(AttributeList); - } - else - { - yyColNr -= (int)yyleng; - REJECT; - } - } - */ -{EXTERNAL_STMT}/({BS}"::"|{BS_}{ID}) { + yy_push_state(AttributeList,yyscanner); + } +{EXTERNAL_STMT}/({BS}"::"|{BS_}{ID}) { /* external can be a "type" or an attribute */ - if(YY_START == Start) + if (YY_START == Start) { - addModule(NULL); - yy_push_state(ModuleBody); //anon program + addModule(yyscanner,NULL); + yy_push_state(ModuleBody,yyscanner); //anon program } QCString tmp = yytext; - currentModifiers |= tmp.stripWhiteSpace(); - argType = QCString(yytext).simplifyWhiteSpace().lower(); - yy_push_state(AttributeList); - } -{ATTR_STMT}/{BS_}{ID} | -{ATTR_STMT}/{BS}"::" { + yyextra->currentModifiers |= tmp.stripWhiteSpace(); + yyextra->argType = QCString(yytext).simplifyWhiteSpace().lower(); + yy_push_state(AttributeList,yyscanner); + } +{ATTR_STMT}/{BS_}{ID} | +{ATTR_STMT}/{BS}"::" { /* attribute statement starts */ DBG_CTX((stderr,"5=========> Attribute statement: %s\n", yytext)); QCString tmp = yytext; - currentModifiers |= tmp.stripWhiteSpace(); - argType=""; - yy_push_state(YY_START); - BEGIN( AttributeList ) ; - } -{ID} { - } -^{BS}"type"{BS_}"is"/{BT_} { } -^{BS}"type"{BS}"=" { } -^{BS}"class"{BS_}"is"/{BT_} { } -^{BS}"class"{BS_}"default" { } + yyextra->currentModifiers |= tmp.stripWhiteSpace(); + yyextra->argType=""; + yy_push_state(YY_START,yyscanner); + BEGIN( AttributeList ) ; + } +{ID} { + } +^{BS}"type"{BS_}"is"/{BT_} {} +^{BS}"type"{BS}"=" {} +^{BS}"class"{BS_}"is"/{BT_} {} +^{BS}"class"{BS_}"default" {} } { -{COMMA} {} -{BS} {} +{COMMA} {} +{BS} {} {LANGUAGE_BIND_SPEC} { - currentModifiers |= yytext; + yyextra->currentModifiers |= yytext; } -{ATTR_SPEC}. { /* update current modifiers when it is an ATTR_SPEC and not a variable name */ - /* bug_625519 */ +{ATTR_SPEC}. { /* update yyextra->current yyextra->modifiers when it is an ATTR_SPEC and not a variable name */ + /* buyyextra->625519 */ QChar chr = yytext[(int)yyleng-1]; if (chr.isLetter() || chr.isDigit() || (chr == '_')) { - yyColNr -= (int)yyleng; + yyextra->colNr -= (int)yyleng; REJECT; } else { QCString tmp = yytext; tmp = tmp.left(tmp.length() - 1); - yyColNr -= 1; + yyextra->colNr -= 1; unput(yytext[(int)yyleng-1]); - currentModifiers |= (tmp); + yyextra->currentModifiers |= (tmp); } - } -"::" { /* end attribute list */ - BEGIN( Variable ); - } -. { /* unknown attribute, consider variable name */ - //cout<<"start variables, unput "<<*yytext<colNr -= 1; + unput(*yytext); + BEGIN( Variable ); + } } -{BS} { } -{ID} { /* parse variable declaration */ - //cout << "5=========> got variable: " << argType << "::" << yytext << endl; - /* work around for bug in QCString.replace (QCString works) */ - QCString name=yytext; +{BS} {} +{ID} { /* parse variable declaration */ + //cout << "5=========> got variable: " << yyextra->argType << "::" << yytext << endl; + /* work around for bug in QCString.replace (QCString works) */ + QCString name=yytext; name = name.lower(); - /* remember attributes for the symbol */ - modifiers[current_root][name.lower()] |= currentModifiers; - argName= name; + /* remember attributes for the symbol */ + yyextra->modifiers[yyextra->current_root][name.lower()] |= yyextra->currentModifiers; + yyextra->argName= name; - v_type= V_IGNORE; - if (!argType.isEmpty() && current_root->section!=Entry::FUNCTION_SEC) + yyextra->vtype= V_IGNORE; + if (!yyextra->argType.isEmpty() && yyextra->current_root->section!=Entry::FUNCTION_SEC) { // new variable entry - v_type = V_VARIABLE; - current->section = Entry::VARIABLE_SEC; - current->name = argName; - current->type = argType; - current->fileName = yyFileName; - current->bodyLine = yyLineNr; // used for source reference - current->startLine = yyLineNr; - if (argType == "@") + yyextra->vtype = V_VARIABLE; + yyextra->current->section = Entry::VARIABLE_SEC; + yyextra->current->name = yyextra->argName; + yyextra->current->type = yyextra->argType; + yyextra->current->fileName = yyextra->fileName; + yyextra->current->bodyLine = yyextra->lineNr; // used for source reference + yyextra->current->startLine = yyextra->lineNr; + if (yyextra->argType == "@") { - current_root->copyToSubEntry(current); + yyextra->current_root->copyToSubEntry(yyextra->current); // add to the scope surrounding the enum (copy!) - last_enum = current; - current_root->parent()->moveToSubEntryAndRefresh(current); - initEntry(); + yyextra->last_enum = yyextra->current; + yyextra->current_root->parent()->moveToSubEntryAndRefresh(yyextra->current); + initEntry(yyscanner); } else { - addCurrentEntry(true); + addCurrentEntry(yyscanner,true); + } + } + else if (!yyextra->argType.isEmpty()) + { // declaration of parameter list: add type for corr. parameter + Argument *parameter = getParameter(yyscanner,yyextra->argName); + if (parameter) + { + yyextra->vtype= V_PARAMETER; + if (!yyextra->argType.isNull()) parameter->type=yyextra->argType.stripWhiteSpace(); + if (!yyextra->docBlock.isNull()) + { + subrHandleCommentBlock(yyscanner,yyextra->docBlock,TRUE); + } + } + // save, it may be function return type + if (parameter) + { + yyextra->modifiers[yyextra->current_root][name.lower()].type = yyextra->argType; + } + else + { + if ((yyextra->current_root->name.lower() == yyextra->argName.lower()) || + (yyextra->modifiers[yyextra->current_root->parent()][yyextra->current_root->name.lower()].returnName.lower() == yyextra->argName.lower())) + { + int strt = yyextra->current_root->type.find("function"); + QCString lft; + QCString rght; + if (strt != -1) + { + yyextra->vtype = V_RESULT; + lft = ""; + rght = ""; + if (strt != 0) lft = yyextra->current_root->type.left(strt).stripWhiteSpace(); + if ((yyextra->current_root->type.length() - strt - strlen("function"))!= 0) + { + rght = yyextra->current_root->type.right(yyextra->current_root->type.length() - strt - strlen("function")).stripWhiteSpace(); + } + yyextra->current_root->type = lft; + if (rght.length() > 0) + { + if (yyextra->current_root->type.length() > 0) yyextra->current_root->type += " "; + yyextra->current_root->type += rght; + } + if (yyextra->argType.stripWhiteSpace().length() > 0) + { + if (yyextra->current_root->type.length() > 0) yyextra->current_root->type += " "; + yyextra->current_root->type += yyextra->argType.stripWhiteSpace(); + } + if (yyextra->current_root->type.length() > 0) yyextra->current_root->type += " "; + yyextra->current_root->type += "function"; + if (!yyextra->docBlock.isNull()) + { + subrHandleCommentBlockResult(yyscanner,yyextra->docBlock,TRUE); + } + } + else + { + yyextra->current_root->type += " " + yyextra->argType.stripWhiteSpace(); + } + yyextra->current_root->type = yyextra->current_root->type.stripWhiteSpace(); + yyextra->modifiers[yyextra->current_root][name.lower()].type = yyextra->current_root->type; + } + else + { + yyextra->modifiers[yyextra->current_root][name.lower()].type = yyextra->argType; + } } + // any accumulated doc for argument should be emptied, + // because it is handled other way and this doc can be + // unexpectedly passed to the next member. + yyextra->current->doc.resize(0); + yyextra->current->brief.resize(0); } - else if (!argType.isEmpty()) - { // declaration of parameter list: add type for corr. parameter - parameter = getParameter(argName); - if (parameter) - { - v_type= V_PARAMETER; - if (!argType.isNull()) parameter->type=argType.stripWhiteSpace(); - if (!docBlock.isNull()) - { - subrHandleCommentBlock(docBlock,TRUE); - } - } - // save, it may be function return type - if (parameter) - { - modifiers[current_root][name.lower()].type = argType; - } - else - { - if ((current_root->name.lower() == argName.lower()) || - (modifiers[current_root->parent()][current_root->name.lower()].returnName.lower() == argName.lower())) - { - int strt = current_root->type.find("function"); - QCString lft; - QCString rght; - if (strt != -1) - { - v_type = V_RESULT; - lft = ""; - rght = ""; - if (strt != 0) lft = current_root->type.left(strt).stripWhiteSpace(); - if ((current_root->type.length() - strt - strlen("function"))!= 0) - { - rght = current_root->type.right(current_root->type.length() - strt - strlen("function")).stripWhiteSpace(); - } - current_root->type = lft; - if (rght.length() > 0) - { - if (current_root->type.length() > 0) current_root->type += " "; - current_root->type += rght; - } - if (argType.stripWhiteSpace().length() > 0) - { - if (current_root->type.length() > 0) current_root->type += " "; - current_root->type += argType.stripWhiteSpace(); - } - if (current_root->type.length() > 0) current_root->type += " "; - current_root->type += "function"; - if (!docBlock.isNull()) - { - subrHandleCommentBlockResult(docBlock,TRUE); - } - } - else - { - current_root->type += " " + argType.stripWhiteSpace(); - } - current_root->type = current_root->type.stripWhiteSpace(); - modifiers[current_root][name.lower()].type = current_root->type; - } - else - { - modifiers[current_root][name.lower()].type = argType; - } - } - // any accumulated doc for argument should be emptied, - // because it is handled other way and this doc can be - // unexpectedly passed to the next member. - current->doc.resize(0); - current->brief.resize(0); - } - } -{ARGS} { /* dimension of the previous entry. */ - QCString name(argName); - QCString attr("dimension"); - attr += yytext; - modifiers[current_root][name.lower()] |= attr; - } -{COMMA} { //printf("COMMA: %d<=..<=%d\n", yyColNr-(int)yyleng, yyColNr); - // locate !< comment - updateVariablePrepassComment(yyColNr-(int)yyleng, yyColNr); - } + } +{ARGS} { /* dimension of the previous entry. */ + QCString name(yyextra->argName); + QCString attr("dimension"); + attr += yytext; + yyextra->modifiers[yyextra->current_root][name.lower()] |= attr; + } +{COMMA} { //printf("COMMA: %d<=..<=%d\n", yyextra->colNr-(int)yyleng, yyextra->colNr); + // locate !< comment + updateVariablePrepassComment(yyscanner,yyextra->colNr-(int)yyleng, yyextra->colNr); + } {BS}"=" { - yy_push_state(YY_START); - initializer="="; - initializerScope = initializerArrayScope = 0; - BEGIN(Initialization); - } -"\n" { currentModifiers = SymbolModifiers(); - yy_pop_state(); // end variable declaration list - newLine(); - docBlock.resize(0); - } -";".*"\n" { currentModifiers = SymbolModifiers(); - yy_pop_state(); // end variable declaration list - docBlock.resize(0); - inputStringSemi =(const char*)(QCString(" \n") + QCString(yytext+1)).data(); - yyLineNr--; - pushBuffer(inputStringSemi); + yy_push_state(YY_START,yyscanner); + yyextra->initializer="="; + yyextra->initializerScope = yyextra->initializerArrayScope = 0; + BEGIN(Initialization); + } +"\n" { yyextra->currentModifiers = SymbolModifiers(); + yy_pop_state(yyscanner); // end variable declaration list + newLine(yyscanner); + yyextra->docBlock.resize(0); + } +";".*"\n" { yyextra->currentModifiers = SymbolModifiers(); + yy_pop_state(yyscanner); // end variable declaration list + yyextra->docBlock.resize(0); + yyextra->inputStringSemi =(const char*)(QCString(" \n") + QCString(yytext+1)).data(); + yyextra->lineNr--; + pushBuffer(yyscanner,yyextra->inputStringSemi); } <*>";".*"\n" { - if (YY_START == Variable) REJECT; // Just be on the safe side + if (YY_START == Variable) REJECT; // Just be on the safe side if (YY_START == String) REJECT; // ";" ignored in strings - if (YY_START == StrIgnore) REJECT; // ";" ignored in regular comments - inputStringSemi =(const char*)(QCString(" \n") + QCString(yytext+1)).data(); - yyLineNr--; - pushBuffer(inputStringSemi); + if (YY_START == StrIgnore) REJECT; // ";" ignored in regular yyextra->comments + yyextra->inputStringSemi =(const char*)(QCString(" \n") + QCString(yytext+1)).data(); + yyextra->lineNr--; + pushBuffer(yyscanner,yyextra->inputStringSemi); } "[" | -"(/" { initializer+=yytext; - initializerArrayScope++; - BEGIN(ArrayInitializer); // initializer may contain comma +"(/" { yyextra->initializer+=yytext; + yyextra->initializerArrayScope++; + BEGIN(ArrayInitializer); // initializer may contain comma } "]" | -"/)" { initializer+=yytext; - initializerArrayScope--; - if(initializerArrayScope<=0) - { - initializerArrayScope = 0; // just in case - BEGIN(Initialization); - } +"/)" { yyextra->initializer+=yytext; + yyextra->initializerArrayScope--; + if (yyextra->initializerArrayScope<=0) + { + yyextra->initializerArrayScope = 0; // just in case + BEGIN(Initialization); + } } -. { initializer+=yytext; } -"(" { initializerScope++; - initializer+=yytext; - } -")" { initializerScope--; - initializer+=yytext; - } -{COMMA} { if (initializerScope == 0) - { - updateVariablePrepassComment(yyColNr-(int)yyleng, yyColNr); - yy_pop_state(); // end initialization - if (last_enum) +. { yyextra->initializer+=yytext; } +"(" { yyextra->initializerScope++; + yyextra->initializer+=yytext; + } +")" { yyextra->initializerScope--; + yyextra->initializer+=yytext; + } +{COMMA} { if (yyextra->initializerScope == 0) + { + updateVariablePrepassComment(yyscanner,yyextra->colNr-(int)yyleng, yyextra->colNr); + yy_pop_state(yyscanner); // end initialization + if (yyextra->last_enum) { - last_enum->initializer= initializer; + yyextra->last_enum->initializer= yyextra->initializer; } else { - if (v_type == V_VARIABLE) last_entry->initializer= initializer; + if (yyextra->vtype == V_VARIABLE) yyextra->last_entry->initializer= yyextra->initializer; } - } - else - initializer+=", "; - } + } + else + { + yyextra->initializer+=", "; + } + } "\n"|"!" { //| - yy_pop_state(); // end initialization - if (last_enum) + yy_pop_state(yyscanner); // end initialization + if (yyextra->last_enum) { - last_enum->initializer= initializer; + yyextra->last_enum->initializer= yyextra->initializer; } else { - if (v_type == V_VARIABLE) last_entry->initializer= initializer; + if (yyextra->vtype == V_VARIABLE) yyextra->last_entry->initializer= yyextra->initializer; } - yyColNr -= 1; - unput(*yytext); + yyextra->colNr -= 1; + unput(*yytext); } -. { initializer+=yytext; } +. { yyextra->initializer+=yytext; } <*>{BS}"enum"{BS}","{BS}"bind"{BS}"("{BS}"c"{BS}")"{BS} { - if(YY_START == Start) + if (YY_START == Start) { - addModule(NULL); - yy_push_state(ModuleBody); //anon program + addModule(yyscanner,NULL); + yy_push_state(ModuleBody,yyscanner); //anon program } - yy_push_state(Enum); - current->protection = defaultProtection; - typeProtection = defaultProtection; - typeMode = true; - - current->spec |= Entry::Struct; - current->name.resize(0); - current->args.resize(0); - current->name.sprintf("@%d",anonCount++); - - current->section = Entry::ENUM_SEC; - current->fileName = yyFileName; - current->startLine = yyLineNr; - current->bodyLine = yyLineNr; - if ((current_root) && - (current_root->section == Entry::CLASS_SEC - || current_root->section == Entry::NAMESPACE_SEC)) + yy_push_state(Enum,yyscanner); + yyextra->current->protection = yyextra->defaultProtection; + yyextra->typeProtection = yyextra->defaultProtection; + yyextra->typeMode = true; + + yyextra->current->spec |= Entry::Struct; + yyextra->current->name.resize(0); + yyextra->current->args.resize(0); + yyextra->current->name.sprintf("@%d",yyextra->anonCount++); + + yyextra->current->section = Entry::ENUM_SEC; + yyextra->current->fileName = yyextra->fileName; + yyextra->current->startLine = yyextra->lineNr; + yyextra->current->bodyLine = yyextra->lineNr; + if ((yyextra->current_root) && + (yyextra->current_root->section == Entry::CLASS_SEC || + yyextra->current_root->section == Entry::NAMESPACE_SEC)) { - current->name = current_root->name + "::" + current->name; + yyextra->current->name = yyextra->current_root->name + "::" + yyextra->current->name; } - addCurrentEntry(true); - startScope(last_entry.get()); - BEGIN( Enum ) ; + addCurrentEntry(yyscanner,true); + startScope(yyscanner,yyextra->last_entry.get()); + BEGIN( Enum ) ; } "end"{BS}"enum" { - last_entry->parent()->endBodyLine = yyLineNr; - if (!endScope(current_root)) + yyextra->last_entry->parent()->endBodyLine = yyextra->lineNr; + if (!endScope(yyscanner,yyextra->current_root)) + { yyterminate(); - typeMode = false; - yy_pop_state(); + } + yyextra->typeMode = false; + yy_pop_state(yyscanner); } /*------ fortran subroutine/function handling ------------------------------------------------------------*/ /* Start is initial condition */ ^{BS}({PREFIX}{BS_})?{TYPE_SPEC}{BS}({PREFIX}{BS_})?/{SUBPROG}{BS_} { - if (ifType == IF_ABSTRACT || ifType == IF_SPECIFIC) - { - addInterface("$interface$", ifType); - startScope(last_entry.get()); - } + if (yyextra->ifType == IF_ABSTRACT || yyextra->ifType == IF_SPECIFIC) + { + addInterface(yyscanner,"$interface$", yyextra->ifType); + startScope(yyscanner,yyextra->last_entry.get()); + } + + // TYPE_SPEC is for old function style function result + QCString result = QCString(yytext).stripWhiteSpace().lower(); + yyextra->current->type = result; + yy_push_state(SubprogPrefix,yyscanner); + } - // TYPE_SPEC is for old function style function result - result = QCString(yytext).stripWhiteSpace().lower(); - current->type = result; - yy_push_state(SubprogPrefix); - } - -{BS}{SUBPROG}{BS_} { - // Fortran subroutine or function found - v_type = V_IGNORE; - result=yytext; - result=result.stripWhiteSpace(); - addSubprogram(result); - BEGIN(Subprog); - current->bodyLine = yyLineNr + lineCountPrepass + 1; // we have to be at the line after the definition and we have to take continuation lines into account. - current->startLine = yyLineNr; - } +{BS}{SUBPROG}{BS_} { + // Fortran subroutine or function found + yyextra->vtype = V_IGNORE; + QCString result=yytext; + result=result.stripWhiteSpace(); + addSubprogram(yyscanner,result); + BEGIN(Subprog); + yyextra->current->bodyLine = yyextra->lineNr + yyextra->lineCountPrepass + 1; // we have to be at the line after the definition and we have to take continuation lines into account. + yyextra->current->startLine = yyextra->lineNr; + } ^{BS}({PREFIX}{BS_})?{SUBPROG}{BS_} { - // Fortran subroutine or function found - v_type = V_IGNORE; - if (ifType == IF_ABSTRACT || ifType == IF_SPECIFIC) - { - addInterface("$interface$", ifType); - startScope(last_entry.get()); - } + // Fortran subroutine or function found + yyextra->vtype = V_IGNORE; + if (yyextra->ifType == IF_ABSTRACT || yyextra->ifType == IF_SPECIFIC) + { + addInterface(yyscanner,"$interface$", yyextra->ifType); + startScope(yyscanner,yyextra->last_entry.get()); + } + + QCString result = QCString(yytext).stripWhiteSpace(); + addSubprogram(yyscanner,result); + yy_push_state(Subprog,yyscanner); + yyextra->current->bodyLine = yyextra->lineNr + yyextra->lineCountPrepass + 1; // we have to be at the line after the definition and we have to take continuation lines into account. + yyextra->current->startLine = yyextra->lineNr; + } + +{BS} { /* ignore white space */ } +{ID} { yyextra->current->name = yytext; + //cout << "1a==========> got " << yyextra->current->type << " " << yytext << " " << yyextra->lineNr << endl; + yyextra->modifiers[yyextra->current_root][yyextra->current->name.lower()].returnName = yyextra->current->name.lower(); - result = QCString(yytext).stripWhiteSpace(); - addSubprogram(result); - yy_push_state(Subprog); - current->bodyLine = yyLineNr + lineCountPrepass + 1; // we have to be at the line after the definition and we have to take continuation lines into account. - current->startLine = yyLineNr; - } - -{BS} { /* ignore white space */ } -{ID} { current->name = yytext; - //cout << "1a==========> got " << current->type << " " << yytext << " " << yyLineNr << endl; - modifiers[current_root][current->name.lower()].returnName = current->name.lower(); - - if (ifType == IF_ABSTRACT || ifType == IF_SPECIFIC) - { - current_root->name.replace(QRegExp("\\$interface\\$"), yytext); + if (yyextra->ifType == IF_ABSTRACT || yyextra->ifType == IF_SPECIFIC) + { + yyextra->current_root->name.replace(QRegExp("\\$interface\\$"), yytext); + } + + BEGIN(Parameterlist); + } +"(" { yyextra->current->args = "("; } +")" { + yyextra->current->args += ")"; + yyextra->current->args = removeRedundantWhiteSpace(yyextra->current->args); + addCurrentEntry(yyscanner,true); + startScope(yyscanner,yyextra->last_entry.get()); + BEGIN(SubprogBody); + } +{COMMA}|{BS} { yyextra->current->args += yytext; + CommentInPrepass *c = locatePrepassComment(yyscanner,yyextra->colNr-(int)yyleng, yyextra->colNr); + if (c!=NULL) + { + if (!yyextra->current->argList.empty()) + { + yyextra->current->argList.back().docs = c->str; + } + } + } +{ID} { + //yyextra->current->type not yet available + QCString param = yytext; + // std::cout << "3=========> got parameter " << param << std::endl; + yyextra->current->args += param; + Argument arg; + arg.name = param; + yyextra->current->argList.push_back(arg); + } +{NOARGS} { + newLine(yyscanner); + //printf("3=========> without parameterlist \n"); + addCurrentEntry(yyscanner,true); + startScope(yyscanner,yyextra->last_entry.get()); + BEGIN(SubprogBody); + } +result{BS}\({BS}{ID} { + if (yyextra->functionLine) + { + QCString result= yytext; + result= result.right(result.length()-result.find("(")-1); + result= result.stripWhiteSpace(); + yyextra->modifiers[yyextra->current_root->parent()][yyextra->current_root->name.lower()].returnName = result; + } + //cout << "=====> got result " << result << endl; } - BEGIN(Parameterlist); - } -"(" { current->args = "("; } -")" { - current->args += ")"; - current->args = removeRedundantWhiteSpace(current->args); - addCurrentEntry(true); - startScope(last_entry.get()); - BEGIN(SubprogBody); - } -{COMMA}|{BS} { current->args += yytext; - CommentInPrepass *c = locatePrepassComment(yyColNr-(int)yyleng, yyColNr); - if (c!=NULL) - { - if (!current->argList.empty()) - { - current->argList.back().docs = c->str; - } - } - } -{ID} { - //current->type not yet available - QCString param = yytext; - // std::cout << "3=========> got parameter " << param << std::endl; - current->args += param; - Argument arg; - arg.name = param; - current->argList.push_back(arg); - } -{NOARGS} { - newLine(); - //printf("3=========> without parameterlist \n"); - addCurrentEntry(true); - startScope(last_entry.get()); - BEGIN(SubprogBody); -} -result{BS}\({BS}{ID} { - if (functionLine) - { - result= yytext; - result= result.right(result.length()-result.find("(")-1); - result= result.stripWhiteSpace(); - modifiers[current_root->parent()][current_root->name.lower()].returnName = result; - } - //cout << "=====> got result " << result << endl; - } - - /*---- documentation comments --------------------------------------------------------------------*/ + /*---- documentation yyextra->comments --------------------------------------------------------------------*/ "!<" { /* backward docu comment */ - if (v_type != V_IGNORE) { - current->docLine = yyLineNr; - docBlockJavaStyle = FALSE; - docBlock.resize(0); - docBlockJavaStyle = Config_getBool(JAVADOC_AUTOBRIEF); - startCommentBlock(TRUE); - yy_push_state(DocBackLine); + if (yyextra->vtype != V_IGNORE) + { + yyextra->current->docLine = yyextra->lineNr; + yyextra->docBlockJavaStyle = FALSE; + yyextra->docBlock.resize(0); + yyextra->docBlockJavaStyle = Config_getBool(JAVADOC_AUTOBRIEF); + startCommentBlock(yyscanner,TRUE); + yy_push_state(DocBackLine,yyscanner); } else { /* handle out of place !< comment as a normal comment */ - if (YY_START == String) { yyColNr -= (int)yyleng; REJECT; } // "!" is ignored in strings - // skip comment line (without docu comments "!>" "!<" ) - /* ignore further "!" and ignore comments in Strings */ - if ((YY_START != StrIgnore) && (YY_START != String)) - { - yy_push_state(YY_START); - BEGIN(StrIgnore); - debugStr="*!"; - } + if (YY_START == String) + { + yyextra->colNr -= (int)yyleng; + REJECT; + } // "!" is ignored in strings + // skip comment line (without docu yyextra->comments "!>" "!<" ) + /* ignore further "!" and ignore yyextra->comments in Strings */ + if ((YY_START != StrIgnore) && (YY_START != String)) + { + yy_push_state(YY_START,yyscanner); + BEGIN(StrIgnore); + yyextra->debugStr="*!"; + } } - } -.* { // contents of current comment line - docBlock+=yytext; - } -"\n"{BS}"!"("<"|"!"+) { // comment block (next line is also comment line) - docBlock+="\n"; // \n is necessary for lists - newLine(); - } -"\n" { // comment block ends at the end of this line - //cout <<"3=========> comment block : "<< docBlock << endl; - yyColNr -= 1; - unput(*yytext); - if (v_type == V_VARIABLE) - { - std::shared_ptr tmp_entry = current; + } +.* { // contents of yyextra->current comment line + yyextra->docBlock+=yytext; + } +"\n"{BS}"!"("<"|"!"+) { // comment block (next line is also comment line) + yyextra->docBlock+="\n"; // \n is necessary for lists + newLine(yyscanner); + } +"\n" { // comment block ends at the end of this line + //cout <<"3=========> comment block : "<< yyextra->docBlock << endl; + yyextra->colNr -= 1; + unput(*yytext); + if (yyextra->vtype == V_VARIABLE) + { + std::shared_ptr tmp_entry = yyextra->current; // temporarily switch to the previous entry - if (last_enum) + if (yyextra->last_enum) { - current = last_enum; + yyextra->current = yyextra->last_enum; } else { - current = last_entry; + yyextra->current = yyextra->last_entry; } - handleCommentBlock(docBlock,TRUE); + handleCommentBlock(yyscanner,yyextra->docBlock,TRUE); // switch back - current = tmp_entry; + yyextra->current = tmp_entry; } - else if (v_type == V_PARAMETER) - { - subrHandleCommentBlock(docBlock,TRUE); + else if (yyextra->vtype == V_PARAMETER) + { + subrHandleCommentBlock(yyscanner,yyextra->docBlock,TRUE); } - else if (v_type == V_RESULT) - { - subrHandleCommentBlockResult(docBlock,TRUE); + else if (yyextra->vtype == V_RESULT) + { + subrHandleCommentBlockResult(yyscanner,yyextra->docBlock,TRUE); } - yy_pop_state(); - docBlock.resize(0); + yy_pop_state(yyscanner); + yyextra->docBlock.resize(0); } "!>" { - yy_push_state(YY_START); - current->docLine = yyLineNr; - docBlockJavaStyle = FALSE; - if (YY_START==SubprogBody) docBlockInBody = TRUE; - docBlock.resize(0); - docBlockJavaStyle = Config_getBool(JAVADOC_AUTOBRIEF); - startCommentBlock(TRUE); - BEGIN(DocBlock); + yy_push_state(YY_START,yyscanner); + yyextra->current->docLine = yyextra->lineNr; + yyextra->docBlockJavaStyle = FALSE; + if (YY_START==SubprogBody) yyextra->docBlockInBody = TRUE; + yyextra->docBlock.resize(0); + yyextra->docBlockJavaStyle = Config_getBool(JAVADOC_AUTOBRIEF); + startCommentBlock(yyscanner,TRUE); + BEGIN(DocBlock); //cout << "start DocBlock " << endl; - } - -.* { // contents of current comment line - docBlock+=yytext; - } -"\n"{BS}"!"(">"|"!"+) { // comment block (next line is also comment line) - docBlock+="\n"; // \n is necessary for lists - newLine(); - } -"\n" { // comment block ends at the end of this line - //cout <<"3=========> comment block : "<< docBlock << endl; - yyColNr -= 1; - unput(*yytext); - handleCommentBlock(docBlock,TRUE); - yy_pop_state(); - } + } + +.* { // contents of yyextra->current comment line + yyextra->docBlock+=yytext; + } +"\n"{BS}"!"(">"|"!"+) { // comment block (next line is also comment line) + yyextra->docBlock+="\n"; // \n is necessary for lists + newLine(yyscanner); + } +"\n" { // comment block ends at the end of this line + //cout <<"3=========> comment block : "<< yyextra->docBlock << endl; + yyextra->colNr -= 1; + unput(*yytext); + handleCommentBlock(yyscanner,yyextra->docBlock,TRUE); + yy_pop_state(yyscanner); + } /*-----Prototype parsing -------------------------------------------------------------------------*/ -{BS}{SUBPROG}{BS_} { - BEGIN(PrototypeSubprog); - } +{BS}{SUBPROG}{BS_} { + BEGIN(PrototypeSubprog); + } {BS}{SCOPENAME}?{BS}{ID} { - current->name = QCString(yytext).lower(); - current->name.stripWhiteSpace(); - BEGIN(PrototypeArgs); - } + yyextra->current->name = QCString(yytext).lower(); + yyextra->current->name.stripWhiteSpace(); + BEGIN(PrototypeArgs); + } { -"("|")"|","|{BS_} { current->args += yytext; } -{ID} { current->args += yytext; - Argument a; - a.name = QCString(yytext).lower(); - current->argList.push_back(a); - } +"("|")"|","|{BS_} { yyextra->current->args += yytext; } +{ID} { yyextra->current->args += yytext; + Argument a; + a.name = QCString(yytext).lower(); + yyextra->current->argList.push_back(a); + } } /*------------------------------------------------------------------------------------------------*/ <*>"\n" { - newLine(); - //if (debugStr.stripWhiteSpace().length() > 0) cout << "ignored text: " << debugStr << " state: " <debugStr.stripWhiteSpace().length() > 0) cout << "ignored text: " << yyextra->debugStr << " state: " <debugStr=""; } /*---- error: EOF in wrong state --------------------------------------------------------------------*/ <*><> { - if (parsingPrototype) { - yyterminate(); - - } else if ( include_stack_ptr <= 0 ) { - if (YY_START!=INITIAL && YY_START!=Start) { + if (yyextra->parsingPrototype) + { + yyterminate(); + } + else if ( yyextra->includeStackPtr <= 0 ) + { + if (YY_START!=INITIAL && YY_START!=Start) + { DBG_CTX((stderr,"==== Error: EOF reached in wrong state (end missing)")); - scanner_abort(); + scanner_abort(yyscanner); } yyterminate(); - } else { - popBuffer(); + } + else + { + popBuffer(yyscanner); } } <*>{LOG_OPER} { // Fortran logical comparison keywords } -<*>. { - //debugStr+=yytext; - //printf("I:%c\n", *yytext); +<*>. { + //yyextra->debugStr+=yytext; + //printf("I:%c\n", *yytext); } // ignore remaining text /**********************************************************************************/ @@ -1325,63 +1353,53 @@ private { %% //---------------------------------------------------------------------------- -#if 0 -static void extractPrefix(QCString &text) +static void newLine(yyscan_t yyscanner) { - int prefixIndex = 0; - int curIndex = 0; - bool cont = TRUE; - const char* pre[] = {"RECURSIVE","IMPURE","PURE","ELEMENTAL"}; - while(cont) - { - cont = FALSE; - for(unsigned int i=0; i<4; i++) - { - if((prefixIndex=text.find(pre[i], curIndex, FALSE))==0) - { - text.remove(0,strlen(pre[i])); - text.stripWhiteSpace(); - cont = TRUE; - } - } - } -} -#endif - -static void newLine() { - yyLineNr++; - yyLineNr+=lineCountPrepass; - lineCountPrepass=0; - comments.clear(); + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + yyextra->lineNr++; + yyextra->lineNr+=yyextra->lineCountPrepass; + yyextra->lineCountPrepass=0; + yyextra->comments.clear(); } -static CommentInPrepass* locatePrepassComment(int from, int to) { +static CommentInPrepass* locatePrepassComment(yyscan_t yyscanner,int from, int to) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; //printf("Locate %d-%d\n", from, to); - for(uint i=0; icolumn; + for (uint i=0; icomments.count(); i++) + { // todo: optimize + int c = yyextra->comments.at(i)->column; //printf("Candidate %d\n", c); - if (c>=from && c<=to) { + if (c>=from && c<=to) + { // comment for previous variable or parameter - return comments.at(i); + return yyextra->comments.at(i); } } return NULL; } -static void updateVariablePrepassComment(int from, int to) { - CommentInPrepass *c = locatePrepassComment(from, to); - if (c!=NULL && v_type == V_VARIABLE) { - last_entry->brief = c->str; - } else if (c!=NULL && v_type == V_PARAMETER) { - Argument *parameter = getParameter(argName); +static void updateVariablePrepassComment(yyscan_t yyscanner,int from, int to) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + CommentInPrepass *c = locatePrepassComment(yyscanner,from, to); + if (c!=NULL && yyextra->vtype == V_VARIABLE) + { + yyextra->last_entry->brief = c->str; + } + else if (c!=NULL && yyextra->vtype == V_PARAMETER) + { + Argument *parameter = getParameter(yyscanner,yyextra->argName); if (parameter) parameter->docs = c->str; } } static int getAmpersandAtTheStart(const char *buf, int length) { - for(int i=0; icomments int parseState = Start; char quoteSymbol = 0; int ampIndex = -1; @@ -1409,9 +1427,9 @@ static int getAmpOrExclAtTheEnd(const char *buf, int length, char ch) { // When in string, skip backslashes // Legacy code, not sure whether this is correct? - if(parseState==String) + if (parseState==String) { - if(buf[i]=='\\') i++; + if (buf[i]=='\\') i++; } switch(buf[i]) @@ -1420,13 +1438,13 @@ static int getAmpOrExclAtTheEnd(const char *buf, int length, char ch) case '"': // Close string, if quote symbol matches. // Quote symbol is set iff parseState==String - if(buf[i]==quoteSymbol) + if (buf[i]==quoteSymbol) { parseState = Start; quoteSymbol = 0; } // Start new string, if not already in string or comment - else if(parseState==Start) + else if (parseState==Start) { parseState = String; quoteSymbol = buf[i]; @@ -1435,7 +1453,7 @@ static int getAmpOrExclAtTheEnd(const char *buf, int length, char ch) break; case '!': // When in string or comment, ignore exclamation mark - if(parseState==Start) + if (parseState==Start) { parseState = Comment; commentIndex = i; @@ -1459,19 +1477,20 @@ static int getAmpOrExclAtTheEnd(const char *buf, int length, char ch) return commentIndex; } -/* Although comments at the end of continuation line are grabbed by this function, +/* Although yyextra->comments at the end of continuation line are grabbed by this function, * we still do not know how to use them later in parsing. */ -void truncatePrepass(int index) +void truncatePrepass(yyscan_t yyscanner,int index) { - int length = inputStringPrepass.length(); + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + int length = yyextra->inputStringPrepass.length(); for (int i=index+1; iinputStringPrepass[i]=='!' && iinputStringPrepass[i+1]=='<') { // save comment + struct CommentInPrepass *c=new CommentInPrepass(index, yyextra->inputStringPrepass.right(length-i-2)); + yyextra->comments.append(c); } } - inputStringPrepass.truncate(index); + yyextra->inputStringPrepass.truncate(index); } // simplified way to know if this is fixed form @@ -1502,16 +1521,16 @@ bool recognizeFixedForm(const char* contents, FortranFormat format) case 'C': case 'c': case '*': - if(column==1) return TRUE; - if(skipLine) break; + if (column==1) return TRUE; + if (skipLine) break; return FALSE; case '!': - if(column>1 && column<7) return FALSE; + if (column>1 && column<7) return FALSE; skipLine=TRUE; break; default: - if(skipLine) break; - if(column==7) return TRUE; + if (skipLine) break; + if (column==7) return TRUE; return FALSE; } } @@ -1528,7 +1547,7 @@ static void insertCharacter(char *contents, int length, int pos, char c) contents[pos] = c; } -/* change comments and bring line continuation character to previous line */ +/* change yyextra->comments and bring line continuation character to previous line */ /* also used to set continuation marks in case of fortran code usage, done here as it is quite complicated code */ const char* prepassFixedForm(const char* contents, int *hasContLine) { @@ -1574,7 +1593,7 @@ const char* prepassFixedForm(const char* contents, int *hasContLine) } j++; - if(j>=newContentsSize-3) { // check for spare characters, which may be eventually used below (by & and '! ') + if (j>=newContentsSize-3) { // check for spare characters, which may be eventually used below (by & and '! ') newContents = (char*)realloc(newContents, newContentsSize+1000); newContentsSize = newContentsSize+1000; } @@ -1605,7 +1624,7 @@ const char* prepassFixedForm(const char* contents, int *hasContLine) spaces=TRUE; fullCommentLine=TRUE; column=0; - emptyLabel=TRUE; + emptyLabel=TRUE; commented=FALSE; newContents[j]=c; prevQuote = thisQuote; @@ -1635,10 +1654,10 @@ const char* prepassFixedForm(const char* contents, int *hasContLine) case '\'': case '\\': if ((column <= fixedCommentAfter) && (column!=6) && !commented) - { + { // we have some special cases in respect to strings and escaped string characters fullCommentLine=FALSE; - newContents[j]=c; + newContents[j]=c; if (c == '\\') { inBackslash = !inBackslash; @@ -1673,71 +1692,89 @@ const char* prepassFixedForm(const char* contents, int *hasContLine) case '*': case '!': if ((column <= fixedCommentAfter) && (column!=6)) - { - emptyLabel=FALSE; - if(column==1) + { + emptyLabel=FALSE; + if (column==1) { - newContents[j]='!'; + newContents[j]='!'; commented = TRUE; } - else if ((c == '!') && !inDouble && !inSingle) + else if ((c == '!') && !inDouble && !inSingle) { - newContents[j]=c; + newContents[j]=c; commented = TRUE; } - else + else { if (!commented) fullCommentLine=FALSE; - newContents[j]=c; + newContents[j]=c; } - break; - } + break; + } // fallthrough default: - if (!commented && (column < 6) && ((c - '0') >= 0) && ((c - '0') <= 9)) { // remove numbers, i.e. labels from first 5 positions. + if (!commented && (column < 6) && ((c - '0') >= 0) && ((c - '0') <= 9)) + { // remove numbers, i.e. labels from first 5 positions. newContents[j]=' '; } - else if(column==6 && emptyLabel) { // continuation + else if (column==6 && emptyLabel) + { // continuation if (!commented) fullCommentLine=FALSE; - if (c != '0') { // 0 not allowed as continuation character, see f95 standard paragraph 3.3.2.3 + if (c != '0') + { // 0 not allowed as continuation character, see f95 standard paragraph 3.3.2.3 newContents[j]=' '; - if(prevLineAmpOrExclIndex==-1) { // add & just before end of previous line + if (prevLineAmpOrExclIndex==-1) + { // add & just before end of previous line /* first line is not a continuation line in code, just in snippets etc. */ if (curLine != 1) insertCharacter(newContents, j+1, (j+1)-6-1, '&'); j++; - } else { // add & just before end of previous line comment + } + else + { // add & just before end of previous line comment /* first line is not a continuation line in code, just in snippets etc. */ if (curLine != 1) insertCharacter(newContents, j+1, (j+1)-6-prevLineLength+prevLineAmpOrExclIndex+skipped, '&'); skipped = 0; j++; } - if (hasContLine) hasContLine[curLine - 1] = 1; - } else { - newContents[j]=c; // , just handle like space + if (hasContLine) + { + hasContLine[curLine - 1] = 1; + } + } + else + { + newContents[j]=c; // , just handle like space } prevLineLength=0; - } else if ((column > fixedCommentAfter) && !commented) { + } + else if ((column > fixedCommentAfter) && !commented) + { // first non commented non blank character after position fixedCommentAfter - if (c == '&') { - newContents[j]=' '; + if (c == '&') + { + newContents[j]=' '; } - else if (c != '!') { + else if (c != '!') + { // I'm not a possible start of doxygen comment - newContents[j]=' '; + newContents[j]=' '; artificialComment = TRUE; spaces=TRUE; skipped = 0; } - else { - newContents[j]=c; + else + { + newContents[j]=c; commented = TRUE; } - } else { + } + else + { if (!commented) fullCommentLine=FALSE; - newContents[j]=c; - emptyLabel=FALSE; - } + newContents[j]=c; + emptyLabel=FALSE; + } break; } } @@ -1758,25 +1795,28 @@ const char* prepassFixedForm(const char* contents, int *hasContLine) return newContents; } -static void pushBuffer(QCString& buffer) +static void pushBuffer(yyscan_t yyscanner,QCString& buffer) { - if (include_stack_cnt <= include_stack_ptr) + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + if (yyextra->includeStackCnt <= yyextra->includeStackPtr) { - include_stack_cnt++; - include_stack = (YY_BUFFER_STATE *)realloc(include_stack, include_stack_cnt * sizeof(YY_BUFFER_STATE)); + yyextra->includeStackCnt++; + yyextra->includeStack = (YY_BUFFER_STATE *)realloc(yyextra->includeStack, yyextra->includeStackCnt * sizeof(YY_BUFFER_STATE)); } - include_stack[include_stack_ptr++] = YY_CURRENT_BUFFER; - yy_switch_to_buffer(yy_scan_string(buffer)); + yyextra->includeStack[yyextra->includeStackPtr++] = YY_CURRENT_BUFFER; + yy_switch_to_buffer(yy_scan_string(buffer,yyscanner),yyscanner); DBG_CTX((stderr, "--PUSH--%s", (const char *)buffer)); buffer = NULL; } -static void popBuffer() { +static void popBuffer(yyscan_t yyscanner) +{ + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; DBG_CTX((stderr, "--POP--")); - include_stack_ptr --; - yy_delete_buffer( YY_CURRENT_BUFFER ); - yy_switch_to_buffer( include_stack[include_stack_ptr] ); + yyextra->includeStackPtr --; + yy_delete_buffer( YY_CURRENT_BUFFER, yyscanner ); + yy_switch_to_buffer( yyextra->includeStack[yyextra->includeStackPtr], yyscanner ); } /** used to copy entry to an interface module procedure */ @@ -1797,9 +1837,10 @@ static void copyEntry(std::shared_ptr dest, const std::shared_ptr corresponding module subprogs @TODO: handle procedures in used modules */ -void resolveModuleProcedures(Entry *current_root) +void resolveModuleProcedures(yyscan_t yyscanner,Entry *current_root) { - for (const auto &ce1 : moduleProcedures) + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + for (const auto &ce1 : yyextra->moduleProcedures) { // check all entries in this module for (const auto &ce2 : current_root->children()) @@ -1808,19 +1849,10 @@ void resolveModuleProcedures(Entry *current_root) { copyEntry(ce1, ce2); } - } // for procedures in current module + } // for procedures in yyextra->current module } // for all interface module procedures - moduleProcedures.clear(); -} - -#if 0 -static bool isTypeName(QCString name) -{ - name = name.lower(); - return name=="integer" || name == "real" || - name=="complex" || name == "logical"; + yyextra->moduleProcedures.clear(); } -#endif /*! Extracts string which resides within parentheses of provided string. */ static QCString extractFromParens(const QCString name) @@ -1865,7 +1897,7 @@ static QCString extractBind(const QCString name) } } -/*! Adds passed modifiers to these modifiers.*/ +/*! Adds passed yyextra->modifiers to these yyextra->modifiers.*/ SymbolModifiers& SymbolModifiers::operator|=(const SymbolModifiers &mdfs) { if (mdfs.protection!=NONE_P) protection = mdfs.protection; @@ -1892,7 +1924,7 @@ SymbolModifiers& SymbolModifiers::operator|=(const SymbolModifiers &mdfs) return *this; } -/*! Extracts and adds passed modifier to these modifiers.*/ +/*! Extracts and adds passed modifier to these yyextra->modifiers.*/ SymbolModifiers& SymbolModifiers::operator|=(QCString mdfStringArg) { QCString mdfString = mdfStringArg.lower(); @@ -2014,7 +2046,7 @@ static Argument *findArgument(Entry* subprog, QCString name, bool byTypeName = F for (Argument &arg : subprog->argList) { if ((!byTypeName && arg.name.lower() == cname) || - (byTypeName && arg.type.lower() == cname) + (byTypeName && arg.type.lower() == cname) ) { return &arg; @@ -2024,7 +2056,7 @@ static Argument *findArgument(Entry* subprog, QCString name, bool byTypeName = F } -/*! Apply modifiers stored in \a mdfs to the \a typeName string. */ +/*! Apply yyextra->modifiers stored in \a mdfs to the \a typeName string. */ static QCString applyModifiers(QCString typeName, SymbolModifiers& mdfs) { if (!mdfs.dimension.isNull()) @@ -2141,14 +2173,14 @@ static QCString applyModifiers(QCString typeName, SymbolModifiers& mdfs) return typeName; } -/*! Apply modifiers stored in \a mdfs to the \a arg argument. */ +/*! Apply yyextra->modifiers stored in \a mdfs to the \a arg argument. */ static void applyModifiers(Argument *arg, SymbolModifiers& mdfs) { QCString tmp = arg->type; arg->type = applyModifiers(tmp, mdfs); } -/*! Apply modifiers stored in \a mdfs to the \a ent entry. */ +/*! Apply yyextra->modifiers stored in \a mdfs to the \a ent entry. */ static void applyModifiers(Entry *ent, SymbolModifiers& mdfs) { QCString tmp = ent->type; @@ -2164,47 +2196,49 @@ static void applyModifiers(Entry *ent, SymbolModifiers& mdfs) * starting module, interface, function or other program block. * \see endScope() */ -static void startScope(Entry *scope) +static void startScope(yyscan_t yyscanner,Entry *scope) { + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; //cout<<"start scope: "<name<current_root= scope; /* start substructure */ QMap mdfMap; - modifiers.insert(scope, mdfMap); + yyextra->modifiers.insert(scope, mdfMap); } /*! Ends scope in fortran program: may update subprogram arguments or module variable attributes. * \see startScope() */ -static bool endScope(Entry *scope, bool isGlobalRoot) +static bool endScope(yyscan_t yyscanner,Entry *scope, bool isGlobalRoot) { - if (global_scope == scope) + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + if (yyextra->global_scope == scope) { - global_scope = 0; + yyextra->global_scope = 0; return TRUE; } - if (global_scope == INVALID_ENTRY) + if (yyextra->global_scope == INVALID_ENTRY) { return TRUE; } //cout<<"end scope: "<name<parent() || isGlobalRoot) + if (yyextra->current_root->parent() || isGlobalRoot) { - current_root= current_root->parent(); /* end substructure */ + yyextra->current_root= yyextra->current_root->parent(); /* end substructure */ } - else // if (current_root != scope) + else // if (yyextra->current_root != scope) { fprintf(stderr,"parse error in end \n"); - scanner_abort(); + scanner_abort(yyscanner); return FALSE; } - // update variables or subprogram arguments with modifiers - QMap& mdfsMap = modifiers[scope]; + // update variables or subprogram arguments with yyextra->modifiers + QMap& mdfsMap = yyextra->modifiers[scope]; if (scope->section == Entry::FUNCTION_SEC) { - // iterate all symbol modifiers of the scope + // iterate all symbol yyextra->modifiers of the scope for (QMap::Iterator it=mdfsMap.begin(); it!=mdfsMap.end(); it++) { //cout<name.lower()].returnName<name.lower()].returnName.lower(); - if (modifiers[scope].contains(returnName)) + //cout<<"RETURN NAME "<modifiers[yyextra->current_root][scope->name.lower()].returnName<modifiers[yyextra->current_root][scope->name.lower()].returnName.lower(); + if (yyextra->modifiers[scope].contains(returnName)) { - scope->type = modifiers[scope][returnName].type; // returning type works - applyModifiers(scope, modifiers[scope][returnName]); // returning array works + scope->type = yyextra->modifiers[scope][returnName].type; // returning type works + applyModifiers(scope, yyextra->modifiers[scope][returnName]); // returning array works } } @@ -2243,17 +2277,17 @@ static bool endScope(Entry *scope, bool isGlobalRoot) Argument *arg = findArgument(scope->parent(), ce->name, TRUE); if (arg != 0) - { + { // set type of dummy procedure argument to interface - arg->name = arg->type; + arg->name = arg->type; arg->type = scope->name; } if (ce->name.lower() == scope->name.lower()) found = TRUE; } if ((count == 1) && found) { - // clear all modifiers of the scope - modifiers.remove(scope); + // clear all yyextra->modifiers of the scope + yyextra->modifiers.remove(scope); scope->parent()->removeSubEntry(scope); scope = 0; return TRUE; @@ -2262,7 +2296,7 @@ static bool endScope(Entry *scope, bool isGlobalRoot) } if (scope->section!=Entry::FUNCTION_SEC) { // not function section - // iterate variables: get and apply modifiers + // iterate variables: get and apply yyextra->modifiers for (const auto &ce : scope->children()) { if (ce->section != Entry::VARIABLE_SEC && ce->section != Entry::FUNCTION_SEC) @@ -2274,165 +2308,156 @@ static bool endScope(Entry *scope, bool isGlobalRoot) } } - // clear all modifiers of the scope - modifiers.remove(scope); + // clear all yyextra->modifiers of the scope + yyextra->modifiers.remove(scope); return TRUE; } -#if 0 -//! Return full name of the entry. Sometimes we must combine several names recursively. -static QCString getFullName(Entry *e) -{ - QCString name = e->name; - if (e->section == Entry::CLASS_SEC // || e->section == Entry::INTERFACE_SEC - || !e->parent() || e->parent()->name.isEmpty()) - return name; - - return getFullName(e->parent())+"::"+name; -} -#endif - -static int yyread(char *buf,int max_size) +static int yyread(yyscan_t yyscanner,char *buf,int max_size) { + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; int c=0; - - while ( c < max_size && inputString[inputPosition] ) + while ( c < max_size && yyextra->inputString[yyextra->inputPosition] ) { - *buf = inputString[inputPosition++] ; + *buf = yyextra->inputString[yyextra->inputPosition++] ; c++; buf++; } return c; } -static void initParser() +static void initParser(yyscan_t yyscanner) { - last_entry.reset(); + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + yyextra->last_entry.reset(); } -static void initEntry() +static void initEntry(yyscan_t yyscanner) { - if (typeMode) + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + if (yyextra->typeMode) { - current->protection = typeProtection; + yyextra->current->protection = yyextra->typeProtection; } else { - current->protection = defaultProtection; + yyextra->current->protection = yyextra->defaultProtection; } - current->mtype = mtype; - current->virt = virt; - current->stat = gstat; - current->lang = SrcLangExt_Fortran; - Doxygen::docGroup.initGroupInfo(current.get()); + yyextra->current->mtype = Method; + yyextra->current->virt = Normal; + yyextra->current->stat = FALSE; + yyextra->current->lang = SrcLangExt_Fortran; + Doxygen::docGroup.initGroupInfo(yyextra->current.get()); } /** - adds current entry to current_root and creates new current + adds yyextra->current entry to yyextra->current_root and creates new yyextra->current */ -static void addCurrentEntry(bool case_insens) +static void addCurrentEntry(yyscan_t yyscanner,bool case_insens) { - if (case_insens) current->name = current->name.lower(); - //printf("===Adding entry %s to %s\n", current->name.data(), current_root->name.data()); - last_entry = current; - current_root->moveToSubEntryAndRefresh(current); - initEntry(); + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + if (case_insens) yyextra->current->name = yyextra->current->name.lower(); + //printf("===Adding entry %s to %s\n", yyextra->current->name.data(), yyextra->current_root->name.data()); + yyextra->last_entry = yyextra->current; + yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current); + initEntry(yyscanner); } -static int max(int a, int b) {return a>b?a:b;} - -static void addModule(const char *name, bool isModule) +static void addModule(yyscan_t yyscanner,const char *name, bool isModule) { + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; DBG_CTX((stderr, "0=========> got module %s\n", name)); if (isModule) - current->section = Entry::NAMESPACE_SEC; + yyextra->current->section = Entry::NAMESPACE_SEC; else - current->section = Entry::FUNCTION_SEC; + yyextra->current->section = Entry::FUNCTION_SEC; if (name!=NULL) { - current->name = name; + yyextra->current->name = name; } else { - QCString fname = yyFileName; - int index = max(fname.findRev('/'), fname.findRev('\\')); + QCString fname = yyextra->fileName; + int index = QMAX(fname.findRev('/'), fname.findRev('\\')); fname = fname.right(fname.length()-index-1); fname = fname.prepend("__").append("__"); - current->name = fname; - } - current->type = "program"; - current->fileName = yyFileName; - current->bodyLine = yyLineNr; // used for source reference - current->startLine = yyLineNr; - current->protection = Public ; - addCurrentEntry(true); - startScope(last_entry.get()); + yyextra->current->name = fname; + } + yyextra->current->type = "program"; + yyextra->current->fileName = yyextra->fileName; + yyextra->current->bodyLine = yyextra->lineNr; // used for source reference + yyextra->current->startLine = yyextra->lineNr; + yyextra->current->protection = Public ; + addCurrentEntry(yyscanner,true); + startScope(yyscanner,yyextra->last_entry.get()); } -static void addSubprogram(const char *text) +static void addSubprogram(yyscan_t yyscanner,const char *text) { + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; DBG_CTX((stderr,"1=========> got subprog, type: %s\n",text)); - subrCurrent.push_back(current); - current->section = Entry::FUNCTION_SEC ; + yyextra->subrCurrent.push_back(yyextra->current); + yyextra->current->section = Entry::FUNCTION_SEC ; QCString subtype = text; subtype=subtype.lower().stripWhiteSpace(); - functionLine = (subtype.find("function") != -1); - current->type += " " + subtype; - current->type = current->type.stripWhiteSpace(); - current->fileName = yyFileName; - current->bodyLine = yyLineNr; // used for source reference start of body of routine - current->startLine = yyLineNr; // used for source reference start of definition - current->args.resize(0); - current->argList.clear(); - docBlock.resize(0); + yyextra->functionLine = (subtype.find("function") != -1); + yyextra->current->type += " " + subtype; + yyextra->current->type = yyextra->current->type.stripWhiteSpace(); + yyextra->current->fileName = yyextra->fileName; + yyextra->current->bodyLine = yyextra->lineNr; // used for source reference start of body of routine + yyextra->current->startLine = yyextra->lineNr; // used for source reference start of definition + yyextra->current->args.resize(0); + yyextra->current->argList.clear(); + yyextra->docBlock.resize(0); } /*! Adds interface to the root entry. * \note Code was brought to this procedure from the parser, * because there was/is idea to use it in several parts of the parser. */ -static void addInterface(QCString name, InterfaceType type) +static void addInterface(yyscan_t yyscanner,QCString name, InterfaceType type) { + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; if (YY_START == Start) { - addModule(NULL); - yy_push_state(ModuleBody); //anon program + addModule(yyscanner,NULL); + yy_push_state(ModuleBody,yyscanner); //anon program } - current->section = Entry::CLASS_SEC; // was Entry::INTERFACE_SEC; - current->spec = Entry::Interface; - current->name = name; + yyextra->current->section = Entry::CLASS_SEC; // was Entry::INTERFACE_SEC; + yyextra->current->spec = Entry::Interface; + yyextra->current->name = name; switch (type) { case IF_ABSTRACT: - current->type = "abstract"; + yyextra->current->type = "abstract"; break; case IF_GENERIC: - current->type = "generic"; + yyextra->current->type = "generic"; break; case IF_SPECIFIC: case IF_NONE: default: - current->type = ""; + yyextra->current->type = ""; } /* if type is part of a module, mod name is necessary for output */ - if ((current_root) && - (current_root->section == Entry::CLASS_SEC || - current_root->section == Entry::NAMESPACE_SEC)) + if ((yyextra->current_root) && + (yyextra->current_root->section == Entry::CLASS_SEC || + yyextra->current_root->section == Entry::NAMESPACE_SEC)) { - current->name= current_root->name + "::" + current->name; + yyextra->current->name= yyextra->current_root->name + "::" + yyextra->current->name; } - current->fileName = yyFileName; - current->bodyLine = yyLineNr; - current->startLine = yyLineNr; - addCurrentEntry(true); + yyextra->current->fileName = yyextra->fileName; + yyextra->current->bodyLine = yyextra->lineNr; + yyextra->current->startLine = yyextra->lineNr; + addCurrentEntry(yyscanner,true); } @@ -2440,11 +2465,12 @@ static void addInterface(QCString name, InterfaceType type) /*! Get the argument \a name. */ -static Argument *getParameter(const QCString &name) +static Argument *getParameter(yyscan_t yyscanner,const QCString &name) { + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; // std::cout<<"addFortranParameter(): "<argList) + for (Argument &a:yyextra->current_root->argList) { if (a.name.lower()==name.lower()) { @@ -2457,70 +2483,73 @@ static Argument *getParameter(const QCString &name) } //---------------------------------------------------------------------------- -static void startCommentBlock(bool brief) +static void startCommentBlock(yyscan_t yyscanner,bool brief) { + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; if (brief) { - current->briefFile = yyFileName; - current->briefLine = yyLineNr; + yyextra->current->briefFile = yyextra->fileName; + yyextra->current->briefLine = yyextra->lineNr; } else { - current->docFile = yyFileName; - current->docLine = yyLineNr; + yyextra->current->docFile = yyextra->fileName; + yyextra->current->docLine = yyextra->lineNr; } } //---------------------------------------------------------------------------- -static void handleCommentBlock(const QCString &doc,bool brief) +static void handleCommentBlock(yyscan_t yyscanner,const QCString &doc,bool brief) { - static bool hideInBodyDocs = Config_getBool(HIDE_IN_BODY_DOCS); - if (docBlockInBody && hideInBodyDocs) + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + bool hideInBodyDocs = Config_getBool(HIDE_IN_BODY_DOCS); + if (yyextra->docBlockInBody && hideInBodyDocs) { - docBlockInBody = FALSE; + yyextra->docBlockInBody = FALSE; return; } DBG_CTX((stderr,"call parseCommentBlock [%s]\n",doc.data())); - int lineNr = brief ? current->briefLine : current->docLine; + int lineNr = brief ? yyextra->current->briefLine : yyextra->current->docLine; int position=0; bool needsEntry = FALSE; - QCString processedDoc = processMarkdownForCommentBlock(doc,yyFileName,lineNr); - while (g_commentScanner.parseCommentBlock( - g_thisParser, - docBlockInBody ? subrCurrent.back().get() : current.get(), - processedDoc, // text - yyFileName, // file - lineNr, - docBlockInBody ? FALSE : brief, - docBlockInBody ? FALSE : docBlockJavaStyle, - docBlockInBody, - defaultProtection, + QCString processedDoc = processMarkdownForCommentBlock(doc,yyextra->fileName,lineNr); + while (yyextra->commentScanner.parseCommentBlock( + yyextra->thisParser, + yyextra->docBlockInBody ? yyextra->subrCurrent.back().get() : yyextra->current.get(), + processedDoc, // text + yyextra->fileName, // file + lineNr, + yyextra->docBlockInBody ? FALSE : brief, + yyextra->docBlockInBody ? FALSE : yyextra->docBlockJavaStyle, + yyextra->docBlockInBody, + yyextra->defaultProtection, position, needsEntry )) { - DBG_CTX((stderr,"parseCommentBlock position=%d [%s] needsEntry=%d\n",position,doc.data()+position,needsEntry)); - if (needsEntry) addCurrentEntry(false); + DBG_CTX((stderr,"parseCommentBlock position=%d [%s] needsEntry=%d\n",position,doc.data()+position,needsEntry)); + if (needsEntry) addCurrentEntry(yyscanner,false); } DBG_CTX((stderr,"parseCommentBlock position=%d [%s] needsEntry=%d\n",position,doc.data()+position,needsEntry)); - if (needsEntry) addCurrentEntry(false); - docBlockInBody = FALSE; + if (needsEntry) addCurrentEntry(yyscanner,false); + yyextra->docBlockInBody = FALSE; } //---------------------------------------------------------------------------- /// Handle parameter description as defined after the declaration of the parameter -static void subrHandleCommentBlock(const QCString &doc,bool brief) +static void subrHandleCommentBlock(yyscan_t yyscanner,const QCString &doc,bool brief) { + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; QCString loc_doc; loc_doc = doc.stripWhiteSpace(); - std::shared_ptr tmp_entry = current; - current = subrCurrent.back(); // temporarily switch to the entry of the subroutine / function + std::shared_ptr tmp_entry = yyextra->current; + yyextra->current = yyextra->subrCurrent.back(); // temporarily switch to the entry of the subroutine / function // Still in the specification section so no inbodyDocs yet, but parameter documentation - current->inbodyDocs = ""; + yyextra->current->inbodyDocs = ""; // strip \\param or @param, so we can do some extra checking. We will add it later on again. if (!loc_doc.stripPrefix("\\param") && @@ -2529,7 +2558,7 @@ static void subrHandleCommentBlock(const QCString &doc,bool brief) loc_doc.stripWhiteSpace(); // direction as defined with the declaration of the parameter - int dir1 = modifiers[current_root][argName.lower()].direction; + int dir1 = yyextra->modifiers[yyextra->current_root][yyextra->argName.lower()].direction; // in description [in] is specified if (loc_doc.lower().find(directionParam[SymbolModifiers::IN]) == 0) { @@ -2541,19 +2570,19 @@ static void subrHandleCommentBlock(const QCString &doc,bool brief) loc_doc = loc_doc.right(loc_doc.length()-strlen(directionParam[SymbolModifiers::IN])); loc_doc.stripWhiteSpace(); // in case of empty documentation or (now) just name, consider it as no documentation - if (!loc_doc.isEmpty() && (loc_doc.lower() != argName.lower())) + if (!loc_doc.isEmpty() && (loc_doc.lower() != yyextra->argName.lower())) { - handleCommentBlock(QCString("\n\n@param ") + directionParam[SymbolModifiers::IN] + " " + - argName + " " + loc_doc,brief); + handleCommentBlock(yyscanner,QCString("\n\n@param ") + directionParam[SymbolModifiers::IN] + " " + + yyextra->argName + " " + loc_doc,brief); } } else { // something different specified, give warning and leave error. - warn(yyFileName,yyLineNr, "Routine: " + current->name + current->args + - " inconsistency between intent attribute and documentation for parameter: " + argName); - handleCommentBlock(QCString("\n\n@param ") + directionParam[dir1] + " " + - argName + " " + loc_doc,brief); + warn(yyextra->fileName,yyextra->lineNr, "Routine: " + yyextra->current->name + yyextra->current->args + + " inconsistency between intent attribute and documentation for parameter: " + yyextra->argName); + handleCommentBlock(yyscanner,QCString("\n\n@param ") + directionParam[dir1] + " " + + yyextra->argName + " " + loc_doc,brief); } } // analogous to the [in] case, here [out] direction specified @@ -2564,20 +2593,20 @@ static void subrHandleCommentBlock(const QCString &doc,bool brief) { loc_doc = loc_doc.right(loc_doc.length()-strlen(directionParam[SymbolModifiers::OUT])); loc_doc.stripWhiteSpace(); - if (loc_doc.isEmpty() || (loc_doc.lower() == argName.lower())) + if (loc_doc.isEmpty() || (loc_doc.lower() == yyextra->argName.lower())) { - current = tmp_entry; + yyextra->current = tmp_entry; return; } - handleCommentBlock(QCString("\n\n@param ") + directionParam[SymbolModifiers::OUT] + " " + - argName + " " + loc_doc,brief); + handleCommentBlock(yyscanner,QCString("\n\n@param ") + directionParam[SymbolModifiers::OUT] + " " + + yyextra->argName + " " + loc_doc,brief); } else { - warn(yyFileName,yyLineNr, "Routine: " + current->name + current->args + - " inconsistency between intent attribute and documentation for parameter: " + argName); - handleCommentBlock(QCString("\n\n@param ") + directionParam[dir1] + " " + - argName + " " + loc_doc,brief); + warn(yyextra->fileName,yyextra->lineNr, "Routine: " + yyextra->current->name + yyextra->current->args + + " inconsistency between intent attribute and documentation for parameter: " + yyextra->argName); + handleCommentBlock(yyscanner,QCString("\n\n@param ") + directionParam[dir1] + " " + + yyextra->argName + " " + loc_doc,brief); } } // analogous to the [in] case, here [in,out] direction specified @@ -2588,42 +2617,43 @@ static void subrHandleCommentBlock(const QCString &doc,bool brief) { loc_doc = loc_doc.right(loc_doc.length()-strlen(directionParam[SymbolModifiers::INOUT])); loc_doc.stripWhiteSpace(); - if (!loc_doc.isEmpty() && (loc_doc.lower() != argName.lower())) + if (!loc_doc.isEmpty() && (loc_doc.lower() != yyextra->argName.lower())) { - handleCommentBlock(QCString("\n\n@param ") + directionParam[SymbolModifiers::INOUT] + " " + - argName + " " + loc_doc,brief); + handleCommentBlock(yyscanner,QCString("\n\n@param ") + directionParam[SymbolModifiers::INOUT] + " " + + yyextra->argName + " " + loc_doc,brief); } } else { - warn(yyFileName,yyLineNr, "Routine: " + current->name + current->args + - " inconsistency between intent attribute and documentation for parameter: " + argName); - handleCommentBlock(QCString("\n\n@param ") + directionParam[dir1] + " " + - argName + " " + loc_doc,brief); + warn(yyextra->fileName,yyextra->lineNr, "Routine: " + yyextra->current->name + yyextra->current->args + + " inconsistency between intent attribute and documentation for parameter: " + yyextra->argName); + handleCommentBlock(yyscanner,QCString("\n\n@param ") + directionParam[dir1] + " " + + yyextra->argName + " " + loc_doc,brief); } } // analogous to the [in] case; here no direction specified - else if (!loc_doc.isEmpty() && (loc_doc.lower() != argName.lower())) + else if (!loc_doc.isEmpty() && (loc_doc.lower() != yyextra->argName.lower())) { - handleCommentBlock(QCString("\n\n@param ") + directionParam[dir1] + " " + - argName + " " + loc_doc,brief); + handleCommentBlock(yyscanner,QCString("\n\n@param ") + directionParam[dir1] + " " + + yyextra->argName + " " + loc_doc,brief); } - // reset current back to the part inside the routine - current = tmp_entry; + // reset yyextra->current back to the part inside the routine + yyextra->current = tmp_entry; } //---------------------------------------------------------------------------- /// Handle result description as defined after the declaration of the parameter -static void subrHandleCommentBlockResult(const QCString &doc,bool brief) +static void subrHandleCommentBlockResult(yyscan_t yyscanner,const QCString &doc,bool brief) { + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; QCString loc_doc; loc_doc = doc.stripWhiteSpace(); - std::shared_ptr tmp_entry = current; - current = subrCurrent.back(); // temporarily switch to the entry of the subroutine / function + std::shared_ptr tmp_entry = yyextra->current; + yyextra->current = yyextra->subrCurrent.back(); // temporarily switch to the entry of the subroutine / function // Still in the specification section so no inbodyDocs yet, but parameter documentation - current->inbodyDocs = ""; + yyextra->current->inbodyDocs = ""; // strip \\returns or @returns. We will add it later on again. if (!loc_doc.stripPrefix("\\returns") && @@ -2633,140 +2663,152 @@ static void subrHandleCommentBlockResult(const QCString &doc,bool brief) ) (void)loc_doc; // Do nothing work has been done by stripPrefix; (void)loc_doc: to overcome 'empty controlled statement' warning loc_doc.stripWhiteSpace(); - if (!loc_doc.isEmpty() && (loc_doc.lower() != argName.lower())) + if (!loc_doc.isEmpty() && (loc_doc.lower() != yyextra->argName.lower())) { - handleCommentBlock(QCString("\n\n@returns ") + loc_doc,brief); + handleCommentBlock(yyscanner,QCString("\n\n@returns ") + loc_doc,brief); } - // reset current back to the part inside the routine - current = tmp_entry; + // reset yyextra->current back to the part inside the routine + yyextra->current = tmp_entry; } //---------------------------------------------------------------------------- -#if 0 -static int level=0; -static void debugCompounds(Entry *rt) // print Entry structure (for debugging) +static void parseMain(yyscan_t yyscanner, const char *fileName,const char *fileBuf, + const std::shared_ptr &rt, FortranFormat format) { - level++; - printf("%d) debugCompounds(%s) line %d\n",level, rt->name.data(), rt->bodyLine); - for (const auto &ce : rt->children()) + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; + char *tmpBuf = NULL; + initParser(yyscanner); + + yyextra->defaultProtection = Public; + yyextra->inputString = fileBuf; + yyextra->inputPosition = 0; + yyextra->inputStringPrepass = NULL; + yyextra->inputPositionPrepass = 0; + + //yyextra->anonCount = 0; // don't reset per file + yyextra->current_root = rt.get(); + yyextra->global_root = rt; + + yyextra->isFixedForm = recognizeFixedForm(fileBuf,format); + + if (yyextra->isFixedForm) + { + msg("Prepassing fixed form of %s\n", fileName); + //printf("---strlen=%d\n", strlen(fileBuf)); + //clock_t start=clock(); + + //printf("Input fixed form string:\n%s\n", fileBuf); + //printf("===========================\n"); + yyextra->inputString = prepassFixedForm(fileBuf, NULL); + Debug::print(Debug::FortranFixed2Free,0,"======== Fixed to Free format =========\n---- Input fixed form string ------- \n%s\n", fileBuf); + Debug::print(Debug::FortranFixed2Free,0,"---- Resulting free form string ------- \n%s\n", yyextra->inputString); + //printf("Resulting free form string:\n%s\n", yyextra->inputString); + //printf("===========================\n"); + + //clock_t end=clock(); + //printf("CPU time used=%f\n", ((double) (end-start))/CLOCKS_PER_SEC); + } + else if (yyextra->inputString[strlen(fileBuf)-1] != '\n') { - debugCompounds(ce.get()); + tmpBuf = (char *)malloc(strlen(fileBuf)+2); + strcpy(tmpBuf,fileBuf); + tmpBuf[strlen(fileBuf)]= '\n'; + tmpBuf[strlen(fileBuf)+1]= '\000'; + yyextra->inputString = tmpBuf; } -level--; -} -#endif + yyextra->lineNr= 1 ; + yyextra->fileName = fileName; + msg("Parsing file %s...\n",yyextra->fileName.data()); -static void parseMain(const char *fileName,const char *fileBuf, - const std::shared_ptr &rt, FortranFormat format) -{ - char *tmpBuf = NULL; - initParser(); - - defaultProtection = Public; - inputString = fileBuf; - inputPosition = 0; - inputStringPrepass = NULL; - inputPositionPrepass = 0; - - //anonCount = 0; // don't reset per file - mtype = Method; - gstat = FALSE; - virt = Normal; - current_root = rt.get(); - global_root = rt; - inputFile.setName(fileName); - if (inputFile.open(IO_ReadOnly)) - { - isFixedForm = recognizeFixedForm(fileBuf,format); - - if (isFixedForm) - { - msg("Prepassing fixed form of %s\n", fileName); - //printf("---strlen=%d\n", strlen(fileBuf)); - //clock_t start=clock(); - - //printf("Input fixed form string:\n%s\n", fileBuf); - //printf("===========================\n"); - inputString = prepassFixedForm(fileBuf, NULL); - Debug::print(Debug::FortranFixed2Free,0,"======== Fixed to Free format =========\n---- Input fixed form string ------- \n%s\n", fileBuf); - Debug::print(Debug::FortranFixed2Free,0,"---- Resulting free form string ------- \n%s\n", inputString); - //printf("Resulting free form string:\n%s\n", inputString); - //printf("===========================\n"); - - //clock_t end=clock(); - //printf("CPU time used=%f\n", ((double) (end-start))/CLOCKS_PER_SEC); - } - else if (inputString[strlen(fileBuf)-1] != '\n') - { - tmpBuf = (char *)malloc(strlen(fileBuf)+2); - strcpy(tmpBuf,fileBuf); - tmpBuf[strlen(fileBuf)]= '\n'; - tmpBuf[strlen(fileBuf)+1]= '\000'; - inputString = tmpBuf; - } + yyextra->global_scope = rt.get(); + startScope(yyscanner,rt.get()); // implies yyextra->current_root = rt + initParser(yyscanner); + Doxygen::docGroup.enterFile(yyextra->fileName,yyextra->lineNr); - yyLineNr= 1 ; - yyFileName = fileName; - msg("Parsing file %s...\n",yyFileName.data()); - - global_scope = rt.get(); - startScope(rt.get()); // implies current_root = rt - initParser(); - Doxygen::docGroup.enterFile(yyFileName,yyLineNr); - - // add entry for the file - current = std::make_shared(); - current->lang = SrcLangExt_Fortran; - current->name = yyFileName; - current->section = Entry::SOURCE_SEC; - file_root = current; - current_root->moveToSubEntryAndRefresh(current); - current->lang = SrcLangExt_Fortran; - - fortranscannerYYrestart( fortranscannerYYin ); - { - BEGIN( Start ); - } + // add entry for the file + yyextra->current = std::make_shared(); + yyextra->current->lang = SrcLangExt_Fortran; + yyextra->current->name = yyextra->fileName; + yyextra->current->section = Entry::SOURCE_SEC; + yyextra->file_root = yyextra->current; + yyextra->current_root->moveToSubEntryAndRefresh(yyextra->current); + yyextra->current->lang = SrcLangExt_Fortran; - fortranscannerYYlex(); - Doxygen::docGroup.leaveFile(yyFileName,yyLineNr); + fortranscannerYYrestart( 0, yyscanner ); + { + BEGIN( Start ); + } - if (global_scope && global_scope != INVALID_ENTRY) endScope(current_root, TRUE); // TRUE - global root + fortranscannerYYlex(yyscanner); + Doxygen::docGroup.leaveFile(yyextra->fileName,yyextra->lineNr); - //debugCompounds(rt); //debug + if (yyextra->global_scope && yyextra->global_scope != INVALID_ENTRY) + { + endScope(yyscanner,yyextra->current_root, TRUE); // TRUE - global root + } - rt->program.resize(0); - //delete current; current=0; - moduleProcedures.clear(); - if (tmpBuf) { - free((char*)tmpBuf); - inputString=NULL; - } - if (isFixedForm) { - free((char*)inputString); - inputString=NULL; - } + //debugCompounds(rt); //debug - inputFile.close(); + rt->program.resize(0); + //delete yyextra->current; yyextra->current=0; + yyextra->moduleProcedures.clear(); + if (tmpBuf) + { + free((char*)tmpBuf); + yyextra->inputString=NULL; } + if (yyextra->isFixedForm) + { + free((char*)yyextra->inputString); + yyextra->inputString=NULL; + } + } //---------------------------------------------------------------------------- +struct FortranOutlineParser::Private +{ + yyscan_t yyscanner; + fortranscannerYY_state extra; + FortranFormat format; + Private(FortranFormat fmt) : format(fmt) + { + fortranscannerYYlex_init_extra(&extra,&yyscanner); +#ifdef FLEX_DEBUG + fortranscannerYYset_debug(1,yyscanner); +#endif + } + ~Private() + { + fortranscannerYYlex_destroy(yyscanner); + } +}; + +FortranOutlineParser::FortranOutlineParser(FortranFormat format) + : p(std::make_unique(format)) +{ +} + +FortranOutlineParser::~FortranOutlineParser() +{ +} + void FortranOutlineParser::parseInput(const char *fileName, const char *fileBuf, const std::shared_ptr &root, bool /*sameTranslationUnit*/, QStrList & /*filesInSameTranslationUnit*/) { - g_thisParser = this; + struct yyguts_t *yyg = (struct yyguts_t*)p->yyscanner; + yyextra->thisParser = this; printlex(yy_flex_debug, TRUE, __FILE__, fileName); - ::parseMain(fileName,fileBuf,root,m_format); + ::parseMain(p->yyscanner,fileName,fileBuf,root,p->format); printlex(yy_flex_debug, FALSE, __FILE__, fileName); } @@ -2775,35 +2817,38 @@ bool FortranOutlineParser::needsPreprocessing(const QCString &extension) const { return extension!=extension.lower(); // use preprocessor only for upper case extensions } + void FortranOutlineParser::parsePrototype(const char *text) { + struct yyguts_t *yyg = (struct yyguts_t*)p->yyscanner; QCString buffer = QCString(text); - pushBuffer(buffer); - parsingPrototype = TRUE; + pushBuffer(p->yyscanner,buffer); + yyextra->parsingPrototype = TRUE; BEGIN(Prototype); - fortranscannerYYlex(); - parsingPrototype = FALSE; - popBuffer(); + fortranscannerYYlex(p->yyscanner); + yyextra->parsingPrototype = FALSE; + popBuffer(p->yyscanner); } //---------------------------------------------------------------------------- -static void scanner_abort() +static void scanner_abort(yyscan_t yyscanner) { + struct yyguts_t *yyg = (struct yyguts_t*)yyscanner; fprintf(stderr,"********************************************************************\n"); - fprintf(stderr,"Error in file %s line: %d, state: %d(%s)\n",yyFileName.data(),yyLineNr,YY_START,stateToString(YY_START)); + fprintf(stderr,"Error in file %s line: %d, state: %d(%s)\n",yyextra->fileName.data(),yyextra->lineNr,YY_START,stateToString(YY_START)); fprintf(stderr,"********************************************************************\n"); bool start=FALSE; - for (const auto &ce : global_root->children()) + for (const auto &ce : yyextra->global_root->children()) { - if (ce == file_root) start=TRUE; + if (ce == yyextra->file_root) start=TRUE; if (start) ce->reset(); } // dummy call to avoid compiler warning - (void)yy_top_state(); + (void)yy_top_state(yyscanner); return; //exit(-1); -- cgit v0.12