|
Packit |
1c1d7e |
/* -*- mode: fundamental; indent-tabs-mode: 1; -*- */
|
|
Packit |
1c1d7e |
/*****************************************************************************
|
|
Packit |
1c1d7e |
* Parser for Fortran90 F subset
|
|
Packit |
1c1d7e |
*
|
|
Packit |
1c1d7e |
* Copyright (C) by Anke Visser
|
|
Packit |
1c1d7e |
* based on the work of Dimitri van Heesch.
|
|
Packit |
1c1d7e |
*
|
|
Packit |
1c1d7e |
* Permission to use, copy, modify, and distribute this software and its
|
|
Packit |
1c1d7e |
* documentation under the terms of the GNU General Public License is hereby
|
|
Packit |
1c1d7e |
* granted. No representations are made about the suitability of this software
|
|
Packit |
1c1d7e |
* for any purpose. It is provided "as is" without express or implied warranty.
|
|
Packit |
1c1d7e |
* See the GNU General Public License for more details.
|
|
Packit |
1c1d7e |
*
|
|
Packit |
1c1d7e |
* Documents produced by Doxygen are derivative works derived from the
|
|
Packit |
1c1d7e |
* input used in their production; they are not affected by this license.
|
|
Packit |
1c1d7e |
*
|
|
Packit |
1c1d7e |
*/
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
/* Developer notes.
|
|
Packit |
1c1d7e |
*
|
|
Packit |
1c1d7e |
* - Consider using startScope(), endScope() functions with module, program,
|
|
Packit |
1c1d7e |
* subroutine or any other scope in fortran program.
|
|
Packit |
1c1d7e |
*
|
|
Packit |
1c1d7e |
* - Symbol modifiers (attributes) are collected using SymbolModifiers |= operator during
|
|
Packit |
1c1d7e |
* substructure parsing. When substructure ends all modifiers are applied to actual
|
|
Packit |
1c1d7e |
* entries in applyModifiers() functions.
|
|
Packit |
1c1d7e |
*
|
|
Packit |
1c1d7e |
* - How case insensitiveness should be handled in code?
|
|
Packit |
1c1d7e |
* On one side we have arg->name and entry->name, on another side modifierMap[name].
|
|
Packit |
1c1d7e |
* In entries and arguments case is the same as in code, in modifier map case is lowered and
|
|
Packit |
1c1d7e |
* then it is compared to lowered entry/argument names.
|
|
Packit |
1c1d7e |
*
|
|
Packit |
1c1d7e |
* - Do not like constructs like aa{BS} or {BS}bb. Should try to handle blank space
|
|
Packit |
1c1d7e |
* with separate rule?: It seems it is often necessary, because we may parse something like
|
|
Packit |
1c1d7e |
* "functionA" or "MyInterface". So constructs like `(^|[ \t])interface({BS_}{ID})?/[ \t\n]'
|
|
Packit |
1c1d7e |
* are desired.
|
|
Packit |
1c1d7e |
*
|
|
Packit |
1c1d7e |
* - Must track yyLineNr when using REJECT, unput() or similar commands.
|
|
Packit |
1c1d7e |
*/
|
|
Packit |
1c1d7e |
%option never-interactive
|
|
Packit |
1c1d7e |
%option case-insensitive
|
|
Packit |
1c1d7e |
%option prefix="fortranscannerYY"
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
%{
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
#include <stdio.h>
|
|
Packit |
1c1d7e |
#include <stdlib.h>
|
|
Packit |
1c1d7e |
#include <assert.h>
|
|
Packit |
1c1d7e |
#include <ctype.h>
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
#include <qarray.h>
|
|
Packit |
1c1d7e |
#include <qstack.h>
|
|
Packit |
1c1d7e |
#include <qregexp.h>
|
|
Packit |
1c1d7e |
#include <qfile.h>
|
|
Packit |
1c1d7e |
#include <qmap.h>
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
#include "fortranscanner.h"
|
|
Packit |
1c1d7e |
#include "entry.h"
|
|
Packit |
1c1d7e |
#include "message.h"
|
|
Packit |
1c1d7e |
#include "config.h"
|
|
Packit |
1c1d7e |
#include "doxygen.h"
|
|
Packit |
1c1d7e |
#include "util.h"
|
|
Packit |
1c1d7e |
#include "defargs.h"
|
|
Packit |
1c1d7e |
#include "language.h"
|
|
Packit |
1c1d7e |
#include "commentscan.h"
|
|
Packit |
1c1d7e |
#include "fortrancode.h"
|
|
Packit |
1c1d7e |
#include "pre.h"
|
|
Packit |
1c1d7e |
#include "arguments.h"
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
// Toggle for some debugging info
|
|
Packit |
1c1d7e |
//#define DBG_CTX(x) fprintf x
|
|
Packit |
1c1d7e |
#define DBG_CTX(x) do { } while(0)
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
#define YY_NO_INPUT 1
|
|
Packit |
1c1d7e |
#define YY_NO_UNISTD_H 1
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
enum ScanVar { V_IGNORE, V_VARIABLE, V_PARAMETER, V_RESULT};
|
|
Packit |
1c1d7e |
enum InterfaceType { IF_NONE, IF_SPECIFIC, IF_GENERIC, IF_ABSTRACT };
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
// {{{ ----- Helper structs -----
|
|
Packit |
1c1d7e |
//! Holds modifiers (ie attributes) for one symbol (variable, function, etc)
|
|
Packit |
1c1d7e |
struct SymbolModifiers {
|
|
Packit |
1c1d7e |
enum Protection {NONE_P, PUBLIC, PRIVATE};
|
|
Packit |
1c1d7e |
enum Direction {NONE_D, IN, OUT, INOUT};
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
//!< This is only used with function return value.
|
|
Packit |
1c1d7e |
QCString type, returnName;
|
|
Packit |
1c1d7e |
Protection protection;
|
|
Packit |
1c1d7e |
Direction direction;
|
|
Packit |
1c1d7e |
bool optional;
|
|
Packit |
1c1d7e |
bool protect;
|
|
Packit |
1c1d7e |
QCString dimension;
|
|
Packit |
1c1d7e |
bool allocatable;
|
|
Packit |
1c1d7e |
bool external;
|
|
Packit |
1c1d7e |
bool intrinsic;
|
|
Packit |
1c1d7e |
bool parameter;
|
|
Packit |
1c1d7e |
bool pointer;
|
|
Packit |
1c1d7e |
bool target;
|
|
Packit |
1c1d7e |
bool save;
|
|
Packit |
1c1d7e |
bool deferred;
|
|
Packit |
1c1d7e |
bool nonoverridable;
|
|
Packit |
1c1d7e |
bool nopass;
|
|
Packit |
1c1d7e |
bool pass;
|
|
Packit |
1c1d7e |
bool contiguous;
|
|
Packit |
1c1d7e |
bool volat; /* volatile is a reserved name */
|
|
Packit |
1c1d7e |
bool value; /* volatile is a reserved name */
|
|
Packit |
1c1d7e |
QCString passVar;
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
SymbolModifiers() : type(), returnName(), protection(NONE_P), direction(NONE_D),
|
|
Packit |
1c1d7e |
optional(FALSE), protect(FALSE), dimension(), allocatable(FALSE),
|
|
Packit |
1c1d7e |
external(FALSE), intrinsic(FALSE), parameter(FALSE),
|
|
Packit |
1c1d7e |
pointer(FALSE), target(FALSE), save(FALSE), deferred(FALSE), nonoverridable(FALSE),
|
|
Packit |
1c1d7e |
nopass(FALSE), pass(FALSE), contiguous(FALSE), volat(FALSE), value(FALSE), passVar() {}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
SymbolModifiers& operator|=(const SymbolModifiers &mdfs);
|
|
Packit |
1c1d7e |
SymbolModifiers& operator|=(QCString mdfrString);
|
|
Packit |
1c1d7e |
};
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
//ostream& operator<<(ostream& out, const SymbolModifiers& mdfs);
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
static const char *directionStrs[] =
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
"", "intent(in)", "intent(out)", "intent(inout)"
|
|
Packit |
1c1d7e |
};
|
|
Packit |
1c1d7e |
static const char *directionParam[] =
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
"", "[in]", "[out]", "[in,out]"
|
|
Packit |
1c1d7e |
};
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
// }}}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
/* -----------------------------------------------------------------
|
|
Packit |
1c1d7e |
*
|
|
Packit |
1c1d7e |
* statics
|
|
Packit |
1c1d7e |
*/
|
|
Packit |
1c1d7e |
static ParserInterface *g_thisParser;
|
|
Packit |
1c1d7e |
static const char * inputString;
|
|
Packit |
1c1d7e |
static int inputPosition;
|
|
Packit |
1c1d7e |
static bool isFixedForm;
|
|
Packit |
1c1d7e |
static QCString inputStringPrepass; ///< Input string for prepass of line cont. '&'
|
|
Packit |
1c1d7e |
static QCString inputStringSemi; ///< Input string after command separetor ';'
|
|
Packit |
1c1d7e |
static unsigned int inputPositionPrepass;
|
|
Packit |
1c1d7e |
static int lineCountPrepass = 0;
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
static QList<Entry> subrCurrent;
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
struct CommentInPrepass {
|
|
Packit |
1c1d7e |
int column;
|
|
Packit |
1c1d7e |
QCString str;
|
|
Packit |
1c1d7e |
CommentInPrepass(int column, QCString str) : column(column), str(str) {}
|
|
Packit |
1c1d7e |
};
|
|
Packit |
1c1d7e |
static QList<CommentInPrepass> comments;
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
YY_BUFFER_STATE *include_stack = NULL;
|
|
Packit |
1c1d7e |
int include_stack_ptr = 0;
|
|
Packit |
1c1d7e |
int include_stack_cnt = 0;
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
static QFile inputFile;
|
|
Packit |
1c1d7e |
static QCString yyFileName;
|
|
Packit |
1c1d7e |
static int yyLineNr = 1 ;
|
|
Packit |
1c1d7e |
static int yyColNr = 0 ;
|
|
Packit |
1c1d7e |
static Entry* current_root = 0 ;
|
|
Packit |
1c1d7e |
static Entry* global_root = 0 ;
|
|
Packit |
1c1d7e |
static Entry* file_root = 0 ;
|
|
Packit |
1c1d7e |
static Entry* current = 0 ;
|
|
Packit |
1c1d7e |
static Entry* last_entry = 0 ;
|
|
Packit |
1c1d7e |
static ScanVar v_type = V_IGNORE; // type of parsed variable
|
|
Packit |
1c1d7e |
static QList<Entry> moduleProcedures; // list of all interfaces which contain unresolved
|
|
Packit |
1c1d7e |
// module procedures
|
|
Packit |
1c1d7e |
static QCString docBlock;
|
|
Packit |
1c1d7e |
static bool docBlockInBody = FALSE;
|
|
Packit |
1c1d7e |
static bool docBlockJavaStyle;
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
static MethodTypes mtype;
|
|
Packit |
1c1d7e |
static bool gstat;
|
|
Packit |
1c1d7e |
static Specifier virt;
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
static QCString debugStr;
|
|
Packit |
1c1d7e |
static QCString result; // function result
|
|
Packit |
1c1d7e |
static Argument *parameter; // element of parameter list
|
|
Packit |
1c1d7e |
static QCString argType; // fortran type of an argument of a parameter list
|
|
Packit |
1c1d7e |
static QCString argName; // last identifier name in variable list
|
|
Packit |
1c1d7e |
static QCString initializer; // initial value of a variable
|
|
Packit |
1c1d7e |
static int initializerArrayScope; // number if nested array scopes in initializer
|
|
Packit |
1c1d7e |
static int initializerScope; // number if nested function calls in initializer
|
|
Packit |
1c1d7e |
static QCString useModuleName; // name of module in the use statement
|
|
Packit |
1c1d7e |
static Protection defaultProtection;
|
|
Packit |
1c1d7e |
static Protection typeProtection;
|
|
Packit |
1c1d7e |
static int typeMode = false;
|
|
Packit |
1c1d7e |
static InterfaceType ifType = IF_NONE;
|
|
Packit |
1c1d7e |
static bool functionLine = FALSE;
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
static char stringStartSymbol; // single or double quote
|
|
Packit |
1c1d7e |
static bool parsingPrototype = FALSE; // see parsePrototype()
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
//! Accumulated modifiers of current statement, eg variable declaration.
|
|
Packit |
1c1d7e |
static SymbolModifiers currentModifiers;
|
|
Packit |
1c1d7e |
//! Holds program scope->symbol name->symbol modifiers.
|
|
Packit |
1c1d7e |
static QMap<Entry*,QMap<QCString,SymbolModifiers> > modifiers;
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
//-----------------------------------------------------------------------------
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
static int yyread(char *buf,int max_size);
|
|
Packit |
1c1d7e |
static void startCommentBlock(bool);
|
|
Packit |
1c1d7e |
static void handleCommentBlock(const QCString &doc,bool brief);
|
|
Packit |
1c1d7e |
static void subrHandleCommentBlock(const QCString &doc,bool brief);
|
|
Packit |
1c1d7e |
static void subrHandleCommentBlockResult(const QCString &doc,bool brief);
|
|
Packit |
1c1d7e |
static void addCurrentEntry(int case_insens);
|
|
Packit |
1c1d7e |
static void addModule(const char *name, bool isModule=FALSE);
|
|
Packit |
1c1d7e |
static void addSubprogram(const char *text);
|
|
Packit |
1c1d7e |
static void addInterface(QCString name, InterfaceType type);
|
|
Packit |
1c1d7e |
static Argument *getParameter(const QCString &name);
|
|
Packit |
1c1d7e |
static void scanner_abort();
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
static void startScope(Entry *scope);
|
|
Packit |
1c1d7e |
static bool endScope(Entry *scope, bool isGlobalRoot=FALSE);
|
|
Packit |
1c1d7e |
//static bool isTypeName(QCString name);
|
|
Packit |
1c1d7e |
static void resolveModuleProcedures(QList<Entry> &moduleProcedures, Entry *current_root);
|
|
Packit |
1c1d7e |
static int getAmpersandAtTheStart(const char *buf, int length);
|
|
Packit |
1c1d7e |
static int getAmpOrExclAtTheEnd(const char *buf, int length, char ch);
|
|
Packit |
1c1d7e |
static void truncatePrepass(int index);
|
|
Packit |
1c1d7e |
static void pushBuffer(QCString &buffer);
|
|
Packit |
1c1d7e |
static void popBuffer();
|
|
Packit |
1c1d7e |
//static void extractPrefix(QCString& text);
|
|
Packit |
1c1d7e |
static QCString extractFromParens(const QCString name);
|
|
Packit |
1c1d7e |
static CommentInPrepass* locatePrepassComment(int from, int to);
|
|
Packit |
1c1d7e |
static void updateVariablePrepassComment(int from, int to);
|
|
Packit |
1c1d7e |
static void newLine();
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
//-----------------------------------------------------------------------------
|
|
Packit |
1c1d7e |
#undef YY_INPUT
|
|
Packit |
1c1d7e |
#define YY_INPUT(buf,result,max_size) result=yyread(buf,max_size);
|
|
Packit |
1c1d7e |
#define YY_USER_ACTION yyColNr+=(int)yyleng;
|
|
Packit |
1c1d7e |
//-----------------------------------------------------------------------------
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
%}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
//-----------------------------------------------------------------------------
|
|
Packit |
1c1d7e |
//-----------------------------------------------------------------------------
|
|
Packit |
1c1d7e |
IDSYM [a-z_A-Z0-9]
|
|
Packit |
1c1d7e |
NOTIDSYM [^a-z_A-Z0-9]
|
|
Packit |
1c1d7e |
SEPARATE [:, \t]
|
|
Packit |
1c1d7e |
ID [a-z_A-Z%]+{IDSYM}*
|
|
Packit |
1c1d7e |
ID_ [a-z_A-Z%]*{IDSYM}*
|
|
Packit |
1c1d7e |
PP_ID {ID}
|
|
Packit |
1c1d7e |
LABELID [a-z_A-Z]+[a-z_A-Z0-9\-]*
|
|
Packit |
1c1d7e |
SUBPROG (subroutine|function)
|
|
Packit |
1c1d7e |
B [ \t]
|
|
Packit |
1c1d7e |
BS [ \t]*
|
|
Packit |
1c1d7e |
BS_ [ \t]+
|
|
Packit |
1c1d7e |
COMMA {BS},{BS}
|
|
Packit |
1c1d7e |
ARGS_L0 ("("[^)]*")")
|
|
Packit |
1c1d7e |
ARGS_L1a [^()]*"("[^)]*")"[^)]*
|
|
Packit |
1c1d7e |
ARGS_L1 ("("{ARGS_L1a}*")")
|
|
Packit |
1c1d7e |
ARGS_L2 "("({ARGS_L0}|[^()]|{ARGS_L1a}|{ARGS_L1})*")"
|
|
Packit |
1c1d7e |
ARGS {BS}({ARGS_L0}|{ARGS_L1}|{ARGS_L2})
|
|
Packit |
1c1d7e |
NOARGS {BS}"\n"
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
NUM_TYPE (complex|integer|logical|real)
|
|
Packit |
1c1d7e |
LOG_OPER (\.and\.|\.eq\.|\.eqv\.|\.ge\.|\.gt\.|\.le\.|\.lt\.|\.ne\.|\.neqv\.|\.or\.|\.not\.)
|
|
Packit |
1c1d7e |
KIND {ARGS}
|
|
Packit |
1c1d7e |
CHAR (CHARACTER{ARGS}?|CHARACTER{BS}"*"({BS}[0-9]+|{ARGS}))
|
|
Packit |
1c1d7e |
TYPE_SPEC (({NUM_TYPE}({BS}"*"{BS}[0-9]+)?)|({NUM_TYPE}{KIND})|DOUBLE{BS}COMPLEX|DOUBLE{BS}PRECISION|{CHAR}|TYPE{ARGS}|CLASS{ARGS}|PROCEDURE{ARGS}?)
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
INTENT_SPEC intent{BS}"("{BS}(in|out|in{BS}out){BS}")"
|
|
Packit |
1c1d7e |
ATTR_SPEC (EXTERNAL|ALLOCATABLE|DIMENSION{ARGS}|{INTENT_SPEC}|INTRINSIC|OPTIONAL|PARAMETER|POINTER|PROTECTED|PRIVATE|PUBLIC|SAVE|TARGET|NOPASS|PASS{ARGS}?|DEFERRED|NON_OVERRIDABLE|CONTIGUOUS|VOLATILE|VALUE)
|
|
Packit |
1c1d7e |
ACCESS_SPEC (PRIVATE|PUBLIC)
|
|
Packit |
1c1d7e |
LANGUAGE_BIND_SPEC BIND{BS}"("{BS}C{BS}(,{BS}NAME{BS}"="{BS}"\""(.*)"\""{BS})?")"
|
|
Packit |
1c1d7e |
/* Assume that attribute statements are almost the same as attributes. */
|
|
Packit |
1c1d7e |
ATTR_STMT {ATTR_SPEC}|DIMENSION|{ACCESS_SPEC}
|
|
Packit |
1c1d7e |
EXTERNAL_STMT (EXTERNAL)
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
CONTAINS CONTAINS
|
|
Packit |
1c1d7e |
PREFIX (RECURSIVE{BS_}|IMPURE{BS_}|PURE{BS_}|ELEMENTAL{BS_}){0,3}(RECURSIVE|IMPURE|PURE|ELEMENTAL)?
|
|
Packit |
1c1d7e |
SCOPENAME ({ID}{BS}"::"{BS})*
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
%option noyywrap
|
|
Packit |
1c1d7e |
%option stack
|
|
Packit |
1c1d7e |
%option caseless
|
|
Packit |
1c1d7e |
/*%option debug */
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
//---------------------------------------------------------------------------------
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
/** fortran parsing states */
|
|
Packit |
1c1d7e |
%x Subprog
|
|
Packit |
1c1d7e |
%x SubprogPrefix
|
|
Packit |
1c1d7e |
%x Parameterlist
|
|
Packit |
1c1d7e |
%x SubprogBody
|
|
Packit |
1c1d7e |
%x SubprogBodyContains
|
|
Packit |
1c1d7e |
%x Start
|
|
Packit |
1c1d7e |
%x Comment
|
|
Packit |
1c1d7e |
%x Module
|
|
Packit |
1c1d7e |
%x Program
|
|
Packit |
1c1d7e |
%x ModuleBody
|
|
Packit |
1c1d7e |
%x ModuleBodyContains
|
|
Packit |
1c1d7e |
%x AttributeList
|
|
Packit |
1c1d7e |
%x Variable
|
|
Packit |
1c1d7e |
%x Initialization
|
|
Packit |
1c1d7e |
%x ArrayInitializer
|
|
Packit |
1c1d7e |
%x Typedef
|
|
Packit |
1c1d7e |
%x TypedefBody
|
|
Packit |
1c1d7e |
%x TypedefBodyContains
|
|
Packit |
1c1d7e |
%x InterfaceBody
|
|
Packit |
1c1d7e |
%x StrIgnore
|
|
Packit |
1c1d7e |
%x String
|
|
Packit |
1c1d7e |
%x Use
|
|
Packit |
1c1d7e |
%x UseOnly
|
|
Packit |
1c1d7e |
%x ModuleProcedure
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
%x Prepass
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
/** comment parsing states */
|
|
Packit |
1c1d7e |
%x DocBlock
|
|
Packit |
1c1d7e |
%x DocBackLine
|
|
Packit |
1c1d7e |
%x EndDoc
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
%x BlockData
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
/** prototype parsing */
|
|
Packit |
1c1d7e |
%x Prototype
|
|
Packit |
1c1d7e |
%x PrototypeSubprog
|
|
Packit |
1c1d7e |
%x PrototypeArgs
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
%%
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
/*-----------------------------------------------------------------------------------*/
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
<Prepass>^{BS}[&]*{BS}!.*\n { /* skip lines with just comment. Note code was in free format or has been converted to it */
|
|
Packit |
1c1d7e |
lineCountPrepass ++;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
<Prepass>^{BS}\n { /* skip empty lines */
|
|
Packit |
1c1d7e |
lineCountPrepass ++;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
<*>^.*\n { // prepass: look for line continuations
|
|
Packit |
1c1d7e |
functionLine = FALSE;
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
DBG_CTX((stderr, "---%s", yytext));
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
int indexStart = getAmpersandAtTheStart(yytext, (int)yyleng);
|
|
Packit |
1c1d7e |
int indexEnd = getAmpOrExclAtTheEnd(yytext, (int)yyleng, '\0');
|
|
Packit |
1c1d7e |
if (indexEnd>=0 && yytext[indexEnd]!='&') //we are only interested in amp
|
|
Packit |
1c1d7e |
indexEnd=-1;
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
if(indexEnd<0){ // ----- no ampersand as line continuation
|
|
Packit |
1c1d7e |
if(YY_START == Prepass) { // last line in "continuation"
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
// Only take input after initial ampersand
|
|
Packit |
1c1d7e |
inputStringPrepass+=(const char*)(yytext+(indexStart+1));
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
//printf("BUFFER:%s\n", (const char*)inputStringPrepass);
|
|
Packit |
1c1d7e |
pushBuffer(inputStringPrepass);
|
|
Packit |
1c1d7e |
yyColNr = 0;
|
|
Packit |
1c1d7e |
yy_pop_state();
|
|
Packit |
1c1d7e |
} else { // simple line
|
|
Packit |
1c1d7e |
yyColNr = 0;
|
|
Packit |
1c1d7e |
REJECT;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
} else { // ----- line with continuation
|
|
Packit |
1c1d7e |
if(YY_START != Prepass) {
|
|
Packit |
1c1d7e |
comments.setAutoDelete(TRUE);
|
|
Packit |
1c1d7e |
comments.clear();
|
|
Packit |
1c1d7e |
yy_push_state(Prepass);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
int length = inputStringPrepass.length();
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
// Only take input after initial ampersand
|
|
Packit |
1c1d7e |
inputStringPrepass+=(const char*)(yytext+(indexStart+1));
|
|
Packit |
1c1d7e |
lineCountPrepass ++;
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
// cut off & and remove following comment if present
|
|
Packit |
1c1d7e |
truncatePrepass(length+indexEnd-(indexStart+1));
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
/*------ ignore strings that are not initialization strings */
|
|
Packit |
1c1d7e |
<*>"\\\\" { if (yy_top_state() == Initialization
|
|
Packit |
1c1d7e |
|| yy_top_state() == ArrayInitializer)
|
|
Packit |
1c1d7e |
initializer+=yytext;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
<*>"\\\""|\\\' { if (yy_top_state() == Initialization
|
|
Packit |
1c1d7e |
|| yy_top_state() == ArrayInitializer)
|
|
Packit |
1c1d7e |
initializer+=yytext;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
<String>\"|\' { // string ends with next quote without previous backspace
|
|
Packit |
1c1d7e |
if (yytext[0]!=stringStartSymbol) { yyColNr -= (int)yyleng; REJECT; } // single vs double quote
|
|
Packit |
1c1d7e |
if (yy_top_state() == Initialization
|
|
Packit |
1c1d7e |
|| yy_top_state() == ArrayInitializer)
|
|
Packit |
1c1d7e |
initializer+=yytext;
|
|
Packit |
1c1d7e |
yy_pop_state();
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
<String>. { if (yy_top_state() == Initialization
|
|
Packit |
1c1d7e |
|| yy_top_state() == ArrayInitializer)
|
|
Packit |
1c1d7e |
initializer+=yytext;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
<*>\"|\' { /* string starts */
|
|
Packit |
1c1d7e |
if (YY_START == StrIgnore) { yyColNr -= (int)yyleng; REJECT; }; // ignore in simple comments
|
|
Packit |
1c1d7e |
yy_push_state(YY_START);
|
|
Packit |
1c1d7e |
if (yy_top_state() == Initialization
|
|
Packit |
1c1d7e |
|| yy_top_state() == ArrayInitializer)
|
|
Packit |
1c1d7e |
initializer+=yytext;
|
|
Packit |
1c1d7e |
stringStartSymbol=yytext[0]; // single or double quote
|
|
Packit |
1c1d7e |
BEGIN(String);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
/*------ ignore simple comment (not documentation comments) */
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
<*>"!"/[^<>\n] { if (YY_START == String) { yyColNr -= (int)yyleng; REJECT; } // "!" is ignored in strings
|
|
Packit |
1c1d7e |
// skip comment line (without docu comments "!>" "!<" )
|
|
Packit |
1c1d7e |
/* ignore further "!" and ignore comments in Strings */
|
|
Packit |
1c1d7e |
if ((YY_START != StrIgnore) && (YY_START != String))
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
yy_push_state(YY_START);
|
|
Packit |
1c1d7e |
BEGIN(StrIgnore);
|
|
Packit |
1c1d7e |
debugStr="*!";
|
|
Packit |
1c1d7e |
DBG_CTX((stderr,"start comment %d\n",yyLineNr));
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
<StrIgnore>.?/\n { yy_pop_state(); // comment ends with endline character
|
|
Packit |
1c1d7e |
DBG_CTX((stderr,"end comment %d %s\n",yyLineNr,debugStr.data()));
|
|
Packit |
1c1d7e |
} // comment line ends
|
|
Packit |
1c1d7e |
<StrIgnore>. { debugStr+=yytext; }
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
/*------ use handling ------------------------------------------------------------*/
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
<Start,ModuleBody,SubprogBody>"use"{BS_} {
|
|
Packit |
1c1d7e |
if(YY_START == Start)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
addModule(NULL);
|
|
Packit |
1c1d7e |
yy_push_state(ModuleBody); //anon program
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
yy_push_state(Use);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
<Use>{ID} {
|
|
Packit |
1c1d7e |
DBG_CTX((stderr,"using dir %s\n",yytext));
|
|
Packit |
1c1d7e |
current->name=yytext;
|
|
Packit |
1c1d7e |
current->fileName = yyFileName;
|
|
Packit |
1c1d7e |
current->section=Entry::USINGDIR_SEC;
|
|
Packit |
1c1d7e |
current_root->addSubEntry(current);
|
|
Packit |
1c1d7e |
current = new Entry;
|
|
Packit |
1c1d7e |
current->lang = SrcLangExt_Fortran;
|
|
Packit |
1c1d7e |
yy_pop_state();
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
<Use>{ID}/, {
|
|
Packit |
1c1d7e |
useModuleName=yytext;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
<Use>,{BS}"ONLY" { BEGIN(UseOnly);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
<UseOnly>{BS},{BS} {}
|
|
Packit |
1c1d7e |
<UseOnly>{ID} {
|
|
Packit |
1c1d7e |
current->name= useModuleName+"::"+yytext;
|
|
Packit |
1c1d7e |
current->fileName = yyFileName;
|
|
Packit |
1c1d7e |
current->section=Entry::USINGDECL_SEC;
|
|
Packit |
1c1d7e |
current_root->addSubEntry(current);
|
|
Packit |
1c1d7e |
current = new Entry ;
|
|
Packit |
1c1d7e |
current->lang = SrcLangExt_Fortran;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
<Use,UseOnly>"\n" {
|
|
Packit |
1c1d7e |
yyColNr -= 1;
|
|
Packit |
1c1d7e |
unput(*yytext);
|
|
Packit |
1c1d7e |
yy_pop_state();
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
/* INTERFACE definitions */
|
|
Packit |
1c1d7e |
<Start,ModuleBody,SubprogBody>{
|
|
Packit |
1c1d7e |
^{BS}interface{IDSYM}+ { /* variable with interface prefix */ }
|
|
Packit |
1c1d7e |
^{BS}interface { ifType = IF_SPECIFIC;
|
|
Packit |
1c1d7e |
yy_push_state(InterfaceBody);
|
|
Packit |
1c1d7e |
// do not start a scope here, every
|
|
Packit |
1c1d7e |
// interface body is a scope of its own
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
^{BS}abstract{BS_}interface { ifType = IF_ABSTRACT;
|
|
Packit |
1c1d7e |
yy_push_state(InterfaceBody);
|
|
Packit |
1c1d7e |
// do not start a scope here, every
|
|
Packit |
1c1d7e |
// interface body is a scope of its own
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
^{BS}interface{BS_}{ID}{ARGS}? { ifType = IF_GENERIC;
|
|
Packit |
1c1d7e |
current->bodyLine = yyLineNr + lineCountPrepass + 1; // we have to be at the line after the definition and we have to take continuation lines into account.
|
|
Packit |
1c1d7e |
yy_push_state(InterfaceBody);
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
// extract generic name
|
|
Packit |
1c1d7e |
QCString name = QCString(yytext).stripWhiteSpace();
|
|
Packit |
1c1d7e |
name = name.right(name.length() - 9).stripWhiteSpace().lower();
|
|
Packit |
1c1d7e |
addInterface(name, ifType);
|
|
Packit |
1c1d7e |
startScope(last_entry);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
<InterfaceBody>^{BS}end{BS}interface({BS_}{ID})? {
|
|
Packit |
1c1d7e |
// end scope only if GENERIC interface
|
|
Packit |
1c1d7e |
if (ifType == IF_GENERIC)last_entry->parent()->endBodyLine = yyLineNr - 1;
|
|
Packit |
1c1d7e |
if (ifType == IF_GENERIC && !endScope(current_root))
|
|
Packit |
1c1d7e |
yyterminate();
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
ifType = IF_NONE;
|
|
Packit |
1c1d7e |
yy_pop_state();
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
<InterfaceBody>module{BS}procedure { yy_push_state(YY_START);
|
|
Packit |
1c1d7e |
BEGIN(ModuleProcedure);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
<ModuleProcedure>{ID} { if (ifType == IF_ABSTRACT || ifType == IF_SPECIFIC)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
addInterface(yytext, ifType);
|
|
Packit |
1c1d7e |
startScope(last_entry);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
current->section = Entry::FUNCTION_SEC ;
|
|
Packit |
1c1d7e |
current->name = yytext;
|
|
Packit |
1c1d7e |
moduleProcedures.append(current);
|
|
Packit |
1c1d7e |
addCurrentEntry(1);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
<ModuleProcedure>"\n" { yyColNr -= 1;
|
|
Packit |
1c1d7e |
unput(*yytext);
|
|
Packit |
1c1d7e |
yy_pop_state();
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
<InterfaceBody>. {}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
/*-- Contains handling --*/
|
|
Packit |
1c1d7e |
<Start>^{BS}{CONTAINS}/({BS}|\n|!) {
|
|
Packit |
1c1d7e |
if(YY_START == Start)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
addModule(NULL);
|
|
Packit |
1c1d7e |
yy_push_state(ModuleBodyContains); //anon program
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
<ModuleBody>^{BS}{CONTAINS}/({BS}|\n|!) { BEGIN(ModuleBodyContains); }
|
|
Packit |
1c1d7e |
<SubprogBody>^{BS}{CONTAINS}/({BS}|\n|!) { BEGIN(SubprogBodyContains); }
|
|
Packit |
1c1d7e |
<TypedefBody>^{BS}{CONTAINS}/({BS}|\n|!) { BEGIN(TypedefBodyContains); }
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
/*------ module handling ------------------------------------------------------------*/
|
|
Packit |
1c1d7e |
<Start>block{BS}data{BS}{ID_} { //
|
|
Packit |
1c1d7e |
v_type = V_IGNORE;
|
|
Packit |
1c1d7e |
yy_push_state(BlockData);
|
|
Packit |
1c1d7e |
defaultProtection = Public;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
<Start>module|program{BS_} { //
|
|
Packit |
1c1d7e |
v_type = V_IGNORE;
|
|
Packit |
1c1d7e |
if(yytext[0]=='m' || yytext[0]=='M')
|
|
Packit |
1c1d7e |
yy_push_state(Module);
|
|
Packit |
1c1d7e |
else
|
|
Packit |
1c1d7e |
yy_push_state(Program);
|
|
Packit |
1c1d7e |
defaultProtection = Public;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
<BlockData>^{BS}"end"({BS}(block{BS}data)({BS_}{ID})?)?{BS}/(\n|!) { // end block data
|
|
Packit |
1c1d7e |
//if (!endScope(current_root))
|
|
Packit |
1c1d7e |
// yyterminate();
|
|
Packit |
1c1d7e |
defaultProtection = Public;
|
|
Packit |
1c1d7e |
yy_pop_state();
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
<Start,ModuleBody,ModuleBodyContains>^{BS}"end"({BS}(module|program)({BS_}{ID})?)?{BS}/(\n|!) { // end module
|
|
Packit |
1c1d7e |
resolveModuleProcedures(moduleProcedures, current_root);
|
|
Packit |
1c1d7e |
if (!endScope(current_root))
|
|
Packit |
1c1d7e |
yyterminate();
|
|
Packit |
1c1d7e |
defaultProtection = Public;
|
|
Packit |
1c1d7e |
yy_pop_state();
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
<Module>{ID} {
|
|
Packit |
1c1d7e |
addModule(yytext, TRUE);
|
|
Packit |
1c1d7e |
BEGIN(ModuleBody);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
<Program>{ID} {
|
|
Packit |
1c1d7e |
addModule(yytext, FALSE);
|
|
Packit |
1c1d7e |
BEGIN(ModuleBody);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
/*------- access specification --------------------------------------------------------------------------*/
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
<ModuleBody>private/{BS}(\n|"!") { defaultProtection = Private;
|
|
Packit |
1c1d7e |
current->protection = defaultProtection ;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
<ModuleBody>public/{BS}(\n|"!") { defaultProtection = Public;
|
|
Packit |
1c1d7e |
current->protection = defaultProtection ;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
/*------- type definition -------------------------------------------------------------------------------*/
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
<Start,ModuleBody>^{BS}type/[^a-z0-9_] {
|
|
Packit |
1c1d7e |
if(YY_START == Start)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
addModule(NULL);
|
|
Packit |
1c1d7e |
yy_push_state(ModuleBody); //anon program
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
yy_push_state(Typedef);
|
|
Packit |
1c1d7e |
current->protection = defaultProtection;
|
|
Packit |
1c1d7e |
typeProtection = defaultProtection;
|
|
Packit |
1c1d7e |
typeMode = true;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
<Typedef>{
|
|
Packit |
1c1d7e |
{COMMA} {}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
{BS}"::"{BS} {}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
abstract {
|
|
Packit |
1c1d7e |
current->spec |= Entry::AbstractClass;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
extends{ARGS} {
|
|
Packit |
1c1d7e |
QCString basename = extractFromParens(yytext);
|
|
Packit |
1c1d7e |
current->extends->append(new BaseInfo(basename, Public, Normal));
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
public {
|
|
Packit |
1c1d7e |
current->protection = Public;
|
|
Packit |
1c1d7e |
typeProtection = Public;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
private {
|
|
Packit |
1c1d7e |
current->protection = Private;
|
|
Packit |
1c1d7e |
typeProtection = Private;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
{LANGUAGE_BIND_SPEC} {
|
|
Packit |
1c1d7e |
/* ignored for now */
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
{ID} { /* type name found */
|
|
Packit |
1c1d7e |
current->section = Entry::CLASS_SEC;
|
|
Packit |
1c1d7e |
current->spec |= Entry::Struct;
|
|
Packit |
1c1d7e |
current->name = yytext;
|
|
Packit |
1c1d7e |
current->fileName = yyFileName;
|
|
Packit |
1c1d7e |
current->bodyLine = yyLineNr;
|
|
Packit |
1c1d7e |
current->startLine = yyLineNr;
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
/* if type is part of a module, mod name is necessary for output */
|
|
Packit |
1c1d7e |
if ((current_root) &&
|
|
Packit |
1c1d7e |
(current_root->section == Entry::CLASS_SEC
|
|
Packit |
1c1d7e |
|| current_root->section == Entry::NAMESPACE_SEC))
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
current->name = current_root->name + "::" + current->name;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
addCurrentEntry(1);
|
|
Packit |
1c1d7e |
startScope(last_entry);
|
|
Packit |
1c1d7e |
BEGIN(TypedefBody);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
<TypedefBodyContains>{ /* Type Bound Procedures */
|
|
Packit |
1c1d7e |
^{BS}PROCEDURE{ARGS}? {
|
|
Packit |
1c1d7e |
current->type = QCString(yytext).simplifyWhiteSpace();
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
^{BS}final {
|
|
Packit |
1c1d7e |
current->spec |= Entry::Final;
|
|
Packit |
1c1d7e |
current->type = QCString(yytext).simplifyWhiteSpace();
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
^{BS}generic {
|
|
Packit |
1c1d7e |
current->type = QCString(yytext).simplifyWhiteSpace();
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
{COMMA} {
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
{ATTR_SPEC} {
|
|
Packit |
1c1d7e |
currentModifiers |= QCString(yytext);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
{BS}"::"{BS} {
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
{ID} {
|
|
Packit |
1c1d7e |
QCString name = yytext;
|
|
Packit |
1c1d7e |
modifiers[current_root][name.lower()] |= currentModifiers;
|
|
Packit |
1c1d7e |
current->section = Entry::FUNCTION_SEC;
|
|
Packit |
1c1d7e |
current->name = name;
|
|
Packit |
1c1d7e |
current->fileName = yyFileName;
|
|
Packit |
1c1d7e |
current->bodyLine = yyLineNr;
|
|
Packit |
1c1d7e |
current->startLine = yyLineNr;
|
|
Packit |
1c1d7e |
addCurrentEntry(1);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
{BS}"=>"[^(\n|\!)]* { /* Specific bindings come after the ID. */
|
|
Packit |
1c1d7e |
last_entry->args = yytext;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
"\n" {
|
|
Packit |
1c1d7e |
currentModifiers = SymbolModifiers();
|
|
Packit |
1c1d7e |
newLine();
|
|
Packit |
1c1d7e |
docBlock.resize(0);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
<TypedefBody,TypedefBodyContains>{
|
|
Packit |
1c1d7e |
^{BS}"end"{BS}"type"({BS_}{ID})?{BS}/(\n|!) { /* end type definition */
|
|
Packit |
1c1d7e |
last_entry->parent()->endBodyLine = yyLineNr;
|
|
Packit |
1c1d7e |
if (!endScope(current_root))
|
|
Packit |
1c1d7e |
yyterminate();
|
|
Packit |
1c1d7e |
typeMode = false;
|
|
Packit |
1c1d7e |
yy_pop_state();
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
/*------- module/global/typedef variable ---------------------------------------------------*/
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
<SubprogBody,SubprogBodyContains>^{BS}[0-9]*{BS}"end"({BS}{SUBPROG}({BS_}{ID})?)?{BS}/(\n|!) {
|
|
Packit |
1c1d7e |
//
|
|
Packit |
1c1d7e |
// ABSTRACT and specific interfaces are stored
|
|
Packit |
1c1d7e |
// in a scope of their own, even if multiple
|
|
Packit |
1c1d7e |
// are group in one INTERFACE/END INTERFACE block.
|
|
Packit |
1c1d7e |
//
|
|
Packit |
1c1d7e |
if (ifType == IF_ABSTRACT || ifType == IF_SPECIFIC)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
endScope(current_root);
|
|
Packit |
1c1d7e |
last_entry->endBodyLine = yyLineNr - 1;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
current_root->endBodyLine = yyLineNr - 1;
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
if (!endScope(current_root))
|
|
Packit |
1c1d7e |
yyterminate();
|
|
Packit |
1c1d7e |
subrCurrent.remove(0u);
|
|
Packit |
1c1d7e |
yy_pop_state() ;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
<BlockData>{
|
|
Packit |
1c1d7e |
{ID} {
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
<Start,ModuleBody,TypedefBody,SubprogBody>{
|
|
Packit |
1c1d7e |
^{BS}{TYPE_SPEC}/{SEPARATE} {
|
|
Packit |
1c1d7e |
current->bodyLine = yyLineNr + 1;
|
|
Packit |
1c1d7e |
current->endBodyLine = yyLineNr + lineCountPrepass;
|
|
Packit |
1c1d7e |
/* variable declaration starts */
|
|
Packit |
1c1d7e |
if(YY_START == Start)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
addModule(NULL);
|
|
Packit |
1c1d7e |
yy_push_state(ModuleBody); //anon program
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
argType = QCString(yytext).simplifyWhiteSpace().lower();
|
|
Packit |
1c1d7e |
yy_push_state(AttributeList);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
/* Dimitri: macro expansion should already be done during preprocessing not here!
|
|
Packit |
1c1d7e |
^{BS}{PP_ID}{KIND}? { // check for preprocessor symbol expand to type
|
|
Packit |
1c1d7e |
QCString str = yytext;
|
|
Packit |
1c1d7e |
str = str.stripWhiteSpace();
|
|
Packit |
1c1d7e |
//DefineDict* defines = getGlobalDefineDict();
|
|
Packit |
1c1d7e |
QCString name;
|
|
Packit |
1c1d7e |
int index = str.find("(");
|
|
Packit |
1c1d7e |
if (index != -1)
|
|
Packit |
1c1d7e |
name = str.left(index).stripWhiteSpace();
|
|
Packit |
1c1d7e |
else
|
|
Packit |
1c1d7e |
name = str;
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
Define *define = 0; //(*defines)[name];
|
|
Packit |
1c1d7e |
if (define != 0 && isTypeName(define->definition))
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
argType = str;
|
|
Packit |
1c1d7e |
yy_push_state(AttributeList);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
else
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
yyColNr -= (int)yyleng;
|
|
Packit |
1c1d7e |
REJECT;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
*/
|
|
Packit |
1c1d7e |
{EXTERNAL_STMT}/({BS}"::"|{BS_}{ID}) {
|
|
Packit |
1c1d7e |
/* external can be a "type" or an attribute */
|
|
Packit |
1c1d7e |
if(YY_START == Start)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
addModule(NULL);
|
|
Packit |
1c1d7e |
yy_push_state(ModuleBody); //anon program
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
QCString tmp = yytext;
|
|
Packit |
1c1d7e |
currentModifiers |= tmp.stripWhiteSpace();
|
|
Packit |
1c1d7e |
argType = QCString(yytext).simplifyWhiteSpace().lower();
|
|
Packit |
1c1d7e |
yy_push_state(AttributeList);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
{ATTR_STMT}/{BS_}{ID} |
|
|
Packit |
1c1d7e |
{ATTR_STMT}/{BS}"::" {
|
|
Packit |
1c1d7e |
/* attribute statement starts */
|
|
Packit |
1c1d7e |
DBG_CTX((stderr,"5=========> Attribute statement: %s\n", yytext));
|
|
Packit |
1c1d7e |
QCString tmp = yytext;
|
|
Packit |
1c1d7e |
currentModifiers |= tmp.stripWhiteSpace();
|
|
Packit |
1c1d7e |
argType="";
|
|
Packit |
1c1d7e |
yy_push_state(YY_START);
|
|
Packit |
1c1d7e |
BEGIN( AttributeList ) ;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
{ID} {
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
^{BS}"type"{BS_}"is"/{BS_} { }
|
|
Packit |
1c1d7e |
^{BS}"type"{BS}"=" { }
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
<AttributeList>{
|
|
Packit |
1c1d7e |
{COMMA} {}
|
|
Packit |
1c1d7e |
{BS} {}
|
|
Packit |
1c1d7e |
{ATTR_SPEC}. { /* update current modifiers when it is an ATTR_SPEC and not a variable name */
|
|
Packit |
1c1d7e |
/* bug_625519 */
|
|
Packit |
1c1d7e |
QChar chr = yytext[(int)yyleng-1];
|
|
Packit |
1c1d7e |
if (chr.isLetter() || chr.isDigit() || (chr == '_'))
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
yyColNr -= (int)yyleng;
|
|
Packit |
1c1d7e |
REJECT;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
else
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
QCString tmp = yytext;
|
|
Packit |
1c1d7e |
tmp = tmp.left(tmp.length() - 1);
|
|
Packit |
1c1d7e |
yyColNr -= 1;
|
|
Packit |
1c1d7e |
unput(yytext[(int)yyleng-1]);
|
|
Packit |
1c1d7e |
currentModifiers |= (tmp);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
"::" { /* end attribute list */
|
|
Packit |
1c1d7e |
BEGIN( Variable );
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
. { /* unknown attribute, consider variable name */
|
|
Packit |
1c1d7e |
//cout<<"start variables, unput "<<*yytext<
|
|
Packit |
1c1d7e |
yyColNr -= 1;
|
|
Packit |
1c1d7e |
unput(*yytext);
|
|
Packit |
1c1d7e |
BEGIN( Variable );
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
<Variable>{BS} { }
|
|
Packit |
1c1d7e |
<Variable>{ID} { /* parse variable declaration */
|
|
Packit |
1c1d7e |
//cout << "5=========> got variable: " << argType << "::" << yytext << endl;
|
|
Packit |
1c1d7e |
/* work around for bug in QCString.replace (QCString works) */
|
|
Packit |
1c1d7e |
QCString name=yytext;
|
|
Packit |
1c1d7e |
name = name.lower();
|
|
Packit |
1c1d7e |
/* remember attributes for the symbol */
|
|
Packit |
1c1d7e |
modifiers[current_root][name.lower()] |= currentModifiers;
|
|
Packit |
1c1d7e |
argName= name;
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
v_type= V_IGNORE;
|
|
Packit |
1c1d7e |
if (!argType.isEmpty() && current_root->section!=Entry::FUNCTION_SEC)
|
|
Packit |
1c1d7e |
{ // new variable entry
|
|
Packit |
1c1d7e |
v_type = V_VARIABLE;
|
|
Packit |
1c1d7e |
current->section = Entry::VARIABLE_SEC;
|
|
Packit |
1c1d7e |
current->name = argName;
|
|
Packit |
1c1d7e |
current->type = argType;
|
|
Packit |
1c1d7e |
current->fileName = yyFileName;
|
|
Packit |
1c1d7e |
current->bodyLine = yyLineNr; // used for source reference
|
|
Packit |
1c1d7e |
current->startLine = yyLineNr;
|
|
Packit |
1c1d7e |
addCurrentEntry(1);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
else if (!argType.isEmpty())
|
|
Packit |
1c1d7e |
{ // declaration of parameter list: add type for corr. parameter
|
|
Packit |
1c1d7e |
parameter = getParameter(argName);
|
|
Packit |
1c1d7e |
if (parameter)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
v_type= V_PARAMETER;
|
|
Packit |
1c1d7e |
if (!argType.isNull()) parameter->type=argType.stripWhiteSpace();
|
|
Packit |
1c1d7e |
if (!docBlock.isNull())
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
subrHandleCommentBlock(docBlock,TRUE);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
// save, it may be function return type
|
|
Packit |
1c1d7e |
if (parameter)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
modifiers[current_root][name.lower()].type = argType;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
else
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
if ((current_root->name.lower() == argName.lower()) ||
|
|
Packit |
1c1d7e |
(modifiers[current_root->parent()][current_root->name.lower()].returnName.lower() == argName.lower()))
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
int strt = current_root->type.find("function");
|
|
Packit |
1c1d7e |
QCString lft;
|
|
Packit |
1c1d7e |
QCString rght;
|
|
Packit |
1c1d7e |
if (strt != -1)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
v_type = V_RESULT;
|
|
Packit |
1c1d7e |
lft = "";
|
|
Packit |
1c1d7e |
rght = "";
|
|
Packit |
1c1d7e |
if (strt != 0) lft = current_root->type.left(strt).stripWhiteSpace();
|
|
Packit |
1c1d7e |
if ((current_root->type.length() - strt - strlen("function"))!= 0)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
rght = current_root->type.right(current_root->type.length() - strt - strlen("function")).stripWhiteSpace();
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
current_root->type = lft;
|
|
Packit |
1c1d7e |
if (rght.length() > 0)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
if (current_root->type.length() > 0) current_root->type += " ";
|
|
Packit |
1c1d7e |
current_root->type += rght;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
if (argType.stripWhiteSpace().length() > 0)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
if (current_root->type.length() > 0) current_root->type += " ";
|
|
Packit |
1c1d7e |
current_root->type += argType.stripWhiteSpace();
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
if (current_root->type.length() > 0) current_root->type += " ";
|
|
Packit |
1c1d7e |
current_root->type += "function";
|
|
Packit |
1c1d7e |
if (!docBlock.isNull())
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
subrHandleCommentBlockResult(docBlock,TRUE);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
else
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
current_root->type += " " + argType.stripWhiteSpace();
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
current_root->type = current_root->type.stripWhiteSpace();
|
|
Packit |
1c1d7e |
modifiers[current_root][name.lower()].type = current_root->type;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
else
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
modifiers[current_root][name.lower()].type = argType;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
// any accumulated doc for argument should be emptied,
|
|
Packit |
1c1d7e |
// because it is handled other way and this doc can be
|
|
Packit |
1c1d7e |
// unexpectedly passed to the next member.
|
|
Packit |
1c1d7e |
current->doc.resize(0);
|
|
Packit |
1c1d7e |
current->brief.resize(0);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
<Variable>{ARGS} { /* dimension of the previous entry. */
|
|
Packit |
1c1d7e |
QCString name(argName);
|
|
Packit |
1c1d7e |
QCString attr("dimension");
|
|
Packit |
1c1d7e |
attr += yytext;
|
|
Packit |
1c1d7e |
modifiers[current_root][name.lower()] |= attr;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
<Variable>{COMMA} { //printf("COMMA: %d<=..<=%d\n", yyColNr-(int)yyleng, yyColNr);
|
|
Packit |
1c1d7e |
// locate !< comment
|
|
Packit |
1c1d7e |
updateVariablePrepassComment(yyColNr-(int)yyleng, yyColNr);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
<Variable>{BS}"=" {
|
|
Packit |
1c1d7e |
yy_push_state(YY_START);
|
|
Packit |
1c1d7e |
initializer="=";
|
|
Packit |
1c1d7e |
initializerScope = initializerArrayScope = 0;
|
|
Packit |
1c1d7e |
BEGIN(Initialization);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
<Variable>"\n" { currentModifiers = SymbolModifiers();
|
|
Packit |
1c1d7e |
yy_pop_state(); // end variable declaration list
|
|
Packit |
1c1d7e |
newLine();
|
|
Packit |
1c1d7e |
docBlock.resize(0);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
<Variable>";".*"\n" { currentModifiers = SymbolModifiers();
|
|
Packit |
1c1d7e |
yy_pop_state(); // end variable declaration list
|
|
Packit |
1c1d7e |
docBlock.resize(0);
|
|
Packit |
1c1d7e |
inputStringSemi =(const char*)(QCString(" \n") + QCString(yytext+1)).data();
|
|
Packit |
1c1d7e |
yyLineNr--;
|
|
Packit |
1c1d7e |
pushBuffer(inputStringSemi);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
<*>";".*"\n" {
|
|
Packit |
1c1d7e |
if (YY_START == Variable) REJECT; // Just be on the safe side
|
|
Packit |
1c1d7e |
if (YY_START == String) REJECT; // ";" ignored in strings
|
|
Packit |
1c1d7e |
if (YY_START == StrIgnore) REJECT; // ";" ignored in regular comments
|
|
Packit |
1c1d7e |
inputStringSemi =(const char*)(QCString(" \n") + QCString(yytext+1)).data();
|
|
Packit |
1c1d7e |
yyLineNr--;
|
|
Packit |
1c1d7e |
pushBuffer(inputStringSemi);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
<Initialization,ArrayInitializer>"[" |
|
|
Packit |
1c1d7e |
<Initialization,ArrayInitializer>"(/" { initializer+=yytext;
|
|
Packit |
1c1d7e |
initializerArrayScope++;
|
|
Packit |
1c1d7e |
BEGIN(ArrayInitializer); // initializer may contain comma
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
<ArrayInitializer>"]" |
|
|
Packit |
1c1d7e |
<ArrayInitializer>"/)" { initializer+=yytext;
|
|
Packit |
1c1d7e |
initializerArrayScope--;
|
|
Packit |
1c1d7e |
if(initializerArrayScope<=0)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
initializerArrayScope = 0; // just in case
|
|
Packit |
1c1d7e |
BEGIN(Initialization);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
<ArrayInitializer>. { initializer+=yytext; }
|
|
Packit |
1c1d7e |
<Initialization>"(" { initializerScope++;
|
|
Packit |
1c1d7e |
initializer+=yytext;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
<Initialization>")" { initializerScope--;
|
|
Packit |
1c1d7e |
initializer+=yytext;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
<Initialization>{COMMA} { if (initializerScope == 0)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
updateVariablePrepassComment(yyColNr-(int)yyleng, yyColNr);
|
|
Packit |
1c1d7e |
yy_pop_state(); // end initialization
|
|
Packit |
1c1d7e |
if (v_type == V_VARIABLE) last_entry->initializer= initializer;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
else
|
|
Packit |
1c1d7e |
initializer+=", ";
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
<Initialization>"\n"|"!" { //|
|
|
Packit |
1c1d7e |
yy_pop_state(); // end initialization
|
|
Packit |
1c1d7e |
if (v_type == V_VARIABLE) last_entry->initializer= initializer;
|
|
Packit |
1c1d7e |
yyColNr -= 1;
|
|
Packit |
1c1d7e |
unput(*yytext);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
<Initialization>. { initializer+=yytext; }
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
/*------ fortran subroutine/function handling ------------------------------------------------------------*/
|
|
Packit |
1c1d7e |
/* Start is initial condition */
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
<Start,ModuleBody,SubprogBody,InterfaceBody,ModuleBodyContains,SubprogBodyContains>^{BS}({PREFIX}{BS_})?{TYPE_SPEC}{BS}({PREFIX}{BS_})?/{SUBPROG}{BS_} {
|
|
Packit |
1c1d7e |
if (ifType == IF_ABSTRACT || ifType == IF_SPECIFIC)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
addInterface("$interface$", ifType);
|
|
Packit |
1c1d7e |
startScope(last_entry);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
// TYPE_SPEC is for old function style function result
|
|
Packit |
1c1d7e |
result = QCString(yytext).stripWhiteSpace().lower();
|
|
Packit |
1c1d7e |
current->type = result;
|
|
Packit |
1c1d7e |
yy_push_state(SubprogPrefix);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
<SubprogPrefix>{BS}{SUBPROG}{BS_} {
|
|
Packit |
1c1d7e |
// Fortran subroutine or function found
|
|
Packit |
1c1d7e |
v_type = V_IGNORE;
|
|
Packit |
1c1d7e |
result=yytext;
|
|
Packit |
1c1d7e |
result=result.stripWhiteSpace();
|
|
Packit |
1c1d7e |
addSubprogram(result);
|
|
Packit |
1c1d7e |
BEGIN(Subprog);
|
|
Packit |
1c1d7e |
current->bodyLine = yyLineNr + lineCountPrepass + 1; // we have to be at the line after the definition and we have to take continuation lines into account.
|
|
Packit |
1c1d7e |
current->startLine = yyLineNr;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
<Start,ModuleBody,SubprogBody,InterfaceBody,ModuleBodyContains,SubprogBodyContains>^{BS}({PREFIX}{BS_})?{SUBPROG}{BS_} {
|
|
Packit |
1c1d7e |
// Fortran subroutine or function found
|
|
Packit |
1c1d7e |
v_type = V_IGNORE;
|
|
Packit |
1c1d7e |
if (ifType == IF_ABSTRACT || ifType == IF_SPECIFIC)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
addInterface("$interface$", ifType);
|
|
Packit |
1c1d7e |
startScope(last_entry);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
result = QCString(yytext).stripWhiteSpace();
|
|
Packit |
1c1d7e |
addSubprogram(result);
|
|
Packit |
1c1d7e |
yy_push_state(Subprog);
|
|
Packit |
1c1d7e |
current->bodyLine = yyLineNr + lineCountPrepass + 1; // we have to be at the line after the definition and we have to take continuation lines into account.
|
|
Packit |
1c1d7e |
current->startLine = yyLineNr;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
<Subprog>{BS} { /* ignore white space */ }
|
|
Packit |
1c1d7e |
<Subprog>{ID} { current->name = yytext;
|
|
Packit |
1c1d7e |
//cout << "1a==========> got " << current->type << " " << yytext << " " << yyLineNr << endl;
|
|
Packit |
1c1d7e |
modifiers[current_root][current->name.lower()].returnName = current->name.lower();
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
if (ifType == IF_ABSTRACT || ifType == IF_SPECIFIC)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
current_root->name.replace(QRegExp("\\$interface\\$"), yytext);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
BEGIN(Parameterlist);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
<Parameterlist>"(" { current->args = "("; }
|
|
Packit |
1c1d7e |
<Parameterlist>")" {
|
|
Packit |
1c1d7e |
current->args += ")";
|
|
Packit |
1c1d7e |
current->args = removeRedundantWhiteSpace(current->args);
|
|
Packit |
1c1d7e |
addCurrentEntry(1);
|
|
Packit |
1c1d7e |
startScope(last_entry);
|
|
Packit |
1c1d7e |
BEGIN(SubprogBody);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
<Parameterlist>{COMMA}|{BS} { current->args += yytext;
|
|
Packit |
1c1d7e |
CommentInPrepass *c = locatePrepassComment(yyColNr-(int)yyleng, yyColNr);
|
|
Packit |
1c1d7e |
if (c!=NULL) {
|
|
Packit |
1c1d7e |
if(current->argList->count()>0) {
|
|
Packit |
1c1d7e |
current->argList->at(current->argList->count()-1)->docs = c->str;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
<Parameterlist>{ID} {
|
|
Packit |
1c1d7e |
//current->type not yet available
|
|
Packit |
1c1d7e |
QCString param = yytext;
|
|
Packit |
1c1d7e |
// std::cout << "3=========> got parameter " << param << std::endl;
|
|
Packit |
1c1d7e |
current->args += param;
|
|
Packit |
1c1d7e |
Argument *arg = new Argument;
|
|
Packit |
1c1d7e |
arg->name = param;
|
|
Packit |
1c1d7e |
arg->type = "";
|
|
Packit |
1c1d7e |
current->argList->append(arg);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
<Parameterlist>{NOARGS} {
|
|
Packit |
1c1d7e |
newLine();
|
|
Packit |
1c1d7e |
//printf("3=========> without parameterlist \n");
|
|
Packit |
1c1d7e |
//current->argList = ;
|
|
Packit |
1c1d7e |
addCurrentEntry(1);
|
|
Packit |
1c1d7e |
startScope(last_entry);
|
|
Packit |
1c1d7e |
BEGIN(SubprogBody);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
<SubprogBody>result{BS}\({BS}{ID} {
|
|
Packit |
1c1d7e |
if (functionLine)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
result= yytext;
|
|
Packit |
1c1d7e |
result= result.right(result.length()-result.find("(")-1);
|
|
Packit |
1c1d7e |
result= result.stripWhiteSpace();
|
|
Packit |
1c1d7e |
modifiers[current_root->parent()][current_root->name.lower()].returnName = result;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
//cout << "=====> got result " << result << endl;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
/*---- documentation comments --------------------------------------------------------------------*/
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
<Variable,SubprogBody,ModuleBody,TypedefBody,TypedefBodyContains>"!<" { /* backward docu comment */
|
|
Packit |
1c1d7e |
if (v_type != V_IGNORE) {
|
|
Packit |
1c1d7e |
current->docLine = yyLineNr;
|
|
Packit |
1c1d7e |
docBlockJavaStyle = FALSE;
|
|
Packit |
1c1d7e |
docBlock.resize(0);
|
|
Packit |
1c1d7e |
docBlockJavaStyle = Config_getBool(JAVADOC_AUTOBRIEF);
|
|
Packit |
1c1d7e |
startCommentBlock(TRUE);
|
|
Packit |
1c1d7e |
yy_push_state(DocBackLine);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
else
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
/* handle out of place !< comment as a normal comment */
|
|
Packit |
1c1d7e |
if (YY_START == String) { yyColNr -= (int)yyleng; REJECT; } // "!" is ignored in strings
|
|
Packit |
1c1d7e |
// skip comment line (without docu comments "!>" "!<" )
|
|
Packit |
1c1d7e |
/* ignore further "!" and ignore comments in Strings */
|
|
Packit |
1c1d7e |
if ((YY_START != StrIgnore) && (YY_START != String))
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
yy_push_state(YY_START);
|
|
Packit |
1c1d7e |
BEGIN(StrIgnore);
|
|
Packit |
1c1d7e |
debugStr="*!";
|
|
Packit |
1c1d7e |
//fprintf(stderr,"start comment %d\n",yyLineNr);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
<DocBackLine>.* { // contents of current comment line
|
|
Packit |
1c1d7e |
docBlock+=yytext;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
<DocBackLine>"\n"{BS}"!"("<"|"!"+) { // comment block (next line is also comment line)
|
|
Packit |
1c1d7e |
docBlock+="\n"; // \n is necessary for lists
|
|
Packit |
1c1d7e |
newLine();
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
<DocBackLine>"\n" { // comment block ends at the end of this line
|
|
Packit |
1c1d7e |
//cout <<"3=========> comment block : "<< docBlock << endl;
|
|
Packit |
1c1d7e |
yyColNr -= 1;
|
|
Packit |
1c1d7e |
unput(*yytext);
|
|
Packit |
1c1d7e |
if (v_type == V_VARIABLE)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
Entry *tmp_entry = current;
|
|
Packit |
1c1d7e |
current = last_entry; // temporarily switch to the previous entry
|
|
Packit |
1c1d7e |
handleCommentBlock(docBlock,TRUE);
|
|
Packit |
1c1d7e |
current=tmp_entry;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
else if (v_type == V_PARAMETER)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
subrHandleCommentBlock(docBlock,TRUE);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
else if (v_type == V_RESULT)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
subrHandleCommentBlockResult(docBlock,TRUE);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
yy_pop_state();
|
|
Packit |
1c1d7e |
docBlock.resize(0);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
<Start,SubprogBody,ModuleBody,TypedefBody,InterfaceBody,ModuleBodyContains,SubprogBodyContains,TypedefBodyContains>"!>" {
|
|
Packit |
1c1d7e |
yy_push_state(YY_START);
|
|
Packit |
1c1d7e |
current->docLine = yyLineNr;
|
|
Packit |
1c1d7e |
docBlockJavaStyle = FALSE;
|
|
Packit |
1c1d7e |
if (YY_START==SubprogBody) docBlockInBody = TRUE;
|
|
Packit |
1c1d7e |
docBlock.resize(0);
|
|
Packit |
1c1d7e |
docBlockJavaStyle = Config_getBool(JAVADOC_AUTOBRIEF);
|
|
Packit |
1c1d7e |
startCommentBlock(TRUE);
|
|
Packit |
1c1d7e |
BEGIN(DocBlock);
|
|
Packit |
1c1d7e |
//cout << "start DocBlock " << endl;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
<DocBlock>.* { // contents of current comment line
|
|
Packit |
1c1d7e |
docBlock+=yytext;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
<DocBlock>"\n"{BS}"!"(">"|"!"+) { // comment block (next line is also comment line)
|
|
Packit |
1c1d7e |
docBlock+="\n"; // \n is necessary for lists
|
|
Packit |
1c1d7e |
newLine();
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
<DocBlock>"\n" { // comment block ends at the end of this line
|
|
Packit |
1c1d7e |
//cout <<"3=========> comment block : "<< docBlock << endl;
|
|
Packit |
1c1d7e |
yyColNr -= 1;
|
|
Packit |
1c1d7e |
unput(*yytext);
|
|
Packit |
1c1d7e |
handleCommentBlock(docBlock,TRUE);
|
|
Packit |
1c1d7e |
yy_pop_state();
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
/*-----Prototype parsing -------------------------------------------------------------------------*/
|
|
Packit |
1c1d7e |
<Prototype>{BS}{SUBPROG}{BS_} {
|
|
Packit |
1c1d7e |
BEGIN(PrototypeSubprog);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
<Prototype,PrototypeSubprog>{BS}{SCOPENAME}?{BS}{ID} {
|
|
Packit |
1c1d7e |
current->name = QCString(yytext).lower();
|
|
Packit |
1c1d7e |
current->name.stripWhiteSpace();
|
|
Packit |
1c1d7e |
BEGIN(PrototypeArgs);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
<PrototypeArgs>{
|
|
Packit |
1c1d7e |
"("|")"|","|{BS_} { current->args += yytext; }
|
|
Packit |
1c1d7e |
{ID} { current->args += yytext;
|
|
Packit |
1c1d7e |
Argument *a = new Argument;
|
|
Packit |
1c1d7e |
a->name = QCString(yytext).lower();
|
|
Packit |
1c1d7e |
current->argList->append(a);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
/*------------------------------------------------------------------------------------------------*/
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
<*>"\n" {
|
|
Packit |
1c1d7e |
newLine();
|
|
Packit |
1c1d7e |
//if (debugStr.stripWhiteSpace().length() > 0) cout << "ignored text: " << debugStr << " state: " <
|
|
Packit |
1c1d7e |
debugStr="";
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
/*---- error: EOF in wrong state --------------------------------------------------------------------*/
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
<*><<EOF>> {
|
|
Packit |
1c1d7e |
if (parsingPrototype) {
|
|
Packit |
1c1d7e |
yyterminate();
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
} else if ( include_stack_ptr <= 0 ) {
|
|
Packit |
1c1d7e |
if (YY_START!=INITIAL && YY_START!=Start) {
|
|
Packit |
1c1d7e |
DBG_CTX((stderr,"==== Error: EOF reached in wrong state (end missing)"));
|
|
Packit |
1c1d7e |
scanner_abort();
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
yyterminate();
|
|
Packit |
1c1d7e |
} else {
|
|
Packit |
1c1d7e |
popBuffer();
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
<*>{LOG_OPER} { // Fortran logical comparison keywords
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
<*>. {
|
|
Packit |
1c1d7e |
//debugStr+=yytext;
|
|
Packit |
1c1d7e |
//printf("I:%c\n", *yytext);
|
|
Packit |
1c1d7e |
} // ignore remaining text
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
/**********************************************************************************/
|
|
Packit |
1c1d7e |
/**********************************************************************************/
|
|
Packit |
1c1d7e |
/**********************************************************************************/
|
|
Packit |
1c1d7e |
%%
|
|
Packit |
1c1d7e |
//----------------------------------------------------------------------------
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
#if 0
|
|
Packit |
1c1d7e |
static void extractPrefix(QCString &text)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
int prefixIndex = 0;
|
|
Packit |
1c1d7e |
int curIndex = 0;
|
|
Packit |
1c1d7e |
bool cont = TRUE;
|
|
Packit |
1c1d7e |
const char* pre[] = {"RECURSIVE","IMPURE","PURE","ELEMENTAL"};
|
|
Packit |
1c1d7e |
while(cont)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
cont = FALSE;
|
|
Packit |
1c1d7e |
for(unsigned int i=0; i<4; i++)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
if((prefixIndex=text.find(pre[i], curIndex, FALSE))==0)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
text.remove(0,strlen(pre[i]));
|
|
Packit |
1c1d7e |
text.stripWhiteSpace();
|
|
Packit |
1c1d7e |
cont = TRUE;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
#endif
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
static void newLine() {
|
|
Packit |
1c1d7e |
yyLineNr++;
|
|
Packit |
1c1d7e |
yyLineNr+=lineCountPrepass;
|
|
Packit |
1c1d7e |
lineCountPrepass=0;
|
|
Packit |
1c1d7e |
comments.clear();
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
static CommentInPrepass* locatePrepassComment(int from, int to) {
|
|
Packit |
1c1d7e |
//printf("Locate %d-%d\n", from, to);
|
|
Packit |
1c1d7e |
for(uint i=0; i
|
|
Packit |
1c1d7e |
int c = comments.at(i)->column;
|
|
Packit |
1c1d7e |
//printf("Candidate %d\n", c);
|
|
Packit |
1c1d7e |
if (c>=from && c<=to) {
|
|
Packit |
1c1d7e |
// comment for previous variable or parameter
|
|
Packit |
1c1d7e |
return comments.at(i);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
return NULL;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
static void updateVariablePrepassComment(int from, int to) {
|
|
Packit |
1c1d7e |
CommentInPrepass *c = locatePrepassComment(from, to);
|
|
Packit |
1c1d7e |
if (c!=NULL && v_type == V_VARIABLE) {
|
|
Packit |
1c1d7e |
last_entry->brief = c->str;
|
|
Packit |
1c1d7e |
} else if (c!=NULL && v_type == V_PARAMETER) {
|
|
Packit |
1c1d7e |
Argument *parameter = getParameter(argName);
|
|
Packit |
1c1d7e |
if (parameter) parameter->docs = c->str;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
static int getAmpersandAtTheStart(const char *buf, int length)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
for(int i=0; i
|
|
Packit |
1c1d7e |
switch(buf[i]) {
|
|
Packit |
1c1d7e |
case ' ':
|
|
Packit |
1c1d7e |
case '\t':
|
|
Packit |
1c1d7e |
break;
|
|
Packit |
1c1d7e |
case '&':
|
|
Packit |
1c1d7e |
return i;
|
|
Packit |
1c1d7e |
default:
|
|
Packit |
1c1d7e |
return -1;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
return -1;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
/* Returns ampersand index, comment start index or -1 if neither exist.*/
|
|
Packit |
1c1d7e |
static int getAmpOrExclAtTheEnd(const char *buf, int length, char ch)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
// Avoid ampersands in string and comments
|
|
Packit |
1c1d7e |
int parseState = Start;
|
|
Packit |
1c1d7e |
char quoteSymbol = 0;
|
|
Packit |
1c1d7e |
int ampIndex = -1;
|
|
Packit |
1c1d7e |
int commentIndex = -1;
|
|
Packit |
1c1d7e |
quoteSymbol = ch;
|
|
Packit |
1c1d7e |
if (ch != '\0') parseState = String;
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
for(int i=0; i
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
// When in string, skip backslashes
|
|
Packit |
1c1d7e |
// Legacy code, not sure whether this is correct?
|
|
Packit |
1c1d7e |
if(parseState==String)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
if(buf[i]=='\\') i++;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
switch(buf[i])
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
case '\'':
|
|
Packit |
1c1d7e |
case '"':
|
|
Packit |
1c1d7e |
// Close string, if quote symbol matches.
|
|
Packit |
1c1d7e |
// Quote symbol is set iff parseState==String
|
|
Packit |
1c1d7e |
if(buf[i]==quoteSymbol)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
parseState = Start;
|
|
Packit |
1c1d7e |
quoteSymbol = 0;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
// Start new string, if not already in string or comment
|
|
Packit |
1c1d7e |
else if(parseState==Start)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
parseState = String;
|
|
Packit |
1c1d7e |
quoteSymbol = buf[i];
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
ampIndex = -1; // invalidate prev ampersand
|
|
Packit |
1c1d7e |
break;
|
|
Packit |
1c1d7e |
case '!':
|
|
Packit |
1c1d7e |
// When in string or comment, ignore exclamation mark
|
|
Packit |
1c1d7e |
if(parseState==Start)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
parseState = Comment;
|
|
Packit |
1c1d7e |
commentIndex = i;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
break;
|
|
Packit |
1c1d7e |
case ' ': // ignore whitespace
|
|
Packit |
1c1d7e |
case '\t':
|
|
Packit |
1c1d7e |
case '\n': // this may be at the end of line
|
|
Packit |
1c1d7e |
break;
|
|
Packit |
1c1d7e |
case '&':
|
|
Packit |
1c1d7e |
ampIndex = i;
|
|
Packit |
1c1d7e |
break;
|
|
Packit |
1c1d7e |
default:
|
|
Packit |
1c1d7e |
ampIndex = -1; // invalidate prev ampersand
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
if (ampIndex>=0)
|
|
Packit |
1c1d7e |
return ampIndex;
|
|
Packit |
1c1d7e |
else
|
|
Packit |
1c1d7e |
return commentIndex;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
/* Although comments at the end of continuation line are grabbed by this function,
|
|
Packit |
1c1d7e |
* we still do not know how to use them later in parsing.
|
|
Packit |
1c1d7e |
*/
|
|
Packit |
1c1d7e |
void truncatePrepass(int index)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
int length = inputStringPrepass.length();
|
|
Packit |
1c1d7e |
for (int i=index+1; i
|
|
Packit |
1c1d7e |
if (inputStringPrepass[i]=='!' && i
|
|
Packit |
1c1d7e |
struct CommentInPrepass *c=new CommentInPrepass(index, inputStringPrepass.right(length-i-2));
|
|
Packit |
1c1d7e |
comments.append(c);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
inputStringPrepass.truncate(index);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
// simplified way to know if this is fixed form
|
|
Packit |
1c1d7e |
// duplicate in fortrancode.l
|
|
Packit |
1c1d7e |
bool recognizeFixedForm(const char* contents, FortranFormat format)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
int column=0;
|
|
Packit |
1c1d7e |
bool skipLine=FALSE;
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
if (format == FortranFormat_Fixed) return TRUE;
|
|
Packit |
1c1d7e |
if (format == FortranFormat_Free) return FALSE;
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
for(int i=0;;i++) {
|
|
Packit |
1c1d7e |
column++;
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
switch(contents[i]) {
|
|
Packit |
1c1d7e |
case '\n':
|
|
Packit |
1c1d7e |
column=0;
|
|
Packit |
1c1d7e |
skipLine=FALSE;
|
|
Packit |
1c1d7e |
break;
|
|
Packit |
1c1d7e |
case ' ':
|
|
Packit |
1c1d7e |
break;
|
|
Packit |
1c1d7e |
case '\000':
|
|
Packit |
1c1d7e |
return FALSE;
|
|
Packit |
1c1d7e |
case '#':
|
|
Packit |
1c1d7e |
skipLine=TRUE;
|
|
Packit |
1c1d7e |
break;
|
|
Packit |
1c1d7e |
case 'C':
|
|
Packit |
1c1d7e |
case 'c':
|
|
Packit |
1c1d7e |
case '*':
|
|
Packit |
1c1d7e |
if(column==1) return TRUE;
|
|
Packit |
1c1d7e |
if(skipLine) break;
|
|
Packit |
1c1d7e |
return FALSE;
|
|
Packit |
1c1d7e |
case '!':
|
|
Packit |
1c1d7e |
if(column>1 && column<7) return FALSE;
|
|
Packit |
1c1d7e |
skipLine=TRUE;
|
|
Packit |
1c1d7e |
break;
|
|
Packit |
1c1d7e |
default:
|
|
Packit |
1c1d7e |
if(skipLine) break;
|
|
Packit |
1c1d7e |
if(column==7) return TRUE;
|
|
Packit |
1c1d7e |
return FALSE;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
return FALSE;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
/* This function assumes that contents has at least size=length+1 */
|
|
Packit |
1c1d7e |
static void insertCharacter(char *contents, int length, int pos, char c)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
// shift tail by one character
|
|
Packit |
1c1d7e |
for(int i=length; i>pos; i--)
|
|
Packit |
1c1d7e |
contents[i]=contents[i-1];
|
|
Packit |
1c1d7e |
// set the character
|
|
Packit |
1c1d7e |
contents[pos] = c;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
/* change comments and bring line continuation character to previous line */
|
|
Packit |
1c1d7e |
/* also used to set continuation marks in case of fortran code usage, done here as it is quite complicated code */
|
|
Packit |
1c1d7e |
const char* prepassFixedForm(const char* contents, int *hasContLine)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
int column=0;
|
|
Packit |
1c1d7e |
int prevLineLength=0;
|
|
Packit |
1c1d7e |
int prevLineAmpOrExclIndex=-1;
|
|
Packit |
1c1d7e |
char prevQuote = '\0';
|
|
Packit |
1c1d7e |
char thisQuote = '\0';
|
|
Packit |
1c1d7e |
bool emptyLabel=TRUE;
|
|
Packit |
1c1d7e |
bool commented=FALSE;
|
|
Packit |
1c1d7e |
bool inSingle=FALSE;
|
|
Packit |
1c1d7e |
bool inDouble=FALSE;
|
|
Packit |
1c1d7e |
bool inBackslash=FALSE;
|
|
Packit |
1c1d7e |
bool fullCommentLine=TRUE;
|
|
Packit |
1c1d7e |
int newContentsSize = strlen(contents)+3; // \000, \n (when necessary) and one spare character (to avoid reallocation)
|
|
Packit |
1c1d7e |
char* newContents = (char*)malloc(newContentsSize);
|
|
Packit |
1c1d7e |
int curLine = 1;
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
for(int i=0, j=0;;i++,j++) {
|
|
Packit |
1c1d7e |
if(j>=newContentsSize-3) { // check for spare characters, which may be eventually used below (by & and '! ')
|
|
Packit |
1c1d7e |
newContents = (char*)realloc(newContents, newContentsSize+1000);
|
|
Packit |
1c1d7e |
newContentsSize = newContentsSize+1000;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
column++;
|
|
Packit |
1c1d7e |
char c = contents[i];
|
|
Packit |
1c1d7e |
switch(c) {
|
|
Packit |
1c1d7e |
case '\n':
|
|
Packit |
1c1d7e |
if (!fullCommentLine)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
prevLineLength=column;
|
|
Packit |
1c1d7e |
prevLineAmpOrExclIndex=getAmpOrExclAtTheEnd(&contents[i-prevLineLength+1], prevLineLength,prevQuote);
|
|
Packit |
1c1d7e |
if (prevLineAmpOrExclIndex == -1) prevLineAmpOrExclIndex = column - 1;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
else
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
prevLineLength+=column;
|
|
Packit |
1c1d7e |
/* Even though a full comment line is not really a comment line it can be seen as one. An empty line is also seen as a comment line (small bonus) */
|
|
Packit |
1c1d7e |
if (hasContLine)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
hasContLine[curLine - 1] = 1;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
fullCommentLine=TRUE;
|
|
Packit |
1c1d7e |
column=0;
|
|
Packit |
1c1d7e |
emptyLabel=TRUE;
|
|
Packit |
1c1d7e |
commented=FALSE;
|
|
Packit |
1c1d7e |
newContents[j]=c;
|
|
Packit |
1c1d7e |
prevQuote = thisQuote;
|
|
Packit |
1c1d7e |
curLine++;
|
|
Packit |
1c1d7e |
break;
|
|
Packit |
1c1d7e |
case ' ':
|
|
Packit |
1c1d7e |
case '\t':
|
|
Packit |
1c1d7e |
newContents[j]=c;
|
|
Packit |
1c1d7e |
break;
|
|
Packit |
1c1d7e |
case '\000':
|
|
Packit |
1c1d7e |
if (hasContLine)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
free(newContents);
|
|
Packit |
1c1d7e |
return NULL;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
newContents[j]='\000';
|
|
Packit |
1c1d7e |
newContentsSize = strlen(newContents);
|
|
Packit |
1c1d7e |
if (newContents[newContentsSize - 1] != '\n')
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
// to be on the safe side
|
|
Packit |
1c1d7e |
newContents = (char*)realloc(newContents, newContentsSize+2);
|
|
Packit |
1c1d7e |
newContents[newContentsSize] = '\n';
|
|
Packit |
1c1d7e |
newContents[newContentsSize + 1] = '\000';
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
return newContents;
|
|
Packit |
1c1d7e |
case '"':
|
|
Packit |
1c1d7e |
case '\'':
|
|
Packit |
1c1d7e |
case '\\':
|
|
Packit |
1c1d7e |
if ((column <= fixedCommentAfter) && (column!=6) && !commented)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
// we have some special cases in respect to strings and escaped string characters
|
|
Packit |
1c1d7e |
fullCommentLine=FALSE;
|
|
Packit |
1c1d7e |
newContents[j]=c;
|
|
Packit |
1c1d7e |
if (c == '\\')
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
inBackslash = !inBackslash;
|
|
Packit |
1c1d7e |
break;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
else if (c == '\'')
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
if (!inDouble)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
inSingle = !inSingle;
|
|
Packit |
1c1d7e |
if (inSingle) thisQuote = c;
|
|
Packit |
1c1d7e |
else thisQuote = '\0';
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
break;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
else if (c == '"')
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
if (!inSingle)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
inDouble = !inDouble;
|
|
Packit |
1c1d7e |
if (inDouble) thisQuote = c;
|
|
Packit |
1c1d7e |
else thisQuote = '\0';
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
break;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
inBackslash = FALSE;
|
|
Packit |
1c1d7e |
// fallthrough
|
|
Packit |
1c1d7e |
case 'C':
|
|
Packit |
1c1d7e |
case 'c':
|
|
Packit |
1c1d7e |
case '*':
|
|
Packit |
1c1d7e |
case '!':
|
|
Packit |
1c1d7e |
if ((column <= fixedCommentAfter) && (column!=6))
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
emptyLabel=FALSE;
|
|
Packit |
1c1d7e |
if(column==1)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
newContents[j]='!';
|
|
Packit |
1c1d7e |
commented = TRUE;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
else if ((c == '!') && !inDouble && !inSingle)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
newContents[j]=c;
|
|
Packit |
1c1d7e |
commented = TRUE;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
else
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
if (!commented) fullCommentLine=FALSE;
|
|
Packit |
1c1d7e |
newContents[j]=c;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
break;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
// fallthrough
|
|
Packit |
1c1d7e |
default:
|
|
Packit |
1c1d7e |
if(column==6 && emptyLabel) { // continuation
|
|
Packit |
1c1d7e |
if (!commented) fullCommentLine=FALSE;
|
|
Packit |
1c1d7e |
if (c != '0') { // 0 not allowed as continuation character, see f95 standard paragraph 3.3.2.3
|
|
Packit |
1c1d7e |
newContents[j]=' ';
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
if(prevLineAmpOrExclIndex==-1) { // add & just before end of previous line
|
|
Packit |
1c1d7e |
/* first line is not a continuation line in code, just in snippets etc. */
|
|
Packit |
1c1d7e |
if (curLine != 1) insertCharacter(newContents, j+1, (j+1)-6-1, '&';;
|
|
Packit |
1c1d7e |
j++;
|
|
Packit |
1c1d7e |
} else { // add & just before end of previous line comment
|
|
Packit |
1c1d7e |
/* first line is not a continuation line in code, just in snippets etc. */
|
|
Packit |
1c1d7e |
if (curLine != 1) insertCharacter(newContents, j+1, (j+1)-6-prevLineLength+prevLineAmpOrExclIndex, '&';;
|
|
Packit |
1c1d7e |
j++;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
if (hasContLine) hasContLine[curLine - 1] = 1;
|
|
Packit |
1c1d7e |
} else {
|
|
Packit |
1c1d7e |
newContents[j]=c; // , just handle like space
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
prevLineLength=0;
|
|
Packit |
1c1d7e |
} else if ((column > fixedCommentAfter) && !commented) {
|
|
Packit |
1c1d7e |
// first non commented non blank character after position fixedCommentAfter
|
|
Packit |
1c1d7e |
if (c != '!') {
|
|
Packit |
1c1d7e |
// I'm not a possible start of doxygen comment
|
|
Packit |
1c1d7e |
newContents[j++]='!';
|
|
Packit |
1c1d7e |
newContents[j++]=' '; // so that '<' and '>' as first character are not converted to doxygen comment
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
newContents[j]=c;
|
|
Packit |
1c1d7e |
commented = TRUE;
|
|
Packit |
1c1d7e |
} else {
|
|
Packit |
1c1d7e |
if (!commented) fullCommentLine=FALSE;
|
|
Packit |
1c1d7e |
newContents[j]=c;
|
|
Packit |
1c1d7e |
emptyLabel=FALSE;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
break;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
if (hasContLine)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
free(newContents);
|
|
Packit |
1c1d7e |
return NULL;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
newContentsSize = strlen(newContents);
|
|
Packit |
1c1d7e |
if (newContents[newContentsSize - 1] != '\n')
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
// to be on the safe side
|
|
Packit |
1c1d7e |
newContents = (char*)realloc(newContents, newContentsSize+2);
|
|
Packit |
1c1d7e |
newContents[newContentsSize] = '\n';
|
|
Packit |
1c1d7e |
newContents[newContentsSize + 1] = '\000';
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
return newContents;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
static void pushBuffer(QCString& buffer)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
if (include_stack_cnt <= include_stack_ptr)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
include_stack_cnt++;
|
|
Packit |
1c1d7e |
include_stack = (YY_BUFFER_STATE *)realloc(include_stack, include_stack_cnt * sizeof(YY_BUFFER_STATE));
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
include_stack[include_stack_ptr++] = YY_CURRENT_BUFFER;
|
|
Packit |
1c1d7e |
yy_switch_to_buffer(yy_scan_string(buffer));
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
DBG_CTX((stderr, "--PUSH--%s", (const char *)buffer));
|
|
Packit |
1c1d7e |
buffer = NULL;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
static void popBuffer() {
|
|
Packit |
1c1d7e |
DBG_CTX((stderr, "--POP--"));
|
|
Packit |
1c1d7e |
include_stack_ptr --;
|
|
Packit |
1c1d7e |
yy_delete_buffer( YY_CURRENT_BUFFER );
|
|
Packit |
1c1d7e |
yy_switch_to_buffer( include_stack[include_stack_ptr] );
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
/** used to copy entry to an interface module procedure */
|
|
Packit |
1c1d7e |
static void copyEntry(Entry *dest, Entry *src)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
dest->type = src->type;
|
|
Packit |
1c1d7e |
dest->fileName = src->fileName;
|
|
Packit |
1c1d7e |
dest->startLine = src->startLine;
|
|
Packit |
1c1d7e |
dest->bodyLine = src->bodyLine;
|
|
Packit |
1c1d7e |
dest->endBodyLine = src->endBodyLine;
|
|
Packit |
1c1d7e |
dest->args = src->args;
|
|
Packit |
1c1d7e |
dest->argList = new ArgumentList(*src->argList);
|
|
Packit |
1c1d7e |
dest->doc = src->doc;
|
|
Packit |
1c1d7e |
dest->brief = src->brief;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
/** fill empty interface module procedures with info from
|
|
Packit |
1c1d7e |
corresponding module subprogs
|
|
Packit |
1c1d7e |
@TODO: handle procedures in used modules
|
|
Packit |
1c1d7e |
*/
|
|
Packit |
1c1d7e |
void resolveModuleProcedures(QList<Entry> &moduleProcedures, Entry *current_root)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
if (moduleProcedures.isEmpty()) return;
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
EntryListIterator eli1(moduleProcedures);
|
|
Packit |
1c1d7e |
// for all module procedures
|
|
Packit |
1c1d7e |
for (Entry *ce1; (ce1=eli1.current()); ++eli1)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
// check all entries in this module
|
|
Packit |
1c1d7e |
EntryListIterator eli2(*current_root->children());
|
|
Packit |
1c1d7e |
for (Entry *ce2; (ce2=eli2.current()); ++eli2)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
if (ce1->name == ce2->name)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
copyEntry(ce1, ce2);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
} // for procedures in current module
|
|
Packit |
1c1d7e |
} // for all interface module procedures
|
|
Packit |
1c1d7e |
moduleProcedures.clear();
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
#if 0
|
|
Packit |
1c1d7e |
static bool isTypeName(QCString name)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
name = name.lower();
|
|
Packit |
1c1d7e |
return name=="integer" || name == "real" ||
|
|
Packit |
1c1d7e |
name=="complex" || name == "logical";
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
#endif
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
/*! Extracts string which resides within parentheses of provided string. */
|
|
Packit |
1c1d7e |
static QCString extractFromParens(const QCString name)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
QCString extracted = name;
|
|
Packit |
1c1d7e |
int start = extracted.find("(");
|
|
Packit |
1c1d7e |
if (start != -1)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
extracted.remove(0, start+1);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
int end = extracted.findRev(")");
|
|
Packit |
1c1d7e |
if (end != -1)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
int length = extracted.length();
|
|
Packit |
1c1d7e |
extracted.remove(end, length);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
extracted = extracted.stripWhiteSpace();
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
return extracted;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
/*! Adds passed modifiers to these modifiers.*/
|
|
Packit |
1c1d7e |
SymbolModifiers& SymbolModifiers::operator|=(const SymbolModifiers &mdfs)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
if (mdfs.protection!=NONE_P) protection = mdfs.protection;
|
|
Packit |
1c1d7e |
if (mdfs.direction!=NONE_D) direction = mdfs.direction;
|
|
Packit |
1c1d7e |
optional |= mdfs.optional;
|
|
Packit |
1c1d7e |
if (!mdfs.dimension.isNull()) dimension = mdfs.dimension;
|
|
Packit |
1c1d7e |
allocatable |= mdfs.allocatable;
|
|
Packit |
1c1d7e |
external |= mdfs.external;
|
|
Packit |
1c1d7e |
intrinsic |= mdfs.intrinsic;
|
|
Packit |
1c1d7e |
protect |= mdfs.protect;
|
|
Packit |
1c1d7e |
parameter |= mdfs.parameter;
|
|
Packit |
1c1d7e |
pointer |= mdfs.pointer;
|
|
Packit |
1c1d7e |
target |= mdfs.target;
|
|
Packit |
1c1d7e |
save |= mdfs.save;
|
|
Packit |
1c1d7e |
deferred |= mdfs.deferred;
|
|
Packit |
1c1d7e |
nonoverridable |= mdfs.nonoverridable;
|
|
Packit |
1c1d7e |
nopass |= mdfs.nopass;
|
|
Packit |
1c1d7e |
pass |= mdfs.pass;
|
|
Packit |
1c1d7e |
passVar = mdfs.passVar;
|
|
Packit |
1c1d7e |
contiguous |= mdfs.contiguous;
|
|
Packit |
1c1d7e |
volat |= mdfs.volat;
|
|
Packit |
1c1d7e |
value |= mdfs.value;
|
|
Packit |
1c1d7e |
return *this;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
/*! Extracts and adds passed modifier to these modifiers.*/
|
|
Packit |
1c1d7e |
SymbolModifiers& SymbolModifiers::operator|=(QCString mdfString)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
mdfString = mdfString.lower();
|
|
Packit |
1c1d7e |
SymbolModifiers newMdf;
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
if (mdfString.find("dimension")==0)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
newMdf.dimension=mdfString;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
else if (mdfString.contains("intent"))
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
QCString tmp = extractFromParens(mdfString);
|
|
Packit |
1c1d7e |
bool isin = tmp.contains("in");
|
|
Packit |
1c1d7e |
bool isout = tmp.contains("out");
|
|
Packit |
1c1d7e |
if (isin && isout) newMdf.direction = SymbolModifiers::INOUT;
|
|
Packit |
1c1d7e |
else if (isin) newMdf.direction = SymbolModifiers::IN;
|
|
Packit |
1c1d7e |
else if (isout) newMdf.direction = SymbolModifiers::OUT;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
else if (mdfString=="public")
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
newMdf.protection = SymbolModifiers::PUBLIC;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
else if (mdfString=="private")
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
newMdf.protection = SymbolModifiers::PRIVATE;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
else if (mdfString=="protected")
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
newMdf.protect = TRUE;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
else if (mdfString=="optional")
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
newMdf.optional = TRUE;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
else if (mdfString=="allocatable")
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
newMdf.allocatable = TRUE;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
else if (mdfString=="external")
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
newMdf.external = TRUE;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
else if (mdfString=="intrinsic")
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
newMdf.intrinsic = TRUE;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
else if (mdfString=="parameter")
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
newMdf.parameter = TRUE;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
else if (mdfString=="pointer")
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
newMdf.pointer = TRUE;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
else if (mdfString=="target")
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
newMdf.target = TRUE;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
else if (mdfString=="save")
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
newMdf.save = TRUE;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
else if (mdfString=="nopass")
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
newMdf.nopass = TRUE;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
else if (mdfString=="deferred")
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
newMdf.deferred = TRUE;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
else if (mdfString=="non_overridable")
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
newMdf.nonoverridable = TRUE;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
else if (mdfString=="contiguous")
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
newMdf.contiguous = TRUE;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
else if (mdfString=="volatile")
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
newMdf.volat = TRUE;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
else if (mdfString=="value")
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
newMdf.value = TRUE;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
else if (mdfString.contains("pass"))
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
newMdf.pass = TRUE;
|
|
Packit |
1c1d7e |
if (mdfString.contains("("))
|
|
Packit |
1c1d7e |
newMdf.passVar = extractFromParens(mdfString);
|
|
Packit |
1c1d7e |
else
|
|
Packit |
1c1d7e |
newMdf.passVar = "";
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
(*this) |= newMdf;
|
|
Packit |
1c1d7e |
return *this;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
/*! For debugging purposes. */
|
|
Packit |
1c1d7e |
//ostream& operator<<(ostream& out, const SymbolModifiers& mdfs)
|
|
Packit |
1c1d7e |
//{
|
|
Packit |
1c1d7e |
// out<
|
|
Packit |
1c1d7e |
// ", "<<(mdfs.dimension.isNull() ? "" : mdfs.dimension.latin1())<<
|
|
Packit |
1c1d7e |
// ", "<
|
|
Packit |
1c1d7e |
//
|
|
Packit |
1c1d7e |
// return out;
|
|
Packit |
1c1d7e |
//}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
/*! Find argument with given name in \a subprog entry. */
|
|
Packit |
1c1d7e |
static Argument *findArgument(Entry* subprog, QCString name, bool byTypeName = FALSE)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
QCString cname(name.lower());
|
|
Packit |
1c1d7e |
for (unsigned int i=0; i<subprog->argList->count(); i++)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
Argument *arg = subprog->argList->at(i);
|
|
Packit |
1c1d7e |
if ((!byTypeName && arg->name.lower() == cname) ||
|
|
Packit |
1c1d7e |
(byTypeName && arg->type.lower() == cname)
|
|
Packit |
1c1d7e |
)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
return arg;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
return 0;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
/*! Find function with given name in \a entry. */
|
|
Packit |
1c1d7e |
#if 0
|
|
Packit |
1c1d7e |
static Entry *findFunction(Entry* entry, QCString name)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
QCString cname(name.lower());
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
EntryListIterator eli(*entry->children());
|
|
Packit |
1c1d7e |
Entry *ce;
|
|
Packit |
1c1d7e |
for (;(ce=eli.current());++eli)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
if (ce->section != Entry::FUNCTION_SEC)
|
|
Packit |
1c1d7e |
continue;
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
if (ce->name.lower() == cname)
|
|
Packit |
1c1d7e |
return ce;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
return 0;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
#endif
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
/*! Apply modifiers stored in \a mdfs to the \a typeName string. */
|
|
Packit |
1c1d7e |
static QCString applyModifiers(QCString typeName, SymbolModifiers& mdfs)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
if (!mdfs.dimension.isNull())
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
if (!typeName.isEmpty()) typeName += ", ";
|
|
Packit |
1c1d7e |
typeName += mdfs.dimension;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
if (mdfs.direction!=SymbolModifiers::NONE_D)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
if (!typeName.isEmpty()) typeName += ", ";
|
|
Packit |
1c1d7e |
typeName += directionStrs[mdfs.direction];
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
if (mdfs.optional)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
if (!typeName.isEmpty()) typeName += ", ";
|
|
Packit |
1c1d7e |
typeName += "optional";
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
if (mdfs.allocatable)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
if (!typeName.isEmpty()) typeName += ", ";
|
|
Packit |
1c1d7e |
typeName += "allocatable";
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
if (mdfs.external)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
if (!typeName.contains("external"))
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
if (!typeName.isEmpty()) typeName += ", ";
|
|
Packit |
1c1d7e |
typeName += "external";
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
if (mdfs.intrinsic)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
if (!typeName.isEmpty()) typeName += ", ";
|
|
Packit |
1c1d7e |
typeName += "intrinsic";
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
if (mdfs.parameter)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
if (!typeName.isEmpty()) typeName += ", ";
|
|
Packit |
1c1d7e |
typeName += "parameter";
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
if (mdfs.pointer)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
if (!typeName.isEmpty()) typeName += ", ";
|
|
Packit |
1c1d7e |
typeName += "pointer";
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
if (mdfs.target)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
if (!typeName.isEmpty()) typeName += ", ";
|
|
Packit |
1c1d7e |
typeName += "target";
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
if (mdfs.save)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
if (!typeName.isEmpty()) typeName += ", ";
|
|
Packit |
1c1d7e |
typeName += "save";
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
if (mdfs.deferred)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
if (!typeName.isEmpty()) typeName += ", ";
|
|
Packit |
1c1d7e |
typeName += "deferred";
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
if (mdfs.nonoverridable)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
if (!typeName.isEmpty()) typeName += ", ";
|
|
Packit |
1c1d7e |
typeName += "non_overridable";
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
if (mdfs.nopass)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
if (!typeName.isEmpty()) typeName += ", ";
|
|
Packit |
1c1d7e |
typeName += "nopass";
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
if (mdfs.pass)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
if (!typeName.isEmpty()) typeName += ", ";
|
|
Packit |
1c1d7e |
typeName += "pass";
|
|
Packit |
1c1d7e |
if (!mdfs.passVar.isEmpty())
|
|
Packit |
1c1d7e |
typeName += "(" + mdfs.passVar + ")";
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
if (mdfs.protection == SymbolModifiers::PUBLIC)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
if (!typeName.isEmpty()) typeName += ", ";
|
|
Packit |
1c1d7e |
typeName += "public";
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
else if (mdfs.protection == SymbolModifiers::PRIVATE)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
if (!typeName.isEmpty()) typeName += ", ";
|
|
Packit |
1c1d7e |
typeName += "private";
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
if (mdfs.protect)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
if (!typeName.isEmpty()) typeName += ", ";
|
|
Packit |
1c1d7e |
typeName += "protected";
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
if (mdfs.contiguous)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
if (!typeName.isEmpty()) typeName += ", ";
|
|
Packit |
1c1d7e |
typeName += "contiguous";
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
if (mdfs.volat)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
if (!typeName.isEmpty()) typeName += ", ";
|
|
Packit |
1c1d7e |
typeName += "volatile";
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
if (mdfs.value)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
if (!typeName.isEmpty()) typeName += ", ";
|
|
Packit |
1c1d7e |
typeName += "value";
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
return typeName;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
/*! Apply modifiers stored in \a mdfs to the \a arg argument. */
|
|
Packit |
1c1d7e |
static void applyModifiers(Argument *arg, SymbolModifiers& mdfs)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
QCString tmp = arg->type;
|
|
Packit |
1c1d7e |
arg->type = applyModifiers(tmp, mdfs);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
/*! Apply modifiers stored in \a mdfs to the \a ent entry. */
|
|
Packit |
1c1d7e |
static void applyModifiers(Entry *ent, SymbolModifiers& mdfs)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
QCString tmp = ent->type;
|
|
Packit |
1c1d7e |
ent->type = applyModifiers(tmp, mdfs);
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
if (mdfs.protection == SymbolModifiers::PUBLIC)
|
|
Packit |
1c1d7e |
ent->protection = Public;
|
|
Packit |
1c1d7e |
else if (mdfs.protection == SymbolModifiers::PRIVATE)
|
|
Packit |
1c1d7e |
ent->protection = Private;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
/*! Starts the new scope in fortran program. Consider using this function when
|
|
Packit |
1c1d7e |
* starting module, interface, function or other program block.
|
|
Packit |
1c1d7e |
* \see endScope()
|
|
Packit |
1c1d7e |
*/
|
|
Packit |
1c1d7e |
static void startScope(Entry *scope)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
//cout<<"start scope: "<<scope->name<
|
|
Packit |
1c1d7e |
current_root= scope; /* start substructure */
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
QMap<QCString,SymbolModifiers> mdfMap;
|
|
Packit |
1c1d7e |
modifiers.insert(scope, mdfMap);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
/*! Ends scope in fortran program: may update subprogram arguments or module variable attributes.
|
|
Packit |
1c1d7e |
* \see startScope()
|
|
Packit |
1c1d7e |
*/
|
|
Packit |
1c1d7e |
static bool endScope(Entry *scope, bool isGlobalRoot)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
//cout<<"end scope: "<<scope->name<
|
|
Packit |
1c1d7e |
if (current_root->parent() || isGlobalRoot)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
current_root= current_root->parent(); /* end substructure */
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
else
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
fprintf(stderr,"parse error in end <scopename>");
|
|
Packit |
1c1d7e |
scanner_abort();
|
|
Packit |
1c1d7e |
return FALSE;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
// update variables or subprogram arguments with modifiers
|
|
Packit |
1c1d7e |
QMap<QCString,SymbolModifiers>& mdfsMap = modifiers[scope];
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
if (scope->section == Entry::FUNCTION_SEC)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
// iterate all symbol modifiers of the scope
|
|
Packit |
1c1d7e |
for (QMap<QCString,SymbolModifiers>::Iterator it=mdfsMap.begin(); it!=mdfsMap.end(); it++)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
//cout<
|
|
Packit |
1c1d7e |
Argument *arg = findArgument(scope, it.key());
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
if (arg)
|
|
Packit |
1c1d7e |
applyModifiers(arg, it.data());
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
// find return type for function
|
|
Packit |
1c1d7e |
//cout<<"RETURN NAME "<<modifiers[current_root][scope->name.lower()].returnName<
|
|
Packit |
1c1d7e |
QCString returnName = modifiers[current_root][scope->name.lower()].returnName.lower();
|
|
Packit |
1c1d7e |
if (modifiers[scope].contains(returnName))
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
scope->type = modifiers[scope][returnName].type; // returning type works
|
|
Packit |
1c1d7e |
applyModifiers(scope, modifiers[scope][returnName]); // returning array works
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
if (scope->section == Entry::CLASS_SEC)
|
|
Packit |
1c1d7e |
{ // was INTERFACE_SEC
|
|
Packit |
1c1d7e |
if (scope->parent()->section == Entry::FUNCTION_SEC)
|
|
Packit |
1c1d7e |
{ // interface within function
|
|
Packit |
1c1d7e |
// iterate functions of interface and
|
|
Packit |
1c1d7e |
// try to find types for dummy(ie. argument) procedures.
|
|
Packit |
1c1d7e |
//cout<<"Search in "<<scope->name<
|
|
Packit |
1c1d7e |
EntryListIterator eli(*scope->children());
|
|
Packit |
1c1d7e |
Entry *ce;
|
|
Packit |
1c1d7e |
int count = 0;
|
|
Packit |
1c1d7e |
int found = FALSE;
|
|
Packit |
1c1d7e |
for (;(ce=eli.current());++eli)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
count++;
|
|
Packit |
1c1d7e |
if (ce->section != Entry::FUNCTION_SEC)
|
|
Packit |
1c1d7e |
continue;
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
Argument *arg = findArgument(scope->parent(), ce->name, TRUE);
|
|
Packit |
1c1d7e |
if (arg != 0)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
// set type of dummy procedure argument to interface
|
|
Packit |
1c1d7e |
arg->name = arg->type;
|
|
Packit |
1c1d7e |
arg->type = scope->name;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
if (ce->name.lower() == scope->name.lower()) found = TRUE;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
if ((count == 1) && found)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
// clear all modifiers of the scope
|
|
Packit |
1c1d7e |
modifiers.remove(scope);
|
|
Packit |
1c1d7e |
delete scope->parent()->removeSubEntry(scope);
|
|
Packit |
1c1d7e |
scope = 0;
|
|
Packit |
1c1d7e |
return TRUE;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
if (scope->section!=Entry::FUNCTION_SEC)
|
|
Packit |
1c1d7e |
{ // not function section
|
|
Packit |
1c1d7e |
// iterate variables: get and apply modifiers
|
|
Packit |
1c1d7e |
EntryListIterator eli(*scope->children());
|
|
Packit |
1c1d7e |
Entry *ce;
|
|
Packit |
1c1d7e |
for (;(ce=eli.current());++eli)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
if (ce->section != Entry::VARIABLE_SEC && ce->section != Entry::FUNCTION_SEC)
|
|
Packit |
1c1d7e |
continue;
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
//cout<<ce->name<<", "<<mdfsMap.contains(ce->name.lower())<
|
|
Packit |
1c1d7e |
if (mdfsMap.contains(ce->name.lower()))
|
|
Packit |
1c1d7e |
applyModifiers(ce, mdfsMap[ce->name.lower()]);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
// clear all modifiers of the scope
|
|
Packit |
1c1d7e |
modifiers.remove(scope);
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
return TRUE;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
#if 0
|
|
Packit |
1c1d7e |
//! Return full name of the entry. Sometimes we must combine several names recursively.
|
|
Packit |
1c1d7e |
static QCString getFullName(Entry *e)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
QCString name = e->name;
|
|
Packit |
1c1d7e |
if (e->section == Entry::CLASS_SEC // || e->section == Entry::INTERFACE_SEC
|
|
Packit |
1c1d7e |
|| !e->parent() || e->parent()->name.isEmpty())
|
|
Packit |
1c1d7e |
return name;
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
return getFullName(e->parent())+"::"+name;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
#endif
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
static int yyread(char *buf,int max_size)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
int c=0;
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
while ( c < max_size && inputString[inputPosition] )
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
*buf = inputString[inputPosition++] ;
|
|
Packit |
1c1d7e |
c++; buf++;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
return c;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
static void initParser()
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
last_entry = 0;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
static void initEntry()
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
if (typeMode)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
current->protection = typeProtection;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
else
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
current->protection = defaultProtection;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
current->mtype = mtype;
|
|
Packit |
1c1d7e |
current->virt = virt;
|
|
Packit |
1c1d7e |
current->stat = gstat;
|
|
Packit |
1c1d7e |
current->lang = SrcLangExt_Fortran;
|
|
Packit |
1c1d7e |
initGroupInfo(current);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
/**
|
|
Packit |
1c1d7e |
adds current entry to current_root and creates new current
|
|
Packit |
1c1d7e |
*/
|
|
Packit |
1c1d7e |
static void addCurrentEntry(int case_insens)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
if (case_insens) current->name = current->name.lower();
|
|
Packit |
1c1d7e |
//printf("===Adding entry %s to %s\n", current->name.data(), current_root->name.data());
|
|
Packit |
1c1d7e |
current_root->addSubEntry(current);
|
|
Packit |
1c1d7e |
last_entry = current;
|
|
Packit |
1c1d7e |
current = new Entry ;
|
|
Packit |
1c1d7e |
initEntry();
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
static int max(int a, int b) {return a>b?a:b;}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
static void addModule(const char *name, bool isModule)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
DBG_CTX((stderr, "0=========> got module %s\n", name));
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
if (isModule)
|
|
Packit |
1c1d7e |
current->section = Entry::NAMESPACE_SEC;
|
|
Packit |
1c1d7e |
else
|
|
Packit |
1c1d7e |
current->section = Entry::FUNCTION_SEC;
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
if (name!=NULL)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
current->name = name;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
else
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
QCString fname = yyFileName;
|
|
Packit |
1c1d7e |
int index = max(fname.findRev('/'), fname.findRev('\\'));
|
|
Packit |
1c1d7e |
fname = fname.right(fname.length()-index-1);
|
|
Packit |
1c1d7e |
fname = fname.prepend("__").append("__");
|
|
Packit |
1c1d7e |
current->name = fname;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
current->type = "program";
|
|
Packit |
1c1d7e |
current->fileName = yyFileName;
|
|
Packit |
1c1d7e |
current->bodyLine = yyLineNr; // used for source reference
|
|
Packit |
1c1d7e |
current->startLine = yyLineNr;
|
|
Packit |
1c1d7e |
current->protection = Public ;
|
|
Packit |
1c1d7e |
addCurrentEntry(1);
|
|
Packit |
1c1d7e |
startScope(last_entry);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
static void addSubprogram(const char *text)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
DBG_CTX((stderr,"1=========> got subprog, type: %s\n",text));
|
|
Packit |
1c1d7e |
subrCurrent.prepend(current);
|
|
Packit |
1c1d7e |
current->section = Entry::FUNCTION_SEC ;
|
|
Packit |
1c1d7e |
QCString subtype = text; subtype=subtype.lower().stripWhiteSpace();
|
|
Packit |
1c1d7e |
functionLine = (subtype.find("function") != -1);
|
|
Packit |
1c1d7e |
current->type += " " + subtype;
|
|
Packit |
1c1d7e |
current->type = current->type.stripWhiteSpace();
|
|
Packit |
1c1d7e |
current->fileName = yyFileName;
|
|
Packit |
1c1d7e |
current->bodyLine = yyLineNr; // used for source reference start of body of routine
|
|
Packit |
1c1d7e |
current->startLine = yyLineNr; // used for source reference start of definition
|
|
Packit |
1c1d7e |
current->args.resize(0);
|
|
Packit |
1c1d7e |
current->argList->clear();
|
|
Packit |
1c1d7e |
docBlock.resize(0);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
/*! Adds interface to the root entry.
|
|
Packit |
1c1d7e |
* \note Code was brought to this procedure from the parser,
|
|
Packit |
1c1d7e |
* because there was/is idea to use it in several parts of the parser.
|
|
Packit |
1c1d7e |
*/
|
|
Packit |
1c1d7e |
static void addInterface(QCString name, InterfaceType type)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
if (YY_START == Start)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
addModule(NULL);
|
|
Packit |
1c1d7e |
yy_push_state(ModuleBody); //anon program
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
current->section = Entry::CLASS_SEC; // was Entry::INTERFACE_SEC;
|
|
Packit |
1c1d7e |
current->spec = Entry::Interface;
|
|
Packit |
1c1d7e |
current->name = name;
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
switch (type)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
case IF_ABSTRACT:
|
|
Packit |
1c1d7e |
current->type = "abstract";
|
|
Packit |
1c1d7e |
break;
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
case IF_GENERIC:
|
|
Packit |
1c1d7e |
current->type = "generic";
|
|
Packit |
1c1d7e |
break;
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
case IF_SPECIFIC:
|
|
Packit |
1c1d7e |
case IF_NONE:
|
|
Packit |
1c1d7e |
default:
|
|
Packit |
1c1d7e |
current->type = "";
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
/* if type is part of a module, mod name is necessary for output */
|
|
Packit |
1c1d7e |
if ((current_root) &&
|
|
Packit |
1c1d7e |
(current_root->section == Entry::CLASS_SEC ||
|
|
Packit |
1c1d7e |
current_root->section == Entry::NAMESPACE_SEC))
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
current->name= current_root->name + "::" + current->name;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
current->fileName = yyFileName;
|
|
Packit |
1c1d7e |
current->bodyLine = yyLineNr;
|
|
Packit |
1c1d7e |
current->startLine = yyLineNr;
|
|
Packit |
1c1d7e |
addCurrentEntry(1);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
//-----------------------------------------------------------------------------
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
/*! Get the argument \a name.
|
|
Packit |
1c1d7e |
*/
|
|
Packit |
1c1d7e |
static Argument* getParameter(const QCString &name)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
// std::cout<<"addFortranParameter(): "<
|
|
Packit |
1c1d7e |
Argument *ret = 0;
|
|
Packit |
1c1d7e |
if (current_root->argList==0) return 0;
|
|
Packit |
1c1d7e |
ArgumentListIterator ali(*current_root->argList);
|
|
Packit |
1c1d7e |
Argument *a;
|
|
Packit |
1c1d7e |
for (ali.toFirst();(a=ali.current());++ali)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
if (a->name.lower()==name.lower())
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
ret=a;
|
|
Packit |
1c1d7e |
//printf("parameter found: %s\n",(const char*)name);
|
|
Packit |
1c1d7e |
break;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
} // for
|
|
Packit |
1c1d7e |
return ret;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
//----------------------------------------------------------------------------
|
|
Packit |
1c1d7e |
static void startCommentBlock(bool brief)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
if (brief)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
current->briefFile = yyFileName;
|
|
Packit |
1c1d7e |
current->briefLine = yyLineNr;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
else
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
current->docFile = yyFileName;
|
|
Packit |
1c1d7e |
current->docLine = yyLineNr;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
//----------------------------------------------------------------------------
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
static void handleCommentBlock(const QCString &doc,bool brief)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
bool needsEntry = FALSE;
|
|
Packit |
1c1d7e |
static bool hideInBodyDocs = Config_getBool(HIDE_IN_BODY_DOCS);
|
|
Packit |
1c1d7e |
int position=0;
|
|
Packit |
1c1d7e |
if (docBlockInBody && hideInBodyDocs)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
docBlockInBody = FALSE;
|
|
Packit |
1c1d7e |
return;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
DBG_CTX((stderr,"call parseCommentBlock [%s]\n",doc.data()));
|
|
Packit |
1c1d7e |
int lineNr = brief ? current->briefLine : current->docLine;
|
|
Packit |
1c1d7e |
while (parseCommentBlock(
|
|
Packit |
1c1d7e |
g_thisParser,
|
|
Packit |
1c1d7e |
docBlockInBody ? subrCurrent.getFirst() : current,
|
|
Packit |
1c1d7e |
doc, // text
|
|
Packit |
1c1d7e |
yyFileName, // file
|
|
Packit |
1c1d7e |
lineNr,
|
|
Packit |
1c1d7e |
docBlockInBody ? FALSE : brief,
|
|
Packit |
1c1d7e |
docBlockInBody ? FALSE : docBlockJavaStyle,
|
|
Packit |
1c1d7e |
docBlockInBody,
|
|
Packit |
1c1d7e |
defaultProtection,
|
|
Packit |
1c1d7e |
position,
|
|
Packit |
1c1d7e |
needsEntry
|
|
Packit |
1c1d7e |
))
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
DBG_CTX((stderr,"parseCommentBlock position=%d [%s] needsEntry=%d\n",position,doc.data()+position,needsEntry));
|
|
Packit |
1c1d7e |
if (needsEntry) addCurrentEntry(0);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
DBG_CTX((stderr,"parseCommentBlock position=%d [%s] needsEntry=%d\n",position,doc.data()+position,needsEntry));
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
if (needsEntry) addCurrentEntry(0);
|
|
Packit |
1c1d7e |
docBlockInBody = FALSE;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
//----------------------------------------------------------------------------
|
|
Packit |
1c1d7e |
/// Handle parameter description as defined after the declaration of the parameter
|
|
Packit |
1c1d7e |
static void subrHandleCommentBlock(const QCString &doc,bool brief)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
QCString loc_doc;
|
|
Packit |
1c1d7e |
loc_doc = doc.stripWhiteSpace();
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
Entry *tmp_entry = current;
|
|
Packit |
1c1d7e |
current = subrCurrent.getFirst(); // temporarily switch to the entry of the subroutine / function
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
// Still in the specification section so no inbodyDocs yet, but parameter documentation
|
|
Packit |
1c1d7e |
current->inbodyDocs = "";
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
// strip \\param or @param, so we can do some extra checking. We will add it later on again.
|
|
Packit |
1c1d7e |
if (!loc_doc.stripPrefix("\\param") &&
|
|
Packit |
1c1d7e |
!loc_doc.stripPrefix("@param")
|
|
Packit |
1c1d7e |
) (void)loc_doc; // Do nothing work has been done by stripPrefix; (void)loc_doc: to overcome 'empty controlled statement' warning
|
|
Packit |
1c1d7e |
loc_doc.stripWhiteSpace();
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
// direction as defined with the declaration of the parameter
|
|
Packit |
1c1d7e |
int dir1 = modifiers[current_root][argName.lower()].direction;
|
|
Packit |
1c1d7e |
// in description [in] is specified
|
|
Packit |
1c1d7e |
if (loc_doc.lower().find(directionParam[SymbolModifiers::IN]) == 0)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
// check if with the declaration intent(in) or nothing has been specified
|
|
Packit |
1c1d7e |
if ((directionParam[dir1] == directionParam[SymbolModifiers::NONE_D]) ||
|
|
Packit |
1c1d7e |
(directionParam[dir1] == directionParam[SymbolModifiers::IN]))
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
// strip direction
|
|
Packit |
1c1d7e |
loc_doc = loc_doc.right(loc_doc.length()-strlen(directionParam[SymbolModifiers::IN]));
|
|
Packit |
1c1d7e |
loc_doc.stripWhiteSpace();
|
|
Packit |
1c1d7e |
// in case of empty documentation or (now) just name, consider it as no documemntation
|
|
Packit |
1c1d7e |
if (loc_doc.isEmpty() || (loc_doc.lower() == argName.lower()))
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
// reset current back to the part inside the routine
|
|
Packit |
1c1d7e |
current=tmp_entry;
|
|
Packit |
1c1d7e |
return;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
handleCommentBlock(QCString("\n\n@param ") + directionParam[SymbolModifiers::IN] + " " +
|
|
Packit |
1c1d7e |
argName + " " + loc_doc,brief);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
else
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
// something different specified, give warning and leave error.
|
|
Packit |
1c1d7e |
warn(yyFileName,yyLineNr, "Routine: " + current->name + current->args +
|
|
Packit |
1c1d7e |
" inconsistency between intent attribute and documentation for parameter: " + argName);
|
|
Packit |
1c1d7e |
handleCommentBlock(QCString("\n\n@param ") + directionParam[dir1] + " " +
|
|
Packit |
1c1d7e |
argName + " " + loc_doc,brief);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
// analogous to the [in] case, here [out] direction specified
|
|
Packit |
1c1d7e |
else if (loc_doc.lower().find(directionParam[SymbolModifiers::OUT]) == 0)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
if ((directionParam[dir1] == directionParam[SymbolModifiers::NONE_D]) ||
|
|
Packit |
1c1d7e |
(directionParam[dir1] == directionParam[SymbolModifiers::OUT]))
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
loc_doc = loc_doc.right(loc_doc.length()-strlen(directionParam[SymbolModifiers::OUT]));
|
|
Packit |
1c1d7e |
loc_doc.stripWhiteSpace();
|
|
Packit |
1c1d7e |
if (loc_doc.isEmpty() || (loc_doc.lower() == argName.lower()))
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
current=tmp_entry;
|
|
Packit |
1c1d7e |
return;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
handleCommentBlock(QCString("\n\n@param ") + directionParam[SymbolModifiers::OUT] + " " +
|
|
Packit |
1c1d7e |
argName + " " + loc_doc,brief);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
else
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
warn(yyFileName,yyLineNr, "Routine: " + current->name + current->args +
|
|
Packit |
1c1d7e |
" inconsistency between intent attribute and documentation for parameter: " + argName);
|
|
Packit |
1c1d7e |
handleCommentBlock(QCString("\n\n@param ") + directionParam[dir1] + " " +
|
|
Packit |
1c1d7e |
argName + " " + loc_doc,brief);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
// analogous to the [in] case, here [in,out] direction specified
|
|
Packit |
1c1d7e |
else if (loc_doc.lower().find(directionParam[SymbolModifiers::INOUT]) == 0)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
if ((directionParam[dir1] == directionParam[SymbolModifiers::NONE_D]) ||
|
|
Packit |
1c1d7e |
(directionParam[dir1] == directionParam[SymbolModifiers::INOUT]))
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
loc_doc = loc_doc.right(loc_doc.length()-strlen(directionParam[SymbolModifiers::INOUT]));
|
|
Packit |
1c1d7e |
loc_doc.stripWhiteSpace();
|
|
Packit |
1c1d7e |
if (loc_doc.isEmpty() || (loc_doc.lower() == argName.lower()))
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
current=tmp_entry;
|
|
Packit |
1c1d7e |
return;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
handleCommentBlock(QCString("\n\n@param ") + directionParam[SymbolModifiers::INOUT] + " " +
|
|
Packit |
1c1d7e |
argName + " " + loc_doc,brief);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
else
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
warn(yyFileName,yyLineNr, "Routine: " + current->name + current->args +
|
|
Packit |
1c1d7e |
" inconsistency between intent attribute and documentation for parameter: " + argName);
|
|
Packit |
1c1d7e |
handleCommentBlock(QCString("\n\n@param ") + directionParam[dir1] + " " +
|
|
Packit |
1c1d7e |
argName + " " + loc_doc,brief);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
// analogous to the [in] case; here no direction specified
|
|
Packit |
1c1d7e |
else
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
if (loc_doc.isEmpty() || (loc_doc.lower() == argName.lower()))
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
current=tmp_entry;
|
|
Packit |
1c1d7e |
return;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
handleCommentBlock(QCString("\n\n@param ") + directionParam[dir1] + " " +
|
|
Packit |
1c1d7e |
argName + " " + loc_doc,brief);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
// reset current back to the part inside the routine
|
|
Packit |
1c1d7e |
current=tmp_entry;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
//----------------------------------------------------------------------------
|
|
Packit |
1c1d7e |
/// Handle result description as defined after the declaration of the parameter
|
|
Packit |
1c1d7e |
static void subrHandleCommentBlockResult(const QCString &doc,bool brief)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
QCString loc_doc;
|
|
Packit |
1c1d7e |
loc_doc = doc.stripWhiteSpace();
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
Entry *tmp_entry = current;
|
|
Packit |
1c1d7e |
current = subrCurrent.getFirst(); // temporarily switch to the entry of the subroutine / function
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
// Still in the specification section so no inbodyDocs yet, but parameter documentation
|
|
Packit |
1c1d7e |
current->inbodyDocs = "";
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
// strip \\returns or @returns. We will add it later on again.
|
|
Packit |
1c1d7e |
if (!loc_doc.stripPrefix("\\returns") &&
|
|
Packit |
1c1d7e |
!loc_doc.stripPrefix("\\return") &&
|
|
Packit |
1c1d7e |
!loc_doc.stripPrefix("@returns") &&
|
|
Packit |
1c1d7e |
!loc_doc.stripPrefix("@return")
|
|
Packit |
1c1d7e |
) (void)loc_doc; // Do nothing work has been done by stripPrefix; (void)loc_doc: to overcome 'empty controlled statement' warning
|
|
Packit |
1c1d7e |
loc_doc.stripWhiteSpace();
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
if (loc_doc.isEmpty() || (loc_doc.lower() == argName.lower()))
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
current=tmp_entry;
|
|
Packit |
1c1d7e |
return;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
handleCommentBlock(QCString("\n\n@returns ") + loc_doc,brief);
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
// reset current back to the part inside the routine
|
|
Packit |
1c1d7e |
current=tmp_entry;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
//----------------------------------------------------------------------------
|
|
Packit |
1c1d7e |
#if 0
|
|
Packit |
1c1d7e |
static int level=0;
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
static void debugCompounds(Entry *rt) // print Entry structure (for debugging)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
level++;
|
|
Packit |
1c1d7e |
printf("%d) debugCompounds(%s) line %d\n",level, rt->name.data(), rt->bodyLine);
|
|
Packit |
1c1d7e |
EntryListIterator eli(*rt->children());
|
|
Packit |
1c1d7e |
Entry *ce;
|
|
Packit |
1c1d7e |
for (;(ce=eli.current());++eli)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
debugCompounds(ce);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
level--;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
#endif
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
static void parseMain(const char *fileName,const char *fileBuf,Entry *rt, FortranFormat format)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
char *tmpBuf = NULL;
|
|
Packit |
1c1d7e |
initParser();
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
defaultProtection = Public;
|
|
Packit |
1c1d7e |
inputString = fileBuf;
|
|
Packit |
1c1d7e |
inputPosition = 0;
|
|
Packit |
1c1d7e |
inputStringPrepass = NULL;
|
|
Packit |
1c1d7e |
inputPositionPrepass = 0;
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
//anonCount = 0; // don't reset per file
|
|
Packit |
1c1d7e |
mtype = Method;
|
|
Packit |
1c1d7e |
gstat = FALSE;
|
|
Packit |
1c1d7e |
virt = Normal;
|
|
Packit |
1c1d7e |
current_root = rt;
|
|
Packit |
1c1d7e |
global_root = rt;
|
|
Packit |
1c1d7e |
inputFile.setName(fileName);
|
|
Packit |
1c1d7e |
if (inputFile.open(IO_ReadOnly))
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
isFixedForm = recognizeFixedForm(fileBuf,format);
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
if (isFixedForm)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
msg("Prepassing fixed form of %s\n", fileName);
|
|
Packit |
1c1d7e |
//printf("---strlen=%d\n", strlen(fileBuf));
|
|
Packit |
1c1d7e |
//clock_t start=clock();
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
//printf("Input fixed form string:\n%s\n", fileBuf);
|
|
Packit |
1c1d7e |
//printf("===========================\n");
|
|
Packit |
1c1d7e |
inputString = prepassFixedForm(fileBuf, NULL);
|
|
Packit |
1c1d7e |
//printf("Resulting free form string:\n%s\n", inputString);
|
|
Packit |
1c1d7e |
//printf("===========================\n");
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
//clock_t end=clock();
|
|
Packit |
1c1d7e |
//printf("CPU time used=%f\n", ((double) (end-start))/CLOCKS_PER_SEC);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
else if (inputString[strlen(fileBuf)-1] != '\n')
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
tmpBuf = (char *)malloc(strlen(fileBuf)+2);
|
|
Packit |
1c1d7e |
strcpy(tmpBuf,fileBuf);
|
|
Packit |
1c1d7e |
tmpBuf[strlen(fileBuf)]= '\n';
|
|
Packit |
1c1d7e |
tmpBuf[strlen(fileBuf)+1]= '\000';
|
|
Packit |
1c1d7e |
inputString = tmpBuf;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
yyLineNr= 1 ;
|
|
Packit |
1c1d7e |
yyFileName = fileName;
|
|
Packit |
1c1d7e |
msg("Parsing file %s...\n",yyFileName.data());
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
startScope(rt); // implies current_root = rt
|
|
Packit |
1c1d7e |
initParser();
|
|
Packit |
1c1d7e |
groupEnterFile(yyFileName,yyLineNr);
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
current = new Entry;
|
|
Packit |
1c1d7e |
current->lang = SrcLangExt_Fortran;
|
|
Packit |
1c1d7e |
current->name = yyFileName;
|
|
Packit |
1c1d7e |
current->section = Entry::SOURCE_SEC;
|
|
Packit |
1c1d7e |
current_root->addSubEntry(current);
|
|
Packit |
1c1d7e |
file_root = current;
|
|
Packit |
1c1d7e |
current = new Entry;
|
|
Packit |
1c1d7e |
current->lang = SrcLangExt_Fortran;
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
fortranscannerYYrestart( fortranscannerYYin );
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
BEGIN( Start );
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
fortranscannerYYlex();
|
|
Packit |
1c1d7e |
groupLeaveFile(yyFileName,yyLineNr);
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
endScope(current_root, TRUE); // TRUE - global root
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
//debugCompounds(rt); //debug
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
rt->program.resize(0);
|
|
Packit |
1c1d7e |
delete current; current=0;
|
|
Packit |
1c1d7e |
moduleProcedures.clear();
|
|
Packit |
1c1d7e |
if (tmpBuf) {
|
|
Packit |
1c1d7e |
free((char*)tmpBuf);
|
|
Packit |
1c1d7e |
inputString=NULL;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
if (isFixedForm) {
|
|
Packit |
1c1d7e |
free((char*)inputString);
|
|
Packit |
1c1d7e |
inputString=NULL;
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
inputFile.close();
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
//----------------------------------------------------------------------------
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
void FortranLanguageScanner::parseInput(const char *fileName,
|
|
Packit |
1c1d7e |
const char *fileBuf,
|
|
Packit |
1c1d7e |
Entry *root,
|
|
Packit |
1c1d7e |
bool /*sameTranslationUnit*/,
|
|
Packit |
1c1d7e |
QStrList & /*filesInSameTranslationUnit*/)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
g_thisParser = this;
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
printlex(yy_flex_debug, TRUE, __FILE__, fileName);
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
::parseMain(fileName,fileBuf,root,m_format);
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
printlex(yy_flex_debug, FALSE, __FILE__, fileName);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
void FortranLanguageScanner::parseCode(CodeOutputInterface & codeOutIntf,
|
|
Packit |
1c1d7e |
const char * scopeName,
|
|
Packit |
1c1d7e |
const QCString & input,
|
|
Packit |
1c1d7e |
SrcLangExt /*lang*/,
|
|
Packit |
1c1d7e |
bool isExampleBlock,
|
|
Packit |
1c1d7e |
const char * exampleName,
|
|
Packit |
1c1d7e |
FileDef * fileDef,
|
|
Packit |
1c1d7e |
int startLine,
|
|
Packit |
1c1d7e |
int endLine,
|
|
Packit |
1c1d7e |
bool inlineFragment,
|
|
Packit |
1c1d7e |
MemberDef *memberDef,
|
|
Packit |
1c1d7e |
bool showLineNumbers,
|
|
Packit |
1c1d7e |
Definition *searchCtx,
|
|
Packit |
1c1d7e |
bool collectXRefs
|
|
Packit |
1c1d7e |
)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
::parseFortranCode(codeOutIntf,scopeName,input,isExampleBlock,exampleName,
|
|
Packit |
1c1d7e |
fileDef,startLine,endLine,inlineFragment,memberDef,
|
|
Packit |
1c1d7e |
showLineNumbers,searchCtx,collectXRefs,m_format);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
bool FortranLanguageScanner::needsPreprocessing(const QCString &extension)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
return extension!=extension.lower(); // use preprocessor only for upper case extensions
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
void FortranLanguageScanner::resetCodeParserState()
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
::resetFortranCodeParserState();
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
void FortranLanguageScanner::parsePrototype(const char *text)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
QCString buffer = QCString(text);
|
|
Packit |
1c1d7e |
pushBuffer(buffer);
|
|
Packit |
1c1d7e |
parsingPrototype = TRUE;
|
|
Packit |
1c1d7e |
BEGIN(Prototype);
|
|
Packit |
1c1d7e |
fortranscannerYYlex();
|
|
Packit |
1c1d7e |
parsingPrototype = FALSE;
|
|
Packit |
1c1d7e |
popBuffer();
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
static void scanner_abort()
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
fprintf(stderr,"********************************************************************\n");
|
|
Packit |
1c1d7e |
fprintf(stderr,"Error in file %s line: %d, state: %d\n",yyFileName.data(),yyLineNr,YY_START);
|
|
Packit |
1c1d7e |
fprintf(stderr,"********************************************************************\n");
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
EntryListIterator eli(*global_root->children());
|
|
Packit |
1c1d7e |
Entry *ce;
|
|
Packit |
1c1d7e |
bool start=FALSE;
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
for (;(ce=eli.current());++eli)
|
|
Packit |
1c1d7e |
{
|
|
Packit |
1c1d7e |
if (ce == file_root) start=TRUE;
|
|
Packit |
1c1d7e |
if (start) ce->reset();
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
// dummy call to avoid compiler warning
|
|
Packit |
1c1d7e |
(void)yy_top_state();
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
return;
|
|
Packit |
1c1d7e |
//exit(-1);
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
//----------------------------------------------------------------------------
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
#if !defined(YY_FLEX_SUBMINOR_VERSION)
|
|
Packit |
1c1d7e |
//----------------------------------------------------------------------------
|
|
Packit |
1c1d7e |
extern "C" { // some bogus code to keep the compiler happy
|
|
Packit |
1c1d7e |
void fortranscannernerYYdummy() { yy_flex_realloc(0,0); }
|
|
Packit |
1c1d7e |
}
|
|
Packit |
1c1d7e |
#endif
|
|
Packit |
1c1d7e |
|