summaryrefslogtreecommitdiffstats
path: root/src/fortranscanner.l
diff options
context:
space:
mode:
Diffstat (limited to 'src/fortranscanner.l')
-rw-r--r--src/fortranscanner.l240
1 files changed, 102 insertions, 138 deletions
diff --git a/src/fortranscanner.l b/src/fortranscanner.l
index d75134a..9ff89e7 100644
--- a/src/fortranscanner.l
+++ b/src/fortranscanner.l
@@ -165,11 +165,11 @@ static int yyColNr = 0 ;
static Entry* current_root = 0 ;
static Entry* global_root = 0 ;
static Entry* file_root = 0 ;
-static Entry* current = 0 ;
static Entry* last_entry = 0 ;
static Entry* last_enum = 0 ;
+static std::unique_ptr<Entry> current;
static ScanVar v_type = V_IGNORE; // type of parsed variable
-static QList<Entry> moduleProcedures; // list of all interfaces which contain unresolved
+static std::vector<Entry*> moduleProcedures; // list of all interfaces which contain unresolved
// module procedures
static QCString docBlock;
static bool docBlockInBody = FALSE;
@@ -202,7 +202,7 @@ static SymbolModifiers currentModifiers;
//! Holds program scope->symbol name->symbol modifiers.
static QMap<Entry*,QMap<QCString,SymbolModifiers> > modifiers;
-static Entry *global_scope = NULL;
+static Entry *global_scope = 0;
static int anonCount = 0 ;
//-----------------------------------------------------------------------------
@@ -211,7 +211,7 @@ 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(int case_insens);
+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);
@@ -221,7 +221,7 @@ 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(QList<Entry> &moduleProcedures, Entry *current_root);
+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);
@@ -241,6 +241,7 @@ 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;
+#define INVALID_ENTRY ((Entry*)0x8)
//-----------------------------------------------------------------------------
%}
@@ -444,8 +445,7 @@ SCOPENAME ({ID}{BS}"::"{BS})*
current->name=yytext;
current->fileName = yyFileName;
current->section=Entry::USINGDIR_SEC;
- current_root->addSubEntry(current);
- current = new Entry;
+ current_root->moveToSubEntryAndRefresh(current);
current->lang = SrcLangExt_Fortran;
yy_pop_state();
}
@@ -459,8 +459,7 @@ SCOPENAME ({ID}{BS}"::"{BS})*
current->name= useModuleName+"::"+yytext;
current->fileName = yyFileName;
current->section=Entry::USINGDECL_SEC;
- current_root->addSubEntry(current);
- current = new Entry ;
+ current_root->moveToSubEntryAndRefresh(current);
current->lang = SrcLangExt_Fortran;
}
<Use,UseOnly>"\n" {
@@ -516,8 +515,8 @@ SCOPENAME ({ID}{BS}"::"{BS})*
current->section = Entry::FUNCTION_SEC ;
current->name = yytext;
- moduleProcedures.append(current);
- addCurrentEntry(1);
+ moduleProcedures.push_back(current.get());
+ addCurrentEntry(true);
}
<ModuleProcedure>"\n" { yyColNr -= 1;
unput(*yytext);
@@ -558,13 +557,13 @@ SCOPENAME ({ID}{BS}"::"{BS})*
yy_pop_state();
}
<Start,ModuleBody,ModuleBodyContains>"end"({BS}(module|program)({BS_}{ID})?)?{BS}/(\n|!|;) { // end module
- resolveModuleProcedures(moduleProcedures, current_root);
+ resolveModuleProcedures(current_root);
if (!endScope(current_root))
yyterminate();
defaultProtection = Public;
if (global_scope)
{
- if (global_scope != (Entry *) -1)
+ if (global_scope != INVALID_ENTRY)
yy_push_state(Start);
else
yy_pop_state(); // cannot pop artrificial entry
@@ -572,7 +571,7 @@ SCOPENAME ({ID}{BS}"::"{BS})*
else
{
yy_push_state(Start);
- global_scope = (Entry *)-1; // signal that the global_scope has already been used.
+ global_scope = INVALID_ENTRY; // signal that the global_scope has already been used.
}
}
<Module>{ID} {
@@ -647,7 +646,7 @@ private {
current->name = current_root->name + "::" + current->name;
}
- addCurrentEntry(1);
+ addCurrentEntry(true);
startScope(last_entry);
BEGIN(TypedefBody);
}
@@ -679,7 +678,7 @@ private {
current->fileName = yyFileName;
current->bodyLine = yyLineNr;
current->startLine = yyLineNr;
- addCurrentEntry(1);
+ addCurrentEntry(true);
}
{BS}"=>"[^(\n|\!)]* { /* Specific bindings come after the ID. */
QCString args = yytext;
@@ -866,17 +865,15 @@ private {
current->startLine = yyLineNr;
if (argType == "@")
{
- current_root->addSubEntry(current);
- current = new Entry(*current);
+ current_root->copyToSubEntry(current);
// add to the scope surrounding the enum (copy!)
- current_root->parent()->addSubEntry(current);
- last_enum = current;
- current = new Entry ;
+ last_enum = current.get();
+ current_root->parent()->moveToSubEntryAndRefresh(current);
initEntry();
}
else
{
- addCurrentEntry(1);
+ addCurrentEntry(true);
}
}
else if (!argType.isEmpty())
@@ -889,7 +886,7 @@ private {
if (!docBlock.isNull())
{
subrHandleCommentBlock(docBlock,TRUE);
- }
+ }
}
// save, it may be function return type
if (parameter)
@@ -1068,7 +1065,7 @@ private {
current->name = current_root->name + "::" + current->name;
}
- addCurrentEntry(1);
+ addCurrentEntry(true);
startScope(last_entry);
BEGIN( Enum ) ;
}
@@ -1138,7 +1135,7 @@ private {
<Parameterlist>")" {
current->args += ")";
current->args = removeRedundantWhiteSpace(current->args);
- addCurrentEntry(1);
+ addCurrentEntry(true);
startScope(last_entry);
BEGIN(SubprogBody);
}
@@ -1164,7 +1161,7 @@ private {
newLine();
//printf("3=========> without parameterlist \n");
//current->argList = ;
- addCurrentEntry(1);
+ addCurrentEntry(true);
startScope(last_entry);
BEGIN(SubprogBody);
}
@@ -1217,11 +1214,20 @@ private {
unput(*yytext);
if (v_type == V_VARIABLE)
{
- Entry *tmp_entry = current;
- current = last_entry; // temporarily switch to the previous entry
- if (last_enum) current = last_enum;
+ std::unique_ptr<Entry> tmp_entry;
+ current.swap(tmp_entry);
+ // temporarily switch to the previous entry
+ if (last_enum)
+ {
+ current.reset(last_enum);
+ }
+ else
+ {
+ current.reset(last_entry);
+ }
handleCommentBlock(docBlock,TRUE);
- current=tmp_entry;
+ // switch back
+ tmp_entry.swap(current);
}
else if (v_type == V_PARAMETER)
{
@@ -1773,34 +1779,30 @@ static void popBuffer() {
}
/** used to copy entry to an interface module procedure */
-static void copyEntry(Entry *dest, Entry *src)
+static void copyEntry(Entry *dest, const std::unique_ptr<Entry> &src)
{
- dest->type = src->type;
- dest->fileName = src->fileName;
- dest->startLine = src->startLine;
- dest->bodyLine = src->bodyLine;
+ dest->type = src->type;
+ dest->fileName = src->fileName;
+ dest->startLine = src->startLine;
+ dest->bodyLine = src->bodyLine;
dest->endBodyLine = src->endBodyLine;
- dest->args = src->args;
- dest->argList = new ArgumentList(*src->argList);
- dest->doc = src->doc;
- dest->brief = src->brief;
+ dest->args = src->args;
+ delete dest->argList;
+ dest->argList = new ArgumentList(*src->argList);
+ dest->doc = src->doc;
+ dest->brief = src->brief;
}
/** fill empty interface module procedures with info from
corresponding module subprogs
@TODO: handle procedures in used modules
*/
-void resolveModuleProcedures(QList<Entry> &moduleProcedures, Entry *current_root)
+void resolveModuleProcedures(Entry *current_root)
{
- if (moduleProcedures.isEmpty()) return;
-
- EntryListIterator eli1(moduleProcedures);
- // for all module procedures
- for (Entry *ce1; (ce1=eli1.current()); ++eli1)
+ for (const auto &ce1 : moduleProcedures)
{
// check all entries in this module
- EntryListIterator eli2(*current_root->children());
- for (Entry *ce2; (ce2=eli2.current()); ++eli2)
+ for (const auto &ce2 : current_root->children())
{
if (ce1->name == ce2->name)
{
@@ -2022,26 +2024,6 @@ static Argument *findArgument(Entry* subprog, QCString name, bool byTypeName = F
return 0;
}
-/*! Find function with given name in \a entry. */
-#if 0
-static Entry *findFunction(Entry* entry, QCString name)
-{
- QCString cname(name.lower());
-
- EntryListIterator eli(*entry->children());
- Entry *ce;
- for (;(ce=eli.current());++eli)
- {
- if (ce->section != Entry::FUNCTION_SEC)
- continue;
-
- if (ce->name.lower() == cname)
- return ce;
- }
-
- return 0;
-}
-#endif
/*! Apply modifiers stored in \a mdfs to the \a typeName string. */
static QCString applyModifiers(QCString typeName, SymbolModifiers& mdfs)
@@ -2199,10 +2181,10 @@ static bool endScope(Entry *scope, bool isGlobalRoot)
{
if (global_scope == scope)
{
- global_scope = NULL;
+ global_scope = 0;
return TRUE;
}
- if (global_scope == (Entry *) -1)
+ if (global_scope == INVALID_ENTRY)
{
return TRUE;
}
@@ -2250,11 +2232,9 @@ static bool endScope(Entry *scope, bool isGlobalRoot)
// iterate functions of interface and
// try to find types for dummy(ie. argument) procedures.
//cout<<"Search in "<<scope->name<<endl;
- EntryListIterator eli(*scope->children());
- Entry *ce;
int count = 0;
int found = FALSE;
- for (;(ce=eli.current());++eli)
+ for (const auto &ce : scope->children())
{
count++;
if (ce->section != Entry::FUNCTION_SEC)
@@ -2273,7 +2253,7 @@ static bool endScope(Entry *scope, bool isGlobalRoot)
{
// clear all modifiers of the scope
modifiers.remove(scope);
- delete scope->parent()->removeSubEntry(scope);
+ scope->parent()->removeSubEntry(scope);
scope = 0;
return TRUE;
}
@@ -2282,16 +2262,14 @@ static bool endScope(Entry *scope, bool isGlobalRoot)
if (scope->section!=Entry::FUNCTION_SEC)
{ // not function section
// iterate variables: get and apply modifiers
- EntryListIterator eli(*scope->children());
- Entry *ce;
- for (;(ce=eli.current());++eli)
+ for (const auto &ce : scope->children())
{
if (ce->section != Entry::VARIABLE_SEC && ce->section != Entry::FUNCTION_SEC)
continue;
//cout<<ce->name<<", "<<mdfsMap.contains(ce->name.lower())<<mdfsMap.count()<<endl;
if (mdfsMap.contains(ce->name.lower()))
- applyModifiers(ce, mdfsMap[ce->name.lower()]);
+ applyModifiers(ce.get(), mdfsMap[ce->name.lower()]);
}
}
@@ -2345,19 +2323,18 @@ static void initEntry()
current->virt = virt;
current->stat = gstat;
current->lang = SrcLangExt_Fortran;
- Doxygen::docGroup.initGroupInfo(current);
+ Doxygen::docGroup.initGroupInfo(current.get());
}
/**
adds current entry to current_root and creates new current
*/
-static void addCurrentEntry(int case_insens)
+static void addCurrentEntry(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());
- current_root->addSubEntry(current);
- last_entry = current;
- current = new Entry ;
+ last_entry = current.get();
+ current_root->moveToSubEntryAndRefresh(current);
initEntry();
}
@@ -2375,7 +2352,7 @@ static void addModule(const char *name, bool isModule)
if (name!=NULL)
{
current->name = name;
- }
+ }
else
{
QCString fname = yyFileName;
@@ -2389,7 +2366,7 @@ static void addModule(const char *name, bool isModule)
current->bodyLine = yyLineNr; // used for source reference
current->startLine = yyLineNr;
current->protection = Public ;
- addCurrentEntry(1);
+ addCurrentEntry(true);
startScope(last_entry);
}
@@ -2397,7 +2374,7 @@ static void addModule(const char *name, bool isModule)
static void addSubprogram(const char *text)
{
DBG_CTX((stderr,"1=========> got subprog, type: %s\n",text));
- subrCurrent.prepend(current);
+ subrCurrent.prepend(current.get());
current->section = Entry::FUNCTION_SEC ;
QCString subtype = text; subtype=subtype.lower().stripWhiteSpace();
functionLine = (subtype.find("function") != -1);
@@ -2454,7 +2431,7 @@ static void addInterface(QCString name, InterfaceType type)
current->fileName = yyFileName;
current->bodyLine = yyLineNr;
current->startLine = yyLineNr;
- addCurrentEntry(1);
+ addCurrentEntry(true);
}
@@ -2513,7 +2490,7 @@ static void handleCommentBlock(const QCString &doc,bool brief)
QCString processedDoc = preprocessCommentBlock(doc,yyFileName,lineNr);
while (parseCommentBlock(
g_thisParser,
- docBlockInBody ? subrCurrent.getFirst() : current,
+ docBlockInBody ? subrCurrent.getFirst() : current.get(),
processedDoc, // text
yyFileName, // file
lineNr,
@@ -2526,11 +2503,11 @@ static void handleCommentBlock(const QCString &doc,bool brief)
))
{
DBG_CTX((stderr,"parseCommentBlock position=%d [%s] needsEntry=%d\n",position,doc.data()+position,needsEntry));
- if (needsEntry) addCurrentEntry(0);
+ if (needsEntry) addCurrentEntry(false);
}
DBG_CTX((stderr,"parseCommentBlock position=%d [%s] needsEntry=%d\n",position,doc.data()+position,needsEntry));
- if (needsEntry) addCurrentEntry(0);
+ if (needsEntry) addCurrentEntry(false);
docBlockInBody = FALSE;
}
@@ -2541,8 +2518,9 @@ static void subrHandleCommentBlock(const QCString &doc,bool brief)
QCString loc_doc;
loc_doc = doc.stripWhiteSpace();
- Entry *tmp_entry = current;
- current = subrCurrent.getFirst(); // temporarily switch to the entry of the subroutine / function
+ std::unique_ptr<Entry> tmp_entry;
+ current.swap(tmp_entry);
+ current.reset(subrCurrent.getFirst()); // temporarily switch to the entry of the subroutine / function
// Still in the specification section so no inbodyDocs yet, but parameter documentation
current->inbodyDocs = "";
@@ -2566,14 +2544,11 @@ 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 documemntation
- if (loc_doc.isEmpty() || (loc_doc.lower() == argName.lower()))
+ if (!loc_doc.isEmpty() && (loc_doc.lower() != argName.lower()))
{
- // reset current back to the part inside the routine
- current=tmp_entry;
- return;
- }
- handleCommentBlock(QCString("\n\n@param ") + directionParam[SymbolModifiers::IN] + " " +
+ handleCommentBlock(QCString("\n\n@param ") + directionParam[SymbolModifiers::IN] + " " +
argName + " " + loc_doc,brief);
+ }
}
else
{
@@ -2594,7 +2569,7 @@ static void subrHandleCommentBlock(const QCString &doc,bool brief)
loc_doc.stripWhiteSpace();
if (loc_doc.isEmpty() || (loc_doc.lower() == argName.lower()))
{
- current=tmp_entry;
+ tmp_entry.swap(current);
return;
}
handleCommentBlock(QCString("\n\n@param ") + directionParam[SymbolModifiers::OUT] + " " +
@@ -2616,13 +2591,11 @@ 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() != argName.lower()))
{
- current=tmp_entry;
- return;
+ handleCommentBlock(QCString("\n\n@param ") + directionParam[SymbolModifiers::INOUT] + " " +
+ argName + " " + loc_doc,brief);
}
- handleCommentBlock(QCString("\n\n@param ") + directionParam[SymbolModifiers::INOUT] + " " +
- argName + " " + loc_doc,brief);
}
else
{
@@ -2633,19 +2606,14 @@ static void subrHandleCommentBlock(const QCString &doc,bool brief)
}
}
// analogous to the [in] case; here no direction specified
- else
+ else if (!loc_doc.isEmpty() && (loc_doc.lower() != argName.lower()))
{
- if (loc_doc.isEmpty() || (loc_doc.lower() == argName.lower()))
- {
- current=tmp_entry;
- return;
- }
handleCommentBlock(QCString("\n\n@param ") + directionParam[dir1] + " " +
argName + " " + loc_doc,brief);
}
// reset current back to the part inside the routine
- current=tmp_entry;
+ tmp_entry.swap(current);
}
//----------------------------------------------------------------------------
/// Handle result description as defined after the declaration of the parameter
@@ -2654,8 +2622,9 @@ static void subrHandleCommentBlockResult(const QCString &doc,bool brief)
QCString loc_doc;
loc_doc = doc.stripWhiteSpace();
- Entry *tmp_entry = current;
- current = subrCurrent.getFirst(); // temporarily switch to the entry of the subroutine / function
+ std::unique_ptr<Entry> tmp_entry;
+ current.swap(tmp_entry);
+ current.reset(subrCurrent.getFirst()); // temporarily switch to the entry of the subroutine / function
// Still in the specification section so no inbodyDocs yet, but parameter documentation
current->inbodyDocs = "";
@@ -2668,15 +2637,13 @@ 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() != argName.lower()))
{
- current=tmp_entry;
- return;
+ handleCommentBlock(QCString("\n\n@returns ") + loc_doc,brief);
}
- handleCommentBlock(QCString("\n\n@returns ") + loc_doc,brief);
// reset current back to the part inside the routine
- current=tmp_entry;
+ tmp_entry.swap(current);
}
//----------------------------------------------------------------------------
@@ -2687,18 +2654,17 @@ static void debugCompounds(Entry *rt) // print Entry structure (for debugging)
{
level++;
printf("%d) debugCompounds(%s) line %d\n",level, rt->name.data(), rt->bodyLine);
- EntryListIterator eli(*rt->children());
- Entry *ce;
- for (;(ce=eli.current());++eli)
+ for (const auto &ce : rt->children())
{
- debugCompounds(ce);
- }
+ debugCompounds(ce.get());
+ }
level--;
}
#endif
-static void parseMain(const char *fileName,const char *fileBuf,Entry *rt, FortranFormat format)
+static void parseMain(const char *fileName,const char *fileBuf,
+ const std::unique_ptr<Entry> &rt, FortranFormat format)
{
char *tmpBuf = NULL;
initParser();
@@ -2713,8 +2679,8 @@ static void parseMain(const char *fileName,const char *fileBuf,Entry *rt, Fortra
mtype = Method;
gstat = FALSE;
virt = Normal;
- current_root = rt;
- global_root = rt;
+ current_root = rt.get();
+ global_root = rt.get();
inputFile.setName(fileName);
if (inputFile.open(IO_ReadOnly))
{
@@ -2750,18 +2716,18 @@ static void parseMain(const char *fileName,const char *fileBuf,Entry *rt, Fortra
yyFileName = fileName;
msg("Parsing file %s...\n",yyFileName.data());
- global_scope = rt;
- startScope(rt); // implies current_root = rt
+ global_scope = rt.get();
+ startScope(rt.get()); // implies current_root = rt
initParser();
Doxygen::docGroup.enterFile(yyFileName,yyLineNr);
- current = new Entry;
+ // add entry for the file
+ current = std::make_unique<Entry>();
current->lang = SrcLangExt_Fortran;
current->name = yyFileName;
current->section = Entry::SOURCE_SEC;
- current_root->addSubEntry(current);
- file_root = current;
- current = new Entry;
+ file_root = current.get();
+ current_root->moveToSubEntryAndRefresh(current);
current->lang = SrcLangExt_Fortran;
fortranscannerYYrestart( fortranscannerYYin );
@@ -2772,12 +2738,12 @@ static void parseMain(const char *fileName,const char *fileBuf,Entry *rt, Fortra
fortranscannerYYlex();
Doxygen::docGroup.leaveFile(yyFileName,yyLineNr);
- if (global_scope && global_scope != (Entry *) -1) endScope(current_root, TRUE); // TRUE - global root
+ if (global_scope && global_scope != INVALID_ENTRY) endScope(current_root, TRUE); // TRUE - global root
//debugCompounds(rt); //debug
rt->program.resize(0);
- delete current; current=0;
+ //delete current; current=0;
moduleProcedures.clear();
if (tmpBuf) {
free((char*)tmpBuf);
@@ -2796,7 +2762,7 @@ static void parseMain(const char *fileName,const char *fileBuf,Entry *rt, Fortra
void FortranLanguageScanner::parseInput(const char *fileName,
const char *fileBuf,
- Entry *root,
+ const std::unique_ptr<Entry> &root,
bool /*sameTranslationUnit*/,
QStrList & /*filesInSameTranslationUnit*/)
{
@@ -2856,13 +2822,11 @@ static void scanner_abort()
fprintf(stderr,"Error in file %s line: %d, state: %d(%s)\n",yyFileName.data(),yyLineNr,YY_START,stateToString(YY_START));
fprintf(stderr,"********************************************************************\n");
- EntryListIterator eli(*global_root->children());
- Entry *ce;
bool start=FALSE;
- for (;(ce=eli.current());++eli)
+ for (const auto &ce : global_root->children())
{
- if (ce == file_root) start=TRUE;
+ if (ce.get() == file_root) start=TRUE;
if (start) ce->reset();
}