Blame src/fortranscanner.l

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